Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/* 
2
 *  hre_api.c:        Implementation of HRE API
3
 *  Author:           James &
4
 *  Created On:       Wed Dec  9 13:49:14 1992
5
 *  Last Modified By: James Kempf
6
 *  Last Modified On: Fri Sep 23 13:49:04 1994
7
 *  Update Count:     137
8
 *  Copyright (c) 1994 by Sun Microsystems Computer Company
9
 *  All rights reserved.
10
 *  
11
 *  Use and copying of this software and preparation of 
12
 *  derivative works based upon this software are permitted.
13
 *  Any distribution of this software or derivative works
14
 *  must comply with all applicable United States export control
15
 *  laws.
16
 *
17
 *  This software is made available as is, and Sun Microsystems
18
 *  Computer Company makes no warranty about the software, its
19
 *  performance, or its conformity to any specification
20
 */
21
 
22
#include <u.h>
23
#include <libc.h>
24
#include <draw.h>
25
#include <scribble.h>
26
 
27
#include "scribbleimpl.h"
28
#include "hre_internal.h"
29
 
30
/* ari -- prototype for rii function */
31
recognizer __recognizer_internal_initialize(rec_info* ri);
32
 
33
/*Version number of API.*/
34
 
35
char* REC_VERSION = "2.0";
36
 
37
/*Domain name for internationalized text.*/
38
 
39
#define INTL_DOMAIN "recognition_manager"
40
 
41
/* XXX -- Intl Hack -- Jay & Ari */
42
#define	dgettext(domain, msg)	(msg)
43
#define	bindtextdomain(dirname,	domain)
44
 
45
/*
46
 * These magic numbers are used to ensure the integrity of the
47
 * recognizer structure.
48
*/
49
 
50
 
51
#define REC_MAGIC       0xfeed
52
#define REC_END_MAGIC   0xbeef
53
 
54
/*Check the recognizer for validity*/
55
 
56
#define RI_CHECK_MAGIC(rec) \
57
  ( (rec != nil) && \
58
    (((recognizer)rec)->recognizer_magic == REC_MAGIC) && \
59
   (((recognizer)rec)->recognizer_end_magic == REC_END_MAGIC) &&\
60
   (((recognizer)rec)->recognizer_version == REC_VERSION) )
61
 
62
/*The name of the initialization & finalization functions.*/
63
 
64
/* static char rii_name[] = "__recognizer_internal_initialize";
65
static char rif_name[] = "__recognizer_internal_finalize";  */
66
 
67
/*User home directory for recognizer info.*/
68
/* ari -- changed USERRECHOME from ".recognizers" */
69
#define HOME "HOME"
70
#define USERRECHOME ".classifiers"
71
 
72
/*Local functions*/
73
 
74
static char* shared_library_name(char* directory,char* locale,char* name);
75
static rec_info* make_rec_info(char* directory,char* name,char** subset);
76
static void delete_rec_info(rec_info* ri);
77
static int check_for_user_home(void);
78
static void intl_initialize(void);
79
 
80
static void cleanup_rec_element(rec_element* re,bool delete_points_p);
81
 
82
/*The last error.*/
83
 
84
static char* the_last_error = nil;
85
 
86
static char *safe_malloc (int nbytes)
87
{
88
  char *res = malloc(nbytes);
89
  if (res == nil) {
90
    sysfatal("malloc failure");
91
  }
92
  return (res);
93
}
94
 
95
 
96
/*
97
 * Implementation of API functions
98
*/
99
 
100
/*
101
 * recognizer_load - Load the recognizer matching the rec_info struct.
102
 * If name is not null, then load the recognizer having that name. Returns
103
 * the recognizer object, or null if it can't load the recognizer, and
104
 * sets errno to indicate why.
105
*/
106
 
