📄 coolwidget.c
字号:
size_hints.max_width = max_w; size_hints.max_height = max_h; size_hints.width_inc = FONT_MEAN_WIDTH; size_hints.height_inc = FONT_PIX_PER_LINE; size_hints.base_width = min_w; size_hints.base_height = min_h; size_hints.flags = PBaseSize | PResizeInc | PMaxSize | PMinSize; if (wdt->options & WINDOW_USER_POSITION) { size_hints.x = wdt->x; size_hints.y = wdt->y; size_hints.flags |= USPosition | PPosition; } if (wdt->options & WINDOW_USER_SIZE) { size_hints.width = wdt->width; size_hints.height = wdt->height; size_hints.flags |= USSize | PSize; }/* used as check if hints are not set when CMap is called */ wdt->options |= WINDOW_SIZE_HINTS_SET; XSetWMNormalHints (CDisplay, wdt->winid, &size_hints); XSync (CDisplay, 0); XGetWMNormalHints (CDisplay, wdt->winid, &size_hints, &d); XSync (CDisplay, 0);}void CSetWindowResizable (const char *ident, int min_width, int min_height, int max_width, int max_height){ Window w; int width, height; CWidget *wdt; wdt = CIdent (ident); w = wdt->winid; width = wdt->width; height = wdt->height; min_width = width - ((width - min_width) / FONT_MEAN_WIDTH) * FONT_MEAN_WIDTH; min_height = height - ((height - min_height) / FONT_PIX_PER_LINE) * FONT_PIX_PER_LINE; max_width = width - ((width - max_width) / FONT_MEAN_WIDTH) * FONT_MEAN_WIDTH; max_height = height - ((height - max_height) / FONT_PIX_PER_LINE) * FONT_PIX_PER_LINE; if (wdt->parentid == CRoot) { /* set the window manager to manage resizing */ XWMHints wm_hints; XClassHint class_hints; class_hints.res_name = CAppName; class_hints.res_class = CAppName; wm_hints.flags = (InputHint | StateHint); wm_hints.input = True; wm_hints.initial_state = NormalState; XSetWMProperties (CDisplay, w, 0, 0, 0, 0, 0, &wm_hints, &class_hints); CSetWindowSizeHints (wdt, min_width, min_height, max_width, max_height); } else {/* else, we must manage our own resizing. *//* the member names do not mean what they are named here */ XSelectInput (CDisplay, w, INPUT_MOTION | StructureNotifyMask); wdt->position |= WINDOW_RESIZABLE; wdt->mark1 = min_width; wdt->mark2 = min_height; wdt->firstcolumn = width; wdt->firstline = height;/* we are not going to specify a maximum */ wdt->numlines = FONT_PIX_PER_LINE; /* resizing granularity x */ wdt->textlength = FONT_MEAN_WIDTH; /* resizing granularity y */ }}extern char *init_geometry;Window CDrawHeadedDialog (const char *identifier, Window parent, int x, int y, const char *label){ Window win; CWidget *wdt; if ((parent == CRoot || !parent) && !override_redirect) { int width, height, bitmask; bitmask = 0; x = 0; y = 0; width = 10; height = 10; parent = CRoot; if (!CFirstWindow) { if (init_geometry) bitmask = XParseGeometry (init_geometry, &x, &y, (unsigned int *) &width, (unsigned int *) &height); } win = (wdt = CSetupWidget (identifier, CRoot, x, y, width, height, C_WINDOW_WIDGET, INPUT_MOTION | StructureNotifyMask | FocusChangeMask, COLOR_FLAT, 0))->winid; if (!CFirstWindow) { /* create the GC the first time round and CFirstWindow. when the window is closed, the app gets a QuitApplication event */ CFirstWindow = win;/* these options tell CSetWindowSizeHints() to give those hints to the WM: */ if (bitmask & (XValue | YValue)) wdt->options |= WINDOW_USER_POSITION; if (bitmask & (WidthValue | HeightValue)) wdt->options |= WINDOW_USER_SIZE; } wdt->label = (char *) strdup (label); XSetIconName (CDisplay, win, wdt->label); XStoreName (CDisplay, win, wdt->label); XChangeProperty (CDisplay, win, ATOM_WM_PROTOCOLS, XA_ATOM, 32, PropModeReplace, (unsigned char *) &ATOM_WM_DELETE_WINDOW, 1); reset_hint_pos (WIDGET_SPACING + 2, WIDGET_SPACING + 2); wdt->position |= WINDOW_UNMOVEABLE; wdt->options |= WINDOW_NO_BORDER; } else { int w, h; CTextSize (&w, &h, label); win = CDrawDialog (identifier, parent, x, y); (CDrawText (catstrs (identifier, ".header", 0), win, WIDGET_SPACING, WIDGET_SPACING + 2, label))->position |= POSITION_CENTRE; CGetHintPos (&x, &y);#ifndef NEXT_LOOK_X (CDrawBar (win, WIDGET_SPACING, y, 10))->position |= POSITION_FILL; CGetHintPos (&x, &y);#endif reset_hint_pos (WIDGET_SPACING + 2, y); } return win;}Window CDrawDialog (const char *identifier, Window parent, int x, int y){ Window w; CWidget *wdt; w = (wdt = CSetupWidget (identifier, parent, x, y, 2, 2, C_WINDOW_WIDGET, INPUT_MOTION, COLOR_FLAT, 0))->winid; reset_hint_pos (WIDGET_SPACING + 2, WIDGET_SPACING + 2); return w;}/* returns the actual window that is a child of the root window *//* this is not the same as a main window, since the WM places each *//* main window inside a cosmetic window */Window CGetWMWindow (Window win){ Window root, parent, *children; unsigned int nchildren; for (;;) { if (!XQueryTree (CDisplay, win, &root, &parent, &children, &nchildren)) break; if (parent == CRoot) return win; if (children) XFree ((char *) children); win = parent; } return 0;}/* I tested this procedure with kwm, fvwm95, fvwm, twm, olwm, without problems */void CRaiseWMWindow (char *ident){ Window wm_win; CWidget *w; w = CIdent (ident); if (!w) return; wm_win = CGetWMWindow (w->winid); if (!wm_win) return; XRaiseWindow (CDisplay, wm_win); XFlush (CDisplay);}void CSetBackgroundPixmap (const char *ident, const char *data[], int w, int h, char start_char){ XSetWindowAttributes xswa; CWidget *wdt; wdt = CIdent (ident); if (wdt->pixmap) XFreePixmap (CDisplay, wdt->pixmap); xswa.background_pixmap = wdt->pixmap = CCreatePixmap (data, w, h, start_char); if (xswa.background_pixmap) XChangeWindowAttributes (CDisplay, wdt->winid, CWBackPixmap, &xswa);}#define MAX_KEYS_IN_DIALOG 64int find_letter_at_word_start (unsigned char *label, unsigned char *used_keys, int n){ int c, j; for (j = 0; label[j]; j++) { /* check for letters with an & in front of them */ c = my_lower_case (label[j + 1]); if (!c) break; if (label[j] == '&') if (!memchr (used_keys, c, n)) return label[j + 1]; } c = my_lower_case (label[0]); if (c >= 'a' && c <= 'z') if (!memchr (used_keys, c, n)) /* check if first letter has not already been used */ return label[0]; for (j = 1; label[j]; j++) { /* check for letters at start of words that have not already been used */ c = my_lower_case (label[j]); if (label[j - 1] == ' ' && c >= 'a' && c <= 'z') if (!memchr (used_keys, c, n)) return label[j]; } for (j = 1; label[j]; j++) { /* check for any letters that have not already been used */ c = my_lower_case (label[j]); if (c >= 'a' && c <= 'z') if (!memchr (used_keys, c, n)) return label[j]; } return 0;}int find_hotkey (CWidget * w){ unsigned char used_keys[MAX_KEYS_IN_DIALOG + 3]; char *label; int n = 0; CWidget *p = w; label = w->label ? w->label : w->text; /* text for text-widgets which don't have a label */ if (!label) return 0; if (!*label) return 0; do { w = CNextFocus (w); if (!w || n == MAX_KEYS_IN_DIALOG) return 0; if (w->hotkey < 256) used_keys[n++] = my_lower_case (w->hotkey); } while ((unsigned long) w != (unsigned long) p); if (!n) return 0; return find_letter_at_word_start ((unsigned char *) label, used_keys, n);}CWidget *CDrawButton (const char *identifier, Window parent, int x, int y, int width, int height, const char *label){ CWidget *wdt; int w, h; CPushFont ("widget", 0); 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;#ifdef NEXT_LOOK_X height++ ;#endif } wdt = CSetupWidget (identifier, parent, x, y, width, height, C_BUTTON_WIDGET, INPUT_BUTTON, COLOR_FLAT, 1); if (label) wdt->label = (char *) strdup (label); wdt->hotkey = find_hotkey (wdt); wdt->render = render_button; wdt->options |= WIDGET_TAKES_FOCUS_RING | WIDGET_HOTKEY_ACTIVATES; set_hint_pos (x + width + WIDGET_SPACING, y + height + WIDGET_SPACING); CPopFont (); return wdt;}CWidget *CDrawProgress (const char *identifier, Window parent, int x, int y, int width, int height, int p){ CWidget *w; if ((w = CIdent (identifier))) { w->cursor = p; CSetWidgetPosition (identifier, x, y); CSetWidgetSize (identifier, width, height); CExpose (identifier); } else { w = CSetupWidget (identifier, parent, x, y, width, height, C_PROGRESS_WIDGET, INPUT_EXPOSE, COLOR_FLAT, 0); w->cursor = p; set_hint_pos (x + width + WIDGET_SPACING, y + height + WIDGET_SPACING); } return w;}CWidget *CDrawBar (Window parent, int x, int y, int w){ CWidget *wdt; wdt = CSetupWidget ("hbar", parent, x, y, w, 3, C_BAR_WIDGET, INPUT_EXPOSE, COLOR_FLAT, 0); set_hint_pos (x + w + WIDGET_SPACING, y + 3 + WIDGET_SPACING); return wdt;}/* returns the text size. The result is one descent greater than the actual size */void CTextSize (int *w, int *h, const char *str){ char *p, *q = (char *) str; int w1, h1; if (!w) w = &w1; if (!h) h = &h1; *w = *h = 0; for (;;) { if (!(p = strchr (q, '\n'))) p = q + strlen (q); *h += FONT_PIX_PER_LINE; *w = max (CImageTextWidth (q, (unsigned long) p - (unsigned long) q), *w); if (!*p) break; q = p + 1; }}CWidget *CDrawText (const char *identifier, Window parent, int x, int y, const char *fmt,...){ va_list pa; char *str; int w, h; CWidget *wdt; va_start (pa, fmt); str = vsprintf_alloc (fmt, pa); va_end (pa); CPushFont ("widget", 0); CTextSize (&w, &h, str); w += TEXT_RELIEF * 2 + 2; h += TEXT_RELIEF * 2 + 2; wdt = CSetupWidget (identifier, parent, x, y, w, h, C_TEXT_WIDGET, INPUT_EXPOSE, COLOR_FLAT, 0); wdt->text = (char *) strdup (str); free (str); set_hint_pos (x + w + WIDGET_SPACING, y + h + WIDGET_SPACING); CPopFont (); return wdt;}CWidget *CDrawStatus (const char *identifier, Window parent, int x, int y, int w, char *str){ CWidget *wdt; int h; h = FONT_PIX_PER_LINE + TEXT_RELIEF * 2 + 2; wdt = CSetupWidget (identifier, parent, x, y, w, h, C_STATUS_WIDGET, INPUT_EXPOSE, COLOR_FLAT, 0); wdt->text = (char *) strdup (str); set_hint_pos (x + w + WIDGET_SPACING, y + h + WIDGET_SPACING); return wdt;}void render_text (CWidget * w);CWidget *CRedrawText (const char *identifier, const char *fmt,...){ va_list pa; char *str; CWidget *wdt; int w, h; wdt = CIdent (identifier); if (!wdt) return 0; va_start (pa, fmt); str = vsprintf_alloc (fmt, pa); va_end (pa); free (wdt->text); wdt->text = (char *) strdup (str); CTextSize (&w, &h, str); w += TEXT_RELIEF * 2 + 2; h += TEXT_RELIEF * 2 + 2; CSetWidgetSize (identifier, w, h); render_text (wdt); free (str); return wdt;}void focus_stack_remove_window (Window w);void selection_clear (void);/* Unmaps and destroys widget and frees memory. Only for a widget that has no children. */int free_single_widget (int i){ if (i && CIndex (i)) { if (CIndex (i)->winid) { if (CIndex (i)->options & WIDGET_TAKES_SELECTION) if (CIndex (i)->winid == XGetSelectionOwner (CDisplay, XA_PRIMARY)) XSetSelectionOwner (CDisplay, XA_PRIMARY, CFirstWindow, CurrentTime); if (CursorState.window == CIndex (i)->winid) set_cursor_position (0, 0, 0, 0, 0, 0, 0, 0, 0, 0); XUnmapWindow (CDisplay, CIndex (i)->winid); XDestroyWindow (CDisplay, CIndex (i)->winid); if (CFirstWindow == CIndex (i)->winid) CFirstWindow = 0; focus_stack_remove_window (CIndex (i)->winid); /* removes the window from the focus history stack */ } if (CIndex (i)->label) free (CIndex (i)->label); if (CIndex (i)->toolhint) free (CIndex (i)->toolhint); if (CIndex (i)->headings) free (CIndex (i)->headings); if (CIndex (i)->gl_graphicscontext) { free (CIndex (i)->gl_graphicscontext); CIndex (i)->gl_graphicscontext = 0; } if (CIndex (i)->ximage) { if ((long) CIndex (i)->ximage->data == (long) CIndex (i)->graphic) CIndex (i)->graphic = NULL; if (CIndex (i)->ximage->data) { free (CIndex (i)->ximage->data); CIndex (i)->ximage->data = 0; } XDestroyImage (CIndex (i)->ximage); } if (CIndex (i)->pixmap) { XFreePixmap (CDisplay, CIndex (i)->pixmap); CIndex (i)->pixmap = 0; } if (CIndex (i)->pixmap_mask) { XFreePixmap (CDisplay, CIndex (i)->pixmap_mask); CIndex (i)->pixmap_mask = 0; } if (CIndex (i)->graphic) free (CIndex (i)->graphic); if (CIndex (i)->tab) free (CIndex (i)->tab); if (CIndex (i)->destroy) (*(CIndex (i)->destroy)) (CIndex (i)); if (CIndex (i)->text) free (CIndex (i)->text); /* for input history, this must come after the destroy, so that the text can be added to the input history by the destroy function before the text is free'd */ if (CIndex (i)->funcs) free (CIndex (i)->funcs); if (CIndex (i)->free_user) (*(CIndex (i)->free_user)) (CIndex (i)->user); else if (CIndex (i)->user && (CIndex (i)->options & WIDGET_FREE_USER_ON_DESTROY)) free (CIndex (i)->user); free (CIndex (i)); CIndex (i) = NULL; while (!CIndex (last_widget - 1) && last_widget > 1) last_widget--; return 1; } else return 0;}/*searches for the first widget in the list that has win as its parent and returns index */int find_first_child_of (Window win){ int i = 0; while (last_widget > i++) if (CIndex (i) != NULL) if (CIndex (i)->parentid == win) return i; return 0;}int find_last_child_of (Window win){ int i = last_widget; while (--i > 0) if (CIndex (i) != NULL) if (CIndex (i)->parentid == win) return i; return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -