Author Topic: sefun WrapText()  (Read 2735 times)

Offline z993126

  • BFF
  • ***
  • Posts: 128
    • View Profile
sefun WrapText()
« on: September 11, 2011, 08:34:24 am »
Because the Wrap() function doesn't handle colour at all, I wrote my own function.  It replaces tab characters with four spaces, and puts one space between all words and two spaces after sentence-breaks and colons.  It maintains existing line breaks, and pads lines with spaces to exactly fit the passed width and returns the text as an array of lines (so it's easy to later add border-characters to the block).

Code: [Select]
/* ** HEADER for /secure/sefuns/wraptext.c **
 * 2011-Sep-11 - T. Cook
 * text-wrapping that handles colours
 */
#pragma strong_types

string *WrapText( string s_str, int i_width ){
string s_temp1 = "", s_temp2 = "";
string *sa_temptext1, *sa_temptext2, *sa_temptext3;
int i_count, i_countmax, i_count2, i_count2max, i_screenX;

i_screenX = this_player()->GetScreen()[0];
if( i_width > i_screenX ){ i_width = i_screenX; }

sa_temptext1 = explode( s_str, "\n" );
i_countmax = sizeof( sa_temptext1 );
for( i_count = 0; i_count < i_countmax; i_count++ ){
sa_temptext2 = explode( sa_temptext1[i_count], " " ) - ({ "" });
sa_temptext3 = explode( strip_colors( sa_temptext1[i_count] ), " " ) - ({ "" });
i_count2max = sizeof( sa_temptext2 );
for( i_count2 = 0; i_count2 < i_count2max; i_count2++ ){
sa_temptext2[i_count2] = replace_string( sa_temptext2[i_count2], "\t", "    " );
sa_temptext3[i_count2] = replace_string( sa_temptext3[i_count2], "\t", "    " );
if( sizeof( strip_colors( s_temp1 ) ) + sizeof( sa_temptext3[i_count2] ) < i_width ){
s_temp1 += sa_temptext2[i_count2];
if( i_count2 < sizeof( sa_temptext2 ) - 1 ){
s_temp1 += " ";
switch( sa_temptext3[i_count2][<1..<1] ){
case ".": case ":": case "?": case "!":
if( sizeof( s_temp1 ) < i_width ){ s_temp1 += " "; }
break;
default: break;
}
}else{
s_temp2 += sprintf(
"%s%s\n",
s_temp1,
repeat_string( " ", i_width - sizeof( strip_colors( s_temp1 ) ) )
);
s_temp1 = "";
}
}else{
s_temp2 += sprintf(
"%s%s\n",
s_temp1,
repeat_string( " ", i_width - sizeof( strip_colors( s_temp1 ) ) )
);
s_temp1 = sa_temptext2[i_count2];
if( i_count2 < sizeof( sa_temptext2 ) - 1 ){
s_temp1 += " ";
switch( sa_temptext3[i_count2][<1..<1] ){
case ".": case ":": case "?": case "!":
if( sizeof( s_temp1 ) < i_width ){ s_temp1 += " "; }
break;
default: break;
}
}else{
s_temp2 += sprintf(
"%s%s\n",
s_temp1,
repeat_string( " ", i_width - sizeof( strip_colors( s_temp1 ) ) )
);
s_temp1 = "";
}
}
}
}
return explode( s_temp2, "\n" );
}

Offline z993126

  • BFF
  • ***
  • Posts: 128
    • View Profile
Re: sefun WrapText()
« Reply #1 on: October 27, 2011, 04:55:48 pm »
Previous version did not maintain colour codes across line breaks.  Corrected here, and replaced outer for() loop with foreach().  Free to use/copy/modify.

Code: [Select]
/* ** HEADER for /secure/sefuns/wraptext.c **
 * 2011-Sep-11 - T. Cook
 * text-wrapping that handles colours and outputs into a space-padded array to allow easy adding of a border
 * 2011-Oct-26 - changed outer for() to foreach()
 * 2011-Oct-27 - added check for colour strings to continue on newline
 * To do:
 * - Intermittent not correctly handling two-spaces-after-punctuation?
 */
#pragma strong_types

