|
|
1.1 root 1: /* @(#)ll_refresh.c 1.1 (1.22) */
2: #include "curses.ext"
3:
4: extern int InputPending;
5: extern int outchcount;
6:
7: extern int *context;
8:
9: int didntdobotright; /* writechars didn't output char in bot right corner */
10:
11: /*
12: * Optimally make the screen (which currently looks like SP->cur_body)
13: * look like SP->std_body. If use_idl is 1, this routine will call
14: * out all its horses, including some code to figure out
15: * how to use insert/delete line. If use_idl is 0, or if the terminal
16: * does not have insert/delete line, a simpler scheme will
17: * be used, and the insert/delete line features of the terminal will not
18: * be used.
19: *
20: * While the original intent of this parameter was speed (insert/delete
21: * line was slow) the parameter currently is there to avoid annoying
22: * the user with unnecessary insert/delete lines.
23: */
24: int
25: _ll_refresh (use_idl)
26: int use_idl;
27: {
28: register int n, i, j;
29: register struct line *dln, *pln;
30: struct line *_line_alloc();
31:
32: #ifdef DEBUG
33: if(outf) fprintf(outf, "_ll_refresh(%d)\n", use_idl);
34: if(outf) fprintf(outf, "phys cursor at (%d,%d), want cursor at (%d,%d)\n",
35: SP->phys_y, SP->phys_x, SP->virt_y, SP->virt_x);
36: #endif DEBUG
37: outchcount = 0;
38: #ifdef FIONREAD
39: if( SP->check_fd >= 0 )
40: {
41: ioctl (SP->check_fd, FIONREAD, &InputPending);
42: }
43: else
44: {
45: InputPending = 0;
46: }
47: if( InputPending )
48: {
49: #ifdef DEBUG
50: if (outf) fprintf(outf, "InputPending %d, aborted ll_refresh at start\n", InputPending);
51: #endif DEBUG
52: return 0;
53: }
54: #endif FIONREAD
55: #ifdef NONSTANDARD
56: input_wait();
57: #endif NONSTANDARD
58: #ifdef DEBUG
59: if (outf) fprintf(outf, "virt cursor at y=%d, x=%d, length %d, length-1 %d\n",
60: SP->virt_y, SP->virt_x, SP->std_body[SP->virt_y+1]->length,
61: SP->std_body[SP->virt_y]->length);
62: #endif DEBUG
63: if( SP->virt_y >= 0 && SP->std_body[SP->virt_y+1]->length < SP->virt_x )
64: {
65: SP->std_body[SP->virt_y+1]->length =
66: SP->virt_x >= columns ? columns : SP->virt_x;
67: }
68: /* Get rid of trailing blanks on all lines */
69: for( n = 1; n <= lines; n++ )
70: {
71: dln = SP->std_body[n];
72: pln = SP->cur_body[n];
73: if( dln && dln != pln )
74: {
75: register chtype *p;
76:
77: if( i = dln->length )
78: {
79: p = dln->body + i;
80: while( *--p == ' ' && --i > 0 )
81: ;
82: dln->length = i;
83: }
84: }
85:
86: if( pln )
87: {
88: register chtype *p;
89:
90: if( i = pln->length )
91: {
92: p = pln->body + i;
93: while( *--p == ' ' && --i > 0 )
94: ;
95: pln->length = i;
96: }
97: }
98: }
99: if( magic_cookie_glitch > 0 )
100: _toss_cookies();
101: #ifdef DEBUG
102: if(outf) fprintf(outf, "what we have:\n");
103: for( i=1; i<=lines; i++ )
104: {
105: if(outf) fprintf(outf, "%8x: ", SP->cur_body[i]);
106: if( SP->cur_body[i] == NULL )
107: {
108: if(outf) fprintf(outf, "()\n");
109: }
110: else
111: {
112: if(outf) fprintf(outf, "%4d ", SP->cur_body[i]->length);
113: for( j=0; j<SP->cur_body[i]->length; j++ )
114: {
115: n = SP->cur_body[i]->body[j];
116: if( n & A_ATTRIBUTES )
117: {
118: putc('\'', outf);
119: }
120: n &= 0177;
121: if(outf) fprintf(outf, "%c", n>=' ' ? n : '.');
122: }
123: if(outf) fprintf(outf, "\n");
124: }
125: }
126: if(outf) fprintf(outf, "what we want:\n");
127: for (i=1; i<=lines; i++)
128: {
129: if(outf) fprintf(outf, "%8x: ", SP->std_body[i]);
130: if (SP->std_body[i] == NULL)
131: {
132: if(outf) fprintf(outf, "()\n");
133: }
134: else
135: {
136: if(outf) fprintf(outf, "%4d ", SP->std_body[i]->length);
137: for (j=0; j<SP->std_body[i]->length; j++)
138: {
139: n = SP->std_body[i]->body[j];
140: if (n & A_ATTRIBUTES)
141: {
142: putc('\'', outf);
143: }
144: n &= 0177;
145: if(outf) fprintf(outf, "%c", n>=' ' ? n : '.');
146: }
147: if(outf) fprintf(outf, "\n");
148: }
149: }
150: if(outf) fprintf(outf, "----\n");
151: if(outf) fflush(outf);
152: #endif DEBUG
153: SP->check_input = SP->baud / 2400;
154: if (SP->doclear)
155: {
156: #ifdef DEBUG
157: if(outf) fprintf(outf, "SP->doclear, clearing screen\n");
158: #endif
159: _reset();
160: SP->doclear = 0;
161: for( n = 0; n <= lines; n++ )
162: {
163: if( SP->cur_body[n] != SP->std_body[n] )
164: {
165: _line_free( SP->cur_body[n] );
166: }
167: SP->cur_body[n] = 0;
168: }
169: }
170:
171: /* Choose between two updating algorithms. */
172: if( use_idl && _cost(ilfixed) < INFINITY )
173: {
174: #ifdef DEBUG
175: if(outf) fprintf(outf, "use_idl\n");
176: #endif
177: for( n = 1; n <= lines; n++ )
178: {
179: if( SP->cur_body[n] == 0 )
180: {
181: SP->cur_body[n] = _line_alloc();
182: }
183: if( SP->std_body[n] == 0 )
184: {
185: SP->std_body[n] = SP->cur_body[n];
186: }
187: else
188: {
189: _comphash( SP->std_body[n] );
190: }
191: _comphash( SP->cur_body[n] );
192: }
193: /*
194: * Count number of matches if we scroll 1 line and if we
195: * don't scroll at all. This is primarily useful for the
196: * case where we scroll the whole screen. Scrolling a portion
197: * of the screen will be handled by the ins/del line routines,
198: * although a special case here might buy some CPU speed.
199: */
200: for( i=1,n=0,j=0; i<lines; i++ )
201: {
202: if( SP->cur_body[i+1]->hash == SP->std_body[i]->hash )
203: n++;
204: if( SP->cur_body[i]->hash == SP->std_body[i]->hash )
205: j++;
206: }
207: if( n > lines-3 && n > j )
208: {
209: _window(0, lines-1, 0, columns-1);
210: _scrollf(1);
211: _line_free(SP->cur_body[1]);
212: for( i=1; i<lines; i++ )
213: {
214: /* Copy line with two references since they
215: * are no longer the same row on screen. */
216: if( SP->cur_body[i+1] == SP->std_body[i+1] )
217: {
218: struct line *p;
219: int l;
220: chtype *b1, *b2;
221: p = _line_alloc ();
222: p->length=l=SP->cur_body[i+1]->length;
223: p->hash = SP->cur_body[i+1]->hash;
224: b1 = &(p->body[0]);
225: b2 = &(SP->cur_body[i+1]->body[0]);
226: for( ; l>0; l-- )
227: {
228: *b1++ = *b2++;
229: }
230: SP->std_body[i+1] = p;
231: }
232: SP->cur_body[i] = SP->cur_body[i+1];
233: }
234: SP->cur_body[lines] = _line_alloc();
235: }
236: i = 1;
237: /*
238: * Break the screen (from 1 to lines) into clumps of
239: * lines that are different. Thus we ignore the ones that
240: * are identical.
241: */
242: for( ;; )
243: {
244: while( i<=lines && SP->cur_body[i]==SP->std_body[i] )
245: {
246: i++;
247: }
248: if( i > lines )
249: {
250: break;
251: }
252: for( j=i; j <= lines &&
253: SP->cur_body[j] != SP->std_body[j]; j++)
254: ;
255: j--;
256: #ifdef DEBUG
257: if(outf) fprintf(outf, "window from %d to %d\n", i, j);
258: #endif
259: /* i thru j is a window of different lines. */
260: if( i == j )
261: {
262: _id_char(SP->cur_body[i], SP->std_body[i], i-1);
263: if( SP->cur_body[i] != SP->std_body[i] )
264: {
265: _line_free (SP->cur_body[i]);
266: }
267: SP->cur_body[i] = SP->std_body[i];
268: }
269: else
270: {
271: _window(i-1, j-1, 0, columns-1);
272: _setwind(); /* Force action for moves, etc */
273: _id_line(i, j);
274: }
275: i = j+1;
276: }
277: }
278: else /* fast update */
279: {
280: #ifdef DEBUG
281: if(outf) fprintf(outf, "Fast Update, lines %d\n", lines);
282: #endif
283: _window(0, lines-1, 0, columns-1);
284: _setwind(); /* Force action for moves, etc */
285: for( n = 1; n <= lines; n++ )
286: if( SP->std_body[n] != SP->cur_body[n] )
287: {
288: _id_char( SP->cur_body[n],SP->std_body[n],n-1 );
289: if( SP->cur_body[n] != SP->std_body[n] )
290: {
291: _line_free (SP->cur_body[n]);
292: }
293: SP->cur_body[n] = SP->std_body[n];
294: }
295: }
296:
297: /*
298: * Didn't output char in bottom right corner of screen.
299: * Remember this fact so that next time when it's higher
300: * on the screen, we'll fix it up.
301: */
302: if( didntdobotright )
303: {
304: int holdvx, holdvy;
305: #ifdef DEBUG
306: if (outf) fprintf(outf, "didntdobotright so setting SP->cur_body[%d]->body[%d] from '%c' to space.\n", lines, columns-1, SP->cur_body[lines]->body[columns-1]);
307: #endif
308: holdvx = SP->virt_x;
309: holdvy = SP->virt_y;
310: /*
311: * This code in effect marks the last line dirty
312: * so that the next time it will get fixed. It also
313: * splits the line back into virt/phys so we don't
314: * clobber the virtual part too.
315: */
316: _ll_move(lines-1, columns-1);
317: SP->cur_body[lines]->body[columns-1] = ' ';
318: didntdobotright = 0;
319: /* Now restore the cursor we clobbered. */
320: _ll_move(holdvy, holdvx);
321: }
322:
323: _hlmode(0); _sethl();
324: #ifdef DEBUG
325: if(outf) fprintf(outf, "at end, phys SP->curptr at (%d,%d), want SP->curptr at (%d,%d)\n",
326: SP->phys_y, SP->phys_x, SP->virt_y, SP->virt_x);
327: #endif DEBUG
328: #ifdef notdef
329: if(magic_cookie_glitch > 0)
330: _fixcursor();
331: #endif notdef
332: if( !InputPending && SP->virt_x >= 0 && SP->virt_y >= 0 )
333: {
334: _pos (SP->virt_y, SP->virt_x);
335: }
336: __cflush();
337: #ifdef DEBUG
338: if(outf) fprintf(outf, "end of _ll_refresh, InputPending %d\n", InputPending);
339: if(outf) fflush(outf);
340: #endif DEBUG
341: return outchcount;
342: }
343:
344: /*
345: * This routine is only needed on terminals with the "magic cookie"
346: * effect. The problem is that the designers of
347: * these terminals didn't allocate 16 bits for
348: * each character (7 for the character and 9 for attributes) but instead
349: * created some reserved "magic cookie" characters to tell the scan
350: * routine "you should change attributes now". This would be fine except
351: * that these cookies take up a space in memory, and usually display as a
352: * blank. This makes it impossible to display what the user really
353: * wanted, if he is using attributes for underlining, bold, etc. Such
354: * terminals include the Teleray 1061, TVI 912 and 950, Teletype
355: * DataSpeed 40, and Adds Regent 40.
356: *
357: * One approach to this problem is to make everybody pay the price of
358: * this effect, forcing the programmer to allocate a blank space
359: * when attributes are changed. This works cleanly but I consider it
360: * unacceptable.
361: *
362: * My approach is to simulate what the programmer (who wasn't thinking
363: * about these terminals) wanted as closely as possible. If there
364: * is a desired blank in there, we use that slot. If not, we shove the
365: * rest of the line to the right one space. (When several attributes
366: * are changed on one line, this can result in losing several characters
367: * from the right of the line.)
368: *
369: * This routine looks for places in SP->std_body where shoving to the
370: * right is needed, and does the required shoving.
371: */
372: static
373: _toss_cookies()
374: {
375: register int i, j, len;
376: register struct line *dsi;
377: register chtype *b;
378:
379: #ifdef DEBUG
380: if(outf) fprintf(outf, "_toss_cookies\n");
381: #endif
382: for( i=1; i<=lines; i++ )
383: {
384: dsi = SP->std_body[i];
385: if( dsi && dsi != SP->cur_body[i] )
386: {
387: len = dsi->length;
388: b = dsi->body;
389: for( j=0; j<len; j++ )
390: {
391: if( b[j]&A_ATTRIBUTES )
392: {
393: #ifdef DEBUG
394: if(outf) fprintf(outf, "_shove, line %d, char %d, val %o\n", i, j, b[j]);
395: #endif
396: dsi->length = _shove(b, len, i);
397: break;
398: }
399: }
400: }
401: }
402: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.