X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/1d09060524a16ba61d99818816e58477a8c6082f..2afd5e90eb946a0e70547e56a4c705d7d0d4cb7f:/src/xfns.c diff --git a/src/xfns.c b/src/xfns.c index 6c9b40a329..1b9b629b36 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -24,6 +24,10 @@ Boston, MA 02111-1307, USA. */ #include #include +#ifdef HAVE_UNISTD_H +#include +#endif + /* This makes the fields of a Display accessible, in Xlib header files. */ #define XLIB_ILLEGAL_ACCESS @@ -61,6 +65,10 @@ Boston, MA 02111-1307, USA. */ #include "[.bitmaps]gray.xbm" #endif +#ifdef USE_GTK +#include "gtkutil.h" +#endif + #ifdef USE_X_TOOLKIT #include @@ -107,10 +115,15 @@ extern XFontStruct *xlwmenu_default_font; extern void free_frame_menubar (); extern double atof (); -#endif /* USE_X_TOOLKIT */ +#ifdef USE_MOTIF + +/* LessTif/Motif version info. */ + +static Lisp_Object Vmotif_version_string; + +#endif /* USE_MOTIF */ -#define min(a,b) ((a) < (b) ? (a) : (b)) -#define max(a,b) ((a) > (b) ? (a) : (b)) +#endif /* USE_X_TOOLKIT */ #ifdef HAVE_X11R4 #define MAXREQUEST(dpy) (XMaxRequestSize (dpy)) @@ -135,15 +148,15 @@ Lisp_Object Vx_resource_name; Lisp_Object Vx_resource_class; -/* Non-zero means we're allowed to display a busy cursor. */ +/* Non-zero means we're allowed to display an hourglass cursor. */ -int display_busy_cursor_p; +int display_hourglass_p; /* The background and shape of the mouse pointer, and shape when not over text or in the modeline. */ Lisp_Object Vx_pointer_shape, Vx_nontext_pointer_shape, Vx_mode_pointer_shape; -Lisp_Object Vx_busy_pointer_shape; +Lisp_Object Vx_hourglass_pointer_shape; /* The shape when over mouse-sensitive text. */ @@ -176,10 +189,9 @@ Lisp_Object Vx_pixel_size_width_font_regexp; Lisp_Object Qauto_raise; Lisp_Object Qauto_lower; -Lisp_Object Qbar; Lisp_Object Qborder_color; Lisp_Object Qborder_width; -Lisp_Object Qbox; +extern Lisp_Object Qbox; Lisp_Object Qcursor_color; Lisp_Object Qcursor_type; Lisp_Object Qgeometry; @@ -209,6 +221,11 @@ extern Lisp_Object Qdisplay; Lisp_Object Qscroll_bar_foreground, Qscroll_bar_background; Lisp_Object Qscreen_gamma, Qline_spacing, Qcenter; Lisp_Object Qcompound_text, Qcancel_timer; +Lisp_Object Qwait_for_wm; +Lisp_Object Qfullscreen; +Lisp_Object Qfullwidth; +Lisp_Object Qfullheight; +Lisp_Object Qfullboth; /* The below are defined in frame.c. */ @@ -255,7 +272,7 @@ check_x_frame (frame) if (NILP (frame)) frame = selected_frame; - CHECK_LIVE_FRAME (frame, 0); + CHECK_LIVE_FRAME (frame); f = XFRAME (frame); if (! FRAME_X_P (f)) error ("Non-X frame used"); @@ -287,12 +304,7 @@ check_x_display_info (frame) dpyinfo = x_display_info_for_name (frame); else { - FRAME_PTR f; - - CHECK_LIVE_FRAME (frame, 0); - f = XFRAME (frame); - if (! FRAME_X_P (f)) - error ("Non-X frame used"); + FRAME_PTR f = check_x_frame (frame); dpyinfo = FRAME_X_DISPLAY_INFO (f); } @@ -321,7 +333,7 @@ x_window_to_frame (dpyinfo, wdesc) f = XFRAME (frame); if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo) continue; - if (f->output_data.x->busy_window == wdesc) + if (f->output_data.x->hourglass_window == wdesc) return f; #ifdef USE_X_TOOLKIT if ((f->output_data.x->edit_widget @@ -332,6 +344,15 @@ x_window_to_frame (dpyinfo, wdesc) || f->output_data.x->icon_desc == wdesc) return f; #else /* not USE_X_TOOLKIT */ +#ifdef USE_GTK + if (f->output_data.x->edit_widget) + { + GtkWidget *gwdesc = xg_win_to_widget (wdesc); + struct x_output *x = f->output_data.x; + if (gwdesc != 0 && gwdesc == x->edit_widget) + return f; + } +#endif /* USE_GTK */ if (FRAME_X_WINDOW (f) == wdesc || f->output_data.x->icon_desc == wdesc) return f; @@ -340,7 +361,7 @@ x_window_to_frame (dpyinfo, wdesc) return 0; } -#ifdef USE_X_TOOLKIT +#if defined (USE_X_TOOLKIT) || defined (USE_GTK) /* Like x_window_to_frame but also compares the window with the widget's windows. */ @@ -365,10 +386,19 @@ x_any_window_to_frame (dpyinfo, wdesc) { /* This frame matches if the window is any of its widgets. */ x = f->output_data.x; - if (x->busy_window == wdesc) + if (x->hourglass_window == wdesc) found = f; else if (x->widget) { +#ifdef USE_GTK + GtkWidget *gwdesc = xg_win_to_widget (wdesc); + if (gwdesc != 0 + && (gwdesc == x->widget + || gwdesc == x->edit_widget + || gwdesc == x->vbox_widget + || gwdesc == x->menubar_widget)) + found = f; +#else if (wdesc == XtWindow (x->widget) || wdesc == XtWindow (x->column_widget) || wdesc == XtWindow (x->edit_widget)) @@ -376,6 +406,7 @@ x_any_window_to_frame (dpyinfo, wdesc) /* Match if the window is this frame's menubar. */ else if (lw_window_is_in_menubar (wdesc, x->menubar_widget)) found = f; +#endif } else if (FRAME_X_WINDOW (f) == wdesc) /* A tooltip frame. */ @@ -407,14 +438,23 @@ x_non_menubar_window_to_frame (dpyinfo, wdesc) continue; x = f->output_data.x; /* This frame matches if the window is any of its widgets. */ - if (x->busy_window == wdesc) + if (x->hourglass_window == wdesc) return f; else if (x->widget) { +#ifdef USE_GTK + GtkWidget *gwdesc = xg_win_to_widget (wdesc); + if (gwdesc != 0 + && (gwdesc == x->widget + || gwdesc == x->edit_widget + || gwdesc == x->vbox_widget)) + return f; +#else if (wdesc == XtWindow (x->widget) || wdesc == XtWindow (x->column_widget) || wdesc == XtWindow (x->edit_widget)) return f; +#endif } else if (FRAME_X_WINDOW (f) == wdesc) /* A tooltip frame. */ @@ -444,9 +484,25 @@ x_menubar_window_to_frame (dpyinfo, wdesc) continue; x = f->output_data.x; /* Match if the window is this frame's menubar. */ +#ifdef USE_GTK + if (x->menubar_widget) + { + GtkWidget *gwdesc = xg_win_to_widget (wdesc); + int found = 0; + + BLOCK_INPUT; + if (gwdesc != 0 + && (gwdesc == x->menubar_widget + || gtk_widget_get_parent (gwdesc) == x->menubar_widget)) + found = 1; + UNBLOCK_INPUT; + if (found) return f; + } +#else if (x->menubar_widget && lw_window_is_in_menubar (wdesc, x->menubar_widget)) return f; +#endif } return 0; } @@ -476,6 +532,11 @@ x_top_window_to_frame (dpyinfo, wdesc) if (x->widget) { /* This frame matches if the window is its topmost widget. */ +#ifdef USE_GTK + GtkWidget *gwdesc = xg_win_to_widget (wdesc); + if (gwdesc == x->widget) + return f; +#else if (wdesc == XtWindow (x->widget)) return f; #if 0 /* I don't know why it did this, @@ -485,6 +546,7 @@ x_top_window_to_frame (dpyinfo, wdesc) if (x->menubar_widget && wdesc == XtWindow (x->menubar_widget)) return f; +#endif #endif } else if (FRAME_X_WINDOW (f) == wdesc) @@ -493,7 +555,7 @@ x_top_window_to_frame (dpyinfo, wdesc) } return 0; } -#endif /* USE_X_TOOLKIT */ +#endif /* USE_X_TOOLKIT || USE_GTK */ @@ -627,7 +689,7 @@ x_create_bitmap_from_file (f, file) { if (dpyinfo->bitmaps[id].refcount && dpyinfo->bitmaps[id].file - && !strcmp (dpyinfo->bitmaps[id].file, (char *) XSTRING (file)->data)) + && !strcmp (dpyinfo->bitmaps[id].file, (char *) SDATA (file))) { ++dpyinfo->bitmaps[id].refcount; return id + 1; @@ -635,12 +697,12 @@ x_create_bitmap_from_file (f, file) } /* Search bitmap-file-path for the file, if appropriate. */ - fd = openp (Vx_bitmap_file_path, file, "", &found, 0); + fd = openp (Vx_bitmap_file_path, file, Qnil, &found, Qnil); if (fd < 0) return -1; emacs_close (fd); - filename = (char *) XSTRING (found)->data; + filename = (char *) SDATA (found); result = XReadBitmapFile (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), filename, &width, &height, &bitmap, &xhot, &yhot); @@ -651,11 +713,11 @@ x_create_bitmap_from_file (f, file) dpyinfo->bitmaps[id - 1].pixmap = bitmap; dpyinfo->bitmaps[id - 1].refcount = 1; dpyinfo->bitmaps[id - 1].file - = (char *) xmalloc (STRING_BYTES (XSTRING (file)) + 1); + = (char *) xmalloc (SBYTES (file) + 1); dpyinfo->bitmaps[id - 1].depth = 1; dpyinfo->bitmaps[id - 1].height = height; dpyinfo->bitmaps[id - 1].width = width; - strcpy (dpyinfo->bitmaps[id - 1].file, XSTRING (file)->data); + strcpy (dpyinfo->bitmaps[id - 1].file, SDATA (file)); return id; } @@ -720,9 +782,10 @@ static Lisp_Object unwind_create_frame P_ ((Lisp_Object)); static Lisp_Object unwind_create_tip_frame P_ ((Lisp_Object)); static void x_change_window_heights P_ ((Lisp_Object, int)); static void x_disable_image P_ ((struct frame *, struct image *)); -static void x_create_im P_ ((struct frame *)); void x_set_foreground_color P_ ((struct frame *, Lisp_Object, Lisp_Object)); static void x_set_line_spacing P_ ((struct frame *, Lisp_Object, Lisp_Object)); +static void x_set_wait_for_wm P_ ((struct frame *, Lisp_Object, Lisp_Object)); +static void x_set_fullscreen P_ ((struct frame *, Lisp_Object, Lisp_Object)); void x_set_background_color P_ ((struct frame *, Lisp_Object, Lisp_Object)); void x_set_mouse_color P_ ((struct frame *, Lisp_Object, Lisp_Object)); void x_set_cursor_color P_ ((struct frame *, Lisp_Object, Lisp_Object)); @@ -730,6 +793,7 @@ void x_set_border_color P_ ((struct frame *, Lisp_Object, Lisp_Object)); void x_set_cursor_type P_ ((struct frame *, Lisp_Object, Lisp_Object)); void x_set_icon_type P_ ((struct frame *, Lisp_Object, Lisp_Object)); void x_set_icon_name P_ ((struct frame *, Lisp_Object, Lisp_Object)); +static void x_set_fringe_width P_ ((struct frame *, Lisp_Object, Lisp_Object)); void x_set_font P_ ((struct frame *, Lisp_Object, Lisp_Object)); void x_set_border_width P_ ((struct frame *, Lisp_Object, Lisp_Object)); void x_set_internal_border_width P_ ((struct frame *, Lisp_Object, @@ -767,31 +831,36 @@ static unsigned long lookup_pixel_color P_ ((struct frame *f, unsigned long p)); static struct x_frame_parm_table x_frame_parms[] = { - "auto-raise", x_set_autoraise, - "auto-lower", x_set_autolower, - "background-color", x_set_background_color, - "border-color", x_set_border_color, - "border-width", x_set_border_width, - "cursor-color", x_set_cursor_color, - "cursor-type", x_set_cursor_type, - "font", x_set_font, - "foreground-color", x_set_foreground_color, - "icon-name", x_set_icon_name, - "icon-type", x_set_icon_type, - "internal-border-width", x_set_internal_border_width, - "menu-bar-lines", x_set_menu_bar_lines, - "mouse-color", x_set_mouse_color, - "name", x_explicitly_set_name, - "scroll-bar-width", x_set_scroll_bar_width, - "title", x_set_title, - "unsplittable", x_set_unsplittable, - "vertical-scroll-bars", x_set_vertical_scroll_bars, - "visibility", x_set_visibility, - "tool-bar-lines", x_set_tool_bar_lines, - "scroll-bar-foreground", x_set_scroll_bar_foreground, - "scroll-bar-background", x_set_scroll_bar_background, - "screen-gamma", x_set_screen_gamma, - "line-spacing", x_set_line_spacing + {"auto-raise", x_set_autoraise}, + {"auto-lower", x_set_autolower}, + {"background-color", x_set_background_color}, + {"border-color", x_set_border_color}, + {"border-width", x_set_border_width}, + {"cursor-color", x_set_cursor_color}, + {"cursor-type", x_set_cursor_type}, + {"font", x_set_font}, + {"foreground-color", x_set_foreground_color}, + {"icon-name", x_set_icon_name}, + {"icon-type", x_set_icon_type}, + {"internal-border-width", x_set_internal_border_width}, + {"menu-bar-lines", x_set_menu_bar_lines}, + {"mouse-color", x_set_mouse_color}, + {"name", x_explicitly_set_name}, + {"scroll-bar-width", x_set_scroll_bar_width}, + {"title", x_set_title}, + {"unsplittable", x_set_unsplittable}, + {"vertical-scroll-bars", x_set_vertical_scroll_bars}, + {"visibility", x_set_visibility}, + {"tool-bar-lines", x_set_tool_bar_lines}, + {"scroll-bar-foreground", x_set_scroll_bar_foreground}, + {"scroll-bar-background", x_set_scroll_bar_background}, + {"screen-gamma", x_set_screen_gamma}, + {"line-spacing", x_set_line_spacing}, + {"left-fringe", x_set_fringe_width}, + {"right-fringe", x_set_fringe_width}, + {"wait-for-wm", x_set_wait_for_wm}, + {"fullscreen", x_set_fullscreen}, + }; /* Attach the `x-frame-parameter' properties to @@ -807,6 +876,28 @@ init_x_parm_symbols () make_number (i)); } + +/* Really try to move where we want to be in case of fullscreen. Some WMs + moves the window where we tell them. Some (mwm, twm) moves the outer + window manager window there instead. + Try to compensate for those WM here. */ +static void +x_fullscreen_move (f, new_top, new_left) + struct frame *f; + int new_top; + int new_left; +{ + if (new_top != f->output_data.x->top_pos + || new_left != f->output_data.x->left_pos) + { + int move_x = new_left + f->output_data.x->x_pixels_outer_diff; + int move_y = new_top + f->output_data.x->y_pixels_outer_diff; + + f->output_data.x->want_fullscreen |= FULLSCREEN_MOVE_WAIT; + x_set_offset (f, move_x, move_y, 1); + } +} + /* Change the parameters of frame F as specified by ALIST. If a parameter is not specially recognized, do nothing special; otherwise call the `x_set_...' function for that parameter. @@ -837,6 +928,7 @@ x_set_frame_parameters (f, alist) int i, p; int left_no_change = 0, top_no_change = 0; int icon_left_no_change = 0, icon_top_no_change = 0; + int fullscreen_is_being_set = 0; struct gcpro gcpro1, gcpro2; @@ -885,23 +977,34 @@ x_set_frame_parameters (f, alist) /* Process foreground_color and background_color before anything else. They are independent of other properties, but other properties (e.g., cursor_color) are dependent upon them. */ + /* Process default font as well, since fringe widths depends on it. */ + /* Also, process fullscreen, width and height depend upon that */ for (p = 0; p < i; p++) { Lisp_Object prop, val; prop = parms[p]; val = values[p]; - if (EQ (prop, Qforeground_color) || EQ (prop, Qbackground_color)) + if (EQ (prop, Qforeground_color) + || EQ (prop, Qbackground_color) + || EQ (prop, Qfont) + || EQ (prop, Qfullscreen)) { register Lisp_Object param_index, old_value; - param_index = Fget (prop, Qx_frame_parameter); old_value = get_frame_param (f, prop); - store_frame_param (f, prop, val); - if (NATNUMP (param_index) - && (XFASTINT (param_index) - < sizeof (x_frame_parms)/sizeof (x_frame_parms[0]))) - (*x_frame_parms[XINT (param_index)].setter)(f, val, old_value); + fullscreen_is_being_set |= EQ (prop, Qfullscreen); + + if (NILP (Fequal (val, old_value))) + { + store_frame_param (f, prop, val); + + param_index = Fget (prop, Qx_frame_parameter); + if (NATNUMP (param_index) + && (XFASTINT (param_index) + < sizeof (x_frame_parms)/sizeof (x_frame_parms[0]))) + (*x_frame_parms[XINT (param_index)].setter)(f, val, old_value); + } } } @@ -925,17 +1028,22 @@ x_set_frame_parameters (f, alist) icon_top = val; else if (EQ (prop, Qicon_left)) icon_left = val; - else if (EQ (prop, Qforeground_color) || EQ (prop, Qbackground_color)) + else if (EQ (prop, Qforeground_color) + || EQ (prop, Qbackground_color) + || EQ (prop, Qfont) + || EQ (prop, Qfullscreen)) /* Processed above. */ continue; else { register Lisp_Object param_index, old_value; - param_index = Fget (prop, Qx_frame_parameter); old_value = get_frame_param (f, prop); + store_frame_param (f, prop, val); - if (NATNUMP (param_index) + + param_index = Fget (prop, Qx_frame_parameter); + if (NATNUMP (param_index) && (XFASTINT (param_index) < sizeof (x_frame_parms)/sizeof (x_frame_parms[0]))) (*x_frame_parms[XINT (param_index)].setter)(f, val, old_value); @@ -976,6 +1084,21 @@ x_set_frame_parameters (f, alist) XSETINT (icon_top, 0); } + if (FRAME_VISIBLE_P (f) && fullscreen_is_being_set) + { + /* If the frame is visible already and the fullscreen parameter is + being set, it is too late to set WM manager hints to specify + size and position. + Here we first get the width, height and position that applies to + fullscreen. We then move the frame to the appropriate + position. Resize of the frame is taken care of in the code after + this if-statement. */ + int new_left, new_top; + + x_fullscreen_adjust (f, &width, &height, &new_top, &new_left); + x_fullscreen_move (f, new_top, new_left); + } + /* Don't set these parameters unless they've been explicitly specified. The window might be mapped or resized while we're in this function, and we don't want to override that unless the lisp @@ -1078,70 +1201,115 @@ x_real_positions (f, xptr, yptr) FRAME_PTR f; int *xptr, *yptr; { - int win_x, win_y; - Window child; + int win_x, win_y, outer_x, outer_y; + int real_x = 0, real_y = 0; + int had_errors = 0; + Window win = f->output_data.x->parent_desc; - /* This is pretty gross, but seems to be the easiest way out of - the problem that arises when restarting window-managers. */ + int count; -#ifdef USE_X_TOOLKIT - Window outer = (f->output_data.x->widget - ? XtWindow (f->output_data.x->widget) - : FRAME_X_WINDOW (f)); -#else - Window outer = f->output_data.x->window_desc; -#endif - Window tmp_root_window; - Window *tmp_children; - unsigned int tmp_nchildren; + BLOCK_INPUT; + + count = x_catch_errors (FRAME_X_DISPLAY (f)); - while (1) + if (win == FRAME_X_DISPLAY_INFO (f)->root_window) + win = FRAME_OUTER_WINDOW (f); + + /* This loop traverses up the containment tree until we hit the root + window. Window managers may intersect many windows between our window + and the root window. The window we find just before the root window + should be the outer WM window. */ + for (;;) { - int count = x_catch_errors (FRAME_X_DISPLAY (f)); - Window outer_window; + Window wm_window, rootw; + Window *tmp_children; + unsigned int tmp_nchildren; + int success; - XQueryTree (FRAME_X_DISPLAY (f), outer, &tmp_root_window, - &f->output_data.x->parent_desc, - &tmp_children, &tmp_nchildren); - XFree ((char *) tmp_children); + success = XQueryTree (FRAME_X_DISPLAY (f), win, &rootw, + &wm_window, &tmp_children, &tmp_nchildren); - win_x = win_y = 0; + had_errors = x_had_errors_p (FRAME_X_DISPLAY (f)); - /* Find the position of the outside upper-left corner of - the inner window, with respect to the outer window. */ - if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window) - outer_window = f->output_data.x->parent_desc; - else - outer_window = outer; + /* Don't free tmp_children if XQueryTree failed. */ + if (! success) + break; + + XFree ((char *) tmp_children); + + if (wm_window == rootw || had_errors) + break; + win = wm_window; + } + + if (! had_errors) + { + int 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, &ign, &ign, &ign, &ign); + + /* Translate real coordinates to coordinates relative to our + window. For our window, the upper left corner is 0, 0. + Since the upper left corner of the WM window is outside + our window, win_x and win_y will be negative: + + ------------------ ---> x + | title | + | ----------------- v y + | | our window + */ XTranslateCoordinates (FRAME_X_DISPLAY (f), /* From-window, to-window. */ - outer_window, FRAME_X_DISPLAY_INFO (f)->root_window, + FRAME_X_WINDOW (f), /* From-position, to-position. */ - 0, 0, &win_x, &win_y, + real_x, real_y, &win_x, &win_y, /* Child of win. */ &child); - /* It is possible for the window returned by the XQueryNotify - to become invalid by the time we call XTranslateCoordinates. - That can happen when you restart some window managers. - If so, we get an error in XTranslateCoordinates. - Detect that and try the whole thing over. */ - if (! x_had_errors_p (FRAME_X_DISPLAY (f))) + if (FRAME_X_WINDOW (f) == FRAME_OUTER_WINDOW (f)) { - x_uncatch_errors (FRAME_X_DISPLAY (f), count); - break; + outer_x = win_x; + outer_y = win_y; } + else + { + XTranslateCoordinates (FRAME_X_DISPLAY (f), + + /* From-window, to-window. */ + FRAME_X_DISPLAY_INFO (f)->root_window, + FRAME_OUTER_WINDOW (f), + + /* From-position, to-position. */ + real_x, real_y, &outer_x, &outer_y, + + /* Child of win. */ + &child); + } - x_uncatch_errors (FRAME_X_DISPLAY (f), count); + had_errors = x_had_errors_p (FRAME_X_DISPLAY (f)); } + + x_uncatch_errors (FRAME_X_DISPLAY (f), count); + + UNBLOCK_INPUT; + + if (had_errors) return; + + f->output_data.x->x_pixels_diff = -win_x; + f->output_data.x->y_pixels_diff = -win_y; + f->output_data.x->x_pixels_outer_diff = -outer_x; + f->output_data.x->y_pixels_outer_diff = -outer_y; - *xptr = win_x; - *yptr = win_y; + *xptr = real_x; + *yptr = real_y; } /* Insert a description of internally-recorded parameters of frame X @@ -1176,6 +1344,19 @@ x_report_frame_params (f, alistptr) make_number (f->output_data.x->border_width)); store_in_alist (alistptr, Qinternal_border_width, make_number (f->output_data.x->internal_border_width)); + store_in_alist (alistptr, Qleft_fringe, + make_number (f->output_data.x->left_fringe_width)); + store_in_alist (alistptr, Qright_fringe, + make_number (f->output_data.x->right_fringe_width)); + store_in_alist (alistptr, Qscroll_bar_width, + (! FRAME_HAS_VERTICAL_SCROLL_BARS (f) + ? make_number (0) + : FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0 + ? make_number (FRAME_SCROLL_BAR_PIXEL_WIDTH (f)) + /* nil means "use default width" + for non-toolkit scroll bar. + ruler-mode.el depends on this. */ + : Qnil)); sprintf (buf, "%ld", (long) FRAME_X_WINDOW (f)); store_in_alist (alistptr, Qwindow_id, build_string (buf)); @@ -1257,14 +1438,14 @@ x_decode_color (f, color_name, mono_color) { XColor cdef; - CHECK_STRING (color_name, 0); + CHECK_STRING (color_name); #if 0 /* Don't do this. It's wrong when we're not using the default colormap, it makes freeing difficult, and it's probably not an important optimization. */ - if (strcmp (XSTRING (color_name)->data, "black") == 0) + if (strcmp (SDATA (color_name), "black") == 0) return BLACK_PIX_DEFAULT (f); - else if (strcmp (XSTRING (color_name)->data, "white") == 0) + else if (strcmp (SDATA (color_name), "white") == 0) return WHITE_PIX_DEFAULT (f); #endif @@ -1274,7 +1455,7 @@ x_decode_color (f, color_name, mono_color) /* x_defined_color is responsible for coping with failures by looking for a near-miss. */ - if (x_defined_color (f, XSTRING (color_name)->data, &cdef, 1)) + if (x_defined_color (f, SDATA (color_name), &cdef, 1)) return cdef.pixel; Fsignal (Qerror, Fcons (build_string ("Undefined color"), @@ -1304,8 +1485,41 @@ x_set_line_spacing (f, new_value, old_value) } +/* Change the `wait-for-wm' frame parameter of frame F. OLD_VALUE is + the previous value of that parameter, NEW_VALUE is the new value. + See also the comment of wait_for_wm in struct x_output. */ + +static void +x_set_wait_for_wm (f, new_value, old_value) + struct frame *f; + Lisp_Object new_value, old_value; +{ + f->output_data.x->wait_for_wm = !NILP (new_value); +} + + +/* Change the `fullscreen' frame parameter of frame F. OLD_VALUE is + the previous value of that parameter, NEW_VALUE is the new value. */ + +static void +x_set_fullscreen (f, new_value, old_value) + struct frame *f; + Lisp_Object new_value, old_value; +{ + if (NILP (new_value)) + f->output_data.x->want_fullscreen = FULLSCREEN_NONE; + else if (EQ (new_value, Qfullboth)) + f->output_data.x->want_fullscreen = FULLSCREEN_BOTH; + else if (EQ (new_value, Qfullwidth)) + f->output_data.x->want_fullscreen = FULLSCREEN_WIDTH; + else if (EQ (new_value, Qfullheight)) + f->output_data.x->want_fullscreen = FULLSCREEN_HEIGHT; +} + + /* Change the `screen-gamma' frame parameter of frame F. OLD_VALUE is - the previous value of that parameter, NEW_VALUE is the new value. */ + the previous value of that parameter, NEW_VALUE is the new + value. */ static void x_set_screen_gamma (f, new_value, old_value) @@ -1338,23 +1552,37 @@ x_set_foreground_color (f, arg, oldval) struct frame *f; Lisp_Object arg, oldval; { - unsigned long pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f)); + struct x_output *x = f->output_data.x; + unsigned long fg, old_fg; - unload_color (f, f->output_data.x->foreground_pixel); - f->output_data.x->foreground_pixel = pixel; + fg = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f)); + old_fg = x->foreground_pixel; + x->foreground_pixel = fg; if (FRAME_X_WINDOW (f) != 0) { + Display *dpy = FRAME_X_DISPLAY (f); + BLOCK_INPUT; - XSetForeground (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc, - f->output_data.x->foreground_pixel); - XSetBackground (FRAME_X_DISPLAY (f), f->output_data.x->reverse_gc, - f->output_data.x->foreground_pixel); + XSetForeground (dpy, x->normal_gc, fg); + XSetBackground (dpy, x->reverse_gc, fg); + + if (x->cursor_pixel == old_fg) + { + unload_color (f, x->cursor_pixel); + x->cursor_pixel = x_copy_color (f, fg); + XSetBackground (dpy, x->cursor_gc, x->cursor_pixel); + } + UNBLOCK_INPUT; + update_face_from_frame_parameter (f, Qforeground_color, arg); + if (FRAME_VISIBLE_P (f)) redraw_frame (f); } + + unload_color (f, old_fg); } void @@ -1362,33 +1590,42 @@ x_set_background_color (f, arg, oldval) struct frame *f; Lisp_Object arg, oldval; { - unsigned long pixel = x_decode_color (f, arg, WHITE_PIX_DEFAULT (f)); + struct x_output *x = f->output_data.x; + unsigned long bg; - unload_color (f, f->output_data.x->background_pixel); - f->output_data.x->background_pixel = pixel; + bg = x_decode_color (f, arg, WHITE_PIX_DEFAULT (f)); + unload_color (f, x->background_pixel); + x->background_pixel = bg; if (FRAME_X_WINDOW (f) != 0) { + Display *dpy = FRAME_X_DISPLAY (f); + BLOCK_INPUT; - /* The main frame area. */ - XSetBackground (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc, - f->output_data.x->background_pixel); - XSetForeground (FRAME_X_DISPLAY (f), f->output_data.x->reverse_gc, - f->output_data.x->background_pixel); - XSetForeground (FRAME_X_DISPLAY (f), f->output_data.x->cursor_gc, - f->output_data.x->background_pixel); - XSetWindowBackground (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), - f->output_data.x->background_pixel); + XSetBackground (dpy, x->normal_gc, bg); + XSetForeground (dpy, x->reverse_gc, bg); + XSetWindowBackground (dpy, FRAME_X_WINDOW (f), bg); + XSetForeground (dpy, x->cursor_gc, bg); + +#ifdef USE_GTK + xg_set_background_color (f, bg); +#endif + +#ifndef USE_TOOLKIT_SCROLL_BARS /* Turns out to be annoying with + toolkit scroll bars. */ { Lisp_Object bar; - for (bar = FRAME_SCROLL_BARS (f); !NILP (bar); + for (bar = FRAME_SCROLL_BARS (f); + !NILP (bar); bar = XSCROLL_BAR (bar)->next) - XSetWindowBackground (FRAME_X_DISPLAY (f), - SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)), - f->output_data.x->background_pixel); + { + Window window = SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)); + XSetWindowBackground (dpy, window, bg); + } } - UNBLOCK_INPUT; +#endif /* USE_TOOLKIT_SCROLL_BARS */ + UNBLOCK_INPUT; update_face_from_frame_parameter (f, Qbackground_color, arg); if (FRAME_VISIBLE_P (f)) @@ -1401,149 +1638,141 @@ x_set_mouse_color (f, arg, oldval) struct frame *f; Lisp_Object arg, oldval; { + struct x_output *x = f->output_data.x; + Display *dpy = FRAME_X_DISPLAY (f); Cursor cursor, nontext_cursor, mode_cursor, cross_cursor; - Cursor busy_cursor, horizontal_drag_cursor; + Cursor hourglass_cursor, horizontal_drag_cursor; int count; unsigned long pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f)); - unsigned long mask_color = f->output_data.x->background_pixel; + unsigned long mask_color = x->background_pixel; /* Don't let pointers be invisible. */ - if (mask_color == pixel - && mask_color == f->output_data.x->background_pixel) + if (mask_color == pixel) { x_free_colors (f, &pixel, 1); - pixel = x_copy_color (f, f->output_data.x->foreground_pixel); + pixel = x_copy_color (f, x->foreground_pixel); } - unload_color (f, f->output_data.x->mouse_pixel); - f->output_data.x->mouse_pixel = pixel; + unload_color (f, x->mouse_pixel); + x->mouse_pixel = pixel; BLOCK_INPUT; /* It's not okay to crash if the user selects a screwy cursor. */ - count = x_catch_errors (FRAME_X_DISPLAY (f)); + count = x_catch_errors (dpy); - if (!EQ (Qnil, Vx_pointer_shape)) + if (!NILP (Vx_pointer_shape)) { - CHECK_NUMBER (Vx_pointer_shape, 0); - cursor = XCreateFontCursor (FRAME_X_DISPLAY (f), XINT (Vx_pointer_shape)); + CHECK_NUMBER (Vx_pointer_shape); + cursor = XCreateFontCursor (dpy, XINT (Vx_pointer_shape)); } else - cursor = XCreateFontCursor (FRAME_X_DISPLAY (f), XC_xterm); - x_check_errors (FRAME_X_DISPLAY (f), "bad text pointer cursor: %s"); + cursor = XCreateFontCursor (dpy, XC_xterm); + x_check_errors (dpy, "bad text pointer cursor: %s"); - if (!EQ (Qnil, Vx_nontext_pointer_shape)) + if (!NILP (Vx_nontext_pointer_shape)) { - CHECK_NUMBER (Vx_nontext_pointer_shape, 0); - nontext_cursor = XCreateFontCursor (FRAME_X_DISPLAY (f), - XINT (Vx_nontext_pointer_shape)); + CHECK_NUMBER (Vx_nontext_pointer_shape); + nontext_cursor + = XCreateFontCursor (dpy, XINT (Vx_nontext_pointer_shape)); } else - nontext_cursor = XCreateFontCursor (FRAME_X_DISPLAY (f), XC_left_ptr); - x_check_errors (FRAME_X_DISPLAY (f), "bad nontext pointer cursor: %s"); + nontext_cursor = XCreateFontCursor (dpy, XC_left_ptr); + x_check_errors (dpy, "bad nontext pointer cursor: %s"); - if (!EQ (Qnil, Vx_busy_pointer_shape)) + if (!NILP (Vx_hourglass_pointer_shape)) { - CHECK_NUMBER (Vx_busy_pointer_shape, 0); - busy_cursor = XCreateFontCursor (FRAME_X_DISPLAY (f), - XINT (Vx_busy_pointer_shape)); + CHECK_NUMBER (Vx_hourglass_pointer_shape); + hourglass_cursor + = XCreateFontCursor (dpy, XINT (Vx_hourglass_pointer_shape)); } else - busy_cursor = XCreateFontCursor (FRAME_X_DISPLAY (f), XC_watch); - x_check_errors (FRAME_X_DISPLAY (f), "bad busy pointer cursor: %s"); + hourglass_cursor = XCreateFontCursor (dpy, XC_watch); + x_check_errors (dpy, "bad hourglass pointer cursor: %s"); - x_check_errors (FRAME_X_DISPLAY (f), "bad nontext pointer cursor: %s"); - if (!EQ (Qnil, Vx_mode_pointer_shape)) + x_check_errors (dpy, "bad nontext pointer cursor: %s"); + if (!NILP (Vx_mode_pointer_shape)) { - CHECK_NUMBER (Vx_mode_pointer_shape, 0); - mode_cursor = XCreateFontCursor (FRAME_X_DISPLAY (f), - XINT (Vx_mode_pointer_shape)); + CHECK_NUMBER (Vx_mode_pointer_shape); + mode_cursor = XCreateFontCursor (dpy, XINT (Vx_mode_pointer_shape)); } else - mode_cursor = XCreateFontCursor (FRAME_X_DISPLAY (f), XC_xterm); - x_check_errors (FRAME_X_DISPLAY (f), "bad modeline pointer cursor: %s"); + mode_cursor = XCreateFontCursor (dpy, XC_xterm); + x_check_errors (dpy, "bad modeline pointer cursor: %s"); - if (!EQ (Qnil, Vx_sensitive_text_pointer_shape)) + if (!NILP (Vx_sensitive_text_pointer_shape)) { - CHECK_NUMBER (Vx_sensitive_text_pointer_shape, 0); + CHECK_NUMBER (Vx_sensitive_text_pointer_shape); cross_cursor - = XCreateFontCursor (FRAME_X_DISPLAY (f), - XINT (Vx_sensitive_text_pointer_shape)); + = XCreateFontCursor (dpy, XINT (Vx_sensitive_text_pointer_shape)); } else - cross_cursor = XCreateFontCursor (FRAME_X_DISPLAY (f), XC_crosshair); + cross_cursor = XCreateFontCursor (dpy, XC_hand2); if (!NILP (Vx_window_horizontal_drag_shape)) { - CHECK_NUMBER (Vx_window_horizontal_drag_shape, 0); + CHECK_NUMBER (Vx_window_horizontal_drag_shape); horizontal_drag_cursor - = XCreateFontCursor (FRAME_X_DISPLAY (f), - XINT (Vx_window_horizontal_drag_shape)); + = XCreateFontCursor (dpy, XINT (Vx_window_horizontal_drag_shape)); } else horizontal_drag_cursor - = XCreateFontCursor (FRAME_X_DISPLAY (f), XC_sb_h_double_arrow); + = XCreateFontCursor (dpy, XC_sb_h_double_arrow); /* Check and report errors with the above calls. */ - x_check_errors (FRAME_X_DISPLAY (f), "can't set cursor shape: %s"); - x_uncatch_errors (FRAME_X_DISPLAY (f), count); + x_check_errors (dpy, "can't set cursor shape: %s"); + x_uncatch_errors (dpy, count); { XColor fore_color, back_color; - fore_color.pixel = f->output_data.x->mouse_pixel; + fore_color.pixel = x->mouse_pixel; x_query_color (f, &fore_color); back_color.pixel = mask_color; x_query_color (f, &back_color); - XRecolorCursor (FRAME_X_DISPLAY (f), cursor, - &fore_color, &back_color); - XRecolorCursor (FRAME_X_DISPLAY (f), nontext_cursor, - &fore_color, &back_color); - XRecolorCursor (FRAME_X_DISPLAY (f), mode_cursor, - &fore_color, &back_color); - XRecolorCursor (FRAME_X_DISPLAY (f), cross_cursor, - &fore_color, &back_color); - XRecolorCursor (FRAME_X_DISPLAY (f), busy_cursor, - &fore_color, &back_color); - XRecolorCursor (FRAME_X_DISPLAY (f), horizontal_drag_cursor, - &fore_color, &back_color); + XRecolorCursor (dpy, cursor, &fore_color, &back_color); + XRecolorCursor (dpy, nontext_cursor, &fore_color, &back_color); + XRecolorCursor (dpy, mode_cursor, &fore_color, &back_color); + XRecolorCursor (dpy, cross_cursor, &fore_color, &back_color); + XRecolorCursor (dpy, hourglass_cursor, &fore_color, &back_color); + XRecolorCursor (dpy, horizontal_drag_cursor, &fore_color, &back_color); } if (FRAME_X_WINDOW (f) != 0) - XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor); - - if (cursor != f->output_data.x->text_cursor - && f->output_data.x->text_cursor != 0) - XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->text_cursor); - f->output_data.x->text_cursor = cursor; - - if (nontext_cursor != f->output_data.x->nontext_cursor - && f->output_data.x->nontext_cursor != 0) - XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->nontext_cursor); - f->output_data.x->nontext_cursor = nontext_cursor; - - if (busy_cursor != f->output_data.x->busy_cursor - && f->output_data.x->busy_cursor != 0) - XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->busy_cursor); - f->output_data.x->busy_cursor = busy_cursor; - - if (mode_cursor != f->output_data.x->modeline_cursor - && f->output_data.x->modeline_cursor != 0) - XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->modeline_cursor); - f->output_data.x->modeline_cursor = mode_cursor; - - if (cross_cursor != f->output_data.x->cross_cursor - && f->output_data.x->cross_cursor != 0) - XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->cross_cursor); - f->output_data.x->cross_cursor = cross_cursor; - - if (horizontal_drag_cursor != f->output_data.x->horizontal_drag_cursor - && f->output_data.x->horizontal_drag_cursor != 0) - XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->horizontal_drag_cursor); - f->output_data.x->horizontal_drag_cursor = horizontal_drag_cursor; + XDefineCursor (dpy, FRAME_X_WINDOW (f), cursor); + + if (cursor != x->text_cursor + && x->text_cursor != 0) + XFreeCursor (dpy, x->text_cursor); + x->text_cursor = cursor; + + if (nontext_cursor != x->nontext_cursor + && x->nontext_cursor != 0) + XFreeCursor (dpy, x->nontext_cursor); + x->nontext_cursor = nontext_cursor; + + if (hourglass_cursor != x->hourglass_cursor + && x->hourglass_cursor != 0) + XFreeCursor (dpy, x->hourglass_cursor); + x->hourglass_cursor = hourglass_cursor; + + if (mode_cursor != x->modeline_cursor + && x->modeline_cursor != 0) + XFreeCursor (dpy, f->output_data.x->modeline_cursor); + x->modeline_cursor = mode_cursor; + + if (cross_cursor != x->cross_cursor + && x->cross_cursor != 0) + XFreeCursor (dpy, x->cross_cursor); + x->cross_cursor = cross_cursor; - XFlush (FRAME_X_DISPLAY (f)); + if (horizontal_drag_cursor != x->horizontal_drag_cursor + && x->horizontal_drag_cursor != 0) + XFreeCursor (dpy, x->horizontal_drag_cursor); + x->horizontal_drag_cursor = horizontal_drag_cursor; + + XFlush (dpy); UNBLOCK_INPUT; update_face_from_frame_parameter (f, Qmouse_color, arg); @@ -1556,6 +1785,7 @@ x_set_cursor_color (f, arg, oldval) { unsigned long fore_pixel, pixel; int fore_pixel_allocated_p = 0, pixel_allocated_p = 0; + struct x_output *x = f->output_data.x; if (!NILP (Vx_cursor_fore_pixel)) { @@ -1564,13 +1794,13 @@ x_set_cursor_color (f, arg, oldval) fore_pixel_allocated_p = 1; } else - fore_pixel = f->output_data.x->background_pixel; + fore_pixel = x->background_pixel; pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f)); pixel_allocated_p = 1; /* Make sure that the cursor color differs from the background color. */ - if (pixel == f->output_data.x->background_pixel) + if (pixel == x->background_pixel) { if (pixel_allocated_p) { @@ -1578,7 +1808,7 @@ x_set_cursor_color (f, arg, oldval) pixel_allocated_p = 0; } - pixel = f->output_data.x->mouse_pixel; + pixel = x->mouse_pixel; if (pixel == fore_pixel) { if (fore_pixel_allocated_p) @@ -1586,27 +1816,25 @@ x_set_cursor_color (f, arg, oldval) x_free_colors (f, &fore_pixel, 1); fore_pixel_allocated_p = 0; } - fore_pixel = f->output_data.x->background_pixel; + fore_pixel = x->background_pixel; } } - unload_color (f, f->output_data.x->cursor_foreground_pixel); + unload_color (f, x->cursor_foreground_pixel); if (!fore_pixel_allocated_p) fore_pixel = x_copy_color (f, fore_pixel); - f->output_data.x->cursor_foreground_pixel = fore_pixel; + x->cursor_foreground_pixel = fore_pixel; - unload_color (f, f->output_data.x->cursor_pixel); + unload_color (f, x->cursor_pixel); if (!pixel_allocated_p) pixel = x_copy_color (f, pixel); - f->output_data.x->cursor_pixel = pixel; + x->cursor_pixel = pixel; if (FRAME_X_WINDOW (f) != 0) { BLOCK_INPUT; - XSetBackground (FRAME_X_DISPLAY (f), f->output_data.x->cursor_gc, - f->output_data.x->cursor_pixel); - XSetForeground (FRAME_X_DISPLAY (f), f->output_data.x->cursor_gc, - fore_pixel); + XSetBackground (FRAME_X_DISPLAY (f), x->cursor_gc, x->cursor_pixel); + XSetForeground (FRAME_X_DISPLAY (f), x->cursor_gc, fore_pixel); UNBLOCK_INPUT; if (FRAME_VISIBLE_P (f)) @@ -1637,7 +1865,7 @@ x_set_border_color (f, arg, oldval) { int pix; - CHECK_STRING (arg, 0); + CHECK_STRING (arg); pix = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f)); x_set_border_pixel (f, pix); update_face_from_frame_parameter (f, Qborder_color, arg); @@ -1668,54 +1896,16 @@ x_set_border_pixel (f, pix) } -/* Value is the internal representation of the specified cursor type - ARG. If type is BAR_CURSOR, return in *WIDTH the specified width - of the bar cursor. */ - -enum text_cursor_kinds -x_specified_cursor_type (arg, width) - Lisp_Object arg; - int *width; -{ - enum text_cursor_kinds type; - - if (EQ (arg, Qbar)) - { - type = BAR_CURSOR; - *width = 2; - } - else if (CONSP (arg) - && EQ (XCAR (arg), Qbar) - && INTEGERP (XCDR (arg)) - && XINT (XCDR (arg)) >= 0) - { - type = BAR_CURSOR; - *width = XINT (XCDR (arg)); - } - else if (NILP (arg)) - type = NO_CURSOR; - else - /* Treat anything unknown as "box cursor". - It was bad to signal an error; people have trouble fixing - .Xdefaults with Emacs, when it has something bad in it. */ - type = FILLED_BOX_CURSOR; - - return type; -} void x_set_cursor_type (f, arg, oldval) FRAME_PTR f; Lisp_Object arg, oldval; { - int width; - - FRAME_DESIRED_CURSOR (f) = x_specified_cursor_type (arg, &width); - f->output_data.x->cursor_width = width; + set_frame_cursor_types (f, arg); - /* Make sure the cursor gets redrawn. This is overkill, but how - often do people change cursor types? */ - update_mode_lines++; + /* Make sure the cursor gets redrawn. */ + cursor_type_changed = 1; } void @@ -1736,9 +1926,9 @@ x_set_icon_type (f, arg, oldval) BLOCK_INPUT; if (NILP (arg)) result = x_text_icon (f, - (char *) XSTRING ((!NILP (f->icon_name) + (char *) SDATA ((!NILP (f->icon_name) ? f->icon_name - : f->name))->data); + : f->name))); else result = x_bitmap_icon (f, arg); @@ -1790,11 +1980,11 @@ x_set_icon_name (f, arg, oldval) BLOCK_INPUT; result = x_text_icon (f, - (char *) XSTRING ((!NILP (f->icon_name) - ? f->icon_name - : !NILP (f->title) - ? f->title - : f->name))->data); + (char *) SDATA ((!NILP (f->icon_name) + ? f->icon_name + : !NILP (f->title) + ? f->title + : f->name))); if (result) { @@ -1814,25 +2004,34 @@ x_set_font (f, arg, oldval) Lisp_Object result; Lisp_Object fontset_name; Lisp_Object frame; + int old_fontset = f->output_data.x->fontset; - CHECK_STRING (arg, 1); + CHECK_STRING (arg); fontset_name = Fquery_fontset (arg, Qnil); BLOCK_INPUT; result = (STRINGP (fontset_name) - ? x_new_fontset (f, XSTRING (fontset_name)->data) - : x_new_font (f, XSTRING (arg)->data)); + ? x_new_fontset (f, SDATA (fontset_name)) + : x_new_font (f, SDATA (arg))); UNBLOCK_INPUT; if (EQ (result, Qnil)) - error ("Font `%s' is not defined", XSTRING (arg)->data); + error ("Font `%s' is not defined", SDATA (arg)); else if (EQ (result, Qt)) error ("The characters of the given font have varying widths"); else if (STRINGP (result)) { - if (!NILP (Fequal (result, oldval))) + if (STRINGP (fontset_name)) + { + /* Fontset names are built from ASCII font names, so the + names may be equal despite there was a change. */ + if (old_fontset == f->output_data.x->fontset) + return; + } + else if (!NILP (Fequal (result, oldval))) return; + store_frame_param (f, Qfont, result); recompute_basic_faces (f); } @@ -1853,12 +2052,20 @@ x_set_font (f, arg, oldval) } } +static void +x_set_fringe_width (f, new_value, old_value) + struct frame *f; + Lisp_Object new_value, old_value; +{ + x_compute_fringe_widths (f, 1); +} + void x_set_border_width (f, arg, oldval) struct frame *f; Lisp_Object arg, oldval; { - CHECK_NUMBER (arg, 0); + CHECK_NUMBER (arg); if (XINT (arg) == f->output_data.x->border_width) return; @@ -1876,7 +2083,7 @@ x_set_internal_border_width (f, arg, oldval) { int old = f->output_data.x->internal_border_width; - CHECK_NUMBER (arg, 0); + CHECK_NUMBER (arg); f->output_data.x->internal_border_width = XINT (arg); if (f->output_data.x->internal_border_width < 0) f->output_data.x->internal_border_width = 0; @@ -1895,6 +2102,8 @@ x_set_internal_border_width (f, arg, oldval) SET_FRAME_GARBAGED (f); do_pending_window_change (0); } + else + SET_FRAME_GARBAGED (f); } void @@ -1968,7 +2177,7 @@ x_set_menu_bar_lines (f, value, oldval) /* Make sure we redisplay all windows in this frame. */ windows_or_buffers_changed++; -#ifdef USE_X_TOOLKIT +#if defined (USE_X_TOOLKIT) || defined (USE_GTK) FRAME_MENU_BAR_LINES (f) = 0; if (nlines) { @@ -1985,7 +2194,7 @@ x_set_menu_bar_lines (f, value, oldval) if (FRAME_X_P (f)) f->output_data.x->menubar_widget = 0; } -#else /* not USE_X_TOOLKIT */ +#else /* not USE_X_TOOLKIT && not USE_GTK */ FRAME_MENU_BAR_LINES (f) = nlines; x_change_window_heights (f->root_window, nlines - olines); #endif /* not USE_X_TOOLKIT */ @@ -2017,7 +2226,27 @@ x_set_tool_bar_lines (f, value, oldval) else nlines = 0; - /* Make sure we redisplay all windows in this frame. */ +#ifdef USE_GTK + FRAME_TOOL_BAR_LINES (f) = 0; + if (nlines) + { + FRAME_EXTERNAL_TOOL_BAR (f) = 1; + if (FRAME_X_P (f) && f->output_data.x->toolbar_widget == 0) + /* Make sure next redisplay shows the tool bar. */ + XWINDOW (FRAME_SELECTED_WINDOW (f))->update_mode_line = Qt; + update_frame_tool_bar (f); + } + else + { + if (FRAME_EXTERNAL_TOOL_BAR (f)) + free_frame_tool_bar (f); + FRAME_EXTERNAL_TOOL_BAR (f) = 0; + } + + return; +#endif + + /* Make sure we redisplay all windows in this frame. */ ++windows_or_buffers_changed; delta = nlines - FRAME_TOOL_BAR_LINES (f); @@ -2062,6 +2291,9 @@ x_set_tool_bar_lines (f, value, oldval) x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 0, y, width, height, False); UNBLOCK_INPUT; + + if (WINDOWP (f->tool_bar_window)) + clear_glyph_matrix (XWINDOW (f->tool_bar_window)->current_matrix); } } @@ -2121,6 +2353,20 @@ x_set_scroll_bar_background (f, value, oldval) if (f->output_data.x->scroll_bar_background_pixel != -1) unload_color (f, f->output_data.x->scroll_bar_background_pixel); +#ifdef USE_TOOLKIT_SCROLL_BARS + /* Scrollbar shadow colors. */ + if (f->output_data.x->scroll_bar_top_shadow_pixel != -1) + { + unload_color (f, f->output_data.x->scroll_bar_top_shadow_pixel); + f->output_data.x->scroll_bar_top_shadow_pixel = -1; + } + if (f->output_data.x->scroll_bar_bottom_shadow_pixel != -1) + { + unload_color (f, f->output_data.x->scroll_bar_bottom_shadow_pixel); + f->output_data.x->scroll_bar_bottom_shadow_pixel = -1; + } +#endif /* USE_TOOLKIT_SCROLL_BARS */ + f->output_data.x->scroll_bar_background_pixel = pixel; if (FRAME_X_WINDOW (f) && FRAME_VISIBLE_P (f)) { @@ -2144,6 +2390,10 @@ x_set_scroll_bar_background (f, value, oldval) CODING_SYSTEM, and return a newly allocated memory area which should be freed by `xfree' by a caller. + SELECTIONP non-zero means the string is being encoded for an X + selection, so it is safe to run pre-write conversions (which + may run Lisp code). + Store the byte length of resulting text in *TEXT_BYTES. If the text contains only ASCII and Latin-1, store 1 in *STRING_P, @@ -2152,17 +2402,19 @@ x_set_scroll_bar_background (f, value, oldval) the result should be `COMPOUND_TEXT'. */ unsigned char * -x_encode_text (string, coding_system, text_bytes, stringp) +x_encode_text (string, coding_system, selectionp, text_bytes, stringp) Lisp_Object string, coding_system; int *text_bytes, *stringp; + int selectionp; { - unsigned char *str = XSTRING (string)->data; - int chars = XSTRING (string)->size; - int bytes = STRING_BYTES (XSTRING (string)); + unsigned char *str = SDATA (string); + int chars = SCHARS (string); + int bytes = SBYTES (string); int charset_info; int bufsize; unsigned char *buf; struct coding_system coding; + extern Lisp_Object Qcompound_text_with_extensions; charset_info = find_charset_in_text (str, chars, bytes, NULL, Qnil); if (charset_info == 0) @@ -2174,6 +2426,15 @@ x_encode_text (string, coding_system, text_bytes, stringp) } setup_coding_system (coding_system, &coding); + if (selectionp + && SYMBOLP (coding.pre_write_conversion) + && !NILP (Ffboundp (coding.pre_write_conversion))) + { + string = run_pre_post_conversion_on_str (string, &coding, 1); + str = SDATA (string); + chars = SCHARS (string); + bytes = SBYTES (string); + } coding.src_multibyte = 1; coding.dst_multibyte = 0; coding.mode |= CODING_MODE_LAST_BLOCK; @@ -2185,7 +2446,9 @@ x_encode_text (string, coding_system, text_bytes, stringp) buf = (unsigned char *) xmalloc (bufsize); encode_coding (&coding, str, buf, bytes, bufsize); *text_bytes = coding.produced; - *stringp = (charset_info == 1 || !EQ (coding_system, Qcompound_text)); + *stringp = (charset_info == 1 + || (!EQ (coding_system, Qcompound_text) + && !EQ (coding_system, Qcompound_text_with_extensions))); return buf; } @@ -2227,12 +2490,12 @@ x_set_name (f, name, explicit) /* Check for no change needed in this very common case before we do any consing. */ if (!strcmp (FRAME_X_DISPLAY_INFO (f)->x_id_name, - XSTRING (f->name)->data)) + SDATA (f->name))) return; name = build_string (FRAME_X_DISPLAY_INFO (f)->x_id_name); } else - CHECK_STRING (name, 0); + CHECK_STRING (name); /* Don't change the name if it's already NAME. */ if (! NILP (Fstring_equal (name, f->name))) @@ -2254,10 +2517,8 @@ x_set_name (f, name, explicit) int bytes, stringp; Lisp_Object coding_system; - coding_system = Vlocale_coding_system; - if (NILP (coding_system)) - coding_system = Qcompound_text; - text.value = x_encode_text (name, coding_system, &bytes, &stringp); + coding_system = Qcompound_text; + text.value = x_encode_text (name, coding_system, 0, &bytes, &stringp); text.encoding = (stringp ? XA_STRING : FRAME_X_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT); text.format = 8; @@ -2269,7 +2530,7 @@ x_set_name (f, name, explicit) } else { - icon.value = x_encode_text (f->icon_name, coding_system, + icon.value = x_encode_text (f->icon_name, coding_system, 0, &bytes, &stringp); icon.encoding = (stringp ? XA_STRING : FRAME_X_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT); @@ -2282,20 +2543,27 @@ x_set_name (f, name, explicit) XSetWMIconName (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget), &icon); #else /* not USE_X_TOOLKIT */ +#ifdef USE_GTK + gtk_window_set_title (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), + SDATA (name)); + XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), + &icon); +#else /* not USE_GTK */ XSetWMName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &text); XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &icon); +#endif /* not USE_GTK */ #endif /* not USE_X_TOOLKIT */ if (!NILP (f->icon_name) - && icon.value != XSTRING (f->icon_name)->data) + && icon.value != (unsigned char *) SDATA (f->icon_name)) xfree (icon.value); - if (text.value != XSTRING (name)->data) + if (text.value != (unsigned char *) SDATA (name)) xfree (text.value); } #else /* not HAVE_X11R4 */ XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), - XSTRING (name)->data); + SDATA (name)); XStoreName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), - XSTRING (name)->data); + SDATA (name)); #endif /* not HAVE_X11R4 */ UNBLOCK_INPUT; } @@ -2350,7 +2618,7 @@ x_set_title (f, name, old_name) if (NILP (name)) name = f->name; else - CHECK_STRING (name, 0); + CHECK_STRING (name); if (FRAME_X_WINDOW (f)) { @@ -2361,10 +2629,8 @@ x_set_title (f, name, old_name) int bytes, stringp; Lisp_Object coding_system; - coding_system = Vlocale_coding_system; - if (NILP (coding_system)) - coding_system = Qcompound_text; - text.value = x_encode_text (name, coding_system, &bytes, &stringp); + coding_system = Qcompound_text; + text.value = x_encode_text (name, coding_system, 0, &bytes, &stringp); text.encoding = (stringp ? XA_STRING : FRAME_X_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT); text.format = 8; @@ -2376,7 +2642,7 @@ x_set_title (f, name, old_name) } else { - icon.value = x_encode_text (f->icon_name, coding_system, + icon.value = x_encode_text (f->icon_name, coding_system, 0, &bytes, &stringp); icon.encoding = (stringp ? XA_STRING : FRAME_X_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT); @@ -2389,20 +2655,27 @@ x_set_title (f, name, old_name) XSetWMIconName (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget), &icon); #else /* not USE_X_TOOLKIT */ +#ifdef USE_GTK + gtk_window_set_title (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), + SDATA (name)); + XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), + &icon); +#else /* not USE_GTK */ XSetWMName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &text); XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &icon); +#endif /* not USE_GTK */ #endif /* not USE_X_TOOLKIT */ if (!NILP (f->icon_name) - && icon.value != XSTRING (f->icon_name)->data) + && icon.value != (unsigned char *) SDATA (f->icon_name)) xfree (icon.value); - if (text.value != XSTRING (name)->data) + if (text.value != (unsigned char *) SDATA (name)) xfree (text.value); } #else /* not HAVE_X11R4 */ XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), - XSTRING (name)->data); + SDATA (name)); XStoreName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), - XSTRING (name)->data); + SDATA (name)); #endif /* not HAVE_X11R4 */ UNBLOCK_INPUT; } @@ -2527,10 +2800,10 @@ validate_x_resource_name () if (STRINGP (Vx_resource_name)) { - unsigned char *p = XSTRING (Vx_resource_name)->data; + unsigned char *p = SDATA (Vx_resource_name); int i; - len = STRING_BYTES (XSTRING (Vx_resource_name)); + len = SBYTES (Vx_resource_name); /* Only letters, digits, - and _ are valid in resource names. Count the valid characters and count the invalid ones. */ @@ -2569,12 +2842,12 @@ validate_x_resource_name () for (i = 0; i < len; i++) { - int c = XSTRING (new)->data[i]; + int c = SREF (new, i); if (! ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '-' || c == '_')) - XSTRING (new)->data[i] = '_'; + SSET (new, i, '_'); } } @@ -2582,16 +2855,16 @@ validate_x_resource_name () extern char *x_get_string_resource (); DEFUN ("x-get-resource", Fx_get_resource, Sx_get_resource, 2, 4, 0, - "Return the value of ATTRIBUTE, of class CLASS, from the X defaults database.\n\ -This uses `INSTANCE.ATTRIBUTE' as the key and `Emacs.CLASS' as the\n\ -class, where INSTANCE is the name under which Emacs was invoked, or\n\ -the name specified by the `-name' or `-rn' command-line arguments.\n\ -\n\ -The optional arguments COMPONENT and SUBCLASS add to the key and the\n\ -class, respectively. You must specify both of them or neither.\n\ -If you specify them, the key is `INSTANCE.COMPONENT.ATTRIBUTE'\n\ -and the class is `Emacs.CLASS.SUBCLASS'.") - (attribute, class, component, subclass) + doc: /* Return the value of ATTRIBUTE, of class CLASS, from the X defaults database. +This uses `INSTANCE.ATTRIBUTE' as the key and `Emacs.CLASS' as the +class, where INSTANCE is the name under which Emacs was invoked, or +the name specified by the `-name' or `-rn' command-line arguments. + +The optional arguments COMPONENT and SUBCLASS add to the key and the +class, respectively. You must specify both of them or neither. +If you specify them, the key is `INSTANCE.COMPONENT.ATTRIBUTE' +and the class is `Emacs.CLASS.SUBCLASS'. */) + (attribute, class, component, subclass) Lisp_Object attribute, class, component, subclass; { register char *value; @@ -2600,13 +2873,13 @@ and the class is `Emacs.CLASS.SUBCLASS'.") check_x (); - CHECK_STRING (attribute, 0); - CHECK_STRING (class, 0); + CHECK_STRING (attribute); + CHECK_STRING (class); if (!NILP (component)) - CHECK_STRING (component, 1); + CHECK_STRING (component); if (!NILP (subclass)) - CHECK_STRING (subclass, 2); + CHECK_STRING (subclass); if (NILP (component) != NILP (subclass)) error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither"); @@ -2614,37 +2887,37 @@ and the class is `Emacs.CLASS.SUBCLASS'.") /* Allocate space for the components, the dots which separate them, and the final '\0'. Make them big enough for the worst case. */ - name_key = (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_name)) + name_key = (char *) alloca (SBYTES (Vx_resource_name) + (STRINGP (component) - ? STRING_BYTES (XSTRING (component)) : 0) - + STRING_BYTES (XSTRING (attribute)) + ? SBYTES (component) : 0) + + SBYTES (attribute) + 3); - class_key = (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_class)) - + STRING_BYTES (XSTRING (class)) + class_key = (char *) alloca (SBYTES (Vx_resource_class) + + SBYTES (class) + (STRINGP (subclass) - ? STRING_BYTES (XSTRING (subclass)) : 0) + ? SBYTES (subclass) : 0) + 3); /* Start with emacs.FRAMENAME for the name (the specific one) and with `Emacs' for the class key (the general one). */ - strcpy (name_key, XSTRING (Vx_resource_name)->data); - strcpy (class_key, XSTRING (Vx_resource_class)->data); + strcpy (name_key, SDATA (Vx_resource_name)); + strcpy (class_key, SDATA (Vx_resource_class)); strcat (class_key, "."); - strcat (class_key, XSTRING (class)->data); + strcat (class_key, SDATA (class)); if (!NILP (component)) { strcat (class_key, "."); - strcat (class_key, XSTRING (subclass)->data); + strcat (class_key, SDATA (subclass)); strcat (name_key, "."); - strcat (name_key, XSTRING (component)->data); + strcat (name_key, SDATA (component)); } strcat (name_key, "."); - strcat (name_key, XSTRING (attribute)->data); + strcat (name_key, SDATA (attribute)); value = x_get_string_resource (check_x_display_info (Qnil)->xrdb, name_key, class_key); @@ -2666,13 +2939,13 @@ display_x_get_resource (dpyinfo, attribute, class, component, subclass) char *name_key; char *class_key; - CHECK_STRING (attribute, 0); - CHECK_STRING (class, 0); + CHECK_STRING (attribute); + CHECK_STRING (class); if (!NILP (component)) - CHECK_STRING (component, 1); + CHECK_STRING (component); if (!NILP (subclass)) - CHECK_STRING (subclass, 2); + CHECK_STRING (subclass); if (NILP (component) != NILP (subclass)) error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither"); @@ -2680,37 +2953,37 @@ display_x_get_resource (dpyinfo, attribute, class, component, subclass) /* Allocate space for the components, the dots which separate them, and the final '\0'. Make them big enough for the worst case. */ - name_key = (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_name)) + name_key = (char *) alloca (SBYTES (Vx_resource_name) + (STRINGP (component) - ? STRING_BYTES (XSTRING (component)) : 0) - + STRING_BYTES (XSTRING (attribute)) + ? SBYTES (component) : 0) + + SBYTES (attribute) + 3); - class_key = (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_class)) - + STRING_BYTES (XSTRING (class)) + class_key = (char *) alloca (SBYTES (Vx_resource_class) + + SBYTES (class) + (STRINGP (subclass) - ? STRING_BYTES (XSTRING (subclass)) : 0) + ? SBYTES (subclass) : 0) + 3); /* Start with emacs.FRAMENAME for the name (the specific one) and with `Emacs' for the class key (the general one). */ - strcpy (name_key, XSTRING (Vx_resource_name)->data); - strcpy (class_key, XSTRING (Vx_resource_class)->data); + strcpy (name_key, SDATA (Vx_resource_name)); + strcpy (class_key, SDATA (Vx_resource_class)); strcat (class_key, "."); - strcat (class_key, XSTRING (class)->data); + strcat (class_key, SDATA (class)); if (!NILP (component)) { strcat (class_key, "."); - strcat (class_key, XSTRING (subclass)->data); + strcat (class_key, SDATA (subclass)); strcat (name_key, "."); - strcat (name_key, XSTRING (component)->data); + strcat (name_key, SDATA (component)); } strcat (name_key, "."); - strcat (name_key, XSTRING (attribute)->data); + strcat (name_key, SDATA (attribute)); value = x_get_string_resource (dpyinfo->xrdb, name_key, class_key); @@ -2732,13 +3005,13 @@ x_get_resource_string (attribute, class) /* Allocate space for the components, the dots which separate them, and the final '\0'. */ - name_key = (char *) alloca (STRING_BYTES (XSTRING (Vinvocation_name)) + name_key = (char *) alloca (SBYTES (Vinvocation_name) + strlen (attribute) + 2); class_key = (char *) alloca ((sizeof (EMACS_CLASS) - 1) + strlen (class) + 2); sprintf (name_key, "%s.%s", - XSTRING (Vinvocation_name)->data, + SDATA (Vinvocation_name), attribute); sprintf (class_key, "%s.%s", EMACS_CLASS, class); @@ -2796,15 +3069,15 @@ x_get_arg (dpyinfo, alist, param, attribute, class, type) switch (type) { case RES_TYPE_NUMBER: - return make_number (atoi (XSTRING (tem)->data)); + return make_number (atoi (SDATA (tem))); case RES_TYPE_FLOAT: - return make_float (atof (XSTRING (tem)->data)); + return make_float (atof (SDATA (tem))); case RES_TYPE_BOOLEAN: tem = Fdowncase (tem); - if (!strcmp (XSTRING (tem)->data, "on") - || !strcmp (XSTRING (tem)->data, "true")) + if (!strcmp (SDATA (tem), "on") + || !strcmp (SDATA (tem), "true")) return Qt; else return Qnil; @@ -2818,11 +3091,11 @@ x_get_arg (dpyinfo, alist, param, attribute, class, type) { Lisp_Object lower; lower = Fdowncase (tem); - if (!strcmp (XSTRING (lower)->data, "on") - || !strcmp (XSTRING (lower)->data, "true")) + if (!strcmp (SDATA (lower), "on") + || !strcmp (SDATA (lower), "true")) return Qt; - else if (!strcmp (XSTRING (lower)->data, "off") - || !strcmp (XSTRING (lower)->data, "false")) + else if (!strcmp (SDATA (lower), "off") + || !strcmp (SDATA (lower), "false")) return Qnil; else return Fintern (tem, Qnil); @@ -2913,9 +3186,9 @@ x_default_scroll_bar_color_parameter (f, alist, prop, xprop, xclass, build_string (foreground_p ? "foreground" : "background"), - build_string (""), + empty_string, build_string ("verticalScrollBar"), - build_string ("")); + empty_string); if (!STRINGP (tem)) { /* If nothing has been specified, scroll bars will use a @@ -2940,12 +3213,12 @@ x_default_scroll_bar_color_parameter (f, alist, prop, xprop, xclass, DEFUN ("x-parse-geometry", Fx_parse_geometry, Sx_parse_geometry, 1, 1, 0, - "Parse an X-style geometry string STRING.\n\ -Returns an alist of the form ((top . TOP), (left . LEFT) ... ).\n\ -The properties returned may include `top', `left', `height', and `width'.\n\ -The value of `left' or `top' may be an integer,\n\ -or a list (+ N) meaning N pixels relative to top/left corner,\n\ -or a list (- N) meaning -N pixels relative to bottom/right corner.") + doc: /* Parse an X-style geometry string STRING. +Returns an alist of the form ((top . TOP), (left . LEFT) ... ). +The properties returned may include `top', `left', `height', and `width'. +The value of `left' or `top' may be an integer, +or a list (+ N) meaning N pixels relative to top/left corner, +or a list (- N) meaning -N pixels relative to bottom/right corner. */) (string) Lisp_Object string; { @@ -2953,9 +3226,9 @@ or a list (- N) meaning -N pixels relative to bottom/right corner.") unsigned int width, height; Lisp_Object result; - CHECK_STRING (string, 0); + CHECK_STRING (string); - geometry = XParseGeometry ((char *) XSTRING (string)->data, + geometry = XParseGeometry ((char *) SDATA (string), &x, &y, &width, &height); #if 0 @@ -3032,12 +3305,12 @@ x_figure_window_size (f, parms) { if (!EQ (tem0, Qunbound)) { - CHECK_NUMBER (tem0, 0); + CHECK_NUMBER (tem0); f->height = XINT (tem0); } if (!EQ (tem1, Qunbound)) { - CHECK_NUMBER (tem1, 0); + CHECK_NUMBER (tem1); SET_FRAME_WIDTH (f, XINT (tem1)); } if (!NILP (tem2) && !EQ (tem2, Qunbound)) @@ -3050,8 +3323,9 @@ x_figure_window_size (f, parms) = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f) ? 0 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font))); - f->output_data.x->flags_areas_extra - = FRAME_FLAGS_AREA_WIDTH (f); + + x_compute_fringe_widths (f, 0); + f->output_data.x->pixel_width = CHAR_TO_PIXEL_WIDTH (f, f->width); f->output_data.x->pixel_height = CHAR_TO_PIXEL_HEIGHT (f, f->height); @@ -3082,7 +3356,7 @@ x_figure_window_size (f, parms) f->output_data.x->top_pos = 0; else { - CHECK_NUMBER (tem0, 0); + CHECK_NUMBER (tem0); f->output_data.x->top_pos = XINT (tem0); if (f->output_data.x->top_pos < 0) window_prompting |= YNegative; @@ -3110,7 +3384,7 @@ x_figure_window_size (f, parms) f->output_data.x->left_pos = 0; else { - CHECK_NUMBER (tem1, 0); + CHECK_NUMBER (tem1); f->output_data.x->left_pos = XINT (tem1); if (f->output_data.x->left_pos < 0) window_prompting |= XNegative; @@ -3122,6 +3396,22 @@ x_figure_window_size (f, parms) window_prompting |= PPosition; } + if (f->output_data.x->want_fullscreen != FULLSCREEN_NONE) + { + int left, top; + int width, height; + + /* It takes both for some WM:s to place it where we want */ + window_prompting = USPosition | PPosition; + x_fullscreen_adjust (f, &width, &height, &top, &left); + f->width = width; + f->height = height; + f->output_data.x->pixel_width = CHAR_TO_PIXEL_WIDTH (f, f->width); + f->output_data.x->pixel_height = CHAR_TO_PIXEL_HEIGHT (f, f->height); + f->output_data.x->left_pos = left; + f->output_data.x->top_pos = top; + } + return window_prompting; } @@ -3311,7 +3601,7 @@ create_frame_xic (f) { /* Determine the base fontname from the ASCII font name of FONTSET. */ - char *ascii_font = (char *) XSTRING (fontset_ascii (fontset))->data; + char *ascii_font = (char *) SDATA (fontset_ascii (fontset)); char *p = ascii_font; int i; @@ -3466,7 +3756,9 @@ xic_set_statusarea (f) area.height = needed->height; area.x = PIXEL_WIDTH (f) - area.width - FRAME_INTERNAL_BORDER_WIDTH (f); area.y = (PIXEL_HEIGHT (f) - area.height - - FRAME_MENUBAR_HEIGHT (f) - FRAME_INTERNAL_BORDER_WIDTH (f)); + - FRAME_MENUBAR_HEIGHT (f) + - FRAME_TOOLBAR_HEIGHT (f) + - FRAME_INTERNAL_BORDER_WIDTH (f)); XFree (needed); attr = XVaCreateNestedList (0, XNArea, &area, NULL); @@ -3532,7 +3824,7 @@ x_window (f, window_prompting, minibuffer_only) Elsewhere we specify the window name for the window manager. */ { - char *str = (char *) XSTRING (Vx_resource_name)->data; + char *str = (char *) SDATA (Vx_resource_name); f->namebuf = (char *) xmalloc (strlen (str) + 1); strcpy (f->namebuf, str); } @@ -3665,8 +3957,8 @@ x_window (f, window_prompting, minibuffer_only) validate_x_resource_name (); - class_hints.res_name = (char *) XSTRING (Vx_resource_name)->data; - class_hints.res_class = (char *) XSTRING (Vx_resource_class)->data; + class_hints.res_name = (char *) SDATA (Vx_resource_name); + class_hints.res_class = (char *) SDATA (Vx_resource_class); XSetClassHint (FRAME_X_DISPLAY (f), XtWindow (shell_widget), &class_hints); #ifdef HAVE_X_I18N @@ -3740,7 +4032,16 @@ x_window (f, window_prompting, minibuffer_only) } #else /* not USE_X_TOOLKIT */ +#ifdef USE_GTK +void +x_window (f) + FRAME_PTR f; +{ + if (! xg_create_frame_widgets (f)) + error ("Unable to create window"); +} +#else /*! USE_GTK */ /* Create and set up the X window for frame F. */ void @@ -3793,8 +4094,8 @@ x_window (f) validate_x_resource_name (); - class_hints.res_name = (char *) XSTRING (Vx_resource_name)->data; - class_hints.res_class = (char *) XSTRING (Vx_resource_class)->data; + class_hints.res_name = (char *) SDATA (Vx_resource_name); + class_hints.res_class = (char *) SDATA (Vx_resource_class); XSetClassHint (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &class_hints); /* The menubar is part of the ordinary display; @@ -3843,6 +4144,7 @@ x_window (f) error ("Unable to create window"); } +#endif /* not USE_GTK */ #endif /* not USE_X_TOOLKIT */ /* Handle the icon stuff for this window. Perhaps later we might @@ -3863,8 +4165,8 @@ x_icon (f, parms) icon_y = x_get_and_record_arg (f, parms, Qicon_top, 0, 0, RES_TYPE_NUMBER); if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound)) { - CHECK_NUMBER (icon_x, 0); - CHECK_NUMBER (icon_y, 0); + CHECK_NUMBER (icon_x); + CHECK_NUMBER (icon_y); } else if (!EQ (icon_x, Qunbound) || !EQ (icon_y, Qunbound)) error ("Both left and top icon corners of icon must be specified"); @@ -3881,9 +4183,9 @@ x_icon (f, parms) ? IconicState : NormalState)); - x_text_icon (f, (char *) XSTRING ((!NILP (f->icon_name) + x_text_icon (f, (char *) SDATA ((!NILP (f->icon_name) ? f->icon_name - : f->name))->data); + : f->name))); UNBLOCK_INPUT; } @@ -3958,8 +4260,7 @@ x_make_gc (f) gray_bits, gray_width, gray_height, f->output_data.x->foreground_pixel, f->output_data.x->background_pixel, - DefaultDepth (FRAME_X_DISPLAY (f), - XScreenNumberOfScreen (FRAME_X_SCREEN (f))))); + DefaultDepth (FRAME_X_DISPLAY (f), FRAME_X_SCREEN_NUMBER (f)))); UNBLOCK_INPUT; } @@ -4034,16 +4335,16 @@ unwind_create_frame (frame) DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame, 1, 1, 0, - "Make a new X window, which is called a \"frame\" in Emacs terms.\n\ -Returns an Emacs frame object.\n\ -ALIST is an alist of frame parameters.\n\ -If the parameters specify that the frame should not have a minibuffer,\n\ -and do not specify a specific minibuffer window to use,\n\ -then `default-minibuffer-frame' must be a frame whose minibuffer can\n\ -be shared by the new frame.\n\ -\n\ -This function is an internal primitive--use `make-frame' instead.") - (parms) + doc: /* Make a new X window, which is called a "frame" in Emacs terms. +Returns an Emacs frame object. +ALIST is an alist of frame parameters. +If the parameters specify that the frame should not have a minibuffer, +and do not specify a specific minibuffer window to use, +then `default-minibuffer-frame' must be a frame whose minibuffer can +be shared by the new frame. + +This function is an internal primitive--use `make-frame' instead. */) + (parms) Lisp_Object parms; { struct frame *f; @@ -4052,7 +4353,7 @@ This function is an internal primitive--use `make-frame' instead.") int minibuffer_only = 0; long window_prompting = 0; int width, height; - int count = BINDING_STACK_SIZE (); + int count = SPECPDL_INDEX (); struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; Lisp_Object display; struct x_display_info *dpyinfo = NULL; @@ -4089,7 +4390,7 @@ This function is an internal primitive--use `make-frame' instead.") if (EQ (parent, Qunbound)) parent = Qnil; if (! NILP (parent)) - CHECK_NUMBER (parent, 0); + CHECK_NUMBER (parent); /* make_frame_without_minibuffer can run Lisp code and garbage collect. */ /* No need to protect DISPLAY because that's not used after passing @@ -4122,6 +4423,10 @@ This function is an internal primitive--use `make-frame' instead.") f->output_data.x->fontset = -1; f->output_data.x->scroll_bar_foreground_pixel = -1; f->output_data.x->scroll_bar_background_pixel = -1; +#ifdef USE_TOOLKIT_SCROLL_BARS + f->output_data.x->scroll_bar_top_shadow_pixel = -1; + f->output_data.x->scroll_bar_bottom_shadow_pixel = -1; +#endif /* USE_TOOLKIT_SCROLL_BARS */ record_unwind_protect (unwind_create_frame, frame); f->icon_name @@ -4144,6 +4449,16 @@ This function is an internal primitive--use `make-frame' instead.") { Lisp_Object black; struct gcpro gcpro1; + + /* Function x_decode_color can signal an error. Make + sure to initialize color slots so that we won't try + to free colors we haven't allocated. */ + f->output_data.x->foreground_pixel = -1; + f->output_data.x->background_pixel = -1; + f->output_data.x->cursor_pixel = -1; + f->output_data.x->cursor_foreground_pixel = -1; + f->output_data.x->border_pixel = -1; + f->output_data.x->mouse_pixel = -1; black = build_string ("black"); GCPRO1 (black); @@ -4203,9 +4518,9 @@ This function is an internal primitive--use `make-frame' instead.") { tem = Fquery_fontset (font, Qnil); if (STRINGP (tem)) - font = x_new_fontset (f, XSTRING (tem)->data); + font = x_new_fontset (f, SDATA (tem)); else - font = x_new_font (f, XSTRING (font)->data); + font = x_new_font (f, SDATA (font)); } /* Try out a font which we hope has bold and italic variations. */ @@ -4239,7 +4554,7 @@ This function is an internal primitive--use `make-frame' instead.") x_default_parameter (f, parms, Qborder_width, make_number (2), "borderWidth", "BorderWidth", RES_TYPE_NUMBER); - /* This defaults to 2 in order to match xterm. We recognize either + /* This defaults to 1 in order to match xterm. We recognize either internalBorderWidth or internalBorder (which is what xterm calls it). */ if (NILP (Fassq (Qinternal_border_width, parms))) @@ -4274,6 +4589,10 @@ This function is an internal primitive--use `make-frame' instead.") "screenGamma", "ScreenGamma", RES_TYPE_FLOAT); x_default_parameter (f, parms, Qline_spacing, Qnil, "lineSpacing", "LineSpacing", RES_TYPE_NUMBER); + x_default_parameter (f, parms, Qleft_fringe, Qnil, + "leftFringe", "LeftFringe", RES_TYPE_NUMBER); + x_default_parameter (f, parms, Qright_fringe, Qnil, + "rightFringe", "RightFringe", RES_TYPE_NUMBER); x_default_scroll_bar_color_parameter (f, parms, Qscroll_bar_foreground, "scrollBarForeground", @@ -4299,8 +4618,42 @@ This function is an internal primitive--use `make-frame' instead.") RES_TYPE_SYMBOL); x_default_parameter (f, parms, Qtitle, Qnil, "title", "Title", RES_TYPE_STRING); + x_default_parameter (f, parms, Qwait_for_wm, Qt, + "waitForWM", "WaitForWM", RES_TYPE_BOOLEAN); + x_default_parameter (f, parms, Qfullscreen, Qnil, + "fullscreen", "Fullscreen", RES_TYPE_SYMBOL); f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window; + + /* Add the tool-bar height to the initial frame height so that the + user gets a text display area of the size he specified with -g or + via .Xdefaults. Later changes of the tool-bar height don't + change the frame size. This is done so that users can create + tall Emacs frames without having to guess how tall the tool-bar + will get. */ + if (FRAME_TOOL_BAR_LINES (f)) + { + int margin, relief, bar_height; + + relief = (tool_bar_button_relief >= 0 + ? tool_bar_button_relief + : DEFAULT_TOOL_BAR_BUTTON_RELIEF); + + if (INTEGERP (Vtool_bar_button_margin) + && XINT (Vtool_bar_button_margin) > 0) + margin = XFASTINT (Vtool_bar_button_margin); + else if (CONSP (Vtool_bar_button_margin) + && INTEGERP (XCDR (Vtool_bar_button_margin)) + && XINT (XCDR (Vtool_bar_button_margin)) > 0) + margin = XFASTINT (XCDR (Vtool_bar_button_margin)); + else + margin = 0; + + bar_height = DEFAULT_TOOL_BAR_IMAGE_HEIGHT + 2 * margin + 2 * relief; + f->height += (bar_height + CANON_Y_UNIT (f) - 1) / CANON_Y_UNIT (f); + } + + /* Compute the size of the X window. */ window_prompting = x_figure_window_size (f, parms); if (window_prompting & XNegative) @@ -4358,34 +4711,6 @@ This function is an internal primitive--use `make-frame' instead.") width = f->width; height = f->height; - /* Add the tool-bar height to the initial frame height so that the - user gets a text display area of the size he specified with -g or - via .Xdefaults. Later changes of the tool-bar height don't - change the frame size. This is done so that users can create - tall Emacs frames without having to guess how tall the tool-bar - will get. */ - if (FRAME_TOOL_BAR_LINES (f)) - { - int margin, relief, bar_height; - - relief = (tool_bar_button_relief > 0 - ? tool_bar_button_relief - : DEFAULT_TOOL_BAR_BUTTON_RELIEF); - - if (INTEGERP (Vtool_bar_button_margin) - && XINT (Vtool_bar_button_margin) > 0) - margin = XFASTINT (Vtool_bar_button_margin); - else if (CONSP (Vtool_bar_button_margin) - && INTEGERP (XCDR (Vtool_bar_button_margin)) - && XINT (XCDR (Vtool_bar_button_margin)) > 0) - margin = XFASTINT (XCDR (Vtool_bar_button_margin)); - else - margin = 0; - - bar_height = DEFAULT_TOOL_BAR_IMAGE_HEIGHT + 2 * margin + 2 * relief; - height += (bar_height + CANON_Y_UNIT (f) - 1) / CANON_Y_UNIT (f); - } - f->height = 0; SET_FRAME_WIDTH (f, 0); change_frame_size (f, height, width, 1, 0, 0); @@ -4397,7 +4722,7 @@ This function is an internal primitive--use `make-frame' instead.") new frames. */ call1 (Qface_set_after_frame_default, frame); -#ifdef USE_X_TOOLKIT +#if defined (USE_X_TOOLKIT) || defined (USE_GTK) /* Create the menu bar. */ if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f)) { @@ -4405,13 +4730,15 @@ This function is an internal primitive--use `make-frame' instead.") frame and we didn't make it visible. */ initialize_frame_menubar (f); +#ifndef USE_GTK /* This is a no-op, except under Motif where it arranges the main window for the widgets on it. */ lw_set_main_areas (f->output_data.x->column_widget, f->output_data.x->menubar_widget, f->output_data.x->edit_widget); +#endif /* not USE_GTK */ } -#endif /* USE_X_TOOLKIT */ +#endif /* USE_X_TOOLKIT || USE_GTK */ /* Tell the server what size and position, etc, we want, and how badly we want them. This should be done after we have the menu @@ -4442,6 +4769,11 @@ This function is an internal primitive--use `make-frame' instead.") } UNGCPRO; + + /* Make sure windows on this frame appear in calls to next-window + and similar functions. */ + Vwindow_list = Qnil; + return unbind_to (count, frame); } @@ -4474,9 +4806,9 @@ x_get_focus_frame (frame) following a user-command. */ DEFUN ("x-focus-frame", Fx_focus_frame, Sx_focus_frame, 1, 1, 0, - "Set the input focus to FRAME.\n\ -FRAME nil means use the selected frame.") - (frame) + doc: /* Set the input focus to FRAME. +FRAME nil means use the selected frame. */) + (frame) Lisp_Object frame; { struct frame *f = check_x_frame (frame); @@ -4495,32 +4827,32 @@ FRAME nil means use the selected frame.") DEFUN ("xw-color-defined-p", Fxw_color_defined_p, Sxw_color_defined_p, 1, 2, 0, - "Internal function called by `color-defined-p', which see.") - (color, frame) + doc: /* Internal function called by `color-defined-p', which see. */) + (color, frame) Lisp_Object color, frame; { XColor foo; FRAME_PTR f = check_x_frame (frame); - CHECK_STRING (color, 1); + CHECK_STRING (color); - if (x_defined_color (f, XSTRING (color)->data, &foo, 0)) + if (x_defined_color (f, SDATA (color), &foo, 0)) return Qt; else return Qnil; } DEFUN ("xw-color-values", Fxw_color_values, Sxw_color_values, 1, 2, 0, - "Internal function called by `color-values', which see.") - (color, frame) + doc: /* Internal function called by `color-values', which see. */) + (color, frame) Lisp_Object color, frame; { XColor foo; FRAME_PTR f = check_x_frame (frame); - CHECK_STRING (color, 1); + CHECK_STRING (color); - if (x_defined_color (f, XSTRING (color)->data, &foo, 0)) + if (x_defined_color (f, SDATA (color), &foo, 0)) { Lisp_Object rgb[3]; @@ -4534,8 +4866,8 @@ DEFUN ("xw-color-values", Fxw_color_values, Sxw_color_values, 1, 2, 0, } DEFUN ("xw-display-color-p", Fxw_display_color_p, Sxw_display_color_p, 0, 1, 0, - "Internal function called by `display-color-p', which see.") - (display) + doc: /* Internal function called by `display-color-p', which see. */) + (display) Lisp_Object display; { struct x_display_info *dpyinfo = check_x_display_info (display); @@ -4557,13 +4889,13 @@ DEFUN ("xw-display-color-p", Fxw_display_color_p, Sxw_display_color_p, 0, 1, 0, } DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p, Sx_display_grayscale_p, - 0, 1, 0, - "Return t if the X display supports shades of gray.\n\ -Note that color displays do support shades of gray.\n\ -The optional argument DISPLAY specifies which display to ask about.\n\ -DISPLAY should be either a frame or a display name (a string).\n\ -If omitted or nil, that stands for the selected frame's display.") - (display) + 0, 1, 0, + doc: /* Return t if the X display supports shades of gray. +Note that color displays do support shades of gray. +The optional argument DISPLAY specifies which display to ask about. +DISPLAY should be either a frame or a display name (a string). +If omitted or nil, that stands for the selected frame's display. */) + (display) Lisp_Object display; { struct x_display_info *dpyinfo = check_x_display_info (display); @@ -4587,12 +4919,12 @@ If omitted or nil, that stands for the selected frame's display.") } DEFUN ("x-display-pixel-width", Fx_display_pixel_width, Sx_display_pixel_width, - 0, 1, 0, - "Returns the width in pixels of the X display DISPLAY.\n\ -The optional argument DISPLAY specifies which display to ask about.\n\ -DISPLAY should be either a frame or a display name (a string).\n\ -If omitted or nil, that stands for the selected frame's display.") - (display) + 0, 1, 0, + doc: /* Returns the width in pixels of the X display DISPLAY. +The optional argument DISPLAY specifies which display to ask about. +DISPLAY should be either a frame or a display name (a string). +If omitted or nil, that stands for the selected frame's display. */) + (display) Lisp_Object display; { struct x_display_info *dpyinfo = check_x_display_info (display); @@ -4601,12 +4933,12 @@ If omitted or nil, that stands for the selected frame's display.") } DEFUN ("x-display-pixel-height", Fx_display_pixel_height, - Sx_display_pixel_height, 0, 1, 0, - "Returns the height in pixels of the X display DISPLAY.\n\ -The optional argument DISPLAY specifies which display to ask about.\n\ -DISPLAY should be either a frame or a display name (a string).\n\ -If omitted or nil, that stands for the selected frame's display.") - (display) + Sx_display_pixel_height, 0, 1, 0, + doc: /* Returns the height in pixels of the X display DISPLAY. +The optional argument DISPLAY specifies which display to ask about. +DISPLAY should be either a frame or a display name (a string). +If omitted or nil, that stands for the selected frame's display. */) + (display) Lisp_Object display; { struct x_display_info *dpyinfo = check_x_display_info (display); @@ -4615,12 +4947,12 @@ If omitted or nil, that stands for the selected frame's display.") } DEFUN ("x-display-planes", Fx_display_planes, Sx_display_planes, - 0, 1, 0, - "Returns the number of bitplanes of the X display DISPLAY.\n\ -The optional argument DISPLAY specifies which display to ask about.\n\ -DISPLAY should be either a frame or a display name (a string).\n\ -If omitted or nil, that stands for the selected frame's display.") - (display) + 0, 1, 0, + doc: /* Returns the number of bitplanes of the X display DISPLAY. +The optional argument DISPLAY specifies which display to ask about. +DISPLAY should be either a frame or a display name (a string). +If omitted or nil, that stands for the selected frame's display. */) + (display) Lisp_Object display; { struct x_display_info *dpyinfo = check_x_display_info (display); @@ -4629,12 +4961,12 @@ If omitted or nil, that stands for the selected frame's display.") } DEFUN ("x-display-color-cells", Fx_display_color_cells, Sx_display_color_cells, - 0, 1, 0, - "Returns the number of color cells of the X display DISPLAY.\n\ -The optional argument DISPLAY specifies which display to ask about.\n\ -DISPLAY should be either a frame or a display name (a string).\n\ -If omitted or nil, that stands for the selected frame's display.") - (display) + 0, 1, 0, + doc: /* Returns the number of color cells of the X display DISPLAY. +The optional argument DISPLAY specifies which display to ask about. +DISPLAY should be either a frame or a display name (a string). +If omitted or nil, that stands for the selected frame's display. */) + (display) Lisp_Object display; { struct x_display_info *dpyinfo = check_x_display_info (display); @@ -4645,12 +4977,12 @@ If omitted or nil, that stands for the selected frame's display.") DEFUN ("x-server-max-request-size", Fx_server_max_request_size, Sx_server_max_request_size, - 0, 1, 0, - "Returns the maximum request size of the X server of display DISPLAY.\n\ -The optional argument DISPLAY specifies which display to ask about.\n\ -DISPLAY should be either a frame or a display name (a string).\n\ -If omitted or nil, that stands for the selected frame's display.") - (display) + 0, 1, 0, + doc: /* Returns the maximum request size of the X server of display DISPLAY. +The optional argument DISPLAY specifies which display to ask about. +DISPLAY should be either a frame or a display name (a string). +If omitted or nil, that stands for the selected frame's display. */) + (display) Lisp_Object display; { struct x_display_info *dpyinfo = check_x_display_info (display); @@ -4659,11 +4991,11 @@ If omitted or nil, that stands for the selected frame's display.") } DEFUN ("x-server-vendor", Fx_server_vendor, Sx_server_vendor, 0, 1, 0, - "Returns the vendor ID string of the X server of display DISPLAY.\n\ -The optional argument DISPLAY specifies which display to ask about.\n\ -DISPLAY should be either a frame or a display name (a string).\n\ -If omitted or nil, that stands for the selected frame's display.") - (display) + doc: /* Returns the vendor ID string of the X server of display DISPLAY. +The optional argument DISPLAY specifies which display to ask about. +DISPLAY should be either a frame or a display name (a string). +If omitted or nil, that stands for the selected frame's display. */) + (display) Lisp_Object display; { struct x_display_info *dpyinfo = check_x_display_info (display); @@ -4674,14 +5006,15 @@ If omitted or nil, that stands for the selected frame's display.") } DEFUN ("x-server-version", Fx_server_version, Sx_server_version, 0, 1, 0, - "Returns the version numbers of the X server of display DISPLAY.\n\ -The value is a list of three integers: the major and minor\n\ -version numbers of the X Protocol in use, and the vendor-specific release\n\ -number. See also the function `x-server-vendor'.\n\n\ -The optional argument DISPLAY specifies which display to ask about.\n\ -DISPLAY should be either a frame or a display name (a string).\n\ -If omitted or nil, that stands for the selected frame's display.") - (display) + doc: /* Returns the version numbers of the X server of display DISPLAY. +The value is a list of three integers: the major and minor +version numbers of the X Protocol in use, and the vendor-specific release +number. See also the function `x-server-vendor'. + +The optional argument DISPLAY specifies which display to ask about. +DISPLAY should be either a frame or a display name (a string). +If omitted or nil, that stands for the selected frame's display. */) + (display) Lisp_Object display; { struct x_display_info *dpyinfo = check_x_display_info (display); @@ -4693,11 +5026,11 @@ If omitted or nil, that stands for the selected frame's display.") } DEFUN ("x-display-screens", Fx_display_screens, Sx_display_screens, 0, 1, 0, - "Returns the number of screens on the X server of display DISPLAY.\n\ -The optional argument DISPLAY specifies which display to ask about.\n\ -DISPLAY should be either a frame or a display name (a string).\n\ -If omitted or nil, that stands for the selected frame's display.") - (display) + doc: /* Return the number of screens on the X server of display DISPLAY. +The optional argument DISPLAY specifies which display to ask about. +DISPLAY should be either a frame or a display name (a string). +If omitted or nil, that stands for the selected frame's display. */) + (display) Lisp_Object display; { struct x_display_info *dpyinfo = check_x_display_info (display); @@ -4706,11 +5039,11 @@ If omitted or nil, that stands for the selected frame's display.") } DEFUN ("x-display-mm-height", Fx_display_mm_height, Sx_display_mm_height, 0, 1, 0, - "Returns the height in millimeters of the X display DISPLAY.\n\ -The optional argument DISPLAY specifies which display to ask about.\n\ -DISPLAY should be either a frame or a display name (a string).\n\ -If omitted or nil, that stands for the selected frame's display.") - (display) + doc: /* Return the height in millimeters of the X display DISPLAY. +The optional argument DISPLAY specifies which display to ask about. +DISPLAY should be either a frame or a display name (a string). +If omitted or nil, that stands for the selected frame's display. */) + (display) Lisp_Object display; { struct x_display_info *dpyinfo = check_x_display_info (display); @@ -4719,11 +5052,11 @@ If omitted or nil, that stands for the selected frame's display.") } DEFUN ("x-display-mm-width", Fx_display_mm_width, Sx_display_mm_width, 0, 1, 0, - "Returns the width in millimeters of the X display DISPLAY.\n\ -The optional argument DISPLAY specifies which display to ask about.\n\ -DISPLAY should be either a frame or a display name (a string).\n\ -If omitted or nil, that stands for the selected frame's display.") - (display) + doc: /* Return the width in millimeters of the X display DISPLAY. +The optional argument DISPLAY specifies which display to ask about. +DISPLAY should be either a frame or a display name (a string). +If omitted or nil, that stands for the selected frame's display. */) + (display) Lisp_Object display; { struct x_display_info *dpyinfo = check_x_display_info (display); @@ -4732,13 +5065,13 @@ If omitted or nil, that stands for the selected frame's display.") } DEFUN ("x-display-backing-store", Fx_display_backing_store, - Sx_display_backing_store, 0, 1, 0, - "Returns an indication of whether X display DISPLAY does backing store.\n\ -The value may be `always', `when-mapped', or `not-useful'.\n\ -The optional argument DISPLAY specifies which display to ask about.\n\ -DISPLAY should be either a frame or a display name (a string).\n\ -If omitted or nil, that stands for the selected frame's display.") - (display) + Sx_display_backing_store, 0, 1, 0, + doc: /* Returns an indication of whether X display DISPLAY does backing store. +The value may be `always', `when-mapped', or `not-useful'. +The optional argument DISPLAY specifies which display to ask about. +DISPLAY should be either a frame or a display name (a string). +If omitted or nil, that stands for the selected frame's display. */) + (display) Lisp_Object display; { struct x_display_info *dpyinfo = check_x_display_info (display); @@ -4767,14 +5100,15 @@ If omitted or nil, that stands for the selected frame's display.") } DEFUN ("x-display-visual-class", Fx_display_visual_class, - Sx_display_visual_class, 0, 1, 0, - "Returns the visual class of the X display DISPLAY.\n\ -The value is one of the symbols `static-gray', `gray-scale',\n\ -`static-color', `pseudo-color', `true-color', or `direct-color'.\n\n\ -The optional argument DISPLAY specifies which display to ask about.\n\ -DISPLAY should be either a frame or a display name (a string).\n\ -If omitted or nil, that stands for the selected frame's display.") - (display) + Sx_display_visual_class, 0, 1, 0, + doc: /* Return the visual class of the X display DISPLAY. +The value is one of the symbols `static-gray', `gray-scale', +`static-color', `pseudo-color', `true-color', or `direct-color'. + +The optional argument DISPLAY specifies which display to ask about. +DISPLAY should be either a frame or a display name (a string). +If omitted or nil, that stands for the selected frame's display. */) + (display) Lisp_Object display; { struct x_display_info *dpyinfo = check_x_display_info (display); @@ -4809,12 +5143,12 @@ If omitted or nil, that stands for the selected frame's display.") } DEFUN ("x-display-save-under", Fx_display_save_under, - Sx_display_save_under, 0, 1, 0, - "Returns t if the X display DISPLAY supports the save-under feature.\n\ -The optional argument DISPLAY specifies which display to ask about.\n\ -DISPLAY should be either a frame or a display name (a string).\n\ -If omitted or nil, that stands for the selected frame's display.") - (display) + Sx_display_save_under, 0, 1, 0, + doc: /* Returns t if the X display DISPLAY supports the save-under feature. +The optional argument DISPLAY specifies which display to ask about. +DISPLAY should be either a frame or a display name (a string). +If omitted or nil, that stands for the selected frame's display. */) + (display) Lisp_Object display; { struct x_display_info *dpyinfo = check_x_display_info (display); @@ -4882,7 +5216,7 @@ visual_classes[] = {"PseudoColor", PseudoColor}, {"TrueColor", TrueColor}, {"DirectColor", DirectColor}, - NULL + {NULL, 0} }; @@ -4899,7 +5233,7 @@ XScreenNumberOfScreen (scr) int i; for (i = 0; i < dpy->nscreens; ++i) - if (scr == dpy->screens[i]) + if (scr == dpy->screens + i) break; return i; @@ -4929,12 +5263,12 @@ select_visual (dpyinfo) /* VALUE should be of the form CLASS-DEPTH, where CLASS is one of `PseudoColor', `TrueColor' etc. and DEPTH is the color depth, a decimal number. NAME is compared with case ignored. */ - char *s = (char *) alloca (STRING_BYTES (XSTRING (value)) + 1); + char *s = (char *) alloca (SBYTES (value) + 1); char *dash; int i, class = -1; XVisualInfo vinfo; - strcpy (s, XSTRING (value)->data); + strcpy (s, SDATA (value)); dash = index (s, '-'); if (dash) { @@ -4958,7 +5292,7 @@ select_visual (dpyinfo) if (class == -1 || !XMatchVisualInfo (dpy, XScreenNumberOfScreen (screen), dpyinfo->n_planes, class, &vinfo)) - fatal ("Invalid visual specification `%s'", XSTRING (value)->data); + fatal ("Invalid visual specification `%s'", SDATA (value)); dpyinfo->visual = vinfo.visual; } @@ -4996,7 +5330,7 @@ x_display_info_for_name (name) Lisp_Object names; struct x_display_info *dpyinfo; - CHECK_STRING (name, 0); + CHECK_STRING (name); if (! EQ (Vwindow_system, intern ("x"))) error ("Not using X Windows"); @@ -5017,10 +5351,10 @@ x_display_info_for_name (name) validate_x_resource_name (); dpyinfo = x_term_init (name, (char *)0, - (char *) XSTRING (Vx_resource_name)->data); + (char *) SDATA (Vx_resource_name)); if (dpyinfo == 0) - error ("Cannot connect to X server %s", XSTRING (name)->data); + error ("Cannot connect to X server %s", SDATA (name)); x_in_use = 1; XSETFASTINT (Vwindow_system_version, 11); @@ -5030,26 +5364,27 @@ x_display_info_for_name (name) DEFUN ("x-open-connection", Fx_open_connection, Sx_open_connection, - 1, 3, 0, "Open a connection to an X server.\n\ -DISPLAY is the name of the display to connect to.\n\ -Optional second arg XRM-STRING is a string of resources in xrdb format.\n\ -If the optional third arg MUST-SUCCEED is non-nil,\n\ -terminate Emacs if we can't open the connection.") - (display, xrm_string, must_succeed) + 1, 3, 0, + doc: /* Open a connection to an X server. +DISPLAY is the name of the display to connect to. +Optional second arg XRM-STRING is a string of resources in xrdb format. +If the optional third arg MUST-SUCCEED is non-nil, +terminate Emacs if we can't open the connection. */) + (display, xrm_string, must_succeed) Lisp_Object display, xrm_string, must_succeed; { unsigned char *xrm_option; struct x_display_info *dpyinfo; - CHECK_STRING (display, 0); + CHECK_STRING (display); if (! NILP (xrm_string)) - CHECK_STRING (xrm_string, 1); + CHECK_STRING (xrm_string); if (! EQ (Vwindow_system, intern ("x"))) error ("Not using X Windows"); if (! NILP (xrm_string)) - xrm_option = (unsigned char *) XSTRING (xrm_string)->data; + xrm_option = (unsigned char *) SDATA (xrm_string); else xrm_option = (unsigned char *) 0; @@ -5058,18 +5393,19 @@ terminate Emacs if we can't open the connection.") /* This is what opens the connection and sets x_current_display. This also initializes many symbols, such as those used for input. */ dpyinfo = x_term_init (display, xrm_option, - (char *) XSTRING (Vx_resource_name)->data); + (char *) SDATA (Vx_resource_name)); if (dpyinfo == 0) { if (!NILP (must_succeed)) fatal ("Cannot connect to X server %s.\n\ Check the DISPLAY environment variable or use `-d'.\n\ -Also use the `xhost' program to verify that it is set to permit\n\ -connections from your machine.\n", - XSTRING (display)->data); +Also use the `xauth' program to verify that you have the proper\n\ +authorization information needed to connect the X server.\n\ +An insecure way to solve the problem may be to use `xhost'.\n", + SDATA (display)); else - error ("Cannot connect to X server %s", XSTRING (display)->data); + error ("Cannot connect to X server %s", SDATA (display)); } x_in_use = 1; @@ -5080,11 +5416,11 @@ connections from your machine.\n", DEFUN ("x-close-connection", Fx_close_connection, Sx_close_connection, 1, 1, 0, - "Close the connection to DISPLAY's X server.\n\ -For DISPLAY, specify either a frame or a display name (a string).\n\ -If DISPLAY is nil, that stands for the selected frame's display.") - (display) - Lisp_Object display; + doc: /* Close the connection to DISPLAY's X server. +For DISPLAY, specify either a frame or a display name (a string). +If DISPLAY is nil, that stands for the selected frame's display. */) + (display) + Lisp_Object display; { struct x_display_info *dpyinfo = check_x_display_info (display); int i; @@ -5119,8 +5455,8 @@ If DISPLAY is nil, that stands for the selected frame's display.") } DEFUN ("x-display-list", Fx_display_list, Sx_display_list, 0, 0, 0, - "Return the list of display names that Emacs has connections to.") - () + doc: /* Return the list of display names that Emacs has connections to. */) + () { Lisp_Object tail, result; @@ -5132,15 +5468,15 @@ DEFUN ("x-display-list", Fx_display_list, Sx_display_list, 0, 0, 0, } DEFUN ("x-synchronize", Fx_synchronize, Sx_synchronize, 1, 2, 0, - "If ON is non-nil, report X errors as soon as the erring request is made.\n\ -If ON is nil, allow buffering of requests.\n\ -Turning on synchronization prohibits the Xlib routines from buffering\n\ -requests and seriously degrades performance, but makes debugging much\n\ -easier.\n\ -The optional second argument DISPLAY specifies which display to act on.\n\ -DISPLAY should be either a frame or a display name (a string).\n\ -If DISPLAY is omitted or nil, that stands for the selected frame's display.") - (on, display) + doc: /* If ON is non-nil, report X errors as soon as the erring request is made. +If ON is nil, allow buffering of requests. +Turning on synchronization prohibits the Xlib routines from buffering +requests and seriously degrades performance, but makes debugging much +easier. +The optional second argument DISPLAY specifies which display to act on. +DISPLAY should be either a frame or a display name (a string). +If DISPLAY is omitted or nil, that stands for the selected frame's display. */) + (on, display) Lisp_Object display, on; { struct x_display_info *dpyinfo = check_x_display_info (display); @@ -5187,8 +5523,8 @@ Lisp_Object Qxbm; /* Keywords. */ extern Lisp_Object QCwidth, QCheight, QCforeground, QCbackground, QCfile; -extern Lisp_Object QCdata; -Lisp_Object QCtype, QCascent, QCmargin, QCrelief; +extern Lisp_Object QCdata, QCtype; +Lisp_Object QCascent, QCmargin, QCrelief; Lisp_Object QCconversion, QCcolor_symbols, QCheuristic_mask; Lisp_Object QCindex, QCmatrix, QCcolor_adjustment, QCmask; @@ -5261,11 +5597,22 @@ valid_image_p (object) if (CONSP (object) && EQ (XCAR (object), Qimage)) { - Lisp_Object symbol = Fplist_get (XCDR (object), QCtype); - struct image_type *type = lookup_image_type (symbol); - - if (type) - valid_p = type->valid_p (object); + Lisp_Object tem; + + for (tem = XCDR (object); CONSP (tem); tem = XCDR (tem)) + if (EQ (XCAR (tem), QCtype)) + { + tem = XCDR (tem); + if (CONSP (tem) && SYMBOLP (XCAR (tem))) + { + struct image_type *type; + type = lookup_image_type (XCAR (tem)); + if (type) + valid_p = type->valid_p (object); + } + + break; + } } return valid_p; @@ -5296,6 +5643,7 @@ enum image_value_type { IMAGE_DONT_CHECK_VALUE_TYPE, IMAGE_STRING_VALUE, + IMAGE_STRING_OR_NIL_VALUE, IMAGE_SYMBOL_VALUE, IMAGE_POSITIVE_INTEGER_VALUE, IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, @@ -5371,7 +5719,7 @@ parse_image_spec (spec, keywords, nkeywords, type) /* Find key in KEYWORDS. Error if not found. */ for (i = 0; i < nkeywords; ++i) - if (strcmp (keywords[i].name, XSYMBOL (key)->name->data) == 0) + if (strcmp (keywords[i].name, SDATA (SYMBOL_NAME (key))) == 0) break; if (i == nkeywords) @@ -5393,6 +5741,11 @@ parse_image_spec (spec, keywords, nkeywords, type) return 0; break; + case IMAGE_STRING_OR_NIL_VALUE: + if (!STRINGP (value) && !NILP (value)) + return 0; + break; + case IMAGE_SYMBOL_VALUE: if (!SYMBOLP (value)) return 0; @@ -5502,12 +5855,12 @@ image_spec_value (spec, key, found) DEFUN ("image-size", Fimage_size, Simage_size, 1, 3, 0, - "Return the size of image SPEC as pair (WIDTH . HEIGHT).\n\ -PIXELS non-nil means return the size in pixels, otherwise return the\n\ -size in canonical character units.\n\ -FRAME is the frame on which the image will be displayed. FRAME nil\n\ -or omitted means use the selected frame.") - (spec, pixels, frame) + doc: /* Return the size of image SPEC as pair (WIDTH . HEIGHT). +PIXELS non-nil means return the size in pixels, otherwise return the +size in canonical character units. +FRAME is the frame on which the image will be displayed. FRAME nil +or omitted means use the selected frame. */) + (spec, pixels, frame) Lisp_Object spec, pixels, frame; { Lisp_Object size; @@ -5535,10 +5888,10 @@ or omitted means use the selected frame.") DEFUN ("image-mask-p", Fimage_mask_p, Simage_mask_p, 1, 2, 0, - "Return t if image SPEC has a mask bitmap.\n\ -FRAME is the frame on which the image will be displayed. FRAME nil\n\ -or omitted means use the selected frame.") - (spec, frame) + doc: /* Return t if image SPEC has a mask bitmap. +FRAME is the frame on which the image will be displayed. FRAME nil +or omitted means use the selected frame. */) + (spec, frame) Lisp_Object spec, frame; { Lisp_Object mask; @@ -5648,28 +6001,126 @@ image_ascent (img, face) struct image *img; struct face *face; { - int height = img->height + img->vmargin; - int ascent; - - if (img->ascent == CENTERED_IMAGE_ASCENT) + int height = img->height + img->vmargin; + int ascent; + + if (img->ascent == CENTERED_IMAGE_ASCENT) + { + if (face->font) + /* This expression is arranged so that if the image can't be + exactly centered, it will be moved slightly up. This is + because a typical font is `top-heavy' (due to the presence + uppercase letters), so the image placement should err towards + being top-heavy too. It also just generally looks better. */ + ascent = (height + face->font->ascent - face->font->descent + 1) / 2; + else + ascent = height / 2; + } + else + ascent = height * img->ascent / 100.0; + + return ascent; +} + + +/* Image background colors. */ + +static unsigned long +four_corners_best (ximg, width, height) + XImage *ximg; + unsigned long width, height; +{ + unsigned long corners[4], best; + int i, best_count; + + /* Get the colors at the corners of ximg. */ + corners[0] = XGetPixel (ximg, 0, 0); + corners[1] = XGetPixel (ximg, width - 1, 0); + corners[2] = XGetPixel (ximg, width - 1, height - 1); + corners[3] = XGetPixel (ximg, 0, height - 1); + + /* Choose the most frequently found color as background. */ + for (i = best_count = 0; i < 4; ++i) + { + int j, n; + + for (j = n = 0; j < 4; ++j) + if (corners[i] == corners[j]) + ++n; + + if (n > best_count) + best = corners[i], best_count = n; + } + + return best; +} + +/* Return the `background' field of IMG. If IMG doesn't have one yet, + it is guessed heuristically. If non-zero, XIMG is an existing XImage + object to use for the heuristic. */ + +unsigned long +image_background (img, f, ximg) + struct image *img; + struct frame *f; + XImage *ximg; +{ + if (! img->background_valid) + /* IMG doesn't have a background yet, try to guess a reasonable value. */ + { + int free_ximg = !ximg; + + if (! ximg) + ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap, + 0, 0, img->width, img->height, ~0, ZPixmap); + + img->background = four_corners_best (ximg, img->width, img->height); + + if (free_ximg) + XDestroyImage (ximg); + + img->background_valid = 1; + } + + return img->background; +} + +/* Return the `background_transparent' field of IMG. If IMG doesn't + have one yet, it is guessed heuristically. If non-zero, MASK is an + existing XImage object to use for the heuristic. */ + +int +image_background_transparent (img, f, mask) + struct image *img; + struct frame *f; + XImage *mask; +{ + if (! img->background_transparent_valid) + /* IMG doesn't have a background yet, try to guess a reasonable value. */ { - if (face->font) - /* This expression is arranged so that if the image can't be - exactly centered, it will be moved slightly up. This is - because a typical font is `top-heavy' (due to the presence - uppercase letters), so the image placement should err towards - being top-heavy too. It also just generally looks better. */ - ascent = (height + face->font->ascent - face->font->descent + 1) / 2; + if (img->mask) + { + int free_mask = !mask; + + if (! mask) + mask = XGetImage (FRAME_X_DISPLAY (f), img->mask, + 0, 0, img->width, img->height, ~0, ZPixmap); + + img->background_transparent + = !four_corners_best (mask, img->width, img->height); + + if (free_mask) + XDestroyImage (mask); + } else - ascent = height / 2; + img->background_transparent = 0; + + img->background_transparent_valid = 1; } - else - ascent = height * img->ascent / 100.0; - return ascent; + return img->background_transparent; } - /*********************************************************************** Helper functions for X image types @@ -5699,12 +6150,14 @@ x_clear_image_1 (f, img, pixmap_p, mask_p, colors_p) { XFreePixmap (FRAME_X_DISPLAY (f), img->pixmap); img->pixmap = None; + img->background_valid = 0; } if (mask_p && img->mask) { XFreePixmap (FRAME_X_DISPLAY (f), img->mask); img->mask = None; + img->background_transparent_valid = 0; } if (colors_p && img->ncolors) @@ -5746,7 +6199,7 @@ x_alloc_image_color (f, img, color_name, dflt) xassert (STRINGP (color_name)); - if (x_defined_color (f, XSTRING (color_name)->data, &color, 1)) + if (x_defined_color (f, SDATA (color_name), &color, 1)) { /* This isn't called frequently so we get away with simply reallocating the color vector to the needed size, here. */ @@ -5770,6 +6223,7 @@ x_alloc_image_color (f, img, color_name, dflt) ***********************************************************************/ static void cache_image P_ ((struct frame *f, struct image *img)); +static void postprocess_image P_ ((struct frame *, struct image *)); /* Return a new, initialized image cache that is allocated from the @@ -5880,10 +6334,10 @@ clear_image_cache (f, force_p) DEFUN ("clear-image-cache", Fclear_image_cache, Sclear_image_cache, 0, 1, 0, - "Clear the image cache of FRAME.\n\ -FRAME nil or omitted means use the selected frame.\n\ -FRAME t means clear the image caches of all frames.") - (frame) + doc: /* Clear the image cache of FRAME. +FRAME nil or omitted means use the selected frame. +FRAME t means clear the image caches of all frames. */) + (frame) Lisp_Object frame; { if (EQ (frame, Qt)) @@ -5901,6 +6355,81 @@ FRAME t means clear the image caches of all frames.") } +/* Compute masks and transform image IMG on frame F, as specified + by the image's specification, */ + +static void +postprocess_image (f, img) + struct frame *f; + struct image *img; +{ + /* Manipulation of the image's mask. */ + if (img->pixmap) + { + Lisp_Object conversion, spec; + Lisp_Object mask; + + spec = img->spec; + + /* `:heuristic-mask t' + `:mask heuristic' + means build a mask heuristically. + `:heuristic-mask (R G B)' + `:mask (heuristic (R G B))' + means build a mask from color (R G B) in the + image. + `:mask nil' + means remove a mask, if any. */ + + mask = image_spec_value (spec, QCheuristic_mask, NULL); + if (!NILP (mask)) + x_build_heuristic_mask (f, img, mask); + else + { + int found_p; + + mask = image_spec_value (spec, QCmask, &found_p); + + if (EQ (mask, Qheuristic)) + x_build_heuristic_mask (f, img, Qt); + else if (CONSP (mask) + && EQ (XCAR (mask), Qheuristic)) + { + if (CONSP (XCDR (mask))) + x_build_heuristic_mask (f, img, XCAR (XCDR (mask))); + else + x_build_heuristic_mask (f, img, XCDR (mask)); + } + else if (NILP (mask) && found_p && img->mask) + { + XFreePixmap (FRAME_X_DISPLAY (f), img->mask); + img->mask = None; + } + } + + + /* Should we apply an image transformation algorithm? */ + conversion = image_spec_value (spec, QCconversion, NULL); + if (EQ (conversion, Qdisabled)) + x_disable_image (f, img); + else if (EQ (conversion, Qlaplace)) + x_laplace (f, img); + else if (EQ (conversion, Qemboss)) + x_emboss (f, img); + else if (CONSP (conversion) + && EQ (XCAR (conversion), Qedge_detection)) + { + Lisp_Object tem; + tem = XCDR (conversion); + if (CONSP (tem)) + x_edge_detection (f, img, + Fplist_get (tem, QCmatrix), + Fplist_get (tem, QCcolor_adjustment)); + } + } +} + + /* Return the id of image with Lisp specification SPEC on frame F. SPEC must be a valid Lisp image specification (see valid_image_p). */ @@ -5934,6 +6463,8 @@ lookup_image (f, spec) /* If not found, create a new image and cache it. */ if (img == NULL) { + extern Lisp_Object Qpostscript; + BLOCK_INPUT; img = make_image (spec, hash); cache_image (f, img); @@ -5956,8 +6487,9 @@ lookup_image (f, spec) else { /* Handle image type independent image attributes - `:ascent ASCENT', `:margin MARGIN', `:relief RELIEF'. */ - Lisp_Object ascent, margin, relief; + `:ascent ASCENT', `:margin MARGIN', `:relief RELIEF', + `:background COLOR'. */ + Lisp_Object ascent, margin, relief, bg; ascent = image_spec_value (spec, QCascent, NULL); if (INTEGERP (ascent)) @@ -5985,71 +6517,22 @@ lookup_image (f, spec) img->vmargin += abs (img->relief); } - /* Manipulation of the image's mask. */ - if (img->pixmap) - { - /* `:heuristic-mask t' - `:mask heuristic' - means build a mask heuristically. - `:heuristic-mask (R G B)' - `:mask (heuristic (R G B))' - means build a mask from color (R G B) in the - image. - `:mask nil' - means remove a mask, if any. */ - - Lisp_Object mask; - - mask = image_spec_value (spec, QCheuristic_mask, NULL); - if (!NILP (mask)) - x_build_heuristic_mask (f, img, mask); - else - { - int found_p; - - mask = image_spec_value (spec, QCmask, &found_p); - - if (EQ (mask, Qheuristic)) - x_build_heuristic_mask (f, img, Qt); - else if (CONSP (mask) - && EQ (XCAR (mask), Qheuristic)) - { - if (CONSP (XCDR (mask))) - x_build_heuristic_mask (f, img, XCAR (XCDR (mask))); - else - x_build_heuristic_mask (f, img, XCDR (mask)); - } - else if (NILP (mask) && found_p && img->mask) - { - XFreePixmap (FRAME_X_DISPLAY (f), img->mask); - img->mask = None; - } - } - } - - /* Should we apply an image transformation algorithm? */ - if (img->pixmap) + if (! img->background_valid) { - Lisp_Object conversion; - - conversion = image_spec_value (spec, QCconversion, NULL); - if (EQ (conversion, Qdisabled)) - x_disable_image (f, img); - else if (EQ (conversion, Qlaplace)) - x_laplace (f, img); - else if (EQ (conversion, Qemboss)) - x_emboss (f, img); - else if (CONSP (conversion) - && EQ (XCAR (conversion), Qedge_detection)) + bg = image_spec_value (img->spec, QCbackground, NULL); + if (!NILP (bg)) { - Lisp_Object tem; - tem = XCDR (conversion); - if (CONSP (tem)) - x_edge_detection (f, img, - Fplist_get (tem, QCmatrix), - Fplist_get (tem, QCcolor_adjustment)); + img->background + = x_alloc_image_color (f, img, bg, + FRAME_BACKGROUND_PIXEL (f)); + img->background_valid = 1; } } + + /* Do image transformations and compute masks, unless we + don't have the image yet. */ + if (!EQ (*img->type->type, Qpostscript)) + postprocess_image (f, img); } UNBLOCK_INPUT; @@ -6210,6 +6693,7 @@ x_put_x_image (f, ximg, pixmap, width, height) struct frame *f; XImage *ximg; Pixmap pixmap; + int width, height; { GC gc; @@ -6246,7 +6730,7 @@ x_find_image_file (file) GCPRO2 (file_found, search_path); /* Try to find FILE in data-directory, then x-bitmap-file-path. */ - fd = openp (search_path, file, "", &file_found, 0); + fd = openp (search_path, file, Qnil, &file_found, Qnil); if (fd == -1) file_found = Qnil; @@ -6339,8 +6823,8 @@ static struct image_keyword xbm_format[XBM_LAST] = {":width", IMAGE_POSITIVE_INTEGER_VALUE, 0}, {":height", IMAGE_POSITIVE_INTEGER_VALUE, 0}, {":data", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, - {":foreground", IMAGE_STRING_VALUE, 0}, - {":background", IMAGE_STRING_VALUE, 0}, + {":foreground", IMAGE_STRING_OR_NIL_VALUE, 0}, + {":background", IMAGE_STRING_OR_NIL_VALUE, 0}, {":ascent", IMAGE_ASCENT_VALUE, 0}, {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0}, {":relief", IMAGE_INTEGER_VALUE, 0}, @@ -6454,7 +6938,7 @@ xbm_image_p (object) if (STRINGP (elt)) { - if (XSTRING (elt)->size + if (SCHARS (elt) < (width + BITS_PER_CHAR - 1) / BITS_PER_CHAR) return 0; } @@ -6469,7 +6953,7 @@ xbm_image_p (object) } else if (STRINGP (data)) { - if (XSTRING (data)->size + if (SCHARS (data) < (width + BITS_PER_CHAR - 1) / BITS_PER_CHAR * height) return 0; } @@ -6759,10 +7243,13 @@ xbm_load_image (f, img, contents, end) value = image_spec_value (img->spec, QCforeground, NULL); if (!NILP (value)) foreground = x_alloc_image_color (f, img, value, foreground); - value = image_spec_value (img->spec, QCbackground, NULL); if (!NILP (value)) - background = x_alloc_image_color (f, img, value, background); + { + background = x_alloc_image_color (f, img, value, background); + img->background = background; + img->background_valid = 1; + } img->pixmap = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f), @@ -6796,9 +7283,9 @@ xbm_file_p (data) { int w, h; return (STRINGP (data) - && xbm_read_bitmap_data (XSTRING (data)->data, - (XSTRING (data)->data - + STRING_BYTES (XSTRING (data))), + && xbm_read_bitmap_data (SDATA (data), + (SDATA (data) + + SBYTES (data)), &w, &h, NULL)); } @@ -6834,7 +7321,7 @@ xbm_load (f, img) return 0; } - contents = slurp_file (XSTRING (file)->data, &size); + contents = slurp_file (SDATA (file), &size); if (contents == NULL) { image_error ("Error loading XBM image `%s'", img->spec, Qnil); @@ -6874,17 +7361,19 @@ xbm_load (f, img) } /* Get foreground and background colors, maybe allocate colors. */ - if (fmt[XBM_FOREGROUND].count) + if (fmt[XBM_FOREGROUND].count + && STRINGP (fmt[XBM_FOREGROUND].value)) foreground = x_alloc_image_color (f, img, fmt[XBM_FOREGROUND].value, foreground); - if (fmt[XBM_BACKGROUND].count) + if (fmt[XBM_BACKGROUND].count + && STRINGP (fmt[XBM_BACKGROUND].value)) background = x_alloc_image_color (f, img, fmt[XBM_BACKGROUND].value, background); if (in_memory_file_p) - success_p = xbm_load_image (f, img, XSTRING (data)->data, - (XSTRING (data)->data - + STRING_BYTES (XSTRING (data)))); + success_p = xbm_load_image (f, img, SDATA (data), + (SDATA (data) + + SBYTES (data))); else { if (VECTORP (data)) @@ -6898,13 +7387,13 @@ xbm_load (f, img) { Lisp_Object line = XVECTOR (data)->contents[i]; if (STRINGP (line)) - bcopy (XSTRING (line)->data, p, nbytes); + bcopy (SDATA (line), p, nbytes); else bcopy (XBOOL_VECTOR (line)->data, p, nbytes); } } else if (STRINGP (data)) - bits = XSTRING (data)->data; + bits = SDATA (data); else bits = XBOOL_VECTOR (data)->data; @@ -6963,6 +7452,7 @@ enum xpm_keyword_index XPM_HEURISTIC_MASK, XPM_MASK, XPM_COLOR_SYMBOLS, + XPM_BACKGROUND, XPM_LAST }; @@ -6980,7 +7470,8 @@ static struct image_keyword xpm_format[XPM_LAST] = {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, - {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE, 0} + {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, + {":background", IMAGE_STRING_OR_NIL_VALUE, 0} }; /* Structure describing the image type XBM. */ @@ -7304,10 +7795,10 @@ xpm_load (f, img) { Lisp_Object name = XCAR (XCAR (tail)); Lisp_Object color = XCDR (XCAR (tail)); - xpm_syms[i].name = (char *) alloca (XSTRING (name)->size + 1); - strcpy (xpm_syms[i].name, XSTRING (name)->data); - xpm_syms[i].value = (char *) alloca (XSTRING (color)->size + 1); - strcpy (xpm_syms[i].value, XSTRING (color)->data); + xpm_syms[i].name = (char *) alloca (SCHARS (name) + 1); + strcpy (xpm_syms[i].name, SDATA (name)); + xpm_syms[i].value = (char *) alloca (SCHARS (color) + 1); + strcpy (xpm_syms[i].value, SDATA (color)); } } @@ -7328,14 +7819,14 @@ xpm_load (f, img) } rc = XpmReadFileToPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), - XSTRING (file)->data, &img->pixmap, &img->mask, + SDATA (file), &img->pixmap, &img->mask, &attrs); } else { Lisp_Object buffer = image_spec_value (img->spec, QCdata, NULL); rc = XpmCreatePixmapFromBuffer (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), - XSTRING (buffer)->data, + SDATA (buffer), &img->pixmap, &img->mask, &attrs); } @@ -7597,10 +8088,6 @@ colors_in_color_table (n) Algorithms ***********************************************************************/ -static void x_laplace_write_row P_ ((struct frame *, long *, - int, XImage *, int)); -static void x_laplace_read_row P_ ((struct frame *, Colormap, - XColor *, int, XImage *, int)); static XColor *x_to_xcolors P_ ((struct frame *, struct image *, int)); static void x_from_xcolors P_ ((struct frame *, struct image *, XColor *)); static void x_detect_edges P_ ((struct frame *, struct image *, int[9], int)); @@ -7927,13 +8414,14 @@ x_build_heuristic_mask (f, img, how) { Display *dpy = FRAME_X_DISPLAY (f); XImage *ximg, *mask_img; - int x, y, rc, look_at_corners_p; + int x, y, rc, use_img_background; unsigned long bg = 0; if (img->mask) { XFreePixmap (FRAME_X_DISPLAY (f), img->mask); img->mask = None; + img->background_transparent_valid = 0; } /* Create an image and pixmap serving as mask. */ @@ -7947,17 +8435,14 @@ x_build_heuristic_mask (f, img, how) ~0, ZPixmap); /* Determine the background color of ximg. If HOW is `(R G B)' - take that as color. Otherwise, try to determine the color - heuristically. */ - look_at_corners_p = 1; + take that as color. Otherwise, use the image's background color. */ + use_img_background = 1; if (CONSP (how)) { - int rgb[3], i = 0; + int rgb[3], i; - while (i < 3 - && CONSP (how) - && NATNUMP (XCAR (how))) + for (i = 0; i < 3 && CONSP (how) && NATNUMP (XCAR (how)); ++i) { rgb[i] = XFASTINT (XCAR (how)) & 0xffff; how = XCDR (how); @@ -7966,44 +8451,14 @@ x_build_heuristic_mask (f, img, how) if (i == 3 && NILP (how)) { char color_name[30]; - XColor exact, color; - Colormap cmap; - sprintf (color_name, "#%04x%04x%04x", rgb[0], rgb[1], rgb[2]); - - cmap = FRAME_X_COLORMAP (f); - if (XLookupColor (dpy, cmap, color_name, &exact, &color)) - { - bg = color.pixel; - look_at_corners_p = 0; - } + bg = x_alloc_image_color (f, img, build_string (color_name), 0); + use_img_background = 0; } } - if (look_at_corners_p) - { - unsigned long corners[4]; - int i, best_count; - - /* Get the colors at the corners of ximg. */ - corners[0] = XGetPixel (ximg, 0, 0); - corners[1] = XGetPixel (ximg, img->width - 1, 0); - corners[2] = XGetPixel (ximg, img->width - 1, img->height - 1); - corners[3] = XGetPixel (ximg, 0, img->height - 1); - - /* Choose the most frequently found color as background. */ - for (i = best_count = 0; i < 4; ++i) - { - int j, n; - - for (j = n = 0; j < 4; ++j) - if (corners[i] == corners[j]) - ++n; - - if (n > best_count) - bg = corners[i], best_count = n; - } - } + if (use_img_background) + bg = four_corners_best (ximg, img->width, img->height); /* Set all bits in mask_img to 1 whose color in ximg is different from the background color bg. */ @@ -8011,6 +8466,9 @@ x_build_heuristic_mask (f, img, how) for (x = 0; x < img->width; ++x) XPutPixel (mask_img, x, y, XGetPixel (ximg, x, y) != bg); + /* Fill in the background_transparent field while we have the mask handy. */ + image_background_transparent (img, f, mask_img); + /* Put mask_img into img->mask. */ x_put_x_image (f, mask_img, img->mask, img->width, img->height); x_destroy_x_image (mask_img); @@ -8065,8 +8523,8 @@ static struct image_keyword pbm_format[PBM_LAST] = {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, - {":foreground", IMAGE_STRING_VALUE, 0}, - {":background", IMAGE_STRING_VALUE, 0} + {":foreground", IMAGE_STRING_OR_NIL_VALUE, 0}, + {":background", IMAGE_STRING_OR_NIL_VALUE, 0} }; /* Structure describing the image type `pbm'. */ @@ -8168,7 +8626,7 @@ pbm_load (f, img) return 0; } - contents = slurp_file (XSTRING (file)->data, &size); + contents = slurp_file (SDATA (file), &size); if (contents == NULL) { image_error ("Error reading `%s'", file, Qnil); @@ -8183,8 +8641,8 @@ pbm_load (f, img) { Lisp_Object data; data = image_spec_value (img->spec, QCdata, NULL); - p = XSTRING (data)->data; - end = p + STRING_BYTES (XSTRING (data)); + p = SDATA (data); + end = p + SBYTES (data); } /* Check magic number. */ @@ -8264,10 +8722,16 @@ pbm_load (f, img) parse_image_spec (img->spec, fmt, PBM_LAST, Qpbm); /* Get foreground and background colors, maybe allocate colors. */ - if (fmt[PBM_FOREGROUND].count) + if (fmt[PBM_FOREGROUND].count + && STRINGP (fmt[PBM_FOREGROUND].value)) fg = x_alloc_image_color (f, img, fmt[PBM_FOREGROUND].value, fg); - if (fmt[PBM_BACKGROUND].count) - bg = x_alloc_image_color (f, img, fmt[PBM_BACKGROUND].value, bg); + if (fmt[PBM_BACKGROUND].count + && STRINGP (fmt[PBM_BACKGROUND].value)) + { + bg = x_alloc_image_color (f, img, fmt[PBM_BACKGROUND].value, bg); + img->background = bg; + img->background_valid = 1; + } for (y = 0; y < height; ++y) for (x = 0; x < width; ++x) @@ -8330,6 +8794,10 @@ pbm_load (f, img) free the color table. */ img->colors = colors_in_color_table (&img->ncolors); free_color_table (); + + /* Maybe fill in the background field while we have ximg handy. */ + if (NILP (image_spec_value (img->spec, QCbackground, NULL))) + IMAGE_BACKGROUND (img, f, ximg); /* Put the image into a pixmap. */ x_put_x_image (f, ximg, img->pixmap, width, height); @@ -8375,6 +8843,7 @@ enum png_keyword_index PNG_ALGORITHM, PNG_HEURISTIC_MASK, PNG_MASK, + PNG_BACKGROUND, PNG_LAST }; @@ -8391,7 +8860,8 @@ static struct image_keyword png_format[PNG_LAST] = {":relief", IMAGE_INTEGER_VALUE, 0}, {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, - {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0} + {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, + {":background", IMAGE_STRING_OR_NIL_VALUE, 0} }; /* Structure describing the image type `png'. */ @@ -8500,7 +8970,6 @@ png_load (f, img) png_byte channels; png_uint_32 row_bytes; int transparent_p; - char *gamma_str; double screen_gamma, image_gamma; int intent; struct png_memory_storage tbr; /* Data to be read */ @@ -8522,7 +8991,7 @@ png_load (f, img) } /* Open the image file. */ - fp = fopen (XSTRING (file)->data, "rb"); + fp = fopen (SDATA (file), "rb"); if (!fp) { image_error ("Cannot open image file `%s'", file, Qnil); @@ -8544,8 +9013,8 @@ png_load (f, img) else { /* Read from memory. */ - tbr.bytes = XSTRING (specified_data)->data; - tbr.len = STRING_BYTES (XSTRING (specified_data)); + tbr.bytes = SDATA (specified_data); + tbr.len = SBYTES (specified_data); tbr.index = 0; /* Check PNG signature. */ @@ -8638,36 +9107,54 @@ png_load (f, img) || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb (png_ptr); - /* The value 2.2 is a guess for PC monitors from PNG example.c. */ - gamma_str = getenv ("SCREEN_GAMMA"); - screen_gamma = gamma_str ? atof (gamma_str) : 2.2; + screen_gamma = (f->gamma ? 1 / f->gamma / 0.45455 : 2.2); +#if 0 /* Avoid double gamma correction for PNG images. */ /* Tell the PNG lib to handle gamma correction for us. */ - #if defined(PNG_READ_sRGB_SUPPORTED) || defined(PNG_WRITE_sRGB_SUPPORTED) if (png_get_sRGB (png_ptr, info_ptr, &intent)) - /* There is a special chunk in the image specifying the gamma. */ - png_set_sRGB (png_ptr, info_ptr, intent); + /* The libpng documentation says this is right in this case. */ + png_set_gamma (png_ptr, screen_gamma, 0.45455); else #endif if (png_get_gAMA (png_ptr, info_ptr, &image_gamma)) /* Image contains gamma information. */ png_set_gamma (png_ptr, screen_gamma, image_gamma); else - /* Use a default of 0.5 for the image gamma. */ - png_set_gamma (png_ptr, screen_gamma, 0.5); + /* Use the standard default for the image gamma. */ + png_set_gamma (png_ptr, screen_gamma, 0.45455); +#endif /* if 0 */ /* Handle alpha channel by combining the image with a background color. Do this only if a real alpha channel is supplied. For simple transparency, we prefer a clipping mask. */ if (!transparent_p) { - png_color_16 *image_background; + png_color_16 *image_bg; + Lisp_Object specified_bg + = image_spec_value (img->spec, QCbackground, NULL); + + if (STRINGP (specified_bg)) + /* The user specified `:background', use that. */ + { + XColor color; + if (x_defined_color (f, SDATA (specified_bg), &color, 0)) + { + png_color_16 user_bg; + + bzero (&user_bg, sizeof user_bg); + user_bg.red = color.red; + user_bg.green = color.green; + user_bg.blue = color.blue; - if (png_get_bKGD (png_ptr, info_ptr, &image_background)) + png_set_background (png_ptr, &user_bg, + PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); + } + } + else if (png_get_bKGD (png_ptr, info_ptr, &image_bg)) /* Image contains a background color with which to combine the image. */ - png_set_background (png_ptr, image_background, + png_set_background (png_ptr, image_bg, PNG_BACKGROUND_GAMMA_FILE, 1, 1.0); else { @@ -8780,6 +9267,18 @@ png_load (f, img) } } + if (NILP (image_spec_value (img->spec, QCbackground, NULL))) + /* Set IMG's background color from the PNG image, unless the user + overrode it. */ + { + png_color_16 *bg; + if (png_get_bKGD (png_ptr, info_ptr, &bg)) + { + img->background = lookup_rgb_color (f, bg->red, bg->green, bg->blue); + img->background_valid = 1; + } + } + /* Remember colors allocated for this image. */ img->colors = colors_in_color_table (&img->ncolors); free_color_table (); @@ -8792,6 +9291,9 @@ png_load (f, img) img->width = width; img->height = height; + /* Maybe fill in the background field while we have ximg handy. */ + IMAGE_BACKGROUND (img, f, ximg); + /* Put the image into the pixmap, then free the X image and its buffer. */ x_put_x_image (f, ximg, img->pixmap, width, height); x_destroy_x_image (ximg); @@ -8799,6 +9301,10 @@ png_load (f, img) /* Same for the mask. */ if (mask_img) { + /* Fill in the background_transparent field while we have the mask + handy. */ + image_background_transparent (img, f, mask_img); + x_put_x_image (f, mask_img, img->mask, img->width, img->height); x_destroy_x_image (mask_img); } @@ -8852,6 +9358,7 @@ enum jpeg_keyword_index JPEG_ALGORITHM, JPEG_HEURISTIC_MASK, JPEG_MASK, + JPEG_BACKGROUND, JPEG_LAST }; @@ -8868,7 +9375,8 @@ static struct image_keyword jpeg_format[JPEG_LAST] = {":relief", IMAGE_INTEGER_VALUE, 0}, {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, - {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0} + {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, + {":background", IMAGE_STRING_OR_NIL_VALUE, 0} }; /* Structure describing the image type `jpeg'. */ @@ -9050,7 +9558,7 @@ jpeg_load (f, img) return 0; } - fp = fopen (XSTRING (file)->data, "r"); + fp = fopen (SDATA (file), "r"); if (fp == NULL) { image_error ("Cannot open `%s'", file, Qnil); @@ -9097,8 +9605,8 @@ jpeg_load (f, img) if (NILP (specified_data)) jpeg_stdio_src (&cinfo, (FILE *) fp); else - jpeg_memory_src (&cinfo, XSTRING (specified_data)->data, - STRING_BYTES (XSTRING (specified_data))); + jpeg_memory_src (&cinfo, SDATA (specified_data), + SBYTES (specified_data)); jpeg_read_header (&cinfo, TRUE); @@ -9167,6 +9675,10 @@ jpeg_load (f, img) jpeg_destroy_decompress (&cinfo); if (fp) fclose ((FILE *) fp); + + /* Maybe fill in the background field while we have ximg handy. */ + if (NILP (image_spec_value (img->spec, QCbackground, NULL))) + IMAGE_BACKGROUND (img, f, ximg); /* Put the image into the pixmap. */ x_put_x_image (f, ximg, img->pixmap, width, height); @@ -9207,6 +9719,7 @@ enum tiff_keyword_index TIFF_ALGORITHM, TIFF_HEURISTIC_MASK, TIFF_MASK, + TIFF_BACKGROUND, TIFF_LAST }; @@ -9223,7 +9736,8 @@ static struct image_keyword tiff_format[TIFF_LAST] = {":relief", IMAGE_INTEGER_VALUE, 0}, {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, - {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0} + {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, + {":background", IMAGE_STRING_OR_NIL_VALUE, 0} }; /* Structure describing the image type `tiff'. */ @@ -9372,6 +9886,34 @@ tiff_size_of_memory (data) } +static void +tiff_error_handler (title, format, ap) + const char *title, *format; + va_list ap; +{ + char buf[512]; + int len; + + len = sprintf (buf, "TIFF error: %s ", title); + vsprintf (buf + len, format, ap); + add_to_log (buf, Qnil, Qnil); +} + + +static void +tiff_warning_handler (title, format, ap) + const char *title, *format; + va_list ap; +{ + char buf[512]; + int len; + + len = sprintf (buf, "TIFF warning: %s ", title); + vsprintf (buf + len, format, ap); + add_to_log (buf, Qnil, Qnil); +} + + /* Load TIFF image IMG for use on frame F. Value is non-zero if successful. */ @@ -9395,6 +9937,9 @@ tiff_load (f, img) file = Qnil; GCPRO1 (file); + TIFFSetErrorHandler (tiff_error_handler); + TIFFSetWarningHandler (tiff_warning_handler); + if (NILP (specified_data)) { /* Read from a file */ @@ -9407,7 +9952,7 @@ tiff_load (f, img) } /* Try to open the image file. */ - tiff = TIFFOpen (XSTRING (file)->data, "r"); + tiff = TIFFOpen (SDATA (file), "r"); if (tiff == NULL) { image_error ("Cannot open `%s'", file, Qnil); @@ -9418,8 +9963,8 @@ tiff_load (f, img) else { /* Memory source! */ - memsrc.bytes = XSTRING (specified_data)->data; - memsrc.len = STRING_BYTES (XSTRING (specified_data)); + memsrc.bytes = SDATA (specified_data); + memsrc.len = SBYTES (specified_data); memsrc.index = 0; tiff = TIFFClientOpen ("memory_source", "r", &memsrc, @@ -9484,14 +10029,18 @@ tiff_load (f, img) /* Remember the colors allocated for the image. Free the color table. */ img->colors = colors_in_color_table (&img->ncolors); free_color_table (); + + img->width = width; + img->height = height; + + /* Maybe fill in the background field while we have ximg handy. */ + if (NILP (image_spec_value (img->spec, QCbackground, NULL))) + IMAGE_BACKGROUND (img, f, ximg); /* Put the image into the pixmap, then free the X image and its buffer. */ x_put_x_image (f, ximg, img->pixmap, width, height); x_destroy_x_image (ximg); xfree (buf); - - img->width = width; - img->height = height; UNGCPRO; return 1; @@ -9530,6 +10079,7 @@ enum gif_keyword_index GIF_HEURISTIC_MASK, GIF_MASK, GIF_IMAGE, + GIF_BACKGROUND, GIF_LAST }; @@ -9547,7 +10097,8 @@ static struct image_keyword gif_format[GIF_LAST] = {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, - {":image", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0} + {":image", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0}, + {":background", IMAGE_STRING_OR_NIL_VALUE, 0} }; /* Structure describing the image type `gif'. */ @@ -9650,7 +10201,7 @@ gif_load (f, img) } /* Open the GIF file. */ - gif = DGifOpenFileName (XSTRING (file)->data); + gif = DGifOpenFileName (SDATA (file)); if (gif == NULL) { image_error ("Cannot open `%s'", file, Qnil); @@ -9662,8 +10213,8 @@ gif_load (f, img) { /* Read from memory! */ current_gif_memory_src = &memsrc; - memsrc.bytes = XSTRING (specified_data)->data; - memsrc.len = STRING_BYTES (XSTRING (specified_data)); + memsrc.bytes = SDATA (specified_data); + memsrc.len = SBYTES (specified_data); memsrc.index = 0; gif = DGifOpen(&memsrc, gif_read_from_memory); @@ -9696,8 +10247,8 @@ gif_load (f, img) return 0; } - width = img->width = gif->SWidth; - height = img->height = gif->SHeight; + width = img->width = max (gif->SWidth, gif->Image.Left + gif->Image.Width); + height = img->height = max (gif->SHeight, gif->Image.Top + gif->Image.Height); /* Create the X image and pixmap. */ if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap)) @@ -9795,6 +10346,10 @@ gif_load (f, img) } DGifCloseFile (gif); + + /* Maybe fill in the background field while we have ximg handy. */ + if (NILP (image_spec_value (img->spec, QCbackground, NULL))) + IMAGE_BACKGROUND (img, f, ximg); /* Put the image into the pixmap, then free the X image and its buffer. */ x_put_x_image (f, ximg, img->pixmap, width, height); @@ -9840,6 +10395,7 @@ enum gs_keyword_index GS_ALGORITHM, GS_HEURISTIC_MASK, GS_MASK, + GS_BACKGROUND, GS_LAST }; @@ -9859,7 +10415,8 @@ static struct image_keyword gs_format[GS_LAST] = {":relief", IMAGE_INTEGER_VALUE, 0}, {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, - {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0} + {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, + {":background", IMAGE_STRING_OR_NIL_VALUE, 0} }; /* Structure describing the image type `ghostscript'. */ @@ -10015,9 +10572,13 @@ x_kill_gs_process (pixmap, f) if (c->images[i]->pixmap == pixmap) break; + /* Should someone in between have cleared the image cache, for + instance, give up. */ + if (i == c->used) + return; + /* Kill the GS process. We should have found PIXMAP in the image cache and its image should contain a process object. */ - xassert (i < c->used); img = c->images[i]; xassert (PROCESSP (img->data.lisp_val)); Fkill_process (img->data.lisp_val, Qnil); @@ -10074,6 +10635,12 @@ x_kill_gs_process (pixmap, f) UNBLOCK_INPUT; } + + /* Now that we have the pixmap, compute mask and transform the + image if requested. */ + BLOCK_INPUT; + postprocess_image (f, img); + UNBLOCK_INPUT; } @@ -10084,23 +10651,23 @@ x_kill_gs_process (pixmap, f) DEFUN ("x-change-window-property", Fx_change_window_property, Sx_change_window_property, 2, 3, 0, - "Change window property PROP to VALUE on the X window of FRAME.\n\ -PROP and VALUE must be strings. FRAME nil or omitted means use the\n\ -selected frame. Value is VALUE.") - (prop, value, frame) + doc: /* Change window property PROP to VALUE on the X window of FRAME. +PROP and VALUE must be strings. FRAME nil or omitted means use the +selected frame. Value is VALUE. */) + (prop, value, frame) Lisp_Object frame, prop, value; { struct frame *f = check_x_frame (frame); Atom prop_atom; - CHECK_STRING (prop, 1); - CHECK_STRING (value, 2); + CHECK_STRING (prop); + CHECK_STRING (value); BLOCK_INPUT; - prop_atom = XInternAtom (FRAME_X_DISPLAY (f), XSTRING (prop)->data, False); + prop_atom = XInternAtom (FRAME_X_DISPLAY (f), SDATA (prop), False); XChangeProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), prop_atom, XA_STRING, 8, PropModeReplace, - XSTRING (value)->data, XSTRING (value)->size); + SDATA (value), SCHARS (value)); /* Make sure the property is set when we return. */ XFlush (FRAME_X_DISPLAY (f)); @@ -10112,17 +10679,17 @@ selected frame. Value is VALUE.") DEFUN ("x-delete-window-property", Fx_delete_window_property, Sx_delete_window_property, 1, 2, 0, - "Remove window property PROP from X window of FRAME.\n\ -FRAME nil or omitted means use the selected frame. Value is PROP.") - (prop, frame) + doc: /* Remove window property PROP from X window of FRAME. +FRAME nil or omitted means use the selected frame. Value is PROP. */) + (prop, frame) Lisp_Object prop, frame; { struct frame *f = check_x_frame (frame); Atom prop_atom; - CHECK_STRING (prop, 1); + CHECK_STRING (prop); BLOCK_INPUT; - prop_atom = XInternAtom (FRAME_X_DISPLAY (f), XSTRING (prop)->data, False); + prop_atom = XInternAtom (FRAME_X_DISPLAY (f), SDATA (prop), False); XDeleteProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), prop_atom); /* Make sure the property is removed when we return. */ @@ -10135,11 +10702,11 @@ FRAME nil or omitted means use the selected frame. Value is PROP.") DEFUN ("x-window-property", Fx_window_property, Sx_window_property, 1, 2, 0, - "Value is the value of window property PROP on FRAME.\n\ -If FRAME is nil or omitted, use the selected frame. Value is nil\n\ -if FRAME hasn't a property with name PROP or if PROP has no string\n\ -value.") - (prop, frame) + doc: /* Value is the value of window property PROP on FRAME. +If FRAME is nil or omitted, use the selected frame. Value is nil +if FRAME hasn't a property with name PROP or if PROP has no string +value. */) + (prop, frame) Lisp_Object prop, frame; { struct frame *f = check_x_frame (frame); @@ -10151,9 +10718,9 @@ value.") int actual_format; unsigned long actual_size, bytes_remaining; - CHECK_STRING (prop, 1); + CHECK_STRING (prop); BLOCK_INPUT; - prop_atom = XInternAtom (FRAME_X_DISPLAY (f), XSTRING (prop)->data, False); + prop_atom = XInternAtom (FRAME_X_DISPLAY (f), SDATA (prop), False); rc = XGetWindowProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), prop_atom, 0, 0, False, XA_STRING, &actual_type, &actual_format, &actual_size, @@ -10171,7 +10738,7 @@ value.") &actual_type, &actual_format, &actual_size, &bytes_remaining, (unsigned char **) &tmp_data); - if (rc == Success) + if (rc == Success && tmp_data) prop_value = make_string (tmp_data, size); XFree (tmp_data); @@ -10188,94 +10755,94 @@ value.") ***********************************************************************/ /* If non-null, an asynchronous timer that, when it expires, displays - a busy cursor on all frames. */ + an hourglass cursor on all frames. */ -static struct atimer *busy_cursor_atimer; +static struct atimer *hourglass_atimer; -/* Non-zero means a busy cursor is currently shown. */ +/* Non-zero means an hourglass cursor is currently shown. */ -static int busy_cursor_shown_p; +static int hourglass_shown_p; -/* Number of seconds to wait before displaying a busy cursor. */ +/* Number of seconds to wait before displaying an hourglass cursor. */ -static Lisp_Object Vbusy_cursor_delay; +static Lisp_Object Vhourglass_delay; -/* Default number of seconds to wait before displaying a busy +/* Default number of seconds to wait before displaying an hourglass cursor. */ -#define DEFAULT_BUSY_CURSOR_DELAY 1 +#define DEFAULT_HOURGLASS_DELAY 1 /* Function prototypes. */ -static void show_busy_cursor P_ ((struct atimer *)); -static void hide_busy_cursor P_ ((void)); +static void show_hourglass P_ ((struct atimer *)); +static void hide_hourglass P_ ((void)); -/* Cancel a currently active busy-cursor timer, and start a new one. */ +/* Cancel a currently active hourglass timer, and start a new one. */ void -start_busy_cursor () +start_hourglass () { EMACS_TIME delay; int secs, usecs = 0; - cancel_busy_cursor (); + cancel_hourglass (); - if (INTEGERP (Vbusy_cursor_delay) - && XINT (Vbusy_cursor_delay) > 0) - secs = XFASTINT (Vbusy_cursor_delay); - else if (FLOATP (Vbusy_cursor_delay) - && XFLOAT_DATA (Vbusy_cursor_delay) > 0) + if (INTEGERP (Vhourglass_delay) + && XINT (Vhourglass_delay) > 0) + secs = XFASTINT (Vhourglass_delay); + else if (FLOATP (Vhourglass_delay) + && XFLOAT_DATA (Vhourglass_delay) > 0) { Lisp_Object tem; - tem = Ftruncate (Vbusy_cursor_delay, Qnil); + tem = Ftruncate (Vhourglass_delay, Qnil); secs = XFASTINT (tem); - usecs = (XFLOAT_DATA (Vbusy_cursor_delay) - secs) * 1000000; + usecs = (XFLOAT_DATA (Vhourglass_delay) - secs) * 1000000; } else - secs = DEFAULT_BUSY_CURSOR_DELAY; + secs = DEFAULT_HOURGLASS_DELAY; EMACS_SET_SECS_USECS (delay, secs, usecs); - busy_cursor_atimer = start_atimer (ATIMER_RELATIVE, delay, - show_busy_cursor, NULL); + hourglass_atimer = start_atimer (ATIMER_RELATIVE, delay, + show_hourglass, NULL); } -/* Cancel the busy cursor timer if active, hide a busy cursor if +/* Cancel the hourglass cursor timer if active, hide a busy cursor if shown. */ void -cancel_busy_cursor () +cancel_hourglass () { - if (busy_cursor_atimer) + if (hourglass_atimer) { - cancel_atimer (busy_cursor_atimer); - busy_cursor_atimer = NULL; + cancel_atimer (hourglass_atimer); + hourglass_atimer = NULL; } - if (busy_cursor_shown_p) - hide_busy_cursor (); + if (hourglass_shown_p) + hide_hourglass (); } -/* Timer function of busy_cursor_atimer. TIMER is equal to - busy_cursor_atimer. +/* Timer function of hourglass_atimer. TIMER is equal to + hourglass_atimer. - Display a busy cursor on all frames by mapping the frames' - busy_window. Set the busy_p flag in the frames' output_data.x - structure to indicate that a busy cursor is shown on the - frames. */ + Display an hourglass pointer on all frames by mapping the frames' + hourglass_window. Set the hourglass_p flag in the frames' + output_data.x structure to indicate that an hourglass cursor is + shown on the frames. */ static void -show_busy_cursor (timer) +show_hourglass (timer) struct atimer *timer; { /* The timer implementation will cancel this timer automatically - after this function has run. Set busy_cursor_atimer to null + after this function has run. Set hourglass_atimer to null so that we know the timer doesn't have to be canceled. */ - busy_cursor_atimer = NULL; + hourglass_atimer = NULL; - if (!busy_cursor_shown_p) + if (!hourglass_shown_p) { Lisp_Object rest, frame; @@ -10295,16 +10862,16 @@ show_busy_cursor (timer) if (FRAME_OUTER_WINDOW (f)) #endif { - f->output_data.x->busy_p = 1; + f->output_data.x->hourglass_p = 1; - if (!f->output_data.x->busy_window) + if (!f->output_data.x->hourglass_window) { unsigned long mask = CWCursor; XSetWindowAttributes attrs; - attrs.cursor = f->output_data.x->busy_cursor; + attrs.cursor = f->output_data.x->hourglass_cursor; - f->output_data.x->busy_window + f->output_data.x->hourglass_window = XCreateWindow (dpy, FRAME_OUTER_WINDOW (f), 0, 0, 32000, 32000, 0, 0, InputOnly, @@ -10312,24 +10879,25 @@ show_busy_cursor (timer) mask, &attrs); } - XMapRaised (dpy, f->output_data.x->busy_window); + XMapRaised (dpy, f->output_data.x->hourglass_window); XFlush (dpy); } } } - busy_cursor_shown_p = 1; + hourglass_shown_p = 1; UNBLOCK_INPUT; } } -/* Hide the busy cursor on all frames, if it is currently shown. */ +/* Hide the hourglass pointer on all frames, if it is currently + shown. */ static void -hide_busy_cursor () +hide_hourglass () { - if (busy_cursor_shown_p) + if (hourglass_shown_p) { Lisp_Object rest, frame; @@ -10340,17 +10908,18 @@ hide_busy_cursor () if (FRAME_X_P (f) /* Watch out for newly created frames. */ - && f->output_data.x->busy_window) + && f->output_data.x->hourglass_window) { - XUnmapWindow (FRAME_X_DISPLAY (f), f->output_data.x->busy_window); - /* Sync here because XTread_socket looks at the busy_p flag - that is reset to zero below. */ + XUnmapWindow (FRAME_X_DISPLAY (f), + f->output_data.x->hourglass_window); + /* Sync here because XTread_socket looks at the + hourglass_p flag that is reset to zero below. */ XSync (FRAME_X_DISPLAY (f), False); - f->output_data.x->busy_p = 0; + f->output_data.x->hourglass_p = 0; } } - busy_cursor_shown_p = 0; + hourglass_shown_p = 0; UNBLOCK_INPUT; } } @@ -10362,9 +10931,9 @@ hide_busy_cursor () ***********************************************************************/ static Lisp_Object x_create_tip_frame P_ ((struct x_display_info *, - Lisp_Object)); + Lisp_Object, Lisp_Object)); static void compute_tip_xy P_ ((struct frame *, Lisp_Object, Lisp_Object, - Lisp_Object, int *, int *)); + Lisp_Object, int, int, int *, int *)); /* The frame of a currently visible tooltip. */ @@ -10381,6 +10950,10 @@ Window tip_window; Lisp_Object last_show_tip_args; +/* Maximum size for tooltips; a cons (COLUMNS . ROWS). */ + +Lisp_Object Vx_max_tooltip_size; + static Lisp_Object unwind_create_tip_frame (frame) @@ -10400,7 +10973,8 @@ unwind_create_tip_frame (frame) /* Create a frame for a tooltip on the display described by DPYINFO. - PARMS is a list of frame parameters. Value is the frame. + PARMS is a list of frame parameters. TEXT is the string to + display in the tip frame. Value is the frame. Note that functions called here, esp. x_default_parameter can signal errors, for instance when a specified color name is @@ -10408,19 +10982,21 @@ unwind_create_tip_frame (frame) when this happens. */ static Lisp_Object -x_create_tip_frame (dpyinfo, parms) +x_create_tip_frame (dpyinfo, parms, text) struct x_display_info *dpyinfo; - Lisp_Object parms; + Lisp_Object parms, text; { struct frame *f; Lisp_Object frame, tem; Lisp_Object name; long window_prompting = 0; int width, height; - int count = BINDING_STACK_SIZE (); + int count = SPECPDL_INDEX (); struct gcpro gcpro1, gcpro2, gcpro3; struct kboard *kb; int face_change_count_before = face_change_count; + Lisp_Object buffer; + struct buffer *old_buffer; check_x (); @@ -10446,6 +11022,16 @@ x_create_tip_frame (dpyinfo, parms) GCPRO3 (parms, name, frame); f = make_frame (1); XSETFRAME (frame, f); + + buffer = Fget_buffer_create (build_string (" *tip*")); + Fset_window_buffer (FRAME_ROOT_WINDOW (f), buffer); + old_buffer = current_buffer; + set_buffer_internal_1 (XBUFFER (buffer)); + current_buffer->truncate_lines = Qnil; + Ferase_buffer (); + Finsert (1, &text); + set_buffer_internal_1 (old_buffer); + FRAME_CAN_HAVE_SCROLL_BARS (f) = 0; record_unwind_protect (unwind_create_tip_frame, frame); @@ -10460,6 +11046,10 @@ x_create_tip_frame (dpyinfo, parms) f->output_data.x->fontset = -1; f->output_data.x->scroll_bar_foreground_pixel = -1; f->output_data.x->scroll_bar_background_pixel = -1; +#ifdef USE_TOOLKIT_SCROLL_BARS + f->output_data.x->scroll_bar_top_shadow_pixel = -1; + f->output_data.x->scroll_bar_bottom_shadow_pixel = -1; +#endif /* USE_TOOLKIT_SCROLL_BARS */ f->icon_name = Qnil; FRAME_X_DISPLAY_INFO (f) = dpyinfo; #if GLYPH_DEBUG @@ -10523,9 +11113,9 @@ x_create_tip_frame (dpyinfo, parms) { tem = Fquery_fontset (font, Qnil); if (STRINGP (tem)) - font = x_new_fontset (f, XSTRING (tem)->data); + font = x_new_fontset (f, SDATA (tem)); else - font = x_new_font (f, XSTRING (font)->data); + font = x_new_font (f, SDATA (font)); } /* Try out a font which we hope has bold and italic variations. */ @@ -10657,7 +11247,12 @@ x_create_tip_frame (dpyinfo, parms) f->height = 0; SET_FRAME_WIDTH (f, 0); change_frame_size (f, height, width, 1, 0, 0); - + + /* Add `tooltip' frame parameter's default value. */ + if (NILP (Fframe_parameter (frame, intern ("tooltip")))) + Fmodify_frame_parameters (frame, Fcons (Fcons (intern ("tooltip"), Qt), + Qnil)); + /* Set up faces after all frame parameters are known. This call also merges in face attributes specified for new frames. @@ -10705,13 +11300,15 @@ x_create_tip_frame (dpyinfo, parms) /* Compute where to display tip frame F. PARMS is the list of frame parameters for F. DX and DY are specified offsets from the current - location of the mouse. Return coordinates relative to the root - window of the display in *ROOT_X, and *ROOT_Y. */ + location of the mouse. WIDTH and HEIGHT are the width and height + of the tooltip. Return coordinates relative to the root window of + the display in *ROOT_X, and *ROOT_Y. */ static void -compute_tip_xy (f, parms, dx, dy, root_x, root_y) +compute_tip_xy (f, parms, dx, dy, width, height, root_x, root_y) struct frame *f; Lisp_Object parms, dx, dy; + int width, height; int *root_x, *root_y; { Lisp_Object left, top; @@ -10725,74 +11322,93 @@ compute_tip_xy (f, parms, dx, dy, root_x, root_y) /* Move the tooltip window where the mouse pointer is. Resize and show it. */ - BLOCK_INPUT; - XQueryPointer (FRAME_X_DISPLAY (f), FRAME_X_DISPLAY_INFO (f)->root_window, - &root, &child, root_x, root_y, &win_x, &win_y, &pmask); - UNBLOCK_INPUT; + if (!INTEGERP (left) || !INTEGERP (top)) + { + BLOCK_INPUT; + XQueryPointer (FRAME_X_DISPLAY (f), FRAME_X_DISPLAY_INFO (f)->root_window, + &root, &child, root_x, root_y, &win_x, &win_y, &pmask); + UNBLOCK_INPUT; + } - *root_x += XINT (dx); - *root_y += XINT (dy); - - if (INTEGERP (left)) - *root_x = XINT (left); if (INTEGERP (top)) *root_y = XINT (top); + else if (*root_y + XINT (dy) - height < 0) + *root_y -= XINT (dy); + else + { + *root_y -= height; + *root_y += XINT (dy); + } + + if (INTEGERP (left)) + *root_x = XINT (left); + else if (*root_x + XINT (dx) + width <= FRAME_X_DISPLAY_INFO (f)->width) + /* It fits to the right of the pointer. */ + *root_x += XINT (dx); + else if (width + XINT (dx) <= *root_x) + /* It fits to the left of the pointer. */ + *root_x -= width + XINT (dx); + else + /* Put it left-justified on the screen--it ought to fit that way. */ + *root_x = 0; } DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0, - "Show STRING in a \"tooltip\" window on frame FRAME.\n\ -A tooltip window is a small X window displaying a string.\n\ -\n\ -FRAME nil or omitted means use the selected frame.\n\ -\n\ -PARMS is an optional list of frame parameters which can be\n\ -used to change the tooltip's appearance.\n\ -\n\ -Automatically hide the tooltip after TIMEOUT seconds.\n\ -TIMEOUT nil means use the default timeout of 5 seconds.\n\ -\n\ -If the list of frame parameters PARAMS contains a `left' parameters,\n\ -the tooltip is displayed at that x-position. Otherwise it is\n\ -displayed at the mouse position, with offset DX added (default is 5 if\n\ -DX isn't specified). Likewise for the y-position; if a `top' frame\n\ -parameter is specified, it determines the y-position of the tooltip\n\ -window, otherwise it is displayed at the mouse position, with offset\n\ -DY added (default is -10).") - (string, frame, parms, timeout, dx, dy) + doc: /* Show STRING in a "tooltip" window on frame FRAME. +A tooltip window is a small X window displaying a string. + +FRAME nil or omitted means use the selected frame. + +PARMS is an optional list of frame parameters which can be used to +change the tooltip's appearance. + +Automatically hide the tooltip after TIMEOUT seconds. TIMEOUT nil +means use the default timeout of 5 seconds. + +If the list of frame parameters PARAMS contains a `left' parameters, +the tooltip is displayed at that x-position. Otherwise it is +displayed at the mouse position, with offset DX added (default is 5 if +DX isn't specified). Likewise for the y-position; if a `top' frame +parameter is specified, it determines the y-position of the tooltip +window, otherwise it is displayed at the mouse position, with offset +DY added (default is -10). + +A tooltip's maximum size is specified by `x-max-tooltip-size'. +Text larger than the specified size is clipped. */) + (string, frame, parms, timeout, dx, dy) Lisp_Object string, frame, parms, timeout, dx, dy; { struct frame *f; struct window *w; - Lisp_Object buffer, top, left; int root_x, root_y; struct buffer *old_buffer; struct text_pos pos; int i, width, height; struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; int old_windows_or_buffers_changed = windows_or_buffers_changed; - int count = BINDING_STACK_SIZE (); + int count = SPECPDL_INDEX (); specbind (Qinhibit_redisplay, Qt); GCPRO4 (string, parms, frame, timeout); - CHECK_STRING (string, 0); + CHECK_STRING (string); f = check_x_frame (frame); if (NILP (timeout)) timeout = make_number (5); else - CHECK_NATNUM (timeout, 2); + CHECK_NATNUM (timeout); if (NILP (dx)) dx = make_number (5); else - CHECK_NUMBER (dx, 5); + CHECK_NUMBER (dx); if (NILP (dy)) dy = make_number (-10); else - CHECK_NUMBER (dy, 6); + CHECK_NUMBER (dy); if (NILP (last_show_tip_args)) last_show_tip_args = Fmake_vector (make_number (3), Qnil); @@ -10818,9 +11434,10 @@ DY added (default is -10).") } BLOCK_INPUT; - compute_tip_xy (f, parms, dx, dy, &root_x, &root_y); + compute_tip_xy (f, parms, dx, dy, PIXEL_WIDTH (f), + PIXEL_HEIGHT (f), &root_x, &root_y); XMoveWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), - root_x, root_y - PIXEL_HEIGHT (f)); + root_x, root_y); UNBLOCK_INPUT; goto start_timer; } @@ -10848,26 +11465,36 @@ DY added (default is -10).") /* Create a frame for the tooltip, and record it in the global variable tip_frame. */ - frame = x_create_tip_frame (FRAME_X_DISPLAY_INFO (f), parms); + frame = x_create_tip_frame (FRAME_X_DISPLAY_INFO (f), parms, string); f = XFRAME (frame); - /* Set up the frame's root window. Currently we use a size of 80 - columns x 40 lines. If someone wants to show a larger tip, he - will loose. I don't think this is a realistic case. */ + /* Set up the frame's root window. */ w = XWINDOW (FRAME_ROOT_WINDOW (f)); w->left = w->top = make_number (0); - w->width = make_number (80); - w->height = make_number (40); + + if (CONSP (Vx_max_tooltip_size) + && INTEGERP (XCAR (Vx_max_tooltip_size)) + && XINT (XCAR (Vx_max_tooltip_size)) > 0 + && INTEGERP (XCDR (Vx_max_tooltip_size)) + && XINT (XCDR (Vx_max_tooltip_size)) > 0) + { + w->width = XCAR (Vx_max_tooltip_size); + w->height = XCDR (Vx_max_tooltip_size); + } + else + { + w->width = make_number (80); + w->height = make_number (40); + } + + f->window_width = XINT (w->width); adjust_glyphs (f); w->pseudo_window_p = 1; /* Display the tooltip text in a temporary buffer. */ - buffer = Fget_buffer_create (build_string (" *tip*")); - Fset_window_buffer (FRAME_ROOT_WINDOW (f), buffer); old_buffer = current_buffer; - set_buffer_internal_1 (XBUFFER (buffer)); - Ferase_buffer (); - Finsert (1, &string); + set_buffer_internal_1 (XBUFFER (XWINDOW (FRAME_ROOT_WINDOW (f))->buffer)); + current_buffer->truncate_lines = Qnil; clear_glyph_matrix (w->desired_matrix); clear_glyph_matrix (w->current_matrix); SET_TEXT_POS (pos, BEGV, BEGV_BYTE); @@ -10909,11 +11536,11 @@ DY added (default is -10).") /* Move the tooltip window where the mouse pointer is. Resize and show it. */ - compute_tip_xy (f, parms, dx, dy, &root_x, &root_y); + compute_tip_xy (f, parms, dx, dy, width, height, &root_x, &root_y); BLOCK_INPUT; XMoveResizeWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), - root_x, root_y - height, width, height); + root_x, root_y, width, height); XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f)); UNBLOCK_INPUT; @@ -10936,9 +11563,9 @@ DY added (default is -10).") DEFUN ("x-hide-tip", Fx_hide_tip, Sx_hide_tip, 0, 0, 0, - "Hide the current tooltip window, if there is any.\n\ -Value is t is tooltip was open, nil otherwise.") - () + doc: /* Hide the current tooltip window, if there is any. +Value is t if tooltip was open, nil otherwise. */) + () { int count; Lisp_Object deleted, frame, timer; @@ -10953,7 +11580,7 @@ Value is t is tooltip was open, nil otherwise.") GCPRO2 (frame, timer); tip_frame = tip_timer = deleted = Qnil; - count = BINDING_STACK_SIZE (); + count = SPECPDL_INDEX (); specbind (Qinhibit_redisplay, Qt); specbind (Qinhibit_quit, Qt); @@ -10973,9 +11600,9 @@ Value is t is tooltip was open, nil otherwise.") struct frame *f = SELECTED_FRAME (); Widget w = f->output_data.x->menubar_widget; extern void xlwmenu_redisplay P_ ((Widget)); - + if (!DoesSaveUnders (FRAME_X_DISPLAY_INFO (f)->screen) - && w != None) + && w != NULL) { BLOCK_INPUT; xlwmenu_redisplay (w); @@ -11010,13 +11637,28 @@ file_dialog_cb (widget, client_data, call_data) } +/* Callback for unmapping a file selection dialog. This is used to + capture the case where a dialog is closed via a window manager's + closer button, for example. Using a XmNdestroyCallback didn't work + in this case. */ + +static void +file_dialog_unmap_cb (widget, client_data, call_data) + Widget widget; + XtPointer call_data, client_data; +{ + int *result = (int *) client_data; + *result = XmCR_CANCEL; +} + + DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 4, 0, - "Read file name, prompting with PROMPT in directory DIR.\n\ -Use a file selection dialog.\n\ -Select DEFAULT-FILENAME in the dialog's file selection box, if\n\ -specified. Don't let the user enter a file name in the file\n\ -selection dialog's entry field, if MUSTMATCH is non-nil.") - (prompt, dir, default_filename, mustmatch) + doc: /* Read file name, prompting with PROMPT in directory DIR. +Use a file selection dialog. +Select DEFAULT-FILENAME in the dialog's file selection box, if +specified. Don't let the user enter a file name in the file +selection dialog's entry field, if MUSTMATCH is non-nil. */) + (prompt, dir, default_filename, mustmatch) Lisp_Object prompt, dir, default_filename, mustmatch; { int result; @@ -11026,15 +11668,13 @@ selection dialog's entry field, if MUSTMATCH is non-nil.") Arg al[10]; int ac = 0; extern XtAppContext Xt_app_con; - char *title; XmString dir_xmstring, pattern_xmstring; - int popup_activated_flag; - int count = specpdl_ptr - specpdl; + int count = SPECPDL_INDEX (); struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5; GCPRO5 (prompt, dir, default_filename, mustmatch, file); - CHECK_STRING (prompt, 0); - CHECK_STRING (dir, 1); + CHECK_STRING (prompt); + CHECK_STRING (dir); /* Prevent redisplay. */ specbind (Qinhibit_redisplay, Qt); @@ -11044,10 +11684,10 @@ selection dialog's entry field, if MUSTMATCH is non-nil.") /* Create the dialog with PROMPT as title, using DIR as initial directory and using "*" as pattern. */ dir = Fexpand_file_name (dir, Qnil); - dir_xmstring = XmStringCreateLocalized (XSTRING (dir)->data); + dir_xmstring = XmStringCreateLocalized (SDATA (dir)); pattern_xmstring = XmStringCreateLocalized ("*"); - XtSetArg (al[ac], XmNtitle, XSTRING (prompt)->data); ++ac; + XtSetArg (al[ac], XmNtitle, SDATA (prompt)); ++ac; XtSetArg (al[ac], XmNdirectory, dir_xmstring); ++ac; XtSetArg (al[ac], XmNpattern, pattern_xmstring); ++ac; XtSetArg (al[ac], XmNresizePolicy, XmRESIZE_GROW); ++ac; @@ -11062,6 +11702,8 @@ selection dialog's entry field, if MUSTMATCH is non-nil.") (XtPointer) &result); XtAddCallback (dialog, XmNcancelCallback, file_dialog_cb, (XtPointer) &result); + XtAddCallback (dialog, XmNunmapCallback, file_dialog_unmap_cb, + (XtPointer) &result); /* Disable the help button since we can't display help. */ help = XmFileSelectionBoxGetChild (dialog, XmDIALOG_HELP_BUTTON); @@ -11096,7 +11738,7 @@ selection dialog's entry field, if MUSTMATCH is non-nil.") int item_pos; default_xmstring - = XmStringCreateLocalized (XSTRING (default_filename)->data); + = XmStringCreateLocalized (SDATA (default_filename)); if (!XmListItemExists (list, default_xmstring)) { @@ -11115,8 +11757,12 @@ selection dialog's entry field, if MUSTMATCH is non-nil.") /* Process events until the user presses Cancel or OK. */ result = 0; - while (result == 0 || XtAppPending (Xt_app_con)) - XtAppProcessEvent (Xt_app_con, XtIMAll); + while (result == 0) + { + XEvent event; + XtAppNextEvent (Xt_app_con, &event); + x_dispatch_event (&event, FRAME_X_DISPLAY (f) ); + } /* Get the result. */ if (result == XmCR_OK) @@ -11148,6 +11794,58 @@ selection dialog's entry field, if MUSTMATCH is non-nil.") #endif /* USE_MOTIF */ +#ifdef USE_GTK + +DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 4, 0, + "Read file name, prompting with PROMPT in directory DIR.\n\ +Use a file selection dialog.\n\ +Select DEFAULT-FILENAME in the dialog's file selection box, if\n\ +specified. Don't let the user enter a file name in the file\n\ +selection dialog's entry field, if MUSTMATCH is non-nil.") + (prompt, dir, default_filename, mustmatch) + Lisp_Object prompt, dir, default_filename, mustmatch; +{ + FRAME_PTR f = SELECTED_FRAME (); + char *fn; + Lisp_Object file = Qnil; + int count = specpdl_ptr - specpdl; + struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5; + char *cdef_file; + char *cprompt; + + GCPRO5 (prompt, dir, default_filename, mustmatch, file); + CHECK_STRING (prompt); + CHECK_STRING (dir); + + /* Prevent redisplay. */ + specbind (Qinhibit_redisplay, Qt); + + BLOCK_INPUT; + + if (STRINGP (default_filename)) + cdef_file = SDATA (default_filename); + else + cdef_file = SDATA (dir); + + fn = xg_get_file_name (f, SDATA (prompt), cdef_file, ! NILP (mustmatch)); + + if (fn) + { + file = build_string (fn); + xfree (fn); + } + + UNBLOCK_INPUT; + UNGCPRO; + + /* Make "Cancel" equivalent to C-g. */ + if (NILP (file)) + Fsignal (Qquit, Qnil); + + return unbind_to (count, file); +} + +#endif /* USE_GTK */ /*********************************************************************** @@ -11161,11 +11859,11 @@ selection dialog's entry field, if MUSTMATCH is non-nil.") DEFUN ("x-backspace-delete-keys-p", Fx_backspace_delete_keys_p, Sx_backspace_delete_keys_p, 0, 1, 0, - "Check if both Backspace and Delete keys are on the keyboard of FRAME.\n\ -FRAME nil means use the selected frame.\n\ -Value is t if we know that both keys are present, and are mapped to the\n\ -usual X keysyms.") - (frame) + doc: /* Check if both Backspace and Delete keys are on the keyboard of FRAME. +FRAME nil means use the selected frame. +Value is t if we know that both keys are present, and are mapped to the +usual X keysyms. */) + (frame) Lisp_Object frame; { #ifdef HAVE_XKBGETKEYBOARD @@ -11208,8 +11906,9 @@ usual X keysyms.") && (delete_keycode == 0 || backspace_keycode == 0)); ++i) { - /* The XKB symbolic key names can be seen most easily - in the PS file generated by `xkbprint -label name $DISPLAY'. */ + /* The XKB symbolic key names can be seen most easily in + the PS file generated by `xkbprint -label name + $DISPLAY'. */ if (bcmp ("DELE", kb->names->keys[i].name, 4) == 0) delete_keycode = i; else if (bcmp ("BKSP", kb->names->keys[i].name, 4) == 0) @@ -11253,14 +11952,10 @@ syms_of_xfns () staticpro (&Qauto_raise); Qauto_lower = intern ("auto-lower"); staticpro (&Qauto_lower); - Qbar = intern ("bar"); - staticpro (&Qbar); Qborder_color = intern ("border-color"); staticpro (&Qborder_color); Qborder_width = intern ("border-width"); staticpro (&Qborder_width); - Qbox = intern ("box"); - staticpro (&Qbox); Qcursor_color = intern ("cursor-color"); staticpro (&Qcursor_color); Qcursor_type = intern ("cursor-type"); @@ -11323,6 +12018,16 @@ syms_of_xfns () staticpro (&Qcompound_text); Qcancel_timer = intern ("cancel-timer"); staticpro (&Qcancel_timer); + Qwait_for_wm = intern ("wait-for-wm"); + staticpro (&Qwait_for_wm); + Qfullscreen = intern ("fullscreen"); + staticpro (&Qfullscreen); + Qfullwidth = intern ("fullwidth"); + staticpro (&Qfullwidth); + Qfullheight = intern ("fullheight"); + staticpro (&Qfullheight); + Qfullboth = intern ("fullboth"); + staticpro (&Qfullboth); /* This is the end of symbol initialization. */ /* Text property `display' should be nonsticky by default. */ @@ -11356,124 +12061,134 @@ syms_of_xfns () init_x_parm_symbols (); DEFVAR_BOOL ("cross-disabled-images", &cross_disabled_images, - "Non-nil means always draw a cross over disabled images.\n\ -Disabled images are those having an `:conversion disabled' property.\n\ -A cross is always drawn on black & white displays."); + doc: /* Non-nil means always draw a cross over disabled images. +Disabled images are those having an `:conversion disabled' property. +A cross is always drawn on black & white displays. */); cross_disabled_images = 0; DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path, - "List of directories to search for bitmap files for X."); + doc: /* List of directories to search for window system bitmap files. */); Vx_bitmap_file_path = decode_env_path ((char *) 0, PATH_BITMAPS); DEFVAR_LISP ("x-pointer-shape", &Vx_pointer_shape, - "The shape of the pointer when over text.\n\ -Changing the value does not affect existing frames\n\ -unless you set the mouse color."); + doc: /* The shape of the pointer when over text. +Changing the value does not affect existing frames +unless you set the mouse color. */); Vx_pointer_shape = Qnil; DEFVAR_LISP ("x-resource-name", &Vx_resource_name, - "The name Emacs uses to look up X resources.\n\ -`x-get-resource' uses this as the first component of the instance name\n\ -when requesting resource values.\n\ -Emacs initially sets `x-resource-name' to the name under which Emacs\n\ -was invoked, or to the value specified with the `-name' or `-rn'\n\ -switches, if present.\n\ -\n\ -It may be useful to bind this variable locally around a call\n\ -to `x-get-resource'. See also the variable `x-resource-class'."); + doc: /* The name Emacs uses to look up X resources. +`x-get-resource' uses this as the first component of the instance name +when requesting resource values. +Emacs initially sets `x-resource-name' to the name under which Emacs +was invoked, or to the value specified with the `-name' or `-rn' +switches, if present. + +It may be useful to bind this variable locally around a call +to `x-get-resource'. See also the variable `x-resource-class'. */); Vx_resource_name = Qnil; DEFVAR_LISP ("x-resource-class", &Vx_resource_class, - "The class Emacs uses to look up X resources.\n\ -`x-get-resource' uses this as the first component of the instance class\n\ -when requesting resource values.\n\ -Emacs initially sets `x-resource-class' to \"Emacs\".\n\ -\n\ -Setting this variable permanently is not a reasonable thing to do,\n\ -but binding this variable locally around a call to `x-get-resource'\n\ -is a reasonable practice. See also the variable `x-resource-name'."); + doc: /* The class Emacs uses to look up X resources. +`x-get-resource' uses this as the first component of the instance class +when requesting resource values. + +Emacs initially sets `x-resource-class' to "Emacs". + +Setting this variable permanently is not a reasonable thing to do, +but binding this variable locally around a call to `x-get-resource' +is a reasonable practice. See also the variable `x-resource-name'. */); Vx_resource_class = build_string (EMACS_CLASS); #if 0 /* This doesn't really do anything. */ DEFVAR_LISP ("x-nontext-pointer-shape", &Vx_nontext_pointer_shape, - "The shape of the pointer when not over text.\n\ -This variable takes effect when you create a new frame\n\ -or when you set the mouse color."); + doc: /* The shape of the pointer when not over text. +This variable takes effect when you create a new frame +or when you set the mouse color. */); #endif Vx_nontext_pointer_shape = Qnil; - DEFVAR_LISP ("x-busy-pointer-shape", &Vx_busy_pointer_shape, - "The shape of the pointer when Emacs is busy.\n\ -This variable takes effect when you create a new frame\n\ -or when you set the mouse color."); - Vx_busy_pointer_shape = Qnil; + DEFVAR_LISP ("x-hourglass-pointer-shape", &Vx_hourglass_pointer_shape, + doc: /* The shape of the pointer when Emacs is busy. +This variable takes effect when you create a new frame +or when you set the mouse color. */); + Vx_hourglass_pointer_shape = Qnil; - DEFVAR_BOOL ("display-busy-cursor", &display_busy_cursor_p, - "Non-zero means Emacs displays a busy cursor on window systems."); - display_busy_cursor_p = 1; + DEFVAR_BOOL ("display-hourglass", &display_hourglass_p, + doc: /* Non-zero means Emacs displays an hourglass pointer on window systems. */); + display_hourglass_p = 1; - DEFVAR_LISP ("busy-cursor-delay", &Vbusy_cursor_delay, - "*Seconds to wait before displaying a busy-cursor.\n\ -Value must be an integer or float."); - Vbusy_cursor_delay = make_number (DEFAULT_BUSY_CURSOR_DELAY); + DEFVAR_LISP ("hourglass-delay", &Vhourglass_delay, + doc: /* *Seconds to wait before displaying an hourglass pointer. +Value must be an integer or float. */); + Vhourglass_delay = make_number (DEFAULT_HOURGLASS_DELAY); #if 0 /* This doesn't really do anything. */ DEFVAR_LISP ("x-mode-pointer-shape", &Vx_mode_pointer_shape, - "The shape of the pointer when over the mode line.\n\ -This variable takes effect when you create a new frame\n\ -or when you set the mouse color."); + doc: /* The shape of the pointer when over the mode line. +This variable takes effect when you create a new frame +or when you set the mouse color. */); #endif Vx_mode_pointer_shape = Qnil; DEFVAR_LISP ("x-sensitive-text-pointer-shape", &Vx_sensitive_text_pointer_shape, - "The shape of the pointer when over mouse-sensitive text.\n\ -This variable takes effect when you create a new frame\n\ -or when you set the mouse color."); + doc: /* The shape of the pointer when over mouse-sensitive text. +This variable takes effect when you create a new frame +or when you set the mouse color. */); Vx_sensitive_text_pointer_shape = Qnil; DEFVAR_LISP ("x-window-horizontal-drag-cursor", &Vx_window_horizontal_drag_shape, - "Pointer shape to use for indicating a window can be dragged horizontally.\n\ -This variable takes effect when you create a new frame\n\ -or when you set the mouse color."); + doc: /* Pointer shape to use for indicating a window can be dragged horizontally. +This variable takes effect when you create a new frame +or when you set the mouse color. */); Vx_window_horizontal_drag_shape = Qnil; DEFVAR_LISP ("x-cursor-fore-pixel", &Vx_cursor_fore_pixel, - "A string indicating the foreground color of the cursor box."); + doc: /* A string indicating the foreground color of the cursor box. */); Vx_cursor_fore_pixel = Qnil; + DEFVAR_LISP ("x-max-tooltip-size", &Vx_max_tooltip_size, + doc: /* Maximum size for tooltips. Value is a pair (COLUMNS . ROWS). +Text larger than this is clipped. */); + Vx_max_tooltip_size = Fcons (make_number (80), make_number (40)); + DEFVAR_LISP ("x-no-window-manager", &Vx_no_window_manager, - "Non-nil if no X window manager is in use.\n\ -Emacs doesn't try to figure this out; this is always nil\n\ -unless you set it to something else."); + doc: /* Non-nil if no X window manager is in use. +Emacs doesn't try to figure this out; this is always nil +unless you set it to something else. */); /* We don't have any way to find this out, so set it to nil and maybe the user would like to set it to t. */ Vx_no_window_manager = Qnil; DEFVAR_LISP ("x-pixel-size-width-font-regexp", &Vx_pixel_size_width_font_regexp, - "Regexp matching a font name whose width is the same as `PIXEL_SIZE'.\n\ -\n\ -Since Emacs gets width of a font matching with this regexp from\n\ -PIXEL_SIZE field of the name, font finding mechanism gets faster for\n\ -such a font. This is especially effective for such large fonts as\n\ -Chinese, Japanese, and Korean."); + doc: /* Regexp matching a font name whose width is the same as `PIXEL_SIZE'. + +Since Emacs gets width of a font matching with this regexp from +PIXEL_SIZE field of the name, font finding mechanism gets faster for +such a font. This is especially effective for such large fonts as +Chinese, Japanese, and Korean. */); Vx_pixel_size_width_font_regexp = Qnil; DEFVAR_LISP ("image-cache-eviction-delay", &Vimage_cache_eviction_delay, - "Time after which cached images are removed from the cache.\n\ -When an image has not been displayed this many seconds, remove it\n\ -from the image cache. Value must be an integer or nil with nil\n\ -meaning don't clear the cache."); + doc: /* Time after which cached images are removed from the cache. +When an image has not been displayed this many seconds, remove it +from the image cache. Value must be an integer or nil with nil +meaning don't clear the cache. */); Vimage_cache_eviction_delay = make_number (30 * 60); #ifdef USE_X_TOOLKIT - Fprovide (intern ("x-toolkit")); -#endif + Fprovide (intern ("x-toolkit"), Qnil); #ifdef USE_MOTIF - Fprovide (intern ("motif")); -#endif + Fprovide (intern ("motif"), Qnil); + + DEFVAR_LISP ("motif-version-string", &Vmotif_version_string, + doc: /* Version info for LessTif/Motif. */); + Vmotif_version_string = build_string (XmVERSION_STRING); +#endif /* USE_MOTIF */ +#endif /* USE_X_TOOLKIT */ defsubr (&Sx_get_resource); @@ -11525,8 +12240,6 @@ meaning don't clear the cache."); /* Images. */ Qxbm = intern ("xbm"); staticpro (&Qxbm); - QCtype = intern (":type"); - staticpro (&QCtype); QCconversion = intern (":conversion"); staticpro (&QCconversion); QCheuristic_mask = intern (":heuristic-mask"); @@ -11583,8 +12296,8 @@ meaning don't clear the cache."); defsubr (&Simage_size); defsubr (&Simage_mask_p); - busy_cursor_atimer = NULL; - busy_cursor_shown_p = 0; + hourglass_atimer = NULL; + hourglass_shown_p = 0; defsubr (&Sx_show_tip); defsubr (&Sx_hide_tip);