Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/*
2
 * Graffiti.c is based on the file Scribble.c copyrighted
3
 * by Keith Packard:
4
 *
5
 * Copyright © 1999 Keith Packard
6
 *
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.
16
 *
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.
24
 */
25
 
26
#include <u.h>
27
#include <libc.h>
28
#include <draw.h>
29
#include <scribble.h>
30
 
31
#include "scribbleimpl.h"
32
#include "graffiti.h"
33
 
34
int ScribbleDebug;
35
 
36
char *cl_name[3] = {
37
	DEFAULT_LETTERS_FILE,
38
	DEFAULT_DIGITS_FILE,
39
	DEFAULT_PUNC_FILE
40
};
41
 
42
Rune
43
recognize (Scribble *s)
44
{
45
	struct graffiti *graf = s->graf;
46
	Stroke	    *ps = &s->ps;
47
	Rune		    rune;
48
	int		    	c;
49
	int				nr;
50
	rec_alternative	*ret;
51
 
52
	if (ps->npts == 0)
53
		return '\0';
54
 
55
	c = recognizer_translate(
56
		graf->rec[s->puncShift ? CS_PUNCTUATION : s->curCharSet],
57
		1, ps, false, &nr, &ret);
58
	if (c != -1)
59
		delete_rec_alternative_array(nr, ret, false);
60
 
61
	rune = '\0';
62
 
63
	switch (c) {
64
	case '\0':
65
		if(ScribbleDebug)fprint(2, "(case '\\0')\n");
66
		break;
67
	case 'A':	/* space */
68
		rune = ' ';
69
		if(ScribbleDebug)fprint(2, "(case A) character = ' %C' (0x%x)\n", rune, rune);
70
		break;
71
	case 'B':	/* backspace */
72
		rune = '\b';
73
		if(ScribbleDebug)fprint(2, "(case B) character = \\b (0x%x)\n", rune);
74
		break;
75
	case 'N': /* numlock */
76
		if(ScribbleDebug)fprint(2, "(case N)\n");
77
		if (s->curCharSet == CS_DIGITS) {
78
			s->curCharSet = CS_LETTERS;
79
		} else {
80
			s->curCharSet = CS_DIGITS;
81
		}
82
		s->tmpShift = 0;
83
		s->puncShift = 0;
84
		s->ctrlShift = 0;
85
		break;
86
	case 'P': /* usually puncshift, but we'll make it CTRL */
87
		if(ScribbleDebug)fprint(2, "(case P)\n");
88
		s->ctrlShift = !s->ctrlShift;
89
		s->tmpShift = 0;
90
		s->puncShift = 0;
91
		break;
92
	case 'R':	/* newline */
93
		rune = '\n';
94
		if(ScribbleDebug)fprint(2, "(case R) character = \\n (0x%x)\n", rune);
95
		break;
96
	case 'S': /* shift */
97
		if(ScribbleDebug)fprint(2, "(case S)\n");
98
		s->puncShift = 0;
99
		s->ctrlShift = 0;
100
		if (s->capsLock) {
101
			s->capsLock = 0;
102
			s->tmpShift = 0;
103
			break;
104
		}
105
		if (s->tmpShift == 0) {
106
			s->tmpShift++;
107
			break;
108
		}
109
		/* fall through */
110
	case 'L': /* caps lock */
111
		if(ScribbleDebug)fprint(2, "(case L)\n");
112
		s->capsLock = !s->capsLock;
113
		break;
114
	case '.':	/* toggle punctuation mode */
115
		if (s->puncShift) {
116
			s->puncShift = 0;
117
		} else {
118
			s->puncShift = 1;
119
			s->ctrlShift = 0;
120
			s->tmpShift = 0;
121
			return rune;
122
		}		  	
123
		rune = '.';
124
		if(0)fprint(2, "(case .) character = %c (0x%x)\n", rune, rune);
125
		break;
126
	default:
127
		if ('A' <= c && c <= 'Z') {
128
			if(ScribbleDebug)fprint(2, "(bad case?) character = %c (0x%x)\n", c, c);
129
			return rune;
130
		}
131
		rune = c;
132
		if (s->ctrlShift) 
133
		{
134
			if (c < 'a' || 'z' < c)
135
			{
136
				if(ScribbleDebug)fprint(2, "(default) character = %c (0x%x)\n", rune, rune);
137
				return rune;
138
			}
139
			rune = rune & 0x1f;
140
		} else if ((s->capsLock && !s->tmpShift) || 
141
				 (!s->capsLock && s->tmpShift)) 
142
		{
143
			if (rune < 0xff)
144
				rune = toupper(rune);
145
		} 
146
		s->tmpShift = 0;
147
		s->puncShift = 0;
148
		s->ctrlShift = 0;
149
		if(ScribbleDebug)fprint(2, "(default) character = %c (0x%x)\n", rune, rune);
150
	}
151
	return rune;
152
}
153
 
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.
162
 */
