View Issue Details

IDProjectCategoryView StatusLast Update
0001992FSSCPuser interfacepublic2010-01-25 03:24
ReporterFUBAR-BDHR Assigned ToZacam  
PrioritynormalSeverityminorReproducibilityalways
Status resolvedResolutionfixed 
Product Version3.6.11 
Summary0001992: Color codes in briefigns not working correctly
DescriptionNoticed doing some testing for a campaign. Some ship and wing names didn't have color so I reported them as bugs. Vidmaster got back to me that they were in fact in the briefing which I confirmed in notepad. It seems to be randomly ignoring the $g and $r (and probably others) color codes. There doesn't seem to be any pattern that I can see.
Additional Information3.6.11 r5596 Inferno in TBP. I'll attempt to reproduce it in FS2 and attach a test mission shortly.
TagsNo tags attached.

Activities

2009-09-14 23:58

 

1briefcolor.fs2 (3,691 bytes)

FUBAR-BDHR

2009-09-15 01:01

developer   ~0011176

I tried to see what was happening and stepped through the line manually. Looks like it set up the colors correctly. Still doesn't display Delta as green though. Line at the end of the routine:

+ src 0x0012e358 "The $g Big $g Cash will deploy two wings of fighters in the area, $g Alpha and $g Delta." char *
        instance 0 int
