1 /* X output and frame manipulation routines.
2 Copyright (C) 1994, 1995 Board of Trustees, University of Illinois.
3 Copyright (C) 1994 Lucid, Inc.
4 Copyright (C) 1995 Sun Microsystems, Inc.
6 This file is part of XEmacs.
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
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
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. */
23 /* Synched up with: Not in FSF. */
25 /* Author: Chuck Thompson */
27 /* Lots of work done by Ben Wing for Mule */
32 #include "console-x.h"
33 #include "EmacsFrame.h"
34 #include "EmacsFrameP.h"
37 #include "objects-x.h"
43 #include "redisplay.h"
46 #include <X11/bitmaps/gray>
48 #include "sysproc.h" /* for select() */
52 #include "file-coding.h" /* for CCL conversion */
55 /* Number of pixels below each line. */
56 /* #### implement me */
57 int x_interline_space;
59 #define EOL_CURSOR_WIDTH 5
61 static void x_output_pixmap (struct window *w, struct display_line *dl,
62 Lisp_Object image_instance, int xpos,
64 int start_pixpos, int width, face_index findex,
65 int cursor_start, int cursor_width,
67 static void x_output_vertical_divider (struct window *w, int clear);
68 static void x_output_blank (struct window *w, struct display_line *dl,
69 struct rune *rb, int start_pixpos,
70 int cursor_start, int cursor_width);
71 static void x_output_hline (struct window *w, struct display_line *dl,
73 static void x_redraw_exposed_window (struct window *w, int x, int y,
74 int width, int height);
75 static void x_redraw_exposed_windows (Lisp_Object window, int x, int y,
76 int width, int height);
77 static void x_clear_region (Lisp_Object window, face_index findex, int x,
78 int y, int width, int height);
79 static void x_output_eol_cursor (struct window *w, struct display_line *dl,
80 int xpos, face_index findex);
81 static void x_clear_frame (struct frame *f);
82 static void x_clear_frame_windows (Lisp_Object window);
83 static void x_bevel_modeline (struct window *w, struct display_line *dl);
86 /* Note: We do not use the Xmb*() functions and XFontSets.
87 Those functions are generally losing for a number of reasons:
89 1) They only support one locale (e.g. you could display
90 Japanese and ASCII text, but not mixed Japanese/Chinese
91 text). You could maybe call setlocale() frequently
92 to try to deal with this, but that would generally
93 fail because an XFontSet is tied to one locale and
94 won't have the other character sets in it.
95 2) Not all (or even very many) OS's support the useful
96 locales. For example, as far as I know SunOS and
97 Solaris only support the Japanese locale if you get the
98 special Asian-language version of the OS. Yuck yuck
99 yuck. Linux doesn't support the Japanese locale at
101 3) The locale support in X only exists in R5, not in R4.
102 (Not sure how big of a problem this is: how many
103 people are using R4?)
104 4) Who knows if the multi-byte text format (which is locale-
105 specific) is even the same for the same locale on
106 different OS's? It's not even documented anywhere that
107 I can find what the multi-byte text format for the
108 Japanese locale under SunOS and Solaris is, but I assume
120 /* Separate out the text in DYN into a series of textual runs of a
121 particular charset. Also convert the characters as necessary into
122 the format needed by XDrawImageString(), XDrawImageString16(), et
123 al. (This means converting to one or two byte format, possibly
124 tweaking the high bits, and possibly running a CCL program.) You
125 must pre-allocate the space used and pass it in. (This is done so
126 you can alloca() the space.) You need to allocate (2 * len) bytes
127 of TEXT_STORAGE and (len * sizeof (struct textual_run)) bytes of
128 RUN_STORAGE, where LEN is the length of the dynarr.
130 Returns the number of runs actually used. */
133 separate_textual_runs (unsigned char *text_storage,
134 struct textual_run *run_storage,
135 CONST Emchar *str, Charcount len)
137 Lisp_Object prev_charset = Qunbound; /* not Qnil because that is a
138 possible valid charset when
139 MULE is not defined */
143 struct ccl_program char_converter;
144 int need_ccl_conversion = 0;
147 for (i = 0; i < len; i++)
155 BREAKUP_CHAR (ch, charset, byte1, byte2);
156 dimension = XCHARSET_DIMENSION (charset);
157 graphic = XCHARSET_GRAPHIC (charset);
159 if (!EQ (charset, prev_charset))
161 run_storage[runs_so_far].ptr = text_storage;
162 run_storage[runs_so_far].charset = charset;
163 run_storage[runs_so_far].dimension = dimension;
167 run_storage[runs_so_far - 1].len =
168 text_storage - run_storage[runs_so_far - 1].ptr;
169 if (run_storage[runs_so_far - 1].dimension == 2)
170 run_storage[runs_so_far - 1].len >>= 1;
173 prev_charset = charset;
176 Lisp_Object ccl_prog = XCHARSET_CCL_PROGRAM (charset);
177 need_ccl_conversion = !NILP (ccl_prog);
178 if (need_ccl_conversion)
179 setup_ccl_program (&char_converter, ccl_prog);
189 else if (graphic == 1)
195 if (need_ccl_conversion)
197 char_converter.reg[0] = XCHARSET_ID (charset);
198 char_converter.reg[1] = byte1;
199 char_converter.reg[2] = byte2;
200 ccl_driver (&char_converter, 0, 0, 0, 0);
201 byte1 = char_converter.reg[1];
202 byte2 = char_converter.reg[2];
205 *text_storage++ = (unsigned char) byte1;
207 *text_storage++ = (unsigned char) byte2;
212 run_storage[runs_so_far - 1].len =
213 text_storage - run_storage[runs_so_far - 1].ptr;
214 if (run_storage[runs_so_far - 1].dimension == 2)
215 run_storage[runs_so_far - 1].len >>= 1;
221 /****************************************************************************/
223 /* X output routines */
225 /****************************************************************************/
228 x_text_width_single_run (struct face_cachel *cachel, struct textual_run *run)
230 Lisp_Object font_inst = FACE_CACHEL_FONT (cachel, run->charset);
231 struct Lisp_Font_Instance *fi = XFONT_INSTANCE (font_inst);
232 if (!fi->proportional_p)
233 return fi->width * run->len;
236 if (run->dimension == 2)
237 return XTextWidth16 (FONT_INSTANCE_X_FONT (fi),
238 (XChar2b *) run->ptr, run->len);
240 return XTextWidth (FONT_INSTANCE_X_FONT (fi),
241 (char *) run->ptr, run->len);
248 Given a string and a face, return the string's length in pixels when
249 displayed in the font associated with the face.
253 x_text_width (struct frame *f, struct face_cachel *cachel, CONST Emchar *str,
256 int width_so_far = 0;
257 unsigned char *text_storage = (unsigned char *) alloca (2 * len);
258 struct textual_run *runs = alloca_array (struct textual_run, len);
262 nruns = separate_textual_runs (text_storage, runs, str, len);
264 for (i = 0; i < nruns; i++)
265 width_so_far += x_text_width_single_run (cachel, runs + i);
270 /*****************************************************************************
273 Return the height of the horizontal divider. This is a function because
274 divider_height is a device method.
276 #### If we add etched horizontal divider lines this will have to get
278 ****************************************************************************/
280 x_divider_height (void)
285 /*****************************************************************************
288 Return the width of the end-of-line cursor. This is a function
289 because eol_cursor_width is a device method.
290 ****************************************************************************/
292 x_eol_cursor_width (void)
294 return EOL_CURSOR_WIDTH;
297 /*****************************************************************************
300 Perform any necessary initialization prior to an update.
301 ****************************************************************************/
303 x_output_begin (struct device *d)
307 /*****************************************************************************
310 Perform any necessary flushing of queues when an update has completed.
311 ****************************************************************************/
313 x_output_end (struct device *d)
315 XFlush (DEVICE_X_DISPLAY (d));
318 /*****************************************************************************
319 x_output_display_block
321 Given a display line, a block number for that start line, output all
322 runes between start and end in the specified display block.
323 ****************************************************************************/
325 x_output_display_block (struct window *w, struct display_line *dl, int block,
326 int start, int end, int start_pixpos, int cursor_start,
327 int cursor_width, int cursor_height)
329 struct frame *f = XFRAME (w->frame);
330 Emchar_dynarr *buf = Dynarr_new (Emchar);
333 struct display_block *db = Dynarr_atp (dl->display_blocks, block);
334 rune_dynarr *rba = db->runes;
340 Lisp_Object charset = Qunbound; /* Qnil is a valid charset when
341 MULE is not defined */
343 XSETWINDOW (window, w);
344 rb = Dynarr_atp (rba, start);
348 /* Nothing to do so don't do anything. */
356 if (rb->type == RUNE_CHAR)
357 charset = CHAR_CHARSET (rb->object.chr.ch);
361 end = Dynarr_length (rba);
366 rb = Dynarr_atp (rba, elt);
368 if (rb->findex == findex && rb->type == RUNE_CHAR
369 && rb->object.chr.ch != '\n' && rb->cursor_type != CURSOR_ON
370 && EQ (charset, CHAR_CHARSET (rb->object.chr.ch)))
372 Dynarr_add (buf, rb->object.chr.ch);
378 if (Dynarr_length (buf))
380 x_output_string (w, dl, buf, xpos, 0, start_pixpos, width,
381 findex, 0, cursor_start, cursor_width,
389 if (rb->type == RUNE_CHAR)
393 charset = CHAR_CHARSET (rb->object.chr.ch);
395 if (rb->cursor_type == CURSOR_ON)
397 if (rb->object.chr.ch == '\n')
399 x_output_eol_cursor (w, dl, xpos, findex);
403 Dynarr_add (buf, rb->object.chr.ch);
404 x_output_string (w, dl, buf, xpos, 0, start_pixpos,
405 rb->width, findex, 1,
406 cursor_start, cursor_width,
414 else if (rb->object.chr.ch == '\n')
416 /* Clear in case a cursor was formerly here. */
417 int height = dl->ascent + dl->descent - dl->clip;
419 x_clear_region (window, findex, xpos, dl->ypos - dl->ascent,
424 else if (rb->type == RUNE_BLANK || rb->type == RUNE_HLINE)
426 if (rb->type == RUNE_BLANK)
427 x_output_blank (w, dl, rb, start_pixpos, cursor_start,
431 /* #### Our flagging of when we need to redraw the
432 modeline shadows sucks. Since RUNE_HLINE is only used
433 by the modeline at the moment it is a good bet
434 that if it gets redrawn then we should also
435 redraw the shadows. This won't be true forever.
436 We borrow the shadow_thickness_changed flag for
438 w->shadow_thickness_changed = 1;
439 x_output_hline (w, dl, rb);
445 rb = Dynarr_atp (rba, elt);
451 else if (rb->type == RUNE_DGLYPH)
453 Lisp_Object instance;
455 XSETWINDOW (window, w);
456 instance = glyph_image_instance (rb->object.dglyph.glyph,
457 window, ERROR_ME_NOT, 1);
460 if (IMAGE_INSTANCEP (instance))
461 switch (XIMAGE_INSTANCE_TYPE (instance))
465 /* #### This is way losing. See the comment in
468 XIMAGE_INSTANCE_TEXT_STRING (instance);
469 convert_bufbyte_string_into_emchar_dynarr
470 (XSTRING_DATA (string), XSTRING_LENGTH (string), buf);
472 x_output_string (w, dl, buf, xpos,
473 rb->object.dglyph.xoffset,
474 start_pixpos, -1, findex,
475 (rb->cursor_type == CURSOR_ON),
476 cursor_start, cursor_width,
482 case IMAGE_MONO_PIXMAP:
483 case IMAGE_COLOR_PIXMAP:
484 x_output_pixmap (w, dl, instance, xpos,
485 rb->object.dglyph.xoffset, start_pixpos,
486 rb->width, findex, cursor_start,
487 cursor_width, cursor_height);
493 case IMAGE_SUBWINDOW:
494 /* #### implement me */
498 /* nothing is as nothing does */
513 if (Dynarr_length (buf))
514 x_output_string (w, dl, buf, xpos, 0, start_pixpos, width, findex,
515 0, cursor_start, cursor_width, cursor_height);
517 /* #### This is really conditionalized well for optimized
520 && !EQ (Qzero, w->modeline_shadow_thickness)
522 || f->windows_structure_changed
523 || w->shadow_thickness_changed))
524 x_bevel_modeline (w, dl);
529 /*****************************************************************************
532 Draw a 3d border around the modeline on window W.
533 ****************************************************************************/
535 x_bevel_modeline (struct window *w, struct display_line *dl)
537 struct frame *f = XFRAME (w->frame);
538 struct device *d = XDEVICE (f->device);
539 Display *dpy = DEVICE_X_DISPLAY (d);
540 Window x_win = XtWindow (FRAME_X_TEXT_WIDGET (f));
541 EmacsFrame ef = (EmacsFrame) FRAME_X_TEXT_WIDGET (f);
542 GC top_shadow_gc, bottom_shadow_gc, background_gc;
543 Pixel top_shadow_pixel, bottom_shadow_pixel, background_pixel;
545 Lisp_Object tmp_pixel;
546 int x, y, width, height;
551 int shadow_thickness;
553 memset (&gcv, ~0, sizeof (XGCValues));
555 tmp_pixel = WINDOW_FACE_CACHEL_BACKGROUND (w, MODELINE_INDEX);
556 tmp_color = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (tmp_pixel));
558 /* First, get the GC's. */
559 top_shadow_pixel = tmp_color.pixel;
560 bottom_shadow_pixel = tmp_color.pixel;
561 background_pixel = tmp_color.pixel;
563 x_generate_shadow_pixels (f, &top_shadow_pixel, &bottom_shadow_pixel,
564 background_pixel, ef->core.background_pixel);
566 tmp_pixel = WINDOW_FACE_CACHEL_FOREGROUND (w, MODELINE_INDEX);
567 tmp_color = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (tmp_pixel));
568 gcv.background = tmp_color.pixel;
569 gcv.graphics_exposures = False;
570 mask = GCForeground | GCBackground | GCGraphicsExposures;
572 if (top_shadow_pixel == background_pixel ||
573 bottom_shadow_pixel == background_pixel)
578 if (DEVICE_X_GRAY_PIXMAP (d) == None)
580 DEVICE_X_GRAY_PIXMAP (d) =
581 XCreatePixmapFromBitmapData (dpy, x_win, (char *) gray_bits,
582 gray_width, gray_height, 1, 0, 1);
585 tmp_pixel = WINDOW_FACE_CACHEL_BACKGROUND (w, MODELINE_INDEX);
586 tmp_color = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (tmp_pixel));
587 gcv.foreground = tmp_color.pixel;
588 gcv.fill_style = FillOpaqueStippled;
589 gcv.stipple = DEVICE_X_GRAY_PIXMAP (d);
590 top_shadow_gc = gc_cache_lookup (DEVICE_X_GC_CACHE (d), &gcv,
591 (mask | GCStipple | GCFillStyle));
593 tmp_pixel = WINDOW_FACE_CACHEL_FOREGROUND (w, MODELINE_INDEX);
594 tmp_color = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (tmp_pixel));
595 bottom_shadow_pixel = tmp_color.pixel;
597 flip_gcs = (bottom_shadow_pixel ==
598 WhitePixelOfScreen (DefaultScreenOfDisplay (dpy)));
602 gcv.foreground = top_shadow_pixel;
603 top_shadow_gc = gc_cache_lookup (DEVICE_X_GC_CACHE (d), &gcv, mask);
606 gcv.foreground = bottom_shadow_pixel;
607 bottom_shadow_gc = gc_cache_lookup (DEVICE_X_GC_CACHE (d), &gcv, mask);
609 if (use_pixmap && flip_gcs)
611 GC tmp_gc = bottom_shadow_gc;
612 bottom_shadow_gc = top_shadow_gc;
613 top_shadow_gc = tmp_gc;
616 gcv.foreground = background_pixel;
617 background_gc = gc_cache_lookup (DEVICE_X_GC_CACHE (d), &gcv, mask);
619 if (XINT (w->modeline_shadow_thickness) < 0)
623 temp = top_shadow_gc;
624 top_shadow_gc = bottom_shadow_gc;
625 bottom_shadow_gc = temp;
628 shadow_thickness = MODELINE_SHADOW_THICKNESS (w);
630 x = WINDOW_MODELINE_LEFT (w);
631 width = WINDOW_MODELINE_RIGHT (w) - x;
632 y = dl->ypos - dl->ascent - shadow_thickness;
633 height = dl->ascent + dl->descent + 2 * shadow_thickness;
635 x_output_shadows (f, x, y, width, height, top_shadow_gc, bottom_shadow_gc,
636 background_gc, shadow_thickness);
639 /*****************************************************************************
642 Given a number of parameters return a GC with those properties.
643 ****************************************************************************/
645 x_get_gc (struct device *d, Lisp_Object font, Lisp_Object fg, Lisp_Object bg,
646 Lisp_Object bg_pmap, Lisp_Object lwidth)
651 memset (&gcv, ~0, sizeof (XGCValues));
652 gcv.graphics_exposures = False;
653 /* Make absolutely sure that we don't pick up a clipping region in
654 the GC returned by this function. */
655 gcv.clip_mask = None;
656 gcv.clip_x_origin = 0;
657 gcv.clip_y_origin = 0;
658 gcv.fill_style = FillSolid;
659 mask = GCGraphicsExposures | GCClipMask | GCClipXOrigin | GCClipYOrigin;
664 gcv.font = FONT_INSTANCE_X_FONT (XFONT_INSTANCE (font))->fid;
669 if (!NILP (fg) && !COLOR_INSTANCEP (fg) && !INTP (fg))
671 /* #### I fixed once case where this was getting it. It was a
672 bad macro expansion (compiler bug). */
673 fprintf (stderr, "Help! x_get_gc got a bogus fg value! fg = ");
680 if (COLOR_INSTANCEP (fg))
681 gcv.foreground = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (fg)).pixel;
683 gcv.foreground = XINT (fg);
684 mask |= GCForeground;
689 if (COLOR_INSTANCEP (bg))
690 gcv.background = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (bg)).pixel;
692 gcv.background = XINT (bg);
693 mask |= GCBackground;
696 if (IMAGE_INSTANCEP (bg_pmap)
697 && IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (bg_pmap)))
699 if (XIMAGE_INSTANCE_PIXMAP_DEPTH (bg_pmap) == 0)
701 gcv.fill_style = FillOpaqueStippled;
702 gcv.stipple = XIMAGE_INSTANCE_X_PIXMAP (bg_pmap);
703 mask |= (GCStipple | GCFillStyle);
707 gcv.fill_style = FillTiled;
708 gcv.tile = XIMAGE_INSTANCE_X_PIXMAP (bg_pmap);
709 mask |= (GCTile | GCFillStyle);
715 gcv.line_width = XINT (lwidth);
719 return gc_cache_lookup (DEVICE_X_GC_CACHE (d), &gcv, mask);
722 /*****************************************************************************
725 Given a string and a starting position, output that string in the
726 given face. If cursor is true, draw a cursor around the string.
727 Correctly handles multiple charsets in the string.
729 The meaning of the parameters is something like this:
731 W Window that the text is to be displayed in.
732 DL Display line that this text is on. The values in the
733 structure are used to determine the vertical position and
734 clipping range of the text.
735 BUF Dynamic array of Emchars specifying what is actually to be
737 XPOS X position in pixels where the text should start being drawn.
738 XOFFSET Number of pixels to be chopped off the left side of the
739 text. The effect is as if the text were shifted to the
740 left this many pixels and clipped at XPOS.
741 CLIP_START Clip everything left of this X position.
742 WIDTH Clip everything right of XPOS + WIDTH.
743 FINDEX Index for the face cache element describing how to display
745 CURSOR #### I don't understand this. There's something
746 strange and overcomplexified with this variable.
747 Chuck, explain please?
748 CURSOR_START Starting X position of cursor.
749 CURSOR_WIDTH Width of cursor in pixels.
750 CURSOR_HEIGHT Height of cursor in pixels.
752 Starting Y position of cursor is the top of the text line.
753 The cursor is drawn sometimes whether or not CURSOR is set. ???
754 ****************************************************************************/
756 x_output_string (struct window *w, struct display_line *dl,
757 Emchar_dynarr *buf, int xpos, int xoffset, int clip_start,
758 int width, face_index findex, int cursor,
759 int cursor_start, int cursor_width, int cursor_height)
761 /* General variables */
762 struct frame *f = XFRAME (w->frame);
763 struct device *d = XDEVICE (f->device);
766 Display *dpy = DEVICE_X_DISPLAY (d);
767 Window x_win = XtWindow (FRAME_X_TEXT_WIDGET (f));
771 /* Cursor-related variables */
772 int focus = EQ (w->frame, DEVICE_FRAME_WITH_FOCUS_REAL (d));
774 Lisp_Object bar_cursor_value = symbol_value_in_buffer (Qbar_cursor,
776 struct face_cachel *cursor_cachel = 0;
778 /* Text-related variables */
782 int len = Dynarr_length (buf);
783 unsigned char *text_storage = (unsigned char *) alloca (2 * len);
784 struct textual_run *runs = alloca_array (struct textual_run, len);
787 struct face_cachel *cachel = WINDOW_FACE_CACHEL (w, findex);
789 XSETDEVICE (device, d);
790 XSETWINDOW (window, w);
793 width = x_text_width (f, cachel, Dynarr_atp (buf, 0), Dynarr_length (buf));
794 height = dl->ascent + dl->descent - dl->clip;
796 /* Regularize the variables passed in. */
798 if (clip_start < xpos)
800 clip_end = xpos + width;
801 if (clip_start >= clip_end)
802 /* It's all clipped out. */
807 nruns = separate_textual_runs (text_storage, runs, Dynarr_atp (buf, 0),
808 Dynarr_length (buf));
810 cursor_clip = (cursor_start >= clip_start &&
811 cursor_start < clip_end);
813 /* This cursor code is really a mess. */
814 if (!NILP (w->text_cursor_visible_p)
818 && (cursor_start + cursor_width >= clip_start)
819 && !NILP (bar_cursor_value))))
821 /* These have to be in separate statements in order to avoid a
823 face_index sucks = get_builtin_face_cache_index (w, Vtext_cursor_face);
824 cursor_cachel = WINDOW_FACE_CACHEL (w, sucks);
826 /* We have to reset this since any call to WINDOW_FACE_CACHEL
827 may cause the cache to resize and any pointers to it to
829 cachel = WINDOW_FACE_CACHEL (w, findex);
833 if (cursor && focus && (cursor_start == clip_start) && cursor_height)
834 XIM_SetSpotLocation (f, xpos - 2, dl->ypos + dl->descent - 2);
835 #endif /* HAVE_XIM */
837 bg_pmap = cachel->background_pixmap;
838 if (!IMAGE_INSTANCEP (bg_pmap)
839 || !IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (bg_pmap)))
842 if ((cursor && focus && NILP (bar_cursor_value)
843 && !NILP (w->text_cursor_visible_p)) || NILP (bg_pmap))
846 bgc = x_get_gc (d, Qnil, cachel->foreground, cachel->background,
850 XFillRectangle (dpy, x_win, bgc, clip_start,
851 dl->ypos - dl->ascent, clip_end - clip_start,
854 for (i = 0; i < nruns; i++)
856 Lisp_Object font = FACE_CACHEL_FONT (cachel, runs[i].charset);
857 struct Lisp_Font_Instance *fi = XFONT_INSTANCE (font);
861 if (EQ (font, Vthe_null_font_instance))
864 this_width = x_text_width_single_run (cachel, runs + i);
865 need_clipping = (dl->clip || clip_start > xpos ||
866 clip_end < xpos + this_width);
868 /* XDrawImageString only clears the area equal to the height of
869 the given font. It is possible that a font is being displayed
870 on a line taller than it is, so this would cause us to fail to
872 if ((int) fi->height < (int) (height + dl->clip))
874 int clear_start = max (xpos, clip_start);
875 int clear_end = min (xpos + this_width, clip_end);
879 int ypos1_line, ypos1_string, ypos2_line, ypos2_string;
881 ypos1_string = dl->ypos - fi->ascent;
882 ypos2_string = dl->ypos + fi->descent;
883 ypos1_line = dl->ypos - dl->ascent;
884 ypos2_line = dl->ypos + dl->descent - dl->clip;
886 /* Make sure we don't clear below the real bottom of the
888 if (ypos1_string > ypos2_line)
889 ypos1_string = ypos2_line;
890 if (ypos2_string > ypos2_line)
891 ypos2_string = ypos2_line;
893 if (ypos1_line < ypos1_string)
895 x_clear_region (window, findex, clear_start, ypos1_line,
896 clear_end - clear_start,
897 ypos1_string - ypos1_line);
900 if (ypos2_line > ypos2_string)
902 x_clear_region (window, findex, clear_start, ypos2_string,
903 clear_end - clear_start,
904 ypos2_line - ypos2_string);
909 x_clear_region (window, findex, clear_start,
910 dl->ypos - dl->ascent, clear_end - clear_start,
915 if (cursor && cursor_cachel && focus && NILP (bar_cursor_value))
916 gc = x_get_gc (d, font, cursor_cachel->foreground,
917 cursor_cachel->background, Qnil, Qnil);
919 gc = x_get_gc (d, font, cachel->foreground, cachel->background,
924 XRectangle clip_box[1];
928 clip_box[0].width = clip_end - clip_start;
929 clip_box[0].height = height;
931 XSetClipRectangles (dpy, gc, clip_start, dl->ypos - dl->ascent,
932 clip_box, 1, Unsorted);
935 if (runs[i].dimension == 1)
936 (bgc ? XDrawString : XDrawImageString) (dpy, x_win, gc, xpos,
937 dl->ypos, (char *) runs[i].ptr,
940 (bgc ? XDrawString16 : XDrawImageString16) (dpy, x_win, gc, xpos,
942 (XChar2b *) runs[i].ptr,
945 /* We draw underlines in the same color as the text. */
946 if (cachel->underline)
948 unsigned long upos, uthick;
951 xfont = FONT_INSTANCE_X_FONT (XFONT_INSTANCE (font));
952 if (!XGetFontProperty (xfont, XA_UNDERLINE_POSITION, &upos))
953 upos = dl->descent / 2;
954 if (!XGetFontProperty (xfont, XA_UNDERLINE_THICKNESS, &uthick))
957 if (dl->ypos + upos < dl->ypos + dl->descent - dl->clip)
959 if (dl->ypos + upos + uthick > dl->ypos + dl->descent - dl->clip)
960 uthick = dl->descent - dl->clip - upos;
964 XDrawLine (dpy, x_win, gc, xpos, dl->ypos + upos,
965 xpos + this_width, dl->ypos + upos);
969 XFillRectangle (dpy, x_win, gc, xpos,
970 dl->ypos + upos, this_width, uthick);
975 if (cachel->strikethru) {
976 unsigned long ascent,descent,upos, uthick;
979 xfont = FONT_INSTANCE_X_FONT (XFONT_INSTANCE (font));
981 if (!XGetFontProperty (xfont, XA_STRIKEOUT_ASCENT, &ascent))
982 ascent = xfont->ascent;
983 if (!XGetFontProperty (xfont, XA_STRIKEOUT_DESCENT, &descent))
984 descent = xfont->descent;
985 if (!XGetFontProperty (xfont, XA_UNDERLINE_THICKNESS, &uthick))
988 upos = ascent - ((ascent + descent) / 2) + 1;
990 /* Generally, upos will be positive (above the baseline),so subtract */
991 if (dl->ypos - upos < dl->ypos + dl->descent - dl->clip)
993 if (dl->ypos - upos + uthick > dl->ypos + dl->descent - dl->clip)
994 uthick = dl->descent - dl->clip + upos;
998 XDrawLine (dpy, x_win, gc, xpos, dl->ypos - upos,
999 xpos + this_width, dl->ypos - upos);
1001 else if (uthick > 1)
1003 XFillRectangle (dpy, x_win, gc, xpos, dl->ypos + upos,
1004 this_width, uthick);
1009 /* Restore the GC */
1012 XSetClipMask (dpy, gc, None);
1013 XSetClipOrigin (dpy, gc, 0, 0);
1016 /* If we are actually superimposing the cursor then redraw with just
1017 the appropriate section highlighted. */
1018 if (cursor_clip && !cursor && focus && cursor_cachel)
1021 XRectangle clip_box[1];
1023 cgc = x_get_gc (d, font, cursor_cachel->foreground,
1024 cursor_cachel->background, Qnil, Qnil);
1028 clip_box[0].width = cursor_width;
1029 clip_box[0].height = height;
1031 XSetClipRectangles (dpy, cgc, cursor_start, dl->ypos - dl->ascent,
1032 clip_box, 1, Unsorted);
1034 if (runs[i].dimension == 1)
1035 XDrawImageString (dpy, x_win, cgc, xpos, dl->ypos,
1036 (char *) runs[i].ptr, runs[i].len);
1038 XDrawImageString16 (dpy, x_win, cgc, xpos, dl->ypos,
1039 (XChar2b *) runs[i].ptr, runs[i].len);
1041 XSetClipMask (dpy, cgc, None);
1042 XSetClipOrigin (dpy, cgc, 0, 0);
1048 /* Draw the non-focus box or bar-cursor as needed. */
1049 /* Can't this logic be simplified? */
1051 && ((cursor && !focus && NILP (bar_cursor_value))
1053 && (cursor_start + cursor_width >= clip_start)
1054 && !NILP (bar_cursor_value))))
1056 int tmp_height, tmp_y;
1057 int bar_width = EQ (bar_cursor_value, Qt) ? 1 : 2;
1058 int need_clipping = (cursor_start < clip_start
1059 || clip_end < cursor_start + cursor_width);
1061 /* #### This value is correct (as far as I know) because
1062 all of the times we need to draw this cursor, we will
1063 be called with exactly one character, so we know we
1064 can always use runs[0].
1066 This is bogus as all hell, however. The cursor handling in
1067 this function is way bogus and desperately needs to be
1068 cleaned up. (In particular, the drawing of the cursor should
1069 really really be separated out of this function. This may be
1070 a bit tricky now because this function itself does way too
1071 much stuff, a lot of which needs to be moved into
1072 redisplay.c) This is the only way to be able to easily add
1073 new cursor types or (e.g.) make the bar cursor be able to
1074 span two characters instead of overlaying just one. */
1075 int bogusly_obtained_ascent_value =
1076 XFONT_INSTANCE (FACE_CACHEL_FONT (cachel, runs[0].charset))->ascent;
1078 if (!NILP (bar_cursor_value))
1080 gc = x_get_gc (d, Qnil, cursor_cachel->background, Qnil, Qnil,
1081 make_int (bar_width));
1085 gc = x_get_gc (d, Qnil, cursor_cachel->background,
1089 tmp_y = dl->ypos - bogusly_obtained_ascent_value;
1090 tmp_height = cursor_height;
1091 if (tmp_y + tmp_height > (int) (dl->ypos - dl->ascent + height))
1093 tmp_y = dl->ypos - dl->ascent + height - tmp_height;
1094 if (tmp_y < (int) (dl->ypos - dl->ascent))
1095 tmp_y = dl->ypos - dl->ascent;
1096 tmp_height = dl->ypos - dl->ascent + height - tmp_y;
1101 XRectangle clip_box[1];
1104 clip_box[0].width = clip_end - clip_start;
1105 clip_box[0].height = tmp_height;
1106 XSetClipRectangles (dpy, gc, clip_start, tmp_y,
1107 clip_box, 1, Unsorted);
1110 if (!focus && NILP (bar_cursor_value))
1112 XDrawRectangle (dpy, x_win, gc, cursor_start, tmp_y,
1113 cursor_width - 1, tmp_height - 1);
1115 else if (focus && !NILP (bar_cursor_value))
1117 XDrawLine (dpy, x_win, gc, cursor_start + bar_width - 1, tmp_y,
1118 cursor_start + bar_width - 1, tmp_y + tmp_height - 1);
1121 /* Restore the GC */
1124 XSetClipMask (dpy, gc, None);
1125 XSetClipOrigin (dpy, gc, 0, 0);
1131 x_output_x_pixmap (struct frame *f, struct Lisp_Image_Instance *p, int x,
1132 int y, int clip_x, int clip_y, int clip_width,
1133 int clip_height, int width, int height, int pixmap_offset,
1134 unsigned long fg, unsigned long bg, GC override_gc)
1136 struct device *d = XDEVICE (f->device);
1137 Display *dpy = DEVICE_X_DISPLAY (d);
1138 Window x_win = XtWindow (FRAME_X_TEXT_WIDGET (f));
1142 unsigned long pixmap_mask;
1143 int need_clipping = (clip_x || clip_y);
1147 memset (&gcv, ~0, sizeof (XGCValues));
1148 gcv.graphics_exposures = False;
1149 gcv.foreground = fg;
1150 gcv.background = bg;
1151 pixmap_mask = GCForeground | GCBackground | GCGraphicsExposures;
1153 if (IMAGE_INSTANCE_X_MASK (p))
1155 gcv.function = GXcopy;
1156 gcv.clip_mask = IMAGE_INSTANCE_X_MASK (p);
1157 gcv.clip_x_origin = x;
1158 gcv.clip_y_origin = y - pixmap_offset;
1159 pixmap_mask |= (GCFunction | GCClipMask | GCClipXOrigin |
1161 /* Can't set a clip rectangle below because we already have a mask.
1162 We could conceivably create a new clipmask by zeroing out
1163 everything outside the clip region. Is it worth it?
1164 Is it possible to get an equivalent effect by changing the
1165 args to XCopyArea below rather than messing with a clip box?
1166 - dkindred@cs.cmu.edu */
1170 gc = gc_cache_lookup (DEVICE_X_GC_CACHE (d), &gcv, pixmap_mask);
1175 /* override_gc might have a mask already--we don't want to nuke it.
1176 Maybe we can insist that override_gc have no mask, or use
1177 one of the suggestions above. */
1183 XRectangle clip_box[1];
1185 clip_box[0].x = clip_x;
1186 clip_box[0].y = clip_y;
1187 clip_box[0].width = clip_width;
1188 clip_box[0].height = clip_height;
1190 XSetClipRectangles (dpy, gc, x, y, clip_box, 1, Unsorted);
1193 /* depth of 0 means it's a bitmap, not a pixmap, and we should use
1194 XCopyPlane (1 = current foreground color, 0 = background) instead
1195 of XCopyArea, which means that the bits in the pixmap are actual
1196 pixel values, instead of symbolic of fg/bg. */
1197 if (IMAGE_INSTANCE_PIXMAP_DEPTH (p) > 0)
1199 XCopyArea (dpy, IMAGE_INSTANCE_X_PIXMAP (p), x_win, gc, 0,
1200 pixmap_offset, width,
1205 XCopyPlane (dpy, IMAGE_INSTANCE_X_PIXMAP (p), x_win, gc, 0,
1218 XSetClipMask (dpy, gc, None);
1219 XSetClipOrigin (dpy, gc, 0, 0);
1224 x_output_pixmap (struct window *w, struct display_line *dl,
1225 Lisp_Object image_instance, int xpos, int xoffset,
1226 int start_pixpos, int width, face_index findex,
1227 int cursor_start, int cursor_width, int cursor_height)
1229 struct frame *f = XFRAME (w->frame);
1230 struct device *d = XDEVICE (f->device);
1231 struct Lisp_Image_Instance *p = XIMAGE_INSTANCE (image_instance);
1234 Display *dpy = DEVICE_X_DISPLAY (d);
1235 Window x_win = XtWindow (FRAME_X_TEXT_WIDGET (f));
1236 int lheight = dl->ascent + dl->descent - dl->clip;
1237 int pheight = ((int) IMAGE_INSTANCE_PIXMAP_HEIGHT (p) > lheight ? lheight :
1238 IMAGE_INSTANCE_PIXMAP_HEIGHT (p));
1239 int pwidth = min (width + xoffset, (int) IMAGE_INSTANCE_PIXMAP_WIDTH (p));
1240 int clip_x, clip_y, clip_width, clip_height;
1242 /* The pixmap_offset is used to center the pixmap on lines which are
1243 shorter than it is. This results in odd effects when scrolling
1244 pixmaps off of the bottom. Let's try not using it. */
1246 int pixmap_offset = (int) (IMAGE_INSTANCE_PIXMAP_HEIGHT (p) - lheight) / 2;
1248 int pixmap_offset = 0;
1251 XSETWINDOW (window, w);
1253 if ((start_pixpos >= 0 && start_pixpos > xpos) || xoffset)
1255 if (start_pixpos > xpos && start_pixpos > xpos + width)
1260 if (start_pixpos > xpos)
1262 clip_x += (start_pixpos - xpos);
1263 clip_width -= (start_pixpos - xpos);
1272 /* Place markers for possible future functionality (clipping the top
1273 half instead of the bottom half; think pixel scrolling). */
1275 clip_height = pheight;
1277 /* Clear the area the pixmap is going into. The pixmap itself will
1278 always take care of the full width. We don't want to clear where
1279 it is going to go in order to avoid flicker. So, all we have to
1280 take care of is any area above or below the pixmap. */
1281 /* #### We take a shortcut for now. We know that since we have
1282 pixmap_offset hardwired to 0 that the pixmap is against the top
1283 edge so all we have to worry about is below it. */
1284 /* #### Unless the pixmap has a mask in which case we have to clear
1285 the whole damn thing since we can't yet clear just the area not
1286 included in the mask. */
1287 if (((int) (dl->ypos - dl->ascent + pheight) <
1288 (int) (dl->ypos + dl->descent - dl->clip))
1289 || IMAGE_INSTANCE_X_MASK (p))
1291 int clear_x, clear_y, clear_width, clear_height;
1293 if (IMAGE_INSTANCE_X_MASK (p))
1295 clear_y = dl->ypos - dl->ascent;
1296 clear_height = lheight;
1300 clear_y = dl->ypos - dl->ascent + pheight;
1301 clear_height = lheight - pheight;
1304 if (start_pixpos >= 0 && start_pixpos > xpos)
1306 clear_x = start_pixpos;
1307 clear_width = xpos + width - start_pixpos;
1312 clear_width = width;
1315 x_clear_region (window, findex, clear_x, clear_y,
1316 clear_width, clear_height);
1319 /* Output the pixmap. */
1321 Lisp_Object tmp_pixel;
1322 XColor tmp_bcolor, tmp_fcolor;
1324 tmp_pixel = WINDOW_FACE_CACHEL_FOREGROUND (w, findex);
1325 tmp_fcolor = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (tmp_pixel));
1326 tmp_pixel = WINDOW_FACE_CACHEL_BACKGROUND (w, findex);
1327 tmp_bcolor = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (tmp_pixel));
1329 x_output_x_pixmap (f, p, xpos - xoffset, dl->ypos - dl->ascent, clip_x,
1330 clip_y, clip_width, clip_height,
1331 pwidth, pheight, pixmap_offset,
1332 tmp_fcolor.pixel, tmp_bcolor.pixel, 0);
1335 /* Draw a cursor over top of the pixmap. */
1336 if (cursor_width && cursor_height && (cursor_start >= xpos)
1337 && !NILP (w->text_cursor_visible_p)
1338 && (cursor_start < xpos + pwidth))
1341 int focus = EQ (w->frame, DEVICE_FRAME_WITH_FOCUS_REAL (d));
1342 int y = dl->ypos - dl->ascent;
1343 struct face_cachel *cursor_cachel =
1344 WINDOW_FACE_CACHEL (w,
1345 get_builtin_face_cache_index
1346 (w, Vtext_cursor_face));
1348 gc = x_get_gc (d, Qnil, cursor_cachel->background, Qnil, Qnil, Qnil);
1350 if (cursor_width > xpos + pwidth - cursor_start)
1351 cursor_width = xpos + pwidth - cursor_start;
1355 XFillRectangle (dpy, x_win, gc, cursor_start, y, cursor_width,
1360 XDrawRectangle (dpy, x_win, gc, cursor_start, y, cursor_width,
1366 /*****************************************************************************
1367 x_output_vertical_divider
1369 Draw a vertical divider down the right side of the given window.
1370 ****************************************************************************/
1372 x_output_vertical_divider (struct window *w, int clear)
1374 struct frame *f = XFRAME (w->frame);
1375 struct device *d = XDEVICE (f->device);
1377 EmacsFrame ef = (EmacsFrame) FRAME_X_TEXT_WIDGET (f);
1378 Display *dpy = DEVICE_X_DISPLAY (d);
1379 Window x_win = XtWindow (FRAME_X_TEXT_WIDGET (f));
1380 Pixel top_shadow_pixel, bottom_shadow_pixel, background_pixel;
1381 Lisp_Object tmp_pixel;
1384 GC top_shadow_gc, bottom_shadow_gc, background_gc;
1389 int x, y1, y2, width, shadow_thickness, spacing, line_width;
1390 face_index div_face = get_builtin_face_cache_index (w, Vvertical_divider_face);
1392 width = window_divider_width (w);
1393 shadow_thickness = XINT (w->vertical_divider_shadow_thickness);
1394 spacing = XINT (w->vertical_divider_spacing);
1395 line_width = XINT (w->vertical_divider_line_width);
1396 x = WINDOW_RIGHT (w) - width;
1397 y1 = WINDOW_TOP (w);
1398 y2 = WINDOW_BOTTOM (w);
1400 memset (&gcv, ~0, sizeof (XGCValues));
1402 tmp_pixel = WINDOW_FACE_CACHEL_BACKGROUND (w, div_face);
1403 tmp_color = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (tmp_pixel));
1405 /* First, get the GC's. */
1406 top_shadow_pixel = tmp_color.pixel;
1407 bottom_shadow_pixel = tmp_color.pixel;
1408 background_pixel = tmp_color.pixel;
1410 x_generate_shadow_pixels (f, &top_shadow_pixel, &bottom_shadow_pixel,
1411 background_pixel, ef->core.background_pixel);
1413 tmp_pixel = WINDOW_FACE_CACHEL_FOREGROUND (w, div_face);
1414 tmp_color = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (tmp_pixel));
1415 gcv.background = tmp_color.pixel;
1416 gcv.graphics_exposures = False;
1417 mask = GCForeground | GCBackground | GCGraphicsExposures;
1419 /* If we can't distinguish one of the shadows (the color is the same as the
1420 background), it's better to use a pixmap to generate a dithrered gray. */
1421 if (top_shadow_pixel == background_pixel ||
1422 bottom_shadow_pixel == background_pixel)
1427 if (DEVICE_X_GRAY_PIXMAP (d) == None)
1429 DEVICE_X_GRAY_PIXMAP (d) =
1430 XCreatePixmapFromBitmapData (dpy, x_win, (char *) gray_bits,
1431 gray_width, gray_height, 1, 0, 1);
1434 tmp_pixel = WINDOW_FACE_CACHEL_BACKGROUND (w, div_face);
1435 tmp_color = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (tmp_pixel));
1436 gcv.foreground = tmp_color.pixel;
1437 /* this is needed because the GC draws with a pixmap here */
1438 gcv.fill_style = FillOpaqueStippled;
1439 gcv.stipple = DEVICE_X_GRAY_PIXMAP (d);
1440 top_shadow_gc = gc_cache_lookup (DEVICE_X_GC_CACHE (d), &gcv,
1441 (mask | GCStipple | GCFillStyle));
1443 tmp_pixel = WINDOW_FACE_CACHEL_FOREGROUND (w, div_face);
1444 tmp_color = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (tmp_pixel));
1445 bottom_shadow_pixel = tmp_color.pixel;
1447 flip_gcs = (bottom_shadow_pixel ==
1448 WhitePixelOfScreen (DefaultScreenOfDisplay (dpy)));
1452 gcv.foreground = top_shadow_pixel;
1453 top_shadow_gc = gc_cache_lookup (DEVICE_X_GC_CACHE (d), &gcv, mask);
1456 gcv.foreground = bottom_shadow_pixel;
1457 bottom_shadow_gc = gc_cache_lookup (DEVICE_X_GC_CACHE (d), &gcv, mask);
1459 if (use_pixmap && flip_gcs)
1461 GC tmp_gc = bottom_shadow_gc;
1462 bottom_shadow_gc = top_shadow_gc;
1463 top_shadow_gc = tmp_gc;
1466 gcv.foreground = background_pixel;
1467 background_gc = gc_cache_lookup (DEVICE_X_GC_CACHE (d), &gcv, mask);
1469 /* possibly revert the GC's in case the shadow thickness is < 0.
1470 This will give a depressed look to the divider */
1471 if (shadow_thickness < 0)
1475 temp = top_shadow_gc;
1476 top_shadow_gc = bottom_shadow_gc;
1477 bottom_shadow_gc = temp;
1479 /* better avoid a Bad Adress XLib error ;-) */
1480 shadow_thickness = - shadow_thickness;
1483 /* Clear the divider area first. This needs to be done when a
1484 window split occurs. */
1486 XClearArea (dpy, x_win, x, y1, width, y2 - y1, False);
1488 /* Draw the divider line. */
1489 XFillRectangle (dpy, x_win, background_gc,
1490 x + spacing + shadow_thickness, y1,
1491 line_width, y2 - y1);
1493 /* Draw the shadows around the divider line */
1494 x_output_shadows (f, x + spacing, y1,
1495 width - 2 * spacing, y2 - y1,
1496 top_shadow_gc, bottom_shadow_gc,
1497 background_gc, shadow_thickness);
1500 /*****************************************************************************
1503 Output a blank by clearing the area it covers in the foreground color
1505 ****************************************************************************/
1507 x_output_blank (struct window *w, struct display_line *dl, struct rune *rb,
1508 int start_pixpos, int cursor_start, int cursor_width)
1510 struct frame *f = XFRAME (w->frame);
1511 struct device *d = XDEVICE (f->device);
1513 Display *dpy = DEVICE_X_DISPLAY (d);
1514 Window x_win = XtWindow (FRAME_X_TEXT_WIDGET (f));
1516 struct face_cachel *cursor_cachel =
1517 WINDOW_FACE_CACHEL (w,
1518 get_builtin_face_cache_index
1519 (w, Vtext_cursor_face));
1520 Lisp_Object bg_pmap;
1521 Lisp_Object buffer = WINDOW_BUFFER (w);
1522 Lisp_Object bar_cursor_value = symbol_value_in_buffer (Qbar_cursor,
1526 int y = dl->ypos - dl->ascent;
1527 int width = rb->width;
1528 int height = dl->ascent + dl->descent - dl->clip;
1530 if (start_pixpos > x)
1532 if (start_pixpos >= (x + width))
1536 width -= (start_pixpos - x);
1541 bg_pmap = WINDOW_FACE_CACHEL_BACKGROUND_PIXMAP (w, rb->findex);
1542 if (!IMAGE_INSTANCEP (bg_pmap)
1543 || !IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (bg_pmap)))
1547 gc = x_get_gc (d, Qnil, WINDOW_FACE_CACHEL_BACKGROUND (w, rb->findex),
1550 gc = x_get_gc (d, Qnil, WINDOW_FACE_CACHEL_FOREGROUND (w, rb->findex),
1551 WINDOW_FACE_CACHEL_BACKGROUND (w, rb->findex), bg_pmap,
1554 XFillRectangle (dpy, x_win, gc, x, y, width, height);
1556 /* If this rune is marked as having the cursor, then it is actually
1557 representing a tab. */
1558 if (!NILP (w->text_cursor_visible_p)
1559 && (rb->cursor_type == CURSOR_ON
1561 && (cursor_start + cursor_width > x)
1562 && cursor_start < (x + width))))
1564 int cursor_height, cursor_y;
1565 int focus = EQ (w->frame, DEVICE_FRAME_WITH_FOCUS_REAL (d));
1566 struct Lisp_Font_Instance *fi;
1568 fi = XFONT_INSTANCE (FACE_CACHEL_FONT
1569 (WINDOW_FACE_CACHEL (w, rb->findex),
1572 gc = x_get_gc (d, Qnil, cursor_cachel->background, Qnil, Qnil, Qnil);
1574 cursor_y = dl->ypos - fi->ascent;
1575 cursor_height = fi->height;
1576 if (cursor_y + cursor_height > y + height)
1577 cursor_height = y + height - cursor_y;
1581 if (NILP (bar_cursor_value))
1583 XFillRectangle (dpy, x_win, gc, cursor_start, cursor_y,
1584 fi->width, cursor_height);
1588 int bar_width = EQ (bar_cursor_value, Qt) ? 1 : 2;
1590 gc = x_get_gc (d, Qnil, cursor_cachel->background, Qnil, Qnil,
1591 make_int (bar_width));
1592 XDrawLine (dpy, x_win, gc, cursor_start + bar_width - 1,
1593 cursor_y, cursor_start + bar_width - 1,
1594 cursor_y + cursor_height - 1);
1597 else if (NILP (bar_cursor_value))
1599 XDrawRectangle (dpy, x_win, gc, cursor_start, cursor_y,
1600 fi->width - 1, cursor_height - 1);
1605 /*****************************************************************************
1608 Output a horizontal line in the foreground of its face.
1609 ****************************************************************************/
1611 x_output_hline (struct window *w, struct display_line *dl, struct rune *rb)
1613 struct frame *f = XFRAME (w->frame);
1614 struct device *d = XDEVICE (f->device);
1616 Display *dpy = DEVICE_X_DISPLAY (d);
1617 Window x_win = XtWindow (FRAME_X_TEXT_WIDGET (f));
1621 int width = rb->width;
1622 int height = dl->ascent + dl->descent - dl->clip;
1623 int ypos1, ypos2, ypos3, ypos4;
1625 ypos1 = dl->ypos - dl->ascent;
1626 ypos2 = ypos1 + rb->object.hline.yoffset;
1627 ypos3 = ypos2 + rb->object.hline.thickness;
1628 ypos4 = dl->ypos + dl->descent - dl->clip;
1630 /* First clear the area not covered by the line. */
1631 if (height - rb->object.hline.thickness > 0)
1633 gc = x_get_gc (d, Qnil, WINDOW_FACE_CACHEL_FOREGROUND (w, rb->findex),
1636 if (ypos2 - ypos1 > 0)
1637 XFillRectangle (dpy, x_win, gc, x, ypos1, width, ypos2 - ypos1);
1638 if (ypos4 - ypos3 > 0)
1639 XFillRectangle (dpy, x_win, gc, x, ypos1, width, ypos2 - ypos1);
1642 /* Now draw the line. */
1643 gc = x_get_gc (d, Qnil, WINDOW_FACE_CACHEL_BACKGROUND (w, rb->findex),
1651 if (ypos3 - ypos2 > 0)
1652 XFillRectangle (dpy, x_win, gc, x, ypos2, width, ypos3 - ypos2);
1655 /*****************************************************************************
1658 Draw a shadow around the given area using the given GC's. It is the
1659 callers responsibility to ste the GC's appropriately.
1660 ****************************************************************************/
1662 x_output_shadows (struct frame *f, int x, int y, int width, int height,
1663 GC top_shadow_gc, GC bottom_shadow_gc, GC background_gc,
1664 int shadow_thickness)
1666 struct device *d = XDEVICE (f->device);
1668 Display *dpy = DEVICE_X_DISPLAY (d);
1669 Window x_win = XtWindow (FRAME_X_TEXT_WIDGET (f));
1671 XSegment top_shadow[20], bottom_shadow[20];
1674 if (shadow_thickness > 10)
1675 shadow_thickness = 10;
1676 else if (shadow_thickness < 0)
1677 shadow_thickness = 0;
1678 if (shadow_thickness > (width / 2))
1679 shadow_thickness = width / 2;
1680 if (shadow_thickness > (height / 2))
1681 shadow_thickness = height / 2;
1683 for (elt = 0; elt < shadow_thickness; elt++)
1686 int seg2 = elt + shadow_thickness;
1688 top_shadow[seg1].x1 = x;
1689 top_shadow[seg1].x2 = x + width - elt - 1;
1690 top_shadow[seg1].y1 = top_shadow[seg1].y2 = y + elt;
1692 top_shadow[seg2].x1 = top_shadow[seg2].x2 = x + elt;
1693 top_shadow[seg2].y1 = y + shadow_thickness;
1694 top_shadow[seg2].y2 = y + height - elt - 1;
1696 bottom_shadow[seg1].x1 = x + elt + 1;
1697 bottom_shadow[seg1].x2 = x + width - 1;
1698 bottom_shadow[seg1].y1 = bottom_shadow[seg1].y2 = y + height - elt - 1;
1700 bottom_shadow[seg2].x1 = bottom_shadow[seg2].x2 = x + width - elt - 1;
1701 bottom_shadow[seg2].y1 = y + elt + 1;
1702 bottom_shadow[seg2].y2 = y + height - shadow_thickness;
1705 XDrawSegments (dpy, x_win, top_shadow_gc, top_shadow, shadow_thickness * 2);
1706 XDrawSegments (dpy, x_win, bottom_shadow_gc, bottom_shadow,
1707 shadow_thickness * 2);
1710 /*****************************************************************************
1711 x_generate_shadow_pixels
1713 Given three pixels (top shadow, bottom shadow, background) massage
1714 the top and bottom shadow colors to guarantee that they differ. The
1715 background pixels are not allowed to be modified.
1717 This function modifies its parameters.
1719 This code is modified from code blatantly stolen from lwlib/xlwmenu.c
1720 ****************************************************************************/
1721 #define MINL(x,y) ((((unsigned long) (x)) < ((unsigned long) (y))) \
1722 ? ((unsigned long) (x)) : ((unsigned long) (y)))
1725 x_generate_shadow_pixels (struct frame *f, unsigned long *top_shadow,
1726 unsigned long *bottom_shadow,
1727 unsigned long background,
1728 unsigned long core_background)
1730 struct device *d = XDEVICE (f->device);
1731 Display *dpy = DEVICE_X_DISPLAY (d);
1732 Colormap cmap = DEVICE_X_COLORMAP (d);
1733 Visual *visual = DEVICE_X_VISUAL (d);
1736 int top_frobbed = 0, bottom_frobbed = 0;
1738 /* If the top shadow is the same color as the background, try to
1740 if (*top_shadow == background)
1742 topc.pixel = background;
1743 XQueryColor (dpy, cmap, &topc);
1744 /* don't overflow/wrap! */
1745 topc.red = MINL (65535, (unsigned long) topc.red * 6 / 5);
1746 topc.green = MINL (65535, (unsigned long) topc.green * 6 / 5);
1747 topc.blue = MINL (65535, (unsigned long) topc.blue * 6 / 5);
1748 if (allocate_nearest_color (dpy, cmap, visual, &topc))
1750 *top_shadow = topc.pixel;
1755 /* If the bottom shadow is the same color as the background, try to
1757 if (*bottom_shadow == background)
1759 botc.pixel = background;
1760 XQueryColor (dpy, cmap, &botc);
1761 botc.red = (unsigned short) ((unsigned long) botc.red * 3 / 5);
1762 botc.green = (unsigned short) ((unsigned long) botc.green * 3 / 5);
1763 botc.blue = (unsigned short) ((unsigned long) botc.blue * 3 / 5);
1764 if (allocate_nearest_color (dpy, cmap, visual, &botc))
1766 *bottom_shadow = botc.pixel;
1771 /* If we had to adjust both shadows, then we have to do some
1773 if (top_frobbed && bottom_frobbed)
1775 int top_avg = ((topc.red / 3) + (topc.green / 3) + (topc.blue / 3));
1776 int bot_avg = ((botc.red / 3) + (botc.green / 3) + (botc.blue / 3));
1777 if (bot_avg > top_avg)
1779 Pixel tmp = *top_shadow;
1781 *top_shadow = *bottom_shadow;
1782 *bottom_shadow = tmp;
1784 else if (topc.pixel == botc.pixel)
1786 if (botc.pixel == background)
1787 *top_shadow = core_background;
1789 *bottom_shadow = background;
1794 /*****************************************************************************
1795 x_clear_to_window_end
1797 Clear the area between ypos1 and ypos2. Each margin area and the
1798 text area is handled separately since they may each have their own
1800 ****************************************************************************/
1802 x_clear_to_window_end (struct window *w, int ypos1, int ypos2)
1804 int height = ypos2 - ypos1;
1808 struct frame *f = XFRAME (w->frame);
1810 int bflag = (window_needs_vertical_divider (w) ? 0 : 1);
1811 layout_bounds bounds;
1813 bounds = calculate_display_line_boundaries (w, bflag);
1814 XSETWINDOW (window, w);
1816 if (window_is_leftmost (w))
1817 x_clear_region (window, DEFAULT_INDEX, FRAME_LEFT_BORDER_START (f),
1818 ypos1, FRAME_BORDER_WIDTH (f), height);
1820 if (bounds.left_in - bounds.left_out > 0)
1821 x_clear_region (window,
1822 get_builtin_face_cache_index (w, Vleft_margin_face),
1823 bounds.left_out, ypos1,
1824 bounds.left_in - bounds.left_out, height);
1826 if (bounds.right_in - bounds.left_in > 0)
1827 x_clear_region (window, DEFAULT_INDEX, bounds.left_in, ypos1,
1828 bounds.right_in - bounds.left_in, height);
1830 if (bounds.right_out - bounds.right_in > 0)
1831 x_clear_region (window,
1832 get_builtin_face_cache_index (w, Vright_margin_face),
1833 bounds.right_in, ypos1,
1834 bounds.right_out - bounds.right_in, height);
1836 if (window_is_rightmost (w))
1837 x_clear_region (window, DEFAULT_INDEX, FRAME_RIGHT_BORDER_START (f),
1838 ypos1, FRAME_BORDER_WIDTH (f), height);
1842 /*****************************************************************************
1843 x_redraw_exposed_window
1845 Given a bounding box for an area that needs to be redrawn, determine
1846 what parts of what lines are contained within and re-output their
1848 ****************************************************************************/
1850 x_redraw_exposed_window (struct window *w, int x, int y, int width, int height)
1852 struct frame *f = XFRAME (w->frame);
1854 int start_x, start_y, end_x, end_y;
1855 int orig_windows_structure_changed;
1857 display_line_dynarr *cdla = window_display_lines (w, CURRENT_DISP);
1859 if (!NILP (w->vchild))
1861 x_redraw_exposed_windows (w->vchild, x, y, width, height);
1864 else if (!NILP (w->hchild))
1866 x_redraw_exposed_windows (w->hchild, x, y, width, height);
1870 /* If the window doesn't intersect the exposed region, we're done here. */
1871 if (x >= WINDOW_RIGHT (w) || (x + width) <= WINDOW_LEFT (w)
1872 || y >= WINDOW_BOTTOM (w) || (y + height) <= WINDOW_TOP (w))
1878 start_x = max (WINDOW_LEFT (w), x);
1879 end_x = min (WINDOW_RIGHT (w), (x + width));
1880 start_y = max (WINDOW_TOP (w), y);
1881 end_y = min (WINDOW_BOTTOM (w), y + height);
1883 /* We do this to make sure that the 3D modelines get redrawn if
1884 they are in the exposed region. */
1885 orig_windows_structure_changed = f->windows_structure_changed;
1886 f->windows_structure_changed = 1;
1889 if (window_needs_vertical_divider (w))
1891 x_output_vertical_divider (w, 0);
1894 for (line = 0; line < Dynarr_length (cdla); line++)
1896 struct display_line *cdl = Dynarr_atp (cdla, line);
1897 int top_y = cdl->ypos - cdl->ascent;
1898 int bottom_y = cdl->ypos + cdl->descent;
1900 if (bottom_y >= start_y)
1911 output_display_line (w, 0, cdla, line, start_x, end_x);
1916 f->windows_structure_changed = orig_windows_structure_changed;
1918 /* If there have never been any face cache_elements created, then this
1919 expose event doesn't actually have anything to do. */
1920 if (Dynarr_largest (w->face_cachels))
1921 redisplay_clear_bottom_of_window (w, cdla, start_y, end_y);
1924 /*****************************************************************************
1925 x_redraw_exposed_windows
1927 For each window beneath the given window in the window hierarchy,
1928 ensure that it is redrawn if necessary after an Expose event.
1929 ****************************************************************************/
1931 x_redraw_exposed_windows (Lisp_Object window, int x, int y, int width,
1934 for (; !NILP (window); window = XWINDOW (window)->next)
1935 x_redraw_exposed_window (XWINDOW (window), x, y, width, height);
1938 /*****************************************************************************
1939 x_redraw_exposed_area
1941 For each window on the given frame, ensure that any area in the
1942 Exposed area is redrawn.
1943 ****************************************************************************/
1945 x_redraw_exposed_area (struct frame *f, int x, int y, int width, int height)
1947 /* If any window on the frame has had its face cache reset then the
1948 redisplay structures are effectively invalid. If we attempt to
1949 use them we'll blow up. We mark the frame as changed to ensure
1950 that redisplay will do a full update. This probably isn't
1951 necessary but it can't hurt. */
1953 #ifdef HAVE_TOOLBARS
1954 /* #### We would rather put these off as well but there is currently
1955 no combination of flags which will force an unchanged toolbar to
1957 MAYBE_FRAMEMETH (f, redraw_exposed_toolbars, (f, x, y, width, height));
1960 if (!f->window_face_cache_reset)
1962 x_redraw_exposed_windows (f->root_window, x, y, width, height);
1964 XFlush (DEVICE_X_DISPLAY (XDEVICE (f->device)));
1967 MARK_FRAME_CHANGED (f);
1970 /****************************************************************************
1973 Clear the area in the box defined by the given parameters using the
1975 ****************************************************************************/
1977 x_clear_region (Lisp_Object locale, face_index findex, int x, int y,
1978 int width, int height)
1980 struct window *w = NULL;
1981 struct frame *f = NULL;
1983 Lisp_Object background_pixmap;
1988 if (WINDOWP (locale))
1990 w = XWINDOW (locale);
1991 f = XFRAME (w->frame);
1993 else if (FRAMEP (locale))
1996 f = XFRAME (locale);
2001 d = XDEVICE (f->device);
2002 dpy = DEVICE_X_DISPLAY (d);
2003 x_win = XtWindow (FRAME_X_TEXT_WIDGET (f));
2005 /* #### This function is going to have to be made cursor aware. */
2006 if (width && height)
2010 /* #### This isn't quite right for when this function is called
2011 from the toolbar code. */
2012 background_pixmap = Qunbound;
2014 /* Don't use a backing pixmap in the border area */
2015 if (x >= FRAME_LEFT_BORDER_END (f)
2016 && x < FRAME_RIGHT_BORDER_START (f)
2017 && y >= FRAME_TOP_BORDER_END (f)
2018 && y < FRAME_BOTTOM_BORDER_START (f))
2024 temp = WINDOW_FACE_CACHEL_BACKGROUND_PIXMAP (w, findex);
2026 if (IMAGE_INSTANCEP (temp)
2027 && IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (temp)))
2029 /* #### maybe we could implement such that a string
2030 can be a background pixmap? */
2031 background_pixmap = temp;
2036 temp = FACE_BACKGROUND_PIXMAP (Vdefault_face, locale);
2038 if (IMAGE_INSTANCEP (temp)
2039 && IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (temp)))
2041 background_pixmap = temp;
2045 if (!UNBOUNDP (background_pixmap) &&
2046 XIMAGE_INSTANCE_PIXMAP_DEPTH (background_pixmap) == 0)
2048 Lisp_Object fcolor, bcolor;
2052 fcolor = WINDOW_FACE_CACHEL_FOREGROUND (w, findex);
2053 bcolor = WINDOW_FACE_CACHEL_BACKGROUND (w, findex);
2057 fcolor = FACE_FOREGROUND (Vdefault_face, locale);
2058 bcolor = FACE_BACKGROUND (Vdefault_face, locale);
2061 gc = x_get_gc (d, Qnil, fcolor, bcolor, background_pixmap, Qnil);
2065 Lisp_Object color = (w ?
2066 WINDOW_FACE_CACHEL_BACKGROUND (w, findex) :
2067 FACE_BACKGROUND (Vdefault_face, locale));
2069 if (UNBOUNDP (background_pixmap))
2070 background_pixmap = Qnil;
2072 gc = x_get_gc (d, Qnil, color, Qnil, background_pixmap, Qnil);
2077 XFillRectangle (dpy, x_win, gc, x, y, width, height);
2079 XClearArea (dpy, x_win, x, y, width, height, False);
2083 /*****************************************************************************
2086 Draw a cursor at the end of a line. The end-of-line cursor is
2087 narrower than the normal cursor.
2088 ****************************************************************************/
2090 x_output_eol_cursor (struct window *w, struct display_line *dl, int xpos,
2093 struct frame *f = XFRAME (w->frame);
2094 struct device *d = XDEVICE (f->device);
2097 Display *dpy = DEVICE_X_DISPLAY (d);
2098 Window x_win = XtWindow (FRAME_X_TEXT_WIDGET (f));
2100 face_index elt = get_builtin_face_cache_index (w, Vtext_cursor_face);
2101 struct face_cachel *cursor_cachel = WINDOW_FACE_CACHEL (w, elt);
2103 int focus = EQ (w->frame, DEVICE_FRAME_WITH_FOCUS_REAL (d));
2104 Lisp_Object bar_cursor_value = symbol_value_in_buffer (Qbar_cursor,
2108 int y = dl->ypos - dl->ascent;
2109 int width = EOL_CURSOR_WIDTH;
2110 int height = dl->ascent + dl->descent - dl->clip;
2111 int cursor_height, cursor_y;
2112 int defheight, defascent;
2114 XSETWINDOW (window, w);
2115 x_clear_region (window, findex, x, y, width, height);
2117 if (NILP (w->text_cursor_visible_p))
2120 gc = x_get_gc (d, Qnil, cursor_cachel->background, Qnil, Qnil, Qnil);
2122 default_face_font_info (window, &defascent, 0, &defheight, 0, 0);
2124 /* make sure the cursor is entirely contained between y and y+height */
2125 cursor_height = min (defheight, height);
2126 cursor_y = max (y, min (y + height - cursor_height,
2127 dl->ypos - defascent));
2132 XIM_SetSpotLocation (f, x - 2 , cursor_y + cursor_height - 2);
2133 #endif /* HAVE_XIM */
2135 if (NILP (bar_cursor_value))
2137 XFillRectangle (dpy, x_win, gc, x, cursor_y, width, cursor_height);
2141 int bar_width = EQ (bar_cursor_value, Qt) ? 1 : 2;
2143 gc = x_get_gc (d, Qnil, cursor_cachel->background, Qnil, Qnil,
2144 make_int (bar_width));
2145 XDrawLine (dpy, x_win, gc, x + bar_width - 1, cursor_y,
2146 x + bar_width - 1, cursor_y + cursor_height - 1);
2149 else if (NILP (bar_cursor_value))
2151 XDrawRectangle (dpy, x_win, gc, x, cursor_y, width - 1,
2157 x_clear_frame_window (Lisp_Object window)
2159 struct window *w = XWINDOW (window);
2161 if (!NILP (w->vchild))
2163 x_clear_frame_windows (w->vchild);
2167 if (!NILP (w->hchild))
2169 x_clear_frame_windows (w->hchild);
2173 x_clear_to_window_end (w, WINDOW_TEXT_TOP (w), WINDOW_TEXT_BOTTOM (w));
2177 x_clear_frame_windows (Lisp_Object window)
2179 for (; !NILP (window); window = XWINDOW (window)->next)
2180 x_clear_frame_window (window);
2184 x_clear_frame (struct frame *f)
2186 struct device *d = XDEVICE (f->device);
2187 Display *dpy = DEVICE_X_DISPLAY (d);
2188 Window x_win = XtWindow (FRAME_X_TEXT_WIDGET (f));
2189 int x, y, width, height;
2192 x = FRAME_LEFT_BORDER_START (f);
2193 width = (FRAME_PIXWIDTH (f) - FRAME_REAL_LEFT_TOOLBAR_WIDTH (f) -
2194 FRAME_REAL_RIGHT_TOOLBAR_WIDTH (f) -
2195 2 * FRAME_REAL_LEFT_TOOLBAR_BORDER_WIDTH (f) -
2196 2 * FRAME_REAL_RIGHT_TOOLBAR_BORDER_WIDTH (f));
2197 /* #### This adjustment by 1 should be being done in the macros.
2198 There is some small differences between when the menubar is on
2199 and off that we still need to deal with. */
2200 y = FRAME_TOP_BORDER_START (f) - 1;
2201 height = (FRAME_PIXHEIGHT (f) - FRAME_REAL_TOP_TOOLBAR_HEIGHT (f) -
2202 FRAME_REAL_BOTTOM_TOOLBAR_HEIGHT (f) -
2203 2 * FRAME_REAL_TOP_TOOLBAR_BORDER_WIDTH (f) -
2204 2 * FRAME_REAL_BOTTOM_TOOLBAR_BORDER_WIDTH (f)) + 1;
2206 XClearArea (dpy, x_win, x, y, width, height, False);
2208 XSETFRAME (frame, f);
2210 if (!UNBOUNDP (FACE_BACKGROUND_PIXMAP (Vdefault_face, frame))
2211 || !UNBOUNDP (FACE_BACKGROUND_PIXMAP (Vleft_margin_face, frame))
2212 || !UNBOUNDP (FACE_BACKGROUND_PIXMAP (Vright_margin_face, frame)))
2214 x_clear_frame_windows (f->root_window);
2217 XFlush (DEVICE_X_DISPLAY (d));
2220 /* briefly swap the foreground and background colors.
2224 x_flash (struct device *d)
2230 XColor tmp_fcolor, tmp_bcolor;
2231 Lisp_Object tmp_pixel, frame;
2232 struct frame *f = device_selected_frame (d);
2233 struct window *w = XWINDOW (FRAME_ROOT_WINDOW (f));
2234 Widget shell = FRAME_X_SHELL_WIDGET (f);
2236 XSETFRAME (frame, f);
2238 tmp_pixel = FACE_FOREGROUND (Vdefault_face, frame);
2239 tmp_fcolor = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (tmp_pixel));
2240 tmp_pixel = FACE_BACKGROUND (Vdefault_face, frame);
2241 tmp_bcolor = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (tmp_pixel));
2243 dpy = XtDisplay (shell);
2244 win = XtWindow (FRAME_X_TEXT_WIDGET (f));
2245 memset (&gcv, ~0, sizeof (XGCValues)); /* initialize all slots to ~0 */
2246 gcv.foreground = (tmp_fcolor.pixel ^ tmp_bcolor.pixel);
2247 gcv.function = GXxor;
2248 gcv.graphics_exposures = False;
2249 gc = gc_cache_lookup (DEVICE_X_GC_CACHE (XDEVICE (f->device)), &gcv,
2250 (GCForeground | GCFunction | GCGraphicsExposures));
2251 XFillRectangle (dpy, win, gc, w->pixel_left, w->pixel_top,
2252 w->pixel_width, w->pixel_height);
2259 tv.tv_sec = usecs / 1000000L;
2260 tv.tv_usec = usecs % 1000000L;
2261 /* I'm sure someone is going to complain about this... */
2262 select (0, 0, 0, 0, &tv);
2267 #else /* !HAVE_POLL */
2269 #endif /* HAVE_POLL */
2270 #endif /* HAVE_SELECT */
2272 XFillRectangle (dpy, win, gc, w->pixel_left, w->pixel_top,
2273 w->pixel_width, w->pixel_height);
2279 /* Make audible bell. */
2282 x_ring_bell (struct device *d, int volume, int pitch, int duration)
2284 Display *display = DEVICE_X_DISPLAY (d);
2286 if (volume < 0) volume = 0;
2287 else if (volume > 100) volume = 100;
2288 if (pitch < 0 && duration < 0)
2290 XBell (display, (volume * 2) - 100);
2295 XKeyboardState state;
2296 XKeyboardControl ctl;
2298 /* #### grab server? */
2299 XGetKeyboardControl (display, &state);
2301 ctl.bell_pitch = (pitch >= 0 ? pitch : state.bell_pitch);
2302 ctl.bell_duration = (duration >= 0 ? duration : state.bell_duration);
2303 XChangeKeyboardControl (display, KBBellPitch|KBBellDuration, &ctl);
2305 XBell (display, (volume * 2) - 100);
2307 ctl.bell_pitch = state.bell_pitch;
2308 ctl.bell_duration = state.bell_duration;
2309 XChangeKeyboardControl (display, KBBellPitch|KBBellDuration, &ctl);
2311 /* #### ungrab server? */
2317 /************************************************************************/
2318 /* initialization */
2319 /************************************************************************/
2322 console_type_create_redisplay_x (void)
2324 /* redisplay methods */
2325 CONSOLE_HAS_METHOD (x, text_width);
2326 CONSOLE_HAS_METHOD (x, output_display_block);
2327 CONSOLE_HAS_METHOD (x, divider_height);
2328 CONSOLE_HAS_METHOD (x, eol_cursor_width);
2329 CONSOLE_HAS_METHOD (x, output_vertical_divider);
2330 CONSOLE_HAS_METHOD (x, clear_to_window_end);
2331 CONSOLE_HAS_METHOD (x, clear_region);
2332 CONSOLE_HAS_METHOD (x, clear_frame);
2333 CONSOLE_HAS_METHOD (x, output_begin);
2334 CONSOLE_HAS_METHOD (x, output_end);
2335 CONSOLE_HAS_METHOD (x, flash);
2336 CONSOLE_HAS_METHOD (x, ring_bell);