Replaced return IDs by hook functions.
[AROS.git] / workbench / tools / commodities / FKey.c
blob4a0a29d23bc09d60131f06a369ed4d39a5528080
1 /*
2 Copyright © 1995-2016, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 /*********************************************************************************************/
8 #include <intuition/classusr.h>
9 #include <graphics/layers.h>
10 #include <graphics/clip.h>
11 #include <libraries/asl.h>
12 #include <libraries/locale.h>
13 #include <libraries/gadtools.h>
14 #include <libraries/commodities.h>
15 #include <libraries/mui.h>
16 #include <workbench/startup.h>
17 #include <workbench/workbench.h>
18 #include <devices/inputevent.h>
19 #include <aros/asmcall.h>
20 #include <rexx/storage.h>
21 #include <rexx/errors.h>
23 #include <proto/exec.h>
24 #include <proto/dos.h>
25 #include <proto/locale.h>
26 #include <proto/muimaster.h>
27 #include <proto/intuition.h>
28 #include <proto/layers.h>
29 #include <proto/commodities.h>
30 #include <proto/alib.h>
31 #include <proto/icon.h>
32 #include <proto/utility.h>
33 #include <proto/rexxsyslib.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
40 #define CATCOMP_ARRAY
41 #include "strings.h"
43 #define CATALOG_NAME "System/Tools/Commodities.catalog"
44 #define CATALOG_VERSION 3
46 #include <aros/debug.h>
48 /*********************************************************************************************/
50 #define VERSION 1
51 #define REVISION 7
52 #define DATESTR "20.03.2016"
53 #define VERSIONSTR "$VER: FKey 1.7 (" DATESTR ")"
55 /*********************************************************************************************/
57 #define ARG_TEMPLATE "CX_PRIORITY/N/K,CX_POPKEY/K,CX_POPUP/S,PORT/K,QUIET/S"
59 #define ARG_CXPRI 0
60 #define ARG_CXPOPKEY 1
61 #define ARG_CXPOPUP 2
62 #define ARG_CXPORT 3
63 #define ARG_QUIET 4
65 #define NUM_ARGS 5
67 /*********************************************************************************************/
69 #define ACTION_CYCLE_WIN 0
70 #define ACTION_CYCLE_SCR 1
71 #define ACTION_ENLARGE_WIN 2
72 #define ACTION_SHRINK_WIN 3
73 #define ACTION_TOGGLE_WIN 4
74 #define ACTION_RESCUE_WIN 5
75 #define ACTION_INSERT_TEXT 6
76 #define ACTION_RUN_PROG 7
77 #define ACTION_RUN_AREXX 8
79 /*********************************************************************************************/
81 struct KeyInfo
83 struct InputEvent *translist;
84 CxObj *filter, *trans, *custom;
85 WORD action;
86 char descr[80];
87 char param[256];
90 /*********************************************************************************************/
92 struct LocaleBase *LocaleBase;
94 static char *cx_popkey = "ctrl alt f";
95 static LONG cx_pri = 0;
96 static BOOL cx_popup = FALSE;
98 static CxObj *broker, *activated_custom_cobj;
99 static Object *app, *wnd, *cmdcycle, *list, *liststr;
100 static Object *insertstr, *runprogstr, *runarexxstr;
101 static Object *cmdpage;
102 static struct Task *maintask;
103 static struct Hook keylist_construct_hook, keylist_destruct_hook, keylist_disp_hook;
104 static struct Hook broker_hook;
105 static struct Hook show_hook;
106 static struct Hook newkey_hook;
107 static struct Hook delkey_hook;
108 static struct Hook stringack_hook;
109 static struct Hook lvack_hook;
110 static struct Hook cmdack_hook;
111 static struct Hook save_hook;
112 static struct MsgPort *brokermp;
113 static struct Catalog *catalog;
114 static struct RDArgs *myargs;
115 static struct WBStartup *wbstartup;
116 static LONG prog_exitcode;
117 static UBYTE **wbargs;
118 static IPTR args[NUM_ARGS];
119 static UBYTE s[257];
121 /*********************************************************************************************/
123 static void broker_func(struct Hook *hook, Object *obj, CxMsg *msg);
124 static UBYTE *BuildToolType(struct KeyInfo *ki);
125 static UBYTE **BuildToolTypes(UBYTE **src_ttypes);
126 static void Cleanup(CONST_STRPTR msg);
127 static void CleanupLocale(void);
128 static void CmdToKey(void);
129 static void DelKey(void);
130 static struct DiskObject *LoadProgIcon(BPTR *icondir, STRPTR iconname);
131 static void FreeArguments(void);
132 static void FreeToolTypes(UBYTE **ttypes);
133 static void GetArguments(int argc, char **argv);
134 static void HandleAction(void);
135 static void HandleAll(void);
136 static void InitCX(void);
137 static void InitLocale(STRPTR catname, ULONG version);
138 static void InitMenus(void);
139 static APTR keylist_construct_func(struct Hook *hook, APTR pool, struct KeyInfo *ki);
140 static void keylist_destruct_func(struct Hook *hook, APTR pool, struct KeyInfo *ki);
141 static void keylist_disp_func(struct Hook *hook, char **array, struct KeyInfo *ki);
142 static void KillCX(void);
143 static void KillGUI(void);
144 static void ListToString(void);
145 static void LoadSettings(void);
146 static void MakeGUI(void);
147 static CONST_STRPTR MSG(ULONG id);
148 static void NewKey(void);
149 static void RethinkAction(void);
150 static void RethinkKey(struct KeyInfo *ki);
151 static void SaveSettings(void);
152 static WORD ShowMessage(CONST_STRPTR title, CONST_STRPTR text, CONST_STRPTR gadtext);
153 static void StringToKey(void);
154 static struct DiskObject *disko;
155 static void ExecuteArexx(struct KeyInfo *ki);
157 /*********************************************************************************************/
159 static WORD ShowMessage(CONST_STRPTR title, CONST_STRPTR text, CONST_STRPTR gadtext)
161 struct EasyStruct es;
163 es.es_StructSize = sizeof(es);
164 es.es_Flags = 0;
165 es.es_Title = title;
166 es.es_TextFormat = text;
167 es.es_GadgetFormat = gadtext;
169 return EasyRequestArgs(NULL, &es, NULL, NULL);
172 /*********************************************************************************************/
174 static void Cleanup(CONST_STRPTR msg)
176 if (msg)
178 if (IntuitionBase && !((struct Process *)FindTask(NULL))->pr_CLI)
180 ShowMessage("Fkey", msg, MSG(MSG_OK));
182 else
184 printf("FKey: %s\n", msg);
188 KillGUI();
189 FreeDiskObject(disko);
190 FreeArguments();
191 KillCX();
192 CleanupLocale();
194 exit(prog_exitcode);
198 /*********************************************************************************************/
200 static void InitCX(void)
202 maintask = FindTask(NULL);
205 /*********************************************************************************************/
207 static void KillCX(void)
211 /*********************************************************************************************/
213 static void InitLocale(STRPTR catname, ULONG version)
215 LocaleBase = (struct LocaleBase *)OpenLibrary("locale.library", 39);
216 if (LocaleBase)
218 catalog = OpenCatalog(NULL, catname, OC_Version, version,
219 TAG_DONE);
223 /*********************************************************************************************/
225 static void CleanupLocale(void)
227 if (catalog) CloseCatalog(catalog);
228 if (LocaleBase) CloseLibrary((struct Library *)LocaleBase);
231 /*********************************************************************************************/
233 static CONST_STRPTR MSG(ULONG id)
235 if (catalog != NULL)
237 return GetCatalogStr(catalog, id, CatCompArray[id].cca_Str);
239 else
241 return CatCompArray[id].cca_Str;
245 /*********************************************************************************************/
247 static struct NewMenu nm[] =
249 {NM_TITLE, (STRPTR)MSG_MEN_PROJECT },
250 {NM_ITEM, (STRPTR)MSG_FKEY_MEN_PROJECT_SAVE },
251 {NM_ITEM, NM_BARLABEL },
252 {NM_ITEM, (STRPTR)MSG_MEN_PROJECT_HIDE },
253 {NM_ITEM, (STRPTR)MSG_MEN_PROJECT_ICONIFY },
254 {NM_ITEM, NM_BARLABEL },
255 {NM_ITEM, (STRPTR)MSG_MEN_PROJECT_QUIT },
256 {NM_END }
259 /*********************************************************************************************/
261 static void InitMenus(void)
263 struct NewMenu *actnm = nm;
265 for(actnm = nm; actnm->nm_Type != NM_END; actnm++)
267 if (actnm->nm_Label != NM_BARLABEL)
269 ULONG id = (IPTR)actnm->nm_Label;
270 CONST_STRPTR str = MSG(id);
272 if (actnm->nm_Type == NM_TITLE)
274 actnm->nm_Label = str;
275 } else {
276 actnm->nm_Label = str + 2;
277 if (str[0] != ' ') actnm->nm_CommKey = str;
279 actnm->nm_UserData = (APTR)(IPTR)id;
281 } /* if (actnm->nm_Label != NM_BARLABEL) */
283 } /* for(actnm = nm; nm->nm_Type != NM_END; nm++) */
287 /*********************************************************************************************/
289 static void FreeArguments(void)
291 if (myargs) FreeArgs(myargs);
292 ArgArrayDone();
295 /*********************************************************************************************/
297 static void KillGUI(void)
299 DisposeObject(app);
302 /*********************************************************************************************/
304 static void GetArguments(int argc, char **argv)
306 static struct WBArg *wb_arg;
307 static STRPTR cxname;
308 if (argc)
310 if (!(myargs = ReadArgs(ARG_TEMPLATE, args, NULL)))
312 Fault(IoErr(), 0, s, 256);
313 Cleanup(s);
316 if (args[ARG_CXPRI]) cx_pri = (LONG)*(IPTR *)args[ARG_CXPRI];
317 if (args[ARG_CXPOPKEY]) cx_popkey = (STRPTR)args[ARG_CXPOPKEY];
318 if (args[ARG_CXPOPUP]) cx_popup = TRUE;
319 cxname=argv[0];
321 else
323 wbstartup = (struct WBStartup *)argv;
324 wb_arg = wbstartup->sm_ArgList;
325 cxname = wb_arg->wa_Name;
326 wbargs = ArgArrayInit(argc, (UBYTE **)argv);
328 cx_pri = ArgInt(wbargs, "CX_PRIORITY", 0);
329 cx_popkey = ArgString(wbargs, "CX_POPKEY", cx_popkey);
331 if (strnicmp(ArgString(wbargs, "CX_POPUP", "NO"), "Y", 1) == 0)
333 cx_popup = TRUE;
336 disko = GetDiskObject(cxname);
339 /*********************************************************************************************/
341 static APTR keylist_construct_func(struct Hook *hook, APTR pool, struct KeyInfo *ki)
343 struct KeyInfo *new;
345 new = AllocPooled(pool, sizeof(*ki));
346 if (new) *new = *ki;
348 return new;
351 /*********************************************************************************************/
353 static void keylist_destruct_func(struct Hook *hook, APTR pool, struct KeyInfo *ki)
355 if (ki)
357 if (ki->filter) DeleteCxObjAll(ki->filter);
358 if (ki->translist) FreeIEvents(ki->translist);
360 FreePooled(pool, ki, sizeof(*ki));
364 /*********************************************************************************************/
366 static void keylist_disp_func(struct Hook *hook, char **array, struct KeyInfo *ki)
368 *array = ki->descr;
371 /*********************************************************************************************/
373 static void broker_func(struct Hook *hook, Object *obj, CxMsg *msg)
375 D(bug("FKey: broker_func called\n"));
376 if (CxMsgType(msg) == CXM_COMMAND)
378 if (CxMsgID(msg) == CXCMD_APPEAR)
380 CallHookPkt(&show_hook, NULL, NULL);
382 else if (CxMsgID(msg) == CXCMD_DISAPPEAR)
384 set(wnd, MUIA_Window_Open, FALSE);
389 /*** show_func ************************************************************/
390 AROS_UFH3(
391 void, show_func,
392 AROS_UFHA(struct Hook *, hook, A0),
393 AROS_UFHA(APTR *, obj, A2),
394 AROS_UFHA(APTR, param, A1)
397 AROS_USERFUNC_INIT
399 if (XGET(app, MUIA_Application_Iconified) == TRUE)
400 set(app, MUIA_Application_Iconified, FALSE);
401 else
402 set(wnd, MUIA_Window_Open, TRUE);
404 AROS_USERFUNC_EXIT
407 /*********************************************************************************************/
409 AROS_UFH2S(void, custom_func,
410 AROS_UFHA(CxMsg *, msg, A0),
411 AROS_UFHA(CxObj *, co, A1))
413 AROS_USERFUNC_INIT
415 activated_custom_cobj = co;
416 Signal(maintask, SIGBREAKF_CTRL_E);
418 AROS_USERFUNC_EXIT
421 /*********************************************************************************************/
423 AROS_UFH3S(
424 void, newkey_func,
425 AROS_UFHA(struct Hook *, hook, A0),
426 AROS_UFHA(Object *, obj, A2),
427 AROS_UFHA(APTR, param, A1)
430 AROS_USERFUNC_INIT
432 NewKey();
434 AROS_USERFUNC_EXIT
437 /*********************************************************************************************/
439 AROS_UFH3S(
440 void, delkey_func,
441 AROS_UFHA(struct Hook *, hook, A0),
442 AROS_UFHA(Object *, obj, A2),
443 AROS_UFHA(APTR, param, A1)
446 AROS_USERFUNC_INIT
448 DelKey();
450 AROS_USERFUNC_EXIT
453 /*********************************************************************************************/
455 AROS_UFH3S(
456 void, stringack_func,
457 AROS_UFHA(struct Hook *, hook, A0),
458 AROS_UFHA(Object *, obj, A2),
459 AROS_UFHA(APTR, param, A1)
462 AROS_USERFUNC_INIT
464 StringToKey();
466 AROS_USERFUNC_EXIT
469 /*********************************************************************************************/
471 AROS_UFH3S(
472 void, lvack_func,
473 AROS_UFHA(struct Hook *, hook, A0),
474 AROS_UFHA(Object *, obj, A2),
475 AROS_UFHA(APTR, param, A1)
478 AROS_USERFUNC_INIT
480 ListToString();
482 AROS_USERFUNC_EXIT
485 /*********************************************************************************************/
487 AROS_UFH3S(
488 void, cmdack_func,
489 AROS_UFHA(struct Hook *, hook, A0),
490 AROS_UFHA(Object *, obj, A2),
491 AROS_UFHA(APTR, param, A1)
494 AROS_USERFUNC_INIT
496 CmdToKey();
498 AROS_USERFUNC_EXIT
501 /*********************************************************************************************/
503 AROS_UFH3S(
504 void, save_func,
505 AROS_UFHA(struct Hook *, hook, A0),
506 AROS_UFHA(Object *, obj, A2),
507 AROS_UFHA(APTR, param, A1)
510 AROS_USERFUNC_INIT
512 SaveSettings();
514 AROS_USERFUNC_EXIT
517 /*********************************************************************************************/
519 static void MakeGUI(void)
521 static CONST_STRPTR cmdarray[] =
523 (CONST_STRPTR)MSG_FKEY_CMD_CYCLE_WIN,
524 (CONST_STRPTR)MSG_FKEY_CMD_CYCLE_SCR,
525 (CONST_STRPTR)MSG_FKEY_CMD_ENLARGE_WIN,
526 (CONST_STRPTR)MSG_FKEY_CMD_SHRINK_WIN,
527 (CONST_STRPTR)MSG_FKEY_CMD_TOGGLE_WIN_SIZE,
528 (CONST_STRPTR)MSG_FKEY_CMD_RESCUE_WIN,
529 (CONST_STRPTR)MSG_FKEY_CMD_INSERT_TEXT,
530 (CONST_STRPTR)MSG_FKEY_CMD_RUN_PROG,
531 (CONST_STRPTR)MSG_FKEY_CMD_RUN_AREXX,
534 static TEXT wintitle[100];
535 WORD i;
536 Object *menu, *newkey, *delkey, *savekey;
538 for(i = 0; cmdarray[i]; i++)
540 cmdarray[i] = MSG((IPTR) cmdarray[i]);
543 keylist_construct_hook.h_Entry = HookEntry;
544 keylist_construct_hook.h_SubEntry = (HOOKFUNC)keylist_construct_func;
546 keylist_destruct_hook.h_Entry = HookEntry;
547 keylist_destruct_hook.h_SubEntry = (HOOKFUNC)keylist_destruct_func;
549 keylist_disp_hook.h_Entry = HookEntry;
550 keylist_disp_hook.h_SubEntry = (HOOKFUNC)keylist_disp_func;
552 broker_hook.h_Entry = HookEntry;
553 broker_hook.h_SubEntry = (HOOKFUNC)broker_func;
555 show_hook.h_Entry = (HOOKFUNC)show_func;
556 newkey_hook.h_Entry = (HOOKFUNC)newkey_func;
557 delkey_hook.h_Entry = (HOOKFUNC)delkey_func;
558 stringack_hook.h_Entry = (HOOKFUNC)stringack_func;
559 lvack_hook.h_Entry = (HOOKFUNC)lvack_func;
560 cmdack_hook.h_Entry = (HOOKFUNC)cmdack_func;
561 save_hook.h_Entry = (HOOKFUNC)save_func;
563 menu = MUI_MakeObject(MUIO_MenustripNM, &nm, 0);
565 snprintf(wintitle, sizeof(wintitle), MSG(MSG_FKEY_WINTITLE), cx_popkey);
567 app = ApplicationObject,
568 MUIA_Application_Title, (IPTR)MSG(MSG_FKEY_CXNAME),
569 MUIA_Application_Version, (IPTR)VERSIONSTR,
570 MUIA_Application_Copyright, (IPTR)"Copyright © 1995-2012, The AROS Development Team",
571 MUIA_Application_Author, (IPTR)"The AROS Development Team",
572 MUIA_Application_Description, (IPTR)MSG(MSG_FKEY_CXDESCR),
573 MUIA_Application_BrokerPri, cx_pri,
574 MUIA_Application_BrokerHook, (IPTR)&broker_hook,
575 MUIA_Application_Base, (IPTR)"FKey",
576 MUIA_Application_SingleTask, TRUE,
577 menu ? MUIA_Application_Menustrip : TAG_IGNORE, menu,
578 MUIA_Application_DiskObject, (IPTR)disko,
579 SubWindow, wnd = WindowObject,
580 MUIA_Window_Title, (IPTR)wintitle,
581 MUIA_Window_ID, MAKE_ID('F','W','I','N'),
582 WindowContents, HGroup,
583 Child, VGroup,
584 GroupFrameT(MSG(MSG_FKEY_DEFINED_KEYS)),
585 Child, VGroup,
586 GroupSpacing(0),
587 Child, ListviewObject,
588 MUIA_Listview_List, list = ListObject,
589 InputListFrame,
590 MUIA_List_ConstructHook, (IPTR)&keylist_construct_hook,
591 MUIA_List_DestructHook, (IPTR)&keylist_destruct_hook,
592 MUIA_List_DisplayHook, (IPTR)&keylist_disp_hook,
593 End,
594 End,
595 Child, liststr = StringObject,
596 MUIA_Disabled, TRUE,
597 StringFrame,
598 End,
599 End,
600 Child, HGroup,
601 Child, newkey = SimpleButton(MSG(MSG_FKEY_NEW_KEY)),
602 Child, delkey = SimpleButton(MSG(MSG_FKEY_DELETE_KEY)),
603 End,
604 Child, savekey = SimpleButton(MSG(MSG_FKEY_SAVE_KEY)),
605 End,
606 Child, VGroup,
607 GroupFrameT(MSG(MSG_FKEY_COMMAND)),
608 Child, cmdcycle = MUI_MakeObject(MUIO_Cycle, NULL, cmdarray),
609 Child, cmdpage = PageGroup,
610 Child, HVSpace, /* cycle win */
611 Child, HVSpace, /* cycle scr */
612 Child, HVSpace, /* enlarge win */
613 Child, HVSpace, /* shrink win */
614 Child, HVSpace, /* Toggle win */
615 Child, HVSpace, /* rescue win */
616 Child, insertstr = StringObject, StringFrame, End, /* Insert text */
617 Child, PopaslObject, /* Run prog */
618 MUIA_Popstring_String, runprogstr = StringObject, StringFrame, End,
619 MUIA_Popstring_Button, PopButton(MUII_PopFile),
620 ASLFR_RejectIcons, TRUE,
621 End,
622 Child, PopaslObject, /* Run AREXX */
623 MUIA_Popstring_String, runarexxstr = StringObject, StringFrame, End,
624 MUIA_Popstring_Button, PopButton(MUII_PopFile),
625 ASLFR_RejectIcons, TRUE,
626 End,
627 End,
628 Child, HVSpace,
629 End,
630 End,
631 End,
632 End;
634 if (!app)
636 #if 1
637 Cleanup(NULL); /* Make no noise. Is ugly if FKey is double-started. */
638 #else
639 Cleanup(MSG(MSG_CANT_CREATE_GADGET));
640 #endif
643 get(app, MUIA_Application_Broker, &broker);
644 get(app, MUIA_Application_BrokerPort, &brokermp);
646 if (!broker || !brokermp)
647 Cleanup(MSG(MSG_CANT_CREATE_GADGET));
650 CxObj *popfilter = CxFilter(cx_popkey);
652 if (popfilter)
654 CxObj *popsig = CxSignal(maintask, SIGBREAKB_CTRL_F);
656 if (popsig)
658 CxObj *trans;
660 AttachCxObj(popfilter, popsig);
662 trans = CxTranslate(NULL);
663 if (trans) AttachCxObj(popfilter, trans);
666 AttachCxObj(broker, popfilter);
671 set(liststr, MUIA_String_AttachedList, (IPTR)list);
673 DoMethod(app, MUIM_Notify, MUIA_Application_DoubleStart, TRUE, (IPTR) app, 2, MUIM_CallHook, &show_hook);
675 DoMethod(wnd, MUIM_Notify, MUIA_Window_CloseRequest, TRUE, (IPTR) wnd, 3, MUIM_Set, MUIA_Window_Open, FALSE);
677 DoMethod(wnd, MUIM_Notify, MUIA_Window_MenuAction, MSG_MEN_PROJECT_QUIT, (IPTR) app, 2, MUIM_Application_ReturnID, MUIV_Application_ReturnID_Quit);
678 DoMethod(wnd, MUIM_Notify, MUIA_Window_MenuAction, MSG_MEN_PROJECT_HIDE, (IPTR) wnd, 3, MUIM_Set, MUIA_Window_Open, FALSE);
679 DoMethod(wnd, MUIM_Notify, MUIA_Window_MenuAction, MSG_MEN_PROJECT_ICONIFY, (IPTR) app, 3, MUIM_Set, MUIA_Application_Iconified, TRUE);
680 DoMethod(wnd, MUIM_Notify, MUIA_Window_MenuAction, MSG_FKEY_MEN_PROJECT_SAVE, (IPTR) app, 2, MUIM_CallHook, &save_hook);
682 DoMethod(cmdcycle, MUIM_Notify, MUIA_Cycle_Active, MUIV_EveryTime, (IPTR)cmdpage, 3, MUIM_Set, MUIA_Group_ActivePage, MUIV_TriggerValue);
683 DoMethod(cmdcycle, MUIM_Notify, MUIA_Cycle_Active, MUIV_EveryTime, (IPTR)app, 2, MUIM_CallHook, &cmdack_hook);
684 DoMethod(newkey, MUIM_Notify, MUIA_Pressed, FALSE, (IPTR)app, 2, MUIM_CallHook, &newkey_hook);
685 DoMethod(delkey, MUIM_Notify, MUIA_Pressed, FALSE, (IPTR)app, 2, MUIM_CallHook, &delkey_hook);
686 DoMethod(savekey, MUIM_Notify, MUIA_Pressed, FALSE, (IPTR)app, 2, MUIM_CallHook, &save_hook);
687 DoMethod(list, MUIM_Notify, MUIA_List_Active, MUIV_EveryTime, (IPTR)app, 2, MUIM_CallHook, &lvack_hook);
688 DoMethod(liststr, MUIM_Notify, MUIA_String_Acknowledge, MUIV_EveryTime, (IPTR)app, 2, MUIM_CallHook, &stringack_hook);
689 DoMethod(insertstr, MUIM_Notify, MUIA_String_Acknowledge, MUIV_EveryTime, (IPTR)app, 2, MUIM_CallHook, &cmdack_hook);
690 DoMethod(runprogstr, MUIM_Notify, MUIA_String_Acknowledge, MUIV_EveryTime, (IPTR)app, 2, MUIM_CallHook, &cmdack_hook);
691 DoMethod(runarexxstr, MUIM_Notify, MUIA_String_Acknowledge, MUIV_EveryTime, (IPTR)app, 2, MUIM_CallHook, &cmdack_hook);
694 /*********************************************************************************************/
696 static void RethinkKey(struct KeyInfo *ki)
698 if (ki->filter) DeleteCxObjAll(ki->filter);
699 if (ki->translist)
701 FreeIEvents(ki->translist);
702 ki->translist = NULL;
704 ki->custom = ki->trans = ki->filter = NULL;
706 if ((ki->filter = CxFilter(ki->descr)))
708 switch(ki->action)
710 case ACTION_INSERT_TEXT:
711 strrev(ki->param);
712 if ((ki->translist = InvertStringForwd(ki->param, NULL)))
714 if ((ki->trans = CxTranslate(ki->translist)))
716 AttachCxObj(ki->filter, ki->trans);
719 strrev(ki->param);
720 break;
722 default:
723 /* This CxCustom thing is hacky/ugly. A CxSender
724 would be better, but if want to send a pointer
725 with it then this would require some fixes in
726 commodities.library and it's header in case we are
727 running on 64 bit machines :-\ */
729 if ((ki->custom = CxCustom(custom_func, 0)))
731 AttachCxObj(ki->filter, ki->custom);
732 if ((ki->trans = CxTranslate(NULL)))
734 AttachCxObj(ki->filter, ki->trans);
737 break;
741 AttachCxObj(broker, ki->filter);
746 /*********************************************************************************************/
748 static void RethinkAction(void)
750 struct KeyInfo *ki = NULL;
752 DoMethod(list, MUIM_List_GetEntry, MUIV_List_GetEntry_Active, (IPTR)&ki);
754 if (ki)
756 Object *str = NULL;
757 IPTR val = 0;
759 get(cmdcycle, MUIA_Cycle_Active, &val);
760 ki->action = val;
762 switch(ki->action)
764 case ACTION_INSERT_TEXT:
765 str = insertstr;
766 break;
768 case ACTION_RUN_PROG:
769 str = runprogstr;
770 break;
772 case ACTION_RUN_AREXX:
773 str = runarexxstr;
774 break;
778 if (str)
780 STRPTR s = "";
782 get(str, MUIA_String_Contents, &s);
784 strncpy(ki->param, s, sizeof(ki->param));
787 RethinkKey(ki);
791 /*********************************************************************************************/
793 static void NewKey(void)
795 struct KeyInfo ki = {0};
797 StringToKey();
799 DoMethod(list, MUIM_List_InsertSingle, (IPTR)&ki, MUIV_List_Insert_Bottom);
800 nnset(list, MUIA_List_Active, MUIV_List_Active_Bottom);
801 nnset(liststr, MUIA_String_Contents, "");
802 nnset(liststr, MUIA_Disabled, FALSE);
803 set(wnd, MUIA_Window_ActiveObject, (IPTR)liststr);
805 RethinkAction();
808 /*********************************************************************************************/
810 static void DelKey(void)
812 struct KeyInfo *ki = NULL;
814 DoMethod(list, MUIM_List_GetEntry, MUIV_List_GetEntry_Active, (IPTR)&ki);
816 if (ki)
818 DoMethod(list, MUIM_List_Remove, MUIV_List_Remove_Active);
819 DoMethod(list, MUIM_List_GetEntry, MUIV_List_GetEntry_Active, (IPTR)&ki);
820 if (!ki)
822 nnset(liststr, MUIA_String_Contents, (IPTR)"");
823 nnset(liststr, MUIA_Disabled, TRUE);
825 ListToString();
830 /*********************************************************************************************/
832 static void StringToKey(void)
834 struct KeyInfo *ki = NULL;
835 STRPTR text = "";
837 DoMethod(list, MUIM_List_GetEntry, MUIV_List_GetEntry_Active, (IPTR)&ki);
838 if (!ki) return;
840 get(liststr, MUIA_String_Contents, &text);
841 strncpy(ki->descr, text, sizeof(ki->descr));
843 DoMethod(list, MUIM_List_Redraw, MUIV_List_Redraw_Active);
845 RethinkKey(ki);
848 /*********************************************************************************************/
850 static void ListToString(void)
852 struct KeyInfo *ki = NULL;
854 DoMethod(list, MUIM_List_GetEntry, MUIV_List_GetEntry_Active, (IPTR)&ki);
855 if (!ki) return;
857 nnset(liststr, MUIA_Disabled, FALSE);
858 nnset(liststr, MUIA_String_Contents, ki->descr);
860 switch(ki->action)
862 case ACTION_INSERT_TEXT:
863 nnset(insertstr, MUIA_String_Contents, ki->param);
864 break;
866 case ACTION_RUN_PROG:
867 nnset(runprogstr, MUIA_String_Contents, ki->param);
868 break;
870 case ACTION_RUN_AREXX:
871 nnset(runarexxstr, MUIA_String_Contents, ki->param);
872 break;
875 nnset(cmdcycle, MUIA_Cycle_Active, ki->action);
876 nnset(cmdpage, MUIA_Group_ActivePage, ki->action);
879 /*********************************************************************************************/
881 static void CmdToKey(void)
883 RethinkAction();
886 /*********************************************************************************************/
888 static void ExecuteArexx(struct KeyInfo *ki)
890 struct RexxMsg *msg = NULL;
891 struct MsgPort *rexxport = NULL, *replyport = NULL;
892 BPTR out;
893 BOOL closestdout = FALSE;
894 struct RexxMsg *reply;
896 if (ki->param == NULL)
898 return;
901 out = ErrorOutput();
902 if (out == BNULL)
904 out = Output();
907 rexxport = FindPort("REXX");
908 if (rexxport == NULL)
910 if (SystemTags("RexxMast", SYS_Asynch, TRUE,
911 SYS_Input, BNULL, SYS_Output, BNULL,
912 TAG_DONE
913 ) >= 0
916 SystemTags("WaitForPort REXX", TAG_DONE);
919 rexxport = FindPort("REXX");
920 if (rexxport == NULL)
922 FPuts(out, "Could not start RexxMast; no Rexx interpreter seems to be installed\n");
923 goto cleanup;
926 replyport = CreatePort(NULL, 0);
927 if (replyport == NULL)
929 FPuts(out, "Could not create a port\n");
930 goto cleanup;
933 msg = CreateRexxMsg(replyport, NULL, NULL);
934 if (msg == NULL)
936 FPuts(out, "Could not create RexxMsg\n");
937 goto cleanup;
939 msg->rm_Action = RXCOMM | RXFF_RESULT;
940 msg->rm_Stdin = Input();
941 Flush(msg->rm_Stdin); /* Remove command line arguments */
942 msg->rm_Stdout = Output();
944 out = msg->rm_Stdout = Open("CON:////RX Output/CLOSE/WAIT/AUTO", MODE_READWRITE);
945 closestdout = TRUE;
947 msg->rm_Args[0] = (IPTR)CreateArgstring(ki->param, strlen(ki->param));
948 msg->rm_Action |= 1;
950 PutMsg(rexxport, (struct Message *)msg);
951 do {
952 reply = (struct RexxMsg *)WaitPort(replyport);
953 } while (reply != msg);
955 if (msg->rm_Result1 != RC_OK)
957 FPrintf(out, "Error executing script %ld/%ld\n",
958 msg->rm_Result1, msg->rm_Result2
961 ClearRexxMsg(msg, msg->rm_Action & RXARGMASK);
963 cleanup:
964 if (closestdout)
965 Close(msg->rm_Stdout);
966 if (msg)
967 DeleteRexxMsg(msg);
968 if (replyport)
969 DeletePort(replyport);
972 /*********************************************************************************************/
974 static void HandleAction(void)
976 struct KeyInfo *ki;
977 struct Window *win;
978 struct Screen *scr;
979 CxObj *cobj;
980 WORD i;
982 cobj = activated_custom_cobj;
983 activated_custom_cobj = NULL;
985 for(i = 0; ; i++)
987 DoMethod(list, MUIM_List_GetEntry, i, (IPTR)&ki);
988 if (!ki) break;
990 if (ki->custom == cobj) break;
993 if (!ki) return;
995 win = IntuitionBase->ActiveWindow;
996 scr = IntuitionBase->FirstScreen;
998 switch(ki->action)
1000 case ACTION_CYCLE_WIN:
1001 if (win)
1003 struct Layer *lay;
1005 scr = win->WScreen;
1006 win = NULL;
1008 LockLayerInfo(&scr->LayerInfo);
1009 lay = scr->LayerInfo.top_layer;
1010 while(lay)
1012 if (lay->Window &&
1013 (lay != scr->BarLayer) &&
1014 !(lay->Flags & LAYERBACKDROP) &&
1015 !(((struct Window *)lay->Window)->Flags & WFLG_BORDERLESS))
1017 win = (struct Window *)lay->Window;
1020 lay = lay->back;
1022 UnlockLayerInfo(&scr->LayerInfo);
1024 if (win)
1026 WindowToFront(win);
1027 ActivateWindow(win);
1030 break;
1032 case ACTION_CYCLE_SCR:
1033 if (scr) ScreenToBack(scr);
1034 break;
1036 case ACTION_ENLARGE_WIN:
1037 if (win && (win->Flags & WFLG_SIZEGADGET))
1039 WORD neww = win->MaxWidth;
1040 WORD newh = win->MaxHeight;
1042 if (neww > win->WScreen->Width) neww = win->WScreen->Width;
1043 if (newh > win->WScreen->Height) newh = win->WScreen->Height;
1045 ChangeWindowBox(win, win->LeftEdge, win->TopEdge, neww, newh);
1047 break;
1049 case ACTION_SHRINK_WIN:
1050 if (win && (win->Flags & WFLG_SIZEGADGET))
1052 WORD neww = win->MinWidth;
1053 WORD newh = win->MinHeight;
1055 ChangeWindowBox(win, win->LeftEdge, win->TopEdge, neww, newh);
1057 break;
1059 case ACTION_RESCUE_WIN:
1060 if (win)
1062 WORD dx = 0, dy = 0;
1063 if (win->LeftEdge < 0)
1064 dx = -win->LeftEdge;
1065 else if (win->LeftEdge + win->Width > win->WScreen->Width)
1066 dx = win->WScreen->Width - win->Width - win->LeftEdge;
1068 if (win->TopEdge + win->Height > win->WScreen->Height)
1069 dy = win->WScreen->Height - win->Height - win->TopEdge;
1070 else if (win->TopEdge < win->WScreen->BarHeight)
1072 // try to keep the screen title bar visible
1073 if (win->WScreen->BarHeight + win->Height < win->WScreen->Height)
1074 dy = -win->TopEdge + win->WScreen->BarHeight;
1075 else
1076 dy = win->WScreen->Height - win->Height - win->TopEdge;
1078 MoveWindow(win, dx, dy);
1080 break;
1082 case ACTION_TOGGLE_WIN:
1083 if (win) ZipWindow(win);
1084 break;
1086 case ACTION_RUN_PROG:
1087 if (ki->param)
1089 BPTR infh;
1091 infh = Open("CON:20/20/500/300/FKey/CLOSE/AUTO/WAIT", MODE_READWRITE);
1092 if (infh)
1094 struct TagItem systemtags[] =
1096 {SYS_Asynch , TRUE },
1097 {SYS_Input , (IPTR)infh},
1098 {SYS_Output , 0 },
1099 {TAG_DONE }
1102 if (SystemTagList(ki->param, systemtags) == -1)
1104 /* Error */
1105 Close(infh);
1109 break;
1111 case ACTION_RUN_AREXX:
1112 ExecuteArexx(ki);
1113 break;
1115 } /* switch(ki->action) */
1119 /*********************************************************************************************/
1121 #define QUOTE_START 0xAB
1122 #define QUOTE_END 0xBB
1124 /*********************************************************************************************/
1126 static UBYTE *BuildToolType(struct KeyInfo *ki)
1128 static UBYTE ttstring[500];
1129 UBYTE *param1 = "";
1130 UBYTE *param2 = "";
1132 switch(ki->action)
1134 case ACTION_CYCLE_WIN:
1135 param1 = "CYCLE";
1136 break;
1138 case ACTION_CYCLE_SCR:
1139 param1 = "CYCLESCREEN";
1140 break;
1142 case ACTION_ENLARGE_WIN:
1143 param1 = "MAKEBIG";
1144 break;
1146 case ACTION_SHRINK_WIN:
1147 param1 = "MAKESMALL";
1148 break;
1150 case ACTION_TOGGLE_WIN:
1151 param1 = "ZIPWINDOW";
1152 break;
1154 case ACTION_RESCUE_WIN:
1155 param1 = "RESCUEWIN";
1156 break;
1158 case ACTION_INSERT_TEXT:
1159 param1 = "INSERT ";
1160 param2 = ki->param;
1161 break;
1163 case ACTION_RUN_PROG:
1164 param1 = "RUN ";
1165 param2 = ki->param;
1166 break;
1168 case ACTION_RUN_AREXX:
1169 param1 = "AREXX ";
1170 param2 = ki->param;
1171 break;
1175 snprintf(ttstring, sizeof(ttstring), "%c%s%c %s%s",
1176 QUOTE_START,
1177 ki->descr,
1178 QUOTE_END,
1179 param1,
1180 param2);
1182 return ttstring;
1185 /*********************************************************************************************/
1187 static UBYTE **BuildToolTypes(UBYTE **src_ttypes)
1189 APTR pool = CreatePool(MEMF_CLEAR, 200, 200);
1190 Object *listobj = list;
1191 UBYTE *tt;
1192 WORD list_index = 0, num_ttypes = 0, alloc_ttypes = 10;
1194 UBYTE **dst_ttypes;
1196 if (!pool) return NULL;
1198 dst_ttypes = AllocPooled(pool, (alloc_ttypes + 2) * sizeof(UBYTE *));
1199 if (!dst_ttypes)
1201 DeletePool(pool);
1202 return NULL;
1205 /* Put together final tooltypes list based on old tooltypes and
1206 new tooltypes all in one loop */
1208 for(;;)
1210 tt = NULL;
1212 if (listobj)
1214 /* New tooltypes */
1216 struct KeyInfo *ki = NULL;
1218 DoMethod(listobj, MUIM_List_GetEntry, list_index, (IPTR)&ki);
1219 list_index++;
1221 if (ki)
1223 tt = BuildToolType(ki);
1225 else
1227 listobj = NULL;
1231 if (!listobj)
1233 /* Old tooltypes */
1235 if (src_ttypes) tt = *src_ttypes++;
1236 if (!tt) break; /* Done. Skip out of "for(;;)" loop */
1238 if (tt[0] == QUOTE_START) continue; /* skip tooltype containing old settings */
1241 if (!tt) break; /* Paranoia. Should not happen. */
1243 if (num_ttypes >= alloc_ttypes)
1245 UBYTE **new_dst_ttypes = AllocPooled(pool, (alloc_ttypes + 10 + 2) * sizeof(UBYTE *));
1247 if (!new_dst_ttypes)
1249 DeletePool(pool);
1250 return NULL;
1253 CopyMem(dst_ttypes + 1, new_dst_ttypes + 1, alloc_ttypes * sizeof(UBYTE *));
1254 dst_ttypes = new_dst_ttypes;
1255 alloc_ttypes += 10;
1258 dst_ttypes[num_ttypes + 1] = AllocPooled(pool, strlen(tt) + 1);
1259 if (!dst_ttypes[num_ttypes + 1])
1261 DeletePool(pool);
1262 return NULL;
1265 CopyMem(tt, dst_ttypes[num_ttypes + 1], strlen(tt) + 1);
1266 num_ttypes++;
1270 dst_ttypes[0] = (APTR)pool;
1272 return dst_ttypes + 1;
1276 /*********************************************************************************************/
1278 static void FreeToolTypes(UBYTE **ttypes)
1280 if (ttypes)
1282 DeletePool((APTR)ttypes[-1]);
1286 /*********************************************************************************************/
1288 static struct DiskObject *LoadProgIcon(BPTR *icondir, STRPTR iconname)
1290 struct DiskObject *progicon = NULL;
1292 if (wbstartup)
1294 BPTR olddir;
1296 *icondir = wbstartup->sm_ArgList[0].wa_Lock;
1298 olddir = CurrentDir(*icondir);
1299 progicon = GetDiskObject(wbstartup->sm_ArgList[0].wa_Name);
1300 CurrentDir(olddir);
1302 strncpy(iconname, wbstartup->sm_ArgList[0].wa_Name, 255);
1304 else
1306 if (GetProgramName(iconname, 255))
1308 BPTR olddir;
1310 *icondir = GetProgramDir();
1312 olddir = CurrentDir(*icondir);
1313 progicon = GetDiskObject(iconname);
1314 CurrentDir(olddir);
1318 return progicon;
1321 /*********************************************************************************************/
1323 static void SaveSettings(void)
1325 struct DiskObject *progicon;
1326 UBYTE **ttypes, **old_ttypes;
1327 UBYTE iconname[256];
1328 BPTR icondir = BNULL;
1330 progicon = LoadProgIcon(&icondir, iconname);
1332 if (!progicon) return;
1334 old_ttypes = (UBYTE **)progicon->do_ToolTypes;
1335 if ((ttypes = BuildToolTypes(old_ttypes)))
1337 BPTR olddir;
1339 #if 0 /* DEBUG */
1340 UBYTE *tt, **ttypes_copy = ttypes;
1342 while((tt = *ttypes_copy++))
1344 kprintf("TT: %s\n", tt);
1346 #endif
1348 olddir = CurrentDir(icondir);
1350 progicon->do_ToolTypes = ttypes;
1351 PutDiskObject(iconname, progicon);
1352 progicon->do_ToolTypes = old_ttypes;
1354 CurrentDir(olddir);
1356 FreeToolTypes(ttypes);
1359 FreeDiskObject(progicon);
1363 /*********************************************************************************************/
1365 static void LoadSettings(void)
1367 struct DiskObject *progicon;
1368 UBYTE iconname[256];
1369 BPTR icondir = BNULL;
1370 UBYTE **ttypes, *tt;
1372 progicon = LoadProgIcon(&icondir, iconname);
1373 if (!progicon) return;
1375 if ((ttypes = (UBYTE **)progicon->do_ToolTypes))
1377 while((tt = *ttypes++))
1379 struct KeyInfo ki = {0};
1380 UBYTE *quote_end;
1382 ki.action = 0xFF;
1384 if ((tt[0] == QUOTE_START) && ((quote_end = strchr(tt, (char)QUOTE_END))))
1386 WORD len = quote_end - tt - 1;
1388 if (len >= sizeof(ki.descr)) continue;
1389 if (quote_end[1] != ' ') continue;
1391 strncpy(ki.descr, tt + 1, len);
1393 if (strncmp(quote_end + 2, "CYCLE", 5 + 1) == 0)
1395 ki.action = ACTION_CYCLE_WIN;
1397 else if (strncmp(quote_end + 2, "CYCLESCREEN", 11 + 1) == 0)
1399 ki.action = ACTION_CYCLE_SCR;
1401 else if (strncmp(quote_end + 2, "MAKEBIG", 7 + 1) == 0)
1403 ki.action = ACTION_ENLARGE_WIN;
1405 else if (strncmp(quote_end + 2, "MAKESMALL", 9 + 1) == 0)
1407 ki.action = ACTION_SHRINK_WIN;
1409 else if (strncmp(quote_end + 2, "ZIPWINDOW", 9 + 1) == 0)
1411 ki.action = ACTION_TOGGLE_WIN;
1413 else if (strncmp(quote_end + 2, "RESCUEWIN", 9 + 1) == 0)
1415 ki.action = ACTION_RESCUE_WIN;
1417 else if (strncmp(quote_end + 2, "INSERT ", 7) == 0)
1419 ki.action = ACTION_INSERT_TEXT;
1420 strncpy(ki.param, quote_end + 2 + 7, sizeof(ki.param) - 1);
1422 else if (strncmp(quote_end + 2, "RUN ", 4) == 0)
1424 ki.action = ACTION_RUN_PROG;
1425 strncpy(ki.param, quote_end + 2 + 4, sizeof(ki.param) - 1);
1427 else if (strncmp(quote_end + 2, "AREXX ", 6) == 0)
1429 ki.action = ACTION_RUN_AREXX;
1430 strncpy(ki.param, quote_end + 2 + 6, sizeof(ki.param) - 1);
1433 if (ki.action != 0xFF)
1435 DoMethod(list, MUIM_List_InsertSingle, (IPTR)&ki, MUIV_List_Insert_Bottom);
1438 } /* if ((tt[0] == QUOTE_START) && ((quote_end = strchr(tt, QUOTE_END)))) */
1440 } /* while((tt = *ttypes++)) */
1443 LONG index;
1445 for(index = 0; ; index++)
1447 struct KeyInfo *ki = NULL;
1449 DoMethod(list, MUIM_List_GetEntry, index, (IPTR)&ki);
1450 if (!ki) break;
1452 RethinkKey(ki);
1456 } /* if ((ttypes = (UBYTE **)progicon->do_ToolTypes)) */
1458 FreeDiskObject(progicon);
1461 /*********************************************************************************************/
1463 static void HandleAll(void)
1465 ULONG sigs = 0;
1466 IPTR num_list_entries = 0;
1468 get(list, MUIA_List_Entries, &num_list_entries);
1469 if ((num_list_entries == 0) || cx_popup)
1471 set(wnd, MUIA_Window_Open, TRUE);
1473 else
1475 set(wnd, MUIA_Window_Open, FALSE);
1478 while (DoMethod(app,MUIM_Application_NewInput,&sigs) !=MUIV_Application_ReturnID_Quit)
1480 if (sigs)
1482 sigs = Wait(sigs | SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_E | SIGBREAKF_CTRL_F);
1483 if (sigs & SIGBREAKF_CTRL_C)
1485 break;
1487 if (sigs & SIGBREAKF_CTRL_E)
1489 HandleAction();
1491 if (sigs & SIGBREAKF_CTRL_F)
1493 CallHookPkt(&show_hook, NULL, NULL);
1499 /*********************************************************************************************/
1501 int main(int argc, char **argv)
1503 GetArguments(argc, argv);
1504 InitLocale(CATALOG_NAME, CATALOG_VERSION);
1505 InitCX();
1506 InitMenus();
1507 MakeGUI();
1508 LoadSettings();
1509 HandleAll();
1510 Cleanup(NULL);
1512 return 0;