107
recognizer 
108
recognizer_load(char* directory, char* name, char** subset)
109
{
110
    recognizer	rec;				/*the recognizer*/
111
    rec_info*	rinf;				/*rec_info for recognizer information*/
112
    static bool	intl_init = false;	/*true if recog. manager initted.*/
113
 
114
    if( intl_init == false ) {
115
      intl_init = true;
116
      intl_initialize();
117
    }
118
 
119
    /*The name takes precedence.*/
120
    rinf = make_rec_info(directory, name, subset);
121
    if (rinf == nil) {
122
	the_last_error = 
123
	  dgettext(INTL_DOMAIN,
124
		   "Ran out of memory during prelinking initialization.");
125
	return((recognizer)nil);
126
    } 
127
/* fprint(2, "Got past make_rec_info.\n"); */
128
 
129
    /*Let recognition code create recognizer and initialize*/
130
    rec = __recognizer_internal_initialize(rinf);
131
    if (rec == nil) {
132
	return((recognizer)nil);
133
    }
134
/* fprint(2, "Did rii.\n"); */
135
    /*Check whether it's been correctly initialized*/
136
 
137
    if( rec->recognizer_load_state == nil ||
138
        rec->recognizer_save_state == nil ||
139
        rec->recognizer_load_dictionary == nil ||
140
        rec->recognizer_save_dictionary == nil ||
141
        rec->recognizer_free_dictionary == nil ||
142
        rec->recognizer_add_to_dictionary == nil ||
143
        rec->recognizer_delete_from_dictionary == nil ||
144
        rec->recognizer_error == nil ||
145
        rec->recognizer_set_context == nil ||
146
        rec->recognizer_get_context == nil ||
147
        rec->recognizer_clear == nil ||
148
        rec->recognizer_get_buffer == nil ||
149
        rec->recognizer_set_buffer == nil ||
150
        rec->recognizer_translate == nil ||
151
        rec->recognizer_get_extension_functions == nil ||
152
        rec->recognizer_get_gesture_names == nil ||
153
        rec->recognizer_set_gesture_action == nil
154
       ) {
155
 
156
	recognizer_unload(rec);
157
/* fprint(2, "Unloading b/c null function pointer.\n"); */
158
	the_last_error = 
159
	  dgettext(INTL_DOMAIN,
160
		   "One or more recognizer function pointers is nil.");
161
	return((recognizer)nil);
162
    }
163
 
164
 
165
    /*Set the rec_info structure.*/
166
 
167
    rec->recognizer_info = rinf;
168
 
169
    /*Check whether home directory is there for recognizer info.*/
170
 
171
/*
172
 *  ari -- don't bother.  We're not going to load from each user's
173
 *  home directory at this point.  Instead, we'll use a stupid
174
 *  little a-b-c file because it loads FAST.
175
 *
176
 *    if( check_for_user_home() < 0 ) {
177
 *	recognizer_unload(rec);
178
 *	return((recognizer)nil);
179
 *   }
180
 */
181
    /*We got it!*/
182
/* fprint(2, "Done.\n"); */
183
 
184
    return(rec);
185
}
186
 
187
/*
188
 * recognizer_unload - Unload the recognizer.
189
*/
190
 
191
int
192
recognizer_unload(recognizer rec)
193
{
194
    /*Make sure magic numbers right.*/
195
 
196
	if( !RI_CHECK_MAGIC(rec) ) {
197
		the_last_error = dgettext(INTL_DOMAIN,"Bad recognizer object.");
198
		return(-1);
199
	}
200
 
201
	return __recognizer_internal_finalize(rec);
202
}
203
 
204
/*
205
 * recognizer_load_state-Get any recognizer state associated with name
206
 * in dir. Note that name may not be simple file name, since
207
 * there may be more than one file involved. Return 0 if successful,
208
 * -1 if not.
209
*/
210
 
211
int recognizer_load_state(recognizer rec, char* dir, char* name)
212
{
213
    /*Make sure magic numbers right.*/
214
 
215
    if( !RI_CHECK_MAGIC(rec) ) {
216
		the_last_error = dgettext(INTL_DOMAIN,"Bad recognizer object.");
217
		return(-1);
218
    }
219
 
220
    /*Do the function.*/
221
 
222
    return(rec->recognizer_load_state(rec, dir, name));
223
}
224
 
225
/*
226
 * recognizer_save_state-Save any recognizer state to name
227
 * in dir. Note that name may not be a simple file name, since
228
 * there may be more than one file involved. Return 0 if successful,
229
 * -1 if not.
230
*/
231
 
232
int recognizer_save_state(recognizer rec,char* dir,char* name)
233
{
234
    /*Make sure magic numbers right.*/
235
 
236
    if( !RI_CHECK_MAGIC(rec) ) {
237
	the_last_error = dgettext(INTL_DOMAIN,"Bad recognizer object.");
238
	return(-1);
239
    }
240
 
241
    /*Do the function.*/
242
 
243
    return(rec->recognizer_save_state(rec,dir,name));
244
}
245
 
246
/*
247
 * recognizer_load_dictionary-Load dictionary, return pointer
248
 * to it, or nil if error.
249
*/
250
 
251
wordset recognizer_load_dictionary(recognizer rec,char* dir,char* name)
252
{
253
    /*Make sure magic numbers right.*/
254
 
255
    if( !RI_CHECK_MAGIC(rec) ) {
256
	the_last_error = dgettext(INTL_DOMAIN,"Bad recognizer object.");
257
	return(nil);
258
    }
259
 
260
    /*Do the function.*/
261
 
262
    return(rec->recognizer_load_dictionary(rec,dir,name));
263
}
264
 
265
/*
266
 * recognizer_save_dictionary-Save the  dictionary to the file, return 0 if
267
 * OK, -1 if error.
268
*/
269
 
270
int recognizer_save_dictionary(recognizer rec,char* dir,char* name,wordset dict)
271
{
272
    /*Make sure magic numbers right.*/
273
 
274
    if( !RI_CHECK_MAGIC(rec) ) {
275
	the_last_error = dgettext(INTL_DOMAIN,"Bad recognizer object.");
276
	return(-1);
277
    }
278
 
279
    /*Do the function.*/
280
 
281
    return(rec->recognizer_save_dictionary(rec,dir,name,dict));
282
}
283
 
284
/*
285
 * recognizer_free_dictionary-Free the dictionary, return 0 if
286
 * OK, -1 if error.
287
*/
288
 
289
int recognizer_free_dictionary(recognizer rec,wordset dict)
290
{
291
    /*Make sure magic numbers right.*/
292
 
293
    if( !RI_CHECK_MAGIC(rec) ) {
294
	the_last_error = dgettext(INTL_DOMAIN,"Bad recognizer object.");
295
	return(-1);
296
    }
297
 
298
    /*Do the function.*/
299
 
300
    return(rec->recognizer_free_dictionary(rec,dict));
301
}
302
 
