Initial revision
[chise/xemacs-chise.git.1] / src / win32.c
1 /* Utility routines for XEmacs on Windows 9x, NT and Cygwin.
2    Copyright (C) 2000 Ben Wing.
3
4 This file is part of XEmacs.
5
6 XEmacs is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
9 later version.
10
11 XEmacs is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with XEmacs; see the file COPYING.  If not, write to the Free
18 Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19 02111-1307, USA. */
20
21 #include <config.h>
22 #include "lisp.h"
23
24 #include "buffer.h"
25 #include "syswindows.h"
26
27 typedef BOOL (WINAPI *pfSwitchToThread_t) (VOID);
28 pfSwitchToThread_t xSwitchToThread;
29
30 typedef HKL (WINAPI *pfGetKeyboardLayout_t) (DWORD);
31 pfGetKeyboardLayout_t xGetKeyboardLayout;
32 typedef BOOL (WINAPI *pfSetMenuDefaultItem_t) (HMENU, UINT, UINT);
33 pfSetMenuDefaultItem_t xSetMenuDefaultItem;
34 typedef BOOL (WINAPI *pfInsertMenuItemA_t) 
35      (HMENU, UINT, BOOL, LPCMENUITEMINFOA);
36 pfInsertMenuItemA_t xInsertMenuItemA;
37 typedef BOOL (WINAPI *pfInsertMenuItemW_t) 
38      (HMENU, UINT, BOOL, LPCMENUITEMINFOW);
39 pfInsertMenuItemW_t xInsertMenuItemW;
40 typedef HANDLE (WINAPI *pfLoadImageA_t) 
41      (HINSTANCE, LPCSTR, UINT, int, int, UINT);
42 pfLoadImageA_t xLoadImageA;
43 typedef HANDLE (WINAPI *pfLoadImageW_t)
44      (HINSTANCE, LPCWSTR, UINT, int, int, UINT);
45 pfLoadImageW_t xLoadImageW;
46 typedef ATOM (WINAPI *pfRegisterClassExA_t) (CONST WNDCLASSEXA *);
47 pfRegisterClassExA_t xRegisterClassExA;
48 typedef ATOM (WINAPI *pfRegisterClassExW_t) (CONST WNDCLASSEXW *);
49 pfRegisterClassExW_t xRegisterClassExW;
50
51 typedef int (WINAPI *pfEnumFontFamiliesExA_t) 
52      (HDC, LPLOGFONTA, FONTENUMPROCA, LPARAM, DWORD);
53 pfEnumFontFamiliesExA_t xEnumFontFamiliesExA;
54 typedef int (WINAPI *pfEnumFontFamiliesExW_t) 
55      (HDC, LPLOGFONTW, FONTENUMPROCW, LPARAM, DWORD);
56 pfEnumFontFamiliesExW_t xEnumFontFamiliesExW;
57
58 typedef DWORD (WINAPI *pfSHGetFileInfoA_t) 
59      (LPCSTR, DWORD, SHFILEINFOA FAR *, UINT, UINT);
60 pfSHGetFileInfoA_t xSHGetFileInfoA;
61 typedef DWORD (WINAPI *pfSHGetFileInfoW_t) 
62      (LPCWSTR, DWORD, SHFILEINFOW FAR *, UINT, UINT);
63 pfSHGetFileInfoW_t xSHGetFileInfoW;
64
65 Lisp_Object
66 tstr_to_local_file_format (Extbyte *pathout)
67 {
68   Bufbyte *ttlff;
69   Lisp_Object in;
70
71   EXTERNAL_TO_C_STRING (pathout, ttlff, Qmswindows_tstr);
72   WIN32_TO_LOCAL_FILE_FORMAT (ttlff, in);
73
74   return in;
75 }
76
77 static void
78 init_potentially_nonexistent_functions (void)
79 {
80   HMODULE h_kernel = GetModuleHandle ("kernel32");
81   HMODULE h_user = GetModuleHandle ("user32");
82   HMODULE h_gdi = GetModuleHandle ("gdi32");
83   HMODULE h_shell = GetModuleHandle ("shell32");
84
85   if (h_kernel)
86     {
87       xSwitchToThread =
88         (pfSwitchToThread_t) GetProcAddress (h_kernel, "SwitchToThread");
89     }
90
91   if (h_user)
92     {
93       xGetKeyboardLayout =
94         (pfGetKeyboardLayout_t) GetProcAddress (h_user, "GetKeyboardLayout");
95       xSetMenuDefaultItem =
96         (pfSetMenuDefaultItem_t) GetProcAddress (h_user, "SetMenuDefaultItem");
97       xInsertMenuItemA =
98         (pfInsertMenuItemA_t) GetProcAddress (h_user, "InsertMenuItemA");
99       xInsertMenuItemW =
100         (pfInsertMenuItemW_t) GetProcAddress (h_user, "InsertMenuItemW");
101       xLoadImageA =
102         (pfLoadImageA_t) GetProcAddress (h_user, "LoadImageA");
103       xLoadImageW =
104         (pfLoadImageW_t) GetProcAddress (h_user, "LoadImageW");
105       xRegisterClassExA =
106         (pfRegisterClassExA_t) GetProcAddress (h_user, "RegisterClassExA");
107       xRegisterClassExW =
108         (pfRegisterClassExW_t) GetProcAddress (h_user, "RegisterClassExW");
109     }
110
111   if (h_gdi)
112     {
113       xEnumFontFamiliesExA =
114         (pfEnumFontFamiliesExA_t) GetProcAddress (h_gdi, "EnumFontFamiliesExA");
115       xEnumFontFamiliesExW =
116         (pfEnumFontFamiliesExW_t) GetProcAddress (h_gdi, "EnumFontFamiliesExW");
117     }
118
119   if (h_shell)
120     {
121       xSHGetFileInfoA =
122         (pfSHGetFileInfoA_t) GetProcAddress (h_shell, "SHGetFileInfoA");
123       xSHGetFileInfoW =
124         (pfSHGetFileInfoW_t) GetProcAddress (h_shell, "SHGetFileInfoW");
125     }
126 }
127
128 DEFUN ("mswindows-shell-execute", Fmswindows_shell_execute, 2, 4, 0, /*
129 Get Windows to perform OPERATION on DOCUMENT.
130 This is a wrapper around the ShellExecute system function, which
131 invokes the application registered to handle OPERATION for DOCUMENT.
132 OPERATION is typically \"open\", \"print\" or \"explore\" (but can be
133 nil for the default action), and DOCUMENT is typically the name of a
134 document file or URL, but can also be a program executable to run or
135 a directory to open in the Windows Explorer.
136
137 If DOCUMENT is a program executable, PARAMETERS can be a string
138 containing command line parameters, but otherwise should be nil.
139
140 SHOW-FLAG can be used to control whether the invoked application is hidden
141 or minimized.  If SHOW-FLAG is nil, the application is displayed normally,
142 otherwise it is an integer representing a ShowWindow flag:
143
144   0 - start hidden
145   1 - start normally
146   3 - start maximized
147   6 - start minimized
148 */
149        (operation, document, parameters, show_flag))
150 {
151   /* Encode filename and current directory.  */
152   Lisp_Object current_dir = Ffile_name_directory (document);
153   char* path = NULL;
154   char* doc = NULL;
155   Extbyte* f=0;
156   int ret;
157   struct gcpro gcpro1, gcpro2;
158
159   CHECK_STRING (document);
160
161   if (NILP (current_dir))
162     current_dir = current_buffer->directory;
163
164   GCPRO2 (current_dir, document);
165
166   /* Use mule and cygwin-safe APIs top get at file data. */
167   if (STRINGP (current_dir))
168     {
169       TO_EXTERNAL_FORMAT (LISP_STRING, current_dir,
170                           C_STRING_ALLOCA, f,
171                           Qfile_name);
172 #ifdef CYGWIN
173       CYGWIN_WIN32_PATH (f, path);
174 #else
175       path = f;
176 #endif
177     }
178
179   if (STRINGP (document))
180     {
181       TO_EXTERNAL_FORMAT (LISP_STRING, document,
182                           C_STRING_ALLOCA, f,
183                           Qfile_name);
184 #ifdef CYGWIN
185       CYGWIN_WIN32_PATH (f, doc);
186 #else
187       doc = f;
188 #endif
189     }
190
191   UNGCPRO;
192
193   ret = (int) ShellExecute (NULL,
194                             (STRINGP (operation) ?
195                              XSTRING_DATA (operation) : NULL),
196                             doc, 
197                             (STRINGP (parameters) ?
198                              XSTRING_DATA (parameters) : NULL),
199                             path,
200                             (INTP (show_flag) ?
201                              XINT (show_flag) : SW_SHOWDEFAULT));
202
203   if (ret > 32)
204     return Qt;
205   
206   if (ret == ERROR_FILE_NOT_FOUND)
207     signal_simple_error ("file not found", document);
208   else if (ret == ERROR_PATH_NOT_FOUND)
209     signal_simple_error ("path not found", current_dir);
210   else if (ret == ERROR_BAD_FORMAT)
211     signal_simple_error ("bad executable format", document);
212   else
213     error ("internal error");
214
215   return Qnil;
216 }
217
218 void
219 syms_of_win32 (void)
220 {
221   DEFSUBR (Fmswindows_shell_execute);
222 }
223
224 void
225 init_win32 (void)
226 {
227   init_potentially_nonexistent_functions ();
228 }