Some compiler warnings removed.
[cake.git] / workbench / tools / commodities / Opaque.c
blob9a3a44620e8bc2dad4f83cccf79b2335e0f99abc
1 /*
2 Copyright © 1995-2006, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #include <aros/symbolsets.h>
7 #include <workbench/startup.h>
8 #include <intuition/intuition.h>
9 #include <intuition/intuitionbase.h>
10 #include <graphics/gfx.h>
11 #include <graphics/gfxbase.h>
12 #include <libraries/commodities.h>
13 #include <libraries/locale.h>
14 #include <proto/exec.h>
15 #include <proto/dos.h>
16 #include <proto/intuition.h>
17 #include <proto/layers.h>
18 #include <proto/commodities.h>
19 #include <proto/locale.h>
20 #include <proto/alib.h>
21 #include <proto/iffparse.h>
22 #include <proto/icon.h>
23 #include <prefs/prefhdr.h>
24 #include <prefs/icontrol.h>
26 #define DEBUG 0
27 #include <aros/debug.h>
29 #include <stdio.h>
30 #include <stdlib.h>
32 #define CATCOMP_ARRAY
33 #include "strings.h"
35 #define CATALOG_NAME "System/Tools/Commodities.catalog"
36 #define CATALOG_VERSION 2
39 #define ACCELERATOR_THRESH 2
40 #define ACCELERATOR_MULTI 2
42 /************************************************************************************/
44 /* Using ChangeWindowBox has the advantage, that one can specify absolute window
45 coords, instead of relative ones as in case of MoveWindow. OTOH it has the
46 disadvantage that it also generates IDCMP_NEWSIZE IntuiMessages. */
48 #define USE_CHANGEWINDOWBOX 0
50 #define CALL_WINDOWFUNCS_IN_INPUTHANDLER 0
52 /************************************************************************************/
54 UBYTE version[] = "$VER: Opaque 0.5 (15.04.2006)";
56 #define ARG_TEMPLATE "CX_PRIORITY=PRI/N/K"
58 #define ARG_PRI 0
59 #define NUM_ARGS 1
61 #define ACTIONTYPE_DRAGGING 1
62 #define ACTIONTYPE_RESIZING 2
64 #define SYSGADTYPE(gad) ((gad)->GadgetType & GTYP_SYSTYPEMASK)
67 static struct NewBroker nb =
69 NB_VERSION,
70 NULL,
71 NULL,
72 NULL,
73 NBU_NOTIFY | NBU_UNIQUE,
75 -120,
76 NULL,
80 static struct Catalog *catalog;
81 static struct MsgPort *cxport;
82 static struct Window *actionwin;
83 static struct Task *maintask;
85 static struct RDArgs *myargs;
86 static CxObj *cxbroker, *cxcust;
87 static ULONG cxmask, actionmask, icontrolmask;
88 static WORD winoffx, winoffy, winwidth, winheight;
89 #if !USE_CHANGEWINDOWBOX
90 static WORD actionstart_winx, actionstart_winy;
91 #endif
92 static struct Rectangle mousebounds;
93 static LONG gadgetLeft, gadgetTop;
94 static LONG gadgetWidth, gadgetHeight;
95 static BYTE actionsig, icontrolsig;
96 static UBYTE actiontype;
97 static BOOL quitme, disabled;
98 static BOOL offScreenLayersFlag;
99 static struct NotifyRequest *IControlChangeNR;
101 static IPTR args[NUM_ARGS];
102 static char s[256];
104 static void HandleAction(void);
105 static void HandleIControl(void);
107 /**********************************************************************************************/
109 #define ARRAY_TO_LONG(x) ( ((x)[0] << 24UL) + ((x)[1] << 16UL) + ((x)[2] << 8UL) + ((x)[3]) )
110 #define ARRAY_TO_WORD(x) ( ((x)[0] << 8UL) + ((x)[1]) )
112 #define CONFIGNAME_ENV "ENV:Sys/icontrol.prefs"
114 struct FileIControlPrefs
116 UBYTE ic_Reserved0[4];
117 UBYTE ic_Reserved1[4];
118 UBYTE ic_Reserved2[4];
119 UBYTE ic_Reserved3[4];
120 UBYTE ic_TimeOut[2];
121 UBYTE ic_MetaDrag[2];
122 UBYTE ic_Flags[4];
123 UBYTE ic_WBtoFront;
124 UBYTE ic_FrontToBack;
125 UBYTE ic_ReqTrue;
126 UBYTE ic_ReqFalse;
128 /************************************************************************************/
130 static CONST_STRPTR _(ULONG id)
132 if (LocaleBase != NULL && catalog != NULL)
134 return GetCatalogStr(catalog, id, CatCompArray[id].cca_Str);
136 else
138 return CatCompArray[id].cca_Str;
142 /************************************************************************************/
144 static BOOL Locale_Initialize(VOID)
146 if (LocaleBase != NULL)
148 catalog = OpenCatalog
150 NULL, CATALOG_NAME, OC_Version, CATALOG_VERSION, TAG_DONE
153 else
155 catalog = NULL;
158 return TRUE;
161 /************************************************************************************/
163 static VOID Locale_Deinitialize(VOID)
165 if(LocaleBase != NULL && catalog != NULL) CloseCatalog(catalog);
168 /************************************************************************************/
170 static void showSimpleMessage(CONST_STRPTR msgString)
172 struct EasyStruct easyStruct;
174 easyStruct.es_StructSize = sizeof(easyStruct);
175 easyStruct.es_Flags = 0;
176 easyStruct.es_Title = _(MSG_OPAQUE_CXNAME);
177 easyStruct.es_TextFormat = msgString;
178 easyStruct.es_GadgetFormat = _(MSG_OK);
180 if (IntuitionBase != NULL && !Cli() )
182 EasyRequestArgs(NULL, &easyStruct, NULL, NULL);
184 else
186 PutStr(msgString);
190 /************************************************************************************/
192 #define MINWINDOWWIDTH (5)
193 #define MINWINDOWHEIGHT (5)
195 #define mouseLeft mousebounds.MinX
196 #define mouseTop mousebounds.MinY
197 #define mouseRight mousebounds.MaxX
198 #define mouseBottom mousebounds.MaxY
200 void SetMouseBounds(struct Window *win)
202 WORD minheight, minwidth, maxheight, maxwidth;
204 if (win) {
205 if (actiontype == ACTIONTYPE_DRAGGING) {
206 if (offScreenLayersFlag) {
207 mouseLeft = 0; /* as left as you want */
208 mouseTop = winoffy; /* keep the titlebar visible */
209 mouseRight = win->WScreen->Width; /* as far right as you want */
210 mouseBottom = win->WScreen->Height - (gadgetHeight - (winoffy + 1));
212 else { /* bounds such that the window never goes offscreen */
213 mouseLeft = winoffx;
214 mouseTop = winoffy;
215 mouseRight = (win->WScreen->Width - winwidth) + winoffx;
216 mouseBottom = (win->WScreen->Height - winheight) + winoffy;
219 else { /* actiontype == ACTIONTYPE_RESIZING) */
220 /* force legal min/max values */
221 minwidth = win->MinWidth;
222 maxwidth = win->MaxWidth;
223 minheight = win->MinHeight;
224 maxheight = win->MaxHeight;
226 if (maxwidth <= 0) maxwidth = win->WScreen->Width;
227 if (maxheight <= 0) maxheight = win->WScreen->Height;
229 if ((minwidth < MINWINDOWWIDTH) || (minheight < MINWINDOWHEIGHT) || /* if any dimention too small, or */
230 (minwidth > maxwidth) || (minheight > maxheight) || /* either min/max value pairs are inverted, or */
231 (minwidth > win->Width) || (minheight > win->Height) || /* the window is already smaller than minwidth/height, or */
232 (maxwidth < win->Width) || (maxheight < win->Height)) { /* the window is already bigger than maxwidth/height */
233 minwidth = MINWINDOWWIDTH; /* then put sane values in */
234 minheight = MINWINDOWHEIGHT;
235 maxwidth = win->WScreen->Width;
236 maxheight = win->WScreen->Height;
239 /* set new mouse bounds */
240 mouseLeft = win->LeftEdge + minwidth - (win->Width - winoffx);
241 mouseTop = win->TopEdge + minheight - (win->Height - winoffy);
242 mouseRight = (win->LeftEdge + maxwidth) - (win->Width - winoffx);
243 mouseBottom = (win->TopEdge + maxheight) - (win->Height - winoffy);
244 if ((win->WScreen->Width - (win->Width - winoffx)) < mouseRight)
245 mouseRight = (win->WScreen->Width - (win->Width - winoffx));
246 if ((win->WScreen->Height - (win->Height - winoffy)) < mouseBottom)
247 mouseBottom = (win->WScreen->Height - (win->Height - winoffy));
252 /************************************************************************************/
254 BOOL GetOFFSCREENLAYERSPref()
256 static struct FileIControlPrefs loadprefs;
257 struct IFFHandle *iff;
258 BOOL retval = TRUE;
260 if ((iff = AllocIFF()))
262 if ((iff->iff_Stream = (IPTR)Open(CONFIGNAME_ENV, MODE_OLDFILE)))
264 InitIFFasDOS(iff);
266 if (!OpenIFF(iff, IFFF_READ))
268 if (!StopChunk(iff, ID_PREF, ID_ICTL))
270 if (!ParseIFF(iff, IFFPARSE_SCAN))
272 struct ContextNode *cn;
274 cn = CurrentChunk(iff);
276 if (cn->cn_Size == sizeof(loadprefs))
278 if (ReadChunkBytes(iff, &loadprefs, sizeof(loadprefs)) == sizeof(loadprefs))
280 if ( ! (ARRAY_TO_LONG(loadprefs.ic_Flags) & ICF_OFFSCREENLAYERS) ) retval = FALSE;
284 } /* if (!ParseIFF(iff, IFFPARSE_SCAN)) */
286 } /* if (!StopChunk(iff, ID_PREF, ID_INPT)) */
288 CloseIFF(iff);
290 } /* if (!OpenIFF(iff, IFFF_READ)) */
292 Close((BPTR)iff->iff_Stream);
294 } /* if ((iff->iff_Stream = (IPTR)Open(CONFIGNAME_ENV, MODE_OLDFILE))) */
296 FreeIFF(iff);
298 } /* if ((iff = AllocIFF())) */
300 return retval;
303 /************************************************************************************/
305 static void Cleanup(CONST_STRPTR msg)
307 struct Message *cxmsg;
309 if (msg)
311 showSimpleMessage(msg);
314 if(CxBase)
316 if (cxbroker) DeleteCxObjAll(cxbroker);
317 if (cxport)
319 while((cxmsg = GetMsg(cxport)))
321 ReplyMsg(cxmsg);
324 DeleteMsgPort(cxport);
328 if (myargs) FreeArgs(myargs);
330 if (actionsig) FreeSignal(actionsig);
331 if (icontrolsig) FreeSignal(icontrolsig);
333 if (IControlChangeNR != NULL) {
334 EndNotify(IControlChangeNR);
335 FreeMem(IControlChangeNR, sizeof(struct NotifyRequest));
338 exit(0);
341 /************************************************************************************/
343 static void DosError(void)
345 Fault(IoErr(),0,s,255);
346 Cleanup(s);
349 /************************************************************************************/
351 static void Init(void)
354 /* create "action" signal, to handle window dragging and resize events */
355 maintask = FindTask(0);
356 if((actionsig = AllocSignal(-1L)) != -1)
358 actionmask = 1L << actionsig;
360 /* create "IControl pref changes" signal */
361 if((icontrolsig = AllocSignal(-1L)) != -1)
363 icontrolmask = 1L << icontrolsig;
364 if ((IControlChangeNR = AllocMem(sizeof(struct NotifyRequest), MEMF_CLEAR)))
366 IControlChangeNR->nr_Name = CONFIGNAME_ENV;
367 IControlChangeNR->nr_Flags = NRF_SEND_SIGNAL;
368 IControlChangeNR->nr_stuff.nr_Signal.nr_Task = maintask;
369 IControlChangeNR->nr_stuff.nr_Signal.nr_SignalNum = icontrolsig;
371 StartNotify(IControlChangeNR);
373 /* set inital value for offscreenlayers */
374 offScreenLayersFlag = GetOFFSCREENLAYERSPref();
375 } else {
376 showSimpleMessage(_(MSG_CANT_ALLOCATE_MEM));
383 #define ABS(x) (((x)<0)?(-(x)):(x))
384 inline WORD WITHACCEL(WORD raw) { if (ABS(raw) > ACCELERATOR_THRESH) return(raw << 2); else return(raw << 1);}
385 inline WORD WITHOUTACCEL(WORD raw) { if (ABS(raw) > ACCELERATOR_THRESH) return(raw >> 2); else return(raw >> 1);}
387 /************************************************************************************/
389 static void GetArguments(int argc, char **argv)
391 if (argc == 0)
393 UBYTE **array = ArgArrayInit(argc, (UBYTE**)argv);
394 nb.nb_Pri = ArgInt(array, "CX_PRIORITY", 0);
395 ArgArrayDone();
397 else
399 if (!(myargs = ReadArgs(ARG_TEMPLATE, args, 0)))
401 DosError();
404 if (args[ARG_PRI]) nb.nb_Pri = *(LONG *)args[ARG_PRI];
408 /************************************************************************************/
410 static void OpaqueAction(CxMsg *msg,CxObj *obj)
412 static BOOL opaque_active = FALSE;
414 struct InputEvent *ie = (struct InputEvent *)CxMsgData(msg);
415 struct Screen *scr;
417 if (ie->ie_Class == IECLASS_RAWMOUSE)
419 switch(ie->ie_Code)
421 case SELECTDOWN:
422 if (IntuitionBase->ActiveWindow)
424 scr = IntuitionBase->ActiveWindow->WScreen;
425 } else {
426 scr = IntuitionBase->ActiveScreen;
429 if (!opaque_active && scr)
431 struct Layer *lay = WhichLayer(&scr->LayerInfo, scr->MouseX, scr->MouseY);
432 struct Window *win = NULL;
434 if (lay) win = (struct Window *)lay->Window;
436 if (win && !(ie->ie_Qualifier & (IEQUALIFIER_LCOMMAND | IEQUALIFIER_RCOMMAND)))
438 struct Gadget *gad;
439 struct Window *newwin = NULL;
441 for(gad = win->FirstGadget; gad; gad = gad->NextGadget)
443 /* FIXME: does not handle app made dragging/resize gadgets in
444 GZZ innerlayer or boopsi gadgets with special GM_HITTEST
445 method correctly! */
447 if (!(gad->Flags & GFLG_DISABLED))
449 WORD x = gad->LeftEdge;
450 WORD y = gad->TopEdge;
451 WORD w = gad->Width;
452 WORD h = gad->Height;
453 gadgetLeft = gad->LeftEdge;
454 gadgetTop = gad->TopEdge;
455 gadgetWidth = gad->Width;
456 gadgetHeight = gad->Height;
458 if (gad->Flags & GFLG_RELRIGHT) x += win->Width - 1;
459 if (gad->Flags & GFLG_RELBOTTOM) y += win->Height - 1;
460 if (gad->Flags & GFLG_RELWIDTH) w += win->Width;
461 if (gad->Flags & GFLG_RELHEIGHT) h += win->Height;
463 if ((win->MouseX >= x) &&
464 (win->MouseY >= y) &&
465 (win->MouseX < x + w) &&
466 (win->MouseY < y + h))
468 if ((SYSGADTYPE(gad) == GTYP_WDRAGGING) || (SYSGADTYPE(gad) == GTYP_SIZING))
470 /* found dragging or resize gadget */
471 newwin = win;
472 actiontype = (SYSGADTYPE(gad) == GTYP_WDRAGGING) ? ACTIONTYPE_DRAGGING :
473 ACTIONTYPE_RESIZING;
475 break;
479 } /* for(gad = win->FirstGadget; gad; gad = gad->NextGadget) */
481 win = newwin;
483 } /* if (win && !(ie->ie_Qualifier & (IEQUALIFIER_LCOMMAND | IEQUALIFIER_RCOMMAND))) */
485 if (win)
487 opaque_active = TRUE;
488 if (IntuitionBase->ActiveWindow != win) ActivateWindow(win);
489 actionwin = win;
490 winoffx = win->WScreen->MouseX - win->LeftEdge;
491 winoffy = win->WScreen->MouseY - win->TopEdge;
492 winwidth = win->Width;
493 winheight = win->Height;
494 #if !USE_CHANGEWINDOWBOX
495 actionstart_winx = win->LeftEdge;
496 actionstart_winy = win->TopEdge;
497 #endif
498 DisposeCxMsg(msg);
499 /* reset mouse bounds */
500 SetMouseBounds(actionwin);
501 if (!offScreenLayersFlag) SetPointerBounds(actionwin->WScreen, &mousebounds, 0, NULL);
503 //Signal(maintask, icontrolmask);
506 } /* if (!opaque_active && scr) */
507 break;
509 case SELECTUP:
510 if (opaque_active)
512 opaque_active = FALSE;
513 if (!offScreenLayersFlag) SetPointerBounds(actionwin->WScreen, NULL, 0, NULL);
514 DisposeCxMsg(msg);
516 break;
518 case IECODE_NOBUTTON:
519 if (opaque_active)
521 if (!offScreenLayersFlag) SetPointerBounds(actionwin->WScreen, &mousebounds, 0, NULL);
523 #if CALL_WINDOWFUNCS_IN_INPUTHANDLER
524 HandleAction();
525 #else
526 Signal(maintask, actionmask);
527 #endif
529 break;
531 } /* switch(ie->ie_Code) */
533 } /* if (ie->ie_Class == IECLASS_RAWMOUSE) */
534 else if (ie->ie_Class == IECLASS_TIMER)
536 if (opaque_active && !offScreenLayersFlag)
538 SetPointerBounds(actionwin->WScreen, &mousebounds, 0, NULL);
543 /************************************************************************************/
545 static void InitCX(void)
547 if (!(cxport = CreateMsgPort()))
549 Cleanup(_(MSG_CANT_CREATE_MSGPORT));
552 nb.nb_Port = cxport;
554 cxmask = 1L << cxport->mp_SigBit;
556 if (!(cxbroker = CxBroker(&nb, 0)))
558 Cleanup(_(MSG_CANT_CREATE_BROKER));
561 if (!(cxcust = CxCustom(OpaqueAction, 0)))
563 Cleanup(_(MSG_CANT_CREATE_CUSTOM));
566 AttachCxObj(cxbroker, cxcust);
567 ActivateCxObj(cxbroker, 1);
571 /************************************************************************************/
573 /* Handle the case where the IControl Prefs have changed */
574 static void HandleIControl(void)
576 D(bug("[Opaque] notified of icontrol.prefs change\n"));
577 offScreenLayersFlag = GetOFFSCREENLAYERSPref();
578 //SetMouseBounds();
581 /************************************************************************************/
583 /* Move window to absolute position newWindowX, newWindowY */
584 static void HandleAction(void)
586 if (actiontype == ACTIONTYPE_DRAGGING)
588 WORD newx = actionwin->WScreen->MouseX - winoffx;
589 WORD newy = actionwin->WScreen->MouseY - winoffy;
591 /* MoveWindow(actionwin, newx - actionwin->LeftEdge, newy - actionwin->TopEdge); */
592 #if USE_CHANGEWINDOWBOX
593 ChangeWindowBox(actionwin, newx, newy, actionwin->Width, actionwin->Height);
594 #else
595 MoveWindow(actionwin, newx - actionstart_winx, newy - actionstart_winy);
596 actionstart_winx = newx;
597 actionstart_winy = newy;
598 #endif
600 else
602 LONG neww = winwidth + actionwin->WScreen->MouseX - actionwin->LeftEdge - winoffx;
603 LONG newh = winheight + actionwin->WScreen->MouseY - actionwin->TopEdge - winoffy;
605 if ((neww != actionwin->Width) || (newh != actionwin->Height))
607 /* SizeWindow(actionwin, neww - actionwin->Width, newh - actionwin->Height); */
608 ChangeWindowBox(actionwin, actionwin->LeftEdge, actionwin->TopEdge, neww, newh);
613 /************************************************************************************/
615 static void HandleCx(void)
617 CxMsg *msg;
618 while((msg = (CxMsg *)GetMsg(cxport)))
620 switch(CxMsgType(msg))
622 case CXM_COMMAND:
623 switch(CxMsgID(msg))
625 case CXCMD_DISABLE:
626 ActivateCxObj(cxbroker,0L);
627 disabled = TRUE;
628 break;
630 case CXCMD_ENABLE:
631 ActivateCxObj(cxbroker,1L);
632 disabled = FALSE;
633 break;
635 case CXCMD_UNIQUE:
636 case CXCMD_KILL:
637 quitme = TRUE;
638 break;
640 } /* switch(CxMsgID(msg)) */
641 break;
643 } /* switch (CxMsgType(msg))*/
645 ReplyMsg((struct Message *)msg);
647 } /* while((msg = (CxMsg *)GetMsg(cxport))) */
650 /************************************************************************************/
652 static void HandleAll(void)
654 ULONG sigs;
656 while(!quitme)
658 sigs = Wait(cxmask | actionmask | icontrolmask | SIGBREAKF_CTRL_C);
660 if (sigs & cxmask) HandleCx();
661 if (sigs & actionmask) HandleAction(); /* "Action" == window moving or resizing */
662 if (sigs & icontrolmask) HandleIControl();
663 if (sigs & SIGBREAKF_CTRL_C) quitme = TRUE;
664 } /* while(!quitme) */
667 /************************************************************************************/
669 int main(int argc, char **argv)
671 Init();
673 nb.nb_Name = _(MSG_OPAQUE_CXNAME);
674 nb.nb_Title = _(MSG_OPAQUE_CXTITLE);
675 nb.nb_Descr = _(MSG_OPAQUE_CXDESCR);
677 GetArguments(argc, argv);
678 InitCX();
679 HandleAll();
680 Cleanup(0);
681 return 0;
684 /************************************************************************************/
686 ADD2INIT(Locale_Initialize, 90);
687 ADD2EXIT(Locale_Deinitialize, 90);