303
/*
304
 * recognizer_add_to_dictionary-Add word to the dictionary,
305
 * return 0 if OK, -1 if error.
306
*/
307
 
308
 
309
int recognizer_add_to_dictionary(recognizer rec,letterset* word,wordset dict)
310
{
311
    /*Make sure magic numbers right.*/
312
 
313
    if( !RI_CHECK_MAGIC(rec) ) {
314
	the_last_error = dgettext(INTL_DOMAIN,"Bad recognizer object.");
315
	return(-1);
316
    }
317
 
318
    /*Do the function.*/
319
 
320
    return(rec->recognizer_add_to_dictionary(rec,word,dict));
321
}
322
 
323
/*
324
 * recognizer_delete_from_dictionary-Delete word from the dictionary,
325
 * return 0 if OK, -1 if error.
326
*/
327
 
328
int 
329
recognizer_delete_from_dictionary(recognizer rec,letterset* word,wordset dict)
330
{
331
    /*Make sure magic numbers right.*/
332
 
333
    if( !RI_CHECK_MAGIC(rec) ) {
334
	the_last_error = dgettext(INTL_DOMAIN,"Bad recognizer object.");
335
	return(-1);
336
    }
337
 
338
    /*Do the function.*/
339
 
340
    return(rec->recognizer_delete_from_dictionary(rec,word,dict));
341
}
342
 
343
/*
344
 * recognizer_get_info-Get a pointers to the rec_info
345
 * giving the locales and subsets supported by the recognizer
346
 * and the shared library pathname.
347
*/
348
 
349
const rec_info*
350
recognizer_get_info(recognizer rec)
351
{
352
    /*Make sure magic numbers right.*/
353
 
354
    if( !RI_CHECK_MAGIC(rec) ) {
355
	the_last_error = dgettext(INTL_DOMAIN,"Bad recognizer object.");
356
	return((rec_info*)nil);
357
    }
358
 
359
    /*Return the rec_info object.*/
360
 
361
    return(rec->recognizer_info);
362
}
363
 
364
/*
365
 * recognizer_manager_version-Return the version number string of the
366
 * recognition manager.
367
*/
368
 
369
const char* recognizer_manager_version(recognizer rec)
370
{
371
    /*Make sure magic numbers right.*/
372
 
373
    if( !RI_CHECK_MAGIC(rec) ) {
374
	the_last_error = dgettext(INTL_DOMAIN,"Bad recognizer object.");
375
	return(nil);
376
    }
377
 
378
    return(rec->recognizer_version);
379
 
380
}
381
/*
382
 * recognizer_error-Return the last error message, or nil if none.
383
*/
384
 
385
char* recognizer_error(recognizer rec)
386
{
387
 
388
    /*Make sure magic numbers right and function there.*/
389
 
390
    if( !RI_CHECK_MAGIC(rec) && the_last_error == nil ) {
391
      return(dgettext(INTL_DOMAIN,"Bad recognizer object."));
392
 
393
    } else if( the_last_error != nil ) {
394
      char* error = the_last_error;
395
 
396
      the_last_error = nil;
397
      return(error);
398
    }
399
 
400
    /*Do the function.*/
401
 
402
    return(rec->recognizer_error(rec));
403
}
404
 
405
/*
406
 * recognizer_set_context-Set the recognition context for translation.
407
 * Return 0 if successful, -1 if error.
408
*/
409
 
410
int recognizer_set_context(recognizer rec,rc* rec_xt)
411
{
412
 
413
    /*Make sure magic numbers right.*/
414
 
415
    if( !RI_CHECK_MAGIC(rec) ) {
416
	the_last_error = dgettext(INTL_DOMAIN,"Bad recognizer object.");
417
	return(-1);
418
    }
419
 
420
    /*Do the function.*/
421
 
422
    return(rec->recognizer_set_context(rec,rec_xt));
423
}
424
 
425
/* 
426
 * recognzier_get_context-Get the recognition context for translation.
427
 * If none or error, return nil.
428
*/
429
 
430
rc* recognizer_get_context(recognizer rec)
431
{
432
 
433
    /*Make sure magic numbers right.*/
434
 
435
    if( !RI_CHECK_MAGIC(rec) ) {
436
	the_last_error = dgettext(INTL_DOMAIN,"Bad recognizer object.");
437
	return(nil);
438
    }
439
 
440
    /*Do the function.*/
441
 
442
    return(rec->recognizer_get_context(rec));
443
}
444
 
445
/*
446
 * recognizer_clear-Clear buffer and recognition context.
447
 * Return 0 if success, else -1.
448
*/
449
 
450
int recognizer_clear(recognizer rec,bool delete_points_p)
451
{
452
 
453
    /*Make sure magic numbers right.*/
454
 
455
    if( !RI_CHECK_MAGIC(rec) ) {
456
	the_last_error = dgettext(INTL_DOMAIN,"Bad recognizer object.");
457
	return(-1);
458
    }
459
 
460
    /*Do the function.*/
461
 
462
    return(rec->recognizer_clear(rec,delete_points_p));
463
}
464
 