string *WrapText( string s_str, int i_width ){
string s_temp1 = "", s_temp2 = "", s_strline = "", s_colorfg = "", s_colorbg = "", s_colorspecial = "", s_color;
string *sa_temptext1, *sa_temptext2;
string *sa_fgcolors = ({
"%^BLACK%^", "%^BLUE%^", "%^GREEN%^", "%^CYAN%^", "%^RED%^", "%^MAGENTA%^", "%^ORANGE%^", "%^YELLOW%^",
"%^WHITE%^", "%^RESET%^"
});
string *sa_bgcolors = ({
"%^B_BLACK%^", "%^B_BLUE%^", "%^B_GREEN%^", "%^B_CYAN%^", "%^RED%^", "%^B_MAGENTA%^", "%^B_ORANGE%^",
"%^B_YELLOW%^", "%^B_WHITE%^", "%^RESET%^"
});
string *sa_specialcolors = ({
"%^BOLD%^", "%^FLASH%^", "%^RESET%^"
});
int i_count, i_count_max, i_screenX, i_colorstartactual, i_colorstartflag;

i_screenX = this_player()->GetScreen()[0];
if( i_width > i_screenX ){ i_width = i_screenX; }

foreach( s_strline in explode( s_str, "\n" ) ){
sa_temptext1 = explode( s_strline, " " ) - ({ "" });
sa_temptext2 = explode( strip_colors( s_strline ), " " ) - ({ "" });
i_count_max = sizeof( sa_temptext1 );
for( i_count = 0; i_count < i_count_max; i_count++ ){
sa_temptext1[i_count] = replace_string( sa_temptext1[i_count], "\t", "    " );
sa_temptext2[i_count] = replace_string( sa_temptext2[i_count], "\t", "    " );

if( sizeof( sa_temptext1[i_count] ) > sizeof( sa_temptext2[i_count] ) ){
i_colorstartactual = sizeof( sa_temptext1[i_count] );
foreach( s_color in sa_fgcolors ){
i_colorstartflag = strsrch( sa_temptext1[i_count], s_color, -1 );
if( i_colorstartflag != -1 && i_colorstartflag <= i_colorstartactual ){
i_colorstartactual = i_colorstartflag;
s_colorfg = s_color;
}
}
i_colorstartactual = sizeof( sa_temptext1[i_count] );
foreach( s_color in sa_bgcolors ){
i_colorstartflag = strsrch( sa_temptext1[i_count], s_color, -1 );
if( i_colorstartflag != -1 && i_colorstartflag <= i_colorstartactual ){
i_colorstartactual = i_colorstartflag;
s_colorbg = s_color;
}
}
if( strsrch( sa_temptext1[i_count], "%^BOLD%^",  -1 ) != -1 ){ s_colorspecial += "%^BOLD%^"; }
if( strsrch( sa_temptext1[i_count], "%^FLASH%^", -1 ) != -1 ){ s_colorspecial += "%^FLASH%^"; }
}

if( sizeof( strip_colors( s_temp1 ) ) + sizeof( sa_temptext2[i_count] ) < i_width ){
s_temp1 += sa_temptext1[i_count];
if( i_count < sizeof( sa_temptext1 ) - 1 ){
s_temp1 += " ";
switch( sa_temptext2[i_count][<1..<1] ){
case ".": case ":": case "?": case "!":
if( sizeof( s_temp1 ) < i_width ){ s_temp1 += " "; }
break;
default: break;
}
}else{
s_temp2 += sprintf(
"%s%s\n",
s_temp1 + "%^RESET%^",
repeat_string( " ", i_width - sizeof( strip_colors( s_temp1 ) ) )
);
s_temp1 =  s_colorspecial + s_colorfg + s_colorbg;
}
}else{
s_temp2 += sprintf(
"%s%s\n",
s_temp1 + "%^RESET%^",
repeat_string( " ", i_width - sizeof( strip_colors( s_temp1 ) ) )
);
s_temp1 = s_colorspecial + s_colorfg + s_colorbg + sa_temptext1[i_count];
if( i_count < sizeof( sa_temptext1 ) - 1 ){
s_temp1 += " ";
switch( sa_temptext2[i_count][<1..<1] ){
case ".": case ":": case "?": case "!":
if( sizeof( s_temp1 ) < i_width ){ s_temp1 += " "; }
break;
default: break;
}
}else{
s_temp2 += sprintf(
"%s%s\n",
s_temp1 + "%^RESET%^",
repeat_string( " ", i_width - sizeof( strip_colors( s_temp1 ) ) )
);
s_temp1 = "";
}
}
}
}
return explode( s_temp2, "\n" );
}

