static UI_CALLBACK(submenu_popdown_callback) { submenu_popped_up--; #if 0 /* doesn't seem to be needed */ if (XawSimpleMenuGetActiveEntry(w)) { #if MENU_DEBUG printf("calling XtPopdown(%p)\n", client_data); #endif XtPopdown((Widget)client_data); } #endif active_submenu = 0; }
/* * Usually called from a key press, but there is no reason it can't * be called from a button event. * * Accepts 1 numeric parameter: if nonzero, the menu stays up instead * of popping down. */ static void menu_select_action(Widget w, XEvent *event, String *params, Cardinal *num_params) { int keep_menu_up = 0; if (*num_params == 1) { keep_menu_up = atoi(*params); } if (event->type == KeyPress || event->type == KeyRelease) { XtWidgetGeometry geometry; Widget old_active_entry; /* * Keyboard events bubble up to the top menu, because the top is * "spring loaded", So we may get to see them multiple times for * different widgets, if the mouse happens to be in a submenu. To * put a stop to that: only listen to the top_menu. */ if (w != top_menu) { #if MENU_DEBUG printf("menu_select_action: ignoring event, not top_menu\n"); #endif return; } /* * Apparently, notify() looks at the event coordinates to know * which item should be notify()d, instead of just doing the * active one. So fake them. * It also looks if the event's window matches the widget, * presumably also because of spring-loaded menus. Fake that too. * To look at the coordinates, it checks the event type, and it * doesn't know about keys. More faking. */ old_active_entry = XawSimpleMenuGetActiveEntry(active_keyboard_menu); if (!old_active_entry) { return; } fake_button_action(w, event, NULL, NULL); /* notify() cares */ XtQueryGeometry(old_active_entry, NULL, &geometry); event->xbutton.x = geometry.x + 1; event->xbutton.y = geometry.y + 1; w = active_keyboard_menu; event->xany.window = XtWindow(w); /* notify() cares about this */ } do_menu_select(w, event, keep_menu_up); }
/* * Sub Popup Open [action] */ XtActionProc SubPopup(Widget w,XEvent *e,String *par,Cardinal *n) { int ex,ey; Position x,y; Dimension xw,yh; Widget cur_item,item,menu; Window tmp1; int tmp2; cur_item = XawSimpleMenuGetActiveEntry(w); if (cur_item == pmColor) { item = pmColor; menu = pcTop; } else if (cur_item == pmFont) { item = pmFont; menu = pfTop; } else return; ex = e->xmotion.x; ey = e->xmotion.y; XtVaGetValues(item, XtNx,&x, XtNy,&y, XtNwidth,&xw, XtNheight,&yh, NULL); if ((ex < x + xw*3/4) ||(ey < y) ||(ey > y + yh)) return; x = e->xmotion.x_root; y = e->xmotion.y_root; XtVaGetValues(menu,XtNwidth,&xw,NULL); x -= xw/2; y -= 8; XtVaSetValues(menu,XtNx,x,XtNy,y,NULL); XtPopup(menu,XtGrabExclusive); }
/* Yes, this sucks. Sorry. */ static void position_submenu_action(Widget w, XEvent *event, String *params, Cardinal *num_params) { Widget new_active_submenu, new_active_entry; new_active_entry = XawSimpleMenuGetActiveEntry(w); if (new_active_entry != active_entry) { int i, level; int level_found, active_found; new_active_submenu = NULL; /* Find the submenu for the current active menu item and the level of this submenu. */ for (level_found = active_found = 0, level = 0, i = 0; i < num_submenus && !(level_found && active_found); i++) { if (!active_found && submenus[i].parent == new_active_entry) { new_active_submenu = submenus[i].widget; active_found = 1; } if (!level_found && submenus[i].widget == w) { level = submenus[i].level; level_found = 1; } } /* Remove all the submenus whose level is higher than this submenu. */ for (i = 0; i < num_submenus; i++) { if (submenus[i].level > level) { XtPopdown(submenus[i].widget); } } /* Position the submenu for this menu item. */ if (new_active_submenu != NULL && new_active_entry != NULL) { position_submenu(new_active_submenu, new_active_entry); } active_submenu = new_active_submenu; active_entry = new_active_entry; } }
/* ARGSUSED */ static void XawSmeBSBRedisplay(Widget w, XEvent *event, Region region) { GC gc; SmeBSBObject entry = (SmeBSBObject)w; int font_ascent, font_descent, y_loc; int fontset_ascent, fontset_descent; XFontSetExtents *ext = XExtentsOfFontSet(entry->sme_bsb.fontset); font_ascent = font_descent = fontset_ascent = fontset_descent = 0; entry->sme_bsb.set_values_area_cleared = False; if (entry->sme.international == True) { fontset_ascent = XawAbs(ext->max_ink_extent.y); fontset_descent = ext->max_ink_extent.height - fontset_ascent; } else { font_ascent = entry->sme_bsb.font->max_bounds.ascent; font_descent = entry->sme_bsb.font->max_bounds.descent; } y_loc = XtY(entry); if (XtIsSensitive(w) && XtIsSensitive(XtParent(w))) { if (w == XawSimpleMenuGetActiveEntry(XtParent(w))) { XFillRectangle(XtDisplayOfObject(w), XtWindowOfObject(w), entry->sme_bsb.norm_gc, XtX(w), y_loc, XtWidth(entry), XtHeight(entry)); gc = entry->sme_bsb.rev_gc; } else gc = entry->sme_bsb.norm_gc; } else gc = entry->sme_bsb.norm_gray_gc; if (entry->sme_bsb.label != NULL) { int x_loc = entry->sme_bsb.left_margin; int len = strlen(entry->sme_bsb.label); char *label = entry->sme_bsb.label; int width, t_width; switch(entry->sme_bsb.justify) { case XtJustifyCenter: if (entry->sme.international == True) { t_width = XmbTextEscapement(entry->sme_bsb.fontset,label, len); width = XtWidth(entry) - (entry->sme_bsb.left_margin + entry->sme_bsb.right_margin); } else { t_width = XTextWidth(entry->sme_bsb.font, label, len); width = XtWidth(entry) - (entry->sme_bsb.left_margin + entry->sme_bsb.right_margin); } x_loc += (width - t_width) >> 1; break; case XtJustifyRight: if (entry->sme.international == True) { t_width = XmbTextEscapement(entry->sme_bsb.fontset,label, len); x_loc = XtWidth(entry) - (entry->sme_bsb.right_margin + t_width); } else { t_width = XTextWidth(entry->sme_bsb.font, label, len); x_loc = XtWidth(entry) - (entry->sme_bsb.right_margin + t_width); } break; case XtJustifyLeft: /*FALLTHROUGH*/ default: break; } /* this will center the text in the gadget top-to-bottom */ if (entry->sme.international == True) { y_loc += ((XtHeight(entry) - (fontset_ascent + fontset_descent)) >> 1) + fontset_ascent; XmbDrawString(XtDisplayOfObject(w), XtWindowOfObject(w), entry->sme_bsb.fontset, gc, XtX(w) + x_loc, y_loc, label, len); }
static void menu_nextprev_item(Widget w, XEvent *event, int incr) { Widget old_active_entry; Widget new_active_entry = NULL; WidgetList children; Cardinal numChildren; int i = 0, found = 0, wrapped = 0; if (w != top_menu) { #if MENU_DEBUG printf("menu_nextprev_item_action: ignoring event, not top_menu\n"); #endif return; } /* * Find which smeBSB object is the active one. */ XtVaGetValues(active_keyboard_menu, XtNchildren, &children, XtNnumChildren, &numChildren, NULL); /* * If there are not at least 2 children * then there is no point in even trying to go up or down. * Besides, might go out of the array's bounds. */ if (numChildren < 2) { return; } old_active_entry = XawSimpleMenuGetActiveEntry(active_keyboard_menu); if (old_active_entry) { for (i = 0; i < numChildren; i++) { if (children[i] == old_active_entry) { found = 1; break; } } } /* * If no item was active, start at the top or the bottom. */ if (!found) { i = (incr > 0) ? -incr : numChildren; } /* * Find the next sensitive item, going either up or down. * Note that we made the separator lines non-sensitive, just for this. * Do wrap around, but no more than once, that would be an endless loop. */ while (wrapped < 2) { Boolean flag; i += incr; if (i < 0) { i = numChildren - 1; wrapped++; } else if (i >= numChildren) { i = 0; wrapped++; } XtVaGetValues(children[i], XtNsensitive, &flag, NULL); if (flag) { new_active_entry = children[i]; break; } } if (new_active_entry && new_active_entry != old_active_entry) { XtWidgetGeometry geometry; int x, y; XtQueryGeometry(new_active_entry, NULL, &geometry); x = geometry.x + 1; y = geometry.y + 1; do_fake_motion(active_keyboard_menu, event, x, y); } }