diff src/glyphs-msw.c @ 286:57709be46d1b r21-0b41

Import from CVS: tag r21-0b41
author cvs
date Mon, 13 Aug 2007 10:35:03 +0200
parents 558f606b08ae
children e11d67e05968
line wrap: on
line diff
--- a/src/glyphs-msw.c	Mon Aug 13 10:34:15 2007 +0200
+++ b/src/glyphs-msw.c	Mon Aug 13 10:35:03 2007 +0200
@@ -26,6 +26,8 @@
 #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"
@@ -47,8 +49,8 @@
 Lisp_Object Vmswindows_bitmap_file_path;
 static	COLORREF transparent_color = RGB (1,1,1);
 
-DEFINE_IMAGE_INSTANTIATOR_FORMAT (cursor);
-Lisp_Object Qcursor;
+DEFINE_IMAGE_INSTANTIATOR_FORMAT (resource);
+Lisp_Object Qresource;
 Lisp_Object Q_resource_type, Q_resource_id;
 
 static void
@@ -160,9 +162,9 @@
       
       /* build up an RGBQUAD colortable */
       for (i = 0; i < qtable->num_active_colors; i++) {
-	colortbl[i].rgbRed = qtable->rm[i];
-	colortbl[i].rgbGreen = qtable->gm[i];
-	colortbl[i].rgbBlue = qtable->bm[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;
       }
 
@@ -448,20 +450,21 @@
     CreateIconIndirect (&x_icon);
 }
 
-int
-mswindows_resize_dibitmap_instance (struct Lisp_Image_Instance* ii,
-				    struct frame* f,
-				    int newx, int newy)
+HBITMAP
+mswindows_create_resized_bitmap (struct Lisp_Image_Instance* ii,
+				 struct frame* f,
+				 int newx, int newy)
 {
-  HBITMAP newbmp, newmask=NULL;
+  HBITMAP newbmp;
+  HGDIOBJ old1, old2;
   HDC hcdc = FRAME_MSWINDOWS_CDC (f);
   HDC hdcDst = CreateCompatibleDC (hcdc);  
   
-  SelectObject (hcdc, IMAGE_INSTANCE_MSWINDOWS_BITMAP (ii)); 
+  old1 = SelectObject (hcdc, IMAGE_INSTANCE_MSWINDOWS_BITMAP (ii)); 
   
   newbmp = CreateCompatibleBitmap (hcdc, newx, newy);
 
-  DeleteObject (SelectObject (hdcDst, newbmp) );
+  old2 = SelectObject (hdcDst, newbmp);
   
   if (!StretchBlt (hdcDst, 0, 0, newx, newy,
 		   hcdc, 0, 0, 
@@ -469,14 +472,31 @@
 		   IMAGE_INSTANCE_PIXMAP_HEIGHT (ii), 
 		   SRCCOPY))
     {
-      return FALSE;
+      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))
     {
-      SelectObject (hcdc, 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);
-      SelectObject (hdcDst, newmask);
+      old2 = SelectObject (hdcDst, newmask);
 
       if (!StretchBlt(hdcDst, 0, 0, newx, newy,
 		      hcdc, 0, 0, 
@@ -484,12 +504,30 @@
 		      IMAGE_INSTANCE_PIXMAP_HEIGHT (ii), 
 		      SRCCOPY))
 	{
-	  return FALSE;
+	  return NULL;
 	}
+      
+      SelectObject (hdcDst, old2);
+      SelectObject (hcdc, old1);
+
+      DeleteDC (hdcDst);
+
+      return newmask;
     }
 
-  SelectObject (hdcDst, 0);
-  SelectObject (hcdc, 0);
+  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));
@@ -501,8 +539,6 @@
   IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = newx;
   IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) = newy;
 
-  DeleteDC (hdcDst);
-
   return TRUE;
 }
 
@@ -839,11 +875,11 @@
 
 
 /**********************************************************************
- *                               CURSORS                              *
+ *                             RESOURCES                              *
  **********************************************************************/
 
 static void
