From cd06d173a602bf0aa8a227ff1626dc70013fe480 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Mon, 28 Jan 2019 17:24:04 +0200 Subject: [PATCH] Fix bug with face-id after restoring from pdump * src/xfaces.c (init_xfaces): New function. * src/emacs.c (main) [HAVE_PDUMPER]: If dumped with pdumper, call init_xfaces. (Bug#34226) * src/lisp.h (init_xfaces) [HAVE_PDUMPER]: Add prototype. * test/lisp/faces-tests.el (faces--test-face-id): New test for bug#34226. --- src/emacs.c | 5 +++++ src/lisp.h | 3 +++ src/xfaces.c | 40 ++++++++++++++++++++++++++++++++++++++++ test/lisp/faces-tests.el | 9 +++++++++ 4 files changed, 57 insertions(+) diff --git a/src/emacs.c b/src/emacs.c index 2acee8e6fea..d6b8a87c723 100644 --- a/src/emacs.c +++ b/src/emacs.c @@ -1484,6 +1484,11 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem running_asynch_code = 0; init_random (); +#ifdef HAVE_PDUMPER + if (dumped_with_pdumper_p ()) + init_xfaces (); +#endif + #if defined HAVE_JSON && !defined WINDOWSNT init_json (); #endif diff --git a/src/lisp.h b/src/lisp.h index c5631e28453..5159f050a49 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -4606,6 +4606,9 @@ extern void syms_of_w32cygwinx (void); extern Lisp_Object Vface_alternative_font_family_alist; extern Lisp_Object Vface_alternative_font_registry_alist; extern void syms_of_xfaces (void); +#ifdef HAVE_PDUMPER +extern void init_xfaces (void); +#endif #ifdef HAVE_X_WINDOWS /* Defined in xfns.c. */ diff --git a/src/xfaces.c b/src/xfaces.c index cffa89e1f39..7facb13b76c 100644 --- a/src/xfaces.c +++ b/src/xfaces.c @@ -6507,6 +6507,46 @@ DEFUN ("show-face-resources", Fshow_face_resources, Sshow_face_resources, Initialization ***********************************************************************/ +#ifdef HAVE_PDUMPER +/* All the faces defined during loadup are recorded in + face-new-frame-defaults, with the last face first in the list. We + need to set next_lface_id to the next face ID number, so that any + new faces defined in this session will have face IDs different from + those defined during loadup. We also need to set up the + lface_id_to_name[] array for the faces that were defined during + loadup. */ +void +init_xfaces (void) +{ + if (CONSP (Vface_new_frame_defaults)) + { + Lisp_Object lface = XCAR (Vface_new_frame_defaults); + if (CONSP (lface)) + { + /* The first face in the list is the last face defined + during loadup. Compute how many faces are there, and + allocate the lface_id_to_name[] array. */ + Lisp_Object lface_id = Fget (XCAR (lface), Qface); + lface_id_to_name_size = next_lface_id = XFIXNAT (lface_id) + 1; + lface_id_to_name = xnmalloc (next_lface_id, sizeof *lface_id_to_name); + /* Store the last face. */ + lface_id_to_name[next_lface_id - 1] = lface; + + /* Store the rest of the faces. */ + Lisp_Object tail; + for (tail = XCDR (Vface_new_frame_defaults); CONSP (tail); + tail = XCDR (tail)) + { + lface = XCAR (tail); + int face_id = XFIXNAT (Fget (XCAR (lface), Qface)); + eassert (face_id < lface_id_to_name_size); + lface_id_to_name[face_id] = lface; + } + } + } +} +#endif + void syms_of_xfaces (void) { diff --git a/test/lisp/faces-tests.el b/test/lisp/faces-tests.el index 4447dd7b309..f00c93cedcb 100644 --- a/test/lisp/faces-tests.el +++ b/test/lisp/faces-tests.el @@ -60,5 +60,14 @@ (should (equal (background-color-at-point) "black")) (should (equal (foreground-color-at-point) "black")))) +(ert-deftest faces--test-face-id () + ;; Face ID of 0 is the 'default' face; no face should have the same ID. + (should (> (face-id 'faces--test1) 0)) + ;; 'tooltip' is the last face defined by preloaded packages, so any + ;; face we define in Emacs should have a face ID greater than that, + ;; since the ID of a face is just its index in the array that maps + ;; face IDs to faces. + (should (> (face-id 'faces--test1) (face-id 'tooltip)))) + (provide 'faces-tests) ;;; faces-tests.el ends here -- 2.39.5