Initial revision
[chise/xemacs-chise.git.1] / src / redisplay-output.c
1 /* Synchronize redisplay structures and output changes.
2    Copyright (C) 1994, 1995 Board of Trustees, University of Illinois.
3    Copyright (C) 1995, 1996 Ben Wing.
4    Copyright (C) 1996 Chuck Thompson.
5
6 This file is part of XEmacs.
7
8 XEmacs is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
11 later version.
12
13 XEmacs is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16 for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with XEmacs; see the file COPYING.  If not, write to
20 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA.  */
22
23 /* Synched up with: Not in FSF. */
24
25 /* This file has been Mule-ized. */
26
27 /* Author: Chuck Thompson */
28
29 #include <config.h>
30 #include "lisp.h"
31 #include "debug.h"
32
33 #include "buffer.h"
34 #include "window.h"
35 #include "frame.h"
36 #include "device.h"
37 #include "glyphs.h"
38 #include "redisplay.h"
39 #include "faces.h"
40
41 #include "sysdep.h"
42
43 static int compare_runes (struct window *w, struct rune *crb,
44                           struct rune *drb);
45 static void redraw_cursor_in_window (struct window *w,
46                                      int run_end_begin_glyphs);
47
48 /*****************************************************************************
49  sync_rune_structs
50
51  Synchronize the given rune blocks.
52  ****************************************************************************/
53 static void
54 sync_rune_structs (struct window *w, rune_dynarr *cra, rune_dynarr *dra)
55 {
56   int rune_elt;
57   int max_move = ((Dynarr_length (dra) > Dynarr_largest (cra))
58                   ? Dynarr_largest (cra)
59                   : Dynarr_length (dra));
60
61   if (max_move)
62     {
63       /* #### Doing this directly breaks the encapsulation.  But, the
64          running time of this function has a measurable impact on
65          redisplay performance so avoiding all excess overhead is a
66          good thing.  Is all of this true? */
67       memcpy (cra->base, dra->base, sizeof (struct rune) * max_move);
68       Dynarr_set_size (cra, max_move);
69     }
70   else
71     Dynarr_reset (cra);
72
73   for (rune_elt = max_move; rune_elt < Dynarr_length (dra); rune_elt++)
74     {
75       struct rune rb, *crb;
76       struct rune *drb = Dynarr_atp (dra, rune_elt);
77
78       crb = &rb;
79       memcpy (crb, drb, sizeof (struct rune));
80       Dynarr_add (cra, *crb);
81     }
82 }
83
84 /*****************************************************************************
85  sync_display_line_structs
86
87  For the given LINE in window W, make the current display line equal
88  the desired display line.
89  ****************************************************************************/
90 static void
91 sync_display_line_structs (struct window *w, int line, int do_blocks,
92                            display_line_dynarr *cdla,
93                            display_line_dynarr *ddla)
94 {
95   int cdla_len = Dynarr_length (cdla);
96
97   struct display_line dl, *clp, *dlp;
98   int db_elt;
99
100   dlp = Dynarr_atp (ddla, line);
101   if (line >= Dynarr_largest (cdla))
102     {
103       clp = &dl;
104       clp->display_blocks = Dynarr_new (display_block);
105     }
106   else
107     {
108       clp = Dynarr_atp (cdla, line);
109       if (clp->display_blocks)
110         Dynarr_reset (clp->display_blocks);
111       if (clp->left_glyphs)
112         {
113           Dynarr_free (clp->left_glyphs);
114           clp->left_glyphs = 0;
115         }
116       if (clp->right_glyphs)
117         {
118           Dynarr_free (clp->right_glyphs);
119           clp->right_glyphs = 0;
120         }
121     }
122   {
123     display_block_dynarr *tdb = clp->display_blocks;
124
125     memcpy (clp, dlp, sizeof (struct display_line));
126     clp->display_blocks = tdb;
127     clp->left_glyphs = 0;
128     clp->right_glyphs = 0;
129   }
130
131   if (!do_blocks && line >= cdla_len)
132     {
133       Dynarr_add (cdla, *clp);
134       return;
135     }
136
137   for (db_elt = 0; db_elt < Dynarr_length (dlp->display_blocks); db_elt++)
138     {
139       struct display_block db, *cdb;
140       struct display_block *ddb = Dynarr_atp (dlp->display_blocks, db_elt);
141
142       if (db_elt >= Dynarr_largest (clp->display_blocks))
143         {
144           cdb = &db;
145           memcpy (cdb, ddb, sizeof (struct display_block));
146           cdb->runes = Dynarr_new (rune);
147           Dynarr_add (clp->display_blocks, *cdb);
148         }
149       else
150         {
151           rune_dynarr *tr;
152
153           cdb = Dynarr_atp (clp->display_blocks, db_elt);
154           tr = cdb->runes;
155           memcpy (cdb, ddb, sizeof (struct display_block));
156           cdb->runes = tr;
157           Dynarr_increment (clp->display_blocks);
158         }
159
160       sync_rune_structs (w, cdb->runes, ddb->runes);
161     }
162
163   if (line >= cdla_len)
164     Dynarr_add (cdla, *clp);
165 }
166
167 /*****************************************************************************
168  compare_runes
169
170  Compare to runes to see if each of their fields is equal.  If so,
171  return true otherwise return false.
172  ****************************************************************************/
173 static int
174 compare_runes (struct window *w, struct rune *crb, struct rune *drb)
175 {
176   /* Do not compare the values of bufpos and endpos.  They do not
177      affect the display characteristics. */
178
179   if ((crb->findex != drb->findex) ||
180       (WINDOW_FACE_CACHEL_DIRTY (w, drb->findex)))
181     return 0;
182   else if (crb->xpos != drb->xpos)
183     return 0;
184   else if (crb->width != drb->width)
185     return 0;
186   else if (crb->cursor_type != drb->cursor_type)
187     return 0;
188   else if (crb->type != drb->type)
189     return 0;
190   else if (crb->type == RUNE_CHAR &&
191            (crb->object.chr.ch != drb->object.chr.ch))
192     return 0;
193   else if (crb->type == RUNE_DGLYPH &&
194            (!EQ (crb->object.dglyph.glyph, drb->object.dglyph.glyph) ||
195             !EQ (crb->object.dglyph.extent, drb->object.dglyph.extent) ||
196             crb->object.dglyph.xoffset != drb->object.dglyph.xoffset))
197     return 0;
198   else if (crb->type == RUNE_HLINE &&
199            (crb->object.hline.thickness != drb->object.hline.thickness ||
200             crb->object.hline.yoffset != drb->object.hline.yoffset))
201     return 0;
202   else
203     return 1;
204 }
205
206 /*****************************************************************************
207  get_next_display_block
208
209  Return the next display starting at or overlapping START_POS.  Return
210  the start of the next region in NEXT_START.
211  ****************************************************************************/
212 int
213 get_next_display_block (layout_bounds bounds, display_block_dynarr *dba,
214                         int start_pos, int *next_start)
215 {
216   int next_display_block = NO_BLOCK;
217   int priority = -1;
218   int block;
219
220   /* If we don't find a display block covering or starting at
221      start_pos, then we return the starting point of the next display
222      block or the next division boundary, whichever is closer to
223      start_pos. */
224   if (next_start)
225     {
226       if (start_pos >= bounds.left_out && start_pos < bounds.left_in)
227         *next_start = bounds.left_in;
228       else if (start_pos < bounds.left_white)
229         *next_start = bounds.left_white;
230       else if (start_pos < bounds.right_white)
231         *next_start = bounds.right_white;
232       else if (start_pos < bounds.right_in)
233         *next_start = bounds.right_in;
234       else if (start_pos <= bounds.right_out)
235         *next_start = bounds.right_out;
236       else
237         abort ();
238     }
239
240   for (block = 0; block < Dynarr_length (dba); block++)
241     {
242       struct display_block *db = Dynarr_atp (dba, block);
243
244       if (db->start_pos <= start_pos && db->end_pos > start_pos)
245         {
246           if ((int) db->type > priority)
247             {
248               priority = db->type;
249               next_display_block = block;
250               if (next_start)
251                 *next_start = db->end_pos;
252             }
253         }
254       else if (next_start && db->start_pos > start_pos)
255         {
256           if (db->start_pos < *next_start)
257             *next_start = db->start_pos;
258         }
259     }
260
261   return next_display_block;
262 }
263
264 /*****************************************************************************
265  get_cursor_size_and_location
266
267  Return the information defining the pixel location of the cursor.
268  ****************************************************************************/
269 static void
270 get_cursor_size_and_location (struct window *w, struct display_block *db,
271                               int cursor_location,
272                               int *cursor_start, int *cursor_width,
273                               int *cursor_height)
274 {
275   struct rune *rb;
276   Lisp_Object window;
277   int defheight, defwidth;
278
279   if (Dynarr_length (db->runes) <= cursor_location)
280     abort ();
281
282   XSETWINDOW (window, w);
283
284   rb = Dynarr_atp (db->runes, cursor_location);
285   *cursor_start = rb->xpos;
286
287   default_face_height_and_width (window, &defheight, &defwidth);
288   *cursor_height = defheight;
289
290   if (rb->type == RUNE_BLANK)
291     *cursor_width = defwidth;
292   else
293     *cursor_width = rb->width;
294 }
295
296 /*****************************************************************************
297  compare_display_blocks
298
299  Given two display blocks, output only those areas where they differ.
300  ****************************************************************************/
301 static int
302 compare_display_blocks (struct window *w, struct display_line *cdl,
303                         struct display_line *ddl, int c_block, int d_block,
304                         int start_pixpos, int cursor_start, int cursor_width,
305                         int cursor_height)
306 {
307   struct frame *f = XFRAME (w->frame);
308   struct device *d = XDEVICE (f->device);
309
310   struct display_block *cdb, *ddb;
311   int start_pos;
312   int stop_pos;
313   int force = 0;
314   int block_end;
315
316   cdb = Dynarr_atp (cdl->display_blocks, c_block);
317   ddb = Dynarr_atp (ddl->display_blocks, d_block);
318
319   assert (cdb->type == ddb->type);
320
321   start_pos = -1;
322   stop_pos = min (Dynarr_length (cdb->runes), Dynarr_length (ddb->runes));
323
324   block_end =
325     (!Dynarr_length (ddb->runes)
326      ? 0
327      : (Dynarr_atp (ddb->runes, Dynarr_length (ddb->runes) - 1)->xpos +
328         Dynarr_atp (ddb->runes, Dynarr_length (ddb->runes) - 1)->width));
329
330   /* If the new block type is not text and the cursor status is
331      changing and it overlaps the position of this block then force a
332      full redraw of the block in order to make sure that the cursor is
333      updated properly. */
334   if (ddb->type != TEXT
335 #if 0
336       /* I'm not sure exactly what this code wants to do, but it's
337        * not right--it doesn't update when cursor_elt changes from, e.g.,
338        * 0 to 8, and the new or old cursor loc overlaps this block.
339        * I've replaced it with the more conservative test below.
340        * -dkindred@cs.cmu.edu 23-Mar-1997 */
341       && ((cdl->cursor_elt == -1 && ddl->cursor_elt != -1)
342           || (cdl->cursor_elt != -1 && ddl->cursor_elt == -1))
343       && (ddl->cursor_elt == -1 ||
344           (cursor_start
345            && cursor_width
346            && (cursor_start + cursor_width) >= start_pixpos
347            && cursor_start <= block_end))
348 #else
349       && (cdl->cursor_elt != ddl->cursor_elt)
350 #endif
351       )
352     force = 1;
353
354   if (f->windows_structure_changed ||
355       f->faces_changed ||
356       f->glyphs_changed ||
357       cdl->ypos != ddl->ypos ||
358       cdl->ascent != ddl->ascent ||
359       cdl->descent != ddl->descent ||
360       cdl->clip != ddl->clip ||
361       force)
362     {
363       start_pos = 0;
364       force = 1;
365     }
366   else
367     {
368       int elt = 0;
369
370       while (start_pos < 0 && elt < stop_pos)
371         {
372           if (!compare_runes (w, Dynarr_atp (cdb->runes, elt),
373                               Dynarr_atp (ddb->runes, elt)))
374             {
375               start_pos = elt;
376             }
377           else
378             {
379               elt++;
380             }
381         }
382
383       /* If nothing has changed in the area where the blocks overlap, but
384          there are new blocks in the desired block, then adjust the start
385          point accordingly. */
386       if (elt == stop_pos && stop_pos < Dynarr_length (ddb->runes))
387         start_pos = stop_pos;
388     }
389
390   if (start_pos >= 0)
391     {
392       if ((Dynarr_length (ddb->runes) != Dynarr_length (cdb->runes))
393           || force)
394         {
395           stop_pos = Dynarr_length (ddb->runes);
396         }
397       else
398         {
399           /* If the lines have the same number of runes and we are not
400              forcing a full redraw because the display line has
401              changed position then we try and optimize how much of the
402              line we actually redraw by scanning backwards from the
403              end for the first changed rune.  This optimization is
404              almost always triggered by face changes. */
405
406           int elt = Dynarr_length (ddb->runes) - 1;
407
408           while (elt > start_pos)
409             {
410               if (!compare_runes (w, Dynarr_atp (cdb->runes, elt),
411                                   Dynarr_atp (ddb->runes, elt)))
412                 break;
413               else
414                 elt--;
415             }
416           stop_pos = elt + 1;
417         }
418
419       DEVMETH (d, output_display_block, (w, ddl, d_block, start_pos,
420                                          stop_pos, start_pixpos,
421                                          cursor_start, cursor_width,
422                                          cursor_height));
423       return 1;
424     }
425
426   return 0;
427 }
428
429 /*****************************************************************************
430  clear_left_border
431
432  Clear the lefthand outside border.
433  ****************************************************************************/
434 static void
435 clear_left_border (struct window *w, int y, int height)
436 {
437   struct frame *f = XFRAME (w->frame);
438   struct device *d = XDEVICE (f->device);
439   Lisp_Object window;
440
441   XSETWINDOW (window, w);
442   DEVMETH (d, clear_region, (window, DEFAULT_INDEX,
443                              FRAME_LEFT_BORDER_START (f), y,
444                              FRAME_BORDER_WIDTH (f), height));
445 }
446
447 /*****************************************************************************
448  clear_right_border
449
450  Clear the righthand outside border.
451  ****************************************************************************/
452 static void
453 clear_right_border (struct window *w, int y, int height)
454 {
455   struct frame *f = XFRAME (w->frame);
456   struct device *d = XDEVICE (f->device);
457   Lisp_Object window;
458
459   XSETWINDOW (window, w);
460   DEVMETH (d, clear_region, (window, DEFAULT_INDEX,
461                              FRAME_RIGHT_BORDER_START (f),
462                              y, FRAME_BORDER_WIDTH (f), height));
463 }
464
465 /*****************************************************************************
466  output_display_line
467
468  Ensure that the contents of the given display line is correct
469  on-screen.  The force_ parameters are used by redisplay_move_cursor
470  to correctly update cursor locations and only cursor locations.
471  ****************************************************************************/
472 void
473 output_display_line (struct window *w, display_line_dynarr *cdla,
474                      display_line_dynarr *ddla, int line, int force_start,
475                      int force_end)
476
477 {
478   struct frame *f = XFRAME (w->frame);
479   struct device *d = XDEVICE (f->device);
480   struct buffer *b = XBUFFER (w->buffer);
481   struct buffer *old_b = window_display_buffer (w);
482   struct display_line *cdl, *ddl;
483   display_block_dynarr *cdba, *ddba;
484   int start_pixpos, end_pixpos;
485   int cursor_start, cursor_width, cursor_height;
486
487   int force = (force_start >= 0 || force_end >= 0);
488   int clear_border = 0;
489   int must_sync = 0;
490
491   if (cdla && line < Dynarr_length (cdla))
492     {
493       cdl = Dynarr_atp (cdla, line);
494       cdba = cdl->display_blocks;
495     }
496   else
497     {
498       cdl = NULL;
499       cdba = NULL;
500     }
501
502   ddl = Dynarr_atp (ddla, line);      /* assert line < Dynarr_length (ddla) */
503   ddba = ddl->display_blocks;
504
505   if (force_start >= 0 && force_start >= ddl->bounds.left_out)
506     start_pixpos = force_start;
507   else
508     start_pixpos = ddl->bounds.left_out;
509
510   if (force_end >= 0 && force_end < ddl->bounds.right_out)
511     end_pixpos = force_end;
512   else
513     end_pixpos = ddl->bounds.right_out;
514
515   /* Get the cursor parameters. */
516   if (ddl->cursor_elt != -1)
517     {
518       struct display_block *db;
519
520       /* If the lines cursor parameter is not -1 then it indicates
521          which rune in the TEXT block contains the cursor.  This means
522          that there must be at least one display block.  The TEXT
523          block, if present, must always be the first display block. */
524       assert (Dynarr_length (ddba) != 0);
525
526       db = Dynarr_atp (ddba, 0);
527       assert (db->type == TEXT);
528
529       get_cursor_size_and_location (w, db, ddl->cursor_elt, &cursor_start,
530                                     &cursor_width, &cursor_height);
531     }
532   else
533     {
534       cursor_start = cursor_width = cursor_height = 0;
535     }
536
537   /* The modeline should only have a single block and it had better be
538      a TEXT block. */
539   if (ddl->modeline)
540     {
541       /* The shadow thickness check is necesssary if only the sign of
542          the size changed. */
543       if (cdba && !w->shadow_thickness_changed)
544         {
545           must_sync |= compare_display_blocks (w, cdl, ddl, 0, 0,
546                                                start_pixpos, 0, 0, 0);
547         }
548       else
549         {
550           DEVMETH (d, output_display_block, (w, ddl, 0, 0, -1, start_pixpos,
551                                              0, 0, 0));
552           must_sync = 1;
553         }
554
555       if (must_sync)
556         clear_border = 1;
557     }
558
559   while (!ddl->modeline && start_pixpos < end_pixpos)
560     {
561       int block;
562       int next_start_pixpos;
563
564       block = get_next_display_block (ddl->bounds, ddba, start_pixpos,
565                                       &next_start_pixpos);
566
567       /* If we didn't find a block then we should blank the area
568          between start_pos and next_start if necessary. */
569       if (block == NO_BLOCK)
570         {
571           /* We only erase those areas which were actually previously
572              covered by a display block unless the window structure
573              changed.  In that case we clear all areas since the current
574              structures may actually represent a different buffer. */
575           while (start_pixpos < next_start_pixpos)
576             {
577               int block_end;
578               int old_block;
579
580               if (cdba)
581                 old_block = get_next_display_block (ddl->bounds, cdba,
582                                                     start_pixpos, &block_end);
583               else
584                 {
585                   old_block = NO_BLOCK;
586                   block_end = next_start_pixpos;
587                 }
588
589               if (!cdba || old_block != NO_BLOCK || b != old_b ||
590                   f->windows_structure_changed ||
591                   f->faces_changed ||
592                   force ||
593                   (cdl && (cdl->ypos != ddl->ypos ||
594                            cdl->ascent != ddl->ascent ||
595                            cdl->descent != ddl->descent ||
596                            cdl->clip != ddl->clip)))
597                 {
598                   int x, y, width, height;
599                   Lisp_Object face;
600
601                   must_sync = 1;
602                   x = start_pixpos;
603                   y = ddl->ypos - ddl->ascent;
604                   width = min (next_start_pixpos, block_end) - x;
605                   height = ddl->ascent + ddl->descent - ddl->clip;
606
607                   if (x < ddl->bounds.left_in)
608                     face = Vleft_margin_face;
609                   else if (x < ddl->bounds.right_in)
610                     face = Vdefault_face;
611                   else if (x < ddl->bounds.right_out)
612                     face = Vright_margin_face;
613                   else
614                     face = Qnil;
615
616                   if (!NILP (face))
617                     {
618                       Lisp_Object window;
619
620                       XSETWINDOW (window, w);
621
622                       /* Clear the empty area. */
623                       DEVMETH (d, clear_region,
624                                (window, get_builtin_face_cache_index (w,
625                                                                       face),
626                                 x, y, width, height));
627
628                       /* Mark that we should clear the border.  This is
629                          necessary because italic fonts may leave
630                          droppings in the border. */
631                       clear_border = 1;
632                     }
633                 }
634
635               start_pixpos = min (next_start_pixpos, block_end);
636             }
637         }
638       else
639         {
640           struct display_block *cdb, *ddb;
641           int block_end;
642           int old_block;
643
644           if (cdba)
645             old_block = get_next_display_block (ddl->bounds, cdba,
646                                                 start_pixpos, &block_end);
647           else
648             old_block = NO_BLOCK;
649
650           ddb = Dynarr_atp (ddba, block);
651           cdb = (old_block != NO_BLOCK ? Dynarr_atp (cdba, old_block) : 0);
652
653           /* If there was formerly no block over the current
654              region or if it was a block of a different type, then
655              output the entire ddb.  Otherwise, compare cdb and
656              ddb and output only the changed region. */
657           if (!force && cdb && ddb->type == cdb->type && b == old_b)
658             {
659               must_sync |= compare_display_blocks (w, cdl, ddl, old_block,
660                                                    block, start_pixpos,
661                                                    cursor_start, cursor_width,
662                                                    cursor_height);
663             }
664           else
665             {
666               int elt;
667               int first_elt = 0;
668               int last_elt = -1;
669
670               for (elt = 0; elt < Dynarr_length (ddb->runes); elt++)
671                 {
672                   struct rune *rb = Dynarr_atp (ddb->runes, elt);
673
674                   if (start_pixpos >= rb->xpos
675                       && start_pixpos < rb->xpos + rb->width)
676                     first_elt = elt;
677
678                   if (end_pixpos > rb->xpos
679                       && end_pixpos <= rb->xpos + rb->width)
680                     {
681                       last_elt = elt + 1;
682                       if (last_elt > Dynarr_length (ddb->runes))
683                         last_elt = Dynarr_length (ddb->runes);
684                       break;
685                     }
686                 }
687
688               must_sync = 1;
689               DEVMETH (d, output_display_block, (w, ddl, block, first_elt,
690                                                  last_elt,
691                                                  start_pixpos,
692                                                  cursor_start, cursor_width,
693                                                  cursor_height));
694             }
695
696           start_pixpos = next_start_pixpos;
697         }
698     }
699
700   /* Clear the internal border if we are next to it and the window
701      structure or frame size has changed or if something caused
702      clear_border to be tripped.  */
703   /* #### Doing this on f->clear sucks but is necessary because of
704      window-local background values. */
705   if (f->windows_structure_changed || f->faces_changed || clear_border
706       || f->clear)
707     {
708       int y = ddl->ypos - ddl->ascent;
709       int height = ddl->ascent + ddl->descent - ddl->clip;
710
711       if (ddl->modeline)
712         {
713           y -= MODELINE_SHADOW_THICKNESS (w);
714           height += (2 * MODELINE_SHADOW_THICKNESS (w));
715         }
716
717       if (window_is_leftmost (w))
718         clear_left_border (w, y, height);
719       if (window_is_rightmost (w))
720         clear_right_border (w, y, height);
721     }
722
723   if (cdla)
724     sync_display_line_structs (w, line, must_sync, cdla, ddla);
725 }
726
727 /*****************************************************************************
728  redisplay_move_cursor
729
730  For the given window W, move the cursor to NEW_POINT.  Returns a
731  boolean indicating success or failure.
732  ****************************************************************************/
733
734 #define ADJ_BUFPOS (rb->bufpos + dl->offset)
735 #define ADJ_ENDPOS (rb->endpos + dl->offset)
736
737 int
738 redisplay_move_cursor (struct window *w, Bufpos new_point, int no_output_end)
739 {
740   struct frame *f = XFRAME (w->frame);
741   struct device *d = XDEVICE (f->device);
742
743   display_line_dynarr *cla = window_display_lines (w, CURRENT_DISP);
744   struct display_line *dl;
745   struct display_block *db;
746   struct rune *rb;
747   int x = w->last_point_x[CURRENT_DISP];
748   int y = w->last_point_y[CURRENT_DISP];
749
750   /*
751    * Bail if cursor_in_echo_area is non-zero and we're fiddling with
752    * the cursor in a non-active minibuffer window, since that is a
753    * special case that is handled elsewhere and this function need
754    * not handle it.  Return 1 so the caller will assume we
755    * succeeded.
756    */
757   if (cursor_in_echo_area && MINI_WINDOW_P (w) &&
758       w != XWINDOW (FRAME_SELECTED_WINDOW (f)))
759     return 1;
760
761   if (y < 0 || y >= Dynarr_length (cla))
762     return 0;
763
764   dl = Dynarr_atp (cla, y);
765   db = get_display_block_from_line (dl, TEXT);
766
767   if (x < 0 || x >= Dynarr_length (db->runes))
768     return 0;
769
770   rb = Dynarr_atp (db->runes, x);
771
772   if (rb->cursor_type == CURSOR_OFF)
773     return 0;
774   else if (ADJ_BUFPOS == new_point
775            || (ADJ_ENDPOS && (new_point >= ADJ_BUFPOS)
776                && (new_point <= ADJ_ENDPOS)))
777     {
778       w->last_point_x[CURRENT_DISP] = x;
779       w->last_point_y[CURRENT_DISP] = y;
780       Fset_marker (w->last_point[CURRENT_DISP], make_int (ADJ_BUFPOS),
781                    w->buffer);
782       dl->cursor_elt = x;
783       return 1;
784     }
785   else
786     {
787       DEVMETH (d, output_begin, (d));
788
789       /* #### This is a gross kludge.  Cursor handling is such a royal
790          pain in the ass. */
791       if (rb->type == RUNE_DGLYPH &&
792           (EQ (rb->object.dglyph.glyph, Vtruncation_glyph) ||
793            EQ (rb->object.dglyph.glyph, Vcontinuation_glyph)))
794         rb->cursor_type = NO_CURSOR;
795       else
796         rb->cursor_type = CURSOR_OFF;
797       dl->cursor_elt = -1;
798       output_display_line (w, 0, cla, y, rb->xpos, rb->xpos + rb->width);
799     }
800
801   w->last_point_x[CURRENT_DISP] = -1;
802   w->last_point_y[CURRENT_DISP] = -1;
803   Fset_marker (w->last_point[CURRENT_DISP], Qnil, w->buffer);
804
805   /* If this isn't the selected frame, then erasing the old cursor is
806      all we actually had to do. */
807   if (w != XWINDOW (FRAME_SELECTED_WINDOW (device_selected_frame (d))))
808     {
809       if (!no_output_end)
810         DEVMETH (d, output_end, (d));
811
812       return 1;
813     }
814
815   /* This should only occur in the minibuffer. */
816   if (new_point == 0)
817     {
818       w->last_point_x[CURRENT_DISP] = 0;
819       w->last_point_y[CURRENT_DISP] = y;
820       Fset_marker (w->last_point[CURRENT_DISP], Qzero, w->buffer);
821
822       rb = Dynarr_atp (db->runes, 0);
823       rb->cursor_type = CURSOR_ON;
824       dl->cursor_elt = 0;
825
826       output_display_line (w, 0, cla, y, rb->xpos, rb->xpos + rb->width);
827
828       if (!no_output_end)
829         DEVMETH (d, output_end, (d));
830       return 1;
831     }
832   else
833     {
834       int cur_rb = 0;
835       int first = 0;
836       int cur_dl, up;
837
838       if (ADJ_BUFPOS < new_point)
839         {
840           up = 1;
841           cur_rb = x + 1;
842           cur_dl = y;
843         }
844       else /* (rb->bufpos + dl->offset) > new_point */
845         {
846           up = 0;
847
848           if (!x)
849             {
850               cur_dl = y - 1;
851               first = 0;
852             }
853           else
854             {
855               cur_rb = x - 1;
856               cur_dl = y;
857               first = 1;
858             }
859         }
860
861       while ((up ? (cur_dl < Dynarr_length (cla)) : (cur_dl >= 0)))
862         {
863           dl = Dynarr_atp (cla, cur_dl);
864           db = get_display_block_from_line (dl, TEXT);
865
866           if (!up && !first)
867             cur_rb = Dynarr_length (db->runes) - 1;
868
869           while ((!scroll_on_clipped_lines || !dl->clip) &&
870                  (up ? (cur_rb < Dynarr_length (db->runes)) : (cur_rb >= 0)))
871             {
872               rb = Dynarr_atp (db->runes, cur_rb);
873
874               if (rb->cursor_type != IGNORE_CURSOR
875                   && rb->cursor_type != NO_CURSOR &&
876                   (ADJ_BUFPOS == new_point
877                    || (ADJ_ENDPOS && (new_point >= ADJ_BUFPOS)
878                        && (new_point <= ADJ_BUFPOS))))
879                 {
880                   rb->cursor_type = CURSOR_ON;
881                   dl->cursor_elt = cur_rb;
882
883
884                   output_display_line (w, 0, cla, cur_dl, rb->xpos,
885                                        rb->xpos + rb->width);
886
887                   w->last_point_x[CURRENT_DISP] = cur_rb;
888                   w->last_point_y[CURRENT_DISP] = cur_dl;
889                   Fset_marker (w->last_point[CURRENT_DISP],
890                                make_int (ADJ_BUFPOS), w->buffer);
891
892                   if (!no_output_end)
893                     DEVMETH (d, output_end, (d));
894                   return 1;
895                 }
896
897               (up ? cur_rb++ : cur_rb--);
898             }
899
900           (up ? (cur_rb = 0) : (first = 0));
901           (up ? cur_dl++ : cur_dl--);
902         }
903     }
904
905   if (!no_output_end)
906     DEVMETH (d, output_end, (d));
907   return 0;
908 }
909 #undef ADJ_BUFPOS
910 #undef ADJ_ENDPOS
911
912 /*****************************************************************************
913  redraw_cursor_in_window
914
915  For the given window W, redraw the cursor if it is contained within
916  the window.
917  ****************************************************************************/
918 static void
919 redraw_cursor_in_window (struct window *w, int run_end_begin_meths)
920 {
921   struct frame *f = XFRAME (w->frame);
922   struct device *d = XDEVICE (f->device);
923
924   display_line_dynarr *dla = window_display_lines (w, CURRENT_DISP);
925   struct display_line *dl;
926   struct display_block *db;
927   struct rune *rb;
928
929   int x = w->last_point_x[CURRENT_DISP];
930   int y = w->last_point_y[CURRENT_DISP];
931
932   if (cursor_in_echo_area && MINI_WINDOW_P (w) &&
933       !echo_area_active (f) && minibuf_level == 0)
934     {
935       MAYBE_DEVMETH (d, set_final_cursor_coords, (f, w->pixel_top, 0));
936     }
937
938   if (y < 0 || y >= Dynarr_length (dla))
939     return;
940
941   if (MINI_WINDOW_P (w) && f != device_selected_frame (d) &&
942       !is_surrogate_for_selected_frame (f))
943     return;
944
945   dl = Dynarr_atp (dla, y);
946   db = get_display_block_from_line (dl, TEXT);
947
948   if (x < 0 || x >= Dynarr_length (db->runes))
949     return;
950
951   rb = Dynarr_atp (db->runes, x);
952
953   /* Don't call the output routine if the block isn't actually the
954      cursor. */
955   if (rb->cursor_type == CURSOR_ON)
956     {
957       MAYBE_DEVMETH (d, set_final_cursor_coords,
958                      (f, dl->ypos - 1, rb->xpos));
959
960       if (run_end_begin_meths)
961         DEVMETH (d, output_begin, (d));
962
963       output_display_line (w, 0, dla, y, rb->xpos, rb->xpos + rb->width);
964
965       if (run_end_begin_meths)
966         DEVMETH (d, output_end, (d));
967     }
968 }
969
970 /*****************************************************************************
971  redisplay_redraw_cursor
972
973  For the given frame F, redraw the cursor on the selected window.
974  This is used to update the cursor after focus changes.
975  ****************************************************************************/
976 void
977 redisplay_redraw_cursor (struct frame *f, int run_end_begin_meths)
978 {
979   Lisp_Object window;
980
981   if (!cursor_in_echo_area)
982     window = FRAME_SELECTED_WINDOW (f);
983   else if (FRAME_HAS_MINIBUF_P (f))
984     window = FRAME_MINIBUF_WINDOW (f);
985   else
986     return;
987
988   redraw_cursor_in_window (XWINDOW (window), run_end_begin_meths);
989 }
990
991 /*****************************************************************************
992  redisplay_clear_top_of_window
993
994  If window is topmost, clear the internal border above it.
995  ****************************************************************************/
996 static void
997 redisplay_clear_top_of_window (struct window *w)
998 {
999   Lisp_Object window;
1000   XSETWINDOW (window, w);
1001
1002   if (!NILP (Fwindow_highest_p (window)))
1003     {
1004       struct frame *f = XFRAME (w->frame);
1005       struct device *d = XDEVICE (f->device);
1006       int x, y, width, height;
1007
1008       x = w->pixel_left;
1009       width = w->pixel_width;
1010
1011       if (window_is_leftmost (w))
1012         {
1013           x -= FRAME_BORDER_WIDTH (f);
1014           width += FRAME_BORDER_WIDTH (f);
1015         }
1016       if (window_is_rightmost (w))
1017         width += FRAME_BORDER_WIDTH (f);
1018
1019       y = FRAME_TOP_BORDER_START (f) - 1;
1020       height = FRAME_BORDER_HEIGHT (f) + 1;
1021
1022       DEVMETH (d, clear_region, (window, DEFAULT_INDEX, x, y, width, height));
1023     }
1024 }
1025
1026 /*****************************************************************************
1027  redisplay_clear_bottom_of_window
1028
1029  Clear window from right below the last display line to right above
1030  the modeline.  The calling function can limit the area actually
1031  erased by setting min_start and/or max_end to positive values.
1032  ****************************************************************************/
1033 void
1034 redisplay_clear_bottom_of_window (struct window *w, display_line_dynarr *ddla,
1035                                   int min_start, int max_end)
1036 {
1037   struct frame *f = XFRAME (w->frame);
1038   struct device *d = XDEVICE (f->device);
1039   int ypos1, ypos2;
1040   int ddla_len = Dynarr_length (ddla);
1041
1042   ypos2 = WINDOW_TEXT_BOTTOM (w);
1043 #ifdef HAVE_SCROLLBARS
1044   /* This adjustment is to catch the intersection of any scrollbars. */
1045   if (f->windows_structure_changed && NILP (w->scrollbar_on_top_p))
1046     ypos2 += window_scrollbar_height (w);
1047 #endif
1048
1049   if (ddla_len)
1050     {
1051       if (ddla_len == 1 && Dynarr_atp (ddla, 0)->modeline)
1052         {
1053           ypos1 = WINDOW_TEXT_TOP (w);
1054 #ifdef HAVE_SCROLLBARS
1055           /* This adjustment is to catch the intersection of any scrollbars. */
1056           if (f->windows_structure_changed && !NILP (w->scrollbar_on_top_p))
1057             ypos1 -= window_scrollbar_height (w);
1058 #endif
1059         }
1060       else
1061         {
1062           struct display_line *dl = Dynarr_atp (ddla, ddla_len - 1);
1063           ypos1 = dl->ypos + dl->descent - dl->clip;
1064         }
1065     }
1066   else
1067     ypos1 = WINDOW_TEXT_TOP (w);
1068
1069   /* #### See if this can be made conditional on the frame
1070      changing size. */
1071   if (MINI_WINDOW_P (w))
1072     ypos2 += FRAME_BORDER_HEIGHT (f);
1073
1074   if (min_start >= 0 && ypos1 < min_start)
1075     ypos1 = min_start;
1076   if (max_end >= 0 && ypos2 > max_end)
1077     ypos2 = max_end;
1078
1079   if (ypos2 <= ypos1)
1080     return;
1081
1082   DEVMETH (d, clear_to_window_end, (w, ypos1, ypos2));
1083 }
1084
1085 /*****************************************************************************
1086  redisplay_update_line
1087
1088  This is used during incremental updates to update a single line and
1089  correct the offsets on all lines below it.  At the moment
1090  update_values is false if we are only updating the modeline.
1091  ****************************************************************************/
1092 void
1093 redisplay_update_line (struct window *w, int first_line, int last_line,
1094                        int update_values)
1095 {
1096   struct frame *f = XFRAME (w->frame);
1097   struct device *d = XDEVICE (f->device);
1098
1099   display_line_dynarr *cdla = window_display_lines (w, CURRENT_DISP);
1100   display_line_dynarr *ddla = window_display_lines (w, DESIRED_DISP);
1101
1102   DEVMETH (d, output_begin, (d));
1103
1104   while (first_line <= last_line)
1105     {
1106       Charcount old_len = (Dynarr_atp (cdla, first_line)->end_bufpos -
1107                            Dynarr_atp (cdla, first_line)->bufpos);
1108       Charcount new_len = (Dynarr_atp (ddla, first_line)->end_bufpos -
1109                            Dynarr_atp (ddla, first_line)->bufpos);
1110
1111       assert (Dynarr_length (cdla) == Dynarr_length (ddla));
1112
1113       /* Output the changes. */
1114       output_display_line (w, cdla, ddla, first_line, -1, -1);
1115
1116       /* Update the offsets. */
1117       if (update_values)
1118         {
1119           int cur_line = first_line + 1;
1120           while (cur_line < Dynarr_length (cdla))
1121             {
1122               Dynarr_atp (cdla, cur_line)->offset += (new_len - old_len);
1123               Dynarr_atp (ddla, cur_line)->offset += (new_len - old_len);
1124               cur_line++;
1125             }
1126         }
1127
1128       /* Update the window_end_pos and other settings. */
1129       if (update_values)
1130         {
1131           w->window_end_pos[CURRENT_DISP] -= (new_len - old_len);
1132
1133           if (Dynarr_atp (ddla, first_line)->cursor_elt != -1)
1134             {
1135               w->last_point_x[CURRENT_DISP] = w->last_point_x[DESIRED_DISP];
1136               w->last_point_y[CURRENT_DISP] = w->last_point_y[DESIRED_DISP];
1137             }
1138         }
1139
1140       first_line++;
1141     }
1142
1143   /* Update the window max line length.  We have to scan the entire
1144      set of display lines otherwise we might not detect if the max is
1145      supposed to shrink. */
1146   if (update_values)
1147     {
1148       int line = 0;
1149
1150       w->max_line_len = 0;
1151       while (line < Dynarr_length (ddla))
1152         {
1153           struct display_line *dl = Dynarr_atp (ddla, line);
1154
1155           if (!dl->modeline)
1156             w->max_line_len = max (dl->num_chars, w->max_line_len);
1157
1158           line++;
1159         }
1160     }
1161
1162   w->last_modified[CURRENT_DISP] = w->last_modified[DESIRED_DISP];
1163   w->last_facechange[CURRENT_DISP] = w->last_facechange[DESIRED_DISP];
1164   Fset_marker (w->last_point[CURRENT_DISP],
1165                Fmarker_position (w->last_point[DESIRED_DISP]), w->buffer);
1166   Fset_marker (w->last_start[CURRENT_DISP],
1167                Fmarker_position (w->last_start[DESIRED_DISP]), w->buffer);
1168
1169   /* We don't bother updating the vertical scrollbars here.  This
1170      gives us a performance increase while having minimal loss of
1171      quality to the scrollbar slider size and position since when this
1172      function is called we know that the changes to the buffer were
1173      very localized.  We have to update the horizontal scrollbars,
1174      though, because this routine could cause a change which has a
1175      larger impact on their sizing. */
1176   /* #### See if we can get away with only calling this if
1177      max_line_len is greater than the window_char_width. */
1178 #if defined(HAVE_SCROLLBARS) && defined(HAVE_X_WINDOWS)
1179   {
1180     extern int stupid_vertical_scrollbar_drag_hack;
1181
1182     update_window_scrollbars (w, NULL, 1, stupid_vertical_scrollbar_drag_hack);
1183     stupid_vertical_scrollbar_drag_hack = 1;
1184   }
1185 #endif
1186
1187   /* This has to be done after we've updated the values.  We don't
1188      call output_end for tty frames.  Redisplay will do this after all
1189      tty windows have been updated.  This cuts down on cursor
1190      flicker. */
1191   if (FRAME_TTY_P (f))
1192     redisplay_redraw_cursor (f, 0);
1193   else
1194     DEVMETH (d, output_end, (d));
1195 }
1196
1197 /*****************************************************************************
1198  redisplay_output_window
1199
1200  For the given window W, ensure that the current display lines are
1201  equal to the desired display lines, outputing changes as necessary.
1202
1203  #### Fuck me.  This just isn't going to cut it for tty's.  The output
1204  decisions for them must be based on the contents of the entire frame
1205  because that is how the available output capabilities think.  The
1206  solution is relatively simple.  Create redisplay_output_frame.  This
1207  will basically merge all of the separate window display structs into
1208  a single one for the frame.  This combination structure will be able
1209  to be passed to the same output_display_line which works for windows
1210  on X frames and the right things will happen.  It just takes time to
1211  do.
1212  ****************************************************************************/
1213 void
1214 redisplay_output_window (struct window *w)
1215 {
1216   struct frame *f = XFRAME (w->frame);
1217   struct device *d = XDEVICE (f->device);
1218
1219   display_line_dynarr *cdla = window_display_lines (w, CURRENT_DISP);
1220   display_line_dynarr *ddla = window_display_lines (w, DESIRED_DISP);
1221
1222   int cdla_len = Dynarr_length (cdla);
1223   int ddla_len = Dynarr_length (ddla);
1224
1225   int line;
1226   int need_to_clear_bottom = 0;
1227   int need_to_clear_start = -1;
1228   int need_to_clear_end = -1;
1229
1230   /* Backgrounds may have changed or windows may have gone away
1231      leaving dividers lying around. */
1232   if (f->faces_changed
1233       || f->windows_structure_changed
1234       || w->shadow_thickness_changed)
1235     need_to_clear_bottom = 1;
1236
1237   /* The first thing we do is determine if we are going to need to
1238      clear the bottom of the window.  We only need to do this if the
1239      bottom of the current display lines is below the bottom of the
1240      desired display lines.  Note that the number of lines is
1241      irrelevant.  Only the position matters.  We also clear to the
1242      bottom of the window if the modeline has shifted position. */
1243   /* #### We can't blindly not clear the bottom if f->clear is true
1244      since there might be a window-local background.  However, for
1245      those cases where there isn't, clearing the end of the window in
1246      this case sucks. */
1247   if (!need_to_clear_bottom)
1248     {
1249       struct display_line *cdl, *ddl;
1250
1251       /* If the modeline has changed position or size, clear the bottom
1252          of the window. */
1253       if (!need_to_clear_bottom)
1254         {
1255           cdl = ddl = 0;
1256
1257           if (cdla_len)
1258             cdl = Dynarr_atp (cdla, 0);
1259           if (ddla_len)
1260             ddl = Dynarr_atp (ddla, 0);
1261
1262           if (!cdl || !ddl)
1263             need_to_clear_bottom = 1;
1264           else if ((!cdl->modeline && ddl->modeline)
1265                    || (cdl->modeline && !ddl->modeline))
1266             need_to_clear_bottom = 1;
1267           else if (cdl->ypos != ddl->ypos ||
1268                    cdl->ascent != ddl->ascent ||
1269                    cdl->descent != ddl->descent ||
1270                    cdl->clip != ddl->clip)
1271             need_to_clear_bottom = 1;
1272
1273           /* #### This kludge is to make sure the modeline shadows get
1274              redrawn if the modeline position shifts. */
1275           if (need_to_clear_bottom)
1276             w->shadow_thickness_changed = 1;
1277         }
1278
1279       if (!need_to_clear_bottom)
1280         {
1281           cdl = ddl = 0;
1282
1283           if (cdla_len)
1284             cdl = Dynarr_atp (cdla, cdla_len - 1);
1285           if (ddla_len)
1286             ddl = Dynarr_atp (ddla, ddla_len - 1);
1287
1288           if (!cdl || !ddl)
1289             need_to_clear_bottom = 1;
1290           else
1291             {
1292               int cdl_bottom, ddl_bottom;
1293
1294               cdl_bottom = cdl->ypos + cdl->descent;
1295               ddl_bottom = ddl->ypos + ddl->descent;
1296
1297               if (cdl_bottom > ddl_bottom)
1298                 {
1299                   need_to_clear_bottom = 1;
1300                   need_to_clear_start = ddl_bottom;
1301                   need_to_clear_end = cdl_bottom;
1302                 }
1303             }
1304         }
1305     }
1306
1307   /* Perform any output initialization. */
1308   DEVMETH (d, output_begin, (d));
1309
1310   /* If the window's structure has changed clear the internal border
1311      above it if it is topmost (the function will check). */
1312   if (f->windows_structure_changed)
1313     redisplay_clear_top_of_window (w);
1314
1315   /* Output each line. */
1316   for (line = 0; line < Dynarr_length (ddla); line++)
1317     {
1318       output_display_line (w, cdla, ddla, line, -1, -1);
1319     }
1320
1321   /* If the number of display lines has shrunk, adjust. */
1322   if (cdla_len > ddla_len)
1323     {
1324       Dynarr_length (cdla) = ddla_len;
1325     }
1326
1327   /* Output a vertical divider between windows, if necessary. */
1328   if (window_needs_vertical_divider (w)
1329       && (f->windows_structure_changed || f->clear))
1330     {
1331       DEVMETH (d, output_vertical_divider, (w, f->windows_structure_changed));
1332     }
1333
1334   /* Clear the rest of the window, if necessary. */
1335   if (need_to_clear_bottom)
1336     {
1337       redisplay_clear_bottom_of_window (w, ddla, need_to_clear_start,
1338                                         need_to_clear_end);
1339     }
1340
1341   w->window_end_pos[CURRENT_DISP] = w->window_end_pos[DESIRED_DISP];
1342   Fset_marker (w->start[CURRENT_DISP],
1343                make_int (marker_position (w->start[DESIRED_DISP])),
1344                w->buffer);
1345   Fset_marker (w->pointm[CURRENT_DISP],
1346                make_int (marker_position (w->pointm[DESIRED_DISP])),
1347                w->buffer);
1348   w->last_modified[CURRENT_DISP] = w->last_modified[DESIRED_DISP];
1349   w->last_facechange[CURRENT_DISP] = w->last_facechange[DESIRED_DISP];
1350   Fset_marker (w->last_start[CURRENT_DISP],
1351                Fmarker_position (w->last_start[DESIRED_DISP]), w->buffer);
1352   Fset_marker (w->last_point[CURRENT_DISP],
1353                Fmarker_position (w->last_point[DESIRED_DISP]), w->buffer);
1354   w->last_point_x[CURRENT_DISP] = w->last_point_x[DESIRED_DISP];
1355   w->last_point_y[CURRENT_DISP] = w->last_point_y[DESIRED_DISP];
1356   w->shadow_thickness_changed = 0;
1357
1358   set_window_display_buffer (w, XBUFFER (w->buffer));
1359   find_window_mirror (w)->truncate_win = window_truncation_on (w);
1360
1361   /* Overkill on invalidating the cache.  It is very bad for it to not
1362      get invalidated when it should be. */
1363   INVALIDATE_DEVICE_PIXEL_TO_GLYPH_CACHE (d);
1364
1365   /* We don't call output_end for tty frames.  Redisplay will do this
1366      after all tty windows have been updated.  This cuts down on
1367      cursor flicker. */
1368   if (FRAME_TTY_P (f))
1369     redisplay_redraw_cursor (f, 0);
1370   else
1371     DEVMETH (d, output_end, (d));
1372
1373 #ifdef HAVE_SCROLLBARS
1374   update_window_scrollbars (w, NULL, !MINI_WINDOW_P (w), 0);
1375 #endif
1376 }