Skip to content
This repository has been archived by the owner on Apr 17, 2020. It is now read-only.

[PATCH] Color support for "gui_entry" to allow better spellcheckers. #621

Open
irssibot opened this issue Sep 8, 2008 · 1 comment
Open

Comments

@irssibot
Copy link
Collaborator

irssibot commented Sep 8, 2008

This patch adds color support to the "gui_entry" input line.
It does so, by assigning a color to each character. The color is stored in a GUI_ENTRY_REC as int *colors.

To use the functionality, I added the method:
void gui_entry_set_color(GUI_ENTRY_REC *entry, int pos, int len, int color);

On top of this, for the Perl bindings I added:
gui_input_color(pos, len, color)

I am not sure about exact naming conventions, but this would be trivial to change anyway.

The main purpose for now (and my main motivation) is to provide better support for spellcheckers by marking misspelled words.
See http://outpo.st/irssi/spellcheck.pl for an implementation based on the original script by Jakub Jankowski.

@irssibot
Copy link
Collaborator Author

irssibot commented Sep 8, 2008

      • Attachment 166 by @jott

color_support_for_gui_entry.diff

Index: src/perl/textui/TextUI.xs
===================================================================
--- src/perl/textui/TextUI.xs	(revision 4874)
+++ src/perl/textui/TextUI.xs	(working copy)
@@ -123,6 +123,14 @@
 CODE:
 	gui_entry_set_text(active_entry, str);
 
+void
+gui_input_color(pos, len, color)
+	int pos
+	int len
+	int color
+CODE:
+	gui_entry_set_color(active_entry, pos, len, color);
+
 int
 gui_input_get_pos()
 CODE:
Index: src/fe-text/gui-entry.c
===================================================================
--- src/fe-text/gui-entry.c	(revision 4874)
+++ src/fe-text/gui-entry.c	(working copy)
@@ -64,6 +64,8 @@
 	entry->text_alloc = nearest_power(entry->text_alloc+grow_size);
 	entry->text = g_realloc(entry->text,
 				sizeof(unichar) * entry->text_alloc);
+	entry->colors = g_realloc(entry->colors,
+	                        sizeof(int) * entry->text_alloc);
 }
 
 GUI_ENTRY_REC *gui_entry_create(int xpos, int ypos, int width, int utf8)
@@ -73,11 +75,12 @@
 	rec = g_new0(GUI_ENTRY_REC, 1);
 	rec->xpos = xpos;
 	rec->ypos = ypos;
-        rec->width = width;
-        rec->text_alloc = 1024;
+	rec->width = width;
+	rec->text_alloc = 1024;
 	rec->text = g_new(unichar, rec->text_alloc);
-        rec->text[0] = '\0';
-        rec->utf8 = utf8;
+	rec->colors = g_new(int, rec->text_alloc);
+	rec->text[0] = '\0';
+	rec->utf8 = utf8;
 	return rec;
 }
 
@@ -88,7 +91,8 @@
 	if (active_entry == entry)
 		gui_entry_set_active(NULL);
 
-        g_free(entry->text);
+	g_free(entry->text);
+	g_free(entry->colors);
 	g_free(entry->prompt);
         g_free(entry);
 }
