3 * Provides handling for list boxes
5 * v. 1.00 (27 July 1993)
7 * © 1993-1998 Straylight
10 /*----- Licensing note ----------------------------------------------------*
12 * This file is part of Straylight's Steel library.
14 * Steel is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2, or (at your option)
19 * Steel is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with Steel. If not, write to the Free Software Foundation,
26 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
49 extern void _dllEntry(list__events)(wimp_eventstr *e,void *handle);
52 #define list__ITEMHEIGHT 44
53 #define list__MINHEIGHT 176
56 * A structure for the list items
58 typedef struct list__item
60 struct list__item *next;
61 struct list__item *prev;
70 * A structure that says everything about a listbox
72 typedef struct list__liststr
79 list_eventhandler events;
81 list_raweventhandler rawEvents;
83 list_redrawhandler rdr;
100 static list list__dragging;
101 static int list__dragIndex;
102 static int list__currentIndex;
104 _dll_static void list__events(wimp_eventstr *e,void *handle);
107 * void list__resize(list l)
110 * This routine will resize a list box according to how many items there
114 * list l == the list handle
117 static void list__resize(list l)
124 wimp_redrawstr extent;
126 BOOL hscr=FALSE,ohscr;
127 BOOL vscr=FALSE,ovscr;
134 /* --- Find out if there's anything to do --- */
136 if (!l->wind || !l->update)
139 /* --- Get information about the window --- */
141 wimpt_noerr(wimp_get_wind_state(l->wind,&s));
142 open=s.flags & wimp_WOPEN;
143 height=l->items*l->iHeight;
144 width=maxlen=l->width+16+l->extraWidth;
146 /* --- If it's a pane listbox, add in scroll bars if necessary --- */
150 /* --- First, read the position and scroll sizes --- */
152 win_gadgetWidths(wimp_WNEW | wimp_WVSCR | wimp_WHSCR,&b);
154 /* --- Get the outline extents of the window --- */
156 ohscr=s.flags & wimp_WHSCR;
157 ovscr=s.flags & wimp_WVSCR;
158 scbh=b.y0-wimpt_dy();
159 xe=s.o.box.x1-s.o.box.x0+(ovscr ? b.x1-wimpt_dx() : 0);
160 ye=s.o.box.y1-s.o.box.y0+(ohscr ? scbh : 0);
162 /* --- Now find out if we really want scroll bars --- */
176 if (!hscr && maxlen>xe)
182 /* --- If we changed the scroll bars, recreate the window --- */
184 if (!hscr!=!ohscr || !vscr!=!ovscr)
186 /* --- Update the scroll bar flags --- */
191 /* --- Save all the window's info so we recreate it properly --- */
196 pane_removePane(p,l->wind);
199 wimpt_noerr(wimp_get_wind_info(&w));
200 menu_saveHandler(l->wind,&mhnd);
201 wimpt_noerr(wimp_delete_wind(l->wind));
202 win_register_event_handler(l->wind,0,0);
204 /* --- Set up window with new scroll bar gadgetry --- */
206 w.info.flags&=~(wimp_WHSCR | wimp_WVSCR);
208 w.info.flags|=wimp_WHSCR;
210 w.info.flags|=wimp_WVSCR;
211 w.info.flags|=wimp_WNEW;
214 wimpt_noerr(wimp_create_wind(&w.info,&l->wind));
216 /* --- Read the new outline and check the sizes again --- */
219 s.o.box.x1=s.o.box.x0+xe;
220 s.o.box.y0=s.o.box.y1-ye;
221 wimpt_noerr(wimp_open_wind(&s.o));
223 /* --- Restore everything we saved above --- */
226 wimpt_noerr(wimp_close_wind(l->wind));
227 win_register_event_handler(l->wind,_dllEntry(list__events),l);
228 menu_restoreHandler(l->wind,&mhnd);
232 xe=l->visSize.x1-l->visSize.x0;
234 /* --- Correct the extent dimensions --- */
238 if (height<ye && !l->alterSize)
240 if (height<list__MINHEIGHT-scbh)
241 height=list__MINHEIGHT-scbh;
244 extent.box.x0=l->visSize.x0;
245 extent.box.x1=l->visSize.x0+width;
246 extent.box.y0=-height;
248 l->extWidth=width; /* Remember the width of the window for redrawing */
249 wimpt_noerr(wimp_set_extent(&extent));
252 wimpt_noerr(wimp_open_wind(&s.o));
253 wimpt_noerr(wimp_force_redraw(&extent));
258 pane_addListbox(p,l);
263 * void list__rescanSize(list l)
266 * Recalculates a list box's width.
269 static void list__rescanSize(list l)
274 if (!l->wind || !l->update)
281 len=wimpt_stringWidth(itm->data);
290 * void list__event(list l,list_item clicked)
293 * Posts an event to the event handler registered for the list box (if it's
297 * list l == the list box handle
298 * list_item clicked == the item that was clicked
301 static void list__event(list l,list_item clicked)
304 (l->events)(l,clicked,l->evntHandle);
308 * void list__defaultRedraw(list l,
314 * Standard redraw handler for list boxes. This may be overridden if the
315 * list box is a fancy one.
318 * As for list redraw handlers, except that there's no handle passed to it.
321 static void list__defaultRedraw(list l,
328 icn.flags=0x00000131+(l->foreg<<24)+(l->backg<<28);
329 icn.data.indirecttext.validstring=(char *)-1;
330 icn.data.indirecttext.bufflen=0;
332 icn.flags|=wimp_ISELECTED;
334 icn.flags&=~wimp_ISELECTED;
335 icn.data.indirecttext.buffer=text;
336 wimpt_noerr(wimp_ploticon(&icn));
340 * void list__redraw(wimp_redrawstr *r,void *handle)
343 * Redraws a list box window
346 * wimp_redrawstr *r == redraw structure for this redraw event
347 * void *handle == pointer to this list box
350 static void list__redraw(wimp_redrawstr *r,void *handle)
353 list_item itm=l->list;
354 int ox=r->box.x0-r->scx;
355 int oy=r->box.y1-r->scy;
357 int first=-(r->g.y1-r->box.y1+r->scy)/l->iHeight;
358 int last=first+(r->g.y1-r->g.y0)/l->iHeight+1;
360 box.x0=l->visSize.x0;
361 box.x1=l->visSize.x0+l->extWidth;
366 if (i>=first && i<=last)
370 (l->rdr)(l,itm,r,&box,itm->data,
371 itm->selected || itm->nsel,l->redrawHandle);
374 list__defaultRedraw(l,&box,itm->data,itm->selected || itm->nsel);
381 wimpt_noerr(wimp_setcolour(l->backg));
384 bbc_rectanglefill(l->visSize.x0+ox,
385 box.y1+oy-l->iHeight*(last-i+1)-wimpt_dy(),
387 l->iHeight*(last-i+1));
392 * list_item list__coordsToItem(int x,int y,list l)
395 * Given a screen position and a list handle, returns
396 * the item beneath the point.
399 * int x == absolute OS-unit screen x-coordinate of the point
400 * int y == absolute OS-unit screen y-coordinate of the point
401 * list l == the list handle
404 * The list item handle
407 static list_item list__coordsToItem(int x,int y,list l)
414 wimpt_noerr(wimp_get_wind_state(l->wind,&state));
415 oy=state.o.box.y1-state.o.y;
416 index=-(y-oy+wimpt_dy())/l->iHeight;
418 return (list_NOITEM);
419 i=list_indexToItem(l,index);
424 * void list__selectIdles(void *handle)
427 * Gets passed idle events when dragging out a selection.
430 * void *handle == a NULL pointer
433 #define min2(x,y) ((x)<(y) ? (x) : (y))
434 #define max2(x,y) ((x)>(y) ? (x) : (y))
435 #define min3(x,y,z) min2(min2(x,y),z)
436 #define max3(x,y,z) max2(max2(x,y),z)
438 static void list__redrawItem(list l,int i);
440 static void list__selectIdles(void *handle)
442 /* --- Rewritten 24-Jun-1993 - MDW --- */
444 /* --- Variables required to update the drag --- */
445 wimp_mousestr m; /* Pointer state (window coords) */
446 wimp_wstate s; /* Position of window */
447 int ox,oy; /* Screen coords of window origin */
448 int i; /* Item index counter */
449 int start; /* Index to start processing items */
450 int end; /* Index to finish processing items */
451 int index; /* Index of item under pointer */
452 list_item item; /* List item ptr (for list traverse) */
453 int sel; /* -1 == ignore, 0 == deselect, */
458 /* --- Set up pointer position --- */
459 wimpt_noerr(wimp_get_point_info(&m)); /* I only need the coordinates */
460 wimpt_noerr(wimp_get_wind_state(list__dragging->wind,&s)); /* For origin,*/
461 /* and scrolling the window */
462 ox=s.o.box.x0-s.o.x; /* Derive position of window origin */
463 oy=s.o.box.y1-s.o.y; /* from state as per PRM */
464 m.x-=ox; /* Now convert mouse position to */
465 m.y-=oy; /* window coordinates */
466 index=-(m.y+wimpt_dy())/list__dragging->iHeight; /* Calc item under ptr */
467 if (index<0) /* Stop negative indices */
470 /* --- Set up for loop through list items --- */
471 start=min3(list__currentIndex,list__dragIndex,index);
472 end=max3(list__currentIndex,list__dragIndex,index);
473 item=list__dragging->list;
477 /* --- Now loop through the relevant icons --- */
478 while (item) /* Carry on until we run out of items*/
482 if (list__dragIndex<index)
484 if (i==list__dragIndex)
493 if (i==list__dragIndex+1)
498 if (sel!=-1 && !item->selected && sel!=item->nsel)
501 list__redrawItem(list__dragging,i);
502 list__dragging->nsel+=(sel==TRUE)-(sel==FALSE);
507 list__currentIndex=index;
509 /* --- Scroll the window to include the added selection --- */
510 if (m.y>s.o.y) /* If pointer too far up, scroll up */
512 else if (m.y+s.o.box.y1-s.o.box.y0<s.o.y) /* If too far down, scroll down*/
513 s.o.y=m.y+s.o.box.y1-s.o.box.y0;
514 wimpt_noerr(wimp_open_wind(&s.o)); /* Open the window in new position */
518 * BOOL list__selectUnknowns(wimp_eventstr *e,void *handle)
521 * Unknown event handler for dragging out selections.
524 * wimp_eventstr *e == the unknown event
525 * void *handle == a NULL pointer
528 * TRUE if the event was interesting
531 static BOOL list__selectUnknowns(wimp_eventstr *e,void *handle)
539 list__selectIdles(0);
540 for (i=list__dragging->list;i;i=i->next)
546 win_remove_unknown_event_processor(list__selectUnknowns,0);
547 win_remove_idle_claimer(list__selectIdles,0);
555 * BOOL list__modeChange(wimp_eventstr *e,void *handle)
558 * Handles mode change events for list boxes (rescan the width)
561 static BOOL list__modeChange(wimp_eventstr *e,void *handle)
568 case wimp_ESENDWANTACK:
569 if (e->data.msg.hdr.action==wimp_MMODECHANGE ||
570 e->data.msg.hdr.action==0x400CF)
578 * void list__events(wimp_eventstr *e,void *handle)
581 * The event handler for list boxes.
584 * wimp_eventstr *e == the event
585 * void *handle == the list box handle
588 _dll_static void list__events(wimp_eventstr *e,void *handle)
593 handled=(l->rawEvents)(l,e,l->rawHandle);
599 wimpt_redraw(list__redraw,l);
602 wimpt_noerr(wimp_open_wind(&e->data.o));
605 list__event(l,list_CLOSE);
610 e->data.but.m.bbits & wimp_BLEFT ||
611 e->data.but.m.bbits & wimp_BRIGHT ||
612 e->data.but.m.bbits & wimp_BCLICKLEFT ||
613 e->data.but.m.bbits & wimp_BCLICKRIGHT
616 list_item i=list__coordsToItem(e->data.but.m.x,e->data.but.m.y,l);
617 if (e->data.but.m.bbits&wimp_BLEFT || l->multSel==FALSE)
618 list_selectItem(l,i);
620 list_addToSelection(l,i,list_TOGGLESTATE);
621 list__event(l,l->selected);
625 (e->data.but.m.bbits & wimp_BDRAGLEFT ||
626 e->data.but.m.bbits & wimp_BDRAGRIGHT) &&
632 wimpt_noerr(wimp_get_wind_state(l->wind,&s));
633 d.type=wimp_USER_HIDDEN;
634 d.parent.x0=e->data.but.m.x;
636 d.parent.x1=e->data.but.m.x;
638 wimpt_noerr(wimp_drag_box(&d));
640 list__dragIndex=-(e->data.but.m.y+wimpt_dy()-s.o.box.y1+s.o.y)/
642 list__currentIndex=list__dragIndex;
643 list__selectIdles(0);
644 win_add_unknown_event_processor(list__selectUnknowns,0);
645 win_addIdleClaimer(list__selectIdles,2,0);
649 wimpt_noerr(wimp_processkey(e->data.key.chcode));
653 int height=e->data.scroll.o.box.y1-e->data.scroll.o.box.y0;
654 int width=e->data.scroll.o.box.x1-e->data.scroll.o.box.x0;
655 switch (e->data.scroll.y)
659 int bottom=-(e->data.scroll.o.y-height)/l->iHeight;
660 int itms=height/l->iHeight;
661 if (-bottom*l->iHeight==e->data.scroll.o.y-height)
663 e->data.scroll.o.y=-(bottom+itms)*l->iHeight+height;
668 int bottom=-(e->data.scroll.o.y-height)/l->iHeight;
670 e->data.scroll.o.y=-bottom*l->iHeight+height;
677 int top=-(e->data.scroll.o.y)/l->iHeight;
678 if (-top*l->iHeight==e->data.scroll.o.y)
680 e->data.scroll.o.y=-top*l->iHeight;
685 int top=-(e->data.scroll.o.y)/l->iHeight;
686 int itms=height/l->iHeight;
687 if (-top*l->iHeight!=e->data.scroll.o.y);
689 e->data.scroll.o.y=-(top-itms)*l->iHeight;
693 switch (e->data.scroll.x)
696 e->data.scroll.o.x-=width;
699 e->data.scroll.o.x-=32;
704 e->data.scroll.o.x+=32;
707 e->data.scroll.o.x+=width;
710 wimpt_noerr(wimp_open_wind(&(e->data.scroll.o)));
714 case wimp_ESENDWANTACK:
715 switch (e->data.msg.hdr.action)
717 case wimp_MHELPREQUEST:
718 list__event(l,list_HELP);
727 * list_item list__findItem(list l,list_item i)
730 * Returns a pointer to a list item.
734 * list_item i == the item number
737 * A pointer to the list item or 0 if it couldn't be found.
740 #define list__findItem(l,i) (i)
743 * void list_isPane(list l,pane p)
746 * This routine is part of the private interface between the listbox and
747 * pane segments. Do *NOT* try to call it in your own code.
750 void list_isPane(list l,pane p)
758 * void list__redrawItem(list l,int item)
761 * Calls for a redraw of a single list item
764 * list l == the list handle
765 * int i == the item index
768 static void list__redrawItem(list l,int i)
775 wimpt_noerr(wimp_get_wind_state(l->wind,&s));
778 r.box.x1=s.o.x+s.o.box.x1-s.o.box.x0;
779 r.box.y0=-l->iHeight*i-l->iHeight;
780 r.box.y1=-l->iHeight*i;
781 wimpt_noerr(wimp_update_wind(&r,&more));
785 wimpt_noerr(wimp_get_rectangle(&r,&more));
791 * void list_selectItem(list l,list_item item)
794 * Makes the item the currently selected one.
797 * list l == the list handle
798 * list_item item == the item number
801 void list_selectItem(list l,list_item item)
808 if (i->selected==TRUE && i!=item)
811 list__redrawItem(l,c);
818 l->selected=list_NOITEM;
819 list_addToSelection(l,item,list_SETSTATE);
823 * list_item list_selected(list l)
826 * Returns the currently selected item of the list.
829 * list l == the list handle
832 * The item number of the currently selected item.
835 list_item list_selected(list l)
837 list_item itm=l->list;
844 return (list_NOITEM);
848 * list list_create(char *name,BOOL alterSize)
851 * Creates a new list box window, and returns a handle to it. Initially,
852 * there are no items, and the list box is not shown. The function returns
853 * 0 if the call fails for one reason or another (not enough windows or
857 * char *name == the name to match in the template file
858 * BOOL alterSize == TRUE if we are allowed to change the box's visible
862 * An abstract handle for the list box.
865 list list_create(char *name,BOOL alterSize)
867 list new=(list)mem_alloc(sizeof(list__liststr));
870 werr(FALSE,msgs_lookup("listNEM:Not enough room to create list box."));
880 new->selected=list_NOITEM;
881 new->windDef=template_syshandle(name);
882 new->alterSize=alterSize;
884 new->foreg=new->windDef->colours[wimp_WCWKAREAFORE];
885 new->backg=new->windDef->colours[wimp_WCWKAREABACK];
891 new->iHeight=list__ITEMHEIGHT;
896 * char *list_itemData(list l,list_item i)
899 * Returns the string for an item
902 * list l == the list handle
903 * list_item i == the item's handle
906 * A pointer to the item's data
909 char *list_itemData(list l,list_item i)
912 return (list__findItem(l,i)->data);
916 * list_item list_addItem(list l,char *data,BOOL inOrder)
919 * Adds a new piece of data into the list.
922 * list l == the list handle
923 * char *data == the data (as a char *, because most of the time you'll
924 * want to be using character strings).
927 * A handle for the list item. This is 0 if the call failed.
930 list_item list_addItem(list l,char *data,BOOL inOrder)
932 list_item itm=(list_item)&(l->list);
933 list_item new=(list_item)mem_alloc(sizeof(list__item));
938 werr(FALSE,msgs_lookup("listNEMI:Not enough room to add new item."));
941 if (new->data=mem_alloc(strlen(data)+1),!new->data)
944 werr(FALSE,msgs_lookup("listNEMI:Not enough room to add new item."));
947 strcpy(new->data,data);
950 if (utils_caselessCmp(itm->next->data,data)>0 && inOrder==TRUE)
963 len=wimpt_stringWidth(data);
971 * list_item list_findItem(list l,char *data)
974 * Searches through a list and returns the item number of the item whose
975 * data matches that given in the function.
978 * list l == the list handle
979 * char *data == the data to compare with
982 * The item number of the item, or -1 if no match.
985 list_item list_findItem(list l,char *data)
987 list_item itm=l->list;
988 list_item found=list_NOITEM;
991 if (utils_caselessCmp(itm->data,data)==0)
999 * void list_removeItem(list l,list_item i)
1002 * Removes an item from the list.
1005 * list l == the list's handle
1006 * list_item i == the item number
1009 void list_removeItem(list l,list_item i)
1012 l->selected=list_NOITEM;
1016 i->prev->next=i->next;
1018 i->next->prev=i->prev;
1022 list__rescanSize(l);
1026 * void list_delete(list l)
1029 * Destroys a list totally.
1032 * list l == the list handle
1035 void list_delete(list l)
1037 list_item itm=l->list;
1053 * void list_updatePosition(list l)
1056 * Writes the position of the listbox back into the template, so any new
1057 * list boxes created from the template open at that position.
1060 * list l == the list handle
1063 void list_updatePosition(list l)
1066 if (w=(wimp_winfo *)mem_alloc
1068 sizeof(wimp_winfo)+l->windDef->nicons*sizeof(wimp_icon)
1073 wimpt_noerr(wimp_get_wind_info(w));
1074 *(l->windDef)=w->info;
1075 l->windDef->colours[wimp_WCWKAREABACK]=l->backg;
1076 /* Put colour back into *your* life :-) */
1082 * BOOL list_link(list l)
1085 * Links a list box to a WIMP window. If the list is already linked,
1086 * nothing happens. The list box is not displayed.
1089 * list l == the list handle
1092 * TRUE if the link succeeded (may run out of windows!)
1095 BOOL list_link(list l)
1100 l->windDef->colours[wimp_WCWKAREABACK]=255;
1101 /* We draw the whole lot anyway, so this is quicker */
1102 if (wimp_create_wind(l->windDef,&l->wind))
1107 msgs_lookup("listTMW:Too many windows - "
1108 "%s could not create list box."),
1112 l->windDef->colours[wimp_WCWKAREABACK]=l->backg;
1113 /* Put it back for reading again later */
1116 l->windDef->colours[wimp_WCWKAREABACK]=l->backg;
1117 /* Put it back for reading again later */
1118 win_register_event_handler(l->wind,_dllEntry(list__events),l);
1119 win_add_unknown_event_processor(list__modeChange,l);
1120 ox=l->windDef->box.x0-l->windDef->scx;
1121 oy=l->windDef->box.y1-l->windDef->scy;
1122 l->visSize.x0=l->windDef->ex.x0;
1123 l->visSize.y0=l->windDef->box.y0-oy;
1124 l->visSize.x1=l->windDef->ex.x1;
1125 l->visSize.y1=l->windDef->box.y1-oy;
1127 list__rescanSize(l);
1132 * void list_unlink(list l)
1135 * Unlinks the list box from its window and deletes the window.
1138 * list l == the list handle
1141 void list_unlink(list l)
1145 list_updatePosition(l);
1146 win_register_event_handler(l->wind,0,0);
1147 win_remove_unknown_event_processor(list__modeChange,l);
1148 wimpt_noerr(wimp_delete_wind(l->wind));
1152 * void list_unlinkNoUpdate(list l)
1155 * Unlinks a list from its window without storing its final position back
1156 * in memory. Note that list_delete() calls list_unlink(), so make sure
1157 * you call this routine before deleting the list box it you want to
1158 * prevent the position being written back.
1161 * list l == the list handle
1164 void list_unlinkNoUpdate(list l)
1168 win_register_event_handler(l->wind,0,0);
1169 wimpt_noerr(wimp_delete_wind(l->wind));
1175 * void list_update(list l,BOOL really)
1178 * Enables or disables list updating (i.e. whether the listbox resizes and
1179 * redraws itself between every operation). If you're going to do some
1180 * lengthy operation, it would be a good idea to turn update off first,
1181 * and then turn it on again afterwards.
1183 * Note that this is an all-or-nothing thing -- no counter is kept.
1186 * list l == the listbox which we're messing about with
1187 * BOOL really == whether to turn the update on or off
1190 void list_update(list l,BOOL really)
1194 list__rescanSize(l);
1198 * void list_display(list l)
1201 * Displays a list box on-screen
1204 * list l == the list
1207 void list_display(list l)
1212 if (list_link(l)==0)
1215 wimpt_noerr(wimp_get_wind_state(l->wind,&state));
1216 state.o.behind=(wimp_w)-1;
1217 wimpt_noerr(wimp_open_wind(&state.o));
1221 * void list_openDisplaced(list l)
1224 * Opens the listbox on-screen displaced from its previous position by the
1225 * normal 48 OS units. It must be unlinked using list_unlinkNoUpdate
1229 * list l == the list handle.
1232 void list_openDisplaced(list l)
1236 if (l->windDef->box.y0-48<132)
1238 new=((976-l->windDef->box.y1)/48-4)*48+l->windDef->box.y1;
1239 l->windDef->box.y0+=new-l->windDef->box.y1;
1240 l->windDef->box.y1=new;
1244 l->windDef->box.y0-=48;
1245 l->windDef->box.y1-=48;
1247 wimpt_noerr(wimp_get_wind_state(l->wind,&s));
1248 s.o.box=l->windDef->box;
1250 wimpt_noerr(wimp_open_wind(&s.o));
1254 * void list_hide(list l)
1257 * Stops the list box being displayed
1260 * list l == the list handle
1263 void list_hide(list l)
1265 wimpt_noerr(wimp_close_wind(l->wind));
1269 * wimp_w list_syshandle(list l)
1272 * Returns the WIMP window handle being used for the list box.
1275 * list l == the list
1278 * The window handle (a wimp_w).
1281 wimp_w list_syshandle(list l)
1287 * void list_eventHandler(list l,list_eventhandler proc,void *handle)
1290 * Attaches an event handler to the list box. Most won't actually need
1291 * this, just the stand-alone ones, or ones that do clever-dick things.
1294 * list l == the list handle
1295 * list_eventhandler proc == the procedure to handle events
1296 * void *handle == the jolly olde pointer to the user-defined data
1299 void list_eventHandler(list l,list_eventhandler proc,void *handle)
1302 l->evntHandle=handle;
1306 * void list_rawEventHandler(list l,list_raweventhandler proc,void *handle)
1309 * Attaches the raw event handler procedure to the list box. You can then
1310 * vet any events coming into the list box and have your wicked way with
1314 * list l == the list handle
1315 * list_raweventhandler proc == the raw event handler routine
1316 * void *handle == the (now-famous) caller defined handle.
1319 void list_rawEventHandler(list l,list_raweventhandler proc,void *handle)
1322 l->rawHandle=handle;
1326 * void list_redrawHandler(list l,list_redrawhandler rdr,void *handle)
1329 * Attaches a replacement redraw handler to the list box. The new handler
1330 * redraws individual items in the list. It must fill in the box it is
1331 * passed, because the WIMP does not fill in the background. The part of
1332 * the list box not populated by items is filled in the window background
1333 * colour automatically. Using this, you can achieve quite a pleasing
1334 * effect by making the background grey (colour 1) and the actual item
1335 * backgrounds white (colour 0), indicating clearly the bottom of the list.
1337 * You can also implement other things like items being shaded etc.
1340 * list l == the list to which the redraw handler is to be attached
1341 * list_redrawhandler == the replacement redraw routine (or 0 to cancel)
1342 * void *handle == a pointer to pass the redraw routine
1345 void list_redrawHandler(list l,list_redrawhandler rdr,void *handle)
1348 l->redrawHandle=handle;
1352 * void list_widthAdd(list l,int extra)
1355 * Since redraw handlers can basically do whatever they want to for each
1356 * items, the list manager no longer really has any idea about how wide an
1357 * item is. Since the main thing displayed in lists is text, it is assumed
1358 * that the width of an item is the width of the longest piece of text plus
1359 * a constant (e.g. for a sprite on the side). If this is not so, I'll
1360 * have to rethink this bit...
1363 * list l == the list we're setting the width of
1364 * int extra == the constant to add to each item
1367 void list_widthAdd(list l,int extra)
1369 l->extraWidth=extra;
1370 list__resize(l); /* In case it's open */
1374 * void list_setItemHeight(list l,int height)
1377 * Sets the height of items in the specified list box. By default, the
1378 * height is 44 OS units (the height of menu items). This should be
1379 * sufficient for most purposes.
1382 * list l == the list to set
1383 * int height == the new height of each item, in OS units
1386 void list_setItemHeight(list l,int height)
1389 list__resize(l); /* In case it's open now */
1393 * int list_items(list l)
1396 * Informs the caller how many items there are in a list
1399 * list l == the list handle
1402 * The number of items in a list
1405 int list_items(list l)
1411 * void list_doForItems
1414 * void (*proc)(list l,list_item i,void *handle),
1419 * Performs an operation on all of the items in a list box.
1422 * list l == the list handle
1423 * void (*proc)(list l,list_item i,void *handle) == the procedure to use
1424 * void *handle == a handle to pass to the procedure.
1427 void list_doForItems
1430 void (*proc)(list l,list_item i,void *handle),
1434 list_item i=l->list;
1447 * void list_attachData(list l,list_item i,void *data)
1450 * Attaches a data structure to a list item. This is a bit of an
1451 * afterthought really.
1454 * list l == the list
1455 * list_item i == the list item
1456 * void *data == a pointer to the data structure
1459 void list_attachData(list l,list_item i,void *data)
1462 list__findItem(l,i)->handle=data;
1466 * void *list_getData(list l,list_item i)
1469 * Returns the data attached to a list item. The item number may have
1470 * changed etc. with items deleted and added.
1473 * list l == the list
1474 * list_item i == the list item number
1477 * A pointer to the data structure attached using list_attachData().
1480 void *list_getData(list l,list_item i)
1484 return (list__findItem(l,i)->handle);
1490 * void list_multipleSelection(list l)
1493 * Makes a list able to handle a multiple selection.
1496 * list l == the list handle
1499 void list_multipleSelection(list l)
1505 * BOOL list_addToSelection(list l,list_item i,list_action a)
1508 * Adds an item to the current selection.
1511 * list l == the list
1512 * list_item i == the list item
1513 * list_action a == what to do with the state
1516 * The previous state of the item
1519 BOOL list_addToSelection(list l,list_item i,list_action a)
1537 case list_RESETSTATE:
1540 case list_TOGGLESTATE:
1541 i->selected=!(i->selected);
1544 l->nsel+=i->selected-ostate;
1545 if (l->wind==0 || i->selected==ostate)
1547 list__redrawItem(l,list_itemToIndex(l,l->selected));
1549 top=-l->iHeight*list_itemToIndex(l,i);
1550 bottom=top-l->iHeight;
1551 wimpt_noerr(wimp_get_wind_state(l->wind,&state));
1552 height=state.o.box.y1-state.o.box.y0;
1555 if (state.o.y-height>bottom)
1556 state.o.y=bottom+height;
1557 wimpt_noerr(wimp_open_wind(&state.o));
1563 * void list_doForSelected
1566 * void (*proc)(list l,list_item i,void *handle),
1571 * Performs a user-specified action for each selected list item.
1574 * list l == the list box
1575 * void (*proc)(list l,list_item i,void *handle) == the procedure to do
1577 * void *handle == a handle to pass to the routine.
1580 void list_doForSelected
1583 void (*proc)(list l,list_item i,void *handle),
1587 list_item i=l->list;
1601 * void list__sel(list l,list_item i,void *handle)
1604 * Selects a single item in a list. This is a list_doForItems() procedure.
1607 * list l == the list
1608 * list_item i == the list item to select
1609 * void *handle == a pointer to a variable of type list_action
1612 static void list__sel(list l,list_item i,void *handle)
1614 list_action *a=(list_action *)handle;
1615 list_addToSelection(l,i,*a);
1619 * void list_selectAll(list l,list_action a)
1622 * Selects all the items in a list
1625 * list l == the list
1626 * list_action a == what to do with the icons (list_READSTATE ain't all
1627 * that useful, and list_TOGGLESTATE is downright wierd).
1630 void list_selectAll(list l,list_action a)
1632 list_doForItems(l,list__sel,&a);
1636 * int list_numSelected(list l)
1639 * Informs the caller how many items are selected.
1642 * list l == the list handle
1645 * An integer indicating the number of selected items
1648 int list_numSelected(list l)
1654 * int list_itemToIndex(list l,list_item i)
1657 * Translates a list_item into the index of the item. This avoids
1658 * assumptions about the mapping of indices to item numbers. In the
1659 * future, for example, the list_item data type may be used as a pointer to
1660 * the list item data structure in memory. Most of the time this will be
1661 * irrelevant anyway.
1664 * list l == the list handle
1665 * list_item i == the list item to translate
1668 * An integer giving the index of the item. The first item has index 0, as
1672 int list_itemToIndex(list l,list_item i)
1675 list_item itm=l->list;
1687 * list_item list_indexToItem(list l,int index)
1690 * Performs the reverse operation to the previous routine. It will
1691 * translate an index to a list_item.
1694 * list l == the list handle
1695 * int index == the index of the item required
1698 * The equivalent list_item for the item.
1701 list_item list_indexToItem(list l,int index)
1704 list_item itm=l->list;
1712 return (list_NOITEM);
1716 * list_item list_helpItem(list l)
1719 * Returns the item that Help is interested in.
1722 * list l == the list's handle
1728 list_item list_helpItem(list l)
1730 wimp_eventstr *e=wimpt_last_event();
1732 return (list__coordsToItem
1734 e->data.msg.data.helprequest.m.x,
1735 e->data.msg.data.helprequest.m.y,l
1738 werr(TRUE,msgs_lookup("listHIE:(list_helpItem, caller fault): "
1739 "Not called on HELPREQUEST event."));