Offline z993126

  • BFF
  • ***
  • Posts: 128
    • View Profile
Re: sefun WrapText()
« Reply #2 on: October 28, 2011, 03:29:25 pm »
...and here's a much simpler version that just uses terminal_colour(), but handles the padding-with-spaces of end-of-lines, as well as converts tab characters to five (5) spaces.

Code: [Select]
/* ** HEADER for /secure/sefuns/wraptext.c **
 * 2011-Sep-11 - T. Cook
 * text-wrapping that handles colours and outputs into a space-padded array to allow easy adding of a border
 * 2011-Oct-26 - changed outer for() to foreach()
 * 2011-Oct-27 - added check for colour strings to continue on newline
 *             - fixed problem caused by colour strings being an isolated word
 * 2011-Oct-28 - replaced majority of code with terminal_colour() call
 */
#pragma strong_types

string *WrapText( string s_str, int i_width ){
string s_line = "";
string *sa_temptext1, *sa_temptext2 = ({});
int i_count, i_screenX;

i_screenX = this_player()->GetScreen()[0];
if( i_width > i_screenX ){ i_width = i_screenX; }

sa_temptext1 = explode( terminal_colour( replace_string( s_str, "\t", "     " ), ([
"BLACK"     : "%^BLACK%^",
"BLUE"      : "%^BLUE%^",
"GREEN"     : "%^GREEN%^",
"CYAN"      : "%^CYAN%^",
"RED"       : "%^RED%^",
"MAGENTA"   : "%^MAGENTA%^",
"ORANGE"    : "%^ORANGE%^",
"YELLOW"    : "%^YELLOW%^",
"WHITE"     : "%^WHITE%^",
"B_BLACK"   : "%^B_BLACK%^",
"B_BLUE"    : "%^B_BLUE%^",
"B_GREEN"   : "%^B_GREEN%^",
"B_CYAN"    : "%^B_CYAN%^",
"B_RED"     : "%^B_RED%^",
"B_MAGENTA" : "%^B_MAGENTA%^",
"B_ORANGE"  : "%^B_ORANGE%^",
"B_YELLOW"  : "%^B_YELLOW%^",
"B_WHITE"   : "%^B_WHITE%^",
"BOLD"      : "%^BOLD%^",
"FLASH"     : "%^FLASH%^",
"RESET"     : "%^RESET%^"
]), i_width ), "\n" );
foreach( s_line in sa_temptext1 ){
i_count = sizeof( strip_colors( s_line ) );
if( i_count <= i_width ){ sa_temptext2 += ({ s_line + repeat_string( " ", i_width - i_count ) }); }
}
return sa_temptext2;
}
/* EOF */

Offline quixadhal

  • BFF
  • ***
  • Posts: 642
    • View Profile
    • WileyMUD
Re: sefun WrapText()
« Reply #3 on: October 29, 2011, 12:03:53 am »
Rather than hard-coding the set of Pinkfish tokens, which will fail for people like me who have customized and added to it, try this:

Code: [Select]
...
mapping m_colors = ([ ]);
foreach( mapping t in map(keys(TERMINAL_D->query_term_info(LIB_INTERFACE->GetTerminal())), (: ([ $1 : "%^" + $1 + "%^" ]) :))) {
    m_colors = m_colors + t;
}

sa_temptext1 = explode( terminal_colour( replace_string( s_str, "\t", "     " ), m_colors), i_width ), "\n" );
...

Note that you could avoid the call to GetTerminal() and just use "unknown", but in the stock DS terminal system, different terminal types have different keys, so it may or may not do what you want.

Offline Archaegeo

  • Acquaintance
  • *
  • Posts: 33
    • View Profile
Re: sefun WrapText()
« Reply #4 on: November 02, 2011, 04:08:09 pm »
And instead of setting tab to 4 or 5 spaces, put a nice TAB variable at the top and let folks set their own :)