blob: 8c0fdfd83f5c21ccf6570aeb6af01060aead22e9 [file] [log] [blame]
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +05301/****************************************************************************
Steve Kondikae271bc2015-11-15 02:50:53 +01002 * Copyright (c) 1998-2014,2015 Free Software Foundation, Inc. *
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +05303 * *
4 * Permission is hereby granted, free of charge, to any person obtaining a *
5 * copy of this software and associated documentation files (the *
6 * "Software"), to deal in the Software without restriction, including *
7 * without limitation the rights to use, copy, modify, merge, publish, *
8 * distribute, distribute with modifications, sublicense, and/or sell *
9 * copies of the Software, and to permit persons to whom the Software is *
10 * furnished to do so, subject to the following conditions: *
11 * *
12 * The above copyright notice and this permission notice shall be included *
13 * in all copies or substantial portions of the Software. *
14 * *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
16 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
18 * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR *
21 * THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
22 * *
23 * Except as contained in this notice, the name(s) of the above copyright *
24 * holders shall not be used in advertising or otherwise to promote the *
25 * sale, use or other dealings in this Software without prior written *
26 * authorization. *
27 ****************************************************************************/
28
29/****************************************************************************
30 * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 *
31 * and: Eric S. Raymond <esr@snark.thyrsus.com> *
32 ****************************************************************************/
33
34/******************************************************************************
35
36NAME
37 hashmap.c -- fill in scramble vector based on text hashes
38
39SYNOPSIS
40 void _nc_hash_map(void)
41
42DESCRIPTION:
43 This code attempts to recognize pairs of old and new lines in the physical
44and virtual screens. When a line pair is recognized, the old line index is
45placed in the oldindex member of the virtual screen line, to be used by the
46vertical-motion optimizer portion of the update logic (see hardscroll.c).
47
48 Line pairs are recognized by applying a modified Heckel's algorithm,
49sped up by hashing. If a line hash is unique in both screens, those
50lines must be a pair. Then if the lines just before or after the pair
51are the same or similar, they are a pair too.
52
53 We don't worry about false pairs produced by hash collisions, on the
54assumption that such cases are rare and will only make the latter stages
55of update less efficient, not introduce errors.
56
57HOW TO TEST THIS:
58
59Use the following production:
60
61hashmap: hashmap.c
62 $(CC) -g -DHASHDEBUG hashmap.c hardscroll.c ../objects/lib_trace.o -o hashmap
63
64AUTHOR
65 Eric S. Raymond <esr@snark.thyrsus.com>, May 1996
66 Bug fixes and improvements by Alexander V. Lukyanov <lav@yars.free.net>, 1997
67
68*****************************************************************************/
69
70#include <curses.priv.h>
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +053071
Steve Kondikae271bc2015-11-15 02:50:53 +010072#ifndef CUR
73#define CUR SP_TERMTYPE
74#endif
75
76MODULE_ID("$Id: hashmap.c,v 1.65 2015/07/25 20:13:56 tom Exp $")
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +053077
78#ifdef HASHDEBUG
79
80# define _tracef printf
81# undef TR
Steve Kondikae271bc2015-11-15 02:50:53 +010082# ifdef TRACE
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +053083# define TR(n, a) if (_nc_tracing & (n)) { _tracef a ; putchar('\n'); }
Steve Kondikae271bc2015-11-15 02:50:53 +010084# else
85# define TR(n, a) { _tracef a ; putchar('\n'); }
86# endif
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +053087# undef screen_lines
Steve Kondikae271bc2015-11-15 02:50:53 +010088# define screen_lines(sp) MAXLINES
89# define TEXTWIDTH(sp) 1
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +053090int oldnums[MAXLINES], reallines[MAXLINES];
Steve Kondikae271bc2015-11-15 02:50:53 +010091static NCURSES_CH_T oldtext[MAXLINES][TEXTWIDTH(sp)];
92static NCURSES_CH_T newtext[MAXLINES][TEXTWIDTH(sp)];
93# define OLDNUM(sp,n) oldnums[n]
94# define OLDTEXT(sp,n) oldtext[n]
95# define NEWTEXT(sp,m) newtext[m]
96# define PENDING(sp,n) 1
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +053097
98#else /* !HASHDEBUG */
99
Steve Kondikae271bc2015-11-15 02:50:53 +0100100# define OLDNUM(sp,n) (sp)->_oldnum_list[n]
101# define OLDTEXT(sp,n) CurScreen(sp)->_line[n].text
102# define NEWTEXT(sp,m) NewScreen(sp)->_line[m].text
103# define TEXTWIDTH(sp) (CurScreen(sp)->_maxx + 1)
104# define PENDING(sp,n) (NewScreen(sp)->_line[n].firstchar != _NOCHANGE)
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530105
106#endif /* !HASHDEBUG */
107
Steve Kondikae271bc2015-11-15 02:50:53 +0100108#define oldhash(sp) ((sp)->oldhash)
109#define newhash(sp) ((sp)->newhash)
110#define hashtab(sp) ((sp)->hashtab)
111#define lines_alloc(sp) ((sp)->hashtab_len)
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530112
113#if USE_WIDEC_SUPPORT
114#define HASH_VAL(ch) (ch.chars[0])
115#else
116#define HASH_VAL(ch) (ch)
117#endif
118
119static const NCURSES_CH_T blankchar = NewChar(BLANK_TEXT);
120
121static NCURSES_INLINE unsigned long
Steve Kondikae271bc2015-11-15 02:50:53 +0100122hash(SCREEN *sp, NCURSES_CH_T * text)
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530123{
124 int i;
125 NCURSES_CH_T ch;
126 unsigned long result = 0;
Steve Kondikae271bc2015-11-15 02:50:53 +0100127 (void) sp;
128
129 for (i = TEXTWIDTH(sp); i > 0; i--) {
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530130 ch = *text++;
Steve Kondikae271bc2015-11-15 02:50:53 +0100131 result += (result << 5) + (unsigned long) HASH_VAL(ch);
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530132 }
133 return result;
134}
135
136/* approximate update cost */
137static int
Steve Kondikae271bc2015-11-15 02:50:53 +0100138update_cost(SCREEN *sp, NCURSES_CH_T * from, NCURSES_CH_T * to)
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530139{
140 int cost = 0;
141 int i;
Steve Kondikae271bc2015-11-15 02:50:53 +0100142 (void) sp;
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530143
Steve Kondikae271bc2015-11-15 02:50:53 +0100144 for (i = TEXTWIDTH(sp); i > 0; i--, from++, to++)
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530145 if (!(CharEq(*from, *to)))
146 cost++;
147
148 return cost;
149}
150
151static int
Steve Kondikae271bc2015-11-15 02:50:53 +0100152update_cost_from_blank(SCREEN *sp, NCURSES_CH_T * to)
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530153{
154 int cost = 0;
155 int i;
156 NCURSES_CH_T blank = blankchar;
Steve Kondikae271bc2015-11-15 02:50:53 +0100157 (void) sp;
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530158
159 if (back_color_erase)
160 SetPair(blank, GetPair(stdscr->_nc_bkgd));
161
Steve Kondikae271bc2015-11-15 02:50:53 +0100162 for (i = TEXTWIDTH(sp); i > 0; i--, to++)
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530163 if (!(CharEq(blank, *to)))
164 cost++;
165
166 return cost;
167}
168
169/*
170 * Returns true when moving line 'from' to line 'to' seems to be cost
171 * effective. 'blank' indicates whether the line 'to' would become blank.
172 */
173static NCURSES_INLINE bool
Steve Kondikae271bc2015-11-15 02:50:53 +0100174cost_effective(SCREEN *sp, const int from, const int to, const int blank)
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530175{
176 int new_from;
177
178 if (from == to)
179 return FALSE;
180
Steve Kondikae271bc2015-11-15 02:50:53 +0100181 new_from = OLDNUM(sp, from);
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530182 if (new_from == _NEWINDEX)
183 new_from = from;
184
185 /*
186 * On the left side of >= is the cost before moving;
187 * on the right side -- cost after moving.
188 */
Steve Kondikae271bc2015-11-15 02:50:53 +0100189 return (((blank ? update_cost_from_blank(sp, NEWTEXT(sp, to))
190 : update_cost(sp, OLDTEXT(sp, to), NEWTEXT(sp, to)))
191 + update_cost(sp, OLDTEXT(sp, new_from), NEWTEXT(sp, from)))
192 >= ((new_from == from ? update_cost_from_blank(sp, NEWTEXT(sp, from))
193 : update_cost(sp, OLDTEXT(sp, new_from), NEWTEXT(sp, from)))
194 + update_cost(sp, OLDTEXT(sp, from), NEWTEXT(sp, to))))
195 ? TRUE : FALSE;
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530196}
197
198static void
Steve Kondikae271bc2015-11-15 02:50:53 +0100199grow_hunks(SCREEN *sp)
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530200{
201 int start, end, shift;
202 int back_limit, forward_limit; /* limits for cells to fill */
203 int back_ref_limit, forward_ref_limit; /* limits for refrences */
204 int i;
205 int next_hunk;
206
207 /*
208 * This is tricky part. We have unique pairs to use as anchors.
209 * Use these to deduce the presence of spans of identical lines.
210 */
211 back_limit = 0;
212 back_ref_limit = 0;
213
214 i = 0;
Steve Kondikae271bc2015-11-15 02:50:53 +0100215 while (i < screen_lines(sp) && OLDNUM(sp, i) == _NEWINDEX)
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530216 i++;
Steve Kondikae271bc2015-11-15 02:50:53 +0100217 for (; i < screen_lines(sp); i = next_hunk) {
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530218 start = i;
Steve Kondikae271bc2015-11-15 02:50:53 +0100219 shift = OLDNUM(sp, i) - i;
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530220
221 /* get forward limit */
222 i = start + 1;
Steve Kondikae271bc2015-11-15 02:50:53 +0100223 while (i < screen_lines(sp)
224 && OLDNUM(sp, i) != _NEWINDEX
225 && OLDNUM(sp, i) - i == shift)
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530226 i++;
227 end = i;
Steve Kondikae271bc2015-11-15 02:50:53 +0100228 while (i < screen_lines(sp) && OLDNUM(sp, i) == _NEWINDEX)
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530229 i++;
230 next_hunk = i;
231 forward_limit = i;
Steve Kondikae271bc2015-11-15 02:50:53 +0100232 if (i >= screen_lines(sp) || OLDNUM(sp, i) >= i)
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530233 forward_ref_limit = i;
234 else
Steve Kondikae271bc2015-11-15 02:50:53 +0100235 forward_ref_limit = OLDNUM(sp, i);
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530236
237 i = start - 1;
238 /* grow back */
239 if (shift < 0)
240 back_limit = back_ref_limit + (-shift);
241 while (i >= back_limit) {
Steve Kondikae271bc2015-11-15 02:50:53 +0100242 if (newhash(sp)[i] == oldhash(sp)[i + shift]
243 || cost_effective(sp, i + shift, i, shift < 0)) {
244 OLDNUM(sp, i) = i + shift;
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530245 TR(TRACE_UPDATE | TRACE_MOVE,
246 ("connected new line %d to old line %d (backward continuation)",
247 i, i + shift));
248 } else {
249 TR(TRACE_UPDATE | TRACE_MOVE,
250 ("not connecting new line %d to old line %d (backward continuation)",
251 i, i + shift));
252 break;
253 }
254 i--;
255 }
256
257 i = end;
258 /* grow forward */
259 if (shift > 0)
260 forward_limit = forward_ref_limit - shift;
261 while (i < forward_limit) {
Steve Kondikae271bc2015-11-15 02:50:53 +0100262 if (newhash(sp)[i] == oldhash(sp)[i + shift]
263 || cost_effective(sp, i + shift, i, shift > 0)) {
264 OLDNUM(sp, i) = i + shift;
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530265 TR(TRACE_UPDATE | TRACE_MOVE,
266 ("connected new line %d to old line %d (forward continuation)",
267 i, i + shift));
268 } else {
269 TR(TRACE_UPDATE | TRACE_MOVE,
270 ("not connecting new line %d to old line %d (forward continuation)",
271 i, i + shift));
272 break;
273 }
274 i++;
275 }
276
277 back_ref_limit = back_limit = i;
278 if (shift > 0)
279 back_ref_limit += shift;
280 }
281}
282
283NCURSES_EXPORT(void)
Steve Kondikae271bc2015-11-15 02:50:53 +0100284NCURSES_SP_NAME(_nc_hash_map) (NCURSES_SP_DCL0)
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530285{
Steve Kondikae271bc2015-11-15 02:50:53 +0100286 HASHMAP *hsp;
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530287 register int i;
288 int start, shift, size;
289
Steve Kondikae271bc2015-11-15 02:50:53 +0100290 if (screen_lines(SP_PARM) > lines_alloc(SP_PARM)) {
291 if (hashtab(SP_PARM))
292 free(hashtab(SP_PARM));
293 hashtab(SP_PARM) = typeMalloc(HASHMAP,
294 ((size_t) screen_lines(SP_PARM) + 1) * 2);
295 if (!hashtab(SP_PARM)) {
296 if (oldhash(SP_PARM)) {
297 FreeAndNull(oldhash(SP_PARM));
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530298 }
Steve Kondikae271bc2015-11-15 02:50:53 +0100299 lines_alloc(SP_PARM) = 0;
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530300 return;
301 }
Steve Kondikae271bc2015-11-15 02:50:53 +0100302 lines_alloc(SP_PARM) = screen_lines(SP_PARM);
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530303 }
304
Steve Kondikae271bc2015-11-15 02:50:53 +0100305 if (oldhash(SP_PARM) && newhash(SP_PARM)) {
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530306 /* re-hash only changed lines */
Steve Kondikae271bc2015-11-15 02:50:53 +0100307 for (i = 0; i < screen_lines(SP_PARM); i++) {
308 if (PENDING(SP_PARM, i))
309 newhash(SP_PARM)[i] = hash(SP_PARM, NEWTEXT(SP_PARM, i));
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530310 }
311 } else {
312 /* re-hash all */
Steve Kondikae271bc2015-11-15 02:50:53 +0100313 if (oldhash(SP_PARM) == 0)
314 oldhash(SP_PARM) = typeCalloc(unsigned long,
315 (size_t) screen_lines(SP_PARM));
316 if (newhash(SP_PARM) == 0)
317 newhash(SP_PARM) = typeCalloc(unsigned long,
318 (size_t) screen_lines(SP_PARM));
319 if (!oldhash(SP_PARM) || !newhash(SP_PARM))
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530320 return; /* malloc failure */
Steve Kondikae271bc2015-11-15 02:50:53 +0100321 for (i = 0; i < screen_lines(SP_PARM); i++) {
322 newhash(SP_PARM)[i] = hash(SP_PARM, NEWTEXT(SP_PARM, i));
323 oldhash(SP_PARM)[i] = hash(SP_PARM, OLDTEXT(SP_PARM, i));
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530324 }
325 }
326
327#ifdef HASH_VERIFY
Steve Kondikae271bc2015-11-15 02:50:53 +0100328 for (i = 0; i < screen_lines(SP_PARM); i++) {
329 if (newhash(SP_PARM)[i] != hash(SP_PARM, NEWTEXT(SP_PARM, i)))
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530330 fprintf(stderr, "error in newhash[%d]\n", i);
Steve Kondikae271bc2015-11-15 02:50:53 +0100331 if (oldhash(SP_PARM)[i] != hash(SP_PARM, OLDTEXT(SP_PARM, i)))
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530332 fprintf(stderr, "error in oldhash[%d]\n", i);
333 }
334#endif
335
336 /*
337 * Set up and count line-hash values.
338 */
Steve Kondikae271bc2015-11-15 02:50:53 +0100339 memset(hashtab(SP_PARM), '\0',
340 sizeof(*(hashtab(SP_PARM)))
341 * ((size_t) screen_lines(SP_PARM) + 1) * 2);
342 for (i = 0; i < screen_lines(SP_PARM); i++) {
343 unsigned long hashval = oldhash(SP_PARM)[i];
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530344
Steve Kondikae271bc2015-11-15 02:50:53 +0100345 for (hsp = hashtab(SP_PARM); hsp->hashval; hsp++)
346 if (hsp->hashval == hashval)
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530347 break;
Steve Kondikae271bc2015-11-15 02:50:53 +0100348 hsp->hashval = hashval; /* in case this is a new entry */
349 hsp->oldcount++;
350 hsp->oldindex = i;
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530351 }
Steve Kondikae271bc2015-11-15 02:50:53 +0100352 for (i = 0; i < screen_lines(SP_PARM); i++) {
353 unsigned long hashval = newhash(SP_PARM)[i];
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530354
Steve Kondikae271bc2015-11-15 02:50:53 +0100355 for (hsp = hashtab(SP_PARM); hsp->hashval; hsp++)
356 if (hsp->hashval == hashval)
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530357 break;
Steve Kondikae271bc2015-11-15 02:50:53 +0100358 hsp->hashval = hashval; /* in case this is a new entry */
359 hsp->newcount++;
360 hsp->newindex = i;
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530361
Steve Kondikae271bc2015-11-15 02:50:53 +0100362 OLDNUM(SP_PARM, i) = _NEWINDEX; /* initialize old indices array */
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530363 }
364
365 /*
366 * Mark line pairs corresponding to unique hash pairs.
367 *
368 * We don't mark lines with offset 0, because it can make fail
369 * extending hunks by cost_effective. Otherwise, it does not
370 * have any side effects.
371 */
Steve Kondikae271bc2015-11-15 02:50:53 +0100372 for (hsp = hashtab(SP_PARM); hsp->hashval; hsp++)
373 if (hsp->oldcount == 1 && hsp->newcount == 1
374 && hsp->oldindex != hsp->newindex) {
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530375 TR(TRACE_UPDATE | TRACE_MOVE,
376 ("new line %d is hash-identical to old line %d (unique)",
Steve Kondikae271bc2015-11-15 02:50:53 +0100377 hsp->newindex, hsp->oldindex));
378 OLDNUM(SP_PARM, hsp->newindex) = hsp->oldindex;
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530379 }
380
Steve Kondikae271bc2015-11-15 02:50:53 +0100381 grow_hunks(SP_PARM);
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530382
383 /*
384 * Eliminate bad or impossible shifts -- this includes removing
385 * those hunks which could not grow because of conflicts, as well
386 * those which are to be moved too far, they are likely to destroy
387 * more than carry.
388 */
Steve Kondikae271bc2015-11-15 02:50:53 +0100389 for (i = 0; i < screen_lines(SP_PARM);) {
390 while (i < screen_lines(SP_PARM) && OLDNUM(SP_PARM, i) == _NEWINDEX)
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530391 i++;
Steve Kondikae271bc2015-11-15 02:50:53 +0100392 if (i >= screen_lines(SP_PARM))
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530393 break;
394 start = i;
Steve Kondikae271bc2015-11-15 02:50:53 +0100395 shift = OLDNUM(SP_PARM, i) - i;
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530396 i++;
Steve Kondikae271bc2015-11-15 02:50:53 +0100397 while (i < screen_lines(SP_PARM)
398 && OLDNUM(SP_PARM, i) != _NEWINDEX
399 && OLDNUM(SP_PARM, i) - i == shift)
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530400 i++;
401 size = i - start;
402 if (size < 3 || size + min(size / 8, 2) < abs(shift)) {
403 while (start < i) {
Steve Kondikae271bc2015-11-15 02:50:53 +0100404 OLDNUM(SP_PARM, start) = _NEWINDEX;
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530405 start++;
406 }
407 }
408 }
409
410 /* After clearing invalid hunks, try grow the rest. */
Steve Kondikae271bc2015-11-15 02:50:53 +0100411 grow_hunks(SP_PARM);
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530412}
413
Steve Kondikae271bc2015-11-15 02:50:53 +0100414#if NCURSES_SP_FUNCS
415NCURSES_EXPORT(void)
416_nc_hash_map(void)
417{
418 NCURSES_SP_NAME(_nc_hash_map) (CURRENT_SCREEN);
419}
420#endif
421
422NCURSES_EXPORT(void)
423NCURSES_SP_NAME(_nc_make_oldhash) (NCURSES_SP_DCLx int i)
424{
425 if (oldhash(SP_PARM))
426 oldhash(SP_PARM)[i] = hash(SP_PARM, OLDTEXT(SP_PARM, i));
427}
428
429#if NCURSES_SP_FUNCS
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530430NCURSES_EXPORT(void)
431_nc_make_oldhash(int i)
432{
Steve Kondikae271bc2015-11-15 02:50:53 +0100433 NCURSES_SP_NAME(_nc_make_oldhash) (CURRENT_SCREEN, i);
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530434}
Steve Kondikae271bc2015-11-15 02:50:53 +0100435#endif
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530436
437NCURSES_EXPORT(void)
Steve Kondikae271bc2015-11-15 02:50:53 +0100438NCURSES_SP_NAME(_nc_scroll_oldhash) (NCURSES_SP_DCLx int n, int top, int bot)
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530439{
440 size_t size;
441 int i;
442
Steve Kondikae271bc2015-11-15 02:50:53 +0100443 if (!oldhash(SP_PARM))
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530444 return;
445
Steve Kondikae271bc2015-11-15 02:50:53 +0100446 size = sizeof(*(oldhash(SP_PARM))) * (size_t) (bot - top + 1 - abs(n));
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530447 if (n > 0) {
Steve Kondikae271bc2015-11-15 02:50:53 +0100448 memmove(oldhash(SP_PARM) + top, oldhash(SP_PARM) + top + n, size);
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530449 for (i = bot; i > bot - n; i--)
Steve Kondikae271bc2015-11-15 02:50:53 +0100450 oldhash(SP_PARM)[i] = hash(SP_PARM, OLDTEXT(SP_PARM, i));
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530451 } else {
Steve Kondikae271bc2015-11-15 02:50:53 +0100452 memmove(oldhash(SP_PARM) + top - n, oldhash(SP_PARM) + top, size);
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530453 for (i = top; i < top - n; i++)
Steve Kondikae271bc2015-11-15 02:50:53 +0100454 oldhash(SP_PARM)[i] = hash(SP_PARM, OLDTEXT(SP_PARM, i));
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530455 }
456}
457
Steve Kondikae271bc2015-11-15 02:50:53 +0100458#if NCURSES_SP_FUNCS
459NCURSES_EXPORT(void)
460_nc_scroll_oldhash(int n, int top, int bot)
461{
462 NCURSES_SP_NAME(_nc_scroll_oldhash) (CURRENT_SCREEN, n, top, bot);
463}
464#endif
465
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530466#ifdef HASHDEBUG
467static void
468usage(void)
469{
470 static const char *table[] =
471 {
472 "hashmap test-driver",
473 "",
474 "# comment",
475 "l get initial line number vector",
476 "n use following letters as text of new lines",
477 "o use following letters as text of old lines",
478 "d dump state of test arrays",
479 "h apply hash mapper and see scroll optimization",
480 "? this message"
481 };
482 size_t n;
483 for (n = 0; n < sizeof(table) / sizeof(table[0]); n++)
484 fprintf(stderr, "%s\n", table[n]);
485}
486
487int
488main(int argc GCC_UNUSED, char *argv[]GCC_UNUSED)
489{
490 char line[BUFSIZ], *st;
491 int n;
492
493 if (setupterm(NULL, fileno(stdout), (int *) 0) == ERR)
494 return EXIT_FAILURE;
495 (void) _nc_alloc_screen();
496
Steve Kondikae271bc2015-11-15 02:50:53 +0100497 for (n = 0; n < screen_lines(sp); n++) {
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530498 reallines[n] = n;
499 oldnums[n] = _NEWINDEX;
500 CharOf(oldtext[n][0]) = CharOf(newtext[n][0]) = '.';
501 }
502
Steve Kondikae271bc2015-11-15 02:50:53 +0100503 if (NC_ISATTY(fileno(stdin)))
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530504 usage();
505
506#ifdef TRACE
507 _nc_tracing = TRACE_MOVE;
508#endif
509 for (;;) {
510 /* grab a test command */
511 if (fgets(line, sizeof(line), stdin) == (char *) NULL)
512 break;
513
514 switch (line[0]) {
515 case '#': /* comment */
516 (void) fputs(line, stderr);
517 break;
518
519 case 'l': /* get initial line number vector */
Steve Kondikae271bc2015-11-15 02:50:53 +0100520 for (n = 0; n < screen_lines(sp); n++) {
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530521 reallines[n] = n;
522 oldnums[n] = _NEWINDEX;
523 }
524 n = 0;
525 st = strtok(line, " ");
526 do {
527 oldnums[n++] = atoi(st);
528 } while
529 ((st = strtok((char *) NULL, " ")) != 0);
530 break;
531
532 case 'n': /* use following letters as text of new lines */
Steve Kondikae271bc2015-11-15 02:50:53 +0100533 for (n = 0; n < screen_lines(sp); n++)
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530534 CharOf(newtext[n][0]) = '.';
Steve Kondikae271bc2015-11-15 02:50:53 +0100535 for (n = 0; n < screen_lines(sp); n++)
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530536 if (line[n + 1] == '\n')
537 break;
538 else
539 CharOf(newtext[n][0]) = line[n + 1];
540 break;
541
542 case 'o': /* use following letters as text of old lines */
Steve Kondikae271bc2015-11-15 02:50:53 +0100543 for (n = 0; n < screen_lines(sp); n++)
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530544 CharOf(oldtext[n][0]) = '.';
Steve Kondikae271bc2015-11-15 02:50:53 +0100545 for (n = 0; n < screen_lines(sp); n++)
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530546 if (line[n + 1] == '\n')
547 break;
548 else
549 CharOf(oldtext[n][0]) = line[n + 1];
550 break;
551
552 case 'd': /* dump state of test arrays */
553#ifdef TRACE
554 _nc_linedump();
555#endif
556 (void) fputs("Old lines: [", stdout);
Steve Kondikae271bc2015-11-15 02:50:53 +0100557 for (n = 0; n < screen_lines(sp); n++)
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530558 putchar(CharOf(oldtext[n][0]));
559 putchar(']');
560 putchar('\n');
561 (void) fputs("New lines: [", stdout);
Steve Kondikae271bc2015-11-15 02:50:53 +0100562 for (n = 0; n < screen_lines(sp); n++)
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530563 putchar(CharOf(newtext[n][0]));
564 putchar(']');
565 putchar('\n');
566 break;
567
568 case 'h': /* apply hash mapper and see scroll optimization */
569 _nc_hash_map();
570 (void) fputs("Result:\n", stderr);
571#ifdef TRACE
572 _nc_linedump();
573#endif
574 _nc_scroll_optimize();
575 (void) fputs("Done.\n", stderr);
576 break;
577 default:
578 case '?':
579 usage();
580 break;
581 }
582 }
583#if NO_LEAKS
584 _nc_free_and_exit(EXIT_SUCCESS);
585#else
586 return EXIT_SUCCESS;
587#endif
588}
589
590#endif /* HASHDEBUG */
591
592/* hashmap.c ends here */