-cursor_validate (Lisp_Object instantiator)
+resource_validate (Lisp_Object instantiator)
 {
   if ((NILP (find_keyword_in_vector (instantiator, Q_file)) 
        &&
@@ -855,7 +891,7 @@
 }
 
 static Lisp_Object
-cursor_normalize (Lisp_Object inst, Lisp_Object console_type)
+resource_normalize (Lisp_Object inst, Lisp_Object console_type)
 {
   /* This function can call lisp */
   Lisp_Object file = Qnil;
@@ -883,14 +919,14 @@
   }
 
   {
-    Lisp_Object result = alist_to_tagged_vector (Qcursor, alist);
+    Lisp_Object result = alist_to_tagged_vector (Qresource, alist);
     free_alist (alist);
     RETURN_UNGCPRO (result);
   }
 }
 
 static int
-cursor_possible_dest_types (void)
+resource_possible_dest_types (void)
 {
   return IMAGE_POINTER_MASK | IMAGE_COLOR_PIXMAP_MASK;
 }
@@ -912,7 +948,7 @@
 #define LR_SHARED           0x8000
 #endif
 
-static CONST resource_t resource_table[] = 
+static CONST resource_t bitmap_table[] = 
 {
   /* bitmaps */
   { "close", OBM_CLOSE },
@@ -941,6 +977,11 @@
   { "check", OBM_CHECK },
   { "cehckboxes", OBM_CHECKBOXES },
   { "btncorners" , OBM_BTNCORNERS },
+  {0}
+};
+
+static CONST resource_t cursor_table[] = 
+{
   /* cursors */
   { "normal", OCR_NORMAL },
   { "ibeam", OCR_IBEAM },
@@ -955,6 +996,11 @@
   { "sizeall", OCR_SIZEALL },
   /* { "icour", OCR_ICOCUR }, */
   { "no", OCR_NO },
+  { 0 }
+};
+
+static CONST resource_t icon_table[] = 
+{
   /* icons */
   { "sample", OIC_SAMPLE },
   { "hand", OIC_HAND },
@@ -965,9 +1011,11 @@
   {0}
 };
 
-static int cursor_name_to_resource (Lisp_Object name)
+static int resource_name_to_resource (Lisp_Object name, int type)
 {
-  CONST resource_t* res = resource_table;
+  CONST resource_t* res = (type == IMAGE_CURSOR ? cursor_table 
+			   : type == IMAGE_ICON ? icon_table 
+			   : bitmap_table);
 
   if (INTP (name))
     {
@@ -985,8 +1033,21 @@
   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
-cursor_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
+resource_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
 		    Lisp_Object pointer_fg, Lisp_Object pointer_bg,
 		    int dest_mask, Lisp_Object domain)
 {
@@ -994,7 +1055,10 @@
   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);
@@ -1003,27 +1067,12 @@
   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);
 
-  assert (!NILP (resource_type) && !NILP (resource_id));
-
-  /* check the resource type */
-  if (!SYMBOLP (resource_type))
-    {
-      signal_simple_error ("invalid resource type", resource_type);
-    }
-  if (!strcmp ((char *) string_data (XSYMBOL (resource_type)->name),
-	       "bitmap"))
-    type = IMAGE_BITMAP;
-  else if (!strcmp ((char *) string_data (XSYMBOL (resource_type)->name),
-	       "cursor"))
-    type = IMAGE_CURSOR;
-  else if (!strcmp ((char *) string_data (XSYMBOL (resource_type)->name),
-	       "icon"))
-    type = IMAGE_ICON;
-  else
-    signal_simple_error ("invalid resource type", resource_type);
+  type = resource_symbol_to_type (resource_type);
 
   if (dest_mask & IMAGE_POINTER_MASK && type == IMAGE_CURSOR)
     iitype = IMAGE_POINTER;
@@ -1033,13 +1082,35 @@
     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))
