OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [mw/] [src/] [demos/] [nxscribble/] [scribwidget.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 673 markom
/*
2
 * Copyright (c) 2000 Greg Haerr <greg@censoft.com>
3
 * Copyright (c) 2000 Century Software <embedded.centurysoftware.com>
4
 * Scribble Handwriting Recognition for Nano-X!
5
 * Scribble object routines
6
 *
7
 * Copyright © 1999 Keith Packard
8
 *
9
 * Permission to use, copy, modify, distribute, and sell this software and its
10
 * documentation for any purpose is hereby granted without fee, provided that
11
 * the above copyright notice appear in all copies and that both that
12
 * copyright notice and this permission notice appear in supporting
13
 * documentation, and that the name of Keith Packard not be used in
14
 * advertising or publicity pertaining to distribution of the software without
15
 * specific, written prior permission.  Keith Packard makes no
16
 * representations about the suitability of this software for any purpose.  It
17
 * is provided "as is" without express or implied warranty.
18
 *
19
 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
20
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
21
 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
22
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
23
 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
24
 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
25
 * PERFORMANCE OF THIS SOFTWARE.
26
 */
27
 
28
#include <stdio.h>
29
#include <string.h>
30
#include "scrib.h"
31
 
32
static ScribbleRec      scrib;          /* static object instance*/
33
static char *curmsg = NULL;
34
 
35
static char *cl_name[3] = {DEFAULT_LETTERS_FILE,
36
                             DEFAULT_DIGITS_FILE,
37
                             DEFAULT_PUNC_FILE};
38
 
39
static int graffiti_load_recognizers(struct graffiti *pg);
40
static void Recognize (ScribbleWidget w);
41
static void ShowMode (ScribbleWidget w);
42
 
43
static void
44
ResetStroke (ScribbleWidget w)
45
{
46
    w->ps.ps_npts = 0;
47
    w->ps.ps_nstate = 0;
48
    w->ps.ps_trans = 0;
49
    w->ps.ps_state = 0;
50
    w->lastchar = 0;
51
    curmsg = NULL;
52
    ShowMode(w);
53
}
54
 
55
static void
56
DisplayStroke (ScribbleWidget   w)
57
{
58
    GrDrawLines(w->win, w->gc, w->pt, w->ps.ps_npts);
59
}
60
 
61
static void
62
DisplayLast (ScribbleWidget w)
63
{
64
    int     npt;
65
 
66
    npt = w->ps.ps_npts;
67
    if (npt > 2)
68
        npt = 2;
69
    GrDrawLines(w->win, w->gc, w->pt + (w->ps.ps_npts - npt), npt);
70
}
71
 
72
static void
73
AddPoint (ScribbleWidget w, int x, int y)
74
{
75
    pen_point   *ppa;
76
    GR_POINT    *pt;
77
    int         ppasize;
78
 
79
    if (w->ps.ps_npts == w->ppasize)
80
    {
81
        ppasize = w->ppasize + 100;
82
        ppa = malloc ((sizeof (pen_point) + sizeof (GR_POINT)) * ppasize);
83
        if (!ppa)
84
            return;
85
        pt = (GR_POINT *) (ppa + ppasize);
86
        memcpy (ppa, w->ps.ps_pts, w->ppasize * sizeof (pen_point));
87
        memcpy (pt, w->pt, w->ppasize * sizeof (GR_POINT));
88
        free (w->ps.ps_pts);
89
        w->ps.ps_pts = ppa;
90
        w->pt = pt;
91
        w->ppasize = ppasize;
92
    }
93
    ppa = &w->ps.ps_pts[w->ps.ps_npts];
94
    ppa->x = x;
95
    ppa->y = y;
96
 
97
    pt = &w->pt[w->ps.ps_npts];
98
    pt->x = x;
99
    pt->y = y;
100
 
101
    w->ps.ps_npts++;
102
 
103
    DisplayLast (w);
104
}
105
 
106
ScribbleWidget
107
create_scribble(void)
108
{
109
    ScribbleWidget new = (ScribbleWidget)&scrib;
110
    GR_WM_PROPERTIES props;
111
 
112
    new->capsLock = 0;
113
    new->puncShift = 0;
114
    new->tmpShift = 0;
115
    new->ctrlShift = 0;
116
    new->curCharSet = CS_LETTERS;
117
    new->lastchar = 0;
118
    new->down = GR_FALSE;
119
    /*new->lastfocusid = 0;*/
120
 
121
    graffiti_load_recognizers (&new->graf);
122
 
123
    new->ppasize = 0;
124
    new->ps.ps_pts = 0;
125
    new->pt = 0;
126
 
127
    new->win = GrNewWindow(GR_ROOT_WINDOW_ID,
128
                    350, 20, 200, 150,
129
                    0, GrGetSysColor(GR_COLOR_APPWINDOW), BLACK);
130
    /* set title, disallow focus on input window*/
131
    props.flags = GR_WM_FLAGS_TITLE | GR_WM_FLAGS_PROPS;
132
    props.props = GR_WM_PROPS_NOFOCUS | GR_WM_PROPS_BORDER |
133
            GR_WM_PROPS_CAPTION | GR_WM_PROPS_CLOSEBOX;
134
    props.title = "nxScribble";
135
    GrSetWMProperties(new->win, &props);
136
 
137
    GrSelectEvents(new->win, GR_EVENT_MASK_BUTTON_DOWN |
138
                GR_EVENT_MASK_BUTTON_UP | GR_EVENT_MASK_MOUSE_MOTION |
139
                GR_EVENT_MASK_KEY_DOWN | /*GR_EVENT_MASK_FOCUS_IN |*/
140
                GR_EVENT_MASK_EXPOSURE | GR_EVENT_MASK_CLOSE_REQ);
141
    GrMapWindow(new->win);
142
 
143
    new->gc = GrNewGC();
144
    GrSetGCForeground(new->gc, GrGetSysColor(GR_COLOR_APPTEXT));
145
    GrSetGCBackground(new->gc, GrGetSysColor(GR_COLOR_APPWINDOW));
146
    GrSetGCFont(new->gc, GrCreateFont(GR_FONT_OEM_FIXED, 0, NULL));
147
 
148
    ResetStroke (new);
149
    return new;
150
}
151
 
152
void
153
destroy_scribble(ScribbleWidget w)
154
{
155
    GrDestroyWindow(w->win);
156
    GrDestroyGC(w->gc);
157
    free (w->ps.ps_pts);
158
}
159
 
160
void
161
Redisplay (ScribbleWidget w)
162
{
163
    /*DisplayStroke (w);*/
164
    ShowMode(w);
165
}
166
 
167
void
168
ActionStart (ScribbleWidget w, int x, int y)
169
{
170
    GrRaiseWindow(w->win);
171
    ResetStroke (w);
172
    w->down = GR_TRUE;
173
    AddPoint (w, x, y);
174
}
175
 
176
void
177
ActionMove (ScribbleWidget w, int x, int y)
178
{
179
    if (w->down)
180
        AddPoint (w, x, y);
181
}
182
 
183
void
184
ActionEnd (ScribbleWidget w, int x, int y)
185
{
186
    AddPoint (w, x, y);
187
    w->down = GR_FALSE;
188
    Recognize (w);
189
}
190
 
191
 
192
static void
193
SendKey(ScribbleWidget w, int ch)
194
{
195
        GR_WINDOW_ID    win = GrGetFocus();
196
 
197
        /* FIXME: modifiers are incorrect*/
198
        GrInjectKeyboardEvent(win, ch, 0, 0, 1);
199
        GrInjectKeyboardEvent(win, ch, 0, 0, 0);
200
}
201
 
202
/* This procedure is called to initialize pg by loading the three
203
   recognizers, loading the initial set of three classifiers, and
204
   loading & verifying the recognizer extension functions.  If the
205
   directory $HOME/.recognizers exists, the classifier files will be
206
   loaded from that directory.  If not, or if there is an error, the
207
   default files (directory specified in Makefile) will be loaded
208
   instead.  Returns non-zero on success, 0 on failure.  (Adapted from
209
   package tkgraf/src/GraffitiPkg.c. */
210
 
211
static int
212
graffiti_load_recognizers(struct graffiti *pg)
213
{
214
        bool usingDefault;
215
#if 0
216
        char* homedir;
217
#endif
218
        int i;
219
        rec_fn *fns;
220
 
221
        /* First, load the recognizers... */
222
        /* call recognizer_unload if an error ? */
223
        for (i = 0; i < NUM_RECS; i++) {
224
                /* Load the recognizer itself... */
225
                pg->rec[i] = recognizer_load(DEFAULT_REC_DIR, rec_name, NULL);
226
                if (pg->rec[i] == NULL) {
227
                        fprintf(stderr,"Error loading recognizer from %s.", DEFAULT_REC_DIR);
228
                        return 0;
229
                }
230
                if ((* (int *)(pg->rec[i])) != 0xfeed) {
231
                        fprintf(stderr,"Error in recognizer_magic.");
232
                        return 0;
233
                }
234
        }
235
 
236
        /* ...then figure out where the classifiers are... */
237
#if 0
238
        if ( (homedir = (char*)getenv("HOME")) == NULL ) {
239
#endif
240
                strcpy(pg->cldir, REC_DEFAULT_USER_DIR);
241
                usingDefault = true;
242
#if 0
243
        } else {
244
                strcpy(pg->cldir, homedir);
245
                strcat(pg->cldir, "/");
246
                strcat(pg->cldir, CLASSIFIER_DIR);
247
                usingDefault = false;
248
        }
249
#endif
250
 
251
        /* ...then load the classifiers... */
252
        for (i = 0; i < NUM_RECS; i++) {
253
                int rec_return;
254
                char *s;
255
 
256
                rec_return = recognizer_load_state(pg->rec[i], pg->cldir, cl_name[i]);
257
                if ((rec_return == -1) && (usingDefault == false)) {
258
                        fprintf(stderr,
259
                                "Unable to load custom classifier file %s/%s.\nTrying default classifier file instead.\nOriginal error: %s\n ",
260
                                pg->cldir, cl_name[i],
261
                                (s = recognizer_error(pg->rec[i])) ? s : "(none)");
262
                        rec_return = recognizer_load_state(pg->rec[i],
263
                                                           REC_DEFAULT_USER_DIR, cl_name[i]);
264
                }
265
                if (rec_return == -1) {
266
                        fprintf(stderr, "Unable to load default classifier file %s.\nOriginal error: %s\n",
267
                                cl_name[i],
268
                                (s = recognizer_error(pg->rec[i])) ? s : "(none)");
269
                        return 0;
270
                }
271
        }
272
 
273
        /* We have recognizers and classifiers now.   */
274
        /* Get the vector of LIextension functions..     */
275
        fns = recognizer_get_extension_functions(pg->rec[CS_LETTERS]);
276
        if (fns == NULL) {
277
                fprintf(stderr, "LI Recognizer Training:No extension functions!");
278
                return 0;
279
        }
280
 
281
        /* ... and make sure the training & get-classes functions are okay. */
282
        if( (pg->rec_train = (li_recognizer_train)fns[LI_TRAIN]) == NULL ) {
283
                fprintf(stderr,
284
                        "LI Recognizer Training:li_recognizer_train() not found!");
285
                if (fns != NULL) {
286
                        free(fns);
287
                }
288
                return 0;
289
        }
290
 
291
        if( (pg->rec_getClasses = (li_recognizer_getClasses)fns[LI_GET_CLASSES]) == NULL ) {
292
                fprintf(stderr,
293
                        "LI Recognizer Training:li_recognizer_getClasses() not found!");
294
                if (fns != NULL) {
295
                        free(fns);
296
                }
297
                return 0;
298
        }
299
        free(fns);
300
        return 1;
301
}
302
 
303
static void
304
msg(char *str)
305
{
306
        curmsg = str;
307
}
308
 
309
static void
310
ShowMode (ScribbleWidget w)
311
{
312
    char *mode;
313
    char buf[32];
314
 
315
    if (w->ctrlShift)
316
        mode = "^C";
317
    else if (w->puncShift)
318
        mode = "#&^";
319
    else if (w->curCharSet == CS_DIGITS)
320
        mode = "123";
321
    else if (w->capsLock)
322
        mode = "ABC";
323
    else if (w->tmpShift)
324
        mode = "Abc";
325
    else
326
        mode = "abc";
327
 
328
    if (curmsg)
329
        sprintf(buf, "%s  %s", mode, curmsg);
330
    else if (w->lastchar > ' ')
331
        sprintf(buf, "%s    %c", mode, w->lastchar);
332
    else sprintf(buf, "%s", mode);
333
    GrClearWindow(w->win, GR_FALSE);
334
    GrText(w->win, w->gc, 70, 0, buf, strlen(buf), GR_TFTOP);
335
}
336
 
337
static char
338
do_recognize(struct graffiti *pg, pen_stroke *ps, int charset)
339
{
340
       int rec_char;
341
       int nret;
342
       rec_alternative *ret;
343
 
344
       rec_char = recognizer_translate(pg->rec[charset], 1, ps, false,
345
                                       &nret, &ret);
346
       if (rec_char != -1) {
347
               delete_rec_alternative_array(nret, ret, false);
348
       }
349
       return rec_char;
350
}
351
 
352
typedef int KeySym;
353
 
354
static void
355
Recognize (ScribbleWidget w)
356
{
357
    struct graffiti *graf = &w->graf;
358
    pen_stroke      *ps = &w->ps;
359
    KeySym          keysym;
360
    GR_BOOL         control;
361
    char            c;
362
 
363
    if (ps->ps_npts == 0)
364
        return;
365
 
366
    w->lastchar = 0;
367
 
368
    c = do_recognize(graf, ps, w->puncShift ? CS_PUNCTUATION : w->curCharSet);
369
 
370
    /*printf("class %c (%d)\n", c, c);*/
371
 
372
    switch (c) {
373
    case '\000':
374
msg("[Error]");
375
        w->tmpShift = 0;
376
        w->puncShift = 0;
377
        w->ctrlShift = 0;
378
        ShowMode (w);
379
        break;
380
    case 'L': /* caps lock */
381
msg("[Capslock]");
382
        w->capsLock = !w->capsLock;
383
        ShowMode (w);
384
        break;
385
    case 'N': /* numlock */
386
        if (w->curCharSet == CS_DIGITS) {
387
            w->curCharSet = CS_LETTERS;
388
msg("[Letters]");
389
        } else {
390
            w->curCharSet = CS_DIGITS;
391
msg("[Digits]");
392
        }
393
        w->tmpShift = 0;
394
        w->puncShift = 0;
395
        w->ctrlShift = 0;
396
        ShowMode (w);
397
        break;
398
    case 'P': /* usually puncshift, but we'll make it CTRL */
399
msg("[Ctrlshift]");
400
        w->ctrlShift = !w->ctrlShift;
401
        w->tmpShift = 0;
402
        w->puncShift = 0;
403
        ShowMode (w);
404
        break;
405
    case 'S': /* shift */
406
        w->tmpShift = !w->tmpShift;
407
if (w->tmpShift) msg("[Shift]"); else msg("[Unshift]");
408
        w->puncShift = 0;
409
        w->ctrlShift = 0;
410
        ShowMode (w);
411
        break;
412
    default:
413
        control = GR_FALSE;
414
        switch (c) {
415
        case 'A':
416
msg("[Space]");
417
            keysym = ' ';
418
            break;
419
        case 'B':
420
msg("[Backspace]");
421
            keysym = '\b';
422
            break;
423
        case 'R':
424
msg("[Return]");
425
            keysym = '\r';
426
            break;
427
        case '.':
428
            if (! w->puncShift) {
429
msg("[Puncshift]");
430
                w->puncShift = 1;
431
                w->ctrlShift = 0;
432
                w->tmpShift = 0;
433
                ShowMode (w);
434
                return;
435
            } else {
436
                w->puncShift = 0;
437
                ShowMode (w);
438
            }
439
            keysym = '.';
440
            break;
441
        default:
442
            if ('A' <= c && c <= 'Z') {
443
msg("[Notimp]");
444
                ShowMode (w);
445
                return;
446
            }
447
            keysym = (KeySym) c;
448
            if (w->ctrlShift)
449
            {
450
                control = GR_TRUE;
451
                w->ctrlShift = 0;
452
                if (c < 'a' || 'z' < c)
453
                {
454
                    ShowMode (w);
455
                    return;
456
                }
457
            }
458
            else if ((w->capsLock && !w->tmpShift) ||
459
                     (!w->capsLock && w->tmpShift))
460
            {
461
                keysym = keysym-'a'+'A';
462
            }
463
            w->tmpShift = 0;
464
            w->puncShift = 0;
465
            ShowMode(w);
466
        }
467
 
468
        if (control)
469
                keysym &= 0x1f;
470
        w->lastchar = keysym;
471
        ShowMode(w);
472
        SendKey(w, keysym);
473
        break;
474
    }
475
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.