Mercurial > hg > xemacs-beta
annotate src/toolbar-xlike.c @ 5283:be436ac36ba4
Don't share a counter when checking for circularity, list_merge().
src/ChangeLog addition:
2010-10-12 Aidan Kehoe <kehoea@parhasard.net>
* fns.c (list_merge):
Circularity checking here needs to be done independently for each
list, they can't share a loop counter. Thank you for the bug
report, Robert Pluim!
tests/ChangeLog addition:
2010-10-12 Aidan Kehoe <kehoea@parhasard.net>
* automated/lisp-tests.el:
Make sure circularity checking with #'merge is sane.
author | Aidan Kehoe <kehoea@parhasard.net> |
---|---|
date | Tue, 12 Oct 2010 18:14:12 +0100 |
parents | d372b17f63ce |
children | 308d34e9f07d |
rev | line source |
---|---|
771 | 1 /* toolbar implementation -- "Generic" (X or GTK) redisplay interface. |
713 | 2 Copyright (C) 1995 Board of Trustees, University of Illinois. |
3 Copyright (C) 1995 Sun Microsystems, Inc. | |
4917 | 4 Copyright (C) 1995, 1996, 2002, 2010 Ben Wing. |
713 | 5 Copyright (C) 1996 Chuck Thompson. |
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 #include <config.h> | |
27 #include "lisp.h" | |
28 | |
872 | 29 #include "device-impl.h" |
713 | 30 #include "faces.h" |
872 | 31 #include "frame-impl.h" |
800 | 32 #include "glyphs.h" |
713 | 33 #include "toolbar.h" |
34 #include "window.h" | |
35 | |
771 | 36 /* This is used when we need to draw the toolbars ourselves -- on X or GTK. |
37 On MS Windows, we use the built-in toolbar controls. */ | |
38 | |
713 | 39 /* Only a very few things need to differ based on the toolkit used. |
40 ** | |
5077
d372b17f63ce
clean up toolbar/gutter edge geometry
Ben Wing <ben@xemacs.org>
parents:
4969
diff
changeset
|
41 ** Some of the routines used assert (FRAME_yyy_P(f)) checks, this is |
713 | 42 ** now abstracted into __INTERNAL_APPROPRIATENESS_CHECK(). When we |
43 ** add new window systems that use this code, we should either add a | |
44 ** new case here, or just remove the checks completely. | |
45 ** | |
46 ** At least for X & GTK redraw_frame_toolbars() might end up getting | |
47 ** called before we are completely initialized. To avoid this, we use | |
5077
d372b17f63ce
clean up toolbar/gutter edge geometry
Ben Wing <ben@xemacs.org>
parents:
4969
diff
changeset
|
48 ** the __INTERNAL_MAPPED_P (f) macro, that should return 0 if we should |
713 | 49 ** not draw the toolbars yet. When we add new window systems that use |
50 ** this code, we should add a new case here, if they need it. | |
51 ** | |
52 ** When clearing the toolbar, it is nice to flush the drawing queue. | |
53 ** Use __INTERNAL_FLUSH to do this. It is passed a device. | |
54 */ | |
55 #if defined(HAVE_GTK) | |
872 | 56 #include "console-gtk-impl.h" |
713 | 57 #define __INTERNAL_MAPPED_P(f) GTK_WIDGET_REALIZED (FRAME_GTK_TEXT_WIDGET (f)) |
58 #define __INTERNAL_FLUSH(d) gdk_flush() | |
59 #define __INTERNAL_APPROPRIATENESS_CHECK(f) assert(FRAME_GTK_P (f)) | |
60 #elif defined(HAVE_X_WINDOWS) | |
872 | 61 #include "console-x-impl.h" |
713 | 62 #define __INTERNAL_MAPPED_P(f) XtIsRealized (FRAME_X_SHELL_WIDGET (f)) |
63 #define __INTERNAL_APPROPRIATENESS_CHECK(f) assert(FRAME_X_P (f)) | |
64 #define __INTERNAL_FLUSH(d) XFlush (DEVICE_X_DISPLAY (d)) | |
65 #else | |
2500 | 66 #define __INTERNAL_MAPPED_P(f) ABORT() |
67 #define __INTERNAL_APPROPRIATENESS_CHECK(f) ABORT() | |
68 #define __INTERNAL_FLUSH(f) ABORT() | |
713 | 69 #endif |
70 | |
4917 | 71 #include "toolbar-xlike.h" |
713 | 72 |
744 | 73 extern Lisp_Object Vtoolbar_shadow_thickness; |
74 | |
713 | 75 static void __prepare_button_area (struct frame *f, |
76 struct toolbar_button *tb) | |
77 { | |
78 int sx = tb->x; | |
79 int sy = tb->y; | |
80 int swidth = tb->width; | |
81 int sheight = tb->height; | |
82 int border_width = tb->border_width; | |
83 int x_adj, width_adj, y_adj, height_adj; | |
84 struct device *d = XDEVICE (f->device); | |
85 Lisp_Object window = FRAME_LAST_NONMINIBUF_WINDOW (f); | |
86 struct window *w = XWINDOW (window); | |
744 | 87 int shadow_thickness; |
5077
d372b17f63ce
clean up toolbar/gutter edge geometry
Ben Wing <ben@xemacs.org>
parents:
4969
diff
changeset
|
88 int def_shadow_thickness = XINT (Fspecifier_instance (Vtoolbar_shadow_thickness, window, Qnil, Qnil)); |
713 | 89 face_index toolbar_findex; |
90 | |
91 if (tb->vertical) | |
92 { | |
93 x_adj = border_width; | |
94 width_adj = - 2 * border_width; | |
95 y_adj = height_adj = 0; | |
96 } | |
97 else | |
98 { | |
99 x_adj = width_adj = 0; | |
100 y_adj = border_width; | |
101 height_adj = - 2 * border_width; | |
102 } | |
103 | |
104 toolbar_findex = get_builtin_face_cache_index (w, Vtoolbar_face); | |
105 | |
5077
d372b17f63ce
clean up toolbar/gutter edge geometry
Ben Wing <ben@xemacs.org>
parents:
4969
diff
changeset
|
106 /* Blank toolbar buttons that should be 3d will have EQ (tb->up_glyph, Qt) |
713 | 107 ** Blank toolbar buttons that should be flat will have NILP (tb->up_glyph) |
108 ** | |
109 ** Real toolbar buttons will check tb->enabled && tb->down | |
110 */ | |
111 if (EQ (Qt, tb->up_glyph)) | |
112 { | |
744 | 113 shadow_thickness = def_shadow_thickness; |
713 | 114 } |
115 else if (NILP (tb->up_glyph)) | |
116 { | |
117 shadow_thickness = 0; | |
118 } | |
119 else | |
120 { | |
121 if (tb->enabled) | |
122 { | |
123 if (tb->down) | |
744 | 124 shadow_thickness = -def_shadow_thickness; |
713 | 125 else |
744 | 126 shadow_thickness = def_shadow_thickness; |
713 | 127 } |
128 else | |
129 { | |
130 shadow_thickness = 0; | |
131 } | |
132 } | |
133 | |
134 /* Blank the entire area. */ | |
135 redisplay_clear_region (window, toolbar_findex, | |
136 sx + x_adj, sy + y_adj, | |
137 swidth + width_adj, | |
138 sheight + height_adj); | |
139 | |
140 /* Draw the outline. */ | |
141 if (shadow_thickness) | |
142 { | |
143 MAYBE_DEVMETH (d, bevel_area, | |
144 (w, toolbar_findex, sx + x_adj, | |
145 sy + y_adj, swidth + width_adj, | |
5077
d372b17f63ce
clean up toolbar/gutter edge geometry
Ben Wing <ben@xemacs.org>
parents:
4969
diff
changeset
|
146 sheight + height_adj, abs (shadow_thickness), |
3094 | 147 EDGE_ALL, (shadow_thickness < 0) ? EDGE_BEVEL_IN |
148 : EDGE_BEVEL_OUT)); | |
713 | 149 } |
150 | |
151 /* Handle the borders... */ | |
152 redisplay_clear_region (window, toolbar_findex, | |
153 sx, sy, | |
154 (tb->vertical ? border_width : swidth), | |
155 (tb->vertical ? sheight : border_width)); | |
156 redisplay_clear_region (window, toolbar_findex, | |
157 (tb->vertical ? sx + swidth : sx), | |
158 (tb->vertical ? sy : sy + sheight), | |
159 (tb->vertical ? border_width : swidth), | |
160 (tb->vertical ? sheight : border_width)); | |
161 } | |
162 | |
4917 | 163 #define xlike_draw_blank_toolbar_button(f,tb) __prepare_button_area (f,tb) |
713 | 164 |
165 void | |
4917 | 166 xlike_output_toolbar_button (struct frame *f, Lisp_Object button) |
713 | 167 { |
168 int shadow_thickness = 2; | |
169 int x_adj, y_adj, width_adj, height_adj; | |
170 struct device *d = XDEVICE (f->device); | |
2212 | 171 Lisp_Object instance, window, glyph; |
713 | 172 struct toolbar_button *tb = XTOOLBAR_BUTTON (button); |
173 struct Lisp_Image_Instance *p; | |
174 struct window *w; | |
175 int vertical = tb->vertical; | |
176 int border_width = tb->border_width; | |
3094 | 177 face_index button_findex; |
713 | 178 |
179 if (vertical) | |
180 { | |
181 x_adj = border_width; | |
182 width_adj = - 2 * border_width; | |
183 y_adj = 0; | |
184 height_adj = 0; | |
185 } | |
186 else | |
187 { | |
188 x_adj = 0; | |
189 width_adj = 0; | |
190 y_adj = border_width; | |
191 height_adj = - 2 * border_width; | |
192 } | |
193 | |
194 window = FRAME_LAST_NONMINIBUF_WINDOW (f); | |
195 w = XWINDOW (window); | |
196 | |
197 glyph = get_toolbar_button_glyph (w, tb); | |
198 | |
199 if (tb->enabled) | |
200 { | |
201 if (tb->down) | |
202 { | |
203 shadow_thickness = -2; | |
204 } | |
205 else | |
206 { | |
207 shadow_thickness = 2; | |
208 } | |
209 } | |
210 else | |
211 { | |
212 shadow_thickness = 0; | |
213 } | |
214 | |
215 /* #### It is currently possible for users to trash us by directly | |
216 changing the toolbar glyphs. Avoid crashing in that case. */ | |
217 if (GLYPHP (glyph)) | |
3094 | 218 { |
219 /* WARNING: this interface may change */ | |
220 Lisp_Object face_list[2] = { XGLYPH_FACE (glyph), Vtoolbar_face }; | |
221 | |
222 button_findex = merge_face_list_to_cache_index (w, face_list, 2); | |
223 instance = glyph_image_instance (glyph, window, ERROR_ME_DEBUG_WARN, 1); | |
224 } | |
713 | 225 else |
3094 | 226 { |
227 button_findex = get_builtin_face_cache_index (w, Vtoolbar_face); | |
228 instance = Qnil; | |
229 } | |
230 | |
231 __prepare_button_area (f, tb); | |
713 | 232 |
233 if (IMAGE_INSTANCEP (instance)) | |
234 { | |
235 int width = tb->width + width_adj - shadow_thickness * 2; | |
236 int height = tb->height + height_adj - shadow_thickness * 2; | |
237 int x_offset = x_adj + shadow_thickness; | |
238 int y_offset = y_adj + shadow_thickness; | |
239 | |
240 p = XIMAGE_INSTANCE (instance); | |
241 | |
242 if (IMAGE_INSTANCE_PIXMAP_TYPE_P (p)) | |
243 { | |
244 struct display_box db; | |
245 struct display_glyph_area dga; | |
246 | |
247 if (width > (int) IMAGE_INSTANCE_PIXMAP_WIDTH (p)) | |
248 { | |
249 x_offset += ((int) (width - IMAGE_INSTANCE_PIXMAP_WIDTH (p)) | |
250 / 2); | |
251 width = IMAGE_INSTANCE_PIXMAP_WIDTH (p); | |
252 } | |
253 if (height > (int) IMAGE_INSTANCE_PIXMAP_HEIGHT (p)) | |
254 { | |
255 y_offset += ((int) (height - IMAGE_INSTANCE_PIXMAP_HEIGHT (p)) | |
256 / 2); | |
257 height = IMAGE_INSTANCE_PIXMAP_HEIGHT (p); | |
258 } | |
259 | |
260 /* Draw exactly in the area specified... */ | |
261 db.xpos = tb->x + x_offset; | |
262 db.ypos = tb->y + y_offset; | |
263 db.width = width; | |
264 db.height = height; | |
265 | |
266 /* Display the whole glyph */ | |
267 dga.xoffset = 0; | |
268 dga.yoffset = 0; | |
269 dga.width = width; | |
270 dga.height = height; | |
271 | |
272 redisplay_output_pixmap (w, instance, | |
273 &db, &dga, | |
3094 | 274 button_findex, 0, 0, 0, 0); |
713 | 275 } |
276 else if (IMAGE_INSTANCE_TYPE (p) == IMAGE_TEXT) | |
277 { | |
278 /* #### We need to make the face used configurable. */ | |
279 struct face_cachel *cachel = | |
280 WINDOW_FACE_CACHEL (w, DEFAULT_INDEX); | |
281 struct display_line dl; | |
282 Lisp_Object string = IMAGE_INSTANCE_TEXT_STRING (p); | |
283 unsigned char charsets[NUM_LEADING_BYTES]; | |
867 | 284 Ichar_dynarr *buf; |
713 | 285 struct font_metric_info fm; |
286 | |
287 /* This could be true if we were called via the Expose event | |
288 handler. Mark the button as dirty and return | |
289 immediately. */ | |
290 if (f->window_face_cache_reset) | |
291 { | |
292 tb->dirty = 1; | |
293 MARK_TOOLBAR_CHANGED; | |
294 return; | |
295 } | |
867 | 296 buf = Dynarr_new (Ichar); |
297 convert_ibyte_string_into_ichar_dynarr | |
713 | 298 (XSTRING_DATA (string), XSTRING_LENGTH (string), buf); |
4967 | 299 find_charsets_in_ichar_string (charsets, Dynarr_begin (buf), |
713 | 300 Dynarr_length (buf)); |
301 ensure_face_cachel_complete (cachel, window, charsets); | |
302 face_cachel_charset_font_metric_info (cachel, charsets, &fm); | |
303 | |
304 dl.ascent = fm.ascent; | |
305 dl.descent = fm.descent; | |
306 dl.ypos = tb->y + y_offset + fm.ascent; | |
307 | |
308 if (fm.ascent + fm.descent <= height) | |
309 { | |
310 dl.ypos += (height - fm.ascent - fm.descent) / 2; | |
311 dl.clip = 0; | |
312 } | |
313 else | |
314 { | |
315 dl.clip = fm.ascent + fm.descent - height; | |
316 } | |
317 | |
318 MAYBE_DEVMETH (d, output_string, | |
319 (w, &dl, buf, tb->x + x_offset, 0, 0, width, | |
3094 | 320 button_findex, 0, 0, 0, 0)); |
713 | 321 Dynarr_free (buf); |
322 } | |
323 | |
324 /* We silently ignore the image if it isn't a pixmap or text. */ | |
325 } | |
326 | |
327 tb->dirty = 0; | |
328 } | |
329 | |
330 static int | |
4917 | 331 xlike_get_button_size (struct frame *f, Lisp_Object window, |
713 | 332 struct toolbar_button *tb, int vert, int pos) |
333 { | |
334 int shadow_thickness = 2; | |
335 int size; | |
336 | |
337 if (tb->blank) | |
338 { | |
339 if (!NILP (tb->down_glyph)) | |
340 size = XINT (tb->down_glyph); | |
341 else | |
342 size = DEFAULT_TOOLBAR_BLANK_SIZE; | |
343 } | |
344 else | |
345 { | |
346 struct window *w = XWINDOW (window); | |
347 Lisp_Object glyph = get_toolbar_button_glyph (w, tb); | |
348 | |
349 /* Unless, of course, the user has done something stupid like | |
350 change the glyph out from under us. Use a blank placeholder | |
351 in that case. */ | |
352 if (NILP (glyph)) | |
353 return XINT (f->toolbar_size[pos]); | |
354 | |
355 if (vert) | |
356 size = glyph_height (glyph, window); | |
357 else | |
358 size = glyph_width (glyph, window); | |
359 } | |
360 | |
361 if (!size) | |
362 { | |
363 /* If the glyph doesn't have a size we'll insert a blank | |
364 placeholder instead. */ | |
365 return XINT (f->toolbar_size[pos]); | |
366 } | |
367 | |
368 size += shadow_thickness * 2; | |
369 | |
370 return (size); | |
371 } | |
372 | |
5077
d372b17f63ce
clean up toolbar/gutter edge geometry
Ben Wing <ben@xemacs.org>
parents:
4969
diff
changeset
|
373 #define XLIKE_OUTPUT_BUTTONS_LOOP(left) \ |
713 | 374 do { \ |
375 while (!NILP (button)) \ | |
376 { \ | |
377 struct toolbar_button *tb = XTOOLBAR_BUTTON (button); \ | |
378 int size, height, width; \ | |
379 \ | |
380 if (left && tb->pushright) \ | |
381 break; \ | |
382 \ | |
4917 | 383 size = xlike_get_button_size (f, window, tb, vert, pos); \ |
713 | 384 \ |
385 if (vert) \ | |
386 { \ | |
387 width = bar_width; \ | |
388 if (y + size > max_pixpos) \ | |
389 height = max_pixpos - y; \ | |
390 else \ | |
391 height = size; \ | |
392 } \ | |
393 else \ | |
394 { \ | |
395 if (x + size > max_pixpos) \ | |
396 width = max_pixpos - x; \ | |
397 else \ | |
398 width = size; \ | |
399 height = bar_height; \ | |
400 } \ | |
401 \ | |
402 if (tb->x != x \ | |
403 || tb->y != y \ | |
404 || tb->width != width \ | |
405 || tb->height != height \ | |
905 | 406 || tb->dirty \ |
407 || f->clear) /* This is clearly necessary. */ \ | |
713 | 408 { \ |
409 if (width && height) \ | |
410 { \ | |
411 tb->x = x; \ | |
412 tb->y = y; \ | |
413 tb->width = width; \ | |
414 tb->height = height; \ | |
415 tb->border_width = border_width; \ | |
416 tb->vertical = vert; \ | |
417 \ | |
418 if (tb->blank || NILP (tb->up_glyph)) \ | |
419 { \ | |
4917 | 420 xlike_draw_blank_toolbar_button (f, tb); \ |
713 | 421 } \ |
422 else \ | |
4917 | 423 xlike_output_toolbar_button (f, button); \ |
713 | 424 } \ |
425 } \ | |
426 \ | |
427 if (vert) \ | |
428 y += height; \ | |
429 else \ | |
430 x += width; \ | |
431 \ | |
432 if ((vert && y == max_pixpos) || (!vert && x == max_pixpos)) \ | |
433 button = Qnil; \ | |
434 else \ | |
435 button = tb->next; \ | |
436 } \ | |
437 } while (0) | |
438 | |
439 static void | |
5077
d372b17f63ce
clean up toolbar/gutter edge geometry
Ben Wing <ben@xemacs.org>
parents:
4969
diff
changeset
|
440 xlike_output_toolbar (struct frame *f, enum edge_pos pos) |
713 | 441 { |
442 int x, y, bar_width, bar_height, vert; | |
443 int max_pixpos, right_size, right_start, blank_size; | |
444 int border_width = FRAME_REAL_TOOLBAR_BORDER_WIDTH (f, pos); | |
445 Lisp_Object button, window; | |
446 face_index toolbar_findex; | |
447 | |
448 get_toolbar_coords (f, pos, &x, &y, &bar_width, &bar_height, &vert, 1); | |
449 window = FRAME_LAST_NONMINIBUF_WINDOW (f); | |
450 toolbar_findex = get_builtin_face_cache_index (XWINDOW (window), Vtoolbar_face); | |
451 | |
452 /* Do the border */ | |
453 redisplay_clear_region (window, toolbar_findex, | |
454 x, y, | |
455 (vert ? bar_width : border_width), | |
456 (vert ? border_width : bar_height)); | |
457 redisplay_clear_region (window, toolbar_findex, | |
458 (vert ? x : x + bar_width - border_width), | |
459 (vert ? y + bar_height - border_width : y), | |
460 (vert ? bar_width : border_width), | |
461 (vert ? border_width : bar_height)); | |
462 | |
463 if (vert) | |
464 { | |
465 max_pixpos = y + bar_height - border_width; | |
466 y += border_width; | |
467 } | |
468 else | |
469 { | |
470 max_pixpos = x + bar_width - border_width; | |
471 x += border_width; | |
472 } | |
473 | |
474 button = FRAME_TOOLBAR_BUTTONS (f, pos); | |
475 right_size = 0; | |
476 | |
477 /* First loop over all of the buttons to determine how much room we | |
478 need for left hand and right hand buttons. This loop will also | |
479 make sure that all instances are instantiated so when we actually | |
480 output them they will come up immediately. */ | |
481 while (!NILP (button)) | |
482 { | |
483 struct toolbar_button *tb = XTOOLBAR_BUTTON (button); | |
4917 | 484 int size = xlike_get_button_size (f, window, tb, vert, pos); |
713 | 485 |
486 if (tb->pushright) | |
487 right_size += size; | |
488 | |
489 button = tb->next; | |
490 } | |
491 | |
492 button = FRAME_TOOLBAR_BUTTONS (f, pos); | |
493 | |
494 /* Loop over the left buttons, updating and outputting them. */ | |
4917 | 495 XLIKE_OUTPUT_BUTTONS_LOOP (1); |
713 | 496 |
497 /* Now determine where the right buttons start. */ | |
498 right_start = max_pixpos - right_size; | |
499 if (right_start < (vert ? y : x)) | |
500 right_start = (vert ? y : x); | |
501 | |
502 /* Output the blank which goes from the end of the left buttons to | |
503 the start of the right. */ | |
504 blank_size = right_start - (vert ? y : x); | |
505 if (blank_size) | |
506 { | |
507 int height, width; | |
508 | |
509 if (vert) | |
510 { | |
511 width = bar_width; | |
512 height = blank_size; | |
513 } | |
514 else | |
515 { | |
516 width = blank_size; | |
517 height = bar_height; | |
518 } | |
519 | |
520 /* | |
521 * Use a 3D pushright separator only if there isn't a toolbar | |
522 * border. A flat separator meshes with the border and looks | |
523 * better. | |
524 */ | |
525 if (1) | |
526 { | |
527 struct toolbar_button tb; | |
528 | |
529 tb.x = x; | |
530 tb.y = y; | |
531 tb.width = width; | |
532 tb.height = height; | |
533 tb.border_width = border_width; | |
534 tb.vertical = vert; | |
535 tb.enabled = 1; | |
536 tb.up_glyph = border_width ? Qt : Qnil; | |
537 | |
538 __prepare_button_area (f, &tb); | |
539 } | |
540 | |
541 if (vert) | |
542 y += height; | |
543 else | |
544 x += width; | |
545 } | |
546 | |
547 /* Loop over the right buttons, updating and outputting them. */ | |
4917 | 548 XLIKE_OUTPUT_BUTTONS_LOOP (0); |
713 | 549 |
550 if (!vert) | |
551 { | |
793 | 552 Lisp_Object frame = wrap_frame (f); |
713 | 553 |
554 redisplay_clear_region (frame, | |
555 DEFAULT_INDEX, FRAME_PIXWIDTH (f) - 1, y, 1, | |
556 bar_height); | |
557 } | |
558 | |
559 SET_TOOLBAR_WAS_VISIBLE_FLAG (f, pos, 1); | |
560 __INTERNAL_FLUSH (XDEVICE (f->device)); | |
561 } | |
562 | |
563 static void | |
5077
d372b17f63ce
clean up toolbar/gutter edge geometry
Ben Wing <ben@xemacs.org>
parents:
4969
diff
changeset
|
564 xlike_clear_toolbar (struct frame *f, enum edge_pos pos, int thickness_change) |
713 | 565 { |
566 Lisp_Object frame; | |
567 int x, y, width, height, vert; | |
568 | |
569 get_toolbar_coords (f, pos, &x, &y, &width, &height, &vert, 1); | |
793 | 570 frame = wrap_frame (f); |
713 | 571 |
572 /* The thickness_change parameter is used by the toolbar resize routines | |
573 to clear any excess toolbar if the size shrinks. */ | |
574 if (thickness_change < 0) | |
575 { | |
5077
d372b17f63ce
clean up toolbar/gutter edge geometry
Ben Wing <ben@xemacs.org>
parents:
4969
diff
changeset
|
576 if (pos == LEFT_EDGE || pos == RIGHT_EDGE) |
713 | 577 { |
578 x = x + width + thickness_change; | |
579 width = -thickness_change; | |
580 } | |
581 else | |
582 { | |
583 y = y + height + thickness_change; | |
584 height = -thickness_change; | |
585 } | |
586 } | |
587 | |
588 SET_TOOLBAR_WAS_VISIBLE_FLAG (f, pos, 0); | |
589 | |
590 redisplay_clear_region (frame, DEFAULT_INDEX, x, y, width, height); | |
591 | |
592 __INTERNAL_FLUSH (XDEVICE (f->device)); | |
593 } | |
594 | |
595 void | |
4917 | 596 xlike_output_frame_toolbars (struct frame *f) |
713 | 597 { |
5077
d372b17f63ce
clean up toolbar/gutter edge geometry
Ben Wing <ben@xemacs.org>
parents:
4969
diff
changeset
|
598 enum edge_pos pos; |
d372b17f63ce
clean up toolbar/gutter edge geometry
Ben Wing <ben@xemacs.org>
parents:
4969
diff
changeset
|
599 __INTERNAL_APPROPRIATENESS_CHECK (f); |
713 | 600 |
5077
d372b17f63ce
clean up toolbar/gutter edge geometry
Ben Wing <ben@xemacs.org>
parents:
4969
diff
changeset
|
601 EDGE_POS_LOOP (pos) |
d372b17f63ce
clean up toolbar/gutter edge geometry
Ben Wing <ben@xemacs.org>
parents:
4969
diff
changeset
|
602 { |
d372b17f63ce
clean up toolbar/gutter edge geometry
Ben Wing <ben@xemacs.org>
parents:
4969
diff
changeset
|
603 if (FRAME_REAL_TOOLBAR_VISIBLE (f, pos)) |
d372b17f63ce
clean up toolbar/gutter edge geometry
Ben Wing <ben@xemacs.org>
parents:
4969
diff
changeset
|
604 xlike_output_toolbar (f, pos); |
d372b17f63ce
clean up toolbar/gutter edge geometry
Ben Wing <ben@xemacs.org>
parents:
4969
diff
changeset
|
605 } |
905 | 606 } |
607 | |
608 void | |
4917 | 609 xlike_clear_frame_toolbars (struct frame *f) |
905 | 610 { |
5077
d372b17f63ce
clean up toolbar/gutter edge geometry
Ben Wing <ben@xemacs.org>
parents:
4969
diff
changeset
|
611 enum edge_pos pos; |
d372b17f63ce
clean up toolbar/gutter edge geometry
Ben Wing <ben@xemacs.org>
parents:
4969
diff
changeset
|
612 __INTERNAL_APPROPRIATENESS_CHECK (f); |
905 | 613 |
5077
d372b17f63ce
clean up toolbar/gutter edge geometry
Ben Wing <ben@xemacs.org>
parents:
4969
diff
changeset
|
614 EDGE_POS_LOOP (pos) |
d372b17f63ce
clean up toolbar/gutter edge geometry
Ben Wing <ben@xemacs.org>
parents:
4969
diff
changeset
|
615 { |
d372b17f63ce
clean up toolbar/gutter edge geometry
Ben Wing <ben@xemacs.org>
parents:
4969
diff
changeset
|
616 if (f->toolbar_was_visible[pos] |
d372b17f63ce
clean up toolbar/gutter edge geometry
Ben Wing <ben@xemacs.org>
parents:
4969
diff
changeset
|
617 && !FRAME_REAL_TOOLBAR_VISIBLE (f, pos)) |
d372b17f63ce
clean up toolbar/gutter edge geometry
Ben Wing <ben@xemacs.org>
parents:
4969
diff
changeset
|
618 xlike_clear_toolbar (f, pos, 0); |
d372b17f63ce
clean up toolbar/gutter edge geometry
Ben Wing <ben@xemacs.org>
parents:
4969
diff
changeset
|
619 } |
713 | 620 } |
621 | |
622 static void | |
5077
d372b17f63ce
clean up toolbar/gutter edge geometry
Ben Wing <ben@xemacs.org>
parents:
4969
diff
changeset
|
623 xlike_redraw_exposed_toolbar (struct frame *f, enum edge_pos pos, int x, int y, |
713 | 624 int width, int height) |
625 { | |
626 int bar_x, bar_y, bar_width, bar_height, vert; | |
627 Lisp_Object button = FRAME_TOOLBAR_BUTTONS (f, pos); | |
628 | |
629 get_toolbar_coords (f, pos, &bar_x, &bar_y, &bar_width, &bar_height, | |
630 &vert, 1); | |
631 | |
632 if (((y + height) < bar_y) || (y > (bar_y + bar_height))) | |
633 return; | |
634 if (((x + width) < bar_x) || (x > (bar_x + bar_width))) | |
635 return; | |
636 | |
637 while (!NILP (button)) | |
638 { | |
639 struct toolbar_button *tb = XTOOLBAR_BUTTON (button); | |
640 | |
641 if (vert) | |
642 { | |
643 if (((tb->y + tb->height) > y) && (tb->y < (y + height))) | |
644 tb->dirty = 1; | |
645 | |
646 /* If this is true we have gone past the exposed region. */ | |
647 if (tb->y > (y + height)) | |
648 break; | |
649 } | |
650 else | |
651 { | |
652 if (((tb->x + tb->width) > x) && (tb->x < (x + width))) | |
653 tb->dirty = 1; | |
654 | |
655 /* If this is true we have gone past the exposed region. */ | |
656 if (tb->x > (x + width)) | |
657 break; | |
658 } | |
659 | |
660 button = tb->next; | |
661 } | |
662 | |
663 /* Even if none of the buttons is in the area, the blank region at | |
664 the very least must be because the first thing we did is verify | |
665 that some portion of the toolbar is in the exposed region. */ | |
4917 | 666 xlike_output_toolbar (f, pos); |
713 | 667 } |
668 | |
669 void | |
4917 | 670 xlike_redraw_exposed_toolbars (struct frame *f, int x, int y, int width, |
713 | 671 int height) |
672 { | |
5077
d372b17f63ce
clean up toolbar/gutter edge geometry
Ben Wing <ben@xemacs.org>
parents:
4969
diff
changeset
|
673 enum edge_pos pos; |
d372b17f63ce
clean up toolbar/gutter edge geometry
Ben Wing <ben@xemacs.org>
parents:
4969
diff
changeset
|
674 __INTERNAL_APPROPRIATENESS_CHECK (f); |
713 | 675 |
5077
d372b17f63ce
clean up toolbar/gutter edge geometry
Ben Wing <ben@xemacs.org>
parents:
4969
diff
changeset
|
676 EDGE_POS_LOOP (pos) |
d372b17f63ce
clean up toolbar/gutter edge geometry
Ben Wing <ben@xemacs.org>
parents:
4969
diff
changeset
|
677 { |
d372b17f63ce
clean up toolbar/gutter edge geometry
Ben Wing <ben@xemacs.org>
parents:
4969
diff
changeset
|
678 if (FRAME_REAL_TOOLBAR_VISIBLE (f, pos)) |
d372b17f63ce
clean up toolbar/gutter edge geometry
Ben Wing <ben@xemacs.org>
parents:
4969
diff
changeset
|
679 xlike_redraw_exposed_toolbar (f, pos, x, y, width, height); |
d372b17f63ce
clean up toolbar/gutter edge geometry
Ben Wing <ben@xemacs.org>
parents:
4969
diff
changeset
|
680 } |
713 | 681 } |
682 | |
683 void | |
4917 | 684 xlike_redraw_frame_toolbars (struct frame *f) |
713 | 685 { |
686 /* There are certain startup paths that lead to update_EmacsFrame in | |
687 faces.c being called before a new frame is fully initialized. In | |
688 particular before we have actually mapped it. That routine can | |
689 call this one. So, we need to make sure that the frame is | |
690 actually ready before we try and draw all over it. */ | |
5077
d372b17f63ce
clean up toolbar/gutter edge geometry
Ben Wing <ben@xemacs.org>
parents:
4969
diff
changeset
|
691 if (__INTERNAL_MAPPED_P (f)) |
4917 | 692 xlike_redraw_exposed_toolbars (f, 0, 0, FRAME_PIXWIDTH (f), |
713 | 693 FRAME_PIXHEIGHT (f)); |
694 } |