about summary refs log tree commit diff
path: root/src/base
diff options
context:
space:
mode:
authorMagnus Auvinen <magnus.auvinen@gmail.com>2009-06-13 08:22:37 +0000
committerMagnus Auvinen <magnus.auvinen@gmail.com>2009-06-13 08:22:37 +0000
commit69511102de9b0f3ec6ad555baf2a01d9ee1c3dfd (patch)
treeebef66e5ab0cfd16e96026d8ac8d5a708eb68219 /src/base
parent9254ca61f1e459cbaf137ce4511332365da9c225 (diff)
downloadzcatch-69511102de9b0f3ec6ad555baf2a01d9ee1c3dfd.tar.gz
zcatch-69511102de9b0f3ec6ad555baf2a01d9ee1c3dfd.zip
improved the font system even futher. utf8 is now used everywhere. it uses less memory as well
Diffstat (limited to 'src/base')
-rw-r--r--src/base/system.c133
-rw-r--r--src/base/system.h63
2 files changed, 196 insertions, 0 deletions
diff --git a/src/base/system.c b/src/base/system.c
index 40d53e8a..c94e4cf9 100644
--- a/src/base/system.c
+++ b/src/base/system.c
@@ -1188,6 +1188,139 @@ void gui_messagebox(const char *title, const char *message)
 int str_isspace(char c) { return c == ' ' || c == '\n' || c == '\t'; }
 
 
+
+static int str_utf8_isstart(char c)
+{
+	if((c&0xC0) == 0x80)  /* 10xxxxxx */
+		return 0;
+	return 1;
+}
+
+int str_utf8_rewind(const char *str, int cursor)
+{
+	while(cursor)
+	{
+		cursor--;
+		if(str_utf8_isstart(*(str + cursor)))
+			break;
+	}
+	return cursor;
+}
+
+int str_utf8_forward(const char *str, int cursor)
+{
+	const char *buf = str + cursor;
+	if(!buf[0])
+		return cursor;
+	
+	if((*buf&0x80) == 0x0)  /* 0xxxxxxx */
+		return cursor+1;
+	else if((*buf&0xE0) == 0xC0) /* 110xxxxx */
+	{
+		if(!buf[1]) return cursor+1;
+		return cursor+2;
+	}
+	else  if((*buf & 0xF0) == 0xE0)	/* 1110xxxx */
+	{
+		if(!buf[1]) return cursor+1;
+		if(!buf[2]) return cursor+2;
+		return cursor+2;
+	}
+	else if((*buf & 0xF8) == 0xF0)	/* 11110xxx */
+	{
+		if(!buf[1]) return cursor+1;
+		if(!buf[2]) return cursor+2;
+		if(!buf[3]) return cursor+3;
+		return cursor+3;
+	}
+	
+	/* invalid */
+	return cursor+1;
+}
+
+int str_utf8_encode(char *ptr, int chr)
+{
+	/* encode */
+	if(chr <= 0x7F)
+	{
+		ptr[0] = (char)chr;
+		return 1;
+	}
+	else if(chr <= 0x7FF)
+	{
+		ptr[0] = 0xC0|((chr>>6)&0x1F);
+		ptr[1] = 0x80|(chr&0x3F);
+		return 2;
+	}
+	else if(chr <= 0xFFFF)
+	{
+		ptr[0] = 0xE0|((chr>>12)&0x0F);
+		ptr[1] = 0xC0|((chr>>6)&0x3F);
+		ptr[2] = 0xC0|(chr&0x3F);
+		return 3;
+	}
+	else if(chr <= 0x10FFFF)
+	{
+		ptr[0] = 0xF0|((chr>>18)&0x07);
+		ptr[1] = 0xC0|((chr>>12)&0x3F);
+		ptr[2] = 0xC0|((chr>>6)&0x3F);
+		ptr[3] = 0xC0|(chr&0x3F);
+		return 4;
+	}
+	
+	return 0;
+}
+
+int str_utf8_decode(const char **ptr)
+{
+	const char *buf = *ptr;
+	int ch = 0;
+	
+	do
+	{
+		if((*buf&0x80) == 0x0)  /* 0xxxxxxx */
+		{
+			ch = *buf;
+			buf++;
+		}
+		else if((*buf&0xE0) == 0xC0) /* 110xxxxx */
+		{
+			ch  = (*buf++ & 0x3F) << 6; if(!(*buf)) break;
+			ch += (*buf++ & 0x3F);
+			if(ch == 0) ch = -1;
+		}
+		else  if((*buf & 0xF0) == 0xE0)	/* 1110xxxx */
+		{
+			ch  = (*buf++ & 0x1F) << 12; if(!(*buf)) break;
+			ch += (*buf++ & 0x3F) <<  6; if(!(*buf)) break;
+			ch += (*buf++ & 0x3F);
+			if(ch == 0) ch = -1;
+		}
+		else if((*buf & 0xF8) == 0xF0)	/* 11110xxx */
+		{
+			ch  = (*buf++ & 0x0F) << 18; if(!(*buf)) break;
+			ch += (*buf++ & 0x3F) << 12; if(!(*buf)) break;
+			ch += (*buf++ & 0x3F) <<  6; if(!(*buf)) break;
+			ch += (*buf++ & 0x3F);
+			if(ch == 0) ch = -1;
+		}
+		else
+		{
+			/* invalid */
+			buf++;
+			break;
+		}
+		
+		*ptr = buf;
+		return ch;
+	} while(0);
+
+	/* out of bounds */
+	*ptr = buf;
+	return -1;
+	
+}
+
 #if defined(__cplusplus)
 }
 #endif
diff --git a/src/base/system.h b/src/base/system.h
index 3aa01cab..87cae4a0 100644
--- a/src/base/system.h
+++ b/src/base/system.h
@@ -947,6 +947,69 @@ int str_isspace(char c);
 */
 void gui_messagebox(const char *title, const char *message);
 
+
+/*
+	Function: str_utf8_rewind
+		Moves a cursor backwards in an utf8 string
+	
+	Parameters:
+		str - utf8 string
+		cursor - position in the string
+
+	Returns:
+		New cursor position.
+
+	Remarks:
+		- Won't move the cursor less then 0
+*/
+int str_utf8_rewind(const char *str, int cursor);
+
+/*
+	Function: str_utf8_forward
+		Moves a cursor forwards in an utf8 string
+	
+	Parameters:
+		str - utf8 string
+		cursor - position in the string
+		
+	Returns:
+		New cursor position.
+
+	Remarks:
+		- Won't move the cursor beyond the zero termination marker
+*/
+int str_utf8_forward(const char *str, int cursor);
+
+/*
+	Function: str_utf8_decode
+		Decodes an utf8 character
+	
+	Parameters:
+		ptr - pointer to an utf8 string. this pointer will be moved forward
+		
+	Returns:
+		Unicode value for the character. -1 for invalid characters and 0 for end of string.
+
+	Remarks:
+		- This function will also move the pointer forward.
+*/
+int str_utf8_decode(const char **ptr);
+
+/*
+	Function: str_utf8_encode
+		Encode an utf8 character
+	
+	Parameters:
+		ptr - Pointer to a buffer that should recive the data. Should be able to hold at least 4 bytes.
+		
+	Returns:
+		Number of bytes put into the buffer.
+
+	Remarks:
+		- Does not do zero termination of the string.
+*/
+int str_utf8_encode(char *ptr, int chr);
+
 #ifdef __cplusplus
 }
 #endif