465
/*recognizer_get_buffer-Get stroke buffer. Return 0 if success, else -1.*/
466
 
467
 
468
int recognizer_get_buffer(recognizer rec, uint* nstrokes,Stroke** strokes)
469
{
470
 
471
    /*Make sure magic numbers right.*/
472
 
473
    if( !RI_CHECK_MAGIC(rec) ) {
474
	the_last_error = dgettext(INTL_DOMAIN,"Bad recognizer object.");
475
	return(-1);
476
    }
477
 
478
    /*Do the function.*/
479
 
480
    return(rec->recognizer_get_buffer(rec,nstrokes,strokes));
481
 
482
}
483
 
484
/*
485
 * recognizer_set_buffer-Set stroke buffer to arg. Return 0 if success, else 
486
 * return -1.
487
*/
488
 
489
int recognizer_set_buffer(recognizer rec,uint nstrokes,Stroke* strokes)
490
{
491
 
492
    /*Make sure magic numbers right.*/
493
 
494
    if( !RI_CHECK_MAGIC(rec) ) {
495
	the_last_error = dgettext(INTL_DOMAIN,"Bad recognizer object.");
496
	return(-1);
497
    }
498
 
499
    /*Do the function.*/
500
 
501
    return(rec->recognizer_set_buffer(rec,nstrokes,strokes));
502
 
503
}
504
 
505
/*
506
 * recognizer_translate-Translate the strokes in the current context, including
507
 * buffered strokes. If nstrokes == 0 or strokes == nil, return 
508
 * translation of stroke buffer.
509
*/
510
 
511
int recognizer_translate(recognizer rec,
512
			 uint nstrokes,
513
			 Stroke* strokes,
514
			 bool correlate_p,
515
			 int* nret,
516
			 rec_alternative** ret)
517
{
518
    int retval;
519
    char msg[80];
520
    /*Make sure magic numbers right.*/
521
 
522
    if( !RI_CHECK_MAGIC(rec) ) {
523
	the_last_error = dgettext(INTL_DOMAIN, msg);
524
	return(-1);
525
    }
526
 
527
/* ari */
528
/*    {
529
 *      uint i;
530
 *      Stroke ari_pstr;
531
 *      pen_point* ari_pts;
532
 *      int ari;
533
 *      for (i = 0; i < nstrokes; i++) {
534
 *	ari_pstr = strokes[i];
535
 *	ari_pts = ari_pstr.ps_pts;
536
 *	fprint(2, "\nrecognizer_translate: ari_pts = %ld, sizeof(Time) = %d, sizeof(ari_pts[0] = %d, %d points are...\n", ari_pts, sizeof(Time), sizeof(ari_pts[0]), ari_pstr.ps_npts);
537
 *	for (ari = 0; ari < ari_pstr.ps_npts; ari++)
538
 *	   fprint(2, "%ld -- (%d, %d)  ", ari_pts[ari], ari_pts[ari].x, ari_pts[ari].y);
539
 *      }
540
 *    }     
541
*/
542
    /*Do the function.*/
543
/* ari -- this is calling cmu_recognizer_translate */
544
    retval = rec->recognizer_translate(rec,
545
				     nstrokes,
546
				     strokes,
547
				     correlate_p,
548
				     nret,
549
				     ret);
550
    return (retval);
551
}
552
 
553
 
554
/*
555
 * recognizer_get_extension_functions-Return a null terminated array
556
 * of functions providing extended functionality. Their interfaces
557
 * will change depending on the recognizer.
558
*/
559
 
560
rec_fn* recognizer_get_extension_functions(recognizer rec)
561
{
562
    /*Make sure magic numbers right.*/
563
 
564
    if( !RI_CHECK_MAGIC(rec) ) {
565
	the_last_error = dgettext(INTL_DOMAIN,"Bad recognizer object.");
566
	return((rec_fn*)nil);
567
    }
568
 
569
    /*Do the function.*/
570
 
571
    return(rec->recognizer_get_extension_functions(rec));
572
}
573
 
574
 
575
/*
576
 * recognizer_get_gesture_names - Return a null terminated array of
577
 * gesture name strings.
578
*/
579
 
580
char**
581
recognizer_get_gesture_names(recognizer rec)
582
{
583
    /*Make sure magic numbers right.*/
584
 
585
    if( !RI_CHECK_MAGIC(rec) ) {
586
	the_last_error = dgettext(INTL_DOMAIN,"Bad recognizer object.");
587
	return(nil);
588
    }
589
 
590
    /*Do the function.*/
591
 
592
    return(rec->recognizer_get_gesture_names(rec));
593
}
594
 
595
/*
596
 * recognizer_set_gesture_action-Set the action function for the gesture.
597
*/
598
 
599
xgesture 
600
recognizer_train_gestures(recognizer rec,char* name,xgesture fn,void* wsinfo)
601
{
602
    /*Make sure magic numbers right.*/
603
 
604
    if( !RI_CHECK_MAGIC(rec) ) {
605
	the_last_error = dgettext(INTL_DOMAIN,"Bad recognizer object.");
606
	return((xgesture)-1);
607
    }
608
 
609
    /*Do the function.*/
610
 
611
    return(rec->recognizer_set_gesture_action(rec,name,fn,wsinfo));
612
}
613
 
