1/* display.c -- How to display Info windows.
| 1/* display.c -- How to display Info windows.
|
2 $Id: display.c,v 1.6 1997/07/24 21:13:27 karl Exp $
| 2 $Id: display.c,v 1.7 2002/03/08 21:41:44 karl Exp $
|
3 4 Copyright (C) 1993, 97 Free Software Foundation, Inc. 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 2, or (at your option) 9 any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program; if not, write to the Free Software 18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 20 Written by Brian Fox (bfox@ai.mit.edu). */ 21 22#include "info.h" 23#include "display.h" 24 25extern int info_any_buffered_input_p (); /* Found in session.c. */ 26 27static void free_display (); 28static DISPLAY_LINE **make_display (); 29 30/* An array of display lines which tell us what is currently visible on 31 the display. */ 32DISPLAY_LINE **the_display = (DISPLAY_LINE **)NULL; 33 34/* Non-zero means do no output. */ 35int display_inhibited = 0; 36 37/* Initialize THE_DISPLAY to WIDTH and HEIGHT, with nothing in it. */ 38void 39display_initialize_display (width, height) 40 int width, height; 41{ 42 free_display (the_display); 43 the_display = make_display (width, height); 44 display_clear_display (the_display); 45} 46 47/* Clear all of the lines in DISPLAY making the screen blank. */ 48void 49display_clear_display (display) 50 DISPLAY_LINE **display; 51{ 52 register int i; 53 register DISPLAY_LINE *display_line; 54 55 for (i = 0; (display_line = display[i]); i++) 56 { 57 display[i]->text[0] = '\0'; 58 display[i]->textlen = 0; 59 display[i]->inverse = 0; 60 } 61} 62 63/* Non-zero if we didn't completely redisplay a window. */ 64int display_was_interrupted_p = 0; 65 66/* Update the windows pointed to by WINDOW in the_display. This actually 67 writes the text on the screen. */ 68void 69display_update_display (window) 70 WINDOW *window; 71{ 72 register WINDOW *win; 73 74 display_was_interrupted_p = 0; 75 76 /* For every window in the list, check contents against the display. */ 77 for (win = window; win; win = win->next) 78 { 79 /* Only re-display visible windows which need updating. */ 80 if (((win->flags & W_WindowVisible) == 0) || 81 ((win->flags & W_UpdateWindow) == 0) || 82 (win->height == 0)) 83 continue; 84 85 display_update_one_window (win); 86 if (display_was_interrupted_p) 87 break; 88 } 89 90 /* Always update the echo area. */ 91 display_update_one_window (the_echo_area); 92} 93 94/* Display WIN on the_display. Unlike display_update_display (), this 95 function only does one window. */ 96void 97display_update_one_window (win) 98 WINDOW *win; 99{ 100 register char *nodetext; /* Current character to display. */ 101 register char *last_node_char; /* Position of the last character in node. */ 102 register int i; /* General use index. */ 103 char *printed_line; /* Buffer for a printed line. */ 104 int pl_index = 0; /* Index into PRINTED_LINE. */ 105 int line_index = 0; /* Number of lines done so far. */
| 3 4 Copyright (C) 1993, 97 Free Software Foundation, Inc. 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 2, or (at your option) 9 any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program; if not, write to the Free Software 18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 20 Written by Brian Fox (bfox@ai.mit.edu). */ 21 22#include "info.h" 23#include "display.h" 24 25extern int info_any_buffered_input_p (); /* Found in session.c. */ 26 27static void free_display (); 28static DISPLAY_LINE **make_display (); 29 30/* An array of display lines which tell us what is currently visible on 31 the display. */ 32DISPLAY_LINE **the_display = (DISPLAY_LINE **)NULL; 33 34/* Non-zero means do no output. */ 35int display_inhibited = 0; 36 37/* Initialize THE_DISPLAY to WIDTH and HEIGHT, with nothing in it. */ 38void 39display_initialize_display (width, height) 40 int width, height; 41{ 42 free_display (the_display); 43 the_display = make_display (width, height); 44 display_clear_display (the_display); 45} 46 47/* Clear all of the lines in DISPLAY making the screen blank. */ 48void 49display_clear_display (display) 50 DISPLAY_LINE **display; 51{ 52 register int i; 53 register DISPLAY_LINE *display_line; 54 55 for (i = 0; (display_line = display[i]); i++) 56 { 57 display[i]->text[0] = '\0'; 58 display[i]->textlen = 0; 59 display[i]->inverse = 0; 60 } 61} 62 63/* Non-zero if we didn't completely redisplay a window. */ 64int display_was_interrupted_p = 0; 65 66/* Update the windows pointed to by WINDOW in the_display. This actually 67 writes the text on the screen. */ 68void 69display_update_display (window) 70 WINDOW *window; 71{ 72 register WINDOW *win; 73 74 display_was_interrupted_p = 0; 75 76 /* For every window in the list, check contents against the display. */ 77 for (win = window; win; win = win->next) 78 { 79 /* Only re-display visible windows which need updating. */ 80 if (((win->flags & W_WindowVisible) == 0) || 81 ((win->flags & W_UpdateWindow) == 0) || 82 (win->height == 0)) 83 continue; 84 85 display_update_one_window (win); 86 if (display_was_interrupted_p) 87 break; 88 } 89 90 /* Always update the echo area. */ 91 display_update_one_window (the_echo_area); 92} 93 94/* Display WIN on the_display. Unlike display_update_display (), this 95 function only does one window. */ 96void 97display_update_one_window (win) 98 WINDOW *win; 99{ 100 register char *nodetext; /* Current character to display. */ 101 register char *last_node_char; /* Position of the last character in node. */ 102 register int i; /* General use index. */ 103 char *printed_line; /* Buffer for a printed line. */ 104 int pl_index = 0; /* Index into PRINTED_LINE. */ 105 int line_index = 0; /* Number of lines done so far. */
|
| 106 int pl_ignore = 0; /* How many chars use zero width on screen. */ 107 int allocated_win_width;
|
106 DISPLAY_LINE **display = the_display; 107 108 /* If display is inhibited, that counts as an interrupted display. */ 109 if (display_inhibited) 110 display_was_interrupted_p = 1; 111 112 /* If the window has no height, or display is inhibited, quit now. */ 113 if (!win->height || display_inhibited) 114 return; 115 116 /* If the window's first row doesn't appear in the_screen, then it 117 cannot be displayed. This can happen when the_echo_area is the 118 window to be displayed, and the screen has shrunk to less than one 119 line. */ 120 if ((win->first_row < 0) || (win->first_row > the_screen->height)) 121 return; 122 123 /* Print each line in the window into our local buffer, and then 124 check the contents of that buffer against the display. If they 125 differ, update the display. */
| 108 DISPLAY_LINE **display = the_display; 109 110 /* If display is inhibited, that counts as an interrupted display. */ 111 if (display_inhibited) 112 display_was_interrupted_p = 1; 113 114 /* If the window has no height, or display is inhibited, quit now. */ 115 if (!win->height || display_inhibited) 116 return; 117 118 /* If the window's first row doesn't appear in the_screen, then it 119 cannot be displayed. This can happen when the_echo_area is the 120 window to be displayed, and the screen has shrunk to less than one 121 line. */ 122 if ((win->first_row < 0) || (win->first_row > the_screen->height)) 123 return; 124 125 /* Print each line in the window into our local buffer, and then 126 check the contents of that buffer against the display. If they 127 differ, update the display. */
|
126 printed_line = (char *)xmalloc (1 + win->width);
| 128 allocated_win_width = win->width + 1; 129 printed_line = (char *)xmalloc (allocated_win_width);
|
127 128 if (!win->node || !win->line_starts) 129 goto done_with_node_display; 130 131 nodetext = win->line_starts[win->pagetop]; 132 last_node_char = win->node->contents + win->node->nodelen; 133 134 for (; nodetext < last_node_char; nodetext++) 135 { 136 char *rep, *rep_carried_over, rep_temp[2]; 137 int replen; 138 139 if (isprint (*nodetext)) 140 { 141 rep_temp[0] = *nodetext; 142 replen = 1; 143 rep_temp[1] = '\0'; 144 rep = rep_temp; 145 } 146 else 147 { 148 if (*nodetext == '\r' || *nodetext == '\n') 149 {
| 130 131 if (!win->node || !win->line_starts) 132 goto done_with_node_display; 133 134 nodetext = win->line_starts[win->pagetop]; 135 last_node_char = win->node->contents + win->node->nodelen; 136 137 for (; nodetext < last_node_char; nodetext++) 138 { 139 char *rep, *rep_carried_over, rep_temp[2]; 140 int replen; 141 142 if (isprint (*nodetext)) 143 { 144 rep_temp[0] = *nodetext; 145 replen = 1; 146 rep_temp[1] = '\0'; 147 rep = rep_temp; 148 } 149 else 150 { 151 if (*nodetext == '\r' || *nodetext == '\n') 152 {
|
150 replen = win->width - pl_index;
| 153 replen = win->width - pl_index + pl_ignore;
|
151 } 152 else 153 { 154 rep = printed_representation (*nodetext, pl_index); 155 replen = strlen (rep); 156 } 157 } 158
| 154 } 155 else 156 { 157 rep = printed_representation (*nodetext, pl_index); 158 replen = strlen (rep); 159 } 160 } 161
|
| 162 /* Support ANSI escape sequences under -R. */ 163 if (raw_escapes_p 164 && *nodetext == '\033' 165 && nodetext[1] == '[' 166 && isdigit (nodetext[2])) 167 { 168 if (nodetext[3] == 'm') 169 pl_ignore += 4; 170 else if (isdigit (nodetext[3]) && nodetext[4] == 'm') 171 pl_ignore += 5; 172 } 173 while (pl_index + 2 >= allocated_win_width - 1) 174 { 175 allocated_win_width *= 2; 176 printed_line = (char *)xrealloc (printed_line, allocated_win_width); 177 } 178
|
159 /* If this character can be printed without passing the width of 160 the line, then stuff it into the line. */
| 179 /* If this character can be printed without passing the width of 180 the line, then stuff it into the line. */
|
161 if (replen + pl_index < win->width)
| 181 if (replen + pl_index < win->width + pl_ignore)
|
162 { 163 /* Optimize if possible. */ 164 if (replen == 1) 165 { 166 printed_line[pl_index++] = *rep; 167 } 168 else 169 { 170 for (i = 0; i < replen; i++) 171 printed_line[pl_index++] = rep[i]; 172 } 173 } 174 else 175 { 176 DISPLAY_LINE *entry; 177 178 /* If this character cannot be printed in this line, we have 179 found the end of this line as it would appear on the screen. 180 Carefully print the end of the line, and then compare. */ 181 if (*nodetext == '\n' || *nodetext == '\r' || *nodetext == '\t') 182 { 183 printed_line[pl_index] = '\0'; 184 rep_carried_over = (char *)NULL; 185 } 186 else 187 { 188 /* The printed representation of this character extends into 189 the next line. Remember the offset of the last character 190 printed out of REP so that we can carry the character over 191 to the next line. */
| 182 { 183 /* Optimize if possible. */ 184 if (replen == 1) 185 { 186 printed_line[pl_index++] = *rep; 187 } 188 else 189 { 190 for (i = 0; i < replen; i++) 191 printed_line[pl_index++] = rep[i]; 192 } 193 } 194 else 195 { 196 DISPLAY_LINE *entry; 197 198 /* If this character cannot be printed in this line, we have 199 found the end of this line as it would appear on the screen. 200 Carefully print the end of the line, and then compare. */ 201 if (*nodetext == '\n' || *nodetext == '\r' || *nodetext == '\t') 202 { 203 printed_line[pl_index] = '\0'; 204 rep_carried_over = (char *)NULL; 205 } 206 else 207 { 208 /* The printed representation of this character extends into 209 the next line. Remember the offset of the last character 210 printed out of REP so that we can carry the character over 211 to the next line. */
|
192 for (i = 0; pl_index < (win->width - 1);)
| 212 for (i = 0; pl_index < (win->width + pl_ignore - 1);)
|
193 printed_line[pl_index++] = rep[i++]; 194 195 rep_carried_over = rep + i; 196 197 /* If printing the last character in this window couldn't 198 possibly cause the screen to scroll, place a backslash 199 in the rightmost column. */ 200 if (1 + line_index + win->first_row < the_screen->height) 201 { 202 if (win->flags & W_NoWrap) 203 printed_line[pl_index++] = '$'; 204 else 205 printed_line[pl_index++] = '\\'; 206 } 207 printed_line[pl_index] = '\0'; 208 } 209 210 /* We have the exact line as it should appear on the screen. 211 Check to see if this line matches the one already appearing 212 on the screen. */ 213 entry = display[line_index + win->first_row]; 214 215 /* If the screen line is inversed, then we have to clear 216 the line from the screen first. Why, I don't know. */
| 213 printed_line[pl_index++] = rep[i++]; 214 215 rep_carried_over = rep + i; 216 217 /* If printing the last character in this window couldn't 218 possibly cause the screen to scroll, place a backslash 219 in the rightmost column. */ 220 if (1 + line_index + win->first_row < the_screen->height) 221 { 222 if (win->flags & W_NoWrap) 223 printed_line[pl_index++] = '$'; 224 else 225 printed_line[pl_index++] = '\\'; 226 } 227 printed_line[pl_index] = '\0'; 228 } 229 230 /* We have the exact line as it should appear on the screen. 231 Check to see if this line matches the one already appearing 232 on the screen. */ 233 entry = display[line_index + win->first_row]; 234 235 /* If the screen line is inversed, then we have to clear 236 the line from the screen first. Why, I don't know. */
|
217 if (entry->inverse)
| 237 if (entry->inverse 238 /* Need to erase the line if it has escape sequences. */ 239 || (raw_escapes_p && strchr (entry->text, '\033') != 0))
|
218 { 219 terminal_goto_xy (0, line_index + win->first_row); 220 terminal_clear_to_eol (); 221 entry->inverse = 0; 222 entry->text[0] = '\0'; 223 entry->textlen = 0; 224 } 225 226 /* Find the offset where these lines differ. */ 227 for (i = 0; i < pl_index; i++) 228 if (printed_line[i] != entry->text[i]) 229 break; 230 231 /* If the lines are not the same length, or if they differed 232 at all, we must do some redrawing. */ 233 if ((i != pl_index) || (pl_index != entry->textlen)) 234 { 235 /* Move to the proper point on the terminal. */ 236 terminal_goto_xy (i, line_index + win->first_row); 237 238 /* If there is any text to print, print it. */ 239 if (i != pl_index) 240 terminal_put_text (printed_line + i); 241 242 /* If the printed text didn't extend all the way to the edge 243 of the window, and text was appearing between here and the 244 edge of the window, clear from here to the end of the line. */
| 240 { 241 terminal_goto_xy (0, line_index + win->first_row); 242 terminal_clear_to_eol (); 243 entry->inverse = 0; 244 entry->text[0] = '\0'; 245 entry->textlen = 0; 246 } 247 248 /* Find the offset where these lines differ. */ 249 for (i = 0; i < pl_index; i++) 250 if (printed_line[i] != entry->text[i]) 251 break; 252 253 /* If the lines are not the same length, or if they differed 254 at all, we must do some redrawing. */ 255 if ((i != pl_index) || (pl_index != entry->textlen)) 256 { 257 /* Move to the proper point on the terminal. */ 258 terminal_goto_xy (i, line_index + win->first_row); 259 260 /* If there is any text to print, print it. */ 261 if (i != pl_index) 262 terminal_put_text (printed_line + i); 263 264 /* If the printed text didn't extend all the way to the edge 265 of the window, and text was appearing between here and the 266 edge of the window, clear from here to the end of the line. */
|
245 if ((pl_index < win->width && pl_index < entry->textlen) || 246 (entry->inverse))
| 267 if ((pl_index < win->width + pl_ignore 268 && pl_index < entry->textlen) 269 || (entry->inverse))
|
247 terminal_clear_to_eol (); 248 249 fflush (stdout); 250 251 /* Update the display text buffer. */
| 270 terminal_clear_to_eol (); 271 272 fflush (stdout); 273 274 /* Update the display text buffer. */
|
| 275 if (strlen (printed_line) > screenwidth) 276 /* printed_line[] can include more than screenwidth 277 characters if we are under -R and there are escape 278 sequences in it. However, entry->text was 279 allocated (in display_initialize_display) for 280 screenwidth characters only. */ 281 entry->text = xrealloc (entry->text, strlen (printed_line)+1);
|
252 strcpy (entry->text + i, printed_line + i); 253 entry->textlen = pl_index; 254 255 /* Lines showing node text are not in inverse. Only modelines 256 have that distinction. */ 257 entry->inverse = 0; 258 } 259 260 /* We have done at least one line. Increment our screen line 261 index, and check against the bottom of the window. */ 262 if (++line_index == win->height) 263 break; 264 265 /* A line has been displayed, and the screen reflects that state. 266 If there is typeahead pending, then let that typeahead be read 267 now, instead of continuing with the display. */ 268 if (info_any_buffered_input_p ()) 269 { 270 free (printed_line); 271 display_was_interrupted_p = 1; 272 return; 273 } 274 275 /* Reset PL_INDEX to the start of the line. */ 276 pl_index = 0;
| 282 strcpy (entry->text + i, printed_line + i); 283 entry->textlen = pl_index; 284 285 /* Lines showing node text are not in inverse. Only modelines 286 have that distinction. */ 287 entry->inverse = 0; 288 } 289 290 /* We have done at least one line. Increment our screen line 291 index, and check against the bottom of the window. */ 292 if (++line_index == win->height) 293 break; 294 295 /* A line has been displayed, and the screen reflects that state. 296 If there is typeahead pending, then let that typeahead be read 297 now, instead of continuing with the display. */ 298 if (info_any_buffered_input_p ()) 299 { 300 free (printed_line); 301 display_was_interrupted_p = 1; 302 return; 303 } 304 305 /* Reset PL_INDEX to the start of the line. */ 306 pl_index = 0;
|
| 307 pl_ignore = 0; /* this is computed per line */
|
277 278 /* If there are characters from REP left to print, stuff them 279 into the buffer now. */ 280 if (rep_carried_over) 281 for (; rep[pl_index]; pl_index++) 282 printed_line[pl_index] = rep[pl_index]; 283 284 /* If this window has chosen not to wrap lines, skip to the end 285 of the physical line in the buffer, and start a new line here. */ 286 if (pl_index && (win->flags & W_NoWrap)) 287 { 288 char *begin; 289 290 pl_index = 0; 291 printed_line[0] = '\0'; 292 293 begin = nodetext; 294 295 while ((nodetext < last_node_char) && (*nodetext != '\n')) 296 nodetext++; 297 } 298 } 299 } 300 301 done_with_node_display: 302 /* We have reached the end of the node or the end of the window. If it 303 is the end of the node, then clear the lines of the window from here 304 to the end of the window. */ 305 for (; line_index < win->height; line_index++) 306 { 307 DISPLAY_LINE *entry = display[line_index + win->first_row]; 308 309 /* If this line has text on it then make it go away. */ 310 if (entry && entry->textlen) 311 { 312 entry->textlen = 0; 313 entry->text[0] = '\0'; 314 315 terminal_goto_xy (0, line_index + win->first_row); 316 terminal_clear_to_eol (); 317 } 318 } 319 320 /* Finally, if this window has a modeline it might need to be redisplayed. 321 Check the window's modeline against the one in the display, and update 322 if necessary. */ 323 if ((win->flags & W_InhibitMode) == 0) 324 { 325 window_make_modeline (win); 326 line_index = win->first_row + win->height; 327 328 /* This display line must both be in inverse, and have the same 329 contents. */ 330 if ((!display[line_index]->inverse) || 331 (strcmp (display[line_index]->text, win->modeline) != 0)) 332 { 333 terminal_goto_xy (0, line_index); 334 terminal_begin_inverse (); 335 terminal_put_text (win->modeline); 336 terminal_end_inverse (); 337 strcpy (display[line_index]->text, win->modeline); 338 display[line_index]->inverse = 1; 339 display[line_index]->textlen = strlen (win->modeline); 340 fflush (stdout); 341 } 342 } 343 344 /* Okay, this window doesn't need updating anymore. */ 345 win->flags &= ~W_UpdateWindow; 346 free (printed_line); 347 fflush (stdout); 348} 349 350/* Scroll the region of the_display starting at START, ending at END, and 351 moving the lines AMOUNT lines. If AMOUNT is less than zero, the lines 352 are moved up in the screen, otherwise down. Actually, it is possible 353 for no scrolling to take place in the case that the terminal doesn't 354 support it. This doesn't matter to us. */ 355void 356display_scroll_display (start, end, amount) 357 int start, end, amount; 358{ 359 register int i, last; 360 DISPLAY_LINE *temp; 361 362 /* If this terminal cannot do scrolling, give up now. */ 363 if (!terminal_can_scroll) 364 return; 365 366 /* If there isn't anything displayed on the screen because it is too 367 small, quit now. */ 368 if (!the_display[0]) 369 return; 370 371 /* If there is typeahead pending, then don't actually do any scrolling. */ 372 if (info_any_buffered_input_p ()) 373 return; 374 375 /* Do it on the screen. */ 376 terminal_scroll_terminal (start, end, amount); 377 378 /* Now do it in the display buffer so our contents match the screen. */ 379 if (amount > 0) 380 { 381 last = end + amount; 382 383 /* Shift the lines to scroll right into place. */ 384 for (i = 0; i < (end - start); i++) 385 { 386 temp = the_display[last - i]; 387 the_display[last - i] = the_display[end - i]; 388 the_display[end - i] = temp; 389 } 390 391 /* The lines have been shifted down in the buffer. Clear all of the 392 lines that were vacated. */ 393 for (i = start; i != (start + amount); i++) 394 { 395 the_display[i]->text[0] = '\0'; 396 the_display[i]->textlen = 0; 397 the_display[i]->inverse = 0; 398 } 399 } 400 401 if (amount < 0) 402 { 403 last = start + amount; 404 for (i = 0; i < (end - start); i++) 405 { 406 temp = the_display[last + i]; 407 the_display[last + i] = the_display[start + i]; 408 the_display[start + i] = temp; 409 } 410 411 /* The lines have been shifted up in the buffer. Clear all of the 412 lines that are left over. */ 413 for (i = end + amount; i != end; i++) 414 { 415 the_display[i]->text[0] = '\0'; 416 the_display[i]->textlen = 0; 417 the_display[i]->inverse = 0; 418 } 419 } 420} 421 422/* Try to scroll lines in WINDOW. OLD_PAGETOP is the pagetop of WINDOW before 423 having had its line starts recalculated. OLD_STARTS is the list of line 424 starts that used to appear in this window. OLD_COUNT is the number of lines 425 that appear in the OLD_STARTS array. */ 426void 427display_scroll_line_starts (window, old_pagetop, old_starts, old_count) 428 WINDOW *window; 429 int old_pagetop, old_count; 430 char **old_starts; 431{ 432 register int i, old, new; /* Indices into the line starts arrays. */ 433 int last_new, last_old; /* Index of the last visible line. */ 434 int old_first, new_first; /* Index of the first changed line. */ 435 int unchanged_at_top = 0; 436 int already_scrolled = 0; 437 438 /* Locate the first line which was displayed on the old window. */ 439 old_first = old_pagetop; 440 new_first = window->pagetop; 441 442 /* Find the last line currently visible in this window. */ 443 last_new = window->pagetop + (window->height - 1); 444 if (last_new > window->line_count) 445 last_new = window->line_count - 1; 446 447 /* Find the last line which used to be currently visible in this window. */ 448 last_old = old_pagetop + (window->height - 1); 449 if (last_old > old_count) 450 last_old = old_count - 1; 451 452 for (old = old_first, new = new_first; 453 old < last_old && new < last_new; 454 old++, new++) 455 if (old_starts[old] != window->line_starts[new]) 456 break; 457 else 458 unchanged_at_top++; 459 460 /* Loop through the old lines looking for a match in the new lines. */ 461 for (old = old_first + unchanged_at_top; old < last_old; old++) 462 { 463 for (new = new_first; new < last_new; new++) 464 if (old_starts[old] == window->line_starts[new]) 465 { 466 /* Find the extent of the matching lines. */ 467 for (i = 0; (old + i) < last_old; i++) 468 if (old_starts[old + i] != window->line_starts[new + i]) 469 break; 470 471 /* Scroll these lines if there are enough of them. */ 472 { 473 int start, end, amount; 474 475 start = (window->first_row 476 + ((old + already_scrolled) - old_pagetop)); 477 amount = new - (old + already_scrolled); 478 end = window->first_row + window->height; 479 480 /* If we are shifting the block of lines down, then the last 481 AMOUNT lines will become invisible. Thus, don't bother 482 scrolling them. */ 483 if (amount > 0) 484 end -= amount; 485 486 if ((end - start) > 0) 487 { 488 display_scroll_display (start, end, amount); 489 490 /* Some lines have been scrolled. Simulate the scrolling 491 by offsetting the value of the old index. */ 492 old += i; 493 already_scrolled += amount; 494 } 495 } 496 } 497 } 498} 499 500/* Move the screen cursor to directly over the current character in WINDOW. */ 501void 502display_cursor_at_point (window) 503 WINDOW *window; 504{ 505 int vpos, hpos; 506 507 vpos = window_line_of_point (window) - window->pagetop + window->first_row; 508 hpos = window_get_cursor_column (window); 509 terminal_goto_xy (hpos, vpos); 510 fflush (stdout); 511} 512 513/* **************************************************************** */ 514/* */ 515/* Functions Static to this File */ 516/* */ 517/* **************************************************************** */ 518 519/* Make a DISPLAY_LINE ** with width and height. */ 520static DISPLAY_LINE ** 521make_display (width, height) 522 int width, height; 523{ 524 register int i; 525 DISPLAY_LINE **display; 526 527 display = (DISPLAY_LINE **)xmalloc ((1 + height) * sizeof (DISPLAY_LINE *)); 528 529 for (i = 0; i < height; i++) 530 { 531 display[i] = (DISPLAY_LINE *)xmalloc (sizeof (DISPLAY_LINE)); 532 display[i]->text = (char *)xmalloc (1 + width); 533 display[i]->textlen = 0; 534 display[i]->inverse = 0; 535 } 536 display[i] = (DISPLAY_LINE *)NULL; 537 return (display); 538} 539 540/* Free the storage allocated to DISPLAY. */ 541static void 542free_display (display) 543 DISPLAY_LINE **display; 544{ 545 register int i; 546 register DISPLAY_LINE *display_line; 547 548 if (!display) 549 return; 550 551 for (i = 0; (display_line = display[i]); i++) 552 { 553 free (display_line->text); 554 free (display_line); 555 } 556 free (display); 557}
| 308 309 /* If there are characters from REP left to print, stuff them 310 into the buffer now. */ 311 if (rep_carried_over) 312 for (; rep[pl_index]; pl_index++) 313 printed_line[pl_index] = rep[pl_index]; 314 315 /* If this window has chosen not to wrap lines, skip to the end 316 of the physical line in the buffer, and start a new line here. */ 317 if (pl_index && (win->flags & W_NoWrap)) 318 { 319 char *begin; 320 321 pl_index = 0; 322 printed_line[0] = '\0'; 323 324 begin = nodetext; 325 326 while ((nodetext < last_node_char) && (*nodetext != '\n')) 327 nodetext++; 328 } 329 } 330 } 331 332 done_with_node_display: 333 /* We have reached the end of the node or the end of the window. If it 334 is the end of the node, then clear the lines of the window from here 335 to the end of the window. */ 336 for (; line_index < win->height; line_index++) 337 { 338 DISPLAY_LINE *entry = display[line_index + win->first_row]; 339 340 /* If this line has text on it then make it go away. */ 341 if (entry && entry->textlen) 342 { 343 entry->textlen = 0; 344 entry->text[0] = '\0'; 345 346 terminal_goto_xy (0, line_index + win->first_row); 347 terminal_clear_to_eol (); 348 } 349 } 350 351 /* Finally, if this window has a modeline it might need to be redisplayed. 352 Check the window's modeline against the one in the display, and update 353 if necessary. */ 354 if ((win->flags & W_InhibitMode) == 0) 355 { 356 window_make_modeline (win); 357 line_index = win->first_row + win->height; 358 359 /* This display line must both be in inverse, and have the same 360 contents. */ 361 if ((!display[line_index]->inverse) || 362 (strcmp (display[line_index]->text, win->modeline) != 0)) 363 { 364 terminal_goto_xy (0, line_index); 365 terminal_begin_inverse (); 366 terminal_put_text (win->modeline); 367 terminal_end_inverse (); 368 strcpy (display[line_index]->text, win->modeline); 369 display[line_index]->inverse = 1; 370 display[line_index]->textlen = strlen (win->modeline); 371 fflush (stdout); 372 } 373 } 374 375 /* Okay, this window doesn't need updating anymore. */ 376 win->flags &= ~W_UpdateWindow; 377 free (printed_line); 378 fflush (stdout); 379} 380 381/* Scroll the region of the_display starting at START, ending at END, and 382 moving the lines AMOUNT lines. If AMOUNT is less than zero, the lines 383 are moved up in the screen, otherwise down. Actually, it is possible 384 for no scrolling to take place in the case that the terminal doesn't 385 support it. This doesn't matter to us. */ 386void 387display_scroll_display (start, end, amount) 388 int start, end, amount; 389{ 390 register int i, last; 391 DISPLAY_LINE *temp; 392 393 /* If this terminal cannot do scrolling, give up now. */ 394 if (!terminal_can_scroll) 395 return; 396 397 /* If there isn't anything displayed on the screen because it is too 398 small, quit now. */ 399 if (!the_display[0]) 400 return; 401 402 /* If there is typeahead pending, then don't actually do any scrolling. */ 403 if (info_any_buffered_input_p ()) 404 return; 405 406 /* Do it on the screen. */ 407 terminal_scroll_terminal (start, end, amount); 408 409 /* Now do it in the display buffer so our contents match the screen. */ 410 if (amount > 0) 411 { 412 last = end + amount; 413 414 /* Shift the lines to scroll right into place. */ 415 for (i = 0; i < (end - start); i++) 416 { 417 temp = the_display[last - i]; 418 the_display[last - i] = the_display[end - i]; 419 the_display[end - i] = temp; 420 } 421 422 /* The lines have been shifted down in the buffer. Clear all of the 423 lines that were vacated. */ 424 for (i = start; i != (start + amount); i++) 425 { 426 the_display[i]->text[0] = '\0'; 427 the_display[i]->textlen = 0; 428 the_display[i]->inverse = 0; 429 } 430 } 431 432 if (amount < 0) 433 { 434 last = start + amount; 435 for (i = 0; i < (end - start); i++) 436 { 437 temp = the_display[last + i]; 438 the_display[last + i] = the_display[start + i]; 439 the_display[start + i] = temp; 440 } 441 442 /* The lines have been shifted up in the buffer. Clear all of the 443 lines that are left over. */ 444 for (i = end + amount; i != end; i++) 445 { 446 the_display[i]->text[0] = '\0'; 447 the_display[i]->textlen = 0; 448 the_display[i]->inverse = 0; 449 } 450 } 451} 452 453/* Try to scroll lines in WINDOW. OLD_PAGETOP is the pagetop of WINDOW before 454 having had its line starts recalculated. OLD_STARTS is the list of line 455 starts that used to appear in this window. OLD_COUNT is the number of lines 456 that appear in the OLD_STARTS array. */ 457void 458display_scroll_line_starts (window, old_pagetop, old_starts, old_count) 459 WINDOW *window; 460 int old_pagetop, old_count; 461 char **old_starts; 462{ 463 register int i, old, new; /* Indices into the line starts arrays. */ 464 int last_new, last_old; /* Index of the last visible line. */ 465 int old_first, new_first; /* Index of the first changed line. */ 466 int unchanged_at_top = 0; 467 int already_scrolled = 0; 468 469 /* Locate the first line which was displayed on the old window. */ 470 old_first = old_pagetop; 471 new_first = window->pagetop; 472 473 /* Find the last line currently visible in this window. */ 474 last_new = window->pagetop + (window->height - 1); 475 if (last_new > window->line_count) 476 last_new = window->line_count - 1; 477 478 /* Find the last line which used to be currently visible in this window. */ 479 last_old = old_pagetop + (window->height - 1); 480 if (last_old > old_count) 481 last_old = old_count - 1; 482 483 for (old = old_first, new = new_first; 484 old < last_old && new < last_new; 485 old++, new++) 486 if (old_starts[old] != window->line_starts[new]) 487 break; 488 else 489 unchanged_at_top++; 490 491 /* Loop through the old lines looking for a match in the new lines. */ 492 for (old = old_first + unchanged_at_top; old < last_old; old++) 493 { 494 for (new = new_first; new < last_new; new++) 495 if (old_starts[old] == window->line_starts[new]) 496 { 497 /* Find the extent of the matching lines. */ 498 for (i = 0; (old + i) < last_old; i++) 499 if (old_starts[old + i] != window->line_starts[new + i]) 500 break; 501 502 /* Scroll these lines if there are enough of them. */ 503 { 504 int start, end, amount; 505 506 start = (window->first_row 507 + ((old + already_scrolled) - old_pagetop)); 508 amount = new - (old + already_scrolled); 509 end = window->first_row + window->height; 510 511 /* If we are shifting the block of lines down, then the last 512 AMOUNT lines will become invisible. Thus, don't bother 513 scrolling them. */ 514 if (amount > 0) 515 end -= amount; 516 517 if ((end - start) > 0) 518 { 519 display_scroll_display (start, end, amount); 520 521 /* Some lines have been scrolled. Simulate the scrolling 522 by offsetting the value of the old index. */ 523 old += i; 524 already_scrolled += amount; 525 } 526 } 527 } 528 } 529} 530 531/* Move the screen cursor to directly over the current character in WINDOW. */ 532void 533display_cursor_at_point (window) 534 WINDOW *window; 535{ 536 int vpos, hpos; 537 538 vpos = window_line_of_point (window) - window->pagetop + window->first_row; 539 hpos = window_get_cursor_column (window); 540 terminal_goto_xy (hpos, vpos); 541 fflush (stdout); 542} 543 544/* **************************************************************** */ 545/* */ 546/* Functions Static to this File */ 547/* */ 548/* **************************************************************** */ 549 550/* Make a DISPLAY_LINE ** with width and height. */ 551static DISPLAY_LINE ** 552make_display (width, height) 553 int width, height; 554{ 555 register int i; 556 DISPLAY_LINE **display; 557 558 display = (DISPLAY_LINE **)xmalloc ((1 + height) * sizeof (DISPLAY_LINE *)); 559 560 for (i = 0; i < height; i++) 561 { 562 display[i] = (DISPLAY_LINE *)xmalloc (sizeof (DISPLAY_LINE)); 563 display[i]->text = (char *)xmalloc (1 + width); 564 display[i]->textlen = 0; 565 display[i]->inverse = 0; 566 } 567 display[i] = (DISPLAY_LINE *)NULL; 568 return (display); 569} 570 571/* Free the storage allocated to DISPLAY. */ 572static void 573free_display (display) 574 DISPLAY_LINE **display; 575{ 576 register int i; 577 register DISPLAY_LINE *display_line; 578 579 if (!display) 580 return; 581 582 for (i = 0; (display_line = display[i]); i++) 583 { 584 free (display_line->text); 585 free (display_line); 586 } 587 free (display); 588}
|