4 * Handling events for template windows
6 * © 1994-1998 Straylight
9 /*----- Licensing note ----------------------------------------------------*
11 * This file is part of Straylight's Glass.
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)
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.
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.
28 /*----- Header files ------------------------------------------------------*/
31 * ANSI standard headers
44 #include "steel/Steel.h"
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"
71 /*----- Main code ---------------------------------------------------------*/
74 * void window__winIdles(void *handle)
77 * Changes the pointer shape to something appropriate for what its over.
80 * void *handle == pointer to window containing pointer
83 void window__winIdles(void *handle)
85 glass_windPointer *w=handle;
86 int i=window__pointerInfo(w,-1,TRUE);
91 window__setPtrShape(i);
92 window__updateInfoBar(FALSE);
96 * int window__keyAhead(int k,int *nk)
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).
103 * int k == the key to check for
104 * int *nk == where to store next key value
107 * Number of times key was buffered.
110 static int window__keyAhead(int k,int *nk)
117 if (!akbd_pollkey(nk))
120 *nk=akbd_translate(*nk);
126 * void window__testEvents(wimp_eventstr *e,void *handle)
129 * Handles all events for windows running in Test mode. Events handled
132 * Redraw Redraws the window using Interface/hatch pattern as requested.
133 * Open Moves the window around.
134 * Close Closes the window(!)
136 * Enter Turn off STEEL pointer changing
137 * Click Handled by WIMP or Interface, except for menu, which opens
139 * Key Handled by WIMP, WimpExtension, or ignored
142 * wimp_eventstr *e == the event
143 * void *handle == pointer to window info
148 void window__testEvents(wimp_eventstr *e,void *handle)
150 glass_windPointer *w=handle; /* Extract my data from the handle */
153 wimp_redrawstr r; /* For the redraw event */
154 BOOL more; /* To tell me when I've finished */
158 sculptrix_slabDescriptor d;
164 wimpt_noerr(wimp_redraw_wind(&r,&more)); /* Start the redraw */
165 window__redraw(w,&r,&more);
168 if (e->data.o.x<=w->def->desc.w.scx &&
169 e->data.o.y>=w->def->desc.w.scy)
173 if (tst(w->def->desc.w.flags,14))
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-
179 if (tst(w->def->desc.w.flags,15))
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+
185 if (memcmp(&r.box,&w->tex,sizeof(wimp_box)))
187 wimpt_noerr(wimp_set_extent(&r));
192 if (window_selectionOwner()==w)
193 window__setToolBarPositions(&e->data.o);
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)
204 if (wnd=window__recreate(w),!wnd)
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);
213 wimpt_noerr(wimp_open_wind(&s.o));
220 e=wimpt_last_event(); /* Get the real event */
221 switch (e->data.but.m.bbits)
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)
228 wimpt_noerr(wimp_get_icon_info(w->h,e->data.but.m.i,&icon));
229 interface_slabButton(&e->data.but.m);
231 wimpt_noerr(wimp_get_wind_state(w->h,&s));
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)
238 interface_slabButton(&e->data.but.m);
239 if (icon.flags & wimp_IFONT)
241 wimpt_noerr(wimp_set_icon_state(w->h,
243 icon.flags & 0xff000000,
247 if (gPrefs_current()->sSlabMenu && e->data.but.m.i!=-1)
248 sculptrix_unslabIcon(&d);
251 case wimp_BDRAGRIGHT:
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);
257 if (gPrefs_current()->iSlabIcons && e->data.but.m.i!=-1)
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)
265 wimpt_noerr(wimp_set_icon_state(w->h,
267 icon.flags & 0xff000000,
272 if (gPrefs_current()->sSlabIcons && e->data.but.m.i!=-1)
273 sculptrix_unslabIcon(&d);
279 win_removeIdleClaimer(window__winIdles,w);
280 window__updateInfoBar(FALSE);
281 window__setPtrShape(window__SELECT);
282 interface_spritearea((sprite_area *)1);
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);
291 if (gPrefs_current()->wKeyPress)
293 reg.r[0]=e->data.key.chcode;
295 reg.r[3]=e->data.key.c.i;
296 os_swix(XWimpExt_MoveCaret,®);
298 wimpt_noerr(wimp_processkey(e->data.key.chcode));
303 os_swix(XWimpExt_ViewIcon,®);
305 /* --- That may have moved the window, so... --- */
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)
310 w->def->desc.w.scx=s.o.x;
311 w->def->desc.w.scy=s.o.y;
313 tfile_markAsAltered(w->t);
318 wimpt_noerr(wimp_processkey(e->data.key.chcode));
321 case wimp_ESENDWANTACK:
330 * void window__events(wimp_eventstr *e,void *handle)
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!)
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
341 void window__events(wimp_eventstr *e,void *handle)
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 */
356 static BOOL dontDrag; /* Disable/ignore next drag event */
357 glass_iconDescription icd;
366 wimpt_noerr(wimp_redraw_wind(&r,&more)); /* Start the redraw */
367 window__redraw(w,&r,&more);
371 /* --- Handle rubbery extents --- *
373 * We've got to make sure the window's not scrolling here, otherwise
374 * very strange things start happening.
377 if (e->data.o.x<=w->def->desc.w.scx &&
378 e->data.o.y>=w->def->desc.w.scy)
382 if (tst(w->def->desc.w.flags,14))
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-
388 if (tst(w->def->desc.w.flags,15))
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+
394 if (memcmp(&r.box,&w->tex,sizeof(wimp_box)))
396 wimpt_noerr(wimp_set_extent(&r));
401 if (window_selectionOwner()==w)
402 window__setToolBarPositions(&e->data.o);
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)
414 if (wnd=window__recreate(w),!wnd)
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);
423 wimpt_noerr(wimp_open_wind(&s.o));
430 if (window__qDragType()!=-1)
432 switch (e->data.but.m.bbits)
435 wimpt_noerr(wimp_get_wind_state(w->h,&s));
438 window__showMenu(e->data.but.m.x-ox,e->data.but.m.y-oy,w);
441 if (!(akbd_pollsh() && (w->lastClicked!=-1)) &&
443 (!gPrefs_current()->mCtrlEdit || akbd_pollctl()))
445 i=window__pointerInfo(w,-1,TRUE);
446 if ((i & window__ZONEMASK)==window__HORGUIDE ||
447 (i & window__ZONEMASK)==window__VERGUIDE)
450 editIcon(w,i&window__ICONMASK);
453 i=window__pointerInfo(w,-1,FALSE);
461 /* Otherwise drop through to select... */
463 /* Treat this as a normal click - drop to select */
464 case wimp_BCLICKLEFT:
465 case wimp_BCLICKRIGHT:
467 /* --- if we're in the toolbox, or grab mode, ignore click --- */
469 if (toolbox_toolSelected() || window_grabbing())
471 dontDrag=TRUE; /* The WIMP gives a drag on grab sprites! */
475 /* --- give this window the selection, tool bars, and caret --- */
477 window__gainSelection(w);
479 /* --- special case for renumbering --- */
483 i=window__pointerInfo(w,-1,FALSE);
484 if (!(i & window__ZONEMASK) && w->def->i[i].selected)
486 set=window__lowestSelected(w);
487 window__select(w,i,FALSE);
489 w->def->i[i]=w->def->i[set];
491 window_redrawIcon(w,i);
492 window_redrawIcon(w,set);
493 tfile_markAsAltered(w->t);
495 window__nextRenumber(w);
497 window__renumber(w,FALSE);
499 window__updateMenu(w); /* May have changed focus */
503 /* --- handle depthwise selection - no problem with guides --- */
504 /* --- because we know the pointer is over an icon --- */
507 w->lastClicked!=-1 &&
508 window__pointerOverIcon(w,w->lastClicked))
511 w->lastClicked=window__pointerInfo(w,w->lastClicked,FALSE);
512 if (i!=w->lastClicked)
514 if (i==window__selectedIcon())
515 window__setSelectedIconDeselecting(w->lastClicked);
518 window__select(w,i,FALSE);
519 window__select(w,w->lastClicked,TRUE);
523 window__updateMenu(w);
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 --- */
531 if (e->data.but.m.bbits==wimp_BCLICKRIGHT ||
532 e->data.but.m.bbits==wimp_BRIGHT)
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);
543 window__select(w,i,!w->def->i[i].selected);
550 window__updateMenu(w);
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.) --- */
558 i=window__pointerInfo(w,-1,TRUE);
561 i=window__pointerInfo(w,-1,FALSE);
566 zone=i & window__ZONEMASK;
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++)
578 if (i!=w->lastClicked)
579 window__select(w,i,FALSE);
583 case window__HORGUIDE:
584 case window__VERGUIDE:
585 if (!w->guide[i].selected)
587 for (i=0;i<glass_GUIDELIMIT;i++)
589 if (w->guide[i].selected)
591 w->guide[i].selected=FALSE;
592 window__redrawGuide(w,i);
595 w->guide[w->lastClicked].selected=TRUE;
596 window__redrawGuide(w,w->lastClicked);
601 /* --- Any other zones we ignore - these are for drag --- */
602 /* --- operations --- */
603 window__setSelectedIcon(w->lastClicked);
607 window__updateMenu(w);
610 case wimp_BDRAGRIGHT:
612 toolbox_toolSelected() ||
617 /* --- YARB -- Yet Another RISC OS Bug --- *
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
629 if (e->data.but.m.bbits==wimp_BDRAGLEFT)
631 i=window__pointerInfo(w,-1,TRUE);
633 dragType = window__SELECT;
635 dragType=i & window__ZONEMASK;
638 dragType=window__SELECT;
642 case window__HORGUIDE:
643 case window__VERGUIDE:
646 for (i=0;i<w->def->desc.w.nicons;i++)
648 if (w->def->i[i].selected)
650 window_boundingBox(w,i,&b);
669 bound.x1-=wimpt_dx();
670 bound.y1-=wimpt_dy();
673 wimpt_noerr(wimp_get_wind_state(w->h,&s));
676 window__startDrag(dragType,
686 win_removeIdleClaimer(window__winIdles,w);
687 window__updateInfoBar(FALSE);
688 window__setPtrShape(window__SELECT);
692 win_addIdleClaimer(window__winIdles,win_DONTCARE,w);
693 if (window__qDragType()==window__GRABICON && !window__dragWind())
694 window__setDragWind(w);
697 key=akbd_translate(e->data.key.chcode);
705 /* --- Normal short-cuts, simulate menu entries --- */
708 window__simMenu(w,glass_TWMISC,glass_TWMINFO);
711 window__simMenu(w,glass_TWMISC,glass_TWMEDITWIN);
714 window__simMenu(w,glass_TWMISC,glass_TWMTEST);
717 window__simMenu(w,glass_TWMISC,glass_TWMCLOSE);
720 window__simMenu(w,glass_TWSAVE,0);
723 window__simMenu(w,glass_TWSELECT,glass_TWSALL);
726 window__simMenu(w,glass_TWSELECT,glass_TWSCLR);
729 window__simMenu(w,glass_TWSELECT,glass_TWSCOPY);
732 window__simMenu(w,glass_TWSELECT,glass_TWSDEL);
735 window__simMenu(w,glass_TWSELECT,glass_TWSORDER);
738 window__simMenu(w,glass_TWSELECT,glass_TWSFRONT);
741 window__simMenu(w,glass_TWSELECT,glass_TWSRAISE);
744 window__simMenu(w,glass_TWSELECT,glass_TWSLOWER);
747 window__simMenu(w,glass_TWSELECT,glass_TWSBACK);
750 window__simMenu(w,glass_TWSELECT,glass_TWSPULL);
753 window__simMenu(w,glass_TWSELECT,glass_TWSALIGN);
759 window__simMenu(w,glass_TWSELECT,glass_TWSEDIT);
763 window__simMenu(w,glass_TWSELECT,glass_TWSDATA);
767 window__simMenu(w,glass_TWICON,glass_TWINEW);
770 window__simMenu(w,glass_TWICON,glass_TWIGRAB);
773 /* --- Cursor keys -- move icons around --- */
775 /* No modifiers -- move the whole icon */
778 b.y0=b.y1=window__keyAhead(okey,&key);
780 window__nudgeIcons(w,&b);
783 b.y0=b.y1=-window__keyAhead(okey,&key);
785 window__nudgeIcons(w,&b);
789 b.x0=b.x1=-window__keyAhead(okey,&key);
790 window__nudgeIcons(w,&b);
794 b.x0=b.x1=window__keyAhead(okey,&key);
795 window__nudgeIcons(w,&b);
798 /* Control pressed -- move the most significant edge */
801 b.y1=window__keyAhead(okey,&key);
803 window__nudgeIcons(w,&b);
806 b.y1=-window__keyAhead(okey,&key);
808 window__nudgeIcons(w,&b);
811 b.x1=-window__keyAhead(okey,&key);
813 window__nudgeIcons(w,&b);
816 b.x1=window__keyAhead(okey,&key);
818 window__nudgeIcons(w,&b);
821 /* Shift pressed -- move the least significant edge */
824 b.y0=window__keyAhead(okey,&key);
826 window__nudgeIcons(w,&b);
829 b.y0=-window__keyAhead(okey,&key);
831 window__nudgeIcons(w,&b);
834 b.x0=-window__keyAhead(okey,&key);
836 window__nudgeIcons(w,&b);
839 b.x0=window__keyAhead(okey,&key);
841 window__nudgeIcons(w,&b);
844 /* Shift and control pressed -- scroll the window --- */
847 window__nudgeScroll(w,0,window__keyAhead(okey,&key));
850 window__nudgeScroll(w,0,-window__keyAhead(okey,&key));
853 window__nudgeScroll(w,-window__keyAhead(okey,&key),0);
856 window__nudgeScroll(w,window__keyAhead(okey,&key),0);
859 /* --- No match -- pass on keypress --- */
862 wimp_processkey(e->data.key.chcode);
868 case wimp_ESENDWANTACK:
869 switch (e->data.msg.hdr.action)
871 case wimp_MHELPREQUEST:
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);
877 help_addLine(msgs_lookup("wdhBKG"));
881 m=intMsgs_receive(e);
882 switch (e->data.msg.data.words[0])
885 if (m->rdr.t==w->t || m->rdr.t==0)
887 wimpt_noerr(wimp_get_wind_state(w->h,&s));
890 r.box.x1=r.box.x0+s.o.box.x1-s.o.box.x0;
892 r.box.y0=r.box.y1+s.o.box.y0-s.o.box.y1;
893 wimpt_noerr(wimp_force_redraw(&r));
897 if (m->rn.w==w && w==window_selectionOwner())
898 window__updateInfoName(w->id);
900 case glass_SPRITECHANGE:
903 wimpt_noerr(wimp_get_caret_pos(&c));
904 if (wnd=window__recreate(w),!wnd)
909 win_register_event_handler(wnd,
910 w->testMode ? window__testEvents : window__events,w);
912 win_register_event_handler(wnd,window__events,w);
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);
920 wimpt_noerr(wimp_open_wind(&s.o));
922 wimp_set_caret_pos(&c);