614
/*
615
 * Local functions.
616
*/
617
 
618
/*
619
 * shared_library_name-Get the full pathname to the shared library,
620
 *    based on the recognizer name and the environment.
621
*/
622
 
623
 
624
static char* shared_library_name(char* directory,char* locale,char* name)
625
{
626
    char* ret;
627
    int len = strlen(name);
628
 
629
    /*If directory is there, it takes precedence.*/
630
 
631
    if( directory != nil ) {
632
		ret = (char*)safe_malloc(strlen(directory) + len + 2);
633
		strcpy(ret,directory);
634
		strcat(ret,"/");
635
		strcat(ret,name);
636
    } else {
637
		char* dir;
638
 
639
		/*First try the environment variable.*/
640
 
641
		if( (dir = getenv(RECHOME)) == nil ) {
642
		    dir = "REC_DEFAULT_HOME_DIR";
643
 
644
		  }
645
 
646
		ret = (char*)safe_malloc(strlen(dir) + strlen(locale) + len + 3);
647
		/*Form the pathname.*/
648
		strcpy(ret,dir);
649
		strcat(ret,"/");
650
		strcat(ret,locale);
651
		strcat(ret,"/");
652
		strcat(ret,name);
653
	}
654
 
655
    return(ret);
656
}
657
 
658
/*
659
 * intl_initialize-Initialize the internationaliztion of messages for
660
 * the recognition manager.
661
*/
662
 
663
static void intl_initialize(void)
664
{
665
	char* dirname;
666
 
667
	/*Get recognizer home directory name from environment.*/
668
 
669
	if( (dirname = getenv(RECHOME)) == nil ) {
670
		dirname = "REC_DEFAULT_HOME_DIR";
671
	}
672
 
673
	/*Bind the text domain.*/
674
	USED(dirname);
675
	bindtextdomain(dirname, INTL_DOMAIN);
676
}
677
 
678
 
679
/*make_rec_info-Create a rec_info structure*/
680
 
681
static rec_info* make_rec_info(char*, char*, char** subset)
682
{
683
    int i,len;
684
    rec_info* ri;
685
    char* locale;
686
 
687
    ri = (rec_info*)safe_malloc(sizeof(rec_info));
688
    ri->ri_locale = nil;
689
    ri->ri_name = nil;
690
    ri->ri_subset = nil;
691
 
692
    /*Get locale*/
693
 
694
    if( (locale = getenv(LANG)) == nil ) {
695
		locale = strdup(REC_DEFAULT_LOCALE);
696
    }
697
 
698
    if( (ri->ri_locale = strdup(locale)) == nil ) {
699
		delete_rec_info(ri);
700
		return(nil);
701
    }
702
 
703
    /*Get shared library pathname.*/
704
 
705
    /*Initialize the subset information.*/
706
 
707
    if( subset != nil ) {
708
 
709
	/*Count the subset strings.*/
710
 
711
	for( len = 1; subset[len] != nil; len++ ) ;
712
 
713
	/*Copy the subset strings.*/
714
 
715
	ri->ri_subset = (char**)safe_malloc((len +1)*sizeof(char*));
716
 
717
	for( i = 0; i < len; i++ ) {
718
	    if( subset[i] != nil ) {
719
		if( (ri->ri_subset[i] = strdup(subset[i])) == nil ) {
720
		    delete_rec_info(ri);
721
		    return(nil);
722
		}
723
	    } else {
724
		ri->ri_subset[i] = subset[i];
725
	    }
726
	}
727
 
728
	ri->ri_subset[i] = nil;
729
 
730
    } else {
731
 
732
	ri->ri_subset = nil;
733
    }
734
 
735
    return(ri);
736
}
737
 
738
static void delete_rec_info(rec_info* ri)
739
{
740
    if( ri != nil ) {
741
	if( ri->ri_locale != nil ) {
742
	    free(ri->ri_locale);
743
	}
744
/*
745
 *	if( ri->ri_name != nil ) {
746
 *	    free(ri->ri_name);
747
 *	}
748
 */
749
	if( ri->ri_subset != nil ) {
750
	    int i;
751
	    for( i = 0; ri->ri_subset[i] != nil; i++) {
752
		free(ri->ri_subset[i]);
753
	    }
754
	    free(ri->ri_subset);
755
	}
756
	free(ri);
757
    }
758
}
759
 
760
/*check_for_user_home-Check whether USERRECHOME has been created.*/
761
 
762
static int check_for_user_home()
763
{
764
	char* homedir = getenv(HOME);
765
	char* rechome;
766
	Dir *dir;
767
 
768
	if( homedir == nil ) {
769
		the_last_error = "Home environment variable HOME not set.";
770
		return(-1);
771
	}
772
 
773
    rechome = (char*)safe_malloc(strlen(homedir) + strlen(USERRECHOME) + 2);
774
 
775
    /*Form name.*/
776
 
777
    strcpy(rechome,homedir);
778
    strcat(rechome,"/");
779
    strcat(rechome,USERRECHOME);
780
 
781
    /*Create directory.*/
782
 
783
    dir = dirstat(rechome);
784
    if (dir != nil) {
785
		if (dir->mode & DMDIR) {
786
			free(dir);
787
			free(rechome);
788
			return 0;
789
		}
790
		free(dir);
791
	} else {
792
		int fd;
793
		if ((fd = create(rechome, OREAD, DMDIR|0755)) >= 0) {
794
			close(fd);
795
    		free(rechome);
796
    		return(0);
797
		}
798
    }
799
	free(rechome);
800
	return(-1);
801
}
802
 
