Mercurial > hg > xemacs-beta
annotate src/redisplay-x.c @ 4882:eab9498ecc0e
merge most of rest of redisplay-x.c and redisplay-gtk.c into redisplay-xlike-inc.c
-------------------- ChangeLog entries follow: --------------------
src/ChangeLog addition:
2010-01-18 Ben Wing <ben@xemacs.org>
* redisplay-gtk.c:
* redisplay-gtk.c (gtk_bevel_area):
* redisplay-x.c:
* redisplay-x.c (THIS_IS_X):
* redisplay-xlike-inc.c:
* redisplay-xlike-inc.c (XLIKE_text_width_single_run):
* redisplay-xlike-inc.c (XLIKE_text_width):
* redisplay-xlike-inc.c (XLIKE_output_display_block):
* redisplay-xlike-inc.c (XLIKE_get_gc):
* redisplay-xlike-inc.c (XLIKE_output_string):
* redisplay-xlike-inc.c (XLIKE_OUTPUT_XLIKE_PIXMAP):
* redisplay-xlike-inc.c (XLIKE_output_pixmap):
* redisplay-xlike-inc.c (XLIKE_output_vertical_divider):
* redisplay-xlike-inc.c (XLIKE_output_blank):
* redisplay-xlike-inc.c (XLIKE_output_horizontal_line):
* redisplay-xlike-inc.c (XLIKE_clear_region):
* redisplay-xlike-inc.c (XLIKE_output_eol_cursor):
* redisplay-xlike-inc.c (XLIKE_clear_frame_window):
* redisplay-xlike-inc.c (XLIKE_clear_frame):
* redisplay-xlike-inc.c (XLIKE_flash):
* redisplay-xlike-inc.c (console_type_create_redisplay_XLIKE):
Move lots more code into redisplay-xlike-inc.c. Use macros to
isolate the code that differs among X vs. GTK, to reduce the need
for ifdefs in the middle of the code. Now, redisplay-x.c and
redisplay-gtk.c only contain a few functions whose implementation
is completely different from one to the other, or which are not
present at all in one of them.
GTK code not currently tested, but it has bitrotted somewhat
any. Doing this will help keep it less bitrotty.
* depend: Regenerate.
author | Ben Wing <ben@xemacs.org> |
---|---|
date | Mon, 18 Jan 2010 08:44:49 -0600 |
parents | a4322ac49e37 |
children | b3ce27ca7647 |
rev | line source |
---|---|
428 | 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. | |
1318 | 5 Copyright (C) 2002, 2003 Ben Wing. |
428 | 6 |
7 This file is part of XEmacs. | |
8 | |
9 XEmacs is free software; you can redistribute it and/or modify it | |
10 under the terms of the GNU General Public License as published by the | |
11 Free Software Foundation; either version 2, or (at your option) any | |
12 later version. | |
13 | |
14 XEmacs is distributed in the hope that it will be useful, but WITHOUT | |
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
17 for more details. | |
18 | |
19 You should have received a copy of the GNU General Public License | |
20 along with XEmacs; see the file COPYING. If not, write to | |
21 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
22 Boston, MA 02111-1307, USA. */ | |
23 | |
24 /* Synched up with: Not in FSF. */ | |
25 | |
26 /* Author: Chuck Thompson */ | |
27 | |
28 /* Lots of work done by Ben Wing for Mule */ | |
29 | |
30 | |
31 /* Number of pixels below each line. */ | |
3094 | 32 int x_interline_space; /* #### this needs to be implemented, but per-font */ |
428 | 33 |
4882
eab9498ecc0e
merge most of rest of redisplay-x.c and redisplay-gtk.c into redisplay-xlike-inc.c
Ben Wing <ben@xemacs.org>
parents:
4881
diff
changeset
|
34 #define THIS_IS_X |
3094 | 35 |
4881
a4322ac49e37
break out common separate-into-runs routines into redisplay-xlike-inc.c
Ben Wing <ben@xemacs.org>
parents:
4827
diff
changeset
|
36 #include "redisplay-xlike-inc.c" |
428 | 37 |
38 /***************************************************************************** | |
442 | 39 x_window_output_begin |
428 | 40 |
41 Perform any necessary initialization prior to an update. | |
42 ****************************************************************************/ | |
43 static void | |
2286 | 44 x_window_output_begin (struct window *UNUSED (w)) |
428 | 45 { |
46 } | |
47 | |
48 /***************************************************************************** | |
442 | 49 x_window_output_end |
428 | 50 |
51 Perform any necessary flushing of queues when an update has completed. | |
52 ****************************************************************************/ | |
53 static void | |
442 | 54 x_window_output_end (struct window *w) |
428 | 55 { |
1204 | 56 if (!(check_if_pending_expose_event (WINDOW_XDEVICE (w)))) |
57 XFlush (DEVICE_X_DISPLAY (WINDOW_XDEVICE (w))); | |
428 | 58 } |
59 | |
60 /***************************************************************************** | |
61 x_bevel_area | |
62 | |
450 | 63 Draw shadows for the given area in the given face. |
428 | 64 ****************************************************************************/ |
65 static void | |
66 x_bevel_area (struct window *w, face_index findex, | |
67 int x, int y, int width, int height, | |
68 int shadow_thickness, int edges, enum edge_style style) | |
69 { | |
70 struct frame *f = XFRAME (w->frame); | |
71 struct device *d = XDEVICE (f->device); | |
72 | |
73 EmacsFrame ef = (EmacsFrame) FRAME_X_TEXT_WIDGET (f); | |
74 Display *dpy = DEVICE_X_DISPLAY (d); | |
75 Window x_win = XtWindow (FRAME_X_TEXT_WIDGET (f)); | |
76 Pixel top_shadow_pixel, bottom_shadow_pixel, background_pixel; | |
77 Lisp_Object tmp_pixel; | |
78 XColor tmp_color; | |
79 XGCValues gcv; | |
80 GC top_shadow_gc, bottom_shadow_gc, background_gc; | |
81 | |
82 int use_pixmap = 0; | |
83 int flip_gcs = 0; | |
84 unsigned long mask; | |
85 | |
86 assert (shadow_thickness >=0); | |
87 memset (&gcv, ~0, sizeof (XGCValues)); | |
88 | |
89 tmp_pixel = WINDOW_FACE_CACHEL_BACKGROUND (w, findex); | |
90 tmp_color = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (tmp_pixel)); | |
91 | |
92 /* First, get the GC's. */ | |
93 top_shadow_pixel = tmp_color.pixel; | |
94 bottom_shadow_pixel = tmp_color.pixel; | |
95 background_pixel = tmp_color.pixel; | |
96 | |
97 x_generate_shadow_pixels (f, &top_shadow_pixel, &bottom_shadow_pixel, | |
98 background_pixel, ef->core.background_pixel); | |
99 | |
100 tmp_pixel = WINDOW_FACE_CACHEL_FOREGROUND (w, findex); | |
101 tmp_color = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (tmp_pixel)); | |
102 gcv.background = tmp_color.pixel; | |
103 gcv.graphics_exposures = False; | |
104 mask = GCForeground | GCBackground | GCGraphicsExposures; | |
105 | |
106 /* If we can't distinguish one of the shadows (the color is the same as the | |
107 background), it's better to use a pixmap to generate a dithered gray. */ | |
108 if (top_shadow_pixel == background_pixel || | |
109 bottom_shadow_pixel == background_pixel) | |
110 use_pixmap = 1; | |
111 | |
112 if (use_pixmap) | |
113 { | |
114 if (DEVICE_X_GRAY_PIXMAP (d) == None) | |
115 { | |
116 DEVICE_X_GRAY_PIXMAP (d) = | |
117 XCreatePixmapFromBitmapData (dpy, x_win, (char *) gray_bits, | |
118 gray_width, gray_height, 1, 0, 1); | |
119 } | |
120 | |
121 tmp_pixel = WINDOW_FACE_CACHEL_BACKGROUND (w, findex); | |
122 tmp_color = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (tmp_pixel)); | |
123 gcv.foreground = tmp_color.pixel; | |
124 /* this is needed because the GC draws with a pixmap here */ | |
125 gcv.fill_style = FillOpaqueStippled; | |
126 gcv.stipple = DEVICE_X_GRAY_PIXMAP (d); | |
127 top_shadow_gc = gc_cache_lookup (DEVICE_X_GC_CACHE (d), &gcv, | |
128 (mask | GCStipple | GCFillStyle)); | |
129 | |
130 tmp_pixel = WINDOW_FACE_CACHEL_FOREGROUND (w, findex); | |
131 tmp_color = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (tmp_pixel)); | |
132 bottom_shadow_pixel = tmp_color.pixel; | |
133 | |
134 flip_gcs = (bottom_shadow_pixel == | |
135 WhitePixelOfScreen (DefaultScreenOfDisplay (dpy))); | |
136 } | |
137 else | |
138 { | |
139 gcv.foreground = top_shadow_pixel; | |
140 top_shadow_gc = gc_cache_lookup (DEVICE_X_GC_CACHE (d), &gcv, mask); | |
141 } | |
142 | |
143 gcv.foreground = bottom_shadow_pixel; | |
144 bottom_shadow_gc = gc_cache_lookup (DEVICE_X_GC_CACHE (d), &gcv, mask); | |
145 | |
146 if (use_pixmap && flip_gcs) | |
147 { | |
148 GC tmp_gc = bottom_shadow_gc; | |
149 bottom_shadow_gc = top_shadow_gc; | |
150 top_shadow_gc = tmp_gc; | |
151 } | |
152 | |
153 gcv.foreground = background_pixel; | |
154 background_gc = gc_cache_lookup (DEVICE_X_GC_CACHE (d), &gcv, mask); | |
155 | |
156 /* possibly revert the GC's This will give a depressed look to the | |
157 divider */ | |
158 if (style == EDGE_ETCHED_IN || style == EDGE_BEVEL_IN) | |
159 { | |
160 GC temp; | |
161 | |
162 temp = top_shadow_gc; | |
163 top_shadow_gc = bottom_shadow_gc; | |
164 bottom_shadow_gc = temp; | |
165 } | |
166 | |
167 if (style == EDGE_ETCHED_IN || style == EDGE_ETCHED_OUT) | |
168 shadow_thickness /= 2; | |
169 | |
170 /* Draw the shadows around the divider line */ | |
171 x_output_shadows (f, x, y, width, height, | |
172 top_shadow_gc, bottom_shadow_gc, | |
173 background_gc, shadow_thickness, edges); | |
174 | |
175 if (style == EDGE_ETCHED_IN || style == EDGE_ETCHED_OUT) | |
176 { | |
177 /* Draw the shadows around the divider line */ | |
178 x_output_shadows (f, x + shadow_thickness, y + shadow_thickness, | |
179 width - 2*shadow_thickness, height - 2*shadow_thickness, | |
180 bottom_shadow_gc, top_shadow_gc, | |
181 background_gc, shadow_thickness, edges); | |
182 } | |
183 } | |
184 | |
185 /***************************************************************************** | |
186 x_output_shadows | |
187 | |
188 Draw a shadow around the given area using the given GC's. It is the | |
189 callers responsibility to set the GC's appropriately. | |
190 ****************************************************************************/ | |
191 void | |
192 x_output_shadows (struct frame *f, int x, int y, int width, int height, | |
2286 | 193 GC top_shadow_gc, GC bottom_shadow_gc, |
194 GC UNUSED (background_gc), int shadow_thickness, int edges) | |
428 | 195 { |
196 struct device *d = XDEVICE (f->device); | |
197 | |
198 Display *dpy = DEVICE_X_DISPLAY (d); | |
199 Window x_win = XtWindow (FRAME_X_TEXT_WIDGET (f)); | |
200 | |
201 XSegment top_shadow[20], bottom_shadow[20]; | |
202 int elt; | |
203 | |
204 if (shadow_thickness > 10) | |
205 shadow_thickness = 10; | |
206 else if (shadow_thickness < 0) | |
207 shadow_thickness = 0; | |
208 if (shadow_thickness > (width / 2)) | |
209 shadow_thickness = width / 2; | |
210 if (shadow_thickness > (height / 2)) | |
211 shadow_thickness = height / 2; | |
212 | |
213 for (elt = 0; elt < shadow_thickness; elt++) | |
214 { | |
215 int seg1 = elt; | |
216 int seg2 = (edges & EDGE_TOP) ? elt + shadow_thickness : elt; | |
217 int bot_seg2 = (edges & EDGE_BOTTOM) ? elt + shadow_thickness : elt; | |
218 | |
219 if (edges & EDGE_TOP) | |
220 { | |
221 top_shadow[seg1].x1 = x + elt; | |
222 top_shadow[seg1].x2 = x + width - elt - 1; | |
223 top_shadow[seg1].y1 = top_shadow[seg1].y2 = y + elt; | |
224 } | |
225 if (edges & EDGE_LEFT) | |
226 { | |
227 top_shadow[seg2].x1 = top_shadow[seg2].x2 = x + elt; | |
228 top_shadow[seg2].y1 = y + elt; | |
229 top_shadow[seg2].y2 = y + height - elt - 1; | |
230 } | |
231 if (edges & EDGE_BOTTOM) | |
232 { | |
233 bottom_shadow[seg1].x1 = x + elt; | |
234 bottom_shadow[seg1].x2 = x + width - elt - 1; | |
235 bottom_shadow[seg1].y1 = bottom_shadow[seg1].y2 = y + height - elt - 1; | |
236 } | |
237 if (edges & EDGE_RIGHT) | |
238 { | |
239 bottom_shadow[bot_seg2].x1 = bottom_shadow[bot_seg2].x2 = x + width - elt - 1; | |
240 bottom_shadow[bot_seg2].y1 = y + elt; | |
241 bottom_shadow[bot_seg2].y2 = y + height - elt - 1; | |
242 } | |
243 } | |
244 | |
245 XDrawSegments (dpy, x_win, top_shadow_gc, top_shadow, | |
246 ((edges & EDGE_TOP) ? shadow_thickness : 0) | |
247 + ((edges & EDGE_LEFT) ? shadow_thickness : 0)); | |
248 XDrawSegments (dpy, x_win, bottom_shadow_gc, bottom_shadow, | |
249 ((edges & EDGE_BOTTOM) ? shadow_thickness : 0) | |
250 + ((edges & EDGE_RIGHT) ? shadow_thickness : 0)); | |
251 } | |
252 | |
253 /***************************************************************************** | |
254 x_generate_shadow_pixels | |
255 | |
256 Given three pixels (top shadow, bottom shadow, background) massage | |
257 the top and bottom shadow colors to guarantee that they differ. The | |
258 background pixels are not allowed to be modified. | |
259 | |
260 This function modifies its parameters. | |
261 | |
262 This code is modified from code blatantly stolen from lwlib/xlwmenu.c | |
263 ****************************************************************************/ | |
264 #define MINL(x,y) ((((unsigned long) (x)) < ((unsigned long) (y))) \ | |
265 ? ((unsigned long) (x)) : ((unsigned long) (y))) | |
266 | |
267 void | |
268 x_generate_shadow_pixels (struct frame *f, unsigned long *top_shadow, | |
269 unsigned long *bottom_shadow, | |
270 unsigned long background, | |
271 unsigned long core_background) | |
272 { | |
273 struct device *d = XDEVICE (f->device); | |
274 Display *dpy = DEVICE_X_DISPLAY (d); | |
275 Colormap cmap = DEVICE_X_COLORMAP (d); | |
276 Visual *visual = DEVICE_X_VISUAL (d); | |
277 | |
278 XColor topc, botc; | |
279 int top_frobbed = 0, bottom_frobbed = 0; | |
280 | |
281 /* If the top shadow is the same color as the background, try to | |
282 adjust it. */ | |
283 if (*top_shadow == background) | |
284 { | |
285 topc.pixel = background; | |
286 XQueryColor (dpy, cmap, &topc); | |
287 /* don't overflow/wrap! */ | |
288 topc.red = MINL (65535, (unsigned long) topc.red * 6 / 5); | |
289 topc.green = MINL (65535, (unsigned long) topc.green * 6 / 5); | |
290 topc.blue = MINL (65535, (unsigned long) topc.blue * 6 / 5); | |
3094 | 291 if (x_allocate_nearest_color (dpy, cmap, visual, &topc)) |
428 | 292 { |
293 *top_shadow = topc.pixel; | |
294 top_frobbed = 1; | |
295 } | |
296 } | |
297 | |
298 /* If the bottom shadow is the same color as the background, try to | |
299 adjust it. */ | |
300 if (*bottom_shadow == background) | |
301 { | |
302 botc.pixel = background; | |
303 XQueryColor (dpy, cmap, &botc); | |
304 botc.red = (unsigned short) ((unsigned long) botc.red * 3 / 5); | |
305 botc.green = (unsigned short) ((unsigned long) botc.green * 3 / 5); | |
306 botc.blue = (unsigned short) ((unsigned long) botc.blue * 3 / 5); | |
3094 | 307 if (x_allocate_nearest_color (dpy, cmap, visual, &botc)) |
428 | 308 { |
309 *bottom_shadow = botc.pixel; | |
310 bottom_frobbed = 1; | |
311 } | |
312 } | |
313 | |
314 /* If we had to adjust both shadows, then we have to do some | |
315 additional work. */ | |
316 if (top_frobbed && bottom_frobbed) | |
317 { | |
318 int top_avg = ((topc.red / 3) + (topc.green / 3) + (topc.blue / 3)); | |
319 int bot_avg = ((botc.red / 3) + (botc.green / 3) + (botc.blue / 3)); | |
320 if (bot_avg > top_avg) | |
321 { | |
322 Pixel tmp = *top_shadow; | |
323 | |
324 *top_shadow = *bottom_shadow; | |
325 *bottom_shadow = tmp; | |
326 } | |
327 else if (topc.pixel == botc.pixel) | |
328 { | |
329 if (botc.pixel == background) | |
330 *top_shadow = core_background; | |
331 else | |
332 *bottom_shadow = background; | |
333 } | |
334 } | |
335 } | |
336 | |
337 | |
338 /* Make audible bell. */ | |
339 | |
340 static void | |
341 x_ring_bell (struct device *d, int volume, int pitch, int duration) | |
342 { | |
343 Display *display = DEVICE_X_DISPLAY (d); | |
344 | |
345 if (volume < 0) volume = 0; | |
346 else if (volume > 100) volume = 100; | |
347 if (pitch < 0 && duration < 0) | |
348 { | |
349 XBell (display, (volume * 2) - 100); | |
350 XFlush (display); | |
351 } | |
352 else | |
353 { | |
354 XKeyboardState state; | |
355 XKeyboardControl ctl; | |
356 XSync (display, 0); | |
357 /* #### grab server? */ | |
358 XGetKeyboardControl (display, &state); | |
359 | |
664 | 360 ctl.bell_pitch = (pitch >= 0 ? pitch : (int) state.bell_pitch); |
361 ctl.bell_duration = (duration >= 0 ? duration : (int) state.bell_duration); | |
428 | 362 XChangeKeyboardControl (display, KBBellPitch|KBBellDuration, &ctl); |
363 | |
364 XBell (display, (volume * 2) - 100); | |
365 | |
366 ctl.bell_pitch = state.bell_pitch; | |
367 ctl.bell_duration = state.bell_duration; | |
368 XChangeKeyboardControl (display, KBBellPitch|KBBellDuration, &ctl); | |
369 | |
370 /* #### ungrab server? */ | |
371 XSync (display, 0); | |
372 } | |
373 } |