diff --git a/share/grafx2/skins/unicode_0410-044F.png b/share/grafx2/skins/unicode_0410-044F.png
new file mode 100644
index 00000000..c5b70d5c
Binary files /dev/null and b/share/grafx2/skins/unicode_0410-044F.png differ
diff --git a/src/buttons.c b/src/buttons.c
index 3fc89f10..69e169c9 100644
--- a/src/buttons.c
+++ b/src/buttons.c
@@ -1459,7 +1459,7 @@ void Button_Skins(void)
T_Fileselector_item* fontName;
selected_font = Window_attribute2; // Get the index of the chosen font.
fontName = Get_item_by_index(&Font_files_list,selected_font);
- new_font = Load_font(fontName->Full_name);
+ new_font = Load_font(fontName->Full_name, 1);
if (new_font)
{
free(Menu_font);
@@ -1498,7 +1498,7 @@ void Button_Skins(void)
Set_current_skin(skinsdir, gfx);
}
// (Re-)load the selected font
- new_font = Load_font(Get_item_by_index(&Font_files_list,selected_font)->Full_name);
+ new_font = Load_font(Get_item_by_index(&Font_files_list,selected_font)->Full_name, 1);
if (new_font)
{
const char * fname;
diff --git a/src/global.h b/src/global.h
index 6b669065..8ddbd191 100644
--- a/src/global.h
+++ b/src/global.h
@@ -646,6 +646,9 @@ GFX2_GLOBAL byte Resolution_in_command_line;
/// Pointer to the font selected for menus.
GFX2_GLOBAL byte * Menu_font;
+/// additional fonts for unicode characters
+GFX2_GLOBAL T_Unicode_Font * Unicode_fonts;
+
/// Pointer to the current active skin.
GFX2_GLOBAL T_Gui_skin * Gfx;
diff --git a/src/init.c b/src/init.c
index 4b34a50c..a300227b 100644
--- a/src/init.c
+++ b/src/init.c
@@ -701,27 +701,36 @@ T_Gui_skin * Load_graphics(const char * skin_file, T_Gradient_array *gradients)
// ---- font loading -----
-byte Parse_font(SDL_Surface * image, byte * font)
+static byte * Parse_font(SDL_Surface * image, int is_main)
{
+ byte * font;
int character;
byte color;
int x, y;
int chars_per_line;
+ int character_count;
// Check image size
if (image->w % 8)
{
sprintf(Gui_loading_error_message, "Error in font file: Image width is not a multiple of 8.\n");
- return 1;
+ return NULL;
}
- if (image->w * image->h < 8*8*256)
+ character_count = (image->w * image->h) / (8*8);
+ if (is_main && character_count < 256)
{
sprintf(Gui_loading_error_message, "Error in font file: Image is too small to be a 256-character 8x8 font.\n");
- return 1;
+ return NULL;
+ }
+ font = (byte *)malloc(8*8*character_count);
+ if (font == NULL)
+ {
+ sprintf(Gui_loading_error_message, "Not enough memory to read font file\n");
+ return NULL;
}
chars_per_line = image->w/8;
- for (character=0; character < 256; character++)
+ for (character=0; character < character_count; character++)
{
for (y=0; y<8; y++)
{
@@ -732,19 +741,20 @@ byte Parse_font(SDL_Surface * image, byte * font)
if (color > 1)
{
sprintf(Gui_loading_error_message, "Error in font file: Only colors 0 and 1 can be used for the font.\n");
- return 1;
+ free(font);
+ return NULL;
}
// Put it in font. 0 = BG, 1 = FG.
font[character*64 + y*8 + x]=color;
}
}
}
- return 0;
+ return font;
}
-byte * Load_font(const char * font_name)
+byte * Load_font(const char * font_name, int is_main)
{
- byte * font;
+ byte * font = NULL;
char filename[MAX_PATH_CHARACTERS];
SDL_Surface * image;
@@ -754,13 +764,6 @@ byte * Load_font(const char * font_name)
return NULL;
}
- font = (byte *)malloc(8*8*256);
- if (font == NULL)
- {
- sprintf(Gui_loading_error_message, "Not enough memory to read font file\n");
- return NULL;
- }
-
// Read the file containing the image
sprintf(filename,"%s" SKINS_SUBDIRECTORY "%s%s", Data_directory, PATH_SEPARATOR, font_name);
@@ -768,19 +771,41 @@ byte * Load_font(const char * font_name)
if (!image)
{
sprintf(Gui_loading_error_message, "Unable to load the skin image (missing? not an image file?)\n");
- free(font);
- return NULL;
- }
- if (Parse_font(image, font))
- {
- SDL_FreeSurface(image);
- free(font);
return NULL;
}
+ font = Parse_font(image, is_main);
SDL_FreeSurface(image);
return font;
}
+static void Load_Unicode_font(const char * filename)
+{
+ T_Unicode_Font * ufont;
+ byte * font;
+ unsigned int first, last;
+
+ if (sscanf(filename, "unicode_%04X-%04X.png", &first, &last) == 2)
+ {
+ font = Load_font(filename, 0);
+ if (font)
+ {
+ ufont = malloc(sizeof(T_Unicode_Font));
+ ufont->FirstChar = first;
+ ufont->LastChar = last;
+ ufont->FontData = font;
+ ufont->Next = Unicode_fonts;
+ Unicode_fonts = ufont;
+ }
+ }
+ else
+ Warning("Could not parse filename");
+}
+
+void Load_Unicode_fonts(void)
+{
+ // TODO : for each unicode*.png file in skin directory
+ Load_Unicode_font("unicode_0410-044F.png");
+}
// Initialisation des boutons:
diff --git a/src/init.h b/src/init.h
index 14714cac..eafcc214 100644
--- a/src/init.h
+++ b/src/init.h
@@ -47,4 +47,7 @@ extern char Gui_loading_error_message[512];
/// successful.
/// If an error is encountered, it frees what needs it, prints an error message
/// in ::Gui_loading_error_message, and returns NULL.
-byte * Load_font(const char * font_name);
+byte * Load_font(const char * font_name, int is_main);
+
+/// Load fonts for additional Unicode characters
+void Load_Unicode_fonts(void);
diff --git a/src/main.c b/src/main.c
index 3d96e27d..4efa10ad 100644
--- a/src/main.c
+++ b/src/main.c
@@ -745,12 +745,13 @@ int Init_program(int argc,char * argv[])
Copy_preset_sieve(0);
// Font
- if (!(Menu_font=Load_font(Config.Font_file)))
- if (!(Menu_font=Load_font(DEFAULT_FONT_FILENAME)))
+ if (!(Menu_font=Load_font(Config.Font_file, 1)))
+ if (!(Menu_font=Load_font(DEFAULT_FONT_FILENAME, 1)))
{
printf("Unable to open the default font file: %s\n", DEFAULT_FONT_FILENAME);
Error(ERROR_GUI_MISSING);
}
+ Load_Unicode_fonts();
memcpy(Main.palette, Gfx->Default_palette, sizeof(T_Palette));
@@ -993,6 +994,16 @@ void Program_shutdown(void)
free(Gfx);
Gfx=NULL;
+ free(Menu_font);
+ Menu_font = NULL;
+ while (Unicode_fonts != NULL)
+ {
+ T_Unicode_Font * ufont = Unicode_fonts->Next;
+ free(Unicode_fonts->FontData);
+ free(Unicode_fonts);
+ Unicode_fonts = ufont;
+ }
+
// On prend bien soin de passer dans le répertoire initial:
if (chdir(Initial_directory)!=-1)
{
diff --git a/src/struct.h b/src/struct.h
index e85d4f81..1e6177ba 100644
--- a/src/struct.h
+++ b/src/struct.h
@@ -549,7 +549,7 @@ typedef struct T_Selector_settings
char Directory[MAX_PATH_CHARACTERS]; ///< Directory currently browsed
} T_Selector_settings;
-// structure for Main or Spare page global data
+/// structure for Main or Spare page global data
typedef struct
{
/// Palette
@@ -618,4 +618,12 @@ typedef struct
T_List_of_pages * backups;
} T_Document;
+typedef struct T_Unicode_Font
+{
+ struct T_Unicode_Font * Next;
+ dword FirstChar;
+ dword LastChar;
+ byte * FontData;
+} T_Unicode_Font;
+
#endif
diff --git a/src/unicode.c b/src/unicode.c
new file mode 100644
index 00000000..3517d7b6
--- /dev/null
+++ b/src/unicode.c
@@ -0,0 +1,81 @@
+/* vim:expandtab:ts=2 sw=2:
+*/
+/* Grafx2 - The Ultimate 256-color bitmap paint program
+
+ Copyright 2018 Thomas Bernard
+ Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
+
+ Grafx2 is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; version 2
+ of the License.
+
+ Grafx2 is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Grafx2; if not, see
+*/
+
+#include
+#include
+
+#include "unicode.h"
+
+size_t Unicode_strlen(const word * str)
+{
+ size_t len;
+
+ len = 0;
+ while(str[len] != 0)
+ len++;
+ return len;
+}
+
+/// equivalent of strdup() for our Unicode strings
+word * Unicode_strdup(const word * str)
+{
+ size_t byte_size;
+ word * new_str;
+
+ byte_size = Unicode_strlen(str) * 2 + 2;
+ new_str = malloc(byte_size);
+ if (new_str != NULL)
+ memcpy(new_str, str, byte_size);
+ return new_str;
+}
+
+/// Compare an unicode string with a regular Latin1 string
+int Unicode_char_strcmp(const word * s1, const char * s2)
+{
+ const byte * str2 = (const byte *)s2;
+
+ while (*s1 == *str2)
+ {
+ if (*s1 == 0) return 0;
+ s1++;
+ str2++;
+ }
+ return (*s1 > *str2) ? 1 : -1;
+}
+
+/// Copy a regular Latin1 string to an unicode string
+void Unicode_char_strlcpy(word * dst, const char * src, size_t len)
+{
+ const byte * s = (const byte *)src;
+
+ if (len == 0)
+ return;
+ while (len > 1)
+ {
+ *dst = *s;
+ if (*s == '\0')
+ return;
+ dst++;
+ s++;
+ len--;
+ }
+ *dst = 0;
+}
diff --git a/src/unicode.h b/src/unicode.h
new file mode 100644
index 00000000..c3948904
--- /dev/null
+++ b/src/unicode.h
@@ -0,0 +1,39 @@
+/* vim:expandtab:ts=2 sw=2:
+*/
+/* Grafx2 - The Ultimate 256-color bitmap paint program
+
+ Copyright 2018 Thomas Bernard
+ Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
+
+ Grafx2 is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; version 2
+ of the License.
+
+ Grafx2 is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Grafx2; if not, see
+*/
+#ifndef UNICODE_H_INCLUDED
+#define UNICODE_H_INCLUDED
+
+#include "struct.h"
+
+/// equivalent of strlen() for out Unicode strings
+/// return the number of characters (words), so there is twice as much bytes
+size_t Unicode_strlen(const word * str);
+
+/// equivalent of strdup() for our Unicode strings
+word * Unicode_strdup(const word * str);
+
+/// Compare an unicode string with a regular Latin1 string
+int Unicode_char_strcmp(const word * s1, const char * s2);
+
+/// Copy a regular Latin1 string to an unicode string
+void Unicode_char_strlcpy(word * dst, const char * src, size_t len);
+
+#endif
diff --git a/src/windows.c b/src/windows.c
index 60d08bb2..60540bbb 100644
--- a/src/windows.c
+++ b/src/windows.c
@@ -708,13 +708,25 @@ void Print_general(short x,short y,const char * str,byte text_color,byte backgro
}
/// Draws a char in a window
-void Print_char_in_window(short x_pos,short y_pos,const unsigned char c,byte text_color,byte background_color)
+void Print_char_in_window(short x_pos, short y_pos, unsigned int c,byte text_color,byte background_color)
{
short x,y;
- byte *pixel;
+ const byte *pixel;
// Premier pixel du caractère
- pixel=Menu_font + (c<<6);
-
+ if (c < 256)
+ pixel=Menu_font + (c<<6);
+ else
+ {
+ T_Unicode_Font * ufont;
+ pixel=Menu_font + (1<<6); // dummy character
+ for (ufont = Unicode_fonts; ufont != NULL; ufont = ufont->Next)
+ if (ufont->FirstChar <= c && c <= ufont->LastChar)
+ {
+ pixel = ufont->FontData + ((c - ufont->FirstChar) << 6);
+ break;
+ }
+ }
+
for (y=0;y<8;y++)
for (x=0;x<8;x++)
Pixel_in_window(x_pos+x, y_pos+y,
@@ -739,16 +751,31 @@ void Print_in_window_limited(short x,short y,const char * str,byte size,byte tex
void Print_in_window(short x,short y,const char * str,byte text_color,byte background_color)
{
short x_pos = x;
- int index;
+ const unsigned char * p = (const unsigned char *)str;
- for (index=0;str[index]!='\0';index++)
+ while (*p !='\0')
{
- Print_char_in_window(x,y,str[index],text_color,background_color);
+ Print_char_in_window(x,y,*p++,text_color,background_color);
x+=8;
}
- Update_window_area(x_pos,y,8*strlen(str),8);
+ Update_window_area(x_pos,y,x-x_pos,8);
}
+/// Draws a string in a window
+void Print_in_window_utf16(short x,short y,const word * str,byte text_color,byte background_color)
+{
+ short x_pos = x;
+ const word * p = str;
+
+ while (*p != 0)
+ {
+ Print_char_in_window(x,y,*p++,text_color,background_color);
+ x+=8;
+ }
+ Update_window_area(x_pos,y,x-x_pos,8);
+}
+
+
// Draws a string in the menu's status bar
void Print_in_menu(const char * str, short position)
{
diff --git a/src/windows.h b/src/windows.h
index 0b2ea718..91569587 100644
--- a/src/windows.h
+++ b/src/windows.h
@@ -67,8 +67,9 @@ word Palette_cells_Y(void);
void Print_general(short x,short y,const char * str,byte text_color,byte background_color);
void Print_in_window(short x,short y,const char * str,byte text_color,byte background_color);
+void Print_in_window_utf16(short x,short y,const word * str,byte text_color,byte background_color);
void Print_in_window_limited(short x,short y,const char * str,byte size,byte text_color,byte background_color);
-void Print_char_in_window(short x_pos,short y_pos,const unsigned char c,byte text_color,byte background_color);
+void Print_char_in_window(short x_pos,short y_pos, unsigned int c,byte text_color,byte background_color);
void Print_in_menu(const char * str, short position);
void Print_coordinates(void);
void Print_filename(void);