Mercurial > hg > xemacs-beta
annotate src/toolbar-xlike.c @ 5554:a42e686a01bf
Automated merge with file:///Sources/xemacs-21.5-checked-out
| author | Aidan Kehoe <kehoea@parhasard.net> |
|---|---|
| date | Wed, 24 Aug 2011 11:07:26 +0100 |
| parents | 308d34e9f07d |
| children | 56144c8593a8 |
| 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 | |
|
5402
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
5077
diff
changeset
|
9 XEmacs is free software: you can redistribute it and/or modify it |
| 713 | 10 under the terms of the GNU General Public License as published by the |
|
5402
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
5077
diff
changeset
|
11 Free Software Foundation, either version 3 of the License, or (at your |
|
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
5077
diff
changeset
|
12 option) any later version. |
| 713 | 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 | |
|
5402
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
5077
diff
changeset
|
20 along with XEmacs. If not, see <http://www.gnu.org/licenses/>. */ |
| 713 | 21 |
| 22 /* Synched up with: Not in FSF. */ | |
| 23 | |
| 24 #include <config.h> | |
| 25 #include "lisp.h" | |
| 26 | |
| 872 | 27 #include "device-impl.h" |
| 713 | 28 #include "faces.h" |
| 872 | 29 #include "frame-impl.h" |
| 800 | 30 #include "glyphs.h" |
| 713 | 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 ** | |
|
5077
d372b17f63ce
clean up toolbar/gutter edge geometry
Ben Wing <ben@xemacs.org>
parents:
4969
diff
changeset
|
39 ** Some of the routines used assert (FRAME_yyy_P(f)) checks, this is |
| 713 | 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 | |
|
5077
d372b17f63ce
clean up toolbar/gutter edge geometry
Ben Wing <ben@xemacs.org>
parents:
4969
diff
changeset
|
46 ** the __INTERNAL_MAPPED_P (f) macro, that should return 0 if we should |
| 713 | 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) | |
| 872 | 54 #include "console-gtk-impl.h" |
| 713 | 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) | |
| 872 | 59 #include "console-x-impl.h" |
| 713 | 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 | |
| 2500 | 64 #define __INTERNAL_MAPPED_P(f) ABORT() |
| 65 #define __INTERNAL_APPROPRIATENESS_CHECK(f) ABORT() | |
| 66 #define __INTERNAL_FLUSH(f) ABORT() | |
| 713 | 67 #endif |
| 68 | |
| 4917 | 69 #include "toolbar-xlike.h" |
| 713 | 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; |
|
5077
d372b17f63ce
clean up toolbar/gutter edge geometry
Ben Wing <ben@xemacs.org>
parents:
4969
diff
changeset
|
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 | |
|
5077
d372b17f63ce
clean up toolbar/gutter edge geometry
Ben Wing <ben@xemacs.org>
parents:
4969
diff
changeset
|
104 /* Blank toolbar buttons that should be 3d will have EQ (tb->up_glyph, Qt) |
| 713 | 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, | |
|
5077
d372b17f63ce
clean up toolbar/gutter edge geometry
Ben Wing <ben@xemacs.org>
parents:
4969
diff
changeset
|
144 sheight + height_adj, abs (shadow_thickness), |
| 3094 | 145 EDGE_ALL, (shadow_thickness < 0) ? EDGE_BEVEL_IN |
| 146 : EDGE_BEVEL_OUT)); | |
| 713 | 147 } |
| 148 | |
| 149 /* Handle the borders... */ | |
| 150 redisplay_clear_region (window, toolbar_findex, | |
| 151 sx, sy, | |
| 152 (tb->vertical ? border_width : swidth), | |
| 153 (tb->vertical ? sheight : border_width)); | |
| 154 redisplay_clear_region (window, toolbar_findex, | |
| 155 (tb->vertical ? sx + swidth : sx), | |
| 156 (tb->vertical ? sy : sy + sheight), | |
| 157 (tb->vertical ? border_width : swidth), | |
| 158 (tb->vertical ? sheight : border_width)); | |
| 159 } | |
| 160 | |
| 4917 | 161 #define xlike_draw_blank_toolbar_button(f,tb) __prepare_button_area (f,tb) |
| 713 | 162 |
| 163 void | |
| 4917 | 164 xlike_output_toolbar_button (struct frame *f, Lisp_Object button) |
| 713 | 165 { |
| 166 int shadow_thickness = 2; | |
| 167 int x_adj, y_adj, width_adj, height_adj; | |
| 168 struct device *d = XDEVICE (f->device); | |
| 2212 | 169 Lisp_Object instance, window, glyph; |
| 713 | 170 struct toolbar_button *tb = XTOOLBAR_BUTTON (button); |
| 171 struct Lisp_Image_Instance *p; | |
| 172 struct window *w; | |
| 173 int vertical = tb->vertical; | |
| 174 int border_width = tb->border_width; | |
| 3094 | 175 face_index button_findex; |
| 713 | 176 |
| 177 if (vertical) | |
| 178 { | |
| 179 x_adj = border_width; | |
| 180 width_adj = - 2 * border_width; | |
| 181 y_adj = 0; | |
| 182 height_adj = 0; | |
| 183 } | |
| 184 else | |
| 185 { | |
| 186 x_adj = 0; | |
| 187 width_adj = 0; | |
| 188 y_adj = border_width; | |
| 189 height_adj = - 2 * border_width; | |
| 190 } | |
| 191 | |
| 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 /* #### It is currently possible for users to trash us by directly | |
| 214 changing the toolbar glyphs. Avoid crashing in that case. */ | |
| 215 if (GLYPHP (glyph)) | |
| 3094 | 216 { |
| 217 /* WARNING: this interface may change */ | |
| 218 Lisp_Object face_list[2] = { XGLYPH_FACE (glyph), Vtoolbar_face }; | |
| 219 | |
| 220 button_findex = merge_face_list_to_cache_index (w, face_list, 2); | |
| 221 instance = glyph_image_instance (glyph, window, ERROR_ME_DEBUG_WARN, 1); | |
| 222 } | |
| 713 | 223 else |
| 3094 | 224 { |
| 225 button_findex = get_builtin_face_cache_index (w, Vtoolbar_face); | |
| 226 instance = Qnil; | |
| 227 } | |
| 228 | |
| 229 __prepare_button_area (f, tb); | |
| 713 | 230 |
| 231 if (IMAGE_INSTANCEP (instance)) | |
| 232 { | |
| 233 int width = tb->width + width_adj - shadow_thickness * 2; | |
| 234 int height = tb->height + height_adj - shadow_thickness * 2; | |
| 235 int x_offset = x_adj + shadow_thickness; | |
| 236 int y_offset = y_adj + shadow_thickness; | |
| 237 | |
| 238 p = XIMAGE_INSTANCE (instance); | |
| 239 | |
| 240 if (IMAGE_INSTANCE_PIXMAP_TYPE_P (p)) | |
| 241 { | |
| 242 struct display_box db; | |
| 243 struct display_glyph_area dga; | |
| 244 | |
| 245 if (width > (int) IMAGE_INSTANCE_PIXMAP_WIDTH (p)) | |
| 246 { | |
| 247 x_offset += ((int) (width - IMAGE_INSTANCE_PIXMAP_WIDTH (p)) | |
| 248 / 2); | |
| 249 width = IMAGE_INSTANCE_PIXMAP_WIDTH (p); | |
| 250 } | |
| 251 if (height > (int) IMAGE_INSTANCE_PIXMAP_HEIGHT (p)) | |
| 252 { | |
| 253 y_offset += ((int) (height - IMAGE_INSTANCE_PIXMAP_HEIGHT (p)) | |
| 254 / 2); | |
| 255 height = IMAGE_INSTANCE_PIXMAP_HEIGHT (p); | |
| 256 } | |
| 257 | |
| 258 /* Draw exactly in the area specified... */ | |
| 259 db.xpos = tb->x + x_offset; | |
| 260 db.ypos = tb->y + y_offset; | |
| 261 db.width = width; | |
| 262 db.height = height; | |
| 263 | |
| 264 /* Display the whole glyph */ | |
| 265 dga.xoffset = 0; | |
| 266 dga.yoffset = 0; | |
| 267 dga.width = width; | |
| 268 dga.height = height; | |
| 269 | |
| 270 redisplay_output_pixmap (w, instance, | |
| 271 &db, &dga, | |
| 3094 | 272 button_findex, 0, 0, 0, 0); |
| 713 | 273 } |
| 274 else if (IMAGE_INSTANCE_TYPE (p) == IMAGE_TEXT) | |
| 275 { | |
| 276 /* #### We need to make the face used configurable. */ | |
| 277 struct face_cachel *cachel = | |
| 278 WINDOW_FACE_CACHEL (w, DEFAULT_INDEX); | |
| 279 struct display_line dl; | |
| 280 Lisp_Object string = IMAGE_INSTANCE_TEXT_STRING (p); | |
| 281 unsigned char charsets[NUM_LEADING_BYTES]; | |
| 867 | 282 Ichar_dynarr *buf; |
| 713 | 283 struct font_metric_info fm; |
| 284 | |
| 285 /* This could be true if we were called via the Expose event | |
| 286 handler. Mark the button as dirty and return | |
| 287 immediately. */ | |
| 288 if (f->window_face_cache_reset) | |
| 289 { | |
| 290 tb->dirty = 1; | |
| 291 MARK_TOOLBAR_CHANGED; | |
| 292 return; | |
| 293 } | |
| 867 | 294 buf = Dynarr_new (Ichar); |
| 295 convert_ibyte_string_into_ichar_dynarr | |
| 713 | 296 (XSTRING_DATA (string), XSTRING_LENGTH (string), buf); |
| 4967 | 297 find_charsets_in_ichar_string (charsets, Dynarr_begin (buf), |
| 713 | 298 Dynarr_length (buf)); |
| 299 ensure_face_cachel_complete (cachel, window, charsets); | |
| 300 face_cachel_charset_font_metric_info (cachel, charsets, &fm); | |
| 301 | |
| 302 dl.ascent = fm.ascent; | |
| 303 dl.descent = fm.descent; | |
| 304 dl.ypos = tb->y + y_offset + fm.ascent; | |
| 305 | |
| 306 if (fm.ascent + fm.descent <= height) | |
| 307 { | |
| 308 dl.ypos += (height - fm.ascent - fm.descent) / 2; | |
| 309 dl.clip = 0; | |
| 310 } | |
| 311 else | |
| 312 { | |
| 313 dl.clip = fm.ascent + fm.descent - height; | |
| 314 } | |
| 315 | |
| 316 MAYBE_DEVMETH (d, output_string, | |
| 317 (w, &dl, buf, tb->x + x_offset, 0, 0, width, | |
| 3094 | 318 button_findex, 0, 0, 0, 0)); |
| 713 | 319 Dynarr_free (buf); |
| 320 } | |
| 321 | |
| 322 /* We silently ignore the image if it isn't a pixmap or text. */ | |
| 323 } | |
| 324 | |
| 325 tb->dirty = 0; | |
| 326 } | |
| 327 | |
| 328 static int | |
| 4917 | 329 xlike_get_button_size (struct frame *f, Lisp_Object window, |
| 713 | 330 struct toolbar_button *tb, int vert, int pos) |
| 331 { | |
| 332 int shadow_thickness = 2; | |
| 333 int size; | |
| 334 | |
| 335 if (tb->blank) | |
| 336 { | |
| 337 if (!NILP (tb->down_glyph)) | |
| 338 size = XINT (tb->down_glyph); | |
| 339 else | |
| 340 size = DEFAULT_TOOLBAR_BLANK_SIZE; | |
| 341 } | |
| 342 else | |
| 343 { | |
| 344 struct window *w = XWINDOW (window); | |
| 345 Lisp_Object glyph = get_toolbar_button_glyph (w, tb); | |
| 346 | |
| 347 /* Unless, of course, the user has done something stupid like | |
| 348 change the glyph out from under us. Use a blank placeholder | |
| 349 in that case. */ | |
| 350 if (NILP (glyph)) | |
| 351 return XINT (f->toolbar_size[pos]); | |
| 352 | |
| 353 if (vert) | |
| 354 size = glyph_height (glyph, window); | |
| 355 else | |
| 356 size = glyph_width (glyph, window); | |
| 357 } | |
| 358 | |
| 359 if (!size) | |
| 360 { | |
| 361 /* If the glyph doesn't have a size we'll insert a blank | |
| 362 placeholder instead. */ | |
| 363 return XINT (f->toolbar_size[pos]); | |
| 364 } | |
| 365 | |
| 366 size += shadow_thickness * 2; | |
| 367 | |
| 368 return (size); | |
| 369 } | |
| 370 | |
|
5077
d372b17f63ce
clean up toolbar/gutter edge geometry
Ben Wing <ben@xemacs.org>
parents:
4969
diff
changeset
|
371 #define XLIKE_OUTPUT_BUTTONS_LOOP(left) \ |
| 713 | 372 do { \ |
| 373 while (!NILP (button)) \ | |
| 374 { \ | |
| 375 struct toolbar_button *tb = XTOOLBAR_BUTTON (button); \ | |
| 376 int size, height, width; \ | |
| 377 \ | |
| 378 if (left && tb->pushright) \ | |
| 379 break; \ | |
| 380 \ | |
| 4917 | 381 size = xlike_get_button_size (f, window, tb, vert, pos); \ |
| 713 | 382 \ |
| 383 if (vert) \ | |
| 384 { \ | |
| 385 width = bar_width; \ | |
| 386 if (y + size > max_pixpos) \ | |
| 387 height = max_pixpos - y; \ | |
| 388 else \ | |
| 389 height = size; \ | |
| 390 } \ | |
| 391 else \ | |
| 392 { \ | |
| 393 if (x + size > max_pixpos) \ | |
| 394 width = max_pixpos - x; \ | |
| 395 else \ | |
| 396 width = size; \ | |
| 397 height = bar_height; \ | |
| 398 } \ | |
| 399 \ | |
| 400 if (tb->x != x \ | |
| 401 || tb->y != y \ | |
| 402 || tb->width != width \ | |
| 403 || tb->height != height \ | |
| 905 | 404 || tb->dirty \ |
| 405 || f->clear) /* This is clearly necessary. */ \ | |
| 713 | 406 { \ |
| 407 if (width && height) \ | |
| 408 { \ | |
| 409 tb->x = x; \ | |
| 410 tb->y = y; \ | |
| 411 tb->width = width; \ | |
| 412 tb->height = height; \ | |
| 413 tb->border_width = border_width; \ | |
| 414 tb->vertical = vert; \ | |
| 415 \ | |
| 416 if (tb->blank || NILP (tb->up_glyph)) \ | |
| 417 { \ | |
| 4917 | 418 xlike_draw_blank_toolbar_button (f, tb); \ |
| 713 | 419 } \ |
| 420 else \ | |
| 4917 | 421 xlike_output_toolbar_button (f, button); \ |
| 713 | 422 } \ |
| 423 } \ | |
| 424 \ | |
| 425 if (vert) \ | |
| 426 y += height; \ | |
| 427 else \ | |
| 428 x += width; \ | |
| 429 \ | |
| 430 if ((vert && y == max_pixpos) || (!vert && x == max_pixpos)) \ | |
| 431 button = Qnil; \ | |
| 432 else \ | |
| 433 button = tb->next; \ | |
| 434 } \ | |
| 435 } while (0) | |
| 436 | |
| 437 static void | |
|
5077
d372b17f63ce
clean up toolbar/gutter edge geometry
Ben Wing <ben@xemacs.org>
parents:
4969
diff
changeset
|
438 xlike_output_toolbar (struct frame *f, enum edge_pos pos) |
| 713 | 439 { |
| 440 int x, y, bar_width, bar_height, vert; | |
| 441 int max_pixpos, right_size, right_start, blank_size; | |
| 442 int border_width = FRAME_REAL_TOOLBAR_BORDER_WIDTH (f, pos); | |
| 443 Lisp_Object button, window; | |
| 444 face_index toolbar_findex; | |
| 445 | |
| 446 get_toolbar_coords (f, pos, &x, &y, &bar_width, &bar_height, &vert, 1); | |
| 447 window = FRAME_LAST_NONMINIBUF_WINDOW (f); | |
| 448 toolbar_findex = get_builtin_face_cache_index (XWINDOW (window), Vtoolbar_face); | |
| 449 | |
| 450 /* Do the border */ | |
| 451 redisplay_clear_region (window, toolbar_findex, | |
| 452 x, y, | |
| 453 (vert ? bar_width : border_width), | |
| 454 (vert ? border_width : bar_height)); | |
| 455 redisplay_clear_region (window, toolbar_findex, | |
| 456 (vert ? x : x + bar_width - border_width), | |
| 457 (vert ? y + bar_height - border_width : y), | |
| 458 (vert ? bar_width : border_width), | |
| 459 (vert ? border_width : bar_height)); | |
| 460 | |
| 461 if (vert) | |
| 462 { | |
| 463 max_pixpos = y + bar_height - border_width; | |
| 464 y += border_width; | |
| 465 } | |
| 466 else | |
| 467 { | |
| 468 max_pixpos = x + bar_width - border_width; | |
| 469 x += border_width; | |
| 470 } | |
| 471 | |
| 472 button = FRAME_TOOLBAR_BUTTONS (f, pos); | |
| 473 right_size = 0; | |
| 474 | |
| 475 /* First loop over all of the buttons to determine how much room we | |
| 476 need for left hand and right hand buttons. This loop will also | |
| 477 make sure that all instances are instantiated so when we actually | |
| 478 output them they will come up immediately. */ | |
| 479 while (!NILP (button)) | |
| 480 { | |
| 481 struct toolbar_button *tb = XTOOLBAR_BUTTON (button); | |
| 4917 | 482 int size = xlike_get_button_size (f, window, tb, vert, pos); |
| 713 | 483 |
| 484 if (tb->pushright) | |
| 485 right_size += size; | |
| 486 | |
| 487 button = tb->next; | |
| 488 } | |
| 489 | |
| 490 button = FRAME_TOOLBAR_BUTTONS (f, pos); | |
| 491 | |
| 492 /* Loop over the left buttons, updating and outputting them. */ | |
| 4917 | 493 XLIKE_OUTPUT_BUTTONS_LOOP (1); |
| 713 | 494 |
| 495 /* Now determine where the right buttons start. */ | |
| 496 right_start = max_pixpos - right_size; | |
| 497 if (right_start < (vert ? y : x)) | |
| 498 right_start = (vert ? y : x); | |
| 499 | |
| 500 /* Output the blank which goes from the end of the left buttons to | |
| 501 the start of the right. */ | |
| 502 blank_size = right_start - (vert ? y : x); | |
| 503 if (blank_size) | |
| 504 { | |
| 505 int height, width; | |
| 506 | |
| 507 if (vert) | |
| 508 { | |
| 509 width = bar_width; | |
| 510 height = blank_size; | |
| 511 } | |
| 512 else | |
| 513 { | |
| 514 width = blank_size; | |
| 515 height = bar_height; | |
| 516 } | |
| 517 | |
| 518 /* | |
| 519 * Use a 3D pushright separator only if there isn't a toolbar | |
| 520 * border. A flat separator meshes with the border and looks | |
| 521 * better. | |
| 522 */ | |
| 523 if (1) | |
| 524 { | |
| 525 struct toolbar_button tb; | |
| 526 | |
| 527 tb.x = x; | |
| 528 tb.y = y; | |
| 529 tb.width = width; | |
| 530 tb.height = height; | |
| 531 tb.border_width = border_width; | |
| 532 tb.vertical = vert; | |
| 533 tb.enabled = 1; | |
| 534 tb.up_glyph = border_width ? Qt : Qnil; | |
| 535 | |
| 536 __prepare_button_area (f, &tb); | |
| 537 } | |
| 538 | |
| 539 if (vert) | |
| 540 y += height; | |
| 541 else | |
| 542 x += width; | |
| 543 } | |
| 544 | |
| 545 /* Loop over the right buttons, updating and outputting them. */ | |
| 4917 | 546 XLIKE_OUTPUT_BUTTONS_LOOP (0); |
| 713 | 547 |
| 548 if (!vert) | |
| 549 { | |
| 793 | 550 Lisp_Object frame = wrap_frame (f); |
| 713 | 551 |
| 552 redisplay_clear_region (frame, | |
| 553 DEFAULT_INDEX, FRAME_PIXWIDTH (f) - 1, y, 1, | |
| 554 bar_height); | |
| 555 } | |
| 556 | |
| 557 SET_TOOLBAR_WAS_VISIBLE_FLAG (f, pos, 1); | |
| 558 __INTERNAL_FLUSH (XDEVICE (f->device)); | |
| 559 } | |
| 560 | |
| 561 static void | |
|
5077
d372b17f63ce
clean up toolbar/gutter edge geometry
Ben Wing <ben@xemacs.org>
parents:
4969
diff
changeset
|
562 xlike_clear_toolbar (struct frame *f, enum edge_pos pos, int thickness_change) |
| 713 | 563 { |
| 564 Lisp_Object frame; | |
| 565 int x, y, width, height, vert; | |
| 566 | |
| 567 get_toolbar_coords (f, pos, &x, &y, &width, &height, &vert, 1); | |
| 793 | 568 frame = wrap_frame (f); |
| 713 | 569 |
| 570 /* The thickness_change parameter is used by the toolbar resize routines | |
| 571 to clear any excess toolbar if the size shrinks. */ | |
| 572 if (thickness_change < 0) | |
| 573 { | |
|
5077
d372b17f63ce
clean up toolbar/gutter edge geometry
Ben Wing <ben@xemacs.org>
parents:
4969
diff
changeset
|
574 if (pos == LEFT_EDGE || pos == RIGHT_EDGE) |
| 713 | 575 { |
| 576 x = x + width + thickness_change; | |
| 577 width = -thickness_change; | |
| 578 } | |
| 579 else | |
| 580 { | |
| 581 y = y + height + thickness_change; | |
| 582 height = -thickness_change; | |
| 583 } | |
| 584 } | |
| 585 | |
| 586 SET_TOOLBAR_WAS_VISIBLE_FLAG (f, pos, 0); | |
| 587 | |
| 588 redisplay_clear_region (frame, DEFAULT_INDEX, x, y, width, height); | |
| 589 | |
| 590 __INTERNAL_FLUSH (XDEVICE (f->device)); | |
| 591 } | |
| 592 | |
| 593 void | |
| 4917 | 594 xlike_output_frame_toolbars (struct frame *f) |
| 713 | 595 { |
|
5077
d372b17f63ce
clean up toolbar/gutter edge geometry
Ben Wing <ben@xemacs.org>
parents:
4969
diff
changeset
|
596 enum edge_pos pos; |
|
d372b17f63ce
clean up toolbar/gutter edge geometry
Ben Wing <ben@xemacs.org>
parents:
4969
diff
changeset
|
597 __INTERNAL_APPROPRIATENESS_CHECK (f); |
| 713 | 598 |
|
5077
d372b17f63ce
clean up toolbar/gutter edge geometry
Ben Wing <ben@xemacs.org>
parents:
4969
diff
changeset
|
599 EDGE_POS_LOOP (pos) |
|
d372b17f63ce
clean up toolbar/gutter edge geometry
Ben Wing <ben@xemacs.org>
parents:
4969
diff
changeset
|
600 { |
|
d372b17f63ce
clean up toolbar/gutter edge geometry
Ben Wing <ben@xemacs.org>
parents:
4969
diff
changeset
|
601 if (FRAME_REAL_TOOLBAR_VISIBLE (f, pos)) |
|
d372b17f63ce
clean up toolbar/gutter edge geometry
Ben Wing <ben@xemacs.org>
parents:
4969
diff
changeset
|
602 xlike_output_toolbar (f, pos); |
|
d372b17f63ce
clean up toolbar/gutter edge geometry
Ben Wing <ben@xemacs.org>
parents:
4969
diff
changeset
|
603 } |
| 905 | 604 } |
| 605 | |
| 606 void | |
| 4917 | 607 xlike_clear_frame_toolbars (struct frame *f) |
| 905 | 608 { |
|
5077
d372b17f63ce
clean up toolbar/gutter edge geometry
Ben Wing <ben@xemacs.org>
parents:
4969
diff
changeset
|
609 enum edge_pos pos; |
|
d372b17f63ce
clean up toolbar/gutter edge geometry
Ben Wing <ben@xemacs.org>
parents:
4969
diff
changeset
|
610 __INTERNAL_APPROPRIATENESS_CHECK (f); |
| 905 | 611 |
|
5077
d372b17f63ce
clean up toolbar/gutter edge geometry
Ben Wing <ben@xemacs.org>
parents:
4969
diff
changeset
|
612 EDGE_POS_LOOP (pos) |
|
d372b17f63ce
clean up toolbar/gutter edge geometry
Ben Wing <ben@xemacs.org>
parents:
4969
diff
changeset
|
613 { |
|
d372b17f63ce
clean up toolbar/gutter edge geometry
Ben Wing <ben@xemacs.org>
parents:
4969
diff
changeset
|
614 if (f->toolbar_was_visible[pos] |
|
d372b17f63ce
clean up toolbar/gutter edge geometry
Ben Wing <ben@xemacs.org>
parents:
4969
diff
changeset
|
615 && !FRAME_REAL_TOOLBAR_VISIBLE (f, pos)) |
|
d372b17f63ce
clean up toolbar/gutter edge geometry
Ben Wing <ben@xemacs.org>
parents:
4969
diff
changeset
|
616 xlike_clear_toolbar (f, pos, 0); |
|
d372b17f63ce
clean up toolbar/gutter edge geometry
Ben Wing <ben@xemacs.org>
parents:
4969
diff
changeset
|
617 } |
| 713 | 618 } |
| 619 | |
| 620 static void | |
|
5077
d372b17f63ce
clean up toolbar/gutter edge geometry
Ben Wing <ben@xemacs.org>
parents:
4969
diff
changeset
|
621 xlike_redraw_exposed_toolbar (struct frame *f, enum edge_pos pos, int x, int y, |
| 713 | 622 int width, int height) |
| 623 { | |
| 624 int bar_x, bar_y, bar_width, bar_height, vert; | |
| 625 Lisp_Object button = FRAME_TOOLBAR_BUTTONS (f, pos); | |
| 626 | |
| 627 get_toolbar_coords (f, pos, &bar_x, &bar_y, &bar_width, &bar_height, | |
| 628 &vert, 1); | |
| 629 | |
| 630 if (((y + height) < bar_y) || (y > (bar_y + bar_height))) | |
| 631 return; | |
| 632 if (((x + width) < bar_x) || (x > (bar_x + bar_width))) | |
| 633 return; | |
| 634 | |
| 635 while (!NILP (button)) | |
| 636 { | |
| 637 struct toolbar_button *tb = XTOOLBAR_BUTTON (button); | |
| 638 | |
| 639 if (vert) | |
| 640 { | |
| 641 if (((tb->y + tb->height) > y) && (tb->y < (y + height))) | |
| 642 tb->dirty = 1; | |
| 643 | |
| 644 /* If this is true we have gone past the exposed region. */ | |
| 645 if (tb->y > (y + height)) | |
| 646 break; | |
| 647 } | |
| 648 else | |
| 649 { | |
| 650 if (((tb->x + tb->width) > x) && (tb->x < (x + width))) | |
| 651 tb->dirty = 1; | |
| 652 | |
| 653 /* If this is true we have gone past the exposed region. */ | |
| 654 if (tb->x > (x + width)) | |
| 655 break; | |
| 656 } | |
| 657 | |
| 658 button = tb->next; | |
| 659 } | |
| 660 | |
| 661 /* Even if none of the buttons is in the area, the blank region at | |
| 662 the very least must be because the first thing we did is verify | |
| 663 that some portion of the toolbar is in the exposed region. */ | |
| 4917 | 664 xlike_output_toolbar (f, pos); |
| 713 | 665 } |
| 666 | |
| 667 void | |
| 4917 | 668 xlike_redraw_exposed_toolbars (struct frame *f, int x, int y, int width, |
| 713 | 669 int height) |
| 670 { | |
|
5077
d372b17f63ce
clean up toolbar/gutter edge geometry
Ben Wing <ben@xemacs.org>
parents:
4969
diff
changeset
|
671 enum edge_pos pos; |
|
d372b17f63ce
clean up toolbar/gutter edge geometry
Ben Wing <ben@xemacs.org>
parents:
4969
diff
changeset
|
672 __INTERNAL_APPROPRIATENESS_CHECK (f); |
| 713 | 673 |
|
5077
d372b17f63ce
clean up toolbar/gutter edge geometry
Ben Wing <ben@xemacs.org>
parents:
4969
diff
changeset
|
674 EDGE_POS_LOOP (pos) |
|
d372b17f63ce
clean up toolbar/gutter edge geometry
Ben Wing <ben@xemacs.org>
parents:
4969
diff
changeset
|
675 { |
|
d372b17f63ce
clean up toolbar/gutter edge geometry
Ben Wing <ben@xemacs.org>
parents:
4969
diff
changeset
|
676 if (FRAME_REAL_TOOLBAR_VISIBLE (f, pos)) |
|
d372b17f63ce
clean up toolbar/gutter edge geometry
Ben Wing <ben@xemacs.org>
parents:
4969
diff
changeset
|
677 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
|
678 } |
| 713 | 679 } |
| 680 | |
| 681 void | |
| 4917 | 682 xlike_redraw_frame_toolbars (struct frame *f) |
| 713 | 683 { |
| 684 /* There are certain startup paths that lead to update_EmacsFrame in | |
| 685 faces.c being called before a new frame is fully initialized. In | |
| 686 particular before we have actually mapped it. That routine can | |
| 687 call this one. So, we need to make sure that the frame is | |
| 688 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
|
689 if (__INTERNAL_MAPPED_P (f)) |
| 4917 | 690 xlike_redraw_exposed_toolbars (f, 0, 0, FRAME_PIXWIDTH (f), |
| 713 | 691 FRAME_PIXHEIGHT (f)); |
| 692 } |
