chiark / gitweb /
Initial revision
[ssr] / StraySrc / Glass / !Glass / c / wWinEvent
1 /*
2  * wWinEvent.c
3  *
4  * Handling events for 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/interface.h"
47 #include "steel/sculptrix.h"
48 #include "steel/caretPtr.h"
49 #include "steel/akbd.h"
50 #include "steel/bbc.h"
51
52 /*
53  * Glass headers
54  */
55
56 #include "gStruct.h"
57 #include "gMenus.h"
58 #include "gIcons.h"
59
60 #include "glass.h"
61 #include "gPrefs.h"
62 #include "tfile.h"
63 #include "window.h"
64 #include "_window.h"
65 #include "intMsgs.h"
66 #include "toolbox.h"
67 #include "editIcon.h"
68 #include "editWin.h"
69 #include "tearEdit.h"
70
71 /*----- Main code ---------------------------------------------------------*/
72
73 /*
74  * void window__winIdles(void *handle)
75  *
76  * Use
77  *  Changes the pointer shape to something appropriate for what its over.
78  *
79  * Parameters
80  *  void *handle == pointer to window containing pointer
81  */
82
83 void window__winIdles(void *handle)
84 {
85   glass_windPointer *w=handle;
86   int i=window__pointerInfo(w,-1,TRUE);
87 #ifndef glass_DEMO
88   if (w->testMode)
89     i=window__SELECT;
90 #endif
91   window__setPtrShape(i);
92   window__updateInfoBar(FALSE);
93 }
94
95 /*
96  * int window__keyAhead(int k,int *nk)
97  *
98  * Use
99  *  Counts how many times the given key k is pressed, and returns the next
100  *  key in *nk (or -1 if no next key).
101  *
102  * Parameters
103  *  int k == the key to check for
104  *  int *nk == where to store next key value
105  *
106  * Returns
107  *  Number of times key was buffered.
108  */
109
110 static int window__keyAhead(int k,int *nk)
111 {
112   int count=0;
113   *nk=k;
114   while (*nk==k)
115   {
116     count++;
117     if (!akbd_pollkey(nk))
118       *nk=-1;
119     else
120       *nk=akbd_translate(*nk);
121   }
122   return (count);
123 }
124
125 /*
126  * void window__testEvents(wimp_eventstr *e,void *handle)
127  *
128  * Use
129  *  Handles all events for windows running in Test mode.  Events handled
130  *  are:
131  *
132  *  Redraw   Redraws the window using Interface/hatch pattern as requested.
133  *  Open     Moves the window around.
134  *  Close    Closes the window(!)
135  *  Leave    Ignored
136  *  Enter    Turn off STEEL pointer changing
137  *  Click    Handled by WIMP or Interface, except for menu, which opens
138  *           the menu(!)
139  *  Key      Handled by WIMP, WimpExtension, or ignored
140  *
141  * Parameters
142  *  wimp_eventstr *e == the event
143  *  void *handle == pointer to window info
144  */
145
146 #ifndef glass_DEMO
147
148 void window__testEvents(wimp_eventstr *e,void *handle)
149 {
150   glass_windPointer *w=handle; /* Extract my data from the handle       */
151   wimp_wstate s;
152   int ox,oy;
153   wimp_redrawstr r;              /* For the redraw event                   */
154   BOOL more;                     /* To tell me when I've finished          */
155   wimp_w wnd;
156   os_regset reg;
157   wimp_icon icon;
158   sculptrix_slabDescriptor d;
159
160   switch (e->e)
161   {
162     case wimp_EREDRAW:
163       r.w=w->h;
164       wimpt_noerr(wimp_redraw_wind(&r,&more)); /* Start the redraw         */
165       window__redraw(w,&r,&more);
166       break;
167     case wimp_EOPEN:
168       if (e->data.o.x<=w->def->desc.w.scx &&
169           e->data.o.y>=w->def->desc.w.scy)
170       {
171         r.w=e->data.o.w;
172         r.box=w->tex;
173         if (tst(w->def->desc.w.flags,14))
174         {
175           r.box.x0=w->def->desc.w.ex.x0;
176           r.box.x1=max2(w->def->desc.w.ex.x1,e->data.o.x+e->data.o.box.x1-
177                                                          e->data.o.box.x0);
178         }
179         if (tst(w->def->desc.w.flags,15))
180         {
181           r.box.y1=w->def->desc.w.ex.y1;
182           r.box.y0=min2(w->def->desc.w.ex.y0,e->data.o.y-e->data.o.box.y1+
183                                                          e->data.o.box.y0);
184         }
185         if (memcmp(&r.box,&w->tex,sizeof(wimp_box)))
186         {
187           wimpt_noerr(wimp_set_extent(&r));
188           w->tex=r.box;
189         }
190       }
191
192       if (window_selectionOwner()==w)
193         window__setToolBarPositions(&e->data.o);
194       else
195         wimpt_noerr(wimp_open_wind(&e->data.o));
196       w->def->desc.w.box=e->data.o.box; /* Copy the information down       */
197       w->def->desc.w.scx=e->data.o.x;
198       w->def->desc.w.scy=e->data.o.y;
199       w->def->desc.w.behind=e->data.o.behind;
200       if (!w->t->alts)           /* Moving the window alters the template  */
201         tfile_markAsAltered(w->t); /* But only if not already altered      */
202       if (wimpt_justChangedMode() && w->antiAliased)
203       {
204         if (wnd=window__recreate(w),!wnd)
205           return;
206         win_register_event_handler(wnd,window__testEvents,w);
207         wimpt_noerr(wimp_get_wind_state(w->h,&s));
208         wimpt_noerr(wimp_delete_wind(w->h));
209         win_register_event_handler(w->h,0,0);
210         win_activedec();
211         w->h=wnd;
212         s.o.w=w->h;
213         wimpt_noerr(wimp_open_wind(&s.o));
214       }
215       break;
216     case wimp_ECLOSE:
217       window_close(w);
218       break;
219     case wimp_EBUT:
220       e=wimpt_last_event();      /* Get the real event                     */
221       switch (e->data.but.m.bbits)
222       {
223         case wimp_BMID:
224           if (gPrefs_current()->sSlabMenu && e->data.but.m.i!=-1)
225             sculptrix_slabIcon(e->data.but.m.w,e->data.but.m.i,&d);
226           if (gPrefs_current()->iSlabMenu && e->data.but.m.i!=-1)
227           {
228             wimpt_noerr(wimp_get_icon_info(w->h,e->data.but.m.i,&icon));
229             interface_slabButton(&e->data.but.m);
230           }
231           wimpt_noerr(wimp_get_wind_state(w->h,&s));
232           ox=s.o.box.x0-s.o.x;
233           oy=s.o.box.y1-s.o.y;
234           window__showMenu(e->data.but.m.x-ox,e->data.but.m.y-oy,w);
235           e->data.but.m.bbits=0;
236           if (gPrefs_current()->iSlabMenu && e->data.but.m.i!=-1)
237           {
238             interface_slabButton(&e->data.but.m);
239             if (icon.flags & wimp_IFONT)
240             {
241               wimpt_noerr(wimp_set_icon_state(w->h,
242                                               e->data.but.m.i,
243                                               icon.flags & 0xff000000,
244                                               0xff000000));
245             }
246           }
247           if (gPrefs_current()->sSlabMenu && e->data.but.m.i!=-1)
248             sculptrix_unslabIcon(&d);
249           break;
250         case wimp_BDRAGLEFT:
251         case wimp_BDRAGRIGHT:
252           break;
253         default:
254           if (gPrefs_current()->sSlabIcons && e->data.but.m.i!=-1)
255             sculptrix_slabIcon(e->data.but.m.w,e->data.but.m.i,&d);
256
257           if (gPrefs_current()->iSlabIcons && e->data.but.m.i!=-1)
258           {
259             wimpt_noerr(wimp_get_icon_info(w->h,e->data.but.m.i,&icon));
260             interface_slabButton(&e->data.but.m);
261             e->data.but.m.bbits=0;
262             interface_slabButton(&e->data.but.m);
263             if (icon.flags & wimp_IFONT)
264             {
265               wimpt_noerr(wimp_set_icon_state(w->h,
266                                               e->data.but.m.i,
267                                               icon.flags & 0xff000000,
268                                               0xff000000));
269             }
270           }
271
272           if (gPrefs_current()->sSlabIcons && e->data.but.m.i!=-1)
273             sculptrix_unslabIcon(&d);
274           break;
275       }
276       break;
277     case wimp_EPTRLEAVE:
278       w->ownPointer=FALSE;
279       win_removeIdleClaimer(window__winIdles,w);
280       window__updateInfoBar(FALSE);
281       window__setPtrShape(window__SELECT);
282       interface_spritearea((sprite_area *)1);
283       break;
284     case wimp_EPTRENTER:
285       w->ownPointer=TRUE;
286       win_addIdleClaimer(window__winIdles,win_DONTCARE,w);
287       caretPtr__pointer(FALSE); /* Don't change pointer in this window */
288       interface_spritearea(w->t->s);
289       break;
290     case wimp_EKEY:
291       if (gPrefs_current()->wKeyPress)
292       {
293         reg.r[0]=e->data.key.chcode;
294         reg.r[2]=w->h;
295         reg.r[3]=e->data.key.c.i;
296         os_swix(XWimpExt_MoveCaret,&reg);
297         if (reg.r[0])
298           wimpt_noerr(wimp_processkey(e->data.key.chcode));
299         else
300         {
301           reg.r[0]=2;
302           reg.r[2]=-1;
303           os_swix(XWimpExt_ViewIcon,&reg);
304
305           /* --- That may have moved the window, so... --- */
306
307           wimpt_noerr(wimp_get_wind_state(w->h,&s));
308           if (s.o.x!=w->def->desc.w.scx || s.o.y!=w->def->desc.w.scy)
309           {
310             w->def->desc.w.scx=s.o.x;
311             w->def->desc.w.scy=s.o.y;
312             if (!w->t->alts)
313               tfile_markAsAltered(w->t);
314           }
315         }
316       }
317       else
318         wimpt_noerr(wimp_processkey(e->data.key.chcode));
319       break;
320     case wimp_ESEND:
321     case wimp_ESENDWANTACK:
322       window__events(e,w);
323       break;
324   }
325 }
326
327 #endif
328
329 /*
330  * void window__events(wimp_eventstr *e,void *handle)
331  *
332  * Use
333  *  Handles all events for template windows (this is the first chance I've
334  *  had to get my fingers *REALLY* mucky on this whole project!)
335  *
336  * Parameters
337  *  wimp_eventstr *e == the event that I am meant to be inerested in
338  *  void *handle == a pointer to the structural information for this window
339  */
340
341 void window__events(wimp_eventstr *e,void *handle)
342 {
343   glass_windPointer *w=handle;   /* Extract my data from the handle        */
344   wimp_redrawstr r;              /* For the redraw event                   */
345   BOOL more;                     /* To tell me when I've finished          */
346   int i;
347   int zone;
348   glass_intMsgstr *m;
349   wimp_wstate s;
350   wimp_w wnd;
351   wimp_caretstr c;
352   int ox=0,oy=0;
353   int set=FALSE;
354   wimp_box b;
355   BOOL started=FALSE;
356   static BOOL dontDrag;           /* Disable/ignore next drag event        */
357   glass_iconDescription icd;
358   wimp_box bound;
359   int dragType;
360   int key,okey;
361
362   switch (e->e)
363   {
364     case wimp_EREDRAW:
365       r.w=w->h;
366       wimpt_noerr(wimp_redraw_wind(&r,&more)); /* Start the redraw         */
367       window__redraw(w,&r,&more);
368       break;
369     case wimp_EOPEN:
370
371       /* --- Handle rubbery extents --- *
372        *
373        * We've got to make sure the window's not scrolling here, otherwise
374        * very strange things start happening.
375        */
376
377       if (e->data.o.x<=w->def->desc.w.scx &&
378           e->data.o.y>=w->def->desc.w.scy)
379       {
380         r.w=e->data.o.w;
381         r.box=w->tex;
382         if (tst(w->def->desc.w.flags,14))
383         {
384           r.box.x0=w->def->desc.w.ex.x0;
385           r.box.x1=max2(w->def->desc.w.ex.x1,e->data.o.x+e->data.o.box.x1-
386                                                          e->data.o.box.x0);
387         }
388         if (tst(w->def->desc.w.flags,15))
389         {
390           r.box.y1=w->def->desc.w.ex.y1;
391           r.box.y0=min2(w->def->desc.w.ex.y0,e->data.o.y-e->data.o.box.y1+
392                                                          e->data.o.box.y0);
393         }
394         if (memcmp(&r.box,&w->tex,sizeof(wimp_box)))
395         {
396           wimpt_noerr(wimp_set_extent(&r));
397           w->tex=r.box;
398         }
399       }
400
401       if (window_selectionOwner()==w)
402         window__setToolBarPositions(&e->data.o);
403       else
404         wimpt_noerr(wimp_open_wind(&e->data.o));
405       w->def->desc.w.box=e->data.o.box; /* Copy the information down       */
406       w->def->desc.w.scx=e->data.o.x;
407       w->def->desc.w.scy=e->data.o.y;
408       w->def->desc.w.behind=e->data.o.behind;
409       if (!w->t->alts)           /* Moving the window alters the template  */
410         tfile_markAsAltered(w->t); /* But only if not already altered      */
411       editWindow_windowMoved(w);
412       if (wimpt_justChangedMode() && w->antiAliased)
413       {
414         if (wnd=window__recreate(w),!wnd)
415           return;
416         win_register_event_handler(wnd,window__events,w);
417         wimpt_noerr(wimp_get_wind_state(w->h,&s));
418         wimpt_noerr(wimp_delete_wind(w->h));
419         win_register_event_handler(w->h,0,0);
420         win_activedec();
421         w->h=wnd;
422         s.o.w=w->h;
423         wimpt_noerr(wimp_open_wind(&s.o));
424       }
425       break;
426     case wimp_ECLOSE:
427       window_close(w);
428       break;
429     case wimp_EBUT:
430       if (window__qDragType()!=-1)
431         break;
432       switch (e->data.but.m.bbits)
433       {
434          case wimp_BMID:
435           wimpt_noerr(wimp_get_wind_state(w->h,&s));
436           ox=s.o.box.x0-s.o.x;
437           oy=s.o.box.y1-s.o.y;
438           window__showMenu(e->data.but.m.x-ox,e->data.but.m.y-oy,w);
439           break;
440         case wimp_BLEFT:
441           if (!(akbd_pollsh() && (w->lastClicked!=-1)) &&
442               !w->renumber &&
443               (!gPrefs_current()->mCtrlEdit || akbd_pollctl()))
444           {
445             i=window__pointerInfo(w,-1,TRUE);
446             if ((i & window__ZONEMASK)==window__HORGUIDE ||
447                 (i & window__ZONEMASK)==window__VERGUIDE)
448               break;
449             if (i!=-1)
450               editIcon(w,i&window__ICONMASK);
451             else
452             {
453               i=window__pointerInfo(w,-1,FALSE);
454               if (i!=-1)
455                 editIcon(w,i);
456               else
457                 editWindow(w);
458             }
459             break;
460           }
461           /* Otherwise drop through to select... */
462         case wimp_BRIGHT:
463           /* Treat this as a normal click - drop to select */
464         case wimp_BCLICKLEFT:
465         case wimp_BCLICKRIGHT:
466
467           /* --- if we're in the toolbox, or grab mode, ignore click --- */
468
469           if (toolbox_toolSelected() || window_grabbing())
470           {
471             dontDrag=TRUE;      /* The WIMP gives a drag on grab sprites!  */
472             break;
473           }
474
475           /* --- give this window the selection, tool bars, and caret --- */
476
477           window__gainSelection(w);
478
479           /* --- special case for renumbering --- */
480
481           if (w->renumber)
482           {
483             i=window__pointerInfo(w,-1,FALSE);
484             if (!(i & window__ZONEMASK) && w->def->i[i].selected)
485             {
486               set=window__lowestSelected(w);
487               window__select(w,i,FALSE);
488               icd=w->def->i[i];
489               w->def->i[i]=w->def->i[set];
490               w->def->i[set]=icd;
491               window_redrawIcon(w,i);
492               window_redrawIcon(w,set);
493               tfile_markAsAltered(w->t);
494               if (w->selno)
495                 window__nextRenumber(w);
496               else
497                 window__renumber(w,FALSE);
498             }
499             window__updateMenu(w); /* May have changed focus */
500             break;
501           }
502
503           /* --- handle depthwise selection - no problem with guides --- */
504           /* --- because we know the pointer is over an icon --- */
505
506           if (akbd_pollsh() &&
507               w->lastClicked!=-1 &&
508               window__pointerOverIcon(w,w->lastClicked))
509           {
510             i=w->lastClicked;
511             w->lastClicked=window__pointerInfo(w,w->lastClicked,FALSE);
512             if (i!=w->lastClicked)
513             {
514               if (i==window__selectedIcon())
515                 window__setSelectedIconDeselecting(w->lastClicked);
516               else
517               {
518                 window__select(w,i,FALSE);
519                 window__select(w,w->lastClicked,TRUE);
520               }
521             }
522             dontDrag=TRUE;
523             window__updateMenu(w);
524             break;
525           }
526
527           /* --- this is the complicated bit.  ADJUST should just --- */
528           /* --- toggle the object.  So do this, but remember, it --- */
529           /* --- could have been a double-click --- */
530
531           if (e->data.but.m.bbits==wimp_BCLICKRIGHT ||
532               e->data.but.m.bbits==wimp_BRIGHT)
533           {
534             i=window__pointerInfo(w,-1,FALSE);
535             if (i != -1 && (i & window__ZONEMASK)) {
536               i &= window__ICONMASK;
537               w->guide[i].selected=!w->guide[i].selected;
538               window__redrawGuide(w,i);
539               dontDrag=TRUE;
540             } else {
541               if (i!=-1)
542               {
543                 window__select(w,i,!w->def->i[i].selected);
544                 w->lastClicked=i;
545                 dontDrag=TRUE;
546               }
547               else
548                 dontDrag=FALSE;
549             }
550             window__updateMenu(w);
551             break;
552           }
553
554           /* --- now we're left with a SELECT click.  If this is the --- */
555           /* --- start of a drag, then ignore it, otherwise do normal --- */
556           /* --- SELECT-type things (deselecting other icons etc.) --- */
557
558           i=window__pointerInfo(w,-1,TRUE);
559           if (i==-1)
560           {
561             i=window__pointerInfo(w,-1,FALSE);
562             zone=-1;
563           }
564           else
565           {
566             zone=i & window__ZONEMASK;
567             i&=window__ICONMASK;
568           }
569           w->lastClicked=i;
570
571           switch (zone)
572           {
573             case -1:             /* Not previously selected                */
574               if (w->lastClicked!=-1)
575                 window__setSelectedIconDeselecting(w->lastClicked);
576               for (i=0;i<w->def->desc.w.nicons;i++)
577               {
578                 if (i!=w->lastClicked)
579                   window__select(w,i,FALSE);
580               }
581               dontDrag=FALSE;
582               break;
583             case window__HORGUIDE:
584             case window__VERGUIDE:
585               if (!w->guide[i].selected)
586               {
587                 for (i=0;i<glass_GUIDELIMIT;i++)
588                 {
589                   if (w->guide[i].selected)
590                   {
591                     w->guide[i].selected=FALSE;
592                     window__redrawGuide(w,i);
593                   }
594                 }
595                 w->guide[w->lastClicked].selected=TRUE;
596                 window__redrawGuide(w,w->lastClicked);
597               }
598               dontDrag=FALSE;
599               break;
600             default:
601               /* --- Any other zones we ignore - these are for drag --- */
602               /* --- operations --- */
603               window__setSelectedIcon(w->lastClicked);
604               dontDrag=FALSE;
605               break;
606           }
607           window__updateMenu(w);
608           break;
609         case wimp_BDRAGLEFT:
610         case wimp_BDRAGRIGHT:
611           if (dontDrag ||
612               toolbox_toolSelected() ||
613               window_grabbing() ||
614               w->renumber)
615             break;
616
617           /* --- YARB -- Yet Another RISC OS Bug --- *
618            *
619            * In a terribly cunning way, the WIMP gives me drag events even
620            * when the mouse button is up and the user didn't drag at all.
621            * This is phenomenally irritating, and so, hi-ho, a bodging we
622            * will go...
623            */
624
625           bbc_mouse(0,0,&i,0);
626           if (!i)
627             return;
628
629           if (e->data.but.m.bbits==wimp_BDRAGLEFT)
630           {
631             i=window__pointerInfo(w,-1,TRUE);
632             if (i == -1)
633               dragType = window__SELECT;
634             else
635               dragType=i & window__ZONEMASK;
636           }
637           else
638             dragType=window__SELECT;
639           switch (dragType)
640           {
641             case window__SELECT:
642             case window__HORGUIDE:
643             case window__VERGUIDE:
644               break;
645             default:
646               for (i=0;i<w->def->desc.w.nicons;i++)
647               {
648                 if (w->def->i[i].selected)
649                 {
650                   window_boundingBox(w,i,&b);
651                   if (!started)
652                   {
653                     bound=b;
654                     started=TRUE;
655                   }
656                   else
657                   {
658                     if (bound.x0>b.x0)
659                       bound.x0=b.x0;
660                     if (bound.x1<b.x1)
661                       bound.x1=b.x1;
662                     if (bound.y0>b.y0)
663                       bound.y0=b.y0;
664                     if (bound.y1<b.y1)
665                       bound.y1=b.y1;
666                   }
667                 }
668               }
669               bound.x1-=wimpt_dx();
670               bound.y1-=wimpt_dy();
671               break;
672           }
673           wimpt_noerr(wimp_get_wind_state(w->h,&s));
674           ox=s.o.box.x0-s.o.x;
675           oy=s.o.box.y1-s.o.y;
676           window__startDrag(dragType,
677                             &bound,
678                             w,
679                             e->data.but.m.x-ox,
680                             e->data.but.m.y-oy);
681           break;
682       }
683       break;
684     case wimp_EPTRLEAVE:
685       w->ownPointer=FALSE;
686       win_removeIdleClaimer(window__winIdles,w);
687       window__updateInfoBar(FALSE);
688       window__setPtrShape(window__SELECT);
689       break;
690     case wimp_EPTRENTER:
691       w->ownPointer=TRUE;
692       win_addIdleClaimer(window__winIdles,win_DONTCARE,w);
693       if (window__qDragType()==window__GRABICON && !window__dragWind())
694         window__setDragWind(w);
695       break;
696     case wimp_EKEY:
697       key=akbd_translate(e->data.key.chcode);
698       while (key!=-1)
699       {
700         okey=key;
701         key=-1;
702         switch (okey)
703         {
704
705           /* --- Normal short-cuts, simulate menu entries --- */
706
707           case key_cF1:
708             window__simMenu(w,glass_TWMISC,glass_TWMINFO);
709             break;
710           case key_cW:
711             window__simMenu(w,glass_TWMISC,glass_TWMEDITWIN);
712             break;
713           case key_cT:
714             window__simMenu(w,glass_TWMISC,glass_TWMTEST);
715             break;
716           case key_cF2:
717             window__simMenu(w,glass_TWMISC,glass_TWMCLOSE);
718             break;
719           case key_F3:
720             window__simMenu(w,glass_TWSAVE,0);
721             break;
722           case key_cA:
723             window__simMenu(w,glass_TWSELECT,glass_TWSALL);
724             break;
725           case key_cZ:
726             window__simMenu(w,glass_TWSELECT,glass_TWSCLR);
727             break;
728           case key_cC:
729             window__simMenu(w,glass_TWSELECT,glass_TWSCOPY);
730             break;
731           case key_cX:
732             window__simMenu(w,glass_TWSELECT,glass_TWSDEL);
733             break;
734           case key_cR:
735             window__simMenu(w,glass_TWSELECT,glass_TWSORDER);
736             break;
737           case key_scF:
738             window__simMenu(w,glass_TWSELECT,glass_TWSFRONT);
739             break;
740           case key_cF:
741             window__simMenu(w,glass_TWSELECT,glass_TWSRAISE);
742             break;
743           case key_cB:
744             window__simMenu(w,glass_TWSELECT,glass_TWSLOWER);
745             break;
746           case key_scB:
747             window__simMenu(w,glass_TWSELECT,glass_TWSBACK);
748             break;
749           case key_cP:
750             window__simMenu(w,glass_TWSELECT,glass_TWSPULL);
751             break;
752           case key_cL:
753             window__simMenu(w,glass_TWSELECT,glass_TWSALIGN);
754             break;
755           case key_scE:
756             tearEdit_open();
757             break;
758           case key_cE:
759             window__simMenu(w,glass_TWSELECT,glass_TWSEDIT);
760             break;
761         #ifdef glass_NOTLAZY
762           case key_cD:
763             window__simMenu(w,glass_TWSELECT,glass_TWSDATA);
764             break;
765         #endif
766           case key_cN:
767             window__simMenu(w,glass_TWICON,glass_TWINEW);
768             break;
769           case key_cG:
770             window__simMenu(w,glass_TWICON,glass_TWIGRAB);
771             break;
772
773           /* --- Cursor keys -- move icons around --- */
774
775           /* No modifiers -- move the whole icon */
776
777           case key_Up:
778             b.y0=b.y1=window__keyAhead(okey,&key);
779             b.x0=b.x1=0;
780             window__nudgeIcons(w,&b);
781             break;
782           case key_Down:
783             b.y0=b.y1=-window__keyAhead(okey,&key);
784             b.x0=b.x1=0;
785             window__nudgeIcons(w,&b);
786             break;
787           case key_Left:
788             b.y0=b.y1=0;
789             b.x0=b.x1=-window__keyAhead(okey,&key);
790             window__nudgeIcons(w,&b);
791             break;
792           case key_Right:
793             b.y0=b.y1=0;
794             b.x0=b.x1=window__keyAhead(okey,&key);
795             window__nudgeIcons(w,&b);
796             break;
797
798           /* Control pressed -- move the most significant edge */
799
800           case key_cUp:
801             b.y1=window__keyAhead(okey,&key);
802             b.x0=b.x1=b.y0=0;
803             window__nudgeIcons(w,&b);
804             break;
805           case key_cDown:
806             b.y1=-window__keyAhead(okey,&key);
807             b.x0=b.x1=b.y0=0;
808             window__nudgeIcons(w,&b);
809             break;
810           case key_cLeft:
811             b.x1=-window__keyAhead(okey,&key);
812             b.y0=b.y1=b.x0=0;
813             window__nudgeIcons(w,&b);
814             break;
815           case key_cRight:
816             b.x1=window__keyAhead(okey,&key);
817             b.y0=b.y1=b.x0=0;
818             window__nudgeIcons(w,&b);
819             break;
820
821           /* Shift pressed -- move the least significant edge */
822
823           case key_sUp:
824             b.y0=window__keyAhead(okey,&key);
825             b.x0=b.x1=b.y1=0;
826             window__nudgeIcons(w,&b);
827             break;
828           case key_sDown:
829             b.y0=-window__keyAhead(okey,&key);
830             b.x0=b.x1=b.y1=0;
831             window__nudgeIcons(w,&b);
832             break;
833           case key_sLeft:
834             b.x0=-window__keyAhead(okey,&key);
835             b.y0=b.y1=b.x1=0;
836             window__nudgeIcons(w,&b);
837             break;
838           case key_sRight:
839             b.x0=window__keyAhead(okey,&key);
840             b.y0=b.y1=b.x1=0;
841             window__nudgeIcons(w,&b);
842             break;
843
844           /* Shift and control pressed -- scroll the window --- */
845
846           case key_scUp:
847             window__nudgeScroll(w,0,window__keyAhead(okey,&key));
848             break;
849           case key_scDown:
850             window__nudgeScroll(w,0,-window__keyAhead(okey,&key));
851             break;
852           case key_scLeft:
853             window__nudgeScroll(w,-window__keyAhead(okey,&key),0);
854             break;
855           case key_scRight:
856             window__nudgeScroll(w,window__keyAhead(okey,&key),0);
857             break;
858
859           /* --- No match -- pass on keypress --- */
860
861           default:
862             wimp_processkey(e->data.key.chcode);
863             break;
864         }
865       }
866       break;
867     case wimp_ESEND:
868     case wimp_ESENDWANTACK:
869       switch (e->data.msg.hdr.action)
870       {
871         case wimp_MHELPREQUEST:
872           help_startHelp();
873           help_addLine(msgs_lookup("wdhWIN"),w->id);
874           if (i=window__pointerInfo(w,-1,FALSE),i!=-1)
875             help_addLine(msgs_lookup("wdhICN"),i);
876           else
877             help_addLine(msgs_lookup("wdhBKG"));
878           help_endHelp();
879           break;
880         case wimp_MINTERNAL:
881           m=intMsgs_receive(e);
882           switch (e->data.msg.data.words[0])
883           {
884             case glass_REDRAW:
885               if (m->rdr.t==w->t || m->rdr.t==0)
886               {
887                 wimpt_noerr(wimp_get_wind_state(w->h,&s));
888                 r.w=w->h;
889                 r.box.x0=s.o.x;
890                 r.box.x1=r.box.x0+s.o.box.x1-s.o.box.x0;
891                 r.box.y1=s.o.y;
892                 r.box.y0=r.box.y1+s.o.box.y0-s.o.box.y1;
893                 wimpt_noerr(wimp_force_redraw(&r));
894               }
895               break;
896             case glass_RENAME:
897               if (m->rn.w==w && w==window_selectionOwner())
898                 window__updateInfoName(w->id);
899               break;
900             case glass_SPRITECHANGE:
901               if (m->sc.t==w->t)
902               {
903                 wimpt_noerr(wimp_get_caret_pos(&c));
904                 if (wnd=window__recreate(w),!wnd)
905                   return;
906                 if (c.w==w->h)
907                   c.w=wnd;
908               #ifndef glass_DEMO
909                 win_register_event_handler(wnd,
910                         w->testMode ? window__testEvents : window__events,w);
911               #else
912                 win_register_event_handler(wnd,window__events,w);
913               #endif
914                 wimpt_noerr(wimp_get_wind_state(w->h,&s));
915                 wimpt_noerr(wimp_delete_wind(w->h));
916                 win_register_event_handler(w->h,0,0);
917                 win_activedec();
918                 w->h=wnd;
919                 s.o.w=w->h;
920                 wimpt_noerr(wimp_open_wind(&s.o));
921                 if (c.w==wnd)
922                   wimp_set_caret_pos(&c);
923               }
924               break;
925           }
926           break;
927       }
928       break;
929   }
930 }