803
/*
804
 * Constructor functions for making structures.
805
 *
806
 *    The general philosophy here is that we control all memory
807
 *    in connected data structures, *except* for pen_point arrays.
808
 *    There are likely to be lots and lots of points, they are likely
809
 *    to come from the window system; so if we wanted to control them,
810
 *    we would have to copy which would be slow. We require the client
811
 *    to deal with them directly, or the client can give us permission
812
 *    to delete them.
813
*/
814
 
815
/*
816
 * recognizer
817
*/
818
 
819
 
820
recognizer make_recognizer(rec_info* rif)
821
{
822
    recognizer rec;
823
 
824
    /*Allocate it.*/
825
 
826
    rec = (recognizer)safe_malloc(sizeof(*rec));
827
    rec->recognizer_magic = REC_MAGIC;
828
    rec->recognizer_version = REC_VERSION;
829
    rec->recognizer_info = rif;
830
    rec->recognizer_specific = nil;
831
    rec->recognizer_end_magic = REC_END_MAGIC;
832
    rec->recognizer_load_state = nil;
833
    rec->recognizer_save_state = nil;
834
    rec->recognizer_load_dictionary = nil;
835
    rec->recognizer_save_dictionary = nil;
836
    rec->recognizer_free_dictionary = nil;
837
    rec->recognizer_add_to_dictionary = nil;
838
    rec->recognizer_delete_from_dictionary = nil;
839
    rec->recognizer_error = nil;
840
    rec->recognizer_set_context = nil;
841
    rec->recognizer_get_context = nil;
842
    rec->recognizer_clear = nil;
843
    rec->recognizer_get_buffer = nil;
844
    rec->recognizer_set_buffer = nil;
845
    rec->recognizer_translate = nil;
846
    rec->recognizer_get_extension_functions = nil;
847
    rec->recognizer_get_gesture_names = nil;
848
    rec->recognizer_set_gesture_action = nil;
849
    return(rec);
850
}
851
 
852
void delete_recognizer(recognizer rec)
853
{
854
 
855
    if( rec != nil ) {
856
	if( rec->recognizer_info != nil ) {
857
	    delete_rec_info(rec->recognizer_info);
858
	}
859
	free(rec);
860
    }
861
}
862
 
863
/*
864
 * rec_alternative
865
*/
866
 
867
rec_alternative* make_rec_alternative_array(uint size)
868
{
869
    int i;
870
    rec_alternative* ri;
871
 
872
    ri = (rec_alternative*) safe_malloc(size * sizeof(rec_alternative));
873
 
874
    for( i = 0; i < size; i++ ) {
875
        ri[i].ra_elem.re_type = REC_NONE;
876
	ri[i].ra_elem.re_result.aval = nil;
877
	ri[i].ra_elem.re_conf = 0;
878
	ri[i].ra_nalter = 0;
879
	ri[i].ra_next = nil;
880
    }
881
 
882
    return(ri);    
883
}
884
 
885
rec_alternative*
886
  initialize_rec_alternative(rec_alternative* ra, uint nelm)
887
{
888
  if( ra != nil ) {
889
    if( (ra->ra_next = make_rec_alternative_array(nelm)) == nil ) {
890
      return(nil);
891
    }
892
 
893
    ra->ra_nalter = nelm;
894
  }
895
 
896
  return(ra);
897
}
898
 
899
void delete_rec_alternative_array(uint nalter,
900
				  rec_alternative* ra,
901
				  bool delete_points_p)
902
{
903
  int i;
904
 
905
    if( ra != nil ) {
906
 
907
      for( i = 0; i < nalter; i++ ) {
908
	cleanup_rec_element(&ra[i].ra_elem,delete_points_p);
909
 
910
	/*Now do the next one down the line.*/
911
 
912
	if( ra[i].ra_nalter > 0 ) {
913
	  delete_rec_alternative_array(ra[i].ra_nalter,
914
				       ra[i].ra_next,
915
				       delete_points_p);
916
        }
917
      }
918
 
919
      free(ra);
920
    }
921
}
922
 
923
 
924
/*initialize_rec_element-Initialize a recognition element.*/
925
 
926
rec_element*
927
initialize_rec_element(rec_element* re,
928
		       char type,
929
		       uint size,
930
		       void* trans,
931
		       rec_confidence conf)
