diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/dispextern.h | 2245 | ||||
| -rw-r--r-- | src/dispnew.c | 5740 | ||||
| -rw-r--r-- | src/xdisp.c | 12553 |
3 files changed, 16028 insertions, 4510 deletions
diff --git a/src/dispextern.h b/src/dispextern.h index a6b4e3856f7..f848194d201 100644 --- a/src/dispextern.h +++ b/src/dispextern.h | |||
| @@ -1,5 +1,6 @@ | |||
| 1 | /* Interface definitions for display code. | 1 | /* Interface definitions for display code. |
| 2 | Copyright (C) 1985, 1993, 1994 Free Software Foundation, Inc. | 2 | Copyright (C) 1985, 1993, 1994, 1997, 1998, 1999 |
| 3 | Free Software Foundation, Inc. | ||
| 3 | 4 | ||
| 4 | This file is part of GNU Emacs. | 5 | This file is part of GNU Emacs. |
| 5 | 6 | ||
| @@ -18,12 +19,10 @@ along with GNU Emacs; see the file COPYING. If not, write to | |||
| 18 | the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | 19 | the Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
| 19 | Boston, MA 02111-1307, USA. */ | 20 | Boston, MA 02111-1307, USA. */ |
| 20 | 21 | ||
| 21 | #ifndef _DISPEXTERN_H_ | 22 | /* New redisplay written by Gerd Moellmann <gerd@acm.org>. */ |
| 22 | #define _DISPEXTERN_H_ | ||
| 23 | 23 | ||
| 24 | /* Nonzero means last display completed and cursor is really at | 24 | #ifndef DISPEXTERN_H_INCLUDED |
| 25 | cursX, cursY. Zero means it was preempted. */ | 25 | #define DISPEXTERN_H_INCLUDED |
| 26 | extern int display_completed; | ||
| 27 | 26 | ||
| 28 | #ifdef HAVE_X_WINDOWS | 27 | #ifdef HAVE_X_WINDOWS |
| 29 | #include <X11/Xlib.h> | 28 | #include <X11/Xlib.h> |
| @@ -37,180 +36,2131 @@ extern int display_completed; | |||
| 37 | #include "w32gui.h" | 36 | #include "w32gui.h" |
| 38 | #endif | 37 | #endif |
| 39 | 38 | ||
| 40 | #ifdef HAVE_FACES | 39 | |
| 40 | /* Structure forward declarations. Some are here because function | ||
| 41 | prototypes below reference structure types before their definition | ||
| 42 | in this file. Some are here because not every file including | ||
| 43 | dispextern.h also includes frame.h and windows.h. */ | ||
| 44 | |||
| 45 | struct glyph; | ||
| 46 | struct glyph_row; | ||
| 47 | struct glyph_matrix; | ||
| 48 | struct glyph_pool; | ||
| 49 | struct frame; | ||
| 50 | struct window; | ||
| 51 | |||
| 52 | |||
| 53 | |||
| 54 | /*********************************************************************** | ||
| 55 | Configuration | ||
| 56 | ***********************************************************************/ | ||
| 57 | |||
| 58 | /* If NO_PROMPT_IN_BUFFER is zero or undefined (default), prompts are | ||
| 59 | inserted into minibuffers as read-only text. Otherwise, the | ||
| 60 | behavior of Emacs 20.2 is restored. Define this as part of CFLAGS | ||
| 61 | because dispextern.h is not included in every C source file | ||
| 62 | containing conditional code for it. */ | ||
| 63 | |||
| 64 | #if 0 | ||
| 65 | #define NO_PROMPT_IN_BUFFER 1 | ||
| 66 | #endif | ||
| 67 | |||
| 68 | |||
| 69 | |||
| 70 | /*********************************************************************** | ||
| 71 | Debugging | ||
| 72 | ***********************************************************************/ | ||
| 73 | |||
| 74 | /* If GLYPH_DEBUG is non-zero, additional checks are activated. Turn | ||
| 75 | it off by defining the macro GLYPH_DEBUG to zero. */ | ||
| 76 | |||
| 77 | #ifndef GLYPH_DEBUG | ||
| 78 | #define GLYPH_DEBUG 0 | ||
| 79 | #endif | ||
| 80 | |||
| 81 | /* Macros to include code only if GLYPH_DEBUG != 0. */ | ||
| 82 | |||
| 83 | #if GLYPH_DEBUG | ||
| 84 | #define IF_DEBUG(X) X | ||
| 85 | #define xassert(X) if (!(X)) abort (); else (void) 0 | ||
| 86 | #else | ||
| 87 | #define IF_DEBUG(X) (void) 0 | ||
| 88 | #define xassert(X) (void) 0 | ||
| 89 | #endif | ||
| 90 | |||
| 91 | /* Macro for displaying traces of redisplay. If Emacs was compiled | ||
| 92 | with GLYPH_DEBUG != 0, the variable trace_redisplay_p can be set to | ||
| 93 | a non-zero value in debugging sessions to activate traces. */ | ||
| 94 | |||
| 95 | #if GLYPH_DEBUG | ||
| 96 | |||
| 97 | extern int trace_redisplay_p; | ||
| 98 | #include <stdio.h> | ||
| 99 | |||
| 100 | #define TRACE(X) \ | ||
| 101 | if (trace_redisplay_p) \ | ||
| 102 | fprintf X; \ | ||
| 103 | else \ | ||
| 104 | (void) 0 | ||
| 105 | |||
| 106 | #else /* GLYPH_DEBUG == 0 */ | ||
| 107 | |||
| 108 | #define TRACE(X) (void) 0 | ||
| 109 | |||
| 110 | #endif /* GLYPH_DEBUG == 0 */ | ||
| 111 | |||
| 112 | |||
| 113 | |||
| 114 | /*********************************************************************** | ||
| 115 | Text positions | ||
| 116 | ***********************************************************************/ | ||
| 117 | |||
| 118 | /* Starting with Emacs 20.3, characters from strings and buffers have | ||
| 119 | both a character and a byte position associated with them. The | ||
| 120 | following structure holds such a pair of positions. */ | ||
| 121 | |||
| 122 | struct text_pos | ||
| 123 | { | ||
| 124 | /* Character position. */ | ||
| 125 | int charpos; | ||
| 126 | |||
| 127 | /* Corresponding byte position. */ | ||
| 128 | int bytepos; | ||
| 129 | }; | ||
| 130 | |||
| 131 | /* Access character and byte position of POS in a functional form. */ | ||
| 132 | |||
| 133 | #define BYTEPOS(POS) (POS).bytepos | ||
| 134 | #define CHARPOS(POS) (POS).charpos | ||
| 135 | |||
| 136 | /* Set character position of POS to CHARPOS, byte position to BYTEPOS. */ | ||
| 137 | |||
| 138 | #define SET_TEXT_POS(POS, CHARPOS, BYTEPOS) \ | ||
| 139 | ((POS).charpos = (CHARPOS), (POS).bytepos = BYTEPOS) | ||
| 140 | |||
| 141 | /* Increment text position POS. */ | ||
| 142 | |||
| 143 | #define INC_TEXT_POS(POS) \ | ||
| 144 | do \ | ||
| 145 | { \ | ||
| 146 | ++(POS).charpos; \ | ||
| 147 | INC_POS ((POS).bytepos); \ | ||
| 148 | } \ | ||
| 149 | while (0) | ||
| 150 | |||
| 151 | /* Decrement text position POS. */ | ||
| 152 | |||
| 153 | #define DEC_TEXT_POS(POS) \ | ||
| 154 | do \ | ||
| 155 | { \ | ||
| 156 | --(POS).charpos; \ | ||
| 157 | DEC_POS ((POS).bytepos); \ | ||
| 158 | } \ | ||
| 159 | while (0) | ||
| 160 | |||
| 161 | /* Set text position POS from marker MARKER. */ | ||
| 162 | |||
| 163 | #define SET_TEXT_POS_FROM_MARKER(POS, MARKER) \ | ||
| 164 | (CHARPOS (POS) = marker_position ((MARKER)), \ | ||
| 165 | BYTEPOS (POS) = marker_byte_position ((MARKER))) | ||
| 166 | |||
| 167 | /* Set marker MARKER from text position POS. */ | ||
| 168 | |||
| 169 | #define SET_MARKER_FROM_TEXT_POS(MARKER, POS) \ | ||
| 170 | set_marker_both ((MARKER), Qnil, CHARPOS ((POS)), BYTEPOS ((POS))) | ||
| 171 | |||
| 172 | /* Value is non-zero if character and byte positions of POS1 and POS2 | ||
| 173 | are equal. */ | ||
| 174 | |||
| 175 | #define TEXT_POS_EQUAL_P(POS1, POS2) \ | ||
| 176 | ((POS1).charpos == (POS2).charpos \ | ||
| 177 | && (POS1).bytepos == (POS2).bytepos) | ||
| 178 | |||
| 179 | /* When rendering glyphs, redisplay scans string or buffer text, | ||
| 180 | overlay strings in that text, and does display table or control | ||
| 181 | character translations. The following structure captures a | ||
| 182 | position taking all this into account. */ | ||
| 183 | |||
| 184 | struct display_pos | ||
| 185 | { | ||
| 186 | /* Buffer or string position. */ | ||
| 187 | struct text_pos pos; | ||
| 188 | |||
| 189 | /* If this is a position in an overlay string, overlay_string_index | ||
| 190 | is the index of that overlay string in the sequence of overlay | ||
| 191 | strings at `pos' in the order redisplay processes them. A value | ||
| 192 | < 0 means that this is not a position in an overlay string. */ | ||
| 193 | int overlay_string_index; | ||
| 194 | |||
| 195 | /* If this is a position in an overlay string, string_pos is the | ||
| 196 | position within that string. */ | ||
| 197 | struct text_pos string_pos; | ||
| 198 | |||
| 199 | /* If the character at the position above is a control character or | ||
| 200 | has a display table entry, dpvec_index is an index in the display | ||
| 201 | table or control character translation of that character. A | ||
| 202 | value < 0 means this is not a position in such a translation. */ | ||
| 203 | int dpvec_index; | ||
| 204 | }; | ||
| 205 | |||
| 206 | |||
| 207 | |||
| 208 | /*********************************************************************** | ||
| 209 | Glyphs | ||
| 210 | ***********************************************************************/ | ||
| 211 | |||
| 212 | /* Enumeration of glyph types. Glyph structures contain a type field | ||
| 213 | containing one of the enumerators defined here. */ | ||
| 214 | |||
| 215 | enum glyph_type | ||
| 216 | { | ||
| 217 | /* Glyph describes a character. */ | ||
| 218 | CHAR_GLYPH, | ||
| 219 | |||
| 220 | /* Glyph describes an image. */ | ||
| 221 | IMAGE_GLYPH, | ||
| 222 | |||
| 223 | /* Glyph is a space of fractional width and/or height. */ | ||
| 224 | STRETCH_GLYPH | ||
| 225 | }; | ||
| 226 | |||
| 227 | |||
| 228 | /* Glyphs. */ | ||
| 229 | |||
| 230 | struct glyph | ||
| 231 | { | ||
| 232 | /* Position from which this glyph was drawn. If `object' below is a | ||
| 233 | Lisp string, this is a position in that string. If it is a | ||
| 234 | buffer, this is a position in that buffer. A value of -1 | ||
| 235 | together with a null object means glyph is a truncation glyph at | ||
| 236 | the start of a row. */ | ||
| 237 | int charpos; | ||
| 238 | |||
| 239 | /* Lisp object source of this glyph. Currently either a buffer or | ||
| 240 | a string, or 0. */ | ||
| 241 | Lisp_Object object; | ||
| 242 | |||
| 243 | /* Width in pixels. */ | ||
| 244 | short pixel_width; | ||
| 245 | |||
| 246 | /* Vertical offset. If < 0, the glyph is displayed raised, if > 0 | ||
| 247 | the glyph is displayed lowered. */ | ||
| 248 | short voffset; | ||
| 249 | |||
| 250 | /* Which kind of glyph this is---character, image etc. Value | ||
| 251 | should be an enumerator of type enum glyph_type. */ | ||
| 252 | unsigned type : 2; | ||
| 253 | |||
| 254 | /* 1 means this glyph was produced from multibyte text. Zero | ||
| 255 | means it was produced from unibyte text, i.e. charsets aren't | ||
| 256 | applicable, and encoding is not performed. */ | ||
| 257 | unsigned multibyte_p : 1; | ||
| 258 | |||
| 259 | /* Non-zero means draw a box line at the left or right side of this | ||
| 260 | glyph. This is part of the implementation of the face attribute | ||
| 261 | `:box'. */ | ||
| 262 | unsigned left_box_line_p : 1; | ||
| 263 | unsigned right_box_line_p : 1; | ||
| 264 | |||
| 265 | /* A union of sub-structures for different glyph types. */ | ||
| 266 | union | ||
| 267 | { | ||
| 268 | /* Sub-structure for character glyphs (type == CHAR_GLYPH). */ | ||
| 269 | struct | ||
| 270 | { | ||
| 271 | /* Character code. */ | ||
| 272 | unsigned code : 19; | ||
| 273 | |||
| 274 | /* Character's face. */ | ||
| 275 | unsigned face_id : 11; | ||
| 276 | |||
| 277 | /* 1 means glyph is a padding glyph. Padding glyphs are used | ||
| 278 | for characters whose visual shape consists of more than one | ||
| 279 | glyph (e.g. Asian characters). All but the first glyph of | ||
| 280 | such a glyph sequence have the padding_p flag set. Only used | ||
| 281 | for terminal frames, and there only to minimize code changes. | ||
| 282 | A better way would probably be to use the width field of | ||
| 283 | glyphs to express padding. */ | ||
| 284 | unsigned padding_p : 1; | ||
| 285 | } | ||
| 286 | ch; | ||
| 287 | |||
| 288 | /* Sub-structure for image glyphs (type == IMAGE_GLYPH). */ | ||
| 289 | struct | ||
| 290 | { | ||
| 291 | /* Image id. */ | ||
| 292 | unsigned id : 20; | ||
| 293 | |||
| 294 | /* Face under the image. */ | ||
| 295 | unsigned face_id : 12; | ||
| 296 | } | ||
| 297 | img; | ||
| 298 | |||
| 299 | /* Sub-structure for type == STRETCH_GLYPH. */ | ||
| 300 | struct | ||
| 301 | { | ||
| 302 | /* The height of the glyph. */ | ||
| 303 | unsigned height : 11; | ||
| 304 | |||
| 305 | /* The ascent of the glyph. */ | ||
| 306 | unsigned ascent : 10; | ||
| 307 | |||
| 308 | /* The face of the stretch glyph. */ | ||
| 309 | unsigned face_id : 11; | ||
| 310 | } | ||
| 311 | stretch; | ||
| 312 | |||
| 313 | /* Used to compare all bit-fields above in one step. */ | ||
| 314 | unsigned val; | ||
| 315 | } u; | ||
| 316 | }; | ||
| 317 | |||
| 318 | |||
| 319 | /* Is GLYPH a space? */ | ||
| 320 | |||
| 321 | #define CHAR_GLYPH_SPACE_P(GLYPH) \ | ||
| 322 | (GLYPH_FROM_CHAR_GLYPH ((GLYPH)) == SPACEGLYPH) | ||
| 323 | |||
| 324 | /* Are glyphs *X and *Y equal? */ | ||
| 325 | |||
| 326 | #define GLYPH_EQUAL_P(X, Y) \ | ||
| 327 | ((X)->type == (Y)->type \ | ||
| 328 | && (X)->u.val == (Y)->u.val \ | ||
| 329 | && (X)->left_box_line_p == (Y)->left_box_line_p \ | ||
| 330 | && (X)->right_box_line_p == (Y)->right_box_line_p \ | ||
| 331 | && (X)->voffset == (Y)->voffset) | ||
| 332 | |||
| 333 | /* Fill a character glyph GLYPH. CODE, FACE_ID, PADDING_P correspond | ||
| 334 | to the bits defined for the typedef `GLYPH' in lisp.h. */ | ||
| 335 | |||
| 336 | #define SET_CHAR_GLYPH(GLYPH, CODE, FACE_ID, PADDING_P) \ | ||
| 337 | do \ | ||
| 338 | { \ | ||
| 339 | (GLYPH).u.ch.code = (CODE); \ | ||
| 340 | (GLYPH).u.ch.face_id = (FACE_ID); \ | ||
| 341 | (GLYPH).u.ch.padding_p = (PADDING_P); \ | ||
| 342 | } \ | ||
| 343 | while (0) | ||
| 344 | |||
| 345 | /* Fill a character type glyph GLYPH from a glyph typedef FROM as | ||
| 346 | defined in lisp.h. */ | ||
| 347 | |||
| 348 | #define SET_CHAR_GLYPH_FROM_GLYPH(GLYPH, FROM) \ | ||
| 349 | SET_CHAR_GLYPH ((GLYPH), \ | ||
| 350 | FAST_GLYPH_CHAR ((FROM)), \ | ||
| 351 | FAST_GLYPH_FACE ((FROM)), \ | ||
| 352 | ((FROM) & GLYPH_MASK_PADDING) != 0) | ||
| 353 | |||
| 354 | /* Construct a typedef'd GLYPH value from a character glyph GLYPH. */ | ||
| 355 | |||
| 356 | #define GLYPH_FROM_CHAR_GLYPH(GLYPH) \ | ||
| 357 | ((GLYPH).u.ch.code \ | ||
| 358 | | ((GLYPH).u.ch.face_id << CHARACTERBITS) \ | ||
| 359 | | ((GLYPH).u.ch.padding_p ? GLYPH_MASK_PADDING : 0)) | ||
| 360 | |||
| 361 | /* Is GLYPH a padding glyph? */ | ||
| 362 | |||
| 363 | #define CHAR_GLYPH_PADDING_P(GLYPH) (GLYPH).u.ch.padding_p | ||
| 364 | |||
| 365 | |||
| 366 | |||
| 367 | |||
| 368 | /*********************************************************************** | ||
| 369 | Glyph Pools | ||
| 370 | ***********************************************************************/ | ||
| 371 | |||
| 372 | /* Glyph Pool. | ||
| 373 | |||
| 374 | Glyph memory for frame-based redisplay is allocated from the heap | ||
| 375 | in one vector kept in a glyph pool structure which is stored with | ||
| 376 | the frame. The size of the vector is made large enough to cover | ||
| 377 | all windows on the frame. | ||
| 378 | |||
| 379 | Both frame and window glyph matrices reference memory from a glyph | ||
| 380 | pool in frame-based redisplay. | ||
| 381 | |||
| 382 | In window-based redisplay, no glyphs pools exist; windows allocate | ||
| 383 | and free their glyph memory themselves. */ | ||
| 384 | |||
| 385 | struct glyph_pool | ||
| 386 | { | ||
| 387 | /* Vector of glyphs allocated from the heap. */ | ||
| 388 | struct glyph *glyphs; | ||
| 389 | |||
| 390 | /* Allocated size of `glyphs'. */ | ||
| 391 | int nglyphs; | ||
| 392 | |||
| 393 | /* Number of rows and columns in a matrix. */ | ||
| 394 | int nrows, ncolumns; | ||
| 395 | }; | ||
| 396 | |||
| 397 | |||
| 398 | |||
| 399 | /*********************************************************************** | ||
| 400 | Glyph Matrix | ||
| 401 | ***********************************************************************/ | ||
| 402 | |||
| 403 | /* Glyph Matrix. | ||
| 404 | |||
| 405 | Three kinds of glyph matrices exist: | ||
| 406 | |||
| 407 | 1. Frame glyph matrices. These are used for terminal frames whose | ||
| 408 | redisplay needs a view of the whole screen due to limited terminal | ||
| 409 | capabilities. Frame matrices are used only in the update phase | ||
| 410 | of redisplay. They are built in update_frame and not used after | ||
| 411 | the update has been performed. | ||
| 412 | |||
| 413 | 2. Window glyph matrices on frames having frame glyph matrices. | ||
| 414 | Such matrices are sub-matrices of their corresponding frame matrix, | ||
| 415 | i.e. frame glyph matrices and window glyph matrices share the same | ||
| 416 | glyph memory which is allocated in form of a glyph_pool structure. | ||
| 417 | Glyph rows in such a window matrix are slices of frame matrix rows. | ||
| 418 | |||
| 419 | 2. Free-standing window glyph matrices managing their own glyph | ||
| 420 | storage. This form is used in window-based redisplay which | ||
| 421 | includes variable width and height fonts etc. | ||
| 422 | |||
| 423 | The size of a window's row vector depends on the height of fonts | ||
| 424 | defined on its frame. It is chosen so that the vector is large | ||
| 425 | enough to describe all lines in a window when it is displayed in | ||
| 426 | the smallest possible character size. When new fonts are loaded, | ||
| 427 | or window sizes change, the row vector is adjusted accordingly. */ | ||
| 428 | |||
| 429 | struct glyph_matrix | ||
| 430 | { | ||
| 431 | /* The pool from which glyph memory is allocated, if any. This is | ||
| 432 | null for frame matrices and for window matrices managing their | ||
| 433 | own storage. */ | ||
| 434 | struct glyph_pool *pool; | ||
| 435 | |||
| 436 | /* Vector of glyph row structures. The row at nrows - 1 is reserved | ||
| 437 | for the mode line. */ | ||
| 438 | struct glyph_row *rows; | ||
| 439 | |||
| 440 | /* Number of elements allocated for the vector rows above. */ | ||
| 441 | int rows_allocated; | ||
| 442 | |||
| 443 | /* The number of rows used by the window if all lines were displayed | ||
| 444 | with the smallest possible character height. */ | ||
| 445 | int nrows; | ||
| 446 | |||
| 447 | /* Origin within the frame matrix if this is a window matrix on a | ||
| 448 | frame having a frame matrix. Both values are zero for | ||
| 449 | window-based redisplay. */ | ||
| 450 | int matrix_x, matrix_y; | ||
| 451 | |||
| 452 | /* Width and height of the matrix in columns and rows. */ | ||
| 453 | int matrix_w, matrix_h; | ||
| 454 | |||
| 455 | /* If this structure describes a window matrix, window_top_y is the | ||
| 456 | top-most y-position and window_height is the height of the | ||
| 457 | window, and window_vscroll is the vscroll at the time the matrix | ||
| 458 | was last adjusted. Only set for window-based redisplay. */ | ||
| 459 | int window_top_y, window_height, window_width, window_vscroll; | ||
| 460 | |||
| 461 | /* Number of glyphs reserved for left and right marginal areas when | ||
| 462 | the matrix was last adjusted. */ | ||
| 463 | int left_margin_glyphs, right_margin_glyphs; | ||
| 464 | |||
| 465 | /* Flag indicating that scrolling should not be tried in | ||
| 466 | update_window. This flag is set by functions like try_window_id | ||
| 467 | which do their own scrolling. */ | ||
| 468 | unsigned no_scrolling_p : 1; | ||
| 469 | |||
| 470 | /* Non-zero means window displayed in this matrix has a top mode | ||
| 471 | line. */ | ||
| 472 | unsigned top_line_p : 1; | ||
| 473 | |||
| 474 | #ifdef GLYPH_DEBUG | ||
| 475 | /* A string identifying the method used to display the matrix. */ | ||
| 476 | char method[512]; | ||
| 477 | #endif | ||
| 478 | }; | ||
| 479 | |||
| 480 | |||
| 481 | /* Check that glyph pointers stored in glyph rows of MATRIX are okay. | ||
| 482 | This aborts if any pointer is found twice. */ | ||
| 483 | |||
| 484 | #if GLYPH_DEBUG | ||
| 485 | void check_matrix_pointer_lossage P_ ((struct glyph_matrix *)); | ||
| 486 | #define CHECK_MATRIX(MATRIX) check_matrix_pointer_lossage ((MATRIX)) | ||
| 487 | #else | ||
| 488 | #define CHECK_MATRIX(MATRIX) (void) 0 | ||
| 489 | #endif | ||
| 490 | |||
| 491 | |||
| 492 | |||
| 493 | /*********************************************************************** | ||
| 494 | Glyph Rows | ||
| 495 | ***********************************************************************/ | ||
| 496 | |||
| 497 | /* Area in window glyph matrix. If values are added or removed, the | ||
| 498 | function mark_object in alloc.c has to be changed. */ | ||
| 499 | |||
| 500 | enum glyph_row_area | ||
| 501 | { | ||
| 502 | LEFT_MARGIN_AREA, | ||
| 503 | TEXT_AREA, | ||
| 504 | RIGHT_MARGIN_AREA, | ||
| 505 | LAST_AREA | ||
| 506 | }; | ||
| 507 | |||
| 508 | |||
| 509 | /* Rows of glyphs in a windows or frame glyph matrix. | ||
| 510 | |||
| 511 | Each row is partitioned into three areas. The start and end of | ||
| 512 | each area is recorded in a pointer as shown below. | ||
| 513 | |||
| 514 | +--------------------+-------------+---------------------+ | ||
| 515 | | left margin area | text area | right margin area | | ||
| 516 | +--------------------+-------------+---------------------+ | ||
| 517 | | | | | | ||
| 518 | glyphs[LEFT_MARGIN_AREA] glyphs[RIGHT_MARGIN_AREA] | ||
| 519 | | | | ||
| 520 | glyphs[TEXT_AREA] | | ||
| 521 | glyphs[LAST_AREA] | ||
| 522 | |||
| 523 | Rows in frame matrices reference glyph memory allocated in a frame | ||
| 524 | glyph pool (see the description of struct glyph_pool). Rows in | ||
| 525 | window matrices on frames having frame matrices reference slices of | ||
| 526 | the glyphs of corresponding rows in the frame matrix. | ||
| 527 | |||
| 528 | Rows in window matrices on frames having no frame matrices point to | ||
| 529 | glyphs allocated from the heap via xmalloc; | ||
| 530 | glyphs[LEFT_MARGIN_AREA] is the start address of the allocated | ||
| 531 | glyph structure array. */ | ||
| 532 | |||
| 533 | struct glyph_row | ||
| 534 | { | ||
| 535 | /* Pointers to beginnings of areas. The end of an area A is found at | ||
| 536 | A + 1 in the vector. The last element of the vector is the end | ||
| 537 | of the whole row. | ||
| 538 | |||
| 539 | Kludge alert: Even if used[TEXT_AREA] == 0, glyphs[TEXT_AREA][0]'s | ||
| 540 | position field is used. It is -1 if this row does not correspond | ||
| 541 | to any text; it is some buffer position if the row corresponds to | ||
| 542 | an empty display line that displays a line end. This is what old | ||
| 543 | redisplay used to do. (Except in code for terminal frames, this | ||
| 544 | kludge is no longer use, I believe. --gerd). | ||
| 545 | |||
| 546 | See also start, end, displays_text_p and ends_at_zv_p for cleaner | ||
| 547 | ways to do it. The special meaning of positions 0 and -1 will be | ||
| 548 | removed some day, so don't use it in new code. */ | ||
| 549 | struct glyph *glyphs[1 + LAST_AREA]; | ||
| 550 | |||
| 551 | /* Number of glyphs actually filled in areas. */ | ||
| 552 | short used[LAST_AREA]; | ||
| 553 | |||
| 554 | /* Window-relative x and y-position of the top-left corner of this | ||
| 555 | row. If y < 0, this means that abs (y) pixels of the row are | ||
| 556 | invisible because it is partially visible at the top of a window. | ||
| 557 | If x < 0, this means that abs (x) pixels of the first glyph of | ||
| 558 | the text area of the row are invisible because the glyph is | ||
| 559 | partially visible. */ | ||
| 560 | int x, y; | ||
| 561 | |||
| 562 | /* Width of the row in pixels without taking face extension at the | ||
| 563 | end of the row into account. */ | ||
| 564 | int pixel_width; | ||
| 565 | |||
| 566 | /* Height information. The value of ascent is zero and height is 1 | ||
| 567 | on terminal frames. */ | ||
| 568 | int ascent, height; | ||
| 569 | |||
| 570 | /* Portion of row that is visible. Partially visible rows may be | ||
| 571 | found at the top and bottom of a window. This is 1 for tty | ||
| 572 | frames. It may be < 0 in case of completely invisible rows. */ | ||
| 573 | int visible_height; | ||
| 574 | |||
| 575 | /* Hash code. This hash code is available as soon as the row | ||
| 576 | is constructed, i.e. after a call to display_line. */ | ||
| 577 | unsigned hash; | ||
| 578 | |||
| 579 | /* First position in this row. This is the text position, including | ||
| 580 | overlay position information etc, where the display of this row | ||
| 581 | started, and can thus be less the position of the first glyph | ||
| 582 | (e.g. due to invisible text or horizontal scrolling). */ | ||
| 583 | struct display_pos start; | ||
| 584 | |||
| 585 | /* Text position at the end of this row. This is the position after | ||
| 586 | the last glyph on this row. It can be greater than the last | ||
| 587 | glyph position + 1, due to truncation, invisible text etc. In an | ||
| 588 | up-to-date display, this should always be equal to the start | ||
| 589 | position of the next row. */ | ||
| 590 | struct display_pos end; | ||
| 591 | |||
| 592 | /* In a desired matrix, 1 means that this row must be updated. In a | ||
| 593 | current matrix, 0 means that the row has been invalidated, i.e. | ||
| 594 | the row's contents do not agree with what is visible on the | ||
| 595 | screen. */ | ||
| 596 | unsigned enabled_p : 1; | ||
| 597 | |||
| 598 | /* Display this line in inverse video? Used for the mode line and | ||
| 599 | menu bar lines. */ | ||
| 600 | unsigned inverse_p : 1; | ||
| 601 | |||
| 602 | /* 1 means row displays a text line that is truncated on the left or | ||
| 603 | right side. */ | ||
| 604 | unsigned truncated_on_left_p : 1; | ||
| 605 | unsigned truncated_on_right_p : 1; | ||
| 606 | |||
| 607 | /* 1 means the overlay arrow is on this line. */ | ||
| 608 | unsigned overlay_arrow_p : 1; | ||
| 609 | |||
| 610 | /* 1 means that this row displays a continued line, i.e. it has a | ||
| 611 | continuation mark at the right side. */ | ||
| 612 | unsigned continued_p : 1; | ||
| 613 | |||
| 614 | /* 0 means that this row does not contain any text, i.e. it is | ||
| 615 | a blank line at the window and buffer end. */ | ||
| 616 | unsigned displays_text_p : 1; | ||
| 617 | |||
| 618 | /* 1 means that this line ends at ZV. */ | ||
| 619 | unsigned ends_at_zv_p : 1; | ||
| 620 | |||
| 621 | /* 1 means the face of the last glyph in the text area is drawn to | ||
| 622 | the right end of the window. This flag is used in | ||
| 623 | update_text_area to optimize clearing to the end of the area. */ | ||
| 624 | unsigned fill_line_p : 1; | ||
| 625 | |||
| 626 | /* Non-zero means display a bitmap on X frames indicating that this | ||
| 627 | line contains no text and ends in ZV. */ | ||
| 628 | unsigned indicate_empty_line_p : 1; | ||
| 629 | |||
| 630 | /* 1 means this row contains glyphs that overlap each other because | ||
| 631 | of lbearing or rbearing. */ | ||
| 632 | unsigned contains_overlapping_glyphs_p : 1; | ||
| 633 | |||
| 634 | /* 1 means this row is a wide as the window it is displayed in, including | ||
| 635 | scroll bars, bitmap areas, and internal borders. This also | ||
| 636 | implies that the row doesn't have marginal areas. */ | ||
| 637 | unsigned full_width_p : 1; | ||
| 638 | |||
| 639 | /* if non-zero, and full_width_p is also non-zero, don't let | ||
| 640 | the row draw over the frame's internal border. */ | ||
| 641 | unsigned internal_border_p : 1; | ||
| 642 | |||
| 643 | /* Non-zero means row is a mode or top-line. */ | ||
| 644 | unsigned mode_line_p : 1; | ||
| 645 | |||
| 646 | /* Continuation lines width at the start of the row. */ | ||
| 647 | int continuation_lines_width; | ||
| 648 | }; | ||
| 649 | |||
| 650 | |||
| 651 | /* Get a pointer to row number ROW in matrix MATRIX. If GLYPH_DEBUG | ||
| 652 | is defined to a non-zero value, the function matrix_row checks that | ||
| 653 | we don't try to access rows that are out of bounds. */ | ||
| 654 | |||
| 655 | #if GLYPH_DEBUG | ||
| 656 | struct glyph_row *matrix_row P_ ((struct glyph_matrix *, int)); | ||
| 657 | #define MATRIX_ROW(MATRIX, ROW) matrix_row ((MATRIX), (ROW)) | ||
| 658 | #else | ||
| 659 | #define MATRIX_ROW(MATRIX, ROW) ((MATRIX)->rows + (ROW)) | ||
| 660 | #endif | ||
| 661 | |||
| 662 | /* Return a pointer to the row reserved for the mode line in MATRIX. | ||
| 663 | Row MATRIX->nrows - 1 is always reserved for the mode line. */ | ||
| 664 | |||
| 665 | #define MATRIX_MODE_LINE_ROW(MATRIX) \ | ||
| 666 | ((MATRIX)->rows + (MATRIX)->nrows - 1) | ||
| 667 | |||
| 668 | /* Return a pointer to the row reserved for the top line in MATRIX. | ||
| 669 | This is always the first row in MATRIX because that's the only | ||
| 670 | way that works in frame-based redisplay. */ | ||
| 671 | |||
| 672 | #define MATRIX_TOP_LINE_ROW(MATRIX) (MATRIX)->rows | ||
| 673 | |||
| 674 | /* Return a pointer to first row in MATRIX used for text display. */ | ||
| 675 | |||
| 676 | #define MATRIX_FIRST_TEXT_ROW(MATRIX) \ | ||
| 677 | ((MATRIX)->rows->mode_line_p ? (MATRIX)->rows + 1 : (MATRIX)->rows) | ||
| 678 | |||
| 679 | /* Return a pointer to the first glyph in the text area of a row. | ||
| 680 | MATRIX is the glyph matrix accessed, and ROW is the row index in | ||
| 681 | MATRIX. */ | ||
| 682 | |||
| 683 | #define MATRIX_ROW_GLYPH_START(MATRIX, ROW) \ | ||
| 684 | (MATRIX_ROW ((MATRIX), (ROW))->glyphs[TEXT_AREA]) | ||
| 685 | |||
| 686 | /* Return the number of used glyphs in the text area of a row. */ | ||
| 687 | |||
| 688 | #define MATRIX_ROW_USED(MATRIX, ROW) \ | ||
| 689 | (MATRIX_ROW ((MATRIX), (ROW))->used[TEXT_AREA]) | ||
| 690 | |||
| 691 | /* Return the character/ byte position at which the display of ROW | ||
| 692 | starts. */ | ||
| 693 | |||
| 694 | #define MATRIX_ROW_START_CHARPOS(ROW) ((ROW)->start.pos.charpos) | ||
| 695 | #define MATRIX_ROW_START_BYTEPOS(ROW) ((ROW)->start.pos.bytepos) | ||
| 696 | |||
| 697 | /* Return character/ byte position at which ROW ends. */ | ||
| 698 | |||
| 699 | #define MATRIX_ROW_END_CHARPOS(ROW) ((ROW)->end.pos.charpos) | ||
| 700 | #define MATRIX_ROW_END_BYTEPOS(ROW) ((ROW)->end.pos.bytepos) | ||
| 701 | |||
| 702 | /* Return the vertical position of ROW in MATRIX. */ | ||
| 703 | |||
| 704 | #define MATRIX_ROW_VPOS(ROW, MATRIX) ((ROW) - (MATRIX)->rows) | ||
| 705 | |||
| 706 | /* Return the last glyph row + 1 in MATRIX on window W reserved for | ||
| 707 | text. If W has a mode line, the last row in the matrix is reserved | ||
| 708 | for it. */ | ||
| 709 | |||
| 710 | #define MATRIX_BOTTOM_TEXT_ROW(MATRIX, W) \ | ||
| 711 | ((MATRIX)->rows \ | ||
| 712 | + (MATRIX)->nrows \ | ||
| 713 | - (WINDOW_WANTS_MODELINE_P ((W)) ? 1 : 0)) | ||
| 714 | |||
| 715 | /* Non-zero if the face of the last glyph in ROW's text area has | ||
| 716 | to be drawn to the end of the text area. */ | ||
| 717 | |||
| 718 | #define MATRIX_ROW_EXTENDS_FACE_P(ROW) ((ROW)->fill_line_p) | ||
| 719 | |||
| 720 | /* Set and query the enabled_p flag of glyph row ROW in MATRIX. */ | ||
| 721 | |||
| 722 | #define SET_MATRIX_ROW_ENABLED_P(MATRIX, ROW, VALUE) \ | ||
| 723 | (MATRIX_ROW ((MATRIX), (ROW))->enabled_p = (VALUE) != 0) | ||
| 724 | |||
| 725 | #define MATRIX_ROW_ENABLED_P(MATRIX, ROW) \ | ||
| 726 | (MATRIX_ROW ((MATRIX), (ROW))->enabled_p) | ||
| 727 | |||
| 728 | /* Non-zero if ROW displays text. Value is non-zero if the row is | ||
| 729 | blank but displays a line end. */ | ||
| 730 | |||
| 731 | #define MATRIX_ROW_DISPLAYS_TEXT_P(ROW) ((ROW)->displays_text_p) | ||
| 732 | |||
| 733 | /* Non-zero if ROW is not completely visible in window W. */ | ||
| 734 | |||
| 735 | #define MATRIX_ROW_PARTIALLY_VISIBLE_P(ROW) \ | ||
| 736 | ((ROW)->height != (ROW)->visible_height) | ||
| 737 | |||
| 738 | /* Non-zero if ROW is partially visible at the top of window W. */ | ||
| 739 | |||
| 740 | #define MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P(W, ROW) \ | ||
| 741 | (MATRIX_ROW_PARTIALLY_VISIBLE_P ((ROW)) \ | ||
| 742 | && (ROW)->y < WINDOW_DISPLAY_TOP_LINE_HEIGHT ((W))) | ||
| 743 | |||
| 744 | /* Non-zero if ROW is partially visible at the bottom of window W. */ | ||
| 745 | |||
| 746 | #define MATRIX_ROW_PARTIALLY_VISIBLE_AT_BOTTOM_P(W, ROW) \ | ||
| 747 | (MATRIX_ROW_PARTIALLY_VISIBLE_P ((ROW)) \ | ||
| 748 | && (ROW)->y + (ROW)->height > WINDOW_DISPLAY_HEIGHT_NO_MODE_LINE ((W))) | ||
| 749 | |||
| 750 | /* Return the bottom Y + 1 of ROW. */ | ||
| 751 | |||
| 752 | #define MATRIX_ROW_BOTTOM_Y(ROW) ((ROW)->y + (ROW)->height) | ||
| 753 | |||
| 754 | /* Is ROW the last visible one in the display described by the | ||
| 755 | iterator structure pointed to by IT?. */ | ||
| 756 | |||
| 757 | #define MATRIX_ROW_LAST_VISIBLE_P(ROW, IT) \ | ||
| 758 | (MATRIX_ROW_BOTTOM_Y ((ROW)) >= (IT)->last_visible_y) | ||
| 759 | |||
| 760 | /* Non-zero if ROW displays a continuation line. */ | ||
| 761 | |||
| 762 | #define MATRIX_ROW_CONTINUATION_LINE_P(ROW) \ | ||
| 763 | ((ROW)->continuation_lines_width > 0) | ||
| 764 | |||
| 765 | /* Non-zero if ROW ends in the middle of a character. This is the | ||
| 766 | case for continued lines showing only part of a display table entry | ||
| 767 | or a control char, or an overlay string. */ | ||
| 768 | |||
| 769 | #define MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P(ROW) \ | ||
| 770 | ((ROW)->end.dpvec_index >= 0 \ | ||
| 771 | || (ROW)->end.overlay_string_index >= 0) | ||
| 772 | |||
| 773 | /* Non-zero if ROW ends in the middle of an overlay string. */ | ||
| 774 | |||
| 775 | #define MATRIX_ROW_ENDS_IN_OVERLAY_STRING_P(ROW) \ | ||
| 776 | ((ROW)->end.overlay_string_index >= 0) | ||
| 777 | |||
| 778 | /* Non-zero if ROW starts in the middle of a character. See above. */ | ||
| 779 | |||
| 780 | #define MATRIX_ROW_STARTS_IN_MIDDLE_OF_CHAR_P(ROW) \ | ||
| 781 | ((ROW)->start.dpvec_index >= 0 \ | ||
| 782 | || ((ROW)->start.overlay_string_index >= 0 \ | ||
| 783 | && (ROW)->start.string_pos.charpos > 0)) | ||
| 784 | |||
| 785 | |||
| 786 | /* Non-zero means that fonts have been loaded since the last glyph | ||
| 787 | matrix adjustments. The function redisplay_internal adjusts glyph | ||
| 788 | matrices when this flag is non-zero. */ | ||
| 789 | |||
| 790 | extern int fonts_changed_p; | ||
| 791 | |||
| 792 | /* A glyph for a space. */ | ||
| 793 | |||
| 794 | extern struct glyph space_glyph; | ||
| 795 | |||
| 796 | /* Window being updated by update_window. This is non-null as long as | ||
| 797 | update_window has not finished, and null otherwise. It's role is | ||
| 798 | analogous to updating_frame. */ | ||
| 799 | |||
| 800 | extern struct window *updated_window; | ||
| 801 | |||
| 802 | /* Glyph row and area updated by update_window_line. */ | ||
| 803 | |||
| 804 | extern struct glyph_row *updated_row; | ||
| 805 | extern int updated_area; | ||
| 806 | |||
| 807 | /* Non-zero means reading single-character input with prompt so put | ||
| 808 | cursor on mini-buffer after the prompt. Positive means at end of | ||
| 809 | text in echo area; negative means at beginning of line. */ | ||
| 810 | |||
| 811 | extern int cursor_in_echo_area; | ||
| 812 | |||
| 813 | /* Non-zero means last display completed. Zero means it was | ||
| 814 | preempted. */ | ||
| 815 | |||
| 816 | extern int display_completed; | ||
| 817 | |||
| 818 | /* Non-zero means redisplay has been performed directly (see also | ||
| 819 | direct_output_for_insert and direct_output_forward_char), so that | ||
| 820 | no further updating has to be performed. The function | ||
| 821 | redisplay_internal checks this flag, and does nothing but reset it | ||
| 822 | to zero if it is non-zero. */ | ||
| 823 | |||
| 824 | extern int redisplay_performed_directly_p; | ||
| 825 | |||
| 826 | /* A temporary storage area, including a row of glyphs. Initialized | ||
| 827 | in xdisp.c. Used for various purposes, as an example see | ||
| 828 | direct_output_for_insert. */ | ||
| 829 | |||
| 830 | extern struct glyph_row scratch_glyph_row; | ||
| 831 | |||
| 832 | |||
| 833 | |||
| 834 | /************************************************************************ | ||
| 835 | Display Dimensions | ||
| 836 | ************************************************************************/ | ||
| 837 | |||
| 838 | /* Return the height of the mode line in glyph matrix MATRIX, or zero | ||
| 839 | if not known. This macro is called under circumstances where | ||
| 840 | MATRIX might not have been allocated yet. */ | ||
| 841 | |||
| 842 | #define MATRIX_MODE_LINE_HEIGHT(MATRIX) \ | ||
| 843 | ((MATRIX) && (MATRIX)->rows \ | ||
| 844 | ? MATRIX_MODE_LINE_ROW (MATRIX)->height \ | ||
| 845 | : 0) | ||
| 846 | |||
| 847 | /* Return the height of the top line in glyph matrix MATRIX, or zero | ||
| 848 | if not known. This macro is called under circumstances where | ||
| 849 | MATRIX might not have been allocated yet. */ | ||
| 850 | |||
| 851 | #define MATRIX_TOP_LINE_HEIGHT(MATRIX) \ | ||
| 852 | ((MATRIX) && (MATRIX)->rows \ | ||
| 853 | ? MATRIX_TOP_LINE_ROW (MATRIX)->height \ | ||
| 854 | : 0) | ||
| 855 | |||
| 856 | /* Return the current height of the mode line of window W. If not | ||
| 857 | known from W's current glyph matrix, return a default based on the | ||
| 858 | height of the font of the face `modeline'. */ | ||
| 859 | |||
| 860 | #define CURRENT_MODE_LINE_HEIGHT(W) \ | ||
| 861 | (MATRIX_MODE_LINE_HEIGHT ((W)->current_matrix) \ | ||
| 862 | ? MATRIX_MODE_LINE_HEIGHT ((W)->current_matrix) \ | ||
| 863 | : estimate_mode_line_height (XFRAME ((W)->frame), MODE_LINE_FACE_ID)) | ||
| 864 | |||
| 865 | /* Return the current height of the top line of window W. If not | ||
| 866 | known from W's current glyph matrix, return an estimation based on | ||
| 867 | the height of the font of the face `top-line'. */ | ||
| 868 | |||
| 869 | #define CURRENT_TOP_LINE_HEIGHT(W) \ | ||
| 870 | (MATRIX_TOP_LINE_HEIGHT ((W)->current_matrix) \ | ||
| 871 | ? MATRIX_TOP_LINE_HEIGHT ((W)->current_matrix) \ | ||
| 872 | : estimate_mode_line_height (XFRAME ((W)->frame), TOP_LINE_FACE_ID)) | ||
| 873 | |||
| 874 | /* Return the height of the desired mode line of window W. */ | ||
| 875 | |||
| 876 | #define DESIRED_MODE_LINE_HEIGHT(W) \ | ||
| 877 | MATRIX_MODE_LINE_HEIGHT ((W)->desired_matrix) | ||
| 878 | |||
| 879 | /* Return the height of the desired top line of window W. */ | ||
| 880 | |||
| 881 | #define DESIRED_TOP_LINE_HEIGHT(W) \ | ||
| 882 | MATRIX_TOP_LINE_HEIGHT ((W)->desired_matrix) | ||
| 883 | |||
| 884 | /* Like FRAME_INTERNAL_BORDER_WIDTH but checks whether frame F is a | ||
| 885 | window-system frame. */ | ||
| 886 | |||
| 887 | #define FRAME_INTERNAL_BORDER_WIDTH_SAFE(F) \ | ||
| 888 | (FRAME_WINDOW_P (F) ? FRAME_INTERNAL_BORDER_WIDTH (F) : 0) | ||
| 889 | |||
| 890 | /* Width of display region of window W. For terminal frames, this | ||
| 891 | equals the width of W since there are no vertical scroll bars. For | ||
| 892 | window system frames, the value has to be corrected by the pixel | ||
| 893 | width of vertical scroll bars, and bitmap areas. */ | ||
| 894 | |||
| 895 | #define WINDOW_DISPLAY_PIXEL_WIDTH(W) \ | ||
| 896 | (((XFASTINT ((W)->width) \ | ||
| 897 | - FRAME_SCROLL_BAR_WIDTH (XFRAME (WINDOW_FRAME ((W)))) \ | ||
| 898 | - 2 * FRAME_FLAGS_AREA_COLS (XFRAME (WINDOW_FRAME ((W))))) \ | ||
| 899 | * CANON_X_UNIT (XFRAME (WINDOW_FRAME ((W)))))) | ||
| 900 | |||
| 901 | /* Height of the display region of W, including a mode line, if any. */ | ||
| 902 | |||
| 903 | #define WINDOW_DISPLAY_PIXEL_HEIGHT(W) \ | ||
| 904 | (XFASTINT ((W)->height) \ | ||
| 905 | * CANON_Y_UNIT (XFRAME (WINDOW_FRAME ((W))))) | ||
| 906 | |||
| 907 | /* Height in pixels of the mode line. May be zero if W doesn't have a | ||
| 908 | mode line. */ | ||
| 909 | |||
| 910 | #define WINDOW_DISPLAY_MODE_LINE_HEIGHT(W) \ | ||
| 911 | (WINDOW_WANTS_MODELINE_P ((W)) \ | ||
| 912 | ? CURRENT_MODE_LINE_HEIGHT (W) \ | ||
| 913 | : 0) | ||
| 914 | |||
| 915 | /* Height in pixels of the top line. Zero if W doesn't have a top | ||
| 916 | line. */ | ||
| 917 | |||
| 918 | #define WINDOW_DISPLAY_TOP_LINE_HEIGHT(W) \ | ||
| 919 | (WINDOW_WANTS_TOP_LINE_P ((W)) \ | ||
| 920 | ? CURRENT_TOP_LINE_HEIGHT (W) \ | ||
| 921 | : 0) | ||
| 922 | |||
| 923 | /* Pixel height of window W without mode line. */ | ||
| 924 | |||
| 925 | #define WINDOW_DISPLAY_HEIGHT_NO_MODE_LINE(W) \ | ||
| 926 | (WINDOW_DISPLAY_PIXEL_HEIGHT ((W)) \ | ||
| 927 | - WINDOW_DISPLAY_MODE_LINE_HEIGHT ((W))) | ||
| 928 | |||
| 929 | /* Pixel height of window W without mode and top line. */ | ||
| 930 | |||
| 931 | #define WINDOW_DISPLAY_TEXT_HEIGHT(W) \ | ||
| 932 | (WINDOW_DISPLAY_PIXEL_HEIGHT ((W)) \ | ||
| 933 | - WINDOW_DISPLAY_MODE_LINE_HEIGHT ((W)) \ | ||
| 934 | - WINDOW_DISPLAY_TOP_LINE_HEIGHT ((W))) | ||
| 935 | |||
| 936 | /* Left edge of W in pixels relative to its frame. */ | ||
| 937 | |||
| 938 | #define WINDOW_DISPLAY_LEFT_EDGE_PIXEL_X(W) \ | ||
| 939 | (FRAME_INTERNAL_BORDER_WIDTH_SAFE (XFRAME (WINDOW_FRAME ((W)))) \ | ||
| 940 | + (WINDOW_LEFT_MARGIN ((W)) \ | ||
| 941 | * CANON_X_UNIT (XFRAME (WINDOW_FRAME ((W))))) \ | ||
| 942 | + FRAME_FLAGS_AREA_WIDTH (XFRAME (WINDOW_FRAME ((W))))) | ||
| 943 | |||
| 944 | /* Right edge of window W in pixels, relative to its frame. */ | ||
| 945 | |||
| 946 | #define WINDOW_DISPLAY_RIGHT_EDGE_PIXEL_X(W) \ | ||
| 947 | (WINDOW_DISPLAY_LEFT_EDGE_PIXEL_X ((W)) \ | ||
| 948 | + WINDOW_DISPLAY_PIXEL_WIDTH ((W))) | ||
| 949 | |||
| 950 | /* Top edge of W in pixels relative to its frame. */ | ||
| 951 | |||
| 952 | #define WINDOW_DISPLAY_TOP_EDGE_PIXEL_Y(W) \ | ||
| 953 | (FRAME_INTERNAL_BORDER_WIDTH_SAFE (XFRAME (WINDOW_FRAME ((W)))) \ | ||
| 954 | + (XFASTINT ((W)->top) \ | ||
| 955 | * CANON_Y_UNIT (XFRAME (WINDOW_FRAME ((W)))))) | ||
| 956 | |||
| 957 | /* Bottom edge of window W relative to its frame. */ | ||
| 958 | |||
| 959 | #define WINDOW_DISPLAY_BOTTOM_EDGE_PIXEL_Y(W) \ | ||
| 960 | (WINDOW_DISPLAY_TOP_EDGE_PIXEL_Y ((W)) \ | ||
| 961 | + WINDOW_DISPLAY_PIXEL_HEIGHT ((W))) | ||
| 962 | |||
| 963 | /* Convert window W relative pixel X to frame pixel coordinates. */ | ||
| 964 | |||
| 965 | #define WINDOW_TO_FRAME_PIXEL_X(W, X) \ | ||
| 966 | ((X) + WINDOW_DISPLAY_LEFT_EDGE_PIXEL_X ((W))) | ||
| 967 | |||
| 968 | /* Convert window W relative pixel Y to frame pixel coordinates. */ | ||
| 969 | |||
| 970 | #define WINDOW_TO_FRAME_PIXEL_Y(W, Y) \ | ||
| 971 | ((Y) + WINDOW_DISPLAY_TOP_EDGE_PIXEL_Y ((W))) | ||
| 972 | |||
| 973 | /* Convert frame relative pixel X to window relative pixel X. */ | ||
| 974 | |||
| 975 | #define FRAME_TO_WINDOW_PIXEL_X(W, X) \ | ||
| 976 | ((X) - WINDOW_DISPLAY_LEFT_EDGE_PIXEL_X ((W))) | ||
| 977 | |||
| 978 | /* Convert frame relative pixel X to window relative pixel Y. */ | ||
| 979 | |||
| 980 | #define FRAME_TO_WINDOW_PIXEL_Y(W, Y) \ | ||
| 981 | ((Y) - WINDOW_DISPLAY_TOP_EDGE_PIXEL_Y ((W))) | ||
| 982 | |||
| 983 | /* Width of left margin area in pixels. */ | ||
| 984 | |||
| 985 | #define WINDOW_DISPLAY_LEFT_AREA_PIXEL_WIDTH(W) \ | ||
| 986 | (NILP ((W)->left_margin_width) \ | ||
| 987 | ? 0 \ | ||
| 988 | : (XINT ((W)->left_margin_width) \ | ||
| 989 | * CANON_X_UNIT (XFRAME (WINDOW_FRAME ((W)))))) | ||
| 990 | |||
| 991 | /* Width of right marginal area in pixels. */ | ||
| 992 | |||
| 993 | #define WINDOW_DISPLAY_RIGHT_AREA_PIXEL_WIDTH(W) \ | ||
| 994 | (NILP ((W)->right_margin_width) \ | ||
| 995 | ? 0 \ | ||
| 996 | : (XINT ((W)->right_margin_width) \ | ||
| 997 | * CANON_X_UNIT (XFRAME (WINDOW_FRAME ((W)))))) | ||
| 998 | |||
| 999 | /* Width of text area in pixels. */ | ||
| 1000 | |||
| 1001 | #define WINDOW_DISPLAY_TEXT_AREA_PIXEL_WIDTH(W) \ | ||
| 1002 | (WINDOW_DISPLAY_PIXEL_WIDTH ((W)) \ | ||
| 1003 | - WINDOW_DISPLAY_LEFT_AREA_PIXEL_WIDTH ((W)) \ | ||
| 1004 | - WINDOW_DISPLAY_RIGHT_AREA_PIXEL_WIDTH ((W))) | ||
| 1005 | |||
| 1006 | /* Convert a text area relative x-position in window W to frame X | ||
| 1007 | pixel coordinates. */ | ||
| 1008 | |||
| 1009 | #define WINDOW_TEXT_TO_FRAME_PIXEL_X(W, X) \ | ||
| 1010 | (WINDOW_TO_FRAME_PIXEL_X ((W), (X)) \ | ||
| 1011 | + WINDOW_DISPLAY_LEFT_AREA_PIXEL_WIDTH ((W))) | ||
| 1012 | |||
| 1013 | /* Translate an x-position relative to AREA in window W to frame pixel | ||
| 1014 | coordinates. */ | ||
| 1015 | |||
| 1016 | #define WINDOW_AREA_TO_FRAME_PIXEL_X(W, AREA, X) \ | ||
| 1017 | (WINDOW_TO_FRAME_PIXEL_X ((W), (X)) \ | ||
| 1018 | + (((AREA) > LEFT_MARGIN_AREA) \ | ||
| 1019 | ? WINDOW_DISPLAY_LEFT_AREA_PIXEL_WIDTH ((W)) \ | ||
| 1020 | : 0) \ | ||
| 1021 | + (((AREA) > TEXT_AREA) \ | ||
| 1022 | ? WINDOW_DISPLAY_TEXT_AREA_PIXEL_WIDTH ((W)) \ | ||
| 1023 | : 0)) | ||
| 1024 | |||
| 1025 | /* Return the pixel width of AREA in W. */ | ||
| 1026 | |||
| 1027 | #define WINDOW_AREA_PIXEL_WIDTH(W, AREA) \ | ||
| 1028 | (((AREA) == TEXT_AREA) \ | ||
| 1029 | ? WINDOW_DISPLAY_TEXT_AREA_PIXEL_WIDTH ((W)) \ | ||
| 1030 | : (((AREA) == LEFT_MARGIN_AREA) \ | ||
| 1031 | ? WINDOW_DISPLAY_LEFT_AREA_PIXEL_WIDTH ((W)) \ | ||
| 1032 | : WINDOW_DISPLAY_RIGHT_AREA_PIXEL_WIDTH ((W)))) | ||
| 1033 | |||
| 1034 | /* Value is non-zero if window W has a mode line. */ | ||
| 1035 | |||
| 1036 | #define WINDOW_WANTS_MODELINE_P(W) \ | ||
| 1037 | (!MINI_WINDOW_P (W) \ | ||
| 1038 | && !(W)->pseudo_window_p \ | ||
| 1039 | && FRAME_WANTS_MODELINE_P (XFRAME (WINDOW_FRAME (W))) \ | ||
| 1040 | && !NILP (XBUFFER ((W)->buffer)->mode_line_format)) | ||
| 1041 | |||
| 1042 | /* Value is non-zero if window W wants a top line. */ | ||
| 1043 | |||
| 1044 | #define WINDOW_WANTS_TOP_LINE_P(W) \ | ||
| 1045 | (!MINI_WINDOW_P (W) \ | ||
| 1046 | && !(W)->pseudo_window_p \ | ||
| 1047 | && FRAME_WANTS_MODELINE_P (XFRAME (WINDOW_FRAME (W))) \ | ||
| 1048 | && !NILP (XBUFFER ((W)->buffer)->top_line_format)) | ||
| 1049 | |||
| 1050 | |||
| 1051 | /*********************************************************************** | ||
| 1052 | Faces | ||
| 1053 | ***********************************************************************/ | ||
| 1054 | |||
| 1055 | /* Indices of face attributes in Lisp face vectors. Slot zero is the | ||
| 1056 | symbol `face'. */ | ||
| 1057 | |||
| 1058 | enum lface_attribute_index | ||
| 1059 | { | ||
| 1060 | LFACE_FAMILY_INDEX = 1, | ||
| 1061 | LFACE_SWIDTH_INDEX, | ||
| 1062 | LFACE_HEIGHT_INDEX, | ||
| 1063 | LFACE_WEIGHT_INDEX, | ||
| 1064 | LFACE_SLANT_INDEX, | ||
| 1065 | LFACE_UNDERLINE_INDEX, | ||
| 1066 | LFACE_INVERSE_INDEX, | ||
| 1067 | LFACE_FOREGROUND_INDEX, | ||
| 1068 | LFACE_BACKGROUND_INDEX, | ||
| 1069 | LFACE_STIPPLE_INDEX, | ||
| 1070 | LFACE_OVERLINE_INDEX, | ||
| 1071 | LFACE_STRIKE_THROUGH_INDEX, | ||
| 1072 | LFACE_BOX_INDEX, | ||
| 1073 | LFACE_VECTOR_SIZE | ||
| 1074 | }; | ||
| 1075 | |||
| 1076 | |||
| 1077 | /* Box types of faces. */ | ||
| 1078 | |||
| 1079 | enum face_box_type | ||
| 1080 | { | ||
| 1081 | /* No box around text. */ | ||
| 1082 | FACE_NO_BOX, | ||
| 1083 | |||
| 1084 | /* Simple box of specified width and color. Default width is 1, and | ||
| 1085 | default color is the foreground color of the face. */ | ||
| 1086 | FACE_SIMPLE_BOX, | ||
| 1087 | |||
| 1088 | /* Boxes with 3D shadows. Color equals the background color of the | ||
| 1089 | face. Width is specified. */ | ||
| 1090 | FACE_RAISED_BOX, | ||
| 1091 | FACE_SUNKEN_BOX | ||
| 1092 | }; | ||
| 1093 | |||
| 1094 | |||
| 1095 | /* Structure describing a realized face. | ||
| 1096 | |||
| 1097 | For each Lisp face, 0..N realized faces can exist for different | ||
| 1098 | frames and different charsets. Realized faces are built from Lisp | ||
| 1099 | faces and text properties/overlays by merging faces and adding | ||
| 1100 | unspecified attributes from the `default' face. */ | ||
| 1101 | |||
| 41 | struct face | 1102 | struct face |
| 1103 | { | ||
| 1104 | /* The id of this face. The id equals the index of this face in the | ||
| 1105 | vector faces_by_id of its face cache. */ | ||
| 1106 | int id; | ||
| 1107 | |||
| 1108 | #ifdef HAVE_WINDOW_SYSTEM | ||
| 1109 | |||
| 1110 | /* If non-zero, a GC we can use without modification to draw | ||
| 1111 | characters in this face. */ | ||
| 1112 | GC gc; | ||
| 1113 | |||
| 1114 | /* Font used for this face, or null if the font could not be loaded | ||
| 1115 | for some reason. This points to a `font' slot of a struct | ||
| 1116 | font_info, and we should not call XFreeFont on it because the | ||
| 1117 | font may still be used somewhere else. */ | ||
| 1118 | XFontStruct *font; | ||
| 1119 | |||
| 1120 | /* Background stipple or bitmap used for this face. */ | ||
| 1121 | Pixmap stipple; | ||
| 1122 | |||
| 1123 | #else /* not HAVE_WINDOW_SYSTEM */ | ||
| 1124 | |||
| 1125 | /* Dummy. */ | ||
| 1126 | int stipple; | ||
| 1127 | |||
| 1128 | #endif /* not HAVE_WINDOW_SYSTEM */ | ||
| 1129 | |||
| 1130 | /* Pixel value of foreground color for X frames. Color index | ||
| 1131 | for tty frames. */ | ||
| 1132 | unsigned long foreground; | ||
| 1133 | |||
| 1134 | /* Pixel value or color index of background color. */ | ||
| 1135 | unsigned long background; | ||
| 1136 | |||
| 1137 | /* Pixel value or color index of underline color. */ | ||
| 1138 | unsigned long underline_color; | ||
| 1139 | |||
| 1140 | /* Pixel value or color index of overlined, strike-through, or box | ||
| 1141 | color. */ | ||
| 1142 | unsigned long overline_color; | ||
| 1143 | unsigned long strike_through_color; | ||
| 1144 | unsigned long box_color; | ||
| 1145 | |||
| 1146 | /* The font's name. This points to a `name' of a font_info, and it | ||
| 1147 | must not be freed. */ | ||
| 1148 | char *font_name; | ||
| 1149 | |||
| 1150 | /* The X font registry and encoding of font_name. */ | ||
| 1151 | Lisp_Object registry; | ||
| 1152 | |||
| 1153 | /* Font info ID for this face's font. An ID is stored here because | ||
| 1154 | pointers to font_info structures may change. The reason is that | ||
| 1155 | they are pointers into a font table vector that is itself | ||
| 1156 | reallocated. */ | ||
| 1157 | int font_info_id; | ||
| 1158 | |||
| 1159 | /* Fontset ID if this face uses a fontset, or -1. This is only >= 0 | ||
| 1160 | if the face was realized for CHARSET_COMPOSITION. For all other | ||
| 1161 | charsets, a specific font is loaded from the set of fonts | ||
| 1162 | specified by the fontset given by the family attribute of the face. */ | ||
| 1163 | int fontset; | ||
| 1164 | |||
| 1165 | /* Pixmap width and height. */ | ||
| 1166 | unsigned int pixmap_w, pixmap_h; | ||
| 1167 | |||
| 1168 | /* Non-zero means characters in this face have a box that thickness | ||
| 1169 | around them. */ | ||
| 1170 | int box_line_width; | ||
| 1171 | |||
| 1172 | /* Type of box drawn. A value of FACE_NO_BOX means no box is drawn | ||
| 1173 | around text in this face. A value of FACE_SIMPLE_BOX means a box | ||
| 1174 | of width box_line_width is drawn in color box_color. A value of | ||
| 1175 | FACE_RAISED_BOX or FACE_SUNKEN_BOX means a 3D box is drawn with | ||
| 1176 | shadow colors derived from the background color of the face. */ | ||
| 1177 | enum face_box_type box; | ||
| 1178 | |||
| 1179 | /* If `box' above specifies a 3D type, 1 means use box_color for | ||
| 1180 | drawing shadows. */ | ||
| 1181 | unsigned use_box_color_for_shadows_p : 1; | ||
| 1182 | |||
| 1183 | /* The Lisp face attributes this face realizes. All attributes | ||
| 1184 | in this vector are non-nil. */ | ||
| 1185 | Lisp_Object lface[LFACE_VECTOR_SIZE]; | ||
| 1186 | |||
| 1187 | /* The hash value of this face. */ | ||
| 1188 | unsigned hash; | ||
| 1189 | |||
| 1190 | /* The charset for which this face was realized if it was realized | ||
| 1191 | for use in multibyte text. If fontset >= 0, this is | ||
| 1192 | CHARSET_COMPOSITION. A value of charset < 0 means the face was | ||
| 1193 | realized for use in unibyte text where the idea of Emacs | ||
| 1194 | charsets isn't applicable. */ | ||
| 1195 | int charset; | ||
| 1196 | |||
| 1197 | /* Non-zero if text in this face should be underlined, overlined, | ||
| 1198 | strike-through or have a box drawn around it. */ | ||
| 1199 | unsigned underline_p : 1; | ||
| 1200 | unsigned overline_p : 1; | ||
| 1201 | unsigned strike_through_p : 1; | ||
| 1202 | |||
| 1203 | /* 1 means that the colors specified for this face could not be | ||
| 1204 | loaded, and were replaced by default colors, so they shouldn't be | ||
| 1205 | freed. */ | ||
| 1206 | unsigned foreground_defaulted_p : 1; | ||
| 1207 | unsigned background_defaulted_p : 1; | ||
| 1208 | |||
| 1209 | /* 1 means that either no color is specified for underlining or that | ||
| 1210 | the the specified color couldn't be loaded. Use the foreground | ||
| 1211 | color when drawing in that case. */ | ||
| 1212 | unsigned underline_defaulted_p : 1; | ||
| 1213 | |||
| 1214 | /* 1 means that either no color is specified for the corresponding | ||
| 1215 | attribute or that the the specified color couldn't be loaded. | ||
| 1216 | Use the foreground color when drawing in that case. */ | ||
| 1217 | unsigned overline_color_defaulted_p : 1; | ||
| 1218 | unsigned strike_through_color_defaulted_p : 1; | ||
| 1219 | unsigned box_color_defaulted_p : 1; | ||
| 1220 | |||
| 1221 | /* TTY appearances. Blinking is not yet implemented. Colors are | ||
| 1222 | found in `lface' with empty color string meaning the default | ||
| 1223 | color of the TTY. */ | ||
| 1224 | unsigned tty_bold_p : 1; | ||
| 1225 | unsigned tty_dim_p : 1; | ||
| 1226 | unsigned tty_underline_p : 1; | ||
| 1227 | unsigned tty_alt_charset_p : 1; | ||
| 1228 | unsigned tty_reverse_p : 1; | ||
| 1229 | unsigned tty_blinking_p : 1; | ||
| 1230 | |||
| 1231 | /* Next and previous face in hash collision list of face cache. */ | ||
| 1232 | struct face *next, *prev; | ||
| 1233 | }; | ||
| 1234 | |||
| 1235 | |||
| 1236 | /* Color index indicating that face uses a terminal's default color. */ | ||
| 1237 | |||
| 1238 | #define FACE_TTY_DEFAULT_COLOR ((unsigned long) -1) | ||
| 1239 | |||
| 1240 | /* Non-zero if FACE was realized for unibyte use. */ | ||
| 1241 | |||
| 1242 | #define FACE_UNIBYTE_P(FACE) ((FACE)->charset < 0) | ||
| 1243 | |||
| 1244 | |||
| 1245 | /* IDs of important faces known by the C face code. These are the IDs | ||
| 1246 | of the faces for CHARSET_ASCII. */ | ||
| 1247 | |||
| 1248 | enum face_id | ||
| 1249 | { | ||
| 1250 | DEFAULT_FACE_ID, | ||
| 1251 | MODE_LINE_FACE_ID, | ||
| 1252 | TOOLBAR_FACE_ID, | ||
| 1253 | BITMAP_AREA_FACE_ID, | ||
| 1254 | TOP_LINE_FACE_ID, | ||
| 1255 | BASIC_FACE_ID_SENTINEL | ||
| 1256 | }; | ||
| 1257 | |||
| 1258 | |||
| 1259 | /* A cache of realized faces. Each frame has its own cache because | ||
| 1260 | Emacs allows different frame-local face definitions. */ | ||
| 1261 | |||
| 1262 | struct face_cache | ||
| 1263 | { | ||
| 1264 | /* Hash table of cached realized faces. */ | ||
| 1265 | struct face **buckets; | ||
| 1266 | |||
| 1267 | /* Back-pointer to the frame this cache belongs to. */ | ||
| 1268 | struct frame *f; | ||
| 1269 | |||
| 1270 | /* A vector of faces so that faces can be referenced by an ID. */ | ||
| 1271 | struct face **faces_by_id; | ||
| 1272 | |||
| 1273 | /* The allocated size, and number of used slots of faces_by_id. */ | ||
| 1274 | int size, used; | ||
| 1275 | }; | ||
| 1276 | |||
| 1277 | |||
| 1278 | /* Prepare face FACE for use on frame F. This must be called before | ||
| 1279 | using X resources of FACE. */ | ||
| 1280 | |||
| 1281 | #define PREPARE_FACE_FOR_DISPLAY(F, FACE) \ | ||
| 1282 | if ((FACE)->gc == 0) \ | ||
| 1283 | prepare_face_for_display ((F), (FACE)); \ | ||
| 1284 | else \ | ||
| 1285 | (void) 0 | ||
| 1286 | |||
| 1287 | /* Return a pointer to the face with ID on frame F, or null if such a | ||
| 1288 | face doesn't exist. */ | ||
| 1289 | |||
| 1290 | #define FACE_FROM_ID(F, ID) \ | ||
| 1291 | (((ID) >= 0 && (ID) < FRAME_FACE_CACHE (F)->used) \ | ||
| 1292 | ? FRAME_FACE_CACHE (F)->faces_by_id[ID] \ | ||
| 1293 | : NULL) | ||
| 1294 | |||
| 1295 | /* Non-zero if FACE is suitable for displaying characters of CHARSET. | ||
| 1296 | CHARSET < 0 means unibyte text. */ | ||
| 1297 | |||
| 1298 | #define FACE_SUITABLE_FOR_CHARSET_P(FACE, CHARSET) \ | ||
| 1299 | (((CHARSET) < 0 \ | ||
| 1300 | ? (EQ ((FACE)->registry, Vface_default_registry) \ | ||
| 1301 | || !NILP (Fequal ((FACE)->registry, Vface_default_registry))) \ | ||
| 1302 | : ((FACE)->charset == (CHARSET) \ | ||
| 1303 | || ((FACE)->charset == CHARSET_ASCII \ | ||
| 1304 | && (CHARSET) == charset_latin_iso8859_1 \ | ||
| 1305 | && face_suitable_for_iso8859_1_p ((FACE))) \ | ||
| 1306 | || ((FACE)->charset == charset_latin_iso8859_1 \ | ||
| 1307 | && (CHARSET) == CHARSET_ASCII)))) | ||
| 1308 | |||
| 1309 | /* Return the id of the realized face on frame F that is like the face | ||
| 1310 | with id ID but is suitable for displaying characters of CHARSET. | ||
| 1311 | This macro is only meaningful for CHARSET >= 0, i.e. multibyte | ||
| 1312 | text. */ | ||
| 1313 | |||
| 1314 | #define FACE_FOR_CHARSET(F, ID, CHARSET) \ | ||
| 1315 | (FACE_SUITABLE_FOR_CHARSET_P (FACE_FROM_ID ((F), (ID)), (CHARSET)) \ | ||
| 1316 | ? (ID) \ | ||
| 1317 | : lookup_face ((F), FACE_FROM_ID ((F), (ID))->lface, (CHARSET))) | ||
| 1318 | |||
| 1319 | /* The default registry and encoding to use. */ | ||
| 1320 | |||
| 1321 | extern Lisp_Object Vface_default_registry; | ||
| 1322 | |||
| 1323 | /* Non-zero means face attributes have been changed since the last | ||
| 1324 | redisplay. Used in redisplay_internal. */ | ||
| 1325 | |||
| 1326 | extern int face_change_count; | ||
| 1327 | |||
| 1328 | |||
| 1329 | |||
| 1330 | |||
| 1331 | /*********************************************************************** | ||
| 1332 | Display Iterator | ||
| 1333 | ***********************************************************************/ | ||
| 1334 | |||
| 1335 | /* Iteration over things to display in current_buffer or in a string. | ||
| 1336 | |||
| 1337 | The iterator handles: | ||
| 1338 | |||
| 1339 | 1. Overlay strings (after-string, before-string). | ||
| 1340 | 2. Face properties. | ||
| 1341 | 3. Invisible text properties. | ||
| 1342 | 4. Selective display. | ||
| 1343 | 5. Translation of characters via display tables. | ||
| 1344 | 6. Translation of control characters to the forms `\003' or `^C'. | ||
| 1345 | 7. `glyph' and `space-width' properties. | ||
| 1346 | |||
| 1347 | Iterators are initialized by calling init_iterator or one of the | ||
| 1348 | equivalent functions below. A call to get_next_display_element | ||
| 1349 | loads the iterator structure with information about what next to | ||
| 1350 | display. A call to set_iterator_to_next increments the iterator's | ||
| 1351 | position. | ||
| 1352 | |||
| 1353 | Characters from overlay strings, display table entries or control | ||
| 1354 | character translations are returned one at a time. For example, if | ||
| 1355 | we have a text of `a\x01' where `a' has a display table definition | ||
| 1356 | of `cd' and the control character is displayed with a leading | ||
| 1357 | arrow, then the iterator will return: | ||
| 1358 | |||
| 1359 | Call Return Source Call next | ||
| 1360 | ----------------------------------------------------------------- | ||
| 1361 | next c display table move | ||
| 1362 | next d display table move | ||
| 1363 | next ^ control char move | ||
| 1364 | next A control char move | ||
| 1365 | |||
| 1366 | The same mechanism is also used to return characters for ellipses | ||
| 1367 | displayed at the end of invisible text. | ||
| 1368 | |||
| 1369 | CAVEAT: Under some circumstances, move_.* functions can be called | ||
| 1370 | asynchronously, e.g. when computing a buffer position from an x and | ||
| 1371 | y pixel position. This means that these functions and functions | ||
| 1372 | called from them SHOULD NOT USE xmalloc and alike. See also the | ||
| 1373 | comment at the start of xdisp.c. */ | ||
| 1374 | |||
| 1375 | /* Enumeration describing what kind of display element an iterator is | ||
| 1376 | loaded with after a call to get_next_display_element. */ | ||
| 1377 | |||
| 1378 | enum display_element_type | ||
| 1379 | { | ||
| 1380 | /* A normal character. */ | ||
| 1381 | IT_CHARACTER, | ||
| 1382 | |||
| 1383 | /* An image. */ | ||
| 1384 | IT_IMAGE, | ||
| 1385 | |||
| 1386 | /* A flexible width and height space. */ | ||
| 1387 | IT_STRETCH, | ||
| 1388 | |||
| 1389 | /* End of buffer or string. */ | ||
| 1390 | IT_EOB, | ||
| 1391 | |||
| 1392 | /* Truncation glyphs. Never returned by get_next_display_element. | ||
| 1393 | Used to get display information about truncation glyphs via | ||
| 1394 | produce_glyphs. */ | ||
| 1395 | IT_TRUNCATION, | ||
| 1396 | |||
| 1397 | /* Continuation glyphs. See the comment for IT_TRUNCATION. */ | ||
| 1398 | IT_CONTINUATION | ||
| 1399 | }; | ||
| 1400 | |||
| 1401 | |||
| 1402 | /* An enumerator for each text property that has a meaning for display | ||
| 1403 | purposes. */ | ||
| 1404 | |||
| 1405 | enum prop_idx | ||
| 1406 | { | ||
| 1407 | FONTIFIED_PROP_IDX, | ||
| 1408 | FACE_PROP_IDX, | ||
| 1409 | INVISIBLE_PROP_IDX, | ||
| 1410 | DISPLAY_PROP_IDX, | ||
| 1411 | |||
| 1412 | /* Not a property. Used to indicate changes in overlays. */ | ||
| 1413 | OVERLAY_PROP_IDX, | ||
| 1414 | |||
| 1415 | /* Sentinel. */ | ||
| 1416 | LAST_PROP_IDX | ||
| 1417 | }; | ||
| 1418 | |||
| 1419 | |||
| 1420 | struct it | ||
| 1421 | { | ||
| 1422 | /* The window in which we iterate over current_buffer (or a string). */ | ||
| 1423 | Lisp_Object window; | ||
| 1424 | struct window *w; | ||
| 1425 | |||
| 1426 | /* The window's frame. */ | ||
| 1427 | struct frame *f; | ||
| 1428 | |||
| 1429 | /* Function to call to load this structure with the next display | ||
| 1430 | element. */ | ||
| 1431 | int (* method) P_ ((struct it *it)); | ||
| 1432 | |||
| 1433 | /* The next position at which to check for face changes, invisible | ||
| 1434 | text, overlay strings, end of text etc., which see. */ | ||
| 1435 | int stop_charpos; | ||
| 1436 | |||
| 1437 | /* Maximum string or buffer position + 1. ZV when iterating over | ||
| 1438 | current_buffer. */ | ||
| 1439 | int end_charpos; | ||
| 1440 | |||
| 1441 | /* C string to iterate over. Non-null means get characters from | ||
| 1442 | this string, otherwise characters are read from current_buffer | ||
| 1443 | or it->string. */ | ||
| 1444 | unsigned char *s; | ||
| 1445 | |||
| 1446 | /* Number of characters in the string (s, or it->string) we iterate | ||
| 1447 | over. */ | ||
| 1448 | int string_nchars; | ||
| 1449 | |||
| 1450 | /* Start and end of a visible region; -1 if the region is not | ||
| 1451 | visible in the window. */ | ||
| 1452 | int region_beg_charpos, region_end_charpos; | ||
| 1453 | |||
| 1454 | /* Position at which redisplay end trigger functions should be run. */ | ||
| 1455 | int redisplay_end_trigger_charpos; | ||
| 1456 | |||
| 1457 | /* 1 means multibyte characters are enabled. */ | ||
| 1458 | unsigned multibyte_p : 1; | ||
| 1459 | |||
| 1460 | /* 1 means highlight trailing whitespace. */ | ||
| 1461 | unsigned show_trailing_whitespace_p : 1; | ||
| 1462 | |||
| 1463 | /* 1 means window has a mode line at its top. */ | ||
| 1464 | unsigned top_line_p : 1; | ||
| 1465 | |||
| 1466 | /* 1 means `string' is the value of a `display' property. | ||
| 1467 | Don't handle some `display' properties in these strings. */ | ||
| 1468 | unsigned string_from_display_prop_p : 1; | ||
| 1469 | |||
| 1470 | /* Display table in effect or null for none. */ | ||
| 1471 | struct Lisp_Char_Table *dp; | ||
| 1472 | |||
| 1473 | /* Current display table vector to return characters from and its | ||
| 1474 | end. dpvec null means we are not returning characters from a | ||
| 1475 | display table entry; current.dpvec_index gives the current index | ||
| 1476 | into dpvec. This same mechanism is also used to return | ||
| 1477 | characters from translated control characters, i.e. `\003' or | ||
| 1478 | `^C'. */ | ||
| 1479 | Lisp_Object *dpvec, *dpend; | ||
| 1480 | |||
| 1481 | /* Length in bytes of the char that filled dpvec. A value of zero | ||
| 1482 | means that no character such character is involved. */ | ||
| 1483 | int dpvec_char_len; | ||
| 1484 | |||
| 1485 | /* Face id of the iterator saved in case a glyph from dpvec contains | ||
| 1486 | a face. The face is restored when all glyphs from dpvec have | ||
| 1487 | been delivered. */ | ||
| 1488 | int saved_face_id; | ||
| 1489 | |||
| 1490 | /* Vector of glyphs for control character translation. The pointer | ||
| 1491 | dpvec is set to ctl_chars when a control character is translated. */ | ||
| 1492 | Lisp_Object ctl_chars[4]; | ||
| 1493 | |||
| 1494 | /* Current buffer or string position of the iterator, including | ||
| 1495 | position in overlay strings etc. */ | ||
| 1496 | struct display_pos current; | ||
| 1497 | |||
| 1498 | /* Vector of overlays to process. Overlay strings are processed | ||
| 1499 | OVERLAY_STRING_CHUNK_SIZE at a time. */ | ||
| 1500 | #define OVERLAY_STRING_CHUNK_SIZE 3 | ||
| 1501 | Lisp_Object overlay_strings[OVERLAY_STRING_CHUNK_SIZE]; | ||
| 1502 | |||
| 1503 | /* Total number of overlay strings to process. This can be > | ||
| 1504 | OVERLAY_STRING_CHUNK_SIZE. */ | ||
| 1505 | int n_overlay_strings; | ||
| 1506 | |||
| 1507 | /* If non-nil, a Lisp string being processed. If | ||
| 1508 | current.overlay_string_index >= 0, this is an overlay string from | ||
| 1509 | pos. */ | ||
| 1510 | Lisp_Object string; | ||
| 1511 | |||
| 1512 | /* Stack of saved values. New entries are pushed when we begin to | ||
| 1513 | process an overlay string or a string from a `glyph' property. | ||
| 1514 | Entries are popped when we return to deliver display elements | ||
| 1515 | from what we previously had. */ | ||
| 1516 | struct iterator_stack_entry | ||
| 42 | { | 1517 | { |
| 43 | /* If this is non-zero, it is a GC we can use without modification | 1518 | int stop_charpos; |
| 44 | to represent this face. Used only for ASCII characters. */ | 1519 | int face_id; |
| 45 | GC gc; | 1520 | Lisp_Object string; |
| 1521 | struct display_pos pos; | ||
| 1522 | int end_charpos; | ||
| 1523 | int string_nchars; | ||
| 1524 | enum glyph_row_area area; | ||
| 1525 | unsigned multibyte_p : 1; | ||
| 1526 | unsigned string_from_display_prop_p : 1; | ||
| 1527 | Lisp_Object space_width; | ||
| 1528 | short voffset; | ||
| 1529 | Lisp_Object font_height; | ||
| 1530 | } | ||
| 1531 | stack[2]; | ||
| 46 | 1532 | ||
| 47 | /* GC used for non-ASCII characters. */ | 1533 | /* Stack pointer. */ |
| 48 | GC non_ascii_gc; | 1534 | int sp; |
| 1535 | |||
| 1536 | /* Setting of buffer-local variable selective-display-ellipsis. */ | ||
| 1537 | unsigned selective_display_ellipsis_p : 1; | ||
| 1538 | |||
| 1539 | /* 1 means control characters are translated into the form `^C' | ||
| 1540 | where the `^' can be replaced by a display table entry. */ | ||
| 1541 | unsigned ctl_arrow_p : 1; | ||
| 1542 | |||
| 1543 | /* -1 means selective display hides everything between a \r and the | ||
| 1544 | next newline; > 0 means hide lines indented more than that value. */ | ||
| 1545 | int selective; | ||
| 1546 | |||
| 1547 | /* An enumeration describing what the next display element is | ||
| 1548 | after a call to get_next_display_element. */ | ||
| 1549 | enum display_element_type what; | ||
| 49 | 1550 | ||
| 50 | /* Pixel value for foreground color. */ | 1551 | /* Face to use. */ |
| 51 | EMACS_UINT foreground; | 1552 | int face_id; |
| 1553 | |||
| 1554 | /* Non-zero means that the current face has a box. */ | ||
| 1555 | unsigned face_box_p : 1; | ||
| 1556 | |||
| 1557 | /* Non-null means that the current character is the first in a run | ||
| 1558 | of characters with box face. */ | ||
| 1559 | unsigned start_of_box_run_p : 1; | ||
| 52 | 1560 | ||
| 53 | /* Pixel value for background color. */ | 1561 | /* Non-zero means that the current character is the last in a run |
| 54 | EMACS_UINT background; | 1562 | of characters with box face. */ |
| 1563 | unsigned end_of_box_run_p : 1; | ||
| 1564 | |||
| 1565 | /* 1 means overlay strings at end_charpos have been processed. */ | ||
| 1566 | unsigned overlay_strings_at_end_processed_p : 1; | ||
| 1567 | |||
| 1568 | /* The ID of the default face to use. One of DEFAULT_FACE_ID, | ||
| 1569 | MODE_LINE_FACE_ID, or TOOLBAR_FACE_ID, depending on what we | ||
| 1570 | are displaying. */ | ||
| 1571 | int base_face_id; | ||
| 1572 | |||
| 1573 | /* If what == IT_CHARACTER, character and length in bytes. This is | ||
| 1574 | a character from a buffer or string. It may be different from | ||
| 1575 | the character displayed in case that | ||
| 1576 | unibyte_display_via_language_environment is set. */ | ||
| 1577 | int c, len; | ||
| 1578 | |||
| 1579 | /* The character to display, possibly translated to multibyte | ||
| 1580 | if unibyte_display_via_language_environment is set. This | ||
| 1581 | is set after x_produce_glyphs has been called. */ | ||
| 1582 | int char_to_display; | ||
| 1583 | |||
| 1584 | /* Charset for which face_id was computed. This is the charset | ||
| 1585 | of char_to_display after x_produce_glyphs has been called. */ | ||
| 1586 | int charset; | ||
| 1587 | |||
| 1588 | /* If what == IT_IMAGE, the id of the image to display. */ | ||
| 1589 | int image_id; | ||
| 1590 | |||
| 1591 | /* Value of the `space-width' property, if any; nil if none. */ | ||
| 1592 | Lisp_Object space_width; | ||
| 1593 | |||
| 1594 | /* Computed from the value of the `raise' property. */ | ||
| 1595 | short voffset; | ||
| 1596 | |||
| 1597 | /* Value of the `height' property, if any; nil if none. */ | ||
| 1598 | Lisp_Object font_height; | ||
| 1599 | |||
| 1600 | /* Object and position where the current display element came from. | ||
| 1601 | Object can be a Lisp string in case the current display element | ||
| 1602 | comes from an overlay string, or it is buffer. Position is | ||
| 1603 | a position in object. */ | ||
| 1604 | Lisp_Object object; | ||
| 1605 | struct text_pos position; | ||
| 1606 | |||
| 1607 | /* 1 means lines are truncated. */ | ||
| 1608 | unsigned truncate_lines_p : 1; | ||
| 1609 | |||
| 1610 | /* Number of columns per \t. */ | ||
| 1611 | short tab_width; | ||
| 1612 | |||
| 1613 | /* Width in pixels of truncation and continuation glyphs. */ | ||
| 1614 | short truncation_pixel_width, continuation_pixel_width; | ||
| 1615 | |||
| 1616 | /* First and last visible x-position in the display area. If window | ||
| 1617 | is hscrolled by n columns, first_visible_x == n * CANON_X_UNIT | ||
| 1618 | (f), and last_visible_x == pixel width of W + first_visible_x. */ | ||
| 1619 | int first_visible_x, last_visible_x; | ||
| 1620 | |||
| 1621 | /* Last visible y-position + 1 in the display area without a mode | ||
| 1622 | line, if the window has one. */ | ||
| 1623 | int last_visible_y; | ||
| 1624 | |||
| 1625 | /* Width of a prompt in front of the line. Used to perform tab | ||
| 1626 | calculations. The x on which tab calculations are based is | ||
| 1627 | current_x - prompt_width + continuation_lines_width. */ | ||
| 1628 | int prompt_width; | ||
| 1629 | |||
| 1630 | /* If non-null, glyphs are produced in glyph_row with each call to | ||
| 1631 | produce_glyphs. */ | ||
| 1632 | struct glyph_row *glyph_row; | ||
| 1633 | |||
| 1634 | /* The area of glyph_row to which glyphs are added. */ | ||
| 1635 | enum glyph_row_area area; | ||
| 1636 | |||
| 1637 | /* Number of glyphs needed for the last character requested via | ||
| 1638 | produce_glyphs. This is 1 except for tabs. */ | ||
| 1639 | int nglyphs; | ||
| 1640 | |||
| 1641 | /* Width of the display element in pixels. Result of | ||
| 1642 | produce_glyphs. */ | ||
| 1643 | int pixel_width; | ||
| 1644 | |||
| 1645 | /* Current and maximum line height information. Result of | ||
| 1646 | produce_glyphs. */ | ||
| 1647 | int ascent, descent, max_ascent, max_descent; | ||
| 1648 | |||
| 1649 | /* Current x pixel position within the display line. This value | ||
| 1650 | does not include the width of continuation lines in front of the | ||
| 1651 | line. The value of current_x is automatically incremented by | ||
| 1652 | pixel_width with each call to produce_glyphs. */ | ||
| 1653 | int current_x; | ||
| 1654 | |||
| 1655 | /* Accumulated width of continuation lines. If > 0, this means we | ||
| 1656 | are currently in a continuation line. This is initially zero and | ||
| 1657 | incremented/reset by display_line, move_it_to etc. */ | ||
| 1658 | int continuation_lines_width; | ||
| 1659 | |||
| 1660 | /* Current y-position. Automatically incremented by the height of | ||
| 1661 | glyph_row in move_it_to and display_line. */ | ||
| 1662 | int current_y; | ||
| 1663 | |||
| 1664 | /* Current vertical matrix position, or line number. Automatically | ||
| 1665 | incremented by move_it_to and display_line. */ | ||
| 1666 | int vpos; | ||
| 1667 | |||
| 1668 | /* Horizontal matrix position reached in move_it_in_display_line. | ||
| 1669 | Only set there, not in display_line. */ | ||
| 1670 | int hpos; | ||
| 1671 | }; | ||
| 1672 | |||
| 1673 | |||
| 1674 | /* Access to positions of iterator IT. */ | ||
| 1675 | |||
| 1676 | #define IT_CHARPOS(IT) CHARPOS ((IT).current.pos) | ||
| 1677 | #define IT_BYTEPOS(IT) BYTEPOS ((IT).current.pos) | ||
| 1678 | #define IT_STRING_CHARPOS(IT) CHARPOS ((IT).current.string_pos) | ||
| 1679 | #define IT_STRING_BYTEPOS(IT) BYTEPOS ((IT).current.string_pos) | ||
| 1680 | |||
| 1681 | /* Test if IT has reached the end of its buffer or string. This will | ||
| 1682 | only work after get_next_display_element has been called. */ | ||
| 1683 | |||
| 1684 | #define ITERATOR_AT_END_P(IT) ((IT)->what == IT_EOB) | ||
| 1685 | |||
| 1686 | /* Non-zero means IT is at the end of a line. This is the case if it | ||
| 1687 | is either on a newline or on a carriage return and selective | ||
| 1688 | display hides the rest of the line. */ | ||
| 1689 | |||
| 1690 | #define ITERATOR_AT_END_OF_LINE_P(IT) \ | ||
| 1691 | ((IT)->what == IT_CHARACTER \ | ||
| 1692 | && ((IT)->c == '\n' \ | ||
| 1693 | || ((IT)->c == '\r' && (IT)->selective))) | ||
| 1694 | |||
| 1695 | /* Call produce_glyphs or produce_glyphs_hook, if set. Shortcut to | ||
| 1696 | avoid the function call overhead. */ | ||
| 1697 | |||
| 1698 | #define PRODUCE_GLYPHS(IT) \ | ||
| 1699 | (rif \ | ||
| 1700 | ? rif->produce_glyphs ((IT)) \ | ||
| 1701 | : produce_glyphs ((IT))) | ||
| 1702 | |||
| 1703 | /* Bit-flags indicating what operation move_it_to should perform. */ | ||
| 1704 | |||
| 1705 | enum move_operation_enum | ||
| 1706 | { | ||
| 1707 | /* Stop if specified x-position is reached. */ | ||
| 1708 | MOVE_TO_X = 0x01, | ||
| 1709 | |||
| 1710 | /* Stop if specified y-position is reached. */ | ||
| 1711 | MOVE_TO_Y = 0x02, | ||
| 1712 | |||
| 1713 | /* Stop if specified vpos is reached. */ | ||
| 1714 | MOVE_TO_VPOS = 0x04, | ||
| 1715 | |||
| 1716 | /* Stop if specified buffer or string position is reached. */ | ||
| 1717 | MOVE_TO_POS = 0x08 | ||
| 1718 | }; | ||
| 1719 | |||
| 1720 | |||
| 1721 | |||
| 1722 | /*********************************************************************** | ||
| 1723 | Window-based redisplay interface | ||
| 1724 | ***********************************************************************/ | ||
| 1725 | |||
| 1726 | /* Structure used to describe runs of lines that must be scrolled. */ | ||
| 1727 | |||
| 1728 | struct run | ||
| 1729 | { | ||
| 1730 | /* Source and destination y pixel position. */ | ||
| 1731 | int desired_y, current_y; | ||
| 1732 | |||
| 1733 | /* Source and destination vpos in matrix. */ | ||
| 1734 | int desired_vpos, current_vpos; | ||
| 1735 | |||
| 1736 | /* Height in pixels, number of glyph rows. */ | ||
| 1737 | int height, nrows; | ||
| 1738 | }; | ||
| 1739 | |||
| 1740 | |||
| 1741 | /* Structure holding system-dependent interface functions needed | ||
| 1742 | for window-based redisplay. */ | ||
| 1743 | |||
| 1744 | struct redisplay_interface | ||
| 1745 | { | ||
| 1746 | /* Produce glyphs/get display metrics for the display element IT is | ||
| 1747 | loaded with. */ | ||
| 1748 | void (*produce_glyphs) P_ ((struct it *it)); | ||
| 55 | 1749 | ||
| 56 | /* Font used for this face. If any fontset is set for this face, | 1750 | /* Write or insert LEN glyphs from STRING at the nominal output |
| 57 | this points to a `font' slot of the struct `font_info' for an | 1751 | position. */ |
| 58 | ASCII font of the fontset. In that case, we should not call | 1752 | void (*write_glyphs) P_ ((struct glyph *string, int len)); |
| 59 | XFreeFont on it because the font may still be used somewhere | 1753 | void (*insert_glyphs) P_ ((struct glyph *start, int len)); |
| 60 | else. */ | 1754 | |
| 61 | XFontStruct *font; | 1755 | /* Clear from nominal output position to X. X < 0 means clear |
| 62 | 1756 | to right end of display. */ | |
| 63 | /* Fontset ID if any fontset is set for this face, else -1. */ | 1757 | void (*clear_end_of_line) P_ ((int x)); |
| 64 | int fontset; | ||
| 65 | 1758 | ||
| 66 | /* Background stipple or bitmap used for this face. */ | 1759 | /* Function to call to scroll the display as described by RUN on |
| 67 | Pixmap stipple; | 1760 | window W. */ |
| 1761 | void (*scroll_run_hook) P_ ((struct window *w, struct run *run)); | ||
| 1762 | |||
| 1763 | /* Function to call after a line in a display has been completely | ||
| 1764 | updated. Used to draw truncation marks and alike. DESIRED_ROW | ||
| 1765 | is the desired row which has been updated. */ | ||
| 1766 | void (*after_update_window_line_hook) P_ ((struct glyph_row *desired_row)); | ||
| 68 | 1767 | ||
| 69 | /* Pixmap_depth. */ | 1768 | /* Function to call before beginning to update window W in |
| 70 | unsigned int pixmap_w, pixmap_h; | 1769 | window-based redisplay. */ |
| 1770 | void (*update_window_begin_hook) P_ ((struct window *w)); | ||
| 1771 | |||
| 1772 | /* Function to call after window W has been updated in window-based | ||
| 1773 | redisplay. CURSOR_ON_P non-zero means switch cursor on. */ | ||
| 1774 | void (*update_window_end_hook) P_ ((struct window *w, int cursor_on_p)); | ||
| 71 | 1775 | ||
| 72 | /* Whether or not to underline text in this face. */ | 1776 | /* Move cursor to row/column position VPOS/HPOS, pixel coordinates |
| 73 | char underline; | 1777 | Y/X. HPOS/VPOS are window-relative row and column numbers and X/Y |
| 74 | }; | 1778 | are window-relative pixel positions. */ |
| 1779 | void (*cursor_to) P_ ((int vpos, int hpos, int y, int x)); | ||
| 1780 | |||
| 1781 | /* Flush the display of frame F. For X, this is XFlush. */ | ||
| 1782 | void (*flush_display) P_ ((struct frame *f)); | ||
| 1783 | |||
| 1784 | /* Set *LEFT and *RIGHT to the left and right overhang of GLYPH on | ||
| 1785 | frame F. */ | ||
| 1786 | void (*get_glyph_overhangs) P_ ((struct glyph *glyph, struct frame *f, | ||
| 1787 | int *left, int *right)); | ||
| 1788 | }; | ||
| 1789 | |||
| 1790 | /* The current interface for window-based redisplay. */ | ||
| 1791 | |||
| 1792 | extern struct redisplay_interface *rif; | ||
| 1793 | |||
| 1794 | /* Hook to call in estimate_mode_line_height. */ | ||
| 1795 | |||
| 1796 | extern int (* estimate_mode_line_height_hook) P_ ((struct frame *, | ||
| 1797 | enum face_id)); | ||
| 1798 | |||
| 1799 | |||
| 1800 | /*********************************************************************** | ||
| 1801 | Images | ||
| 1802 | ***********************************************************************/ | ||
| 1803 | |||
| 1804 | #ifdef HAVE_X_WINDOWS | ||
| 1805 | |||
| 1806 | /* Structure forward declarations. */ | ||
| 1807 | |||
| 1808 | struct image; | ||
| 1809 | |||
| 1810 | |||
| 1811 | /* Each image format (JPEG, IIFF, ...) supported is described by | ||
| 1812 | a structure of the type below. */ | ||
| 1813 | |||
| 1814 | struct image_type | ||
| 1815 | { | ||
| 1816 | /* A symbol uniquely identifying the image type, .e.g `jpeg'. */ | ||
| 1817 | Lisp_Object *type; | ||
| 1818 | |||
| 1819 | /* Check that SPEC is a valid image specification for the given | ||
| 1820 | image type. Value is non-zero if SPEC is valid. */ | ||
| 1821 | int (* valid_p) P_ ((Lisp_Object spec)); | ||
| 1822 | |||
| 1823 | /* Load IMG which is used on frame F from information contained in | ||
| 1824 | IMG->spec. Value is non-zero if successful. */ | ||
| 1825 | int (* load) P_ ((struct frame *f, struct image *img)); | ||
| 1826 | |||
| 1827 | /* Free resources of image IMG which is used on frame F. */ | ||
| 1828 | void (* free) P_ ((struct frame *f, struct image *img)); | ||
| 75 | 1829 | ||
| 76 | /* Let's stop using this and get rid of it. */ | 1830 | /* Next in list of all supported image types. */ |
| 77 | typedef struct face *FACE; | 1831 | struct image_type *next; |
| 1832 | }; | ||
| 78 | 1833 | ||
| 79 | #define NORMAL_FACE ((struct face *) 0) | ||
| 80 | 1834 | ||
| 81 | #define FACE_HAS_GC(f) ((f)->gc) | 1835 | /* Structure describing an image. Specific image formats like XBM are |
| 82 | #define FACE_GC(f) ((f)->gc) | 1836 | converted into this form, so that display only has to deal with |
| 83 | #define FACE_NON_ASCII_GC(f) ((f)->non_ascii_gc) | 1837 | this type of image. */ |
| 84 | #define FACE_FOREGROUND(f) ((f)->foreground) | ||
| 85 | #define FACE_BACKGROUND(f) ((f)->background) | ||
| 86 | #define FACE_FONT(f) ((f)->font) | ||
| 87 | #define FACE_FONTSET(f) ((f)->fontset) | ||
| 88 | #define FACE_STIPPLE(f) ((f)->stipple) | ||
| 89 | #define FACE_UNDERLINE_P(f) ((f)->underline) | ||
| 90 | 1838 | ||
| 91 | #else /* not HAVE_FACES */ | 1839 | struct image |
| 1840 | { | ||
| 1841 | /* The time in seconds at which the image was last displayed. Set | ||
| 1842 | in prepare_image_for_display. */ | ||
| 1843 | unsigned long timestamp; | ||
| 92 | 1844 | ||
| 93 | typedef int FACE; | 1845 | /* Pixmaps of the image. */ |
| 1846 | Pixmap pixmap, mask; | ||
| 94 | 1847 | ||
| 95 | #define NORMAL_FACE 0x0 | 1848 | /* Colors allocated for this image, if any. Allocated via xmalloc. */ |
| 96 | #define HIGHLIGHT_FACE 0x1 | 1849 | unsigned long *colors; |
| 97 | #define UNDERLINE_FACE 0x2 | 1850 | int ncolors; |
| 98 | #define HIGHLIGHT_UNDERLINE_FACE 0x3 | ||
| 99 | 1851 | ||
| 100 | #define FACE_HIGHLIGHT(f) ((f) & 0x1) | 1852 | /* Width and height of the image. */ |
| 101 | #define FACE_UNDERLINE(f) ((f) & 0x2) | 1853 | int width, height; |
| 102 | 1854 | ||
| 103 | #endif /* not HAVE_FACES */ | 1855 | /* These values are used for the rectangles displayed for images |
| 1856 | that can't be loaded. */ | ||
| 1857 | #define DEFAULT_IMAGE_WIDTH 30 | ||
| 1858 | #define DEFAULT_IMAGE_HEIGHT 30 | ||
| 104 | 1859 | ||
| 1860 | /* Percent of image height used as ascent. */ | ||
| 1861 | int ascent; | ||
| 1862 | #define DEFAULT_IMAGE_ASCENT 50 | ||
| 105 | 1863 | ||
| 106 | /* This structure is used for the actual display of text on a frame. | 1864 | /* Lisp specification of this image. */ |
| 1865 | Lisp_Object spec; | ||
| 107 | 1866 | ||
| 108 | There are two instantiations of it: the glyphs currently displayed, | 1867 | /* Relief to draw around the image. */ |
| 109 | and the glyphs we desire to display. The latter object is generated | 1868 | int relief; |
| 110 | from buffers being displayed. */ | ||
| 111 | 1869 | ||
| 112 | struct frame_glyphs | 1870 | /* Optional margin around the image. This includes the relief. */ |
| 1871 | int margin; | ||
| 1872 | |||
| 1873 | /* Reference to the type of the image. */ | ||
| 1874 | struct image_type *type; | ||
| 1875 | |||
| 1876 | /* A place for image types to store additional data. The member | ||
| 1877 | data.lisp_val is marked during GC, so it's safe to store Lisp data | ||
| 1878 | there. Image types should free this data when their `free' | ||
| 1879 | function is called. */ | ||
| 1880 | struct | ||
| 113 | { | 1881 | { |
| 114 | struct frame *frame; /* Frame these glyphs belong to. */ | 1882 | int int_val; |
| 115 | int height; | 1883 | void *ptr_val; |
| 116 | int width; | 1884 | Lisp_Object lisp_val; |
| 117 | 1885 | } data; | |
| 118 | /* Contents of the frame. | ||
| 119 | glyphs[V][H] is the glyph at position V, H. | ||
| 120 | Note that glyphs[V][-1], | ||
| 121 | glyphs[V][used[V]], | ||
| 122 | and glyphs[V][frame_width] are always '\0'. */ | ||
| 123 | GLYPH **glyphs; | ||
| 124 | /* long vector from which the strings in `glyphs' are taken. */ | ||
| 125 | GLYPH *total_contents; | ||
| 126 | |||
| 127 | /* When representing a desired frame, | ||
| 128 | enable[n] == 0 means that line n is same as current frame. | ||
| 129 | Between updates, all lines should be disabled. | ||
| 130 | When representing current frame contents, | ||
| 131 | enable[n] == 0 means that line n is blank. */ | ||
| 132 | char *enable; | ||
| 133 | |||
| 134 | /* Everything on line n after column used[n] is considered blank. */ | ||
| 135 | int *used; | ||
| 136 | |||
| 137 | /* highlight[n] != 0 iff line n is highlighted. */ | ||
| 138 | char *highlight; | ||
| 139 | |||
| 140 | /* Buffer offset of this line's first char. | ||
| 141 | This is not really implemented, and cannot be, | ||
| 142 | and should be deleted. */ | ||
| 143 | int *bufp; | ||
| 144 | 1886 | ||
| 145 | #ifdef HAVE_WINDOW_SYSTEM | 1887 | /* Hash value of image specification to speed up comparisons. */ |
| 146 | /* Pixel position of top left corner of line. */ | 1888 | unsigned hash; |
| 147 | short *top_left_x; | 1889 | |
| 148 | short *top_left_y; | 1890 | /* Image id of this image. */ |
| 149 | 1891 | int id; | |
| 150 | /* Pixel width of line. */ | 1892 | |
| 151 | short *pix_width; | 1893 | /* Hash collision chain. */ |
| 152 | 1894 | struct image *next, *prev; | |
| 153 | /* Pixel height of line. */ | 1895 | }; |
| 154 | short *pix_height; | 1896 | |
| 155 | 1897 | ||
| 156 | /* Largest font ascent on this line. */ | 1898 | /* Cache of images. Each frame has a cache. X frames with the same |
| 157 | short *max_ascent; | 1899 | x_display_info share their caches. */ |
| 158 | #endif /* HAVE_WINDOW_SYSTEM */ | 1900 | |
| 159 | 1901 | struct image_cache | |
| 160 | /* Mapping of coordinate pairs to buffer positions. | 1902 | { |
| 161 | This field holds a vector indexed by row number. | 1903 | /* Hash table of images. */ |
| 162 | Its elements are vectors indexed by column number. | 1904 | struct image **buckets; |
| 163 | Each element of these vectors is a buffer position, 0, or -1. | 1905 | |
| 164 | 1906 | /* Vector mapping image ids to images. */ | |
| 165 | For a column where the image of a text character starts, | 1907 | struct image **images; |
| 166 | the element value is the buffer position of that character. | 1908 | |
| 167 | When a window's screen line starts in mid character, | 1909 | /* Allocated size of `images'. */ |
| 168 | the element for the line's first column (at the window's left margin) | 1910 | unsigned size; |
| 169 | is that character's position. | 1911 | |
| 170 | For successive columns within a multicolumn character, | 1912 | /* Number of images in the cache. */ |
| 171 | the element is -1. | 1913 | unsigned used; |
| 172 | For the column just beyond the last glyph on a line, | 1914 | |
| 173 | the element is the buffer position of the end of the line. | 1915 | /* Reference count (number of frames sharing this cache). */ |
| 174 | For following columns within the same window, the element is 0. | 1916 | int refcount; |
| 175 | For rows past the end of the accessible buffer text, | 1917 | }; |
| 176 | the window's first column has ZV and other columns have 0. | 1918 | |
| 177 | 1919 | ||
| 178 | Mode lines and vertical separator lines have 0. | 1920 | /* Value is the ascent of image IMG. */ |
| 179 | 1921 | ||
| 180 | The column of a window's left margin | 1922 | #define IMAGE_ASCENT(IMG) \ |
| 181 | always has a positive value (a buffer position), not 0 or -1, | 1923 | (((IMG)->height + (IMG)->margin) * (IMG)->ascent / 100.0) |
| 182 | for each line in that window's interior. */ | 1924 | |
| 183 | 1925 | /* Value is a pointer to the image with id ID on frame F, or null if | |
| 184 | int **charstarts; | 1926 | no image with that id exists. */ |
| 185 | 1927 | ||
| 186 | /* This holds all the space in the subvectors of the charstarts field. */ | 1928 | #define IMAGE_FROM_ID(F, ID) \ |
| 187 | int *total_charstarts; | 1929 | (((ID) >= 0 && (ID) < (FRAME_X_IMAGE_CACHE (F)->used)) \ |
| 188 | }; | 1930 | ? FRAME_X_IMAGE_CACHE (F)->images[ID] \ |
| 1931 | : NULL) | ||
| 1932 | |||
| 1933 | /* Size of bucket vector of image caches. Should be prime. */ | ||
| 1934 | |||
| 1935 | #define IMAGE_CACHE_BUCKETS_SIZE 1001 | ||
| 1936 | |||
| 1937 | #endif /* HAVE_X_WINDOWS */ | ||
| 1938 | |||
| 1939 | |||
| 1940 | |||
| 1941 | /*********************************************************************** | ||
| 1942 | Toolbars | ||
| 1943 | ***********************************************************************/ | ||
| 1944 | |||
| 1945 | /* Enumeration defining where to find toolbar item information in | ||
| 1946 | toolbar items vectors stored with frames. Each toolbar item | ||
| 1947 | occupies TOOLBAR_ITEM_NSLOTS elements in such a vector. */ | ||
| 1948 | |||
| 1949 | enum toolbar_item_idx | ||
| 1950 | { | ||
| 1951 | /* The key of the toolbar item. Used to remove items when a binding | ||
| 1952 | for `undefined' is found. */ | ||
| 1953 | TOOLBAR_ITEM_KEY, | ||
| 1954 | |||
| 1955 | /* Non-nil if item is enabled. */ | ||
| 1956 | TOOLBAR_ITEM_ENABLED_P, | ||
| 1957 | |||
| 1958 | /* Non-nil if item is selected (pressed). */ | ||
| 1959 | TOOLBAR_ITEM_SELECTED_P, | ||
| 1960 | |||
| 1961 | /* Caption. */ | ||
| 1962 | TOOLBAR_ITEM_CAPTION, | ||
| 1963 | |||
| 1964 | /* Image(s) to display. This is either a single image specification | ||
| 1965 | or a vector of specifications. */ | ||
| 1966 | TOOLBAR_ITEM_IMAGES, | ||
| 1967 | |||
| 1968 | /* The binding. */ | ||
| 1969 | TOOLBAR_ITEM_BINDING, | ||
| 1970 | |||
| 1971 | /* Button type. One of nil, `:radio' or `:toggle'. */ | ||
| 1972 | TOOLBAR_ITEM_TYPE, | ||
| 189 | 1973 | ||
| 1974 | /* Help string. */ | ||
| 1975 | TOOLBAR_ITEM_HELP, | ||
| 1976 | |||
| 1977 | /* Sentinel = number of slots in toolbar_items occupied by one | ||
| 1978 | toolbar item. */ | ||
| 1979 | TOOLBAR_ITEM_NSLOTS | ||
| 1980 | }; | ||
| 1981 | |||
| 1982 | |||
| 1983 | /* An enumeration for the different images that can be specified | ||
| 1984 | for a toolbar item. */ | ||
| 1985 | |||
| 1986 | enum toolbar_item_image | ||
| 1987 | { | ||
| 1988 | TOOLBAR_IMAGE_ENABLED_SELECTED, | ||
| 1989 | TOOLBAR_IMAGE_ENABLED_DESELECTED, | ||
| 1990 | TOOLBAR_IMAGE_DISABLED_SELECTED, | ||
| 1991 | TOOLBAR_IMAGE_DISABLED_DESELECTED | ||
| 1992 | }; | ||
| 1993 | |||
| 1994 | /* Non-zero means raise toolbar buttons when the mouse moves over them. */ | ||
| 1995 | |||
| 1996 | extern int auto_raise_toolbar_buttons_p; | ||
| 1997 | |||
| 1998 | /* Margin around toolbar buttons in pixels. */ | ||
| 1999 | |||
| 2000 | extern int toolbar_button_margin; | ||
| 2001 | |||
| 2002 | /* Thickness of relief to draw around toolbar buttons. */ | ||
| 2003 | |||
| 2004 | extern int toolbar_button_relief; | ||
| 2005 | |||
| 2006 | |||
| 2007 | |||
| 2008 | /*********************************************************************** | ||
| 2009 | Function Prototypes | ||
| 2010 | ***********************************************************************/ | ||
| 2011 | |||
| 2012 | /* Defined in xdisp.c */ | ||
| 2013 | |||
| 2014 | int try_window P_ ((Lisp_Object, struct text_pos)); | ||
| 2015 | void window_box P_ ((struct window *, int, int *, int *, int *, int *)); | ||
| 2016 | int window_box_height P_ ((struct window *)); | ||
| 2017 | int window_text_bottom_y P_ ((struct window *)); | ||
| 2018 | int window_box_width P_ ((struct window *, int)); | ||
| 2019 | int window_box_left P_ ((struct window *, int)); | ||
| 2020 | int window_box_right P_ ((struct window *, int)); | ||
| 2021 | void window_box_edges P_ ((struct window *, int, int *, int *, int *, int *)); | ||
| 2022 | void mark_window_display_accurate P_ ((Lisp_Object, int)); | ||
| 2023 | void redisplay_preserve_echo_area P_ ((void)); | ||
| 2024 | void set_cursor_from_row P_ ((struct window *, struct glyph_row *, | ||
| 2025 | struct glyph_matrix *, int, int, int, int)); | ||
| 2026 | void init_iterator P_ ((struct it *, struct window *, int, | ||
| 2027 | int, struct glyph_row *, enum face_id)); | ||
| 2028 | void init_iterator_to_row_start P_ ((struct it *, struct window *, | ||
| 2029 | struct glyph_row *)); | ||
| 2030 | int get_next_display_element P_ ((struct it *)); | ||
| 2031 | void set_iterator_to_next P_ ((struct it *)); | ||
| 2032 | void produce_glyphs P_ ((struct it *)); | ||
| 2033 | void produce_special_glyphs P_ ((struct it *, enum display_element_type)); | ||
| 2034 | void start_display P_ ((struct it *, struct window *, struct text_pos)); | ||
| 2035 | void move_it_to P_ ((struct it *, int, int, int, int, int)); | ||
| 2036 | void move_it_vertically P_ ((struct it *, int)); | ||
| 2037 | void move_it_by_lines P_ ((struct it *, int, int)); | ||
| 2038 | int frame_mode_line_height P_ ((struct frame *)); | ||
| 2039 | void highlight_trailing_whitespace P_ ((struct frame *, struct glyph_row *)); | ||
| 2040 | int toolbar_item_info P_ ((struct frame *, struct glyph *, int *)); | ||
| 2041 | extern Lisp_Object Qtoolbar; | ||
| 2042 | extern int redisplaying_p; | ||
| 2043 | |||
| 2044 | /* Defined in sysdep.c */ | ||
| 2045 | |||
| 2046 | void get_frame_size P_ ((int *, int *)); | ||
| 2047 | void request_sigio P_ ((void)); | ||
| 2048 | void unrequest_sigio P_ ((void)); | ||
| 2049 | int tabs_safe_p P_ ((void)); | ||
| 2050 | void init_baud_rate P_ ((void)); | ||
| 2051 | void init_sigio P_ ((int)); | ||
| 2052 | |||
| 2053 | /* Defined in xface.c */ | ||
| 2054 | |||
| 2055 | char *x_charset_registry P_ ((int)); | ||
| 2056 | void clear_face_cache P_ ((int)); | ||
| 2057 | void unload_color P_ ((struct frame *, unsigned long)); | ||
| 2058 | int frame_update_line_height P_ ((struct frame *)); | ||
| 2059 | int ascii_face_of_lisp_face P_ ((struct frame *, int)); | ||
| 2060 | void prepare_face_for_display P_ ((struct frame *, struct face *)); | ||
| 2061 | int face_suitable_for_iso8859_1_p P_ ((struct face *)); | ||
| 2062 | int xstricmp P_ ((unsigned char *, unsigned char *)); | ||
| 2063 | int lookup_face P_ ((struct frame *, Lisp_Object *, int)); | ||
| 2064 | int face_suitable_for_charset_p P_ ((struct face *, int)); | ||
| 2065 | int lookup_named_face P_ ((struct frame *, Lisp_Object, int)); | ||
| 2066 | int smaller_face P_ ((struct frame *, int, int)); | ||
| 2067 | int face_with_height P_ ((struct frame *, int, int)); | ||
| 2068 | void init_frame_faces P_ ((struct frame *)); | ||
| 2069 | void free_frame_faces P_ ((struct frame *)); | ||
| 2070 | void recompute_basic_faces P_ ((struct frame *)); | ||
| 2071 | int face_at_buffer_position P_ ((struct window *, int, int, int, int *, | ||
| 2072 | int, int)); | ||
| 2073 | int face_at_string_position P_ ((struct window *, Lisp_Object, | ||
| 2074 | int, int, int, int, int *, enum face_id)); | ||
| 2075 | int compute_char_face P_ ((struct frame *, int, Lisp_Object)); | ||
| 2076 | void free_all_realized_faces P_ ((Lisp_Object)); | ||
| 2077 | extern Lisp_Object Qforeground_color, Qbackground_color; | ||
| 2078 | |||
| 2079 | /* Defined in xfns.c */ | ||
| 2080 | |||
| 2081 | #ifdef HAVE_X_WINDOWS | ||
| 2082 | |||
| 2083 | int x_screen_planes P_ ((struct frame *)); | ||
| 2084 | void x_implicitly_set_name P_ ((struct frame *, Lisp_Object, Lisp_Object)); | ||
| 2085 | struct image_cache *make_image_cache P_ ((void)); | ||
| 2086 | void free_image_cache P_ ((struct frame *)); | ||
| 2087 | void clear_image_cache P_ ((struct frame *, int)); | ||
| 2088 | void forall_images_in_image_cache P_ ((struct frame *, | ||
| 2089 | void (*) P_ ((struct image *)))); | ||
| 2090 | int valid_image_p P_ ((Lisp_Object)); | ||
| 2091 | void prepare_image_for_display P_ ((struct frame *, struct image *)); | ||
| 2092 | int lookup_image P_ ((struct frame *, Lisp_Object)); | ||
| 2093 | extern struct frame *tip_frame; | ||
| 2094 | extern Window tip_window; | ||
| 2095 | EXFUN (Fx_show_tip, 4); | ||
| 2096 | EXFUN (Fx_hide_tip, 0); | ||
| 2097 | EXFUN (Fx_show_busy_cursor, 0); | ||
| 2098 | EXFUN (Fx_hide_busy_cursor, 1); | ||
| 2099 | extern int inhibit_busy_cursor; | ||
| 2100 | extern int display_busy_cursor_p; | ||
| 2101 | |||
| 2102 | #endif /* HAVE_X_WINDOWS */ | ||
| 2103 | |||
| 2104 | |||
| 2105 | /* Defined in xmenu.c */ | ||
| 2106 | |||
| 2107 | int popup_activated P_ ((void)); | ||
| 2108 | |||
| 2109 | /* Defined in dispnw.c */ | ||
| 2110 | |||
| 2111 | Lisp_Object mode_line_string P_ ((struct window *, int, int, int, int *)); | ||
| 190 | extern void redraw_frame P_ ((struct frame *)); | 2112 | extern void redraw_frame P_ ((struct frame *)); |
| 191 | extern void redraw_garbaged_frames P_ ((void)); | 2113 | extern void redraw_garbaged_frames P_ ((void)); |
| 192 | extern void free_frame_glyphs P_ ((struct frame *, struct frame_glyphs *)); | ||
| 193 | extern void remake_frame_glyphs P_ ((struct frame *)); | ||
| 194 | extern void cancel_line P_ ((int, struct frame *)); | 2114 | extern void cancel_line P_ ((int, struct frame *)); |
| 195 | extern void clear_frame_records P_ ((struct frame *)); | ||
| 196 | extern void init_desired_glyphs P_ ((struct frame *)); | 2115 | extern void init_desired_glyphs P_ ((struct frame *)); |
| 197 | extern void get_display_line P_ ((struct frame *, int, int)); | ||
| 198 | extern int scroll_frame_lines P_ ((struct frame *, int, int, int, int)); | 2116 | extern int scroll_frame_lines P_ ((struct frame *, int, int, int, int)); |
| 199 | extern void preserve_other_columns P_ ((struct window *)); | ||
| 200 | extern void adjust_window_charstarts P_ ((struct window *, int, int)); | ||
| 201 | extern void verify_charstarts P_ ((struct window *)); | ||
| 202 | extern void cancel_my_columns P_ ((struct window *)); | ||
| 203 | extern int direct_output_for_insert P_ ((int)); | 2117 | extern int direct_output_for_insert P_ ((int)); |
| 204 | extern int direct_output_forward_char P_ ((int)); | 2118 | extern int direct_output_forward_char P_ ((int)); |
| 205 | extern int update_frame P_ ((struct frame *, int, int)); | 2119 | extern int update_frame P_ ((struct frame *, int, int)); |
| 206 | extern void quit_error_check P_ ((void)); | ||
| 207 | extern int scrolling P_ ((struct frame *)); | 2120 | extern int scrolling P_ ((struct frame *)); |
| 208 | extern int buffer_posn_from_coords P_ ((struct window *, int, int)); | ||
| 209 | extern void do_pending_window_change P_ ((void)); | 2121 | extern void do_pending_window_change P_ ((void)); |
| 210 | extern void change_frame_size P_ ((struct frame *, int, int, int, int)); | 2122 | extern void change_frame_size P_ ((struct frame *, int, int, int, int)); |
| 211 | extern void bitch_at_user P_ ((void)); | 2123 | extern void bitch_at_user P_ ((void)); |
| 2124 | void adjust_glyphs P_ ((struct frame *)); | ||
| 2125 | void free_glyphs P_ ((struct frame *)); | ||
| 2126 | void free_window_matrices P_ ((struct window *)); | ||
| 2127 | void check_glyph_memory P_ ((void)); | ||
| 2128 | void mirrored_line_dance P_ ((struct glyph_matrix *, int, int, int *, char *)); | ||
| 2129 | void clear_glyph_matrix P_ ((struct glyph_matrix *)); | ||
| 2130 | void clear_current_matrices P_ ((struct frame *f)); | ||
| 2131 | void clear_desired_matrices P_ ((struct frame *)); | ||
| 2132 | void shift_glyph_matrix P_ ((struct window *, struct glyph_matrix *, | ||
| 2133 | int, int, int)); | ||
| 2134 | void rotate_matrix P_ ((struct glyph_matrix *, int, int, int)); | ||
| 2135 | void increment_glyph_matrix_buffer_positions P_ ((struct glyph_matrix *, | ||
| 2136 | int, int, int, int)); | ||
| 2137 | void blank_row P_ ((struct window *, struct glyph_row *, int)); | ||
| 2138 | void increment_glyph_row_buffer_positions P_ ((struct glyph_row *, int, int)); | ||
| 2139 | void enable_glyph_matrix_rows P_ ((struct glyph_matrix *, int, int, int)); | ||
| 2140 | void clear_glyph_row P_ ((struct glyph_row *)); | ||
| 2141 | void prepare_desired_row P_ ((struct glyph_row *)); | ||
| 2142 | int line_hash_code P_ ((struct glyph_row *)); | ||
| 2143 | void set_window_update_flags P_ ((struct window *, int)); | ||
| 2144 | void write_glyphs P_ ((struct glyph *, int)); | ||
| 2145 | void insert_glyphs P_ ((struct glyph *, int)); | ||
| 2146 | void redraw_frame P_ ((struct frame *)); | ||
| 2147 | void redraw_garbaged_frames P_ ((void)); | ||
| 2148 | int scroll_cost P_ ((struct frame *, int, int, int)); | ||
| 2149 | int direct_output_for_insert P_ ((int)); | ||
| 2150 | int direct_output_forward_char P_ ((int)); | ||
| 2151 | int update_frame P_ ((struct frame *, int, int)); | ||
| 2152 | void update_single_window P_ ((struct window *, int)); | ||
| 2153 | int scrolling P_ ((struct frame *)); | ||
| 2154 | int buffer_posn_from_coords P_ ((struct window *, int *, int *)); | ||
| 2155 | void do_pending_window_change P_ ((void)); | ||
| 2156 | void change_frame_size P_ ((struct frame *, int, int, int, int)); | ||
| 2157 | void bitch_at_user P_ ((void)); | ||
| 2158 | Lisp_Object sit_for P_ ((int, int, int, int, int)); | ||
| 2159 | void init_display P_ ((void)); | ||
| 2160 | void syms_of_display P_ ((void)); | ||
| 212 | 2161 | ||
| 213 | /* Defined in term.c */ | 2162 | /* Defined in term.c */ |
| 2163 | |||
| 214 | extern void ring_bell P_ ((void)); | 2164 | extern void ring_bell P_ ((void)); |
| 215 | extern void set_terminal_modes P_ ((void)); | 2165 | extern void set_terminal_modes P_ ((void)); |
| 216 | extern void reset_terminal_modes P_ ((void)); | 2166 | extern void reset_terminal_modes P_ ((void)); |
| @@ -222,13 +2172,9 @@ extern void turn_off_insert P_ ((void)); | |||
| 222 | extern void turn_off_highlight P_ ((void)); | 2172 | extern void turn_off_highlight P_ ((void)); |
| 223 | extern void background_highlight P_ ((void)); | 2173 | extern void background_highlight P_ ((void)); |
| 224 | extern void reassert_line_highlight P_ ((int, int)); | 2174 | extern void reassert_line_highlight P_ ((int, int)); |
| 225 | extern void change_line_highlight P_ ((int, int, int)); | ||
| 226 | extern void cursor_to P_ ((int, int)); | ||
| 227 | extern void clear_frame P_ ((void)); | 2175 | extern void clear_frame P_ ((void)); |
| 228 | extern void clear_end_of_line P_ ((int)); | 2176 | extern void clear_end_of_line P_ ((int)); |
| 229 | extern void clear_end_of_line_raw P_ ((int)); | 2177 | extern void clear_end_of_line_raw P_ ((int)); |
| 230 | extern void write_glyphs P_ ((GLYPH *, int)); | ||
| 231 | extern void insert_glyphs P_ ((GLYPH *, int)); | ||
| 232 | extern void delete_glyphs P_ ((int)); | 2178 | extern void delete_glyphs P_ ((int)); |
| 233 | extern void ins_del_lines P_ ((int, int)); | 2179 | extern void ins_del_lines P_ ((int, int)); |
| 234 | extern int string_cost P_ ((char *)); | 2180 | extern int string_cost P_ ((char *)); |
| @@ -236,12 +2182,17 @@ extern int per_line_cost P_ ((char *)); | |||
| 236 | extern void calculate_costs P_ ((struct frame *)); | 2182 | extern void calculate_costs P_ ((struct frame *)); |
| 237 | extern void term_init P_ ((char *)); | 2183 | extern void term_init P_ ((char *)); |
| 238 | extern void fatal P_ ((/* char *, ... */)); | 2184 | extern void fatal P_ ((/* char *, ... */)); |
| 2185 | void cursor_to P_ ((int, int)); | ||
| 2186 | void change_line_highlight P_ ((int, int, int, int)); | ||
| 239 | 2187 | ||
| 240 | /* Defined in scroll.c */ | 2188 | /* Defined in scroll.c */ |
| 2189 | |||
| 241 | extern int scrolling_max_lines_saved P_ ((int, int, int *, int *, int *)); | 2190 | extern int scrolling_max_lines_saved P_ ((int, int, int *, int *, int *)); |
| 242 | extern int scroll_cost P_ ((struct frame *, int, int, int)); | 2191 | extern int scroll_cost P_ ((struct frame *, int, int, int)); |
| 243 | extern void do_line_insertion_deletion_costs P_ ((struct frame *, char *, | 2192 | extern void do_line_insertion_deletion_costs P_ ((struct frame *, char *, |
| 244 | char *, char *, char *, | 2193 | char *, char *, char *, |
| 245 | char *, char *, int)); | 2194 | char *, char *, int)); |
| 2195 | void scrolling_1 P_ ((struct frame *, int, int, int, int *, int *, int *, | ||
| 2196 | int *, int)); | ||
| 246 | 2197 | ||
| 247 | #endif /* not _DISPEXTERN_H_ */ | 2198 | #endif /* not DISPEXTERN_H_INCLUDED */ |
diff --git a/src/dispnew.c b/src/dispnew.c index a468e6ea55c..1f5eb937c7a 100644 --- a/src/dispnew.c +++ b/src/dispnew.c | |||
| @@ -19,11 +19,8 @@ along with GNU Emacs; see the file COPYING. If not, write to | |||
| 19 | the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | 19 | the Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
| 20 | Boston, MA 02111-1307, USA. */ | 20 | Boston, MA 02111-1307, USA. */ |
| 21 | 21 | ||
| 22 | |||
| 23 | #include <signal.h> | 22 | #include <signal.h> |
| 24 | |||
| 25 | #include <config.h> | 23 | #include <config.h> |
| 26 | |||
| 27 | #include <stdio.h> | 24 | #include <stdio.h> |
| 28 | #include <ctype.h> | 25 | #include <ctype.h> |
| 29 | 26 | ||
| @@ -57,29 +54,36 @@ Boston, MA 02111-1307, USA. */ | |||
| 57 | 54 | ||
| 58 | #ifdef HAVE_X_WINDOWS | 55 | #ifdef HAVE_X_WINDOWS |
| 59 | #include "xterm.h" | 56 | #include "xterm.h" |
| 60 | #endif /* HAVE_X_WINDOWS */ | 57 | #endif /* HAVE_X_WINDOWS */ |
| 61 | 58 | ||
| 62 | #ifdef HAVE_NTGUI | 59 | #ifdef HAVE_NTGUI |
| 63 | #include "w32term.h" | 60 | #include "w32term.h" |
| 64 | #endif /* HAVE_NTGUI */ | 61 | #endif /* HAVE_NTGUI */ |
| 65 | 62 | ||
| 66 | /* Include systime.h after xterm.h to avoid double inclusion of time.h. */ | 63 | /* Include systime.h after xterm.h to avoid double inclusion of time.h. */ |
| 67 | #include "systime.h" | ||
| 68 | 64 | ||
| 65 | #include "systime.h" | ||
| 69 | #include <errno.h> | 66 | #include <errno.h> |
| 70 | 67 | ||
| 68 | /* To get the prototype for `sleep'. */ | ||
| 69 | |||
| 70 | #ifdef HAVE_UNISTD_H | ||
| 71 | #include <unistd.h> | ||
| 72 | #endif | ||
| 73 | |||
| 71 | #define max(a, b) ((a) > (b) ? (a) : (b)) | 74 | #define max(a, b) ((a) > (b) ? (a) : (b)) |
| 72 | #define min(a, b) ((a) < (b) ? (a) : (b)) | 75 | #define min(a, b) ((a) < (b) ? (a) : (b)) |
| 73 | #define minmax(floor, val, ceil) \ | ||
| 74 | ((val) < (floor) ? (floor) : (val) > (ceil) ? (ceil) : (val)) | ||
| 75 | 76 | ||
| 76 | /* Get number of chars of output now in the buffer of a stdio stream. | 77 | /* Get number of chars of output now in the buffer of a stdio stream. |
| 77 | This ought to be built in in stdio, but it isn't. | 78 | This ought to be built in in stdio, but it isn't. Some s- files |
| 78 | Some s- files override this because their stdio internals differ. */ | 79 | override this because their stdio internals differ. */ |
| 80 | |||
| 79 | #ifdef __GNU_LIBRARY__ | 81 | #ifdef __GNU_LIBRARY__ |
| 80 | /* The s- file might have overridden the definition with one that works for | 82 | |
| 81 | the system's C library. But we are using the GNU C library, so this is | 83 | /* The s- file might have overridden the definition with one that |
| 82 | the right definition for every system. */ | 84 | works for the system's C library. But we are using the GNU C |
| 85 | library, so this is the right definition for every system. */ | ||
| 86 | |||
| 83 | #ifdef GNU_LIBRARY_PENDING_OUTPUT_COUNT | 87 | #ifdef GNU_LIBRARY_PENDING_OUTPUT_COUNT |
| 84 | #define PENDING_OUTPUT_COUNT GNU_LIBRARY_PENDING_OUTPUT_COUNT | 88 | #define PENDING_OUTPUT_COUNT GNU_LIBRARY_PENDING_OUTPUT_COUNT |
| 85 | #else | 89 | #else |
| @@ -90,21 +94,98 @@ Boston, MA 02111-1307, USA. */ | |||
| 90 | #ifndef PENDING_OUTPUT_COUNT | 94 | #ifndef PENDING_OUTPUT_COUNT |
| 91 | #define PENDING_OUTPUT_COUNT(FILE) ((FILE)->_ptr - (FILE)->_base) | 95 | #define PENDING_OUTPUT_COUNT(FILE) ((FILE)->_ptr - (FILE)->_base) |
| 92 | #endif | 96 | #endif |
| 93 | #endif | 97 | #endif /* not __GNU_LIBRARY__ */ |
| 98 | |||
| 99 | |||
| 100 | /* Structure to pass dimensions around. Used for character bounding | ||
| 101 | boxes, glyph matrix dimensions and alike. */ | ||
| 102 | |||
| 103 | struct dim | ||
| 104 | { | ||
| 105 | int width; | ||
| 106 | int height; | ||
| 107 | }; | ||
| 94 | 108 | ||
| 95 | static void change_frame_size_1 (); | 109 | |
| 110 | /* Function prototypes. */ | ||
| 111 | |||
| 112 | static int count_blanks P_ ((struct glyph *, int)); | ||
| 113 | static int count_match P_ ((struct glyph *, struct glyph *, | ||
| 114 | struct glyph *, struct glyph *)); | ||
| 115 | static unsigned line_draw_cost P_ ((struct glyph_matrix *, int)); | ||
| 116 | static void update_frame_line P_ ((struct frame *, int)); | ||
| 117 | static struct dim allocate_matrices_for_frame_redisplay | ||
| 118 | P_ ((Lisp_Object, int, int, struct dim, int, int *)); | ||
| 119 | static void allocate_matrices_for_window_redisplay P_ ((struct window *, | ||
| 120 | struct dim)); | ||
| 121 | static int realloc_glyph_pool P_ ((struct glyph_pool *, struct dim)); | ||
| 122 | static void adjust_frame_glyphs P_ ((struct frame *)); | ||
| 123 | struct glyph_matrix *new_glyph_matrix P_ ((struct glyph_pool *)); | ||
| 124 | static void free_glyph_matrix P_ ((struct glyph_matrix *)); | ||
| 125 | static void adjust_glyph_matrix P_ ((struct window *, struct glyph_matrix *, | ||
| 126 | int, int, struct dim)); | ||
| 127 | static void change_frame_size_1 P_ ((struct frame *, int, int, int, int)); | ||
| 128 | static void swap_glyphs_in_rows P_ ((struct glyph_row *, struct glyph_row *)); | ||
| 129 | static void swap_glyph_pointers P_ ((struct glyph_row *, struct glyph_row *)); | ||
| 130 | static int glyph_row_slice_p P_ ((struct glyph_row *, struct glyph_row *)); | ||
| 131 | static void fill_up_frame_row_with_spaces P_ ((struct glyph_row *, int)); | ||
| 132 | static void build_frame_matrix_from_window_tree P_ ((struct glyph_matrix *, | ||
| 133 | struct window *)); | ||
| 134 | static void build_frame_matrix_from_leaf_window P_ ((struct glyph_matrix *, | ||
| 135 | struct window *)); | ||
| 136 | static struct glyph_pool *new_glyph_pool P_ ((void)); | ||
| 137 | static void free_glyph_pool P_ ((struct glyph_pool *)); | ||
| 138 | static void adjust_frame_glyphs_initially P_ ((void)); | ||
| 139 | static void adjust_frame_message_buffer P_ ((struct frame *)); | ||
| 140 | static void adjust_decode_mode_spec_buffer P_ ((struct frame *)); | ||
| 141 | static void fill_up_glyph_row_with_spaces P_ ((struct glyph_row *)); | ||
| 142 | static void build_frame_matrix P_ ((struct frame *)); | ||
| 143 | void clear_current_matrices P_ ((struct frame *)); | ||
| 144 | void scroll_glyph_matrix_range P_ ((struct glyph_matrix *, int, int, | ||
| 145 | int, int)); | ||
| 146 | static void clear_window_matrices P_ ((struct window *, int)); | ||
| 147 | static void fill_up_glyph_row_area_with_spaces P_ ((struct glyph_row *, int)); | ||
| 148 | static int scrolling_window P_ ((struct window *, int)); | ||
| 149 | static void update_window_line P_ ((struct window *, int)); | ||
| 150 | static void update_marginal_area P_ ((struct window *, int, int)); | ||
| 151 | static void update_text_area P_ ((struct window *, int)); | ||
| 152 | static void make_current P_ ((struct glyph_matrix *, struct glyph_matrix *, | ||
| 153 | int)); | ||
| 154 | static void mirror_make_current P_ ((struct window *, int)); | ||
| 155 | void check_window_matrix_pointers P_ ((struct window *)); | ||
| 156 | static void check_matrix_pointers P_ ((struct glyph_matrix *, | ||
| 157 | struct glyph_matrix *)); | ||
| 158 | static void mirror_line_dance P_ ((struct window *, int, int, int *, char *)); | ||
| 159 | static int update_window_tree P_ ((struct window *, int)); | ||
| 160 | static int update_window P_ ((struct window *, int)); | ||
| 161 | static int update_frame_1 P_ ((struct frame *, int, int)); | ||
| 162 | static void set_window_cursor_after_update P_ ((struct window *)); | ||
| 163 | static int row_equal_p P_ ((struct window *, struct glyph_row *, | ||
| 164 | struct glyph_row *)); | ||
| 165 | static void adjust_frame_glyphs_for_window_redisplay P_ ((struct frame *)); | ||
| 166 | static void adjust_frame_glyphs_for_frame_redisplay P_ ((struct frame *)); | ||
| 167 | static void reverse_rows P_ ((struct glyph_matrix *, int, int)); | ||
| 168 | static int margin_glyphs_to_reserve P_ ((struct window *, int, Lisp_Object)); | ||
| 169 | |||
| 170 | |||
| 171 | |||
| 172 | /* Non-zero means don't pause redisplay for pending input. (This is | ||
| 173 | for debugging and for a future implementation of EDT-like | ||
| 174 | scrolling. */ | ||
| 175 | |||
| 176 | int redisplay_dont_pause; | ||
| 96 | 177 | ||
| 97 | /* Nonzero upon entry to redisplay means do not assume anything about | 178 | /* Nonzero upon entry to redisplay means do not assume anything about |
| 98 | current contents of actual terminal frame; clear and redraw it. */ | 179 | current contents of actual terminal frame; clear and redraw it. */ |
| 99 | 180 | ||
| 100 | int frame_garbaged; | 181 | int frame_garbaged; |
| 101 | 182 | ||
| 102 | /* Nonzero means last display completed. Zero means it was preempted. */ | 183 | /* Nonzero means last display completed. Zero means it was preempted. */ |
| 103 | 184 | ||
| 104 | int display_completed; | 185 | int display_completed; |
| 105 | 186 | ||
| 106 | /* Lisp variable visible-bell; enables use of screen-flash | 187 | /* Lisp variable visible-bell; enables use of screen-flash instead of |
| 107 | instead of audible bell. */ | 188 | audible bell. */ |
| 108 | 189 | ||
| 109 | int visible_bell; | 190 | int visible_bell; |
| 110 | 191 | ||
| @@ -116,19 +197,23 @@ int inverse_video; | |||
| 116 | 197 | ||
| 117 | int baud_rate; | 198 | int baud_rate; |
| 118 | 199 | ||
| 119 | /* nil or a symbol naming the window system under which emacs is | 200 | /* Either nil or a symbol naming the window system under which Emacs |
| 120 | running ('x is the only current possibility). */ | 201 | is running. */ |
| 121 | 202 | ||
| 122 | Lisp_Object Vwindow_system; | 203 | Lisp_Object Vwindow_system; |
| 123 | 204 | ||
| 124 | /* Version number of X windows: 10, 11 or nil. */ | 205 | /* Version number of X windows: 10, 11 or nil. */ |
| 206 | |||
| 125 | Lisp_Object Vwindow_system_version; | 207 | Lisp_Object Vwindow_system_version; |
| 126 | 208 | ||
| 127 | /* Vector of glyph definitions. Indexed by glyph number, | 209 | /* Vector of glyph definitions. Indexed by glyph number, the contents |
| 128 | the contents are a string which is how to output the glyph. | 210 | are a string which is how to output the glyph. |
| 129 | 211 | ||
| 130 | If Vglyph_table is nil, a glyph is output by using its low 8 bits | 212 | If Vglyph_table is nil, a glyph is output by using its low 8 bits |
| 131 | as a character code. */ | 213 | as a character code. |
| 214 | |||
| 215 | This is an obsolete feature that is no longer used. The variable | ||
| 216 | is retained for compatibility. */ | ||
| 132 | 217 | ||
| 133 | Lisp_Object Vglyph_table; | 218 | Lisp_Object Vglyph_table; |
| 134 | 219 | ||
| @@ -136,1093 +221,4054 @@ Lisp_Object Vglyph_table; | |||
| 136 | 221 | ||
| 137 | Lisp_Object Vstandard_display_table; | 222 | Lisp_Object Vstandard_display_table; |
| 138 | 223 | ||
| 139 | /* Nonzero means reading single-character input with prompt | 224 | /* Nonzero means reading single-character input with prompt so put |
| 140 | so put cursor on minibuffer after the prompt. | 225 | cursor on mini-buffer after the prompt. positive means at end of |
| 141 | positive means at end of text in echo area; | 226 | text in echo area; negative means at beginning of line. */ |
| 142 | negative means at beginning of line. */ | 227 | |
| 143 | int cursor_in_echo_area; | 228 | int cursor_in_echo_area; |
| 144 | 229 | ||
| 145 | Lisp_Object Qdisplay_table; | 230 | Lisp_Object Qdisplay_table; |
| 231 | |||
| 146 | 232 | ||
| 147 | /* The currently selected frame. | 233 | /* The currently selected frame. In a single-frame version, this |
| 148 | In a single-frame version, this variable always holds the address of | 234 | variable always holds the address of the_only_frame. */ |
| 149 | the_only_frame. */ | ||
| 150 | 235 | ||
| 151 | FRAME_PTR selected_frame; | 236 | struct frame *selected_frame; |
| 152 | 237 | ||
| 153 | /* A frame which is not just a minibuffer, or 0 if there are no such | 238 | /* A frame which is not just a mini-buffer, or 0 if there are no such |
| 154 | frames. This is usually the most recent such frame that was | 239 | frames. This is usually the most recent such frame that was |
| 155 | selected. In a single-frame version, this variable always holds | 240 | selected. In a single-frame version, this variable always holds |
| 156 | the address of the_only_frame. */ | 241 | the address of the_only_frame. */ |
| 157 | FRAME_PTR last_nonminibuf_frame; | ||
| 158 | 242 | ||
| 159 | /* This is a vector, made larger whenever it isn't large enough, | 243 | struct frame *last_nonminibuf_frame; |
| 160 | which is used inside `update_frame' to hold the old contents | ||
| 161 | of the FRAME_PHYS_LINES of the frame being updated. */ | ||
| 162 | struct frame_glyphs **ophys_lines; | ||
| 163 | /* Length of vector currently allocated. */ | ||
| 164 | int ophys_lines_length; | ||
| 165 | 244 | ||
| 166 | FILE *termscript; /* Stdio stream being used for copy of all output. */ | 245 | /* Stdio stream being used for copy of all output. */ |
| 167 | 246 | ||
| 168 | struct cm Wcm; /* Structure for info on cursor positioning */ | 247 | FILE *termscript; |
| 169 | 248 | ||
| 170 | int delayed_size_change; /* 1 means SIGWINCH happened when not safe. */ | 249 | /* Structure for info on cursor positioning. */ |
| 171 | 250 | ||
| 172 | DEFUN ("redraw-frame", Fredraw_frame, Sredraw_frame, 1, 1, 0, | 251 | struct cm Wcm; |
| 173 | "Clear frame FRAME and output again what is supposed to appear on it.") | 252 | |
| 174 | (frame) | 253 | /* 1 means SIGWINCH happened when not safe. */ |
| 175 | Lisp_Object frame; | 254 | |
| 255 | int delayed_size_change; | ||
| 256 | |||
| 257 | /* 1 means glyph initialization has been completed at startup. */ | ||
| 258 | |||
| 259 | static int glyphs_initialized_initially_p; | ||
| 260 | |||
| 261 | /* Updated window if != 0. Set by update_window. */ | ||
| 262 | |||
| 263 | struct window *updated_window; | ||
| 264 | |||
| 265 | /* Glyph row updated in update_window_line, and area that is updated. */ | ||
| 266 | |||
| 267 | struct glyph_row *updated_row; | ||
| 268 | int updated_area; | ||
| 269 | |||
| 270 | /* A glyph for a space. */ | ||
| 271 | |||
| 272 | struct glyph space_glyph; | ||
| 273 | |||
| 274 | /* Non-zero means update has been performed directly, so that there's | ||
| 275 | no need for redisplay_internal to do much work. Set by | ||
| 276 | direct_output_for_insert. */ | ||
| 277 | |||
| 278 | int redisplay_performed_directly_p; | ||
| 279 | |||
| 280 | /* Counts of allocated structures. These counts serve to diagnose | ||
| 281 | memory leaks and double frees. */ | ||
| 282 | |||
| 283 | int glyph_matrix_count; | ||
| 284 | int glyph_pool_count; | ||
| 285 | |||
| 286 | /* If non-null, the frame whose frame matrices are manipulated. If | ||
| 287 | null, window matrices are worked on. */ | ||
| 288 | |||
| 289 | static struct frame *frame_matrix_frame; | ||
| 290 | |||
| 291 | /* Current interface for window-based redisplay. Set from init_xterm. | ||
| 292 | A null value means we are not using window-based redisplay. */ | ||
| 293 | |||
| 294 | struct redisplay_interface *rif; | ||
| 295 | |||
| 296 | /* Non-zero means that fonts have been loaded since the last glyph | ||
| 297 | matrix adjustments. Redisplay must stop, and glyph matrices must | ||
| 298 | be adjusted when this flag becomes non-zero during display. The | ||
| 299 | reason fonts can be loaded so late is that fonts of fontsets are | ||
| 300 | loaded on demand. */ | ||
| 301 | |||
| 302 | int fonts_changed_p; | ||
| 303 | |||
| 304 | /* Convert vpos and hpos from frame to window and vice versa. | ||
| 305 | This may only be used for terminal frames. */ | ||
| 306 | |||
| 307 | #if GLYPH_DEBUG | ||
| 308 | |||
| 309 | static int window_to_frame_vpos P_ ((struct window *, int)); | ||
| 310 | static int window_to_frame_hpos P_ ((struct window *, int)); | ||
| 311 | #define WINDOW_TO_FRAME_VPOS(W, VPOS) window_to_frame_vpos ((W), (VPOS)) | ||
| 312 | #define WINDOW_TO_FRAME_HPOS(W, HPOS) window_to_frame_hpos ((W), (HPOS)) | ||
| 313 | |||
| 314 | #else /* GLYPH_DEBUG == 0 */ | ||
| 315 | |||
| 316 | #define WINDOW_TO_FRAME_VPOS(W, VPOS) ((VPOS) + XFASTINT ((W)->top)) | ||
| 317 | #define WINDOW_TO_FRAME_HPOS(W, HPOS) ((HPOS) + XFASTINT ((W)->left)) | ||
| 318 | |||
| 319 | #endif /* GLYPH_DEBUG == 0 */ | ||
| 320 | |||
| 321 | |||
| 322 | /* Like bcopy except never gets confused by overlap. Let this be the | ||
| 323 | first function defined in this file, or change emacs.c where the | ||
| 324 | address of this function is used. */ | ||
| 325 | |||
| 326 | void | ||
| 327 | safe_bcopy (from, to, size) | ||
| 328 | char *from, *to; | ||
| 329 | int size; | ||
| 176 | { | 330 | { |
| 177 | FRAME_PTR f; | 331 | if (size <= 0 || from == to) |
| 332 | return; | ||
| 178 | 333 | ||
| 179 | CHECK_LIVE_FRAME (frame, 0); | 334 | /* If the source and destination don't overlap, then bcopy can |
| 180 | f = XFRAME (frame); | 335 | handle it. If they do overlap, but the destination is lower in |
| 336 | memory than the source, we'll assume bcopy can handle that. */ | ||
| 337 | if (to < from || from + size <= to) | ||
| 338 | bcopy (from, to, size); | ||
| 181 | 339 | ||
| 182 | /* Erase the frame and its glyph records--if it has any records. | 340 | /* Otherwise, we'll copy from the end. */ |
| 183 | It may have none, in the case of the terminal frame | 341 | else |
| 184 | that initially exists but is never used | ||
| 185 | when Emacs is using a window system. */ | ||
| 186 | if (FRAME_CURRENT_GLYPHS (f) != 0) | ||
| 187 | { | 342 | { |
| 188 | update_begin (f); | 343 | register char *endf = from + size; |
| 189 | if (FRAME_MSDOS_P (f)) | 344 | register char *endt = to + size; |
| 190 | set_terminal_modes (); | 345 | |
| 191 | clear_frame (); | 346 | /* If TO - FROM is large, then we should break the copy into |
| 192 | clear_frame_records (f); | 347 | nonoverlapping chunks of TO - FROM bytes each. However, if |
| 193 | update_end (f); | 348 | TO - FROM is small, then the bcopy function call overhead |
| 194 | fflush (stdout); | 349 | makes this not worth it. The crossover point could be about |
| 350 | anywhere. Since I don't think the obvious copy loop is too | ||
| 351 | bad, I'm trying to err in its favor. */ | ||
| 352 | if (to - from < 64) | ||
| 353 | { | ||
| 354 | do | ||
| 355 | *--endt = *--endf; | ||
| 356 | while (endf != from); | ||
| 357 | } | ||
| 358 | else | ||
| 359 | { | ||
| 360 | for (;;) | ||
| 361 | { | ||
| 362 | endt -= (to - from); | ||
| 363 | endf -= (to - from); | ||
| 364 | |||
| 365 | if (endt < to) | ||
| 366 | break; | ||
| 367 | |||
| 368 | bcopy (endf, endt, to - from); | ||
| 369 | } | ||
| 370 | |||
| 371 | /* If SIZE wasn't a multiple of TO - FROM, there will be a | ||
| 372 | little left over. The amount left over is (endt + (to - | ||
| 373 | from)) - to, which is endt - from. */ | ||
| 374 | bcopy (from, to, endt - from); | ||
| 375 | } | ||
| 195 | } | 376 | } |
| 377 | } | ||
| 196 | 378 | ||
| 197 | windows_or_buffers_changed++; | 379 | |
| 198 | /* Mark all windows as INaccurate, | 380 | |
| 199 | so that every window will have its redisplay done. */ | 381 | /*********************************************************************** |
| 200 | mark_window_display_accurate (FRAME_ROOT_WINDOW (f), 0); | 382 | Glyph Matrices |
| 201 | f->garbaged = 0; | 383 | ***********************************************************************/ |
| 202 | return Qnil; | 384 | |
| 385 | /* Allocate and return a glyph_matrix structure. POOL is the glyph | ||
| 386 | pool from which memory for the matrix should be allocated, or null | ||
| 387 | for window-based redisplay where no glyph pools are used. The | ||
| 388 | member `pool' of the glyph matrix structure returned is set to | ||
| 389 | POOL, the structure is otherwise zeroed. */ | ||
| 390 | |||
| 391 | struct glyph_matrix * | ||
| 392 | new_glyph_matrix (pool) | ||
| 393 | struct glyph_pool *pool; | ||
| 394 | { | ||
| 395 | struct glyph_matrix *result; | ||
| 396 | |||
| 397 | /* Allocate and clear. */ | ||
| 398 | result = (struct glyph_matrix *) xmalloc (sizeof *result); | ||
| 399 | bzero (result, sizeof *result); | ||
| 400 | |||
| 401 | /* Increment number of allocated matrices. This count is used | ||
| 402 | to detect memory leaks. */ | ||
| 403 | ++glyph_matrix_count; | ||
| 404 | |||
| 405 | /* Set pool and return. */ | ||
| 406 | result->pool = pool; | ||
| 407 | return result; | ||
| 203 | } | 408 | } |
| 204 | 409 | ||
| 205 | void | 410 | |
| 206 | redraw_frame (f) | 411 | /* Free glyph matrix MATRIX. Passing in a null MATRIX is allowed. |
| 207 | FRAME_PTR f; | 412 | |
| 413 | The global counter glyph_matrix_count is decremented when a matrix | ||
| 414 | is freed. If the count gets negative, more structures were freed | ||
| 415 | than allocated, i.e. one matrix was freed more than once or a bogus | ||
| 416 | pointer was passed to this function. | ||
| 417 | |||
| 418 | If MATRIX->pool is null, this means that the matrix manages its own | ||
| 419 | glyph memory---this is done for matrices on X frames. Freeing the | ||
| 420 | matrix also frees the glyph memory in this case. */ | ||
| 421 | |||
| 422 | static void | ||
| 423 | free_glyph_matrix (matrix) | ||
| 424 | struct glyph_matrix *matrix; | ||
| 208 | { | 425 | { |
| 209 | Lisp_Object frame; | 426 | if (matrix) |
| 210 | XSETFRAME (frame, f); | 427 | { |
| 211 | Fredraw_frame (frame); | 428 | int i; |
| 429 | |||
| 430 | /* Detect the case that more matrices are freed than were | ||
| 431 | allocated. */ | ||
| 432 | if (--glyph_matrix_count < 0) | ||
| 433 | abort (); | ||
| 434 | |||
| 435 | /* Free glyph memory if MATRIX owns it. */ | ||
| 436 | if (matrix->pool == NULL) | ||
| 437 | for (i = 0; i < matrix->rows_allocated; ++i) | ||
| 438 | xfree (matrix->rows[i].glyphs[LEFT_MARGIN_AREA]); | ||
| 439 | |||
| 440 | /* Free row structures and the matrix itself. */ | ||
| 441 | xfree (matrix->rows); | ||
| 442 | xfree (matrix); | ||
| 443 | } | ||
| 212 | } | 444 | } |
| 213 | 445 | ||
| 214 | DEFUN ("redraw-display", Fredraw_display, Sredraw_display, 0, 0, "", | 446 | |
| 215 | "Clear and redisplay all visible frames.") | 447 | /* Return the number of glyphs to reserve for a marginal area of |
| 216 | () | 448 | window W. TOTAL_GLYPHS is the number of glyphs in a complete |
| 449 | display line of window W. MARGIN gives the width of the marginal | ||
| 450 | area in canonical character units. MARGIN should be an integer | ||
| 451 | or a float. */ | ||
| 452 | |||
| 453 | static int | ||
| 454 | margin_glyphs_to_reserve (w, total_glyphs, margin) | ||
| 455 | struct window *w; | ||
| 456 | int total_glyphs; | ||
| 457 | Lisp_Object margin; | ||
| 217 | { | 458 | { |
| 218 | Lisp_Object tail, frame; | 459 | int n; |
| 219 | 460 | ||
| 220 | FOR_EACH_FRAME (tail, frame) | 461 | if (NUMBERP (margin)) |
| 221 | if (FRAME_VISIBLE_P (XFRAME (frame))) | 462 | { |
| 222 | Fredraw_frame (frame); | 463 | int width = XFASTINT (w->width); |
| 464 | double d = max (0, XFLOATINT (margin)); | ||
| 465 | d = min (width / 2 - 1, d); | ||
| 466 | n = (int) ((double) total_glyphs / width * d); | ||
| 467 | } | ||
| 468 | else | ||
| 469 | n = 0; | ||
| 223 | 470 | ||
| 224 | return Qnil; | 471 | return n; |
| 225 | } | 472 | } |
| 226 | 473 | ||
| 227 | /* This is used when frame_garbaged is set. | ||
| 228 | Redraw the individual frames marked as garbaged. */ | ||
| 229 | 474 | ||
| 230 | void | 475 | /* Adjust glyph matrix MATRIX on window W or on a frame to changed |
| 231 | redraw_garbaged_frames () | 476 | window sizes. |
| 477 | |||
| 478 | W is null if the function is called for a frame glyph matrix. | ||
| 479 | Otherwise it is the window MATRIX is a member of. X and Y are the | ||
| 480 | indices of the first column and row of MATRIX within the frame | ||
| 481 | matrix, if such a matrix exists. They are zero for purely | ||
| 482 | window-based redisplay. DIM is the needed size of the matrix. | ||
| 483 | |||
| 484 | In window-based redisplay, where no frame matrices exist, glyph | ||
| 485 | matrices manage their own glyph storage. Otherwise, they allocate | ||
| 486 | storage from a common frame glyph pool which can be found in | ||
| 487 | MATRIX->pool. | ||
| 488 | |||
| 489 | The reason for this memory management strategy is to avoid complete | ||
| 490 | frame redraws if possible. When we allocate from a common pool, a | ||
| 491 | change of the location or size of a sub-matrix within the pool | ||
| 492 | requires a complete redisplay of the frame because we cannot easily | ||
| 493 | make sure that the current matrices of all windows still agree with | ||
| 494 | what is displayed on the screen. While this is usually fast, it | ||
| 495 | leads to screen flickering. */ | ||
| 496 | |||
| 497 | static void | ||
| 498 | adjust_glyph_matrix (w, matrix, x, y, dim) | ||
| 499 | struct window *w; | ||
| 500 | struct glyph_matrix *matrix; | ||
| 501 | int x, y; | ||
| 502 | struct dim dim; | ||
| 232 | { | 503 | { |
| 233 | Lisp_Object tail, frame; | 504 | int i; |
| 505 | int new_rows; | ||
| 506 | int marginal_areas_changed_p = 0; | ||
| 507 | int top_line_changed_p = 0; | ||
| 508 | int top_line_p = 0; | ||
| 509 | int left = -1, right = -1; | ||
| 510 | int window_x, window_y, window_width, window_height; | ||
| 511 | |||
| 512 | /* See if W had a top line that has disappeared now, or vice versa. */ | ||
| 513 | if (w) | ||
| 514 | { | ||
| 515 | top_line_p = WINDOW_WANTS_TOP_LINE_P (w); | ||
| 516 | top_line_changed_p = top_line_p != matrix->top_line_p; | ||
| 517 | } | ||
| 518 | matrix->top_line_p = top_line_p; | ||
| 234 | 519 | ||
| 235 | FOR_EACH_FRAME (tail, frame) | 520 | /* Do nothing if MATRIX' size, position, vscroll, and marginal areas |
| 236 | if (FRAME_VISIBLE_P (XFRAME (frame)) | 521 | haven't changed. This optimization is important because preserving |
| 237 | && FRAME_GARBAGED_P (XFRAME (frame))) | 522 | the matrix means preventing redisplay. */ |
| 238 | Fredraw_frame (frame); | 523 | if (matrix->pool == NULL) |
| 524 | { | ||
| 525 | window_box (w, -1, &window_x, &window_y, &window_width, &window_height); | ||
| 526 | left = margin_glyphs_to_reserve (w, dim.width, w->left_margin_width); | ||
| 527 | right = margin_glyphs_to_reserve (w, dim.width, w->right_margin_width); | ||
| 528 | xassert (left >= 0 && right >= 0); | ||
| 529 | marginal_areas_changed_p = (left != matrix->left_margin_glyphs | ||
| 530 | || right != matrix->right_margin_glyphs); | ||
| 531 | |||
| 532 | if (!marginal_areas_changed_p | ||
| 533 | && !fonts_changed_p | ||
| 534 | && !top_line_changed_p | ||
| 535 | && matrix->window_top_y == XFASTINT (w->top) | ||
| 536 | && matrix->window_height == window_height | ||
| 537 | && matrix->window_vscroll == w->vscroll | ||
| 538 | && matrix->window_width == window_width) | ||
| 539 | return; | ||
| 540 | } | ||
| 541 | |||
| 542 | /* Enlarge MATRIX->rows if necessary. New rows are cleared. */ | ||
| 543 | if (matrix->rows_allocated < dim.height) | ||
| 544 | { | ||
| 545 | int size = dim.height * sizeof (struct glyph_row); | ||
| 546 | new_rows = dim.height - matrix->rows_allocated; | ||
| 547 | matrix->rows = (struct glyph_row *) xrealloc (matrix->rows, size); | ||
| 548 | bzero (matrix->rows + matrix->rows_allocated, | ||
| 549 | new_rows * sizeof *matrix->rows); | ||
| 550 | matrix->rows_allocated = dim.height; | ||
| 551 | } | ||
| 552 | else | ||
| 553 | new_rows = 0; | ||
| 554 | |||
| 555 | /* If POOL is not null, MATRIX is a frame matrix or a window matrix | ||
| 556 | on a frame not using window-based redisplay. Set up pointers for | ||
| 557 | each row into the glyph pool. */ | ||
| 558 | if (matrix->pool) | ||
| 559 | { | ||
| 560 | xassert (matrix->pool->glyphs); | ||
| 561 | |||
| 562 | if (w) | ||
| 563 | { | ||
| 564 | left = margin_glyphs_to_reserve (w, dim.width, | ||
| 565 | w->left_margin_width); | ||
| 566 | right = margin_glyphs_to_reserve (w, dim.width, | ||
| 567 | w->right_margin_width); | ||
| 568 | } | ||
| 569 | else | ||
| 570 | left = right = 0; | ||
| 571 | |||
| 572 | for (i = 0; i < dim.height; ++i) | ||
| 573 | { | ||
| 574 | struct glyph_row *row = &matrix->rows[i]; | ||
| 575 | |||
| 576 | row->glyphs[LEFT_MARGIN_AREA] | ||
| 577 | = (matrix->pool->glyphs | ||
| 578 | + (y + i) * matrix->pool->ncolumns | ||
| 579 | + x); | ||
| 580 | |||
| 581 | if (w == NULL | ||
| 582 | || row == matrix->rows + dim.height - 1 | ||
| 583 | || (row == matrix->rows && matrix->top_line_p)) | ||
| 584 | { | ||
| 585 | row->glyphs[TEXT_AREA] | ||
| 586 | = row->glyphs[LEFT_MARGIN_AREA]; | ||
| 587 | row->glyphs[RIGHT_MARGIN_AREA] | ||
| 588 | = row->glyphs[TEXT_AREA] + dim.width; | ||
| 589 | row->glyphs[LAST_AREA] | ||
| 590 | = row->glyphs[RIGHT_MARGIN_AREA]; | ||
| 591 | } | ||
| 592 | else | ||
| 593 | { | ||
| 594 | row->glyphs[TEXT_AREA] | ||
| 595 | = row->glyphs[LEFT_MARGIN_AREA] + left; | ||
| 596 | row->glyphs[RIGHT_MARGIN_AREA] | ||
| 597 | = row->glyphs[TEXT_AREA] + dim.width - left - right; | ||
| 598 | row->glyphs[LAST_AREA] | ||
| 599 | = row->glyphs[LEFT_MARGIN_AREA] + dim.width; | ||
| 600 | } | ||
| 601 | } | ||
| 602 | |||
| 603 | matrix->left_margin_glyphs = left; | ||
| 604 | matrix->right_margin_glyphs = right; | ||
| 605 | } | ||
| 606 | else | ||
| 607 | { | ||
| 608 | /* If MATRIX->pool is null, MATRIX is responsible for managing | ||
| 609 | its own memory. Allocate glyph memory from the heap. */ | ||
| 610 | if (dim.width > matrix->matrix_w | ||
| 611 | || new_rows | ||
| 612 | || top_line_changed_p | ||
| 613 | || marginal_areas_changed_p) | ||
| 614 | { | ||
| 615 | struct glyph_row *row = matrix->rows; | ||
| 616 | struct glyph_row *end = row + matrix->rows_allocated; | ||
| 617 | |||
| 618 | while (row < end) | ||
| 619 | { | ||
| 620 | row->glyphs[LEFT_MARGIN_AREA] | ||
| 621 | = (struct glyph *) xrealloc (row->glyphs[LEFT_MARGIN_AREA], | ||
| 622 | (dim.width | ||
| 623 | * sizeof (struct glyph))); | ||
| 624 | |||
| 625 | /* The mode line never has marginal areas. */ | ||
| 626 | if (row == matrix->rows + dim.height - 1 | ||
| 627 | || (row == matrix->rows && matrix->top_line_p)) | ||
| 628 | { | ||
| 629 | row->glyphs[TEXT_AREA] | ||
| 630 | = row->glyphs[LEFT_MARGIN_AREA]; | ||
| 631 | row->glyphs[RIGHT_MARGIN_AREA] | ||
| 632 | = row->glyphs[TEXT_AREA] + dim.width; | ||
| 633 | row->glyphs[LAST_AREA] | ||
| 634 | = row->glyphs[RIGHT_MARGIN_AREA]; | ||
| 635 | } | ||
| 636 | else | ||
| 637 | { | ||
| 638 | row->glyphs[TEXT_AREA] | ||
| 639 | = row->glyphs[LEFT_MARGIN_AREA] + left; | ||
| 640 | row->glyphs[RIGHT_MARGIN_AREA] | ||
| 641 | = row->glyphs[TEXT_AREA] + dim.width - left - right; | ||
| 642 | row->glyphs[LAST_AREA] | ||
| 643 | = row->glyphs[LEFT_MARGIN_AREA] + dim.width; | ||
| 644 | } | ||
| 645 | ++row; | ||
| 646 | } | ||
| 647 | } | ||
| 648 | |||
| 649 | xassert (left >= 0 && right >= 0); | ||
| 650 | matrix->left_margin_glyphs = left; | ||
| 651 | matrix->right_margin_glyphs = right; | ||
| 652 | } | ||
| 653 | |||
| 654 | /* Number of rows to be used by MATRIX. */ | ||
| 655 | matrix->nrows = dim.height; | ||
| 656 | |||
| 657 | /* Mark rows in a current matrix of a window as not having valid | ||
| 658 | contents. It's important to not do this for desired matrices. | ||
| 659 | When Emacs starts, it may already be building desired matrices | ||
| 660 | when this function runs. */ | ||
| 661 | if (w && matrix == w->current_matrix) | ||
| 662 | { | ||
| 663 | /* Optimize the case that only the height has changed (C-x 2, | ||
| 664 | upper window). Invalidate all rows that are no longer part | ||
| 665 | of the window. */ | ||
| 666 | if (!marginal_areas_changed_p | ||
| 667 | && matrix->window_top_y == XFASTINT (w->top) | ||
| 668 | && matrix->window_width == window_width) | ||
| 669 | { | ||
| 670 | i = 0; | ||
| 671 | while (matrix->rows[i].enabled_p | ||
| 672 | && (MATRIX_ROW_BOTTOM_Y (matrix->rows + i) | ||
| 673 | < matrix->window_height)) | ||
| 674 | ++i; | ||
| 675 | |||
| 676 | /* Window end is invalid, if inside of the rows that | ||
| 677 | are invalidated. */ | ||
| 678 | if (INTEGERP (w->window_end_vpos) | ||
| 679 | && XFASTINT (w->window_end_vpos) >= i) | ||
| 680 | w->window_end_valid = Qnil; | ||
| 681 | |||
| 682 | while (i < matrix->nrows) | ||
| 683 | matrix->rows[i++].enabled_p = 0; | ||
| 684 | } | ||
| 685 | else | ||
| 686 | { | ||
| 687 | for (i = 0; i < matrix->nrows; ++i) | ||
| 688 | matrix->rows[i].enabled_p = 0; | ||
| 689 | } | ||
| 690 | } | ||
| 691 | |||
| 692 | /* Remember last values to be able to optimize frame redraws. */ | ||
| 693 | matrix->matrix_x = x; | ||
| 694 | matrix->matrix_y = y; | ||
| 695 | matrix->matrix_w = dim.width; | ||
| 696 | matrix->matrix_h = dim.height; | ||
| 697 | |||
| 698 | /* Record the top y location and height of W at the time the matrix | ||
| 699 | was last adjusted. This is used to optimize redisplay above. */ | ||
| 700 | if (w) | ||
| 701 | { | ||
| 702 | matrix->window_top_y = XFASTINT (w->top); | ||
| 703 | matrix->window_height = window_height; | ||
| 704 | matrix->window_width = window_width; | ||
| 705 | matrix->window_vscroll = w->vscroll; | ||
| 706 | } | ||
| 239 | } | 707 | } |
| 240 | 708 | ||
| 241 | 709 | ||
| 242 | static struct frame_glyphs * | 710 | /* Reverse the contents of rows in MATRIX between START and END. The |
| 243 | make_frame_glyphs (frame, empty) | 711 | contents of the row at END - 1 end up at START, END - 2 at START + |
| 244 | register FRAME_PTR frame; | 712 | 1 etc. This is part of the implementation of rotate_matrix (see |
| 245 | int empty; | 713 | below). */ |
| 714 | |||
| 715 | static void | ||
| 716 | reverse_rows (matrix, start, end) | ||
| 717 | struct glyph_matrix *matrix; | ||
| 718 | int start, end; | ||
| 246 | { | 719 | { |
| 247 | register int i; | 720 | int i, j; |
| 248 | register int width = FRAME_WINDOW_WIDTH (frame); | ||
| 249 | register int height = FRAME_HEIGHT (frame); | ||
| 250 | register struct frame_glyphs *new | ||
| 251 | = (struct frame_glyphs *) xmalloc (sizeof (struct frame_glyphs)); | ||
| 252 | |||
| 253 | SET_GLYPHS_FRAME (new, frame); | ||
| 254 | new->height = height; | ||
| 255 | new->width = width; | ||
| 256 | new->used = (int *) xmalloc (height * sizeof (int)); | ||
| 257 | new->glyphs = (GLYPH **) xmalloc (height * sizeof (GLYPH *)); | ||
| 258 | new->charstarts = (int **) xmalloc (height * sizeof (int *)); | ||
| 259 | new->highlight = (char *) xmalloc (height * sizeof (char)); | ||
| 260 | new->enable = (char *) xmalloc (height * sizeof (char)); | ||
| 261 | bzero (new->enable, height * sizeof (char)); | ||
| 262 | new->bufp = (int *) xmalloc (height * sizeof (int)); | ||
| 263 | 721 | ||
| 264 | #ifdef HAVE_WINDOW_SYSTEM | 722 | for (i = start, j = end - 1; i < j; ++i, --j) |
| 265 | if (FRAME_WINDOW_P (frame)) | ||
| 266 | { | 723 | { |
| 267 | new->top_left_x = (short *) xmalloc (height * sizeof (short)); | 724 | /* Non-ISO HP/UX compiler doesn't like auto struct |
| 268 | new->top_left_y = (short *) xmalloc (height * sizeof (short)); | 725 | initialization. */ |
| 269 | new->pix_width = (short *) xmalloc (height * sizeof (short)); | 726 | struct glyph_row temp; |
| 270 | new->pix_height = (short *) xmalloc (height * sizeof (short)); | 727 | temp = matrix->rows[i]; |
| 271 | new->max_ascent = (short *) xmalloc (height * sizeof (short)); | 728 | matrix->rows[i] = matrix->rows[j]; |
| 729 | matrix->rows[j] = temp; | ||
| 272 | } | 730 | } |
| 273 | #endif /* HAVE_WINDOW_SYSTEM */ | 731 | } |
| 732 | |||
| 274 | 733 | ||
| 275 | if (empty) | 734 | /* Rotate the contents of rows in MATRIX in the range FIRST .. LAST - |
| 735 | 1 by BY positions. BY < 0 means rotate left, i.e. towards lower | ||
| 736 | indices. (Note: this does not copy glyphs, only glyph pointers in | ||
| 737 | row structures are moved around). | ||
| 738 | |||
| 739 | The algorithm used for rotating the vector was, I believe, first | ||
| 740 | described by Kernighan. See the vector R as consisting of two | ||
| 741 | sub-vectors AB, where A has length BY for BY >= 0. The result | ||
| 742 | after rotating is then BA. Reverse both sub-vectors to get ArBr | ||
| 743 | and reverse the result to get (ArBr)r which is BA. Similar for | ||
| 744 | rotating right. */ | ||
| 745 | |||
| 746 | void | ||
| 747 | rotate_matrix (matrix, first, last, by) | ||
| 748 | struct glyph_matrix *matrix; | ||
| 749 | int first, last, by; | ||
| 750 | { | ||
| 751 | if (by < 0) | ||
| 752 | { | ||
| 753 | /* Up (rotate left, i.e. towards lower indices). */ | ||
| 754 | by = -by; | ||
| 755 | reverse_rows (matrix, first, first + by); | ||
| 756 | reverse_rows (matrix, first + by, last); | ||
| 757 | reverse_rows (matrix, first, last); | ||
| 758 | } | ||
| 759 | else if (by > 0) | ||
| 276 | { | 760 | { |
| 277 | /* Make the buffer used by decode_mode_spec. This buffer is also | 761 | /* Down (rotate right, i.e. towards higher indices). */ |
| 278 | used as temporary storage when updating the frame. See scroll.c. */ | 762 | reverse_rows (matrix, last - by, last); |
| 279 | unsigned int total_glyphs = (width + 2) * sizeof (GLYPH); | 763 | reverse_rows (matrix, first, last - by); |
| 280 | unsigned int total_charstarts = (width + 2) * sizeof (int); | 764 | reverse_rows (matrix, first, last); |
| 765 | } | ||
| 766 | } | ||
| 767 | |||
| 768 | |||
| 769 | /* Increment buffer positions in glyph rows of MATRIX. Do it for rows | ||
| 770 | with indices START <= index < END. Increment positions by DELTA/ | ||
| 771 | DELTA_BYTES. */ | ||
| 281 | 772 | ||
| 282 | new->total_contents = (GLYPH *) xmalloc (total_glyphs); | 773 | void |
| 283 | bzero (new->total_contents, total_glyphs); | 774 | increment_glyph_matrix_buffer_positions (matrix, start, end, delta, |
| 775 | delta_bytes) | ||
| 776 | struct glyph_matrix *matrix; | ||
| 777 | int start, end, delta, delta_bytes; | ||
| 778 | { | ||
| 779 | /* Check that START and END are reasonable values. */ | ||
| 780 | xassert (start >= 0 && start <= matrix->nrows); | ||
| 781 | xassert (end >= 0 && end <= matrix->nrows); | ||
| 782 | xassert (start <= end); | ||
| 783 | |||
| 784 | for (; start < end; ++start) | ||
| 785 | increment_glyph_row_buffer_positions (matrix->rows + start, | ||
| 786 | delta, delta_bytes); | ||
| 787 | } | ||
| 284 | 788 | ||
| 285 | new->total_charstarts = (int *) xmalloc (total_charstarts); | 789 | |
| 286 | bzero (new->total_charstarts, total_charstarts); | 790 | /* Enable a range of rows in glyph matrix MATRIX. START and END are |
| 791 | the row indices of the first and last + 1 row to enable. If | ||
| 792 | ENABLED_P is non-zero, enabled_p flags in rows will be set to 1. */ | ||
| 793 | |||
| 794 | void | ||
| 795 | enable_glyph_matrix_rows (matrix, start, end, enabled_p) | ||
| 796 | struct glyph_matrix *matrix; | ||
| 797 | int start, end; | ||
| 798 | int enabled_p; | ||
| 799 | { | ||
| 800 | xassert (start <= end); | ||
| 801 | xassert (start >= 0 && start < matrix->nrows); | ||
| 802 | xassert (end >= 0 && end <= matrix->nrows); | ||
| 803 | |||
| 804 | for (; start < end; ++start) | ||
| 805 | matrix->rows[start].enabled_p = enabled_p != 0; | ||
| 806 | } | ||
| 807 | |||
| 808 | |||
| 809 | /* Clear MATRIX. | ||
| 810 | |||
| 811 | This empties all rows in MATRIX by setting the enabled_p flag for | ||
| 812 | all rows of the matrix to zero. The function prepare_desired_row | ||
| 813 | will eventually really clear a row when it sees one with a zero | ||
| 814 | enabled_p flag. | ||
| 815 | |||
| 816 | Resets update hints to defaults value. The only update hint | ||
| 817 | currently present is the flag MATRIX->no_scrolling_p. */ | ||
| 818 | |||
| 819 | void | ||
| 820 | clear_glyph_matrix (matrix) | ||
| 821 | struct glyph_matrix *matrix; | ||
| 822 | { | ||
| 823 | if (matrix) | ||
| 824 | { | ||
| 825 | enable_glyph_matrix_rows (matrix, 0, matrix->nrows, 0); | ||
| 826 | matrix->no_scrolling_p = 0; | ||
| 287 | } | 827 | } |
| 288 | else | 828 | } |
| 829 | |||
| 830 | |||
| 831 | /* Shift part of the glyph matrix MATRIX of window W up or down. | ||
| 832 | Increment y-positions in glyph rows between START and END by DY, | ||
| 833 | and recompute their visible height. */ | ||
| 834 | |||
| 835 | void | ||
| 836 | shift_glyph_matrix (w, matrix, start, end, dy) | ||
| 837 | struct window *w; | ||
| 838 | struct glyph_matrix *matrix; | ||
| 839 | int start, end, dy; | ||
| 840 | { | ||
| 841 | int min_y, max_y; | ||
| 842 | |||
| 843 | xassert (start <= end); | ||
| 844 | xassert (start >= 0 && start < matrix->nrows); | ||
| 845 | xassert (end >= 0 && end <= matrix->nrows); | ||
| 846 | |||
| 847 | min_y = WINDOW_DISPLAY_TOP_LINE_HEIGHT (w); | ||
| 848 | max_y = WINDOW_DISPLAY_HEIGHT_NO_MODE_LINE (w); | ||
| 849 | |||
| 850 | for (; start < end; ++start) | ||
| 289 | { | 851 | { |
| 290 | unsigned int total_glyphs = height * (width + 2) * sizeof (GLYPH); | 852 | struct glyph_row *row = &matrix->rows[start]; |
| 853 | |||
| 854 | row->y += dy; | ||
| 855 | |||
| 856 | if (row->y < min_y) | ||
| 857 | row->visible_height = row->height - (min_y - row->y); | ||
| 858 | else if (row->y + row->height > max_y) | ||
| 859 | row->visible_height = row->height - (row->y + row->height - max_y); | ||
| 860 | else | ||
| 861 | row->visible_height = row->height; | ||
| 862 | } | ||
| 863 | } | ||
| 291 | 864 | ||
| 292 | new->total_contents = (GLYPH *) xmalloc (total_glyphs); | ||
| 293 | bzero (new->total_contents, total_glyphs); | ||
| 294 | for (i = 0; i < height; i++) | ||
| 295 | new->glyphs[i] = new->total_contents + i * (width + 2) + 1; | ||
| 296 | 865 | ||
| 297 | if (!FRAME_TERMCAP_P (frame)) | 866 | /* Mark all rows in current matrices of frame F as invalid. Marking |
| 298 | { | 867 | invalid is done by setting enabled_p to zero for all rows in a |
| 299 | unsigned int total_charstarts = height * (width + 2) * sizeof (int); | 868 | current matrix. */ |
| 869 | |||
| 870 | void | ||
| 871 | clear_current_matrices (f) | ||
| 872 | register struct frame *f; | ||
| 873 | { | ||
| 874 | /* Clear frame current matrix, if we have one. */ | ||
| 875 | if (f->current_matrix) | ||
| 876 | clear_glyph_matrix (f->current_matrix); | ||
| 877 | |||
| 878 | /* Clear the matrix of the menu bar window, if such a window exists. | ||
| 879 | The menu bar window is currently used to display menus on X when | ||
| 880 | no toolkit support is compiled in. */ | ||
| 881 | if (WINDOWP (f->menu_bar_window)) | ||
| 882 | clear_glyph_matrix (XWINDOW (f->menu_bar_window)->current_matrix); | ||
| 883 | |||
| 884 | /* Clear the matrix of the toolbar window, if any. */ | ||
| 885 | if (WINDOWP (f->toolbar_window)) | ||
| 886 | clear_glyph_matrix (XWINDOW (f->toolbar_window)->current_matrix); | ||
| 887 | |||
| 888 | /* Clear current window matrices. */ | ||
| 889 | xassert (WINDOWP (FRAME_ROOT_WINDOW (f))); | ||
| 890 | clear_window_matrices (XWINDOW (FRAME_ROOT_WINDOW (f)), 0); | ||
| 891 | } | ||
| 892 | |||
| 893 | |||
| 894 | /* Clear out all display lines of F for a coming redisplay. */ | ||
| 895 | |||
| 896 | void | ||
| 897 | clear_desired_matrices (f) | ||
| 898 | register struct frame *f; | ||
| 899 | { | ||
| 900 | if (f->desired_matrix) | ||
| 901 | clear_glyph_matrix (f->desired_matrix); | ||
| 902 | |||
| 903 | if (WINDOWP (f->menu_bar_window)) | ||
| 904 | clear_glyph_matrix (XWINDOW (f->menu_bar_window)->desired_matrix); | ||
| 905 | |||
| 906 | if (WINDOWP (f->toolbar_window)) | ||
| 907 | clear_glyph_matrix (XWINDOW (f->toolbar_window)->desired_matrix); | ||
| 908 | |||
| 909 | /* Do it for window matrices. */ | ||
| 910 | xassert (WINDOWP (FRAME_ROOT_WINDOW (f))); | ||
| 911 | clear_window_matrices (XWINDOW (FRAME_ROOT_WINDOW (f)), 1); | ||
| 912 | } | ||
| 913 | |||
| 300 | 914 | ||
| 301 | new->total_charstarts = (int *) xmalloc (total_charstarts); | 915 | /* Clear matrices in window tree rooted in W. If DESIRED_P is |
| 302 | bzero (new->total_charstarts, total_charstarts); | 916 | non-zero clear desired matrices, otherwise clear current matrices. */ |
| 303 | for (i = 0; i < height; i++) | 917 | |
| 304 | new->charstarts[i] = new->total_charstarts + i * (width + 2) + 1; | 918 | static void |
| 919 | clear_window_matrices (w, desired_p) | ||
| 920 | struct window *w; | ||
| 921 | int desired_p; | ||
| 922 | { | ||
| 923 | while (w) | ||
| 924 | { | ||
| 925 | if (!NILP (w->hchild)) | ||
| 926 | { | ||
| 927 | xassert (WINDOWP (w->hchild)); | ||
| 928 | clear_window_matrices (XWINDOW (w->hchild), desired_p); | ||
| 929 | } | ||
| 930 | else if (!NILP (w->vchild)) | ||
| 931 | { | ||
| 932 | xassert (WINDOWP (w->vchild)); | ||
| 933 | clear_window_matrices (XWINDOW (w->vchild), desired_p); | ||
| 305 | } | 934 | } |
| 306 | else | 935 | else |
| 307 | { | 936 | { |
| 308 | /* Without a window system, we don't really need charstarts. | 937 | if (desired_p) |
| 309 | So use a small amount of space to make enough data structure | 938 | clear_glyph_matrix (w->desired_matrix); |
| 310 | to prevent crashes in display_text_line. */ | 939 | else |
| 311 | new->total_charstarts = (int *) xmalloc ((width + 2) * sizeof (int)); | 940 | { |
| 312 | for (i = 0; i < height; i++) | 941 | clear_glyph_matrix (w->current_matrix); |
| 313 | new->charstarts[i] = new->total_charstarts; | 942 | w->window_end_valid = Qnil; |
| 943 | } | ||
| 314 | } | 944 | } |
| 945 | |||
| 946 | w = NILP (w->next) ? 0 : XWINDOW (w->next); | ||
| 315 | } | 947 | } |
| 948 | } | ||
| 949 | |||
| 950 | |||
| 951 | |||
| 952 | /*********************************************************************** | ||
| 953 | Glyph Rows | ||
| 954 | |||
| 955 | See dispextern.h for an overall explanation of glyph rows. | ||
| 956 | ***********************************************************************/ | ||
| 957 | |||
| 958 | /* Clear glyph row ROW. Do it in a way that makes it robust against | ||
| 959 | changes in the glyph_row structure, i.e. addition or removal of | ||
| 960 | structure members. */ | ||
| 961 | |||
| 962 | void | ||
| 963 | clear_glyph_row (row) | ||
| 964 | struct glyph_row *row; | ||
| 965 | { | ||
| 966 | struct glyph *p[1 + LAST_AREA]; | ||
| 967 | static struct glyph_row null_row; | ||
| 968 | |||
| 969 | /* Save pointers. */ | ||
| 970 | p[LEFT_MARGIN_AREA] = row->glyphs[LEFT_MARGIN_AREA]; | ||
| 971 | p[TEXT_AREA] = row->glyphs[TEXT_AREA]; | ||
| 972 | p[RIGHT_MARGIN_AREA] = row->glyphs[RIGHT_MARGIN_AREA]; | ||
| 973 | p[LAST_AREA] = row->glyphs[LAST_AREA]; | ||
| 974 | |||
| 975 | /* Clear. */ | ||
| 976 | *row = null_row; | ||
| 977 | |||
| 978 | /* Restore pointers. */ | ||
| 979 | row->glyphs[LEFT_MARGIN_AREA] = p[LEFT_MARGIN_AREA]; | ||
| 980 | row->glyphs[TEXT_AREA] = p[TEXT_AREA]; | ||
| 981 | row->glyphs[RIGHT_MARGIN_AREA] = p[RIGHT_MARGIN_AREA]; | ||
| 982 | row->glyphs[LAST_AREA] = p[LAST_AREA]; | ||
| 983 | } | ||
| 984 | |||
| 985 | |||
| 986 | /* Make ROW an empty, enabled row of canonical character height, | ||
| 987 | in window W starting at y-position Y. */ | ||
| 316 | 988 | ||
| 317 | return new; | 989 | void |
| 990 | blank_row (w, row, y) | ||
| 991 | struct window *w; | ||
| 992 | struct glyph_row *row; | ||
| 993 | int y; | ||
| 994 | { | ||
| 995 | int min_y, max_y; | ||
| 996 | |||
| 997 | min_y = WINDOW_DISPLAY_TOP_LINE_HEIGHT (w); | ||
| 998 | max_y = WINDOW_DISPLAY_HEIGHT_NO_MODE_LINE (w); | ||
| 999 | |||
| 1000 | clear_glyph_row (row); | ||
| 1001 | row->y = y; | ||
| 1002 | row->ascent = 0; | ||
| 1003 | row->height = CANON_Y_UNIT (XFRAME (WINDOW_FRAME (w))); | ||
| 1004 | |||
| 1005 | if (row->y < min_y) | ||
| 1006 | row->visible_height = row->height - (min_y - row->y); | ||
| 1007 | else if (row->y + row->height > max_y) | ||
| 1008 | row->visible_height = row->height - (row->y + row->height - max_y); | ||
| 1009 | else | ||
| 1010 | row->visible_height = row->height; | ||
| 1011 | |||
| 1012 | row->enabled_p = 1; | ||
| 318 | } | 1013 | } |
| 319 | 1014 | ||
| 1015 | |||
| 1016 | /* Increment buffer positions in glyph row ROW. DELTA and DELTA_BYTES | ||
| 1017 | are the amounts by which to change positions. Note that the first | ||
| 1018 | glyph of the text area of a row can have a buffer position even if | ||
| 1019 | the used count of the text area is zero. Such rows display line | ||
| 1020 | ends. */ | ||
| 1021 | |||
| 320 | void | 1022 | void |
| 321 | free_frame_glyphs (frame, glyphs) | 1023 | increment_glyph_row_buffer_positions (row, delta, delta_bytes) |
| 322 | FRAME_PTR frame; | 1024 | struct glyph_row *row; |
| 323 | struct frame_glyphs *glyphs; | 1025 | int delta, delta_bytes; |
| 324 | { | 1026 | { |
| 325 | if (glyphs->total_contents) | 1027 | int area, i; |
| 326 | xfree (glyphs->total_contents); | 1028 | |
| 327 | if (glyphs->total_charstarts) | 1029 | /* Increment start and end positions. */ |
| 328 | xfree (glyphs->total_charstarts); | 1030 | MATRIX_ROW_START_CHARPOS (row) += delta; |
| 329 | 1031 | MATRIX_ROW_START_BYTEPOS (row) += delta_bytes; | |
| 330 | xfree (glyphs->used); | 1032 | MATRIX_ROW_END_CHARPOS (row) += delta; |
| 331 | xfree (glyphs->glyphs); | 1033 | MATRIX_ROW_END_BYTEPOS (row) += delta_bytes; |
| 332 | xfree (glyphs->highlight); | 1034 | |
| 333 | xfree (glyphs->enable); | 1035 | /* Increment positions in glyphs. */ |
| 334 | xfree (glyphs->bufp); | 1036 | for (area = 0; area < LAST_AREA; ++area) |
| 335 | if (glyphs->charstarts) | 1037 | for (i = 0; i < row->used[area]; ++i) |
| 336 | xfree (glyphs->charstarts); | 1038 | if (BUFFERP (row->glyphs[area][i].object) |
| 1039 | && row->glyphs[area][i].charpos > 0) | ||
| 1040 | row->glyphs[area][i].charpos += delta; | ||
| 1041 | |||
| 1042 | /* Capture the case of rows displaying a line end. */ | ||
| 1043 | if (row->used[TEXT_AREA] == 0 | ||
| 1044 | && MATRIX_ROW_DISPLAYS_TEXT_P (row)) | ||
| 1045 | row->glyphs[TEXT_AREA]->charpos += delta; | ||
| 1046 | } | ||
| 337 | 1047 | ||
| 338 | #ifdef HAVE_WINDOW_SYSTEM | 1048 | |
| 339 | if (FRAME_WINDOW_P (frame)) | 1049 | /* Swap glyphs between two glyph rows A and B. This exchanges glyph |
| 1050 | contents, i.e. glyph structure contents are exchanged between A and | ||
| 1051 | B without changing glyph pointers in A and B. */ | ||
| 1052 | |||
| 1053 | static void | ||
| 1054 | swap_glyphs_in_rows (a, b) | ||
| 1055 | struct glyph_row *a, *b; | ||
| 1056 | { | ||
| 1057 | int area; | ||
| 1058 | |||
| 1059 | for (area = 0; area < LAST_AREA; ++area) | ||
| 1060 | { | ||
| 1061 | /* Number of glyphs to swap. */ | ||
| 1062 | int max_used = max (a->used[area], b->used[area]); | ||
| 1063 | |||
| 1064 | /* Start of glyphs in area of row A. */ | ||
| 1065 | struct glyph *glyph_a = a->glyphs[area]; | ||
| 1066 | |||
| 1067 | /* End + 1 of glyphs in area of row A. */ | ||
| 1068 | struct glyph *glyph_a_end = a->glyphs[max_used]; | ||
| 1069 | |||
| 1070 | /* Start of glyphs in area of row B. */ | ||
| 1071 | struct glyph *glyph_b = b->glyphs[area]; | ||
| 1072 | |||
| 1073 | while (glyph_a < glyph_a_end) | ||
| 1074 | { | ||
| 1075 | /* Non-ISO HP/UX compiler doesn't like auto struct | ||
| 1076 | initialization. */ | ||
| 1077 | struct glyph temp; | ||
| 1078 | temp = *glyph_a; | ||
| 1079 | *glyph_a = *glyph_b; | ||
| 1080 | *glyph_b = temp; | ||
| 1081 | ++glyph_a; | ||
| 1082 | ++glyph_b; | ||
| 1083 | } | ||
| 1084 | } | ||
| 1085 | } | ||
| 1086 | |||
| 1087 | |||
| 1088 | /* Exchange pointers to glyph memory between glyph rows A and B. */ | ||
| 1089 | |||
| 1090 | static INLINE void | ||
| 1091 | swap_glyph_pointers (a, b) | ||
| 1092 | struct glyph_row *a, *b; | ||
| 1093 | { | ||
| 1094 | int i; | ||
| 1095 | for (i = 0; i < LAST_AREA + 1; ++i) | ||
| 340 | { | 1096 | { |
| 341 | xfree (glyphs->top_left_x); | 1097 | struct glyph *temp = a->glyphs[i]; |
| 342 | xfree (glyphs->top_left_y); | 1098 | a->glyphs[i] = b->glyphs[i]; |
| 343 | xfree (glyphs->pix_width); | 1099 | b->glyphs[i] = temp; |
| 344 | xfree (glyphs->pix_height); | ||
| 345 | xfree (glyphs->max_ascent); | ||
| 346 | } | 1100 | } |
| 347 | #endif /* HAVE_WINDOW_SYSTEM */ | 1101 | } |
| 1102 | |||
| 1103 | |||
| 1104 | /* Copy glyph row structure FROM to glyph row structure TO, except | ||
| 1105 | that glyph pointers in the structures are left unchanged. */ | ||
| 1106 | |||
| 1107 | INLINE void | ||
| 1108 | copy_row_except_pointers (to, from) | ||
| 1109 | struct glyph_row *to, *from; | ||
| 1110 | { | ||
| 1111 | struct glyph *pointers[1 + LAST_AREA]; | ||
| 1112 | |||
| 1113 | /* Save glyph pointers of TO. */ | ||
| 1114 | bcopy (to->glyphs, pointers, sizeof to->glyphs); | ||
| 348 | 1115 | ||
| 349 | xfree (glyphs); | 1116 | /* Do a structure assignment. */ |
| 1117 | *to = *from; | ||
| 1118 | |||
| 1119 | /* Restore original pointers of TO. */ | ||
| 1120 | bcopy (pointers, to->glyphs, sizeof to->glyphs); | ||
| 350 | } | 1121 | } |
| 351 | 1122 | ||
| 1123 | |||
| 1124 | /* Copy contents of glyph row FROM to glyph row TO. Glyph pointers in | ||
| 1125 | TO and FROM are left unchanged. Glyph contents are copied from the | ||
| 1126 | glyph memory of FROM to the glyph memory of TO. Increment buffer | ||
| 1127 | positions in row TO by DELTA/ DELTA_BYTES. */ | ||
| 1128 | |||
| 352 | void | 1129 | void |
| 353 | remake_frame_glyphs (frame) | 1130 | copy_glyph_row_contents (to, from, delta, delta_bytes) |
| 354 | FRAME_PTR frame; | 1131 | struct glyph_row *to, *from; |
| 1132 | int delta, delta_bytes; | ||
| 355 | { | 1133 | { |
| 356 | if (FRAME_CURRENT_GLYPHS (frame)) | 1134 | int area; |
| 357 | free_frame_glyphs (frame, FRAME_CURRENT_GLYPHS (frame)); | ||
| 358 | if (FRAME_DESIRED_GLYPHS (frame)) | ||
| 359 | free_frame_glyphs (frame, FRAME_DESIRED_GLYPHS (frame)); | ||
| 360 | if (FRAME_TEMP_GLYPHS (frame)) | ||
| 361 | free_frame_glyphs (frame, FRAME_TEMP_GLYPHS (frame)); | ||
| 362 | 1135 | ||
| 363 | if (FRAME_MESSAGE_BUF (frame)) | 1136 | /* This is like a structure assignment TO = FROM, except that |
| 364 | { | 1137 | glyph pointers in the rows are left unchanged. */ |
| 365 | /* Reallocate the frame's message buffer; remember that | 1138 | copy_row_except_pointers (to, from); |
| 366 | echo_area_glyphs may be pointing here. */ | ||
| 367 | char *old_message_buf = FRAME_MESSAGE_BUF (frame); | ||
| 368 | 1139 | ||
| 369 | FRAME_MESSAGE_BUF (frame) | 1140 | /* Copy glyphs from FROM to TO. */ |
| 370 | = (char *) xrealloc (FRAME_MESSAGE_BUF (frame), | 1141 | for (area = 0; area < LAST_AREA; ++area) |
| 371 | FRAME_MESSAGE_BUF_SIZE (frame) + 1); | 1142 | if (from->used[area]) |
| 1143 | bcopy (from->glyphs[area], to->glyphs[area], | ||
| 1144 | from->used[area] * sizeof (struct glyph)); | ||
| 372 | 1145 | ||
| 373 | if (echo_area_glyphs == old_message_buf) | 1146 | /* Increment buffer positions in TO by DELTA. */ |
| 374 | echo_area_glyphs = FRAME_MESSAGE_BUF (frame); | 1147 | increment_glyph_row_buffer_positions (to, delta, delta_bytes); |
| 375 | if (previous_echo_glyphs == old_message_buf) | 1148 | } |
| 376 | previous_echo_glyphs = FRAME_MESSAGE_BUF (frame); | 1149 | |
| 377 | } | 1150 | |
| 378 | else | 1151 | /* Assign glyph row FROM to glyph row TO. This works like a structure |
| 379 | FRAME_MESSAGE_BUF (frame) | 1152 | assignment TO = FROM, except that glyph pointers are not copied but |
| 380 | = (char *) xmalloc (FRAME_MESSAGE_BUF_SIZE (frame) + 1); | 1153 | exchanged between TO and FROM. Pointers must be exchanged to avoid |
| 1154 | a memory leak. */ | ||
| 381 | 1155 | ||
| 382 | FRAME_CURRENT_GLYPHS (frame) = make_frame_glyphs (frame, 0); | 1156 | static INLINE void |
| 383 | FRAME_DESIRED_GLYPHS (frame) = make_frame_glyphs (frame, 0); | 1157 | assign_row (to, from) |
| 384 | FRAME_TEMP_GLYPHS (frame) = make_frame_glyphs (frame, 1); | 1158 | struct glyph_row *to, *from; |
| 385 | if (FRAME_WINDOW_P (frame) || frame == selected_frame) | 1159 | { |
| 386 | SET_FRAME_GARBAGED (frame); | 1160 | swap_glyph_pointers (to, from); |
| 1161 | copy_row_except_pointers (to, from); | ||
| 387 | } | 1162 | } |
| 388 | 1163 | ||
| 389 | /* Return the hash code of contents of line VPOS in frame-matrix M. */ | 1164 | |
| 1165 | /* Test whether the glyph memory of the glyph row WINDOW_ROW, which is | ||
| 1166 | a row in a window matrix, is a slice of the glyph memory of the | ||
| 1167 | glyph row FRAME_ROW which is a row in a frame glyph matrix. Value | ||
| 1168 | is non-zero if the glyph memory of WINDOW_ROW is part of the glyph | ||
| 1169 | memory of FRAME_ROW. */ | ||
| 390 | 1170 | ||
| 391 | static int | 1171 | static int |
| 392 | line_hash_code (m, vpos) | 1172 | glyph_row_slice_p (window_row, frame_row) |
| 393 | register struct frame_glyphs *m; | 1173 | struct glyph_row *window_row, *frame_row; |
| 394 | int vpos; | ||
| 395 | { | 1174 | { |
| 396 | register GLYPH *body, *end; | 1175 | struct glyph *window_glyph_start = window_row->glyphs[0]; |
| 397 | register int h = 0; | 1176 | struct glyph *frame_glyph_start = frame_row->glyphs[0]; |
| 1177 | struct glyph *frame_glyph_end = frame_row->glyphs[LAST_AREA]; | ||
| 398 | 1178 | ||
| 399 | if (!m->enable[vpos]) | 1179 | return (frame_glyph_start <= window_glyph_start |
| 400 | return 0; | 1180 | && window_glyph_start < frame_glyph_end); |
| 1181 | } | ||
| 401 | 1182 | ||
| 402 | /* Give all highlighted lines the same hash code | ||
| 403 | so as to encourage scrolling to leave them in place. */ | ||
| 404 | if (m->highlight[vpos]) | ||
| 405 | return -1; | ||
| 406 | 1183 | ||
| 407 | body = m->glyphs[vpos]; | 1184 | /* Find the row in the window glyph matrix WINDOW_MATRIX being a slice |
| 1185 | of ROW in the frame matrix FRAME_MATRIX. Value is null if no row | ||
| 1186 | in WINDOW_MATRIX is found satisfying the condition. */ | ||
| 408 | 1187 | ||
| 409 | if (must_write_spaces) | 1188 | static struct glyph_row * |
| 410 | while (1) | 1189 | find_glyph_row_slice (window_matrix, frame_matrix, row) |
| 411 | { | 1190 | struct glyph_matrix *window_matrix, *frame_matrix; |
| 412 | GLYPH g = *body++; | 1191 | int row; |
| 1192 | { | ||
| 1193 | int i; | ||
| 413 | 1194 | ||
| 414 | if (g == 0) | 1195 | xassert (row >= 0 && row < frame_matrix->nrows); |
| 415 | break; | ||
| 416 | h = (((h << 4) + (h >> 24)) & 0x0fffffff) + g - SPACEGLYPH; | ||
| 417 | } | ||
| 418 | else | ||
| 419 | while (1) | ||
| 420 | { | ||
| 421 | GLYPH g = *body++; | ||
| 422 | 1196 | ||
| 423 | if (g == 0) | 1197 | for (i = 0; i < window_matrix->nrows; ++i) |
| 424 | break; | 1198 | if (glyph_row_slice_p (window_matrix->rows + i, |
| 425 | h = (((h << 4) + (h >> 24)) & 0x0fffffff) + g; | 1199 | frame_matrix->rows + row)) |
| 426 | } | 1200 | break; |
| 427 | 1201 | ||
| 428 | if (h) | 1202 | return i < window_matrix->nrows ? window_matrix->rows + i : 0; |
| 429 | return h; | 1203 | } |
| 430 | return 1; | 1204 | |
| 1205 | |||
| 1206 | /* Prepare ROW for display. Desired rows are cleared lazily, | ||
| 1207 | i.e. they are only marked as to be cleared by setting their | ||
| 1208 | enabled_p flag to zero. When a row is to be displayed, a prior | ||
| 1209 | call to this function really clears it. */ | ||
| 1210 | |||
| 1211 | void | ||
| 1212 | prepare_desired_row (row) | ||
| 1213 | struct glyph_row *row; | ||
| 1214 | { | ||
| 1215 | if (!row->enabled_p) | ||
| 1216 | { | ||
| 1217 | clear_glyph_row (row); | ||
| 1218 | row->enabled_p = 1; | ||
| 1219 | } | ||
| 431 | } | 1220 | } |
| 432 | 1221 | ||
| 433 | /* Return number of characters in line in M at vpos VPOS, | 1222 | |
| 434 | except don't count leading and trailing spaces | 1223 | /* Return a hash code for glyph row ROW. */ |
| 435 | unless the terminal requires those to be explicitly output. */ | 1224 | |
| 1225 | int | ||
| 1226 | line_hash_code (row) | ||
| 1227 | struct glyph_row *row; | ||
| 1228 | { | ||
| 1229 | int hash = 0; | ||
| 1230 | |||
| 1231 | if (row->enabled_p) | ||
| 1232 | { | ||
| 1233 | if (row->inverse_p) | ||
| 1234 | { | ||
| 1235 | /* Give all highlighted lines the same hash code | ||
| 1236 | so as to encourage scrolling to leave them in place. */ | ||
| 1237 | hash = -1; | ||
| 1238 | } | ||
| 1239 | else | ||
| 1240 | { | ||
| 1241 | struct glyph *glyph = row->glyphs[TEXT_AREA]; | ||
| 1242 | struct glyph *end = glyph + row->used[TEXT_AREA]; | ||
| 1243 | |||
| 1244 | while (glyph < end) | ||
| 1245 | { | ||
| 1246 | GLYPH g = GLYPH_FROM_CHAR_GLYPH (*glyph); | ||
| 1247 | if (must_write_spaces) | ||
| 1248 | g -= SPACEGLYPH; | ||
| 1249 | hash = (((hash << 4) + (hash >> 24)) & 0x0fffffff) + g; | ||
| 1250 | ++glyph; | ||
| 1251 | } | ||
| 1252 | |||
| 1253 | if (hash == 0) | ||
| 1254 | hash = 1; | ||
| 1255 | } | ||
| 1256 | } | ||
| 1257 | |||
| 1258 | return hash; | ||
| 1259 | } | ||
| 1260 | |||
| 1261 | |||
| 1262 | /* Return the cost of drawing line VPOS In MATRIX. The cost equals | ||
| 1263 | the number of characters in the line. If must_write_spaces is | ||
| 1264 | zero, leading and trailing spaces are ignored. */ | ||
| 436 | 1265 | ||
| 437 | static unsigned int | 1266 | static unsigned int |
| 438 | line_draw_cost (m, vpos) | 1267 | line_draw_cost (matrix, vpos) |
| 439 | struct frame_glyphs *m; | 1268 | struct glyph_matrix *matrix; |
| 440 | int vpos; | 1269 | int vpos; |
| 441 | { | 1270 | { |
| 442 | register GLYPH *beg = m->glyphs[vpos]; | 1271 | struct glyph_row *row = matrix->rows + vpos; |
| 443 | register GLYPH *end = m->glyphs[vpos] + m->used[vpos]; | 1272 | struct glyph *beg = row->glyphs[TEXT_AREA]; |
| 444 | register int i; | 1273 | struct glyph *end = beg + row->used[TEXT_AREA]; |
| 445 | register int tlen = GLYPH_TABLE_LENGTH; | 1274 | int len; |
| 446 | register Lisp_Object *tbase = GLYPH_TABLE_BASE; | 1275 | Lisp_Object *glyph_table_base = GLYPH_TABLE_BASE; |
| 1276 | int glyph_table_len = GLYPH_TABLE_LENGTH; | ||
| 447 | 1277 | ||
| 448 | /* Ignore trailing and leading spaces if we can. */ | 1278 | /* Ignore trailing and leading spaces if we can. */ |
| 449 | if (!must_write_spaces) | 1279 | if (!must_write_spaces) |
| 450 | { | 1280 | { |
| 451 | while ((end != beg) && (*end == SPACEGLYPH)) | 1281 | /* Skip from the end over trailing spaces. */ |
| 1282 | while (end != beg && CHAR_GLYPH_SPACE_P (*end)) | ||
| 452 | --end; | 1283 | --end; |
| 1284 | |||
| 1285 | /* All blank line. */ | ||
| 453 | if (end == beg) | 1286 | if (end == beg) |
| 454 | return (0); /* All blank line. */ | 1287 | return 0; |
| 455 | 1288 | ||
| 456 | while (*beg == SPACEGLYPH) | 1289 | /* Skip over leading spaces. */ |
| 1290 | while (CHAR_GLYPH_SPACE_P (*beg)) | ||
| 457 | ++beg; | 1291 | ++beg; |
| 458 | } | 1292 | } |
| 459 | 1293 | ||
| 460 | /* If we don't have a glyph-table, each glyph is one character, | 1294 | /* If we don't have a glyph-table, each glyph is one character, |
| 461 | so return the number of glyphs. */ | 1295 | so return the number of glyphs. */ |
| 462 | if (tbase == 0) | 1296 | if (glyph_table_base == 0) |
| 463 | return end - beg; | 1297 | len = end - beg; |
| 1298 | else | ||
| 1299 | { | ||
| 1300 | /* Otherwise, scan the glyphs and accumulate their total length | ||
| 1301 | in LEN. */ | ||
| 1302 | len = 0; | ||
| 1303 | while (beg < end) | ||
| 1304 | { | ||
| 1305 | GLYPH g = GLYPH_FROM_CHAR_GLYPH (*beg); | ||
| 1306 | |||
| 1307 | if (GLYPH_SIMPLE_P (glyph_table_base, glyph_table_len, g)) | ||
| 1308 | len += 1; | ||
| 1309 | else | ||
| 1310 | len += GLYPH_LENGTH (glyph_table_base, g); | ||
| 1311 | |||
| 1312 | ++beg; | ||
| 1313 | } | ||
| 1314 | } | ||
| 1315 | |||
| 1316 | return len; | ||
| 1317 | } | ||
| 1318 | |||
| 1319 | |||
| 1320 | /* Test two glyph rows A and B for equality. Value is non-zero if A | ||
| 1321 | and B have equal contents. W is the window to which the glyphs | ||
| 1322 | rows A and B belong. It is needed here to test for partial row | ||
| 1323 | visibility. */ | ||
| 464 | 1324 | ||
| 465 | /* Otherwise, scan the glyphs and accumulate their total size in I. */ | 1325 | static INLINE int |
| 466 | i = 0; | 1326 | row_equal_p (w, a, b) |
| 467 | while ((beg <= end) && *beg) | 1327 | struct window *w; |
| 1328 | struct glyph_row *a, *b; | ||
| 1329 | { | ||
| 1330 | if (a == b) | ||
| 1331 | return 1; | ||
| 1332 | else if (a->hash != b->hash) | ||
| 1333 | return 0; | ||
| 1334 | else | ||
| 468 | { | 1335 | { |
| 469 | register GLYPH g = *beg++; | 1336 | struct glyph *a_glyph, *b_glyph, *a_end; |
| 1337 | int area; | ||
| 470 | 1338 | ||
| 471 | if (GLYPH_SIMPLE_P (tbase, tlen, g)) | 1339 | /* Compare glyphs. */ |
| 472 | i += 1; | 1340 | for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area) |
| 473 | else | 1341 | { |
| 474 | i += GLYPH_LENGTH (tbase, g); | 1342 | if (a->used[area] != b->used[area]) |
| 1343 | return 0; | ||
| 1344 | |||
| 1345 | a_glyph = a->glyphs[area]; | ||
| 1346 | a_end = a_glyph + a->used[area]; | ||
| 1347 | b_glyph = b->glyphs[area]; | ||
| 1348 | |||
| 1349 | while (a_glyph < a_end | ||
| 1350 | && GLYPH_EQUAL_P (a_glyph, b_glyph)) | ||
| 1351 | ++a_glyph, ++b_glyph; | ||
| 1352 | |||
| 1353 | if (a_glyph != a_end) | ||
| 1354 | return 0; | ||
| 1355 | } | ||
| 1356 | |||
| 1357 | if (a->truncated_on_left_p != b->truncated_on_left_p | ||
| 1358 | || a->inverse_p != b->inverse_p | ||
| 1359 | || a->fill_line_p != b->fill_line_p | ||
| 1360 | || a->truncated_on_right_p != b->truncated_on_right_p | ||
| 1361 | || a->overlay_arrow_p != b->overlay_arrow_p | ||
| 1362 | || a->continued_p != b->continued_p | ||
| 1363 | || a->indicate_empty_line_p != b->indicate_empty_line_p | ||
| 1364 | || (MATRIX_ROW_CONTINUATION_LINE_P (a) | ||
| 1365 | != MATRIX_ROW_CONTINUATION_LINE_P (b)) | ||
| 1366 | /* Different partially visible characters on left margin. */ | ||
| 1367 | || a->x != b->x | ||
| 1368 | /* Different height. */ | ||
| 1369 | || a->ascent != b->ascent | ||
| 1370 | || a->visible_height != b->visible_height) | ||
| 1371 | return 0; | ||
| 475 | } | 1372 | } |
| 476 | return i; | 1373 | |
| 1374 | return 1; | ||
| 477 | } | 1375 | } |
| 1376 | |||
| 1377 | |||
| 478 | 1378 | ||
| 479 | /* The functions on this page are the interface from xdisp.c to redisplay. | 1379 | /*********************************************************************** |
| 1380 | Glyph Pool | ||
| 480 | 1381 | ||
| 481 | The only other interface into redisplay is through setting | 1382 | See dispextern.h for an overall explanation of glyph pools. |
| 482 | FRAME_CURSOR_X (frame) and FRAME_CURSOR_Y (frame) | 1383 | ***********************************************************************/ |
| 483 | and SET_FRAME_GARBAGED (frame). */ | ||
| 484 | 1384 | ||
| 485 | /* cancel_line eliminates any request to display a line at position `vpos' */ | 1385 | /* Allocate a glyph_pool structure. The structure returned is |
| 1386 | initialized with zeros. The global variable glyph_pool_count is | ||
| 1387 | incremented for each pool allocated. */ | ||
| 486 | 1388 | ||
| 487 | void | 1389 | static struct glyph_pool * |
| 488 | cancel_line (vpos, frame) | 1390 | new_glyph_pool () |
| 489 | int vpos; | ||
| 490 | register FRAME_PTR frame; | ||
| 491 | { | 1391 | { |
| 492 | FRAME_DESIRED_GLYPHS (frame)->enable[vpos] = 0; | 1392 | struct glyph_pool *result; |
| 493 | } | ||
| 494 | 1393 | ||
| 495 | void | 1394 | /* Allocate a new glyph_pool and clear it. */ |
| 496 | clear_frame_records (frame) | 1395 | result = (struct glyph_pool *) xmalloc (sizeof *result); |
| 497 | register FRAME_PTR frame; | 1396 | bzero (result, sizeof *result); |
| 498 | { | 1397 | |
| 499 | bzero (FRAME_CURRENT_GLYPHS (frame)->enable, FRAME_HEIGHT (frame)); | 1398 | /* For memory leak and double deletion checking. */ |
| 1399 | ++glyph_pool_count; | ||
| 1400 | |||
| 1401 | return result; | ||
| 500 | } | 1402 | } |
| 501 | 1403 | ||
| 502 | /* Clear out all display lines for a coming redisplay. */ | ||
| 503 | 1404 | ||
| 504 | void | 1405 | /* Free a glyph_pool structure POOL. The function may be called with |
| 505 | init_desired_glyphs (frame) | 1406 | a null POOL pointer. The global variable glyph_pool_count is |
| 506 | register FRAME_PTR frame; | 1407 | decremented with every pool structure freed. If this count gets |
| 1408 | negative, more structures were freed than allocated, i.e. one | ||
| 1409 | structure must have been freed more than once or a bogus pointer | ||
| 1410 | was passed to free_glyph_pool. */ | ||
| 1411 | |||
| 1412 | static void | ||
| 1413 | free_glyph_pool (pool) | ||
| 1414 | struct glyph_pool *pool; | ||
| 507 | { | 1415 | { |
| 508 | register struct frame_glyphs *desired_glyphs = FRAME_DESIRED_GLYPHS (frame); | 1416 | if (pool) |
| 509 | int vpos; | 1417 | { |
| 510 | int height = FRAME_HEIGHT (frame); | 1418 | /* More freed than allocated? */ |
| 1419 | --glyph_pool_count; | ||
| 1420 | xassert (glyph_pool_count >= 0); | ||
| 511 | 1421 | ||
| 512 | for (vpos = 0; vpos < height; vpos++) | 1422 | xfree (pool->glyphs); |
| 513 | desired_glyphs->enable[vpos] = 0; | 1423 | xfree (pool); |
| 1424 | } | ||
| 514 | } | 1425 | } |
| 515 | 1426 | ||
| 516 | /* Prepare to display on line VPOS starting at HPOS within it. */ | ||
| 517 | 1427 | ||
| 518 | void | 1428 | /* Enlarge a glyph pool POOL. MATRIX_DIM gives the number of rows and |
| 519 | get_display_line (frame, vpos, hpos) | 1429 | columns we need. This function never shrinks a pool. The only |
| 520 | register FRAME_PTR frame; | 1430 | case in which this would make sense, would be when a frame's size |
| 521 | int vpos; | 1431 | is changed from a large value to a smaller one. But, if someone |
| 522 | register int hpos; | 1432 | does it once, we can expect that he will do it again. |
| 1433 | |||
| 1434 | Value is non-zero if the pool changed in a way which makes | ||
| 1435 | re-adjusting window glyph matrices necessary. */ | ||
| 1436 | |||
| 1437 | static int | ||
| 1438 | realloc_glyph_pool (pool, matrix_dim) | ||
| 1439 | struct glyph_pool *pool; | ||
| 1440 | struct dim matrix_dim; | ||
| 523 | { | 1441 | { |
| 524 | register struct frame_glyphs *glyphs; | 1442 | int needed; |
| 525 | register struct frame_glyphs *desired_glyphs = FRAME_DESIRED_GLYPHS (frame); | 1443 | int changed_p; |
| 526 | register GLYPH *p; | ||
| 527 | 1444 | ||
| 528 | if (vpos < 0) | 1445 | changed_p = (pool->glyphs == 0 |
| 529 | abort (); | 1446 | || matrix_dim.height != pool->nrows |
| 1447 | || matrix_dim.width != pool->ncolumns); | ||
| 530 | 1448 | ||
| 531 | if (! desired_glyphs->enable[vpos]) | 1449 | /* Enlarge the glyph pool. */ |
| 1450 | needed = matrix_dim.width * matrix_dim.height; | ||
| 1451 | if (needed > pool->nglyphs) | ||
| 532 | { | 1452 | { |
| 533 | desired_glyphs->used[vpos] = 0; | 1453 | int size = needed * sizeof (struct glyph); |
| 534 | desired_glyphs->highlight[vpos] = 0; | ||
| 535 | desired_glyphs->enable[vpos] = 1; | ||
| 536 | } | ||
| 537 | 1454 | ||
| 538 | if (hpos > desired_glyphs->used[vpos]) | 1455 | if (pool->glyphs) |
| 539 | { | 1456 | pool->glyphs = (struct glyph *) xrealloc (pool->glyphs, size); |
| 540 | GLYPH *g = desired_glyphs->glyphs[vpos] + desired_glyphs->used[vpos]; | 1457 | else |
| 541 | GLYPH *end = desired_glyphs->glyphs[vpos] + hpos; | 1458 | { |
| 1459 | pool->glyphs = (struct glyph *) xmalloc (size); | ||
| 1460 | bzero (pool->glyphs, size); | ||
| 1461 | } | ||
| 542 | 1462 | ||
| 543 | desired_glyphs->used[vpos] = hpos; | 1463 | pool->nglyphs = needed; |
| 544 | while (g != end) | ||
| 545 | *g++ = SPACEGLYPH; | ||
| 546 | } | 1464 | } |
| 1465 | |||
| 1466 | /* Remember the number of rows and columns because (a) we use then | ||
| 1467 | to do sanity checks, and (b) the number of columns determines | ||
| 1468 | where rows in the frame matrix start---this must be available to | ||
| 1469 | determine pointers to rows of window sub-matrices. */ | ||
| 1470 | pool->nrows = matrix_dim.height; | ||
| 1471 | pool->ncolumns = matrix_dim.width; | ||
| 1472 | |||
| 1473 | return changed_p; | ||
| 547 | } | 1474 | } |
| 548 | 1475 | ||
| 549 | /* Like bcopy except never gets confused by overlap. */ | 1476 | |
| 1477 | |||
| 1478 | /*********************************************************************** | ||
| 1479 | Debug Code | ||
| 1480 | ***********************************************************************/ | ||
| 1481 | |||
| 1482 | #if GLYPH_DEBUG | ||
| 1483 | |||
| 1484 | /* Check that no glyph pointers have been lost in MATRIX. If a | ||
| 1485 | pointer has been lost, e.g. by using a structure assignment between | ||
| 1486 | rows, at least one pointer must occur more than once in the rows of | ||
| 1487 | MATRIX. */ | ||
| 550 | 1488 | ||
| 551 | void | 1489 | void |
| 552 | safe_bcopy (from, to, size) | 1490 | check_matrix_pointer_lossage (matrix) |
| 553 | char *from, *to; | 1491 | struct glyph_matrix *matrix; |
| 554 | int size; | ||
| 555 | { | 1492 | { |
| 556 | if (size <= 0 || from == to) | 1493 | int i, j; |
| 1494 | |||
| 1495 | for (i = 0; i < matrix->nrows; ++i) | ||
| 1496 | for (j = 0; j < matrix->nrows; ++j) | ||
| 1497 | xassert (i == j | ||
| 1498 | || (matrix->rows[i].glyphs[TEXT_AREA] | ||
| 1499 | != matrix->rows[j].glyphs[TEXT_AREA])); | ||
| 1500 | } | ||
| 1501 | |||
| 1502 | |||
| 1503 | /* Get a pointer to glyph row ROW in MATRIX, with bounds checks. */ | ||
| 1504 | |||
| 1505 | struct glyph_row * | ||
| 1506 | matrix_row (matrix, row) | ||
| 1507 | struct glyph_matrix *matrix; | ||
| 1508 | int row; | ||
| 1509 | { | ||
| 1510 | xassert (matrix && matrix->rows); | ||
| 1511 | xassert (row >= 0 && row < matrix->nrows); | ||
| 1512 | |||
| 1513 | /* That's really too slow for normal testing because this function | ||
| 1514 | is called almost everywhere. Although---it's still astonishingly | ||
| 1515 | fast, so it is valuable to have for debugging purposes. */ | ||
| 1516 | #if 0 | ||
| 1517 | check_matrix_pointer_lossage (matrix); | ||
| 1518 | #endif | ||
| 1519 | |||
| 1520 | return matrix->rows + row; | ||
| 1521 | } | ||
| 1522 | |||
| 1523 | |||
| 1524 | #if 0 /* This function makes invalid assumptions when text is | ||
| 1525 | partially invisible. But it might come handy for debugging | ||
| 1526 | nevertheless. */ | ||
| 1527 | |||
| 1528 | /* Check invariants that must hold for an up to date current matrix of | ||
| 1529 | window W. */ | ||
| 1530 | |||
| 1531 | static void | ||
| 1532 | check_matrix_invariants (w) | ||
| 1533 | struct window *w; | ||
| 1534 | { | ||
| 1535 | struct glyph_matrix *matrix = w->current_matrix; | ||
| 1536 | int yb = window_text_bottom_y (w); | ||
| 1537 | struct glyph_row *row = matrix->rows; | ||
| 1538 | struct glyph_row *last_text_row = NULL; | ||
| 1539 | struct buffer *saved = current_buffer; | ||
| 1540 | struct buffer *buffer = XBUFFER (w->buffer); | ||
| 1541 | int c; | ||
| 1542 | |||
| 1543 | /* This can sometimes happen for a fresh window. */ | ||
| 1544 | if (matrix->nrows < 2) | ||
| 557 | return; | 1545 | return; |
| 558 | 1546 | ||
| 559 | /* If the source and destination don't overlap, then bcopy can | 1547 | set_buffer_temp (buffer); |
| 560 | handle it. If they do overlap, but the destination is lower in | ||
| 561 | memory than the source, we'll assume bcopy can handle that. */ | ||
| 562 | if (to < from || from + size <= to) | ||
| 563 | bcopy (from, to, size); | ||
| 564 | 1548 | ||
| 565 | /* Otherwise, we'll copy from the end. */ | 1549 | /* Note: last row is always reserved for the mode line. */ |
| 566 | else | 1550 | while (MATRIX_ROW_DISPLAYS_TEXT_P (row) |
| 1551 | && MATRIX_ROW_BOTTOM_Y (row) < yb) | ||
| 567 | { | 1552 | { |
| 568 | register char *endf = from + size; | 1553 | struct glyph_row *next = row + 1; |
| 569 | register char *endt = to + size; | ||
| 570 | 1554 | ||
| 571 | /* If TO - FROM is large, then we should break the copy into | 1555 | if (MATRIX_ROW_DISPLAYS_TEXT_P (row)) |
| 572 | nonoverlapping chunks of TO - FROM bytes each. However, if | 1556 | last_text_row = row; |
| 573 | TO - FROM is small, then the bcopy function call overhead | 1557 | |
| 574 | makes this not worth it. The crossover point could be about | 1558 | /* Check that character and byte positions are in sync. */ |
| 575 | anywhere. Since I don't think the obvious copy loop is too | 1559 | xassert (MATRIX_ROW_START_BYTEPOS (row) |
| 576 | bad, I'm trying to err in its favor. */ | 1560 | == CHAR_TO_BYTE (MATRIX_ROW_START_CHARPOS (row))); |
| 577 | if (to - from < 64) | 1561 | |
| 1562 | /* CHAR_TO_BYTE aborts when invoked for a position > Z. We can | ||
| 1563 | have such a position temporarily in case of a minibuffer | ||
| 1564 | displaying something like `[Sole completion]' at its end. */ | ||
| 1565 | if (MATRIX_ROW_END_CHARPOS (row) < BUF_ZV (current_buffer)) | ||
| 1566 | xassert (MATRIX_ROW_END_BYTEPOS (row) | ||
| 1567 | == CHAR_TO_BYTE (MATRIX_ROW_END_CHARPOS (row))); | ||
| 1568 | |||
| 1569 | /* Check that end position of `row' is equal to start position | ||
| 1570 | of next row. */ | ||
| 1571 | if (next->enabled_p && MATRIX_ROW_DISPLAYS_TEXT_P (next)) | ||
| 578 | { | 1572 | { |
| 579 | do | 1573 | xassert (MATRIX_ROW_END_CHARPOS (row) |
| 580 | *--endt = *--endf; | 1574 | == MATRIX_ROW_START_CHARPOS (next)); |
| 581 | while (endf != from); | 1575 | xassert (MATRIX_ROW_END_BYTEPOS (row) |
| 1576 | == MATRIX_ROW_START_BYTEPOS (next)); | ||
| 582 | } | 1577 | } |
| 1578 | row = next; | ||
| 1579 | } | ||
| 1580 | |||
| 1581 | xassert (w->current_matrix->nrows == w->desired_matrix->nrows); | ||
| 1582 | xassert (w->desired_matrix->rows != NULL); | ||
| 1583 | set_buffer_temp (saved); | ||
| 1584 | } | ||
| 1585 | |||
| 1586 | #endif /* 0 */ | ||
| 1587 | |||
| 1588 | #endif /* GLYPH_DEBUG != 0 */ | ||
| 1589 | |||
| 1590 | |||
| 1591 | |||
| 1592 | /********************************************************************** | ||
| 1593 | Allocating/ Adjusting Glyph Matrices | ||
| 1594 | **********************************************************************/ | ||
| 1595 | |||
| 1596 | /* Allocate glyph matrices over a window tree for a frame-based | ||
| 1597 | redisplay | ||
| 1598 | |||
| 1599 | X and Y are column/row within the frame glyph matrix where | ||
| 1600 | sub-matrices for the window tree rooted at WINDOW must be | ||
| 1601 | allocated. CH_DIM contains the dimensions of the smallest | ||
| 1602 | character that could be used during display. DIM_ONLY_P non-zero | ||
| 1603 | means that the caller of this function is only interested in the | ||
| 1604 | result matrix dimension, and matrix adjustments should not be | ||
| 1605 | performed. | ||
| 1606 | |||
| 1607 | The function returns the total width/height of the sub-matrices of | ||
| 1608 | the window tree. If called on a frame root window, the computation | ||
| 1609 | will take the mini-buffer window into account. | ||
| 1610 | |||
| 1611 | *WINDOW_CHANGE_FLAGS is set to a bit mask with bits | ||
| 1612 | |||
| 1613 | NEW_LEAF_MATRIX set if any window in the tree did not have a | ||
| 1614 | glyph matrices yet, and | ||
| 1615 | |||
| 1616 | CHANGED_LEAF_MATRIX set if the dimension or location of a matrix of | ||
| 1617 | any window in the tree will be changed or have been changed (see | ||
| 1618 | DIM_ONLY_P). | ||
| 1619 | |||
| 1620 | *WINDOW_CHANGE_FLAGS must be initialized by the caller of this | ||
| 1621 | function. | ||
| 1622 | |||
| 1623 | Windows are arranged into chains of windows on the same level | ||
| 1624 | through the next fields of window structures. Such a level can be | ||
| 1625 | either a sequence of horizontally adjacent windows from left to | ||
| 1626 | right, or a sequence of vertically adjacent windows from top to | ||
| 1627 | bottom. Each window in a horizontal sequence can be either a leaf | ||
| 1628 | window or a vertical sequence; a window in a vertical sequence can | ||
| 1629 | be either a leaf or a horizontal sequence. All windows in a | ||
| 1630 | horizontal sequence have the same height, and all windows in a | ||
| 1631 | vertical sequence have the same width. | ||
| 1632 | |||
| 1633 | This function uses, for historical reasons, a more general | ||
| 1634 | algorithm to determine glyph matrix dimensions that would be | ||
| 1635 | necessary. | ||
| 1636 | |||
| 1637 | The matrix height of a horizontal sequence is determined by the | ||
| 1638 | maximum height of any matrix in the sequence. The matrix width of | ||
| 1639 | a horizontal sequence is computed by adding up matrix widths of | ||
| 1640 | windows in the sequence. | ||
| 1641 | |||
| 1642 | |<------- result width ------->| | ||
| 1643 | +---------+----------+---------+ --- | ||
| 1644 | | | | | | | ||
| 1645 | | | | | | ||
| 1646 | +---------+ | | result height | ||
| 1647 | | +---------+ | ||
| 1648 | | | | | ||
| 1649 | +----------+ --- | ||
| 1650 | |||
| 1651 | The matrix width of a vertical sequence is the maximum matrix width | ||
| 1652 | of any window in the sequence. Its height is computed by adding up | ||
| 1653 | matrix heights of windows in the sequence. | ||
| 1654 | |||
| 1655 | |<---- result width -->| | ||
| 1656 | +---------+ --- | ||
| 1657 | | | | | ||
| 1658 | | | | | ||
| 1659 | +---------+--+ | | ||
| 1660 | | | | | ||
| 1661 | | | result height | ||
| 1662 | | | | ||
| 1663 | +------------+---------+ | | ||
| 1664 | | | | | ||
| 1665 | | | | | ||
| 1666 | +------------+---------+ --- */ | ||
| 1667 | |||
| 1668 | /* Bit indicating that a new matrix will be allocated or has been | ||
| 1669 | allocated. */ | ||
| 1670 | |||
| 1671 | #define NEW_LEAF_MATRIX (1 << 0) | ||
| 1672 | |||
| 1673 | /* Bit indicating that a matrix will or has changed its location or | ||
| 1674 | size. */ | ||
| 1675 | |||
| 1676 | #define CHANGED_LEAF_MATRIX (1 << 1) | ||
| 1677 | |||
| 1678 | static struct dim | ||
| 1679 | allocate_matrices_for_frame_redisplay (window, x, y, ch_dim, | ||
| 1680 | dim_only_p, window_change_flags) | ||
| 1681 | Lisp_Object window; | ||
| 1682 | int x, y; | ||
| 1683 | struct dim ch_dim; | ||
| 1684 | int dim_only_p; | ||
| 1685 | int *window_change_flags; | ||
| 1686 | { | ||
| 1687 | struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (window))); | ||
| 1688 | int x0 = x, y0 = y; | ||
| 1689 | int wmax = 0, hmax = 0; | ||
| 1690 | struct dim total; | ||
| 1691 | struct dim dim; | ||
| 1692 | struct window *w; | ||
| 1693 | int in_horz_combination_p; | ||
| 1694 | |||
| 1695 | /* What combination is WINDOW part of? Compute this once since the | ||
| 1696 | result is the same for all windows in the `next' chain. The | ||
| 1697 | special case of a root window (parent equal to nil) is treated | ||
| 1698 | like a vertical combination because a root window's `next' | ||
| 1699 | points to the mini-buffer window, if any, which is arranged | ||
| 1700 | vertically below other windows. */ | ||
| 1701 | in_horz_combination_p | ||
| 1702 | = (!NILP (XWINDOW (window)->parent) | ||
| 1703 | && !NILP (XWINDOW (XWINDOW (window)->parent)->hchild)); | ||
| 1704 | |||
| 1705 | /* For WINDOW and all windows on the same level. */ | ||
| 1706 | do | ||
| 1707 | { | ||
| 1708 | w = XWINDOW (window); | ||
| 1709 | |||
| 1710 | /* Get the dimension of the window sub-matrix for W, depending | ||
| 1711 | on whether this a combination or a leaf window. */ | ||
| 1712 | if (!NILP (w->hchild)) | ||
| 1713 | dim = allocate_matrices_for_frame_redisplay (w->hchild, x, y, ch_dim, | ||
| 1714 | dim_only_p, | ||
| 1715 | window_change_flags); | ||
| 1716 | else if (!NILP (w->vchild)) | ||
| 1717 | dim = allocate_matrices_for_frame_redisplay (w->vchild, x, y, ch_dim, | ||
| 1718 | dim_only_p, | ||
| 1719 | window_change_flags); | ||
| 583 | else | 1720 | else |
| 584 | { | 1721 | { |
| 585 | for (;;) | 1722 | /* If not already done, allocate sub-matrix structures. */ |
| 1723 | if (w->desired_matrix == NULL) | ||
| 586 | { | 1724 | { |
| 587 | endt -= (to - from); | 1725 | w->desired_matrix = new_glyph_matrix (f->desired_pool); |
| 588 | endf -= (to - from); | 1726 | w->current_matrix = new_glyph_matrix (f->current_pool); |
| 1727 | *window_change_flags |= NEW_LEAF_MATRIX; | ||
| 1728 | } | ||
| 1729 | |||
| 1730 | /* Width and height MUST be chosen so that there are no | ||
| 1731 | holes in the frame matrix. */ | ||
| 1732 | dim.width = w->width; | ||
| 1733 | dim.height = w->height; | ||
| 1734 | |||
| 1735 | /* Will matrix be re-allocated? */ | ||
| 1736 | if (x != w->desired_matrix->matrix_x | ||
| 1737 | || y != w->desired_matrix->matrix_y | ||
| 1738 | || dim.width != w->desired_matrix->matrix_w | ||
| 1739 | || dim.height != w->desired_matrix->matrix_h | ||
| 1740 | || (margin_glyphs_to_reserve (w, dim.width, | ||
| 1741 | w->right_margin_width) | ||
| 1742 | != w->desired_matrix->left_margin_glyphs) | ||
| 1743 | || (margin_glyphs_to_reserve (w, dim.width, | ||
| 1744 | w->left_margin_width) | ||
| 1745 | != w->desired_matrix->right_margin_glyphs)) | ||
| 1746 | *window_change_flags |= CHANGED_LEAF_MATRIX; | ||
| 1747 | |||
| 1748 | /* Actually change matrices, if allowed. Do not consider | ||
| 1749 | CHANGED_LEAF_MATRIX computed above here because the pool | ||
| 1750 | may have been changed which we don't now here. We trust | ||
| 1751 | that we only will be called with DIM_ONLY_P != 0 when | ||
| 1752 | necessary. */ | ||
| 1753 | if (!dim_only_p) | ||
| 1754 | { | ||
| 1755 | adjust_glyph_matrix (w, w->desired_matrix, x, y, dim); | ||
| 1756 | adjust_glyph_matrix (w, w->current_matrix, x, y, dim); | ||
| 1757 | } | ||
| 1758 | } | ||
| 589 | 1759 | ||
| 590 | if (endt < to) | 1760 | /* If we are part of a horizontal combination, advance x for |
| 591 | break; | 1761 | windows to the right of W; otherwise advance y for windows |
| 1762 | below W. */ | ||
| 1763 | if (in_horz_combination_p) | ||
| 1764 | x += dim.width; | ||
| 1765 | else | ||
| 1766 | y += dim.height; | ||
| 592 | 1767 | ||
| 593 | bcopy (endf, endt, to - from); | 1768 | /* Remember maximum glyph matrix dimensions. */ |
| 1769 | wmax = max (wmax, dim.width); | ||
| 1770 | hmax = max (hmax, dim.height); | ||
| 1771 | |||
| 1772 | /* Next window on same level. */ | ||
| 1773 | window = w->next; | ||
| 1774 | } | ||
| 1775 | while (!NILP (window)); | ||
| 1776 | |||
| 1777 | /* Set `total' to the total glyph matrix dimension of this window | ||
| 1778 | level. In a vertical combination, the width is the width of the | ||
| 1779 | widest window; the height is the y we finally reached, corrected | ||
| 1780 | by the y we started with. In a horizontal combination, the total | ||
| 1781 | height is the height of the tallest window, and the width is the | ||
| 1782 | x we finally reached, corrected by the x we started with. */ | ||
| 1783 | if (in_horz_combination_p) | ||
| 1784 | { | ||
| 1785 | total.width = x - x0; | ||
| 1786 | total.height = hmax; | ||
| 1787 | } | ||
| 1788 | else | ||
| 1789 | { | ||
| 1790 | total.width = wmax; | ||
| 1791 | total.height = y - y0; | ||
| 1792 | } | ||
| 1793 | |||
| 1794 | return total; | ||
| 1795 | } | ||
| 1796 | |||
| 1797 | |||
| 1798 | /* Allocate window matrices for window-based redisplay. W is the | ||
| 1799 | window whose matrices must be allocated/reallocated. CH_DIM is the | ||
| 1800 | size of the smallest character that could potentially be used on W. */ | ||
| 1801 | |||
| 1802 | static void | ||
| 1803 | allocate_matrices_for_window_redisplay (w, ch_dim) | ||
| 1804 | struct window *w; | ||
| 1805 | struct dim ch_dim; | ||
| 1806 | { | ||
| 1807 | struct frame *f = XFRAME (w->frame); | ||
| 1808 | |||
| 1809 | while (w) | ||
| 1810 | { | ||
| 1811 | if (!NILP (w->vchild)) | ||
| 1812 | allocate_matrices_for_window_redisplay (XWINDOW (w->vchild), ch_dim); | ||
| 1813 | else if (!NILP (w->hchild)) | ||
| 1814 | allocate_matrices_for_window_redisplay (XWINDOW (w->hchild), ch_dim); | ||
| 1815 | else | ||
| 1816 | { | ||
| 1817 | /* W is a leaf window. */ | ||
| 1818 | int window_pixel_width = XFLOATINT (w->width) * CANON_X_UNIT (f); | ||
| 1819 | int window_pixel_height = window_box_height (w) + abs (w->vscroll); | ||
| 1820 | struct dim dim; | ||
| 1821 | |||
| 1822 | /* If matrices are not yet allocated, allocate them now. */ | ||
| 1823 | if (w->desired_matrix == NULL) | ||
| 1824 | { | ||
| 1825 | w->desired_matrix = new_glyph_matrix (NULL); | ||
| 1826 | w->current_matrix = new_glyph_matrix (NULL); | ||
| 594 | } | 1827 | } |
| 595 | 1828 | ||
| 596 | /* If SIZE wasn't a multiple of TO - FROM, there will be a | 1829 | /* Compute number of glyphs needed in a glyph row. */ |
| 597 | little left over. The amount left over is | 1830 | dim.width = (((window_pixel_width + ch_dim.width - 1) |
| 598 | (endt + (to - from)) - to, which is endt - from. */ | 1831 | / ch_dim.width) |
| 599 | bcopy (from, to, endt - from); | 1832 | /* 2 partially visible columns in the text area. */ |
| 1833 | + 2 | ||
| 1834 | /* One partially visible column at the right | ||
| 1835 | edge of each marginal area. */ | ||
| 1836 | + 1 + 1); | ||
| 1837 | |||
| 1838 | /* Compute number of glyph rows needed. */ | ||
| 1839 | dim.height = (((window_pixel_height + ch_dim.height - 1) | ||
| 1840 | / ch_dim.height) | ||
| 1841 | /* One partially visible line at the top and | ||
| 1842 | bottom of the window. */ | ||
| 1843 | + 2 | ||
| 1844 | /* 2 for top and mode line. */ | ||
| 1845 | + 2); | ||
| 1846 | |||
| 1847 | /* Change matrices. */ | ||
| 1848 | adjust_glyph_matrix (w, w->desired_matrix, 0, 0, dim); | ||
| 1849 | adjust_glyph_matrix (w, w->current_matrix, 0, 0, dim); | ||
| 600 | } | 1850 | } |
| 1851 | |||
| 1852 | w = NILP (w->next) ? NULL : XWINDOW (w->next); | ||
| 601 | } | 1853 | } |
| 602 | } | 1854 | } |
| 1855 | |||
| 603 | 1856 | ||
| 604 | /* Rotate a vector of SIZE bytes right, by DISTANCE bytes. | 1857 | /* Re-allocate/ re-compute glyph matrices on frame F. If F is null, |
| 605 | DISTANCE may be negative. */ | 1858 | do it for all frames; otherwise do it just for the given frame. |
| 1859 | This function must be called when a new frame is created, its size | ||
| 1860 | changes, or its window configuration changes. */ | ||
| 1861 | |||
| 1862 | void | ||
| 1863 | adjust_glyphs (f) | ||
| 1864 | struct frame *f; | ||
| 1865 | { | ||
| 1866 | if (f) | ||
| 1867 | adjust_frame_glyphs (f); | ||
| 1868 | else | ||
| 1869 | { | ||
| 1870 | Lisp_Object tail, lisp_frame; | ||
| 1871 | |||
| 1872 | FOR_EACH_FRAME (tail, lisp_frame) | ||
| 1873 | adjust_frame_glyphs (XFRAME (lisp_frame)); | ||
| 1874 | } | ||
| 1875 | } | ||
| 1876 | |||
| 1877 | |||
| 1878 | /* Adjust frame glyphs when Emacs is initialized. | ||
| 1879 | |||
| 1880 | To be called from init_display. | ||
| 1881 | |||
| 1882 | We need a glyph matrix because redraw will happen soon. | ||
| 1883 | Unfortunately, window sizes on selected_frame are not yet set to | ||
| 1884 | meaningful values. I believe we can assume that there are only two | ||
| 1885 | windows on the frame---the mini-buffer and the root window. Frame | ||
| 1886 | height and width seem to be correct so far. So, set the sizes of | ||
| 1887 | windows to estimated values. */ | ||
| 606 | 1888 | ||
| 607 | static void | 1889 | static void |
| 608 | rotate_vector (vector, size, distance) | 1890 | adjust_frame_glyphs_initially () |
| 609 | char *vector; | ||
| 610 | int size; | ||
| 611 | int distance; | ||
| 612 | { | 1891 | { |
| 613 | char *temp = (char *) alloca (size); | 1892 | struct window *root = XWINDOW (selected_frame->root_window); |
| 1893 | struct window *mini = XWINDOW (root->next); | ||
| 1894 | int frame_height = FRAME_HEIGHT (selected_frame); | ||
| 1895 | int frame_width = FRAME_WIDTH (selected_frame); | ||
| 1896 | int top_margin = FRAME_TOP_MARGIN (selected_frame); | ||
| 1897 | |||
| 1898 | /* Do it for the root window. */ | ||
| 1899 | XSETFASTINT (root->top, top_margin); | ||
| 1900 | XSETFASTINT (root->width, frame_width); | ||
| 1901 | set_window_height (selected_frame->root_window, | ||
| 1902 | frame_height - 1 - top_margin, 0); | ||
| 1903 | |||
| 1904 | /* Do it for the mini-buffer window. */ | ||
| 1905 | XSETFASTINT (mini->top, frame_height - 1); | ||
| 1906 | XSETFASTINT (mini->width, frame_width); | ||
| 1907 | set_window_height (root->next, 1, 0); | ||
| 1908 | |||
| 1909 | adjust_frame_glyphs (selected_frame); | ||
| 1910 | glyphs_initialized_initially_p = 1; | ||
| 1911 | } | ||
| 1912 | |||
| 614 | 1913 | ||
| 615 | if (distance < 0) | 1914 | /* Allocate/reallocate glyph matrices of a single frame F. */ |
| 616 | distance += size; | ||
| 617 | 1915 | ||
| 618 | bcopy (vector, temp + distance, size - distance); | 1916 | static void |
| 619 | bcopy (vector + size - distance, temp, distance); | 1917 | adjust_frame_glyphs (f) |
| 620 | bcopy (temp, vector, size); | 1918 | struct frame *f; |
| 1919 | { | ||
| 1920 | if (FRAME_WINDOW_P (f)) | ||
| 1921 | adjust_frame_glyphs_for_window_redisplay (f); | ||
| 1922 | else | ||
| 1923 | adjust_frame_glyphs_for_frame_redisplay (f); | ||
| 1924 | |||
| 1925 | /* Don't forget the message buffer and the buffer for | ||
| 1926 | decode_mode_spec. */ | ||
| 1927 | adjust_frame_message_buffer (f); | ||
| 1928 | adjust_decode_mode_spec_buffer (f); | ||
| 1929 | |||
| 1930 | f->glyphs_initialized_p = 1; | ||
| 621 | } | 1931 | } |
| 622 | 1932 | ||
| 623 | /* Scroll lines from vpos FROM up to but not including vpos END | ||
| 624 | down by AMOUNT lines (AMOUNT may be negative). | ||
| 625 | Returns nonzero if done, zero if terminal cannot scroll them. */ | ||
| 626 | 1933 | ||
| 627 | int | 1934 | /* Allocate/reallocate glyph matrices of a single frame F for |
| 628 | scroll_frame_lines (frame, from, end, amount, newpos) | 1935 | frame-based redisplay. */ |
| 629 | register FRAME_PTR frame; | 1936 | |
| 630 | int from, end, amount, newpos; | 1937 | static void |
| 1938 | adjust_frame_glyphs_for_frame_redisplay (f) | ||
| 1939 | struct frame *f; | ||
| 631 | { | 1940 | { |
| 632 | register int i; | 1941 | struct dim ch_dim; |
| 633 | register struct frame_glyphs *current_frame | 1942 | struct dim matrix_dim; |
| 634 | = FRAME_CURRENT_GLYPHS (frame); | 1943 | int pool_changed_p; |
| 635 | int pos_adjust; | 1944 | int window_change_flags; |
| 636 | int width = FRAME_WINDOW_WIDTH (frame); | 1945 | int top_window_y; |
| 637 | 1946 | ||
| 638 | if (!line_ins_del_ok) | 1947 | if (!FRAME_LIVE_P (f)) |
| 639 | return 0; | 1948 | return; |
| 640 | 1949 | ||
| 641 | if (amount == 0) | 1950 | /* Determine the smallest character in any font for F. On |
| 642 | return 1; | 1951 | console windows, all characters have dimension (1, 1). */ |
| 1952 | ch_dim.width = ch_dim.height = 1; | ||
| 1953 | |||
| 1954 | top_window_y = FRAME_TOP_MARGIN (f); | ||
| 643 | 1955 | ||
| 644 | if (amount > 0) | 1956 | /* Allocate glyph pool structures if not already done. */ |
| 1957 | if (f->desired_pool == NULL) | ||
| 645 | { | 1958 | { |
| 646 | update_begin (frame); | 1959 | f->desired_pool = new_glyph_pool (); |
| 647 | set_terminal_window (end + amount); | 1960 | f->current_pool = new_glyph_pool (); |
| 648 | if (!scroll_region_ok) | 1961 | } |
| 649 | ins_del_lines (end, -amount); | ||
| 650 | ins_del_lines (from, amount); | ||
| 651 | set_terminal_window (0); | ||
| 652 | 1962 | ||
| 653 | rotate_vector (current_frame->glyphs + from, | 1963 | /* Allocate frames matrix structures if needed. */ |
| 654 | sizeof (GLYPH *) * (end + amount - from), | 1964 | if (f->desired_matrix == NULL) |
| 655 | amount * sizeof (GLYPH *)); | 1965 | { |
| 1966 | f->desired_matrix = new_glyph_matrix (f->desired_pool); | ||
| 1967 | f->current_matrix = new_glyph_matrix (f->current_pool); | ||
| 1968 | } | ||
| 1969 | |||
| 1970 | /* Compute window glyph matrices. (This takes the mini-buffer | ||
| 1971 | window into account). The result is the size of the frame glyph | ||
| 1972 | matrix needed. The variable window_change_flags is set to a bit | ||
| 1973 | mask indicating whether new matrices will be allocated or | ||
| 1974 | existing matrices change their size or location within the frame | ||
| 1975 | matrix. */ | ||
| 1976 | window_change_flags = 0; | ||
| 1977 | matrix_dim | ||
| 1978 | = allocate_matrices_for_frame_redisplay (FRAME_ROOT_WINDOW (f), | ||
| 1979 | 0, top_window_y, | ||
| 1980 | ch_dim, 1, | ||
| 1981 | &window_change_flags); | ||
| 1982 | |||
| 1983 | /* Add in menu bar lines, if any. */ | ||
| 1984 | matrix_dim.height += top_window_y; | ||
| 1985 | |||
| 1986 | /* Enlarge pools as necessary. */ | ||
| 1987 | pool_changed_p = realloc_glyph_pool (f->desired_pool, matrix_dim); | ||
| 1988 | realloc_glyph_pool (f->current_pool, matrix_dim); | ||
| 1989 | |||
| 1990 | /* Set up glyph pointers within window matrices. Do this only if | ||
| 1991 | absolutely necessary since it requires a frame redraw. */ | ||
| 1992 | if (pool_changed_p || window_change_flags) | ||
| 1993 | { | ||
| 1994 | /* Do it for window matrices. */ | ||
| 1995 | allocate_matrices_for_frame_redisplay (FRAME_ROOT_WINDOW (f), | ||
| 1996 | 0, top_window_y, ch_dim, 0, | ||
| 1997 | &window_change_flags); | ||
| 1998 | |||
| 1999 | /* Size of frame matrices must equal size of frame. Note | ||
| 2000 | that we are called for X frames with window widths NOT equal | ||
| 2001 | to the frame width (from CHANGE_FRAME_SIZE_1). */ | ||
| 2002 | xassert (matrix_dim.width == FRAME_WIDTH (f) | ||
| 2003 | && matrix_dim.height == FRAME_HEIGHT (f)); | ||
| 2004 | |||
| 2005 | /* Resize frame matrices. */ | ||
| 2006 | adjust_glyph_matrix (NULL, f->desired_matrix, 0, 0, matrix_dim); | ||
| 2007 | adjust_glyph_matrix (NULL, f->current_matrix, 0, 0, matrix_dim); | ||
| 2008 | |||
| 2009 | /* Since location and size of sub-matrices within the pool may | ||
| 2010 | have changed, and current matrices don't have meaningful | ||
| 2011 | contents anymore, mark the frame garbaged. */ | ||
| 2012 | SET_FRAME_GARBAGED (f); | ||
| 2013 | } | ||
| 2014 | } | ||
| 656 | 2015 | ||
| 657 | rotate_vector (current_frame->charstarts + from, | ||
| 658 | sizeof (int *) * (end + amount - from), | ||
| 659 | amount * sizeof (int *)); | ||
| 660 | 2016 | ||
| 661 | safe_bcopy (current_frame->used + from, | 2017 | /* Allocate/reallocate glyph matrices of a single frame F for |
| 662 | current_frame->used + from + amount, | 2018 | window-based redisplay. */ |
| 663 | (end - from) * sizeof current_frame->used[0]); | ||
| 664 | 2019 | ||
| 665 | safe_bcopy (current_frame->highlight + from, | 2020 | static void |
| 666 | current_frame->highlight + from + amount, | 2021 | adjust_frame_glyphs_for_window_redisplay (f) |
| 667 | (end - from) * sizeof current_frame->highlight[0]); | 2022 | struct frame *f; |
| 2023 | { | ||
| 2024 | struct dim ch_dim; | ||
| 2025 | struct window *w; | ||
| 668 | 2026 | ||
| 669 | safe_bcopy (current_frame->enable + from, | 2027 | xassert (FRAME_WINDOW_P (f) && FRAME_LIVE_P (f)); |
| 670 | current_frame->enable + from + amount, | 2028 | |
| 671 | (end - from) * sizeof current_frame->enable[0]); | 2029 | /* Get minimum sizes. */ |
| 2030 | #ifdef HAVE_WINDOW_SYSTEM | ||
| 2031 | ch_dim.width = FRAME_SMALLEST_CHAR_WIDTH (f); | ||
| 2032 | ch_dim.height = FRAME_SMALLEST_FONT_HEIGHT (f); | ||
| 2033 | #else | ||
| 2034 | ch_dim.width = ch_dim.height = 1; | ||
| 2035 | #endif | ||
| 2036 | |||
| 2037 | /* Allocate/reallocate window matrices. */ | ||
| 2038 | allocate_matrices_for_window_redisplay (XWINDOW (FRAME_ROOT_WINDOW (f)), | ||
| 2039 | ch_dim); | ||
| 672 | 2040 | ||
| 673 | /* Adjust the lines by an amount | 2041 | /* Allocate/ reallocate matrices of the dummy window used to display |
| 674 | that puts the first of them at NEWPOS. */ | 2042 | the menu bar under X when no X toolkit support is available. */ |
| 675 | pos_adjust = newpos - current_frame->charstarts[from + amount][0]; | 2043 | #ifndef USE_X_TOOLKIT |
| 2044 | { | ||
| 2045 | /* Allocate a dummy window if not already done. */ | ||
| 2046 | if (NILP (f->menu_bar_window)) | ||
| 2047 | { | ||
| 2048 | f->menu_bar_window = make_window (); | ||
| 2049 | w = XWINDOW (f->menu_bar_window); | ||
| 2050 | XSETFRAME (w->frame, f); | ||
| 2051 | w->pseudo_window_p = 1; | ||
| 2052 | } | ||
| 2053 | else | ||
| 2054 | w = XWINDOW (f->menu_bar_window); | ||
| 2055 | |||
| 2056 | /* Set window dimensions to frame dimensions and allocate or | ||
| 2057 | adjust glyph matrices of W. */ | ||
| 2058 | XSETFASTINT (w->top, 0); | ||
| 2059 | XSETFASTINT (w->left, 0); | ||
| 2060 | XSETFASTINT (w->height, FRAME_MENU_BAR_LINES (f)); | ||
| 2061 | XSETFASTINT (w->width, FRAME_WINDOW_WIDTH (f)); | ||
| 2062 | allocate_matrices_for_window_redisplay (w, ch_dim); | ||
| 2063 | } | ||
| 2064 | #endif /* not USE_X_TOOLKIT */ | ||
| 676 | 2065 | ||
| 677 | /* Offset each char position in the charstarts lines we moved | 2066 | /* Allocate/ reallocate matrices of the toolbar window. If we don't |
| 678 | by pos_adjust. */ | 2067 | have a toolbar window yet, make one. */ |
| 679 | for (i = from + amount; i < end + amount; i++) | 2068 | if (NILP (f->toolbar_window)) |
| 680 | { | 2069 | { |
| 681 | int *line = current_frame->charstarts[i]; | 2070 | f->toolbar_window = make_window (); |
| 682 | int col; | 2071 | w = XWINDOW (f->toolbar_window); |
| 683 | for (col = 0; col < width; col++) | 2072 | XSETFRAME (w->frame, f); |
| 684 | if (line[col] > 0) | 2073 | w->pseudo_window_p = 1; |
| 685 | line[col] += pos_adjust; | 2074 | } |
| 686 | } | 2075 | else |
| 687 | for (i = from; i < from + amount; i++) | 2076 | w = XWINDOW (f->toolbar_window); |
| 688 | { | ||
| 689 | int *line = current_frame->charstarts[i]; | ||
| 690 | int col; | ||
| 691 | line[0] = -1; | ||
| 692 | for (col = 0; col < width; col++) | ||
| 693 | line[col] = 0; | ||
| 694 | } | ||
| 695 | 2077 | ||
| 696 | /* Mark the lines made empty by scrolling as enabled, empty and | 2078 | XSETFASTINT (w->top, FRAME_MENU_BAR_LINES (f)); |
| 697 | normal video. */ | 2079 | XSETFASTINT (w->left, 0); |
| 698 | bzero (current_frame->used + from, | 2080 | XSETFASTINT (w->height, FRAME_TOOLBAR_LINES (f)); |
| 699 | amount * sizeof current_frame->used[0]); | 2081 | XSETFASTINT (w->width, FRAME_WINDOW_WIDTH (f)); |
| 700 | bzero (current_frame->highlight + from, | 2082 | allocate_matrices_for_window_redisplay (w, ch_dim); |
| 701 | amount * sizeof current_frame->highlight[0]); | 2083 | } |
| 702 | for (i = from; i < from + amount; i++) | ||
| 703 | { | ||
| 704 | current_frame->glyphs[i][0] = '\0'; | ||
| 705 | current_frame->charstarts[i][0] = -1; | ||
| 706 | current_frame->enable[i] = 1; | ||
| 707 | } | ||
| 708 | 2084 | ||
| 709 | safe_bcopy (current_frame->bufp + from, | ||
| 710 | current_frame->bufp + from + amount, | ||
| 711 | (end - from) * sizeof current_frame->bufp[0]); | ||
| 712 | 2085 | ||
| 713 | #ifdef HAVE_WINDOW_SYSTEM | 2086 | /* Adjust/ allocate message buffer of frame F. |
| 714 | if (FRAME_WINDOW_P (frame)) | ||
| 715 | { | ||
| 716 | safe_bcopy (current_frame->top_left_x + from, | ||
| 717 | current_frame->top_left_x + from + amount, | ||
| 718 | (end - from) * sizeof current_frame->top_left_x[0]); | ||
| 719 | 2087 | ||
| 720 | safe_bcopy (current_frame->top_left_y + from, | 2088 | The global variables echo_area_glyphs and previous_echo_area_glyphs |
| 721 | current_frame->top_left_y + from + amount, | 2089 | may be pointing to the frames message buffer and must be relocated |
| 722 | (end - from) * sizeof current_frame->top_left_y[0]); | 2090 | if the buffer is reallocated. |
| 723 | 2091 | ||
| 724 | safe_bcopy (current_frame->pix_width + from, | 2092 | Note that the message buffer is never freed. Since I could not |
| 725 | current_frame->pix_width + from + amount, | 2093 | find a free in 19.34, I assume that freeing it would be |
| 726 | (end - from) * sizeof current_frame->pix_width[0]); | 2094 | problematic in some way and don't do it either. |
| 727 | 2095 | ||
| 728 | safe_bcopy (current_frame->pix_height + from, | 2096 | (Implementation note: It should be checked if we can free it |
| 729 | current_frame->pix_height + from + amount, | 2097 | eventually without causing trouble). */ |
| 730 | (end - from) * sizeof current_frame->pix_height[0]); | ||
| 731 | 2098 | ||
| 732 | safe_bcopy (current_frame->max_ascent + from, | 2099 | static void |
| 733 | current_frame->max_ascent + from + amount, | 2100 | adjust_frame_message_buffer (f) |
| 734 | (end - from) * sizeof current_frame->max_ascent[0]); | 2101 | struct frame *f; |
| 735 | } | 2102 | { |
| 736 | #endif /* HAVE_WINDOW_SYSTEM */ | 2103 | int size = FRAME_MESSAGE_BUF_SIZE (f) + 1; |
| 737 | 2104 | ||
| 738 | update_end (frame); | 2105 | if (FRAME_MESSAGE_BUF (f)) |
| 739 | } | ||
| 740 | if (amount < 0) | ||
| 741 | { | 2106 | { |
| 742 | update_begin (frame); | 2107 | char *buffer = FRAME_MESSAGE_BUF (f); |
| 743 | set_terminal_window (end); | 2108 | char *new_buffer = (char *) xrealloc (buffer, size); |
| 744 | ins_del_lines (from + amount, amount); | 2109 | |
| 745 | if (!scroll_region_ok) | 2110 | if (buffer == echo_area_glyphs) |
| 746 | ins_del_lines (end + amount, -amount); | 2111 | echo_area_glyphs = new_buffer; |
| 747 | set_terminal_window (0); | 2112 | if (buffer == previous_echo_glyphs) |
| 2113 | previous_echo_glyphs = new_buffer; | ||
| 748 | 2114 | ||
| 749 | rotate_vector (current_frame->glyphs + from + amount, | 2115 | FRAME_MESSAGE_BUF (f) = new_buffer; |
| 750 | sizeof (GLYPH *) * (end - from - amount), | 2116 | } |
| 751 | amount * sizeof (GLYPH *)); | 2117 | else |
| 2118 | FRAME_MESSAGE_BUF (f) = (char *) xmalloc (size); | ||
| 2119 | } | ||
| 752 | 2120 | ||
| 753 | rotate_vector (current_frame->charstarts + from + amount, | ||
| 754 | sizeof (int *) * (end - from - amount), | ||
| 755 | amount * sizeof (int *)); | ||
| 756 | 2121 | ||
| 757 | safe_bcopy (current_frame->used + from, | 2122 | /* Re-allocate buffer for decode_mode_spec on frame F. */ |
| 758 | current_frame->used + from + amount, | ||
| 759 | (end - from) * sizeof current_frame->used[0]); | ||
| 760 | 2123 | ||
| 761 | safe_bcopy (current_frame->highlight + from, | 2124 | static void |
| 762 | current_frame->highlight + from + amount, | 2125 | adjust_decode_mode_spec_buffer (f) |
| 763 | (end - from) * sizeof current_frame->highlight[0]); | 2126 | struct frame *f; |
| 2127 | { | ||
| 2128 | f->decode_mode_spec_buffer | ||
| 2129 | = (char *) xrealloc (f->decode_mode_spec_buffer, | ||
| 2130 | FRAME_MESSAGE_BUF_SIZE (f) + 1); | ||
| 2131 | } | ||
| 764 | 2132 | ||
| 765 | safe_bcopy (current_frame->enable + from, | ||
| 766 | current_frame->enable + from + amount, | ||
| 767 | (end - from) * sizeof current_frame->enable[0]); | ||
| 768 | 2133 | ||
| 769 | /* Adjust the lines by an amount | 2134 | |
| 770 | that puts the first of them at NEWPOS. */ | 2135 | /********************************************************************** |
| 771 | pos_adjust = newpos - current_frame->charstarts[from + amount][0]; | 2136 | Freeing Glyph Matrices |
| 2137 | **********************************************************************/ | ||
| 2138 | |||
| 2139 | /* Free glyph memory for a frame F. F may be null. This function can | ||
| 2140 | be called for the same frame more than once. The root window of | ||
| 2141 | F may be nil when this function is called. This is the case when | ||
| 2142 | the function is called when F is destroyed. */ | ||
| 772 | 2143 | ||
| 773 | /* Offset each char position in the charstarts lines we moved | 2144 | void |
| 774 | by pos_adjust. */ | 2145 | free_glyphs (f) |
| 775 | for (i = from + amount; i < end + amount; i++) | 2146 | struct frame *f; |
| 2147 | { | ||
| 2148 | if (f && f->glyphs_initialized_p) | ||
| 2149 | { | ||
| 2150 | f->glyphs_initialized_p = 0; | ||
| 2151 | |||
| 2152 | /* Release window sub-matrices. */ | ||
| 2153 | if (!NILP (f->root_window)) | ||
| 2154 | free_window_matrices (XWINDOW (f->root_window)); | ||
| 2155 | |||
| 2156 | /* Free the dummy window for menu bars without X toolkit and its | ||
| 2157 | glyph matrices. */ | ||
| 2158 | if (!NILP (f->menu_bar_window)) | ||
| 776 | { | 2159 | { |
| 777 | int *line = current_frame->charstarts[i]; | 2160 | struct window *w = XWINDOW (f->menu_bar_window); |
| 778 | int col; | 2161 | free_glyph_matrix (w->desired_matrix); |
| 779 | for (col = 0; col < width; col++) | 2162 | free_glyph_matrix (w->current_matrix); |
| 780 | if (line[col] > 0) | 2163 | w->desired_matrix = w->current_matrix = NULL; |
| 781 | line[col] += pos_adjust; | 2164 | f->menu_bar_window = Qnil; |
| 782 | } | 2165 | } |
| 783 | for (i = end + amount; i < end; i++) | 2166 | |
| 2167 | /* Free the toolbar window and its glyph matrices. */ | ||
| 2168 | if (!NILP (f->toolbar_window)) | ||
| 784 | { | 2169 | { |
| 785 | int *line = current_frame->charstarts[i]; | 2170 | struct window *w = XWINDOW (f->toolbar_window); |
| 786 | int col; | 2171 | free_glyph_matrix (w->desired_matrix); |
| 787 | line[0] = -1; | 2172 | free_glyph_matrix (w->current_matrix); |
| 788 | for (col = 0; col < width; col++) | 2173 | w->desired_matrix = w->current_matrix = NULL; |
| 789 | line[col] = 0; | 2174 | f->toolbar_window = Qnil; |
| 790 | } | 2175 | } |
| 791 | 2176 | ||
| 792 | /* Mark the lines made empty by scrolling as enabled, empty and | 2177 | /* Release frame glyph matrices. Reset fields to zero in |
| 793 | normal video. */ | 2178 | case we are called a second time. */ |
| 794 | bzero (current_frame->used + end + amount, | 2179 | if (f->desired_matrix) |
| 795 | - amount * sizeof current_frame->used[0]); | ||
| 796 | bzero (current_frame->highlight + end + amount, | ||
| 797 | - amount * sizeof current_frame->highlight[0]); | ||
| 798 | for (i = end + amount; i < end; i++) | ||
| 799 | { | 2180 | { |
| 800 | current_frame->glyphs[i][0] = '\0'; | 2181 | free_glyph_matrix (f->desired_matrix); |
| 801 | current_frame->charstarts[i][0] = 0; | 2182 | free_glyph_matrix (f->current_matrix); |
| 802 | current_frame->enable[i] = 1; | 2183 | f->desired_matrix = f->current_matrix = NULL; |
| 803 | } | 2184 | } |
| 804 | 2185 | ||
| 805 | safe_bcopy (current_frame->bufp + from, | 2186 | /* Release glyph pools. */ |
| 806 | current_frame->bufp + from + amount, | 2187 | if (f->desired_pool) |
| 807 | (end - from) * sizeof current_frame->bufp[0]); | ||
| 808 | |||
| 809 | #ifdef HAVE_WINDOW_SYSTEM | ||
| 810 | if (FRAME_WINDOW_P (frame)) | ||
| 811 | { | 2188 | { |
| 812 | safe_bcopy (current_frame->top_left_x + from, | 2189 | free_glyph_pool (f->desired_pool); |
| 813 | current_frame->top_left_x + from + amount, | 2190 | free_glyph_pool (f->current_pool); |
| 814 | (end - from) * sizeof current_frame->top_left_x[0]); | 2191 | f->desired_pool = f->current_pool = NULL; |
| 815 | 2192 | } | |
| 816 | safe_bcopy (current_frame->top_left_y + from, | 2193 | } |
| 817 | current_frame->top_left_y + from + amount, | 2194 | } |
| 818 | (end - from) * sizeof current_frame->top_left_y[0]); | ||
| 819 | 2195 | ||
| 820 | safe_bcopy (current_frame->pix_width + from, | ||
| 821 | current_frame->pix_width + from + amount, | ||
| 822 | (end - from) * sizeof current_frame->pix_width[0]); | ||
| 823 | 2196 | ||
| 824 | safe_bcopy (current_frame->pix_height + from, | 2197 | /* Free glyph sub-matrices in the window tree rooted at W. This |
| 825 | current_frame->pix_height + from + amount, | 2198 | function may be called with a null pointer, and it may be called on |
| 826 | (end - from) * sizeof current_frame->pix_height[0]); | 2199 | the same tree more than once. */ |
| 827 | 2200 | ||
| 828 | safe_bcopy (current_frame->max_ascent + from, | 2201 | void |
| 829 | current_frame->max_ascent + from + amount, | 2202 | free_window_matrices (w) |
| 830 | (end - from) * sizeof current_frame->max_ascent[0]); | 2203 | struct window *w; |
| 2204 | { | ||
| 2205 | while (w) | ||
| 2206 | { | ||
| 2207 | if (!NILP (w->hchild)) | ||
| 2208 | free_window_matrices (XWINDOW (w->hchild)); | ||
| 2209 | else if (!NILP (w->vchild)) | ||
| 2210 | free_window_matrices (XWINDOW (w->vchild)); | ||
| 2211 | else | ||
| 2212 | { | ||
| 2213 | /* This is a leaf window. Free its memory and reset fields | ||
| 2214 | to zero in case this function is called a second time for | ||
| 2215 | W. */ | ||
| 2216 | free_glyph_matrix (w->current_matrix); | ||
| 2217 | free_glyph_matrix (w->desired_matrix); | ||
| 2218 | w->current_matrix = w->desired_matrix = NULL; | ||
| 831 | } | 2219 | } |
| 832 | #endif /* HAVE_WINDOW_SYSTEM */ | ||
| 833 | 2220 | ||
| 834 | update_end (frame); | 2221 | /* Next window on same level. */ |
| 2222 | w = NILP (w->next) ? 0 : XWINDOW (w->next); | ||
| 835 | } | 2223 | } |
| 836 | return 1; | ||
| 837 | } | 2224 | } |
| 838 | 2225 | ||
| 839 | /* After updating a window W that isn't the full frame wide, | 2226 | |
| 840 | copy all the columns that W does not occupy | 2227 | /* Check glyph memory leaks. This function is called from |
| 841 | into the FRAME_DESIRED_GLYPHS (frame) from the FRAME_PHYS_GLYPHS (frame) | 2228 | shut_down_emacs. Note that frames are not destroyed when Emacs |
| 842 | so that update_frame will not change those columns. */ | 2229 | exits. We therefore free all glyph memory for all active frames |
| 2230 | explicitly and check that nothing is left allocated. */ | ||
| 843 | 2231 | ||
| 844 | void | 2232 | void |
| 845 | preserve_other_columns (w) | 2233 | check_glyph_memory () |
| 2234 | { | ||
| 2235 | Lisp_Object tail, frame; | ||
| 2236 | |||
| 2237 | /* Free glyph memory for all frames. */ | ||
| 2238 | FOR_EACH_FRAME (tail, frame) | ||
| 2239 | free_glyphs (XFRAME (frame)); | ||
| 2240 | |||
| 2241 | /* Check that nothing is left allocated. */ | ||
| 2242 | if (glyph_matrix_count) | ||
| 2243 | abort (); | ||
| 2244 | if (glyph_pool_count) | ||
| 2245 | abort (); | ||
| 2246 | } | ||
| 2247 | |||
| 2248 | |||
| 2249 | |||
| 2250 | /********************************************************************** | ||
| 2251 | Building a Frame Matrix | ||
| 2252 | **********************************************************************/ | ||
| 2253 | |||
| 2254 | /* Most of the redisplay code works on glyph matrices attached to | ||
| 2255 | windows. This is a good solution most of the time, but it is not | ||
| 2256 | suitable for terminal code. Terminal output functions cannot rely | ||
| 2257 | on being able to set an arbitrary terminal window. Instead they | ||
| 2258 | must be provided with a view of the whole frame, i.e. the whole | ||
| 2259 | screen. We build such a view by constructing a frame matrix from | ||
| 2260 | window matrices in this section. | ||
| 2261 | |||
| 2262 | Windows that must be updated have their must_be_update_p flag set. | ||
| 2263 | For all such windows, their desired matrix is made part of the | ||
| 2264 | desired frame matrix. For other windows, their current matrix is | ||
| 2265 | made part of the desired frame matrix. | ||
| 2266 | |||
| 2267 | +-----------------+----------------+ | ||
| 2268 | | desired | desired | | ||
| 2269 | | | | | ||
| 2270 | +-----------------+----------------+ | ||
| 2271 | | current | | ||
| 2272 | | | | ||
| 2273 | +----------------------------------+ | ||
| 2274 | |||
| 2275 | Desired window matrices can be made part of the frame matrix in a | ||
| 2276 | cheap way: We exploit the fact that the desired frame matrix and | ||
| 2277 | desired window matrices share their glyph memory. This is not | ||
| 2278 | possible for current window matrices. Their glyphs are copied to | ||
| 2279 | the desired frame matrix. The latter is equivalent to | ||
| 2280 | preserve_other_columns in the old redisplay. | ||
| 2281 | |||
| 2282 | Used glyphs counters for frame matrix rows are the result of adding | ||
| 2283 | up glyph lengths of the window matrices. A line in the frame | ||
| 2284 | matrix is enabled, if a corresponding line in a window matrix is | ||
| 2285 | enabled. | ||
| 2286 | |||
| 2287 | After building the desired frame matrix, it will be passed to | ||
| 2288 | terminal code, which will manipulate both the desired and current | ||
| 2289 | frame matrix. Changes applied to the frame's current matrix have | ||
| 2290 | to be visible in current window matrices afterwards, of course. | ||
| 2291 | |||
| 2292 | This problem is solved like this: | ||
| 2293 | |||
| 2294 | 1. Window and frame matrices share glyphs. Window matrices are | ||
| 2295 | constructed in a way that their glyph contents ARE the glyph | ||
| 2296 | contents needed in a frame matrix. Thus, any modification of | ||
| 2297 | glyphs done in terminal code will be reflected in window matrices | ||
| 2298 | automatically. | ||
| 2299 | |||
| 2300 | 2. Exchanges of rows in a frame matrix done by terminal code are | ||
| 2301 | intercepted by hook functions so that corresponding row operations | ||
| 2302 | on window matrices can be performed. This is necessary because we | ||
| 2303 | use pointers to glyphs in glyph row structures. To satisfy the | ||
| 2304 | assumption of point 1 above that glyphs are updated implicitly in | ||
| 2305 | window matrices when they are manipulated via the frame matrix, | ||
| 2306 | window and frame matrix must of course agree where to find the | ||
| 2307 | glyphs for their rows. Possible manipulations that must be | ||
| 2308 | mirrored are assignments of rows of the desired frame matrix to the | ||
| 2309 | current frame matrix and scrolling the current frame matrix. */ | ||
| 2310 | |||
| 2311 | /* Build frame F's desired matrix from window matrices. Only windows | ||
| 2312 | which have the flag must_be_updated_p set have to be updated. Menu | ||
| 2313 | bar lines of a frame are not covered by window matrices, so make | ||
| 2314 | sure not to touch them in this function. */ | ||
| 2315 | |||
| 2316 | static void | ||
| 2317 | build_frame_matrix (f) | ||
| 2318 | struct frame *f; | ||
| 2319 | { | ||
| 2320 | int i; | ||
| 2321 | |||
| 2322 | /* F must have a frame matrix when this function is called. */ | ||
| 2323 | xassert (!FRAME_WINDOW_P (f)); | ||
| 2324 | |||
| 2325 | /* Clear all rows in the frame matrix covered by window matrices. | ||
| 2326 | Menu bar lines are not covered by windows. */ | ||
| 2327 | for (i = FRAME_TOP_MARGIN (f); i < f->desired_matrix->nrows; ++i) | ||
| 2328 | clear_glyph_row (MATRIX_ROW (f->desired_matrix, i)); | ||
| 2329 | |||
| 2330 | /* Build the matrix by walking the window tree. */ | ||
| 2331 | build_frame_matrix_from_window_tree (f->desired_matrix, | ||
| 2332 | XWINDOW (FRAME_ROOT_WINDOW (f))); | ||
| 2333 | } | ||
| 2334 | |||
| 2335 | |||
| 2336 | /* Walk a window tree, building a frame matrix MATRIX from window | ||
| 2337 | matrices. W is the root of a window tree. */ | ||
| 2338 | |||
| 2339 | static void | ||
| 2340 | build_frame_matrix_from_window_tree (matrix, w) | ||
| 2341 | struct glyph_matrix *matrix; | ||
| 846 | struct window *w; | 2342 | struct window *w; |
| 847 | { | 2343 | { |
| 848 | register int vpos; | 2344 | while (w) |
| 849 | register struct frame_glyphs *current_frame, *desired_frame; | 2345 | { |
| 850 | register FRAME_PTR frame = XFRAME (w->frame); | 2346 | if (!NILP (w->hchild)) |
| 851 | int start = WINDOW_LEFT_MARGIN (w); | 2347 | build_frame_matrix_from_window_tree (matrix, XWINDOW (w->hchild)); |
| 852 | int end = WINDOW_RIGHT_EDGE (w); | 2348 | else if (!NILP (w->vchild)) |
| 853 | int bot = XFASTINT (w->top) + XFASTINT (w->height); | 2349 | build_frame_matrix_from_window_tree (matrix, XWINDOW (w->vchild)); |
| 2350 | else | ||
| 2351 | build_frame_matrix_from_leaf_window (matrix, w); | ||
| 854 | 2352 | ||
| 855 | current_frame = FRAME_CURRENT_GLYPHS (frame); | 2353 | w = NILP (w->next) ? 0 : XWINDOW (w->next); |
| 856 | desired_frame = FRAME_DESIRED_GLYPHS (frame); | 2354 | } |
| 2355 | } | ||
| 2356 | |||
| 2357 | |||
| 2358 | /* Add a window's matrix to a frame matrix. FRAME_MATRIX is the | ||
| 2359 | desired frame matrix built. W is a leaf window whose desired or | ||
| 2360 | current matrix is to be added to FRAME_MATRIX. W's flag | ||
| 2361 | must_be_updated_p determines which matrix it contributes to | ||
| 2362 | FRAME_MATRIX. If must_be_updated_p is non-zero, W's desired matrix | ||
| 2363 | is added to FRAME_MATRIX, otherwise W's current matrix is added. | ||
| 2364 | Adding a desired matrix means setting up used counters and such in | ||
| 2365 | frame rows, while adding a current window matrix to FRAME_MATRIX | ||
| 2366 | means copying glyphs. The latter case corresponds to | ||
| 2367 | preserve_other_columns in the old redisplay. */ | ||
| 2368 | |||
| 2369 | static void | ||
| 2370 | build_frame_matrix_from_leaf_window (frame_matrix, w) | ||
| 2371 | struct glyph_matrix *frame_matrix; | ||
| 2372 | struct window *w; | ||
| 2373 | { | ||
| 2374 | struct glyph_matrix *window_matrix; | ||
| 2375 | int window_y, frame_y; | ||
| 2376 | /* If non-zero, a glyph to insert at the right border of W. */ | ||
| 2377 | GLYPH right_border_glyph = 0; | ||
| 857 | 2378 | ||
| 858 | for (vpos = XFASTINT (w->top); vpos < bot; vpos++) | 2379 | /* Set window_matrix to the matrix we have to add to FRAME_MATRIX. */ |
| 2380 | if (w->must_be_updated_p) | ||
| 859 | { | 2381 | { |
| 860 | if (current_frame->enable[vpos] && desired_frame->enable[vpos]) | 2382 | window_matrix = w->desired_matrix; |
| 2383 | |||
| 2384 | /* Decide whether we want to add a vertical border glyph. */ | ||
| 2385 | if (!WINDOW_RIGHTMOST_P (w)) | ||
| 861 | { | 2386 | { |
| 862 | if (start > 0) | 2387 | struct Lisp_Char_Table *dp = window_display_table (w); |
| 2388 | right_border_glyph = (dp && INTEGERP (DISP_BORDER_GLYPH (dp)) | ||
| 2389 | ? XINT (DISP_BORDER_GLYPH (dp)) | ||
| 2390 | : '|'); | ||
| 2391 | } | ||
| 2392 | } | ||
| 2393 | else | ||
| 2394 | window_matrix = w->current_matrix; | ||
| 2395 | |||
| 2396 | /* For all rows in the window matrix and corresponding rows in the | ||
| 2397 | frame matrix. */ | ||
| 2398 | window_y = 0; | ||
| 2399 | frame_y = window_matrix->matrix_y; | ||
| 2400 | while (window_y < window_matrix->nrows) | ||
| 2401 | { | ||
| 2402 | struct glyph_row *frame_row = frame_matrix->rows + frame_y; | ||
| 2403 | struct glyph_row *window_row = window_matrix->rows + window_y; | ||
| 2404 | |||
| 2405 | /* Fill up the frame row with spaces up to the left margin of the | ||
| 2406 | window row. */ | ||
| 2407 | fill_up_frame_row_with_spaces (frame_row, window_matrix->matrix_x); | ||
| 2408 | |||
| 2409 | /* Fill up areas in the window matrix row with spaces. */ | ||
| 2410 | fill_up_glyph_row_with_spaces (window_row); | ||
| 2411 | |||
| 2412 | if (window_matrix == w->current_matrix) | ||
| 2413 | { | ||
| 2414 | /* We have to copy W's current matrix. Copy window | ||
| 2415 | row to frame row. */ | ||
| 2416 | bcopy (window_row->glyphs[0], | ||
| 2417 | frame_row->glyphs[TEXT_AREA] + window_matrix->matrix_x, | ||
| 2418 | window_matrix->matrix_w * sizeof (struct glyph)); | ||
| 2419 | } | ||
| 2420 | else | ||
| 2421 | { | ||
| 2422 | /* Copy W's desired matrix. */ | ||
| 2423 | |||
| 2424 | /* Maybe insert a vertical border between horizontally adjacent | ||
| 2425 | windows. */ | ||
| 2426 | if (right_border_glyph) | ||
| 863 | { | 2427 | { |
| 864 | int len; | 2428 | struct glyph *border = window_row->glyphs[LAST_AREA] - 1; |
| 865 | 2429 | SET_CHAR_GLYPH_FROM_GLYPH (*border, right_border_glyph); | |
| 866 | bcopy (current_frame->glyphs[vpos], | ||
| 867 | desired_frame->glyphs[vpos], | ||
| 868 | start * sizeof (current_frame->glyphs[vpos][0])); | ||
| 869 | bcopy (current_frame->charstarts[vpos], | ||
| 870 | desired_frame->charstarts[vpos], | ||
| 871 | start * sizeof (current_frame->charstarts[vpos][0])); | ||
| 872 | len = min (start, current_frame->used[vpos]); | ||
| 873 | if (desired_frame->used[vpos] < len) | ||
| 874 | desired_frame->used[vpos] = len; | ||
| 875 | } | 2430 | } |
| 876 | if (current_frame->used[vpos] > end | 2431 | |
| 877 | && desired_frame->used[vpos] < current_frame->used[vpos]) | 2432 | /* Due to hooks installed, it normally doesn't happen that |
| 2433 | window rows and frame rows of the same matrix are out of | ||
| 2434 | sync, i.e. have a different understanding of where to | ||
| 2435 | find glyphs for the row. The following is a safety-belt | ||
| 2436 | that doesn't cost much and makes absolutely sure that | ||
| 2437 | window and frame matrices are in sync. */ | ||
| 2438 | if (!glyph_row_slice_p (window_row, frame_row)) | ||
| 878 | { | 2439 | { |
| 879 | while (desired_frame->used[vpos] < end) | 2440 | /* Find the row in the window being a slice. There |
| 880 | { | 2441 | should exist one from program logic. */ |
| 881 | int used = desired_frame->used[vpos]++; | 2442 | struct glyph_row *slice_row |
| 882 | desired_frame->glyphs[vpos][used] = SPACEGLYPH; | 2443 | = find_glyph_row_slice (window_matrix, frame_matrix, frame_y); |
| 883 | desired_frame->glyphs[vpos][used] = 0; | 2444 | xassert (slice_row != 0); |
| 884 | } | 2445 | |
| 885 | bcopy (current_frame->glyphs[vpos] + end, | 2446 | /* Exchange glyphs between both window rows. */ |
| 886 | desired_frame->glyphs[vpos] + end, | 2447 | swap_glyphs_in_rows (window_row, slice_row); |
| 887 | ((current_frame->used[vpos] - end) | 2448 | |
| 888 | * sizeof (current_frame->glyphs[vpos][0]))); | 2449 | /* Exchange pointers between both rows. */ |
| 889 | bcopy (current_frame->charstarts[vpos] + end, | 2450 | swap_glyph_pointers (window_row, slice_row); |
| 890 | desired_frame->charstarts[vpos] + end, | ||
| 891 | ((current_frame->used[vpos] - end) | ||
| 892 | * sizeof (current_frame->charstarts[vpos][0]))); | ||
| 893 | desired_frame->used[vpos] = current_frame->used[vpos]; | ||
| 894 | } | 2451 | } |
| 2452 | |||
| 2453 | /* Now, we are sure that window row window_y is a slice of | ||
| 2454 | the frame row frame_y. But, lets check that assumption. */ | ||
| 2455 | xassert (glyph_row_slice_p (window_row, frame_row)); | ||
| 2456 | |||
| 2457 | /* If rows are in sync, we don't have to copy glyphs because | ||
| 2458 | frame and window share glyphs. */ | ||
| 895 | } | 2459 | } |
| 2460 | |||
| 2461 | /* Set number of used glyphs in the frame matrix. Since we fill | ||
| 2462 | up with spaces, and visit leaf windows from left to right it | ||
| 2463 | can be done simply. */ | ||
| 2464 | frame_row->used[TEXT_AREA] | ||
| 2465 | = window_matrix->matrix_x + window_matrix->matrix_w; | ||
| 2466 | |||
| 2467 | /* Or in flags. */ | ||
| 2468 | frame_row->enabled_p |= window_row->enabled_p; | ||
| 2469 | frame_row->inverse_p |= window_row->inverse_p; | ||
| 2470 | |||
| 2471 | /* Next row. */ | ||
| 2472 | ++window_y; | ||
| 2473 | ++frame_y; | ||
| 2474 | } | ||
| 2475 | } | ||
| 2476 | |||
| 2477 | |||
| 2478 | /* Add spaces to a glyph row ROW in a window matrix. | ||
| 2479 | |||
| 2480 | Each row has the form: | ||
| 2481 | |||
| 2482 | +---------+-----------------------------+------------+ | ||
| 2483 | | left | text | right | | ||
| 2484 | +---------+-----------------------------+------------+ | ||
| 2485 | |||
| 2486 | Left and right marginal areas are optional. This function adds | ||
| 2487 | spaces to areas so that there are no empty holes between areas. | ||
| 2488 | In other words: If the right area is not empty, the text area | ||
| 2489 | is filled up with spaces up to the right area. If the text area | ||
| 2490 | is not empty, the left area is filled up. | ||
| 2491 | |||
| 2492 | To be called for frame-based redisplay, only. */ | ||
| 2493 | |||
| 2494 | static void | ||
| 2495 | fill_up_glyph_row_with_spaces (row) | ||
| 2496 | struct glyph_row *row; | ||
| 2497 | { | ||
| 2498 | fill_up_glyph_row_area_with_spaces (row, LEFT_MARGIN_AREA); | ||
| 2499 | fill_up_glyph_row_area_with_spaces (row, TEXT_AREA); | ||
| 2500 | fill_up_glyph_row_area_with_spaces (row, RIGHT_MARGIN_AREA); | ||
| 2501 | } | ||
| 2502 | |||
| 2503 | |||
| 2504 | /* Fill area AREA of glyph row ROW with spaces. To be called for | ||
| 2505 | frame-based redisplay only. */ | ||
| 2506 | |||
| 2507 | static void | ||
| 2508 | fill_up_glyph_row_area_with_spaces (row, area) | ||
| 2509 | struct glyph_row *row; | ||
| 2510 | int area; | ||
| 2511 | { | ||
| 2512 | if (row->glyphs[area] < row->glyphs[area + 1]) | ||
| 2513 | { | ||
| 2514 | struct glyph *end = row->glyphs[area + 1]; | ||
| 2515 | struct glyph *text = row->glyphs[area] + row->used[area]; | ||
| 2516 | |||
| 2517 | while (text < end) | ||
| 2518 | *text++ = space_glyph; | ||
| 2519 | row->used[area] = text - row->glyphs[area]; | ||
| 896 | } | 2520 | } |
| 897 | } | 2521 | } |
| 2522 | |||
| 2523 | |||
| 2524 | /* Add spaces to the end of ROW in a frame matrix until index UPTO is | ||
| 2525 | reached. In frame matrices only one area, TEXT_AREA, is used. */ | ||
| 2526 | |||
| 2527 | static void | ||
| 2528 | fill_up_frame_row_with_spaces (row, upto) | ||
| 2529 | struct glyph_row *row; | ||
| 2530 | int upto; | ||
| 2531 | { | ||
| 2532 | int i = row->used[TEXT_AREA]; | ||
| 2533 | struct glyph *glyph = row->glyphs[TEXT_AREA]; | ||
| 2534 | |||
| 2535 | while (i < upto) | ||
| 2536 | glyph[i++] = space_glyph; | ||
| 2537 | |||
| 2538 | row->used[TEXT_AREA] = i; | ||
| 2539 | } | ||
| 2540 | |||
| 2541 | |||
| 898 | 2542 | ||
| 899 | #if 0 | 2543 | /********************************************************************** |
| 2544 | Mirroring operations on frame matrices in window matrices | ||
| 2545 | **********************************************************************/ | ||
| 2546 | |||
| 2547 | /* Set frame being updated via frame-based redisplay to F. This | ||
| 2548 | function must be called before updates to make explicit that we are | ||
| 2549 | working on frame matrices or not. */ | ||
| 900 | 2550 | ||
| 901 | /* If window w does not need to be updated and isn't the full frame wide, | 2551 | static INLINE void |
| 902 | copy all the columns that w does occupy | 2552 | set_frame_matrix_frame (f) |
| 903 | into the FRAME_DESIRED_LINES (frame) from the FRAME_PHYS_LINES (frame) | 2553 | struct frame *f; |
| 904 | so that update_frame will not change those columns. | 2554 | { |
| 2555 | frame_matrix_frame = f; | ||
| 2556 | } | ||
| 905 | 2557 | ||
| 906 | Have not been able to figure out how to use this correctly. */ | ||
| 907 | 2558 | ||
| 908 | preserve_my_columns (w) | 2559 | /* Make sure glyph row ROW in CURRENT_MATRIX is up to date. |
| 909 | struct window *w; | 2560 | DESIRED_MATRIX is the desired matrix corresponding to |
| 2561 | CURRENT_MATRIX. The update is done by exchanging glyph pointers | ||
| 2562 | between rows in CURRENT_MATRIX and DESIRED_MATRIX. If | ||
| 2563 | frame_matrix_frame is non-null, this indicates that the exchange is | ||
| 2564 | done in frame matrices, and that we have to perform analogous | ||
| 2565 | operations in window matrices of frame_matrix_frame. */ | ||
| 2566 | |||
| 2567 | static INLINE void | ||
| 2568 | make_current (desired_matrix, current_matrix, row) | ||
| 2569 | struct glyph_matrix *desired_matrix, *current_matrix; | ||
| 2570 | int row; | ||
| 910 | { | 2571 | { |
| 911 | register int vpos, fin; | 2572 | struct glyph_row *current_row = MATRIX_ROW (current_matrix, row); |
| 912 | register struct frame_glyphs *l1, *l2; | 2573 | struct glyph_row *desired_row = MATRIX_ROW (desired_matrix, row); |
| 913 | register FRAME_PTR frame = XFRAME (w->frame); | 2574 | |
| 914 | int start = WINDOW_LEFT_MARGIN (w); | 2575 | /* Do current_row = desired_row. This exchanges glyph pointers |
| 915 | int end = WINDOW_RIGHT_EDGE (w); | 2576 | between both rows, and does a structure assignment otherwise. */ |
| 916 | int bot = XFASTINT (w->top) + XFASTINT (w->height); | 2577 | assign_row (current_row, desired_row); |
| 2578 | |||
| 2579 | /* Enable current_row to mark it as valid. */ | ||
| 2580 | current_row->enabled_p = 1; | ||
| 2581 | |||
| 2582 | /* If we are called on frame matrices, perform analogous operations | ||
| 2583 | for window matrices. */ | ||
| 2584 | if (frame_matrix_frame) | ||
| 2585 | mirror_make_current (XWINDOW (frame_matrix_frame->root_window), row); | ||
| 2586 | } | ||
| 2587 | |||
| 917 | 2588 | ||
| 918 | for (vpos = XFASTINT (w->top); vpos < bot; vpos++) | 2589 | /* W is the root of a window tree. FRAME_ROW is the index of a row in |
| 2590 | W's frame which has been made current (by swapping pointers between | ||
| 2591 | current and desired matrix). Perform analogous operations in the | ||
| 2592 | matrices of leaf windows in the window tree rooted at W. */ | ||
| 2593 | |||
| 2594 | static void | ||
| 2595 | mirror_make_current (w, frame_row) | ||
| 2596 | struct window *w; | ||
| 2597 | int frame_row; | ||
| 2598 | { | ||
| 2599 | while (w) | ||
| 919 | { | 2600 | { |
| 920 | if ((l1 = FRAME_DESIRED_GLYPHS (frame)->glyphs[vpos + 1]) | 2601 | if (!NILP (w->hchild)) |
| 921 | && (l2 = FRAME_PHYS_GLYPHS (frame)->glyphs[vpos + 1])) | 2602 | mirror_make_current (XWINDOW (w->hchild), frame_row); |
| 2603 | else if (!NILP (w->vchild)) | ||
| 2604 | mirror_make_current (XWINDOW (w->vchild), frame_row); | ||
| 2605 | else | ||
| 922 | { | 2606 | { |
| 923 | if (l2->length > start && l1->length < l2->length) | 2607 | /* Row relative to window W. Don't use FRAME_TO_WINDOW_VPOS |
| 2608 | here because the checks performed in debug mode there | ||
| 2609 | will not allow the conversion. */ | ||
| 2610 | int row = frame_row - w->desired_matrix->matrix_y; | ||
| 2611 | |||
| 2612 | /* If FRAME_ROW is within W, assign the desired row to the | ||
| 2613 | current row (exchanging glyph pointers). */ | ||
| 2614 | if (row >= 0 && row < w->desired_matrix->matrix_h) | ||
| 924 | { | 2615 | { |
| 925 | fin = l2->length; | 2616 | struct glyph_row *current_row |
| 926 | if (fin > end) fin = end; | 2617 | = MATRIX_ROW (w->current_matrix, row); |
| 927 | while (l1->length < start) | 2618 | struct glyph_row *desired_row |
| 928 | l1->body[l1->length++] = ' '; | 2619 | = MATRIX_ROW (w->desired_matrix, row); |
| 929 | bcopy (l2->body + start, l1->body + start, fin - start); | 2620 | |
| 930 | l1->length = fin; | 2621 | assign_row (current_row, desired_row); |
| 2622 | current_row->enabled_p = 1; | ||
| 931 | } | 2623 | } |
| 932 | } | 2624 | } |
| 2625 | |||
| 2626 | w = NILP (w->next) ? 0 : XWINDOW (w->next); | ||
| 933 | } | 2627 | } |
| 934 | } | 2628 | } |
| 935 | 2629 | ||
| 936 | #endif | ||
| 937 | |||
| 938 | /* Adjust by ADJUST the charstart values in window W | ||
| 939 | after vpos VPOS, which counts relative to the frame | ||
| 940 | (not relative to W itself). */ | ||
| 941 | 2630 | ||
| 2631 | /* Perform row dance after scrolling. We are working on the range of | ||
| 2632 | lines UNCHANGED_AT_TOP + 1 to UNCHANGED_AT_TOP + NLINES (not | ||
| 2633 | including) in MATRIX. COPY_FROM is a vector containing, for each | ||
| 2634 | row I in the range 0 <= I < NLINES, the index of the original line | ||
| 2635 | to move to I. This index is relative to the row range, i.e. 0 <= | ||
| 2636 | index < NLINES. RETAINED_P is a vector containing zero for each | ||
| 2637 | row 0 <= I < NLINES which is empty. | ||
| 2638 | |||
| 2639 | This function is called from do_scrolling and do_direct_scrolling. */ | ||
| 2640 | |||
| 942 | void | 2641 | void |
| 943 | adjust_window_charstarts (w, vpos, adjust) | 2642 | mirrored_line_dance (matrix, unchanged_at_top, nlines, copy_from, |
| 944 | struct window *w; | 2643 | retained_p) |
| 945 | int vpos; | 2644 | struct glyph_matrix *matrix; |
| 946 | int adjust; | 2645 | int unchanged_at_top, nlines; |
| 2646 | int *copy_from; | ||
| 2647 | char *retained_p; | ||
| 947 | { | 2648 | { |
| 948 | int left = WINDOW_LEFT_MARGIN (w); | 2649 | /* A copy of original rows. */ |
| 949 | int top = XFASTINT (w->top); | 2650 | struct glyph_row *old_rows; |
| 950 | int right = left + window_internal_width (w); | 2651 | |
| 951 | int bottom = top + window_internal_height (w); | 2652 | /* Rows to assign to. */ |
| 2653 | struct glyph_row *new_rows = MATRIX_ROW (matrix, unchanged_at_top); | ||
| 2654 | |||
| 952 | int i; | 2655 | int i; |
| 953 | 2656 | ||
| 954 | for (i = vpos + 1; i < bottom; i++) | 2657 | /* Make a copy of the original rows. */ |
| 2658 | old_rows = (struct glyph_row *) alloca (nlines * sizeof *old_rows); | ||
| 2659 | bcopy (new_rows, old_rows, nlines * sizeof *old_rows); | ||
| 2660 | |||
| 2661 | /* Assign new rows, maybe clear lines. */ | ||
| 2662 | for (i = 0; i < nlines; ++i) | ||
| 955 | { | 2663 | { |
| 956 | int *charstart | 2664 | int enabled_before_p = new_rows[i].enabled_p; |
| 957 | = FRAME_CURRENT_GLYPHS (XFRAME (WINDOW_FRAME (w)))->charstarts[i]; | 2665 | |
| 958 | int j; | 2666 | xassert (i + unchanged_at_top < matrix->nrows); |
| 959 | for (j = left; j < right; j++) | 2667 | xassert (unchanged_at_top + copy_from[i] < matrix->nrows); |
| 960 | if (charstart[j] > 0) | 2668 | new_rows[i] = old_rows[copy_from[i]]; |
| 961 | charstart[j] += adjust; | 2669 | new_rows[i].enabled_p = enabled_before_p; |
| 2670 | |||
| 2671 | /* RETAINED_P is zero for empty lines. */ | ||
| 2672 | if (!retained_p[copy_from[i]]) | ||
| 2673 | new_rows[i].enabled_p = 0; | ||
| 962 | } | 2674 | } |
| 2675 | |||
| 2676 | /* Do the same for window matrices, if MATRIX Is a frame matrix. */ | ||
| 2677 | if (frame_matrix_frame) | ||
| 2678 | mirror_line_dance (XWINDOW (frame_matrix_frame->root_window), | ||
| 2679 | unchanged_at_top, nlines, copy_from, retained_p); | ||
| 963 | } | 2680 | } |
| 964 | 2681 | ||
| 965 | /* Check the charstarts values in the area of window W | ||
| 966 | for internal consistency. We cannot check that they are "right"; | ||
| 967 | we can only look for something nonsensical. */ | ||
| 968 | 2682 | ||
| 969 | void | 2683 | /* Perform a line dance in the window tree rooted at W, after |
| 970 | verify_charstarts (w) | 2684 | scrolling a frame matrix in mirrored_line_dance. |
| 2685 | |||
| 2686 | We are working on the range of lines UNCHANGED_AT_TOP + 1 to | ||
| 2687 | UNCHANGED_AT_TOP + NLINES (not including) in W's frame matrix. | ||
| 2688 | COPY_FROM is a vector containing, for each row I in the range 0 <= | ||
| 2689 | I < NLINES, the index of the original line to move to I. This | ||
| 2690 | index is relative to the row range, i.e. 0 <= index < NLINES. | ||
| 2691 | RETAINED_P is a vector containing zero for each row 0 <= I < NLINES | ||
| 2692 | which is empty. */ | ||
| 2693 | |||
| 2694 | static void | ||
| 2695 | mirror_line_dance (w, unchanged_at_top, nlines, copy_from, retained_p) | ||
| 971 | struct window *w; | 2696 | struct window *w; |
| 2697 | int unchanged_at_top, nlines; | ||
| 2698 | int *copy_from; | ||
| 2699 | char *retained_p; | ||
| 972 | { | 2700 | { |
| 973 | FRAME_PTR f = XFRAME (WINDOW_FRAME (w)); | 2701 | while (w) |
| 974 | int i; | 2702 | { |
| 975 | int top = XFASTINT (w->top); | 2703 | if (!NILP (w->hchild)) |
| 976 | int bottom = top + window_internal_height (w); | 2704 | mirror_line_dance (XWINDOW (w->hchild), unchanged_at_top, |
| 977 | int left = WINDOW_LEFT_MARGIN (w); | 2705 | nlines, copy_from, retained_p); |
| 978 | int right = left + window_internal_width (w); | 2706 | else if (!NILP (w->vchild)) |
| 979 | int next_line; | 2707 | mirror_line_dance (XWINDOW (w->vchild), unchanged_at_top, |
| 980 | int truncate = (XINT (w->hscroll) | 2708 | nlines, copy_from, retained_p); |
| 981 | || (truncate_partial_width_windows | 2709 | else |
| 982 | && !WINDOW_FULL_WIDTH_P (w)) | ||
| 983 | || !NILP (XBUFFER (w->buffer)->truncate_lines)); | ||
| 984 | |||
| 985 | for (i = top; i < bottom; i++) | ||
| 986 | { | ||
| 987 | int j; | ||
| 988 | int last; | ||
| 989 | int *charstart = FRAME_CURRENT_GLYPHS (f)->charstarts[i]; | ||
| 990 | |||
| 991 | if (i != top) | ||
| 992 | { | 2710 | { |
| 993 | if (truncate) | 2711 | /* W is a leaf window, and we are working on its current |
| 994 | { | 2712 | matrix m. */ |
| 995 | /* If we are truncating lines, allow a jump | 2713 | struct glyph_matrix *m = w->current_matrix; |
| 996 | in charstarts from one line to the next. */ | 2714 | |
| 997 | if (charstart[left] < next_line) | 2715 | int i; |
| 998 | abort (); | 2716 | |
| 999 | } | 2717 | struct glyph_row *old_rows; |
| 1000 | else | 2718 | |
| 2719 | /* Make a copy of the original rows of matrix m. */ | ||
| 2720 | old_rows = (struct glyph_row *) alloca (m->nrows * sizeof *old_rows); | ||
| 2721 | bcopy (m->rows, old_rows, m->nrows * sizeof *old_rows); | ||
| 2722 | |||
| 2723 | for (i = 0; i < nlines; ++i) | ||
| 1001 | { | 2724 | { |
| 1002 | if (charstart[left] != next_line) | 2725 | /* Frame relative line assigned to. */ |
| 1003 | abort (); | 2726 | int frame_to = i + unchanged_at_top; |
| 2727 | |||
| 2728 | /* Frame relative line assigned. */ | ||
| 2729 | int frame_from = copy_from[i] + unchanged_at_top; | ||
| 2730 | |||
| 2731 | /* Window relative line assigned to. */ | ||
| 2732 | int window_to = frame_to - m->matrix_y; | ||
| 2733 | |||
| 2734 | /* Window relative line assigned. */ | ||
| 2735 | int window_from = frame_from - m->matrix_y; | ||
| 2736 | |||
| 2737 | /* Is assigned line inside window? */ | ||
| 2738 | int from_inside_window_p | ||
| 2739 | = window_from >= 0 && window_from < m->matrix_h; | ||
| 2740 | |||
| 2741 | if (from_inside_window_p) | ||
| 2742 | { | ||
| 2743 | #if GLYPH_DEBUG | ||
| 2744 | /* Is assigned to line inside window? */ | ||
| 2745 | int to_inside_window_p | ||
| 2746 | = window_to >= 0 && window_to < m->matrix_h; | ||
| 2747 | #endif | ||
| 2748 | |||
| 2749 | /* Enabled setting before assignment. */ | ||
| 2750 | int enabled_before_p; | ||
| 2751 | |||
| 2752 | /* If not both lines inside the window, we have a | ||
| 2753 | serious problem. */ | ||
| 2754 | xassert (to_inside_window_p); | ||
| 2755 | |||
| 2756 | /* Do the assignment. The enabled_p flag is saved | ||
| 2757 | over the assignment because the old redisplay did | ||
| 2758 | that. */ | ||
| 2759 | enabled_before_p = m->rows[window_to].enabled_p; | ||
| 2760 | m->rows[window_to] = old_rows[window_from]; | ||
| 2761 | m->rows[window_to].enabled_p = enabled_before_p; | ||
| 2762 | |||
| 2763 | /* If frame line is empty, window line is empty, too. */ | ||
| 2764 | if (!retained_p[copy_from[i]]) | ||
| 2765 | m->rows[window_to].enabled_p = 0; | ||
| 2766 | } | ||
| 1004 | } | 2767 | } |
| 2768 | |||
| 2769 | /* Check that no pointers are lost. */ | ||
| 2770 | CHECK_MATRIX (m); | ||
| 1005 | } | 2771 | } |
| 1006 | 2772 | ||
| 1007 | for (j = left; j < right; j++) | 2773 | /* Next window on same level. */ |
| 1008 | if (charstart[j] > 0) | 2774 | w = NILP (w->next) ? 0 : XWINDOW (w->next); |
| 1009 | last = charstart[j]; | 2775 | } |
| 1010 | /* Record where the next line should start. */ | 2776 | } |
| 1011 | next_line = last; | 2777 | |
| 1012 | if (BUF_ZV (XBUFFER (w->buffer)) != last) | 2778 | |
| 2779 | #if GLYPH_DEBUG | ||
| 2780 | |||
| 2781 | /* Check that window and frame matrices agree about their | ||
| 2782 | understanding where glyphs of the rows are to find. For each | ||
| 2783 | window in the window tree rooted at W, check that rows in the | ||
| 2784 | matrices of leaf window agree with their frame matrices about | ||
| 2785 | glyph pointers. */ | ||
| 2786 | |||
| 2787 | void | ||
| 2788 | check_window_matrix_pointers (w) | ||
| 2789 | struct window *w; | ||
| 2790 | { | ||
| 2791 | while (w) | ||
| 2792 | { | ||
| 2793 | if (!NILP (w->hchild)) | ||
| 2794 | check_window_matrix_pointers (XWINDOW (w->hchild)); | ||
| 2795 | else if (!NILP (w->vchild)) | ||
| 2796 | check_window_matrix_pointers (XWINDOW (w->vchild)); | ||
| 2797 | else | ||
| 1013 | { | 2798 | { |
| 1014 | /* If there's a newline between the two lines, count that. */ | 2799 | struct frame *f = XFRAME (w->frame); |
| 1015 | int endchar = *BUF_CHAR_ADDRESS (XBUFFER (w->buffer), last); | 2800 | check_matrix_pointers (w->desired_matrix, f->desired_matrix); |
| 1016 | if (endchar == '\n') | 2801 | check_matrix_pointers (w->current_matrix, f->current_matrix); |
| 1017 | next_line++; | ||
| 1018 | } | 2802 | } |
| 2803 | |||
| 2804 | w = NILP (w->next) ? 0 : XWINDOW (w->next); | ||
| 1019 | } | 2805 | } |
| 1020 | } | 2806 | } |
| 2807 | |||
| 2808 | |||
| 2809 | /* Check that window rows are slices of frame rows. WINDOW_MATRIX is | ||
| 2810 | a window and FRAME_MATRIX is the corresponding frame matrix. For | ||
| 2811 | each row in WINDOW_MATRIX check that it's a slice of the | ||
| 2812 | corresponding frame row. If it isn't, abort. */ | ||
| 2813 | |||
| 2814 | static void | ||
| 2815 | check_matrix_pointers (window_matrix, frame_matrix) | ||
| 2816 | struct glyph_matrix *window_matrix, *frame_matrix; | ||
| 2817 | { | ||
| 2818 | /* Row number in WINDOW_MATRIX. */ | ||
| 2819 | int i = 0; | ||
| 2820 | |||
| 2821 | /* Row number corresponding to I in FRAME_MATRIX. */ | ||
| 2822 | int j = window_matrix->matrix_y; | ||
| 2823 | |||
| 2824 | /* For all rows check that the row in the window matrix is a | ||
| 2825 | slice of the row in the frame matrix. If it isn't we didn't | ||
| 2826 | mirror an operation on the frame matrix correctly. */ | ||
| 2827 | while (i < window_matrix->nrows) | ||
| 2828 | { | ||
| 2829 | if (!glyph_row_slice_p (window_matrix->rows + i, | ||
| 2830 | frame_matrix->rows + j)) | ||
| 2831 | abort (); | ||
| 2832 | ++i, ++j; | ||
| 2833 | } | ||
| 2834 | } | ||
| 2835 | |||
| 2836 | #endif /* GLYPH_DEBUG != 0 */ | ||
| 2837 | |||
| 2838 | |||
| 1021 | 2839 | ||
| 1022 | /* On discovering that the redisplay for a window was no good, | 2840 | /********************************************************************** |
| 1023 | cancel the columns of that window, so that when the window is | 2841 | VPOS and HPOS translations |
| 1024 | displayed over again get_display_line will not complain. */ | 2842 | **********************************************************************/ |
| 1025 | 2843 | ||
| 1026 | void | 2844 | #if GLYPH_DEBUG |
| 1027 | cancel_my_columns (w) | 2845 | |
| 2846 | /* Translate vertical position VPOS which is relative to window W to a | ||
| 2847 | vertical position relative to W's frame. */ | ||
| 2848 | |||
| 2849 | static int | ||
| 2850 | window_to_frame_vpos (w, vpos) | ||
| 2851 | struct window *w; | ||
| 2852 | int vpos; | ||
| 2853 | { | ||
| 2854 | struct frame *f = XFRAME (w->frame); | ||
| 2855 | |||
| 2856 | xassert (!FRAME_WINDOW_P (f)); | ||
| 2857 | xassert (vpos >= 0 && vpos <= w->desired_matrix->nrows); | ||
| 2858 | vpos += XFASTINT (w->top); | ||
| 2859 | xassert (vpos >= 0 && vpos <= FRAME_HEIGHT (f)); | ||
| 2860 | return vpos; | ||
| 2861 | } | ||
| 2862 | |||
| 2863 | |||
| 2864 | /* Translate horizontal position HPOS which is relative to window W to | ||
| 2865 | a vertical position relative to W's frame. */ | ||
| 2866 | |||
| 2867 | static int | ||
| 2868 | window_to_frame_hpos (w, hpos) | ||
| 1028 | struct window *w; | 2869 | struct window *w; |
| 2870 | int hpos; | ||
| 2871 | { | ||
| 2872 | struct frame *f = XFRAME (w->frame); | ||
| 2873 | |||
| 2874 | xassert (!FRAME_WINDOW_P (f)); | ||
| 2875 | hpos += XFASTINT (w->left); | ||
| 2876 | return hpos; | ||
| 2877 | } | ||
| 2878 | |||
| 2879 | #endif /* GLYPH_DEBUG */ | ||
| 2880 | |||
| 2881 | |||
| 2882 | |||
| 2883 | /********************************************************************** | ||
| 2884 | Redrawing Frames | ||
| 2885 | **********************************************************************/ | ||
| 2886 | |||
| 2887 | DEFUN ("redraw-frame", Fredraw_frame, Sredraw_frame, 1, 1, 0, | ||
| 2888 | "Clear frame FRAME and output again what is supposed to appear on it.") | ||
| 2889 | (frame) | ||
| 2890 | Lisp_Object frame; | ||
| 2891 | { | ||
| 2892 | struct frame *f; | ||
| 2893 | |||
| 2894 | CHECK_LIVE_FRAME (frame, 0); | ||
| 2895 | f = XFRAME (frame); | ||
| 2896 | |||
| 2897 | /* Ignore redraw requests, if frame has no glyphs yet. | ||
| 2898 | (Implementation note: It still has to be checked why we are | ||
| 2899 | called so early here). */ | ||
| 2900 | if (!glyphs_initialized_initially_p) | ||
| 2901 | return Qnil; | ||
| 2902 | |||
| 2903 | update_begin (f); | ||
| 2904 | if (FRAME_MSDOS_P (f)) | ||
| 2905 | set_terminal_modes (); | ||
| 2906 | clear_frame (); | ||
| 2907 | clear_current_matrices (f); | ||
| 2908 | update_end (f); | ||
| 2909 | fflush (stdout); | ||
| 2910 | windows_or_buffers_changed++; | ||
| 2911 | /* Mark all windows as inaccurate, so that every window will have | ||
| 2912 | its redisplay done. */ | ||
| 2913 | mark_window_display_accurate (FRAME_ROOT_WINDOW (f), 0); | ||
| 2914 | set_window_update_flags (XWINDOW (FRAME_ROOT_WINDOW (f)), 1); | ||
| 2915 | f->garbaged = 0; | ||
| 2916 | return Qnil; | ||
| 2917 | } | ||
| 2918 | |||
| 2919 | |||
| 2920 | /* Redraw frame F. This is nothing more than a call to the Lisp | ||
| 2921 | function redraw-frame. */ | ||
| 2922 | |||
| 2923 | void | ||
| 2924 | redraw_frame (f) | ||
| 2925 | struct frame *f; | ||
| 2926 | { | ||
| 2927 | Lisp_Object frame; | ||
| 2928 | XSETFRAME (frame, f); | ||
| 2929 | Fredraw_frame (frame); | ||
| 2930 | } | ||
| 2931 | |||
| 2932 | |||
| 2933 | DEFUN ("redraw-display", Fredraw_display, Sredraw_display, 0, 0, "", | ||
| 2934 | "Clear and redisplay all visible frames.") | ||
| 2935 | () | ||
| 1029 | { | 2936 | { |
| 1030 | register int vpos; | 2937 | Lisp_Object tail, frame; |
| 1031 | register struct frame_glyphs *desired_glyphs | ||
| 1032 | = FRAME_DESIRED_GLYPHS (XFRAME (w->frame)); | ||
| 1033 | register int start = WINDOW_LEFT_MARGIN (w); | ||
| 1034 | register int bot = XFASTINT (w->top) + XFASTINT (w->height); | ||
| 1035 | 2938 | ||
| 1036 | for (vpos = XFASTINT (w->top); vpos < bot; vpos++) | 2939 | FOR_EACH_FRAME (tail, frame) |
| 1037 | if (desired_glyphs->enable[vpos] | 2940 | if (FRAME_VISIBLE_P (XFRAME (frame))) |
| 1038 | && desired_glyphs->used[vpos] >= start) | 2941 | Fredraw_frame (frame); |
| 1039 | desired_glyphs->used[vpos] = start; | 2942 | |
| 2943 | return Qnil; | ||
| 1040 | } | 2944 | } |
| 2945 | |||
| 2946 | |||
| 2947 | /* This is used when frame_garbaged is set. Call Fredraw_frame on all | ||
| 2948 | visible frames marked as garbaged. */ | ||
| 2949 | |||
| 2950 | void | ||
| 2951 | redraw_garbaged_frames () | ||
| 2952 | { | ||
| 2953 | Lisp_Object tail, frame; | ||
| 2954 | |||
| 2955 | FOR_EACH_FRAME (tail, frame) | ||
| 2956 | if (FRAME_VISIBLE_P (XFRAME (frame)) | ||
| 2957 | && FRAME_GARBAGED_P (XFRAME (frame))) | ||
| 2958 | Fredraw_frame (frame); | ||
| 2959 | } | ||
| 2960 | |||
| 2961 | |||
| 1041 | 2962 | ||
| 1042 | /* These functions try to perform directly and immediately on the frame | 2963 | /*********************************************************************** |
| 1043 | the necessary output for one change in the buffer. | 2964 | Direct Operations |
| 1044 | They may return 0 meaning nothing was done if anything is difficult, | 2965 | ***********************************************************************/ |
| 1045 | or 1 meaning the output was performed properly. | 2966 | |
| 1046 | They assume that the frame was up to date before the buffer | 2967 | /* Try to update display and current glyph matrix directly. |
| 1047 | change being displayed. They make various other assumptions too; | 2968 | |
| 1048 | see command_loop_1 where these are called. */ | 2969 | This function is called after a character G has been inserted into |
| 2970 | current_buffer. It tries to update the current glyph matrix and | ||
| 2971 | perform appropriate screen output to reflect the insertion. If it | ||
| 2972 | succeeds, the global flag redisplay_performed_directly_p will be | ||
| 2973 | set to 1, and thereby prevent the more costly general redisplay | ||
| 2974 | from running (see redisplay_internal). | ||
| 2975 | |||
| 2976 | This function is not called for `hairy' character insertions. | ||
| 2977 | In particular, it is not called when after or before change | ||
| 2978 | functions exist, like they are used by font-lock. See keyboard.c | ||
| 2979 | for details where this function is called. */ | ||
| 1049 | 2980 | ||
| 1050 | int | 2981 | int |
| 1051 | direct_output_for_insert (g) | 2982 | direct_output_for_insert (g) |
| 1052 | int g; | 2983 | int g; |
| 1053 | { | 2984 | { |
| 1054 | register FRAME_PTR frame = selected_frame; | 2985 | register struct frame *f = selected_frame; |
| 1055 | register struct frame_glyphs *current_frame | 2986 | struct window *w = XWINDOW (selected_window); |
| 1056 | = FRAME_CURRENT_GLYPHS (frame); | 2987 | struct it it, it2; |
| 1057 | 2988 | struct glyph_row *glyph_row; | |
| 1058 | #ifndef COMPILER_REGISTER_BUG | 2989 | struct glyph *glyphs, *glyph, *end; |
| 1059 | register | 2990 | int n; |
| 1060 | #endif /* COMPILER_REGISTER_BUG */ | 2991 | /* Non-null means that Redisplay of W is based on window matrices. */ |
| 1061 | struct window *w = XWINDOW (selected_window); | 2992 | int window_redisplay_p = FRAME_WINDOW_P (f); |
| 1062 | #ifndef COMPILER_REGISTER_BUG | 2993 | /* Non-null means we are in overwrite mode. */ |
| 1063 | register | 2994 | int overwrite_p = !NILP (current_buffer->overwrite_mode); |
| 1064 | #endif /* COMPILER_REGISTER_BUG */ | 2995 | int added_width; |
| 1065 | int hpos = FRAME_CURSOR_X (frame); | 2996 | struct text_pos pos; |
| 1066 | #ifndef COMPILER_REGISTER_BUG | 2997 | int delta, delta_bytes; |
| 1067 | register | 2998 | |
| 1068 | #endif /* COMPILER_REGISTER_BUG */ | 2999 | /* Not done directly. */ |
| 1069 | int vpos = FRAME_CURSOR_Y (frame); | 3000 | redisplay_performed_directly_p = 0; |
| 1070 | 3001 | ||
| 1071 | /* Give up if about to continue line. */ | 3002 | /* Quickly give up for some common cases. */ |
| 1072 | if (hpos >= WINDOW_LEFT_MARGIN (w) + window_internal_width (w) - 1 | 3003 | if (cursor_in_echo_area |
| 1073 | 3004 | /* Give up if fonts have changed. */ | |
| 1074 | /* Avoid losing if cursor is in invisible text off left margin */ | 3005 | || fonts_changed_p |
| 1075 | || (XINT (w->hscroll) && hpos == WINDOW_LEFT_MARGIN (w)) | 3006 | /* Give up if face attributes have been changed. */ |
| 1076 | 3007 | || face_change_count | |
| 1077 | /* Give up if cursor outside window (in minibuf, probably) */ | 3008 | /* Give up if cursor position not really known. */ |
| 1078 | || cursor_in_echo_area | ||
| 1079 | || FRAME_CURSOR_Y (frame) < XFASTINT (w->top) | ||
| 1080 | || FRAME_CURSOR_Y (frame) >= XFASTINT (w->top) + XFASTINT (w->height) | ||
| 1081 | |||
| 1082 | /* Give up if cursor not really at FRAME_CURSOR_X, FRAME_CURSOR_Y */ | ||
| 1083 | || !display_completed | 3009 | || !display_completed |
| 1084 | 3010 | /* Give up if buffer appears in two places. */ | |
| 1085 | /* Give up if buffer appears in two places. */ | ||
| 1086 | || buffer_shared > 1 | 3011 | || buffer_shared > 1 |
| 3012 | /* Give up if w is mini-buffer and a message is being displayed there */ | ||
| 3013 | || (MINI_WINDOW_P (w) | ||
| 3014 | && (echo_area_glyphs || STRINGP (echo_area_message))) | ||
| 3015 | /* Give up for hscrolled mini-buffer because display of the prompt | ||
| 3016 | is handled specially there (see display_line). */ | ||
| 3017 | || (MINI_WINDOW_P (w) && XFASTINT (w->hscroll)) | ||
| 3018 | /* Give up if overwriting in the middle of a line. */ | ||
| 3019 | || (overwrite_p | ||
| 3020 | && PT != ZV | ||
| 3021 | && FETCH_BYTE (PT) != '\n') | ||
| 3022 | /* Give up for tabs and line ends. */ | ||
| 3023 | || g == '\t' | ||
| 3024 | || g == '\n' | ||
| 3025 | || g == '\r' | ||
| 3026 | /* Give up if unable to display the cursor in the window. */ | ||
| 3027 | || w->cursor.vpos < 0 | ||
| 3028 | /* Can't do it in a continued line because continuation lines | ||
| 3029 | will change. */ | ||
| 3030 | || MATRIX_ROW (w->current_matrix, w->cursor.vpos)->continued_p | ||
| 3031 | /* Can't do it for partial width windows on terminal frames | ||
| 3032 | because we can't clear to eol in such a window. */ | ||
| 3033 | || (!window_redisplay_p && !WINDOW_FULL_WIDTH_P (w))) | ||
| 3034 | return 0; | ||
| 1087 | 3035 | ||
| 1088 | #ifdef USE_TEXT_PROPERTIES | 3036 | /* Set up a display iterator structure for W. Glyphs will be |
| 1089 | /* Intervals have already been adjusted, point is after the | 3037 | produced in scratch_glyph_row. Current position is W's cursor |
| 1090 | character that was just inserted. */ | 3038 | position. */ |
| 1091 | /* Give up if character is invisible. */ | 3039 | clear_glyph_row (&scratch_glyph_row); |
| 1092 | /* Give up if character has a face property. | 3040 | SET_TEXT_POS (pos, PT, PT_BYTE); |
| 1093 | At the moment we only lose at end of line or end of buffer | 3041 | DEC_TEXT_POS (pos); |
| 1094 | and only with faces that have some background */ | 3042 | init_iterator (&it, w, CHARPOS (pos), BYTEPOS (pos), &scratch_glyph_row, |
| 1095 | /* Instead of wasting time, give up if character has any text properties */ | 3043 | DEFAULT_FACE_ID); |
| 1096 | || ! NILP (Ftext_properties_at (make_number (PT - 1), Qnil)) | 3044 | |
| 1097 | #endif | 3045 | glyph_row = MATRIX_ROW (w->current_matrix, w->cursor.vpos); |
| 3046 | |||
| 3047 | /* Give up if highlighting trailing whitespace and we have trailing | ||
| 3048 | whitespace in glyph_row. We would have to remove the trailing | ||
| 3049 | whitespace face in that case. */ | ||
| 3050 | if (it.show_trailing_whitespace_p | ||
| 3051 | && glyph_row->used[TEXT_AREA]) | ||
| 3052 | { | ||
| 3053 | struct glyph *last; | ||
| 1098 | 3054 | ||
| 1099 | /* Give up if w is minibuffer and a message is being displayed there */ | 3055 | last = glyph_row->glyphs[TEXT_AREA] + glyph_row->used[TEXT_AREA] - 1; |
| 1100 | || (MINI_WINDOW_P (w) && echo_area_glyphs)) | 3056 | if (last->type == STRETCH_GLYPH |
| 3057 | || (last->type == CHAR_GLYPH | ||
| 3058 | && last->u.ch.code == ' ')) | ||
| 3059 | return 0; | ||
| 3060 | } | ||
| 3061 | |||
| 3062 | /* Give up if there are overlay strings at pos. This would fail | ||
| 3063 | if the overlay string has newlines in it. */ | ||
| 3064 | if (STRINGP (it.string)) | ||
| 1101 | return 0; | 3065 | return 0; |
| 3066 | |||
| 3067 | it.hpos = w->cursor.hpos; | ||
| 3068 | it.vpos = w->cursor.vpos; | ||
| 3069 | it.current_x = w->cursor.x + it.first_visible_x; | ||
| 3070 | it.current_y = w->cursor.y; | ||
| 3071 | it.end_charpos = PT; | ||
| 3072 | it.stop_charpos = min (PT, it.stop_charpos); | ||
| 3073 | |||
| 3074 | /* More than one display element may be returned for PT - 1 if | ||
| 3075 | (i) it's a control character which is translated into `\003' or | ||
| 3076 | `^C', or (ii) it has a display table entry, or (iii) it's a | ||
| 3077 | combination of both. */ | ||
| 3078 | delta = delta_bytes = 0; | ||
| 3079 | while (get_next_display_element (&it)) | ||
| 3080 | { | ||
| 3081 | PRODUCE_GLYPHS (&it); | ||
| 1102 | 3082 | ||
| 1103 | { | 3083 | /* Give up if glyph doesn't fit completely on the line. */ |
| 1104 | int face = 0; | 3084 | if (it.current_x >= it.last_visible_x) |
| 1105 | #ifdef HAVE_FACES | 3085 | return 0; |
| 1106 | int dummy; | 3086 | |
| 3087 | /* Give up if new glyph has different ascent or descent than | ||
| 3088 | the original row, or if it is not a character glyph. */ | ||
| 3089 | if (glyph_row->ascent != it.ascent | ||
| 3090 | || glyph_row->height != it.ascent + it.descent | ||
| 3091 | || it.what != IT_CHARACTER) | ||
| 3092 | return 0; | ||
| 3093 | |||
| 3094 | delta += 1; | ||
| 3095 | delta_bytes += it.len; | ||
| 3096 | set_iterator_to_next (&it); | ||
| 3097 | } | ||
| 3098 | |||
| 3099 | /* Give up if we hit the right edge of the window. We would have | ||
| 3100 | to insert truncation or continuation glyphs. */ | ||
| 3101 | added_width = it.current_x - (w->cursor.x + it.first_visible_x); | ||
| 3102 | if (glyph_row->pixel_width + added_width >= it.last_visible_x) | ||
| 3103 | return 0; | ||
| 3104 | |||
| 3105 | /* Give up if there is a \t following in the line. */ | ||
| 3106 | it2 = it; | ||
| 3107 | it2.end_charpos = ZV; | ||
| 3108 | it2.stop_charpos = min (it2.stop_charpos, ZV); | ||
| 3109 | while (get_next_display_element (&it2) | ||
| 3110 | && !ITERATOR_AT_END_OF_LINE_P (&it2)) | ||
| 3111 | { | ||
| 3112 | if (it2.c == '\t') | ||
| 3113 | return 0; | ||
| 3114 | set_iterator_to_next (&it2); | ||
| 3115 | } | ||
| 3116 | |||
| 3117 | /* Number of new glyphs produced. */ | ||
| 3118 | n = it.glyph_row->used[TEXT_AREA]; | ||
| 3119 | |||
| 3120 | /* Start and end of glyphs in original row. */ | ||
| 3121 | glyphs = glyph_row->glyphs[TEXT_AREA] + w->cursor.hpos; | ||
| 3122 | end = glyph_row->glyphs[1 + TEXT_AREA]; | ||
| 3123 | |||
| 3124 | /* Make room for new glyphs, then insert them. */ | ||
| 3125 | xassert (end - glyphs - n >= 0); | ||
| 3126 | safe_bcopy (glyphs, glyphs + n, (end - glyphs - n) * sizeof (*end)); | ||
| 3127 | bcopy (it.glyph_row->glyphs[TEXT_AREA], glyphs, n * sizeof *glyphs); | ||
| 3128 | glyph_row->used[TEXT_AREA] = min (glyph_row->used[TEXT_AREA] + n, | ||
| 3129 | end - glyph_row->glyphs[TEXT_AREA]); | ||
| 3130 | |||
| 3131 | /* Compute new line width. */ | ||
| 3132 | glyph = glyph_row->glyphs[TEXT_AREA]; | ||
| 3133 | end = glyph + glyph_row->used[TEXT_AREA]; | ||
| 3134 | glyph_row->pixel_width = glyph_row->x; | ||
| 3135 | while (glyph < end) | ||
| 3136 | { | ||
| 3137 | glyph_row->pixel_width += glyph->pixel_width; | ||
| 3138 | ++glyph; | ||
| 3139 | } | ||
| 3140 | |||
| 3141 | /* Increment buffer positions for glyphs following the newly | ||
| 3142 | inserted ones. */ | ||
| 3143 | for (glyph = glyphs + n; glyph < end; ++glyph) | ||
| 3144 | if (glyph->charpos > 0) | ||
| 3145 | glyph->charpos += delta; | ||
| 3146 | |||
| 3147 | if (MATRIX_ROW_END_CHARPOS (glyph_row) > 0) | ||
| 3148 | { | ||
| 3149 | MATRIX_ROW_END_CHARPOS (glyph_row) += delta; | ||
| 3150 | MATRIX_ROW_END_BYTEPOS (glyph_row) += delta_bytes; | ||
| 3151 | } | ||
| 3152 | |||
| 3153 | /* Adjust positions in lines following the one we are in. */ | ||
| 3154 | increment_glyph_matrix_buffer_positions (w->current_matrix, | ||
| 3155 | w->cursor.vpos + 1, | ||
| 3156 | w->current_matrix->nrows, | ||
| 3157 | delta, delta_bytes); | ||
| 3158 | |||
| 3159 | glyph_row->contains_overlapping_glyphs_p | ||
| 3160 | |= it.glyph_row->contains_overlapping_glyphs_p; | ||
| 3161 | |||
| 3162 | if (it.show_trailing_whitespace_p) | ||
| 3163 | highlight_trailing_whitespace (it.f, glyph_row); | ||
| 3164 | |||
| 3165 | /* Write glyphs. If at end of row, we can simply call write_glyphs. | ||
| 3166 | In the middle, we have to insert glyphs. Note that this is now | ||
| 3167 | implemented for X frames. The implementation uses updated_window | ||
| 3168 | and updated_row. */ | ||
| 3169 | updated_row = glyph_row; | ||
| 3170 | update_begin (f); | ||
| 3171 | if (rif) | ||
| 3172 | { | ||
| 3173 | rif->update_window_begin_hook (w); | ||
| 3174 | |||
| 3175 | if (glyphs == end - n) | ||
| 3176 | rif->write_glyphs (glyphs, n); | ||
| 3177 | else | ||
| 3178 | rif->insert_glyphs (glyphs, n); | ||
| 3179 | } | ||
| 3180 | else | ||
| 3181 | { | ||
| 3182 | if (glyphs == end - n) | ||
| 3183 | write_glyphs (glyphs, n); | ||
| 3184 | else | ||
| 3185 | insert_glyphs (glyphs, n); | ||
| 3186 | } | ||
| 3187 | |||
| 3188 | w->cursor.hpos += n; | ||
| 3189 | w->cursor.x = it.current_x - it.first_visible_x; | ||
| 3190 | xassert (w->cursor.hpos >= 0 | ||
| 3191 | && w->cursor.hpos < w->desired_matrix->matrix_w); | ||
| 3192 | |||
| 3193 | /* How to set the cursor differs depending on whether we are | ||
| 3194 | using a frame matrix or a window matrix. Note that when | ||
| 3195 | a frame matrix is used, cursor_to expects frame coordinates, | ||
| 3196 | and the X and Y parameters are not used. */ | ||
| 3197 | if (window_redisplay_p) | ||
| 3198 | rif->cursor_to (w->cursor.vpos, w->cursor.hpos, | ||
| 3199 | w->cursor.y, w->cursor.x); | ||
| 3200 | else | ||
| 3201 | { | ||
| 3202 | int x, y; | ||
| 3203 | x = (WINDOW_TO_FRAME_HPOS (w, w->cursor.hpos) | ||
| 3204 | + (INTEGERP (w->left_margin_width) | ||
| 3205 | ? XFASTINT (w->left_margin_width) | ||
| 3206 | : 0)); | ||
| 3207 | y = WINDOW_TO_FRAME_VPOS (w, w->cursor.vpos); | ||
| 3208 | cursor_to (y, x); | ||
| 3209 | } | ||
| 3210 | |||
| 3211 | if (rif) | ||
| 3212 | rif->update_window_end_hook (w, 1); | ||
| 3213 | update_end (f); | ||
| 3214 | updated_row = NULL; | ||
| 3215 | fflush (stdout); | ||
| 3216 | |||
| 3217 | TRACE ((stderr, "direct output for insert\n")); | ||
| 1107 | 3218 | ||
| 1108 | if (FRAME_WINDOW_P (frame) || FRAME_MSDOS_P (frame)) | ||
| 1109 | face = compute_char_face (frame, w, PT - 1, -1, -1, &dummy, PT, 0); | ||
| 1110 | #endif | ||
| 1111 | current_frame->glyphs[vpos][hpos] = MAKE_GLYPH (frame, g, face); | ||
| 1112 | current_frame->charstarts[vpos][hpos] = PT - 1; | ||
| 1113 | /* Record the entry for after the newly inserted character. */ | ||
| 1114 | current_frame->charstarts[vpos][hpos + 1] = PT; | ||
| 1115 | adjust_window_charstarts (w, vpos, 1); | ||
| 1116 | } | ||
| 1117 | unchanged_modified = MODIFF; | 3219 | unchanged_modified = MODIFF; |
| 1118 | beg_unchanged = GPT - BEG; | 3220 | beg_unchanged = GPT - BEG; |
| 1119 | XSETFASTINT (w->last_point, PT); | 3221 | XSETFASTINT (w->last_point, PT); |
| 1120 | XSETFASTINT (w->last_point_x, hpos + 1); | 3222 | w->last_cursor = w->cursor; |
| 1121 | XSETFASTINT (w->last_modified, MODIFF); | 3223 | XSETFASTINT (w->last_modified, MODIFF); |
| 1122 | XSETFASTINT (w->last_overlay_modified, OVERLAY_MODIFF); | 3224 | XSETFASTINT (w->last_overlay_modified, OVERLAY_MODIFF); |
| 1123 | 3225 | ||
| 1124 | reassert_line_highlight (0, vpos); | 3226 | redisplay_performed_directly_p = 1; |
| 1125 | write_glyphs (¤t_frame->glyphs[vpos][hpos], 1); | ||
| 1126 | fflush (stdout); | ||
| 1127 | ++FRAME_CURSOR_X (frame); | ||
| 1128 | if (hpos == current_frame->used[vpos]) | ||
| 1129 | { | ||
| 1130 | current_frame->used[vpos] = hpos + 1; | ||
| 1131 | current_frame->glyphs[vpos][hpos + 1] = 0; | ||
| 1132 | } | ||
| 1133 | |||
| 1134 | return 1; | 3227 | return 1; |
| 1135 | } | 3228 | } |
| 1136 | 3229 | ||
| 3230 | |||
| 3231 | /* Perform a direct display update for moving PT by N positions | ||
| 3232 | left or right. N < 0 means a movement backwards. This function | ||
| 3233 | is currently only called for N == 1 or N == -1. */ | ||
| 3234 | |||
| 1137 | int | 3235 | int |
| 1138 | direct_output_forward_char (n) | 3236 | direct_output_forward_char (n) |
| 1139 | int n; | 3237 | int n; |
| 1140 | { | 3238 | { |
| 1141 | register FRAME_PTR frame = selected_frame; | 3239 | struct frame *f = selected_frame; |
| 1142 | register struct window *w = XWINDOW (selected_window); | 3240 | struct window *w = XWINDOW (selected_window); |
| 1143 | Lisp_Object position; | 3241 | struct glyph_row *row; |
| 1144 | int hpos = FRAME_CURSOR_X (frame); | ||
| 1145 | 3242 | ||
| 1146 | /* Give up if in truncated text at end of line. */ | 3243 | /* Give up if face attributes have been changed. */ |
| 1147 | /* This check is not redundant. */ | 3244 | if (face_change_count) |
| 1148 | if (hpos >= WINDOW_LEFT_MARGIN (w) + window_internal_width (w) - 1) | ||
| 1149 | return 0; | 3245 | return 0; |
| 1150 | 3246 | ||
| 1151 | /* Give up if the buffer's direction is reversed (i.e. right-to-left). */ | 3247 | /* Give up if current matrix is not up to date or we are |
| 1152 | if (!NILP (XBUFFER(w->buffer)->direction_reversed)) | 3248 | displaying a message. */ |
| 3249 | if (!display_completed || cursor_in_echo_area) | ||
| 1153 | return 0; | 3250 | return 0; |
| 1154 | 3251 | ||
| 1155 | /* Avoid losing if cursor is in invisible text off left margin | 3252 | /* Give up if the buffer's direction is reversed. */ |
| 1156 | or about to go off either side of window. */ | 3253 | if (!NILP (XBUFFER (w->buffer)->direction_reversed)) |
| 1157 | if ((FRAME_CURSOR_X (frame) == WINDOW_LEFT_MARGIN (w) | ||
| 1158 | && (XINT (w->hscroll) || n < 0)) | ||
| 1159 | || (n > 0 | ||
| 1160 | && (FRAME_CURSOR_X (frame) + 1 | ||
| 1161 | >= XFASTINT (w->left) + window_internal_width (w) - 1)) | ||
| 1162 | /* BUG FIX: Added "XFASTINT (w->left)". Without this, | ||
| 1163 | direct_output_forward_char() always fails on "the right" | ||
| 1164 | window. */ | ||
| 1165 | || cursor_in_echo_area) | ||
| 1166 | return 0; | 3254 | return 0; |
| 1167 | 3255 | ||
| 1168 | /* Can't use direct output if highlighting a region. */ | 3256 | /* Can't use direct output if highlighting a region. */ |
| 1169 | if (!NILP (Vtransient_mark_mode) && !NILP (current_buffer->mark_active)) | 3257 | if (!NILP (Vtransient_mark_mode) && !NILP (current_buffer->mark_active)) |
| 1170 | return 0; | 3258 | return 0; |
| 1171 | 3259 | ||
| 1172 | /* Can't use direct output at an overlay boundary; it might have | 3260 | row = MATRIX_ROW (w->current_matrix, w->cursor.vpos); |
| 1173 | before-string or after-string properties. */ | 3261 | |
| 1174 | if (overlay_touches_p (PT) || overlay_touches_p (PT - n)) | 3262 | if (PT <= MATRIX_ROW_START_BYTEPOS (row) |
| 3263 | || PT >= MATRIX_ROW_END_BYTEPOS (row)) | ||
| 1175 | return 0; | 3264 | return 0; |
| 1176 | 3265 | ||
| 1177 | #ifdef USE_TEXT_PROPERTIES | 3266 | set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0); |
| 1178 | /* Don't use direct output next to an invisible character | 3267 | w->last_cursor = w->cursor; |
| 1179 | since we might need to do something special. */ | 3268 | XSETFASTINT (w->last_point, PT); |
| 3269 | |||
| 3270 | xassert (w->cursor.hpos >= 0 | ||
| 3271 | && w->cursor.hpos < w->desired_matrix->matrix_w); | ||
| 3272 | |||
| 3273 | if (FRAME_WINDOW_P (f)) | ||
| 3274 | rif->cursor_to (w->cursor.vpos, w->cursor.hpos, | ||
| 3275 | w->cursor.y, w->cursor.x); | ||
| 3276 | else | ||
| 3277 | { | ||
| 3278 | int x, y; | ||
| 3279 | x = (WINDOW_TO_FRAME_HPOS (w, w->cursor.hpos) | ||
| 3280 | + (INTEGERP (w->left_margin_width) | ||
| 3281 | ? XFASTINT (w->left_margin_width) | ||
| 3282 | : 0)); | ||
| 3283 | y = WINDOW_TO_FRAME_VPOS (w, w->cursor.vpos); | ||
| 3284 | cursor_to (y, x); | ||
| 3285 | } | ||
| 3286 | |||
| 3287 | fflush (stdout); | ||
| 3288 | redisplay_performed_directly_p = 1; | ||
| 3289 | return 1; | ||
| 3290 | } | ||
| 3291 | |||
| 3292 | |||
| 3293 | |||
| 3294 | /*********************************************************************** | ||
| 3295 | Frame Update | ||
| 3296 | ***********************************************************************/ | ||
| 3297 | |||
| 3298 | /* Update frame F based on the data in desired matrices. | ||
| 3299 | |||
| 3300 | If FORCE_P is non-zero, don't let redisplay be stopped by detecting | ||
| 3301 | pending input. If INHIBIT_HAIRY_ID_P is non-zero, don't try | ||
| 3302 | scrolling. | ||
| 3303 | |||
| 3304 | Value is non-zero if redisplay was stopped due to pending input. */ | ||
| 3305 | |||
| 3306 | int | ||
| 3307 | update_frame (f, force_p, inhibit_hairy_id_p) | ||
| 3308 | struct frame *f; | ||
| 3309 | int force_p; | ||
| 3310 | int inhibit_hairy_id_p; | ||
| 3311 | { | ||
| 3312 | /* 1 means display has been paused because of pending input. */ | ||
| 3313 | int paused_p; | ||
| 3314 | struct window *root_window = XWINDOW (f->root_window); | ||
| 3315 | |||
| 3316 | if (FRAME_WINDOW_P (f)) | ||
| 3317 | { | ||
| 3318 | /* We are working on window matrix basis. All windows whose | ||
| 3319 | flag must_be_updated_p is set have to be updated. */ | ||
| 3320 | |||
| 3321 | /* Record that we are not working on frame matrices. */ | ||
| 3322 | set_frame_matrix_frame (NULL); | ||
| 3323 | |||
| 3324 | /* Update all windows in the window tree of F, maybe stopping | ||
| 3325 | when pending input is detected. */ | ||
| 3326 | update_begin (f); | ||
| 3327 | |||
| 3328 | /* Update the menu bar on X frames that don't have toolkit | ||
| 3329 | support. */ | ||
| 3330 | if (WINDOWP (f->menu_bar_window)) | ||
| 3331 | update_window (XWINDOW (f->menu_bar_window), 1); | ||
| 3332 | |||
| 3333 | /* Update the tool-bar window, if present. */ | ||
| 3334 | if (WINDOWP (f->toolbar_window)) | ||
| 3335 | { | ||
| 3336 | Lisp_Object tem; | ||
| 3337 | struct window *w = XWINDOW (f->toolbar_window); | ||
| 3338 | |||
| 3339 | /* Update tool-bar window. */ | ||
| 3340 | if (w->must_be_updated_p) | ||
| 3341 | { | ||
| 3342 | update_window (w, 1); | ||
| 3343 | w->must_be_updated_p = 0; | ||
| 3344 | |||
| 3345 | /* Swap tool-bar strings. We swap because we want to | ||
| 3346 | reuse strings. */ | ||
| 3347 | tem = f->current_toolbar_string; | ||
| 3348 | f->current_toolbar_string = f->desired_toolbar_string; | ||
| 3349 | f->desired_toolbar_string = tem; | ||
| 3350 | f->n_current_toolbar_items = f->n_desired_toolbar_items; | ||
| 3351 | |||
| 3352 | /* Swap tool-bar items. We swap because we want to | ||
| 3353 | reuse vectors. */ | ||
| 3354 | tem = f->current_toolbar_items; | ||
| 3355 | f->current_toolbar_items = f->desired_toolbar_items; | ||
| 3356 | f->desired_toolbar_items = tem; | ||
| 3357 | } | ||
| 3358 | } | ||
| 3359 | |||
| 3360 | |||
| 3361 | /* Update windows. */ | ||
| 3362 | paused_p = update_window_tree (root_window, force_p); | ||
| 3363 | update_end (f); | ||
| 3364 | display_completed = !paused_p; | ||
| 3365 | |||
| 3366 | /* The flush is a performance bottleneck under X. */ | ||
| 3367 | #if 0 | ||
| 3368 | rif->flush_display (f); | ||
| 3369 | #endif | ||
| 3370 | } | ||
| 3371 | else | ||
| 3372 | { | ||
| 3373 | /* We are working on frame matrix basis. Set the frame on whose | ||
| 3374 | frame matrix we operate. */ | ||
| 3375 | set_frame_matrix_frame (f); | ||
| 3376 | |||
| 3377 | /* Build F's desired matrix from window matrices. For windows | ||
| 3378 | whose must_be_updated_p flag is set, desired matrices are | ||
| 3379 | made part of the desired frame matrix. For other windows, | ||
| 3380 | the current matrix is copied. */ | ||
| 3381 | build_frame_matrix (f); | ||
| 3382 | |||
| 3383 | /* Do the update on the frame desired matrix. */ | ||
| 3384 | paused_p = update_frame_1 (f, force_p, inhibit_hairy_id_p); | ||
| 3385 | |||
| 3386 | /* Check window matrices for lost pointers. */ | ||
| 3387 | IF_DEBUG (check_window_matrix_pointers (root_window)); | ||
| 3388 | } | ||
| 3389 | |||
| 3390 | /* Reset flags indicating that a window should be updated. */ | ||
| 3391 | set_window_update_flags (root_window, 0); | ||
| 3392 | return paused_p; | ||
| 3393 | } | ||
| 3394 | |||
| 3395 | |||
| 3396 | |||
| 3397 | /************************************************************************ | ||
| 3398 | Window-based updates | ||
| 3399 | ************************************************************************/ | ||
| 3400 | |||
| 3401 | /* Perform updates in window tree rooted at W. FORCE_P non-zero means | ||
| 3402 | don't stop updating when input is pending. */ | ||
| 3403 | |||
| 3404 | static int | ||
| 3405 | update_window_tree (w, force_p) | ||
| 3406 | struct window *w; | ||
| 3407 | int force_p; | ||
| 3408 | { | ||
| 3409 | int paused_p = 0; | ||
| 3410 | |||
| 3411 | while (w && !paused_p) | ||
| 3412 | { | ||
| 3413 | if (!NILP (w->hchild)) | ||
| 3414 | paused_p |= update_window_tree (XWINDOW (w->hchild), force_p); | ||
| 3415 | else if (!NILP (w->vchild)) | ||
| 3416 | paused_p |= update_window_tree (XWINDOW (w->vchild), force_p); | ||
| 3417 | else if (w->must_be_updated_p) | ||
| 3418 | paused_p |= update_window (w, force_p); | ||
| 3419 | |||
| 3420 | w = NILP (w->next) ? 0 : XWINDOW (w->next); | ||
| 3421 | } | ||
| 3422 | |||
| 3423 | return paused_p; | ||
| 3424 | } | ||
| 3425 | |||
| 3426 | |||
| 3427 | /* Update window W if its flag must_be_updated_p is non-zero. If | ||
| 3428 | FORCE_P is non-zero, don't stop updating if input is pending. */ | ||
| 3429 | |||
| 3430 | void | ||
| 3431 | update_single_window (w, force_p) | ||
| 3432 | struct window *w; | ||
| 3433 | int force_p; | ||
| 3434 | { | ||
| 3435 | if (w->must_be_updated_p) | ||
| 3436 | { | ||
| 3437 | struct frame *f = XFRAME (WINDOW_FRAME (w)); | ||
| 3438 | |||
| 3439 | /* Record that this is not a frame-based redisplay. */ | ||
| 3440 | set_frame_matrix_frame (NULL); | ||
| 3441 | |||
| 3442 | /* Update W. */ | ||
| 3443 | update_begin (f); | ||
| 3444 | update_window (w, force_p); | ||
| 3445 | update_end (f); | ||
| 3446 | |||
| 3447 | /* Reset flag in W. */ | ||
| 3448 | w->must_be_updated_p = 0; | ||
| 3449 | } | ||
| 3450 | } | ||
| 3451 | |||
| 3452 | |||
| 3453 | /* Update display of window W. FORCE_P non-zero means that we should | ||
| 3454 | not stop when detecting pending input. */ | ||
| 3455 | |||
| 3456 | static int | ||
| 3457 | update_window (w, force_p) | ||
| 3458 | struct window *w; | ||
| 3459 | int force_p; | ||
| 3460 | { | ||
| 3461 | struct frame *f = XFRAME (WINDOW_FRAME (w)); | ||
| 3462 | struct glyph_matrix *desired_matrix = w->desired_matrix; | ||
| 3463 | int paused_p; | ||
| 3464 | int preempt_count = baud_rate / 2400 + 1; | ||
| 3465 | extern int input_pending; | ||
| 3466 | extern struct frame *updating_frame; | ||
| 3467 | |||
| 3468 | /* Check that W's frame doesn't have glyph matrices. */ | ||
| 3469 | xassert (FRAME_WINDOW_P (f)); | ||
| 3470 | xassert (updating_frame != NULL); | ||
| 3471 | |||
| 3472 | /* Check pending input the first time so that we can quickly return. */ | ||
| 3473 | if (redisplay_dont_pause) | ||
| 3474 | force_p = 1; | ||
| 3475 | else | ||
| 3476 | detect_input_pending (); | ||
| 3477 | |||
| 3478 | /* If forced to complete the update, or if no input is pending, do | ||
| 3479 | the update. */ | ||
| 3480 | if (force_p || !input_pending) | ||
| 3481 | { | ||
| 3482 | struct glyph_row *row, *end; | ||
| 3483 | struct glyph_row *mode_line_row; | ||
| 3484 | struct glyph_row *top_line_row = NULL; | ||
| 3485 | int yb; | ||
| 3486 | |||
| 3487 | rif->update_window_begin_hook (w); | ||
| 3488 | yb = window_text_bottom_y (w); | ||
| 3489 | |||
| 3490 | /* If window has a top line, update it before everything else. | ||
| 3491 | Adjust y-positions of other rows by the top line height. */ | ||
| 3492 | row = desired_matrix->rows; | ||
| 3493 | end = row + desired_matrix->nrows - 1; | ||
| 3494 | if (row->mode_line_p) | ||
| 3495 | top_line_row = row++; | ||
| 3496 | |||
| 3497 | /* Update the mode line, if necessary. */ | ||
| 3498 | mode_line_row = MATRIX_MODE_LINE_ROW (desired_matrix); | ||
| 3499 | if (mode_line_row->mode_line_p && mode_line_row->enabled_p) | ||
| 3500 | { | ||
| 3501 | mode_line_row->y = yb; | ||
| 3502 | update_window_line (w, MATRIX_ROW_VPOS (mode_line_row, | ||
| 3503 | desired_matrix)); | ||
| 3504 | } | ||
| 3505 | |||
| 3506 | /* Find first enabled row. Optimizations in redisplay_internal | ||
| 3507 | may lead to an update with only one row enabled. There may | ||
| 3508 | be also completely empty matrices. */ | ||
| 3509 | while (row < end && !row->enabled_p) | ||
| 3510 | ++row; | ||
| 3511 | |||
| 3512 | /* Try reusing part of the display by inserting/deleting lines. */ | ||
| 3513 | if (row < end && !desired_matrix->no_scrolling_p) | ||
| 3514 | { | ||
| 3515 | int rc = scrolling_window (w, top_line_row != NULL); | ||
| 3516 | if (rc < 0) | ||
| 3517 | { | ||
| 3518 | /* All rows were found to be equal. */ | ||
| 3519 | paused_p = 0; | ||
| 3520 | goto set_cursor; | ||
| 3521 | } | ||
| 3522 | else if (rc > 0) | ||
| 3523 | force_p = 1; | ||
| 3524 | } | ||
| 3525 | |||
| 3526 | /* Update the top mode line after scrolling because a new top | ||
| 3527 | line would otherwise overwrite lines at the top of the window | ||
| 3528 | that can be scrolled. */ | ||
| 3529 | if (top_line_row && top_line_row->enabled_p) | ||
| 3530 | { | ||
| 3531 | top_line_row->y = 0; | ||
| 3532 | update_window_line (w, 0); | ||
| 3533 | } | ||
| 3534 | |||
| 3535 | /* Update the rest of the lines. */ | ||
| 3536 | for (; row < end && (force_p || !input_pending); ++row) | ||
| 3537 | if (row->enabled_p | ||
| 3538 | /* A row can be completely invisible in case a desired | ||
| 3539 | matrix was built with a vscroll and then | ||
| 3540 | make_cursor_line_fully_visible shifts the matrix. */ | ||
| 3541 | && row->visible_height > 0) | ||
| 3542 | { | ||
| 3543 | int vpos = MATRIX_ROW_VPOS (row, desired_matrix); | ||
| 3544 | int i; | ||
| 3545 | |||
| 3546 | /* We'll Have to play a little bit with when to | ||
| 3547 | detect_input_pending. If it's done too often, | ||
| 3548 | scrolling large windows with repeated scroll-up | ||
| 3549 | commands will too quickly pause redisplay. */ | ||
| 3550 | if (!force_p && vpos % preempt_count == 0) | ||
| 3551 | detect_input_pending (); | ||
| 3552 | |||
| 3553 | update_window_line (w, vpos); | ||
| 3554 | |||
| 3555 | /* Mark all rows below the last visible one in the current | ||
| 3556 | matrix as invalid. This is necessary because of | ||
| 3557 | variable line heights. Consider the case of three | ||
| 3558 | successive redisplays, where the first displays 5 | ||
| 3559 | lines, the second 3 lines, and the third 5 lines again. | ||
| 3560 | If the second redisplay wouldn't mark rows in the | ||
| 3561 | current matrix invalid, the third redisplay might be | ||
| 3562 | tempted to optimize redisplay based on lines displayed | ||
| 3563 | in the first redisplay. */ | ||
| 3564 | if (MATRIX_ROW_BOTTOM_Y (row) >= yb) | ||
| 3565 | for (i = vpos + 1; i < w->current_matrix->nrows - 1; ++i) | ||
| 3566 | MATRIX_ROW (w->current_matrix, i)->enabled_p = 0; | ||
| 3567 | } | ||
| 3568 | |||
| 3569 | /* Was display preempted? */ | ||
| 3570 | paused_p = row < end; | ||
| 3571 | |||
| 3572 | set_cursor: | ||
| 3573 | |||
| 3574 | if (!paused_p && !w->pseudo_window_p) | ||
| 3575 | { | ||
| 3576 | /* Make cursor visible at cursor position of W. */ | ||
| 3577 | set_window_cursor_after_update (w); | ||
| 3578 | |||
| 3579 | #if 0 | ||
| 3580 | /* Check that current matrix invariants are satisfied. This | ||
| 3581 | is for debugging only. See the comment around | ||
| 3582 | check_matrix_invariants. */ | ||
| 3583 | IF_DEBUG (check_matrix_invariants (w)); | ||
| 3584 | #endif | ||
| 3585 | } | ||
| 3586 | |||
| 3587 | #if GLYPH_DEBUG | ||
| 3588 | /* Remember the redisplay method used to display the matrix. */ | ||
| 3589 | strcpy (w->current_matrix->method, w->desired_matrix->method); | ||
| 3590 | #endif | ||
| 3591 | |||
| 3592 | /* End of update of window W. */ | ||
| 3593 | rif->update_window_end_hook (w, 1); | ||
| 3594 | } | ||
| 3595 | else | ||
| 3596 | paused_p = 1; | ||
| 3597 | |||
| 3598 | clear_glyph_matrix (desired_matrix); | ||
| 3599 | return paused_p; | ||
| 3600 | } | ||
| 3601 | |||
| 3602 | |||
| 3603 | /* Update the display of area AREA in window W, row number VPOS. | ||
| 3604 | AREA can be either LEFT_MARGIN_AREA or RIGHT_MARGIN_AREA. */ | ||
| 3605 | |||
| 3606 | static void | ||
| 3607 | update_marginal_area (w, area, vpos) | ||
| 3608 | struct window *w; | ||
| 3609 | int area, vpos; | ||
| 3610 | { | ||
| 3611 | struct glyph_row *desired_row = MATRIX_ROW (w->desired_matrix, vpos); | ||
| 3612 | |||
| 3613 | /* Let functions in xterm.c know what area subsequent X positions | ||
| 3614 | will be relative to. */ | ||
| 3615 | updated_area = area; | ||
| 3616 | |||
| 3617 | /* Set cursor to start of glyphs, write them, and clear to the end | ||
| 3618 | of the area. I don't think that something more sophisticated is | ||
| 3619 | necessary here, since marginal areas will not be the default. */ | ||
| 3620 | rif->cursor_to (vpos, 0, desired_row->y, 0); | ||
| 3621 | if (desired_row->used[area]) | ||
| 3622 | rif->write_glyphs (desired_row->glyphs[area], desired_row->used[area]); | ||
| 3623 | rif->clear_end_of_line (-1); | ||
| 3624 | } | ||
| 3625 | |||
| 3626 | |||
| 3627 | /* Update the display of the text area of row VPOS in window W. */ | ||
| 3628 | |||
| 3629 | static void | ||
| 3630 | update_text_area (w, vpos) | ||
| 3631 | struct window *w; | ||
| 3632 | int vpos; | ||
| 3633 | { | ||
| 3634 | struct glyph_row *current_row = MATRIX_ROW (w->current_matrix, vpos); | ||
| 3635 | struct glyph_row *desired_row = MATRIX_ROW (w->desired_matrix, vpos); | ||
| 3636 | |||
| 3637 | /* Let functions in xterm.c know what area subsequent X positions | ||
| 3638 | will be relative to. */ | ||
| 3639 | updated_area = TEXT_AREA; | ||
| 3640 | |||
| 3641 | /* If rows are at different X or Y, or rows have different height, | ||
| 3642 | or the current row is marked invalid, write the entire line. */ | ||
| 3643 | if (!current_row->enabled_p | ||
| 3644 | || desired_row->y != current_row->y | ||
| 3645 | || desired_row->ascent != current_row->ascent | ||
| 3646 | || desired_row->visible_height != current_row->visible_height | ||
| 3647 | || current_row->x != desired_row->x) | ||
| 3648 | { | ||
| 3649 | rif->cursor_to (vpos, 0, desired_row->y, desired_row->x); | ||
| 3650 | |||
| 3651 | if (desired_row->used[TEXT_AREA]) | ||
| 3652 | rif->write_glyphs (desired_row->glyphs[TEXT_AREA], | ||
| 3653 | desired_row->used[TEXT_AREA]); | ||
| 3654 | |||
| 3655 | /* Clear to end of window. */ | ||
| 3656 | rif->clear_end_of_line (-1); | ||
| 3657 | } | ||
| 3658 | else | ||
| 3659 | { | ||
| 3660 | int stop, i, x; | ||
| 3661 | struct glyph *current_glyph = current_row->glyphs[TEXT_AREA]; | ||
| 3662 | struct glyph *desired_glyph = desired_row->glyphs[TEXT_AREA]; | ||
| 3663 | |||
| 3664 | /* If the desired row extends its face to the text area end, | ||
| 3665 | make sure we write at least one glyph, so that the face | ||
| 3666 | extension actually takes place. */ | ||
| 3667 | int desired_stop_pos = (desired_row->used[TEXT_AREA] | ||
| 3668 | - (MATRIX_ROW_EXTENDS_FACE_P (desired_row) | ||
| 3669 | ? 1 : 0)); | ||
| 3670 | |||
| 3671 | stop = min (current_row->used[TEXT_AREA], desired_stop_pos); | ||
| 3672 | i = 0; | ||
| 3673 | x = desired_row->x; | ||
| 3674 | |||
| 3675 | while (i < stop) | ||
| 3676 | { | ||
| 3677 | /* Skip over glyphs that both rows have in common. These | ||
| 3678 | don't have to be written. */ | ||
| 3679 | while (i < stop | ||
| 3680 | && GLYPH_EQUAL_P (desired_glyph, current_glyph)) | ||
| 3681 | { | ||
| 3682 | x += desired_glyph->pixel_width; | ||
| 3683 | ++desired_glyph, ++current_glyph, ++i; | ||
| 3684 | } | ||
| 3685 | |||
| 3686 | /* Consider the case that the current row contains "xxx ppp | ||
| 3687 | ggg" in italic Courier font, and the desired row is "xxx | ||
| 3688 | ggg". The character `p' has lbearing, `g' has not. The | ||
| 3689 | loop above will stop in front of the first `p' in the | ||
| 3690 | current row. If we would start writing glyphs there, we | ||
| 3691 | wouldn't erase the lbearing of the `p'. The rest of the | ||
| 3692 | lbearing problem is then taken care of by x_draw_glyphs. */ | ||
| 3693 | if (current_row->contains_overlapping_glyphs_p | ||
| 3694 | && i > 0 | ||
| 3695 | && i < current_row->used[TEXT_AREA] | ||
| 3696 | && current_row->used[TEXT_AREA] != desired_row->used[TEXT_AREA]) | ||
| 3697 | { | ||
| 3698 | int left, right; | ||
| 3699 | rif->get_glyph_overhangs (current_glyph, XFRAME (w->frame), | ||
| 3700 | &left, &right); | ||
| 3701 | while (left > 0 && i > 0) | ||
| 3702 | { | ||
| 3703 | --i, --desired_glyph, --current_glyph; | ||
| 3704 | x -= desired_glyph->pixel_width; | ||
| 3705 | left -= desired_glyph->pixel_width; | ||
| 3706 | } | ||
| 3707 | } | ||
| 3708 | |||
| 3709 | /* Try to avoid writing the entire rest of the desired row | ||
| 3710 | by looking for a resync point. This mainly prevents | ||
| 3711 | mode line flickering in the case the mode line is in | ||
| 3712 | fixed-pitch font, which it usually will be. */ | ||
| 3713 | if (i < desired_row->used[TEXT_AREA]) | ||
| 3714 | { | ||
| 3715 | int start_x = x, start_hpos = i; | ||
| 3716 | struct glyph *start = desired_glyph; | ||
| 3717 | int current_x = x; | ||
| 3718 | |||
| 3719 | /* Find the next glyph that's equal again. */ | ||
| 3720 | while (i < stop | ||
| 3721 | && !GLYPH_EQUAL_P (desired_glyph, current_glyph) | ||
| 3722 | && x == current_x) | ||
| 3723 | { | ||
| 3724 | x += desired_glyph->pixel_width; | ||
| 3725 | current_x += current_glyph->pixel_width; | ||
| 3726 | ++desired_glyph, ++current_glyph, ++i; | ||
| 3727 | } | ||
| 3728 | |||
| 3729 | if (i == start_hpos || x != current_x) | ||
| 3730 | { | ||
| 3731 | i = start_hpos; | ||
| 3732 | x = start_x; | ||
| 3733 | desired_glyph = start; | ||
| 3734 | break; | ||
| 3735 | } | ||
| 3736 | |||
| 3737 | rif->cursor_to (vpos, start_hpos, desired_row->y, start_x); | ||
| 3738 | rif->write_glyphs (start, i - start_hpos); | ||
| 3739 | } | ||
| 3740 | } | ||
| 3741 | |||
| 3742 | /* Write the rest. */ | ||
| 3743 | if (i < desired_row->used[TEXT_AREA]) | ||
| 3744 | { | ||
| 3745 | rif->cursor_to (vpos, i, desired_row->y, x); | ||
| 3746 | rif->write_glyphs (desired_glyph, desired_row->used[TEXT_AREA] - i); | ||
| 3747 | } | ||
| 3748 | |||
| 3749 | /* Maybe clear to end of line. */ | ||
| 3750 | if (MATRIX_ROW_EXTENDS_FACE_P (desired_row)) | ||
| 3751 | { | ||
| 3752 | /* If new row extends to the end of the text area, nothing | ||
| 3753 | has to be cleared, if and only if we did a write_glyphs | ||
| 3754 | above. This is made sure by setting desired_stop_pos | ||
| 3755 | appropriately above. */ | ||
| 3756 | xassert (i < desired_row->used[TEXT_AREA]); | ||
| 3757 | } | ||
| 3758 | else if (MATRIX_ROW_EXTENDS_FACE_P (current_row)) | ||
| 3759 | { | ||
| 3760 | /* If old row extends to the end of the text area, clear. */ | ||
| 3761 | if (i >= desired_row->used[TEXT_AREA]) | ||
| 3762 | rif->cursor_to (vpos, i, desired_row->y, | ||
| 3763 | desired_row->x + desired_row->pixel_width); | ||
| 3764 | rif->clear_end_of_line (-1); | ||
| 3765 | } | ||
| 3766 | else if (desired_row->pixel_width < current_row->pixel_width) | ||
| 3767 | { | ||
| 3768 | /* Otherwise clear to the end of the old row. Everything | ||
| 3769 | after that position should be clear already. */ | ||
| 3770 | int x; | ||
| 3771 | |||
| 3772 | if (i >= desired_row->used[TEXT_AREA]) | ||
| 3773 | rif->cursor_to (vpos, i, desired_row->y, | ||
| 3774 | desired_row->x + desired_row->pixel_width); | ||
| 3775 | |||
| 3776 | /* If cursor is displayed at the end of the line, make sure | ||
| 3777 | it's cleared. Nowadays we don't have a phys_cursor_glyph | ||
| 3778 | with which to erase the cursor (because this method | ||
| 3779 | doesn't work with lbearing/rbearing), so we must do it | ||
| 3780 | this way. */ | ||
| 3781 | if (vpos == w->phys_cursor.vpos | ||
| 3782 | && w->phys_cursor.hpos >= desired_row->used[TEXT_AREA]) | ||
| 3783 | { | ||
| 3784 | w->phys_cursor_on_p = 0; | ||
| 3785 | x = -1; | ||
| 3786 | } | ||
| 3787 | else | ||
| 3788 | x = current_row->x + current_row->pixel_width; | ||
| 3789 | rif->clear_end_of_line (x); | ||
| 3790 | } | ||
| 3791 | } | ||
| 3792 | } | ||
| 3793 | |||
| 3794 | |||
| 3795 | /* Update row VPOS in window W. */ | ||
| 3796 | |||
| 3797 | static void | ||
| 3798 | update_window_line (w, vpos) | ||
| 3799 | struct window *w; | ||
| 3800 | int vpos; | ||
| 3801 | { | ||
| 3802 | struct glyph_row *current_row = MATRIX_ROW (w->current_matrix, vpos); | ||
| 3803 | struct glyph_row *desired_row = MATRIX_ROW (w->desired_matrix, vpos); | ||
| 3804 | |||
| 3805 | xassert (desired_row->enabled_p); | ||
| 3806 | |||
| 3807 | /* Set the row being updated. This is important to let xterm.c | ||
| 3808 | know what line height values are in effect. */ | ||
| 3809 | updated_row = desired_row; | ||
| 3810 | |||
| 3811 | /* Update display of the left margin area, if there is one. */ | ||
| 3812 | if (!desired_row->full_width_p | ||
| 3813 | && !NILP (w->left_margin_width)) | ||
| 3814 | update_marginal_area (w, LEFT_MARGIN_AREA, vpos); | ||
| 3815 | |||
| 3816 | /* Update the display of the text area. */ | ||
| 3817 | update_text_area (w, vpos); | ||
| 3818 | |||
| 3819 | /* Update display of the right margin area, if there is one. */ | ||
| 3820 | if (!desired_row->full_width_p | ||
| 3821 | && !NILP (w->right_margin_width)) | ||
| 3822 | update_marginal_area (w, RIGHT_MARGIN_AREA, vpos); | ||
| 3823 | |||
| 3824 | /* Draw truncation marks etc. */ | ||
| 3825 | if (!current_row->enabled_p | ||
| 3826 | || desired_row->y != current_row->y | ||
| 3827 | || desired_row->visible_height != current_row->visible_height | ||
| 3828 | || desired_row->overlay_arrow_p != current_row->overlay_arrow_p | ||
| 3829 | || desired_row->truncated_on_left_p != current_row->truncated_on_left_p | ||
| 3830 | || desired_row->truncated_on_right_p != current_row->truncated_on_right_p | ||
| 3831 | || desired_row->continued_p != current_row->continued_p | ||
| 3832 | || desired_row->mode_line_p != current_row->mode_line_p | ||
| 3833 | || (desired_row->indicate_empty_line_p | ||
| 3834 | != current_row->indicate_empty_line_p) | ||
| 3835 | || (MATRIX_ROW_CONTINUATION_LINE_P (desired_row) | ||
| 3836 | != MATRIX_ROW_CONTINUATION_LINE_P (current_row))) | ||
| 3837 | rif->after_update_window_line_hook (desired_row); | ||
| 3838 | |||
| 3839 | /* Update current_row from desired_row. */ | ||
| 3840 | make_current (w->desired_matrix, w->current_matrix, vpos); | ||
| 3841 | updated_row = NULL; | ||
| 3842 | } | ||
| 3843 | |||
| 3844 | |||
| 3845 | /* Set the cursor after an update of window W. This function may only | ||
| 3846 | be called from update_window. */ | ||
| 3847 | |||
| 3848 | static void | ||
| 3849 | set_window_cursor_after_update (w) | ||
| 3850 | struct window *w; | ||
| 3851 | { | ||
| 3852 | struct frame *f = XFRAME (w->frame); | ||
| 3853 | int cx, cy, vpos, hpos; | ||
| 3854 | |||
| 3855 | /* Not intended for frame matrix updates. */ | ||
| 3856 | xassert (FRAME_WINDOW_P (f)); | ||
| 3857 | |||
| 3858 | if ((cursor_in_echo_area | ||
| 3859 | /* If we are showing a message instead of the mini-buffer, | ||
| 3860 | show the cursor for the message instead of for the | ||
| 3861 | (now hidden) mini-buffer contents. */ | ||
| 3862 | || (XWINDOW (minibuf_window) == w | ||
| 3863 | && EQ (minibuf_window, echo_area_window) | ||
| 3864 | && (echo_area_glyphs || STRINGP (echo_area_message)))) | ||
| 3865 | /* These cases apply only to the frame that contains | ||
| 3866 | the active mini-buffer window. */ | ||
| 3867 | && FRAME_HAS_MINIBUF_P (f) | ||
| 3868 | && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window)) | ||
| 3869 | { | ||
| 3870 | cx = cy = vpos = hpos = 0; | ||
| 3871 | |||
| 3872 | if (cursor_in_echo_area >= 0) | ||
| 3873 | { | ||
| 3874 | /* If the mini-buffer is several lines high, find the last | ||
| 3875 | line that has any text on it. Note: either all lines | ||
| 3876 | are enabled or none. Otherwise we wouldn't be able to | ||
| 3877 | determine Y. */ | ||
| 3878 | struct glyph_row *row = MATRIX_ROW (w->current_matrix, 0); | ||
| 3879 | int vpos, last_row_vpos; | ||
| 3880 | struct glyph_row *last_row = NULL; | ||
| 3881 | |||
| 3882 | vpos = 0; | ||
| 3883 | while (vpos < w->current_matrix->nrows) | ||
| 3884 | { | ||
| 3885 | if (row->enabled_p && row->used[TEXT_AREA]) | ||
| 3886 | { | ||
| 3887 | last_row = row; | ||
| 3888 | last_row_vpos = vpos; | ||
| 3889 | } | ||
| 3890 | ++row; | ||
| 3891 | ++vpos; | ||
| 3892 | } | ||
| 3893 | |||
| 3894 | if (last_row) | ||
| 3895 | { | ||
| 3896 | cx = last_row->pixel_width; | ||
| 3897 | hpos = last_row->used[TEXT_AREA]; | ||
| 3898 | cy = last_row->y; | ||
| 3899 | vpos = last_row_vpos; | ||
| 3900 | } | ||
| 3901 | } | ||
| 3902 | } | ||
| 3903 | else | ||
| 3904 | { | ||
| 3905 | cx = w->cursor.x; | ||
| 3906 | cy = w->cursor.y; | ||
| 3907 | hpos = w->cursor.hpos; | ||
| 3908 | vpos = w->cursor.vpos; | ||
| 3909 | } | ||
| 3910 | |||
| 3911 | /* Window cursor can be out of sync for horizontally split windows. */ | ||
| 3912 | hpos = max (0, hpos); | ||
| 3913 | hpos = min (w->current_matrix->matrix_w - 1, hpos); | ||
| 3914 | vpos = max (0, vpos); | ||
| 3915 | vpos = min (w->current_matrix->nrows - 1, vpos); | ||
| 3916 | rif->cursor_to (vpos, hpos, cy, cx); | ||
| 3917 | } | ||
| 3918 | |||
| 3919 | |||
| 3920 | /* Try to reuse part of the current display of W by scrolling lines. | ||
| 3921 | TOP_LINE_P non-zero means W has a top mode line. | ||
| 3922 | |||
| 3923 | The algorithm is taken from Communications of the ACM, Apr78 "A | ||
| 3924 | Technique for Isolating Differences Between Files." It should take | ||
| 3925 | O(N) time. | ||
| 3926 | |||
| 3927 | A short outline of the steps of the algorithm | ||
| 3928 | |||
| 3929 | 1. Skip lines equal at the start and end of both matrices. | ||
| 3930 | |||
| 3931 | 2. Enter rows in the current and desired matrix into a symbol | ||
| 3932 | table, counting how often they appear in both matrices. | ||
| 3933 | |||
| 3934 | 3. Rows that appear exactly once in both matrices serve as anchors, | ||
| 3935 | i.e. we assume that such lines are likely to have been moved. | ||
| 1180 | 3936 | ||
| 1181 | XSETFASTINT (position, PT); | 3937 | 4. Starting from anchor lines, extend regions to be scrolled both |
| 1182 | if (XFASTINT (position) < ZV | 3938 | forward and backward. |
| 1183 | && ! NILP (Fget_char_property (position, | 3939 | |
| 1184 | Qinvisible, | 3940 | Value is |
| 1185 | selected_window))) | 3941 | |
| 3942 | -1 if all rows were found to be equal. | ||
| 3943 | 0 to indicate that we did not scroll the display, or | ||
| 3944 | 1 if we did scroll. */ | ||
| 3945 | |||
| 3946 | static int | ||
| 3947 | scrolling_window (w, top_line_p) | ||
| 3948 | struct window *w; | ||
| 3949 | int top_line_p; | ||
| 3950 | { | ||
| 3951 | struct symbol | ||
| 3952 | { | ||
| 3953 | /* Number of occurrences of this line in old and new matrix. */ | ||
| 3954 | short old_uses, new_uses; | ||
| 3955 | |||
| 3956 | /* Vpos of line in new matrix. */ | ||
| 3957 | short new_line_number; | ||
| 3958 | |||
| 3959 | /* The line itself. */ | ||
| 3960 | struct glyph_row *row; | ||
| 3961 | |||
| 3962 | /* Hash collision chain. */ | ||
| 3963 | struct symbol *next; | ||
| 3964 | }; | ||
| 3965 | |||
| 3966 | int SYMBOL_TABLE_SIZE = 101; | ||
| 3967 | struct symbol **table; | ||
| 3968 | struct symbol **old_line_syms, **new_line_syms; | ||
| 3969 | int i, j, first_old, first_new, last_old, last_new; | ||
| 3970 | struct symbol *sym; | ||
| 3971 | struct run **runs; | ||
| 3972 | int nruns; | ||
| 3973 | struct glyph_matrix *desired_matrix = w->desired_matrix; | ||
| 3974 | struct glyph_matrix *current_matrix = w->current_matrix; | ||
| 3975 | int yb = window_text_bottom_y (w); | ||
| 3976 | |||
| 3977 | /* Skip over rows equal at the start. */ | ||
| 3978 | i = top_line_p ? 1 : 0; | ||
| 3979 | while (i < current_matrix->nrows - 1 | ||
| 3980 | && MATRIX_ROW_ENABLED_P (current_matrix, i) | ||
| 3981 | && MATRIX_ROW_ENABLED_P (desired_matrix, i) | ||
| 3982 | && MATRIX_ROW_BOTTOM_Y (MATRIX_ROW (desired_matrix, i)) < yb | ||
| 3983 | && MATRIX_ROW_BOTTOM_Y (MATRIX_ROW (current_matrix, i)) < yb | ||
| 3984 | && row_equal_p (w, | ||
| 3985 | MATRIX_ROW (desired_matrix, i), | ||
| 3986 | MATRIX_ROW (current_matrix, i))) | ||
| 3987 | { | ||
| 3988 | assign_row (MATRIX_ROW (current_matrix, i), | ||
| 3989 | MATRIX_ROW (desired_matrix, i)); | ||
| 3990 | MATRIX_ROW (desired_matrix, i)->enabled_p = 0; | ||
| 3991 | ++i; | ||
| 3992 | } | ||
| 3993 | |||
| 3994 | /* Give up if some rows in the desired matrix are not enabled. */ | ||
| 3995 | if (!MATRIX_ROW (desired_matrix, i)->enabled_p) | ||
| 3996 | return -1; | ||
| 3997 | |||
| 3998 | first_old = first_new = i; | ||
| 3999 | |||
| 4000 | /* Set last_new to the index + 1 of the last enabled row in the | ||
| 4001 | desired matrix. */ | ||
| 4002 | i = first_new + 1; | ||
| 4003 | while (i < desired_matrix->nrows - 1 | ||
| 4004 | && MATRIX_ROW (desired_matrix, i)->enabled_p | ||
| 4005 | && MATRIX_ROW_BOTTOM_Y (MATRIX_ROW (desired_matrix, i)) < yb) | ||
| 4006 | ++i; | ||
| 4007 | |||
| 4008 | if (!MATRIX_ROW (desired_matrix, i)->enabled_p) | ||
| 1186 | return 0; | 4009 | return 0; |
| 1187 | 4010 | ||
| 1188 | XSETFASTINT (position, PT - 1); | 4011 | last_new = i; |
| 1189 | if (XFASTINT (position) >= BEGV | 4012 | |
| 1190 | && ! NILP (Fget_char_property (position, | 4013 | /* Set last_old to the index + 1 of the last enabled row in the |
| 1191 | Qinvisible, | 4014 | current matrix. We don't look at the enabled flag here because |
| 1192 | selected_window))) | 4015 | we plan to reuse part of the display even if other parts are |
| 4016 | disabled. */ | ||
| 4017 | i = first_old + 1; | ||
| 4018 | while (i < current_matrix->nrows - 1 | ||
| 4019 | && MATRIX_ROW_BOTTOM_Y (MATRIX_ROW (current_matrix, i)) < yb) | ||
| 4020 | ++i; | ||
| 4021 | last_old = i; | ||
| 4022 | |||
| 4023 | /* Skip over rows equal at the bottom. */ | ||
| 4024 | i = last_new; | ||
| 4025 | j = last_old; | ||
| 4026 | while (i - 1 > first_new | ||
| 4027 | && j - 1 > first_old | ||
| 4028 | && MATRIX_ROW (current_matrix, i - 1)->enabled_p | ||
| 4029 | && (MATRIX_ROW (current_matrix, i - 1)->y | ||
| 4030 | == MATRIX_ROW (desired_matrix, j - 1)->y) | ||
| 4031 | && row_equal_p (w, | ||
| 4032 | MATRIX_ROW (desired_matrix, i - 1), | ||
| 4033 | MATRIX_ROW (current_matrix, j - 1))) | ||
| 4034 | --i, --j; | ||
| 4035 | last_new = i; | ||
| 4036 | last_old = j; | ||
| 4037 | |||
| 4038 | /* Nothing to do if all rows are equal. */ | ||
| 4039 | if (last_new == first_new) | ||
| 1193 | return 0; | 4040 | return 0; |
| 1194 | #endif | ||
| 1195 | 4041 | ||
| 1196 | FRAME_CURSOR_X (frame) += n; | 4042 | /* Allocate a hash table in which all rows will be inserted. */ |
| 1197 | XSETFASTINT (w->last_point_x, FRAME_CURSOR_X (frame)); | 4043 | table = (struct symbol **) alloca (SYMBOL_TABLE_SIZE * sizeof *table); |
| 1198 | XSETFASTINT (w->last_point, PT); | 4044 | bzero (table, SYMBOL_TABLE_SIZE * sizeof *table); |
| 1199 | cursor_to (FRAME_CURSOR_Y (frame), FRAME_CURSOR_X (frame)); | 4045 | |
| 1200 | fflush (stdout); | 4046 | /* For each row in the current matrix, record the symbol belonging |
| 4047 | to the row in OLD_LINE_SYMS. */ | ||
| 4048 | old_line_syms = (struct symbol **) alloca (current_matrix->nrows | ||
| 4049 | * sizeof *old_line_syms); | ||
| 4050 | new_line_syms = (struct symbol **) alloca (desired_matrix->nrows | ||
| 4051 | * sizeof *new_line_syms); | ||
| 4052 | |||
| 4053 | #define ADDSYM(ROW) \ | ||
| 4054 | do \ | ||
| 4055 | { \ | ||
| 4056 | struct glyph_row *row_ = (ROW); \ | ||
| 4057 | int i_ = row_->hash % SYMBOL_TABLE_SIZE; \ | ||
| 4058 | sym = table[i_]; \ | ||
| 4059 | while (sym && !row_equal_p (w, sym->row, row_)) \ | ||
| 4060 | sym = sym->next; \ | ||
| 4061 | if (sym == NULL) \ | ||
| 4062 | { \ | ||
| 4063 | sym = (struct symbol *) alloca (sizeof *sym); \ | ||
| 4064 | sym->row = row_; \ | ||
| 4065 | sym->old_uses = sym->new_uses = 0; \ | ||
| 4066 | sym->next = table[i_]; \ | ||
| 4067 | table[i_] = sym; \ | ||
| 4068 | } \ | ||
| 4069 | } \ | ||
| 4070 | while (0) | ||
| 4071 | |||
| 4072 | /* Add current rows to the symbol table. */ | ||
| 4073 | for (i = first_old; i < last_old; ++i) | ||
| 4074 | { | ||
| 4075 | if (MATRIX_ROW (current_matrix, i)->enabled_p) | ||
| 4076 | { | ||
| 4077 | ADDSYM (MATRIX_ROW (current_matrix, i)); | ||
| 4078 | old_line_syms[i] = sym; | ||
| 4079 | ++sym->old_uses; | ||
| 4080 | } | ||
| 4081 | else | ||
| 4082 | old_line_syms[i] = NULL; | ||
| 4083 | } | ||
| 1201 | 4084 | ||
| 4085 | /* Add desired rows to the symbol table. */ | ||
| 4086 | for (i = first_new; i < last_new; ++i) | ||
| 4087 | { | ||
| 4088 | xassert (MATRIX_ROW_ENABLED_P (desired_matrix, i)); | ||
| 4089 | ADDSYM (MATRIX_ROW (desired_matrix, i)); | ||
| 4090 | ++sym->new_uses; | ||
| 4091 | new_line_syms[i] = sym; | ||
| 4092 | sym->new_line_number = i; | ||
| 4093 | } | ||
| 4094 | |||
| 4095 | #undef ADDSYM | ||
| 4096 | |||
| 4097 | /* Record in runs which moves were found, ordered by pixel | ||
| 4098 | height of copied areas. */ | ||
| 4099 | nruns = 0; | ||
| 4100 | runs = (struct run **) alloca (desired_matrix->nrows * sizeof *runs); | ||
| 4101 | |||
| 4102 | /* Identify moves based on lines that are unique and equal | ||
| 4103 | in both matrices. */ | ||
| 4104 | for (i = first_old; i < last_old;) | ||
| 4105 | if (old_line_syms[i] | ||
| 4106 | && old_line_syms[i]->old_uses == 1 | ||
| 4107 | && old_line_syms[i]->new_uses == 1) | ||
| 4108 | { | ||
| 4109 | int j, k; | ||
| 4110 | int new_line = old_line_syms[i]->new_line_number; | ||
| 4111 | struct run *run = (struct run *) alloca (sizeof *run); | ||
| 4112 | |||
| 4113 | /* Record move. */ | ||
| 4114 | run->current_vpos = i; | ||
| 4115 | run->current_y = MATRIX_ROW (current_matrix, i)->y; | ||
| 4116 | run->desired_vpos = new_line; | ||
| 4117 | run->desired_y = MATRIX_ROW (desired_matrix, new_line)->y; | ||
| 4118 | run->nrows = 1; | ||
| 4119 | run->height = MATRIX_ROW (current_matrix, i)->height; | ||
| 4120 | |||
| 4121 | /* Extend backward. */ | ||
| 4122 | j = i - 1; | ||
| 4123 | k = new_line - 1; | ||
| 4124 | while (j > first_old | ||
| 4125 | && k > first_new | ||
| 4126 | && old_line_syms[j] == new_line_syms[k]) | ||
| 4127 | { | ||
| 4128 | int h = MATRIX_ROW (current_matrix, j)->height; | ||
| 4129 | --run->current_vpos; | ||
| 4130 | --run->desired_vpos; | ||
| 4131 | ++run->nrows; | ||
| 4132 | run->height += h; | ||
| 4133 | run->desired_y -= h; | ||
| 4134 | run->current_y -= h; | ||
| 4135 | --j, --k; | ||
| 4136 | } | ||
| 4137 | |||
| 4138 | /* Extend forward. */ | ||
| 4139 | j = i + 1; | ||
| 4140 | k = new_line + 1; | ||
| 4141 | while (j < last_old | ||
| 4142 | && k < last_new | ||
| 4143 | && old_line_syms[j] == new_line_syms[k]) | ||
| 4144 | { | ||
| 4145 | int h = MATRIX_ROW (current_matrix, j)->height; | ||
| 4146 | ++run->nrows; | ||
| 4147 | run->height += h; | ||
| 4148 | ++j, ++k; | ||
| 4149 | } | ||
| 4150 | |||
| 4151 | /* Insert run into list of all runs. Order runs by copied | ||
| 4152 | pixel lines. Note that we record runs that don't have to | ||
| 4153 | be copied because they are already in place. This is done | ||
| 4154 | because we can avoid calling update_window_line in this | ||
| 4155 | case. */ | ||
| 4156 | for (j = 0; j < nruns && runs[j]->height > run->height; ++j) | ||
| 4157 | ; | ||
| 4158 | for (k = nruns; k >= j; --k) | ||
| 4159 | runs[k] = runs[k - 1]; | ||
| 4160 | runs[j] = run; | ||
| 4161 | ++nruns; | ||
| 4162 | |||
| 4163 | i += run->nrows; | ||
| 4164 | } | ||
| 4165 | else | ||
| 4166 | ++i; | ||
| 4167 | |||
| 4168 | /* Do the moves. Do it in a way that we don't overwrite something | ||
| 4169 | we want to copy later on. This is not solvable in general | ||
| 4170 | because there is only one display and we don't have a way to | ||
| 4171 | exchange areas on this display. Example: | ||
| 4172 | |||
| 4173 | +-----------+ +-----------+ | ||
| 4174 | | A | | B | | ||
| 4175 | +-----------+ --> +-----------+ | ||
| 4176 | | B | | A | | ||
| 4177 | +-----------+ +-----------+ | ||
| 4178 | |||
| 4179 | Instead, prefer bigger moves, and invalidate moves that would | ||
| 4180 | copy from where we copied to. */ | ||
| 4181 | |||
| 4182 | for (i = 0; i < nruns; ++i) | ||
| 4183 | if (runs[i]->nrows > 0) | ||
| 4184 | { | ||
| 4185 | struct run *r = runs[i]; | ||
| 4186 | |||
| 4187 | /* Copy on the display. */ | ||
| 4188 | if (r->current_y != r->desired_y) | ||
| 4189 | { | ||
| 4190 | rif->scroll_run_hook (w, r); | ||
| 4191 | |||
| 4192 | /* Invalidate runs that copy from where we copied to. */ | ||
| 4193 | for (j = i + 1; j < nruns; ++j) | ||
| 4194 | { | ||
| 4195 | struct run *p = runs[j]; | ||
| 4196 | |||
| 4197 | if ((p->current_y >= r->desired_y | ||
| 4198 | && p->current_y < r->desired_y + r->height) | ||
| 4199 | || (p->current_y + p->height >= r->desired_y | ||
| 4200 | && (p->current_y + p->height | ||
| 4201 | < r->desired_y + r->height))) | ||
| 4202 | p->nrows = 0; | ||
| 4203 | } | ||
| 4204 | } | ||
| 4205 | |||
| 4206 | /* Assign matrix rows. */ | ||
| 4207 | for (j = 0; j < r->nrows; ++j) | ||
| 4208 | { | ||
| 4209 | struct glyph_row *from, *to; | ||
| 4210 | to = MATRIX_ROW (current_matrix, r->desired_vpos + j); | ||
| 4211 | from = MATRIX_ROW (desired_matrix, r->desired_vpos + j); | ||
| 4212 | assign_row (to, from); | ||
| 4213 | to->enabled_p = 1, from->enabled_p = 0; | ||
| 4214 | } | ||
| 4215 | } | ||
| 4216 | |||
| 4217 | /* Value is non-zero to indicate that we scrolled the display. */ | ||
| 1202 | return 1; | 4218 | return 1; |
| 1203 | } | 4219 | } |
| 4220 | |||
| 4221 | |||
| 4222 | /* Set WINDOW->must_be_updated_p TO ON_P for all windows WINDOW in the | ||
| 4223 | window tree rooted at W. */ | ||
| 4224 | |||
| 4225 | void | ||
| 4226 | set_window_update_flags (w, on_p) | ||
| 4227 | struct window *w; | ||
| 4228 | int on_p; | ||
| 4229 | { | ||
| 4230 | while (w) | ||
| 4231 | { | ||
| 4232 | if (!NILP (w->hchild)) | ||
| 4233 | set_window_update_flags (XWINDOW (w->hchild), on_p); | ||
| 4234 | else if (!NILP (w->vchild)) | ||
| 4235 | set_window_update_flags (XWINDOW (w->vchild), on_p); | ||
| 4236 | else | ||
| 4237 | w->must_be_updated_p = on_p; | ||
| 4238 | |||
| 4239 | w = NILP (w->next) ? 0 : XWINDOW (w->next); | ||
| 4240 | } | ||
| 4241 | } | ||
| 4242 | |||
| 4243 | |||
| 1204 | 4244 | ||
| 1205 | static void update_line (); | 4245 | /************************************************************************ |
| 4246 | Frame-Based Updates | ||
| 4247 | ************************************************************************/ | ||
| 1206 | 4248 | ||
| 1207 | /* Update frame F based on the data in FRAME_DESIRED_GLYPHS. | 4249 | /* Update the desired frame matrix of frame F. |
| 1208 | Value is nonzero if redisplay stopped due to pending input. | ||
| 1209 | FORCE nonzero means do not stop for pending input. */ | ||
| 1210 | 4250 | ||
| 1211 | int | 4251 | FORCE_P non-zero means that the update should not be stopped by |
| 1212 | update_frame (f, force, inhibit_hairy_id) | 4252 | pending input. INHIBIT_HAIRY_ID_P non-zero means that scrolling |
| 1213 | FRAME_PTR f; | 4253 | should not be tried. |
| 1214 | int force; | 4254 | |
| 1215 | int inhibit_hairy_id; | 4255 | Value is non-zero if update was stopped due to pending input. */ |
| 4256 | |||
| 4257 | static int | ||
| 4258 | update_frame_1 (f, force_p, inhibit_id_p) | ||
| 4259 | struct frame *f; | ||
| 4260 | int force_p; | ||
| 4261 | int inhibit_id_p; | ||
| 1216 | { | 4262 | { |
| 1217 | register struct frame_glyphs *current_frame; | 4263 | /* Frame matrices to work on. */ |
| 1218 | register struct frame_glyphs *desired_frame = 0; | 4264 | struct glyph_matrix *current_matrix = f->current_matrix; |
| 1219 | register int i; | 4265 | struct glyph_matrix *desired_matrix = f->desired_matrix; |
| 4266 | int i; | ||
| 1220 | int pause; | 4267 | int pause; |
| 1221 | int preempt_count = baud_rate / 2400 + 1; | 4268 | int preempt_count = baud_rate / 2400 + 1; |
| 1222 | extern int input_pending; | 4269 | extern int input_pending; |
| 1223 | #ifdef HAVE_WINDOW_SYSTEM | 4270 | |
| 1224 | register int downto, leftmost; | 4271 | xassert (current_matrix && desired_matrix); |
| 1225 | #endif | ||
| 1226 | 4272 | ||
| 1227 | if (baud_rate != FRAME_COST_BAUD_RATE (f)) | 4273 | if (baud_rate != FRAME_COST_BAUD_RATE (f)) |
| 1228 | calculate_costs (f); | 4274 | calculate_costs (f); |
| @@ -1230,10 +4276,8 @@ update_frame (f, force, inhibit_hairy_id) | |||
| 1230 | if (preempt_count <= 0) | 4276 | if (preempt_count <= 0) |
| 1231 | preempt_count = 1; | 4277 | preempt_count = 1; |
| 1232 | 4278 | ||
| 1233 | if (FRAME_HEIGHT (f) == 0) abort (); /* Some bug zeros some core */ | ||
| 1234 | |||
| 1235 | detect_input_pending (); | 4279 | detect_input_pending (); |
| 1236 | if (input_pending && !force) | 4280 | if (input_pending && !force_p) |
| 1237 | { | 4281 | { |
| 1238 | pause = 1; | 4282 | pause = 1; |
| 1239 | goto do_pause; | 4283 | goto do_pause; |
| @@ -1241,48 +4285,28 @@ update_frame (f, force, inhibit_hairy_id) | |||
| 1241 | 4285 | ||
| 1242 | update_begin (f); | 4286 | update_begin (f); |
| 1243 | 4287 | ||
| 4288 | /* If we cannot insert/delete lines, it's no use trying it. */ | ||
| 1244 | if (!line_ins_del_ok) | 4289 | if (!line_ins_del_ok) |
| 1245 | inhibit_hairy_id = 1; | 4290 | inhibit_id_p = 1; |
| 1246 | |||
| 1247 | /* These are separate to avoid a possible bug in the AIX C compiler. */ | ||
| 1248 | current_frame = FRAME_CURRENT_GLYPHS (f); | ||
| 1249 | desired_frame = FRAME_DESIRED_GLYPHS (f); | ||
| 1250 | 4291 | ||
| 1251 | /* See if any of the desired lines are enabled; don't compute for | 4292 | /* See if any of the desired lines are enabled; don't compute for |
| 1252 | i/d line if just want cursor motion. */ | 4293 | i/d line if just want cursor motion. */ |
| 1253 | for (i = 0; i < FRAME_HEIGHT (f); i++) | 4294 | for (i = 0; i < desired_matrix->nrows; i++) |
| 1254 | if (desired_frame->enable[i]) | 4295 | if (MATRIX_ROW_ENABLED_P (desired_matrix, i)) |
| 1255 | break; | 4296 | break; |
| 1256 | 4297 | ||
| 1257 | /* Try doing i/d line, if not yet inhibited. */ | 4298 | /* Try doing i/d line, if not yet inhibited. */ |
| 1258 | if (!inhibit_hairy_id && i < FRAME_HEIGHT (f)) | 4299 | if (!inhibit_id_p && i < desired_matrix->nrows) |
| 1259 | force |= scrolling (f); | 4300 | force_p |= scrolling (f); |
| 1260 | 4301 | ||
| 1261 | /* Update the individual lines as needed. Do bottom line first. */ | 4302 | /* Update the individual lines as needed. Do bottom line first. */ |
| 4303 | if (MATRIX_ROW_ENABLED_P (desired_matrix, desired_matrix->nrows - 1)) | ||
| 4304 | update_frame_line (f, desired_matrix->nrows - 1); | ||
| 1262 | 4305 | ||
| 1263 | if (desired_frame->enable[FRAME_HEIGHT (f) - 1]) | 4306 | /* Now update the rest of the lines. */ |
| 1264 | update_line (f, FRAME_HEIGHT (f) - 1); | 4307 | for (i = 0; i < desired_matrix->nrows - 1 && (force_p || !input_pending); i++) |
| 1265 | |||
| 1266 | #ifdef HAVE_WINDOW_SYSTEM | ||
| 1267 | if (FRAME_WINDOW_P (f)) | ||
| 1268 | { | 4308 | { |
| 1269 | leftmost = downto = FRAME_INTERNAL_BORDER_WIDTH (f); | 4309 | if (MATRIX_ROW_ENABLED_P (desired_matrix, i)) |
| 1270 | if (desired_frame->enable[0]) | ||
| 1271 | { | ||
| 1272 | current_frame->top_left_x[FRAME_HEIGHT (f) - 1] = leftmost; | ||
| 1273 | current_frame->top_left_y[FRAME_HEIGHT (f) - 1] | ||
| 1274 | = PIXEL_HEIGHT (f) - FRAME_INTERNAL_BORDER_WIDTH (f) | ||
| 1275 | - current_frame->pix_height[FRAME_HEIGHT (f) - 1]; | ||
| 1276 | current_frame->top_left_x[0] = leftmost; | ||
| 1277 | current_frame->top_left_y[0] = downto; | ||
| 1278 | } | ||
| 1279 | } | ||
| 1280 | #endif /* HAVE_WINDOW_SYSTEM */ | ||
| 1281 | |||
| 1282 | /* Now update the rest of the lines. */ | ||
| 1283 | for (i = 0; i < FRAME_HEIGHT (f) - 1 && (force || !input_pending); i++) | ||
| 1284 | { | ||
| 1285 | if (desired_frame->enable[i]) | ||
| 1286 | { | 4310 | { |
| 1287 | if (FRAME_TERMCAP_P (f)) | 4311 | if (FRAME_TERMCAP_P (f)) |
| 1288 | { | 4312 | { |
| @@ -1300,7 +4324,7 @@ update_frame (f, force, inhibit_hairy_id) | |||
| 1300 | #ifdef EMACS_OUTQSIZE | 4324 | #ifdef EMACS_OUTQSIZE |
| 1301 | if (EMACS_OUTQSIZE (0, &outq) < 0) | 4325 | if (EMACS_OUTQSIZE (0, &outq) < 0) |
| 1302 | /* Probably not a tty. Ignore the error and reset | 4326 | /* Probably not a tty. Ignore the error and reset |
| 1303 | * the outq count. */ | 4327 | * the outq count. */ |
| 1304 | outq = PENDING_OUTPUT_COUNT (stdout); | 4328 | outq = PENDING_OUTPUT_COUNT (stdout); |
| 1305 | #endif | 4329 | #endif |
| 1306 | outq *= 10; | 4330 | outq *= 10; |
| @@ -1313,35 +4337,24 @@ update_frame (f, force, inhibit_hairy_id) | |||
| 1313 | if ((i - 1) % preempt_count == 0) | 4337 | if ((i - 1) % preempt_count == 0) |
| 1314 | detect_input_pending (); | 4338 | detect_input_pending (); |
| 1315 | 4339 | ||
| 1316 | update_line (f, i); | 4340 | update_frame_line (f, i); |
| 1317 | #ifdef HAVE_WINDOW_SYSTEM | ||
| 1318 | if (FRAME_WINDOW_P (f)) | ||
| 1319 | { | ||
| 1320 | current_frame->top_left_y[i] = downto; | ||
| 1321 | current_frame->top_left_x[i] = leftmost; | ||
| 1322 | } | ||
| 1323 | #endif /* HAVE_WINDOW_SYSTEM */ | ||
| 1324 | } | 4341 | } |
| 1325 | |||
| 1326 | #ifdef HAVE_WINDOW_SYSTEM | ||
| 1327 | if (FRAME_WINDOW_P (f)) | ||
| 1328 | downto += current_frame->pix_height[i]; | ||
| 1329 | #endif /* HAVE_WINDOW_SYSTEM */ | ||
| 1330 | } | 4342 | } |
| 4343 | |||
| 1331 | pause = (i < FRAME_HEIGHT (f) - 1) ? i : 0; | 4344 | pause = (i < FRAME_HEIGHT (f) - 1) ? i : 0; |
| 1332 | 4345 | ||
| 1333 | /* Now just clean up termcap drivers and set cursor, etc. */ | 4346 | /* Now just clean up termcap drivers and set cursor, etc. */ |
| 1334 | if (!pause) | 4347 | if (!pause) |
| 1335 | { | 4348 | { |
| 1336 | if ((cursor_in_echo_area | 4349 | if ((cursor_in_echo_area |
| 1337 | /* If we are showing a message instead of the minibuffer, | 4350 | /* If we are showing a message instead of the mini-buffer, |
| 1338 | show the cursor for the message instead of for the | 4351 | show the cursor for the message instead of for the |
| 1339 | (now hidden) minibuffer contents. */ | 4352 | (now hidden) mini-buffer contents. */ |
| 1340 | || (EQ (minibuf_window, selected_window) | 4353 | || (EQ (minibuf_window, selected_window) |
| 1341 | && EQ (minibuf_window, echo_area_window) | 4354 | && EQ (minibuf_window, echo_area_window) |
| 1342 | && echo_area_glyphs != 0)) | 4355 | && (echo_area_glyphs || STRINGP (echo_area_message)))) |
| 1343 | /* These cases apply only to the frame that contains | 4356 | /* These cases apply only to the frame that contains |
| 1344 | the active minibuffer window. */ | 4357 | the active mini-buffer window. */ |
| 1345 | && FRAME_HAS_MINIBUF_P (f) | 4358 | && FRAME_HAS_MINIBUF_P (f) |
| 1346 | && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window)) | 4359 | && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window)) |
| 1347 | { | 4360 | { |
| @@ -1350,21 +4363,39 @@ update_frame (f, force, inhibit_hairy_id) | |||
| 1350 | 4363 | ||
| 1351 | if (cursor_in_echo_area < 0) | 4364 | if (cursor_in_echo_area < 0) |
| 1352 | { | 4365 | { |
| 4366 | /* Negative value of cursor_in_echo_area means put | ||
| 4367 | cursor at beginning of line. */ | ||
| 1353 | row = top; | 4368 | row = top; |
| 1354 | col = 0; | 4369 | col = 0; |
| 1355 | } | 4370 | } |
| 1356 | else | 4371 | else |
| 1357 | { | 4372 | { |
| 1358 | /* If the minibuffer is several lines high, find the last | 4373 | /* Positive value of cursor_in_echo_area means put |
| 1359 | line that has any text on it. */ | 4374 | cursor at the end of the prompt. If the mini-buffer |
| 4375 | is several lines high, find the last line that has | ||
| 4376 | any text on it. */ | ||
| 1360 | row = FRAME_HEIGHT (f); | 4377 | row = FRAME_HEIGHT (f); |
| 1361 | do | 4378 | do |
| 1362 | { | 4379 | { |
| 1363 | row--; | 4380 | --row; |
| 1364 | if (current_frame->enable[row]) | 4381 | col = 0; |
| 1365 | col = current_frame->used[row]; | 4382 | |
| 1366 | else | 4383 | if (MATRIX_ROW_ENABLED_P (current_matrix, row)) |
| 1367 | col = 0; | 4384 | { |
| 4385 | /* Frame rows are filled up with spaces that | ||
| 4386 | must be ignored here. */ | ||
| 4387 | int i; | ||
| 4388 | struct glyph_row *r = MATRIX_ROW (current_matrix, | ||
| 4389 | row); | ||
| 4390 | struct glyph *start = r->glyphs[TEXT_AREA]; | ||
| 4391 | struct glyph *last = start + r->used[TEXT_AREA]; | ||
| 4392 | |||
| 4393 | while (last > start | ||
| 4394 | && (last - 1)->charpos < 0) | ||
| 4395 | --last; | ||
| 4396 | |||
| 4397 | col = last - start; | ||
| 4398 | } | ||
| 1368 | } | 4399 | } |
| 1369 | while (row > top && col == 0); | 4400 | while (row > top && col == 0); |
| 1370 | 4401 | ||
| @@ -1386,9 +4417,22 @@ update_frame (f, force, inhibit_hairy_id) | |||
| 1386 | cursor_to (row, col); | 4417 | cursor_to (row, col); |
| 1387 | } | 4418 | } |
| 1388 | else | 4419 | else |
| 1389 | cursor_to (FRAME_CURSOR_Y (f), | 4420 | { |
| 1390 | minmax (0, FRAME_CURSOR_X (f), | 4421 | /* We have only one cursor on terminal frames. Use it to |
| 1391 | FRAME_CURSOR_X_LIMIT (f) - 1)); | 4422 | display the cursor of the selected window. */ |
| 4423 | struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f)); | ||
| 4424 | if (w->cursor.vpos >= 0) | ||
| 4425 | { | ||
| 4426 | int x = WINDOW_TO_FRAME_HPOS (w, w->cursor.hpos); | ||
| 4427 | int y = WINDOW_TO_FRAME_VPOS (w, w->cursor.vpos); | ||
| 4428 | |||
| 4429 | if (INTEGERP (w->left_margin_width)) | ||
| 4430 | x += XFASTINT (w->left_margin_width); | ||
| 4431 | |||
| 4432 | /* x = max (min (x, FRAME_WINDOW_WIDTH (f) - 1), 0); */ | ||
| 4433 | cursor_to (y, x); | ||
| 4434 | } | ||
| 4435 | } | ||
| 1392 | } | 4436 | } |
| 1393 | 4437 | ||
| 1394 | update_end (f); | 4438 | update_end (f); |
| @@ -1397,39 +4441,19 @@ update_frame (f, force, inhibit_hairy_id) | |||
| 1397 | fflush (termscript); | 4441 | fflush (termscript); |
| 1398 | fflush (stdout); | 4442 | fflush (stdout); |
| 1399 | 4443 | ||
| 1400 | /* Here if output is preempted because input is detected. */ | ||
| 1401 | do_pause: | 4444 | do_pause: |
| 1402 | 4445 | ||
| 1403 | if (FRAME_HEIGHT (f) == 0) abort (); /* Some bug zeros some core */ | ||
| 1404 | display_completed = !pause; | 4446 | display_completed = !pause; |
| 1405 | 4447 | clear_desired_matrices (f); | |
| 1406 | bzero (FRAME_DESIRED_GLYPHS (f)->enable, FRAME_HEIGHT (f)); | ||
| 1407 | return pause; | 4448 | return pause; |
| 1408 | } | 4449 | } |
| 1409 | 4450 | ||
| 1410 | /* Called when about to quit, to check for doing so | ||
| 1411 | at an improper time. */ | ||
| 1412 | |||
| 1413 | void | ||
| 1414 | quit_error_check () | ||
| 1415 | { | ||
| 1416 | #if 0 | ||
| 1417 | if (FRAME_DESIRED_GLYPHS (selected_frame) == 0) | ||
| 1418 | return; | ||
| 1419 | if (FRAME_DESIRED_GLYPHS (selected_frame)->enable[0]) | ||
| 1420 | abort (); | ||
| 1421 | if (FRAME_DESIRED_GLYPHS (selected_frame)->enable[FRAME_HEIGHT (selected_frame) - 1]) | ||
| 1422 | abort (); | ||
| 1423 | #endif | ||
| 1424 | } | ||
| 1425 | |||
| 1426 | /* Decide what insert/delete line to do, and do it */ | ||
| 1427 | 4451 | ||
| 1428 | extern void scrolling_1 (); | 4452 | /* Do line insertions/deletions on frame F for frame-based redisplay. */ |
| 1429 | 4453 | ||
| 1430 | int | 4454 | int |
| 1431 | scrolling (frame) | 4455 | scrolling (frame) |
| 1432 | FRAME_PTR frame; | 4456 | struct frame *frame; |
| 1433 | { | 4457 | { |
| 1434 | int unchanged_at_top, unchanged_at_bottom; | 4458 | int unchanged_at_top, unchanged_at_bottom; |
| 1435 | int window_size; | 4459 | int window_size; |
| @@ -1440,24 +4464,25 @@ scrolling (frame) | |||
| 1440 | int *old_draw_cost = (int *) alloca (FRAME_HEIGHT (frame) * sizeof (int)); | 4464 | int *old_draw_cost = (int *) alloca (FRAME_HEIGHT (frame) * sizeof (int)); |
| 1441 | register int i; | 4465 | register int i; |
| 1442 | int free_at_end_vpos = FRAME_HEIGHT (frame); | 4466 | int free_at_end_vpos = FRAME_HEIGHT (frame); |
| 1443 | register struct frame_glyphs *current_frame = FRAME_CURRENT_GLYPHS (frame); | 4467 | struct glyph_matrix *current_matrix = frame->current_matrix; |
| 1444 | register struct frame_glyphs *desired_frame = FRAME_DESIRED_GLYPHS (frame); | 4468 | struct glyph_matrix *desired_matrix = frame->desired_matrix; |
| 1445 | 4469 | ||
| 1446 | /* Compute hash codes of all the lines. | 4470 | if (!current_matrix) |
| 1447 | Also calculate number of changed lines, | 4471 | abort (); |
| 1448 | number of unchanged lines at the beginning, | ||
| 1449 | and number of unchanged lines at the end. */ | ||
| 1450 | 4472 | ||
| 4473 | /* Compute hash codes of all the lines. Also calculate number of | ||
| 4474 | changed lines, number of unchanged lines at the beginning, and | ||
| 4475 | number of unchanged lines at the end. */ | ||
| 1451 | changed_lines = 0; | 4476 | changed_lines = 0; |
| 1452 | unchanged_at_top = 0; | 4477 | unchanged_at_top = 0; |
| 1453 | unchanged_at_bottom = FRAME_HEIGHT (frame); | 4478 | unchanged_at_bottom = FRAME_HEIGHT (frame); |
| 1454 | for (i = 0; i < FRAME_HEIGHT (frame); i++) | 4479 | for (i = 0; i < FRAME_HEIGHT (frame); i++) |
| 1455 | { | 4480 | { |
| 1456 | /* Give up on this scrolling if some old lines are not enabled. */ | 4481 | /* Give up on this scrolling if some old lines are not enabled. */ |
| 1457 | if (!current_frame->enable[i]) | 4482 | if (!MATRIX_ROW_ENABLED_P (current_matrix, i)) |
| 1458 | return 0; | 4483 | return 0; |
| 1459 | old_hash[i] = line_hash_code (current_frame, i); | 4484 | old_hash[i] = line_hash_code (MATRIX_ROW (current_matrix, i)); |
| 1460 | if (! desired_frame->enable[i]) | 4485 | if (! MATRIX_ROW_ENABLED_P (desired_matrix, i)) |
| 1461 | { | 4486 | { |
| 1462 | /* This line cannot be redrawn, so don't let scrolling mess it. */ | 4487 | /* This line cannot be redrawn, so don't let scrolling mess it. */ |
| 1463 | new_hash[i] = old_hash[i]; | 4488 | new_hash[i] = old_hash[i]; |
| @@ -1466,8 +4491,8 @@ scrolling (frame) | |||
| 1466 | } | 4491 | } |
| 1467 | else | 4492 | else |
| 1468 | { | 4493 | { |
| 1469 | new_hash[i] = line_hash_code (desired_frame, i); | 4494 | new_hash[i] = line_hash_code (MATRIX_ROW (desired_matrix, i)); |
| 1470 | draw_cost[i] = line_draw_cost (desired_frame, i); | 4495 | draw_cost[i] = line_draw_cost (desired_matrix, i); |
| 1471 | } | 4496 | } |
| 1472 | 4497 | ||
| 1473 | if (old_hash[i] != new_hash[i]) | 4498 | if (old_hash[i] != new_hash[i]) |
| @@ -1477,11 +4502,11 @@ scrolling (frame) | |||
| 1477 | } | 4502 | } |
| 1478 | else if (i == unchanged_at_top) | 4503 | else if (i == unchanged_at_top) |
| 1479 | unchanged_at_top++; | 4504 | unchanged_at_top++; |
| 1480 | old_draw_cost[i] = line_draw_cost (current_frame, i); | 4505 | old_draw_cost[i] = line_draw_cost (current_matrix, i); |
| 1481 | } | 4506 | } |
| 1482 | 4507 | ||
| 1483 | /* If changed lines are few, don't allow preemption, don't scroll. */ | 4508 | /* If changed lines are few, don't allow preemption, don't scroll. */ |
| 1484 | if (!scroll_region_ok && changed_lines < baud_rate / 2400 | 4509 | if ((!scroll_region_ok && changed_lines < baud_rate / 2400) |
| 1485 | || unchanged_at_bottom == FRAME_HEIGHT (frame)) | 4510 | || unchanged_at_bottom == FRAME_HEIGHT (frame)) |
| 1486 | return 1; | 4511 | return 1; |
| 1487 | 4512 | ||
| @@ -1494,7 +4519,7 @@ scrolling (frame) | |||
| 1494 | free_at_end_vpos = -1; | 4519 | free_at_end_vpos = -1; |
| 1495 | 4520 | ||
| 1496 | /* If large window, fast terminal and few lines in common between | 4521 | /* If large window, fast terminal and few lines in common between |
| 1497 | current frame and desired frame, don't bother with i/d calc. */ | 4522 | current frame and desired frame, don't bother with i/d calc. */ |
| 1498 | if (!scroll_region_ok && window_size >= 18 && baud_rate > 2400 | 4523 | if (!scroll_region_ok && window_size >= 18 && baud_rate > 2400 |
| 1499 | && (window_size >= | 4524 | && (window_size >= |
| 1500 | 10 * scrolling_max_lines_saved (unchanged_at_top, | 4525 | 10 * scrolling_max_lines_saved (unchanged_at_top, |
| @@ -1502,6 +4527,9 @@ scrolling (frame) | |||
| 1502 | old_hash, new_hash, draw_cost))) | 4527 | old_hash, new_hash, draw_cost))) |
| 1503 | return 0; | 4528 | return 0; |
| 1504 | 4529 | ||
| 4530 | if (window_size < 2) | ||
| 4531 | return 0; | ||
| 4532 | |||
| 1505 | scrolling_1 (frame, window_size, unchanged_at_top, unchanged_at_bottom, | 4533 | scrolling_1 (frame, window_size, unchanged_at_top, unchanged_at_bottom, |
| 1506 | draw_cost + unchanged_at_top - 1, | 4534 | draw_cost + unchanged_at_top - 1, |
| 1507 | old_draw_cost + unchanged_at_top - 1, | 4535 | old_draw_cost + unchanged_at_top - 1, |
| @@ -1511,218 +4539,174 @@ scrolling (frame) | |||
| 1511 | 4539 | ||
| 1512 | return 0; | 4540 | return 0; |
| 1513 | } | 4541 | } |
| 1514 | |||
| 1515 | /* Return the offset in its buffer of the character at location col, line | ||
| 1516 | in the given window. */ | ||
| 1517 | int | ||
| 1518 | buffer_posn_from_coords (window, col, line) | ||
| 1519 | struct window *window; | ||
| 1520 | int col, line; | ||
| 1521 | { | ||
| 1522 | int hscroll = XINT (window->hscroll); | ||
| 1523 | int window_left = WINDOW_LEFT_MARGIN (window); | ||
| 1524 | 4542 | ||
| 1525 | /* The actual width of the window is window->width less one for the | ||
| 1526 | DISP_CONTINUE_GLYPH, and less one if it's not the rightmost | ||
| 1527 | window. */ | ||
| 1528 | int window_width = window_internal_width (window) - 1; | ||
| 1529 | 4543 | ||
| 1530 | int startp = marker_position (window->start); | 4544 | /* Count the number of blanks at the start of the vector of glyphs R |
| 4545 | which is LEN glyphs long. */ | ||
| 1531 | 4546 | ||
| 1532 | /* Since compute_motion will only operate on the current buffer, | ||
| 1533 | we need to save the old one and restore it when we're done. */ | ||
| 1534 | struct buffer *old_current_buffer = current_buffer; | ||
| 1535 | struct position *posn; | ||
| 1536 | |||
| 1537 | current_buffer = XBUFFER (window->buffer); | ||
| 1538 | |||
| 1539 | /* We can't get a correct result in this case, | ||
| 1540 | but at least prevent compute_motion from crashing. */ | ||
| 1541 | if (startp < BEGV) | ||
| 1542 | startp = BEGV; | ||
| 1543 | |||
| 1544 | /* It would be nice if we could use FRAME_CURRENT_GLYPHS (XFRAME | ||
| 1545 | (window->frame))->bufp to avoid scanning from the very top of | ||
| 1546 | the window, but it isn't maintained correctly, and I'm not even | ||
| 1547 | sure I will keep it. */ | ||
| 1548 | posn = compute_motion (startp, 0, | ||
| 1549 | ((window == XWINDOW (minibuf_window) && startp == BEG | ||
| 1550 | ? minibuf_prompt_width : 0) | ||
| 1551 | + (hscroll ? 1 - hscroll : 0)), | ||
| 1552 | 0, | ||
| 1553 | ZV, line, col, | ||
| 1554 | window_width, hscroll, 0, window); | ||
| 1555 | |||
| 1556 | current_buffer = old_current_buffer; | ||
| 1557 | |||
| 1558 | /* compute_motion considers frame points past the end of a line | ||
| 1559 | to be *after* the newline, i.e. at the start of the next line. | ||
| 1560 | This is reasonable, but not really what we want. So if the | ||
| 1561 | result is on a line below LINE, back it up one character. */ | ||
| 1562 | if (posn->vpos > line) | ||
| 1563 | return posn->bufpos - 1; | ||
| 1564 | else | ||
| 1565 | return posn->bufpos; | ||
| 1566 | } | ||
| 1567 | |||
| 1568 | static int | 4547 | static int |
| 1569 | count_blanks (r) | 4548 | count_blanks (r, len) |
| 1570 | register GLYPH *r; | 4549 | struct glyph *r; |
| 4550 | int len; | ||
| 1571 | { | 4551 | { |
| 1572 | register GLYPH *p = r; | 4552 | int i; |
| 1573 | while (*p++ == SPACEGLYPH); | 4553 | |
| 1574 | return p - r - 1; | 4554 | for (i = 0; i < len; ++i) |
| 4555 | if (!CHAR_GLYPH_SPACE_P (r[i])) | ||
| 4556 | break; | ||
| 4557 | |||
| 4558 | return i; | ||
| 1575 | } | 4559 | } |
| 1576 | 4560 | ||
| 4561 | |||
| 4562 | /* Count the number of glyphs in common at the start of the glyph | ||
| 4563 | vectors STR1 and STR2. END1 is the end of STR1 and END2 is the end | ||
| 4564 | of STR2. Value is the number of equal glyphs equal at the start. */ | ||
| 4565 | |||
| 1577 | static int | 4566 | static int |
| 1578 | count_match (str1, str2) | 4567 | count_match (str1, end1, str2, end2) |
| 1579 | GLYPH *str1, *str2; | 4568 | struct glyph *str1, *end1, *str2, *end2; |
| 1580 | { | 4569 | { |
| 1581 | register GLYPH *p1 = str1; | 4570 | struct glyph *p1 = str1; |
| 1582 | register GLYPH *p2 = str2; | 4571 | struct glyph *p2 = str2; |
| 1583 | while (*p1++ == *p2++); | 4572 | |
| 1584 | return p1 - str1 - 1; | 4573 | while (p1 < end1 |
| 4574 | && p2 < end2 | ||
| 4575 | && GLYPH_FROM_CHAR_GLYPH (*p1) == GLYPH_FROM_CHAR_GLYPH (*p2)) | ||
| 4576 | ++p1, ++p2; | ||
| 4577 | |||
| 4578 | return p1 - str1; | ||
| 1585 | } | 4579 | } |
| 1586 | 4580 | ||
| 4581 | |||
| 1587 | /* Char insertion/deletion cost vector, from term.c */ | 4582 | /* Char insertion/deletion cost vector, from term.c */ |
| 1588 | extern int *char_ins_del_vector; | ||
| 1589 | 4583 | ||
| 4584 | extern int *char_ins_del_vector; | ||
| 1590 | #define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_WINDOW_WIDTH((f))]) | 4585 | #define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_WINDOW_WIDTH((f))]) |
| 1591 | 4586 | ||
| 4587 | |||
| 4588 | /* Perform a frame-based update on line VPOS in frame FRAME. */ | ||
| 4589 | |||
| 1592 | static void | 4590 | static void |
| 1593 | update_line (frame, vpos) | 4591 | update_frame_line (frame, vpos) |
| 1594 | register FRAME_PTR frame; | 4592 | register struct frame *frame; |
| 1595 | int vpos; | 4593 | int vpos; |
| 1596 | { | 4594 | { |
| 1597 | register GLYPH *obody, *nbody, *op1, *op2, *np1, *temp; | 4595 | struct glyph *obody, *nbody, *op1, *op2, *np1, *nend; |
| 1598 | int *temp1; | ||
| 1599 | int tem; | 4596 | int tem; |
| 1600 | int osp, nsp, begmatch, endmatch, olen, nlen; | 4597 | int osp, nsp, begmatch, endmatch, olen, nlen; |
| 1601 | GLYPH save; | 4598 | struct glyph_matrix *current_matrix = frame->current_matrix; |
| 1602 | register struct frame_glyphs *current_frame | 4599 | struct glyph_matrix *desired_matrix = frame->desired_matrix; |
| 1603 | = FRAME_CURRENT_GLYPHS (frame); | 4600 | struct glyph_row *current_row = MATRIX_ROW (current_matrix, vpos); |
| 1604 | register struct frame_glyphs *desired_frame | 4601 | struct glyph_row *desired_row = MATRIX_ROW (desired_matrix, vpos); |
| 1605 | = FRAME_DESIRED_GLYPHS (frame); | 4602 | int must_write_whole_line_p; |
| 1606 | 4603 | ||
| 1607 | if (desired_frame->highlight[vpos] | 4604 | if (desired_row->inverse_p |
| 1608 | != (current_frame->enable[vpos] && current_frame->highlight[vpos])) | 4605 | != (current_row->enabled_p && current_row->inverse_p)) |
| 1609 | { | 4606 | { |
| 1610 | change_line_highlight (desired_frame->highlight[vpos], vpos, | 4607 | int n = current_row->enabled_p ? current_row->used[TEXT_AREA] : 0; |
| 1611 | (current_frame->enable[vpos] ? | 4608 | change_line_highlight (desired_row->inverse_p, vpos, vpos, n); |
| 1612 | current_frame->used[vpos] : 0)); | 4609 | current_row->enabled_p = 0; |
| 1613 | current_frame->enable[vpos] = 0; | ||
| 1614 | } | 4610 | } |
| 1615 | else | 4611 | else |
| 1616 | reassert_line_highlight (desired_frame->highlight[vpos], vpos); | 4612 | reassert_line_highlight (desired_row->inverse_p, vpos); |
| 1617 | 4613 | ||
| 1618 | if (! current_frame->enable[vpos]) | 4614 | must_write_whole_line_p = !current_row->enabled_p; |
| 4615 | if (must_write_whole_line_p) | ||
| 1619 | { | 4616 | { |
| 4617 | /* A line that is not enabled is empty. */ | ||
| 4618 | obody = 0; | ||
| 1620 | olen = 0; | 4619 | olen = 0; |
| 1621 | } | 4620 | } |
| 1622 | else | 4621 | else |
| 1623 | { | 4622 | { |
| 1624 | obody = current_frame->glyphs[vpos]; | 4623 | /* A line not empty in the current matrix. */ |
| 1625 | olen = current_frame->used[vpos]; | 4624 | obody = MATRIX_ROW_GLYPH_START (current_matrix, vpos); |
| 1626 | if (! current_frame->highlight[vpos]) | 4625 | olen = current_row->used[TEXT_AREA]; |
| 4626 | |||
| 4627 | if (! current_row->inverse_p) | ||
| 1627 | { | 4628 | { |
| 4629 | /* Ignore trailing spaces. */ | ||
| 1628 | if (!must_write_spaces) | 4630 | if (!must_write_spaces) |
| 1629 | while (olen > 0 && obody[olen - 1] == SPACEGLYPH) | 4631 | while (olen > 0 && CHAR_GLYPH_SPACE_P (obody[olen-1])) |
| 1630 | olen--; | 4632 | olen--; |
| 1631 | } | 4633 | } |
| 1632 | else | 4634 | else |
| 1633 | { | 4635 | { |
| 1634 | /* For an inverse-video line, remember we gave it | 4636 | /* For an inverse-video line, remember we gave it spaces all |
| 1635 | spaces all the way to the frame edge | 4637 | the way to the frame edge so that the reverse video |
| 1636 | so that the reverse video extends all the way across. */ | 4638 | extends all the way across. */ |
| 1637 | 4639 | while (olen < FRAME_WIDTH (frame) - 1) | |
| 1638 | while (olen < FRAME_WINDOW_WIDTH (frame) - 1) | 4640 | obody[olen++] = space_glyph; |
| 1639 | obody[olen++] = SPACEGLYPH; | ||
| 1640 | } | 4641 | } |
| 1641 | } | 4642 | } |
| 1642 | 4643 | ||
| 1643 | /* One way or another, this will enable the line being updated. */ | 4644 | current_row->enabled_p = 1; |
| 1644 | current_frame->enable[vpos] = 1; | 4645 | current_row->used[TEXT_AREA] = desired_row->used[TEXT_AREA]; |
| 1645 | current_frame->used[vpos] = desired_frame->used[vpos]; | 4646 | current_row->inverse_p = desired_row->inverse_p; |
| 1646 | current_frame->highlight[vpos] = desired_frame->highlight[vpos]; | ||
| 1647 | current_frame->bufp[vpos] = desired_frame->bufp[vpos]; | ||
| 1648 | 4647 | ||
| 1649 | #ifdef HAVE_WINDOW_SYSTEM | 4648 | /* If desired line is empty, just clear the line. */ |
| 1650 | if (FRAME_WINDOW_P (frame)) | 4649 | if (!desired_row->enabled_p) |
| 1651 | { | ||
| 1652 | current_frame->pix_width[vpos] | ||
| 1653 | = current_frame->used[vpos] | ||
| 1654 | * FONT_WIDTH (FRAME_FONT (frame)); | ||
| 1655 | current_frame->pix_height[vpos] | ||
| 1656 | = FRAME_LINE_HEIGHT (frame); | ||
| 1657 | } | ||
| 1658 | #endif /* HAVE_WINDOW_SYSTEM */ | ||
| 1659 | |||
| 1660 | if (!desired_frame->enable[vpos]) | ||
| 1661 | { | 4650 | { |
| 1662 | nlen = 0; | 4651 | nlen = 0; |
| 1663 | goto just_erase; | 4652 | goto just_erase; |
| 1664 | } | 4653 | } |
| 1665 | 4654 | ||
| 1666 | nbody = desired_frame->glyphs[vpos]; | 4655 | nbody = desired_row->glyphs[TEXT_AREA]; |
| 1667 | nlen = desired_frame->used[vpos]; | 4656 | nlen = desired_row->used[TEXT_AREA]; |
| 4657 | nend = nbody + nlen; | ||
| 4658 | |||
| 4659 | /* If display line has unknown contents, write the whole line. */ | ||
| 4660 | if (must_write_whole_line_p) | ||
| 4661 | { | ||
| 4662 | cursor_to (vpos, 0); | ||
| 4663 | write_glyphs (nbody, nlen); | ||
| 4664 | cursor_to (vpos, nlen); | ||
| 4665 | clear_end_of_line (-1); | ||
| 4666 | make_current (desired_matrix, current_matrix, vpos); | ||
| 4667 | return; | ||
| 4668 | } | ||
| 1668 | 4669 | ||
| 1669 | /* Pretend trailing spaces are not there at all, | 4670 | /* Pretend trailing spaces are not there at all, |
| 1670 | unless for one reason or another we must write all spaces. */ | 4671 | unless for one reason or another we must write all spaces. */ |
| 1671 | if (! desired_frame->highlight[vpos]) | 4672 | if (!desired_row->inverse_p) |
| 1672 | { | 4673 | { |
| 1673 | if (!must_write_spaces) | 4674 | if (!must_write_spaces) |
| 1674 | /* We know that the previous character byte contains 0. */ | 4675 | while (nlen > 0 && CHAR_GLYPH_SPACE_P (nbody[nlen - 1])) |
| 1675 | while (nbody[nlen - 1] == SPACEGLYPH) | ||
| 1676 | nlen--; | 4676 | nlen--; |
| 1677 | } | 4677 | } |
| 1678 | else | 4678 | else |
| 1679 | { | 4679 | { |
| 1680 | /* For an inverse-video line, give it extra trailing spaces | 4680 | /* For an inverse-video line, give it extra trailing spaces all |
| 1681 | all the way to the frame edge | 4681 | the way to the frame edge so that the reverse video extends |
| 1682 | so that the reverse video extends all the way across. */ | 4682 | all the way across. */ |
| 1683 | 4683 | while (nlen < FRAME_WIDTH (frame) - 1) | |
| 1684 | while (nlen < FRAME_WINDOW_WIDTH (frame) - 1) | 4684 | nbody[nlen++] = space_glyph; |
| 1685 | nbody[nlen++] = SPACEGLYPH; | ||
| 1686 | } | 4685 | } |
| 1687 | 4686 | ||
| 1688 | /* If there's no i/d char, quickly do the best we can without it. */ | 4687 | /* If there's no i/d char, quickly do the best we can without it. */ |
| 1689 | if (!char_ins_del_ok) | 4688 | if (!char_ins_del_ok) |
| 1690 | { | 4689 | { |
| 1691 | int i,j; | 4690 | int i, j; |
| 1692 | 4691 | ||
| 1693 | #if 0 | 4692 | /* Find the first glyph in desired row that doesn't agree with |
| 1694 | if (FRAME_X_P (frame)) | 4693 | a glyph in the current row, and write the rest from there on. */ |
| 1695 | { | ||
| 1696 | /* Under X, erase everything we are going to rewrite, | ||
| 1697 | and rewrite everything from the first char that's changed. | ||
| 1698 | This is part of supporting fonts like Courier | ||
| 1699 | whose chars can overlap outside the char width. */ | ||
| 1700 | for (i = 0; i < nlen; i++) | ||
| 1701 | if (i >= olen || nbody[i] != obody[i]) | ||
| 1702 | break; | ||
| 1703 | |||
| 1704 | cursor_to (vpos, i); | ||
| 1705 | if (i != olen) | ||
| 1706 | clear_end_of_line (olen); | ||
| 1707 | write_glyphs (nbody + i, nlen - i); | ||
| 1708 | } | ||
| 1709 | else | ||
| 1710 | {} | ||
| 1711 | #endif /* 0 */ | ||
| 1712 | for (i = 0; i < nlen; i++) | 4694 | for (i = 0; i < nlen; i++) |
| 1713 | { | 4695 | { |
| 1714 | if (i >= olen || nbody[i] != obody[i]) /* A non-matching char. */ | 4696 | if (i >= olen || !GLYPH_EQUAL_P (nbody + i, obody + i)) |
| 1715 | { | 4697 | { |
| 1716 | cursor_to (vpos, i); | 4698 | /* Find the end of the run of different glyphs. */ |
| 1717 | for (j = 1; | 4699 | j = i + 1; |
| 1718 | (i + j < nlen | 4700 | while (j < nlen |
| 1719 | && (i + j >= olen || nbody[i + j] != obody[i + j] | 4701 | && (j >= olen |
| 1720 | || (nbody[i + j] & GLYPH_MASK_PADDING))); | 4702 | || !GLYPH_EQUAL_P (nbody + j, obody + j) |
| 1721 | j++); | 4703 | || CHAR_GLYPH_PADDING_P (nbody[j]))) |
| 1722 | 4704 | ++j; | |
| 4705 | |||
| 1723 | /* Output this run of non-matching chars. */ | 4706 | /* Output this run of non-matching chars. */ |
| 1724 | write_glyphs (nbody + i, j); | 4707 | cursor_to (vpos, i); |
| 1725 | i += j - 1; | 4708 | write_glyphs (nbody + i, j - i); |
| 4709 | i = j - 1; | ||
| 1726 | 4710 | ||
| 1727 | /* Now find the next non-match. */ | 4711 | /* Now find the next non-match. */ |
| 1728 | } | 4712 | } |
| @@ -1735,23 +4719,23 @@ update_line (frame, vpos) | |||
| 1735 | clear_end_of_line (olen); | 4719 | clear_end_of_line (olen); |
| 1736 | } | 4720 | } |
| 1737 | 4721 | ||
| 1738 | /* Exchange contents between current_frame and new_frame. */ | 4722 | /* Make current row = desired row. */ |
| 1739 | temp = desired_frame->glyphs[vpos]; | 4723 | make_current (desired_matrix, current_matrix, vpos); |
| 1740 | desired_frame->glyphs[vpos] = current_frame->glyphs[vpos]; | ||
| 1741 | current_frame->glyphs[vpos] = temp; | ||
| 1742 | |||
| 1743 | /* Exchange charstarts between current_frame and new_frame. */ | ||
| 1744 | temp1 = desired_frame->charstarts[vpos]; | ||
| 1745 | desired_frame->charstarts[vpos] = current_frame->charstarts[vpos]; | ||
| 1746 | current_frame->charstarts[vpos] = temp1; | ||
| 1747 | |||
| 1748 | return; | 4724 | return; |
| 1749 | } | 4725 | } |
| 1750 | 4726 | ||
| 4727 | /* Here when CHAR_INS_DEL_OK != 0, i.e. we can insert or delete | ||
| 4728 | characters in a row. */ | ||
| 4729 | |||
| 1751 | if (!olen) | 4730 | if (!olen) |
| 1752 | { | 4731 | { |
| 1753 | nsp = (must_write_spaces || desired_frame->highlight[vpos]) | 4732 | /* If current line is blank, skip over initial spaces, if |
| 1754 | ? 0 : count_blanks (nbody); | 4733 | possible, and write the rest. */ |
| 4734 | if (must_write_spaces || desired_row->inverse_p) | ||
| 4735 | nsp = 0; | ||
| 4736 | else | ||
| 4737 | nsp = count_blanks (nbody, nlen); | ||
| 4738 | |||
| 1755 | if (nlen > nsp) | 4739 | if (nlen > nsp) |
| 1756 | { | 4740 | { |
| 1757 | cursor_to (vpos, nsp); | 4741 | cursor_to (vpos, nsp); |
| @@ -1759,44 +4743,30 @@ update_line (frame, vpos) | |||
| 1759 | } | 4743 | } |
| 1760 | 4744 | ||
| 1761 | /* Exchange contents between current_frame and new_frame. */ | 4745 | /* Exchange contents between current_frame and new_frame. */ |
| 1762 | temp = desired_frame->glyphs[vpos]; | 4746 | make_current (desired_matrix, current_matrix, vpos); |
| 1763 | desired_frame->glyphs[vpos] = current_frame->glyphs[vpos]; | ||
| 1764 | current_frame->glyphs[vpos] = temp; | ||
| 1765 | |||
| 1766 | /* Exchange charstarts between current_frame and new_frame. */ | ||
| 1767 | temp1 = desired_frame->charstarts[vpos]; | ||
| 1768 | desired_frame->charstarts[vpos] = current_frame->charstarts[vpos]; | ||
| 1769 | current_frame->charstarts[vpos] = temp1; | ||
| 1770 | |||
| 1771 | return; | 4747 | return; |
| 1772 | } | 4748 | } |
| 1773 | 4749 | ||
| 1774 | obody[olen] = 1; | ||
| 1775 | save = nbody[nlen]; | ||
| 1776 | nbody[nlen] = 0; | ||
| 1777 | |||
| 1778 | /* Compute number of leading blanks in old and new contents. */ | 4750 | /* Compute number of leading blanks in old and new contents. */ |
| 1779 | osp = count_blanks (obody); | 4751 | osp = count_blanks (obody, olen); |
| 1780 | if (!desired_frame->highlight[vpos]) | 4752 | nsp = desired_row->inverse_p ? 0 : count_blanks (nbody, nlen); |
| 1781 | nsp = count_blanks (nbody); | ||
| 1782 | else | ||
| 1783 | nsp = 0; | ||
| 1784 | 4753 | ||
| 1785 | /* Compute number of matching chars starting with first nonblank. */ | 4754 | /* Compute number of matching chars starting with first non-blank. */ |
| 1786 | begmatch = count_match (obody + osp, nbody + nsp); | 4755 | begmatch = count_match (obody + osp, obody + olen, |
| 4756 | nbody + nsp, nbody + nlen); | ||
| 1787 | 4757 | ||
| 1788 | /* Spaces in new match implicit space past the end of old. */ | 4758 | /* Spaces in new match implicit space past the end of old. */ |
| 1789 | /* A bug causing this to be a no-op was fixed in 18.29. */ | 4759 | /* A bug causing this to be a no-op was fixed in 18.29. */ |
| 1790 | if (!must_write_spaces && osp + begmatch == olen) | 4760 | if (!must_write_spaces && osp + begmatch == olen) |
| 1791 | { | 4761 | { |
| 1792 | np1 = nbody + nsp; | 4762 | np1 = nbody + nsp; |
| 1793 | while (np1[begmatch] == SPACEGLYPH) | 4763 | while (np1 + begmatch < nend && CHAR_GLYPH_SPACE_P (np1[begmatch])) |
| 1794 | begmatch++; | 4764 | ++begmatch; |
| 1795 | } | 4765 | } |
| 1796 | 4766 | ||
| 1797 | /* Avoid doing insert/delete char | 4767 | /* Avoid doing insert/delete char |
| 1798 | just cause number of leading spaces differs | 4768 | just cause number of leading spaces differs |
| 1799 | when the following text does not match. */ | 4769 | when the following text does not match. */ |
| 1800 | if (begmatch == 0 && osp != nsp) | 4770 | if (begmatch == 0 && osp != nsp) |
| 1801 | osp = nsp = min (osp, nsp); | 4771 | osp = nsp = min (osp, nsp); |
| 1802 | 4772 | ||
| @@ -1804,20 +4774,14 @@ update_line (frame, vpos) | |||
| 1804 | op1 = obody + olen; | 4774 | op1 = obody + olen; |
| 1805 | np1 = nbody + nlen; | 4775 | np1 = nbody + nlen; |
| 1806 | op2 = op1 + begmatch - min (olen - osp, nlen - nsp); | 4776 | op2 = op1 + begmatch - min (olen - osp, nlen - nsp); |
| 1807 | while (op1 > op2 && op1[-1] == np1[-1]) | 4777 | while (op1 > op2 |
| 4778 | && GLYPH_EQUAL_P (op1 - 1, np1 - 1)) | ||
| 1808 | { | 4779 | { |
| 1809 | op1--; | 4780 | op1--; |
| 1810 | np1--; | 4781 | np1--; |
| 1811 | } | 4782 | } |
| 1812 | endmatch = obody + olen - op1; | 4783 | endmatch = obody + olen - op1; |
| 1813 | 4784 | ||
| 1814 | /* Put correct value back in nbody[nlen]. | ||
| 1815 | This is important because direct_output_for_insert | ||
| 1816 | can write into the line at a later point. | ||
| 1817 | If this screws up the zero at the end of the line, re-establish it. */ | ||
| 1818 | nbody[nlen] = save; | ||
| 1819 | obody[olen] = 0; | ||
| 1820 | |||
| 1821 | /* tem gets the distance to insert or delete. | 4785 | /* tem gets the distance to insert or delete. |
| 1822 | endmatch is how many characters we save by doing so. | 4786 | endmatch is how many characters we save by doing so. |
| 1823 | Is it worth it? */ | 4787 | Is it worth it? */ |
| @@ -1861,7 +4825,7 @@ update_line (frame, vpos) | |||
| 1861 | olen = nlen - (nsp - osp); | 4825 | olen = nlen - (nsp - osp); |
| 1862 | } | 4826 | } |
| 1863 | cursor_to (vpos, osp); | 4827 | cursor_to (vpos, osp); |
| 1864 | insert_glyphs ((GLYPH *) 0, nsp - osp); | 4828 | insert_glyphs (0, nsp - osp); |
| 1865 | } | 4829 | } |
| 1866 | olen += nsp - osp; | 4830 | olen += nsp - osp; |
| 1867 | 4831 | ||
| @@ -1878,29 +4842,6 @@ update_line (frame, vpos) | |||
| 1878 | if (nlen == FRAME_WINDOW_WIDTH (frame)) | 4842 | if (nlen == FRAME_WINDOW_WIDTH (frame)) |
| 1879 | olen = 0; | 4843 | olen = 0; |
| 1880 | write_glyphs (nbody + nsp + begmatch, nlen - tem); | 4844 | write_glyphs (nbody + nsp + begmatch, nlen - tem); |
| 1881 | |||
| 1882 | #ifdef obsolete | ||
| 1883 | |||
| 1884 | /* the following code loses disastrously if tem == nlen. | ||
| 1885 | Rather than trying to fix that case, I am trying the simpler | ||
| 1886 | solution found above. */ | ||
| 1887 | |||
| 1888 | /* If the text reaches to the right margin, | ||
| 1889 | it will lose one way or another (depending on AutoWrap) | ||
| 1890 | to clear to end of line after outputting all the text. | ||
| 1891 | So pause with one character to go and clear the line then. */ | ||
| 1892 | if (nlen == FRAME_WINDOW_WIDTH (frame) && fast_clear_end_of_line && olen > nlen) | ||
| 1893 | { | ||
| 1894 | /* endmatch must be zero, and tem must equal nsp + begmatch */ | ||
| 1895 | write_glyphs (nbody + tem, nlen - tem - 1); | ||
| 1896 | clear_end_of_line (olen); | ||
| 1897 | olen = 0; /* Don't let it be cleared again later */ | ||
| 1898 | write_glyphs (nbody + nlen - 1, 1); | ||
| 1899 | } | ||
| 1900 | else | ||
| 1901 | write_glyphs (nbody + nsp + begmatch, nlen - tem); | ||
| 1902 | #endif /* OBSOLETE */ | ||
| 1903 | |||
| 1904 | } | 4845 | } |
| 1905 | else if (nlen > olen) | 4846 | else if (nlen > olen) |
| 1906 | { | 4847 | { |
| @@ -1915,9 +4856,9 @@ update_line (frame, vpos) | |||
| 1915 | int del; | 4856 | int del; |
| 1916 | 4857 | ||
| 1917 | /* Calculate columns we can actually overwrite. */ | 4858 | /* Calculate columns we can actually overwrite. */ |
| 1918 | while (nbody[nsp + begmatch + out] & GLYPH_MASK_PADDING) out--; | 4859 | while (CHAR_GLYPH_PADDING_P (nbody[nsp + begmatch + out])) out--; |
| 1919 | write_glyphs (nbody + nsp + begmatch, out); | 4860 | write_glyphs (nbody + nsp + begmatch, out); |
| 1920 | /* If we left columns to be overwritten. we must delete them. */ | 4861 | /* If we left columns to be overwritten, we must delete them. */ |
| 1921 | del = olen - tem - out; | 4862 | del = olen - tem - out; |
| 1922 | if (del > 0) delete_glyphs (del); | 4863 | if (del > 0) delete_glyphs (del); |
| 1923 | /* At last, we insert columns not yet written out. */ | 4864 | /* At last, we insert columns not yet written out. */ |
| @@ -1941,130 +4882,107 @@ update_line (frame, vpos) | |||
| 1941 | } | 4882 | } |
| 1942 | 4883 | ||
| 1943 | /* Exchange contents between current_frame and new_frame. */ | 4884 | /* Exchange contents between current_frame and new_frame. */ |
| 1944 | temp = desired_frame->glyphs[vpos]; | 4885 | make_current (desired_matrix, current_matrix, vpos); |
| 1945 | desired_frame->glyphs[vpos] = current_frame->glyphs[vpos]; | ||
| 1946 | current_frame->glyphs[vpos] = temp; | ||
| 1947 | |||
| 1948 | /* Exchange charstarts between current_frame and new_frame. */ | ||
| 1949 | temp1 = desired_frame->charstarts[vpos]; | ||
| 1950 | desired_frame->charstarts[vpos] = current_frame->charstarts[vpos]; | ||
| 1951 | current_frame->charstarts[vpos] = temp1; | ||
| 1952 | } | 4886 | } |
| 4887 | |||
| 4888 | |||
| 1953 | 4889 | ||
| 1954 | /* A vector of size >= 2 * NFRAMES + 3 * NBUFFERS + 1, containing the | 4890 | /*********************************************************************** |
| 1955 | session's frames, frame names, buffers, buffer-read-only flags, and | 4891 | X/Y Position -> Buffer Position |
| 1956 | buffer-modified-flags, and a trailing sentinel (so we don't need to | 4892 | ***********************************************************************/ |
| 1957 | add length checks). */ | ||
| 1958 | static Lisp_Object frame_and_buffer_state; | ||
| 1959 | 4893 | ||
| 1960 | DEFUN ("frame-or-buffer-changed-p", Fframe_or_buffer_changed_p, | 4894 | /* Return the character position of the character at window relative |
| 1961 | Sframe_or_buffer_changed_p, 0, 0, 0, | 4895 | pixel position (*X, *Y). *X and *Y are adjusted to character |
| 1962 | "Return non-nil if the frame and buffer state appears to have changed.\n\ | 4896 | boundaries. */ |
| 1963 | The state variable is an internal vector containing all frames and buffers,\n\ | ||
| 1964 | aside from buffers whose names start with space,\n\ | ||
| 1965 | along with the buffers' read-only and modified flags, which allows a fast\n\ | ||
| 1966 | check to see whether the menu bars might need to be recomputed.\n\ | ||
| 1967 | If this function returns non-nil, it updates the internal vector to reflect\n\ | ||
| 1968 | the current state.\n") | ||
| 1969 | () | ||
| 1970 | { | ||
| 1971 | Lisp_Object tail, frame, buf; | ||
| 1972 | Lisp_Object *vecp; | ||
| 1973 | int n; | ||
| 1974 | 4897 | ||
| 1975 | vecp = XVECTOR (frame_and_buffer_state)->contents; | 4898 | int |
| 1976 | FOR_EACH_FRAME (tail, frame) | 4899 | buffer_posn_from_coords (w, x, y) |
| 1977 | { | 4900 | struct window *w; |
| 1978 | if (!EQ (*vecp++, frame)) | 4901 | int *x, *y; |
| 1979 | goto changed; | 4902 | { |
| 1980 | if (!EQ (*vecp++, XFRAME (frame)->name)) | 4903 | struct it it; |
| 1981 | goto changed; | 4904 | struct buffer *old_current_buffer = current_buffer; |
| 1982 | } | 4905 | struct text_pos startp; |
| 1983 | /* Check that the buffer info matches. | 4906 | int left_area_width; |
| 1984 | No need to test for the end of the vector | 4907 | |
| 1985 | because the last element of the vector is lambda | 4908 | current_buffer = XBUFFER (w->buffer); |
| 1986 | and that will always cause a mismatch. */ | 4909 | SET_TEXT_POS_FROM_MARKER (startp, w->start); |
| 1987 | for (tail = Vbuffer_alist; CONSP (tail); tail = XCONS (tail)->cdr) | 4910 | CHARPOS (startp) = min (ZV, max (BEGV, CHARPOS (startp))); |
| 1988 | { | 4911 | BYTEPOS (startp) = min (ZV_BYTE, max (BEGV_BYTE, BYTEPOS (startp))); |
| 1989 | buf = XCONS (XCONS (tail)->car)->cdr; | 4912 | start_display (&it, w, startp); |
| 1990 | /* Ignore buffers that aren't included in buffer lists. */ | 4913 | |
| 1991 | if (XSTRING (XBUFFER (buf)->name)->data[0] == ' ') | 4914 | left_area_width = WINDOW_DISPLAY_LEFT_AREA_PIXEL_WIDTH (w); |
| 1992 | continue; | 4915 | move_it_to (&it, -1, *x + it.first_visible_x - left_area_width, *y, -1, |
| 1993 | if (!EQ (*vecp++, buf)) | 4916 | MOVE_TO_X | MOVE_TO_Y); |
| 1994 | goto changed; | 4917 | |
| 1995 | if (!EQ (*vecp++, XBUFFER (buf)->read_only)) | 4918 | *x = it.current_x - it.first_visible_x + left_area_width; |
| 1996 | goto changed; | 4919 | *y = it.current_y; |
| 1997 | if (!EQ (*vecp++, Fbuffer_modified_p (buf))) | 4920 | current_buffer = old_current_buffer; |
| 1998 | goto changed; | 4921 | return IT_CHARPOS (it); |
| 1999 | } | ||
| 2000 | /* Detect deletion of a buffer at the end of the list. */ | ||
| 2001 | if (EQ (*vecp, Qlambda)) | ||
| 2002 | return Qnil; | ||
| 2003 | changed: | ||
| 2004 | /* Start with 1 so there is room for at least one lambda at the end. */ | ||
| 2005 | n = 1; | ||
| 2006 | FOR_EACH_FRAME (tail, frame) | ||
| 2007 | n += 2; | ||
| 2008 | for (tail = Vbuffer_alist; CONSP (tail); tail = XCONS (tail)->cdr) | ||
| 2009 | n += 3; | ||
| 2010 | /* Reallocate the vector if it's grown, or if it's shrunk a lot. */ | ||
| 2011 | if (n > XVECTOR (frame_and_buffer_state)->size | ||
| 2012 | || n + 20 < XVECTOR (frame_and_buffer_state)->size / 2) | ||
| 2013 | /* Add 20 extra so we grow it less often. */ | ||
| 2014 | frame_and_buffer_state = Fmake_vector (make_number (n + 20), Qlambda); | ||
| 2015 | vecp = XVECTOR (frame_and_buffer_state)->contents; | ||
| 2016 | FOR_EACH_FRAME (tail, frame) | ||
| 2017 | { | ||
| 2018 | *vecp++ = frame; | ||
| 2019 | *vecp++ = XFRAME (frame)->name; | ||
| 2020 | } | ||
| 2021 | for (tail = Vbuffer_alist; CONSP (tail); tail = XCONS (tail)->cdr) | ||
| 2022 | { | ||
| 2023 | buf = XCONS (XCONS (tail)->car)->cdr; | ||
| 2024 | /* Ignore buffers that aren't included in buffer lists. */ | ||
| 2025 | if (XSTRING (XBUFFER (buf)->name)->data[0] == ' ') | ||
| 2026 | continue; | ||
| 2027 | *vecp++ = buf; | ||
| 2028 | *vecp++ = XBUFFER (buf)->read_only; | ||
| 2029 | *vecp++ = Fbuffer_modified_p (buf); | ||
| 2030 | } | ||
| 2031 | /* Fill up the vector with lambdas (always at least one). */ | ||
| 2032 | *vecp++ = Qlambda; | ||
| 2033 | while (vecp - XVECTOR (frame_and_buffer_state)->contents | ||
| 2034 | < XVECTOR (frame_and_buffer_state)->size) | ||
| 2035 | *vecp++ = Qlambda; | ||
| 2036 | /* Make sure we didn't overflow the vector. */ | ||
| 2037 | if (vecp - XVECTOR (frame_and_buffer_state)->contents | ||
| 2038 | > XVECTOR (frame_and_buffer_state)->size) | ||
| 2039 | abort (); | ||
| 2040 | return Qt; | ||
| 2041 | } | 4922 | } |
| 2042 | 4923 | ||
| 2043 | DEFUN ("open-termscript", Fopen_termscript, Sopen_termscript, | 4924 | |
| 2044 | 1, 1, "FOpen termscript file: ", | 4925 | /* Value is the string under window-relative coordinates X/Y in the |
| 2045 | "Start writing all terminal output to FILE as well as the terminal.\n\ | 4926 | mode or top line of window W, or nil if none. MODE_LINE_P non-zero |
| 2046 | FILE = nil means just close any termscript file currently open.") | 4927 | means look at the mode line. *CHARPOS is set to the position in |
| 2047 | (file) | 4928 | the string returned. */ |
| 2048 | Lisp_Object file; | 4929 | |
| 4930 | Lisp_Object | ||
| 4931 | mode_line_string (w, x, y, mode_line_p, charpos) | ||
| 4932 | struct window *w; | ||
| 4933 | int x, y; | ||
| 4934 | int *charpos; | ||
| 2049 | { | 4935 | { |
| 2050 | if (termscript != 0) fclose (termscript); | 4936 | struct glyph_row *row; |
| 2051 | termscript = 0; | 4937 | struct glyph *glyph, *end; |
| 4938 | struct frame *f = XFRAME (w->frame); | ||
| 4939 | int x0; | ||
| 4940 | Lisp_Object string = Qnil; | ||
| 4941 | |||
| 4942 | /* Only do this for frames under a window system. */ | ||
| 4943 | if (!FRAME_WINDOW_P (f)) | ||
| 4944 | return Qnil; | ||
| 2052 | 4945 | ||
| 2053 | if (! NILP (file)) | 4946 | if (mode_line_p) |
| 4947 | row = MATRIX_MODE_LINE_ROW (w->current_matrix); | ||
| 4948 | else | ||
| 4949 | row = MATRIX_TOP_LINE_ROW (w->current_matrix); | ||
| 4950 | |||
| 4951 | if (row->mode_line_p && row->enabled_p) | ||
| 2054 | { | 4952 | { |
| 2055 | file = Fexpand_file_name (file, Qnil); | 4953 | /* The mode lines are displayed over scroll bars and bitmap |
| 2056 | termscript = fopen (XSTRING (file)->data, "w"); | 4954 | areas, and X is window-relative. Correct X by the scroll bar |
| 2057 | if (termscript == 0) | 4955 | and bitmap area width. */ |
| 2058 | report_file_error ("Opening termscript", Fcons (file, Qnil)); | 4956 | if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f)) |
| 4957 | x += FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f); | ||
| 4958 | x += FRAME_FLAGS_AREA_WIDTH (f); | ||
| 4959 | |||
| 4960 | /* Find the glyph under X. If we find one with a string object, | ||
| 4961 | it's the one we were looking for. */ | ||
| 4962 | glyph = row->glyphs[TEXT_AREA]; | ||
| 4963 | end = glyph + row->used[TEXT_AREA]; | ||
| 4964 | for (x0 = 0; glyph < end; x0 += glyph->pixel_width, ++glyph) | ||
| 4965 | if (x >= x0 && x < x0 + glyph->pixel_width) | ||
| 4966 | { | ||
| 4967 | string = glyph->object; | ||
| 4968 | *charpos = glyph->charpos; | ||
| 4969 | break; | ||
| 4970 | } | ||
| 2059 | } | 4971 | } |
| 2060 | return Qnil; | 4972 | |
| 4973 | return string; | ||
| 2061 | } | 4974 | } |
| 2062 | 4975 | ||
| 4976 | |||
| 4977 | /*********************************************************************** | ||
| 4978 | Changing Frame Sizes | ||
| 4979 | ***********************************************************************/ | ||
| 2063 | 4980 | ||
| 2064 | #ifdef SIGWINCH | 4981 | #ifdef SIGWINCH |
| 4982 | |||
| 2065 | SIGTYPE | 4983 | SIGTYPE |
| 2066 | window_change_signal (signalnum) /* If we don't have an argument, */ | 4984 | window_change_signal (signalnum) /* If we don't have an argument, */ |
| 2067 | int signalnum; /* some compilers complain in signal calls. */ | 4985 | int signalnum; /* some compilers complain in signal calls. */ |
| 2068 | { | 4986 | { |
| 2069 | int width, height; | 4987 | int width, height; |
| 2070 | extern int errno; | 4988 | extern int errno; |
| @@ -2112,7 +5030,7 @@ do_pending_window_change () | |||
| 2112 | 5030 | ||
| 2113 | FOR_EACH_FRAME (tail, frame) | 5031 | FOR_EACH_FRAME (tail, frame) |
| 2114 | { | 5032 | { |
| 2115 | FRAME_PTR f = XFRAME (frame); | 5033 | struct frame *f = XFRAME (frame); |
| 2116 | 5034 | ||
| 2117 | int height = FRAME_NEW_HEIGHT (f); | 5035 | int height = FRAME_NEW_HEIGHT (f); |
| 2118 | int width = FRAME_NEW_WIDTH (f); | 5036 | int width = FRAME_NEW_WIDTH (f); |
| @@ -2134,7 +5052,7 @@ do_pending_window_change () | |||
| 2134 | 5052 | ||
| 2135 | void | 5053 | void |
| 2136 | change_frame_size (f, newheight, newwidth, pretend, delay) | 5054 | change_frame_size (f, newheight, newwidth, pretend, delay) |
| 2137 | register FRAME_PTR f; | 5055 | register struct frame *f; |
| 2138 | int newheight, newwidth, pretend, delay; | 5056 | int newheight, newwidth, pretend, delay; |
| 2139 | { | 5057 | { |
| 2140 | Lisp_Object tail, frame; | 5058 | Lisp_Object tail, frame; |
| @@ -2153,8 +5071,8 @@ change_frame_size (f, newheight, newwidth, pretend, delay) | |||
| 2153 | } | 5071 | } |
| 2154 | 5072 | ||
| 2155 | static void | 5073 | static void |
| 2156 | change_frame_size_1 (frame, newheight, newwidth, pretend, delay) | 5074 | change_frame_size_1 (f, newheight, newwidth, pretend, delay) |
| 2157 | register FRAME_PTR frame; | 5075 | register struct frame *f; |
| 2158 | int newheight, newwidth, pretend, delay; | 5076 | int newheight, newwidth, pretend, delay; |
| 2159 | { | 5077 | { |
| 2160 | int new_frame_window_width; | 5078 | int new_frame_window_width; |
| @@ -2164,36 +5082,32 @@ change_frame_size_1 (frame, newheight, newwidth, pretend, delay) | |||
| 2164 | /* If we can't deal with the change now, queue it for later. */ | 5082 | /* If we can't deal with the change now, queue it for later. */ |
| 2165 | if (delay) | 5083 | if (delay) |
| 2166 | { | 5084 | { |
| 2167 | FRAME_NEW_HEIGHT (frame) = newheight; | 5085 | FRAME_NEW_HEIGHT (f) = newheight; |
| 2168 | FRAME_NEW_WIDTH (frame) = newwidth; | 5086 | FRAME_NEW_WIDTH (f) = newwidth; |
| 2169 | delayed_size_change = 1; | 5087 | delayed_size_change = 1; |
| 2170 | return; | 5088 | return; |
| 2171 | } | 5089 | } |
| 2172 | 5090 | ||
| 2173 | /* This size-change overrides any pending one for this frame. */ | 5091 | /* This size-change overrides any pending one for this frame. */ |
| 2174 | FRAME_NEW_HEIGHT (frame) = 0; | 5092 | FRAME_NEW_HEIGHT (f) = 0; |
| 2175 | FRAME_NEW_WIDTH (frame) = 0; | 5093 | FRAME_NEW_WIDTH (f) = 0; |
| 2176 | 5094 | ||
| 2177 | /* If an argument is zero, set it to the current value. */ | 5095 | /* If an argument is zero, set it to the current value. */ |
| 2178 | if (newheight == 0) | 5096 | if (newheight == 0) |
| 2179 | newheight = FRAME_HEIGHT (frame); | 5097 | newheight = FRAME_HEIGHT (f); |
| 2180 | if (newwidth == 0) | 5098 | if (newwidth == 0) |
| 2181 | newwidth = FRAME_WIDTH (frame); | 5099 | newwidth = FRAME_WIDTH (f); |
| 2182 | new_frame_window_width = FRAME_WINDOW_WIDTH_ARG (frame, newwidth); | ||
| 2183 | |||
| 2184 | total_glyphs = newheight * (newwidth + 2) * sizeof (GLYPH); | ||
| 2185 | 5100 | ||
| 2186 | /* If these sizes are so big they cause overflow, | 5101 | /* Compute width of windows in F. |
| 2187 | just ignore the change. It's not clear what better we could do. */ | 5102 | This is the width of the frame without vertical scroll bars. */ |
| 2188 | if (total_glyphs / sizeof (GLYPH) / newheight != newwidth + 2) | 5103 | new_frame_window_width = FRAME_WINDOW_WIDTH_ARG (f, newwidth); |
| 2189 | return; | ||
| 2190 | 5104 | ||
| 2191 | /* Round up to the smallest acceptable size. */ | 5105 | /* Round up to the smallest acceptable size. */ |
| 2192 | check_frame_size (frame, &newheight, &newwidth); | 5106 | check_frame_size (f, &newheight, &newwidth); |
| 2193 | 5107 | ||
| 2194 | /* If we're not changing the frame size, quit now. */ | 5108 | /* If we're not changing the frame size, quit now. */ |
| 2195 | if (newheight == FRAME_HEIGHT (frame) | 5109 | if (newheight == FRAME_HEIGHT (f) |
| 2196 | && new_frame_window_width == FRAME_WINDOW_WIDTH (frame)) | 5110 | && new_frame_window_width == FRAME_WINDOW_WIDTH (f)) |
| 2197 | return; | 5111 | return; |
| 2198 | 5112 | ||
| 2199 | BLOCK_INPUT; | 5113 | BLOCK_INPUT; |
| @@ -2205,76 +5119,101 @@ change_frame_size_1 (frame, newheight, newwidth, pretend, delay) | |||
| 2205 | dos_set_window_size (&newheight, &newwidth); | 5119 | dos_set_window_size (&newheight, &newwidth); |
| 2206 | #endif | 5120 | #endif |
| 2207 | 5121 | ||
| 2208 | if (newheight != FRAME_HEIGHT (frame)) | 5122 | if (newheight != FRAME_HEIGHT (f)) |
| 2209 | { | 5123 | { |
| 2210 | if (FRAME_HAS_MINIBUF_P (frame) | 5124 | if (FRAME_HAS_MINIBUF_P (f) && !FRAME_MINIBUF_ONLY_P (f)) |
| 2211 | && ! FRAME_MINIBUF_ONLY_P (frame)) | ||
| 2212 | { | 5125 | { |
| 2213 | /* Frame has both root and minibuffer. */ | 5126 | /* Frame has both root and mini-buffer. */ |
| 2214 | set_window_height (FRAME_ROOT_WINDOW (frame), | 5127 | XSETFASTINT (XWINDOW (FRAME_ROOT_WINDOW (f))->top, |
| 2215 | newheight - 1 - FRAME_MENU_BAR_LINES (frame), 0); | 5128 | FRAME_TOP_MARGIN (f)); |
| 2216 | XSETFASTINT (XWINDOW (FRAME_MINIBUF_WINDOW (frame))->top, | 5129 | set_window_height (FRAME_ROOT_WINDOW (f), |
| 5130 | (newheight | ||
| 5131 | - 1 | ||
| 5132 | - FRAME_TOP_MARGIN (f)), | ||
| 5133 | 0); | ||
| 5134 | XSETFASTINT (XWINDOW (FRAME_MINIBUF_WINDOW (f))->top, | ||
| 2217 | newheight - 1); | 5135 | newheight - 1); |
| 2218 | set_window_height (FRAME_MINIBUF_WINDOW (frame), 1, 0); | 5136 | set_window_height (FRAME_MINIBUF_WINDOW (f), 1, 0); |
| 2219 | } | 5137 | } |
| 2220 | else | 5138 | else |
| 2221 | /* Frame has just one top-level window. */ | 5139 | /* Frame has just one top-level window. */ |
| 2222 | set_window_height (FRAME_ROOT_WINDOW (frame), | 5140 | set_window_height (FRAME_ROOT_WINDOW (f), |
| 2223 | newheight - FRAME_MENU_BAR_LINES (frame), 0); | 5141 | newheight - FRAME_TOP_MARGIN (f), 0); |
| 2224 | 5142 | ||
| 2225 | if (FRAME_TERMCAP_P (frame) && !pretend) | 5143 | if (FRAME_TERMCAP_P (f) && !pretend) |
| 2226 | FrameRows = newheight; | 5144 | FrameRows = newheight; |
| 2227 | |||
| 2228 | #if 0 | ||
| 2229 | if (frame->output_method == output_termcap) | ||
| 2230 | { | ||
| 2231 | frame_height = newheight; | ||
| 2232 | if (!pretend) | ||
| 2233 | FrameRows = newheight; | ||
| 2234 | } | ||
| 2235 | #endif | ||
| 2236 | } | 5145 | } |
| 2237 | 5146 | ||
| 2238 | if (new_frame_window_width != FRAME_WINDOW_WIDTH (frame)) | 5147 | if (new_frame_window_width != FRAME_WINDOW_WIDTH (f)) |
| 2239 | { | 5148 | { |
| 2240 | set_window_width (FRAME_ROOT_WINDOW (frame), new_frame_window_width, 0); | 5149 | set_window_width (FRAME_ROOT_WINDOW (f), new_frame_window_width, 0); |
| 2241 | if (FRAME_HAS_MINIBUF_P (frame)) | 5150 | if (FRAME_HAS_MINIBUF_P (f)) |
| 2242 | set_window_width (FRAME_MINIBUF_WINDOW (frame), new_frame_window_width, 0); | 5151 | set_window_width (FRAME_MINIBUF_WINDOW (f), new_frame_window_width, 0); |
| 2243 | 5152 | ||
| 2244 | if (FRAME_TERMCAP_P (frame) && !pretend) | 5153 | if (FRAME_TERMCAP_P (f) && !pretend) |
| 2245 | FrameCols = newwidth; | 5154 | FrameCols = newwidth; |
| 2246 | #if 0 | 5155 | |
| 2247 | if (frame->output_method == output_termcap) | 5156 | if (WINDOWP (f->toolbar_window)) |
| 2248 | { | 5157 | XSETFASTINT (XWINDOW (f->toolbar_window)->width, newwidth); |
| 2249 | frame_width = newwidth; | ||
| 2250 | if (!pretend) | ||
| 2251 | FrameCols = newwidth; | ||
| 2252 | } | ||
| 2253 | #endif | ||
| 2254 | } | 5158 | } |
| 2255 | 5159 | ||
| 2256 | FRAME_HEIGHT (frame) = newheight; | 5160 | FRAME_HEIGHT (f) = newheight; |
| 2257 | SET_FRAME_WIDTH (frame, newwidth); | 5161 | SET_FRAME_WIDTH (f, newwidth); |
| 2258 | 5162 | ||
| 2259 | if (FRAME_CURSOR_X (frame) >= FRAME_CURSOR_X_LIMIT (frame)) | 5163 | { |
| 2260 | FRAME_CURSOR_X (frame) = FRAME_CURSOR_X_LIMIT (frame) - 1; | 5164 | struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f)); |
| 2261 | if (FRAME_CURSOR_Y (frame) >= FRAME_HEIGHT (frame)) | 5165 | int text_area_x, text_area_y, text_area_width, text_area_height; |
| 2262 | FRAME_CURSOR_Y (frame) = FRAME_HEIGHT (frame) - 1; | 5166 | |
| 5167 | window_box (w, TEXT_AREA, &text_area_x, &text_area_y, &text_area_width, | ||
| 5168 | &text_area_height); | ||
| 5169 | if (w->cursor.x >= text_area_x + text_area_width) | ||
| 5170 | w->cursor.hpos = w->cursor.x = 0; | ||
| 5171 | if (w->cursor.y >= text_area_y + text_area_height) | ||
| 5172 | w->cursor.vpos = w->cursor.y = 0; | ||
| 5173 | } | ||
| 2263 | 5174 | ||
| 2264 | remake_frame_glyphs (frame); | 5175 | adjust_glyphs (f); |
| 2265 | calculate_costs (frame); | 5176 | SET_FRAME_GARBAGED (f); |
| 5177 | calculate_costs (f); | ||
| 2266 | 5178 | ||
| 2267 | UNBLOCK_INPUT; | 5179 | UNBLOCK_INPUT; |
| 2268 | 5180 | ||
| 2269 | record_unwind_protect (Fset_buffer, Fcurrent_buffer ()); | 5181 | record_unwind_protect (Fset_buffer, Fcurrent_buffer ()); |
| 2270 | 5182 | ||
| 2271 | /* This isn't quite a no-op: it runs window-configuration-change-hook. */ | 5183 | /* This isn't quite a no-op: it runs window-configuration-change-hook. */ |
| 2272 | Fset_window_buffer (FRAME_SELECTED_WINDOW (frame), | 5184 | Fset_window_buffer (FRAME_SELECTED_WINDOW (f), |
| 2273 | XWINDOW (FRAME_SELECTED_WINDOW (frame))->buffer); | 5185 | XWINDOW (FRAME_SELECTED_WINDOW (f))->buffer); |
| 2274 | 5186 | ||
| 2275 | unbind_to (count, Qnil); | 5187 | unbind_to (count, Qnil); |
| 2276 | } | 5188 | } |
| 5189 | |||
| 5190 | |||
| 2277 | 5191 | ||
| 5192 | /*********************************************************************** | ||
| 5193 | Terminal Related Lisp Functions | ||
| 5194 | ***********************************************************************/ | ||
| 5195 | |||
| 5196 | DEFUN ("open-termscript", Fopen_termscript, Sopen_termscript, | ||
| 5197 | 1, 1, "FOpen termscript file: ", | ||
| 5198 | "Start writing all terminal output to FILE as well as the terminal.\n\ | ||
| 5199 | FILE = nil means just close any termscript file currently open.") | ||
| 5200 | (file) | ||
| 5201 | Lisp_Object file; | ||
| 5202 | { | ||
| 5203 | if (termscript != 0) fclose (termscript); | ||
| 5204 | termscript = 0; | ||
| 5205 | |||
| 5206 | if (! NILP (file)) | ||
| 5207 | { | ||
| 5208 | file = Fexpand_file_name (file, Qnil); | ||
| 5209 | termscript = fopen (XSTRING (file)->data, "w"); | ||
| 5210 | if (termscript == 0) | ||
| 5211 | report_file_error ("Opening termscript", Fcons (file, Qnil)); | ||
| 5212 | } | ||
| 5213 | return Qnil; | ||
| 5214 | } | ||
| 5215 | |||
| 5216 | |||
| 2278 | DEFUN ("send-string-to-terminal", Fsend_string_to_terminal, | 5217 | DEFUN ("send-string-to-terminal", Fsend_string_to_terminal, |
| 2279 | Ssend_string_to_terminal, 1, 1, 0, | 5218 | Ssend_string_to_terminal, 1, 1, 0, |
| 2280 | "Send STRING to the terminal without alteration.\n\ | 5219 | "Send STRING to the terminal without alteration.\n\ |
| @@ -2295,6 +5234,7 @@ Control characters in STRING will have terminal-dependent effects.") | |||
| 2295 | return Qnil; | 5234 | return Qnil; |
| 2296 | } | 5235 | } |
| 2297 | 5236 | ||
| 5237 | |||
| 2298 | DEFUN ("ding", Fding, Sding, 0, 1, 0, | 5238 | DEFUN ("ding", Fding, Sding, 0, 1, 0, |
| 2299 | "Beep, or flash the screen.\n\ | 5239 | "Beep, or flash the screen.\n\ |
| 2300 | Also, unless an argument is given,\n\ | 5240 | Also, unless an argument is given,\n\ |
| @@ -2321,13 +5261,19 @@ bitch_at_user () | |||
| 2321 | { | 5261 | { |
| 2322 | if (noninteractive) | 5262 | if (noninteractive) |
| 2323 | putchar (07); | 5263 | putchar (07); |
| 2324 | else if (!INTERACTIVE) /* Stop executing a keyboard macro. */ | 5264 | else if (!INTERACTIVE) /* Stop executing a keyboard macro. */ |
| 2325 | error ("Keyboard macro terminated by a command ringing the bell"); | 5265 | error ("Keyboard macro terminated by a command ringing the bell"); |
| 2326 | else | 5266 | else |
| 2327 | ring_bell (); | 5267 | ring_bell (); |
| 2328 | fflush (stdout); | 5268 | fflush (stdout); |
| 2329 | } | 5269 | } |
| 2330 | 5270 | ||
| 5271 | |||
| 5272 | |||
| 5273 | /*********************************************************************** | ||
| 5274 | Sleeping, Waiting | ||
| 5275 | ***********************************************************************/ | ||
| 5276 | |||
| 2331 | DEFUN ("sleep-for", Fsleep_for, Ssleep_for, 1, 2, 0, | 5277 | DEFUN ("sleep-for", Fsleep_for, Ssleep_for, 1, 2, 0, |
| 2332 | "Pause, without updating display, for SECONDS seconds.\n\ | 5278 | "Pause, without updating display, for SECONDS seconds.\n\ |
| 2333 | SECONDS may be a floating-point value, meaning that you can wait for a\n\ | 5279 | SECONDS may be a floating-point value, meaning that you can wait for a\n\ |
| @@ -2421,6 +5367,7 @@ Emacs was built without floating point support.\n\ | |||
| 2421 | return Qnil; | 5367 | return Qnil; |
| 2422 | } | 5368 | } |
| 2423 | 5369 | ||
| 5370 | |||
| 2424 | /* This is just like wait_reading_process_input, except that | 5371 | /* This is just like wait_reading_process_input, except that |
| 2425 | it does the redisplay. | 5372 | it does the redisplay. |
| 2426 | 5373 | ||
| @@ -2454,6 +5401,7 @@ sit_for (sec, usec, reading, display, initial_display) | |||
| 2454 | return detect_input_pending () ? Qnil : Qt; | 5401 | return detect_input_pending () ? Qnil : Qt; |
| 2455 | } | 5402 | } |
| 2456 | 5403 | ||
| 5404 | |||
| 2457 | DEFUN ("sit-for", Fsit_for, Ssit_for, 1, 3, 0, | 5405 | DEFUN ("sit-for", Fsit_for, Ssit_for, 1, 3, 0, |
| 2458 | "Perform redisplay, then wait for SECONDS seconds or until input is available.\n\ | 5406 | "Perform redisplay, then wait for SECONDS seconds or until input is available.\n\ |
| 2459 | SECONDS may be a floating-point value, meaning that you can wait for a\n\ | 5407 | SECONDS may be a floating-point value, meaning that you can wait for a\n\ |
| @@ -2494,13 +5442,115 @@ Value is t if waited the full time with no input arriving.") | |||
| 2494 | 5442 | ||
| 2495 | return sit_for (sec, usec, 0, NILP (nodisp), NILP (nodisp)); | 5443 | return sit_for (sec, usec, 0, NILP (nodisp), NILP (nodisp)); |
| 2496 | } | 5444 | } |
| 5445 | |||
| 5446 | |||
| 2497 | 5447 | ||
| 5448 | /*********************************************************************** | ||
| 5449 | Other Lisp Functions | ||
| 5450 | ***********************************************************************/ | ||
| 5451 | |||
| 5452 | /* A vector of size >= 2 * NFRAMES + 3 * NBUFFERS + 1, containing the | ||
| 5453 | session's frames, frame names, buffers, buffer-read-only flags, and | ||
| 5454 | buffer-modified-flags, and a trailing sentinel (so we don't need to | ||
| 5455 | add length checks). */ | ||
| 5456 | |||
| 5457 | static Lisp_Object frame_and_buffer_state; | ||
| 5458 | |||
| 5459 | |||
| 5460 | DEFUN ("frame-or-buffer-changed-p", Fframe_or_buffer_changed_p, | ||
| 5461 | Sframe_or_buffer_changed_p, 0, 0, 0, | ||
| 5462 | "Return non-nil if the frame and buffer state appears to have changed.\n\ | ||
| 5463 | The state variable is an internal vector containing all frames and buffers,\n\ | ||
| 5464 | aside from buffers whose names start with space,\n\ | ||
| 5465 | along with the buffers' read-only and modified flags, which allows a fast\n\ | ||
| 5466 | check to see whether the menu bars might need to be recomputed.\n\ | ||
| 5467 | If this function returns non-nil, it updates the internal vector to reflect\n\ | ||
| 5468 | the current state.\n") | ||
| 5469 | () | ||
| 5470 | { | ||
| 5471 | Lisp_Object tail, frame, buf; | ||
| 5472 | Lisp_Object *vecp; | ||
| 5473 | int n; | ||
| 5474 | |||
| 5475 | vecp = XVECTOR (frame_and_buffer_state)->contents; | ||
| 5476 | FOR_EACH_FRAME (tail, frame) | ||
| 5477 | { | ||
| 5478 | if (!EQ (*vecp++, frame)) | ||
| 5479 | goto changed; | ||
| 5480 | if (!EQ (*vecp++, XFRAME (frame)->name)) | ||
| 5481 | goto changed; | ||
| 5482 | } | ||
| 5483 | /* Check that the buffer info matches. | ||
| 5484 | No need to test for the end of the vector | ||
| 5485 | because the last element of the vector is lambda | ||
| 5486 | and that will always cause a mismatch. */ | ||
| 5487 | for (tail = Vbuffer_alist; CONSP (tail); tail = XCONS (tail)->cdr) | ||
| 5488 | { | ||
| 5489 | buf = XCONS (XCONS (tail)->car)->cdr; | ||
| 5490 | /* Ignore buffers that aren't included in buffer lists. */ | ||
| 5491 | if (XSTRING (XBUFFER (buf)->name)->data[0] == ' ') | ||
| 5492 | continue; | ||
| 5493 | if (!EQ (*vecp++, buf)) | ||
| 5494 | goto changed; | ||
| 5495 | if (!EQ (*vecp++, XBUFFER (buf)->read_only)) | ||
| 5496 | goto changed; | ||
| 5497 | if (!EQ (*vecp++, Fbuffer_modified_p (buf))) | ||
| 5498 | goto changed; | ||
| 5499 | } | ||
| 5500 | /* Detect deletion of a buffer at the end of the list. */ | ||
| 5501 | if (EQ (*vecp, Qlambda)) | ||
| 5502 | return Qnil; | ||
| 5503 | changed: | ||
| 5504 | /* Start with 1 so there is room for at least one lambda at the end. */ | ||
| 5505 | n = 1; | ||
| 5506 | FOR_EACH_FRAME (tail, frame) | ||
| 5507 | n += 2; | ||
| 5508 | for (tail = Vbuffer_alist; CONSP (tail); tail = XCONS (tail)->cdr) | ||
| 5509 | n += 3; | ||
| 5510 | /* Reallocate the vector if it's grown, or if it's shrunk a lot. */ | ||
| 5511 | if (n > XVECTOR (frame_and_buffer_state)->size | ||
| 5512 | || n + 20 < XVECTOR (frame_and_buffer_state)->size / 2) | ||
| 5513 | /* Add 20 extra so we grow it less often. */ | ||
| 5514 | frame_and_buffer_state = Fmake_vector (make_number (n + 20), Qlambda); | ||
| 5515 | vecp = XVECTOR (frame_and_buffer_state)->contents; | ||
| 5516 | FOR_EACH_FRAME (tail, frame) | ||
| 5517 | { | ||
| 5518 | *vecp++ = frame; | ||
| 5519 | *vecp++ = XFRAME (frame)->name; | ||
| 5520 | } | ||
| 5521 | for (tail = Vbuffer_alist; CONSP (tail); tail = XCONS (tail)->cdr) | ||
| 5522 | { | ||
| 5523 | buf = XCONS (XCONS (tail)->car)->cdr; | ||
| 5524 | /* Ignore buffers that aren't included in buffer lists. */ | ||
| 5525 | if (XSTRING (XBUFFER (buf)->name)->data[0] == ' ') | ||
| 5526 | continue; | ||
| 5527 | *vecp++ = buf; | ||
| 5528 | *vecp++ = XBUFFER (buf)->read_only; | ||
| 5529 | *vecp++ = Fbuffer_modified_p (buf); | ||
| 5530 | } | ||
| 5531 | /* Fill up the vector with lambdas (always at least one). */ | ||
| 5532 | *vecp++ = Qlambda; | ||
| 5533 | while (vecp - XVECTOR (frame_and_buffer_state)->contents | ||
| 5534 | < XVECTOR (frame_and_buffer_state)->size) | ||
| 5535 | *vecp++ = Qlambda; | ||
| 5536 | /* Make sure we didn't overflow the vector. */ | ||
| 5537 | if (vecp - XVECTOR (frame_and_buffer_state)->contents | ||
| 5538 | > XVECTOR (frame_and_buffer_state)->size) | ||
| 5539 | abort (); | ||
| 5540 | return Qt; | ||
| 5541 | } | ||
| 5542 | |||
| 5543 | |||
| 5544 | |||
| 5545 | /*********************************************************************** | ||
| 5546 | Initialization | ||
| 5547 | ***********************************************************************/ | ||
| 5548 | |||
| 2498 | char *terminal_type; | 5549 | char *terminal_type; |
| 2499 | 5550 | ||
| 2500 | /* Initialization done when Emacs fork is started, before doing stty. */ | 5551 | /* Initialization done when Emacs fork is started, before doing stty. |
| 2501 | /* Determine terminal type and set terminal_driver */ | 5552 | Determine terminal type and set terminal_driver. Then invoke its |
| 2502 | /* Then invoke its decoding routine to set up variables | 5553 | decoding routine to set up variables in the terminal package. */ |
| 2503 | in the terminal package */ | ||
| 2504 | 5554 | ||
| 2505 | void | 5555 | void |
| 2506 | init_display () | 5556 | init_display () |
| @@ -2509,6 +5559,11 @@ init_display () | |||
| 2509 | extern int display_arg; | 5559 | extern int display_arg; |
| 2510 | #endif | 5560 | #endif |
| 2511 | 5561 | ||
| 5562 | /* Construct the space glyph. */ | ||
| 5563 | space_glyph.type = CHAR_GLYPH; | ||
| 5564 | SET_CHAR_GLYPH_FROM_GLYPH (space_glyph, ' '); | ||
| 5565 | space_glyph.charpos = -1; | ||
| 5566 | |||
| 2512 | meta_key = 0; | 5567 | meta_key = 0; |
| 2513 | inverse_video = 0; | 5568 | inverse_video = 0; |
| 2514 | cursor_in_echo_area = 0; | 5569 | cursor_in_echo_area = 0; |
| @@ -2557,6 +5612,7 @@ init_display () | |||
| 2557 | So call tgetent. */ | 5612 | So call tgetent. */ |
| 2558 | { char b[2044]; tgetent (b, "xterm");} | 5613 | { char b[2044]; tgetent (b, "xterm");} |
| 2559 | #endif | 5614 | #endif |
| 5615 | adjust_frame_glyphs_initially (); | ||
| 2560 | return; | 5616 | return; |
| 2561 | } | 5617 | } |
| 2562 | #endif /* HAVE_X_WINDOWS */ | 5618 | #endif /* HAVE_X_WINDOWS */ |
| @@ -2566,6 +5622,7 @@ init_display () | |||
| 2566 | { | 5622 | { |
| 2567 | Vwindow_system = intern ("w32"); | 5623 | Vwindow_system = intern ("w32"); |
| 2568 | Vwindow_system_version = make_number (1); | 5624 | Vwindow_system_version = make_number (1); |
| 5625 | adjust_frame_glyphs_initially (); | ||
| 2569 | return; | 5626 | return; |
| 2570 | } | 5627 | } |
| 2571 | #endif /* HAVE_NTGUI */ | 5628 | #endif /* HAVE_NTGUI */ |
| @@ -2593,7 +5650,7 @@ For types not defined in VMS, use define emacs_term \"TYPE\".\n\ | |||
| 2593 | } | 5650 | } |
| 2594 | 5651 | ||
| 2595 | #ifdef VMS | 5652 | #ifdef VMS |
| 2596 | /* VMS DCL tends to upcase things, so downcase term type. | 5653 | /* VMS DCL tends to up-case things, so down-case term type. |
| 2597 | Hardly any uppercase letters in terminal types; should be none. */ | 5654 | Hardly any uppercase letters in terminal types; should be none. */ |
| 2598 | { | 5655 | { |
| 2599 | char *new = (char *) xmalloc (strlen (terminal_type) + 1); | 5656 | char *new = (char *) xmalloc (strlen (terminal_type) + 1); |
| @@ -2607,37 +5664,84 @@ For types not defined in VMS, use define emacs_term \"TYPE\".\n\ | |||
| 2607 | 5664 | ||
| 2608 | terminal_type = new; | 5665 | terminal_type = new; |
| 2609 | } | 5666 | } |
| 2610 | #endif | 5667 | #endif /* VMS */ |
| 2611 | 5668 | ||
| 2612 | term_init (terminal_type); | 5669 | term_init (terminal_type); |
| 2613 | 5670 | ||
| 2614 | { | 5671 | { |
| 2615 | int width = FRAME_WINDOW_WIDTH (selected_frame); | 5672 | int width = FRAME_WINDOW_WIDTH (selected_frame); |
| 2616 | int height = FRAME_HEIGHT (selected_frame); | 5673 | int height = FRAME_HEIGHT (selected_frame); |
| 2617 | 5674 | ||
| 2618 | unsigned int total_glyphs = height * (width + 2) * sizeof (GLYPH); | 5675 | unsigned int total_glyphs = height * (width + 2) * sizeof (struct glyph); |
| 2619 | 5676 | ||
| 2620 | /* If these sizes are so big they cause overflow, | 5677 | /* If these sizes are so big they cause overflow, just ignore the |
| 2621 | just ignore the change. It's not clear what better we could do. */ | 5678 | change. It's not clear what better we could do. */ |
| 2622 | if (total_glyphs / sizeof (GLYPH) / height != width + 2) | 5679 | if (total_glyphs / sizeof (struct glyph) / height != width + 2) |
| 2623 | fatal ("screen size %dx%d too big", width, height); | 5680 | fatal ("screen size %dx%d too big", width, height); |
| 2624 | } | 5681 | } |
| 2625 | 5682 | ||
| 2626 | remake_frame_glyphs (selected_frame); | 5683 | adjust_frame_glyphs_initially (); |
| 2627 | calculate_costs (selected_frame); | 5684 | calculate_costs (selected_frame); |
| 2628 | 5685 | ||
| 2629 | /* X and Y coordinates of the cursor between updates. */ | ||
| 2630 | FRAME_CURSOR_X (selected_frame) = 0; | ||
| 2631 | FRAME_CURSOR_Y (selected_frame) = 0; | ||
| 2632 | |||
| 2633 | #ifdef SIGWINCH | 5686 | #ifdef SIGWINCH |
| 2634 | #ifndef CANNOT_DUMP | 5687 | #ifndef CANNOT_DUMP |
| 2635 | if (initialized) | 5688 | if (initialized) |
| 2636 | #endif /* CANNOT_DUMP */ | 5689 | #endif /* CANNOT_DUMP */ |
| 2637 | signal (SIGWINCH, window_change_signal); | 5690 | signal (SIGWINCH, window_change_signal); |
| 2638 | #endif /* SIGWINCH */ | 5691 | #endif /* SIGWINCH */ |
| 5692 | |||
| 5693 | /* Set up faces of the initial terminal frame of a dumped Emacs. */ | ||
| 5694 | if (initialized | ||
| 5695 | && !noninteractive | ||
| 5696 | && NILP (Vwindow_system)) | ||
| 5697 | call0 (intern ("tty-set-up-initial-frame-faces")); | ||
| 2639 | } | 5698 | } |
| 5699 | |||
| 5700 | |||
| 5701 | |||
| 5702 | /*********************************************************************** | ||
| 5703 | Blinking cursor | ||
| 5704 | ***********************************************************************/ | ||
| 5705 | |||
| 5706 | DEFUN ("show-cursor", Fshow_cursor, Sshow_cursor, 0, 2, 0, | ||
| 5707 | "Change visibility flag of the text cursor of WINDOW.\n\ | ||
| 5708 | ON_P nil means toggle the flag. Otherwise, ON_P must be an integer,\n\ | ||
| 5709 | and the flag is set according to the value of ON_P. WINDOW nil or\n\ | ||
| 5710 | omitted means use the selected window. The new cursor state takes effect\n\ | ||
| 5711 | with the next redisplay.") | ||
| 5712 | (on_p, window) | ||
| 5713 | Lisp_Object on_p, window; | ||
| 5714 | { | ||
| 5715 | struct window *w; | ||
| 5716 | |||
| 5717 | /* Don't change cursor state while redisplaying. This could confuse | ||
| 5718 | output routines. */ | ||
| 5719 | if (!redisplaying_p) | ||
| 5720 | { | ||
| 5721 | if (NILP (window)) | ||
| 5722 | window = selected_window; | ||
| 5723 | else | ||
| 5724 | CHECK_WINDOW (window, 2); | ||
| 5725 | w = XWINDOW (window); | ||
| 5726 | |||
| 5727 | if (NILP (on_p)) | ||
| 5728 | w->cursor_off_p = !w->cursor_off_p; | ||
| 5729 | else | ||
| 5730 | { | ||
| 5731 | CHECK_NUMBER (on_p, 1); | ||
| 5732 | w->cursor_off_p = XINT (on_p) != 0; | ||
| 5733 | } | ||
| 5734 | } | ||
| 5735 | |||
| 5736 | return Qnil; | ||
| 5737 | } | ||
| 5738 | |||
| 5739 | |||
| 2640 | 5740 | ||
| 5741 | /*********************************************************************** | ||
| 5742 | Initialization | ||
| 5743 | ***********************************************************************/ | ||
| 5744 | |||
| 2641 | void | 5745 | void |
| 2642 | syms_of_display () | 5746 | syms_of_display () |
| 2643 | { | 5747 | { |
| @@ -2649,6 +5753,7 @@ syms_of_display () | |||
| 2649 | defsubr (&Ssit_for); | 5753 | defsubr (&Ssit_for); |
| 2650 | defsubr (&Ssleep_for); | 5754 | defsubr (&Ssleep_for); |
| 2651 | defsubr (&Ssend_string_to_terminal); | 5755 | defsubr (&Ssend_string_to_terminal); |
| 5756 | defsubr (&Sshow_cursor); | ||
| 2652 | 5757 | ||
| 2653 | frame_and_buffer_state = Fmake_vector (make_number (20), Qlambda); | 5758 | frame_and_buffer_state = Fmake_vector (make_number (20), Qlambda); |
| 2654 | staticpro (&frame_and_buffer_state); | 5759 | staticpro (&frame_and_buffer_state); |
| @@ -2660,24 +5765,31 @@ syms_of_display () | |||
| 2660 | "*The output baud rate of the terminal.\n\ | 5765 | "*The output baud rate of the terminal.\n\ |
| 2661 | On most systems, changing this value will affect the amount of padding\n\ | 5766 | On most systems, changing this value will affect the amount of padding\n\ |
| 2662 | and the other strategic decisions made during redisplay."); | 5767 | and the other strategic decisions made during redisplay."); |
| 5768 | |||
| 2663 | DEFVAR_BOOL ("inverse-video", &inverse_video, | 5769 | DEFVAR_BOOL ("inverse-video", &inverse_video, |
| 2664 | "*Non-nil means invert the entire frame display.\n\ | 5770 | "*Non-nil means invert the entire frame display.\n\ |
| 2665 | This means everything is in inverse video which otherwise would not be."); | 5771 | This means everything is in inverse video which otherwise would not be."); |
| 5772 | |||
| 2666 | DEFVAR_BOOL ("visible-bell", &visible_bell, | 5773 | DEFVAR_BOOL ("visible-bell", &visible_bell, |
| 2667 | "*Non-nil means try to flash the frame to represent a bell."); | 5774 | "*Non-nil means try to flash the frame to represent a bell."); |
| 5775 | |||
| 2668 | DEFVAR_BOOL ("no-redraw-on-reenter", &no_redraw_on_reenter, | 5776 | DEFVAR_BOOL ("no-redraw-on-reenter", &no_redraw_on_reenter, |
| 2669 | "*Non-nil means no need to redraw entire frame after suspending.\n\ | 5777 | "*Non-nil means no need to redraw entire frame after suspending.\n\ |
| 2670 | A non-nil value is useful if the terminal can automatically preserve\n\ | 5778 | A non-nil value is useful if the terminal can automatically preserve\n\ |
| 2671 | Emacs's frame display when you reenter Emacs.\n\ | 5779 | Emacs's frame display when you reenter Emacs.\n\ |
| 2672 | It is up to you to set this variable if your terminal can do that."); | 5780 | It is up to you to set this variable if your terminal can do that."); |
| 5781 | |||
| 2673 | DEFVAR_LISP ("window-system", &Vwindow_system, | 5782 | DEFVAR_LISP ("window-system", &Vwindow_system, |
| 2674 | "A symbol naming the window-system under which Emacs is running\n\ | 5783 | "A symbol naming the window-system under which Emacs is running\n\ |
| 2675 | \(such as `x'), or nil if emacs is running on an ordinary terminal."); | 5784 | \(such as `x'), or nil if emacs is running on an ordinary terminal."); |
| 5785 | |||
| 2676 | DEFVAR_LISP ("window-system-version", &Vwindow_system_version, | 5786 | DEFVAR_LISP ("window-system-version", &Vwindow_system_version, |
| 2677 | "The version number of the window system in use.\n\ | 5787 | "The version number of the window system in use.\n\ |
| 2678 | For X windows, this is 10 or 11."); | 5788 | For X windows, this is 10 or 11."); |
| 5789 | |||
| 2679 | DEFVAR_BOOL ("cursor-in-echo-area", &cursor_in_echo_area, | 5790 | DEFVAR_BOOL ("cursor-in-echo-area", &cursor_in_echo_area, |
| 2680 | "Non-nil means put cursor in minibuffer, at end of any message there."); | 5791 | "Non-nil means put cursor in minibuffer, at end of any message there."); |
| 5792 | |||
| 2681 | DEFVAR_LISP ("glyph-table", &Vglyph_table, | 5793 | DEFVAR_LISP ("glyph-table", &Vglyph_table, |
| 2682 | "Table defining how to output a glyph code to the frame.\n\ | 5794 | "Table defining how to output a glyph code to the frame.\n\ |
| 2683 | If not nil, this is a vector indexed by glyph code to define the glyph.\n\ | 5795 | If not nil, this is a vector indexed by glyph code to define the glyph.\n\ |
| @@ -2693,6 +5805,10 @@ Each element can be:\n\ | |||
| 2693 | See `buffer-display-table' for more information."); | 5805 | See `buffer-display-table' for more information."); |
| 2694 | Vstandard_display_table = Qnil; | 5806 | Vstandard_display_table = Qnil; |
| 2695 | 5807 | ||
| 5808 | DEFVAR_BOOL ("redisplay-dont-pause", &redisplay_dont_pause, | ||
| 5809 | "*Non-nil means update isn't paused when input is detected."); | ||
| 5810 | redisplay_dont_pause = 0; | ||
| 5811 | |||
| 2696 | /* Initialize `window-system', unless init_display already decided it. */ | 5812 | /* Initialize `window-system', unless init_display already decided it. */ |
| 2697 | #ifdef CANNOT_DUMP | 5813 | #ifdef CANNOT_DUMP |
| 2698 | if (noninteractive) | 5814 | if (noninteractive) |
diff --git a/src/xdisp.c b/src/xdisp.c index 9f5c6139dc6..c74e3f95ce4 100644 --- a/src/xdisp.c +++ b/src/xdisp.c | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /* Display generation from window structure and buffer text. | 1 | /* Display generation from window structure and buffer text. |
| 2 | Copyright (C) 1985, 86, 87, 88, 93, 94, 95, 97, 1998 | 2 | Copyright (C) 1985, 86, 87, 88, 93, 94, 95, 97, 98, 99 |
| 3 | Free Software Foundation, Inc. | 3 | Free Software Foundation, Inc. |
| 4 | 4 | ||
| 5 | This file is part of GNU Emacs. | 5 | This file is part of GNU Emacs. |
| 6 | 6 | ||
| @@ -19,11 +19,159 @@ along with GNU Emacs; see the file COPYING. If not, write to | |||
| 19 | the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | 19 | the Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
| 20 | Boston, MA 02111-1307, USA. */ | 20 | Boston, MA 02111-1307, USA. */ |
| 21 | 21 | ||
| 22 | /* New redisplay written by Gerd Moellmann <gerd@gnu.org>. | ||
| 23 | |||
| 24 | Redisplay. | ||
| 25 | |||
| 26 | Emacs separates the task of updating the display from code | ||
| 27 | modifying global state, e.g. buffer text. This way functions | ||
| 28 | operating on buffers don't also have to be concerned with updating | ||
| 29 | the display. | ||
| 30 | |||
| 31 | Updating the display is triggered by the Lisp interpreter when it | ||
| 32 | decides it's time to do it. This is done either automatically for | ||
| 33 | you as part of the interpreter's command loop or as the result of | ||
| 34 | calling Lisp functions like `sit-for'. The C function `redisplay' | ||
| 35 | in xdisp.c is the only entry into the inner redisplay code. (Or, | ||
| 36 | let's say almost---see the the description of direct update | ||
| 37 | operations, below.). | ||
| 38 | |||
| 39 | The following diagram shows how redisplay code is invoked. As you | ||
| 40 | can see, Lisp calls redisplay and vice versa. Under window systems | ||
| 41 | like X, some portions of the redisplay code are also called | ||
| 42 | asynchronously during mouse movement or expose events. It is very | ||
| 43 | important that these code parts do NOT use the C library (malloc, | ||
| 44 | free) because many C libraries under Unix are not reentrant. They | ||
| 45 | may also NOT call functions of the Lisp interpreter which could | ||
| 46 | change the interpreter's state. If you don't follow these rules, | ||
| 47 | you will encounter bugs which are very hard to explain. | ||
| 48 | |||
| 49 | (Direct functions, see below) | ||
| 50 | direct_output_for_insert, | ||
| 51 | direct_forward_char (dispnew.c) | ||
| 52 | +---------------------------------+ | ||
| 53 | | | | ||
| 54 | | V | ||
| 55 | +--------------+ redisplay() +----------------+ | ||
| 56 | | Lisp machine |---------------->| Redisplay code |<--+ | ||
| 57 | +--------------+ (xdisp.c) +----------------+ | | ||
| 58 | ^ | | | ||
| 59 | +----------------------------------+ | | ||
| 60 | Don't use this path when called | | ||
| 61 | asynchronously! | | ||
| 62 | | | ||
| 63 | expose_window (asynchronous) | | ||
| 64 | | | ||
| 65 | X expose events -----+ | ||
| 66 | |||
| 67 | What does redisplay? Obviously, it has to figure out somehow what | ||
| 68 | has been changed since the last time the display has been updated, | ||
| 69 | and to make these changes visible. Preferably it would do that in | ||
| 70 | a moderately intelligent way, i.e. fast. | ||
| 71 | |||
| 72 | Changes in buffer text can be deduced from window and buffer | ||
| 73 | structures, and from some global variables like `beg_unchanged' and | ||
| 74 | `end_unchanged'. The contents of the display are additionally | ||
| 75 | recorded in a `glyph matrix', a two-dimensional matrix of glyph | ||
| 76 | structures. Each row in such a matrix corresponds to a line on the | ||
| 77 | display, and each glyph in a row corresponds to a column displaying | ||
| 78 | a character, an image, or what else. This matrix is called the | ||
| 79 | `current glyph matrix' or `current matrix' in redisplay | ||
| 80 | terminology. | ||
| 81 | |||
| 82 | For buffer parts that have been changed since the last update, a | ||
| 83 | second glyph matrix is constructed, the so called `desired glyph | ||
| 84 | matrix' or short `desired matrix'. Current and desired matrix are | ||
| 85 | then compared to find a cheap way to update the display, e.g. by | ||
| 86 | reusing part of the display by scrolling lines. | ||
| 87 | |||
| 88 | |||
| 89 | Direct operations. | ||
| 90 | |||
| 91 | You will find a lot of of redisplay optimizations when you start | ||
| 92 | looking at the innards of redisplay. The overall goal of all these | ||
| 93 | optimizations is to make redisplay fast because it is done | ||
| 94 | frequently. | ||
| 95 | |||
| 96 | Two optimizations are not found in xdisp.c. These are the direct | ||
| 97 | operations mentioned above. As the name suggests they follow a | ||
| 98 | different principle than the rest of redisplay. Instead of | ||
| 99 | building a desired matrix and then comparing it with the current | ||
| 100 | display, they perform their actions directly on the display and on | ||
| 101 | the current matrix. | ||
| 102 | |||
| 103 | One direct operation updates the display after one character has | ||
| 104 | been entered. The other one moves the cursor by one position | ||
| 105 | forward or backward. You find these functions under the names | ||
| 106 | `direct_output_for_insert' and `direct_output_forward_char' in | ||
| 107 | dispnew.c. | ||
| 108 | |||
| 109 | |||
| 110 | Desired matrices. | ||
| 111 | |||
| 112 | Desired matrices are always built per Emacs window. The function | ||
| 113 | `display_line' is the central function to look at if you are | ||
| 114 | interested. It constructs one row in a desired matrix given an | ||
| 115 | iterator structure containing both a buffer position and a | ||
| 116 | description of the environment in which the text is to be | ||
| 117 | displayed. But this is too early, read on. | ||
| 118 | |||
| 119 | Characters and pixmaps displayed for a range of buffer text depend | ||
| 120 | on various settings of buffers and windows, on overlays and text | ||
| 121 | properties, on display tables, on selective display. The good news | ||
| 122 | is that all this hairy stuff is hidden behind a small set of | ||
| 123 | interface functions taking a iterator structure (struct it) | ||
| 124 | argument. | ||
| 125 | |||
| 126 | Iteration over things to be be displayed is then simple. It is | ||
| 127 | started by initializing an iterator with a call to init_iterator | ||
| 128 | (or init_string_iterator for that matter). Calls to | ||
| 129 | get_next_display_element fill the iterator structure with relevant | ||
| 130 | information about the next thing to display. Calls to | ||
| 131 | set_iterator_to_next move the iterator to the next thing. | ||
| 132 | |||
| 133 | Besides this, an iterator also contains information about the | ||
| 134 | display environment in which glyphs for display elements are to be | ||
| 135 | produced. It has fields for the width and height of the display, | ||
| 136 | the information whether long lines are truncated or continued, a | ||
| 137 | current X and Y position, and lots of other stuff you can better | ||
| 138 | see in dispextern.h. | ||
| 139 | |||
| 140 | Glyphs in a desired matrix are normally constructed in a loop | ||
| 141 | calling get_next_display_element and then produce_glyphs. The call | ||
| 142 | to produce_glyphs will fill the iterator structure with pixel | ||
| 143 | information about the element being displayed and at the same time | ||
| 144 | produce glyphs for it. If the display element fits on the line | ||
| 145 | being displayed, set_iterator_to_next is called next, otherwise the | ||
| 146 | glyphs produced are discarded. | ||
| 147 | |||
| 148 | |||
| 149 | Frame matrices. | ||
| 150 | |||
| 151 | That just couldn't be all, could it? What about terminal types not | ||
| 152 | supporting operations on sub-windows of the screen? To update the | ||
| 153 | display on such a terminal, window-based glyph matrices are not | ||
| 154 | well suited. To be able to reuse part of the display (scrolling | ||
| 155 | lines up and down), we must instead have a view of the whole | ||
| 156 | screen. This is what `frame matrices' are for. They are a trick. | ||
| 157 | |||
| 158 | Frames on terminals like above have a glyph pool. Windows on such | ||
| 159 | a frame sub-allocate their glyph memory from their frame's glyph | ||
| 160 | pool. The frame itself is given its own glyph matrices. By | ||
| 161 | coincidence---or maybe something else---rows in window glyph | ||
| 162 | matrices are slices of corresponding rows in frame matrices. Thus | ||
| 163 | writing to window matrices implicitly updates a frame matrix which | ||
| 164 | provides us with the view of the whole screen that we originally | ||
| 165 | wanted to have without having to move many bytes around. To be | ||
| 166 | honest, there is a little bit more done, but not much more. If you | ||
| 167 | plan to extend that code, take a look at dispnew.c. The function | ||
| 168 | build_frame_matrix is a good starting point. */ | ||
| 22 | 169 | ||
| 23 | #include <config.h> | 170 | #include <config.h> |
| 24 | #include <stdio.h> | 171 | #include <stdio.h> |
| 25 | /*#include <ctype.h>*/ | 172 | #ifdef STDC_HEADERS |
| 26 | #undef NULL | 173 | #include <stdlib.h> |
| 174 | #endif | ||
| 27 | #include "lisp.h" | 175 | #include "lisp.h" |
| 28 | #include "frame.h" | 176 | #include "frame.h" |
| 29 | #include "window.h" | 177 | #include "window.h" |
| @@ -46,6 +194,11 @@ Boston, MA 02111-1307, USA. */ | |||
| 46 | #include "xterm.h" | 194 | #include "xterm.h" |
| 47 | #endif | 195 | #endif |
| 48 | 196 | ||
| 197 | #define min(a, b) ((a) < (b) ? (a) : (b)) | ||
| 198 | #define max(a, b) ((a) > (b) ? (a) : (b)) | ||
| 199 | |||
| 200 | #define INFINITY 10000000 | ||
| 201 | |||
| 49 | #if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) | 202 | #if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) |
| 50 | extern void set_frame_menubar (); | 203 | extern void set_frame_menubar (); |
| 51 | extern int pending_menu_activation; | 204 | extern int pending_menu_activation; |
| @@ -60,222 +213,4333 @@ extern Lisp_Object Qface; | |||
| 60 | 213 | ||
| 61 | extern Lisp_Object Voverriding_local_map; | 214 | extern Lisp_Object Voverriding_local_map; |
| 62 | extern Lisp_Object Voverriding_local_map_menu_flag; | 215 | extern Lisp_Object Voverriding_local_map_menu_flag; |
| 216 | extern Lisp_Object Qmenu_item; | ||
| 63 | 217 | ||
| 64 | Lisp_Object Qoverriding_local_map, Qoverriding_terminal_local_map; | 218 | Lisp_Object Qoverriding_local_map, Qoverriding_terminal_local_map; |
| 65 | Lisp_Object Qwindow_scroll_functions, Vwindow_scroll_functions; | 219 | Lisp_Object Qwindow_scroll_functions, Vwindow_scroll_functions; |
| 66 | Lisp_Object Qredisplay_end_trigger_functions; | 220 | Lisp_Object Qredisplay_end_trigger_functions; |
| 67 | Lisp_Object Qinhibit_point_motion_hooks; | 221 | Lisp_Object Qinhibit_point_motion_hooks; |
| 222 | Lisp_Object QCeval, QCwhen; | ||
| 223 | Lisp_Object Qfontified; | ||
| 224 | |||
| 225 | /* Functions called to fontify regions of text. */ | ||
| 226 | |||
| 227 | Lisp_Object Vfontification_functions; | ||
| 228 | Lisp_Object Qfontification_functions; | ||
| 229 | |||
| 230 | /* Non-zero means draw toolbar buttons raised when the mouse moves | ||
| 231 | over them. */ | ||
| 232 | |||
| 233 | int auto_raise_toolbar_buttons_p; | ||
| 234 | |||
| 235 | /* Margin around toolbar buttons in pixels. */ | ||
| 236 | |||
| 237 | int toolbar_button_margin; | ||
| 238 | |||
| 239 | /* Thickness of shadow to draw around toolbar buttons. */ | ||
| 240 | |||
| 241 | int toolbar_button_relief; | ||
| 242 | |||
| 243 | /* Non-zero means automatically resize toolbars so that all toolbar | ||
| 244 | items are visible, and no blank lines remain. */ | ||
| 245 | |||
| 246 | int auto_resize_toolbars_p; | ||
| 68 | 247 | ||
| 69 | /* Non-nil means don't actually do any redisplay. */ | 248 | /* Non-nil means don't actually do any redisplay. */ |
| 70 | 249 | ||
| 71 | Lisp_Object Vinhibit_redisplay, Qinhibit_redisplay; | 250 | Lisp_Object Vinhibit_redisplay, Qinhibit_redisplay; |
| 72 | 251 | ||
| 73 | /* Nonzero means print newline to stdout before next minibuffer message. */ | 252 | /* Names of text properties relevant for redisplay. */ |
| 253 | |||
| 254 | Lisp_Object Qdisplay, Qrelative_width, Qwidth, Qalign_to; | ||
| 255 | extern Lisp_Object Qface, Qinvisible, Qimage; | ||
| 256 | |||
| 257 | /* Symbols used in text property values. */ | ||
| 258 | |||
| 259 | Lisp_Object Qspace, QCalign_to, QCrelative_width, QCrelative_height; | ||
| 260 | Lisp_Object Qleft_margin, Qright_margin, Qspace_width, Qheight, Qraise; | ||
| 261 | |||
| 262 | /* Name of the variable controlling the highlighting of trailing | ||
| 263 | whitespace. The implementation uses find_symbol_value to get its | ||
| 264 | value. */ | ||
| 265 | |||
| 266 | Lisp_Object Qshow_trailing_whitespace; | ||
| 267 | |||
| 268 | /* Name of the face used to highlight trailing whitespace. */ | ||
| 269 | |||
| 270 | Lisp_Object Qtrailing_whitespace; | ||
| 271 | |||
| 272 | /* The symbol `image' which is the car of the lists used to represent | ||
| 273 | images in Lisp. */ | ||
| 274 | |||
| 275 | Lisp_Object Qimage; | ||
| 276 | |||
| 277 | /* Non-zero means print newline to stdout before next mini-buffer | ||
| 278 | message. */ | ||
| 74 | 279 | ||
| 75 | int noninteractive_need_newline; | 280 | int noninteractive_need_newline; |
| 76 | 281 | ||
| 77 | /* Nonzero means print newline to message log before next message. */ | 282 | /* Non-zero means print newline to message log before next message. */ |
| 78 | 283 | ||
| 79 | static int message_log_need_newline; | 284 | static int message_log_need_newline; |
| 80 | 285 | ||
| 81 | #define min(a, b) ((a) < (b) ? (a) : (b)) | 286 | |
| 82 | #define max(a, b) ((a) > (b) ? (a) : (b)) | 287 | /* The buffer position of the first character appearing entirely or |
| 83 | #define minmax(floor, val, ceil) \ | 288 | partially on the line of the selected window which contains the |
| 84 | ((val) < (floor) ? (floor) : (val) > (ceil) ? (ceil) : (val)) | 289 | cursor; <= 0 if not known. Set by set_cursor_from_row, used for |
| 290 | redisplay optimization in redisplay_internal. */ | ||
| 291 | |||
| 292 | static struct text_pos this_line_start_pos; | ||
| 293 | |||
| 294 | /* Number of characters past the end of the line above, including the | ||
| 295 | terminating newline. */ | ||
| 85 | 296 | ||
| 86 | /* The buffer position of the first character appearing | 297 | static struct text_pos this_line_end_pos; |
| 87 | entirely or partially on the current frame line. | ||
| 88 | Or zero, which disables the optimization for the current frame line. */ | ||
| 89 | static int this_line_bufpos; | ||
| 90 | 298 | ||
| 91 | /* Number of characters past the end of this line, | 299 | /* The vertical positions and the height of this line. */ |
| 92 | including the terminating newline */ | ||
| 93 | static int this_line_endpos; | ||
| 94 | 300 | ||
| 95 | /* The vertical position of this frame line. */ | ||
| 96 | static int this_line_vpos; | 301 | static int this_line_vpos; |
| 302 | static int this_line_y; | ||
| 303 | static int this_line_pixel_height; | ||
| 97 | 304 | ||
| 98 | /* Hpos value for start of display on this frame line. | 305 | /* X position at which this display line starts. Usually zero; |
| 99 | Usually zero, but negative if first character really began | 306 | negative if first character is partially visible. */ |
| 100 | on previous line */ | 307 | |
| 101 | static int this_line_start_hpos; | 308 | static int this_line_start_x; |
| 309 | |||
| 310 | /* Buffer that this_line_.* variables are referring to. */ | ||
| 102 | 311 | ||
| 103 | /* Buffer that this_line variables are describing. */ | ||
| 104 | static struct buffer *this_line_buffer; | 312 | static struct buffer *this_line_buffer; |
| 105 | 313 | ||
| 106 | /* Value of echo_area_glyphs when it was last acted on. | 314 | /* Nonzero means truncate lines in all windows less wide than the |
| 107 | If this is nonzero, there is a message on the frame | 315 | frame. */ |
| 108 | in the minibuffer and it should be erased as soon | ||
| 109 | as it is no longer requested to appear. */ | ||
| 110 | char *previous_echo_glyphs; | ||
| 111 | 316 | ||
| 112 | /* Nonzero means truncate lines in all windows less wide than the frame */ | ||
| 113 | int truncate_partial_width_windows; | 317 | int truncate_partial_width_windows; |
| 114 | 318 | ||
| 115 | /* A flag to control how to display unibyte 8-bit character. */ | 319 | /* A flag to control how to display unibyte 8-bit character. */ |
| 320 | |||
| 116 | int unibyte_display_via_language_environment; | 321 | int unibyte_display_via_language_environment; |
| 322 | |||
| 323 | /* Nonzero means we have more than one non-mini-buffer-only frame. | ||
| 324 | Not guaranteed to be accurate except while parsing | ||
| 325 | frame-title-format. */ | ||
| 117 | 326 | ||
| 118 | /* Nonzero means we have more than one non-minibuffer-only frame. | ||
| 119 | Not guaranteed to be accurate except while parsing frame-title-format. */ | ||
| 120 | int multiple_frames; | 327 | int multiple_frames; |
| 121 | 328 | ||
| 122 | Lisp_Object Vglobal_mode_string; | 329 | Lisp_Object Vglobal_mode_string; |
| 123 | 330 | ||
| 124 | /* Marker for where to display an arrow on top of the buffer text. */ | 331 | /* Marker for where to display an arrow on top of the buffer text. */ |
| 332 | |||
| 125 | Lisp_Object Voverlay_arrow_position; | 333 | Lisp_Object Voverlay_arrow_position; |
| 126 | 334 | ||
| 127 | /* String to display for the arrow. */ | 335 | /* String to display for the arrow. Only used on terminal frames. */ |
| 336 | |||
| 128 | Lisp_Object Voverlay_arrow_string; | 337 | Lisp_Object Voverlay_arrow_string; |
| 129 | 338 | ||
| 130 | /* Values of those variables at last redisplay. | 339 | /* Values of those variables at last redisplay. However, if |
| 131 | However, if Voverlay_arrow_position is a marker, | 340 | Voverlay_arrow_position is a marker, last_arrow_position is its |
| 132 | last_arrow_position is its numerical position. */ | 341 | numerical position. */ |
| 342 | |||
| 133 | static Lisp_Object last_arrow_position, last_arrow_string; | 343 | static Lisp_Object last_arrow_position, last_arrow_string; |
| 134 | 344 | ||
| 135 | /* Like mode-line-format, but for the titlebar on a visible frame. */ | 345 | /* Like mode-line-format, but for the title bar on a visible frame. */ |
| 346 | |||
| 136 | Lisp_Object Vframe_title_format; | 347 | Lisp_Object Vframe_title_format; |
| 137 | 348 | ||
| 138 | /* Like mode-line-format, but for the titlebar on an iconified frame. */ | 349 | /* Like mode-line-format, but for the title bar on an iconified frame. */ |
| 350 | |||
| 139 | Lisp_Object Vicon_title_format; | 351 | Lisp_Object Vicon_title_format; |
| 140 | 352 | ||
| 141 | /* List of functions to call when a window's size changes. These | 353 | /* List of functions to call when a window's size changes. These |
| 142 | functions get one arg, a frame on which one or more windows' sizes | 354 | functions get one arg, a frame on which one or more windows' sizes |
| 143 | have changed. */ | 355 | have changed. */ |
| 356 | |||
| 144 | static Lisp_Object Vwindow_size_change_functions; | 357 | static Lisp_Object Vwindow_size_change_functions; |
| 145 | 358 | ||
| 146 | Lisp_Object Qmenu_bar_update_hook; | 359 | Lisp_Object Qmenu_bar_update_hook; |
| 147 | 360 | ||
| 148 | /* Nonzero if overlay arrow has been displayed once in this window. */ | 361 | /* Nonzero if overlay arrow has been displayed once in this window. */ |
| 149 | static int overlay_arrow_seen; | ||
| 150 | 362 | ||
| 151 | /* Nonzero if visible end of buffer has already been displayed once | 363 | static int overlay_arrow_seen; |
| 152 | in this window. (We need this variable in case there are overlay | ||
| 153 | strings that get displayed there.) */ | ||
| 154 | static int zv_strings_seen; | ||
| 155 | 364 | ||
| 156 | /* Nonzero means highlight the region even in nonselected windows. */ | 365 | /* Nonzero means highlight the region even in nonselected windows. */ |
| 157 | static int highlight_nonselected_windows; | ||
| 158 | 366 | ||
| 159 | /* If cursor motion alone moves point off frame, | 367 | int highlight_nonselected_windows; |
| 160 | Try scrolling this many lines up or down if that will bring it back. */ | 368 | |
| 369 | /* If cursor motion alone moves point off frame, try scrolling this | ||
| 370 | many lines up or down if that will bring it back. */ | ||
| 371 | |||
| 161 | static int scroll_step; | 372 | static int scroll_step; |
| 162 | 373 | ||
| 163 | /* Non-0 means scroll just far enough to bring point back on the screen, | 374 | /* Non-0 means scroll just far enough to bring point back on the |
| 164 | when appropriate. */ | 375 | screen, when appropriate. */ |
| 376 | |||
| 165 | static int scroll_conservatively; | 377 | static int scroll_conservatively; |
| 166 | 378 | ||
| 167 | /* Recenter the window whenever point gets within this many lines | 379 | /* Recenter the window whenever point gets within this many lines of |
| 168 | of the top or bottom of the window. */ | 380 | the top or bottom of the window. This value is translated into a |
| 381 | pixel value by multiplying it with CANON_Y_UNIT, which means that | ||
| 382 | there is really a fixed pixel height scroll margin. */ | ||
| 383 | |||
| 169 | int scroll_margin; | 384 | int scroll_margin; |
| 170 | 385 | ||
| 171 | /* Number of characters of overlap to show, | 386 | /* Number of characters of overlap to show, when scrolling a one-line |
| 172 | when scrolling a one-line window such as a minibuffer. */ | 387 | window such as a minibuffer. */ |
| 388 | |||
| 173 | static int minibuffer_scroll_overlap; | 389 | static int minibuffer_scroll_overlap; |
| 174 | 390 | ||
| 175 | /* Nonzero if try_window_id has made blank lines at window bottom | 391 | /* Number of windows showing the buffer of the selected window (or |
| 176 | since the last redisplay that paused */ | 392 | another buffer with the same base buffer). keyboard.c refers to |
| 177 | static int blank_end_of_window; | 393 | this. */ |
| 178 | 394 | ||
| 179 | /* Number of windows showing the buffer of the selected window | ||
| 180 | (or another buffer with the same base buffer). | ||
| 181 | keyboard.c refers to this. */ | ||
| 182 | int buffer_shared; | 395 | int buffer_shared; |
| 183 | 396 | ||
| 184 | /* display_text_line sets these to the frame position (origin 0) of point, | 397 | /* Vector containing glyphs for an ellipsis `...'. */ |
| 185 | whether the window is selected or not. | ||
| 186 | Set one to -1 first to determine whether point was found afterwards. */ | ||
| 187 | 398 | ||
| 188 | static int cursor_vpos; | 399 | static Lisp_Object default_invis_vector[3]; |
| 189 | static int cursor_hpos; | ||
| 190 | 400 | ||
| 191 | static int debug_end_pos; | 401 | /* Nonzero means display mode line highlighted. */ |
| 192 | 402 | ||
| 193 | /* Nonzero means display mode line highlighted */ | ||
| 194 | int mode_line_inverse_video; | 403 | int mode_line_inverse_video; |
| 195 | 404 | ||
| 196 | static void redisplay_internal (); | 405 | /* Prompt to display in front of the mini-buffer contents. */ |
| 197 | static int message_log_check_duplicate (); | 406 | |
| 198 | static void echo_area_display (); | ||
| 199 | void mark_window_display_accurate (); | ||
| 200 | static void redisplay_windows (); | ||
| 201 | static void redisplay_window (); | ||
| 202 | static void update_menu_bar (); | ||
| 203 | static void try_window (); | ||
| 204 | static int try_window_id (); | ||
| 205 | static struct position *display_text_line (); | ||
| 206 | static void display_mode_line (); | ||
| 207 | static int display_mode_element (); | ||
| 208 | static char *decode_mode_spec (); | ||
| 209 | static int display_string (); | ||
| 210 | static void display_menu_bar (); | ||
| 211 | static int display_count_lines (); | ||
| 212 | |||
| 213 | /* Prompt to display in front of the minibuffer contents */ | ||
| 214 | Lisp_Object minibuf_prompt; | 407 | Lisp_Object minibuf_prompt; |
| 215 | 408 | ||
| 216 | /* Width in columns of current minibuffer prompt. */ | 409 | /* Width of current mini-buffer prompt. Only set after display_line |
| 410 | of the line that contains the prompt. */ | ||
| 411 | |||
| 217 | int minibuf_prompt_width; | 412 | int minibuf_prompt_width; |
| 413 | int minibuf_prompt_pixel_width; | ||
| 414 | |||
| 415 | /* Message to display instead of mini-buffer contents. This is what | ||
| 416 | the functions error and message make, and command echoing uses it | ||
| 417 | as well. It overrides the minibuf_prompt as well as the buffer. */ | ||
| 218 | 418 | ||
| 219 | /* Message to display instead of minibuffer contents | ||
| 220 | This is what the functions error and message make, | ||
| 221 | and command echoing uses it as well. | ||
| 222 | It overrides the minibuf_prompt as well as the buffer. */ | ||
| 223 | char *echo_area_glyphs; | 419 | char *echo_area_glyphs; |
| 224 | 420 | ||
| 225 | /* This is the length of the message in echo_area_glyphs. */ | 421 | /* A Lisp string to display instead of mini-buffer contents, analogous |
| 422 | to echo_area_glyphs. If this is a string, display that string. | ||
| 423 | Otherwise, if echo_area_glyphs is non-null, display that. */ | ||
| 424 | |||
| 425 | Lisp_Object echo_area_message; | ||
| 426 | |||
| 427 | /* This is the length of the message in echo_area_glyphs or | ||
| 428 | echo_area_message. */ | ||
| 429 | |||
| 226 | int echo_area_glyphs_length; | 430 | int echo_area_glyphs_length; |
| 227 | 431 | ||
| 228 | /* This is the window where the echo area message was displayed. | 432 | /* Value of echo_area_glyphs when it was last acted on. If this is |
| 229 | It is always a minibuffer window, but it may not be the | 433 | nonzero, there is a message on the frame in the mini-buffer and it |
| 230 | same window currently active as a minibuffer. */ | 434 | should be erased as soon as it is no longer requested to appear. */ |
| 435 | |||
| 436 | char *previous_echo_glyphs; | ||
| 437 | Lisp_Object previous_echo_area_message; | ||
| 438 | static int previous_echo_glyphs_length; | ||
| 439 | |||
| 440 | /* This is the window where the echo area message was displayed. It | ||
| 441 | is always a mini-buffer window, but it may not be the same window | ||
| 442 | currently active as a mini-buffer. */ | ||
| 443 | |||
| 231 | Lisp_Object echo_area_window; | 444 | Lisp_Object echo_area_window; |
| 232 | 445 | ||
| 233 | /* Nonzero means multibyte characters were enabled when the echo area | 446 | /* Nonzero means multibyte characters were enabled when the echo area |
| 234 | message was specified. */ | 447 | message was specified. */ |
| 448 | |||
| 235 | int message_enable_multibyte; | 449 | int message_enable_multibyte; |
| 236 | 450 | ||
| 237 | /* true iff we should redraw the mode lines on the next redisplay */ | 451 | /* True if we should redraw the mode lines on the next redisplay. */ |
| 452 | |||
| 238 | int update_mode_lines; | 453 | int update_mode_lines; |
| 239 | 454 | ||
| 240 | /* Smallest number of characters before the gap | 455 | /* Smallest number of characters before the gap at any time since last |
| 241 | at any time since last redisplay that finished. | 456 | redisplay that finished. Valid for current buffer when |
| 242 | Valid for current buffer when try_window_id can be called. */ | 457 | try_window_id can be called. */ |
| 458 | |||
| 243 | int beg_unchanged; | 459 | int beg_unchanged; |
| 244 | 460 | ||
| 245 | /* Smallest number of characters after the gap | 461 | /* Smallest number of characters after the gap at any time since last |
| 246 | at any time since last redisplay that finished. | 462 | redisplay that finished. Valid for current buffer when |
| 247 | Valid for current buffer when try_window_id can be called. */ | 463 | try_window_id can be called. */ |
| 464 | |||
| 248 | int end_unchanged; | 465 | int end_unchanged; |
| 249 | 466 | ||
| 250 | /* MODIFF as of last redisplay that finished; | 467 | /* MODIFF as of last redisplay that finished; if it matches MODIFF, |
| 251 | if it matches MODIFF, and overlay_unchanged_modified | 468 | and overlay_unchanged_modified matches OVERLAY_MODIFF, that means |
| 252 | matches OVERLAY_MODIFF, that means beg_unchanged and end_unchanged | 469 | beg_unchanged and end_unchanged contain no useful information. */ |
| 253 | contain no useful information */ | 470 | |
| 254 | int unchanged_modified; | 471 | int unchanged_modified; |
| 255 | 472 | ||
| 256 | /* OVERLAY_MODIFF as of last redisplay that finished. */ | 473 | /* OVERLAY_MODIFF as of last redisplay that finished. */ |
| 474 | |||
| 257 | int overlay_unchanged_modified; | 475 | int overlay_unchanged_modified; |
| 258 | 476 | ||
| 259 | /* Nonzero if window sizes or contents have changed | 477 | /* Nonzero if window sizes or contents have changed since last |
| 260 | since last redisplay that finished */ | 478 | redisplay that finished */ |
| 479 | |||
| 261 | int windows_or_buffers_changed; | 480 | int windows_or_buffers_changed; |
| 262 | 481 | ||
| 263 | /* Nonzero after display_mode_line if %l was used | 482 | /* Nonzero after display_mode_line if %l was used and it displayed a |
| 264 | and it displayed a line number. */ | 483 | line number. */ |
| 484 | |||
| 265 | int line_number_displayed; | 485 | int line_number_displayed; |
| 266 | 486 | ||
| 267 | /* Maximum buffer size for which to display line numbers. */ | 487 | /* Maximum buffer size for which to display line numbers. */ |
| 488 | |||
| 268 | static int line_number_display_limit; | 489 | static int line_number_display_limit; |
| 269 | 490 | ||
| 270 | /* Number of lines to keep in the message log buffer. | 491 | /* Number of lines to keep in the message log buffer. t means |
| 271 | t means infinite. nil means don't log at all. */ | 492 | infinite. nil means don't log at all. */ |
| 493 | |||
| 272 | Lisp_Object Vmessage_log_max; | 494 | Lisp_Object Vmessage_log_max; |
| 273 | 495 | ||
| 274 | #define COERCE_MARKER(X) \ | 496 | /* A scratch glyph row with contents used for generating truncation |
| 275 | (MARKERP ((X)) ? Fmarker_position (X) : (X)) | 497 | glyphs. Also used in direct_output_for_insert. */ |
| 498 | |||
| 499 | #define MAX_SCRATCH_GLYPHS 100 | ||
| 500 | struct glyph_row scratch_glyph_row; | ||
| 501 | static struct glyph scratch_glyphs[MAX_SCRATCH_GLYPHS]; | ||
| 502 | |||
| 503 | /* Ascent and height of the last line processed by move_it_to. */ | ||
| 504 | |||
| 505 | static int last_max_ascent, last_height; | ||
| 506 | |||
| 507 | /* The maximum distance to look ahead for text properties. Values | ||
| 508 | that are too small let us call compute_char_face and similar | ||
| 509 | functions too often which is expensive. Values that are too large | ||
| 510 | let us call compute_char_face and alike too often because we | ||
| 511 | might not be interested in text properties that far away. */ | ||
| 512 | |||
| 513 | #define TEXT_PROP_DISTANCE_LIMIT 100 | ||
| 514 | |||
| 515 | /* Non-zero means print traces of redisplay if compiled with | ||
| 516 | GLYPH_DEBUG != 0. */ | ||
| 517 | |||
| 518 | #if GLYPH_DEBUG | ||
| 519 | int trace_redisplay_p; | ||
| 520 | #endif | ||
| 521 | |||
| 522 | /* Value returned from text property handlers (see below). */ | ||
| 523 | |||
| 524 | enum prop_handled | ||
| 525 | { | ||
| 526 | HANDLED_NORMALLY, | ||
| 527 | HANDLED_RECOMPUTE_PROPS, | ||
| 528 | HANDLED_OVERLAY_STRING_CONSUMED, | ||
| 529 | HANDLED_RETURN | ||
| 530 | }; | ||
| 531 | |||
| 532 | /* A description of text properties that redisplay is interested | ||
| 533 | in. */ | ||
| 534 | |||
| 535 | struct props | ||
| 536 | { | ||
| 537 | /* The name of the property. */ | ||
| 538 | Lisp_Object *name; | ||
| 539 | |||
| 540 | /* A unique index for the property. */ | ||
| 541 | enum prop_idx idx; | ||
| 542 | |||
| 543 | /* A handler function called to set up iterator IT from the property | ||
| 544 | at IT's current position. Value is used to steer handle_stop. */ | ||
| 545 | enum prop_handled (*handler) P_ ((struct it *it)); | ||
| 546 | }; | ||
| 547 | |||
| 548 | static enum prop_handled handle_face_prop P_ ((struct it *)); | ||
| 549 | static enum prop_handled handle_invisible_prop P_ ((struct it *)); | ||
| 550 | static enum prop_handled handle_display_prop P_ ((struct it *)); | ||
| 551 | static enum prop_handled handle_overlay_change P_ ((struct it *)); | ||
| 552 | static enum prop_handled handle_fontified_prop P_ ((struct it *)); | ||
| 553 | |||
| 554 | /* Properties handled by iterators. */ | ||
| 555 | |||
| 556 | static struct props it_props[] = | ||
| 557 | { | ||
| 558 | {&Qfontified, FONTIFIED_PROP_IDX, handle_fontified_prop}, | ||
| 559 | /* Handle `face' before `display' because some sub-properties of | ||
| 560 | `display' need to know the face. */ | ||
| 561 | {&Qface, FACE_PROP_IDX, handle_face_prop}, | ||
| 562 | {&Qdisplay, DISPLAY_PROP_IDX, handle_display_prop}, | ||
| 563 | {&Qinvisible, INVISIBLE_PROP_IDX, handle_invisible_prop}, | ||
| 564 | {NULL, 0, NULL} | ||
| 565 | }; | ||
| 566 | |||
| 567 | /* Value is the position described by X. If X is a marker, value is | ||
| 568 | the marker_position of X. Otherwise, value is X. */ | ||
| 569 | |||
| 570 | #define COERCE_MARKER(X) (MARKERP ((X)) ? Fmarker_position (X) : (X)) | ||
| 571 | |||
| 572 | /* Enumeration returned by some move_it_.* functions internally. */ | ||
| 573 | |||
| 574 | enum move_it_result | ||
| 575 | { | ||
| 576 | /* Not used. Undefined value. */ | ||
| 577 | MOVE_UNDEFINED, | ||
| 578 | |||
| 579 | /* Move ended at the requested buffer position or ZV. */ | ||
| 580 | MOVE_POS_MATCH_OR_ZV, | ||
| 581 | |||
| 582 | /* Move ended at the requested X pixel position. */ | ||
| 583 | MOVE_X_REACHED, | ||
| 584 | |||
| 585 | /* Move within a line ended at the end of a line that must be | ||
| 586 | continued. */ | ||
| 587 | MOVE_LINE_CONTINUED, | ||
| 588 | |||
| 589 | /* Move within a line ended at the end of a line that would | ||
| 590 | be displayed truncated. */ | ||
| 591 | MOVE_LINE_TRUNCATED, | ||
| 592 | |||
| 593 | /* Move within a line ended at a line end. */ | ||
| 594 | MOVE_NEWLINE_OR_CR | ||
| 595 | }; | ||
| 596 | |||
| 597 | |||
| 598 | |||
| 599 | /* Function prototypes. */ | ||
| 600 | |||
| 601 | static struct text_pos display_prop_end P_ ((struct it *, Lisp_Object, | ||
| 602 | struct text_pos)); | ||
| 603 | static int compute_window_start_on_continuation_line P_ ((struct window *)); | ||
| 604 | static Lisp_Object eval_handler P_ ((Lisp_Object)); | ||
| 605 | static Lisp_Object eval_form P_ ((Lisp_Object)); | ||
| 606 | static void insert_left_trunc_glyphs P_ ((struct it *)); | ||
| 607 | static struct glyph_row *get_overlay_arrow_glyph_row P_ ((struct window *)); | ||
| 608 | static void extend_face_to_end_of_line P_ ((struct it *)); | ||
| 609 | static void append_space P_ ((struct it *, int)); | ||
| 610 | static void make_cursor_line_fully_visible P_ ((struct window *)); | ||
| 611 | static int try_scrolling P_ ((Lisp_Object, int, int, int, int)); | ||
| 612 | static int trailing_whitespace_p P_ ((int)); | ||
| 613 | static int message_log_check_duplicate P_ ((int, int, int, int)); | ||
| 614 | int invisible_p P_ ((Lisp_Object, Lisp_Object)); | ||
| 615 | int invisible_ellipsis_p P_ ((Lisp_Object, Lisp_Object)); | ||
| 616 | static void push_it P_ ((struct it *)); | ||
| 617 | static void pop_it P_ ((struct it *)); | ||
| 618 | static void sync_frame_with_window_matrix_rows P_ ((struct window *)); | ||
| 619 | static void redisplay_internal P_ ((int)); | ||
| 620 | static void echo_area_display P_ ((int)); | ||
| 621 | static void redisplay_windows P_ ((Lisp_Object)); | ||
| 622 | static void redisplay_window P_ ((Lisp_Object, int)); | ||
| 623 | static void update_menu_bar P_ ((struct frame *, int)); | ||
| 624 | static int try_window_reusing_current_matrix P_ ((struct window *)); | ||
| 625 | static int try_window_id P_ ((struct window *)); | ||
| 626 | static int display_line P_ ((struct it *)); | ||
| 627 | static void display_mode_lines P_ ((struct window *)); | ||
| 628 | static void display_mode_line P_ ((struct window *, enum face_id, | ||
| 629 | Lisp_Object)); | ||
| 630 | static int display_mode_element P_ ((struct it *, int, int, int, Lisp_Object)); | ||
| 631 | static char *decode_mode_spec P_ ((struct window *, char, int, int)); | ||
| 632 | static void display_menu_bar P_ ((struct window *)); | ||
| 633 | static int display_count_lines P_ ((int, int, int, int, int *)); | ||
| 634 | static int display_string P_ ((unsigned char *, Lisp_Object, Lisp_Object, | ||
| 635 | int, int, struct it *, int, int, int, int)); | ||
| 636 | static void compute_line_metrics P_ ((struct it *)); | ||
| 637 | static void run_redisplay_end_trigger_hook P_ ((struct it *)); | ||
| 638 | static int get_overlay_strings P_ ((struct it *)); | ||
| 639 | static void next_overlay_string P_ ((struct it *)); | ||
| 640 | void set_iterator_to_next P_ ((struct it *)); | ||
| 641 | static void reseat P_ ((struct it *, struct text_pos, int)); | ||
| 642 | static void reseat_1 P_ ((struct it *, struct text_pos, int)); | ||
| 643 | static void back_to_previous_visible_line_start P_ ((struct it *)); | ||
| 644 | static void reseat_at_previous_visible_line_start P_ ((struct it *)); | ||
| 645 | static int next_element_from_display_vector P_ ((struct it *)); | ||
| 646 | static int next_element_from_string P_ ((struct it *)); | ||
| 647 | static int next_element_from_c_string P_ ((struct it *)); | ||
| 648 | static int next_element_from_buffer P_ ((struct it *)); | ||
| 649 | static int next_element_from_image P_ ((struct it *)); | ||
| 650 | static int next_element_from_stretch P_ ((struct it *)); | ||
| 651 | static void load_overlay_strings P_ ((struct it *)); | ||
| 652 | static void init_from_display_pos P_ ((struct it *, struct window *, | ||
| 653 | struct display_pos *)); | ||
| 654 | static void reseat_to_string P_ ((struct it *, unsigned char *, | ||
| 655 | Lisp_Object, int, int, int, int)); | ||
| 656 | static int charset_at_position P_ ((struct text_pos)); | ||
| 657 | static enum move_it_result move_it_in_display_line_to P_ ((struct it *, | ||
| 658 | int, int, int)); | ||
| 659 | void move_it_vertically_backward P_ ((struct it *, int)); | ||
| 660 | static void init_to_row_start P_ ((struct it *, struct window *, | ||
| 661 | struct glyph_row *)); | ||
| 662 | static void init_to_row_end P_ ((struct it *, struct window *, | ||
| 663 | struct glyph_row *)); | ||
| 664 | static void back_to_previous_line_start P_ ((struct it *)); | ||
| 665 | static void forward_to_next_line_start P_ ((struct it *)); | ||
| 666 | static struct text_pos string_pos_nchars_ahead P_ ((struct text_pos, | ||
| 667 | Lisp_Object, int)); | ||
| 668 | static struct text_pos string_pos P_ ((int, Lisp_Object)); | ||
| 669 | static struct text_pos c_string_pos P_ ((int, unsigned char *, int)); | ||
| 670 | static int number_of_chars P_ ((unsigned char *, int)); | ||
| 671 | static void compute_stop_pos P_ ((struct it *)); | ||
| 672 | static void compute_string_pos P_ ((struct text_pos *, struct text_pos, | ||
| 673 | Lisp_Object)); | ||
| 674 | static int face_before_or_after_it_pos P_ ((struct it *, int)); | ||
| 675 | static int next_overlay_change P_ ((int)); | ||
| 676 | static int handle_single_display_prop P_ ((struct it *, Lisp_Object, | ||
| 677 | Lisp_Object, struct text_pos *)); | ||
| 678 | |||
| 679 | #define face_before_it_pos(IT) face_before_or_after_it_pos ((IT), 1) | ||
| 680 | #define face_after_it_pos(IT) face_before_or_after_it_pos ((IT), 0) | ||
| 681 | |||
| 682 | #ifdef HAVE_WINDOW_SYSTEM | ||
| 683 | |||
| 684 | static void update_toolbar P_ ((struct frame *, int)); | ||
| 685 | static void build_desired_toolbar_string P_ ((struct frame *f)); | ||
| 686 | static int redisplay_toolbar P_ ((struct frame *)); | ||
| 687 | static void display_toolbar_line P_ ((struct it *)); | ||
| 688 | |||
| 689 | #endif /* HAVE_WINDOW_SYSTEM */ | ||
| 690 | |||
| 691 | |||
| 692 | /*********************************************************************** | ||
| 693 | Window display dimensions | ||
| 694 | ***********************************************************************/ | ||
| 695 | |||
| 696 | /* Return the window-relative maximum y + 1 for glyph rows displaying | ||
| 697 | text in window W. This is the height of W minus the height of a | ||
| 698 | mode line, if any. */ | ||
| 699 | |||
| 700 | INLINE int | ||
| 701 | window_text_bottom_y (w) | ||
| 702 | struct window *w; | ||
| 703 | { | ||
| 704 | struct frame *f = XFRAME (w->frame); | ||
| 705 | int height = XFASTINT (w->height) * CANON_Y_UNIT (f); | ||
| 706 | |||
| 707 | if (WINDOW_WANTS_MODELINE_P (w)) | ||
| 708 | height -= CURRENT_MODE_LINE_HEIGHT (w); | ||
| 709 | return height; | ||
| 710 | } | ||
| 711 | |||
| 712 | |||
| 713 | /* Return the pixel width of display area AREA of window W. AREA < 0 | ||
| 714 | means return the total width of W, not including bitmap areas to | ||
| 715 | the left and right of the window. */ | ||
| 716 | |||
| 717 | INLINE int | ||
| 718 | window_box_width (w, area) | ||
| 719 | struct window *w; | ||
| 720 | int area; | ||
| 721 | { | ||
| 722 | struct frame *f = XFRAME (w->frame); | ||
| 723 | int width = XFASTINT (w->width); | ||
| 724 | |||
| 725 | if (!w->pseudo_window_p) | ||
| 726 | { | ||
| 727 | width -= FRAME_SCROLL_BAR_WIDTH (f) + 2 * FRAME_FLAGS_AREA_COLS (f); | ||
| 728 | |||
| 729 | if (area == TEXT_AREA) | ||
| 730 | { | ||
| 731 | if (INTEGERP (w->left_margin_width)) | ||
| 732 | width -= XFASTINT (w->left_margin_width); | ||
| 733 | if (INTEGERP (w->right_margin_width)) | ||
| 734 | width -= XFASTINT (w->right_margin_width); | ||
| 735 | } | ||
| 736 | else if (area == LEFT_MARGIN_AREA) | ||
| 737 | width = (INTEGERP (w->left_margin_width) | ||
| 738 | ? XFASTINT (w->left_margin_width) : 0); | ||
| 739 | else if (area == RIGHT_MARGIN_AREA) | ||
| 740 | width = (INTEGERP (w->right_margin_width) | ||
| 741 | ? XFASTINT (w->right_margin_width) : 0); | ||
| 742 | } | ||
| 743 | |||
| 744 | return width * CANON_X_UNIT (f); | ||
| 745 | } | ||
| 746 | |||
| 747 | |||
| 748 | /* Return the pixel height of the display area of window W, not | ||
| 749 | including mode lines of W, if any.. */ | ||
| 750 | |||
| 751 | INLINE int | ||
| 752 | window_box_height (w) | ||
| 753 | struct window *w; | ||
| 754 | { | ||
| 755 | struct frame *f = XFRAME (w->frame); | ||
| 756 | int height = XFASTINT (w->height) * CANON_Y_UNIT (f); | ||
| 757 | |||
| 758 | if (WINDOW_WANTS_MODELINE_P (w)) | ||
| 759 | height -= CURRENT_MODE_LINE_HEIGHT (w); | ||
| 760 | |||
| 761 | if (WINDOW_WANTS_TOP_LINE_P (w)) | ||
| 762 | height -= CURRENT_TOP_LINE_HEIGHT (w); | ||
| 763 | |||
| 764 | return height; | ||
| 765 | } | ||
| 766 | |||
| 767 | |||
| 768 | /* Return the frame-relative coordinate of the left edge of display | ||
| 769 | area AREA of window W. AREA < 0 means return the left edge of the | ||
| 770 | whole window, to the right of any bitmap area at the left side of | ||
| 771 | W. */ | ||
| 772 | |||
| 773 | INLINE int | ||
| 774 | window_box_left (w, area) | ||
| 775 | struct window *w; | ||
| 776 | int area; | ||
| 777 | { | ||
| 778 | struct frame *f = XFRAME (w->frame); | ||
| 779 | int x = FRAME_INTERNAL_BORDER_WIDTH_SAFE (f); | ||
| 780 | |||
| 781 | if (!w->pseudo_window_p) | ||
| 782 | { | ||
| 783 | x += (WINDOW_LEFT_MARGIN (w) * CANON_X_UNIT (f) | ||
| 784 | + FRAME_FLAGS_AREA_WIDTH (f)); | ||
| 785 | |||
| 786 | if (area == TEXT_AREA) | ||
| 787 | x += window_box_width (w, LEFT_MARGIN_AREA); | ||
| 788 | else if (area == RIGHT_MARGIN_AREA) | ||
| 789 | x += (window_box_width (w, LEFT_MARGIN_AREA) | ||
| 790 | + window_box_width (w, TEXT_AREA)); | ||
| 791 | } | ||
| 792 | |||
| 793 | return x; | ||
| 794 | } | ||
| 795 | |||
| 796 | |||
| 797 | /* Return the frame-relative coordinate of the right edge of display | ||
| 798 | area AREA of window W. AREA < 0 means return the left edge of the | ||
| 799 | whole window, to the left of any bitmap area at the right side of | ||
| 800 | W. */ | ||
| 801 | |||
| 802 | INLINE int | ||
| 803 | window_box_right (w, area) | ||
| 804 | struct window *w; | ||
| 805 | int area; | ||
| 806 | { | ||
| 807 | return window_box_left (w, area) + window_box_width (w, area); | ||
| 808 | } | ||
| 809 | |||
| 810 | |||
| 811 | /* Get the bounding box of the display area AREA of window W, without | ||
| 812 | mode lines, in frame-relative coordinates. AREA < 0 means the | ||
| 813 | whole window, not including bitmap areas to the left and right of | ||
| 814 | the window. Return in *BOX_X and *BOX_Y the frame-relative pixel | ||
| 815 | coordinates of the upper-left corner of the box. Return in | ||
| 816 | *BOX_WIDTH, and *BOX_HEIGHT the pixel width and height of the box. */ | ||
| 817 | |||
| 818 | INLINE void | ||
| 819 | window_box (w, area, box_x, box_y, box_width, box_height) | ||
| 820 | struct window *w; | ||
| 821 | int area; | ||
| 822 | int *box_x, *box_y, *box_width, *box_height; | ||
| 823 | { | ||
| 824 | struct frame *f = XFRAME (w->frame); | ||
| 825 | |||
| 826 | *box_width = window_box_width (w, area); | ||
| 827 | *box_height = window_box_height (w); | ||
| 828 | *box_x = window_box_left (w, area); | ||
| 829 | *box_y = (FRAME_INTERNAL_BORDER_WIDTH_SAFE (f) | ||
| 830 | + XFASTINT (w->top) * CANON_Y_UNIT (f)); | ||
| 831 | if (WINDOW_WANTS_TOP_LINE_P (w)) | ||
| 832 | *box_y += CURRENT_TOP_LINE_HEIGHT (w); | ||
| 833 | } | ||
| 834 | |||
| 835 | |||
| 836 | /* Get the bounding box of the display area AREA of window W, without | ||
| 837 | mode lines. AREA < 0 means the whole window, not including bitmap | ||
| 838 | areas to the left and right of the window. Return in *TOP_LEFT_X | ||
| 839 | and TOP_LEFT_Y the frame-relative pixel coordinates of the | ||
| 840 | upper-left corner of the box. Return in *BOTTOM_RIGHT_X, and | ||
| 841 | *BOTTOM_RIGHT_Y the coordinates of the bottom-right corner of the | ||
| 842 | box. */ | ||
| 843 | |||
| 844 | INLINE void | ||
| 845 | window_box_edges (w, area, top_left_x, top_left_y, | ||
| 846 | bottom_right_x, bottom_right_y) | ||
| 847 | struct window *w; | ||
| 848 | int area; | ||
| 849 | int *top_left_x, *top_left_y, *bottom_right_x, *bottom_right_y; | ||
| 850 | { | ||
| 851 | window_box (w, area, top_left_x, top_left_y, bottom_right_x, | ||
| 852 | bottom_right_y); | ||
| 853 | *bottom_right_x += *top_left_x; | ||
| 854 | *bottom_right_y += *top_left_y; | ||
| 855 | } | ||
| 856 | |||
| 276 | 857 | ||
| 277 | static int pos_tab_offset P_ ((struct window *, int, int)); | ||
| 278 | 858 | ||
| 859 | /*********************************************************************** | ||
| 860 | Utilities | ||
| 861 | ***********************************************************************/ | ||
| 862 | |||
| 863 | /* Given a position POS containing a valid character and byte position | ||
| 864 | in STRING, return the position NCHARS ahead (NCHARS >= 0). */ | ||
| 865 | |||
| 866 | static struct text_pos | ||
| 867 | string_pos_nchars_ahead (pos, string, nchars) | ||
| 868 | struct text_pos pos; | ||
| 869 | Lisp_Object string; | ||
| 870 | int nchars; | ||
| 871 | { | ||
| 872 | xassert (STRINGP (string) && nchars >= 0); | ||
| 873 | |||
| 874 | if (STRING_MULTIBYTE (string)) | ||
| 875 | { | ||
| 876 | int rest = STRING_BYTES (XSTRING (string)) - BYTEPOS (pos); | ||
| 877 | unsigned char *p = XSTRING (string)->data + BYTEPOS (pos); | ||
| 878 | int len; | ||
| 879 | |||
| 880 | while (nchars--) | ||
| 881 | { | ||
| 882 | STRING_CHAR_AND_LENGTH (p, rest, len); | ||
| 883 | p += len, rest -= len; | ||
| 884 | xassert (rest >= 0); | ||
| 885 | CHARPOS (pos) += 1; | ||
| 886 | BYTEPOS (pos) += len; | ||
| 887 | } | ||
| 888 | } | ||
| 889 | else | ||
| 890 | SET_TEXT_POS (pos, CHARPOS (pos) + nchars, BYTEPOS (pos) + nchars); | ||
| 891 | |||
| 892 | return pos; | ||
| 893 | } | ||
| 894 | |||
| 895 | |||
| 896 | /* Value is the text position, i.e. character and byte position, | ||
| 897 | for character position CHARPOS in STRING. */ | ||
| 898 | |||
| 899 | static INLINE struct text_pos | ||
| 900 | string_pos (charpos, string) | ||
| 901 | int charpos; | ||
| 902 | Lisp_Object string; | ||
| 903 | { | ||
| 904 | struct text_pos pos; | ||
| 905 | xassert (STRINGP (string)); | ||
| 906 | xassert (charpos >= 0); | ||
| 907 | SET_TEXT_POS (pos, charpos, string_char_to_byte (string, charpos)); | ||
| 908 | return pos; | ||
| 909 | } | ||
| 910 | |||
| 911 | |||
| 912 | /* Value is a text position, i.e. character and byte position, for | ||
| 913 | character position CHARPOS in C string S. MULTIBYTE_P non-zero | ||
| 914 | means recognize multibyte characters. */ | ||
| 915 | |||
| 916 | static struct text_pos | ||
| 917 | c_string_pos (charpos, s, multibyte_p) | ||
| 918 | int charpos; | ||
| 919 | unsigned char *s; | ||
| 920 | int multibyte_p; | ||
| 921 | { | ||
| 922 | struct text_pos pos; | ||
| 923 | |||
| 924 | xassert (s != NULL); | ||
| 925 | xassert (charpos >= 0); | ||
| 926 | |||
| 927 | if (multibyte_p) | ||
| 928 | { | ||
| 929 | int rest = strlen (s), len; | ||
| 930 | |||
| 931 | SET_TEXT_POS (pos, 0, 0); | ||
| 932 | while (charpos--) | ||
| 933 | { | ||
| 934 | STRING_CHAR_AND_LENGTH (s, rest, len); | ||
| 935 | s += len, rest -= len; | ||
| 936 | xassert (rest >= 0); | ||
| 937 | CHARPOS (pos) += 1; | ||
| 938 | BYTEPOS (pos) += len; | ||
| 939 | } | ||
| 940 | } | ||
| 941 | else | ||
| 942 | SET_TEXT_POS (pos, charpos, charpos); | ||
| 943 | |||
| 944 | return pos; | ||
| 945 | } | ||
| 946 | |||
| 947 | |||
| 948 | /* Value is the number of characters in C string S. MULTIBYTE_P | ||
| 949 | non-zero means recognize multibyte characters. */ | ||
| 950 | |||
| 951 | static int | ||
| 952 | number_of_chars (s, multibyte_p) | ||
| 953 | unsigned char *s; | ||
| 954 | int multibyte_p; | ||
| 955 | { | ||
| 956 | int nchars; | ||
| 957 | |||
| 958 | if (multibyte_p) | ||
| 959 | { | ||
| 960 | int rest = strlen (s), len; | ||
| 961 | unsigned char *p = (unsigned char *) s; | ||
| 962 | |||
| 963 | for (nchars = 0; rest > 0; ++nchars) | ||
| 964 | { | ||
| 965 | STRING_CHAR_AND_LENGTH (p, rest, len); | ||
| 966 | rest -= len, p += len; | ||
| 967 | } | ||
| 968 | } | ||
| 969 | else | ||
| 970 | nchars = strlen (s); | ||
| 971 | |||
| 972 | return nchars; | ||
| 973 | } | ||
| 974 | |||
| 975 | |||
| 976 | /* Compute byte position NEWPOS->bytepos corresponding to | ||
| 977 | NEWPOS->charpos. POS is a known position in string STRING. | ||
| 978 | NEWPOS->charpos must be >= POS.charpos. */ | ||
| 979 | |||
| 980 | static void | ||
| 981 | compute_string_pos (newpos, pos, string) | ||
| 982 | struct text_pos *newpos, pos; | ||
| 983 | Lisp_Object string; | ||
| 984 | { | ||
| 985 | xassert (STRINGP (string)); | ||
| 986 | xassert (CHARPOS (*newpos) >= CHARPOS (pos)); | ||
| 987 | |||
| 988 | if (STRING_MULTIBYTE (string)) | ||
| 989 | *newpos = string_pos_nchars_ahead (pos, CHARPOS (*newpos) - CHARPOS (pos), | ||
| 990 | string); | ||
| 991 | else | ||
| 992 | BYTEPOS (*newpos) = CHARPOS (*newpos); | ||
| 993 | } | ||
| 994 | |||
| 995 | |||
| 996 | /* Return the charset of the character at position POS in | ||
| 997 | current_buffer. */ | ||
| 998 | |||
| 999 | static int | ||
| 1000 | charset_at_position (pos) | ||
| 1001 | struct text_pos pos; | ||
| 1002 | { | ||
| 1003 | int c, multibyte_p; | ||
| 1004 | unsigned char *p = BYTE_POS_ADDR (BYTEPOS (pos)); | ||
| 1005 | |||
| 1006 | multibyte_p = !NILP (current_buffer->enable_multibyte_characters); | ||
| 1007 | if (multibyte_p) | ||
| 1008 | { | ||
| 1009 | int maxlen = ((BYTEPOS (pos) >= GPT_BYTE ? ZV_BYTE : GPT_BYTE) | ||
| 1010 | - BYTEPOS (pos)); | ||
| 1011 | int len; | ||
| 1012 | c = STRING_CHAR_AND_LENGTH (p, maxlen, len); | ||
| 1013 | } | ||
| 1014 | else | ||
| 1015 | c = *p; | ||
| 1016 | |||
| 1017 | return CHAR_CHARSET (c); | ||
| 1018 | } | ||
| 1019 | |||
| 1020 | |||
| 1021 | |||
| 1022 | /*********************************************************************** | ||
| 1023 | Lisp form evaluation | ||
| 1024 | ***********************************************************************/ | ||
| 1025 | |||
| 1026 | /* Error handler for eval_form. */ | ||
| 1027 | |||
| 1028 | static Lisp_Object | ||
| 1029 | eval_handler (arg) | ||
| 1030 | Lisp_Object arg; | ||
| 1031 | { | ||
| 1032 | return Qnil; | ||
| 1033 | } | ||
| 1034 | |||
| 1035 | |||
| 1036 | /* Evaluate SEXPR and return the result, or nil if something went | ||
| 1037 | wrong. */ | ||
| 1038 | |||
| 1039 | static Lisp_Object | ||
| 1040 | eval_form (sexpr) | ||
| 1041 | Lisp_Object sexpr; | ||
| 1042 | { | ||
| 1043 | int count = specpdl_ptr - specpdl; | ||
| 1044 | Lisp_Object val; | ||
| 1045 | specbind (Qinhibit_redisplay, Qt); | ||
| 1046 | val = internal_condition_case_1 (Feval, sexpr, Qerror, eval_handler); | ||
| 1047 | return unbind_to (count, val); | ||
| 1048 | } | ||
| 1049 | |||
| 1050 | |||
| 1051 | |||
| 1052 | /*********************************************************************** | ||
| 1053 | Debugging | ||
| 1054 | ***********************************************************************/ | ||
| 1055 | |||
| 1056 | #if 0 | ||
| 1057 | |||
| 1058 | /* Define CHECK_IT to perform sanity checks on iterators. | ||
| 1059 | This is for debugging. It is too slow to do unconditionally. */ | ||
| 1060 | |||
| 1061 | static void | ||
| 1062 | check_it (it) | ||
| 1063 | struct it *it; | ||
| 1064 | { | ||
| 1065 | if (it->method == next_element_from_string) | ||
| 1066 | { | ||
| 1067 | xassert (STRINGP (it->string)); | ||
| 1068 | xassert (IT_STRING_CHARPOS (*it) >= 0); | ||
| 1069 | } | ||
| 1070 | else if (it->method == next_element_from_buffer) | ||
| 1071 | { | ||
| 1072 | /* Check that character and byte positions agree. */ | ||
| 1073 | xassert (IT_CHARPOS (*it) == BYTE_TO_CHAR (IT_BYTEPOS (*it))); | ||
| 1074 | } | ||
| 1075 | |||
| 1076 | if (it->dpvec) | ||
| 1077 | xassert (it->current.dpvec_index >= 0); | ||
| 1078 | else | ||
| 1079 | xassert (it->current.dpvec_index < 0); | ||
| 1080 | } | ||
| 1081 | |||
| 1082 | #define CHECK_IT(IT) check_it ((IT)) | ||
| 1083 | |||
| 1084 | #else /* not 0 */ | ||
| 1085 | |||
| 1086 | #define CHECK_IT(IT) (void) 0 | ||
| 1087 | |||
| 1088 | #endif /* not 0 */ | ||
| 1089 | |||
| 1090 | |||
| 1091 | #if GLYPH_DEBUG | ||
| 1092 | |||
| 1093 | /* Check that the window end of window W is what we expect it | ||
| 1094 | to be---the last row in the current matrix displaying text. */ | ||
| 1095 | |||
| 1096 | static void | ||
| 1097 | check_window_end (w) | ||
| 1098 | struct window *w; | ||
| 1099 | { | ||
| 1100 | if (!MINI_WINDOW_P (w) | ||
| 1101 | && !NILP (w->window_end_valid)) | ||
| 1102 | { | ||
| 1103 | struct glyph_row *row; | ||
| 1104 | xassert ((row = MATRIX_ROW (w->current_matrix, | ||
| 1105 | XFASTINT (w->window_end_vpos)), | ||
| 1106 | !row->enabled_p | ||
| 1107 | || MATRIX_ROW_DISPLAYS_TEXT_P (row) | ||
| 1108 | || MATRIX_ROW_VPOS (row, w->current_matrix) == 0)); | ||
| 1109 | } | ||
| 1110 | } | ||
| 1111 | |||
| 1112 | #define CHECK_WINDOW_END(W) check_window_end ((W)) | ||
| 1113 | |||
| 1114 | #else /* not GLYPH_DEBUG */ | ||
| 1115 | |||
| 1116 | #define CHECK_WINDOW_END(W) (void) 0 | ||
| 1117 | |||
| 1118 | #endif /* not GLYPH_DEBUG */ | ||
| 1119 | |||
| 1120 | |||
| 1121 | |||
| 1122 | /*********************************************************************** | ||
| 1123 | Iterator initialization | ||
| 1124 | ***********************************************************************/ | ||
| 1125 | |||
| 1126 | /* Initialize IT for displaying current_buffer in window W, starting | ||
| 1127 | at character position CHARPOS. CHARPOS < 0 means that no buffer | ||
| 1128 | position is specified which is useful when the iterator is assigned | ||
| 1129 | a position later. BYTEPOS is the byte position corresponding to | ||
| 1130 | CHARPOS. BYTEPOS <= 0 means compute it from CHARPOS. | ||
| 1131 | |||
| 1132 | If ROW is not null, calls to produce_glyphs with IT as parameter | ||
| 1133 | will produce glyphs in that row. | ||
| 1134 | |||
| 1135 | BASE_FACE_ID is the id of a base face to use. It must be one of | ||
| 1136 | DEFAULT_FACE_ID for normal text, MODE_LINE_FACE_ID or | ||
| 1137 | TOP_LINE_FACE_ID for displaying mode lines, or TOOLBAR_FACE_ID for | ||
| 1138 | displaying the toolbar. | ||
| 1139 | |||
| 1140 | If ROW is null and BASE_FACE_ID is equal to MODE_LINE_FACE_ID or | ||
| 1141 | TOP_LINE_FACE_ID, the iterator will be initialized to use the | ||
| 1142 | corresponding mode line glyph row of the desired matrix of W. */ | ||
| 1143 | |||
| 1144 | void | ||
| 1145 | init_iterator (it, w, charpos, bytepos, row, base_face_id) | ||
| 1146 | struct it *it; | ||
| 1147 | struct window *w; | ||
| 1148 | int charpos, bytepos; | ||
| 1149 | struct glyph_row *row; | ||
| 1150 | enum face_id base_face_id; | ||
| 1151 | { | ||
| 1152 | int highlight_region_p; | ||
| 1153 | Lisp_Object value; | ||
| 1154 | |||
| 1155 | /* Some precondition checks. */ | ||
| 1156 | xassert (w != NULL && it != NULL); | ||
| 1157 | xassert (charpos < 0 || current_buffer == XBUFFER (w->buffer)); | ||
| 1158 | xassert (charpos < 0 || (charpos > 0 && charpos <= ZV)); | ||
| 1159 | |||
| 1160 | /* If face attributes have been changed since the last redisplay, | ||
| 1161 | free realized faces now because they depend on face definitions | ||
| 1162 | that might have changed. */ | ||
| 1163 | if (face_change_count) | ||
| 1164 | { | ||
| 1165 | face_change_count = 0; | ||
| 1166 | free_all_realized_faces (Qnil); | ||
| 1167 | } | ||
| 1168 | |||
| 1169 | /* Use one of the mode line rows of W's desired matrix if | ||
| 1170 | appropriate. */ | ||
| 1171 | if (row == NULL) | ||
| 1172 | { | ||
| 1173 | if (base_face_id == MODE_LINE_FACE_ID) | ||
| 1174 | row = MATRIX_MODE_LINE_ROW (w->desired_matrix); | ||
| 1175 | else if (base_face_id == TOP_LINE_FACE_ID) | ||
| 1176 | row = MATRIX_TOP_LINE_ROW (w->desired_matrix); | ||
| 1177 | } | ||
| 1178 | |||
| 1179 | /* Clear IT. */ | ||
| 1180 | bzero (it, sizeof *it); | ||
| 1181 | it->current.overlay_string_index = -1; | ||
| 1182 | it->current.dpvec_index = -1; | ||
| 1183 | it->charset = CHARSET_ASCII; | ||
| 1184 | it->base_face_id = base_face_id; | ||
| 1185 | |||
| 1186 | /* The window in which we iterate over current_buffer: */ | ||
| 1187 | XSETWINDOW (it->window, w); | ||
| 1188 | it->w = w; | ||
| 1189 | it->f = XFRAME (w->frame); | ||
| 1190 | |||
| 1191 | /* If realized faces have been removed, e.g. because of face | ||
| 1192 | attribute changes of named faces, recompute them. */ | ||
| 1193 | if (FRAME_FACE_CACHE (it->f)->used == 0) | ||
| 1194 | recompute_basic_faces (it->f); | ||
| 1195 | |||
| 1196 | /* Should we highlight trailing whitespace? */ | ||
| 1197 | value = find_symbol_value (Qshow_trailing_whitespace); | ||
| 1198 | it->show_trailing_whitespace_p | ||
| 1199 | = EQ (value, Qunbound) ? 0 : !NILP (value); | ||
| 1200 | |||
| 1201 | /* Current value of the `space-width', and 'height' properties. */ | ||
| 1202 | it->space_width = Qnil; | ||
| 1203 | it->font_height = Qnil; | ||
| 1204 | |||
| 1205 | /* Are control characters displayed as `^C'? */ | ||
| 1206 | it->ctl_arrow_p = !NILP (current_buffer->ctl_arrow); | ||
| 1207 | |||
| 1208 | /* -1 means everything between a CR and the following line end | ||
| 1209 | is invisible. >0 means lines indented more than this value are | ||
| 1210 | invisible. */ | ||
| 1211 | it->selective = (INTEGERP (current_buffer->selective_display) | ||
| 1212 | ? XFASTINT (current_buffer->selective_display) | ||
| 1213 | : (!NILP (current_buffer->selective_display) | ||
| 1214 | ? -1 : 0)); | ||
| 1215 | it->selective_display_ellipsis_p | ||
| 1216 | = !NILP (current_buffer->selective_display_ellipses); | ||
| 1217 | |||
| 1218 | /* Display table to use. */ | ||
| 1219 | it->dp = window_display_table (w); | ||
| 1220 | |||
| 1221 | /* Are multibyte characters enabled in current_buffer? */ | ||
| 1222 | it->multibyte_p = !NILP (current_buffer->enable_multibyte_characters); | ||
| 1223 | |||
| 1224 | /* Non-zero if we should highlight the region. */ | ||
| 1225 | highlight_region_p | ||
| 1226 | = (!NILP (Vtransient_mark_mode) | ||
| 1227 | && !NILP (current_buffer->mark_active) | ||
| 1228 | && XMARKER (current_buffer->mark)->buffer != 0); | ||
| 1229 | |||
| 1230 | /* Set IT->region_beg_charpos and IT->region_end_charpos to the | ||
| 1231 | start and end of a visible region in window IT->w. Set both to | ||
| 1232 | -1 to indicate no region. */ | ||
| 1233 | if (highlight_region_p | ||
| 1234 | /* Maybe highlight only in selected window. */ | ||
| 1235 | && (/* Either show region everywhere. */ | ||
| 1236 | highlight_nonselected_windows | ||
| 1237 | /* Or show region in the selected window. */ | ||
| 1238 | || w == XWINDOW (selected_window) | ||
| 1239 | /* Or show the region if we are in the mini-buffer and W is | ||
| 1240 | the window the mini-buffer refers to. */ | ||
| 1241 | || (MINI_WINDOW_P (XWINDOW (selected_window)) | ||
| 1242 | && w == XWINDOW (Vminibuf_scroll_window)))) | ||
| 1243 | { | ||
| 1244 | int charpos = marker_position (current_buffer->mark); | ||
| 1245 | it->region_beg_charpos = min (PT, charpos); | ||
| 1246 | it->region_end_charpos = max (PT, charpos); | ||
| 1247 | } | ||
| 1248 | else | ||
| 1249 | it->region_beg_charpos = it->region_end_charpos = -1; | ||
| 1250 | |||
| 1251 | /* Get the position at which the redisplay_end_trigger hook should | ||
| 1252 | be run, if it is to be run at all. */ | ||
| 1253 | if (MARKERP (w->redisplay_end_trigger) | ||
| 1254 | && XMARKER (w->redisplay_end_trigger)->buffer != 0) | ||
| 1255 | it->redisplay_end_trigger_charpos | ||
| 1256 | = marker_position (w->redisplay_end_trigger); | ||
| 1257 | else if (INTEGERP (w->redisplay_end_trigger)) | ||
| 1258 | it->redisplay_end_trigger_charpos = XINT (w->redisplay_end_trigger); | ||
| 1259 | |||
| 1260 | /* Correct bogus values of tab_width. */ | ||
| 1261 | it->tab_width = XINT (current_buffer->tab_width); | ||
| 1262 | if (it->tab_width <= 0 || it->tab_width > 1000) | ||
| 1263 | it->tab_width = 8; | ||
| 1264 | |||
| 1265 | /* Are lines in the display truncated? */ | ||
| 1266 | it->truncate_lines_p | ||
| 1267 | = (base_face_id != DEFAULT_FACE_ID | ||
| 1268 | || XINT (it->w->hscroll) | ||
| 1269 | || (truncate_partial_width_windows | ||
| 1270 | && !WINDOW_FULL_WIDTH_P (it->w)) | ||
| 1271 | || !NILP (current_buffer->truncate_lines)); | ||
| 1272 | |||
| 1273 | /* Get dimensions of truncation and continuation glyphs. These are | ||
| 1274 | displayed as bitmaps under X, so we don't need them for such | ||
| 1275 | frames. */ | ||
| 1276 | if (!FRAME_WINDOW_P (it->f)) | ||
| 1277 | { | ||
| 1278 | if (it->truncate_lines_p) | ||
| 1279 | { | ||
| 1280 | /* We will need the truncation glyph. */ | ||
| 1281 | xassert (it->glyph_row == NULL); | ||
| 1282 | produce_special_glyphs (it, IT_TRUNCATION); | ||
| 1283 | it->truncation_pixel_width = it->pixel_width; | ||
| 1284 | } | ||
| 1285 | else | ||
| 1286 | { | ||
| 1287 | /* We will need the continuation glyph. */ | ||
| 1288 | xassert (it->glyph_row == NULL); | ||
| 1289 | produce_special_glyphs (it, IT_CONTINUATION); | ||
| 1290 | it->continuation_pixel_width = it->pixel_width; | ||
| 1291 | } | ||
| 1292 | |||
| 1293 | /* Reset these values to zero becaue the produce_special_glyphs | ||
| 1294 | above has changed them. */ | ||
| 1295 | it->pixel_width = it->ascent = it->descent = 0; | ||
| 1296 | } | ||
| 1297 | |||
| 1298 | /* Set this after getting the dimensions of truncation and | ||
| 1299 | continuation glyphs, so that we don't produce glyphs when calling | ||
| 1300 | produce_special_glyphs, above. */ | ||
| 1301 | it->glyph_row = row; | ||
| 1302 | it->area = TEXT_AREA; | ||
| 1303 | |||
| 1304 | /* Get the dimensions of the display area. The display area | ||
| 1305 | consists of the visible window area plus a horizontally scrolled | ||
| 1306 | part to the left of the window. All x-values are relative to the | ||
| 1307 | start of this total display area. */ | ||
| 1308 | if (base_face_id != DEFAULT_FACE_ID) | ||
| 1309 | { | ||
| 1310 | /* Mode lines, menu bar in terminal frames. */ | ||
| 1311 | it->first_visible_x = 0; | ||
| 1312 | it->last_visible_x = XFASTINT (w->width) * CANON_X_UNIT (it->f); | ||
| 1313 | } | ||
| 1314 | else | ||
| 1315 | { | ||
| 1316 | it->first_visible_x | ||
| 1317 | = XFASTINT (it->w->hscroll) * CANON_X_UNIT (it->f); | ||
| 1318 | it->last_visible_x = (it->first_visible_x | ||
| 1319 | + window_box_width (w, TEXT_AREA)); | ||
| 1320 | |||
| 1321 | /* If we truncate lines, leave room for the truncator glyph(s) at | ||
| 1322 | the right margin. Otherwise, leave room for the continuation | ||
| 1323 | glyph(s). Truncation and continuation glyphs are not inserted | ||
| 1324 | for window-based redisplay. */ | ||
| 1325 | if (!FRAME_WINDOW_P (it->f)) | ||
| 1326 | { | ||
| 1327 | if (it->truncate_lines_p) | ||
| 1328 | it->last_visible_x -= it->truncation_pixel_width; | ||
| 1329 | else | ||
| 1330 | it->last_visible_x -= it->continuation_pixel_width; | ||
| 1331 | } | ||
| 1332 | |||
| 1333 | it->top_line_p = WINDOW_WANTS_TOP_LINE_P (w); | ||
| 1334 | it->current_y = WINDOW_DISPLAY_TOP_LINE_HEIGHT (w) + w->vscroll; | ||
| 1335 | } | ||
| 1336 | |||
| 1337 | /* Leave room for a border glyph. */ | ||
| 1338 | if (!FRAME_WINDOW_P (it->f) | ||
| 1339 | && !WINDOW_RIGHTMOST_P (it->w)) | ||
| 1340 | it->last_visible_x -= 1; | ||
| 1341 | |||
| 1342 | it->last_visible_y = window_text_bottom_y (w); | ||
| 1343 | |||
| 1344 | /* For mode lines and alike, arrange for the first glyph having a | ||
| 1345 | left box line if the face specifies a box. */ | ||
| 1346 | if (base_face_id != DEFAULT_FACE_ID) | ||
| 1347 | { | ||
| 1348 | struct face *face; | ||
| 1349 | |||
| 1350 | it->face_id = base_face_id; | ||
| 1351 | |||
| 1352 | /* If we have a boxed mode line, make the first character appear | ||
| 1353 | with a left box line. */ | ||
| 1354 | face = FACE_FROM_ID (it->f, base_face_id); | ||
| 1355 | if (face->box != FACE_NO_BOX) | ||
| 1356 | it->start_of_box_run_p = 1; | ||
| 1357 | } | ||
| 1358 | |||
| 1359 | /* If a buffer position was specified, set the iterator there, | ||
| 1360 | getting overlays and face properties from that position. */ | ||
| 1361 | if (charpos > 0) | ||
| 1362 | { | ||
| 1363 | it->end_charpos = ZV; | ||
| 1364 | it->face_id = -1; | ||
| 1365 | IT_CHARPOS (*it) = charpos; | ||
| 1366 | |||
| 1367 | /* Compute byte position if not specified. */ | ||
| 1368 | if (bytepos <= 0) | ||
| 1369 | IT_BYTEPOS (*it) = CHAR_TO_BYTE (charpos); | ||
| 1370 | else | ||
| 1371 | IT_BYTEPOS (*it) = bytepos; | ||
| 1372 | |||
| 1373 | /* Compute faces etc. */ | ||
| 1374 | reseat (it, it->current.pos, 1); | ||
| 1375 | } | ||
| 1376 | |||
| 1377 | CHECK_IT (it); | ||
| 1378 | } | ||
| 1379 | |||
| 1380 | |||
| 1381 | /* Initialize IT for the display of window W with window start POS. */ | ||
| 1382 | |||
| 1383 | void | ||
| 1384 | start_display (it, w, pos) | ||
| 1385 | struct it *it; | ||
| 1386 | struct window *w; | ||
| 1387 | struct text_pos pos; | ||
| 1388 | { | ||
| 1389 | int start_at_line_beg_p; | ||
| 1390 | struct glyph_row *row; | ||
| 1391 | int first_vpos = WINDOW_WANTS_TOP_LINE_P (w) ? 1 : 0; | ||
| 1392 | int first_y; | ||
| 1393 | |||
| 1394 | row = w->desired_matrix->rows + first_vpos; | ||
| 1395 | init_iterator (it, w, CHARPOS (pos), BYTEPOS (pos), row, DEFAULT_FACE_ID); | ||
| 1396 | first_y = it->current_y; | ||
| 1397 | |||
| 1398 | /* If window start is not at a line start, move back to the line | ||
| 1399 | start. This makes sure that we take continuation lines into | ||
| 1400 | account. */ | ||
| 1401 | start_at_line_beg_p = (CHARPOS (pos) == BEGV | ||
| 1402 | || FETCH_BYTE (BYTEPOS (pos) - 1) == '\n'); | ||
| 1403 | if (!start_at_line_beg_p) | ||
| 1404 | reseat_at_previous_visible_line_start (it); | ||
| 1405 | |||
| 1406 | #if NO_PROMPT_IN_BUFFER | ||
| 1407 | /* Take the mini-buffer prompt width into account for tab | ||
| 1408 | calculations. */ | ||
| 1409 | if (MINI_WINDOW_P (w) && IT_CHARPOS (*it) == BEGV) | ||
| 1410 | { | ||
| 1411 | /* Why is mini-buffer_prompt_width guaranteed to be set here? */ | ||
| 1412 | it->prompt_width = minibuf_prompt_pixel_width; | ||
| 1413 | } | ||
| 1414 | #endif /* NO_PROMPT_IN_BUFFER */ | ||
| 1415 | |||
| 1416 | /* If window start is not at a line start, skip forward to POS to | ||
| 1417 | get the correct continuation_lines_width and current_x. */ | ||
| 1418 | if (!start_at_line_beg_p) | ||
| 1419 | { | ||
| 1420 | move_it_to (it, CHARPOS (pos), -1, -1, -1, MOVE_TO_POS); | ||
| 1421 | |||
| 1422 | /* If lines are continued, this line may end in the middle of a | ||
| 1423 | multi-glyph character (e.g. a control character displayed as | ||
| 1424 | \003, or in the middle of an overlay string). In this case | ||
| 1425 | move_it_to above will not have taken us to the start of | ||
| 1426 | the continuation line but to the end of the continued line. */ | ||
| 1427 | if (!it->truncate_lines_p && it->current_x > 0) | ||
| 1428 | { | ||
| 1429 | if (it->current.dpvec_index >= 0 | ||
| 1430 | || it->current.overlay_string_index >= 0) | ||
| 1431 | { | ||
| 1432 | set_iterator_to_next (it); | ||
| 1433 | move_it_in_display_line_to (it, -1, -1, 0); | ||
| 1434 | } | ||
| 1435 | it->continuation_lines_width += it->current_x; | ||
| 1436 | } | ||
| 1437 | |||
| 1438 | it->current_y = first_y; | ||
| 1439 | it->vpos = 0; | ||
| 1440 | it->current_x = it->hpos = 0; | ||
| 1441 | } | ||
| 1442 | |||
| 1443 | #if 0 /* Don't assert the following because start_display is sometimes | ||
| 1444 | called intentionally with a window start that is not at a | ||
| 1445 | line start. Please leave this code in as a comment. */ | ||
| 1446 | |||
| 1447 | /* Window start should be on a line start, now. */ | ||
| 1448 | xassert (it->continuation_lines_width | ||
| 1449 | || IT_CHARPOS (it) == BEGV | ||
| 1450 | || FETCH_BYTE (IT_BYTEPOS (it) - 1) == '\n'); | ||
| 1451 | #endif /* 0 */ | ||
| 1452 | } | ||
| 1453 | |||
| 1454 | |||
| 1455 | /* Initialize IT for stepping through current_buffer in window W, | ||
| 1456 | starting at position POS that includes overlay string and display | ||
| 1457 | vector/ control character translation position information. */ | ||
| 1458 | |||
| 1459 | static void | ||
| 1460 | init_from_display_pos (it, w, pos) | ||
| 1461 | struct it *it; | ||
| 1462 | struct window *w; | ||
| 1463 | struct display_pos *pos; | ||
| 1464 | { | ||
| 1465 | /* Keep in mind: the call to reseat in init_iterator skips invisible | ||
| 1466 | text, so we might end up at a position different from POS. This | ||
| 1467 | is only a problem when POS is a row start after a newline and an | ||
| 1468 | overlay starts there with an after-string, and the overlay has an | ||
| 1469 | invisible property. Since we don't skip invisible text in | ||
| 1470 | display_line and elsewhere immediately after consuming the | ||
| 1471 | newline before the row start, such a POS will not be in a string, | ||
| 1472 | but the call to init_iterator below will move us to the | ||
| 1473 | after-string. */ | ||
| 1474 | init_iterator (it, w, CHARPOS (pos->pos), BYTEPOS (pos->pos), | ||
| 1475 | NULL, DEFAULT_FACE_ID); | ||
| 1476 | |||
| 1477 | /* If position is within an overlay string, set up IT to | ||
| 1478 | the right overlay string. */ | ||
| 1479 | if (pos->overlay_string_index >= 0) | ||
| 1480 | { | ||
| 1481 | int relative_index; | ||
| 1482 | |||
| 1483 | /* We already have the first chunk of overlay strings in | ||
| 1484 | IT->overlay_strings. Load more until the one for | ||
| 1485 | pos->overlay_string_index is in IT->overlay_strings. */ | ||
| 1486 | if (pos->overlay_string_index >= OVERLAY_STRING_CHUNK_SIZE) | ||
| 1487 | { | ||
| 1488 | int n = pos->overlay_string_index / OVERLAY_STRING_CHUNK_SIZE; | ||
| 1489 | it->current.overlay_string_index = 0; | ||
| 1490 | while (n--) | ||
| 1491 | { | ||
| 1492 | load_overlay_strings (it); | ||
| 1493 | it->current.overlay_string_index += OVERLAY_STRING_CHUNK_SIZE; | ||
| 1494 | } | ||
| 1495 | } | ||
| 1496 | |||
| 1497 | it->current.overlay_string_index = pos->overlay_string_index; | ||
| 1498 | relative_index = (it->current.overlay_string_index | ||
| 1499 | % OVERLAY_STRING_CHUNK_SIZE); | ||
| 1500 | it->string = it->overlay_strings[relative_index]; | ||
| 1501 | it->current.string_pos = pos->string_pos; | ||
| 1502 | it->method = next_element_from_string; | ||
| 1503 | } | ||
| 1504 | else if (CHARPOS (pos->string_pos) >= 0) | ||
| 1505 | { | ||
| 1506 | /* Recorded position is not in an overlay string, but in another | ||
| 1507 | string. This can only be a string from a `display' property. | ||
| 1508 | IT should already be filled with that string. */ | ||
| 1509 | it->current.string_pos = pos->string_pos; | ||
| 1510 | xassert (STRINGP (it->string)); | ||
| 1511 | } | ||
| 1512 | |||
| 1513 | /* Restore position in display vector translations or control | ||
| 1514 | character translations. */ | ||
| 1515 | if (pos->dpvec_index >= 0) | ||
| 1516 | { | ||
| 1517 | /* This fills IT->dpvec. */ | ||
| 1518 | get_next_display_element (it); | ||
| 1519 | xassert (it->dpvec && it->current.dpvec_index == 0); | ||
| 1520 | it->current.dpvec_index = pos->dpvec_index; | ||
| 1521 | } | ||
| 1522 | |||
| 1523 | CHECK_IT (it); | ||
| 1524 | } | ||
| 1525 | |||
| 1526 | |||
| 1527 | /* Initialize IT for stepping through current_buffer in window W | ||
| 1528 | starting at ROW->start. */ | ||
| 1529 | |||
| 1530 | static void | ||
| 1531 | init_to_row_start (it, w, row) | ||
| 1532 | struct it *it; | ||
| 1533 | struct window *w; | ||
| 1534 | struct glyph_row *row; | ||
| 1535 | { | ||
| 1536 | init_from_display_pos (it, w, &row->start); | ||
| 1537 | it->continuation_lines_width = row->continuation_lines_width; | ||
| 1538 | CHECK_IT (it); | ||
| 1539 | } | ||
| 1540 | |||
| 1541 | |||
| 1542 | /* Initialize IT for stepping through current_buffer in window W | ||
| 1543 | starting in the line following ROW, i.e. starting at ROW->end. */ | ||
| 1544 | |||
| 1545 | static void | ||
| 1546 | init_to_row_end (it, w, row) | ||
| 1547 | struct it *it; | ||
| 1548 | struct window *w; | ||
| 1549 | struct glyph_row *row; | ||
| 1550 | { | ||
| 1551 | init_from_display_pos (it, w, &row->end); | ||
| 1552 | |||
| 1553 | if (row->continued_p) | ||
| 1554 | it->continuation_lines_width = (row->continuation_lines_width | ||
| 1555 | + row->pixel_width); | ||
| 1556 | CHECK_IT (it); | ||
| 1557 | } | ||
| 1558 | |||
| 1559 | |||
| 1560 | |||
| 1561 | |||
| 1562 | /*********************************************************************** | ||
| 1563 | Text properties | ||
| 1564 | ***********************************************************************/ | ||
| 1565 | |||
| 1566 | /* Called when IT reaches IT->stop_charpos. Handle text property and | ||
| 1567 | overlay changes. Set IT->stop_charpos to the next position where | ||
| 1568 | to stop. */ | ||
| 1569 | |||
| 1570 | static void | ||
| 1571 | handle_stop (it) | ||
| 1572 | struct it *it; | ||
| 1573 | { | ||
| 1574 | enum prop_handled handled; | ||
| 1575 | int handle_overlay_change_p = 1; | ||
| 1576 | struct props *p; | ||
| 1577 | |||
| 1578 | it->dpvec = NULL; | ||
| 1579 | it->current.dpvec_index = -1; | ||
| 1580 | |||
| 1581 | do | ||
| 1582 | { | ||
| 1583 | handled = HANDLED_NORMALLY; | ||
| 1584 | |||
| 1585 | /* Call text property handlers. */ | ||
| 1586 | for (p = it_props; p->handler; ++p) | ||
| 1587 | { | ||
| 1588 | handled = p->handler (it); | ||
| 1589 | |||
| 1590 | if (handled == HANDLED_RECOMPUTE_PROPS) | ||
| 1591 | break; | ||
| 1592 | else if (handled == HANDLED_RETURN) | ||
| 1593 | return; | ||
| 1594 | else if (handled == HANDLED_OVERLAY_STRING_CONSUMED) | ||
| 1595 | handle_overlay_change_p = 0; | ||
| 1596 | } | ||
| 1597 | |||
| 1598 | if (handled != HANDLED_RECOMPUTE_PROPS) | ||
| 1599 | { | ||
| 1600 | /* Don't check for overlay strings below when set to deliver | ||
| 1601 | characters from a display vector. */ | ||
| 1602 | if (it->method == next_element_from_display_vector) | ||
| 1603 | handle_overlay_change_p = 0; | ||
| 1604 | |||
| 1605 | /* Handle overlay changes. */ | ||
| 1606 | if (handle_overlay_change_p) | ||
| 1607 | handled = handle_overlay_change (it); | ||
| 1608 | |||
| 1609 | /* Determine where to stop next. */ | ||
| 1610 | if (handled == HANDLED_NORMALLY) | ||
| 1611 | compute_stop_pos (it); | ||
| 1612 | } | ||
| 1613 | } | ||
| 1614 | while (handled == HANDLED_RECOMPUTE_PROPS); | ||
| 1615 | } | ||
| 1616 | |||
| 1617 | |||
| 1618 | /* Compute IT->stop_charpos from text property and overlay change | ||
| 1619 | information for IT's current position. */ | ||
| 1620 | |||
| 1621 | static void | ||
| 1622 | compute_stop_pos (it) | ||
| 1623 | struct it *it; | ||
| 1624 | { | ||
| 1625 | register INTERVAL iv, next_iv; | ||
| 1626 | Lisp_Object object, limit, position; | ||
| 1627 | |||
| 1628 | /* If nowhere else, stop at the end. */ | ||
| 1629 | it->stop_charpos = it->end_charpos; | ||
| 1630 | |||
| 1631 | if (STRINGP (it->string)) | ||
| 1632 | { | ||
| 1633 | /* Strings are usually short, so don't limit the search for | ||
| 1634 | properties. */ | ||
| 1635 | object = it->string; | ||
| 1636 | limit = Qnil; | ||
| 1637 | XSETFASTINT (position, IT_STRING_CHARPOS (*it)); | ||
| 1638 | } | ||
| 1639 | else | ||
| 1640 | { | ||
| 1641 | int charpos; | ||
| 1642 | |||
| 1643 | /* If next overlay change is in front of the current stop pos | ||
| 1644 | (which is IT->end_charpos), stop there. Note: value of | ||
| 1645 | next_overlay_change is point-max if no overlay change | ||
| 1646 | follows. */ | ||
| 1647 | charpos = next_overlay_change (IT_CHARPOS (*it)); | ||
| 1648 | if (charpos < it->stop_charpos) | ||
| 1649 | it->stop_charpos = charpos; | ||
| 1650 | |||
| 1651 | /* If showing the region, we have to stop at the region | ||
| 1652 | start or end because the face might change there. */ | ||
| 1653 | if (it->region_beg_charpos > 0) | ||
| 1654 | { | ||
| 1655 | if (IT_CHARPOS (*it) < it->region_beg_charpos) | ||
| 1656 | it->stop_charpos = min (it->stop_charpos, it->region_beg_charpos); | ||
| 1657 | else if (IT_CHARPOS (*it) < it->region_end_charpos) | ||
| 1658 | it->stop_charpos = min (it->stop_charpos, it->region_end_charpos); | ||
| 1659 | } | ||
| 1660 | |||
| 1661 | /* Set up variables for computing the stop position from text | ||
| 1662 | property changes. */ | ||
| 1663 | XSETBUFFER (object, current_buffer); | ||
| 1664 | XSETFASTINT (limit, IT_CHARPOS (*it) + TEXT_PROP_DISTANCE_LIMIT); | ||
| 1665 | XSETFASTINT (position, IT_CHARPOS (*it)); | ||
| 1666 | |||
| 1667 | } | ||
| 1668 | |||
| 1669 | /* Get the interval containing IT's position. Value is a null | ||
| 1670 | interval if there isn't such an interval. */ | ||
| 1671 | iv = validate_interval_range (object, &position, &position, 0); | ||
| 1672 | if (!NULL_INTERVAL_P (iv)) | ||
| 1673 | { | ||
| 1674 | Lisp_Object values_here[LAST_PROP_IDX]; | ||
| 1675 | struct props *p; | ||
| 1676 | |||
| 1677 | /* Get properties here. */ | ||
| 1678 | for (p = it_props; p->handler; ++p) | ||
| 1679 | values_here[p->idx] = textget (iv->plist, *p->name); | ||
| 1680 | |||
| 1681 | /* Look for an interval following iv that has different | ||
| 1682 | properties. */ | ||
| 1683 | for (next_iv = next_interval (iv); | ||
| 1684 | (!NULL_INTERVAL_P (next_iv) | ||
| 1685 | && (NILP (limit) | ||
| 1686 | || XFASTINT (limit) > next_iv->position)); | ||
| 1687 | next_iv = next_interval (next_iv)) | ||
| 1688 | { | ||
| 1689 | for (p = it_props; p->handler; ++p) | ||
| 1690 | { | ||
| 1691 | Lisp_Object new_value; | ||
| 1692 | |||
| 1693 | new_value = textget (next_iv->plist, *p->name); | ||
| 1694 | if (!EQ (values_here[p->idx], new_value)) | ||
| 1695 | break; | ||
| 1696 | } | ||
| 1697 | |||
| 1698 | if (p->handler) | ||
| 1699 | break; | ||
| 1700 | } | ||
| 1701 | |||
| 1702 | if (!NULL_INTERVAL_P (next_iv)) | ||
| 1703 | { | ||
| 1704 | if (INTEGERP (limit) | ||
| 1705 | && next_iv->position >= XFASTINT (limit)) | ||
| 1706 | /* No text property change up to limit. */ | ||
| 1707 | it->stop_charpos = min (XFASTINT (limit), it->stop_charpos); | ||
| 1708 | else | ||
| 1709 | /* Text properties change in next_iv. */ | ||
| 1710 | it->stop_charpos = min (it->stop_charpos, next_iv->position); | ||
| 1711 | } | ||
| 1712 | } | ||
| 1713 | |||
| 1714 | xassert (STRINGP (it->string) | ||
| 1715 | || (it->stop_charpos >= BEGV | ||
| 1716 | && it->stop_charpos >= IT_CHARPOS (*it))); | ||
| 1717 | } | ||
| 1718 | |||
| 1719 | |||
| 1720 | /* Return the position of the next overlay change after POS in | ||
| 1721 | current_buffer. Value is point-max if no overlay change | ||
| 1722 | follows. This is like `next-overlay-change' but doesn't use | ||
| 1723 | xmalloc. */ | ||
| 1724 | |||
| 1725 | static int | ||
| 1726 | next_overlay_change (pos) | ||
| 1727 | int pos; | ||
| 1728 | { | ||
| 1729 | int noverlays; | ||
| 1730 | int endpos; | ||
| 1731 | Lisp_Object *overlays; | ||
| 1732 | int len; | ||
| 1733 | int i; | ||
| 1734 | |||
| 1735 | /* Get all overlays at the given position. */ | ||
| 1736 | len = 10; | ||
| 1737 | overlays = (Lisp_Object *) alloca (len * sizeof *overlays); | ||
| 1738 | noverlays = overlays_at (pos, 0, &overlays, &len, &endpos, NULL); | ||
| 1739 | if (noverlays > len) | ||
| 1740 | { | ||
| 1741 | len = noverlays; | ||
| 1742 | overlays = (Lisp_Object *) alloca (len * sizeof *overlays); | ||
| 1743 | noverlays = overlays_at (pos, 0, &overlays, &len, &endpos, NULL); | ||
| 1744 | } | ||
| 1745 | |||
| 1746 | /* If any of these overlays ends before endpos, | ||
| 1747 | use its ending point instead. */ | ||
| 1748 | for (i = 0; i < noverlays; ++i) | ||
| 1749 | { | ||
| 1750 | Lisp_Object oend; | ||
| 1751 | int oendpos; | ||
| 1752 | |||
| 1753 | oend = OVERLAY_END (overlays[i]); | ||
| 1754 | oendpos = OVERLAY_POSITION (oend); | ||
| 1755 | endpos = min (endpos, oendpos); | ||
| 1756 | } | ||
| 1757 | |||
| 1758 | return endpos; | ||
| 1759 | } | ||
| 1760 | |||
| 1761 | |||
| 1762 | |||
| 1763 | /*********************************************************************** | ||
| 1764 | Fontification | ||
| 1765 | ***********************************************************************/ | ||
| 1766 | |||
| 1767 | /* Handle changes in the `fontified' property of the current buffer by | ||
| 1768 | calling hook functions from Qfontification_functions to fontify | ||
| 1769 | regions of text. */ | ||
| 1770 | |||
| 1771 | static enum prop_handled | ||
| 1772 | handle_fontified_prop (it) | ||
| 1773 | struct it *it; | ||
| 1774 | { | ||
| 1775 | Lisp_Object prop, pos; | ||
| 1776 | enum prop_handled handled = HANDLED_NORMALLY; | ||
| 1777 | |||
| 1778 | /* Get the value of the `fontified' property at IT's current buffer | ||
| 1779 | position. (The `fontified' property doesn't have a special | ||
| 1780 | meaning in strings.) If the value is nil, call functions from | ||
| 1781 | Qfontification_functions. */ | ||
| 1782 | if (!STRINGP (it->string) | ||
| 1783 | && it->s == NULL | ||
| 1784 | && !NILP (Vfontification_functions) | ||
| 1785 | && (pos = make_number (IT_CHARPOS (*it)), | ||
| 1786 | prop = Fget_char_property (pos, Qfontified, Qnil), | ||
| 1787 | NILP (prop))) | ||
| 1788 | { | ||
| 1789 | Lisp_Object args[2]; | ||
| 1790 | |||
| 1791 | /* Run the hook functions. */ | ||
| 1792 | args[0] = Qfontification_functions; | ||
| 1793 | args[1] = pos; | ||
| 1794 | Frun_hook_with_args (make_number (2), args); | ||
| 1795 | |||
| 1796 | /* Return HANDLED_RECOMPUTE_PROPS only if function fontified | ||
| 1797 | something. This avoids an endless loop if they failed to | ||
| 1798 | fontify the text for which reason ever. */ | ||
| 1799 | if (!NILP (Fget_char_property (pos, Qfontified, Qnil))) | ||
| 1800 | handled = HANDLED_RECOMPUTE_PROPS; | ||
| 1801 | } | ||
| 1802 | |||
| 1803 | return handled; | ||
| 1804 | } | ||
| 1805 | |||
| 1806 | |||
| 1807 | |||
| 1808 | /*********************************************************************** | ||
| 1809 | Faces | ||
| 1810 | ***********************************************************************/ | ||
| 1811 | |||
| 1812 | /* Set up iterator IT from face properties at its current position. | ||
| 1813 | Called from handle_stop. */ | ||
| 1814 | |||
| 1815 | static enum prop_handled | ||
| 1816 | handle_face_prop (it) | ||
| 1817 | struct it *it; | ||
| 1818 | { | ||
| 1819 | int new_face_id, next_stop; | ||
| 1820 | |||
| 1821 | if (!STRINGP (it->string)) | ||
| 1822 | { | ||
| 1823 | new_face_id | ||
| 1824 | = face_at_buffer_position (it->w, | ||
| 1825 | IT_CHARPOS (*it), | ||
| 1826 | it->region_beg_charpos, | ||
| 1827 | it->region_end_charpos, | ||
| 1828 | &next_stop, | ||
| 1829 | (IT_CHARPOS (*it) | ||
| 1830 | + TEXT_PROP_DISTANCE_LIMIT), | ||
| 1831 | 0); | ||
| 1832 | |||
| 1833 | /* Is this a start of a run of characters with box face? | ||
| 1834 | Caveat: this can be called for a freshly initialized | ||
| 1835 | iterator; face_id is -1 is this case. We know that the new | ||
| 1836 | face will not change until limit, i.e. if the new face has a | ||
| 1837 | box, all characters up to limit will have one. But, as | ||
| 1838 | usual, we don't know whether limit is really the end. */ | ||
| 1839 | if (new_face_id != it->face_id) | ||
| 1840 | { | ||
| 1841 | struct face *new_face = FACE_FROM_ID (it->f, new_face_id); | ||
| 1842 | |||
| 1843 | /* If new face has a box but old face has not, this is | ||
| 1844 | the start of a run of characters with box, i.e. it has | ||
| 1845 | a shadow on the left side. The value of face_id of the | ||
| 1846 | iterator will be -1 if this is the initial call that gets | ||
| 1847 | the face. In this case, we have to look in front of IT's | ||
| 1848 | position and see whether there is a face != new_face_id. */ | ||
| 1849 | it->start_of_box_run_p | ||
| 1850 | = (new_face->box != FACE_NO_BOX | ||
| 1851 | && (it->face_id >= 0 | ||
| 1852 | || IT_CHARPOS (*it) == BEG | ||
| 1853 | || new_face_id != face_before_it_pos (it))); | ||
| 1854 | it->face_box_p = new_face->box != FACE_NO_BOX; | ||
| 1855 | } | ||
| 1856 | } | ||
| 1857 | else | ||
| 1858 | { | ||
| 1859 | new_face_id | ||
| 1860 | = face_at_string_position (it->w, | ||
| 1861 | it->string, | ||
| 1862 | IT_STRING_CHARPOS (*it), | ||
| 1863 | (it->current.overlay_string_index >= 0 | ||
| 1864 | ? IT_CHARPOS (*it) | ||
| 1865 | : 0), | ||
| 1866 | it->region_beg_charpos, | ||
| 1867 | it->region_end_charpos, | ||
| 1868 | &next_stop, | ||
| 1869 | it->base_face_id); | ||
| 1870 | |||
| 1871 | #if 0 /* This shouldn't be neccessary. Let's check it. */ | ||
| 1872 | /* If IT is used to display a mode line we would really like to | ||
| 1873 | use the mode line face instead of the frame's default face. */ | ||
| 1874 | if (it->glyph_row == MATRIX_MODE_LINE_ROW (it->w->desired_matrix) | ||
| 1875 | && new_face_id == DEFAULT_FACE_ID) | ||
| 1876 | new_face_id = MODE_LINE_FACE_ID; | ||
| 1877 | #endif | ||
| 1878 | |||
| 1879 | /* Is this a start of a run of characters with box? Caveat: | ||
| 1880 | this can be called for a freshly allocated iterator; face_id | ||
| 1881 | is -1 is this case. We know that the new face will not | ||
| 1882 | change until the next check pos, i.e. if the new face has a | ||
| 1883 | box, all characters up to that position will have a | ||
| 1884 | box. But, as usual, we don't know whether that position | ||
| 1885 | is really the end. */ | ||
| 1886 | if (new_face_id != it->face_id) | ||
| 1887 | { | ||
| 1888 | struct face *new_face = FACE_FROM_ID (it->f, new_face_id); | ||
| 1889 | struct face *old_face = FACE_FROM_ID (it->f, it->face_id); | ||
| 1890 | |||
| 1891 | /* If new face has a box but old face hasn't, this is the | ||
| 1892 | start of a run of characters with box, i.e. it has a | ||
| 1893 | shadow on the left side. */ | ||
| 1894 | it->start_of_box_run_p | ||
| 1895 | = new_face->box && (old_face == NULL || !old_face->box); | ||
| 1896 | it->face_box_p = new_face->box != FACE_NO_BOX; | ||
| 1897 | } | ||
| 1898 | } | ||
| 1899 | |||
| 1900 | it->face_id = new_face_id; | ||
| 1901 | it->charset = CHARSET_ASCII; | ||
| 1902 | return HANDLED_NORMALLY; | ||
| 1903 | } | ||
| 1904 | |||
| 1905 | |||
| 1906 | /* Compute the face one character before or after the current position | ||
| 1907 | of IT. BEFORE_P non-zero means get the face in front of IT's | ||
| 1908 | position. Value is the id of the face. */ | ||
| 1909 | |||
| 1910 | static int | ||
| 1911 | face_before_or_after_it_pos (it, before_p) | ||
| 1912 | struct it *it; | ||
| 1913 | int before_p; | ||
| 1914 | { | ||
| 1915 | int face_id, limit; | ||
| 1916 | int next_check_charpos; | ||
| 1917 | struct text_pos pos; | ||
| 1918 | |||
| 1919 | xassert (it->s == NULL); | ||
| 1920 | |||
| 1921 | if (STRINGP (it->string)) | ||
| 1922 | { | ||
| 1923 | /* No face change past the end of the string (for the case | ||
| 1924 | we are padding with spaces). No face change before the | ||
| 1925 | string start. */ | ||
| 1926 | if (IT_STRING_CHARPOS (*it) >= XSTRING (it->string)->size | ||
| 1927 | || (IT_STRING_CHARPOS (*it) == 0 && before_p)) | ||
| 1928 | return it->face_id; | ||
| 1929 | |||
| 1930 | /* Set pos to the position before or after IT's current position. */ | ||
| 1931 | if (before_p) | ||
| 1932 | pos = string_pos (IT_STRING_CHARPOS (*it) - 1, it->string); | ||
| 1933 | else | ||
| 1934 | pos = string_pos (IT_STRING_CHARPOS (*it) + 1, it->string); | ||
| 1935 | |||
| 1936 | /* Get the face for ASCII, or unibyte. */ | ||
| 1937 | face_id | ||
| 1938 | = face_at_string_position (it->w, | ||
| 1939 | it->string, | ||
| 1940 | CHARPOS (pos), | ||
| 1941 | (it->current.overlay_string_index >= 0 | ||
| 1942 | ? IT_CHARPOS (*it) | ||
| 1943 | : 0), | ||
| 1944 | it->region_beg_charpos, | ||
| 1945 | it->region_end_charpos, | ||
| 1946 | &next_check_charpos, | ||
| 1947 | it->base_face_id); | ||
| 1948 | |||
| 1949 | /* Correct the face for charsets different from ASCII. Do it | ||
| 1950 | for the multibyte case only. The face returned above is | ||
| 1951 | suitable for unibyte text if IT->string is unibyte. */ | ||
| 1952 | if (STRING_MULTIBYTE (it->string)) | ||
| 1953 | { | ||
| 1954 | unsigned char *p = XSTRING (it->string)->data + BYTEPOS (pos); | ||
| 1955 | int rest = STRING_BYTES (XSTRING (it->string)) - BYTEPOS (pos); | ||
| 1956 | int c, len, charset; | ||
| 1957 | |||
| 1958 | c = STRING_CHAR_AND_LENGTH (p, rest, len); | ||
| 1959 | charset = CHAR_CHARSET (c); | ||
| 1960 | if (charset != CHARSET_ASCII) | ||
| 1961 | face_id = FACE_FOR_CHARSET (it->f, face_id, charset); | ||
| 1962 | } | ||
| 1963 | } | ||
| 1964 | else | ||
| 1965 | { | ||
| 1966 | limit = IT_CHARPOS (*it) + TEXT_PROP_DISTANCE_LIMIT; | ||
| 1967 | pos = it->current.pos; | ||
| 1968 | |||
| 1969 | if (before_p) | ||
| 1970 | DEC_TEXT_POS (pos); | ||
| 1971 | else | ||
| 1972 | INC_TEXT_POS (pos); | ||
| 1973 | |||
| 1974 | /* Determine face for CHARSET_ASCII, or unibyte. */ | ||
| 1975 | face_id = face_at_buffer_position (it->w, | ||
| 1976 | CHARPOS (pos), | ||
| 1977 | it->region_beg_charpos, | ||
| 1978 | it->region_end_charpos, | ||
| 1979 | &next_check_charpos, | ||
| 1980 | limit, 0); | ||
| 1981 | |||
| 1982 | /* Correct the face for charsets different from ASCII. Do it | ||
| 1983 | for the multibyte case only. The face returned above is | ||
| 1984 | suitable for unibyte text if current_buffer is unibyte. */ | ||
| 1985 | if (it->multibyte_p) | ||
| 1986 | { | ||
| 1987 | int charset = charset_at_position (pos); | ||
| 1988 | if (charset != CHARSET_ASCII) | ||
| 1989 | face_id = FACE_FOR_CHARSET (it->f, face_id, charset); | ||
| 1990 | } | ||
| 1991 | } | ||
| 1992 | |||
| 1993 | return face_id; | ||
| 1994 | } | ||
| 1995 | |||
| 1996 | |||
| 1997 | |||
| 1998 | /*********************************************************************** | ||
| 1999 | Invisible text | ||
| 2000 | ***********************************************************************/ | ||
| 2001 | |||
| 2002 | /* Set up iterator IT from invisible properties at its current | ||
| 2003 | position. Called from handle_stop. */ | ||
| 2004 | |||
| 2005 | static enum prop_handled | ||
| 2006 | handle_invisible_prop (it) | ||
| 2007 | struct it *it; | ||
| 2008 | { | ||
| 2009 | enum prop_handled handled = HANDLED_NORMALLY; | ||
| 2010 | |||
| 2011 | if (STRINGP (it->string)) | ||
| 2012 | { | ||
| 2013 | extern Lisp_Object Qinvisible; | ||
| 2014 | Lisp_Object prop, end_charpos, limit, charpos; | ||
| 2015 | |||
| 2016 | /* Get the value of the invisible text property at the | ||
| 2017 | current position. Value will be nil if there is no such | ||
| 2018 | property. */ | ||
| 2019 | XSETFASTINT (charpos, IT_STRING_CHARPOS (*it)); | ||
| 2020 | prop = Fget_text_property (charpos, Qinvisible, it->string); | ||
| 2021 | |||
| 2022 | if (!NILP (prop)) | ||
| 2023 | { | ||
| 2024 | handled = HANDLED_RECOMPUTE_PROPS; | ||
| 2025 | |||
| 2026 | /* Get the position at which the next change of the | ||
| 2027 | invisible text property can be found in IT->string. | ||
| 2028 | Value will be nil if the property value is the same for | ||
| 2029 | all the rest of IT->string. */ | ||
| 2030 | XSETINT (limit, XSTRING (it->string)->size); | ||
| 2031 | end_charpos = Fnext_single_property_change (charpos, Qinvisible, | ||
| 2032 | it->string, limit); | ||
| 2033 | |||
| 2034 | /* Text at current position is invisible. The next | ||
| 2035 | change in the property is at position end_charpos. | ||
| 2036 | Move IT's current position to that position. */ | ||
| 2037 | if (INTEGERP (end_charpos) | ||
| 2038 | && XFASTINT (end_charpos) < XFASTINT (limit)) | ||
| 2039 | { | ||
| 2040 | struct text_pos old; | ||
| 2041 | old = it->current.string_pos; | ||
| 2042 | IT_STRING_CHARPOS (*it) = XFASTINT (end_charpos); | ||
| 2043 | compute_string_pos (&it->current.string_pos, old, it->string); | ||
| 2044 | } | ||
| 2045 | else | ||
| 2046 | { | ||
| 2047 | /* The rest of the string is invisible. If this is an | ||
| 2048 | overlay string, proceed with the next overlay string | ||
| 2049 | or whatever comes and return a character from there. */ | ||
| 2050 | if (it->current.overlay_string_index >= 0) | ||
| 2051 | { | ||
| 2052 | next_overlay_string (it); | ||
| 2053 | /* Don't check for overlay strings when we just | ||
| 2054 | finished processing them. */ | ||
| 2055 | handled = HANDLED_OVERLAY_STRING_CONSUMED; | ||
| 2056 | } | ||
| 2057 | else | ||
| 2058 | { | ||
| 2059 | struct Lisp_String *s = XSTRING (it->string); | ||
| 2060 | IT_STRING_CHARPOS (*it) = s->size; | ||
| 2061 | IT_STRING_BYTEPOS (*it) = STRING_BYTES (s); | ||
| 2062 | } | ||
| 2063 | } | ||
| 2064 | } | ||
| 2065 | } | ||
| 2066 | else | ||
| 2067 | { | ||
| 2068 | int visible_p, newpos, next_stop; | ||
| 2069 | Lisp_Object pos, prop; | ||
| 2070 | |||
| 2071 | /* First of all, is there invisible text at this position? */ | ||
| 2072 | XSETFASTINT (pos, IT_CHARPOS (*it)); | ||
| 2073 | prop = Fget_char_property (pos, Qinvisible, it->window); | ||
| 2074 | |||
| 2075 | /* If we are on invisible text, skip over it. */ | ||
| 2076 | if (TEXT_PROP_MEANS_INVISIBLE (prop)) | ||
| 2077 | { | ||
| 2078 | /* Record whether we have to display an ellipsis for the | ||
| 2079 | invisible text. */ | ||
| 2080 | int display_ellipsis_p | ||
| 2081 | = TEXT_PROP_MEANS_INVISIBLE_WITH_ELLIPSIS (prop); | ||
| 2082 | |||
| 2083 | handled = HANDLED_RECOMPUTE_PROPS; | ||
| 2084 | |||
| 2085 | /* Loop skipping over invisible text. The loop is left at | ||
| 2086 | ZV or with IT on the first char being visible again. */ | ||
| 2087 | do | ||
| 2088 | { | ||
| 2089 | /* Try to skip some invisible text. Return value is the | ||
| 2090 | position reached which can be equal to IT's position | ||
| 2091 | if there is nothing invisible here. This skips both | ||
| 2092 | over invisible text properties and overlays with | ||
| 2093 | invisible property. */ | ||
| 2094 | newpos = skip_invisible (IT_CHARPOS (*it), | ||
| 2095 | &next_stop, ZV, it->window); | ||
| 2096 | |||
| 2097 | /* If we skipped nothing at all we weren't at invisible | ||
| 2098 | text in the first place. If everything to the end of | ||
| 2099 | the buffer was skipped, end the loop. */ | ||
| 2100 | if (newpos == IT_CHARPOS (*it) || newpos >= ZV) | ||
| 2101 | visible_p = 1; | ||
| 2102 | else | ||
| 2103 | { | ||
| 2104 | /* We skipped some characters but not necessarily | ||
| 2105 | all there are. Check if we ended up on visible | ||
| 2106 | text. Fget_char_property returns the property of | ||
| 2107 | the char before the given position, i.e. if we | ||
| 2108 | get visible_p = 1, this means that the char at | ||
| 2109 | newpos is visible. */ | ||
| 2110 | XSETFASTINT (pos, newpos); | ||
| 2111 | prop = Fget_char_property (pos, Qinvisible, it->window); | ||
| 2112 | visible_p = !TEXT_PROP_MEANS_INVISIBLE (prop); | ||
| 2113 | } | ||
| 2114 | |||
| 2115 | /* If we ended up on invisible text, proceed to | ||
| 2116 | skip starting with next_stop. */ | ||
| 2117 | if (!visible_p) | ||
| 2118 | IT_CHARPOS (*it) = next_stop; | ||
| 2119 | } | ||
| 2120 | while (!visible_p); | ||
| 2121 | |||
| 2122 | /* The position newpos is now either ZV or on visible text. */ | ||
| 2123 | IT_CHARPOS (*it) = newpos; | ||
| 2124 | IT_BYTEPOS (*it) = CHAR_TO_BYTE (newpos); | ||
| 2125 | |||
| 2126 | /* Maybe return `...' next for the end of the invisible text. */ | ||
| 2127 | if (display_ellipsis_p) | ||
| 2128 | { | ||
| 2129 | if (it->dp | ||
| 2130 | && VECTORP (DISP_INVIS_VECTOR (it->dp))) | ||
| 2131 | { | ||
| 2132 | struct Lisp_Vector *v = XVECTOR (DISP_INVIS_VECTOR (it->dp)); | ||
| 2133 | it->dpvec = v->contents; | ||
| 2134 | it->dpend = v->contents + v->size; | ||
| 2135 | } | ||
| 2136 | else | ||
| 2137 | { | ||
| 2138 | /* Default `...'. */ | ||
| 2139 | it->dpvec = default_invis_vector; | ||
| 2140 | it->dpend = default_invis_vector + 3; | ||
| 2141 | } | ||
| 2142 | |||
| 2143 | /* The ellipsis display does not replace the display of | ||
| 2144 | the character at the new position. Indicate this by | ||
| 2145 | setting IT->dpvec_char_len to zero. */ | ||
| 2146 | it->dpvec_char_len = 0; | ||
| 2147 | |||
| 2148 | it->current.dpvec_index = 0; | ||
| 2149 | it->method = next_element_from_display_vector; | ||
| 2150 | } | ||
| 2151 | } | ||
| 2152 | } | ||
| 2153 | |||
| 2154 | return handled; | ||
| 2155 | } | ||
| 2156 | |||
| 2157 | |||
| 2158 | |||
| 2159 | /*********************************************************************** | ||
| 2160 | 'display' property | ||
| 2161 | ***********************************************************************/ | ||
| 2162 | |||
| 2163 | /* Set up iterator IT from `display' property at its current position. | ||
| 2164 | Called from handle_stop. */ | ||
| 2165 | |||
| 2166 | static enum prop_handled | ||
| 2167 | handle_display_prop (it) | ||
| 2168 | struct it *it; | ||
| 2169 | { | ||
| 2170 | Lisp_Object prop, object; | ||
| 2171 | struct text_pos *position; | ||
| 2172 | int space_or_image_found_p; | ||
| 2173 | |||
| 2174 | if (STRINGP (it->string)) | ||
| 2175 | { | ||
| 2176 | object = it->string; | ||
| 2177 | position = &it->current.string_pos; | ||
| 2178 | } | ||
| 2179 | else | ||
| 2180 | { | ||
| 2181 | object = Qnil; | ||
| 2182 | position = &it->current.pos; | ||
| 2183 | } | ||
| 2184 | |||
| 2185 | /* Reset those iterator values set from display property values. */ | ||
| 2186 | it->font_height = Qnil; | ||
| 2187 | it->space_width = Qnil; | ||
| 2188 | it->voffset = 0; | ||
| 2189 | |||
| 2190 | /* We don't support recursive `display' properties, i.e. string | ||
| 2191 | values that have a string `display' property, that have a string | ||
| 2192 | `display' property etc. */ | ||
| 2193 | if (!it->string_from_display_prop_p) | ||
| 2194 | it->area = TEXT_AREA; | ||
| 2195 | |||
| 2196 | prop = Fget_char_property (make_number (position->charpos), | ||
| 2197 | Qdisplay, object); | ||
| 2198 | if (NILP (prop)) | ||
| 2199 | return HANDLED_NORMALLY; | ||
| 2200 | |||
| 2201 | space_or_image_found_p = 0; | ||
| 2202 | if (CONSP (prop) && CONSP (XCAR (prop))) | ||
| 2203 | { | ||
| 2204 | while (CONSP (prop)) | ||
| 2205 | { | ||
| 2206 | if (handle_single_display_prop (it, XCAR (prop), object, position)) | ||
| 2207 | space_or_image_found_p = 1; | ||
| 2208 | prop = XCDR (prop); | ||
| 2209 | } | ||
| 2210 | } | ||
| 2211 | else if (VECTORP (prop)) | ||
| 2212 | { | ||
| 2213 | int i; | ||
| 2214 | for (i = 0; i < XVECTOR (prop)->size; ++i) | ||
| 2215 | if (handle_single_display_prop (it, XVECTOR (prop)->contents[i], | ||
| 2216 | object, position)) | ||
| 2217 | space_or_image_found_p = 1; | ||
| 2218 | } | ||
| 2219 | else | ||
| 2220 | { | ||
| 2221 | if (handle_single_display_prop (it, prop, object, position)) | ||
| 2222 | space_or_image_found_p = 1; | ||
| 2223 | } | ||
| 2224 | |||
| 2225 | return space_or_image_found_p ? HANDLED_RETURN : HANDLED_NORMALLY; | ||
| 2226 | } | ||
| 2227 | |||
| 2228 | |||
| 2229 | /* Value is the position of the end of the `display' property stating | ||
| 2230 | at START_POS in OBJECT. */ | ||
| 2231 | |||
| 2232 | static struct text_pos | ||
| 2233 | display_prop_end (it, object, start_pos) | ||
| 2234 | struct it *it; | ||
| 2235 | Lisp_Object object; | ||
| 2236 | struct text_pos start_pos; | ||
| 2237 | { | ||
| 2238 | Lisp_Object end; | ||
| 2239 | struct text_pos end_pos; | ||
| 2240 | |||
| 2241 | /* Characters having this form of property are not displayed, so | ||
| 2242 | we have to find the end of the property. */ | ||
| 2243 | end = Fnext_single_property_change (make_number (start_pos.charpos), | ||
| 2244 | Qdisplay, object, Qnil); | ||
| 2245 | if (NILP (end)) | ||
| 2246 | { | ||
| 2247 | /* A nil value of `end' means there are no changes of the | ||
| 2248 | property to the end of the buffer or string. */ | ||
| 2249 | if (it->current.overlay_string_index >= 0) | ||
| 2250 | end_pos.charpos = XSTRING (it->string)->size; | ||
| 2251 | else | ||
| 2252 | end_pos.charpos = it->end_charpos; | ||
| 2253 | } | ||
| 2254 | else | ||
| 2255 | end_pos.charpos = XFASTINT (end); | ||
| 2256 | |||
| 2257 | if (STRINGP (it->string)) | ||
| 2258 | compute_string_pos (&end_pos, start_pos, it->string); | ||
| 2259 | else | ||
| 2260 | end_pos.bytepos = CHAR_TO_BYTE (end_pos.charpos); | ||
| 2261 | |||
| 2262 | return end_pos; | ||
| 2263 | } | ||
| 2264 | |||
| 2265 | |||
| 2266 | /* Set up IT from a single `display' sub-property value PROP. OBJECT | ||
| 2267 | is the object in which the `display' property was found. *POSITION | ||
| 2268 | is the position at which it was found. | ||
| 2269 | |||
| 2270 | If PROP is a `space' or `image' sub-property, set *POSITION to the | ||
| 2271 | end position of the `display' property. | ||
| 2272 | |||
| 2273 | Value is non-zero if a `space' or `image' property value was found. */ | ||
| 2274 | |||
| 2275 | static int | ||
| 2276 | handle_single_display_prop (it, prop, object, position) | ||
| 2277 | struct it *it; | ||
| 2278 | Lisp_Object prop; | ||
| 2279 | Lisp_Object object; | ||
| 2280 | struct text_pos *position; | ||
| 2281 | { | ||
| 2282 | Lisp_Object value; | ||
| 2283 | int space_or_image_found_p = 0; | ||
| 2284 | |||
| 2285 | Lisp_Object form; | ||
| 2286 | |||
| 2287 | /* If PROP is a list of the form `(:when FORM VALUE)', FORM is | ||
| 2288 | evaluated. If the result is nil, VALUE is ignored. */ | ||
| 2289 | form = Qt; | ||
| 2290 | if (CONSP (prop) && EQ (XCAR (prop), QCwhen)) | ||
| 2291 | { | ||
| 2292 | prop = XCDR (prop); | ||
| 2293 | if (!CONSP (prop)) | ||
| 2294 | return 0; | ||
| 2295 | form = XCAR (prop); | ||
| 2296 | prop = XCDR (prop); | ||
| 2297 | if (!CONSP (prop)) | ||
| 2298 | return 0; | ||
| 2299 | prop = XCAR (prop); | ||
| 2300 | } | ||
| 2301 | |||
| 2302 | if (!NILP (form) && !EQ (form, Qt)) | ||
| 2303 | { | ||
| 2304 | struct gcpro gcpro1; | ||
| 2305 | struct text_pos end_pos, pt; | ||
| 2306 | |||
| 2307 | end_pos = display_prop_end (it, object, *position); | ||
| 2308 | GCPRO1 (form); | ||
| 2309 | |||
| 2310 | /* Temporarily set point to the end position, and then evaluate | ||
| 2311 | the form. This makes `(eolp)' work as FORM. */ | ||
| 2312 | CHARPOS (pt) = PT; | ||
| 2313 | BYTEPOS (pt) = PT_BYTE; | ||
| 2314 | TEMP_SET_PT_BOTH (CHARPOS (end_pos), BYTEPOS (end_pos)); | ||
| 2315 | form = eval_form (form); | ||
| 2316 | TEMP_SET_PT_BOTH (CHARPOS (pt), BYTEPOS (pt)); | ||
| 2317 | UNGCPRO; | ||
| 2318 | } | ||
| 2319 | |||
| 2320 | if (NILP (form)) | ||
| 2321 | return 0; | ||
| 2322 | |||
| 2323 | if (CONSP (prop) | ||
| 2324 | && EQ (XCAR (prop), Qheight) | ||
| 2325 | && CONSP (XCDR (prop))) | ||
| 2326 | { | ||
| 2327 | if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f)) | ||
| 2328 | return 0; | ||
| 2329 | |||
| 2330 | /* `(height HEIGHT)'. */ | ||
| 2331 | it->font_height = XCAR (XCDR (prop)); | ||
| 2332 | if (!NILP (it->font_height)) | ||
| 2333 | { | ||
| 2334 | struct face *face = FACE_FROM_ID (it->f, it->face_id); | ||
| 2335 | int new_height = -1; | ||
| 2336 | |||
| 2337 | if (CONSP (it->font_height) | ||
| 2338 | && (EQ (XCAR (it->font_height), Qplus) | ||
| 2339 | || EQ (XCAR (it->font_height), Qminus)) | ||
| 2340 | && CONSP (XCDR (it->font_height)) | ||
| 2341 | && INTEGERP (XCAR (XCDR (it->font_height)))) | ||
| 2342 | { | ||
| 2343 | /* `(+ N)' or `(- N)' where N is an integer. */ | ||
| 2344 | int steps = XINT (XCAR (XCDR (it->font_height))); | ||
| 2345 | if (EQ (XCAR (it->font_height), Qplus)) | ||
| 2346 | steps = - steps; | ||
| 2347 | it->face_id = smaller_face (it->f, it->face_id, steps); | ||
| 2348 | } | ||
| 2349 | else if (SYMBOLP (it->font_height)) | ||
| 2350 | { | ||
| 2351 | /* Call function with current height as argument. | ||
| 2352 | Value is the new height. */ | ||
| 2353 | Lisp_Object form, height; | ||
| 2354 | struct gcpro gcpro1; | ||
| 2355 | |||
| 2356 | height = face->lface[LFACE_HEIGHT_INDEX]; | ||
| 2357 | form = Fcons (it->font_height, Fcons (height, Qnil)); | ||
| 2358 | GCPRO1 (form); | ||
| 2359 | height = eval_form (form); | ||
| 2360 | if (NUMBERP (height)) | ||
| 2361 | new_height = XFLOATINT (height); | ||
| 2362 | UNGCPRO; | ||
| 2363 | } | ||
| 2364 | else if (NUMBERP (it->font_height)) | ||
| 2365 | { | ||
| 2366 | /* Value is a multiple of the canonical char height. */ | ||
| 2367 | struct face *face; | ||
| 2368 | |||
| 2369 | face = FACE_FROM_ID (it->f, DEFAULT_FACE_ID); | ||
| 2370 | new_height = (XFLOATINT (it->font_height) | ||
| 2371 | * XINT (face->lface[LFACE_HEIGHT_INDEX])); | ||
| 2372 | } | ||
| 2373 | else | ||
| 2374 | { | ||
| 2375 | /* Evaluate IT->font_height with `height' bound to the | ||
| 2376 | current specified height to get the new height. */ | ||
| 2377 | Lisp_Object value; | ||
| 2378 | int count = specpdl_ptr - specpdl; | ||
| 2379 | |||
| 2380 | specbind (Qheight, face->lface[LFACE_HEIGHT_INDEX]); | ||
| 2381 | value = eval_form (it->font_height); | ||
| 2382 | unbind_to (count, Qnil); | ||
| 2383 | |||
| 2384 | if (NUMBERP (value)) | ||
| 2385 | new_height = XFLOATINT (value); | ||
| 2386 | } | ||
| 2387 | |||
| 2388 | if (new_height > 0) | ||
| 2389 | it->face_id = face_with_height (it->f, it->face_id, new_height); | ||
| 2390 | } | ||
| 2391 | } | ||
| 2392 | else if (CONSP (prop) | ||
| 2393 | && EQ (XCAR (prop), Qspace_width) | ||
| 2394 | && CONSP (XCDR (prop))) | ||
| 2395 | { | ||
| 2396 | /* `(space_width WIDTH)'. */ | ||
| 2397 | if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f)) | ||
| 2398 | return 0; | ||
| 2399 | |||
| 2400 | value = XCAR (XCDR (prop)); | ||
| 2401 | if (NUMBERP (value) && XFLOATINT (value) > 0) | ||
| 2402 | it->space_width = value; | ||
| 2403 | } | ||
| 2404 | else if (CONSP (prop) | ||
| 2405 | && EQ (XCAR (prop), Qraise) | ||
| 2406 | && CONSP (XCDR (prop))) | ||
| 2407 | { | ||
| 2408 | #ifdef HAVE_WINDOW_SYSTEM | ||
| 2409 | /* `(raise FACTOR)'. */ | ||
| 2410 | if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f)) | ||
| 2411 | return 0; | ||
| 2412 | |||
| 2413 | value = XCAR (XCDR (prop)); | ||
| 2414 | if (NUMBERP (value)) | ||
| 2415 | { | ||
| 2416 | struct face *face = FACE_FROM_ID (it->f, it->face_id); | ||
| 2417 | it->voffset = - (XFLOATINT (value) | ||
| 2418 | * (face->font->ascent + face->font->descent)); | ||
| 2419 | } | ||
| 2420 | #endif /* HAVE_WINDOW_SYSTEM */ | ||
| 2421 | } | ||
| 2422 | else if (!it->string_from_display_prop_p) | ||
| 2423 | { | ||
| 2424 | /* `(left-margin VALUE)' or `(right-margin VALUE) | ||
| 2425 | or `(nil VALUE)' or VALUE. */ | ||
| 2426 | Lisp_Object location, value; | ||
| 2427 | struct text_pos start_pos; | ||
| 2428 | int valid_p; | ||
| 2429 | |||
| 2430 | /* Characters having this form of property are not displayed, so | ||
| 2431 | we have to find the end of the property. */ | ||
| 2432 | space_or_image_found_p = 1; | ||
| 2433 | start_pos = *position; | ||
| 2434 | *position = display_prop_end (it, object, start_pos); | ||
| 2435 | |||
| 2436 | /* Let's stop at the new position and assume that all | ||
| 2437 | text properties change there. */ | ||
| 2438 | it->stop_charpos = position->charpos; | ||
| 2439 | |||
| 2440 | if (CONSP (prop) | ||
| 2441 | && !EQ (XCAR (prop), Qspace) | ||
| 2442 | && !EQ (XCAR (prop), Qimage)) | ||
| 2443 | { | ||
| 2444 | location = XCAR (prop); | ||
| 2445 | value = XCDR (prop); | ||
| 2446 | } | ||
| 2447 | else | ||
| 2448 | { | ||
| 2449 | location = Qnil; | ||
| 2450 | value = prop; | ||
| 2451 | } | ||
| 2452 | |||
| 2453 | #ifdef HAVE_WINDOW_SYSTEM | ||
| 2454 | if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f)) | ||
| 2455 | valid_p = STRINGP (value); | ||
| 2456 | else | ||
| 2457 | valid_p = (STRINGP (value) | ||
| 2458 | || (CONSP (value) && EQ (XCAR (value), Qspace)) | ||
| 2459 | || valid_image_p (value)); | ||
| 2460 | #else /* not HAVE_WINDOW_SYSTEM */ | ||
| 2461 | valid_p = STRINGP (value); | ||
| 2462 | #endif /* not HAVE_WINDOW_SYSTEM */ | ||
| 2463 | |||
| 2464 | if ((EQ (location, Qleft_margin) | ||
| 2465 | || EQ (location, Qright_margin) | ||
| 2466 | || NILP (location)) | ||
| 2467 | && valid_p) | ||
| 2468 | { | ||
| 2469 | /* Save current settings of IT so that we can restore them | ||
| 2470 | when we are finished with the glyph property value. */ | ||
| 2471 | push_it (it); | ||
| 2472 | |||
| 2473 | if (NILP (location)) | ||
| 2474 | it->area = TEXT_AREA; | ||
| 2475 | else if (EQ (location, Qleft_margin)) | ||
| 2476 | it->area = LEFT_MARGIN_AREA; | ||
| 2477 | else | ||
| 2478 | it->area = RIGHT_MARGIN_AREA; | ||
| 2479 | |||
| 2480 | if (STRINGP (value)) | ||
| 2481 | { | ||
| 2482 | it->string = value; | ||
| 2483 | it->multibyte_p = STRING_MULTIBYTE (it->string); | ||
| 2484 | it->current.overlay_string_index = -1; | ||
| 2485 | IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = 0; | ||
| 2486 | it->end_charpos = it->string_nchars | ||
| 2487 | = XSTRING (it->string)->size; | ||
| 2488 | it->method = next_element_from_string; | ||
| 2489 | it->stop_charpos = 0; | ||
| 2490 | it->string_from_display_prop_p = 1; | ||
| 2491 | } | ||
| 2492 | else if (CONSP (value) && EQ (XCAR (value), Qspace)) | ||
| 2493 | { | ||
| 2494 | it->method = next_element_from_stretch; | ||
| 2495 | it->object = value; | ||
| 2496 | it->current.pos = it->position = start_pos; | ||
| 2497 | } | ||
| 2498 | #ifdef HAVE_WINDOW_SYSTEM | ||
| 2499 | else | ||
| 2500 | { | ||
| 2501 | it->what = IT_IMAGE; | ||
| 2502 | it->image_id = lookup_image (it->f, value); | ||
| 2503 | it->position = start_pos; | ||
| 2504 | it->object = NILP (object) ? it->w->buffer : object; | ||
| 2505 | it->method = next_element_from_image; | ||
| 2506 | |||
| 2507 | /* Say that we don't have consumed the characters with | ||
| 2508 | `display' property yet. The call to pop_it in | ||
| 2509 | set_iterator_to_next will clean this up. */ | ||
| 2510 | *position = start_pos; | ||
| 2511 | } | ||
| 2512 | #endif /* HAVE_WINDOW_SYSTEM */ | ||
| 2513 | } | ||
| 2514 | } | ||
| 2515 | |||
| 2516 | return space_or_image_found_p; | ||
| 2517 | } | ||
| 2518 | |||
| 2519 | |||
| 2520 | |||
| 2521 | /*********************************************************************** | ||
| 2522 | Overlay strings | ||
| 2523 | ***********************************************************************/ | ||
| 2524 | |||
| 2525 | /* The following structure is used to record overlay strings for | ||
| 2526 | later sorting in load_overlay_strings. */ | ||
| 2527 | |||
| 2528 | struct overlay_entry | ||
| 2529 | { | ||
| 2530 | Lisp_Object string; | ||
| 2531 | int priority; | ||
| 2532 | int after_string_p; | ||
| 2533 | }; | ||
| 2534 | |||
| 2535 | |||
| 2536 | /* Set up iterator IT from overlay strings at its current position. | ||
| 2537 | Called from handle_stop. */ | ||
| 2538 | |||
| 2539 | static enum prop_handled | ||
| 2540 | handle_overlay_change (it) | ||
| 2541 | struct it *it; | ||
| 2542 | { | ||
| 2543 | /* Overlays are handled in current_buffer only. */ | ||
| 2544 | if (STRINGP (it->string)) | ||
| 2545 | return HANDLED_NORMALLY; | ||
| 2546 | else | ||
| 2547 | return (get_overlay_strings (it) | ||
| 2548 | ? HANDLED_RECOMPUTE_PROPS | ||
| 2549 | : HANDLED_NORMALLY); | ||
| 2550 | } | ||
| 2551 | |||
| 2552 | |||
| 2553 | /* Set up the next overlay string for delivery by IT, if there is an | ||
| 2554 | overlay string to deliver. Called by set_iterator_to_next when the | ||
| 2555 | end of the current overlay string is reached. If there are more | ||
| 2556 | overlay strings to display, IT->string and | ||
| 2557 | IT->current.overlay_string_index are set appropriately here. | ||
| 2558 | Otherwise IT->string is set to nil. */ | ||
| 2559 | |||
| 2560 | static void | ||
| 2561 | next_overlay_string (it) | ||
| 2562 | struct it *it; | ||
| 2563 | { | ||
| 2564 | ++it->current.overlay_string_index; | ||
| 2565 | if (it->current.overlay_string_index == it->n_overlay_strings) | ||
| 2566 | { | ||
| 2567 | /* No more overlay strings. Restore IT's settings to what | ||
| 2568 | they were before overlay strings were processed, and | ||
| 2569 | continue to deliver from current_buffer. */ | ||
| 2570 | pop_it (it); | ||
| 2571 | xassert (it->stop_charpos >= BEGV | ||
| 2572 | && it->stop_charpos <= it->end_charpos); | ||
| 2573 | it->string = Qnil; | ||
| 2574 | it->current.overlay_string_index = -1; | ||
| 2575 | SET_TEXT_POS (it->current.string_pos, -1, -1); | ||
| 2576 | it->n_overlay_strings = 0; | ||
| 2577 | it->method = next_element_from_buffer; | ||
| 2578 | } | ||
| 2579 | else | ||
| 2580 | { | ||
| 2581 | /* There are more overlay strings to process. If | ||
| 2582 | IT->current.overlay_string_index has advanced to a position | ||
| 2583 | where we must load IT->overlay_strings with more strings, do | ||
| 2584 | it. */ | ||
| 2585 | int i = it->current.overlay_string_index % OVERLAY_STRING_CHUNK_SIZE; | ||
| 2586 | |||
| 2587 | if (it->current.overlay_string_index && i == 0) | ||
| 2588 | load_overlay_strings (it); | ||
| 2589 | |||
| 2590 | /* Initialize IT to deliver display elements from the overlay | ||
| 2591 | string. */ | ||
| 2592 | it->string = it->overlay_strings[i]; | ||
| 2593 | it->multibyte_p = STRING_MULTIBYTE (it->string); | ||
| 2594 | SET_TEXT_POS (it->current.string_pos, 0, 0); | ||
| 2595 | it->method = next_element_from_string; | ||
| 2596 | it->stop_charpos = 0; | ||
| 2597 | } | ||
| 2598 | |||
| 2599 | CHECK_IT (it); | ||
| 2600 | } | ||
| 2601 | |||
| 2602 | |||
| 2603 | /* Compare two overlay_entry structures E1 and E2. Used as a | ||
| 2604 | comparison function for qsort in load_overlay_strings. Overlay | ||
| 2605 | strings for the same position are sorted so that | ||
| 2606 | |||
| 2607 | 1. All after-strings come in front of before-strings. | ||
| 2608 | |||
| 2609 | 2. Within after-strings, strings are sorted so that overlay strings | ||
| 2610 | from overlays with higher priorities come first. | ||
| 2611 | |||
| 2612 | 2. Within before-strings, strings are sorted so that overlay | ||
| 2613 | strings from overlays with higher priorities come last. | ||
| 2614 | |||
| 2615 | Value is analogous to strcmp. */ | ||
| 2616 | |||
| 2617 | |||
| 2618 | static int | ||
| 2619 | compare_overlay_entries (e1, e2) | ||
| 2620 | void *e1, *e2; | ||
| 2621 | { | ||
| 2622 | struct overlay_entry *entry1 = (struct overlay_entry *) e1; | ||
| 2623 | struct overlay_entry *entry2 = (struct overlay_entry *) e2; | ||
| 2624 | int result; | ||
| 2625 | |||
| 2626 | if (entry1->after_string_p != entry2->after_string_p) | ||
| 2627 | /* Let after-strings appear in front of before-strings. */ | ||
| 2628 | result = entry1->after_string_p ? -1 : 1; | ||
| 2629 | else if (entry1->after_string_p) | ||
| 2630 | /* After-strings sorted in order of decreasing priority. */ | ||
| 2631 | result = entry2->priority - entry1->priority; | ||
| 2632 | else | ||
| 2633 | /* Before-strings sorted in order of increasing priority. */ | ||
| 2634 | result = entry1->priority - entry2->priority; | ||
| 2635 | |||
| 2636 | return result; | ||
| 2637 | } | ||
| 2638 | |||
| 2639 | |||
| 2640 | /* Load the vector IT->overlay_strings with overlay strings from IT's | ||
| 2641 | current buffer position. Set IT->n_overlays to the total number of | ||
| 2642 | overlay strings found. | ||
| 2643 | |||
| 2644 | Overlay strings are processed OVERLAY_STRING_CHUNK_SIZE strings at | ||
| 2645 | a time. On entry into load_overlay_strings, | ||
| 2646 | IT->current.overlay_string_index gives the number of overlay | ||
| 2647 | strings that have already been loaded by previous calls to this | ||
| 2648 | function. | ||
| 2649 | |||
| 2650 | Overlay strings are sorted so that after-string strings come in | ||
| 2651 | front of before-string strings. Within before and after-strings, | ||
| 2652 | strings are sorted by overlay priority. See also function | ||
| 2653 | compare_overlay_entries. */ | ||
| 2654 | |||
| 2655 | static void | ||
| 2656 | load_overlay_strings (it) | ||
| 2657 | struct it *it; | ||
| 2658 | { | ||
| 2659 | extern Lisp_Object Qafter_string, Qbefore_string, Qwindow, Qpriority; | ||
| 2660 | Lisp_Object ov, overlay, window, str; | ||
| 2661 | int start, end; | ||
| 2662 | int size = 20; | ||
| 2663 | int n = 0, i, j; | ||
| 2664 | struct overlay_entry *entries | ||
| 2665 | = (struct overlay_entry *) alloca (size * sizeof *entries); | ||
| 2666 | |||
| 2667 | /* Append the overlay string STRING of overlay OVERLAY to vector | ||
| 2668 | `entries' which has size `size' and currently contains `n' | ||
| 2669 | elements. AFTER_P non-zero means STRING is an after-string of | ||
| 2670 | OVERLAY. */ | ||
| 2671 | #define RECORD_OVERLAY_STRING(OVERLAY, STRING, AFTER_P) \ | ||
| 2672 | do \ | ||
| 2673 | { \ | ||
| 2674 | Lisp_Object priority; \ | ||
| 2675 | \ | ||
| 2676 | if (n == size) \ | ||
| 2677 | { \ | ||
| 2678 | int new_size = 2 * size; \ | ||
| 2679 | struct overlay_entry *old = entries; \ | ||
| 2680 | entries = \ | ||
| 2681 | (struct overlay_entry *) alloca (new_size \ | ||
| 2682 | * sizeof *entries); \ | ||
| 2683 | bcopy (old, entries, size * sizeof *entries); \ | ||
| 2684 | size = new_size; \ | ||
| 2685 | } \ | ||
| 2686 | \ | ||
| 2687 | entries[n].string = (STRING); \ | ||
| 2688 | priority = Foverlay_get ((OVERLAY), Qpriority); \ | ||
| 2689 | entries[n].priority \ | ||
| 2690 | = INTEGERP (priority) ? XFASTINT (priority) : 0; \ | ||
| 2691 | entries[n].after_string_p = (AFTER_P); \ | ||
| 2692 | ++n; \ | ||
| 2693 | } \ | ||
| 2694 | while (0) | ||
| 2695 | |||
| 2696 | /* Process overlay before the overlay center. */ | ||
| 2697 | for (ov = current_buffer->overlays_before; | ||
| 2698 | CONSP (ov); | ||
| 2699 | ov = XCONS (ov)->cdr) | ||
| 2700 | { | ||
| 2701 | overlay = XCONS (ov)->car; | ||
| 2702 | xassert (OVERLAYP (overlay)); | ||
| 2703 | start = OVERLAY_POSITION (OVERLAY_START (overlay)); | ||
| 2704 | end = OVERLAY_POSITION (OVERLAY_END (overlay)); | ||
| 2705 | |||
| 2706 | if (end < IT_CHARPOS (*it)) | ||
| 2707 | break; | ||
| 2708 | |||
| 2709 | /* Skip this overlay if it doesn't start or end at IT's current | ||
| 2710 | position. */ | ||
| 2711 | if (end != IT_CHARPOS (*it) && start != IT_CHARPOS (*it)) | ||
| 2712 | continue; | ||
| 2713 | |||
| 2714 | /* Skip this overlay if it doesn't apply to IT->w. */ | ||
| 2715 | window = Foverlay_get (overlay, Qwindow); | ||
| 2716 | if (WINDOWP (window) && XWINDOW (window) != it->w) | ||
| 2717 | continue; | ||
| 2718 | |||
| 2719 | /* If overlay has a non-empty before-string, record it. */ | ||
| 2720 | if (start == IT_CHARPOS (*it) | ||
| 2721 | && (str = Foverlay_get (overlay, Qbefore_string), STRINGP (str)) | ||
| 2722 | && XSTRING (str)->size) | ||
| 2723 | RECORD_OVERLAY_STRING (overlay, str, 0); | ||
| 2724 | |||
| 2725 | /* If overlay has a non-empty after-string, record it. */ | ||
| 2726 | if (end == IT_CHARPOS (*it) | ||
| 2727 | && (str = Foverlay_get (overlay, Qafter_string), STRINGP (str)) | ||
| 2728 | && XSTRING (str)->size) | ||
| 2729 | RECORD_OVERLAY_STRING (overlay, str, 1); | ||
| 2730 | } | ||
| 2731 | |||
| 2732 | /* Process overlays after the overlay center. */ | ||
| 2733 | for (ov = current_buffer->overlays_after; | ||
| 2734 | CONSP (ov); | ||
| 2735 | ov = XCONS (ov)->cdr) | ||
| 2736 | { | ||
| 2737 | overlay = XCONS (ov)->car; | ||
| 2738 | xassert (OVERLAYP (overlay)); | ||
| 2739 | start = OVERLAY_POSITION (OVERLAY_START (overlay)); | ||
| 2740 | end = OVERLAY_POSITION (OVERLAY_END (overlay)); | ||
| 2741 | |||
| 2742 | if (start > IT_CHARPOS (*it)) | ||
| 2743 | break; | ||
| 2744 | |||
| 2745 | /* Skip this overlay if it doesn't start or end at IT's current | ||
| 2746 | position. */ | ||
| 2747 | if (end != IT_CHARPOS (*it) && start != IT_CHARPOS (*it)) | ||
| 2748 | continue; | ||
| 2749 | |||
| 2750 | /* Skip this overlay if it doesn't apply to IT->w. */ | ||
| 2751 | window = Foverlay_get (overlay, Qwindow); | ||
| 2752 | if (WINDOWP (window) && XWINDOW (window) != it->w) | ||
| 2753 | continue; | ||
| 2754 | |||
| 2755 | /* If overlay has a non-empty before-string, record it. */ | ||
| 2756 | if (start == IT_CHARPOS (*it) | ||
| 2757 | && (str = Foverlay_get (overlay, Qbefore_string), STRINGP (str)) | ||
| 2758 | && XSTRING (str)->size) | ||
| 2759 | RECORD_OVERLAY_STRING (overlay, str, 0); | ||
| 2760 | |||
| 2761 | /* If overlay has a non-empty after-string, record it. */ | ||
| 2762 | if (end == IT_CHARPOS (*it) | ||
| 2763 | && (str = Foverlay_get (overlay, Qafter_string), STRINGP (str)) | ||
| 2764 | && XSTRING (str)->size) | ||
| 2765 | RECORD_OVERLAY_STRING (overlay, str, 1); | ||
| 2766 | } | ||
| 2767 | |||
| 2768 | #undef RECORD_OVERLAY_STRING | ||
| 2769 | |||
| 2770 | /* Sort entries. */ | ||
| 2771 | qsort (entries, n, sizeof *entries, compare_overlay_entries); | ||
| 2772 | |||
| 2773 | /* Record the total number of strings to process. */ | ||
| 2774 | it->n_overlay_strings = n; | ||
| 2775 | |||
| 2776 | /* IT->current.overlay_string_index is the number of overlay strings | ||
| 2777 | that have already been consumed by IT. Copy some of the | ||
| 2778 | remaining overlay strings to IT->overlay_strings. */ | ||
| 2779 | i = 0; | ||
| 2780 | j = it->current.overlay_string_index; | ||
| 2781 | while (i < OVERLAY_STRING_CHUNK_SIZE && j < n) | ||
| 2782 | it->overlay_strings[i++] = entries[j++].string; | ||
| 2783 | |||
| 2784 | CHECK_IT (it); | ||
| 2785 | } | ||
| 2786 | |||
| 2787 | |||
| 2788 | /* Get the first chunk of overlay strings at IT's current buffer | ||
| 2789 | position. Value is non-zero if at least one overlay string was | ||
| 2790 | found. */ | ||
| 2791 | |||
| 2792 | static int | ||
| 2793 | get_overlay_strings (it) | ||
| 2794 | struct it *it; | ||
| 2795 | { | ||
| 2796 | /* Get the first OVERLAY_STRING_CHUNK_SIZE overlay strings to | ||
| 2797 | process. This fills IT->overlay_strings with strings, and sets | ||
| 2798 | IT->n_overlay_strings to the total number of strings to process. | ||
| 2799 | IT->pos.overlay_string_index has to be set temporarily to zero | ||
| 2800 | because load_overlay_strings needs this; it must be set to -1 | ||
| 2801 | when no overlay strings are found because a zero value would | ||
| 2802 | indicate a position in the first overlay string. */ | ||
| 2803 | it->current.overlay_string_index = 0; | ||
| 2804 | load_overlay_strings (it); | ||
| 2805 | |||
| 2806 | /* If we found overlay strings, set up IT to deliver display | ||
| 2807 | elements from the first one. Otherwise set up IT to deliver | ||
| 2808 | from current_buffer. */ | ||
| 2809 | if (it->n_overlay_strings) | ||
| 2810 | { | ||
| 2811 | /* Make sure we know settings in current_buffer, so that we can | ||
| 2812 | restore meaningful values when we're done with the overlay | ||
| 2813 | strings. */ | ||
| 2814 | compute_stop_pos (it); | ||
| 2815 | xassert (it->face_id >= 0); | ||
| 2816 | |||
| 2817 | /* Save IT's settings. They are restored after all overlay | ||
| 2818 | strings have been processed. */ | ||
| 2819 | xassert (it->sp == 0); | ||
| 2820 | push_it (it); | ||
| 2821 | |||
| 2822 | /* Set up IT to deliver display elements from the first overlay | ||
| 2823 | string. */ | ||
| 2824 | IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = 0; | ||
| 2825 | it->stop_charpos = 0; | ||
| 2826 | it->string = it->overlay_strings[0]; | ||
| 2827 | it->multibyte_p = STRING_MULTIBYTE (it->string); | ||
| 2828 | xassert (STRINGP (it->string)); | ||
| 2829 | it->method = next_element_from_string; | ||
| 2830 | } | ||
| 2831 | else | ||
| 2832 | { | ||
| 2833 | it->string = Qnil; | ||
| 2834 | it->current.overlay_string_index = -1; | ||
| 2835 | it->method = next_element_from_buffer; | ||
| 2836 | } | ||
| 2837 | |||
| 2838 | CHECK_IT (it); | ||
| 2839 | |||
| 2840 | /* Value is non-zero if we found at least one overlay string. */ | ||
| 2841 | return STRINGP (it->string); | ||
| 2842 | } | ||
| 2843 | |||
| 2844 | |||
| 2845 | |||
| 2846 | /*********************************************************************** | ||
| 2847 | Saving and restoring state | ||
| 2848 | ***********************************************************************/ | ||
| 2849 | |||
| 2850 | /* Save current settings of IT on IT->stack. Called, for example, | ||
| 2851 | before setting up IT for an overlay string, to be able to restore | ||
| 2852 | IT's settings to what they were after the overlay string has been | ||
| 2853 | processed. */ | ||
| 2854 | |||
| 2855 | static void | ||
| 2856 | push_it (it) | ||
| 2857 | struct it *it; | ||
| 2858 | { | ||
| 2859 | struct iterator_stack_entry *p; | ||
| 2860 | |||
| 2861 | xassert (it->sp < 2); | ||
| 2862 | p = it->stack + it->sp; | ||
| 2863 | |||
| 2864 | p->stop_charpos = it->stop_charpos; | ||
| 2865 | xassert (it->face_id >= 0); | ||
| 2866 | p->face_id = it->face_id; | ||
| 2867 | p->string = it->string; | ||
| 2868 | p->pos = it->current; | ||
| 2869 | p->end_charpos = it->end_charpos; | ||
| 2870 | p->string_nchars = it->string_nchars; | ||
| 2871 | p->area = it->area; | ||
| 2872 | p->multibyte_p = it->multibyte_p; | ||
| 2873 | p->space_width = it->space_width; | ||
| 2874 | p->font_height = it->font_height; | ||
| 2875 | p->voffset = it->voffset; | ||
| 2876 | p->string_from_display_prop_p = it->string_from_display_prop_p; | ||
| 2877 | ++it->sp; | ||
| 2878 | } | ||
| 2879 | |||
| 2880 | |||
| 2881 | /* Restore IT's settings from IT->stack. Called, for example, when no | ||
| 2882 | more overlay strings must be processed, and we return to delivering | ||
| 2883 | display elements from a buffer, or when the end of a string from a | ||
| 2884 | `display' property is reached and we return to delivering display | ||
| 2885 | elements from an overlay string, or from a buffer. */ | ||
| 2886 | |||
| 2887 | static void | ||
| 2888 | pop_it (it) | ||
| 2889 | struct it *it; | ||
| 2890 | { | ||
| 2891 | struct iterator_stack_entry *p; | ||
| 2892 | |||
| 2893 | xassert (it->sp > 0); | ||
| 2894 | --it->sp; | ||
| 2895 | p = it->stack + it->sp; | ||
| 2896 | it->stop_charpos = p->stop_charpos; | ||
| 2897 | it->face_id = p->face_id; | ||
| 2898 | it->string = p->string; | ||
| 2899 | it->current = p->pos; | ||
| 2900 | it->end_charpos = p->end_charpos; | ||
| 2901 | it->string_nchars = p->string_nchars; | ||
| 2902 | it->area = p->area; | ||
| 2903 | it->multibyte_p = p->multibyte_p; | ||
| 2904 | it->space_width = p->space_width; | ||
| 2905 | it->font_height = p->font_height; | ||
| 2906 | it->voffset = p->voffset; | ||
| 2907 | it->string_from_display_prop_p = p->string_from_display_prop_p; | ||
| 2908 | } | ||
| 2909 | |||
| 2910 | |||
| 2911 | |||
| 2912 | /*********************************************************************** | ||
| 2913 | Moving over lines | ||
| 2914 | ***********************************************************************/ | ||
| 2915 | |||
| 2916 | /* Set IT's current position to the previous line start. */ | ||
| 2917 | |||
| 2918 | static void | ||
| 2919 | back_to_previous_line_start (it) | ||
| 2920 | struct it *it; | ||
| 2921 | { | ||
| 2922 | IT_CHARPOS (*it) = find_next_newline_no_quit (IT_CHARPOS (*it) - 1, -1); | ||
| 2923 | IT_BYTEPOS (*it) = CHAR_TO_BYTE (IT_CHARPOS (*it)); | ||
| 2924 | } | ||
| 2925 | |||
| 2926 | |||
| 2927 | /* Set IT's current position to the next line start. */ | ||
| 2928 | |||
| 2929 | static void | ||
| 2930 | forward_to_next_line_start (it) | ||
| 2931 | struct it *it; | ||
| 2932 | { | ||
| 2933 | IT_CHARPOS (*it) = find_next_newline_no_quit (IT_CHARPOS (*it), 1); | ||
| 2934 | IT_BYTEPOS (*it) = CHAR_TO_BYTE (IT_CHARPOS (*it)); | ||
| 2935 | } | ||
| 2936 | |||
| 2937 | |||
| 2938 | /* Set IT's current position to the previous visible line start. Skip | ||
| 2939 | invisible text that is so either due to text properties or due to | ||
| 2940 | selective display. Caution: this does not change IT->current_x and | ||
| 2941 | IT->hpos. */ | ||
| 2942 | |||
| 2943 | static void | ||
| 2944 | back_to_previous_visible_line_start (it) | ||
| 2945 | struct it *it; | ||
| 2946 | { | ||
| 2947 | int visible_p = 0; | ||
| 2948 | |||
| 2949 | /* Go back one newline if not on BEGV already. */ | ||
| 2950 | if (IT_CHARPOS (*it) > BEGV) | ||
| 2951 | back_to_previous_line_start (it); | ||
| 2952 | |||
| 2953 | /* Move over lines that are invisible because of selective display | ||
| 2954 | or text properties. */ | ||
| 2955 | while (IT_CHARPOS (*it) > BEGV | ||
| 2956 | && !visible_p) | ||
| 2957 | { | ||
| 2958 | visible_p = 1; | ||
| 2959 | |||
| 2960 | /* If selective > 0, then lines indented more than that values | ||
| 2961 | are invisible. */ | ||
| 2962 | if (it->selective > 0 | ||
| 2963 | && indented_beyond_p (IT_CHARPOS (*it), IT_BYTEPOS (*it), | ||
| 2964 | it->selective)) | ||
| 2965 | visible_p = 0; | ||
| 2966 | #ifdef USE_TEXT_PROPERTIES | ||
| 2967 | else | ||
| 2968 | { | ||
| 2969 | Lisp_Object prop; | ||
| 2970 | |||
| 2971 | prop = Fget_char_property (IT_CHARPOS (*it), Qinvisible, it->window); | ||
| 2972 | if (TEXT_PROP_MEANS_INVISIBLE (prop)) | ||
| 2973 | visible_p = 0; | ||
| 2974 | } | ||
| 2975 | #endif /* USE_TEXT_PROPERTIES */ | ||
| 2976 | |||
| 2977 | /* Back one more newline if the current one is invisible. */ | ||
| 2978 | if (!visible_p) | ||
| 2979 | back_to_previous_line_start (it); | ||
| 2980 | } | ||
| 2981 | |||
| 2982 | xassert (IT_CHARPOS (*it) >= BEGV); | ||
| 2983 | xassert (IT_CHARPOS (*it) == BEGV | ||
| 2984 | || FETCH_BYTE (IT_BYTEPOS (*it) - 1) == '\n'); | ||
| 2985 | CHECK_IT (it); | ||
| 2986 | } | ||
| 2987 | |||
| 2988 | |||
| 2989 | /* Reseat iterator IT at the previous visible line start. Skip | ||
| 2990 | invisible text that is so either due to text properties or due to | ||
| 2991 | selective display. At the end, update IT's overlay information, | ||
| 2992 | face information etc. */ | ||
| 2993 | |||
| 2994 | static void | ||
| 2995 | reseat_at_previous_visible_line_start (it) | ||
| 2996 | struct it *it; | ||
| 2997 | { | ||
| 2998 | back_to_previous_visible_line_start (it); | ||
| 2999 | reseat (it, it->current.pos, 1); | ||
| 3000 | CHECK_IT (it); | ||
| 3001 | } | ||
| 3002 | |||
| 3003 | |||
| 3004 | /* Reseat iterator IT on the next visible line start in the current | ||
| 3005 | buffer. Skip over invisible text that is so because of selective | ||
| 3006 | display. Compute faces, overlays etc at the new position. Note | ||
| 3007 | that this function does not skip over text that is invisible | ||
| 3008 | because of text properties. */ | ||
| 3009 | |||
| 3010 | static void | ||
| 3011 | reseat_at_next_visible_line_start (it) | ||
| 3012 | struct it *it; | ||
| 3013 | { | ||
| 3014 | /* Restore the buffer position when currently not delivering display | ||
| 3015 | elements from the current buffer. This is the case, for example, | ||
| 3016 | when called at the end of a truncated overlay string. */ | ||
| 3017 | while (it->sp) | ||
| 3018 | pop_it (it); | ||
| 3019 | it->method = next_element_from_buffer; | ||
| 3020 | |||
| 3021 | /* Otherwise, scan_buffer would not work. */ | ||
| 3022 | if (IT_CHARPOS (*it) < ZV) | ||
| 3023 | { | ||
| 3024 | /* If on a newline, advance past it. Otherwise, find the next | ||
| 3025 | newline which automatically gives us the position following | ||
| 3026 | the newline. */ | ||
| 3027 | if (FETCH_BYTE (IT_BYTEPOS (*it)) == '\n') | ||
| 3028 | { | ||
| 3029 | ++IT_CHARPOS (*it); | ||
| 3030 | ++IT_BYTEPOS (*it); | ||
| 3031 | } | ||
| 3032 | else | ||
| 3033 | forward_to_next_line_start (it); | ||
| 3034 | |||
| 3035 | /* We must either have reached the end of the buffer or end up | ||
| 3036 | after a newline. */ | ||
| 3037 | xassert (IT_CHARPOS (*it) == ZV | ||
| 3038 | || FETCH_BYTE (IT_BYTEPOS (*it) - 1) == '\n'); | ||
| 3039 | |||
| 3040 | /* Skip over lines that are invisible because they are indented | ||
| 3041 | more than the value of IT->selective. */ | ||
| 3042 | if (it->selective > 0) | ||
| 3043 | while (IT_CHARPOS (*it) < ZV | ||
| 3044 | && indented_beyond_p (IT_CHARPOS (*it), IT_BYTEPOS (*it), | ||
| 3045 | it->selective)) | ||
| 3046 | forward_to_next_line_start (it); | ||
| 3047 | |||
| 3048 | /* Set the iterator there. The 0 as the last parameter of | ||
| 3049 | reseat means don't force a text property lookup. The lookup | ||
| 3050 | is then only done if we've skipped past the iterator's | ||
| 3051 | check_charpos'es. This optimization is important because | ||
| 3052 | text property lookups tend to be expensive. */ | ||
| 3053 | reseat (it, it->current.pos, 0); | ||
| 3054 | } | ||
| 3055 | |||
| 3056 | CHECK_IT (it); | ||
| 3057 | } | ||
| 3058 | |||
| 3059 | |||
| 3060 | |||
| 3061 | /*********************************************************************** | ||
| 3062 | Changing an iterator's position | ||
| 3063 | ***********************************************************************/ | ||
| 3064 | |||
| 3065 | /* Change IT's current position to POS in current_buffer. If FORCE_P | ||
| 3066 | is non-zero, always check for text properties at the new position. | ||
| 3067 | Otherwise, text properties are only looked up if POS >= | ||
| 3068 | IT->check_charpos of a property. */ | ||
| 3069 | |||
| 3070 | static void | ||
| 3071 | reseat (it, pos, force_p) | ||
| 3072 | struct it *it; | ||
| 3073 | struct text_pos pos; | ||
| 3074 | int force_p; | ||
| 3075 | { | ||
| 3076 | int original_pos = IT_CHARPOS (*it); | ||
| 3077 | |||
| 3078 | reseat_1 (it, pos, 0); | ||
| 3079 | |||
| 3080 | /* Determine where to check text properties. Avoid doing it | ||
| 3081 | where possible because text property lookup is very expensive. */ | ||
| 3082 | if (force_p | ||
| 3083 | || CHARPOS (pos) > it->stop_charpos | ||
| 3084 | || CHARPOS (pos) < original_pos) | ||
| 3085 | handle_stop (it); | ||
| 3086 | |||
| 3087 | CHECK_IT (it); | ||
| 3088 | } | ||
| 3089 | |||
| 3090 | |||
| 3091 | /* Change IT's buffer position to POS. SET_STOP_P non-zero means set | ||
| 3092 | IT->stop_pos to POS, also. */ | ||
| 3093 | |||
| 3094 | static void | ||
| 3095 | reseat_1 (it, pos, set_stop_p) | ||
| 3096 | struct it *it; | ||
| 3097 | struct text_pos pos; | ||
| 3098 | int set_stop_p; | ||
| 3099 | { | ||
| 3100 | /* Don't call this function when scanning a C string. */ | ||
| 3101 | xassert (it->s == NULL); | ||
| 3102 | |||
| 3103 | /* POS must be a reasonable value. */ | ||
| 3104 | xassert (CHARPOS (pos) >= BEGV && CHARPOS (pos) <= ZV); | ||
| 3105 | |||
| 3106 | it->current.pos = it->position = pos; | ||
| 3107 | XSETBUFFER (it->object, current_buffer); | ||
| 3108 | it->dpvec = NULL; | ||
| 3109 | it->current.dpvec_index = -1; | ||
| 3110 | it->current.overlay_string_index = -1; | ||
| 3111 | IT_STRING_CHARPOS (*it) = -1; | ||
| 3112 | IT_STRING_BYTEPOS (*it) = -1; | ||
| 3113 | it->string = Qnil; | ||
| 3114 | it->method = next_element_from_buffer; | ||
| 3115 | it->sp = 0; | ||
| 3116 | |||
| 3117 | if (set_stop_p) | ||
| 3118 | it->stop_charpos = CHARPOS (pos); | ||
| 3119 | } | ||
| 3120 | |||
| 3121 | |||
| 3122 | /* Set up IT for displaying a string, starting at CHARPOS in window W. | ||
| 3123 | If S is non-null, it is a C string to iterate over. Otherwise, | ||
| 3124 | STRING gives a Lisp string to iterate over. | ||
| 3125 | |||
| 3126 | If PRECISION > 0, don't return more then PRECISION number of | ||
| 3127 | characters from the string. | ||
| 3128 | |||
| 3129 | If FIELD_WIDTH > 0, return padding spaces until FIELD_WIDTH | ||
| 3130 | characters have been returned. FIELD_WIDTH < 0 means an infinite | ||
| 3131 | field width. | ||
| 3132 | |||
| 3133 | MULTIBYTE = 0 means disable processing of multibyte characters, | ||
| 3134 | MULTIBYTE > 0 means enable it, | ||
| 3135 | MULTIBYTE < 0 means use IT->multibyte_p. | ||
| 3136 | |||
| 3137 | IT must be initialized via a prior call to init_iterator before | ||
| 3138 | calling this function. */ | ||
| 3139 | |||
| 3140 | static void | ||
| 3141 | reseat_to_string (it, s, string, charpos, precision, field_width, multibyte) | ||
| 3142 | struct it *it; | ||
| 3143 | unsigned char *s; | ||
| 3144 | Lisp_Object string; | ||
| 3145 | int charpos; | ||
| 3146 | int precision, field_width, multibyte; | ||
| 3147 | { | ||
| 3148 | /* No region in strings. */ | ||
| 3149 | it->region_beg_charpos = it->region_end_charpos = -1; | ||
| 3150 | |||
| 3151 | /* No text property checks performed by default, but see below. */ | ||
| 3152 | it->stop_charpos = -1; | ||
| 3153 | |||
| 3154 | /* Set iterator position and end position. */ | ||
| 3155 | bzero (&it->current, sizeof it->current); | ||
| 3156 | it->current.overlay_string_index = -1; | ||
| 3157 | it->current.dpvec_index = -1; | ||
| 3158 | it->charset = CHARSET_ASCII; | ||
| 3159 | xassert (charpos >= 0); | ||
| 3160 | |||
| 3161 | /* Use the setting of MULTIBYTE if specified. */ | ||
| 3162 | if (multibyte >= 0) | ||
| 3163 | it->multibyte_p = multibyte > 0; | ||
| 3164 | |||
| 3165 | if (s == NULL) | ||
| 3166 | { | ||
| 3167 | xassert (STRINGP (string)); | ||
| 3168 | it->string = string; | ||
| 3169 | it->s = NULL; | ||
| 3170 | it->end_charpos = it->string_nchars = XSTRING (string)->size; | ||
| 3171 | it->method = next_element_from_string; | ||
| 3172 | it->current.string_pos = string_pos (charpos, string); | ||
| 3173 | } | ||
| 3174 | else | ||
| 3175 | { | ||
| 3176 | it->s = s; | ||
| 3177 | it->string = Qnil; | ||
| 3178 | |||
| 3179 | /* Note that we use IT->current.pos, not it->current.string_pos, | ||
| 3180 | for displaying C strings. */ | ||
| 3181 | IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = -1; | ||
| 3182 | if (it->multibyte_p) | ||
| 3183 | { | ||
| 3184 | it->current.pos = c_string_pos (charpos, s, 1); | ||
| 3185 | it->end_charpos = it->string_nchars = number_of_chars (s, 1); | ||
| 3186 | } | ||
| 3187 | else | ||
| 3188 | { | ||
| 3189 | IT_CHARPOS (*it) = IT_BYTEPOS (*it) = charpos; | ||
| 3190 | it->end_charpos = it->string_nchars = strlen (s); | ||
| 3191 | } | ||
| 3192 | |||
| 3193 | it->method = next_element_from_c_string; | ||
| 3194 | } | ||
| 3195 | |||
| 3196 | /* PRECISION > 0 means don't return more than PRECISION characters | ||
| 3197 | from the string. */ | ||
| 3198 | if (precision > 0 && it->end_charpos - charpos > precision) | ||
| 3199 | it->end_charpos = it->string_nchars = charpos + precision; | ||
| 3200 | |||
| 3201 | /* FIELD_WIDTH > 0 means pad with spaces until FIELD_WIDTH | ||
| 3202 | characters have been returned. FIELD_WIDTH == 0 means don't pad, | ||
| 3203 | FIELD_WIDTH < 0 means infinite field width. This is useful for | ||
| 3204 | padding with `-' at the end of a mode line. */ | ||
| 3205 | if (field_width < 0) | ||
| 3206 | field_width = INFINITY; | ||
| 3207 | if (field_width > it->end_charpos - charpos) | ||
| 3208 | it->end_charpos = charpos + field_width; | ||
| 3209 | |||
| 3210 | /* Use the standard display table for displaying strings. */ | ||
| 3211 | if (DISP_TABLE_P (Vstandard_display_table)) | ||
| 3212 | it->dp = XCHAR_TABLE (Vstandard_display_table); | ||
| 3213 | |||
| 3214 | it->stop_charpos = charpos; | ||
| 3215 | CHECK_IT (it); | ||
| 3216 | } | ||
| 3217 | |||
| 3218 | |||
| 3219 | |||
| 3220 | /*********************************************************************** | ||
| 3221 | Iteration | ||
| 3222 | ***********************************************************************/ | ||
| 3223 | |||
| 3224 | /* Load IT's display element fields with information about the next | ||
| 3225 | display element from the current position of IT. Value is zero if | ||
| 3226 | end of buffer (or C string) is reached. */ | ||
| 3227 | |||
| 3228 | int | ||
| 3229 | get_next_display_element (it) | ||
| 3230 | struct it *it; | ||
| 3231 | { | ||
| 3232 | /* Non-zero means that we found an display element. Zero means that | ||
| 3233 | we hit the end of what we iterate over. Performance note: the | ||
| 3234 | function pointer `method' used here turns out to be faster than | ||
| 3235 | using a sequence of if-statements. */ | ||
| 3236 | int success_p = (*it->method) (it); | ||
| 3237 | int charset; | ||
| 3238 | |||
| 3239 | if (it->what == IT_CHARACTER) | ||
| 3240 | { | ||
| 3241 | /* Map via display table or translate control characters. | ||
| 3242 | IT->c, IT->len etc. have been set to the next character by | ||
| 3243 | the function call above. If we have a display table, and it | ||
| 3244 | contains an entry for IT->c, translate it. Don't do this if | ||
| 3245 | IT->c itself comes from a display table, otherwise we could | ||
| 3246 | end up in an infinite recursion. (An alternative could be to | ||
| 3247 | count the recursion depth of this function and signal an | ||
| 3248 | error when a certain maximum depth is reached.) Is it worth | ||
| 3249 | it? */ | ||
| 3250 | if (success_p && it->dpvec == NULL) | ||
| 3251 | { | ||
| 3252 | Lisp_Object dv; | ||
| 3253 | |||
| 3254 | if (it->dp | ||
| 3255 | && (dv = DISP_CHAR_VECTOR (it->dp, it->c), | ||
| 3256 | VECTORP (dv))) | ||
| 3257 | { | ||
| 3258 | struct Lisp_Vector *v = XVECTOR (dv); | ||
| 3259 | |||
| 3260 | /* Return the first character from the display table | ||
| 3261 | entry, if not empty. If empty, don't display the | ||
| 3262 | current character. */ | ||
| 3263 | if (v->size) | ||
| 3264 | { | ||
| 3265 | it->dpvec_char_len = it->len; | ||
| 3266 | it->dpvec = v->contents; | ||
| 3267 | it->dpend = v->contents + v->size; | ||
| 3268 | it->current.dpvec_index = 0; | ||
| 3269 | it->method = next_element_from_display_vector; | ||
| 3270 | } | ||
| 3271 | |||
| 3272 | success_p = get_next_display_element (it); | ||
| 3273 | } | ||
| 3274 | |||
| 3275 | /* Translate control characters into `\003' or `^C' form. | ||
| 3276 | Control characters coming from a display table entry are | ||
| 3277 | currently not translated because we use IT->dpvec to hold | ||
| 3278 | the translation. This could easily be changed but I | ||
| 3279 | don't believe that it is worth doing. */ | ||
| 3280 | else if ((it->c < ' ' | ||
| 3281 | && (it->area != TEXT_AREA | ||
| 3282 | || (it->c != '\n' | ||
| 3283 | && it->c != '\t' | ||
| 3284 | && it->c != '\r'))) | ||
| 3285 | || (it->c >= 128 | ||
| 3286 | && it->len == 1)) | ||
| 3287 | { | ||
| 3288 | /* IT->c is a control character which must be displayed | ||
| 3289 | either as '\003' or as `^C' where the '\\' and '^' | ||
| 3290 | can be defined in the display table. Fill | ||
| 3291 | IT->ctl_chars with glyphs for what we have to | ||
| 3292 | display. Then, set IT->dpvec to these glyphs. */ | ||
| 3293 | GLYPH g; | ||
| 3294 | |||
| 3295 | if (it->c < ' ' && it->ctl_arrow_p) | ||
| 3296 | { | ||
| 3297 | /* Set IT->ctl_chars[0] to the glyph for `^'. */ | ||
| 3298 | if (it->dp | ||
| 3299 | && INTEGERP (DISP_CTRL_GLYPH (it->dp)) | ||
| 3300 | && GLYPH_CHAR_VALID_P (XINT (DISP_CTRL_GLYPH (it->dp)))) | ||
| 3301 | g = XINT (DISP_CTRL_GLYPH (it->dp)); | ||
| 3302 | else | ||
| 3303 | g = FAST_MAKE_GLYPH ('^', 0); | ||
| 3304 | XSETINT (it->ctl_chars[0], g); | ||
| 3305 | |||
| 3306 | g = FAST_MAKE_GLYPH (it->c ^ 0100, 0); | ||
| 3307 | XSETINT (it->ctl_chars[1], g); | ||
| 3308 | |||
| 3309 | /* Set up IT->dpvec and return first character from it. */ | ||
| 3310 | it->dpvec_char_len = it->len; | ||
| 3311 | it->dpvec = it->ctl_chars; | ||
| 3312 | it->dpend = it->dpvec + 2; | ||
| 3313 | it->current.dpvec_index = 0; | ||
| 3314 | it->method = next_element_from_display_vector; | ||
| 3315 | get_next_display_element (it); | ||
| 3316 | } | ||
| 3317 | else | ||
| 3318 | { | ||
| 3319 | /* Set IT->ctl_chars[0] to the glyph for `\\'. */ | ||
| 3320 | if (it->dp | ||
| 3321 | && INTEGERP (DISP_ESCAPE_GLYPH (it->dp)) | ||
| 3322 | && GLYPH_CHAR_VALID_P (XFASTINT (DISP_ESCAPE_GLYPH (it->dp)))) | ||
| 3323 | g = XFASTINT (DISP_ESCAPE_GLYPH (it->dp)); | ||
| 3324 | else | ||
| 3325 | g = FAST_MAKE_GLYPH ('\\', 0); | ||
| 3326 | XSETINT (it->ctl_chars[0], g); | ||
| 3327 | |||
| 3328 | /* Insert three more glyphs into IT->ctl_chars for | ||
| 3329 | the octal display of the character. */ | ||
| 3330 | g = FAST_MAKE_GLYPH (((it->c >> 6) & 7) + '0', 0); | ||
| 3331 | XSETINT (it->ctl_chars[1], g); | ||
| 3332 | g = FAST_MAKE_GLYPH (((it->c >> 3) & 7) + '0', 0); | ||
| 3333 | XSETINT (it->ctl_chars[2], g); | ||
| 3334 | g = FAST_MAKE_GLYPH ((it->c & 7) + '0', 0); | ||
| 3335 | XSETINT (it->ctl_chars[3], g); | ||
| 3336 | |||
| 3337 | /* Set up IT->dpvec and return the first character | ||
| 3338 | from it. */ | ||
| 3339 | it->dpvec_char_len = it->len; | ||
| 3340 | it->dpvec = it->ctl_chars; | ||
| 3341 | it->dpend = it->dpvec + 4; | ||
| 3342 | it->current.dpvec_index = 0; | ||
| 3343 | it->method = next_element_from_display_vector; | ||
| 3344 | get_next_display_element (it); | ||
| 3345 | } | ||
| 3346 | } | ||
| 3347 | } | ||
| 3348 | |||
| 3349 | /* Adjust face id if charset changes. There are no charset | ||
| 3350 | changes in unibyte text because Emacs' charsets are not | ||
| 3351 | applicable there. */ | ||
| 3352 | if (it->multibyte_p | ||
| 3353 | && success_p | ||
| 3354 | && (charset = CHAR_CHARSET (it->c), | ||
| 3355 | charset != it->charset)) | ||
| 3356 | { | ||
| 3357 | it->charset = charset; | ||
| 3358 | it->face_id = FACE_FOR_CHARSET (it->f, it->face_id, charset); | ||
| 3359 | } | ||
| 3360 | } | ||
| 3361 | |||
| 3362 | /* Is this character the last one of a run of characters with | ||
| 3363 | box? If yes, set IT->end_of_box_run_p to 1. */ | ||
| 3364 | if (it->face_box_p | ||
| 3365 | && it->s == NULL) | ||
| 3366 | { | ||
| 3367 | int face_id; | ||
| 3368 | struct face *face; | ||
| 3369 | |||
| 3370 | it->end_of_box_run_p | ||
| 3371 | = ((face_id = face_after_it_pos (it), | ||
| 3372 | face_id != it->face_id) | ||
| 3373 | && (face = FACE_FROM_ID (it->f, face_id), | ||
| 3374 | face->box == FACE_NO_BOX)); | ||
| 3375 | } | ||
| 3376 | |||
| 3377 | /* Value is 0 if end of buffer or string reached. */ | ||
| 3378 | return success_p; | ||
| 3379 | } | ||
| 3380 | |||
| 3381 | |||
| 3382 | /* Move IT to the next display element. | ||
| 3383 | |||
| 3384 | Functions get_next_display_element and set_iterator_to_next are | ||
| 3385 | separate because I find this arrangement easier to handle than a | ||
| 3386 | get_next_display_element function that also increments IT's | ||
| 3387 | position. The way it is we can first look at an iterator's current | ||
| 3388 | display element, decide whether it fits on a line, and if it does, | ||
| 3389 | increment the iterator position. The other way around we probably | ||
| 3390 | would either need a flag indicating whether the iterator has to be | ||
| 3391 | incremented the next time, or we would have to implement a | ||
| 3392 | decrement position function which would not be easy to write. */ | ||
| 3393 | |||
| 3394 | void | ||
| 3395 | set_iterator_to_next (it) | ||
| 3396 | struct it *it; | ||
| 3397 | { | ||
| 3398 | if (it->method == next_element_from_buffer) | ||
| 3399 | { | ||
| 3400 | /* The current display element of IT is a character from | ||
| 3401 | current_buffer. Advance in the buffer, and maybe skip over | ||
| 3402 | invisible lines that are so because of selective display. */ | ||
| 3403 | if (ITERATOR_AT_END_OF_LINE_P (it)) | ||
| 3404 | reseat_at_next_visible_line_start (it); | ||
| 3405 | else | ||
| 3406 | { | ||
| 3407 | xassert (it->len != 0); | ||
| 3408 | IT_BYTEPOS (*it) += it->len; | ||
| 3409 | IT_CHARPOS (*it) += 1; | ||
| 3410 | xassert (IT_BYTEPOS (*it) == CHAR_TO_BYTE (IT_CHARPOS (*it))); | ||
| 3411 | } | ||
| 3412 | } | ||
| 3413 | else if (it->method == next_element_from_c_string) | ||
| 3414 | { | ||
| 3415 | /* Current display element of IT is from a C string. */ | ||
| 3416 | IT_BYTEPOS (*it) += it->len; | ||
| 3417 | IT_CHARPOS (*it) += 1; | ||
| 3418 | } | ||
| 3419 | else if (it->method == next_element_from_display_vector) | ||
| 3420 | { | ||
| 3421 | /* Current display element of IT is from a display table entry. | ||
| 3422 | Advance in the display table definition. Reset it to null if | ||
| 3423 | end reached, and continue with characters from buffers/ | ||
| 3424 | strings. */ | ||
| 3425 | ++it->current.dpvec_index; | ||
| 3426 | it->face_id = it->saved_face_id; | ||
| 3427 | if (it->dpvec + it->current.dpvec_index == it->dpend) | ||
| 3428 | { | ||
| 3429 | if (it->s) | ||
| 3430 | it->method = next_element_from_c_string; | ||
| 3431 | else if (STRINGP (it->string)) | ||
| 3432 | it->method = next_element_from_string; | ||
| 3433 | else | ||
| 3434 | it->method = next_element_from_buffer; | ||
| 3435 | |||
| 3436 | it->dpvec = NULL; | ||
| 3437 | it->current.dpvec_index = -1; | ||
| 3438 | |||
| 3439 | /* Consume the character which was displayed via IT->dpvec. */ | ||
| 3440 | if (it->dpvec_char_len) | ||
| 3441 | { | ||
| 3442 | it->len = it->dpvec_char_len; | ||
| 3443 | set_iterator_to_next (it); | ||
| 3444 | } | ||
| 3445 | } | ||
| 3446 | } | ||
| 3447 | else if (it->method == next_element_from_string) | ||
| 3448 | { | ||
| 3449 | /* Current display element is a character from a Lisp string. */ | ||
| 3450 | xassert (it->s == NULL && STRINGP (it->string)); | ||
| 3451 | IT_STRING_BYTEPOS (*it) += it->len; | ||
| 3452 | IT_STRING_CHARPOS (*it) += 1; | ||
| 3453 | |||
| 3454 | consider_string_end: | ||
| 3455 | |||
| 3456 | if (it->current.overlay_string_index >= 0) | ||
| 3457 | { | ||
| 3458 | /* IT->string is an overlay string. Advance to the | ||
| 3459 | next, if there is one. */ | ||
| 3460 | if (IT_STRING_CHARPOS (*it) >= XSTRING (it->string)->size) | ||
| 3461 | next_overlay_string (it); | ||
| 3462 | } | ||
| 3463 | else | ||
| 3464 | { | ||
| 3465 | /* IT->string is not an overlay string. If we reached | ||
| 3466 | its end, and there is something on IT->stack, proceed | ||
| 3467 | with what is on the stack. This can be either another | ||
| 3468 | string, this time an overlay string, or a buffer. */ | ||
| 3469 | if (IT_STRING_CHARPOS (*it) == XSTRING (it->string)->size | ||
| 3470 | && it->sp > 0) | ||
| 3471 | { | ||
| 3472 | pop_it (it); | ||
| 3473 | if (!STRINGP (it->string)) | ||
| 3474 | it->method = next_element_from_buffer; | ||
| 3475 | } | ||
| 3476 | } | ||
| 3477 | } | ||
| 3478 | else if (it->method == next_element_from_image | ||
| 3479 | || it->method == next_element_from_stretch) | ||
| 3480 | { | ||
| 3481 | /* The position etc with which we have to proceed are on | ||
| 3482 | the stack. The position may be at the end of a string, | ||
| 3483 | if the `display' property takes up the whole string. */ | ||
| 3484 | pop_it (it); | ||
| 3485 | it->image_id = 0; | ||
| 3486 | if (STRINGP (it->string)) | ||
| 3487 | { | ||
| 3488 | it->method = next_element_from_string; | ||
| 3489 | goto consider_string_end; | ||
| 3490 | } | ||
| 3491 | else | ||
| 3492 | it->method = next_element_from_buffer; | ||
| 3493 | } | ||
| 3494 | else | ||
| 3495 | /* There are no other methods defined, so this should be a bug. */ | ||
| 3496 | abort (); | ||
| 3497 | |||
| 3498 | /* Reset flags indicating start and end of a sequence of | ||
| 3499 | characters with box. */ | ||
| 3500 | it->start_of_box_run_p = it->end_of_box_run_p = 0; | ||
| 3501 | |||
| 3502 | xassert (it->method != next_element_from_string | ||
| 3503 | || (STRINGP (it->string) | ||
| 3504 | && IT_STRING_CHARPOS (*it) >= 0)); | ||
| 3505 | } | ||
| 3506 | |||
| 3507 | |||
| 3508 | /* Load IT's display element fields with information about the next | ||
| 3509 | display element which comes from a display table entry or from the | ||
| 3510 | result of translating a control character to one of the forms `^C' | ||
| 3511 | or `\003'. IT->dpvec holds the glyphs to return as characters. */ | ||
| 3512 | |||
| 3513 | static int | ||
| 3514 | next_element_from_display_vector (it) | ||
| 3515 | struct it *it; | ||
| 3516 | { | ||
| 3517 | /* Precondition. */ | ||
| 3518 | xassert (it->dpvec && it->current.dpvec_index >= 0); | ||
| 3519 | |||
| 3520 | /* Remember the current face id in case glyphs specify faces. | ||
| 3521 | IT's face is restored in set_iterator_to_next. */ | ||
| 3522 | it->saved_face_id = it->face_id; | ||
| 3523 | |||
| 3524 | if (INTEGERP (*it->dpvec) | ||
| 3525 | && GLYPH_CHAR_VALID_P (XFASTINT (*it->dpvec))) | ||
| 3526 | { | ||
| 3527 | int lface_id; | ||
| 3528 | GLYPH g; | ||
| 3529 | |||
| 3530 | g = XFASTINT (it->dpvec[it->current.dpvec_index]); | ||
| 3531 | it->c = FAST_GLYPH_CHAR (g); | ||
| 3532 | it->len = CHAR_LEN (it->c); | ||
| 3533 | |||
| 3534 | /* The entry may contain a face id to use. Such a face id is | ||
| 3535 | the id of a Lisp face, not a realized face. A face id of | ||
| 3536 | zero means no face. */ | ||
| 3537 | lface_id = FAST_GLYPH_FACE (g); | ||
| 3538 | if (lface_id) | ||
| 3539 | { | ||
| 3540 | int face_id = ascii_face_of_lisp_face (it->f, lface_id); | ||
| 3541 | if (face_id >= 0) | ||
| 3542 | { | ||
| 3543 | it->face_id = face_id; | ||
| 3544 | it->charset = CHARSET_ASCII; | ||
| 3545 | } | ||
| 3546 | } | ||
| 3547 | } | ||
| 3548 | else | ||
| 3549 | /* Display table entry is invalid. Return a space. */ | ||
| 3550 | it->c = ' ', it->len = 1; | ||
| 3551 | |||
| 3552 | /* Don't change position and object of the iterator here. They are | ||
| 3553 | still the values of the character that had this display table | ||
| 3554 | entry or was translated, and that's what we want. */ | ||
| 3555 | it->what = IT_CHARACTER; | ||
| 3556 | return 1; | ||
| 3557 | } | ||
| 3558 | |||
| 3559 | |||
| 3560 | /* Load IT with the next display element from Lisp string IT->string. | ||
| 3561 | IT->current.string_pos is the current position within the string. | ||
| 3562 | If IT->current.overlay_string_index >= 0, the Lisp string is an | ||
| 3563 | overlay string. */ | ||
| 3564 | |||
| 3565 | static int | ||
| 3566 | next_element_from_string (it) | ||
| 3567 | struct it *it; | ||
| 3568 | { | ||
| 3569 | struct text_pos position; | ||
| 3570 | |||
| 3571 | xassert (STRINGP (it->string)); | ||
| 3572 | xassert (IT_STRING_CHARPOS (*it) >= 0); | ||
| 3573 | position = it->current.string_pos; | ||
| 3574 | |||
| 3575 | /* Time to check for invisible text? */ | ||
| 3576 | if (IT_STRING_CHARPOS (*it) < it->end_charpos | ||
| 3577 | && IT_STRING_CHARPOS (*it) == it->stop_charpos) | ||
| 3578 | { | ||
| 3579 | handle_stop (it); | ||
| 3580 | |||
| 3581 | /* Since a handler may have changed IT->method, we must | ||
| 3582 | recurse here. */ | ||
| 3583 | return get_next_display_element (it); | ||
| 3584 | } | ||
| 3585 | |||
| 3586 | if (it->current.overlay_string_index >= 0) | ||
| 3587 | { | ||
| 3588 | /* Get the next character from an overlay string. In overlay | ||
| 3589 | strings, There is no field width or padding with spaces to | ||
| 3590 | do. */ | ||
| 3591 | if (IT_STRING_CHARPOS (*it) >= XSTRING (it->string)->size) | ||
| 3592 | { | ||
| 3593 | it->what = IT_EOB; | ||
| 3594 | return 0; | ||
| 3595 | } | ||
| 3596 | else if (STRING_MULTIBYTE (it->string)) | ||
| 3597 | { | ||
| 3598 | int remaining = (STRING_BYTES (XSTRING (it->string)) | ||
| 3599 | - IT_STRING_BYTEPOS (*it)); | ||
| 3600 | unsigned char *s = (XSTRING (it->string)->data | ||
| 3601 | + IT_STRING_BYTEPOS (*it)); | ||
| 3602 | it->c = STRING_CHAR_AND_LENGTH (s, remaining, it->len); | ||
| 3603 | } | ||
| 3604 | else | ||
| 3605 | { | ||
| 3606 | it->c = XSTRING (it->string)->data[IT_STRING_BYTEPOS (*it)]; | ||
| 3607 | it->len = 1; | ||
| 3608 | } | ||
| 3609 | } | ||
| 3610 | else | ||
| 3611 | { | ||
| 3612 | /* Get the next character from a Lisp string that is not an | ||
| 3613 | overlay string. Such strings come from the mode line, for | ||
| 3614 | example. We may have to pad with spaces, or truncate the | ||
| 3615 | string. See also next_element_from_c_string. */ | ||
| 3616 | if (IT_STRING_CHARPOS (*it) >= it->end_charpos) | ||
| 3617 | { | ||
| 3618 | it->what = IT_EOB; | ||
| 3619 | return 0; | ||
| 3620 | } | ||
| 3621 | else if (IT_STRING_CHARPOS (*it) >= it->string_nchars) | ||
| 3622 | { | ||
| 3623 | /* Pad with spaces. */ | ||
| 3624 | it->c = ' ', it->len = 1; | ||
| 3625 | CHARPOS (position) = BYTEPOS (position) = -1; | ||
| 3626 | } | ||
| 3627 | else if (STRING_MULTIBYTE (it->string)) | ||
| 3628 | { | ||
| 3629 | int maxlen = (STRING_BYTES (XSTRING (it->string)) | ||
| 3630 | - IT_STRING_BYTEPOS (*it)); | ||
| 3631 | unsigned char *s = (XSTRING (it->string)->data | ||
| 3632 | + IT_STRING_BYTEPOS (*it)); | ||
| 3633 | it->c = STRING_CHAR_AND_LENGTH (s, maxlen, it->len); | ||
| 3634 | } | ||
| 3635 | else | ||
| 3636 | { | ||
| 3637 | it->c = XSTRING (it->string)->data[IT_STRING_BYTEPOS (*it)]; | ||
| 3638 | it->len = 1; | ||
| 3639 | } | ||
| 3640 | } | ||
| 3641 | |||
| 3642 | /* Record what we have and where it came from. Note that we store a | ||
| 3643 | buffer position in IT->position although it could arguably be a | ||
| 3644 | string position. */ | ||
| 3645 | it->what = IT_CHARACTER; | ||
| 3646 | it->object = it->string; | ||
| 3647 | it->position = position; | ||
| 3648 | return 1; | ||
| 3649 | } | ||
| 3650 | |||
| 3651 | |||
| 3652 | /* Load IT with next display element from C string IT->s. | ||
| 3653 | IT->string_nchars is the maximum number of characters to return | ||
| 3654 | from the string. IT->end_charpos may be greater than | ||
| 3655 | IT->string_nchars when this function is called, in which case we | ||
| 3656 | may have to return padding spaces. Value is zero if end of string | ||
| 3657 | reached, including padding spaces. */ | ||
| 3658 | |||
| 3659 | static int | ||
| 3660 | next_element_from_c_string (it) | ||
| 3661 | struct it *it; | ||
| 3662 | { | ||
| 3663 | int success_p = 1; | ||
| 3664 | |||
| 3665 | xassert (it->s); | ||
| 3666 | it->what = IT_CHARACTER; | ||
| 3667 | BYTEPOS (it->position) = CHARPOS (it->position) = 0; | ||
| 3668 | it->object = Qnil; | ||
| 3669 | |||
| 3670 | /* IT's position can be greater IT->string_nchars in case a field | ||
| 3671 | width or precision has been specified when the iterator was | ||
| 3672 | initialized. */ | ||
| 3673 | if (IT_CHARPOS (*it) >= it->end_charpos) | ||
| 3674 | { | ||
| 3675 | /* End of the game. */ | ||
| 3676 | it->what = IT_EOB; | ||
| 3677 | success_p = 0; | ||
| 3678 | } | ||
| 3679 | else if (IT_CHARPOS (*it) >= it->string_nchars) | ||
| 3680 | { | ||
| 3681 | /* Pad with spaces. */ | ||
| 3682 | it->c = ' ', it->len = 1; | ||
| 3683 | BYTEPOS (it->position) = CHARPOS (it->position) = -1; | ||
| 3684 | } | ||
| 3685 | else if (it->multibyte_p) | ||
| 3686 | { | ||
| 3687 | /* Implementation note: The calls to strlen apparently aren't a | ||
| 3688 | performance problem because there is no noticeable performance | ||
| 3689 | difference between Emacs running in unibyte or multibyte mode. */ | ||
| 3690 | int maxlen = strlen (it->s) - IT_BYTEPOS (*it); | ||
| 3691 | it->c = STRING_CHAR_AND_LENGTH (it->s + IT_BYTEPOS (*it), | ||
| 3692 | maxlen, it->len); | ||
| 3693 | } | ||
| 3694 | else | ||
| 3695 | it->c = it->s[IT_BYTEPOS (*it)], it->len = 1; | ||
| 3696 | |||
| 3697 | return success_p; | ||
| 3698 | } | ||
| 3699 | |||
| 3700 | |||
| 3701 | /* Set up IT to return characters from an ellipsis, if appropriate. | ||
| 3702 | The definition of the ellipsis glyphs may come from a display table | ||
| 3703 | entry. This function Fills IT with the first glyph from the | ||
| 3704 | ellipsis if an ellipsis is to be displayed. */ | ||
| 3705 | |||
| 3706 | static void | ||
| 3707 | next_element_from_ellipsis (it) | ||
| 3708 | struct it *it; | ||
| 3709 | { | ||
| 3710 | if (it->dp && VECTORP (DISP_INVIS_VECTOR (it->dp))) | ||
| 3711 | { | ||
| 3712 | /* Use the display table definition for `...'. Invalid glyphs | ||
| 3713 | will be handled by the method returning elements from dpvec. */ | ||
| 3714 | struct Lisp_Vector *v = XVECTOR (DISP_INVIS_VECTOR (it->dp)); | ||
| 3715 | it->dpvec_char_len = it->len; | ||
| 3716 | it->dpvec = v->contents; | ||
| 3717 | it->dpend = v->contents + v->size; | ||
| 3718 | it->current.dpvec_index = 0; | ||
| 3719 | it->method = next_element_from_display_vector; | ||
| 3720 | get_next_display_element (it); | ||
| 3721 | } | ||
| 3722 | else if (it->selective_display_ellipsis_p) | ||
| 3723 | { | ||
| 3724 | /* Use default `...' which is stored in default_invis_vector. */ | ||
| 3725 | it->dpvec_char_len = it->len; | ||
| 3726 | it->dpvec = default_invis_vector; | ||
| 3727 | it->dpend = default_invis_vector + 3; | ||
| 3728 | it->current.dpvec_index = 0; | ||
| 3729 | it->method = next_element_from_display_vector; | ||
| 3730 | get_next_display_element (it); | ||
| 3731 | } | ||
| 3732 | } | ||
| 3733 | |||
| 3734 | |||
| 3735 | /* Deliver an image display element. The iterator IT is already | ||
| 3736 | filled with image information (done in handle_display_prop). Value | ||
| 3737 | is always 1. */ | ||
| 3738 | |||
| 3739 | |||
| 3740 | static int | ||
| 3741 | next_element_from_image (it) | ||
| 3742 | struct it *it; | ||
| 3743 | { | ||
| 3744 | it->what = IT_IMAGE; | ||
| 3745 | return 1; | ||
| 3746 | } | ||
| 3747 | |||
| 3748 | |||
| 3749 | /* Fill iterator IT with next display element from a stretch glyph | ||
| 3750 | property. IT->object is the value of the text property. Value is | ||
| 3751 | always 1. */ | ||
| 3752 | |||
| 3753 | static int | ||
| 3754 | next_element_from_stretch (it) | ||
| 3755 | struct it *it; | ||
| 3756 | { | ||
| 3757 | it->what = IT_STRETCH; | ||
| 3758 | return 1; | ||
| 3759 | } | ||
| 3760 | |||
| 3761 | |||
| 3762 | /* Load IT with the next display element from current_buffer. Value | ||
| 3763 | is zero if end of buffer reached. IT->stop_charpos is the next | ||
| 3764 | position at which to stop and check for text properties or buffer | ||
| 3765 | end. */ | ||
| 3766 | |||
| 3767 | static int | ||
| 3768 | next_element_from_buffer (it) | ||
| 3769 | struct it *it; | ||
| 3770 | { | ||
| 3771 | int success_p = 1; | ||
| 3772 | |||
| 3773 | /* Check this assumption, otherwise, we would never enter the | ||
| 3774 | if-statement, below. */ | ||
| 3775 | xassert (IT_CHARPOS (*it) >= BEGV | ||
| 3776 | && IT_CHARPOS (*it) <= it->stop_charpos); | ||
| 3777 | |||
| 3778 | if (IT_CHARPOS (*it) >= it->stop_charpos) | ||
| 3779 | { | ||
| 3780 | if (IT_CHARPOS (*it) >= it->end_charpos) | ||
| 3781 | { | ||
| 3782 | int overlay_strings_follow_p; | ||
| 3783 | |||
| 3784 | /* End of the game, except when overlay strings follow that | ||
| 3785 | haven't been returned yet. */ | ||
| 3786 | if (it->overlay_strings_at_end_processed_p) | ||
| 3787 | overlay_strings_follow_p = 0; | ||
| 3788 | else | ||
| 3789 | { | ||
| 3790 | it->overlay_strings_at_end_processed_p = 1; | ||
| 3791 | overlay_strings_follow_p | ||
| 3792 | = get_overlay_strings (it); | ||
| 3793 | } | ||
| 3794 | |||
| 3795 | if (overlay_strings_follow_p) | ||
| 3796 | success_p = get_next_display_element (it); | ||
| 3797 | else | ||
| 3798 | { | ||
| 3799 | it->what = IT_EOB; | ||
| 3800 | it->position = it->current.pos; | ||
| 3801 | success_p = 0; | ||
| 3802 | } | ||
| 3803 | } | ||
| 3804 | else | ||
| 3805 | { | ||
| 3806 | handle_stop (it); | ||
| 3807 | return get_next_display_element (it); | ||
| 3808 | } | ||
| 3809 | } | ||
| 3810 | else | ||
| 3811 | { | ||
| 3812 | /* No face changes, overlays etc. in sight, so just return a | ||
| 3813 | character from current_buffer. */ | ||
| 3814 | unsigned char *p; | ||
| 3815 | |||
| 3816 | /* Maybe run the redisplay end trigger hook. Performance note: | ||
| 3817 | This doesn't seem to cost measurable time. */ | ||
| 3818 | if (it->redisplay_end_trigger_charpos | ||
| 3819 | && it->glyph_row | ||
| 3820 | && IT_CHARPOS (*it) >= it->redisplay_end_trigger_charpos) | ||
| 3821 | run_redisplay_end_trigger_hook (it); | ||
| 3822 | |||
| 3823 | /* Get the next character, maybe multibyte. */ | ||
| 3824 | p = BYTE_POS_ADDR (IT_BYTEPOS (*it)); | ||
| 3825 | if (it->multibyte_p) | ||
| 3826 | { | ||
| 3827 | int maxlen = ((IT_BYTEPOS (*it) >= GPT_BYTE ? ZV_BYTE : GPT_BYTE) | ||
| 3828 | - IT_BYTEPOS (*it)); | ||
| 3829 | it->c = STRING_CHAR_AND_LENGTH (p, maxlen, it->len); | ||
| 3830 | } | ||
| 3831 | else | ||
| 3832 | it->c = *p, it->len = 1; | ||
| 3833 | |||
| 3834 | /* Record what we have and where it came from. */ | ||
| 3835 | it->what = IT_CHARACTER;; | ||
| 3836 | it->object = it->w->buffer; | ||
| 3837 | it->position = it->current.pos; | ||
| 3838 | |||
| 3839 | /* Normally we return the character found above, except when we | ||
| 3840 | really want to return an ellipsis for selective display. */ | ||
| 3841 | if (it->selective) | ||
| 3842 | { | ||
| 3843 | if (it->c == '\n') | ||
| 3844 | { | ||
| 3845 | /* A value of selective > 0 means hide lines indented more | ||
| 3846 | than that number of columns. */ | ||
| 3847 | if (it->selective > 0 | ||
| 3848 | && IT_CHARPOS (*it) + 1 < ZV | ||
| 3849 | && indented_beyond_p (IT_CHARPOS (*it) + 1, | ||
| 3850 | IT_BYTEPOS (*it) + 1, | ||
| 3851 | it->selective)) | ||
| 3852 | next_element_from_ellipsis (it); | ||
| 3853 | } | ||
| 3854 | else if (it->c == '\r' && it->selective == -1) | ||
| 3855 | { | ||
| 3856 | /* A value of selective == -1 means that everything from the | ||
| 3857 | CR to the end of the line is invisible, with maybe an | ||
| 3858 | ellipsis displayed for it. */ | ||
| 3859 | next_element_from_ellipsis (it); | ||
| 3860 | } | ||
| 3861 | } | ||
| 3862 | } | ||
| 3863 | |||
| 3864 | /* Value is zero if end of buffer reached. */ | ||
| 3865 | xassert (!success_p || it->len > 0); | ||
| 3866 | return success_p; | ||
| 3867 | } | ||
| 3868 | |||
| 3869 | |||
| 3870 | /* Run the redisplay end trigger hook for IT. */ | ||
| 3871 | |||
| 3872 | static void | ||
| 3873 | run_redisplay_end_trigger_hook (it) | ||
| 3874 | struct it *it; | ||
| 3875 | { | ||
| 3876 | Lisp_Object args[3]; | ||
| 3877 | |||
| 3878 | /* IT->glyph_row should be non-null, i.e. we should be actually | ||
| 3879 | displaying something, or otherwise we should not run the hook. */ | ||
| 3880 | xassert (it->glyph_row); | ||
| 3881 | |||
| 3882 | /* Set up hook arguments. */ | ||
| 3883 | args[0] = Qredisplay_end_trigger_functions; | ||
| 3884 | args[1] = it->window; | ||
| 3885 | XSETINT (args[2], it->redisplay_end_trigger_charpos); | ||
| 3886 | it->redisplay_end_trigger_charpos = 0; | ||
| 3887 | |||
| 3888 | /* Since we are *trying* to run these functions, don't try to run | ||
| 3889 | them again, even if they get an error. */ | ||
| 3890 | it->w->redisplay_end_trigger = Qnil; | ||
| 3891 | Frun_hook_with_args (3, args); | ||
| 3892 | |||
| 3893 | /* Notice if it changed the face of the character we are on. */ | ||
| 3894 | handle_face_prop (it); | ||
| 3895 | } | ||
| 3896 | |||
| 3897 | |||
| 3898 | |||
| 3899 | /*********************************************************************** | ||
| 3900 | Moving an iterator without producing glyphs | ||
| 3901 | ***********************************************************************/ | ||
| 3902 | |||
| 3903 | /* Move iterator IT to a specified buffer or X position within one | ||
| 3904 | line on the display without producing glyphs. | ||
| 3905 | |||
| 3906 | Begin to skip at IT's current position. Skip to TO_CHARPOS or TO_X | ||
| 3907 | whichever is reached first. | ||
| 3908 | |||
| 3909 | TO_CHARPOS <= 0 means no TO_CHARPOS is specified. | ||
| 3910 | |||
| 3911 | TO_X < 0 means that no TO_X is specified. TO_X is normally a value | ||
| 3912 | 0 <= TO_X <= IT->last_visible_x. This means in particular, that | ||
| 3913 | TO_X includes the amount by which a window is horizontally | ||
| 3914 | scrolled. | ||
| 3915 | |||
| 3916 | Value is | ||
| 3917 | |||
| 3918 | MOVE_POS_MATCH_OR_ZV | ||
| 3919 | - when TO_POS or ZV was reached. | ||
| 3920 | |||
| 3921 | MOVE_X_REACHED | ||
| 3922 | -when TO_X was reached before TO_POS or ZV were reached. | ||
| 3923 | |||
| 3924 | MOVE_LINE_CONTINUED | ||
| 3925 | - when we reached the end of the display area and the line must | ||
| 3926 | be continued. | ||
| 3927 | |||
| 3928 | MOVE_LINE_TRUNCATED | ||
| 3929 | - when we reached the end of the display area and the line is | ||
| 3930 | truncated. | ||
| 3931 | |||
| 3932 | MOVE_NEWLINE_OR_CR | ||
| 3933 | - when we stopped at a line end, i.e. a newline or a CR and selective | ||
| 3934 | display is on. */ | ||
| 3935 | |||
| 3936 | enum move_it_result | ||
| 3937 | move_it_in_display_line_to (it, to_charpos, to_x, op) | ||
| 3938 | struct it *it; | ||
| 3939 | int to_charpos, to_x, op; | ||
| 3940 | { | ||
| 3941 | enum move_it_result result = MOVE_UNDEFINED; | ||
| 3942 | struct glyph_row *saved_glyph_row; | ||
| 3943 | |||
| 3944 | /* Don't produce glyphs in produce_glyphs. */ | ||
| 3945 | saved_glyph_row = it->glyph_row; | ||
| 3946 | it->glyph_row = NULL; | ||
| 3947 | |||
| 3948 | #if NO_PROMPT_IN_BUFFER | ||
| 3949 | /* Take a mini-buffer prompt into account. */ | ||
| 3950 | if (MINI_WINDOW_P (it->w) | ||
| 3951 | && IT_CHARPOS (*it) == BEGV) | ||
| 3952 | { | ||
| 3953 | it->current_x = minibuf_prompt_pixel_width; | ||
| 3954 | it->hpos = minibuf_prompt_width; | ||
| 3955 | } | ||
| 3956 | #endif | ||
| 3957 | |||
| 3958 | while (1) | ||
| 3959 | { | ||
| 3960 | int x, i; | ||
| 3961 | |||
| 3962 | /* Stop when ZV or TO_CHARPOS reached. */ | ||
| 3963 | if (!get_next_display_element (it) | ||
| 3964 | || ((op & MOVE_TO_POS) != 0 | ||
| 3965 | && BUFFERP (it->object) | ||
| 3966 | && IT_CHARPOS (*it) >= to_charpos)) | ||
| 3967 | { | ||
| 3968 | result = MOVE_POS_MATCH_OR_ZV; | ||
| 3969 | break; | ||
| 3970 | } | ||
| 3971 | |||
| 3972 | /* The call to produce_glyphs will get the metrics of the | ||
| 3973 | display element IT is loaded with. We record in x the | ||
| 3974 | x-position before this display element in case it does not | ||
| 3975 | fit on the line. */ | ||
| 3976 | x = it->current_x; | ||
| 3977 | PRODUCE_GLYPHS (it); | ||
| 3978 | |||
| 3979 | if (it->area != TEXT_AREA) | ||
| 3980 | { | ||
| 3981 | set_iterator_to_next (it); | ||
| 3982 | continue; | ||
| 3983 | } | ||
| 3984 | |||
| 3985 | /* The number of glyphs we get back in IT->nglyphs will normally | ||
| 3986 | be 1 except when IT->c is (i) a TAB, or (ii) a multi-glyph | ||
| 3987 | character on a terminal frame, or (iii) a line end. For the | ||
| 3988 | second case, IT->nglyphs - 1 padding glyphs will be present | ||
| 3989 | (on X frames, there is only one glyph produced for a | ||
| 3990 | composite character. | ||
| 3991 | |||
| 3992 | The behavior implemented below means, for continuation lines, | ||
| 3993 | that as many spaces of a TAB as fit on the current line are | ||
| 3994 | displayed there. For terminal frames, as many glyphs of a | ||
| 3995 | multi-glyph character are displayed in the current line, too. | ||
| 3996 | This is what the old redisplay code did, and we keep it that | ||
| 3997 | way. Under X, the whole shape of a complex character must | ||
| 3998 | fit on the line or it will be completely displayed in the | ||
| 3999 | next line. | ||
| 4000 | |||
| 4001 | Note that both for tabs and padding glyphs, all glyphs have | ||
| 4002 | the same width. */ | ||
| 4003 | if (it->nglyphs) | ||
| 4004 | { | ||
| 4005 | /* More than one glyph or glyph doesn't fit on line. All | ||
| 4006 | glyphs have the same width. */ | ||
| 4007 | int single_glyph_width = it->pixel_width / it->nglyphs; | ||
| 4008 | int new_x; | ||
| 4009 | |||
| 4010 | for (i = 0; i < it->nglyphs; ++i, x = new_x) | ||
| 4011 | { | ||
| 4012 | new_x = x + single_glyph_width; | ||
| 4013 | |||
| 4014 | /* We want to leave anything reaching TO_X to the caller. */ | ||
| 4015 | if ((op & MOVE_TO_X) && new_x > to_x) | ||
| 4016 | { | ||
| 4017 | it->current_x = x; | ||
| 4018 | result = MOVE_X_REACHED; | ||
| 4019 | break; | ||
| 4020 | } | ||
| 4021 | else if (/* Lines are continued. */ | ||
| 4022 | !it->truncate_lines_p | ||
| 4023 | && (/* And glyph doesn't fit on the line. */ | ||
| 4024 | new_x > it->last_visible_x | ||
| 4025 | /* Or it fits exactly and we're on a window | ||
| 4026 | system frame. */ | ||
| 4027 | || (new_x == it->last_visible_x | ||
| 4028 | && FRAME_WINDOW_P (it->f)))) | ||
| 4029 | { | ||
| 4030 | if (/* IT->hpos == 0 means the very first glyph | ||
| 4031 | doesn't fit on the line, e.g. a wide image. */ | ||
| 4032 | it->hpos == 0 | ||
| 4033 | || (new_x == it->last_visible_x | ||
| 4034 | && FRAME_WINDOW_P (it->f))) | ||
| 4035 | { | ||
| 4036 | ++it->hpos; | ||
| 4037 | it->current_x = new_x; | ||
| 4038 | if (i == it->nglyphs - 1) | ||
| 4039 | set_iterator_to_next (it); | ||
| 4040 | } | ||
| 4041 | else | ||
| 4042 | it->current_x = x; | ||
| 4043 | |||
| 4044 | result = MOVE_LINE_CONTINUED; | ||
| 4045 | break; | ||
| 4046 | } | ||
| 4047 | else if (new_x > it->first_visible_x) | ||
| 4048 | { | ||
| 4049 | /* Glyph is visible. Increment number of glyphs that | ||
| 4050 | would be displayed. */ | ||
| 4051 | ++it->hpos; | ||
| 4052 | } | ||
| 4053 | else | ||
| 4054 | { | ||
| 4055 | /* Glyph is completely off the left margin of the display | ||
| 4056 | area. Nothing to do. */ | ||
| 4057 | } | ||
| 4058 | } | ||
| 4059 | |||
| 4060 | if (result != MOVE_UNDEFINED) | ||
| 4061 | break; | ||
| 4062 | } | ||
| 4063 | else if ((op & MOVE_TO_X) && it->current_x >= to_x) | ||
| 4064 | { | ||
| 4065 | /* Stop when TO_X specified and reached. This check is | ||
| 4066 | necessary here because of lines consisting of a line end, | ||
| 4067 | only. The line end will not produce any glyphs and we | ||
| 4068 | would never get MOVE_X_REACHED. */ | ||
| 4069 | xassert (it->nglyphs == 0); | ||
| 4070 | result = MOVE_X_REACHED; | ||
| 4071 | break; | ||
| 4072 | } | ||
| 4073 | |||
| 4074 | /* Is this a line end? If yes, we're done. */ | ||
| 4075 | if (ITERATOR_AT_END_OF_LINE_P (it)) | ||
| 4076 | { | ||
| 4077 | result = MOVE_NEWLINE_OR_CR; | ||
| 4078 | break; | ||
| 4079 | } | ||
| 4080 | |||
| 4081 | /* The current display element has been consumed. Advance | ||
| 4082 | to the next. */ | ||
| 4083 | set_iterator_to_next (it); | ||
| 4084 | |||
| 4085 | /* Stop if lines are truncated and IT's current x-position is | ||
| 4086 | past the right edge of the window now. */ | ||
| 4087 | if (it->truncate_lines_p | ||
| 4088 | && it->current_x >= it->last_visible_x) | ||
| 4089 | { | ||
| 4090 | result = MOVE_LINE_TRUNCATED; | ||
| 4091 | break; | ||
| 4092 | } | ||
| 4093 | } | ||
| 4094 | |||
| 4095 | /* Restore the iterator settings altered at the beginning of this | ||
| 4096 | function. */ | ||
| 4097 | it->glyph_row = saved_glyph_row; | ||
| 4098 | return result; | ||
| 4099 | } | ||
| 4100 | |||
| 4101 | |||
| 4102 | /* Move IT forward to a specified buffer position TO_CHARPOS, TO_X, | ||
| 4103 | TO_Y, TO_VPOS. OP is a bit-mask that specifies where to stop. See | ||
| 4104 | the description of enum move_operation_enum. | ||
| 4105 | |||
| 4106 | If TO_CHARPOS is in invisible text, e.g. a truncated part of a | ||
| 4107 | screen line, this function will set IT to the next position > | ||
| 4108 | TO_CHARPOS. */ | ||
| 4109 | |||
| 4110 | void | ||
| 4111 | move_it_to (it, to_charpos, to_x, to_y, to_vpos, op) | ||
| 4112 | struct it *it; | ||
| 4113 | int to_charpos, to_x, to_y, to_vpos; | ||
| 4114 | int op; | ||
| 4115 | { | ||
| 4116 | enum move_it_result skip, skip2 = MOVE_X_REACHED; | ||
| 4117 | int line_height; | ||
| 4118 | |||
| 4119 | xassert (XBUFFER (it->w->buffer) == current_buffer); | ||
| 4120 | |||
| 4121 | while (1) | ||
| 4122 | { | ||
| 4123 | if (op & MOVE_TO_VPOS) | ||
| 4124 | { | ||
| 4125 | /* If no TO_CHARPOS and no TO_X specified, stop at the | ||
| 4126 | start of the line TO_VPOS. */ | ||
| 4127 | if ((op & (MOVE_TO_X | MOVE_TO_POS)) == 0) | ||
| 4128 | { | ||
| 4129 | if (it->vpos == to_vpos) | ||
| 4130 | break; | ||
| 4131 | skip = move_it_in_display_line_to (it, -1, -1, 0); | ||
| 4132 | } | ||
| 4133 | else | ||
| 4134 | { | ||
| 4135 | /* TO_VPOS >= 0 means stop at TO_X in the line at | ||
| 4136 | TO_VPOS, or at TO_POS, whichever comes first. */ | ||
| 4137 | skip = move_it_in_display_line_to (it, to_charpos, to_x, op); | ||
| 4138 | |||
| 4139 | if (skip == MOVE_POS_MATCH_OR_ZV || it->vpos == to_vpos) | ||
| 4140 | break; | ||
| 4141 | else if (skip == MOVE_X_REACHED && it->vpos != to_vpos) | ||
| 4142 | { | ||
| 4143 | /* We have reached TO_X but not in the line we want. */ | ||
| 4144 | skip = move_it_in_display_line_to (it, to_charpos, | ||
| 4145 | -1, MOVE_TO_POS); | ||
| 4146 | if (skip == MOVE_POS_MATCH_OR_ZV) | ||
| 4147 | break; | ||
| 4148 | } | ||
| 4149 | } | ||
| 4150 | } | ||
| 4151 | else if (op & MOVE_TO_Y) | ||
| 4152 | { | ||
| 4153 | struct it it_backup; | ||
| 4154 | int done_p; | ||
| 4155 | |||
| 4156 | /* TO_Y specified means stop at TO_X in the line containing | ||
| 4157 | TO_Y---or at TO_CHARPOS if this is reached first. The | ||
| 4158 | problem is that we can't really tell whether the line | ||
| 4159 | contains TO_Y before we have completely scanned it, and | ||
| 4160 | this may skip past TO_X. What we do is to first scan to | ||
| 4161 | TO_X. | ||
| 4162 | |||
| 4163 | If TO_X is not specified, use a TO_X of zero. The reason | ||
| 4164 | is to make the outcome of this function more predictable. | ||
| 4165 | If we didn't use TO_X == 0, we would stop at the end of | ||
| 4166 | the line which is probably not what a caller would expect | ||
| 4167 | to happen. */ | ||
| 4168 | skip = move_it_in_display_line_to (it, to_charpos, | ||
| 4169 | ((op & MOVE_TO_X) | ||
| 4170 | ? to_x : 0), | ||
| 4171 | (MOVE_TO_X | ||
| 4172 | | (op & MOVE_TO_POS))); | ||
| 4173 | |||
| 4174 | /* If TO_CHARPOS is reached or ZV, we don't have to do more. */ | ||
| 4175 | if (skip == MOVE_POS_MATCH_OR_ZV) | ||
| 4176 | break; | ||
| 4177 | |||
| 4178 | /* If TO_X was reached, we would like to know whether TO_Y | ||
| 4179 | is in the line. This can only be said if we know the | ||
| 4180 | total line height which requires us to scan the rest of | ||
| 4181 | the line. */ | ||
| 4182 | done_p = 0; | ||
| 4183 | if (skip == MOVE_X_REACHED) | ||
| 4184 | { | ||
| 4185 | it_backup = *it; | ||
| 4186 | skip2 = move_it_in_display_line_to (it, to_charpos, -1, | ||
| 4187 | op & MOVE_TO_POS); | ||
| 4188 | } | ||
| 4189 | |||
| 4190 | /* Now, decide whether TO_Y is in this line. */ | ||
| 4191 | line_height = it->max_ascent + it->max_descent; | ||
| 4192 | |||
| 4193 | if (to_y >= it->current_y | ||
| 4194 | && to_y < it->current_y + line_height) | ||
| 4195 | { | ||
| 4196 | if (skip == MOVE_X_REACHED) | ||
| 4197 | /* If TO_Y is in this line and TO_X was reached above, | ||
| 4198 | we scanned too far. We have to restore IT's settings | ||
| 4199 | to the ones before skipping. */ | ||
| 4200 | *it = it_backup; | ||
| 4201 | done_p = 1; | ||
| 4202 | } | ||
| 4203 | else if (skip == MOVE_X_REACHED) | ||
| 4204 | { | ||
| 4205 | skip = skip2; | ||
| 4206 | if (skip == MOVE_POS_MATCH_OR_ZV) | ||
| 4207 | done_p = 1; | ||
| 4208 | } | ||
| 4209 | |||
| 4210 | if (done_p) | ||
| 4211 | break; | ||
| 4212 | } | ||
| 4213 | else | ||
| 4214 | skip = move_it_in_display_line_to (it, to_charpos, -1, MOVE_TO_POS); | ||
| 4215 | |||
| 4216 | switch (skip) | ||
| 4217 | { | ||
| 4218 | case MOVE_POS_MATCH_OR_ZV: | ||
| 4219 | return; | ||
| 4220 | |||
| 4221 | case MOVE_NEWLINE_OR_CR: | ||
| 4222 | set_iterator_to_next (it); | ||
| 4223 | it->continuation_lines_width = 0; | ||
| 4224 | break; | ||
| 4225 | |||
| 4226 | case MOVE_LINE_TRUNCATED: | ||
| 4227 | it->continuation_lines_width = 0; | ||
| 4228 | reseat_at_next_visible_line_start (it); | ||
| 4229 | if ((op & MOVE_TO_POS) != 0 | ||
| 4230 | && IT_CHARPOS (*it) > to_charpos) | ||
| 4231 | goto out; | ||
| 4232 | break; | ||
| 4233 | |||
| 4234 | case MOVE_LINE_CONTINUED: | ||
| 4235 | it->continuation_lines_width += it->current_x; | ||
| 4236 | break; | ||
| 4237 | |||
| 4238 | default: | ||
| 4239 | abort (); | ||
| 4240 | } | ||
| 4241 | |||
| 4242 | /* Reset/increment for the next run. */ | ||
| 4243 | recenter_overlay_lists (current_buffer, IT_CHARPOS (*it)); | ||
| 4244 | it->current_x = it->hpos = 0; | ||
| 4245 | it->current_y += it->max_ascent + it->max_descent; | ||
| 4246 | ++it->vpos; | ||
| 4247 | last_height = it->max_ascent + it->max_descent; | ||
| 4248 | last_max_ascent = it->max_ascent; | ||
| 4249 | it->max_ascent = it->max_descent = 0; | ||
| 4250 | } | ||
| 4251 | out:; | ||
| 4252 | } | ||
| 4253 | |||
| 4254 | |||
| 4255 | /* Move iterator IT backward by a specified y-distance DY, DY >= 0. | ||
| 4256 | |||
| 4257 | If DY > 0, move IT backward at least that many pixels. DY = 0 | ||
| 4258 | means move IT backward to the preceding line start or BEGV. This | ||
| 4259 | function may move over more than DY pixels if IT->current_y - DY | ||
| 4260 | ends up in the middle of a line; in this case IT->current_y will be | ||
| 4261 | set to the top of the line moved to. */ | ||
| 4262 | |||
| 4263 | void | ||
| 4264 | move_it_vertically_backward (it, dy) | ||
| 4265 | struct it *it; | ||
| 4266 | int dy; | ||
| 4267 | { | ||
| 4268 | int nlines, h, line_height; | ||
| 4269 | struct it it2; | ||
| 4270 | int start_pos = IT_CHARPOS (*it); | ||
| 4271 | |||
| 4272 | xassert (dy >= 0); | ||
| 4273 | |||
| 4274 | /* Estimate how many newlines we must move back. */ | ||
| 4275 | nlines = max (1, dy / CANON_Y_UNIT (it->f)); | ||
| 4276 | |||
| 4277 | /* Set the iterator's position that many lines back. */ | ||
| 4278 | while (nlines-- && IT_CHARPOS (*it) > BEGV) | ||
| 4279 | back_to_previous_visible_line_start (it); | ||
| 4280 | |||
| 4281 | /* Reseat the iterator here. When moving backward, we don't want | ||
| 4282 | reseat to skip forward over invisible text, set up the iterator | ||
| 4283 | to deliver from overlay strings at the new position etc. So, | ||
| 4284 | use reseat_1 here. */ | ||
| 4285 | reseat_1 (it, it->current.pos, 1); | ||
| 4286 | |||
| 4287 | /* We are now surely at a line start. */ | ||
| 4288 | it->current_x = it->hpos = 0; | ||
| 4289 | |||
| 4290 | /* Move forward and see what y-distance we moved. First move to the | ||
| 4291 | start of the next line so that we get its height. We need this | ||
| 4292 | height to be able to tell whether we reached the specified | ||
| 4293 | y-distance. */ | ||
| 4294 | it2 = *it; | ||
| 4295 | it2.max_ascent = it2.max_descent = 0; | ||
| 4296 | move_it_to (&it2, start_pos, -1, -1, it2.vpos + 1, | ||
| 4297 | MOVE_TO_POS | MOVE_TO_VPOS); | ||
| 4298 | xassert (IT_CHARPOS (*it) >= BEGV); | ||
| 4299 | line_height = it2.max_ascent + it2.max_descent; | ||
| 4300 | move_it_to (&it2, start_pos, -1, -1, -1, MOVE_TO_POS); | ||
| 4301 | xassert (IT_CHARPOS (*it) >= BEGV); | ||
| 4302 | h = it2.current_y - it->current_y; | ||
| 4303 | nlines = it2.vpos - it->vpos; | ||
| 4304 | |||
| 4305 | /* Correct IT's y and vpos position. */ | ||
| 4306 | it->vpos -= nlines; | ||
| 4307 | it->current_y -= h; | ||
| 4308 | |||
| 4309 | if (dy == 0) | ||
| 4310 | { | ||
| 4311 | /* DY == 0 means move to the start of the screen line. The | ||
| 4312 | value of nlines is > 0 if continuation lines were involved. */ | ||
| 4313 | if (nlines > 0) | ||
| 4314 | move_it_by_lines (it, nlines, 1); | ||
| 4315 | xassert (IT_CHARPOS (*it) <= start_pos); | ||
| 4316 | } | ||
| 4317 | else if (nlines) | ||
| 4318 | { | ||
| 4319 | /* The y-position we try to reach. Note that h has been | ||
| 4320 | subtracted in front of the if-statement. */ | ||
| 4321 | int target_y = it->current_y + h - dy; | ||
| 4322 | |||
| 4323 | /* If we did not reach target_y, try to move further backward if | ||
| 4324 | we can. If we moved too far backward, try to move forward. */ | ||
| 4325 | if (target_y < it->current_y | ||
| 4326 | && IT_CHARPOS (*it) > BEGV) | ||
| 4327 | { | ||
| 4328 | move_it_vertically (it, target_y - it->current_y); | ||
| 4329 | xassert (IT_CHARPOS (*it) >= BEGV); | ||
| 4330 | } | ||
| 4331 | else if (target_y >= it->current_y + line_height | ||
| 4332 | && IT_CHARPOS (*it) < ZV) | ||
| 4333 | { | ||
| 4334 | move_it_vertically (it, target_y - (it->current_y + line_height)); | ||
| 4335 | xassert (IT_CHARPOS (*it) >= BEGV); | ||
| 4336 | } | ||
| 4337 | } | ||
| 4338 | } | ||
| 4339 | |||
| 4340 | |||
| 4341 | /* Move IT by a specified amount of pixel lines DY. DY negative means | ||
| 4342 | move backwards. DY = 0 means move to start of screen line. At the | ||
| 4343 | end, IT will be on the start of a screen line. */ | ||
| 4344 | |||
| 4345 | void | ||
| 4346 | move_it_vertically (it, dy) | ||
| 4347 | struct it *it; | ||
| 4348 | int dy; | ||
| 4349 | { | ||
| 4350 | if (dy <= 0) | ||
| 4351 | move_it_vertically_backward (it, -dy); | ||
| 4352 | else if (dy > 0) | ||
| 4353 | { | ||
| 4354 | move_it_to (it, ZV, -1, it->current_y + dy, -1, | ||
| 4355 | MOVE_TO_POS | MOVE_TO_Y); | ||
| 4356 | |||
| 4357 | /* If buffer ends in ZV without a newline, move to the start of | ||
| 4358 | the line to satisfy the post-condition. */ | ||
| 4359 | if (IT_CHARPOS (*it) == ZV | ||
| 4360 | && FETCH_BYTE (IT_BYTEPOS (*it) - 1) != '\n') | ||
| 4361 | move_it_by_lines (it, 0, 0); | ||
| 4362 | } | ||
| 4363 | } | ||
| 4364 | |||
| 4365 | |||
| 4366 | /* Return non-zero if some text between buffer positions START_CHARPOS | ||
| 4367 | and END_CHARPOS is invisible. IT->window is the window for text | ||
| 4368 | property lookup. */ | ||
| 4369 | |||
| 4370 | static int | ||
| 4371 | invisible_text_between_p (it, start_charpos, end_charpos) | ||
| 4372 | struct it *it; | ||
| 4373 | int start_charpos, end_charpos; | ||
| 4374 | { | ||
| 4375 | #ifdef USE_TEXT_PROPERTIES | ||
| 4376 | Lisp_Object prop, limit; | ||
| 4377 | int invisible_found_p; | ||
| 4378 | |||
| 4379 | xassert (it != NULL && start_charpos <= end_charpos); | ||
| 4380 | |||
| 4381 | /* Is text at START invisible? */ | ||
| 4382 | prop = Fget_char_property (make_number (start_charpos), Qinvisible, | ||
| 4383 | it->window); | ||
| 4384 | if (TEXT_PROP_MEANS_INVISIBLE (prop)) | ||
| 4385 | invisible_found_p = 1; | ||
| 4386 | else | ||
| 4387 | { | ||
| 4388 | limit = Fnext_single_property_change (make_number (start_charpos), | ||
| 4389 | Qinvisible, | ||
| 4390 | Fcurrent_buffer (), | ||
| 4391 | make_number (end_charpos)); | ||
| 4392 | invisible_found_p = XFASTINT (limit) < end_charpos; | ||
| 4393 | } | ||
| 4394 | |||
| 4395 | return invisible_found_p; | ||
| 4396 | |||
| 4397 | #else /* not USE_TEXT_PROPERTIES */ | ||
| 4398 | return 0; | ||
| 4399 | #endif /* not USE_TEXT_PROPERTIES */ | ||
| 4400 | } | ||
| 4401 | |||
| 4402 | |||
| 4403 | /* Move IT by a specified number DVPOS of screen lines down. DVPOS | ||
| 4404 | negative means move up. DVPOS == 0 means move to the start of the | ||
| 4405 | screen line. NEED_Y_P non-zero means calculate IT->current_y. If | ||
| 4406 | NEED_Y_P is zero, IT->current_y will be left unchanged. | ||
| 4407 | |||
| 4408 | Further optimization ideas: If we would know that IT->f doesn't use | ||
| 4409 | a face with proportional font, we could be faster for | ||
| 4410 | truncate-lines nil. */ | ||
| 4411 | |||
| 4412 | void | ||
| 4413 | move_it_by_lines (it, dvpos, need_y_p) | ||
| 4414 | struct it *it; | ||
| 4415 | int dvpos, need_y_p; | ||
| 4416 | { | ||
| 4417 | struct position pos; | ||
| 4418 | |||
| 4419 | if (!FRAME_WINDOW_P (it->f)) | ||
| 4420 | { | ||
| 4421 | struct text_pos textpos; | ||
| 4422 | |||
| 4423 | /* We can use vmotion on frames without proportional fonts. */ | ||
| 4424 | pos = *vmotion (IT_CHARPOS (*it), dvpos, it->w); | ||
| 4425 | SET_TEXT_POS (textpos, pos.bufpos, pos.bytepos); | ||
| 4426 | reseat (it, textpos, 1); | ||
| 4427 | it->vpos += pos.vpos; | ||
| 4428 | it->current_y += pos.vpos; | ||
| 4429 | } | ||
| 4430 | else if (dvpos == 0) | ||
| 4431 | { | ||
| 4432 | /* DVPOS == 0 means move to the start of the screen line. */ | ||
| 4433 | move_it_vertically_backward (it, 0); | ||
| 4434 | xassert (it->current_x == 0 && it->hpos == 0); | ||
| 4435 | } | ||
| 4436 | else if (dvpos > 0) | ||
| 4437 | { | ||
| 4438 | /* If there are no continuation lines, and if there is no | ||
| 4439 | selective display, try the simple method of moving forward | ||
| 4440 | DVPOS newlines, then see where we are. */ | ||
| 4441 | if (!need_y_p && it->truncate_lines_p && it->selective == 0) | ||
| 4442 | { | ||
| 4443 | int shortage = 0, charpos; | ||
| 4444 | |||
| 4445 | if (FETCH_BYTE (IT_BYTEPOS (*it) == '\n')) | ||
| 4446 | charpos = IT_CHARPOS (*it) + 1; | ||
| 4447 | else | ||
| 4448 | charpos = scan_buffer ('\n', IT_CHARPOS (*it), 0, dvpos, | ||
| 4449 | &shortage, 0); | ||
| 4450 | |||
| 4451 | if (!invisible_text_between_p (it, IT_CHARPOS (*it), charpos)) | ||
| 4452 | { | ||
| 4453 | struct text_pos pos; | ||
| 4454 | CHARPOS (pos) = charpos; | ||
| 4455 | BYTEPOS (pos) = CHAR_TO_BYTE (charpos); | ||
| 4456 | reseat (it, pos, 1); | ||
| 4457 | it->vpos += dvpos - shortage; | ||
| 4458 | it->hpos = it->current_x = 0; | ||
| 4459 | return; | ||
| 4460 | } | ||
| 4461 | } | ||
| 4462 | |||
| 4463 | move_it_to (it, -1, -1, -1, it->vpos + dvpos, MOVE_TO_VPOS); | ||
| 4464 | } | ||
| 4465 | else | ||
| 4466 | { | ||
| 4467 | struct it it2; | ||
| 4468 | int start_charpos, i; | ||
| 4469 | |||
| 4470 | /* If there are no continuation lines, and if there is no | ||
| 4471 | selective display, try the simple method of moving backward | ||
| 4472 | -DVPOS newlines. */ | ||
| 4473 | if (!need_y_p && it->truncate_lines_p && it->selective == 0) | ||
| 4474 | { | ||
| 4475 | int shortage; | ||
| 4476 | int charpos = IT_CHARPOS (*it); | ||
| 4477 | int bytepos = IT_BYTEPOS (*it); | ||
| 4478 | |||
| 4479 | /* If in the middle of a line, go to its start. */ | ||
| 4480 | if (charpos > BEGV && FETCH_BYTE (bytepos - 1) != '\n') | ||
| 4481 | { | ||
| 4482 | charpos = find_next_newline_no_quit (charpos, -1); | ||
| 4483 | bytepos = CHAR_TO_BYTE (charpos); | ||
| 4484 | } | ||
| 4485 | |||
| 4486 | if (charpos == BEGV) | ||
| 4487 | { | ||
| 4488 | struct text_pos pos; | ||
| 4489 | CHARPOS (pos) = charpos; | ||
| 4490 | BYTEPOS (pos) = bytepos; | ||
| 4491 | reseat (it, pos, 1); | ||
| 4492 | it->hpos = it->current_x = 0; | ||
| 4493 | return; | ||
| 4494 | } | ||
| 4495 | else | ||
| 4496 | { | ||
| 4497 | charpos = scan_buffer ('\n', charpos - 1, 0, dvpos, &shortage, 0); | ||
| 4498 | if (!invisible_text_between_p (it, charpos, IT_CHARPOS (*it))) | ||
| 4499 | { | ||
| 4500 | struct text_pos pos; | ||
| 4501 | CHARPOS (pos) = charpos; | ||
| 4502 | BYTEPOS (pos) = CHAR_TO_BYTE (charpos); | ||
| 4503 | reseat (it, pos, 1); | ||
| 4504 | it->vpos += dvpos + (shortage ? shortage - 1 : 0); | ||
| 4505 | it->hpos = it->current_x = 0; | ||
| 4506 | return; | ||
| 4507 | } | ||
| 4508 | } | ||
| 4509 | } | ||
| 4510 | |||
| 4511 | /* Go back -DVPOS visible lines and reseat the iterator there. */ | ||
| 4512 | start_charpos = IT_CHARPOS (*it); | ||
| 4513 | for (i = -dvpos; i && IT_CHARPOS (*it) > BEGV; --i) | ||
| 4514 | back_to_previous_visible_line_start (it); | ||
| 4515 | reseat (it, it->current.pos, 1); | ||
| 4516 | it->current_x = it->hpos = 0; | ||
| 4517 | |||
| 4518 | /* Above call may have moved too far if continuation lines | ||
| 4519 | are involved. Scan forward and see if it did. */ | ||
| 4520 | it2 = *it; | ||
| 4521 | it2.vpos = it2.current_y = 0; | ||
| 4522 | move_it_to (&it2, start_charpos, -1, -1, -1, MOVE_TO_POS); | ||
| 4523 | it->vpos -= it2.vpos; | ||
| 4524 | it->current_y -= it2.current_y; | ||
| 4525 | it->current_x = it->hpos = 0; | ||
| 4526 | |||
| 4527 | /* If we moved too far, move IT some lines forward. */ | ||
| 4528 | if (it2.vpos > -dvpos) | ||
| 4529 | { | ||
| 4530 | int delta = it2.vpos + dvpos; | ||
| 4531 | move_it_to (it, -1, -1, -1, it->vpos + delta, MOVE_TO_VPOS); | ||
| 4532 | } | ||
| 4533 | } | ||
| 4534 | } | ||
| 4535 | |||
| 4536 | |||
| 4537 | |||
| 4538 | /*********************************************************************** | ||
| 4539 | Messages | ||
| 4540 | ***********************************************************************/ | ||
| 4541 | |||
| 4542 | |||
| 279 | /* Output a newline in the *Messages* buffer if "needs" one. */ | 4543 | /* Output a newline in the *Messages* buffer if "needs" one. */ |
| 280 | 4544 | ||
| 281 | void | 4545 | void |
| @@ -286,10 +4550,11 @@ message_log_maybe_newline () | |||
| 286 | } | 4550 | } |
| 287 | 4551 | ||
| 288 | 4552 | ||
| 289 | /* Add a string to the message log, optionally terminated with a newline. | 4553 | /* Add a string M of length LEN to the message log, optionally |
| 290 | This function calls low-level routines in order to bypass text property | 4554 | terminated with a newline when NLFLAG is non-zero. MULTIBYTE, if |
| 291 | hooks, etc. which might not be safe to run. | 4555 | nonzero, means interpret the contents of M as multibyte. This |
| 292 | MULTIBYTE, if nonzero, means interpret the contents of M as multibyte. */ | 4556 | function calls low-level routines in order to bypass text property |
| 4557 | hooks, etc. which might not be safe to run. */ | ||
| 293 | 4558 | ||
| 294 | void | 4559 | void |
| 295 | message_dolog (m, len, nlflag, multibyte) | 4560 | message_dolog (m, len, nlflag, multibyte) |
| @@ -334,6 +4599,7 @@ message_dolog (m, len, nlflag, multibyte) | |||
| 334 | { | 4599 | { |
| 335 | int i, c, nbytes; | 4600 | int i, c, nbytes; |
| 336 | unsigned char work[1]; | 4601 | unsigned char work[1]; |
| 4602 | |||
| 337 | /* Convert a multibyte string to single-byte | 4603 | /* Convert a multibyte string to single-byte |
| 338 | for the *Message* buffer. */ | 4604 | for the *Message* buffer. */ |
| 339 | for (i = 0; i < len; i += nbytes) | 4605 | for (i = 0; i < len; i += nbytes) |
| @@ -442,6 +4708,7 @@ message_dolog (m, len, nlflag, multibyte) | |||
| 442 | } | 4708 | } |
| 443 | } | 4709 | } |
| 444 | 4710 | ||
| 4711 | |||
| 445 | /* We are at the end of the buffer after just having inserted a newline. | 4712 | /* We are at the end of the buffer after just having inserted a newline. |
| 446 | (Note: We depend on the fact we won't be crossing the gap.) | 4713 | (Note: We depend on the fact we won't be crossing the gap.) |
| 447 | Check to see if the most recent message looks a lot like the previous one. | 4714 | Check to see if the most recent message looks a lot like the previous one. |
| @@ -480,16 +4747,16 @@ message_log_check_duplicate (prev_bol, prev_bol_byte, this_bol, this_bol_byte) | |||
| 480 | } | 4747 | } |
| 481 | return 0; | 4748 | return 0; |
| 482 | } | 4749 | } |
| 483 | |||
| 484 | /* Display an echo area message M with a specified length of LEN chars. | ||
| 485 | The string may include null characters. If M is 0, clear out any | ||
| 486 | existing message, and let the minibuffer text show through. | ||
| 487 | 4750 | ||
| 488 | The buffer M must continue to exist until after the echo area | ||
| 489 | gets cleared or some other message gets displayed there. | ||
| 490 | 4751 | ||
| 491 | Do not pass text that is stored in a Lisp string. | 4752 | /* Display an echo area message M with a specified length of LEN |
| 492 | Do not pass text in a buffer that was alloca'd. */ | 4753 | chars. The string may include null characters. If M is 0, clear |
| 4754 | out any existing message, and let the mini-buffer text show through. | ||
| 4755 | |||
| 4756 | The buffer M must continue to exist until after the echo area gets | ||
| 4757 | cleared or some other message gets displayed there. This means do | ||
| 4758 | not pass text that is stored in a Lisp string; do not pass text in | ||
| 4759 | a buffer that was alloca'd. */ | ||
| 493 | 4760 | ||
| 494 | void | 4761 | void |
| 495 | message2 (m, len, multibyte) | 4762 | message2 (m, len, multibyte) |
| @@ -528,12 +4795,14 @@ message2_nolog (m, len, multibyte) | |||
| 528 | /* A null message buffer means that the frame hasn't really been | 4795 | /* A null message buffer means that the frame hasn't really been |
| 529 | initialized yet. Error messages get reported properly by | 4796 | initialized yet. Error messages get reported properly by |
| 530 | cmd_error, so this must be just an informative message; toss it. */ | 4797 | cmd_error, so this must be just an informative message; toss it. */ |
| 531 | else if (INTERACTIVE && FRAME_MESSAGE_BUF (selected_frame)) | 4798 | else if (INTERACTIVE |
| 4799 | && selected_frame->glyphs_initialized_p | ||
| 4800 | && FRAME_MESSAGE_BUF (selected_frame)) | ||
| 532 | { | 4801 | { |
| 533 | Lisp_Object mini_window; | 4802 | Lisp_Object mini_window; |
| 534 | FRAME_PTR f; | 4803 | struct frame *f; |
| 535 | 4804 | ||
| 536 | /* Get the frame containing the minibuffer | 4805 | /* Get the frame containing the mini-buffer |
| 537 | that the selected frame is using. */ | 4806 | that the selected frame is using. */ |
| 538 | mini_window = FRAME_MINIBUF_WINDOW (selected_frame); | 4807 | mini_window = FRAME_MINIBUF_WINDOW (selected_frame); |
| 539 | f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window))); | 4808 | f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window))); |
| @@ -547,31 +4816,122 @@ message2_nolog (m, len, multibyte) | |||
| 547 | { | 4816 | { |
| 548 | echo_area_glyphs = m; | 4817 | echo_area_glyphs = m; |
| 549 | echo_area_glyphs_length = len; | 4818 | echo_area_glyphs_length = len; |
| 4819 | echo_area_message = Qnil; | ||
| 550 | 4820 | ||
| 551 | if (minibuffer_auto_raise) | 4821 | if (minibuffer_auto_raise) |
| 552 | Fraise_frame (WINDOW_FRAME (XWINDOW (mini_window))); | 4822 | Fraise_frame (WINDOW_FRAME (XWINDOW (mini_window))); |
| 553 | } | 4823 | } |
| 554 | else | 4824 | else |
| 555 | echo_area_glyphs = previous_echo_glyphs = 0; | 4825 | { |
| 4826 | echo_area_glyphs = previous_echo_glyphs = NULL; | ||
| 4827 | echo_area_message = previous_echo_area_message = Qnil; | ||
| 4828 | } | ||
| 556 | 4829 | ||
| 557 | do_pending_window_change (); | 4830 | do_pending_window_change (); |
| 558 | echo_area_display (); | 4831 | echo_area_display (1); |
| 559 | update_frame (f, 1, 1); | ||
| 560 | do_pending_window_change (); | 4832 | do_pending_window_change (); |
| 561 | if (frame_up_to_date_hook != 0 && ! gc_in_progress) | 4833 | if (frame_up_to_date_hook != 0 && ! gc_in_progress) |
| 562 | (*frame_up_to_date_hook) (f); | 4834 | (*frame_up_to_date_hook) (f); |
| 563 | } | 4835 | } |
| 564 | } | 4836 | } |
| 565 | |||
| 566 | /* Display in echo area the null-terminated ASCII-only string M. | ||
| 567 | If M is 0, clear out any existing message, | ||
| 568 | and let the minibuffer text show through. | ||
| 569 | 4837 | ||
| 570 | The string M must continue to exist until after the echo area | ||
| 571 | gets cleared or some other message gets displayed there. | ||
| 572 | 4838 | ||
| 573 | Do not pass text that is stored in a Lisp string. | 4839 | /* Display an echo area message M with a specified length of LEN |
| 574 | Do not pass text in a buffer that was alloca'd. */ | 4840 | chars. The string may include null characters. If M is not a |
| 4841 | string, clear out any existing message, and let the mini-buffer | ||
| 4842 | text show through. */ | ||
| 4843 | |||
| 4844 | void | ||
| 4845 | message3 (m, len, multibyte) | ||
| 4846 | Lisp_Object m; | ||
| 4847 | int len; | ||
| 4848 | int multibyte; | ||
| 4849 | { | ||
| 4850 | struct gcpro gcpro1; | ||
| 4851 | |||
| 4852 | GCPRO1 (m); | ||
| 4853 | |||
| 4854 | /* First flush out any partial line written with print. */ | ||
| 4855 | message_log_maybe_newline (); | ||
| 4856 | if (STRINGP (m)) | ||
| 4857 | message_dolog (XSTRING (m)->data, len, 1, multibyte); | ||
| 4858 | message3_nolog (m, len, multibyte); | ||
| 4859 | |||
| 4860 | UNGCPRO; | ||
| 4861 | } | ||
| 4862 | |||
| 4863 | |||
| 4864 | /* The non-logging version of message3. */ | ||
| 4865 | |||
| 4866 | void | ||
| 4867 | message3_nolog (m, len, multibyte) | ||
| 4868 | Lisp_Object m; | ||
| 4869 | int len, multibyte; | ||
| 4870 | { | ||
| 4871 | message_enable_multibyte = multibyte; | ||
| 4872 | |||
| 4873 | if (noninteractive) | ||
| 4874 | { | ||
| 4875 | if (noninteractive_need_newline) | ||
| 4876 | putc ('\n', stderr); | ||
| 4877 | noninteractive_need_newline = 0; | ||
| 4878 | if (STRINGP (m)) | ||
| 4879 | fwrite (XSTRING (m)->data, len, 1, stderr); | ||
| 4880 | if (cursor_in_echo_area == 0) | ||
| 4881 | fprintf (stderr, "\n"); | ||
| 4882 | fflush (stderr); | ||
| 4883 | } | ||
| 4884 | /* A null message buffer means that the frame hasn't really been | ||
| 4885 | initialized yet. Error messages get reported properly by | ||
| 4886 | cmd_error, so this must be just an informative message; toss it. */ | ||
| 4887 | else if (INTERACTIVE | ||
| 4888 | && selected_frame->glyphs_initialized_p | ||
| 4889 | && FRAME_MESSAGE_BUF (selected_frame)) | ||
| 4890 | { | ||
| 4891 | Lisp_Object mini_window; | ||
| 4892 | struct frame *f; | ||
| 4893 | |||
| 4894 | /* Get the frame containing the mini-buffer | ||
| 4895 | that the selected frame is using. */ | ||
| 4896 | mini_window = FRAME_MINIBUF_WINDOW (selected_frame); | ||
| 4897 | f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window))); | ||
| 4898 | |||
| 4899 | FRAME_SAMPLE_VISIBILITY (f); | ||
| 4900 | if (FRAME_VISIBLE_P (selected_frame) | ||
| 4901 | && ! FRAME_VISIBLE_P (f)) | ||
| 4902 | Fmake_frame_visible (WINDOW_FRAME (XWINDOW (mini_window))); | ||
| 4903 | |||
| 4904 | if (STRINGP (m)) | ||
| 4905 | { | ||
| 4906 | echo_area_glyphs = NULL; | ||
| 4907 | echo_area_message = m; | ||
| 4908 | echo_area_glyphs_length = len; | ||
| 4909 | |||
| 4910 | if (minibuffer_auto_raise) | ||
| 4911 | Fraise_frame (WINDOW_FRAME (XWINDOW (mini_window))); | ||
| 4912 | } | ||
| 4913 | else | ||
| 4914 | { | ||
| 4915 | echo_area_glyphs = previous_echo_glyphs = NULL; | ||
| 4916 | echo_area_message = previous_echo_area_message = Qnil; | ||
| 4917 | } | ||
| 4918 | |||
| 4919 | do_pending_window_change (); | ||
| 4920 | echo_area_display (1); | ||
| 4921 | do_pending_window_change (); | ||
| 4922 | if (frame_up_to_date_hook != 0 && ! gc_in_progress) | ||
| 4923 | (*frame_up_to_date_hook) (f); | ||
| 4924 | } | ||
| 4925 | } | ||
| 4926 | |||
| 4927 | |||
| 4928 | /* Display a null-terminated echo area message M. If M is 0, clear | ||
| 4929 | out any existing message, and let the mini-buffer text show through. | ||
| 4930 | |||
| 4931 | The buffer M must continue to exist until after the echo area gets | ||
| 4932 | cleared or some other message gets displayed there. Do not pass | ||
| 4933 | text that is stored in a Lisp string. Do not pass text in a buffer | ||
| 4934 | that was alloca'd. */ | ||
| 575 | 4935 | ||
| 576 | void | 4936 | void |
| 577 | message1 (m) | 4937 | message1 (m) |
| @@ -580,6 +4940,9 @@ message1 (m) | |||
| 580 | message2 (m, (m ? strlen (m) : 0), 0); | 4940 | message2 (m, (m ? strlen (m) : 0), 0); |
| 581 | } | 4941 | } |
| 582 | 4942 | ||
| 4943 | |||
| 4944 | /* The non-logging counterpart of message1. */ | ||
| 4945 | |||
| 583 | void | 4946 | void |
| 584 | message1_nolog (m) | 4947 | message1_nolog (m) |
| 585 | char *m; | 4948 | char *m; |
| @@ -648,6 +5011,7 @@ message_with_string (m, string, log) | |||
| 648 | } | 5011 | } |
| 649 | } | 5012 | } |
| 650 | 5013 | ||
| 5014 | |||
| 651 | /* Truncate what will be displayed in the echo area | 5015 | /* Truncate what will be displayed in the echo area |
| 652 | the next time we display it--but don't redisplay it now. */ | 5016 | the next time we display it--but don't redisplay it now. */ |
| 653 | 5017 | ||
| @@ -662,12 +5026,15 @@ truncate_echo_area (len) | |||
| 662 | echo_area_glyphs_length = len; | 5026 | echo_area_glyphs_length = len; |
| 663 | } | 5027 | } |
| 664 | 5028 | ||
| 665 | /* Nonzero if FRAME_MESSAGE_BUF (selected_frame) is being used by print; | 5029 | |
| 666 | zero if being used by message. */ | 5030 | /* Nonzero if FRAME_MESSAGE_BUF (selected_frame) is being used by |
| 5031 | print; zero if being used by message. */ | ||
| 5032 | |||
| 667 | int message_buf_print; | 5033 | int message_buf_print; |
| 668 | 5034 | ||
| 5035 | |||
| 669 | /* Dump an informative message to the minibuf. If M is 0, clear out | 5036 | /* Dump an informative message to the minibuf. If M is 0, clear out |
| 670 | any existing message, and let the minibuffer text show through. */ | 5037 | any existing message, and let the mini-buffer text show through. */ |
| 671 | 5038 | ||
| 672 | /* VARARGS 1 */ | 5039 | /* VARARGS 1 */ |
| 673 | void | 5040 | void |
| @@ -690,20 +5057,21 @@ message (m, a1, a2, a3) | |||
| 690 | } | 5057 | } |
| 691 | else if (INTERACTIVE) | 5058 | else if (INTERACTIVE) |
| 692 | { | 5059 | { |
| 693 | /* The frame whose minibuffer we're going to display the message on. | 5060 | /* The frame whose mini-buffer we're going to display the message |
| 694 | It may be larger than the selected frame, so we need | 5061 | on. It may be larger than the selected frame, so we need to |
| 695 | to use its buffer, not the selected frame's buffer. */ | 5062 | use its buffer, not the selected frame's buffer. */ |
| 696 | Lisp_Object mini_window; | 5063 | Lisp_Object mini_window; |
| 697 | FRAME_PTR f; | 5064 | struct frame *f; |
| 698 | 5065 | ||
| 699 | /* Get the frame containing the minibuffer | 5066 | /* Get the frame containing the mini-buffer |
| 700 | that the selected frame is using. */ | 5067 | that the selected frame is using. */ |
| 701 | mini_window = FRAME_MINIBUF_WINDOW (selected_frame); | 5068 | mini_window = FRAME_MINIBUF_WINDOW (selected_frame); |
| 702 | f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window))); | 5069 | f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window))); |
| 703 | 5070 | ||
| 704 | /* A null message buffer means that the frame hasn't really been | 5071 | /* A null message buffer means that the frame hasn't really been |
| 705 | initialized yet. Error messages get reported properly by | 5072 | initialized yet. Error messages get reported properly by |
| 706 | cmd_error, so this must be just an informative message; toss it. */ | 5073 | cmd_error, so this must be just an informative message; toss |
| 5074 | it. */ | ||
| 707 | if (FRAME_MESSAGE_BUF (f)) | 5075 | if (FRAME_MESSAGE_BUF (f)) |
| 708 | { | 5076 | { |
| 709 | if (m) | 5077 | if (m) |
| @@ -735,7 +5103,9 @@ message (m, a1, a2, a3) | |||
| 735 | } | 5103 | } |
| 736 | } | 5104 | } |
| 737 | 5105 | ||
| 5106 | |||
| 738 | /* The non-logging version of message. */ | 5107 | /* The non-logging version of message. */ |
| 5108 | |||
| 739 | void | 5109 | void |
| 740 | message_nolog (m, a1, a2, a3) | 5110 | message_nolog (m, a1, a2, a3) |
| 741 | char *m; | 5111 | char *m; |
| @@ -748,204 +5118,341 @@ message_nolog (m, a1, a2, a3) | |||
| 748 | Vmessage_log_max = old_log_max; | 5118 | Vmessage_log_max = old_log_max; |
| 749 | } | 5119 | } |
| 750 | 5120 | ||
| 5121 | |||
| 5122 | /* Display echo_area_message or echo_area_glyphs in the current | ||
| 5123 | mini-buffer. */ | ||
| 5124 | |||
| 751 | void | 5125 | void |
| 752 | update_echo_area () | 5126 | update_echo_area () |
| 753 | { | 5127 | { |
| 754 | message2 (echo_area_glyphs, echo_area_glyphs_length, | 5128 | if (STRINGP (echo_area_message)) |
| 755 | ! NILP (current_buffer->enable_multibyte_characters)); | 5129 | message3 (echo_area_message, echo_area_glyphs_length, |
| 5130 | !NILP (current_buffer->enable_multibyte_characters)); | ||
| 5131 | else | ||
| 5132 | message2 (echo_area_glyphs, echo_area_glyphs_length, | ||
| 5133 | !NILP (current_buffer->enable_multibyte_characters)); | ||
| 756 | } | 5134 | } |
| 757 | 5135 | ||
| 5136 | |||
| 5137 | /* Redisplay the echo area of selected_frame. If UPDATE_FRAME_P is | ||
| 5138 | non-zero update selected_frame. */ | ||
| 5139 | |||
| 758 | static void | 5140 | static void |
| 759 | echo_area_display () | 5141 | echo_area_display (update_frame_p) |
| 5142 | int update_frame_p; | ||
| 760 | { | 5143 | { |
| 761 | register int vpos; | ||
| 762 | FRAME_PTR f; | ||
| 763 | Lisp_Object mini_window; | 5144 | Lisp_Object mini_window; |
| 5145 | struct window *w; | ||
| 5146 | struct frame *f; | ||
| 764 | 5147 | ||
| 765 | /* Choose the minibuffer window for this display. | ||
| 766 | It is the minibuffer window used by the selected frame. */ | ||
| 767 | mini_window = FRAME_MINIBUF_WINDOW (selected_frame); | 5148 | mini_window = FRAME_MINIBUF_WINDOW (selected_frame); |
| 768 | /* This is the frame that window is in. */ | 5149 | w = XWINDOW (mini_window); |
| 769 | f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window))); | 5150 | f = XFRAME (WINDOW_FRAME (w)); |
| 5151 | |||
| 5152 | /* Don't display if frame is invisible or not yet initialized. */ | ||
| 5153 | if (!FRAME_VISIBLE_P (f) | ||
| 5154 | || !f->glyphs_initialized_p) | ||
| 5155 | return; | ||
| 770 | 5156 | ||
| 771 | if (! FRAME_VISIBLE_P (f)) | 5157 | /* When Emacs starts, selected_frame may be a visible terminal |
| 5158 | frame, even if we run under a window system. If we let this | ||
| 5159 | through, a message would be displayed on the terminal. */ | ||
| 5160 | #ifdef HAVE_WINDOW_SYSTEM | ||
| 5161 | if (!inhibit_window_system && !FRAME_WINDOW_P (selected_frame)) | ||
| 772 | return; | 5162 | return; |
| 5163 | #endif /* HAVE_WINDOW_SYSTEM */ | ||
| 773 | 5164 | ||
| 5165 | /* Redraw garbaged frames. */ | ||
| 774 | if (frame_garbaged) | 5166 | if (frame_garbaged) |
| 775 | { | 5167 | { |
| 776 | redraw_garbaged_frames (); | 5168 | /* Old redisplay called redraw_garbaged_frames here which in |
| 5169 | turn called redraw_frame which in turn called clear_frame. | ||
| 5170 | The call to clear_frame is a source of flickering. After | ||
| 5171 | checking the places where SET_FRAME_GARBAGED is called, I | ||
| 5172 | believe a clear_frame is not necessary. It should suffice in | ||
| 5173 | the new redisplay to invalidate all current matrices, and | ||
| 5174 | ensure a complete redisplay of all windows. */ | ||
| 5175 | Lisp_Object tail, frame; | ||
| 5176 | |||
| 5177 | FOR_EACH_FRAME (tail, frame) | ||
| 5178 | { | ||
| 5179 | struct frame *f = XFRAME (frame); | ||
| 5180 | |||
| 5181 | if (FRAME_VISIBLE_P (f) && FRAME_GARBAGED_P (f)) | ||
| 5182 | { | ||
| 5183 | clear_current_matrices (f); | ||
| 5184 | f->garbaged = 0; | ||
| 5185 | } | ||
| 5186 | } | ||
| 5187 | |||
| 777 | frame_garbaged = 0; | 5188 | frame_garbaged = 0; |
| 5189 | ++windows_or_buffers_changed; | ||
| 778 | } | 5190 | } |
| 779 | 5191 | ||
| 780 | if (echo_area_glyphs || minibuf_level == 0) | 5192 | if (echo_area_glyphs |
| 5193 | || STRINGP (echo_area_message) | ||
| 5194 | || minibuf_level == 0) | ||
| 781 | { | 5195 | { |
| 782 | int i; | 5196 | struct it it; |
| 783 | 5197 | ||
| 784 | echo_area_window = mini_window; | 5198 | echo_area_window = mini_window; |
| 5199 | clear_glyph_matrix (w->desired_matrix); | ||
| 5200 | init_iterator (&it, w, -1, -1, w->desired_matrix->rows, DEFAULT_FACE_ID); | ||
| 5201 | |||
| 5202 | if (STRINGP (echo_area_message) | ||
| 5203 | && echo_area_glyphs_length) | ||
| 5204 | { | ||
| 5205 | prepare_desired_row (it.glyph_row); | ||
| 5206 | display_string (NULL, echo_area_message, Qnil, 0, 0, | ||
| 5207 | &it, -1, echo_area_glyphs_length, 0, | ||
| 5208 | message_enable_multibyte); | ||
| 5209 | it.glyph_row->truncated_on_right_p = 0; | ||
| 5210 | compute_line_metrics (&it); | ||
| 5211 | } | ||
| 5212 | else if (echo_area_glyphs | ||
| 5213 | && echo_area_glyphs_length) | ||
| 5214 | { | ||
| 5215 | prepare_desired_row (it.glyph_row); | ||
| 5216 | display_string (echo_area_glyphs, Qnil, Qnil, 0, 0, &it, | ||
| 5217 | -1, echo_area_glyphs_length, 0, | ||
| 5218 | message_enable_multibyte); | ||
| 5219 | it.glyph_row->truncated_on_right_p = 0; | ||
| 5220 | compute_line_metrics (&it); | ||
| 5221 | } | ||
| 5222 | else | ||
| 5223 | blank_row (w, it.glyph_row, 0); | ||
| 5224 | |||
| 5225 | it.glyph_row->y = it.current_y; | ||
| 5226 | it.current_y += it.glyph_row->height; | ||
| 785 | 5227 | ||
| 786 | vpos = XFASTINT (XWINDOW (mini_window)->top); | 5228 | /* Clear the rest of the lines. */ |
| 787 | get_display_line (f, vpos, 0); | 5229 | while (it.current_y < it.last_visible_y) |
| 788 | 5230 | { | |
| 789 | /* Make sure the columns that overlap a left-hand scroll bar | 5231 | ++it.glyph_row; |
| 790 | are always clear. */ | 5232 | blank_row (w, it.glyph_row, it.current_y); |
| 791 | for (i = 0; i < FRAME_LEFT_SCROLL_BAR_WIDTH (f); i++) | 5233 | it.current_y += it.glyph_row->height; |
| 792 | f->desired_glyphs->glyphs[vpos][i] = SPACEGLYPH; | 5234 | } |
| 793 | |||
| 794 | display_string (XWINDOW (mini_window), vpos, | ||
| 795 | echo_area_glyphs ? echo_area_glyphs : "", | ||
| 796 | echo_area_glyphs ? echo_area_glyphs_length : -1, | ||
| 797 | FRAME_LEFT_SCROLL_BAR_WIDTH (f), | ||
| 798 | 0, 0, 0, | ||
| 799 | FRAME_WIDTH (f) + FRAME_LEFT_SCROLL_BAR_WIDTH (f), | ||
| 800 | message_enable_multibyte); | ||
| 801 | |||
| 802 | #if 0 /* This just gets in the way. update_frame does the job. */ | ||
| 803 | /* If desired cursor location is on this line, put it at end of text */ | ||
| 804 | if (cursor_in_echo_area) | ||
| 805 | FRAME_CURSOR_Y (f) = vpos; | ||
| 806 | if (FRAME_CURSOR_Y (f) == vpos) | ||
| 807 | FRAME_CURSOR_X (f) = FRAME_DESIRED_GLYPHS (f)->used[vpos]; | ||
| 808 | #endif | ||
| 809 | |||
| 810 | /* Fill the rest of the minibuffer window with blank lines. */ | ||
| 811 | { | ||
| 812 | int i; | ||
| 813 | 5235 | ||
| 814 | for (i = vpos + 1; | 5236 | w->must_be_updated_p = 1; |
| 815 | i < vpos + XFASTINT (XWINDOW (mini_window)->height); i++) | 5237 | if (update_frame_p) |
| 816 | { | 5238 | { |
| 817 | get_display_line (f, i, 0); | 5239 | /* Calling update_single_window is faster when we can use |
| 818 | /* We don't use FRAME_SCROLL_BAR_WIDTH (f) as the starting | 5240 | window-based redisplay. */ |
| 819 | hpos, because it is good to clear whatever is behind the | 5241 | if (FRAME_WINDOW_P (f)) |
| 820 | scroll bar. This does not affect the scroll bar itself. */ | 5242 | { |
| 821 | display_string (XWINDOW (mini_window), i, | 5243 | update_single_window (w, 1); |
| 822 | "", 0, | 5244 | rif->flush_display (f); |
| 823 | 0, 0, 0, | 5245 | } |
| 824 | 0, FRAME_WIDTH (f) + FRAME_SCROLL_BAR_WIDTH (f), | 5246 | else |
| 825 | 0); | 5247 | update_frame (f, 1, 1); |
| 826 | } | 5248 | } |
| 827 | } | ||
| 828 | } | 5249 | } |
| 829 | else if (!EQ (mini_window, selected_window)) | 5250 | else if (!EQ (mini_window, selected_window)) |
| 830 | windows_or_buffers_changed++; | 5251 | windows_or_buffers_changed++; |
| 831 | 5252 | ||
| 5253 | /* Prevent redisplay optimization in redisplay_internal by resetting | ||
| 5254 | this_line_start_pos. This is done because the mini-buffer now | ||
| 5255 | displays the message instead of its buffer text. */ | ||
| 832 | if (EQ (mini_window, selected_window)) | 5256 | if (EQ (mini_window, selected_window)) |
| 833 | this_line_bufpos = 0; | 5257 | CHARPOS (this_line_start_pos) = 0; |
| 834 | 5258 | ||
| 835 | previous_echo_glyphs = echo_area_glyphs; | 5259 | previous_echo_glyphs = echo_area_glyphs; |
| 5260 | previous_echo_area_message = echo_area_message; | ||
| 5261 | previous_echo_glyphs_length = echo_area_glyphs_length; | ||
| 836 | } | 5262 | } |
| 5263 | |||
| 5264 | |||
| 837 | 5265 | ||
| 838 | /* Update frame titles. */ | 5266 | /*********************************************************************** |
| 5267 | Frame Titles | ||
| 5268 | ***********************************************************************/ | ||
| 5269 | |||
| 839 | 5270 | ||
| 840 | #ifdef HAVE_WINDOW_SYSTEM | 5271 | #ifdef HAVE_WINDOW_SYSTEM |
| 841 | static char frame_title_buf[512]; | 5272 | |
| 5273 | /* A buffer for constructing frame titles in it; allocated from the | ||
| 5274 | heap in init_xdisp and resized as needed in store_frame_title_char. */ | ||
| 5275 | |||
| 5276 | static char *frame_title_buf; | ||
| 5277 | |||
| 5278 | /* The buffer's end, and a current output position in it. */ | ||
| 5279 | |||
| 5280 | static char *frame_title_buf_end; | ||
| 842 | static char *frame_title_ptr; | 5281 | static char *frame_title_ptr; |
| 843 | 5282 | ||
| 5283 | |||
| 5284 | /* Store a single character C for the frame title in frame_title_buf. | ||
| 5285 | Re-allocate frame_title_buf if necessary. */ | ||
| 5286 | |||
| 5287 | static void | ||
| 5288 | store_frame_title_char (c) | ||
| 5289 | char c; | ||
| 5290 | { | ||
| 5291 | /* If output position has reached the end of the allocated buffer, | ||
| 5292 | double the buffer's size. */ | ||
| 5293 | if (frame_title_ptr == frame_title_buf_end) | ||
| 5294 | { | ||
| 5295 | int len = frame_title_ptr - frame_title_buf; | ||
| 5296 | int new_size = 2 * len * sizeof *frame_title_buf; | ||
| 5297 | frame_title_buf = (char *) xrealloc (frame_title_buf, new_size); | ||
| 5298 | frame_title_buf_end = frame_title_buf + new_size; | ||
| 5299 | frame_title_ptr = frame_title_buf + len; | ||
| 5300 | } | ||
| 5301 | |||
| 5302 | *frame_title_ptr++ = c; | ||
| 5303 | } | ||
| 5304 | |||
| 5305 | |||
| 5306 | /* Store part of a frame title in frame_title_buf, beginning at | ||
| 5307 | frame_title_ptr. STR is the string to store. Do not copy more | ||
| 5308 | than PRECISION number of bytes from STR; PRECISION <= 0 means copy | ||
| 5309 | the whole string. Pad with spaces until FIELD_WIDTH number of | ||
| 5310 | characters have been copied; FIELD_WIDTH <= 0 means don't pad. | ||
| 5311 | Called from display_mode_element when it is used to build a frame | ||
| 5312 | title. */ | ||
| 5313 | |||
| 844 | static int | 5314 | static int |
| 845 | store_frame_title (str, mincol, maxcol) | 5315 | store_frame_title (str, field_width, precision) |
| 846 | char *str; | 5316 | unsigned char *str; |
| 847 | int mincol, maxcol; | 5317 | int field_width, precision; |
| 848 | { | 5318 | { |
| 849 | char *limit; | 5319 | int n = 0; |
| 850 | if (maxcol < 0 || maxcol >= sizeof(frame_title_buf)) | 5320 | |
| 851 | maxcol = sizeof (frame_title_buf); | 5321 | /* Copy at most PRECISION chars from STR. */ |
| 852 | limit = &frame_title_buf[maxcol]; | 5322 | while ((precision <= 0 || n < precision) |
| 853 | while (*str != '\0' && frame_title_ptr < limit) | 5323 | && *str) |
| 854 | *frame_title_ptr++ = *str++; | 5324 | { |
| 855 | while (frame_title_ptr < &frame_title_buf[mincol]) | 5325 | store_frame_title_char (*str++); |
| 856 | *frame_title_ptr++ = ' '; | 5326 | ++n; |
| 857 | return frame_title_ptr - frame_title_buf; | 5327 | } |
| 5328 | |||
| 5329 | /* Fill up with spaces until FIELD_WIDTH reached. */ | ||
| 5330 | while (field_width > 0 | ||
| 5331 | && n < field_width) | ||
| 5332 | { | ||
| 5333 | store_frame_title_char (' '); | ||
| 5334 | ++n; | ||
| 5335 | } | ||
| 5336 | |||
| 5337 | return n; | ||
| 858 | } | 5338 | } |
| 859 | 5339 | ||
| 5340 | |||
| 5341 | /* Set the title of FRAME, if it has changed. The title format is | ||
| 5342 | Vicon_title_format if FRAME is iconified, otherwise it is | ||
| 5343 | frame_title_format. */ | ||
| 5344 | |||
| 860 | static void | 5345 | static void |
| 861 | x_consider_frame_title (frame) | 5346 | x_consider_frame_title (frame) |
| 862 | Lisp_Object frame; | 5347 | Lisp_Object frame; |
| 863 | { | 5348 | { |
| 864 | Lisp_Object fmt; | 5349 | struct frame *f = XFRAME (frame); |
| 865 | struct buffer *obuf; | ||
| 866 | int len; | ||
| 867 | FRAME_PTR f = XFRAME (frame); | ||
| 868 | 5350 | ||
| 869 | if (!(FRAME_WINDOW_P (f) || FRAME_MINIBUF_ONLY_P (f) || f->explicit_name)) | 5351 | if (FRAME_WINDOW_P (f) |
| 870 | return; | 5352 | || FRAME_MINIBUF_ONLY_P (f) |
| 5353 | || f->explicit_name) | ||
| 5354 | { | ||
| 5355 | /* Do we have more than one visible frame on this X display? */ | ||
| 5356 | Lisp_Object tail; | ||
| 5357 | Lisp_Object fmt; | ||
| 5358 | struct buffer *obuf; | ||
| 5359 | int len; | ||
| 5360 | struct it it; | ||
| 871 | 5361 | ||
| 872 | /* Do we have more than one visible frame on this X display? */ | 5362 | for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr) |
| 873 | { | 5363 | { |
| 874 | Lisp_Object tail; | 5364 | struct frame *tf = XFRAME (XCONS (tail)->car); |
| 875 | 5365 | ||
| 876 | for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr) | 5366 | if (tf != f |
| 877 | { | 5367 | && FRAME_KBOARD (tf) == FRAME_KBOARD (f) |
| 878 | FRAME_PTR tf = XFRAME (XCONS (tail)->car); | 5368 | && !FRAME_MINIBUF_ONLY_P (tf) |
| 5369 | && (FRAME_VISIBLE_P (tf) || FRAME_ICONIFIED_P (tf))) | ||
| 5370 | break; | ||
| 5371 | } | ||
| 879 | 5372 | ||
| 880 | if (tf != f && FRAME_KBOARD (tf) == FRAME_KBOARD (f) | 5373 | /* Set global variable indicating that multiple frames exist. */ |
| 881 | && !FRAME_MINIBUF_ONLY_P (tf) | 5374 | multiple_frames = CONSP (tail); |
| 882 | && (FRAME_VISIBLE_P (tf) || FRAME_ICONIFIED_P (tf))) | 5375 | |
| 883 | break; | 5376 | /* Switch to the buffer of selected window of the frame. Set up |
| 884 | } | 5377 | frame_title_ptr so that display_mode_element will output into it; |
| 5378 | then display the title. */ | ||
| 5379 | obuf = current_buffer; | ||
| 5380 | Fset_buffer (XWINDOW (f->selected_window)->buffer); | ||
| 5381 | fmt = FRAME_ICONIFIED_P (f) ? Vicon_title_format : Vframe_title_format; | ||
| 5382 | frame_title_ptr = frame_title_buf; | ||
| 5383 | init_iterator (&it, XWINDOW (f->selected_window), -1, -1, | ||
| 5384 | NULL, DEFAULT_FACE_ID); | ||
| 5385 | len = display_mode_element (&it, 0, -1, -1, fmt); | ||
| 5386 | frame_title_ptr = NULL; | ||
| 5387 | set_buffer_internal (obuf); | ||
| 5388 | |||
| 5389 | /* Set the title only if it's changed. This avoids consing in | ||
| 5390 | the common case where it hasn't. (If it turns out that we've | ||
| 5391 | already wasted too much time by walking through the list with | ||
| 5392 | display_mode_element, then we might need to optimize at a | ||
| 5393 | higher level than this.) */ | ||
| 5394 | if (! STRINGP (f->name) | ||
| 5395 | || STRING_BYTES (XSTRING (f->name)) != len | ||
| 5396 | || bcmp (frame_title_buf, XSTRING (f->name)->data, len) != 0) | ||
| 5397 | x_implicitly_set_name (f, make_string (frame_title_buf, len), Qnil); | ||
| 5398 | } | ||
| 5399 | } | ||
| 885 | 5400 | ||
| 886 | multiple_frames = CONSP (tail); | 5401 | #else /* not HAVE_WINDOW_SYSTEM */ |
| 887 | } | ||
| 888 | 5402 | ||
| 889 | obuf = current_buffer; | ||
| 890 | Fset_buffer (XWINDOW (f->selected_window)->buffer); | ||
| 891 | fmt = (FRAME_ICONIFIED_P (f) ? Vicon_title_format : Vframe_title_format); | ||
| 892 | frame_title_ptr = frame_title_buf; | ||
| 893 | len = display_mode_element (XWINDOW (f->selected_window), 0, 0, 0, | ||
| 894 | 0, sizeof (frame_title_buf), fmt); | ||
| 895 | frame_title_ptr = 0; | ||
| 896 | set_buffer_internal (obuf); | ||
| 897 | /* Set the name only if it's changed. This avoids consing | ||
| 898 | in the common case where it hasn't. (If it turns out that we've | ||
| 899 | already wasted too much time by walking through the list with | ||
| 900 | display_mode_element, then we might need to optimize at a higher | ||
| 901 | level than this.) */ | ||
| 902 | if (! STRINGP (f->name) || STRING_BYTES (XSTRING (f->name)) != len | ||
| 903 | || bcmp (frame_title_buf, XSTRING (f->name)->data, len) != 0) | ||
| 904 | x_implicitly_set_name (f, make_string (frame_title_buf, len), Qnil); | ||
| 905 | } | ||
| 906 | #else | ||
| 907 | #define frame_title_ptr ((char *)0) | 5403 | #define frame_title_ptr ((char *)0) |
| 908 | #define store_frame_title(str, mincol, maxcol) 0 | 5404 | #define store_frame_title(str, mincol, maxcol) 0 |
| 909 | #endif | 5405 | |
| 5406 | #endif /* not HAVE_WINDOW_SYSTEM */ | ||
| 5407 | |||
| 5408 | |||
| 5409 | |||
| 910 | 5410 | ||
| 911 | /* Prepare for redisplay by updating menu-bar item lists when appropriate. | 5411 | /*********************************************************************** |
| 912 | This can call eval. */ | 5412 | Menu Bars |
| 5413 | ***********************************************************************/ | ||
| 5414 | |||
| 5415 | |||
| 5416 | /* Prepare for redisplay by updating menu-bar item lists when | ||
| 5417 | appropriate. This can call eval. */ | ||
| 913 | 5418 | ||
| 914 | void | 5419 | void |
| 915 | prepare_menu_bars () | 5420 | prepare_menu_bars () |
| 916 | { | 5421 | { |
| 917 | register struct window *w = XWINDOW (selected_window); | ||
| 918 | int all_windows; | 5422 | int all_windows; |
| 919 | struct gcpro gcpro1, gcpro2; | 5423 | struct gcpro gcpro1, gcpro2; |
| 5424 | struct frame *f; | ||
| 5425 | struct frame *tooltip_frame; | ||
| 920 | 5426 | ||
| 921 | all_windows = (update_mode_lines || buffer_shared > 1 | 5427 | #ifdef HAVE_X_WINDOWS |
| 922 | || windows_or_buffers_changed); | 5428 | tooltip_frame = tip_frame; |
| 923 | 5429 | #else | |
| 924 | /* Update all frame titles based on their buffer names, etc. | 5430 | tooltip_frame = NULL; |
| 925 | We do this before the menu bars so that the buffer-menu | 5431 | #endif |
| 926 | will show the up-to-date frame titles. | ||
| 927 | 5432 | ||
| 928 | This used to be done after the menu bars, for a reason that | 5433 | /* Update all frame titles based on their buffer names, etc. We do |
| 929 | was stated as follows but which I do not understand: | 5434 | this before the menu bars so that the buffer-menu will show the |
| 930 | "We do this after the menu bars so that the frame will first | 5435 | up-to-date frame titles. */ |
| 931 | create its menu bar using the name `emacs' if no other name | ||
| 932 | has yet been specified." | ||
| 933 | I think that is no longer a concern. */ | ||
| 934 | #ifdef HAVE_WINDOW_SYSTEM | 5436 | #ifdef HAVE_WINDOW_SYSTEM |
| 935 | if (windows_or_buffers_changed || update_mode_lines) | 5437 | if (windows_or_buffers_changed || update_mode_lines) |
| 936 | { | 5438 | { |
| 937 | Lisp_Object tail, frame; | 5439 | Lisp_Object tail, frame; |
| 938 | 5440 | ||
| 939 | FOR_EACH_FRAME (tail, frame) | 5441 | FOR_EACH_FRAME (tail, frame) |
| 940 | if (FRAME_VISIBLE_P (XFRAME (frame)) | 5442 | { |
| 941 | || FRAME_ICONIFIED_P (XFRAME (frame))) | 5443 | f = XFRAME (frame); |
| 942 | x_consider_frame_title (frame); | 5444 | if (f != tooltip_frame |
| 5445 | && (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f))) | ||
| 5446 | x_consider_frame_title (frame); | ||
| 5447 | } | ||
| 943 | } | 5448 | } |
| 944 | #endif | 5449 | #endif /* HAVE_WINDOW_SYSTEM */ |
| 945 | 5450 | ||
| 946 | /* Update the menu bar item lists, if appropriate. | 5451 | /* Update the menu bar item lists, if appropriate. This has to be |
| 947 | This has to be done before any actual redisplay | 5452 | done before any actual redisplay or generation of display lines. */ |
| 948 | or generation of display lines. */ | 5453 | all_windows = (update_mode_lines |
| 5454 | || buffer_shared > 1 | ||
| 5455 | || windows_or_buffers_changed); | ||
| 949 | if (all_windows) | 5456 | if (all_windows) |
| 950 | { | 5457 | { |
| 951 | Lisp_Object tail, frame; | 5458 | Lisp_Object tail, frame; |
| @@ -955,65 +5462,823 @@ prepare_menu_bars () | |||
| 955 | 5462 | ||
| 956 | FOR_EACH_FRAME (tail, frame) | 5463 | FOR_EACH_FRAME (tail, frame) |
| 957 | { | 5464 | { |
| 958 | /* If a window on this frame changed size, | 5465 | f = XFRAME (frame); |
| 959 | report that to the user and clear the size-change flag. */ | 5466 | |
| 960 | if (FRAME_WINDOW_SIZES_CHANGED (XFRAME (frame))) | 5467 | /* Ignore tooltip frame. */ |
| 5468 | if (f == tooltip_frame) | ||
| 5469 | continue; | ||
| 5470 | |||
| 5471 | /* If a window on this frame changed size, report that to | ||
| 5472 | the user and clear the size-change flag. */ | ||
| 5473 | if (FRAME_WINDOW_SIZES_CHANGED (f)) | ||
| 961 | { | 5474 | { |
| 962 | Lisp_Object functions; | 5475 | Lisp_Object functions; |
| 963 | /* Clear flag first in case we get error below. */ | 5476 | |
| 964 | FRAME_WINDOW_SIZES_CHANGED (XFRAME (frame)) = 0; | 5477 | /* Clear flag first in case we get an error below. */ |
| 5478 | FRAME_WINDOW_SIZES_CHANGED (f) = 0; | ||
| 965 | functions = Vwindow_size_change_functions; | 5479 | functions = Vwindow_size_change_functions; |
| 966 | GCPRO2 (tail, functions); | 5480 | GCPRO2 (tail, functions); |
| 5481 | |||
| 967 | while (CONSP (functions)) | 5482 | while (CONSP (functions)) |
| 968 | { | 5483 | { |
| 969 | call1 (XCONS (functions)->car, frame); | 5484 | call1 (XCAR (functions), frame); |
| 970 | functions = XCONS (functions)->cdr; | 5485 | functions = XCDR (functions); |
| 971 | } | 5486 | } |
| 972 | UNGCPRO; | 5487 | UNGCPRO; |
| 973 | } | 5488 | } |
| 5489 | |||
| 974 | GCPRO1 (tail); | 5490 | GCPRO1 (tail); |
| 975 | update_menu_bar (XFRAME (frame), 0); | 5491 | update_menu_bar (f, 0); |
| 5492 | #ifdef HAVE_WINDOW_SYSTEM | ||
| 5493 | update_toolbar (f, 0); | ||
| 5494 | #endif | ||
| 976 | UNGCPRO; | 5495 | UNGCPRO; |
| 977 | } | 5496 | } |
| 978 | 5497 | ||
| 979 | unbind_to (count, Qnil); | 5498 | unbind_to (count, Qnil); |
| 980 | } | 5499 | } |
| 981 | else | 5500 | else |
| 982 | update_menu_bar (selected_frame, 1); | 5501 | { |
| 5502 | update_menu_bar (selected_frame, 1); | ||
| 5503 | #ifdef HAVE_WINDOW_SYSTEM | ||
| 5504 | update_toolbar (selected_frame, 1); | ||
| 5505 | #endif | ||
| 5506 | } | ||
| 983 | 5507 | ||
| 984 | /* Motif needs this. See comment in xmenu.c. | 5508 | /* Motif needs this. See comment in xmenu.c. Turn it off when |
| 985 | Turn it off when pending_menu_activation is not defined. */ | 5509 | pending_menu_activation is not defined. */ |
| 986 | #ifdef USE_X_TOOLKIT | 5510 | #ifdef USE_X_TOOLKIT |
| 987 | pending_menu_activation = 0; | 5511 | pending_menu_activation = 0; |
| 988 | #endif | 5512 | #endif |
| 989 | } | 5513 | } |
| 5514 | |||
| 5515 | |||
| 5516 | /* Update the menu bar item list for frame F. This has to be done | ||
| 5517 | before we start to fill in any display lines, because it can call | ||
| 5518 | eval. | ||
| 5519 | |||
| 5520 | If SAVE_MATCH_DATA is non-zero, we must save and restore it here. */ | ||
| 5521 | |||
| 5522 | static void | ||
| 5523 | update_menu_bar (f, save_match_data) | ||
| 5524 | struct frame *f; | ||
| 5525 | int save_match_data; | ||
| 5526 | { | ||
| 5527 | Lisp_Object window; | ||
| 5528 | register struct window *w; | ||
| 5529 | |||
| 5530 | window = FRAME_SELECTED_WINDOW (f); | ||
| 5531 | w = XWINDOW (window); | ||
| 5532 | |||
| 5533 | if (update_mode_lines) | ||
| 5534 | w->update_mode_line = Qt; | ||
| 5535 | |||
| 5536 | if (FRAME_WINDOW_P (f) | ||
| 5537 | ? | ||
| 5538 | #if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) | ||
| 5539 | FRAME_EXTERNAL_MENU_BAR (f) | ||
| 5540 | #else | ||
| 5541 | FRAME_MENU_BAR_LINES (f) > 0 | ||
| 5542 | #endif | ||
| 5543 | : FRAME_MENU_BAR_LINES (f) > 0) | ||
| 5544 | { | ||
| 5545 | /* If the user has switched buffers or windows, we need to | ||
| 5546 | recompute to reflect the new bindings. But we'll | ||
| 5547 | recompute when update_mode_lines is set too; that means | ||
| 5548 | that people can use force-mode-line-update to request | ||
| 5549 | that the menu bar be recomputed. The adverse effect on | ||
| 5550 | the rest of the redisplay algorithm is about the same as | ||
| 5551 | windows_or_buffers_changed anyway. */ | ||
| 5552 | if (windows_or_buffers_changed | ||
| 5553 | || !NILP (w->update_mode_line) | ||
| 5554 | || ((BUF_SAVE_MODIFF (XBUFFER (w->buffer)) | ||
| 5555 | < BUF_MODIFF (XBUFFER (w->buffer))) | ||
| 5556 | != !NILP (w->last_had_star)) | ||
| 5557 | || ((!NILP (Vtransient_mark_mode) | ||
| 5558 | && !NILP (XBUFFER (w->buffer)->mark_active)) | ||
| 5559 | != !NILP (w->region_showing))) | ||
| 5560 | { | ||
| 5561 | struct buffer *prev = current_buffer; | ||
| 5562 | int count = specpdl_ptr - specpdl; | ||
| 5563 | |||
| 5564 | set_buffer_internal_1 (XBUFFER (w->buffer)); | ||
| 5565 | if (save_match_data) | ||
| 5566 | record_unwind_protect (Fset_match_data, Fmatch_data (Qnil, Qnil)); | ||
| 5567 | if (NILP (Voverriding_local_map_menu_flag)) | ||
| 5568 | { | ||
| 5569 | specbind (Qoverriding_terminal_local_map, Qnil); | ||
| 5570 | specbind (Qoverriding_local_map, Qnil); | ||
| 5571 | } | ||
| 5572 | |||
| 5573 | /* Run the Lucid hook. */ | ||
| 5574 | call1 (Vrun_hooks, Qactivate_menubar_hook); | ||
| 5575 | |||
| 5576 | /* If it has changed current-menubar from previous value, | ||
| 5577 | really recompute the menu-bar from the value. */ | ||
| 5578 | if (! NILP (Vlucid_menu_bar_dirty_flag)) | ||
| 5579 | call0 (Qrecompute_lucid_menubar); | ||
| 5580 | |||
| 5581 | safe_run_hooks (Qmenu_bar_update_hook); | ||
| 5582 | FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f)); | ||
| 5583 | |||
| 5584 | /* Redisplay the menu bar in case we changed it. */ | ||
| 5585 | #if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) | ||
| 5586 | if (FRAME_WINDOW_P (f)) | ||
| 5587 | set_frame_menubar (f, 0, 0); | ||
| 5588 | else | ||
| 5589 | /* On a terminal screen, the menu bar is an ordinary screen | ||
| 5590 | line, and this makes it get updated. */ | ||
| 5591 | w->update_mode_line = Qt; | ||
| 5592 | #else /* ! (USE_X_TOOLKIT || HAVE_NTGUI) */ | ||
| 5593 | /* In the non-toolkit version, the menu bar is an ordinary screen | ||
| 5594 | line, and this makes it get updated. */ | ||
| 5595 | w->update_mode_line = Qt; | ||
| 5596 | #endif /* ! (USE_X_TOOLKIT || HAVE_NTGUI) */ | ||
| 5597 | |||
| 5598 | unbind_to (count, Qnil); | ||
| 5599 | set_buffer_internal_1 (prev); | ||
| 5600 | } | ||
| 5601 | } | ||
| 5602 | } | ||
| 5603 | |||
| 5604 | |||
| 5605 | |||
| 5606 | /*********************************************************************** | ||
| 5607 | Toolbars | ||
| 5608 | ***********************************************************************/ | ||
| 5609 | |||
| 5610 | #ifdef HAVE_WINDOW_SYSTEM | ||
| 5611 | |||
| 5612 | /* Update the toolbar item list for frame F. This has to be done | ||
| 5613 | before we start to fill in any display lines. Called from | ||
| 5614 | prepare_menu_bars. If SAVE_MATCH_DATA is non-zero, we must save | ||
| 5615 | and restore it here. */ | ||
| 5616 | |||
| 5617 | static void | ||
| 5618 | update_toolbar (f, save_match_data) | ||
| 5619 | struct frame *f; | ||
| 5620 | int save_match_data; | ||
| 5621 | { | ||
| 5622 | if (WINDOWP (f->toolbar_window) | ||
| 5623 | && XFASTINT (XWINDOW (f->toolbar_window)->height) > 0) | ||
| 5624 | { | ||
| 5625 | Lisp_Object window; | ||
| 5626 | struct window *w; | ||
| 5627 | |||
| 5628 | window = FRAME_SELECTED_WINDOW (f); | ||
| 5629 | w = XWINDOW (window); | ||
| 5630 | |||
| 5631 | /* If the user has switched buffers or windows, we need to | ||
| 5632 | recompute to reflect the new bindings. But we'll | ||
| 5633 | recompute when update_mode_lines is set too; that means | ||
| 5634 | that people can use force-mode-line-update to request | ||
| 5635 | that the menu bar be recomputed. The adverse effect on | ||
| 5636 | the rest of the redisplay algorithm is about the same as | ||
| 5637 | windows_or_buffers_changed anyway. */ | ||
| 5638 | if (windows_or_buffers_changed | ||
| 5639 | || !NILP (w->update_mode_line) | ||
| 5640 | || ((BUF_SAVE_MODIFF (XBUFFER (w->buffer)) | ||
| 5641 | < BUF_MODIFF (XBUFFER (w->buffer))) | ||
| 5642 | != !NILP (w->last_had_star)) | ||
| 5643 | || ((!NILP (Vtransient_mark_mode) | ||
| 5644 | && !NILP (XBUFFER (w->buffer)->mark_active)) | ||
| 5645 | != !NILP (w->region_showing))) | ||
| 5646 | { | ||
| 5647 | struct buffer *prev = current_buffer; | ||
| 5648 | int count = specpdl_ptr - specpdl; | ||
| 5649 | |||
| 5650 | /* Set current_buffer to the buffer of the selected | ||
| 5651 | window of the frame, so that we get the right local | ||
| 5652 | keymaps. */ | ||
| 5653 | set_buffer_internal_1 (XBUFFER (w->buffer)); | ||
| 5654 | |||
| 5655 | /* Save match data, if we must. */ | ||
| 5656 | if (save_match_data) | ||
| 5657 | record_unwind_protect (Fset_match_data, Fmatch_data (Qnil, Qnil)); | ||
| 5658 | |||
| 5659 | /* Make sure that we don't accidentally use bogus keymaps. */ | ||
| 5660 | if (NILP (Voverriding_local_map_menu_flag)) | ||
| 5661 | { | ||
| 5662 | specbind (Qoverriding_terminal_local_map, Qnil); | ||
| 5663 | specbind (Qoverriding_local_map, Qnil); | ||
| 5664 | } | ||
| 5665 | |||
| 5666 | /* Build desired toolbar items from keymaps. */ | ||
| 5667 | f->desired_toolbar_items | ||
| 5668 | = toolbar_items (f->desired_toolbar_items, | ||
| 5669 | &f->n_desired_toolbar_items); | ||
| 5670 | |||
| 5671 | /* Redisplay the toolbar in case we changed it. */ | ||
| 5672 | w->update_mode_line = Qt; | ||
| 5673 | |||
| 5674 | unbind_to (count, Qnil); | ||
| 5675 | set_buffer_internal_1 (prev); | ||
| 5676 | } | ||
| 5677 | } | ||
| 5678 | } | ||
| 5679 | |||
| 5680 | |||
| 5681 | /* Set F->desired_toolbar_string to a Lisp string representing frame | ||
| 5682 | F's desired toolbar contents. F->desired_toolbar_items must have | ||
| 5683 | been set up previously by calling prepare_menu_bars. */ | ||
| 5684 | |||
| 5685 | static void | ||
| 5686 | build_desired_toolbar_string (f) | ||
| 5687 | struct frame *f; | ||
| 5688 | { | ||
| 5689 | int i, size, size_needed, string_idx; | ||
| 5690 | struct gcpro gcpro1, gcpro2, gcpro3; | ||
| 5691 | Lisp_Object image, plist, props; | ||
| 5692 | |||
| 5693 | image = plist = props = Qnil; | ||
| 5694 | GCPRO3 (image, plist, props); | ||
| 5695 | |||
| 5696 | /* Prepare F->desired_toolbar_string. If we can reuse it, do so. | ||
| 5697 | Otherwise, make a new string. */ | ||
| 5698 | |||
| 5699 | /* The size of the string we might be able to reuse. */ | ||
| 5700 | size = (STRINGP (f->desired_toolbar_string) | ||
| 5701 | ? XSTRING (f->desired_toolbar_string)->size | ||
| 5702 | : 0); | ||
| 5703 | |||
| 5704 | /* Each image in the string we build is preceded by a space, | ||
| 5705 | and there is a space at the end. */ | ||
| 5706 | size_needed = f->n_desired_toolbar_items + 1; | ||
| 5707 | |||
| 5708 | /* Reuse f->desired_toolbar_string, if possible. */ | ||
| 5709 | if (size < size_needed) | ||
| 5710 | f->desired_toolbar_string = Fmake_string (make_number (size_needed), ' '); | ||
| 5711 | else | ||
| 5712 | { | ||
| 5713 | props = list4 (Qdisplay, Qnil, Qmenu_item, Qnil); | ||
| 5714 | Fremove_text_properties (make_number (0), make_number (size), | ||
| 5715 | props, f->desired_toolbar_string); | ||
| 5716 | } | ||
| 5717 | |||
| 5718 | /* Put a `display' property on the string for the images to display, | ||
| 5719 | put a `menu_item' property on toolbar items with a value that | ||
| 5720 | is the index of the item in F's toolbar item vector. */ | ||
| 5721 | for (i = 0, string_idx = 0; | ||
| 5722 | i < f->n_desired_toolbar_items; | ||
| 5723 | ++i, string_idx += 1) | ||
| 5724 | { | ||
| 5725 | #define PROP(IDX) \ | ||
| 5726 | (XVECTOR (f->desired_toolbar_items) \ | ||
| 5727 | ->contents[i * TOOLBAR_ITEM_NSLOTS + (IDX)]) | ||
| 5728 | |||
| 5729 | int enabled_p = !NILP (PROP (TOOLBAR_ITEM_ENABLED_P)); | ||
| 5730 | int selected_p = !NILP (PROP (TOOLBAR_ITEM_SELECTED_P)); | ||
| 5731 | int margin, relief; | ||
| 5732 | extern Lisp_Object QCrelief, QCmargin, QCalgorithm, Qimage; | ||
| 5733 | extern Lisp_Object Qlaplace; | ||
| 5734 | |||
| 5735 | /* If image is a vector, choose the image according to the | ||
| 5736 | button state. */ | ||
| 5737 | image = PROP (TOOLBAR_ITEM_IMAGES); | ||
| 5738 | if (VECTORP (image)) | ||
| 5739 | { | ||
| 5740 | enum toolbar_item_image idx; | ||
| 5741 | |||
| 5742 | if (enabled_p) | ||
| 5743 | idx = (selected_p | ||
| 5744 | ? TOOLBAR_IMAGE_ENABLED_SELECTED | ||
| 5745 | : TOOLBAR_IMAGE_ENABLED_DESELECTED); | ||
| 5746 | else | ||
| 5747 | idx = (selected_p | ||
| 5748 | ? TOOLBAR_IMAGE_DISABLED_SELECTED | ||
| 5749 | : TOOLBAR_IMAGE_DISABLED_DESELECTED); | ||
| 5750 | |||
| 5751 | xassert (XVECTOR (image)->size >= idx); | ||
| 5752 | image = XVECTOR (image)->contents[idx]; | ||
| 5753 | } | ||
| 5754 | |||
| 5755 | /* Ignore invalid image specifications. */ | ||
| 5756 | if (!valid_image_p (image)) | ||
| 5757 | continue; | ||
| 5758 | |||
| 5759 | /* Display the toolbar button pressed, or depressed. */ | ||
| 5760 | plist = Fcopy_sequence (XCDR (image)); | ||
| 5761 | |||
| 5762 | /* Compute margin and relief to draw. */ | ||
| 5763 | relief = toolbar_button_relief > 0 ? toolbar_button_relief : 3; | ||
| 5764 | margin = relief + max (0, toolbar_button_margin); | ||
| 5765 | |||
| 5766 | if (auto_raise_toolbar_buttons_p) | ||
| 5767 | { | ||
| 5768 | /* Add a `:relief' property to the image spec if the item is | ||
| 5769 | selected. */ | ||
| 5770 | if (selected_p) | ||
| 5771 | { | ||
| 5772 | plist = Fplist_put (plist, QCrelief, make_number (-relief)); | ||
| 5773 | margin -= relief; | ||
| 5774 | } | ||
| 5775 | } | ||
| 5776 | else | ||
| 5777 | { | ||
| 5778 | /* If image is selected, display it pressed, i.e. with a | ||
| 5779 | negative relief. If it's not selected, display it with a | ||
| 5780 | raised relief. */ | ||
| 5781 | plist = Fplist_put (plist, QCrelief, | ||
| 5782 | (selected_p | ||
| 5783 | ? make_number (-relief) | ||
| 5784 | : make_number (relief))); | ||
| 5785 | margin -= relief; | ||
| 5786 | } | ||
| 5787 | |||
| 5788 | /* Put a margin around the image. */ | ||
| 5789 | if (margin) | ||
| 5790 | plist = Fplist_put (plist, QCmargin, make_number (margin)); | ||
| 5791 | |||
| 5792 | /* If button is not enabled, make the image appear disabled by | ||
| 5793 | applying an appropriate algorithm to it. */ | ||
| 5794 | if (!enabled_p) | ||
| 5795 | plist = Fplist_put (plist, QCalgorithm, Qlaplace); | ||
| 5796 | |||
| 5797 | /* Put a `display' text property on the string for the image to | ||
| 5798 | display. Put a `menu-item' property on the string that gives | ||
| 5799 | the start of this item's properties in the toolbar items | ||
| 5800 | vector. */ | ||
| 5801 | image = Fcons (Qimage, plist); | ||
| 5802 | props = list4 (Qdisplay, image, | ||
| 5803 | Qmenu_item, make_number (i * TOOLBAR_ITEM_NSLOTS)), | ||
| 5804 | Fadd_text_properties (make_number (string_idx), | ||
| 5805 | make_number (string_idx + 1), | ||
| 5806 | props, f->desired_toolbar_string); | ||
| 5807 | #undef PROP | ||
| 5808 | } | ||
| 5809 | |||
| 5810 | UNGCPRO; | ||
| 5811 | } | ||
| 5812 | |||
| 5813 | |||
| 5814 | /* Display one line of the toolbar of frame IT->f. */ | ||
| 5815 | |||
| 5816 | static void | ||
| 5817 | display_toolbar_line (it) | ||
| 5818 | struct it *it; | ||
| 5819 | { | ||
| 5820 | struct glyph_row *row = it->glyph_row; | ||
| 5821 | int max_x = it->last_visible_x; | ||
| 5822 | struct glyph *last; | ||
| 5823 | |||
| 5824 | prepare_desired_row (row); | ||
| 5825 | row->y = it->current_y; | ||
| 5826 | |||
| 5827 | while (it->current_x < max_x) | ||
| 5828 | { | ||
| 5829 | int x_before, x, n_glyphs_before, i, nglyphs; | ||
| 5830 | |||
| 5831 | /* Get the next display element. */ | ||
| 5832 | if (!get_next_display_element (it)) | ||
| 5833 | break; | ||
| 5834 | |||
| 5835 | /* Produce glyphs. */ | ||
| 5836 | x_before = it->current_x; | ||
| 5837 | n_glyphs_before = it->glyph_row->used[TEXT_AREA]; | ||
| 5838 | PRODUCE_GLYPHS (it); | ||
| 5839 | |||
| 5840 | nglyphs = it->glyph_row->used[TEXT_AREA] - n_glyphs_before; | ||
| 5841 | i = 0; | ||
| 5842 | x = x_before; | ||
| 5843 | while (i < nglyphs) | ||
| 5844 | { | ||
| 5845 | struct glyph *glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i; | ||
| 5846 | |||
| 5847 | if (x + glyph->pixel_width > max_x) | ||
| 5848 | { | ||
| 5849 | /* Glyph doesn't fit on line. */ | ||
| 5850 | it->glyph_row->used[TEXT_AREA] = n_glyphs_before + i; | ||
| 5851 | it->current_x = x; | ||
| 5852 | goto out; | ||
| 5853 | } | ||
| 5854 | |||
| 5855 | ++it->hpos; | ||
| 5856 | x += glyph->pixel_width; | ||
| 5857 | ++i; | ||
| 5858 | } | ||
| 5859 | |||
| 5860 | /* Stop at line ends. */ | ||
| 5861 | if (ITERATOR_AT_END_OF_LINE_P (it)) | ||
| 5862 | break; | ||
| 5863 | |||
| 5864 | set_iterator_to_next (it); | ||
| 5865 | } | ||
| 5866 | |||
| 5867 | out:; | ||
| 5868 | |||
| 5869 | row->displays_text_p = row->used[TEXT_AREA] != 0; | ||
| 5870 | extend_face_to_end_of_line (it); | ||
| 5871 | last = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1; | ||
| 5872 | last->right_box_line_p = 1; | ||
| 5873 | compute_line_metrics (it); | ||
| 5874 | |||
| 5875 | /* If line is empty, make it occupy the rest of the toolbar. */ | ||
| 5876 | if (!row->displays_text_p) | ||
| 5877 | { | ||
| 5878 | row->height = it->last_visible_y - row->y; | ||
| 5879 | row->ascent = 0; | ||
| 5880 | } | ||
| 5881 | |||
| 5882 | row->full_width_p = 1; | ||
| 5883 | row->continued_p = 0; | ||
| 5884 | row->truncated_on_left_p = 0; | ||
| 5885 | row->truncated_on_right_p = 0; | ||
| 5886 | |||
| 5887 | it->current_x = it->hpos = 0; | ||
| 5888 | it->current_y += row->height; | ||
| 5889 | ++it->vpos; | ||
| 5890 | ++it->glyph_row; | ||
| 5891 | } | ||
| 5892 | |||
| 5893 | |||
| 5894 | /* Value is the number of screen lines needed to make all toolbar | ||
| 5895 | items of frame F visible. */ | ||
| 5896 | |||
| 5897 | static int | ||
| 5898 | toolbar_lines_needed (f) | ||
| 5899 | struct frame *f; | ||
| 5900 | { | ||
| 5901 | struct window *w = XWINDOW (f->toolbar_window); | ||
| 5902 | struct it it; | ||
| 5903 | |||
| 5904 | /* Initialize an iterator for iteration over F->desired_toolbar_string | ||
| 5905 | in the toolbar window of frame F. */ | ||
| 5906 | init_iterator (&it, w, -1, -1, w->desired_matrix->rows, TOOLBAR_FACE_ID); | ||
| 5907 | it.first_visible_x = 0; | ||
| 5908 | it.last_visible_x = FRAME_WINDOW_WIDTH (f) * CANON_X_UNIT (f); | ||
| 5909 | reseat_to_string (&it, NULL, f->desired_toolbar_string, 0, 0, 0, -1); | ||
| 5910 | |||
| 5911 | while (!ITERATOR_AT_END_P (&it)) | ||
| 5912 | { | ||
| 5913 | it.glyph_row = w->desired_matrix->rows; | ||
| 5914 | clear_glyph_row (it.glyph_row); | ||
| 5915 | display_toolbar_line (&it); | ||
| 5916 | } | ||
| 5917 | |||
| 5918 | return (it.current_y + CANON_Y_UNIT (f) - 1) / CANON_Y_UNIT (f); | ||
| 5919 | } | ||
| 5920 | |||
| 5921 | |||
| 5922 | /* Display the toolbar of frame F. Value is non-zero if toolbar's | ||
| 5923 | height should be changed. */ | ||
| 5924 | |||
| 5925 | static int | ||
| 5926 | redisplay_toolbar (f) | ||
| 5927 | struct frame *f; | ||
| 5928 | { | ||
| 5929 | struct window *w; | ||
| 5930 | struct it it; | ||
| 5931 | struct glyph_row *row; | ||
| 5932 | int change_height_p = 0; | ||
| 5933 | |||
| 5934 | /* If frame hasn't a toolbar window or if it is zero-height, don't | ||
| 5935 | do anything. This means you must start with toolbar-lines | ||
| 5936 | non-zero to get the auto-sizing effect. Or in other words, you | ||
| 5937 | can turn off toolbars by specifying toolbar-lines zero. */ | ||
| 5938 | if (!WINDOWP (f->toolbar_window) | ||
| 5939 | || (w = XWINDOW (f->toolbar_window), | ||
| 5940 | XFASTINT (w->height) == 0)) | ||
| 5941 | return 0; | ||
| 5942 | |||
| 5943 | /* Set up an iterator for the toolbar window. */ | ||
| 5944 | init_iterator (&it, w, -1, -1, w->desired_matrix->rows, TOOLBAR_FACE_ID); | ||
| 5945 | it.first_visible_x = 0; | ||
| 5946 | it.last_visible_x = FRAME_WINDOW_WIDTH (f) * CANON_X_UNIT (f); | ||
| 5947 | row = it.glyph_row; | ||
| 5948 | |||
| 5949 | /* Build a string that represents the contents of the toolbar. */ | ||
| 5950 | build_desired_toolbar_string (f); | ||
| 5951 | reseat_to_string (&it, NULL, f->desired_toolbar_string, 0, 0, 0, -1); | ||
| 5952 | |||
| 5953 | /* Display as many lines as needed to display all toolbar items. */ | ||
| 5954 | while (it.current_y < it.last_visible_y) | ||
| 5955 | display_toolbar_line (&it); | ||
| 5956 | |||
| 5957 | /* It doesn't make much sense to try scrolling in the toolbar | ||
| 5958 | window, so don't do it. */ | ||
| 5959 | w->desired_matrix->no_scrolling_p = 1; | ||
| 5960 | w->must_be_updated_p = 1; | ||
| 5961 | |||
| 5962 | if (auto_resize_toolbars_p) | ||
| 5963 | { | ||
| 5964 | int nlines; | ||
| 5965 | |||
| 5966 | /* If there are blank lines at the end, except for a partially | ||
| 5967 | visible blank line at the end that is smaller than | ||
| 5968 | CANON_Y_UNIT, change the toolbar's height. */ | ||
| 5969 | row = it.glyph_row - 1; | ||
| 5970 | if (!row->displays_text_p | ||
| 5971 | && row->height >= CANON_Y_UNIT (f)) | ||
| 5972 | change_height_p = 1; | ||
| 5973 | |||
| 5974 | /* If row displays toolbar items, but is partially visible, | ||
| 5975 | change the toolbar's height. */ | ||
| 5976 | if (row->displays_text_p | ||
| 5977 | && MATRIX_ROW_BOTTOM_Y (row) > it.last_visible_y) | ||
| 5978 | change_height_p = 1; | ||
| 5979 | |||
| 5980 | /* Resize windows as needed by changing the `toolbar-lines' | ||
| 5981 | frame parameter. */ | ||
| 5982 | if (change_height_p | ||
| 5983 | && (nlines = toolbar_lines_needed (f), | ||
| 5984 | nlines != XFASTINT (w->height))) | ||
| 5985 | { | ||
| 5986 | extern Lisp_Object Qtoolbar_lines; | ||
| 5987 | Lisp_Object frame; | ||
| 5988 | |||
| 5989 | XSETFRAME (frame, f); | ||
| 5990 | clear_glyph_matrix (w->desired_matrix); | ||
| 5991 | Fmodify_frame_parameters (frame, | ||
| 5992 | Fcons (Fcons (Qtoolbar_lines, | ||
| 5993 | make_number (nlines)), | ||
| 5994 | Qnil)); | ||
| 5995 | fonts_changed_p = 1; | ||
| 5996 | } | ||
| 5997 | } | ||
| 5998 | |||
| 5999 | return change_height_p; | ||
| 6000 | } | ||
| 6001 | |||
| 6002 | |||
| 6003 | /* Get information about the toolbar item which is displayed in GLYPH | ||
| 6004 | on frame F. Return in *PROP_IDX the index where toolbar item | ||
| 6005 | properties start in F->current_toolbar_items. Value is zero if | ||
| 6006 | GLYPH doesn't display a toolbar item. */ | ||
| 6007 | |||
| 6008 | int | ||
| 6009 | toolbar_item_info (f, glyph, prop_idx) | ||
| 6010 | struct frame *f; | ||
| 6011 | struct glyph *glyph; | ||
| 6012 | int *prop_idx; | ||
| 6013 | { | ||
| 6014 | Lisp_Object prop; | ||
| 6015 | int success_p; | ||
| 6016 | |||
| 6017 | /* Get the text property `menu-item' at pos. The value of that | ||
| 6018 | property is the start index of this item's properties in | ||
| 6019 | F->current_toolbar_items. */ | ||
| 6020 | prop = Fget_text_property (make_number (glyph->charpos), | ||
| 6021 | Qmenu_item, f->current_toolbar_string); | ||
| 6022 | if (INTEGERP (prop)) | ||
| 6023 | { | ||
| 6024 | *prop_idx = XINT (prop); | ||
| 6025 | success_p = 1; | ||
| 6026 | } | ||
| 6027 | else | ||
| 6028 | success_p = 0; | ||
| 6029 | |||
| 6030 | return success_p; | ||
| 6031 | } | ||
| 6032 | |||
| 6033 | #endif /* HAVE_WINDOW_SYSTEM */ | ||
| 6034 | |||
| 6035 | |||
| 6036 | |||
| 6037 | /************************************************************************ | ||
| 6038 | Horizontal scrolling | ||
| 6039 | ************************************************************************/ | ||
| 6040 | |||
| 6041 | static int hscroll_window_tree P_ ((Lisp_Object)); | ||
| 6042 | static int hscroll_windows P_ ((Lisp_Object)); | ||
| 6043 | |||
| 6044 | /* For all leaf windows in the window tree rooted at WINDOW, set their | ||
| 6045 | hscroll value so that PT is (i) visible in the window, and (ii) so | ||
| 6046 | that it is not within a certain margin at the window's left and | ||
| 6047 | right border. Value is non-zero if any window's hscroll has been | ||
| 6048 | changed. */ | ||
| 6049 | |||
| 6050 | static int | ||
| 6051 | hscroll_window_tree (window) | ||
| 6052 | Lisp_Object window; | ||
| 6053 | { | ||
| 6054 | int hscrolled_p = 0; | ||
| 6055 | |||
| 6056 | while (WINDOWP (window)) | ||
| 6057 | { | ||
| 6058 | struct window *w = XWINDOW (window); | ||
| 6059 | |||
| 6060 | if (WINDOWP (w->hchild)) | ||
| 6061 | hscrolled_p |= hscroll_window_tree (w->hchild); | ||
| 6062 | else if (WINDOWP (w->vchild)) | ||
| 6063 | hscrolled_p |= hscroll_window_tree (w->vchild); | ||
| 6064 | else if (w->cursor.vpos >= 0) | ||
| 6065 | { | ||
| 6066 | int hscroll_margin, text_area_x, text_area_y; | ||
| 6067 | int text_area_width, text_area_height; | ||
| 6068 | struct glyph_row *cursor_row = MATRIX_ROW (w->current_matrix, | ||
| 6069 | w->cursor.vpos); | ||
| 6070 | |||
| 6071 | window_box (w, TEXT_AREA, &text_area_x, &text_area_y, | ||
| 6072 | &text_area_width, &text_area_height); | ||
| 6073 | |||
| 6074 | /* Scroll when cursor is inside this scroll margin. */ | ||
| 6075 | hscroll_margin = 5 * CANON_X_UNIT (XFRAME (w->frame)); | ||
| 6076 | |||
| 6077 | if ((XFASTINT (w->hscroll) | ||
| 6078 | && w->cursor.x < hscroll_margin) | ||
| 6079 | || (cursor_row->truncated_on_right_p | ||
| 6080 | && (w->cursor.x > text_area_width - hscroll_margin))) | ||
| 6081 | { | ||
| 6082 | struct it it; | ||
| 6083 | int hscroll; | ||
| 6084 | struct buffer *saved_current_buffer; | ||
| 6085 | int pt; | ||
| 6086 | |||
| 6087 | /* Find point in a display of infinite width. */ | ||
| 6088 | saved_current_buffer = current_buffer; | ||
| 6089 | current_buffer = XBUFFER (w->buffer); | ||
| 6090 | |||
| 6091 | if (w == XWINDOW (selected_window)) | ||
| 6092 | pt = BUF_PT (current_buffer); | ||
| 6093 | else | ||
| 6094 | { | ||
| 6095 | pt = marker_position (w->pointm); | ||
| 6096 | pt = max (BEGV, pt); | ||
| 6097 | pt = min (ZV, pt); | ||
| 6098 | } | ||
| 6099 | |||
| 6100 | /* Move iterator to pt starting at cursor_row->start in | ||
| 6101 | a line with infinite width. */ | ||
| 6102 | init_to_row_start (&it, w, cursor_row); | ||
| 6103 | it.last_visible_x = INFINITY; | ||
| 6104 | move_it_in_display_line_to (&it, pt, -1, MOVE_TO_POS); | ||
| 6105 | current_buffer = saved_current_buffer; | ||
| 6106 | |||
| 6107 | /* Center cursor in window. */ | ||
| 6108 | hscroll = (max (0, it.current_x - text_area_width / 2) | ||
| 6109 | / CANON_X_UNIT (it.f)); | ||
| 6110 | |||
| 6111 | /* Don't call Fset_window_hscroll if value hasn't | ||
| 6112 | changed because it will prevent redisplay | ||
| 6113 | optimizations. */ | ||
| 6114 | if (XFASTINT (w->hscroll) != hscroll) | ||
| 6115 | { | ||
| 6116 | Fset_window_hscroll (window, make_number (hscroll)); | ||
| 6117 | hscrolled_p = 1; | ||
| 6118 | } | ||
| 6119 | } | ||
| 6120 | } | ||
| 6121 | |||
| 6122 | window = w->next; | ||
| 6123 | } | ||
| 6124 | |||
| 6125 | /* Value is non-zero if hscroll of any leaf window has been changed. */ | ||
| 6126 | return hscrolled_p; | ||
| 6127 | } | ||
| 6128 | |||
| 6129 | |||
| 6130 | /* Set hscroll so that cursor is visible and not inside horizontal | ||
| 6131 | scroll margins for all windows in the tree rooted at WINDOW. See | ||
| 6132 | also hscroll_window_tree above. Value is non-zero if any window's | ||
| 6133 | hscroll has been changed. If it has, desired matrices on the frame | ||
| 6134 | of WINDOW are cleared. */ | ||
| 6135 | |||
| 6136 | static int | ||
| 6137 | hscroll_windows (window) | ||
| 6138 | Lisp_Object window; | ||
| 6139 | { | ||
| 6140 | int hscrolled_p = hscroll_window_tree (window); | ||
| 6141 | if (hscrolled_p) | ||
| 6142 | clear_desired_matrices (XFRAME (WINDOW_FRAME (XWINDOW (window)))); | ||
| 6143 | return hscrolled_p; | ||
| 6144 | } | ||
| 6145 | |||
| 6146 | |||
| 990 | 6147 | ||
| 991 | /* Do a frame update, taking possible shortcuts into account. | 6148 | /************************************************************************ |
| 992 | This is the main external entry point for redisplay. | 6149 | Redisplay |
| 6150 | ************************************************************************/ | ||
| 6151 | |||
| 6152 | /* Variables holding some state of redisplay if GLYPH_DEBUG is defined | ||
| 6153 | to a non-zero value. This is sometimes handy to have in a debugger | ||
| 6154 | session. */ | ||
| 6155 | |||
| 6156 | #if GLYPH_DEBUG | ||
| 6157 | |||
| 6158 | /* Values of beg_unchanged and end_unchanged as of last call to | ||
| 6159 | try_window_id. */ | ||
| 993 | 6160 | ||
| 994 | If the last redisplay displayed an echo area message and that | 6161 | int debug_beg_unchanged, debug_end_unchanged; |
| 995 | message is no longer requested, we clear the echo area | 6162 | |
| 996 | or bring back the minibuffer if that is in use. | 6163 | /* First and last unchanged row for try_window_id. */ |
| 6164 | |||
| 6165 | int debug_first_unchanged_at_end_vpos; | ||
| 6166 | int debug_last_unchanged_at_beg_vpos; | ||
| 6167 | |||
| 6168 | /* Delta vpos and y. */ | ||
| 6169 | |||
| 6170 | int debug_dvpos, debug_dy; | ||
| 6171 | |||
| 6172 | /* Delta in characters and bytes for try_window_id. */ | ||
| 6173 | |||
| 6174 | int debug_delta, debug_delta_bytes; | ||
| 6175 | |||
| 6176 | /* Values of window_end_pos and window_end_vpos at the end of | ||
| 6177 | try_window_id. */ | ||
| 6178 | |||
| 6179 | int debug_end_pos, debug_end_vpos; | ||
| 6180 | |||
| 6181 | /* Append a string to W->desired_matrix->method. FMT is a printf | ||
| 6182 | format string. A1...A9 are a supplement for a variable-length | ||
| 6183 | argument list. If trace_redisplay_p is non-zero also printf the | ||
| 6184 | resulting string to stderr. */ | ||
| 6185 | |||
| 6186 | static void | ||
| 6187 | debug_method_add (w, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9) | ||
| 6188 | struct window *w; | ||
| 6189 | char *fmt; | ||
| 6190 | int a1, a2, a3, a4, a5, a6, a7, a8, a9; | ||
| 6191 | { | ||
| 6192 | char buffer[512]; | ||
| 6193 | char *method = w->desired_matrix->method; | ||
| 6194 | int len = strlen (method); | ||
| 6195 | int size = sizeof w->desired_matrix->method; | ||
| 6196 | int remaining = size - len - 1; | ||
| 6197 | |||
| 6198 | sprintf (buffer, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9); | ||
| 6199 | if (len && remaining) | ||
| 6200 | { | ||
| 6201 | method[len] = '|'; | ||
| 6202 | --remaining, ++len; | ||
| 6203 | } | ||
| 6204 | |||
| 6205 | strncpy (method + len, buffer, remaining); | ||
| 6206 | |||
| 6207 | if (trace_redisplay_p) | ||
| 6208 | fprintf (stderr, "%p (%s): %s\n", | ||
| 6209 | w, | ||
| 6210 | ((BUFFERP (w->buffer) | ||
| 6211 | && STRINGP (XBUFFER (w->buffer)->name)) | ||
| 6212 | ? (char *) XSTRING (XBUFFER (w->buffer)->name)->data | ||
| 6213 | : "no buffer"), | ||
| 6214 | buffer); | ||
| 6215 | } | ||
| 997 | 6216 | ||
| 998 | Do not call eval from within this function. | 6217 | #endif /* GLYPH_DEBUG */ |
| 999 | Calls to eval after the call to echo_area_display would confuse | ||
| 1000 | the display_line mechanism and would cause a crash. | ||
| 1001 | Calls to eval before that point will work most of the time, | ||
| 1002 | but can still lose, because this function | ||
| 1003 | can be called from signal handlers; with alarms set up; | ||
| 1004 | or with synchronous processes running. | ||
| 1005 | 6218 | ||
| 1006 | See Fcall_process; if you called it from here, it could be | ||
| 1007 | entered recursively. */ | ||
| 1008 | 6219 | ||
| 1009 | static int do_verify_charstarts; | 6220 | /* This counter is used to clear the face cache every once in a while |
| 6221 | in redisplay_internal. It is incremented for each redisplay. | ||
| 6222 | Every CLEAR_FACE_CACHE_COUNT full redisplays, the face cache is | ||
| 6223 | cleared. */ | ||
| 1010 | 6224 | ||
| 1011 | /* Counter is used to clear the face cache | 6225 | #define CLEAR_FACE_CACHE_COUNT 10000 |
| 1012 | no more than once ever 1000 redisplays. */ | ||
| 1013 | static int clear_face_cache_count; | 6226 | static int clear_face_cache_count; |
| 1014 | 6227 | ||
| 1015 | /* Record the previous terminal frame we displayed. */ | 6228 | /* Record the previous terminal frame we displayed. */ |
| 1016 | static FRAME_PTR previous_terminal_frame; | 6229 | |
| 6230 | static struct frame *previous_terminal_frame; | ||
| 6231 | |||
| 6232 | /* Non-zero while redisplay_internal is in progress. */ | ||
| 6233 | |||
| 6234 | int redisplaying_p; | ||
| 6235 | |||
| 6236 | |||
| 6237 | /* Value is non-zero if all changes in window W, which displays | ||
| 6238 | current_buffer, are in the text between START and END. START is a | ||
| 6239 | buffer position, END is given as a distance from Z. Used in | ||
| 6240 | redisplay_internal for display optimization. */ | ||
| 6241 | |||
| 6242 | static INLINE int | ||
| 6243 | text_outside_line_unchanged_p (w, start, end) | ||
| 6244 | struct window *w; | ||
| 6245 | int start, end; | ||
| 6246 | { | ||
| 6247 | int unchanged_p = 1; | ||
| 6248 | |||
| 6249 | /* If text or overlays have changed, see where. */ | ||
| 6250 | if (XFASTINT (w->last_modified) < MODIFF | ||
| 6251 | || XFASTINT (w->last_overlay_modified) < OVERLAY_MODIFF) | ||
| 6252 | { | ||
| 6253 | /* Gap in the line? */ | ||
| 6254 | if (GPT < start || Z - GPT < end) | ||
| 6255 | unchanged_p = 0; | ||
| 6256 | |||
| 6257 | /* Changes start in front of the line, or end after it? */ | ||
| 6258 | if (unchanged_p | ||
| 6259 | && (beg_unchanged < start - 1 | ||
| 6260 | || end_unchanged < end)) | ||
| 6261 | unchanged_p = 0; | ||
| 6262 | |||
| 6263 | /* If selective display, can't optimize if changes start at the | ||
| 6264 | beginning of the line. */ | ||
| 6265 | if (unchanged_p | ||
| 6266 | && INTEGERP (current_buffer->selective_display) | ||
| 6267 | && XINT (current_buffer->selective_display) > 0 | ||
| 6268 | && (beg_unchanged < start || GPT <= start)) | ||
| 6269 | unchanged_p = 0; | ||
| 6270 | } | ||
| 6271 | |||
| 6272 | return unchanged_p; | ||
| 6273 | } | ||
| 6274 | |||
| 6275 | |||
| 6276 | /* Do a frame update, taking possible shortcuts into account. This is | ||
| 6277 | the main external entry point for redisplay. | ||
| 6278 | |||
| 6279 | If the last redisplay displayed an echo area message and that message | ||
| 6280 | is no longer requested, we clear the echo area or bring back the | ||
| 6281 | mini-buffer if that is in use. */ | ||
| 1017 | 6282 | ||
| 1018 | void | 6283 | void |
| 1019 | redisplay () | 6284 | redisplay () |
| @@ -1021,52 +6286,84 @@ redisplay () | |||
| 1021 | redisplay_internal (0); | 6286 | redisplay_internal (0); |
| 1022 | } | 6287 | } |
| 1023 | 6288 | ||
| 1024 | /* If PRESERVE_ECHO_AREA is nonzero, it means this redisplay | 6289 | |
| 1025 | is not in response to any user action; therefore, we should | 6290 | /* If PRESERVE_ECHO_AREA is nonzero, it means this redisplay is not in |
| 1026 | preserve the echo area. (Actually, our caller does that job.) | 6291 | response to any user action; therefore, we should preserve the echo |
| 1027 | Perhaps in the future avoid recentering windows | 6292 | area. (Actually, our caller does that job.) Perhaps in the future |
| 1028 | if it is not necessary; currently that causes some problems. */ | 6293 | avoid recentering windows if it is not necessary; currently that |
| 6294 | causes some problems. */ | ||
| 1029 | 6295 | ||
| 1030 | static void | 6296 | static void |
| 1031 | redisplay_internal (preserve_echo_area) | 6297 | redisplay_internal (preserve_echo_area) |
| 1032 | int preserve_echo_area; | 6298 | int preserve_echo_area; |
| 1033 | { | 6299 | { |
| 1034 | register struct window *w = XWINDOW (selected_window); | 6300 | struct window *w = XWINDOW (selected_window); |
| 1035 | register int pause; | 6301 | struct frame *f = XFRAME (w->frame); |
| 6302 | int pause; | ||
| 1036 | int must_finish = 0; | 6303 | int must_finish = 0; |
| 1037 | int all_windows; | 6304 | struct text_pos tlbufpos, tlendpos; |
| 1038 | register int tlbufpos, tlendpos; | ||
| 1039 | struct position pos; | ||
| 1040 | int number_of_visible_frames; | 6305 | int number_of_visible_frames; |
| 1041 | 6306 | ||
| 1042 | if (noninteractive) | 6307 | /* Non-zero means redisplay has to consider all windows on all |
| 6308 | frames. Zero means, only selected_window is considered. */ | ||
| 6309 | int consider_all_windows_p; | ||
| 6310 | |||
| 6311 | TRACE ((stderr, "redisplay_internal %d\n", redisplaying_p)); | ||
| 6312 | |||
| 6313 | /* No redisplay if running in batch mode or frame is not yet fully | ||
| 6314 | initialized, or redisplay is explicitly turned off by setting | ||
| 6315 | Vinhibit_redisplay. */ | ||
| 6316 | if (noninteractive | ||
| 6317 | || !NILP (Vinhibit_redisplay) | ||
| 6318 | || !f->glyphs_initialized_p) | ||
| 1043 | return; | 6319 | return; |
| 1044 | 6320 | ||
| 6321 | /* The flag redisplay_performed_directly_p is set by | ||
| 6322 | direct_output_for_insert when it already did the whole screen | ||
| 6323 | update necessary. */ | ||
| 6324 | if (redisplay_performed_directly_p) | ||
| 6325 | { | ||
| 6326 | redisplay_performed_directly_p = 0; | ||
| 6327 | if (!hscroll_windows (selected_window)) | ||
| 6328 | return; | ||
| 6329 | } | ||
| 6330 | |||
| 1045 | #ifdef USE_X_TOOLKIT | 6331 | #ifdef USE_X_TOOLKIT |
| 1046 | if (popup_activated ()) | 6332 | if (popup_activated ()) |
| 1047 | return; | 6333 | return; |
| 1048 | #endif | 6334 | #endif |
| 1049 | 6335 | ||
| 1050 | if (! NILP (Vinhibit_redisplay)) | 6336 | if (redisplaying_p) |
| 1051 | return; | 6337 | return; |
| 6338 | ++redisplaying_p; | ||
| 1052 | 6339 | ||
| 1053 | retry: | 6340 | retry: |
| 1054 | 6341 | ||
| 6342 | /* If new fonts have been loaded that make a glyph matrix adjustment | ||
| 6343 | necessary, do it. */ | ||
| 6344 | if (fonts_changed_p) | ||
| 6345 | { | ||
| 6346 | adjust_glyphs (NULL); | ||
| 6347 | ++windows_or_buffers_changed; | ||
| 6348 | fonts_changed_p = 0; | ||
| 6349 | } | ||
| 6350 | |||
| 1055 | if (! FRAME_WINDOW_P (selected_frame) | 6351 | if (! FRAME_WINDOW_P (selected_frame) |
| 1056 | && previous_terminal_frame != selected_frame) | 6352 | && previous_terminal_frame != selected_frame) |
| 1057 | { | 6353 | { |
| 1058 | /* Since frames on an ASCII terminal share the same display area, | 6354 | /* Since frames on an ASCII terminal share the same display |
| 1059 | displaying a different frame means redisplay the whole thing. */ | 6355 | area, displaying a different frame means redisplay the whole |
| 6356 | thing. */ | ||
| 1060 | windows_or_buffers_changed++; | 6357 | windows_or_buffers_changed++; |
| 1061 | SET_FRAME_GARBAGED (selected_frame); | 6358 | SET_FRAME_GARBAGED (selected_frame); |
| 1062 | XSETFRAME (Vterminal_frame, selected_frame); | 6359 | XSETFRAME (Vterminal_frame, selected_frame); |
| 1063 | } | 6360 | } |
| 1064 | previous_terminal_frame = selected_frame; | 6361 | previous_terminal_frame = selected_frame; |
| 1065 | 6362 | ||
| 1066 | /* Set the visible flags for all frames. | 6363 | /* Set the visible flags for all frames. Do this before checking |
| 1067 | Do this before checking for resized or garbaged frames; they want | 6364 | for resized or garbaged frames; they want to know if their frames |
| 1068 | to know if their frames are visible. | 6365 | are visible. See the comment in frame.h for |
| 1069 | See the comment in frame.h for FRAME_SAMPLE_VISIBILITY. */ | 6366 | FRAME_SAMPLE_VISIBILITY. */ |
| 1070 | { | 6367 | { |
| 1071 | Lisp_Object tail, frame; | 6368 | Lisp_Object tail, frame; |
| 1072 | 6369 | ||
| @@ -1074,26 +6371,46 @@ redisplay_internal (preserve_echo_area) | |||
| 1074 | 6371 | ||
| 1075 | FOR_EACH_FRAME (tail, frame) | 6372 | FOR_EACH_FRAME (tail, frame) |
| 1076 | { | 6373 | { |
| 1077 | FRAME_SAMPLE_VISIBILITY (XFRAME (frame)); | 6374 | struct frame *f = XFRAME (frame); |
| 1078 | 6375 | ||
| 1079 | if (FRAME_VISIBLE_P (XFRAME (frame))) | 6376 | FRAME_SAMPLE_VISIBILITY (f); |
| 1080 | number_of_visible_frames++; | 6377 | if (FRAME_VISIBLE_P (f)) |
| 1081 | 6378 | ++number_of_visible_frames; | |
| 1082 | /* Clear out all the display lines in which we will generate the | 6379 | clear_desired_matrices (f); |
| 1083 | glyphs to display. */ | ||
| 1084 | init_desired_glyphs (XFRAME (frame)); | ||
| 1085 | } | 6380 | } |
| 1086 | } | 6381 | } |
| 1087 | 6382 | ||
| 1088 | /* Notice any pending interrupt request to change frame size. */ | 6383 | /* Notice any pending interrupt request to change frame size. */ |
| 1089 | do_pending_window_change (); | 6384 | do_pending_window_change (); |
| 1090 | 6385 | ||
| 6386 | /* Clear frames marked as garbaged. */ | ||
| 1091 | if (frame_garbaged) | 6387 | if (frame_garbaged) |
| 1092 | { | 6388 | { |
| 1093 | redraw_garbaged_frames (); | 6389 | /* Old redisplay called redraw_garbaged_frames here which in |
| 6390 | turn called redraw_frame which in turn called clear_frame. | ||
| 6391 | The call to clear_frame is a source of flickering. After | ||
| 6392 | checking the places where SET_FRAME_GARBAGED is called, I | ||
| 6393 | believe a clear_frame is not necessary. It should suffice in | ||
| 6394 | the new redisplay to invalidate all current matrices, and | ||
| 6395 | ensure a complete redisplay of all windows. */ | ||
| 6396 | Lisp_Object tail, frame; | ||
| 6397 | |||
| 6398 | FOR_EACH_FRAME (tail, frame) | ||
| 6399 | { | ||
| 6400 | struct frame *f = XFRAME (frame); | ||
| 6401 | |||
| 6402 | if (FRAME_VISIBLE_P (f) && FRAME_GARBAGED_P (f)) | ||
| 6403 | { | ||
| 6404 | clear_current_matrices (f); | ||
| 6405 | f->garbaged = 0; | ||
| 6406 | } | ||
| 6407 | } | ||
| 6408 | |||
| 1094 | frame_garbaged = 0; | 6409 | frame_garbaged = 0; |
| 6410 | ++windows_or_buffers_changed; | ||
| 1095 | } | 6411 | } |
| 1096 | 6412 | ||
| 6413 | /* Build menubar and toolbar items. */ | ||
| 1097 | prepare_menu_bars (); | 6414 | prepare_menu_bars (); |
| 1098 | 6415 | ||
| 1099 | if (windows_or_buffers_changed) | 6416 | if (windows_or_buffers_changed) |
| @@ -1107,7 +6424,7 @@ redisplay_internal (preserve_echo_area) | |||
| 1107 | update_mode_lines++; | 6424 | update_mode_lines++; |
| 1108 | } | 6425 | } |
| 1109 | 6426 | ||
| 1110 | /* If %c is in use, update it if needed. */ | 6427 | /* If %c is in the mode line, update it if needed. */ |
| 1111 | if (!NILP (w->column_number_displayed) | 6428 | if (!NILP (w->column_number_displayed) |
| 1112 | /* This alternative quickly identifies a common case | 6429 | /* This alternative quickly identifies a common case |
| 1113 | where no change is needed. */ | 6430 | where no change is needed. */ |
| @@ -1119,66 +6436,69 @@ redisplay_internal (preserve_echo_area) | |||
| 1119 | 6436 | ||
| 1120 | FRAME_SCROLL_BOTTOM_VPOS (XFRAME (w->frame)) = -1; | 6437 | FRAME_SCROLL_BOTTOM_VPOS (XFRAME (w->frame)) = -1; |
| 1121 | 6438 | ||
| 1122 | all_windows = update_mode_lines || buffer_shared > 1; | 6439 | /* The variable buffer_shared is set in redisplay_window and |
| 6440 | indicates that we redisplay a buffer in different windows. See | ||
| 6441 | there. */ | ||
| 6442 | consider_all_windows_p = update_mode_lines || buffer_shared > 1; | ||
| 1123 | 6443 | ||
| 1124 | /* If specs for an arrow have changed, do thorough redisplay | 6444 | /* If specs for an arrow have changed, do thorough redisplay |
| 1125 | to ensure we remove any arrow that should no longer exist. */ | 6445 | to ensure we remove any arrow that should no longer exist. */ |
| 1126 | if (! EQ (COERCE_MARKER (Voverlay_arrow_position), last_arrow_position) | 6446 | if (! EQ (COERCE_MARKER (Voverlay_arrow_position), last_arrow_position) |
| 1127 | || ! EQ (Voverlay_arrow_string, last_arrow_string)) | 6447 | || ! EQ (Voverlay_arrow_string, last_arrow_string)) |
| 1128 | all_windows = 1; | 6448 | consider_all_windows_p = windows_or_buffers_changed = 1; |
| 1129 | 6449 | ||
| 1130 | /* Normally the message* functions will have already displayed and | 6450 | /* Normally the message* functions will have already displayed and |
| 1131 | updated the echo area, but the frame may have been trashed, or | 6451 | updated the echo area, but the frame may have been trashed, or |
| 1132 | the update may have been preempted, so display the echo area | 6452 | the update may have been preempted, so display the echo area |
| 1133 | again here. */ | 6453 | again here. */ |
| 1134 | if (echo_area_glyphs || previous_echo_glyphs) | 6454 | if (echo_area_glyphs |
| 6455 | || STRINGP (echo_area_message) | ||
| 6456 | || previous_echo_glyphs | ||
| 6457 | || STRINGP (previous_echo_area_message)) | ||
| 1135 | { | 6458 | { |
| 1136 | echo_area_display (); | 6459 | echo_area_display (0); |
| 1137 | must_finish = 1; | 6460 | must_finish = 1; |
| 1138 | } | 6461 | } |
| 1139 | 6462 | ||
| 1140 | /* If showing region, and mark has changed, must redisplay whole window. */ | 6463 | /* If showing the region, and mark has changed, we must redisplay |
| 6464 | the whole window. The assignment to this_line_start_pos prevents | ||
| 6465 | the optimization directly below this if-statement. */ | ||
| 1141 | if (((!NILP (Vtransient_mark_mode) | 6466 | if (((!NILP (Vtransient_mark_mode) |
| 1142 | && !NILP (XBUFFER (w->buffer)->mark_active)) | 6467 | && !NILP (XBUFFER (w->buffer)->mark_active)) |
| 1143 | != !NILP (w->region_showing)) | 6468 | != !NILP (w->region_showing)) |
| 1144 | || (!NILP (w->region_showing) | 6469 | || (!NILP (w->region_showing) |
| 1145 | && !EQ (w->region_showing, | 6470 | && !EQ (w->region_showing, |
| 1146 | Fmarker_position (XBUFFER (w->buffer)->mark)))) | 6471 | Fmarker_position (XBUFFER (w->buffer)->mark)))) |
| 1147 | this_line_bufpos = -1; | 6472 | CHARPOS (this_line_start_pos) = 0; |
| 1148 | 6473 | ||
| 1149 | tlbufpos = this_line_bufpos; | 6474 | /* Optimize the case that only the line containing the cursor in the |
| 1150 | tlendpos = this_line_endpos; | 6475 | selected window has changed. Variables starting with this_ are |
| 1151 | if (!all_windows && tlbufpos > 0 && NILP (w->update_mode_line) | 6476 | set in display_line and record information about the line |
| 6477 | containing the cursor. */ | ||
| 6478 | tlbufpos = this_line_start_pos; | ||
| 6479 | tlendpos = this_line_end_pos; | ||
| 6480 | if (!consider_all_windows_p | ||
| 6481 | && CHARPOS (tlbufpos) > 0 | ||
| 6482 | && NILP (w->update_mode_line) | ||
| 1152 | && !current_buffer->clip_changed | 6483 | && !current_buffer->clip_changed |
| 1153 | && FRAME_VISIBLE_P (XFRAME (w->frame)) | 6484 | && FRAME_VISIBLE_P (XFRAME (w->frame)) |
| 1154 | && !FRAME_OBSCURED_P (XFRAME (w->frame)) | 6485 | && !FRAME_OBSCURED_P (XFRAME (w->frame)) |
| 1155 | /* Make sure recorded data applies to current buffer, etc */ | 6486 | /* Make sure recorded data applies to current buffer, etc. */ |
| 1156 | && this_line_buffer == current_buffer | 6487 | && this_line_buffer == current_buffer |
| 1157 | && current_buffer == XBUFFER (w->buffer) | 6488 | && current_buffer == XBUFFER (w->buffer) |
| 1158 | && NILP (w->force_start) | 6489 | && NILP (w->force_start) |
| 1159 | /* Point must be on the line that we have info recorded about */ | 6490 | /* Point must be on the line that we have info recorded about. */ |
| 1160 | && PT >= tlbufpos | 6491 | && PT >= CHARPOS (tlbufpos) |
| 1161 | && PT <= Z - tlendpos | 6492 | && PT <= Z - CHARPOS (tlendpos) |
| 1162 | /* All text outside that line, including its final newline, | 6493 | /* All text outside that line, including its final newline, |
| 1163 | must be unchanged */ | 6494 | must be unchanged */ |
| 1164 | && ((XFASTINT (w->last_modified) >= MODIFF | 6495 | && text_outside_line_unchanged_p (w, CHARPOS (tlbufpos), |
| 1165 | && (XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF)) | 6496 | CHARPOS (tlendpos))) |
| 1166 | || (beg_unchanged >= tlbufpos - 1 | 6497 | { |
| 1167 | && GPT >= tlbufpos | 6498 | if (CHARPOS (tlbufpos) > BEGV |
| 1168 | /* If selective display, can't optimize | 6499 | && FETCH_BYTE (BYTEPOS (tlbufpos) - 1) != '\n' |
| 1169 | if the changes start at the beginning of the line. */ | 6500 | && (CHARPOS (tlbufpos) == ZV |
| 1170 | && ((INTEGERP (current_buffer->selective_display) | 6501 | || FETCH_BYTE (BYTEPOS (tlbufpos)) == '\n')) |
| 1171 | && XINT (current_buffer->selective_display) > 0 | ||
| 1172 | ? (beg_unchanged >= tlbufpos | ||
| 1173 | && GPT > tlbufpos) | ||
| 1174 | : 1)) | ||
| 1175 | && end_unchanged >= tlendpos | ||
| 1176 | && Z - GPT >= tlendpos))) | ||
| 1177 | { | ||
| 1178 | int tlbufpos_byte = CHAR_TO_BYTE (tlbufpos); | ||
| 1179 | if (tlbufpos > BEGV && FETCH_BYTE (tlbufpos_byte - 1) != '\n' | ||
| 1180 | && (tlbufpos == ZV | ||
| 1181 | || FETCH_BYTE (tlbufpos_byte) == '\n')) | ||
| 1182 | /* Former continuation line has disappeared by becoming empty */ | 6502 | /* Former continuation line has disappeared by becoming empty */ |
| 1183 | goto cancel; | 6503 | goto cancel; |
| 1184 | else if (XFASTINT (w->last_modified) < MODIFF | 6504 | else if (XFASTINT (w->last_modified) < MODIFF |
| @@ -1199,76 +6519,115 @@ redisplay_internal (preserve_echo_area) | |||
| 1199 | 6519 | ||
| 1200 | As we have to redraw the line above, we should goto cancel. */ | 6520 | As we have to redraw the line above, we should goto cancel. */ |
| 1201 | 6521 | ||
| 1202 | struct position val; | 6522 | struct it it; |
| 1203 | int prevline; | 6523 | int line_height_before = this_line_pixel_height; |
| 1204 | int opoint = PT, opoint_byte = PT_BYTE; | 6524 | |
| 1205 | 6525 | /* Note that start_display will handle the case that the | |
| 1206 | scan_newline (tlbufpos, tlbufpos_byte, BEGV, BEGV_BYTE, -1, 1); | 6526 | line starting at tlbufpos is a continuation lines. */ |
| 1207 | 6527 | start_display (&it, w, tlbufpos); | |
| 1208 | val = *compute_motion (PT, 0, | 6528 | |
| 1209 | XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0, | 6529 | /* Implementation note: It this still necessary? */ |
| 1210 | 0, | 6530 | if (it.current_x != this_line_start_x) |
| 1211 | tlbufpos, | ||
| 1212 | 1 << (BITS_PER_SHORT - 1), | ||
| 1213 | 1 << (BITS_PER_SHORT - 1), | ||
| 1214 | window_internal_width (w) - 1, | ||
| 1215 | XINT (w->hscroll), 0, w); | ||
| 1216 | TEMP_SET_PT_BOTH (opoint, opoint_byte); | ||
| 1217 | if (val.hpos != this_line_start_hpos) | ||
| 1218 | goto cancel; | 6531 | goto cancel; |
| 1219 | 6532 | ||
| 1220 | cursor_vpos = -1; | 6533 | TRACE ((stderr, "trying display optimization 1\n")); |
| 6534 | w->cursor.vpos = -1; | ||
| 1221 | overlay_arrow_seen = 0; | 6535 | overlay_arrow_seen = 0; |
| 1222 | zv_strings_seen = 0; | 6536 | it.vpos = this_line_vpos; |
| 1223 | display_text_line (w, tlbufpos, tlbufpos_byte, | 6537 | it.current_y = this_line_y; |
| 1224 | this_line_vpos, this_line_start_hpos, | 6538 | it.glyph_row = MATRIX_ROW (w->desired_matrix, this_line_vpos); |
| 1225 | pos_tab_offset (w, tlbufpos, tlbufpos_byte), 0); | 6539 | display_line (&it); |
| 6540 | |||
| 1226 | /* If line contains point, is not continued, | 6541 | /* If line contains point, is not continued, |
| 1227 | and ends at same distance from eob as before, we win */ | 6542 | and ends at same distance from eob as before, we win */ |
| 1228 | if (cursor_vpos >= 0 && this_line_bufpos | 6543 | if (w->cursor.vpos >= 0 |
| 1229 | && this_line_endpos == tlendpos) | 6544 | /* Line is not continued, otherwise this_line_start_pos |
| 6545 | would have been set to 0 in display_line. */ | ||
| 6546 | && CHARPOS (this_line_start_pos) | ||
| 6547 | /* Line ends as before. */ | ||
| 6548 | && CHARPOS (this_line_end_pos) == CHARPOS (tlendpos) | ||
| 6549 | /* Line has same height as before. Otherwise other lines | ||
| 6550 | would have to be shifted up or down. */ | ||
| 6551 | && this_line_pixel_height == line_height_before) | ||
| 1230 | { | 6552 | { |
| 1231 | /* If this is not the window's last line, | 6553 | /* If this is not the window's last line, we must adjust |
| 1232 | we must adjust the charstarts of the lines below. */ | 6554 | the charstarts of the lines below. */ |
| 1233 | if (this_line_vpos + 1 | 6555 | if (it.current_y < it.last_visible_y) |
| 1234 | < XFASTINT (w->top) + window_internal_height (w)) | 6556 | { |
| 1235 | { | 6557 | struct glyph_row *row |
| 1236 | int left = WINDOW_LEFT_MARGIN (w); | 6558 | = MATRIX_ROW (w->current_matrix, this_line_vpos + 1); |
| 1237 | int *charstart_next_line | 6559 | int delta, delta_bytes; |
| 1238 | = FRAME_CURRENT_GLYPHS (XFRAME (WINDOW_FRAME (w)))->charstarts[this_line_vpos + 1]; | 6560 | |
| 1239 | int adjust; | 6561 | if (Z - CHARPOS (tlendpos) == ZV) |
| 1240 | 6562 | { | |
| 1241 | if (Z - tlendpos == ZV) | 6563 | /* This line ends at end of (accessible part of) |
| 1242 | /* This line ends at end of (accessible part of) buffer. | 6564 | buffer. There is no newline to count. */ |
| 1243 | There is no newline to count. */ | 6565 | delta = (Z |
| 1244 | adjust = Z - tlendpos - charstart_next_line[left]; | 6566 | - CHARPOS (tlendpos) |
| 1245 | else | 6567 | - MATRIX_ROW_START_CHARPOS (row)); |
| 1246 | /* This line ends in a newline. | 6568 | delta_bytes = (Z_BYTE |
| 1247 | Must take account of the newline and the rest of the | 6569 | - BYTEPOS (tlendpos) |
| 1248 | text that follows. */ | 6570 | - MATRIX_ROW_START_BYTEPOS (row)); |
| 1249 | adjust = Z - tlendpos + 1 - charstart_next_line[left]; | 6571 | } |
| 1250 | 6572 | else | |
| 1251 | adjust_window_charstarts (w, this_line_vpos, adjust); | 6573 | { |
| 6574 | /* This line ends in a newline. Must take | ||
| 6575 | account of the newline and the rest of the | ||
| 6576 | text that follows. */ | ||
| 6577 | delta = (Z | ||
| 6578 | - CHARPOS (tlendpos) | ||
| 6579 | - MATRIX_ROW_START_CHARPOS (row)); | ||
| 6580 | delta_bytes = (Z_BYTE | ||
| 6581 | - BYTEPOS (tlendpos) | ||
| 6582 | - MATRIX_ROW_START_BYTEPOS (row)); | ||
| 6583 | } | ||
| 6584 | |||
| 6585 | increment_glyph_matrix_buffer_positions (w->current_matrix, | ||
| 6586 | this_line_vpos + 1, | ||
| 6587 | w->current_matrix->nrows, | ||
| 6588 | delta, delta_bytes); | ||
| 1252 | } | 6589 | } |
| 1253 | 6590 | ||
| 1254 | if (!WINDOW_FULL_WIDTH_P (w)) | 6591 | /* If this row displays text now but previously didn't, |
| 1255 | preserve_other_columns (w); | 6592 | or vice versa, w->window_end_vpos may have to be |
| 6593 | adjusted. */ | ||
| 6594 | if ((it.glyph_row - 1)->displays_text_p) | ||
| 6595 | { | ||
| 6596 | if (XFASTINT (w->window_end_vpos) < this_line_vpos) | ||
| 6597 | XSETINT (w->window_end_vpos, this_line_vpos); | ||
| 6598 | } | ||
| 6599 | else if (XFASTINT (w->window_end_vpos) == this_line_vpos | ||
| 6600 | && this_line_vpos > 0) | ||
| 6601 | XSETINT (w->window_end_vpos, this_line_vpos - 1); | ||
| 6602 | w->window_end_valid = Qnil; | ||
| 6603 | |||
| 6604 | /* Update hint: No need to try to scroll in update_window. */ | ||
| 6605 | w->desired_matrix->no_scrolling_p = 1; | ||
| 6606 | |||
| 6607 | #if GLYPH_DEBUG | ||
| 6608 | *w->desired_matrix->method = 0; | ||
| 6609 | debug_method_add (w, "optimization 1"); | ||
| 6610 | #endif | ||
| 1256 | goto update; | 6611 | goto update; |
| 1257 | } | 6612 | } |
| 1258 | else | 6613 | else |
| 1259 | goto cancel; | 6614 | goto cancel; |
| 1260 | } | 6615 | } |
| 1261 | else if (PT == XFASTINT (w->last_point) | 6616 | else if (/* Cursor position hasn't changed. */ |
| 6617 | PT == XFASTINT (w->last_point) | ||
| 1262 | /* Make sure the cursor was last displayed | 6618 | /* Make sure the cursor was last displayed |
| 1263 | in this window. Otherwise we have to reposition it. */ | 6619 | in this window. Otherwise we have to reposition it. */ |
| 1264 | && XINT (w->top) <= FRAME_CURSOR_Y (selected_frame) | 6620 | && 0 <= w->cursor.vpos |
| 1265 | && (XINT (w->top) + XINT (w->height) | 6621 | && XINT (w->height) > w->cursor.vpos) |
| 1266 | > FRAME_CURSOR_Y (selected_frame))) | ||
| 1267 | { | 6622 | { |
| 1268 | if (!must_finish) | 6623 | if (!must_finish) |
| 1269 | { | 6624 | { |
| 1270 | do_pending_window_change (); | 6625 | do_pending_window_change (); |
| 1271 | return; | 6626 | |
| 6627 | /* We used to always goto end_of_redisplay here, but this | ||
| 6628 | isn't enough if we have a blinking cursor. */ | ||
| 6629 | if (w->cursor_off_p == w->last_cursor_off_p) | ||
| 6630 | goto end_of_redisplay; | ||
| 1272 | } | 6631 | } |
| 1273 | goto update; | 6632 | goto update; |
| 1274 | } | 6633 | } |
| @@ -1281,82 +6640,97 @@ redisplay_internal (preserve_echo_area) | |||
| 1281 | && NILP (w->region_showing) | 6640 | && NILP (w->region_showing) |
| 1282 | && !cursor_in_echo_area) | 6641 | && !cursor_in_echo_area) |
| 1283 | { | 6642 | { |
| 1284 | pos = *compute_motion (tlbufpos, 0, | 6643 | struct it it; |
| 1285 | XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0, | 6644 | struct glyph_row *row; |
| 1286 | 0, | 6645 | |
| 1287 | PT, 2, - (1 << (BITS_PER_SHORT - 1)), | 6646 | /* Skip from tlbufpos to PT and see where it is. Note that |
| 1288 | window_internal_width (w) - 1, | 6647 | PT may be in invisible text. If so, we will end at the |
| 1289 | XINT (w->hscroll), | 6648 | next visible position. */ |
| 1290 | pos_tab_offset (w, tlbufpos, tlbufpos_byte), | 6649 | init_iterator (&it, w, CHARPOS (tlbufpos), BYTEPOS (tlbufpos), |
| 1291 | w); | 6650 | NULL, DEFAULT_FACE_ID); |
| 1292 | if (pos.vpos < 1) | 6651 | it.current_x = this_line_start_x; |
| 6652 | it.current_y = this_line_y; | ||
| 6653 | it.vpos = this_line_vpos; | ||
| 6654 | |||
| 6655 | /* The call to move_it_to stops in front of PT, but | ||
| 6656 | moves over before-strings. */ | ||
| 6657 | move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS); | ||
| 6658 | |||
| 6659 | if (it.vpos == this_line_vpos | ||
| 6660 | && (row = MATRIX_ROW (w->current_matrix, this_line_vpos), | ||
| 6661 | row->enabled_p)) | ||
| 1293 | { | 6662 | { |
| 1294 | int width = window_internal_width (w) - 1; | 6663 | xassert (this_line_vpos == it.vpos); |
| 1295 | FRAME_CURSOR_X (selected_frame) | 6664 | xassert (this_line_y == it.current_y); |
| 1296 | = WINDOW_LEFT_MARGIN (w) + minmax (0, pos.hpos, width); | 6665 | set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0); |
| 1297 | FRAME_CURSOR_Y (selected_frame) = this_line_vpos; | ||
| 1298 | goto update; | 6666 | goto update; |
| 1299 | } | 6667 | } |
| 1300 | else | 6668 | else |
| 1301 | goto cancel; | 6669 | goto cancel; |
| 1302 | } | 6670 | } |
| 6671 | |||
| 1303 | cancel: | 6672 | cancel: |
| 1304 | /* Text changed drastically or point moved off of line */ | 6673 | /* Text changed drastically or point moved off of line. */ |
| 1305 | cancel_line (this_line_vpos, selected_frame); | 6674 | SET_MATRIX_ROW_ENABLED_P (w->desired_matrix, this_line_vpos, 0); |
| 1306 | } | 6675 | } |
| 1307 | 6676 | ||
| 1308 | this_line_bufpos = 0; | 6677 | CHARPOS (this_line_start_pos) = 0; |
| 1309 | all_windows |= buffer_shared > 1; | 6678 | consider_all_windows_p |= buffer_shared > 1; |
| 6679 | ++clear_face_cache_count; | ||
| 1310 | 6680 | ||
| 1311 | clear_face_cache_count++; | 6681 | |
| 6682 | /* Build desired matrices. If consider_all_windows_p is non-zero, | ||
| 6683 | do it for all windows on all frames. Otherwise do it for | ||
| 6684 | selected_window, only. */ | ||
| 1312 | 6685 | ||
| 1313 | if (all_windows) | 6686 | if (consider_all_windows_p) |
| 1314 | { | 6687 | { |
| 1315 | Lisp_Object tail, frame; | 6688 | Lisp_Object tail, frame; |
| 1316 | 6689 | ||
| 1317 | #ifdef HAVE_FACES | 6690 | /* Clear the face cache eventually. */ |
| 1318 | /* Clear the face cache, only when we do a full redisplay | 6691 | if (clear_face_cache_count > CLEAR_FACE_CACHE_COUNT) |
| 1319 | and not too often either. */ | ||
| 1320 | if (clear_face_cache_count > 1000) | ||
| 1321 | { | 6692 | { |
| 1322 | clear_face_cache (); | 6693 | clear_face_cache (0); |
| 1323 | clear_face_cache_count = 0; | 6694 | clear_face_cache_count = 0; |
| 1324 | } | 6695 | } |
| 1325 | #endif | ||
| 1326 | 6696 | ||
| 1327 | /* Recompute # windows showing selected buffer. | 6697 | /* Recompute # windows showing selected buffer. This will be |
| 1328 | This will be incremented each time such a window is displayed. */ | 6698 | incremented each time such a window is displayed. */ |
| 1329 | buffer_shared = 0; | 6699 | buffer_shared = 0; |
| 1330 | 6700 | ||
| 1331 | FOR_EACH_FRAME (tail, frame) | 6701 | FOR_EACH_FRAME (tail, frame) |
| 1332 | { | 6702 | { |
| 1333 | FRAME_PTR f = XFRAME (frame); | 6703 | struct frame *f = XFRAME (frame); |
| 1334 | if (FRAME_WINDOW_P (f) || f == selected_frame) | 6704 | if (FRAME_WINDOW_P (f) || f == selected_frame) |
| 1335 | { | 6705 | { |
| 1336 | 6706 | /* Mark all the scroll bars to be removed; we'll redeem | |
| 1337 | /* Mark all the scroll bars to be removed; we'll redeem the ones | 6707 | the ones we want when we redisplay their windows. */ |
| 1338 | we want when we redisplay their windows. */ | ||
| 1339 | if (condemn_scroll_bars_hook) | 6708 | if (condemn_scroll_bars_hook) |
| 1340 | (*condemn_scroll_bars_hook) (f); | 6709 | (*condemn_scroll_bars_hook) (f); |
| 1341 | 6710 | ||
| 1342 | if (FRAME_VISIBLE_P (f) && !FRAME_OBSCURED_P (f)) | 6711 | if (FRAME_VISIBLE_P (f) && !FRAME_OBSCURED_P (f)) |
| 1343 | redisplay_windows (FRAME_ROOT_WINDOW (f), preserve_echo_area); | 6712 | redisplay_windows (FRAME_ROOT_WINDOW (f)); |
| 1344 | 6713 | ||
| 1345 | /* Any scroll bars which redisplay_windows should have nuked | 6714 | /* Any scroll bars which redisplay_windows should have |
| 1346 | should now go away. */ | 6715 | nuked should now go away. */ |
| 1347 | if (judge_scroll_bars_hook) | 6716 | if (judge_scroll_bars_hook) |
| 1348 | (*judge_scroll_bars_hook) (f); | 6717 | (*judge_scroll_bars_hook) (f); |
| 1349 | } | 6718 | } |
| 1350 | } | 6719 | } |
| 1351 | } | 6720 | } |
| 1352 | else if (FRAME_VISIBLE_P (selected_frame) && !FRAME_OBSCURED_P (selected_frame)) | 6721 | else if (FRAME_VISIBLE_P (selected_frame) |
| 1353 | { | 6722 | && !FRAME_OBSCURED_P (selected_frame)) |
| 1354 | redisplay_window (selected_window, 1, preserve_echo_area); | 6723 | redisplay_window (selected_window, 1); |
| 1355 | if (!WINDOW_FULL_WIDTH_P (w)) | 6724 | |
| 1356 | preserve_other_columns (w); | 6725 | |
| 1357 | } | 6726 | /* Compare desired and current matrices, perform output. */ |
| 6727 | |||
| 6728 | update: | ||
| 6729 | |||
| 6730 | /* If fonts changed, display again. */ | ||
| 6731 | if (fonts_changed_p) | ||
| 6732 | goto retry; | ||
| 1358 | 6733 | ||
| 1359 | update: | ||
| 1360 | /* Prevent various kinds of signals during display update. | 6734 | /* Prevent various kinds of signals during display update. |
| 1361 | stdio is not robust about handling signals, | 6735 | stdio is not robust about handling signals, |
| 1362 | which can cause an apparent I/O error. */ | 6736 | which can cause an apparent I/O error. */ |
| @@ -1364,7 +6738,7 @@ update: | |||
| 1364 | unrequest_sigio (); | 6738 | unrequest_sigio (); |
| 1365 | stop_polling (); | 6739 | stop_polling (); |
| 1366 | 6740 | ||
| 1367 | if (all_windows) | 6741 | if (consider_all_windows_p) |
| 1368 | { | 6742 | { |
| 1369 | Lisp_Object tail; | 6743 | Lisp_Object tail; |
| 1370 | 6744 | ||
| @@ -1372,7 +6746,7 @@ update: | |||
| 1372 | 6746 | ||
| 1373 | for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr) | 6747 | for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr) |
| 1374 | { | 6748 | { |
| 1375 | FRAME_PTR f; | 6749 | struct frame *f; |
| 1376 | 6750 | ||
| 1377 | if (!FRAMEP (XCONS (tail)->car)) | 6751 | if (!FRAMEP (XCONS (tail)->car)) |
| 1378 | continue; | 6752 | continue; |
| @@ -1382,9 +6756,14 @@ update: | |||
| 1382 | if ((FRAME_WINDOW_P (f) || f == selected_frame) | 6756 | if ((FRAME_WINDOW_P (f) || f == selected_frame) |
| 1383 | && FRAME_VISIBLE_P (f) && !FRAME_OBSCURED_P (f)) | 6757 | && FRAME_VISIBLE_P (f) && !FRAME_OBSCURED_P (f)) |
| 1384 | { | 6758 | { |
| 6759 | /* Mark all windows as to be updated. */ | ||
| 6760 | set_window_update_flags (XWINDOW (f->root_window), 1); | ||
| 1385 | pause |= update_frame (f, 0, 0); | 6761 | pause |= update_frame (f, 0, 0); |
| 1386 | if (!pause) | 6762 | if (!pause) |
| 1387 | { | 6763 | { |
| 6764 | if (hscroll_windows (f->root_window)) | ||
| 6765 | goto retry; | ||
| 6766 | |||
| 1388 | mark_window_display_accurate (f->root_window, 1); | 6767 | mark_window_display_accurate (f->root_window, 1); |
| 1389 | if (frame_up_to_date_hook != 0) | 6768 | if (frame_up_to_date_hook != 0) |
| 1390 | (*frame_up_to_date_hook) (f); | 6769 | (*frame_up_to_date_hook) (f); |
| @@ -1394,8 +6773,14 @@ update: | |||
| 1394 | } | 6773 | } |
| 1395 | else | 6774 | else |
| 1396 | { | 6775 | { |
| 1397 | if (FRAME_VISIBLE_P (selected_frame) && !FRAME_OBSCURED_P (selected_frame)) | 6776 | if (FRAME_VISIBLE_P (selected_frame) |
| 1398 | pause = update_frame (selected_frame, 0, 0); | 6777 | && !FRAME_OBSCURED_P (selected_frame)) |
| 6778 | { | ||
| 6779 | XWINDOW (selected_window)->must_be_updated_p = 1; | ||
| 6780 | pause = update_frame (selected_frame, 0, 0); | ||
| 6781 | if (!pause && hscroll_windows (selected_window)) | ||
| 6782 | goto retry; | ||
| 6783 | } | ||
| 1399 | else | 6784 | else |
| 1400 | pause = 0; | 6785 | pause = 0; |
| 1401 | 6786 | ||
| @@ -1406,66 +6791,63 @@ update: | |||
| 1406 | it here. */ | 6791 | it here. */ |
| 1407 | { | 6792 | { |
| 1408 | Lisp_Object mini_window; | 6793 | Lisp_Object mini_window; |
| 1409 | FRAME_PTR mini_frame; | 6794 | struct frame *mini_frame; |
| 1410 | 6795 | ||
| 1411 | mini_window = FRAME_MINIBUF_WINDOW (selected_frame); | 6796 | mini_window = FRAME_MINIBUF_WINDOW (selected_frame); |
| 1412 | mini_frame = XFRAME (WINDOW_FRAME (XWINDOW (mini_window))); | 6797 | mini_frame = XFRAME (WINDOW_FRAME (XWINDOW (mini_window))); |
| 1413 | 6798 | ||
| 1414 | if (mini_frame != selected_frame && FRAME_WINDOW_P (mini_frame)) | 6799 | if (mini_frame != selected_frame && FRAME_WINDOW_P (mini_frame)) |
| 1415 | pause |= update_frame (mini_frame, 0, 0); | 6800 | { |
| 6801 | XWINDOW (mini_window)->must_be_updated_p = 1; | ||
| 6802 | pause |= update_frame (mini_frame, 0, 0); | ||
| 6803 | if (!pause && hscroll_windows (mini_window)) | ||
| 6804 | goto retry; | ||
| 6805 | } | ||
| 1416 | } | 6806 | } |
| 1417 | } | 6807 | } |
| 1418 | 6808 | ||
| 1419 | /* If frame does not match, prevent doing single-line-update next time. | 6809 | /* If display was paused because of pending input, make sure we do a |
| 1420 | Also, don't forget to check every line to update the arrow. */ | 6810 | thorough update the next time. */ |
| 1421 | if (pause) | 6811 | if (pause) |
| 1422 | { | 6812 | { |
| 1423 | this_line_bufpos = 0; | 6813 | /* Prevent the optimization at the beginning of |
| 6814 | redisplay_internal that tries a single-line update of the | ||
| 6815 | line containing the cursor in the selected window. */ | ||
| 6816 | CHARPOS (this_line_start_pos) = 0; | ||
| 6817 | |||
| 6818 | /* Let the overlay arrow be updated the next time. */ | ||
| 1424 | if (!NILP (last_arrow_position)) | 6819 | if (!NILP (last_arrow_position)) |
| 1425 | { | 6820 | { |
| 1426 | last_arrow_position = Qt; | 6821 | last_arrow_position = Qt; |
| 1427 | last_arrow_string = Qt; | 6822 | last_arrow_string = Qt; |
| 1428 | } | 6823 | } |
| 1429 | /* If we pause after scrolling, some lines in current_frame | 6824 | |
| 1430 | may be null, so preserve_other_columns won't be able to | 6825 | /* If we pause after scrolling, some rows in the current |
| 1431 | preserve all the vertical-bar separators. So, avoid using it | 6826 | matrices of some windows are not valid. */ |
| 1432 | in that case. */ | 6827 | if (!WINDOW_FULL_WIDTH_P (w) |
| 1433 | if (!WINDOW_FULL_WIDTH_P (w)) | 6828 | && !FRAME_WINDOW_P (XFRAME (w->frame))) |
| 1434 | update_mode_lines = 1; | 6829 | update_mode_lines = 1; |
| 1435 | } | 6830 | } |
| 1436 | 6831 | ||
| 1437 | /* Now text on frame agrees with windows, so | 6832 | /* Now text on frame agrees with windows, so put info into the |
| 1438 | put info into the windows for partial redisplay to follow */ | 6833 | windows for partial redisplay to follow. */ |
| 1439 | |||
| 1440 | if (!pause) | 6834 | if (!pause) |
| 1441 | { | 6835 | { |
| 1442 | register struct buffer *b = XBUFFER (w->buffer); | 6836 | register struct buffer *b = XBUFFER (w->buffer); |
| 1443 | 6837 | ||
| 1444 | blank_end_of_window = 0; | ||
| 1445 | unchanged_modified = BUF_MODIFF (b); | 6838 | unchanged_modified = BUF_MODIFF (b); |
| 1446 | overlay_unchanged_modified = BUF_OVERLAY_MODIFF (b); | 6839 | overlay_unchanged_modified = BUF_OVERLAY_MODIFF (b); |
| 1447 | beg_unchanged = BUF_GPT (b) - BUF_BEG (b); | 6840 | beg_unchanged = BUF_GPT (b) - BUF_BEG (b); |
| 1448 | end_unchanged = BUF_Z (b) - BUF_GPT (b); | 6841 | end_unchanged = BUF_Z (b) - BUF_GPT (b); |
| 1449 | 6842 | ||
| 1450 | /* Record the last place cursor was displayed in this window. | 6843 | if (consider_all_windows_p) |
| 1451 | But not if cursor is in the echo area, because in that case | ||
| 1452 | FRAME_CURSOR_X and FRAME_CURSOR_Y are in the echo area. */ | ||
| 1453 | if (!(cursor_in_echo_area && FRAME_HAS_MINIBUF_P (selected_frame) | ||
| 1454 | && EQ (FRAME_MINIBUF_WINDOW (selected_frame), minibuf_window))) | ||
| 1455 | { | ||
| 1456 | XSETFASTINT (w->last_point, BUF_PT (b)); | ||
| 1457 | XSETFASTINT (w->last_point_x, FRAME_CURSOR_X (selected_frame)); | ||
| 1458 | XSETFASTINT (w->last_point_y, FRAME_CURSOR_Y (selected_frame)); | ||
| 1459 | } | ||
| 1460 | else | ||
| 1461 | /* Make last_point invalid, since we don't really know | ||
| 1462 | where the cursor would be if it were not in the echo area. */ | ||
| 1463 | XSETINT (w->last_point, -1); | ||
| 1464 | |||
| 1465 | if (all_windows) | ||
| 1466 | mark_window_display_accurate (FRAME_ROOT_WINDOW (selected_frame), 1); | 6844 | mark_window_display_accurate (FRAME_ROOT_WINDOW (selected_frame), 1); |
| 1467 | else | 6845 | else |
| 1468 | { | 6846 | { |
| 6847 | XSETFASTINT (w->last_point, BUF_PT (b)); | ||
| 6848 | w->last_cursor = w->cursor; | ||
| 6849 | w->last_cursor_off_p = w->cursor_off_p; | ||
| 6850 | |||
| 1469 | b->clip_changed = 0; | 6851 | b->clip_changed = 0; |
| 1470 | w->update_mode_line = Qnil; | 6852 | w->update_mode_line = Qnil; |
| 1471 | XSETFASTINT (w->last_modified, BUF_MODIFF (b)); | 6853 | XSETFASTINT (w->last_modified, BUF_MODIFF (b)); |
| @@ -1486,28 +6868,28 @@ update: | |||
| 1486 | w->window_end_valid = w->buffer; | 6868 | w->window_end_valid = w->buffer; |
| 1487 | last_arrow_position = COERCE_MARKER (Voverlay_arrow_position); | 6869 | last_arrow_position = COERCE_MARKER (Voverlay_arrow_position); |
| 1488 | last_arrow_string = Voverlay_arrow_string; | 6870 | last_arrow_string = Voverlay_arrow_string; |
| 1489 | if (do_verify_charstarts) | ||
| 1490 | verify_charstarts (w); | ||
| 1491 | if (frame_up_to_date_hook != 0) | 6871 | if (frame_up_to_date_hook != 0) |
| 1492 | (*frame_up_to_date_hook) (selected_frame); | 6872 | (*frame_up_to_date_hook) (selected_frame); |
| 1493 | } | 6873 | } |
| 6874 | |||
| 1494 | update_mode_lines = 0; | 6875 | update_mode_lines = 0; |
| 1495 | windows_or_buffers_changed = 0; | 6876 | windows_or_buffers_changed = 0; |
| 1496 | } | 6877 | } |
| 1497 | 6878 | ||
| 1498 | /* Start SIGIO interrupts coming again. | 6879 | /* Start SIGIO interrupts coming again. Having them off during the |
| 1499 | Having them off during the code above | 6880 | code above makes it less likely one will discard output, but not |
| 1500 | makes it less likely one will discard output, | 6881 | impossible, since there might be stuff in the system buffer here. |
| 1501 | but not impossible, since there might be stuff | ||
| 1502 | in the system buffer here. | ||
| 1503 | But it is much hairier to try to do anything about that. */ | 6882 | But it is much hairier to try to do anything about that. */ |
| 1504 | |||
| 1505 | if (interrupt_input) | 6883 | if (interrupt_input) |
| 1506 | request_sigio (); | 6884 | request_sigio (); |
| 1507 | start_polling (); | 6885 | start_polling (); |
| 1508 | 6886 | ||
| 1509 | /* If something has become visible now which was not before, | 6887 | /* If a frame has become visible which was not before, redisplay |
| 1510 | redisplay again, so that we get them. */ | 6888 | again, so that we display it. Expose events for such a frame |
| 6889 | (which it gets when becoming visible) don't call the parts of | ||
| 6890 | redisplay constructing glyphs, so simply exposing a frame won't | ||
| 6891 | display anything in this case. So, we have to display these | ||
| 6892 | frames here explicitly. */ | ||
| 1511 | if (!pause) | 6893 | if (!pause) |
| 1512 | { | 6894 | { |
| 1513 | Lisp_Object tail, frame; | 6895 | Lisp_Object tail, frame; |
| @@ -1538,10 +6920,16 @@ update: | |||
| 1538 | visible frames, redisplay again. */ | 6920 | visible frames, redisplay again. */ |
| 1539 | if (windows_or_buffers_changed && !pause) | 6921 | if (windows_or_buffers_changed && !pause) |
| 1540 | goto retry; | 6922 | goto retry; |
| 6923 | |||
| 6924 | end_of_redisplay:; | ||
| 6925 | |||
| 6926 | if (--redisplaying_p < 0) | ||
| 6927 | redisplaying_p = 0; | ||
| 1541 | } | 6928 | } |
| 1542 | 6929 | ||
| 1543 | /* Redisplay, but leave alone any recent echo area message | 6930 | |
| 1544 | unless another message has been requested in its place. | 6931 | /* Redisplay, but leave alone any recent echo area message unless |
| 6932 | another message has been requested in its place. | ||
| 1545 | 6933 | ||
| 1546 | This is useful in situations where you need to redisplay but no | 6934 | This is useful in situations where you need to redisplay but no |
| 1547 | user action has occurred, making it inappropriate for the message | 6935 | user action has occurred, making it inappropriate for the message |
| @@ -1551,175 +6939,105 @@ update: | |||
| 1551 | void | 6939 | void |
| 1552 | redisplay_preserve_echo_area () | 6940 | redisplay_preserve_echo_area () |
| 1553 | { | 6941 | { |
| 1554 | if (echo_area_glyphs == 0 && previous_echo_glyphs != 0) | 6942 | if (!echo_area_glyphs |
| 6943 | && !STRINGP (echo_area_message) | ||
| 6944 | && (previous_echo_glyphs | ||
| 6945 | || STRINGP (previous_echo_area_message))) | ||
| 1555 | { | 6946 | { |
| 1556 | echo_area_glyphs = previous_echo_glyphs; | 6947 | echo_area_glyphs = previous_echo_glyphs; |
| 6948 | echo_area_message = previous_echo_area_message; | ||
| 6949 | echo_area_glyphs_length = previous_echo_glyphs_length; | ||
| 1557 | redisplay_internal (1); | 6950 | redisplay_internal (1); |
| 1558 | echo_area_glyphs = 0; | 6951 | echo_area_glyphs = NULL; |
| 6952 | echo_area_message = Qnil; | ||
| 1559 | } | 6953 | } |
| 1560 | else | 6954 | else |
| 1561 | redisplay_internal (1); | 6955 | redisplay_internal (1); |
| 1562 | } | 6956 | } |
| 1563 | 6957 | ||
| 6958 | |||
| 6959 | /* Mark the display of windows in the window tree rooted at WINDOW as | ||
| 6960 | accurate or inaccurate. If FLAG is non-zero mark display of WINDOW | ||
| 6961 | as accurate. If FLAG is zero arrange for WINDOW to be redisplayed | ||
| 6962 | the next time redisplay_internal is called. */ | ||
| 6963 | |||
| 1564 | void | 6964 | void |
| 1565 | mark_window_display_accurate (window, flag) | 6965 | mark_window_display_accurate (window, accurate_p) |
| 1566 | Lisp_Object window; | 6966 | Lisp_Object window; |
| 1567 | int flag; | 6967 | int accurate_p; |
| 1568 | { | 6968 | { |
| 1569 | register struct window *w; | 6969 | struct window *w; |
| 1570 | 6970 | ||
| 1571 | for (;!NILP (window); window = w->next) | 6971 | for (; !NILP (window); window = w->next) |
| 1572 | { | 6972 | { |
| 1573 | if (!WINDOWP (window)) abort (); | ||
| 1574 | w = XWINDOW (window); | 6973 | w = XWINDOW (window); |
| 1575 | 6974 | ||
| 1576 | if (!NILP (w->buffer)) | 6975 | if (BUFFERP (w->buffer)) |
| 1577 | { | 6976 | { |
| 6977 | struct buffer *b = XBUFFER (w->buffer); | ||
| 6978 | |||
| 1578 | XSETFASTINT (w->last_modified, | 6979 | XSETFASTINT (w->last_modified, |
| 1579 | !flag ? 0 : BUF_MODIFF (XBUFFER (w->buffer))); | 6980 | accurate_p ? BUF_MODIFF (b) : 0); |
| 1580 | XSETFASTINT (w->last_overlay_modified, | 6981 | XSETFASTINT (w->last_overlay_modified, |
| 1581 | !flag ? 0 : BUF_OVERLAY_MODIFF (XBUFFER (w->buffer))); | 6982 | accurate_p ? BUF_OVERLAY_MODIFF (b) : 0); |
| 1582 | w->last_had_star | 6983 | w->last_had_star = (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b) |
| 1583 | = (BUF_MODIFF (XBUFFER (w->buffer)) > BUF_SAVE_MODIFF (XBUFFER (w->buffer)) | 6984 | ? Qt : Qnil); |
| 1584 | ? Qt : Qnil); | ||
| 1585 | 6985 | ||
| 6986 | #if 0 /* I don't think this is necessary because display_line does it. | ||
| 6987 | Let's check it. */ | ||
| 1586 | /* Record if we are showing a region, so can make sure to | 6988 | /* Record if we are showing a region, so can make sure to |
| 1587 | update it fully at next redisplay. */ | 6989 | update it fully at next redisplay. */ |
| 1588 | w->region_showing = (!NILP (Vtransient_mark_mode) | 6990 | w->region_showing |
| 1589 | && (w == XWINDOW (current_buffer->last_selected_window) | 6991 | = (!NILP (Vtransient_mark_mode) |
| 1590 | || highlight_nonselected_windows) | 6992 | && (w == XWINDOW (current_buffer->last_selected_window) |
| 1591 | && !NILP (XBUFFER (w->buffer)->mark_active) | 6993 | || highlight_nonselected_windows) |
| 1592 | ? Fmarker_position (XBUFFER (w->buffer)->mark) | 6994 | && (!NILP (b->mark_active) |
| 1593 | : Qnil); | 6995 | ? Fmarker_position (b->mark) |
| 6996 | : Qnil)); | ||
| 6997 | #endif | ||
| 6998 | |||
| 6999 | if (accurate_p) | ||
| 7000 | { | ||
| 7001 | b->clip_changed = 0; | ||
| 7002 | w->last_cursor = w->cursor; | ||
| 7003 | w->last_cursor_off_p = w->cursor_off_p; | ||
| 7004 | if (w == XWINDOW (selected_window)) | ||
| 7005 | w->last_point = BUF_PT (b); | ||
| 7006 | else | ||
| 7007 | w->last_point = XMARKER (w->pointm)->charpos; | ||
| 7008 | } | ||
| 1594 | } | 7009 | } |
| 1595 | 7010 | ||
| 1596 | w->window_end_valid = w->buffer; | 7011 | w->window_end_valid = w->buffer; |
| 1597 | w->update_mode_line = Qnil; | 7012 | w->update_mode_line = Qnil; |
| 1598 | if (!NILP (w->buffer) && flag) | ||
| 1599 | XBUFFER (w->buffer)->clip_changed = 0; | ||
| 1600 | 7013 | ||
| 1601 | if (!NILP (w->vchild)) | 7014 | if (!NILP (w->vchild)) |
| 1602 | mark_window_display_accurate (w->vchild, flag); | 7015 | mark_window_display_accurate (w->vchild, accurate_p); |
| 1603 | if (!NILP (w->hchild)) | 7016 | if (!NILP (w->hchild)) |
| 1604 | mark_window_display_accurate (w->hchild, flag); | 7017 | mark_window_display_accurate (w->hchild, accurate_p); |
| 1605 | } | 7018 | } |
| 1606 | 7019 | ||
| 1607 | if (flag) | 7020 | if (accurate_p) |
| 1608 | { | 7021 | { |
| 1609 | last_arrow_position = COERCE_MARKER (Voverlay_arrow_position); | 7022 | last_arrow_position = COERCE_MARKER (Voverlay_arrow_position); |
| 1610 | last_arrow_string = Voverlay_arrow_string; | 7023 | last_arrow_string = Voverlay_arrow_string; |
| 1611 | } | 7024 | } |
| 1612 | else | 7025 | else |
| 1613 | { | 7026 | { |
| 1614 | /* t is unequal to any useful value of Voverlay_arrow_... */ | 7027 | /* Force a thorough redisplay the next time by setting |
| 7028 | last_arrow_position and last_arrow_string to t, which is | ||
| 7029 | unequal to any useful value of Voverlay_arrow_... */ | ||
| 1615 | last_arrow_position = Qt; | 7030 | last_arrow_position = Qt; |
| 1616 | last_arrow_string = Qt; | 7031 | last_arrow_string = Qt; |
| 1617 | } | 7032 | } |
| 1618 | } | 7033 | } |
| 1619 | |||
| 1620 | /* Update the menu bar item list for frame F. | ||
| 1621 | This has to be done before we start to fill in any display lines, | ||
| 1622 | because it can call eval. | ||
| 1623 | |||
| 1624 | If SAVE_MATCH_DATA is 1, we must save and restore it here. */ | ||
| 1625 | |||
| 1626 | static void | ||
| 1627 | update_menu_bar (f, save_match_data) | ||
| 1628 | FRAME_PTR f; | ||
| 1629 | int save_match_data; | ||
| 1630 | { | ||
| 1631 | struct buffer *old = current_buffer; | ||
| 1632 | Lisp_Object window; | ||
| 1633 | register struct window *w; | ||
| 1634 | |||
| 1635 | window = FRAME_SELECTED_WINDOW (f); | ||
| 1636 | w = XWINDOW (window); | ||
| 1637 | |||
| 1638 | if (update_mode_lines) | ||
| 1639 | w->update_mode_line = Qt; | ||
| 1640 | |||
| 1641 | if (FRAME_WINDOW_P (f) | ||
| 1642 | ? | ||
| 1643 | #if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) | ||
| 1644 | FRAME_EXTERNAL_MENU_BAR (f) | ||
| 1645 | #else | ||
| 1646 | FRAME_MENU_BAR_LINES (f) > 0 | ||
| 1647 | #endif | ||
| 1648 | : FRAME_MENU_BAR_LINES (f) > 0) | ||
| 1649 | { | ||
| 1650 | /* If the user has switched buffers or windows, we need to | ||
| 1651 | recompute to reflect the new bindings. But we'll | ||
| 1652 | recompute when update_mode_lines is set too; that means | ||
| 1653 | that people can use force-mode-line-update to request | ||
| 1654 | that the menu bar be recomputed. The adverse effect on | ||
| 1655 | the rest of the redisplay algorithm is about the same as | ||
| 1656 | windows_or_buffers_changed anyway. */ | ||
| 1657 | if (windows_or_buffers_changed | ||
| 1658 | || !NILP (w->update_mode_line) | ||
| 1659 | || ((BUF_SAVE_MODIFF (XBUFFER (w->buffer)) | ||
| 1660 | < BUF_MODIFF (XBUFFER (w->buffer))) | ||
| 1661 | != !NILP (w->last_had_star)) | ||
| 1662 | || ((!NILP (Vtransient_mark_mode) | ||
| 1663 | && !NILP (XBUFFER (w->buffer)->mark_active)) | ||
| 1664 | != !NILP (w->region_showing))) | ||
| 1665 | { | ||
| 1666 | struct buffer *prev = current_buffer; | ||
| 1667 | int count = specpdl_ptr - specpdl; | ||
| 1668 | |||
| 1669 | set_buffer_internal_1 (XBUFFER (w->buffer)); | ||
| 1670 | if (save_match_data) | ||
| 1671 | record_unwind_protect (Fset_match_data, Fmatch_data (Qnil, Qnil)); | ||
| 1672 | if (NILP (Voverriding_local_map_menu_flag)) | ||
| 1673 | { | ||
| 1674 | specbind (Qoverriding_terminal_local_map, Qnil); | ||
| 1675 | specbind (Qoverriding_local_map, Qnil); | ||
| 1676 | } | ||
| 1677 | |||
| 1678 | /* Run the Lucid hook. */ | ||
| 1679 | call1 (Vrun_hooks, Qactivate_menubar_hook); | ||
| 1680 | /* If it has changed current-menubar from previous value, | ||
| 1681 | really recompute the menubar from the value. */ | ||
| 1682 | if (! NILP (Vlucid_menu_bar_dirty_flag)) | ||
| 1683 | call0 (Qrecompute_lucid_menubar); | ||
| 1684 | safe_run_hooks (Qmenu_bar_update_hook); | ||
| 1685 | FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f)); | ||
| 1686 | /* Redisplay the menu bar in case we changed it. */ | ||
| 1687 | #if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) | ||
| 1688 | if (FRAME_WINDOW_P (f)) | ||
| 1689 | set_frame_menubar (f, 0, 0); | ||
| 1690 | else | ||
| 1691 | /* On a terminal screen, the menu bar is an ordinary screen | ||
| 1692 | line, and this makes it get updated. */ | ||
| 1693 | w->update_mode_line = Qt; | ||
| 1694 | #else /* ! (USE_X_TOOLKIT || HAVE_NTGUI) */ | ||
| 1695 | /* In the non-toolkit version, the menu bar is an ordinary screen | ||
| 1696 | line, and this makes it get updated. */ | ||
| 1697 | w->update_mode_line = Qt; | ||
| 1698 | #endif /* ! (USE_X_TOOLKIT || HAVE_NTGUI) */ | ||
| 1699 | |||
| 1700 | unbind_to (count, Qnil); | ||
| 1701 | set_buffer_internal_1 (prev); | ||
| 1702 | } | ||
| 1703 | } | ||
| 1704 | } | ||
| 1705 | |||
| 1706 | int do_id = 1; | ||
| 1707 | 7034 | ||
| 1708 | /* Redisplay WINDOW and its subwindows and siblings. */ | ||
| 1709 | |||
| 1710 | static void | ||
| 1711 | redisplay_windows (window, preserve_echo_area) | ||
| 1712 | Lisp_Object window; | ||
| 1713 | int preserve_echo_area; | ||
| 1714 | { | ||
| 1715 | for (; !NILP (window); window = XWINDOW (window)->next) | ||
| 1716 | redisplay_window (window, 0, preserve_echo_area); | ||
| 1717 | } | ||
| 1718 | 7035 | ||
| 1719 | /* Return value in display table DP (Lisp_Char_Table *) for character | 7036 | /* Return value in display table DP (Lisp_Char_Table *) for character |
| 1720 | C. Since a display table doesn't have any parent, we don't have to | 7037 | C. Since a display table doesn't have any parent, we don't have to |
| 1721 | follow parent. Do not call this function directly but use the | 7038 | follow parent. Do not call this function directly but use the |
| 1722 | macro DISP_CHAR_VECTOR. */ | 7039 | macro DISP_CHAR_VECTOR. */ |
| 7040 | |||
| 1723 | Lisp_Object | 7041 | Lisp_Object |
| 1724 | disp_char_vector (dp, c) | 7042 | disp_char_vector (dp, c) |
| 1725 | struct Lisp_Char_Table *dp; | 7043 | struct Lisp_Char_Table *dp; |
| @@ -1728,18 +7046,22 @@ disp_char_vector (dp, c) | |||
| 1728 | int code[4], i; | 7046 | int code[4], i; |
| 1729 | Lisp_Object val; | 7047 | Lisp_Object val; |
| 1730 | 7048 | ||
| 1731 | if (SINGLE_BYTE_CHAR_P (c)) return (dp->contents[c]); | 7049 | if (SINGLE_BYTE_CHAR_P (c)) |
| 7050 | return (dp->contents[c]); | ||
| 1732 | 7051 | ||
| 1733 | SPLIT_NON_ASCII_CHAR (c, code[0], code[1], code[2]); | 7052 | SPLIT_NON_ASCII_CHAR (c, code[0], code[1], code[2]); |
| 1734 | if (code[0] != CHARSET_COMPOSITION) | 7053 | if (code[0] != CHARSET_COMPOSITION) |
| 1735 | { | 7054 | { |
| 1736 | if (code[1] < 32) code[1] = -1; | 7055 | if (code[1] < 32) |
| 1737 | else if (code[2] < 32) code[2] = -1; | 7056 | code[1] = -1; |
| 7057 | else if (code[2] < 32) | ||
| 7058 | code[2] = -1; | ||
| 1738 | } | 7059 | } |
| 1739 | /* Here, the possible range of CODE[0] (== charset ID) is | 7060 | |
| 1740 | 128..MAX_CHARSET. Since the top level char table contains data | 7061 | /* Here, the possible range of code[0] (== charset ID) is |
| 7062 | 128..max_charset. Since the top level char table contains data | ||
| 1741 | for multibyte characters after 256th element, we must increment | 7063 | for multibyte characters after 256th element, we must increment |
| 1742 | CODE[0] by 128 to get a correct index. */ | 7064 | code[0] by 128 to get a correct index. */ |
| 1743 | code[0] += 128; | 7065 | code[0] += 128; |
| 1744 | code[3] = -1; /* anchor */ | 7066 | code[3] = -1; /* anchor */ |
| 1745 | 7067 | ||
| @@ -1749,105 +7071,567 @@ disp_char_vector (dp, c) | |||
| 1749 | if (!SUB_CHAR_TABLE_P (val)) | 7071 | if (!SUB_CHAR_TABLE_P (val)) |
| 1750 | return (NILP (val) ? dp->defalt : val); | 7072 | return (NILP (val) ? dp->defalt : val); |
| 1751 | } | 7073 | } |
| 1752 | /* Here, VAL is a sub char table. We return the default value of it. */ | 7074 | |
| 7075 | /* Here, val is a sub char table. We return the default value of | ||
| 7076 | it. */ | ||
| 1753 | return (dp->defalt); | 7077 | return (dp->defalt); |
| 1754 | } | 7078 | } |
| 1755 | 7079 | ||
| 1756 | /* Redisplay window WINDOW and its subwindows. */ | 7080 | |
| 7081 | |||
| 7082 | /*********************************************************************** | ||
| 7083 | Window Redisplay | ||
| 7084 | ***********************************************************************/ | ||
| 7085 | |||
| 7086 | /* Redisplay all leaf windows in the window tree rooted at WINDOW. */ | ||
| 1757 | 7087 | ||
| 1758 | static void | 7088 | static void |
| 1759 | redisplay_window (window, just_this_one, preserve_echo_area) | 7089 | redisplay_windows (window) |
| 1760 | Lisp_Object window; | 7090 | Lisp_Object window; |
| 1761 | int just_this_one, preserve_echo_area; | ||
| 1762 | { | 7091 | { |
| 1763 | register struct window *w = XWINDOW (window); | 7092 | while (!NILP (window)) |
| 1764 | FRAME_PTR f = XFRAME (WINDOW_FRAME (w)); | 7093 | { |
| 1765 | int height; | 7094 | struct window *w = XWINDOW (window); |
| 1766 | int lpoint = PT; | 7095 | |
| 1767 | int lpoint_byte = PT_BYTE; | 7096 | if (!NILP (w->hchild)) |
| 1768 | struct buffer *old = current_buffer; | 7097 | redisplay_windows (w->hchild); |
| 1769 | register int width = window_internal_width (w) - 1; | 7098 | else if (!NILP (w->vchild)) |
| 1770 | register int startp, startp_byte; | 7099 | redisplay_windows (w->vchild); |
| 1771 | register int hscroll = XINT (w->hscroll); | 7100 | else |
| 1772 | struct position pos; | 7101 | redisplay_window (window, 0); |
| 1773 | int opoint = PT; | 7102 | |
| 1774 | int opoint_byte = PT_BYTE; | 7103 | window = w->next; |
| 1775 | int tem; | 7104 | } |
| 1776 | int update_mode_line; | 7105 | } |
| 1777 | struct Lisp_Char_Table *dp = window_display_table (w); | ||
| 1778 | int really_switched_buffer = 0; | ||
| 1779 | int count = specpdl_ptr - specpdl; | ||
| 1780 | 7106 | ||
| 1781 | if (Z == Z_BYTE && lpoint != lpoint_byte) | ||
| 1782 | abort (); | ||
| 1783 | if (lpoint_byte < lpoint) | ||
| 1784 | abort (); | ||
| 1785 | 7107 | ||
| 1786 | if (FRAME_HEIGHT (f) == 0) abort (); /* Some bug zeros some core */ | 7108 | /* Set cursor position of W. PT is assumed to be displayed in ROW. |
| 7109 | DELTA is the number of bytes by which positions recorded in ROW | ||
| 7110 | differ from current buffer positions. */ | ||
| 1787 | 7111 | ||
| 1788 | /* If this is a combination window, do its children; that's all. */ | 7112 | void |
| 7113 | set_cursor_from_row (w, row, matrix, delta, delta_bytes, dy, dvpos) | ||
| 7114 | struct window *w; | ||
| 7115 | struct glyph_row *row; | ||
| 7116 | struct glyph_matrix *matrix; | ||
| 7117 | int delta, delta_bytes, dy, dvpos; | ||
| 7118 | { | ||
| 7119 | struct glyph *glyph = row->glyphs[TEXT_AREA]; | ||
| 7120 | struct glyph *end = glyph + row->used[TEXT_AREA]; | ||
| 7121 | int x = row->x; | ||
| 7122 | int pt_old = PT - delta; | ||
| 7123 | |||
| 7124 | /* Skip over glyphs not having an object at the start of the row. | ||
| 7125 | These are special glyphs like truncation marks on terminal | ||
| 7126 | frames. */ | ||
| 7127 | if (row->displays_text_p) | ||
| 7128 | while (glyph < end | ||
| 7129 | && !glyph->object | ||
| 7130 | && glyph->charpos < 0) | ||
| 7131 | { | ||
| 7132 | x += glyph->pixel_width; | ||
| 7133 | ++glyph; | ||
| 7134 | } | ||
| 1789 | 7135 | ||
| 1790 | if (!NILP (w->vchild)) | 7136 | while (glyph < end |
| 7137 | && glyph->object | ||
| 7138 | && (!BUFFERP (glyph->object) | ||
| 7139 | || glyph->charpos < pt_old)) | ||
| 1791 | { | 7140 | { |
| 1792 | redisplay_windows (w->vchild, preserve_echo_area); | 7141 | x += glyph->pixel_width; |
| 1793 | return; | 7142 | ++glyph; |
| 1794 | } | 7143 | } |
| 1795 | if (!NILP (w->hchild)) | 7144 | |
| 7145 | w->cursor.hpos = glyph - row->glyphs[TEXT_AREA]; | ||
| 7146 | w->cursor.x = x; | ||
| 7147 | w->cursor.vpos = MATRIX_ROW_VPOS (row, matrix) + dvpos; | ||
| 7148 | w->cursor.y = row->y + dy; | ||
| 7149 | |||
| 7150 | if (w == XWINDOW (selected_window)) | ||
| 1796 | { | 7151 | { |
| 1797 | redisplay_windows (w->hchild, preserve_echo_area); | 7152 | if (!row->continued_p |
| 1798 | return; | 7153 | && !MATRIX_ROW_CONTINUATION_LINE_P (row) |
| 7154 | && row->x == 0) | ||
| 7155 | { | ||
| 7156 | this_line_buffer = XBUFFER (w->buffer); | ||
| 7157 | |||
| 7158 | CHARPOS (this_line_start_pos) | ||
| 7159 | = MATRIX_ROW_START_CHARPOS (row) + delta; | ||
| 7160 | BYTEPOS (this_line_start_pos) | ||
| 7161 | = MATRIX_ROW_START_BYTEPOS (row) + delta_bytes; | ||
| 7162 | |||
| 7163 | CHARPOS (this_line_end_pos) | ||
| 7164 | = Z - (MATRIX_ROW_END_CHARPOS (row) + delta); | ||
| 7165 | BYTEPOS (this_line_end_pos) | ||
| 7166 | = Z_BYTE - (MATRIX_ROW_END_BYTEPOS (row) + delta_bytes); | ||
| 7167 | |||
| 7168 | this_line_y = w->cursor.y; | ||
| 7169 | this_line_pixel_height = row->height; | ||
| 7170 | this_line_vpos = w->cursor.vpos; | ||
| 7171 | this_line_start_x = row->x; | ||
| 7172 | } | ||
| 7173 | else | ||
| 7174 | CHARPOS (this_line_start_pos) = 0; | ||
| 1799 | } | 7175 | } |
| 1800 | if (NILP (w->buffer)) | 7176 | } |
| 1801 | abort (); | ||
| 1802 | 7177 | ||
| 1803 | specbind (Qinhibit_point_motion_hooks, Qt); | ||
| 1804 | 7178 | ||
| 1805 | height = window_internal_height (w); | 7179 | /* Run window scroll functions, if any, for WINDOW with new window |
| 1806 | update_mode_line = (!NILP (w->update_mode_line) || update_mode_lines); | 7180 | start STARTP. Sets the window start of WINDOW to that position. */ |
| 1807 | if (XBUFFER (w->buffer)->clip_changed) | ||
| 1808 | update_mode_line = 1; | ||
| 1809 | 7181 | ||
| 1810 | if (MINI_WINDOW_P (w)) | 7182 | static INLINE struct text_pos |
| 7183 | run_window_scroll_functions (window, startp) | ||
| 7184 | Lisp_Object window; | ||
| 7185 | struct text_pos startp; | ||
| 7186 | { | ||
| 7187 | struct window *w = XWINDOW (window); | ||
| 7188 | SET_MARKER_FROM_TEXT_POS (w->start, startp); | ||
| 7189 | |||
| 7190 | if (!NILP (Vwindow_scroll_functions)) | ||
| 1811 | { | 7191 | { |
| 1812 | if (w == XWINDOW (echo_area_window) && echo_area_glyphs) | 7192 | run_hook_with_args_2 (Qwindow_scroll_functions, window, |
| 1813 | /* We've already displayed the echo area glyphs in this window. */ | 7193 | make_number (CHARPOS (startp))); |
| 1814 | goto finish_scroll_bars; | 7194 | SET_TEXT_POS_FROM_MARKER (startp, w->start); |
| 1815 | else if (w != XWINDOW (minibuf_window)) | 7195 | } |
| 7196 | |||
| 7197 | return startp; | ||
| 7198 | } | ||
| 7199 | |||
| 7200 | |||
| 7201 | /* Modify the desired matrix of window W and W->vscroll so that the | ||
| 7202 | line containing the cursor is fully visible. */ | ||
| 7203 | |||
| 7204 | static void | ||
| 7205 | make_cursor_line_fully_visible (w) | ||
| 7206 | struct window *w; | ||
| 7207 | { | ||
| 7208 | struct glyph_matrix *matrix; | ||
| 7209 | struct glyph_row *row; | ||
| 7210 | int top_line_height; | ||
| 7211 | |||
| 7212 | /* It's not always possible to find the cursor, e.g, when a window | ||
| 7213 | is full of overlay strings. Don't do anything in that case. */ | ||
| 7214 | if (w->cursor.vpos < 0) | ||
| 7215 | return; | ||
| 7216 | |||
| 7217 | matrix = w->desired_matrix; | ||
| 7218 | row = MATRIX_ROW (matrix, w->cursor.vpos); | ||
| 7219 | |||
| 7220 | /* If row->y == top y of window display area, the window isn't tall | ||
| 7221 | enough to display a single line. There is nothing we can do | ||
| 7222 | about it. */ | ||
| 7223 | top_line_height = WINDOW_DISPLAY_TOP_LINE_HEIGHT (w); | ||
| 7224 | if (row->y == top_line_height) | ||
| 7225 | return; | ||
| 7226 | |||
| 7227 | if (MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (w, row)) | ||
| 7228 | { | ||
| 7229 | int dy = row->height - row->visible_height; | ||
| 7230 | w->vscroll = 0; | ||
| 7231 | w->cursor.y += dy; | ||
| 7232 | shift_glyph_matrix (w, matrix, 0, matrix->nrows, dy); | ||
| 7233 | } | ||
| 7234 | else if (MATRIX_ROW_PARTIALLY_VISIBLE_AT_BOTTOM_P (w, row)) | ||
| 7235 | { | ||
| 7236 | int dy = - (row->height - row->visible_height); | ||
| 7237 | w->vscroll = dy; | ||
| 7238 | w->cursor.y += dy; | ||
| 7239 | shift_glyph_matrix (w, matrix, 0, matrix->nrows, dy); | ||
| 7240 | } | ||
| 7241 | |||
| 7242 | /* When we change the cursor y-position of the selected window, | ||
| 7243 | change this_line_y as well so that the display optimization for | ||
| 7244 | the cursor line of the selected window in redisplay_internal uses | ||
| 7245 | the correct y-position. */ | ||
| 7246 | if (w == XWINDOW (selected_window)) | ||
| 7247 | this_line_y = w->cursor.y; | ||
| 7248 | } | ||
| 7249 | |||
| 7250 | |||
| 7251 | /* Try scrolling PT into view in window WINDOW. JUST_THIS_ONE_P | ||
| 7252 | non-zero means only WINDOW is redisplayed in redisplay_internal. | ||
| 7253 | TEMP_SCROLL_STEP has the same meaning as scroll_step, and is used | ||
| 7254 | in redisplay_window to bring a partially visible line into view in | ||
| 7255 | the case that only the cursor has moved. | ||
| 7256 | |||
| 7257 | Value is | ||
| 7258 | |||
| 7259 | 1 if scrolling succeeded | ||
| 7260 | |||
| 7261 | 0 if scrolling didn't find point. | ||
| 7262 | |||
| 7263 | -1 if new fonts have been loaded so that we must interrupt | ||
| 7264 | redisplay, adjust glyph matrices, and try again. */ | ||
| 7265 | |||
| 7266 | static int | ||
| 7267 | try_scrolling (window, just_this_one_p, scroll_conservatively, | ||
| 7268 | scroll_step, temp_scroll_step) | ||
| 7269 | Lisp_Object window; | ||
| 7270 | int just_this_one_p; | ||
| 7271 | int scroll_conservatively, scroll_step; | ||
| 7272 | int temp_scroll_step; | ||
| 7273 | { | ||
| 7274 | struct window *w = XWINDOW (window); | ||
| 7275 | struct frame *f = XFRAME (w->frame); | ||
| 7276 | struct text_pos scroll_margin_pos; | ||
| 7277 | struct text_pos pos; | ||
| 7278 | struct text_pos startp; | ||
| 7279 | struct it it; | ||
| 7280 | Lisp_Object window_end; | ||
| 7281 | int this_scroll_margin; | ||
| 7282 | int dy = 0; | ||
| 7283 | int scroll_max; | ||
| 7284 | int line_height, rc; | ||
| 7285 | int amount_to_scroll = 0; | ||
| 7286 | Lisp_Object aggressive; | ||
| 7287 | int height; | ||
| 7288 | |||
| 7289 | #if GLYPH_DEBUG | ||
| 7290 | debug_method_add (w, "try_scrolling"); | ||
| 7291 | #endif | ||
| 7292 | |||
| 7293 | SET_TEXT_POS_FROM_MARKER (startp, w->start); | ||
| 7294 | |||
| 7295 | /* Compute scroll margin height in pixels. We scroll when point is | ||
| 7296 | within this distance from the top or bottom of the window. */ | ||
| 7297 | if (scroll_margin > 0) | ||
| 7298 | { | ||
| 7299 | this_scroll_margin = min (scroll_margin, XINT (w->height) / 4); | ||
| 7300 | this_scroll_margin *= CANON_Y_UNIT (f); | ||
| 7301 | } | ||
| 7302 | else | ||
| 7303 | this_scroll_margin = 0; | ||
| 7304 | |||
| 7305 | /* Compute how much we should try to scroll maximally to bring point | ||
| 7306 | into view. */ | ||
| 7307 | if (scroll_step) | ||
| 7308 | scroll_max = scroll_step; | ||
| 7309 | else if (scroll_conservatively) | ||
| 7310 | scroll_max = scroll_conservatively; | ||
| 7311 | else if (temp_scroll_step) | ||
| 7312 | scroll_max = temp_scroll_step; | ||
| 7313 | else if (NUMBERP (current_buffer->scroll_down_aggressively) | ||
| 7314 | || NUMBERP (current_buffer->scroll_up_aggressively)) | ||
| 7315 | /* We're trying to scroll because of aggressive scrolling | ||
| 7316 | but no scroll_step is set. Choose an arbitrary one. Maybe | ||
| 7317 | there should be a variable for this. */ | ||
| 7318 | scroll_max = 10; | ||
| 7319 | else | ||
| 7320 | scroll_max = 0; | ||
| 7321 | scroll_max *= CANON_Y_UNIT (f); | ||
| 7322 | |||
| 7323 | /* Decide whether we have to scroll down. Start at the window end | ||
| 7324 | and move this_scroll_margin up to find the position of the scroll | ||
| 7325 | margin. */ | ||
| 7326 | window_end = Fwindow_end (window, Qt); | ||
| 7327 | CHARPOS (scroll_margin_pos) = XINT (window_end); | ||
| 7328 | BYTEPOS (scroll_margin_pos) = CHAR_TO_BYTE (CHARPOS (scroll_margin_pos)); | ||
| 7329 | if (this_scroll_margin) | ||
| 7330 | { | ||
| 7331 | start_display (&it, w, scroll_margin_pos); | ||
| 7332 | move_it_vertically (&it, - this_scroll_margin); | ||
| 7333 | scroll_margin_pos = it.current.pos; | ||
| 7334 | } | ||
| 7335 | |||
| 7336 | if (PT >= CHARPOS (scroll_margin_pos)) | ||
| 7337 | { | ||
| 7338 | int y0; | ||
| 7339 | |||
| 7340 | /* Point is in the scroll margin at the bottom of the window, or | ||
| 7341 | below. Compute a new window start that makes point visible. */ | ||
| 7342 | |||
| 7343 | /* Compute the distance from the scroll margin to PT. | ||
| 7344 | Give up if the distance is greater than scroll_max. */ | ||
| 7345 | start_display (&it, w, scroll_margin_pos); | ||
| 7346 | y0 = it.current_y; | ||
| 7347 | move_it_to (&it, PT, 0, it.last_visible_y, -1, | ||
| 7348 | MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y); | ||
| 7349 | line_height = (it.max_ascent + it.max_descent | ||
| 7350 | ? it.max_ascent + it.max_descent | ||
| 7351 | : last_height); | ||
| 7352 | dy = it.current_y + line_height - y0; | ||
| 7353 | if (dy > scroll_max) | ||
| 7354 | return 0; | ||
| 7355 | |||
| 7356 | /* Move the window start down. If scrolling conservatively, | ||
| 7357 | move it just enough down to make point visible. If | ||
| 7358 | scroll_step is set, move it down by scroll_step. */ | ||
| 7359 | start_display (&it, w, startp); | ||
| 7360 | |||
| 7361 | if (scroll_conservatively) | ||
| 7362 | amount_to_scroll = dy; | ||
| 7363 | else if (scroll_step || temp_scroll_step) | ||
| 7364 | amount_to_scroll = scroll_max; | ||
| 7365 | else | ||
| 7366 | { | ||
| 7367 | aggressive = current_buffer->scroll_down_aggressively; | ||
| 7368 | height = (WINDOW_DISPLAY_HEIGHT_NO_MODE_LINE (w) | ||
| 7369 | - WINDOW_DISPLAY_TOP_LINE_HEIGHT (w)); | ||
| 7370 | if (NUMBERP (aggressive)) | ||
| 7371 | amount_to_scroll = XFLOATINT (aggressive) * height; | ||
| 7372 | } | ||
| 7373 | |||
| 7374 | if (amount_to_scroll <= 0) | ||
| 7375 | return 0; | ||
| 7376 | |||
| 7377 | move_it_vertically (&it, amount_to_scroll); | ||
| 7378 | startp = it.current.pos; | ||
| 7379 | } | ||
| 7380 | else | ||
| 7381 | { | ||
| 7382 | /* See if point is inside the scroll margin at the top of the | ||
| 7383 | window. */ | ||
| 7384 | scroll_margin_pos = startp; | ||
| 7385 | if (this_scroll_margin) | ||
| 1816 | { | 7386 | { |
| 1817 | /* This is a minibuffer, but it's not the currently active one, | 7387 | start_display (&it, w, startp); |
| 1818 | so clear it. */ | 7388 | move_it_vertically (&it, this_scroll_margin); |
| 1819 | int vpos = XFASTINT (w->top); | 7389 | scroll_margin_pos = it.current.pos; |
| 1820 | int i; | 7390 | } |
| 1821 | 7391 | ||
| 1822 | for (i = 0; i < height; i++) | 7392 | if (PT < CHARPOS (scroll_margin_pos)) |
| 7393 | { | ||
| 7394 | /* Point is in the scroll margin at the top of the window or | ||
| 7395 | above what is displayed in the window. */ | ||
| 7396 | int y0; | ||
| 7397 | |||
| 7398 | /* Compute the vertical distance from PT to the scroll | ||
| 7399 | margin position. Give up if distance is greater than | ||
| 7400 | scroll_max. */ | ||
| 7401 | SET_TEXT_POS (pos, PT, PT_BYTE); | ||
| 7402 | start_display (&it, w, pos); | ||
| 7403 | y0 = it.current_y; | ||
| 7404 | move_it_to (&it, CHARPOS (scroll_margin_pos), 0, | ||
| 7405 | it.last_visible_y, -1, | ||
| 7406 | MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y); | ||
| 7407 | dy = it.current_y - y0; | ||
| 7408 | if (dy > scroll_max) | ||
| 7409 | return 0; | ||
| 7410 | |||
| 7411 | /* Compute new window start. */ | ||
| 7412 | start_display (&it, w, startp); | ||
| 7413 | |||
| 7414 | if (scroll_conservatively) | ||
| 7415 | amount_to_scroll = dy; | ||
| 7416 | else if (scroll_step || temp_scroll_step) | ||
| 7417 | amount_to_scroll = scroll_max; | ||
| 7418 | else | ||
| 1823 | { | 7419 | { |
| 1824 | get_display_line (f, vpos + i, 0); | 7420 | aggressive = current_buffer->scroll_up_aggressively; |
| 1825 | display_string (w, vpos + i, "", 0, | 7421 | height = (WINDOW_DISPLAY_HEIGHT_NO_MODE_LINE (w) |
| 1826 | FRAME_LEFT_SCROLL_BAR_WIDTH (f), | 7422 | - WINDOW_DISPLAY_TOP_LINE_HEIGHT (w)); |
| 1827 | 0, 1, 0, width, 0); | 7423 | if (NUMBERP (aggressive)) |
| 7424 | amount_to_scroll = XFLOATINT (aggressive) * height; | ||
| 1828 | } | 7425 | } |
| 7426 | |||
| 7427 | if (amount_to_scroll <= 0) | ||
| 7428 | return 0; | ||
| 1829 | 7429 | ||
| 1830 | goto finish_scroll_bars; | 7430 | move_it_vertically (&it, - amount_to_scroll); |
| 7431 | startp = it.current.pos; | ||
| 7432 | } | ||
| 7433 | } | ||
| 7434 | |||
| 7435 | /* Run window scroll functions. */ | ||
| 7436 | startp = run_window_scroll_functions (window, startp); | ||
| 7437 | |||
| 7438 | /* Display the window. Give up if new fonts are loaded, or if point | ||
| 7439 | doesn't appear. */ | ||
| 7440 | if (!try_window (window, startp)) | ||
| 7441 | rc = -1; | ||
| 7442 | else if (w->cursor.vpos < 0) | ||
| 7443 | { | ||
| 7444 | clear_glyph_matrix (w->desired_matrix); | ||
| 7445 | rc = 0; | ||
| 7446 | } | ||
| 7447 | else | ||
| 7448 | { | ||
| 7449 | /* Maybe forget recorded base line for line number display. */ | ||
| 7450 | if (!just_this_one_p | ||
| 7451 | || current_buffer->clip_changed | ||
| 7452 | || beg_unchanged < CHARPOS (startp)) | ||
| 7453 | w->base_line_number = Qnil; | ||
| 7454 | |||
| 7455 | /* If cursor ends up on a partially visible line, shift display | ||
| 7456 | lines up or down. */ | ||
| 7457 | make_cursor_line_fully_visible (w); | ||
| 7458 | rc = 1; | ||
| 7459 | } | ||
| 7460 | |||
| 7461 | return rc; | ||
| 7462 | } | ||
| 7463 | |||
| 7464 | |||
| 7465 | /* Compute a suitable window start for window W if display of W starts | ||
| 7466 | on a continuation line. Value is non-zero if a new window start | ||
| 7467 | was computed. | ||
| 7468 | |||
| 7469 | The new window start will be computed, based on W's width, starting | ||
| 7470 | from the start of the continued line. It is the start of the | ||
| 7471 | screen line with the minimum distance from the old start W->start. */ | ||
| 7472 | |||
| 7473 | static int | ||
| 7474 | compute_window_start_on_continuation_line (w) | ||
| 7475 | struct window *w; | ||
| 7476 | { | ||
| 7477 | struct text_pos pos, start_pos; | ||
| 7478 | int window_start_changed_p = 0; | ||
| 7479 | |||
| 7480 | SET_TEXT_POS_FROM_MARKER (start_pos, w->start); | ||
| 7481 | |||
| 7482 | /* If window start is on a continuation line... Window start may be | ||
| 7483 | < BEGV in case there's invisible text at the start of the | ||
| 7484 | buffer (M-x rmail, for example). */ | ||
| 7485 | if (CHARPOS (start_pos) > BEGV | ||
| 7486 | && FETCH_BYTE (BYTEPOS (start_pos) - 1) != '\n') | ||
| 7487 | { | ||
| 7488 | struct it it; | ||
| 7489 | struct glyph_row *row; | ||
| 7490 | |||
| 7491 | /* Find the start of the continued line. This should be fast | ||
| 7492 | because scan_buffer is fast (newline cache). */ | ||
| 7493 | row = w->desired_matrix->rows + (WINDOW_WANTS_TOP_LINE_P (w) ? 1 : 0); | ||
| 7494 | init_iterator (&it, w, CHARPOS (start_pos), BYTEPOS (start_pos), | ||
| 7495 | row, DEFAULT_FACE_ID); | ||
| 7496 | reseat_at_previous_visible_line_start (&it); | ||
| 7497 | |||
| 7498 | /* If the line start is "too far" away from the window start, | ||
| 7499 | say it takes too much time to compute a new window start. */ | ||
| 7500 | if (CHARPOS (start_pos) - IT_CHARPOS (it) | ||
| 7501 | < XFASTINT (w->height) * XFASTINT (w->width)) | ||
| 7502 | { | ||
| 7503 | int min_distance, distance; | ||
| 7504 | |||
| 7505 | /* Move forward by display lines to find the new window | ||
| 7506 | start. If window width was enlarged, the new start can | ||
| 7507 | be expected to be > the old start. If window width was | ||
| 7508 | decreased, the new window start will be < the old start. | ||
| 7509 | So, we're looking for the display line start with the | ||
| 7510 | minimum distance from the old window start. */ | ||
| 7511 | pos = it.current.pos; | ||
| 7512 | min_distance = INFINITY; | ||
| 7513 | while ((distance = abs (CHARPOS (start_pos) - IT_CHARPOS (it))), | ||
| 7514 | distance < min_distance) | ||
| 7515 | { | ||
| 7516 | min_distance = distance; | ||
| 7517 | pos = it.current.pos; | ||
| 7518 | move_it_by_lines (&it, 1, 0); | ||
| 7519 | } | ||
| 7520 | |||
| 7521 | /* Set the window start there. */ | ||
| 7522 | SET_MARKER_FROM_TEXT_POS (w->start, pos); | ||
| 7523 | window_start_changed_p = 1; | ||
| 1831 | } | 7524 | } |
| 1832 | } | 7525 | } |
| 7526 | |||
| 7527 | return window_start_changed_p; | ||
| 7528 | } | ||
| 1833 | 7529 | ||
| 1834 | /* Otherwise set up data on this window; select its buffer and point value */ | ||
| 1835 | 7530 | ||
| 7531 | /* Redisplay leaf window WINDOW. JUST_THIS_ONE_P non-zero means only | ||
| 7532 | selected_window is redisplayed. */ | ||
| 7533 | |||
| 7534 | static void | ||
| 7535 | redisplay_window (window, just_this_one_p) | ||
| 7536 | Lisp_Object window; | ||
| 7537 | int just_this_one_p; | ||
| 7538 | { | ||
| 7539 | struct window *w = XWINDOW (window); | ||
| 7540 | struct frame *f = XFRAME (w->frame); | ||
| 7541 | struct buffer *buffer = XBUFFER (w->buffer); | ||
| 7542 | struct buffer *old = current_buffer; | ||
| 7543 | struct text_pos lpoint, opoint, startp; | ||
| 7544 | int update_mode_line; | ||
| 7545 | int tem; | ||
| 7546 | struct it it; | ||
| 7547 | /* Record it now because it's overwritten. */ | ||
| 7548 | int current_matrix_up_to_date_p = 0; | ||
| 7549 | int really_switched_buffer = 0; | ||
| 7550 | int temp_scroll_step = 0; | ||
| 7551 | int count = specpdl_ptr - specpdl; | ||
| 7552 | |||
| 7553 | SET_TEXT_POS (lpoint, PT, PT_BYTE); | ||
| 7554 | opoint = lpoint; | ||
| 7555 | |||
| 7556 | /* W must be a leaf window here. */ | ||
| 7557 | xassert (!NILP (w->buffer)); | ||
| 7558 | #if GLYPH_DEBUG | ||
| 7559 | *w->desired_matrix->method = 0; | ||
| 7560 | #endif | ||
| 7561 | |||
| 7562 | specbind (Qinhibit_point_motion_hooks, Qt); | ||
| 7563 | |||
| 7564 | /* Has the mode line to be updated? */ | ||
| 7565 | update_mode_line = (!NILP (w->update_mode_line) | ||
| 7566 | || update_mode_lines | ||
| 7567 | || buffer->clip_changed); | ||
| 7568 | |||
| 7569 | if (MINI_WINDOW_P (w)) | ||
| 7570 | { | ||
| 7571 | if (w == XWINDOW (echo_area_window) | ||
| 7572 | && (echo_area_glyphs | ||
| 7573 | || STRINGP (echo_area_message))) | ||
| 7574 | { | ||
| 7575 | if (update_mode_line) | ||
| 7576 | /* We may have to update a tty frame's menu bar or a | ||
| 7577 | toolbar. Example `M-x C-h C-h C-g'. */ | ||
| 7578 | goto finish_menu_bars; | ||
| 7579 | else | ||
| 7580 | /* We've already displayed the echo area glyphs in this window. */ | ||
| 7581 | goto finish_scroll_bars; | ||
| 7582 | } | ||
| 7583 | else if (w != XWINDOW (minibuf_window)) | ||
| 7584 | { | ||
| 7585 | /* W is a mini-buffer window, but it's not the currently | ||
| 7586 | active one, so clear it. */ | ||
| 7587 | int yb = window_text_bottom_y (w); | ||
| 7588 | struct glyph_row *row; | ||
| 7589 | int y; | ||
| 7590 | |||
| 7591 | for (y = 0, row = w->desired_matrix->rows; | ||
| 7592 | y < yb; | ||
| 7593 | y += row->height, ++row) | ||
| 7594 | blank_row (w, row, y); | ||
| 7595 | goto finish_scroll_bars; | ||
| 7596 | } | ||
| 7597 | } | ||
| 7598 | |||
| 7599 | /* Otherwise set up data on this window; select its buffer and point | ||
| 7600 | value. */ | ||
| 1836 | if (update_mode_line) | 7601 | if (update_mode_line) |
| 1837 | /* Really select the buffer, for the sake of buffer-local variables. */ | ||
| 1838 | { | 7602 | { |
| 7603 | /* Really select the buffer, for the sake of buffer-local | ||
| 7604 | variables. */ | ||
| 1839 | set_buffer_internal_1 (XBUFFER (w->buffer)); | 7605 | set_buffer_internal_1 (XBUFFER (w->buffer)); |
| 1840 | really_switched_buffer = 1; | 7606 | really_switched_buffer = 1; |
| 1841 | } | 7607 | } |
| 1842 | else | 7608 | else |
| 1843 | set_buffer_temp (XBUFFER (w->buffer)); | 7609 | set_buffer_temp (XBUFFER (w->buffer)); |
| 7610 | SET_TEXT_POS (opoint, PT, PT_BYTE); | ||
| 1844 | 7611 | ||
| 1845 | opoint = PT; | 7612 | current_matrix_up_to_date_p |
| 1846 | opoint_byte = PT_BYTE; | 7613 | = (!NILP (w->window_end_valid) |
| 7614 | && !current_buffer->clip_changed | ||
| 7615 | && XFASTINT (w->last_modified) >= MODIFF | ||
| 7616 | && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF); | ||
| 7617 | |||
| 7618 | /* When windows_or_buffers_changed is non-zero, we can't rely on | ||
| 7619 | the window end being valid, so set it to nil there. */ | ||
| 7620 | if (windows_or_buffers_changed) | ||
| 7621 | { | ||
| 7622 | /* If window starts on a continuation line, maybe adjust the | ||
| 7623 | window start in case the window's width changed. */ | ||
| 7624 | if (XMARKER (w->start)->buffer == current_buffer) | ||
| 7625 | compute_window_start_on_continuation_line (w); | ||
| 7626 | |||
| 7627 | w->window_end_valid = Qnil; | ||
| 7628 | } | ||
| 1847 | 7629 | ||
| 1848 | if (Z == Z_BYTE && opoint != opoint_byte) | 7630 | /* Some sanity checks. */ |
| 7631 | CHECK_WINDOW_END (w); | ||
| 7632 | if (Z == Z_BYTE && CHARPOS (opoint) != BYTEPOS (opoint)) | ||
| 1849 | abort (); | 7633 | abort (); |
| 1850 | if (opoint_byte < opoint) | 7634 | if (BYTEPOS (opoint) < CHARPOS (opoint)) |
| 1851 | abort (); | 7635 | abort (); |
| 1852 | 7636 | ||
| 1853 | /* If %c is in mode line, update it if needed. */ | 7637 | /* If %c is in mode line, update it if needed. */ |
| @@ -1860,10 +7644,9 @@ redisplay_window (window, just_this_one, preserve_echo_area) | |||
| 1860 | && XFASTINT (w->column_number_displayed) != current_column ()) | 7644 | && XFASTINT (w->column_number_displayed) != current_column ()) |
| 1861 | update_mode_line = 1; | 7645 | update_mode_line = 1; |
| 1862 | 7646 | ||
| 1863 | /* Count number of windows showing the selected buffer. | 7647 | /* Count number of windows showing the selected buffer. An indirect |
| 1864 | An indirect buffer counts as its base buffer. */ | 7648 | buffer counts as its base buffer. */ |
| 1865 | 7649 | if (!just_this_one_p) | |
| 1866 | if (!just_this_one) | ||
| 1867 | { | 7650 | { |
| 1868 | struct buffer *current_base, *window_base; | 7651 | struct buffer *current_base, *window_base; |
| 1869 | current_base = current_buffer; | 7652 | current_base = current_buffer; |
| @@ -1876,9 +7659,8 @@ redisplay_window (window, just_this_one, preserve_echo_area) | |||
| 1876 | buffer_shared++; | 7659 | buffer_shared++; |
| 1877 | } | 7660 | } |
| 1878 | 7661 | ||
| 1879 | /* POINT refers normally to the selected window. | 7662 | /* Point refers normally to the selected window. For any other |
| 1880 | For any other window, set up appropriate value. */ | 7663 | window, set up appropriate value. */ |
| 1881 | |||
| 1882 | if (!EQ (window, selected_window)) | 7664 | if (!EQ (window, selected_window)) |
| 1883 | { | 7665 | { |
| 1884 | int new_pt = XMARKER (w->pointm)->charpos; | 7666 | int new_pt = XMARKER (w->pointm)->charpos; |
| @@ -1895,13 +7677,14 @@ redisplay_window (window, just_this_one, preserve_echo_area) | |||
| 1895 | new_pt_byte = ZV_BYTE; | 7677 | new_pt_byte = ZV_BYTE; |
| 1896 | set_marker_both (w->pointm, Qnil, ZV, ZV_BYTE); | 7678 | set_marker_both (w->pointm, Qnil, ZV, ZV_BYTE); |
| 1897 | } | 7679 | } |
| 7680 | |||
| 1898 | /* We don't use SET_PT so that the point-motion hooks don't run. */ | 7681 | /* We don't use SET_PT so that the point-motion hooks don't run. */ |
| 1899 | TEMP_SET_PT_BOTH (new_pt, new_pt_byte); | 7682 | TEMP_SET_PT_BOTH (new_pt, new_pt_byte); |
| 1900 | } | 7683 | } |
| 1901 | 7684 | ||
| 1902 | /* If any of the character widths specified in the display table | 7685 | /* If any of the character widths specified in the display table |
| 1903 | have changed, invalidate the width run cache. It's true that this | 7686 | have changed, invalidate the width run cache. It's true that |
| 1904 | may be a bit late to catch such changes, but the rest of | 7687 | this may be a bit late to catch such changes, but the rest of |
| 1905 | redisplay goes (non-fatally) haywire when the display table is | 7688 | redisplay goes (non-fatally) haywire when the display table is |
| 1906 | changed, so why should we worry about doing any better? */ | 7689 | changed, so why should we worry about doing any better? */ |
| 1907 | if (current_buffer->width_run_cache) | 7690 | if (current_buffer->width_run_cache) |
| @@ -1922,32 +7705,18 @@ redisplay_window (window, just_this_one, preserve_echo_area) | |||
| 1922 | if (XMARKER (w->start)->buffer != current_buffer) | 7705 | if (XMARKER (w->start)->buffer != current_buffer) |
| 1923 | goto recenter; | 7706 | goto recenter; |
| 1924 | 7707 | ||
| 1925 | startp = marker_position (w->start); | 7708 | SET_TEXT_POS_FROM_MARKER (startp, w->start); |
| 1926 | startp_byte = marker_byte_position (w->start); | ||
| 1927 | 7709 | ||
| 1928 | /* If someone specified a new starting point but did not insist, | 7710 | /* If someone specified a new starting point but did not insist, |
| 1929 | check whether it can be used. */ | 7711 | check whether it can be used. */ |
| 1930 | if (!NILP (w->optional_new_start) | 7712 | if (!NILP (w->optional_new_start)) |
| 1931 | && startp >= BEGV && startp <= ZV) | ||
| 1932 | { | 7713 | { |
| 1933 | w->optional_new_start = Qnil; | 7714 | w->optional_new_start = Qnil; |
| 1934 | /* Check whether this start pos is usable given where point is. */ | 7715 | /* This takes a mini-buffer prompt into account. */ |
| 1935 | 7716 | start_display (&it, w, startp); | |
| 1936 | pos = *compute_motion (startp, 0, | 7717 | move_it_to (&it, PT, 0, it.last_visible_y, -1, |
| 1937 | (((EQ (window, minibuf_window) | 7718 | MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y); |
| 1938 | && startp == BEG) | 7719 | if (IT_CHARPOS (it) == PT) |
| 1939 | ? minibuf_prompt_width : 0) | ||
| 1940 | + (hscroll ? 1 - hscroll : 0)), | ||
| 1941 | 0, | ||
| 1942 | PT, height, | ||
| 1943 | /* BUG FIX: See the comment of | ||
| 1944 | Fpos_visible_in_window_p (window.c). */ | ||
| 1945 | - (1 << (BITS_PER_SHORT - 1)), | ||
| 1946 | width, hscroll, | ||
| 1947 | pos_tab_offset (w, startp, startp_byte), w); | ||
| 1948 | /* If PT does fit on the screen, we will use this start pos, | ||
| 1949 | so do so by setting force_start. */ | ||
| 1950 | if (pos.bufpos == PT) | ||
| 1951 | w->force_start = Qt; | 7720 | w->force_start = Qt; |
| 1952 | } | 7721 | } |
| 1953 | 7722 | ||
| @@ -1956,10 +7725,14 @@ redisplay_window (window, just_this_one, preserve_echo_area) | |||
| 1956 | if (!NILP (w->force_start)) | 7725 | if (!NILP (w->force_start)) |
| 1957 | { | 7726 | { |
| 1958 | w->force_start = Qnil; | 7727 | w->force_start = Qnil; |
| 1959 | /* Forget any recorded base line for line number display. */ | 7728 | w->vscroll = 0; |
| 1960 | w->base_line_number = Qnil; | ||
| 1961 | /* The old bottom-of-screen position is no longer valid. */ | ||
| 1962 | w->window_end_valid = Qnil; | 7729 | w->window_end_valid = Qnil; |
| 7730 | |||
| 7731 | /* Forget any recorded base line for line number display. */ | ||
| 7732 | if (!current_matrix_up_to_date_p | ||
| 7733 | || current_buffer->clip_changed) | ||
| 7734 | w->base_line_number = Qnil; | ||
| 7735 | |||
| 1963 | /* Redisplay the mode line. Select the buffer properly for that. | 7736 | /* Redisplay the mode line. Select the buffer properly for that. |
| 1964 | Also, run the hook window-scroll-functions | 7737 | Also, run the hook window-scroll-functions |
| 1965 | because we have scrolled. */ | 7738 | because we have scrolled. */ |
| @@ -1970,259 +7743,335 @@ redisplay_window (window, just_this_one, preserve_echo_area) | |||
| 1970 | if (!update_mode_line | 7743 | if (!update_mode_line |
| 1971 | || ! NILP (Vwindow_scroll_functions)) | 7744 | || ! NILP (Vwindow_scroll_functions)) |
| 1972 | { | 7745 | { |
| 1973 | Lisp_Object temp[3]; | ||
| 1974 | |||
| 1975 | if (!really_switched_buffer) | 7746 | if (!really_switched_buffer) |
| 1976 | { | 7747 | { |
| 1977 | set_buffer_temp (old); | 7748 | set_buffer_temp (old); |
| 1978 | set_buffer_internal_1 (XBUFFER (w->buffer)); | 7749 | set_buffer_internal_1 (XBUFFER (w->buffer)); |
| 7750 | really_switched_buffer = 1; | ||
| 1979 | } | 7751 | } |
| 1980 | really_switched_buffer = 1; | 7752 | |
| 1981 | update_mode_line = 1; | 7753 | update_mode_line = 1; |
| 1982 | w->update_mode_line = Qt; | 7754 | w->update_mode_line = Qt; |
| 1983 | if (! NILP (Vwindow_scroll_functions)) | 7755 | startp = run_window_scroll_functions (window, startp); |
| 1984 | { | ||
| 1985 | run_hook_with_args_2 (Qwindow_scroll_functions, window, | ||
| 1986 | make_number (startp)); | ||
| 1987 | startp = marker_position (w->start); | ||
| 1988 | startp_byte = marker_byte_position (w->start); | ||
| 1989 | } | ||
| 1990 | } | 7756 | } |
| 7757 | |||
| 1991 | XSETFASTINT (w->last_modified, 0); | 7758 | XSETFASTINT (w->last_modified, 0); |
| 1992 | XSETFASTINT (w->last_overlay_modified, 0); | 7759 | XSETFASTINT (w->last_overlay_modified, 0); |
| 1993 | if (startp < BEGV) startp = BEGV, startp_byte = BEGV_BYTE; | 7760 | if (CHARPOS (startp) < BEGV) |
| 1994 | if (startp > ZV) startp = ZV, startp = ZV_BYTE; | 7761 | SET_TEXT_POS (startp, BEGV, BEGV_BYTE); |
| 1995 | try_window (window, startp); | 7762 | else if (CHARPOS (startp) > ZV) |
| 1996 | if (cursor_vpos < 0) | 7763 | SET_TEXT_POS (startp, ZV, ZV_BYTE); |
| 1997 | { | 7764 | |
| 1998 | /* If point does not appear, move point so it does appear */ | 7765 | /* Redisplay, then check if cursor has been set during the |
| 1999 | pos = *compute_motion (startp, 0, | 7766 | redisplay. Give up if new fonts were loaded. */ |
| 2000 | (((EQ (window, minibuf_window) | 7767 | if (!try_window (window, startp)) |
| 2001 | && startp == BEG) | 7768 | { |
| 2002 | ? minibuf_prompt_width : 0) | 7769 | w->force_start = Qt; |
| 2003 | + (hscroll ? 1 - hscroll : 0)), | 7770 | clear_glyph_matrix (w->desired_matrix); |
| 2004 | 0, | 7771 | goto restore_buffers; |
| 2005 | ZV, height / 2, | 7772 | } |
| 2006 | - (1 << (BITS_PER_SHORT - 1)), | 7773 | |
| 2007 | width, hscroll, | 7774 | if (w->cursor.vpos < 0) |
| 2008 | pos_tab_offset (w, startp, startp_byte), | 7775 | { |
| 2009 | w); | 7776 | /* If point does not appear, or on a line that is not fully |
| 2010 | TEMP_SET_PT_BOTH (pos.bufpos, pos.bytepos); | 7777 | visible, move point so it does appear. The desired |
| 7778 | matrix has been built above, so we can use it. */ | ||
| 7779 | int height = window_box_height (w) / 2; | ||
| 7780 | struct glyph_row *row = MATRIX_ROW (w->desired_matrix, 0); | ||
| 7781 | |||
| 7782 | while (row->y < height) | ||
| 7783 | ++row; | ||
| 7784 | |||
| 7785 | TEMP_SET_PT_BOTH (MATRIX_ROW_START_CHARPOS (row), | ||
| 7786 | MATRIX_ROW_START_BYTEPOS (row)); | ||
| 7787 | |||
| 2011 | if (w != XWINDOW (selected_window)) | 7788 | if (w != XWINDOW (selected_window)) |
| 2012 | set_marker_both (w->pointm, Qnil, PT, PT_BYTE); | 7789 | set_marker_both (w->pointm, Qnil, PT, PT_BYTE); |
| 2013 | else | 7790 | else if (current_buffer == old) |
| 2014 | { | 7791 | SET_TEXT_POS (lpoint, PT, PT_BYTE); |
| 2015 | if (current_buffer == old) | 7792 | |
| 2016 | { | 7793 | set_cursor_from_row (w, row, w->desired_matrix, 0, 0, 0, 0); |
| 2017 | lpoint = PT; | 7794 | |
| 2018 | lpoint_byte = PT_BYTE; | 7795 | /* If we are highlighting the region, then we just changed |
| 2019 | } | 7796 | the region, so redisplay to show it. */ |
| 2020 | FRAME_CURSOR_X (f) = (WINDOW_LEFT_MARGIN (w) | ||
| 2021 | + minmax (0, pos.hpos, width)); | ||
| 2022 | FRAME_CURSOR_Y (f) = pos.vpos + XFASTINT (w->top); | ||
| 2023 | } | ||
| 2024 | /* If we are highlighting the region, | ||
| 2025 | then we just changed the region, so redisplay to show it. */ | ||
| 2026 | if (!NILP (Vtransient_mark_mode) | 7797 | if (!NILP (Vtransient_mark_mode) |
| 2027 | && !NILP (current_buffer->mark_active)) | 7798 | && !NILP (current_buffer->mark_active)) |
| 2028 | { | 7799 | { |
| 2029 | cancel_my_columns (XWINDOW (window)); | 7800 | clear_glyph_matrix (w->desired_matrix); |
| 2030 | try_window (window, startp); | 7801 | if (!try_window (window, startp)) |
| 7802 | goto restore_buffers; | ||
| 2031 | } | 7803 | } |
| 2032 | } | 7804 | } |
| 7805 | |||
| 7806 | make_cursor_line_fully_visible (w); | ||
| 7807 | #if GLYPH_DEBUG | ||
| 7808 | debug_method_add (w, "forced window start"); | ||
| 7809 | #endif | ||
| 2033 | goto done; | 7810 | goto done; |
| 2034 | } | 7811 | } |
| 2035 | 7812 | ||
| 2036 | /* Handle case where text has not changed, only point, | 7813 | /* Handle case where text has not changed, only point, and it has |
| 2037 | and it has not moved off the frame. */ | 7814 | not moved off the frame. */ |
| 2038 | 7815 | if (current_matrix_up_to_date_p | |
| 2039 | /* This code is not used for minibuffer for the sake of | 7816 | /* Point may be in this window. */ |
| 2040 | the case of redisplaying to replace an echo area message; | 7817 | && PT >= CHARPOS (startp) |
| 2041 | since in that case the minibuffer contents per se are usually unchanged. | 7818 | /* If we don't check this, we are called to move the cursor in a |
| 2042 | This code is of no real use in the minibuffer since | 7819 | horizontally split window with a current matrix that doesn't |
| 2043 | the handling of this_line_bufpos, etc., | 7820 | fit the display. */ |
| 2044 | in redisplay handles the same cases. */ | 7821 | && !windows_or_buffers_changed |
| 2045 | 7822 | /* Selective display hasn't changed. */ | |
| 2046 | if (XFASTINT (w->last_modified) >= MODIFF | 7823 | && !current_buffer->clip_changed |
| 2047 | && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF | ||
| 2048 | && PT >= startp && !current_buffer->clip_changed | ||
| 2049 | && (just_this_one || WINDOW_FULL_WIDTH_P (w)) | ||
| 2050 | /* If force-mode-line-update was called, really redisplay; | 7824 | /* If force-mode-line-update was called, really redisplay; |
| 2051 | that's how redisplay is forced after e.g. changing | 7825 | that's how redisplay is forced after e.g. changing |
| 2052 | buffer-invisibility-spec. */ | 7826 | buffer-invisibility-spec. */ |
| 2053 | && NILP (w->update_mode_line) | 7827 | && NILP (w->update_mode_line) |
| 2054 | /* Can't use this case if highlighting a region. */ | 7828 | /* Can't use this case if highlighting a region. When a |
| 2055 | && !(!NILP (Vtransient_mark_mode) && !NILP (current_buffer->mark_active)) | 7829 | region exists, cursor movement has to do more than just |
| 7830 | set the cursor. */ | ||
| 7831 | && !(!NILP (Vtransient_mark_mode) | ||
| 7832 | && !NILP (current_buffer->mark_active)) | ||
| 2056 | && NILP (w->region_showing) | 7833 | && NILP (w->region_showing) |
| 2057 | /* If end pos is out of date, scroll bar and percentage will be wrong */ | 7834 | /* Right after splitting windows, last_point may be nil. */ |
| 2058 | && INTEGERP (w->window_end_vpos) | 7835 | && INTEGERP (w->last_point) |
| 2059 | && XFASTINT (w->window_end_vpos) < XFASTINT (w->height) | 7836 | /* This code is not used for mini-buffer for the sake of the case |
| 7837 | of redisplaying to replace an echo area message; since in | ||
| 7838 | that case the mini-buffer contents per se are usually | ||
| 7839 | unchanged. This code is of no real use in the mini-buffer | ||
| 7840 | since the handling of this_line_start_pos, etc., in redisplay | ||
| 7841 | handles the same cases. */ | ||
| 2060 | && !EQ (window, minibuf_window) | 7842 | && !EQ (window, minibuf_window) |
| 2061 | && (!MARKERP (Voverlay_arrow_position) | 7843 | /* When splitting windows or for new windows, it happens that |
| 7844 | redisplay is called with a nil window_end_vpos or one being | ||
| 7845 | larger than the window. This should really be fixed in | ||
| 7846 | window.c. I don't have this on my list, now, so we do | ||
| 7847 | approximately the same as the old redisplay code. --gerd. */ | ||
| 7848 | && INTEGERP (w->window_end_vpos) | ||
| 7849 | && XFASTINT (w->window_end_vpos) < w->current_matrix->nrows | ||
| 7850 | && (FRAME_WINDOW_P (f) | ||
| 7851 | || !MARKERP (Voverlay_arrow_position) | ||
| 2062 | || current_buffer != XMARKER (Voverlay_arrow_position)->buffer)) | 7852 | || current_buffer != XMARKER (Voverlay_arrow_position)->buffer)) |
| 2063 | { | 7853 | { |
| 2064 | /* All positions in this clause are relative to the window edge. */ | 7854 | int this_scroll_margin; |
| 2065 | 7855 | struct glyph_row *row; | |
| 2066 | int this_scroll_margin = scroll_margin; | 7856 | int scroll_p; |
| 2067 | int last_point_y = XFASTINT (w->last_point_y) - XINT (w->top); | ||
| 2068 | int last_point_x = (XFASTINT (w->last_point_x) - WINDOW_LEFT_MARGIN (w)); | ||
| 2069 | |||
| 2070 | /* Find where PT is located now on the frame. */ | ||
| 2071 | /* Check just_this_one as a way of verifying that the | ||
| 2072 | window edges have not changed. */ | ||
| 2073 | if (PT == XFASTINT (w->last_point) && just_this_one | ||
| 2074 | /* If CURSOR_IN_ECHO_AREA, last_point_x and last_point_y | ||
| 2075 | refer to the echo area and are not related to this window. */ | ||
| 2076 | && ! cursor_in_echo_area) | ||
| 2077 | { | ||
| 2078 | pos.hpos = last_point_x; | ||
| 2079 | pos.vpos = last_point_y; | ||
| 2080 | pos.bufpos = PT; | ||
| 2081 | } | ||
| 2082 | else if (PT > XFASTINT (w->last_point) | ||
| 2083 | && ! cursor_in_echo_area | ||
| 2084 | && XFASTINT (w->last_point) > startp && just_this_one | ||
| 2085 | /* We can't use this if point is in the left margin of a | ||
| 2086 | hscrolled window, because w->last_point_x has been | ||
| 2087 | clipped to the window edges. */ | ||
| 2088 | && !(last_point_x <= 0 && hscroll)) | ||
| 2089 | { | ||
| 2090 | int last_point = XFASTINT (w->last_point); | ||
| 2091 | int last_point_byte = CHAR_TO_BYTE (last_point); | ||
| 2092 | int tab_offset = (pos_tab_offset (w, last_point, last_point_byte) | ||
| 2093 | - (last_point_x + hscroll - !! hscroll)); | ||
| 2094 | |||
| 2095 | pos = *compute_motion (last_point, last_point_y, last_point_x, 1, | ||
| 2096 | PT, height, | ||
| 2097 | /* BUG FIX: See the comment of | ||
| 2098 | Fpos_visible_in_window_p (window.c). */ | ||
| 2099 | - (1 << (BITS_PER_SHORT - 1)), | ||
| 2100 | width, hscroll, | ||
| 2101 | tab_offset, | ||
| 2102 | w); | ||
| 2103 | } | ||
| 2104 | else | ||
| 2105 | { | ||
| 2106 | pos = *compute_motion (startp, 0, (hscroll ? 1 - hscroll : 0), 0, | ||
| 2107 | PT, height, | ||
| 2108 | /* BUG FIX: See the comment of | ||
| 2109 | Fpos_visible_in_window_p (window.c). */ | ||
| 2110 | - (1 << (BITS_PER_SHORT - 1)), | ||
| 2111 | width, hscroll, | ||
| 2112 | pos_tab_offset (w, startp, startp_byte), | ||
| 2113 | w); | ||
| 2114 | } | ||
| 2115 | 7857 | ||
| 2116 | /* Don't use a scroll margin that is negative or too large. */ | 7858 | #if GLYPH_DEBUG |
| 2117 | if (this_scroll_margin < 0) | 7859 | debug_method_add (w, "cursor movement"); |
| 2118 | this_scroll_margin = 0; | 7860 | #endif |
| 2119 | 7861 | ||
| 2120 | if (XINT (w->height) < 4 * scroll_margin) | 7862 | /* Scroll if point within this distance from the top or bottom |
| 2121 | this_scroll_margin = XINT (w->height) / 4; | 7863 | of the window. This is a pixel value. */ |
| 7864 | this_scroll_margin = max (0, scroll_margin); | ||
| 7865 | this_scroll_margin = min (this_scroll_margin, XFASTINT (w->height) / 4); | ||
| 7866 | this_scroll_margin *= CANON_Y_UNIT (f); | ||
| 7867 | |||
| 7868 | /* Start with the row the cursor was displayed during the last | ||
| 7869 | not paused redisplay. Give up if that row is not valid. */ | ||
| 7870 | if (w->last_cursor.vpos >= w->current_matrix->nrows) | ||
| 7871 | goto try_to_scroll; | ||
| 7872 | row = MATRIX_ROW (w->current_matrix, w->last_cursor.vpos); | ||
| 7873 | if (row->mode_line_p) | ||
| 7874 | ++row; | ||
| 7875 | if (!row->enabled_p) | ||
| 7876 | goto try_to_scroll; | ||
| 7877 | |||
| 7878 | scroll_p = 0; | ||
| 7879 | if (PT > XFASTINT (w->last_point)) | ||
| 7880 | { | ||
| 7881 | /* Point has moved forward. */ | ||
| 7882 | int last_y = window_text_bottom_y (w) - this_scroll_margin; | ||
| 7883 | |||
| 7884 | while ((MATRIX_ROW_END_CHARPOS (row) < PT | ||
| 7885 | /* The end position of a row equals the start | ||
| 7886 | position of the next row. If PT is there, we | ||
| 7887 | would rather display it in the next line, except | ||
| 7888 | when this line ends in ZV. */ | ||
| 7889 | || (MATRIX_ROW_END_CHARPOS (row) == PT | ||
| 7890 | && (MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row) | ||
| 7891 | || !row->ends_at_zv_p))) | ||
| 7892 | && MATRIX_ROW_BOTTOM_Y (row) < last_y) | ||
| 7893 | { | ||
| 7894 | xassert (row->enabled_p); | ||
| 7895 | ++row; | ||
| 7896 | } | ||
| 2122 | 7897 | ||
| 2123 | /* If point fits on the screen, and not within the scroll margin, | 7898 | /* If within the scroll margin, scroll. Note that |
| 2124 | we are ok. */ | 7899 | MATRIX_ROW_BOTTOM_Y gives the pixel position at which the |
| 2125 | if (pos.vpos < height - this_scroll_margin | 7900 | next line would be drawn, and that this_scroll_margin can |
| 2126 | && (pos.vpos >= this_scroll_margin || startp == BEGV)) | 7901 | be zero. */ |
| 7902 | if (MATRIX_ROW_BOTTOM_Y (row) > last_y | ||
| 7903 | || PT > MATRIX_ROW_END_CHARPOS (row) | ||
| 7904 | /* Line is completely visible last line in window and PT | ||
| 7905 | is to be set in the next line. */ | ||
| 7906 | || (MATRIX_ROW_BOTTOM_Y (row) == last_y | ||
| 7907 | && PT == MATRIX_ROW_END_CHARPOS (row) | ||
| 7908 | && !row->ends_at_zv_p | ||
| 7909 | && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row))) | ||
| 7910 | scroll_p = 1; | ||
| 7911 | } | ||
| 7912 | else if (PT < XFASTINT (w->last_point)) | ||
| 2127 | { | 7913 | { |
| 2128 | /* Ok, point is still on frame */ | 7914 | /* Cursor has to be moved backward. Note that PT >= |
| 2129 | if (w == XWINDOW (FRAME_SELECTED_WINDOW (f))) | 7915 | CHARPOS (startp) because of the outer if-statement. */ |
| 7916 | while (!row->mode_line_p | ||
| 7917 | && (MATRIX_ROW_START_CHARPOS (row) > PT | ||
| 7918 | || (MATRIX_ROW_START_CHARPOS (row) == PT | ||
| 7919 | && MATRIX_ROW_STARTS_IN_MIDDLE_OF_CHAR_P (row))) | ||
| 7920 | && (row->y > this_scroll_margin | ||
| 7921 | || CHARPOS (startp) == BEGV)) | ||
| 2130 | { | 7922 | { |
| 2131 | /* These variables are supposed to be origin 1 */ | 7923 | xassert (row->enabled_p); |
| 2132 | FRAME_CURSOR_X (f) = (WINDOW_LEFT_MARGIN (w) | 7924 | --row; |
| 2133 | + minmax (0, pos.hpos, width)); | ||
| 2134 | FRAME_CURSOR_Y (f) = pos.vpos + XFASTINT (w->top); | ||
| 2135 | } | 7925 | } |
| 2136 | /* This doesn't do the trick, because if a window to the right of | ||
| 2137 | this one must be redisplayed, this does nothing because there | ||
| 2138 | is nothing in DesiredFrame yet, and then the other window is | ||
| 2139 | redisplayed, making likes that are empty in this window's columns. | ||
| 2140 | if (WINDOW_FULL_WIDTH_P (w)) | ||
| 2141 | preserve_my_columns (w); | ||
| 2142 | */ | ||
| 2143 | if (current_buffer->clip_changed | ||
| 2144 | && ! NILP (Vwindow_scroll_functions)) | ||
| 2145 | run_hook_with_args_2 (Qwindow_scroll_functions, window, | ||
| 2146 | make_number (marker_position (w->start))); | ||
| 2147 | 7926 | ||
| 2148 | goto done; | 7927 | /* Consider the following case: Window starts at BEGV, there |
| 7928 | is invisible, intangible text at BEGV, so that display | ||
| 7929 | starts at some point START > BEGV. It can happen that | ||
| 7930 | we are called with PT somewhere between BEGV and START. | ||
| 7931 | Try to handle that case. */ | ||
| 7932 | if (row < w->current_matrix->rows | ||
| 7933 | || row->mode_line_p) | ||
| 7934 | { | ||
| 7935 | row = w->current_matrix->rows; | ||
| 7936 | if (row->mode_line_p) | ||
| 7937 | ++row; | ||
| 7938 | } | ||
| 7939 | |||
| 7940 | /* Due to newlines in overlay strings, we may have to skip | ||
| 7941 | forward over overlay strings. */ | ||
| 7942 | while (MATRIX_ROW_END_CHARPOS (row) == PT | ||
| 7943 | && MATRIX_ROW_ENDS_IN_OVERLAY_STRING_P (row) | ||
| 7944 | && !row->ends_at_zv_p) | ||
| 7945 | ++row; | ||
| 7946 | |||
| 7947 | /* If within the scroll margin, scroll. */ | ||
| 7948 | if (row->y < this_scroll_margin | ||
| 7949 | && CHARPOS (startp) != BEGV) | ||
| 7950 | scroll_p = 1; | ||
| 7951 | } | ||
| 7952 | |||
| 7953 | /* if PT is not in the glyph row, give up. */ | ||
| 7954 | if (PT < MATRIX_ROW_START_CHARPOS (row) | ||
| 7955 | || PT > MATRIX_ROW_END_CHARPOS (row)) | ||
| 7956 | goto try_to_scroll; | ||
| 7957 | |||
| 7958 | /* If we end up in a partially visible line, let's make it fully | ||
| 7959 | visible. This can be done most easily by using the existing | ||
| 7960 | scrolling code. */ | ||
| 7961 | if (MATRIX_ROW_PARTIALLY_VISIBLE_P (row)) | ||
| 7962 | { | ||
| 7963 | temp_scroll_step = 1; | ||
| 7964 | goto try_to_scroll; | ||
| 2149 | } | 7965 | } |
| 2150 | /* Don't bother trying redisplay with same start; | 7966 | else if (scroll_p) |
| 2151 | we already know it will lose. */ | 7967 | goto try_to_scroll; |
| 7968 | |||
| 7969 | set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0); | ||
| 7970 | goto done; | ||
| 2152 | } | 7971 | } |
| 7972 | |||
| 2153 | /* If current starting point was originally the beginning of a line | 7973 | /* If current starting point was originally the beginning of a line |
| 2154 | but no longer is, find a new starting point. */ | 7974 | but no longer is, find a new starting point. */ |
| 2155 | else if (!NILP (w->start_at_line_beg) | 7975 | else if (!NILP (w->start_at_line_beg) |
| 2156 | && !(startp <= BEGV | 7976 | && !(CHARPOS (startp) <= BEGV |
| 2157 | || FETCH_BYTE (startp_byte - 1) == '\n')) | 7977 | || FETCH_BYTE (BYTEPOS (startp) - 1) == '\n')) |
| 2158 | { | 7978 | { |
| 7979 | #if GLYPH_DEBUG | ||
| 7980 | debug_method_add (w, "recenter 1"); | ||
| 7981 | #endif | ||
| 2159 | goto recenter; | 7982 | goto recenter; |
| 2160 | } | 7983 | } |
| 2161 | else if (just_this_one && !MINI_WINDOW_P (w) | 7984 | |
| 2162 | && PT >= startp | 7985 | /* Try scrolling with try_window_id. */ |
| 7986 | else if (!windows_or_buffers_changed | ||
| 7987 | /* Window must be either use window-based redisplay or | ||
| 7988 | be full width. */ | ||
| 7989 | && (FRAME_WINDOW_P (f) | ||
| 7990 | || ((line_ins_del_ok && WINDOW_FULL_WIDTH_P (w)) | ||
| 7991 | && just_this_one_p)) | ||
| 7992 | && !MINI_WINDOW_P (w) | ||
| 7993 | /* Point is not known NOT to appear in window. */ | ||
| 7994 | && PT >= CHARPOS (startp) | ||
| 2163 | && XFASTINT (w->last_modified) | 7995 | && XFASTINT (w->last_modified) |
| 2164 | /* or else vmotion on first line won't work. */ | 7996 | /* Window is not hscrolled. */ |
| 2165 | && ! NILP (w->start_at_line_beg) | 7997 | && XFASTINT (w->hscroll) == 0 |
| 2166 | && ! EQ (w->window_end_valid, Qnil) | 7998 | /* Selective display has not changed. */ |
| 2167 | && do_id && !current_buffer->clip_changed | 7999 | && !current_buffer->clip_changed |
| 2168 | && !blank_end_of_window | 8000 | /* Current matrix is up to date. */ |
| 2169 | && WINDOW_FULL_WIDTH_P (w) | 8001 | && !NILP (w->window_end_valid) |
| 2170 | /* Can't use this case if highlighting a region. */ | 8002 | /* Can't use this case if highlighting a region because |
| 8003 | a cursor movement will do more than just set the cursor. */ | ||
| 2171 | && !(!NILP (Vtransient_mark_mode) | 8004 | && !(!NILP (Vtransient_mark_mode) |
| 2172 | && !NILP (current_buffer->mark_active)) | 8005 | && !NILP (current_buffer->mark_active)) |
| 2173 | /* Don't use try_window_id if newline | ||
| 2174 | doesn't display as the end of a line. */ | ||
| 2175 | && !(dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, '\n'))) | ||
| 2176 | && NILP (w->region_showing) | 8006 | && NILP (w->region_showing) |
| 8007 | /* Overlay arrow position and string not changed. */ | ||
| 2177 | && EQ (last_arrow_position, COERCE_MARKER (Voverlay_arrow_position)) | 8008 | && EQ (last_arrow_position, COERCE_MARKER (Voverlay_arrow_position)) |
| 2178 | && EQ (last_arrow_string, Voverlay_arrow_string) | 8009 | && EQ (last_arrow_string, Voverlay_arrow_string) |
| 2179 | && (tem = try_window_id (FRAME_SELECTED_WINDOW (f))) | 8010 | /* Value is > 0 if update has been done, it is -1 if we |
| 2180 | && tem != -2) | 8011 | know that the same window start will not work. It is 0 |
| 8012 | if unsuccessful for some other reason. */ | ||
| 8013 | && (tem = try_window_id (w)) != 0) | ||
| 2181 | { | 8014 | { |
| 2182 | /* tem > 0 means success. tem == -1 means choose new start. | 8015 | #if GLYPH_DEBUG |
| 2183 | tem == -2 means try again with same start, | 8016 | debug_method_add (w, "try_window_id"); |
| 2184 | and nothing but whitespace follows the changed stuff. | 8017 | #endif |
| 2185 | tem == 0 means try again with same start. */ | 8018 | |
| 8019 | if (fonts_changed_p) | ||
| 8020 | goto restore_buffers; | ||
| 2186 | if (tem > 0) | 8021 | if (tem > 0) |
| 2187 | goto done; | 8022 | goto done; |
| 8023 | /* Otherwise try_window_id has returned -1 which means that we | ||
| 8024 | don't want the alternative below this comment to execute. */ | ||
| 2188 | } | 8025 | } |
| 2189 | else if (startp >= BEGV && startp <= ZV | 8026 | else if (CHARPOS (startp) >= BEGV |
| 2190 | && (startp < ZV | 8027 | && CHARPOS (startp) <= ZV |
| 8028 | && PT >= CHARPOS (startp) | ||
| 8029 | && (CHARPOS (startp) < ZV | ||
| 2191 | /* Avoid starting at end of buffer. */ | 8030 | /* Avoid starting at end of buffer. */ |
| 2192 | #if 0 /* This change causes trouble for M-! finger & RET. | 8031 | || CHARPOS (startp) == BEGV |
| 2193 | It will have to be considered later. */ | ||
| 2194 | || ! EQ (window, selected_window) | ||
| 2195 | /* Don't do the recentering if redisplay | ||
| 2196 | is not for no user action. */ | ||
| 2197 | || preserve_echo_area | ||
| 2198 | #endif | ||
| 2199 | || startp == BEGV | ||
| 2200 | || (XFASTINT (w->last_modified) >= MODIFF | 8032 | || (XFASTINT (w->last_modified) >= MODIFF |
| 2201 | && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF))) | 8033 | && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF))) |
| 2202 | { | 8034 | { |
| 2203 | /* Try to redisplay starting at same place as before */ | 8035 | #if GLYPH_DEBUG |
| 2204 | /* If point has not moved off frame, accept the results */ | 8036 | debug_method_add (w, "same window start"); |
| 2205 | try_window (window, startp); | 8037 | #endif |
| 2206 | if (cursor_vpos >= 0) | 8038 | |
| 8039 | /* Try to redisplay starting at same place as before. | ||
| 8040 | If point has not moved off frame, accept the results. */ | ||
| 8041 | if (!current_matrix_up_to_date_p | ||
| 8042 | /* Don't use try_window_reusing_current_matrix in this case | ||
| 8043 | because it can have changed the buffer. */ | ||
| 8044 | || !NILP (Vwindow_scroll_functions) | ||
| 8045 | || MINI_WINDOW_P (w) | ||
| 8046 | || !try_window_reusing_current_matrix (w)) | ||
| 8047 | { | ||
| 8048 | IF_DEBUG (debug_method_add (w, "1")); | ||
| 8049 | try_window (window, startp); | ||
| 8050 | } | ||
| 8051 | |||
| 8052 | if (fonts_changed_p) | ||
| 8053 | goto restore_buffers; | ||
| 8054 | |||
| 8055 | if (w->cursor.vpos >= 0) | ||
| 2207 | { | 8056 | { |
| 2208 | if (!just_this_one || current_buffer->clip_changed | 8057 | if (!just_this_one_p |
| 2209 | || beg_unchanged < startp) | 8058 | || current_buffer->clip_changed |
| 8059 | || beg_unchanged < CHARPOS (startp)) | ||
| 2210 | /* Forget any recorded base line for line number display. */ | 8060 | /* Forget any recorded base line for line number display. */ |
| 2211 | w->base_line_number = Qnil; | 8061 | w->base_line_number = Qnil; |
| 2212 | 8062 | ||
| 2213 | if (current_buffer->clip_changed | 8063 | make_cursor_line_fully_visible (w); |
| 2214 | && ! NILP (Vwindow_scroll_functions)) | ||
| 2215 | run_hook_with_args_2 (Qwindow_scroll_functions, window, | ||
| 2216 | make_number (marker_position (w->start))); | ||
| 2217 | |||
| 2218 | goto done; | 8064 | goto done; |
| 2219 | } | 8065 | } |
| 2220 | else | 8066 | else |
| 2221 | cancel_my_columns (w); | 8067 | clear_glyph_matrix (w->desired_matrix); |
| 2222 | } | 8068 | } |
| 2223 | 8069 | ||
| 8070 | try_to_scroll: | ||
| 8071 | |||
| 2224 | XSETFASTINT (w->last_modified, 0); | 8072 | XSETFASTINT (w->last_modified, 0); |
| 2225 | XSETFASTINT (w->last_overlay_modified, 0); | 8073 | XSETFASTINT (w->last_overlay_modified, 0); |
| 8074 | |||
| 2226 | /* Redisplay the mode line. Select the buffer properly for that. */ | 8075 | /* Redisplay the mode line. Select the buffer properly for that. */ |
| 2227 | if (!update_mode_line) | 8076 | if (!update_mode_line) |
| 2228 | { | 8077 | { |
| @@ -2230,257 +8079,224 @@ redisplay_window (window, just_this_one, preserve_echo_area) | |||
| 2230 | { | 8079 | { |
| 2231 | set_buffer_temp (old); | 8080 | set_buffer_temp (old); |
| 2232 | set_buffer_internal_1 (XBUFFER (w->buffer)); | 8081 | set_buffer_internal_1 (XBUFFER (w->buffer)); |
| 8082 | really_switched_buffer = 1; | ||
| 2233 | } | 8083 | } |
| 2234 | update_mode_line = 1; | 8084 | update_mode_line = 1; |
| 2235 | w->update_mode_line = Qt; | 8085 | w->update_mode_line = Qt; |
| 2236 | } | 8086 | } |
| 2237 | 8087 | ||
| 2238 | /* Try to scroll by specified few lines */ | 8088 | /* Try to scroll by specified few lines. */ |
| 2239 | 8089 | if ((scroll_conservatively | |
| 2240 | if ((scroll_conservatively || scroll_step) | 8090 | || scroll_step |
| 8091 | || temp_scroll_step | ||
| 8092 | || NUMBERP (current_buffer->scroll_up_aggressively) | ||
| 8093 | || NUMBERP (current_buffer->scroll_down_aggressively)) | ||
| 2241 | && !current_buffer->clip_changed | 8094 | && !current_buffer->clip_changed |
| 2242 | && startp >= BEGV && startp <= ZV) | 8095 | && CHARPOS (startp) >= BEGV |
| 8096 | && CHARPOS (startp) <= ZV) | ||
| 2243 | { | 8097 | { |
| 2244 | int this_scroll_margin = scroll_margin; | 8098 | /* The function returns -1 if new fonts were loaded, 1 if |
| 2245 | int scroll_margin_pos, scroll_margin_bytepos; | 8099 | successful, 0 if not successful. */ |
| 2246 | int scroll_max = scroll_step; | 8100 | int rc = try_scrolling (window, just_this_one_p, |
| 2247 | Lisp_Object ltemp; | 8101 | scroll_conservatively, |
| 2248 | 8102 | scroll_step, | |
| 2249 | if (scroll_conservatively) | 8103 | temp_scroll_step); |
| 2250 | scroll_max = scroll_conservatively; | 8104 | if (rc > 0) |
| 2251 | 8105 | goto done; | |
| 2252 | /* Don't use a scroll margin that is negative or too large. */ | 8106 | else if (rc < 0) |
| 2253 | if (this_scroll_margin < 0) | 8107 | goto restore_buffers; |
| 2254 | this_scroll_margin = 0; | 8108 | } |
| 2255 | 8109 | ||
| 2256 | if (XINT (w->height) < 4 * this_scroll_margin) | 8110 | /* Finally, just choose place to start which centers point */ |
| 2257 | this_scroll_margin = XINT (w->height) / 4; | ||
| 2258 | 8111 | ||
| 2259 | ltemp = Fwindow_end (window, Qt); | 8112 | recenter: |
| 2260 | scroll_margin_pos = XINT (ltemp); | ||
| 2261 | 8113 | ||
| 2262 | if (this_scroll_margin) | 8114 | #if GLYPH_DEBUG |
| 2263 | { | 8115 | debug_method_add (w, "recenter"); |
| 2264 | pos = *vmotion (scroll_margin_pos, -this_scroll_margin, w); | 8116 | #endif |
| 2265 | scroll_margin_pos = pos.bufpos; | ||
| 2266 | scroll_margin_bytepos = pos.bytepos; | ||
| 2267 | } | ||
| 2268 | else | ||
| 2269 | scroll_margin_bytepos = CHAR_TO_BYTE (scroll_margin_pos); | ||
| 2270 | |||
| 2271 | if (PT >= scroll_margin_pos) | ||
| 2272 | { | ||
| 2273 | struct position pos; | ||
| 2274 | pos = *compute_motion (scroll_margin_pos, 0, 0, 0, | ||
| 2275 | PT, XFASTINT (w->height), 0, | ||
| 2276 | XFASTINT (w->width), XFASTINT (w->hscroll), | ||
| 2277 | pos_tab_offset (w, scroll_margin_pos, | ||
| 2278 | scroll_margin_bytepos), | ||
| 2279 | w); | ||
| 2280 | if (pos.vpos >= scroll_max) | ||
| 2281 | goto scroll_fail_1; | ||
| 2282 | |||
| 2283 | pos = *vmotion (startp, | ||
| 2284 | scroll_conservatively ? pos.vpos + 1 : scroll_step, | ||
| 2285 | w); | ||
| 2286 | |||
| 2287 | /* The old bottom-of-screen position is no longer valid. */ | ||
| 2288 | w->window_end_valid = Qnil; | ||
| 2289 | if (! NILP (Vwindow_scroll_functions)) | ||
| 2290 | { | ||
| 2291 | set_marker_both (w->start, Qnil, pos.bufpos, pos.bytepos); | ||
| 2292 | run_hook_with_args_2 (Qwindow_scroll_functions, window, | ||
| 2293 | make_number (pos.bufpos)); | ||
| 2294 | pos.bufpos = marker_position (w->start); | ||
| 2295 | } | ||
| 2296 | try_window (window, pos.bufpos); | ||
| 2297 | if (cursor_vpos >= 0) | ||
| 2298 | { | ||
| 2299 | if (!just_this_one || current_buffer->clip_changed | ||
| 2300 | || beg_unchanged < startp) | ||
| 2301 | /* Forget any recorded base line for line number display. */ | ||
| 2302 | w->base_line_number = Qnil; | ||
| 2303 | goto done; | ||
| 2304 | } | ||
| 2305 | else | ||
| 2306 | cancel_my_columns (w); | ||
| 2307 | } | ||
| 2308 | |||
| 2309 | scroll_margin_pos = startp; | ||
| 2310 | if (this_scroll_margin) | ||
| 2311 | { | ||
| 2312 | pos = *vmotion (scroll_margin_pos, this_scroll_margin, w); | ||
| 2313 | scroll_margin_pos = pos.bufpos; | ||
| 2314 | } | ||
| 2315 | if (PT < scroll_margin_pos) | ||
| 2316 | { | ||
| 2317 | struct position pos; | ||
| 2318 | pos = *compute_motion (PT, 0, 0, 0, | ||
| 2319 | scroll_margin_pos, XFASTINT (w->height), 0, | ||
| 2320 | XFASTINT (w->width), XFASTINT (w->hscroll), | ||
| 2321 | pos_tab_offset (w, PT, PT_BYTE), | ||
| 2322 | w); | ||
| 2323 | if (pos.vpos > scroll_max) | ||
| 2324 | goto scroll_fail_1; | ||
| 2325 | 8117 | ||
| 2326 | pos = *vmotion (startp, | 8118 | /* w->vscroll = 0; */ |
| 2327 | scroll_conservatively ? -pos.vpos : - scroll_step, | ||
| 2328 | w); | ||
| 2329 | 8119 | ||
| 2330 | /* The old bottom-of-screen position is no longer valid. */ | 8120 | /* Forget any previously recorded base line for line number display. */ |
| 2331 | w->window_end_valid = Qnil; | 8121 | if (!current_matrix_up_to_date_p |
| 2332 | if (! NILP (Vwindow_scroll_functions)) | 8122 | || current_buffer->clip_changed) |
| 2333 | { | 8123 | w->base_line_number = Qnil; |
| 2334 | set_marker_both (w->start, Qnil, pos.bufpos, pos.bytepos); | 8124 | |
| 2335 | run_hook_with_args_2 (Qwindow_scroll_functions, window, | 8125 | /* Move backward half the height of the window. */ |
| 2336 | make_number (pos.bufpos)); | 8126 | init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID); |
| 2337 | pos.bufpos = marker_position (w->start); | 8127 | it.current_y = it.last_visible_y; |
| 2338 | } | 8128 | move_it_vertically_backward (&it, it.last_visible_y / 2); |
| 2339 | try_window (window, pos.bufpos); | 8129 | xassert (IT_CHARPOS (it) >= BEGV); |
| 2340 | if (cursor_vpos >= 0) | 8130 | |
| 2341 | { | 8131 | /* The function move_it_vertically_backward may move over more |
| 2342 | if (!just_this_one || current_buffer->clip_changed | 8132 | than the specified y-distance. If it->w is small, e.g. a |
| 2343 | || beg_unchanged < startp) | 8133 | mini-buffer window, we may end up in front of the window's |
| 2344 | /* Forget any recorded base line for line number display. */ | 8134 | display area. Start displaying at the start of the line |
| 2345 | w->base_line_number = Qnil; | 8135 | containing PT in this case. */ |
| 2346 | goto done; | 8136 | if (it.current_y <= 0) |
| 2347 | } | 8137 | { |
| 2348 | else | 8138 | init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID); |
| 2349 | cancel_my_columns (w); | 8139 | move_it_vertically (&it, 0); |
| 2350 | } | 8140 | xassert (IT_CHARPOS (it) <= PT); |
| 2351 | scroll_fail_1: ; | 8141 | it.current_y = 0; |
| 2352 | } | 8142 | } |
| 2353 | 8143 | ||
| 2354 | #if 0 | 8144 | it.current_x = it.hpos = 0; |
| 2355 | if (scroll_step && ! scroll_margin && !current_buffer->clip_changed | 8145 | |
| 2356 | && startp >= BEGV && startp <= ZV) | 8146 | /* Set startp here explicitly in case that helps avoid an infinite loop |
| 8147 | in case the window-scroll-functions functions get errors. */ | ||
| 8148 | set_marker_both (w->start, Qnil, IT_CHARPOS (it), IT_BYTEPOS (it)); | ||
| 8149 | |||
| 8150 | /* Run scroll hooks. */ | ||
| 8151 | startp = run_window_scroll_functions (window, it.current.pos); | ||
| 8152 | |||
| 8153 | /* Redisplay the window. */ | ||
| 8154 | if (!current_matrix_up_to_date_p | ||
| 8155 | || windows_or_buffers_changed | ||
| 8156 | /* Don't use try_window_reusing_current_matrix in this case | ||
| 8157 | because it can have changed the buffer. */ | ||
| 8158 | || !NILP (Vwindow_scroll_functions) | ||
| 8159 | || !just_this_one_p | ||
| 8160 | || MINI_WINDOW_P (w) | ||
| 8161 | || !try_window_reusing_current_matrix (w)) | ||
| 8162 | try_window (window, startp); | ||
| 8163 | |||
| 8164 | /* If new fonts have been loaded (due to fontsets), give up. We | ||
| 8165 | have to start a new redisplay since we need to re-adjust glyph | ||
| 8166 | matrices. */ | ||
| 8167 | if (fonts_changed_p) | ||
| 8168 | goto restore_buffers; | ||
| 8169 | |||
| 8170 | /* If cursor did not appear assume that the middle of the window is | ||
| 8171 | in the first line of the window. Do it again with the next line. | ||
| 8172 | (Imagine a window of height 100, displaying two lines of height | ||
| 8173 | 60. Moving back 50 from it->last_visible_y will end in the first | ||
| 8174 | line.) */ | ||
| 8175 | if (w->cursor.vpos < 0) | ||
| 2357 | { | 8176 | { |
| 2358 | if (margin_call == 0) | 8177 | if (!NILP (w->window_end_valid) |
| 2359 | margin_call = (PT > startp ? 1 : -1); | 8178 | && PT >= Z - XFASTINT (w->window_end_pos)) |
| 2360 | if (margin_call > 0) | ||
| 2361 | { | 8179 | { |
| 2362 | pos = *vmotion (Z - XFASTINT (w->window_end_pos), scroll_step, w); | 8180 | clear_glyph_matrix (w->desired_matrix); |
| 2363 | if (pos.vpos >= height) | 8181 | move_it_by_lines (&it, 1, 0); |
| 2364 | goto scroll_fail; | 8182 | try_window (window, it.current.pos); |
| 2365 | } | 8183 | } |
| 2366 | 8184 | else if (PT < IT_CHARPOS (it)) | |
| 2367 | pos = *vmotion (startp, (margin_call < 0 ? - scroll_step : scroll_step), | ||
| 2368 | w); | ||
| 2369 | |||
| 2370 | if (PT >= pos.bufpos) | ||
| 2371 | { | 8185 | { |
| 2372 | /* The old bottom-of-screen position is no longer valid. */ | 8186 | clear_glyph_matrix (w->desired_matrix); |
| 2373 | w->window_end_valid = Qnil; | 8187 | move_it_by_lines (&it, -1, 0); |
| 2374 | 8188 | try_window (window, it.current.pos); | |
| 2375 | if (! NILP (Vwindow_scroll_functions)) | 8189 | } |
| 2376 | { | 8190 | else |
| 2377 | set_marker_both (w->start, Qnil, pos.bufpos, pos.bytepos); | 8191 | { |
| 2378 | run_hook_with_args_2 (Qwindow_scroll_functions, window, | 8192 | /* Not much we can do about it. */ |
| 2379 | make_number (pos.bufpos)); | ||
| 2380 | pos.bufpos = marker_position (w->start); | ||
| 2381 | } | ||
| 2382 | try_window (window, pos.bufpos); | ||
| 2383 | if (cursor_vpos >= 0) | ||
| 2384 | { | ||
| 2385 | if (!just_this_one || current_buffer->clip_changed | ||
| 2386 | || beg_unchanged < startp) | ||
| 2387 | /* Forget any recorded base line for line number display. */ | ||
| 2388 | w->base_line_number = Qnil; | ||
| 2389 | goto done; | ||
| 2390 | } | ||
| 2391 | else | ||
| 2392 | cancel_my_columns (w); | ||
| 2393 | } | 8193 | } |
| 2394 | scroll_fail: ; | ||
| 2395 | } | 8194 | } |
| 2396 | #endif | ||
| 2397 | |||
| 2398 | /* Finally, just choose place to start which centers point */ | ||
| 2399 | 8195 | ||
| 2400 | recenter: | 8196 | /* Consider the following case: Window starts at BEGV, there is |
| 2401 | /* Forget any previously recorded base line for line number display. */ | 8197 | invisible, intangible text at BEGV, so that display starts at |
| 2402 | w->base_line_number = Qnil; | 8198 | some point START > BEGV. It can happen that we are called with |
| 2403 | 8199 | PT somewhere between BEGV and START. Try to handle that case. */ | |
| 2404 | pos = *vmotion (PT, - (height / 2), w); | 8200 | if (w->cursor.vpos < 0) |
| 2405 | |||
| 2406 | /* The minibuffer is often just one line. Ordinary scrolling | ||
| 2407 | gives little overlap and looks bad. So show 20 chars before point. */ | ||
| 2408 | if (height == 1 | ||
| 2409 | && (pos.bufpos >= PT - minibuffer_scroll_overlap | ||
| 2410 | /* If we scrolled less than 1/2 line forward, we will | ||
| 2411 | get too much overlap, so change to the usual amount. */ | ||
| 2412 | || pos.bufpos < startp + width / 2) | ||
| 2413 | && PT > BEGV + minibuffer_scroll_overlap | ||
| 2414 | /* If we scrolled to an actual line boundary, | ||
| 2415 | that's different; don't ignore line boundaries. */ | ||
| 2416 | && FETCH_BYTE (pos.bytepos - 1) != '\n') | ||
| 2417 | { | 8201 | { |
| 2418 | pos.bufpos = PT - minibuffer_scroll_overlap; | 8202 | struct glyph_row *row = w->current_matrix->rows; |
| 2419 | pos.bytepos = CHAR_TO_BYTE (pos.bufpos); | 8203 | if (row->mode_line_p) |
| 8204 | ++row; | ||
| 8205 | set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0); | ||
| 2420 | } | 8206 | } |
| 2421 | 8207 | ||
| 2422 | /* Set startp here explicitly in case that helps avoid an infinite loop | 8208 | make_cursor_line_fully_visible (w); |
| 2423 | in case the window-scroll-functions functions get errors. */ | ||
| 2424 | set_marker_both (w->start, Qnil, pos.bufpos, pos.bytepos); | ||
| 2425 | 8209 | ||
| 2426 | /* The old bottom-of-screen position is no longer valid. */ | 8210 | SET_TEXT_POS_FROM_MARKER (startp, w->start); |
| 2427 | w->window_end_valid = Qnil; | 8211 | w->start_at_line_beg = ((CHARPOS (startp) == BEGV |
| 2428 | if (! NILP (Vwindow_scroll_functions)) | 8212 | || FETCH_BYTE (BYTEPOS (startp) - 1) == '\n') |
| 2429 | { | 8213 | ? Qt : Qnil); |
| 2430 | run_hook_with_args_2 (Qwindow_scroll_functions, window, | ||
| 2431 | make_number (pos.bufpos)); | ||
| 2432 | pos.bufpos = marker_position (w->start); | ||
| 2433 | pos.bytepos = marker_byte_position (w->start); | ||
| 2434 | } | ||
| 2435 | try_window (window, pos.bufpos); | ||
| 2436 | 8214 | ||
| 2437 | startp = marker_position (w->start); | 8215 | done: |
| 2438 | startp_byte = marker_byte_position (w->start); | ||
| 2439 | w->start_at_line_beg | ||
| 2440 | = (startp == BEGV || FETCH_BYTE (startp_byte - 1) == '\n') ? Qt : Qnil; | ||
| 2441 | 8216 | ||
| 2442 | done: | 8217 | /* Display the mode line, if we must. */ |
| 2443 | if ((update_mode_line | 8218 | if ((update_mode_line |
| 2444 | /* If window not full width, must redo its mode line | 8219 | /* If window not full width, must redo its mode line |
| 2445 | if the window to its side is being redone */ | 8220 | if (a) the window to its side is being redone and |
| 2446 | || (!just_this_one && !WINDOW_FULL_WIDTH_P (w)) | 8221 | (b) we do a frame-based redisplay. This is a consequence |
| 8222 | of how inverted lines are drawn in frame-based redisplay. */ | ||
| 8223 | || (!just_this_one_p | ||
| 8224 | && !FRAME_WINDOW_P (f) | ||
| 8225 | && !WINDOW_FULL_WIDTH_P (w)) | ||
| 8226 | /* Line number to display. */ | ||
| 2447 | || INTEGERP (w->base_line_pos) | 8227 | || INTEGERP (w->base_line_pos) |
| 8228 | /* Column number is displayed and different from the one displayed. */ | ||
| 2448 | || (!NILP (w->column_number_displayed) | 8229 | || (!NILP (w->column_number_displayed) |
| 2449 | && XFASTINT (w->column_number_displayed) != current_column ())) | 8230 | && XFASTINT (w->column_number_displayed) != current_column ())) |
| 2450 | && height != XFASTINT (w->height)) | 8231 | /* This means that the window has a mode line. */ |
| 8232 | && (WINDOW_WANTS_MODELINE_P (w) | ||
| 8233 | || WINDOW_WANTS_TOP_LINE_P (w))) | ||
| 2451 | { | 8234 | { |
| 2452 | FRAME_PTR oframe = selected_frame; | 8235 | display_mode_lines (w); |
| 2453 | if (!really_switched_buffer) | 8236 | |
| 8237 | /* If mode line height has changed, arrange for a thorough | ||
| 8238 | immediate redisplay using the correct mode line height. */ | ||
| 8239 | if (WINDOW_WANTS_MODELINE_P (w) | ||
| 8240 | && CURRENT_MODE_LINE_HEIGHT (w) != DESIRED_MODE_LINE_HEIGHT (w)) | ||
| 2454 | { | 8241 | { |
| 2455 | set_buffer_temp (old); | 8242 | fonts_changed_p = 1; |
| 2456 | set_buffer_internal_1 (XBUFFER (w->buffer)); | 8243 | MATRIX_MODE_LINE_ROW (w->current_matrix)->height |
| 2457 | really_switched_buffer = 1; | 8244 | = DESIRED_MODE_LINE_HEIGHT (w); |
| 8245 | } | ||
| 8246 | |||
| 8247 | /* If top line height has changed, arrange for a thorough | ||
| 8248 | immediate redisplay using the correct mode line height. */ | ||
| 8249 | if (WINDOW_WANTS_TOP_LINE_P (w) | ||
| 8250 | && CURRENT_TOP_LINE_HEIGHT (w) != DESIRED_TOP_LINE_HEIGHT (w)) | ||
| 8251 | { | ||
| 8252 | fonts_changed_p = 1; | ||
| 8253 | MATRIX_TOP_LINE_ROW (w->current_matrix)->height | ||
| 8254 | = DESIRED_TOP_LINE_HEIGHT (w); | ||
| 2458 | } | 8255 | } |
| 2459 | selected_frame = f; | 8256 | |
| 2460 | display_mode_line (w); | 8257 | if (fonts_changed_p) |
| 2461 | selected_frame = oframe; | 8258 | goto restore_buffers; |
| 2462 | } | 8259 | } |
| 2463 | if (! line_number_displayed | 8260 | |
| 2464 | && ! BUFFERP (w->base_line_pos)) | 8261 | if (!line_number_displayed |
| 8262 | && !BUFFERP (w->base_line_pos)) | ||
| 2465 | { | 8263 | { |
| 2466 | w->base_line_pos = Qnil; | 8264 | w->base_line_pos = Qnil; |
| 2467 | w->base_line_number = Qnil; | 8265 | w->base_line_number = Qnil; |
| 2468 | } | 8266 | } |
| 2469 | 8267 | ||
| 8268 | finish_menu_bars: | ||
| 8269 | |||
| 2470 | /* When we reach a frame's selected window, redo the frame's menu bar. */ | 8270 | /* When we reach a frame's selected window, redo the frame's menu bar. */ |
| 2471 | if (update_mode_line | 8271 | if (update_mode_line |
| 2472 | && (FRAME_WINDOW_P (f) | 8272 | && EQ (FRAME_SELECTED_WINDOW (f), window)) |
| 2473 | ? | 8273 | { |
| 8274 | int redisplay_menu_p = 0; | ||
| 8275 | |||
| 8276 | if (FRAME_WINDOW_P (f)) | ||
| 8277 | { | ||
| 2474 | #if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) | 8278 | #if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) |
| 2475 | FRAME_EXTERNAL_MENU_BAR (f) | 8279 | redisplay_menu_p = FRAME_EXTERNAL_MENU_BAR (f); |
| 2476 | #else | 8280 | #else |
| 2477 | FRAME_MENU_BAR_LINES (f) > 0 | 8281 | redisplay_menu_p = FRAME_MENU_BAR_LINES (f) > 0; |
| 2478 | #endif | 8282 | #endif |
| 2479 | : FRAME_MENU_BAR_LINES (f) > 0) | 8283 | } |
| 2480 | && EQ (FRAME_SELECTED_WINDOW (f), window)) | 8284 | else |
| 2481 | display_menu_bar (w); | 8285 | redisplay_menu_p = FRAME_MENU_BAR_LINES (f) > 0; |
| 8286 | |||
| 8287 | if (redisplay_menu_p) | ||
| 8288 | display_menu_bar (w); | ||
| 8289 | |||
| 8290 | #ifdef HAVE_WINDOW_SYSTEM | ||
| 8291 | if (WINDOWP (f->toolbar_window) | ||
| 8292 | && (FRAME_TOOLBAR_LINES (f) > 0 | ||
| 8293 | || auto_resize_toolbars_p)) | ||
| 8294 | redisplay_toolbar (f); | ||
| 8295 | #endif | ||
| 8296 | } | ||
| 2482 | 8297 | ||
| 2483 | finish_scroll_bars: | 8298 | finish_scroll_bars: |
| 8299 | |||
| 2484 | if (FRAME_HAS_VERTICAL_SCROLL_BARS (f)) | 8300 | if (FRAME_HAS_VERTICAL_SCROLL_BARS (f)) |
| 2485 | { | 8301 | { |
| 2486 | int start, end, whole; | 8302 | int start, end, whole; |
| @@ -2491,18 +8307,22 @@ done: | |||
| 2491 | indicating narrowing, and scrollbars which reflect only the | 8307 | indicating narrowing, and scrollbars which reflect only the |
| 2492 | visible region. | 8308 | visible region. |
| 2493 | 8309 | ||
| 2494 | Note that minibuffers sometimes aren't displaying any text. */ | 8310 | Note that mini-buffers sometimes aren't displaying any text. */ |
| 2495 | if (! MINI_WINDOW_P (w) | 8311 | if (! MINI_WINDOW_P (w) |
| 2496 | || (w == XWINDOW (minibuf_window) && ! echo_area_glyphs)) | 8312 | || (w == XWINDOW (minibuf_window) |
| 8313 | && !echo_area_glyphs | ||
| 8314 | && !STRINGP (echo_area_message))) | ||
| 2497 | { | 8315 | { |
| 2498 | whole = ZV - BEGV; | 8316 | whole = ZV - BEGV; |
| 2499 | start = marker_position (w->start) - BEGV; | 8317 | start = marker_position (w->start) - BEGV; |
| 2500 | /* I don't think this is guaranteed to be right. For the | 8318 | /* I don't think this is guaranteed to be right. For the |
| 2501 | moment, we'll pretend it is. */ | 8319 | moment, we'll pretend it is. */ |
| 2502 | end = (Z - XINT (w->window_end_pos)) - BEGV; | 8320 | end = (Z - XFASTINT (w->window_end_pos)) - BEGV; |
| 2503 | 8321 | ||
| 2504 | if (end < start) end = start; | 8322 | if (end < start) |
| 2505 | if (whole < (end - start)) whole = end - start; | 8323 | end = start; |
| 8324 | if (whole < (end - start)) | ||
| 8325 | whole = end - start; | ||
| 2506 | } | 8326 | } |
| 2507 | else | 8327 | else |
| 2508 | start = end = whole = 0; | 8328 | start = end = whole = 0; |
| @@ -2510,1829 +8330,2387 @@ done: | |||
| 2510 | /* Indicate what this scroll bar ought to be displaying now. */ | 8330 | /* Indicate what this scroll bar ought to be displaying now. */ |
| 2511 | (*set_vertical_scroll_bar_hook) (w, end - start, whole, start); | 8331 | (*set_vertical_scroll_bar_hook) (w, end - start, whole, start); |
| 2512 | 8332 | ||
| 2513 | /* Note that we actually used the scroll bar attached to this window, | 8333 | /* Note that we actually used the scroll bar attached to this |
| 2514 | so it shouldn't be deleted at the end of redisplay. */ | 8334 | window, so it shouldn't be deleted at the end of redisplay. */ |
| 2515 | (*redeem_scroll_bar_hook) (w); | 8335 | (*redeem_scroll_bar_hook) (w); |
| 2516 | } | 8336 | } |
| 2517 | 8337 | ||
| 2518 | TEMP_SET_PT_BOTH (opoint, opoint_byte); | 8338 | restore_buffers: |
| 8339 | |||
| 8340 | /* Restore current_buffer and value of point in it. */ | ||
| 8341 | TEMP_SET_PT_BOTH (CHARPOS (opoint), BYTEPOS (opoint)); | ||
| 2519 | if (really_switched_buffer) | 8342 | if (really_switched_buffer) |
| 2520 | set_buffer_internal_1 (old); | 8343 | set_buffer_internal_1 (old); |
| 2521 | else | 8344 | else |
| 2522 | set_buffer_temp (old); | 8345 | set_buffer_temp (old); |
| 2523 | TEMP_SET_PT_BOTH (lpoint, lpoint_byte); | 8346 | TEMP_SET_PT_BOTH (CHARPOS (lpoint), BYTEPOS (lpoint)); |
| 2524 | 8347 | ||
| 2525 | unbind_to (count, Qnil); | 8348 | unbind_to (count, Qnil); |
| 2526 | } | 8349 | } |
| 2527 | |||
| 2528 | /* Do full redisplay on one window, starting at position `pos'. */ | ||
| 2529 | 8350 | ||
| 2530 | static void | 8351 | |
| 8352 | /* Build the complete desired matrix of WINDOW with a window start | ||
| 8353 | buffer position POS. Value is non-zero if successful. It is zero | ||
| 8354 | if fonts were loaded during redisplay which makes re-adjusting | ||
| 8355 | glyph matrices necessary. */ | ||
| 8356 | |||
| 8357 | int | ||
| 2531 | try_window (window, pos) | 8358 | try_window (window, pos) |
| 2532 | Lisp_Object window; | 8359 | Lisp_Object window; |
| 2533 | register int pos; | 8360 | struct text_pos pos; |
| 2534 | { | 8361 | { |
| 2535 | register struct window *w = XWINDOW (window); | 8362 | struct window *w = XWINDOW (window); |
| 2536 | register int height = window_internal_height (w); | 8363 | struct it it; |
| 2537 | register int vpos = XFASTINT (w->top); | 8364 | struct glyph_row *last_text_row = NULL; |
| 2538 | register int last_text_vpos = vpos; | ||
| 2539 | FRAME_PTR f = XFRAME (w->frame); | ||
| 2540 | int width = window_internal_width (w) - 1; | ||
| 2541 | struct position val; | ||
| 2542 | |||
| 2543 | /* POS should never be out of range! */ | ||
| 2544 | if (pos < XBUFFER (w->buffer)->begv | ||
| 2545 | || pos > XBUFFER (w->buffer)->zv) | ||
| 2546 | abort (); | ||
| 2547 | 8365 | ||
| 2548 | if (XMARKER (w->start)->charpos != pos) | 8366 | /* Make POS the new window start. */ |
| 2549 | Fset_marker (w->start, make_number (pos), Qnil); | 8367 | set_marker_both (w->start, Qnil, CHARPOS (pos), BYTEPOS (pos)); |
| 2550 | 8368 | ||
| 2551 | cursor_vpos = -1; | 8369 | /* Mark cursor position as unknown. No overlay arrow seen. */ |
| 8370 | w->cursor.vpos = -1; | ||
| 2552 | overlay_arrow_seen = 0; | 8371 | overlay_arrow_seen = 0; |
| 2553 | zv_strings_seen = 0; | ||
| 2554 | val.hpos = XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0; | ||
| 2555 | val.ovstring_chars_done = 0; | ||
| 2556 | val.bytepos = marker_byte_position (w->start); | ||
| 2557 | val.tab_offset = pos_tab_offset (w, pos, val.bytepos); | ||
| 2558 | |||
| 2559 | while (--height >= 0) | ||
| 2560 | { | ||
| 2561 | val = *display_text_line (w, pos, val.bytepos, vpos, | ||
| 2562 | val.hpos, val.tab_offset, | ||
| 2563 | val.ovstring_chars_done); | ||
| 2564 | /* The following code is omitted because we maintain tab_offset | ||
| 2565 | in VAL. */ | ||
| 2566 | #if 0 | ||
| 2567 | tab_offset += width; | ||
| 2568 | if (val.vpos) tab_offset = 0; | ||
| 2569 | #endif /* 0 */ | ||
| 2570 | vpos++; | ||
| 2571 | if (pos != val.bufpos) | ||
| 2572 | { | ||
| 2573 | int invis = 0; | ||
| 2574 | #ifdef USE_TEXT_PROPERTIES | ||
| 2575 | Lisp_Object invis_prop; | ||
| 2576 | invis_prop = Fget_char_property (make_number (val.bufpos - 1), | ||
| 2577 | Qinvisible, window); | ||
| 2578 | invis = TEXT_PROP_MEANS_INVISIBLE (invis_prop); | ||
| 2579 | #endif | ||
| 2580 | 8372 | ||
| 2581 | last_text_vpos | 8373 | /* Initialize iterator and info to start at POS. */ |
| 2582 | /* Next line, unless prev line ended in end of buffer with no cr */ | 8374 | start_display (&it, w, pos); |
| 2583 | = vpos - (val.vpos | ||
| 2584 | && (FETCH_BYTE (val.bytepos - 1) != '\n' || invis)); | ||
| 2585 | } | ||
| 2586 | pos = val.bufpos; | ||
| 2587 | } | ||
| 2588 | 8375 | ||
| 2589 | /* If last line is continued in middle of character, | 8376 | /* Display all lines of W. */ |
| 2590 | include the split character in the text considered on the frame */ | 8377 | while (it.current_y < it.last_visible_y) |
| 2591 | if (val.hpos < (XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0)) | 8378 | { |
| 2592 | pos++; | 8379 | if (display_line (&it)) |
| 8380 | last_text_row = it.glyph_row - 1; | ||
| 8381 | if (fonts_changed_p) | ||
| 8382 | return 0; | ||
| 8383 | } | ||
| 2593 | 8384 | ||
| 2594 | /* If bottom just moved off end of frame, change mode line percentage. */ | 8385 | /* If bottom moved off end of frame, change mode line percentage. */ |
| 2595 | if (XFASTINT (w->window_end_pos) == 0 | 8386 | if (XFASTINT (w->window_end_pos) <= 0 |
| 2596 | && Z != pos) | 8387 | && Z != IT_CHARPOS (it)) |
| 2597 | w->update_mode_line = Qt; | 8388 | w->update_mode_line = Qt; |
| 2598 | 8389 | ||
| 2599 | /* Say where last char on frame will be, once redisplay is finished. */ | 8390 | /* Set window_end_pos to the offset of the last character displayed |
| 2600 | XSETFASTINT (w->window_end_pos, Z - pos); | 8391 | on the window from the end of current_buffer. Set |
| 2601 | XSETFASTINT (w->window_end_vpos, last_text_vpos - XFASTINT (w->top)); | 8392 | window_end_vpos to its row number. */ |
| 8393 | if (last_text_row) | ||
| 8394 | { | ||
| 8395 | xassert (MATRIX_ROW_DISPLAYS_TEXT_P (last_text_row)); | ||
| 8396 | w->window_end_bytepos | ||
| 8397 | = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row); | ||
| 8398 | XSETFASTINT (w->window_end_pos, | ||
| 8399 | Z - MATRIX_ROW_END_CHARPOS (last_text_row)); | ||
| 8400 | XSETFASTINT (w->window_end_vpos, | ||
| 8401 | MATRIX_ROW_VPOS (last_text_row, w->desired_matrix)); | ||
| 8402 | xassert (MATRIX_ROW (w->desired_matrix, XFASTINT (w->window_end_vpos)) | ||
| 8403 | ->displays_text_p); | ||
| 8404 | } | ||
| 8405 | else | ||
| 8406 | { | ||
| 8407 | w->window_end_bytepos = 0; | ||
| 8408 | XSETFASTINT (w->window_end_pos, 0); | ||
| 8409 | XSETFASTINT (w->window_end_vpos, 0); | ||
| 8410 | } | ||
| 8411 | |||
| 2602 | /* But that is not valid info until redisplay finishes. */ | 8412 | /* But that is not valid info until redisplay finishes. */ |
| 2603 | w->window_end_valid = Qnil; | 8413 | w->window_end_valid = Qnil; |
| 8414 | return 1; | ||
| 2604 | } | 8415 | } |
| 8416 | |||
| 8417 | |||
| 2605 | 8418 | ||
| 2606 | /* Try to redisplay when buffer is modified locally, | 8419 | /************************************************************************ |
| 2607 | computing insert/delete line to preserve text outside | 8420 | Window redisplay reusing current matrix when buffer has not changed |
| 2608 | the bounds of the changes. | 8421 | ************************************************************************/ |
| 2609 | Return 1 if successful, 0 if if cannot tell what to do, | 8422 | |
| 2610 | or -1 to tell caller to find a new window start, | 8423 | /* Try redisplay of window W showing an unchanged buffer with a |
| 2611 | or -2 to tell caller to do normal redisplay with same window start. */ | 8424 | different window start than the last time it was displayed by |
| 8425 | reusing its current matrix. Value is non-zero if successful. | ||
| 8426 | W->start is the new window start. */ | ||
| 2612 | 8427 | ||
| 2613 | static int | 8428 | static int |
| 2614 | try_window_id (window) | 8429 | try_window_reusing_current_matrix (w) |
| 2615 | Lisp_Object window; | 8430 | struct window *w; |
| 2616 | { | 8431 | { |
| 2617 | int pos, pos_byte; | 8432 | struct frame *f = XFRAME (w->frame); |
| 2618 | int opoint, opoint_byte; | 8433 | struct glyph_row *row, *bottom_row; |
| 2619 | register struct window *w = XWINDOW (window); | 8434 | struct it it; |
| 2620 | register int height = window_internal_height (w); | 8435 | struct run run; |
| 2621 | FRAME_PTR f = XFRAME (w->frame); | 8436 | struct text_pos start, new_start; |
| 2622 | int top = XFASTINT (w->top); | 8437 | int nrows_scrolled, i; |
| 2623 | int start = marker_position (w->start); | 8438 | struct glyph_row *last_text_row; |
| 2624 | int width = window_internal_width (w) - 1; | 8439 | struct glyph_row *last_reused_text_row; |
| 2625 | int hscroll = XINT (w->hscroll); | 8440 | struct glyph_row *start_row; |
| 2626 | int lmargin = hscroll > 0 ? 1 - hscroll : 0; | 8441 | int start_vpos, min_y, max_y; |
| 2627 | int did_motion; | 8442 | |
| 2628 | register int vpos; | 8443 | /* Right now this function doesn't handle terminal frames. */ |
| 2629 | register int i, tem; | 8444 | if (!FRAME_WINDOW_P (f)) |
| 2630 | int last_text_vpos = 0; | 8445 | return 0; |
| 2631 | int stop_vpos; | ||
| 2632 | int selective = (INTEGERP (current_buffer->selective_display) | ||
| 2633 | ? XINT (current_buffer->selective_display) | ||
| 2634 | : !NILP (current_buffer->selective_display) ? -1 : 0); | ||
| 2635 | struct position val, bp, ep, xp, pp; | ||
| 2636 | int scroll_amount = 0; | ||
| 2637 | int delta; | ||
| 2638 | int epto, old_tick; | ||
| 2639 | |||
| 2640 | int start_byte = marker_byte_position (w->start); | ||
| 2641 | |||
| 2642 | if (GPT - BEG < beg_unchanged) | ||
| 2643 | beg_unchanged = GPT - BEG; | ||
| 2644 | if (Z - GPT < end_unchanged) | ||
| 2645 | end_unchanged = Z - GPT; | ||
| 2646 | |||
| 2647 | if (beg_unchanged + BEG < start) | ||
| 2648 | return 0; /* Give up if changes go above top of window */ | ||
| 2649 | |||
| 2650 | /* Find position before which nothing is changed. */ | ||
| 2651 | bp = *compute_motion (start, 0, lmargin, 0, | ||
| 2652 | min (ZV, beg_unchanged + BEG), height, | ||
| 2653 | /* BUG FIX: See the comment of | ||
| 2654 | Fpos_visible_in_window_p (window.c). */ | ||
| 2655 | - (1 << (BITS_PER_SHORT - 1)), | ||
| 2656 | width, hscroll, | ||
| 2657 | pos_tab_offset (w, start, start_byte), | ||
| 2658 | w); | ||
| 2659 | if (bp.vpos >= height) | ||
| 2660 | { | ||
| 2661 | if (PT < bp.bufpos) | ||
| 2662 | { | ||
| 2663 | /* All changes are beyond the window end, and point is on the screen. | ||
| 2664 | We don't need to change the text at all. | ||
| 2665 | But we need to update window_end_pos to account for | ||
| 2666 | any change in buffer size. */ | ||
| 2667 | bp = *compute_motion (start, 0, lmargin, 0, | ||
| 2668 | ZV, height, | ||
| 2669 | /* BUG FIX: See the comment of | ||
| 2670 | Fpos_visible_in_window_p() (window.c). */ | ||
| 2671 | - (1 << (BITS_PER_SHORT - 1)), | ||
| 2672 | width, hscroll, | ||
| 2673 | pos_tab_offset (w, start, start_byte), w); | ||
| 2674 | XSETFASTINT (w->window_end_vpos, height); | ||
| 2675 | XSETFASTINT (w->window_end_pos, Z - bp.bufpos); | ||
| 2676 | goto findpoint; | ||
| 2677 | } | ||
| 2678 | return 0; | ||
| 2679 | } | ||
| 2680 | |||
| 2681 | vpos = bp.vpos; | ||
| 2682 | |||
| 2683 | /* Find beginning of that frame line. Must display from there. */ | ||
| 2684 | bp = *vmotion (bp.bufpos, 0, w); | ||
| 2685 | |||
| 2686 | pos = bp.bufpos; | ||
| 2687 | pos_byte = bp.bytepos; | ||
| 2688 | val.hpos = lmargin; | ||
| 2689 | if (pos < start) | ||
| 2690 | return -1; | ||
| 2691 | 8446 | ||
| 2692 | did_motion = 0; | 8447 | /* Can't do this if region may have changed. */ |
| 2693 | /* If about to start displaying at the beginning of a continuation line, | 8448 | if ((!NILP (Vtransient_mark_mode) |
| 2694 | really start with previous frame line, in case it was not | 8449 | && !NILP (current_buffer->mark_active)) |
| 2695 | continued when last redisplayed */ | 8450 | || !NILP (w->region_showing)) |
| 2696 | if ((bp.contin && bp.bufpos - 1 == beg_unchanged && vpos > 0) | 8451 | return 0; |
| 2697 | || | ||
| 2698 | /* Likewise if we have to worry about selective display. */ | ||
| 2699 | (selective > 0 && bp.bufpos - 1 == beg_unchanged && vpos > 0)) | ||
| 2700 | { | ||
| 2701 | bp = *vmotion (bp.bufpos, -1, w); | ||
| 2702 | --vpos; | ||
| 2703 | pos = bp.bufpos; | ||
| 2704 | pos_byte = bp.bytepos; | ||
| 2705 | } | ||
| 2706 | val.tab_offset = bp.tab_offset; /* Update tab offset. */ | ||
| 2707 | |||
| 2708 | if (bp.contin && bp.hpos != lmargin) | ||
| 2709 | { | ||
| 2710 | val.hpos = bp.prevhpos - width + lmargin; | ||
| 2711 | val.tab_offset = bp.tab_offset + width - bp.prevhpos; | ||
| 2712 | did_motion = 1; | ||
| 2713 | DEC_BOTH (pos, pos_byte); | ||
| 2714 | } | ||
| 2715 | |||
| 2716 | bp.vpos = vpos; | ||
| 2717 | |||
| 2718 | /* Find first visible newline after which no more is changed. */ | ||
| 2719 | opoint = PT, opoint_byte = PT_BYTE; | ||
| 2720 | TEMP_SET_PT (Z - max (end_unchanged, Z - ZV)); | ||
| 2721 | scan_newline (PT, PT_BYTE, ZV, ZV_BYTE, 1, 1); | ||
| 2722 | if (selective > 0) | ||
| 2723 | while (PT < ZV - 1 && indented_beyond_p (PT, PT_BYTE, selective)) | ||
| 2724 | scan_newline (PT, PT_BYTE, ZV, ZV_BYTE, 1, 1); | ||
| 2725 | tem = PT; | ||
| 2726 | TEMP_SET_PT_BOTH (opoint, opoint_byte); | ||
| 2727 | |||
| 2728 | /* Compute the cursor position after that newline. */ | ||
| 2729 | ep = *compute_motion (pos, vpos, val.hpos, did_motion, tem, | ||
| 2730 | height, - (1 << (BITS_PER_SHORT - 1)), | ||
| 2731 | width, hscroll, | ||
| 2732 | /* We have tab offset in VAL, use it. */ | ||
| 2733 | val.tab_offset, w); | ||
| 2734 | |||
| 2735 | /* If changes reach past the text available on the frame, | ||
| 2736 | just display rest of frame. */ | ||
| 2737 | if (ep.bufpos > Z - XFASTINT (w->window_end_pos)) | ||
| 2738 | stop_vpos = height; | ||
| 2739 | else | ||
| 2740 | stop_vpos = ep.vpos; | ||
| 2741 | |||
| 2742 | /* If no newline before ep, the line ep is on includes some changes | ||
| 2743 | that must be displayed. Make sure we don't stop before it. */ | ||
| 2744 | /* Also, if changes reach all the way until ep.bufpos, | ||
| 2745 | it is possible that something was deleted after the | ||
| 2746 | newline before it, so the following line must be redrawn. */ | ||
| 2747 | if (stop_vpos == ep.vpos | ||
| 2748 | && (ep.bufpos == BEGV | ||
| 2749 | || FETCH_BYTE (ep.bytepos - 1) != '\n' | ||
| 2750 | || ep.bufpos == Z - end_unchanged)) | ||
| 2751 | stop_vpos = ep.vpos + 1; | ||
| 2752 | |||
| 2753 | cursor_vpos = -1; | ||
| 2754 | overlay_arrow_seen = 0; | ||
| 2755 | zv_strings_seen = 0; | ||
| 2756 | |||
| 2757 | /* If changes do not reach to bottom of window, | ||
| 2758 | figure out how much to scroll the rest of the window */ | ||
| 2759 | if (stop_vpos < height) | ||
| 2760 | { | ||
| 2761 | /* Now determine how far up or down the rest of the window has moved */ | ||
| 2762 | xp = *compute_motion (ep.bufpos, ep.vpos, ep.hpos, 1, | ||
| 2763 | Z - XFASTINT (w->window_end_pos), | ||
| 2764 | /* Don't care for VPOS... */ | ||
| 2765 | 1 << (BITS_PER_SHORT - 1), | ||
| 2766 | /* ... nor HPOS. */ | ||
| 2767 | 1 << (BITS_PER_SHORT - 1), | ||
| 2768 | width, hscroll, ep.tab_offset, w); | ||
| 2769 | scroll_amount = xp.vpos - XFASTINT (w->window_end_vpos); | ||
| 2770 | |||
| 2771 | /* Is everything on frame below the changes whitespace? | ||
| 2772 | If so, no scrolling is really necessary. */ | ||
| 2773 | for (i = ep.bytepos; i < xp.bytepos; i++) | ||
| 2774 | { | ||
| 2775 | tem = FETCH_BYTE (i); | ||
| 2776 | if (tem != ' ' && tem != '\n' && tem != '\t') | ||
| 2777 | break; | ||
| 2778 | } | ||
| 2779 | if (i == xp.bytepos) | ||
| 2780 | return -2; | ||
| 2781 | 8452 | ||
| 2782 | XSETFASTINT (w->window_end_vpos, | 8453 | /* If top-line visibility has changed, give up. */ |
| 2783 | XFASTINT (w->window_end_vpos) + scroll_amount); | 8454 | if (WINDOW_WANTS_TOP_LINE_P (w) |
| 8455 | != MATRIX_TOP_LINE_ROW (w->current_matrix)->mode_line_p) | ||
| 8456 | return 0; | ||
| 8457 | |||
| 8458 | /* Give up if old or new display is scrolled vertically. We could | ||
| 8459 | make this function handle this, but right now it doesn't. */ | ||
| 8460 | start_row = MATRIX_FIRST_TEXT_ROW (w->current_matrix); | ||
| 8461 | if (w->vscroll || MATRIX_ROW_PARTIALLY_VISIBLE_P (start_row)) | ||
| 8462 | return 0; | ||
| 8463 | |||
| 8464 | /* The variable new_start now holds the new window start. The old | ||
| 8465 | start `start' can be determined from the current matrix. */ | ||
| 8466 | SET_TEXT_POS_FROM_MARKER (new_start, w->start); | ||
| 8467 | start = start_row->start.pos; | ||
| 8468 | start_vpos = MATRIX_ROW_VPOS (start_row, w->current_matrix); | ||
| 2784 | 8469 | ||
| 2785 | /* Before doing any scrolling, verify that point will be on frame. */ | 8470 | /* Clear the desired matrix for the display below. */ |
| 2786 | if (PT > ep.bufpos && !(PT <= xp.bufpos && xp.vpos < height)) | 8471 | clear_glyph_matrix (w->desired_matrix); |
| 8472 | |||
| 8473 | if (CHARPOS (new_start) <= CHARPOS (start)) | ||
| 8474 | { | ||
| 8475 | int first_row_y; | ||
| 8476 | |||
| 8477 | IF_DEBUG (debug_method_add (w, "twu1")); | ||
| 8478 | |||
| 8479 | /* Display up to a row that can be reused. The variable | ||
| 8480 | last_text_row is set to the last row displayed that displays | ||
| 8481 | text. */ | ||
| 8482 | start_display (&it, w, new_start); | ||
| 8483 | first_row_y = it.current_y; | ||
| 8484 | w->cursor.vpos = -1; | ||
| 8485 | last_text_row = last_reused_text_row = NULL; | ||
| 8486 | while (it.current_y < it.last_visible_y | ||
| 8487 | && IT_CHARPOS (it) < CHARPOS (start) | ||
| 8488 | && !fonts_changed_p) | ||
| 8489 | if (display_line (&it)) | ||
| 8490 | last_text_row = it.glyph_row - 1; | ||
| 8491 | |||
| 8492 | /* A value of current_y < last_visible_y means that we stopped | ||
| 8493 | at the previous window start, which in turn means that we | ||
| 8494 | have at least one reusable row. */ | ||
| 8495 | if (it.current_y < it.last_visible_y) | ||
| 2787 | { | 8496 | { |
| 2788 | if (PT <= xp.bufpos) | 8497 | nrows_scrolled = it.vpos; |
| 8498 | |||
| 8499 | /* Find PT if not already found in the lines displayed. */ | ||
| 8500 | if (w->cursor.vpos < 0) | ||
| 2789 | { | 8501 | { |
| 2790 | pp = *compute_motion (ep.bufpos, ep.vpos, ep.hpos, 1, | 8502 | int dy = it.current_y - first_row_y; |
| 2791 | PT, height, - (1 << (BITS_PER_SHORT - 1)), | 8503 | |
| 2792 | width, hscroll, | 8504 | row = MATRIX_FIRST_TEXT_ROW (w->current_matrix); |
| 2793 | /* We have tab offset in EP, use it. */ | 8505 | while (MATRIX_ROW_DISPLAYS_TEXT_P (row)) |
| 2794 | ep.tab_offset, w); | 8506 | { |
| 8507 | if (PT >= MATRIX_ROW_START_CHARPOS (row) | ||
| 8508 | && PT < MATRIX_ROW_END_CHARPOS (row)) | ||
| 8509 | { | ||
| 8510 | set_cursor_from_row (w, row, w->current_matrix, 0, 0, | ||
| 8511 | dy, nrows_scrolled); | ||
| 8512 | break; | ||
| 8513 | } | ||
| 8514 | |||
| 8515 | if (MATRIX_ROW_BOTTOM_Y (row) + dy >= it.last_visible_y) | ||
| 8516 | break; | ||
| 8517 | |||
| 8518 | ++row; | ||
| 8519 | } | ||
| 8520 | |||
| 8521 | /* Give up if point was not found. This shouldn't | ||
| 8522 | happen often; not more often than with try_window | ||
| 8523 | itself. */ | ||
| 8524 | if (w->cursor.vpos < 0) | ||
| 8525 | { | ||
| 8526 | clear_glyph_matrix (w->desired_matrix); | ||
| 8527 | return 0; | ||
| 8528 | } | ||
| 2795 | } | 8529 | } |
| 2796 | else | 8530 | |
| 8531 | /* Scroll the display. Do it before the current matrix is | ||
| 8532 | changed. The problem here is that update has not yet | ||
| 8533 | run, i.e. part of the current matrix is not up to date. | ||
| 8534 | scroll_run_hook will clear the cursor, and use the | ||
| 8535 | current matrix to get the height of the row the cursor is | ||
| 8536 | in. */ | ||
| 8537 | run.current_y = first_row_y; | ||
| 8538 | run.desired_y = it.current_y; | ||
| 8539 | run.height = it.last_visible_y - it.current_y; | ||
| 8540 | if (run.height > 0) | ||
| 2797 | { | 8541 | { |
| 2798 | pp = *compute_motion (xp.bufpos, xp.vpos, xp.hpos, 1, | 8542 | update_begin (f); |
| 2799 | PT, height, - (1 << (BITS_PER_SHORT - 1)), | 8543 | rif->update_window_begin_hook (w); |
| 2800 | width, hscroll, | 8544 | rif->scroll_run_hook (w, &run); |
| 2801 | /* We have tab offset in XP, use it. */ | 8545 | rif->update_window_end_hook (w, 0); |
| 2802 | xp.tab_offset, w); | 8546 | update_end (f); |
| 2803 | } | 8547 | } |
| 2804 | if (pp.bufpos < PT || pp.vpos == height) | 8548 | |
| 2805 | return 0; | 8549 | /* Shift current matrix down by nrows_scrolled lines. */ |
| 2806 | cursor_vpos = pp.vpos + top; | 8550 | bottom_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w); |
| 2807 | cursor_hpos = WINDOW_LEFT_MARGIN (w) + minmax (0, pp.hpos, width); | 8551 | rotate_matrix (w->current_matrix, |
| 2808 | } | 8552 | start_vpos, |
| 2809 | 8553 | MATRIX_ROW_VPOS (bottom_row, w->current_matrix), | |
| 2810 | if (stop_vpos - scroll_amount >= height | 8554 | nrows_scrolled); |
| 2811 | || ep.bufpos == xp.bufpos) | 8555 | |
| 2812 | { | 8556 | /* Disable lines not reused. */ |
| 2813 | if (scroll_amount < 0) | 8557 | for (i = 0; i < it.vpos; ++i) |
| 2814 | stop_vpos -= scroll_amount; | 8558 | MATRIX_ROW (w->current_matrix, i)->enabled_p = 0; |
| 2815 | scroll_amount = 0; | 8559 | |
| 2816 | /* In this path, we have altered window_end_vpos | 8560 | /* Re-compute Y positions. */ |
| 2817 | and not left it negative. | 8561 | row = MATRIX_FIRST_TEXT_ROW (w->current_matrix) + nrows_scrolled; |
| 2818 | We must make sure that, in case display is preempted | 8562 | min_y = WINDOW_DISPLAY_TOP_LINE_HEIGHT (w); |
| 2819 | before the frame changes to reflect what we do here, | 8563 | max_y = it.last_visible_y; |
| 2820 | further updates will not come to try_window_id | 8564 | while (row < bottom_row) |
| 2821 | and assume the frame and window_end_vpos match. */ | ||
| 2822 | blank_end_of_window = 1; | ||
| 2823 | } | ||
| 2824 | else if (!scroll_amount) | ||
| 2825 | { | ||
| 2826 | /* Even if we don't need to scroll, we must adjust the | ||
| 2827 | charstarts of subsequent lines (that we won't redisplay) | ||
| 2828 | according to the amount of text inserted or deleted. */ | ||
| 2829 | int oldpos = FRAME_CURRENT_GLYPHS (f)->charstarts[ep.vpos + top][0]; | ||
| 2830 | int adjust = ep.bufpos - oldpos; | ||
| 2831 | adjust_window_charstarts (w, ep.vpos + top - 1, adjust); | ||
| 2832 | } | ||
| 2833 | else if (bp.bufpos == Z - end_unchanged) | ||
| 2834 | { | ||
| 2835 | /* If reprinting everything is nearly as fast as scrolling, | ||
| 2836 | don't bother scrolling. Can happen if lines are short. */ | ||
| 2837 | if (scroll_cost (f, bp.vpos + top - scroll_amount, | ||
| 2838 | top + height - max (0, scroll_amount), | ||
| 2839 | scroll_amount) | ||
| 2840 | > xp.bufpos - bp.bufpos - 20) | ||
| 2841 | /* Return "try normal display with same window-start." | ||
| 2842 | Too bad we can't prevent further scroll-thinking. */ | ||
| 2843 | return -2; | ||
| 2844 | /* If pure deletion, scroll up as many lines as possible. | ||
| 2845 | In common case of killing a line, this can save the | ||
| 2846 | following line from being overwritten by scrolling | ||
| 2847 | and therefore having to be redrawn. */ | ||
| 2848 | tem = scroll_frame_lines (f, bp.vpos + top - scroll_amount, | ||
| 2849 | top + height - max (0, scroll_amount), | ||
| 2850 | scroll_amount, bp.bufpos); | ||
| 2851 | if (!tem) | ||
| 2852 | stop_vpos = height; | ||
| 2853 | else | ||
| 2854 | { | 8565 | { |
| 2855 | /* scroll_frame_lines did not properly adjust subsequent | 8566 | row->y = it.current_y; |
| 2856 | lines' charstarts in the case where the text of the | 8567 | |
| 2857 | screen line at bp.vpos has changed. | 8568 | if (row->y < min_y) |
| 2858 | (This can happen in a deletion that ends in mid-line.) | 8569 | row->visible_height = row->height - (min_y - row->y); |
| 2859 | To adjust properly, we need to make things consistent | 8570 | else if (row->y + row->height > max_y) |
| 2860 | at the position ep. | 8571 | row->visible_height |
| 2861 | So do a second adjust to make that happen. | 8572 | = row->height - (row->y + row->height - max_y); |
| 2862 | Note that stop_vpos >= ep.vpos, so it is sufficient | 8573 | else |
| 2863 | to update the charstarts for lines at ep.vpos and below. */ | 8574 | row->visible_height = row->height; |
| 2864 | int oldstart | 8575 | |
| 2865 | = FRAME_CURRENT_GLYPHS (f)->charstarts[ep.vpos + top][0]; | 8576 | it.current_y += row->height; |
| 2866 | adjust_window_charstarts (w, ep.vpos + top - 1, | 8577 | ++it.vpos; |
| 2867 | ep.bufpos - oldstart); | 8578 | |
| 8579 | if (MATRIX_ROW_DISPLAYS_TEXT_P (row)) | ||
| 8580 | last_reused_text_row = row; | ||
| 8581 | if (MATRIX_ROW_BOTTOM_Y (row) >= it.last_visible_y) | ||
| 8582 | break; | ||
| 8583 | ++row; | ||
| 2868 | } | 8584 | } |
| 2869 | } | 8585 | } |
| 2870 | else if (scroll_amount) | 8586 | |
| 8587 | /* Update window_end_pos etc.; last_reused_text_row is the last | ||
| 8588 | reused row from the current matrix containing text, if any. | ||
| 8589 | The value of last_text_row is the last displayed line | ||
| 8590 | containing text. */ | ||
| 8591 | if (last_reused_text_row) | ||
| 2871 | { | 8592 | { |
| 2872 | /* If reprinting everything is nearly as fast as scrolling, | 8593 | w->window_end_bytepos |
| 2873 | don't bother scrolling. Can happen if lines are short. */ | 8594 | = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_reused_text_row); |
| 2874 | /* Note that if scroll_amount > 0, xp.bufpos - bp.bufpos is an | 8595 | XSETFASTINT (w->window_end_pos, |
| 2875 | overestimate of cost of reprinting, since xp.bufpos | 8596 | Z - MATRIX_ROW_END_CHARPOS (last_reused_text_row)); |
| 2876 | would end up below the bottom of the window. */ | 8597 | XSETFASTINT (w->window_end_vpos, |
| 2877 | if (scroll_cost (f, ep.vpos + top - scroll_amount, | 8598 | MATRIX_ROW_VPOS (last_reused_text_row, |
| 2878 | top + height - max (0, scroll_amount), | 8599 | w->current_matrix)); |
| 2879 | scroll_amount) | ||
| 2880 | > xp.bufpos - ep.bufpos - 20) | ||
| 2881 | /* Return "try normal display with same window-start." | ||
| 2882 | Too bad we can't prevent further scroll-thinking. */ | ||
| 2883 | return -2; | ||
| 2884 | tem = scroll_frame_lines (f, ep.vpos + top - scroll_amount, | ||
| 2885 | top + height - max (0, scroll_amount), | ||
| 2886 | scroll_amount, ep.bufpos); | ||
| 2887 | if (!tem) stop_vpos = height; | ||
| 2888 | } | 8600 | } |
| 2889 | } | 8601 | else if (last_text_row) |
| 8602 | { | ||
| 8603 | w->window_end_bytepos | ||
| 8604 | = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row); | ||
| 8605 | XSETFASTINT (w->window_end_pos, | ||
| 8606 | Z - MATRIX_ROW_END_CHARPOS (last_text_row)); | ||
| 8607 | XSETFASTINT (w->window_end_vpos, | ||
| 8608 | MATRIX_ROW_VPOS (last_text_row, w->desired_matrix)); | ||
| 8609 | } | ||
| 8610 | else | ||
| 8611 | { | ||
| 8612 | /* This window must be completely empty. */ | ||
| 8613 | w->window_end_bytepos = 0; | ||
| 8614 | XSETFASTINT (w->window_end_pos, 0); | ||
| 8615 | XSETFASTINT (w->window_end_vpos, 0); | ||
| 8616 | } | ||
| 8617 | w->window_end_valid = Qnil; | ||
| 2890 | 8618 | ||
| 2891 | /* In any case, do not display past bottom of window */ | 8619 | /* Update hint: don't try scrolling again in update_window. */ |
| 2892 | if (stop_vpos >= height) | 8620 | w->desired_matrix->no_scrolling_p = 1; |
| 2893 | { | 8621 | |
| 2894 | stop_vpos = height; | 8622 | #if GLYPH_DEBUG |
| 2895 | scroll_amount = 0; | 8623 | debug_method_add (w, "try_window_reusing_current_matrix 1"); |
| 8624 | #endif | ||
| 8625 | return 1; | ||
| 2896 | } | 8626 | } |
| 8627 | else if (CHARPOS (new_start) > CHARPOS (start)) | ||
| 8628 | { | ||
| 8629 | struct glyph_row *pt_row, *row; | ||
| 8630 | struct glyph_row *first_reusable_row; | ||
| 8631 | struct glyph_row *first_row_to_display; | ||
| 8632 | int dy; | ||
| 8633 | int yb = window_text_bottom_y (w); | ||
| 8634 | |||
| 8635 | IF_DEBUG (debug_method_add (w, "twu2")); | ||
| 8636 | |||
| 8637 | /* Find the row starting at new_start, if there is one. Don't | ||
| 8638 | reuse a partially visible line at the end. */ | ||
| 8639 | first_reusable_row = MATRIX_FIRST_TEXT_ROW (w->current_matrix); | ||
| 8640 | while (first_reusable_row->enabled_p | ||
| 8641 | && MATRIX_ROW_BOTTOM_Y (first_reusable_row) < yb | ||
| 8642 | && (MATRIX_ROW_START_CHARPOS (first_reusable_row) | ||
| 8643 | < CHARPOS (new_start))) | ||
| 8644 | ++first_reusable_row; | ||
| 8645 | |||
| 8646 | /* Give up if there is no row to reuse. */ | ||
| 8647 | if (MATRIX_ROW_BOTTOM_Y (first_reusable_row) >= yb | ||
| 8648 | || !first_reusable_row->enabled_p) | ||
| 8649 | return 0; | ||
| 8650 | |||
| 8651 | /* The row we found must start at new_start, or else something | ||
| 8652 | is broken. */ | ||
| 8653 | xassert (MATRIX_ROW_START_CHARPOS (first_reusable_row) | ||
| 8654 | == CHARPOS (new_start)); | ||
| 8655 | |||
| 8656 | /* We can reuse fully visible rows beginning with | ||
| 8657 | first_reusable_row to the end of the window. Set | ||
| 8658 | first_row_to_display to the first row that cannot be reused. | ||
| 8659 | Set pt_row to the row containing point, if there is any. */ | ||
| 8660 | first_row_to_display = first_reusable_row; | ||
| 8661 | pt_row = NULL; | ||
| 8662 | while (MATRIX_ROW_BOTTOM_Y (first_row_to_display) < yb) | ||
| 8663 | { | ||
| 8664 | if (PT >= MATRIX_ROW_START_CHARPOS (first_row_to_display) | ||
| 8665 | && PT < MATRIX_ROW_END_CHARPOS (first_row_to_display)) | ||
| 8666 | pt_row = first_row_to_display; | ||
| 2897 | 8667 | ||
| 2898 | /* Handle case where pos is before w->start -- | 8668 | ++first_row_to_display; |
| 2899 | can happen if part of line had been clipped and is not clipped now */ | 8669 | } |
| 2900 | if (vpos == 0 && pos < marker_position (w->start)) | ||
| 2901 | Fset_marker (w->start, make_number (pos), Qnil); | ||
| 2902 | 8670 | ||
| 2903 | val.bytepos = pos_byte; | 8671 | /* Start displaying at the start of first_row_to_display. */ |
| 2904 | val.ovstring_chars_done = 0; | 8672 | xassert (first_row_to_display->y < yb); |
| 8673 | init_to_row_start (&it, w, first_row_to_display); | ||
| 8674 | nrows_scrolled = MATRIX_ROW_VPOS (first_reusable_row, w->current_matrix); | ||
| 8675 | it.vpos = (MATRIX_ROW_VPOS (first_row_to_display, w->current_matrix) | ||
| 8676 | - nrows_scrolled); | ||
| 8677 | it.current_y = first_row_to_display->y - first_reusable_row->y; | ||
| 8678 | |||
| 8679 | /* Display lines beginning with first_row_to_display in the | ||
| 8680 | desired matrix. Set last_text_row to the last row displayed | ||
| 8681 | that displays text. */ | ||
| 8682 | it.glyph_row = MATRIX_ROW (w->desired_matrix, it.vpos); | ||
| 8683 | if (pt_row == NULL) | ||
| 8684 | w->cursor.vpos = -1; | ||
| 8685 | last_text_row = NULL; | ||
| 8686 | while (it.current_y < it.last_visible_y && !fonts_changed_p) | ||
| 8687 | if (display_line (&it)) | ||
| 8688 | last_text_row = it.glyph_row - 1; | ||
| 8689 | |||
| 8690 | /* Give up If point isn't in a row displayed or reused. */ | ||
| 8691 | if (w->cursor.vpos < 0) | ||
| 8692 | { | ||
| 8693 | clear_glyph_matrix (w->desired_matrix); | ||
| 8694 | return 0; | ||
| 8695 | } | ||
| 2905 | 8696 | ||
| 2906 | /* Redisplay the lines where the text was changed */ | 8697 | /* If point is in a reused row, adjust y and vpos of the cursor |
| 2907 | last_text_vpos = vpos; | 8698 | position. */ |
| 2908 | /* The following code is omitted because we maintain tab offset in | 8699 | if (pt_row) |
| 2909 | val.tab_offset. */ | 8700 | { |
| 2910 | #if 0 | 8701 | w->cursor.vpos -= MATRIX_ROW_VPOS (first_reusable_row, |
| 2911 | tab_offset = pos_tab_offset (w, pos, pos_byte); | 8702 | w->current_matrix); |
| 2912 | /* If we are starting display in mid-character, correct tab_offset | 8703 | w->cursor.y -= first_reusable_row->y; |
| 2913 | to account for passing the line that that character really starts in. */ | ||
| 2914 | if (val.hpos < lmargin) | ||
| 2915 | tab_offset += width; | ||
| 2916 | #endif /* 0 */ | ||
| 2917 | old_tick = MODIFF; | ||
| 2918 | while (vpos < stop_vpos) | ||
| 2919 | { | ||
| 2920 | val = *display_text_line (w, pos, val.bytepos, top + vpos++, | ||
| 2921 | val.hpos, val.tab_offset, | ||
| 2922 | val.ovstring_chars_done); | ||
| 2923 | /* If display_text_line ran a hook and changed some text, | ||
| 2924 | redisplay all the way to bottom of buffer | ||
| 2925 | So that we show the changes. */ | ||
| 2926 | if (old_tick != MODIFF) | ||
| 2927 | stop_vpos = height; | ||
| 2928 | /* The following code is omitted because we maintain tab offset | ||
| 2929 | in val.tab_offset. */ | ||
| 2930 | #if 0 | ||
| 2931 | tab_offset += width; | ||
| 2932 | if (val.vpos) tab_offset = 0; | ||
| 2933 | #endif | ||
| 2934 | if (pos != val.bufpos) | ||
| 2935 | last_text_vpos | ||
| 2936 | /* Next line, unless prev line ended in end of buffer with no cr */ | ||
| 2937 | = vpos - (val.vpos && FETCH_BYTE (val.bytepos - 1) != '\n'); | ||
| 2938 | pos = val.bufpos; | ||
| 2939 | } | ||
| 2940 | |||
| 2941 | /* There are two cases: | ||
| 2942 | 1) we have displayed down to the bottom of the window | ||
| 2943 | 2) we have scrolled lines below stop_vpos by scroll_amount */ | ||
| 2944 | |||
| 2945 | if (vpos == height) | ||
| 2946 | { | ||
| 2947 | /* If last line is continued in middle of character, | ||
| 2948 | include the split character in the text considered on the frame */ | ||
| 2949 | if (val.hpos < lmargin) | ||
| 2950 | val.bufpos++; | ||
| 2951 | XSETFASTINT (w->window_end_vpos, last_text_vpos); | ||
| 2952 | XSETFASTINT (w->window_end_pos, Z - val.bufpos); | ||
| 2953 | } | ||
| 2954 | |||
| 2955 | /* If scrolling made blank lines at window bottom, | ||
| 2956 | redisplay to fill those lines */ | ||
| 2957 | if (scroll_amount < 0) | ||
| 2958 | { | ||
| 2959 | /* Don't consider these lines for general-purpose scrolling. | ||
| 2960 | That will save time in the scrolling computation. */ | ||
| 2961 | FRAME_SCROLL_BOTTOM_VPOS (f) = xp.vpos; | ||
| 2962 | vpos = xp.vpos; | ||
| 2963 | pos = xp.bufpos; | ||
| 2964 | pos_byte = xp.bytepos; | ||
| 2965 | val.hpos = xp.hpos; | ||
| 2966 | val.tab_offset = xp.tab_offset; | ||
| 2967 | if (pos == ZV) | ||
| 2968 | { /* Display from next line */ | ||
| 2969 | vpos = height + scroll_amount; | ||
| 2970 | val.hpos = lmargin; | ||
| 2971 | val.tab_offset = 0; | ||
| 2972 | } | ||
| 2973 | else if (xp.contin && xp.hpos != lmargin) | ||
| 2974 | { | ||
| 2975 | val.hpos = xp.prevhpos - width + lmargin; | ||
| 2976 | val.tab_offset = xp.tab_offset + bp.prevhpos - width; | ||
| 2977 | DEC_BOTH (pos, pos_byte); | ||
| 2978 | } | ||
| 2979 | |||
| 2980 | blank_end_of_window = 1; | ||
| 2981 | /* The following code is omitted because we maintain tab offset | ||
| 2982 | in val.tab_offset. */ | ||
| 2983 | #if 0 | ||
| 2984 | tab_offset = pos_tab_offset (w, pos, pos_byte); | ||
| 2985 | /* If we are starting display in mid-character, correct tab_offset | ||
| 2986 | to account for passing the line that that character starts in. */ | ||
| 2987 | if (val.hpos < lmargin) | ||
| 2988 | tab_offset += width; | ||
| 2989 | #endif | ||
| 2990 | val.bytepos = pos_byte; | ||
| 2991 | while (vpos < height) | ||
| 2992 | { | ||
| 2993 | val = *display_text_line (w, pos, val.bytepos, | ||
| 2994 | top + vpos++, val.hpos, | ||
| 2995 | val.tab_offset, val.ovstring_chars_done); | ||
| 2996 | /* The following code is omitted because we maintain tab | ||
| 2997 | offset in val.tab_offset. */ | ||
| 2998 | #if 0 | ||
| 2999 | tab_offset += width; | ||
| 3000 | if (val.vpos) tab_offset = 0; | ||
| 3001 | #endif /* 0 */ | ||
| 3002 | pos = val.bufpos; | ||
| 3003 | } | 8704 | } |
| 3004 | 8705 | ||
| 3005 | /* Here is a case where display_text_line sets cursor_vpos wrong. | 8706 | /* Scroll the display. */ |
| 3006 | Make it be fixed up, below. */ | 8707 | run.current_y = first_reusable_row->y; |
| 3007 | if (xp.bufpos == ZV | 8708 | run.desired_y = WINDOW_DISPLAY_TOP_LINE_HEIGHT (w); |
| 3008 | && xp.bufpos == PT) | 8709 | run.height = it.last_visible_y - run.current_y; |
| 3009 | cursor_vpos = -1; | 8710 | if (run.height) |
| 3010 | } | 8711 | { |
| 8712 | struct frame *f = XFRAME (WINDOW_FRAME (w)); | ||
| 8713 | update_begin (f); | ||
| 8714 | rif->update_window_begin_hook (w); | ||
| 8715 | rif->scroll_run_hook (w, &run); | ||
| 8716 | rif->update_window_end_hook (w, 0); | ||
| 8717 | update_end (f); | ||
| 8718 | } | ||
| 3011 | 8719 | ||
| 3012 | /* If bottom just moved off end of frame, change mode line percentage. */ | 8720 | /* Adjust Y positions of reused rows. */ |
| 3013 | if (XFASTINT (w->window_end_pos) == 0 | 8721 | bottom_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w); |
| 3014 | && Z != val.bufpos) | 8722 | row = first_reusable_row; |
| 3015 | w->update_mode_line = Qt; | 8723 | dy = first_reusable_row->y; |
| 8724 | min_y = WINDOW_DISPLAY_TOP_LINE_HEIGHT (w); | ||
| 8725 | max_y = it.last_visible_y; | ||
| 8726 | while (row < first_row_to_display) | ||
| 8727 | { | ||
| 8728 | row->y -= dy; | ||
| 8729 | if (row->y < min_y) | ||
| 8730 | row->visible_height = row->height - (min_y - row->y); | ||
| 8731 | else if (row->y + row->height > max_y) | ||
| 8732 | row->visible_height | ||
| 8733 | = row->height - (row->y + row->height - max_y); | ||
| 8734 | else | ||
| 8735 | row->visible_height = row->height; | ||
| 8736 | ++row; | ||
| 8737 | } | ||
| 3016 | 8738 | ||
| 3017 | /* Attempt to adjust end-of-text positions to new bottom line */ | 8739 | /* Disable rows not reused. */ |
| 3018 | if (scroll_amount) | 8740 | while (row < bottom_row) |
| 3019 | { | 8741 | { |
| 3020 | delta = height - xp.vpos; | 8742 | row->enabled_p = 0; |
| 3021 | if (delta < 0 | 8743 | ++row; |
| 3022 | || (delta > 0 && xp.bufpos <= ZV) | 8744 | } |
| 3023 | || (delta == 0 && xp.hpos)) | 8745 | |
| 8746 | /* Scroll the current matrix. */ | ||
| 8747 | xassert (nrows_scrolled > 0); | ||
| 8748 | rotate_matrix (w->current_matrix, | ||
| 8749 | start_vpos, | ||
| 8750 | MATRIX_ROW_VPOS (bottom_row, w->current_matrix), | ||
| 8751 | -nrows_scrolled); | ||
| 8752 | |||
| 8753 | /* Adjust window end. A null value of last_text_row means that | ||
| 8754 | the window end is in reused rows which in turn means that | ||
| 8755 | only its vpos can have changed. */ | ||
| 8756 | if (last_text_row) | ||
| 3024 | { | 8757 | { |
| 3025 | val = *vmotion (Z - XFASTINT (w->window_end_pos), delta, w); | 8758 | w->window_end_bytepos |
| 3026 | XSETFASTINT (w->window_end_pos, Z - val.bufpos); | 8759 | = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row); |
| 8760 | XSETFASTINT (w->window_end_pos, | ||
| 8761 | Z - MATRIX_ROW_END_CHARPOS (last_text_row)); | ||
| 3027 | XSETFASTINT (w->window_end_vpos, | 8762 | XSETFASTINT (w->window_end_vpos, |
| 3028 | XFASTINT (w->window_end_vpos) + val.vpos); | 8763 | MATRIX_ROW_VPOS (last_text_row, w->desired_matrix)); |
| 3029 | } | 8764 | } |
| 8765 | else | ||
| 8766 | { | ||
| 8767 | XSETFASTINT (w->window_end_vpos, | ||
| 8768 | XFASTINT (w->window_end_vpos) - nrows_scrolled); | ||
| 8769 | } | ||
| 8770 | |||
| 8771 | w->window_end_valid = Qnil; | ||
| 8772 | w->desired_matrix->no_scrolling_p = 1; | ||
| 8773 | |||
| 8774 | #if GLYPH_DEBUG | ||
| 8775 | debug_method_add (w, "try_window_reusing_current_matrix 2"); | ||
| 8776 | #endif | ||
| 8777 | return 1; | ||
| 3030 | } | 8778 | } |
| 8779 | |||
| 8780 | return 0; | ||
| 8781 | } | ||
| 3031 | 8782 | ||
| 3032 | w->window_end_valid = Qnil; | ||
| 3033 | 8783 | ||
| 3034 | /* If point was not in a line that was displayed, find it */ | 8784 | |
| 3035 | if (cursor_vpos < 0) | 8785 | /************************************************************************ |
| 3036 | { | 8786 | Window redisplay reusing current matrix when buffer has changed |
| 3037 | findpoint: | 8787 | ************************************************************************/ |
| 3038 | val = *compute_motion (start, 0, lmargin, 0, PT, | 8788 | |
| 3039 | /* Don't care for VPOS... */ | 8789 | static struct glyph_row *get_last_unchanged_at_beg_row P_ ((struct window *)); |
| 3040 | 1 << (BITS_PER_SHORT - 1), | 8790 | static struct glyph_row *get_first_unchanged_at_end_row P_ ((struct window *, |
| 3041 | /* ... nor HPOS. */ | 8791 | int *, int *)); |
| 3042 | 1 << (BITS_PER_SHORT - 1), | 8792 | static struct glyph_row * |
| 3043 | width, hscroll, | 8793 | find_last_row_displaying_text P_ ((struct glyph_matrix *, struct it *, |
| 3044 | pos_tab_offset (w, start, start_byte), | 8794 | struct glyph_row *)); |
| 3045 | w); | 8795 | |
| 3046 | /* Admit failure if point is off frame now */ | 8796 | |
| 3047 | if (val.vpos >= height) | 8797 | /* Return the last row in MATRIX displaying text. If row START is |
| 3048 | { | 8798 | non-null, start searching with that row. IT gives the dimensions |
| 3049 | for (vpos = 0; vpos < height; vpos++) | 8799 | of the display. Value is null if matrix is empty; otherwise it is |
| 3050 | cancel_line (vpos + top, f); | 8800 | a pointer to the row found. */ |
| 3051 | return 0; | 8801 | |
| 3052 | } | 8802 | static struct glyph_row * |
| 3053 | cursor_vpos = val.vpos + top; | 8803 | find_last_row_displaying_text (matrix, it, start) |
| 3054 | cursor_hpos = WINDOW_LEFT_MARGIN (w) + minmax (0, val.hpos, width); | 8804 | struct glyph_matrix *matrix; |
| 8805 | struct it *it; | ||
| 8806 | struct glyph_row *start; | ||
| 8807 | { | ||
| 8808 | struct glyph_row *row, *row_found; | ||
| 8809 | |||
| 8810 | /* Set row_found to the last row in IT->w's current matrix | ||
| 8811 | displaying text. The loop looks funny but think of partially | ||
| 8812 | visible lines. */ | ||
| 8813 | row_found = NULL; | ||
| 8814 | row = start ? start : MATRIX_FIRST_TEXT_ROW (matrix); | ||
| 8815 | while (MATRIX_ROW_DISPLAYS_TEXT_P (row)) | ||
| 8816 | { | ||
| 8817 | xassert (row->enabled_p); | ||
| 8818 | row_found = row; | ||
| 8819 | if (MATRIX_ROW_BOTTOM_Y (row) >= it->last_visible_y) | ||
| 8820 | break; | ||
| 8821 | ++row; | ||
| 3055 | } | 8822 | } |
| 8823 | |||
| 8824 | return row_found; | ||
| 8825 | } | ||
| 8826 | |||
| 3056 | 8827 | ||
| 3057 | FRAME_CURSOR_X (f) = cursor_hpos; | 8828 | /* Return the last row in the current matrix of W that is not affected |
| 3058 | FRAME_CURSOR_Y (f) = cursor_vpos; | 8829 | by changes at the start of current_buffer that occurred since the |
| 8830 | last time W was redisplayed. Value is null if no such row exists. | ||
| 3059 | 8831 | ||
| 3060 | if (debug_end_pos) | 8832 | The global variable beg_unchanged has to contain the number of |
| 8833 | bytes unchanged at the start of current_buffer. BEG + | ||
| 8834 | beg_unchanged is the buffer position of the first changed byte in | ||
| 8835 | current_buffer. Characters at positions < BEG + beg_unchanged are | ||
| 8836 | at the same buffer positions as they were when the current matrix | ||
| 8837 | was built. */ | ||
| 8838 | |||
| 8839 | static struct glyph_row * | ||
| 8840 | get_last_unchanged_at_beg_row (w) | ||
| 8841 | struct window *w; | ||
| 8842 | { | ||
| 8843 | int first_changed_pos = BEG + beg_unchanged; | ||
| 8844 | struct glyph_row *row; | ||
| 8845 | struct glyph_row *row_found = NULL; | ||
| 8846 | int yb = window_text_bottom_y (w); | ||
| 8847 | |||
| 8848 | /* Find the last row displaying unchanged text. */ | ||
| 8849 | row = MATRIX_FIRST_TEXT_ROW (w->current_matrix); | ||
| 8850 | while (MATRIX_ROW_DISPLAYS_TEXT_P (row) | ||
| 8851 | && MATRIX_ROW_START_CHARPOS (row) < first_changed_pos) | ||
| 3061 | { | 8852 | { |
| 3062 | val = *compute_motion (start, 0, lmargin, 0, ZV, | 8853 | if (/* If row ends before first_changed_pos, it is unchanged, |
| 3063 | height, - (1 << (BITS_PER_SHORT - 1)), | 8854 | except in some case. */ |
| 3064 | width, hscroll, | 8855 | MATRIX_ROW_END_CHARPOS (row) <= first_changed_pos |
| 3065 | pos_tab_offset (w, start, start_byte), | 8856 | /* When row ends in ZV and we write at ZV it is not |
| 3066 | w); | 8857 | unchanged. */ |
| 3067 | if (val.vpos != XFASTINT (w->window_end_vpos)) | 8858 | && !row->ends_at_zv_p |
| 3068 | abort (); | 8859 | /* When first_changed_pos is the end of a continued line, |
| 3069 | if (XFASTINT (w->window_end_pos) | 8860 | row is not unchanged because it may be no longer |
| 3070 | != Z - val.bufpos) | 8861 | continued. */ |
| 3071 | abort (); | 8862 | && !(MATRIX_ROW_END_CHARPOS (row) == first_changed_pos |
| 8863 | && row->continued_p)) | ||
| 8864 | row_found = row; | ||
| 8865 | |||
| 8866 | /* Stop if last visible row. */ | ||
| 8867 | if (MATRIX_ROW_BOTTOM_Y (row) >= yb) | ||
| 8868 | break; | ||
| 8869 | |||
| 8870 | ++row; | ||
| 3072 | } | 8871 | } |
| 3073 | 8872 | ||
| 3074 | return 1; | 8873 | return row_found; |
| 3075 | } | 8874 | } |
| 3076 | 8875 | ||
| 3077 | /* Copy LEN glyphs starting address FROM to the rope TO. | 8876 | |
| 3078 | But don't actually copy the parts that would come in before S. | 8877 | /* Find the first glyph row in the current matrix of W that is not |
| 3079 | Value is TO, advanced past the copied data. | 8878 | affected by changes at the end of current_buffer since the last |
| 3080 | F is the frame we are displaying in. */ | 8879 | time the window was redisplayed. Return in *DELTA the number of |
| 3081 | 8880 | bytes by which buffer positions in unchanged text at the end of | |
| 3082 | static GLYPH * | 8881 | current_buffer must be adjusted. Value is null if no such row |
| 3083 | copy_part_of_rope (f, to, s, from, len, face) | 8882 | exists, i.e. all rows are affected by changes. |
| 3084 | FRAME_PTR f; | 8883 | |
| 3085 | register GLYPH *to; /* Copy to here. */ | 8884 | The global variable end_unchanged is assumed to contain the number |
| 3086 | register GLYPH *s; /* Starting point. */ | 8885 | of unchanged bytes at the end of current_buffer. The buffer |
| 3087 | Lisp_Object *from; /* Data to copy. */ | 8886 | position of the last changed byte in current_buffer is then Z - |
| 3088 | int len; | 8887 | end_unchanged. */ |
| 3089 | int face; /* Face to apply to glyphs which don't specify one. */ | 8888 | |
| 8889 | static struct glyph_row * | ||
| 8890 | get_first_unchanged_at_end_row (w, delta, delta_bytes) | ||
| 8891 | struct window *w; | ||
| 8892 | int *delta, *delta_bytes; | ||
| 3090 | { | 8893 | { |
| 3091 | int n = len; | 8894 | struct glyph_row *row; |
| 3092 | register Lisp_Object *fp = from; | 8895 | struct glyph_row *row_found = NULL; |
| 3093 | /* These cache the results of the last call to compute_glyph_face. */ | ||
| 3094 | int last_code = -1; | ||
| 3095 | int last_merged = 0; | ||
| 3096 | 8896 | ||
| 3097 | #ifdef HAVE_FACES | 8897 | *delta = *delta_bytes = 0; |
| 3098 | if (! FRAME_TERMCAP_P (f)) | ||
| 3099 | while (n--) | ||
| 3100 | { | ||
| 3101 | GLYPH glyph = (INTEGERP (*fp) ? XFASTINT (*fp) : 0); | ||
| 3102 | int facecode; | ||
| 3103 | unsigned int c = FAST_GLYPH_CHAR (glyph); | ||
| 3104 | |||
| 3105 | if (c > MAX_CHAR) | ||
| 3106 | /* For an invalid character code, use space. */ | ||
| 3107 | c = ' '; | ||
| 3108 | |||
| 3109 | if (FAST_GLYPH_FACE (glyph) == 0) | ||
| 3110 | /* If GLYPH has no face code, use FACE. */ | ||
| 3111 | facecode = face; | ||
| 3112 | else if (FAST_GLYPH_FACE (glyph) == last_code) | ||
| 3113 | /* If it's same as previous glyph, use same result. */ | ||
| 3114 | facecode = last_merged; | ||
| 3115 | else | ||
| 3116 | { | ||
| 3117 | /* Merge this glyph's face and remember the result. */ | ||
| 3118 | last_code = FAST_GLYPH_FACE (glyph); | ||
| 3119 | last_merged = facecode = compute_glyph_face (f, last_code, face); | ||
| 3120 | } | ||
| 3121 | 8898 | ||
| 3122 | if (to >= s) | 8899 | /* A value of window_end_pos >= end_unchanged means that the window |
| 3123 | *to = FAST_MAKE_GLYPH (c, facecode); | 8900 | end is in the range of changed text. If so, there is no |
| 3124 | ++to; | 8901 | unchanged row at the end of W's current matrix. */ |
| 3125 | ++fp; | 8902 | xassert (!NILP (w->window_end_valid)); |
| 3126 | } | 8903 | if (XFASTINT (w->window_end_pos) >= end_unchanged) |
| 3127 | else | 8904 | return NULL; |
| 3128 | #endif | ||
| 3129 | while (n--) | ||
| 3130 | { | ||
| 3131 | if (to >= s) *to = (INTEGERP (*fp) ? XFASTINT (*fp) : 0); | ||
| 3132 | ++to; | ||
| 3133 | ++fp; | ||
| 3134 | } | ||
| 3135 | return to; | ||
| 3136 | } | ||
| 3137 | 8905 | ||
| 3138 | /* Correct a glyph by replacing its specified user-level face code | 8906 | /* Set row to the last row in W's current matrix displaying text. */ |
| 3139 | with a displayable computed face code. */ | 8907 | row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos)); |
| 8908 | |||
| 8909 | /* End vpos should always be on text, except in an entirely empty | ||
| 8910 | matrix. */ | ||
| 8911 | xassert (MATRIX_ROW_DISPLAYS_TEXT_P (row) | ||
| 8912 | || MATRIX_ROW_VPOS (row, w->current_matrix) == 0); | ||
| 3140 | 8913 | ||
| 3141 | static GLYPH | 8914 | /* If matrix is entirely empty, no unchanged row exists. */ |
| 3142 | fix_glyph (f, glyph, cface) | 8915 | if (MATRIX_ROW_DISPLAYS_TEXT_P (row)) |
| 3143 | FRAME_PTR f; | ||
| 3144 | GLYPH glyph; | ||
| 3145 | int cface; | ||
| 3146 | { | ||
| 3147 | #ifdef HAVE_FACES | ||
| 3148 | if (! FRAME_TERMCAP_P (f)) | ||
| 3149 | { | 8916 | { |
| 3150 | if (FAST_GLYPH_FACE (glyph) != 0) | 8917 | /* The value of row is the last glyph row in the matrix having a |
| 3151 | cface = compute_glyph_face (f, FAST_GLYPH_FACE (glyph), cface); | 8918 | meaningful buffer position in it. The end position of row |
| 3152 | glyph = FAST_MAKE_GLYPH (FAST_GLYPH_CHAR (glyph), cface); | 8919 | corresponds to window_end_pos. This allows us to translate |
| 8920 | buffer positions in the current matrix to current buffer | ||
| 8921 | positions for characters not in changed text. */ | ||
| 8922 | int Z_old = MATRIX_ROW_END_CHARPOS (row) + XFASTINT (w->window_end_pos); | ||
| 8923 | int Z_BYTE_old = MATRIX_ROW_END_BYTEPOS (row) + w->window_end_bytepos; | ||
| 8924 | int last_unchanged_pos, last_unchanged_pos_old; | ||
| 8925 | struct glyph_row *first_text_row | ||
| 8926 | = MATRIX_FIRST_TEXT_ROW (w->current_matrix); | ||
| 8927 | |||
| 8928 | *delta = Z - Z_old; | ||
| 8929 | *delta_bytes = Z_BYTE - Z_BYTE_old; | ||
| 8930 | |||
| 8931 | /* Set last_unchanged_pos to the buffer position of the last | ||
| 8932 | character in the buffer that has not been changed. Z is the | ||
| 8933 | index + 1 of the last byte in current_buffer, i.e. by | ||
| 8934 | subtracting end_unchanged we get the index of the last | ||
| 8935 | unchanged character, and we have to add BEG to get its buffer | ||
| 8936 | position. */ | ||
| 8937 | last_unchanged_pos = Z - end_unchanged + BEG; | ||
| 8938 | last_unchanged_pos_old = last_unchanged_pos - *delta; | ||
| 8939 | |||
| 8940 | /* Search backward from ROW for a row displaying a line that | ||
| 8941 | starts at a minimum position >= last_unchanged_pos_old. */ | ||
| 8942 | while (row >= first_text_row) | ||
| 8943 | { | ||
| 8944 | xassert (row->enabled_p); | ||
| 8945 | xassert (MATRIX_ROW_DISPLAYS_TEXT_P (row)); | ||
| 8946 | |||
| 8947 | if (MATRIX_ROW_START_CHARPOS (row) >= last_unchanged_pos_old) | ||
| 8948 | row_found = row; | ||
| 8949 | --row; | ||
| 8950 | } | ||
| 3153 | } | 8951 | } |
| 3154 | #endif | 8952 | |
| 3155 | return glyph; | 8953 | xassert (!row_found || MATRIX_ROW_DISPLAYS_TEXT_P (row_found)); |
| 8954 | return row_found; | ||
| 3156 | } | 8955 | } |
| 3157 | |||
| 3158 | /* Return the column of position POS / POS_BYTE in window W's buffer. | ||
| 3159 | When used on the character at the beginning of a line, | ||
| 3160 | starting at column 0, this says how much to subtract from | ||
| 3161 | the column position of any character in the line | ||
| 3162 | to get its horizontal position on the screen. */ | ||
| 3163 | 8956 | ||
| 3164 | static int | 8957 | |
| 3165 | pos_tab_offset (w, pos, pos_byte) | 8958 | /* Make sure that glyph rows in the current matrix of window W |
| 8959 | reference the same glyph memory as corresponding rows in the | ||
| 8960 | frame's frame matrix. This function is called after scrolling W's | ||
| 8961 | current matrix on a terminal frame in try_window_id and | ||
| 8962 | try_window_reusing_current_matrix. */ | ||
| 8963 | |||
| 8964 | static void | ||
| 8965 | sync_frame_with_window_matrix_rows (w) | ||
| 3166 | struct window *w; | 8966 | struct window *w; |
| 3167 | register int pos, pos_byte; | ||
| 3168 | { | 8967 | { |
| 3169 | int opoint = PT; | 8968 | struct frame *f = XFRAME (w->frame); |
| 3170 | int opoint_byte = PT_BYTE; | 8969 | struct glyph_row *window_row, *window_row_end, *frame_row; |
| 3171 | int col; | 8970 | |
| 3172 | int width = window_internal_width (w) - 1; | 8971 | /* Preconditions: W must be a leaf window and full-width. Its frame |
| 8972 | must have a frame matrix. */ | ||
| 8973 | xassert (NILP (w->hchild) && NILP (w->vchild)); | ||
| 8974 | xassert (WINDOW_FULL_WIDTH_P (w)); | ||
| 8975 | xassert (!FRAME_WINDOW_P (f)); | ||
| 8976 | |||
| 8977 | /* If W is a full-width window, glyph pointers in W's current matrix | ||
| 8978 | have, by definition, to be the same as glyph pointers in the | ||
| 8979 | corresponding frame matrix. */ | ||
| 8980 | window_row = w->current_matrix->rows; | ||
| 8981 | window_row_end = window_row + w->current_matrix->nrows; | ||
| 8982 | frame_row = f->current_matrix->rows + XFASTINT (w->top); | ||
| 8983 | while (window_row < window_row_end) | ||
| 8984 | { | ||
| 8985 | int area; | ||
| 8986 | for (area = LEFT_MARGIN_AREA; area <= LAST_AREA; ++area) | ||
| 8987 | frame_row->glyphs[area] = window_row->glyphs[area]; | ||
| 8988 | ++window_row, ++frame_row; | ||
| 8989 | } | ||
| 8990 | } | ||
| 3173 | 8991 | ||
| 3174 | if (pos == BEGV) | ||
| 3175 | return MINI_WINDOW_P (w) ? -minibuf_prompt_width : 0; | ||
| 3176 | 8992 | ||
| 3177 | if (FETCH_BYTE (pos_byte - 1) == '\n') | 8993 | /* Try to redisplay window W by reusing its existing display. W's |
| 3178 | return 0; | 8994 | current matrix must be up to date when this function is called, |
| 8995 | i.e. window_end_valid must not be nil. | ||
| 3179 | 8996 | ||
| 3180 | TEMP_SET_PT_BOTH (pos, pos_byte); | 8997 | Value is |
| 3181 | col = current_column (); | ||
| 3182 | TEMP_SET_PT_BOTH (opoint, opoint_byte); | ||
| 3183 | 8998 | ||
| 3184 | return col; | 8999 | 1 if display has been updated |
| 3185 | } | 9000 | 0 if otherwise unsuccessful |
| 3186 | 9001 | -1 if redisplay with same window start is known not to succeed | |
| 3187 | /* Display one line of window W, starting at char position START in W's buffer. | ||
| 3188 | START_BYTE is the corresponding byte position. | ||
| 3189 | 9002 | ||
| 3190 | Display starting at horizontal position HPOS, expressed relative to | 9003 | The following steps are performed: |
| 3191 | W's left edge. In situations where the text at START shouldn't | ||
| 3192 | start at the left margin (i.e. when the window is hscrolled, or | ||
| 3193 | we're continuing a line which left off in the midst of a | ||
| 3194 | multi-column character), HPOS should be negative; we throw away | ||
| 3195 | characters up 'til hpos = 0. So, HPOS must take hscrolling into | ||
| 3196 | account. | ||
| 3197 | 9004 | ||
| 3198 | TABOFFSET is an offset for ostensible hpos, used in tab stop calculations. | 9005 | 1. Find the last row in the current matrix of W that is not |
| 9006 | affected by changes at the start of current_buffer. If no such row | ||
| 9007 | is found, give up. | ||
| 3199 | 9008 | ||
| 3200 | OVSTR_DONE is the number of chars of overlay before/after strings | 9009 | 2. Find the first row in W's current matrix that is not affected by |
| 3201 | at this position which have already been processed. | 9010 | changes at the end of current_buffer. Maybe there is no such row. |
| 3202 | 9011 | ||
| 3203 | Display on position VPOS on the frame. It is origin 0, relative to | 9012 | 3. Display lines beginning with the row + 1 found in step 1 to the |
| 3204 | the top of the frame, not W. | 9013 | row found in step 2 or, if step 2 didn't find a row, to the end of |
| 9014 | the window. | ||
| 3205 | 9015 | ||
| 3206 | Returns a STRUCT POSITION giving character to start next line with | 9016 | 4. If cursor is not known to appear on the window, give up. |
| 3207 | and where to display it, including a zero or negative hpos. | ||
| 3208 | The vpos field is not really a vpos; it is 1 unless the line is continued */ | ||
| 3209 | 9017 | ||
| 3210 | struct position val_display_text_line; | 9018 | 5. If display stopped at the row found in step 2, scroll the |
| 9019 | display and current matrix as needed. | ||
| 3211 | 9020 | ||
| 3212 | static struct position * | 9021 | 6. Maybe display some lines at the end of W, if we must. This can |
| 3213 | display_text_line (w, start, start_byte, vpos, hpos, taboffset, ovstr_done) | 9022 | happen under various circumstances, like a partially visible line |
| 3214 | struct window *w; | 9023 | becoming fully visible, or because newly displayed lines are displayed |
| 3215 | int start; | 9024 | in smaller font sizes. |
| 3216 | int vpos; | ||
| 3217 | int hpos; | ||
| 3218 | int taboffset; | ||
| 3219 | int ovstr_done; | ||
| 3220 | { | ||
| 3221 | register int pos = start; | ||
| 3222 | int pos_byte = start_byte; | ||
| 3223 | register int c; | ||
| 3224 | register GLYPH *p1; | ||
| 3225 | int pause, limit_byte; | ||
| 3226 | register unsigned char *p; | ||
| 3227 | GLYPH *endp; | ||
| 3228 | register GLYPH *leftmargin; | ||
| 3229 | register GLYPH *p1prev; | ||
| 3230 | register GLYPH *p1start; | ||
| 3231 | GLYPH *p1_wide_column_end = (GLYPH *) 0; | ||
| 3232 | int prevpos, prevpos_byte; | ||
| 3233 | int *charstart; | ||
| 3234 | FRAME_PTR f = XFRAME (w->frame); | ||
| 3235 | int tab_width = XINT (current_buffer->tab_width); | ||
| 3236 | int ctl_arrow = !NILP (current_buffer->ctl_arrow); | ||
| 3237 | int width = window_internal_width (w) - 1; | ||
| 3238 | struct position val; | ||
| 3239 | int lastpos, lastpos_byte; | ||
| 3240 | int invis; | ||
| 3241 | int last_invis_skip = 0; | ||
| 3242 | Lisp_Object last_invis_prop; | ||
| 3243 | int hscroll = XINT (w->hscroll); | ||
| 3244 | int truncate = (hscroll | ||
| 3245 | || (truncate_partial_width_windows | ||
| 3246 | && !WINDOW_FULL_WIDTH_P (w)) | ||
| 3247 | || !NILP (current_buffer->truncate_lines)); | ||
| 3248 | |||
| 3249 | /* 1 if this buffer has a region to highlight. */ | ||
| 3250 | int highlight_region | ||
| 3251 | = (!NILP (Vtransient_mark_mode) && !NILP (current_buffer->mark_active) | ||
| 3252 | && XMARKER (current_buffer->mark)->buffer != 0); | ||
| 3253 | int region_beg, region_end; | ||
| 3254 | |||
| 3255 | int selective = (INTEGERP (current_buffer->selective_display) | ||
| 3256 | ? XINT (current_buffer->selective_display) | ||
| 3257 | : !NILP (current_buffer->selective_display) ? -1 : 0); | ||
| 3258 | register struct frame_glyphs *desired_glyphs = FRAME_DESIRED_GLYPHS (f); | ||
| 3259 | register struct Lisp_Char_Table *dp = window_display_table (w); | ||
| 3260 | |||
| 3261 | Lisp_Object default_invis_vector[3]; | ||
| 3262 | /* Number of characters of ellipsis to display after an invisible line | ||
| 3263 | if it calls for an ellipsis. | ||
| 3264 | Note that this value can be nonzero regardless of whether | ||
| 3265 | selective display is enabled--you must check that separately. */ | ||
| 3266 | int selective_rlen | ||
| 3267 | = (dp && VECTORP (DISP_INVIS_VECTOR (dp)) | ||
| 3268 | ? XVECTOR (DISP_INVIS_VECTOR (dp))->size | ||
| 3269 | : !NILP (current_buffer->selective_display_ellipses) ? 3 : 0); | ||
| 3270 | /* This is the sequence of Lisp objects to display | ||
| 3271 | when there are invisible lines. */ | ||
| 3272 | Lisp_Object *invis_vector_contents | ||
| 3273 | = (dp && VECTORP (DISP_INVIS_VECTOR (dp)) | ||
| 3274 | ? XVECTOR (DISP_INVIS_VECTOR (dp))->contents | ||
| 3275 | : default_invis_vector); | ||
| 3276 | |||
| 3277 | GLYPH truncator = (dp == 0 || !INTEGERP (DISP_TRUNC_GLYPH (dp)) | ||
| 3278 | || !GLYPH_CHAR_VALID_P (XINT (DISP_TRUNC_GLYPH (dp))) | ||
| 3279 | ? '$' : XINT (DISP_TRUNC_GLYPH (dp))); | ||
| 3280 | GLYPH continuer = (dp == 0 || !INTEGERP (DISP_CONTINUE_GLYPH (dp)) | ||
| 3281 | || !GLYPH_CHAR_VALID_P (XINT (DISP_CONTINUE_GLYPH (dp))) | ||
| 3282 | ? '\\' : XINT (DISP_CONTINUE_GLYPH (dp))); | ||
| 3283 | |||
| 3284 | /* If 1, we must handle multibyte characters. */ | ||
| 3285 | int multibyte = !NILP (current_buffer->enable_multibyte_characters); | ||
| 3286 | /* Length of multibyte form of each character. */ | ||
| 3287 | int len; | ||
| 3288 | /* Glyphs generated should be set this bit mask if text must be | ||
| 3289 | displayed from right to left. */ | ||
| 3290 | GLYPH rev_dir_bit = (NILP (current_buffer->direction_reversed) | ||
| 3291 | ? 0 : GLYPH_MASK_REV_DIR); | ||
| 3292 | 9025 | ||
| 3293 | /* The next buffer location at which the face should change, due | 9026 | 7. Update W's window end information. */ |
| 3294 | to overlays or text property changes. */ | ||
| 3295 | int next_face_change; | ||
| 3296 | 9027 | ||
| 3297 | /* The next location where the `invisible' property changes, or an | 9028 | /* Check that window end is what we expect it to be. */ |
| 3298 | overlay starts or ends. */ | ||
| 3299 | int next_boundary; | ||
| 3300 | 9029 | ||
| 3301 | /* The face we're currently using. */ | 9030 | static int |
| 3302 | int current_face = 0; | 9031 | try_window_id (w) |
| 3303 | int i; | 9032 | struct window *w; |
| 9033 | { | ||
| 9034 | struct frame *f = XFRAME (w->frame); | ||
| 9035 | struct glyph_matrix *current_matrix = w->current_matrix; | ||
| 9036 | struct glyph_matrix *desired_matrix = w->desired_matrix; | ||
| 9037 | struct glyph_row *last_unchanged_at_beg_row; | ||
| 9038 | struct glyph_row *first_unchanged_at_end_row; | ||
| 9039 | struct glyph_row *row; | ||
| 9040 | struct glyph_row *bottom_row; | ||
| 9041 | int bottom_vpos; | ||
| 9042 | struct it it; | ||
| 9043 | int delta = 0, delta_bytes = 0, stop_pos, dvpos, dy; | ||
| 9044 | struct text_pos start_pos; | ||
| 9045 | struct run run; | ||
| 9046 | int first_unchanged_at_end_vpos = 0; | ||
| 9047 | struct glyph_row *last_text_row, *last_text_row_at_end; | ||
| 9048 | struct text_pos start; | ||
| 9049 | |||
| 9050 | SET_TEXT_POS_FROM_MARKER (start, w->start); | ||
| 9051 | |||
| 9052 | /* Check pre-conditions. Window end must be valid, otherwise | ||
| 9053 | the current matrix would not be up to date. */ | ||
| 9054 | xassert (!NILP (w->window_end_valid)); | ||
| 9055 | xassert (FRAME_WINDOW_P (XFRAME (w->frame)) | ||
| 9056 | || (line_ins_del_ok && WINDOW_FULL_WIDTH_P (w))); | ||
| 9057 | |||
| 9058 | /* Make sure beg_unchanged and end_unchanged are up to date. Do it | ||
| 9059 | only if buffer has really changed. The reason is that the gap is | ||
| 9060 | initially at Z for freshly visited files. The code below would | ||
| 9061 | set end_unchanged to 0 in that case. */ | ||
| 9062 | if (MODIFF > SAVE_MODIFF) | ||
| 9063 | { | ||
| 9064 | if (GPT - BEG < beg_unchanged) | ||
| 9065 | beg_unchanged = GPT - BEG; | ||
| 9066 | if (Z - GPT < end_unchanged) | ||
| 9067 | end_unchanged = Z - GPT; | ||
| 9068 | } | ||
| 9069 | |||
| 9070 | /* If window starts after a line end, and the last change is in | ||
| 9071 | front of that newline, then changes don't affect the display. | ||
| 9072 | This case happens with stealth-fontification. */ | ||
| 9073 | row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos)); | ||
| 9074 | if (CHARPOS (start) > BEGV | ||
| 9075 | && Z - end_unchanged < CHARPOS (start) - 1 | ||
| 9076 | && FETCH_BYTE (BYTEPOS (start) - 1) == '\n' | ||
| 9077 | && PT < MATRIX_ROW_END_CHARPOS (row)) | ||
| 9078 | { | ||
| 9079 | /* We have to update window end positions because the buffer's | ||
| 9080 | size has changed. */ | ||
| 9081 | w->window_end_pos | ||
| 9082 | = make_number (Z - MATRIX_ROW_END_CHARPOS (row)); | ||
| 9083 | w->window_end_bytepos | ||
| 9084 | = make_number (Z_BYTE - MATRIX_ROW_END_BYTEPOS (row)); | ||
| 9085 | return 1; | ||
| 9086 | } | ||
| 3304 | 9087 | ||
| 3305 | XSETFASTINT (default_invis_vector[2], '.'); | 9088 | /* Return quickly if changes are all below what is displayed in the |
| 3306 | default_invis_vector[0] = default_invis_vector[1] = default_invis_vector[2]; | 9089 | window, and if PT is in the window. */ |
| 9090 | if (beg_unchanged > MATRIX_ROW_END_CHARPOS (row) | ||
| 9091 | && PT < MATRIX_ROW_END_CHARPOS (row)) | ||
| 9092 | { | ||
| 9093 | /* We have to update window end positions because the buffer's | ||
| 9094 | size has changed. */ | ||
| 9095 | w->window_end_pos | ||
| 9096 | = make_number (Z - MATRIX_ROW_END_CHARPOS (row)); | ||
| 9097 | w->window_end_bytepos | ||
| 9098 | = make_number (Z_BYTE - MATRIX_ROW_END_BYTEPOS (row)); | ||
| 9099 | return 1; | ||
| 9100 | } | ||
| 3307 | 9101 | ||
| 3308 | get_display_line (f, vpos, WINDOW_LEFT_MARGIN (w)); | 9102 | /* Check that window start agrees with the start of the first glyph |
| 3309 | if (tab_width <= 0 || tab_width > 1000) tab_width = 8; | 9103 | row in its current matrix. Check this after we know the window |
| 9104 | start is not in changed text, otherwise positions would not be | ||
| 9105 | comparable. */ | ||
| 9106 | row = MATRIX_FIRST_TEXT_ROW (w->current_matrix); | ||
| 9107 | if (!TEXT_POS_EQUAL_P (start, row->start.pos)) | ||
| 9108 | return 0; | ||
| 3310 | 9109 | ||
| 3311 | /* Show where to highlight the region. */ | 9110 | /* Remember beg_unchanged and end_unchanged for debugging purposes. */ |
| 3312 | if (highlight_region | 9111 | IF_DEBUG (debug_beg_unchanged = beg_unchanged; |
| 3313 | /* Maybe highlight only in selected window. */ | 9112 | debug_end_unchanged = end_unchanged); |
| 3314 | && (highlight_nonselected_windows | 9113 | |
| 3315 | || w == XWINDOW (selected_window) | 9114 | /* Compute the position at which we have to start displaying new |
| 3316 | || (MINI_WINDOW_P (XWINDOW (selected_window)) | 9115 | lines. Some of the lines at the top of the window might be |
| 3317 | && w == XWINDOW (Vminibuf_scroll_window)))) | 9116 | reusable because they are not displaying changed text. Find the |
| 9117 | last row in W's current matrix not affected by changes at the | ||
| 9118 | start of current_buffer. Value is null if changes start in the | ||
| 9119 | first line of window. */ | ||
| 9120 | last_unchanged_at_beg_row = get_last_unchanged_at_beg_row (w); | ||
| 9121 | if (last_unchanged_at_beg_row) | ||
| 3318 | { | 9122 | { |
| 3319 | region_beg = marker_position (current_buffer->mark); | 9123 | init_to_row_end (&it, w, last_unchanged_at_beg_row); |
| 3320 | if (PT < region_beg) | 9124 | start_pos = it.current.pos; |
| 3321 | { | 9125 | |
| 3322 | region_end = region_beg; | 9126 | /* Start displaying new lines in the desired matrix at the same |
| 3323 | region_beg = PT; | 9127 | vpos we would use in the current matrix, i.e. below |
| 3324 | } | 9128 | last_unchanged_at_beg_row. */ |
| 3325 | else | 9129 | it.vpos = 1 + MATRIX_ROW_VPOS (last_unchanged_at_beg_row, |
| 3326 | region_end = PT; | 9130 | current_matrix); |
| 3327 | w->region_showing = Qt; | 9131 | it.glyph_row = MATRIX_ROW (desired_matrix, it.vpos); |
| 9132 | it.current_y = MATRIX_ROW_BOTTOM_Y (last_unchanged_at_beg_row); | ||
| 9133 | |||
| 9134 | xassert (it.hpos == 0 && it.current_x == 0); | ||
| 3328 | } | 9135 | } |
| 3329 | else | 9136 | else |
| 3330 | { | 9137 | { |
| 3331 | region_beg = region_end = -1; | 9138 | /* There are no reusable lines at the start of the window. |
| 3332 | w->region_showing = Qnil; | 9139 | Start displaying in the first line. */ |
| 9140 | start_display (&it, w, start); | ||
| 9141 | start_pos = it.current.pos; | ||
| 3333 | } | 9142 | } |
| 3334 | 9143 | ||
| 3335 | if (MINI_WINDOW_P (w) | 9144 | bottom_row = MATRIX_BOTTOM_TEXT_ROW (current_matrix, w); |
| 3336 | && start == BEG | 9145 | bottom_vpos = MATRIX_ROW_VPOS (bottom_row, current_matrix); |
| 3337 | && vpos == XFASTINT (w->top)) | 9146 | |
| 9147 | /* Find the first row that is not affected by changes at the end of | ||
| 9148 | the buffer. Value will be null if there is no unchanged row, in | ||
| 9149 | which case we must redisplay to the end of the window. delta | ||
| 9150 | will be set to the value by which buffer positions beginning with | ||
| 9151 | first_unchanged_at_end_row have to be adjusted due to text | ||
| 9152 | changes. */ | ||
| 9153 | first_unchanged_at_end_row | ||
| 9154 | = get_first_unchanged_at_end_row (w, &delta, &delta_bytes); | ||
| 9155 | IF_DEBUG (debug_delta = delta); | ||
| 9156 | IF_DEBUG (debug_delta_bytes = delta_bytes); | ||
| 9157 | |||
| 9158 | /* Set stop_pos to the buffer position up to which we will have to | ||
| 9159 | display new lines. If first_unchanged_at_end_row != NULL, this | ||
| 9160 | is the buffer position of the start of the line displayed in that | ||
| 9161 | row. For first_unchanged_at_end_row == NULL, use 0 to indicate | ||
| 9162 | that we don't stop at a buffer position. */ | ||
| 9163 | stop_pos = 0; | ||
| 9164 | if (first_unchanged_at_end_row) | ||
| 3338 | { | 9165 | { |
| 3339 | if (! NILP (minibuf_prompt)) | 9166 | xassert (last_unchanged_at_beg_row == NULL |
| 9167 | || first_unchanged_at_end_row >= last_unchanged_at_beg_row); | ||
| 9168 | |||
| 9169 | /* If this is a continuation line, move forward to the next one | ||
| 9170 | that isn't. Changes in lines above affect this line. | ||
| 9171 | Caution: this may move first_unchanged_at_end_row to a row | ||
| 9172 | not displaying text. */ | ||
| 9173 | while (MATRIX_ROW_CONTINUATION_LINE_P (first_unchanged_at_end_row) | ||
| 9174 | && MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row) | ||
| 9175 | && (MATRIX_ROW_BOTTOM_Y (first_unchanged_at_end_row) | ||
| 9176 | < it.last_visible_y)) | ||
| 9177 | ++first_unchanged_at_end_row; | ||
| 9178 | |||
| 9179 | if (!MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row) | ||
| 9180 | || (MATRIX_ROW_BOTTOM_Y (first_unchanged_at_end_row) | ||
| 9181 | >= it.last_visible_y)) | ||
| 9182 | first_unchanged_at_end_row = NULL; | ||
| 9183 | else | ||
| 3340 | { | 9184 | { |
| 3341 | int old_width = minibuf_prompt_width; | 9185 | stop_pos = (MATRIX_ROW_START_CHARPOS (first_unchanged_at_end_row) |
| 3342 | 9186 | + delta); | |
| 3343 | minibuf_prompt_width | 9187 | first_unchanged_at_end_vpos |
| 3344 | = (display_string (w, vpos, XSTRING (minibuf_prompt)->data, | 9188 | = MATRIX_ROW_VPOS (first_unchanged_at_end_row, current_matrix); |
| 3345 | STRING_BYTES (XSTRING (minibuf_prompt)), | 9189 | xassert (stop_pos >= Z - end_unchanged); |
| 3346 | hpos + WINDOW_LEFT_MARGIN (w), | ||
| 3347 | /* Display a space if we truncate. */ | ||
| 3348 | ' ', | ||
| 3349 | 1, -1, | ||
| 3350 | /* Truncate the prompt a little before the | ||
| 3351 | margin, so user input can at least start | ||
| 3352 | on the first line. */ | ||
| 3353 | (XFASTINT (w->width) > 10 | ||
| 3354 | ? XFASTINT (w->width) - 4 : -1), | ||
| 3355 | STRING_MULTIBYTE (minibuf_prompt)) | ||
| 3356 | - hpos - WINDOW_LEFT_MARGIN (w)); | ||
| 3357 | hpos += minibuf_prompt_width; | ||
| 3358 | taboffset -= minibuf_prompt_width - old_width; | ||
| 3359 | } | 9190 | } |
| 3360 | else | ||
| 3361 | minibuf_prompt_width = 0; | ||
| 3362 | } | ||
| 3363 | |||
| 3364 | /* If we're hscrolled at all, use compute_motion to skip over any | ||
| 3365 | text off the left edge of the window. compute_motion may know | ||
| 3366 | tricks to do this faster than we can. */ | ||
| 3367 | if (hpos < 0) | ||
| 3368 | { | ||
| 3369 | struct position *left_edge | ||
| 3370 | = compute_motion (pos, vpos, hpos, 0, | ||
| 3371 | ZV, vpos, 0, | ||
| 3372 | width, hscroll, taboffset, w); | ||
| 3373 | |||
| 3374 | /* Retrieve the buffer position and column provided by | ||
| 3375 | compute_motion. We can't assume that the column will be | ||
| 3376 | zero, because you may have multi-column characters crossing | ||
| 3377 | the left margin. | ||
| 3378 | |||
| 3379 | compute_motion may have moved us past the screen position we | ||
| 3380 | requested, if we hit a multi-column character, or the end of | ||
| 3381 | the line. If so, back up. */ | ||
| 3382 | if ((left_edge->vpos > vpos | ||
| 3383 | || left_edge->hpos > 0) | ||
| 3384 | && left_edge->bufpos > pos) | ||
| 3385 | { | ||
| 3386 | pos = left_edge->bufpos; | ||
| 3387 | pos_byte = left_edge->bytepos; | ||
| 3388 | DEC_BOTH (pos, pos_byte); | ||
| 3389 | hpos = left_edge->prevhpos; | ||
| 3390 | } | ||
| 3391 | else | ||
| 3392 | { | ||
| 3393 | pos = left_edge->bufpos; | ||
| 3394 | pos_byte = left_edge->bytepos; | ||
| 3395 | hpos = left_edge->hpos; | ||
| 3396 | } | ||
| 3397 | } | 9191 | } |
| 9192 | else if (last_unchanged_at_beg_row == NULL) | ||
| 9193 | return 0; | ||
| 3398 | 9194 | ||
| 3399 | hpos += WINDOW_LEFT_MARGIN (w); | ||
| 3400 | 9195 | ||
| 3401 | desired_glyphs->bufp[vpos] = start; | 9196 | #if GLYPH_DEBUG |
| 3402 | p1 = desired_glyphs->glyphs[vpos] + hpos; | 9197 | |
| 3403 | p1start = p1; | 9198 | /* Either there is no unchanged row at the end, or the one we have |
| 3404 | charstart = desired_glyphs->charstarts[vpos] + hpos; | 9199 | now displays text. This is a necessary condition for the window |
| 3405 | /* In case we don't ever write anything into it... */ | 9200 | end pos calculation at the end of this function. */ |
| 3406 | desired_glyphs->charstarts[vpos][WINDOW_LEFT_MARGIN (w)] = -1; | 9201 | xassert (first_unchanged_at_end_row == NULL |
| 3407 | leftmargin = desired_glyphs->glyphs[vpos] + WINDOW_LEFT_MARGIN (w); | 9202 | || MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row)); |
| 3408 | endp = leftmargin + width; | 9203 | |
| 9204 | debug_last_unchanged_at_beg_vpos | ||
| 9205 | = (last_unchanged_at_beg_row | ||
| 9206 | ? MATRIX_ROW_VPOS (last_unchanged_at_beg_row, current_matrix) | ||
| 9207 | : -1); | ||
| 9208 | debug_first_unchanged_at_end_vpos = first_unchanged_at_end_vpos; | ||
| 9209 | |||
| 9210 | #endif /* GLYPH_DEBUG != 0 */ | ||
| 3409 | 9211 | ||
| 3410 | /* Arrange the overlays nicely for our purposes. Usually, we call | ||
| 3411 | display_text_line on only one line at a time, in which case this | ||
| 3412 | can't really hurt too much, or we call it on lines which appear | ||
| 3413 | one after another in the buffer, in which case all calls to | ||
| 3414 | recenter_overlay_lists but the first will be pretty cheap. */ | ||
| 3415 | recenter_overlay_lists (current_buffer, pos); | ||
| 3416 | 9212 | ||
| 3417 | /* Loop generating characters. | 9213 | /* Display new lines. Set last_text_row to the last new line |
| 3418 | Stop at end of buffer, before newline, | 9214 | displayed which has text on it, i.e. might end up as being the |
| 3419 | if reach or pass continuation column, | 9215 | line where the window_end_vpos is. */ |
| 3420 | or at face change. */ | 9216 | w->cursor.vpos = -1; |
| 3421 | pause = pos; | 9217 | last_text_row = NULL; |
| 3422 | limit_byte = pos_byte; | 9218 | overlay_arrow_seen = 0; |
| 3423 | next_face_change = pos; | 9219 | while (it.current_y < it.last_visible_y |
| 3424 | next_boundary = pos; | 9220 | && !fonts_changed_p |
| 3425 | p1prev = p1; | 9221 | && (first_unchanged_at_end_row == NULL |
| 3426 | prevpos = pos; | 9222 | || IT_CHARPOS (it) < stop_pos)) |
| 3427 | prevpos_byte = pos_byte; | 9223 | { |
| 9224 | if (display_line (&it)) | ||
| 9225 | last_text_row = it.glyph_row - 1; | ||
| 9226 | } | ||
| 9227 | |||
| 9228 | if (fonts_changed_p) | ||
| 9229 | return -1; | ||
| 9230 | |||
| 3428 | 9231 | ||
| 3429 | /* If the window is hscrolled and point is in the invisible part of the | 9232 | /* Compute differences in buffer positions, y-positions etc. for |
| 3430 | current line beyond the left margin we can record the cursor location | 9233 | lines reused at the bottom of the window. Compute what we can |
| 3431 | right away. */ | 9234 | scroll. */ |
| 3432 | if (hscroll && start <= PT && PT < pos && cursor_vpos < 0) | 9235 | if (first_unchanged_at_end_row) |
| 3433 | { | 9236 | { |
| 3434 | cursor_vpos = vpos; | 9237 | dvpos = (it.vpos |
| 3435 | cursor_hpos = p1 - leftmargin; | 9238 | - MATRIX_ROW_VPOS (first_unchanged_at_end_row, |
| 9239 | current_matrix)); | ||
| 9240 | dy = it.current_y - first_unchanged_at_end_row->y; | ||
| 9241 | run.current_y = first_unchanged_at_end_row->y; | ||
| 9242 | run.desired_y = run.current_y + dy; | ||
| 9243 | run.height = it.last_visible_y - max (run.current_y, run.desired_y); | ||
| 3436 | } | 9244 | } |
| 9245 | else | ||
| 9246 | delta = dvpos = dy = run.current_y = run.desired_y = run.height = 0; | ||
| 9247 | IF_DEBUG (debug_dvpos = dvpos; debug_dy = dy); | ||
| 3437 | 9248 | ||
| 3438 | while (p1 < endp) | 9249 | |
| 9250 | /* Find the cursor if not already found. We have to decide whether | ||
| 9251 | PT will appear on this window (it sometimes doesn't, but this is | ||
| 9252 | not a very frequent case.) This decision has to be made before | ||
| 9253 | the current matrix is altered. A value of cursor.vpos < 0 means | ||
| 9254 | that PT is either in one of the lines beginning at | ||
| 9255 | first_unchanged_at_end_row or below the window. Don't care for | ||
| 9256 | lines that might be displayed later at the window end; as | ||
| 9257 | mentioned, this is not a frequent case. */ | ||
| 9258 | if (w->cursor.vpos < 0) | ||
| 3439 | { | 9259 | { |
| 3440 | if (pos >= pause) | 9260 | int last_y = min (it.last_visible_y, it.last_visible_y + dy); |
| 9261 | |||
| 9262 | /* Cursor in unchanged rows at the top? */ | ||
| 9263 | if (PT < CHARPOS (start_pos) | ||
| 9264 | && last_unchanged_at_beg_row) | ||
| 3441 | { | 9265 | { |
| 3442 | int e_t_h; | 9266 | row = MATRIX_FIRST_TEXT_ROW (w->current_matrix); |
| 9267 | while (row <= last_unchanged_at_beg_row | ||
| 9268 | && MATRIX_ROW_END_CHARPOS (row) <= PT) | ||
| 9269 | ++row; | ||
| 9270 | xassert (row <= last_unchanged_at_beg_row); | ||
| 9271 | set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0); | ||
| 9272 | } | ||
| 3443 | 9273 | ||
| 3444 | while (pos == next_boundary) | 9274 | /* Start from first_unchanged_at_end_row looking for PT. */ |
| 9275 | else if (first_unchanged_at_end_row) | ||
| 9276 | { | ||
| 9277 | row = first_unchanged_at_end_row; | ||
| 9278 | while (MATRIX_ROW_DISPLAYS_TEXT_P (row)) | ||
| 3445 | { | 9279 | { |
| 3446 | Lisp_Object position, limit, prop, ww; | 9280 | if (PT - delta >= MATRIX_ROW_START_CHARPOS (row) |
| 3447 | 9281 | && PT - delta < MATRIX_ROW_END_CHARPOS (row)) | |
| 3448 | /* Display the overlay strings here, unless we're at ZV | ||
| 3449 | and have already displayed the appropriate strings | ||
| 3450 | on an earlier line. */ | ||
| 3451 | if (pos < ZV || !zv_strings_seen++) | ||
| 3452 | { | ||
| 3453 | int ovlen; | ||
| 3454 | unsigned char *ovstr; | ||
| 3455 | ovlen = overlay_strings (pos, w, &ovstr); | ||
| 3456 | |||
| 3457 | if (ovlen > 0) | ||
| 3458 | { | ||
| 3459 | /* Skip the ones we did in a previous line. */ | ||
| 3460 | ovstr += ovstr_done; | ||
| 3461 | ovlen -= ovstr_done; | ||
| 3462 | |||
| 3463 | while (ovlen > 0 && p1 < endp) | ||
| 3464 | { | ||
| 3465 | int charset, cols; | ||
| 3466 | GLYPH g; | ||
| 3467 | |||
| 3468 | if (multibyte) | ||
| 3469 | { | ||
| 3470 | c = STRING_CHAR_AND_LENGTH (ovstr, ovlen, len); | ||
| 3471 | ovstr += len, ovlen -= len, ovstr_done += len; | ||
| 3472 | charset = CHAR_CHARSET (c); | ||
| 3473 | cols = (charset == CHARSET_COMPOSITION | ||
| 3474 | ? cmpchar_table[COMPOSITE_CHAR_ID (c)]->width | ||
| 3475 | : CHARSET_WIDTH (charset)); | ||
| 3476 | } | ||
| 3477 | else | ||
| 3478 | { | ||
| 3479 | c = *ovstr++, ovlen--, ovstr_done++; | ||
| 3480 | cols = 1; | ||
| 3481 | } | ||
| 3482 | g = MAKE_GLYPH (f, c, current_face) | rev_dir_bit; | ||
| 3483 | while (cols-- > 0) | ||
| 3484 | { | ||
| 3485 | if (p1 >= leftmargin && p1 < endp) | ||
| 3486 | *p1 = g, g |= GLYPH_MASK_PADDING; | ||
| 3487 | p1++; | ||
| 3488 | } | ||
| 3489 | } | ||
| 3490 | /* If we did all the overlay strings | ||
| 3491 | and we have room for text, clear ovstr_done | ||
| 3492 | just for neatness' sake. */ | ||
| 3493 | if (ovlen == 0 && p1 < endp) | ||
| 3494 | ovstr_done = 0; | ||
| 3495 | } | ||
| 3496 | } | ||
| 3497 | |||
| 3498 | /* Did we reach point? Record the cursor location. */ | ||
| 3499 | if (pos == PT && cursor_vpos < 0) | ||
| 3500 | { | 9282 | { |
| 3501 | cursor_vpos = vpos; | 9283 | set_cursor_from_row (w, row, w->current_matrix, delta, |
| 3502 | cursor_hpos = p1 - leftmargin; | 9284 | delta_bytes, dy, dvpos); |
| 9285 | break; | ||
| 3503 | } | 9286 | } |
| 3504 | 9287 | else if (MATRIX_ROW_BOTTOM_Y (row) >= last_y) | |
| 3505 | if (pos >= ZV) | ||
| 3506 | break; | 9288 | break; |
| 3507 | 9289 | ++row; | |
| 3508 | XSETFASTINT (position, pos); | ||
| 3509 | limit = Fnext_overlay_change (position); | ||
| 3510 | #ifdef USE_TEXT_PROPERTIES | ||
| 3511 | /* This is just an estimate to give reasonable | ||
| 3512 | performance; nothing should go wrong if it is too small. */ | ||
| 3513 | if (XFASTINT (limit) > pos + 50) | ||
| 3514 | { | ||
| 3515 | int limitpos = pos + 50; | ||
| 3516 | XSETFASTINT (limit, limitpos); | ||
| 3517 | } | ||
| 3518 | limit = Fnext_single_property_change (position, Qinvisible, | ||
| 3519 | Fcurrent_buffer (), limit); | ||
| 3520 | #endif | ||
| 3521 | next_boundary = XFASTINT (limit); | ||
| 3522 | /* if the `invisible' property is set, we can skip to | ||
| 3523 | the next property change. */ | ||
| 3524 | XSETWINDOW (ww, w); | ||
| 3525 | prop = Fget_char_property (position, Qinvisible, ww); | ||
| 3526 | if (TEXT_PROP_MEANS_INVISIBLE (prop)) | ||
| 3527 | { | ||
| 3528 | if (pos < PT && next_boundary >= PT) | ||
| 3529 | { | ||
| 3530 | cursor_vpos = vpos; | ||
| 3531 | cursor_hpos = p1 - leftmargin; | ||
| 3532 | } | ||
| 3533 | pos = next_boundary; | ||
| 3534 | pos_byte = CHAR_TO_BYTE (pos); | ||
| 3535 | last_invis_skip = pos; | ||
| 3536 | last_invis_prop = prop; | ||
| 3537 | } | ||
| 3538 | } | 9290 | } |
| 9291 | } | ||
| 3539 | 9292 | ||
| 3540 | /* Did we reach point? Record the cursor location. */ | 9293 | /* Give up if cursor was not found. */ |
| 3541 | if (pos == PT && cursor_vpos < 0) | 9294 | if (w->cursor.vpos < 0) |
| 9295 | { | ||
| 9296 | clear_glyph_matrix (w->desired_matrix); | ||
| 9297 | return -1; | ||
| 9298 | } | ||
| 9299 | } | ||
| 9300 | |||
| 9301 | /* Don't let the cursor end in the scroll margins. */ | ||
| 9302 | { | ||
| 9303 | int this_scroll_margin, cursor_height; | ||
| 9304 | |||
| 9305 | this_scroll_margin = max (0, scroll_margin); | ||
| 9306 | this_scroll_margin = min (this_scroll_margin, | ||
| 9307 | XFASTINT (w->height) / 4); | ||
| 9308 | this_scroll_margin *= CANON_Y_UNIT (it.f); | ||
| 9309 | cursor_height = MATRIX_ROW (w->desired_matrix, w->cursor.vpos)->height; | ||
| 9310 | |||
| 9311 | if ((w->cursor.y < this_scroll_margin | ||
| 9312 | && CHARPOS (start) > BEGV) | ||
| 9313 | /* Don't take scroll margin into account at the bottom because | ||
| 9314 | old redisplay didn't do it either. */ | ||
| 9315 | || w->cursor.y + cursor_height > it.last_visible_y) | ||
| 9316 | { | ||
| 9317 | w->cursor.vpos = -1; | ||
| 9318 | clear_glyph_matrix (w->desired_matrix); | ||
| 9319 | return -1; | ||
| 9320 | } | ||
| 9321 | } | ||
| 9322 | |||
| 9323 | /* Scroll the display. Do it before changing the current matrix so | ||
| 9324 | that xterm.c doesn't get confused about where the cursor glyph is | ||
| 9325 | found. */ | ||
| 9326 | if (dy) | ||
| 9327 | { | ||
| 9328 | update_begin (f); | ||
| 9329 | |||
| 9330 | if (FRAME_WINDOW_P (f)) | ||
| 9331 | { | ||
| 9332 | rif->update_window_begin_hook (w); | ||
| 9333 | rif->scroll_run_hook (w, &run); | ||
| 9334 | rif->update_window_end_hook (w, 0); | ||
| 9335 | } | ||
| 9336 | else | ||
| 9337 | { | ||
| 9338 | /* Terminal frame. In this case, dvpos gives the number of | ||
| 9339 | lines to scroll by; dvpos < 0 means scroll up. */ | ||
| 9340 | int first_unchanged_at_end_vpos | ||
| 9341 | = MATRIX_ROW_VPOS (first_unchanged_at_end_row, w->current_matrix); | ||
| 9342 | int from = XFASTINT (w->top) + first_unchanged_at_end_vpos; | ||
| 9343 | int end = XFASTINT (w->top) + window_internal_height (w); | ||
| 9344 | |||
| 9345 | /* Perform the operation on the screen. */ | ||
| 9346 | if (dvpos > 0) | ||
| 3542 | { | 9347 | { |
| 3543 | cursor_vpos = vpos; | 9348 | /* Scroll last_unchanged_at_beg_row to the end of the |
| 3544 | cursor_hpos = p1 - leftmargin; | 9349 | window down dvpos lines. */ |
| 9350 | set_terminal_window (end); | ||
| 9351 | |||
| 9352 | /* On dumb terminals delete dvpos lines at the end | ||
| 9353 | before inserting dvpos empty lines. */ | ||
| 9354 | if (!scroll_region_ok) | ||
| 9355 | ins_del_lines (end - dvpos, -dvpos); | ||
| 9356 | |||
| 9357 | /* Insert dvpos empty lines in front of | ||
| 9358 | last_unchanged_at_beg_row. */ | ||
| 9359 | ins_del_lines (from, dvpos); | ||
| 3545 | } | 9360 | } |
| 3546 | 9361 | else if (dvpos < 0) | |
| 3547 | /* Did we hit the end of the visible region of the buffer? | ||
| 3548 | Stop here. */ | ||
| 3549 | if (pos >= ZV) | ||
| 3550 | { | 9362 | { |
| 3551 | /* Update charstarts for the end of this line. */ | 9363 | /* Scroll up last_unchanged_at_beg_vpos to the end of |
| 3552 | /* Do nothing if off the left edge or at the right edge. */ | 9364 | the window to last_unchanged_at_beg_vpos - |dvpos|. */ |
| 3553 | if (p1 >= leftmargin && p1 + 1 != endp) | 9365 | set_terminal_window (end); |
| 3554 | { | 9366 | |
| 3555 | int *p2x = &charstart[(p1 < leftmargin | 9367 | /* Delete dvpos lines in front of |
| 3556 | ? leftmargin : p1) | 9368 | last_unchanged_at_beg_vpos. ins_del_lines will set |
| 3557 | - p1start]; | 9369 | the cursor to the given vpos and emit |dvpos| delete |
| 3558 | *p2x++ = pos; | 9370 | line sequences. */ |
| 3559 | } | 9371 | ins_del_lines (from + dvpos, dvpos); |
| 3560 | break; | 9372 | |
| 9373 | /* On a dumb terminal insert dvpos empty lines at the | ||
| 9374 | end. */ | ||
| 9375 | if (!scroll_region_ok) | ||
| 9376 | ins_del_lines (end + dvpos, -dvpos); | ||
| 3561 | } | 9377 | } |
| 9378 | |||
| 9379 | set_terminal_window (0); | ||
| 9380 | } | ||
| 9381 | |||
| 9382 | update_end (f); | ||
| 9383 | } | ||
| 3562 | 9384 | ||
| 3563 | /* Figure out where (if at all) the | 9385 | /* Shift reused rows of the current matrix to the right position. */ |
| 3564 | redisplay_end_trigger-hook should run. */ | 9386 | if (dvpos < 0) |
| 3565 | if (MARKERP (w->redisplay_end_trigger) | 9387 | { |
| 3566 | && XMARKER (w->redisplay_end_trigger)->buffer != 0) | 9388 | rotate_matrix (current_matrix, first_unchanged_at_end_vpos + dvpos, |
| 3567 | e_t_h = marker_position (w->redisplay_end_trigger); | 9389 | bottom_vpos, dvpos); |
| 3568 | else if (INTEGERP (w->redisplay_end_trigger)) | 9390 | enable_glyph_matrix_rows (current_matrix, bottom_vpos + dvpos, |
| 3569 | e_t_h = XINT (w->redisplay_end_trigger); | 9391 | bottom_vpos, 0); |
| 3570 | else | 9392 | } |
| 3571 | e_t_h = ZV; | 9393 | else if (dvpos > 0) |
| 9394 | { | ||
| 9395 | rotate_matrix (current_matrix, first_unchanged_at_end_vpos, | ||
| 9396 | bottom_vpos, dvpos); | ||
| 9397 | enable_glyph_matrix_rows (current_matrix, first_unchanged_at_end_vpos, | ||
| 9398 | first_unchanged_at_end_vpos + dvpos, 0); | ||
| 9399 | } | ||
| 3572 | 9400 | ||
| 3573 | /* If we've gone past the place to run a hook, | 9401 | /* For frame-based redisplay, make sure that current frame and window |
| 3574 | run the hook. */ | 9402 | matrix are in sync with respect to glyph memory. */ |
| 3575 | if (pos >= e_t_h && e_t_h != ZV) | 9403 | if (!FRAME_WINDOW_P (f)) |
| 3576 | { | 9404 | sync_frame_with_window_matrix_rows (w); |
| 3577 | Lisp_Object args[3]; | 9405 | |
| 9406 | /* Adjust buffer positions in reused rows. */ | ||
| 9407 | if (delta) | ||
| 9408 | increment_glyph_matrix_buffer_positions (current_matrix, | ||
| 9409 | first_unchanged_at_end_vpos + dvpos, | ||
| 9410 | bottom_vpos, delta, delta_bytes); | ||
| 9411 | |||
| 9412 | /* Adjust Y positions. */ | ||
| 9413 | if (dy) | ||
| 9414 | shift_glyph_matrix (w, current_matrix, | ||
| 9415 | first_unchanged_at_end_vpos + dvpos, | ||
| 9416 | bottom_vpos, dy); | ||
| 9417 | |||
| 9418 | if (first_unchanged_at_end_row) | ||
| 9419 | first_unchanged_at_end_row += dvpos; | ||
| 9420 | |||
| 9421 | /* If scrolling up, there may be some lines to display at the end of | ||
| 9422 | the window. */ | ||
| 9423 | last_text_row_at_end = NULL; | ||
| 9424 | if (dy < 0) | ||
| 9425 | { | ||
| 9426 | /* Set last_row to the glyph row in the current matrix where the | ||
| 9427 | window end line is found. It has been moved up or down in | ||
| 9428 | the matrix by dvpos. */ | ||
| 9429 | int last_vpos = XFASTINT (w->window_end_vpos) + dvpos; | ||
| 9430 | struct glyph_row *last_row = MATRIX_ROW (current_matrix, last_vpos); | ||
| 9431 | |||
| 9432 | /* If last_row is the window end line, it should display text. */ | ||
| 9433 | xassert (last_row->displays_text_p); | ||
| 9434 | |||
| 9435 | /* If window end line was partially visible before, begin | ||
| 9436 | displaying at that line. Otherwise begin displaying with the | ||
| 9437 | line following it. */ | ||
| 9438 | if (MATRIX_ROW_BOTTOM_Y (last_row) - dy >= it.last_visible_y) | ||
| 9439 | { | ||
| 9440 | init_to_row_start (&it, w, last_row); | ||
| 9441 | it.vpos = last_vpos; | ||
| 9442 | it.current_y = last_row->y; | ||
| 9443 | } | ||
| 9444 | else | ||
| 9445 | { | ||
| 9446 | init_to_row_end (&it, w, last_row); | ||
| 9447 | it.vpos = 1 + last_vpos; | ||
| 9448 | it.current_y = MATRIX_ROW_BOTTOM_Y (last_row); | ||
| 9449 | ++last_row; | ||
| 9450 | } | ||
| 3578 | 9451 | ||
| 3579 | args[0] = Qredisplay_end_trigger_functions; | 9452 | /* We may start in a continuation line. If so, we have to get |
| 3580 | XSETWINDOW (args[1], w); | 9453 | the right continuation_lines_width and current_x. */ |
| 3581 | XSETINT (args[2], e_t_h); | 9454 | it.continuation_lines_width = last_row->continuation_lines_width; |
| 9455 | it.hpos = it.current_x = 0; | ||
| 9456 | |||
| 9457 | /* Display the rest of the lines at the window end. */ | ||
| 9458 | it.glyph_row = MATRIX_ROW (desired_matrix, it.vpos); | ||
| 9459 | while (it.current_y < it.last_visible_y | ||
| 9460 | && !fonts_changed_p) | ||
| 9461 | { | ||
| 9462 | /* Is it always sure that the display agrees with lines in | ||
| 9463 | the current matrix? I don't think so, so we mark rows | ||
| 9464 | displayed invalid in the current matrix by setting their | ||
| 9465 | enabled_p flag to zero. */ | ||
| 9466 | MATRIX_ROW (w->current_matrix, it.vpos)->enabled_p = 0; | ||
| 9467 | if (display_line (&it)) | ||
| 9468 | last_text_row_at_end = it.glyph_row - 1; | ||
| 9469 | } | ||
| 9470 | } | ||
| 3582 | 9471 | ||
| 3583 | /* Since we are *trying* to run these functions, | 9472 | /* Update window_end_pos and window_end_vpos. */ |
| 3584 | don't try to run them again, even if they get an error. */ | 9473 | if (first_unchanged_at_end_row |
| 3585 | w->redisplay_end_trigger = Qnil; | 9474 | && first_unchanged_at_end_row->y < it.last_visible_y |
| 3586 | Frun_hook_with_args (3, args); | 9475 | && !last_text_row_at_end) |
| 9476 | { | ||
| 9477 | /* Window end line if one of the preserved rows from the current | ||
| 9478 | matrix. Set row to the last row displaying text in current | ||
| 9479 | matrix starting at first_unchanged_at_end_row, after | ||
| 9480 | scrolling. */ | ||
| 9481 | xassert (first_unchanged_at_end_row->displays_text_p); | ||
| 9482 | row = find_last_row_displaying_text (w->current_matrix, &it, | ||
| 9483 | first_unchanged_at_end_row); | ||
| 9484 | xassert (row && MATRIX_ROW_DISPLAYS_TEXT_P (row)); | ||
| 9485 | |||
| 9486 | XSETFASTINT (w->window_end_pos, Z - MATRIX_ROW_END_CHARPOS (row)); | ||
| 9487 | w->window_end_bytepos = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row); | ||
| 9488 | XSETFASTINT (w->window_end_vpos, | ||
| 9489 | MATRIX_ROW_VPOS (row, w->current_matrix)); | ||
| 9490 | } | ||
| 9491 | else if (last_text_row_at_end) | ||
| 9492 | { | ||
| 9493 | XSETFASTINT (w->window_end_pos, | ||
| 9494 | Z - MATRIX_ROW_END_CHARPOS (last_text_row_at_end)); | ||
| 9495 | w->window_end_bytepos | ||
| 9496 | = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row_at_end); | ||
| 9497 | XSETFASTINT (w->window_end_vpos, | ||
| 9498 | MATRIX_ROW_VPOS (last_text_row_at_end, desired_matrix)); | ||
| 9499 | } | ||
| 9500 | else if (last_text_row) | ||
| 9501 | { | ||
| 9502 | /* We have displayed either to the end of the window or at the | ||
| 9503 | end of the window, i.e. the last row with text is to be found | ||
| 9504 | in the desired matrix. */ | ||
| 9505 | XSETFASTINT (w->window_end_pos, | ||
| 9506 | Z - MATRIX_ROW_END_CHARPOS (last_text_row)); | ||
| 9507 | w->window_end_bytepos | ||
| 9508 | = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row); | ||
| 9509 | XSETFASTINT (w->window_end_vpos, | ||
| 9510 | MATRIX_ROW_VPOS (last_text_row, desired_matrix)); | ||
| 9511 | } | ||
| 9512 | else if (first_unchanged_at_end_row == NULL | ||
| 9513 | && last_text_row == NULL | ||
| 9514 | && last_text_row_at_end == NULL) | ||
| 9515 | { | ||
| 9516 | /* Displayed to end of window, but no line containing text was | ||
| 9517 | displayed. Lines were deleted at the end of the window. */ | ||
| 9518 | int vpos; | ||
| 9519 | int top_line_p = WINDOW_WANTS_TOP_LINE_P (w) ? 1 : 0; | ||
| 9520 | |||
| 9521 | for (vpos = XFASTINT (w->window_end_vpos); vpos > 0; --vpos) | ||
| 9522 | if ((w->desired_matrix->rows[vpos + top_line_p].enabled_p | ||
| 9523 | && w->desired_matrix->rows[vpos + top_line_p].displays_text_p) | ||
| 9524 | || (!w->desired_matrix->rows[vpos + top_line_p].enabled_p | ||
| 9525 | && w->current_matrix->rows[vpos + top_line_p].displays_text_p)) | ||
| 9526 | break; | ||
| 3587 | 9527 | ||
| 3588 | e_t_h = ZV; | 9528 | w->window_end_vpos = make_number (vpos); |
| 3589 | /* Notice if it changed the face of this character. */ | 9529 | } |
| 3590 | next_face_change = pos; | 9530 | else |
| 3591 | } | 9531 | abort (); |
| 9532 | |||
| 9533 | IF_DEBUG (debug_end_pos = XFASTINT (w->window_end_pos); | ||
| 9534 | debug_end_vpos = XFASTINT (w->window_end_vpos)); | ||
| 3592 | 9535 | ||
| 3593 | #ifdef HAVE_FACES | 9536 | /* Record that display has not been completed. */ |
| 3594 | /* Did we hit a face change? Figure out what face we should | 9537 | w->window_end_valid = Qnil; |
| 3595 | use now. We also hit this the first time through the | 9538 | w->desired_matrix->no_scrolling_p = 1; |
| 3596 | loop, to see what face we should start with. */ | 9539 | return 1; |
| 3597 | if (pos >= next_face_change | 9540 | } |
| 3598 | && (FRAME_WINDOW_P (f) || FRAME_MSDOS_P (f))) | ||
| 3599 | { | ||
| 3600 | int limit = pos + 50; | ||
| 3601 | 9541 | ||
| 3602 | current_face = compute_char_face (f, w, pos, | ||
| 3603 | region_beg, region_end, | ||
| 3604 | &next_face_change, limit, 0); | ||
| 3605 | } | ||
| 3606 | #endif | ||
| 3607 | 9542 | ||
| 3608 | /* Compute the next place we need to stop | 9543 | |
| 3609 | and do something special; set PAUSE. */ | 9544 | /*********************************************************************** |
| 9545 | More debugging support | ||
| 9546 | ***********************************************************************/ | ||
| 3610 | 9547 | ||
| 3611 | pause = ZV; | 9548 | #if GLYPH_DEBUG |
| 3612 | 9549 | ||
| 3613 | if (pos < next_boundary && next_boundary < pause) | 9550 | void dump_glyph_row P_ ((struct glyph_matrix *, int, int)); |
| 3614 | pause = next_boundary; | 9551 | static void dump_glyph_matrix P_ ((struct glyph_matrix *, int)); |
| 3615 | if (pos < next_face_change && next_face_change < pause) | ||
| 3616 | pause = next_face_change; | ||
| 3617 | 9552 | ||
| 3618 | if (e_t_h < pause) | ||
| 3619 | pause = e_t_h; | ||
| 3620 | 9553 | ||
| 3621 | /* Wouldn't you hate to read the next line to someone over | 9554 | /* Dump the contents of glyph matrix MATRIX on stderr. If |
| 3622 | the phone? */ | 9555 | WITH_GLYPHS_P is non-zero, dump glyph contents as well. */ |
| 3623 | if (pos < PT && PT < pause) | ||
| 3624 | pause = PT; | ||
| 3625 | if (pos < GPT && GPT < pause) | ||
| 3626 | pause = GPT; | ||
| 3627 | 9556 | ||
| 3628 | /* LIMIT_BYTE is not the same place in the buffer as PAUSE. | 9557 | void |
| 3629 | It is a limit on valid characters. | 9558 | dump_glyph_matrix (matrix, with_glyphs_p) |
| 3630 | We use it to bound STRING_CHAR_AND_LENGTH. */ | 9559 | struct glyph_matrix *matrix; |
| 3631 | limit_byte = ZV_BYTE; | 9560 | int with_glyphs_p; |
| 3632 | if (pos < GPT && GPT_BYTE < limit_byte) | 9561 | { |
| 3633 | limit_byte = GPT_BYTE; | 9562 | int i; |
| 9563 | for (i = 0; i < matrix->nrows; ++i) | ||
| 9564 | dump_glyph_row (matrix, i, with_glyphs_p); | ||
| 9565 | } | ||
| 3634 | 9566 | ||
| 3635 | { | ||
| 3636 | int temp = CHAR_TO_BYTE (pos); | ||
| 3637 | p = BYTE_POS_ADDR (temp); | ||
| 3638 | } | ||
| 3639 | } | ||
| 3640 | 9567 | ||
| 3641 | if (p1 >= endp) | 9568 | /* Dump the contents of glyph row at VPOS in MATRIX to stderr. |
| 3642 | break; | 9569 | WITH_GLYPH_SP non-zero means dump glyph contents, too. */ |
| 3643 | 9570 | ||
| 3644 | p1prev = p1; | 9571 | void |
| 3645 | p1_wide_column_end = (GLYPH *) 0; | 9572 | dump_glyph_row (matrix, vpos, with_glyphs_p) |
| 9573 | struct glyph_matrix *matrix; | ||
| 9574 | int vpos, with_glyphs_p; | ||
| 9575 | { | ||
| 9576 | struct glyph_row *row; | ||
| 9577 | |||
| 9578 | if (vpos < 0 || vpos >= matrix->nrows) | ||
| 9579 | return; | ||
| 3646 | 9580 | ||
| 3647 | if (multibyte) | 9581 | row = MATRIX_ROW (matrix, vpos); |
| 3648 | c = STRING_CHAR_AND_LENGTH (p, limit_byte - pos_byte, len), p += len; | 9582 | |
| 3649 | else | 9583 | fprintf (stderr, "Row Start End Used oEI><O\\CTZF X Y W\n"); |
| 3650 | c = *p++, len = 1; | 9584 | fprintf (stderr, "=============================================\n"); |
| 3651 | /* Let a display table override all standard display methods. */ | 9585 | |
| 3652 | if (dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, c))) | 9586 | fprintf (stderr, "%3d %5d %5d %4d %1.1d%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d %4d %4d %4d\n", |
| 3653 | { | 9587 | row - matrix->rows, |
| 3654 | p1 = copy_part_of_rope (f, p1, leftmargin, | 9588 | MATRIX_ROW_START_CHARPOS (row), |
| 3655 | XVECTOR (DISP_CHAR_VECTOR (dp, c))->contents, | 9589 | MATRIX_ROW_END_CHARPOS (row), |
| 3656 | XVECTOR (DISP_CHAR_VECTOR (dp, c))->size, | 9590 | row->used[TEXT_AREA], |
| 3657 | current_face, rev_dir_bit); | 9591 | row->contains_overlapping_glyphs_p, |
| 3658 | } | 9592 | row->enabled_p, |
| 3659 | else if (c >= 040 && c < 0177) | 9593 | row->inverse_p, |
| 9594 | row->truncated_on_left_p, | ||
| 9595 | row->truncated_on_right_p, | ||
| 9596 | row->overlay_arrow_p, | ||
| 9597 | row->continued_p, | ||
| 9598 | MATRIX_ROW_CONTINUATION_LINE_P (row), | ||
| 9599 | row->displays_text_p, | ||
| 9600 | row->ends_at_zv_p, | ||
| 9601 | row->fill_line_p, | ||
| 9602 | row->x, | ||
| 9603 | row->y, | ||
| 9604 | row->pixel_width); | ||
| 9605 | fprintf (stderr, "%9d %5d\n", row->start.overlay_string_index, | ||
| 9606 | row->end.overlay_string_index); | ||
| 9607 | fprintf (stderr, "%9d %5d\n", | ||
| 9608 | CHARPOS (row->start.string_pos), | ||
| 9609 | CHARPOS (row->end.string_pos)); | ||
| 9610 | fprintf (stderr, "%9d %5d\n", row->start.dpvec_index, | ||
| 9611 | row->end.dpvec_index); | ||
| 9612 | |||
| 9613 | if (with_glyphs_p) | ||
| 9614 | { | ||
| 9615 | struct glyph *glyph, *glyph_end; | ||
| 9616 | int prev_had_glyphs_p; | ||
| 9617 | |||
| 9618 | glyph = row->glyphs[TEXT_AREA]; | ||
| 9619 | glyph_end = glyph + row->used[TEXT_AREA]; | ||
| 9620 | |||
| 9621 | /* Glyph for a line end in text. */ | ||
| 9622 | if (glyph == glyph_end && glyph->charpos > 0) | ||
| 9623 | ++glyph_end; | ||
| 9624 | |||
| 9625 | if (glyph < glyph_end) | ||
| 3660 | { | 9626 | { |
| 3661 | if (p1 >= leftmargin) | 9627 | fprintf (stderr, " Glyph Type Pos W Code C Face LR\n"); |
| 3662 | *p1 = MAKE_GLYPH (f, c, current_face) | rev_dir_bit; | 9628 | prev_had_glyphs_p = 1; |
| 3663 | p1++; | ||
| 3664 | } | 9629 | } |
| 3665 | else if (c == '\n') | 9630 | else |
| 9631 | prev_had_glyphs_p = 0; | ||
| 9632 | |||
| 9633 | while (glyph < glyph_end) | ||
| 3666 | { | 9634 | { |
| 3667 | #if 0 | 9635 | if (glyph->type == CHAR_GLYPH) |
| 3668 | /* Same as p1prev, but after the invis_vector_contents text | ||
| 3669 | (if we have that on this line). */ | ||
| 3670 | GLYPH *p1prev_modified; | ||
| 3671 | #endif | ||
| 3672 | |||
| 3673 | invis = 0; | ||
| 3674 | if (last_invis_skip == pos | ||
| 3675 | && TEXT_PROP_MEANS_INVISIBLE_WITH_ELLIPSIS (last_invis_prop)) | ||
| 3676 | invis = 1; | ||
| 3677 | while (pos + 1 < ZV | ||
| 3678 | && selective > 0 | ||
| 3679 | && indented_beyond_p (pos + 1, pos_byte + 1, selective)) | ||
| 3680 | { | 9636 | { |
| 3681 | int opoint = PT, opoint_byte = PT_BYTE; | 9637 | fprintf (stderr, |
| 3682 | 9638 | " %5d %4c %6d %3d 0x%05x %c %4d %1.1d%1.1d\n", | |
| 3683 | invis = 1; | 9639 | glyph - row->glyphs[TEXT_AREA], |
| 3684 | INC_BOTH (pos, pos_byte); | 9640 | 'C', |
| 3685 | scan_newline (pos, pos_byte, ZV, ZV_BYTE, 1, 1); | 9641 | glyph->charpos, |
| 3686 | pos = PT, pos_byte = PT_BYTE; | 9642 | glyph->pixel_width, |
| 3687 | if (FETCH_BYTE (pos_byte - 1) == '\n') | 9643 | glyph->u.ch.code, |
| 3688 | { | 9644 | (glyph->u.ch.code < 0x80 && glyph->u.ch.code >= ' ' |
| 3689 | pos--; | 9645 | ? glyph->u.ch.code |
| 3690 | pos_byte--; | 9646 | : '.'), |
| 3691 | } | 9647 | glyph->u.ch.face_id, |
| 3692 | TEMP_SET_PT_BOTH (opoint, opoint_byte); | 9648 | glyph->left_box_line_p, |
| 9649 | glyph->right_box_line_p); | ||
| 3693 | } | 9650 | } |
| 3694 | if (invis && selective_rlen > 0 && p1 >= leftmargin) | 9651 | else if (glyph->type == STRETCH_GLYPH) |
| 3695 | { | 9652 | { |
| 3696 | #if 0 | 9653 | fprintf (stderr, |
| 3697 | GLYPH *cs, *csend; | 9654 | " %5d %4c %6d %3d 0x%05x %c %4d %1.1d%1.1d\n", |
| 9655 | glyph - row->glyphs[TEXT_AREA], | ||
| 9656 | 'S', | ||
| 9657 | glyph->charpos, | ||
| 9658 | glyph->pixel_width, | ||
| 9659 | 0, | ||
| 9660 | '.', | ||
| 9661 | glyph->u.stretch.face_id, | ||
| 9662 | glyph->left_box_line_p, | ||
| 9663 | glyph->right_box_line_p); | ||
| 9664 | } | ||
| 9665 | else if (glyph->type == IMAGE_GLYPH) | ||
| 9666 | { | ||
| 9667 | fprintf (stderr, | ||
| 9668 | " %5d %4c %6d %3d 0x%05x %c %4d %1.1d%1.1d\n", | ||
| 9669 | glyph - row->glyphs[TEXT_AREA], | ||
| 9670 | 'I', | ||
| 9671 | glyph->charpos, | ||
| 9672 | glyph->pixel_width, | ||
| 9673 | glyph->u.img.id, | ||
| 9674 | '.', | ||
| 9675 | glyph->u.img.face_id, | ||
| 9676 | glyph->left_box_line_p, | ||
| 9677 | glyph->right_box_line_p); | ||
| 9678 | } | ||
| 9679 | ++glyph; | ||
| 9680 | } | ||
| 9681 | } | ||
| 9682 | } | ||
| 3698 | 9683 | ||
| 3699 | cs = charstart + (p1 - p1start); | ||
| 3700 | #endif | ||
| 3701 | 9684 | ||
| 3702 | p1 += selective_rlen; | 9685 | DEFUN ("dump-glyph-matrix", Fdump_glyph_matrix, |
| 3703 | if (p1 - leftmargin > width) | 9686 | Sdump_glyph_matrix, 0, 1, "p", |
| 3704 | p1 = endp; | 9687 | "Dump the current matrix of the selected window to stderr.\n\ |
| 3705 | 9688 | Shows contents of glyph row structures. With non-nil optional\n\ | |
| 3706 | #if 0 /* This needs more work; charstarts needs to record | 9689 | parameter WITH-GLYPHS-P, dump glyphs as well.") |
| 3707 | both whether a position ho;ds an ellipsis character | 9690 | (with_glyphs_p) |
| 3708 | and what buffer position it corresponds to. */ | 9691 | { |
| 3709 | csend = charstart + (p1 - p1start); | 9692 | struct window *w = XWINDOW (selected_window); |
| 3710 | while (cs != csend) | 9693 | struct buffer *buffer = XBUFFER (w->buffer); |
| 3711 | *cs++ = -2; | 9694 | |
| 3712 | /* The idea is to use p1prev_modified instead of p1prev | 9695 | fprintf (stderr, "PT = %d, BEGV = %d. ZV = %d\n", |
| 3713 | in the loop below over p2x. */ | 9696 | BUF_PT (buffer), BUF_BEGV (buffer), BUF_ZV (buffer)); |
| 3714 | p1prev_modified = p1; | 9697 | fprintf (stderr, "Cursor x = %d, y = %d, hpos = %d, vpos = %d\n", |
| 3715 | #endif | 9698 | w->cursor.x, w->cursor.y, w->cursor.hpos, w->cursor.vpos); |
| 9699 | fprintf (stderr, "=============================================\n"); | ||
| 9700 | dump_glyph_matrix (w->current_matrix, !NILP (with_glyphs_p)); | ||
| 9701 | return Qnil; | ||
| 9702 | } | ||
| 3716 | 9703 | ||
| 3717 | copy_part_of_rope (f, p1prev, p1prev, invis_vector_contents, | ||
| 3718 | (p1 - p1prev), current_face, rev_dir_bit); | ||
| 3719 | } | ||
| 3720 | 9704 | ||
| 3721 | /* Update charstarts for the newline that ended this line. */ | 9705 | DEFUN ("dump-glyph-row", Fdump_glyph_row, Sdump_glyph_row, 1, 1, "", |
| 3722 | /* Do nothing here for a char that's entirely off the left edge | 9706 | "Dump glyph row ROW to stderr.") |
| 3723 | or if it starts at the right edge. */ | 9707 | (row) |
| 3724 | if (p1 >= leftmargin && p1prev != endp) | 9708 | Lisp_Object row; |
| 3725 | { | 9709 | { |
| 3726 | /* Store the newline's position into charstarts | 9710 | CHECK_NUMBER (row, 0); |
| 3727 | for the column where the newline starts. | 9711 | dump_glyph_row (XWINDOW (selected_window)->current_matrix, XINT (row), 1); |
| 3728 | Store -1 for the rest of the glyphs it occupies. */ | 9712 | return Qnil; |
| 3729 | int *p2x = &charstart[(p1prev < leftmargin | 9713 | } |
| 3730 | ? leftmargin : p1prev) | ||
| 3731 | - p1start]; | ||
| 3732 | int *p2 = &charstart[(p1 < endp ? p1 : endp) - p1start]; | ||
| 3733 | |||
| 3734 | *p2x++ = pos; | ||
| 3735 | while (p2x < p2) | ||
| 3736 | *p2x++ = -1; | ||
| 3737 | } | ||
| 3738 | #ifdef HAVE_FACES | ||
| 3739 | /* Draw the face of the newline character as extending all the | ||
| 3740 | way to the end of the frame line. */ | ||
| 3741 | if (current_face) | ||
| 3742 | { | ||
| 3743 | if (p1 < leftmargin) | ||
| 3744 | p1 = leftmargin; | ||
| 3745 | while (p1 < endp) | ||
| 3746 | *p1++ = FAST_MAKE_GLYPH (' ', current_face) | rev_dir_bit; | ||
| 3747 | } | ||
| 3748 | #endif | ||
| 3749 | 9714 | ||
| 3750 | break; | ||
| 3751 | } | ||
| 3752 | else if (c == '\t') | ||
| 3753 | { | ||
| 3754 | do | ||
| 3755 | { | ||
| 3756 | if (p1 >= leftmargin && p1 < endp) | ||
| 3757 | *p1 = MAKE_GLYPH (f, ' ', current_face) | rev_dir_bit; | ||
| 3758 | p1++; | ||
| 3759 | } | ||
| 3760 | while ((p1 - leftmargin + taboffset + hscroll - (hscroll > 0)) | ||
| 3761 | % tab_width); | ||
| 3762 | } | ||
| 3763 | else if (c == Ctl ('M') && selective == -1) | ||
| 3764 | { | ||
| 3765 | int opoint = PT, opoint_byte = PT_BYTE; | ||
| 3766 | scan_newline (pos, pos_byte, ZV, ZV_BYTE, 1, 1); | ||
| 3767 | pos = PT, pos_byte = PT_BYTE; | ||
| 3768 | TEMP_SET_PT_BOTH (opoint, opoint_byte); | ||
| 3769 | 9715 | ||
| 3770 | if (FETCH_BYTE (pos_byte - 1) == '\n') | 9716 | DEFUN ("dump-toolbar-row", Fdump_toolbar_row, Sdump_toolbar_row, |
| 3771 | pos--, pos_byte--; | 9717 | 0, 0, "", "") |
| 3772 | if (selective_rlen > 0) | 9718 | () |
| 3773 | { | 9719 | { |
| 3774 | p1 += selective_rlen; | 9720 | struct glyph_matrix *m = (XWINDOW (selected_frame->toolbar_window) |
| 3775 | if (p1 - leftmargin > width) | 9721 | ->current_matrix); |
| 3776 | p1 = endp; | 9722 | dump_glyph_row (m, 0, 1); |
| 3777 | copy_part_of_rope (f, p1prev, p1prev, invis_vector_contents, | 9723 | return Qnil; |
| 3778 | (p1 - p1prev), current_face, rev_dir_bit); | 9724 | } |
| 3779 | } | ||
| 3780 | #ifdef HAVE_FACES | ||
| 3781 | /* Draw the face of the newline character as extending all the | ||
| 3782 | way to the end of the frame line. */ | ||
| 3783 | if (current_face) | ||
| 3784 | { | ||
| 3785 | if (p1 < leftmargin) | ||
| 3786 | p1 = leftmargin; | ||
| 3787 | while (p1 < endp) | ||
| 3788 | *p1++ = FAST_MAKE_GLYPH (' ', current_face) | rev_dir_bit; | ||
| 3789 | } | ||
| 3790 | #endif | ||
| 3791 | 9725 | ||
| 3792 | /* Update charstarts for the ^M that ended this line. */ | 9726 | |
| 3793 | /* Do nothing here for a char that's entirely off the left edge | 9727 | DEFUN ("trace-redisplay-toggle", Ftrace_redisplay_toggle, |
| 3794 | or if it starts at the right edge. */ | 9728 | Strace_redisplay_toggle, 0, 0, "", |
| 3795 | if (p1 >= leftmargin && p1prev != endp) | 9729 | "Toggle tracing of redisplay.") |
| 3796 | { | 9730 | () |
| 3797 | /* Store the newline's position into charstarts | 9731 | { |
| 3798 | for the column where the newline starts. | 9732 | trace_redisplay_p = !trace_redisplay_p; |
| 3799 | Store -1 for the rest of the glyphs it occupies. */ | 9733 | return Qnil; |
| 3800 | int *p2x = &charstart[(p1prev < leftmargin | 9734 | } |
| 3801 | ? leftmargin : p1prev) | 9735 | |
| 3802 | - p1start]; | 9736 | |
| 3803 | int *p2 = &charstart[(p1 < endp ? p1 : endp) - p1start]; | 9737 | #endif /* GLYPH_DEBUG */ |
| 3804 | 9738 | ||
| 3805 | *p2x++ = pos; | 9739 | |
| 3806 | while (p2x < p2) | 9740 | |
| 3807 | *p2x++ = -1; | 9741 | /*********************************************************************** |
| 3808 | } | 9742 | Building Desired Matrix Rows |
| 9743 | ***********************************************************************/ | ||
| 9744 | |||
| 9745 | /* Return a temporary glyph row holding the glyphs of an overlay | ||
| 9746 | arrow. Only used for non-window-redisplay windows. */ | ||
| 9747 | |||
| 9748 | static struct glyph_row * | ||
| 9749 | get_overlay_arrow_glyph_row (w) | ||
| 9750 | struct window *w; | ||
| 9751 | { | ||
| 9752 | struct frame *f = XFRAME (WINDOW_FRAME (w)); | ||
| 9753 | struct buffer *buffer = XBUFFER (w->buffer); | ||
| 9754 | struct buffer *old = current_buffer; | ||
| 9755 | unsigned char *arrow_string = XSTRING (Voverlay_arrow_string)->data; | ||
| 9756 | int arrow_len = XSTRING (Voverlay_arrow_string)->size; | ||
| 9757 | unsigned char *arrow_end = arrow_string + arrow_len; | ||
| 9758 | unsigned char *p; | ||
| 9759 | struct it it; | ||
| 9760 | int multibyte_p; | ||
| 9761 | int n_glyphs_before; | ||
| 9762 | |||
| 9763 | set_buffer_temp (buffer); | ||
| 9764 | init_iterator (&it, w, -1, -1, &scratch_glyph_row, DEFAULT_FACE_ID); | ||
| 9765 | it.glyph_row->used[TEXT_AREA] = 0; | ||
| 9766 | SET_TEXT_POS (it.position, 0, 0); | ||
| 9767 | |||
| 9768 | multibyte_p = !NILP (buffer->enable_multibyte_characters); | ||
| 9769 | p = arrow_string; | ||
| 9770 | while (p < arrow_end) | ||
| 9771 | { | ||
| 9772 | Lisp_Object face, ilisp; | ||
| 9773 | |||
| 9774 | /* Get the next character. */ | ||
| 9775 | if (multibyte_p) | ||
| 9776 | it.c = STRING_CHAR_AND_LENGTH (p, arrow_len, it.len); | ||
| 9777 | else | ||
| 9778 | it.c = *p, it.len = 1; | ||
| 9779 | p += it.len; | ||
| 9780 | |||
| 9781 | /* Get its face. */ | ||
| 9782 | XSETFASTINT (ilisp, p - arrow_string); | ||
| 9783 | face = Fget_text_property (ilisp, Qface, Voverlay_arrow_string); | ||
| 9784 | it.face_id = compute_char_face (f, it.c, face); | ||
| 9785 | |||
| 9786 | /* Compute its width, get its glyphs. */ | ||
| 9787 | n_glyphs_before = it.glyph_row->used[TEXT_AREA]; | ||
| 9788 | PRODUCE_GLYPHS (&it); | ||
| 9789 | |||
| 9790 | /* If this character doesn't fit any more in the line, we have | ||
| 9791 | to remove some glyphs. */ | ||
| 9792 | if (it.current_x > it.last_visible_x) | ||
| 9793 | { | ||
| 9794 | it.glyph_row->used[TEXT_AREA] = n_glyphs_before; | ||
| 3809 | break; | 9795 | break; |
| 3810 | } | 9796 | } |
| 3811 | else if (c < 0200 && ctl_arrow) | 9797 | } |
| 9798 | |||
| 9799 | set_buffer_temp (old); | ||
| 9800 | return it.glyph_row; | ||
| 9801 | } | ||
| 9802 | |||
| 9803 | |||
| 9804 | /* Insert truncation glyphs at the start of IT->glyph_row. Truncation | ||
| 9805 | glyphs are only inserted for terminal frames since we can't really | ||
| 9806 | win with truncation glyphs when partially visible glyphs are | ||
| 9807 | involved. Which glyphs to insert is determined by | ||
| 9808 | produce_special_glyphs. */ | ||
| 9809 | |||
| 9810 | static void | ||
| 9811 | insert_left_trunc_glyphs (it) | ||
| 9812 | struct it *it; | ||
| 9813 | { | ||
| 9814 | struct it truncate_it; | ||
| 9815 | struct glyph *from, *end, *to, *toend; | ||
| 9816 | |||
| 9817 | xassert (!FRAME_WINDOW_P (it->f)); | ||
| 9818 | |||
| 9819 | /* Get the truncation glyphs. */ | ||
| 9820 | truncate_it = *it; | ||
| 9821 | truncate_it.charset = -1; | ||
| 9822 | truncate_it.current_x = 0; | ||
| 9823 | truncate_it.face_id = DEFAULT_FACE_ID; | ||
| 9824 | truncate_it.glyph_row = &scratch_glyph_row; | ||
| 9825 | truncate_it.glyph_row->used[TEXT_AREA] = 0; | ||
| 9826 | CHARPOS (truncate_it.position) = BYTEPOS (truncate_it.position) = -1; | ||
| 9827 | truncate_it.object = 0; | ||
| 9828 | produce_special_glyphs (&truncate_it, IT_TRUNCATION); | ||
| 9829 | |||
| 9830 | /* Overwrite glyphs from IT with truncation glyphs. */ | ||
| 9831 | from = truncate_it.glyph_row->glyphs[TEXT_AREA]; | ||
| 9832 | end = from + truncate_it.glyph_row->used[TEXT_AREA]; | ||
| 9833 | to = it->glyph_row->glyphs[TEXT_AREA]; | ||
| 9834 | toend = to + it->glyph_row->used[TEXT_AREA]; | ||
| 9835 | |||
| 9836 | while (from < end) | ||
| 9837 | *to++ = *from++; | ||
| 9838 | |||
| 9839 | /* There may be padding glyphs left over. Remove them. */ | ||
| 9840 | from = to; | ||
| 9841 | while (from < toend && CHAR_GLYPH_PADDING_P (*from)) | ||
| 9842 | ++from; | ||
| 9843 | while (from < toend) | ||
| 9844 | *to++ = *from++; | ||
| 9845 | |||
| 9846 | it->glyph_row->used[TEXT_AREA] = to - it->glyph_row->glyphs[TEXT_AREA]; | ||
| 9847 | } | ||
| 9848 | |||
| 9849 | |||
| 9850 | /* Compute the pixel height and width of IT->glyph_row. | ||
| 9851 | |||
| 9852 | Most of the time, ascent and height of a display line will be equal | ||
| 9853 | to the max_ascent and max_height values of the display iterator | ||
| 9854 | structure. This is not the case if | ||
| 9855 | |||
| 9856 | 1. We hit ZV without displaying anything. In this case, max_ascent | ||
| 9857 | and max_height will be zero. | ||
| 9858 | |||
| 9859 | 2. We have some glyphs that don't contribute to the line height. | ||
| 9860 | (The glyph row flag contributes_to_line_height_p is for future | ||
| 9861 | pixmap extensions). | ||
| 9862 | |||
| 9863 | The first case is easily covered by using default values because in | ||
| 9864 | these cases, the line height does not really matter, except that it | ||
| 9865 | must not be zero. */ | ||
| 9866 | |||
| 9867 | static void | ||
| 9868 | compute_line_metrics (it) | ||
| 9869 | struct it *it; | ||
| 9870 | { | ||
| 9871 | struct glyph_row *row = it->glyph_row; | ||
| 9872 | int area, i; | ||
| 9873 | |||
| 9874 | if (FRAME_WINDOW_P (it->f)) | ||
| 9875 | { | ||
| 9876 | int i, top_line_height; | ||
| 9877 | |||
| 9878 | /* The line may consist of one space only, that was added to | ||
| 9879 | place the cursor on it. If so, the row's height hasn't been | ||
| 9880 | computed yet. */ | ||
| 9881 | if (row->height == 0) | ||
| 3812 | { | 9882 | { |
| 3813 | if (p1 >= leftmargin) | 9883 | if (it->max_ascent + it->max_descent == 0) |
| 3814 | *p1 = (fix_glyph | 9884 | it->max_descent = CANON_Y_UNIT (it->f); |
| 3815 | (f, (dp && INTEGERP (DISP_CTRL_GLYPH (dp)) | 9885 | row->ascent = it->max_ascent; |
| 3816 | && GLYPH_CHAR_VALID_P (XINT (DISP_CTRL_GLYPH (dp))) | 9886 | row->height = it->max_ascent + it->max_descent; |
| 3817 | ? XINT (DISP_CTRL_GLYPH (dp)) : '^'), | ||
| 3818 | current_face) | ||
| 3819 | | rev_dir_bit); | ||
| 3820 | p1++; | ||
| 3821 | if (p1 >= leftmargin && p1 < endp) | ||
| 3822 | *p1 = MAKE_GLYPH (f, c ^ 0100, current_face) | rev_dir_bit; | ||
| 3823 | p1++; | ||
| 3824 | } | 9887 | } |
| 9888 | |||
| 9889 | /* Compute the width of this line. */ | ||
| 9890 | row->pixel_width = row->x; | ||
| 9891 | for (i = 0; i < row->used[TEXT_AREA]; ++i) | ||
| 9892 | row->pixel_width += row->glyphs[TEXT_AREA][i].pixel_width; | ||
| 9893 | |||
| 9894 | xassert (row->pixel_width >= 0); | ||
| 9895 | xassert (row->ascent >= 0 && row->height > 0); | ||
| 9896 | |||
| 9897 | /* Compute how much of the line is visible. */ | ||
| 9898 | row->visible_height = row->height; | ||
| 9899 | |||
| 9900 | top_line_height = WINDOW_DISPLAY_TOP_LINE_HEIGHT (it->w); | ||
| 9901 | if (row->y < top_line_height) | ||
| 9902 | row->visible_height -= top_line_height - row->y; | ||
| 3825 | else | 9903 | else |
| 3826 | { | 9904 | { |
| 3827 | /* C is a multibyte character or a character to be displayed | 9905 | int max_y = WINDOW_DISPLAY_HEIGHT_NO_MODE_LINE (it->w); |
| 3828 | by octal form. */ | 9906 | if (row->y + row->height > max_y) |
| 3829 | int remaining_bytes = len; | 9907 | row->visible_height -= row->y + row->height - max_y; |
| 9908 | } | ||
| 9909 | } | ||
| 9910 | else | ||
| 9911 | { | ||
| 9912 | row->pixel_width = row->used[TEXT_AREA]; | ||
| 9913 | row->ascent = 0; | ||
| 9914 | row->height = row->visible_height = 1; | ||
| 9915 | } | ||
| 3830 | 9916 | ||
| 3831 | if (unibyte_display_via_language_environment | 9917 | /* Compute a hash code for this row. */ |
| 3832 | && SINGLE_BYTE_CHAR_P (c) | 9918 | row->hash = 0; |
| 3833 | && (c >= 0240 | 9919 | for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area) |
| 3834 | || (c >= 0200 && !NILP (Vnonascii_translation_table)))) | 9920 | for (i = 0; i < row->used[area]; ++i) |
| 3835 | c = unibyte_char_to_multibyte (c); | 9921 | row->hash = ((((row->hash << 4) + (row->hash >> 24)) & 0x0fffffff) |
| 9922 | + row->glyphs[area][i].u.val | ||
| 9923 | + (row->glyphs[area][i].type << 2)); | ||
| 3836 | 9924 | ||
| 3837 | if (c >= 0400 && CHAR_VALID_P (c, 0)) | 9925 | it->max_ascent = it->max_descent = 0; |
| 3838 | { | 9926 | } |
| 3839 | /* C is a multibyte character. */ | ||
| 3840 | int charset = CHAR_CHARSET (c); | ||
| 3841 | int columns = (charset == CHARSET_COMPOSITION | ||
| 3842 | ? cmpchar_table[COMPOSITE_CHAR_ID (c)]->width | ||
| 3843 | : CHARSET_WIDTH (charset)); | ||
| 3844 | GLYPH g = MAKE_GLYPH (f, c, current_face) | rev_dir_bit; | ||
| 3845 | |||
| 3846 | while (columns--) | ||
| 3847 | { | ||
| 3848 | if (p1 >= leftmargin && p1 < endp) | ||
| 3849 | *p1 = g, g |= GLYPH_MASK_PADDING; | ||
| 3850 | p1++; | ||
| 3851 | } | ||
| 3852 | p1_wide_column_end = p1; | ||
| 3853 | remaining_bytes -= CHARSET_BYTES (charset); | ||
| 3854 | } | ||
| 3855 | 9927 | ||
| 3856 | while (remaining_bytes > 0) | ||
| 3857 | { | ||
| 3858 | c = *(p - remaining_bytes--); | ||
| 3859 | |||
| 3860 | if (p1 >= leftmargin && p1 < endp) | ||
| 3861 | *p1 = (fix_glyph | ||
| 3862 | (f, | ||
| 3863 | (dp && INTEGERP (DISP_ESCAPE_GLYPH (dp)) | ||
| 3864 | && GLYPH_CHAR_VALID_P (XINT (DISP_ESCAPE_GLYPH (dp))) | ||
| 3865 | ? XINT (DISP_ESCAPE_GLYPH (dp)) : '\\'), | ||
| 3866 | current_face) | ||
| 3867 | | rev_dir_bit); | ||
| 3868 | p1++; | ||
| 3869 | if (p1 >= leftmargin && p1 < endp) | ||
| 3870 | *p1 = (MAKE_GLYPH (f, (c >> 6) + '0', current_face) | ||
| 3871 | | rev_dir_bit); | ||
| 3872 | p1++; | ||
| 3873 | if (p1 >= leftmargin && p1 < endp) | ||
| 3874 | *p1 = (MAKE_GLYPH (f, (7 & (c >> 3)) + '0', current_face) | ||
| 3875 | | rev_dir_bit); | ||
| 3876 | p1++; | ||
| 3877 | if (p1 >= leftmargin && p1 < endp) | ||
| 3878 | *p1 = (MAKE_GLYPH (f, (7 & c) + '0', current_face) | ||
| 3879 | | rev_dir_bit); | ||
| 3880 | p1++; | ||
| 3881 | } | ||
| 3882 | } | ||
| 3883 | 9928 | ||
| 3884 | prevpos = pos; | 9929 | /* Append one space to the glyph row of iterator IT if doing a |
| 3885 | prevpos_byte = pos_byte; | 9930 | window-based redisplay. DEFAULT_FACE_P non-zero means let the |
| 3886 | pos++; | 9931 | space have the default face, otherwise let it have the same face as |
| 3887 | pos_byte += len; | 9932 | IT->face_id. This function is called to make sure that there is |
| 9933 | always one glyph at the end of a glyph row that the cursor can be | ||
| 9934 | set on under window-systems. (If there weren't such a glyph we | ||
| 9935 | would not know how wide and tall the cursor should be displayed). */ | ||
| 3888 | 9936 | ||
| 3889 | /* Update charstarts for the character just output. */ | 9937 | static void |
| 9938 | append_space (it, default_face_p) | ||
| 9939 | struct it *it; | ||
| 9940 | int default_face_p; | ||
| 9941 | { | ||
| 9942 | if (FRAME_WINDOW_P (it->f)) | ||
| 9943 | { | ||
| 9944 | int n = it->glyph_row->used[TEXT_AREA]; | ||
| 3890 | 9945 | ||
| 3891 | /* Do nothing here for a char that's entirely off the left edge. */ | 9946 | if (it->glyph_row->glyphs[TEXT_AREA] + n |
| 3892 | if (p1 >= leftmargin) | 9947 | < it->glyph_row->glyphs[1 + TEXT_AREA]) |
| 3893 | { | 9948 | { |
| 3894 | /* Store the char's position into charstarts | 9949 | /* Save some values that must not be changed. */ |
| 3895 | for the first glyph occupied by this char. | 9950 | int saved_x = it->current_x; |
| 3896 | Store -1 for the rest of the glyphs it occupies. */ | 9951 | struct text_pos saved_pos; |
| 3897 | if (p1 != p1prev) | 9952 | int saved_what = it->what; |
| 3898 | { | 9953 | int saved_face_id = it->face_id; |
| 3899 | int *p2x = &charstart[(p1prev < leftmargin | 9954 | int saved_charset = it->charset; |
| 3900 | ? leftmargin : p1prev) | 9955 | Lisp_Object saved_object; |
| 3901 | - p1start]; | 9956 | |
| 3902 | int *p2 = &charstart[(p1 < endp ? p1 : endp) - p1start]; | 9957 | saved_object = it->object; |
| 3903 | 9958 | saved_pos = it->position; | |
| 3904 | if (p2x < p2) | 9959 | |
| 3905 | *p2x++ = prevpos; | 9960 | it->what = IT_CHARACTER; |
| 3906 | while (p2x < p2) | 9961 | bzero (&it->position, sizeof it->position); |
| 3907 | *p2x++ = -1; | 9962 | it->object = 0; |
| 3908 | } | 9963 | it->c = ' '; |
| 9964 | it->len = 1; | ||
| 9965 | it->charset = CHARSET_ASCII; | ||
| 9966 | |||
| 9967 | if (default_face_p) | ||
| 9968 | it->face_id = DEFAULT_FACE_ID; | ||
| 9969 | if (it->multibyte_p) | ||
| 9970 | it->face_id = FACE_FOR_CHARSET (it->f, it->face_id, CHARSET_ASCII); | ||
| 9971 | else | ||
| 9972 | it->face_id = FACE_FOR_CHARSET (it->f, it->face_id, -1); | ||
| 9973 | |||
| 9974 | PRODUCE_GLYPHS (it); | ||
| 9975 | |||
| 9976 | it->current_x = saved_x; | ||
| 9977 | it->object = saved_object; | ||
| 9978 | it->position = saved_pos; | ||
| 9979 | it->what = saved_what; | ||
| 9980 | it->face_id = saved_face_id; | ||
| 9981 | it->charset = saved_charset; | ||
| 3909 | } | 9982 | } |
| 3910 | } | 9983 | } |
| 9984 | } | ||
| 3911 | 9985 | ||
| 3912 | val.hpos = - XINT (w->hscroll); | ||
| 3913 | if (val.hpos) | ||
| 3914 | val.hpos++; | ||
| 3915 | |||
| 3916 | val.vpos = 1; | ||
| 3917 | |||
| 3918 | lastpos = pos; | ||
| 3919 | lastpos_byte = pos_byte; | ||
| 3920 | |||
| 3921 | /* Store 0 in this charstart line for the positions where | ||
| 3922 | there is no character. But do leave what was recorded | ||
| 3923 | for the character that ended the line. */ | ||
| 3924 | /* Add 1 in the endtest to compensate for the fact that ENDP was | ||
| 3925 | made from WIDTH, which is 1 less than the window's actual | ||
| 3926 | internal width. */ | ||
| 3927 | i = p1 - p1start + 1; | ||
| 3928 | if (p1 < leftmargin) | ||
| 3929 | i += leftmargin - p1; | ||
| 3930 | for (; i < endp - p1start + 1; i++) | ||
| 3931 | charstart[i] = 0; | ||
| 3932 | |||
| 3933 | /* Handle continuation in middle of a character */ | ||
| 3934 | /* by backing up over it */ | ||
| 3935 | if (p1 > endp) | ||
| 3936 | { | ||
| 3937 | /* Don't back up if we never actually displayed any text. | ||
| 3938 | This occurs when the minibuffer prompt takes up the whole line. */ | ||
| 3939 | if (p1prev) | ||
| 3940 | { | ||
| 3941 | /* Start the next line with that same character whose | ||
| 3942 | character code is C and the length of multi-byte form is | ||
| 3943 | LEN. */ | ||
| 3944 | pos = prevpos; | ||
| 3945 | pos_byte = prevpos_byte; | ||
| 3946 | |||
| 3947 | if (p1_wide_column_end < endp) | ||
| 3948 | /* As ENDP is not in the middle of wide-column character, | ||
| 3949 | we can break the line at ENDP and start from the middle | ||
| 3950 | column in the next line. So, adjust VAL.HPOS to skip | ||
| 3951 | the columns output on this line. */ | ||
| 3952 | val.hpos += p1prev - endp; | ||
| 3953 | else | ||
| 3954 | { | ||
| 3955 | /* We displayed a wide-column character at around ENDP. | ||
| 3956 | Since we can't broke it in the middle, the whole | ||
| 3957 | character should be driven into the next line. */ | ||
| 3958 | /* As the result, the actual columns occupied by the | ||
| 3959 | text on this line is less than WIDTH. VAL.TAB_OFFSET | ||
| 3960 | must be adjusted. */ | ||
| 3961 | taboffset = taboffset + (p1prev - endp); | ||
| 3962 | /* Let's fill unused columns with TRUNCATOR or CONTINUER. */ | ||
| 3963 | { | ||
| 3964 | GLYPH g = fix_glyph (f, truncate ? truncator : continuer, 0); | ||
| 3965 | while (p1prev < endp) | ||
| 3966 | *p1prev++ = g; | ||
| 3967 | } | ||
| 3968 | /* If POINT is at POS, cursor should not on this line. */ | ||
| 3969 | lastpos = pos; | ||
| 3970 | lastpos_byte = pos_byte; | ||
| 3971 | if (PT == pos) | ||
| 3972 | cursor_vpos = -1; | ||
| 3973 | } | ||
| 3974 | } | ||
| 3975 | 9986 | ||
| 3976 | /* Keep in this line everything up to the continuation column. */ | 9987 | /* Extend the face of the last glyph in the text area of IT->glyph_row |
| 3977 | p1 = endp; | 9988 | to the end of the display line. Called from display_line. |
| 3978 | } | 9989 | If the glyph row is empty, add a space glyph to it so that we |
| 9990 | know the face to draw. Set the glyph row flag fill_line_p. */ | ||
| 9991 | |||
| 9992 | static void | ||
| 9993 | extend_face_to_end_of_line (it) | ||
| 9994 | struct it *it; | ||
| 9995 | { | ||
| 9996 | struct face *face; | ||
| 9997 | struct frame *f = it->f; | ||
| 3979 | 9998 | ||
| 3980 | /* Finish deciding which character to start the next line on, | 9999 | /* If line is already filled, do nothing. */ |
| 3981 | and what hpos to start it at. | 10000 | if (it->current_x >= it->last_visible_x) |
| 3982 | Also set `lastpos' to the last position which counts as "on this line" | 10001 | return; |
| 3983 | for cursor-positioning. */ | 10002 | |
| 10003 | /* Face extension extends the background and box of IT->face_id | ||
| 10004 | to the end of the line. If the background equals the background | ||
| 10005 | of the frame, we haven't to do anything. */ | ||
| 10006 | face = FACE_FROM_ID (f, it->face_id); | ||
| 10007 | if (FRAME_WINDOW_P (f) | ||
| 10008 | && face->box == FACE_NO_BOX | ||
| 10009 | && face->background == FRAME_BACKGROUND_PIXEL (f) | ||
| 10010 | && !face->stipple) | ||
| 10011 | return; | ||
| 3984 | 10012 | ||
| 3985 | if (pos < ZV) | 10013 | /* Set the glyph row flag indicating that the face of the last glyph |
| 10014 | in the text area has to be drawn to the end of the text area. */ | ||
| 10015 | it->glyph_row->fill_line_p = 1; | ||
| 10016 | |||
| 10017 | /* If current charset of IT is not ASCII, make sure we have the | ||
| 10018 | ASCII face. This will be automatically undone the next time | ||
| 10019 | get_next_display_element returns a character from a different | ||
| 10020 | charset. Note that the charset will always be ASCII in unibyte | ||
| 10021 | text. */ | ||
| 10022 | if (it->charset != CHARSET_ASCII) | ||
| 10023 | { | ||
| 10024 | it->charset = CHARSET_ASCII; | ||
| 10025 | it->face_id = FACE_FOR_CHARSET (f, it->face_id, CHARSET_ASCII); | ||
| 10026 | } | ||
| 10027 | |||
| 10028 | if (FRAME_WINDOW_P (f)) | ||
| 3986 | { | 10029 | { |
| 3987 | if (FETCH_BYTE (pos_byte) == '\n') | 10030 | /* If the row is empty, add a space with the current face of IT, |
| 10031 | so that we know which face to draw. */ | ||
| 10032 | if (it->glyph_row->used[TEXT_AREA] == 0) | ||
| 3988 | { | 10033 | { |
| 3989 | int opoint = PT, opoint_byte = PT_BYTE; | 10034 | it->glyph_row->glyphs[TEXT_AREA][0] = space_glyph; |
| 10035 | it->glyph_row->glyphs[TEXT_AREA][0].u.ch.face_id = it->face_id; | ||
| 10036 | it->glyph_row->used[TEXT_AREA] = 1; | ||
| 10037 | } | ||
| 10038 | } | ||
| 10039 | else | ||
| 10040 | { | ||
| 10041 | /* Save some values that must not be changed. */ | ||
| 10042 | int saved_x = it->current_x; | ||
| 10043 | struct text_pos saved_pos; | ||
| 10044 | Lisp_Object saved_object; | ||
| 10045 | int saved_what = it->what; | ||
| 10046 | |||
| 10047 | saved_object = it->object; | ||
| 10048 | saved_pos = it->position; | ||
| 10049 | |||
| 10050 | it->what = IT_CHARACTER; | ||
| 10051 | bzero (&it->position, sizeof it->position); | ||
| 10052 | it->object = 0; | ||
| 10053 | it->c = ' '; | ||
| 10054 | it->len = 1; | ||
| 10055 | |||
| 10056 | PRODUCE_GLYPHS (it); | ||
| 10057 | |||
| 10058 | while (it->current_x <= it->last_visible_x) | ||
| 10059 | PRODUCE_GLYPHS (it); | ||
| 10060 | |||
| 10061 | /* Don't count these blanks really. It would let us insert a left | ||
| 10062 | truncation glyph below and make us set the cursor on them, maybe. */ | ||
| 10063 | it->current_x = saved_x; | ||
| 10064 | it->object = saved_object; | ||
| 10065 | it->position = saved_pos; | ||
| 10066 | it->what = saved_what; | ||
| 10067 | } | ||
| 10068 | } | ||
| 3990 | 10069 | ||
| 3991 | /* If stopped due to a newline, start next line after it */ | ||
| 3992 | TEMP_SET_PT_BOTH (pos + 1, pos_byte + 1); | ||
| 3993 | 10070 | ||
| 3994 | val.tab_offset = 0; | 10071 | /* Value is non-zero if text starting at CHARPOS in current_buffer is |
| 3995 | /* Check again for hidden lines, in case the newline occurred exactly | 10072 | trailing whitespace. */ |
| 3996 | at the right margin. */ | ||
| 3997 | while (PT < ZV && selective > 0 | ||
| 3998 | && indented_beyond_p (PT, PT_BYTE, selective)) | ||
| 3999 | scan_newline (PT, PT_BYTE, ZV, ZV_BYTE, 1, 1); | ||
| 4000 | 10073 | ||
| 4001 | pos = PT, pos_byte = PT_BYTE; | 10074 | static int |
| 4002 | TEMP_SET_PT_BOTH (opoint, opoint_byte); | 10075 | trailing_whitespace_p (charpos) |
| 4003 | } | 10076 | int charpos; |
| 4004 | else | 10077 | { |
| 4005 | /* Stopped due to right margin of window */ | 10078 | int bytepos = CHAR_TO_BYTE (charpos); |
| 10079 | int c = 0; | ||
| 10080 | |||
| 10081 | while (bytepos < ZV_BYTE | ||
| 10082 | && (c = FETCH_CHAR (bytepos), | ||
| 10083 | c == ' ' || c == '\t')) | ||
| 10084 | ++bytepos; | ||
| 10085 | |||
| 10086 | return bytepos >= ZV_BYTE || c == '\n' || c == '\r'; | ||
| 10087 | } | ||
| 10088 | |||
| 10089 | |||
| 10090 | /* Highlight trailing whitespace, if any, in ROW. */ | ||
| 10091 | |||
| 10092 | void | ||
| 10093 | highlight_trailing_whitespace (f, row) | ||
| 10094 | struct frame *f; | ||
| 10095 | struct glyph_row *row; | ||
| 10096 | { | ||
| 10097 | int used = row->used[TEXT_AREA]; | ||
| 10098 | |||
| 10099 | if (used) | ||
| 10100 | { | ||
| 10101 | struct glyph *start = row->glyphs[TEXT_AREA]; | ||
| 10102 | struct glyph *glyph = start + used - 1; | ||
| 10103 | |||
| 10104 | /* Skip over the space glyph inserted to display the | ||
| 10105 | cursor at the end of a line. */ | ||
| 10106 | if (glyph->type == CHAR_GLYPH | ||
| 10107 | && glyph->u.ch.code == ' ' | ||
| 10108 | && glyph->object == 0) | ||
| 10109 | --glyph; | ||
| 10110 | |||
| 10111 | /* If last glyph is a space or stretch, and it's trailing | ||
| 10112 | whitespace, set the face of all trailing whitespace glyphs in | ||
| 10113 | IT->glyph_row to `trailing-whitespace'. */ | ||
| 10114 | if (glyph >= start | ||
| 10115 | && BUFFERP (glyph->object) | ||
| 10116 | && (glyph->type == STRETCH_GLYPH | ||
| 10117 | || (glyph->type == CHAR_GLYPH | ||
| 10118 | && glyph->u.ch.code == ' ')) | ||
| 10119 | && trailing_whitespace_p (glyph->charpos)) | ||
| 4006 | { | 10120 | { |
| 4007 | if (truncate) | 10121 | int face_id = lookup_named_face (f, Qtrailing_whitespace, |
| 4008 | { | 10122 | CHARSET_ASCII); |
| 4009 | int opoint = PT, opoint_byte = PT_BYTE; | 10123 | |
| 4010 | 10124 | while (glyph >= start | |
| 4011 | TEMP_SET_PT_BOTH (pos, pos_byte); | 10125 | && BUFFERP (glyph->object) |
| 4012 | *p1++ = fix_glyph (f, truncator, 0); | 10126 | && (glyph->type == STRETCH_GLYPH |
| 4013 | /* Truncating => start next line after next newline, | 10127 | || (glyph->type == CHAR_GLYPH |
| 4014 | and point is on this line if it is before the newline, | 10128 | && glyph->u.ch.code == ' '))) |
| 4015 | and skip none of first char of next line */ | ||
| 4016 | do | ||
| 4017 | scan_newline (PT, PT_BYTE, ZV, ZV_BYTE, 1, 1); | ||
| 4018 | while (PT < ZV && selective > 0 | ||
| 4019 | && indented_beyond_p (PT, PT_BYTE, selective)); | ||
| 4020 | pos = PT, pos_byte = PT_BYTE; | ||
| 4021 | val.hpos = XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0; | ||
| 4022 | TEMP_SET_PT_BOTH (opoint, opoint_byte); | ||
| 4023 | |||
| 4024 | lastpos = pos - (FETCH_BYTE (pos_byte - 1) == '\n'); | ||
| 4025 | lastpos_byte = CHAR_TO_BYTE (lastpos); | ||
| 4026 | val.tab_offset = 0; | ||
| 4027 | } | ||
| 4028 | else | ||
| 4029 | { | 10129 | { |
| 4030 | *p1++ = fix_glyph (f, continuer, 0); | 10130 | if (glyph->type == STRETCH_GLYPH) |
| 4031 | val.vpos = 0; | 10131 | glyph->u.stretch.face_id = face_id; |
| 4032 | DEC_BOTH (lastpos, lastpos_byte); | 10132 | else |
| 4033 | val.tab_offset = taboffset + width; | 10133 | glyph->u.ch.face_id = face_id; |
| 10134 | --glyph; | ||
| 4034 | } | 10135 | } |
| 4035 | } | 10136 | } |
| 4036 | } | 10137 | } |
| 4037 | else | 10138 | } |
| 4038 | val.tab_offset = 0; | 10139 | |
| 10140 | |||
| 10141 | |||
| 10142 | /* Construct the glyph row IT->glyph_row in the desired matrix of | ||
| 10143 | IT->w from text at the current position of IT. See dispextern.h | ||
| 10144 | for an overview of struct it. Value is non-zero if | ||
| 10145 | IT->glyph_row displays text, as opposed to a line displaying ZV | ||
| 10146 | only. */ | ||
| 10147 | |||
| 10148 | static int | ||
| 10149 | display_line (it) | ||
| 10150 | struct it *it; | ||
| 10151 | { | ||
| 10152 | struct glyph_row *row = it->glyph_row; | ||
| 10153 | |||
| 10154 | /* We always start displaying at hpos zero even if hscrolled. */ | ||
| 10155 | xassert (it->hpos == 0 && it->current_x == 0); | ||
| 10156 | |||
| 10157 | /* We must not display in a row that's not a text row. */ | ||
| 10158 | xassert (MATRIX_ROW_VPOS (row, it->w->desired_matrix) | ||
| 10159 | < it->w->desired_matrix->nrows); | ||
| 10160 | |||
| 10161 | /* Is IT->w showing the region? */ | ||
| 10162 | it->w->region_showing = it->region_beg_charpos > 0 ? Qt : Qnil; | ||
| 10163 | |||
| 10164 | /* Clear the result glyph row and enable it. */ | ||
| 10165 | prepare_desired_row (row); | ||
| 4039 | 10166 | ||
| 4040 | /* If point is at eol or in invisible text at eol, | 10167 | row->y = it->current_y; |
| 4041 | record its frame location now. */ | 10168 | row->start = it->current; |
| 10169 | row->continuation_lines_width = it->continuation_lines_width; | ||
| 10170 | row->displays_text_p = 1; | ||
| 4042 | 10171 | ||
| 4043 | if (start <= PT && PT <= lastpos && cursor_vpos < 0) | 10172 | /* Arrange the overlays nicely for our purposes. Usually, we call |
| 10173 | display_line on only one line at a time, in which case this | ||
| 10174 | can't really hurt too much, or we call it on lines which appear | ||
| 10175 | one after another in the buffer, in which case all calls to | ||
| 10176 | recenter_overlay_lists but the first will be pretty cheap. */ | ||
| 10177 | recenter_overlay_lists (current_buffer, IT_CHARPOS (*it)); | ||
| 10178 | |||
| 10179 | #if NO_PROMPT_IN_BUFFER | ||
| 10180 | /* Show mini-buffer prompt, if at the beginning of a mini-buffer | ||
| 10181 | window. */ | ||
| 10182 | if (MINI_WINDOW_P (it->w) | ||
| 10183 | && MATRIX_ROW_START_CHARPOS (row) == BEG | ||
| 10184 | && it->vpos == 0) | ||
| 4044 | { | 10185 | { |
| 4045 | cursor_vpos = vpos; | 10186 | if (NILP (minibuf_prompt)) |
| 4046 | cursor_hpos = p1 - leftmargin; | 10187 | minibuf_prompt_width = minibuf_prompt_pixel_width = 0; |
| 10188 | else | ||
| 10189 | { | ||
| 10190 | /* We would like to truncate the prompt a little bit before | ||
| 10191 | the right margin of the window, so that user input can | ||
| 10192 | start on the first line. Set max_x to this position. */ | ||
| 10193 | int max_x = (it->last_visible_x - 4 * CANON_X_UNIT (it->f)); | ||
| 10194 | |||
| 10195 | /* We use a temporary iterator different from IT so that | ||
| 10196 | IT's settings are not overwritten when displaying | ||
| 10197 | the prompt. */ | ||
| 10198 | struct it ti; | ||
| 10199 | |||
| 10200 | ti = *it; | ||
| 10201 | |||
| 10202 | /* Display the prompt. Set minibuf_prompt_width to the | ||
| 10203 | number of glyphs generated for the prompt, set | ||
| 10204 | minibuf_prompt_pixel_width to its width in pixels. */ | ||
| 10205 | xassert (it->current_x == 0); | ||
| 10206 | display_string (NULL, minibuf_prompt, Qnil, 0, 0, &ti, | ||
| 10207 | 0, 0, max_x, -1); | ||
| 10208 | minibuf_prompt_width = ti.hpos; | ||
| 10209 | minibuf_prompt_pixel_width = ti.current_x; | ||
| 10210 | |||
| 10211 | /* Transfer pixel and hpos information to IT. */ | ||
| 10212 | it->hpos = ti.hpos; | ||
| 10213 | it->current_x = ti.current_x; | ||
| 10214 | } | ||
| 4047 | } | 10215 | } |
| 4048 | 10216 | #endif /* NO_PROMPT_IN_BUFFER */ | |
| 4049 | if (cursor_vpos == vpos) | 10217 | |
| 10218 | /* Move over display elements that are not visible because we are | ||
| 10219 | hscrolled. This may stop at an x-position < IT->first_visible_x | ||
| 10220 | if the first glyph is partially visible or if we hit a line end. */ | ||
| 10221 | if (it->current_x < it->first_visible_x) | ||
| 10222 | move_it_in_display_line_to (it, ZV, it->first_visible_x, | ||
| 10223 | MOVE_TO_POS | MOVE_TO_X); | ||
| 10224 | |||
| 10225 | /* Get the initial row height. This is either the height of the | ||
| 10226 | text hscrolled, if there is any, or zero. */ | ||
| 10227 | row->ascent = it->max_ascent; | ||
| 10228 | row->height = it->max_ascent + it->max_descent; | ||
| 10229 | |||
| 10230 | /* Loop generating characters. The loop is left with IT on the next | ||
| 10231 | character to display. */ | ||
| 10232 | while (1) | ||
| 4050 | { | 10233 | { |
| 4051 | if (cursor_hpos < 0) cursor_hpos = 0; | 10234 | int n_glyphs_before, hpos_before, x_before; |
| 4052 | if (cursor_hpos > width) cursor_hpos = width; | 10235 | int x, i, nglyphs; |
| 4053 | cursor_hpos += WINDOW_LEFT_MARGIN (w); | 10236 | |
| 4054 | if (w == XWINDOW (FRAME_SELECTED_WINDOW (f))) | 10237 | /* Retrieve the next thing to display. Value is zero if end of |
| 10238 | buffer reached. */ | ||
| 10239 | if (!get_next_display_element (it)) | ||
| 4055 | { | 10240 | { |
| 4056 | this_line_bufpos = 0; | 10241 | /* Maybe add a space at the end of this line that is used to |
| 4057 | 10242 | display the cursor there under X. */ | |
| 4058 | /* If this frame's cursor will be in its echo area, | 10243 | append_space (it, 1); |
| 4059 | don't record a cursor from the window text, | 10244 | |
| 4060 | and turn off the optimization for cursor-motion-only case. */ | 10245 | /* The position -1 below indicates a blank line not |
| 4061 | if (!(cursor_in_echo_area && FRAME_HAS_MINIBUF_P (f) | 10246 | corresponding to any text, as opposed to an empty line |
| 4062 | && EQ (FRAME_MINIBUF_WINDOW (f), minibuf_window))) | 10247 | corresponding to a line end. */ |
| 10248 | if (row->used[TEXT_AREA] <= 1) | ||
| 4063 | { | 10249 | { |
| 4064 | FRAME_CURSOR_Y (f) = cursor_vpos; | 10250 | row->glyphs[TEXT_AREA]->charpos = -1; |
| 4065 | FRAME_CURSOR_X (f) = cursor_hpos; | 10251 | row->displays_text_p = 0; |
| 4066 | 10252 | ||
| 4067 | if (w == XWINDOW (selected_window)) | 10253 | if (!NILP (XBUFFER (it->w->buffer)->indicate_empty_lines)) |
| 10254 | row->indicate_empty_line_p = 1; | ||
| 10255 | } | ||
| 10256 | |||
| 10257 | it->continuation_lines_width = 0; | ||
| 10258 | row->ends_at_zv_p = 1; | ||
| 10259 | break; | ||
| 10260 | } | ||
| 10261 | |||
| 10262 | /* Now, get the metrics of what we want to display. This also | ||
| 10263 | generates glyphs in `row' (which is IT->glyph_row). */ | ||
| 10264 | n_glyphs_before = row->used[TEXT_AREA]; | ||
| 10265 | x = it->current_x; | ||
| 10266 | PRODUCE_GLYPHS (it); | ||
| 10267 | |||
| 10268 | /* If this display element was in marginal areas, continue with | ||
| 10269 | the next one. */ | ||
| 10270 | if (it->area != TEXT_AREA) | ||
| 10271 | { | ||
| 10272 | row->ascent = max (row->ascent, it->max_ascent); | ||
| 10273 | row->height = max (row->height, it->max_ascent + it->max_descent); | ||
| 10274 | set_iterator_to_next (it); | ||
| 10275 | continue; | ||
| 10276 | } | ||
| 10277 | |||
| 10278 | /* Does the display element fit on the line? If we truncate | ||
| 10279 | lines, we should draw past the right edge of the window. If | ||
| 10280 | we don't truncate, we want to stop so that we can display the | ||
| 10281 | continuation glyph before the right margin. If lines are | ||
| 10282 | continued, there are two possible strategies for characters | ||
| 10283 | resulting in more than 1 glyph (e.g. tabs): Display as many | ||
| 10284 | glyphs as possible in this line and leave the rest for the | ||
| 10285 | continuation line, or display the whole element in the next | ||
| 10286 | line. Original redisplay did the former, so we do it also. */ | ||
| 10287 | nglyphs = row->used[TEXT_AREA] - n_glyphs_before; | ||
| 10288 | hpos_before = it->hpos; | ||
| 10289 | x_before = x; | ||
| 10290 | |||
| 10291 | if (nglyphs == 1 | ||
| 10292 | && it->current_x < it->last_visible_x) | ||
| 10293 | { | ||
| 10294 | ++it->hpos; | ||
| 10295 | row->ascent = max (row->ascent, it->max_ascent); | ||
| 10296 | row->height = max (row->height, it->max_ascent + it->max_descent); | ||
| 10297 | if (it->current_x - it->pixel_width < it->first_visible_x) | ||
| 10298 | row->x = x - it->first_visible_x; | ||
| 10299 | } | ||
| 10300 | else | ||
| 10301 | { | ||
| 10302 | int new_x; | ||
| 10303 | struct glyph *glyph; | ||
| 10304 | |||
| 10305 | for (i = 0; i < nglyphs; ++i, x = new_x) | ||
| 10306 | { | ||
| 10307 | glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i; | ||
| 10308 | new_x = x + glyph->pixel_width; | ||
| 10309 | |||
| 10310 | if (/* Lines are continued. */ | ||
| 10311 | !it->truncate_lines_p | ||
| 10312 | && (/* Glyph doesn't fit on the line. */ | ||
| 10313 | new_x > it->last_visible_x | ||
| 10314 | /* Or it fits exactly on a window system frame. */ | ||
| 10315 | || (new_x == it->last_visible_x | ||
| 10316 | && FRAME_WINDOW_P (it->f)))) | ||
| 4068 | { | 10317 | { |
| 4069 | /* Line is not continued and did not start | 10318 | /* End of a continued line. */ |
| 4070 | in middle of character */ | 10319 | |
| 4071 | if ((hpos - WINDOW_LEFT_MARGIN (w) | 10320 | if (it->hpos == 0 |
| 4072 | == (XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0)) | 10321 | || (new_x == it->last_visible_x |
| 4073 | && val.vpos) | 10322 | && FRAME_WINDOW_P (it->f))) |
| 4074 | { | 10323 | { |
| 4075 | this_line_bufpos = start; | 10324 | /* Current glyph fits exactly on the line. We |
| 4076 | this_line_buffer = current_buffer; | 10325 | must continue the line because we can't draw |
| 4077 | this_line_vpos = cursor_vpos; | 10326 | the cursor after the glyph. */ |
| 4078 | this_line_start_hpos = hpos - WINDOW_LEFT_MARGIN (w); | 10327 | row->continued_p = 1; |
| 4079 | this_line_endpos = Z - lastpos; | 10328 | it->current_x = new_x; |
| 10329 | it->continuation_lines_width += new_x; | ||
| 10330 | ++it->hpos; | ||
| 10331 | if (i == nglyphs - 1) | ||
| 10332 | set_iterator_to_next (it); | ||
| 4080 | } | 10333 | } |
| 10334 | else | ||
| 10335 | { | ||
| 10336 | /* Display element draws past the right edge of | ||
| 10337 | the window. Restore positions to values | ||
| 10338 | before the element. The next line starts | ||
| 10339 | with current_x before the glyph that could | ||
| 10340 | not be displayed, so that TAB works right. */ | ||
| 10341 | row->used[TEXT_AREA] = n_glyphs_before + i; | ||
| 10342 | |||
| 10343 | /* Display continuation glyphs. */ | ||
| 10344 | if (!FRAME_WINDOW_P (it->f)) | ||
| 10345 | produce_special_glyphs (it, IT_CONTINUATION); | ||
| 10346 | row->continued_p = 1; | ||
| 10347 | |||
| 10348 | it->current_x = x; | ||
| 10349 | it->continuation_lines_width += x; | ||
| 10350 | } | ||
| 10351 | break; | ||
| 10352 | } | ||
| 10353 | else if (new_x > it->first_visible_x) | ||
| 10354 | { | ||
| 10355 | /* Increment number of glyphs actually displayed. */ | ||
| 10356 | ++it->hpos; | ||
| 10357 | |||
| 10358 | if (x < it->first_visible_x) | ||
| 10359 | /* Glyph is partially visible, i.e. row starts at | ||
| 10360 | negative X position. */ | ||
| 10361 | row->x = x - it->first_visible_x; | ||
| 10362 | } | ||
| 10363 | else | ||
| 10364 | { | ||
| 10365 | /* Glyph is completely off the left margin of the | ||
| 10366 | window. This should not happen because of the | ||
| 10367 | move_it_in_display_line at the start of | ||
| 10368 | this function. */ | ||
| 10369 | abort (); | ||
| 4081 | } | 10370 | } |
| 4082 | } | 10371 | } |
| 10372 | |||
| 10373 | row->ascent = max (row->ascent, it->max_ascent); | ||
| 10374 | row->height = max (row->height, it->max_ascent + it->max_descent); | ||
| 10375 | |||
| 10376 | /* End of this display line if row is continued. */ | ||
| 10377 | if (row->continued_p) | ||
| 10378 | break; | ||
| 4083 | } | 10379 | } |
| 4084 | } | ||
| 4085 | 10380 | ||
| 4086 | /* If hscroll and line not empty, insert truncation-at-left marker */ | 10381 | /* Is this a line end? If yes, we're also done, after making |
| 4087 | if (hscroll && lastpos != start) | 10382 | sure that a non-default face is extended up to the right |
| 4088 | { | 10383 | margin of the window. */ |
| 4089 | GLYPH g = fix_glyph (f, truncator, 0); | 10384 | if (ITERATOR_AT_END_OF_LINE_P (it)) |
| 4090 | *leftmargin = g; | ||
| 4091 | if (p1 <= leftmargin) | ||
| 4092 | p1 = leftmargin + 1; | ||
| 4093 | else /* MULE: it may be a wide-column character */ | ||
| 4094 | { | 10385 | { |
| 4095 | p1prev = leftmargin + 1; | 10386 | int used_before = row->used[TEXT_AREA]; |
| 4096 | while (p1prev < p1 && *p1prev & GLYPH_MASK_PADDING) | 10387 | |
| 4097 | *p1prev++ = g; | 10388 | /* Add a space at the end of the line that is used to |
| 10389 | display the cursor there. */ | ||
| 10390 | append_space (it, 0); | ||
| 10391 | |||
| 10392 | /* Extend the face to the end of the line. */ | ||
| 10393 | extend_face_to_end_of_line (it); | ||
| 10394 | |||
| 10395 | /* Make sure we have the position. */ | ||
| 10396 | if (used_before == 0) | ||
| 10397 | row->glyphs[TEXT_AREA]->charpos = CHARPOS (it->position); | ||
| 10398 | |||
| 10399 | /* Consume the line end. This skips over invisible lines. */ | ||
| 10400 | set_iterator_to_next (it); | ||
| 10401 | it->continuation_lines_width = 0; | ||
| 10402 | break; | ||
| 4098 | } | 10403 | } |
| 4099 | } | ||
| 4100 | 10404 | ||
| 4101 | if (!WINDOW_RIGHTMOST_P (w)) | 10405 | /* Proceed with next display element. Note that this skips |
| 4102 | { | 10406 | over lines invisible because of selective display. */ |
| 4103 | endp++; | 10407 | set_iterator_to_next (it); |
| 4104 | if (p1 < leftmargin) p1 = leftmargin; | ||
| 4105 | while (p1 < endp) *p1++ = SPACEGLYPH; | ||
| 4106 | 10408 | ||
| 4107 | /* Don't draw vertical bars if we're using scroll bars. They're | 10409 | /* If we truncate lines, we are done when the last displayed |
| 4108 | covered up by the scroll bars, and it's distracting to see | 10410 | glyphs reach past the right margin of the window. */ |
| 4109 | them when the scroll bar windows are flickering around to be | 10411 | if (it->truncate_lines_p |
| 4110 | reconfigured. */ | 10412 | && (FRAME_WINDOW_P (it->f) |
| 4111 | if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f)) | 10413 | ? (it->current_x >= it->last_visible_x) |
| 10414 | : (it->current_x > it->last_visible_x))) | ||
| 4112 | { | 10415 | { |
| 4113 | int i; | 10416 | /* Maybe add truncation glyphs. */ |
| 4114 | for (i = 0; i < FRAME_SCROLL_BAR_COLS (f); i++) | 10417 | if (!FRAME_WINDOW_P (it->f)) |
| 4115 | *p1++ = SPACEGLYPH; | 10418 | { |
| 10419 | --it->glyph_row->used[TEXT_AREA]; | ||
| 10420 | produce_special_glyphs (it, IT_TRUNCATION); | ||
| 10421 | } | ||
| 10422 | |||
| 10423 | row->truncated_on_right_p = 1; | ||
| 10424 | it->continuation_lines_width = 0; | ||
| 10425 | reseat_at_next_visible_line_start (it); | ||
| 10426 | row->ends_at_zv_p = FETCH_BYTE (IT_BYTEPOS (*it) - 1) != '\n'; | ||
| 10427 | it->hpos = hpos_before; | ||
| 10428 | it->current_x = x_before; | ||
| 10429 | break; | ||
| 4116 | } | 10430 | } |
| 4117 | else if (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)) | ||
| 4118 | *p1++ = (dp && INTEGERP (DISP_BORDER_GLYPH (dp)) | ||
| 4119 | ? XINT (DISP_BORDER_GLYPH (dp)) | ||
| 4120 | : '|'); | ||
| 4121 | } | 10431 | } |
| 4122 | desired_glyphs->used[vpos] = max (desired_glyphs->used[vpos], | ||
| 4123 | p1 - desired_glyphs->glyphs[vpos]); | ||
| 4124 | desired_glyphs->glyphs[vpos][desired_glyphs->used[vpos]] = 0; | ||
| 4125 | 10432 | ||
| 4126 | /* If the start of this line is the overlay arrow-position, | 10433 | /* If line is not empty and hscrolled, maybe insert truncation glyphs |
| 4127 | then put the arrow string into the display-line. */ | 10434 | at the left window margin. */ |
| 10435 | if (it->first_visible_x | ||
| 10436 | && IT_CHARPOS (*it) != MATRIX_ROW_START_CHARPOS (row)) | ||
| 10437 | { | ||
| 10438 | if (!FRAME_WINDOW_P (it->f)) | ||
| 10439 | insert_left_trunc_glyphs (it); | ||
| 10440 | row->truncated_on_left_p = 1; | ||
| 10441 | } | ||
| 4128 | 10442 | ||
| 10443 | /* If the start of this line is the overlay arrow-position, then | ||
| 10444 | mark this glyph row as the one containing the overlay arrow. | ||
| 10445 | This is clearly a mess with variable size fonts. It would be | ||
| 10446 | better to let it be displayed like cursors under X. */ | ||
| 4129 | if (MARKERP (Voverlay_arrow_position) | 10447 | if (MARKERP (Voverlay_arrow_position) |
| 4130 | && current_buffer == XMARKER (Voverlay_arrow_position)->buffer | 10448 | && current_buffer == XMARKER (Voverlay_arrow_position)->buffer |
| 4131 | && start == marker_position (Voverlay_arrow_position) | 10449 | && (MATRIX_ROW_START_CHARPOS (row) |
| 10450 | == marker_position (Voverlay_arrow_position)) | ||
| 4132 | && STRINGP (Voverlay_arrow_string) | 10451 | && STRINGP (Voverlay_arrow_string) |
| 4133 | && ! overlay_arrow_seen) | 10452 | && ! overlay_arrow_seen) |
| 4134 | { | 10453 | { |
| 4135 | int i, i_byte; | 10454 | /* Overlay arrow in window redisplay is a bitmap. */ |
| 4136 | int len = XSTRING (Voverlay_arrow_string)->size; | 10455 | if (!FRAME_WINDOW_P (it->f)) |
| 4137 | int arrow_end; | ||
| 4138 | |||
| 4139 | if (len > width) | ||
| 4140 | len = width; | ||
| 4141 | |||
| 4142 | /* If the arrow string has text props, obey them when displaying. */ | ||
| 4143 | for (i = 0, i_byte = 0; i < len; ) | ||
| 4144 | { | 10456 | { |
| 4145 | int c; | 10457 | struct glyph_row *arrow_row = get_overlay_arrow_glyph_row (it->w); |
| 4146 | Lisp_Object face, ilisp; | 10458 | struct glyph *glyph = arrow_row->glyphs[TEXT_AREA]; |
| 4147 | int newface; | 10459 | struct glyph *arrow_end = glyph + arrow_row->used[TEXT_AREA]; |
| 4148 | int idx = i; | 10460 | struct glyph *p = row->glyphs[TEXT_AREA]; |
| 4149 | 10461 | struct glyph *p2, *end; | |
| 4150 | if (STRING_MULTIBYTE (Voverlay_arrow_string)) | 10462 | |
| 4151 | FETCH_STRING_CHAR_ADVANCE (c, Voverlay_arrow_string, i, i_byte); | 10463 | /* Copy the arrow glyphs. */ |
| 4152 | else | 10464 | while (glyph < arrow_end) |
| 4153 | c = XSTRING (Voverlay_arrow_string)->data[i++]; | 10465 | *p++ = *glyph++; |
| 4154 | 10466 | ||
| 4155 | XSETFASTINT (ilisp, i); | 10467 | /* Throw away padding glyphs. */ |
| 4156 | #ifdef HAVE_FACES | 10468 | p2 = p; |
| 4157 | if (FRAME_WINDOW_P (f)) | 10469 | end = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA]; |
| 10470 | while (p2 < end && CHAR_GLYPH_PADDING_P (*p2)) | ||
| 10471 | ++p2; | ||
| 10472 | if (p2 > p) | ||
| 4158 | { | 10473 | { |
| 4159 | face = Fget_text_property (ilisp, Qface, Voverlay_arrow_string); | 10474 | while (p2 < end) |
| 4160 | newface = compute_glyph_face_1 (f, face, 0); | 10475 | *p++ = *p2++; |
| 4161 | c = FAST_MAKE_GLYPH (c, newface); | 10476 | row->used[TEXT_AREA] = p2 - row->glyphs[TEXT_AREA]; |
| 4162 | } | 10477 | } |
| 4163 | #endif /* HAVE_FACES */ | ||
| 4164 | leftmargin[idx] = c; | ||
| 4165 | } | 10478 | } |
| 4166 | 10479 | ||
| 4167 | /* Bug in SunOS 4.1.1 compiler requires this intermediate variable. */ | ||
| 4168 | arrow_end = (leftmargin - desired_glyphs->glyphs[vpos]) + len; | ||
| 4169 | if (desired_glyphs->used[vpos] < arrow_end) | ||
| 4170 | desired_glyphs->used[vpos] = arrow_end; | ||
| 4171 | |||
| 4172 | overlay_arrow_seen = 1; | 10480 | overlay_arrow_seen = 1; |
| 10481 | row->overlay_arrow_p = 1; | ||
| 4173 | } | 10482 | } |
| 4174 | 10483 | ||
| 4175 | val.bufpos = pos; | 10484 | /* Compute pixel dimensions of this line. */ |
| 4176 | val.bytepos = pos_byte; | 10485 | compute_line_metrics (it); |
| 4177 | val.ovstring_chars_done = ovstr_done; | 10486 | |
| 4178 | val_display_text_line = val; | 10487 | /* Remember the position at which this line ends. */ |
| 4179 | return &val_display_text_line; | 10488 | row->end = it->current; |
| 10489 | |||
| 10490 | /* Maybe set the cursor. If you change this, it's probably a good | ||
| 10491 | idea to also change the code in redisplay_window for cursor | ||
| 10492 | movement in an unchanged window. */ | ||
| 10493 | if (it->w->cursor.vpos < 0 | ||
| 10494 | && PT >= MATRIX_ROW_START_CHARPOS (row) | ||
| 10495 | && MATRIX_ROW_END_CHARPOS (row) >= PT | ||
| 10496 | && !(MATRIX_ROW_END_CHARPOS (row) == PT | ||
| 10497 | && (MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row) | ||
| 10498 | || !row->ends_at_zv_p))) | ||
| 10499 | set_cursor_from_row (it->w, row, it->w->desired_matrix, 0, 0, 0, 0); | ||
| 10500 | |||
| 10501 | /* Highlight trailing whitespace. */ | ||
| 10502 | if (it->show_trailing_whitespace_p) | ||
| 10503 | highlight_trailing_whitespace (it->f, it->glyph_row); | ||
| 10504 | |||
| 10505 | /* Prepare for the next line. This line starts horizontally at (X | ||
| 10506 | HPOS) = (0 0). Vertical positions are incremented. As a | ||
| 10507 | convenience for the caller, IT->glyph_row is set to the next | ||
| 10508 | row to be used. */ | ||
| 10509 | it->current_x = it->hpos = 0; | ||
| 10510 | it->current_y += row->height; | ||
| 10511 | ++it->vpos; | ||
| 10512 | ++it->glyph_row; | ||
| 10513 | return row->displays_text_p; | ||
| 4180 | } | 10514 | } |
| 10515 | |||
| 10516 | |||
| 4181 | 10517 | ||
| 4182 | /* Redisplay the menu bar in the frame for window W. */ | 10518 | /*********************************************************************** |
| 10519 | Menu Bar | ||
| 10520 | ***********************************************************************/ | ||
| 10521 | |||
| 10522 | /* Redisplay the menu bar in the frame for window W. | ||
| 10523 | |||
| 10524 | The menu bar of X frames that don't have X toolkit support is | ||
| 10525 | displayed in a special window W->frame->menu_bar_window. | ||
| 10526 | |||
| 10527 | The menu bar of terminal frames is treated specially as far as | ||
| 10528 | glyph matrices are concerned. Menu bar lines are not part of | ||
| 10529 | windows, so the update is done directly on the frame matrix rows | ||
| 10530 | for the menu bar. */ | ||
| 4183 | 10531 | ||
| 4184 | static void | 10532 | static void |
| 4185 | display_menu_bar (w) | 10533 | display_menu_bar (w) |
| 4186 | struct window *w; | 10534 | struct window *w; |
| 4187 | { | 10535 | { |
| 4188 | Lisp_Object items, tail; | 10536 | struct frame *f = XFRAME (WINDOW_FRAME (w)); |
| 4189 | register int vpos = 0; | 10537 | struct it it; |
| 4190 | register FRAME_PTR f = XFRAME (WINDOW_FRAME (w)); | 10538 | Lisp_Object items; |
| 4191 | int maxendcol = FRAME_WIDTH (f); | ||
| 4192 | int hpos = 0; | ||
| 4193 | int i; | 10539 | int i; |
| 4194 | 10540 | ||
| 10541 | /* Don't do all this for graphical frames. */ | ||
| 4195 | #ifdef HAVE_NTGUI | 10542 | #ifdef HAVE_NTGUI |
| 4196 | if (!NILP (Vwindow_system)) | 10543 | if (!NILP (Vwindow_system)) |
| 4197 | return; | 10544 | return; |
| 4198 | #endif | 10545 | #endif |
| 4199 | |||
| 4200 | #ifdef USE_X_TOOLKIT | 10546 | #ifdef USE_X_TOOLKIT |
| 4201 | if (FRAME_X_P (f)) | 10547 | if (FRAME_X_P (f)) |
| 4202 | return; | 10548 | return; |
| 4203 | #endif /* USE_X_TOOLKIT */ | 10549 | #endif |
| 10550 | |||
| 10551 | #ifdef USE_X_TOOLKIT | ||
| 10552 | xassert (!FRAME_WINDOW_P (f)); | ||
| 10553 | init_iterator (&it, w, -1, -1, f->desired_matrix->rows, MODE_LINE_FACE_ID); | ||
| 10554 | it.first_visible_x = 0; | ||
| 10555 | it.last_visible_x = FRAME_WINDOW_WIDTH (f) * CANON_X_UNIT (f); | ||
| 10556 | #else /* not USE_X_TOOLKIT */ | ||
| 10557 | if (FRAME_WINDOW_P (f)) | ||
| 10558 | { | ||
| 10559 | /* Menu bar lines are displayed in the desired matrix of the | ||
| 10560 | dummy window menu_bar_window. */ | ||
| 10561 | struct window *menu_w; | ||
| 10562 | xassert (WINDOWP (f->menu_bar_window)); | ||
| 10563 | menu_w = XWINDOW (f->menu_bar_window); | ||
| 10564 | init_iterator (&it, menu_w, -1, -1, menu_w->desired_matrix->rows, | ||
| 10565 | MODE_LINE_FACE_ID); | ||
| 10566 | it.first_visible_x = 0; | ||
| 10567 | it.last_visible_x = FRAME_WINDOW_WIDTH (f) * CANON_X_UNIT (f); | ||
| 10568 | } | ||
| 10569 | else | ||
| 10570 | { | ||
| 10571 | /* This is a TTY frame, i.e. character hpos/vpos are used as | ||
| 10572 | pixel x/y. */ | ||
| 10573 | init_iterator (&it, w, -1, -1, f->desired_matrix->rows, | ||
| 10574 | MODE_LINE_FACE_ID); | ||
| 10575 | it.first_visible_x = 0; | ||
| 10576 | it.last_visible_x = FRAME_WIDTH (f); | ||
| 10577 | } | ||
| 10578 | #endif /* not USE_X_TOOLKIT */ | ||
| 4204 | 10579 | ||
| 4205 | get_display_line (f, vpos, 0); | 10580 | /* Clear all rows of the menu bar. */ |
| 10581 | for (i = 0; i < FRAME_MENU_BAR_LINES (f); ++i) | ||
| 10582 | { | ||
| 10583 | struct glyph_row *row = it.glyph_row + i; | ||
| 10584 | clear_glyph_row (row); | ||
| 10585 | row->enabled_p = 1; | ||
| 10586 | row->full_width_p = 1; | ||
| 10587 | } | ||
| 10588 | |||
| 10589 | /* Make the first line of the menu bar appear in reverse video. */ | ||
| 10590 | it.glyph_row->inverse_p = mode_line_inverse_video != 0; | ||
| 4206 | 10591 | ||
| 4207 | items = FRAME_MENU_BAR_ITEMS (f); | 10592 | /* Display all items of the menu bar. */ |
| 10593 | items = FRAME_MENU_BAR_ITEMS (it.f); | ||
| 4208 | for (i = 0; i < XVECTOR (items)->size; i += 4) | 10594 | for (i = 0; i < XVECTOR (items)->size; i += 4) |
| 4209 | { | 10595 | { |
| 4210 | Lisp_Object pos, string; | 10596 | Lisp_Object string; |
| 10597 | |||
| 10598 | /* Stop at nil string. */ | ||
| 4211 | string = XVECTOR (items)->contents[i + 1]; | 10599 | string = XVECTOR (items)->contents[i + 1]; |
| 4212 | if (NILP (string)) | 10600 | if (NILP (string)) |
| 4213 | break; | 10601 | break; |
| 4214 | 10602 | ||
| 4215 | XSETFASTINT (XVECTOR (items)->contents[i + 3], hpos); | 10603 | /* Remember where item was displayed. */ |
| 10604 | XSETFASTINT (XVECTOR (items)->contents[i + 3], it.hpos); | ||
| 4216 | 10605 | ||
| 4217 | if (hpos < maxendcol) | 10606 | /* Display the item, pad with one space. */ |
| 4218 | hpos = display_string (w, vpos, | 10607 | if (it.current_x < it.last_visible_x) |
| 4219 | XSTRING (string)->data, | 10608 | display_string (NULL, string, Qnil, 0, 0, &it, |
| 4220 | STRING_BYTES (XSTRING (string)), | 10609 | XSTRING (string)->size + 1, 0, 0, -1); |
| 4221 | hpos, 0, 0, hpos, maxendcol, | ||
| 4222 | STRING_MULTIBYTE (string)); | ||
| 4223 | /* Put a space between items. */ | ||
| 4224 | if (hpos < maxendcol) | ||
| 4225 | { | ||
| 4226 | int hpos1 = hpos + 1; | ||
| 4227 | hpos = display_string (w, vpos, "", 0, hpos, 0, 0, | ||
| 4228 | min (hpos1, maxendcol), maxendcol, 0); | ||
| 4229 | } | ||
| 4230 | } | 10610 | } |
| 4231 | 10611 | ||
| 4232 | FRAME_DESIRED_GLYPHS (f)->bufp[vpos] = 0; | ||
| 4233 | FRAME_DESIRED_GLYPHS (f)->highlight[vpos] = mode_line_inverse_video; | ||
| 4234 | |||
| 4235 | /* Fill out the line with spaces. */ | 10612 | /* Fill out the line with spaces. */ |
| 4236 | if (maxendcol > hpos) | 10613 | if (it.current_x < it.last_visible_x) |
| 4237 | hpos = display_string (w, vpos, "", 0, hpos, 0, 0, maxendcol, maxendcol, 0); | 10614 | display_string ("", Qnil, Qnil, 0, 0, &it, -1, 0, 0, -1); |
| 4238 | 10615 | ||
| 4239 | /* Clear the rest of the lines allocated to the menu bar. */ | 10616 | /* Compute the total height of the lines. */ |
| 4240 | vpos++; | 10617 | compute_line_metrics (&it); |
| 4241 | while (vpos < FRAME_MENU_BAR_LINES (f)) | ||
| 4242 | get_display_line (f, vpos++, 0); | ||
| 4243 | } | 10618 | } |
| 10619 | |||
| 10620 | |||
| 4244 | 10621 | ||
| 4245 | /* Display the mode line for window w */ | 10622 | /*********************************************************************** |
| 10623 | Mode Line | ||
| 10624 | ***********************************************************************/ | ||
| 10625 | |||
| 10626 | /* Display the mode and/or top line of window W. */ | ||
| 4246 | 10627 | ||
| 4247 | static void | 10628 | static void |
| 4248 | display_mode_line (w) | 10629 | display_mode_lines (w) |
| 4249 | struct window *w; | 10630 | struct window *w; |
| 4250 | { | 10631 | { |
| 4251 | register int vpos = XFASTINT (w->height) + XFASTINT (w->top) - 1; | 10632 | /* These will be set while the mode line specs are processed. */ |
| 4252 | register int left = WINDOW_LEFT_MARGIN (w); | ||
| 4253 | register int right = WINDOW_RIGHT_MARGIN (w); | ||
| 4254 | register FRAME_PTR f = XFRAME (WINDOW_FRAME (w)); | ||
| 4255 | |||
| 4256 | line_number_displayed = 0; | 10633 | line_number_displayed = 0; |
| 4257 | w->column_number_displayed = Qnil; | 10634 | w->column_number_displayed = Qnil; |
| 4258 | 10635 | ||
| 4259 | get_display_line (f, vpos, left); | 10636 | if (WINDOW_WANTS_MODELINE_P (w)) |
| 10637 | display_mode_line (w, MODE_LINE_FACE_ID, current_buffer->mode_line_format); | ||
| 10638 | |||
| 10639 | if (WINDOW_WANTS_TOP_LINE_P (w)) | ||
| 10640 | display_mode_line (w, TOP_LINE_FACE_ID, current_buffer->top_line_format); | ||
| 10641 | } | ||
| 10642 | |||
| 4260 | 10643 | ||
| 4261 | /* Temporarily make frame F's kboard the current kboard | 10644 | /* Display mode or top line of window W. FACE_ID specifies which line |
| 4262 | so that kboard-local variables in the mode_line_format | 10645 | to display; it is either MODE_LINE_FACE_ID or TOP_LINE_FACE_ID. |
| 4263 | will get the right values. */ | 10646 | FORMAT is the mode line format to display. */ |
| 4264 | push_frame_kboard (f); | ||
| 4265 | 10647 | ||
| 4266 | display_mode_element (w, vpos, left, 0, right, right, | 10648 | static void |
| 4267 | current_buffer->mode_line_format); | 10649 | display_mode_line (w, face_id, format) |
| 10650 | struct window *w; | ||
| 10651 | enum face_id face_id; | ||
| 10652 | Lisp_Object format; | ||
| 10653 | { | ||
| 10654 | struct it it; | ||
| 10655 | struct face *face; | ||
| 4268 | 10656 | ||
| 4269 | pop_frame_kboard (); | 10657 | init_iterator (&it, w, -1, -1, NULL, face_id); |
| 10658 | prepare_desired_row (it.glyph_row); | ||
| 4270 | 10659 | ||
| 4271 | FRAME_DESIRED_GLYPHS (f)->bufp[vpos] = 0; | 10660 | /* Temporarily make frame's keyboard the current kboard so that |
| 10661 | kboard-local variables in the mode_line_format will get the right | ||
| 10662 | values. */ | ||
| 10663 | push_frame_kboard (it.f); | ||
| 10664 | display_mode_element (&it, 0, 0, 0, format); | ||
| 10665 | pop_frame_kboard (); | ||
| 4272 | 10666 | ||
| 4273 | /* Put the mode line in inverse video. | 10667 | /* Fill up with spaces. */ |
| 4274 | Use faces if possible, since that lets us handle | 10668 | display_string (" ", Qnil, Qnil, 0, 0, &it, 10000, -1, -1, 0); |
| 4275 | partial-width windows and avoid inverting the scroll bar columns. */ | 10669 | |
| 4276 | #ifdef HAVE_FACES | 10670 | compute_line_metrics (&it); |
| 4277 | if (! FRAME_TERMCAP_P (f) && mode_line_inverse_video) | 10671 | it.glyph_row->full_width_p = 1; |
| 10672 | it.glyph_row->mode_line_p = 1; | ||
| 10673 | it.glyph_row->inverse_p = mode_line_inverse_video != 0; | ||
| 10674 | it.glyph_row->continued_p = 0; | ||
| 10675 | it.glyph_row->truncated_on_left_p = 0; | ||
| 10676 | it.glyph_row->truncated_on_right_p = 0; | ||
| 10677 | |||
| 10678 | /* Make a 3D mode-line have a shadow at its right end. */ | ||
| 10679 | face = FACE_FROM_ID (it.f, face_id); | ||
| 10680 | extend_face_to_end_of_line (&it); | ||
| 10681 | if (face->box != FACE_NO_BOX) | ||
| 4278 | { | 10682 | { |
| 4279 | /* For a partial width window, explicitly set face of each glyph. */ | 10683 | struct glyph *last = (it.glyph_row->glyphs[TEXT_AREA] |
| 4280 | int i; | 10684 | + it.glyph_row->used[TEXT_AREA] - 1); |
| 4281 | unsigned int padding; | 10685 | last->right_box_line_p = 1; |
| 4282 | GLYPH *ptr = FRAME_DESIRED_GLYPHS (f)->glyphs[vpos]; | ||
| 4283 | for (i = left; i < right; ++i) | ||
| 4284 | { | ||
| 4285 | padding = ptr[i] & GLYPH_MASK_PADDING; | ||
| 4286 | ptr[i] = FAST_MAKE_GLYPH (FAST_GLYPH_CHAR (ptr[i]), 1) | padding; | ||
| 4287 | } | ||
| 4288 | } | 10686 | } |
| 4289 | else | ||
| 4290 | #endif | ||
| 4291 | |||
| 4292 | /* Make the mode line inverse video if the entire line | ||
| 4293 | is made of mode lines. | ||
| 4294 | I.e. if this window is full width, | ||
| 4295 | or if it is the child of a full width window | ||
| 4296 | (which implies that that window is split side-by-side | ||
| 4297 | and the rest of this line is mode lines of the sibling windows). */ | ||
| 4298 | if (WINDOW_FULL_WIDTH_P (w) | ||
| 4299 | || WINDOW_FULL_WIDTH_P (XWINDOW (w->parent))) | ||
| 4300 | FRAME_DESIRED_GLYPHS (f)->highlight[vpos] = mode_line_inverse_video; | ||
| 4301 | } | 10687 | } |
| 4302 | 10688 | ||
| 4303 | /* Contribute ELT to the mode line for window W. | ||
| 4304 | How it translates into text depends on its data type. | ||
| 4305 | 10689 | ||
| 4306 | VPOS is the position of the mode line being displayed. | 10690 | /* Contribute ELT to the mode line for window IT->w. How it |
| 10691 | translates into text depends on its data type. | ||
| 4307 | 10692 | ||
| 4308 | HPOS is the position (absolute on frame) where this element's text | 10693 | IT describes the display environment in which we display, as usual. |
| 4309 | should start. The output is truncated automatically at the right | ||
| 4310 | edge of window W. | ||
| 4311 | 10694 | ||
| 4312 | DEPTH is the depth in recursion. It is used to prevent | 10695 | DEPTH is the depth in recursion. It is used to prevent |
| 4313 | infinite recursion here. | 10696 | infinite recursion here. |
| 4314 | 10697 | ||
| 4315 | MINENDCOL is the hpos before which the element may not end. | 10698 | FIELD_WIDTH is the number of characters the display of ELT should |
| 4316 | The element is padded at the right with spaces if nec | 10699 | occupy in the mode line, and PRECISION is the maximum number of |
| 4317 | to reach this column. | 10700 | characters to display from ELT's representation. See |
| 4318 | 10701 | display_string for details. * | |
| 4319 | MAXENDCOL is the hpos past which this element may not extend. | ||
| 4320 | If MINENDCOL is > MAXENDCOL, MINENDCOL takes priority. | ||
| 4321 | (This is necessary to make nested padding and truncation work.) | ||
| 4322 | 10702 | ||
| 4323 | Returns the hpos of the end of the text generated by ELT. | 10703 | Returns the hpos of the end of the text generated by ELT. */ |
| 4324 | The next element will receive that value as its HPOS arg, | ||
| 4325 | so as to concatenate the elements. */ | ||
| 4326 | 10704 | ||
| 4327 | static int | 10705 | static int |
| 4328 | display_mode_element (w, vpos, hpos, depth, minendcol, maxendcol, elt) | 10706 | display_mode_element (it, depth, field_width, precision, elt) |
| 4329 | struct window *w; | 10707 | struct it *it; |
| 4330 | register int vpos, hpos; | ||
| 4331 | int depth; | 10708 | int depth; |
| 4332 | int minendcol; | 10709 | int field_width, precision; |
| 4333 | register int maxendcol; | 10710 | Lisp_Object elt; |
| 4334 | register Lisp_Object elt; | ||
| 4335 | { | 10711 | { |
| 10712 | int n = 0, field, prec; | ||
| 10713 | |||
| 4336 | tail_recurse: | 10714 | tail_recurse: |
| 4337 | if (depth > 10) | 10715 | if (depth > 10) |
| 4338 | goto invalid; | 10716 | goto invalid; |
| @@ -4344,60 +10722,92 @@ display_mode_element (w, vpos, hpos, depth, minendcol, maxendcol, elt) | |||
| 4344 | case Lisp_String: | 10722 | case Lisp_String: |
| 4345 | { | 10723 | { |
| 4346 | /* A string: output it and check for %-constructs within it. */ | 10724 | /* A string: output it and check for %-constructs within it. */ |
| 4347 | register unsigned char c; | 10725 | unsigned char c; |
| 4348 | register unsigned char *this = XSTRING (elt)->data; | 10726 | unsigned char *this = XSTRING (elt)->data; |
| 4349 | 10727 | unsigned char *lisp_string = this; | |
| 4350 | while (hpos < maxendcol && *this) | 10728 | |
| 10729 | while ((precision <= 0 || n < precision) | ||
| 10730 | && *this | ||
| 10731 | && (frame_title_ptr | ||
| 10732 | || it->current_x < it->last_visible_x)) | ||
| 4351 | { | 10733 | { |
| 4352 | unsigned char *last = this; | 10734 | unsigned char *last = this; |
| 10735 | |||
| 10736 | /* Advance to end of string or next format specifier. */ | ||
| 4353 | while ((c = *this++) != '\0' && c != '%') | 10737 | while ((c = *this++) != '\0' && c != '%') |
| 4354 | ; | 10738 | ; |
| 10739 | |||
| 4355 | if (this - 1 != last) | 10740 | if (this - 1 != last) |
| 4356 | { | 10741 | { |
| 4357 | register int lim = --this - last + hpos; | 10742 | /* Output to end of string or up to '%'. Field width |
| 10743 | is length of string. Don't output more than | ||
| 10744 | PRECISION allows us. */ | ||
| 10745 | prec = --this - last; | ||
| 10746 | if (precision > 0 && prec > precision - n) | ||
| 10747 | prec = precision - n; | ||
| 10748 | |||
| 4358 | if (frame_title_ptr) | 10749 | if (frame_title_ptr) |
| 4359 | hpos = store_frame_title (last, hpos, min (lim, maxendcol)); | 10750 | n += store_frame_title (last, prec, prec); |
| 4360 | else | 10751 | else |
| 4361 | hpos = display_string (w, vpos, last, -1, hpos, 0, 1, | 10752 | n += display_string (NULL, elt, Qnil, 0, last - lisp_string, |
| 4362 | hpos, min (lim, maxendcol), | 10753 | it, 0, prec, 0, -1); |
| 4363 | STRING_MULTIBYTE (elt)); | ||
| 4364 | } | 10754 | } |
| 4365 | else /* c == '%' */ | 10755 | else /* c == '%' */ |
| 4366 | { | 10756 | { |
| 4367 | register int minendcol; | 10757 | unsigned char *percent_position = this; |
| 4368 | register int spec_width = 0; | 10758 | |
| 4369 | 10759 | /* Get the specified minimum width. Zero means | |
| 4370 | /* We can't allow -ve args due to the "%-" construct */ | 10760 | don't pad. */ |
| 4371 | /* Argument specifies minwidth but not maxwidth | 10761 | field = 0; |
| 4372 | (maxwidth can be specified by | ||
| 4373 | (<negative-number> . <stuff>) mode-line elements) */ | ||
| 4374 | |||
| 4375 | while ((c = *this++) >= '0' && c <= '9') | 10762 | while ((c = *this++) >= '0' && c <= '9') |
| 4376 | { | 10763 | field = field * 10 + c - '0'; |
| 4377 | spec_width = spec_width * 10 + (c - '0'); | ||
| 4378 | } | ||
| 4379 | 10764 | ||
| 4380 | minendcol = hpos + spec_width; | 10765 | /* Don't pad beyond the total padding allowed. */ |
| 4381 | if (minendcol > maxendcol) | 10766 | if (field_width - n > 0 && field > field_width - n) |
| 4382 | { | 10767 | field = field_width - n; |
| 4383 | spec_width = maxendcol - hpos; | ||
| 4384 | minendcol = maxendcol; | ||
| 4385 | } | ||
| 4386 | 10768 | ||
| 10769 | /* Note that either PRECISION <= 0 or N < PRECISION. */ | ||
| 10770 | prec = precision - n; | ||
| 10771 | |||
| 4387 | if (c == 'M') | 10772 | if (c == 'M') |
| 4388 | hpos = display_mode_element (w, vpos, hpos, depth, | 10773 | n += display_mode_element (it, depth, field, prec, |
| 4389 | spec_width, maxendcol, | 10774 | Vglobal_mode_string); |
| 4390 | Vglobal_mode_string); | ||
| 4391 | else if (c != 0) | 10775 | else if (c != 0) |
| 4392 | { | 10776 | { |
| 4393 | char *spec = decode_mode_spec (w, c, spec_width, | 10777 | unsigned char *spec |
| 4394 | maxendcol - hpos); | 10778 | = decode_mode_spec (it->w, c, field, prec); |
| 10779 | |||
| 4395 | if (frame_title_ptr) | 10780 | if (frame_title_ptr) |
| 4396 | hpos = store_frame_title (spec, minendcol, maxendcol); | 10781 | n += store_frame_title (spec, field, prec); |
| 4397 | else | 10782 | else |
| 4398 | hpos = display_string (w, vpos, spec, -1, | 10783 | { |
| 4399 | hpos, 0, 1, | 10784 | int nglyphs_before |
| 4400 | minendcol, maxendcol, -1); | 10785 | = it->glyph_row->used[TEXT_AREA]; |
| 10786 | int charpos | ||
| 10787 | = percent_position - XSTRING (elt)->data; | ||
| 10788 | int nwritten | ||
| 10789 | = display_string (spec, Qnil, elt, charpos, 0, it, | ||
| 10790 | field, prec, 0, -1); | ||
| 10791 | |||
| 10792 | /* Assign to the glyphs written above the | ||
| 10793 | string where the `%x' came from, position | ||
| 10794 | of the `%'. */ | ||
| 10795 | if (nwritten > 0) | ||
| 10796 | { | ||
| 10797 | struct glyph *glyph | ||
| 10798 | = (it->glyph_row->glyphs[TEXT_AREA] | ||
| 10799 | + nglyphs_before); | ||
| 10800 | int i; | ||
| 10801 | |||
| 10802 | for (i = 0; i < nwritten; ++i) | ||
| 10803 | { | ||
| 10804 | glyph[i].object = elt; | ||
| 10805 | glyph[i].charpos = charpos; | ||
| 10806 | } | ||
| 10807 | |||
| 10808 | n += nwritten; | ||
| 10809 | } | ||
| 10810 | } | ||
| 4401 | } | 10811 | } |
| 4402 | } | 10812 | } |
| 4403 | } | 10813 | } |
| @@ -4419,18 +10829,21 @@ display_mode_element (w, vpos, hpos, depth, minendcol, maxendcol, elt) | |||
| 4419 | don't check for % within it. */ | 10829 | don't check for % within it. */ |
| 4420 | if (STRINGP (tem)) | 10830 | if (STRINGP (tem)) |
| 4421 | { | 10831 | { |
| 10832 | prec = XSTRING (tem)->size; | ||
| 10833 | if (precision > 0 && prec > precision - n) | ||
| 10834 | prec = precision - n; | ||
| 4422 | if (frame_title_ptr) | 10835 | if (frame_title_ptr) |
| 4423 | hpos = store_frame_title (XSTRING (tem)->data, | 10836 | n += store_frame_title (XSTRING (tem)->data, -1, prec); |
| 4424 | minendcol, maxendcol); | ||
| 4425 | else | 10837 | else |
| 4426 | hpos = display_string (w, vpos, XSTRING (tem)->data, | 10838 | n += display_string (NULL, tem, Qnil, 0, 0, it, |
| 4427 | STRING_BYTES (XSTRING (tem)), | 10839 | 0, prec, 0, -1); |
| 4428 | hpos, 0, 1, minendcol, maxendcol, | ||
| 4429 | STRING_MULTIBYTE (tem)); | ||
| 4430 | } | 10840 | } |
| 4431 | /* Give up right away for nil or t. */ | ||
| 4432 | else if (!EQ (tem, elt)) | 10841 | else if (!EQ (tem, elt)) |
| 4433 | { elt = tem; goto tail_recurse; } | 10842 | { |
| 10843 | /* Give up right away for nil or t. */ | ||
| 10844 | elt = tem; | ||
| 10845 | goto tail_recurse; | ||
| 10846 | } | ||
| 4434 | } | 10847 | } |
| 4435 | } | 10848 | } |
| 4436 | break; | 10849 | break; |
| @@ -4448,7 +10861,20 @@ display_mode_element (w, vpos, hpos, depth, minendcol, maxendcol, elt) | |||
| 4448 | If first element is a symbol, process the cadr or caddr recursively | 10861 | If first element is a symbol, process the cadr or caddr recursively |
| 4449 | according to whether the symbol's value is non-nil or nil. */ | 10862 | according to whether the symbol's value is non-nil or nil. */ |
| 4450 | car = XCONS (elt)->car; | 10863 | car = XCONS (elt)->car; |
| 4451 | if (SYMBOLP (car)) | 10864 | if (EQ (car, QCeval) && CONSP (XCDR (elt))) |
| 10865 | { | ||
| 10866 | /* An element of the form (:eval FORM) means evaluate FORM | ||
| 10867 | and use the result as mode line elements. */ | ||
| 10868 | struct gcpro gcpro1; | ||
| 10869 | Lisp_Object spec; | ||
| 10870 | |||
| 10871 | spec = eval_form (XCAR (XCDR (elt))); | ||
| 10872 | GCPRO1 (spec); | ||
| 10873 | n += display_mode_element (it, depth, field_width - n, | ||
| 10874 | precision - n, spec); | ||
| 10875 | UNGCPRO; | ||
| 10876 | } | ||
| 10877 | else if (SYMBOLP (car)) | ||
| 4452 | { | 10878 | { |
| 4453 | tem = Fboundp (car); | 10879 | tem = Fboundp (car); |
| 4454 | elt = XCONS (elt)->cdr; | 10880 | elt = XCONS (elt)->cdr; |
| @@ -4478,36 +10904,37 @@ display_mode_element (w, vpos, hpos, depth, minendcol, maxendcol, elt) | |||
| 4478 | register int lim = XINT (car); | 10904 | register int lim = XINT (car); |
| 4479 | elt = XCONS (elt)->cdr; | 10905 | elt = XCONS (elt)->cdr; |
| 4480 | if (lim < 0) | 10906 | if (lim < 0) |
| 4481 | /* Negative int means reduce maximum width. | 10907 | { |
| 4482 | DO NOT change MINENDCOL here! | 10908 | /* Negative int means reduce maximum width. */ |
| 4483 | (20 -10 . foo) should truncate foo to 10 col | 10909 | if (precision <= 0) |
| 4484 | and then pad to 20. */ | 10910 | precision = -lim; |
| 4485 | maxendcol = min (maxendcol, hpos - lim); | 10911 | else |
| 10912 | precision = min (precision, -lim); | ||
| 10913 | } | ||
| 4486 | else if (lim > 0) | 10914 | else if (lim > 0) |
| 4487 | { | 10915 | { |
| 4488 | /* Padding specified. Don't let it be more than | 10916 | /* Padding specified. Don't let it be more than |
| 4489 | current maximum. */ | 10917 | current maximum. */ |
| 4490 | lim += hpos; | 10918 | if (precision > 0) |
| 4491 | if (lim > maxendcol) | 10919 | lim = min (precision, lim); |
| 4492 | lim = maxendcol; | 10920 | |
| 4493 | /* If that's more padding than already wanted, queue it. | 10921 | /* If that's more padding than already wanted, queue it. |
| 4494 | But don't reduce padding already specified even if | 10922 | But don't reduce padding already specified even if |
| 4495 | that is beyond the current truncation point. */ | 10923 | that is beyond the current truncation point. */ |
| 4496 | if (lim > minendcol) | 10924 | field_width = max (lim, field_width); |
| 4497 | minendcol = lim; | ||
| 4498 | } | 10925 | } |
| 4499 | goto tail_recurse; | 10926 | goto tail_recurse; |
| 4500 | } | 10927 | } |
| 4501 | else if (STRINGP (car) || CONSP (car)) | 10928 | else if (STRINGP (car) || CONSP (car)) |
| 4502 | { | 10929 | { |
| 4503 | register int limit = 50; | 10930 | register int limit = 50; |
| 4504 | /* LIMIT is to protect against circular lists. */ | 10931 | /* Limit is to protect against circular lists. */ |
| 4505 | while (CONSP (elt) && --limit > 0 | 10932 | while (CONSP (elt) |
| 4506 | && hpos < maxendcol) | 10933 | && --limit > 0 |
| 10934 | && (precision <= 0 || n < precision)) | ||
| 4507 | { | 10935 | { |
| 4508 | hpos = display_mode_element (w, vpos, hpos, depth, | 10936 | n += display_mode_element (it, depth, field_width - n, |
| 4509 | hpos, maxendcol, | 10937 | precision - n, XCONS (elt)->car); |
| 4510 | XCONS (elt)->car); | ||
| 4511 | elt = XCONS (elt)->cdr; | 10938 | elt = XCONS (elt)->cdr; |
| 4512 | } | 10939 | } |
| 4513 | } | 10940 | } |
| @@ -4517,22 +10944,27 @@ display_mode_element (w, vpos, hpos, depth, minendcol, maxendcol, elt) | |||
| 4517 | default: | 10944 | default: |
| 4518 | invalid: | 10945 | invalid: |
| 4519 | if (frame_title_ptr) | 10946 | if (frame_title_ptr) |
| 4520 | hpos = store_frame_title ("*invalid*", minendcol, maxendcol); | 10947 | n += store_frame_title ("*invalid*", 0, precision - n); |
| 4521 | else | 10948 | else |
| 4522 | hpos = display_string (w, vpos, "*invalid*", -1, hpos, 0, 1, | 10949 | n += display_string ("*invalid*", Qnil, Qnil, 0, 0, it, 0, |
| 4523 | minendcol, maxendcol, 0); | 10950 | precision - n, 0, 0); |
| 4524 | return hpos; | 10951 | return n; |
| 4525 | } | 10952 | } |
| 4526 | 10953 | ||
| 4527 | if (minendcol > hpos) | 10954 | /* Pad to FIELD_WIDTH. */ |
| 4528 | if (frame_title_ptr) | 10955 | if (field_width > 0 && n < field_width) |
| 4529 | hpos = store_frame_title ("", minendcol, maxendcol); | 10956 | { |
| 4530 | else | 10957 | if (frame_title_ptr) |
| 4531 | hpos = display_string (w, vpos, "", 0, hpos, | 10958 | n += store_frame_title ("", field_width - n, 0); |
| 4532 | 0, 1, minendcol, maxendcol, 0); | 10959 | else |
| 4533 | return hpos; | 10960 | n += display_string ("", Qnil, Qnil, 0, 0, it, field_width - n, |
| 10961 | 0, 0, 0); | ||
| 10962 | } | ||
| 10963 | |||
| 10964 | return n; | ||
| 4534 | } | 10965 | } |
| 4535 | 10966 | ||
| 10967 | |||
| 4536 | /* Write a null-terminated, right justified decimal representation of | 10968 | /* Write a null-terminated, right justified decimal representation of |
| 4537 | the positive integer D to BUF using a minimal field width WIDTH. */ | 10969 | the positive integer D to BUF using a minimal field width WIDTH. */ |
| 4538 | 10970 | ||
| @@ -4545,24 +10977,28 @@ pint2str (buf, width, d) | |||
| 4545 | register char *p = buf; | 10977 | register char *p = buf; |
| 4546 | 10978 | ||
| 4547 | if (d <= 0) | 10979 | if (d <= 0) |
| 4548 | *p++ = '0'; | 10980 | *p++ = '0'; |
| 4549 | else | 10981 | else |
| 10982 | { | ||
| 4550 | while (d > 0) | 10983 | while (d > 0) |
| 4551 | { | 10984 | { |
| 4552 | *p++ = d % 10 + '0'; | 10985 | *p++ = d % 10 + '0'; |
| 4553 | d /= 10; | 10986 | d /= 10; |
| 4554 | } | 10987 | } |
| 4555 | for (width -= (int) (p - buf); width > 0; --width) *p++ = ' '; | 10988 | } |
| 10989 | |||
| 10990 | for (width -= (int) (p - buf); width > 0; --width) | ||
| 10991 | *p++ = ' '; | ||
| 4556 | *p-- = '\0'; | 10992 | *p-- = '\0'; |
| 4557 | while (p > buf) | 10993 | while (p > buf) |
| 4558 | { | 10994 | { |
| 4559 | d = *buf; | 10995 | d = *buf; |
| 4560 | *buf++ = *p; | 10996 | *buf++ = *p; |
| 4561 | *p-- = d; | 10997 | *p-- = d; |
| 4562 | } | 10998 | } |
| 4563 | } | 10999 | } |
| 4564 | 11000 | ||
| 4565 | /* Set a mnemonic character for CODING_SYSTEM (Lisp symbol) in BUF. | 11001 | /* Set a mnemonic character for coding_system (Lisp symbol) in BUF. |
| 4566 | If EOL_FLAG is 1, set also a mnemonic character for end-of-line | 11002 | If EOL_FLAG is 1, set also a mnemonic character for end-of-line |
| 4567 | type of CODING_SYSTEM. Return updated pointer into BUF. */ | 11003 | type of CODING_SYSTEM. Return updated pointer into BUF. */ |
| 4568 | 11004 | ||
| @@ -4622,7 +11058,7 @@ decode_mode_spec_coding (coding_system, buf, eol_flag) | |||
| 4622 | ? eol_mnemonic_dos : eol_mnemonic_mac)); | 11058 | ? eol_mnemonic_dos : eol_mnemonic_mac)); |
| 4623 | } | 11059 | } |
| 4624 | } | 11060 | } |
| 4625 | 11061 | ||
| 4626 | if (eol_flag) | 11062 | if (eol_flag) |
| 4627 | { | 11063 | { |
| 4628 | /* Mention the EOL conversion if it is not the usual one. */ | 11064 | /* Mention the EOL conversion if it is not the usual one. */ |
| @@ -4652,27 +11088,24 @@ decode_mode_spec_coding (coding_system, buf, eol_flag) | |||
| 4652 | } | 11088 | } |
| 4653 | 11089 | ||
| 4654 | /* Return a string for the output of a mode line %-spec for window W, | 11090 | /* Return a string for the output of a mode line %-spec for window W, |
| 4655 | generated by character C. SPEC_WIDTH is the field width when | 11091 | generated by character C. PRECISION >= 0 means don't return a |
| 4656 | padding to the left (%c, %l). The value returned from this | 11092 | string longer than that value. FIELD_WIDTH > 0 means pad the |
| 4657 | function will later be truncated to width MAXWIDTH. */ | 11093 | string returned with spaces to that value. */ |
| 4658 | 11094 | ||
| 4659 | static char lots_of_dashes[] = "--------------------------------------------------------------------------------------------------------------------------------------------"; | 11095 | static char lots_of_dashes[] = "--------------------------------------------------------------------------------------------------------------------------------------------"; |
| 4660 | 11096 | ||
| 4661 | static char * | 11097 | static char * |
| 4662 | decode_mode_spec (w, c, spec_width, maxwidth) | 11098 | decode_mode_spec (w, c, field_width, precision) |
| 4663 | struct window *w; | 11099 | struct window *w; |
| 4664 | register char c; | 11100 | register char c; |
| 4665 | register int spec_width; | 11101 | int field_width, precision; |
| 4666 | register int maxwidth; | ||
| 4667 | { | 11102 | { |
| 4668 | Lisp_Object obj; | 11103 | Lisp_Object obj; |
| 4669 | FRAME_PTR f = XFRAME (WINDOW_FRAME (w)); | 11104 | struct frame *f = XFRAME (WINDOW_FRAME (w)); |
| 4670 | char *decode_mode_spec_buf = (char *) FRAME_TEMP_GLYPHS (f)->total_contents; | 11105 | char *decode_mode_spec_buf = f->decode_mode_spec_buffer; |
| 4671 | struct buffer *b = XBUFFER (w->buffer); | 11106 | struct buffer *b = XBUFFER (w->buffer); |
| 4672 | 11107 | ||
| 4673 | obj = Qnil; | 11108 | obj = Qnil; |
| 4674 | if (maxwidth > FRAME_WIDTH (f)) | ||
| 4675 | maxwidth = FRAME_WIDTH (f); | ||
| 4676 | 11109 | ||
| 4677 | switch (c) | 11110 | switch (c) |
| 4678 | { | 11111 | { |
| @@ -4730,47 +11163,36 @@ decode_mode_spec (w, c, spec_width, maxwidth) | |||
| 4730 | 11163 | ||
| 4731 | case '-': | 11164 | case '-': |
| 4732 | { | 11165 | { |
| 4733 | register char *p; | ||
| 4734 | register int i; | 11166 | register int i; |
| 4735 | 11167 | ||
| 4736 | if (maxwidth < sizeof (lots_of_dashes)) | 11168 | /* Let lots_of_dashes be a string of infinite length. */ |
| 4737 | return lots_of_dashes; | 11169 | if (field_width <= 0 |
| 4738 | else | 11170 | || field_width > sizeof (lots_of_dashes)) |
| 4739 | { | 11171 | { |
| 4740 | for (p = decode_mode_spec_buf, i = maxwidth; i > 0; i--) | 11172 | for (i = 0; i < FRAME_MESSAGE_BUF_SIZE (f) - 1; ++i) |
| 4741 | *p++ = '-'; | 11173 | decode_mode_spec_buf[i] = '-'; |
| 4742 | *p = '\0'; | 11174 | decode_mode_spec_buf[i] = '\0'; |
| 11175 | return decode_mode_spec_buf; | ||
| 4743 | } | 11176 | } |
| 4744 | return decode_mode_spec_buf; | 11177 | else |
| 11178 | return lots_of_dashes; | ||
| 4745 | } | 11179 | } |
| 4746 | 11180 | ||
| 4747 | case 'b': | 11181 | case 'b': |
| 4748 | obj = b->name; | 11182 | obj = b->name; |
| 4749 | #if 0 | ||
| 4750 | if (maxwidth >= 3 && STRING_BYTES (XSTRING (obj)) > maxwidth) | ||
| 4751 | { | ||
| 4752 | bcopy (XSTRING (obj)->data, decode_mode_spec_buf, maxwidth - 1); | ||
| 4753 | decode_mode_spec_buf[maxwidth - 1] = '\\'; | ||
| 4754 | decode_mode_spec_buf[maxwidth] = '\0'; | ||
| 4755 | return decode_mode_spec_buf; | ||
| 4756 | } | ||
| 4757 | #endif | ||
| 4758 | break; | 11183 | break; |
| 4759 | 11184 | ||
| 4760 | case 'c': | 11185 | case 'c': |
| 4761 | { | 11186 | { |
| 4762 | int col = current_column (); | 11187 | int col = current_column (); |
| 4763 | XSETFASTINT (w->column_number_displayed, col); | 11188 | XSETFASTINT (w->column_number_displayed, col); |
| 4764 | pint2str (decode_mode_spec_buf, spec_width, col); | 11189 | pint2str (decode_mode_spec_buf, field_width, col); |
| 4765 | return decode_mode_spec_buf; | 11190 | return decode_mode_spec_buf; |
| 4766 | } | 11191 | } |
| 4767 | 11192 | ||
| 4768 | case 'F': | 11193 | case 'F': |
| 4769 | /* %F displays the frame name. */ | 11194 | /* %F displays the frame name. */ |
| 4770 | /* Systems that can only display a single frame at a time should | 11195 | if (!NILP (f->title)) |
| 4771 | NOT replace the frame name with the (constant) frame title, | ||
| 4772 | since then they won't be able to tell which frame is that. */ | ||
| 4773 | if (FRAME_WINDOW_P (f) && !NILP (f->title)) | ||
| 4774 | return (char *) XSTRING (f->title)->data; | 11196 | return (char *) XSTRING (f->title)->data; |
| 4775 | if (f->explicit_name || ! FRAME_WINDOW_P (f)) | 11197 | if (f->explicit_name || ! FRAME_WINDOW_P (f)) |
| 4776 | return (char *) XSTRING (f->name)->data; | 11198 | return (char *) XSTRING (f->name)->data; |
| @@ -4778,17 +11200,6 @@ decode_mode_spec (w, c, spec_width, maxwidth) | |||
| 4778 | 11200 | ||
| 4779 | case 'f': | 11201 | case 'f': |
| 4780 | obj = b->filename; | 11202 | obj = b->filename; |
| 4781 | #if 0 | ||
| 4782 | if (NILP (obj)) | ||
| 4783 | return "[none]"; | ||
| 4784 | else if (STRINGP (obj) && STRING_BYTES (XSTRING (obj)) > maxwidth) | ||
| 4785 | { | ||
| 4786 | bcopy ("...", decode_mode_spec_buf, 3); | ||
| 4787 | bcopy (XSTRING (obj)->data + STRING_BYTES (XSTRING (obj)) - maxwidth + 3, | ||
| 4788 | decode_mode_spec_buf + 3, maxwidth - 3); | ||
| 4789 | return decode_mode_spec_buf; | ||
| 4790 | } | ||
| 4791 | #endif | ||
| 4792 | break; | 11203 | break; |
| 4793 | 11204 | ||
| 4794 | case 'l': | 11205 | case 'l': |
| @@ -4797,7 +11208,6 @@ decode_mode_spec (w, c, spec_width, maxwidth) | |||
| 4797 | int startpos_byte = marker_byte_position (w->start); | 11208 | int startpos_byte = marker_byte_position (w->start); |
| 4798 | int line, linepos, linepos_byte, topline; | 11209 | int line, linepos, linepos_byte, topline; |
| 4799 | int nlines, junk; | 11210 | int nlines, junk; |
| 4800 | Lisp_Object tem; | ||
| 4801 | int height = XFASTINT (w->height); | 11211 | int height = XFASTINT (w->height); |
| 4802 | 11212 | ||
| 4803 | /* If we decided that this buffer isn't suitable for line numbers, | 11213 | /* If we decided that this buffer isn't suitable for line numbers, |
| @@ -4887,13 +11297,16 @@ decode_mode_spec (w, c, spec_width, maxwidth) | |||
| 4887 | line_number_displayed = 1; | 11297 | line_number_displayed = 1; |
| 4888 | 11298 | ||
| 4889 | /* Make the string to show. */ | 11299 | /* Make the string to show. */ |
| 4890 | pint2str (decode_mode_spec_buf, spec_width, topline + nlines); | 11300 | pint2str (decode_mode_spec_buf, field_width, topline + nlines); |
| 4891 | return decode_mode_spec_buf; | 11301 | return decode_mode_spec_buf; |
| 4892 | no_value: | 11302 | no_value: |
| 4893 | { | 11303 | { |
| 4894 | char* p = decode_mode_spec_buf; | 11304 | char* p = decode_mode_spec_buf; |
| 4895 | for (spec_width -= 2; spec_width > 0; --spec_width) *p++ = ' '; | 11305 | int pad = field_width - 2; |
| 4896 | strcpy (p, "??"); | 11306 | while (pad-- > 0) |
| 11307 | *p++ = ' '; | ||
| 11308 | *p++ = '?'; | ||
| 11309 | *p = '?'; | ||
| 4897 | return decode_mode_spec_buf; | 11310 | return decode_mode_spec_buf; |
| 4898 | } | 11311 | } |
| 4899 | } | 11312 | } |
| @@ -5028,7 +11441,8 @@ decode_mode_spec (w, c, spec_width, maxwidth) | |||
| 5028 | else | 11441 | else |
| 5029 | return ""; | 11442 | return ""; |
| 5030 | } | 11443 | } |
| 5031 | 11444 | ||
| 11445 | |||
| 5032 | /* Count up to COUNT lines starting from START / START_BYTE. | 11446 | /* Count up to COUNT lines starting from START / START_BYTE. |
| 5033 | But don't go beyond LIMIT_BYTE. | 11447 | But don't go beyond LIMIT_BYTE. |
| 5034 | Return the number of lines thus found (always nonnegative). | 11448 | Return the number of lines thus found (always nonnegative). |
| @@ -5132,269 +11546,202 @@ display_count_lines (start, start_byte, limit_byte, count, byte_pos_ptr) | |||
| 5132 | return orig_count - count; | 11546 | return orig_count - count; |
| 5133 | 11547 | ||
| 5134 | } | 11548 | } |
| 5135 | |||
| 5136 | /* Display STRING on one line of window W, starting at HPOS. | ||
| 5137 | Display at position VPOS. Caller should have done get_display_line. | ||
| 5138 | If VPOS == -1, display it as the current frame's title. | ||
| 5139 | LENGTH is the length of STRING, or -1 meaning STRING is null-terminated. | ||
| 5140 | 11549 | ||
| 5141 | TRUNCATE is GLYPH to display at end if truncated. Zero for none. | ||
| 5142 | 11550 | ||
| 5143 | MINCOL is the first column ok to end at. (Pad with spaces to this col.) | 11551 | |
| 5144 | MAXCOL is the last column ok to end at. Truncate here. | 11552 | /*********************************************************************** |
| 5145 | -1 for MINCOL or MAXCOL means no explicit minimum or maximum. | 11553 | Displaying strings |
| 5146 | Both count from the left edge of the frame, as does HPOS. | 11554 | ***********************************************************************/ |
| 5147 | The right edge of W is an implicit maximum. | ||
| 5148 | If TRUNCATE is nonzero, the implicit maximum is one column before the edge. | ||
| 5149 | 11555 | ||
| 5150 | OBEY_WINDOW_WIDTH says to put spaces or vertical bars | 11556 | /* Display a NUL-terminated string, starting with index START. |
| 5151 | at the place where the current window ends in this line | ||
| 5152 | and not display anything beyond there. Otherwise, only MAXCOL | ||
| 5153 | controls where to stop output. | ||
| 5154 | 11557 | ||
| 5155 | MULTIBYTE can be 0 meaning do not display multibyte chars, | 11558 | If STRING is non-null, display that C string. Otherwise, the Lisp |
| 5156 | 1 meaning do display them, or -1 meaning obey the current buffer's | 11559 | string LISP_STRING is displayed. |
| 5157 | value of enable_multibyte_characters. | ||
| 5158 | 11560 | ||
| 5159 | Returns ending hpos. */ | 11561 | If FACE_STRING is not nil, FACE_STRING_POS is a position in |
| 11562 | FACE_STRING. Display STRING or LISP_STRING with the face at | ||
| 11563 | FACE_STRING_POS in FACE_STRING: | ||
| 5160 | 11564 | ||
| 5161 | static int | 11565 | Display the string in the environment given by IT, but use the |
| 5162 | display_string (w, vpos, string, length, hpos, truncate, | 11566 | standard display table, temporarily. |
| 5163 | obey_window_width, mincol, maxcol, multibyte) | ||
| 5164 | struct window *w; | ||
| 5165 | unsigned char *string; | ||
| 5166 | int length; | ||
| 5167 | int vpos, hpos; | ||
| 5168 | GLYPH truncate; | ||
| 5169 | int obey_window_width; | ||
| 5170 | int mincol, maxcol; | ||
| 5171 | int multibyte; | ||
| 5172 | { | ||
| 5173 | register int c; | ||
| 5174 | int truncated; | ||
| 5175 | register GLYPH *p1; | ||
| 5176 | int hscroll = XINT (w->hscroll); | ||
| 5177 | int tab_width = XINT (XBUFFER (w->buffer)->tab_width); | ||
| 5178 | register GLYPH *start; | ||
| 5179 | register GLYPH *end; | ||
| 5180 | FRAME_PTR f = XFRAME (WINDOW_FRAME (w)); | ||
| 5181 | struct frame_glyphs *desired_glyphs = FRAME_DESIRED_GLYPHS (f); | ||
| 5182 | GLYPH *p1start = desired_glyphs->glyphs[vpos] + hpos; | ||
| 5183 | int window_width = XFASTINT (w->width); | ||
| 5184 | |||
| 5185 | /* Use the standard display table, not the window's display table. | ||
| 5186 | We don't want the mode line in rot13. */ | ||
| 5187 | register struct Lisp_Char_Table *dp = 0; | ||
| 5188 | int i; | ||
| 5189 | |||
| 5190 | if (multibyte == -1) | ||
| 5191 | multibyte = !NILP (current_buffer->enable_multibyte_characters); | ||
| 5192 | /* Now multibyte is 1 if we should display multibyte characters. */ | ||
| 5193 | 11567 | ||
| 5194 | if (DISP_TABLE_P (Vstandard_display_table)) | 11568 | FIELD_WIDTH is the minimum number of output glyphs to produce. |
| 5195 | dp = XCHAR_TABLE (Vstandard_display_table); | 11569 | If STRING has fewer characters than FIELD_WIDTH, pad to the right |
| 11570 | with spaces. If STRING has more characters, more than FIELD_WIDTH | ||
| 11571 | glyphs will be produced. FIELD_WIDTH <= 0 means don't pad. | ||
| 11572 | |||
| 11573 | PRECISION is the maximum number of characters to output from | ||
| 11574 | STRING. PRECISION < 0 means don't truncate the string. | ||
| 5196 | 11575 | ||
| 5197 | if (tab_width <= 0 || tab_width > 1000) tab_width = 8; | 11576 | This is roughly equivalent to printf format specifiers: |
| 5198 | 11577 | ||
| 5199 | p1 = p1start; | 11578 | FIELD_WIDTH PRECISION PRINTF |
| 5200 | start = desired_glyphs->glyphs[vpos]; | 11579 | ---------------------------------------- |
| 11580 | -1 -1 %s | ||
| 11581 | -1 10 %.10s | ||
| 11582 | 10 -1 %10s | ||
| 11583 | 20 10 %20.10s | ||
| 5201 | 11584 | ||
| 5202 | if (obey_window_width) | 11585 | MULTIBYTE zero means do not display multibyte chars, > 0 means do |
| 5203 | { | 11586 | display them, and < 0 means obey the current buffer's value of |
| 5204 | start += XFASTINT (w->left); | 11587 | enable_multibyte_characters. |
| 5205 | end = start + window_width - (truncate != 0); | ||
| 5206 | 11588 | ||
| 5207 | if (!WINDOW_RIGHTMOST_P (w)) | 11589 | Value is the number of glyphs produced. */ |
| 5208 | { | ||
| 5209 | if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f)) | ||
| 5210 | { | ||
| 5211 | int i; | ||
| 5212 | 11590 | ||
| 5213 | for (i = 0; i < FRAME_SCROLL_BAR_COLS (f); i++) | 11591 | static int |
| 5214 | *end-- = ' '; | 11592 | display_string (string, lisp_string, face_string, face_string_pos, |
| 5215 | } | 11593 | start, it, field_width, precision, max_x, multibyte) |
| 5216 | else if (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)) | 11594 | unsigned char *string; |
| 5217 | *end-- = '|'; | 11595 | Lisp_Object lisp_string; |
| 5218 | } | 11596 | int start; |
| 11597 | struct it *it; | ||
| 11598 | int field_width, precision, max_x; | ||
| 11599 | int multibyte; | ||
| 11600 | { | ||
| 11601 | int hpos_at_start = it->hpos; | ||
| 11602 | int saved_face_id = it->face_id; | ||
| 11603 | struct glyph_row *row = it->glyph_row; | ||
| 11604 | |||
| 11605 | /* Initialize the iterator IT for iteration over STRING beginning | ||
| 11606 | with index START. We assume that IT may be modified here (which | ||
| 11607 | means that display_line has to do something when displaying a | ||
| 11608 | mini-buffer prompt, which it does). */ | ||
| 11609 | reseat_to_string (it, string, lisp_string, start, | ||
| 11610 | precision, field_width, multibyte); | ||
| 11611 | |||
| 11612 | /* If displaying STRING, set up the face of the iterator | ||
| 11613 | from LISP_STRING, if that's given. */ | ||
| 11614 | if (STRINGP (face_string)) | ||
| 11615 | { | ||
| 11616 | int endptr; | ||
| 11617 | struct face *face; | ||
| 11618 | |||
| 11619 | it->face_id | ||
| 11620 | = face_at_string_position (it->w, face_string, face_string_pos, | ||
| 11621 | 0, it->region_beg_charpos, | ||
| 11622 | it->region_end_charpos, | ||
| 11623 | &endptr, it->base_face_id); | ||
| 11624 | face = FACE_FROM_ID (it->f, it->face_id); | ||
| 11625 | it->face_box_p = face->box != FACE_NO_BOX; | ||
| 5219 | } | 11626 | } |
| 5220 | 11627 | ||
| 5221 | if (! obey_window_width | 11628 | /* Set max_x to the maximum allowed X position. Don't let it go |
| 5222 | || (maxcol >= 0 && end - desired_glyphs->glyphs[vpos] > maxcol)) | 11629 | beyond the right edge of the window. */ |
| 5223 | end = desired_glyphs->glyphs[vpos] + maxcol; | 11630 | if (max_x <= 0) |
| 5224 | 11631 | max_x = it->last_visible_x; | |
| 5225 | /* Store 0 in charstart for these columns. */ | 11632 | else |
| 5226 | for (i = (hpos >= 0 ? hpos : 0); i < end - p1start + hpos; i++) | 11633 | max_x = min (max_x, it->last_visible_x); |
| 5227 | desired_glyphs->charstarts[vpos][i] = 0; | ||
| 5228 | 11634 | ||
| 5229 | if (maxcol >= 0 && mincol > maxcol) | 11635 | /* Skip over display elements that are not visible. because IT->w is |
| 5230 | mincol = maxcol; | 11636 | hscrolled. */ |
| 11637 | if (it->current_x < it->first_visible_x) | ||
| 11638 | move_it_in_display_line_to (it, 100000, it->first_visible_x, | ||
| 11639 | MOVE_TO_POS | MOVE_TO_X); | ||
| 5231 | 11640 | ||
| 5232 | if (length < 0) | 11641 | row->ascent = it->max_ascent; |
| 5233 | /* We need this value for multibyte characters. */ | 11642 | row->height = it->max_ascent + it->max_descent; |
| 5234 | length = strlen (string); | ||
| 5235 | 11643 | ||
| 5236 | /* We set truncated to 1 if we get stopped by trying to pass END | 11644 | /* This condition is for the case that we are called with current_x |
| 5237 | (that is, trying to pass MAXCOL.) */ | 11645 | past last_visible_x. */ |
| 5238 | truncated = 0; | 11646 | while (it->current_x < max_x) |
| 5239 | while (1) | ||
| 5240 | { | 11647 | { |
| 5241 | int len; | 11648 | int x_before, x, n_glyphs_before, i, nglyphs; |
| 5242 | 11649 | ||
| 5243 | if (length <= 0) | 11650 | /* Get the next display element. */ |
| 11651 | if (!get_next_display_element (it)) | ||
| 5244 | break; | 11652 | break; |
| 5245 | if (multibyte) | ||
| 5246 | c = STRING_CHAR_AND_LENGTH (string, length, len); | ||
| 5247 | else | ||
| 5248 | c = *string, len = 1; | ||
| 5249 | 11653 | ||
| 5250 | string += len, length -= len; | 11654 | /* Produce glyphs. */ |
| 11655 | x_before = it->current_x; | ||
| 11656 | n_glyphs_before = it->glyph_row->used[TEXT_AREA]; | ||
| 11657 | PRODUCE_GLYPHS (it); | ||
| 5251 | 11658 | ||
| 5252 | if (p1 >= end) | 11659 | nglyphs = it->glyph_row->used[TEXT_AREA] - n_glyphs_before; |
| 11660 | i = 0; | ||
| 11661 | x = x_before; | ||
| 11662 | while (i < nglyphs) | ||
| 5253 | { | 11663 | { |
| 5254 | truncated = 1; | 11664 | struct glyph *glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i; |
| 5255 | break; | 11665 | |
| 5256 | } | 11666 | if (!it->truncate_lines_p |
| 5257 | 11667 | && x + glyph->pixel_width > max_x) | |
| 5258 | if (dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, c))) | 11668 | { |
| 5259 | { | 11669 | /* End of continued line or max_x reached. */ |
| 5260 | p1 = copy_part_of_rope (f, p1, start, | 11670 | it->glyph_row->used[TEXT_AREA] = n_glyphs_before + i; |
| 5261 | XVECTOR (DISP_CHAR_VECTOR (dp, c))->contents, | 11671 | it->current_x = x; |
| 5262 | XVECTOR (DISP_CHAR_VECTOR (dp, c))->size, | 11672 | break; |
| 5263 | 0); | 11673 | } |
| 5264 | } | 11674 | else if (x + glyph->pixel_width > it->first_visible_x) |
| 5265 | else if (c >= 040 && c < 0177) | ||
| 5266 | { | ||
| 5267 | if (p1 >= start) | ||
| 5268 | *p1 = c; | ||
| 5269 | p1++; | ||
| 5270 | } | ||
| 5271 | else if (c == '\t') | ||
| 5272 | { | ||
| 5273 | do | ||
| 5274 | { | 11675 | { |
| 5275 | if (p1 >= start && p1 < end) | 11676 | /* Glyph is at least partially visible. */ |
| 5276 | *p1 = SPACEGLYPH; | 11677 | ++it->hpos; |
| 5277 | p1++; | 11678 | if (x < it->first_visible_x) |
| 11679 | it->glyph_row->x = x - it->first_visible_x; | ||
| 5278 | } | 11680 | } |
| 5279 | while ((p1 - start + hscroll - (hscroll > 0)) % tab_width); | 11681 | else |
| 11682 | { | ||
| 11683 | /* Glyph is off the left margin of the display area. | ||
| 11684 | Should not happen. */ | ||
| 11685 | abort (); | ||
| 11686 | } | ||
| 11687 | |||
| 11688 | row->ascent = max (row->ascent, it->max_ascent); | ||
| 11689 | row->height = max (row->height, it->max_ascent + it->max_descent); | ||
| 11690 | x += glyph->pixel_width; | ||
| 11691 | ++i; | ||
| 5280 | } | 11692 | } |
| 5281 | else if (c < 0200 && ! NILP (buffer_defaults.ctl_arrow)) | 11693 | |
| 11694 | /* Stop if max_x reached. */ | ||
| 11695 | if (i < nglyphs) | ||
| 11696 | break; | ||
| 11697 | |||
| 11698 | /* Stop at line ends. */ | ||
| 11699 | if (ITERATOR_AT_END_OF_LINE_P (it)) | ||
| 5282 | { | 11700 | { |
| 5283 | if (p1 >= start) | 11701 | it->continuation_lines_width = 0; |
| 5284 | *p1 = (fix_glyph | 11702 | break; |
| 5285 | (f, (dp && INTEGERP (DISP_CTRL_GLYPH (dp)) | ||
| 5286 | && GLYPH_CHAR_VALID_P (XINT (DISP_CTRL_GLYPH (dp))) | ||
| 5287 | ? XINT (DISP_CTRL_GLYPH (dp)) : '^'), | ||
| 5288 | 0)); | ||
| 5289 | p1++; | ||
| 5290 | if (p1 >= start && p1 < end) | ||
| 5291 | *p1 = c ^ 0100; | ||
| 5292 | p1++; | ||
| 5293 | } | 11703 | } |
| 5294 | else | ||
| 5295 | { | ||
| 5296 | /* C is a multibyte character, control character or a binary | ||
| 5297 | byte data. */ | ||
| 5298 | int remaining_bytes = len; | ||
| 5299 | 11704 | ||
| 5300 | if (c >= 0400 && CHAR_VALID_P (c, 0)) | 11705 | set_iterator_to_next (it); |
| 5301 | { | ||
| 5302 | /* C is a multibyte character. */ | ||
| 5303 | int charset = CHAR_CHARSET (c); | ||
| 5304 | int columns = (charset == CHARSET_COMPOSITION | ||
| 5305 | ? cmpchar_table[COMPOSITE_CHAR_ID (c)]->width | ||
| 5306 | : CHARSET_WIDTH (charset)); | ||
| 5307 | |||
| 5308 | remaining_bytes -= CHARSET_BYTES (charset); | ||
| 5309 | if (p1 < start) | ||
| 5310 | { | ||
| 5311 | /* Since we can't show the left part of C, fill all | ||
| 5312 | columns with spaces. */ | ||
| 5313 | columns -= start - p1; | ||
| 5314 | p1 = start; | ||
| 5315 | while (columns--) | ||
| 5316 | { | ||
| 5317 | if (p1 < end) | ||
| 5318 | *p1 = SPACEGLYPH; | ||
| 5319 | p1++; | ||
| 5320 | } | ||
| 5321 | } | ||
| 5322 | else if (p1 + columns > end) | ||
| 5323 | { | ||
| 5324 | /* Since we can't show the right part of C, fill all | ||
| 5325 | columns with TRUNCATE if TRUNCATE is specified. */ | ||
| 5326 | if (truncate) | ||
| 5327 | { | ||
| 5328 | while (p1 < end) | ||
| 5329 | *p1++ = fix_glyph (f, truncate, 0); | ||
| 5330 | /* And tell the line is truncated. */ | ||
| 5331 | truncated = 1; | ||
| 5332 | } | ||
| 5333 | break; | ||
| 5334 | } | ||
| 5335 | else | ||
| 5336 | { | ||
| 5337 | /* We can show the whole glyph of C. */ | ||
| 5338 | *p1++ = c; | ||
| 5339 | while (--columns) | ||
| 5340 | *p1++ = c | GLYPH_MASK_PADDING; | ||
| 5341 | } | ||
| 5342 | } | ||
| 5343 | 11706 | ||
| 5344 | while (remaining_bytes > 0) | 11707 | /* Stop if truncating at the right edge. */ |
| 11708 | if (it->truncate_lines_p | ||
| 11709 | && it->current_x >= it->last_visible_x) | ||
| 11710 | { | ||
| 11711 | /* Add truncation mark, but don't do it if the line is | ||
| 11712 | truncated at a padding space. */ | ||
| 11713 | if (IT_CHARPOS (*it) < it->string_nchars) | ||
| 5345 | { | 11714 | { |
| 5346 | c = *(string - remaining_bytes--); | 11715 | if (!FRAME_WINDOW_P (it->f)) |
| 5347 | 11716 | produce_special_glyphs (it, IT_TRUNCATION); | |
| 5348 | if (p1 >= start) | 11717 | it->glyph_row->truncated_on_right_p = 1; |
| 5349 | *p1 = (fix_glyph | ||
| 5350 | (f, (dp && INTEGERP (DISP_ESCAPE_GLYPH (dp)) | ||
| 5351 | && GLYPH_CHAR_VALID_P (XINT (DISP_ESCAPE_GLYPH (dp))) | ||
| 5352 | ? XINT (DISP_ESCAPE_GLYPH (dp)) : '\\'), | ||
| 5353 | 0)); | ||
| 5354 | p1++; | ||
| 5355 | if (p1 >= start && p1 < end) | ||
| 5356 | *p1 = (c >> 6) + '0'; | ||
| 5357 | p1++; | ||
| 5358 | if (p1 >= start && p1 < end) | ||
| 5359 | *p1 = (7 & (c >> 3)) + '0'; | ||
| 5360 | p1++; | ||
| 5361 | if (p1 >= start && p1 < end) | ||
| 5362 | *p1 = (7 & c) + '0'; | ||
| 5363 | p1++; | ||
| 5364 | } | 11718 | } |
| 11719 | break; | ||
| 5365 | } | 11720 | } |
| 5366 | } | 11721 | } |
| 5367 | 11722 | ||
| 5368 | if (truncated) | 11723 | /* Maybe insert a truncation at the left. */ |
| 5369 | { | 11724 | if (it->first_visible_x |
| 5370 | p1 = end; | 11725 | && IT_CHARPOS (*it) > 0) |
| 5371 | if (truncate) *p1++ = fix_glyph (f, truncate, 0); | ||
| 5372 | } | ||
| 5373 | else if (mincol >= 0) | ||
| 5374 | { | 11726 | { |
| 5375 | end = desired_glyphs->glyphs[vpos] + mincol; | 11727 | if (!FRAME_WINDOW_P (it->f)) |
| 5376 | while (p1 < end) | 11728 | insert_left_trunc_glyphs (it); |
| 5377 | *p1++ = SPACEGLYPH; | 11729 | it->glyph_row->truncated_on_left_p = 1; |
| 5378 | } | 11730 | } |
| 5379 | 11731 | ||
| 5380 | { | 11732 | it->face_id = saved_face_id; |
| 5381 | register int len = p1 - desired_glyphs->glyphs[vpos]; | 11733 | |
| 11734 | /* Value is number of columns displayed. */ | ||
| 11735 | return it->hpos - hpos_at_start; | ||
| 11736 | } | ||
| 5382 | 11737 | ||
| 5383 | if (len > desired_glyphs->used[vpos]) | ||
| 5384 | desired_glyphs->used[vpos] = len; | ||
| 5385 | desired_glyphs->glyphs[vpos][desired_glyphs->used[vpos]] = 0; | ||
| 5386 | 11738 | ||
| 5387 | return len; | ||
| 5388 | } | ||
| 5389 | } | ||
| 5390 | 11739 | ||
| 5391 | /* This is like a combination of memq and assq. | 11740 | /* This is like a combination of memq and assq. Return 1 if PROPVAL |
| 5392 | Return 1 if PROPVAL appears as an element of LIST | 11741 | appears as an element of LIST or as the car of an element of LIST. |
| 5393 | or as the car of an element of LIST. | 11742 | If PROPVAL is a list, compare each element against LIST in that |
| 5394 | If PROPVAL is a list, compare each element against LIST | 11743 | way, and return 1 if any element of PROPVAL is found in LIST. |
| 5395 | in that way, and return 1 if any element of PROPVAL is found in LIST. | 11744 | Otherwise return 0. This function cannot quit. */ |
| 5396 | Otherwise return 0. | ||
| 5397 | This function cannot quit. */ | ||
| 5398 | 11745 | ||
| 5399 | int | 11746 | int |
| 5400 | invisible_p (propval, list) | 11747 | invisible_p (propval, list) |
| @@ -5430,13 +11777,12 @@ invisible_p (propval, list) | |||
| 5430 | return 0; | 11777 | return 0; |
| 5431 | } | 11778 | } |
| 5432 | 11779 | ||
| 5433 | /* Return 1 if PROPVAL appears as the car of an element of LIST | 11780 | |
| 5434 | and the cdr of that element is non-nil. | 11781 | /* Return 1 if PROPVAL appears as the car of an element of LIST and |
| 5435 | If PROPVAL is a list, check each element of PROPVAL in that way, | 11782 | the cdr of that element is non-nil. If PROPVAL is a list, check |
| 5436 | and the first time some element is found, | 11783 | each element of PROPVAL in that way, and the first time some |
| 5437 | return 1 if the cdr of that element is non-nil. | 11784 | element is found, return 1 if the cdr of that element is non-nil. |
| 5438 | Otherwise return 0. | 11785 | Otherwise return 0. This function cannot quit. */ |
| 5439 | This function cannot quit. */ | ||
| 5440 | 11786 | ||
| 5441 | int | 11787 | int |
| 5442 | invisible_ellipsis_p (propval, list) | 11788 | invisible_ellipsis_p (propval, list) |
| @@ -5467,13 +11813,30 @@ invisible_ellipsis_p (propval, list) | |||
| 5467 | } | 11813 | } |
| 5468 | return 0; | 11814 | return 0; |
| 5469 | } | 11815 | } |
| 11816 | |||
| 11817 | |||
| 5470 | 11818 | ||
| 11819 | /*********************************************************************** | ||
| 11820 | Initialization | ||
| 11821 | ***********************************************************************/ | ||
| 11822 | |||
| 5471 | void | 11823 | void |
| 5472 | syms_of_xdisp () | 11824 | syms_of_xdisp () |
| 5473 | { | 11825 | { |
| 11826 | echo_area_message = previous_echo_area_message = Qnil; | ||
| 11827 | staticpro (&echo_area_message); | ||
| 11828 | staticpro (&previous_echo_area_message); | ||
| 11829 | |||
| 5474 | staticpro (&Qinhibit_redisplay); | 11830 | staticpro (&Qinhibit_redisplay); |
| 5475 | Qinhibit_redisplay = intern ("inhibit-redisplay"); | 11831 | Qinhibit_redisplay = intern ("inhibit-redisplay"); |
| 5476 | 11832 | ||
| 11833 | #if GLYPH_DEBUG | ||
| 11834 | defsubr (&Sdump_glyph_matrix); | ||
| 11835 | defsubr (&Sdump_glyph_row); | ||
| 11836 | defsubr (&Sdump_toolbar_row); | ||
| 11837 | defsubr (&Strace_redisplay_toggle); | ||
| 11838 | #endif | ||
| 11839 | |||
| 5477 | staticpro (&Qmenu_bar_update_hook); | 11840 | staticpro (&Qmenu_bar_update_hook); |
| 5478 | Qmenu_bar_update_hook = intern ("menu-bar-update-hook"); | 11841 | Qmenu_bar_update_hook = intern ("menu-bar-update-hook"); |
| 5479 | 11842 | ||
| @@ -5488,10 +11851,51 @@ syms_of_xdisp () | |||
| 5488 | 11851 | ||
| 5489 | staticpro (&Qredisplay_end_trigger_functions); | 11852 | staticpro (&Qredisplay_end_trigger_functions); |
| 5490 | Qredisplay_end_trigger_functions = intern ("redisplay-end-trigger-functions"); | 11853 | Qredisplay_end_trigger_functions = intern ("redisplay-end-trigger-functions"); |
| 5491 | 11854 | ||
| 5492 | staticpro (&Qinhibit_point_motion_hooks); | 11855 | staticpro (&Qinhibit_point_motion_hooks); |
| 5493 | Qinhibit_point_motion_hooks = intern ("inhibit-point-motion-hooks"); | 11856 | Qinhibit_point_motion_hooks = intern ("inhibit-point-motion-hooks"); |
| 5494 | 11857 | ||
| 11858 | staticpro (&Qdisplay); | ||
| 11859 | Qdisplay = intern ("display"); | ||
| 11860 | staticpro (&Qleft_margin); | ||
| 11861 | Qspace_width = intern ("space-width"); | ||
| 11862 | staticpro (&Qspace_width); | ||
| 11863 | Qheight = intern ("height"); | ||
| 11864 | staticpro (&Qheight); | ||
| 11865 | Qraise = intern ("raise"); | ||
| 11866 | staticpro (&Qraise); | ||
| 11867 | Qspace = intern ("space"); | ||
| 11868 | staticpro (&Qspace); | ||
| 11869 | Qleft_margin = intern ("left-margin"); | ||
| 11870 | staticpro (&Qright_margin); | ||
| 11871 | Qright_margin = intern ("right-margin"); | ||
| 11872 | Qalign_to = intern ("align-to"); | ||
| 11873 | staticpro (&Qalign_to); | ||
| 11874 | QCalign_to = intern (":align-to"); | ||
| 11875 | staticpro (&QCalign_to); | ||
| 11876 | Qwidth = intern ("width"); | ||
| 11877 | staticpro (&Qwidth); | ||
| 11878 | Qrelative_width = intern ("relative-width"); | ||
| 11879 | staticpro (&Qrelative_width); | ||
| 11880 | QCrelative_width = intern (":relative-width"); | ||
| 11881 | staticpro (&QCrelative_width); | ||
| 11882 | QCrelative_height = intern (":relative-height"); | ||
| 11883 | staticpro (&QCrelative_height); | ||
| 11884 | QCeval = intern (":eval"); | ||
| 11885 | staticpro (&QCeval); | ||
| 11886 | QCwhen = intern (":when"); | ||
| 11887 | staticpro (&QCwhen); | ||
| 11888 | Qfontified = intern ("fontified"); | ||
| 11889 | staticpro (&Qfontified); | ||
| 11890 | Qfontification_functions = intern ("fontification-functions"); | ||
| 11891 | staticpro (&Qfontification_functions); | ||
| 11892 | Qshow_trailing_whitespace = intern ("show-trailing-whitespace"); | ||
| 11893 | staticpro (&Qshow_trailing_whitespace); | ||
| 11894 | Qtrailing_whitespace = intern ("trailing-whitespace"); | ||
| 11895 | staticpro (&Qtrailing_whitespace); | ||
| 11896 | Qimage = intern ("image"); | ||
| 11897 | staticpro (&Qimage); | ||
| 11898 | |||
| 5495 | staticpro (&last_arrow_position); | 11899 | staticpro (&last_arrow_position); |
| 5496 | staticpro (&last_arrow_string); | 11900 | staticpro (&last_arrow_string); |
| 5497 | last_arrow_position = Qnil; | 11901 | last_arrow_position = Qnil; |
| @@ -5531,7 +11935,9 @@ Recenter the window whenever point gets within this many lines\n\ | |||
| 5531 | of the top or bottom of the window."); | 11935 | of the top or bottom of the window."); |
| 5532 | scroll_margin = 0; | 11936 | scroll_margin = 0; |
| 5533 | 11937 | ||
| 11938 | #if GLYPH_DEBUG | ||
| 5534 | DEFVAR_INT ("debug-end-pos", &debug_end_pos, "Don't ask"); | 11939 | DEFVAR_INT ("debug-end-pos", &debug_end_pos, "Don't ask"); |
| 11940 | #endif | ||
| 5535 | 11941 | ||
| 5536 | DEFVAR_BOOL ("truncate-partial-width-windows", | 11942 | DEFVAR_BOOL ("truncate-partial-width-windows", |
| 5537 | &truncate_partial_width_windows, | 11943 | &truncate_partial_width_windows, |
| @@ -5543,7 +11949,7 @@ of the top or bottom of the window."); | |||
| 5543 | mode_line_inverse_video = 1; | 11949 | mode_line_inverse_video = 1; |
| 5544 | 11950 | ||
| 5545 | DEFVAR_INT ("line-number-display-limit", &line_number_display_limit, | 11951 | DEFVAR_INT ("line-number-display-limit", &line_number_display_limit, |
| 5546 | "*Maximum buffer size (in characters) for line number display\n\ | 11952 | "*Maximum buffer size for which line number should be displayed.\n\ |
| 5547 | If the buffer is bigger than this, the line number does not appear\n\ | 11953 | If the buffer is bigger than this, the line number does not appear\n\ |
| 5548 | in the mode line."); | 11954 | in the mode line."); |
| 5549 | line_number_display_limit = 1000000; | 11955 | line_number_display_limit = 1000000; |
| @@ -5559,13 +11965,13 @@ This variable is not guaranteed to be accurate except while processing\n\ | |||
| 5559 | `frame-title-format' and `icon-title-format'."); | 11965 | `frame-title-format' and `icon-title-format'."); |
| 5560 | 11966 | ||
| 5561 | DEFVAR_LISP ("frame-title-format", &Vframe_title_format, | 11967 | DEFVAR_LISP ("frame-title-format", &Vframe_title_format, |
| 5562 | "Template for displaying the titlebar of visible frames.\n\ | 11968 | "Template for displaying the title bar of visible frames.\n\ |
| 5563 | \(Assuming the window manager supports this feature.)\n\ | 11969 | \(Assuming the window manager supports this feature.)\n\ |
| 5564 | This variable has the same structure as `mode-line-format' (which see),\n\ | 11970 | This variable has the same structure as `mode-line-format' (which see),\n\ |
| 5565 | and is used only on frames for which no explicit name has been set\n\ | 11971 | and is used only on frames for which no explicit name has been set\n\ |
| 5566 | \(see `modify-frame-parameters')."); | 11972 | \(see `modify-frame-parameters')."); |
| 5567 | DEFVAR_LISP ("icon-title-format", &Vicon_title_format, | 11973 | DEFVAR_LISP ("icon-title-format", &Vicon_title_format, |
| 5568 | "Template for displaying the titlebar of an iconified frame.\n\ | 11974 | "Template for displaying the title bar of an iconified frame.\n\ |
| 5569 | \(Assuming the window manager supports this feature.)\n\ | 11975 | \(Assuming the window manager supports this feature.)\n\ |
| 5570 | This variable has the same structure as `mode-line-format' (which see),\n\ | 11976 | This variable has the same structure as `mode-line-format' (which see),\n\ |
| 5571 | and is used only on frames for which no explicit name has been set\n\ | 11977 | and is used only on frames for which no explicit name has been set\n\ |
| @@ -5596,20 +12002,43 @@ all the functions in the list are called, with the frame as argument."); | |||
| 5596 | Vwindow_size_change_functions = Qnil; | 12002 | Vwindow_size_change_functions = Qnil; |
| 5597 | 12003 | ||
| 5598 | DEFVAR_LISP ("window-scroll-functions", &Vwindow_scroll_functions, | 12004 | DEFVAR_LISP ("window-scroll-functions", &Vwindow_scroll_functions, |
| 5599 | "List of functions to call before redisplaying a window with scrolling.\n\ | 12005 | "List of Functions to call before redisplaying a window with scrolling.\n\ |
| 5600 | Each function is called with two arguments, the window\n\ | 12006 | Each function is called with two arguments, the window\n\ |
| 5601 | and its new display-start position. Note that the value of `window-end'\n\ | 12007 | and its new display-start position. Note that the value of `window-end'\n\ |
| 5602 | is not valid when these functions are called."); | 12008 | is not valid when these functions are called."); |
| 5603 | Vwindow_scroll_functions = Qnil; | 12009 | Vwindow_scroll_functions = Qnil; |
| 5604 | 12010 | ||
| 5605 | DEFVAR_INT ("minibuffer-scroll-overlap", &minibuffer_scroll_overlap, | 12011 | DEFVAR_BOOL ("auto-resize-toolbars", &auto_resize_toolbars_p, |
| 5606 | "*Number of characters of overlap when scrolling a one-line window.\n\ | 12012 | "*Non-nil means automatically resize toolbars.\n\ |
| 5607 | This commonly affects the minibuffer window, hence the name of the variable."); | 12013 | This increases a toolbar's height if not all toolbar items are visible.\n\ |
| 5608 | minibuffer_scroll_overlap = 20; | 12014 | It decreases a toolbar's height when it would display blank lines\n\ |
| 12015 | otherwise."); | ||
| 12016 | auto_resize_toolbars_p = 1; | ||
| 12017 | |||
| 12018 | DEFVAR_BOOL ("auto-raise-toolbar-buttons", &auto_raise_toolbar_buttons_p, | ||
| 12019 | "*Non-nil means raise toolbar buttons when the mouse moves over them."); | ||
| 12020 | auto_raise_toolbar_buttons_p = 1; | ||
| 12021 | |||
| 12022 | DEFVAR_INT ("toolbar-button-margin", &toolbar_button_margin, | ||
| 12023 | "*Margin around toolbar buttons in pixels."); | ||
| 12024 | toolbar_button_margin = 1; | ||
| 12025 | |||
| 12026 | DEFVAR_INT ("toolbar-button-relief", &toolbar_button_relief, | ||
| 12027 | "Relief thickness of toolbar buttons."); | ||
| 12028 | toolbar_button_relief = 3; | ||
| 12029 | |||
| 12030 | DEFVAR_LISP ("fontification-functions", &Vfontification_functions, | ||
| 12031 | "List of functions to call to fontify regions of text.\n\ | ||
| 12032 | Each function is called with one argument POS. Functions must\n\ | ||
| 12033 | fontify a region starting at POS in the current buffer, and give\n\ | ||
| 12034 | fontified regions the property `fontified'.\n\ | ||
| 12035 | This variable automatically becomes buffer-local when set."); | ||
| 12036 | Vfontification_functions = Qnil; | ||
| 12037 | Fmake_local_variable (Qfontification_functions); | ||
| 5609 | 12038 | ||
| 5610 | DEFVAR_BOOL ("unibyte-display-via-language-environment", | 12039 | DEFVAR_BOOL ("unibyte-display-via-language-environment", |
| 5611 | &unibyte_display_via_language_environment, | 12040 | &unibyte_display_via_language_environment, |
| 5612 | "*Non-nil means display unibyte text according to language environment.\n\ | 12041 | "*Non-nil means display unibyte text according to language environment.\n\ |
| 5613 | Specifically this means that unibyte non-ASCII characters\n\ | 12042 | Specifically this means that unibyte non-ASCII characters\n\ |
| 5614 | are displayed by converting them to the equivalent multibyte characters\n\ | 12043 | are displayed by converting them to the equivalent multibyte characters\n\ |
| 5615 | according to the current language environment. As a result, they are\n\ | 12044 | according to the current language environment. As a result, they are\n\ |
| @@ -5617,35 +12046,57 @@ displayed according to the current fontset."); | |||
| 5617 | unibyte_display_via_language_environment = 0; | 12046 | unibyte_display_via_language_environment = 0; |
| 5618 | } | 12047 | } |
| 5619 | 12048 | ||
| 5620 | /* initialize the window system */ | 12049 | |
| 12050 | /* Initialize this module when Emacs starts. */ | ||
| 12051 | |||
| 5621 | void | 12052 | void |
| 5622 | init_xdisp () | 12053 | init_xdisp () |
| 5623 | { | 12054 | { |
| 5624 | Lisp_Object root_window; | 12055 | Lisp_Object root_window; |
| 5625 | #ifndef COMPILER_REGISTER_BUG | 12056 | struct window *mini_w; |
| 5626 | register | ||
| 5627 | #endif /* COMPILER_REGISTER_BUG */ | ||
| 5628 | struct window *mini_w; | ||
| 5629 | 12057 | ||
| 5630 | this_line_bufpos = 0; | 12058 | CHARPOS (this_line_start_pos) = 0; |
| 5631 | 12059 | ||
| 5632 | mini_w = XWINDOW (minibuf_window); | 12060 | mini_w = XWINDOW (minibuf_window); |
| 5633 | root_window = FRAME_ROOT_WINDOW (XFRAME (WINDOW_FRAME (mini_w))); | 12061 | root_window = FRAME_ROOT_WINDOW (XFRAME (WINDOW_FRAME (mini_w))); |
| 5634 | 12062 | ||
| 5635 | echo_area_glyphs = 0; | 12063 | echo_area_glyphs = 0; |
| 5636 | previous_echo_glyphs = 0; | 12064 | previous_echo_glyphs = 0; |
| 12065 | echo_area_message = previous_echo_area_message = Qnil; | ||
| 5637 | 12066 | ||
| 5638 | if (!noninteractive) | 12067 | if (!noninteractive) |
| 5639 | { | 12068 | { |
| 5640 | FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (root_window))); | 12069 | struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (root_window))); |
| 5641 | XSETFASTINT (XWINDOW (root_window)->top, FRAME_MENU_BAR_LINES (f)); | 12070 | int i; |
| 12071 | |||
| 12072 | XSETFASTINT (XWINDOW (root_window)->top, FRAME_TOP_MARGIN (f)); | ||
| 5642 | set_window_height (root_window, | 12073 | set_window_height (root_window, |
| 5643 | FRAME_HEIGHT (f) - 1 - FRAME_MENU_BAR_LINES (f), | 12074 | FRAME_HEIGHT (f) - 1 - FRAME_TOP_MARGIN (f), |
| 5644 | 0); | 12075 | 0); |
| 5645 | XSETFASTINT (mini_w->top, FRAME_HEIGHT (f) - 1); | 12076 | XSETFASTINT (mini_w->top, FRAME_HEIGHT (f) - 1); |
| 5646 | set_window_height (minibuf_window, 1, 0); | 12077 | set_window_height (minibuf_window, 1, 0); |
| 5647 | 12078 | ||
| 5648 | XSETFASTINT (XWINDOW (root_window)->width, FRAME_WIDTH (f)); | 12079 | XSETFASTINT (XWINDOW (root_window)->width, FRAME_WIDTH (f)); |
| 5649 | XSETFASTINT (mini_w->width, FRAME_WIDTH (f)); | 12080 | XSETFASTINT (mini_w->width, FRAME_WIDTH (f)); |
| 12081 | |||
| 12082 | scratch_glyph_row.glyphs[TEXT_AREA] = scratch_glyphs; | ||
| 12083 | scratch_glyph_row.glyphs[TEXT_AREA + 1] | ||
| 12084 | = scratch_glyphs + MAX_SCRATCH_GLYPHS; | ||
| 12085 | |||
| 12086 | /* The default ellipsis glyphs `...'. */ | ||
| 12087 | for (i = 0; i < 3; ++i) | ||
| 12088 | XSETFASTINT (default_invis_vector[i], '.'); | ||
| 5650 | } | 12089 | } |
| 12090 | |||
| 12091 | #ifdef HAVE_WINDOW_SYSTEM | ||
| 12092 | { | ||
| 12093 | /* Allocate the buffer for frame titles. */ | ||
| 12094 | int size = 100; | ||
| 12095 | frame_title_buf = (char *) xmalloc (size); | ||
| 12096 | frame_title_buf_end = frame_title_buf + size; | ||
| 12097 | frame_title_ptr = NULL; | ||
| 12098 | } | ||
| 12099 | #endif /* HAVE_WINDOW_SYSTEM */ | ||
| 5651 | } | 12100 | } |
| 12101 | |||
| 12102 | |||