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.
793
+ − 4 Copyright (C) 1995, 1996, 2002 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 **
+ − 41 ** Some of the routines used assert(FRAME_yyy_P(f)) checks, this is
+ − 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
+ − 48 ** the __INTERNAL_MAPPED_P(f) macro, that should return 0 if we should
+ − 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
+ − 71 #include "toolbar-common.h"
+ − 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;
+ − 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
+ − 106 /* Blank toolbar buttons that should be 3d will have EQ(tb->up_glyph, Qt)
+ − 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,
+ − 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
+ − 163 #define common_draw_blank_toolbar_button(f,tb) __prepare_button_area (f,tb)
+ − 164
+ − 165 void
+ − 166 common_output_toolbar_button (struct frame *f, Lisp_Object button)
+ − 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);
867
+ − 299 find_charsets_in_ichar_string (charsets, Dynarr_atp (buf, 0),
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
+ − 331 common_get_button_size (struct frame *f, Lisp_Object window,
+ − 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
+ − 373 #define COMMON_OUTPUT_BUTTONS_LOOP(left) \
+ − 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 \
+ − 383 size = common_get_button_size (f, window, tb, vert, pos); \
+ − 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 { \
+ − 420 common_draw_blank_toolbar_button (f, tb); \
+ − 421 } \
+ − 422 else \
+ − 423 common_output_toolbar_button (f, button); \
+ − 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 #define SET_TOOLBAR_WAS_VISIBLE_FLAG(frame, pos, flag) \
+ − 440 do { \
+ − 441 switch (pos) \
+ − 442 { \
+ − 443 case TOP_TOOLBAR: \
+ − 444 (frame)->top_toolbar_was_visible = flag; \
+ − 445 break; \
+ − 446 case BOTTOM_TOOLBAR: \
+ − 447 (frame)->bottom_toolbar_was_visible = flag; \
+ − 448 break; \
+ − 449 case LEFT_TOOLBAR: \
+ − 450 (frame)->left_toolbar_was_visible = flag; \
+ − 451 break; \
+ − 452 case RIGHT_TOOLBAR: \
+ − 453 (frame)->right_toolbar_was_visible = flag; \
+ − 454 break; \
+ − 455 default: \
2500
+ − 456 ABORT (); \
713
+ − 457 } \
+ − 458 } while (0)
+ − 459
+ − 460 static void
+ − 461 common_output_toolbar (struct frame *f, enum toolbar_pos pos)
+ − 462 {
+ − 463 int x, y, bar_width, bar_height, vert;
+ − 464 int max_pixpos, right_size, right_start, blank_size;
+ − 465 int border_width = FRAME_REAL_TOOLBAR_BORDER_WIDTH (f, pos);
+ − 466 Lisp_Object button, window;
+ − 467 face_index toolbar_findex;
+ − 468
+ − 469 get_toolbar_coords (f, pos, &x, &y, &bar_width, &bar_height, &vert, 1);
+ − 470 window = FRAME_LAST_NONMINIBUF_WINDOW (f);
+ − 471 toolbar_findex = get_builtin_face_cache_index (XWINDOW (window), Vtoolbar_face);
+ − 472
+ − 473 /* Do the border */
+ − 474 redisplay_clear_region (window, toolbar_findex,
+ − 475 x, y,
+ − 476 (vert ? bar_width : border_width),
+ − 477 (vert ? border_width : bar_height));
+ − 478 redisplay_clear_region (window, toolbar_findex,
+ − 479 (vert ? x : x + bar_width - border_width),
+ − 480 (vert ? y + bar_height - border_width : y),
+ − 481 (vert ? bar_width : border_width),
+ − 482 (vert ? border_width : bar_height));
+ − 483
+ − 484 if (vert)
+ − 485 {
+ − 486 max_pixpos = y + bar_height - border_width;
+ − 487 y += border_width;
+ − 488 }
+ − 489 else
+ − 490 {
+ − 491 max_pixpos = x + bar_width - border_width;
+ − 492 x += border_width;
+ − 493 }
+ − 494
+ − 495 button = FRAME_TOOLBAR_BUTTONS (f, pos);
+ − 496 right_size = 0;
+ − 497
+ − 498 /* First loop over all of the buttons to determine how much room we
+ − 499 need for left hand and right hand buttons. This loop will also
+ − 500 make sure that all instances are instantiated so when we actually
+ − 501 output them they will come up immediately. */
+ − 502 while (!NILP (button))
+ − 503 {
+ − 504 struct toolbar_button *tb = XTOOLBAR_BUTTON (button);
+ − 505 int size = common_get_button_size (f, window, tb, vert, pos);
+ − 506
+ − 507 if (tb->pushright)
+ − 508 right_size += size;
+ − 509
+ − 510 button = tb->next;
+ − 511 }
+ − 512
+ − 513 button = FRAME_TOOLBAR_BUTTONS (f, pos);
+ − 514
+ − 515 /* Loop over the left buttons, updating and outputting them. */
+ − 516 COMMON_OUTPUT_BUTTONS_LOOP (1);
+ − 517
+ − 518 /* Now determine where the right buttons start. */
+ − 519 right_start = max_pixpos - right_size;
+ − 520 if (right_start < (vert ? y : x))
+ − 521 right_start = (vert ? y : x);
+ − 522
+ − 523 /* Output the blank which goes from the end of the left buttons to
+ − 524 the start of the right. */
+ − 525 blank_size = right_start - (vert ? y : x);
+ − 526 if (blank_size)
+ − 527 {
+ − 528 int height, width;
+ − 529
+ − 530 if (vert)
+ − 531 {
+ − 532 width = bar_width;
+ − 533 height = blank_size;
+ − 534 }
+ − 535 else
+ − 536 {
+ − 537 width = blank_size;
+ − 538 height = bar_height;
+ − 539 }
+ − 540
+ − 541 /*
+ − 542 * Use a 3D pushright separator only if there isn't a toolbar
+ − 543 * border. A flat separator meshes with the border and looks
+ − 544 * better.
+ − 545 */
+ − 546 if (1)
+ − 547 {
+ − 548 struct toolbar_button tb;
+ − 549
+ − 550 tb.x = x;
+ − 551 tb.y = y;
+ − 552 tb.width = width;
+ − 553 tb.height = height;
+ − 554 tb.border_width = border_width;
+ − 555 tb.vertical = vert;
+ − 556 tb.enabled = 1;
+ − 557 tb.up_glyph = border_width ? Qt : Qnil;
+ − 558
+ − 559 __prepare_button_area (f, &tb);
+ − 560 }
+ − 561
+ − 562 if (vert)
+ − 563 y += height;
+ − 564 else
+ − 565 x += width;
+ − 566 }
+ − 567
+ − 568 /* Loop over the right buttons, updating and outputting them. */
+ − 569 COMMON_OUTPUT_BUTTONS_LOOP (0);
+ − 570
+ − 571 if (!vert)
+ − 572 {
793
+ − 573 Lisp_Object frame = wrap_frame (f);
713
+ − 574
+ − 575 redisplay_clear_region (frame,
+ − 576 DEFAULT_INDEX, FRAME_PIXWIDTH (f) - 1, y, 1,
+ − 577 bar_height);
+ − 578 }
+ − 579
+ − 580 SET_TOOLBAR_WAS_VISIBLE_FLAG (f, pos, 1);
+ − 581 __INTERNAL_FLUSH (XDEVICE (f->device));
+ − 582 }
+ − 583
+ − 584 static void
+ − 585 common_clear_toolbar (struct frame *f, enum toolbar_pos pos, int thickness_change)
+ − 586 {
+ − 587 Lisp_Object frame;
+ − 588 int x, y, width, height, vert;
+ − 589
+ − 590 get_toolbar_coords (f, pos, &x, &y, &width, &height, &vert, 1);
793
+ − 591 frame = wrap_frame (f);
713
+ − 592
+ − 593 /* The thickness_change parameter is used by the toolbar resize routines
+ − 594 to clear any excess toolbar if the size shrinks. */
+ − 595 if (thickness_change < 0)
+ − 596 {
+ − 597 if (pos == LEFT_TOOLBAR || pos == RIGHT_TOOLBAR)
+ − 598 {
+ − 599 x = x + width + thickness_change;
+ − 600 width = -thickness_change;
+ − 601 }
+ − 602 else
+ − 603 {
+ − 604 y = y + height + thickness_change;
+ − 605 height = -thickness_change;
+ − 606 }
+ − 607 }
+ − 608
+ − 609 SET_TOOLBAR_WAS_VISIBLE_FLAG (f, pos, 0);
+ − 610
+ − 611 redisplay_clear_region (frame, DEFAULT_INDEX, x, y, width, height);
+ − 612
+ − 613 __INTERNAL_FLUSH (XDEVICE (f->device));
+ − 614 }
+ − 615
+ − 616 void
+ − 617 common_output_frame_toolbars (struct frame *f)
+ − 618 {
+ − 619 __INTERNAL_APPROPRIATENESS_CHECK(f);
+ − 620
+ − 621 if (FRAME_REAL_TOP_TOOLBAR_VISIBLE (f))
+ − 622 common_output_toolbar (f, TOP_TOOLBAR);
+ − 623
+ − 624 if (FRAME_REAL_BOTTOM_TOOLBAR_VISIBLE (f))
+ − 625 common_output_toolbar (f, BOTTOM_TOOLBAR);
+ − 626
+ − 627 if (FRAME_REAL_LEFT_TOOLBAR_VISIBLE (f))
+ − 628 common_output_toolbar (f, LEFT_TOOLBAR);
+ − 629
+ − 630 if (FRAME_REAL_RIGHT_TOOLBAR_VISIBLE (f))
+ − 631 common_output_toolbar (f, RIGHT_TOOLBAR);
905
+ − 632 }
+ − 633
+ − 634 void
+ − 635 common_clear_frame_toolbars (struct frame *f)
+ − 636 {
+ − 637 __INTERNAL_APPROPRIATENESS_CHECK(f);
+ − 638
+ − 639 if (f->top_toolbar_was_visible
+ − 640 && !FRAME_REAL_TOP_TOOLBAR_VISIBLE (f))
+ − 641 common_clear_toolbar (f, TOP_TOOLBAR, 0);
+ − 642 if (f->bottom_toolbar_was_visible
+ − 643 && !FRAME_REAL_BOTTOM_TOOLBAR_VISIBLE (f))
+ − 644 common_clear_toolbar (f, BOTTOM_TOOLBAR, 0);
+ − 645 if (f->left_toolbar_was_visible
+ − 646 && !FRAME_REAL_LEFT_TOOLBAR_VISIBLE (f))
+ − 647 common_clear_toolbar (f, LEFT_TOOLBAR, 0);
+ − 648 if (f->right_toolbar_was_visible
+ − 649 && !FRAME_REAL_RIGHT_TOOLBAR_VISIBLE (f))
713
+ − 650 common_clear_toolbar (f, RIGHT_TOOLBAR, 0);
+ − 651 }
+ − 652
+ − 653 static void
+ − 654 common_redraw_exposed_toolbar (struct frame *f, enum toolbar_pos pos, int x, int y,
+ − 655 int width, int height)
+ − 656 {
+ − 657 int bar_x, bar_y, bar_width, bar_height, vert;
+ − 658 Lisp_Object button = FRAME_TOOLBAR_BUTTONS (f, pos);
+ − 659
+ − 660 get_toolbar_coords (f, pos, &bar_x, &bar_y, &bar_width, &bar_height,
+ − 661 &vert, 1);
+ − 662
+ − 663 if (((y + height) < bar_y) || (y > (bar_y + bar_height)))
+ − 664 return;
+ − 665 if (((x + width) < bar_x) || (x > (bar_x + bar_width)))
+ − 666 return;
+ − 667
+ − 668 while (!NILP (button))
+ − 669 {
+ − 670 struct toolbar_button *tb = XTOOLBAR_BUTTON (button);
+ − 671
+ − 672 if (vert)
+ − 673 {
+ − 674 if (((tb->y + tb->height) > y) && (tb->y < (y + height)))
+ − 675 tb->dirty = 1;
+ − 676
+ − 677 /* If this is true we have gone past the exposed region. */
+ − 678 if (tb->y > (y + height))
+ − 679 break;
+ − 680 }
+ − 681 else
+ − 682 {
+ − 683 if (((tb->x + tb->width) > x) && (tb->x < (x + width)))
+ − 684 tb->dirty = 1;
+ − 685
+ − 686 /* If this is true we have gone past the exposed region. */
+ − 687 if (tb->x > (x + width))
+ − 688 break;
+ − 689 }
+ − 690
+ − 691 button = tb->next;
+ − 692 }
+ − 693
+ − 694 /* Even if none of the buttons is in the area, the blank region at
+ − 695 the very least must be because the first thing we did is verify
+ − 696 that some portion of the toolbar is in the exposed region. */
+ − 697 common_output_toolbar (f, pos);
+ − 698 }
+ − 699
+ − 700 void
+ − 701 common_redraw_exposed_toolbars (struct frame *f, int x, int y, int width,
+ − 702 int height)
+ − 703 {
+ − 704 __INTERNAL_APPROPRIATENESS_CHECK(f);
+ − 705
+ − 706 if (FRAME_REAL_TOP_TOOLBAR_VISIBLE (f))
+ − 707 common_redraw_exposed_toolbar (f, TOP_TOOLBAR, x, y, width, height);
+ − 708
+ − 709 if (FRAME_REAL_BOTTOM_TOOLBAR_VISIBLE (f))
+ − 710 common_redraw_exposed_toolbar (f, BOTTOM_TOOLBAR, x, y, width, height);
+ − 711
+ − 712 if (FRAME_REAL_LEFT_TOOLBAR_VISIBLE (f))
+ − 713 common_redraw_exposed_toolbar (f, LEFT_TOOLBAR, x, y, width, height);
+ − 714
+ − 715 if (FRAME_REAL_RIGHT_TOOLBAR_VISIBLE (f))
+ − 716 common_redraw_exposed_toolbar (f, RIGHT_TOOLBAR, x, y, width, height);
+ − 717 }
+ − 718
+ − 719 void
+ − 720 common_redraw_frame_toolbars (struct frame *f)
+ − 721 {
+ − 722 /* There are certain startup paths that lead to update_EmacsFrame in
+ − 723 faces.c being called before a new frame is fully initialized. In
+ − 724 particular before we have actually mapped it. That routine can
+ − 725 call this one. So, we need to make sure that the frame is
+ − 726 actually ready before we try and draw all over it. */
+ − 727 if (__INTERNAL_MAPPED_P(f))
+ − 728 common_redraw_exposed_toolbars (f, 0, 0, FRAME_PIXWIDTH (f),
+ − 729 FRAME_PIXHEIGHT (f));
+ − 730 }