Browse Source

First version of UTF-8 support.

git-svn-id: https://klish.googlecode.com/svn/trunk@340 0eaa4687-2ee9-07dd-09d9-bcdd2d2dd5fb
Serj Kalichev 13 years ago
parent
commit
2790d2d1cf
5 changed files with 101 additions and 19 deletions
  1. 9 1
      bin/clish.cpp
  2. 2 0
      clish/shell.h
  3. 14 0
      clish/shell/shell_tinyrl.c
  4. 72 18
      tinyrl/tinyrl.c
  5. 4 0
      tinyrl/tinyrl.h

+ 9 - 1
bin/clish.cpp

@@ -53,6 +53,7 @@ int main(int argc, char **argv)
 	bool_t stop_on_error = BOOL_FALSE;
 	bool_t interactive = BOOL_TRUE;
 	bool_t quiet = BOOL_FALSE;
+	bool_t utf8 = BOOL_FALSE;
 	const char *xml_path = getenv("CLISH_PATH");
 	const char *view = getenv("CLISH_VIEW");
 	const char *viewid = getenv("CLISH_VIEWID");
@@ -62,7 +63,7 @@ int main(int argc, char **argv)
 	struct sigaction sigpipe_act;
 	sigset_t sigpipe_set;
 
-	static const char *shortopts = "hvs:ledx:w:i:bq";
+	static const char *shortopts = "hvs:ledx:w:i:bqu";
 #ifdef HAVE_GETOPT_H
 	static const struct option longopts[] = {
 		{"help",	0, NULL, 'h'},
@@ -76,6 +77,7 @@ int main(int argc, char **argv)
 		{"viewid",	1, NULL, 'i'},
 		{"background",	0, NULL, 'b'},
 		{"quiet",	0, NULL, 'q'},
+		{"utf8",	0, NULL, 'u'},
 		{NULL,		0, NULL, 0}
 	};
 #endif
@@ -115,6 +117,9 @@ int main(int argc, char **argv)
 		case 'q':
 			quiet = BOOL_TRUE;
 			break;
+		case 'u':
+			utf8 = BOOL_TRUE;
+			break;
 		case 'd':
 			my_hooks.script_fn = clish_dryrun_callback;
 			break;
@@ -166,6 +171,8 @@ int main(int argc, char **argv)
 	/* Set startup viewid */
 	if (viewid)
 		clish_shell__set_startup_viewid(shell, viewid);
+	/* Set UTF-8 mode if needed */
+	clish_shell__set_utf8(shell, utf8);
 	/* Execute startup */
 	running = clish_shell_startup(shell);
 	if (!running) {
@@ -229,6 +236,7 @@ static void help(int status, const char *argv0)
 		printf("\t-x, --xml-path\tPath to XML scheme files.\n");
 		printf("\t-w, --view\tSet the startup view.\n");
 		printf("\t-i, --viewid\tSet the startup viewid.\n");
+		printf("\t-u, --utf8\tSuppose the console mode is UTF-8.\n");
 	}
 }
 

+ 2 - 0
clish/shell.h

@@ -388,6 +388,8 @@ char * clish_shell__expand_variable(const clish_shell_t *instance,
 const char * clish_shell__get_fifo(clish_shell_t * instance);
 void clish_shell__set_interactive(clish_shell_t * instance, bool_t interactive);
 bool_t clish_shell__get_interactive(const clish_shell_t * instance);
+bool_t clish_shell__get_utf8(const clish_shell_t * instance);
+void clish_shell__set_utf8(clish_shell_t * instance, bool_t utf8);
 
 _END_C_DECL
 

+ 14 - 0
clish/shell/shell_tinyrl.c

@@ -484,3 +484,17 @@ bool_t clish_shell__get_interactive(const clish_shell_t * this)
 }
 
 /*-------------------------------------------------------- */
+bool_t clish_shell__get_utf8(const clish_shell_t * this)
+{
+	assert(this);
+	return tinyrl__get_utf8(this->tinyrl);
+}
+
+/*-------------------------------------------------------- */
+void clish_shell__set_utf8(clish_shell_t * this, bool_t utf8)
+{
+	assert(this);
+	tinyrl__set_utf8(this->tinyrl, utf8);
+}
+
+/*-------------------------------------------------------- */

+ 72 - 18
tinyrl/tinyrl.c

@@ -19,6 +19,45 @@
 
 #include "private.h"
 
