commit 1f37714a11ec91c6aa68a73c7ff6714b24ddadfa (HEAD, refs/remotes/origin/master) Author: Ken Raeburn Date: Mon Oct 5 11:11:32 2015 -0400 Disable non-working pointerColor setting for X tooltip frame. It generates a bunch of server traffic, but there's some bug wherein the new mouse cursor settings don't seem to get used. In most situations the cursor isn't likely to be seen anyway, so it's not urgent to fix. * src/xfns.c (x_create_tip_frame): Don't set pointerColor. diff --git a/src/xfns.c b/src/xfns.c index e4ec315..9c5bc2b 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -5284,8 +5284,12 @@ x_create_tip_frame (struct x_display_info *dpyinfo, "foreground", "Foreground", RES_TYPE_STRING); x_default_parameter (f, parms, Qbackground_color, build_string ("white"), "background", "Background", RES_TYPE_STRING); +#if 0 /* This code currently doesn't work for tooltip frames; the + cursor being set doesn't seem to get used. The call generates + a bit of traffic, so skip it for now. */ x_default_parameter (f, parms, Qmouse_color, build_string ("black"), "pointerColor", "Foreground", RES_TYPE_STRING); +#endif x_default_parameter (f, parms, Qcursor_color, build_string ("black"), "cursorColor", "Foreground", RES_TYPE_STRING); x_default_parameter (f, parms, Qborder_color, build_string ("black"), commit ee529429775037fb2d9e78e7c86db21d7b3f4bdd Author: Ken Raeburn Date: Sun Oct 4 09:54:44 2015 -0400 Reduce some unnecessary X calls. * src/xfns.c (x_real_pos_and_offsets): Remove a redundant XGetGeometry call. If border width is wanted, get it from the XGetGeometry call instead of calling XGetWindowAttributes on the same window. Skip some X calls if we've already detected an error from the X server. * src/xterm.c (x_wm_supports): Delete x_sync before x_had_errors_p. (handle_one_xevent): Delete XSync call before x_uncatch_errors. diff --git a/src/xfns.c b/src/xfns.c index 7a236e7..e4ec315 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -250,19 +250,15 @@ x_real_pos_and_offsets (struct frame *f, if (! had_errors) { - unsigned int ign; + unsigned int bw, ign; Window child, rootw; /* Get the real coordinates for the WM window upper left corner */ XGetGeometry (FRAME_X_DISPLAY (f), win, - &rootw, &real_x, &real_y, &ow, &oh, &ign, &ign); + &rootw, &real_x, &real_y, &ow, &oh, &bw, &ign); if (outer_border) - { - XWindowAttributes atts; - XGetWindowAttributes (FRAME_X_DISPLAY (f), win, &atts); - *outer_border = atts.border_width; - } + *outer_border = bw; /* Translate real coordinates to coordinates relative to our window. For our window, the upper left corner is 0, 0. @@ -309,8 +305,7 @@ x_real_pos_and_offsets (struct frame *f, had_errors = x_had_errors_p (FRAME_X_DISPLAY (f)); } - - if (dpyinfo->root_window == f->output_data.x->parent_desc) + if (!had_errors && dpyinfo->root_window == f->output_data.x->parent_desc) { /* Try _NET_FRAME_EXTENTS if our parent is the root window. */ rc = XGetWindowProperty (dpy, win, dpyinfo->Xatom_net_frame_extents, @@ -321,20 +316,16 @@ x_real_pos_and_offsets (struct frame *f, if (rc == Success && actual_type == target_type && !x_had_errors_p (dpy) && actual_size == 4 && actual_format == 32) { - unsigned int ign; - Window rootw; long *fe = (long *)tmp_data; - XGetGeometry (FRAME_X_DISPLAY (f), win, - &rootw, &real_x, &real_y, &ign, &ign, &ign, &ign); outer_x = -fe[0]; outer_y = -fe[2]; real_x -= fe[0]; real_y -= fe[2]; } - } - if (tmp_data) XFree (tmp_data); + if (tmp_data) XFree (tmp_data); + } x_uncatch_errors (); diff --git a/src/xterm.c b/src/xterm.c index 8be893e..83ef89c 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -7541,9 +7541,6 @@ handle_one_xevent (struct x_display_info *dpyinfo, the only valid choice. */ RevertToParent, event->xclient.data.l[1]); - /* This is needed to detect the error - if there is an error. */ - XSync (d, False); x_uncatch_errors (); } /* Not certain about handling scroll bars here */ @@ -9930,7 +9927,6 @@ x_wm_supports (struct frame *f, Atom want_atom) /* Check if window exists. */ XSelectInput (dpy, wmcheck_window, StructureNotifyMask); - x_sync (f); if (x_had_errors_p (dpy)) { x_uncatch_errors (); commit e23ed19ff933c35111f3a806b4104fee8ef42f55 Author: Ken Raeburn Date: Sat Oct 3 00:18:50 2015 -0400 Reduce color allocation/query traffic in the TrueColor case. When working with an X visual with TrueColor class, pixel values can be generated from the RGB values according to mask value provided by the server on connection. Some of the image-handling code was already doing this. * src/xterm.h (x_make_truecolor_pixel): New function; code taken from lookup_rgb_color. (x_mutable_colormap): New function. * src/image.c (lookup_rgb_color): Move pixel composition code to x_make_truecolor_pixel. (x_kill_gs_process): Call x_mutable_colormap. * src/xfaces.c (x_free_colors, x_free_dpy_colors): Call x_mutable_colormap. * src/xftfont.c (xftfont_get_colors): Call x_query_colors. * src/xterm.c (x_query_colors): For a TrueColor display, decompose the pixel value into RGB values directly, and don't send a request to the server. (x_alloc_nearest_color): For a TrueColor display, construct the pixel value with x_make_truecolor_pixel. (x_copy_color): For an immutable color map, just return the provided pixel value. diff --git a/src/image.c b/src/image.c index 79bf21e..401689e 100644 --- a/src/image.c +++ b/src/image.c @@ -4442,15 +4442,7 @@ lookup_rgb_color (struct frame *f, int r, int g, int b) r = color.red, g = color.green, b = color.blue; } - /* Scale down RGB values to the visual's bits per RGB, and shift - them to the right position in the pixel color. Note that the - original RGB values are 16-bit values, as usual in X. */ - pr = (r >> (16 - dpyinfo->red_bits)) << dpyinfo->red_offset; - pg = (g >> (16 - dpyinfo->green_bits)) << dpyinfo->green_offset; - pb = (b >> (16 - dpyinfo->blue_bits)) << dpyinfo->blue_offset; - - /* Assemble the pixel color. */ - return pr | pg | pb; + return x_make_truecolor_pixel (dpyinfo, r, g, b); } for (p = ct_table[i]; p; p = p->next) @@ -9542,7 +9534,6 @@ void x_kill_gs_process (Pixmap pixmap, struct frame *f) { struct image_cache *c = FRAME_IMAGE_CACHE (f); - int class; ptrdiff_t i; struct image *img; @@ -9568,8 +9559,7 @@ x_kill_gs_process (Pixmap pixmap, struct frame *f) /* On displays with a mutable colormap, figure out the colors allocated for the image by looking at the pixels of an XImage for img->pixmap. */ - class = FRAME_X_VISUAL (f)->class; - if (class != StaticColor && class != StaticGray && class != TrueColor) + if (x_mutable_colormap (FRAME_X_VISUAL (f))) { XImagePtr ximg; diff --git a/src/xfaces.c b/src/xfaces.c index 8cf0b42..a3d122f 100644 --- a/src/xfaces.c +++ b/src/xfaces.c @@ -454,11 +454,9 @@ DEFUN ("dump-colors", Fdump_colors, Sdump_colors, 0, 0, 0, void x_free_colors (struct frame *f, unsigned long *pixels, int npixels) { - int class = FRAME_DISPLAY_INFO (f)->visual->class; - /* If display has an immutable color map, freeing colors is not necessary and some servers don't allow it. So don't do it. */ - if (class != StaticColor && class != StaticGray && class != TrueColor) + if (x_mutable_colormap (FRAME_X_VISUAL (f))) { #ifdef DEBUG_X_COLORS unregister_colors (pixels, npixels); @@ -471,7 +469,7 @@ x_free_colors (struct frame *f, unsigned long *pixels, int npixels) #ifdef USE_X_TOOLKIT -/* Free colors used on frame F. PIXELS is an array of NPIXELS pixel +/* Free colors used on display DPY. PIXELS is an array of NPIXELS pixel color values. Interrupt input must be blocked when this function is called. */ @@ -480,11 +478,10 @@ x_free_dpy_colors (Display *dpy, Screen *screen, Colormap cmap, unsigned long *pixels, int npixels) { struct x_display_info *dpyinfo = x_display_info_for_display (dpy); - int class = dpyinfo->visual->class; /* If display has an immutable color map, freeing colors is not necessary and some servers don't allow it. So don't do it. */ - if (class != StaticColor && class != StaticGray && class != TrueColor) + if (x_mutable_colormap (dpyinfo->visual)) { #ifdef DEBUG_X_COLORS unregister_colors (pixels, npixels); diff --git a/src/xftfont.c b/src/xftfont.c index a1846e8..851edb6 100644 --- a/src/xftfont.c +++ b/src/xftfont.c @@ -111,8 +111,7 @@ xftfont_get_colors (struct frame *f, struct face *face, GC gc, colors[0].pixel = fg->pixel = xgcv.foreground; if (bg) colors[1].pixel = bg->pixel = xgcv.background; - XQueryColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), colors, - bg ? 2 : 1); + x_query_colors (f, colors, bg ? 2 : 1); fg->color.alpha = 0xFFFF; fg->color.red = colors[0].red; fg->color.green = colors[0].green; diff --git a/src/xterm.c b/src/xterm.c index 6065f96..8be893e 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -2197,6 +2197,50 @@ x_query_colors (struct frame *f, XColor *colors, int ncolors) { struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); + if (dpyinfo->red_bits > 0) + { + /* For TrueColor displays, we can decompose the RGB value + directly. */ + int i; + unsigned int rmult, gmult, bmult; + unsigned int rmask, gmask, bmask; + + rmask = (1 << dpyinfo->red_bits) - 1; + gmask = (1 << dpyinfo->green_bits) - 1; + bmask = (1 << dpyinfo->blue_bits) - 1; + /* If we're widening, for example, 8 bits in the pixel value to + 16 bits for the separate-color representation, we want to + extrapolate the lower bits based on those bits available -- + in other words, we'd like 0xff to become 0xffff instead of + the 0xff00 we'd get by just zero-filling the lower bits. + + We generate a 32-bit scaled-up value and shift it, in case + the bit count doesn't divide 16 evently (e.g., when dealing + with a 3-3-2 bit RGB display), to get more of the lower bits + correct. + + Should we cache the multipliers in dpyinfo? Maybe + special-case the 8-8-8 common case? */ + rmult = 0xffffffff / rmask; + gmult = 0xffffffff / gmask; + bmult = 0xffffffff / bmask; + + for (i = 0; i < ncolors; ++i) + { + unsigned int r, g, b; + unsigned long pixel = colors[i].pixel; + + r = (pixel >> dpyinfo->red_offset) & rmask; + g = (pixel >> dpyinfo->green_offset) & gmask; + b = (pixel >> dpyinfo->blue_offset) & bmask; + + colors[i].red = (r * rmult) >> 16; + colors[i].green = (g * gmult) >> 16; + colors[i].blue = (b * bmult) >> 16; + } + return; + } + if (dpyinfo->color_cells) { int i; @@ -2207,9 +2251,10 @@ x_query_colors (struct frame *f, XColor *colors, int ncolors) eassert (dpyinfo->color_cells[pixel].pixel == pixel); colors[i] = dpyinfo->color_cells[pixel]; } + return; } - else - XQueryColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), colors, ncolors); + + XQueryColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), colors, ncolors); } @@ -2341,15 +2386,27 @@ x_alloc_nearest_color_1 (Display *dpy, Colormap cmap, XColor *color) } -/* Allocate the color COLOR->pixel on frame F, colormap CMAP. If an - exact match can't be allocated, try the nearest color available. - Value is true if successful. Set *COLOR to the color - allocated. */ +/* Allocate the color COLOR->pixel on frame F, colormap CMAP, after + gamma correction. If an exact match can't be allocated, try the + nearest color available. Value is true if successful. Set *COLOR + to the color allocated. */ bool x_alloc_nearest_color (struct frame *f, Colormap cmap, XColor *color) { + struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); + gamma_correct (f, color); + + if (dpyinfo->red_bits > 0) + { + color->pixel = x_make_truecolor_pixel (dpyinfo, + color->red, + color->green, + color->blue); + return true; + } + return x_alloc_nearest_color_1 (FRAME_X_DISPLAY (f), cmap, color); } @@ -2363,8 +2420,16 @@ x_copy_color (struct frame *f, unsigned long pixel) { XColor color; + /* If display has an immutable color map, freeing colors is not + necessary and some servers don't allow it. Since we won't free a + color once we've allocated it, we don't need to re-allocate it to + maintain the server's reference count. */ + if (!x_mutable_colormap (FRAME_X_VISUAL (f))) + return pixel; + color.pixel = pixel; block_input (); + /* The color could still be found in the color_cells array. */ x_query_color (f, &color); XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color); unblock_input (); diff --git a/src/xterm.h b/src/xterm.h index 300a8b7..d8edbc2 100644 --- a/src/xterm.h +++ b/src/xterm.h @@ -1085,6 +1085,33 @@ x_display_set_last_user_time (struct x_display_info *dpyinfo, Time t) dpyinfo->last_user_time = t; } +INLINE unsigned long +x_make_truecolor_pixel (struct x_display_info *dpyinfo, int r, int g, int b) +{ + unsigned long pr, pg, pb; + + /* Scale down RGB values to the visual's bits per RGB, and shift + them to the right position in the pixel color. Note that the + original RGB values are 16-bit values, as usual in X. */ + pr = (r >> (16 - dpyinfo->red_bits)) << dpyinfo->red_offset; + pg = (g >> (16 - dpyinfo->green_bits)) << dpyinfo->green_offset; + pb = (b >> (16 - dpyinfo->blue_bits)) << dpyinfo->blue_offset; + + /* Assemble the pixel color. */ + return pr | pg | pb; +} + +/* If display has an immutable color map, freeing colors is not + necessary and some servers don't allow it, so we won't do it. That + also allows us to make other optimizations relating to server-side + reference counts. */ +INLINE bool +x_mutable_colormap (Visual *visual) +{ + int class = visual->class; + return (class != StaticColor && class != StaticGray && class != TrueColor); +} + extern void x_set_sticky (struct frame *, Lisp_Object, Lisp_Object); extern bool x_wm_supports (struct frame *, Atom); extern void x_wait_for_event (struct frame *, int); commit b8eea1d7b1485a147f112127c0ca58cb1a0a8ebb Author: Ken Raeburn Date: Sat Oct 3 00:15:54 2015 -0400 Cache XParseColor results in the X display info structure. With repeated lookups of foreground and background colors for multiple faces per frame, we issue a lot of redundant color name lookups to the X server, waiting every time for the response. On a remote network with, say, 30ms round-trip time, this can add nearly a full second to creation of a new frame. * src/gtkutil.c (xg_check_special_colors): Call x_parse_color. * src/image.c (get_spec_bg_or_alpha_as_argb): (xpm_init_color_cache, xpm_lookup_color): * src/xfns.c (x_defined_color): * src/xterm.c (x_parse_color): New function; caches color names not starting with "#" in the display-info structure. (x_delete_display): Delete the cache content. * src/xterm.h (struct color_name_cache_entry): New type. (x_parse_color): Declare. (struct x_display_info): Add a new field for the cache. diff --git a/src/gtkutil.c b/src/gtkutil.c index 725e330..34e81b5 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c @@ -583,9 +583,7 @@ xg_check_special_colors (struct frame *f, (unsigned) (col.red * 65535), (unsigned) (col.green * 65535), (unsigned) (col.blue * 65535)); - success_p = (XParseColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), - buf, color) - != 0); + success_p = x_parse_color (f, buf, color) != 0; #else GtkStyle *gsty = gtk_widget_get_style (FRAME_GTK_WIDGET (f)); GdkColor *grgb = get_bg diff --git a/src/image.c b/src/image.c index 10b067f..79bf21e 100644 --- a/src/image.c +++ b/src/image.c @@ -1108,10 +1108,7 @@ get_spec_bg_or_alpha_as_argb (struct image *img, XColor xbgcolor; Lisp_Object bg = image_spec_value (img->spec, QCbackground, NULL); - if (STRINGP (bg) && XParseColor (FRAME_X_DISPLAY (f), - FRAME_X_COLORMAP (f), - SSDATA (bg), - &xbgcolor)) + if (STRINGP (bg) && x_parse_color (f, SSDATA (bg), &xbgcolor)) bgcolor = xcolor_to_argb32 (xbgcolor); return bgcolor; @@ -3241,7 +3238,10 @@ static struct xpm_cached_color *xpm_cache_color (struct frame *, char *, /* An entry in a hash table used to cache color definitions of named colors. This cache is necessary to speed up XPM image loading in case we do color allocations ourselves. Without it, we would need - a call to XParseColor per pixel in the image. */ + a call to XParseColor per pixel in the image. + + FIXME Now that we're using x_parse_color and its cache, reevaluate + the need for this caching layer. */ struct xpm_cached_color { @@ -3276,8 +3276,7 @@ xpm_init_color_cache (struct frame *f, XpmAttributes *attrs) XColor color; for (i = 0; i < attrs->numsymbols; ++i) - if (XParseColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), - attrs->colorsymbols[i].value, &color)) + if (x_parse_color (f, attrs->colorsymbols[i].value, &color)) { color.pixel = lookup_rgb_color (f, color.red, color.green, color.blue); @@ -3356,8 +3355,7 @@ xpm_lookup_color (struct frame *f, char *color_name, XColor *color) if (p != NULL) *color = p->color; - else if (XParseColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), - color_name, color)) + else if (x_parse_color (f, color_name, color)) { color->pixel = lookup_rgb_color (f, color->red, color->green, color->blue); diff --git a/src/xfns.c b/src/xfns.c index fc6111c..7a236e7 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -454,7 +454,7 @@ x_defined_color (struct frame *f, const char *color_name, success_p = xg_check_special_colors (f, color_name, color); #endif if (!success_p) - success_p = XParseColor (dpy, cmap, color_name, color) != 0; + success_p = x_parse_color (f, color_name, color) != 0; if (success_p && alloc_p) success_p = x_alloc_nearest_color (f, cmap, color); unblock_input (); diff --git a/src/xterm.c b/src/xterm.c index dd54552..6065f96 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -2223,6 +2223,52 @@ x_query_color (struct frame *f, XColor *color) } +/* On frame F, translate the color name to RGB values. Use cached + information, if possible. + + Note that there is currently no way to clean old entries out of the + cache. However, it is limited to names in the server's database, + and names we've actually looked up; list-colors-display is probably + the most color-intensive case we're likely to hit. */ + +Status x_parse_color (struct frame *f, const char *color_name, + XColor *color) +{ + Display *dpy = FRAME_X_DISPLAY (f); + Colormap cmap = FRAME_X_COLORMAP (f); + Status status; + struct color_name_cache_entry *cache_entry; + + if (color_name[0] == '#') + { + /* The hex form is parsed directly by XParseColor without + talking to the X server. No need for caching. */ + return XParseColor (dpy, cmap, color_name, color); + } + + for (cache_entry = FRAME_DISPLAY_INFO (f)->color_names; cache_entry; + cache_entry = cache_entry->next) + { + if (!xstrcasecmp(cache_entry->name, color_name)) + { + *color = cache_entry->rgb; + return 1; + } + } + + if (XParseColor (dpy, cmap, color_name, color) == 0) + /* No caching of negative results, currently. */ + return 0; + + cache_entry = xzalloc (sizeof *cache_entry); + cache_entry->rgb = *color; + cache_entry->name = xstrdup (color_name); + cache_entry->next = FRAME_DISPLAY_INFO (f)->color_names; + FRAME_DISPLAY_INFO (f)->color_names = cache_entry; + return 1; +} + + /* Allocate the color COLOR->pixel on DISPLAY, colormap CMAP. If an exact match can't be allocated, try the nearest color available. Value is true if successful. Set *COLOR to the color @@ -12119,6 +12165,7 @@ static void x_delete_display (struct x_display_info *dpyinfo) { struct terminal *t; + struct color_name_cache_entry *color_entry, *next_color_entry; /* Close all frames and delete the generic struct terminal for this X display. */ @@ -12148,6 +12195,15 @@ x_delete_display (struct x_display_info *dpyinfo) tail->next = tail->next->next; } + for (color_entry = dpyinfo->color_names; + color_entry; + color_entry = next_color_entry) + { + next_color_entry = color_entry->next; + xfree (color_entry->name); + xfree (color_entry); + } + xfree (dpyinfo->x_id_name); xfree (dpyinfo->x_dnd_atoms); xfree (dpyinfo->color_cells); diff --git a/src/xterm.h b/src/xterm.h index 6165906..300a8b7 100644 --- a/src/xterm.h +++ b/src/xterm.h @@ -153,6 +153,17 @@ struct x_gc_ext_data #endif +struct color_name_cache_entry +{ + struct color_name_cache_entry *next; + XColor rgb; + char *name; +}; + +Status x_parse_color (struct frame *f, const char *color_name, + XColor *color); + + /* For each X display, we have a structure that records information about it. */ @@ -385,6 +396,9 @@ struct x_display_info struct xim_inst_t *xim_callback_data; #endif + /* A cache mapping color names to RGB values. */ + struct color_name_cache_entry *color_names; + /* If non-null, a cache of the colors in the color map. Don't use this directly, call x_color_cells instead. */ XColor *color_cells; commit 0360b7f2c4f0358106e229de4dfe91a67445a50c Author: Stefan Monnier Date: Wed Oct 7 21:11:38 2015 -0400 * src/syntax.c (syms_of_syntax): Make syntax-propertize--done local diff --git a/src/syntax.c b/src/syntax.c index cacdf18..6bfb3b7 100644 --- a/src/syntax.c +++ b/src/syntax.c @@ -3672,6 +3672,7 @@ See the info node `(elisp)Syntax Properties' for a description of the doc: /* Position up to which syntax-table properties have been set. */); syntax_propertize__done = -1; DEFSYM (Qinternal__syntax_propertize, "internal--syntax-propertize"); + Fmake_variable_buffer_local (intern ("syntax-propertize--done")); words_include_escapes = 0; DEFVAR_BOOL ("words-include-escapes", words_include_escapes, commit c026c0016e8075f4112e7ea0d868a8e2b81105d0 Author: Eli Zaretskii Date: Wed Oct 7 20:49:05 2015 +0300 Fix segfault in image_size_error * src/image.c (image_size_error): Pass a Lisp string to image_error, not a C string. (Bug#21641) diff --git a/src/image.c b/src/image.c index b586c53..10b067f 100644 --- a/src/image.c +++ b/src/image.c @@ -647,7 +647,8 @@ image_error (const char *format, ...) static void image_size_error (void) { - image_error ("Invalid image size (see `%s')", "max-image-size"); + AUTO_STRING (max_image_size_name, "max-image-size"); + image_error ("Invalid image size (see `%s')", max_image_size_name); } commit 3cd29a5d15d22866eb45c7bd4460215cb8902a05 Author: Simen Heggestøyl Date: Wed Oct 7 19:19:42 2015 +0200 Highlight CSS variable definitions * lisp/textmodes/css-mode.el (css-nmstart-re): Tweak regexp to accept CSS variables. (Bug#21638) diff --git a/lisp/textmodes/css-mode.el b/lisp/textmodes/css-mode.el index 5f4eebd..3e84b43 100644 --- a/lisp/textmodes/css-mode.el +++ b/lisp/textmodes/css-mode.el @@ -215,7 +215,7 @@ (defconst css-escapes-re "\\\\\\(?:[^\000-\037\177]\\|[0-9a-fA-F]+[ \n\t\r\f]?\\)") (defconst css-nmchar-re (concat "\\(?:[-[:alnum:]]\\|" css-escapes-re "\\)")) -(defconst css-nmstart-re (concat "\\(?:[[:alpha:]]\\|" css-escapes-re "\\)")) +(defconst css-nmstart-re (concat "\\(?:--\\)?\\(?:[[:alpha:]]\\|" css-escapes-re "\\)")) (defconst css-ident-re ;; (concat css-nmstart-re css-nmchar-re "*") ;; Apparently, "at rules" names can start with a dash, e.g. @-moz-keyframes. (concat css-nmchar-re "+")) commit 8a40c5a67eb6b89574ff98f7d55b456d89ff22ee Author: Artur Malabarba Date: Wed Oct 7 15:12:49 2015 +0100 * test/automated/tabulated-list-test.el: New file Test bug#21639 and some basic functionality. diff --git a/test/automated/tabulated-list-test.el b/test/automated/tabulated-list-test.el new file mode 100644 index 0000000..5731db4 --- /dev/null +++ b/test/automated/tabulated-list-test.el @@ -0,0 +1,118 @@ +;;; tabulated-list-test.el --- Tests for emacs-lisp/tabulated-list.el -*- lexical-binding: t; -*- + +;; Copyright (C) 2015 Free Software Foundation, Inc. + +;; Author: Artur Malabarba + +;; This file is part of GNU Emacs. + +;; GNU Emacs 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. + +;; GNU Emacs 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 . + +;;; Code: + +(require 'tabulated-list) +(require 'ert) + +(defconst tabulated-list--test-entries + '(("zzzz-game" ["zzzz-game" "zzzz-game" "2113" "installed" " play zzzz in Emacs"]) + ("4clojure" ["4clojure" "4clojure" "1507" "obsolete" " Open and evaluate 4clojure.com questions"]) + ("abc-mode" ["abc-mode" "abc-mode" "944" "available" " Major mode for editing abc music files"]) + ("mode" ["mode" "mode" "1128" "installed" " A simple mode for editing Actionscript 3 files"]))) + +(defun tabulated-list--test-sort-car (a b) + (string< (car a) (car b))) + +(defconst tabulated-list--test-format + [("name" 10 tabulated-list--test-sort-car) + ("name-2" 10 t) + ("Version" 9 nil) + ("Status" 10 ) + ("Description" 0 nil)]) + +(defmacro tabulated-list--test-with-buffer (&rest body) + `(with-temp-buffer + (tabulated-list-mode) + (setq tabulated-list-entries (copy-alist tabulated-list--test-entries)) + (setq tabulated-list-format tabulated-list--test-format) + (setq tabulated-list-padding 7) + (tabulated-list-init-header) + (tabulated-list-print) + ,@body)) + + +;;; Tests +(ert-deftest tabulated-list-print () + (tabulated-list--test-with-buffer + ;; Basic printing. + (should (string= (buffer-substring-no-properties (point-min) (point-max)) + " zzzz-game zzzz-game 2113 installed play zzzz in Emacs + 4clojure 4clojure 1507 obsolete Open and evaluate 4clojure.com questions + abc-mode abc-mode 944 available Major mode for editing abc music files + mode mode 1128 installed A simple mode for editing Actionscript 3 files\n")) + ;; Preseve position. + (forward-line 3) + (let ((pos (thing-at-point 'line))) + (pop tabulated-list-entries) + (tabulated-list-print t) + (should (equal (thing-at-point 'line) pos)) + (should (string= (buffer-substring-no-properties (point-min) (point-max)) + " 4clojure 4clojure 1507 obsolete Open and evaluate 4clojure.com questions + abc-mode abc-mode 944 available Major mode for editing abc music files + mode mode 1128 installed A simple mode for editing Actionscript 3 files\n")) + ;; Check the UPDATE argument + (pop tabulated-list-entries) + (setf (cdr (car tabulated-list-entries)) (list ["x" "x" "944" "available" " XX"])) + (tabulated-list-print t t) + (should (string= (buffer-substring-no-properties (point-min) (point-max)) + " x x 944 available XX + mode mode 1128 installed A simple mode for editing Actionscript 3 files\n")) + (should (equal (thing-at-point 'line) pos))))) + +(ert-deftest tabulated-list-sort () + (tabulated-list--test-with-buffer + ;; Basic sorting + (goto-char (point-min)) + (skip-chars-forward "[:blank:]") + (tabulated-list-sort) + (let ((text (buffer-substring-no-properties (point-min) (point-max)))) + (should (string= text " 4clojure 4clojure 1507 obsolete Open and evaluate 4clojure.com questions + abc-mode abc-mode 944 available Major mode for editing abc music files + mode mode 1128 installed A simple mode for editing Actionscript 3 files + zzzz-game zzzz-game 2113 installed play zzzz in Emacs\n")) + + (skip-chars-forward "^[:blank:]") + (skip-chars-forward "[:blank:]") + (should (equal (get-text-property (point) 'tabulated-list-column-name) + "name-2")) + (tabulated-list-sort) + ;; Check a `t' as the sorting predicate. + (should (string= text (buffer-substring-no-properties (point-min) (point-max)))) + ;; Invert. + (tabulated-list-sort 1) + (should (string= (buffer-substring-no-properties (point-min) (point-max)) + " zzzz-game zzzz-game 2113 installed play zzzz in Emacs + mode mode 1128 installed A simple mode for editing Actionscript 3 files + abc-mode abc-mode 944 available Major mode for editing abc music files + 4clojure 4clojure 1507 obsolete Open and evaluate 4clojure.com questions\n")) + ;; Again + (tabulated-list-sort 1) + (should (string= text (buffer-substring-no-properties (point-min) (point-max))))) + ;; Check that you can't sort some cols. + (skip-chars-forward "^[:blank:]") + (skip-chars-forward "[:blank:]") + (should-error (tabulated-list-sort) :type 'user-error) + (should-error (tabulated-list-sort 4) :type 'user-error))) + +(provide 'tabulated-list-test) +;;; tabulated-list-test.el ends here commit e60a1e2717ded78f062719b2cd8c41f358cf0198 Author: Artur Malabarba Date: Wed Oct 7 14:09:09 2015 +0100 * lisp/emacs-lisp/tabulated-list.el (tabulated-list-sort): Check if column can be sorted before trying. (Bug#21639) diff --git a/lisp/emacs-lisp/tabulated-list.el b/lisp/emacs-lisp/tabulated-list.el index 47ecd2b..4bd8a19 100644 --- a/lisp/emacs-lisp/tabulated-list.el +++ b/lisp/emacs-lisp/tabulated-list.el @@ -520,7 +520,9 @@ With a numeric prefix argument N, sort the Nth column." (car (aref tabulated-list-format n)) (get-text-property (point) 'tabulated-list-column-name)))) - (tabulated-list--sort-by-column-name name))) + (if (nth 2 (assoc name (append tabulated-list-format nil))) + (tabulated-list--sort-by-column-name name) + (user-error "Cannot sort by %s" name)))) (defun tabulated-list--sort-by-column-name (name) (when (and name (derived-mode-p 'tabulated-list-mode)) commit 9ed9b7dc953c787518f12da4fa2d28fccf8c1b24 Author: Nicolas Richard Date: Wed Oct 7 15:08:30 2015 +0200 Add test for `self-insert-command' (bug#21633) * test/automated/cmds-tests.el: New file. diff --git a/test/automated/cmds-tests.el b/test/automated/cmds-tests.el new file mode 100644 index 0000000..7e742a1 --- /dev/null +++ b/test/automated/cmds-tests.el @@ -0,0 +1,34 @@ +;;; cmds-tests.el --- Testing some Emacs commands + +;; Copyright (C) 2013-2015 Free Software Foundation, Inc. + +;; Author: Nicolas Richard +;; Keywords: + +;; This program 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. + +;; This program 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 this program. If not, see . + +;;; Commentary: + +;; + +;;; Code: + + +(ert-deftest self-insert-command-with-negative-argument () + "Test `self-insert-command' with a negative argument." + (let ((last-command-event ?a)) + (should-error (self-insert-command -1)))) + +(provide 'cmds-tests) +;;; cmds-tests.el ends here commit 391291f4b18b4a1370840de4869797a514a900ae Author: Martin Rudalics Date: Wed Oct 7 11:11:53 2015 +0200 In resize_frame_windows don't set a top position when resizing horizontally. * src/window.c (resize_frame_windows): Don't set root window's top position when resizing horizontally. diff --git a/src/window.c b/src/window.c index 6d06e54..3566f6e 100644 --- a/src/window.c +++ b/src/window.c @@ -3971,7 +3971,6 @@ resize_frame_windows (struct frame *f, int size, bool horflag, bool pixelwise) /* old_size is the old size of the frame's root window. */ int old_size = horflag ? r->total_cols : r->total_lines; int old_pixel_size = horflag ? r->pixel_width : r->pixel_height; - int old_pixel_top = r->pixel_top; /* new_size is the new size of the frame's root window. */ int new_size, new_pixel_size; int unit = horflag ? FRAME_COLUMN_WIDTH (f) : FRAME_LINE_HEIGHT (f); @@ -4001,11 +4000,8 @@ resize_frame_windows (struct frame *f, int size, bool horflag, bool pixelwise) new_pixel_size = new_size * unit; } - r->top_line = FRAME_TOP_MARGIN (f); - r->pixel_top = FRAME_TOP_MARGIN_HEIGHT (f); - if (new_pixel_size == old_pixel_size - && r->pixel_top == old_pixel_top) + && (horflag || r->pixel_top == FRAME_TOP_MARGIN_HEIGHT (f))) ; else if (WINDOW_LEAF_P (r)) /* For a leaf root window just set the size. */ @@ -4016,6 +4012,9 @@ resize_frame_windows (struct frame *f, int size, bool horflag, bool pixelwise) } else { + r->top_line = FRAME_TOP_MARGIN (f); + r->pixel_top = FRAME_TOP_MARGIN_HEIGHT (f); + r->total_lines = new_size; r->pixel_height = new_pixel_size; } @@ -4023,6 +4022,12 @@ resize_frame_windows (struct frame *f, int size, bool horflag, bool pixelwise) { Lisp_Object delta; + if (!horflag) + { + r->top_line = FRAME_TOP_MARGIN (f); + r->pixel_top = FRAME_TOP_MARGIN_HEIGHT (f); + } + if (pixelwise) XSETINT (delta, new_pixel_size - old_pixel_size); else commit 4d04cee0602bc2238b739da10fd56eae5c23f74b Author: Artur Malabarba Date: Wed Oct 7 09:40:00 2015 +0100 * lisp/progmodes/prog-mode.el (prettify-symbols-alist): Document more possible values. diff --git a/lisp/progmodes/prog-mode.el b/lisp/progmodes/prog-mode.el index 6696356..b459cbf 100644 --- a/lisp/progmodes/prog-mode.el +++ b/lisp/progmodes/prog-mode.el @@ -132,7 +132,11 @@ narrowing is in effect." "Alist of symbol prettifications. Each element looks like (SYMBOL . CHARACTER), where the symbol matching SYMBOL (a string, not a regexp) will be shown as -CHARACTER instead.") +CHARACTER instead. + +CHARACTER can be a character or it can be a list or vector, in +which case it will be used to compose the new symbol as per the +third argument of `compose-region'.") (defun prettify-symbols-default-compose-p (start end _match) "Return true iff the symbol MATCH should be composed.