chiark / gitweb /
Initial revision
[ssr] / StraySrc / Libraries / Steel / c / nopoll
1 /*
2  * nopoll
3  *  Provides handling for a dialogue box without polling (for error boxes
4  *  and so on
5  *
6  * v. 1.00 (30 July 1993)
7  *
8  * © 1993-1998 Straylight
9  */
10
11 /*----- Licensing note ----------------------------------------------------*
12  *
13  * This file is part of Straylight's Steel library.
14  *
15  * Steel is free software; you can redistribute it and/or modify
16  * it under the terms of the GNU General Public License as published by
17  * the Free Software Foundation; either version 2, or (at your option)
18  * any later version.
19  *
20  * Steel is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23  * GNU General Public License for more details.
24  *
25  * You should have received a copy of the GNU General Public License
26  * along with Steel.  If not, write to the Free Software Foundation,
27  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
28  */
29
30 /*---------------------------------------------------------------------------
31
32   Support is provided for three action buttons, here referred to as 'OK',
33   'Cancel' and 'Other'.  Fair enough?  Good.  'OK' is the default action
34   button, which may also be selected by pressing return.  Pressing escape
35   is equivalent to clicking Cancel.  The 'Other' button (good, eh?) has no
36   keyboard equivalent.  To indicate that you don't want a particular button
37   to exist, just pass -1 as the number.
38
39 ---------------------------------------------------------------------------*/
40
41 #include "dbox.h"
42 #include "wimpt.h"
43 #include "coords.h"
44 #include "bbc.h"
45 #include "os.h"
46 #include "nopoll.h"
47 #include "interface.h"
48 #include "sculptrix.h"
49 #include "visdelay.h"
50 #include "resspr.h"
51 #include "swiv.h"
52
53 #define OS_Mouse 0x2001C
54 #define XWimpExt_Redraw 0x65783
55
56 static dbox nopoll__d;
57 static dbox_field nopoll__f;
58
59 /*
60  * void nopoll__clickicon(dbox d,dbox_field f)
61  *
62  * Use
63  *  Clicks in a given field in a nice way
64  */
65
66 static void nopoll__clickicon(dbox d,dbox_field f)
67 {
68   nopoll__d=d;
69   nopoll__f=f;
70   if (wimpt_options() & 7)
71     dbox_clickicon(d,f);
72   else
73     dbox_selecticon(d,f,TRUE);
74 }
75
76 /*
77  * void nopoll__unclick(void)
78  *
79  * Use
80  *  Unclicks a clicked icon
81  */
82
83 static void nopoll__unclick(void)
84 {
85   if (wimpt_options() & 7)
86     dbox_unclick();
87   else
88     dbox_selecticon(nopoll__d,nopoll__f,FALSE);
89 }
90
91 /*
92  * void nopoll__mouseRectangle(wimp_w window)
93  *
94  * Use
95  *  Sets up the mouse rectangle to the limits of the window specified.
96  *
97  * Parameters
98  *  wimp_w window == the window handle
99  */
100
101 static void nopoll__mouseRectangle(wimp_w window)
102 {
103   wimp_wstate s;
104   wimpt_noerr(wimp_get_wind_state(window,&s));
105   wimpt_noerr((os_error *)bbc_mouserect(s.o.box.x0-wimpt_dx(),
106                             s.o.box.y0-wimpt_dy(),
107                             s.o.box.x1,
108                             s.o.box.y1));
109 }
110
111 /*
112  * void nopoll__freeMouse(void)
113  *
114  * Use
115  *  Frees the mouse from the current mouse rectangle.
116  */
117
118 static void nopoll__freeMouse(void)
119 {
120   bbc_mouserect(0,0,wimpt_scwidth()-wimpt_dx(),wimpt_scheight()-wimpt_dy());
121 }
122
123 /*
124  * void nopoll_showDbox(dbox d,nopoll_appearFlags flags)
125  *
126  * Use
127  *  Displays a dbox on-screen without polling the WIMP.  Useful for
128  *  copyright windows and things.
129  *
130  * Parameters
131  *  dbox d == the dbox handle
132  *  nopoll_appearFlags flags == how you want the dbox to appear
133  */
134
135 void nopoll_showDbox(dbox d,nopoll_appearFlags flags)
136 {
137   wimp_w wind=dbox_syshandle(d);
138   wimp_redrawstr rdr;
139   int more=0;
140
141   switch (flags)
142   {
143     case nopoll_ASIS:
144       dbox_display(d,dbox_STATIC_LASTPOS);
145       break;
146     case nopoll_CENTRE:
147       dbox_display(d,dbox_STATIC_CENTRE);
148       break;
149     case nopoll_ONPTR:
150       dbox_display(d,dbox_STATIC_OVERPTR);
151       break;
152   }
153   rdr.w=wind;
154   wimpt_noerr(wimp_redraw_wind(&rdr,&more));
155   while (more)
156   {
157     if (wimpt_options() & wimpt_OSCULPTRIX)
158     {
159       wimpt_noerr(sculptrix_setSpriteArea(resspr_area()));
160       wimpt_noerr(sculptrix_redrawWindow(&rdr));
161     }
162     if (wimpt_options() & wimpt_OINTERFACE)
163       wimpt_noerr(interface_render3dWindow(&rdr));
164     if (wimpt_options() & wimpt_OWIMPEXT)
165       wimpt_noerr(_swix(XWimpExt_Redraw,_in(1),&rdr));
166     if (!dbox_hasTitle(d))
167       dbox_drawEmbeddedTitle(&rdr,d);
168     wimpt_noerr(wimp_get_rectangle(&rdr,&more));
169   }
170 }
171
172 /*
173  * int nopoll_doDbox
174  * (
175  *   dbox d,
176  *   nopoll_appearFlags flags,
177  *   dbox_field OK,
178  *   dbox_field cancel,
179  *   dbox_field other
180  * )
181  *
182  * Use
183  *  Opens a NoPoll dialogue box, continues until it gets a sensible result,
184  *  closes it, and then returns the result.
185  *
186  * Parameters
187  *  dbox d == the dialogue box you want to use for this.
188  *  nopoll_appearFlags flags == how you want the box to appear (see above)
189  *  dbox_field OK == the number of the OK button
190  *  dbox_field cancel == the number of the Cancel button
191  *  dbox_field other == the number of the Other button
192  *
193  * Returns
194  *  One of the macros defined above, depending on what the user did.
195  */
196
197 int nopoll_doDbox
198 (
199   dbox d,
200   nopoll_appearFlags flags,
201   dbox_field OK,
202   dbox_field cancel,
203   dbox_field other
204 )
205 {
206   wimp_w wind=dbox_syshandle(d);
207   wimp_wstate state;
208   wimp_icon icn;
209   wimp_box okBox={-1,-1,-1,-1};
210   wimp_box cancelBox=okBox;
211   wimp_box otherBox=okBox;
212   wimp_mousestr m;
213   coords_cvtstr crds;
214   int done=0;
215   BOOL ignoreClick=TRUE;
216   int b;
217   coords_pointstr p;
218   int key;
219   int dummy;
220   visdelay_state visstate=visdelay_suspend();
221   wimpt_noerr(wimp_get_point_info(&m));
222   nopoll_showDbox(d,flags);
223   nopoll__mouseRectangle(wind);
224   wimpt_noerr(wimp_get_wind_state(wind,&state));
225   crds.box=state.o.box;
226   crds.scx=state.o.x;
227   crds.scy=state.o.y;
228   if (OK!=-1)
229   {
230     wimpt_noerr(wimp_get_icon_info(wind,OK,&icn));
231     okBox=icn.box;
232     coords_box_toscreen(&okBox,&crds);
233   }
234   if (cancel!=-1)
235   {
236     wimpt_noerr(wimp_get_icon_info(wind,cancel,&icn));
237     cancelBox=icn.box;
238     coords_box_toscreen(&cancelBox,&crds);
239   }
240   if (other!=-1)
241   {
242     wimpt_noerr(wimp_get_icon_info(wind,other,&icn));
243     otherBox=icn.box;
244     coords_box_toscreen(&otherBox,&crds);
245   }
246   while (!done)
247   {
248     bbc_mouse(&p.x,&p.y,&b,0);
249     if ((b==1 || b==4) && !ignoreClick)
250     {
251       if (coords_withinbox(&p,&okBox))
252         done=nopoll_OK;
253       else if (coords_withinbox(&p,&cancelBox))
254         done=nopoll_CANCEL;
255       else if (coords_withinbox(&p,&otherBox))
256         done=nopoll_OTHER;
257       else
258         ignoreClick=TRUE;
259     }
260     else
261     {
262       if (b!=1 && b!=4)
263         ignoreClick=FALSE;
264       key=0;
265       dummy=0;
266       wimpt_noerr(os_byte(129,&key,&dummy));
267       if (dummy!=0)
268         key=-1;
269       switch (key)
270       {
271         case 13:
272           if (OK!=-1)
273             done=nopoll_OK;
274           break;
275         case 27:
276           if (cancel!=-1)
277             done=nopoll_CANCEL;
278           else if (OK!=-1)
279             done=nopoll_OK;
280           break;
281       }
282     }
283   }
284   visdelay_resume(visstate);
285   switch (done)
286   {
287     case nopoll_OK:
288       nopoll__clickicon(d,OK);
289       break;
290     case nopoll_CANCEL:
291       nopoll__clickicon(d,cancel);
292       break;
293     case nopoll_OTHER:
294       nopoll__clickicon(d,other);
295       break;
296   }
297   dbox_hide(d);
298   nopoll__unclick();
299   nopoll__freeMouse();
300   return (done);
301 }