+/*-------------------------------------------------------- */
+static void utf8_point_left(tinyrl_t * this)
+{
+	if (this->utf8) {
+		while (this->point &&
+			(UTF8_10 == (this->buffer[this->point] & UTF8_MASK)))
+			this->point--;
+	}
+}
+
+/*-------------------------------------------------------- */
+static void utf8_point_right(tinyrl_t * this)
+{
+	if (this->utf8) {
+		while ((this->point < this->end) &&
+			(UTF8_10 == (this->buffer[this->point] & UTF8_MASK)))
+			this->point++;
+	}
+}
+
+/*-------------------------------------------------------- */
+static unsigned utf8_nsyms(tinyrl_t * this, const char *str, unsigned num)
+{
+	unsigned nsym = 0;
+	unsigned i;
+
+	if (!this->utf8)
+		return num;
+	for (i = 0; i < num; i++) {
+		if ('\0' == str[i])
+			break;
+		if (UTF8_10 == (str[i] & UTF8_MASK))
+			continue;
+		nsym++;
+	}
+
+	return nsym;
+}
+
 /*----------------------------------------------------------------------- */
 static void tty_set_raw_mode(tinyrl_t * this)
 {
@@ -213,6 +252,7 @@ static bool_t tinyrl_key_left(tinyrl_t * this, int key)
 	bool_t result = BOOL_FALSE;
 	if (this->point > 0) {
 		this->point--;
+		utf8_point_left(this);
 		result = BOOL_TRUE;
 	}
 	/* keep the compiler happy */
@@ -226,6 +266,7 @@ static bool_t tinyrl_key_right(tinyrl_t * this, int key)
 	bool_t result = BOOL_FALSE;
 	if (this->point < this->end) {
 		this->point++;
+		utf8_point_right(this);
 		result = BOOL_TRUE;
 	}
 	/* keep the compiler happy */
@@ -238,8 +279,9 @@ static bool_t tinyrl_key_backspace(tinyrl_t * this, int key)
 {
 	bool_t result = BOOL_FALSE;
 	if (this->point) {
-		this->point--;
-		tinyrl_delete_text(this, this->point, this->point);
+		unsigned end = --this->point;
+		utf8_point_left(this);
+		tinyrl_delete_text(this, this->point, end);
 		result = BOOL_TRUE;
 	}
 	/* keep the compiler happy */
@@ -252,7 +294,9 @@ static bool_t tinyrl_key_delete(tinyrl_t * this, int key)
 {
 	bool_t result = BOOL_FALSE;
 	if (this->point < this->end) {
-		tinyrl_delete_text(this, this->point, this->point);
+		unsigned end = this->point;
+		utf8_point_left(this);
+		tinyrl_delete_text(this, this->point, end);
 		result = BOOL_TRUE;
 	}
 	/* keep the compiler happy */
@@ -507,19 +551,24 @@ void tinyrl_redisplay(tinyrl_t * this)
 							  this->point);
 						/* just get the terminal to delete the characters */
 						if (shift > 0) {
-							count = (unsigned)shift;
+							count = utf8_nsyms(this,
+								this->last_buffer + this->point,
+								(unsigned)shift);
 							/* we've moved the cursor backwards */
 							tinyrl_vt100_cursor_back
 							    (this->term, count);
 						} else if (shift < 0) {
-							count =
-							    (unsigned)-shift;
+							count = utf8_nsyms(this,
+								this->last_buffer + this->last_point,
+								(unsigned)-shift);
 							/* we've moved the cursor forwards */
 							tinyrl_vt100_cursor_forward
 							    (this->term, count);
 						}
 						/* now delete the characters */
-						count = (unsigned)-delta;
+						count = utf8_nsyms(this,
+							this->last_buffer + line_len,
+							(unsigned)-delta);
 						tinyrl_vt100_erase(this->term,
 								   count);
 					}
@@ -534,13 +583,16 @@ void tinyrl_redisplay(tinyrl_t * this)
 						    (int)(this->point -
 							  this->last_point);
 						if (delta > 0) {
-							count = (unsigned)delta;
+							count = utf8_nsyms(this,
+								this->line + this->last_point,
+								(unsigned)delta);
 							/* move the point forwards */
 							tinyrl_vt100_cursor_forward
 							    (this->term, count);
 						} else if (delta < 0) {
-							count =
-							    (unsigned)-delta;
+							count = utf8_nsyms(this,
+								this->line + this->point,
+								(unsigned)-delta);
 							/* move the cursor backwards */
 							tinyrl_vt100_cursor_back
 							    (this->term, count);
@@ -556,9 +608,10 @@ void tinyrl_redisplay(tinyrl_t * this)
 			tinyrl_internal_print(this, this->line);
 			if (this->point < line_len) {
 				/* move the cursor to the insertion point */
-				tinyrl_vt100_cursor_back(this->term,
-							 line_len -
-							 this->point);
+				count = utf8_nsyms(this,
+					this->line + this->point,
+					line_len - this->point);
+				tinyrl_vt100_cursor_back(this->term, count);
 			}
 			break;
 		}
@@ -567,10 +620,12 @@ void tinyrl_redisplay(tinyrl_t * this)
 		 */
 		if (this->last_point) {
 			/* move to just after the prompt of the line */
-			tinyrl_vt100_cursor_back(this->term, this->last_point);
+			count = utf8_nsyms(this, this->last_buffer, this->last_point);
+			tinyrl_vt100_cursor_back(this->term, count);
 		}
 		/* erase the previous line */
-		tinyrl_vt100_erase(this->term, strlen(this->last_buffer));
+		count = utf8_nsyms(this, this->last_buffer, last_line_len);
+		tinyrl_vt100_erase(this->term, count);
 
 		/* output the line accounting for the echo behaviour */
 		tinyrl_internal_print(this, this->line);
@@ -578,9 +633,8 @@ void tinyrl_redisplay(tinyrl_t * this)
 		delta = (int)(line_len - this->point);
 		if (delta) {
 			/* move the cursor back to the insertion point */
-			tinyrl_vt100_cursor_back(this->term,
-						 (strlen(this->line) -
-						  this->point));
+			count = utf8_nsyms(this, this->line + this->point, delta);
+			tinyrl_vt100_cursor_back(this->term, count);
 		}
 	} /*lint -e717 */ while (0)	/*lint +e717 */
 	;

+ 4 - 0
tinyrl/tinyrl.h

@@ -15,6 +15,10 @@ from a CLI in a "readline" like fashion.
 #include "lub/c_decl.h"
 #include "tinyrl/history.h"
 
+#define UTF8_MASK 0xC0
+#define UTF8_11   0xC0
+#define UTF8_10   0x80
+
 _BEGIN_C_DECL typedef struct _tinyrl tinyrl_t;
 typedef enum {
     /**