aboutsummaryrefslogtreecommitdiff
path: root/ncurses/tty/hashmap.c
diff options
context:
space:
mode:
Diffstat (limited to 'ncurses/tty/hashmap.c')
-rw-r--r--ncurses/tty/hashmap.c259
1 files changed, 147 insertions, 112 deletions
diff --git a/ncurses/tty/hashmap.c b/ncurses/tty/hashmap.c
index 9b60df62d5cf..b670e1b9691f 100644
--- a/ncurses/tty/hashmap.c
+++ b/ncurses/tty/hashmap.c
@@ -1,5 +1,5 @@
/****************************************************************************
- * Copyright (c) 1998-2006,2007 Free Software Foundation, Inc. *
+ * Copyright (c) 1998-2009,2010 Free Software Foundation, Inc. *
* *
* Permission is hereby granted, free of charge, to any person obtaining a *
* copy of this software and associated documentation files (the *
@@ -68,9 +68,12 @@ AUTHOR
*****************************************************************************/
#include <curses.priv.h>
-#include <term.h> /* for back_color_erase */
-MODULE_ID("$Id: hashmap.c,v 1.56 2007/10/13 18:47:25 Miroslav.Lichvar Exp $")
+#ifndef CUR
+#define CUR SP_TERMTYPE
+#endif
+
+MODULE_ID("$Id: hashmap.c,v 1.62 2010/04/24 23:46:07 tom Exp $")
#ifdef HASHDEBUG
@@ -83,25 +86,25 @@ MODULE_ID("$Id: hashmap.c,v 1.56 2007/10/13 18:47:25 Miroslav.Lichvar Exp $")
int oldnums[MAXLINES], reallines[MAXLINES];
static NCURSES_CH_T oldtext[MAXLINES][TEXTWIDTH];
static NCURSES_CH_T newtext[MAXLINES][TEXTWIDTH];
-# define OLDNUM(n) oldnums[n]
-# define OLDTEXT(n) oldtext[n]
-# define NEWTEXT(m) newtext[m]
-# define PENDING(n) 1
+# define OLDNUM(sp,n) oldnums[n]
+# define OLDTEXT(sp,n) oldtext[n]
+# define NEWTEXT(sp,m) newtext[m]
+# define PENDING(sp,n) 1
#else /* !HASHDEBUG */
-# define OLDNUM(n) SP->_oldnum_list[n]
-# define OLDTEXT(n) curscr->_line[n].text
-# define NEWTEXT(m) newscr->_line[m].text
-# define TEXTWIDTH (curscr->_maxx+1)
-# define PENDING(n) (newscr->_line[n].firstchar != _NOCHANGE)
+# define OLDNUM(sp,n) (sp)->_oldnum_list[n]
+# define OLDTEXT(sp,n) CurScreen(sp)->_line[n].text
+# define NEWTEXT(sp,m) NewScreen(sp)->_line[m].text
+# define TEXTWIDTH(sp) (CurScreen(sp)->_maxx + 1)
+# define PENDING(sp,n) (NewScreen(sp)->_line[n].firstchar != _NOCHANGE)
#endif /* !HASHDEBUG */
-#define oldhash (SP->oldhash)
-#define newhash (SP->newhash)
-#define hashtab (SP->hashtab)
-#define lines_alloc (SP->hashtab_len)
+#define oldhash(sp) ((sp)->oldhash)
+#define newhash(sp) ((sp)->newhash)
+#define hashtab(sp) ((sp)->hashtab)
+#define lines_alloc(sp) ((sp)->hashtab_len)
#if USE_WIDEC_SUPPORT
#define HASH_VAL(ch) (ch.chars[0])
@@ -112,26 +115,26 @@ static NCURSES_CH_T newtext[MAXLINES][TEXTWIDTH];
static const NCURSES_CH_T blankchar = NewChar(BLANK_TEXT);
static NCURSES_INLINE unsigned long
-hash(NCURSES_CH_T * text)
+hash(SCREEN *sp, NCURSES_CH_T * text)
{
int i;
NCURSES_CH_T ch;
unsigned long result = 0;
- for (i = TEXTWIDTH; i > 0; i--) {
+ for (i = TEXTWIDTH(sp); i > 0; i--) {
ch = *text++;
- result += (result << 5) + HASH_VAL(ch);
+ result += (result << 5) + (unsigned long) HASH_VAL(ch);
}
return result;
}
/* approximate update cost */
static int
-update_cost(NCURSES_CH_T * from, NCURSES_CH_T * to)
+update_cost(SCREEN *sp, NCURSES_CH_T * from, NCURSES_CH_T * to)
{
int cost = 0;
int i;
- for (i = TEXTWIDTH; i > 0; i--, from++, to++)
+ for (i = TEXTWIDTH(sp); i > 0; i--, from++, to++)
if (!(CharEq(*from, *to)))
cost++;
@@ -139,7 +142,7 @@ update_cost(NCURSES_CH_T * from, NCURSES_CH_T * to)
}
static int
-update_cost_from_blank(NCURSES_CH_T * to)
+update_cost_from_blank(SCREEN *sp, NCURSES_CH_T * to)
{
int cost = 0;
int i;
@@ -148,7 +151,7 @@ update_cost_from_blank(NCURSES_CH_T * to)
if (back_color_erase)
SetPair(blank, GetPair(stdscr->_nc_bkgd));
- for (i = TEXTWIDTH; i > 0; i--, to++)
+ for (i = TEXTWIDTH(sp); i > 0; i--, to++)
if (!(CharEq(blank, *to)))
cost++;
@@ -160,14 +163,14 @@ update_cost_from_blank(NCURSES_CH_T * to)
* effective. 'blank' indicates whether the line 'to' would become blank.
*/
static NCURSES_INLINE bool
-cost_effective(const int from, const int to, const bool blank)
+cost_effective(SCREEN *sp, const int from, const int to, const bool blank)
{
int new_from;
if (from == to)
return FALSE;
- new_from = OLDNUM(from);
+ new_from = OLDNUM(sp, from);
if (new_from == _NEWINDEX)
new_from = from;
@@ -175,16 +178,17 @@ cost_effective(const int from, const int to, const bool blank)
* On the left side of >= is the cost before moving;
* on the right side -- cost after moving.
*/
- return (((blank ? update_cost_from_blank(NEWTEXT(to))
- : update_cost(OLDTEXT(to), NEWTEXT(to)))
- + update_cost(OLDTEXT(new_from), NEWTEXT(from)))
- >= ((new_from == from ? update_cost_from_blank(NEWTEXT(from))
- : update_cost(OLDTEXT(new_from), NEWTEXT(from)))
- + update_cost(OLDTEXT(from), NEWTEXT(to)))) ? TRUE : FALSE;
+ return (((blank ? update_cost_from_blank(sp, NEWTEXT(sp, to))
+ : update_cost(sp, OLDTEXT(sp, to), NEWTEXT(sp, to)))
+ + update_cost(sp, OLDTEXT(sp, new_from), NEWTEXT(sp, from)))
+ >= ((new_from == from ? update_cost_from_blank(sp, NEWTEXT(sp, from))
+ : update_cost(sp, OLDTEXT(sp, new_from), NEWTEXT(sp, from)))
+ + update_cost(sp, OLDTEXT(sp, from), NEWTEXT(sp, to))))
+ ? TRUE : FALSE;
}
static void
-grow_hunks(void)
+grow_hunks(SCREEN *sp)
{
int start, end, shift;
int back_limit, forward_limit; /* limits for cells to fill */
@@ -200,35 +204,36 @@ grow_hunks(void)
back_ref_limit = 0;
i = 0;
- while (i < screen_lines && OLDNUM(i) == _NEWINDEX)
+ while (i < screen_lines(sp) && OLDNUM(sp, i) == _NEWINDEX)
i++;
- for (; i < screen_lines; i = next_hunk) {
+ for (; i < screen_lines(sp); i = next_hunk) {
start = i;
- shift = OLDNUM(i) - i;
+ shift = OLDNUM(sp, i) - i;
/* get forward limit */
i = start + 1;
- while (i < screen_lines && OLDNUM(i) != _NEWINDEX && OLDNUM(i) - i
- == shift)
+ while (i < screen_lines(sp)
+ && OLDNUM(sp, i) != _NEWINDEX
+ && OLDNUM(sp, i) - i == shift)
i++;
end = i;
- while (i < screen_lines && OLDNUM(i) == _NEWINDEX)
+ while (i < screen_lines(sp) && OLDNUM(sp, i) == _NEWINDEX)
i++;
next_hunk = i;
forward_limit = i;
- if (i >= screen_lines || OLDNUM(i) >= i)
+ if (i >= screen_lines(sp) || OLDNUM(sp, i) >= i)
forward_ref_limit = i;
else
- forward_ref_limit = OLDNUM(i);
+ forward_ref_limit = OLDNUM(sp, i);
i = start - 1;
/* grow back */
if (shift < 0)
back_limit = back_ref_limit + (-shift);
while (i >= back_limit) {
- if (newhash[i] == oldhash[i + shift]
- || cost_effective(i + shift, i, shift < 0)) {
- OLDNUM(i) = i + shift;
+ if (newhash(sp)[i] == oldhash(sp)[i + shift]
+ || cost_effective(sp, i + shift, i, shift < 0)) {
+ OLDNUM(sp, i) = i + shift;
TR(TRACE_UPDATE | TRACE_MOVE,
("connected new line %d to old line %d (backward continuation)",
i, i + shift));
@@ -246,9 +251,9 @@ grow_hunks(void)
if (shift > 0)
forward_limit = forward_ref_limit - shift;
while (i < forward_limit) {
- if (newhash[i] == oldhash[i + shift]
- || cost_effective(i + shift, i, shift > 0)) {
- OLDNUM(i) = i + shift;
+ if (newhash(sp)[i] == oldhash(sp)[i + shift]
+ || cost_effective(sp, i + shift, i, shift > 0)) {
+ OLDNUM(sp, i) = i + shift;
TR(TRACE_UPDATE | TRACE_MOVE,
("connected new line %d to old line %d (forward continuation)",
i, i + shift));
@@ -268,51 +273,54 @@ grow_hunks(void)
}
NCURSES_EXPORT(void)
-_nc_hash_map(void)
+NCURSES_SP_NAME(_nc_hash_map) (NCURSES_SP_DCL0)
{
- HASHMAP *sp;
+ HASHMAP *hsp;
register int i;
int start, shift, size;
- if (screen_lines > lines_alloc) {
- if (hashtab)
- free(hashtab);
- hashtab = typeMalloc(HASHMAP, (screen_lines + 1) * 2);
- if (!hashtab) {
- if (oldhash) {
- FreeAndNull(oldhash);
+ if (screen_lines(SP_PARM) > lines_alloc(SP_PARM)) {
+ if (hashtab(SP_PARM))
+ free(hashtab(SP_PARM));
+ hashtab(SP_PARM) = typeMalloc(HASHMAP,
+ ((size_t) screen_lines(SP_PARM) + 1) * 2);
+ if (!hashtab(SP_PARM)) {
+ if (oldhash(SP_PARM)) {
+ FreeAndNull(oldhash(SP_PARM));
}
- lines_alloc = 0;
+ lines_alloc(SP_PARM) = 0;
return;
}
- lines_alloc = screen_lines;
+ lines_alloc(SP_PARM) = screen_lines(SP_PARM);
}
- if (oldhash && newhash) {
+ if (oldhash(SP_PARM) && newhash(SP_PARM)) {
/* re-hash only changed lines */
- for (i = 0; i < screen_lines; i++) {
- if (PENDING(i))
- newhash[i] = hash(NEWTEXT(i));
+ for (i = 0; i < screen_lines(SP_PARM); i++) {
+ if (PENDING(SP_PARM, i))
+ newhash(SP_PARM)[i] = hash(SP_PARM, NEWTEXT(SP_PARM, i));
}
} else {
/* re-hash all */
- if (oldhash == 0)
- oldhash = typeCalloc(unsigned long, (unsigned) screen_lines);
- if (newhash == 0)
- newhash = typeCalloc(unsigned long, (unsigned) screen_lines);
- if (!oldhash || !newhash)
+ if (oldhash(SP_PARM) == 0)
+ oldhash(SP_PARM) = typeCalloc(unsigned long,
+ (size_t) screen_lines(SP_PARM));
+ if (newhash(SP_PARM) == 0)
+ newhash(SP_PARM) = typeCalloc(unsigned long,
+ (size_t) screen_lines(SP_PARM));
+ if (!oldhash(SP_PARM) || !newhash(SP_PARM))
return; /* malloc failure */
- for (i = 0; i < screen_lines; i++) {
- newhash[i] = hash(NEWTEXT(i));
- oldhash[i] = hash(OLDTEXT(i));
+ for (i = 0; i < screen_lines(SP_PARM); i++) {
+ newhash(SP_PARM)[i] = hash(SP_PARM, NEWTEXT(SP_PARM, i));
+ oldhash(SP_PARM)[i] = hash(SP_PARM, OLDTEXT(SP_PARM, i));
}
}
#ifdef HASH_VERIFY
- for (i = 0; i < screen_lines; i++) {
- if (newhash[i] != hash(NEWTEXT(i)))
+ for (i = 0; i < screen_lines(SP_PARM); i++) {
+ if (newhash(SP_PARM)[i] != hash(SP_PARM, NEWTEXT(SP_PARM, i)))
fprintf(stderr, "error in newhash[%d]\n", i);
- if (oldhash[i] != hash(OLDTEXT(i)))
+ if (oldhash(SP_PARM)[i] != hash(SP_PARM, OLDTEXT(SP_PARM, i)))
fprintf(stderr, "error in oldhash[%d]\n", i);
}
#endif
@@ -320,28 +328,30 @@ _nc_hash_map(void)
/*
* Set up and count line-hash values.
*/
- memset(hashtab, '\0', sizeof(*hashtab) * (screen_lines + 1) * 2);
- for (i = 0; i < screen_lines; i++) {
- unsigned long hashval = oldhash[i];
-
- for (sp = hashtab; sp->hashval; sp++)
- if (sp->hashval == hashval)
+ memset(hashtab(SP_PARM), '\0',
+ sizeof(*(hashtab(SP_PARM)))
+ * ((size_t) screen_lines(SP_PARM) + 1) * 2);
+ for (i = 0; i < screen_lines(SP_PARM); i++) {
+ unsigned long hashval = oldhash(SP_PARM)[i];
+
+ for (hsp = hashtab(SP_PARM); hsp->hashval; hsp++)
+ if (hsp->hashval == hashval)
break;
- sp->hashval = hashval; /* in case this is a new entry */
- sp->oldcount++;
- sp->oldindex = i;
+ hsp->hashval = hashval; /* in case this is a new entry */
+ hsp->oldcount++;
+ hsp->oldindex = i;
}
- for (i = 0; i < screen_lines; i++) {
- unsigned long hashval = newhash[i];
+ for (i = 0; i < screen_lines(SP_PARM); i++) {
+ unsigned long hashval = newhash(SP_PARM)[i];
- for (sp = hashtab; sp->hashval; sp++)
- if (sp->hashval == hashval)
+ for (hsp = hashtab(SP_PARM); hsp->hashval; hsp++)
+ if (hsp->hashval == hashval)
break;
- sp->hashval = hashval; /* in case this is a new entry */
- sp->newcount++;
- sp->newindex = i;
+ hsp->hashval = hashval; /* in case this is a new entry */
+ hsp->newcount++;
+ hsp->newindex = i;
- OLDNUM(i) = _NEWINDEX; /* initialize old indices array */
+ OLDNUM(SP_PARM, i) = _NEWINDEX; /* initialize old indices array */
}
/*
@@ -351,16 +361,16 @@ _nc_hash_map(void)
* extending hunks by cost_effective. Otherwise, it does not
* have any side effects.
*/
- for (sp = hashtab; sp->hashval; sp++)
- if (sp->oldcount == 1 && sp->newcount == 1
- && sp->oldindex != sp->newindex) {
+ for (hsp = hashtab(SP_PARM); hsp->hashval; hsp++)
+ if (hsp->oldcount == 1 && hsp->newcount == 1
+ && hsp->oldindex != hsp->newindex) {
TR(TRACE_UPDATE | TRACE_MOVE,
("new line %d is hash-identical to old line %d (unique)",
- sp->newindex, sp->oldindex));
- OLDNUM(sp->newindex) = sp->oldindex;
+ hsp->newindex, hsp->oldindex));
+ OLDNUM(SP_PARM, hsp->newindex) = hsp->oldindex;
}
- grow_hunks();
+ grow_hunks(SP_PARM);
/*
* Eliminate bad or impossible shifts -- this includes removing
@@ -368,58 +378,83 @@ _nc_hash_map(void)
* those which are to be moved too far, they are likely to destroy
* more than carry.
*/
- for (i = 0; i < screen_lines;) {
- while (i < screen_lines && OLDNUM(i) == _NEWINDEX)
+ for (i = 0; i < screen_lines(SP_PARM);) {
+ while (i < screen_lines(SP_PARM) && OLDNUM(SP_PARM, i) == _NEWINDEX)
i++;
- if (i >= screen_lines)
+ if (i >= screen_lines(SP_PARM))
break;
start = i;
- shift = OLDNUM(i) - i;
+ shift = OLDNUM(SP_PARM, i) - i;
i++;
- while (i < screen_lines && OLDNUM(i) != _NEWINDEX && OLDNUM(i) - i
- == shift)
+ while (i < screen_lines(SP_PARM)
+ && OLDNUM(SP_PARM, i) != _NEWINDEX
+ && OLDNUM(SP_PARM, i) - i == shift)
i++;
size = i - start;
if (size < 3 || size + min(size / 8, 2) < abs(shift)) {
while (start < i) {
- OLDNUM(start) = _NEWINDEX;
+ OLDNUM(SP_PARM, start) = _NEWINDEX;
start++;
}
}
}
/* After clearing invalid hunks, try grow the rest. */
- grow_hunks();
+ grow_hunks(SP_PARM);
+}
+
+#if NCURSES_SP_FUNCS
+NCURSES_EXPORT(void)
+_nc_hash_map(void)
+{
+ NCURSES_SP_NAME(_nc_hash_map) (CURRENT_SCREEN);
+}
+#endif
+
+NCURSES_EXPORT(void)
+NCURSES_SP_NAME(_nc_make_oldhash) (NCURSES_SP_DCLx int i)
+{
+ if (oldhash(SP_PARM))
+ oldhash(SP_PARM)[i] = hash(SP_PARM, OLDTEXT(SP_PARM, i));
}
+#if NCURSES_SP_FUNCS
NCURSES_EXPORT(void)
_nc_make_oldhash(int i)
{
- if (oldhash)
- oldhash[i] = hash(OLDTEXT(i));
+ NCURSES_SP_NAME(_nc_make_oldhash) (CURRENT_SCREEN, i);
}
+#endif
NCURSES_EXPORT(void)
-_nc_scroll_oldhash(int n, int top, int bot)
+NCURSES_SP_NAME(_nc_scroll_oldhash) (NCURSES_SP_DCLx int n, int top, int bot)
{
size_t size;
int i;
- if (!oldhash)
+ if (!oldhash(SP_PARM))
return;
- size = sizeof(*oldhash) * (bot - top + 1 - abs(n));
+ size = sizeof(*(oldhash(SP_PARM))) * (size_t) (bot - top + 1 - abs(n));
if (n > 0) {
- memmove(oldhash + top, oldhash + top + n, size);
+ memmove(oldhash(SP_PARM) + top, oldhash(SP_PARM) + top + n, size);
for (i = bot; i > bot - n; i--)
- oldhash[i] = hash(OLDTEXT(i));
+ oldhash(SP_PARM)[i] = hash(SP_PARM, OLDTEXT(SP_PARM, i));
} else {
- memmove(oldhash + top - n, oldhash + top, size);
+ memmove(oldhash(SP_PARM) + top - n, oldhash(SP_PARM) + top, size);
for (i = top; i < top - n; i++)
- oldhash[i] = hash(OLDTEXT(i));
+ oldhash(SP_PARM)[i] = hash(SP_PARM, OLDTEXT(SP_PARM, i));
}
}
+#if NCURSES_SP_FUNCS
+NCURSES_EXPORT(void)
+_nc_scroll_oldhash(int n, int top, int bot)
+{
+ NCURSES_SP_NAME(_nc_scroll_oldhash) (CURRENT_SCREEN, n, top, bot);
+}
+#endif
+
#ifdef HASHDEBUG
static void
usage(void)