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;
/* 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));
{"screen-gamma", x_set_screen_gamma},
{"line-spacing", x_set_line_spacing},
{"left-fringe", x_set_fringe_width},
- {"right-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;
val = values[p];
if (EQ (prop, Qforeground_color)
|| EQ (prop, Qbackground_color)
- || EQ (prop, Qfont))
+ || 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_left = val;
else if (EQ (prop, Qforeground_color)
|| EQ (prop, Qbackground_color)
- || EQ (prop, Qfont))
+ || 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;
}
}
+/* 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);
: 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);
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",
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);
- /* Free memory used by owner-drawn and help-echo strings. */
- w32_free_menu_strings (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:
/* 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);
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:
{
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;
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));
/* 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;
}
/* Handle startup case of w32-charset-info-alist not
being set up yet. */
if (NILP(Vw32_charset_info_alist))
- return "iso8859-1";
+ return Fcons (build_string ("iso8859-1"), Qnil);
+
charset_type = Qw32_charset_ansi;
break;
case DEFAULT_CHARSET:
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",
{
charset = xlfd_charset_of_font (XSTRING(*(lpef->pattern))->data);
- /* Ensure that charset is valid for this font.
- Continue if invalid in case charset contains a wildcard. */
- 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;
}
if (charset)
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 /* TODO: W32 image support */
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 != 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 (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 (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);
+
+ /* Realize display palette and garbage all frames. */
+ release_frame_dc (f, hdc);
- /* Allocate a pixmap of the same size. */
- *pixmap = XCreatePixmap (display, window, width, height, depth);
- if (*pixmap == 0)
+ 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);
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;
}
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;
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));
track_mouse_event_fn = GetProcAddress (user32_lib, "TrackMouseEvent");
track_mouse_window = NULL;
- /* 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 &&&*/
+ 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
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;
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