932
{
933
    if( re != nil ) {
934
 
935
	re->re_type = type;
936
	re->re_conf = conf;
937
	re->re_result.aval = nil;
938
 
939
	switch (type) {
940
 
941
	  case REC_GESTURE:
942
	    if( size > 0 && trans != nil ) {
943
		re->re_result.gval = 
944
		     (gesture*)safe_malloc(sizeof(gesture));
945
		memcpy((void*)re->re_result.gval,trans,sizeof(gesture));
946
	    }
947
	    break;
948
 
949
	  case REC_ASCII:
950
	  case REC_VAR:
951
	  case REC_OTHER:
952
	    if( size > 0 && trans != nil ) {
953
		re->re_result.aval = 
954
		     (char*)safe_malloc((size+1)*sizeof(char));
955
		memcpy((void*)re->re_result.aval,trans,size*sizeof(char));
956
		re->re_result.aval[size] = '\000';
957
	    }
958
	    break;
959
 
960
	  case REC_WCHAR:
961
	    if( size > 0 && trans != nil ) {
962
		re->re_result.wval = 
963
		     (wchar_t*)safe_malloc((size+1)*sizeof(wchar_t));
964
		memcpy((void*)re->re_result.wval,trans,size*sizeof(wchar_t));
965
		re->re_result.wval[size] = '\000';
966
	    }
967
	    break;
968
 
969
	  case REC_CORR:
970
	    if( size > 0 && trans != nil ) {
971
	      re->re_result.rcval =
972
		   (rec_correlation*)safe_malloc(sizeof(rec_correlation));
973
	      memcpy((void*)re->re_result.rcval,
974
		     trans,
975
		     sizeof(rec_correlation));
976
	    }
977
	    break;
978
 
979
	  default:
980
	    return(nil);
981
	}
982
 
983
    }
984
 
985
    return(re);
986
}
987
 
988
static void cleanup_rec_element(rec_element* re,bool delete_points_p)
989
{
990
  switch(re->re_type) {
991
 
992
  case REC_NONE:
993
    break;
994
 
995
  case REC_ASCII:
996
  case REC_VAR:
997
  case REC_WCHAR:
998
  case REC_OTHER:
999
    free(re->re_result.aval);
1000
    break;
1001
 
1002
  case REC_GESTURE:
1003
    delete_gesture_array(1,re->re_result.gval,true);
1004
    break;
1005
 
1006
  case REC_CORR:
1007
    delete_rec_correlation(re->re_result.rcval,
1008
			   delete_points_p);
1009
    break;
1010
 
1011
  }
1012
 
1013
}
1014
 
1015
/*
1016
 * rec_correlation
1017
*/
1018
 
1019
 
1020
rec_correlation* 
1021
make_rec_correlation(char type,
1022
		     uint size,
1023
		     void* trans,
1024
		     rec_confidence conf,
1025
		     uint ps_size)
1026
{
1027
  rec_correlation* rc;
1028
 
1029
    rc = (rec_correlation*)safe_malloc(sizeof(rec_correlation));
1030
 
1031
    rc->ro_nstrokes = ps_size;
1032
 
1033
    /*First initialize element.*/
1034
 
1035
    if( initialize_rec_element(&(rc->ro_elem),
1036
			       type,
1037
			       size,
1038
			       trans,
1039
			       conf) == nil ) {
1040
      return(nil);
1041
    }
1042
 
1043
    if( (rc->ro_strokes = make_Stroke_array(ps_size)) == nil ) {
1044
      return(nil);
1045
    }
1046
 
1047
    rc->ro_start = (uint*)safe_malloc(ps_size * sizeof(int));
1048
    rc->ro_stop = (uint*)safe_malloc(ps_size * sizeof(int));
1049
    return(rc);
1050
}
1051
 
1052
void delete_rec_correlation(rec_correlation* rc,bool delete_points_p)
1053
{
1054
  if( rc != nil ) {
1055
 
1056
    cleanup_rec_element(&rc->ro_elem,delete_points_p);
1057
 
1058
    delete_Stroke_array(rc->ro_nstrokes,rc->ro_strokes,delete_points_p);
1059
 
1060
    if( rc->ro_start != nil ) {
1061
      free(rc->ro_start);
1062
    }
1063
 
1064
    if( rc->ro_stop != nil ) {
1065
      free(rc->ro_stop);
1066
    }
1067
 
1068
    free(rc);
1069
  }
1070
 
1071
}
1072
 
1073
 
1074
/*
1075
 * rec_fn
1076
*/
1077
 
1078
 
1079
rec_fn* make_rec_fn_array(uint size)
1080
{
1081
    rec_fn* ri = (rec_fn*)safe_malloc((size + 1) * sizeof(rec_fn));
1082
    int i;
1083
 
1084
    for( i = 0; i < size; i++ ) {
1085
	ri[i] = nil;
1086
    }
1087
 
1088
    ri[i] = nil;
1089
 
1090
    return(ri);
1091
}
1092
 
1093
void delete_rec_fn_array(rec_fn* rf)
1094
{
1095
    if( rf != nil ) {
1096
	free(rf);
1097
    }
1098
}
1099
 
1100
/*
1101
 * Stroke
1102
*/
1103
 
1104
 
1105
Stroke* make_Stroke_array(uint size)
1106
{
1107
    int i;
1108
    Stroke* ri;
1109
 
1110
    ri = (Stroke*) safe_malloc(size * sizeof(Stroke));
1111
    for( i = 0; i < size; i++ ) {
1112
	ri[i].npts = 0;
1113
	ri[i].pts = nil;
1114
    }
1115
 
1116
    return(ri);       
1117
}
1118
 
