[mw-devel] [Git][milliways/mw][master] 2 commits: Rework colour handling with a view to making it more flexible

Alice Mitchell alice at sucs.org
Thu Mar 28 23:41:41 GMT 2019


Alice Mitchell pushed to branch master at milliways / mw


Commits:
3b97891f by Alice Mitchell at 2019-03-28T22:13:07Z
Rework colour handling with a view to making it more flexible

- - - - -
15a0fb44 by Alice Mitchell at 2019-03-28T23:40:35Z
Add simple ANSI-256 colour sequences with &ff& and &ff:ff& sequences
implements #38

- - - - -


3 changed files:

- src/client/colour.c
- src/client/colour.h
- src/client/main.c


Changes:

=====================================
src/client/colour.c
=====================================
@@ -22,85 +22,166 @@ static char *colour_set=NULL;
 /* the current user template */
 extern struct user * const user;
 
-/* return colour code sequence */
-char *colour(char *text)
+/* safe copy string */
+static void copy_in(char *dest, int len, const char *input)
 {
-	static char line[40];
-	int i;
+	snprintf(dest, len, "%s", input);
+}
 
-	line[0]=0;
+static int hex_decode(const char *input, int len)
+{
+	int i=0;
+	int total=0;
 
-	/* system colour chart */
-	if (strchr("0123456789",text[0]))
-	{
-		i=atoi(text);
-
-		if (i<0 || i>= COLOUR_LIMIT) return(line);
-		if (colour_chart[i]==NULL)
-			if (colour_chart[0]==NULL)
-				return(line);
-			else
-				return (colour_chart[0]);
+	while (i<len && *input) {
+		total <<= 4;
+		if (*input >= '0' && *input <= '9')
+			total |= *input - '0';
 		else
-			return (colour_chart[i]);
-	}
-
-	i=0;
-	line[i++]=033;
-	line[i++]='[';
-
-	/* reset string ? */
-	if (strchr("-n", text[0]) &&
-	    strchr("-n", text[1]) )
-	{
-		line[i++]='m';
-		line[i]=0;
-		return(line);
-	}
-
-	/* high intensity mode? */
-	if (isupper(text[0]))
-	{
-		line[i++]='1';
-		line[i++]=';';
-	} else {
-		line[i++]='0';
-		line[i++]=';';
+		if (*input >= 'a' && *input <= 'f')
+			total |= (*input - 'a') + 10;
+		else
+		if (*input >= 'A' && *input <= 'F')
+			total |= (*input - 'a') + 10;
+		input++;
+		i++;
 	}
+	return total;
+}
 
-	if (strchr("kKrRgGyYbBmMcCwW", text[0])!=NULL)
-	{
-		if (strchr("n-", text[0])==NULL) line[i++]='3';
-		if (strchr("kK",text[0])) line[i++]='0'; else
-		if (strchr("rR",text[0])) line[i++]='1'; else
-		if (strchr("gG",text[0])) line[i++]='2'; else
-		if (strchr("yY",text[0])) line[i++]='3'; else
-		if (strchr("bB",text[0])) line[i++]='4'; else
-		if (strchr("mM",text[0])) line[i++]='5'; else
-		if (strchr("cC",text[0])) line[i++]='6'; else
-		if (strchr("wW",text[0])) line[i++]='7';
-
-		/* seperator */
-		if (strchr("n-",text[0])==NULL && strchr("n-",text[1])==NULL) line[i++]=';';
+/* return colour code sequence */
+int colour(const char *input, char *output, int outlen)
+{
+	int consume = 0;
+
+	/* original colour mode */
+	if (*input == 033) {
+		char text[3];
+		int i = 0;
+		consume = 1;
+		/* build the string, skipping unicode sequences */
+		while (i < 2 && input[consume] != 0) {
+			if ((input[consume] & 192) == 192) {
+				consume++;
+				text[i++] = '-';
+				while ((input[consume] & 192) == 128)
+					consume++;
+			} else {
+				text[i++] = input[consume++];
+			}
+		}
+		text[2] = '\0';
+
+		/* system colour chart */
+		if (strchr("0123456789",text[0]))
+		{
+			i=atoi(text);
+
+			if (i>=0 && i < COLOUR_LIMIT) {
+				if (colour_chart[i] != NULL)
+					copy_in(output, outlen, colour_chart[i]);
+				else
+				if (colour_chart[0] != NULL)
+					copy_in(output, outlen, colour_chart[0]);
+			}
+			return consume;
+		}
+
+		i=0;
+		output[i++] = 033;
+		output[i++] = '[';
+
+		/* reset string ? */
+		if (strchr("-n", text[0]) &&
+		    strchr("-n", text[1]) )
+		{
+			output[i++] = 'm';
+			output[i] = '\0';
+			return(consume);
+		}
+
+		/* high intensity mode? */
+		if (isupper(text[0]))
+		{
+			output[i++] = '1';
+			output[i++] = ';';
+		} else {
+			output[i++] = '0';
+			output[i++] = ';';
+		}
+
+		if (strchr("kKrRgGyYbBmMcCwW", text[0])!=NULL)
+		{
+			if (strchr("n-", text[0])==NULL) output[i++] = '3';
+			if (strchr("kK",text[0])) output[i++] = '0'; else
+			if (strchr("rR",text[0])) output[i++] = '1'; else
+			if (strchr("gG",text[0])) output[i++] = '2'; else
+			if (strchr("yY",text[0])) output[i++] = '3'; else
+			if (strchr("bB",text[0])) output[i++] = '4'; else
+			if (strchr("mM",text[0])) output[i++] = '5'; else
+			if (strchr("cC",text[0])) output[i++] = '6'; else
+			if (strchr("wW",text[0])) output[i++] = '7';
+
+			/* seperator */
+			if (strchr("n-",text[0])==NULL && strchr("n-",text[1])==NULL)
+				output[i++] = ';';
+		}
+
+		if (strchr("kKrRgGyYbBmMcCwW", text[1])!=NULL)
+		{
+			/* now background colour */
+			if (strchr("n-",text[1])==NULL) output[i++] = '4';
+			if (strchr("kK",text[1])) output[i++] = '0'; else
+			if (strchr("rR",text[1])) output[i++] = '1'; else
+			if (strchr("gG",text[1])) output[i++] = '2'; else
+			if (strchr("yY",text[1])) output[i++] = '3'; else
+			if (strchr("bB",text[1])) output[i++] = '4'; else
+			if (strchr("mM",text[1])) output[i++] = '5'; else
+			if (strchr("cC",text[1])) output[i++] = '6'; else
+			if (strchr("wW",text[1])) output[i++] = '7';
+		}
+
+		output[i++] = 'm';
+		output[i] = '\0';
 	}
-
-	if (strchr("kKrRgGyYbBmMcCwW", text[1])!=NULL)
-	{
-		/* now background colour */
-		if (strchr("n-",text[1])==NULL) line[i++]='4';
-		if (strchr("kK",text[1])) line[i++]='0'; else
-		if (strchr("rR",text[1])) line[i++]='1'; else
-		if (strchr("gG",text[1])) line[i++]='2'; else
-		if (strchr("yY",text[1])) line[i++]='3'; else
-		if (strchr("bB",text[1])) line[i++]='4'; else
-		if (strchr("mM",text[1])) line[i++]='5'; else
-		if (strchr("cC",text[1])) line[i++]='6'; else
-		if (strchr("wW",text[1])) line[i++]='7';
+	if (*input == '&') {
+		/* first let us test this is a valid colour string */
+		const char *p = input + 1;
+		/* skip past all valid chars */
+		while (*p && strchr("0123456789AbBcCdDeEfF:", *p)) p++;
+		/* not the ending we were expecting, ignore it then */
+		if (*p != '&') return 0;
+
+		char hex[7];
+		int i = 0;
+		consume = 1;
+		while (i < 7 && input[consume] && strchr("0123456789AbBcCdDeEfF", input[consume]))
+			hex[i++] = input[consume++];
+		hex[i] = '\0';
+
+		if (i == 2) {
+			int col = hex_decode(hex, 2);
+			snprintf(output, outlen, "\033[38;5;%dm", col);
+		}
+
+		if (input[consume] == ':') {
+			consume++;
+			i=0;
+			while (i < 7 && input[consume] && strchr("0123456789AbBcCdDeEfF", input[consume]))
+				hex[i++] = input[consume++];
+			hex[i] = '\0';
+
+			if (i == 2) {
+				int col = hex_decode(hex, 2);
+				int off = strlen(output);
+				snprintf(&output[off], outlen-off, "\033[48;5;%dm", col);
+			}
+		}
+		while (input[consume] && strchr("0123456789AbBcCdDeEfF:", input[consume]))
+			consume++;
+		if (input[consume] == '&') consume++;
 	}
-
-	line[i++]='m';
-	line[i]=0;
-	return(line);
+	return(consume);
 }
 
 void colour_free(void)


=====================================
src/client/colour.h
=====================================
@@ -7,7 +7,7 @@ void init_colour(void);
 void destroy_colours(void);
 void colour_load(char *file, int quiet);
 void colour_free(void);
-char *colour(char *text);
+int colour(const char *input, char *output, int outlen);
 char *get_colour(void);
 
 #endif /* COLOUR_H */


=====================================
src/client/main.c
=====================================
@@ -1070,140 +1070,83 @@ void format_message(const char *format, ...)
 
 void display_message(const char *text, int beeps, int newline)
 {
-	static int	count = 0;
-	char		line[MAXTEXTLENGTH];
-	int		i, j, colrstart;
-	int		hascolour;
+	char		outline[MAXTEXTLENGTH];
+	int		olen = 0;
 	int		screen_width = screen_w();
-	char		*colr = NULL;
-	int		endline;
+	char		colr[128];
 	int		convert_warnings=0;
-	const unsigned char *ptr = (const unsigned char *)text;
-	const unsigned char *end;
+	int		charcount = 0;
+	bool		endline;
 	size_t not_in_local = 0;
-	size_t len;
 
-	if (text == NULL || (len = strlen(text)) == 0) {
+	if (text == NULL || strlen(text) == 0) {
 		printf("%s", _("Error: Urk, no message to print.\n"));
 		return;
 	}
-	if (UseRL && disable_rl(1)) count = 0;
-
-	i=0;
-	hascolour=0;
-	colrstart=-1;
-	end = ptr + len;
-
-	while (ptr < end) {
-		if (*ptr == 033) {
-			char str[3];
-			ptr++;
-			if (ptr < end) {
-				if ((*ptr & 192) == 192) {
-					ptr++;
-					str[0] = '-';
-					while ((*ptr & 192) == 128 && ptr < end)
-						ptr++;
-				} else {
-					str[0] = *ptr;
-					ptr++;
-				}
-			}
-			if (ptr < end) {
-				if((*ptr & 192) == 192) {
-					ptr++;
-					str[1] = '-';
-					while((*ptr & 192) == 128 && ptr < end)
-						ptr++;
-				} else {
-					str[1] = *ptr;
-					ptr++;
-				}
-			}
-
+	if (UseRL && disable_rl(1)) charcount = 0;
+	
+	while (*text) {
+		if (*text == 033 || *text == '&') {
 			/* escape sequence, skip next two chars */
-			if (s_colouroff(user))
-				goto eolprint;
 
-			hascolour++;
-			str[2] = 0;
-			colr = colour(str);
+			text += colour(text, colr, sizeof(colr));
 
-			if (colr!=NULL)
-			{
-				if (colrstart >= 0)
-					i = colrstart;
-				else
-					colrstart = i;
-
-				for (j = 0; j < strlen(colr); j++)
-					line[i++] = colr[j];
+			if (colr[0] && !s_colouroff(user)) {
+				for (int j = 0; j < strlen(colr); j++)
+					outline[olen++] = colr[j];
 			}
-		} else if (*ptr >= 040 && *ptr <= 0176) {
-			line[i++] = *ptr;
-			count++;
-			colrstart = -1;
-			ptr++;
-		} else if ((*ptr & 192) == 192) {
-			line[i++] = *ptr;
-			count++;
-			colrstart = -1;
-			ptr++;
+		} else if (*text >= 040 && *text <= 0176) {
+			outline[olen++] = *text++;
+			charcount++;
+		} else if ((*text & 192) == 192) {
+			outline[olen++] = *text++;
 			// stops us randomly splitting over a unicode multibyte character
-			while ((*ptr & 192) == 128 && ptr < end) {
-				line[i++] = *ptr;
-				colrstart = -1;
-				ptr++;
+			while ((*text & 192) == 128 && *text) {
+				outline[olen++] = *text++;
 			}
+			charcount++;
 		} else {
-			ptr++;
+			text++;
 		}
-		if (i >= (MAXTEXTLENGTH-20))
-		{
-			line[i]='\0';
-			printline_in_local(line, &convert_warnings, &not_in_local);
-			i=0;
+		if (olen >= (MAXTEXTLENGTH-20)) {
+			outline[olen]='\0';
+			printline_in_local(outline, &convert_warnings, &not_in_local);
+			olen=0;
+			charcount=0;
 		}
-eolprint:
+
 		if (s_nolinewrap(user))
-			endline = (ptr >= end);
+			endline = (*text == 0);
 		else
-			endline = ((count >= screen_width) || (ptr >= end));
+			endline = ((charcount >= screen_width) || *text==0);
 
 		if (endline)
 		{
-			if (!s_colouroff(user) && hascolour)
-			{
-				line[i++]=033;
-				line[i++]='[';
-				line[i++]='m';
+			if (!s_colouroff(user) && colr[0]) {
+			        outline[olen++] = 033;
+			        outline[olen++] = '[';
+			        outline[olen++] = 'm';
 			}
 
-			if (newline || (ptr < end))
-			{
-				line[i++]='\n';
-				count=0;
+			if (newline || *text) {
+			        outline[olen++] = '\n';
+				charcount=0;
 			}
 
-			line[i]='\0';
-			printline_in_local(line, &convert_warnings, &not_in_local);
+			outline[olen++] = '\0';
+			printline_in_local(outline, &convert_warnings, &not_in_local);
+
+			olen = 0;
+			if (newline) charcount=0;
+
+			if (*text) {
+				outline[olen++] = ' ';
+				charcount = 1;
 
-			if (ptr >= end)
-			{
-				i=0;
-				if (newline) count=0;
-			} else
-			{
-				i=2;
-				count=2;
-				strcpy(line,"  ");
 				/* Restore the colour from the last line */
-				if (!s_colouroff(user) &&
-				    hascolour &&
-				    colr!=NULL)
-				{
-				    for (j=0; j < strlen(colr); j++)
-					    line[i++] = colr[j];
+				if (!s_colouroff(user) && colr[0]) {
+				    for (int j=0; j < strlen(colr); j++)
+					    outline[olen++] = colr[j];
 				}
 			}
 		}



View it on GitLab: https://projects.sucs.org/milliways/mw/compare/fe4f0419b80c691e821a38623712b7f86d9bcb7c...15a0fb4485dee17929cb033ab49c6322f9a9c729

-- 
View it on GitLab: https://projects.sucs.org/milliways/mw/compare/fe4f0419b80c691e821a38623712b7f86d9bcb7c...15a0fb4485dee17929cb033ab49c6322f9a9c729
You're receiving this email because of your account on projects.sucs.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.sucs.org/pipermail/mw-devel/attachments/20190328/9b58db94/attachment-0001.html>


More information about the mw-devel mailing list