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
This commit is contained in:
parent
0bd9018d64
commit
b5529a0aea
175
src/Fl_Input.cxx
175
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];
|
||||
|
||||
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
|
||||
// Insert characters into numeric fields after checking for legality:
|
||||
if (type() == FL_FLOAT_INPUT) {
|
||||
|
||||
// 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 $".
|
||||
//
|
||||
|
136
src/Fl_compose.cxx
Normal file
136
src/Fl_compose.cxx
Normal file
@ -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;
|
||||
}
|
||||
|
@ -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 $".
|
||||
#
|
||||
|
@ -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 $".
|
||||
//
|
||||
|
@ -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 $".
|
||||
//
|
||||
|
Loading…
Reference in New Issue
Block a user