/* -------- coll.c -- the collection object --------------- */ #include "ext.h" #include "edit.h" #include "ext_wind.h" #include "ext_common.h" #include "ext_strings.h" #define C_EMBED 1 /* ddz 06/09/94: * fixed interspersed (entremele) use of next and prev messages * added assistance for third outlet * prototyped functions and removed voids * fixed truncating on sorts */ /* sde use to fill the read and write flags */ #define FILE_DIALOG 1 /* use dialogs to get file name */ #define FILE_NAMED 2 /* symbol specifies file name */ #define Index_Integer 1 #define Index_Symbol 2 typedef struct celem { /* doubly linked list element */ short e_size; short e_extra; long e_index; Symbol *e_assoc; struct celem *e_next; struct celem *e_prev; Atom e_data[1]; /* dummy */ } CElem; typedef struct xcoll { Object c_ob; CElem c_head; /* head of list elements */ CElem *c_next; /* element to be returned by "next" */ CElem *c_prev; /* element to be returned by "prev" */ void *c_out2; /* next "end" signal outlet */ char c_read,c_write;/* flags for reading & writing */ char c_freeing,c_saveme; char c_embed; /* embed in owning patcher? */ Symbol *c_sym; /* associated symbol? */ struct ed *c_edit; /* edit window */ short c_refcount; /* reference count */ struct coll *c_refcoll; /* list of "colls" that reference this xcoll */ /* sde filename, volume, and MAX type */ Symbol *c_fn; short c_vol; short c_bin; short c_writevol; short c_modified; long c_filetype; } XColl; typedef struct coll { Object c_ob; XColl *c_x; Symbol *c_sym; void *c_out2; /* sde third outlet bangs after reading data */ void *c_out3; void *c_out4; struct coll *c_nextref; /* next in the list of colls that share this coll's xcoll */ void *c_owner; } Coll; #define coll_first(x) ((x)->c_head.e_next) /* sde new messages: read sym -- read a named file write sym -- write a named file writeagain -- write to most recently accessed file, or default to "write" if none readagain -- read from most recently accessed file, or default to "read" if none */ /* messages: read -- read a file into coll write -- write to a file clear -- erase everything delete or get rid of thing assoc with symbol or at index, if index, decrement anything past it ? assoc associate symbol with index ? deassoc de-associate symbol with index store --add data at end, associated with sym list add data associated with index first element, replacing thing at index int retreive data at index symbol retreive data at symbol insert insert data at index, incrementing the other indices if necessary remove delete (as above) without decrementing dump send out all messages in order, addresses out right outlet next get next element (circular, but outputs 0 at end) ? goto or set next pointer to that element -- append just insert the list at the end -- bang same as next merge or add elements to existing thing, or like store if it doesn't exist nth gets nth value from or length returns a count of the items (currently slow) prev like next, but goes backwards end goto end refer allow a coll to refer to another xcoll save store in a patcher info dialog to set embed flag, report number of items flags set coll flags (used in saving) sub retreive message with argument substitution (oooh) subsym change the associated symbol X to Y swap swap the data associated with the two symbols or ints sort 1 - ascending order, -1 descending order. Numbers are done first, then symbols, in alpha order min return minimum value max return maxmimum value nstore -- add data at end, associated with sym & num renumber changes the numeric addresses of each successive data element to a consecutive increasing value, starting at */ Object *xc_freelist; Maxclass xc_class; Messlist xc_messlist[6]; long insort; void *coll_class; Symbol *ps_list,*ps_int,*ps_sym,*ps_float,*ps_nothing,*ps_tab,*ps_store, *ps_nstore,*ps_sub; void xc_setup(void); void *outlet_atom(void *out, Atom *at); void argerror(char *s); void texterror(char *name, short line); CElem *celem_new(short numElements, Atom *initial); CElem *celem_clone(CElem *x); void celem_free(CElem *x); CElem *celem_nth(XColl *x, long n); CElem *celem_symth(XColl *x, Symbol *s); CElem *celem_atomth(XColl *x, Atom *a); void celem_setindex(CElem *x, long index); void celem_setassoc(CElem *x, Symbol *s); void coll_int(Coll *x, long n); void *celem_out(Coll *x, CElem *c); void *celem_outadd(Coll *x, CElem *c); CElem *xcoll_last(XColl *x); void coll_end(Coll *xx); void coll_next(Coll *xx); CElem *coll_nlink(XColl *x, long n, short ac, Atom *av, short replace); CElem *coll_slink(XColl *x, Symbol *s, short ac, Atom *av, short replace); void coll_addto(XColl *x, CElem *old, short ac, Atom *av); void coll_substelem(XColl *x, CElem *new, CElem *old); void coll_insertelem(XColl *x, CElem *new, CElem *was); void celem_ins(CElem *new, CElem *was); void celem_aft(CElem *new, CElem *was); void coll_appendelem(XColl *x, CElem *new); void coll_putelem(XColl *x, CElem *new); void coll_unlink(XColl *x, CElem *del); void coll_store(Coll *xx, Symbol *s, short ac, Atom *av); void coll_nstore(Coll *xx, Symbol *s, short ac, Atom *av); void coll_list(Coll *xx, Symbol *s, short ac, Atom *av); void coll_nth(Coll *xx, Symbol *s, short ac, Atom *av); void coll_merge(Coll *xx, Symbol *s, short ac, Atom *av); void coll_symbol(Coll *xx, Symbol *s); void coll_clear(Coll *xx); void xcoll_clear(XColl *x); void coll_delete(Coll *xx, Symbol *s, short ac, Atom *av); void coll_remove(Coll *xx, Symbol *s, short ac, Atom *av); void coll_goto(Coll *xx, Symbol *s, short ac, Atom *av); void coll_insert(Coll *xx, Symbol *s, short ac, Atom *av); void coll_assoc(Coll *xx, Symbol *s, long n); void coll_deassoc(Coll *xx, Symbol *s, long n); void coll_append(Coll *xx, Symbol *s, short ac, Atom *av); void coll_dump(Coll *xx); void coll_read(Coll *xx, Symbol *s); void coll_write(Coll *xx, Symbol *s); /* sde */ void coll_writeagain (Coll *xx); void coll_readagain (Coll *xx); void coll_save(Coll *xx, void *w, long n); void xcoll_dirty(XColl *x); void coll_pstate(Coll *xx, void *w); void coll_qfn(XColl *x); void coll_length(Coll *xx); void coll_prev(Coll *xx); void coll_doread(XColl *x); void coll_dowrite(XColl *x); void *coll_new(Symbol *s); void *xcoll_new(Symbol *s); void xcoll_delink(XColl *x); void coll_filetype(Coll *x, t_symbol *s); void coll_free(Coll *x); void xcoll_free(XColl *x); void coll_dblclick(Coll *xx); void xcoll_edclose(XColl *x, char **ht, long size); void coll_assist(Coll *x, long b, long m, long a, char *s); void coll_totext(XColl *x, Handle han, long *size); void coll_tobinbuf(XColl *x, void *b); void coll_fromtext(XColl *x, Handle han, long size); void xcoll_okclose(XColl *x, char *s, short *result); void coll_open(Coll *xx); void coll_wclose(Coll *xx); void coll_dowclose(Coll *xx); void coll_refer(Coll *x, Symbol *s); void coll_flags(Coll *x, long n1, long n2); void coll_sub(Coll *x, Symbol *s, short argc, Atom *argv); void coll_anything(Coll *x, Symbol *s, short argc, Atom *argv); short xcoll_edsave(XColl *x, char **ht, long size, char *fn, short vol); void xcoll_edeval(XColl *x, char **ht, long size); void coll_subsym(Coll *x, Symbol *s1, Symbol *s2); void coll_swap(Coll *x, Symbol *s, short argc, Atom *argv); void coll_sort(Coll *x, long way, long what); short coll_scompare(long a, long b); short coll_icompare(long a, long b); void coll_min(Coll *x,long index); void coll_max(Coll *x,long index); void coll_renumber(Coll *x,long start); void coll_fromfile(XColl *x,char *name,short vol,OSType type); void HiliteDefaultButton(DialogPtr dlg); void SetDlgItem(DialogPtr dlg, short item, short val, short hilite); void celem_swap(XColl *x, CElem *c1, CElem *c2); void celem_superswap(XColl *x, CElem *c1, CElem *c2); void coll_finished_reading(XColl *x); void xcoll_deref(XColl *x, Coll *xx); void xcoll_refer(XColl *x, Coll *xx); void coll_sswap(long a, long b); short coll_setfileinfo(char *fn, short vol, long type); void main() { setup((t_messlist **)&coll_class, (method)coll_new, (method)coll_free, (short)sizeof(Coll), 0L, A_DEFSYM, 0); addint((method)coll_int); addbang((method)coll_next); addmess((method)coll_list, "list", A_GIMME,0); addmess((method)coll_symbol, "symbol", A_SYM,0); addmess((method)coll_read, "read", A_DEFSYM,0); addmess((method)coll_write, "write", A_DEFSYM,0); /* sde */ addmess((method)coll_writeagain,"writeagain",0); addmess((method)coll_readagain, "readagain",0); addmess((method)coll_insert, "insert", A_GIMME,0); addmess((method)coll_delete, "delete", A_GIMME,0); addmess((method)coll_remove, "remove", A_GIMME,0); addmess((method)coll_assoc, "assoc", A_SYM,A_LONG,0); addmess((method)coll_deassoc, "deassoc", A_SYM,A_LONG,0); addmess((method)coll_next, "next", 0); addmess((method)coll_store, "store", A_GIMME,0); addmess((method)coll_nstore, "nstore", A_GIMME,0); addmess((method)coll_clear, "clear", 0); addmess((method)coll_dump, "dump", 0); addmess((method)coll_goto, "goto", A_GIMME,0); addmess((method)coll_merge, "merge", A_GIMME,0); /* addmess(coll_append, "append", A_GIMME,0); */ addmess((method)coll_dblclick, "dblclick", A_CANT, 0); addmess((method)coll_nth, "nth", A_GIMME,0); addmess((method)coll_length, "length", 0); addmess((method)coll_end, "end", 0); addmess((method)coll_prev, "prev", 0); addmess((method)coll_refer, "refer", A_SYM,0); addmess((method)coll_save, "save", A_CANT,0); addmess((method)inspector_open, "info", A_CANT,0); addmess((method)coll_flags, "flags", A_LONG, A_LONG, 0); addmess((method)coll_sub, "sub", A_GIMME,0); addmess((method)coll_sub, "nsub", A_GIMME,0); addmess((method)coll_subsym, "subsym", A_SYM, A_SYM, 0); addmess((method)coll_sort, "sort", A_LONG,A_DEFLONG,0); addmess((method)coll_swap, "swap", A_GIMME,0); addmess((method)coll_min, "min", A_DEFLONG, 0); addmess((method)coll_max, "max", A_DEFLONG, 0); addmess((method)coll_renumber, "renumber", A_DEFLONG, 0); addmess((method)coll_anything, "anything", A_GIMME,0); addmess((method)coll_assist, "assist", A_CANT,0); addmess((method)coll_pstate, "pstate", A_CANT, 0); addmess((method)coll_open, "open", 0); addmess((method)coll_wclose, "wclose", 0); addmess((method)coll_filetype, "filetype", A_SYM, 0); ps_list = gensym("list"); ps_int = gensym("int"); ps_sym = gensym("symbol"); ps_float = gensym("float"); ps_nothing = gensym(""); ps_tab = gensym("#T"); ps_store = gensym("store"); ps_nstore = gensym("nstore"); ps_sub = gensym("sub"); finder_addclass("Data","coll"); xc_setup(); rescopy('STR#',3039); insort = 0; } void xc_setup(void) { xc_class.c_sym = ps_nothing; xc_class.c_freelist = &xc_freelist; xc_class.c_freefun = (method)xcoll_free; xc_class.c_size = sizeof(XColl); xc_class.c_tiny = 0; xc_class.c_noinlet = 1; xc_messlist[0].m_sym = (Symbol *)&xc_class; xc_messlist[1].m_sym = gensym("edclose"); xc_messlist[1].m_fun = (method)xcoll_edclose; xc_messlist[1].m_type[0] = A_CANT; xc_messlist[1].m_type[1] = 0; xc_messlist[2].m_sym = gensym("okclose"); xc_messlist[2].m_fun = (method)xcoll_okclose; xc_messlist[2].m_type[0] = A_CANT; xc_messlist[2].m_type[1] = 0; xc_messlist[3].m_sym = gensym("edsave"); xc_messlist[3].m_fun = (method)xcoll_edsave; xc_messlist[3].m_type[0] = A_CANT; xc_messlist[3].m_type[1] = 0; xc_messlist[4].m_sym = gensym("edeval"); xc_messlist[4].m_fun = (method)xcoll_edeval; xc_messlist[4].m_type[0] = A_CANT; xc_messlist[4].m_type[1] = 0; xc_messlist[5].m_sym = 0; } void argerror(char *s) { error("coll: bad arguments for message \'%s\'",s); } void texterror(char *name, short line) { error("coll: %s: errors in text file in line %ld",name,(long)line); } CElem *celem_new(short numElements, Atom *initial) { CElem *n; short size; register short i; size = sizeof(CElem)+((numElements-1)*sizeof(Atom)); n = (CElem *)getbytes(size); n->e_size = numElements; n->e_index = 0; n->e_extra = 0; n->e_assoc = 0; n->e_next = 0; n->e_prev = 0; if (!initial) { for (i=0; i < numElements; i++) SETLONG(n->e_data+i,0); } else { for (i=0; i < numElements; i++) n->e_data[i] = *(initial++); } return (n); } CElem *celem_clone(CElem *x) { CElem *n; short i,size = sizeof(CElem) + ((x->e_size-1) * sizeof(Atom)); n = (CElem *)getbytes(size); n->e_size = x->e_size; n->e_extra = x->e_extra; n->e_index = x->e_index; n->e_assoc = x->e_assoc; n->e_next = 0; n->e_prev = 0; for (i=0; i < x->e_size; i++) n->e_data[i] = x->e_data[i]; return n; } void celem_free(CElem *x) { short size; size = sizeof(CElem)+((x->e_size-1)*sizeof(Atom)); freebytes(x,size); } CElem *celem_nth(XColl *x, long n) { register CElem *f; for (f = coll_first(x); f; f = f->e_next) { if ((f->e_extra & Index_Integer) && f->e_index==n) return (f); } return (0); } CElem *celem_symth(XColl *x, Symbol *s) { register CElem *f; for (f = coll_first(x); f; f = f->e_next) { if ((f->e_extra & Index_Symbol) && f->e_assoc==s) return (f); } return (0); } CElem *celem_atomth(XColl *x, Atom *a) { if (a->a_type==A_LONG) return (celem_nth(x,a->a_w.w_long)); else if (a->a_type==A_SYM) return (celem_symth(x,a->a_w.w_sym)); else if (a->a_type==A_FLOAT) return (celem_nth(x,(long)a->a_w.w_float)); } void celem_setindex(CElem *x, long n) { x->e_index = n; x->e_extra |= Index_Integer; } void celem_setassoc(CElem *x, Symbol *s) { x->e_assoc = s; x->e_extra |= Index_Symbol; } void coll_int(Coll *xx, long n) { CElem *f,*fc; XColl *x; short ac; x = xx->c_x; if (f = celem_nth(x,n)) { x->c_modified = false; celem_outadd(xx,f); if (x->c_modified) { if (f = celem_nth(x,n)) celem_out(xx,f); } else celem_out(xx,f); } } void *celem_out(Coll *x, CElem *c) { if (c->e_size==1) return (outlet_atom(x->c_ob.o_outlet,c->e_data)); else if (c->e_data->a_type==A_SYM) return (outlet_anything(x->c_ob.o_outlet,c->e_data->a_w.w_sym,c->e_size-1,c->e_data+1)); else return (outlet_list(x->c_ob.o_outlet,ps_list,c->e_size,c->e_data)); } void *celem_outadd(Coll *x, CElem *c) { Atom assoc; void *res; assoc.a_type = A_NOTHING; res = (void *)1; if (c->e_extra & Index_Integer) SETLONG(&assoc,c->e_index); else if (c->e_extra & Index_Symbol) SETSYM(&assoc,c->e_assoc); else SETLONG(&assoc,0L); if (assoc.a_type) res = outlet_atom(x->c_out2,&assoc); return (res); } void *outlet_atom(void *out, Atom *at) { if (at->a_type==A_LONG) return (outlet_int(out,at->a_w.w_long)); else if (at->a_type==A_FLOAT) return (outlet_float(out,at->a_w.w_float)); else if (at->a_type==A_SYM) return (outlet_anything(out,ps_sym,1,at)); else return ((void *)1); } void coll_next(Coll *xx) { CElem *f,*p; XColl *x; x = xx->c_x; if (!x->c_next || (x->c_next == &x->c_head)) { if (!(f = coll_first(x))) { return; } x->c_next = f; f = f->e_next; p = xcoll_last(x); } else { f = x->c_next->e_next; p = x->c_next->e_prev; } celem_outadd(xx,x->c_next); celem_out(xx,x->c_next); x->c_next = f; x->c_prev = p; } void coll_end(Coll *xx) { XColl *x; x = xx->c_x; x->c_next = x->c_prev = xcoll_last(x); } CElem *xcoll_last(XColl *x) { CElem *f,*p; for (f = coll_first(x),p = 0; f; p = f,f = f->e_next) ; return (p); } void coll_prev(Coll *xx) { CElem *f,*n; XColl *x; x = xx->c_x; if ((!x->c_prev) || (x->c_prev==&x->c_head)) { if (!(f = xcoll_last(x))) { return; } x->c_prev = f; f = f->e_prev; n = coll_first(x); } else { f = x->c_prev->e_prev; n = x->c_prev->e_next; } celem_outadd(xx,x->c_prev); celem_out(xx,x->c_prev); x->c_prev = f; x->c_next = n; } CElem *coll_nlink(XColl *x, long n, short ac, Atom *av, short replace) { register CElem *f,*new; new = celem_new(ac,av); celem_setindex(new,n); f = coll_first(x); if (!f) { coll_first(x) = new; new->e_prev = &x->c_head; } else { f = celem_nth(x,n); if (replace && f) coll_substelem(x,new,f); else if (f && !replace) coll_insertelem(x,new,f); else coll_putelem(x,new); } return (new); } CElem *coll_slink(XColl *x, Symbol *s, short ac, Atom *av, short replace) { register CElem *f,*new; new = celem_new(ac,av); celem_setassoc(new,s); f = coll_first(x); if (!f) { coll_first(x) = new; new->e_prev = &x->c_head; } else { if (s) f = celem_symth(x,s); else f = 0; if (replace && f) coll_substelem(x,new,f); else coll_appendelem(x,new); } return (new); } void coll_addto(XColl *x, CElem *old, short ac, Atom *av) { short size; CElem *new; register short i; size = old->e_size + ac; new = celem_new(size,0L); new->e_assoc = old->e_assoc; new->e_index = old->e_index; new->e_size = size; new->e_extra = old->e_extra; for (i=0; i < old->e_size; i++) new->e_data[i] = old->e_data[i]; for (i=0; i < ac; i++) new->e_data[i+old->e_size] = *(av+i); coll_substelem(x,new,old); } void coll_substelem(XColl *x, CElem *new, CElem *old) { new->e_next = old->e_next; new->e_prev = old->e_prev; if (new->e_next) new->e_next->e_prev = new; if (new->e_prev) new->e_prev->e_next = new; if (x->c_next==old) x->c_next = old->e_next; if (x->c_prev==old) x->c_prev = old->e_prev; celem_free(old); } void coll_insertelem(XColl *x, CElem *new, CElem *was) { register CElem *f; celem_ins(new,was); for (f = was; f; f = f->e_next) if (f->e_index) f->e_index++; } void celem_ins(CElem *new, CElem *was) { new->e_next = was; new->e_prev = was->e_prev; if (was->e_prev) was->e_prev->e_next = new; was->e_prev = new; } void celem_aft(CElem *new, CElem *was) { new->e_prev = was; new->e_next = was->e_next; if (was->e_next) was->e_next->e_prev = new; was->e_next = new; } void coll_appendelem(XColl *x, CElem *new) { /* eventually, keep track of the end of the list? */ register CElem *f; if (!(f = coll_first(x))) { coll_first(x) = new; new->e_prev = &x->c_head; return; } for ( ; f->e_next; f = f->e_next) ; f->e_next = new; new->e_prev = f; new->e_next = 0; } void coll_putelem(XColl *x, CElem *new) { register long index,prev; register CElem *f,*p; index = new->e_index; prev = 0; for (f = coll_first(x); f; ) { if (f->e_extra & Index_Integer) { if (InRange(index,prev,f->e_index)) { celem_ins(new,f); return; } p = f; prev = f->e_index; f = f->e_next; } else { p = f; f = f->e_next; } } if (!p) { p = coll_first(x); prev = p->e_index; } if (prev > index) celem_ins(new,p); else celem_aft(new,p); } void coll_unlink(XColl *x, CElem *del) { if (del->e_prev) del->e_prev->e_next = del->e_next; if (del->e_next) del->e_next->e_prev = del->e_prev; if (x->c_next==del) x->c_next = del->e_next; if (x->c_prev==del) x->c_prev = del->e_prev; celem_free(del); } /* because double-link swapping is so difficult, the contents of c1 and c2 are swapped instead */ void celem_swap(XColl *x, CElem *c1, CElem *c2) { Atom temp; CElem *new1,*new2; long tempIndex; short tempSize,tempExtra; Symbol *tempAssoc; register short i; if (c1->e_size != c2->e_size) { /* asymmetric case */ new1 = celem_new(c2->e_size,c2->e_data); new1->e_index = c2->e_index; new1->e_assoc = c2->e_assoc; new1->e_extra = c2->e_extra; new2 = celem_new(c1->e_size,c1->e_data); new2->e_index = c1->e_index; new2->e_assoc = c1->e_assoc; new2->e_extra = c1->e_extra; coll_substelem(x,new1,c1); coll_substelem(x,new2,c2); } else { tempAssoc = c1->e_assoc; tempIndex = c1->e_index; tempExtra = c1->e_extra; c1->e_assoc = c2->e_assoc; c1->e_index = c2->e_index; c1->e_extra = c2->e_extra; c2->e_assoc = tempAssoc; c2->e_index = tempIndex; c2->e_extra = tempExtra; for (i=0; i < c2->e_size; i++) { temp = c1->e_data[i]; c1->e_data[i] = c2->e_data[i]; c2->e_data[i] = temp; } } } void celem_superswap(XColl *x, CElem *c1, CElem *c2) { CElem *t1 = celem_clone(c1); CElem *t2 = celem_clone(c2); coll_substelem(x, t1, c2); coll_substelem(x, t2, c1); } void coll_store(Coll *xx, Symbol *s, short ac, Atom *av) { XColl *x; x = xx->c_x; if (ac < 2) goto err; if (av->a_type==A_LONG) /* store at index */ coll_nlink(x,av->a_w.w_long,ac-1,av+1,TRUE); else if (av->a_type==A_SYM) coll_slink(x,av->a_w.w_sym,ac-1,av+1,TRUE); else goto err; xcoll_dirty(x); return; err: argerror("store"); } void coll_nstore(Coll *xx, Symbol *s, short ac, Atom *av) { XColl *x; CElem *n,*n2; x = xx->c_x; if (ac < 3) goto err; if (av->a_type==A_LONG && (av+1)->a_type==A_SYM) { /* store at index */ n2 = celem_symth(x,(av+1)->a_w.w_sym); if (n2) coll_unlink(x,n2); n = coll_nlink(x,av->a_w.w_long,ac-2,av+2,TRUE); celem_setassoc(n,(av+1)->a_w.w_sym); } else if (av->a_type==A_SYM && (av+1)->a_type==A_LONG) { n2 = celem_nth(x,(av+1)->a_w.w_long); if (n2) coll_unlink(x,n2); n = coll_slink(x,av->a_w.w_sym,ac-2,av+2,TRUE); celem_setindex(n,(av+1)->a_w.w_long); } else goto err; xcoll_dirty(x); return; err: argerror("nstore"); } void coll_list(Coll *xx, Symbol *s, short ac, Atom *av) { XColl *x; x = xx->c_x; if (ac < 2) goto err; if (av->a_type==A_LONG) coll_nlink(x,av->a_w.w_long,ac-1,av+1,TRUE); else goto err; xcoll_dirty(x); return; err: argerror("list"); } void coll_nth(Coll *xx, Symbol *s, short ac, Atom *av) { XColl *x; CElem *c; long dex; x = xx->c_x; if (ac < 2 || (av+1)->a_type != A_LONG) goto err; dex = (av+1)->a_w.w_long; if (av->a_type==A_LONG) c = celem_nth(x,av->a_w.w_long); else if (av->a_type==A_SYM) c = celem_symth(x,av->a_w.w_sym); else goto err; if (c && (c->e_size >= dex)) { outlet_atom(xx->c_ob.o_outlet,c->e_data+(dex-1)); } return; err: argerror("nth"); } void coll_merge(Coll *xx, Symbol *s, short ac, Atom *av) { CElem *f; long nn; Symbol *ss; XColl *x; x = xx->c_x; if (ac < 2) goto err; if (av->a_type==A_LONG) { nn = av->a_w.w_long; f = celem_nth(x,nn); if (!f) coll_nlink(x,nn,ac-1,av+1,TRUE); else coll_addto(x,f,ac-1,av+1); } else if (av->a_type==A_SYM) { ss = av->a_w.w_sym; f = celem_symth(x,ss); if (!f) coll_slink(x,ss,ac-1,av+1,TRUE); else coll_addto(x,f,ac-1,av+1); } else goto err; xcoll_dirty(x); return; err: argerror("merge"); } void coll_symbol(Coll *xx, Symbol *s) { CElem *f; XColl *x; x = xx->c_x; if (f = celem_symth(x,s)) { x->c_modified = false; celem_outadd(xx,f); if (x->c_modified) { if (f = celem_symth(x,s)) celem_out(xx,f); } else celem_out(xx,f); } } void coll_anything(Coll *xx, Symbol *s, short ac, Atom *av) { coll_symbol(xx,s); } void coll_clear(Coll *xx) { XColl *x; x = xx->c_x; xcoll_clear(x); } void xcoll_clear(XColl *x) { CElem *f,*p; if (!(f = coll_first(x))) { return; } while (f) { p = f->e_next; celem_free(f); f = p; } coll_first(x) = 0; x->c_next = x->c_prev = 0; xcoll_dirty(x); } void coll_delete(Coll *xx, Symbol *s, short ac, Atom *av) { CElem *f,*next; long di; XColl *x; x = xx->c_x; if (!ac) goto err; if (av->a_type==A_LONG) { if (f = celem_nth(x,di = av->a_w.w_long)) { next = f->e_next; coll_unlink(x,f); for (; next; next = next->e_next) { if ((next->e_extra & Index_Integer) && next->e_index > di) next->e_index--; } xcoll_dirty(x); } } else if (av->a_type==A_SYM) { if (f = celem_symth(x,av->a_w.w_sym)) { coll_unlink(x,f); xcoll_dirty(x); } } else goto err; return; err: argerror("delete"); } void coll_remove(Coll *xx, Symbol *s, short ac, Atom *av) { CElem *f; XColl *x; x = xx->c_x; if (!ac) goto err; if (av->a_type==A_LONG) { if (f = celem_nth(x,av->a_w.w_long)) { coll_unlink(x,f); xcoll_dirty(x); } } else if (av->a_type==A_SYM) { if (f = celem_symth(x,av->a_w.w_sym)) { coll_unlink(x,f); xcoll_dirty(x); } } else goto err; return; err: argerror("remove"); } void coll_goto(Coll *xx, Symbol *s, short ac, Atom *av) { XColl *x; x = xx->c_x; if (!ac) goto err; if (av->a_type==A_LONG) { x->c_next = x->c_prev = celem_nth(x,av->a_w.w_long); } else if (av->a_type==A_SYM) { x->c_next = x->c_prev = celem_symth(x,av->a_w.w_sym); } else goto err; return; err: argerror("goto"); } void coll_insert(Coll *xx, Symbol *s, short ac, Atom *av) { CElem *f; XColl *x; x = xx->c_x; if (ac < 2) goto err; if (av->a_type==A_LONG) coll_nlink(x,av->a_w.w_long,ac-1,av+1,FALSE); else goto err; xcoll_dirty(x); return; err: argerror("insert"); } void coll_assoc(Coll *xx, Symbol *s, long n) { CElem *f,*g; XColl *x; x = xx->c_x; if (f = celem_nth(x,n)) { if (g = celem_symth(x,s)) if (f != g) coll_unlink(x,g); f->e_assoc = s; xcoll_dirty(x); } } void coll_deassoc(Coll *xx, Symbol *s, long n) { CElem *f,*g; XColl *x; x = xx->c_x; if (f = celem_nth(x,n)) { f->e_assoc = 0; xcoll_dirty(x); } } void coll_append(Coll *xx, Symbol *s, short ac, Atom *av) { XColl *x; x = xx->c_x; if (ac) coll_slink(x,0L,ac,av,FALSE); else argerror("append"); } void coll_sub(Coll *xx, Symbol *s, short ac, Atom *av) { CElem *f; XColl *x; short index; short putout; t_atom *key; putout = s == ps_sub; x = xx->c_x; f = 0; if (ac) { key = av; if (key->a_type==A_LONG) f = celem_nth(x,key->a_w.w_long); else if (key->a_type==A_SYM) f = celem_symth(x,key->a_w.w_sym); } else argerror("sub"); if (f) { ac--; av++; while (ac >= 2) { if (av->a_type==A_LONG) { index = av->a_w.w_long; if (index>=1 && index <= f->e_size) f->e_data[index-1] = *(av+1); } ac-=2; av+=2; } if (putout) { x->c_modified = false; celem_outadd(xx,f); if (x->c_modified) { if (key->a_type==A_LONG) f = celem_nth(x,key->a_w.w_long); else if (key->a_type==A_SYM) f = celem_symth(x,key->a_w.w_sym); if (f) celem_out(xx,f); } else celem_out(xx,f); } } } void coll_subsym(Coll *xx, Symbol *s1, Symbol *forS2) { CElem *f; XColl *x; short index; x = xx->c_x; f = celem_symth(x,forS2); if (f) f->e_assoc = s1; } void coll_swap(Coll *xx, Symbol *s, short argc, Atom *argv) { CElem *f1,*f2; XColl *x; long temp1; Symbol *temp2; short index,tempe; short err = TRUE; x = xx->c_x; if (argc==2) { f1 = celem_atomth(x,argv); if (f1) { f2 = celem_atomth(x,argv+1); if (f2) { temp1 = f2->e_index; temp2 = f2->e_assoc; tempe = f2->e_extra; f2->e_assoc = f1->e_assoc; f2->e_index = f1->e_index; f2->e_extra = f1->e_extra; f1->e_assoc = temp2; f1->e_index = temp1; f1->e_extra = tempe; err = FALSE; /* sort? */ } } } if (err) argerror("swap"); } void coll_min(Coll *xx, long index) { register CElem *f; long min = 0x7FFFFFFF; XColl *x; Boolean had; Atom an; CElem *minp; if (!index) index = 1; had = 0; minp = 0; x = xx->c_x; for (f = coll_first(x); f; f = f->e_next) { if (f->e_size >= index) { if (f->e_data[index-1].a_type==A_LONG) { if (f->e_data[index-1].a_w.w_long < min) { minp = f; min = f->e_data[index-1].a_w.w_long; } had = 1; } } } if (had) { SETLONG(&an,min); if (minp) celem_outadd(xx,minp); outlet_atom(xx->c_ob.o_outlet,&an); } } void coll_max(Coll *xx, long index) { register CElem *f; long max = -0x7FFFFFFF; XColl *x; Boolean had; Atom an; CElem *maxp; if (!index) index = 1; had = 0; maxp = 0; x = xx->c_x; for (f = coll_first(x); f; f = f->e_next) { if (f->e_size >= index) { if (f->e_data[index-1].a_type==A_LONG) { if (f->e_data[index-1].a_w.w_long > max) { max = f->e_data[index-1].a_w.w_long; maxp = f; } had = 1; } } } if (had) { SETLONG(&an,max); if (maxp) celem_outadd(xx,maxp); outlet_atom(xx->c_ob.o_outlet,&an); } } void coll_renumber(Coll *xx, long start) { register CElem *f; register long inc; XColl *x; x = xx->c_x; inc = 0; for (f = coll_first(x); f; f = f->e_next) { if (f->e_extra & Index_Integer) f->e_index = start + inc++; } } void coll_dump(Coll *xx) { register CElem *f; XColl *x; x = xx->c_x; for (f = coll_first(x); f; f = f->e_next) { x->c_modified = false; if (!celem_outadd(xx,f)) break; if (x->c_modified) // self-modify on dump not allowed break; if (!celem_out(xx,f)) break; } outlet_bang(xx->c_out4); } void coll_length(Coll *xx) { XColl *x; register CElem *f; register long n; Atom an; x = xx->c_x; for (n = 0, f = coll_first(x); f; f = f->e_next, n++) ; SETLONG(&an,n); outlet_atom(xx->c_ob.o_outlet,&an); } void coll_read(Coll *xx, Symbol *s) { XColl *x; x = xx->c_x; /* sde */ if (s->s_name[0]) { x->c_read = FILE_NAMED; x->c_fn=s; } else /* same as it ever was... */ { x->c_read = FILE_DIALOG; } defer(x,(method)coll_doread,0,0,0); } void coll_write(Coll *xx, Symbol *s) { XColl *x; x=xx->c_x; /* sde I originally expected s to be 0 if not used, but incorrecto, check first char*/ if (s->s_name[0]) { x->c_write = FILE_NAMED; x->c_fn=s; x->c_writevol = 0; } else /* same as it ever was... */ { x->c_write = FILE_DIALOG; } defer(x,(method)coll_dowrite,0,0,0); } /* sde new function */ void coll_writeagain(Coll *xx) { XColl *x; x=xx->c_x; if (x->c_fn->s_name[0]) x->c_write = FILE_NAMED; /* use the name we already have */ else x->c_write = FILE_DIALOG; /* put up sfput */ defer(x,(method)coll_dowrite,0,0,0); } /* sde new function */ void coll_readagain(Coll *xx) { XColl *x; x=xx->c_x; if (x->c_fn->s_name[0]) x->c_read = FILE_NAMED; /* use the name we already have */ else x->c_read = FILE_DIALOG; /* put up sfget */ defer(x,(method)coll_doread,0,0,0); } /* sde new function */ void coll_finished_reading(XColl *x) { Coll *xx; short savelock; xx = x->c_refcoll; while (xx) { savelock = lockout_set(1); outlet_bang (xx->c_out3); lockout_set(savelock); xx = xx->c_nextref; } } void coll_doread(XColl *x) { long types[4]; short vol,numtypes = 2; long i; long type; char name[256]; name[0] = 0; types[0]='TEXT'; types[1]='maxb'; /* sde Check the flag type...*/ if (x->c_read==FILE_DIALOG) { if (x->c_filetype) { types[0] = x->c_filetype; numtypes = 1; } if (!open_dialog(name, &vol, &type, types, numtypes)) { coll_fromfile(x,name,vol,type); x->c_fn = gensym(name); x->c_vol = vol; x->c_bin = type != 'TEXT'; coll_finished_reading (x); } } else if (x->c_read==FILE_NAMED) { if (x->c_filetype) { types[0] = x->c_filetype; numtypes = 1; } strcpy(name,x->c_fn->s_name); if (!locatefile_extended (name, &x->c_vol, &type, types, numtypes)) { coll_fromfile(x,name,x->c_vol,type); coll_finished_reading (x); } else { error("coll: can't find file %s",x->c_fn->s_name); x->c_fn = gensym(""); } } } void coll_fromfile(XColl *x, char *name, short vol, OSType type) { short lockwas; Handle ch; long size = 0; void *b = binbuf_new(); if (binbuf_read(b, name, vol, type != 'TEXT')) error("coll: error reading %s",name); else { ch = newhandle(16L); binbuf_totext(b,ch,&size); lockwas = lockout_set(1); xcoll_clear(x); coll_fromtext(x,ch,size); lockout_set(lockwas); DisposeHandle(ch); } freeobject(b); } void coll_dowrite(XColl *x) { char fn[236]; short vol, bin = 2,numtypes; long types[2],type; short *bp = &bin; if (x->c_write==FILE_DIALOG) { if (x->c_filetype) { types[0] = x->c_filetype; numtypes = 1; } else { types[0] = 'TEXT'; types[1] = 'maxb'; numtypes = 2; } strcpy(fn, ""); if (!saveasdialog_extended(fn, &vol, &type, types, numtypes)) { void *b = binbuf_new(); coll_tobinbuf(x,b); bin = type != 'TEXT'? 2 : 0; binbuf_write(b, fn, vol, bin); freeobject(b); if (x->c_filetype) coll_setfileinfo(fn,vol,x->c_filetype); /*sde save the new params */ x->c_bin = bin; x->c_writevol = vol; x->c_fn = gensym(fn); } } else if ( x->c_write==FILE_NAMED ) { void *b = binbuf_new(); short bin = x->c_bin; char filename[256]; coll_tobinbuf(x,b); if (bin == 1) // avoid old format write bin = 2; if (x->c_filetype) bin = x->c_filetype != 'TEXT'; binbuf_write(b, x->c_fn->s_name, x->c_writevol, bin); /* write to default volume */ if (x->c_filetype) coll_setfileinfo(x->c_fn->s_name,x->c_writevol,x->c_filetype); freeobject(b); } } void coll_save(Coll *xx, void *w, long n) { XColl *x; CElem *f; Atom at[6],*ap; short diff; long f1,f2; x = xx->c_x; SETSYM(at,ps_tab); if (x->c_sym) binbuf_vinsert(w,"sss",gensym("#N"),gensym("coll"),x->c_sym); else binbuf_vinsert(w,"ss",gensym("#N"),gensym("coll")); if (x->c_embed) { f1 = C_EMBED; f2 = 0; binbuf_vinsert(w,"ssll",ps_tab,gensym("flags"),f1,f2); for (f = coll_first(x); f; f = f->e_next) { ap = at+1; if (f->e_extra == (Index_Integer + Index_Symbol)) { /* bound to number & symbol */ SETSYM(ap,ps_nstore); ap++; SETSYM(ap,f->e_assoc); ap++; SETLONG(ap,f->e_index); ap++; } else if (f->e_extra & Index_Symbol) { /* bound to symbol */ SETSYM(ap,ps_store); ap++; SETSYM(ap,f->e_assoc); ap++; } else { /* bound to number only */ SETLONG(ap,f->e_index); ap++; } diff = ap - at; binbuf_append(w,ps_nothing,diff,at); binbuf_insert(w,ps_nothing,f->e_size,f->e_data); } } } void coll_pstate(Coll *xx, void *w) { XColl *x; x = xx->c_x; binbuf_vinsert(w,"sl", gensym("coll"), x->c_embed? 1 : 0); } void xcoll_dirty(XColl *x) { Coll *s; x->c_modified = true; if (x->c_embed) { for (s = x->c_refcoll; s; s = s->c_nextref) { if (s->c_owner && ispatcher(s->c_owner)) patcher_dirty(s->c_owner); } } } void xcoll_deref(XColl *x, Coll *xx) { Coll *s,*prev; for (prev = 0,s = x->c_refcoll; s; prev = s, s = s->c_nextref) { if (s==xx) { if (prev) prev->c_nextref = s->c_nextref; else x->c_refcoll = s->c_nextref; } } xx->c_nextref = 0; } void xcoll_refer(XColl *x, Coll *xx) { Coll *s; /* avoid duplicate references */ for (s = x->c_refcoll; s; s = s->c_nextref) { if (s == xx) { post("coll bug: duplicate refer, bagging"); return; } } xx->c_nextref = x->c_refcoll; x->c_refcoll = xx; } void coll_flags(Coll *xx, long n1, long n2) { xx->c_x->c_embed = n1 & C_EMBED ? 1 : 0; } void *coll_new(Symbol *s) { Coll *xx; XColl *x; short vol,bin; if (s != ps_nothing && s->s_thing) { if (ob_messlist(s->s_thing) != xc_messlist) { error("coll: name %s in use",s->s_name); return (0); } else { x = (XColl *)s->s_thing; x->c_refcount++; } } else { x = xcoll_new(s); /* sde initialize file params */ x->c_fn = ps_nothing; x->c_vol = x->c_bin = x->c_writevol = 0; if (s != ps_nothing) { s->s_thing = (Object *)x; /* try to find a file named s->s_name */ if (!locatefile(s->s_name,&vol,&bin)) { coll_fromfile(x,s->s_name,vol,bin?'maxb':'TEXT'); /* sde reset file params */ x->c_fn = s; x->c_vol = vol; x->c_bin = bin; } else { post("note: no coll file %s",s->s_name); } } } xx = newobject(coll_class); xx->c_x = x; /* sde 3d outlet used to bang after reading data */ xx->c_out4 = outlet_new(xx,0); xx->c_out3 = outlet_new (xx,0); xx->c_out2 = outlet_new(xx,0); xx->c_owner = gensym("#P")->s_thing; xcoll_refer(x,xx); outlet_new(xx,0L); ps_tab->s_thing = (Object *)xx; return (xx); } void *xcoll_new(Symbol *s) { XColl *x; x = newobject(xc_messlist); x->c_head.e_next = 0; x->c_head.e_prev = 0; x->c_next = x->c_prev = 0; x->c_read = x->c_write = 0; x->c_freeing = x->c_saveme = 0; x->c_edit = 0; x->c_sym = s; x->c_refcount = 1; x->c_embed = 0; x->c_refcoll = 0; x->c_writevol = 0; x->c_modified = false; x->c_filetype = 0; // no custom filetype return (x); } void xcoll_delink(XColl *x) { if (--x->c_refcount <= 0) freeobject((Object *)x); } void coll_refer(Coll *x, Symbol *s) { XColl *sx; if (s != ps_nothing && s->s_thing) { if (ob_messlist(s->s_thing) == xc_messlist) { sx = (XColl *)s->s_thing; if (sx != x->c_x) { xcoll_deref(x->c_x,x); xcoll_delink(x->c_x); x->c_x = sx; sx->c_refcount++; x->c_sym = s; xcoll_refer(sx,x); } } } } void coll_filetype(Coll *xx, t_symbol *s) { static char fourspace[] = {' ',' ',' ',' '}; XColl *x = xx->c_x; // platform-specific if (s == ps_nothing) x->c_filetype = 0; else { BlockMove(fourspace,&x->c_filetype,4); BlockMove(s->s_name,&x->c_filetype,strlen(s->s_name)); // pads with spaces } } void coll_free(Coll *x) { notify_free((t_object *)x); xcoll_deref(x->c_x,x); xcoll_delink(x->c_x); } void xcoll_free(XColl *x) { x->c_freeing = TRUE; xcoll_clear(x); if (x->c_edit) freeobject((Object *)x->c_edit); if (x->c_sym) { if (x->c_sym != ps_nothing) x->c_sym->s_thing = 0; } } void coll_dblclick(Coll *xx) { Handle h; long size; char title[80]; XColl *x; x = xx->c_x; if (!x->c_edit) { x->c_edit = ed_new((Object *)x); if (x->c_fn != ps_nothing) { wind_filename(x->c_edit->e_wind,x->c_fn->s_name,x->c_vol,x->c_bin); } else { if (x->c_sym != ps_nothing) sprintf(title,"%s",x->c_sym->s_name); else sprintf(title,"Untitled"); wind_settitle(x->c_edit->e_wind,title,FALSE); } x->c_saveme = 0; h = NewHandle(4L); coll_totext(x,h,&size); ed_settext(x->c_edit,h,size); DisposeHandle(h); } else ed_vis(x->c_edit); } void coll_open(Coll *xx) { defer(xx,(method)coll_dblclick,0,0,0); } void coll_wclose(Coll *xx) { defer(xx,(method)coll_dowclose,0,0,0); } void coll_dowclose(Coll *xx) { XColl *x = xx->c_x; if (x->c_edit) { if (x->c_edit->e_wind && x->c_edit->e_wind->w_vis) wind_close(x->c_edit->e_wind); } } void xcoll_okclose(XColl *x, char *s, short *result) { sprintf(s,"Store changes to Ò%sÓ before closing?", ((struct wind *)(x->c_edit->e_wind))->w_name); switch (advise(s)) { case aaYes: x->c_saveme = 1; *result = 3; /* no dialog, don't clear dirty bit */ break; case aaNo: x->c_saveme = 0; *result = 3; break; case aaCancel: *result = 4; break; } } short xcoll_edsave(XColl *x, char **ht, long size, char *fn, short vol) { xcoll_clear(x); coll_fromtext(x,ht,size); return (0); /* didn't save it */ } void xcoll_edeval(XColl *x, char **ht, long size) { HLock(ht); post("some of this text %s",*ht); HUnlock(ht); } void xcoll_edclose(XColl *x, char **ht, long size) { if (x->c_saveme) { xcoll_clear(x); coll_fromtext(x,ht,size); x->c_saveme = 0; } x->c_edit = 0; } void coll_totext(XColl *x, Handle han, long *size) { void *b; b = binbuf_new(); coll_tobinbuf(x,b); binbuf_totext(b,han,size); freeobject(b); } void coll_tobinbuf(XColl *x, void *b) { register CElem *f; Atom at[3],*ap; short diff; for (f = coll_first(x); f; f = f->e_next) { ap = at; if (f->e_extra & Index_Integer) { SETLONG(ap,f->e_index); ap++; } if (f->e_extra & Index_Symbol) { SETSYM(ap,f->e_assoc); ap++; } SETCOMMA(ap); ap++; diff = ap - at; binbuf_append(b,ps_nothing,diff,at); binbuf_insert(b,ps_nothing,f->e_size,f->e_data); } } /* void coll_textline(Coll *x, CElem *f, Handle han, long *size) { register short i,len,p; short sl; long orig; char buf[200],*attostr(),*q; buf[0] = 0; if (f->e_index) sprintf(buf,"%ld",f->e_index); sl = strlen(buf); if (f->e_assoc) { if (sl) buf[sl++] = ' '; sprintf(buf+sl,"%s",f->e_assoc->s_name); } sl = strlen(buf); strcpy(buf+sl,", "); sl = strlen(buf); len = f->e_size; p = 0; for (i=0; i < len; i++) { q = attostr(f->e_data+i); p = strlen(q); strcpy(buf+sl,q); sl += p; } buf[sl++] = ';'; buf[sl++] = '\r'; orig = *size; (*size) += sl; growhandle(han,*size); BlockMove(buf,((Byte *)*han)+orig,(long)sl); } char *attostr(Atom *a) { static char buf[80]; short c; union word p; c = a->a_type; p = a->a_w; if (c == A_SEMI) return(";"); else if (c == A_COMMA) return(","); else if (c == A_SYM) sprintf(buf, "%s ", p.w_sym->s_name); else if (c == A_OBJ) sprintf(buf, "%s ", ob_name(p.w_obj)); else if (c == A_LONG) sprintf(buf, "%ld ",p.w_long); else if (c == A_FLOAT) sprintf(buf, "%f ", p.w_float); else if (c == A_DOLLAR) sprintf(buf, "$%ld ",p.w_long); else if (!c) return("(end)"); else return("?"); return(buf); } */ void coll_fromtext(XColl *x, Handle han, long size) { long onset = 0; char symout[256]; register short line,aCount; register CElem *build; register CElem *f; Atom at; register short atype; Boolean seenComma = FALSE; build = celem_new(1000,0L); line = 1; aCount = 0; while (readatom(symout,han,&onset,size,&at)) { atype = at.a_type; if (!seenComma) { if (atype==A_LONG) celem_setindex(build,at.a_w.w_long); else if (atype==A_SYM) celem_setassoc(build,at.a_w.w_sym); else if (atype==A_COMMA) { aCount = 0; seenComma = TRUE; } else { texterror(x->c_sym? x->c_sym->s_name : "Untitled",line); goto err; } } else { if (atype==A_LONG || atype==A_SYM || atype==A_FLOAT || atype==A_DOLLAR) { build->e_data[aCount++] = at; } else if (atype==A_SEMI) { f = celem_new(aCount,build->e_data); f->e_index = build->e_index; f->e_assoc = build->e_assoc; f->e_extra = build->e_extra; coll_appendelem(x,f); build->e_index = 0; build->e_assoc = 0; build->e_extra = 0; line++; seenComma = FALSE; } else { texterror(x->c_sym? x->c_sym->s_name : "Untitled",line); goto err; } } } if (seenComma) { texterror(x->c_sym? x->c_sym->s_name : "Untitled",line); goto err; } post("finished, %ld lines",(long)line-1); err: celem_free(build); return; } void coll_assist(Coll *x, long b, long m, long a, char *s) { assist_string(3039,m,a,1,2,s); } /* ------------------- sorting stuff ----------------------------- */ XColl *wx; long compway; long compindex; static void qsort1(long first, long last); void coll_sort(Coll *xx, long way, long what) { XColl *x; long length = 0; register CElem *f; if (insort) { error("coll: sort: not reentrant"); return; } insort = 1; x = xx->c_x; for (f = coll_first(x); f; f = f->e_next,length++) ; wx = x; compway = way; if (what <= -1) compindex = -1; else compindex = what ? what - 1 : 0; qsort1(0L,length); insort = 0; } short coll_icompare(long a, long b) { register CElem *f,*f1,*f2; long max,savea,saveb; short res; max = MAX(a,b); f1 = 0; f2 = 0; savea = a; saveb = b; for (f = coll_first(wx); f; f = f->e_next) { if (!a-- && !f1) f1 = f; if (!b-- && !f2) f2 = f; if (!max--) break; } if (!f1 || !f2) { error("coll: sort: bug in compare %ld %ld",savea,saveb); return; } if (f1->e_extra & Index_Symbol) { if (f2->e_extra & Index_Symbol) res = strcmp(f1->e_assoc->s_name,f2->e_assoc->s_name) < 0; else res = 0; } else if (f2->e_extra & Index_Symbol) /* symbols come after numbers */ res = 1; else res = f1->e_index > f2->e_index; if (compway < 0) return (res ? -1 : 1); else return (res ? 1 : -1); } short coll_scompare(long a, long b) /* painfully slow! */ { register CElem *f,*f1,*f2; long max,thing,savea,saveb; Atom *f1ap,*f2ap; double fthing; register short minsize; register short i; short res; Boolean dofloat = FALSE; if (compindex == -1) return (coll_icompare(a,b)); max = MAX(a,b); f1 = 0; f2 = 0; savea = a; saveb = b; for (i=0,f = coll_first(wx); f; f = f->e_next,i++) { if (!a-- && !f1) f1 = f; if (!b-- && !f2) f2 = f; if (!max--) break; } if (!f1 || !f2) { error("coll: sort: bug in compare %ld %ld",savea,saveb); return; } /* for now, always sort by first element */ f1ap = f1->e_data + compindex; f2ap = f2->e_data + compindex; if (compindex >= f1->e_size) f1ap = f1->e_data + f1->e_size-1; if (compindex >= f2->e_size) f2ap = f2->e_data + f2->e_size-1; if (f1ap->a_type==A_LONG) { switch (f2ap->a_type) { case A_FLOAT: dofloat = TRUE; break; case A_LONG: thing = f2ap->a_w.w_long; break; case A_SYM: res = 0; goto decide; } if (dofloat) res = f2ap->a_w.w_float > (double)f1ap->a_w.w_long; else res = thing > f1ap->a_w.w_long; } else if (f1ap->a_type==A_FLOAT) { switch (f2ap->a_type) { case A_FLOAT: dofloat = TRUE; break; case A_LONG: fthing = (double)f2ap->a_w.w_long; break; case A_SYM: res = 0; goto decide; } if (dofloat) res = f2ap->a_w.w_float > f1ap->a_w.w_float; else res = fthing > f1ap->a_w.w_float; } else if (f1ap->a_type==A_SYM) { switch (f2ap->a_type) { case A_FLOAT: case A_LONG: res = 1; break; case A_SYM: res = strcmp(f1ap->a_w.w_sym->s_name, f2ap->a_w.w_sym->s_name) < 0; break; } } else { error("coll: sort: unknown data type, %ld %ld",a,b); return; } decide: if (compway < 0) return (res ? -1 : 1); else return (res ? 1 : -1); } void coll_sswap(long a, long b) { register CElem *f; CElem *f1,*f2; long max,savea,saveb; max = MAX(a,b); f1 = 0; f2 = 0; savea = a; saveb = b; for (f = coll_first(wx); f; f = f->e_next) { if (!a-- && !f1) f1 = f; if (!b-- && !f2) f2 = f; if (!max--) break; } if (!f1 || !f2) { error("coll: sort: bug in swap %ld %ld",savea,saveb); return; } celem_superswap(wx,f1,f2); } /* * sort elements "first" through "last"-1 * */ static void qsort1(long first, long last) { static long i; /* "static" to save stack space */ long j; while (last - first > 1) { i = first; j = last; for (;;) { while (++i < last && coll_scompare(i, first) < 0) ; while (--j > first && coll_scompare(j, first) > 0) ; if (i >= j) break; coll_sswap(i, j); } if (j == first) { ++first; continue; } coll_sswap(first, j); if (j - first < last - (j + 1)) { qsort1(first, j); first = j + 1; /* qsort1(j + 1, last); */ } else { qsort1(j + 1, last); last = j; /* qsort1(first, j); */ } } } // this should be in the kernel... short coll_setfileinfo(char *fn, short vol, long type) { short err; FSSpec fs; FInfo finfo; err = path_tospec(vol,fn,&fs); if (!err) { err = FSpGetFInfo(&fs,&finfo); if (!err) { finfo.fdType = type; FSpSetFInfo(&fs,&finfo); } } return err; }