123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266 |
- /*
- * Graffiti.c is based on the file Scribble.c copyrighted
- * by Keith Packard:
- *
- * Copyright © 1999 Keith Packard
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation, and that the name of Keith Packard not be used in
- * advertising or publicity pertaining to distribution of the software without
- * specific, written prior permission. Keith Packard makes no
- * representations about the suitability of this software for any purpose. It
- * is provided "as is" without express or implied warranty.
- *
- * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
- * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- * PERFORMANCE OF THIS SOFTWARE.
- */
- #include <u.h>
- #include <libc.h>
- #include <draw.h>
- #include <scribble.h>
- #include "scribbleimpl.h"
- #include "graffiti.h"
- int ScribbleDebug;
- char *cl_name[3] = {
- DEFAULT_LETTERS_FILE,
- DEFAULT_DIGITS_FILE,
- DEFAULT_PUNC_FILE
- };
- Rune
- recognize (Scribble *s)
- {
- struct graffiti *graf = s->graf;
- Stroke *ps = &s->ps;
- Rune rune;
- int c;
- int nr;
- rec_alternative *ret;
- if (ps->npts == 0)
- return '\0';
- c = recognizer_translate(
- graf->rec[s->puncShift ? CS_PUNCTUATION : s->curCharSet],
- 1, ps, false, &nr, &ret);
- if (c != -1)
- delete_rec_alternative_array(nr, ret, false);
- rune = '\0';
- switch (c) {
- case '\0':
- if(ScribbleDebug)fprint(2, "(case '\\0')\n");
- break;
- case 'A': /* space */
- rune = ' ';
- if(ScribbleDebug)fprint(2, "(case A) character = ' %C' (0x%x)\n", rune, rune);
- break;
- case 'B': /* backspace */
- rune = '\b';
- if(ScribbleDebug)fprint(2, "(case B) character = \\b (0x%x)\n", rune);
- break;
- case 'N': /* numlock */
- if(ScribbleDebug)fprint(2, "(case N)\n");
- if (s->curCharSet == CS_DIGITS) {
- s->curCharSet = CS_LETTERS;
- } else {
- s->curCharSet = CS_DIGITS;
- }
- s->tmpShift = 0;
- s->puncShift = 0;
- s->ctrlShift = 0;
- break;
- case 'P': /* usually puncshift, but we'll make it CTRL */
- if(ScribbleDebug)fprint(2, "(case P)\n");
- s->ctrlShift = !s->ctrlShift;
- s->tmpShift = 0;
- s->puncShift = 0;
- break;
- case 'R': /* newline */
- rune = '\n';
- if(ScribbleDebug)fprint(2, "(case R) character = \\n (0x%x)\n", rune);
- break;
- case 'S': /* shift */
- if(ScribbleDebug)fprint(2, "(case S)\n");
- s->puncShift = 0;
- s->ctrlShift = 0;
- if (s->capsLock) {
- s->capsLock = 0;
- s->tmpShift = 0;
- break;
- }
- if (s->tmpShift == 0) {
- s->tmpShift++;
- break;
- }
- /* fall through */
- case 'L': /* caps lock */
- if(ScribbleDebug)fprint(2, "(case L)\n");
- s->capsLock = !s->capsLock;
- break;
- case '.': /* toggle punctuation mode */
- if (s->puncShift) {
- s->puncShift = 0;
- } else {
- s->puncShift = 1;
- s->ctrlShift = 0;
- s->tmpShift = 0;
- return rune;
- }
- rune = '.';
- if(0)fprint(2, "(case .) character = %c (0x%x)\n", rune, rune);
- break;
- default:
- if ('A' <= c && c <= 'Z') {
- if(ScribbleDebug)fprint(2, "(bad case?) character = %c (0x%x)\n", c, c);
- return rune;
- }
- rune = c;
- if (s->ctrlShift)
- {
- if (c < 'a' || 'z' < c)
- {
- if(ScribbleDebug)fprint(2, "(default) character = %c (0x%x)\n", rune, rune);
- return rune;
- }
- rune = rune & 0x1f;
- } else if ((s->capsLock && !s->tmpShift) ||
- (!s->capsLock && s->tmpShift))
- {
- if (rune < 0xff)
- rune = toupper(rune);
- }
- s->tmpShift = 0;
- s->puncShift = 0;
- s->ctrlShift = 0;
- if(ScribbleDebug)fprint(2, "(default) character = %c (0x%x)\n", rune, rune);
- }
- return rune;
- }
- /* This procedure is called to initialize pg by loading the three
- * recognizers, loading the initial set of three classifiers, and
- * loading & verifying the recognizer extension functions. If the
- * directory $HOME/.recognizers exists, the classifier files will be
- * loaded from that directory. If not, or if there is an error, the
- * default files (directory specified in Makefile) will be loaded
- * instead. Returns non-zero on success, 0 on failure. (Adapted from
- * package tkgraf/src/GraffitiPkg.c.
- */
- static int
- graffiti_load_recognizers(struct graffiti *pg)
- {
- bool usingDefault;
- char* homedir;
- int i;
- rec_fn *fns;
- /* First, load the recognizers... */
- /* call recognizer_unload if an error ? */
- for (i = 0; i < NUM_RECS; i++) {
- /* Load the recognizer itself... */
- pg->rec[i] = recognizer_load(DEFAULT_REC_DIR, "", nil);
- if (pg->rec[i] == nil) {
- fprint(2,"Error loading recognizer from %s.", DEFAULT_REC_DIR);
- return 0;
- }
- if ((* (int *)(pg->rec[i])) != 0xfeed) {
- fprint(2,"Error in recognizer_magic.");
- return 0;
- }
- }
- /* ...then figure out where the classifiers are... */
- if ( (homedir = (char*)getenv("home")) == nil ) {
- if(0)fprint(2, "no homedir, using = %s\n", REC_DEFAULT_USER_DIR);
- strecpy(pg->cldir, pg->cldir+sizeof pg->cldir, REC_DEFAULT_USER_DIR);
- usingDefault = true;
- } else {
- if(0)fprint(2, "homedir = %s\n", homedir);
- snprint(pg->cldir, sizeof pg->cldir, "%s/%s", homedir, CLASSIFIER_DIR);
- usingDefault = false;
- }
- /* ...then load the classifiers... */
- for (i = 0; i < NUM_RECS; i++) {
- int rec_return;
- char *s;
- rec_return = recognizer_load_state(pg->rec[i], pg->cldir, cl_name[i]);
- if ((rec_return == -1) && (usingDefault == false)) {
- if(0)fprint(2, "Unable to load custom classifier file %s/%s.\nTrying default classifier file instead.\nOriginal error: %s\n ",
- pg->cldir, cl_name[i],
- (s = recognizer_error(pg->rec[i])) ? s : "(none)");
- rec_return = recognizer_load_state(pg->rec[i],
- REC_DEFAULT_USER_DIR, cl_name[i]);
- }
- if (rec_return == -1) {
- fprint(2, "Unable to load default classifier file %s.\nOriginal error: %s\n",
- cl_name[i],
- (s = recognizer_error(pg->rec[i])) ? s : "(none)");
- return 0;
- }
- }
- /* We have recognizers and classifiers now. */
- /* Get the vector of LIextension functions.. */
- fns = recognizer_get_extension_functions(pg->rec[CS_LETTERS]);
- if (fns == nil) {
- fprint(2, "LI Recognizer Training:No extension functions!");
- return 0;
- }
-
- /* ... and make sure the training & get-classes functions are okay. */
- if( (pg->rec_train = (li_recognizer_train)fns[LI_TRAIN]) == nil ) {
- fprint(2,
- "LI Recognizer Training:li_recognizer_train() not found!");
- if (fns != nil) {
- free(fns);
- }
- return 0;
- }
-
- if( (pg->rec_getClasses = (li_recognizer_getClasses)fns[LI_GET_CLASSES]) == nil ) {
- fprint(2,
- "LI Recognizer Training:li_recognizer_getClasses() not found!");
- if (fns != nil) {
- free(fns);
- }
- return 0;
- }
- free(fns);
- return 1;
- }
- Scribble *
- scribblealloc(void)
- {
- Scribble *s;
- s = mallocz(sizeof(Scribble), 1);
- if (s == nil)
- sysfatal("Initialize: %r");
- s->curCharSet = CS_LETTERS;
- s->graf = mallocz(sizeof(struct graffiti), 1);
- if (s->graf == nil)
- sysfatal("Initialize: %r");
- graffiti_load_recognizers(s->graf);
- return s;
- }
|