- dest_line {...} SCP_vector<colored_char>
- std::vector<colored_char,SCP_vm_allocator<colored_char> > [77]({letter='T' color=0 },{letter='h' color=0 },{letter='e' color=0 },{letter=' ' color=0 },{letter='B' color='' },{letter='i' color='' },{letter='g' color='' },{letter=' ' color=0 },{letter='C' color='' },{letter='a' color='' },{letter='s' color='' },{letter='h' color='' },{letter=' ' color=0 },{letter='w' color=0 },{letter='i' color=0 },{letter='l' color=0 },{letter='l' color=0 },{letter,...) std::vector<colored_char,SCP_vm_allocator<colored_char> >
+ [0] {letter='T' color=0 } colored_char
+ [1] {letter='h' color=0 } colored_char
+ [2] {letter='e' color=0 } colored_char
+ [3] {letter=' ' color=0 } colored_char
+ [4] {letter='B' color='' } colored_char
+ [5] {letter='i' color='' } colored_char
+ [6] {letter='g' color='' } colored_char
+ [7] {letter=' ' color=0 } colored_char
+ [8] {letter='C' color='' } colored_char
+ [9] {letter='a' color='' } colored_char
+ [10] {letter='s' color='' } colored_char
+ [11] {letter='h' color='' } colored_char
+ [12] {letter=' ' color=0 } colored_char
+ [13] {letter='w' color=0 } colored_char
+ [14] {letter='i' color=0 } colored_char
+ [15] {letter='l' color=0 } colored_char
+ [16] {letter='l' color=0 } colored_char
+ [17] {letter=' ' color=0 } colored_char
+ [18] {letter='d' color=0 } colored_char
+ [19] {letter='e' color=0 } colored_char
+ [20] {letter='p' color=0 } colored_char
+ [21] {letter='l' color=0 } colored_char
+ [22] {letter='o' color=0 } colored_char
+ [23] {letter='y' color=0 } colored_char
+ [24] {letter=' ' color=0 } colored_char
+ [25] {letter='t' color=0 } colored_char
+ [26] {letter='w' color=0 } colored_char
+ [27] {letter='o' color=0 } colored_char
+ [28] {letter=' ' color=0 } colored_char
+ [29] {letter='w' color=0 } colored_char
+ [30] {letter='i' color=0 } colored_char
+ [31] {letter='n' color=0 } colored_char
+ [32] {letter='g' color=0 } colored_char
+ [33] {letter='s' color=0 } colored_char
+ [34] {letter=' ' color=0 } colored_char
+ [35] {letter='o' color=0 } colored_char
+ [36] {letter='f' color=0 } colored_char
+ [37] {letter=' ' color=0 } colored_char
+ [38] {letter='f' color=0 } colored_char
+ [39] {letter='i' color=0 } colored_char
+ [40] {letter='g' color=0 } colored_char
+ [41] {letter='h' color=0 } colored_char
+ [42] {letter='t' color=0 } colored_char
+ [43] {letter='e' color=0 } colored_char
+ [44] {letter='r' color=0 } colored_char
+ [45] {letter='s' color=0 } colored_char
+ [46] {letter=' ' color=0 } colored_char
+ [47] {letter='i' color=0 } colored_char
+ [48] {letter='n' color=0 } colored_char
+ [49] {letter=' ' color=0 } colored_char
+ [50] {letter='t' color=0 } colored_char
+ [51] {letter='h' color=0 } colored_char
+ [52] {letter='e' color=0 } colored_char
+ [53] {letter=' ' color=0 } colored_char
+ [54] {letter='a' color=0 } colored_char
+ [55] {letter='r' color=0 } colored_char
+ [56] {letter='e' color=0 } colored_char
+ [57] {letter='a' color=0 } colored_char
+ [58] {letter=',' color=0 } colored_char
+ [59] {letter=' ' color=0 } colored_char
+ [60] {letter='A' color='' } colored_char
+ [61] {letter='l' color='' } colored_char
+ [62] {letter='p' color='' } colored_char
+ [63] {letter='h' color='' } colored_char
+ [64] {letter='a' color='' } colored_char
+ [65] {letter=' ' color=0 } colored_char
+ [66] {letter='a' color=0 } colored_char
+ [67] {letter='n' color=0 } colored_char
+ [68] {letter='d' color=0 } colored_char
+ [69] {letter=' ' color=0 } colored_char
+ [70] {letter='D' color='' } colored_char
+ [71] {letter='e' color='' } colored_char
+ [72] {letter='l' color='' } colored_char
+ [73] {letter='t' color='' } colored_char
+ [74] {letter='a' color='' } colored_char
+ [75] {letter='.' color='' } colored_char
+ [76] {letter=0 color=0 } colored_char
        skip_to_next_word 0 int
        len 88 int
- dest {letter=0 color=0 } colored_char
        letter 0 char
        color 0 unsigned char
        active_color_index 3 '' unsigned char
        i 88 int

2009-09-15 06:07

 

1992.jpg (165,425 bytes)   
1992.jpg (165,425 bytes)   

FUBAR-BDHR

2009-09-15 06:08

developer   ~0011177

Doing some more tracking I thought I noticed Delta change colors so I tried catching it. Got a screen shot of it while stepping through. The D is clearly green before it is changed back to normal.

karajorma

2009-09-15 13:49

administrator   ~0011178

I saw one of these in Diaspora which was caused by you using $R. $r worked just fine.

Are the capitals meant to work?

FUBAR-BDHR

2009-09-15 21:29

developer   ~0011179

Last edited: 2009-09-15 21:54

Actually working with Wanderer last night we determined that it only occurs at the end of a line (no matter how short the line). All of these are lower case $r and $g with and occasional $b.

The capitals are probably not supposed to work (only saw lower case in the code)but I've never got an error message from them.

Almost forgot putting a space at the end of the line in notepad results in the color not being overwritten by white.

pedro

2009-11-10 23:23

reporter   ~0011242

Last edited: 2009-11-10 23:55

Hello everybody.

karajorma told me to fix this bug http://scp.indiegames.us/mantis/view.php?id=1992. Here is my correction proposal.

The color bug has two causes:
1 - brief_color_text_init terminates every lines by a {letter=0 color=0 } colored_char. It is useless to add a strign termination character because the SCP_vector stores the string length. In addition it makes SCP_vector.size() = string length +1 which is not intuitive.
2 - brief_render_line draws briefing lines made of character sequences separated by spaces with the color of the last character of the sequence. FUBAR-BDHR notes shows every line are terminated by a {letter=0 color=0 } colored_char. This char is part of the character sequence because it is not a whitespace (whitespace is char 32, not 0), as a consequence the color 0 is used to draw the last character sequence of a line. This is surprising that this method tries to detect words because the coloring information have already been built by brief_color_text_init function. It would be more appropriate to focus on character colors.

I propose a double fix where the two fix are sufficient to solve mantis issue (http://scp.indiegames.us/mantis/view.php?id=1992):
1 - Modify brief_color_text_init to remove the extra terminal character
2 - Rewrite brief_render_line to work with character sequences delimited by color change.

Note that the current implementation of brief_color_text_init does not recognize ',.:;()' as word separators which causes the dot of "$g DELTA." string to be green whereas It could be considered to be white.

I'm going to change the coloring algorithm (if you are ok) and consider the following character to be word separators:
[0;47] for a lot of chars including !"#$%&'()*+,-./
[58;64] for :;<=>?@
[91;94] for [\]^
{96} for `
[123;127] for {|}~

Here are the behavior modification introduced.
I detected a minor memory access out of allocated memory, that can be fixed.

- "$g Alpha_one, and $g Delta." gives Alpha_one, and Delta." whereas it gave "Alpha_one, and Delta.".
- "Something $g" gives "Something" whereas it gave "Something $g".
- "Something $" gives "Something $" whereas it gave an unpredictable result because of the coloring depend on the char after the \0 of the given C string.

To conclude, there are still at least two known bugs that requires a change of structure in the code (probably rewrite/kill split_str). Try the following mission text and see carriage return are ignored or replaced by raw newline
"Something $g
Something $
Else
"

2009-11-10 23:55

 

0001992.patch (10,835 bytes)   
Index: code/mission/missionbriefcommon.cpp
===================================================================
--- code/mission/missionbriefcommon.cpp	(revision 5643)
+++ code/mission/missionbriefcommon.cpp	(working copy)
@@ -1253,26 +1253,34 @@
 // Render a line of text for the briefings.  Lines are drawn in as a wipe, with leading bright
 // white characters.  Have to jump through some hoops since we support colored words.  This means
 // that we need to process the line one character at a time.
+//
+// @param line_num number of the line of the briefing page to be drawn
+// @x     horizontal position where the text is drawn
+// @y     vertical position where the text is drawn
+// @instance index of Colored_stream of the text page to display
 void brief_render_line(int line_num, int x, int y, int instance)
 {
-	int len, count, next, truncate_len, last_color, offset, w, h, bright_len, i;
-	char line[MAX_BRIEF_LINE_LEN];
-	SCP_vector<colored_char> *src; 
-
-	src = &Colored_stream[instance].at(line_num);
-	len = src->size();
-
-	if (len == 0){
+    Assert( 0<=instance && instance < (sizeof(Colored_stream)/sizeof(*Colored_stream)) );
+    
+    SCP_vector<colored_char> *src = &Colored_stream[instance].at(line_num);
+	
+	// empty strings have not to be drawn
+    int src_len = src->size();
+    if (src_len == 0){
 		return;
 	}
 
-	truncate_len = fl2i(Brief_text_wipe_time_elapsed / BRIEF_TEXT_WIPE_TIME * Max_briefing_line_len);
-	if (truncate_len > len){
-		truncate_len = len;
+    // truncate_len is the number of character currently displayed including the bright white characters
+	int truncate_len = fl2i(Brief_text_wipe_time_elapsed / BRIEF_TEXT_WIPE_TIME * Max_briefing_line_len);
+	if (truncate_len > src_len){
+		truncate_len = src_len;
 	}
 
-	bright_len = 0;
-	if (truncate_len < len) {
+    // truncate_len is going to be the number of character displayed with normal intensity
+    // bright_len is the additional characters displayed with high intensity
+    // bright_len+truncate_len<len chars are displayed
+	int bright_len = 0;
+	if (truncate_len < src_len) {
 		if (truncate_len <= BRIGHTEN_LEAD) {
 			bright_len = truncate_len;
 			truncate_len = 0;
@@ -1283,69 +1291,67 @@
 		}
 	}
 
-	offset = 0;
-	count  = 0;
-	next	 = 0;
-
+    int char_seq_pos=0; //Cursor position into the following character sequence
+	char char_seq[MAX_BRIEF_LINE_LEN];	
+	int offset = 0; //offset is the horizontal position of the screen where strings are drawn
 	gr_set_color_fast(&Color_white);
-	last_color = BRIEF_TEXT_WHITE;
-	for (i=0; i<truncate_len; i++) {
-		if (count >= truncate_len){
-			break;
-		}
 
-		line[next] = src->at(count).letter;
+    // PART1: Draw the the briefing line part with normal intensity and words colours.
+    // The following algorythm builds a character sequence of color 'last_color' into 'line' buffer.
+    // When the colour changes, the buffer drawn and reset.
+    {
+        int last_color = src->at(0).color;    
+        for (int current_pos=0; current_pos<truncate_len; current_pos++) {
+            colored_char &current_char=src->at(current_pos);		
+            //when the current color changes, the accumulated character sequence is drawn.
+            if (current_char.color != last_color){
+                //add a 0 terminal character to make line a valid C string
+                Assert(char_seq_pos<sizeof(char_seq));
+                char_seq[char_seq_pos] = 0;         
+                
+                // Draw coloured text, and increment cariage position
+                {
+                    int w=0,h=0;
+                    brief_set_text_color(last_color);        
+                    gr_string(x + offset, y, char_seq);
+                    gr_get_string_size(&w, &h, char_seq);
+                    offset += w;
+                }
+                //clear char buffer
+                char_seq_pos = 0;
+                last_color = current_char.color;
+            }
 
-		if (is_white_space(line[next])) {
-			// end of word reached, blit it
-			line[next + 1] = 0;
-			gr_string(x + offset, y, line);
-			gr_get_string_size(&w, &h, line);
-			offset += w;
-			next = 0;
+            Assert(char_seq_pos<sizeof(char_seq));
+            char_seq[char_seq_pos++] = current_char.letter;		
+        }	
 
-			// reset color
-			if (last_color != BRIEF_TEXT_WHITE) {
-				brief_set_text_color(BRIEF_TEXT_WHITE);
-				last_color = BRIEF_TEXT_WHITE;
-			}
+        // Draw the final chunk of acumulated characters
+        // Add a 0 terminal character to make line a valid C string
+        Assert(char_seq_pos<sizeof(char_seq));
+        char_seq[char_seq_pos] = 0;
+        // Draw coloured text, and increment cariage position
+        {
+            int w=0,h=0;
+            brief_set_text_color(last_color);        
+            gr_string(x + offset, y, char_seq);
+            gr_get_string_size(&w, &h, char_seq);
+            offset += w;
+        }
+    }
 
-			count++;
-			continue;
-		}
-
-		if (src->at(count).color != last_color) {
-			brief_set_text_color(src->at(count).color);
-			last_color = src->at(count).color;
-		}
-
-		count++;
-		next++;
-	}	// end for
-
-	line[next] = 0;
-	gr_string(x + offset, y, line);
-
-
-	// draw leading portion of the line bright white
-	if (bright_len) {
-
-		gr_set_color_fast(&Color_bright_white);
-		for (i=0; i<truncate_len+bright_len; i++) {
-			line[i] = src->at(i).letter;
-		}
-
-		line[i] = 0;
-
-
-		if ( truncate_len > 0 )	{
-			int width_dim, height_dim;
-			gr_get_string_size(&width_dim, &height_dim, line, truncate_len );
-			gr_string(x+width_dim, y, &line[truncate_len]);
-		} else {
-			gr_string(x, y, line);
-		}
-	}
+    // PART2: Draw leading bright white characters
+    {
+        char_seq_pos = 0;
+        for( int current_pos = truncate_len; current_pos<truncate_len + bright_len; current_pos++){		
+            Assert(char_seq_pos<sizeof(char_seq));
+            char_seq[char_seq_pos++] = src->at(current_pos).letter;
+        }
+        Assert(char_seq_pos<sizeof(char_seq));
+        char_seq[char_seq_pos] = 0;
+        gr_set_color_fast(&Color_bright_white);
+        gr_string(x + offset, y, char_seq);    
+    }
 }
 
 int brief_text_wipe_finished()
@@ -1574,51 +1580,78 @@
 	gr_set_color_fast(Brief_text_colors[color_index]);
 }
 
-// Set up the Colored_text array.
-// input:		index		=>		Index into Brief_text[] for source text.
-//					instance	=>		Which instance of Colored_text[] to use.  
-//										Value is 0 unless multiple text streams are required.
+
+// Returns true when a character is a word separator. The most usual separators are space
+// characters and punctuation. The following characters are separators 
+// [33;47] u [58;64] U [91;94] U {96} U [123;127]
+// @param character is the character to be analysed
+// @return true when the given character is a word separator, and false when the caracter is part of a word.
+bool is_a_word_separator(char character){
+    return character<=47                    // 48 characters including !"#$%&'()*+,-./
+        || (58<=character && character<=64) //  7 characters :;<=>?@
+        || (91<=character && character<=94) //  4 characters [\]^
+        || (character == 96 )               //  1 character  `
+        || (123<=character&&character<=127);//  5 characters including {|}~
+}
+
+// Builds a vector of colored character vrom a string containing color markups and store it to 
+// Colored_stream table.
+// a color markup is made of a minimum of three characters: 
+//   '$' + a char standing for a color + contigous multiple spaces (chars \t \n and ' ')
+// The markup is completely removed from the resulting character sequence.
+// @param src a not null pointer to a C string terminated by a /0 char.
+// @param instance index into Colored_stream where the result should be placed.
+//	  			   Value is 0 unless multiple text streams are required.
+// @return number of character of the resulting sequence.
+//
+// Here are a few examples of the expected behavior:
+//  "$g Alpha_one, and $g     Delta." gives "[color=green]Alpha_one[/color], and [color=green]Delta[/color].".
+//  "Something $g" gives "Something" whereas it gave "Something $g".
+//  "Something $" gives "Something $".
+
 int brief_text_colorize(char *src, int instance)
 {
-	int len, i, skip_to_next_word = 0;
-	colored_char dest; 
-	briefing_line dest_line; 
+    Assert(src);
+    Assert( 0<=instance && instance < (sizeof(Colored_stream)/sizeof(*Colored_stream)) );
 
-	ubyte active_color_index = BRIEF_TEXT_WHITE;
+    briefing_line dest_line; //the resulting vector of colored character
+	ubyte active_color_index = BRIEF_TEXT_WHITE; //the current drawing color
 
-	len = strlen(src);
-	for (i=0; i<len; i++) {
-		if (skip_to_next_word) {
-			if (is_white_space(src[i])) {
-				skip_to_next_word = 0;
-			}
+	int src_len = strlen(src);
+	for (int i=0; i<src_len; i++) {
 
-			continue;
+        // Is the character a color markup ?
+        // color markup is made of three character: 
+        // '$' + a char standing for a color + a white space
+		if ( src[i] == BRIEF_META_CHAR  // a $ is encountred
+            && i + 1 < src_len          // $ there is at least one character after the markup in this string
+            && ( i + 2 >= src_len  || is_white_space(src[i + 2])) //The following character is white if any
+            ) {
+            i ++;   //Consume the $ character
+			active_color_index = brief_return_color_index(src[i]);
+            i ++; // Consume the color identifier and focus on the white character (if any)
+            
+            // Skip every whitespace until the next word is reached
+            while( i+1 < src_len && is_white_space(src[i+1]) )
+                i++;
+            //The next character is not a whitespace, let's process it as usual
+            continue;
 		}
 
-		if ( src[i] == BRIEF_META_CHAR && is_white_space(src[i + 2]) ) {
-			active_color_index = brief_return_color_index(src[i + 1]);
-			skip_to_next_word = 1;
-			continue;
-		}
-
-		if (is_white_space(src[i])) {
+        // When the word is terminated reset color to white
+        if (is_a_word_separator(src[i])) {
 			active_color_index = BRIEF_TEXT_WHITE;
 		}
 
-		dest.letter = src[i];
+        // Append the character to the result structure
+        colored_char dest;
+        dest.letter = src[i];
 		dest.color = active_color_index;
-
 		dest_line.push_back(dest); 
-	} // end for
+	} 
 
-	// null terminate the line
-	dest.letter = 0;
-	dest.color = BRIEF_TEXT_WHITE; 
-	dest_line.push_back(dest);
-	Colored_stream[instance].push_back(dest_line); 
-	Colored_stream[instance].size();
-	return len;
+	Colored_stream[instance].push_back(dest_line); 	
+    return dest_line.size();
 }
 
 // ------------------------------------------------------------------------------------
0001992.patch (10,835 bytes)   

2010-01-09 18:52

 

M1992_01032010.patch (10,293 bytes)   
Index: code/mission/missionbriefcommon.cpp
===================================================================
--- code/mission/missionbriefcommon.cpp	(revision 5758)
+++ code/mission/missionbriefcommon.cpp	(working copy)
@@ -1275,98 +1275,94 @@
 // Render a line of text for the briefings.  Lines are drawn in as a wipe, with leading bright
 // white characters.  Have to jump through some hoops since we support colored words.  This means
 // that we need to process the line one character at a time.
+//
+// @param line_num number of the line of the briefing page to be drawn
+// @x     horizontal position where the text is drawn
+// @y     vertical position where the text is drawn
+// @instance index of Colored_stream of the text page to display
 void brief_render_line(int line_num, int x, int y, int instance)
 {
-	int len, count, next, truncate_len, last_color, offset, w, h, bright_len, i;
-	char line[MAX_BRIEF_LINE_LEN];
-	SCP_vector<colored_char> *src; 
+	Assert( 0<=instance && instance < (sizeof(Colored_stream)/sizeof(*Colored_stream)) );
 
-	src = &Colored_stream[instance].at(line_num);
-	len = src->size();
+	SCP_vector<colored_char> *src = &Colored_stream[instance].at(line_num);
 
-	if (len == 0){
+	// empty strings do not have to be drawn
+	int src_len = src->size();
+	if (src_len == 0){
 		return;
 	}
-
-	truncate_len = fl2i(Brief_text_wipe_time_elapsed / BRIEF_TEXT_WIPE_TIME * Max_briefing_line_len);
-	if (truncate_len > len){
-		truncate_len = len;
+	// truncate_len is the number of characters currently displayed including the bright white characters
+	int truncate_len = fl2i(Brief_text_wipe_time_elapsed / BRIEF_TEXT_WIPE_TIME * Max_briefing_line_len);
+	if (truncate_len > src_len){
+		truncate_len = src_len;
 	}
-
-	bright_len = 0;
-	if (truncate_len < len) {
+	// truncate_len is going to be the number of characters displayed with normal intensity
+	// bright_len is the additional characters displayed with high intensity
+	// bright_len+truncate_len<len chars are displayed
+	int bright_len = 0;
+	if (truncate_len < src_len) {
 		if (truncate_len <= BRIGHTEN_LEAD) {
 			bright_len = truncate_len;
 			truncate_len = 0;
-
 		} else {
 			bright_len = BRIGHTEN_LEAD;
 			truncate_len -= BRIGHTEN_LEAD; 
 		}
 	}
-
-	offset = 0;
-	count  = 0;
-	next	 = 0;
-
+	int char_seq_pos=0; //Cursor position into the following character sequence
+	char char_seq[MAX_BRIEF_LINE_LEN];	
+	int offset = 0; //offset is the horizontal position of the screen where strings are drawn
 	gr_set_color_fast(&Color_white);
-	last_color = BRIEF_TEXT_WHITE;
-	for (i=0; i<truncate_len; i++) {
-		if (count >= truncate_len){
-			break;
-		}
 
-		line[next] = src->at(count).letter;
-
-		if (is_white_space(line[next])) {
-			// end of word reached, blit it
-			line[next + 1] = 0;
-			gr_string(x + offset, y, line);
-			gr_get_string_size(&w, &h, line);
-			offset += w;
-			next = 0;
-
-			// reset color
-			if (last_color != BRIEF_TEXT_WHITE) {
-				brief_set_text_color(BRIEF_TEXT_WHITE);
-				last_color = BRIEF_TEXT_WHITE;
+	// PART1: Draw the the briefing line part with normal intensity and word colors.
+	// The following algorithm builds a character sequence of color 'last_color' into 'line' buffer.
+	// When the color changes, the buffer is drawn and reset.
+	{
+		int last_color = src->at(0).color;    
+		for (int current_pos=0; current_pos<truncate_len; current_pos++) {
+			colored_char &current_char=src->at(current_pos);		
+			//when the current color changes, the accumulated character sequence is drawn.
+			if (current_char.color != last_color){
+				//add a 0 terminal character to make line a valid C string
+				Assert(char_seq_pos<sizeof(char_seq));
+				char_seq[char_seq_pos] = 0;         
+				{	// Draw coloured text, and increment cariage position
+					int w=0,h=0;
+					brief_set_text_color(last_color);        
+					gr_string(x + offset, y, char_seq);
+					gr_get_string_size(&w, &h, char_seq);
+					offset += w;
+				}
+				//clear char buffer
+				char_seq_pos = 0;
+				last_color = current_char.color;
 			}
-
-			count++;
-			continue;
+			Assert(char_seq_pos<sizeof(char_seq));
+			char_seq[char_seq_pos++] = current_char.letter;		
 		}
+		// Draw the final chunk of acumulated characters
+		// Add a 0 terminal character to make line a valid C string
+		Assert(char_seq_pos<sizeof(char_seq));
+		char_seq[char_seq_pos] = 0;
+        {	// Draw coloured text, and increment cariage position
+			int w=0,h=0;
+			brief_set_text_color(last_color);        
+			gr_string(x + offset, y, char_seq);
+			gr_get_string_size(&w, &h, char_seq);
+			offset += w;
+		}
+	}
 
-		if (src->at(count).color != last_color) {
-			brief_set_text_color(src->at(count).color);
-			last_color = src->at(count).color;
+	{	// PART2: Draw leading bright white characters
+		char_seq_pos = 0;
+		for( int current_pos = truncate_len; current_pos<truncate_len + bright_len; current_pos++){		
+			Assert(char_seq_pos<sizeof(char_seq));
+			char_seq[char_seq_pos++] = src->at(current_pos).letter;
 		}
-
-		count++;
-		next++;
-	}	// end for
-
-	line[next] = 0;
-	gr_string(x + offset, y, line);
-
-
-	// draw leading portion of the line bright white
-	if (bright_len) {
-
+		Assert(char_seq_pos<sizeof(char_seq));
+		char_seq[char_seq_pos] = 0;
 		gr_set_color_fast(&Color_bright_white);
-		for (i=0; i<truncate_len+bright_len; i++) {
-			line[i] = src->at(i).letter;
-		}
-
-		line[i] = 0;
-
-
-		if ( truncate_len > 0 )	{
-			int width_dim, height_dim;
-			gr_get_string_size(&width_dim, &height_dim, line, truncate_len );
-			gr_string(x+width_dim, y, &line[truncate_len]);
-		} else {
-			gr_string(x, y, line);
-		}
+		gr_string(x + offset, y, char_seq);    
 	}
 }
 
@@ -1618,7 +1614,10 @@
 
 		case 'P':
 			return BRIEF_TEXT_LIGHT_PINK;
- 
+
+		case '|':	//This is not a duplicate, but a Non-Breaking Space case. Do not remove.
+			return BRIEF_TEXT_WHITE;
+
 		default:	//Zacam: Changed fron an Int3() in order to provide better feedback while still allowing play.
 			Warning(LOCATION, "Unrecognized or undefined case character: '$%c' used in Briefing in mission: '%s'. Tell Zacam.", c, Mission_filename);
 	} // end switch
@@ -1632,51 +1631,68 @@
 	gr_set_color_fast(Brief_text_colors[color_index]);
 }
 
-// Set up the Colored_text array.
-// input:		index		=>		Index into Brief_text[] for source text.
-//					instance	=>		Which instance of Colored_text[] to use.  
-//										Value is 0 unless multiple text streams are required.
+// Returns true when a character is a word separator.
+// @param character is the character to be analysed
+// @return true when the given character is a word separator, and false when the caracter is part of a word.
+bool is_a_word_separator(char character){
+	return character<=33					//  2 characters including (space) and !
+		|| (35<=character && character<=38)	//  4 characters #$%&
+		|| (42<=character && character<=44)	//  3 characters *+,
+		|| (character == 47)				//  1 character  /
+		|| (59<=character && character<=64)	//  6 characters ;<=>?@
+		|| (91<=character && character<=95)	//  5 characters [\]^_
+		|| (123<=character&&character<=127);//  5 characters {|}~
+}
+
+// Builds a vector of colored characters from a string containing color markups
+// and stores it to Colored_stream table.
+// A color markup is made of a minimum of three characters: 
+//   '$' + a char standing for a color + contigous multiple spaces (chars \t \n and ' ')
+// The markup is completely removed from the resulting character sequence.
+// @param src a not null pointer to a C string terminated by a /0 char.
+// @param instance index into Colored_stream where the result should be placed.
+//	  			   Value is 0 unless multiple text streams are required.
+// @return number of character of the resulting sequence.
 int brief_text_colorize(char *src, int instance)
 {
-	int len, i, skip_to_next_word = 0;
-	colored_char dest; 
-	briefing_line dest_line; 
+	Assert(src);
+	Assert( 0<=instance && instance < (sizeof(Colored_stream)/sizeof(*Colored_stream)) );
 
-	ubyte active_color_index = BRIEF_TEXT_WHITE;
+	briefing_line dest_line; //the resulting vector of colored character
+	ubyte active_color_index = BRIEF_TEXT_WHITE; //the current drawing color
 
-	len = strlen(src);
-	for (i=0; i<len; i++) {
-		if (skip_to_next_word) {
-			if (is_white_space(src[i])) {
-				skip_to_next_word = 0;
-			}
+	int src_len = strlen(src);
+	for (int i=0; i<src_len; i++) {
+		// Is the character a color markup?
+		// text markup consists of a '$' plus a character plus an optional space
+		if ( (i < src_len - 1)  && (src[i] == BRIEF_META_CHAR) ) {
+			i++;   //Consume the $ character
+			active_color_index = brief_return_color_index(src[i]);
+			i++; // Consume the color identifier and focus on the white character (if any)
+ 
+			// Skip every whitespace until the next word is reached
+			while ( (i < src_len) && is_white_space(src[i]) )
+				i++;
 
+			//The next character is not a whitespace, let's process it as usual
+			//(subtract 1 because the for loop will add it again)
+			i--;
 			continue;
-		}
+ 		}
 
-		if ( src[i] == BRIEF_META_CHAR && is_white_space(src[i + 2]) ) {
-			active_color_index = brief_return_color_index(src[i + 1]);
-			skip_to_next_word = 1;
-			continue;
-		}
-
+		// When the word is terminated reset color to white
 		if (is_white_space(src[i])) {
 			active_color_index = BRIEF_TEXT_WHITE;
 		}
 
+		// Append the character to the result structure
+		colored_char dest;
 		dest.letter = src[i];
 		dest.color = active_color_index;
-
-		dest_line.push_back(dest); 
-	} // end for
-
-	// null terminate the line
-	dest.letter = 0;
-	dest.color = BRIEF_TEXT_WHITE; 
-	dest_line.push_back(dest);
-	Colored_stream[instance].push_back(dest_line); 
-	Colored_stream[instance].size();
-	return len;
+		dest_line.push_back(dest);
+	} 
+	Colored_stream[instance].push_back(dest_line); 	
+	return dest_line.size();
 }
 
 // ------------------------------------------------------------------------------------
M1992_01032010.patch (10,293 bytes)   

Zacam

2010-01-09 18:53

administrator   ~0011506

Current version of the .patch attached. Currently '$|' should probably still be treated just like any other '$c' case in terms of space, but the space is optional unless it happens before a newline/return.

Goober5000

2010-01-25 03:24

administrator   ~0011585

Patch applied.

Issue History

Date Modified Username Field Change
2009-09-14 23:16 FUBAR-BDHR New Issue
2009-09-14 23:58 FUBAR-BDHR File Added: 1briefcolor.fs2
2009-09-15 01:01 FUBAR-BDHR Note Added: 0011176
2009-09-15 06:07 FUBAR-BDHR File Added: 1992.jpg
2009-09-15 06:08 FUBAR-BDHR Note Added: 0011177
2009-09-15 13:49 karajorma Note Added: 0011178
2009-09-15 21:29 FUBAR-BDHR Note Added: 0011179
2009-09-15 21:54 FUBAR-BDHR Note Edited: 0011179
2009-11-10 17:29 Zacam Status new => assigned
2009-11-10 17:29 Zacam Assigned To => Zacam
2009-11-10 23:23 pedro Note Added: 0011242
2009-11-10 23:55 pedro Note Edited: 0011242
2009-11-10 23:55 pedro File Added: 0001992.patch
2010-01-09 18:52 Zacam File Added: M1992_01032010.patch
2010-01-09 18:53 Zacam Note Added: 0011506
2010-01-09 18:54 Zacam Status assigned => feedback
2010-01-25 03:24 Goober5000 Note Added: 0011585
2010-01-25 03:24 Goober5000 Status feedback => resolved
2010-01-25 03:24 Goober5000 Resolution open => fixed