chiark / gitweb /
Initial revision
[ssr] / StraySrc / Glass / !Glass / c / wWindows
1 /*
2  * wWindows.c
3  *
4  * Manipulation of template windows
5  *
6  * © 1994-1998 Straylight
7  */
8
9 /*----- Licensing note ----------------------------------------------------*
10  *
11  * This file is part of Straylight's Glass.
12  *
13  * Glass is free software; you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License as published by
15  * the Free Software Foundation; either version 2, or (at your option)
16  * any later version.
17  *
18  * Glass is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with Glass.  If not, write to the Free Software Foundation,
25  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26  */
27
28 /*----- Header files ------------------------------------------------------*/
29
30 /*
31  * ANSI standard headers
32  */
33
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37
38 /*
39  * Steel headers
40  */
41
42 #define _STDAPP
43 #define _LOWLVL
44 #include "steel/Steel.h"
45
46 #include "steel/flex.h"
47
48 /*
49  * Glass headers
50  */
51
52 #include "gStruct.h"
53 #include "gMenus.h"
54 #include "gIcons.h"
55
56 #include "glass.h"
57 #include "tfile.h"
58 #include "window.h"
59 #include "_window.h"
60 #include "editWin.h"
61
62 /*----- Main code ---------------------------------------------------------*/
63
64 /*
65  * wimp_w window__recreate(glass_windPointer *w)
66  *
67  * Use
68  *  Recreates a window, getting all the fiddly bits right.
69  *
70  * Parameters
71  *  glass_windPointer *w == the window
72  *
73  * Returns
74  *  The window handle, or 0 for failure
75  */
76
77 wimp_w window__recreate(glass_windPointer *w)
78 {
79   wimp_iconflags icf;
80   wimp_w wh;
81   int i;
82
83   /* --- Update all the sprite areas for the title bar and icons --- */
84
85   icf=w->def->desc.w.titleflags;
86   if ((icf & wimp_INDIRECT) && (icf & wimp_ISPRITE) && !(icf & wimp_ITEXT))
87     w->def->desc.w.title.indirectsprite.spritearea=w->t->s;
88   for (i=0;i<w->def->desc.w.nicons;i++)
89   {
90     icf=w->def->i[i].i.flags;
91     if ((icf & wimp_INDIRECT) && (icf & wimp_ISPRITE) && !(icf & wimp_ITEXT))
92       w->def->i[i].i.data.indirectsprite.spritearea=w->t->s;
93   }
94
95   /* --- If we're in test mode, allocate space for all the icons --- */
96
97 #ifndef glass_DEMO
98   if (w->testMode)
99   {
100     wimp_wind *wp;
101     wimp_icon *ip;
102
103     if (!flex_alloc((flex_ptr)&wp,
104                     sizeof(wimp_wind)+
105                     w->def->desc.w.nicons*sizeof(wimp_icon)))
106       return (0);
107
108     /* --- Copy the window data across from our main structure --- */
109
110     *wp=w->def->desc.w;
111     ip=(wimp_icon *)(wp+1);
112     for (i=0;i<w->def->desc.w.nicons;i++)
113       ip[i]=w->def->i[i].i;
114     wp->spritearea=w->t->s;
115
116     /* --- Mangle the flags a little --- */
117
118     wp->flags&=~wimp_WPANE;     /* Strange things occur if we don't...    */
119     wp->flags&=~wimp_BACK_WINDOW; /* Don't let Pinboard hide my windows   */
120     wp->flags&=~wimp_HOT_KEYS;  /* Don't grab hot keys -- no use for them */
121
122     /* --- Bodge the window extent --- *
123      *
124      * Since the visible area can now `stretch' the window extent, we may
125      * need to bodge the extent for a bit
126      */
127
128     wp->ex.x1=max2(wp->ex.x1,wp->scx+wp->box.x1-wp->box.x0);
129     wp->ex.y0=min2(wp->ex.y0,wp->scy-wp->box.y1+wp->box.y0);
130     w->tex=wp->ex;
131
132     /* --- Try to create the window --- */
133
134     if (wimpt_complain(wimp_create_wind(wp,&wh)))
135     {
136       flex_free((flex_ptr)&wp);
137       return (0);
138     }
139     flex_free((flex_ptr)&wp);
140
141     /* --- Bodge for WimpExtension being buggy --- *
142      *
143      * WimpExtension doesn't accept NULL-terminated strings for all its
144      * validation strings, so we have to go through them all and return-
145      * terminate them :-(.  Hopefully we won't have to do this when
146      * WimpExtension II is ready.
147      */
148
149   #ifndef window__WimpExtension_works_with_null_terminated_strings
150     for (i=0;i<w->def->desc.w.nicons;i++)
151     {
152       if ( (w->def->i[i].i.flags & wimp_INDIRECT) &&
153            (w->def->i[i].i.flags & wimp_ITEXT) &&
154            (w->def->i[i].i.data.indirecttext.validstring!=(char *)-1) )
155       {
156         char *j;
157         for (j=w->def->i[i].i.data.indirecttext.validstring;*j>=32;j++)
158           /* thing */;
159         *j=0x0d;
160       }
161     }
162   #endif
163
164   }
165   else
166 #endif
167
168   /* --- We're creating the window for editing -- don't make icons --- */
169
170   {
171     wimp_wind wdef;
172
173     wdef=w->def->desc.w;
174
175     wdef.ex.x1=max2(wdef.ex.x1,wdef.scx+wdef.box.x1-wdef.box.x0);
176     wdef.ex.y0=min2(wdef.ex.y0,wdef.scy-wdef.box.y1+wdef.box.y0);
177     w->tex=wdef.ex;
178
179     wdef.nicons=0;               /* We draw the icons ourselves            */
180     wdef.spritearea=w->t->s;     /* Set up sprite area                     */
181     wdef.workflags=wimp_BCLICKDRAGDOUBLE<<12;
182     wdef.flags|=wimp_WMOVEABLE;  /* Make window movable (Acorn karnt spel) */
183     wdef.flags&=~wimp_REDRAW_OK; /* We need to draw the icons!             */
184     wdef.flags&=~wimp_WPANE;     /* Show the highlight on the actual window*/
185     wdef.flags&=~wimp_BACK_WINDOW; /* Let it come to the front nicely      */
186     wdef.flags&=~wimp_HOT_KEYS;  /* Don't grab hot keys -- no use for them */
187     if (wimpt_complain(wimp_create_wind(&wdef,&wh)))
188       return(0);                 /* Don't be too unhappy if it failed      */
189   }
190
191   win_activeinc();               /* Pointless convention, but there you go */
192   return (wh);
193 }
194
195 /*
196  * void window__nudgeScroll(glass_windPointer *w,int x,int y)
197  *
198  * Use
199  *  Scrolls the window a bit, by adding the x and y values given to the
200  *  scroll offsets of the window.  The values are multiplied up to give a
201  *  sensible sized scroll.
202  *
203  * Parameters
204  *  glass_windPointer *w == the window to scroll
205  *  int x == the x scroll offset to add
206  *  int y == the y scroll offset to add
207  */
208
209 void window__nudgeScroll(glass_windPointer *w,int x,int y)
210 {
211   wimp_wstate s;
212
213   /* --- Scroll the window --- */
214
215   wimpt_noerr(wimp_get_wind_state(w->h,&s));
216   s.o.x+=x*32;
217   s.o.y+=y*32;
218   wimpt_noerr(wimp_open_wind(&s.o));
219   wimpt_noerr(wimp_get_wind_state(w->h,&s));
220
221   /* --- Write the new scroll values back to the window block --- */
222
223   if (s.o.x!=w->def->desc.w.scx || s.o.y!=w->def->desc.w.scy)
224   {
225     w->def->desc.w.scx=s.o.x;
226     w->def->desc.w.scy=s.o.y;
227     if (!w->t->alts)             /* Moving the window alters the template  */
228       tfile_markAsAltered(w->t); /* But only if not already altered        */
229     editWindow_windowMoved(w);
230   }
231 }
232
233 /*
234  * void window_hasBeenDeleted(glass_windPointer *w)
235  *
236  * Use
237  *  Informs the window system that a window is about to be deleted.
238  *
239  * Parameters
240  *  glass_windPointer *w == the window that bites the dust
241  */
242
243 void window_hasBeenDeleted(glass_windPointer *w)
244 {
245   if (window_selectionOwner()==w)
246     window__gainSelection(0);
247   if (window__menuOwner()==w)
248     window__updateMenu(0);
249   if (w->ownPointer)
250   {
251     win_removeIdleClaimer(window__winIdles,w);
252     window__setPtrShape(window__SELECT);
253   }
254 }
255
256 /*
257  * void window_recreate(glass_windPointer *w)
258  *
259  * Use
260  *  Recreates a window after editing.  Nothing happens if the window is not
261  *  open already.  If an error occurs, the open window is removed and left
262  *  that way.
263  *
264  * Parameters
265  *  glass_windPointer *w == the window to recreate
266  */
267
268 void window_recreate(glass_windPointer *w)
269 {
270   wimp_wstate s;
271   wimp_w wnd;
272   if (!w->h)
273     return;
274   wimpt_noerr(wimp_get_wind_state(w->h,&s));
275   wimpt_noerr(wimp_delete_wind(w->h));
276   win_register_event_handler(w->h,0,0);
277   win_activedec();
278   if (wnd=window__recreate(w),!wnd)
279     return;
280   win_register_event_handler(wnd,window__events,w);
281   w->h=wnd;
282   s.o.w=w->h;
283   wimpt_noerr(wimp_open_wind(&s.o));
284   window_updateToolbar();
285 }
286
287 /*
288  * void window_close(glass_windPointer *w)
289  *
290  * Use
291  *  Closes the specified window.
292  *
293  * Parameters
294  *  glass_windPointer *w == the window wot we 'ave to close
295  */
296
297 void window_close(glass_windPointer *w)
298 {
299 #ifndef glass_DEMO
300   int i;
301   wimp_icon icn;
302 #endif
303
304   wimpt_noerr(wimp_close_wind(w->h)); /* Closed, guv'nor                   */
305   if (window_selectionOwner()==w)
306     window__gainSelection(0);
307
308 #ifndef glass_DEMO
309   if (w->testMode)
310   {
311     for (i=0;i<w->def->desc.w.nicons;i++)
312     {
313       wimpt_noerr(wimp_get_icon_info(w->h,i,&icn));
314       if (memcmp(&icn,&w->def->i[i].i,sizeof(wimp_icon)))
315       {
316         tfile_markAsAltered(w->t);
317         w->def->i[i].i=icn;
318       }
319     }
320   }
321   else
322 #endif
323
324   if (w->ownPointer)
325   {
326     win_removeIdleClaimer(window__winIdles,w);
327     window__setPtrShape(window__SELECT);
328   }
329   win_register_event_handler(w->h,0,0); /* Window won't need this now      */
330   wimpt_noerr(wimp_delete_wind(w->h)); /* Delete the window                */
331   w->h=0;                        /* Make sure nobody does anything stupid  */
332
333   if (window__menuOwner()==w)
334     window__updateMenu(0);
335 }
336
337 /*
338  * void window_open(glass_windPointer *w,BOOL test)
339  *
340  * Use
341  *  Opens the specified window.  If the window is off-screen, it is moved
342  *  back.  This routine also registers all handlers required for editing the
343  *  window etc.  If the window is already open, it is brought to the front.
344  *
345  * Parameters
346  *  glass_windPointer *w == pointer to basic window information.
347  *  BOOL test == open in test mode or not
348  */
349
350 void window_open(glass_windPointer *w,BOOL test)
351 {
352   wimp_wstate s;
353   int i;
354
355   /* --- Create the window if it doesn't exist yet --- */
356
357   if (!w->h)
358   {
359     /* --- Allow tfile to set the test flag --- */
360
361   #ifndef glass_DEMO
362     w->testMode=test;
363   #else
364     unused(test);
365   #endif
366
367     /* --- Unselect all the window's icons and guides --- */
368
369     for (i=0;i<w->def->desc.w.nicons;i++)
370     {
371       w->def->i[i].selected=FALSE;
372       w->def->i[i].copied=FALSE;
373     }
374
375     for (i=0;i<glass_GUIDELIMIT;i++)
376       w->guide[i].selected=FALSE;
377     w->lastClicked=-1;
378     w->selno=0;
379     w->ownPointer=FALSE;
380     w->renumber=FALSE;
381
382     /* --- Finally, create the window and attach the event handler --- */
383
384     if (w->h=window__recreate(w),!w->h)
385       return;
386   #ifndef glass_DEMO
387     if (test)
388       win_register_event_handler(w->h,window__testEvents,w);
389     else
390   #endif
391       win_register_event_handler(w->h,window__events,w);
392   }
393   /* --- Now we can open the window --- */
394
395   wimpt_noerr(wimp_get_wind_state(w->h,&s));
396   s.o.behind=-1;                 /* Open the window on top of the screen   */
397   win_adjustBox(&s.o);           /* Make sure it goes on the screen!       */
398   wimpt_noerr(wimp_open_wind(&s.o)); /* Go!                                */
399   wimpt_noerr(wimp_get_wind_state(w->h,&s)); /* Find out where it went     */
400   w->def->desc.w.box=s.o.box;
401   w->def->desc.w.scx=s.o.x;
402   w->def->desc.w.scy=s.o.y;
403   w->def->desc.w.behind=s.o.behind;
404   editWindow_windowMoved(w);
405   if (window_selectionOwner()==w)
406     window_updateToolbar();
407 }