@@ -227,7 +231,8 @@
 static void gui_entry_draw_from(GUI_ENTRY_REC *entry, int pos)
 {
 	const unichar *p;
-	int xpos, end_xpos;
+	const int *c;
+	int xpos, end_xpos, color;
 
 	xpos = entry->xpos + entry->promptlen + 
 		pos2scrpos(entry, pos + entry->scrstart) - 
@@ -237,12 +242,15 @@
 	if (xpos > end_xpos)
                 return;
 
+	color = ATTR_RESET;
 	term_set_color(root_window, ATTR_RESET);
 	term_move(root_window, xpos, entry->ypos);
 
 	p = entry->scrstart + pos < entry->text_len ?
 		entry->text + entry->scrstart + pos : empty_str;
-	for (; *p != '\0'; p++) {
+	c = entry->scrstart + pos < entry->text_len ?
+		entry->colors + entry->scrstart + pos : 0;
+	for (; *p != '\0'; p++, c++) {
 		if (entry->hidden)
 			xpos++;
 		else if (term_type == TERM_TYPE_BIG5)
@@ -255,6 +263,11 @@
 		if (xpos > end_xpos)
 			break;
 
+		if (*c != color) {
+			term_set_color(root_window, *c);
+			color = c;
+		}
+			
 		if (entry->hidden)
                         term_addch(root_window, ' ');
 		else if (unichar_isprint(*p))
@@ -262,7 +275,7 @@
 		else {
 			term_set_color(root_window, ATTR_RESET|ATTR_REVERSE);
 			term_addch(root_window, (*p & 127)+'A'-1);
-			term_set_color(root_window, ATTR_RESET);
+			term_set_color(root_window, color);
 		}
 	}
 
@@ -456,6 +469,10 @@
 	g_memmove(entry->text + entry->pos + len, entry->text + entry->pos,
 		  (entry->text_len-entry->pos + 1) * sizeof(unichar));
 
+	/* make space for the color */
+	g_memmove(entry->colors + entry->pos + len, entry->colors + entry->pos,
+	          (entry->text_len-entry->pos) * sizeof(int));
+	
 	if (!entry->utf8) {
 		if (term_type == TERM_TYPE_BIG5) {
 			chr = entry->text[entry->pos + len];
@@ -470,6 +487,10 @@
 		utf8_to_utf16(str, entry->text+entry->pos);
                 entry->text[entry->pos+len] = chr;
 	}
+	
+	for (i = 0; i < len; i++) {
+		entry->colors[entry->pos + i] = ATTR_RESET;
+	}
 
 	entry->text_len += len;
         entry->pos += len;
@@ -495,8 +516,13 @@
 	/* make space for the string */
 	g_memmove(entry->text + entry->pos + 1, entry->text + entry->pos,
 		  (entry->text_len-entry->pos + 1) * sizeof(unichar));
-
+	
+	g_memmove(entry->colors + entry->pos + 1, entry->colors + entry->pos,
+	          (entry->text_len-entry->pos) * sizeof(int));
+	
+	
 	entry->text[entry->pos] = chr;
+	entry->colors[entry->pos] = ATTR_RESET;
 	entry->text_len++;
         entry->pos++;
 
@@ -571,8 +597,11 @@
 		w = cell_width(entry->text + entry->pos - size, entry->pos - size + 1)-1;
 
 	g_memmove(entry->text + entry->pos - size, entry->text + entry->pos,
-		  (entry->text_len-entry->pos+1) * sizeof(unichar));
-
+	          (entry->text_len-entry->pos+1) * sizeof(unichar));
+	
+	g_memmove(entry->colors+ entry->pos - size, entry->colors + entry->pos,
+	          (entry->text_len-entry->pos) * sizeof(int));
+	
 	entry->pos -= size;
         entry->text_len -= size;
 
@@ -592,8 +621,11 @@
 		       mk_wcwidth(entry->text[entry->pos+size]) == 0) size++;
 
 	g_memmove(entry->text + entry->pos, entry->text + entry->pos + size,
-		  (entry->text_len-entry->pos-size+1) * sizeof(unichar));
-
+	          (entry->text_len-entry->pos-size+1) * sizeof(unichar));
+	
+	g_memmove(entry->colors + entry->pos, entry->colors + entry->pos + size,
+	          (entry->text_len-entry->pos-size) * sizeof(int));
+	
 	entry->text_len -= size;
 
 	gui_entry_redraw_from(entry, entry->pos);
