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