hre_api.c 27 KB

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