From 18e7a9f3d0c27385f8efeb2b1ef80b3446dca288 Mon Sep 17 00:00:00 2001 From: Po Lu Date: Sun, 23 Jun 2024 16:28:22 +0800 Subject: [PATCH 1/9] Restore functionality on Windows 98 * configure.ac (W32_LIBS): Don't link with -lusp10 on non-Cygwin systems. * src/emacs.c (main): Call globals_of_w32 before the startup directory is initialized. * src/w32.c (maybe_load_unicows_dll): Call load_unicows_dll_for_w32fns. * src/w32.h: Update prototypes. * src/w32fns.c (Fx_create_frame, w32_create_tip_frame): Do not register the Uniscribe font driver when unavailable. (pfnSHFileOperationW): New function pointer. (Fsystem_move_file_to_trash): Load UNICOWS.DLL if not yet loaded. Call SHFileOperationW through said function pointer. (pfnShellExecuteExW): New function pointer. (Fw32_shell_execute) [!CYGWIN]: Load UNICOWS.DLL if not yet loaded. Call ShellExecuteExW through said function pointer. (pfnShell_NotifyIconW): New function pointer. (add_tray_notification, delete_tray_notification): Call Shell_NotifyIconW through said function pointer. (Fw32_notification_notify): Load UNICOWS.DLL. (Fw32_notification_close): Return if Shell_NotifyIconW is unavailable, as when UNICOWS.DLL has yet to be loaded. (load_unicows_dll_for_w32fns): New function. * src/w32notify.c (pfnReadDirectoryChangesW): New function pointer. (watch_completion, remove_watch, Fw32notify_add_watch) (Fw32notify_rm_watch, Fw32notify_valid_p): Call ReadDirectoryChangesW through said function pointer, and assert its presence. (globals_of_w32notify): Load ReadDirectoryChangesW from KERNEL32.DLL. * src/w32uniscribe.c (pfnScriptItemize, pfnScriptShape) (pfnScriptPlace, pfnScriptGetGlyphABCWidth, pfnScriptFreeCache) (pfnScriptGetCMap): New function pointers. (uniscribe_close, uniscribe_shape, uniscribe_encode_char) (uniscribe_check_otf_1): Call Uniscribe functions through the same. (syms_of_w32uniscribe_for_pdumper): Load Uniscribe library and required functions from the same, and if unavailable, return while leaving uniscribe_available intact. On Cygwin, simply assign USP10.DLL functions to the said new function pointers. --- configure.ac | 2 +- src/emacs.c | 8 ++- src/w32.c | 2 + src/w32.h | 1 + src/w32fns.c | 79 +++++++++++++++++++++----- src/w32notify.c | 42 +++++++++----- src/w32uniscribe.c | 134 ++++++++++++++++++++++++++++++++------------- 7 files changed, 199 insertions(+), 69 deletions(-) diff --git a/configure.ac b/configure.ac index f75c0a98820..e4ce59b8a05 100644 --- a/configure.ac +++ b/configure.ac @@ -3133,7 +3133,7 @@ if test "${HAVE_W32}" = "yes"; then NATIVE_IMAGE_API="yes (w32)" W32_OBJ="$W32_OBJ w32image.o" fi - W32_LIBS="$W32_LIBS -lwinmm -lusp10 -lgdi32 -lcomdlg32" + W32_LIBS="$W32_LIBS -lwinmm -lgdi32 -lcomdlg32" W32_LIBS="$W32_LIBS -lmpr -lwinspool -lole32 -lcomctl32" W32_RES_LINK="\$(EMACSRES)" CLIENTRES="emacsclient.res" diff --git a/src/emacs.c b/src/emacs.c index d786bc65141..74a46468933 100644 --- a/src/emacs.c +++ b/src/emacs.c @@ -1406,6 +1406,10 @@ main (int argc, char **argv) the additional call here is harmless.) */ cache_system_info (); #ifdef WINDOWSNT + /* This must be called to initialize w32_unicode_filenames and + is_windows_9x prior to w32_init_current_directory. */ + globals_of_w32 (); + /* On Windows 9X, we have to load UNICOWS.DLL as early as possible, to have non-stub implementations of APIs we need to convert file names between UTF-8 and the system's ANSI codepage. */ @@ -1517,11 +1521,10 @@ main (int argc, char **argv) } } #endif - emacs_wd = emacs_get_current_dir_name (); #ifdef WINDOWSNT initial_wd = emacs_wd; -#endif +#endif /* WINDOWSNT */ #ifdef HAVE_PDUMPER if (dumped_with_pdumper_p ()) pdumper_record_wd (emacs_wd); @@ -2176,7 +2179,6 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem init_atimer (); #ifdef WINDOWSNT - globals_of_w32 (); #ifdef HAVE_W32NOTIFY globals_of_w32notify (); #endif diff --git a/src/w32.c b/src/w32.c index 1c6a56bcbd9..4986d4c6676 100644 --- a/src/w32.c +++ b/src/w32.c @@ -10624,6 +10624,7 @@ maybe_load_unicows_dll (void) pWideCharToMultiByte = (WideCharToMultiByte_Proc) get_proc_addr (ret, "WideCharToMultiByte"); multiByteToWideCharFlags = MB_ERR_INVALID_CHARS; + load_unicows_dll_for_w32fns (ret); return ret; } else @@ -10658,6 +10659,7 @@ maybe_load_unicows_dll (void) multiByteToWideCharFlags = 0; else multiByteToWideCharFlags = MB_ERR_INVALID_CHARS; + load_unicows_dll_for_w32fns (NULL); return LoadLibrary ("Gdi32.dll"); } } diff --git a/src/w32.h b/src/w32.h index cf470ae9901..3dc79dabf4b 100644 --- a/src/w32.h +++ b/src/w32.h @@ -170,6 +170,7 @@ extern void release_listen_threads (void); extern void init_ntproc (int); extern void term_ntproc (int); extern HANDLE maybe_load_unicows_dll (void); +extern void load_unicows_dll_for_w32fns (HMODULE); extern void globals_of_w32 (void); extern void term_timers (void); diff --git a/src/w32fns.c b/src/w32fns.c index b784a9a563d..3d372f1c53f 100644 --- a/src/w32fns.c +++ b/src/w32fns.c @@ -2612,6 +2612,7 @@ my_post_msg (W32Msg * wmsg, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) } #ifdef WINDOWSNT + /* The Windows keyboard hook callback. */ static LRESULT CALLBACK funhook (int code, WPARAM w, LPARAM l) @@ -2688,8 +2689,8 @@ funhook (int code, WPARAM w, LPARAM l) can prevent this by setting the w32-pass-[lr]window-to-system variable to NIL. */ - if ((hs->vkCode == VK_LWIN && !NILP (Vw32_pass_lwindow_to_system)) || - (hs->vkCode == VK_RWIN && !NILP (Vw32_pass_rwindow_to_system))) + if ((hs->vkCode == VK_LWIN && !NILP (Vw32_pass_lwindow_to_system)) + || (hs->vkCode == VK_RWIN && !NILP (Vw32_pass_rwindow_to_system))) { /* Not prevented - Simulate the keypress to the system. */ memset (inputs, 0, sizeof (inputs)); @@ -2704,7 +2705,6 @@ funhook (int code, WPARAM w, LPARAM l) inputs[1].ki.dwFlags = KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP; inputs[1].ki.time = 0; - SendInput (2, inputs, sizeof (INPUT)); } else if (focus != NULL) { @@ -6150,7 +6150,8 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame, if (harfbuzz_available) register_font_driver (&harfbuzz_font_driver, f); #endif - register_font_driver (&uniscribe_font_driver, f); + if (uniscribe_available) + register_font_driver (&uniscribe_font_driver, f); register_font_driver (&w32font_driver, f); gui_default_parameter (f, parameters, Qfont_backend, Qnil, @@ -7227,7 +7228,8 @@ w32_create_tip_frame (struct w32_display_info *dpyinfo, Lisp_Object parms) if (harfbuzz_available) register_font_driver (&harfbuzz_font_driver, f); #endif - register_font_driver (&uniscribe_font_driver, f); + if (uniscribe_available) + register_font_driver (&uniscribe_font_driver, f); register_font_driver (&w32font_driver, f); gui_default_parameter (f, parms, Qfont_backend, Qnil, @@ -8265,6 +8267,8 @@ DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 5, 0, #ifdef WINDOWSNT +static int (WINAPI *pfnSHFileOperationW) (LPSHFILEOPSTRUCTW); + /* Moving files to the system recycle bin. Used by `move-file-to-trash' instead of the default moving to ~/.Trash */ DEFUN ("system-move-file-to-trash", Fsystem_move_file_to_trash, @@ -8276,6 +8280,9 @@ DEFUN ("system-move-file-to-trash", Fsystem_move_file_to_trash, Lisp_Object encoded_file; Lisp_Object operation; + /* Required on Windows 9X. */ + maybe_load_unicows_dll (); + operation = Qdelete_file; if (!NILP (Ffile_directory_p (filename)) && NILP (Ffile_symlink_p (filename))) @@ -8324,7 +8331,10 @@ DEFUN ("system-move-file-to-trash", Fsystem_move_file_to_trash, | FOF_NOERRORUI | FOF_NO_CONNECTED_ELEMENTS; file_op_w.fAnyOperationsAborted = FALSE; - result = SHFileOperationW (&file_op_w); + /* This is stated to exist on all versions of Windows NT Emacs + supports. */ + eassert (pfnSHFileOperationW); + result = (*pfnSHFileOperationW) (&file_op_w); } else { @@ -8389,6 +8399,10 @@ If optional parameter FRAME is not specified, use selected frame. */) return Qnil; } +#ifndef CYGWIN +static BOOL (WINAPI *pfnShellExecuteExW) (LPSHELLEXECUTEINFOW); +#endif /* !CYGWIN */ + DEFUN ("w32-shell-execute", Fw32_shell_execute, Sw32_shell_execute, 2, 4, 0, doc: /* Get Windows to perform OPERATION on DOCUMENT. This is a wrapper around the ShellExecute system function, which @@ -8539,6 +8553,9 @@ a ShowWindow flag: const int file_url_len = sizeof (file_url_str) - 1; int doclen; + /* Required on Windows 9X. */ + maybe_load_unicows_dll (); + if (strncmp (SSDATA (document), file_url_str, file_url_len) == 0) { /* Passing "file:///" URLs to ShellExecute causes shlwapi.dll to @@ -8598,7 +8615,7 @@ a ShowWindow flag: doc_w = xmalloc (doclen * sizeof (wchar_t)); pMultiByteToWideChar (CP_UTF8, multiByteToWideCharFlags, SSDATA (document), -1, doc_w, doclen); - if (use_unicode) + if (use_unicode && pfnShellExecuteExW) { wchar_t current_dir_w[MAX_PATH]; SHELLEXECUTEINFOW shexinfo_w; @@ -8650,7 +8667,7 @@ a ShowWindow flag: shexinfo_w.lpDirectory = current_dir_w; shexinfo_w.nShow = (FIXNUMP (show_flag) ? XFIXNUM (show_flag) : SW_SHOWDEFAULT); - success = ShellExecuteExW (&shexinfo_w); + success = (*pfnShellExecuteExW) (&shexinfo_w); xfree (doc_w); } else @@ -9121,6 +9138,7 @@ and width values are in pixels. menu_bar.cbSize = sizeof (menu_bar); menu_bar.rcBar.right = menu_bar.rcBar.left = 0; menu_bar.rcBar.top = menu_bar.rcBar.bottom = 0; + GetMenuBarInfo (FRAME_W32_WINDOW (f), 0xFFFFFFFD, 0, &menu_bar); single_menu_bar_height = GetSystemMetrics (SM_CYMENU); wrapped_menu_bar_height = GetSystemMetrics (SM_CYMENUSIZE); @@ -10007,6 +10025,8 @@ Internal use only. */) #if defined WINDOWSNT && !defined HAVE_DBUS +static BOOL (WINAPI *pfnShell_NotifyIconW) (DWORD, PNOTIFYICONDATAW); + /*********************************************************************** Tray notifications ***********************************************************************/ @@ -10273,7 +10293,7 @@ add_tray_notification (struct frame *f, const char *icon, const char *tip, } } - if (!Shell_NotifyIconW (NIM_ADD, (PNOTIFYICONDATAW)&nidw)) + if (!(*pfnShell_NotifyIconW) (NIM_ADD, (PNOTIFYICONDATAW)&nidw)) { /* GetLastError returns meaningless results when Shell_NotifyIcon fails. */ @@ -10305,7 +10325,7 @@ delete_tray_notification (struct frame *f, int id) nidw.hWnd = FRAME_W32_WINDOW (f); nidw.uID = id; - if (!Shell_NotifyIconW (NIM_DELETE, (PNOTIFYICONDATAW)&nidw)) + if (!(*pfnShell_NotifyIconW) (NIM_DELETE, (PNOTIFYICONDATAW)&nidw)) { /* GetLastError returns meaningless results when Shell_NotifyIcon fails. */ @@ -10372,8 +10392,8 @@ The following parameters are supported: characters long, and will be truncated if it's longer. Note that versions of Windows before W2K support only `:icon' and `:tip'. -You can pass the other parameters, but they will be ignored on those -old systems. +You can pass the other parameters, but they will be ignored on +those old systems. There can be at most one active notification at any given time. An active notification must be removed by calling `w32-notification-close' @@ -10389,7 +10409,10 @@ usage: (w32-notification-notify &rest PARAMS) */) enum NI_Severity severity; unsigned timeout = 0; - if (nargs == 0) + /* Required on Windows 9X. */ + maybe_load_unicows_dll (); + + if (nargs == 0 || !pfnShell_NotifyIconW) return Qnil; arg_plist = Flist (nargs, args); @@ -10448,7 +10471,7 @@ DEFUN ("w32-notification-close", { struct frame *f = SELECTED_FRAME (); - if (FIXNUMP (id)) + if (FIXNUMP (id) && !pfnShell_NotifyIconW) delete_tray_notification (f, XFIXNUM (id)); return Qnil; @@ -11499,7 +11522,7 @@ globals_of_w32fns (void) get_proc_addr (wtsapi32_lib, "WTSRegisterSessionNotification"); WTSUnRegisterSessionNotification_fn = (WTSUnRegisterSessionNotification_Proc) get_proc_addr (wtsapi32_lib, "WTSUnRegisterSessionNotification"); -#endif +#endif /* WINDOWSNT */ /* Support OS dark mode on Windows 10 version 1809 and higher. See `w32_applytheme' which uses appropriate APIs per version of Windows. @@ -11580,6 +11603,32 @@ Changing the value takes effect only for frames created after the change. */); syms_of_w32uniscribe (); } +#ifdef WINDOWSNT + +/* Initialize pointers to functions whose real implementations exist in + UNICOWS.DLL on Windows 9X. UNICOWS should be a pointer to a loaded + handle referencing UNICOWS.DLL, or NULL on Windows NT systems. */ + +void +load_unicows_dll_for_w32fns (HMODULE unicows) +{ + if (!unicows) + /* The functions following are defined by SHELL32.DLL onw Windows + NT. */ + unicows = GetModuleHandle ("shell32"); + + pfnSHFileOperationW + = (void *) get_proc_addr (unicows, "SHFileOperationW"); + pfnShellExecuteExW + = (void *) get_proc_addr (unicows, "ShellExecuteExW"); +#ifndef HAVE_DBUS + pfnShell_NotifyIconW + = (void *) get_proc_addr (unicows, "Shell_NotifyIconW"); +#endif /* !HAVE_DBUS */ +} + +#endif /* WINDOWSNT */ + #ifdef NTGUI_UNICODE Lisp_Object diff --git a/src/w32notify.c b/src/w32notify.c index c93e8796fe2..1001c85fdbe 100644 --- a/src/w32notify.c +++ b/src/w32notify.c @@ -120,6 +120,10 @@ struct notification { /* Used for communicating notifications to the main thread. */ struct notifications_set *notifications_set_head; +/* Function pointers. */ +static BOOL (WINAPI *pfnReadDirectoryChangesW) (HANDLE, PVOID, DWORD, BOOL, + DWORD, PDWORD, LPOVERLAPPED, + LPOVERLAPPED_COMPLETION_ROUTINE); static Lisp_Object watch_list; /* Signal to the main thread that we have file notifications for it to @@ -252,10 +256,10 @@ watch_completion (DWORD status, DWORD bytes_ret, OVERLAPPED *io_info) /* Calling ReadDirectoryChangesW quickly to watch again for new notifications. */ - if (!ReadDirectoryChangesW (dirwatch->dir, dirwatch->buf, - DIRWATCH_BUFFER_SIZE, dirwatch->subtree, - dirwatch->filter, &_bytes, dirwatch->io_info, - watch_completion)) + if (!(*pfnReadDirectoryChangesW) (dirwatch->dir, dirwatch->buf, + DIRWATCH_BUFFER_SIZE, dirwatch->subtree, + dirwatch->filter, &_bytes, + dirwatch->io_info, watch_completion)) { DebPrint (("ReadDirectoryChangesW error: %lu\n", GetLastError ())); /* If this call fails, it means that the directory is not @@ -270,7 +274,7 @@ watch_completion (DWORD status, DWORD bytes_ret, OVERLAPPED *io_info) /* If we were asked to terminate the thread, then fire the event. */ if (terminate) - SetEvent(dirwatch->terminate); + SetEvent (dirwatch->terminate); } /* Worker routine for the watch thread. */ @@ -284,10 +288,10 @@ watch_worker (LPVOID arg) if (dirwatch->dir) { - bErr = ReadDirectoryChangesW (dirwatch->dir, dirwatch->buf, - DIRWATCH_BUFFER_SIZE, dirwatch->subtree, - dirwatch->filter, &_bytes, - dirwatch->io_info, watch_completion); + bErr = (*pfnReadDirectoryChangesW) (dirwatch->dir, dirwatch->buf, + DIRWATCH_BUFFER_SIZE, dirwatch->subtree, + dirwatch->filter, &_bytes, + dirwatch->io_info, watch_completion); if (!bErr) { DebPrint (("ReadDirectoryChangesW: %lu\n", GetLastError ())); @@ -436,7 +440,7 @@ remove_watch (struct notification *dirwatch) DebPrint (("QueueUserAPC failed (%lu)!\n", GetLastError ())); /* We also signal the thread that it can terminate. */ - SetEvent(dirwatch->terminate); + SetEvent (dirwatch->terminate); /* Wait for the thread to exit. FIXME: is there a better method that is not overly complex? */ @@ -466,7 +470,7 @@ remove_watch (struct notification *dirwatch) CloseHandle (dirwatch->thr); dirwatch->thr = NULL; } - CloseHandle(dirwatch->terminate); + CloseHandle (dirwatch->terminate); xfree (dirwatch->buf); xfree (dirwatch->io_info); xfree (dirwatch->watchee); @@ -575,6 +579,8 @@ generate notifications correctly, though. */) report_file_notify_error ("Watching filesystem events is not supported", Qnil); } + else + eassert (pfnReadDirectoryChangesW); /* filenotify.el always passes us a directory, either the parent directory of a file to be watched, or the directory to be @@ -649,7 +655,7 @@ WATCH-DESCRIPTOR should be an object returned by `w32notify-add-watch'. */) if (!NILP (watch_object)) { watch_list = Fdelete (watch_object, watch_list); - dirwatch = (struct notification *)xmint_pointer (watch_descriptor); + dirwatch = (struct notification *) xmint_pointer (watch_descriptor); if (w32_valid_pointer_p (dirwatch, sizeof(struct notification))) status = remove_watch (dirwatch); } @@ -687,7 +693,7 @@ watch by calling `w32notify-rm-watch' also makes it invalid. */) if (!NILP (watch_object)) { struct notification *dirwatch = - (struct notification *)xmint_pointer (watch_descriptor); + (struct notification *) xmint_pointer (watch_descriptor); if (w32_valid_pointer_p (dirwatch, sizeof(struct notification)) && dirwatch->dir != NULL) return Qt; @@ -699,6 +705,16 @@ watch by calling `w32notify-rm-watch' also makes it invalid. */) void globals_of_w32notify (void) { + HANDLE kernel32 = GetModuleHandle ("kernel32"); + + /* Initialize pointers to IO functions that provide file + notifications. In the event that these are absent, no harm will be + done, since their absence indicates that Emacs is running on + Windows 9X, where file notifications are unavailable at the + outset. */ + pfnReadDirectoryChangesW + = (void *) get_proc_addr (kernel32, "ReadDirectoryChangesW"); + watch_list = Qnil; } diff --git a/src/w32uniscribe.c b/src/w32uniscribe.c index b3112912c76..6e07dfe1c99 100644 --- a/src/w32uniscribe.c +++ b/src/w32uniscribe.c @@ -108,6 +108,31 @@ memq_no_quit (Lisp_Object elt, Lisp_Object list) return (CONSP (list)); } + +/* Uniscribe function pointers. */ +static HRESULT (WINAPI * pfnScriptItemize) (const WCHAR *, + int, + int, + const SCRIPT_CONTROL *, + const SCRIPT_STATE *, + SCRIPT_ITEM *, int *); +static HRESULT (WINAPI * pfnScriptShape) (HDC, SCRIPT_CACHE *, + const WCHAR *, + int, int, SCRIPT_ANALYSIS *, + WORD *, WORD *, SCRIPT_VISATTR *, + int *); +static HRESULT (WINAPI * pfnScriptPlace) (HDC, SCRIPT_CACHE *, + const WORD *, int, + const SCRIPT_VISATTR *, + SCRIPT_ANALYSIS *, + int *, GOFFSET *, ABC *); +static HRESULT (WINAPI * pfnScriptGetGlyphABCWidth) (HDC, SCRIPT_CACHE *, + WORD, ABC *); +static HRESULT (WINAPI * pfnScriptFreeCache) (SCRIPT_CACHE *); +static HRESULT (WINAPI * pfnScriptGetCMap) (HDC, SCRIPT_CACHE *, + const WCHAR *, + int, DWORD, WORD *); + /* Font backend interface implementation. */ static Lisp_Object @@ -202,7 +227,7 @@ uniscribe_close (struct font *font) else #endif if (uniscribe_font->cache) - ScriptFreeCache ((SCRIPT_CACHE) &(uniscribe_font->cache)); + (*pfnScriptFreeCache) ((SCRIPT_CACHE) &(uniscribe_font->cache)); uniscribe_font->cache = NULL; @@ -320,8 +345,8 @@ uniscribe_shape (Lisp_Object lgstring, Lisp_Object direction) max_items = 2; items = xmalloc (sizeof (SCRIPT_ITEM) * max_items + 1); - while ((result = ScriptItemize (chars, nchars, max_items, NULL, NULL, - items, &nitems)) == E_OUTOFMEMORY) + while ((result = (*pfnScriptItemize) (chars, nchars, max_items, NULL, NULL, + items, &nitems)) == E_OUTOFMEMORY) { /* If that wasn't enough, keep trying with one more run. */ max_items++; @@ -344,17 +369,18 @@ uniscribe_shape (Lisp_Object lgstring, Lisp_Object direction) { int nglyphs, nchars_in_run; nchars_in_run = items[i+1].iCharPos - items[i].iCharPos; - /* Force ScriptShape to generate glyphs in the same order as + /* Force (*pfnScriptShape) to generate glyphs in the same order as they are in the input LGSTRING, which is in the logical order. */ items[i].a.fLogicalOrder = 1; /* Context may be NULL here, in which case the cache should be used without needing to select the font. */ - result = ScriptShape (context, (SCRIPT_CACHE) &(uniscribe_font->cache), - chars + items[i].iCharPos, nchars_in_run, - max_glyphs - done_glyphs, &(items[i].a), - glyphs, clusters, attributes, &nglyphs); + result + = (*pfnScriptShape) (context, (SCRIPT_CACHE) &(uniscribe_font->cache), + chars + items[i].iCharPos, nchars_in_run, + max_glyphs - done_glyphs, &(items[i].a), + glyphs, clusters, attributes, &nglyphs); if (result == E_PENDING && !context) { @@ -365,10 +391,12 @@ uniscribe_shape (Lisp_Object lgstring, Lisp_Object direction) context = get_frame_dc (f); old_font = SelectObject (context, FONT_HANDLE (font)); - result = ScriptShape (context, (SCRIPT_CACHE) &(uniscribe_font->cache), - chars + items[i].iCharPos, nchars_in_run, - max_glyphs - done_glyphs, &(items[i].a), - glyphs, clusters, attributes, &nglyphs); + result + = (*pfnScriptShape) (context, + (SCRIPT_CACHE) &(uniscribe_font->cache), + chars + items[i].iCharPos, nchars_in_run, + max_glyphs - done_glyphs, &(items[i].a), + glyphs, clusters, attributes, &nglyphs); } if (result == E_OUTOFMEMORY) @@ -390,9 +418,11 @@ uniscribe_shape (Lisp_Object lgstring, Lisp_Object direction) } else { - result = ScriptPlace (context, (SCRIPT_CACHE) &(uniscribe_font->cache), - glyphs, nglyphs, attributes, &(items[i].a), - advances, offsets, &overall_metrics); + result + = (*pfnScriptPlace) (context, + (SCRIPT_CACHE) &(uniscribe_font->cache), + glyphs, nglyphs, attributes, &(items[i].a), + advances, offsets, &overall_metrics); if (result == E_PENDING && !context) { /* Cache not complete... */ @@ -400,10 +430,11 @@ uniscribe_shape (Lisp_Object lgstring, Lisp_Object direction) context = get_frame_dc (f); old_font = SelectObject (context, FONT_HANDLE (font)); - result = ScriptPlace (context, - (SCRIPT_CACHE) &(uniscribe_font->cache), - glyphs, nglyphs, attributes, &(items[i].a), - advances, offsets, &overall_metrics); + result + = (*pfnScriptPlace) (context, + (SCRIPT_CACHE) &(uniscribe_font->cache), + glyphs, nglyphs, attributes, &(items[i].a), + advances, offsets, &overall_metrics); } if (SUCCEEDED (result)) { @@ -469,7 +500,7 @@ uniscribe_shape (Lisp_Object lgstring, Lisp_Object direction) then updated for each successive glyph in the grapheme cluster. */ /* FIXME: Should we use DIRECTION here instead - of what ScriptItemize guessed? */ + of what (*pfnScriptItemize) guessed? */ if (items[i].a.fRTL) { int j1 = j; @@ -496,7 +527,7 @@ uniscribe_shape (Lisp_Object lgstring, Lisp_Object direction) LGLYPH_SET_ASCENT (lglyph, font->ascent); LGLYPH_SET_DESCENT (lglyph, font->descent); - result = ScriptGetGlyphABCWidth + result = (*pfnScriptGetGlyphABCWidth) (context, (SCRIPT_CACHE) &(uniscribe_font->cache), glyphs[j], &char_metric); if (result == E_PENDING && !context) @@ -505,7 +536,7 @@ uniscribe_shape (Lisp_Object lgstring, Lisp_Object direction) f = XFRAME (selected_frame); context = get_frame_dc (f); old_font = SelectObject (context, FONT_HANDLE (font)); - result = ScriptGetGlyphABCWidth + result = (*pfnScriptGetGlyphABCWidth) (context, (SCRIPT_CACHE) &(uniscribe_font->cache), glyphs[j], &char_metric); } @@ -624,7 +655,8 @@ uniscribe_encode_char (struct font *font, int c) convert surrogate pairs to glyph indexes correctly. */ { items = (SCRIPT_ITEM *) alloca (sizeof (SCRIPT_ITEM) * 2 + 1); - if (SUCCEEDED (ScriptItemize (ch, len, 2, NULL, NULL, items, &nitems))) + if (SUCCEEDED ((*pfnScriptItemize) (ch, len, 2, NULL, NULL, items, + &nitems))) { HRESULT result; /* Surrogates seem to need 2 here, even though only one glyph is @@ -635,14 +667,14 @@ uniscribe_encode_char (struct font *font, int c) SCRIPT_VISATTR attrs[2]; int nglyphs; - /* Force ScriptShape to generate glyphs in the logical + /* Force (*pfnScriptShape) to generate glyphs in the logical order. */ items[0].a.fLogicalOrder = 1; - result = ScriptShape (context, - (SCRIPT_CACHE) &(uniscribe_font->cache), - ch, len, 2, &(items[0].a), - glyphs, clusters, attrs, &nglyphs); + result = (*pfnScriptShape) (context, + (SCRIPT_CACHE) &(uniscribe_font->cache), + ch, len, 2, &(items[0].a), + glyphs, clusters, attrs, &nglyphs); if (result == E_PENDING) { @@ -651,10 +683,11 @@ uniscribe_encode_char (struct font *font, int c) f = XFRAME (selected_frame); context = get_frame_dc (f); old_font = SelectObject (context, FONT_HANDLE (font)); - result = ScriptShape (context, - (SCRIPT_CACHE) &(uniscribe_font->cache), - ch, len, 2, &(items[0].a), - glyphs, clusters, attrs, &nglyphs); + result + = (*pfnScriptShape) (context, + (SCRIPT_CACHE) &(uniscribe_font->cache), + ch, len, 2, &(items[0].a), + glyphs, clusters, attrs, &nglyphs); } if (SUCCEEDED (result) && nglyphs == 1) @@ -670,9 +703,10 @@ uniscribe_encode_char (struct font *font, int c) when shaped. But we still need the return from here to be valid for the shaping engine to be invoked later. */ - result = ScriptGetCMap (context, - (SCRIPT_CACHE) &(uniscribe_font->cache), - ch, len, 0, glyphs); + result + = (*pfnScriptGetCMap) (context, + (SCRIPT_CACHE) &(uniscribe_font->cache), + ch, len, 0, glyphs); if (SUCCEEDED (result) && glyphs[0]) code = glyphs[0]; } @@ -942,7 +976,7 @@ uniscribe_check_otf_1 (HDC context, Lisp_Object script, Lisp_Object lang, no_support: if (cache) - ScriptFreeCache (&cache); + (*pfnScriptFreeCache) (&cache); return ret; } @@ -1504,11 +1538,37 @@ syms_of_w32uniscribe_for_pdumper (void) if (!initialized) return; +#ifdef WINDOWSNT /* Don't register if Uniscribe is not available. */ - HMODULE uniscribe = GetModuleHandle ("usp10"); + HMODULE uniscribe = LoadLibrary ("usp10.dll"); if (!uniscribe) return; + pfnScriptItemize = (void *) get_proc_addr (uniscribe, "ScriptItemize"); + pfnScriptShape = (void *) get_proc_addr (uniscribe, "ScriptShape"); + pfnScriptPlace = (void *) get_proc_addr (uniscribe, "ScriptPlace"); + pfnScriptGetGlyphABCWidth + = (void *) get_proc_addr (uniscribe, "ScriptGetGlyphABCWidth"); + pfnScriptFreeCache + = (void *) get_proc_addr (uniscribe, "ScriptFreeCache"); + pfnScriptGetCMap + = (void *) get_proc_addr (uniscribe, "ScriptGetCMap"); + if (!pfnScriptItemize || !pfnScriptShape || !pfnScriptPlace + || !pfnScriptGetGlyphABCWidth || !pfnScriptFreeCache + || !pfnScriptGetCMap) + { + FreeLibrary (uniscribe); + return; + } +#else /* Cygwin */ + pfnScriptItemize = &ScriptItemize; + pfnScriptShape = &ScriptShape; + pfnScriptPlace = &ScriptPlace; + pfnScriptGetGlyphABCWidth = &ScriptGetGlyphABCWidth; + pfnScriptFreeCache = &ScriptFreeCache; + pfnScriptGetCMap = &ScriptGetCMap; +#endif /* Cygwin */ + uniscribe_available = 1; register_font_driver (&uniscribe_font_driver, NULL); From 8d55b38e2a1212c47bfb9f93a73fa50b9f291609 Mon Sep 17 00:00:00 2001 From: Po Lu Date: Thu, 27 Jun 2024 09:59:57 +0800 Subject: [PATCH 2/9] Fix Cygwin build * src/w32uniscribe.c (syms_of_w32uniscribe_for_pdumper): Define and retrieve handle to USP10.DLL on Cygwin. --- src/w32uniscribe.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/w32uniscribe.c b/src/w32uniscribe.c index 6e07dfe1c99..1763ca5dc34 100644 --- a/src/w32uniscribe.c +++ b/src/w32uniscribe.c @@ -1538,12 +1538,13 @@ syms_of_w32uniscribe_for_pdumper (void) if (!initialized) return; -#ifdef WINDOWSNT /* Don't register if Uniscribe is not available. */ - HMODULE uniscribe = LoadLibrary ("usp10.dll"); + HMODULE uniscribe; if (!uniscribe) return; +#ifdef WINDOWSNT + uniscribe = LoadLibrary ("usp10.dll"); pfnScriptItemize = (void *) get_proc_addr (uniscribe, "ScriptItemize"); pfnScriptShape = (void *) get_proc_addr (uniscribe, "ScriptShape"); pfnScriptPlace = (void *) get_proc_addr (uniscribe, "ScriptPlace"); @@ -1561,15 +1562,16 @@ syms_of_w32uniscribe_for_pdumper (void) return; } #else /* Cygwin */ + uniscribe = GetModuleHandle ("usp10.dll"); pfnScriptItemize = &ScriptItemize; pfnScriptShape = &ScriptShape; pfnScriptPlace = &ScriptPlace; pfnScriptGetGlyphABCWidth = &ScriptGetGlyphABCWidth; pfnScriptFreeCache = &ScriptFreeCache; pfnScriptGetCMap = &ScriptGetCMap; -#endif /* Cygwin */ uniscribe_available = 1; +#endif /* Cygwin */ register_font_driver (&uniscribe_font_driver, NULL); From cbede3d43df99177cc6c2d63a24bbec9b19da451 Mon Sep 17 00:00:00 2001 From: Po Lu Date: Thu, 27 Jun 2024 21:42:19 +0800 Subject: [PATCH 3/9] * src/w32uniscribe.c (syms_of_w32uniscribe_for_pdumper): Typos. --- src/w32uniscribe.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/w32uniscribe.c b/src/w32uniscribe.c index 1763ca5dc34..8e16d6a198c 100644 --- a/src/w32uniscribe.c +++ b/src/w32uniscribe.c @@ -1540,11 +1540,12 @@ syms_of_w32uniscribe_for_pdumper (void) /* Don't register if Uniscribe is not available. */ HMODULE uniscribe; - if (!uniscribe) - return; #ifdef WINDOWSNT uniscribe = LoadLibrary ("usp10.dll"); + if (!uniscribe) + return; + pfnScriptItemize = (void *) get_proc_addr (uniscribe, "ScriptItemize"); pfnScriptShape = (void *) get_proc_addr (uniscribe, "ScriptShape"); pfnScriptPlace = (void *) get_proc_addr (uniscribe, "ScriptPlace"); @@ -1563,6 +1564,9 @@ syms_of_w32uniscribe_for_pdumper (void) } #else /* Cygwin */ uniscribe = GetModuleHandle ("usp10.dll"); + if (!uniscribe) + return; + pfnScriptItemize = &ScriptItemize; pfnScriptShape = &ScriptShape; pfnScriptPlace = &ScriptPlace; From c750fbb539e21f5f8263c853fb9690658fa806cf Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sun, 30 Jun 2024 12:18:22 +0300 Subject: [PATCH 4/9] ; * etc/DEBUG: Advice for debugging Emacs on OpenBSD (bug#71712). --- etc/DEBUG | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/etc/DEBUG b/etc/DEBUG index 4eae090621f..fb2863d5655 100644 --- a/etc/DEBUG +++ b/etc/DEBUG @@ -1157,6 +1157,12 @@ Please refer to the LLDB reference on the web for more information about LLDB. If you already know GDB, you will also find a mapping from GDB commands to corresponding LLDB commands there. +** Debugging Emacs on OpenBSD + +To debug Emacs on OpenBSD, use the 'egdb' command from the 'gdb' +package. This reportedly works both if Emacs was compiled with GCC and +if it was compiled with clang. + ** Debugging Emacs on Android. A script located in the java/ directory automates the procedures From f784d946d44e7a9034ca35a41675dfc0e0c37557 Mon Sep 17 00:00:00 2001 From: Po Lu Date: Sun, 30 Jun 2024 17:37:46 +0800 Subject: [PATCH 5/9] ; Repair corruption in etc/DEBUG * etc/DEBUG: Repair corruption reported by Eli Zaretskii . --- etc/DEBUG | 66 +++++++++++++++++++++++++++---------------------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/etc/DEBUG b/etc/DEBUG index fb2863d5655..06544674e5d 100644 --- a/etc/DEBUG +++ b/etc/DEBUG @@ -1288,39 +1288,39 @@ the crash. The third form is printed when Emacs misuses the JVM in some fashion that is detected by the Android CheckJNI facility. It looks like: -A/art﹕ art/runtime/check_jni.cc:65] JNI DETECTED ERROR IN APPLICATION: ... -A/art﹕ art/runtime/check_jni.cc:65] in call to CallVoidMethodV -A/art﹕ art/runtime/check_jni.cc:65] from void android.os.MessageQueue.nativePollOnce(long, int) -A/art﹕ art/runtime/check_jni.cc:65] "main" prio=5 tid=1 Runnable -A/art﹕ art/runtime/check_jni.cc:65] | group="main" sCount=0 dsCount=0 obj=0x87d30ef0 self=0xb4f07800 -A/art﹕ art/runtime/check_jni.cc:65] | sysTid=18828 nice=-11 cgrp=apps sched=0/0 handle=0xb6fdeec8 -A/art﹕ art/runtime/check_jni.cc:65] | state=R schedstat=( 2249126546 506089308 3210 ) utm=183 stm=41 core=3 HZ=100 -A/art﹕ art/runtime/check_jni.cc:65] | stack=0xbe0c8000-0xbe0ca000 stackSize=8MB -A/art﹕ art/runtime/check_jni.cc:65] | held mutexes= "mutator lock"(shared held) -A/art﹕ art/runtime/check_jni.cc:65] native: #00 pc 00004640 /system/lib/libbacktrace_libc++.so (UnwindCurrent::Unwind(unsigned int, ucontext*)+23) -A/art﹕ art/runtime/check_jni.cc:65] native: #01 pc 00002e8d /system/lib/libbacktrace_libc++.so (Backtrace::Unwind(unsigned int, ucontext*)+8) -A/art﹕ art/runtime/check_jni.cc:65] native: #02 pc 00248381 /system/lib/libart.so (art::DumpNativeStack(std::__1::basic_ostream >&, int, char const*, art::mirror::ArtMethod*)+68) -A/art﹕ art/runtime/check_jni.cc:65] native: #03 pc 0022cd0b /system/lib/libart.so (art::Thread::Dump(std::__1::basic_ostream >&) const+146) -A/art﹕ art/runtime/check_jni.cc:65] native: #04 pc 000b189b /system/lib/libart.so (art::JniAbort(char const*, char const*)+582) -A/art﹕ art/runtime/check_jni.cc:65] native: #05 pc 000b1fd5 /system/lib/libart.so (art::JniAbortF(char const*, char const*, ...)+60) -A/art﹕ art/runtime/check_jni.cc:65] native: #06 pc 000b50e5 /system/lib/libart.so (art::ScopedCheck::ScopedCheck(_JNIEnv*, int, char const*)+1284) -A/art﹕ art/runtime/check_jni.cc:65] native: #07 pc 000bc59f /system/lib/libart.so (art::CheckJNI::CallVoidMethodV(_JNIEnv*, _jobject*, _jmethodID*, std::__va_list)+30) -A/art﹕ art/runtime/check_jni.cc:65] native: #08 pc 00063803 /system/lib/libandroid_runtime.so (???) -A/art﹕ art/runtime/check_jni.cc:65] native: #09 pc 000776bd /system/lib/libandroid_runtime.so (android::NativeDisplayEventReceiver::dispatchVsync(long long, int, unsigned int)+40) -A/art﹕ art/runtime/check_jni.cc:65] native: #10 pc 00077885 /system/lib/libandroid_runtime.so (android::NativeDisplayEventReceiver::handleEvent(int, int, void*)+80) -A/art﹕ art/runtime/check_jni.cc:65] native: #11 pc 00010f6f /system/lib/libutils.so (android::Looper::pollInner(int)+482) -A/art﹕ art/runtime/check_jni.cc:65] native: #12 pc 00011019 /system/lib/libutils.so (android::Looper::pollOnce(int, int*, int*, void**)+92) -A/art﹕ art/runtime/check_jni.cc:65] native: #13 pc 000830c1 /system/lib/libandroid_runtime.so (android::NativeMessageQueue::pollOnce(_JNIEnv*, int)+22) -A/art﹕ art/runtime/check_jni.cc:65] native: #14 pc 000b22d7 /system/framework/arm/boot.oat (Java_android_os_MessageQueue_nativePollOnce__JI+102) -A/art﹕ art/runtime/check_jni.cc:65] at android.os.MessageQueue.nativePollOnce(Native method) -A/art﹕ art/runtime/check_jni.cc:65] at android.os.MessageQueue.next(MessageQueue.java:143) -A/art﹕ art/runtime/check_jni.cc:65] at android.os.Looper.loop(Looper.java:130) -A/art﹕ art/runtime/check_jni.cc:65] at android.app.ActivityThread.main(ActivityThread.java:5832) -A/art﹕ art/runtime/check_jni.cc:65] at java.lang.reflect.Method.invoke!(Native method) -A/art﹕ art/runtime/check_jni.cc:65] at java.lang.reflect.Method.invoke(Method.java:372) -A/art﹕ art/runtime/check_jni.cc:65] at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399) -A/art﹕ art/runtime/check_jni.cc:65] at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194) -A/art﹕ art/runtime/check_jni.cc:65] +A/art: art/runtime/check_jni.cc:65] JNI DETECTED ERROR IN APPLICATION: ... +A/art: art/runtime/check_jni.cc:65] in call to CallVoidMethodV +A/art: art/runtime/check_jni.cc:65] from void android.os.MessageQueue.nativePollOnce(long, int) +A/art: art/runtime/check_jni.cc:65] "main" prio=5 tid=1 Runnable +A/art: art/runtime/check_jni.cc:65] | group="main" sCount=0 dsCount=0 obj=0x87d30ef0 self=0xb4f07800 +A/art: art/runtime/check_jni.cc:65] | sysTid=18828 nice=-11 cgrp=apps sched=0/0 handle=0xb6fdeec8 +A/art: art/runtime/check_jni.cc:65] | state=R schedstat=( 2249126546 506089308 3210 ) utm=183 stm=41 core=3 HZ=100 +A/art: art/runtime/check_jni.cc:65] | stack=0xbe0c8000-0xbe0ca000 stackSize=8MB +A/art: art/runtime/check_jni.cc:65] | held mutexes= "mutator lock"(shared held) +A/art: art/runtime/check_jni.cc:65] native: #00 pc 00004640 /system/lib/libbacktrace_libc++.so (UnwindCurrent::Unwind(unsigned int, ucontext*)+23) +A/art: art/runtime/check_jni.cc:65] native: #01 pc 00002e8d /system/lib/libbacktrace_libc++.so (Backtrace::Unwind(unsigned int, ucontext*)+8) +A/art: art/runtime/check_jni.cc:65] native: #02 pc 00248381 /system/lib/libart.so (art::DumpNativeStack(std::__1::basic_ostream >&, int, char const*, art::mirror::ArtMethod*)+68) +A/art: art/runtime/check_jni.cc:65] native: #03 pc 0022cd0b /system/lib/libart.so (art::Thread::Dump(std::__1::basic_ostream >&) const+146) +A/art: art/runtime/check_jni.cc:65] native: #04 pc 000b189b /system/lib/libart.so (art::JniAbort(char const*, char const*)+582) +A/art: art/runtime/check_jni.cc:65] native: #05 pc 000b1fd5 /system/lib/libart.so (art::JniAbortF(char const*, char const*, ...)+60) +A/art: art/runtime/check_jni.cc:65] native: #06 pc 000b50e5 /system/lib/libart.so (art::ScopedCheck::ScopedCheck(_JNIEnv*, int, char const*)+1284) +A/art: art/runtime/check_jni.cc:65] native: #07 pc 000bc59f /system/lib/libart.so (art::CheckJNI::CallVoidMethodV(_JNIEnv*, _jobject*, _jmethodID*, std::__va_list)+30) +A/art: art/runtime/check_jni.cc:65] native: #08 pc 00063803 /system/lib/libandroid_runtime.so (???) +A/art: art/runtime/check_jni.cc:65] native: #09 pc 000776bd /system/lib/libandroid_runtime.so (android::NativeDisplayEventReceiver::dispatchVsync(long long, int, unsigned int)+40) +A/art: art/runtime/check_jni.cc:65] native: #10 pc 00077885 /system/lib/libandroid_runtime.so (android::NativeDisplayEventReceiver::handleEvent(int, int, void*)+80) +A/art: art/runtime/check_jni.cc:65] native: #11 pc 00010f6f /system/lib/libutils.so (android::Looper::pollInner(int)+482) +A/art: art/runtime/check_jni.cc:65] native: #12 pc 00011019 /system/lib/libutils.so (android::Looper::pollOnce(int, int*, int*, void**)+92) +A/art: art/runtime/check_jni.cc:65] native: #13 pc 000830c1 /system/lib/libandroid_runtime.so (android::NativeMessageQueue::pollOnce(_JNIEnv*, int)+22) +A/art: art/runtime/check_jni.cc:65] native: #14 pc 000b22d7 /system/framework/arm/boot.oat (Java_android_os_MessageQueue_nativePollOnce__JI+102) +A/art: art/runtime/check_jni.cc:65] at android.os.MessageQueue.nativePollOnce(Native method) +A/art: art/runtime/check_jni.cc:65] at android.os.MessageQueue.next(MessageQueue.java:143) +A/art: art/runtime/check_jni.cc:65] at android.os.Looper.loop(Looper.java:130) +A/art: art/runtime/check_jni.cc:65] at android.app.ActivityThread.main(ActivityThread.java:5832) +A/art: art/runtime/check_jni.cc:65] at java.lang.reflect.Method.invoke!(Native method) +A/art: art/runtime/check_jni.cc:65] at java.lang.reflect.Method.invoke(Method.java:372) +A/art: art/runtime/check_jni.cc:65] at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399) +A/art: art/runtime/check_jni.cc:65] at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194) +A/art: art/runtime/check_jni.cc:65] In such situations, the first line explains what infraction Emacs committed, while the ensuing ones print backtraces for each running From 4e22ef870c4b650f29c4441ac51b6a2ac506ea57 Mon Sep 17 00:00:00 2001 From: Robert Church Date: Sun, 30 Jun 2024 12:16:20 +0200 Subject: [PATCH 6/9] Add D-Bus test * test/lisp/net/dbus-tests.el (dbus-test05-register-signal-with-nils): New test. (Bug#69926) --- test/lisp/net/dbus-tests.el | 52 +++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/test/lisp/net/dbus-tests.el b/test/lisp/net/dbus-tests.el index 413901b0205..b3337132fb6 100644 --- a/test/lisp/net/dbus-tests.el +++ b/test/lisp/net/dbus-tests.el @@ -792,6 +792,58 @@ is in progress." ;; Cleanup. (dbus-unregister-service :session dbus--test-service))) +(ert-deftest dbus-test05-register-signal-with-nils () + "Check signal registration for an own service. +SERVICE, PATH, INTERFACE and SIGNAL are ‘nil’. This is interpreted as a +wildcard for the respective argument." + (skip-unless dbus--test-enabled-session-bus) + (dbus-ignore-errors (dbus-unregister-service :session dbus--test-service)) + + (unwind-protect + (let ((member "Member") + (handler #'dbus--test-signal-handler) + registered) + + ;; Register signal handler. + (should + (equal + (setq + registered + (dbus-register-signal + :session nil nil nil nil handler)) + `((:signal :session nil nil) + (nil nil ,handler)))) + + (dbus-register-signal + :session nil dbus--test-path + dbus--test-interface member handler) + (dbus-register-signal + :session dbus--test-service nil + dbus--test-interface member handler) + (dbus-register-signal + :session dbus--test-service dbus--test-path + nil member handler) + (dbus-register-signal + :session dbus--test-service dbus--test-path + dbus--test-interface nil handler) + + ;; Send one argument, basic type. + (setq dbus--test-signal-received nil) + (dbus-send-signal + :session dbus--test-service dbus--test-path + dbus--test-interface member "foo") + (with-timeout (1 (dbus--test-timeout-handler)) + (while (null dbus--test-signal-received) + (read-event nil nil 0.1))) + (should (equal dbus--test-signal-received '("foo"))) + + ;; Unregister signal. + (should (dbus-unregister-object registered)) + (should-not (dbus-unregister-object registered))) + + ;; Cleanup. + (dbus-unregister-service :session dbus--test-service))) + (ert-deftest dbus-test06-register-property () "Check property registration for an own service." (skip-unless dbus--test-enabled-session-bus) From f50167ab95ecd151afab12f9226885599be6cee2 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sun, 30 Jun 2024 15:06:06 +0300 Subject: [PATCH 7/9] ; Update NEWS and corresponding manuals * etc/NEWS: Improve wording and mark entries as approriate. * doc/emacs/buffers.texi (Kill Buffer): Document new commands. * doc/emacs/mini.texi (Completion Options, Completion Commands): Document new completion options and behaviors. --- doc/emacs/buffers.texi | 15 ++++++---- doc/emacs/mini.texi | 20 ++++++++++++++ etc/NEWS | 62 ++++++++++++++++++++++++++++-------------- 3 files changed, 72 insertions(+), 25 deletions(-) diff --git a/doc/emacs/buffers.texi b/doc/emacs/buffers.texi index 2786ff6ad65..eba593f0ec9 100644 --- a/doc/emacs/buffers.texi +++ b/doc/emacs/buffers.texi @@ -313,6 +313,8 @@ Kill buffer @var{buffer} (@code{kill-buffer}). Offer to kill each buffer, one by one. @item M-x kill-matching-buffers Offer to kill all buffers matching a regular expression. +@item M-x kill-matching-buffers-no-ask +Like @code{kill-matching-buffers}, but don't ask for confirmation. @end table @findex kill-buffer @@ -334,13 +336,16 @@ by one. An answer of @kbd{yes} means to kill the buffer, just like with a space, which are used internally by Emacs. @findex kill-matching-buffers +@findex kill-matching-buffers-no-ask The command @kbd{M-x kill-matching-buffers} prompts for a regular expression and kills all buffers whose names match that expression. -@xref{Regexps}. Like @code{kill-some-buffers}, it asks for -confirmation before each kill. This command normally ignores buffers -whose names begin with a space, which are used internally by Emacs. -To kill internal buffers as well, call @code{kill-matching-buffers} -with a prefix argument. +@xref{Regexps}. Like @code{kill-some-buffers}, it asks for confirmation +before each kill. This command normally ignores buffers whose names +begin with a space, which are used internally by Emacs. To kill +internal buffers as well, call @code{kill-matching-buffers} with a +prefix argument. The command @w{@kbd{M-x kill-matching-buffers-no-ask}} +works like @code{kill-matching-buffers}, but doesn't ask for +confirmation before killing each matching buffer. The Buffer Menu feature is also convenient for killing various buffers. @xref{Several Buffers}. diff --git a/doc/emacs/mini.texi b/doc/emacs/mini.texi index 4557f41c3f7..79744967455 100644 --- a/doc/emacs/mini.texi +++ b/doc/emacs/mini.texi @@ -452,6 +452,15 @@ While in the completion list buffer, kill it and delete the window showing it (@code{kill-current-buffer}). @end table +@vindex minibuffer-visible-completions + If the variable @code{minibuffer-visible-completions} is customized to +a non-@code{nil} value, it changes the commands bound to the arrow keys: +instead of moving in the minibuffer, they move between completion +candidates, like meta-arrow keys do by default. Similarly, +@kbd{@key{RET}} selects the current candidate, like @kbd{M-@key{RET}} +does normally. @code{C-g} hides the completion window, but leaves the +minibuffer active, so you can continue typing at the prompt. + @node Completion Exit @subsection Completion Exit @@ -685,6 +694,17 @@ then move to a candidate by cursor motion commands and select it with @code{second-tab}, then the first @kbd{@key{TAB}} will pop up the completions list buffer, and the second one will switch to it. +@findex previous-line-completion +@findex next-line-completion +@vindex completion-auto-wrap + When the window showing the completions is selected, either because +you customized @code{completion-auto-select} or because you switched to +it by typing @kbd{C-x o}, the @kbd{@key{UP}} and @kbd{@key{DOWN}} arrow +keys move by lines between completion candidates; with a prefix numeric +argument, they move that many lines. If @code{completion-auto-wrap} is +non-@code{nil}, these commands will wrap at bottom and top of the +candidate list. + @vindex completion-cycle-threshold If @code{completion-cycle-threshold} is non-@code{nil}, completion commands can cycle through completion alternatives. Normally, if diff --git a/etc/NEWS b/etc/NEWS index d5409d139dc..78dfa00aafe 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -58,6 +58,7 @@ ALSA on these operating systems instead. * Startup Changes in Emacs 30.1 +--- ** On GNU/Linux, Emacs is now the default application for 'org-protocol'. Org mode provides a way to quickly capture bookmarks, notes, and links using 'emacsclient': @@ -71,7 +72,7 @@ arranges for Emacs to be the default application for the 'org-protocol' URI scheme. See the Org mode manual, Info node "(org) Protocols" for more details. ---- ++++ ** New variable lets Lisp code read emacsclient arguments. When '--eval' is passed to emacsclient and Emacs is evaluating each argument, the new variable 'server-eval-args-left' is set to those @@ -84,6 +85,7 @@ escaping (to protect them from the shell). * Incompatible Changes in Emacs 30.1 +--- ** Tree-Sitter modes are now declared as submodes of the non-TS modes. In order to help the use of those Tree-Sitter modes, they are now declared to have the corresponding non-Tree-Sitter mode as an @@ -94,6 +96,7 @@ collections of snippets automatically apply to the new Tree-Sitter modes. Note that those modes still do not inherit from the non-TS mode, so configuration settings installed via mode hooks are not affected. +--- ** Mouse wheel events should now always be 'wheel-up/down/left/right'. At those places where the old 'mouse-4/5/6/7' events could still occur (i.e., X11 input in the absence of XInput2, and 'xterm-mouse-mode'), @@ -124,6 +127,7 @@ to your init file: (advice-add 'completion-at-point :after #'minibuffer-hide-completions) +--- ** The default process filter was rewritten in native code. The round-trip through the Lisp function 'internal-default-process-filter' is skipped when the process filter is @@ -158,6 +162,7 @@ see the variable 'url-request-extra-headers'. * Changes in Emacs 30.1 +--- ** Emacs now supports Unicode Standard version 15.1. +++ @@ -184,20 +189,23 @@ TTY frames. --- ** Support for underline colors on TTY frames. -Colors specified in face underlines will now also be displayed in TTY -frames with the previously mentioned capabilities. +Colors specified in the underline face will now also be displayed on TTY +frames on terminals that support the 'Su' or 'Smulx' capabilities. ++++ ** Modeline elements can now be right-aligned. Anything following the symbol 'mode-line-format-right-align' in 'mode-line-format' will be right-aligned. Exactly where it is right-aligned to is controlled by the new user option 'mode-line-right-align-edge'. +--- ** X selection requests are now handled much faster and asynchronously. This means it should be less necessary to disable the likes of 'select-active-regions' when Emacs is running over a slow network connection. +--- ** Emacs now updates invisible frames that are made visible by a compositor. If an invisible or an iconified frame is shown to the user by the compositing manager, Emacs will now redisplay such a frame even though @@ -209,8 +217,8 @@ example, as part of preview for iconified frames. The only exception is w32notify. +++ -** Image ':map' property is now recomputed when image is transformed. -Now images with clickable maps work as expected after you run commands +** The ':map' property of images is now recomputed when image is transformed. +Images with clickable maps now work as expected after you run commands such as 'image-increase-size', 'image-decrease-size', 'image-rotate', 'image-flip-horizontally', and 'image-flip-vertically'. Set the new user option 'image-recompute-map-p' to nil to prevent Emacs @@ -218,11 +226,13 @@ from recomputing image maps. ** Minibuffer and Completions ++++ *** New commands 'previous-line-completion' and 'next-line-completion'. Bound to '' and '' arrow keys, respectively, they navigate the "*Completions*" buffer vertically by lines, wrapping at the top/bottom when 'completion-auto-wrap' is non-nil. ++++ *** New user option 'minibuffer-visible-completions'. When customized to non-nil, you can use arrow keys in the minibuffer to navigate the completions displayed in the "*Completions*" window. @@ -231,6 +241,7 @@ completions window. When the completions window is not visible, then all these keys have their usual meaning in the minibuffer. This option is supported for in-buffer completion as well. +--- *** Selected completion candidates are deselected on typing. When you type at the minibuffer prompt, the current completion candidate will be un-highlighted, and point in the "*Completions*" window @@ -242,6 +253,7 @@ the minibuffer contents instead. This deselection behavior can be controlled with the new user option 'completion-auto-deselect', which is t by default. ++++ *** New value 'historical' for user option 'completions-sort'. When 'completions-sort' is set to 'historical', completion candidates will be first sorted alphabetically, and then re-sorted by their order @@ -304,6 +316,7 @@ It specifies how 'set-window-configuration' and 'window-state-put' should proceed with windows whose buffer was killed after the corresponding configuration or state was recorded. +--- *** New variable 'window-point-context-set-function'. It can be used to set a context for window point in all windows by 'window-point-context-set' before calling 'current-window-configuration' @@ -336,8 +349,9 @@ window systems other than macOS and GNUstep (Nextstep). +++ *** New global minor mode 'modifier-bar-mode'. -When this minor mode is enabled, buttons representing modifier keys -are displayed along the tool bar. +When this minor mode is enabled, the tool bar displays buttons +representing modifier keys. Clicking on these buttons applies the +corresponding modifiers to the next input event. +++ *** New user option 'tool-bar-always-show-default'. @@ -413,10 +427,12 @@ Switch to a buffer visiting the source of what is being described in This user option controls outline visibility in the output buffer of 'describe-bindings' when 'describe-bindings-outline' is non-nil. +--- *** 'describe-function' shows function inferred type when available. For native compiled Lisp functions 'describe-function' prints (after the signature) the automatically inferred function type as well. +--- *** 'describe-function' now shows the type of the function object. The text used to say things like "car is is a built-in function" whereas it now says "car is a primitive-function" where "primitive-function" is @@ -427,6 +443,7 @@ get information about that type. *** 'C-h m' ('describe-mode') uses outlining by default. Set 'describe-mode-outline' to nil to get back the old behavior. +--- *** 'C-h k' ('describe-key') shows Unicode name. For keybindings which produce single characters via translation or input methods, 'C-h k' now shows the Unicode name of the produced character in @@ -436,6 +453,7 @@ addition to the character itself, e.g. € 'EURO SIGN' (translated from C-x 8 E) +--- *** 'C-h b' ('describe-bindings') shows Unicode names. For keybindings which produce single characters via translation (such as those using the 'C-x 8' or 'A-' prefix, or 'dead-acute', 'dead-grave', @@ -465,8 +483,10 @@ This command can toggle boolean options for the duration of a session. *** New prefix argument for modifying directory-local variables. The commands 'add-dir-local-variable', 'delete-dir-local-variable' and 'copy-file-locals-to-dir-locals' now take an optional prefix argument, -to enter the file name you want to modify. +to enter the file name where you want to modify directory-local +variables. ++++ *** New user option 'safe-local-variable-directories'. This user option names directories in which Emacs will treat all directory-local variables as safe. @@ -474,6 +494,10 @@ directory-local variables as safe. +++ ** CL Print ++++ +*** There is a new chapter in the CL manual documenting cl-print.el. +See the Info node "(cl) Printing". + +++ *** You can expand the "..." truncation everywhere. The code that allowed "..." to be expanded in the "*Backtrace*" buffer @@ -494,13 +518,9 @@ This setting causes byte-compiled functions to be printed in full by 'prin1'. A button on this output can be activated to disassemble the function. -+++ -*** There is a new chapter in the CL manual documenting cl-print.el. -See the Info node "(cl) Printing". - ** Miscellaneous ---- ++++ *** New command 'kill-matching-buffers-no-ask'. This works like 'kill-matching-buffers', but without asking for confirmation. @@ -512,9 +532,9 @@ between the auto save file and the current file. +++ *** 'read-passwd' can toggle the visibility of passwords. -Use 'TAB' in the minibuffer to show or hide the password. Likewise, -there is an icon on the mode-line, which toggles the visibility of the -password when clicking with 'mouse-1'. +Use 'TAB' in the minibuffer to show or hide the password. +Alternatively, click the new show-password icon on the mode-line with +'mouse-1' to toggle the visibility of the password. *** 'advice-remove' is now an interactive command. When called interactively, 'advice-remove' now prompts for an advised @@ -541,8 +561,8 @@ remote buffers. The default is nil. +++ *** New user option 'remote-file-name-access-timeout'. -When a positive number, this option limits the call of 'access-file' -for remote files to this number of seconds. Default is nil. +If a positive number, this option limits the call of 'access-file' +for remote files to that number of seconds. Default is nil. +++ *** New user option 'yes-or-no-prompt'. @@ -554,7 +574,8 @@ This allows the user to customize the prompt that is appended by *** New user option 'menu-bar-close-window'. When non-nil, selecting "Close" from the "File" menu or clicking "Close" in the tool bar will result in the current window being -closed, if possible. +deleted, if possible. The default is nil, and these gestures kill the +buffer shown in the current window, but don't delete the window. --- *** New face 'display-time-date-and-time'. @@ -585,8 +606,9 @@ Homebrew. +++ *** 'write-region-inhibit-fsync' now defaults to t in interactive mode, -as it has in batch mode since Emacs 24. +as it did in batch mode since Emacs 24. +--- *** The default value of 'read-process-output-max' was increased to 65536. +++ From 9b294059d71c20b43a35fd4aaa68e78b23e19d7c Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sun, 30 Jun 2024 17:42:38 +0300 Subject: [PATCH 8/9] Fix documentation for Emacs 30 * etc/NEWS: Mark entries and improve wording. * doc/emacs/dired.texi (Operating on Files): Document 'dired-do-open'. Fix indexing. * doc/emacs/files.texi (Diff Mode): Document 'diff-apply-buffer'. Fix indexing. * doc/emacs/maintaining.texi (Project File Commands) (Project Buffer Commands): Document 'project-any-command'. * doc/emacs/building.texi (Other GDB Buffers): Document the user option 'gdb-display-io-buffer'. (Grep Searching): Document 'grep-use-headings'. * doc/emacs/text.texi (Outline Visibility): Document Outline commands that hide/show by heading regexp. * doc/emacs/killing.texi (Kill Options): Document 'kill-ring-deindent-mode'. * doc/emacs/basic.texi (Continuation Lines): Improve wording. --- doc/emacs/basic.texi | 13 +++----- doc/emacs/building.texi | 12 +++++++ doc/emacs/dired.texi | 9 ++++- doc/emacs/files.texi | 41 +++++++++++++---------- doc/emacs/killing.texi | 7 ++++ doc/emacs/maintaining.texi | 15 +++++++++ doc/emacs/text.texi | 16 +++++++++ etc/NEWS | 67 ++++++++++++++++++++++++++------------ 8 files changed, 132 insertions(+), 48 deletions(-) diff --git a/doc/emacs/basic.texi b/doc/emacs/basic.texi index a2a934ff243..42f5c971e2f 100644 --- a/doc/emacs/basic.texi +++ b/doc/emacs/basic.texi @@ -643,14 +643,11 @@ long, by using Auto Fill mode. @xref{Filling}. Normally, the first character of each continuation line is positioned at the beginning of the screen line where it is displayed. The minor mode @code{visual-wrap-prefix-mode} and its global -(@pxref{Minor Modes}) counterpart -@code{global-visual-wrap-prefix-mode} arranges that continuation lines -be prefixed by slightly adjusted versions of the fill prefixes -(@pxref{Fill Prefix}) of their respective logical lines, so that -indentation characters or the prefixes of source code comments are -replicated across every continuation line, and the appearance of such -comments or indentation is not broken. These prefixes are only shown -on display, and does not change the buffer text in any way. +counterpart (@pxref{Minor Modes}) @code{global-visual-wrap-prefix-mode} +arranges for continuation lines to be indented on display using a fill +prefix (@pxref{Fill Prefix}) automatically computed from each line's +surrounding context. These prefixes are display-only feature, and do +not change the buffer text in any way. Sometimes, you may need to edit files containing many long logical lines, and it may not be practical to break them all up by adding diff --git a/doc/emacs/building.texi b/doc/emacs/building.texi index 38cc0bb67af..1b079c2cef9 100644 --- a/doc/emacs/building.texi +++ b/doc/emacs/building.texi @@ -477,6 +477,14 @@ non-@code{nil} if the buffer is to be saved). Any other non-@code{nil} value means that all buffers should be saved without asking. The default is @code{ask}. +@vindex grep-use-headings +@vindex grep-heading@r{ face} + By default, grep matches are shown with the file names prefixed to +each line. But if the variable @code{grep-use-headings} is customized +to a non-@code{nil} value, the matches are split into sections, one +section for each file with matches, and the file names are shown in the +section headings using a special face @code{grep-heading}. + @findex grep-find @findex find-grep The command @kbd{M-x grep-find} (also available as @kbd{M-x @@ -1313,6 +1321,10 @@ of output to its standard output, you may wish to separate its I/O from interaction with GDB. Use the command @w{@kbd{M-x gdb-display-io-buffer}} to show a window with a buffer to which Emacs redirects the input and output from the program you are debugging. +However, if the variable @code{gdb-display-io-buffer} is @code{nil}, +Emacs will not create nor display a separate I/O buffer, but will +instead redirect the program's interaction to the GUD interaction +buffer. @findex gdb-display-registers-buffer @item Registers Buffer diff --git a/doc/emacs/dired.texi b/doc/emacs/dired.texi index c251a6dc2be..cf57350743f 100644 --- a/doc/emacs/dired.texi +++ b/doc/emacs/dired.texi @@ -803,9 +803,9 @@ The @code{dired-keep-marker-copy} user option controls how this command handles file marking. The default is to mark all new copies of files with a @samp{C} mark. -@item D @findex dired-do-delete @kindex D @r{(Dired)} +@item D Delete the specified files (@code{dired-do-delete}). This is like the shell command @code{rm}. @@ -813,6 +813,13 @@ Like the other commands in this section, this command operates on the @emph{marked} files, or the next @var{n} files. By contrast, @kbd{x} (@code{dired-do-flagged-delete}) deletes all @dfn{flagged} files. +@findex dired-do-open +@kindex E @r{(Dired)} +@item E +``Open'' the specified files using an external program. The program is +selected according to the system conventions, as determined by the +variable @code{shell-command-guess-open}. + @findex dired-do-rename @kindex R @r{(Dired)} @cindex renaming files (in Dired) diff --git a/doc/emacs/files.texi b/doc/emacs/files.texi index dfacf501650..709cb0910e6 100644 --- a/doc/emacs/files.texi +++ b/doc/emacs/files.texi @@ -1633,8 +1633,8 @@ commands to visit the corresponding source locations. manipulate and apply parts of patches: @table @kbd -@item M-n @findex diff-hunk-next +@item M-n Move to the next hunk-start (@code{diff-hunk-next}). With prefix argument @var{n}, move forward to the @var{n}th next hunk. @@ -1645,45 +1645,50 @@ you set @code{diff-refine} to the symbol @code{navigation}, Diff mode only refines the hunk you move to with this command or with @code{diff-hunk-prev}. -@item M-p @findex diff-hunk-prev +@item M-p Move to the previous hunk-start (@code{diff-hunk-prev}). With prefix argument @var{n}, move back to the @var{n}th previous hunk. Like @kbd{M-n}, this command refines the hunk you move to if you set @code{diff-refine} to the symbol @code{navigation}. -@item M-@} @findex diff-file-next +@item M-@} Move to the next file-start, in a multi-file patch (@code{diff-file-next}). With prefix argument @var{n}, move forward to the start of the @var{n}th next file. -@item M-@{ @findex diff-file-prev +@item M-@{ Move to the previous file-start, in a multi-file patch (@code{diff-file-prev}). With prefix argument @var{n}, move back to the start of the @var{n}th previous file. -@item M-k @findex diff-hunk-kill +@item M-k Kill the hunk at point (@code{diff-hunk-kill}). -@item M-K @findex diff-file-kill +@item M-K In a multi-file patch, kill the current file part. (@code{diff-file-kill}). -@item C-c C-a @findex diff-apply-hunk @cindex patches, applying +@item C-c C-a Apply this hunk to its target file (@code{diff-apply-hunk}). With a prefix argument of @kbd{C-u}, revert this hunk, i.e.@: apply the reverse of the hunk, which changes the ``new'' version into the ``old'' version. If @code{diff-jump-to-old-file} is non-@code{nil}, apply the hunk to the ``old'' version of the file instead. -@item C-c C-b +@findex diff-apply-buffer +@item C-c @key{RET} a +Apply all the hunks in the buffer (@code{diff-apply-buffer}). If the +diffs were applied successfully, save the changed buffers. + @findex diff-refine-hunk +@item C-c C-b Highlight the changes of the hunk at point with a finer granularity (@code{diff-refine-hunk}). This allows you to see exactly which parts of each changed line were actually changed. @@ -1693,9 +1698,9 @@ By default, Diff mode refines hunks as Emacs displays them, so you may find this command useful if you customize @code{diff-refine} to a non-default value. -@item C-c C-c @findex diff-goto-source @vindex diff-jump-to-old-file +@item C-c C-c Go to the source file and line corresponding to this hunk (@code{diff-goto-source}). By default, this jumps to the ``new'' version of the file, the one shown first on the file header. @@ -1710,20 +1715,20 @@ this jumps to the work file by default. With a prefix argument, jump to the ``old'' revision of the file (@pxref{Old Revisions}), when point is on the old line, or otherwise jump to the ``new'' revision. -@item C-c C-e @findex diff-ediff-patch +@item C-c C-e Start an Ediff session with the patch (@code{diff-ediff-patch}). @xref{Top, Ediff, Ediff, ediff, The Ediff Manual}. -@item C-c C-n @findex diff-restrict-view +@item C-c C-n Restrict the view to the current hunk (@code{diff-restrict-view}). @xref{Narrowing}. With a prefix argument, restrict the view to the current file of a multiple-file patch. To widen again, use @kbd{C-x n w} (@code{widen}). -@item C-c C-r @findex diff-reverse-direction +@item C-c C-r Reverse the direction of comparison for the entire buffer (@code{diff-reverse-direction}). With a prefix argument, reverse the direction only inside the current region (@pxref{Mark}). Reversing @@ -1731,8 +1736,8 @@ the direction means changing the hunks and the file-start headers to produce a patch that would change the ``new'' version into the ``old'' one. -@item C-c C-s @findex diff-split-hunk +@item C-c C-s Split the hunk at point (@code{diff-split-hunk}) into two separate hunks. This inserts a hunk header and modifies the header of the current hunk. This command is useful for manually editing patches, @@ -1743,35 +1748,35 @@ produced by the @option{-c} or @option{--context} options to @command{diff}, first convert the buffer to the unified diff format with @kbd{C-c C-u}. -@item C-c C-d @findex diff-unified->context +@item C-c C-d Convert the entire buffer to the @dfn{context diff format} (@code{diff-unified->context}). With a prefix argument, convert only the hunks within the region. -@item C-c C-u @findex diff-context->unified +@item C-c C-u Convert the entire buffer to unified diff format (@code{diff-context->unified}). With a prefix argument, convert unified format to context format. When the mark is active, convert only the hunks within the region. -@item C-c C-l @findex diff-refresh-hunk +@item C-c C-l Re-generate the current hunk (@code{diff-refresh-hunk}). -@item C-c C-w @vindex diff-ignore-whitespace-switches @findex diff-ignore-whitespace-hunk +@item C-c C-w Re-generate the current hunk, disregarding changes in whitespace. With a non-@code{nil} prefix arg, re-generate all the hunks (@code{diff-ignore-whitespace-hunk}). This calls @code{diff-command} with @code{diff-ignore-whitespace-switches}, which defaults to @samp{-b}, meaning ignore changes in whitespace only. -@item C-x 4 A @findex diff-add-change-log-entries-other-window @findex add-change-log-entry-other-window@r{, in Diff mode} +@item C-x 4 A Generate a ChangeLog entry, like @kbd{C-x 4 a} does (@pxref{Change Log}), for each one of the hunks (@code{diff-add-change-log-entries-other-window}). This creates a diff --git a/doc/emacs/killing.texi b/doc/emacs/killing.texi index 57adc037cb7..62f72763ac6 100644 --- a/doc/emacs/killing.texi +++ b/doc/emacs/killing.texi @@ -302,6 +302,13 @@ a pure white space string to the kill ring, you can say: non-@code{nil} value, identical subsequent kills yield a single kill-ring entry, without duplication. +@findex kill-ring-deindent-mode + If you enable the minor mode @code{kill-ring-deindent-mode}, text +saved to the kill-ring will have its indentation decreased by the amount +of indentation of the first saved line. That is, if the first line of +the saved text was indented @var{n} columns, this mode will remove that +number of columns from the indentation of each saved line. + @node Yanking @section Yanking @cindex moving text diff --git a/doc/emacs/maintaining.texi b/doc/emacs/maintaining.texi index 64d77fb88a5..f4752fa2b29 100644 --- a/doc/emacs/maintaining.texi +++ b/doc/emacs/maintaining.texi @@ -1850,6 +1850,9 @@ Run shell command in the current project's root directory @item C-x p & Run shell command asynchronously in the current project's root directory (@code{project-async-shell-command}). +@item C-x p o +Run the next command in the current project +(@code{project-any-command}). @end table Emacs provides commands for handling project files conveniently. @@ -1946,6 +1949,11 @@ directory. @xref{Top,Eshell,Eshell, eshell, Eshell: The Emacs Shell}. The command @kbd{C-x p &} (@code{project-async-shell-command}) runs @code{async-shell-command} in the current project's root directory. +@findex project-any-command + Finally, the command @kbd{C-x p o} (@code{project-any-command}) will +run the next command you type, whether related to files or not, in the +current project. + @node Project Buffer Commands @subsection Project Commands That Operate on Buffers @@ -1958,6 +1966,9 @@ List the project buffers (@code{project-list-buffers}). @item C-x p k Kill all live buffers that belong to the current project (@code{project-kill-buffers}). +@item C-x p o +Run the next command in the current project +(@code{project-any-command}). @end table @findex project-switch-to-buffer @@ -1986,6 +1997,10 @@ project that satisfy any of @code{project-kill-buffer-conditions}. If @code{project-kill-buffers-display-buffer-list} is non-@code{nil}, the buffers to be killed will be displayed first. + Finally, the command @kbd{C-x p o} (@code{project-any-command}) will +run the next command you type, whether related to buffers or not, in the +current project. + @node Switching Projects @subsection Switching Projects diff --git a/doc/emacs/text.texi b/doc/emacs/text.texi index 1d1065c45c2..8abaeafcf33 100644 --- a/doc/emacs/text.texi +++ b/doc/emacs/text.texi @@ -1208,6 +1208,12 @@ Hide everything except the top @var{n} levels of heading lines Hide everything except for the heading or body that point is in, plus the headings leading up from there to the top level of the outline (@code{outline-hide-other}). +@item C-c / h @var{regexp} @key{RET} +Hide bodies of headings that match @var{regexp} +(@code{outline-hide-by-heading-regexp}). +@item C-c / s @var{regexp} @key{RET} +Show bodies of headings that match @var{regexp} +(@code{outline-show-by-heading-regexp}). @end table @findex outline-hide-entry @@ -1253,6 +1259,16 @@ headers leading up from there to top level in the outline) and the top level headings. It also reveals body lines preceding the first heading in the buffer. +@findex outline-hide-by-heading-regexp +@findex outline-show-by-heading-regexp +@kindex C-c / h @r{(Outline mode)} +@kindex C-c / s @r{(Outline mode)} + The command @kbd{C-c / h} (@code{outline-hide-by-heading-regexp}) +prompts for a regular expression, and hides all the body lines of +headings which match the regular expression. The command @kbd{C-c / s} +likewise prompts for a regular expression, and reveals the bodies of +matching headings. + @findex outline-hide-body @findex outline-show-all @kindex C-c C-t @r{(Outline mode)} diff --git a/etc/NEWS b/etc/NEWS index 78dfa00aafe..a6eda6afddd 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -635,11 +635,11 @@ buffers. (This minor mode is the 'adaptive-wrap' ELPA package renamed and lightly edited for inclusion in Emacs.) ---- ++++ ** New global minor mode 'kill-ring-deindent-mode'. When enabled, text being saved to the kill ring will be de-indented by the column number at its start. For example, saving the entire -function call within: +function call within an indented block: foo () { @@ -648,16 +648,16 @@ foo () argument_3_compute ()); } -will save: +will save this to the kill ring: long_function_with_several_arguments (argument_1_compute (), argument_2_compute (), argument_3_compute ()) -to the kill ring, omitting the two columns of extra indentation that -would otherwise be present in the second and third lines of the -function call. +This omits the two columns of extra indentation that would otherwise be +copied from the second and third lines and saved to the kill ring. +--- ** New command 'replace-regexp-as-diff'. It reads a regexp to search for and a string to replace with, then displays a buffer with replacements as diffs. After reviewing the @@ -728,6 +728,7 @@ whereas if the mouse pointer is in the left half of a glyph, point will be put in front the buffer position corresponding to that glyph. By default this is disabled. +--- ** New pre-defined values for 'electric-quote-chars'. The available customization options for 'electric-quote-chars' have been updated with common pairs of quotation characters, including "‘", "’", @@ -735,7 +736,7 @@ updated with common pairs of quotation characters, including "‘", "’", The default is unchanged. +++ -** 'M-TAB' now invokes 'completion-at-point' also in Text mode. +** 'M-TAB' now invokes 'completion-at-point' in Text mode. By default, Text mode no longer binds 'M-TAB' to 'ispell-complete-word'. Instead, this mode arranges for 'completion-at-point', globally bound to 'M-TAB', to perform word completion as well. You can have Text mode @@ -786,14 +787,17 @@ These languages are spoken in Pakistan and Afghanistan. *** New input method "english-colemak". This input method supports the Colemak keyboard layout. +--- *** Additional 'C-x 8' key translations for "æ" and "Æ". These characters can now be input with 'C-x 8 a e' and 'C-x 8 A E', respectively, in addition to the existing translations 'C-x 8 / e' and 'C-x 8 / E'. +--- *** New 'C-x 8' key translations for "low" quotes "„", and "‚". These can now be entered with 'C-x , "' and 'C-x , ''. +--- *** New German language 'C-x 8' key translations for quotation marks. The characters "„", "“", and "”" can now be entered with 'C-x 8 v', 'C-x 8 b' and 'C-x 8 n'. The single versions "‚", "‘", and "’" can now @@ -801,6 +805,7 @@ be entered with 'C-x 8 V', 'C-x 8 B' and 'C-x 8 N'. These characters are used for the official German quoting style. Using them requires activating German language support via 'iso-transl-set-language'. +--- *** "latin-prefix" and "latin-postfix" quotation marks additions. These input methods can now produce single, double and "low" left and right quotation marks: @@ -810,17 +815,20 @@ right quotation marks: by using "[", "]", and "," for "left", "right", and "low" respectively to modify "'" and """. +--- *** "latin-prefix" and "latin-postfix" guillemets support. These input methods can now produce single guillemets "‹" and "›". For "latin-prefix" use "~~<" and "~~>", for "latin-postfix" use "<~" and ">~". Double guillemets ("«" and "»") were already supported. +--- *** New French language 'C-x 8' key translations for "‹" and "›". These characters can now be entered using 'C-x 8 ~ <' and 'C-x 8 ~ >' respectively, after activating French language support via 'iso-transl-set-language'. Double guillemets were already supported via 'C-x 8 <' and 'C-x 8 >' +--- *** Additional 'C-x 8' key translation for Euro "€" currency symbol. This can now be entered using 'C-x 8 E' in addition to the existing 'C-x 8 * E' translation. @@ -830,11 +838,12 @@ This can now be entered using 'C-x 8 E' in addition to the existing ** Outline mode ++++ *** New commands to show/hide outlines by regexp. -'/ h' ('outline-hide-by-heading-regexp') asks for a regexp and then +'C-c / h' ('outline-hide-by-heading-regexp') asks for a regexp and then hides the body lines of all outlines whose heading lines match the -regexp. '/ s' ('outline-show-by-heading-regexp') does the same but -shows the matched outlines. +regexp. 'C-c / s' ('outline-show-by-heading-regexp') does the inverse: +it shows the bodies of outlines that matched a regexp. +++ *** 'outline-minor-mode' is supported in tree-sitter major modes. @@ -850,6 +859,7 @@ This user option associates manual names with URLs. It affects the Emacs-included manuals are set. Further associations can be added for arbitrary Info manuals. +--- *** Emacs can now display Info manuals compressed with 'lzip'. This requires the 'lzip' program to be installed on your system. @@ -881,7 +891,7 @@ If you want to get back the old behavior, set the user option to the value (setopt gdb-locals-table-row-config `((type . 0) (name . 0) (value . ,gdb-locals-value-limit))) ---- ++++ *** New user option 'gdb-display-io-buffer'. If this is nil, 'M-x gdb' will neither create nor display a separate buffer for the I/O of the program being debugged, but will instead @@ -890,11 +900,13 @@ default is t, to preserve previous behavior. ** Grep ++++ *** New user option 'grep-use-headings'. When non-nil, the output of Grep is split into sections, one for each file, instead of having file names prefixed to each line. It is equivalent to the "--heading" option of some tools such as 'git grep' and 'rg'. The headings are displayed using the new 'grep-heading' face. +The default is nil. ** Compilation mode @@ -904,6 +916,7 @@ This is because it partly acts by modifying other rules which may occasionally be surprising. It can be re-enabled by adding 'omake' to 'compilation-error-regexp-alist'. +--- *** Lua errors and stack traces are now recognized. Compilation mode now recognizes Lua language errors and stack traces. Every Lua error is recognized as a compilation error, and every Lua @@ -917,22 +930,26 @@ When non-nil, display the name of the current project on the mode line. Clicking 'mouse-1' on the project name pops up the project menu. The default value is nil. +--- *** New user option 'project-file-history-behavior'. Customizing it to 'relativize' makes commands like 'project-find-file' and 'project-find-dir' display previous history entries relative to the current project. +-- *** New user option 'project-key-prompt-style'. The look of the key prompt in the project switcher has been changed slightly. To get the previous one, set this option to 'brackets'. +--- *** 'project-try-vc' tries harder to find the responsible VCS. When 'project-vc-extra-root-markers' is non-nil, and causes a -subdirectory project to be detected which is not a VCS root, we now -additionally traverse the parent directories until a VCS root is found +subdirectory project to be detected which is not a VCS root, Project now +additionally traverses the parent directories until a VCS root is found (if any), so that the ignore rules for that repository are used, and the file listing's performance is still optimized. ++++ *** New commands 'project-any-command' and 'project-prefix-or-any-command'. The former is now bound to 'C-x p o' by default. The latter is designed primarily for use as a value of @@ -970,15 +987,16 @@ With this value only the revision number is displayed on the mode-line. *** Obsolete command 'vc-switch-backend' re-added as 'vc-change-backend'. The command was previously obsoleted and unbound in Emacs 28. +--- *** Support for viewing VC change history across renames. -When a fileset's VC change history ('C-x v l') ends at a rename, we -now print the old name(s) and a button which jumps to their history. -Git and Hg are supported. Naturally, 'vc-git-print-log-follow' should -be nil for this to work (or '--follow' should not be in -'vc-hg-print-log-switches', in Hg's case). Unlike when the '--follow' -switch is used, commands to see the diff of the old revision ('d'), -check out an old file version ('f') or annotate it right away ('a'), -also work on revisions which precede renames. +When a fileset's VC change history ends at a rename, ('C-x v l') now +prints the old name(s) and shows a button which jumps to the history of +the files under the old names. This feature is supported for Git and +Hg. Naturally, 'vc-git-print-log-follow' should be nil for this to work +(or '--follow' should not be in 'vc-hg-print-log-switches', in Hg's +case). Unlike when the '--follow' switch is used, commands to see the +diff of the old revision ('d'), to check out an old file version ('f') +or to annotate it ('a'), also work on revisions which precede renames. --- *** 'vc-annotate' now abbreviates the Git revision in the buffer name. @@ -986,6 +1004,7 @@ When using the Git backend, 'vc-annotate' will use an abbreviated revision identifier in its buffer name. To restore the previous behavior, set 'vc-annotate-use-short-revision' to nil. +--- *** New option 'vc-git-file-name-changes-switches'. It allows tweaking the thresholds for rename and copy detection. @@ -1011,6 +1030,7 @@ This allows changing which type of whitespace changes are ignored when regenerating hunks with 'diff-ignore-whitespace-hunk'. Defaults to the previously hard-coded "-b". ++++ *** New command 'diff-apply-buffer' bound to 'C-c RET a'. It applies the diff in the entire diff buffer and saves all modified file buffers. @@ -1025,6 +1045,7 @@ It also controls how to move point when encountering a boundary (e.g., if every line is visible, invoking 'dired-next-line' at the last line will move to the first line). The default is nil. +--- *** New user option 'dired-filename-display-length'. It is an integer representing the maximum display length of filenames. The middle part of a filename whose length exceeds the restriction is @@ -1032,6 +1053,7 @@ hidden and an ellipsis is displayed instead. A value of 'window' means using the right edge of window as the display restriction. The default is nil. +--- *** New user option 'shell-command-guess-functions'. It defines how to populate a list of commands available for 'M-!', 'M-&', '!', '&' and the context menu "Open With" @@ -1040,16 +1062,19 @@ based on marked files in Dired. Possible backends are and a universal command such as "open" or "start" that delegates to the OS. ++++ *** New command 'dired-do-open'. This command is bound to 'E' (mnemonics "External"). Also it can be used by clicking "Open" in the context menu; it "opens" the marked or clicked on files according to the OS conventions. For example, on systems supporting XDG, this runs 'xdg-open' on the files. ++++ *** New variable 'dired-guess-shell-alist-optional'. It contains commands for external viewers and players for various media formats, moved to this list from 'dired-guess-shell-alist-default'. +--- *** The default value of 'dired-omit-size-limit' was increased. After performance improvements to omitting in large directories, the new default value is 300k, up from 100k. This means 'dired-omit-mode' will From 64851d101a854e00c68f3e9259d70777e7b26cb2 Mon Sep 17 00:00:00 2001 From: Po Lu Date: Sun, 30 Jun 2024 23:11:19 +0800 Subject: [PATCH 9/9] Improve Android "adaptive icon" * java/res/drawable/emacs_background.xml: * java/res/drawable/emacs_foreground.xml: Transform borders and gradient colors to better align with the original. --- java/res/drawable/emacs_background.xml | 28 +++++++++++++++----------- java/res/drawable/emacs_foreground.xml | 24 +++++++++------------- 2 files changed, 25 insertions(+), 27 deletions(-) diff --git a/java/res/drawable/emacs_background.xml b/java/res/drawable/emacs_background.xml index 448ca48d1cb..c6b6decc3b0 100644 --- a/java/res/drawable/emacs_background.xml +++ b/java/res/drawable/emacs_background.xml @@ -21,22 +21,26 @@ along with GNU Emacs. If not, see . --> xmlns:aapt="http://schemas.android.com/aapt" android:width="108dp" android:height="108dp" - android:viewportWidth="512" - android:viewportHeight="512"> - + android:viewportWidth="108" + android:viewportHeight="108"> + - + - + + diff --git a/java/res/drawable/emacs_foreground.xml b/java/res/drawable/emacs_foreground.xml index d4d71f8e29a..06a03240e28 100644 --- a/java/res/drawable/emacs_foreground.xml +++ b/java/res/drawable/emacs_foreground.xml @@ -21,19 +21,13 @@ along with GNU Emacs. If not, see . --> xmlns:aapt="http://schemas.android.com/aapt" android:width="108dp" android:height="108dp" - android:viewportWidth="512" - android:viewportHeight="512"> - - - + android:viewportWidth="108" + android:viewportHeight="108"> +