diff options
| author | Bill Spitzak <spitzak@gmail.com> | 2000-02-21 10:30:00 +0000 |
|---|---|---|
| committer | Bill Spitzak <spitzak@gmail.com> | 2000-02-21 10:30:00 +0000 |
| commit | b5529a0aea519389ad9561074ca7e464b2178d6e (patch) | |
| tree | 73fc41307b2c63c0dc0561ff685f2bdd1db052a9 /src | |
| parent | 0bd9018d649616ec81430bc5c3a2ad2b4f46575a (diff) | |
Rearranged the compose code so it is clearer and can be called by things
other than the Fl_Input widget. It now understands "dead keys" on X.
Calling fl_set_fonts repeatedly returns the same set of fonts each time,
rather than adding copies of all the fonts to the set each time.
git-svn-id: file:///fltk/svn/fltk/branches/branch-1.0@1007 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
Diffstat (limited to 'src')
| -rw-r--r-- | src/Fl_Input.cxx | 175 | ||||
| -rw-r--r-- | src/Fl_compose.cxx | 136 | ||||
| -rw-r--r-- | src/Makefile | 5 | ||||
| -rw-r--r-- | src/fl_set_fonts.cxx | 6 | ||||
| -rwxr-xr-x | src/fl_set_fonts_win32.cxx | 7 |
5 files changed, 191 insertions, 138 deletions
diff --git a/src/Fl_Input.cxx b/src/Fl_Input.cxx index dd573150c..ab6947eb5 100644 --- a/src/Fl_Input.cxx +++ b/src/Fl_Input.cxx @@ -1,5 +1,5 @@ // -// "$Id: Fl_Input.cxx,v 1.10.2.5 2000/02/18 07:11:09 bill Exp $" +// "$Id: Fl_Input.cxx,v 1.10.2.6 2000/02/21 10:29:58 bill Exp $" // // Input widget for the Fast Light Tool Kit (FLTK). // @@ -32,9 +32,7 @@ #include <FL/Fl.H> #include <FL/Fl_Input.H> #include <FL/fl_draw.H> -#include <math.h> #include <string.h> -#include <ctype.h> void Fl_Input::draw() { if (type() == FL_HIDDEN_INPUT) return; @@ -52,76 +50,6 @@ int Fl_Input::shift_up_down_position(int p) { return up_down_position(p, Fl::event_state(FL_SHIFT)); } -//////////////////////////////////////////////////////////////// -// Fltk "compose" -// -// This is a demonstration of a IMHO "correct" interface to compose -// character sequences. It does not have a "dead key" effect: the -// user has feedback at all times, and sees exactly the symbol they -// will get if they stop typing at that point. Notice that I totally -// ignore the horrid XIM extension! -// -// You only need to keep track of your normal text buffer and a -// single integer "state". Call fl_compose() for each character -// keystroke. The return value is the new "state" that must be passed -// the next time you call fl_compose(). It also returns the number of -// characters to delete to the left, a buffer of new characters, and -// the number of characters in that buffer. Obey these editing -// instructions. Reset the state to zero if the user types any -// function keys or clicks the mouse. -// -// Fl_Input does not call fl_compose unless you hit the "compose" key -// first. It may be interesting and useful to always call it, though... - -// Although this simple code is only for ISO-8859-1 character -// encodings, I think the interface can be expanded to UTF-8 (encoded -// Unicode) someday. - -// This string lists a pair for each possible foreign letter in ISO-8859-1 -// starting at code 0xa0 (nbsp). If the second character is a space then -// only the first character needs to by typed: -static const char* const compose_pairs = -" ! % # $ y=| & : c a <<~ - r _ * +-2 3 ' u p . , 1 o >>141234? " -"A`A'A^A~A:A*AEC,E`E'E^E:I`I'I^I:D-N~O`O'O^O~O:x O/U`U'U^U:Y'THss" -"a`a'a^a~a:a*aec,e`e'e^e:i`i'i^i:d-n~o`o'o^o~o:-:o/u`u'u^u:y'thy:"; - -int fl_compose(int state, char c, int& del, char* buffer, int& ins) { - del = 0; ins = 1; buffer[0] = c; - - if (c == '"') c = ':'; - - if (!state) { // first character - if (c == ' ') {buffer[0]=char(0xA0);return 0x100;} // space turns into nbsp - // see if it is either character of any pair: - state = 0; - for (const char *p = compose_pairs; *p; p += 2) - if (p[0] == c || p[1] == c) { - if (p[1] == ' ') buffer[0] = (p-compose_pairs)/2+0xA0; - state = c; - } - return state; - - } else if (state == 0x100) { // third character - return 0; - - } else { // second character - char c1 = char(state); // first character - // now search for the pair in either order: - for (const char *p = compose_pairs; *p; p += 2) { - if (p[0] == c && p[1] == c1 || p[1] == c && p[0] == c1) { - buffer[0] = (p-compose_pairs)/2+0xA0; - ins = del = 1; - return 0x100; - } - } - return 0; - } -} - -//////////////////////////////////////////////////////////////// - -static int compose; // compose state (# of characters so far + 1) - // If you define this symbol as zero you will get the peculiar fltk // behavior where moving off the end of an input field will move the // cursor into the next field: @@ -131,45 +59,52 @@ static int compose; // compose state (# of characters so far + 1) #define ctrl(x) (x^0x40) int Fl_Input::handle_key() { - int i; - int pcompose = compose; compose = 0; - char key = Fl::event_text()[0]; + char ascii = Fl::event_text()[0]; + + // Insert characters into numeric fields after checking for legality: + if (type() == FL_FLOAT_INPUT) { - if (pcompose && Fl::event_length()) { - char buf[20]; int ins; int del; - compose = fl_compose(pcompose-1, key, del, buf, ins); - if (compose) { - replace(position(), del ? position()-del : mark(), buf, ins); - compose++; // store value+1 so 1 can initialize compose state + // This could be improved to make sure characters are only inserted + // at legal positions... + if (ascii && strchr("0123456789.eE+-", ascii)) + return replace(position(), mark(), &ascii, 1); + + } else if (type() == FL_INT_INPUT) { + + // Somewhat more complicated so that "0x12ab" hex can be typed + if (!position() && (ascii == '+' || ascii == '-') + || (ascii >= '0' && ascii <= '9') + || (position()==1 && index(0)=='0' && (ascii=='x' || ascii == 'X')) + || (position()>1 && index(0)=='0' && (index(1)=='x'||index(1)=='X') + && (ascii>='A'&& ascii<='F' || ascii>='a'&& ascii<='f'))) + return replace(position(), mark(), &ascii, 1); + + } else { + // normal input fields use compose processing: + int del; + if (Fl::compose(del)) { + replace(position(), del ? position()-del : mark(), + Fl::event_text(), Fl::event_length()); return 1; - } else { - if (pcompose==1) // compose also acts as quote-next: - return replace(position(),mark(),Fl::event_text(),Fl::event_length()); } } - if (Fl::event_state(FL_ALT|FL_META) - && !(Fl::event_length() && (key&128))) { // reserved for shortcuts - compose = pcompose; - return 0; - } - switch (Fl::event_key()) { case FL_Left: - key = ctrl('B'); break; + ascii = ctrl('B'); break; case FL_Right: - key = ctrl('F'); break; + ascii = ctrl('F'); break; case FL_Up: - key = ctrl('P'); break; + ascii = ctrl('P'); break; case FL_Down: - key = ctrl('N'); break; + ascii = ctrl('N'); break; case FL_Delete: - key = ctrl('D'); break; + ascii = ctrl('D'); break; case FL_Home: - key = ctrl('A'); break; + ascii = ctrl('A'); break; case FL_End: - key = ctrl('E'); break; + ascii = ctrl('E'); break; case FL_BackSpace: if (mark() != position()) cut(); else cut(-1); @@ -186,19 +121,15 @@ int Fl_Input::handle_key() { return 0; // reserved for shortcuts case FL_Tab: if (Fl::event_state(FL_CTRL) || type()!=FL_MULTILINE_INPUT) return 0; - break; - case FL_Escape: - return 0; // reserved for shortcuts (Forms cleared field) - case FL_Control_R: - case 0xff20: // Multi-Key - compose = 1; - return 1; + return replace(position(), mark(), &ascii, 1); + default: + if (!ascii) return 0; // don't reset compose on shift keys } - switch(key) { - case 0: // key did not translate to any text - compose = pcompose; // allow user to hit shift keys after ^Q - return 0; + Fl::compose_reset(); + + int i; + switch(ascii) { case ctrl('A'): if (type() == FL_MULTILINE_INPUT) for (i=position(); i && index(i-1)!='\n'; i--) ; @@ -243,9 +174,6 @@ int Fl_Input::handle_key() { if (!i) return NORMAL_INPUT_MOVE; shift_up_down_position(i-1); return 1; - case ctrl('Q'): - compose = 1; - return 1; case ctrl('U'): return cut(0, size()); case ctrl('V'): @@ -261,22 +189,7 @@ int Fl_Input::handle_key() { return undo(); } - // skip all illegal characters - // this could be improved to make sure characters are inserted at - // legal positions... - if (type() == FL_FLOAT_INPUT) { - if (!strchr("0123456789.eE+-", key)) return 0; - } else if (type() == FL_INT_INPUT) { - if (!position() && (key == '+' || key == '-')); - else if (key >= '0' && key <= '9'); - // we allow 0xabc style hex numbers to be typed: - else if (position()==1 && index(0)=='0' && (key == 'x' || key == 'X')); - else if (position()>1 && index(0)=='0' && (index(1)=='x'||index(1)=='X') - && (key>='A'&& key<='F' || key>='a'&& key<='f')); - else return 0; - } - - return replace(position(), mark(), Fl::event_text(), Fl::event_length()); + return 0; } int Fl_Input::handle(int event) { @@ -305,7 +218,7 @@ int Fl_Input::handle(int event) { break; case FL_UNFOCUS: - compose = 0; + Fl::compose_reset(); break; case FL_KEYBOARD: @@ -321,7 +234,7 @@ int Fl_Input::handle(int event) { return 1; } } - compose = 0; + Fl::compose_reset(); break; case FL_RELEASE: @@ -346,5 +259,5 @@ Fl_Input::Fl_Input(int x, int y, int w, int h, const char *l) } // -// End of "$Id: Fl_Input.cxx,v 1.10.2.5 2000/02/18 07:11:09 bill Exp $". +// End of "$Id: Fl_Input.cxx,v 1.10.2.6 2000/02/21 10:29:58 bill Exp $". // diff --git a/src/Fl_compose.cxx b/src/Fl_compose.cxx new file mode 100644 index 000000000..92fa1467b --- /dev/null +++ b/src/Fl_compose.cxx @@ -0,0 +1,136 @@ +// +// "$Id: Fl_compose.cxx,v 1.1.2.1 2000/02/21 10:29:59 bill Exp $" +// +// Character compose processing for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2000 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@easysw.com". +// + +#include <FL/Fl.H> + +static const char* const compose_pairs = +" ! % # $ y=| & : c a <<~ - r _ * +-2 3 ' u p . , 1 o >>141234? " +"`A'A^A~A:A*AAE,C`E'E^E:E`I'I^I:I-D~N`O'O^O~O:Ox O/`U'U^U:U'YTHss" +"`a'a^a~a:a*aae,c`e'e^e:e`i'i^i:i-d~n`o'o^o~o:o-:o/`u'u^u:u'yth:y"; + +#ifndef _WIN32 // X only +// X dead-key lookup table. This turns a dead-key keysym into the +// first of two characters for one of the compose sequences. These +// keysyms start at 0xFE50. +// Win32 handles the dead keys before fltk can see them. This is +// unfortunate, because you don't get the preview effect. +static char dead_keys[] = { + '`', // XK_dead_grave + '\'', // XK_dead_acute + '^', // XK_dead_circumflex + '~', // XK_dead_tilde + '_', // XK_dead_macron + 0, // XK_dead_breve + '.', // XK_dead_abovedot + ':', // XK_dead_diaeresis + '*', // XK_dead_abovering + 0, // XK_dead_doubleacute + 'v', // XK_dead_caron + ',' // XK_dead_cedilla +// 0, // XK_dead_ogonek +// 0, // XK_dead_iota +// 0, // XK_dead_voiced_sound +// 0, // XK_dead_semivoiced_sound +// 0 // XK_dead_belowdot +}; +#endif + +int Fl::compose_state; + +int Fl::compose(int& del) { + + del = 0; + char ascii = e_text[0]; + + // Alt+letters are reserved for shortcuts. But alt+foreign letters + // has to be allowed, because some key layouts require alt to be held + // down in order to type them... + if (e_state & (FL_ALT|FL_META) && !(ascii & 128)) return 0; + + if (compose_state == 1) { // after the compose key + + if (ascii == ' ') { // space turns into nbsp + e_text[0] = char(0xA0); + compose_state = 0; + return 1; + } + + // see if it is either character of any pair: + for (const char *p = compose_pairs; *p; p += 2) + if (p[0] == ascii || p[1] == ascii) { + if (p[1] == ' ') e_text[0] = (p-compose_pairs)/2+0xA0; + compose_state = ascii; + return 1; + } + + if (e_length) { // compose key also "quotes" control characters + compose_state = 0; + return 1; + } + + } else if (compose_state) { // second character of compose + + char c1 = char(compose_state); // retrieve first character + // now search for the pair in either order: + for (const char *p = compose_pairs; *p; p += 2) { + if (p[0] == ascii && p[1] == c1 || p[1] == ascii && p[0] == c1) { + e_text[0] = (p-compose_pairs)/2+0xA0; + del = 1; // delete the old character and insert new one + compose_state = 0; + return 1; + } + } + + } + + int i = e_keysym; + + // See if they type the compose prefix key: + if (i == FL_Control_R || i == 0xff20/* Multi-Key */) { + compose_state = 1; + return 1; + } + +#ifndef _WIN32 // X only + // See if they typed a dead key. This gets it into the same state as + // typing prefix+accent: + if (i >= 0xfe50 && i <= 0xfe5b) { + ascii = dead_keys[i-0xfe50]; + for (const char *p = compose_pairs; *p; p += 2) + if (p[0] == ascii) { + compose_state = ascii; + return 1; + } + compose_state = 0; + return 1; + } +#endif + + // Only insert non-control characters: + if (e_length && (ascii&~31)) {compose_state = 0; return 1;} + + return 0; +} + diff --git a/src/Makefile b/src/Makefile index ffd17ea53..17c847048 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,5 +1,5 @@ # -# "$Id: Makefile,v 1.18.2.8 1999/04/26 12:36:17 mike Exp $" +# "$Id: Makefile,v 1.18.2.9 2000/02/21 10:29:59 bill Exp $" # # Library makefile for the Fast Light Tool Kit (FLTK). # @@ -83,6 +83,7 @@ CPPFILES = \ Fl_abort.cxx \ Fl_add_idle.cxx \ Fl_arg.cxx \ + Fl_compose.cxx \ Fl_cutpaste.cxx \ Fl_display.cxx \ Fl_get_key.cxx \ @@ -209,5 +210,5 @@ install: $(LIBRARY) $(DSONAME) @-ln -s FL $(includedir)/Fl # -# End of "$Id: Makefile,v 1.18.2.8 1999/04/26 12:36:17 mike Exp $". +# End of "$Id: Makefile,v 1.18.2.9 2000/02/21 10:29:59 bill Exp $". # diff --git a/src/fl_set_fonts.cxx b/src/fl_set_fonts.cxx index 27fb23530..13792c5d9 100644 --- a/src/fl_set_fonts.cxx +++ b/src/fl_set_fonts.cxx @@ -1,5 +1,5 @@ // -// "$Id: fl_set_fonts.cxx,v 1.6 1999/01/07 19:17:42 mike Exp $" +// "$Id: fl_set_fonts.cxx,v 1.6.2.1 2000/02/21 10:30:00 bill Exp $" // // More font utilities for the Fast Light Tool Kit (FLTK). // @@ -239,6 +239,8 @@ static int to_canonical(char *to, const char *from) { static int fl_free_font = FL_FREE_FONT; Fl_Font Fl::set_fonts(const char* xstarname) { + if (fl_free_font > FL_FREE_FONT) // already been here + return (Fl_Font)fl_free_font; fl_open_display(); int xlistsize; char buf[20]; @@ -325,5 +327,5 @@ int Fl::get_font_sizes(Fl_Font fnum, int*& sizep) { #endif // -// End of "$Id: fl_set_fonts.cxx,v 1.6 1999/01/07 19:17:42 mike Exp $". +// End of "$Id: fl_set_fonts.cxx,v 1.6.2.1 2000/02/21 10:30:00 bill Exp $". // diff --git a/src/fl_set_fonts_win32.cxx b/src/fl_set_fonts_win32.cxx index 6e93bd5c2..695743d79 100755 --- a/src/fl_set_fonts_win32.cxx +++ b/src/fl_set_fonts_win32.cxx @@ -1,5 +1,5 @@ // -// "$Id: fl_set_fonts_win32.cxx,v 1.5 1999/01/07 19:17:42 mike Exp $" +// "$Id: fl_set_fonts_win32.cxx,v 1.5.2.1 2000/02/21 10:30:00 bill Exp $" // // WIN32 font utilities for the Fast Light Tool Kit (FLTK). // @@ -74,7 +74,8 @@ static int CALLBACK enumcb(ENUMLOGFONT FAR *lpelf, } Fl_Font Fl::set_fonts(const char* xstarname) { - EnumFontFamilies(fl_gc, NULL, (FONTENUMPROC)enumcb, xstarname != 0); + if (fl_free_font == FL_FREE_FONT) // if not already been called + EnumFontFamilies(fl_gc, NULL, (FONTENUMPROC)enumcb, xstarname != 0); return (Fl_Font)fl_free_font; } @@ -87,5 +88,5 @@ int Fl::get_font_sizes(Fl_Font fnum, int*& sizep) { } // -// End of "$Id: fl_set_fonts_win32.cxx,v 1.5 1999/01/07 19:17:42 mike Exp $". +// End of "$Id: fl_set_fonts_win32.cxx,v 1.5.2.1 2000/02/21 10:30:00 bill Exp $". // |
