diff --git a/src/w32notify.c b/src/w32notify.c index ab6cd12..71ee1a3 100644 --- a/src/w32notify.c +++ b/src/w32notify.c @@ -92,12 +92,216 @@ along with GNU Emacs. If not, see . */ #include "lisp.h" #include "w32term.h" /* for enter_crit/leave_crit and WM_EMACS_FILENOTIFY */ #include "w32common.h" /* for OS version data */ -#include "w32.h" /* for w32_strerror */ #include "coding.h" #include "keyboard.h" #include "frame.h" /* needed by termhooks.h */ #include "termhooks.h" /* for FILE_NOTIFY_EVENT */ +/* Experimental code for Cygwin-w32 build */ + +extern char * w32_strerror (int error_no); + +int (WINAPI *pMultiByteToWideChar)(UINT,DWORD,LPCSTR,int,LPWSTR,int); +int (WINAPI *pWideCharToMultiByte)(UINT,DWORD,LPCWSTR,int,LPSTR,int,LPCSTR,LPBOOL); + +#define MAXPATHLEN MAX_PATH +#define MAX_UTF8_PATH (MAXPATHLEN * 4) + +static int file_name_codepage; + +static int +codepage_for_filenames (CPINFO *cp_info) +{ + /* A simple cache to avoid calling GetCPInfo every time we need to + encode/decode a file name. The file-name encoding is not + supposed to be changed too frequently, if ever. */ + static Lisp_Object last_file_name_encoding; + static CPINFO cp; + Lisp_Object current_encoding; + + current_encoding = Vfile_name_coding_system; + if (NILP (current_encoding)) + current_encoding = Vdefault_file_name_coding_system; + + if (!EQ (last_file_name_encoding, current_encoding)) + { + /* Default to the current ANSI codepage. */ + file_name_codepage = w32_ansi_code_page; + + if (NILP (current_encoding)) + { + char *cpname = SDATA (SYMBOL_NAME (current_encoding)); + char *cp = NULL, *end; + int cpnum; + + if (strncmp (cpname, "cp", 2) == 0) + cp = cpname + 2; + else if (strncmp (cpname, "windows-", 8) == 0) + cp = cpname + 8; + + if (cp) + { + end = cp; + cpnum = strtol (cp, &end, 10); + if (cpnum && *end == '\0' && end - cp >= 2) + file_name_codepage = cpnum; + } + } + + if (!file_name_codepage) + file_name_codepage = CP_ACP; /* CP_ACP = 0, but let's not assume that */ + + if (!GetCPInfo (file_name_codepage, &cp)) + { + file_name_codepage = CP_ACP; + if (!GetCPInfo (file_name_codepage, &cp)) + emacs_abort (); + } + } + if (cp_info) + *cp_info = cp; + + return file_name_codepage; +} + +int +filename_to_utf16 (const char *fn_in, wchar_t *fn_out) +{ + int result = pMultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS, fn_in, -1, + fn_out, MAX_PATH); + + if (!result) + { + DWORD err = GetLastError (); + + switch (err) + { + case ERROR_INVALID_FLAGS: + case ERROR_INVALID_PARAMETER: + errno = EINVAL; + break; + case ERROR_INSUFFICIENT_BUFFER: + case ERROR_NO_UNICODE_TRANSLATION: + default: + errno = ENOENT; + break; + } + return -1; + } + return 0; +} + +int +filename_from_utf16 (const wchar_t *fn_in, char *fn_out) +{ + int result = pWideCharToMultiByte (CP_UTF8, 0, fn_in, -1, + fn_out, MAX_UTF8_PATH, NULL, NULL); + + if (!result) + { + DWORD err = GetLastError (); + + switch (err) + { + case ERROR_INVALID_FLAGS: + case ERROR_INVALID_PARAMETER: + errno = EINVAL; + break; + case ERROR_INSUFFICIENT_BUFFER: + case ERROR_NO_UNICODE_TRANSLATION: + default: + errno = ENOENT; + break; + } + return -1; + } + return 0; +} + +int +filename_to_ansi (const char *fn_in, char *fn_out) +{ + wchar_t fn_utf16[MAX_PATH]; + + if (filename_to_utf16 (fn_in, fn_utf16) == 0) + { + int result; + int codepage = codepage_for_filenames (NULL); + + result = pWideCharToMultiByte (codepage, 0, fn_utf16, -1, + fn_out, MAX_PATH, NULL, NULL); + if (!result) + { + DWORD err = GetLastError (); + + switch (err) + { + case ERROR_INVALID_FLAGS: + case ERROR_INVALID_PARAMETER: + errno = EINVAL; + break; + case ERROR_INSUFFICIENT_BUFFER: + case ERROR_NO_UNICODE_TRANSLATION: + default: + errno = ENOENT; + break; + } + return -1; + } + return 0; + } + return -1; +} + +int +filename_from_ansi (const char *fn_in, char *fn_out) +{ + wchar_t fn_utf16[MAX_PATH]; + int codepage = codepage_for_filenames (NULL); + int result = pMultiByteToWideChar (codepage, MB_ERR_INVALID_CHARS, fn_in, -1, + fn_utf16, MAX_PATH); + + if (!result) + { + DWORD err = GetLastError (); + + switch (err) + { + case ERROR_INVALID_FLAGS: + case ERROR_INVALID_PARAMETER: + errno = EINVAL; + break; + case ERROR_INSUFFICIENT_BUFFER: + case ERROR_NO_UNICODE_TRANSLATION: + default: + errno = ENOENT; + break; + } + return -1; + } + return filename_from_utf16 (fn_utf16, fn_out); +} + +int +w32_valid_pointer_p (void *p, int size) +{ + SIZE_T done; + HANDLE h = OpenProcess (PROCESS_VM_READ, FALSE, GetCurrentProcessId ()); + + if (h) + { + unsigned char *buf = alloca (size); + int retval = ReadProcessMemory (h, p, buf, size, &done); + + CloseHandle (h); + return retval; + } + else + return -1; +} + +/* End experimental code for Cygwin-w32 build */ + #define DIRWATCH_SIGNATURE 0x01233210 struct notification { diff --git a/src/w32term.c b/src/w32term.c index d415b13..061c9c3 100644 --- a/src/w32term.c +++ b/src/w32term.c @@ -3195,7 +3195,6 @@ lispy_file_action (DWORD action) return retval; } -#ifdef WINDOWSNT /* Put file notifications into the Emacs input event queue. This function runs when the WM_EMACS_FILENOTIFY message arrives from a watcher thread. */ @@ -3271,7 +3270,6 @@ queue_notifications (struct input_event *event, W32Msg *msg, struct frame *f, /* We've stuffed all the events ourselves, so w32_read_socket shouldn't. */ event->kind = NO_EVENT; } -#endif /* WINDOWSNT */ #endif /* HAVE_W32NOTIFY */