2 * Graffiti.c is based on the file Scribble.c copyrighted
5 * Copyright © 1999 Keith Packard
7 * Permission to use, copy, modify, distribute, and sell this software and its
8 * documentation for any purpose is hereby granted without fee, provided that
9 * the above copyright notice appear in all copies and that both that
10 * copyright notice and this permission notice appear in supporting
11 * documentation, and that the name of Keith Packard not be used in
12 * advertising or publicity pertaining to distribution of the software without
13 * specific, written prior permission. Keith Packard makes no
14 * representations about the suitability of this software for any purpose. It
15 * is provided "as is" without express or implied warranty.
17 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
18 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
19 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
20 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
22 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
23 * PERFORMANCE OF THIS SOFTWARE.
31 #include "scribbleimpl.h"
43 recognize (Scribble *s)
45 struct graffiti *graf = s->graf;
55 c = recognizer_translate(
56 graf->rec[s->puncShift ? CS_PUNCTUATION : s->curCharSet],
57 1, ps, false, &nr, &ret);
59 delete_rec_alternative_array(nr, ret, false);
65 if(ScribbleDebug)fprint(2, "(case '\\0')\n");
69 if(ScribbleDebug)fprint(2, "(case A) character = ' %C' (0x%x)\n", rune, rune);
71 case 'B': /* backspace */
73 if(ScribbleDebug)fprint(2, "(case B) character = \\b (0x%x)\n", rune);
75 case 'N': /* numlock */
76 if(ScribbleDebug)fprint(2, "(case N)\n");
77 if (s->curCharSet == CS_DIGITS) {
78 s->curCharSet = CS_LETTERS;
80 s->curCharSet = CS_DIGITS;
86 case 'P': /* usually puncshift, but we'll make it CTRL */
87 if(ScribbleDebug)fprint(2, "(case P)\n");
88 s->ctrlShift = !s->ctrlShift;
92 case 'R': /* newline */
94 if(ScribbleDebug)fprint(2, "(case R) character = \\n (0x%x)\n", rune);
97 if(ScribbleDebug)fprint(2, "(case S)\n");
105 if (s->tmpShift == 0) {
110 case 'L': /* caps lock */
111 if(ScribbleDebug)fprint(2, "(case L)\n");
112 s->capsLock = !s->capsLock;
114 case '.': /* toggle punctuation mode */
124 if(0)fprint(2, "(case .) character = %c (0x%x)\n", rune, rune);
127 if ('A' <= c && c <= 'Z') {
128 if(ScribbleDebug)fprint(2, "(bad case?) character = %c (0x%x)\n", c, c);
134 if (c < 'a' || 'z' < c)
136 if(ScribbleDebug)fprint(2, "(default) character = %c (0x%x)\n", rune, rune);
140 } else if ((s->capsLock && !s->tmpShift) ||
141 (!s->capsLock && s->tmpShift))
144 rune = toupper(rune);
149 if(ScribbleDebug)fprint(2, "(default) character = %c (0x%x)\n", rune, rune);
154 /* This procedure is called to initialize pg by loading the three
155 * recognizers, loading the initial set of three classifiers, and
156 * loading & verifying the recognizer extension functions. If the
157 * directory $HOME/.recognizers exists, the classifier files will be
158 * loaded from that directory. If not, or if there is an error, the
159 * default files (directory specified in Makefile) will be loaded
160 * instead. Returns non-zero on success, 0 on failure. (Adapted from
161 * package tkgraf/src/GraffitiPkg.c.
165 graffiti_load_recognizers(struct graffiti *pg)
172 /* First, load the recognizers... */
173 /* call recognizer_unload if an error ? */
174 for (i = 0; i < NUM_RECS; i++) {
175 /* Load the recognizer itself... */
176 pg->rec[i] = recognizer_load(DEFAULT_REC_DIR, "", nil);
177 if (pg->rec[i] == nil) {
178 fprint(2,"Error loading recognizer from %s.", DEFAULT_REC_DIR);
181 if ((* (int *)(pg->rec[i])) != 0xfeed) {
182 fprint(2,"Error in recognizer_magic.");
187 /* ...then figure out where the classifiers are... */
188 if ( (homedir = (char*)getenv("home")) == nil ) {
189 if(0)fprint(2, "no homedir, using = %s\n", REC_DEFAULT_USER_DIR);
190 strecpy(pg->cldir, pg->cldir+sizeof pg->cldir, REC_DEFAULT_USER_DIR);
193 if(0)fprint(2, "homedir = %s\n", homedir);
194 snprint(pg->cldir, sizeof pg->cldir, "%s/%s", homedir, CLASSIFIER_DIR);
195 usingDefault = false;
198 /* ...then load the classifiers... */
199 for (i = 0; i < NUM_RECS; i++) {
203 rec_return = recognizer_load_state(pg->rec[i], pg->cldir, cl_name[i]);
204 if ((rec_return == -1) && (usingDefault == false)) {
205 if(0)fprint(2, "Unable to load custom classifier file %s/%s.\nTrying default classifier file instead.\nOriginal error: %s\n ",
206 pg->cldir, cl_name[i],
207 (s = recognizer_error(pg->rec[i])) ? s : "(none)");
208 rec_return = recognizer_load_state(pg->rec[i],
209 REC_DEFAULT_USER_DIR, cl_name[i]);
211 if (rec_return == -1) {
212 fprint(2, "Unable to load default classifier file %s.\nOriginal error: %s\n",
214 (s = recognizer_error(pg->rec[i])) ? s : "(none)");
219 /* We have recognizers and classifiers now. */
220 /* Get the vector of LIextension functions.. */
221 fns = recognizer_get_extension_functions(pg->rec[CS_LETTERS]);
223 fprint(2, "LI Recognizer Training:No extension functions!");
227 /* ... and make sure the training & get-classes functions are okay. */
228 if( (pg->rec_train = (li_recognizer_train)fns[LI_TRAIN]) == nil ) {
230 "LI Recognizer Training:li_recognizer_train() not found!");
237 if( (pg->rec_getClasses = (li_recognizer_getClasses)fns[LI_GET_CLASSES]) == nil ) {
239 "LI Recognizer Training:li_recognizer_getClasses() not found!");
254 s = mallocz(sizeof(Scribble), 1);
256 sysfatal("Initialize: %r");
257 s->curCharSet = CS_LETTERS;
259 s->graf = mallocz(sizeof(struct graffiti), 1);
261 sysfatal("Initialize: %r");
263 graffiti_load_recognizers(s->graf);