-    resid = (LPCTSTR)XSTRING_DATA (file);
-  else if (!(resid = MAKEINTRESOURCE(cursor_name_to_resource (resource_id))))
-    signal_simple_error ("invalid resource id", resource_id);
+    {
+#ifdef __CYGWIN32__
+      CYGWIN_WIN32_PATH (XSTRING_DATA (file), fname);
+#else
+      /* #### FIXME someone who knows ... */
+      fname = XSTRING_DATA (file);
+#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)
+	    resid = XSTRING_DATA (resource_id);
+	}
+    }
+  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 (NULL, resid, type, 0, 0,
+  if (!(himage = LoadImage (hinst, resid, type, 0, 0,
 			    LR_CREATEDIBSECTION | LR_DEFAULTSIZE | 
 			    LR_SHARED |      
 			    (!NILP (file) ? LR_LOADFROMFILE : 0))))
@@ -1047,25 +1118,56 @@
       signal_simple_error ("cannot load image", instantiator);
     }
 
+  if (hinst)
+    FreeLibrary (hinst);
+
   mswindows_initialize_dibitmap_image_instance (ii, iitype);
 
   IMAGE_INSTANCE_PIXMAP_FILENAME (ii) = file;
-  IMAGE_INSTANCE_MSWINDOWS_BITMAP (ii) = (type==IMAGE_BITMAP ? himage : NULL);
-  IMAGE_INSTANCE_MSWINDOWS_MASK (ii) = NULL;
-  IMAGE_INSTANCE_MSWINDOWS_ICON (ii) = (type!=IMAGE_BITMAP ? himage : NULL);
   IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = 
-    (type == IMAGE_CURSOR ? SM_CXCURSOR : SM_CXICON);
+    GetSystemMetrics (type == IMAGE_CURSOR ? SM_CXCURSOR : SM_CXICON);
   IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) = 
-    (type == IMAGE_CURSOR ? SM_CYCURSOR : SM_CYICON);
-  IMAGE_INSTANCE_PIXMAP_DEPTH (ii) = 0;
-  XSETINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii), 0);
-  XSETINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii), 0);
+    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);
+    }
 }
 
-void
-check_valid_symbol (Lisp_Object data)
+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
@@ -1230,23 +1332,24 @@
   IIFORMAT_VALID_KEYWORD (bmp, Q_data, check_valid_string);
   IIFORMAT_VALID_KEYWORD (bmp, Q_file, check_valid_string);
 
-  INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (cursor, "cursor");
+  INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (resource, "resource");
 
-  IIFORMAT_HAS_METHOD (cursor, validate);
-  IIFORMAT_HAS_METHOD (cursor, normalize);
-  IIFORMAT_HAS_METHOD (cursor, possible_dest_types);
-  IIFORMAT_HAS_METHOD (cursor, instantiate);
+  IIFORMAT_HAS_METHOD (resource, validate);
+  IIFORMAT_HAS_METHOD (resource, normalize);
+  IIFORMAT_HAS_METHOD (resource, possible_dest_types);
+  IIFORMAT_HAS_METHOD (resource, instantiate);
 
-  IIFORMAT_VALID_KEYWORD (cursor, Q_resource_type, check_valid_symbol);
-  IIFORMAT_VALID_KEYWORD (cursor, Q_resource_id, check_valid_string_or_int);
-  IIFORMAT_VALID_KEYWORD (cursor, Q_file, check_valid_string);
+  IIFORMAT_VALID_KEYWORD (resource, Q_resource_type, 
+			  check_valid_resource_symbol);
+  IIFORMAT_VALID_KEYWORD (resource, Q_resource_id, check_valid_resource_id);
+  IIFORMAT_VALID_KEYWORD (resource, Q_file, check_valid_string);
 }
 
 void
 vars_of_glyphs_mswindows (void)
 {
   Fprovide (Qbmp);
-  Fprovide (Qcursor);
+  Fprovide (Qresource);
   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.