#include <ctype.h>
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 (int vk_code, Lisp_Object new_state);
+extern int w32_console_toggle_lock_key P_ ((int, Lisp_Object));
+extern void w32_menu_display_help P_ ((HWND, HMENU, UINT, UINT));
+extern void w32_free_menu_strings P_ ((HWND));
+
extern int quit_char;
/* A definition of XColor for non-X frames. */
/* Switch to control whether we inhibit requests for synthesized bold
and italic versions of fonts. */
-Lisp_Object Vw32_enable_synthesized_fonts;
+int w32_enable_synthesized_fonts;
/* Enable palette management. */
Lisp_Object Vw32_enable_palette;
events that are passed on to the event loop. */
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;
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;
-extern Lisp_Object Qtool_bar_lines;
/* State variables for emulating a three button mouse. */
#define LMOUSE 1
static int button_state = 0;
static W32Msg saved_mouse_button_msg;
-static unsigned mouse_button_timer; /* non-zero when timer is active */
+static unsigned mouse_button_timer = 0; /* non-zero when timer is active */
static W32Msg saved_mouse_move_msg;
-static unsigned mouse_move_timer;
+static unsigned mouse_move_timer = 0;
+
+/* Window that is tracking the mouse. */
+static HWND track_mouse_window;
+FARPROC track_mouse_event_fn;
/* W95 mousewheel handler */
unsigned int msh_mousewheel = 0;
+/* Timers */
#define MOUSE_BUTTON_ID 1
#define MOUSE_MOVE_ID 2
+#define MENU_FREE_ID 3
+/* The delay (milliseconds) before a menu is freed after WM_EXITMENULOOP
+ is received. */
+#define MENU_FREE_DELAY 1000
+static unsigned menu_free_timer = 0;
/* The below are defined in frame.c. */
extern Lisp_Object Vw32_recognize_altgr;
extern HWND w32_system_caret_hwnd;
-extern int w32_system_caret_width;
+
extern int w32_system_caret_height;
extern int w32_system_caret_x;
extern int w32_system_caret_y;
+extern int w32_use_visible_system_caret;
+
+static HWND w32_visible_system_caret_hwnd;
\f
/* Error if we are not connected to MS-Windows. */
/* 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));
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));
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
+ {"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
make_number (i));
}
\f
+/* 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. */
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;
/* 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))
+ 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)))
{
icon_top = val;
else if (EQ (prop, Qicon_left))
icon_left = val;
- else if (EQ (prop, Qforeground_color) || EQ (prop, Qbackground_color))
+ else if (EQ (prop, Qforeground_color)
+ || EQ (prop, Qbackground_color)
+ || EQ (prop, Qfont)
+ || EQ (prop, Qfullscreen))
/* Processed above. */
continue;
else
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
int *xptr, *yptr;
{
POINT pt;
+ RECT rect;
- {
- RECT rect;
-
- GetClientRect(FRAME_W32_WINDOW(f), &rect);
- AdjustWindowRect(&rect, f->output_data.w32->dwStyle, FRAME_EXTERNAL_MENU_BAR(f));
-
- pt.x = rect.left;
- pt.y = rect.top;
- }
+ GetClientRect(FRAME_W32_WINDOW(f), &rect);
+ AdjustWindowRect(&rect, f->output_data.w32->dwStyle, FRAME_EXTERNAL_MENU_BAR(f));
+
+ pt.x = rect.left;
+ pt.y = rect.top;
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;
+
*xptr = pt.x;
*yptr = pt.y;
}
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));
}
+/* 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. */
fore_pixel = FRAME_BACKGROUND_PIXEL (f);
}
- FRAME_FOREGROUND_PIXEL (f) = fore_pixel;
+ f->output_data.w32->cursor_foreground_pixel = fore_pixel;
f->output_data.w32->cursor_pixel = pixel;
if (FRAME_W32_WINDOW (f) != 0)
{
+ BLOCK_INPUT;
+ /* Update frame's cursor_gc. */
+ f->output_data.w32->cursor_gc->foreground = fore_pixel;
+ f->output_data.w32->cursor_gc->background = pixel;
+
+ UNBLOCK_INPUT;
+
if (FRAME_VISIBLE_P (f))
{
x_update_cursor (f, 0);
}
}
+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;
: 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)));
- f->output_data.w32->fringes_extra
- = FRAME_FRINGE_WIDTH (f);
+
+ 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);
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;
+ }
+
return window_prompting;
}
{
PAINTSTRUCT paintStruct;
RECT update_rect;
+ bzero (&update_rect, sizeof (update_rect));
f = x_window_to_frame (dpyinfo, hwnd);
if (f == 0)
/* MSDN Docs say not to call BeginPaint if GetUpdateRect
fails. Apparently this can happen under some
circumstances. */
- if (!w32_strict_painting || GetUpdateRect (hwnd, &update_rect, FALSE))
+ if (GetUpdateRect (hwnd, &update_rect, FALSE) || !w32_strict_painting)
{
enter_crit ();
BeginPaint (hwnd, &paintStruct);
- if (w32_strict_painting)
- /* The rectangles returned by GetUpdateRect and BeginPaint
- do not always match. GetUpdateRect seems to be the
- more reliable of the two. */
- wmsg.rect = update_rect;
- else
- wmsg.rect = paintStruct.rcPaint;
+ /* The rectangles returned by GetUpdateRect and BeginPaint
+ do not always match. Play it safe by assuming both areas
+ are invalid. */
+ UnionRect (&(wmsg.rect), &update_rect, &(paintStruct.rcPaint));
#if defined (W32_DEBUG_DISPLAY)
DebPrint (("WM_PAINT (frame %p): painting %d,%d-%d,%d\n",
}
return 0;
+ case WM_XBUTTONDOWN:
+ case WM_XBUTTONUP:
+ if (w32_pass_extra_mouse_buttons_to_system)
+ goto dflt;
+ /* else fall through and process them. */
case WM_MBUTTONDOWN:
case WM_MBUTTONUP:
handle_plain_button:
BOOL up;
int button;
- if (parse_button (msg, &button, &up))
+ if (parse_button (msg, HIWORD (wParam), &button, &up))
{
if (up) ReleaseCapture ();
else SetCapture (hwnd);
wmsg.dwModifiers = w32_get_modifiers ();
my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
- return 0;
- case WM_VSCROLL:
+ /* Need to return true for XBUTTON messages, false for others,
+ to indicate that we processed the message. */
+ return (msg == WM_XBUTTONDOWN || msg == WM_XBUTTONUP);
+
case WM_MOUSEMOVE:
+ /* If the mouse has just moved into the frame, start tracking
+ it, so we will be notified when it leaves the frame. Mouse
+ tracking only works under W98 and NT4 and later. On earlier
+ versions, there is no way of telling when the mouse leaves the
+ frame, so we just have to put up with help-echo and mouse
+ highlighting remaining while the frame is not active. */
+ if (track_mouse_event_fn && !track_mouse_window)
+ {
+ TRACKMOUSEEVENT tme;
+ tme.cbSize = sizeof (tme);
+ tme.dwFlags = TME_LEAVE;
+ tme.hwndTrack = hwnd;
+
+ track_mouse_event_fn (&tme);
+ track_mouse_window = hwnd;
+ }
+ case WM_VSCROLL:
if (XINT (Vw32_mouse_move_interval) <= 0
|| (msg == WM_MOUSEMOVE && button_state == 0))
{
KillTimer (hwnd, mouse_move_timer);
mouse_move_timer = 0;
}
+ else if (wParam == menu_free_timer)
+ {
+ KillTimer (hwnd, menu_free_timer);
+ menu_free_timer = 0;
+ f = x_window_to_frame (dpyinfo, hwnd);
+ if (!f->output_data.w32->menu_command_in_progress)
+ {
+ /* Free memory used by owner-drawn and help-echo strings. */
+ w32_free_menu_strings (hwnd);
+ f->output_data.w32->menubar_active = 0;
+ }
+ }
return 0;
case WM_NCACTIVATE:
case WM_EXITMENULOOP:
f = x_window_to_frame (dpyinfo, hwnd);
- /* Indicate that menubar can be modified again. */
- if (f)
- f->output_data.w32->menubar_active = 0;
+ /* If a menu command is not already in progress, check again
+ after a short delay, since Windows often (always?) sends the
+ WM_EXITMENULOOP before the corresponding WM_COMMAND message. */
+ if (f && !f->output_data.w32->menu_command_in_progress)
+ menu_free_timer = SetTimer (hwnd, MENU_FREE_ID, MENU_FREE_DELAY, NULL);
goto dflt;
case WM_MENUSELECT:
-#if OLD_MENU_HELP
- wmsg.dwModifiers = w32_get_modifiers ();
- my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
-#else
+ /* Direct handling of help_echo in menus. Should be safe now
+ that we generate the help_echo by placing a help event in the
+ keyboard buffer. */
{
- /* Try to process these directly: the relevant parts of redisplay
- are supposed to be re-entrant now. This should allow tooltips
- to be shown for menus. */
HMENU menu = (HMENU) lParam;
UINT menu_item = (UINT) LOWORD (wParam);
UINT flags = (UINT) HIWORD (wParam);
- BLOCK_INPUT;
- w32_menu_display_help (menu, menu_item, flags);
- UNBLOCK_INPUT;
+ w32_menu_display_help (hwnd, menu, menu_item, flags);
}
-#endif
return 0;
case WM_MEASUREITEM:
goto dflt;
#endif
+ case WM_MOUSELEAVE:
+ /* No longer tracking mouse. */
+ track_mouse_window = NULL;
+
case WM_ACTIVATEAPP:
case WM_ACTIVATE:
case WM_WINDOWPOSCHANGED:
/* Relinquish the system caret. */
if (w32_system_caret_hwnd)
{
- DestroyCaret ();
+ w32_visible_system_caret_hwnd = NULL;
w32_system_caret_hwnd = NULL;
+ DestroyCaret ();
+ }
+ goto command;
+ case WM_COMMAND:
+ f = x_window_to_frame (dpyinfo, hwnd);
+ if (f && HIWORD (wParam) == 0)
+ {
+ f->output_data.w32->menu_command_in_progress = 1;
+ if (menu_free_timer)
+ {
+ KillTimer (hwnd, menu_free_timer);
+ menu_free_timer = 0;
+ }
}
case WM_MOVE:
case WM_SIZE:
- case WM_COMMAND:
command:
wmsg.dwModifiers = w32_get_modifiers ();
my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
return 0;
case WM_WINDOWPOSCHANGING:
+ /* Don't restrict the sizing of tip frames. */
+ if (hwnd == tip_window)
+ return 0;
{
WINDOWPLACEMENT wp;
LPWINDOWPOS lppos = (WINDOWPOS *) lParam;
DragAcceptFiles ((HWND) wParam, FALSE);
return DestroyWindow ((HWND) wParam);
+ case WM_EMACS_HIDE_CARET:
+ return HideCaret (hwnd);
+
+ case WM_EMACS_SHOW_CARET:
+ return ShowCaret (hwnd);
+
case WM_EMACS_DESTROY_CARET:
w32_system_caret_hwnd = NULL;
+ w32_visible_system_caret_hwnd = NULL;
return DestroyCaret ();
case WM_EMACS_TRACK_CARET:
/* If there is currently no system caret, create one. */
if (w32_system_caret_hwnd == NULL)
{
+ /* Use the default caret width, and avoid changing it
+ unneccesarily, as it confuses screen reader software. */
w32_system_caret_hwnd = hwnd;
- CreateCaret (hwnd, NULL, w32_system_caret_width,
+ CreateCaret (hwnd, NULL, 0,
w32_system_caret_height);
}
- return SetCaretPos (w32_system_caret_x, w32_system_caret_y);
+
+ if (!SetCaretPos (w32_system_caret_x, w32_system_caret_y))
+ return 0;
+ /* Ensure visible caret gets turned on when requested. */
+ else if (w32_use_visible_system_caret
+ && w32_visible_system_caret_hwnd != hwnd)
+ {
+ w32_visible_system_caret_hwnd = hwnd;
+ return ShowCaret (hwnd);
+ }
+ /* Ensure visible caret gets turned off when requested. */
+ else if (!w32_use_visible_system_caret
+ && w32_visible_system_caret_hwnd)
+ {
+ w32_visible_system_caret_hwnd = NULL;
+ return HideCaret (hwnd);
+ }
+ else
+ return 1;
case WM_EMACS_TRACKPOPUPMENU:
{
my_create_tip_window (f)
struct frame *f;
{
- HWND hwnd;
+ RECT rect;
- FRAME_W32_WINDOW (f) = hwnd
+ rect.left = rect.top = 0;
+ rect.right = PIXEL_WIDTH (f);
+ rect.bottom = PIXEL_HEIGHT (f);
+
+ AdjustWindowRect (&rect, f->output_data.w32->dwStyle,
+ FRAME_EXTERNAL_MENU_BAR (f));
+
+ tip_window = FRAME_W32_WINDOW (f)
= CreateWindow (EMACS_CLASS,
f->namebuf,
f->output_data.w32->dwStyle,
f->output_data.w32->left_pos,
f->output_data.w32->top_pos,
- PIXEL_WIDTH (f),
- PIXEL_HEIGHT (f),
+ rect.right - rect.left,
+ rect.bottom - rect.top,
FRAME_W32_WINDOW (SELECTED_FRAME ()), /* owner */
NULL,
hinst,
NULL);
- if (hwnd)
+ if (tip_window)
{
- 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_BACKGROUND_INDEX, FRAME_BACKGROUND_PIXEL (f));
+ 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_BACKGROUND_INDEX, FRAME_BACKGROUND_PIXEL (f));
+
+ /* Tip frames have no scrollbars. */
+ SetWindowLong (tip_window, WND_SCROLLBAR_INDEX, 0);
/* Do this to discard the default setting specified by our parent. */
- ShowWindow (hwnd, SW_HIDE);
+ ShowWindow (tip_window, SW_HIDE);
}
}
"screenGamma", "ScreenGamma", RES_TYPE_FLOAT);
x_default_parameter (f, parms, Qline_spacing, Qnil,
"lineSpacing", "LineSpacing", RES_TYPE_NUMBER);
+ x_default_parameter (f, parms, Qleft_fringe, Qnil,
+ "leftFringe", "LeftFringe", RES_TYPE_NUMBER);
+ x_default_parameter (f, parms, Qright_fringe, Qnil,
+ "rightFringe", "RightFringe", RES_TYPE_NUMBER);
/* Init faces before x_default_parameter is called for scroll-bar
x_default_parameter (f, parms, Qmenu_bar_lines, make_number (1),
"menuBar", "MenuBar", RES_TYPE_NUMBER);
- x_default_parameter (f, parms, Qtool_bar_lines, make_number (0),
+ x_default_parameter (f, parms, Qtool_bar_lines, make_number (HAVE_IMAGES),
"toolBar", "ToolBar", RES_TYPE_NUMBER);
x_default_parameter (f, parms, Qbuffer_predicate, Qnil,
"bufferPredicate", "BufferPredicate", RES_TYPE_SYMBOL);
x_default_parameter (f, parms, Qtitle, Qnil,
"title", "Title", RES_TYPE_STRING);
+ x_default_parameter (f, parms, Qfullscreen, Qnil,
+ "fullscreen", "Fullscreen", RES_TYPE_SYMBOL);
f->output_data.w32->dwStyle = WS_OVERLAPPEDWINDOW;
f->output_data.w32->parent_desc = FRAME_W32_DISPLAY_INFO (f)->root_window;
x_wm_set_size_hint (f, window_prompting, 0);
UNBLOCK_INPUT;
+ /* Avoid a bug that causes the new frame to never become visible if
+ an echo area message is displayed during the following call1. */
+ specbind(Qredisplay_dont_pause, Qt);
+
/* Set up faces after all frame parameters are known. This call
also merges in face attributes specified for new frames. If we
don't do this, the `menu' face for instance won't have the right
ended up with. */
return NULL;
+ /* Specify anti-aliasing to prevent Cleartype fonts being used,
+ since those fonts leave garbage behind. */
+ lf.lfQuality = ANTIALIASED_QUALITY;
+
font = (XFontStruct *) xmalloc (sizeof (XFontStruct));
bzero (font, sizeof (*font));
/* SJIS fonts need to be set to type 4, all others seem to work as
type FONT_ENCODING_NOT_DECIDED. */
encoding = strrchr (fontp->name, '-');
- if (encoding && stricmp (encoding+1, "sjis") == 0)
+ if (encoding && strnicmp (encoding+1, "sjis", 4) == 0)
fontp->encoding[1] = 4;
else
fontp->encoding[1] = FONT_ENCODING_NOT_DECIDED;
/* Set global flag fonts_changed_p to non-zero if the font loaded
has a character with a smaller width than any other character
- before, or if the font loaded has a smalle>r height than any
+ before, or if the font loaded has a smaller height than any
other font loaded before. If this happens, it will make a
glyph matrix reallocation necessary. */
- fonts_changed_p = x_compute_min_glyph_bounds (f);
+ fonts_changed_p |= x_compute_min_glyph_bounds (f);
UNBLOCK_INPUT;
return fontp;
}
w32_charset = Fcar (Fcdr (this_entry));
- // Translate Lisp symbol to number.
+ /* Translate Lisp symbol to number. */
if (w32_charset == Qw32_charset_ansi)
return ANSI_CHARSET;
if (w32_charset == Qw32_charset_symbol)
best_match = x_charset;
/* If this is an ISO codepage, and the best so far isn't,
then this is better. */
- else if (stricmp (best_match, "iso") != 0
- && stricmp (x_charset, "iso") == 0)
+ else if (strnicmp (best_match, "iso", 3) != 0
+ && strnicmp (x_charset, "iso", 3) == 0)
best_match = x_charset;
/* If both are ISO8859 codepages, choose the one with the
lowest number in the encoding field. */
- else if (stricmp (best_match, "iso8859-") == 0
- && stricmp (x_charset, "iso8859-") == 0)
+ else if (strnicmp (best_match, "iso8859-", 8) == 0
+ && strnicmp (x_charset, "iso8859-", 8) == 0)
{
int best_enc = atoi (best_match + 8);
int this_enc = atoi (x_charset + 8);
}
+/* Return all the X charsets that map to a font. */
+static Lisp_Object
+w32_to_all_x_charsets (fncharset)
+ int fncharset;
+{
+ static char buf[32];
+ Lisp_Object charset_type;
+ Lisp_Object retval = Qnil;
+
+ switch (fncharset)
+ {
+ case ANSI_CHARSET:
+ /* Handle startup case of w32-charset-info-alist not
+ being set up yet. */
+ if (NILP(Vw32_charset_info_alist))
+ return Fcons (build_string ("iso8859-1"), Qnil);
+
+ charset_type = Qw32_charset_ansi;
+ break;
+ case DEFAULT_CHARSET:
+ charset_type = Qw32_charset_default;
+ break;
+ case SYMBOL_CHARSET:
+ charset_type = Qw32_charset_symbol;
+ break;
+ case SHIFTJIS_CHARSET:
+ charset_type = Qw32_charset_shiftjis;
+ break;
+ case HANGEUL_CHARSET:
+ charset_type = Qw32_charset_hangeul;
+ break;
+ case GB2312_CHARSET:
+ charset_type = Qw32_charset_gb2312;
+ break;
+ case CHINESEBIG5_CHARSET:
+ charset_type = Qw32_charset_chinesebig5;
+ break;
+ case OEM_CHARSET:
+ charset_type = Qw32_charset_oem;
+ break;
+
+ /* More recent versions of Windows (95 and NT4.0) define more
+ character sets. */
+#ifdef EASTEUROPE_CHARSET
+ case EASTEUROPE_CHARSET:
+ charset_type = Qw32_charset_easteurope;
+ break;
+ case TURKISH_CHARSET:
+ charset_type = Qw32_charset_turkish;
+ break;
+ case BALTIC_CHARSET:
+ charset_type = Qw32_charset_baltic;
+ break;
+ case RUSSIAN_CHARSET:
+ charset_type = Qw32_charset_russian;
+ break;
+ case ARABIC_CHARSET:
+ charset_type = Qw32_charset_arabic;
+ break;
+ case GREEK_CHARSET:
+ charset_type = Qw32_charset_greek;
+ break;
+ case HEBREW_CHARSET:
+ charset_type = Qw32_charset_hebrew;
+ break;
+ case VIETNAMESE_CHARSET:
+ charset_type = Qw32_charset_vietnamese;
+ break;
+ case THAI_CHARSET:
+ charset_type = Qw32_charset_thai;
+ break;
+ case MAC_CHARSET:
+ charset_type = Qw32_charset_mac;
+ break;
+ case JOHAB_CHARSET:
+ charset_type = Qw32_charset_johab;
+ break;
+#endif
+
+#ifdef UNICODE_CHARSET
+ case UNICODE_CHARSET:
+ charset_type = Qw32_charset_unicode;
+ break;
+#endif
+ default:
+ /* Encode numerical value of unknown charset. */
+ sprintf (buf, "*-#%u", fncharset);
+ return Fcons (build_string (buf), Qnil);
+ }
+
+ {
+ Lisp_Object rest;
+ /* Look through w32-charset-info-alist for the character set.
+ Only return charsets for codepages which are installed.
+
+ Format of each entry in Vw32_charset_info_alist is
+ (CHARSET_NAME . (WINDOWS_CHARSET . CODEPAGE)).
+ */
+ for (rest = Vw32_charset_info_alist; CONSP (rest); rest = XCDR (rest))
+ {
+ Lisp_Object x_charset;
+ Lisp_Object w32_charset;
+ Lisp_Object codepage;
+
+ Lisp_Object this_entry = XCAR (rest);
+
+ /* Skip invalid entries in alist. */
+ if (!CONSP (this_entry) || !STRINGP (XCAR (this_entry))
+ || !CONSP (XCDR (this_entry))
+ || !SYMBOLP (XCAR (XCDR (this_entry))))
+ continue;
+
+ x_charset = XCAR (this_entry);
+ w32_charset = XCAR (XCDR (this_entry));
+ codepage = XCDR (XCDR (this_entry));
+
+ /* Look for Same charset and a valid codepage (or non-int
+ which means ignore). */
+ if (w32_charset == charset_type
+ && (!INTEGERP (codepage) || codepage == CP_DEFAULT
+ || IsValidCodePage (XINT (codepage))))
+ {
+ retval = Fcons (x_charset, retval);
+ }
+ }
+
+ /* If no match, encode the numeric value. */
+ if (NILP (retval))
+ {
+ sprintf (buf, "*-#%u", fncharset);
+ return Fcons (build_string (buf), Qnil);
+ }
+
+ return retval;
+ }
+}
+
/* Get the Windows codepage corresponding to the specified font. The
charset info in the font name is used to look up
w32-charset-to-codepage-alist. */
char height_dpi[8];
char width_pixels[8];
char *fontname_dash;
- int display_resy = one_w32_display_info.resy;
- int display_resx = one_w32_display_info.resx;
+ int display_resy = (int) one_w32_display_info.resy;
+ int display_resx = (int) one_w32_display_info.resx;
int bufsz;
struct coding_system coding;
char name[50], weight[20], slant, pitch, pixels[10], height[10],
width[10], resy[10], remainder[50];
char * encoding;
- int dpi = one_w32_display_info.resy;
+ int dpi = (int) one_w32_display_info.resy;
fields = sscanf (lpxstr,
"-%*[^-]-%49[^-]-%19[^-]-%c-%*[^-]-%*[^-]-%9[^-]-%9[^-]-%*[^-]-%9[^-]-%c-%9[^-]-%49s",
LOGFONT logfont;
XFontStruct *size_ref;
Lisp_Object *pattern;
+ Lisp_Object list;
Lisp_Object *tail;
} enumfont_t;
+
+static void
+enum_font_maybe_add_to_list (enumfont_t *, LOGFONT *, char *, Lisp_Object);
+
+
static int CALLBACK
enum_font_cb2 (lplf, lptm, FontType, lpef)
ENUMLOGFONT * lplf;
{
char buf[100];
Lisp_Object width = Qnil;
+ Lisp_Object charset_list = Qnil;
char *charset = NULL;
/* Truetype fonts do not report their true metrics until loaded */
{
charset = xlfd_charset_of_font (XSTRING(*(lpef->pattern))->data);
- /* Ensure that charset is valid for this font. */
- if (charset
- && (x_to_w32_charset (charset) != lplf->elfLogFont.lfCharSet))
- charset = NULL;
+ /* We already checked charsets above, but DEFAULT_CHARSET
+ slipped through. So only allow exact matches for DEFAULT_CHARSET. */
+ if (charset
+ && strncmp (charset, "*-*", 3) != 0
+ && lpef->logfont.lfCharSet == DEFAULT_CHARSET
+ && strcmp (charset, w32_to_x_charset (DEFAULT_CHARSET)) != 0)
+ return 1;
}
- /* TODO: List all relevant charsets if charset not specified. */
- if (!w32_to_x_font (&(lplf->elfLogFont), buf, 100, charset))
- return 1;
+ if (charset)
+ charset_list = Fcons (build_string (charset), Qnil);
+ else
+ charset_list = w32_to_all_x_charsets (lplf->elfLogFont.lfCharSet);
- if (NILP (*(lpef->pattern))
- || w32_font_match (buf, XSTRING (*(lpef->pattern))->data))
+ /* Loop through the charsets. */
+ for ( ; CONSP (charset_list); charset_list = Fcdr (charset_list))
{
- *lpef->tail = Fcons (Fcons (build_string (buf), width), Qnil);
- lpef->tail = &(XCDR (*lpef->tail));
- lpef->numFonts++;
+ Lisp_Object this_charset = Fcar (charset_list);
+ charset = XSTRING (this_charset)->data;
+
+ /* List bold and italic variations if w32-enable-synthesized-fonts
+ is non-nil and this is a plain font. */
+ if (w32_enable_synthesized_fonts
+ && lplf->elfLogFont.lfWeight == FW_NORMAL
+ && lplf->elfLogFont.lfItalic == FALSE)
+ {
+ enum_font_maybe_add_to_list (lpef, &(lplf->elfLogFont),
+ charset, width);
+ /* bold. */
+ lplf->elfLogFont.lfWeight = FW_BOLD;
+ enum_font_maybe_add_to_list (lpef, &(lplf->elfLogFont),
+ charset, width);
+ /* bold italic. */
+ lplf->elfLogFont.lfItalic = TRUE;
+ enum_font_maybe_add_to_list (lpef, &(lplf->elfLogFont),
+ charset, width);
+ /* italic. */
+ lplf->elfLogFont.lfWeight = FW_NORMAL;
+ enum_font_maybe_add_to_list (lpef, &(lplf->elfLogFont),
+ charset, width);
+ }
+ else
+ enum_font_maybe_add_to_list (lpef, &(lplf->elfLogFont),
+ charset, width);
}
}
return 1;
}
+static void
+enum_font_maybe_add_to_list (lpef, logfont, match_charset, width)
+ enumfont_t * lpef;
+ LOGFONT * logfont;
+ char * match_charset;
+ Lisp_Object width;
+{
+ char buf[100];
+
+ if (!w32_to_x_font (logfont, buf, 100, match_charset))
+ return;
+
+ if (NILP (*(lpef->pattern))
+ || w32_font_match (buf, XSTRING (*(lpef->pattern))->data))
+ {
+ /* Check if we already listed this font. This may happen if
+ w32_enable_synthesized_fonts is non-nil, and there are real
+ bold and italic versions of the font. */
+ Lisp_Object font_name = build_string (buf);
+ if (NILP (Fmember (font_name, lpef->list)))
+ {
+ *lpef->tail = Fcons (Fcons (build_string (buf), width), Qnil);
+ lpef->tail = &(XCDR (*lpef->tail));
+ lpef->numFonts++;
+ }
+ }
+}
+
+
static int CALLBACK
enum_font_cb1 (lplf, lptm, FontType, lpef)
ENUMLOGFONT * lplf;
return newlist;
}
-static Lisp_Object w32_list_synthesized_fonts (FRAME_PTR f,
- Lisp_Object pattern,
- int size, int max_names);
/* Return a list of names of available fonts matching PATTERN on frame
F. If SIZE is not 0, it is the size (maximum bound width) of fonts
/* At first, put PATTERN in the cache. */
list = Qnil;
ef.pattern = &tpat;
+ ef.list = list;
ef.tail = &list;
ef.numFonts = 0;
newlist = Fnconc(2, combined);
}
- /* If we can't find a font that matches, check if Windows would be
- able to synthesize it from a different style. */
- if (NILP (newlist) && !NILP (Vw32_enable_synthesized_fonts))
- newlist = w32_list_synthesized_fonts (f, pattern, size, maxnames);
-
return newlist;
}
-static Lisp_Object
-w32_list_synthesized_fonts (f, pattern, size, max_names)
- FRAME_PTR f;
- Lisp_Object pattern;
- int size;
- int max_names;
-{
- int fields;
- char *full_pattn, *new_pattn, foundary[50], family[50], *pattn_part2;
- char style[20], slant;
- Lisp_Object matches, tem, synthed_matches = Qnil;
-
- full_pattn = XSTRING (pattern)->data;
-
- pattn_part2 = alloca (XSTRING (pattern)->size + 1);
- /* Allow some space for wildcard expansion. */
- new_pattn = alloca (XSTRING (pattern)->size + 100);
-
- fields = sscanf (full_pattn, "-%49[^-]-%49[^-]-%19[^-]-%c-%s",
- foundary, family, style, &slant, pattn_part2);
- if (fields == EOF || fields < 5)
- return Qnil;
-
- /* If the style and slant are wildcards already there is no point
- checking again (and we don't want to keep recursing). */
- if (*style == '*' && slant == '*')
- return Qnil;
-
- sprintf (new_pattn, "-%s-%s-*-*-%s", foundary, family, pattn_part2);
-
- matches = w32_list_fonts (f, build_string (new_pattn), size, max_names);
-
- for ( ; CONSP (matches); matches = XCDR (matches))
- {
- tem = XCAR (matches);
- if (!STRINGP (tem))
- continue;
-
- full_pattn = XSTRING (tem)->data;
- fields = sscanf (full_pattn, "-%49[^-]-%49[^-]-%*[^-]-%*c-%s",
- foundary, family, pattn_part2);
- if (fields == EOF || fields < 3)
- continue;
-
- sprintf (new_pattn, "-%s-%s-%s-%c-%s", foundary, family, style,
- slant, pattn_part2);
-
- synthed_matches = Fcons (build_string (new_pattn),
- synthed_matches);
- }
-
- return synthed_matches;
-}
-
/* Return a pointer to struct font_info of font FONT_IDX of frame F. */
struct font_info *
else
cap = GetDeviceCaps (hdc,NUMCOLORS);
+ /* We force 24+ bit depths to 24-bit, both to prevent an overflow
+ and because probably is more meaningful on Windows anyway */
if (cap < 0)
- cap = 1 << (dpyinfo->n_planes * dpyinfo->n_cbits);
+ cap = 1 << min(dpyinfo->n_planes * dpyinfo->n_cbits, 24);
ReleaseDC (dpyinfo->root_window, hdc);
}
\f
-\f
/***********************************************************************
Image types
***********************************************************************/
/* Keywords. */
extern Lisp_Object QCwidth, QCheight, QCforeground, QCbackground, QCfile;
-extern Lisp_Object QCdata;
-Lisp_Object QCtype, QCascent, QCmargin, QCrelief;
+extern Lisp_Object QCdata, QCtype;
+Lisp_Object QCascent, QCmargin, QCrelief;
Lisp_Object QCconversion, QCcolor_symbols, QCheuristic_mask;
Lisp_Object QCindex, QCmatrix, QCcolor_adjustment, QCmask;
}
+#ifdef HAVE_IMAGES
+DEFUN ("image-size", Fimage_size, Simage_size, 1, 3, 0,
+ doc: /* Return the size of image SPEC as pair (WIDTH . HEIGHT).
+PIXELS non-nil means return the size in pixels, otherwise return the
+size in canonical character units.
+FRAME is the frame on which the image will be displayed. FRAME nil
+or omitted means use the selected frame. */)
+ (spec, pixels, frame)
+ Lisp_Object spec, pixels, frame;
+{
+ Lisp_Object size;
+
+ size = Qnil;
+ if (valid_image_p (spec))
+ {
+ struct frame *f = check_x_frame (frame);
+ int id = lookup_image (f, spec);
+ struct image *img = IMAGE_FROM_ID (f, id);
+ int width = img->width + 2 * img->hmargin;
+ 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)));
+ else
+ size = Fcons (make_number (width), make_number (height));
+ }
+ else
+ error ("Invalid image specification");
+
+ return size;
+}
+
+
+DEFUN ("image-mask-p", Fimage_mask_p, Simage_mask_p, 1, 2, 0,
+ doc: /* Return t if image SPEC has a mask bitmap.
+FRAME is the frame on which the image will be displayed. FRAME nil
+or omitted means use the selected frame. */)
+ (spec, frame)
+ Lisp_Object spec, frame;
+{
+ Lisp_Object mask;
+
+ mask = Qnil;
+ if (valid_image_p (spec))
+ {
+ struct frame *f = check_x_frame (frame);
+ int id = lookup_image (f, spec);
+ struct image *img = IMAGE_FROM_ID (f, id);
+ if (img->mask)
+ mask = Qt;
+ }
+ else
+ error ("Invalid image specification");
+
+ return mask;
+}
+#endif
\f
/***********************************************************************
ascent = height / 2;
}
else
- ascent = height * img->ascent / 100.0;
+ ascent = (int) (height * img->ascent / 100.0);
return ascent;
}
\f
/* Image background colors. */
-static unsigned long
+/* Find the "best" corner color of a bitmap. XIMG is assumed to a device
+ context with the bitmap selected. */
+static COLORREF
four_corners_best (ximg, width, height)
- XImage *ximg;
+ HDC ximg;
unsigned long width, height;
{
-#if 0 /* TODO: Image support. */
- unsigned long corners[4], best;
+ COLORREF corners[4], best;
int i, best_count;
/* Get the colors at the corners of ximg. */
- corners[0] = XGetPixel (ximg, 0, 0);
- corners[1] = XGetPixel (ximg, width - 1, 0);
- corners[2] = XGetPixel (ximg, width - 1, height - 1);
- corners[3] = XGetPixel (ximg, 0, height - 1);
+ corners[0] = GetPixel (ximg, 0, 0);
+ corners[1] = GetPixel (ximg, width - 1, 0);
+ corners[2] = GetPixel (ximg, width - 1, height - 1);
+ corners[3] = GetPixel (ximg, 0, height - 1);
/* Choose the most frequently found color as background. */
for (i = best_count = 0; i < 4; ++i)
}
return best;
-#else
- return 0;
-#endif
}
/* Return the `background' field of IMG. If IMG doesn't have one yet,
struct image *img;
int pixmap_p, mask_p, colors_p;
{
-#if 0
if (pixmap_p && img->pixmap)
{
- XFreePixmap (FRAME_X_DISPLAY (f), img->pixmap);
- img->pixmap = None;
+ DeleteObject (img->pixmap);
+ img->pixmap = NULL;
img->background_valid = 0;
}
if (mask_p && img->mask)
{
- XFreePixmap (FRAME_X_DISPLAY (f), img->mask);
- img->mask = None;
+ DeleteObject (img->mask);
+ img->mask = NULL;
img->background_transparent_valid = 0;
}
if (colors_p && img->ncolors)
{
+#if 0 /* TODO: color table support. */
x_free_colors (f, img->colors, img->ncolors);
+#endif
xfree (img->colors);
img->colors = NULL;
img->ncolors = 0;
}
-#endif
}
/* Free X resources of image IMG which is used on frame F. */
struct frame *f;
struct image *img;
{
-#if 0 /* TODO: W32 image support */
-
if (img->pixmap)
{
BLOCK_INPUT;
- XFreePixmap (NULL, img->pixmap);
+ DeleteObject (img->pixmap);
img->pixmap = 0;
UNBLOCK_INPUT;
}
if (img->ncolors)
{
+#if 0 /* TODO: color table support */
+
int class = FRAME_W32_DISPLAY_INFO (f)->visual->class;
/* If display has an immutable color map, freeing colors is not
img->ncolors, 0);
UNBLOCK_INPUT;
}
+#endif
xfree (img->colors);
img->colors = NULL;
img->ncolors = 0;
}
-#endif
}
Lisp_Object color_name;
unsigned long dflt;
{
-#if 0 /* TODO: allocing colors. */
XColor color;
unsigned long result;
else
result = dflt;
return result;
-#endif
- return 0;
}
{
EMACS_TIME t;
unsigned long old;
- int i, any_freed_p = 0;
+ int i, nfreed;
EMACS_GET_TIME (t);
old = EMACS_SECS (t) - XFASTINT (Vimage_cache_eviction_delay);
- for (i = 0; i < c->used; ++i)
+ /* Block input so that we won't be interrupted by a SIGIO
+ while being in an inconsistent state. */
+ BLOCK_INPUT;
+
+ for (i = nfreed = 0; i < c->used; ++i)
{
struct image *img = c->images[i];
if (img != NULL
- && (force_p
- || (img->timestamp > old)))
+ && (force_p || (img->timestamp < old)))
{
free_image (f, img);
- any_freed_p = 1;
+ ++nfreed;
}
}
Emacs was iconified for a longer period of time. In that
case, current matrices may still contain references to
images freed above. So, clear these matrices. */
- if (any_freed_p)
+ if (nfreed)
{
- clear_current_matrices (f);
+ Lisp_Object tail, frame;
+
+ FOR_EACH_FRAME (tail, frame)
+ {
+ struct frame *f = XFRAME (frame);
+ if (FRAME_W32_P (f)
+ && FRAME_X_IMAGE_CACHE (f) == c)
+ clear_current_matrices (f);
+ }
+
++windows_or_buffers_changed;
}
+
+ UNBLOCK_INPUT;
}
}
}
else if (NILP (mask) && found_p && img->mask)
{
- XFreePixmap (FRAME_X_DISPLAY (f), img->mask);
+ DeleteObject (img->mask);
img->mask = NULL;
}
}
W32 support code
***********************************************************************/
-#if 0 /* TODO: W32 specific image code. */
-
static int x_create_x_image_and_pixmap P_ ((struct frame *, int, int, int,
XImage **, Pixmap *));
static void x_destroy_x_image P_ ((XImage *));
/* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on
frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created.
Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated
- via xmalloc. Print error messages via image_error if an error
- occurs. Value is non-zero if successful. */
+ via xmalloc. DEPTH of zero signifies a 24 bit image, otherwise
+ DEPTH should indicate the bit depth of the image. Print error
+ messages via image_error if an error occurs. Value is non-zero if
+ successful. */
static int
x_create_x_image_and_pixmap (f, width, height, depth, ximg, pixmap)
XImage **ximg;
Pixmap *pixmap;
{
-#if 0 /* TODO: Image support for W32 */
- Display *display = FRAME_W32_DISPLAY (f);
- Screen *screen = FRAME_X_SCREEN (f);
- Window window = FRAME_W32_WINDOW (f);
+ BITMAPINFOHEADER *header;
+ HDC hdc;
+ int scanline_width_bits;
+ int remainder;
+ int palette_colors = 0;
- xassert (interrupt_input_blocked);
+ if (depth == 0)
+ depth = 24;
- if (depth <= 0)
- depth = one_w32_display_info.n_cbits;
- *ximg = XCreateImage (display, DefaultVisualOfScreen (screen),
- depth, ZPixmap, 0, NULL, width, height,
- depth > 16 ? 32 : depth > 8 ? 16 : 8, 0);
+ if (depth != 1 && depth != 4 && depth != 8
+ && depth != 16 && depth != 24 && depth != 32)
+ {
+ image_error ("Invalid image bit depth specified", Qnil, Qnil);
+ return 0;
+ }
+
+ scanline_width_bits = width * depth;
+ remainder = scanline_width_bits % 32;
+
+ if (remainder)
+ scanline_width_bits += 32 - remainder;
+
+ /* Bitmaps with a depth less than 16 need a palette. */
+ /* BITMAPINFO structure already contains the first RGBQUAD. */
+ if (depth < 16)
+ palette_colors = 1 << depth - 1;
+
+ *ximg = xmalloc (sizeof (XImage) + palette_colors * sizeof (RGBQUAD));
if (*ximg == NULL)
{
- image_error ("Unable to allocate X image", Qnil, Qnil);
+ image_error ("Unable to allocate memory for XImage", Qnil, Qnil);
return 0;
}
- /* Allocate image raster. */
- (*ximg)->data = (char *) xmalloc ((*ximg)->bytes_per_line * height);
+ header = &((*ximg)->info.bmiHeader);
+ bzero (&((*ximg)->info), sizeof (BITMAPINFO));
+ header->biSize = sizeof (*header);
+ header->biWidth = width;
+ header->biHeight = -height; /* negative indicates a top-down bitmap. */
+ header->biPlanes = 1;
+ header->biBitCount = depth;
+ header->biCompression = BI_RGB;
+ header->biClrUsed = palette_colors;
+
+ hdc = get_frame_dc (f);
+
+ /* Create a DIBSection and raster array for the bitmap,
+ and store its handle in *pixmap. */
+ *pixmap = CreateDIBSection (hdc, &((*ximg)->info), DIB_RGB_COLORS,
+ &((*ximg)->data), NULL, 0);
- /* Allocate a pixmap of the same size. */
- *pixmap = XCreatePixmap (display, window, width, height, depth);
- if (*pixmap == 0)
+ /* Realize display palette and garbage all frames. */
+ release_frame_dc (f, hdc);
+
+ if (*pixmap == NULL)
{
+ DWORD err = GetLastError();
+ Lisp_Object errcode;
+ /* All system errors are < 10000, so the following is safe. */
+ XSETINT (errcode, (int) err);
+ image_error ("Unable to create bitmap, error code %d", errcode, Qnil);
x_destroy_x_image (*ximg);
- *ximg = NULL;
- image_error ("Unable to create X pixmap", Qnil, Qnil);
return 0;
}
-#endif
+
return 1;
}
xassert (interrupt_input_blocked);
if (ximg)
{
- xfree (ximg->data);
+ /* Data will be freed by DestroyObject. */
ximg->data = NULL;
- XDestroyImage (ximg);
+ xfree (ximg);
}
}
XImage *ximg;
Pixmap pixmap;
{
+
+#if TODO /* W32 specific image code. */
GC gc;
-
+
xassert (interrupt_input_blocked);
gc = XCreateGC (NULL, pixmap, 0, NULL);
XPutImage (NULL, pixmap, gc, ximg, 0, 0, 0, 0, width, height);
XFreeGC (NULL, gc);
-}
-
#endif
+}
\f
/***********************************************************************
if (rc)
{
int depth = one_w32_display_info.n_cbits;
+ int planes = one_w32_display_info.n_planes;
+
unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
unsigned long background = FRAME_BACKGROUND_PIXEL (f);
Lisp_Object value;
img->background = background;
img->background_valid = 1;
}
-
-#if 0 /* TODO : Port image display to W32 */
img->pixmap
- = XCreatePixmapFromBitmapData (FRAME_W32_DISPLAY (f),
- FRAME_W32_WINDOW (f),
- data,
- img->width, img->height,
- foreground, background,
- depth);
-#endif
+ = CreateBitmap (img->width, img->height, planes, depth, data);
+
xfree (data);
if (img->pixmap == 0)
#endif /* TODO */
\f
+#ifdef HAVE_IMAGES /* TODO */
/***********************************************************************
Algorithms
***********************************************************************/
-#if 0 /* TODO: image support. */
static XColor *x_to_xcolors P_ ((struct frame *, struct image *, int));
static void x_from_xcolors P_ ((struct frame *, struct image *, XColor *));
static void x_detect_edges P_ ((struct frame *, struct image *, int[9], int));
+static void XPutPixel (XImage *, int, int, COLORREF);
/* Non-zero means draw a cross on images having `:conversion
disabled'. */
XImage *ximg;
colors = (XColor *) xmalloc (img->width * img->height * sizeof *colors);
-
+#if 0 /* TODO: implement image colors. */
/* Get the X image IMG->pixmap. */
ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
0, 0, img->width, img->height, ~0, ZPixmap);
}
XDestroyImage (ximg);
+#endif
return colors;
}
+/* Put a pixel of COLOR at position X, Y in XIMG. XIMG must have been
+ created with CreateDIBSection, with the pointer to the bit values
+ stored in ximg->data. */
+
+static void XPutPixel (ximg, x, y, color)
+ XImage * ximg;
+ int x, y;
+ COLORREF 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;
+ *pixel = 255 - GetRValue (color);
+ *(pixel + 1) = 255 - GetGValue (color);
+ *(pixel + 2) = 255 - GetBValue (color);
+}
+
/* Create IMG->pixmap from an array COLORS of XColor structures, whose
RGB members are set. F is the frame on which this all happens.
XImage *oimg;
Pixmap pixmap;
XColor *p;
-
+#if 0 /* TODO: color tables. */
init_color_table ();
-
+#endif
x_create_x_image_and_pixmap (f, img->width, img->height, 0,
&oimg, &pixmap);
p = colors;
for (x = 0; x < img->width; ++x, ++p)
{
unsigned long pixel;
+#if 0 /* TODO: color tables. */
pixel = lookup_rgb_color (f, p->red, p->green, p->blue);
+#else
+ pixel = PALETTERGB (p->red, p->green, p->blue);
+#endif
XPutPixel (oimg, x, y, pixel);
}
x_put_x_image (f, oimg, pixmap, img->width, img->height);
x_destroy_x_image (oimg);
img->pixmap = pixmap;
+#if 0 /* TODO: color tables. */
img->colors = colors_in_color_table (&img->ncolors);
free_color_table ();
+#endif
}
struct frame *f;
struct image *img;
{
- struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+ struct w32_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
- if (dpyinfo->n_planes >= 2)
+ if (dpyinfo->n_planes * dpyinfo->n_cbits >= 2)
{
/* Color (or grayscale). Convert to gray, and equalize. Just
drawing such images with a stipple can look very odd, so
/* Draw a cross over the disabled image, if we must or if we
should. */
- if (dpyinfo->n_planes < 2 || cross_disabled_images)
+ if (dpyinfo->n_planes * dpyinfo->n_cbits < 2 || cross_disabled_images)
{
+#if 0 /* TODO: full image support */
Display *dpy = FRAME_X_DISPLAY (f);
GC gc;
img->width - 1, 0);
XFreeGC (dpy, gc);
}
+#endif
}
}
struct image *img;
Lisp_Object how;
{
+#if 0 /* TODO: full image support. */
Display *dpy = FRAME_W32_DISPLAY (f);
XImage *ximg, *mask_img;
int x, y, rc, use_img_background;
XDestroyImage (ximg);
return 1;
+#else
+ return 0;
+#endif
}
-#endif /* TODO */
-
+#endif
\f
/***********************************************************************
PBM (mono, gray, color)
|| (type != PBM_MONO && max_color_idx < 0))
goto error;
- 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))
goto error;
+#if 0 /* TODO: color tables. */
/* Initialize the color hash table. */
init_color_table ();
+#endif
if (type == PBM_MONO)
{
if (r < 0 || g < 0 || b < 0)
{
- xfree (ximg->data);
- ximg->data = NULL;
- XDestroyImage (ximg);
+ x_destroy_x_image (ximg);
image_error ("Invalid pixel value in image `%s'",
img->spec, Qnil);
goto error;
}
/* RGB values are now in the range 0..max_color_idx.
- Scale this to the range 0..0xffff supported by X. */
- r = (double) r * 65535 / max_color_idx;
- g = (double) g * 65535 / max_color_idx;
- b = (double) b * 65535 / max_color_idx;
- XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
+ Scale this to the range 0..0xff supported by W32. */
+ r = (int) ((double) r * 255 / max_color_idx);
+ g = (int) ((double) g * 255 / max_color_idx);
+ b = (int) ((double) b * 255 / max_color_idx);
+ XPutPixel (ximg, x, y,
+#if 0 /* TODO: color tables. */
+ lookup_rgb_color (f, r, g, b));
+#else
+ PALETTERGB (r, g, b));
+#endif
}
}
-
+
+#if 0 /* TODO: color tables. */
/* Store in IMG->colors the colors allocated for the image, and
free the color table. */
img->colors = colors_in_color_table (&img->ncolors);
free_color_table ();
-
+#endif
/* Maybe fill in the background field while we have ximg handy. */
if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
IMAGE_BACKGROUND (img, f, ximg);
frame = Qnil;
GCPRO3 (parms, name, frame);
- f = make_frame (1);
+ /* Make a frame without minibuffer nor mode-line. */
+ f = make_frame (0);
+ f->wants_modeline = 0;
XSETFRAME (frame, f);
buffer = Fget_buffer_create (build_string (" *tip*"));
parms = Fcons (Fcons (Qinternal_border_width, value),
parms);
}
- /* Default internalBorderWidth for tooltips to 2 on Windows to match
- other programs. */
- x_default_parameter (f, parms, Qinternal_border_width, make_number (2),
+ x_default_parameter (f, parms, Qinternal_border_width, make_number (1),
"internalBorderWidth", "internalBorderWidth",
RES_TYPE_NUMBER);
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);
+ /* 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)
int *root_x, *root_y;
{
Lisp_Object left, top;
- unsigned pmask;
/* User-specified position? */
left = Fcdr (Fassq (Qleft, parms));
if (INTEGERP (left))
*root_x = XINT (left);
- else if (*root_x + XINT (dx) + width > FRAME_WIDTH (f))
+ else if (*root_x + XINT (dx) + width <= FRAME_W32_DISPLAY_INFO (f)->width)
+ /* It fits to the right of the pointer. */
+ *root_x += XINT (dx);
+ else if (width + XINT (dx) <= *root_x)
+ /* It fits to the left of the pointer. */
*root_x -= width + XINT (dx);
else
- *root_x += XINT (dx);
+ /* Put it left justified on the screen -- it ought to fit that way. */
+ *root_x = 0;
}
-#ifdef TEST_TOOLTIPS /* Tooltip support in progress. */
DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
doc: /* Show STRING in a \"tooltip\" window on frame FRAME.
A tooltip window is a small window displaying a string.
BLOCK_INPUT;
compute_tip_xy (f, parms, dx, dy, PIXEL_WIDTH (f),
PIXEL_HEIGHT (f), &root_x, &root_y);
+
+ /* Put tooltip in topmost group and in position. */
SetWindowPos (FRAME_W32_WINDOW (f), HWND_TOPMOST,
root_x, root_y, 0, 0,
SWP_NOSIZE | SWP_NOACTIVATE);
+
+ /* Ensure tooltip is on top of other topmost windows (eg menus). */
+ SetWindowPos (FRAME_W32_WINDOW (f), HWND_TOP,
+ 0, 0, 0, 0,
+ SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
+
UNBLOCK_INPUT;
goto start_timer;
}
parms = Fcons (Fcons (Qbackground_color, build_string ("lightyellow")),
parms);
+ /* Block input until the tip has been fully drawn, to avoid crashes
+ when drawing tips in menus. */
+ BLOCK_INPUT;
+
/* Create a frame for the tooltip, and record it in the global
variable tip_frame. */
frame = x_create_tip_frame (FRAME_W32_DISPLAY_INFO (f), parms, string);
/* Let the row go over the full width of the frame. */
row->full_width_p = 1;
+#ifdef TODO /* Investigate why some fonts need more width than is
+ calculated for some tooltips. */
/* There's a glyph at the end of rows that is use to place
the cursor there. Don't include the width of this glyph. */
if (row->used[TEXT_AREA])
row_width = row->pixel_width - last->pixel_width;
}
else
+#endif
row_width = row->pixel_width;
/* TODO: find why tips do not draw along baseline as instructed. */
- height += row->height * 2;
+ height += row->height;
width = max (width, row_width);
}
show it. */
compute_tip_xy (f, parms, dx, dy, width, height, &root_x, &root_y);
- BLOCK_INPUT;
- SetWindowPos (FRAME_W32_WINDOW (f), HWND_TOPMOST,
- root_x, root_y - height, width, height,
- SWP_NOACTIVATE);
- my_show_window (f, FRAME_W32_WINDOW (f), SW_SHOWNORMAL);
- UNBLOCK_INPUT;
+ {
+ /* Adjust Window size to take border into account. */
+ RECT rect;
+ rect.left = rect.top = 0;
+ rect.right = width;
+ rect.bottom = height;
+ AdjustWindowRect (&rect, f->output_data.w32->dwStyle,
+ FRAME_EXTERNAL_MENU_BAR (f));
+
+ /* Position and size tooltip, and put it in the topmost group. */
+ SetWindowPos (FRAME_W32_WINDOW (f), HWND_TOPMOST,
+ root_x, root_y, rect.right - rect.left,
+ rect.bottom - rect.top, SWP_NOACTIVATE);
+
+ /* Ensure tooltip is on top of other topmost windows (eg menus). */
+ SetWindowPos (FRAME_W32_WINDOW (f), HWND_TOP,
+ 0, 0, 0, 0,
+ SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
+
+ /* Let redisplay know that we have made the frame visible already. */
+ f->async_visible = 1;
+
+ ShowWindow (FRAME_W32_WINDOW (f), SW_SHOWNOACTIVATE);
+ }
/* Draw into the window. */
w->must_be_updated_p = 1;
update_single_window (w, 1);
+ UNBLOCK_INPUT;
+
/* Restore original current buffer. */
set_buffer_internal_1 (old_buffer);
windows_or_buffers_changed = old_windows_or_buffers_changed;
UNGCPRO;
return unbind_to (count, deleted);
}
-#endif
\f
w32 specialized functions
***********************************************************************/
-DEFUN ("w32-select-font", Fw32_select_font, Sw32_select_font, 0, 1, 0,
+DEFUN ("w32-select-font", Fw32_select_font, Sw32_select_font, 0, 2, 0,
doc: /* Select a font using the W32 font dialog.
Returns an X font string corresponding to the selection. */)
- (frame)
- Lisp_Object frame;
+ (frame, include_proportional)
+ Lisp_Object frame, include_proportional;
{
FRAME_PTR f = check_x_frame (frame);
CHOOSEFONT cf;
cf.lStructSize = sizeof (cf);
cf.hwndOwner = FRAME_W32_WINDOW (f);
- cf.Flags = CF_FORCEFONTEXIST | CF_SCREENFONTS;
+ cf.Flags = CF_FORCEFONTEXIST | CF_SCREENFONTS | CF_NOVERTFONTS;
+
+ /* Unless include_proportional is non-nil, limit the selection to
+ monospaced fonts. */
+ if (NILP (include_proportional))
+ cf.Flags |= CF_FIXEDPITCHONLY;
+
cf.lpLogFont = &lf;
/* Initialize as much of the font details as we can from the current
DEFUN ("w32-send-sys-command", Fw32_send_sys_command,
Sw32_send_sys_command, 1, 2, 0,
doc: /* Send frame a Windows WM_SYSCOMMAND message of type COMMAND.
-Some useful values for command are 0xf030 to maximise frame (0xf020
-to minimize), 0xf120 to restore frame to original size, and 0xf100
-to activate the menubar for keyboard access. 0xf140 activates the
+Some useful values for command are #xf030 to maximise frame (#xf020
+to minimize), #xf120 to restore frame to original size, and #xf100
+to activate the menubar for keyboard access. #xf140 activates the
screen saver if defined.
If optional parameter FRAME is not specified, use selected frame. */)
if (pfn_GetDiskFreeSpaceEx)
{
+ /* Unsigned large integers cannot be cast to double, so
+ use signed ones instead. */
LARGE_INTEGER availbytes;
LARGE_INTEGER freebytes;
LARGE_INTEGER totalbytes;
if (pfn_GetDiskFreeSpaceEx(rootname,
- &availbytes,
- &totalbytes,
- &freebytes))
+ (ULARGE_INTEGER *)&availbytes,
+ (ULARGE_INTEGER *)&totalbytes,
+ (ULARGE_INTEGER *)&freebytes))
value = list3 (make_float ((double) totalbytes.QuadPart),
make_float ((double) freebytes.QuadPart),
make_float ((double) availbytes.QuadPart));
return value;
}
\f
+/***********************************************************************
+ Initialization
+ ***********************************************************************/
+
+void
syms_of_w32fns ()
{
+ HMODULE user32_lib = GetModuleHandle ("user32.dll");
+
/* This is zero if not using MS-Windows. */
w32_in_use = 0;
- /* The section below is built by the lisp expression at the top of the file,
- just above where these variables are declared. */
- /*&&& init symbols here &&&*/
+ /* 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 = 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 (&Qcenter);
Qcancel_timer = intern ("cancel-timer");
staticpro (&Qcancel_timer);
- /* This is the end of symbol initialization. */
+ 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);
staticpro (&Qcontrol);
Qshift = intern ("shift");
staticpro (&Qshift);
+ /* This is the end of symbol initialization. */
/* Text property `display' should be nonsticky by default. */
Vtext_property_default_nonsticky
Any other value will cause the key to be ignored. */);
Vw32_apps_modifier = Qnil;
- DEFVAR_LISP ("w32-enable-synthesized-fonts", &Vw32_enable_synthesized_fonts,
+ DEFVAR_BOOL ("w32-enable-synthesized-fonts", &w32_enable_synthesized_fonts,
doc: /* Non-nil enables selection of artificially italicized and bold fonts. */);
- Vw32_enable_synthesized_fonts = Qnil;
+ w32_enable_synthesized_fonts = 0;
DEFVAR_LISP ("w32-enable-palette", &Vw32_enable_palette,
doc: /* Non-nil enables Windows palette management to map colors exactly. */);
reported as lisp events. */);
XSETINT (Vw32_mouse_move_interval, 0);
+ DEFVAR_BOOL ("w32-pass-extra-mouse-buttons-to-system",
+ &w32_pass_extra_mouse_buttons_to_system,
+ doc: /* Non-nil if the fourth and fifth mouse buttons are passed to Windows.
+Recent versions of Windows support mice with up to five buttons.
+Since most applications don't support these extra buttons, most mouse
+drivers will allow you to map them to functions at the system level.
+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,
set_frame_fontset_func = x_set_font;
check_window_system_func = check_w32;
-#if 0 /* TODO Image support for W32 */
+#ifdef IMAGES
/* Images. */
Qxbm = intern ("xbm");
staticpro (&Qxbm);
- QCtype = intern (":type");
- staticpro (&QCtype);
QCconversion = intern (":conversion");
staticpro (&QCconversion);
QCheuristic_mask = intern (":heuristic-mask");
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");
staticpro (&QCpt_width);
QCpt_height = intern (":pt-height");
staticpro (&QCpt_height);
+#endif
QCindex = intern (":index");
staticpro (&QCindex);
Qpbm = intern ("pbm");
staticpro (&Qpbm);
+#endif
#if HAVE_XPM
Qxpm = intern ("xpm");
staticpro (&Qpng);
#endif
+#ifdef HAVE_IMAGES
defsubr (&Sclear_image_cache);
+ defsubr (&Simage_size);
+ defsubr (&Simage_mask_p);
+#endif
#if GLYPH_DEBUG
defsubr (&Simagep);
defsubr (&Slookup_image);
#endif
-#endif /* TODO */
hourglass_atimer = NULL;
hourglass_shown_p = 0;
-#if TEST_TOOLTIPS /* Tooltip support in progress. */
defsubr (&Sx_show_tip);
defsubr (&Sx_hide_tip);
-#endif
tip_timer = Qnil;
staticpro (&tip_timer);
tip_frame = Qnil;
image_types = NULL;
Vimage_types = Qnil;
+#if HAVE_PBM
+ define_image_type (&pbm_type);
+#endif
+
#if 0 /* TODO : Image support for W32 */
define_image_type (&xbm_type);
define_image_type (&gs_type);
- define_image_type (&pbm_type);
+#endif
#if HAVE_XPM
define_image_type (&xpm_type);
#if HAVE_PNG
define_image_type (&png_type);
#endif
-#endif /* TODO */
}
#undef abort