442
+ − 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
531
+ − 65 typedef NET_API_STATUS (NET_API_FUNCTION *pfNetUserEnum_t)
+ − 66 (
+ − 67 IN LPCWSTR servername OPTIONAL,
+ − 68 IN DWORD level,
+ − 69 IN DWORD filter,
+ − 70 OUT LPBYTE *bufptr,
+ − 71 IN DWORD prefmaxlen,
+ − 72 OUT LPDWORD entriesread,
+ − 73 OUT LPDWORD totalentries,
+ − 74 IN OUT LPDWORD resume_handle OPTIONAL
+ − 75 );
+ − 76 pfNetUserEnum_t xNetUserEnum;
+ − 77
+ − 78 typedef NET_API_STATUS (NET_API_FUNCTION *pfNetApiBufferFree_t)
+ − 79 (
+ − 80 IN LPVOID Buffer
+ − 81 );
+ − 82 pfNetApiBufferFree_t xNetApiBufferFree;
+ − 83
442
+ − 84 Lisp_Object
+ − 85 tstr_to_local_file_format (Extbyte *pathout)
+ − 86 {
578
+ − 87 Bufbyte *ttlff;
442
+ − 88 Lisp_Object in;
+ − 89
+ − 90 EXTERNAL_TO_C_STRING (pathout, ttlff, Qmswindows_tstr);
+ − 91 WIN32_TO_LOCAL_FILE_FORMAT (ttlff, in);
+ − 92
+ − 93 return in;
+ − 94 }
+ − 95
+ − 96 static void
+ − 97 init_potentially_nonexistent_functions (void)
+ − 98 {
+ − 99 HMODULE h_kernel = GetModuleHandle ("kernel32");
+ − 100 HMODULE h_user = GetModuleHandle ("user32");
+ − 101 HMODULE h_gdi = GetModuleHandle ("gdi32");
+ − 102 HMODULE h_shell = GetModuleHandle ("shell32");
531
+ − 103 /* the following does not seem to get mapped in automatically */
+ − 104 HMODULE h_netapi = LoadLibrary ("netapi32.dll");
442
+ − 105
+ − 106 if (h_kernel)
+ − 107 {
+ − 108 xSwitchToThread =
+ − 109 (pfSwitchToThread_t) GetProcAddress (h_kernel, "SwitchToThread");
+ − 110 }
+ − 111
+ − 112 if (h_user)
+ − 113 {
+ − 114 xGetKeyboardLayout =
+ − 115 (pfGetKeyboardLayout_t) GetProcAddress (h_user, "GetKeyboardLayout");
+ − 116 xSetMenuDefaultItem =
+ − 117 (pfSetMenuDefaultItem_t) GetProcAddress (h_user, "SetMenuDefaultItem");
+ − 118 xInsertMenuItemA =
+ − 119 (pfInsertMenuItemA_t) GetProcAddress (h_user, "InsertMenuItemA");
+ − 120 xInsertMenuItemW =
+ − 121 (pfInsertMenuItemW_t) GetProcAddress (h_user, "InsertMenuItemW");
+ − 122 xLoadImageA =
+ − 123 (pfLoadImageA_t) GetProcAddress (h_user, "LoadImageA");
+ − 124 xLoadImageW =
+ − 125 (pfLoadImageW_t) GetProcAddress (h_user, "LoadImageW");
+ − 126 xRegisterClassExA =
+ − 127 (pfRegisterClassExA_t) GetProcAddress (h_user, "RegisterClassExA");
+ − 128 xRegisterClassExW =
+ − 129 (pfRegisterClassExW_t) GetProcAddress (h_user, "RegisterClassExW");
+ − 130 }
+ − 131
+ − 132 if (h_gdi)
+ − 133 {
+ − 134 xEnumFontFamiliesExA =
+ − 135 (pfEnumFontFamiliesExA_t) GetProcAddress (h_gdi, "EnumFontFamiliesExA");
+ − 136 xEnumFontFamiliesExW =
+ − 137 (pfEnumFontFamiliesExW_t) GetProcAddress (h_gdi, "EnumFontFamiliesExW");
+ − 138 }
+ − 139
+ − 140 if (h_shell)
+ − 141 {
+ − 142 xSHGetFileInfoA =
+ − 143 (pfSHGetFileInfoA_t) GetProcAddress (h_shell, "SHGetFileInfoA");
+ − 144 xSHGetFileInfoW =
+ − 145 (pfSHGetFileInfoW_t) GetProcAddress (h_shell, "SHGetFileInfoW");
+ − 146 }
531
+ − 147
+ − 148 if (h_netapi)
+ − 149 {
+ − 150 xNetUserEnum =
+ − 151 (pfNetUserEnum_t) GetProcAddress (h_netapi, "NetUserEnum");
+ − 152 xNetApiBufferFree =
+ − 153 (pfNetApiBufferFree_t) GetProcAddress (h_netapi, "NetApiBufferFree");
+ − 154 }
442
+ − 155 }
+ − 156
+ − 157 DEFUN ("mswindows-shell-execute", Fmswindows_shell_execute, 2, 4, 0, /*
+ − 158 Get Windows to perform OPERATION on DOCUMENT.
+ − 159 This is a wrapper around the ShellExecute system function, which
+ − 160 invokes the application registered to handle OPERATION for DOCUMENT.
+ − 161 OPERATION is typically \"open\", \"print\" or \"explore\" (but can be
+ − 162 nil for the default action), and DOCUMENT is typically the name of a
+ − 163 document file or URL, but can also be a program executable to run or
+ − 164 a directory to open in the Windows Explorer.
+ − 165
+ − 166 If DOCUMENT is a program executable, PARAMETERS can be a string
+ − 167 containing command line parameters, but otherwise should be nil.
+ − 168
+ − 169 SHOW-FLAG can be used to control whether the invoked application is hidden
+ − 170 or minimized. If SHOW-FLAG is nil, the application is displayed normally,
+ − 171 otherwise it is an integer representing a ShowWindow flag:
+ − 172
+ − 173 0 - start hidden
+ − 174 1 - start normally
+ − 175 3 - start maximized
+ − 176 6 - start minimized
+ − 177 */
+ − 178 (operation, document, parameters, show_flag))
+ − 179 {
+ − 180 /* Encode filename and current directory. */
+ − 181 Lisp_Object current_dir = Ffile_name_directory (document);
+ − 182 char* path = NULL;
+ − 183 char* doc = NULL;
+ − 184 Extbyte* f=0;
+ − 185 int ret;
+ − 186 struct gcpro gcpro1, gcpro2;
+ − 187
+ − 188 CHECK_STRING (document);
+ − 189
+ − 190 if (NILP (current_dir))
+ − 191 current_dir = current_buffer->directory;
+ − 192
+ − 193 GCPRO2 (current_dir, document);
+ − 194
+ − 195 /* Use mule and cygwin-safe APIs top get at file data. */
+ − 196 if (STRINGP (current_dir))
+ − 197 {
+ − 198 TO_EXTERNAL_FORMAT (LISP_STRING, current_dir,
+ − 199 C_STRING_ALLOCA, f,
+ − 200 Qfile_name);
+ − 201 #ifdef CYGWIN
+ − 202 CYGWIN_WIN32_PATH (f, path);
+ − 203 #else
+ − 204 path = f;
+ − 205 #endif
+ − 206 }
+ − 207
+ − 208 if (STRINGP (document))
+ − 209 {
+ − 210 TO_EXTERNAL_FORMAT (LISP_STRING, document,
+ − 211 C_STRING_ALLOCA, f,
+ − 212 Qfile_name);
+ − 213 #ifdef CYGWIN
+ − 214 CYGWIN_WIN32_PATH (f, doc);
+ − 215 #else
+ − 216 doc = f;
+ − 217 #endif
+ − 218 }
+ − 219
+ − 220 UNGCPRO;
+ − 221
+ − 222 ret = (int) ShellExecute (NULL,
+ − 223 (STRINGP (operation) ?
+ − 224 XSTRING_DATA (operation) : NULL),
+ − 225 doc,
+ − 226 (STRINGP (parameters) ?
+ − 227 XSTRING_DATA (parameters) : NULL),
+ − 228 path,
+ − 229 (INTP (show_flag) ?
+ − 230 XINT (show_flag) : SW_SHOWDEFAULT));
+ − 231
+ − 232 if (ret > 32)
+ − 233 return Qt;
+ − 234
+ − 235 if (ret == ERROR_FILE_NOT_FOUND)
563
+ − 236 signal_error (Qfile_error, "file not found", document);
442
+ − 237 else if (ret == ERROR_PATH_NOT_FOUND)
563
+ − 238 signal_error (Qfile_error, "path not found", current_dir);
442
+ − 239 else if (ret == ERROR_BAD_FORMAT)
563
+ − 240 signal_error (Qfile_error, "bad executable format", document);
442
+ − 241 else
563
+ − 242 signal_error (Qinternal_error, "internal error", Qunbound);
442
+ − 243
+ − 244 return Qnil;
+ − 245 }
+ − 246
+ − 247 void
+ − 248 syms_of_win32 (void)
+ − 249 {
+ − 250 DEFSUBR (Fmswindows_shell_execute);
+ − 251 }
+ − 252
+ − 253 void
+ − 254 init_win32 (void)
+ − 255 {
+ − 256 init_potentially_nonexistent_functions ();
+ − 257 }