plan9front/sys/src/libscribble/hre_api.c

1201 lines
25 KiB
C

/*
* hre_api.c: Implementation of HRE API
* Author: James &
* Created On: Wed Dec 9 13:49:14 1992
* Last Modified By: James Kempf
* Last Modified On: Fri Sep 23 13:49:04 1994
* Update Count: 137
* Copyright (c) 1994 by Sun Microsystems Computer Company
* All rights reserved.
*
* Use and copying of this software and preparation of
* derivative works based upon this software are permitted.
* Any distribution of this software or derivative works
* must comply with all applicable United States export control
* laws.
*
* This software is made available as is, and Sun Microsystems
* Computer Company makes no warranty about the software, its
* performance, or its conformity to any specification
*/
#include <u.h>
#include <libc.h>
#include <draw.h>
#include <scribble.h>
#include "scribbleimpl.h"
#include "hre_internal.h"
/* ari -- prototype for rii function */
recognizer __recognizer_internal_initialize(rec_info* ri);
/*Version number of API.*/
char* REC_VERSION = "2.0";
/*Domain name for internationalized text.*/
#define INTL_DOMAIN "recognition_manager"
/* XXX -- Intl Hack -- Jay & Ari */
#define dgettext(domain, msg) (msg)
#define bindtextdomain(dirname, domain)
/*
* These magic numbers are used to ensure the integrity of the
* recognizer structure.
*/
#define REC_MAGIC 0xfeed
#define REC_END_MAGIC 0xbeef
/*Check the recognizer for validity*/
#define RI_CHECK_MAGIC(rec) \
( (rec != nil) && \
(((recognizer)rec)->recognizer_magic == REC_MAGIC) && \
(((recognizer)rec)->recognizer_end_magic == REC_END_MAGIC) &&\
(((recognizer)rec)->recognizer_version == REC_VERSION) )
/*The name of the initialization & finalization functions.*/
/* static char rii_name[] = "__recognizer_internal_initialize";
static char rif_name[] = "__recognizer_internal_finalize"; */
/*User home directory for recognizer info.*/
/* ari -- changed USERRECHOME from ".recognizers" */
#define HOME "HOME"
#define USERRECHOME ".classifiers"
/*Local functions*/
static rec_info* make_rec_info(char* directory,char* name,char** subset);
static void delete_rec_info(rec_info* ri);
static void intl_initialize(void);
static void cleanup_rec_element(rec_element* re,bool delete_points_p);
/*The last error.*/
static char* the_last_error = nil;
static char *safe_malloc (int nbytes)
{
char *res = malloc(nbytes);
if (res == nil) {
sysfatal("malloc failure");
}
return (res);
}
/*
* Implementation of API functions
*/
/*
* recognizer_load - Load the recognizer matching the rec_info struct.
* If name is not null, then load the recognizer having that name. Returns
* the recognizer object, or null if it can't load the recognizer, and
* sets errno to indicate why.
*/
recognizer
recognizer_load(char* directory, char* name, char** subset)
{
recognizer rec; /*the recognizer*/
rec_info* rinf; /*rec_info for recognizer information*/
static bool intl_init = false; /*true if recog. manager initted.*/
if( intl_init == false ) {
intl_init = true;
intl_initialize();
}
/*The name takes precedence.*/
rinf = make_rec_info(directory, name, subset);
if (rinf == nil) {
the_last_error =
dgettext(INTL_DOMAIN,
"Ran out of memory during prelinking initialization.");
return((recognizer)nil);
}
/* fprint(2, "Got past make_rec_info.\n"); */
/*Let recognition code create recognizer and initialize*/
rec = __recognizer_internal_initialize(rinf);
if (rec == nil) {
return((recognizer)nil);
}
/* fprint(2, "Did rii.\n"); */
/*Check whether it's been correctly initialized*/
if( rec->recognizer_load_state == nil ||
rec->recognizer_save_state == nil ||
rec->recognizer_load_dictionary == nil ||
rec->recognizer_save_dictionary == nil ||
rec->recognizer_free_dictionary == nil ||
rec->recognizer_add_to_dictionary == nil ||
rec->recognizer_delete_from_dictionary == nil ||
rec->recognizer_error == nil ||
rec->recognizer_set_context == nil ||
rec->recognizer_get_context == nil ||
rec->recognizer_clear == nil ||
rec->recognizer_get_buffer == nil ||
rec->recognizer_set_buffer == nil ||
rec->recognizer_translate == nil ||
rec->recognizer_get_extension_functions == nil ||
rec->recognizer_get_gesture_names == nil ||
rec->recognizer_set_gesture_action == nil
) {
recognizer_unload(rec);
/* fprint(2, "Unloading b/c null function pointer.\n"); */
the_last_error =
dgettext(INTL_DOMAIN,
"One or more recognizer function pointers is nil.");
return((recognizer)nil);
}
/*Set the rec_info structure.*/
rec->recognizer_info = rinf;
return(rec);
}
/*
* recognizer_unload - Unload the recognizer.
*/
int
recognizer_unload(recognizer rec)
{
/*Make sure magic numbers right.*/
if( !RI_CHECK_MAGIC(rec) ) {
the_last_error = dgettext(INTL_DOMAIN,"Bad recognizer object.");
return(-1);
}
return __recognizer_internal_finalize(rec);
}
/*
* recognizer_load_state-Get any recognizer state associated with name
* in dir. Note that name may not be simple file name, since
* there may be more than one file involved. Return 0 if successful,
* -1 if not.
*/
int recognizer_load_state(recognizer rec, char* dir, char* name)
{
/*Make sure magic numbers right.*/
if( !RI_CHECK_MAGIC(rec) ) {
the_last_error = dgettext(INTL_DOMAIN,"Bad recognizer object.");
return(-1);
}
/*Do the function.*/
return(rec->recognizer_load_state(rec, dir, name));
}
/*
* recognizer_save_state-Save any recognizer state to name
* in dir. Note that name may not be a simple file name, since
* there may be more than one file involved. Return 0 if successful,
* -1 if not.
*/
int recognizer_save_state(recognizer rec,char* dir,char* name)
{
/*Make sure magic numbers right.*/
if( !RI_CHECK_MAGIC(rec) ) {
the_last_error = dgettext(INTL_DOMAIN,"Bad recognizer object.");
return(-1);
}
/*Do the function.*/
return(rec->recognizer_save_state(rec,dir,name));
}
/*
* recognizer_load_dictionary-Load dictionary, return pointer
* to it, or nil if error.
*/
wordset recognizer_load_dictionary(recognizer rec,char* dir,char* name)
{
/*Make sure magic numbers right.*/
if( !RI_CHECK_MAGIC(rec) ) {
the_last_error = dgettext(INTL_DOMAIN,"Bad recognizer object.");
return(nil);
}
/*Do the function.*/
return(rec->recognizer_load_dictionary(rec,dir,name));
}
/*
* recognizer_save_dictionary-Save the dictionary to the file, return 0 if
* OK, -1 if error.
*/
int recognizer_save_dictionary(recognizer rec,char* dir,char* name,wordset dict)
{
/*Make sure magic numbers right.*/
if( !RI_CHECK_MAGIC(rec) ) {
the_last_error = dgettext(INTL_DOMAIN,"Bad recognizer object.");
return(-1);
}
/*Do the function.*/
return(rec->recognizer_save_dictionary(rec,dir,name,dict));
}
/*
* recognizer_free_dictionary-Free the dictionary, return 0 if
* OK, -1 if error.
*/
int recognizer_free_dictionary(recognizer rec,wordset dict)
{
/*Make sure magic numbers right.*/
if( !RI_CHECK_MAGIC(rec) ) {
the_last_error = dgettext(INTL_DOMAIN,"Bad recognizer object.");
return(-1);
}
/*Do the function.*/
return(rec->recognizer_free_dictionary(rec,dict));
}
/*
* recognizer_add_to_dictionary-Add word to the dictionary,
* return 0 if OK, -1 if error.
*/
int recognizer_add_to_dictionary(recognizer rec,letterset* word,wordset dict)
{
/*Make sure magic numbers right.*/
if( !RI_CHECK_MAGIC(rec) ) {
the_last_error = dgettext(INTL_DOMAIN,"Bad recognizer object.");
return(-1);
}
/*Do the function.*/
return(rec->recognizer_add_to_dictionary(rec,word,dict));
}
/*
* recognizer_delete_from_dictionary-Delete word from the dictionary,
* return 0 if OK, -1 if error.
*/
int
recognizer_delete_from_dictionary(recognizer rec,letterset* word,wordset dict)
{
/*Make sure magic numbers right.*/
if( !RI_CHECK_MAGIC(rec) ) {
the_last_error = dgettext(INTL_DOMAIN,"Bad recognizer object.");
return(-1);
}
/*Do the function.*/
return(rec->recognizer_delete_from_dictionary(rec,word,dict));
}
/*
* recognizer_get_info-Get a pointers to the rec_info
* giving the locales and subsets supported by the recognizer
* and the shared library pathname.
*/
const rec_info*
recognizer_get_info(recognizer rec)
{
/*Make sure magic numbers right.*/
if( !RI_CHECK_MAGIC(rec) ) {
the_last_error = dgettext(INTL_DOMAIN,"Bad recognizer object.");
return((rec_info*)nil);
}
/*Return the rec_info object.*/
return(rec->recognizer_info);
}
/*
* recognizer_manager_version-Return the version number string of the
* recognition manager.
*/
const char* recognizer_manager_version(recognizer rec)
{
/*Make sure magic numbers right.*/
if( !RI_CHECK_MAGIC(rec) ) {
the_last_error = dgettext(INTL_DOMAIN,"Bad recognizer object.");
return(nil);
}
return(rec->recognizer_version);
}
/*
* recognizer_error-Return the last error message, or nil if none.
*/
char* recognizer_error(recognizer rec)
{
/*Make sure magic numbers right and function there.*/
if( !RI_CHECK_MAGIC(rec) && the_last_error == nil ) {
return(dgettext(INTL_DOMAIN,"Bad recognizer object."));
} else if( the_last_error != nil ) {
char* error = the_last_error;
the_last_error = nil;
return(error);
}
/*Do the function.*/
return(rec->recognizer_error(rec));
}
/*
* recognizer_set_context-Set the recognition context for translation.
* Return 0 if successful, -1 if error.
*/
int recognizer_set_context(recognizer rec,rc* rec_xt)
{
/*Make sure magic numbers right.*/
if( !RI_CHECK_MAGIC(rec) ) {
the_last_error = dgettext(INTL_DOMAIN,"Bad recognizer object.");
return(-1);
}
/*Do the function.*/
return(rec->recognizer_set_context(rec,rec_xt));
}
/*
* recognzier_get_context-Get the recognition context for translation.
* If none or error, return nil.
*/
rc* recognizer_get_context(recognizer rec)
{
/*Make sure magic numbers right.*/
if( !RI_CHECK_MAGIC(rec) ) {
the_last_error = dgettext(INTL_DOMAIN,"Bad recognizer object.");
return(nil);
}
/*Do the function.*/
return(rec->recognizer_get_context(rec));
}
/*
* recognizer_clear-Clear buffer and recognition context.
* Return 0 if success, else -1.
*/
int recognizer_clear(recognizer rec,bool delete_points_p)
{
/*Make sure magic numbers right.*/
if( !RI_CHECK_MAGIC(rec) ) {
the_last_error = dgettext(INTL_DOMAIN,"Bad recognizer object.");
return(-1);
}
/*Do the function.*/
return(rec->recognizer_clear(rec,delete_points_p));
}
/*recognizer_get_buffer-Get stroke buffer. Return 0 if success, else -1.*/
int recognizer_get_buffer(recognizer rec, uint* nstrokes,Stroke** strokes)
{
/*Make sure magic numbers right.*/
if( !RI_CHECK_MAGIC(rec) ) {
the_last_error = dgettext(INTL_DOMAIN,"Bad recognizer object.");
return(-1);
}
/*Do the function.*/
return(rec->recognizer_get_buffer(rec,nstrokes,strokes));
}
/*
* recognizer_set_buffer-Set stroke buffer to arg. Return 0 if success, else
* return -1.
*/
int recognizer_set_buffer(recognizer rec,uint nstrokes,Stroke* strokes)
{
/*Make sure magic numbers right.*/
if( !RI_CHECK_MAGIC(rec) ) {
the_last_error = dgettext(INTL_DOMAIN,"Bad recognizer object.");
return(-1);
}
/*Do the function.*/
return(rec->recognizer_set_buffer(rec,nstrokes,strokes));
}
/*
* recognizer_translate-Translate the strokes in the current context, including
* buffered strokes. If nstrokes == 0 or strokes == nil, return
* translation of stroke buffer.
*/
int recognizer_translate(recognizer rec,
uint nstrokes,
Stroke* strokes,
bool correlate_p,
int* nret,
rec_alternative** ret)
{
int retval;
char msg[80];
/*Make sure magic numbers right.*/
if( !RI_CHECK_MAGIC(rec) ) {
the_last_error = dgettext(INTL_DOMAIN, msg);
return(-1);
}
/* ari */
/* {
* uint i;
* Stroke ari_pstr;
* pen_point* ari_pts;
* int ari;
* for (i = 0; i < nstrokes; i++) {
* ari_pstr = strokes[i];
* ari_pts = ari_pstr.ps_pts;
* 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);
* for (ari = 0; ari < ari_pstr.ps_npts; ari++)
* fprint(2, "%ld -- (%d, %d) ", ari_pts[ari], ari_pts[ari].x, ari_pts[ari].y);
* }
* }
*/
/*Do the function.*/
/* ari -- this is calling cmu_recognizer_translate */
retval = rec->recognizer_translate(rec,
nstrokes,
strokes,
correlate_p,
nret,
ret);
return (retval);
}
/*
* recognizer_get_extension_functions-Return a null terminated array
* of functions providing extended functionality. Their interfaces
* will change depending on the recognizer.
*/
rec_fn* recognizer_get_extension_functions(recognizer rec)
{
/*Make sure magic numbers right.*/
if( !RI_CHECK_MAGIC(rec) ) {
the_last_error = dgettext(INTL_DOMAIN,"Bad recognizer object.");
return((rec_fn*)nil);
}
/*Do the function.*/
return(rec->recognizer_get_extension_functions(rec));
}
/*
* recognizer_get_gesture_names - Return a null terminated array of
* gesture name strings.
*/
char**
recognizer_get_gesture_names(recognizer rec)
{
/*Make sure magic numbers right.*/
if( !RI_CHECK_MAGIC(rec) ) {
the_last_error = dgettext(INTL_DOMAIN,"Bad recognizer object.");
return(nil);
}
/*Do the function.*/
return(rec->recognizer_get_gesture_names(rec));
}
/*
* recognizer_set_gesture_action-Set the action function for the gesture.
*/
xgesture
recognizer_train_gestures(recognizer rec,char* name,xgesture fn,void* wsinfo)
{
/*Make sure magic numbers right.*/
if( !RI_CHECK_MAGIC(rec) ) {
the_last_error = dgettext(INTL_DOMAIN,"Bad recognizer object.");
return((xgesture)-1);
}
/*Do the function.*/
return(rec->recognizer_set_gesture_action(rec,name,fn,wsinfo));
}
/*
* Local functions.
*/
/*
* intl_initialize-Initialize the internationaliztion of messages for
* the recognition manager.
*/
static void intl_initialize(void)
{
char* dirname;
/*Get recognizer home directory name from environment.*/
if( (dirname = getenv(RECHOME)) == nil ) {
dirname = "REC_DEFAULT_HOME_DIR";
}
/*Bind the text domain.*/
USED(dirname);
bindtextdomain(dirname, INTL_DOMAIN);
}
/*make_rec_info-Create a rec_info structure*/
static rec_info* make_rec_info(char*, char*, char** subset)
{
int i,len;
rec_info* ri;
char* locale;
ri = (rec_info*)safe_malloc(sizeof(rec_info));
ri->ri_locale = nil;
ri->ri_name = nil;
ri->ri_subset = nil;
/*Get locale*/
if( (locale = getenv(LANG)) == nil ) {
locale = strdup(REC_DEFAULT_LOCALE);
}
if( (ri->ri_locale = strdup(locale)) == nil ) {
delete_rec_info(ri);
return(nil);
}
/*Get shared library pathname.*/
/*Initialize the subset information.*/
if( subset != nil ) {
/*Count the subset strings.*/
for( len = 1; subset[len] != nil; len++ ) ;
/*Copy the subset strings.*/
ri->ri_subset = (char**)safe_malloc((len +1)*sizeof(char*));
for( i = 0; i < len; i++ ) {
if( subset[i] != nil ) {
if( (ri->ri_subset[i] = strdup(subset[i])) == nil ) {
delete_rec_info(ri);
return(nil);
}
} else {
ri->ri_subset[i] = subset[i];
}
}
ri->ri_subset[i] = nil;
} else {
ri->ri_subset = nil;
}
return(ri);
}
static void delete_rec_info(rec_info* ri)
{
if( ri != nil ) {
if( ri->ri_locale != nil ) {
free(ri->ri_locale);
}
/*
* if( ri->ri_name != nil ) {
* free(ri->ri_name);
* }
*/
if( ri->ri_subset != nil ) {
int i;
for( i = 0; ri->ri_subset[i] != nil; i++) {
free(ri->ri_subset[i]);
}
free(ri->ri_subset);
}
free(ri);
}
}
/*
* Constructor functions for making structures.
*
* The general philosophy here is that we control all memory
* in connected data structures, *except* for pen_point arrays.
* There are likely to be lots and lots of points, they are likely
* to come from the window system; so if we wanted to control them,
* we would have to copy which would be slow. We require the client
* to deal with them directly, or the client can give us permission
* to delete them.
*/
/*
* recognizer
*/
recognizer make_recognizer(rec_info* rif)
{
recognizer rec;
/*Allocate it.*/
rec = (recognizer)safe_malloc(sizeof(*rec));
rec->recognizer_magic = REC_MAGIC;
rec->recognizer_version = REC_VERSION;
rec->recognizer_info = rif;
rec->recognizer_specific = nil;
rec->recognizer_end_magic = REC_END_MAGIC;
rec->recognizer_load_state = nil;
rec->recognizer_save_state = nil;
rec->recognizer_load_dictionary = nil;
rec->recognizer_save_dictionary = nil;
rec->recognizer_free_dictionary = nil;
rec->recognizer_add_to_dictionary = nil;
rec->recognizer_delete_from_dictionary = nil;
rec->recognizer_error = nil;
rec->recognizer_set_context = nil;
rec->recognizer_get_context = nil;
rec->recognizer_clear = nil;
rec->recognizer_get_buffer = nil;
rec->recognizer_set_buffer = nil;
rec->recognizer_translate = nil;
rec->recognizer_get_extension_functions = nil;
rec->recognizer_get_gesture_names = nil;
rec->recognizer_set_gesture_action = nil;
return(rec);
}
void delete_recognizer(recognizer rec)
{
if( rec != nil ) {
if( rec->recognizer_info != nil ) {
delete_rec_info(rec->recognizer_info);
}
free(rec);
}
}
/*
* rec_alternative
*/
rec_alternative* make_rec_alternative_array(uint size)
{
int i;
rec_alternative* ri;
ri = (rec_alternative*) safe_malloc(size * sizeof(rec_alternative));
for( i = 0; i < size; i++ ) {
ri[i].ra_elem.re_type = REC_NONE;
ri[i].ra_elem.re_result.aval = nil;
ri[i].ra_elem.re_conf = 0;
ri[i].ra_nalter = 0;
ri[i].ra_next = nil;
}
return(ri);
}
rec_alternative*
initialize_rec_alternative(rec_alternative* ra, uint nelm)
{
if( ra != nil ) {
if( (ra->ra_next = make_rec_alternative_array(nelm)) == nil ) {
return(nil);
}
ra->ra_nalter = nelm;
}
return(ra);
}
void delete_rec_alternative_array(uint nalter,
rec_alternative* ra,
bool delete_points_p)
{
int i;
if( ra != nil ) {
for( i = 0; i < nalter; i++ ) {
cleanup_rec_element(&ra[i].ra_elem,delete_points_p);
/*Now do the next one down the line.*/
if( ra[i].ra_nalter > 0 ) {
delete_rec_alternative_array(ra[i].ra_nalter,
ra[i].ra_next,
delete_points_p);
}
}
free(ra);
}
}
/*initialize_rec_element-Initialize a recognition element.*/
rec_element*
initialize_rec_element(rec_element* re,
char type,
uint size,
void* trans,
rec_confidence conf)
{
if( re != nil ) {
re->re_type = type;
re->re_conf = conf;
re->re_result.aval = nil;
switch (type) {
case REC_GESTURE:
if( size > 0 && trans != nil ) {
re->re_result.gval =
(gesture*)safe_malloc(sizeof(gesture));
memcpy((void*)re->re_result.gval,trans,sizeof(gesture));
}
break;
case REC_ASCII:
case REC_VAR:
case REC_OTHER:
if( size > 0 && trans != nil ) {
re->re_result.aval =
(char*)safe_malloc((size+1)*sizeof(char));
memcpy((void*)re->re_result.aval,trans,size*sizeof(char));
re->re_result.aval[size] = '\000';
}
break;
case REC_WCHAR:
if( size > 0 && trans != nil ) {
re->re_result.wval =
(wchar_t*)safe_malloc((size+1)*sizeof(wchar_t));
memcpy((void*)re->re_result.wval,trans,size*sizeof(wchar_t));
re->re_result.wval[size] = '\000';
}
break;
case REC_CORR:
if( size > 0 && trans != nil ) {
re->re_result.rcval =
(rec_correlation*)safe_malloc(sizeof(rec_correlation));
memcpy((void*)re->re_result.rcval,
trans,
sizeof(rec_correlation));
}
break;
default:
return(nil);
}
}
return(re);
}
static void cleanup_rec_element(rec_element* re,bool delete_points_p)
{
switch(re->re_type) {
case REC_NONE:
break;
case REC_ASCII:
case REC_VAR:
case REC_WCHAR:
case REC_OTHER:
free(re->re_result.aval);
break;
case REC_GESTURE:
delete_gesture_array(1,re->re_result.gval,true);
break;
case REC_CORR:
delete_rec_correlation(re->re_result.rcval,
delete_points_p);
break;
}
}
/*
* rec_correlation
*/
rec_correlation*
make_rec_correlation(char type,
uint size,
void* trans,
rec_confidence conf,
uint ps_size)
{
rec_correlation* rc;
rc = (rec_correlation*)safe_malloc(sizeof(rec_correlation));
rc->ro_nstrokes = ps_size;
/*First initialize element.*/
if( initialize_rec_element(&(rc->ro_elem),
type,
size,
trans,
conf) == nil ) {
return(nil);
}
if( (rc->ro_strokes = make_Stroke_array(ps_size)) == nil ) {
return(nil);
}
rc->ro_start = (uint*)safe_malloc(ps_size * sizeof(int));
rc->ro_stop = (uint*)safe_malloc(ps_size * sizeof(int));
return(rc);
}
void delete_rec_correlation(rec_correlation* rc,bool delete_points_p)
{
if( rc != nil ) {
cleanup_rec_element(&rc->ro_elem,delete_points_p);
delete_Stroke_array(rc->ro_nstrokes,rc->ro_strokes,delete_points_p);
if( rc->ro_start != nil ) {
free(rc->ro_start);
}
if( rc->ro_stop != nil ) {
free(rc->ro_stop);
}
free(rc);
}
}
/*
* rec_fn
*/
rec_fn* make_rec_fn_array(uint size)
{
rec_fn* ri = (rec_fn*)safe_malloc((size + 1) * sizeof(rec_fn));
int i;
for( i = 0; i < size; i++ ) {
ri[i] = nil;
}
ri[i] = nil;
return(ri);
}
void delete_rec_fn_array(rec_fn* rf)
{
if( rf != nil ) {
free(rf);
}
}
/*
* Stroke
*/
Stroke* make_Stroke_array(uint size)
{
int i;
Stroke* ri;
ri = (Stroke*) safe_malloc(size * sizeof(Stroke));
for( i = 0; i < size; i++ ) {
ri[i].npts = 0;
ri[i].pts = nil;
}
return(ri);
}
Stroke* initialize_Stroke(Stroke* ps,
uint npts,
pen_point* pts)
{
if( ps != nil ) {
ps->npts = npts;
ps->pts = pts;
}
return (ps);
}
void delete_Stroke_array(uint size,Stroke* ps,bool delete_points_p)
{
int i;
if( ps != nil ) {
for( i = 0; i < size; i++ ) {
if( delete_points_p ) {
delete_pen_point_array(ps[i].pts);
}
}
free(ps);
}
}
/*
* pen_point
*/
void delete_pen_point_array(pen_point* pp)
{
if( pp != nil ) {
free(pp);
}
}
/*
* gesture
*/
gesture*
make_gesture_array(uint size)
{
return((gesture*)safe_malloc(size * sizeof(gesture)));
}
gesture* initialize_gesture(gesture* g,
char* name,
uint nhs,
pen_point* hspots,
pen_rect bbox,
xgesture fn,
void* wsinfo)
{
if( g != nil ) {
/*We don't do points, 'cause they come from the window system.*/
g->g_nhs = nhs;
g->g_hspots = hspots;
g->g_name = strdup(name);
g->g_bbox = bbox;
g->g_action = fn;
g->g_wsinfo = wsinfo;
}
return(g);
}
void
delete_gesture_array(uint size,gesture* ga,bool delete_points_p)
{
int i;
if( ga != nil ) {
for( i = 0; i < size; i++ ) {
free(ga[i].g_name);
if( delete_points_p ) {
delete_pen_point_array(ga[i].g_hspots);
}
}
free(ga);
}
}
/*
* copy fns for stroke buffer management.
*/
static Stroke*
copy_Stroke(Stroke* ps1,Stroke* ps2)
{
initialize_Stroke(ps1,
ps2->npts,
ps2->pts);
return(ps1);
}
Stroke*
copy_Stroke_array(uint nstrokes,
Stroke* strokes)
{
int i;
Stroke* ps = make_Stroke_array(nstrokes);
if( ps != nil ) {
for( i = 0; i < nstrokes; i++ ) {
copy_Stroke(&ps[i],&strokes[i]);
}
}
return(ps);
}
uint*
copy_state_trans_array(uint ntrans,uint* trans)
{
uint* pt = (uint*)safe_malloc(ntrans*sizeof(uint));
int i;
for( i = 0; i < ntrans; i++ ) {
pt[i] = trans[i];
}
return(pt);
}
Stroke*
concatenate_Strokes(int nstrokes1,
Stroke* strokes1,
int nstrokes2,
Stroke* strokes2,
int* nstrokes3,
Stroke** strokes3)
{
int i;
int ns;
Stroke* ps;
/*Measure new strokes*/
ns = nstrokes1 + nstrokes2;
/*Allocate memory*/
if( (ps = make_Stroke_array(ns)) == nil ) {
return(nil);
}
/*Copy old ones into new.*/
for( i = 0; i < nstrokes1; i++ ) {
if( copy_Stroke(&ps[i],&strokes1[i]) == nil ) {
delete_Stroke_array(ns,ps,false);
return(nil);
}
}
for( ; i < ns; i++ ) {
if( copy_Stroke(&ps[i],&strokes2[i - nstrokes1]) == nil ) {
delete_Stroke_array(ns,ps,false);
return(nil);
}
}
*nstrokes3 = ns;
*strokes3 = ps;
return(ps);
}