[Home] [Downloads] [Search] [Help/forum]


Register forum user name Search FAQ

Gammon Forum

[Folder]  Entire forum
-> [Folder]  SMAUG
. -> [Folder]  SMAUG coding
. . -> [Subject]  Colour tokens causing misalignment with string formatting (e.g. %-40s)

Colour tokens causing misalignment with string formatting (e.g. %-40s)

It is now over 60 days since the last post. This thread is closed.     [Refresh] Refresh page


Posted by Marowi   (65 posts)  [Biography] bio
Date Sun 13 Jul 2014 02:12 AM (UTC)
Message
Hey folks,

I've been digging into a problem with aligning coloured text, and am running short on ideas. I'm working with a modified SMAUG/SWR codebase, but I believe this is primarily related to standard functions.

The problem : using '%-40s' (or any string format/length token) will consider the colour tokens as part of the '40', and the output will consequently be 2 shorter than I want.

The code:

	ch_printf( ch, "&zName: &c%-40s &zVnum: &c%d\n\r", (location->name), location->vnum );
	ch_printf( ch, "&zName: &c%-40s &zVnum: &c%d\n\r", showclr(location->name), location->vnum );
	ch_printf( ch, "&zName: &c%-40s &zVnum: &c%d\n\r", stripclr(location->name), location->vnum );
	ch_printf( ch, "&zName: &c%-40s | strlen: %d | strlen_color: %d\n\r", location->name, strlen(location->name), strlen_color(location->name));


The output:

Name: The Kuragame Waterfall                 Vnum: 4102
Name: &pThe Kuragame Waterfall                Vnum: 4102
Name: The Kuragame Waterfall                   Vnum: 4102
Name: The Kuragame Waterfall                 | strlen: 24 | strlen_colour: 22


Technically, there are 24 characters in the string provided, so it's not entirely incorrect to be adding only 16 spaces to make it to the 40 requested. However, I would like it to disregard the colour tags when counting characters.

My best guess is that it's because ch_printf() has no idea that I'm going to swap colour tokens for ANSI code, so when it calculates string length, it's doing the best it can without that information.

ch_printf:

void ch_printf( CHAR_DATA *ch, char *fmt, ... )
{
   char buf[MAX_STRING_LENGTH*2];
   va_list args;

   va_start( args, fmt );
   vsnprintf( buf, MAX_STRING_LENGTH*2, fmt, args );
   va_end( args );

   send_to_char_color( buf, ch );
}


I'm at a bit of a loss as to how other MUDs handle this; perhaps I should have opened with the question - do they?

Any advice is appreciated!

-Marowi
[Go to top] top

Posted by Meerclar   USA  (733 posts)  [Biography] bio
Date Reply #1 on Sun 13 Jul 2014 06:05 AM (UTC)
Message
Honestly, every mud I've worked on has resorted to either coding in the colors elsewhere, adding in extra whitespace to account for the color codes in that string or saying screw it and still does it oldschool. There's also the option of checking the string and subtracting 2 from strlen for every color code in the provided text. Of more concern to me though is the fact that your sample text offsets aren't correct.

2nd should be offset 2 from the first and isn't after the whitespace.

Meerclar - Lord of Cats
Coder, Builder, and Tormenter of Mortals
Stormbringer: Rebirth
storm-bringer.org:4500
www.storm-bringer.org
[Go to top] top

Posted by Marowi   (65 posts)  [Biography] bio
Date Reply #2 on Sun 13 Jul 2014 05:17 PM (UTC)
Message
Trying to determine in which cases to add the whitespace is the difficult part. I'd only want it for particular strings, where the formatting means misalignment (who list, etc).

I have a strlen_color function that doesn't count the colour codes, but it seems that the string length is already determined before it gets to any sort of color conversion code.

The sample text offsets are correct. With this codebase, 'showclr' doubles up any colour codes in the string, so they display in the output.
e.g. "&BOcean" + showclr = "&&BOcean"

I guess I could not bother with alignment for any strings that could have colours, and strip out the colours for any strings I definitely want aligned.

Thanks for your reply.
[Go to top] top

Posted by Nick Gammon   Australia  (22,973 posts)  [Biography] bio   Forum Administrator
Date Reply #3 on Sun 13 Jul 2014 08:44 PM (UTC)
Message
In the source (color.c) I found this, doesn't that do what you want?


/*
 * Quixadhal - I rewrote this too, so that it uses colorcode.  It may not
 * be as efficient as just walking over the string and counting, but it
 * keeps us from duplicating the code several times.
 *
 * This function returns the intended screen length of a string which has
 * color codes embedded in it.  It does this by stripping the codes out
 * entirely (A NULL descriptor means ANSI will be FALSE).
 */
int color_strlen( const char *src )
...


Using that you can find the length of the string without colour codes, then just work out how many spaces to send afterwards.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by Marowi   (65 posts)  [Biography] bio
Date Reply #4 on Sun 13 Jul 2014 10:22 PM (UTC)
Message
I wrote a strlen_color, which presumably does the same thing. In the example, strlen(location->name) returns 24, while strlen_color(location->name) returns 22.

The problem I'm having is that the %-40s has no concept of anything except the raw text passed to it, which it correctly determines as 24 characters in length, and adds another 16 spaces.

Your suggestion did give me the idea that I add another %s after the %-40s, and instead count the colour codes inside (location->name) and add that many spaces - it's messy, but if absolutely necessary, it could work.
[Go to top] top

Posted by Nick Gammon   Australia  (22,973 posts)  [Biography] bio   Forum Administrator
Date Reply #5 on Mon 14 Jul 2014 09:10 AM (UTC)
Message
Yes that was what I meant. In fact you can probably print "" (an empty string) with a dynamic length, eg.


%-40s%-*s


Then supply the number of spaces you want as an integer before the blank string (or is it after?) Like that, anyway.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by Marowi   (65 posts)  [Biography] bio
Date Reply #6 on Thu 17 Jul 2014 06:33 AM (UTC)
Message
Ah! Fantastic. I hadn't known it was possible to insert a dynamic length token like that; a quick search revealed that a lot of people have the same reaction.

Thanks again for all the responses - got this sorted for now!
[Go to top] top

The dates and times for posts above are shown in Universal Co-ordinated Time (UTC).

To show them in your local time you can join the forum, and then set the 'time correction' field in your profile to the number of hours difference between your location and UTC time.


18,325 views.

It is now over 60 days since the last post. This thread is closed.     [Refresh] Refresh page

Go to topic:           Search the forum


[Go to top] top

Quick links: MUSHclient. MUSHclient help. Forum shortcuts. Posting templates. Lua modules. Lua documentation.

Information and images on this site are licensed under the Creative Commons Attribution 3.0 Australia License unless stated otherwise.

[Home]


Written by Nick Gammon - 5K   profile for Nick Gammon on Stack Exchange, a network of free, community-driven Q&A sites   Marriage equality

Comments to: Gammon Software support
[RH click to get RSS URL] Forum RSS feed ( https://gammon.com.au/rss/forum.xml )

[Best viewed with any browser - 2K]    [Hosted at HostDash]