From mboxrd@z Thu Jan 1 00:00:00 1970 Path: main.gmane.org!not-for-mail From: "Ben Key" Newsgroups: gmane.emacs.devel Subject: Patches for Gnu Emacs Date: Fri, 15 Nov 2002 23:04:19 -0500 Sender: emacs-devel-admin@gnu.org Message-ID: <000001c28d25$3e01d8d0$6501a8c0@GODDESS> Reply-To: NNTP-Posting-Host: main.gmane.org Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="----=_NextPart_000_0001_01C28CFB.552BD0D0" X-Trace: main.gmane.org 1037421189 26590 80.91.224.249 (16 Nov 2002 04:33:09 GMT) X-Complaints-To: usenet@main.gmane.org NNTP-Posting-Date: Sat, 16 Nov 2002 04:33:09 +0000 (UTC) Return-path: Original-Received: from quimby.gnus.org ([80.91.224.244]) by main.gmane.org with esmtp (Exim 3.35 #1 (Debian)) id 18Cudn-0006uZ-00 for ; Sat, 16 Nov 2002 05:33:07 +0100 Original-Received: from monty-python.gnu.org ([199.232.76.173]) by quimby.gnus.org with esmtp (Exim 3.12 #1 (Debian)) id 18Cuqy-0003xS-00 for ; Sat, 16 Nov 2002 05:46:44 +0100 Original-Received: from localhost ([127.0.0.1] helo=monty-python.gnu.org) by monty-python.gnu.org with esmtp (Exim 4.10) id 18CueD-0005NV-00; Fri, 15 Nov 2002 23:33:33 -0500 Original-Received: from list by monty-python.gnu.org with tmda-scanned (Exim 4.10) id 18CuDF-0000e8-00 for emacs-devel@gnu.org; Fri, 15 Nov 2002 23:05:41 -0500 Original-Received: from mail by monty-python.gnu.org with spam-scanned (Exim 4.10) id 18CuDB-0000Za-00 for emacs-devel@gnu.org; Fri, 15 Nov 2002 23:05:40 -0500 Original-Received: from smtp-server1.tampabay.rr.com ([65.32.1.34]) by monty-python.gnu.org with esmtp (Exim 4.10) id 18CuBw-0008RO-00 for emacs-devel@gnu.org; Fri, 15 Nov 2002 23:04:20 -0500 Original-Received: from GODDESS (6535194hfc48.tampabay.rr.com [65.35.194.48]) by smtp-server1.tampabay.rr.com (8.12.2/8.12.2) with SMTP id gAG44ICB020153 for ; Fri, 15 Nov 2002 23:04:18 -0500 (EST) Original-To: "Emacs-Devel \(E-mail\)" X-Priority: 3 (Normal) X-MSMail-Priority: Normal X-Mailer: Microsoft Outlook CWS, Build 9.0.2416 (9.0.2911.0) X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1106 Importance: Normal Errors-To: emacs-devel-admin@gnu.org X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.0.11 Precedence: bulk List-Help: List-Post: List-Subscribe: , List-Id: Emacs development discussions. List-Unsubscribe: , List-Archive: Xref: main.gmane.org gmane.emacs.devel:9480 X-Report-Spam: http://spam.gmane.org/gmane.emacs.devel:9480 This is a multi-part message in MIME format. ------=_NextPart_000_0001_01C28CFB.552BD0D0 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: 7bit Attached to this message are 2 patches for Gnu Emacs. The patches are as follows: emacs-21.3.50-w32-play-sound.diff A patch to provide a partial Windows implementation of the function play-sound-internal. It is only a partial implementation in that only the :file and :volume keywords are supported. The :device keyword, if present, is ignored. The :data keyword, if present, will cause an error to be generated. This patch has not been changed since I last sent it to this list. emacs-21.3.50-windows-crash-fix.diff A patch that address the following entry in etc/PROBLEMS: Emacs built on Windows 9x/ME crashes at startup on Windows XP, or Emacs built on XP crashes at startup on Windows 9x/ME. This patch has been updated since I last sent it to this list. In my most recent version of the patch, I removed all calls to the functions OpenProcessToken, GetTokenInformation, LookupAccountSid, and GetSidIdentifierAuthority from init_user_info and replaced them with calls to wrapper functions. These wrapper functions internally verify that Emacs is not running on Windows 9x, obtain the address of the wrapped function, and call the function via a pointer to the function. This change was suggested by Juanma Barranquero [lektu@terra.es]. The reason for this change is that these functions are only officially supported by Microsoft under Windows NT / 2K / XP. We can get away with calling them directly under Windows 9x except this is taking advantage of an undocumented feature of the version of advapi32.dll found in Windows 9x and doing so causes an exception to be generated under Windows 9x. If there are no objections from individuals on this list, I will be adding these changes to CVS Monday. In the meantime, I would appreciate it if as many people as possible were to test this patch. I have already tested this patch by building Emacs on Windows XP using both MSVC 6.0 and MinGW 2.0 and verifying that the build of Emacs runs on Windows 98 and that play-sound-internal functions properly. In addition I have verified that nothing in my patch inadvertently breaks the build in Gnu/Linux. ------=_NextPart_000_0001_01C28CFB.552BD0D0 Content-Type: application/octet-stream; name="emacs-21.3.50-windows-crash-fix.diff" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="emacs-21.3.50-windows-crash-fix.diff" --- _21.3/src/w32.c 2002-07-14 20:00:37.000000000 -0400=0A= +++ 21.3/src/w32.c 2002-11-15 12:50:32.000000000 -0500=0A= @@ -105,6 +105,171 @@=0A= extern Lisp_Object Vw32_num_mouse_buttons;=0A= =0A= =0C=0A= +/*=0A= + BEGIN: Wrapper functions around OpenProcessToken=0A= + and other functions in advapi32.dll that are only=0A= + supported in Windows NT / 2k / XP=0A= +*/=0A= + /* ** Function pointer typedefs ** */=0A= +typedef BOOL (WINAPI * OpenProcessToken_Proc) (=0A= + HANDLE ProcessHandle,=0A= + DWORD DesiredAccess,=0A= + PHANDLE TokenHandle);=0A= +typedef BOOL (WINAPI * GetTokenInformation_Proc) (=0A= + HANDLE TokenHandle,=0A= + TOKEN_INFORMATION_CLASS TokenInformationClass,=0A= + LPVOID TokenInformation,=0A= + DWORD TokenInformationLength,=0A= + PDWORD ReturnLength);=0A= +#ifdef _UNICODE=0A= +const char * const LookupAccountSid_Name =3D "LookupAccountSidW";=0A= +#else=0A= +const char * const LookupAccountSid_Name =3D "LookupAccountSidA";=0A= +#endif=0A= +typedef BOOL (WINAPI * LookupAccountSid_Proc) (=0A= + LPCTSTR lpSystemName,=0A= + PSID Sid,=0A= + LPTSTR Name,=0A= + LPDWORD cbName,=0A= + LPTSTR DomainName,=0A= + LPDWORD cbDomainName,=0A= + PSID_NAME_USE peUse);=0A= +typedef PSID_IDENTIFIER_AUTHORITY (WINAPI * = GetSidIdentifierAuthority_Proc) (=0A= + PSID pSid);=0A= +=0A= + /* ** A utility function ** */=0A= +static BOOL is_windows_9x ()=0A= +{=0A= + BOOL b_ret=3D0;=0A= + OSVERSIONINFO os_ver;=0A= + ZeroMemory(&os_ver, sizeof(OSVERSIONINFO));=0A= + os_ver.dwOSVersionInfoSize =3D sizeof(OSVERSIONINFO);=0A= + if (GetVersionEx (&os_ver))=0A= + {=0A= + b_ret =3D (os_ver.dwPlatformId =3D=3D VER_PLATFORM_WIN32_WINDOWS);=0A= + }=0A= + return b_ret;=0A= +}=0A= +=0A= + /* ** The wrapper functions ** */=0A= +=0A= +BOOL WINAPI open_process_token (=0A= + HANDLE ProcessHandle,=0A= + DWORD DesiredAccess,=0A= + PHANDLE TokenHandle)=0A= +{=0A= + OpenProcessToken_Proc pfn_Open_Process_Token =3D NULL;=0A= + HMODULE hm_advapi32 =3D NULL;=0A= + if (is_windows_9x () =3D=3D TRUE)=0A= + {=0A= + return FALSE;=0A= + }=0A= + hm_advapi32 =3D LoadLibrary ("Advapi32.dll");=0A= + pfn_Open_Process_Token =3D=0A= + (OpenProcessToken_Proc) GetProcAddress (hm_advapi32, = "OpenProcessToken");=0A= + if (pfn_Open_Process_Token =3D=3D NULL)=0A= + {=0A= + return FALSE;=0A= + }=0A= + return (=0A= + pfn_Open_Process_Token (=0A= + ProcessHandle,=0A= + DesiredAccess,=0A= + TokenHandle)=0A= + );=0A= +}=0A= +=0A= +BOOL WINAPI get_token_information (=0A= + HANDLE TokenHandle,=0A= + TOKEN_INFORMATION_CLASS TokenInformationClass,=0A= + LPVOID TokenInformation,=0A= + DWORD TokenInformationLength,=0A= + PDWORD ReturnLength)=0A= +{=0A= + GetTokenInformation_Proc pfn_Get_Token_Information =3D NULL;=0A= + HMODULE hm_advapi32 =3D NULL;=0A= + if (is_windows_9x () =3D=3D TRUE)=0A= + {=0A= + return FALSE;=0A= + }=0A= + hm_advapi32 =3D LoadLibrary ("Advapi32.dll");=0A= + pfn_Get_Token_Information =3D=0A= + (GetTokenInformation_Proc) GetProcAddress (hm_advapi32, = "GetTokenInformation");=0A= + if (pfn_Get_Token_Information =3D=3D NULL)=0A= + {=0A= + return FALSE;=0A= + }=0A= + return (=0A= + pfn_Get_Token_Information (=0A= + TokenHandle,=0A= + TokenInformationClass,=0A= + TokenInformation,=0A= + TokenInformationLength,=0A= + ReturnLength)=0A= + );=0A= +}=0A= +=0A= +BOOL WINAPI lookup_account_sid (=0A= + LPCTSTR lpSystemName,=0A= + PSID Sid,=0A= + LPTSTR Name,=0A= + LPDWORD cbName,=0A= + LPTSTR DomainName,=0A= + LPDWORD cbDomainName,=0A= + PSID_NAME_USE peUse)=0A= +{=0A= + LookupAccountSid_Proc pfn_Lookup_Account_Sid =3D NULL;=0A= + HMODULE hm_advapi32 =3D NULL;=0A= + if (is_windows_9x () =3D=3D TRUE)=0A= + {=0A= + return FALSE;=0A= + }=0A= + hm_advapi32 =3D LoadLibrary ("Advapi32.dll");=0A= + pfn_Lookup_Account_Sid =3D=0A= + (LookupAccountSid_Proc) GetProcAddress (hm_advapi32, = LookupAccountSid_Name);=0A= + if (pfn_Lookup_Account_Sid =3D=3D NULL)=0A= + {=0A= + return FALSE;=0A= + }=0A= + return (=0A= + pfn_Lookup_Account_Sid (=0A= + lpSystemName,=0A= + Sid,=0A= + Name,=0A= + cbName,=0A= + DomainName,=0A= + cbDomainName,=0A= + peUse)=0A= + );=0A= +}=0A= +=0A= +PSID_IDENTIFIER_AUTHORITY WINAPI get_sid_identifier_authority (=0A= + PSID pSid)=0A= +{=0A= + GetSidIdentifierAuthority_Proc pfn_Get_Sid_Identifier_Authority =3D = NULL;=0A= + HMODULE hm_advapi32 =3D NULL;=0A= + if (is_windows_9x () =3D=3D TRUE)=0A= + {=0A= + return NULL;=0A= + }=0A= + hm_advapi32 =3D LoadLibrary ("Advapi32.dll");=0A= + pfn_Get_Sid_Identifier_Authority =3D=0A= + (GetSidIdentifierAuthority_Proc) GetProcAddress (=0A= + hm_advapi32, "GetSidIdentifierAuthority");=0A= + if (pfn_Get_Sid_Identifier_Authority =3D=3D NULL)=0A= + {=0A= + return NULL;=0A= + }=0A= + return (pfn_Get_Sid_Identifier_Authority (pSid));=0A= +}=0A= +=0A= +/*=0A= + END: Wrapper functions around OpenProcessToken=0A= + and other functions in advapi32.dll that are only=0A= + supported in Windows NT / 2k / XP=0A= +*/=0A= +=0A= +=0C=0A= /* Equivalent of strerror for W32 error codes. */=0A= char *=0A= w32_strerror (int error_no)=0A= @@ -254,11 +419,15 @@=0A= HANDLE token =3D NULL;=0A= SID_NAME_USE user_type;=0A= =0A= - if (OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY, &token)=0A= - && GetTokenInformation (token, TokenUser,=0A= + if (=0A= + open_process_token (GetCurrentProcess (), TOKEN_QUERY, &token)=0A= + && get_token_information (=0A= + token, TokenUser,=0A= (PVOID) user_sid, sizeof (user_sid), &trash)=0A= - && LookupAccountSid (NULL, *((PSID *) user_sid), name, &length,=0A= - domain, &dlength, &user_type))=0A= + && lookup_account_sid (=0A= + NULL, *((PSID *) user_sid), name, &length,=0A= + domain, &dlength, &user_type)=0A= + )=0A= {=0A= strcpy (the_passwd.pw_name, name);=0A= /* Determine a reasonable uid value. */=0A= @@ -271,7 +440,7 @@=0A= {=0A= SID_IDENTIFIER_AUTHORITY * pSIA;=0A= =0A= - pSIA =3D GetSidIdentifierAuthority (*((PSID *) user_sid));=0A= + pSIA =3D get_sid_identifier_authority (*((PSID *) user_sid));=0A= /* I believe the relative portion is the last 4 bytes (of 6)=0A= with msb first. */=0A= the_passwd.pw_uid =3D ((pSIA->Value[2] << 24) +=0A= @@ -282,12 +451,12 @@=0A= the_passwd.pw_uid =3D the_passwd.pw_uid % 60001;=0A= =0A= /* Get group id */=0A= - if (GetTokenInformation (token, TokenPrimaryGroup,=0A= + if (get_token_information (token, TokenPrimaryGroup,=0A= (PVOID) user_sid, sizeof (user_sid), &trash))=0A= {=0A= SID_IDENTIFIER_AUTHORITY * pSIA;=0A= =0A= - pSIA =3D GetSidIdentifierAuthority (*((PSID *) user_sid));=0A= + pSIA =3D get_sid_identifier_authority (*((PSID *) user_sid));=0A= the_passwd.pw_gid =3D ((pSIA->Value[2] << 24) +=0A= (pSIA->Value[3] << 16) +=0A= (pSIA->Value[4] << 8) +=0A= --- _21.3/src/w32.h 2002-05-03 16:41:03.000000000 -0400=0A= +++ 21.3/src/w32.h 2002-11-15 12:44:48.000000000 -0500=0A= @@ -124,5 +124,10 @@=0A= =0A= extern void init_ntproc ();=0A= extern void term_ntproc ();=0A= +extern void syms_of_w32term ();=0A= +extern void syms_of_w32fns ();=0A= +extern void syms_of_w32select ();=0A= +extern void syms_of_w32menu ();=0A= +extern void syms_of_fontset ();=0A= =0A= #endif /* EMACS_W32_H */=0A= --- _21.3/src/w32fns.c 2002-10-23 12:55:07.000000000 -0400=0A= +++ 21.3/src/w32fns.c 2002-11-15 12:44:48.000000000 -0500=0A= @@ -283,7 +283,12 @@=0A= =0A= /* Window that is tracking the mouse. */=0A= static HWND track_mouse_window;=0A= -FARPROC track_mouse_event_fn;=0A= +=0A= +typedef BOOL (WINAPI * TrackMouseEvent_Proc) (=0A= + IN OUT LPTRACKMOUSEEVENT lpEventTrack=0A= + );=0A= +=0A= +TrackMouseEvent_Proc track_mouse_event_fn=3DNULL;=0A= =0A= /* W95 mousewheel handler */=0A= unsigned int msh_mousewheel =3D 0;=0A= @@ -4929,6 +4934,30 @@=0A= goto dflt;=0A= =0A= case WM_SETFOCUS:=0A= + /*=0A= + Reinitialize the function pointer track_mouse_event_fn here.=0A= + This is required even though it is initialized in syms_of_w32fns=0A= + which is called in main (emacs.c).=0A= + Reinitialize the function pointer track_mouse_event_fn here.=0A= + Even though this function pointer is initialized in=0A= + syms_of_w32fns which is called from main (emacs.c),=0A= + we need to initialize it again here in order to prevent=0A= + a crash that occurs in Windows 9x (possibly only when Emacs=0A= + was built on Windows NT / 2000 / XP?) when handling the=0A= + WM_MOUSEMOVE message.=0A= + The crash occurs when attempting to call the Win32 API=0A= + function TrackMouseEvent through the function pointer.=0A= + It appears as if the function pointer that is obtained when=0A= + syms_of_w32fns is called from main is no longer valid=0A= + (possibly due to DLL relocation?).=0A= + To resolve this issue, I have placed a call to reinitialize=0A= + this function pointer here because this message gets received=0A= + when the Emacs window gains focus. =0A= + */=0A= + track_mouse_event_fn =3D=0A= + (TrackMouseEvent_Proc) GetProcAddress (=0A= + GetModuleHandle ("user32.dll"),=0A= + "TrackMouseEvent");=0A= dpyinfo->faked_key =3D 0;=0A= reset_modifiers ();=0A= register_hot_keys (hwnd);=0A= @@ -14801,7 +14830,7 @@=0A= =0A= /* TrackMouseEvent not available in all versions of Windows, so must = load=0A= it dynamically. Do it once, here, instead of every time it is = used. */=0A= - track_mouse_event_fn =3D GetProcAddress (user32_lib, = "TrackMouseEvent");=0A= + track_mouse_event_fn =3D (TrackMouseEvent_Proc) GetProcAddress = (user32_lib, "TrackMouseEvent");=0A= track_mouse_window =3D NULL;=0A= =0A= w32_visible_system_caret_hwnd =3D NULL;=0A= --- _21.3/src/w32menu.c 2002-08-05 12:33:44.000000000 -0400=0A= +++ 21.3/src/w32menu.c 2002-11-15 12:44:48.000000000 -0500=0A= @@ -129,8 +129,23 @@=0A= =0A= static HMENU current_popup_menu;=0A= =0A= -FARPROC get_menu_item_info;=0A= -FARPROC set_menu_item_info;=0A= +void syms_of_w32menu ();=0A= +=0A= +typedef BOOL (WINAPI * GetMenuItemInfoA_Proc) (=0A= + IN HMENU,=0A= + IN UINT,=0A= + IN BOOL,=0A= + IN OUT LPMENUITEMINFOA=0A= + );=0A= +typedef BOOL (WINAPI * SetMenuItemInfoA_Proc) (=0A= + IN HMENU,=0A= + IN UINT,=0A= + IN BOOL,=0A= + IN LPCMENUITEMINFOA=0A= + );=0A= +=0A= +GetMenuItemInfoA_Proc get_menu_item_info=3DNULL;=0A= +SetMenuItemInfoA_Proc set_menu_item_info=3DNULL;=0A= =0A= Lisp_Object Vmenu_updating_frame;=0A= =0A= @@ -1591,6 +1606,26 @@=0A= initialize_frame_menubar (f)=0A= FRAME_PTR f;=0A= {=0A= + HMODULE user32 =3D GetModuleHandle ("user32.dll");=0A= + /*=0A= + Reinitialize the function pointers set_menu_item_info and=0A= + get_menu_item_info here.=0A= + Even though these function pointers are initialized in=0A= + syms_of_w32menu which is called from main (emacs.c),=0A= + we need to initialize them again here in order to prevent=0A= + a crash that occurs in Windows 9x (possibly only when Emacs=0A= + was built on Windows NT / 2000 / XP?) in add_menu_item.=0A= + The crash occurs when attempting to call the Win32 API=0A= + function SetMenuItemInfo through the function pointer.=0A= + It appears as if the function pointer that is obtained when=0A= + syms_of_w32menu is called from main is no longer valid=0A= + (possibly due to DLL relocation?).=0A= + To resolve this issue, I have placed calls to reinitialize=0A= + these function pointers here because this function is the=0A= + entry point for menu creation.=0A= + */=0A= + get_menu_item_info =3D (GetMenuItemInfoA_Proc) GetProcAddress = (user32, "GetMenuItemInfoA");=0A= + set_menu_item_info =3D (SetMenuItemInfoA_Proc) GetProcAddress = (user32, "SetMenuItemInfoA");=0A= /* This function is called before the first chance to redisplay=0A= the frame. It has to be, so the frame will have the right size. = */=0A= FRAME_MENU_BAR_ITEMS (f) =3D menu_bar_items (FRAME_MENU_BAR_ITEMS = (f));=0A= @@ -2355,13 +2390,12 @@=0A= =0A= #endif /* HAVE_MENUS */=0A= =0A= -=0C=0A= -syms_of_w32menu ()=0A= +void syms_of_w32menu ()=0A= {=0A= /* See if Get/SetMenuItemInfo functions are available. */=0A= HMODULE user32 =3D GetModuleHandle ("user32.dll");=0A= - get_menu_item_info =3D GetProcAddress (user32, "GetMenuItemInfoA");=0A= - set_menu_item_info =3D GetProcAddress (user32, "SetMenuItemInfoA");=0A= + get_menu_item_info =3D (GetMenuItemInfoA_Proc) GetProcAddress = (user32, "GetMenuItemInfoA");=0A= + set_menu_item_info =3D (SetMenuItemInfoA_Proc) GetProcAddress = (user32, "SetMenuItemInfoA");=0A= =0A= staticpro (&menu_items);=0A= menu_items =3D Qnil;=0A= ------=_NextPart_000_0001_01C28CFB.552BD0D0 Content-Type: application/octet-stream; name="dopatch21_3.sh" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="dopatch21_3.sh" #!/bin/sh if [ -f emacs-21.3.50-w32-play-sound.diff ] then echo "Applying patch emacs-21.3.50-w32-play-sound.diff" patch --unified --quiet --strip=3D1 = --input=3Demacs-21.3.50-w32-play-sound.diff fi if [ -f emacs-21.3.50-windows-crash-fix.diff ] then echo "Applying patch emacs-21.3.50-windows-crash-fix.diff" patch --unified --quiet --strip=3D1 = --input=3Demacs-21.3.50-windows-crash-fix.diff fi ------=_NextPart_000_0001_01C28CFB.552BD0D0 Content-Type: application/octet-stream; name="emacs-21.3.50-w32-play-sound.diff" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="emacs-21.3.50-w32-play-sound.diff" --- _21.3/nt/nmake.defs 2002-01-04 09:04:53.000000000 -0500=0A= +++ 21.3/nt/nmake.defs 2002-11-15 12:44:48.000000000 -0500=0A= @@ -123,6 +123,7 @@=0A= SHELL32 =3D shell32.lib USER32 =3D user32.lib WSOCK32 =3D wsock32.lib +WINMM =3D winmm.lib=0A= =20 !ifdef NOOPT DEBUG_CFLAGS =3D -DEMACSDEBUG --- _21.3/nt/gmake.defs 2002-01-04 09:04:26.000000000 -0500=0A= +++ 21.3/nt/gmake.defs 2002-11-15 12:44:48.000000000 -0500=0A= @@ -166,6 +166,7 @@=0A= SHELL32 =3D -lshell32=0A= USER32 =3D -luser32=0A= WSOCK32 =3D -lwsock32=0A= +WINMM =3D -lwinmm=0A= =0A= ifdef NOOPT=0A= DEBUG_CFLAGS =3D -DEMACSDEBUG=0A= --- _21.3/src/makefile.w32-in 2002-09-04 02:20:50.000000000 -0400=0A= +++ 21.3/src/makefile.w32-in 2002-11-15 12:44:48.000000000 -0500=0A= @@ -94,6 +94,7 @@=0A= $(BLD)/regex.$(O) \=0A= $(BLD)/scroll.$(O) \=0A= $(BLD)/search.$(O) \=0A= + $(BLD)/sound.$(O) \=0A= $(BLD)/syntax.$(O) \=0A= $(BLD)/sysdep.$(O) \=0A= $(BLD)/term.$(O) \=0A= @@ -133,6 +134,7 @@=0A= $(TLIB1) \=0A= $(TLIBW32) \=0A= $(TLASTLIB) \=0A= + $(WINMM) \=0A= $(ADVAPI32) \=0A= $(GDI32) \=0A= $(COMDLG32) \=0A= @@ -1094,6 +1096,13 @@=0A= $(SRC)/w32bdf.h \=0A= $(SRC)/w32gui.h=0A= =0A= +$(BLD)/sound.$(O) : \=0A= + $(SRC)/sound.c \=0A= + $(SRC)/lisp.h \=0A= + $(SRC)/dispextern.h \=0A= + $(SRC)/atimer.h \=0A= + $(SRC)/syssignal.h=0A= +=0A= $(BLD)/strftime.$(O) : \=0A= $(SRC)/strftime.c \=0A= $(EMACS_ROOT)/src/s/ms-w32.h \=0A= --- _21.3/src/s/ms-w32.h 2002-05-03 16:42:33.000000000 -0400=0A= +++ 21.3/src/s/ms-w32.h 2002-11-15 12:44:48.000000000 -0500=0A= @@ -217,6 +217,7 @@=0A= #define MAXPATHLEN _MAX_PATH=0A= #endif=0A= =0A= +#define HAVE_SOUND 1=0A= #define LISP_FLOAT_TYPE 1=0A= =0A= #undef HAVE_SYS_SELECT_H=0A= --- _21.3/src/sound.c 2002-07-19 10:27:20.000000000 -0400=0A= +++ 21.3/src/sound.c 2002-11-15 12:44:48.000000000 -0500=0A= @@ -21,10 +21,26 @@=0A= /* Written by Gerd Moellmann . Tested with Luigi's=0A= driver on FreeBSD 2.2.7 with a SoundBlaster 16. */=0A= =0A= +/*=0A= + Modified by Ben Key to add a partial=0A= + implementation of the play-sound specification for Windows.=0A= +=0A= + Notes:=0A= + In the Windows implementation of play-sound-internal only the=0A= + :file and :volume keywords are supported. The :device keyword,=0A= + if present, is ignored. The :data keyword, if present, will=0A= + cause an error to be generated.=0A= +=0A= + The Windows implementation of play-sound is implemented via the=0A= + Win32 API functions mciSendString, waveOutGetVolume, and=0A= + waveOutGetVolume which are exported by Winmm.dll.=0A= +*/=0A= +=0A= #include =0A= =0A= #if defined HAVE_SOUND=0A= =0A= +/* BEGIN: Common Includes */=0A= #include =0A= #include =0A= #include =0A= @@ -34,6 +50,11 @@=0A= #include "atimer.h"=0A= #include =0A= #include "syssignal.h"=0A= +/* END: Common Includes */=0A= +=0A= +=0A= +/* BEGIN: Non Windows Includes */=0A= +#ifndef WINDOWSNT=0A= =0A= #ifndef MSDOS=0A= #include =0A= @@ -51,12 +72,55 @@=0A= #ifdef HAVE_SOUNDCARD_H=0A= #include =0A= #endif=0A= +/* END: Non Windows Includes */=0A= +=0A= +#else /* WINDOWSNT */=0A= +=0A= +/* BEGIN: Windows Specific Includes */=0A= +#include =0A= +#include =0A= +#include =0A= +#include =0A= +#include =0A= +#include =0A= +/* END: Windows Specific Includes */=0A= +=0A= +#endif /* WINDOWSNT */=0A= +=0A= +/* BEGIN: Common Definitions */=0A= +#define abs(X) ((X) < 0 ? -(X) : (X))=0A= +=0A= +/* Symbols. */=0A= +=0A= +extern Lisp_Object QCfile, QCdata;=0A= +Lisp_Object QCvolume, QCdevice;=0A= +Lisp_Object Qsound;=0A= +Lisp_Object Qplay_sound_functions;=0A= +=0A= +/* Indices of attributes in a sound attributes vector. */=0A= +=0A= +enum sound_attr=0A= +{=0A= + SOUND_FILE,=0A= + SOUND_DATA,=0A= + SOUND_DEVICE,=0A= + SOUND_VOLUME,=0A= + SOUND_ATTR_SENTINEL=0A= +};=0A= +=0A= +static void sound_perror P_ ((char *));=0A= +static void sound_warning P_ ((char *));=0A= +static int parse_sound P_ ((Lisp_Object, Lisp_Object *));=0A= +=0A= +/* END: Common Definitions */=0A= +=0A= +/* BEGIN: Non Windows Definitions */=0A= +#ifndef WINDOWSNT=0A= =0A= #ifndef DEFAULT_SOUND_DEVICE=0A= #define DEFAULT_SOUND_DEVICE "/dev/dsp"=0A= #endif=0A= =0A= -#define abs(X) ((X) < 0 ? -(X) : (X))=0A= =0A= /* Structure forward declarations. */=0A= =0A= @@ -203,24 +267,6 @@=0A= void (* play) P_ ((struct sound *s, struct sound_device *sd));=0A= };=0A= =0A= -/* Indices of attributes in a sound attributes vector. */=0A= -=0A= -enum sound_attr=0A= -{=0A= - SOUND_FILE,=0A= - SOUND_DATA,=0A= - SOUND_DEVICE,=0A= - SOUND_VOLUME,=0A= - SOUND_ATTR_SENTINEL=0A= -};=0A= -=0A= -/* Symbols. */=0A= -=0A= -extern Lisp_Object QCfile, QCdata;=0A= -Lisp_Object QCvolume, QCdevice;=0A= -Lisp_Object Qsound;=0A= -Lisp_Object Qplay_sound_functions;=0A= -=0A= /* These are set during `play-sound-internal' so that sound_cleanup has=0A= access to them. */=0A= =0A= @@ -235,9 +281,6 @@=0A= static void vox_choose_format P_ ((struct sound_device *, struct sound = *));=0A= static void vox_init P_ ((struct sound_device *));=0A= static void vox_write P_ ((struct sound_device *, const char *, int));=0A= -static void sound_perror P_ ((char *));=0A= -static void sound_warning P_ ((char *));=0A= -static int parse_sound P_ ((Lisp_Object, Lisp_Object *));=0A= static void find_sound_type P_ ((struct sound *));=0A= static u_int32_t le2hl P_ ((u_int32_t));=0A= static u_int16_t le2hs P_ ((u_int16_t));=0A= @@ -251,12 +294,22 @@=0A= static u_int16_t be2hs P_ ((u_int16_t));=0A= #endif=0A= =0A= +/* END: Non Windows Definitions */=0A= +#else /* WINDOWSNT */=0A= +=0A= +/* BEGIN: Windows Specific Definitions */=0A= +static int do_play_sound P_ ((const char *, unsigned long));=0A= +/*=0A= + END: Windows Specific Definitions */=0A= +#endif /* WINDOWSNT */=0A= =0A= =0C=0A= /***********************************************************************=0A= General=0A= = ***********************************************************************/=0A= =0A= +/* BEGIN: Common functions */=0A= +=0A= /* Like perror, but signals an error. */=0A= =0A= static void=0A= @@ -327,10 +380,21 @@=0A= attrs[SOUND_DEVICE] =3D Fplist_get (sound, QCdevice);=0A= attrs[SOUND_VOLUME] =3D Fplist_get (sound, QCvolume);=0A= =0A= +#ifndef WINDOWSNT=0A= /* File name or data must be specified. */=0A= if (!STRINGP (attrs[SOUND_FILE])=0A= && !STRINGP (attrs[SOUND_DATA]))=0A= return 0;=0A= +#else /* WINDOWSNT */=0A= + /*=0A= + Data is not supported in Windows. Therefore a=0A= + File name MUST be supplied.=0A= + */=0A= + if (!STRINGP (attrs[SOUND_FILE]))=0A= + {=0A= + return 0;=0A= + }=0A= +#endif /* WINDOWSNT */=0A= =0A= /* Volume must be in the range 0..100 or unspecified. */=0A= if (!NILP (attrs[SOUND_VOLUME]))=0A= @@ -351,14 +415,23 @@=0A= return 0;=0A= }=0A= =0A= +#ifndef WINDOWSNT=0A= /* Device must be a string or unspecified. */=0A= if (!NILP (attrs[SOUND_DEVICE])=0A= && !STRINGP (attrs[SOUND_DEVICE]))=0A= return 0;=0A= -=0A= +#endif /* WINDOWSNT */=0A= + /*=0A= + Since device is ignored in Windows, it does not matter=0A= + what it is.=0A= + */=0A= return 1;=0A= }=0A= =0A= +/* END: Common functions */=0A= +=0A= +/* BEGIN: Non Windows functions */=0A= +#ifndef WINDOWSNT=0A= =0A= /* Find out the type of the sound file whose file descriptor is FD.=0A= S is the sound file structure to fill in. */=0A= @@ -389,105 +462,6 @@=0A= return Qnil;=0A= }=0A= =0A= -=0A= -DEFUN ("play-sound-internal", Fplay_sound_internal, = Splay_sound_internal, 1, 1, 0,=0A= - doc: /* Play sound SOUND.=0A= -=0A= -Internal use only, use `play-sound' instead. */)=0A= - (sound)=0A= - Lisp_Object sound;=0A= -{=0A= - Lisp_Object attrs[SOUND_ATTR_SENTINEL];=0A= - Lisp_Object file;=0A= - struct gcpro gcpro1, gcpro2;=0A= - struct sound_device sd;=0A= - struct sound s;=0A= - Lisp_Object args[2];=0A= - int count =3D SPECPDL_INDEX ();=0A= -=0A= - file =3D Qnil;=0A= - GCPRO2 (sound, file);=0A= - bzero (&sd, sizeof sd);=0A= - bzero (&s, sizeof s);=0A= - current_sound_device =3D &sd;=0A= - current_sound =3D &s;=0A= - record_unwind_protect (sound_cleanup, Qnil);=0A= - s.header =3D (char *) alloca (MAX_SOUND_HEADER_BYTES);=0A= -=0A= - /* Parse the sound specification. Give up if it is invalid. */=0A= - if (!parse_sound (sound, attrs))=0A= - error ("Invalid sound specification");=0A= -=0A= - if (STRINGP (attrs[SOUND_FILE]))=0A= - {=0A= - /* Open the sound file. */=0A= - s.fd =3D openp (Fcons (Vdata_directory, Qnil),=0A= - attrs[SOUND_FILE], Qnil, &file, Qnil);=0A= - if (s.fd < 0)=0A= - sound_perror ("Could not open sound file");=0A= -=0A= - /* Read the first bytes from the file. */=0A= - s.header_size =3D emacs_read (s.fd, s.header, = MAX_SOUND_HEADER_BYTES);=0A= - if (s.header_size < 0)=0A= - sound_perror ("Invalid sound file header");=0A= - }=0A= - else=0A= - {=0A= - s.data =3D attrs[SOUND_DATA];=0A= - s.header_size =3D min (MAX_SOUND_HEADER_BYTES, SBYTES (s.data));=0A= - bcopy (SDATA (s.data), s.header, s.header_size);=0A= - }=0A= -=0A= - /* Find out the type of sound. Give up if we can't tell. */=0A= - find_sound_type (&s);=0A= -=0A= - /* Set up a device. */=0A= - if (STRINGP (attrs[SOUND_DEVICE]))=0A= - {=0A= - int len =3D SCHARS (attrs[SOUND_DEVICE]);=0A= - sd.file =3D (char *) alloca (len + 1);=0A= - strcpy (sd.file, SDATA (attrs[SOUND_DEVICE]));=0A= - }=0A= -=0A= - if (INTEGERP (attrs[SOUND_VOLUME]))=0A= - sd.volume =3D XFASTINT (attrs[SOUND_VOLUME]);=0A= - else if (FLOATP (attrs[SOUND_VOLUME]))=0A= - sd.volume =3D XFLOAT_DATA (attrs[SOUND_VOLUME]) * 100;=0A= -=0A= - args[0] =3D Qplay_sound_functions;=0A= - args[1] =3D sound;=0A= - Frun_hook_with_args (2, args);=0A= -=0A= - /* There is only one type of device we currently support, the VOX=0A= - sound driver. Set up the device interface functions for that=0A= - device. */=0A= - vox_init (&sd);=0A= -=0A= - /* Open the device. */=0A= - sd.open (&sd);=0A= -=0A= - /* Play the sound. */=0A= - s.play (&s, &sd);=0A= -=0A= - /* Close the input file, if any. */=0A= - if (!STRINGP (s.data))=0A= - {=0A= - emacs_close (s.fd);=0A= - s.fd =3D -1;=0A= - }=0A= -=0A= - /* Close the device. */=0A= - sd.close (&sd);=0A= -=0A= - /* Clean up. */=0A= - current_sound_device =3D NULL;=0A= - current_sound =3D NULL;=0A= - UNGCPRO;=0A= - unbind_to (count, Qnil);=0A= - return Qnil;=0A= -}=0A= -=0A= -=0C=0A= /***********************************************************************=0A= Byte-order Conversion=0A= = ***********************************************************************/=0A= @@ -555,7 +529,6 @@=0A= =0A= #endif /* 0 */=0A= =0A= -=0C=0A= /***********************************************************************=0A= RIFF-WAVE (*.wav)=0A= = ***********************************************************************/=0A= @@ -645,7 +618,6 @@=0A= }=0A= =0A= =0A= -=0C=0A= /***********************************************************************=0A= Sun Audio (*.au)=0A= = ***********************************************************************/=0A= @@ -735,7 +707,6 @@=0A= }=0A= =0A= =0A= -=0C=0A= /***********************************************************************=0A= Voxware Driver Interface=0A= = ***********************************************************************/=0A= @@ -909,7 +880,6 @@=0A= sd->write =3D vox_write;=0A= }=0A= =0A= -=0A= /* Write NBYTES bytes from BUFFER to device SD. */=0A= =0A= static void=0A= @@ -923,7 +893,231 @@=0A= sound_perror ("Error writing to sound device");=0A= }=0A= =0A= +/* END: Non Windows functions */=0A= +#else /* WINDOWSNT */=0A= =0A= +/* BEGIN: Windows specific functions */=0A= +=0A= +static int=0A= +do_play_sound (psz_file, ui_volume)=0A= + const char * psz_file;=0A= + unsigned long ui_volume;=0A= +{=0A= + int i_result=3D0;=0A= + MCIERROR mci_error=3D0;=0A= + char sz_cmd_buf[520]=3D{0};=0A= + char sz_ret_buf[520]=3D{0};=0A= + MMRESULT mm_result=3DMMSYSERR_NOERROR;=0A= + unsigned long ui_volume_org=3D0;=0A= + BOOL b_reset_volume=3DFALSE;=0A= + memset (sz_cmd_buf, 0, sizeof(sz_cmd_buf));=0A= + memset (sz_ret_buf, 0, sizeof(sz_ret_buf));=0A= + sprintf (=0A= + sz_cmd_buf,=0A= + "open \"%s\" alias GNUEmacs_PlaySound_Device wait",=0A= + psz_file);=0A= + mci_error=3DmciSendString (sz_cmd_buf, sz_ret_buf, 520, NULL);=0A= + if (mci_error !=3D 0)=0A= + {=0A= + sound_warning (=0A= + "The open mciSendString command failed to open\n"=0A= + "the specified sound file");=0A= + i_result=3D(int)mci_error;=0A= + return i_result;=0A= + }=0A= + if ((ui_volume > 0) && (ui_volume !=3D UINT_MAX))=0A= + {=0A= + mm_result=3DwaveOutGetVolume ((HWAVEOUT)WAVE_MAPPER, = &ui_volume_org);=0A= + if (mm_result =3D=3D MMSYSERR_NOERROR)=0A= + {=0A= + b_reset_volume=3DTRUE;=0A= + mm_result=3DwaveOutSetVolume ((HWAVEOUT)WAVE_MAPPER, = ui_volume);=0A= + if ( mm_result !=3D MMSYSERR_NOERROR)=0A= + {=0A= + sound_warning (=0A= + "waveOutSetVolume failed to set the volume level\n"=0A= + "of the WAVE_MAPPER device.\n"=0A= + "As a result, the user selected volume level will\n"=0A= + "not be used.");=0A= + }=0A= + }=0A= + else=0A= + {=0A= + sound_warning (=0A= + "waveOutGetVolume failed to obtain the original\n"=0A= + "volume level of the WAVE_MAPPER device.\n"=0A= + "As a result, the user selected volume level will\n"=0A= + "not be used.");=0A= + }=0A= + }=0A= + memset (sz_cmd_buf, 0, sizeof(sz_cmd_buf));=0A= + memset (sz_ret_buf, 0, sizeof(sz_ret_buf));=0A= + strcpy (sz_cmd_buf, "play GNUEmacs_PlaySound_Device wait");=0A= + mci_error=3DmciSendString (sz_cmd_buf, sz_ret_buf, 520, NULL);=0A= + if (mci_error !=3D 0)=0A= + {=0A= + sound_warning (=0A= + "The play mciSendString command failed to play the\n"=0A= + "opened sound file.");=0A= + i_result=3D(int)mci_error;=0A= + }=0A= + memset (sz_cmd_buf, 0, sizeof(sz_cmd_buf));=0A= + memset (sz_ret_buf, 0, sizeof(sz_ret_buf));=0A= + strcpy (sz_cmd_buf, "close GNUEmacs_PlaySound_Device wait");=0A= + mci_error=3DmciSendString ( sz_cmd_buf, sz_ret_buf, 520, NULL);=0A= + if (b_reset_volume =3D=3D TRUE)=0A= + {=0A= + mm_result=3DwaveOutSetVolume ((HWAVEOUT)WAVE_MAPPER, = ui_volume_org);=0A= + if (mm_result !=3D MMSYSERR_NOERROR)=0A= + {=0A= + sound_warning (=0A= + "waveOutSetVolume failed to reset the original volume\n"=0A= + "level of the WAVE_MAPPER device.");=0A= + }=0A= + }=0A= + return i_result;=0A= +}=0A= +=0A= +/* END: Windows specific functions */=0A= +=0A= +#endif /* WINDOWSNT */=0A= +=0A= +=0A= +DEFUN ("play-sound-internal", Fplay_sound_internal, = Splay_sound_internal, 1, 1, 0,=0A= + doc: /* Play sound SOUND.=0A= +=0A= +Internal use only, use `play-sound' instead.\n */)=0A= + (sound)=0A= + Lisp_Object sound;=0A= +{=0A= + Lisp_Object attrs[SOUND_ATTR_SENTINEL];=0A= + int count =3D SPECPDL_INDEX ();=0A= +=0A= +#ifndef WINDOWSNT=0A= + Lisp_Object file;=0A= + struct gcpro gcpro1, gcpro2;=0A= + struct sound_device sd;=0A= + struct sound s;=0A= + Lisp_Object args[2];=0A= +#else /* WINDOWSNT */=0A= + int len=3D0;=0A= + Lisp_Object lo_file=3D{0};=0A= + char * psz_file=3DNULL;=0A= + unsigned long ui_volume_tmp=3DUINT_MAX;=0A= + unsigned long ui_volume=3DUINT_MAX;=0A= + int i_result=3D0;=0A= +#endif /* WINDOWSNT */=0A= +=0A= + /* Parse the sound specification. Give up if it is invalid. */=0A= + if (!parse_sound (sound, attrs))=0A= + error ("Invalid sound specification");=0A= +=0A= +#ifndef WINDOWSNT=0A= + file =3D Qnil;=0A= + GCPRO2 (sound, file);=0A= + bzero (&sd, sizeof sd);=0A= + bzero (&s, sizeof s);=0A= + current_sound_device =3D &sd;=0A= + current_sound =3D &s;=0A= + record_unwind_protect (sound_cleanup, Qnil);=0A= + s.header =3D (char *) alloca (MAX_SOUND_HEADER_BYTES);=0A= +=0A= + if (STRINGP (attrs[SOUND_FILE]))=0A= + {=0A= + /* Open the sound file. */=0A= + s.fd =3D openp (Fcons (Vdata_directory, Qnil),=0A= + attrs[SOUND_FILE], Qnil, &file, Qnil);=0A= + if (s.fd < 0)=0A= + sound_perror ("Could not open sound file");=0A= +=0A= + /* Read the first bytes from the file. */=0A= + s.header_size =3D emacs_read (s.fd, s.header, = MAX_SOUND_HEADER_BYTES);=0A= + if (s.header_size < 0)=0A= + sound_perror ("Invalid sound file header");=0A= + }=0A= + else=0A= + {=0A= + s.data =3D attrs[SOUND_DATA];=0A= + s.header_size =3D min (MAX_SOUND_HEADER_BYTES, SBYTES (s.data));=0A= + bcopy (SDATA (s.data), s.header, s.header_size);=0A= + }=0A= +=0A= + /* Find out the type of sound. Give up if we can't tell. */=0A= + find_sound_type (&s);=0A= +=0A= + /* Set up a device. */=0A= + if (STRINGP (attrs[SOUND_DEVICE]))=0A= + {=0A= + int len =3D SCHARS (attrs[SOUND_DEVICE]);=0A= + sd.file =3D (char *) alloca (len + 1);=0A= + strcpy (sd.file, SDATA (attrs[SOUND_DEVICE]));=0A= + }=0A= +=0A= + if (INTEGERP (attrs[SOUND_VOLUME]))=0A= + sd.volume =3D XFASTINT (attrs[SOUND_VOLUME]);=0A= + else if (FLOATP (attrs[SOUND_VOLUME]))=0A= + sd.volume =3D XFLOAT_DATA (attrs[SOUND_VOLUME]) * 100;=0A= +=0A= + args[0] =3D Qplay_sound_functions;=0A= + args[1] =3D sound;=0A= + Frun_hook_with_args (2, args);=0A= +=0A= + /* There is only one type of device we currently support, the VOX=0A= + sound driver. Set up the device interface functions for that=0A= + device. */=0A= + vox_init (&sd);=0A= +=0A= + /* Open the device. */=0A= + sd.open (&sd);=0A= +=0A= + /* Play the sound. */=0A= + s.play (&s, &sd);=0A= +=0A= + /* Close the input file, if any. */=0A= + if (!STRINGP (s.data))=0A= + {=0A= + emacs_close (s.fd);=0A= + s.fd =3D -1;=0A= + }=0A= +=0A= + /* Close the device. */=0A= + sd.close (&sd);=0A= +=0A= + /* Clean up. */=0A= + current_sound_device =3D NULL;=0A= + current_sound =3D NULL;=0A= + UNGCPRO;=0A= +#else /* WINDOWSNT */=0A= + lo_file=3DFexpand_file_name (attrs[SOUND_FILE], Qnil);=0A= + len=3DXSTRING (lo_file)->size;=0A= + psz_file=3D(char *)alloca (len+1);=0A= + strcpy (psz_file, XSTRING (lo_file)->data);=0A= + if (INTEGERP (attrs[SOUND_VOLUME]))=0A= + {=0A= + ui_volume_tmp=3DXFASTINT (attrs[SOUND_VOLUME]);=0A= + }=0A= + else if (FLOATP (attrs[SOUND_VOLUME]))=0A= + {=0A= + ui_volume_tmp=3D(unsigned long)XFLOAT_DATA = (attrs[SOUND_VOLUME])*100;=0A= + }=0A= + /*=0A= + Based on some experiments I have conducted, a value of 100 or less=0A= + for the sound volume is much too low. You cannot even hear it.=0A= + A value of UINT_MAX indicates that you wish for the sound to played=0A= + at the maximum possible volume. A value of UINT_MAX/2 plays the=0A= + sound at 50% maximum volume. Therefore the value passed to = do_play_sound=0A= + (and thus to waveOutSetVolume must be some fraction of UINT_MAX.=0A= + The following code adjusts the user specified volume level = appropriately.=0A= + */=0A= + if ((ui_volume_tmp > 0) && (ui_volume_tmp <=3D 100))=0A= + {=0A= + ui_volume=3Dui_volume_tmp * (UINT_MAX / 100);=0A= + }=0A= + i_result=3Ddo_play_sound (psz_file, ui_volume);=0A= +#endif /* WINDOWSNT */=0A= + unbind_to (count, Qnil);=0A= + return Qnil;=0A= +}=0A= =0C=0A= /***********************************************************************=0A= Initialization=0A= ------=_NextPart_000_0001_01C28CFB.552BD0D0--