X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/0af913d7b6948157d69db11d5f9c80dc5d92ee3f..3c53a3cf83c218772d9bcfde4cd60c1face33e93:/src/xfns.c diff --git a/src/xfns.c b/src/xfns.c index 2460e16bba..8fc083510f 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 @@ -107,10 +111,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)) @@ -209,6 +218,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 +269,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"); @@ -289,7 +303,7 @@ check_x_display_info (frame) { FRAME_PTR f; - CHECK_LIVE_FRAME (frame, 0); + CHECK_LIVE_FRAME (frame); f = XFRAME (frame); if (! FRAME_X_P (f)) error ("Non-X frame used"); @@ -635,7 +649,7 @@ 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, 0); if (fd < 0) return -1; emacs_close (fd); @@ -720,9 +734,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 +745,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 +783,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 +828,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. @@ -885,23 +928,33 @@ 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); + + 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 +978,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 +1034,23 @@ x_set_frame_parameters (f, alist) XSETINT (icon_top, 0); } + if (FRAME_VISIBLE_P (f)) + { + /* 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. + If fullscreen is not specified, x_fullscreen_adjust returns + the current parameters and then x_fullscreen_move does nothing. */ + 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 +1153,109 @@ 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)); + + if (win == FRAME_X_DISPLAY_INFO (f)->root_window) + win = FRAME_OUTER_WINDOW (f); - while (1) + /* 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; - XQueryTree (FRAME_X_DISPLAY (f), outer, &tmp_root_window, - &f->output_data.x->parent_desc, - &tmp_children, &tmp_nchildren); + XQueryTree (FRAME_X_DISPLAY (f), win, &rootw, + &wm_window, &tmp_children, &tmp_nchildren); XFree ((char *) tmp_children); - 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; + 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), - x_uncatch_errors (FRAME_X_DISPLAY (f), count); + /* 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); } - *xptr = win_x; - *yptr = win_y; + 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 = real_x; + *yptr = real_y; } /* Insert a description of internally-recorded parameters of frame X @@ -1176,6 +1290,14 @@ 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, + make_number (FRAME_HAS_VERTICAL_SCROLL_BARS (f) + ? FRAME_SCROLL_BAR_PIXEL_WIDTH(f) + : 0)); sprintf (buf, "%ld", (long) FRAME_X_WINDOW (f)); store_in_alist (alistptr, Qwindow_id, build_string (buf)); @@ -1257,7 +1379,7 @@ 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 @@ -1304,8 +1426,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 +1493,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 +1531,38 @@ 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); + +#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 +1575,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 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_hourglass_pointer_shape)) + if (!NILP (Vx_hourglass_pointer_shape)) { - CHECK_NUMBER (Vx_hourglass_pointer_shape, 0); - hourglass_cursor = XCreateFontCursor (FRAME_X_DISPLAY (f), - XINT (Vx_hourglass_pointer_shape)); + CHECK_NUMBER (Vx_hourglass_pointer_shape); + hourglass_cursor + = XCreateFontCursor (dpy, XINT (Vx_hourglass_pointer_shape)); } else - hourglass_cursor = XCreateFontCursor (FRAME_X_DISPLAY (f), XC_watch); - x_check_errors (FRAME_X_DISPLAY (f), "bad hourglass 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_crosshair); 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), hourglass_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 (hourglass_cursor != f->output_data.x->hourglass_cursor - && f->output_data.x->hourglass_cursor != 0) - XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->hourglass_cursor); - f->output_data.x->hourglass_cursor = hourglass_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 +1722,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 +1731,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 +1745,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 +1753,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 +1802,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); @@ -1814,8 +1979,9 @@ 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); @@ -1831,8 +1997,16 @@ x_set_font (f, arg, oldval) 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 +2027,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 +2058,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 +2077,8 @@ x_set_internal_border_width (f, arg, oldval) SET_FRAME_GARBAGED (f); do_pending_window_change (0); } + else + SET_FRAME_GARBAGED (f); } void @@ -2062,6 +2246,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 +2308,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)) { @@ -2232,7 +2433,7 @@ x_set_name (f, name, explicit) 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))) @@ -2350,7 +2551,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)) { @@ -2582,16 +2783,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 +2801,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"); @@ -2666,13 +2867,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"); @@ -2913,9 +3114,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 +3141,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,7 +3154,7 @@ 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, &x, &y, &width, &height); @@ -3032,12 +3233,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 +3251,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 +3284,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 +3312,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 +3324,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; } @@ -3863,8 +4081,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"); @@ -3958,8 +4176,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 +4251,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; @@ -4089,7 +4306,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 +4339,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 +4365,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); @@ -4239,7 +4470,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 +4505,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 +4534,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 +4627,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); @@ -4442,6 +4683,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 +4720,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,14 +4741,14 @@ 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)) return Qt; @@ -4511,14 +4757,14 @@ DEFUN ("xw-color-defined-p", Fxw_color_defined_p, Sxw_color_defined_p, 1, 2, 0, } 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)) { @@ -4534,8 +4780,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 +4803,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 +4833,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 +4847,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 +4861,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 +4875,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 +4891,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 +4905,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 +4920,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 +4940,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 +4953,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 +4966,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 +4979,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 +5014,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 +5057,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 +5130,7 @@ visual_classes[] = {"PseudoColor", PseudoColor}, {"TrueColor", TrueColor}, {"DirectColor", DirectColor}, - NULL + {NULL, 0} }; @@ -4899,7 +5147,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; @@ -4996,7 +5244,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"); @@ -5030,20 +5278,21 @@ 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"); @@ -5080,11 +5329,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 +5368,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 +5381,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); @@ -5261,11 +5510,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 +5556,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, @@ -5393,6 +5654,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 +5768,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 +5801,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; @@ -5669,6 +5935,104 @@ image_ascent (img, face) 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 (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 + img->background_transparent = 0; + + img->background_transparent_valid = 1; + } + + return img->background_transparent; +} /*********************************************************************** @@ -5699,12 +6063,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) @@ -5770,6 +6136,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 +6247,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 +6268,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 +6376,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 +6400,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 +6430,22 @@ lookup_image (f, spec) img->vmargin += abs (img->relief); } - /* Manipulation of the image's mask. */ - if (img->pixmap) + if (! img->background_valid) { - /* `: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 + bg = image_spec_value (img->spec, QCbackground, NULL); + if (!NILP (bg)) { - 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) - { - 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)) - { - 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; @@ -6246,7 +6642,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, 0); if (fd == -1) file_found = Qnil; @@ -6339,8 +6735,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}, @@ -6759,10 +7155,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), @@ -6874,10 +7273,12 @@ 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); @@ -6963,6 +7364,7 @@ enum xpm_keyword_index XPM_HEURISTIC_MASK, XPM_MASK, XPM_COLOR_SYMBOLS, + XPM_BACKGROUND, XPM_LAST }; @@ -6980,7 +7382,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. */ @@ -7597,10 +8000,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 +8326,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 +8347,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 +8363,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 +8378,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 +8435,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'. */ @@ -8264,10 +8634,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 +8706,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 +8755,7 @@ enum png_keyword_index PNG_ALGORITHM, PNG_HEURISTIC_MASK, PNG_MASK, + PNG_BACKGROUND, PNG_LAST }; @@ -8391,7 +8772,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'. */ @@ -8662,12 +9044,31 @@ png_load (f, img) 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, XSTRING (specified_bg)->data, &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 +9181,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 +9205,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 +9215,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 +9272,7 @@ enum jpeg_keyword_index JPEG_ALGORITHM, JPEG_HEURISTIC_MASK, JPEG_MASK, + JPEG_BACKGROUND, JPEG_LAST }; @@ -8868,7 +9289,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'. */ @@ -9167,6 +9589,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 +9633,7 @@ enum tiff_keyword_index TIFF_ALGORITHM, TIFF_HEURISTIC_MASK, TIFF_MASK, + TIFF_BACKGROUND, TIFF_LAST }; @@ -9223,7 +9650,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 +9800,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 +9851,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 */ @@ -9484,14 +9943,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 +9993,7 @@ enum gif_keyword_index GIF_HEURISTIC_MASK, GIF_MASK, GIF_IMAGE, + GIF_BACKGROUND, GIF_LAST }; @@ -9547,7 +10011,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'. */ @@ -9795,6 +10260,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 +10309,7 @@ enum gs_keyword_index GS_ALGORITHM, GS_HEURISTIC_MASK, GS_MASK, + GS_BACKGROUND, GS_LAST }; @@ -9859,7 +10329,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 +10486,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 +10549,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,17 +10565,17 @@ 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); @@ -10112,15 +10593,15 @@ 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); XDeleteProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), prop_atom); @@ -10135,11 +10616,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,7 +10632,7 @@ 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); rc = XGetWindowProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), @@ -10171,7 +10652,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); @@ -10364,9 +10845,9 @@ hide_hourglass () ***********************************************************************/ 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. */ @@ -10383,6 +10864,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) @@ -10402,7 +10887,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 @@ -10410,9 +10896,9 @@ 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; @@ -10423,6 +10909,8 @@ x_create_tip_frame (dpyinfo, parms) 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 (); @@ -10448,6 +10936,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); @@ -10462,6 +10960,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 @@ -10707,13 +11209,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; @@ -10727,46 +11231,65 @@ 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; @@ -10779,22 +11302,22 @@ DY added (default is -10).") 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); @@ -10820,9 +11343,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; } @@ -10850,26 +11374,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); @@ -10911,11 +11445,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; @@ -10938,9 +11472,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; @@ -10975,9 +11509,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); @@ -11012,13 +11546,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; @@ -11028,15 +11577,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; 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); @@ -11064,6 +11611,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); @@ -11115,10 +11664,18 @@ selection dialog's entry field, if MUSTMATCH is non-nil.") XmListSetPos (list, item_pos); } - /* Process events until the user presses Cancel or OK. */ + /* Process events until the user presses Cancel or OK. Block + and unblock input here so that we get a chance of processing + expose events. */ + UNBLOCK_INPUT; result = 0; - while (result == 0 || XtAppPending (Xt_app_con)) - XtAppProcessEvent (Xt_app_con, XtIMAll); + while (result == 0) + { + BLOCK_INPUT; + XtAppProcessEvent (Xt_app_con, XtIMAll); + UNBLOCK_INPUT; + } + BLOCK_INPUT; /* Get the result. */ if (result == XmCR_OK) @@ -11163,11 +11720,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 @@ -11210,8 +11767,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) @@ -11325,6 +11883,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. */ @@ -11358,124 +11926,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 bitmap files for X. */); 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-hourglass-pointer-shape", &Vx_hourglass_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."); + 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-hourglass", &display_hourglass_p, - "Non-zero means Emacs displays an hourglass pointer on window systems."); + doc: /* Non-zero means Emacs displays an hourglass pointer on window systems. */); display_hourglass_p = 1; DEFVAR_LISP ("hourglass-delay", &Vhourglass_delay, - "*Seconds to wait before displaying an hourglass pointer.\n\ -Value must be an integer or float."); + 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);