* How to walk a Lisp_String? @ 2022-09-01 15:34 Manuel Giraud 2022-09-01 15:42 ` Stefan Monnier 2022-09-01 15:42 ` Eli Zaretskii 0 siblings, 2 replies; 31+ messages in thread From: Manuel Giraud @ 2022-09-01 15:34 UTC (permalink / raw) To: emacs-devel Hi, Some context: As discussed with Po Lu (a month or two ago), I'd like to use some of the emacs' face machinery to render entries of Lucid menus. I'm at a point where I'd like to walk a struct Lisp_String one «character» at a time. Of course, I should be able to handle multi-byte Lisp_String. How could I do that? Thanks. -- Manuel Giraud ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: How to walk a Lisp_String? 2022-09-01 15:34 How to walk a Lisp_String? Manuel Giraud @ 2022-09-01 15:42 ` Stefan Monnier 2022-09-01 15:42 ` Eli Zaretskii 1 sibling, 0 replies; 31+ messages in thread From: Stefan Monnier @ 2022-09-01 15:42 UTC (permalink / raw) To: Manuel Giraud; +Cc: emacs-devel > I'm at a point where I'd like to walk a struct Lisp_String one > «character» at a time. Of course, I should be able to handle multi-byte > Lisp_String. How could I do that? SDATA gives you a pointer to the actual bytes of the string, and then you can use `string_char_and_length` to read a char along with its size in bytes (you have to keep track of your "charpos" and "bytepos" separately). Stefan ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: How to walk a Lisp_String? 2022-09-01 15:34 How to walk a Lisp_String? Manuel Giraud 2022-09-01 15:42 ` Stefan Monnier @ 2022-09-01 15:42 ` Eli Zaretskii 2022-09-01 15:49 ` Eli Zaretskii 1 sibling, 1 reply; 31+ messages in thread From: Eli Zaretskii @ 2022-09-01 15:42 UTC (permalink / raw) To: Manuel Giraud; +Cc: emacs-devel > From: Manuel Giraud <manuel@ledu-giraud.fr> > Date: Thu, 01 Sep 2022 17:34:23 +0200 > > I'm at a point where I'd like to walk a struct Lisp_String one > «character» at a time. Of course, I should be able to handle multi-byte > Lisp_String. How could I do that? Use fetch_string_char_advance. ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: How to walk a Lisp_String? 2022-09-01 15:42 ` Eli Zaretskii @ 2022-09-01 15:49 ` Eli Zaretskii 2022-09-01 20:45 ` Manuel Giraud 0 siblings, 1 reply; 31+ messages in thread From: Eli Zaretskii @ 2022-09-01 15:49 UTC (permalink / raw) To: manuel; +Cc: emacs-devel > Date: Thu, 01 Sep 2022 18:42:07 +0300 > From: Eli Zaretskii <eliz@gnu.org> > Cc: emacs-devel@gnu.org > > > I'm at a point where I'd like to walk a struct Lisp_String one > > «character» at a time. Of course, I should be able to handle multi-byte > > Lisp_String. How could I do that? > > Use fetch_string_char_advance. Btw, my suggestion would be to describe your preliminary design ideas here before you decide how to implement them. E.g., it is not clear to me why you'd need to walk strings character by character in order to use the face machinery. I'm probably missing something. ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: How to walk a Lisp_String? 2022-09-01 15:49 ` Eli Zaretskii @ 2022-09-01 20:45 ` Manuel Giraud 2022-09-02 1:08 ` Po Lu 2022-09-02 6:43 ` Eli Zaretskii 0 siblings, 2 replies; 31+ messages in thread From: Manuel Giraud @ 2022-09-01 20:45 UTC (permalink / raw) To: Eli Zaretskii; +Cc: emacs-devel Eli Zaretskii <eliz@gnu.org> writes: [...] > Btw, my suggestion would be to describe your preliminary design ideas > here before you decide how to implement them. E.g., it is not clear > to me why you'd need to walk strings character by character in order > to use the face machinery. I'm probably missing something. Sure, good idea. I'm working into lwlib only. So I've made a function to get the frame of the menu widget (mw). I'm also converting the char* display_string of each menu entry to a Lisp_String with make_string (note: I don't know if I should have done that but it seems the way to get a proper multi-byte string from a char*). Finally, I'd like to walk this Lisp_String and call FACE_FOR_CHAR for each charater of this frame. And then be able to call XftDrawStringUtf8 (or XmbDrawString) on each substring/font pair. WDYT? -- Manuel Giraud ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: How to walk a Lisp_String? 2022-09-01 20:45 ` Manuel Giraud @ 2022-09-02 1:08 ` Po Lu 2022-09-02 6:32 ` Eli Zaretskii 2022-09-02 6:51 ` Manuel Giraud 2022-09-02 6:43 ` Eli Zaretskii 1 sibling, 2 replies; 31+ messages in thread From: Po Lu @ 2022-09-02 1:08 UTC (permalink / raw) To: Manuel Giraud; +Cc: Eli Zaretskii, emacs-devel Manuel Giraud <manuel@ledu-giraud.fr> writes: > Finally, I'd like to walk this Lisp_String and call FACE_FOR_CHAR for > each charater of this frame. And then be able to call XftDrawStringUtf8 > (or XmbDrawString) on each substring/font pair. WDYT? That won't work correctly since glyphs do not correspond to characters. After you obtain the substring containing characters that can be displayed with a single font, you should pass it to the font driver's `shape' function, and then give the resulting glyphs and offsets to XftDrawGlyphs. Using XftDrawStringUtf8 is a bad idea, along with any other "UTF-8" interface provided by an X library. They simply don't work very well, and cannot handle complicated things such as character compositions and shaping. Using XmbDrawString in conjunction with the Emacs face machinery is probably a bad idea too, since both have differing notions of "fontset" and "font". ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: How to walk a Lisp_String? 2022-09-02 1:08 ` Po Lu @ 2022-09-02 6:32 ` Eli Zaretskii 2022-09-02 8:27 ` Po Lu 2022-09-02 6:51 ` Manuel Giraud 1 sibling, 1 reply; 31+ messages in thread From: Eli Zaretskii @ 2022-09-02 6:32 UTC (permalink / raw) To: Po Lu; +Cc: manuel, emacs-devel > From: Po Lu <luangruo@yahoo.com> > Cc: Eli Zaretskii <eliz@gnu.org>, emacs-devel@gnu.org > Date: Fri, 02 Sep 2022 09:08:10 +0800 > > After you obtain the substring containing characters that can be > displayed with a single font Do menu items use different fonts and colors? Can you give an example of such menu items? If each menu item always uses the same face, then face information can be retrieved once for each menu item. That includes both colors and font information. ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: How to walk a Lisp_String? 2022-09-02 6:32 ` Eli Zaretskii @ 2022-09-02 8:27 ` Po Lu 2022-09-02 10:36 ` Eli Zaretskii 0 siblings, 1 reply; 31+ messages in thread From: Po Lu @ 2022-09-02 8:27 UTC (permalink / raw) To: Eli Zaretskii; +Cc: manuel, emacs-devel Eli Zaretskii <eliz@gnu.org> writes: > Do menu items use different fonts and colors? Can you give an example > of such menu items? No, menu items do not. But we still need to retrieve the faces generated separately by redisplay anyway (for non-ASCII characters), because we want menu items to be able to display multilingual text. ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: How to walk a Lisp_String? 2022-09-02 8:27 ` Po Lu @ 2022-09-02 10:36 ` Eli Zaretskii 2022-09-02 11:03 ` Po Lu 0 siblings, 1 reply; 31+ messages in thread From: Eli Zaretskii @ 2022-09-02 10:36 UTC (permalink / raw) To: Po Lu; +Cc: manuel, emacs-devel > From: Po Lu <luangruo@yahoo.com> > Cc: manuel@ledu-giraud.fr, emacs-devel@gnu.org > Date: Fri, 02 Sep 2022 16:27:11 +0800 > > Eli Zaretskii <eliz@gnu.org> writes: > > > Do menu items use different fonts and colors? Can you give an example > > of such menu items? > > No, menu items do not. But we still need to retrieve the faces > generated separately by redisplay anyway (for non-ASCII characters), > because we want menu items to be able to display multilingual text. I don't think I understand what you are saying. If each menu item uses a single font and single color, then it will use a single face as well, regardless of the scripts used by the item's text, right? ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: How to walk a Lisp_String? 2022-09-02 10:36 ` Eli Zaretskii @ 2022-09-02 11:03 ` Po Lu 2022-09-02 11:15 ` Eli Zaretskii 0 siblings, 1 reply; 31+ messages in thread From: Po Lu @ 2022-09-02 11:03 UTC (permalink / raw) To: Eli Zaretskii; +Cc: manuel, emacs-devel Eli Zaretskii <eliz@gnu.org> writes: > I don't think I understand what you are saying. If each menu item > uses a single font and single color, then it will use a single face as > well, regardless of the scripts used by the item's text, right? Isn't a different face automatically realized for non-ASCII characters containing the correct font for those characters whenever they are encountered by redisplay? ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: How to walk a Lisp_String? 2022-09-02 11:03 ` Po Lu @ 2022-09-02 11:15 ` Eli Zaretskii 2022-09-02 12:48 ` Po Lu 0 siblings, 1 reply; 31+ messages in thread From: Eli Zaretskii @ 2022-09-02 11:15 UTC (permalink / raw) To: Po Lu; +Cc: manuel, emacs-devel > From: Po Lu <luangruo@yahoo.com> > Cc: manuel@ledu-giraud.fr, emacs-devel@gnu.org > Date: Fri, 02 Sep 2022 19:03:00 +0800 > > Eli Zaretskii <eliz@gnu.org> writes: > > > I don't think I understand what you are saying. If each menu item > > uses a single font and single color, then it will use a single face as > > well, regardless of the scripts used by the item's text, right? > > Isn't a different face automatically realized for non-ASCII characters > containing the correct font for those characters whenever they are > encountered by redisplay? AFAIK, only if the so-called "ascii_font" of the default face doesn't support those non-ASCII characters. ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: How to walk a Lisp_String? 2022-09-02 11:15 ` Eli Zaretskii @ 2022-09-02 12:48 ` Po Lu 2022-09-02 13:17 ` Eli Zaretskii 0 siblings, 1 reply; 31+ messages in thread From: Po Lu @ 2022-09-02 12:48 UTC (permalink / raw) To: Eli Zaretskii; +Cc: manuel, emacs-devel Eli Zaretskii <eliz@gnu.org> writes: > AFAIK, only if the so-called "ascii_font" of the default face doesn't > support those non-ASCII characters. Well, that is a situation we want to support in menus. ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: How to walk a Lisp_String? 2022-09-02 12:48 ` Po Lu @ 2022-09-02 13:17 ` Eli Zaretskii 0 siblings, 0 replies; 31+ messages in thread From: Eli Zaretskii @ 2022-09-02 13:17 UTC (permalink / raw) To: Po Lu; +Cc: manuel, emacs-devel > From: Po Lu <luangruo@yahoo.com> > Cc: manuel@ledu-giraud.fr, emacs-devel@gnu.org > Date: Fri, 02 Sep 2022 20:48:24 +0800 > > Eli Zaretskii <eliz@gnu.org> writes: > > > AFAIK, only if the so-called "ascii_font" of the default face doesn't > > support those non-ASCII characters. > > Well, that is a situation we want to support in menus. This is a situation that won't happen if every menu item uses a single font. If you use several different fonts in the same menu item, you will get ugly display. ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: How to walk a Lisp_String? 2022-09-02 1:08 ` Po Lu 2022-09-02 6:32 ` Eli Zaretskii @ 2022-09-02 6:51 ` Manuel Giraud 2022-09-02 7:20 ` Eli Zaretskii 2022-09-02 8:31 ` Po Lu 1 sibling, 2 replies; 31+ messages in thread From: Manuel Giraud @ 2022-09-02 6:51 UTC (permalink / raw) To: Po Lu; +Cc: Eli Zaretskii, emacs-devel Po Lu <luangruo@yahoo.com> writes: > Manuel Giraud <manuel@ledu-giraud.fr> writes: > >> Finally, I'd like to walk this Lisp_String and call FACE_FOR_CHAR for >> each charater of this frame. And then be able to call XftDrawStringUtf8 >> (or XmbDrawString) on each substring/font pair. WDYT? > > That won't work correctly since glyphs do not correspond to > characters. > > After you obtain the substring containing characters that can be > displayed with a single font, you should pass it to the font driver's > `shape' function, and then give the resulting glyphs and offsets to > XftDrawGlyphs. Thanks for those hints. What is a "font driver's `shape' function"? > Using XftDrawStringUtf8 is a bad idea, along with any other "UTF-8" > interface provided by an X library. They simply don't work very well, > and cannot handle complicated things such as character compositions and > shaping. Ok. I've said XftDrawStringUtf8 because this is what is currently used in lwlib for cairo or xft. > Using XmbDrawString in conjunction with the Emacs face machinery is > probably a bad idea too, since both have differing notions of "fontset" > and "font". Yes, I think that this design could be for cairo and xft only and that XmbDrawString/XDrawString should stay as they are. -- Manuel Giraud ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: How to walk a Lisp_String? 2022-09-02 6:51 ` Manuel Giraud @ 2022-09-02 7:20 ` Eli Zaretskii 2022-09-02 8:31 ` Po Lu 1 sibling, 0 replies; 31+ messages in thread From: Eli Zaretskii @ 2022-09-02 7:20 UTC (permalink / raw) To: Manuel Giraud; +Cc: luangruo, emacs-devel > From: Manuel Giraud <manuel@ledu-giraud.fr> > Cc: Eli Zaretskii <eliz@gnu.org>, emacs-devel@gnu.org > Date: Fri, 02 Sep 2022 08:51:34 +0200 > > Thanks for those hints. What is a "font driver's `shape' function"? This: font->driver->shape where 'font' is a pointer to 'struct font'. See font.c for how it is used. ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: How to walk a Lisp_String? 2022-09-02 6:51 ` Manuel Giraud 2022-09-02 7:20 ` Eli Zaretskii @ 2022-09-02 8:31 ` Po Lu 1 sibling, 0 replies; 31+ messages in thread From: Po Lu @ 2022-09-02 8:31 UTC (permalink / raw) To: Manuel Giraud; +Cc: Eli Zaretskii, emacs-devel Manuel Giraud <manuel@ledu-giraud.fr> writes: > Po Lu <luangruo@yahoo.com> writes: > >> Manuel Giraud <manuel@ledu-giraud.fr> writes: >> >>> Finally, I'd like to walk this Lisp_String and call FACE_FOR_CHAR for >>> each charater of this frame. And then be able to call XftDrawStringUtf8 >>> (or XmbDrawString) on each substring/font pair. WDYT? >> >> That won't work correctly since glyphs do not correspond to >> characters. >> >> After you obtain the substring containing characters that can be >> displayed with a single font, you should pass it to the font driver's >> `shape' function, and then give the resulting glyphs and offsets to >> XftDrawGlyphs. > > Thanks for those hints. What is a "font driver's `shape' function"? See i.e. xftfont_shape in xftfont.c. > Ok. I've said XftDrawStringUtf8 because this is what is currently used > in lwlib for cairo or xft. That is definitely a bad thing. The Cairo emulation of XftDrawStringUtf8 uses the Cairo toy text API, which is something that the Cairo developers tell you not to use: The functions with text in their name form cairo's toy text API. The toy API takes UTF-8 encoded text and is limited in its functionality to rendering simple left-to-right text with no advanced features. That means for example that most complex scripts like Hebrew, Arabic, and Indic scripts are out of question. No kerning or correct positioning of diacritical marks either. The font selection is pretty limited too and doesn't handle the case that the selected font does not cover the characters in the text. This set of functions are really that, a toy text API, for testing and demonstration purposes. Any serious application should avoid them. The Xft function itself is much worse than the Cairo emulation. ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: How to walk a Lisp_String? 2022-09-01 20:45 ` Manuel Giraud 2022-09-02 1:08 ` Po Lu @ 2022-09-02 6:43 ` Eli Zaretskii 2022-09-02 7:18 ` Manuel Giraud 1 sibling, 1 reply; 31+ messages in thread From: Eli Zaretskii @ 2022-09-02 6:43 UTC (permalink / raw) To: Manuel Giraud; +Cc: emacs-devel > From: Manuel Giraud <manuel@ledu-giraud.fr> > Cc: emacs-devel@gnu.org > Date: Thu, 01 Sep 2022 22:45:12 +0200 > > I'm working into lwlib only. So I've made a function to get the frame > of the menu widget (mw). I'm also converting the char* display_string > of each menu entry to a Lisp_String with make_string (note: I don't know > if I should have done that but it seems the way to get a proper > multi-byte string from a char*). make_multibyte_string is better, I think. And I don't think I understand how you get the Lisp string to have the face information. The original C char* string cannot have that information as part of the string's data, so where will the face data for the Lisp string come from? > Finally, I'd like to walk this Lisp_String and call FACE_FOR_CHAR for > each charater of this frame. And then be able to call XftDrawStringUtf8 > (or XmbDrawString) on each substring/font pair. WDYT? Po Lu answered about the XftDrawStringUtf8 part. For the faces part, I think face_at_string_position is a better interface. It returns a face ID, from which you can get to the corresponding 'struct face' via FACE_FROM_ID. ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: How to walk a Lisp_String? 2022-09-02 6:43 ` Eli Zaretskii @ 2022-09-02 7:18 ` Manuel Giraud 2022-09-02 7:30 ` Eli Zaretskii 0 siblings, 1 reply; 31+ messages in thread From: Manuel Giraud @ 2022-09-02 7:18 UTC (permalink / raw) To: Eli Zaretskii; +Cc: emacs-devel Eli Zaretskii <eliz@gnu.org> writes: >> From: Manuel Giraud <manuel@ledu-giraud.fr> >> Cc: emacs-devel@gnu.org >> Date: Thu, 01 Sep 2022 22:45:12 +0200 >> >> I'm working into lwlib only. So I've made a function to get the frame >> of the menu widget (mw). I'm also converting the char* display_string >> of each menu entry to a Lisp_String with make_string (note: I don't know >> if I should have done that but it seems the way to get a proper >> multi-byte string from a char*). > > make_multibyte_string is better, I think. make_string seems to be a higher level interface: it calls make_unibyte_string or make_multibyte_string whether the string is uni- or multi-byte. > And I don't think I understand how you get the Lisp string to have the > face information. The original C char* string cannot have that > information as part of the string's data, so where will the face data > for the Lisp string come from? I don't understand your question. I thought it was the job of FACE_FOR_CHAR: you give it a char and a frame and it returns the face for this char in this frame. What am I missing? [...] > For the faces part, I think face_at_string_position is a better > interface. It returns a face ID, from which you can get to the > corresponding 'struct face' via FACE_FROM_ID. Thanks, it is a much better interface. -- Manuel Giraud ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: How to walk a Lisp_String? 2022-09-02 7:18 ` Manuel Giraud @ 2022-09-02 7:30 ` Eli Zaretskii 2022-09-02 8:56 ` Manuel Giraud 0 siblings, 1 reply; 31+ messages in thread From: Eli Zaretskii @ 2022-09-02 7:30 UTC (permalink / raw) To: Manuel Giraud; +Cc: emacs-devel > From: Manuel Giraud <manuel@ledu-giraud.fr> > Cc: emacs-devel@gnu.org > Date: Fri, 02 Sep 2022 09:18:59 +0200 > > >> I'm working into lwlib only. So I've made a function to get the frame > >> of the menu widget (mw). I'm also converting the char* display_string > >> of each menu entry to a Lisp_String with make_string (note: I don't know > >> if I should have done that but it seems the way to get a proper > >> multi-byte string from a char*). > > > > make_multibyte_string is better, I think. > > make_string seems to be a higher level interface: it calls > make_unibyte_string or make_multibyte_string whether the string is uni- > or multi-byte. Why would you need to create a unibyte string? More importantly, why would you trust make_string to make the decision that is right for your purposes? > > And I don't think I understand how you get the Lisp string to have the > > face information. The original C char* string cannot have that > > information as part of the string's data, so where will the face data > > for the Lisp string come from? > > I don't understand your question. I thought it was the job of > FACE_FOR_CHAR: you give it a char and a frame and it returns the face > for this char in this frame. What am I missing? Before you could ask Emacs what is the face of a particular character of a Lisp string, some code should place the face information on that string. In Lisp, you do that by calling 'propertize' or similar APIs. If you don't place the face information on a Lisp string, how can you expect the string to have it? ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: How to walk a Lisp_String? 2022-09-02 7:30 ` Eli Zaretskii @ 2022-09-02 8:56 ` Manuel Giraud 2022-09-02 10:52 ` Eli Zaretskii 0 siblings, 1 reply; 31+ messages in thread From: Manuel Giraud @ 2022-09-02 8:56 UTC (permalink / raw) To: Eli Zaretskii; +Cc: emacs-devel Eli Zaretskii <eliz@gnu.org> writes: [...] >> > make_multibyte_string is better, I think. >> >> make_string seems to be a higher level interface: it calls >> make_unibyte_string or make_multibyte_string whether the string is uni- >> or multi-byte. > > Why would you need to create a unibyte string? More importantly, why > would you trust make_string to make the decision that is right for > your purposes? Because it was written by Emacs' hackers… more seriously, for the purpose of menu entries, I think that most strings will be unibyte ASCII strings. But I thought I needed a Lisp_String in order to use some other emacs interfaces. >> > And I don't think I understand how you get the Lisp string to have the >> > face information. The original C char* string cannot have that >> > information as part of the string's data, so where will the face data >> > for the Lisp string come from? >> >> I don't understand your question. I thought it was the job of >> FACE_FOR_CHAR: you give it a char and a frame and it returns the face >> for this char in this frame. What am I missing? > > Before you could ask Emacs what is the face of a particular character > of a Lisp string, some code should place the face information on that > string. In Lisp, you do that by calling 'propertize' or similar > APIs. If you don't place the face information on a Lisp string, how > can you expect the string to have it? This code : --8<---------------cut here---------------start------------->8--- static int face_upto (Lisp_Object frame, struct Lisp_String *string, int start, int *face_id) { struct frame *f = XFRAME (frame); struct face *face = FACE_FROM_ID (f, DEFAULT_FACE_ID); int mychar = 128517; *face_id = FACE_FOR_CHAR (f, face, mychar, -1, Qnil); face = FACE_FROM_ID_OR_NULL (f, *face_id); if (face && face->font) fprintf(stderr, ">>> %d %s\n", mychar, SDATA (face->font->props[FONT_NAME_INDEX])); mychar = 'c'; *face_id = FACE_FOR_CHAR (f, face, mychar, -1, Qnil); face = FACE_FROM_ID_OR_NULL (f, *face_id); if (face && face->font) fprintf(stderr, ">>> %d %s\n", mychar, SDATA (face->font->props[FONT_NAME_INDEX])); return 0; } --8<---------------cut here---------------end--------------->8--- called from xlwmenu.c/display_menu_item with the retrieved frame works for me and displays this: --8<---------------cut here---------------start------------->8--- >>> 128517 -GOOG-Noto Color Emoji-regular-normal-normal-*-13-*-*-*-m-0-iso10646-1 >>> 99 -UW -Ttyp0-regular-normal-normal-*-13-*-*-*-m-*-iso10646-1 --8<---------------cut here---------------end--------------->8--- But I guess I should propertized those menu strings with the menu face and then use face_at_string_position. That's right? -- Manuel Giraud ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: How to walk a Lisp_String? 2022-09-02 8:56 ` Manuel Giraud @ 2022-09-02 10:52 ` Eli Zaretskii 2022-09-02 11:40 ` Manuel Giraud 0 siblings, 1 reply; 31+ messages in thread From: Eli Zaretskii @ 2022-09-02 10:52 UTC (permalink / raw) To: Manuel Giraud; +Cc: emacs-devel > From: Manuel Giraud <manuel@ledu-giraud.fr> > Cc: emacs-devel@gnu.org > Date: Fri, 02 Sep 2022 10:56:56 +0200 > > > Why would you need to create a unibyte string? More importantly, why > > would you trust make_string to make the decision that is right for > > your purposes? > > Because it was written by Emacs' hackers… more seriously, for the > purpose of menu entries, I think that most strings will be unibyte ASCII > strings. ASCII strings can be unibyte or multibyte, Emacs does TRT with both. So you don't need to worry about that. > But I thought I needed a Lisp_String in order to use some > other emacs interfaces. Depends on the interface. > > Before you could ask Emacs what is the face of a particular character > > of a Lisp string, some code should place the face information on that > > string. In Lisp, you do that by calling 'propertize' or similar > > APIs. If you don't place the face information on a Lisp string, how > > can you expect the string to have it? > > This code : > --8<---------------cut here---------------start------------->8--- > static int > face_upto (Lisp_Object frame, struct Lisp_String *string, int start, int *face_id) > { > struct frame *f = XFRAME (frame); > struct face *face = FACE_FROM_ID (f, DEFAULT_FACE_ID); > int mychar = 128517; > > *face_id = FACE_FOR_CHAR (f, face, mychar, -1, Qnil); > face = FACE_FROM_ID_OR_NULL (f, *face_id); > if (face && face->font) > fprintf(stderr, ">>> %d %s\n", mychar, > SDATA (face->font->props[FONT_NAME_INDEX])); > > > mychar = 'c'; > *face_id = FACE_FOR_CHAR (f, face, mychar, -1, Qnil); > face = FACE_FROM_ID_OR_NULL (f, *face_id); > if (face && face->font) > fprintf(stderr, ">>> %d %s\n", mychar, > SDATA (face->font->props[FONT_NAME_INDEX])); > > return 0; > } > --8<---------------cut here---------------end--------------->8--- > > called from xlwmenu.c/display_menu_item with the retrieved frame works > for me and displays this: You probably modified display_menu_item, because I see no Lisp_String objects there no or Lisp_Object frame. So I still don't understand how you intend to put face information on your Lisp strings, nor even how you produce those Lisp strings in a function that currently manipulates only C data types, without any Emacs-specific Lisp data types. In any case, what you did above is show the font that Emacs will use for a particular character on a particular frame. It has nothing to do with the string or its faces. That should be obvious given the fact that none of APIs you call accept the string as its argument. > But I guess I should propertized those menu strings with the menu face > and then use face_at_string_position. That's right? At least, yes. And then I'd expect the currently active (a.k.a. "selected") menu item to have a different face from the other items, so that the active menu item stands out on display and provides a visual feedback for the user moving the mouse to select menu items. ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: How to walk a Lisp_String? 2022-09-02 10:52 ` Eli Zaretskii @ 2022-09-02 11:40 ` Manuel Giraud 2022-09-02 12:51 ` Po Lu 2022-09-02 13:08 ` Eli Zaretskii 0 siblings, 2 replies; 31+ messages in thread From: Manuel Giraud @ 2022-09-02 11:40 UTC (permalink / raw) To: Eli Zaretskii; +Cc: emacs-devel Eli Zaretskii <eliz@gnu.org> writes: >> From: Manuel Giraud <manuel@ledu-giraud.fr> >> Cc: emacs-devel@gnu.org >> Date: Fri, 02 Sep 2022 10:56:56 +0200 >> >> > Why would you need to create a unibyte string? More importantly, why >> > would you trust make_string to make the decision that is right for >> > your purposes? >> >> Because it was written by Emacs' hackers… more seriously, for the >> purpose of menu entries, I think that most strings will be unibyte ASCII >> strings. > > ASCII strings can be unibyte or multibyte, Emacs does TRT with both. > So you don't need to worry about that. Duly noted. >> But I thought I needed a Lisp_String in order to use some >> other emacs interfaces. > > Depends on the interface. For instance, face_at_string_position or fetch_string_char_advance 😉 [...] > You probably modified display_menu_item, because I see no Lisp_String > objects there no or Lisp_Object frame. Yes obviously. Because I was trying to discuss the design (as you suggested) but also, with informations from you, Po and Stefan, trying to *do* something about it. > So I still don't understand how you intend to put face information on > your Lisp strings, I'm still clueless about this. You said that I have to propertize them so I think there is a C interface for this too. > nor even how you produce those Lisp strings in a function that > currently manipulates only C data types, without any Emacs-specific > Lisp data types. But I'm using Emacs-specific Lisp data types (and Emacs interfaces)! To produce the Lisp strings from char *, I've used make_string. [...] > At least, yes. And then I'd expect the currently active > (a.k.a. "selected") menu item to have a different face from the other > items, so that the active menu item stands out on display and provides > a visual feedback for the user moving the mouse to select menu items. You're right. I guess that I'd have to introduce a menu-selected face. But from where I am now, it will at a final stage. -- Manuel Giraud ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: How to walk a Lisp_String? 2022-09-02 11:40 ` Manuel Giraud @ 2022-09-02 12:51 ` Po Lu 2022-09-02 15:07 ` Manuel Giraud 2022-09-02 13:08 ` Eli Zaretskii 1 sibling, 1 reply; 31+ messages in thread From: Po Lu @ 2022-09-02 12:51 UTC (permalink / raw) To: Manuel Giraud; +Cc: Eli Zaretskii, emacs-devel Manuel Giraud <manuel@ledu-giraud.fr> writes: >> At least, yes. And then I'd expect the currently active >> (a.k.a. "selected") menu item to have a different face from the other >> items, so that the active menu item stands out on display and provides >> a visual feedback for the user moving the mouse to select menu items. > > You're right. I guess that I'd have to introduce a menu-selected face. > But from where I am now, it will at a final stage. That feedback is provided by the Lucid menu widget, not through faces. We want to make the Lucid menu widget display multilingual text correctly by using the Emacs fontset machinery, not to make it define menu text appearance through faces. ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: How to walk a Lisp_String? 2022-09-02 12:51 ` Po Lu @ 2022-09-02 15:07 ` Manuel Giraud 2022-09-03 0:58 ` Po Lu 0 siblings, 1 reply; 31+ messages in thread From: Manuel Giraud @ 2022-09-02 15:07 UTC (permalink / raw) To: Po Lu; +Cc: Eli Zaretskii, emacs-devel Po Lu <luangruo@yahoo.com> writes: > Manuel Giraud <manuel@ledu-giraud.fr> writes: > >>> At least, yes. And then I'd expect the currently active >>> (a.k.a. "selected") menu item to have a different face from the other >>> items, so that the active menu item stands out on display and provides >>> a visual feedback for the user moving the mouse to select menu items. >> >> You're right. I guess that I'd have to introduce a menu-selected face. >> But from where I am now, it will at a final stage. > > That feedback is provided by the Lucid menu widget, not through faces. Yes. > We want to make the Lucid menu widget display multilingual text > correctly by using the Emacs fontset machinery, not to make it define > menu text appearance through faces. Why not both? Having multilingual text handled correctly in menu is a goal but while here, I'd also like to be able to change the default menu face from within emacs and have menus recomputed correctly. Do you think it is attainable? -- Manuel Giraud ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: How to walk a Lisp_String? 2022-09-02 15:07 ` Manuel Giraud @ 2022-09-03 0:58 ` Po Lu 2022-09-03 5:46 ` Tomas Hlavaty 0 siblings, 1 reply; 31+ messages in thread From: Po Lu @ 2022-09-03 0:58 UTC (permalink / raw) To: Manuel Giraud; +Cc: Eli Zaretskii, emacs-devel Manuel Giraud <manuel@ledu-giraud.fr> writes: > Why not both? Having multilingual text handled correctly in menu is a > goal but while here, I'd also like to be able to change the default menu > face from within emacs and have menus recomputed correctly. Do you > think it is attainable? That already works, see x_update_menu_appearance in xfaces.c. ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: How to walk a Lisp_String? 2022-09-03 0:58 ` Po Lu @ 2022-09-03 5:46 ` Tomas Hlavaty 2022-09-03 6:19 ` Po Lu 0 siblings, 1 reply; 31+ messages in thread From: Tomas Hlavaty @ 2022-09-03 5:46 UTC (permalink / raw) To: Po Lu, Manuel Giraud; +Cc: Eli Zaretskii, emacs-devel On Sat 03 Sep 2022 at 08:58, Po Lu <luangruo@yahoo.com> wrote: > Manuel Giraud <manuel@ledu-giraud.fr> writes: >> Why not both? Having multilingual text handled correctly in menu is a >> goal but while here, I'd also like to be able to change the default menu >> face from within emacs and have menus recomputed correctly. Do you >> think it is attainable? > > That already works, see x_update_menu_appearance in xfaces.c. Does it really? That would be great. When I asked for that in bug#57372: no-toolkit menu popups do not respect emacs font configuration, it was dismissed. In what cases does it work? Could you please give an example, how to use that? ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: How to walk a Lisp_String? 2022-09-03 5:46 ` Tomas Hlavaty @ 2022-09-03 6:19 ` Po Lu 2022-09-03 8:05 ` Tomas Hlavaty 0 siblings, 1 reply; 31+ messages in thread From: Po Lu @ 2022-09-03 6:19 UTC (permalink / raw) To: Tomas Hlavaty; +Cc: Manuel Giraud, Eli Zaretskii, emacs-devel Tomas Hlavaty <tom@logand.com> writes: > Does it really? That would be great. When I asked for that in > bug#57372: no-toolkit menu popups do not respect emacs font > configuration, it was dismissed. In what cases does it work? Could you > please give an example, how to use that? We are talking about the Lucid menu bar widget, though this feature also works on Motif menus. And no, changing the size of the default face does is not reflected by changes to the Lucid menu bar. We're talking about the foreground and background colors. Thanks. ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: How to walk a Lisp_String? 2022-09-03 6:19 ` Po Lu @ 2022-09-03 8:05 ` Tomas Hlavaty 0 siblings, 0 replies; 31+ messages in thread From: Tomas Hlavaty @ 2022-09-03 8:05 UTC (permalink / raw) To: Po Lu; +Cc: Manuel Giraud, Eli Zaretskii, emacs-devel On Sat 03 Sep 2022 at 14:19, Po Lu <luangruo@yahoo.com> wrote: > Tomas Hlavaty <tom@logand.com> writes: > >> Does it really? That would be great. When I asked for that in >> bug#57372: no-toolkit menu popups do not respect emacs font >> configuration, it was dismissed. In what cases does it work? Could you >> please give an example, how to use that? > > We are talking about the Lucid menu bar widget, though this feature also > works on Motif menus. > > And no, changing the size of the default face does is not reflected by > changes to the Lucid menu bar. We're talking about the foreground and > background colors. Understand. Thanks for clarification. ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: How to walk a Lisp_String? 2022-09-02 11:40 ` Manuel Giraud 2022-09-02 12:51 ` Po Lu @ 2022-09-02 13:08 ` Eli Zaretskii 2022-09-02 14:58 ` Manuel Giraud 1 sibling, 1 reply; 31+ messages in thread From: Eli Zaretskii @ 2022-09-02 13:08 UTC (permalink / raw) To: Manuel Giraud; +Cc: emacs-devel > From: Manuel Giraud <manuel@ledu-giraud.fr> > Cc: emacs-devel@gnu.org > Date: Fri, 02 Sep 2022 13:40:53 +0200 > > > So I still don't understand how you intend to put face information on > > your Lisp strings, > > I'm still clueless about this. You said that I have to propertize them > so I think there is a C interface for this too. 'propertize' is implemented in C, so you could call it from C (as Fpropertize). But I think perhaps calling Fadd_text_properties (the C name of add-text-properties) will be easier. However, you still didn't answer my original question: where does the face information (colors and fonts) come from? The APIs I mention above will allow you to put the information on a Lisp string, but where will you get the information you need to put on those strings? ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: How to walk a Lisp_String? 2022-09-02 13:08 ` Eli Zaretskii @ 2022-09-02 14:58 ` Manuel Giraud 2022-09-02 15:33 ` Eli Zaretskii 0 siblings, 1 reply; 31+ messages in thread From: Manuel Giraud @ 2022-09-02 14:58 UTC (permalink / raw) To: Eli Zaretskii; +Cc: emacs-devel Eli Zaretskii <eliz@gnu.org> writes: [...] > However, you still didn't answer my original question: where does the > face information (colors and fonts) come from? The APIs I mention > above will allow you to put the information on a Lisp string, but > where will you get the information you need to put on those strings? Hum, I don't know. So far, I've initialized like this: --8<---------------cut here---------------start------------->8--- struct frame *f = XFRAME (frame); struct face *face = FACE_FROM_ID (f, MENU_FACE_ID); --8<---------------cut here---------------end--------------->8--- And it seems to work as intended (at least for fonts). What am I missing? -- Manuel Giraud ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: How to walk a Lisp_String? 2022-09-02 14:58 ` Manuel Giraud @ 2022-09-02 15:33 ` Eli Zaretskii 0 siblings, 0 replies; 31+ messages in thread From: Eli Zaretskii @ 2022-09-02 15:33 UTC (permalink / raw) To: Manuel Giraud; +Cc: emacs-devel > From: Manuel Giraud <manuel@ledu-giraud.fr> > Cc: emacs-devel@gnu.org > Date: Fri, 02 Sep 2022 16:58:22 +0200 > > Eli Zaretskii <eliz@gnu.org> writes: > > [...] > > > However, you still didn't answer my original question: where does the > > face information (colors and fonts) come from? The APIs I mention > > above will allow you to put the information on a Lisp string, but > > where will you get the information you need to put on those strings? > > Hum, I don't know. So far, I've initialized like this: > --8<---------------cut here---------------start------------->8--- > struct frame *f = XFRAME (frame); > struct face *face = FACE_FROM_ID (f, MENU_FACE_ID); > --8<---------------cut here---------------end--------------->8--- > > And it seems to work as intended (at least for fonts). What am I > missing? MENU_FACE_ID is the _basic_ face for menus, but it isn't the only face. By itself, it's used only for the menu bar. See term.c:tty_menu_activate for how we set up faces for the menu items: you will see that we use special faces for that. You will need either to introduce new faces for your case, or perhaps construct it from relevant X resources. ^ permalink raw reply [flat|nested] 31+ messages in thread
end of thread, other threads:[~2022-09-03 8:05 UTC | newest] Thread overview: 31+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2022-09-01 15:34 How to walk a Lisp_String? Manuel Giraud 2022-09-01 15:42 ` Stefan Monnier 2022-09-01 15:42 ` Eli Zaretskii 2022-09-01 15:49 ` Eli Zaretskii 2022-09-01 20:45 ` Manuel Giraud 2022-09-02 1:08 ` Po Lu 2022-09-02 6:32 ` Eli Zaretskii 2022-09-02 8:27 ` Po Lu 2022-09-02 10:36 ` Eli Zaretskii 2022-09-02 11:03 ` Po Lu 2022-09-02 11:15 ` Eli Zaretskii 2022-09-02 12:48 ` Po Lu 2022-09-02 13:17 ` Eli Zaretskii 2022-09-02 6:51 ` Manuel Giraud 2022-09-02 7:20 ` Eli Zaretskii 2022-09-02 8:31 ` Po Lu 2022-09-02 6:43 ` Eli Zaretskii 2022-09-02 7:18 ` Manuel Giraud 2022-09-02 7:30 ` Eli Zaretskii 2022-09-02 8:56 ` Manuel Giraud 2022-09-02 10:52 ` Eli Zaretskii 2022-09-02 11:40 ` Manuel Giraud 2022-09-02 12:51 ` Po Lu 2022-09-02 15:07 ` Manuel Giraud 2022-09-03 0:58 ` Po Lu 2022-09-03 5:46 ` Tomas Hlavaty 2022-09-03 6:19 ` Po Lu 2022-09-03 8:05 ` Tomas Hlavaty 2022-09-02 13:08 ` Eli Zaretskii 2022-09-02 14:58 ` Manuel Giraud 2022-09-02 15:33 ` Eli Zaretskii
Code repositories for project(s) associated with this public inbox https://git.savannah.gnu.org/cgit/emacs.git This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).