unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* 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-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  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: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  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  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  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  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-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: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  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: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 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: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 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 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 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 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 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 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

* 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

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).