163
 
164
static int
165
graffiti_load_recognizers(struct graffiti *pg)
166
{
167
	bool usingDefault;
168
	char* homedir;
169
	int i;
170
	rec_fn *fns;
171
 
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);
179
			return 0;
180
		}
181
		if ((* (int *)(pg->rec[i])) != 0xfeed) {
182
			fprint(2,"Error in recognizer_magic.");
183
			return 0;
184
		}
185
	}
186
 
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);
191
		usingDefault = true;
192
	} else {
193
		if(0)fprint(2, "homedir = %s\n", homedir);
194
		snprint(pg->cldir, sizeof pg->cldir, "%s/%s", homedir, CLASSIFIER_DIR);
195
		usingDefault = false;
196
	}
197
 
198
	/* ...then load the classifiers... */
199
	for (i = 0; i < NUM_RECS; i++) {
200
		int rec_return;
201
		char *s;
202
 
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]);
210
		}
211
		if (rec_return == -1) {
212
			fprint(2, "Unable to load default classifier file %s.\nOriginal error: %s\n",
213
				cl_name[i], 
214
				(s = recognizer_error(pg->rec[i])) ? s : "(none)");
215
			return 0;
216
		}
217
	}
218
 
219
	/* We have recognizers and classifiers now.   */
220
	/* Get the vector of LIextension functions..     */
221
	fns = recognizer_get_extension_functions(pg->rec[CS_LETTERS]);
222
	if (fns == nil) {
223
		fprint(2, "LI Recognizer Training:No extension functions!");
224
		return 0;
225
	}
226
 
227
	/* ... and make sure the training & get-classes functions are okay. */
228
	if( (pg->rec_train = (li_recognizer_train)fns[LI_TRAIN]) == nil ) {
229
		fprint(2,
230
			"LI Recognizer Training:li_recognizer_train() not found!");
231
		if (fns != nil) {
232
			free(fns);
233
		}
234
		return 0;
235
	}
236
 
237
	if( (pg->rec_getClasses = (li_recognizer_getClasses)fns[LI_GET_CLASSES]) == nil ) {
238
		fprint(2,
239
			"LI Recognizer Training:li_recognizer_getClasses() not found!");
240
		if (fns != nil) {
241
			free(fns);
242
		}
243
		return 0;
244
	}
245
	free(fns);
246
	return 1;
247
}
248
 
249
Scribble *
250
scribblealloc(void)
251
{
252
	Scribble *s;
253
 
254
	s = mallocz(sizeof(Scribble), 1);
255
	if (s == nil)
256
		sysfatal("Initialize: %r");
257
	s->curCharSet = CS_LETTERS;
258
 
259
	s->graf = mallocz(sizeof(struct graffiti), 1);
260
	if (s->graf == nil)
261
		sysfatal("Initialize: %r");
262
 
263
	graffiti_load_recognizers(s->graf);
264
 
265
	return s;
266
}