aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGerd Moellmann1999-07-21 21:43:52 +0000
committerGerd Moellmann1999-07-21 21:43:52 +0000
commitbe06a3dffa944d10c576e299afa086048437bd0b (patch)
tree612b6dce1818699623f456e5e1d24742967e3068
parent7c2eb6d1fd9b079e9284439068b5e88504688750 (diff)
downloademacs-be06a3dffa944d10c576e299afa086048437bd0b.tar.gz
emacs-be06a3dffa944d10c576e299afa086048437bd0b.zip
(make_shadow_gcs) ]emacs]: Use x_alloc_nearest_color.
(all_dashes_p): Removed. (size_menu_item): Call lw_separator_p. (display_menu_item): Ditto. (display_menu): Ditto. (draw_separator): New. (display_menu_item): Call it. (separator_height): New. (size_menu_item): Call it. (abort_gracefully): New. (display_menu): Use it instead of abort. (size_menu): Ditto. (xlwMenuResources): Change previously unused XtNmargin to 4. (size_menu): Take margin into account. (display_menu_item): Ditto. (remap_menubar): Ditto. (draw_arrow): Draw it 3D. (radio_button_width): New. (size_menu_item): Use new functions. (draw_shadow_rhombus): New. (draw_radio): Use radio_button_width and draw_shadow_rhombus. (draw_toggle): Use toggle_button_width. (size_menu_item): Add parameter button_width. (size_menu): Compute button_width. (toggle_button_width): New. (draw_toggle): New. (draw_radio): New. (draw_shadow_rectangle): Add parameter `down_p'.
-rw-r--r--lwlib/xlwmenu.c542
1 files changed, 465 insertions, 77 deletions
diff --git a/lwlib/xlwmenu.c b/lwlib/xlwmenu.c
index f6805e8b06a..24c16bbf751 100644
--- a/lwlib/xlwmenu.c
+++ b/lwlib/xlwmenu.c
@@ -84,7 +84,7 @@ xlwMenuResources[] =
84 {XtNbuttonForeground, XtCButtonForeground, XtRPixel, sizeof(Pixel), 84 {XtNbuttonForeground, XtCButtonForeground, XtRPixel, sizeof(Pixel),
85 offset(menu.button_foreground), XtRString, "XtDefaultForeground"}, 85 offset(menu.button_foreground), XtRString, "XtDefaultForeground"},
86 {XtNmargin, XtCMargin, XtRDimension, sizeof(Dimension), 86 {XtNmargin, XtCMargin, XtRDimension, sizeof(Dimension),
87 offset(menu.margin), XtRImmediate, (XtPointer)0}, 87 offset(menu.margin), XtRImmediate, (XtPointer) 4},
88 {XtNhorizontalSpacing, XtCMargin, XtRDimension, sizeof(Dimension), 88 {XtNhorizontalSpacing, XtCMargin, XtRDimension, sizeof(Dimension),
89 offset(menu.horizontal_spacing), XtRImmediate, (XtPointer)3}, 89 offset(menu.horizontal_spacing), XtRImmediate, (XtPointer)3},
90 {XtNverticalSpacing, XtCMargin, XtRDimension, sizeof(Dimension), 90 {XtNverticalSpacing, XtCMargin, XtRDimension, sizeof(Dimension),
@@ -130,6 +130,7 @@ static void Drag();
130static void Select(); 130static void Select();
131static void Key(); 131static void Key();
132static void Nothing(); 132static void Nothing();
133static int separator_height ();
133 134
134static XtActionsRec 135static XtActionsRec
135xlwMenuActionsList [] = 136xlwMenuActionsList [] =
@@ -191,6 +192,20 @@ int submenu_destroyed;
191static int next_release_must_exit; 192static int next_release_must_exit;
192 193
193 /* Utilities */ 194 /* Utilities */
195
196
197/* Like abort, but remove grabs from widget W before. */
198
199static void
200abort_gracefully (w)
201 Widget w;
202{
203 if (XtIsShell (XtParent (w)))
204 XtRemoveGrab (w);
205 XtUngrabPointer (w, CurrentTime);
206 abort ();
207}
208
194static void 209static void
195push_new_stack (mw, val) 210push_new_stack (mw, val)
196 XlwMenuWidget mw; 211 XlwMenuWidget mw;
@@ -246,15 +261,6 @@ make_old_stack_space (mw, n)
246} 261}
247 262
248 /* Size code */ 263 /* Size code */
249static Boolean
250all_dashes_p (s)
251 char *s;
252{
253 char* p;
254 for (p = s; *p == '-'; p++);
255 return !*p;
256}
257
258int 264int
259string_width (mw, s) 265string_width (mw, s)
260 XlwMenuWidget mw; 266 XlwMenuWidget mw;
@@ -271,9 +277,29 @@ static int
271arrow_width (mw) 277arrow_width (mw)
272 XlwMenuWidget mw; 278 XlwMenuWidget mw;
273{ 279{
274 return mw->menu.font->ascent / 2 | 1; 280 return (mw->menu.font->ascent * 3/4) | 1;
281}
282
283/* Return the width of toggle buttons of widget MW. */
284
285static int
286toggle_button_width (mw)
287 XlwMenuWidget mw;
288{
289 return ((mw->menu.font->ascent + mw->menu.font->descent) * 2 / 3) | 1;
275} 290}
276 291
292
293/* Return the width of radio buttons of widget MW. */
294
295static int
296radio_button_width (mw)
297 XlwMenuWidget mw;
298{
299 return toggle_button_width (mw) * 1.41;
300}
301
302
277static XtResource 303static XtResource
278nameResource[] = 304nameResource[] =
279{ 305{
@@ -320,19 +346,24 @@ resource_widget_value (mw, val)
320 346
321/* Returns the sizes of an item */ 347/* Returns the sizes of an item */
322static void 348static void
323size_menu_item (mw, val, horizontal_p, label_width, rest_width, height) 349size_menu_item (mw, val, horizontal_p, label_width, rest_width, button_width,
350 height)
324 XlwMenuWidget mw; 351 XlwMenuWidget mw;
325 widget_value* val; 352 widget_value* val;
326 int horizontal_p; 353 int horizontal_p;
327 int* label_width; 354 int* label_width;
328 int* rest_width; 355 int* rest_width;
356 int* button_width;
329 int* height; 357 int* height;
330{ 358{
331 if (all_dashes_p (val->name)) 359 enum menu_separator separator;
360
361 if (lw_separator_p (val->name, &separator, 0))
332 { 362 {
333 *height = 2; 363 *height = separator_height (separator);
334 *label_width = 1; 364 *label_width = 1;
335 *rest_width = 0; 365 *rest_width = 0;
366 *button_width = 0;
336 } 367 }
337 else 368 else
338 { 369 {
@@ -348,10 +379,19 @@ size_menu_item (mw, val, horizontal_p, label_width, rest_width, height)
348 if (!horizontal_p) 379 if (!horizontal_p)
349 { 380 {
350 if (val->contents) 381 if (val->contents)
382 /* Add width of the arrow displayed for submenus. */
351 *rest_width += arrow_width (mw) + mw->menu.arrow_spacing; 383 *rest_width += arrow_width (mw) + mw->menu.arrow_spacing;
352 else if (val->key) 384 else if (val->key)
353 *rest_width += 385 /* Add width of key equivalent string. */
354 string_width (mw, val->key) + mw->menu.arrow_spacing; 386 *rest_width += (string_width (mw, val->key)
387 + mw->menu.arrow_spacing);
388
389 if (val->button_type == BUTTON_TYPE_TOGGLE)
390 *button_width = (toggle_button_width (mw)
391 + mw->menu.horizontal_spacing);
392 else if (val->button_type == BUTTON_TYPE_RADIO)
393 *button_width = (radio_button_width (mw)
394 + mw->menu.horizontal_spacing);
355 } 395 }
356 } 396 }
357} 397}
@@ -363,24 +403,27 @@ size_menu (mw, level)
363{ 403{
364 unsigned int label_width = 0; 404 unsigned int label_width = 0;
365 int rest_width = 0; 405 int rest_width = 0;
406 int button_width = 0;
366 int max_rest_width = 0; 407 int max_rest_width = 0;
408 int max_button_width = 0;
367 unsigned int height = 0; 409 unsigned int height = 0;
368 int horizontal_p = mw->menu.horizontal && (level == 0); 410 int horizontal_p = mw->menu.horizontal && (level == 0);
369 widget_value* val; 411 widget_value* val;
370 window_state* ws; 412 window_state* ws;
371 413
372 if (level >= mw->menu.old_depth) 414 if (level >= mw->menu.old_depth)
373 abort (); 415 abort_gracefully ((Widget) mw);
374 416
375 ws = &mw->menu.windows [level]; 417 ws = &mw->menu.windows [level];
376 ws->width = 0; 418 ws->width = 0;
377 ws->height = 0; 419 ws->height = 0;
378 ws->label_width = 0; 420 ws->label_width = 0;
421 ws->button_width = 0;
379 422
380 for (val = mw->menu.old_stack [level]->contents; val; val = val->next) 423 for (val = mw->menu.old_stack [level]->contents; val; val = val->next)
381 { 424 {
382 size_menu_item (mw, val, horizontal_p, &label_width, &rest_width, 425 size_menu_item (mw, val, horizontal_p, &label_width, &rest_width,
383 &height); 426 &button_width, &height);
384 if (horizontal_p) 427 if (horizontal_p)
385 { 428 {
386 ws->width += label_width + rest_width; 429 ws->width += label_width + rest_width;
@@ -393,44 +436,99 @@ size_menu (mw, level)
393 ws->label_width = label_width; 436 ws->label_width = label_width;
394 if (rest_width > max_rest_width) 437 if (rest_width > max_rest_width)
395 max_rest_width = rest_width; 438 max_rest_width = rest_width;
439 if (button_width > max_button_width)
440 max_button_width = button_width;
396 ws->height += height; 441 ws->height += height;
397 } 442 }
398 } 443 }
399 444
400 if (horizontal_p) 445 if (horizontal_p)
401 ws->label_width = 0; 446 ws->label_width = ws->button_width = 0;
402 else 447 else
403 ws->width = ws->label_width + max_rest_width; 448 {
449 ws->width = ws->label_width + max_rest_width + max_button_width;
450 ws->button_width = max_button_width;
451 }
404 452
405 ws->width += 2 * mw->menu.shadow_thickness; 453 ws->width += 2 * mw->menu.shadow_thickness;
406 ws->height += 2 * mw->menu.shadow_thickness; 454 ws->height += 2 * mw->menu.shadow_thickness;
455
456 if (horizontal_p)
457 {
458 ws->width += 2 * mw->menu.margin;
459 ws->height += 2 * mw->menu.margin;
460 }
407} 461}
408 462
409 463
410 /* Display code */ 464 /* Display code */
465
411static void 466static void
412draw_arrow (mw, window, gc, x, y, width) 467draw_arrow (mw, window, gc, x, y, width, down_p)
413 XlwMenuWidget mw; 468 XlwMenuWidget mw;
414 Window window; 469 Window window;
415 GC gc; 470 GC gc;
416 int x; 471 int x;
417 int y; 472 int y;
418 int width; 473 int width;
474 int down_p;
419{ 475{
420 XPoint points [3]; 476 Display *dpy = XtDisplay (mw);
421 points [0].x = x; 477 GC top_gc = mw->menu.shadow_top_gc;
422 points [0].y = y + mw->menu.font->ascent; 478 GC bottom_gc = mw->menu.shadow_bottom_gc;
423 points [1].x = x; 479 int thickness = mw->menu.shadow_thickness;
424 points [1].y = y; 480 int height = width;
425 points [2].x = x + width; 481 XPoint pt[10];
426 points [2].y = y + mw->menu.font->ascent / 2; 482 /* alpha = atan (0.5)
483 factor = (1 + sin (alpha)) / cos (alpha) */
484 double factor = 1.62;
485 int thickness2 = thickness * factor;
486
487 y += (mw->menu.font->ascent + mw->menu.font->descent - height) / 2;
488
489 if (down_p)
490 {
491 GC temp;
492 temp = top_gc;
493 top_gc = bottom_gc;
494 bottom_gc = temp;
495 }
496
497 pt[0].x = x;
498 pt[0].y = y + height;
499 pt[1].x = x + thickness;
500 pt[1].y = y + height - thickness2;
501 pt[2].x = x + thickness2;
502 pt[2].y = y + thickness2;
503 pt[3].x = x;
504 pt[3].y = y;
505 XFillPolygon (dpy, window, top_gc, pt, 4, Convex, CoordModeOrigin);
506
507 pt[0].x = x;
508 pt[0].y = y;
509 pt[1].x = x + thickness;
510 pt[1].y = y + thickness2;
511 pt[2].x = x + width - thickness2;
512 pt[2].y = y + height / 2;
513 pt[3].x = x + width;
514 pt[3].y = y + height / 2;
515 XFillPolygon (dpy, window, top_gc, pt, 4, Convex, CoordModeOrigin);
427 516
428 XFillPolygon (XtDisplay (mw), window, gc, points, 3, Convex, 517 pt[0].x = x;
429 CoordModeOrigin); 518 pt[0].y = y + height;
519 pt[1].x = x + thickness;
520 pt[1].y = y + height - thickness2;
521 pt[2].x = x + width - thickness2;
522 pt[2].y = y + height / 2;
523 pt[3].x = x + width;
524 pt[3].y = y + height / 2;
525 XFillPolygon (dpy, window, bottom_gc, pt, 4, Convex, CoordModeOrigin);
430} 526}
431 527
528
529
432static void 530static void
433draw_shadow_rectangle (mw, window, x, y, width, height, erase_p) 531draw_shadow_rectangle (mw, window, x, y, width, height, erase_p, down_p)
434 XlwMenuWidget mw; 532 XlwMenuWidget mw;
435 Window window; 533 Window window;
436 int x; 534 int x;
@@ -438,12 +536,22 @@ draw_shadow_rectangle (mw, window, x, y, width, height, erase_p)
438 int width; 536 int width;
439 int height; 537 int height;
440 int erase_p; 538 int erase_p;
539 int down_p;
441{ 540{
442 Display *dpy = XtDisplay (mw); 541 Display *dpy = XtDisplay (mw);
443 GC top_gc = !erase_p ? mw->menu.shadow_top_gc : mw->menu.background_gc; 542 GC top_gc = !erase_p ? mw->menu.shadow_top_gc : mw->menu.background_gc;
444 GC bottom_gc = !erase_p ? mw->menu.shadow_bottom_gc : mw->menu.background_gc; 543 GC bottom_gc = !erase_p ? mw->menu.shadow_bottom_gc : mw->menu.background_gc;
445 int thickness = mw->menu.shadow_thickness; 544 int thickness = mw->menu.shadow_thickness;
446 XPoint points [4]; 545 XPoint points [4];
546
547 if (!erase_p && down_p)
548 {
549 GC temp;
550 temp = top_gc;
551 top_gc = bottom_gc;
552 bottom_gc = temp;
553 }
554
447 points [0].x = x; 555 points [0].x = x;
448 points [0].y = y; 556 points [0].y = y;
449 points [1].x = x + width; 557 points [1].x = x + width;
@@ -483,11 +591,273 @@ draw_shadow_rectangle (mw, window, x, y, width, height, erase_p)
483} 591}
484 592
485 593
594static void
595draw_shadow_rhombus (mw, window, x, y, width, height, erase_p, down_p)
596 XlwMenuWidget mw;
597 Window window;
598 int x;
599 int y;
600 int width;
601 int height;
602 int erase_p;
603 int down_p;
604{
605 Display *dpy = XtDisplay (mw);
606 GC top_gc = !erase_p ? mw->menu.shadow_top_gc : mw->menu.background_gc;
607 GC bottom_gc = !erase_p ? mw->menu.shadow_bottom_gc : mw->menu.background_gc;
608 int thickness = mw->menu.shadow_thickness;
609 XPoint points [4];
610 double sqrt2 = 1.4142;
611
612 if (!erase_p && down_p)
613 {
614 GC temp;
615 temp = top_gc;
616 top_gc = bottom_gc;
617 bottom_gc = temp;
618 }
619
620 points [0].x = x;
621 points [0].y = y + height / 2;
622 points [1].x = x + thickness;
623 points [1].y = y + height / 2;
624 points [2].x = x + width / 2;
625 points [2].y = y + thickness;
626 points [3].x = x + width / 2;
627 points [3].y = y;
628 XFillPolygon (dpy, window, top_gc, points, 4, Convex, CoordModeOrigin);
629 points [0].x = x + width / 2;
630 points [0].y = y;
631 points [1].x = x + width / 2;
632 points [1].y = y + thickness;
633 points [2].x = x + width - thickness;
634 points [2].y = y + height / 2;
635 points [3].x = x + width;
636 points [3].y = y + height / 2;
637 XFillPolygon (dpy, window, top_gc, points, 4, Convex, CoordModeOrigin);
638 points [0].x = x;
639 points [0].y = y + height / 2;
640 points [1].x = x + thickness;
641 points [1].y = y + height / 2;
642 points [2].x = x + width / 2;
643 points [2].y = y + height - thickness;
644 points [3].x = x + width / 2;
645 points [3].y = y + height;
646 XFillPolygon (dpy, window, bottom_gc, points, 4, Convex, CoordModeOrigin);
647 points [0].x = x + width / 2;
648 points [0].y = y + height;
649 points [1].x = x + width / 2;
650 points [1].y = y + height - thickness;
651 points [2].x = x + width - thickness;
652 points [2].y = y + height / 2;
653 points [3].x = x + width;
654 points [3].y = y + height / 2;
655 XFillPolygon (dpy, window, bottom_gc, points, 4, Convex, CoordModeOrigin);
656}
657
658
659/* Draw a toggle button on widget MW, X window WINDOW. X/Y is the
660 top-left corner of the menu item. SELECTED_P non-zero means the
661 toggle button is selected. */
662
663static void
664draw_toggle (mw, window, x, y, selected_p)
665 XlwMenuWidget mw;
666 Window window;
667 int x, y, selected_p;
668{
669 int width, height;
670
671 width = toggle_button_width (mw);
672 height = width;
673 x += mw->menu.horizontal_spacing;
674 y += (mw->menu.font->ascent - height) / 2;
675 draw_shadow_rectangle (mw, window, x, y, width, height, False, selected_p);
676}
677
678
679/* Draw a radio button on widget MW, X window WINDOW. X/Y is the
680 top-left corner of the menu item. SELECTED_P non-zero means the
681 toggle button is selected. */
682
683static void
684draw_radio (mw, window, x, y, selected_p)
685 XlwMenuWidget mw;
686 Window window;
687 int x, y, selected_p;
688{
689 int width, height;
690
691 width = radio_button_width (mw);
692 height = width;
693 x += mw->menu.horizontal_spacing;
694 y += (mw->menu.font->ascent - height) / 2;
695 draw_shadow_rhombus (mw, window, x, y, width, height, False, selected_p);
696}
697
698
699/* Draw a menu separator on widget MW, X window WINDOW. X/Y is the
700 top-left corner of the menu item. WIDTH is the width of the
701 separator to draw. TYPE is the separator type. */
702
703static void
704draw_separator (mw, window, x, y, width, type)
705 XlwMenuWidget mw;
706 Window window;
707 int x, y, width;
708 enum menu_separator type;
709{
710 Display *dpy = XtDisplay (mw);
711 XGCValues xgcv;
712
713 switch (type)
714 {
715 case SEPARATOR_NO_LINE:
716 break;
717
718 case SEPARATOR_SINGLE_LINE:
719 XDrawLine (dpy, window, mw->menu.foreground_gc,
720 x, y, x + width, y);
721 break;
722
723 case SEPARATOR_DOUBLE_LINE:
724 draw_separator (mw, window, x, y, width, SEPARATOR_SINGLE_LINE);
725 draw_separator (mw, window, x, y + 2, width, SEPARATOR_SINGLE_LINE);
726 break;
727
728 case SEPARATOR_SINGLE_DASHED_LINE:
729 xgcv.line_style = LineOnOffDash;
730 XChangeGC (dpy, mw->menu.foreground_gc, GCLineStyle, &xgcv);
731 XDrawLine (dpy, window, mw->menu.foreground_gc,
732 x, y, x + width, y);
733 xgcv.line_style = LineSolid;
734 XChangeGC (dpy, mw->menu.foreground_gc, GCLineStyle, &xgcv);
735 break;
736
737 case SEPARATOR_DOUBLE_DASHED_LINE:
738 draw_separator (mw, window, x, y, width,
739 SEPARATOR_SINGLE_DASHED_LINE);
740 draw_separator (mw, window, x, y + 2, width,
741 SEPARATOR_SINGLE_DASHED_LINE);
742 break;
743
744 case SEPARATOR_SHADOW_ETCHED_IN:
745 XDrawLine (dpy, window, mw->menu.shadow_bottom_gc,
746 x, y, x + width, y);
747 XDrawLine (dpy, window, mw->menu.shadow_top_gc,
748 x, y + 1, x + width, y + 1);
749 break;
750
751 case SEPARATOR_SHADOW_ETCHED_OUT:
752 XDrawLine (dpy, window, mw->menu.shadow_top_gc,
753 x, y, x + width, y);
754 XDrawLine (dpy, window, mw->menu.shadow_bottom_gc,
755 x, y + 1, x + width, y + 1);
756 break;
757
758 case SEPARATOR_SHADOW_ETCHED_IN_DASH:
759 xgcv.line_style = LineOnOffDash;
760 XChangeGC (dpy, mw->menu.shadow_bottom_gc, GCLineStyle, &xgcv);
761 XChangeGC (dpy, mw->menu.shadow_top_gc, GCLineStyle, &xgcv);
762 draw_separator (mw, window, x, y, SEPARATOR_SHADOW_ETCHED_IN);
763 xgcv.line_style = LineSolid;
764 XChangeGC (dpy, mw->menu.shadow_bottom_gc, GCLineStyle, &xgcv);
765 XChangeGC (dpy, mw->menu.shadow_top_gc, GCLineStyle, &xgcv);
766 break;
767
768 case SEPARATOR_SHADOW_ETCHED_OUT_DASH:
769 xgcv.line_style = LineOnOffDash;
770 XChangeGC (dpy, mw->menu.shadow_bottom_gc, GCLineStyle, &xgcv);
771 XChangeGC (dpy, mw->menu.shadow_top_gc, GCLineStyle, &xgcv);
772 draw_separator (mw, window, x, y, SEPARATOR_SHADOW_ETCHED_OUT);
773 xgcv.line_style = LineSolid;
774 XChangeGC (dpy, mw->menu.shadow_bottom_gc, GCLineStyle, &xgcv);
775 XChangeGC (dpy, mw->menu.shadow_top_gc, GCLineStyle, &xgcv);
776 break;
777
778 case SEPARATOR_SHADOW_DOUBLE_ETCHED_IN:
779 draw_separator (mw, window, x, y, width, SEPARATOR_SHADOW_ETCHED_IN);
780 draw_separator (mw, window, x, y + 3, width, SEPARATOR_SHADOW_ETCHED_IN);
781 break;
782
783 case SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT:
784 draw_separator (mw, window, x, y, width,
785 SEPARATOR_SHADOW_ETCHED_OUT);
786 draw_separator (mw, window, x, y + 3, width,
787 SEPARATOR_SHADOW_ETCHED_OUT);
788 break;
789
790 case SEPARATOR_SHADOW_DOUBLE_ETCHED_IN_DASH:
791 xgcv.line_style = LineOnOffDash;
792 XChangeGC (dpy, mw->menu.shadow_bottom_gc, GCLineStyle, &xgcv);
793 XChangeGC (dpy, mw->menu.shadow_top_gc, GCLineStyle, &xgcv);
794 draw_separator (mw, window, x, y, width,
795 SEPARATOR_SHADOW_DOUBLE_ETCHED_IN);
796 xgcv.line_style = LineSolid;
797 XChangeGC (dpy, mw->menu.shadow_bottom_gc, GCLineStyle, &xgcv);
798 XChangeGC (dpy, mw->menu.shadow_top_gc, GCLineStyle, &xgcv);
799 break;
800
801 case SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT_DASH:
802 xgcv.line_style = LineOnOffDash;
803 XChangeGC (dpy, mw->menu.shadow_bottom_gc, GCLineStyle, &xgcv);
804 XChangeGC (dpy, mw->menu.shadow_top_gc, GCLineStyle, &xgcv);
805 draw_separator (mw, window, x, y, width,
806 SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT);
807 xgcv.line_style = LineSolid;
808 XChangeGC (dpy, mw->menu.shadow_bottom_gc, GCLineStyle, &xgcv);
809 XChangeGC (dpy, mw->menu.shadow_top_gc, GCLineStyle, &xgcv);
810 break;
811
812 default:
813 abort ();
814 }
815}
816
817
818/* Return the pixel height of menu separator SEPARATOR. */
819
820static int
821separator_height (separator)
822 enum menu_separator separator;
823{
824 switch (separator)
825 {
826 case SEPARATOR_NO_LINE:
827 return 2;
828
829 case SEPARATOR_SINGLE_LINE:
830 case SEPARATOR_SINGLE_DASHED_LINE:
831 return 1;
832
833 case SEPARATOR_DOUBLE_LINE:
834 case SEPARATOR_DOUBLE_DASHED_LINE:
835 return 3;
836
837 case SEPARATOR_SHADOW_ETCHED_IN:
838 case SEPARATOR_SHADOW_ETCHED_OUT:
839 case SEPARATOR_SHADOW_ETCHED_IN_DASH:
840 case SEPARATOR_SHADOW_ETCHED_OUT_DASH:
841 return 2;
842
843 case SEPARATOR_SHADOW_DOUBLE_ETCHED_IN:
844 case SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT:
845 case SEPARATOR_SHADOW_DOUBLE_ETCHED_IN_DASH:
846 case SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT_DASH:
847 return 5;
848
849 default:
850 abort ();
851 }
852}
853
854
486/* Display the menu item and increment where.x and where.y to show how large 855/* Display the menu item and increment where.x and where.y to show how large
487** the menu item was. 856 the menu item was. */
488*/ 857
489static void 858static void
490display_menu_item (mw, val, ws, where, highlighted_p, horizontal_p, just_compute_p) 859display_menu_item (mw, val, ws, where, highlighted_p, horizontal_p,
860 just_compute_p)
491 XlwMenuWidget mw; 861 XlwMenuWidget mw;
492 widget_value* val; 862 widget_value* val;
493 window_state* ws; 863 window_state* ws;
@@ -501,17 +871,20 @@ display_menu_item (mw, val, ws, where, highlighted_p, horizontal_p, just_compute
501 int font_ascent = mw->menu.font->ascent; 871 int font_ascent = mw->menu.font->ascent;
502 int font_descent = mw->menu.font->descent; 872 int font_descent = mw->menu.font->descent;
503 int shadow = mw->menu.shadow_thickness; 873 int shadow = mw->menu.shadow_thickness;
504 int separator_p = all_dashes_p (val->name); 874 int margin = mw->menu.margin;
505 int h_spacing = mw->menu.horizontal_spacing; 875 int h_spacing = mw->menu.horizontal_spacing;
506 int v_spacing = mw->menu.vertical_spacing; 876 int v_spacing = mw->menu.vertical_spacing;
507 int label_width; 877 int label_width;
508 int rest_width; 878 int rest_width;
879 int button_width;
509 int height; 880 int height;
510 int width; 881 int width;
511 int button_p; 882 enum menu_separator separator;
883 int separator_p = lw_separator_p (val->name, &separator, 0);
512 884
513 /* compute the sizes of the item */ 885 /* compute the sizes of the item */
514 size_menu_item (mw, val, horizontal_p, &label_width, &rest_width, &height); 886 size_menu_item (mw, val, horizontal_p, &label_width, &rest_width,
887 &button_width, &height);
515 888
516 if (horizontal_p) 889 if (horizontal_p)
517 width = label_width + rest_width; 890 width = label_width + rest_width;
@@ -521,12 +894,6 @@ display_menu_item (mw, val, ws, where, highlighted_p, horizontal_p, just_compute
521 width = ws->width - 2 * shadow; 894 width = ws->width - 2 * shadow;
522 } 895 }
523 896
524#if 0
525 /* see if it should be a button in the menubar */
526 button_p = horizontal_p && val->call_data;
527#endif
528 button_p = 0;
529
530 /* Only highlight an enabled item that has a callback. */ 897 /* Only highlight an enabled item that has a callback. */
531 if (highlighted_p) 898 if (highlighted_p)
532 if (!val->enabled || !(val->call_data || val->contents)) 899 if (!val->enabled || !(val->call_data || val->contents))
@@ -539,26 +906,29 @@ display_menu_item (mw, val, ws, where, highlighted_p, horizontal_p, just_compute
539 int x = where->x + shadow; 906 int x = where->x + shadow;
540 int y = where->y + shadow; 907 int y = where->y + shadow;
541 908
909 if (horizontal_p)
910 {
911 x += margin;
912 y += margin;
913 }
914
542 /* pick the foreground and background GC. */ 915 /* pick the foreground and background GC. */
543 if (val->enabled) 916 if (val->enabled)
544 text_gc = button_p ? mw->menu.button_gc : mw->menu.foreground_gc; 917 text_gc = mw->menu.foreground_gc;
545 else 918 else
546 text_gc = 919 text_gc = mw->menu.inactive_gc;
547 button_p ? mw->menu.inactive_button_gc : mw->menu.inactive_gc;
548 deco_gc = mw->menu.foreground_gc; 920 deco_gc = mw->menu.foreground_gc;
549 921
550 if (separator_p) 922 if (separator_p)
551 { 923 {
552 XDrawLine (XtDisplay (mw), ws->window, mw->menu.shadow_bottom_gc, 924 draw_separator (mw, ws->window, x, y, width, separator);
553 x, y, x + width, y);
554 XDrawLine (XtDisplay (mw), ws->window, mw->menu.shadow_top_gc,
555 x, y + 1, x + width, y + 1);
556 } 925 }
557 else 926 else
558 { 927 {
559 int x_offset = x + h_spacing + shadow; 928 int x_offset = x + h_spacing + shadow;
560 char* display_string = resource_widget_value (mw, val); 929 char* display_string = resource_widget_value (mw, val);
561 draw_shadow_rectangle (mw, ws->window, x, y, width, height, True); 930 draw_shadow_rectangle (mw, ws->window, x, y, width, height, True,
931 False);
562 932
563 /* Deal with centering a menu title. */ 933 /* Deal with centering a menu title. */
564 if (!horizontal_p && !val->contents && !val->call_data) 934 if (!horizontal_p && !val->contents && !val->call_data)
@@ -568,20 +938,32 @@ display_menu_item (mw, val, ws, where, highlighted_p, horizontal_p, just_compute
568 if (width > l) 938 if (width > l)
569 x_offset = (width - l) >> 1; 939 x_offset = (width - l) >> 1;
570 } 940 }
941 else if (!horizontal_p && ws->button_width)
942 x_offset += ws->button_width;
943
944
571 XDrawString (XtDisplay (mw), ws->window, text_gc, x_offset, 945 XDrawString (XtDisplay (mw), ws->window, text_gc, x_offset,
572 y + v_spacing + shadow + font_ascent, 946 y + v_spacing + shadow + font_ascent,
573 display_string, strlen (display_string)); 947 display_string, strlen (display_string));
574 948
575 if (!horizontal_p) 949 if (!horizontal_p)
576 { 950 {
951 if (val->button_type == BUTTON_TYPE_TOGGLE)
952 draw_toggle (mw, ws->window, x, y + v_spacing + shadow,
953 val->selected);
954 else if (val->button_type == BUTTON_TYPE_RADIO)
955 draw_radio (mw, ws->window, x, y + v_spacing + shadow,
956 val->selected);
957
577 if (val->contents) 958 if (val->contents)
578 { 959 {
579 int a_w = arrow_width (mw); 960 int a_w = arrow_width (mw);
580 draw_arrow (mw, ws->window, deco_gc, 961 draw_arrow (mw, ws->window, deco_gc,
581 x + width - arrow_width (mw) 962 x + width - a_w
582 - mw->menu.horizontal_spacing 963 - mw->menu.horizontal_spacing
583 - mw->menu.shadow_thickness, 964 - mw->menu.shadow_thickness,
584 y + v_spacing + shadow, a_w); 965 y + v_spacing + shadow, a_w,
966 highlighted_p);
585 } 967 }
586 else if (val->key) 968 else if (val->key)
587 { 969 {
@@ -591,20 +973,6 @@ display_menu_item (mw, val, ws, where, highlighted_p, horizontal_p, just_compute
591 val->key, strlen (val->key)); 973 val->key, strlen (val->key));
592 } 974 }
593 } 975 }
594
595 else if (button_p)
596 {
597#if 1
598 XDrawRectangle (XtDisplay (mw), ws->window, deco_gc,
599 x + shadow, y + shadow,
600 label_width + h_spacing - 1,
601 font_ascent + font_descent + 2 * v_spacing - 1);
602 draw_shadow_rectangle (mw, ws->window, x, y, width, height,
603 False);
604#else
605 highlighted_p = True;
606#endif
607 }
608 else 976 else
609 { 977 {
610 XDrawRectangle (XtDisplay (mw), ws->window, 978 XDrawRectangle (XtDisplay (mw), ws->window,
@@ -613,11 +981,12 @@ display_menu_item (mw, val, ws, where, highlighted_p, horizontal_p, just_compute
613 label_width + h_spacing - 1, 981 label_width + h_spacing - 1,
614 font_ascent + font_descent + 2 * v_spacing - 1); 982 font_ascent + font_descent + 2 * v_spacing - 1);
615 draw_shadow_rectangle (mw, ws->window, x, y, width, height, 983 draw_shadow_rectangle (mw, ws->window, x, y, width, height,
616 True); 984 True, False);
617 } 985 }
618 986
619 if (highlighted_p) 987 if (highlighted_p)
620 draw_shadow_rectangle (mw, ws->window, x, y, width, height, False); 988 draw_shadow_rectangle (mw, ws->window, x, y, width, height, False,
989 False);
621 } 990 }
622 } 991 }
623 992
@@ -647,9 +1016,10 @@ display_menu (mw, level, just_compute_p, highlighted_pos, hit, hit_return,
647 /* This is set nonzero if the element containing HIGHLIGHTED_POS 1016 /* This is set nonzero if the element containing HIGHLIGHTED_POS
648 is disabled, so that we do not return any subsequent element either. */ 1017 is disabled, so that we do not return any subsequent element either. */
649 int no_return = 0; 1018 int no_return = 0;
1019 enum menu_separator separator;
650 1020
651 if (level >= mw->menu.old_depth) 1021 if (level >= mw->menu.old_depth)
652 abort (); 1022 abort_gracefully ((Widget) mw);
653 1023
654 if (level < mw->menu.old_depth - 1) 1024 if (level < mw->menu.old_depth - 1)
655 following_item = mw->menu.old_stack [level + 1]; 1025 following_item = mw->menu.old_stack [level + 1];
@@ -691,7 +1061,7 @@ display_menu (mw, level, just_compute_p, highlighted_pos, hit, hit_return,
691 if (hit 1061 if (hit
692 && !*hit_return 1062 && !*hit_return
693 && (horizontal_p ? hit->x < where.x : hit->y < where.y) 1063 && (horizontal_p ? hit->x < where.x : hit->y < where.y)
694 && !all_dashes_p (val->name) 1064 && !lw_separator_p (val->name, &separator, 0)
695 && !no_return) 1065 && !no_return)
696 { 1066 {
697 if (val->enabled) 1067 if (val->enabled)
@@ -707,7 +1077,8 @@ display_menu (mw, level, just_compute_p, highlighted_pos, hit, hit_return,
707 } 1077 }
708 1078
709 if (!just_compute_p) 1079 if (!just_compute_p)
710 draw_shadow_rectangle (mw, ws->window, 0, 0, ws->width, ws->height, False); 1080 draw_shadow_rectangle (mw, ws->window, 0, 0, ws->width, ws->height,
1081 False, False);
711} 1082}
712 1083
713 /* Motion code */ 1084 /* Motion code */
@@ -889,12 +1260,20 @@ remap_menubar (mw)
889 window_state *previous_ws = &windows[i - 1]; 1260 window_state *previous_ws = &windows[i - 1];
890 window_state *ws = &windows[i]; 1261 window_state *ws = &windows[i];
891 1262
892 ws->x 1263 ws->x = (previous_ws->x + selection_position.x
893 = previous_ws->x + selection_position.x + mw->menu.shadow_thickness; 1264 + mw->menu.shadow_thickness);
1265 if (i == 1)
1266 ws->x += mw->menu.margin;
1267
1268#if 0
894 if (!mw->menu.horizontal || i > 1) 1269 if (!mw->menu.horizontal || i > 1)
895 ws->x += mw->menu.shadow_thickness; 1270 ws->x += mw->menu.shadow_thickness;
896 ws->y 1271#endif
897 = previous_ws->y + selection_position.y + mw->menu.shadow_thickness; 1272
1273 ws->y = (previous_ws->y + selection_position.y
1274 + mw->menu.shadow_thickness);
1275 if (i == 1)
1276 ws->y += mw->menu.margin;
898 1277
899 size_menu (mw, i); 1278 size_menu (mw, i);
900 1279
@@ -1035,7 +1414,8 @@ make_shadow_gcs (mw)
1035 XGCValues xgcv; 1414 XGCValues xgcv;
1036 unsigned long pm = 0; 1415 unsigned long pm = 0;
1037 Display *dpy = XtDisplay ((Widget) mw); 1416 Display *dpy = XtDisplay ((Widget) mw);
1038 Colormap cmap = DefaultColormapOfScreen (XtScreen ((Widget) mw)); 1417 Screen *screen = XtScreen ((Widget) mw);
1418 Colormap cmap = DefaultColormapOfScreen (screen);
1039 XColor topc, botc; 1419 XColor topc, botc;
1040 int top_frobbed = 0, bottom_frobbed = 0; 1420 int top_frobbed = 0, bottom_frobbed = 0;
1041 1421
@@ -1053,7 +1433,11 @@ make_shadow_gcs (mw)
1053 topc.red = MINL (65535, topc.red * 1.2); 1433 topc.red = MINL (65535, topc.red * 1.2);
1054 topc.green = MINL (65535, topc.green * 1.2); 1434 topc.green = MINL (65535, topc.green * 1.2);
1055 topc.blue = MINL (65535, topc.blue * 1.2); 1435 topc.blue = MINL (65535, topc.blue * 1.2);
1436#ifdef emacs
1437 if (x_alloc_nearest_color (dpy, screen, cmap, &topc))
1438#else
1056 if (XAllocColor (dpy, cmap, &topc)) 1439 if (XAllocColor (dpy, cmap, &topc))
1440#endif
1057 { 1441 {
1058 mw->menu.top_shadow_color = topc.pixel; 1442 mw->menu.top_shadow_color = topc.pixel;
1059 top_frobbed = 1; 1443 top_frobbed = 1;
@@ -1067,7 +1451,11 @@ make_shadow_gcs (mw)
1067 botc.red *= 0.6; 1451 botc.red *= 0.6;
1068 botc.green *= 0.6; 1452 botc.green *= 0.6;
1069 botc.blue *= 0.6; 1453 botc.blue *= 0.6;
1454#ifdef emacs
1455 if (x_alloc_nearest_color (dpy, screen, cmap, &botc))
1456#else
1070 if (XAllocColor (dpy, cmap, &botc)) 1457 if (XAllocColor (dpy, cmap, &botc))
1458#endif
1071 { 1459 {
1072 mw->menu.bottom_shadow_color = botc.pixel; 1460 mw->menu.bottom_shadow_color = botc.pixel;
1073 bottom_frobbed = 1; 1461 bottom_frobbed = 1;