Initial revision
[ssr] / StraySrc / Glass / !Glass / c / glass
1 /*
2 * glass.c
3 *
4 * Main control section and user interface
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 #include <stddef.h>
38 #include <time.h>
39
40 #include "dll.h"
41
42 /*
43 * Steel headers
44 */
45
46 #define _STDAPP
47 #define _XFER
48 #define _LOWLVL
49 #include "steel/Steel.h"
50
51 #include "steel/viewer.h"
52 #include "steel/mem.h"
53 #include "steel/caretptr.h"
54 #include "steel/buttons.h"
55 #include "steel/sculptrix.h"
56 #include "steel/flex.h"
57
58 /*
59 * Glass headers
60 */
61
62 #include "gStruct.h"
63 #include "gIcons.h"
64 #include "gMenus.h"
65
66 #include "glass.h"
67 #include "toolbox.h"
68 #include "tfile.h"
69 #include "intMsgs.h"
70 #include "gPrefs.h"
71 #include "gSprite.h"
72 #include "indir.h"
73 #include "window.h"
74 #include "tearEdit.h"
75
76 /*----- External dependencies ---------------------------------------------*/
77
78 extern char date[], cright[];
79 #define VERSION 100
80
81 /*----- Static global variables -------------------------------------------*/
82
83 static BOOL glass_genDump; /* Send timings to dump (stderr) */
84 static BOOL glass_noWindow; /* Turn off the nice intro window */
85
86 /*----- Icon bar handlers -------------------------------------------------*/
87
88 /*
89 * BOOL glass_unknowns(wimp_eventstr *e,void *handle)
90 *
91 * Use
92 * Vets unknown events. The important ones at the moment are
93 * Message_DataOpen and Message_PreQuit. Glass 1.xx supports the RISC
94 * OS 3 prequit convention to avoid the old misunderstanding. This may
95 * cause problems under RISC OS 2. If so, they'll just have to upgrade...
96 *
97 * Parameters
98 * wimp_eventstr *e == the event in question
99 * void *handle == 0
100 *
101 * Returns
102 * TRUE if the event has now been processed.
103 */
104
105 static BOOL glass_unknowns(wimp_eventstr *e,void *handle)
106 {
107 BOOL handled=FALSE;
108 int filetype;
109 char *filename;
110 char buff[256];
111 os_regset r;
112 unused(handle);
113 switch (e->e)
114 {
115 case wimp_ESEND:
116 case wimp_ESENDWANTACK:
117 switch (e->data.msg.hdr.action)
118 {
119 case wimp_MDATAOPEN:
120 filetype=xferrecv_checkinsert(&filename);
121 switch (filetype)
122 {
123 case 0xfec: /* Template file */
124 xferrecv_insertfileok();
125 tfile_loadFromFile(filename,xferrecv_nameToImport());
126 handled=TRUE;
127 break;
128 }
129 break;
130 case wimp_MPREQUIT:
131 if (tfile_okToQuit(TRUE))
132 intMsgs_send(glass_KILLFILES);
133 else
134 {
135 e->data.msg.hdr.your_ref=e->data.msg.hdr.my_ref;
136 wimpt_noerr(wimp_sendmessage(wimp_EACK,
137 &e->data.msg,
138 e->data.msg.hdr.task));
139 }
140 handled=TRUE;
141 break;
142 case wimp_MMODECHANGE:
143 intMsgs_send(glass_MODECHANGE);
144 break;
145 case wimp_SAVEDESK:
146 sprintf(buff,"Run %s\n",getenv("Glass$Dir"));
147 r.r[0]=2;
148 r.r[1]=e->data.msg.data.savedesk.filehandle;
149 r.r[2]=(int)buff;
150 r.r[3]=strlen(buff);
151 wimpt_noerr(os_swix(XOS_GBPB,&r));
152 handled=TRUE;
153 break;
154 }
155 break;
156 }
157 return (handled);
158 }
159
160 /*
161 * void glass_ibarHandler(ibicon i,ibicon_eventType e,void *handle)
162 *
163 * Use
164 * Handles events for the icon bar icon (such as help requests, load and
165 * save messages, and of course mouse clicks).
166 *
167 * Parameters
168 * ibicon i == the handle of the icon
169 * ibicon_eventType e == what has happened
170 * void *handle == a dummy handle
171 */
172
173 static void glass_ibarHandler(ibicon i,ibicon_eventType e,void *handle)
174 {
175 int filetype; /* Filetype of a file to import */
176 char *filename; /* Filename of a file */
177 int estsize; /* Estimated size of a file to import */
178 void *p; /* Pointer to loaded file */
179 unused(i); /* Not actually interested in the icon */
180 unused(handle); /* Not at all interested in the handle */
181 switch (e) /* Find out what's going on */
182 {
183 case ibicon_LEFTCLICK: /* Clicked with select */
184 {
185 glass_tfile *t;
186 if (t=tfile_createTemplateFile(msgs_lookup("tfUNT")),t)
187 viewer_display(t->v);
188 }
189 break;
190 case ibicon_RIGHTCLICK: /* Clicked with adjust */
191 break; /* Ignore it and hope it goes away */
192 case ibicon_LOAD: /* Load request from Filer */
193 filetype=xferrecv_checkinsert(&filename); /* Get information */
194 switch (filetype)
195 {
196 case 0xfec: /* Template file */
197 tfile_loadFromFile(filename,xferrecv_nameToImport());
198 xferrecv_insertfileok();
199 break;
200 }
201 break;
202 case ibicon_SAVE: /* Save from another application */
203 filetype=xferrecv_checkimport(&estsize); /* Get information */
204 switch (filetype)
205 {
206 case 0xfec: /* Template file */
207 if (xferrecv_returnImportedBlock(&p)!=-1)
208 {
209 tfile_loadFromMemory(&p,xferrecv_nameToImport());
210 flex_free(&p);
211 flex_compact();
212 }
213 break;
214 }
215 break;
216 case ibicon_HELP: /* Help request */
217 help_startHelp(); /* Start a help reply */
218 help_addLine(msgs_lookup("wehIB"));
219 help_endHelp(); /* Send the message back */
220 break;
221 }
222 }
223
224 /*
225 * void glass_ibarMenuHandler(int hit[],void *handle)
226 *
227 * Use
228 * Processes menu clicks for the icon bar menu.
229 *
230 * Parameters
231 * int hit[] == array of menu hits
232 * void *handle == 0 (dummy handle)
233 */
234
235 static void glass_ibarMenuHandler(int hit[],void *handle)
236 {
237 unused(handle); /* This menu not attached to data struct */
238 switch (hit[0]) /* Check which item was chosen */
239 {
240 case glass_IBARINFO: /* About this program */
241 progInfo("Glass",
242 msgs_lookup("wePUR"),
243 cright,
244 VERSION,
245 date);
246 break;
247 case glass_IBARPREFS: /* Preferences dialogue */
248 gPrefs_edit(); /* Edit the preferences... */
249 break;
250 case glass_IBARTBOX: /* Toolbox (window manipulation) */
251 toolbox(); /* Handles it all... */
252 break;
253 case glass_IBARHEAPINFO: /* Heap info display */
254 indir_heapInfo(); /* Display */
255 break;
256 case glass_IBARQUIT: /* Quit program */
257 if (tfile_okToQuit(TRUE)) /* Check the user is sure about this */
258 exit(0); /* End Glass and announce success */
259 break;
260 }
261 }
262
263 /*
264 * void glass_ibarMenuHelp(int hit[],void *handle)
265 *
266 * Use
267 * Help processor for icon bar menu.
268 *
269 * Parameters
270 * int hit[] == the item to give help for
271 * void *handle == a dummy handle
272 */
273
274 static void glass_ibarMenuHelp(int hit[],void *handle)
275 {
276 unused(handle);
277 help_startHelp();
278 help_readFromMenu("wemhIB",hit);
279 help_endHelp();
280 }
281
282 /*----- Initialisation ----------------------------------------------------*/
283
284 /*
285 * void glass_exit(void)
286 *
287 * Use
288 * Exit handler, creates internal broadcast to close down everything.
289 */
290
291 static void glass_exit(void)
292 {
293 intMsgs_send(glass_CLOSEDOWN);
294 }
295
296 /*
297 * void glass_iconbar(void)
298 *
299 * Use
300 * Sets up the icon bar during Glass initialisation. Essentially, it
301 * installs an icon bar, attaches a menu to it, and gives it a handler.
302 * It also establishes a handler for loading and mouse clicks.
303 */
304
305 static void glass_iconbar(void)
306 {
307 ibicon i; /* Handle for the icon we will create */
308 menu m; /* The menu to attach to the icon */
309 m=menu_new("Glass",msgs_lookup("weIBM"));
310 i=ibicon_create(ibicon_RIGHT,"!glass",ibicon_WIMPAREA,0,0);
311 ibicon_attachMenu(i,m,glass_ibarMenuHandler,glass_ibarMenuHelp,0);
312 ibicon_eventHandler(i,glass_ibarHandler,0);
313 }
314
315 /*
316 * void glass_scanCLI(int argc,char *argv[],BOOL inited)
317 *
318 * Use
319 * Scans command line string and loads relevant files
320 *
321 * Parameters
322 * int argc == the number of words in the string
323 * char *argv[] == the words, as an array of strings
324 * BOOL inited == whether we have initialised the WIMP
325 */
326
327 static void glass_scanCLI(int argc,char *argv[],BOOL inited)
328 {
329 int i;
330 for (i=1;i<argc;i++)
331 {
332 if (utils_caselessCmp(argv[i],"-genDump")==0)
333 glass_genDump=TRUE;
334 else if (utils_caselessCmp(argv[i],"-noWindow")==0)
335 glass_noWindow=TRUE;
336 else if (utils_caselessCmp(argv[i],"-help")==0)
337 {
338 printf
339 (
340 "Glass %i.%02i (%s)\n"
341 "\n"
342 "%s"
343 "\n"
344 "Command line syntax:\n"
345 " Glass [<option> | <filename>]...\n"
346 "\n"
347 "<filename> == file name to load\n"
348 "<option> is one of:\n"
349 " -help == display this help\n"
350 " -genDump == dump timings and other crap to stderr\n"
351 " -noWindow == don't display startup window\n",
352 VERSION / 100,
353 VERSION % 100,
354 date, cright
355 );
356 exit(0);
357 }
358 else
359 {
360 if (inited)
361 tfile_loadFromFile(argv[i],argv[i]);
362 }
363 }
364 }
365
366 /*
367 * void glass_wait(int cs)
368 *
369 * Use
370 * Makes everything stand still for a bit
371 *
372 * Parameters
373 * in cs == number of centiseconds to wait
374 */
375
376 static void glass_wait(int cs)
377 {
378 int waiting;
379 os_regset r;
380 wimpt_noerr(os_swix(XOS_ReadMonotonicTime,&r)); /* Now wait for a bit */
381 waiting=r.r[0];
382 while (r.r[0]-waiting<cs) /* Half a second should do... */
383 wimpt_noerr(os_swix(XOS_ReadMonotonicTime,&r)); /* Get the time again */
384 }
385
386 /*
387 * void glass_initProgress(dbox d,char *message,int percent)
388 *
389 * Use
390 * Updates the display on the loading window while we;re initialising
391 * everything.
392 *
393 * Parameters
394 * dbox d == the dbox being used
395 * char *message == the message to display in the little icon. A null
396 * pointer indicates that the message is not to change.
397 * int percent == the percentage complete so far
398 */
399
400 static void glass_initProgress(dbox d,char *message,int percent)
401 {
402 static dbox dd;
403 if (!dd)
404 dd=d;
405 else if (!d)
406 d=dd;
407 if (d)
408 {
409 buttons_updateSlider(d,glass_CRSLIDER,100,percent,8,FALSE);
410 dbox_setfield(d,glass_CRPERCENT,"%i",percent);
411 if (message)
412 dbox_setfield(d,glass_CRDOING,"%s",message);
413 }
414 else
415 visdelay_percent(percent);
416 if (glass_genDump)
417 {
418 fprintf(stderr,
419 "Glass init timing: %s - %i\n",
420 message ? message : "ditto",
421 clock());
422 }
423 }
424
425 /*
426 * void glass_initialise(int argc,char *argv[])
427 *
428 * Use
429 * Does all the tedious initialisation procedure, and the bit with the
430 * intro window.
431 *
432 * Parameters
433 * int argc == the number of words in the CLI string
434 * char *argv[] == the words, as an array of strings
435 */
436
437 static void glass_initialise(int argc,char *argv[])
438 {
439 sprite_area *a=0;
440 os_regset r;
441 dbox d=0;
442 wimp_redrawstr rdr;
443 BOOL more;
444
445 _dll_setname("Glass");
446
447 glass_scanCLI(argc,argv,FALSE); /* Scan command line arguments */
448 visdelay_begin(); /* Turn on the hourglass immediately */
449
450 /* --- Set up STEEL's options --- *
451 *
452 * We need to enable all the external module support, because we need
453 * to handle templates written to use them. The non-WIMP shading is just
454 * a nice touch.
455 */
456
457 #ifdef glass_DEBUGGING
458 #define _options \
459 wimpt_OSCULPTRIX | \
460 wimpt_OINTERFACE | \
461 wimpt_OWIMPEXT | \
462 wimpt_ONOWIMPSHADE | \
463 wimpt_OREMSAVEICON
464 #else
465 #define _options \
466 wimpt_OSCULPTRIX | \
467 wimpt_OINTERFACE | \
468 wimpt_OWIMPEXT | \
469 wimpt_ONOWIMPSHADE | \
470 wimpt_OREMSAVEICON | \
471 wimpt_ONOBACKTRACE
472 #endif
473
474 wimpt_setOptions(_options,_options);
475
476 wimpt_init("Glass"); /* Crank up the WIMP */
477 res_init("Glass"); /* Point to resource files */
478 mem_flexdInit(0, 0); /* Initialise flex system */
479
480 resspr_init(); /* Load my copious quantities of sprites */
481 if (!glass_noWindow)
482 {
483 template_readfile(res_name("LoadTpl"));
484
485 r.r[0]=17; /* Need to find the size of banner sprite */
486 r.r[1]=(int)res_name("LoadSpr"); /* Set up name */
487 wimpt_noerr(os_swix(XOS_File,&r)); /* Do the call */
488 if (!flex_alloc((flex_ptr)&a,r.r[4]+4)) /* Allocate memory for sprites*/
489 a=0; /* If failed, don't show sprites */
490 else
491 {
492 sprite_area_initialise(a,r.r[4]+4); /* Initialise sprite area (!) */
493 wimpt_noerr(sprite_area_load(a,res_name("LoadSpr")));
494 /* Do the load as required */
495 template_syshandle("loading")->spritearea=a; /* Rig sprite area */
496 }
497 if (d=dbox_create("loading"),d) /* Create the dialogue box */
498 {
499 dbox_setfield(d,
500 glass_CRVERSION,
501 "%i.%02i (%s)",
502 VERSION/100,
503 VERSION%100,
504 date);
505 dbox_setfield(d, glass_CRGPLNOTE,
506 "Glass is free software; it may be modified and/or "
507 "redistributed under the terms of the GNU General "
508 "Public License.");
509 dbox_setfield(d, glass_CRNOWARRANTY,
510 "Glass is distributed in the hope that it will be "
511 "useful, but WITHOUT ANY WARRANTY.");
512 dbox_display(d,dbox_STATIC_CENTRE); /* Display */
513 rdr.w=dbox_syshandle(d); /* Draw the window on the screen NOW */
514 wimpt_noerr(wimp_redraw_wind(&rdr,&more)); /* Start redraw process */
515 while (more) /* Carry on till it's all done */
516 {
517 wimpt_noerr(sculptrix_redrawWindow(&rdr)); /* Do the 3D bitties */
518 buttons_redrawSlider(d,glass_CRSLIDER,100,0,8,FALSE); /* Slider */
519 wimpt_noerr(wimp_get_rectangle(&rdr,&more)); /* Get the next bit */
520 }
521 }
522 else
523 visdelay_percent(0); /* If no box, give percentage, at least */
524
525 if (a)
526 {
527 flex_free((flex_ptr)&a);
528 flex_compact();
529 }
530 }
531 else
532 visdelay_percent(0); /* If no box, give percentage, at least */
533
534 glass_initProgress(d,msgs_lookup("weILM:Loading messages"),0);
535 msgs_init(); /* Read messages file (for help messages) */
536
537 glass_initProgress(d,msgs_lookup("weILW"),15);
538 template_init();
539 werr_init(); /* Load nice error box */
540
541 glass_initProgress(d,msgs_lookup("weLDF"),43);
542 gSprite_init();
543 window_init();
544 tearEdit_init();
545
546 glass_iconbar(); /* Set up the icon bar appropriately */
547
548 glass_initProgress(d,msgs_lookup("weIRP"),53);
549 gPrefs_init();
550
551 caretPtr("ptr_caret",resspr_area(),4,5); /* Enable pointer change */
552 win_add_unknown_event_processor(glass_unknowns,0); /* OPEN, PREQUIT */
553 event_returnMenuHelp(TRUE);
554
555 glass_initProgress(d,msgs_lookup("weILD"),61);
556 indir_init();
557 glass_scanCLI(argc,argv,TRUE); /* Scan command line arguments again */
558 if (d)
559 dbox_display(d,dbox_STATIC_LASTPOS);
560 atexit(glass_exit); /* Exit handler to free up fonts */
561
562 if (d)
563 {
564 glass_initProgress(d,msgs_lookup("weIFI"),100);
565 glass_wait(50);
566 dbox_delete(d);
567 }
568
569 visdelay_end(); /* Finished initialisation */
570 }
571
572 /*
573 * int main(int argc,char *argv[])
574 *
575 * Use
576 * Control initially passed to this routine. It essentially sets up all
577 * initial handlers (the icon bar etc.) and lets the event system handle
578 * the rest.
579 *
580 * Parameters
581 * int argc == the number of command line arguments passed
582 * char *argv == an array of command line arguments
583 *
584 * Returns
585 * zero == successful completion
586 * nonzero == abnormal termination
587 *
588 * Defined return codes are:
589 */
590
591 int main(int argc,char *argv[])
592 {
593 exception_handler e; /* Point to return to on an exception */
594 glass_initialise(argc,argv); /* Perform necessary initialisation */
595 visdelay_begin(); /* Display hourglass between polls */
596 (void)exception_registerHandler(e); /* Return here if anything goes amiss*/
597 mem_useMalloc(); /* Ensure use of standard heap */
598 for(;;) /* And now, just process events until... */
599 event_process(); /* ...kingdom come. */
600 return (0); /* Return successfully */
601 }