Mercurial > hg > xemacs-beta
diff src/glyphs-msw.c @ 428:3ecd8885ac67 r21-2-22
Import from CVS: tag r21-2-22
author | cvs |
---|---|
date | Mon, 13 Aug 2007 11:28:15 +0200 |
parents | |
children | a5df635868b2 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/glyphs-msw.c Mon Aug 13 11:28:15 2007 +0200 @@ -0,0 +1,3012 @@ +/* mswindows-specific glyph objects. + Copyright (C) 1998, 1999 Andy Piper. + +This file is part of XEmacs. + +XEmacs is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +XEmacs is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with XEmacs; see the file COPYING. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +/* Synched up with: Not in FSF. */ + +/* written by Andy Piper <andy@xemacs.org> plagerising bits from + glyphs-x.c */ + +#include <config.h> +#include "lisp.h" +#include "lstream.h" + +#define OEMRESOURCE /* Define OCR_ and friend constants */ +#include "console-msw.h" +#include "glyphs-msw.h" +#include "objects-msw.h" + +#include "window.h" +#include "elhash.h" +#include "buffer.h" +#include "frame.h" +#include "insdel.h" +#include "opaque.h" +#include "sysfile.h" +#include "faces.h" +#include "imgproc.h" + +#ifdef FILE_CODING +#include "file-coding.h" +#endif +#include <stdio.h> +#include <ctype.h> +#ifdef HAVE_XFACE +#include <setjmp.h> +#endif + +#define WIDGET_GLYPH_SLOT 0 + +DECLARE_IMAGE_INSTANTIATOR_FORMAT (nothing); +DECLARE_IMAGE_INSTANTIATOR_FORMAT (string); +DECLARE_IMAGE_INSTANTIATOR_FORMAT (formatted_string); +DECLARE_IMAGE_INSTANTIATOR_FORMAT (inherit); +DECLARE_IMAGE_INSTANTIATOR_FORMAT (layout); +#ifdef HAVE_JPEG +DECLARE_IMAGE_INSTANTIATOR_FORMAT (jpeg); +#endif +#ifdef HAVE_TIFF +DECLARE_IMAGE_INSTANTIATOR_FORMAT (tiff); +#endif +#ifdef HAVE_PNG +DECLARE_IMAGE_INSTANTIATOR_FORMAT (png); +#endif +#ifdef HAVE_GIF +DECLARE_IMAGE_INSTANTIATOR_FORMAT (gif); +#endif +#ifdef HAVE_XPM +DEFINE_DEVICE_IIFORMAT (mswindows, xpm); +#endif +DEFINE_DEVICE_IIFORMAT (mswindows, xbm); +#ifdef HAVE_XFACE +DEFINE_DEVICE_IIFORMAT (mswindows, xface); +#endif +DEFINE_DEVICE_IIFORMAT (mswindows, button); +DEFINE_DEVICE_IIFORMAT (mswindows, edit_field); +DEFINE_DEVICE_IIFORMAT (mswindows, subwindow); +DEFINE_DEVICE_IIFORMAT (mswindows, widget); +DEFINE_DEVICE_IIFORMAT (mswindows, label); +DEFINE_DEVICE_IIFORMAT (mswindows, scrollbar); +DEFINE_DEVICE_IIFORMAT (mswindows, combo_box); +DEFINE_DEVICE_IIFORMAT (mswindows, progress_gauge); +DEFINE_DEVICE_IIFORMAT (mswindows, tree_view); +DEFINE_DEVICE_IIFORMAT (mswindows, tab_control); + +DEFINE_IMAGE_INSTANTIATOR_FORMAT (bmp); +Lisp_Object Qbmp; +Lisp_Object Vmswindows_bitmap_file_path; +static COLORREF transparent_color = RGB (1,1,1); + +DEFINE_IMAGE_INSTANTIATOR_FORMAT (mswindows_resource); +Lisp_Object Q_resource_type, Q_resource_id; +Lisp_Object Qmswindows_resource; + +static void +mswindows_initialize_dibitmap_image_instance (struct Lisp_Image_Instance *ii, + int slices, + enum image_instance_type type); +static void +mswindows_initialize_image_instance_mask (struct Lisp_Image_Instance* image, + struct frame* f); + +COLORREF mswindows_string_to_color (CONST char *name); + +#define BPLINE(width) ((int)(~3UL & (unsigned long)((width) +3))) + +/************************************************************************/ +/* convert from a series of RGB triples to a BITMAPINFO formated for the*/ +/* proper display */ +/************************************************************************/ +static BITMAPINFO* convert_EImage_to_DIBitmap (Lisp_Object device, + int width, int height, + unsigned char *pic, + int *bit_count, + unsigned char** bmp_data) +{ + struct device *d = XDEVICE (device); + int i,j; + RGBQUAD* colortbl; + int ncolors; + BITMAPINFO* bmp_info; + unsigned char *ip, *dp; + + if (DEVICE_MSWINDOWS_BITSPIXEL (d) > 0) + { + int bpline = BPLINE(width * 3); + /* FIXME: we can do this because 24bpp implies no color table, once + * we start palettizing this is no longer true. The X versions of + * this function quantises to 256 colors or bit masks down to a + * long. Windows can actually handle rgb triples in the raw so I + * don't see much point trying to optimize down to the best + * structure - unless it has memory / color allocation implications + * .... */ + bmp_info=xnew_and_zero (BITMAPINFO); + + if (!bmp_info) + { + return NULL; + } + + bmp_info->bmiHeader.biBitCount=24; /* just RGB triples for now */ + bmp_info->bmiHeader.biCompression=BI_RGB; /* just RGB triples for now */ + bmp_info->bmiHeader.biSizeImage=width*height*3; + + /* bitmap data needs to be in blue, green, red triples - in that + order, eimage is in RGB format so we need to convert */ + *bmp_data = xnew_array_and_zero (unsigned char, bpline * height); + *bit_count = bpline * height; + + if (!bmp_data) + { + xfree (bmp_info); + return NULL; + } + + ip = pic; + for (i = height-1; i >= 0; i--) { + dp = (*bmp_data) + (i * bpline); + for (j = 0; j < width; j++) { + dp[2] =*ip++; + dp[1] =*ip++; + *dp =*ip++; + dp += 3; + } + } + } + else /* scale to 256 colors */ + { + int rd,gr,bl; + quant_table *qtable; + int bpline = BPLINE (width * 3); + /* Quantize the image and get a histogram while we're at it. + Do this first to save memory */ + qtable = build_EImage_quantable(pic, width, height, 256); + if (qtable == NULL) return NULL; + + /* use our quantize table to allocate the colors */ + ncolors = qtable->num_active_colors; + bmp_info=(BITMAPINFO*)xmalloc_and_zero (sizeof(BITMAPINFOHEADER) + + sizeof(RGBQUAD) * ncolors); + if (!bmp_info) + { + xfree (qtable); + return NULL; + } + + colortbl=(RGBQUAD*)(((unsigned char*)bmp_info)+sizeof(BITMAPINFOHEADER)); + + bmp_info->bmiHeader.biBitCount=8; + bmp_info->bmiHeader.biCompression=BI_RGB; + bmp_info->bmiHeader.biSizeImage=bpline*height; + bmp_info->bmiHeader.biClrUsed=ncolors; + bmp_info->bmiHeader.biClrImportant=ncolors; + + *bmp_data = (unsigned char *) xmalloc_and_zero (bpline * height); + *bit_count = bpline * height; + + if (!*bmp_data) + { + xfree (qtable); + xfree (bmp_info); + return NULL; + } + + /* build up an RGBQUAD colortable */ + for (i = 0; i < qtable->num_active_colors; i++) { + colortbl[i].rgbRed = (BYTE) qtable->rm[i]; + colortbl[i].rgbGreen = (BYTE) qtable->gm[i]; + colortbl[i].rgbBlue = (BYTE) qtable->bm[i]; + colortbl[i].rgbReserved = 0; + } + + /* now build up the data. picture has to be upside-down and + back-to-front for msw bitmaps */ + ip = pic; + for (i = height-1; i >= 0; i--) { + dp = (*bmp_data) + (i * bpline); + for (j = 0; j < width; j++) { + rd = *ip++; + gr = *ip++; + bl = *ip++; + *dp++ = QUANT_GET_COLOR (qtable,rd,gr,bl); + } + } + xfree (qtable); + } + /* fix up the standard stuff */ + bmp_info->bmiHeader.biWidth=width; + bmp_info->bmiHeader.biHeight=height; + bmp_info->bmiHeader.biPlanes=1; + bmp_info->bmiHeader.biSize=sizeof(BITMAPINFOHEADER); + bmp_info->bmiHeader.biXPelsPerMeter=0; /* unless you know better */ + bmp_info->bmiHeader.biYPelsPerMeter=0; + + return bmp_info; +} + +/* Given a pixmap filename, look through all of the "standard" places + where the file might be located. Return a full pathname if found; + otherwise, return Qnil. */ + +static Lisp_Object +mswindows_locate_pixmap_file (Lisp_Object name) +{ + /* This function can GC if IN_REDISPLAY is false */ + Lisp_Object found; + + /* Check non-absolute pathnames with a directory component relative to + the search path; that's the way Xt does it. */ + if (IS_DIRECTORY_SEP(XSTRING_BYTE (name, 0)) || + (XSTRING_BYTE (name, 0) == '.' && + (IS_DIRECTORY_SEP(XSTRING_BYTE (name, 1)) || + (XSTRING_BYTE (name, 1) == '.' && + (IS_DIRECTORY_SEP(XSTRING_BYTE (name, 2))))))) + { + if (!NILP (Ffile_readable_p (name))) + return name; + else + return Qnil; + } + + if (locate_file (Vmswindows_bitmap_file_path, name, Qnil, &found, R_OK) < 0) + { + Lisp_Object temp = list1 (Vdata_directory); + struct gcpro gcpro1; + + GCPRO1 (temp); + locate_file (temp, name, Qnil, &found, R_OK); + UNGCPRO; + } + + return found; +} + + +/* Initialize an image instance from a bitmap + + DEST_MASK specifies the mask of allowed image types. + + If this fails, signal an error. INSTANTIATOR is only used + in the error message. */ + +static void +init_image_instance_from_dibitmap (struct Lisp_Image_Instance *ii, + BITMAPINFO *bmp_info, + int dest_mask, + void *bmp_data, + int bmp_bits, + int slices, + Lisp_Object instantiator, + int x_hot, int y_hot, + int create_mask) +{ + Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii); + struct device *d = XDEVICE (device); + struct frame *f; + void* bmp_buf=0; + int type = 0; + HBITMAP bitmap; + HDC hdc; + + if (!DEVICE_MSWINDOWS_P (d)) + signal_simple_error ("Not an mswindows device", device); + + if (NILP (DEVICE_SELECTED_FRAME (d))) + signal_simple_error ("No selected frame on mswindows device", device); + + f = XFRAME (DEVICE_SELECTED_FRAME (d)); + + if (dest_mask & IMAGE_COLOR_PIXMAP_MASK) + type = IMAGE_COLOR_PIXMAP; + else if (dest_mask & IMAGE_POINTER_MASK) + type = IMAGE_POINTER; + else + incompatible_image_types (instantiator, dest_mask, + IMAGE_COLOR_PIXMAP_MASK | IMAGE_POINTER_MASK); + hdc = FRAME_MSWINDOWS_CDC (f); + + bitmap=CreateDIBSection (hdc, + bmp_info, + DIB_RGB_COLORS, + &bmp_buf, + 0,0); + + if (!bitmap || !bmp_buf) + signal_simple_error ("Unable to create bitmap", instantiator); + + /* copy in the actual bitmap */ + memcpy (bmp_buf, bmp_data, bmp_bits); + + mswindows_initialize_dibitmap_image_instance (ii, slices, type); + + IMAGE_INSTANCE_PIXMAP_FILENAME (ii) = + find_keyword_in_vector (instantiator, Q_file); + + /* Fixup a set of bitmaps. */ + IMAGE_INSTANCE_MSWINDOWS_BITMAP (ii) = bitmap; + + IMAGE_INSTANCE_MSWINDOWS_MASK (ii) = NULL; + IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = bmp_info->bmiHeader.biWidth; + IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) = bmp_info->bmiHeader.biHeight; + IMAGE_INSTANCE_PIXMAP_DEPTH (ii) = bmp_info->bmiHeader.biBitCount; + XSETINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii), x_hot); + XSETINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii), y_hot); + + if (create_mask) + { + mswindows_initialize_image_instance_mask (ii, f); + } + + if (type == IMAGE_POINTER) + { + mswindows_initialize_image_instance_icon(ii, TRUE); + } +} + +static void +image_instance_add_dibitmap (struct Lisp_Image_Instance *ii, + BITMAPINFO *bmp_info, + void *bmp_data, + int bmp_bits, + int slice, + Lisp_Object instantiator) +{ + Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii); + struct device *d = XDEVICE (device); + struct frame *f = XFRAME (DEVICE_SELECTED_FRAME (d)); + void* bmp_buf=0; + HDC hdc = FRAME_MSWINDOWS_CDC (f); + HBITMAP bitmap = CreateDIBSection (hdc, + bmp_info, + DIB_RGB_COLORS, + &bmp_buf, + 0,0); + + if (!bitmap || !bmp_buf) + signal_simple_error ("Unable to create bitmap", instantiator); + + /* copy in the actual bitmap */ + memcpy (bmp_buf, bmp_data, bmp_bits); + IMAGE_INSTANCE_MSWINDOWS_BITMAP_SLICE (ii, slice) = bitmap; +} + +static void +mswindows_init_image_instance_from_eimage (struct Lisp_Image_Instance *ii, + int width, int height, + int slices, + unsigned char *eimage, + int dest_mask, + Lisp_Object instantiator, + Lisp_Object domain) +{ + Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii); + BITMAPINFO* bmp_info; + unsigned char* bmp_data; + int bmp_bits; + COLORREF bkcolor; + int slice; + + if (!DEVICE_MSWINDOWS_P (XDEVICE (device))) + signal_simple_error ("Not an mswindows device", device); + + /* this is a hack but MaskBlt and TransparentBlt are not supported + on most windows variants */ + bkcolor = COLOR_INSTANCE_MSWINDOWS_COLOR + (XCOLOR_INSTANCE (FACE_BACKGROUND (Vdefault_face, domain))); + + for (slice = 0; slice < slices; slice++) + { + /* build a bitmap from the eimage */ + if (!(bmp_info=convert_EImage_to_DIBitmap (device, width, height, + eimage + (width * height * 3 * slice), + &bmp_bits, &bmp_data))) + { + signal_simple_error ("EImage to DIBitmap conversion failed", + instantiator); + } + + /* Now create the pixmap and set up the image instance */ + if (slice == 0) + init_image_instance_from_dibitmap (ii, bmp_info, dest_mask, + bmp_data, bmp_bits, slices, instantiator, + 0, 0, 0); + else + image_instance_add_dibitmap (ii, bmp_info, bmp_data, bmp_bits, slice, + instantiator); + + xfree (bmp_info); + xfree (bmp_data); + } +} + +static void set_mono_pixel ( unsigned char* bits, + int bpline, int height, + int x, int y, int white ) +{ + int index; + unsigned char bitnum; + /* Find the byte on which this scanline begins */ + index = (height - y - 1) * bpline; + /* Find the byte containing this pixel */ + index += (x >> 3); + /* Which bit is it? */ + bitnum = (unsigned char)( 7 - (x % 8) ); + if( white ) /* Turn it on */ + bits[index] |= (1<<bitnum); + else /* Turn it off */ + bits[index] &= ~(1<<bitnum); +} + +static void +mswindows_initialize_image_instance_mask (struct Lisp_Image_Instance* image, + struct frame* f) +{ + HBITMAP mask; + HGDIOBJ old = NULL; + HDC hcdc = FRAME_MSWINDOWS_CDC (f); + unsigned char* dibits; + BITMAPINFO* bmp_info = + xmalloc_and_zero (sizeof(BITMAPINFO) + sizeof(RGBQUAD)); + int i, j; + int height = IMAGE_INSTANCE_PIXMAP_HEIGHT (image); + + void* and_bits; + int maskbpline = BPLINE (((IMAGE_INSTANCE_PIXMAP_WIDTH (image)+7)/8)); + int bpline = BPLINE (IMAGE_INSTANCE_PIXMAP_WIDTH (image) * 3); + + if (!bmp_info) + return; + + bmp_info->bmiHeader.biWidth=IMAGE_INSTANCE_PIXMAP_WIDTH (image); + bmp_info->bmiHeader.biHeight = height; + bmp_info->bmiHeader.biPlanes=1; + bmp_info->bmiHeader.biSize=sizeof(BITMAPINFOHEADER); + bmp_info->bmiHeader.biBitCount=1; + bmp_info->bmiHeader.biCompression=BI_RGB; + bmp_info->bmiHeader.biClrUsed = 2; + bmp_info->bmiHeader.biClrImportant = 2; + bmp_info->bmiHeader.biSizeImage = height * maskbpline; + bmp_info->bmiColors[0].rgbRed = 0; + bmp_info->bmiColors[0].rgbGreen = 0; + bmp_info->bmiColors[0].rgbBlue = 0; + bmp_info->bmiColors[0].rgbReserved = 0; + bmp_info->bmiColors[1].rgbRed = 255; + bmp_info->bmiColors[1].rgbGreen = 255; + bmp_info->bmiColors[1].rgbBlue = 255; + bmp_info->bmiColors[0].rgbReserved = 0; + + if (!(mask = CreateDIBSection (hcdc, + bmp_info, + DIB_RGB_COLORS, + &and_bits, + 0,0))) + { + xfree (bmp_info); + return; + } + + old = SelectObject (hcdc, IMAGE_INSTANCE_MSWINDOWS_BITMAP (image)); + /* build up an in-memory set of bits to mess with */ + xzero (*bmp_info); + + bmp_info->bmiHeader.biWidth=IMAGE_INSTANCE_PIXMAP_WIDTH (image); + bmp_info->bmiHeader.biHeight = -height; + bmp_info->bmiHeader.biPlanes=1; + bmp_info->bmiHeader.biSize=sizeof(BITMAPINFOHEADER); + bmp_info->bmiHeader.biBitCount=24; + bmp_info->bmiHeader.biCompression=BI_RGB; + bmp_info->bmiHeader.biClrUsed = 0; + bmp_info->bmiHeader.biClrImportant = 0; + bmp_info->bmiHeader.biSizeImage = height * bpline; + + dibits = xmalloc_and_zero (bpline * height); + if (GetDIBits (hcdc, + IMAGE_INSTANCE_MSWINDOWS_BITMAP (image), + 0, + height, + dibits, + bmp_info, + DIB_RGB_COLORS) <= 0) + { + xfree (bmp_info); + return; + } + + /* now set the colored bits in the mask and transparent ones to + black in the original */ + for(i=0; i<IMAGE_INSTANCE_PIXMAP_WIDTH (image); i++) + { + for(j=0; j<height; j++) + { + unsigned char* idx = &dibits[j * bpline + i * 3]; + + if( RGB (idx[2], idx[1], idx[0]) == transparent_color ) + { + idx[0] = idx[1] = idx[2] = 0; + set_mono_pixel( and_bits, maskbpline, height, i, j, TRUE ); + } + else + { + set_mono_pixel( and_bits, maskbpline, height, i, j, FALSE ); + } + } + } + + SetDIBits (hcdc, + IMAGE_INSTANCE_MSWINDOWS_BITMAP (image), + 0, + height, + dibits, + bmp_info, + DIB_RGB_COLORS); + + xfree (bmp_info); + xfree (dibits); + + SelectObject(hcdc, old); + + IMAGE_INSTANCE_MSWINDOWS_MASK (image) = mask; +} + +void +mswindows_initialize_image_instance_icon (struct Lisp_Image_Instance* image, + int cursor) +{ + ICONINFO x_icon; + + /* we rely on windows to do any resizing necessary */ + x_icon.fIcon=cursor ? FALSE : TRUE; + x_icon.xHotspot=XINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (image)); + x_icon.yHotspot=XINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (image)); + x_icon.hbmMask=IMAGE_INSTANCE_MSWINDOWS_MASK (image); + x_icon.hbmColor=IMAGE_INSTANCE_MSWINDOWS_BITMAP (image); + + IMAGE_INSTANCE_MSWINDOWS_ICON (image)= + CreateIconIndirect (&x_icon); +} + +HBITMAP +mswindows_create_resized_bitmap (struct Lisp_Image_Instance* ii, + struct frame* f, + int newx, int newy) +{ + HBITMAP newbmp; + HGDIOBJ old1, old2; + HDC hcdc = FRAME_MSWINDOWS_CDC (f); + HDC hdcDst = CreateCompatibleDC (hcdc); + + old1 = SelectObject (hcdc, IMAGE_INSTANCE_MSWINDOWS_BITMAP (ii)); + + newbmp = CreateCompatibleBitmap (hcdc, newx, newy); + + old2 = SelectObject (hdcDst, newbmp); + + if (!StretchBlt (hdcDst, 0, 0, newx, newy, + hcdc, 0, 0, + IMAGE_INSTANCE_PIXMAP_WIDTH (ii), + IMAGE_INSTANCE_PIXMAP_HEIGHT (ii), + SRCCOPY)) + { + DeleteObject (newbmp); + DeleteDC (hdcDst); + return 0; + } + + SelectObject (hdcDst, old2); + SelectObject (hcdc, old1); + DeleteDC (hdcDst); + + return newbmp; +} + +HBITMAP +mswindows_create_resized_mask (struct Lisp_Image_Instance* ii, + struct frame* f, + int newx, int newy) +{ + if (IMAGE_INSTANCE_MSWINDOWS_MASK (ii)) + { + HBITMAP newmask; + HGDIOBJ old1, old2; + HDC hcdc = FRAME_MSWINDOWS_CDC (f); + HDC hdcDst = CreateCompatibleDC (hcdc); + + old1 = SelectObject (hcdc, IMAGE_INSTANCE_MSWINDOWS_MASK (ii)); + newmask = CreateCompatibleBitmap(hcdc, newx, newy); + old2 = SelectObject (hdcDst, newmask); + + if (!StretchBlt(hdcDst, 0, 0, newx, newy, + hcdc, 0, 0, + IMAGE_INSTANCE_PIXMAP_WIDTH (ii), + IMAGE_INSTANCE_PIXMAP_HEIGHT (ii), + SRCCOPY)) + { + DeleteObject (newmask); + DeleteDC (hdcDst); + return NULL; + } + + SelectObject (hdcDst, old2); + SelectObject (hcdc, old1); + + DeleteDC (hdcDst); + + return newmask; + } + + return NULL; +} + +int +mswindows_resize_dibitmap_instance (struct Lisp_Image_Instance* ii, + struct frame* f, + int newx, int newy) +{ + HBITMAP newbmp = mswindows_create_resized_bitmap (ii, f, newx, newy); + HBITMAP newmask = mswindows_create_resized_mask (ii, f, newx, newy); + + if (!newbmp) + return FALSE; + + if (IMAGE_INSTANCE_MSWINDOWS_BITMAP (ii)) + DeleteObject (IMAGE_INSTANCE_MSWINDOWS_BITMAP (ii)); + if (IMAGE_INSTANCE_MSWINDOWS_MASK (ii)) + DeleteObject (IMAGE_INSTANCE_MSWINDOWS_MASK (ii)); + + IMAGE_INSTANCE_MSWINDOWS_BITMAP (ii) = newbmp; + IMAGE_INSTANCE_MSWINDOWS_MASK (ii) = newmask; + IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = newx; + IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) = newy; + + return TRUE; +} + +/********************************************************************** + * XPM * + **********************************************************************/ + +#ifdef HAVE_XPM + +struct color_symbol +{ + char* name; + COLORREF color; +}; + +static struct color_symbol* +extract_xpm_color_names (Lisp_Object device, + Lisp_Object domain, + Lisp_Object color_symbol_alist, + int* nsymbols) +{ + /* This function can GC */ + Lisp_Object rest; + Lisp_Object results = Qnil; + int i, j; + struct color_symbol *colortbl; + struct gcpro gcpro1, gcpro2; + + GCPRO2 (results, device); + + /* We built up results to be (("name" . #<color>) ...) so that if an + error happens we don't lose any malloc()ed data, or more importantly, + leave any pixels allocated in the server. */ + i = 0; + LIST_LOOP (rest, color_symbol_alist) + { + Lisp_Object cons = XCAR (rest); + Lisp_Object name = XCAR (cons); + Lisp_Object value = XCDR (cons); + if (NILP (value)) + continue; + if (STRINGP (value)) + value = + Fmake_color_instance + (value, device, encode_error_behavior_flag (ERROR_ME_NOT)); + else + { + assert (COLOR_SPECIFIERP (value)); + value = Fspecifier_instance (value, domain, Qnil, Qnil); + } + if (NILP (value)) + continue; + results = noseeum_cons (noseeum_cons (name, value), results); + i++; + } + UNGCPRO; /* no more evaluation */ + + *nsymbols=i; + if (i == 0) return 0; + + colortbl = xnew_array_and_zero (struct color_symbol, i); + + for (j=0; j<i; j++) + { + Lisp_Object cons = XCAR (results); + colortbl[j].color = + COLOR_INSTANCE_MSWINDOWS_COLOR (XCOLOR_INSTANCE (XCDR (cons))); + + GET_C_STRING_OS_DATA_ALLOCA (XCAR (cons), colortbl[j].name); + colortbl[j].name = xstrdup (colortbl[j].name); /* mustn't lose this when we return */ + free_cons (XCONS (cons)); + cons = results; + results = XCDR (results); + free_cons (XCONS (cons)); + } + return colortbl; +} + +static int xpm_to_eimage (Lisp_Object image, CONST Extbyte *buffer, + unsigned char** data, + int* width, int* height, + int* x_hot, int* y_hot, + int* transp, + struct color_symbol* color_symbols, + int nsymbols) +{ + XpmImage xpmimage; + XpmInfo xpminfo; + int result, i, j, transp_idx, maskbpline; + unsigned char* dptr; + unsigned int* sptr; + COLORREF color; /* the american spelling virus hits again .. */ + COLORREF* colortbl; + + xzero (xpmimage); + xzero (xpminfo); + xpminfo.valuemask=XpmHotspot; + *transp=FALSE; + + result = XpmCreateXpmImageFromBuffer ((char*)buffer, + &xpmimage, + &xpminfo); + switch (result) + { + case XpmSuccess: + break; + case XpmFileInvalid: + { + signal_simple_error ("Invalid XPM data", image); + } + case XpmNoMemory: + { + signal_double_file_error ("Parsing pixmap data", + "out of memory", image); + } + default: + { + signal_double_file_error_2 ("Parsing pixmap data", + "unknown error code", + make_int (result), image); + } + } + + *width = xpmimage.width; + *height = xpmimage.height; + maskbpline = BPLINE (((~7UL & (unsigned long)(*width + 7)) / 8)); + + *data = xnew_array_and_zero (unsigned char, *width * *height * 3); + + if (!*data) + { + XpmFreeXpmImage (&xpmimage); + XpmFreeXpmInfo (&xpminfo); + return 0; + } + + /* build a color table to speed things up */ + colortbl = xnew_array_and_zero (COLORREF, xpmimage.ncolors); + if (!colortbl) + { + xfree (*data); + XpmFreeXpmImage (&xpmimage); + XpmFreeXpmInfo (&xpminfo); + return 0; + } + + for (i=0; i<xpmimage.ncolors; i++) + { + /* goto alert!!!! */ + /* pick up symbolic colors in preference */ + if (xpmimage.colorTable[i].symbolic) + { + if (!strcasecmp (xpmimage.colorTable[i].symbolic,"BgColor") + || + !strcasecmp (xpmimage.colorTable[i].symbolic,"None")) + { + *transp=TRUE; + colortbl[i]=transparent_color; + transp_idx=i; + goto label_found_color; + } + else if (color_symbols) + { + for (j = 0; j<nsymbols; j++) + { + if (!strcmp (xpmimage.colorTable[i].symbolic, + color_symbols[j].name )) + { + colortbl[i]=color_symbols[j].color; + goto label_found_color; + } + } + } + else if (xpmimage.colorTable[i].c_color == 0) + { + goto label_no_color; + } + } + /* pick up transparencies */ + if (!strcasecmp (xpmimage.colorTable[i].c_color,"None")) + { + *transp=TRUE; + colortbl[i]=transparent_color; + transp_idx=i; + goto label_found_color; + } + /* finally pick up a normal color spec */ + if (xpmimage.colorTable[i].c_color) + { + colortbl[i]= + mswindows_string_to_color (xpmimage.colorTable[i].c_color); + goto label_found_color; + } + + label_no_color: + xfree (*data); + xfree (colortbl); + XpmFreeXpmImage (&xpmimage); + XpmFreeXpmInfo (&xpminfo); + return 0; + + label_found_color:; + } + + /* convert the image */ + sptr=xpmimage.data; + dptr=*data; + for (i = 0; i< *width * *height; i++) + { + color = colortbl[*sptr++]; + + /* split out the 0x02bbggrr colorref into an rgb triple */ + *dptr++=GetRValue (color); /* red */ + *dptr++=GetGValue (color); /* green */ + *dptr++=GetBValue (color); /* blue */ + } + + *x_hot=xpminfo.x_hotspot; + *y_hot=xpminfo.y_hotspot; + + XpmFreeXpmImage (&xpmimage); + XpmFreeXpmInfo (&xpminfo); + xfree (colortbl); + return TRUE; +} + +static void +mswindows_xpm_instantiate (Lisp_Object image_instance, + Lisp_Object instantiator, + Lisp_Object pointer_fg, Lisp_Object pointer_bg, + int dest_mask, Lisp_Object domain) +{ + struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); + Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii); + CONST Extbyte *bytes; + Extcount len; + unsigned char *eimage; + int width, height, x_hot, y_hot; + BITMAPINFO* bmp_info; + unsigned char* bmp_data; + int bmp_bits; + int nsymbols=0, transp; + struct color_symbol* color_symbols=NULL; + + Lisp_Object data = find_keyword_in_vector (instantiator, Q_data); + Lisp_Object color_symbol_alist = find_keyword_in_vector (instantiator, + Q_color_symbols); + + if (!DEVICE_MSWINDOWS_P (XDEVICE (device))) + signal_simple_error ("Not an mswindows device", device); + + assert (!NILP (data)); + + GET_STRING_BINARY_DATA_ALLOCA (data, bytes, len); + + /* in case we have color symbols */ + color_symbols = extract_xpm_color_names (device, domain, + color_symbol_alist, &nsymbols); + + /* convert to an eimage to make processing easier */ + if (!xpm_to_eimage (image_instance, bytes, &eimage, &width, &height, + &x_hot, &y_hot, &transp, color_symbols, nsymbols)) + { + signal_simple_error ("XPM to EImage conversion failed", + image_instance); + } + + if (color_symbols) + { + while (nsymbols--) + { + xfree (color_symbols[nsymbols].name); + } + xfree(color_symbols); + } + + /* build a bitmap from the eimage */ + if (!(bmp_info=convert_EImage_to_DIBitmap (device, width, height, eimage, + &bmp_bits, &bmp_data))) + { + signal_simple_error ("XPM to EImage conversion failed", + image_instance); + } + xfree (eimage); + + /* Now create the pixmap and set up the image instance */ + init_image_instance_from_dibitmap (ii, bmp_info, dest_mask, + bmp_data, bmp_bits, 1, instantiator, + x_hot, y_hot, transp); + + xfree (bmp_info); + xfree (bmp_data); +} +#endif /* HAVE_XPM */ + +/********************************************************************** + * BMP * + **********************************************************************/ + +static void +bmp_validate (Lisp_Object instantiator) +{ + file_or_data_must_be_present (instantiator); +} + +static Lisp_Object +bmp_normalize (Lisp_Object inst, Lisp_Object console_type) +{ + return simple_image_type_normalize (inst, console_type, Qbmp); +} + +static int +bmp_possible_dest_types (void) +{ + return IMAGE_COLOR_PIXMAP_MASK; +} + +static void +bmp_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, + Lisp_Object pointer_fg, Lisp_Object pointer_bg, + int dest_mask, Lisp_Object domain) +{ + struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); + Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii); + CONST Extbyte *bytes; + Extcount len; + BITMAPFILEHEADER* bmp_file_header; + BITMAPINFO* bmp_info; + void* bmp_data; + int bmp_bits; + Lisp_Object data = find_keyword_in_vector (instantiator, Q_data); + + if (!DEVICE_MSWINDOWS_P (XDEVICE (device))) + signal_simple_error ("Not an mswindows device", device); + + assert (!NILP (data)); + + GET_STRING_BINARY_DATA_ALLOCA (data, bytes, len); + + /* Then slurp the image into memory, decoding along the way. + The result is the image in a simple one-byte-per-pixel + format. */ + + bmp_file_header=(BITMAPFILEHEADER*)bytes; + bmp_info = (BITMAPINFO*)(bytes + sizeof(BITMAPFILEHEADER)); + bmp_data = (Extbyte*)bytes + bmp_file_header->bfOffBits; + bmp_bits = bmp_file_header->bfSize - bmp_file_header->bfOffBits; + + /* Now create the pixmap and set up the image instance */ + init_image_instance_from_dibitmap (ii, bmp_info, dest_mask, + bmp_data, bmp_bits, 1, instantiator, + 0, 0, 0); +} + + +/********************************************************************** + * RESOURCES * + **********************************************************************/ + +static void +mswindows_resource_validate (Lisp_Object instantiator) +{ + if ((NILP (find_keyword_in_vector (instantiator, Q_file)) + && + NILP (find_keyword_in_vector (instantiator, Q_resource_id))) + || + NILP (find_keyword_in_vector (instantiator, Q_resource_type))) + signal_simple_error ("Must supply :file, :resource-id and :resource-type", + instantiator); +} + +static Lisp_Object +mswindows_resource_normalize (Lisp_Object inst, Lisp_Object console_type) +{ + /* This function can call lisp */ + Lisp_Object file = Qnil; + struct gcpro gcpro1, gcpro2; + Lisp_Object alist = Qnil; + + GCPRO2 (file, alist); + + file = potential_pixmap_file_instantiator (inst, Q_file, Q_data, + console_type); + + if (CONSP (file)) /* failure locating filename */ + signal_double_file_error ("Opening pixmap file", + "no such file or directory", + Fcar (file)); + + if (NILP (file)) /* no conversion necessary */ + RETURN_UNGCPRO (inst); + + alist = tagged_vector_to_alist (inst); + + { + alist = remassq_no_quit (Q_file, alist); + alist = Fcons (Fcons (Q_file, file), alist); + } + + { + Lisp_Object result = alist_to_tagged_vector (Qmswindows_resource, alist); + free_alist (alist); + RETURN_UNGCPRO (result); + } +} + +static int +mswindows_resource_possible_dest_types (void) +{ + return IMAGE_POINTER_MASK | IMAGE_COLOR_PIXMAP_MASK; +} + +typedef struct +{ + char *name; + int resource_id; +} resource_t; + +#ifndef OCR_ICOCUR +#define OCR_ICOCUR 32647 +#define OIC_SAMPLE 32512 +#define OIC_HAND 32513 +#define OIC_QUES 32514 +#define OIC_BANG 32515 +#define OIC_NOTE 32516 +#define OIC_WINLOGO 32517 +#define LR_SHARED 0x8000 +#endif + +static CONST resource_t bitmap_table[] = +{ + /* bitmaps */ + { "close", OBM_CLOSE }, + { "uparrow", OBM_UPARROW }, + { "dnarrow", OBM_DNARROW }, + { "rgarrow", OBM_RGARROW }, + { "lfarrow", OBM_LFARROW }, + { "reduce", OBM_REDUCE }, + { "zoom", OBM_ZOOM }, + { "restore", OBM_RESTORE }, + { "reduced", OBM_REDUCED }, + { "zoomd", OBM_ZOOMD }, + { "restored", OBM_RESTORED }, + { "uparrowd", OBM_UPARROWD }, + { "dnarrowd", OBM_DNARROWD }, + { "rgarrowd", OBM_RGARROWD }, + { "lfarrowd", OBM_LFARROWD }, + { "mnarrow", OBM_MNARROW }, + { "combo", OBM_COMBO }, + { "uparrowi", OBM_UPARROWI }, + { "dnarrowi", OBM_DNARROWI }, + { "rgarrowi", OBM_RGARROWI }, + { "lfarrowi", OBM_LFARROWI }, + { "size", OBM_SIZE }, + { "btsize", OBM_BTSIZE }, + { "check", OBM_CHECK }, + { "checkboxes", OBM_CHECKBOXES }, + { "btncorners" , OBM_BTNCORNERS }, + {0} +}; + +static CONST resource_t cursor_table[] = +{ + /* cursors */ + { "normal", OCR_NORMAL }, + { "ibeam", OCR_IBEAM }, + { "wait", OCR_WAIT }, + { "cross", OCR_CROSS }, + { "up", OCR_UP }, + /* { "icon", OCR_ICON }, */ + { "sizenwse", OCR_SIZENWSE }, + { "sizenesw", OCR_SIZENESW }, + { "sizewe", OCR_SIZEWE }, + { "sizens", OCR_SIZENS }, + { "sizeall", OCR_SIZEALL }, + /* { "icour", OCR_ICOCUR }, */ + { "no", OCR_NO }, + { 0 } +}; + +static CONST resource_t icon_table[] = +{ + /* icons */ + { "sample", OIC_SAMPLE }, + { "hand", OIC_HAND }, + { "ques", OIC_QUES }, + { "bang", OIC_BANG }, + { "note", OIC_NOTE }, + { "winlogo", OIC_WINLOGO }, + {0} +}; + +static int resource_name_to_resource (Lisp_Object name, int type) +{ + CONST resource_t* res = (type == IMAGE_CURSOR ? cursor_table + : type == IMAGE_ICON ? icon_table + : bitmap_table); + + if (INTP (name)) + { + return XINT (name); + } + else if (!STRINGP (name)) + { + signal_simple_error ("invalid resource identifier", name); + } + + do { + Extbyte* nm=0; + GET_C_STRING_OS_DATA_ALLOCA (name, nm); + if (!strcasecmp ((char*)res->name, nm)) + return res->resource_id; + } while ((++res)->name); + return 0; +} + +static int +resource_symbol_to_type (Lisp_Object data) +{ + if (EQ (data, Qcursor)) + return IMAGE_CURSOR; + else if (EQ (data, Qicon)) + return IMAGE_ICON; + else if (EQ (data, Qbitmap)) + return IMAGE_BITMAP; + else + return 0; +} + +static void +mswindows_resource_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, + Lisp_Object pointer_fg, Lisp_Object pointer_bg, + int dest_mask, Lisp_Object domain) +{ + struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); + unsigned int type = 0; + HANDLE himage = NULL; + LPCTSTR resid=0; + HINSTANCE hinst = NULL; + ICONINFO iconinfo; + int iitype=0; + char* fname=0; + Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii); + + Lisp_Object file = find_keyword_in_vector (instantiator, Q_file); + Lisp_Object resource_type = find_keyword_in_vector (instantiator, + Q_resource_type); + Lisp_Object resource_id = find_keyword_in_vector (instantiator, + Q_resource_id); + + xzero (iconinfo); + + if (!DEVICE_MSWINDOWS_P (XDEVICE (device))) + signal_simple_error ("Not an mswindows device", device); + + type = resource_symbol_to_type (resource_type); + + if (dest_mask & IMAGE_POINTER_MASK && type == IMAGE_CURSOR) + iitype = IMAGE_POINTER; + else if (dest_mask & IMAGE_COLOR_PIXMAP_MASK) + iitype = IMAGE_COLOR_PIXMAP; + else + incompatible_image_types (instantiator, dest_mask, + IMAGE_COLOR_PIXMAP_MASK | IMAGE_POINTER_MASK); + + /* mess with the keyword info we were provided with */ + if (!NILP (file)) + { + Extbyte* f=0; + GET_C_STRING_FILENAME_DATA_ALLOCA (file, f); +#ifdef __CYGWIN32__ + CYGWIN_WIN32_PATH (f, fname); +#else + fname = f; +#endif + + if (NILP (resource_id)) + resid = (LPCTSTR)fname; + else + { + hinst = LoadLibraryEx (fname, NULL, + LOAD_LIBRARY_AS_DATAFILE); + resid = MAKEINTRESOURCE (resource_name_to_resource (resource_id, + type)); + + if (!resid) + GET_C_STRING_OS_DATA_ALLOCA (resource_id, resid); + } + } + else if (!(resid = MAKEINTRESOURCE (resource_name_to_resource (resource_id, + type)))) + signal_simple_error ("Invalid resource identifier", resource_id); + + /* load the image */ + if (!(himage = LoadImage (hinst, resid, type, 0, 0, + LR_CREATEDIBSECTION | LR_DEFAULTSIZE | + LR_SHARED | + (!NILP (file) ? LR_LOADFROMFILE : 0)))) + { + signal_simple_error ("Cannot load image", instantiator); + } + + if (hinst) + FreeLibrary (hinst); + + mswindows_initialize_dibitmap_image_instance (ii, 1, iitype); + + IMAGE_INSTANCE_PIXMAP_FILENAME (ii) = file; + IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = + GetSystemMetrics (type == IMAGE_CURSOR ? SM_CXCURSOR : SM_CXICON); + IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) = + GetSystemMetrics (type == IMAGE_CURSOR ? SM_CYCURSOR : SM_CYICON); + IMAGE_INSTANCE_PIXMAP_DEPTH (ii) = 1; + + /* hey, we've got an icon type thing so we can reverse engineer the + bitmap and mask */ + if (type != IMAGE_BITMAP) + { + GetIconInfo (himage, &iconinfo); + IMAGE_INSTANCE_MSWINDOWS_BITMAP (ii) = iconinfo.hbmColor; + IMAGE_INSTANCE_MSWINDOWS_MASK (ii) = iconinfo.hbmMask; + XSETINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii), iconinfo.xHotspot); + XSETINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii), iconinfo.yHotspot); + IMAGE_INSTANCE_MSWINDOWS_ICON (ii) = himage; + } + else + { + IMAGE_INSTANCE_MSWINDOWS_ICON (ii) = NULL; + IMAGE_INSTANCE_MSWINDOWS_BITMAP (ii) = himage; + IMAGE_INSTANCE_MSWINDOWS_MASK (ii) = NULL; + XSETINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii), 0); + XSETINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii), 0); + } +} + +static void +check_valid_resource_symbol (Lisp_Object data) +{ + CHECK_SYMBOL (data); + if (!resource_symbol_to_type (data)) + signal_simple_error ("invalid resource type", data); +} + +static void +check_valid_resource_id (Lisp_Object data) +{ + if (!resource_name_to_resource (data, IMAGE_CURSOR) + && + !resource_name_to_resource (data, IMAGE_ICON) + && + !resource_name_to_resource (data, IMAGE_BITMAP)) + signal_simple_error ("invalid resource identifier", data); +} + +void +check_valid_string_or_int (Lisp_Object data) +{ + if (!INTP (data)) + CHECK_STRING (data); + else + CHECK_INT (data); +} + +/********************************************************************** + * XBM * + **********************************************************************/ +#ifndef HAVE_X_WINDOWS +/* $XConsortium: RdBitF.c,v 1.10 94/04/17 20:16:13 kaleb Exp $ */ + +/* + +Copyright (c) 1988 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + +*/ + +/* + * This file contains miscellaneous utility routines and is not part of the + * Xlib standard. + * + * Public entry points: + * + * XmuReadBitmapData read data from FILE descriptor + * XmuReadBitmapDataFromFile read X10 or X11 format bitmap files + * and return data + * + * Note that this file and ../X/XRdBitF.c look very similar.... Keep them + * that way (but don't use common source code so that people can have one + * without the other). + */ + + +/* + * Based on an optimized version provided by Jim Becker, August 5, 1988. + */ +#ifndef BitmapSuccess +#define BitmapSuccess 0 +#define BitmapOpenFailed 1 +#define BitmapFileInvalid 2 +#define BitmapNoMemory 3 +#endif +#define MAX_SIZE 255 + +/* shared data for the image read/parse logic */ +static short hexTable[256]; /* conversion value */ +static int initialized = FALSE; /* easier to fill in at run time */ + +/* + * Table index for the hex values. Initialized once, first time. + * Used for translation value or delimiter significance lookup. + */ +static void initHexTable() +{ + /* + * We build the table at run time for several reasons: + * + * 1. portable to non-ASCII machines. + * 2. still reentrant since we set the init flag after setting table. + * 3. easier to extend. + * 4. less prone to bugs. + */ + hexTable['0'] = 0; hexTable['1'] = 1; + hexTable['2'] = 2; hexTable['3'] = 3; + hexTable['4'] = 4; hexTable['5'] = 5; + hexTable['6'] = 6; hexTable['7'] = 7; + hexTable['8'] = 8; hexTable['9'] = 9; + hexTable['A'] = 10; hexTable['B'] = 11; + hexTable['C'] = 12; hexTable['D'] = 13; + hexTable['E'] = 14; hexTable['F'] = 15; + hexTable['a'] = 10; hexTable['b'] = 11; + hexTable['c'] = 12; hexTable['d'] = 13; + hexTable['e'] = 14; hexTable['f'] = 15; + + /* delimiters of significance are flagged w/ negative value */ + hexTable[' '] = -1; hexTable[','] = -1; + hexTable['}'] = -1; hexTable['\n'] = -1; + hexTable['\t'] = -1; + + initialized = TRUE; +} + +/* + * read next hex value in the input stream, return -1 if EOF + */ +static int NextInt ( FILE *fstream ) +{ + int ch; + int value = 0; + int gotone = 0; + int done = 0; + + /* loop, accumulate hex value until find delimiter */ + /* skip any initial delimiters found in read stream */ + + while (!done) { + ch = getc(fstream); + if (ch == EOF) { + value = -1; + done++; + } else { + /* trim high bits, check type and accumulate */ + ch &= 0xff; + if (isascii(ch) && isxdigit(ch)) { + value = (value << 4) + hexTable[ch]; + gotone++; + } else if ((hexTable[ch]) < 0 && gotone) + done++; + } + } + return value; +} + + +/* + * The data returned by the following routine is always in left-most byte + * first and left-most bit first. If it doesn't return BitmapSuccess then + * its arguments won't have been touched. This routine should look as much + * like the Xlib routine XReadBitmapfile as possible. + */ +int read_bitmap_data (fstream, width, height, datap, x_hot, y_hot) + FILE *fstream; /* handle on file */ + unsigned int *width, *height; /* RETURNED */ + unsigned char **datap; /* RETURNED */ + int *x_hot, *y_hot; /* RETURNED */ +{ + unsigned char *data = NULL; /* working variable */ + char line[MAX_SIZE]; /* input line from file */ + int size; /* number of bytes of data */ + char name_and_type[MAX_SIZE]; /* an input line */ + char *type; /* for parsing */ + int value; /* from an input line */ + int version10p; /* boolean, old format */ + int padding; /* to handle alignment */ + int bytes_per_line; /* per scanline of data */ + unsigned int ww = 0; /* width */ + unsigned int hh = 0; /* height */ + int hx = -1; /* x hotspot */ + int hy = -1; /* y hotspot */ + +#define Xmalloc(size) malloc(size) + + /* first time initialization */ + if (initialized == FALSE) initHexTable(); + + /* error cleanup and return macro */ +#define RETURN(code) { if (data) free (data); return code; } + + while (fgets(line, MAX_SIZE, fstream)) { + if (strlen(line) == MAX_SIZE-1) { + RETURN (BitmapFileInvalid); + } + if (sscanf(line,"#define %s %d",name_and_type,&value) == 2) { + if (!(type = strrchr(name_and_type, '_'))) + type = name_and_type; + else + type++; + + if (!strcmp("width", type)) + ww = (unsigned int) value; + if (!strcmp("height", type)) + hh = (unsigned int) value; + if (!strcmp("hot", type)) { + if (type-- == name_and_type || type-- == name_and_type) + continue; + if (!strcmp("x_hot", type)) + hx = value; + if (!strcmp("y_hot", type)) + hy = value; + } + continue; + } + + if (sscanf(line, "static short %s = {", name_and_type) == 1) + version10p = 1; + else if (sscanf(line,"static unsigned char %s = {",name_and_type) == 1) + version10p = 0; + else if (sscanf(line, "static char %s = {", name_and_type) == 1) + version10p = 0; + else + continue; + + if (!(type = strrchr(name_and_type, '_'))) + type = name_and_type; + else + type++; + + if (strcmp("bits[]", type)) + continue; + + if (!ww || !hh) + RETURN (BitmapFileInvalid); + + if ((ww % 16) && ((ww % 16) < 9) && version10p) + padding = 1; + else + padding = 0; + + bytes_per_line = (ww+7)/8 + padding; + + size = bytes_per_line * hh; + data = (unsigned char *) Xmalloc ((unsigned int) size); + if (!data) + RETURN (BitmapNoMemory); + + if (version10p) { + unsigned char *ptr; + int bytes; + + for (bytes=0, ptr=data; bytes<size; (bytes += 2)) { + if ((value = NextInt(fstream)) < 0) + RETURN (BitmapFileInvalid); + *(ptr++) = value; + if (!padding || ((bytes+2) % bytes_per_line)) + *(ptr++) = value >> 8; + } + } else { + unsigned char *ptr; + int bytes; + + for (bytes=0, ptr=data; bytes<size; bytes++, ptr++) { + if ((value = NextInt(fstream)) < 0) + RETURN (BitmapFileInvalid); + *ptr=value; + } + } + break; + } /* end while */ + + if (data == NULL) { + RETURN (BitmapFileInvalid); + } + + *datap = data; + data = NULL; + *width = ww; + *height = hh; + if (x_hot) *x_hot = hx; + if (y_hot) *y_hot = hy; + + RETURN (BitmapSuccess); +} + + +int read_bitmap_data_from_file (CONST char *filename, unsigned int *width, + unsigned int *height, unsigned char **datap, + int *x_hot, int *y_hot) +{ + FILE *fstream; + int status; + + if ((fstream = fopen (filename, "r")) == NULL) { + return BitmapOpenFailed; + } + status = read_bitmap_data (fstream, width, height, datap, x_hot, y_hot); + fclose (fstream); + return status; +} +#endif /* HAVE_X_WINDOWS */ + +/* this table flips four bits around. */ +static int flip_table[] = +{ + 0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15 +}; + +/* the bitmap data comes in the following format: Widths are padded to + a multiple of 8. Scan lines are stored in increasing byte order + from left to right, little-endian within a byte. 0 = white, 1 = + black. It must be converted to the following format: Widths are + padded to a multiple of 16. Scan lines are stored in increasing + byte order from left to right, big-endian within a byte. 0 = + black, 1 = white. */ +HBITMAP +xbm_create_bitmap_from_data (HDC hdc, char *data, + unsigned int width, unsigned int height, + int mask, COLORREF fg, COLORREF bg) +{ + int old_width = (width + 7)/8; + int new_width = BPLINE (2*((width + 15)/16)); + unsigned char *offset; + void *bmp_buf = 0; + unsigned char *new_data, *new_offset; + int i, j; + BITMAPINFO* bmp_info = + xmalloc_and_zero (sizeof(BITMAPINFO) + sizeof(RGBQUAD)); + HBITMAP bitmap; + + if (!bmp_info) + return NULL; + + new_data = (unsigned char *) xmalloc_and_zero (height * new_width); + + if (!new_data) + { + xfree (bmp_info); + return NULL; + } + + for (i=0; i<height; i++) + { + offset = data + i*old_width; + new_offset = new_data + i*new_width; + + for (j=0; j<old_width; j++) + { + int byte = offset[j]; + new_offset[j] = ~ (unsigned char) + ((flip_table[byte & 0xf] << 4) + flip_table[byte >> 4]); + } + } + + /* if we want a mask invert the bits */ + if (!mask) + { + new_offset = &new_data[height * new_width]; + while (new_offset-- != new_data) + { + *new_offset ^= 0xff; + } + } + + bmp_info->bmiHeader.biWidth=width; + bmp_info->bmiHeader.biHeight=-(LONG)height; + bmp_info->bmiHeader.biPlanes=1; + bmp_info->bmiHeader.biSize=sizeof(BITMAPINFOHEADER); + bmp_info->bmiHeader.biBitCount=1; + bmp_info->bmiHeader.biCompression=BI_RGB; + bmp_info->bmiHeader.biClrUsed = 2; + bmp_info->bmiHeader.biClrImportant = 2; + bmp_info->bmiHeader.biSizeImage = height * new_width; + bmp_info->bmiColors[0].rgbRed = GetRValue (fg); + bmp_info->bmiColors[0].rgbGreen = GetGValue (fg); + bmp_info->bmiColors[0].rgbBlue = GetBValue (fg); + bmp_info->bmiColors[0].rgbReserved = 0; + bmp_info->bmiColors[1].rgbRed = GetRValue (bg); + bmp_info->bmiColors[1].rgbGreen = GetGValue (bg); + bmp_info->bmiColors[1].rgbBlue = GetBValue (bg); + bmp_info->bmiColors[1].rgbReserved = 0; + + bitmap = CreateDIBSection (hdc, + bmp_info, + DIB_RGB_COLORS, + &bmp_buf, + 0,0); + + xfree (bmp_info); + + if (!bitmap || !bmp_buf) + { + xfree (new_data); + return NULL; + } + + /* copy in the actual bitmap */ + memcpy (bmp_buf, new_data, height * new_width); + xfree (new_data); + + return bitmap; +} + +/* Given inline data for a mono pixmap, initialize the given + image instance accordingly. */ + +static void +init_image_instance_from_xbm_inline (struct Lisp_Image_Instance *ii, + int width, int height, + /* Note that data is in ext-format! */ + CONST char *bits, + Lisp_Object instantiator, + Lisp_Object pointer_fg, + Lisp_Object pointer_bg, + int dest_mask, + HBITMAP mask, + Lisp_Object mask_filename) +{ + Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii); + struct frame* f = XFRAME (DEVICE_SELECTED_FRAME (XDEVICE (device))); + Lisp_Object foreground = find_keyword_in_vector (instantiator, Q_foreground); + Lisp_Object background = find_keyword_in_vector (instantiator, Q_background); + enum image_instance_type type; + COLORREF black = PALETTERGB (0,0,0); + COLORREF white = PALETTERGB (255,255,255); + + HDC hdc = FRAME_MSWINDOWS_CDC (f); + + if (!DEVICE_MSWINDOWS_P (XDEVICE (device))) + signal_simple_error ("Not an MS-Windows device", device); + + if ((dest_mask & IMAGE_MONO_PIXMAP_MASK) && + (dest_mask & IMAGE_COLOR_PIXMAP_MASK)) + { + if (!NILP (foreground) || !NILP (background)) + type = IMAGE_COLOR_PIXMAP; + else + type = IMAGE_MONO_PIXMAP; + } + else if (dest_mask & IMAGE_MONO_PIXMAP_MASK) + type = IMAGE_MONO_PIXMAP; + else if (dest_mask & IMAGE_COLOR_PIXMAP_MASK) + type = IMAGE_COLOR_PIXMAP; + else if (dest_mask & IMAGE_POINTER_MASK) + type = IMAGE_POINTER; + else + incompatible_image_types (instantiator, dest_mask, + IMAGE_MONO_PIXMAP_MASK | IMAGE_COLOR_PIXMAP_MASK + | IMAGE_POINTER_MASK); + + mswindows_initialize_dibitmap_image_instance (ii, 1, type); + + IMAGE_INSTANCE_PIXMAP_FILENAME (ii) = + find_keyword_in_vector (instantiator, Q_file); + IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = width; + IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) = height; + IMAGE_INSTANCE_PIXMAP_DEPTH (ii) = 1; + XSETINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii), 0); + XSETINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii), 0); + IMAGE_INSTANCE_MSWINDOWS_MASK (ii) = mask ? mask : + xbm_create_bitmap_from_data (hdc, (Extbyte *) bits, width, height, + TRUE, black, white); + + switch (type) + { + case IMAGE_MONO_PIXMAP: + IMAGE_INSTANCE_MSWINDOWS_BITMAP (ii) = + xbm_create_bitmap_from_data (hdc, (Extbyte *) bits, width, height, + FALSE, black, black); + break; + + case IMAGE_COLOR_PIXMAP: + { + COLORREF fg = black; + COLORREF bg = white; + + if (!NILP (foreground) && !COLOR_INSTANCEP (foreground)) + foreground = + Fmake_color_instance (foreground, device, + encode_error_behavior_flag (ERROR_ME)); + + if (COLOR_INSTANCEP (foreground)) + fg = COLOR_INSTANCE_MSWINDOWS_COLOR (XCOLOR_INSTANCE (foreground)); + + if (!NILP (background) && !COLOR_INSTANCEP (background)) + background = + Fmake_color_instance (background, device, + encode_error_behavior_flag (ERROR_ME)); + + if (COLOR_INSTANCEP (background)) + bg = COLOR_INSTANCE_MSWINDOWS_COLOR (XCOLOR_INSTANCE (background)); + + IMAGE_INSTANCE_PIXMAP_FG (ii) = foreground; + IMAGE_INSTANCE_PIXMAP_BG (ii) = background; + + IMAGE_INSTANCE_MSWINDOWS_BITMAP (ii) = + xbm_create_bitmap_from_data (hdc, (Extbyte *) bits, width, height, + FALSE, fg, black); + } + break; + + case IMAGE_POINTER: + { + COLORREF fg = black; + COLORREF bg = white; + + if (NILP (foreground)) + foreground = pointer_fg; + if (NILP (background)) + background = pointer_bg; + + IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii) = + find_keyword_in_vector (instantiator, Q_hotspot_x); + IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii) = + find_keyword_in_vector (instantiator, Q_hotspot_y); + IMAGE_INSTANCE_PIXMAP_FG (ii) = foreground; + IMAGE_INSTANCE_PIXMAP_BG (ii) = background; + if (COLOR_INSTANCEP (foreground)) + fg = COLOR_INSTANCE_MSWINDOWS_COLOR (XCOLOR_INSTANCE (foreground)); + if (COLOR_INSTANCEP (background)) + bg = COLOR_INSTANCE_MSWINDOWS_COLOR (XCOLOR_INSTANCE (background)); + + IMAGE_INSTANCE_MSWINDOWS_BITMAP (ii) = + xbm_create_bitmap_from_data (hdc, (Extbyte *) bits, width, height, + TRUE, fg, black); + mswindows_initialize_image_instance_icon (ii, TRUE); + } + break; + + default: + abort (); + } +} + +static void +xbm_instantiate_1 (Lisp_Object image_instance, Lisp_Object instantiator, + Lisp_Object pointer_fg, Lisp_Object pointer_bg, + int dest_mask, int width, int height, + /* Note that data is in ext-format! */ + CONST char *bits) +{ + Lisp_Object mask_data = find_keyword_in_vector (instantiator, Q_mask_data); + Lisp_Object mask_file = find_keyword_in_vector (instantiator, Q_mask_file); + struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); + struct frame* f = XFRAME (DEVICE_SELECTED_FRAME + (XDEVICE (IMAGE_INSTANCE_DEVICE (ii)))); + HDC hdc = FRAME_MSWINDOWS_CDC (f); + HBITMAP mask = 0; + CONST char *gcc_may_you_rot_in_hell; + + if (!NILP (mask_data)) + { + GET_C_STRING_BINARY_DATA_ALLOCA (XCAR (XCDR (XCDR (mask_data))), + gcc_may_you_rot_in_hell); + mask = + xbm_create_bitmap_from_data ( hdc, + (unsigned char *) + gcc_may_you_rot_in_hell, + XINT (XCAR (mask_data)), + XINT (XCAR (XCDR (mask_data))), FALSE, + PALETTERGB (0,0,0), + PALETTERGB (255,255,255)); + } + + init_image_instance_from_xbm_inline (ii, width, height, bits, + instantiator, pointer_fg, pointer_bg, + dest_mask, mask, mask_file); +} + +/* Instantiate method for XBM's. */ + +static void +mswindows_xbm_instantiate (Lisp_Object image_instance, + Lisp_Object instantiator, + Lisp_Object pointer_fg, Lisp_Object pointer_bg, + int dest_mask, Lisp_Object domain) +{ + Lisp_Object data = find_keyword_in_vector (instantiator, Q_data); + CONST char *gcc_go_home; + + assert (!NILP (data)); + + GET_C_STRING_BINARY_DATA_ALLOCA (XCAR (XCDR (XCDR (data))), + gcc_go_home); + + xbm_instantiate_1 (image_instance, instantiator, pointer_fg, + pointer_bg, dest_mask, XINT (XCAR (data)), + XINT (XCAR (XCDR (data))), gcc_go_home); +} + +#ifdef HAVE_XFACE +/********************************************************************** + * X-Face * + **********************************************************************/ +#if defined(EXTERN) +/* This is about to get redefined! */ +#undef EXTERN +#endif +/* We have to define SYSV32 so that compface.h includes string.h + instead of strings.h. */ +#define SYSV32 +#ifdef __cplusplus +extern "C" { +#endif +#include <compface.h> +#ifdef __cplusplus +} +#endif +/* JMP_BUF cannot be used here because if it doesn't get defined + to jmp_buf we end up with a conflicting type error with the + definition in compface.h */ +extern jmp_buf comp_env; +#undef SYSV32 + +static void +mswindows_xface_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, + Lisp_Object pointer_fg, Lisp_Object pointer_bg, + int dest_mask, Lisp_Object domain) +{ + Lisp_Object data = find_keyword_in_vector (instantiator, Q_data); + int i, stattis; + char *p, *bits, *bp; + CONST char * volatile emsg = 0; + CONST char * volatile dstring; + + assert (!NILP (data)); + + GET_C_STRING_BINARY_DATA_ALLOCA (data, dstring); + + if ((p = strchr (dstring, ':'))) + { + dstring = p + 1; + } + + /* Must use setjmp not SETJMP because we used jmp_buf above not JMP_BUF */ + if (!(stattis = setjmp (comp_env))) + { + UnCompAll ((char *) dstring); + UnGenFace (); + } + + switch (stattis) + { + case -2: + emsg = "uncompface: internal error"; + break; + case -1: + emsg = "uncompface: insufficient or invalid data"; + break; + case 1: + emsg = "uncompface: excess data ignored"; + break; + } + + if (emsg) + signal_simple_error_2 (emsg, data, Qimage); + + bp = bits = (char *) alloca (PIXELS / 8); + + /* the compface library exports char F[], which uses a single byte per + pixel to represent a 48x48 bitmap. Yuck. */ + for (i = 0, p = F; i < (PIXELS / 8); ++i) + { + int n, b; + /* reverse the bit order of each byte... */ + for (b = n = 0; b < 8; ++b) + { + n |= ((*p++) << b); + } + *bp++ = (char) n; + } + + xbm_instantiate_1 (image_instance, instantiator, pointer_fg, + pointer_bg, dest_mask, 48, 48, bits); +} +#endif /* HAVE_XFACE */ + + +/************************************************************************/ +/* image instance methods */ +/************************************************************************/ + +static void +mswindows_print_image_instance (struct Lisp_Image_Instance *p, + Lisp_Object printcharfun, + int escapeflag) +{ + char buf[100]; + + switch (IMAGE_INSTANCE_TYPE (p)) + { + case IMAGE_MONO_PIXMAP: + case IMAGE_COLOR_PIXMAP: + case IMAGE_POINTER: + sprintf (buf, " (0x%lx", + (unsigned long) IMAGE_INSTANCE_MSWINDOWS_BITMAP (p)); + write_c_string (buf, printcharfun); + if (IMAGE_INSTANCE_MSWINDOWS_MASK (p)) + { + sprintf (buf, "/0x%lx", + (unsigned long) IMAGE_INSTANCE_MSWINDOWS_MASK (p)); + write_c_string (buf, printcharfun); + } + write_c_string (")", printcharfun); + break; + + default: + break; + } +} + +#ifdef DEBUG_WIDGETS +extern int debug_widget_instances; +#endif + +static void +mswindows_finalize_image_instance (struct Lisp_Image_Instance *p) +{ + if (DEVICE_LIVE_P (XDEVICE (p->device))) + { + if (IMAGE_INSTANCE_TYPE (p) == IMAGE_WIDGET + || + IMAGE_INSTANCE_TYPE (p) == IMAGE_SUBWINDOW) + { +#ifdef DEBUG_WIDGETS + debug_widget_instances--; + stderr_out ("widget destroyed, %d left\n", debug_widget_instances); +#endif + if (IMAGE_INSTANCE_SUBWINDOW_ID (p)) + { + DestroyWindow (WIDGET_INSTANCE_MSWINDOWS_HANDLE (p)); + DestroyWindow (IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (p)); + IMAGE_INSTANCE_SUBWINDOW_ID (p) = 0; + } + } + else if (p->data) + { + int i; + if (IMAGE_INSTANCE_PIXMAP_TIMEOUT (p)) + disable_glyph_animated_timeout (IMAGE_INSTANCE_PIXMAP_TIMEOUT (p)); + + if (IMAGE_INSTANCE_MSWINDOWS_BITMAP_SLICES (p)) + { + for (i = 0; i < IMAGE_INSTANCE_PIXMAP_MAXSLICE (p); i++) + { + if (IMAGE_INSTANCE_MSWINDOWS_BITMAP_SLICE (p, i)) + DeleteObject (IMAGE_INSTANCE_MSWINDOWS_BITMAP_SLICE (p, i)); + IMAGE_INSTANCE_MSWINDOWS_BITMAP_SLICE (p, i) = 0; + } + xfree (IMAGE_INSTANCE_MSWINDOWS_BITMAP_SLICES (p)); + IMAGE_INSTANCE_MSWINDOWS_BITMAP_SLICES (p) = 0; + } + if (IMAGE_INSTANCE_MSWINDOWS_MASK (p)) + DeleteObject (IMAGE_INSTANCE_MSWINDOWS_MASK (p)); + IMAGE_INSTANCE_MSWINDOWS_MASK (p) = 0; + if (IMAGE_INSTANCE_MSWINDOWS_ICON (p)) + DestroyIcon (IMAGE_INSTANCE_MSWINDOWS_ICON (p)); + IMAGE_INSTANCE_MSWINDOWS_ICON (p) = 0; + } + } + + if (p->data) + { + xfree (p->data); + p->data = 0; + } +} + +/************************************************************************/ +/* subwindow and widget support */ +/************************************************************************/ + +/* unmap the image if it is a widget. This is used by redisplay via + redisplay_unmap_subwindows */ +static void +mswindows_unmap_subwindow (struct Lisp_Image_Instance *p) +{ + if (IMAGE_INSTANCE_SUBWINDOW_ID (p)) + { + SetWindowPos (IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (p), + NULL, + 0, 0, 0, 0, + SWP_HIDEWINDOW | SWP_NOMOVE | SWP_NOSIZE + | SWP_NOSENDCHANGING); + } +} + +/* map the subwindow. This is used by redisplay via + redisplay_output_subwindow */ +static void +mswindows_map_subwindow (struct Lisp_Image_Instance *p, int x, int y, + struct display_glyph_area* dga) +{ + /* move the window before mapping it ... */ + SetWindowPos (IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (p), + NULL, + x, y, dga->width, dga->height, + SWP_NOZORDER + | SWP_NOCOPYBITS | SWP_NOSENDCHANGING); + /* ... adjust the child ... */ + SetWindowPos (WIDGET_INSTANCE_MSWINDOWS_HANDLE (p), + NULL, + -dga->xoffset, -dga->yoffset, 0, 0, + SWP_NOZORDER | SWP_NOSIZE + | SWP_NOCOPYBITS | SWP_NOSENDCHANGING); + /* ... now map it - we are not allowed to move it at the same time. */ + SetWindowPos (IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (p), + NULL, + 0, 0, 0, 0, + SWP_NOZORDER | SWP_NOSIZE | SWP_NOMOVE + | SWP_SHOWWINDOW | SWP_NOCOPYBITS + | SWP_NOSENDCHANGING); +} + +/* resize the subwindow instance */ +static void +mswindows_resize_subwindow (struct Lisp_Image_Instance* ii, int w, int h) +{ + /* Set the size of the control .... */ + SetWindowPos (WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii), + NULL, + 0, 0, w, h, + SWP_NOZORDER | SWP_NOMOVE + | SWP_NOCOPYBITS | SWP_NOSENDCHANGING); +} + +/* when you click on a widget you may activate another widget this + needs to be checked and all appropriate widgets updated */ +static void +mswindows_update_subwindow (struct Lisp_Image_Instance *p) +{ + if (IMAGE_INSTANCE_TYPE (p) == IMAGE_WIDGET) + { + /* buttons checked or otherwise */ + if ( EQ (IMAGE_INSTANCE_WIDGET_TYPE (p), Qbutton)) + { + if (gui_item_selected_p (IMAGE_INSTANCE_WIDGET_ITEM (p))) + SendMessage (WIDGET_INSTANCE_MSWINDOWS_HANDLE (p), + BM_SETCHECK, (WPARAM)BST_CHECKED, 0); + else + SendMessage (WIDGET_INSTANCE_MSWINDOWS_HANDLE (p), + BM_SETCHECK, (WPARAM)BST_UNCHECKED, 0); + } + + /* set the widget font from the widget face */ + SendMessage (WIDGET_INSTANCE_MSWINDOWS_HANDLE (p), + WM_SETFONT, + (WPARAM)FONT_INSTANCE_MSWINDOWS_HFONT + (XFONT_INSTANCE (widget_face_font_info + (IMAGE_INSTANCE_SUBWINDOW_FRAME (p), + IMAGE_INSTANCE_WIDGET_FACE (p), + 0, 0))), + MAKELPARAM (TRUE, 0)); + } +} + +/* register widgets into our hastable so that we can cope with the + callbacks. The hashtable is weak so deregistration is handled + automatically */ +static int +mswindows_register_gui_item (Lisp_Object gui, Lisp_Object domain) +{ + Lisp_Object frame = FW_FRAME (domain); + struct frame* f = XFRAME (frame); + int id = gui_item_id_hash (FRAME_MSWINDOWS_WIDGET_HASH_TABLE (f), + gui, + WIDGET_GLYPH_SLOT); + Fputhash (make_int (id), + XGUI_ITEM (gui)->callback, + FRAME_MSWINDOWS_WIDGET_HASH_TABLE (f)); + return id; +} + +static int +mswindows_register_widget_instance (Lisp_Object instance, Lisp_Object domain) +{ + return mswindows_register_gui_item (XIMAGE_INSTANCE_WIDGET_ITEM (instance), + domain); +} + +static void +mswindows_subwindow_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, + Lisp_Object pointer_fg, Lisp_Object pointer_bg, + int dest_mask, Lisp_Object domain) +{ + struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); + Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii); + struct device* d = XDEVICE (device); + Lisp_Object frame = FW_FRAME (domain); + HWND wnd; + + if (!DEVICE_MSWINDOWS_P (d)) + signal_simple_error ("Not an mswindows device", device); + + /* have to set the type this late in case there is no device + instantiation for a widget */ + IMAGE_INSTANCE_TYPE (ii) = IMAGE_SUBWINDOW; + /* Allocate space for the clip window */ + ii->data = xnew_and_zero (struct mswindows_subwindow_data); + + if ((IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (ii) + = CreateWindowEx( + 0, /* EX flags */ + XEMACS_CONTROL_CLASS, + 0, /* text */ + WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_CHILD, + 0, /* starting x position */ + 0, /* starting y position */ + IMAGE_INSTANCE_WIDGET_WIDTH (ii), + IMAGE_INSTANCE_WIDGET_HEIGHT (ii), + /* parent window */ + FRAME_MSWINDOWS_HANDLE (XFRAME (frame)), + NULL, /* No menu */ + NULL, /* must be null for this class */ + NULL)) == NULL) + signal_simple_error ("window creation failed with code", + make_int (GetLastError())); + + wnd = CreateWindow( "STATIC", + "", + WS_CHILD, + 0, /* starting x position */ + 0, /* starting y position */ + IMAGE_INSTANCE_WIDGET_WIDTH (ii), + IMAGE_INSTANCE_WIDGET_HEIGHT (ii), + IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (ii), + 0, + (HINSTANCE) + GetWindowLong (FRAME_MSWINDOWS_HANDLE (XFRAME (frame)), + GWL_HINSTANCE), + NULL); + + SetWindowLong (wnd, GWL_USERDATA, (LONG)LISP_TO_VOID(image_instance)); + IMAGE_INSTANCE_SUBWINDOW_ID (ii) = wnd; +} + +static int +mswindows_image_instance_equal (struct Lisp_Image_Instance *p1, + struct Lisp_Image_Instance *p2, int depth) +{ + switch (IMAGE_INSTANCE_TYPE (p1)) + { + case IMAGE_MONO_PIXMAP: + case IMAGE_COLOR_PIXMAP: + case IMAGE_POINTER: + if (IMAGE_INSTANCE_MSWINDOWS_BITMAP (p1) + != IMAGE_INSTANCE_MSWINDOWS_BITMAP (p2)) + return 0; + break; + + default: + break; + } + + return 1; +} + +static unsigned long +mswindows_image_instance_hash (struct Lisp_Image_Instance *p, int depth) +{ + switch (IMAGE_INSTANCE_TYPE (p)) + { + case IMAGE_MONO_PIXMAP: + case IMAGE_COLOR_PIXMAP: + case IMAGE_POINTER: + return (unsigned long) IMAGE_INSTANCE_MSWINDOWS_BITMAP (p); + + default: + return 0; + } +} + +/* Set all the slots in an image instance structure to reasonable + default values. This is used somewhere within an instantiate + method. It is assumed that the device slot within the image + instance is already set -- this is the case when instantiate + methods are called. */ + +static void +mswindows_initialize_dibitmap_image_instance (struct Lisp_Image_Instance *ii, + int slices, + enum image_instance_type type) +{ + ii->data = xnew_and_zero (struct mswindows_image_instance_data); + IMAGE_INSTANCE_TYPE (ii) = type; + IMAGE_INSTANCE_PIXMAP_FILENAME (ii) = Qnil; + IMAGE_INSTANCE_PIXMAP_MASK_FILENAME (ii) = Qnil; + IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii) = Qnil; + IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii) = Qnil; + IMAGE_INSTANCE_PIXMAP_FG (ii) = Qnil; + IMAGE_INSTANCE_PIXMAP_BG (ii) = Qnil; + IMAGE_INSTANCE_PIXMAP_MAXSLICE (ii) = slices; + IMAGE_INSTANCE_MSWINDOWS_BITMAP_SLICES (ii) = + xnew_array_and_zero (HBITMAP, slices); +} + + +#ifdef HAVE_WIDGETS + +/************************************************************************/ +/* widgets */ +/************************************************************************/ +static void +mswindows_widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, + Lisp_Object pointer_fg, Lisp_Object pointer_bg, + int dest_mask, Lisp_Object domain, + CONST char* class, int flags, int exflags) +{ + /* this function can call lisp */ + struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); + Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii), style; + struct device* d = XDEVICE (device); + Lisp_Object frame = FW_FRAME (domain); + Extbyte* nm=0; + HWND wnd; + int id = 0xffff; + Lisp_Object gui = IMAGE_INSTANCE_WIDGET_ITEM (ii); + struct Lisp_Gui_Item* pgui = XGUI_ITEM (gui); + + if (!DEVICE_MSWINDOWS_P (d)) + signal_simple_error ("Not an mswindows device", device); + + if (!gui_item_active_p (gui)) + flags |= WS_DISABLED; + + style = pgui->style; + + if (!NILP (pgui->callback)) + { + id = mswindows_register_widget_instance (image_instance, domain); + } + /* have to set the type this late in case there is no device + instantiation for a widget */ + IMAGE_INSTANCE_TYPE (ii) = IMAGE_WIDGET; + if (!NILP (IMAGE_INSTANCE_WIDGET_TEXT (ii))) + GET_C_STRING_OS_DATA_ALLOCA (IMAGE_INSTANCE_WIDGET_TEXT (ii), nm); + + /* allocate space for the clip window and then allocate the clip window */ + ii->data = xnew_and_zero (struct mswindows_subwindow_data); + + if ((IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (ii) + = CreateWindowEx( + 0, /* EX flags */ + XEMACS_CONTROL_CLASS, + 0, /* text */ + WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_CHILD, + 0, /* starting x position */ + 0, /* starting y position */ + IMAGE_INSTANCE_WIDGET_WIDTH (ii), + IMAGE_INSTANCE_WIDGET_HEIGHT (ii), + /* parent window */ + FRAME_MSWINDOWS_HANDLE (XFRAME (frame)), + (HMENU)id, /* No menu */ + NULL, /* must be null for this class */ + NULL)) == NULL) + signal_simple_error ("window creation failed with code", + make_int (GetLastError())); + + if ((wnd = CreateWindowEx( + exflags /* | WS_EX_NOPARENTNOTIFY*/, + class, + nm, + flags | WS_CHILD | WS_VISIBLE, + 0, /* starting x position */ + 0, /* starting y position */ + IMAGE_INSTANCE_WIDGET_WIDTH (ii), + IMAGE_INSTANCE_WIDGET_HEIGHT (ii), + /* parent window */ + IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (ii), + (HMENU)id, /* No menu */ + (HINSTANCE) + GetWindowLong + (FRAME_MSWINDOWS_HANDLE (XFRAME (frame)), + GWL_HINSTANCE), + NULL)) == NULL) + signal_simple_error ("window creation failed with code", + make_int (GetLastError())); + + IMAGE_INSTANCE_SUBWINDOW_ID (ii) = wnd; + SetWindowLong (wnd, GWL_USERDATA, (LONG)LISP_TO_VOID(image_instance)); + /* set the widget font from the widget face */ + SendMessage (wnd, WM_SETFONT, + (WPARAM)FONT_INSTANCE_MSWINDOWS_HFONT + (XFONT_INSTANCE (widget_face_font_info + (domain, + IMAGE_INSTANCE_WIDGET_FACE (ii), + 0, 0))), + MAKELPARAM (TRUE, 0)); +} + +/* Instantiate a button widget. Unfortunately instantiated widgets are + particular to a frame since they need to have a parent. It's not + like images where you just select the image into the context you + want to display it in and BitBlt it. So images instances can have a + many-to-one relationship with things you see, whereas widgets can + only be one-to-one (i.e. per frame) */ +static void +mswindows_button_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, + Lisp_Object pointer_fg, Lisp_Object pointer_bg, + int dest_mask, Lisp_Object domain) +{ + /* this function can call lisp */ + struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); + HWND wnd; + int flags = BS_NOTIFY; + Lisp_Object style; + Lisp_Object gui = IMAGE_INSTANCE_WIDGET_ITEM (ii); + struct Lisp_Gui_Item* pgui = XGUI_ITEM (gui); + Lisp_Object glyph = find_keyword_in_vector (instantiator, Q_image); + + if (!gui_item_active_p (gui)) + flags |= WS_DISABLED; + + if (!NILP (glyph)) + { + if (!IMAGE_INSTANCEP (glyph)) + glyph = glyph_image_instance (glyph, domain, ERROR_ME, 1); + + if (IMAGE_INSTANCEP (glyph)) + flags |= XIMAGE_INSTANCE_MSWINDOWS_BITMAP (glyph) ? + BS_BITMAP : BS_ICON; + } + + style = pgui->style; + + if (EQ (style, Qradio)) + { + flags |= BS_RADIOBUTTON; + } + else if (EQ (style, Qtoggle)) + { + flags |= BS_AUTOCHECKBOX; + } + else + flags |= BS_DEFPUSHBUTTON; + + mswindows_widget_instantiate (image_instance, instantiator, pointer_fg, + pointer_bg, dest_mask, domain, "BUTTON", flags, + WS_EX_CONTROLPARENT); + + wnd = WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii); + /* set the checked state */ + if (gui_item_selected_p (gui)) + SendMessage (wnd, BM_SETCHECK, (WPARAM)BST_CHECKED, 0); + else + SendMessage (wnd, BM_SETCHECK, (WPARAM)BST_UNCHECKED, 0); + /* add the image if one was given */ + if (!NILP (glyph) && IMAGE_INSTANCEP (glyph)) + { + SendMessage (wnd, BM_SETIMAGE, + (WPARAM) (XIMAGE_INSTANCE_MSWINDOWS_BITMAP (glyph) ? + IMAGE_BITMAP : IMAGE_ICON), + (LPARAM) (XIMAGE_INSTANCE_MSWINDOWS_BITMAP (glyph) ? + XIMAGE_INSTANCE_MSWINDOWS_BITMAP (glyph) : + XIMAGE_INSTANCE_MSWINDOWS_ICON (glyph))); + } +} + +/* instantiate an edit control */ +static void +mswindows_edit_field_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, + Lisp_Object pointer_fg, Lisp_Object pointer_bg, + int dest_mask, Lisp_Object domain) +{ + mswindows_widget_instantiate (image_instance, instantiator, pointer_fg, + pointer_bg, dest_mask, domain, "EDIT", + ES_LEFT | ES_AUTOHSCROLL | WS_TABSTOP + | WS_BORDER, + WS_EX_CLIENTEDGE | WS_EX_CONTROLPARENT); +} + +/* instantiate a progress gauge */ +static void +mswindows_progress_gauge_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, + Lisp_Object pointer_fg, Lisp_Object pointer_bg, + int dest_mask, Lisp_Object domain) +{ + HWND wnd; + struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); + mswindows_widget_instantiate (image_instance, instantiator, pointer_fg, + pointer_bg, dest_mask, domain, PROGRESS_CLASS, + WS_TABSTOP | WS_BORDER | PBS_SMOOTH, + WS_EX_CLIENTEDGE | WS_EX_CONTROLPARENT); + wnd = WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii); + /* set the colors */ +#ifdef PBS_SETBKCOLOR + SendMessage (wnd, PBS_SETBKCOLOR, 0, + (LPARAM) (COLOR_INSTANCE_MSWINDOWS_COLOR + (XCOLOR_INSTANCE + (FACE_BACKGROUND + (XIMAGE_INSTANCE_WIDGET_FACE (ii), + XIMAGE_INSTANCE_SUBWINDOW_FRAME (ii)))))); +#endif +#ifdef PBS_SETBARCOLOR + SendMessage (wnd, PBS_SETBARCOLOR, 0, + (L:PARAM) (COLOR_INSTANCE_MSWINDOWS_COLOR + (XCOLOR_INSTANCE + (FACE_FOREGROUND + (XIMAGE_INSTANCE_WIDGET_FACE (ii), + XIMAGE_INSTANCE_SUBWINDOW_FRAME (ii)))))); +#endif +} + +/* instantiate a tree view widget */ +static HTREEITEM add_tree_item (Lisp_Object image_instance, + HWND wnd, HTREEITEM parent, Lisp_Object item, + int children, Lisp_Object domain) +{ + TV_INSERTSTRUCT tvitem; + HTREEITEM ret; + + tvitem.hParent = parent; + tvitem.hInsertAfter = TVI_LAST; + tvitem.item.mask = TVIF_TEXT | TVIF_CHILDREN; + tvitem.item.cChildren = children; + + if (GUI_ITEMP (item)) + { + tvitem.item.lParam = mswindows_register_gui_item (item, domain); + tvitem.item.mask |= TVIF_PARAM; + GET_C_STRING_OS_DATA_ALLOCA (XGUI_ITEM (item)->name, + tvitem.item.pszText); + } + else + GET_C_STRING_OS_DATA_ALLOCA (item, tvitem.item.pszText); + + tvitem.item.cchTextMax = strlen (tvitem.item.pszText); + + if ((ret = (HTREEITEM)SendMessage (wnd, TVM_INSERTITEM, + 0, (LPARAM)&tvitem)) == 0) + signal_simple_error ("error adding tree view entry", item); + + return ret; +} + +static void add_tree_item_list (Lisp_Object image_instance, + HWND wnd, HTREEITEM parent, Lisp_Object list, + Lisp_Object domain) +{ + Lisp_Object rest; + + /* get the first item */ + parent = add_tree_item (image_instance, wnd, parent, XCAR (list), TRUE, domain); + /* recursively add items to the tree view */ + LIST_LOOP (rest, XCDR (list)) + { + if (LISTP (XCAR (rest))) + add_tree_item_list (image_instance, wnd, parent, XCAR (rest), domain); + else + add_tree_item (image_instance, wnd, parent, XCAR (rest), FALSE, domain); + } +} + +static void +mswindows_tree_view_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, + Lisp_Object pointer_fg, Lisp_Object pointer_bg, + int dest_mask, Lisp_Object domain) +{ + Lisp_Object rest; + HWND wnd; + HTREEITEM parent; + struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); + mswindows_widget_instantiate (image_instance, instantiator, pointer_fg, + pointer_bg, dest_mask, domain, WC_TREEVIEW, + WS_TABSTOP | WS_BORDER | PBS_SMOOTH + | TVS_HASLINES | TVS_HASBUTTONS, + WS_EX_CLIENTEDGE | WS_EX_CONTROLPARENT); + + wnd = WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii); + + /* define a root */ + parent = add_tree_item (image_instance, wnd, NULL, + XCAR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)), + TRUE, domain); + + /* recursively add items to the tree view */ + /* add items to the tab */ + LIST_LOOP (rest, XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii))) + { + if (LISTP (XCAR (rest))) + add_tree_item_list (image_instance, wnd, parent, XCAR (rest), domain); + else + add_tree_item (image_instance, wnd, parent, XCAR (rest), FALSE, domain); + } +} + +/* instantiate a tab control */ +static TC_ITEM* add_tab_item (Lisp_Object image_instance, + HWND wnd, Lisp_Object item, + Lisp_Object domain, int index) +{ + TC_ITEM tvitem, *ret; + + tvitem.mask = TCIF_TEXT; + + if (GUI_ITEMP (item)) + { + tvitem.lParam = mswindows_register_gui_item (item, domain); + tvitem.mask |= TCIF_PARAM; + GET_C_STRING_OS_DATA_ALLOCA (XGUI_ITEM (item)->name, + tvitem.pszText); + } + else + { + CHECK_STRING (item); + GET_C_STRING_OS_DATA_ALLOCA (item, tvitem.pszText); + } + + tvitem.cchTextMax = strlen (tvitem.pszText); + + if ((ret = (TC_ITEM*)SendMessage (wnd, TCM_INSERTITEM, + index, (LPARAM)&tvitem)) < 0) + signal_simple_error ("error adding tab entry", item); + + return ret; +} + +static void +mswindows_tab_control_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, + Lisp_Object pointer_fg, Lisp_Object pointer_bg, + int dest_mask, Lisp_Object domain) +{ + Lisp_Object rest; + HWND wnd; + int index = 0; + struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); + mswindows_widget_instantiate (image_instance, instantiator, pointer_fg, + pointer_bg, dest_mask, domain, WC_TABCONTROL, + /* borders don't suit tabs so well */ + WS_TABSTOP, + WS_EX_CONTROLPARENT); + + wnd = WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii); + /* add items to the tab */ + LIST_LOOP (rest, XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii))) + { + add_tab_item (image_instance, wnd, XCAR (rest), domain, index); + index++; + } +} + +/* set the properties of a tab control */ +static Lisp_Object +mswindows_tab_control_set_property (Lisp_Object image_instance, Lisp_Object prop, + Lisp_Object val) +{ + struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); + + if (EQ (prop, Q_items)) + { + HWND wnd = WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii); + int index = 0; + Lisp_Object rest; + check_valid_item_list_1 (val); + + /* delete the pre-existing items */ + SendMessage (wnd, TCM_DELETEALLITEMS, 0, 0); + + IMAGE_INSTANCE_WIDGET_ITEMS (ii) = + Fcons (XCAR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)), + parse_gui_item_tree_children (val)); + + /* add items to the tab */ + LIST_LOOP (rest, XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii))) + { + add_tab_item (image_instance, wnd, XCAR (rest), + IMAGE_INSTANCE_SUBWINDOW_FRAME (ii), index); + index++; + } + + return Qt; + } + return Qunbound; +} + +/* instantiate a static control possible for putting other things in */ +static void +mswindows_label_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, + Lisp_Object pointer_fg, Lisp_Object pointer_bg, + int dest_mask, Lisp_Object domain) +{ + mswindows_widget_instantiate (image_instance, instantiator, pointer_fg, + pointer_bg, dest_mask, domain, "STATIC", + 0, WS_EX_STATICEDGE); +} + +/* instantiate a scrollbar control */ +static void +mswindows_scrollbar_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, + Lisp_Object pointer_fg, Lisp_Object pointer_bg, + int dest_mask, Lisp_Object domain) +{ + mswindows_widget_instantiate (image_instance, instantiator, pointer_fg, + pointer_bg, dest_mask, domain, "SCROLLBAR", + 0, + WS_EX_CLIENTEDGE ); +} + +/* instantiate a combo control */ +static void +mswindows_combo_box_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, + Lisp_Object pointer_fg, Lisp_Object pointer_bg, + int dest_mask, Lisp_Object domain) +{ + struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); + HANDLE wnd; + Lisp_Object rest; + Lisp_Object data = Fplist_get (find_keyword_in_vector (instantiator, Q_properties), + Q_items, Qnil); + int len; + GET_LIST_LENGTH (data, len); + + /* Maybe ought to generalise this more but it may be very windows + specific. In windows the window height of a combo box is the + height when the combo box is open. Thus we need to set the height + before creating the window and then reset it to a single line + after the window is created so that redisplay does the right + thing. */ + widget_instantiate_1 (image_instance, instantiator, pointer_fg, + pointer_bg, dest_mask, domain, len + 1, 0, 0); + + mswindows_widget_instantiate (image_instance, instantiator, pointer_fg, + pointer_bg, dest_mask, domain, "COMBOBOX", + WS_BORDER | WS_TABSTOP | CBS_DROPDOWN + | CBS_AUTOHSCROLL + | CBS_HASSTRINGS | WS_VSCROLL, + WS_EX_CLIENTEDGE | WS_EX_CONTROLPARENT); + /* reset the height */ + widget_text_to_pixel_conversion (domain, + IMAGE_INSTANCE_WIDGET_FACE (ii), 1, 0, + &IMAGE_INSTANCE_SUBWINDOW_HEIGHT (ii), 0); + wnd = WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii); + /* add items to the combo box */ + SendMessage (wnd, CB_RESETCONTENT, 0, 0); + LIST_LOOP (rest, Fplist_get (IMAGE_INSTANCE_WIDGET_PROPS (ii), Q_items, Qnil)) + { + Extbyte* lparam; + GET_C_STRING_OS_DATA_ALLOCA (XCAR (rest), lparam); + if (SendMessage (wnd, CB_ADDSTRING, 0, (LPARAM)lparam) == CB_ERR) + signal_simple_error ("error adding combo entries", instantiator); + } +} + +/* get properties of a control */ +static Lisp_Object +mswindows_widget_property (Lisp_Object image_instance, Lisp_Object prop) +{ + struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); + HANDLE wnd = WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii); + /* get the text from a control */ + if (EQ (prop, Q_text)) + { + Extcount len = SendMessage (wnd, WM_GETTEXTLENGTH, 0, 0); + Extbyte* buf =alloca (len+1); + + SendMessage (wnd, WM_GETTEXT, (WPARAM)len+1, (LPARAM) buf); + return build_ext_string (buf, FORMAT_OS); + } + return Qunbound; +} + +/* get properties of a button */ +static Lisp_Object +mswindows_button_property (Lisp_Object image_instance, Lisp_Object prop) +{ + struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); + HANDLE wnd = WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii); + /* check the state of a button */ + if (EQ (prop, Q_selected)) + { + if (SendMessage (wnd, BM_GETSTATE, 0, 0) & BST_CHECKED) + return Qt; + else + return Qnil; + } + return Qunbound; +} + +/* get properties of a combo box */ +static Lisp_Object +mswindows_combo_box_property (Lisp_Object image_instance, Lisp_Object prop) +{ + struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); + HANDLE wnd = WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii); + /* get the text from a control */ + if (EQ (prop, Q_text)) + { + long item = SendMessage (wnd, CB_GETCURSEL, 0, 0); + Extcount len = SendMessage (wnd, CB_GETLBTEXTLEN, (WPARAM)item, 0); + Extbyte* buf = alloca (len+1); + SendMessage (wnd, CB_GETLBTEXT, (WPARAM)item, (LPARAM)buf); + return build_ext_string (buf, FORMAT_OS); + } + return Qunbound; +} + +/* set the properties of a control */ +static Lisp_Object +mswindows_widget_set_property (Lisp_Object image_instance, Lisp_Object prop, + Lisp_Object val) +{ + struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); + + if (EQ (prop, Q_text)) + { + Extbyte* lparam=0; + CHECK_STRING (val); + GET_C_STRING_OS_DATA_ALLOCA (val, lparam); + SendMessage (WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii), + WM_SETTEXT, 0, (LPARAM)lparam); + return Qt; + } + return Qunbound; +} + +/* set the properties of a progres guage */ +static Lisp_Object +mswindows_progress_gauge_set_property (Lisp_Object image_instance, Lisp_Object prop, + Lisp_Object val) +{ + struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); + + if (EQ (prop, Q_percent)) + { + CHECK_INT (val); + SendMessage (WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii), + PBM_SETPOS, (WPARAM)XINT (val), 0); + return Qt; + } + return Qunbound; +} + +LRESULT WINAPI +mswindows_control_wnd_proc (HWND hwnd, UINT message, + WPARAM wParam, LPARAM lParam) +{ + switch (message) + { + case WM_NOTIFY: + case WM_COMMAND: + case WM_CTLCOLORBTN: + case WM_CTLCOLORLISTBOX: + case WM_CTLCOLOREDIT: + case WM_CTLCOLORSTATIC: + case WM_CTLCOLORSCROLLBAR: + + return mswindows_wnd_proc (GetParent (hwnd), message, wParam, lParam); + default: + return DefWindowProc (hwnd, message, wParam, lParam); + } +} + +#endif /* HAVE_WIDGETS */ + + +/************************************************************************/ +/* initialization */ +/************************************************************************/ + +void +syms_of_glyphs_mswindows (void) +{ + defkeyword (&Q_resource_id, ":resource-id"); + defkeyword (&Q_resource_type, ":resource-type"); +} + +void +console_type_create_glyphs_mswindows (void) +{ + /* image methods */ + + CONSOLE_HAS_METHOD (mswindows, print_image_instance); + CONSOLE_HAS_METHOD (mswindows, finalize_image_instance); + CONSOLE_HAS_METHOD (mswindows, unmap_subwindow); + CONSOLE_HAS_METHOD (mswindows, map_subwindow); + CONSOLE_HAS_METHOD (mswindows, update_subwindow); + CONSOLE_HAS_METHOD (mswindows, image_instance_equal); + CONSOLE_HAS_METHOD (mswindows, image_instance_hash); + CONSOLE_HAS_METHOD (mswindows, init_image_instance_from_eimage); + CONSOLE_HAS_METHOD (mswindows, locate_pixmap_file); + CONSOLE_HAS_METHOD (mswindows, resize_subwindow); +} + +void +image_instantiator_format_create_glyphs_mswindows (void) +{ + IIFORMAT_VALID_CONSOLE (mswindows, nothing); + IIFORMAT_VALID_CONSOLE (mswindows, string); + IIFORMAT_VALID_CONSOLE (mswindows, layout); + IIFORMAT_VALID_CONSOLE (mswindows, formatted_string); + IIFORMAT_VALID_CONSOLE (mswindows, inherit); + /* image-instantiator types */ +#ifdef HAVE_XPM + INITIALIZE_DEVICE_IIFORMAT (mswindows, xpm); + IIFORMAT_HAS_DEVMETHOD (mswindows, xpm, instantiate); +#endif + INITIALIZE_DEVICE_IIFORMAT (mswindows, xbm); + IIFORMAT_HAS_DEVMETHOD (mswindows, xbm, instantiate); +#ifdef HAVE_XFACE + INITIALIZE_DEVICE_IIFORMAT (mswindows, xface); + IIFORMAT_HAS_DEVMETHOD (mswindows, xface, instantiate); +#endif +#ifdef HAVE_JPEG + IIFORMAT_VALID_CONSOLE (mswindows, jpeg); +#endif +#ifdef HAVE_TIFF + IIFORMAT_VALID_CONSOLE (mswindows, tiff); +#endif +#ifdef HAVE_PNG + IIFORMAT_VALID_CONSOLE (mswindows, png); +#endif +#ifdef HAVE_GIF + IIFORMAT_VALID_CONSOLE (mswindows, gif); +#endif +#ifdef HAVE_WIDGETS + /* button widget */ + INITIALIZE_DEVICE_IIFORMAT (mswindows, button); + IIFORMAT_HAS_DEVMETHOD (mswindows, button, property); + IIFORMAT_HAS_DEVMETHOD (mswindows, button, instantiate); + + INITIALIZE_DEVICE_IIFORMAT (mswindows, edit_field); + IIFORMAT_HAS_DEVMETHOD (mswindows, edit_field, instantiate); + + INITIALIZE_DEVICE_IIFORMAT (mswindows, subwindow); + IIFORMAT_HAS_DEVMETHOD (mswindows, subwindow, instantiate); + + INITIALIZE_DEVICE_IIFORMAT (mswindows, widget); + IIFORMAT_HAS_DEVMETHOD (mswindows, widget, property); + IIFORMAT_HAS_DEVMETHOD (mswindows, widget, set_property); + + /* label */ + INITIALIZE_DEVICE_IIFORMAT (mswindows, label); + IIFORMAT_HAS_DEVMETHOD (mswindows, label, instantiate); + + /* combo box */ + INITIALIZE_DEVICE_IIFORMAT (mswindows, combo_box); + IIFORMAT_HAS_DEVMETHOD (mswindows, combo_box, property); + IIFORMAT_HAS_DEVMETHOD (mswindows, combo_box, instantiate); + + /* scrollbar */ + INITIALIZE_DEVICE_IIFORMAT (mswindows, scrollbar); + IIFORMAT_HAS_DEVMETHOD (mswindows, scrollbar, instantiate); + + /* progress gauge */ + INITIALIZE_DEVICE_IIFORMAT (mswindows, progress_gauge); + IIFORMAT_HAS_DEVMETHOD (mswindows, progress_gauge, set_property); + IIFORMAT_HAS_DEVMETHOD (mswindows, progress_gauge, instantiate); + + /* tree view widget */ + INITIALIZE_DEVICE_IIFORMAT (mswindows, tree_view); + /* IIFORMAT_HAS_DEVMETHOD (mswindows, progress, set_property);*/ + IIFORMAT_HAS_DEVMETHOD (mswindows, tree_view, instantiate); + + /* tab control widget */ + INITIALIZE_DEVICE_IIFORMAT (mswindows, tab_control); + IIFORMAT_HAS_DEVMETHOD (mswindows, tab_control, instantiate); + IIFORMAT_HAS_DEVMETHOD (mswindows, tab_control, set_property); +#endif + /* windows bitmap format */ + INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (bmp, "bmp"); + IIFORMAT_HAS_METHOD (bmp, validate); + IIFORMAT_HAS_METHOD (bmp, normalize); + IIFORMAT_HAS_METHOD (bmp, possible_dest_types); + IIFORMAT_HAS_METHOD (bmp, instantiate); + + IIFORMAT_VALID_KEYWORD (bmp, Q_data, check_valid_string); + IIFORMAT_VALID_KEYWORD (bmp, Q_file, check_valid_string); + IIFORMAT_VALID_CONSOLE (mswindows, bmp); + + /* mswindows resources */ + INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (mswindows_resource, + "mswindows-resource"); + + IIFORMAT_HAS_METHOD (mswindows_resource, validate); + IIFORMAT_HAS_METHOD (mswindows_resource, normalize); + IIFORMAT_HAS_METHOD (mswindows_resource, possible_dest_types); + IIFORMAT_HAS_METHOD (mswindows_resource, instantiate); + + IIFORMAT_VALID_KEYWORD (mswindows_resource, Q_resource_type, + check_valid_resource_symbol); + IIFORMAT_VALID_KEYWORD (mswindows_resource, Q_resource_id, check_valid_resource_id); + IIFORMAT_VALID_KEYWORD (mswindows_resource, Q_file, check_valid_string); + IIFORMAT_VALID_CONSOLE (mswindows, mswindows_resource); +} + +void +vars_of_glyphs_mswindows (void) +{ + DEFVAR_LISP ("mswindows-bitmap-file-path", &Vmswindows_bitmap_file_path /* +A list of the directories in which mswindows bitmap files may be found. +This is used by the `make-image-instance' function. +*/ ); + Vmswindows_bitmap_file_path = Qnil; +} + +void +complex_vars_of_glyphs_mswindows (void) +{ +}