📄 menu.c
字号:
return 1; do { w->droppedmenu->current = (w->droppedmenu->current + 1) % w->droppedmenu->numlines; } while (w->droppedmenu->menu[w->droppedmenu->current].text[2] == 0); render_menu (w->droppedmenu); return 1; } if (is_focus_prev_key (c, cwevent->command, xevent->xkey.state)) { f = CPreviousFocus (w); while (f->kind != C_MENU_BUTTON_WIDGET && (unsigned long) f != (unsigned long) w) f = CPreviousFocus (f); if (f) { CFocus (f); if (w->droppedmenu) CMenuSelectionDialog (f); } return 1; } if (is_focus_change_key (c, cwevent->command)) { f = CNextFocus (w); while (f->kind != C_MENU_BUTTON_WIDGET && (unsigned long) f != (unsigned long) w) f = CNextFocus (f); if (f) { CFocus (f); if (w->droppedmenu) CMenuSelectionDialog (f); } return 1; } if (w->droppedmenu && c) { int i; if (c == XK_Return || c == XK_KP_Enter || c == XK_space) { return execute_item (w->droppedmenu, w->droppedmenu->current); } else { for (i = 0; i < w->droppedmenu->numlines; i++) if (match_hotkey (c, w->droppedmenu->menu[i].hot_key)) return execute_item (w->droppedmenu, i); } } if (cwevent->command != CK_Up && cwevent->command != CK_Down) return 0; case ButtonPress: if (xevent->type == ButtonPress) { w->options &= 0xFFFFFFFFUL - BUTTON_PRESSED - BUTTON_HIGHLIGHT; w->options |= BUTTON_PRESSED; } render_menu_button (w); if (!w->droppedmenu) CMenuSelectionDialog (w); return 1; break; case ButtonRelease: w->options &= 0xFFFFFFFFUL - BUTTON_PRESSED - BUTTON_HIGHLIGHT; w->options |= BUTTON_HIGHLIGHT; render_menu_button (w); return 1; case MotionNotify: if (!w->droppedmenu && menu_grabbed) { pull_down (w); CFocus (w); } return 1; case EnterNotify: w->options &= 0xFFFFFFFFUL - BUTTON_PRESSED - BUTTON_HIGHLIGHT; w->options |= BUTTON_HIGHLIGHT; render_menu_button (w); break; case Expose: if (xevent->xexpose.count) break; case LeaveNotify: w->options &= 0xFFFFFFFFUL - BUTTON_PRESSED - BUTTON_HIGHLIGHT; render_menu_button (w); break; } return 0;}int eh_menu (CWidget * w, XEvent * xevent, CEvent * cwevent){ static Window win = 0; static int current = -30000; switch (xevent->type) { case MotionNotify: w->current = whereis_pointer (xevent->xmotion.x, xevent->xmotion.y, w->width, w->numlines, w->menu); if (w->current == current && w->winid == win) break; current = w->current; win = w->winid; render_menu (w); break; case ButtonRelease: return execute_item (w, whereis_pointer (xevent->xmotion.x, xevent->xmotion.y, w->width, w->numlines, w->menu)); case ButtonPress: w->current = whereis_pointer (xevent->xmotion.x, xevent->xmotion.y, w->width, w->numlines, w->menu); render_menu (w); break; case Expose: if (xevent->xexpose.count) break; case LeaveNotify: current = w->current = w->droppedmenu->current; render_menu (w); break; } return 0;}CWidget *CDrawMenuButton (const char *ident, Window parent, Window focus_return, int x, int y, int width, int height, int num_items, const char *label,...){ va_list ap; CWidget *wdt; struct menu_item *m; int i; int w, h; if (width == AUTO_WIDTH || height == AUTO_HEIGHT) CTextSize (&w, &h, label); if (width == AUTO_WIDTH) width = w + 4 + BUTTON_RELIEF * 2; if (height == AUTO_HEIGHT) height = h + 4 + BUTTON_RELIEF * 2; wdt = CSetupWidget (ident, parent, x, y, width, height, C_MENU_BUTTON_WIDGET, INPUT_KEY | OwnerGrabButtonMask, COLOR_FLAT, 1); wdt->options |= MENU_AUTO_PULL_UP; /* default */ set_hint_pos (x + width, y + height + WIDGET_SPACING); wdt->label = (char *) strdup (label); wdt->hotkey = find_hotkey (wdt); wdt->options |= WIDGET_HOTKEY_ACTIVATES; m = CMalloc ((num_items ? num_items : 1) * sizeof (struct menu_item)); va_start (ap, label); for (i = 0; i < num_items; i++) { char *text; text = va_arg (ap, char *); text = text ? text : ""; m[i].text = (char *) strdup (catstrs (" ", text, " ", 0)); m[i].hot_key = va_arg (ap, int); m[i].call_back = va_arg (ap, callfn); m[i].data = va_arg (ap, unsigned long); } va_end (ap); wdt->destroy = destroy_menu; wdt->numlines = num_items; wdt->menu = m; wdt->eh = eh_menubutton; return wdt;}void insert_menu_item (CWidget * w, int i, const char *text, int hot_key, callfn call_back, unsigned long data){ struct menu_item *m; m = CMalloc ((w->numlines + 1) * sizeof (struct menu_item)); memcpy (m, w->menu, i * sizeof (struct menu_item)); memcpy (m + i + 1, w->menu + i, (w->numlines - i) * sizeof (struct menu_item)); free (w->menu); w->menu = m; m[i].text = (char *) strdup (catstrs (" ", text, " ", 0)); m[i].hot_key = hot_key; m[i].call_back = call_back; m[i].data = data; w->numlines++; if (w->droppedmenu != 0) { w->droppedmenu->menu = m; w->droppedmenu->numlines = w->numlines; w->droppedmenu->current = w->current; render_menu (w->droppedmenu); }}void CAddMenuItem (const char *ident, const char *text, int hot_key, callfn call_back, unsigned long data){ CWidget *w; w = CIdent (ident); if (!w) { CErrorDialog (0, 0, 0, _ (" Add Menu Item "), " %s: %s ", _ ("No such menu"), ident); return; } insert_menu_item (w, w->numlines, text, hot_key, call_back, data);}void CInsertMenuItem (const char *ident, const char *after, const char *text, int hot_key, callfn call_back, unsigned long data){ int i; CWidget *w; w = CIdent (ident); if (!w) { CErrorDialog (0, 0, 0, _ (" Insert Menu Item "), " %s: %s ", _ ("No such menu"), ident); return; } i = CHasMenuItem (ident, after); if (i < 0) { CErrorDialog (0, 0, 0, _ (" Insert Menu Item "), " %s: %s ", _ ("No such item"), after); return; } insert_menu_item (w, i, text, hot_key, call_back, data);}static void remove_item (CWidget * w, int i){ if (!w) return; if (i >= w->numlines || i < 0) return; if (w->menu[i].text) free (w->menu[i].text); w->numlines--; memmove (&w->menu[i], &w->menu[i + 1], (w->numlines - i) * sizeof (struct menu_item)); if (w->current == i) w->current = -1; else if (w->current > i) w->current--; if (w->droppedmenu != 0) { w->droppedmenu->numlines = w->numlines; w->droppedmenu->current = w->current; }}void CRemoveMenuItemNumber (const char *ident, int i){ CWidget *w; w = CIdent (ident); remove_item (w, i);}/* Starts from the bottom of the menu and searches for the first menu item containing text (strstr != NULL), and returns the integer. */int CHasMenuItem (const char *ident, const char *text){ CWidget *w; int i; w = CIdent (ident); if (!w) return -1; if (w->numlines) for (i = w->numlines - 1; i >= 0; i--) if (strstr (w->menu[i].text, text) || !*text) return i; return -1;}/* Starts from the bottom of the menu and searches for the first menu item containing text (strstr != NULL), and deletes it. */void CRemoveMenuItem (const char *ident, const char *text){ remove_item (CIdent (ident), CHasMenuItem (ident, text));}void CReplaceMenuItem (const char *ident, const char *old_text, const char *new_text, int hot_key, callfn call_back, unsigned long data){ struct menu_item *m; CWidget *w; int i; w = CIdent (ident); if (!w) { CErrorDialog (0, 0, 0, _ (" Replace Menu Item "), " %s: %s ", _ ("No such menu"), ident); return; } i = CHasMenuItem (ident, old_text); if (i < 0) { CErrorDialog (0, 0, 0, _ (" Replace Menu Item "), " %s: %s ", _ ("No such item"), old_text); return; } m = w->menu; free (m[i].text); m[i].text = (char *) strdup (catstrs (" ", new_text, " ", 0)); m[i].hot_key = hot_key; m[i].call_back = call_back; m[i].data = data; if (w->droppedmenu != 0) render_menu (w->droppedmenu);}void CMenuSelectionDialog (CWidget * button){ CEvent cwevent; XEvent xevent;/* sanity check */ if (!button) return;/* drop the menu and focus on the button */ pull_down (button); CFocus (button);/* we are already inside this function */ if (menu_grabbed) return; menu_grabbed = 1;/* grab the pointer - we want events even when pointer is over other apps windows */ XGrabPointer (CDisplay, button->winid, True, ButtonPressMask | ButtonReleaseMask | ButtonMotionMask | PointerMotionMask | EnterWindowMask | LeaveWindowMask | OwnerGrabButtonMask, GrabModeAsync, GrabModeAsync, None, CGetCursorID (CURSOR_MENU), CurrentTime);/* current_pulled_button could go to zero if some handler does a pull_up of the menu */ while (current_pulled_button) { CNextEvent (&xevent, &cwevent);/* terminate the loop if we have a button press/release as the user expects */ if (xevent.type == ButtonRelease || xevent.type == ButtonPress) { CWidget *w; w = CWidgetOfWindow (xevent.xbutton.window); if (!w) break; if (w->kind != C_MENU_BUTTON_WIDGET && w->kind != C_MENU_WIDGET) break; if (xevent.xbutton.x >= w->width || xevent.xbutton.x < 0 || xevent.xbutton.y >= w->height || xevent.xbutton.y < 0) break; } }/* check if any menu up */ if (current_pulled_button) { pull_up (current_pulled_button); current_pulled_button = 0; }/* ungrab and return focus */ menu_grabbed = 0; XUngrabPointer (CDisplay, CurrentTime); CFocusLast ();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -