📄 coolnext.c
字号:
return p;}/* }}} key conversion utilities *//* {{{ focus cycling *//* returns 1 if the key pressed is usually a key to goto next focus */int is_focus_change_key (KeySym k, int command){ return (k == XK_Tab || k == XK_KP_Tab || k == XK_ISO_Left_Tab || k == XK_Down || k == XK_Up || k == XK_Left || k == XK_Right || k == XK_KP_Down || k == XK_KP_Up || k == XK_KP_Left || k == XK_KP_Right || command == CK_Right || command == CK_Left || command == CK_Tab || command == CK_Up || command == CK_Down);}/* returns 1 if the key pressed is usually a key to goto previous focus */int is_focus_prev_key (KeySym k, int command, unsigned int state){ return (k == XK_ISO_Left_Tab || (((state) & ShiftMask) && (k == XK_Tab || k == XK_KP_Tab || command == CK_Tab)) || k == XK_Left || k == XK_Up || k == XK_KP_Left || k == XK_KP_Up || command == CK_Left || command == CK_Up);}/* use above to in combination to make this next function unnecesary *//* int is_focus_next_key(KeySym k, int command, unsigned int state) *//* This shifts focus to the previous or next sibling widget. (usually the tab key is used, but also responds to up, down, left and right.) */static int CCheckTab (XEvent * xevent, CEvent * cwevent){ if (xevent->type == KeyPress) { KeySym k; CWidget *w; k = CKeySym (xevent); if (!is_focus_change_key (k, cwevent->command)) return 0; w = CWidgetOfWindow (xevent->xany.window); if (!w) CFocus (CFindFirstDescendent (xevent->xany.window)); else if (!w->takes_focus) CFocus (CChildFocus (w)); else if (is_focus_prev_key (k, cwevent->command, xevent->xkey.state)) CFocus (CPreviousFocus (w)); else CFocus (CNextFocus (w)); return (CGetFocus () != xevent->xany.window); /* was handled since the focus did actually change */ } return 0;}void click_on_widget (CWidget * w){ XEvent e; CFocus (w); if (w->options & WIDGET_HOTKEY_ACTIVATES) { memset (&e, 0, sizeof (XEvent)); e.xbutton.type = ButtonPress; e.xbutton.window = w->winid; e.xbutton.button = Button1; CSendEvent (&e); e.xbutton.type = ButtonRelease; CSendEvent (&e); e.xbutton.type = LeaveNotify; CSendEvent (&e); }}int match_hotkey (KeySym a, KeySym b){ if (isalpha (a & 0xFF) && isalpha (b & 0xFF) && my_lower_case (a) == my_lower_case (b)) return 1; if (a == b) return 1; return 0;}/* Check for hot keys of buttons, sends a ButtonPress to the button if the key found. */static int CCheckButtonHotKey (XEvent * xevent, CEvent * cwevent){ if (xevent->type == KeyPress) { KeySym k; CWidget *w, *p; k = CKeySym (xevent); w = CWidgetOfWindow (xevent->xany.window); if (!w) w = CFindFirstDescendent (xevent->xany.window); else if (!w->takes_focus) w = CChildFocus (w); p = w = CNextFocus (w); do { if (!w) return 0; if (match_hotkey (w->hotkey, k)) { click_on_widget (w); return 1; } w = CNextFocus (w); /* check all sibling buttons for a hotkey */ } while ((unsigned long) w != (unsigned long) p); } return 0;}static long check_hotkey_callback (CWidget * w, long k){ if (w->takes_focus && !w->disabled) if (match_hotkey (w->hotkey, k)) { click_on_widget (w); return 1; } return 0;}/* checks all widgets for a hotkey if alt is pressed */static int CCheckGlobalHotKey (XEvent * xevent, CEvent * cwevent){ if (xevent->type == KeyPress && (xevent->xkey.state & MyAltMask) && !(xevent->xkey.state & ControlMask)) return for_all_widgets ((void *) check_hotkey_callback, (void *) CKeySym (xevent), 0); return 0;}/* }}} */#ifdef DEBUG_ENTRYchar *event_names[] ={ "??zero??", "??one??", "KeyPress", "KeyRelease", "ButtonPress", "ButtonRelease", "MotionNotify", "EnterNotify", "LeaveNotify", "FocusIn", "FocusOut", "KeymapNotify", "Expose", "GraphicsExpose", "NoExpose", "VisibilityNotify", "CreateNotify", "DestroyNotify", "UnmapNotify", "MapNotify", "MapRequest", "ReparentNotify", "ConfigureNotify", "ConfigureRequest", "GravityNotify", "ResizeRequest", "CirculateNotify", "CirculateRequest", "PropertyNotify", "SelectionClear", "SelectionRequest", "SelectionNotify", "ColormapNotify", "ClientMessage", "MappingNotify"};int num_event_names = sizeof (event_names) / sizeof (num_event_names);#endifint run_callbacks (CWidget * w, XEvent * xevent, CEvent * cwevent){ static char no_ident[33]; int handled = 0; if (!cwevent->text) cwevent->text = no_ident; if (!cwevent->ident) cwevent->ident = no_ident;#ifdef DEBUG_ENTRY/* NLS ? */ printf ("Calling %s: Type=%s\n", w->ident, type < num_event_names ? event_names[type] : itoa (type));#endif if (w->eh) { if (w->callback_before) handled |= (*(w->callback_before)) (w, xevent, cwevent); handled |= (*(w->eh)) (w, xevent, cwevent); if (w->callback && cwevent->ident[0]) handled |= (*(w->callback)) (w, xevent, cwevent); }#ifdef DEBUG_ENTRY/* NLS ? */ printf ("Returned\n");#endif return handled;}/* sets the mapped member of widget whose window is w, returning the previous state */static int set_mapped (Window win, int i){ int y; CWidget *w; w = CWidgetOfWindow (win); if (!w) return i; y = w->mapped; w->mapped = i; return y;}int compose_key_pressed = 0;int compose_key_which = 0;static unsigned int key_board_state = 0;unsigned int CGetKeyBoardState (void){ return key_board_state;}extern int option_latin2;static void set_compose_key (XEvent * xevent, int type){ KeySym compose_key; compose_key = CKeySym (xevent); if (!option_latin2) { if (compose_key == MyComposeKey || compose_key == XK_Multi_key) { compose_key_pressed = (type == KeyPress); } else { if (!(xevent->xkey.state & ControlMask)) compose_key_pressed = 0; } } else {#if defined(XK_dead_belowdot) && defined(XK_dead_acute) if (compose_key >= XK_dead_acute && compose_key <= XK_dead_belowdot) { if (compose_key_pressed) return; compose_key_pressed = 1; compose_key_which = compose_key; } else#endif { if (!(xevent->xkey.state & ControlMask)) if (compose_key != XK_Shift_L && compose_key != XK_Shift_R && compose_key != XK_Alt_L && compose_key != XK_Alt_R && compose_key != XK_Mode_switch) { compose_key_pressed = 0; compose_key_which = 0; } } }}/* returns cwevent->insert == -1 and cwevent->command == 0 if no significant key pressed */void translate_key (XEvent * xevent, CEvent * cwevent){ cwevent->key = key_sym_xlat (xevent, cwevent->xlat); if (!cwevent->key) cwevent->key = XK_VoidSymbol; cwevent->state = xevent->xkey.state; if (!edit_translate_key (xevent->xkey.keycode, cwevent->key, xevent->xkey.state, &cwevent->command, &cwevent->insert)) { cwevent->insert = -1; cwevent->command = 0; }}/* {{{ Toolhints */int option_toolhint_milliseconds = 1000;static void render_text_ordinary (Window win, int x, int y, char *q){ char *p; int h = 0; for (;;) { if (!(p = strchr (q, '\n'))) p = q + strlen (q); CImageText (win, FONT_OFFSET_X + x, FONT_OFFSET_Y + h + y, q, (unsigned long) p - (unsigned long) q); h += FONT_PIX_PER_LINE; if (!*p) break; q = p + 1; }}static int eh_toolhint (CWidget * w, XEvent * xevent, CEvent * cwevent){ if (xevent->type == Expose) if (!xevent->xexpose.count && w->label) { CSetColor (color_widget (4)); CSetBackgroundColor (color_widget (14)); render_text_ordinary (w->winid, 2, 2, w->label); CSetColor (color_widget (0)); XDrawRectangle (CDisplay, w->winid, CGC, 0, 0, w->width - 1, w->height - 1); } return 0;}static void hide_toolhint (void){ CDestroyWidget ("_toolhint");}static void show_toolhint (Window win, int xp, int yp){ int width, height, x, y; CWidget *w, *t; w = CWidgetOfWindow (win); if (!w) return; if (w->parentid != CRoot) if (!CWidgetOfWindow (CGetFocus ())) return; if (!w->toolhint) return; CDestroyWidget ("_toolhint"); CGetWindowPosition (win, CRoot, &x, &y); CTextSize (&width, &height, w->toolhint); t = CSetupWidget ("_toolhint", CRoot, x + xp + 16, y + yp - 2, width + 4, height + 4, C_TOOLHINT_WIDGET, ExposureMask, color_widget(14), 0); t->eh = eh_toolhint; t->label = (char *) strdup (w->toolhint);}void CSetToolHint (const char *ident, char *text){ CWidget *w; if (!text) return; if (!*text) return; w = CIdent (ident); if (!w) return; if (w->toolhint) free (w->toolhint); w->toolhint = (char *) strdup (text);}/* }}} Toolhints *//* {{{ fd selection */#ifndef FD_SETSIZE#define FD_SETSIZE 256#endifstatic struct file_des_watch { int fd, how; void (*callback) (int, fd_set *, fd_set *, fd_set *, void *); struct file_des_watch *next; void *data;} *watch_table[FD_SETSIZE];static int watch_table_last = 0;/* returns non-zero if table is full */int CAddWatch (int fd, void (*callback) (int, fd_set *, fd_set *, fd_set *, void *), int how, void *data){ int i; if (!callback || fd < 0 || !how) { fprintf (stderr, "bad args to CAddWatch??"); return 1; } for (i = 0; i < watch_table_last; i++) { if (!watch_table[i]) continue; if (watch_table[i]->callback == callback && watch_table[i]->fd == fd) { watch_table[i]->how |= how; return 0; } } for (i = 0; i < watch_table_last && watch_table[i]; i++); if (i >= FD_SETSIZE) { fprintf (stderr, "watch table overflow??"); return 1; } watch_table[i] = malloc (sizeof (struct file_des_watch)); watch_table[i]->callback = callback; watch_table[i]->how = how; watch_table[i]->fd = fd; watch_table[i]->data = data; if (watch_table_last < i + 1) watch_table_last = i + 1; return 0;}void CRemoveWatch (int fd, void (*callback) (int, fd_set *, fd_set *, fd_set *, void *), int how){ int i; for (i = 0; i < watch_table_last; i++) { if (!watch_table[i]) continue; if (watch_table[i]->callback == callback && watch_table[i]->fd == fd) { watch_table[i]->how &= ~how; if (!watch_table[i]->how) goto do_free; return; } } return; do_free: free (watch_table[i]); watch_table[i] = 0; for (;;) { if (!watch_table_last) break; if (watch_table[watch_table_last - 1]) break; watch_table_last--; }}void remove_all_watch (void){ int i; for (i = 0; i < watch_table_last; i++) { if (!watch_table[i]) continue; free (watch_table[i]); watch_table[i] = 0; } watch_table_last = 0;}static int CIdle = 0;int CIsIdle (void){ return CIdle;}static int run_watches (void){ int r, n = 0, i, found_watch; fd_set reading, writing, error; FD_ZERO (&reading); FD_ZERO (&writing); FD_ZERO (&error); FD_SET (ConnectionNumber (CDisplay), &reading); n = max (n, ConnectionNumber (CDisplay)); for (i = 0; i < watch_table_last; i++) { if (!watch_table[i]) continue; if (watch_table[i]->how & WATCH_READING) { FD_SET (watch_table[i]->fd, &reading); n = max (n, watch_table[i]->fd); } if (watch_table[i]->how & WATCH_WRITING) { FD_SET (watch_table[i]->fd, &writing); n = max (n, watch_table[i]->fd); } if (watch_table[i]->how & WATCH_ERROR) { FD_SET (watch_table[i]->fd, &error); n = max (n, watch_table[i]->fd); } }#if 0 /* Norbert Nemec <nobbi@cheerful.com> */ if (!n) return 0;#endif /* Norbert Nemec <nobbi@cheerful.com> */ r = select (n + 1, &reading, &writing, &error, 0); childhandler_ (); if (r <= 0) return 0; if (FD_ISSET (ConnectionNumber (CDisplay), &reading)) { CIdle = 0; r = 1; } else { CIdle = 1; r = 0; }/* callbacks could add or remove watches, so we restart the loop after each callback */ do { found_watch = 0; for (i = 0; i < watch_table_last; i++) { int fd; if (!watch_table[i]) continue; fd = watch_table[i]->fd; if (FD_ISSET (fd, &reading) && watch_table[i]->how & WATCH_READING) { (*watch_table[i]->callback) (fd, &reading, &writing, &error, watch_table[i]->data); FD_CLR (fd, &reading); found_watch = 1; break; } if (FD_ISSET (fd, &writing) && watch_table[i]->how & WATCH_WRITING) { (*watch_table[i]->callback) (fd, &reading, &writing, &error, watch_table[i]->data); FD_CLR (fd, &writing); found_watch = 1; break; } if (FD_ISSET (fd, &error) && watch_table[i]->how & WATCH_ERROR) { (*watch_table[i]->callback) (fd, &reading, &writing, &error, watch_table[i]->data); FD_CLR (fd, &error); found_watch = 1; break; } } } while (found_watch); return r;}/* }}} fd selection */extern Atom ATOM_WM_PROTOCOLS, ATOM_WM_DELETE_WINDOW, ATOM_WM_TAKE_FOCUS;/* This is the core of the library. CNextEvent must be called continually. The calling application must only use CNextEvent as a block. CNextEvent does the following in sequence: 1 check if event is AlarmEvent, yes: toggle cursor and return 2 check MappingNotify and return 3 cache expose event for later handling. No "raw" exposes are ever processed. they are first merged into courser exposes and resent via the internal queue; return 4 check if an internal expose resulting from 3 above. If so rename it to Expose and continue 5 Check for various other events and process/convert them 6 look for a widget whose window matches .xany.window. If the widget is not a picture widget then call the widget event handling routine: eh_* Then call the widgets user event handler: ->callback 7 do the same for picture widgets. These must come last so that the get drawn on top of other things if there is for exampla a image and a picture in the same window. 8 if the event was a key event, and none of the handlers returned 1 check the tab key for focus cycling. This returns cwevent->handled non-zero if the event was a key event and was handled, 0 otherwise. */int (*global_callback) (XEvent *x) = 0;extern int menu_grabbed;/* xevent or cwevent or both my be passed as NULL */void CNextEvent (XEvent * xevent, CEvent * cwevent){ static char idle = 1; static char no_ident[33]; int i = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -