Mercurial > hg > xemacs-beta
view src/gtk-xemacs.c @ 5882:bbe4146603db
Reduce regexp usage, now CL-oriented non-regexp code available, core Lisp
lisp/ChangeLog addition:
2015-04-01 Aidan Kehoe <kehoea@parhasard.net>
When calling #'string-match with a REGEXP without regular
expression special characters, call #'search, #'mismatch, #'find,
etc. instead, making our code less likely to side-effect other
functions' match data and a little faster.
* apropos.el (apropos-command):
* apropos.el (apropos):
Call (position ?\n ...) rather than (string-match "\n" ...) here.
* buff-menu.el:
* buff-menu.el (buffers-menu-omit-invisible-buffers):
Don't fire up the regexp engine just to check if a string starts
with a space.
* buff-menu.el (select-buffers-tab-buffers-by-mode):
Don't fire up the regexp engine just to compare mode basenames.
* buff-menu.el (format-buffers-tab-line):
* buff-menu.el (build-buffers-tab-internal): Moved to being a
label within the following.
* buff-menu.el (buffers-tab-items): Use the label.
* bytecomp.el (byte-compile-log-1):
Don't fire up the regexp engine just to look for a newline.
* cus-edit.el (get):
Ditto.
* cus-edit.el (custom-variable-value-create):
Ditto, but for a colon.
* descr-text.el (describe-text-sexp):
Ditto.
* descr-text.el (describe-char-unicode-data):
Use #'split-string-by-char given that we're just looking for a
semicolon.
* descr-text.el (describe-char):
Don't fire up the regexp engine just to look for a newline.
* disass.el (disassemble-internal):
Ditto.
* files.el (file-name-sans-extension):
Implement this using #'position.
* files.el (file-name-extension):
Correct this function's docstring, implement it in terms of
#'position.
* files.el (insert-directory):
Don't fire up the regexp engine to split a string by space; don't
reverse the list of switches, this is actually a longstand bug as
far as I can see.
* gnuserv.el (gnuserv-process-filter):
Use #'position here, instead of consing inside #'split-string
needlessly.
* gtk-file-dialog.el (gtk-file-dialog-update-dropdown):
Use #'split-string-by-char here, don't fire up #'split-string for
directory-sep-char.
* gtk-font-menu.el (hack-font-truename):
Implement this more cheaply in terms of #'find,
#'split-string-by-char, #'equal, rather than #'string-match,
#'split-string, #'string-equal.
* hyper-apropos.el (hyper-apropos-grok-functions):
* hyper-apropos.el (hyper-apropos-grok-variables):
Look for a newline using #'position rather than #'string-match in
these functions.
* info.el (Info-insert-dir):
* info.el (Info-insert-file-contents):
* info.el (Info-follow-reference):
* info.el (Info-extract-menu-node-name):
* info.el (Info-menu):
Look for fixed strings using #'position or #'search as appropriate
in this file.
* ldap.el (ldap-decode-string):
* ldap.el (ldap-encode-string):
#'encode-coding-string, #'decode-coding-string are always
available, don't check if they're fboundp.
* ldap.el (ldap-decode-address):
* ldap.el (ldap-encode-address):
Use #'split-string-by-char in these functions.
* lisp-mnt.el (lm-creation-date):
* lisp-mnt.el (lm-last-modified-date):
Don't fire up the regexp engine just to look for spaces in this file.
* menubar-items.el (default-menubar):
Use (not (mismatch ...)) rather than #'string-match here, for
simple regexp.
Use (search "beta" ...) rather than (string-match "beta" ...)
* menubar-items.el (sort-buffers-menu-alphabetically):
* menubar-items.el (sort-buffers-menu-by-mode-then-alphabetically):
* menubar-items.el (group-buffers-menu-by-mode-then-alphabetically):
Don't fire up the regexp engine to check if a string starts with
a space or an asterisk.
Use the more fine-grained results of #'compare-strings; compare
case-insensitively for the buffer menu.
* menubar-items.el (list-all-buffers):
* menubar-items.el (tutorials-menu-filter):
Use #'equal rather than #'string-equal, which, in this context,
has the drawback of not having a bytecode, and no redeeming
features.
* minibuf.el:
* minibuf.el (un-substitute-in-file-name):
Use #'count, rather than counting the occurences of $ using the
regexp engine.
* minibuf.el (read-file-name-internal-1):
Don't fire up the regexp engine to search for ?=.
* mouse.el (mouse-eval-sexp):
Check for newline with #'find.
* msw-font-menu.el (mswindows-reset-device-font-menus):
Split a string by newline with #'split-string-by-char.
* mule/japanese.el:
* mule/japanese.el ("Japanese"):
Use #'search rather than #'string-match; canoncase before
comparing; fix a bug I had introduced where I had been making case
insensitive comparisons where the case mattered.
* mule/korea-util.el (default-korean-keyboard):
Look for ?3 using #'find, not #'string-march.
* mule/korea-util.el (quail-hangul-switch-hanja):
Search for a fixed string using #'search.
* mule/mule-cmds.el (set-locale-for-language-environment):
#'position, #'substitute rather than #'string-match,
#'replace-in-string.
* newcomment.el (comment-make-extra-lines):
Use #'search rather than #'string-match for a simple string.
* package-get.el (package-get-remote-filename):
Use #'position when looking for ?@
* process.el (setenv):
* process.el (read-envvar-name):
Use #'position when looking for ?=.
* replace.el (map-query-replace-regexp):
Use #'split-string-by-char instead of using an inline
implementation of it.
* select.el (select-convert-from-cf-text):
* select.el (select-convert-from-cf-unicodetext):
Use #'position rather than #'string-match in these functions.
* setup-paths.el (paths-emacs-data-root-p):
Use #'search when looking for simple string.
* sound.el (load-sound-file):
Use #'split-string-by-char rather than an inline reimplementation
of same.
* startup.el (splash-screen-window-body):
* startup.el (splash-screen-tty-body):
Search for simple strings using #'search.
* version.el (emacs-version):
Ditto.
* x-font-menu.el (hack-font-truename):
Implement this more cheaply in terms of #'find,
#'split-string-by-char, #'equal, rather than #'string-match,
#'split-string, #'string-equal.
* x-font-menu.el (x-reset-device-font-menus-core):
Use #'split-string-by-char here.
* x-init.el (x-initialize-keyboard):
Search for a simple string using #'search.
author | Aidan Kehoe <kehoea@parhasard.net> |
---|---|
date | Wed, 01 Apr 2015 14:28:20 +0100 |
parents | 56144c8593a8 |
children |
line wrap: on
line source
/* gtk-xemacs.c ** ** Description: A widget to encapsulate a XEmacs 'text widget' ** ** Created by: William M. Perry ** Copyright (c) 2000 William M. Perry <wmperry@gnu.org> ** Copyright (C) 2010 Ben Wing. ** ** This file is part of XEmacs. ** ** XEmacs 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 3 of the License, or (at your ** option) any later version. ** ** XEmacs 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 XEmacs. If not, see <http://www.gnu.org/licenses/>. */ #include <config.h> #include "lisp.h" #include "device.h" #include "faces.h" #include "glyphs.h" #include "window.h" #include "frame-impl.h" #include "console-gtk-impl.h" #include "device-impl.h" #include "gtk-xemacs.h" #include "fontcolor-gtk.h" extern Lisp_Object Vmodeline_face; extern Lisp_Object Vscrollbar_on_left_p; EXFUN (Fmake_image_instance, 4); static void gtk_xemacs_class_init (GtkXEmacsClass *klass); static void gtk_xemacs_init (GtkXEmacs *xemacs); static void gtk_xemacs_size_allocate (GtkWidget *widget, GtkAllocation *allocaction); static void gtk_xemacs_draw (GtkWidget *widget, GdkRectangle *area); static void gtk_xemacs_paint (GtkWidget *widget, GdkRectangle *area); static void gtk_xemacs_size_request (GtkWidget *widget, GtkRequisition *requisition); static void gtk_xemacs_realize (GtkWidget *widget); static void gtk_xemacs_style_set (GtkWidget *widget, GtkStyle *previous_style); static gint gtk_xemacs_expose (GtkWidget *widget, GdkEventExpose *event); guint gtk_xemacs_get_type (void) { static guint xemacs_type = 0; if (!xemacs_type) { static const GtkTypeInfo xemacs_info = { "GtkXEmacs", sizeof (GtkXEmacs), sizeof (GtkXEmacsClass), (GtkClassInitFunc) gtk_xemacs_class_init, (GtkObjectInitFunc) gtk_xemacs_init, /* reserved_1 */ NULL, /* reserved_2 */ NULL, (GtkClassInitFunc) NULL, }; xemacs_type = gtk_type_unique (gtk_fixed_get_type (), &xemacs_info); } return xemacs_type; } static GtkWidgetClass *parent_class; static void gtk_xemacs_class_init (GtkXEmacsClass *class_) { GtkWidgetClass *widget_class; widget_class = (GtkWidgetClass*) class_; parent_class = (GtkWidgetClass *) gtk_type_class (gtk_fixed_get_type ()); widget_class->size_allocate = gtk_xemacs_size_allocate; widget_class->size_request = gtk_xemacs_size_request; widget_class->draw = gtk_xemacs_draw; widget_class->expose_event = gtk_xemacs_expose; widget_class->realize = gtk_xemacs_realize; widget_class->button_press_event = emacs_gtk_button_event_handler; widget_class->button_release_event = emacs_gtk_button_event_handler; widget_class->key_press_event = emacs_gtk_key_event_handler; widget_class->key_release_event = emacs_gtk_key_event_handler; widget_class->motion_notify_event = emacs_gtk_motion_event_handler; widget_class->style_set = gtk_xemacs_style_set; } static void gtk_xemacs_init (GtkXEmacs *xemacs) { GTK_WIDGET_SET_FLAGS (xemacs, GTK_CAN_FOCUS); } GtkWidget* gtk_xemacs_new (struct frame *f) { GtkXEmacs *xemacs; xemacs = (GtkXEmacs*) gtk_type_new (gtk_xemacs_get_type ()); xemacs->f = f; return GTK_WIDGET (xemacs); } static void __nuke_background_items (GtkWidget *widget) { /* This bit of voodoo is here to get around the annoying flicker when GDK tries to futz with our background pixmap as well as XEmacs doing it We do NOT set the background of this widget window, that way there is NO flickering, etc. The downside is the XEmacs frame appears as 'seethru' when XEmacs is too busy to redraw the frame. Well, wait, we do... otherwise there sre weird 'seethru' areas even when XEmacs does a full redisplay. Most noticeable in some areas of the modeline, or in the right-hand-side of the window between the scrollbar ad n the edge of the window. */ if (widget->window) { gdk_window_set_back_pixmap (widget->window, NULL, 0); gdk_window_set_back_pixmap (widget->parent->window, NULL, 0); gdk_window_set_background (widget->parent->window, &widget->style->bg[GTK_STATE_NORMAL]); gdk_window_set_background (widget->window, &widget->style->bg[GTK_STATE_NORMAL]); } } extern Lisp_Object xemacs_gtk_convert_color(GdkColor *c, GtkWidget *w); /* From fontcolor-gtk.c */ extern Lisp_Object __get_gtk_font_truename (GdkFont *gdk_font, int expandp); #define convert_font(f) __get_gtk_font_truename (f, 0) #ifdef SMASH_FACE_FALLBACKS static void smash_face_fallbacks (struct frame *f, GtkStyle *style) { #define FROB(face,prop,slot) do { \ Lisp_Object fallback = Qnil; \ Lisp_Object specifier = Fget (face, prop, Qnil); \ struct Lisp_Specifier *sp = NULL; \ if (NILP (specifier)) continue; \ sp = XSPECIFIER (specifier); \ fallback = sp->fallback; \ if (EQ (Fcar (Fcar (Fcar (fallback))), Qgtk)) \ fallback = XCDR (fallback); \ if (! NILP (slot)) \ fallback = acons (list1 (Qgtk), \ slot, \ fallback); \ set_specifier_fallback (specifier, fallback); \ } while (0); #define FROB_FACE(face,fg_slot,bg_slot) \ do { \ FROB (face, Qforeground, xemacs_gtk_convert_color (&style->fg_slot[GTK_STATE_NORMAL], FRAME_GTK_SHELL_WIDGET (f))); \ FROB (face, Qbackground, xemacs_gtk_convert_color (&style->bg_slot[GTK_STATE_NORMAL], FRAME_GTK_SHELL_WIDGET (f))); \ if (style->rc_style && style->rc_style->bg_pixmap_name[GTK_STATE_NORMAL]) \ { \ FROB (Vdefault_face, Qbackground_pixmap, \ Fmake_image_instance (build_cistring (style->rc_style->bg_pixmap_name[GTK_STATE_NORMAL]), \ f->device, Qnil, make_fixnum (5))); \ } \ else \ { \ FROB (Vdefault_face, Qbackground_pixmap, Qnil); \ } \ } while (0) FROB (Vdefault_face, Qfont, convert_font (style->font)); FROB_FACE (Vdefault_face, fg, bg); FROB_FACE (Vgui_element_face, text, mid); #undef FROB #undef FROB_FACE } #endif /* SMASH_FACE_FALLBACKS */ #ifdef HAVE_SCROLLBARS static void smash_scrollbar_specifiers (struct frame *f, GtkStyle *style) { Lisp_Object frame; int slider_size = 0; int hsize, vsize; GtkRangeClass *klass; frame = wrap_frame (f); klass = (GtkRangeClass *) gtk_type_class (GTK_TYPE_SCROLLBAR); slider_size = klass->slider_width; hsize = slider_size + (style->klass->ythickness * 2); vsize = slider_size + (style->klass->xthickness * 2); style = gtk_style_attach (style, GTK_WIDGET (DEVICE_GTK_APP_SHELL (XDEVICE (FRAME_DEVICE (f))))->window); Fadd_spec_to_specifier (Vscrollbar_width, make_fixnum (vsize), frame, Qnil, Qnil); Fadd_spec_to_specifier (Vscrollbar_height, make_fixnum (hsize), frame, Qnil, Qnil); } #endif /* HAVE_SCROLLBARS */ #ifdef HAVE_TOOLBARS extern Lisp_Object Vtoolbar_shadow_thickness; static void smash_toolbar_specifiers(struct frame *f, GtkStyle *style) { Lisp_Object frame; GtkStyleClass *klass = (GtkStyleClass *) style->klass; frame = wrap_frame (f); Fadd_spec_to_specifier (Vtoolbar_shadow_thickness, make_fixnum (klass->xthickness), Qnil, list2 (Qgtk, Qdefault), Qprepend); } #endif /* HAVE_TOOLBARS */ static void gtk_xemacs_realize (GtkWidget *widget) { parent_class->realize (widget); gtk_xemacs_style_set (widget, gtk_widget_get_style (widget)); } static void gtk_xemacs_style_set (GtkWidget *widget, GtkStyle *previous_style) { GtkStyle *new_style = gtk_widget_get_style (widget); GtkXEmacs *x = GTK_XEMACS (widget); parent_class->style_set (widget, previous_style); if (x->f) { __nuke_background_items (widget); #ifdef SMASH_FACE_FALLBACKS smash_face_fallbacks (x->f, new_style); #endif #ifdef HAVE_SCROLLBARS smash_scrollbar_specifiers (x->f, new_style); #endif #ifdef HAVE_TOOLBARS smash_toolbar_specifiers (x->f, new_style); #endif } } static void gtk_xemacs_size_request (GtkWidget *widget, GtkRequisition *requisition) { GtkXEmacs *x = GTK_XEMACS (widget); struct frame *f = GTK_XEMACS_FRAME (x); int width, height; if (f) { frame_unit_to_pixel_size (f, FRAME_WIDTH (f), FRAME_HEIGHT (f), &width, &height); requisition->width = width; requisition->height = height; } else { parent_class->size_request (widget, requisition); } } /* Assign a size and position to the child widgets. This differs from the super class method in that for all widgets except the scrollbars the size and position are not caclulated here. This is because these widgets have this function performed for them by the redisplay code (see gtk_map_subwindow()). If the superclass method is called then the widgets can change size and position as the two pieces of code move the widgets at random. */ static void gtk_xemacs_size_allocate (GtkWidget *widget, GtkAllocation *allocation) { GtkXEmacs *x = GTK_XEMACS (widget); GtkFixed *fixed = GTK_FIXED (widget); struct frame *f = GTK_XEMACS_FRAME (x); int columns, rows; GList *children; guint16 border_width; widget->allocation = *allocation; if (GTK_WIDGET_REALIZED (widget)) gdk_window_move_resize (widget->window, allocation->x, allocation->y, allocation->width, allocation->height); border_width = GTK_CONTAINER (fixed)->border_width; children = fixed->children; while (children) { GtkFixedChild* child = (GtkFixedChild*) children->data; children = children->next; /* Scrollbars are the only widget that is managed by GTK. See comments in gtk_create_scrollbar_instance(). */ if (GTK_WIDGET_VISIBLE (child->widget) && gtk_type_is_a(GTK_OBJECT_TYPE(child->widget), GTK_TYPE_SCROLLBAR)) { GtkAllocation child_allocation; GtkRequisition child_requisition; gtk_widget_get_child_requisition (child->widget, &child_requisition); child_allocation.x = child->x + border_width; child_allocation.y = child->y + border_width; child_allocation.width = child_requisition.width; child_allocation.height = child_requisition.height; gtk_widget_size_allocate (child->widget, &child_allocation); } } if (f) { f->pixwidth = allocation->width; f->pixheight = allocation->height; pixel_to_frame_unit_size (f, allocation->width, allocation->height, &columns, &rows); change_frame_size (f, columns, rows, 1); } } static void gtk_xemacs_paint (GtkWidget *widget, GdkRectangle *area) { GtkXEmacs *x = GTK_XEMACS (widget); struct frame *f = GTK_XEMACS_FRAME (x); if (GTK_WIDGET_DRAWABLE (widget)) redisplay_redraw_exposed_area (f, area->x, area->y, area->width, area->height); } static void gtk_xemacs_draw (GtkWidget *widget, GdkRectangle *area) { GtkFixed *fixed = GTK_FIXED (widget); GtkFixedChild *child; GdkRectangle child_area; GList *children; /* I need to manually iterate over the children instead of just chaining to parent_class->draw() because it calls gtk_fixed_paint() directly, which clears the background window, which causes A LOT of flashing. */ if (GTK_WIDGET_DRAWABLE (widget)) { gtk_xemacs_paint (widget, area); children = fixed->children; while (children) { child = (GtkFixedChild*) children->data; children = children->next; /* #### This is what causes the scrollbar flickering! Evidently the scrollbars pretty much take care of drawing themselves in most cases. Then we come along and tell them to redraw again! But if we just leave it out, then they do not get drawn correctly the first time! Scrollbar flickering has been greatly helped by the optimizations in scrollbar-gtk.c / gtk_update_scrollbar_instance_status (), so this is not that big a deal anymore. */ if (gtk_widget_intersect (child->widget, area, &child_area)) { gtk_widget_draw (child->widget, &child_area); } } } } static gint gtk_xemacs_expose (GtkWidget *widget, GdkEventExpose *event) { GtkXEmacs *x = GTK_XEMACS (widget); struct frame *f = GTK_XEMACS_FRAME (x); GdkRectangle *a = &event->area; if (GTK_WIDGET_DRAWABLE (widget)) { /* This takes care of drawing the scrollbars, etc */ parent_class->expose_event (widget, event); /* Now draw the actual frame data */ if (!check_for_ignored_expose (f, a->x, a->y, a->width, a->height) && !find_matching_subwindow (f, a->x, a->y, a->width, a->height)) redisplay_redraw_exposed_area (f, a->x, a->y, a->width, a->height); return (TRUE); } return FALSE; } Lisp_Object xemacs_gtk_convert_color(GdkColor *c, GtkWidget *UNUSED (w)) { char color_buf[255]; sprintf (color_buf, "#%04x%04x%04x", c->red, c->green, c->blue); return (build_cistring (color_buf)); }