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 }