3 * Allows creation of Filer-like windows which rearrange themselves.
5 * v. 1.00 (13 August 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.
52 extern void _dllEntry(viewer__events)(wimp_eventstr *e,void *handle);
56 * A structure of information about a viewer icon.
59 typedef struct viewer__iconstr
73 * A structure of information about a viewer window.
76 typedef struct viewer__viewerstr
80 viewer_eventhandler events;
82 viewer_raweventhandler rawEvents;
84 viewer_redrawhandler rdr;
102 * Some constants for the things
105 #define viewer__MINWIDTH 380
106 #define viewer__MINHEIGHT 160
107 #define viewer__GAP 16
108 #define viewer__BANNERHEIGHT 48
110 static viewer_saveproc viewer__usersave;
111 static viewer_sendproc viewer__usersend;
112 static viewer_printproc viewer__userprint;
113 static viewer_icon viewer__currentIcon;
114 static viewer viewer__currentViewer;
115 static int viewer__filetype;
117 #define max(x,y) ((x)>(y) ? (x) : (y))
118 #define min(x,y) ((x)<(y) ? (x) : (y))
121 * void viewer__resize(viewer v)
124 * Resizes the viewer nicely, altering the extent if necessary.
127 * viewer v == the viewer handle
130 static void viewer__resize(viewer v)
140 wimpt_noerr(wimp_get_wind_state(v->wind,&s));
141 w=s.o.box.x1-s.o.box.x0;
142 scw=wimpt_scwidth()-40;
143 across=w/(v->width+viewer__GAP);
144 maxacc=scw/(v->width+viewer__GAP);
153 down=v->icons/across;
154 if (v->icons%across!=0)
158 if (v->across==across && v->down==down && (s.flags & wimp_WOPEN))
160 minw=wimpt_stringWidth(v->title)+164;
161 if (v->banner[0]!='\0')
163 int l=wimpt_stringWidth(v->banner)+64;
167 if (minw<viewer__MINWIDTH)
168 minw=viewer__MINWIDTH;
171 r.box.y0=-(v->height+viewer__GAP)*down;
172 if (v->banner[0]!='\0')
173 r.box.y0-=viewer__BANNERHEIGHT;
174 if (r.box.y0>-viewer__MINHEIGHT)
175 r.box.y0=-viewer__MINHEIGHT;
176 r.box.x1=(v->width+viewer__GAP)*maxacc;
180 wimpt_noerr(wimp_set_extent(&r));
182 /* --- Acorn-approved hack --- *
184 * We have problems with the Wimp fiddling our extent after we've set it,
185 * so we just redraw lots and lots.
188 r.box.x0=r.box.y0=-0xFFFFFF;
189 r.box.x1=r.box.y1=0xFFFFFF;
190 wimpt_noerr(wimp_force_redraw(&r));
192 if (s.flags & wimp_WOPEN)
193 wimpt_noerr(wimp_open_wind(&s.o));
199 * void viewer__redrawicon(wimp_redrawstr *r,viewer_icon icn,wimp_box *box)
202 * Redraws an icon in the box specified.
205 * viewer_icon icn == the icon to redraw
206 * wimp_box *box == the box to draw it in
209 static void viewer__redrawicon
221 (v->rdr)(icn,r,box,icn->text,icn->sprite,icn->selected,v->rdrHandle);
225 if (icn->text!=0 && icn->sprite[0]!='\0')
227 i.flags=wimp_ITEXT|wimp_ISPRITE|wimp_INDIRECT|wimp_IHCENTRE;
228 sprintf(valid,"S%s",icn->sprite);
229 i.data.indirecttext.buffer=icn->text;
230 i.data.indirecttext.validstring=valid;
231 i.data.indirecttext.bufflen=1;
233 else if (icn->text!=0)
235 i.flags=wimp_ITEXT|wimp_INDIRECT|wimp_IHCENTRE|wimp_IVCENTRE;
236 i.data.indirecttext.buffer=icn->text;
237 i.data.indirecttext.validstring=(char *)-1;
238 i.data.indirecttext.bufflen=1;
242 i.flags=wimp_ISPRITE|wimp_INDIRECT|wimp_IHCENTRE|wimp_IVCENTRE;
243 i.data.indirectsprite.name=icn->sprite;
244 i.data.indirectsprite.spritearea=v->spr;
245 i.data.indirectsprite.nameisname=TRUE;
249 i.flags|=wimp_ISELECTED;
250 wimpt_noerr(wimp_ploticon(&i));
254 * void viewer_drawFileIcons
266 * Redraw handler which takes into account filetypes of icons. The icons
267 * automatically get new sprites if the sprites for their filetypes change.
268 * For applications, the text is considered to be a filename. Register
269 * this function using viewer_redrawHandler().
272 * viewer_icon icn == the icon to paint
273 * wimp_redrawstr *r == information about this redraw
274 * wimp_box *box == the box to draw the icon in
275 * char *text == the text to display
276 * char *sprite == the sprite to display
277 * BOOL selected == is the icon selected?
278 * void *handle == a caller defined handle (ignored)
281 void viewer_drawFileIcons
297 i.flags=wimp_ITEXT|wimp_ISPRITE|wimp_INDIRECT|wimp_IHCENTRE;
298 if (icn->filetype!=-1)
299 sprintf(valid,"S%s",fileicon_spriteName(icn->filetype,text));
301 sprintf(valid,"S%s",sprite);
302 i.data.indirecttext.buffer=text;
303 i.data.indirecttext.validstring=valid;
304 i.data.indirecttext.bufflen=1;
307 i.flags|=wimp_ISELECTED;
308 wimpt_noerr(wimp_ploticon(&i));
312 * viewer__redraw(wimp_redrawstr *r,void *handle)
315 * Redraws a viewer window
318 * wimp_redrawstr *r == the bit to redraw
319 * void *handle == the viewer
322 static void viewer__redraw(wimp_redrawstr *r,void *handle)
324 viewer v=(viewer)handle;
325 viewer_icon icn=v->iconlist;
326 int oy=r->box.y1-r->scy;
328 int y=-viewer__GAP/2;
333 wimp_icon banicn={28,-48,1000,0,0x037000131};
338 coords_box_toworkarea(&g,&c);
339 wimp_setcolour(0x81);
341 if (v->banner[0]!='\0')
343 if (g.y1>-viewer__BANNERHEIGHT)
349 oy-viewer__BANNERHEIGHT,
354 banicn.box.x1=100+wimpt_stringWidth(v->banner);
355 banicn.data.indirecttext.buffer=v->banner;
356 banicn.data.indirecttext.validstring=(char *)-1;
357 wimpt_noerr(wimp_ploticon(&banicn));
359 y-=viewer__BANNERHEIGHT;
367 if (coords_boxesoverlap(&box,&g))
368 viewer__redrawicon(r,icn,&box);
370 if ((++cnt)==v->across)
373 y-=viewer__GAP+v->height;
377 x+=viewer__GAP+v->width;
382 * void viewer__events(wimp_eventstr *e,void *handle)
385 * Window event handler for the viewer.
388 * wimp_eventstr *e == the wimp event structure
389 * void *handle == my data (i.e. a 'this' pointer to my viewer__viewerstr)
392 _dll_static void viewer__events(wimp_eventstr *e,void *handle)
395 viewer v=(viewer)handle;
398 handled=(v->rawEvents)(v,e,v->rawHandle);
404 wimpt_redraw(viewer__redraw,v);
407 if (wimpt_justChangedMode())
408 viewer_settitle(v,0);
409 wimpt_noerr(wimp_get_wind_state(v->wind,&s));
410 wimpt_noerr(wimp_open_wind(&e->data.o));
412 if (s.flags & wimp_WCLICK_TOGGLE)
414 if (s.flags & wimp_WFULL)
416 e->data.o.box=v->oldSize.box;
417 e->data.o.x=v->oldSize.x;
418 e->data.o.y=v->oldSize.y;
419 wimpt_noerr(wimp_open_wind(&e->data.o));
427 (v->events)(v,viewer_CLOSE,(wimp_bbits)0,v->closeHandle,0);
431 viewer_icon i=viewer_iconFromCoords
445 (i!=viewer_NOICON) ? i->handle : 0
451 wimpt_noerr(wimp_processkey(e->data.key.chcode));
454 case wimp_ESENDWANTACK:
455 switch (e->data.msg.hdr.action)
457 case wimp_MHELPREQUEST:
459 viewer_icon i=viewer_iconFromCoords
462 e->data.msg.data.helprequest.m.x,
463 e->data.msg.data.helprequest.m.y
473 (i!=viewer_NOICON) ? i->handle : 0
484 * viewer viewer_create
496 * Creates a viewer window. Note that viewer windows don't need templates,
497 * and don't contain real wimp icons, just yer normal redrawn-by-
498 * application things (which can be handled by a caller-defined function if
499 * necessary). The banner along the top is optional - if a null pointer is
500 * passed, no banner is included. The sprite area passed applies to all
501 * the icons in the window, although if you want to, you can use your own
502 * redraw routine to handle different sprite areas for them.
505 * int x,int y == the coordinates of the top-left corner of the window
506 * (file windows for editors need good positioning here).
507 * int width == the width of an icon
508 * int height == the height of an icon
509 * sprite_area *spr == the sprite area for the window
510 * char *title == the title of the window
511 * char *banner == the banner heading along the top (like 'Sprite file
512 * window' or something)
515 * A handle to the viewer window. As usual, a NULL pointer indicates
516 * something went wrong.
530 viewer v=(viewer)mem_alloc(sizeof(viewer__viewerstr));
546 {7,2,7,255,3,1,12,0},
548 wimp_ITEXT|wimp_IHCENTRE|wimp_INDIRECT,
549 wimp_IBTYPE*wimp_BCLICKDRAGDOUBLE,
556 w.box.x1=x+900-(900%(width+viewer__GAP));
558 w.box.x1=x+width+viewer__GAP;
559 w.box.y0=y-500+(500%(height+viewer__GAP));
561 w.box.y0=y-height+viewer__GAP;
563 w.spritearea=(void *)spr;
566 werr(FALSE,msgs_lookup("viewerNEM:Not enough room to create viewer."));
569 w.title.indirecttext.buffer=v->title;
570 w.title.indirecttext.validstring=(char *)-1;
571 w.title.indirecttext.bufflen=256;
572 strcpy(v->title,title);
575 strcpy(v->banner,banner);
576 w.box.y0-=viewer__BANNERHEIGHT;
591 v->menuSel=viewer_NOICON;
592 v->oldSize.box=w.box;
595 if (wimp_create_wind(&w,&v->wind))
600 msgs_lookup("viewerTMW:Too many windows - "
601 "%s could not create viewer."),
607 win_register_event_handler(v->wind,_dllEntry(viewer__events),v);
613 * void viewer_display(viewer v)
616 * Displays a viewer on the screen.
619 * viewer v == the viewer handle
622 void viewer_display(viewer v)
626 wimpt_noerr(wimp_get_wind_state(v->wind,&state));
628 wimpt_noerr(wimp_open_wind(&state.o));
632 * void viewer_hide(viewer v)
635 * Hides an open viewer.
638 * viewer v == the handle
641 void viewer_hide(viewer v)
643 wimpt_noerr(wimp_close_wind(v->wind));
647 * void viewer_delete(viewer v,void (*freeProc)(void *handle))
650 * Zaps a viewer and everything in it. The function you pass to this
651 * routine is called with every icon handle the viewer has associated with
652 * it, so you don't need to link all the structures together - I've already
656 * viewer v == the viewer to destroy
657 * void (*freeProc)(void *handle) == a function to free one of the caller-
658 * defined viewer icon structures.
661 void viewer_delete(viewer v,void (*freeProc)(void *handle))
663 viewer_icon icn=v->iconlist;
667 if (icn->handle && freeProc)
668 freeProc(icn->handle);
674 win_register_event_handler(v->wind,0,0);
676 wimpt_noerr(wimp_delete_wind(v->wind));
681 * void viewer_eventHandler(viewer v,viewer_eventhandler proc,void *handle)
684 * Attaches an event handler to the viewer. The handle passed to this
685 * function is only used for close events, so you can take appropriate
686 * action at the other end. Otherwise, the handle for the icon concerned
687 * is used. Suggested code:
689 * void user_viewer(viewer v,viewer_icon i,wimp_bbits b,void *handle)
691 * user_fileStructure *file=(user_fileStructure *)handle;
692 * user_itemStructure *item=(user_itemStructure *)handle;
695 * case (int)viewer_CLOSE:
696 * ... use 'file' for this bit of code ...
698 * case viewer_NOICON:
699 * ... use 'file' for this bit as well ...
702 * ... use 'item' for this bit of code ...
708 * viewer v == the viewer to attach the handler to
709 * viewer_eventhandler proc == the event handler
710 * void *handle == the handle
713 void viewer_eventHandler(viewer v,viewer_eventhandler proc,void *handle)
716 v->closeHandle=handle;
720 * void viewer_rawEventHandler
723 * viewer_raweventhandler proc,
728 * Attaches a raw event handler to a viewer. Same as always, this one.
731 * viewer v == the viewer handle
732 * viewer_raweventhandler proc == the handler routine
733 * void *handle == the handle for the user's data
736 void viewer_rawEventHandler
739 viewer_raweventhandler proc,
748 * void viewer_redrawHandler(viewer v,viewer_redrawhandler proc,void *handle)
751 * Adds in a user-defined routine for redrawing icons in the window.
754 * viewer v == the viewer handle
755 * viewer_redrawhandler proc == the routine for doing the redraw
756 * void *handle == a handle to be passed to the routine (a sprite area or
760 void viewer_redrawHandler(viewer v,viewer_redrawhandler proc,void *handle)
767 * void viewer_setIconSize(viewer v,int width,int height)
770 * Sets a new icon size for the viewer. This would normally be
771 * accompanied by a chnge in redraw handler. It would be used e.g. when
772 * using a menu option giving a choice between 'Large icons' and 'Small
776 * viewer v == the viewer which is to receive this change
777 * int width == the new width
778 * int height == the new height
781 void viewer_setIconSize(viewer v,int width,int height)
790 * void viewer_setCompare(viewer v,viewer_compare cmp)
793 * Registers a compare function for the viewer specified. The function
794 * is passed the caller-defined handles of two icons. The function must
795 * return <0 if a<b, >0 if a>b, or ==0 if a==b (like strcmp does). The
796 * viewer's icons are then resorted. Pass 0 to use the default sorting
797 * system (a caseless compare on the icon text)
799 * The resorting algorithm is the link mergesort, originally implemented
800 * in the Sapphire linklist manager.
803 * viewer v == the viewer we're going to set the comparer up for
804 * viewer_compare cmp == the function to do comparing
807 void viewer_setCompare(viewer v,viewer_compare cmp)
815 /* --- Now we have to resort the list --- *
817 * This code is pretty much based on the mergesort code printed in
818 * Sedgewick's Algorithms.
821 #define next(p) ((p) ? (p)->next : (p))
824 viewer_icon a,b,c,t,todo,x,y;
834 c=(viewer_icon)&v->iconlist;
852 /* --- Now we have to do the actual merge --- *
854 * This is made a little bit more difficult since we have null-
855 * terminated lists rather than a weird node which points to itself.
865 i=(v->cmp)(a->handle,b->handle);
867 i=utils_caselessCmp(a->text,b->text);
892 /* --- Now we have to sort out the back links --- */
895 viewer_icon a=v->iconlist;
907 * viewer_icon viewer_addIcon
917 * Adds a new icon to a viewer window.
920 * viewer v == the handle of the viewer to use.
921 * char *text == the text to put under the icon (may be null)
922 * char *sprite == the sprite to use (may be null)
923 * BOOL inOrder == whether you want the icons sorted into order according
925 * void *handle == the handle you want to pass to the event handler routine
928 * A handle to the icon. If this is NULL, something went majorly wrong
932 viewer_icon viewer_addIcon
941 viewer_icon icn=(viewer_icon)&(v->iconlist);
942 viewer_icon new=(viewer_icon)mem_alloc(sizeof(viewer__iconstr));
945 werr(FALSE,msgs_lookup("viewerCCI:Not enough room to create new icon."));
950 if (new->text=mem_alloc(strlen(text)+1),!new->text)
956 msgs_lookup("viewerCCI:Not enough room to create new icon.")
960 strcpy(new->text,text);
965 strcpy(new->sprite,sprite);
972 if ((v->cmp)(icn->next->handle,handle)>0 && inOrder==TRUE)
977 if (utils_caselessCmp(icn->next->text,text)>0 && inOrder==TRUE)
998 * void viewer_setFiletype(viewer_icon i,int type)
1001 * Sets the filetype of the icon - useful for bins and things. This
1002 * filetype overrides the setting given to viewer_exportSelected(). It can
1003 * also be used to display the correct icon in the viewer by changing the
1004 * redraw handler to viewer_drawFileIcons().
1007 * viewer_icon i == the icon to change
1008 * int type == the filetype to give it (any valid WIMP filetype will do)
1011 void viewer_setFiletype(viewer_icon i,int type)
1017 * int viewer_readFiletype(viewer_icon i)
1020 * Returns the filetype attached to an icon.
1023 * viewer_icon i == the icon handle
1026 * The type attached using viewer_setFiletype(), or -1 if none.
1029 int viewer_readFiletype(viewer_icon i)
1031 return (i->filetype);
1035 * viewer_icon viewer_findIcon(viewer v,char *text)
1038 * Searches through a viewer to find an icon with the same text as 'text'.
1039 * The search is case-insensitive.
1042 * viewer v == the viewer handle
1043 * char *text == text to search for
1046 * The icon handle, or viewer_NOICON if unsuccessful.
1049 viewer_icon viewer_findIcon(viewer v,char *text)
1051 viewer_icon i=v->iconlist;
1054 if (utils_caselessCmp(text,i->text)==0)
1058 return (viewer_NOICON);
1062 * void viewer_removeIcon(viewer_icon i)
1065 * Removes the icon specified. This routine is real easy!
1068 * viewer_icon i == the icon to remove (they ALL have unique handles, so
1072 void viewer_removeIcon(viewer_icon i)
1078 i->last->next=i->next;
1080 v->iconlist=i->next;
1082 i->next->last=i->last;
1087 v->menuSel=viewer_NOICON;
1092 * wimp_w viewer_syshandle(viewer v)
1095 * Returns the WIMP window handle used for the viewer (and much use may it
1099 * viewer v == the viewer handle
1102 * The wimp_w window handle
1105 wimp_w viewer_syshandle(viewer v)
1111 * viewer_icon viewer_iconFromCoords(viewer v,int x,int y)
1114 * Given a set of (absolute) coordinates, this returns the icon in the
1115 * viewer specified that the point is on. This is mainly useful for menu
1116 * maker routines, which will want to be able to select items and so on.
1119 * viewer v == the viewer handle
1120 * int x == the x-coordinate of the point
1121 * int y == the y-coordinate of the point
1124 * The icon handle, or viewer__NOICON if there isn't one.
1127 viewer_icon viewer_iconFromCoords(viewer v,int x,int y)
1133 viewer_icon icn=v->iconlist;
1134 wimpt_noerr(wimp_get_wind_state(v->wind,&s));
1135 x-=(s.o.box.x0-s.o.x);
1136 y-=(s.o.box.y1-s.o.y);
1138 if (v->banner[0]!='\0')
1139 y-=viewer__BANNERHEIGHT;
1140 ix=x/(v->width+viewer__GAP);
1141 x-=(v->width+viewer__GAP)*ix;
1142 if (x<viewer__GAP/2 || x-viewer__GAP/2>v->width || ix>=v->across)
1143 return (viewer_NOICON);
1144 iy=y/(v->height+viewer__GAP);
1145 y-=(v->height+viewer__GAP)*iy;
1146 if (y<viewer__GAP/2 || y-viewer__GAP/2>v->height || iy>=v->down)
1147 return (viewer_NOICON);
1150 return (viewer_NOICON);
1151 for (cnt=0;cnt<i;cnt++)
1154 return (viewer_NOICON);
1161 * void viewer_iconToCoords(viewer_icon i,wimp_box *box)
1164 * Calculates the bounding box of the icon given. If there is an error,
1165 * nothing is written in the block.
1168 * viewer_icon i == the icon we're interested in
1169 * wimp_box *box == where to store the coordinates
1172 void viewer_iconToCoords(viewer_icon i,wimp_box *box)
1177 viewer_icon icn=v->iconlist;
1179 wimpt_noerr(wimp_get_wind_state(v->wind,&s));
1189 if ((++x)==v->across)
1197 box->x0=s.o.box.x0-s.o.x+viewer__GAP/2+(viewer__GAP+v->width)*x;
1198 box->x1=box->x0+v->width;
1199 box->y1=s.o.box.y1-s.o.y-viewer__GAP/2-(viewer__GAP+v->height)*y;
1200 if (v->banner[0]!='\0')
1201 box->y1-=viewer__BANNERHEIGHT;
1202 box->y0=box->y1-v->height;
1206 * BOOL viewer_isSelected(viewer_icon i)
1209 * Returns whether an icon is selected or not.
1212 * viewer_icon i == the icon handle
1215 * TRUE if the icon is selected, or FALSE otherwise.
1218 BOOL viewer_isSelected(viewer_icon i)
1220 return (i->selected);
1224 * void viewer_selectIcon(viewer_icon i,BOOL onOrOff)
1227 * Selects or deselects the icon specified.
1230 * viewer_icon i == the icon handle
1231 * BOOL onOrOff == TRUE to select, FALSE to deselect
1234 void viewer_selectIcon(viewer_icon i,BOOL onOrOff)
1242 if (i==viewer_NOICON)
1245 if (i->selected!=onOrOff)
1254 i->selected=onOrOff;
1256 viewer_iconToCoords(i,&box);
1257 wimpt_noerr(wimp_get_wind_state(v->wind,&s));
1258 ox=s.o.box.x0-s.o.x;
1259 oy=s.o.box.y1-s.o.y;
1265 wimpt_noerr(wimp_update_wind(&r,&more));
1268 viewer__redrawicon(&r,i,&box);
1269 wimpt_noerr(wimp_get_rectangle(&r,&more));
1274 * viewer viewer_iconToViewer(viewer_icon i)
1277 * Returns the viewer in which an icon is contained.
1280 * viewer_icon i == the icon handle
1283 * The viewer handle.
1286 viewer viewer_iconToViewer(viewer_icon i)
1292 * void *viewer_iconHandle(viewer_icon i)
1295 * Returns the handle attached to the icon when it was created
1298 * viewer_icon i == the icon in question
1301 * The handle attached
1304 void *viewer_iconHandle(viewer_icon i)
1310 * char *viewer_textOfIcon(viewer_icon i)
1313 * Returns the text of the icon given.
1316 * viewer_icon i == the icon
1319 * Pointer to the string (read only!).
1322 char *viewer_textOfIcon(viewer_icon i)
1328 * int viewer_selected(viewer v)
1331 * Informs caller how many icons are selected.
1334 * viewer v == the viewer handle
1337 * The number of icons selected.
1340 int viewer_selected(viewer v)
1342 return (v->selected);
1346 * int viewer_icons(viewer v)
1349 * Returns the number of icons in a viewer.
1352 * viewer v == the viewer
1355 * The number of icons.
1358 int viewer_icons(viewer v)
1364 * void viewer_doForIcons
1367 * BOOL onlySelected,
1368 * void (*proc)(viewer_icon i,void *handle)
1372 * Does the same thing for either all the icons in a viewer, or just the
1376 * viewer v == the viewer handle
1377 * BOOL onlySelected == whether you want to handle just the selected ones,
1379 * void (*proc)(viewer_icon i,void *handle) == the routine to do whatever
1380 * it is you want to do.
1383 void viewer_doForIcons
1387 void (*proc)(viewer_icon i,void *handle)
1390 viewer_icon i=v->iconlist;
1395 if (i->selected || !onlySelected)
1402 * void viewer__select(viewer_icon i,void *handle)
1408 * viewer_icon i == the icon handle
1409 * void *handle == a handle (ignored)
1412 static void viewer__select(viewer_icon i,void *handle)
1415 viewer_selectIcon(i,TRUE);
1419 * void viewer__deselect(viewer_icon i,void *handle)
1422 * Deselects an icon.
1425 * viewer_icon i == the icon handle
1426 * void *handle == a handle (ignored)
1429 static void viewer__deselect(viewer_icon i,void *handle)
1432 viewer_selectIcon(i,FALSE);
1436 * void viewer_selectAll(viewer v,BOOL onOrOff)
1439 * Selects or deselects all the icons in a viewer.
1442 * viewer v == the viewer handle
1443 * BOOL onOrOff == whether you want the icons to be on or off
1446 void viewer_selectAll(viewer v,BOOL onOrOff)
1448 viewer_doForIcons(v,FALSE,onOrOff ? viewer__select : viewer__deselect);
1449 v->menuSel=viewer_NOICON;
1453 * BOOL viewer__selectUnknowns(wimp_eventstr *e,void *handle)
1456 * Selects the icons inside the rubber-band box created, RISC OS 3-like.
1459 * wimp_eventstr *e == the event that I might be interested in
1460 * void *handle == a (useless) handle
1463 * TRUE if the event was interesting.
1466 static BOOL viewer__selectUnknowns(wimp_eventstr *e,void *handle)
1472 viewer v=viewer__currentViewer;
1476 viewer_icon icn=v->iconlist;
1480 case wimp_EUSERDRAG:
1481 wimpt_noerr(wimp_get_wind_state(v->wind,&s));
1485 b.x0=min(e->data.dragbox.x0,e->data.dragbox.x1);
1486 b.y0=min(e->data.dragbox.y0,e->data.dragbox.y1);
1487 b.x1=max(e->data.dragbox.x0,e->data.dragbox.x1);
1488 b.y1=max(e->data.dragbox.y0,e->data.dragbox.y1);
1489 b.x0+=viewer__GAP/2;
1490 b.x1-=viewer__GAP/2;
1491 b.y0+=viewer__GAP/2;
1492 b.y1-=viewer__GAP/2;
1493 coords_box_toworkarea(&b,&c);
1494 if (v->banner[0]!='\0')
1495 coords_offsetbox(&b,0,viewer__BANNERHEIGHT,&b);
1496 vib.x0=b.x0/(v->width+viewer__GAP);
1497 vib.y0=(-b.y1)/(v->height+viewer__GAP);
1498 vib.x1=b.x1/(v->width+viewer__GAP);
1499 vib.y1=(-b.y0)/(v->height+viewer__GAP);
1505 win_remove_unknown_event_processor(viewer__selectUnknowns,0);
1506 for (i=0;icn!=0;i++,icn=icn->next)
1510 if (x>=vib.x0 && x<=vib.x1 && y>=vib.y0 && y<=vib.y1)
1511 viewer_selectIcon(icn,TRUE);
1519 * void viewer_clickSelect(viewer v,viewer_icon i,wimp_bbits b)
1522 * Handles a click on an icon just like clicks in Filer windows.
1525 * viewer v == the viewer handle
1526 * viewer_icon i == the icon that was clicked
1527 * wimp_bbits b == the mouse button status
1530 void viewer_clickSelect(viewer v,viewer_icon i,wimp_bbits b)
1532 viewer_icon icn=v->iconlist;
1535 case wimp_BCLICKRIGHT:
1536 if (i!=viewer_NOICON)
1538 viewer_selectIcon(v->menuSel,FALSE);
1539 v->menuSel=viewer_NOICON;
1540 viewer_selectIcon(i,!(i->selected));
1543 case wimp_BCLICKLEFT:
1544 v->menuSel=viewer_NOICON;
1545 if (i->selected==FALSE || i==viewer_NOICON)
1550 viewer_selectIcon(icn,FALSE);
1553 viewer_selectIcon(i,TRUE);
1556 case wimp_BDRAGLEFT:
1557 case wimp_BDRAGRIGHT:
1558 if (i==viewer_NOICON)
1563 wimpt_noerr(wimp_get_point_info(&m));
1564 wimpt_noerr(wimp_get_wind_state(v->wind,&s));
1566 d.type=wimp_USER_RUBBER;
1569 d.box.x1=m.x+wimpt_dx();
1570 d.box.y1=m.y+wimpt_dy();
1572 wimpt_noerr(wimp_drag_box(&d));
1573 viewer__currentViewer=v;
1574 win_add_unknown_event_processor(viewer__selectUnknowns,0);
1578 v->menuSel=viewer_NOICON;
1579 viewer_selectIcon(i,TRUE);
1583 if ((v->menuSel!=viewer_NOICON || v->selected==0) && v->menuSel!=i)
1585 viewer_selectIcon(v->menuSel,FALSE);
1587 viewer_selectIcon(v->menuSel,TRUE);
1593 * char *viewer_menuItem(viewer v,char *header)
1596 * Returns a menu item of the form either "~<header> ''",
1597 * "<header> '<icon name>'", or "Selection", for inclusion in a menu
1601 * viewer v == the viewer handle
1602 * char *header == the header for the menu item
1605 * A pointer to a read-only string.
1608 char *viewer_menuItem(viewer v,char *header)
1610 char *buffer=buffer_find();
1612 switch (v->selected)
1615 sprintf(buffer,"~%s ''",header);
1620 viewer_icon i=v->iconlist;
1621 while (i->selected==FALSE)
1625 sprintf(buffer,"%s '%s'",header,i->text);
1630 strcpy(buffer,msgs_lookup("viewerMIS:Selection"));
1638 * void viewer_setupMenu(viewer v,char *header,menu m,int i,char *buff)
1641 * Writes a menu item out as for the previous routine, but implants it
1642 * directly into the menu, so you don't need to fiddle about with things
1643 * like that, and also means that the menu pointer changes. The menu item
1644 * must have been previously set up with menu_redirectItem. This call will
1645 * also set the menu to the correct width. However, ensure that you call
1646 * menu_minWidth(m,0) before fiddling with the width!
1649 * viewer v == the viewer handle pertaining to this request
1650 * menu m == the menu to doctor
1651 * int i == the menu item
1652 * char *buff == where the menu item wants the data
1655 void viewer_setupMenu(viewer v,char *header,menu m,int i,char *buff)
1657 char *t=viewer_menuItem(v,header);
1661 menu_setflags(m,i,FALSE,TRUE);
1664 menu_setflags(m,i,FALSE,FALSE);
1666 menu_minWidth(m,strlen(buff));
1670 * viewer_icon viewer_firstSelected(viewer v)
1673 * Returns the handle of the first selected icon.
1676 * viewer v == the viewer handle
1679 * A handle to the first one, or viewer_NOICON.
1682 viewer_icon viewer_firstSelected(viewer v)
1684 viewer_icon i=v->iconlist;
1691 return (viewer_NOICON);
1695 * void viewer_settitle(viewer v,char *title)
1698 * Changes a viewer's title, so that the extent is updated as well.
1701 * viewer v == the viewer handle
1702 * char *title == the new title string
1703 * (internal: may be 0 to indicate just to resize the viewer)
1706 void viewer_settitle(viewer v,char *title)
1714 win_settitle(v->wind,"%s",title);
1715 wimpt_noerr(wimp_get_wind_state(v->wind,&s));
1716 scw=wimpt_scwidth();
1717 maxacc=scw/(v->width+viewer__GAP);
1718 if (maxacc>v->icons)
1720 minw=wimpt_stringWidth(v->title)+164;
1721 if (v->banner[0]!='\0') /* Bug fix */
1723 int l=wimpt_stringWidth(v->banner)+64;
1727 if (minw<viewer__MINWIDTH)
1728 minw=viewer__MINWIDTH;
1731 r.box.y0=-(v->height+viewer__GAP)*v->down;
1732 if (v->banner[0]!='\0')
1733 r.box.y0-=viewer__BANNERHEIGHT;
1734 if (r.box.y0>-viewer__MINHEIGHT)
1735 r.box.y0=-viewer__MINHEIGHT;
1736 r.box.x1=(v->width+viewer__GAP)*maxacc;
1740 wimpt_noerr(wimp_set_extent(&r));
1741 if (s.flags & wimp_WOPEN)
1742 wimpt_noerr(wimp_open_wind(&s.o));
1746 * void viewer_dragSelected(viewer_icon icn,wimp_bbits b)
1749 * Drags a set of icons around a window.
1752 * viewer_icon icn == the viewer icon handle
1753 * wimp_bbits b == the button types that started this lot off
1756 void viewer_dragSelected(viewer_icon icn,wimp_bbits b)
1765 int scWidth=wimpt_scwidth();
1766 int scHeight=wimpt_scheight();
1768 if (icn==viewer_NOICON)
1770 if (b!=wimp_BDRAGLEFT && b!=wimp_BDRAGRIGHT)
1772 viewer_selectIcon(icn,TRUE);
1774 wimpt_noerr(wimp_get_point_info(&m));
1777 wimpt_noerr(os_swix(XOS_Byte,&r)); /* Support DragASprite? */
1778 if (wimpt_getVersion()>=300 && (r.r[2] & 2))
1787 if (icn->filetype==-1)
1789 r.r[2]=(int)icn->sprite;
1794 r.r[2]=(int)fileicon_spriteName(icn->filetype,icn->text);
1800 r.r[2]=(int)"package";
1804 sid.s.name="package";
1806 if (!sprite_select(v->spr,&sid))
1811 wimpt_noerr(os_swix(XDragASprite_Start,&r));
1817 if (i->selected==TRUE)
1819 viewer_iconToCoords(i,&box);
1822 if (d.box.x0>box.x0)
1824 if (d.box.y0>box.y0)
1826 if (d.box.x1<box.x1)
1828 if (d.box.y1<box.y1)
1839 d.box.x0-=viewer__GAP/2;
1840 d.box.y0-=viewer__GAP/2;
1841 d.box.x1+=viewer__GAP/2;
1842 d.box.y1+=viewer__GAP/2;
1844 d.type=wimp_USER_FIXED;
1845 d.parent.x0=d.box.x0-m.x;
1846 d.parent.y0=d.box.y0-m.y;
1847 d.parent.x1=scWidth-m.x+d.box.x1;
1848 d.parent.y1=scHeight-m.y+d.box.y1;
1849 wimpt_noerr(wimp_drag_box(&d));
1853 * The routines for the data transfer.
1856 static BOOL viewer__save(char *name,void *handle)
1861 viewer__usersave(viewer__currentIcon,name,viewer__currentIcon->handle)
1865 static BOOL viewer__send(void *handle,int *maxbuf)
1870 viewer__usersend(viewer__currentIcon,viewer__currentIcon->handle,maxbuf)
1874 static int viewer__print(char *filename,void *handle)
1881 viewer__currentIcon,
1883 viewer__currentIcon->handle
1889 * void viewer__export(viewer_icon i,void *handle)
1892 * Exports each icon in turn.
1895 * viewer_icon i == the icon handle
1896 * void *handle == a handle to the user's data (ignored)
1899 static void viewer__export(viewer_icon i,void *handle)
1903 viewer__currentIcon=i;
1905 wimpt_fake_event(&e);
1908 i->filetype==-1 ? viewer__filetype : i->filetype,
1911 viewer__usersave==0 ? 0 : viewer__save,
1912 viewer__usersend==0 ? 0 : viewer__send,
1913 viewer__userprint==0 ? 0 : viewer__print,
1920 * BOOL viewer__unknowns(wimp_eventstr *e,void *handle)
1923 * Unknown event processor - handles the end of the drag operation.
1926 * wimp_eventstr *e == a pointer to the event.
1927 * void *handle == a handle to some data (ignored).
1930 * Whether the event was interesting.
1933 static BOOL viewer__exportUnknowns(wimp_eventstr *e,void *handle)
1940 case wimp_EUSERDRAG:
1941 wimpt_noerr(wimp_get_point_info(&m));
1942 if (m.w!=viewer__currentViewer->wind)
1943 viewer_doForIcons(viewer__currentViewer,TRUE,viewer__export);
1945 win_remove_unknown_event_processor(viewer__exportUnknowns,0);
1952 * void viewer_exportSelected
1957 * viewer_saveproc save,
1958 * viewer_sendproc send,
1959 * viewer_printproc print
1963 * Allows you to export the data connected with each selected icon to
1964 * another application. The filename used is the icon's text.
1967 * viewer_icon icn == the icon on which the user clicked to start the drag
1969 * wimp_bbits b == the mouse buttons which started this up.
1970 * int filetype == the filetype of the data.
1971 * viewer_saveproc save == the save routine (saving and <Wimp$Scrap>
1973 * viewer_sendproc send == the send routine (RAM transfer).
1974 * viewer_printproc print == the print routine (printing etc.)
1977 void viewer_exportSelected
1982 viewer_saveproc save,
1983 viewer_sendproc send,
1984 viewer_printproc print
1987 if (icn==viewer_NOICON)
1989 if (b!=wimp_BDRAGLEFT && b!=wimp_BDRAGRIGHT)
1991 viewer_dragSelected(icn,b);
1992 viewer__filetype=filetype;
1993 viewer__usersave=save;
1994 viewer__usersend=send;
1995 viewer__userprint=print;
1996 viewer__currentViewer=icn->v;
1997 win_add_unknown_event_processor(viewer__exportUnknowns,0);
2001 * viewer_icon viewer_helpIcon(viewer v)
2004 * Informs the caller which icon the Help system is interested in.
2007 * viewer v == the viewer handle
2010 * The icon's handle (or maybe viewer_NOICON)
2013 viewer_icon viewer_helpIcon(viewer v)
2015 wimp_eventstr *e=wimpt_last_event();
2019 viewer_iconFromCoords
2022 e->data.msg.data.helprequest.m.x,
2023 e->data.msg.data.helprequest.m.y
2027 werr(TRUE,msgs_lookup("viewerVIE:(viewer_helpIcon, caller fault): "
2028 "Not called on HELPREQUEST event."));