diff options
| author | Matthias Melcher <fltk@matthiasm.com> | 2008-09-10 23:56:49 +0000 |
|---|---|---|
| committer | Matthias Melcher <fltk@matthiasm.com> | 2008-09-10 23:56:49 +0000 |
| commit | b6bde2e4569aa617c8a6af64947c688c624ed7f8 (patch) | |
| tree | 010d15843eb7d4faf7cd1b0cd44d5b9c00462a83 /test/utf8.cxx | |
| parent | dfb50e85292687561927610e689eb5ab30d0ba26 (diff) | |
Merging the UTF8 patch, consisting of O'ksi'd s original 1.1.6 patch and additions by Ian. PLEASE BE AWARE that the patch in its current incarnation is a regression in many aspects and further work is required before we can announce Unicode support.
git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3@6212 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
Diffstat (limited to 'test/utf8.cxx')
| -rw-r--r-- | test/utf8.cxx | 624 |
1 files changed, 624 insertions, 0 deletions
diff --git a/test/utf8.cxx b/test/utf8.cxx new file mode 100644 index 000000000..6047aba58 --- /dev/null +++ b/test/utf8.cxx @@ -0,0 +1,624 @@ +// +// +// UTF-8 test program for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2003 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems to "fltk-bugs@fltk.org". +// + +#include <FL/Fl.H> +#include <FL/Fl_Window.H> +#include <FL/Fl_Double_Window.H> +#include <FL/Fl_Scroll.H> +#include <FL/Fl_Choice.H> +#include <FL/Fl_Input.H> +#include <FL/Fl_Box.H> +#include <FL/Fl_Hold_Browser.H> +#include <FL/Fl_Value_Output.H> +#include <FL/Fl_Button.H> +#include <FL/Fl_Check_Button.H> +#include <FL/Fl_Output.H> +#include <FL/fl_draw.H> +#include <FL/fl_utf8.H> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <math.h> + +// +// Font chooser widget for the Fast Light Tool Kit(FLTK). +// + +/********************************************************************************************/ +#define DEF_SIZE 16 // default value for the font size picker + +/********************************************************************************************/ +static Fl_Double_Window *fnt_chooser_win; +static Fl_Hold_Browser *fontobj; +static Fl_Hold_Browser *sizeobj; + +static Fl_Value_Output *fnt_cnt; +static Fl_Button *refresh_btn; +static Fl_Button *choose_btn; +static Fl_Output *fix_prop; +static Fl_Check_Button *own_face; + +static int **sizes = NULL; +static int *numsizes = NULL; +static int pickedsize = DEF_SIZE; +static char label[1000]; + +static Fl_Double_Window *main_win; +static Fl_Scroll *thescroll; +static Fl_Font extra_font; + +static int font_count = 0; +static int first_free = 0; + +/********************************************************************************************/ +class FontDisplay : public Fl_Widget +{ + void draw(void); + +public: + int font, size; + + int test_fixed_pitch(void); + + FontDisplay(Fl_Boxtype B, int X, int Y, int W, int H, const char *L = 0) : Fl_Widget(X, Y, W, H, L) + { + box(B); + font = 0; + size = DEF_SIZE; + } +}; + +/********************************************************************************************/ +void FontDisplay::draw(void) +{ + draw_box(); + fl_font((Fl_Font)font, size); + fl_color(FL_BLACK); + fl_draw(label(), x() + 3, y() + 3, w() - 6, h() - 6, align()); +} +/********************************************************************************************/ +int FontDisplay::test_fixed_pitch(void) +{ + int w1, w2; + int h1, h2; + + w1 = w2 = 0; + h1 = h2 = 0; + + fl_font((Fl_Font)font, size); + + fl_measure("MHMHWWMHMHMHM###WWX__--HUW", w1, h1, 0); + fl_measure("iiiiiiiiiiiiiiiiiiiiiiiiii", w2, h2, 0); + + if (w1 == w2) return 1; // exact match - fixed pitch + + // Is the font "nearly" fixed pitch? If it is within 5%, say it is... + double f1 = (double)w1; + double f2 = (double)w2; + double delta = fabs(f1 - f2) * 5.0; + if (delta <= f1) return 2; // nearly fixed pitch... + + return 0; // NOT fixed pitch +} + +/********************************************************************************************/ +static FontDisplay *textobj; + +/********************************************************************************************/ +static void size_cb(Fl_Widget *, long) +{ + int size_idx = sizeobj->value(); + + if (!size_idx) return; + + const char *c = sizeobj->text(size_idx); + + while (*c < '0' || *c > '9') c++; // find the first numeric char + pickedsize = atoi(c); // convert the number string to a value + + // Now set the font view to the selected size and redraw it. + textobj->size = pickedsize; + textobj->redraw(); +} +/********************************************************************************************/ +static void font_cb(Fl_Widget *, long) +{ + int font_idx = fontobj->value() + first_free; + + if (!font_idx) return; + font_idx--; + + textobj->font = font_idx; + sizeobj->clear(); + + int size_count = numsizes[font_idx-first_free]; + int *size_array = sizes[font_idx-first_free]; + if (!size_count) + { + // no preferred sizes - probably TT fonts etc... + } + else if (size_array[0] == 0) + { + // many sizes, probably a scaleable font with preferred sizes + int j = 1; + for (int i = 1; i <= 64 || i < size_array[size_count - 1]; i++) + { + char buf[16]; + if (j < size_count && i == size_array[j]) + { + sprintf(buf, "@b%d", i); + j++; + } + else + sprintf(buf, "%d", i); + sizeobj->add(buf); + } + sizeobj->value(pickedsize); + } + else + { + // some sizes, probably a font with a few fixed sizes available + int w = 0; + for (int i = 0; i < size_count; i++) + { + // find the nearest available size to the current picked size + if (size_array[i] <= pickedsize) w = i; + + char buf[16]; + sprintf(buf, "@b%d", size_array[i]); + sizeobj->add(buf); + } + sizeobj->value(w + 1); + } + size_cb(sizeobj, 0); // force selection of nearest valid size, then redraw + + // Now check to see if the font looks like a fixed pitch font or not... + int looks_fixed = textobj->test_fixed_pitch(); + if(looks_fixed) + { + if (looks_fixed > 1) + fix_prop->value("near"); + else + fix_prop->value("fixed"); + } + else + { + fix_prop->value("prop"); + } +} + +/********************************************************************************************/ +static void choose_cb(Fl_Widget *, long) +{ + int font_idx = fontobj->value() + first_free; + if (!font_idx) + { + puts("No font chosen"); + } + else + { + int font_type; + font_idx -= 1; + const char *name = Fl::get_font_name((Fl_Font)font_idx, &font_type); + printf("idx %d\nUser name :%s:\n", font_idx, name); + printf("FLTK name :%s:\n", Fl::get_font((Fl_Font)font_idx)); + + Fl::set_font(extra_font, (Fl_Font)font_idx); +// Fl::set_font(extra_font, Fl::get_font((Fl_Font)font_idx)); + } + + int size_idx = sizeobj->value(); + if (!size_idx) + { + puts("No size selected"); + } + else + { + const char *c = sizeobj->text(size_idx); + while (*c < '0' || *c > '9') c++; // find the first numeric char + int pickedsize = atoi(c); // convert the number string to a value + + printf("size %d\n\n", pickedsize); + } + + fflush(stdout); + main_win->redraw(); +} +/********************************************************************************************/ +static void refresh_cb(Fl_Widget *, long) +{ + main_win->redraw(); +} + +/********************************************************************************************/ +static void own_face_cb(Fl_Widget *, void *) +{ + int font_idx; + int cursor_restore = 0; + static int i_was = -1; // used to keep track of where we were in the list... + + if (i_was < 0) { // not been here before + i_was = 1; + } else { + i_was = fontobj->topline(); // record which was the topmost visible line + fontobj->clear(); + // Populating the font widget can be slower than an old dog with three legs + // on a bad day, show a wait cursor + fnt_chooser_win->cursor(FL_CURSOR_WAIT); + cursor_restore = 1; + } + + + // Populate the font list with the names of the fonts found + for (font_idx = first_free; font_idx < font_count; font_idx++) + { + int font_type; + const char *name = Fl::get_font_name((Fl_Font)font_idx, &font_type); + char buffer[128]; + + if(own_face->value() == 0) { + char *p = buffer; + if (font_type & FL_BOLD) { // if the font is BOLD, set the bold attribute in the list + *p++ = '@'; + *p++ = 'b'; + } + if (font_type & FL_ITALIC) { // ditto for italic fonts + *p++ = '@'; + *p++ = 'i'; + } + // Suppress subsequent formatting - some MS fonts have '@' in their name + *p++ = '@'; + *p++ = '.'; + strcpy(p, name); + } else { // Show font in its own face + /* this is neat, but really slow on some systems: uses each font to display its own name */ + sprintf (buffer, "@F%d@.%s", font_idx, name); + } + fontobj->add(buffer); + } + // now put the browser position back the way it was... more or less + fontobj->topline(i_was); + // restore the cursor + if(cursor_restore) fnt_chooser_win->cursor(FL_CURSOR_DEFAULT); +} + +/********************************************************************************************/ +static void create_font_widget() +{ + fnt_chooser_win = new Fl_Double_Window(380, 420, "Font Selector"); + + strcpy(label, "Font Sample\n"); + int i = 12; // strlen(label); + int n = 0; + ulong c; + for (c = ' '+1; c < 127; c++) { + if (!(c&0x1f)) label[i++]='\n'; + if (c=='@') label[i++]=c; + label[i++]=c; + } + label[i++] = '\n'; + for (c = 0xA1; c < 0x600; c += 9) {if (!(++n&(0x1f))) label[i++]='\n'; + i += fl_utf8encode((unsigned int)c, label + i);} + label[i] = 0; + + textobj = new FontDisplay(FL_FRAME_BOX, 10, 10, 360, 90, label); + textobj->align(FL_ALIGN_TOP | FL_ALIGN_LEFT | FL_ALIGN_INSIDE | FL_ALIGN_CLIP); + textobj->color(53, 3); + + fontobj = new Fl_Hold_Browser(10, 110, 290, 270); + fontobj->box(FL_FRAME_BOX); + fontobj->color(53, 3); + fontobj->callback(font_cb); + fnt_chooser_win->resizable(fontobj); + + sizeobj = new Fl_Hold_Browser(310, 110, 60, 270); + sizeobj->box(FL_FRAME_BOX); + sizeobj->color(53, 3); + sizeobj->callback(size_cb); + +// Create the status bar + Fl_Group * stat_bar = new Fl_Group (10, 385, 380, 30); + stat_bar->begin(); + + fnt_cnt = new Fl_Value_Output(10, 390, 40, 20); + fnt_cnt->label("fonts"); + fnt_cnt->align(FL_ALIGN_RIGHT); + + fix_prop = new Fl_Output(100, 390, 40, 20); + fix_prop->color(FL_BACKGROUND_COLOR); + fix_prop->value("prop"); + fix_prop->clear_visible_focus(); + + own_face = new Fl_Check_Button(150, 390, 40, 20, "Self"); + own_face->value(0); + own_face->type(FL_TOGGLE_BUTTON); + own_face->clear_visible_focus(); + own_face->callback(own_face_cb); + own_face->tooltip("Display font names in their own face"); + + Fl_Box * dummy = new Fl_Box(220, 390, 1, 1); + + choose_btn = new Fl_Button(240, 385, 60, 30); + choose_btn->label("Select"); + choose_btn->callback(choose_cb); + + refresh_btn = new Fl_Button(310, 385, 60, 30); + refresh_btn->label("Refresh"); + refresh_btn->callback(refresh_cb); + + stat_bar->end(); + stat_bar->resizable (dummy); + + fnt_chooser_win->end(); +} + +/********************************************************************************************/ +int make_font_chooser(void) +{ + int font_idx; + + // create the widget frame + create_font_widget(); + + // Load the systems available fonts - ask for everything +// font_count = Fl::set_fonts("*"); +#ifdef _WIN32 + font_count = Fl::set_fonts("*"); +#elif __APPLE__ + font_count = Fl::set_fonts("*"); +#else + // Load the systems available fonts - ask for everything that claims to be iso10646 compatible + font_count = Fl::set_fonts("-*-*-*-*-*-*-*-*-*-*-*-*-iso10646-1"); +#endif + + // allocate space for the sizes and numsizes array, now we know how many entries it needs + sizes = new int*[font_count]; + numsizes = new int[font_count]; + + // Populate the font list with the names of the fonts found + first_free = FL_FREE_FONT; + for (font_idx = first_free; font_idx < font_count; font_idx++) + { + // Find out how many sizes are supported for each font face + int *size_array; + int size_count = Fl::get_font_sizes((Fl_Font)font_idx, size_array); + numsizes[font_idx-first_free] = size_count; + if (size_count) // if the font has multiple sizes, populate the 2-D sizes array + { + sizes[font_idx-first_free] = new int[size_count]; + for (int j = 0; j < size_count; j++) + sizes[font_idx-first_free][j] = size_array[j]; + } + } // end of font list filling loop + + // Call this once to get the font browser loaded up + own_face_cb(NULL, 0); + + fontobj->value(1); +// fontobj->textfont(261); // optional hard-coded font for testing - do not use! + + font_cb(fontobj, 0); + + fnt_cnt->value(font_count); + + return font_count; + +} // make_font_chooser + +/* End of Font Chooser Widget code */ +/********************************************************************************************/ +/* Unicode Font display widget */ + +void box_cb(Fl_Widget* o, void*) { + thescroll->box(((Fl_Button*)o)->value() ? FL_DOWN_FRAME : FL_NO_BOX); + thescroll->redraw(); +} + +class right_left_input : public Fl_Input +{ +public: + right_left_input (int x, int y, int w, int h) : Fl_Input(x, y, w, h) {}; + void draw() { + if (type() == FL_HIDDEN_INPUT) return; + Fl_Boxtype b = box(); + if (damage() & FL_DAMAGE_ALL) draw_box(b, color()); + drawtext(x()+Fl::box_dx(b)+3, y()+Fl::box_dy(b), + w()-Fl::box_dw(b)-6, h()-Fl::box_dh(b)); + } + void drawtext(int X, int Y, int W, int H) { + fl_color(textcolor()); + fl_font(textfont(), textsize()); + fl_rtl_draw(value(), strlen(value()), + X + W, Y + fl_height() -fl_descent()); + } +}; + + +void i7_cb(Fl_Widget *w, void *d) +{ + int i = 0; + char nb[] = "01234567"; + Fl_Input *i7 = (Fl_Input*)w; + Fl_Input *i8 = (Fl_Input*)d; + static char buf[1024]; + const char *ptr = i7->value(); + while (ptr && *ptr) { + if (*ptr < ' ' || *ptr > 126) { + buf[i++] = '\\'; + buf[i++] = nb[((*ptr >> 6) & 0x3)]; + buf[i++] = nb[((*ptr >> 3) & 0x7)]; + buf[i++] = nb[(*ptr & 0x7)]; + } else { + if (*ptr == '\\') buf[i++] = '\\'; + buf[i++] = *ptr; + } + ptr++; + } + buf[i] = 0; + i8->value(buf); +} + +/********************************************************************************************/ +int main(int argc, char** argv) +{ + int l; +/* If this file is saved as a UTF-8, the latin1 text in the comment + * below doesn't look right any more! + * Store the specific latin-1 byte values here... this should be equivalent to: + * char *latin1 = "ABCabcàèéïâîöüã123"; */ + char *latin1 = "\x41\x42\x43\x61\x62\x63\xe0\xe8\xe9\xef\xe2\xee\xf6\xfc\xe3\x31\x32\x33"; + char *utf8 = (char*) malloc(strlen(latin1) * 5 + 1); + l = 0; +// l = fl_latin12utf((const unsigned char*)latin1, strlen(latin1), utf8); + l = fl_utf8froma(utf8, (strlen(latin1) * 5 + 1), latin1, strlen(latin1)); + + make_font_chooser(); + extra_font = FL_TIMES_BOLD_ITALIC; + + /* setup the extra font */ + Fl::set_font(extra_font, +#ifdef _WIN32 + " Arial Unicode MS" +#elif __APPLE__ + "Monaco" +#else + "-*-*-*-*-*-*-*-*-*-*-*-*-iso10646-1" +#endif + ); + + main_win = new Fl_Double_Window (200 + 5*75, 400, "Unicode Display Test"); + main_win->begin(); + + Fl_Input i1(5, 5, 190, 25); + utf8[l] = '\0'; + i1.value(utf8); + Fl_Scroll scroll(200,0,5 * 75,400); + + int off = 2; + if (argc > 1) { + off = (int)strtoul(argv[1], NULL, 0); + off /= 16; + } + argc = 1; + for (long y=off; y< 0x10000 / 16; y++) { + int o = 0; + char bu[25]; + char buf[16*6]; + int i = 16 * y; + for (int x=0; x<16; x++) { + int l; + l = fl_utf8encode(i, buf + o); + if (l < 1) l = 1; + o += l; + i++; + } + buf[o] = '\0'; + sprintf(bu, "0x%04lX", y * 16); + Fl_Input* b = new Fl_Input(200,(y-off)*25,60,25); + b->value(strdup(bu)); + b = new Fl_Input(260,(y-off)*25,400,25); + b->textfont(extra_font); + b->value(strdup(buf)); + } + main_win->resizable(scroll); + scroll.end(); + + thescroll = &scroll; + + char *utf8l = (char*) malloc(strlen(utf8) * 3 + 1); + Fl_Input i2(5, 35, 190, 25); + l = fl_utf_tolower((const unsigned char*)utf8, l, utf8l); + utf8l[l] = '\0'; + i2.value(utf8l); + + char *utf8u = (char*) malloc(strlen(utf8l) * 3 + 1); + Fl_Input i3(5, 65, 190, 25); + l = fl_utf_toupper((const unsigned char*)utf8l, l, utf8u); + utf8u[l] = '\0'; + i3.value(utf8u); + + char *ltr_txt = "\\->e\xCC\x82=\xC3\xAA"; + Fl_Input i4(5, 90, 190, 25); + i4.value(ltr_txt); + i4.textfont(extra_font); + + wchar_t r_to_l_txt[] ={/*8238,*/ 1610, 1608, 1606, 1604, 1603, 1608, 1583, 0}; + + char abuf[40]; +// l = fl_unicode2utf(r_to_l_txt, 8, abuf); + l = fl_utf8fromwc(abuf, 40, r_to_l_txt, 8); + abuf[l] = 0; + + right_left_input i5(5, 115, 190, 50); + i5.textfont(extra_font); + i5.textsize(30); + i5.value(abuf); + + Fl_Input i7(5, 230, 190, 25); + Fl_Input i8(5, 260, 190, 25); + i7.callback(i7_cb, &i8); + i7.textsize(20); + i7.value(abuf); + i7.when(FL_WHEN_CHANGED); + + wchar_t r_to_l_txt1[] ={/*8238,*/ 1610, 0x20, 1608, 0x20, 1606, 0x20, 1604, 0x20, 1603, 0x20, 1608, 0x20, 1583, 0}; + +// l = fl_unicode2utf(r_to_l_txt1, 14, abuf); + l = fl_utf8fromwc(abuf, 40, r_to_l_txt1, 14); + abuf[l] = 0; + right_left_input i6(5, 175, 190, 50); + i6.textfont(extra_font); + i6.textsize(30); + i6.value(abuf); + + // Now try Greg Ercolano's Japanese test sequence + // SOME JAPANESE UTF8 TEXT + char *utfstr = "\xe4\xbd\x95\xe3\x82\x82\xe8\xa1" + "\x8c\xe3\x82\x8b\xe3\x80\x82"; // 何も行る。 + + Fl_Output o9(5, 330, 190, 45); + o9.textfont(extra_font); + o9.textsize(30); + o9.value(utfstr); + + + main_win->end(); + fl_set_status(0, 370, 100, 30); + + main_win->show(argc,argv); + + fnt_chooser_win->show(); + + int ret = Fl::run(); + + // Free up the sizes arrays we allocated + if(numsizes) {delete [] numsizes;} + if(sizes) {delete [] sizes;} + + return ret; +} + +/* end of file */ + |