@@ -655,6 +687,7 @@
 void gui_entry_transpose_chars(GUI_ENTRY_REC *entry)
 {
         unichar chr;
+	int color;
 
 	if (entry->pos == 0 || entry->text_len < 2)
                 return;
@@ -666,7 +699,11 @@
 	chr = entry->text[entry->pos];
 	entry->text[entry->pos] = entry->text[entry->pos-1];
         entry->text[entry->pos-1] = chr;
-
+	
+	color = entry->colors[entry->pos];
+	entry->colors[entry->pos] = entry->colors[entry->pos-1];
+	entry->colors[entry->pos-1] = color;
+	
         entry->pos++;
 
 	gui_entry_redraw_from(entry, entry->pos-2);
@@ -703,31 +740,50 @@
 	/* do wordswap if any found */
 	if (spos1 < epos1 && epos1 < spos2 && spos2 < epos2) {
 		unichar *first, *sep, *second;
+		int *first_color, *sep_color, *second_color;
 		int i;
 
 		first  = (unichar *) g_malloc( (epos1 - spos1) * sizeof(unichar) );
 		sep    = (unichar *) g_malloc( (spos2 - epos1) * sizeof(unichar) );
 		second = (unichar *) g_malloc( (epos2 - spos2) * sizeof(unichar) );
 
-		for (i = spos1; i < epos1; i++)
+		first_color  = (int *) g_malloc( (epos1 - spos1) * sizeof(int) );
+		sep_color    = (int *) g_malloc( (spos2 - epos1) * sizeof(int) );
+		second_color = (int *) g_malloc( (epos2 - spos2) * sizeof(int) );
+		
+		for (i = spos1; i < epos1; i++) {
 			first[i-spos1] = entry->text[i];
-		for (i = epos1; i < spos2; i++)
+			first_color[i-spos1] = entry->colors[i];
+		}
+		for (i = epos1; i < spos2; i++) {
 			sep[i-epos1] = entry->text[i];
-		for (i = spos2; i < epos2; i++)
+			sep_color[i-epos1] = entry->colors[i];
+		}
+		for (i = spos2; i < epos2; i++) {
 			second[i-spos2] = entry->text[i];
+			second_color[i-spos2] = entry->colors[i];
+		}
 
 		entry->pos = spos1;
-		for (i = 0; i < epos2-spos2; i++)
+		for (i = 0; i < epos2-spos2; i++) {
 			entry->text[entry->pos++] = second[i];
-		for (i = 0; i < spos2-epos1; i++)
+			entry->colors[entry->pos++] = second_color[i];
+		}
+		for (i = 0; i < spos2-epos1; i++) {
 			entry->text[entry->pos++] = sep[i];
-		for (i = 0; i < epos1-spos1; i++)
+			entry->colors[entry->pos++] = sep_color[i];
+		}
+		for (i = 0; i < epos1-spos1; i++) {
 			entry->text[entry->pos++] = first[i];
-
+			entry->colors[entry->pos++] = first_color[i];
+		}
+		
 		g_free(first);
 		g_free(sep);
 		g_free(second);
-
+		g_free(first_color);
+		g_free(sep_color);
+		g_free(second_color);
 	}
 	
 	gui_entry_redraw_from(entry, spos1);
@@ -895,3 +951,31 @@
 	gui_entry_fix_cursor(entry);
 	gui_entry_draw(entry);
 }
+
+void gui_entry_set_color(GUI_ENTRY_REC *entry, int pos, int len, int color)
+{
+	int i, end, update = 0;
+	
+	g_return_if_fail(entry != NULL);
+
+	if (pos > entry->text_len)
+		return;
+
+	end = pos + len;
+
+	if (end > entry->text_len)
+		end = entry->text_len;
+
+	for (i = pos; i < end; i++) {
+		if (entry->colors[i] != color) {
+			entry->colors[i] = color;
+			update = 1;
+		}
+	}
+
+	if (update) {
+		gui_entry_redraw_from(entry, pos);
+		gui_entry_fix_cursor(entry);
+		gui_entry_draw(entry);
+	}
+}
Index: src/fe-text/gui-entry.h
===================================================================
--- src/fe-text/gui-entry.h	(revision 4874)
+++ src/fe-text/gui-entry.h	(working copy)
@@ -4,6 +4,7 @@
 typedef struct {
 	int text_len, text_alloc; /* as shorts, not chars */
 	unichar *text;
+	int *colors;
 
         int cutbuffer_len;
 	unichar *cutbuffer;
@@ -60,4 +61,6 @@
 
 void gui_entry_redraw(GUI_ENTRY_REC *entry);
 
+void gui_entry_set_color(GUI_ENTRY_REC *entry, int pos, int len, int color);
+
 #endif

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Development

No branches or pull requests

1 participant