/* Defines some widget utility functions. Copyright (C) 1992 Lucid, Inc. Copyright (C) 1994, 2001-2023 Free Software Foundation, Inc. This file is part of the Lucid Widget Library. The Lucid Widget Library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version. The Lucid Widget Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNU Emacs. If not, see . */ #include #include #include #include #include #include #include "lwlib-utils.h" #include "lwlib.h" /* Redisplay the contents of the widget, without first clearing it. */ void XtNoClearRefreshWidget (Widget widget) { XEvent event; event.type = Expose; event.xexpose.serial = 0; event.xexpose.send_event = 0; event.xexpose.display = XtDisplay (widget); event.xexpose.window = XtWindow (widget); event.xexpose.x = 0; event.xexpose.y = 0; event.xexpose.width = widget->core.width; event.xexpose.height = widget->core.height; event.xexpose.count = 0; (*widget->core.widget_class->core_class.expose) (widget, &event, (Region)NULL); } /* * Apply a function to all the subwidgets of a given widget recursively. */ void XtApplyToWidgets (Widget w, XtApplyToWidgetsProc proc, XtPointer arg) { if (XtIsComposite (w)) { CompositeWidget cw = (CompositeWidget) w; /* We have to copy the children list before mapping over it, because the procedure might add/delete elements, which would lose badly. */ int nkids = cw->composite.num_children; Widget *kids = (Widget *) xmalloc (sizeof (Widget) * nkids); int i; memcpy ((char *) kids, (char *) cw->composite.children, sizeof (Widget) * nkids); for (i = 0; i < nkids; i++) /* This prevent us from using gadgets, why is it here? */ /* if (XtIsWidget (kids [i])) */ { /* do the kiddies first in case we're destroying */ XtApplyToWidgets (kids [i], proc, arg); proc (kids [i], arg); } xfree (kids); } } /* * Apply a function to all the subwidgets of a given widget recursively. * Stop as soon as the function returns non NULL and returns this as a value. */ void * XtApplyUntilToWidgets (Widget w, XtApplyUntilToWidgetsProc proc, XtPointer arg) { void* result; if (XtIsComposite (w)) { CompositeWidget cw = (CompositeWidget)w; int i; for (i = 0; i < cw->composite.num_children; i++) if (XtIsWidget (cw->composite.children [i])){ result = proc (cw->composite.children [i], arg); if (result) return result; result = XtApplyUntilToWidgets (cw->composite.children [i], proc, arg); if (result) return result; } } return NULL; } /* * Returns a copy of the list of all children of a composite widget */ Widget * XtCompositeChildren (Widget widget, unsigned int *number) { CompositeWidget cw = (CompositeWidget)widget; Widget* result; int n; int i; if (!XtIsComposite (widget)) { *number = 0; return NULL; } n = cw->composite.num_children; result = (Widget*)(void*)XtMalloc (n * sizeof (Widget)); *number = n; for (i = 0; i < n; i++) result [i] = cw->composite.children [i]; return result; } Boolean XtWidgetBeingDestroyedP (Widget widget) { return widget->core.being_destroyed; } #ifdef USE_CAIRO /* Xft emulation on cairo. */ #include #include #include XftFont * crxft_font_open_name (Display *dpy, int screen, const char *name) { XftFont *pub = NULL; FcPattern *match = NULL; FcPattern *pattern = FcNameParse ((FcChar8 *) name); if (pattern) { FcConfigSubstitute (NULL, pattern, FcMatchPattern); double dpi; if (FcPatternGetDouble (pattern, FC_DPI, 0, &dpi) == FcResultNoMatch) { char *v = XGetDefault (dpy, "Xft", FC_DPI); if (v == NULL || sscanf (v, "%lf", &dpi) != 1) dpi = ((DisplayHeight (dpy, screen) * 25.4) / DisplayHeightMM (dpy, screen)); FcPatternAddDouble (pattern, FC_DPI, dpi); } FcDefaultSubstitute (pattern); FcResult result; match = FcFontMatch (NULL, pattern, &result); FcPatternDestroy (pattern); } if (match) { cairo_font_face_t *font_face = cairo_ft_font_face_create_for_pattern (match); if (font_face) { double pixel_size; if ((FcPatternGetDouble (match, FC_PIXEL_SIZE, 0, &pixel_size) != FcResultMatch) || pixel_size < 1) pixel_size = 10; pub = xmalloc (sizeof (*pub)); cairo_matrix_t font_matrix, ctm; cairo_matrix_init_scale (&font_matrix, pixel_size, pixel_size); cairo_matrix_init_identity (&ctm); cairo_font_options_t *options = cairo_font_options_create (); cairo_ft_font_options_substitute (options, match); pub->scaled_font = cairo_scaled_font_create (font_face, &font_matrix, &ctm, options); cairo_font_face_destroy (font_face); cairo_font_options_destroy (options); cairo_font_extents_t extents; cairo_scaled_font_extents (pub->scaled_font, &extents); pub->ascent = lround (extents.ascent); pub->descent = lround (extents.descent); pub->height = lround (extents.height); pub->max_advance_width = lround (extents.max_x_advance); } FcPatternDestroy (match); } if (pub && pub->height <= 0) { crxft_font_close (pub); pub = NULL; } return pub; } void crxft_font_close (XftFont *pub) { cairo_scaled_font_destroy (pub->scaled_font); xfree (pub); } cairo_t * crxft_draw_create (Display *dpy, Drawable drawable, Visual *visual) { cairo_t *cr = NULL; Window root; int x, y; unsigned int width, height, border_width, depth; if (!XGetGeometry (dpy, drawable, &root, &x, &y, &width, &height, &border_width, &depth)) return NULL; cairo_surface_t *surface = cairo_xlib_surface_create (dpy, drawable, visual, width, height); if (surface) { cr = cairo_create (surface); cairo_surface_destroy (surface); } return cr; } static void crxft_set_source_color (cairo_t *cr, const XftColor *color) { cairo_set_source_rgba (cr, color->color.red / 65535.0, color->color.green / 65535.0, color->color.blue / 65535.0, color->color.alpha / 65535.0); } void crxft_draw_rect (cairo_t *cr, const XftColor *color, int x, int y, unsigned int width, unsigned int height) { crxft_set_source_color (cr, color); cairo_rectangle (cr, x, y, width, height); cairo_fill (cr); } void crxft_draw_string (cairo_t *cr, const XftColor *color, XftFont *pub, int x, int y, const FcChar8 *string, int len) { char *buf = xmalloc (len + 1); memcpy (buf, string, len); buf[len] = '\0'; crxft_set_source_color (cr, color); cairo_set_scaled_font (cr, pub->scaled_font); cairo_move_to (cr, x, y); cairo_show_text (cr, buf); xfree (buf); } void crxft_text_extents (XftFont *pub, const FcChar8 *string, int len, XGlyphInfo *extents) { char *buf = xmalloc (len + 1); memcpy (buf, string, len); buf[len] = '\0'; cairo_text_extents_t text_extents; cairo_scaled_font_text_extents (pub->scaled_font, buf, &text_extents); xfree (buf); extents->x = ceil (- text_extents.x_bearing); extents->y = ceil (- text_extents.y_bearing); extents->width = (ceil (text_extents.x_bearing + text_extents.width) + extents->x); extents->height = (ceil (text_extents.y_bearing + text_extents.height) + extents->y); extents->xOff = lround (text_extents.x_advance); extents->yOff = lround (text_extents.y_advance); } #endif /* USE_CAIRO */