hre_api.c 27 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300
  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. #include <u.h>
  22. #include <libc.h>
  23. #include <draw.h>
  24. #include <scribble.h>
  25. #include "scribbleimpl.h"
  26. #include "hre_internal.h"
  27. /* ari -- prototype for rii function */
  28. recognizer __recognizer_internal_initialize(rec_info* ri);
  29. /*Version number of API.*/
  30. char* REC_VERSION = "2.0";
  31. /*Domain name for internationalized text.*/
  32. #define INTL_DOMAIN "recognition_manager"
  33. /* XXX -- Intl Hack -- Jay & Ari */
  34. #define dgettext(domain, msg) (msg)
  35. #define bindtextdomain(dirname, domain)
  36. /*
  37. * These magic numbers are used to ensure the integrity of the
  38. * recognizer structure.
  39. */
  40. #define REC_MAGIC 0xfeed
  41. #define REC_END_MAGIC 0xbeef
  42. /*Check the recognizer for validity*/
  43. #define RI_CHECK_MAGIC(rec) \
  44. ( (rec != nil) && \
  45. (((recognizer)rec)->recognizer_magic == REC_MAGIC) && \
  46. (((recognizer)rec)->recognizer_end_magic == REC_END_MAGIC) &&\
  47. (((recognizer)rec)->recognizer_version == REC_VERSION) )
  48. /*The name of the initialization & finalization functions.*/
  49. /* static char rii_name[] = "__recognizer_internal_initialize";
  50. static char rif_name[] = "__recognizer_internal_finalize"; */
  51. /*User home directory for recognizer info.*/
  52. /* ari -- changed USERRECHOME from ".recognizers" */
  53. #define HOME "HOME"
  54. #define USERRECHOME ".classifiers"
  55. /*Local functions*/
  56. static char* shared_library_name(char* directory,char* locale,char* name);
  57. static rec_info* make_rec_info(char* directory,char* name,char** subset);
  58. static void delete_rec_info(rec_info* ri);
  59. static int check_for_user_home(void);
  60. static void intl_initialize(void);
  61. static void cleanup_rec_element(rec_element* re,bool delete_points_p);
  62. /*The last error.*/
  63. static char* the_last_error = nil;
  64. static char *safe_malloc (int nbytes)
  65. {
  66. char *res = malloc(nbytes);
  67. if (res == nil) {
  68. sysfatal("malloc failure");
  69. }
  70. return (res);
  71. }
  72. /*
  73. * Implementation of API functions
  74. */
  75. /*
  76. * recognizer_load - Load the recognizer matching the rec_info struct.
  77. * If name is not null, then load the recognizer having that name. Returns
  78. * the recognizer object, or null if it can't load the recognizer, and
  79. * sets errno to indicate why.
  80. */
  81. recognizer
  82. recognizer_load(char* directory, char* name, char** subset)
  83. {
  84. recognizer rec; /*the recognizer*/
  85. rec_info* rinf; /*rec_info for recognizer information*/
  86. static bool intl_init = false; /*true if recog. manager initted.*/
  87. if( intl_init == false ) {
  88. intl_init = true;
  89. intl_initialize();
  90. }
  91. /*The name takes precedence.*/
  92. rinf = make_rec_info(directory, name, subset);
  93. if (rinf == nil) {
  94. the_last_error =
  95. dgettext(INTL_DOMAIN,
  96. "Ran out of memory during prelinking initialization.");
  97. return((recognizer)nil);
  98. }
  99. /* fprint(2, "Got past make_rec_info.\n"); */
  100. /*Let recognition code create recognizer and initialize*/
  101. rec = __recognizer_internal_initialize(rinf);
  102. if (rec == nil) {
  103. return((recognizer)nil);
  104. }
  105. /* fprint(2, "Did rii.\n"); */
  106. /*Check whether it's been correctly initialized*/
  107. if( rec->recognizer_load_state == nil ||
  108. rec->recognizer_save_state == nil ||
  109. rec->recognizer_load_dictionary == nil ||
  110. rec->recognizer_save_dictionary == nil ||
  111. rec->recognizer_free_dictionary == nil ||
  112. rec->recognizer_add_to_dictionary == nil ||
  113. rec->recognizer_delete_from_dictionary == nil ||
  114. rec->recognizer_error == nil ||
  115. rec->recognizer_set_context == nil ||
  116. rec->recognizer_get_context == nil ||
  117. rec->recognizer_clear == nil ||
  118. rec->recognizer_get_buffer == nil ||
  119. rec->recognizer_set_buffer == nil ||
  120. rec->recognizer_translate == nil ||
  121. rec->recognizer_get_extension_functions == nil ||
  122. rec->recognizer_get_gesture_names == nil ||
  123. rec->recognizer_set_gesture_action == nil
  124. ) {
  125. recognizer_unload(rec);
  126. /* fprint(2, "Unloading b/c null function pointer.\n"); */
  127. the_last_error =
  128. dgettext(INTL_DOMAIN,
  129. "One or more recognizer function pointers is nil.");
  130. return((recognizer)nil);
  131. }
  132. /*Set the rec_info structure.*/
  133. rec->recognizer_info = rinf;
  134. /*Check whether home directory is there for recognizer info.*/
  135. /*
  136. * ari -- don't bother. We're not going to load from each user's
  137. * home directory at this point. Instead, we'll use a stupid
  138. * little a-b-c file because it loads FAST.
  139. *
  140. * if( check_for_user_home() < 0 ) {
  141. * recognizer_unload(rec);
  142. * return((recognizer)nil);
  143. * }
  144. */
  145. /*We got it!*/
  146. /* fprint(2, "Done.\n"); */
  147. return(rec);
  148. }
  149. /*
  150. * recognizer_unload - Unload the recognizer.
  151. */
  152. int
  153. recognizer_unload(recognizer rec)
  154. {
  155. /*Make sure magic numbers right.*/
  156. if( !RI_CHECK_MAGIC(rec) ) {
  157. the_last_error = dgettext(INTL_DOMAIN,"Bad recognizer object.");
  158. return(-1);
  159. }
  160. return __recognizer_internal_finalize(rec);
  161. }
  162. /*
  163. * recognizer_load_state-Get any recognizer state associated with name
  164. * in dir. Note that name may not be simple file name, since
  165. * there may be more than one file involved. Return 0 if successful,
  166. * -1 if not.
  167. */
  168. int recognizer_load_state(recognizer rec, char* dir, char* name)
  169. {
  170. /*Make sure magic numbers right.*/
  171. if( !RI_CHECK_MAGIC(rec) ) {
  172. the_last_error = dgettext(INTL_DOMAIN,"Bad recognizer object.");
  173. return(-1);
  174. }
  175. /*Do the function.*/
  176. return(rec->recognizer_load_state(rec, dir, name));
  177. }
  178. /*
  179. * recognizer_save_state-Save any recognizer state to name
  180. * in dir. Note that name may not be a simple file name, since
  181. * there may be more than one file involved. Return 0 if successful,
  182. * -1 if not.
  183. */
  184. int recognizer_save_state(recognizer rec,char* dir,char* name)
  185. {
  186. /*Make sure magic numbers right.*/
  187. if( !RI_CHECK_MAGIC(rec) ) {
  188. the_last_error = dgettext(INTL_DOMAIN,"Bad recognizer object.");
  189. return(-1);
  190. }
  191. /*Do the function.*/
  192. return(rec->recognizer_save_state(rec,dir,name));
  193. }
  194. /*
  195. * recognizer_load_dictionary-Load dictionary, return pointer
  196. * to it, or nil if error.
  197. */
  198. wordset recognizer_load_dictionary(recognizer rec,char* dir,char* name)
  199. {
  200. /*Make sure magic numbers right.*/
  201. if( !RI_CHECK_MAGIC(rec) ) {
  202. the_last_error = dgettext(INTL_DOMAIN,"Bad recognizer object.");
  203. return(nil);
  204. }
  205. /*Do the function.*/
  206. return(rec->recognizer_load_dictionary(rec,dir,name));
  207. }
  208. /*
  209. * recognizer_save_dictionary-Save the dictionary to the file, return 0 if
  210. * OK, -1 if error.
  211. */
  212. int recognizer_save_dictionary(recognizer rec,char* dir,char* name,wordset dict)
  213. {
  214. /*Make sure magic numbers right.*/
  215. if( !RI_CHECK_MAGIC(rec) ) {
  216. the_last_error = dgettext(INTL_DOMAIN,"Bad recognizer object.");
  217. return(-1);
  218. }
  219. /*Do the function.*/
  220. return(rec->recognizer_save_dictionary(rec,dir,name,dict));
  221. }
  222. /*
  223. * recognizer_free_dictionary-Free the dictionary, return 0 if
  224. * OK, -1 if error.
  225. */
  226. int recognizer_free_dictionary(recognizer rec,wordset dict)
  227. {
  228. /*Make sure magic numbers right.*/
  229. if( !RI_CHECK_MAGIC(rec) ) {
  230. the_last_error = dgettext(INTL_DOMAIN,"Bad recognizer object.");
  231. return(-1);
  232. }
  233. /*Do the function.*/
  234. return(rec->recognizer_free_dictionary(rec,dict));
  235. }
  236. /*
  237. * recognizer_add_to_dictionary-Add word to the dictionary,
  238. * return 0 if OK, -1 if error.
  239. */
  240. int recognizer_add_to_dictionary(recognizer rec,letterset* word,wordset dict)
  241. {
  242. /*Make sure magic numbers right.*/
  243. if( !RI_CHECK_MAGIC(rec) ) {
  244. the_last_error = dgettext(INTL_DOMAIN,"Bad recognizer object.");
  245. return(-1);
  246. }
  247. /*Do the function.*/
  248. return(rec->recognizer_add_to_dictionary(rec,word,dict));
  249. }
  250. /*
  251. * recognizer_delete_from_dictionary-Delete word from the dictionary,
  252. * return 0 if OK, -1 if error.
  253. */
  254. int
  255. recognizer_delete_from_dictionary(recognizer rec,letterset* word,wordset dict)
  256. {
  257. /*Make sure magic numbers right.*/
  258. if( !RI_CHECK_MAGIC(rec) ) {
  259. the_last_error = dgettext(INTL_DOMAIN,"Bad recognizer object.");
  260. return(-1);
  261. }
  262. /*Do the function.*/
  263. return(rec->recognizer_delete_from_dictionary(rec,word,dict));
  264. }
  265. /*
  266. * recognizer_get_info-Get a pointers to the rec_info
  267. * giving the locales and subsets supported by the recognizer
  268. * and the shared library pathname.
  269. */
  270. const rec_info*
  271. recognizer_get_info(recognizer rec)
  272. {
  273. /*Make sure magic numbers right.*/
  274. if( !RI_CHECK_MAGIC(rec) ) {
  275. the_last_error = dgettext(INTL_DOMAIN,"Bad recognizer object.");
  276. return((rec_info*)nil);
  277. }
  278. /*Return the rec_info object.*/
  279. return(rec->recognizer_info);
  280. }
  281. /*
  282. * recognizer_manager_version-Return the version number string of the
  283. * recognition manager.
  284. */
  285. const char* recognizer_manager_version(recognizer rec)
  286. {
  287. /*Make sure magic numbers right.*/
  288. if( !RI_CHECK_MAGIC(rec) ) {
  289. the_last_error = dgettext(INTL_DOMAIN,"Bad recognizer object.");
  290. return(nil);
  291. }
  292. return(rec->recognizer_version);
  293. }
  294. /*
  295. * recognizer_error-Return the last error message, or nil if none.
  296. */
  297. char* recognizer_error(recognizer rec)
  298. {
  299. /*Make sure magic numbers right and function there.*/
  300. if( !RI_CHECK_MAGIC(rec) && the_last_error == nil ) {
  301. return(dgettext(INTL_DOMAIN,"Bad recognizer object."));
  302. } else if( the_last_error != nil ) {
  303. char* error = the_last_error;
  304. the_last_error = nil;
  305. return(error);
  306. }
  307. /*Do the function.*/
  308. return(rec->recognizer_error(rec));
  309. }
  310. /*
  311. * recognizer_set_context-Set the recognition context for translation.
  312. * Return 0 if successful, -1 if error.
  313. */
  314. int recognizer_set_context(recognizer rec,rc* rec_xt)
  315. {
  316. /*Make sure magic numbers right.*/
  317. if( !RI_CHECK_MAGIC(rec) ) {
  318. the_last_error = dgettext(INTL_DOMAIN,"Bad recognizer object.");
  319. return(-1);
  320. }
  321. /*Do the function.*/
  322. return(rec->recognizer_set_context(rec,rec_xt));
  323. }
  324. /*
  325. * recognzier_get_context-Get the recognition context for translation.
  326. * If none or error, return nil.
  327. */
  328. rc* recognizer_get_context(recognizer rec)
  329. {
  330. /*Make sure magic numbers right.*/
  331. if( !RI_CHECK_MAGIC(rec) ) {
  332. the_last_error = dgettext(INTL_DOMAIN,"Bad recognizer object.");
  333. return(nil);
  334. }
  335. /*Do the function.*/
  336. return(rec->recognizer_get_context(rec));
  337. }
  338. /*
  339. * recognizer_clear-Clear buffer and recognition context.
  340. * Return 0 if success, else -1.
  341. */
  342. int recognizer_clear(recognizer rec,bool delete_points_p)
  343. {
  344. /*Make sure magic numbers right.*/
  345. if( !RI_CHECK_MAGIC(rec) ) {
  346. the_last_error = dgettext(INTL_DOMAIN,"Bad recognizer object.");
  347. return(-1);
  348. }
  349. /*Do the function.*/
  350. return(rec->recognizer_clear(rec,delete_points_p));
  351. }
  352. /*recognizer_get_buffer-Get stroke buffer. Return 0 if success, else -1.*/
  353. int recognizer_get_buffer(recognizer rec, uint* nstrokes,Stroke** strokes)
  354. {
  355. /*Make sure magic numbers right.*/
  356. if( !RI_CHECK_MAGIC(rec) ) {
  357. the_last_error = dgettext(INTL_DOMAIN,"Bad recognizer object.");
  358. return(-1);
  359. }
  360. /*Do the function.*/
  361. return(rec->recognizer_get_buffer(rec,nstrokes,strokes));
  362. }
  363. /*
  364. * recognizer_set_buffer-Set stroke buffer to arg. Return 0 if success, else
  365. * return -1.
  366. */
  367. int recognizer_set_buffer(recognizer rec,uint nstrokes,Stroke* strokes)
  368. {
  369. /*Make sure magic numbers right.*/
  370. if( !RI_CHECK_MAGIC(rec) ) {
  371. the_last_error = dgettext(INTL_DOMAIN,"Bad recognizer object.");
  372. return(-1);
  373. }
  374. /*Do the function.*/
  375. return(rec->recognizer_set_buffer(rec,nstrokes,strokes));
  376. }
  377. /*
  378. * recognizer_translate-Translate the strokes in the current context, including
  379. * buffered strokes. If nstrokes == 0 or strokes == nil, return
  380. * translation of stroke buffer.
  381. */
  382. int recognizer_translate(recognizer rec,
  383. uint nstrokes,
  384. Stroke* strokes,
  385. bool correlate_p,
  386. int* nret,
  387. rec_alternative** ret)
  388. {
  389. int retval;
  390. char msg[80];
  391. /*Make sure magic numbers right.*/
  392. if( !RI_CHECK_MAGIC(rec) ) {
  393. the_last_error = dgettext(INTL_DOMAIN, msg);
  394. return(-1);
  395. }
  396. /* ari */
  397. /* {
  398. * uint i;
  399. * Stroke ari_pstr;
  400. * pen_point* ari_pts;
  401. * int ari;
  402. * for (i = 0; i < nstrokes; i++) {
  403. * ari_pstr = strokes[i];
  404. * ari_pts = ari_pstr.ps_pts;
  405. * 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);
  406. * for (ari = 0; ari < ari_pstr.ps_npts; ari++)
  407. * fprint(2, "%ld -- (%d, %d) ", ari_pts[ari], ari_pts[ari].x, ari_pts[ari].y);
  408. * }
  409. * }
  410. */
  411. /*Do the function.*/
  412. /* ari -- this is calling cmu_recognizer_translate */
  413. retval = rec->recognizer_translate(rec,
  414. nstrokes,
  415. strokes,
  416. correlate_p,
  417. nret,
  418. ret);
  419. return (retval);
  420. }
  421. /*
  422. * recognizer_get_extension_functions-Return a null terminated array
  423. * of functions providing extended functionality. Their interfaces
  424. * will change depending on the recognizer.
  425. */
  426. rec_fn* recognizer_get_extension_functions(recognizer rec)
  427. {
  428. /*Make sure magic numbers right.*/
  429. if( !RI_CHECK_MAGIC(rec) ) {
  430. the_last_error = dgettext(INTL_DOMAIN,"Bad recognizer object.");
  431. return((rec_fn*)nil);
  432. }
  433. /*Do the function.*/
  434. return(rec->recognizer_get_extension_functions(rec));
  435. }
  436. /*
  437. * recognizer_get_gesture_names - Return a null terminated array of
  438. * gesture name strings.
  439. */
  440. char**
  441. recognizer_get_gesture_names(recognizer rec)
  442. {
  443. /*Make sure magic numbers right.*/
  444. if( !RI_CHECK_MAGIC(rec) ) {
  445. the_last_error = dgettext(INTL_DOMAIN,"Bad recognizer object.");
  446. return(nil);
  447. }
  448. /*Do the function.*/
  449. return(rec->recognizer_get_gesture_names(rec));
  450. }
  451. /*
  452. * recognizer_set_gesture_action-Set the action function for the gesture.
  453. */
  454. xgesture
  455. recognizer_train_gestures(recognizer rec,char* name,xgesture fn,void* wsinfo)
  456. {
  457. /*Make sure magic numbers right.*/
  458. if( !RI_CHECK_MAGIC(rec) ) {
  459. the_last_error = dgettext(INTL_DOMAIN,"Bad recognizer object.");
  460. return((xgesture)-1);
  461. }
  462. /*Do the function.*/
  463. return(rec->recognizer_set_gesture_action(rec,name,fn,wsinfo));
  464. }
  465. /*
  466. * Local functions.
  467. */
  468. /*
  469. * shared_library_name-Get the full pathname to the shared library,
  470. * based on the recognizer name and the environment.
  471. */
  472. static char* shared_library_name(char* directory,char* locale,char* name)
  473. {
  474. char* ret;
  475. int len = strlen(name);
  476. /*If directory is there, it takes precedence.*/
  477. if( directory != nil ) {
  478. ret = (char*)safe_malloc(strlen(directory) + len + 2);
  479. strcpy(ret,directory);
  480. strcat(ret,"/");
  481. strcat(ret,name);
  482. } else {
  483. char* dir;
  484. /*First try the environment variable.*/
  485. if( (dir = getenv(RECHOME)) == nil ) {
  486. dir = "REC_DEFAULT_HOME_DIR";
  487. }
  488. ret = (char*)safe_malloc(strlen(dir) + strlen(locale) + len + 3);
  489. /*Form the pathname.*/
  490. strcpy(ret,dir);
  491. strcat(ret,"/");
  492. strcat(ret,locale);
  493. strcat(ret,"/");
  494. strcat(ret,name);
  495. }
  496. return(ret);
  497. }
  498. /*
  499. * intl_initialize-Initialize the internationaliztion of messages for
  500. * the recognition manager.
  501. */
  502. static void intl_initialize(void)
  503. {
  504. char* dirname;
  505. /*Get recognizer home directory name from environment.*/
  506. if( (dirname = getenv(RECHOME)) == nil ) {
  507. dirname = "REC_DEFAULT_HOME_DIR";
  508. }
  509. /*Bind the text domain.*/
  510. USED(dirname);
  511. bindtextdomain(dirname, INTL_DOMAIN);
  512. }
  513. /*make_rec_info-Create a rec_info structure*/
  514. static rec_info* make_rec_info(char*, char*, char** subset)
  515. {
  516. int i,len;
  517. rec_info* ri;
  518. char* locale;
  519. ri = (rec_info*)safe_malloc(sizeof(rec_info));
  520. ri->ri_locale = nil;
  521. ri->ri_name = nil;
  522. ri->ri_subset = nil;
  523. /*Get locale*/
  524. if( (locale = getenv(LANG)) == nil ) {
  525. locale = strdup(REC_DEFAULT_LOCALE);
  526. }
  527. if( (ri->ri_locale = strdup(locale)) == nil ) {
  528. delete_rec_info(ri);
  529. return(nil);
  530. }
  531. /*Get shared library pathname.*/
  532. /*Initialize the subset information.*/
  533. if( subset != nil ) {
  534. /*Count the subset strings.*/
  535. for( len = 1; subset[len] != nil; len++ ) ;
  536. /*Copy the subset strings.*/
  537. ri->ri_subset = (char**)safe_malloc((len +1)*sizeof(char*));
  538. for( i = 0; i < len; i++ ) {
  539. if( subset[i] != nil ) {
  540. if( (ri->ri_subset[i] = strdup(subset[i])) == nil ) {
  541. delete_rec_info(ri);
  542. return(nil);
  543. }
  544. } else {
  545. ri->ri_subset[i] = subset[i];
  546. }
  547. }
  548. ri->ri_subset[i] = nil;
  549. } else {
  550. ri->ri_subset = nil;
  551. }
  552. return(ri);
  553. }
  554. static void delete_rec_info(rec_info* ri)
  555. {
  556. if( ri != nil ) {
  557. if( ri->ri_locale != nil ) {
  558. free(ri->ri_locale);
  559. }
  560. /*
  561. * if( ri->ri_name != nil ) {
  562. * free(ri->ri_name);
  563. * }
  564. */
  565. if( ri->ri_subset != nil ) {
  566. int i;
  567. for( i = 0; ri->ri_subset[i] != nil; i++) {
  568. free(ri->ri_subset[i]);
  569. }
  570. free(ri->ri_subset);
  571. }
  572. free(ri);
  573. }
  574. }
  575. /*check_for_user_home-Check whether USERRECHOME has been created.*/
  576. static int check_for_user_home()
  577. {
  578. char* homedir = getenv(HOME);
  579. char* rechome;
  580. Dir *dir;
  581. if( homedir == nil ) {
  582. the_last_error = "Home environment variable HOME not set.";
  583. return(-1);
  584. }
  585. rechome = (char*)safe_malloc(strlen(homedir) + strlen(USERRECHOME) + 2);
  586. /*Form name.*/
  587. strcpy(rechome,homedir);
  588. strcat(rechome,"/");
  589. strcat(rechome,USERRECHOME);
  590. /*Create directory.*/
  591. dir = dirstat(rechome);
  592. if (dir != nil) {
  593. if (dir->mode & DMDIR) {
  594. free(dir);
  595. free(rechome);
  596. return 0;
  597. }
  598. free(dir);
  599. } else {
  600. int fd;
  601. if ((fd = create(rechome, OREAD, DMDIR|0755)) >= 0) {
  602. close(fd);
  603. free(rechome);
  604. return(0);
  605. }
  606. }
  607. free(rechome);
  608. return(-1);
  609. }
  610. /*
  611. * Constructor functions for making structures.
  612. *
  613. * The general philosophy here is that we control all memory
  614. * in connected data structures, *except* for pen_point arrays.
  615. * There are likely to be lots and lots of points, they are likely
  616. * to come from the window system; so if we wanted to control them,
  617. * we would have to copy which would be slow. We require the client
  618. * to deal with them directly, or the client can give us permission
  619. * to delete them.
  620. */
  621. /*
  622. * recognizer
  623. */
  624. recognizer make_recognizer(rec_info* rif)
  625. {
  626. recognizer rec;
  627. /*Allocate it.*/
  628. rec = (recognizer)safe_malloc(sizeof(*rec));
  629. rec->recognizer_magic = REC_MAGIC;
  630. rec->recognizer_version = REC_VERSION;
  631. rec->recognizer_info = rif;
  632. rec->recognizer_specific = nil;
  633. rec->recognizer_end_magic = REC_END_MAGIC;
  634. rec->recognizer_load_state = nil;
  635. rec->recognizer_save_state = nil;
  636. rec->recognizer_load_dictionary = nil;
  637. rec->recognizer_save_dictionary = nil;
  638. rec->recognizer_free_dictionary = nil;
  639. rec->recognizer_add_to_dictionary = nil;
  640. rec->recognizer_delete_from_dictionary = nil;
  641. rec->recognizer_error = nil;
  642. rec->recognizer_set_context = nil;
  643. rec->recognizer_get_context = nil;
  644. rec->recognizer_clear = nil;
  645. rec->recognizer_get_buffer = nil;
  646. rec->recognizer_set_buffer = nil;
  647. rec->recognizer_translate = nil;
  648. rec->recognizer_get_extension_functions = nil;
  649. rec->recognizer_get_gesture_names = nil;
  650. rec->recognizer_set_gesture_action = nil;
  651. return(rec);
  652. }
  653. void delete_recognizer(recognizer rec)
  654. {
  655. if( rec != nil ) {
  656. if( rec->recognizer_info != nil ) {
  657. delete_rec_info(rec->recognizer_info);
  658. }
  659. free(rec);
  660. }
  661. }
  662. /*
  663. * rec_alternative
  664. */
  665. rec_alternative* make_rec_alternative_array(uint size)
  666. {
  667. int i;
  668. rec_alternative* ri;
  669. ri = (rec_alternative*) safe_malloc(size * sizeof(rec_alternative));
  670. for( i = 0; i < size; i++ ) {
  671. ri[i].ra_elem.re_type = REC_NONE;
  672. ri[i].ra_elem.re_result.aval = nil;
  673. ri[i].ra_elem.re_conf = 0;
  674. ri[i].ra_nalter = 0;
  675. ri[i].ra_next = nil;
  676. }
  677. return(ri);
  678. }
  679. rec_alternative*
  680. initialize_rec_alternative(rec_alternative* ra, uint nelm)
  681. {
  682. if( ra != nil ) {
  683. if( (ra->ra_next = make_rec_alternative_array(nelm)) == nil ) {
  684. return(nil);
  685. }
  686. ra->ra_nalter = nelm;
  687. }
  688. return(ra);
  689. }
  690. void delete_rec_alternative_array(uint nalter,
  691. rec_alternative* ra,
  692. bool delete_points_p)
  693. {
  694. int i;
  695. if( ra != nil ) {
  696. for( i = 0; i < nalter; i++ ) {
  697. cleanup_rec_element(&ra[i].ra_elem,delete_points_p);
  698. /*Now do the next one down the line.*/
  699. if( ra[i].ra_nalter > 0 ) {
  700. delete_rec_alternative_array(ra[i].ra_nalter,
  701. ra[i].ra_next,
  702. delete_points_p);
  703. }
  704. }
  705. free(ra);
  706. }
  707. }
  708. /*initialize_rec_element-Initialize a recognition element.*/
  709. rec_element*
  710. initialize_rec_element(rec_element* re,
  711. char type,
  712. uint size,
  713. void* trans,
  714. rec_confidence conf)
  715. {
  716. if( re != nil ) {
  717. re->re_type = type;
  718. re->re_conf = conf;
  719. re->re_result.aval = nil;
  720. switch (type) {
  721. case REC_GESTURE:
  722. if( size > 0 && trans != nil ) {
  723. re->re_result.gval =
  724. (gesture*)safe_malloc(sizeof(gesture));
  725. memcpy((void*)re->re_result.gval,trans,sizeof(gesture));
  726. }
  727. break;
  728. case REC_ASCII:
  729. case REC_VAR:
  730. case REC_OTHER:
  731. if( size > 0 && trans != nil ) {
  732. re->re_result.aval =
  733. (char*)safe_malloc((size+1)*sizeof(char));
  734. memcpy((void*)re->re_result.aval,trans,size*sizeof(char));
  735. re->re_result.aval[size] = '\000';
  736. }
  737. break;
  738. case REC_WCHAR:
  739. if( size > 0 && trans != nil ) {
  740. re->re_result.wval =
  741. (wchar_t*)safe_malloc((size+1)*sizeof(wchar_t));
  742. memcpy((void*)re->re_result.wval,trans,size*sizeof(wchar_t));
  743. re->re_result.wval[size] = '\000';
  744. }
  745. break;
  746. case REC_CORR:
  747. if( size > 0 && trans != nil ) {
  748. re->re_result.rcval =
  749. (rec_correlation*)safe_malloc(sizeof(rec_correlation));
  750. memcpy((void*)re->re_result.rcval,
  751. trans,
  752. sizeof(rec_correlation));
  753. }
  754. break;
  755. default:
  756. return(nil);
  757. }
  758. }
  759. return(re);
  760. }
  761. static void cleanup_rec_element(rec_element* re,bool delete_points_p)
  762. {
  763. switch(re->re_type) {
  764. case REC_NONE:
  765. break;
  766. case REC_ASCII:
  767. case REC_VAR:
  768. case REC_WCHAR:
  769. case REC_OTHER:
  770. free(re->re_result.aval);
  771. break;
  772. case REC_GESTURE:
  773. delete_gesture_array(1,re->re_result.gval,true);
  774. break;
  775. case REC_CORR:
  776. delete_rec_correlation(re->re_result.rcval,
  777. delete_points_p);
  778. break;
  779. }
  780. }
  781. /*
  782. * rec_correlation
  783. */
  784. rec_correlation*
  785. make_rec_correlation(char type,
  786. uint size,
  787. void* trans,
  788. rec_confidence conf,
  789. uint ps_size)
  790. {
  791. rec_correlation* rc;
  792. rc = (rec_correlation*)safe_malloc(sizeof(rec_correlation));
  793. rc->ro_nstrokes = ps_size;
  794. /*First initialize element.*/
  795. if( initialize_rec_element(&(rc->ro_elem),
  796. type,
  797. size,
  798. trans,
  799. conf) == nil ) {
  800. return(nil);
  801. }
  802. if( (rc->ro_strokes = make_Stroke_array(ps_size)) == nil ) {
  803. return(nil);
  804. }
  805. rc->ro_start = (uint*)safe_malloc(ps_size * sizeof(int));
  806. rc->ro_stop = (uint*)safe_malloc(ps_size * sizeof(int));
  807. return(rc);
  808. }
  809. void delete_rec_correlation(rec_correlation* rc,bool delete_points_p)
  810. {
  811. if( rc != nil ) {
  812. cleanup_rec_element(&rc->ro_elem,delete_points_p);
  813. delete_Stroke_array(rc->ro_nstrokes,rc->ro_strokes,delete_points_p);
  814. if( rc->ro_start != nil ) {
  815. free(rc->ro_start);
  816. }
  817. if( rc->ro_stop != nil ) {
  818. free(rc->ro_stop);
  819. }
  820. free(rc);
  821. }
  822. }
  823. /*
  824. * rec_fn
  825. */
  826. rec_fn* make_rec_fn_array(uint size)
  827. {
  828. rec_fn* ri = (rec_fn*)safe_malloc((size + 1) * sizeof(rec_fn));
  829. int i;
  830. for( i = 0; i < size; i++ ) {
  831. ri[i] = nil;
  832. }
  833. ri[i] = nil;
  834. return(ri);
  835. }
  836. void delete_rec_fn_array(rec_fn* rf)
  837. {
  838. if( rf != nil ) {
  839. free(rf);
  840. }
  841. }
  842. /*
  843. * Stroke
  844. */
  845. Stroke* make_Stroke_array(uint size)
  846. {
  847. int i;
  848. Stroke* ri;
  849. ri = (Stroke*) safe_malloc(size * sizeof(Stroke));
  850. for( i = 0; i < size; i++ ) {
  851. ri[i].npts = 0;
  852. ri[i].pts = nil;
  853. }
  854. return(ri);
  855. }
  856. Stroke* initialize_Stroke(Stroke* ps,
  857. uint npts,
  858. pen_point* pts)
  859. {
  860. if( ps != nil ) {
  861. ps->npts = npts;
  862. ps->pts = pts;
  863. }
  864. return (ps);
  865. }
  866. void delete_Stroke_array(uint size,Stroke* ps,bool delete_points_p)
  867. {
  868. int i;
  869. if( ps != nil ) {
  870. for( i = 0; i < size; i++ ) {
  871. if( delete_points_p ) {
  872. delete_pen_point_array(ps[i].pts);
  873. }
  874. }
  875. free(ps);
  876. }
  877. }
  878. /*
  879. * pen_point
  880. */
  881. void delete_pen_point_array(pen_point* pp)
  882. {
  883. if( pp != nil ) {
  884. free(pp);
  885. }
  886. }
  887. /*
  888. * gesture
  889. */
  890. gesture*
  891. make_gesture_array(uint size)
  892. {
  893. return((gesture*)safe_malloc(size * sizeof(gesture)));
  894. }
  895. gesture* initialize_gesture(gesture* g,
  896. char* name,
  897. uint nhs,
  898. pen_point* hspots,
  899. pen_rect bbox,
  900. xgesture fn,
  901. void* wsinfo)
  902. {
  903. if( g != nil ) {
  904. /*We don't do points, 'cause they come from the window system.*/
  905. g->g_nhs = nhs;
  906. g->g_hspots = hspots;
  907. g->g_name = strdup(name);
  908. g->g_bbox = bbox;
  909. g->g_action = fn;
  910. g->g_wsinfo = wsinfo;
  911. }
  912. return(g);
  913. }
  914. void
  915. delete_gesture_array(uint size,gesture* ga,bool delete_points_p)
  916. {
  917. int i;
  918. if( ga != nil ) {
  919. for( i = 0; i < size; i++ ) {
  920. free(ga[i].g_name);
  921. if( delete_points_p ) {
  922. delete_pen_point_array(ga[i].g_hspots);
  923. }
  924. }
  925. free(ga);
  926. }
  927. }
  928. /*
  929. * copy fns for stroke buffer management.
  930. */
  931. static Stroke*
  932. copy_Stroke(Stroke* ps1,Stroke* ps2)
  933. {
  934. initialize_Stroke(ps1,
  935. ps2->npts,
  936. ps2->pts);
  937. return(ps1);
  938. }
  939. Stroke*
  940. copy_Stroke_array(uint nstrokes,
  941. Stroke* strokes)
  942. {
  943. int i;
  944. Stroke* ps = make_Stroke_array(nstrokes);
  945. if( ps != nil ) {
  946. for( i = 0; i < nstrokes; i++ ) {
  947. copy_Stroke(&ps[i],&strokes[i]);
  948. }
  949. }
  950. return(ps);
  951. }
  952. uint*
  953. copy_state_trans_array(uint ntrans,uint* trans)
  954. {
  955. uint* pt = (uint*)safe_malloc(ntrans*sizeof(uint));
  956. int i;
  957. for( i = 0; i < ntrans; i++ ) {
  958. pt[i] = trans[i];
  959. }
  960. return(pt);
  961. }
  962. Stroke*
  963. concatenate_Strokes(int nstrokes1,
  964. Stroke* strokes1,
  965. int nstrokes2,
  966. Stroke* strokes2,
  967. int* nstrokes3,
  968. Stroke** strokes3)
  969. {
  970. int i;
  971. int ns;
  972. Stroke* ps;
  973. /*Measure new strokes*/
  974. ns = nstrokes1 + nstrokes2;
  975. /*Allocate memory*/
  976. if( (ps = make_Stroke_array(ns)) == nil ) {
  977. return(nil);
  978. }
  979. /*Copy old ones into new.*/
  980. for( i = 0; i < nstrokes1; i++ ) {
  981. if( copy_Stroke(&ps[i],&strokes1[i]) == nil ) {
  982. delete_Stroke_array(ns,ps,false);
  983. return(nil);
  984. }
  985. }
  986. for( ; i < ns; i++ ) {
  987. if( copy_Stroke(&ps[i],&strokes2[i - nstrokes1]) == nil ) {
  988. delete_Stroke_array(ns,ps,false);
  989. return(nil);
  990. }
  991. }
  992. *nstrokes3 = ns;
  993. *strokes3 = ps;
  994. return(ps);
  995. }