1119
Stroke* initialize_Stroke(Stroke* ps,
1120
				  uint npts,
1121
				  pen_point* pts)
1122
{
1123
  if( ps != nil ) {
1124
    ps->npts = npts;
1125
    ps->pts = pts;
1126
  }
1127
  return (ps);
1128
}
1129
 
1130
void delete_Stroke_array(uint size,Stroke* ps,bool delete_points_p)
1131
{
1132
  int i;
1133
 
1134
    if( ps != nil ) {
1135
 
1136
      for( i = 0; i < size; i++ ) {
1137
	    if( delete_points_p ) {
1138
		delete_pen_point_array(ps[i].pts);
1139
	    }
1140
      }
1141
 
1142
      free(ps);
1143
    }
1144
}
1145
 
1146
/*
1147
 * pen_point
1148
*/
1149
 
1150
void delete_pen_point_array(pen_point* pp)
1151
{
1152
    if( pp != nil ) {
1153
	free(pp);
1154
    }
1155
}
1156
 
1157
/*
1158
 * gesture 
1159
*/
1160
 
1161
gesture*
1162
make_gesture_array(uint size)
1163
{
1164
    return((gesture*)safe_malloc(size * sizeof(gesture)));
1165
}
1166
 
1167
gesture* initialize_gesture(gesture* g,
1168
			    char* name,
1169
			    uint nhs,
1170
			    pen_point* hspots,
1171
			    pen_rect bbox,
1172
			    xgesture fn,
1173
			    void* wsinfo)
1174
{
1175
	if( g != nil ) {
1176
 
1177
		/*We don't do points, 'cause they come from the window system.*/
1178
 
1179
		g->g_nhs = nhs;
1180
		g->g_hspots = hspots;
1181
 
1182
		g->g_name = strdup(name);
1183
 
1184
		g->g_bbox = bbox;
1185
		g->g_action = fn;
1186
		g->g_wsinfo = wsinfo;
1187
	}
1188
	return(g);
1189
}
1190
 
1191
void
1192
delete_gesture_array(uint size,gesture* ga,bool delete_points_p)
1193
{
1194
    int i;
1195
 
1196
    if( ga != nil ) {
1197
 
1198
      for( i = 0; i < size; i++ ) {
1199
 
1200
	free(ga[i].g_name);
1201
 
1202
	if( delete_points_p ) {
1203
	  delete_pen_point_array(ga[i].g_hspots);
1204
	}
1205
      }
1206
 
1207
      free(ga);
1208
    }
1209
}
1210
 
1211
/*
1212
 * copy fns for stroke buffer management.
1213
*/
1214
 
1215
static Stroke* 
1216
copy_Stroke(Stroke* ps1,Stroke* ps2)
1217
{
1218
  initialize_Stroke(ps1,
1219
			ps2->npts,
1220
			ps2->pts);
1221
  return(ps1);
1222
 
1223
}
1224
 
1225
Stroke*
1226
 copy_Stroke_array(uint nstrokes,
1227
		    Stroke* strokes)
1228
{
1229
  int i;
1230
  Stroke* ps = make_Stroke_array(nstrokes);
1231
 
1232
  if( ps != nil ) {
1233
 
1234
    for( i = 0; i < nstrokes; i++ ) {
1235
 
1236
      copy_Stroke(&ps[i],&strokes[i]);
1237
 
1238
    }
1239
 
1240
  }
1241
 
1242
  return(ps);
1243
}
1244
 
1245
uint*
1246
 copy_state_trans_array(uint ntrans,uint* trans)
1247
{
1248
  uint* pt = (uint*)safe_malloc(ntrans*sizeof(uint));
1249
  int i;
1250
 
1251
  for( i = 0; i < ntrans; i++ ) {
1252
    pt[i] = trans[i];
1253
  }
1254
  return(pt);
1255
 
1256
}
1257
 
1258
Stroke*
1259
concatenate_Strokes(int nstrokes1,
1260
			Stroke* strokes1,
1261
			int nstrokes2,
1262
			Stroke* strokes2,
1263
			int* nstrokes3,
1264
			Stroke** strokes3)
1265
{
1266
  int i;
1267
  int ns;
1268
  Stroke* ps;
1269
 
1270
  /*Measure new strokes*/
1271
 
1272
  ns = nstrokes1 + nstrokes2;
1273
 
1274
  /*Allocate memory*/
1275
 
1276
  if( (ps = make_Stroke_array(ns)) == nil ) {
1277
    return(nil);
1278
  }
1279
 
1280
  /*Copy old ones into new.*/
1281
 
1282
  for( i = 0; i < nstrokes1; i++ ) {
1283
    if( copy_Stroke(&ps[i],&strokes1[i]) == nil ) {
1284
      delete_Stroke_array(ns,ps,false);
1285
      return(nil);
1286
    }
1287
  }
1288
 
1289
  for( ; i < ns; i++ ) {
1290
    if( copy_Stroke(&ps[i],&strokes2[i - nstrokes1]) == nil ) {
1291
      delete_Stroke_array(ns,ps,false);
1292
      return(nil);
1293
    }
1294
  }
1295
 
1296
  *nstrokes3 = ns;
1297
  *strokes3 = ps;
1298
 
1299
  return(ps);
1300
}