X-Git-Url: http://git.hcoop.net/bpt/emacs.git/blobdiff_plain/adda530bc8492f7207d2c6dd4fdd27d264910f0b..7c402969951c97a2d878c16f7f4c18152258e1f9:/src/w32fns.c diff --git a/src/w32fns.c b/src/w32fns.c index f202eae18e..d8572265be 100644 --- a/src/w32fns.c +++ b/src/w32fns.c @@ -55,8 +55,11 @@ Boston, MA 02111-1307, USA. */ #include #define FILE_NAME_TEXT_FIELD edt1 +void syms_of_w32fns (); +void globals_of_w32fns (); +static void init_external_image_libraries (); + extern void free_frame_menubar (); -extern void x_compute_fringe_widths P_ ((struct frame *, int)); extern double atof (); extern int w32_console_toggle_lock_key P_ ((int, Lisp_Object)); extern void w32_menu_display_help P_ ((HWND, HMENU, UINT, UINT)); @@ -138,9 +141,6 @@ Lisp_Object Vw32_mouse_move_interval; /* Flag to indicate if XBUTTON events should be passed on to Windows. */ int w32_pass_extra_mouse_buttons_to_system; -/* The name we're using in resource queries. */ -Lisp_Object Vx_resource_name; - /* Non nil if no window manager is in use. */ Lisp_Object Vx_no_window_manager; @@ -152,12 +152,16 @@ int display_hourglass_p; over text or in the modeline. */ Lisp_Object Vx_pointer_shape, Vx_nontext_pointer_shape, Vx_mode_pointer_shape; -Lisp_Object Vx_hourglass_pointer_shape, Vx_window_horizontal_drag_shape; +Lisp_Object Vx_hourglass_pointer_shape, Vx_window_horizontal_drag_shape, Vx_hand_shape; /* The shape when over mouse-sensitive text. */ Lisp_Object Vx_sensitive_text_pointer_shape; +#ifndef IDC_HAND +#define IDC_HAND MAKEINTRESOURCE(32649) +#endif + /* Color of chars displayed in cursor box. */ Lisp_Object Vx_cursor_fore_pixel; @@ -192,36 +196,9 @@ Lisp_Object Vw32_charset_info_alist; #define VIETNAMESE_CHARSET 163 #endif -Lisp_Object Qauto_raise; -Lisp_Object Qauto_lower; -Lisp_Object Qborder_color; -Lisp_Object Qborder_width; -extern Lisp_Object Qbox; -Lisp_Object Qcursor_color; -Lisp_Object Qcursor_type; -Lisp_Object Qgeometry; -Lisp_Object Qicon_left; -Lisp_Object Qicon_top; -Lisp_Object Qicon_type; -Lisp_Object Qicon_name; -Lisp_Object Qinternal_border_width; -Lisp_Object Qleft; -Lisp_Object Qright; -Lisp_Object Qmouse_color; Lisp_Object Qnone; -Lisp_Object Qparent_id; -Lisp_Object Qscroll_bar_width; Lisp_Object Qsuppress_icon; Lisp_Object Qundefined_color; -Lisp_Object Qvertical_scroll_bars; -Lisp_Object Qvisibility; -Lisp_Object Qwindow_id; -Lisp_Object Qx_frame_parameter; -Lisp_Object Qx_resource_name; -Lisp_Object Quser_position; -Lisp_Object Quser_size; -Lisp_Object Qscreen_gamma; -Lisp_Object Qline_spacing; Lisp_Object Qcenter; Lisp_Object Qcancel_timer; Lisp_Object Qhyper; @@ -262,13 +239,9 @@ Lisp_Object Qw32_charset_mac; Lisp_Object Qw32_charset_unicode; #endif -Lisp_Object Qfullscreen; -Lisp_Object Qfullwidth; -Lisp_Object Qfullheight; -Lisp_Object Qfullboth; - -extern Lisp_Object Qtop; -extern Lisp_Object Qdisplay; +/* Prefix for system colors. */ +#define SYSTEM_COLOR_PREFIX "System" +#define SYSTEM_COLOR_PREFIX_LEN (sizeof (SYSTEM_COLOR_PREFIX) - 1) /* State variables for emulating a three button mouse. */ #define LMOUSE 1 @@ -284,11 +257,11 @@ static unsigned mouse_move_timer = 0; /* Window that is tracking the mouse. */ static HWND track_mouse_window; -typedef BOOL (WINAPI * TrackMouseEvent_Proc) ( - IN OUT LPTRACKMOUSEEVENT lpEventTrack - ); +typedef BOOL (WINAPI * TrackMouseEvent_Proc) + (IN OUT LPTRACKMOUSEEVENT lpEventTrack); -TrackMouseEvent_Proc track_mouse_event_fn=NULL; +TrackMouseEvent_Proc track_mouse_event_fn = NULL; +ClipboardSequence_Proc clipboard_sequence_fn = NULL; /* W95 mousewheel handler */ unsigned int msh_mousewheel = 0; @@ -304,14 +277,8 @@ static unsigned menu_free_timer = 0; /* The below are defined in frame.c. */ -extern Lisp_Object Qheight, Qminibuffer, Qname, Qonly, Qwidth; -extern Lisp_Object Qunsplittable, Qmenu_bar_lines, Qbuffer_predicate, Qtitle; -extern Lisp_Object Qtool_bar_lines; - extern Lisp_Object Vwindow_system_version; -Lisp_Object Qface_set_after_frame_default; - #ifdef GLYPH_DEBUG int image_cache_refcount, dpyinfo_refcount; #endif @@ -370,7 +337,7 @@ check_x_frame (frame) nil stands for the selected frame--or, if that is not a w32 frame, the first display on the list. */ -static struct w32_display_info * +struct w32_display_info * check_x_display_info (frame) Lisp_Object frame; { @@ -647,48 +614,13 @@ x_destroy_all_bitmaps (dpyinfo) dpyinfo->bitmaps_last = 0; } -/* Connect the frame-parameter names for W32 frames - to the ways of passing the parameter values to the window system. - - The name of a parameter, as a Lisp symbol, - has an `x-frame-parameter' property which is an integer in Lisp - but can be interpreted as an `enum x_frame_parm' in C. */ - -enum x_frame_parm -{ - X_PARM_FOREGROUND_COLOR, - X_PARM_BACKGROUND_COLOR, - X_PARM_MOUSE_COLOR, - X_PARM_CURSOR_COLOR, - X_PARM_BORDER_COLOR, - X_PARM_ICON_TYPE, - X_PARM_FONT, - X_PARM_BORDER_WIDTH, - X_PARM_INTERNAL_BORDER_WIDTH, - X_PARM_NAME, - X_PARM_AUTORAISE, - X_PARM_AUTOLOWER, - X_PARM_VERT_SCROLL_BAR, - X_PARM_VISIBILITY, - X_PARM_MENU_BAR_LINES -}; - - -struct x_frame_parm_table -{ - char *name; - void (*setter) P_ ((struct frame *, Lisp_Object, Lisp_Object)); -}; - BOOL my_show_window P_ ((struct frame *, HWND, int)); void my_set_window_pos P_ ((HWND, HWND, int, int, int, int, UINT)); 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)); + /* TODO: Native Input Method support; see x_create_im. */ 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_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)); @@ -696,380 +628,15 @@ 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)); -void x_set_font P_ ((struct frame *, Lisp_Object, Lisp_Object)); -static void x_set_fringe_width 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, - Lisp_Object)); void x_explicitly_set_name P_ ((struct frame *, Lisp_Object, Lisp_Object)); -void x_set_autoraise P_ ((struct frame *, Lisp_Object, Lisp_Object)); -void x_set_autolower P_ ((struct frame *, Lisp_Object, Lisp_Object)); -void x_set_vertical_scroll_bars P_ ((struct frame *, Lisp_Object, - Lisp_Object)); -void x_set_visibility P_ ((struct frame *, Lisp_Object, Lisp_Object)); void x_set_menu_bar_lines P_ ((struct frame *, Lisp_Object, Lisp_Object)); -void x_set_scroll_bar_width P_ ((struct frame *, Lisp_Object, Lisp_Object)); void x_set_title P_ ((struct frame *, Lisp_Object, Lisp_Object)); -void x_set_unsplittable P_ ((struct frame *, Lisp_Object, Lisp_Object)); void x_set_tool_bar_lines P_ ((struct frame *, Lisp_Object, Lisp_Object)); -static void x_set_screen_gamma P_ ((struct frame *, Lisp_Object, Lisp_Object)); static void x_edge_detection P_ ((struct frame *, struct image *, Lisp_Object, Lisp_Object)); -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}, - {"screen-gamma", x_set_screen_gamma}, - {"line-spacing", x_set_line_spacing}, - {"left-fringe", x_set_fringe_width}, - {"right-fringe", x_set_fringe_width}, - {"fullscreen", x_set_fullscreen}, -}; - -/* Attach the `x-frame-parameter' properties to - the Lisp symbol names of parameters relevant to W32. */ - -void -init_x_parm_symbols () -{ - int i; - for (i = 0; i < sizeof (x_frame_parms) / sizeof (x_frame_parms[0]); i++) - Fput (intern (x_frame_parms[i].name), Qx_frame_parameter, - 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.w32->top_pos - || new_left != f->output_data.w32->left_pos) - { - int move_x = new_left; - int move_y = new_top; - - f->output_data.w32->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; - otherwise call the `x_set_...' function for that parameter. */ - -void -x_set_frame_parameters (f, alist) - FRAME_PTR f; - Lisp_Object alist; -{ - Lisp_Object tail; - - /* If both of these parameters are present, it's more efficient to - set them both at once. So we wait until we've looked at the - entire list before we set them. */ - int width, height; - - /* Same here. */ - Lisp_Object left, top; - - /* Same with these. */ - Lisp_Object icon_left, icon_top; - - /* Record in these vectors all the parms specified. */ - Lisp_Object *parms; - Lisp_Object *values; - int i, p; - int left_no_change = 0, top_no_change = 0; - int icon_left_no_change = 0, icon_top_no_change = 0; - int fullscreen_is_being_set = 0; - - struct gcpro gcpro1, gcpro2; - - i = 0; - for (tail = alist; CONSP (tail); tail = Fcdr (tail)) - i++; - - parms = (Lisp_Object *) alloca (i * sizeof (Lisp_Object)); - values = (Lisp_Object *) alloca (i * sizeof (Lisp_Object)); - - /* Extract parm names and values into those vectors. */ - - i = 0; - for (tail = alist; CONSP (tail); tail = Fcdr (tail)) - { - Lisp_Object elt; - - elt = Fcar (tail); - parms[i] = Fcar (elt); - values[i] = Fcdr (elt); - i++; - } - /* TAIL and ALIST are not used again below here. */ - alist = tail = Qnil; - - GCPRO2 (*parms, *values); - gcpro1.nvars = i; - gcpro2.nvars = i; - - /* There is no need to gcpro LEFT, TOP, ICON_LEFT, or ICON_TOP, - because their values appear in VALUES and strings are not valid. */ - top = left = Qunbound; - icon_left = icon_top = Qunbound; - - /* Provide default values for HEIGHT and WIDTH. */ - if (FRAME_NEW_WIDTH (f)) - width = FRAME_NEW_WIDTH (f); - else - width = FRAME_WIDTH (f); - - if (FRAME_NEW_HEIGHT (f)) - height = FRAME_NEW_HEIGHT (f); - else - height = FRAME_HEIGHT (f); - - /* 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. */ - 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) - || EQ (prop, Qfont) - || EQ (prop, Qfullscreen)) - { - register Lisp_Object param_index, old_value; - - old_value = get_frame_param (f, prop); - fullscreen_is_being_set |= EQ (prop, Qfullscreen); - - if (NILP (Fequal (val, old_value))) - { - store_frame_param (f, prop, val); - - param_index = Fget (prop, Qx_frame_parameter); - if (NATNUMP (param_index) - && (XFASTINT (param_index) - < sizeof (x_frame_parms)/sizeof (x_frame_parms[0]))) - (*x_frame_parms[XINT (param_index)].setter)(f, val, old_value); - } - } - } - - /* Now process them in reverse of specified order. */ - for (i--; i >= 0; i--) - { - Lisp_Object prop, val; - - prop = parms[i]; - val = values[i]; - - if (EQ (prop, Qwidth) && NUMBERP (val)) - width = XFASTINT (val); - else if (EQ (prop, Qheight) && NUMBERP (val)) - height = XFASTINT (val); - else if (EQ (prop, Qtop)) - top = val; - else if (EQ (prop, Qleft)) - left = val; - else if (EQ (prop, Qicon_top)) - icon_top = val; - else if (EQ (prop, Qicon_left)) - icon_left = val; - 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; - - old_value = get_frame_param (f, prop); - - 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); - } - } - - /* Don't die if just one of these was set. */ - if (EQ (left, Qunbound)) - { - left_no_change = 1; - if (f->output_data.w32->left_pos < 0) - left = Fcons (Qplus, Fcons (make_number (f->output_data.w32->left_pos), Qnil)); - else - XSETINT (left, f->output_data.w32->left_pos); - } - if (EQ (top, Qunbound)) - { - top_no_change = 1; - if (f->output_data.w32->top_pos < 0) - top = Fcons (Qplus, Fcons (make_number (f->output_data.w32->top_pos), Qnil)); - else - XSETINT (top, f->output_data.w32->top_pos); - } - - /* If one of the icon positions was not set, preserve or default it. */ - if (EQ (icon_left, Qunbound) || ! INTEGERP (icon_left)) - { - icon_left_no_change = 1; - icon_left = Fcdr (Fassq (Qicon_left, f->param_alist)); - if (NILP (icon_left)) - XSETINT (icon_left, 0); - } - if (EQ (icon_top, Qunbound) || ! INTEGERP (icon_top)) - { - icon_top_no_change = 1; - icon_top = Fcdr (Fassq (Qicon_top, f->param_alist)); - if (NILP (icon_top)) - XSETINT (icon_top, 0); - } - - if (FRAME_VISIBLE_P (f) && fullscreen_is_being_set) - { - /* If the frame is visible already and the fullscreen parameter is - being set, it is too late to set WM manager hints to specify - size and position. - Here we first get the width, height and position that applies to - fullscreen. We then move the frame to the appropriate - position. Resize of the frame is taken care of in the code after - this if-statement. */ - int new_left, new_top; - - x_fullscreen_adjust (f, &width, &height, &new_top, &new_left); - x_fullscreen_move (f, new_top, new_left); - } - - /* Don't set these parameters unless they've been explicitly - specified. The window might be mapped or resized while we're in - this function, and we don't want to override that unless the lisp - code has asked for it. - - Don't set these parameters unless they actually differ from the - window's current parameters; the window may not actually exist - yet. */ - { - Lisp_Object frame; - - check_frame_size (f, &height, &width); - - XSETFRAME (frame, f); - - if (width != FRAME_WIDTH (f) - || height != FRAME_HEIGHT (f) - || FRAME_NEW_HEIGHT (f) || FRAME_NEW_WIDTH (f)) - Fset_frame_size (frame, make_number (width), make_number (height)); - - if ((!NILP (left) || !NILP (top)) - && ! (left_no_change && top_no_change) - && ! (NUMBERP (left) && XINT (left) == f->output_data.w32->left_pos - && NUMBERP (top) && XINT (top) == f->output_data.w32->top_pos)) - { - int leftpos = 0; - int toppos = 0; - - /* Record the signs. */ - f->output_data.w32->size_hint_flags &= ~ (XNegative | YNegative); - if (EQ (left, Qminus)) - f->output_data.w32->size_hint_flags |= XNegative; - else if (INTEGERP (left)) - { - leftpos = XINT (left); - if (leftpos < 0) - f->output_data.w32->size_hint_flags |= XNegative; - } - else if (CONSP (left) && EQ (XCAR (left), Qminus) - && CONSP (XCDR (left)) - && INTEGERP (XCAR (XCDR (left)))) - { - leftpos = - XINT (XCAR (XCDR (left))); - f->output_data.w32->size_hint_flags |= XNegative; - } - else if (CONSP (left) && EQ (XCAR (left), Qplus) - && CONSP (XCDR (left)) - && INTEGERP (XCAR (XCDR (left)))) - { - leftpos = XINT (XCAR (XCDR (left))); - } - - if (EQ (top, Qminus)) - f->output_data.w32->size_hint_flags |= YNegative; - else if (INTEGERP (top)) - { - toppos = XINT (top); - if (toppos < 0) - f->output_data.w32->size_hint_flags |= YNegative; - } - else if (CONSP (top) && EQ (XCAR (top), Qminus) - && CONSP (XCDR (top)) - && INTEGERP (XCAR (XCDR (top)))) - { - toppos = - XINT (XCAR (XCDR (top))); - f->output_data.w32->size_hint_flags |= YNegative; - } - else if (CONSP (top) && EQ (XCAR (top), Qplus) - && CONSP (XCDR (top)) - && INTEGERP (XCAR (XCDR (top)))) - { - toppos = XINT (XCAR (XCDR (top))); - } - - - /* Store the numeric value of the position. */ - f->output_data.w32->top_pos = toppos; - f->output_data.w32->left_pos = leftpos; - - f->output_data.w32->win_gravity = NorthWestGravity; - - /* Actually set that position, and convert to absolute. */ - x_set_offset (f, leftpos, toppos, -1); - } - - if ((!NILP (icon_left) || !NILP (icon_top)) - && ! (icon_left_no_change && icon_top_no_change)) - x_wm_set_icon_position (f, XINT (icon_left), XINT (icon_top)); - } - - UNGCPRO; -} /* Store the screen positions of frame F into XPTR and YPTR. These are the positions of the containing window manager window, @@ -1092,64 +659,13 @@ x_real_positions (f, xptr, yptr) ClientToScreen (FRAME_W32_WINDOW(f), &pt); /* Remember x_pixels_diff and y_pixels_diff. */ - f->output_data.w32->x_pixels_diff = pt.x - rect.left; - f->output_data.w32->y_pixels_diff = pt.y - rect.top; + f->x_pixels_diff = pt.x - rect.left; + f->y_pixels_diff = pt.y - rect.top; *xptr = pt.x; *yptr = pt.y; } -/* Insert a description of internally-recorded parameters of frame X - into the parameter alist *ALISTPTR that is to be given to the user. - Only parameters that are specific to W32 - and whose values are not correctly recorded in the frame's - param_alist need to be considered here. */ - -void -x_report_frame_params (f, alistptr) - struct frame *f; - Lisp_Object *alistptr; -{ - char buf[16]; - Lisp_Object tem; - - /* Represent negative positions (off the top or left screen edge) - in a way that Fmodify_frame_parameters will understand correctly. */ - XSETINT (tem, f->output_data.w32->left_pos); - if (f->output_data.w32->left_pos >= 0) - store_in_alist (alistptr, Qleft, tem); - else - store_in_alist (alistptr, Qleft, Fcons (Qplus, Fcons (tem, Qnil))); - - XSETINT (tem, f->output_data.w32->top_pos); - if (f->output_data.w32->top_pos >= 0) - store_in_alist (alistptr, Qtop, tem); - else - store_in_alist (alistptr, Qtop, Fcons (Qplus, Fcons (tem, Qnil))); - - store_in_alist (alistptr, Qborder_width, - make_number (f->output_data.w32->border_width)); - store_in_alist (alistptr, Qinternal_border_width, - make_number (f->output_data.w32->internal_border_width)); - store_in_alist (alistptr, Qleft_fringe, - make_number (f->output_data.w32->left_fringe_width)); - store_in_alist (alistptr, Qright_fringe, - make_number (f->output_data.w32->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_W32_WINDOW (f)); - store_in_alist (alistptr, Qwindow_id, - build_string (buf)); - store_in_alist (alistptr, Qicon_name, f->icon_name); - FRAME_SAMPLE_VISIBILITY (f); - store_in_alist (alistptr, Qvisibility, - (FRAME_VISIBLE_P (f) ? Qt - : FRAME_ICONIFIED_P (f) ? Qicon : Qnil)); - store_in_alist (alistptr, Qdisplay, - XCAR (FRAME_W32_DISPLAY_INFO (f)->name_list_element)); -} DEFUN ("w32-define-rgb-color", Fw32_define_rgb_color, @@ -1565,6 +1081,56 @@ w32_color_map_lookup (colorname) return ret; } + +static void +add_system_logical_colors_to_map (system_colors) + Lisp_Object *system_colors; +{ + HKEY colors_key; + + /* Other registry operations are done with input blocked. */ + BLOCK_INPUT; + + /* Look for "Control Panel/Colors" under User and Machine registry + settings. */ + if (RegOpenKeyEx (HKEY_CURRENT_USER, "Control Panel\\Colors", 0, + KEY_READ, &colors_key) == ERROR_SUCCESS + || RegOpenKeyEx (HKEY_LOCAL_MACHINE, "Control Panel\\Colors", 0, + KEY_READ, &colors_key) == ERROR_SUCCESS) + { + /* List all keys. */ + char color_buffer[64]; + char full_name_buffer[MAX_PATH + SYSTEM_COLOR_PREFIX_LEN]; + int index = 0; + DWORD name_size, color_size; + char *name_buffer = full_name_buffer + SYSTEM_COLOR_PREFIX_LEN; + + name_size = sizeof (full_name_buffer) - SYSTEM_COLOR_PREFIX_LEN; + color_size = sizeof (color_buffer); + + strcpy (full_name_buffer, SYSTEM_COLOR_PREFIX); + + while (RegEnumValueA (colors_key, index, name_buffer, &name_size, + NULL, NULL, color_buffer, &color_size) + == ERROR_SUCCESS) + { + int r, g, b; + if (sscanf (color_buffer, " %u %u %u", &r, &g, &b) == 3) + *system_colors = Fcons (Fcons (build_string (full_name_buffer), + make_number (RGB (r, g, b))), + *system_colors); + + name_size = sizeof (full_name_buffer) - SYSTEM_COLOR_PREFIX_LEN; + color_size = sizeof (color_buffer); + index++; + } + RegCloseKey (colors_key); + } + + UNBLOCK_INPUT; +} + + COLORREF x_to_w32_color (colorname) char * colorname; @@ -1756,7 +1322,6 @@ x_to_w32_color (colorname) return ret; } - void w32_regenerate_palette (FRAME_PTR f) { @@ -1997,64 +1562,6 @@ x_decode_color (f, arg, def) return def; } -/* Change the `line-spacing' frame parameter of frame F. OLD_VALUE is - the previous value of that parameter, NEW_VALUE is the new value. */ - -static void -x_set_line_spacing (f, new_value, old_value) - struct frame *f; - Lisp_Object new_value, old_value; -{ - if (NILP (new_value)) - f->extra_line_spacing = 0; - else if (NATNUMP (new_value)) - f->extra_line_spacing = XFASTINT (new_value); - else - Fsignal (Qerror, Fcons (build_string ("Invalid line-spacing"), - Fcons (new_value, Qnil))); - if (FRAME_VISIBLE_P (f)) - redraw_frame (f); -} - - -/* 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.w32->want_fullscreen = FULLSCREEN_NONE; - else if (EQ (new_value, Qfullboth)) - f->output_data.w32->want_fullscreen = FULLSCREEN_BOTH; - else if (EQ (new_value, Qfullwidth)) - f->output_data.w32->want_fullscreen = FULLSCREEN_WIDTH; - else if (EQ (new_value, Qfullheight)) - f->output_data.w32->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. */ - -static void -x_set_screen_gamma (f, new_value, old_value) - struct frame *f; - Lisp_Object new_value, old_value; -{ - if (NILP (new_value)) - f->gamma = 0; - else if (NUMBERP (new_value) && XFLOATINT (new_value) > 0) - /* The value 0.4545 is the normal viewing gamma. */ - f->gamma = 1.0 / (0.4545 * XFLOATINT (new_value)); - else - Fsignal (Qerror, Fcons (build_string ("Invalid screen-gamma"), - Fcons (new_value, Qnil))); - - clear_face_cache (0); -} /* Functions called only from `x_set_frame_param' @@ -2113,7 +1620,7 @@ x_set_mouse_color (f, arg, oldval) struct frame *f; Lisp_Object arg, oldval; { - Cursor cursor, nontext_cursor, mode_cursor, cross_cursor; + Cursor cursor, nontext_cursor, mode_cursor, hand_cursor; int count; int mask_color; @@ -2176,12 +1683,12 @@ x_set_mouse_color (f, arg, oldval) if (!EQ (Qnil, Vx_sensitive_text_pointer_shape)) { CHECK_NUMBER (Vx_sensitive_text_pointer_shape); - cross_cursor + hand_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XINT (Vx_sensitive_text_pointer_shape)); } else - cross_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_crosshair); + hand_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_crosshair); if (!NILP (Vx_window_horizontal_drag_shape)) { @@ -2217,7 +1724,7 @@ x_set_mouse_color (f, arg, oldval) &fore_color, &back_color); XRecolorCursor (FRAME_W32_DISPLAY (f), mode_cursor, &fore_color, &back_color); - XRecolorCursor (FRAME_W32_DISPLAY (f), cross_cursor, + XRecolorCursor (FRAME_W32_DISPLAY (f), hand_cursor, &fore_color, &back_color); XRecolorCursor (FRAME_W32_DISPLAY (f), hourglass_cursor, &fore_color, &back_color); @@ -2245,10 +1752,10 @@ x_set_mouse_color (f, arg, oldval) XFreeCursor (FRAME_W32_DISPLAY (f), f->output_data.w32->modeline_cursor); f->output_data.w32->modeline_cursor = mode_cursor; - if (cross_cursor != f->output_data.w32->cross_cursor - && f->output_data.w32->cross_cursor != 0) - XFreeCursor (FRAME_W32_DISPLAY (f), f->output_data.w32->cross_cursor); - f->output_data.w32->cross_cursor = cross_cursor; + if (hand_cursor != f->output_data.w32->hand_cursor + && f->output_data.w32->hand_cursor != 0) + XFreeCursor (FRAME_W32_DISPLAY (f), f->output_data.w32->hand_cursor); + f->output_data.w32->hand_cursor = hand_cursor; XFlush (FRAME_W32_DISPLAY (f)); UNBLOCK_INPUT; @@ -2258,8 +1765,6 @@ x_set_mouse_color (f, arg, oldval) } /* Defined in w32term.c. */ -void x_update_cursor (struct frame *f, int on_p); - void x_set_cursor_color (f, arg, oldval) struct frame *f; @@ -2308,14 +1813,16 @@ x_set_cursor_color (f, arg, oldval) /* Set the border-color of frame F to pixel value PIX. Note that this does not fully take effect if done before F has a window. */ + void x_set_border_pixel (f, pix) struct frame *f; int pix; { + f->output_data.w32->border_pixel = pix; - if (FRAME_W32_WINDOW (f) != 0 && f->output_data.w32->border_width > 0) + if (FRAME_W32_WINDOW (f) != 0 && f->border_width > 0) { if (FRAME_VISIBLE_P (f)) redraw_frame (f); @@ -2349,9 +1856,8 @@ x_set_cursor_type (f, arg, oldval) { set_frame_cursor_types (f, arg); - /* Make sure the cursor gets redrawn. This is overkill, but how - often do people change cursor types? */ - update_mode_lines++; + /* Make sure the cursor gets redrawn. */ + cursor_type_changed = 1; } void @@ -2383,21 +1889,6 @@ x_set_icon_type (f, arg, oldval) UNBLOCK_INPUT; } -/* Return non-nil if frame F wants a bitmap icon. */ - -Lisp_Object -x_icon_type (f) - FRAME_PTR f; -{ - Lisp_Object tem; - - tem = assq_no_quit (Qicon_type, f->param_alist); - if (CONSP (tem)) - return XCDR (tem); - else - return Qnil; -} - void x_set_icon_name (f, arg, oldval) struct frame *f; @@ -2447,160 +1938,7 @@ x_set_icon_name (f, arg, oldval) #endif } -extern Lisp_Object x_new_font (); -extern Lisp_Object x_new_fontset(); - -void -x_set_font (f, arg, oldval) - struct frame *f; - Lisp_Object arg, oldval; -{ - Lisp_Object result; - Lisp_Object fontset_name; - Lisp_Object frame; - int old_fontset = FRAME_FONTSET(f); - - CHECK_STRING (arg); - - fontset_name = Fquery_fontset (arg, Qnil); - - BLOCK_INPUT; - result = (STRINGP (fontset_name) - ? x_new_fontset (f, SDATA (fontset_name)) - : x_new_font (f, SDATA (arg))); - UNBLOCK_INPUT; - - if (EQ (result, Qnil)) - error ("Font `%s' is not defined", SDATA (arg)); - else if (EQ (result, Qt)) - error ("The characters of the given font have varying widths"); - else if (STRINGP (result)) - { - 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 == FRAME_FONTSET (f)) - return; - } - else if (!NILP (Fequal (result, oldval))) - return; - - store_frame_param (f, Qfont, result); - recompute_basic_faces (f); - } - else - abort (); - - do_pending_window_change (0); - - /* Don't call `face-set-after-frame-default' when faces haven't been - initialized yet. This is the case when called from - Fx_create_frame. In that case, the X widget or window doesn't - exist either, and we can end up in x_report_frame_params with a - null widget which gives a segfault. */ - if (FRAME_FACE_CACHE (f)) - { - XSETFRAME (frame, f); - call1 (Qface_set_after_frame_default, frame); - } -} - -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); - - if (XINT (arg) == f->output_data.w32->border_width) - return; - - if (FRAME_W32_WINDOW (f) != 0) - error ("Cannot change the border width of a window"); - - f->output_data.w32->border_width = XINT (arg); -} - -void -x_set_internal_border_width (f, arg, oldval) - struct frame *f; - Lisp_Object arg, oldval; -{ - int old = f->output_data.w32->internal_border_width; - - CHECK_NUMBER (arg); - f->output_data.w32->internal_border_width = XINT (arg); - if (f->output_data.w32->internal_border_width < 0) - f->output_data.w32->internal_border_width = 0; - - if (f->output_data.w32->internal_border_width == old) - return; - - if (FRAME_W32_WINDOW (f) != 0) - { - x_set_window_size (f, 0, f->width, f->height); - SET_FRAME_GARBAGED (f); - do_pending_window_change (0); - } - else - SET_FRAME_GARBAGED (f); -} - -void -x_set_visibility (f, value, oldval) - struct frame *f; - Lisp_Object value, oldval; -{ - Lisp_Object frame; - XSETFRAME (frame, f); - - if (NILP (value)) - Fmake_frame_invisible (frame, Qt); - else if (EQ (value, Qicon)) - Ficonify_frame (frame); - else - Fmake_frame_visible (frame); -} - -/* Change window heights in windows rooted in WINDOW by N lines. */ - -static void -x_change_window_heights (window, n) - Lisp_Object window; - int n; -{ - struct window *w = XWINDOW (window); - - XSETFASTINT (w->top, XFASTINT (w->top) + n); - XSETFASTINT (w->height, XFASTINT (w->height) - n); - - if (INTEGERP (w->orig_top)) - XSETFASTINT (w->orig_top, XFASTINT (w->orig_top) + n); - if (INTEGERP (w->orig_height)) - XSETFASTINT (w->orig_height, XFASTINT (w->orig_height) - n); - - /* Handle just the top child in a vertical split. */ - if (!NILP (w->vchild)) - x_change_window_heights (w->vchild, n); - - /* Adjust all children in a horizontal split. */ - for (window = w->hchild; !NILP (window); window = w->next) - { - w = XWINDOW (window); - x_change_window_heights (window, n); - } -} - void x_set_menu_bar_lines (f, value, oldval) struct frame *f; @@ -2633,7 +1971,7 @@ x_set_menu_bar_lines (f, value, oldval) /* Adjust the frame size so that the client (text) dimensions remain the same. This depends on FRAME_EXTERNAL_MENU_BAR being set correctly. */ - x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f)); + x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f)); do_pending_window_change (0); } adjust_glyphs (f); @@ -2671,7 +2009,7 @@ x_set_tool_bar_lines (f, value, oldval) /* Don't resize the tool-bar to more than we have room for. */ root_window = FRAME_ROOT_WINDOW (f); - root_height = XINT (XWINDOW (root_window)->height); + root_height = WINDOW_TOTAL_LINES (XWINDOW (root_window)); if (root_height - delta < 1) { delta = root_height - 1; @@ -2679,7 +2017,7 @@ x_set_tool_bar_lines (f, value, oldval) } FRAME_TOOL_BAR_LINES (f) = nlines; - x_change_window_heights (root_window, delta); + change_window_heights (root_window, delta); adjust_glyphs (f); /* We also have to make sure that the internal border at the top of @@ -2702,8 +2040,8 @@ x_set_tool_bar_lines (f, value, oldval) if (delta < 0) { int height = FRAME_INTERNAL_BORDER_WIDTH (f); - int width = PIXEL_WIDTH (f); - int y = nlines * CANON_Y_UNIT (f); + int width = FRAME_PIXEL_WIDTH (f); + int y = nlines * FRAME_LINE_HEIGHT (f); BLOCK_INPUT; { @@ -2844,268 +2182,21 @@ x_set_title (f, name, old_name) UNBLOCK_INPUT; } } - -void -x_set_autoraise (f, arg, oldval) - struct frame *f; - Lisp_Object arg, oldval; -{ - f->auto_raise = !EQ (Qnil, arg); -} -void -x_set_autolower (f, arg, oldval) - struct frame *f; - Lisp_Object arg, oldval; -{ - f->auto_lower = !EQ (Qnil, arg); -} -void -x_set_unsplittable (f, arg, oldval) +void x_set_scroll_bar_default_width (f) struct frame *f; - Lisp_Object arg, oldval; { - f->no_split = !NILP (arg); -} + int wid = FRAME_COLUMN_WIDTH (f); -void -x_set_vertical_scroll_bars (f, arg, oldval) - struct frame *f; - Lisp_Object arg, oldval; -{ - if ((EQ (arg, Qleft) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f)) - || (EQ (arg, Qright) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f)) - || (NILP (arg) && FRAME_HAS_VERTICAL_SCROLL_BARS (f)) - || (!NILP (arg) && ! FRAME_HAS_VERTICAL_SCROLL_BARS (f))) - { - FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = NILP (arg) ? - vertical_scroll_bar_none : - /* Put scroll bars on the right by default, as is conventional - on MS-Windows. */ - EQ (Qleft, arg) - ? vertical_scroll_bar_left - : vertical_scroll_bar_right; - - /* We set this parameter before creating the window for the - frame, so we can get the geometry right from the start. - However, if the window hasn't been created yet, we shouldn't - call x_set_window_size. */ - if (FRAME_W32_WINDOW (f)) - x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f)); - do_pending_window_change (0); - } + FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = GetSystemMetrics (SM_CXVSCROLL); + FRAME_CONFIG_SCROLL_BAR_COLS (f) = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + + wid - 1) / wid; } -void -x_set_scroll_bar_width (f, arg, oldval) - struct frame *f; - Lisp_Object arg, oldval; -{ - int wid = FONT_WIDTH (f->output_data.w32->font); - - if (NILP (arg)) - { - FRAME_SCROLL_BAR_PIXEL_WIDTH (f) = GetSystemMetrics (SM_CXVSCROLL); - FRAME_SCROLL_BAR_COLS (f) = (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) + - wid - 1) / wid; - if (FRAME_W32_WINDOW (f)) - x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f)); - do_pending_window_change (0); - } - else if (INTEGERP (arg) && XINT (arg) > 0 - && XFASTINT (arg) != FRAME_SCROLL_BAR_PIXEL_WIDTH (f)) - { - FRAME_SCROLL_BAR_PIXEL_WIDTH (f) = XFASTINT (arg); - FRAME_SCROLL_BAR_COLS (f) = (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) - + wid-1) / wid; - if (FRAME_W32_WINDOW (f)) - x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f)); - do_pending_window_change (0); - } - change_frame_size (f, 0, FRAME_WIDTH (f), 0, 0, 0); - XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.hpos = 0; - XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.x = 0; -} /* Subroutines of creating a frame. */ -/* Make sure that Vx_resource_name is set to a reasonable value. - Fix it up, or set it to `emacs' if it is too hopeless. */ - -static void -validate_x_resource_name () -{ - int len = 0; - /* Number of valid characters in the resource name. */ - int good_count = 0; - /* Number of invalid characters in the resource name. */ - int bad_count = 0; - Lisp_Object new; - int i; - - if (STRINGP (Vx_resource_name)) - { - unsigned char *p = SDATA (Vx_resource_name); - int i; - - len = SBYTES (Vx_resource_name); - - /* Only letters, digits, - and _ are valid in resource names. - Count the valid characters and count the invalid ones. */ - for (i = 0; i < len; i++) - { - int c = p[i]; - if (! ((c >= 'a' && c <= 'z') - || (c >= 'A' && c <= 'Z') - || (c >= '0' && c <= '9') - || c == '-' || c == '_')) - bad_count++; - else - good_count++; - } - } - else - /* Not a string => completely invalid. */ - bad_count = 5, good_count = 0; - - /* If name is valid already, return. */ - if (bad_count == 0) - return; - - /* If name is entirely invalid, or nearly so, use `emacs'. */ - if (good_count == 0 - || (good_count == 1 && bad_count > 0)) - { - Vx_resource_name = build_string ("emacs"); - return; - } - - /* Name is partly valid. Copy it and replace the invalid characters - with underscores. */ - - Vx_resource_name = new = Fcopy_sequence (Vx_resource_name); - - for (i = 0; i < len; i++) - { - int c = SREF (new, i); - if (! ((c >= 'a' && c <= 'z') - || (c >= 'A' && c <= 'Z') - || (c >= '0' && c <= '9') - || c == '-' || c == '_')) - SSET (new, i, '_'); - } -} - - -extern char *x_get_string_resource (); - -DEFUN ("x-get-resource", Fx_get_resource, Sx_get_resource, 2, 4, 0, - 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; - char *name_key; - char *class_key; - - CHECK_STRING (attribute); - CHECK_STRING (class); - - if (!NILP (component)) - CHECK_STRING (component); - if (!NILP (subclass)) - CHECK_STRING (subclass); - if (NILP (component) != NILP (subclass)) - error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither"); - - validate_x_resource_name (); - - /* Allocate space for the components, the dots which separate them, - and the final '\0'. Make them big enough for the worst case. */ - name_key = (char *) alloca (SBYTES (Vx_resource_name) - + (STRINGP (component) - ? SBYTES (component) : 0) - + SBYTES (attribute) - + 3); - - class_key = (char *) alloca ((sizeof (EMACS_CLASS) - 1) - + SBYTES (class) - + (STRINGP (subclass) - ? SBYTES (subclass) : 0) - + 3); - - /* Start with emacs.FRAMENAME for the name (the specific one) - and with `Emacs' for the class key (the general one). */ - strcpy (name_key, SDATA (Vx_resource_name)); - strcpy (class_key, EMACS_CLASS); - - strcat (class_key, "."); - strcat (class_key, SDATA (class)); - - if (!NILP (component)) - { - strcat (class_key, "."); - strcat (class_key, SDATA (subclass)); - - strcat (name_key, "."); - strcat (name_key, SDATA (component)); - } - - strcat (name_key, "."); - strcat (name_key, SDATA (attribute)); - - value = x_get_string_resource (Qnil, - name_key, class_key); - - if (value != (char *) 0) - return build_string (value); - else - return Qnil; -} - -/* Used when C code wants a resource value. */ - -char * -x_get_resource_string (attribute, class) - char *attribute, *class; -{ - char *name_key; - char *class_key; - struct frame *sf = SELECTED_FRAME (); - - /* Allocate space for the components, the dots which separate them, - and the final '\0'. */ - name_key = (char *) alloca (SBYTES (Vinvocation_name) - + strlen (attribute) + 2); - class_key = (char *) alloca ((sizeof (EMACS_CLASS) - 1) - + strlen (class) + 2); - - sprintf (name_key, "%s.%s", - SDATA (Vinvocation_name), - attribute); - sprintf (class_key, "%s.%s", EMACS_CLASS, class); - - return x_get_string_resource (sf, name_key, class_key); -} - -/* Types we might convert a resource string into. */ -enum resource_types -{ - RES_TYPE_NUMBER, - RES_TYPE_FLOAT, - RES_TYPE_BOOLEAN, - RES_TYPE_STRING, - RES_TYPE_SYMBOL -}; /* Return the value of parameter PARAM. @@ -3125,299 +2216,27 @@ w32_get_arg (alist, param, attribute, class, type) char *class; enum resource_types type; { - register Lisp_Object tem; - - tem = Fassq (param, alist); - if (EQ (tem, Qnil)) - tem = Fassq (param, Vdefault_frame_alist); - if (EQ (tem, Qnil)) - { - - if (attribute) - { - tem = Fx_get_resource (build_string (attribute), - build_string (class), - Qnil, Qnil); - - if (NILP (tem)) - return Qunbound; - - switch (type) - { - case RES_TYPE_NUMBER: - return make_number (atoi (SDATA (tem))); - - case RES_TYPE_FLOAT: - return make_float (atof (SDATA (tem))); - - case RES_TYPE_BOOLEAN: - tem = Fdowncase (tem); - if (!strcmp (SDATA (tem), "on") - || !strcmp (SDATA (tem), "true")) - return Qt; - else - return Qnil; - - case RES_TYPE_STRING: - return tem; - - case RES_TYPE_SYMBOL: - /* As a special case, we map the values `true' and `on' - to Qt, and `false' and `off' to Qnil. */ - { - Lisp_Object lower; - lower = Fdowncase (tem); - if (!strcmp (SDATA (lower), "on") - || !strcmp (SDATA (lower), "true")) - return Qt; - else if (!strcmp (SDATA (lower), "off") - || !strcmp (SDATA (lower), "false")) - return Qnil; - else - return Fintern (tem, Qnil); - } - - default: - abort (); - } - } - else - return Qunbound; - } - return Fcdr (tem); + return x_get_arg (check_x_display_info (Qnil), + alist, param, attribute, class, type); } -/* Record in frame F the specified or default value according to ALIST - of the parameter named PROP (a Lisp symbol). - If no value is specified for PROP, look for an X default for XPROP - on the frame named NAME. - If that is not found either, use the value DEFLT. */ - -static Lisp_Object -x_default_parameter (f, alist, prop, deflt, xprop, xclass, type) - struct frame *f; - Lisp_Object alist; - Lisp_Object prop; - Lisp_Object deflt; - char *xprop; - char *xclass; - enum resource_types type; -{ - Lisp_Object tem; - - tem = w32_get_arg (alist, prop, xprop, xclass, type); - if (EQ (tem, Qunbound)) - tem = deflt; - x_set_frame_parameters (f, Fcons (Fcons (prop, tem), Qnil)); - return tem; -} -DEFUN ("x-parse-geometry", Fx_parse_geometry, Sx_parse_geometry, 1, 1, 0, - 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; -{ - int geometry, x, y; - unsigned int width, height; - Lisp_Object result; - - CHECK_STRING (string); - - geometry = XParseGeometry ((char *) SDATA (string), - &x, &y, &width, &height); - - result = Qnil; - if (geometry & XValue) - { - Lisp_Object element; - - if (x >= 0 && (geometry & XNegative)) - element = Fcons (Qleft, Fcons (Qminus, Fcons (make_number (-x), Qnil))); - else if (x < 0 && ! (geometry & XNegative)) - element = Fcons (Qleft, Fcons (Qplus, Fcons (make_number (x), Qnil))); - else - element = Fcons (Qleft, make_number (x)); - result = Fcons (element, result); - } - - if (geometry & YValue) - { - Lisp_Object element; - - if (y >= 0 && (geometry & YNegative)) - element = Fcons (Qtop, Fcons (Qminus, Fcons (make_number (-y), Qnil))); - else if (y < 0 && ! (geometry & YNegative)) - element = Fcons (Qtop, Fcons (Qplus, Fcons (make_number (y), Qnil))); - else - element = Fcons (Qtop, make_number (y)); - result = Fcons (element, result); - } - - if (geometry & WidthValue) - result = Fcons (Fcons (Qwidth, make_number (width)), result); - if (geometry & HeightValue) - result = Fcons (Fcons (Qheight, make_number (height)), result); - - return result; -} - -/* Calculate the desired size and position of this window, - and return the flags saying which aspects were specified. - - This function does not make the coordinates positive. */ - -#define DEFAULT_ROWS 40 -#define DEFAULT_COLS 80 - -static int -x_figure_window_size (f, parms) - struct frame *f; - Lisp_Object parms; +Cursor +w32_load_cursor (LPCTSTR name) { - register Lisp_Object tem0, tem1, tem2; - long window_prompting = 0; - - /* Default values if we fall through. - Actually, if that happens we should get - window manager prompting. */ - SET_FRAME_WIDTH (f, DEFAULT_COLS); - f->height = DEFAULT_ROWS; - /* Window managers expect that if program-specified - positions are not (0,0), they're intentional, not defaults. */ - f->output_data.w32->top_pos = 0; - f->output_data.w32->left_pos = 0; - - /* Ensure that old new_width and new_height will not override the - values set here. */ - FRAME_NEW_WIDTH (f) = 0; - FRAME_NEW_HEIGHT (f) = 0; - - tem0 = w32_get_arg (parms, Qheight, 0, 0, RES_TYPE_NUMBER); - tem1 = w32_get_arg (parms, Qwidth, 0, 0, RES_TYPE_NUMBER); - tem2 = w32_get_arg (parms, Quser_size, 0, 0, RES_TYPE_NUMBER); - if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound)) - { - if (!EQ (tem0, Qunbound)) - { - CHECK_NUMBER (tem0); - f->height = XINT (tem0); - } - if (!EQ (tem1, Qunbound)) - { - CHECK_NUMBER (tem1); - SET_FRAME_WIDTH (f, XINT (tem1)); - } - if (!NILP (tem2) && !EQ (tem2, Qunbound)) - window_prompting |= USSize; - else - window_prompting |= PSize; - } - - f->output_data.w32->vertical_scroll_bar_extra - = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f) - ? 0 - : FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0 - ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f) - : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.w32->font))); - - x_compute_fringe_widths (f, 0); - - f->output_data.w32->pixel_width = CHAR_TO_PIXEL_WIDTH (f, f->width); - f->output_data.w32->pixel_height = CHAR_TO_PIXEL_HEIGHT (f, f->height); - - tem0 = w32_get_arg (parms, Qtop, 0, 0, RES_TYPE_NUMBER); - tem1 = w32_get_arg (parms, Qleft, 0, 0, RES_TYPE_NUMBER); - tem2 = w32_get_arg (parms, Quser_position, 0, 0, RES_TYPE_NUMBER); - if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound)) + /* Try first to load cursor from application resource. */ + Cursor cursor = LoadImage ((HINSTANCE) GetModuleHandle(NULL), + name, IMAGE_CURSOR, 0, 0, + LR_DEFAULTCOLOR | LR_DEFAULTSIZE | LR_SHARED); + if (!cursor) { - if (EQ (tem0, Qminus)) - { - f->output_data.w32->top_pos = 0; - window_prompting |= YNegative; - } - else if (CONSP (tem0) && EQ (XCAR (tem0), Qminus) - && CONSP (XCDR (tem0)) - && INTEGERP (XCAR (XCDR (tem0)))) - { - f->output_data.w32->top_pos = - XINT (XCAR (XCDR (tem0))); - window_prompting |= YNegative; - } - else if (CONSP (tem0) && EQ (XCAR (tem0), Qplus) - && CONSP (XCDR (tem0)) - && INTEGERP (XCAR (XCDR (tem0)))) - { - f->output_data.w32->top_pos = XINT (XCAR (XCDR (tem0))); - } - else if (EQ (tem0, Qunbound)) - f->output_data.w32->top_pos = 0; - else - { - CHECK_NUMBER (tem0); - f->output_data.w32->top_pos = XINT (tem0); - if (f->output_data.w32->top_pos < 0) - window_prompting |= YNegative; - } - - if (EQ (tem1, Qminus)) - { - f->output_data.w32->left_pos = 0; - window_prompting |= XNegative; - } - else if (CONSP (tem1) && EQ (XCAR (tem1), Qminus) - && CONSP (XCDR (tem1)) - && INTEGERP (XCAR (XCDR (tem1)))) - { - f->output_data.w32->left_pos = - XINT (XCAR (XCDR (tem1))); - window_prompting |= XNegative; - } - else if (CONSP (tem1) && EQ (XCAR (tem1), Qplus) - && CONSP (XCDR (tem1)) - && INTEGERP (XCAR (XCDR (tem1)))) - { - f->output_data.w32->left_pos = XINT (XCAR (XCDR (tem1))); - } - else if (EQ (tem1, Qunbound)) - f->output_data.w32->left_pos = 0; - else - { - CHECK_NUMBER (tem1); - f->output_data.w32->left_pos = XINT (tem1); - if (f->output_data.w32->left_pos < 0) - window_prompting |= XNegative; - } - - if (!NILP (tem2) && ! EQ (tem2, Qunbound)) - window_prompting |= USPosition; - else - window_prompting |= PPosition; - } - - if (f->output_data.w32->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.w32->pixel_width = CHAR_TO_PIXEL_WIDTH (f, f->width); - f->output_data.w32->pixel_height = CHAR_TO_PIXEL_HEIGHT (f, f->height); - f->output_data.w32->left_pos = left; - f->output_data.w32->top_pos = top; + /* Then try to load a shared predefined cursor. */ + cursor = LoadImage (NULL, name, IMAGE_CURSOR, 0, 0, + LR_DEFAULTCOLOR | LR_DEFAULTSIZE | LR_SHARED); } - - return window_prompting; + return cursor; } - - extern LRESULT CALLBACK w32_wnd_proc (); BOOL @@ -3432,7 +2251,7 @@ w32_init_class (hinst) wc.cbWndExtra = WND_EXTRA_BYTES; wc.hInstance = hinst; wc.hIcon = LoadIcon (hinst, EMACS_CLASS); - wc.hCursor = LoadCursor (NULL, IDC_ARROW); + wc.hCursor = w32_load_cursor (IDC_ARROW); wc.hbrBackground = NULL; /* GetStockObject (WHITE_BRUSH); */ wc.lpszMenuName = NULL; wc.lpszClassName = EMACS_CLASS; @@ -3465,8 +2284,8 @@ w32_createwindow (f) RECT rect; rect.left = rect.top = 0; - rect.right = PIXEL_WIDTH (f); - rect.bottom = PIXEL_HEIGHT (f); + rect.right = FRAME_PIXEL_WIDTH (f); + rect.bottom = FRAME_PIXEL_HEIGHT (f); AdjustWindowRect (&rect, f->output_data.w32->dwStyle, FRAME_EXTERNAL_MENU_BAR (f)); @@ -3482,8 +2301,8 @@ w32_createwindow (f) = CreateWindow (EMACS_CLASS, f->namebuf, f->output_data.w32->dwStyle | WS_CLIPCHILDREN, - f->output_data.w32->left_pos, - f->output_data.w32->top_pos, + f->left_pos, + f->top_pos, rect.right - rect.left, rect.bottom - rect.top, NULL, @@ -3493,10 +2312,10 @@ w32_createwindow (f) if (hwnd) { - SetWindowLong (hwnd, WND_FONTWIDTH_INDEX, FONT_WIDTH (f->output_data.w32->font)); - SetWindowLong (hwnd, WND_LINEHEIGHT_INDEX, f->output_data.w32->line_height); - SetWindowLong (hwnd, WND_BORDER_INDEX, f->output_data.w32->internal_border_width); - SetWindowLong (hwnd, WND_SCROLLBAR_INDEX, f->output_data.w32->vertical_scroll_bar_extra); + SetWindowLong (hwnd, WND_FONTWIDTH_INDEX, FRAME_COLUMN_WIDTH (f)); + SetWindowLong (hwnd, WND_LINEHEIGHT_INDEX, FRAME_LINE_HEIGHT (f)); + SetWindowLong (hwnd, WND_BORDER_INDEX, FRAME_INTERNAL_BORDER_WIDTH (f)); + SetWindowLong (hwnd, WND_SCROLLBAR_INDEX, f->scroll_bar_actual_width); SetWindowLong (hwnd, WND_BACKGROUND_INDEX, FRAME_BACKGROUND_PIXEL (f)); /* Enable drag-n-drop. */ @@ -4934,30 +3753,6 @@ w32_wnd_proc (hwnd, msg, wParam, lParam) goto dflt; case WM_SETFOCUS: - /* - Reinitialize the function pointer track_mouse_event_fn here. - This is required even though it is initialized in syms_of_w32fns - which is called in main (emacs.c). - Reinitialize the function pointer track_mouse_event_fn here. - Even though this function pointer is initialized in - syms_of_w32fns which is called from main (emacs.c), - we need to initialize it again here in order to prevent - a crash that occurs in Windows 9x (possibly only when Emacs - was built on Windows NT / 2000 / XP?) when handling the - WM_MOUSEMOVE message. - The crash occurs when attempting to call the Win32 API - function TrackMouseEvent through the function pointer. - It appears as if the function pointer that is obtained when - syms_of_w32fns is called from main is no longer valid - (possibly due to DLL relocation?). - To resolve this issue, I have placed a call to reinitialize - this function pointer here because this message gets received - when the Emacs window gains focus. - */ - track_mouse_event_fn = - (TrackMouseEvent_Proc) GetProcAddress ( - GetModuleHandle ("user32.dll"), - "TrackMouseEvent"); dpyinfo->faked_key = 0; reset_modifiers (); register_hot_keys (hwnd); @@ -5084,6 +3879,20 @@ w32_wnd_proc (hwnd, msg, wParam, lParam) ((LPMINMAXINFO) lParam)->ptMaxTrackSize.y = 32767; return 0; + case WM_SETCURSOR: + if (LOWORD (lParam) == HTCLIENT) + return 0; + + goto dflt; + + case WM_EMACS_SETCURSOR: + { + Cursor cursor = (Cursor) wParam; + if (cursor) + SetCursor (cursor); + return 0; + } + case WM_EMACS_CREATESCROLLBAR: return (LRESULT) w32_createscrollbar ((struct frame *) wParam, (struct scroll_bar *) lParam); @@ -5258,8 +4067,8 @@ my_create_tip_window (f) RECT rect; rect.left = rect.top = 0; - rect.right = PIXEL_WIDTH (f); - rect.bottom = PIXEL_HEIGHT (f); + rect.right = FRAME_PIXEL_WIDTH (f); + rect.bottom = FRAME_PIXEL_HEIGHT (f); AdjustWindowRect (&rect, f->output_data.w32->dwStyle, FRAME_EXTERNAL_MENU_BAR (f)); @@ -5268,8 +4077,8 @@ my_create_tip_window (f) = CreateWindow (EMACS_CLASS, f->namebuf, f->output_data.w32->dwStyle, - f->output_data.w32->left_pos, - f->output_data.w32->top_pos, + f->left_pos, + f->top_pos, rect.right - rect.left, rect.bottom - rect.top, FRAME_W32_WINDOW (SELECTED_FRAME ()), /* owner */ @@ -5279,9 +4088,9 @@ my_create_tip_window (f) if (tip_window) { - SetWindowLong (tip_window, WND_FONTWIDTH_INDEX, FONT_WIDTH (f->output_data.w32->font)); - SetWindowLong (tip_window, WND_LINEHEIGHT_INDEX, f->output_data.w32->line_height); - SetWindowLong (tip_window, WND_BORDER_INDEX, f->output_data.w32->internal_border_width); + SetWindowLong (tip_window, WND_FONTWIDTH_INDEX, FRAME_COLUMN_WIDTH (f)); + SetWindowLong (tip_window, WND_LINEHEIGHT_INDEX, FRAME_LINE_HEIGHT (f)); + SetWindowLong (tip_window, WND_BORDER_INDEX, FRAME_INTERNAL_BORDER_WIDTH (f)); SetWindowLong (tip_window, WND_BACKGROUND_INDEX, FRAME_BACKGROUND_PIXEL (f)); /* Tip frames have no scrollbars. */ @@ -5398,7 +4207,7 @@ x_make_gc (f) Note that many default values are used. */ /* Normal video */ - gc_values.font = f->output_data.w32->font; + gc_values.font = FRAME_FONT (f); /* Cursor has cursor-color background, background-color foreground. */ gc_values.foreground = FRAME_BACKGROUND_PIXEL (f); @@ -5528,8 +4337,9 @@ This function is an internal primitive--use `make-frame' instead. */) /* Note that Windows does support scroll bars. */ FRAME_CAN_HAVE_SCROLL_BARS (f) = 1; + /* By default, make scrollbars the system standard width. */ - f->scroll_bar_pixel_width = GetSystemMetrics (SM_CXVSCROLL); + FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = GetSystemMetrics (SM_CXVSCROLL); f->output_method = output_w32; f->output_data.w32 = @@ -5674,52 +4484,14 @@ This function is an internal primitive--use `make-frame' instead. */) f->output_data.w32->dwStyle = WS_OVERLAPPEDWINDOW; f->output_data.w32->parent_desc = FRAME_W32_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); - } - - window_prompting = x_figure_window_size (f, parms); - - if (window_prompting & XNegative) - { - if (window_prompting & YNegative) - f->output_data.w32->win_gravity = SouthEastGravity; - else - f->output_data.w32->win_gravity = NorthEastGravity; - } - else - { - if (window_prompting & YNegative) - f->output_data.w32->win_gravity = SouthWestGravity; - else - f->output_data.w32->win_gravity = NorthWestGravity; - } + f->output_data.w32->text_cursor = w32_load_cursor (IDC_IBEAM); + f->output_data.w32->nontext_cursor = w32_load_cursor (IDC_ARROW); + f->output_data.w32->modeline_cursor = w32_load_cursor (IDC_ARROW); + f->output_data.w32->hand_cursor = w32_load_cursor (IDC_HAND); + f->output_data.w32->hourglass_cursor = w32_load_cursor (IDC_WAIT); + f->output_data.w32->horizontal_drag_cursor = w32_load_cursor (IDC_SIZEWE); - f->output_data.w32->size_hint_flags = window_prompting; + window_prompting = x_figure_window_size (f, parms, 1); tem = w32_get_arg (parms, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN); f->no_split = minibuffer_only || EQ (tem, Qt); @@ -5747,14 +4519,14 @@ This function is an internal primitive--use `make-frame' instead. */) x_default_parameter (f, parms, Qscroll_bar_width, Qnil, "scrollBarWidth", "ScrollBarWidth", RES_TYPE_NUMBER); - /* Dimensions, especially f->height, must be done via change_frame_size. + /* Dimensions, especially FRAME_LINES (f), must be done via change_frame_size. Change will not be effected unless different from the current - f->height. */ - width = f->width; - height = f->height; + FRAME_LINES (f). */ + width = FRAME_COLS (f); + height = FRAME_LINES (f); - f->height = 0; - SET_FRAME_WIDTH (f, 0); + FRAME_LINES (f) = 0; + SET_FRAME_COLS (f, 0); change_frame_size (f, height, width, 1, 0, 0); /* Tell the server what size and position, etc, we want, and how @@ -6012,6 +4784,7 @@ w32_load_system_font (f,fontname,size) /* Now fill in the slots of *FONTP. */ BLOCK_INPUT; + bzero (fontp, sizeof (*fontp)); fontp->font = font; fontp->font_idx = i; fontp->name = (char *) xmalloc (strlen (fontname) + 1); @@ -7317,7 +6090,7 @@ static Lisp_Object w32_list_bdf_fonts (Lisp_Object pattern, int max_names) { newlist = Fcons (XCAR (tem), newlist); n_fonts++; - if (n_fonts >= max_names) + if (max_names >= 0 && n_fonts >= max_names) break; } } @@ -7331,7 +6104,8 @@ static Lisp_Object w32_list_bdf_fonts (Lisp_Object pattern, int max_names) to be listed. Frame F NULL means we have not yet created any frame, which means we can't get proper size info, as we don't have a device context to use for GetTextMetrics. - MAXNAMES sets a limit on how many fonts to match. */ + MAXNAMES sets a limit on how many fonts to match. If MAXNAMES is + negative, then all matching fonts are returned. */ Lisp_Object w32_list_fonts (f, pattern, size, maxnames) @@ -7444,7 +6218,7 @@ w32_list_fonts (f, pattern, size, maxnames) { newlist = Fcons (XCAR (tem), newlist); n_fonts++; - if (n_fonts >= maxnames) + if (maxnames >= 0 && n_fonts >= maxnames) break; else continue; @@ -7483,7 +6257,7 @@ w32_list_fonts (f, pattern, size, maxnames) { newlist = Fcons (XCAR (tem), newlist); n_fonts++; - if (n_fonts >= maxnames) + if (maxnames >= 0 && n_fonts >= maxnames) break; } /* keep track of the closest matching size in case @@ -7519,7 +6293,7 @@ w32_list_fonts (f, pattern, size, maxnames) } /* Include any bdf fonts. */ - if (n_fonts < maxnames) + if (n_fonts < maxnames || maxnames < 0) { Lisp_Object combined[2]; combined[0] = w32_list_bdf_fonts (pattern, maxnames - n_fonts); @@ -7938,28 +6712,28 @@ int x_pixel_width (f) register struct frame *f; { - return PIXEL_WIDTH (f); + return FRAME_PIXEL_WIDTH (f); } int x_pixel_height (f) register struct frame *f; { - return PIXEL_HEIGHT (f); + return FRAME_PIXEL_HEIGHT (f); } int x_char_width (f) register struct frame *f; { - return FONT_WIDTH (f->output_data.w32->font); + return FRAME_COLUMN_WIDTH (f); } int x_char_height (f) register struct frame *f; { - return f->output_data.w32->line_height; + return FRAME_LINE_HEIGHT (f); } int @@ -8054,6 +6828,9 @@ terminate Emacs if we can't open the connection. */) if (NILP (Vw32_color_map)) Vw32_color_map = Fw32_default_color_map (); + /* Merge in system logical colors. */ + add_system_logical_colors_to_map (&Vw32_color_map); + if (! NILP (xrm_string)) xrm_option = (unsigned char *) SDATA (xrm_string); else @@ -8524,8 +7301,8 @@ or omitted means use the selected frame. */) int height = img->height + 2 * img->vmargin; if (NILP (pixels)) - size = Fcons (make_float ((double) width / CANON_X_UNIT (f)), - make_float ((double) height / CANON_Y_UNIT (f))); + size = Fcons (make_float ((double) width / FRAME_COLUMN_WIDTH (f)), + make_float ((double) height / FRAME_LINE_HEIGHT (f))); else size = Fcons (make_number (width), make_number (height)); } @@ -8766,7 +7543,7 @@ image_background_transparent (img, f, mask) mask = CreateCompatibleDC (frame_dc); release_frame_dc (f, frame_dc); - prev = SelectObject (mask, img->mask); + prev = SelectObject (mask, img->mask); } img->background_transparent @@ -9185,7 +7962,7 @@ lookup_image (f, spec) else { /* Handle image type independent image attributes - `:ascent PERCENT', `:margin MARGIN', `:relief RELIEF', + `:ascent ASCENT', `:margin MARGIN', `:relief RELIEF', `:background COLOR'. */ Lisp_Object ascent, margin, relief, bg; @@ -9314,6 +8091,15 @@ forall_images_in_image_cache (f, fn) W32 support code ***********************************************************************/ +/* Macro for defining functions that will be loaded from image DLLs. */ +#define DEF_IMGLIB_FN(func) FARPROC fn_##func + +/* Macro for loading those image functions from the library. */ +#define LOAD_IMGLIB_FN(lib,func) { \ + fn_##func = (void *) GetProcAddress (lib, #func); \ + if (!fn_##func) return 0; \ + } + static int x_create_x_image_and_pixmap P_ ((struct frame *, int, int, int, XImage **, Pixmap *)); static void x_put_x_image P_ ((struct frame *, XImage *, Pixmap, int, int)); @@ -9441,6 +8227,7 @@ x_put_x_image (f, ximg, pixmap, width, height) struct frame *f; XImage *ximg; Pixmap pixmap; + int width, height; { #if 0 /* I don't think this is necessary looking at where it is used. */ HDC hdc = get_frame_dc (f); @@ -9501,7 +8288,7 @@ slurp_file (file, size) struct stat st; if (stat (file, &st) == 0 - && (fp = fopen (file, "r")) != NULL + && (fp = fopen (file, "rb")) != NULL && (buf = (char *) xmalloc (st.st_size), fread (buf, 1, st.st_size, fp) == st.st_size)) { @@ -9834,7 +8621,7 @@ w32_create_pixmap_from_bitmap_data (int width, int height, char *data) w1 = (width + 7) / 8; /* nb of 8bits elt in X bitmap */ w2 = ((width + 15) / 16) * 2; /* nb of 16bits elt in W32 bitmap */ - bits = (char *) xmalloc (height * w2); + bits = (char *) alloca (height * w2); bzero (bits, height * w2); for (i = 0; i < height; i++) { @@ -9843,7 +8630,6 @@ w32_create_pixmap_from_bitmap_data (int width, int height, char *data) *p++ = reflect_byte(*data++); } bmp = CreateBitmap (width, height, 1, 1, bits); - xfree (bits); return bmp; } @@ -9999,6 +8785,38 @@ xbm_read_bitmap_data (contents, end, width, height, data) #undef expect_ident } +static void convert_mono_to_color_image (f, img, foreground, background) + struct frame *f; + struct image *img; + COLORREF foreground, background; +{ + HDC hdc, old_img_dc, new_img_dc; + HGDIOBJ old_prev, new_prev; + HBITMAP new_pixmap; + + hdc = get_frame_dc (f); + old_img_dc = CreateCompatibleDC (hdc); + new_img_dc = CreateCompatibleDC (hdc); + new_pixmap = CreateCompatibleBitmap (hdc, img->width, img->height); + release_frame_dc (f, hdc); + old_prev = SelectObject (old_img_dc, img->pixmap); + new_prev = SelectObject (new_img_dc, new_pixmap); + SetTextColor (new_img_dc, foreground); + SetBkColor (new_img_dc, background); + + BitBlt (new_img_dc, 0, 0, img->width, img->height, old_img_dc, + 0, 0, SRCCOPY); + + SelectObject (old_img_dc, old_prev); + SelectObject (new_img_dc, new_prev); + DeleteDC (old_img_dc); + DeleteDC (new_img_dc); + DeleteObject (img->pixmap); + if (new_pixmap == 0) + fprintf (stderr, "Failed to convert image to color.\n"); + else + img->pixmap = new_pixmap; +} /* Load XBM image IMG which will be displayed on frame F from buffer CONTENTS. END is the end of the buffer. Value is non-zero if @@ -10019,6 +8837,7 @@ xbm_load_image (f, img, contents, end) { unsigned long foreground = FRAME_FOREGROUND_PIXEL (f); unsigned long background = FRAME_BACKGROUND_PIXEL (f); + int non_default_colors = 0; Lisp_Object value; xassert (img->width > 0 && img->height > 0); @@ -10026,17 +8845,25 @@ xbm_load_image (f, img, contents, end) /* Get foreground and background colors, maybe allocate colors. */ value = image_spec_value (img->spec, QCforeground, NULL); if (!NILP (value)) - foreground = x_alloc_image_color (f, img, value, foreground); + { + foreground = x_alloc_image_color (f, img, value, foreground); + non_default_colors = 1; + } value = image_spec_value (img->spec, QCbackground, NULL); if (!NILP (value)) { background = x_alloc_image_color (f, img, value, background); img->background = background; img->background_valid = 1; + non_default_colors = 1; } img->pixmap = w32_create_pixmap_from_bitmap_data (img->width, img->height, data); + /* If colors were specified, transfer the bitmap to a color one. */ + if (non_default_colors) + convert_mono_to_color_image (f, img, foreground, background); + xfree (data); if (img->pixmap == 0) @@ -10117,6 +8944,7 @@ xbm_load (f, img) Lisp_Object data; unsigned long foreground = FRAME_FOREGROUND_PIXEL (f); unsigned long background = FRAME_BACKGROUND_PIXEL (f); + int non_default_colors = 0; char *bits; int parsed_p; int in_memory_file_p = 0; @@ -10141,12 +8969,19 @@ xbm_load (f, img) /* Get foreground and background colors, maybe allocate colors. */ if (fmt[XBM_FOREGROUND].count && STRINGP (fmt[XBM_FOREGROUND].value)) - foreground = x_alloc_image_color (f, img, fmt[XBM_FOREGROUND].value, - foreground); + { + foreground = x_alloc_image_color (f, img, fmt[XBM_FOREGROUND].value, + foreground); + non_default_colors = 1; + } + if (fmt[XBM_BACKGROUND].count && STRINGP (fmt[XBM_BACKGROUND].value)) - background = x_alloc_image_color (f, img, fmt[XBM_BACKGROUND].value, - background); + { + background = x_alloc_image_color (f, img, fmt[XBM_BACKGROUND].value, + background); + non_default_colors = 1; + } if (in_memory_file_p) success_p = xbm_load_image (f, img, SDATA (data), @@ -10180,6 +9015,10 @@ xbm_load (f, img) = w32_create_pixmap_from_bitmap_data (img->width, img->height, bits); + /* If colors were specified, transfer the bitmap to a color one. */ + if (non_default_colors) + convert_mono_to_color_image (f, img, foreground, background); + if (img->pixmap) success_p = 1; else @@ -10206,7 +9045,17 @@ static int xpm_image_p P_ ((Lisp_Object object)); static int xpm_load P_ ((struct frame *f, struct image *img)); static int xpm_valid_color_symbols_p P_ ((Lisp_Object)); +/* Indicate to xpm.h that we don't have Xlib. */ +#define FOR_MSW +/* simx.h in xpm defines XColor and XImage differently than Emacs. */ +#define XColor xpm_XColor +#define XImage xpm_XImage +#define PIXEL_ALREADY_TYPEDEFED #include "X11/xpm.h" +#undef FOR_MSW +#undef XColor +#undef XImage +#undef PIXEL_ALREADY_TYPEDEFED /* The symbol `xpm' identifying XPM-format images. */ @@ -10238,7 +9087,7 @@ static struct image_keyword xpm_format[XPM_LAST] = {":type", IMAGE_SYMBOL_VALUE, 1}, {":file", IMAGE_STRING_VALUE, 0}, {":data", IMAGE_STRING_VALUE, 0}, - {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0}, + {":ascent", IMAGE_ASCENT_VALUE, 0}, {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0}, {":relief", IMAGE_INTEGER_VALUE, 0}, {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, @@ -10260,6 +9109,26 @@ static struct image_type xpm_type = }; +/* XPM library details. */ + +DEF_IMGLIB_FN (XpmFreeAttributes); +DEF_IMGLIB_FN (XpmCreateImageFromBuffer); +DEF_IMGLIB_FN (XpmReadFileToImage); +DEF_IMGLIB_FN (XImageFree); + + +static int +init_xpm_functions (library) + HMODULE library; +{ + LOAD_IMGLIB_FN (library, XpmFreeAttributes); + LOAD_IMGLIB_FN (library, XpmCreateImageFromBuffer); + LOAD_IMGLIB_FN (library, XpmReadFileToImage); + LOAD_IMGLIB_FN (library, XImageFree); + + return 1; +} + /* Value is non-zero if COLOR_SYMBOLS is a valid color symbols list for XPM images. Such a list must consist of conses whose car and cdr are strings. */ @@ -10296,9 +9165,7 @@ xpm_image_p (object) /* Either no `:color-symbols' or it's a list of conses whose car and cdr are strings. */ && (fmt[XPM_COLOR_SYMBOLS].count == 0 - || xpm_valid_color_symbols_p (fmt[XPM_COLOR_SYMBOLS].value)) - && (fmt[XPM_ASCENT].count == 0 - || XFASTINT (fmt[XPM_ASCENT].value) < 100)); + || xpm_valid_color_symbols_p (fmt[XPM_COLOR_SYMBOLS].value))); } @@ -10310,17 +9177,23 @@ xpm_load (f, img) struct frame *f; struct image *img; { - int rc, i; + HDC hdc; + int rc; XpmAttributes attrs; Lisp_Object specified_file, color_symbols; + xpm_XImage * xpm_image, * xpm_mask; /* Configure the XPM lib. Use the visual of frame F. Allocate close colors. Return colors allocated. */ bzero (&attrs, sizeof attrs); + xpm_image = xpm_mask = NULL; + +#if 0 attrs.visual = FRAME_X_VISUAL (f); attrs.colormap = FRAME_X_COLORMAP (f); attrs.valuemask |= XpmVisual; attrs.valuemask |= XpmColormap; +#endif attrs.valuemask |= XpmReturnAllocPixels; #ifdef XpmAllocCloseColors attrs.alloc_close_colors = 1; @@ -10368,34 +9241,71 @@ xpm_load (f, img) /* Create a pixmap for the image, either from a file, or from a string buffer containing data in the same format as an XPM file. */ - BLOCK_INPUT; + specified_file = image_spec_value (img->spec, QCfile, NULL); + + { + HDC frame_dc = get_frame_dc (f); + hdc = CreateCompatibleDC (frame_dc); + release_frame_dc (f, frame_dc); + } + if (STRINGP (specified_file)) { Lisp_Object file = x_find_image_file (specified_file); if (!STRINGP (file)) { image_error ("Cannot find image file `%s'", specified_file, Qnil); - UNBLOCK_INPUT; return 0; } - rc = XpmReadFileToPixmap (NULL, FRAME_W32_WINDOW (f), - SDATA (file), &img->pixmap, &img->mask, - &attrs); + /* XpmReadFileToPixmap is not available in the Windows port of + libxpm. But XpmReadFileToImage almost does what we want. */ + rc = fn_XpmReadFileToImage (&hdc, SDATA (file), + &xpm_image, &xpm_mask, + &attrs); } else { Lisp_Object buffer = image_spec_value (img->spec, QCdata, NULL); - rc = XpmCreatePixmapFromBuffer (NULL, FRAME_W32_WINDOW (f), - SDATA (buffer), - &img->pixmap, &img->mask, - &attrs); + /* XpmCreatePixmapFromBuffer is not available in the Windows port + of libxpm. But XpmCreateImageFromBuffer almost does what we want. */ + rc = fn_XpmCreateImageFromBuffer (&hdc, SDATA (buffer), + &xpm_image, &xpm_mask, + &attrs); } - UNBLOCK_INPUT; if (rc == XpmSuccess) { + int i; + + /* W32 XPM uses XImage to wrap what W32 Emacs calls a Pixmap, + plus some duplicate attributes. */ + if (xpm_image && xpm_image->bitmap) + { + img->pixmap = xpm_image->bitmap; + /* XImageFree in libXpm frees XImage struct without destroying + the bitmap, which is what we want. */ + fn_XImageFree (xpm_image); + } + if (xpm_mask && xpm_mask->bitmap) + { + /* The mask appears to be inverted compared with what we expect. + TODO: invert our expectations. See other places where we + have to invert bits because our idea of masks is backwards. */ + HGDIOBJ old_obj; + old_obj = SelectObject (hdc, xpm_mask->bitmap); + + PatBlt (hdc, 0, 0, xpm_mask->width, xpm_mask->height, DSTINVERT); + SelectObject (hdc, old_obj); + + img->mask = xpm_mask->bitmap; + fn_XImageFree (xpm_mask); + DeleteDC (hdc); + } + + DeleteDC (hdc); + /* Remember allocated colors. */ img->ncolors = attrs.nalloc_pixels; img->colors = (unsigned long *) xmalloc (img->ncolors @@ -10408,12 +9318,12 @@ xpm_load (f, img) xassert (img->width > 0 && img->height > 0); /* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */ - BLOCK_INPUT; - XpmFreeAttributes (&attrs); - UNBLOCK_INPUT; + fn_XpmFreeAttributes (&attrs); } else { + DeleteDC (hdc); + switch (rc) { case XpmOpenFailed: @@ -10738,24 +9648,40 @@ static void XPutPixel (ximg, x, y, color) { int width = ximg->info.bmiHeader.biWidth; int height = ximg->info.bmiHeader.biHeight; - int rowbytes = width * 3; unsigned char * pixel; - /* Don't support putting pixels in images with palettes. */ - xassert (ximg->info.bmiHeader.biBitCount == 24); - - /* Ensure scanlines are aligned on 4 byte boundaries. */ - if (rowbytes % 4) - rowbytes += 4 - (rowbytes % 4); - - pixel = ximg->data + y * rowbytes + x * 3; - /* Windows bitmaps are in BGR order. */ - *pixel = GetBValue (color); - *(pixel + 1) = GetGValue (color); - *(pixel + 2) = GetRValue (color); + /* True color images. */ + if (ximg->info.bmiHeader.biBitCount == 24) + { + int rowbytes = width * 3; + /* Ensure scanlines are aligned on 4 byte boundaries. */ + if (rowbytes % 4) + rowbytes += 4 - (rowbytes % 4); + + pixel = ximg->data + y * rowbytes + x * 3; + /* Windows bitmaps are in BGR order. */ + *pixel = GetBValue (color); + *(pixel + 1) = GetGValue (color); + *(pixel + 2) = GetRValue (color); + } + /* Monochrome images. */ + else if (ximg->info.bmiHeader.biBitCount == 1) + { + int rowbytes = width / 8; + /* Ensure scanlines are aligned on 4 byte boundaries. */ + if (rowbytes % 4) + rowbytes += 4 - (rowbytes % 4); + pixel = ximg->data + y * rowbytes + x / 8; + /* Filter out palette info. */ + if (color & 0x00ffffff) + *pixel = *pixel | (1 << x % 8); + else + *pixel = *pixel & ~(1 << x % 8); + } + else + image_error ("XPutPixel: palette image not supported", Qnil, Qnil); } - /* Create IMG->pixmap from an array COLORS of XColor structures, whose RGB members are set. F is the frame on which this all happens. COLORS will be freed; an existing IMG->pixmap will be freed, too. */ @@ -11063,7 +9989,7 @@ x_build_heuristic_mask (f, img, how) char color_name[30]; sprintf (color_name, "#%04x%04x%04x", rgb[0], rgb[1], rgb[2]); bg = x_alloc_image_color (f, img, build_string (color_name), 0) - & 0xffffff; // Filter out palette info. + & 0x00ffffff; /* Filter out palette info. */ use_img_background = 0; } } @@ -11091,7 +10017,7 @@ x_build_heuristic_mask (f, img, how) image_background_transparent (img, f, img_dc); /* Put mask_img into img->mask. */ - x_destroy_x_image (mask_img); + x_destroy_x_image ((XImage *)mask_img); SelectObject (img_dc, prev); DeleteDC (img_dc); @@ -11137,7 +10063,7 @@ static struct image_keyword pbm_format[PBM_LAST] = {":type", IMAGE_SYMBOL_VALUE, 1}, {":file", IMAGE_STRING_VALUE, 0}, {":data", IMAGE_STRING_VALUE, 0}, - {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0}, + {":ascent", IMAGE_ASCENT_VALUE, 0}, {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0}, {":relief", IMAGE_INTEGER_VALUE, 0}, {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, @@ -11169,9 +10095,7 @@ pbm_image_p (object) bcopy (pbm_format, fmt, sizeof fmt); - if (!parse_image_spec (object, fmt, PBM_LAST, Qpbm) - || (fmt[PBM_ASCENT].count - && XFASTINT (fmt[PBM_ASCENT].value) > 100)) + if (!parse_image_spec (object, fmt, PBM_LAST, Qpbm)) return 0; /* Must specify either :data or :file. */ @@ -11231,7 +10155,7 @@ pbm_read_file (file, size) struct stat st; if (stat (SDATA (file), &st) == 0 - && (fp = fopen (SDATA (file), "r")) != NULL + && (fp = fopen (SDATA (file), "rb")) != NULL && (buf = (char *) xmalloc (st.st_size), fread (buf, 1, st.st_size, fp) == st.st_size)) { @@ -11517,7 +10441,7 @@ static struct image_keyword png_format[PNG_LAST] = {":type", IMAGE_SYMBOL_VALUE, 1}, {":data", IMAGE_STRING_VALUE, 0}, {":file", IMAGE_STRING_VALUE, 0}, - {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0}, + {":ascent", IMAGE_ASCENT_VALUE, 0}, {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0}, {":relief", IMAGE_INTEGER_VALUE, 0}, {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, @@ -11537,6 +10461,59 @@ static struct image_type png_type = NULL }; +/* PNG library details. */ + +DEF_IMGLIB_FN (png_get_io_ptr); +DEF_IMGLIB_FN (png_check_sig); +DEF_IMGLIB_FN (png_create_read_struct); +DEF_IMGLIB_FN (png_create_info_struct); +DEF_IMGLIB_FN (png_destroy_read_struct); +DEF_IMGLIB_FN (png_set_read_fn); +DEF_IMGLIB_FN (png_init_io); +DEF_IMGLIB_FN (png_set_sig_bytes); +DEF_IMGLIB_FN (png_read_info); +DEF_IMGLIB_FN (png_get_IHDR); +DEF_IMGLIB_FN (png_get_valid); +DEF_IMGLIB_FN (png_set_strip_16); +DEF_IMGLIB_FN (png_set_expand); +DEF_IMGLIB_FN (png_set_gray_to_rgb); +DEF_IMGLIB_FN (png_set_background); +DEF_IMGLIB_FN (png_get_bKGD); +DEF_IMGLIB_FN (png_read_update_info); +DEF_IMGLIB_FN (png_get_channels); +DEF_IMGLIB_FN (png_get_rowbytes); +DEF_IMGLIB_FN (png_read_image); +DEF_IMGLIB_FN (png_read_end); +DEF_IMGLIB_FN (png_error); + +static int +init_png_functions (library) + HMODULE library; +{ + LOAD_IMGLIB_FN (library, png_get_io_ptr); + LOAD_IMGLIB_FN (library, png_check_sig); + LOAD_IMGLIB_FN (library, png_create_read_struct); + LOAD_IMGLIB_FN (library, png_create_info_struct); + LOAD_IMGLIB_FN (library, png_destroy_read_struct); + LOAD_IMGLIB_FN (library, png_set_read_fn); + LOAD_IMGLIB_FN (library, png_init_io); + LOAD_IMGLIB_FN (library, png_set_sig_bytes); + LOAD_IMGLIB_FN (library, png_read_info); + LOAD_IMGLIB_FN (library, png_get_IHDR); + LOAD_IMGLIB_FN (library, png_get_valid); + LOAD_IMGLIB_FN (library, png_set_strip_16); + LOAD_IMGLIB_FN (library, png_set_expand); + LOAD_IMGLIB_FN (library, png_set_gray_to_rgb); + LOAD_IMGLIB_FN (library, png_set_background); + LOAD_IMGLIB_FN (library, png_get_bKGD); + LOAD_IMGLIB_FN (library, png_read_update_info); + LOAD_IMGLIB_FN (library, png_get_channels); + LOAD_IMGLIB_FN (library, png_get_rowbytes); + LOAD_IMGLIB_FN (library, png_read_image); + LOAD_IMGLIB_FN (library, png_read_end); + LOAD_IMGLIB_FN (library, png_error); + return 1; +} /* Return non-zero if OBJECT is a valid PNG image specification. */ @@ -11547,9 +10524,7 @@ png_image_p (object) struct image_keyword fmt[PNG_LAST]; bcopy (png_format, fmt, sizeof fmt); - if (!parse_image_spec (object, fmt, PNG_LAST, Qpng) - || (fmt[PNG_ASCENT].count - && XFASTINT (fmt[PNG_ASCENT].value) > 100)) + if (!parse_image_spec (object, fmt, PNG_LAST, Qpng)) return 0; /* Must specify either the :data or :file keyword. */ @@ -11601,10 +10576,10 @@ png_read_from_memory (png_ptr, data, length) png_size_t length; { struct png_memory_storage *tbr - = (struct png_memory_storage *) png_get_io_ptr (png_ptr); + = (struct png_memory_storage *) fn_png_get_io_ptr (png_ptr); if (length > tbr->len - tbr->index) - png_error (png_ptr, "Read error"); + fn_png_error (png_ptr, "Read error"); bcopy (tbr->bytes + tbr->index, data, length); tbr->index = tbr->index + length; @@ -11627,14 +10602,13 @@ png_load (f, img) png_info *info_ptr = NULL, *end_info = NULL; FILE *volatile fp = NULL; png_byte sig[8]; - png_byte *volatile pixels = NULL; - png_byte **volatile rows = NULL; + png_byte * volatile pixels = NULL; + png_byte ** volatile rows = NULL; png_uint_32 width, height; int bit_depth, color_type, interlace_type; png_byte channels; png_uint_32 row_bytes; int transparent_p; - char *gamma_str; double screen_gamma, image_gamma; int intent; struct png_memory_storage tbr; /* Data to be read */ @@ -11649,31 +10623,31 @@ png_load (f, img) { file = x_find_image_file (specified_file); if (!STRINGP (file)) - { - image_error ("Cannot find image file `%s'", specified_file, Qnil); - UNGCPRO; - return 0; - } + { + image_error ("Cannot find image file `%s'", specified_file, Qnil); + UNGCPRO; + return 0; + } /* Open the image file. */ fp = fopen (SDATA (file), "rb"); if (!fp) - { - image_error ("Cannot open image file `%s'", file, Qnil); - UNGCPRO; - fclose (fp); - return 0; - } + { + image_error ("Cannot open image file `%s'", file, Qnil); + UNGCPRO; + fclose (fp); + return 0; + } /* Check PNG signature. */ if (fread (sig, 1, sizeof sig, fp) != sizeof sig - || !png_check_sig (sig, sizeof sig)) - { - image_error ("Not a PNG file:` %s'", file, Qnil); - UNGCPRO; - fclose (fp); - return 0; - } + || !fn_png_check_sig (sig, sizeof sig)) + { + image_error ("Not a PNG file: `%s'", file, Qnil); + UNGCPRO; + fclose (fp); + return 0; + } } else { @@ -11684,7 +10658,7 @@ png_load (f, img) /* Check PNG signature. */ if (tbr.len < sizeof sig - || !png_check_sig (tbr.bytes, sizeof sig)) + || !fn_png_check_sig (tbr.bytes, sizeof sig)) { image_error ("Not a PNG image: `%s'", img->spec, Qnil); UNGCPRO; @@ -11696,8 +10670,8 @@ png_load (f, img) } /* Initialize read and info structs for PNG lib. */ - png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, - my_png_error, my_png_warning); + png_ptr = fn_png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, + my_png_error, my_png_warning); if (!png_ptr) { if (fp) fclose (fp); @@ -11705,19 +10679,19 @@ png_load (f, img) return 0; } - info_ptr = png_create_info_struct (png_ptr); + info_ptr = fn_png_create_info_struct (png_ptr); if (!info_ptr) { - png_destroy_read_struct (&png_ptr, NULL, NULL); + fn_png_destroy_read_struct (&png_ptr, NULL, NULL); if (fp) fclose (fp); UNGCPRO; return 0; } - end_info = png_create_info_struct (png_ptr); + end_info = fn_png_create_info_struct (png_ptr); if (!end_info) { - png_destroy_read_struct (&png_ptr, &info_ptr, NULL); + fn_png_destroy_read_struct (&png_ptr, &info_ptr, NULL); if (fp) fclose (fp); UNGCPRO; return 0; @@ -11729,7 +10703,7 @@ png_load (f, img) { error: if (png_ptr) - png_destroy_read_struct (&png_ptr, &info_ptr, &end_info); + fn_png_destroy_read_struct (&png_ptr, &info_ptr, &end_info); xfree (pixels); xfree (rows); if (fp) fclose (fp); @@ -11739,18 +10713,18 @@ png_load (f, img) /* Read image info. */ if (!NILP (specified_data)) - png_set_read_fn (png_ptr, (void *) &tbr, png_read_from_memory); + fn_png_set_read_fn (png_ptr, (void *) &tbr, png_read_from_memory); else - png_init_io (png_ptr, fp); + fn_png_init_io (png_ptr, fp); - png_set_sig_bytes (png_ptr, sizeof sig); - png_read_info (png_ptr, info_ptr); - png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, - &interlace_type, NULL, NULL); + fn_png_set_sig_bytes (png_ptr, sizeof sig); + fn_png_read_info (png_ptr, info_ptr); + fn_png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, + &interlace_type, NULL, NULL); /* If image contains simply transparency data, we prefer to construct a clipping mask. */ - if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS)) + if (fn_png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS)) transparent_p = 1; else transparent_p = 0; @@ -11761,46 +10735,44 @@ png_load (f, img) /* Strip more than 8 bits per channel. */ if (bit_depth == 16) - png_set_strip_16 (png_ptr); + fn_png_set_strip_16 (png_ptr); /* Expand data to 24 bit RGB, or 8 bit grayscale, with alpha channel if available. */ - png_set_expand (png_ptr); + fn_png_set_expand (png_ptr); /* Convert grayscale images to RGB. */ if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) - png_set_gray_to_rgb (png_ptr); + fn_png_set_gray_to_rgb (png_ptr); - /* The value 2.2 is a guess for PC monitors from PNG example.c. */ - gamma_str = getenv ("SCREEN_GAMMA"); - screen_gamma = gamma_str ? atof (gamma_str) : 2.2; + screen_gamma = (f->gamma ? 1 / f->gamma / 0.45455 : 2.2); +#if 0 /* Avoid double gamma correction for PNG images. */ /* Tell the PNG lib to handle gamma correction for us. */ - #if defined(PNG_READ_sRGB_SUPPORTED) || defined(PNG_WRITE_sRGB_SUPPORTED) if (png_get_sRGB (png_ptr, info_ptr, &intent)) - /* There is a special chunk in the image specifying the gamma. */ - png_set_sRGB (png_ptr, info_ptr, intent); + /* The libpng documentation says this is right in this case. */ + png_set_gamma (png_ptr, screen_gamma, 0.45455); else #endif if (png_get_gAMA (png_ptr, info_ptr, &image_gamma)) /* Image contains gamma information. */ png_set_gamma (png_ptr, screen_gamma, image_gamma); else - /* Use a default of 0.5 for the image gamma. */ - png_set_gamma (png_ptr, screen_gamma, 0.5); + /* Use the standard default for the image gamma. */ + png_set_gamma (png_ptr, screen_gamma, 0.45455); +#endif /* if 0 */ /* Handle alpha channel by combining the image with a background color. Do this only if a real alpha channel is supplied. For simple transparency, we prefer a clipping mask. */ if (!transparent_p) { - png_color_16 *image_background; + png_color_16 *image_bg; Lisp_Object specified_bg = image_spec_value (img->spec, QCbackground, NULL); - if (STRINGP (specified_bg)) /* The user specified `:background', use that. */ { @@ -11810,55 +10782,57 @@ png_load (f, img) 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; + user_bg.red = 256 * GetRValue (color); + user_bg.green = 256 * GetGValue (color); + user_bg.blue = 256 * GetBValue (color); - png_set_background (png_ptr, &user_bg, - PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); + fn_png_set_background (png_ptr, &user_bg, + PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); } } - else if (png_get_bKGD (png_ptr, info_ptr, &image_background)) + else if (fn_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_BACKGROUND_GAMMA_FILE, 1, 1.0); + fn_png_set_background (png_ptr, image_bg, + PNG_BACKGROUND_GAMMA_FILE, 1, 1.0); else { /* Image does not contain a background color with which to combine the image data via an alpha channel. Use the frame's background instead. */ - XColor color; - Colormap cmap; + COLORREF color; png_color_16 frame_background; + color = FRAME_BACKGROUND_PIXEL (f); +#if 0 /* TODO : Colormap support. */ + Colormap cmap; cmap = FRAME_X_COLORMAP (f); - color.pixel = FRAME_BACKGROUND_PIXEL (f); x_query_color (f, &color); +#endif bzero (&frame_background, sizeof frame_background); - frame_background.red = color.red; - frame_background.green = color.green; - frame_background.blue = color.blue; + frame_background.red = 256 * GetRValue (color); + frame_background.green = 256 * GetGValue (color); + frame_background.blue = 256 * GetBValue (color); - png_set_background (png_ptr, &frame_background, - PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); + fn_png_set_background (png_ptr, &frame_background, + PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); } } /* Update info structure. */ - png_read_update_info (png_ptr, info_ptr); + fn_png_read_update_info (png_ptr, info_ptr); /* Get number of channels. Valid values are 1 for grayscale images and images with a palette, 2 for grayscale images with transparency information (alpha channel), 3 for RGB images, and 4 for RGB images with alpha channel, i.e. RGBA. If conversions above were sufficient we should only have 3 or 4 channels here. */ - channels = png_get_channels (png_ptr, info_ptr); + channels = fn_png_get_channels (png_ptr, info_ptr); xassert (channels == 3 || channels == 4); /* Number of bytes needed for one row of the image. */ - row_bytes = png_get_rowbytes (png_ptr, info_ptr); + row_bytes = fn_png_get_rowbytes (png_ptr, info_ptr); /* Allocate memory for the image. */ pixels = (png_byte *) xmalloc (row_bytes * height * sizeof *pixels); @@ -11867,8 +10841,8 @@ png_load (f, img) rows[i] = pixels + i * row_bytes; /* Read the entire image. */ - png_read_image (png_ptr, rows); - png_read_end (png_ptr, info_ptr); + fn_png_read_image (png_ptr, rows); + fn_png_read_end (png_ptr, info_ptr); if (fp) { fclose (fp); @@ -11888,13 +10862,14 @@ png_load (f, img) &mask_img, &img->mask)) { x_destroy_x_image (ximg); - XFreePixmap (FRAME_W32_DISPLAY (f), img->pixmap); + DeleteObject (img->pixmap); img->pixmap = 0; goto error; } - /* Fill the X image and mask from PNG data. */ +#if 0 /* TODO: Color tables. */ init_color_table (); +#endif for (y = 0; y < height; ++y) { @@ -11904,11 +10879,14 @@ png_load (f, img) { unsigned r, g, b; - r = *p++ << 8; - g = *p++ << 8; - b = *p++ << 8; + r = *p++; + g = *p++; + b = *p++; +#if 0 /* TODO: Color tables. */ XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b)); - +#else + XPutPixel (ximg, x, y, PALETTERGB (r, g, b)); +#endif /* An alpha channel, aka mask channel, associates variable transparency with an image. Where other image formats support binary transparency---fully transparent or fully @@ -11939,19 +10917,26 @@ png_load (f, img) overrode it. */ { png_color_16 *bg; - if (png_get_bKGD (png_ptr, info_ptr, &bg)) + if (fn_png_get_bKGD (png_ptr, info_ptr, &bg)) { +#if 0 /* TODO: Color tables. */ img->background = lookup_rgb_color (f, bg->red, bg->green, bg->blue); +#else + img->background = PALETTERGB (bg->red / 256, bg->green / 256, + bg->blue / 256); +#endif img->background_valid = 1; } } +#if 0 /* TODO: Color tables. */ /* Remember colors allocated for this image. */ img->colors = colors_in_color_table (&img->ncolors); free_color_table (); +#endif /* Clean up. */ - png_destroy_read_struct (&png_ptr, &info_ptr, &end_info); + fn_png_destroy_read_struct (&png_ptr, &info_ptr, &end_info); xfree (rows); xfree (pixels); @@ -12037,7 +11022,7 @@ static struct image_keyword jpeg_format[JPEG_LAST] = {":type", IMAGE_SYMBOL_VALUE, 1}, {":data", IMAGE_STRING_VALUE, 0}, {":file", IMAGE_STRING_VALUE, 0}, - {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0}, + {":ascent", IMAGE_ASCENT_VALUE, 0}, {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0}, {":relief", IMAGE_INTEGER_VALUE, 0}, {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, @@ -12058,6 +11043,44 @@ static struct image_type jpeg_type = }; +/* JPEG library details. */ +DEF_IMGLIB_FN (jpeg_CreateDecompress); +DEF_IMGLIB_FN (jpeg_start_decompress); +DEF_IMGLIB_FN (jpeg_finish_decompress); +DEF_IMGLIB_FN (jpeg_destroy_decompress); +DEF_IMGLIB_FN (jpeg_read_header); +DEF_IMGLIB_FN (jpeg_read_scanlines); +DEF_IMGLIB_FN (jpeg_stdio_src); +DEF_IMGLIB_FN (jpeg_std_error); +DEF_IMGLIB_FN (jpeg_resync_to_restart); + +static int +init_jpeg_functions (library) + HMODULE library; +{ + LOAD_IMGLIB_FN (library, jpeg_finish_decompress); + LOAD_IMGLIB_FN (library, jpeg_read_scanlines); + LOAD_IMGLIB_FN (library, jpeg_start_decompress); + LOAD_IMGLIB_FN (library, jpeg_read_header); + LOAD_IMGLIB_FN (library, jpeg_stdio_src); + LOAD_IMGLIB_FN (library, jpeg_CreateDecompress); + LOAD_IMGLIB_FN (library, jpeg_destroy_decompress); + LOAD_IMGLIB_FN (library, jpeg_std_error); + LOAD_IMGLIB_FN (library, jpeg_resync_to_restart); + return 1; +} + +/* Wrapper since we can't directly assign the function pointer + to another function pointer that was declared more completely easily. */ +static boolean +jpeg_resync_to_restart_wrapper(cinfo, desired) + j_decompress_ptr cinfo; + int desired; +{ + return fn_jpeg_resync_to_restart (cinfo, desired); +} + + /* Return non-zero if OBJECT is a valid JPEG image specification. */ static int @@ -12068,9 +11091,7 @@ jpeg_image_p (object) bcopy (jpeg_format, fmt, sizeof fmt); - if (!parse_image_spec (object, fmt, JPEG_LAST, Qjpeg) - || (fmt[JPEG_ASCENT].count - && XFASTINT (fmt[JPEG_ASCENT].value) > 100)) + if (!parse_image_spec (object, fmt, JPEG_LAST, Qjpeg)) return 0; /* Must specify either the :data or :file keyword. */ @@ -12084,6 +11105,7 @@ struct my_jpeg_error_mgr jmp_buf setjmp_buffer; }; + static void my_error_exit (cinfo) j_common_ptr cinfo; @@ -12092,6 +11114,7 @@ my_error_exit (cinfo) longjmp (mgr->setjmp_buffer, 1); } + /* Init source method for JPEG data source manager. Called by jpeg_read_header() before any data is actually read. See libjpeg.doc from the JPEG lib distribution. */ @@ -12181,7 +11204,7 @@ jpeg_memory_src (cinfo, data, len) src->init_source = our_init_source; src->fill_input_buffer = our_fill_input_buffer; src->skip_input_data = our_skip_input_data; - src->resync_to_restart = jpeg_resync_to_restart; /* Use default method. */ + src->resync_to_restart = jpeg_resync_to_restart_wrapper; /* Use default method. */ src->term_source = our_term_source; src->bytes_in_buffer = len; src->next_input_byte = data; @@ -12219,24 +11242,24 @@ jpeg_load (f, img) { file = x_find_image_file (specified_file); if (!STRINGP (file)) - { - image_error ("Cannot find image file `%s'", specified_file, Qnil); - UNGCPRO; - return 0; - } + { + image_error ("Cannot find image file `%s'", specified_file, Qnil); + UNGCPRO; + return 0; + } - fp = fopen (SDATA (file), "r"); + fp = fopen (SDATA (file), "rb"); if (fp == NULL) - { - image_error ("Cannot open `%s'", file, Qnil); - UNGCPRO; - return 0; - } + { + image_error ("Cannot open `%s'", file, Qnil); + UNGCPRO; + return 0; + } } /* Customize libjpeg's error handling to call my_error_exit when an - error is detected. This function will perform a longjmp. */ - cinfo.err = jpeg_std_error (&mgr.pub); + error is detected. This function will perform a longjmp. */ + cinfo.err = fn_jpeg_std_error (&mgr.pub); mgr.pub.error_exit = my_error_exit; if ((rc = setjmp (mgr.setjmp_buffer)) != 0) @@ -12252,8 +11275,8 @@ jpeg_load (f, img) /* Close the input file and destroy the JPEG object. */ if (fp) - fclose (fp); - jpeg_destroy_decompress (&cinfo); + fclose ((FILE *) fp); + fn_jpeg_destroy_decompress (&cinfo); /* If we already have an XImage, free that. */ x_destroy_x_image (ximg); @@ -12266,27 +11289,26 @@ jpeg_load (f, img) } /* Create the JPEG decompression object. Let it read from fp. - Read the JPEG image header. */ - jpeg_create_decompress (&cinfo); + Read the JPEG image header. */ + fn_jpeg_CreateDecompress (&cinfo, JPEG_LIB_VERSION, sizeof (cinfo)); if (NILP (specified_data)) - jpeg_stdio_src (&cinfo, fp); + fn_jpeg_stdio_src (&cinfo, (FILE *) fp); else jpeg_memory_src (&cinfo, SDATA (specified_data), SBYTES (specified_data)); - jpeg_read_header (&cinfo, TRUE); + fn_jpeg_read_header (&cinfo, TRUE); /* Customize decompression so that color quantization will be used. - Start decompression. */ + Start decompression. */ cinfo.quantize_colors = TRUE; - jpeg_start_decompress (&cinfo); + fn_jpeg_start_decompress (&cinfo); width = img->width = cinfo.output_width; height = img->height = cinfo.output_height; /* Create X image and pixmap. */ - if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, - &img->pixmap)) + if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap)) longjmp (mgr.setjmp_buffer, 2); /* Allocate colors. When color quantization is used, @@ -12304,27 +11326,33 @@ jpeg_load (f, img) else ir = 0, ig = 0, ib = 0; +#if 0 /* TODO: Color tables. */ /* Use the color table mechanism because it handles colors that cannot be allocated nicely. Such colors will be replaced with a default color, and we don't have to care about which colors can be freed safely, and which can't. */ init_color_table (); +#endif colors = (unsigned long *) alloca (cinfo.actual_number_of_colors * sizeof *colors); for (i = 0; i < cinfo.actual_number_of_colors; ++i) { - /* Multiply RGB values with 255 because X expects RGB values - in the range 0..0xffff. */ - int r = cinfo.colormap[ir][i] << 8; - int g = cinfo.colormap[ig][i] << 8; - int b = cinfo.colormap[ib][i] << 8; + int r = cinfo.colormap[ir][i]; + int g = cinfo.colormap[ig][i]; + int b = cinfo.colormap[ib][i]; +#if 0 /* TODO: Color tables. */ colors[i] = lookup_rgb_color (f, r, g, b); +#else + colors[i] = PALETTERGB (r, g, b); +#endif } +#if 0 /* TODO: Color tables. */ /* Remember those colors actually allocated. */ img->colors = colors_in_color_table (&img->ncolors); free_color_table (); +#endif } /* Read pixels. */ @@ -12333,16 +11361,16 @@ jpeg_load (f, img) row_stride, 1); for (y = 0; y < height; ++y) { - jpeg_read_scanlines (&cinfo, buffer, 1); + fn_jpeg_read_scanlines (&cinfo, buffer, 1); for (x = 0; x < cinfo.output_width; ++x) XPutPixel (ximg, x, y, colors[buffer[0][x]]); } /* Clean up. */ - jpeg_finish_decompress (&cinfo); - jpeg_destroy_decompress (&cinfo); + fn_jpeg_finish_decompress (&cinfo); + fn_jpeg_destroy_decompress (&cinfo); if (fp) - fclose (fp); + fclose ((FILE *) fp); /* Maybe fill in the background field while we have ximg handy. */ if (NILP (image_spec_value (img->spec, QCbackground, NULL))) @@ -12351,7 +11379,6 @@ jpeg_load (f, img) /* Put the image into the pixmap. */ x_put_x_image (f, ximg, img->pixmap, width, height); x_destroy_x_image (ximg); - UNBLOCK_INPUT; UNGCPRO; return 1; } @@ -12400,7 +11427,7 @@ static struct image_keyword tiff_format[TIFF_LAST] = {":type", IMAGE_SYMBOL_VALUE, 1}, {":data", IMAGE_STRING_VALUE, 0}, {":file", IMAGE_STRING_VALUE, 0}, - {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0}, + {":ascent", IMAGE_ASCENT_VALUE, 0}, {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0}, {":relief", IMAGE_INTEGER_VALUE, 0}, {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, @@ -12420,6 +11447,28 @@ static struct image_type tiff_type = NULL }; +/* TIFF library details. */ +DEF_IMGLIB_FN (TIFFSetErrorHandler); +DEF_IMGLIB_FN (TIFFSetWarningHandler); +DEF_IMGLIB_FN (TIFFOpen); +DEF_IMGLIB_FN (TIFFClientOpen); +DEF_IMGLIB_FN (TIFFGetField); +DEF_IMGLIB_FN (TIFFReadRGBAImage); +DEF_IMGLIB_FN (TIFFClose); + +static int +init_tiff_functions (library) + HMODULE library; +{ + LOAD_IMGLIB_FN (library, TIFFSetErrorHandler); + LOAD_IMGLIB_FN (library, TIFFSetWarningHandler); + LOAD_IMGLIB_FN (library, TIFFOpen); + LOAD_IMGLIB_FN (library, TIFFClientOpen); + LOAD_IMGLIB_FN (library, TIFFGetField); + LOAD_IMGLIB_FN (library, TIFFReadRGBAImage); + LOAD_IMGLIB_FN (library, TIFFClose); + return 1; +} /* Return non-zero if OBJECT is a valid TIFF image specification. */ @@ -12430,9 +11479,7 @@ tiff_image_p (object) struct image_keyword fmt[TIFF_LAST]; bcopy (tiff_format, fmt, sizeof fmt); - if (!parse_image_spec (object, fmt, TIFF_LAST, Qtiff) - || (fmt[TIFF_ASCENT].count - && XFASTINT (fmt[TIFF_ASCENT].value) > 100)) + if (!parse_image_spec (object, fmt, TIFF_LAST, Qtiff)) return 0; /* Must specify either the :data or :file keyword. */ @@ -12601,8 +11648,8 @@ tiff_load (f, img) file = Qnil; GCPRO1 (file); - TIFFSetErrorHandler (tiff_error_handler); - TIFFSetWarningHandler (tiff_warning_handler); + fn_TIFFSetErrorHandler (tiff_error_handler); + fn_TIFFSetWarningHandler (tiff_warning_handler); if (NILP (specified_data)) { @@ -12616,7 +11663,7 @@ tiff_load (f, img) } /* Try to open the image file. */ - tiff = TIFFOpen (SDATA (file), "r"); + tiff = fn_TIFFOpen (SDATA (file), "r"); if (tiff == NULL) { image_error ("Cannot open `%s'", file, Qnil); @@ -12631,14 +11678,14 @@ tiff_load (f, img) memsrc.len = SBYTES (specified_data); memsrc.index = 0; - tiff = TIFFClientOpen ("memory_source", "r", &memsrc, - (TIFFReadWriteProc) tiff_read_from_memory, - (TIFFReadWriteProc) tiff_write_from_memory, - tiff_seek_in_memory, - tiff_close_memory, - tiff_size_of_memory, - tiff_mmap_memory, - tiff_unmap_memory); + tiff = fn_TIFFClientOpen ("memory_source", "r", &memsrc, + (TIFFReadWriteProc) tiff_read_from_memory, + (TIFFReadWriteProc) tiff_write_from_memory, + tiff_seek_in_memory, + tiff_close_memory, + tiff_size_of_memory, + tiff_mmap_memory, + tiff_unmap_memory); if (!tiff) { @@ -12650,12 +11697,12 @@ tiff_load (f, img) /* Get width and height of the image, and allocate a raster buffer of width x height 32-bit values. */ - TIFFGetField (tiff, TIFFTAG_IMAGEWIDTH, &width); - TIFFGetField (tiff, TIFFTAG_IMAGELENGTH, &height); + fn_TIFFGetField (tiff, TIFFTAG_IMAGEWIDTH, &width); + fn_TIFFGetField (tiff, TIFFTAG_IMAGELENGTH, &height); buf = (uint32 *) xmalloc (width * height * sizeof *buf); - rc = TIFFReadRGBAImage (tiff, width, height, buf, 0); - TIFFClose (tiff); + rc = fn_TIFFReadRGBAImage (tiff, width, height, buf, 0); + fn_TIFFClose (tiff); if (!rc) { image_error ("Error reading TIFF image `%s'", img->spec, Qnil); @@ -12672,8 +11719,10 @@ tiff_load (f, img) return 0; } +#if 0 /* TODO: Color tables. */ /* Initialize the color table. */ init_color_table (); +#endif /* Process the pixel raster. Origin is in the lower-left corner. */ for (y = 0; y < height; ++y) @@ -12683,16 +11732,22 @@ tiff_load (f, img) for (x = 0; x < width; ++x) { uint32 abgr = row[x]; - int r = TIFFGetR (abgr) << 8; - int g = TIFFGetG (abgr) << 8; - int b = TIFFGetB (abgr) << 8; + int r = TIFFGetR (abgr); + int g = TIFFGetG (abgr); + int b = TIFFGetB (abgr); +#if 0 /* TODO: Color tables. */ XPutPixel (ximg, x, height - 1 - y, lookup_rgb_color (f, r, g, b)); +#else + XPutPixel (ximg, x, height - 1 - y, PALETTERGB (r, g, b)); +#endif } } +#if 0 /* TODO: Color tables. */ /* Remember the colors allocated for the image. Free the color table. */ img->colors = colors_in_color_table (&img->ncolors); free_color_table (); +#endif img->width = width; img->height = height; @@ -12720,7 +11775,9 @@ tiff_load (f, img) #if HAVE_GIF +#define DrawText gif_DrawText #include +#undef DrawText static int gif_image_p P_ ((Lisp_Object object)); static int gif_load P_ ((struct frame *f, struct image *img)); @@ -12755,7 +11812,7 @@ static struct image_keyword gif_format[GIF_LAST] = {":type", IMAGE_SYMBOL_VALUE, 1}, {":data", IMAGE_STRING_VALUE, 0}, {":file", IMAGE_STRING_VALUE, 0}, - {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0}, + {":ascent", IMAGE_ASCENT_VALUE, 0}, {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0}, {":relief", IMAGE_INTEGER_VALUE, 0}, {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, @@ -12776,6 +11833,25 @@ static struct image_type gif_type = NULL }; + +/* GIF library details. */ +DEF_IMGLIB_FN (DGifCloseFile); +DEF_IMGLIB_FN (DGifSlurp); +DEF_IMGLIB_FN (DGifOpen); +DEF_IMGLIB_FN (DGifOpenFileName); + +static int +init_gif_functions (library) + HMODULE library; +{ + LOAD_IMGLIB_FN (library, DGifCloseFile); + LOAD_IMGLIB_FN (library, DGifSlurp); + LOAD_IMGLIB_FN (library, DGifOpen); + LOAD_IMGLIB_FN (library, DGifOpenFileName); + return 1; +} + + /* Return non-zero if OBJECT is a valid GIF image specification. */ static int @@ -12785,9 +11861,7 @@ gif_image_p (object) struct image_keyword fmt[GIF_LAST]; bcopy (gif_format, fmt, sizeof fmt); - if (!parse_image_spec (object, fmt, GIF_LAST, Qgif) - || (fmt[GIF_ASCENT].count - && XFASTINT (fmt[GIF_ASCENT].value) > 100)) + if (!parse_image_spec (object, fmt, GIF_LAST, Qgif)) return 0; /* Must specify either the :data or :file keyword. */ @@ -12864,7 +11938,7 @@ gif_load (f, img) } /* Open the GIF file. */ - gif = DGifOpenFileName (SDATA (file)); + gif = fn_DGifOpenFileName (SDATA (file)); if (gif == NULL) { image_error ("Cannot open `%s'", file, Qnil); @@ -12880,7 +11954,7 @@ gif_load (f, img) memsrc.len = SBYTES (specified_data); memsrc.index = 0; - gif = DGifOpen(&memsrc, gif_read_from_memory); + gif = fn_DGifOpen(&memsrc, gif_read_from_memory); if (!gif) { image_error ("Cannot open memory source `%s'", img->spec, Qnil); @@ -12890,11 +11964,11 @@ gif_load (f, img) } /* Read entire contents. */ - rc = DGifSlurp (gif); + rc = fn_DGifSlurp (gif); if (rc == GIF_ERROR) { image_error ("Error reading `%s'", img->spec, Qnil); - DGifCloseFile (gif); + fn_DGifCloseFile (gif); UNGCPRO; return 0; } @@ -12905,18 +11979,18 @@ gif_load (f, img) { image_error ("Invalid image number `%s' in image `%s'", image, img->spec); - DGifCloseFile (gif); + fn_DGifCloseFile (gif); UNGCPRO; return 0; } - width = img->width = gif->SWidth; - height = img->height = gif->SHeight; + width = img->width = max (gif->SWidth, gif->Image.Left + gif->Image.Width); + height = img->height = max (gif->SHeight, gif->Image.Top + gif->Image.Height); /* Create the X image and pixmap. */ if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap)) { - DGifCloseFile (gif); + fn_DGifCloseFile (gif); UNGCPRO; return 0; } @@ -12925,19 +11999,27 @@ gif_load (f, img) gif_color_map = gif->SavedImages[ino].ImageDesc.ColorMap; if (!gif_color_map) gif_color_map = gif->SColorMap; +#if 0 /* TODO: Color tables */ init_color_table (); +#endif bzero (pixel_colors, sizeof pixel_colors); for (i = 0; i < gif_color_map->ColorCount; ++i) { - int r = gif_color_map->Colors[i].Red << 8; - int g = gif_color_map->Colors[i].Green << 8; - int b = gif_color_map->Colors[i].Blue << 8; + int r = gif_color_map->Colors[i].Red; + int g = gif_color_map->Colors[i].Green; + int b = gif_color_map->Colors[i].Blue; +#if 0 /* TODO: Color tables */ pixel_colors[i] = lookup_rgb_color (f, r, g, b); +#else + pixel_colors[i] = PALETTERGB (r, g, b); +#endif } +#if 0 /* TODO: Color tables */ img->colors = colors_in_color_table (&img->ncolors); free_color_table (); +#endif /* Clear the part of the screen image that are not covered by the image from the GIF file. Full animated GIF support @@ -13008,7 +12090,7 @@ gif_load (f, img) } } - DGifCloseFile (gif); + fn_DGifCloseFile (gif); /* Maybe fill in the background field while we have ximg handy. */ if (NILP (image_spec_value (img->spec, QCbackground, NULL))) @@ -13032,6 +12114,10 @@ gif_load (f, img) Lisp_Object Qpostscript; +/* Keyword symbols. */ + +Lisp_Object QCloader, QCbounding_box, QCpt_width, QCpt_height; + #ifdef HAVE_GHOSTSCRIPT static int gs_image_p P_ ((Lisp_Object object)); static int gs_load P_ ((struct frame *f, struct image *img)); @@ -13074,7 +12160,7 @@ static struct image_keyword gs_format[GS_LAST] = {":file", IMAGE_STRING_VALUE, 1}, {":loader", IMAGE_FUNCTION_VALUE, 0}, {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE, 1}, - {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0}, + {":ascent", IMAGE_ASCENT_VALUE, 0}, {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0}, {":relief", IMAGE_INTEGER_VALUE, 0}, {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, @@ -13121,9 +12207,7 @@ gs_image_p (object) bcopy (gs_format, fmt, sizeof fmt); - if (!parse_image_spec (object, fmt, GS_LAST, Qpostscript) - || (fmt[GS_ASCENT].count - && XFASTINT (fmt[GS_ASCENT].value) > 100)) + if (!parse_image_spec (object, fmt, GS_LAST, Qpostscript)) return 0; /* Bounding box must be a list or vector containing 4 integers. */ @@ -13704,7 +12788,7 @@ x_create_tip_frame (dpyinfo, parms, text) XSETFRAME (frame, f); buffer = Fget_buffer_create (build_string (" *tip*")); - Fset_window_buffer (FRAME_ROOT_WINDOW (f), buffer); + Fset_window_buffer (FRAME_ROOT_WINDOW (f), buffer, Qnil); old_buffer = current_buffer; set_buffer_internal_1 (XBUFFER (buffer)); current_buffer->truncate_lines = Qnil; @@ -13828,30 +12912,12 @@ x_create_tip_frame (dpyinfo, parms, text) f->output_data.w32->dwStyle = WS_BORDER | WS_POPUP | WS_DISABLED; f->output_data.w32->parent_desc = FRAME_W32_DISPLAY_INFO (f)->root_window; - window_prompting = x_figure_window_size (f, parms); + window_prompting = x_figure_window_size (f, parms, 0); /* No fringes on tip frame. */ - f->output_data.w32->fringes_extra = 0; - f->output_data.w32->fringe_cols = 0; - f->output_data.w32->left_fringe_width = 0; - f->output_data.w32->right_fringe_width = 0; - - if (window_prompting & XNegative) - { - if (window_prompting & YNegative) - f->output_data.w32->win_gravity = SouthEastGravity; - else - f->output_data.w32->win_gravity = NorthEastGravity; - } - else - { - if (window_prompting & YNegative) - f->output_data.w32->win_gravity = SouthWestGravity; - else - f->output_data.w32->win_gravity = NorthWestGravity; - } - - f->output_data.w32->size_hint_flags = window_prompting; + f->fringe_cols = 0; + f->left_fringe_width = 0; + f->right_fringe_width = 0; BLOCK_INPUT; my_create_tip_window (f); @@ -13866,13 +12932,13 @@ x_create_tip_frame (dpyinfo, parms, text) x_default_parameter (f, parms, Qcursor_type, Qbox, "cursorType", "CursorType", RES_TYPE_SYMBOL); - /* Dimensions, especially f->height, must be done via change_frame_size. + /* Dimensions, especially FRAME_LINES (f), must be done via change_frame_size. Change will not be effected unless different from the current - f->height. */ - width = f->width; - height = f->height; - f->height = 0; - SET_FRAME_WIDTH (f, 0); + FRAME_LINES (f). */ + width = FRAME_COLS (f); + height = FRAME_LINES (f); + FRAME_LINES (f) = 0; + SET_FRAME_COLS (f, 0); change_frame_size (f, height, width, 1, 0, 0); /* Add `tooltip' frame parameter's default value. */ @@ -14061,8 +13127,8 @@ Text larger than the specified size is clipped. */) } BLOCK_INPUT; - compute_tip_xy (f, parms, dx, dy, PIXEL_WIDTH (f), - PIXEL_HEIGHT (f), &root_x, &root_y); + compute_tip_xy (f, parms, dx, dy, FRAME_PIXEL_WIDTH (f), + FRAME_PIXEL_HEIGHT (f), &root_x, &root_y); /* Put tooltip in topmost group and in position. */ SetWindowPos (FRAME_W32_WINDOW (f), HWND_TOPMOST, @@ -14110,7 +13176,7 @@ Text larger than the specified size is clipped. */) /* Set up the frame's root window. */ w = XWINDOW (FRAME_ROOT_WINDOW (f)); - w->left = w->top = make_number (0); + w->left_col = w->top_line = make_number (0); if (CONSP (Vx_max_tooltip_size) && INTEGERP (XCAR (Vx_max_tooltip_size)) @@ -14118,16 +13184,16 @@ Text larger than the specified size is clipped. */) && 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); + w->total_cols = XCAR (Vx_max_tooltip_size); + w->total_lines = XCDR (Vx_max_tooltip_size); } else { - w->width = make_number (80); - w->height = make_number (40); + w->total_cols = make_number (80); + w->total_lines = make_number (40); } - f->window_width = XINT (w->width); + FRAME_TOTAL_COLS (f) = XINT (w->total_cols); adjust_glyphs (f); w->pseudo_window_p = 1; @@ -14864,91 +13930,62 @@ If the underlying system call fails, value is nil. */) Initialization ***********************************************************************/ +/* Keep this list in the same order as frame_parms in frame.c. + Use 0 for unsupported frame parameters. */ + +frame_parm_handler w32_frame_parm_handlers[] = +{ + x_set_autoraise, + x_set_autolower, + x_set_background_color, + x_set_border_color, + x_set_border_width, + x_set_cursor_color, + x_set_cursor_type, + x_set_font, + x_set_foreground_color, + x_set_icon_name, + x_set_icon_type, + x_set_internal_border_width, + x_set_menu_bar_lines, + x_set_mouse_color, + x_explicitly_set_name, + x_set_scroll_bar_width, + x_set_title, + x_set_unsplittable, + x_set_vertical_scroll_bars, + x_set_visibility, + x_set_tool_bar_lines, + 0, /* x_set_scroll_bar_foreground, */ + 0, /* x_set_scroll_bar_background, */ + x_set_screen_gamma, + x_set_line_spacing, + x_set_fringe_width, + x_set_fringe_width, + 0, /* x_set_wait_for_wm, */ + x_set_fullscreen, +}; + void syms_of_w32fns () { - HMODULE user32_lib = GetModuleHandle ("user32.dll"); - + globals_of_w32fns (); /* This is zero if not using MS-Windows. */ w32_in_use = 0; - - /* TrackMouseEvent not available in all versions of Windows, so must load - it dynamically. Do it once, here, instead of every time it is used. */ - track_mouse_event_fn = (TrackMouseEvent_Proc) GetProcAddress (user32_lib, "TrackMouseEvent"); track_mouse_window = NULL; w32_visible_system_caret_hwnd = NULL; - Qauto_raise = intern ("auto-raise"); - staticpro (&Qauto_raise); - Qauto_lower = intern ("auto-lower"); - staticpro (&Qauto_lower); - Qborder_color = intern ("border-color"); - staticpro (&Qborder_color); - Qborder_width = intern ("border-width"); - staticpro (&Qborder_width); - Qcursor_color = intern ("cursor-color"); - staticpro (&Qcursor_color); - Qcursor_type = intern ("cursor-type"); - staticpro (&Qcursor_type); - Qgeometry = intern ("geometry"); - staticpro (&Qgeometry); - Qicon_left = intern ("icon-left"); - staticpro (&Qicon_left); - Qicon_top = intern ("icon-top"); - staticpro (&Qicon_top); - Qicon_type = intern ("icon-type"); - staticpro (&Qicon_type); - Qicon_name = intern ("icon-name"); - staticpro (&Qicon_name); - Qinternal_border_width = intern ("internal-border-width"); - staticpro (&Qinternal_border_width); - Qleft = intern ("left"); - staticpro (&Qleft); - Qright = intern ("right"); - staticpro (&Qright); - Qmouse_color = intern ("mouse-color"); - staticpro (&Qmouse_color); Qnone = intern ("none"); staticpro (&Qnone); - Qparent_id = intern ("parent-id"); - staticpro (&Qparent_id); - Qscroll_bar_width = intern ("scroll-bar-width"); - staticpro (&Qscroll_bar_width); Qsuppress_icon = intern ("suppress-icon"); staticpro (&Qsuppress_icon); Qundefined_color = intern ("undefined-color"); staticpro (&Qundefined_color); - Qvertical_scroll_bars = intern ("vertical-scroll-bars"); - staticpro (&Qvertical_scroll_bars); - Qvisibility = intern ("visibility"); - staticpro (&Qvisibility); - Qwindow_id = intern ("window-id"); - staticpro (&Qwindow_id); - Qx_frame_parameter = intern ("x-frame-parameter"); - staticpro (&Qx_frame_parameter); - Qx_resource_name = intern ("x-resource-name"); - staticpro (&Qx_resource_name); - Quser_position = intern ("user-position"); - staticpro (&Quser_position); - Quser_size = intern ("user-size"); - staticpro (&Quser_size); - Qscreen_gamma = intern ("screen-gamma"); - staticpro (&Qscreen_gamma); - Qline_spacing = intern ("line-spacing"); - staticpro (&Qline_spacing); Qcenter = intern ("center"); staticpro (&Qcenter); Qcancel_timer = intern ("cancel-timer"); staticpro (&Qcancel_timer); - Qfullscreen = intern ("fullscreen"); - staticpro (&Qfullscreen); - Qfullwidth = intern ("fullwidth"); - staticpro (&Qfullwidth); - Qfullheight = intern ("fullheight"); - staticpro (&Qfullheight); - Qfullboth = intern ("fullboth"); - staticpro (&Qfullboth); Qhyper = intern ("hyper"); staticpro (&Qhyper); @@ -14986,9 +14023,6 @@ syms_of_w32fns () QCmask = intern (":mask"); staticpro (&QCmask); - Qface_set_after_frame_default = intern ("face-set-after-frame-default"); - staticpro (&Qface_set_after_frame_default); - Fput (Qundefined_color, Qerror_conditions, Fcons (Qundefined_color, Fcons (Qerror, Qnil))); Fput (Qundefined_color, Qerror_message, @@ -15119,10 +14153,8 @@ If this variable is non-nil, Emacs will pass them on, allowing the system to handle them. */); w32_pass_extra_mouse_buttons_to_system = 0; - init_x_parm_symbols (); - DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path, - doc: /* List of directories to search for bitmap files for w32. */); + doc: /* List of directories to search for window system bitmap files. */); Vx_bitmap_file_path = decode_env_path ((char *) 0, "PATH"); DEFVAR_LISP ("x-pointer-shape", &Vx_pointer_shape, @@ -15131,15 +14163,6 @@ 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, - doc: /* The name Emacs uses to look up resources; for internal use only. -`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. */); - Vx_resource_name = Qnil; - Vx_nontext_pointer_shape = Qnil; Vx_mode_pointer_shape = Qnil; @@ -15241,15 +14264,11 @@ WINDOWS_CHARSET is a symbol that can be one of: w32-charset-ansi, w32-charset-default, w32-charset-symbol, w32-charset-shiftjis, w32-charset-hangeul, w32-charset-gb2312, w32-charset-chinesebig5, -#ifdef JOHAB_CHARSET w32-charset-johab, w32-charset-hebrew, w32-charset-arabic, w32-charset-greek, w32-charset-turkish, w32-charset-vietnamese, w32-charset-thai, w32-charset-easteurope, w32-charset-russian, w32-charset-mac, w32-charset-baltic, -#endif -#ifdef UNICODE_CHARSET w32-charset-unicode, -#endif or w32-charset-oem. CODEPAGE should be an integer specifying the codepage that should be used to display the character set, t to do no translation and output as Unicode, @@ -15314,7 +14333,6 @@ versions of Windows) characters. */); Qw32_charset_unicode = intern ("w32-charset-unicode"); #endif - defsubr (&Sx_get_resource); #if 0 /* TODO: Port to W32 */ defsubr (&Sx_change_window_property); defsubr (&Sx_delete_window_property); @@ -15337,7 +14355,6 @@ versions of Windows) characters. */); defsubr (&Sx_display_visual_class); defsubr (&Sx_display_backing_store); defsubr (&Sx_display_save_under); - defsubr (&Sx_parse_geometry); defsubr (&Sx_create_frame); defsubr (&Sx_open_connection); defsubr (&Sx_close_connection); @@ -15393,7 +14410,6 @@ versions of Windows) characters. */); staticpro (&QCrelief); Qpostscript = intern ("postscript"); staticpro (&Qpostscript); -#if 0 /* TODO: These need entries at top of file. */ QCloader = intern (":loader"); staticpro (&QCloader); QCbounding_box = intern (":bounding-box"); @@ -15402,7 +14418,6 @@ versions of Windows) characters. */); staticpro (&QCpt_width); QCpt_height = intern (":pt-height"); staticpro (&QCpt_height); -#endif QCindex = intern (":index"); staticpro (&QCindex); Qpbm = intern ("pbm"); @@ -15437,11 +14452,6 @@ versions of Windows) characters. */); defsubr (&Simage_size); defsubr (&Simage_mask_p); -#if GLYPH_DEBUG - defsubr (&Simagep); - defsubr (&Slookup_image); -#endif - hourglass_atimer = NULL; hourglass_shown_p = 0; defsubr (&Sx_show_tip); @@ -15458,37 +14468,104 @@ versions of Windows) characters. */); } -void -init_xfns () +/* + globals_of_w32fns is used to initialize those global variables that + must always be initialized on startup even when the global variable + initialized is non zero (see the function main in emacs.c). + globals_of_w32fns is called from syms_of_w32fns when the global + variable initialized is 0 and directly from main when initialized + is non zero. + */ +void globals_of_w32fns () { - image_types = NULL; - Vimage_types = Qnil; + HMODULE user32_lib = GetModuleHandle ("user32.dll"); + /* + TrackMouseEvent not available in all versions of Windows, so must load + it dynamically. Do it once, here, instead of every time it is used. + */ + track_mouse_event_fn = (TrackMouseEvent_Proc) + GetProcAddress (user32_lib, "TrackMouseEvent"); + /* ditto for GetClipboardSequenceNumber. */ + clipboard_sequence_fn = (ClipboardSequence_Proc) + GetProcAddress (user32_lib, "GetClipboardSequenceNumber"); +} - define_image_type (&pbm_type); - define_image_type (&xbm_type); -#if 0 /* TODO : Image support for W32 */ - define_image_type (&gs_type); -#endif +/* Initialize image types. Based on which libraries are available. */ +static void +init_external_image_libraries () +{ + HINSTANCE library; #if HAVE_XPM - define_image_type (&xpm_type); + if ((library = LoadLibrary ("libXpm.dll"))) + { + if (init_xpm_functions (library)) + define_image_type (&xpm_type); + } + #endif #if HAVE_JPEG - define_image_type (&jpeg_type); + /* Try loading jpeg library under probable names. */ + if ((library = LoadLibrary ("libjpeg.dll")) + || (library = LoadLibrary ("jpeg-62.dll")) + || (library = LoadLibrary ("jpeg.dll"))) + { + if (init_jpeg_functions (library)) + define_image_type (&jpeg_type); + } #endif #if HAVE_TIFF - define_image_type (&tiff_type); + if (library = LoadLibrary ("libtiff.dll")) + { + if (init_tiff_functions (library)) + define_image_type (&tiff_type); + } #endif #if HAVE_GIF - define_image_type (&gif_type); + if (library = LoadLibrary ("libungif.dll")) + { + if (init_gif_functions (library)) + define_image_type (&gif_type); + } #endif #if HAVE_PNG - define_image_type (&png_type); + /* Ensure zlib is loaded. Try debug version first. */ + if (!LoadLibrary ("zlibd.dll")) + LoadLibrary ("zlib.dll"); + + /* Try loading libpng under probable names. */ + if ((library = LoadLibrary ("libpng13d.dll")) + || (library = LoadLibrary ("libpng13.dll")) + || (library = LoadLibrary ("libpng12d.dll")) + || (library = LoadLibrary ("libpng12.dll")) + || (library = LoadLibrary ("libpng.dll"))) + { + if (init_png_functions (library)) + define_image_type (&png_type); + } +#endif +} + +void +init_xfns () +{ + image_types = NULL; + Vimage_types = Qnil; + + define_image_type (&pbm_type); + define_image_type (&xbm_type); + +#if 0 /* TODO : Ghostscript support for W32 */ + define_image_type (&gs_type); #endif + + /* Image types that rely on external libraries are loaded dynamically + if the library is available. */ + init_external_image_libraries (); } #undef abort @@ -15523,3 +14600,6 @@ w32_last_error() { return GetLastError (); } + +/* arch-tag: 707589ab-b9be-4638-8cdd-74629cc9b446 + (do not change this comment) */