Bubblehelp shows character in decimal and hexadecimal.
[cake.git] / workbench / tools / commodities / ASCIITable.c
blobe3f92010f40d41c25efa33926d73d37981ea0b63
1 /*
2 Copyright © 2009, The AROS Development Team. All rights reserved.
3 $Id$
5 ASCIITable -- Insert characters to clipboard from GUI.
6 */
8 /******************************************************************************
10 NAME
12 ASCIITable
14 SYNOPSIS
16 CX_PRIORITY/K/N,CX_POPUP/K/S,CX_POPKEY/K
18 LOCATION
20 Workbench:Tools/Commodities
22 FUNCTION
24 Insert characters to clipboard from GUI
26 INPUTS
28 CX_PRIORITY -- Priority of the ASCIITable broker
29 CX_POPUP -- Appear at startup
30 CX_POPKEY -- Hotkey combination for ASCIITable
32 RESULT
34 NOTES
36 EXAMPLE
38 BUGS
40 SEE ALSO
42 INTERNALS
44 ******************************************************************************/
46 #define MUIMASTER_YES_INLINE_STDARG
48 #include <stdio.h>
49 #include <stdlib.h>
50 #include <string.h>
52 //#define DEBUG 1
53 #include <aros/debug.h>
54 #include <aros/asmcall.h>
55 #include <aros/symbolsets.h>
56 #include <libraries/iffparse.h>
57 #include <libraries/mui.h>
58 #include <zune/customclasses.h>
59 #include <devices/clipboard.h>
61 #include <proto/muimaster.h>
62 #include <proto/locale.h>
63 #include <proto/intuition.h>
64 #include <proto/exec.h>
65 #include <proto/dos.h>
66 #include <proto/alib.h>
67 #include <proto/commodities.h>
68 #include <proto/utility.h>
70 #define CATCOMP_ARRAY
71 #include "strings.h"
73 #define CATALOG_NAME "System/Tools/Commodities.catalog"
74 #define CATALOG_VERSION 3
76 TEXT version[] = "$VER: ASCIITable 1.0 (27.05.2009)";
78 #define ARG_TEMPLATE "CX_PRIORITY/N/K,CX_POPKEY/K,CX_POPUP/S"
79 #define DEF_POPKEY "ctrl alt a"
81 enum {
82 ARG_CXPRI,
83 ARG_CXPOPKEY,
84 ARG_CXPOPUP,
85 NUM_ARGS
88 static Object *app, *wnd;
89 static struct Catalog *catalog;
90 static UBYTE s[257];
92 static struct Hook broker_hook;
94 static LONG cx_pri;
95 static char *cx_popkey;
96 static BOOL cx_popup = FALSE;
97 static CxObj *broker;
98 static struct MsgPort *brokermp;
99 static struct Task *maintask;
101 static void Cleanup(CONST_STRPTR txt);
102 static void GetArguments(int argc, char **argv);
103 static void HandleAll(void);
104 static void InitMenus(void);
105 static VOID Locale_Deinitialize(VOID);
106 static int Locale_Initialize(VOID);
107 static void MakeGUI(void);
108 static void showSimpleMessage(CONST_STRPTR msgString);
109 static CONST_STRPTR _(ULONG id);
111 static struct IOClipReq *CBOpen(ULONG unit);
112 static void CBClose(struct IOClipReq *ior);
113 static BOOL CBWriteFTXT(struct IOClipReq *ior, CONST_STRPTR string);
114 static BOOL CBWriteLong(struct IOClipReq *ior, LONG *ldata);
116 /*** ASCIITable class *******************************************************/
118 #define MAXLEN (60)
120 #define ASCIITableObject BOOPSIOBJMACRO_START(ASCIITable_CLASS->mcc_Class)
122 #define MUIM_ASCIITable_Copy (TAG_USER | 1)
123 #define MUIM_ASCIITable_Clear (TAG_USER | 2)
124 #define MUIM_ASCIITable_Insert (TAG_USER | 3)
125 struct MUIP_ASCIITable_Insert {STACKED ULONG MethodID; STACKED LONG code;};
127 struct ASCIITable_DATA
129 Object *copy_button;
130 Object *clear_button;
131 Object *ascii_string;
132 Object *key_button[192];
133 TEXT buffer[MAXLEN + 1];
134 struct IOClipReq *clip_req;
135 TEXT shorthelp[20][192];
138 /*** CBOpen *****************************************************************/
139 static struct IOClipReq *CBOpen(ULONG unit)
141 struct MsgPort *mp;
142 struct IORequest *ior;
144 if ((mp = CreatePort(0, 0)))
146 if ((ior = (struct IORequest *)CreateExtIO(mp, sizeof(struct IOClipReq))))
148 if (!(OpenDevice("clipboard.device", unit, ior, 0)))
150 return (struct IOClipReq *)ior;
152 DeleteExtIO(ior);
154 DeletePort(mp);
156 return NULL;
159 /*** CBCLose ****************************************************************/
160 static void CBClose(struct IOClipReq *ior)
162 if (ior)
164 struct MsgPort *mp = ior->io_Message.mn_ReplyPort;
166 CloseDevice((struct IORequest *)ior);
167 DeleteExtIO((struct IORequest *)ior);
168 DeletePort(mp);
172 /*** CBWriteFTXT ************************************************************/
173 static BOOL CBWriteFTXT(struct IOClipReq *ior, CONST_STRPTR string)
175 LONG length, slen, temp;
176 BOOL odd;
178 if (!ior || !string)
179 return FALSE;
181 slen = strlen(string);
182 odd = (slen & 1);
184 length = (odd) ? slen+1 : slen;
186 ior->io_Offset = 0;
187 ior->io_Error = 0;
188 ior->io_ClipID = 0;
190 CBWriteLong(ior, (LONG *) "FORM");
191 length += 12;
193 temp = AROS_LONG2BE(length);
194 CBWriteLong(ior, &temp);
195 CBWriteLong(ior, (LONG *) "FTXT");
196 CBWriteLong(ior, (LONG *) "CHRS");
197 temp = AROS_LONG2BE(slen);
198 CBWriteLong(ior, &temp);
200 ior->io_Data = (STRPTR)string;
201 ior->io_Length = slen;
202 ior->io_Command = CMD_WRITE;
203 DoIO((struct IORequest *)ior);
205 if (odd)
207 ior->io_Data = (APTR)"";
208 ior->io_Length = 1;
209 DoIO((struct IORequest *)ior);
212 ior->io_Command=CMD_UPDATE;
213 DoIO ((struct IORequest *)ior);
215 return ior->io_Error ? FALSE : TRUE;
218 /*** WriteLong **************************************************************/
219 static BOOL CBWriteLong(struct IOClipReq *ior, LONG *ldata)
221 ior->io_Data = (APTR)ldata;
222 ior->io_Length = 4;
223 ior->io_Command = CMD_WRITE;
224 DoIO( (struct IORequest *) ior);
226 if (ior->io_Actual == 4)
228 return ior->io_Error ? FALSE : TRUE;
231 return FALSE;
234 /*** MakeButton *************************************************************/
235 static Object *MakeButton(LONG code)
237 char buffer[2] = {0};
238 buffer[0] = code;
240 Object *btn = (Object *)TextObject,
241 ButtonFrame,
242 MUIA_Font, MUIV_Font_Button,
243 MUIA_Text_Contents, (IPTR)buffer,
244 MUIA_Text_PreParse, (IPTR)"\33c",
245 MUIA_InputMode , MUIV_InputMode_RelVerify,
246 MUIA_Background , MUII_ButtonBack,
247 MUIA_CycleChain , TRUE,
248 End;
249 return btn;
252 /*** OM_NEW *****************************************************************/
253 IPTR ASCIITable__OM_NEW(Class *CLASS, Object *self, struct opSet *message)
255 struct ASCIITable_DATA *data = NULL;
256 Object *copy_button, *clear_button, *ascii_string, *key_group;
257 struct TagItem key_group_tags[200];
258 LONG i, code;
260 for (code = 32 , i = 0 ; code < 128 ; code++ , i++)
262 key_group_tags[i].ti_Tag = Child;
263 key_group_tags[i].ti_Data = (IPTR)MakeButton(code);
265 for (code = 160 ; code < 256 ; code++, i++)
267 key_group_tags[i].ti_Tag = Child;
268 key_group_tags[i].ti_Data = (IPTR)MakeButton(code);
270 key_group_tags[i].ti_Tag = MUIA_Group_Columns;
271 key_group_tags[i].ti_Data = 16;
272 key_group_tags[++i].ti_Tag = TAG_DONE;
273 key_group = MUI_NewObjectA(MUIC_Group, key_group_tags);
275 self = (Object *) DoSuperNewTags
277 CLASS, self, NULL,
278 Child, key_group,
279 Child, (IPTR) (RectangleObject,
280 MUIA_Rectangle_HBar, TRUE,
281 MUIA_FixHeight, 2,
282 End),
283 Child, (IPTR)(ascii_string = (Object *)StringObject,
284 StringFrame,
285 MUIA_String_MaxLen, MAXLEN,
286 End),
287 Child, (IPTR) (HGroup,
288 MUIA_Weight, 0,
289 MUIA_Group_SameSize, TRUE,
291 Child, (IPTR) (copy_button = SimpleButton(_(MSG_ASCIITABLE_GAD_COPY))),
292 Child, (IPTR) (clear_button = SimpleButton(_(MSG_ASCIITABLE_GAD_CLEAR))),
293 End),
294 TAG_DONE
297 if (self != NULL)
299 /*-- Store important variables -------------------------------------*/
300 data = INST_DATA(CLASS, self);
301 data->copy_button = copy_button;
302 data->clear_button = clear_button;
303 data->ascii_string = ascii_string;
305 /*-- Setup notifications -------------------------------------------*/
306 DoMethod
308 copy_button, MUIM_Notify, MUIA_Pressed, FALSE,
309 (IPTR) self, 1, MUIM_ASCIITable_Copy
311 DoMethod
313 clear_button, MUIM_Notify, MUIA_Pressed, FALSE,
314 (IPTR) self, 1, MUIM_ASCIITable_Clear
317 for (i = 0 ; i < 192 ; i++)
319 code = (i < 96) ? i + 32 : i + 64;
320 sprintf(data->shorthelp[i], "%c\n%d\n0x%x", code, code, code);
321 set((Object *)key_group_tags[i].ti_Data, MUIA_ShortHelp, data->shorthelp[i]);
322 DoMethod
324 (Object *)key_group_tags[i].ti_Data, MUIM_Notify, MUIA_Pressed, FALSE,
325 (IPTR) self, 2, MUIM_ASCIITable_Insert, code
328 data->clip_req = CBOpen(0);
329 if (!data->clip_req)
331 showSimpleMessage(_(MSG_CANT_OPEN_CLIPDEVICE));
335 return (IPTR) self;
338 /*** OM_DISPOSE *************************************************************/
339 IPTR ASCIITable__OM_DISPOSE(Class *CLASS, Object *self, Msg message)
341 struct ASCIITable_DATA *data = INST_DATA(CLASS, self);
343 CBClose(data->clip_req);
345 return DoSuperMethodA(CLASS, self, message);
348 /*** MUIM_ASCIITable_Copy ***************************************************/
349 IPTR ASCIITable__MUIM_ASCIITable_Copy(Class *CLASS, Object *self, Msg msg)
351 struct ASCIITable_DATA *data = INST_DATA(CLASS, self);
352 CBWriteFTXT(data->clip_req, (CONST_STRPTR)XGET(data->ascii_string, MUIA_String_Contents));
353 return TRUE;
356 /*** MUIM_ASCIITable_Clear **************************************************/
357 IPTR ASCIITable__MUIM_ASCIITable_Clear(Class *CLASS, Object *self, Msg msg)
359 struct ASCIITable_DATA *data = INST_DATA(CLASS, self);
360 data->buffer[0] = '\0';
361 set(data->ascii_string, MUIA_String_Contents, "");
362 return TRUE;
365 /*** MUIM_ASCIITable_Insert *************************************************/
366 IPTR ASCIITable__MUIM_ASCIITable_Insert(Class *CLASS, Object *self, struct MUIP_ASCIITable_Insert *msg)
368 struct ASCIITable_DATA *data = INST_DATA(CLASS, self);
369 LONG len;
370 D(bug("insert code %d\n", msg->code));
371 strcpy(data->buffer, (CONST_STRPTR)XGET(data->ascii_string, MUIA_String_Contents));
372 len = strlen(data->buffer);
373 if (len < MAXLEN)
375 data->buffer[len] = msg->code;
376 data->buffer[len+1] = '\0';
377 set(data->ascii_string, MUIA_String_Contents, data->buffer);
379 return TRUE;
382 /*** Setup ******************************************************************/
383 ZUNE_CUSTOMCLASS_5
385 ASCIITable, NULL, MUIC_Group, NULL,
386 OM_NEW, struct opSet *,
387 OM_DISPOSE, Msg,
388 MUIM_ASCIITable_Copy, Msg,
389 MUIM_ASCIITable_Clear, Msg,
390 MUIM_ASCIITable_Insert, struct MUIP_ASCIITable_Insert *
395 /*** Begin application ******************************************************/
398 static CONST_STRPTR _(ULONG id)
400 if (LocaleBase != NULL && catalog != NULL)
402 return GetCatalogStr(catalog, id, CatCompArray[id].cca_Str);
404 else
406 return CatCompArray[id].cca_Str;
410 #define __(id) ((IPTR) _(id)) /* Get a message, as an IPTR */
412 /*** Locale_Initialize ******************************************************/
413 static int Locale_Initialize(VOID)
415 if (LocaleBase != NULL)
417 catalog = OpenCatalog
419 NULL, CATALOG_NAME, OC_Version, CATALOG_VERSION, TAG_DONE
422 else
424 catalog = NULL;
426 return TRUE;
429 /*** Locale_Deinitialize ****************************************************/
430 static VOID Locale_Deinitialize(VOID)
432 if (LocaleBase != NULL && catalog != NULL) CloseCatalog(catalog);
435 /*** GetArguments ***********************************************************/
436 static void GetArguments(int argc, char **argv)
438 static struct RDArgs *myargs;
439 static IPTR args[NUM_ARGS];
440 static UBYTE **wbargs;
441 if (argc)
443 if (!(myargs = ReadArgs(ARG_TEMPLATE, args, NULL)))
445 Fault(IoErr(), 0, s, 256);
446 Cleanup(s);
448 if (args[ARG_CXPRI]) cx_pri = *(LONG*)args[ARG_CXPRI];
449 if (args[ARG_CXPOPKEY])
451 cx_popkey = StrDup((char *)args[ARG_CXPOPKEY]);
453 else
455 cx_popkey = StrDup(DEF_POPKEY);
457 if (args[ARG_CXPOPUP]) cx_popup = TRUE;
458 FreeArgs(myargs);
460 else
462 wbargs = ArgArrayInit(argc, (UBYTE**)argv);
463 cx_pri = ArgInt(wbargs, "CX_PRIORITY", 0);
464 cx_popkey = StrDup(ArgString(wbargs, "CX_POPKEY", DEF_POPKEY));
465 if (strnicmp(ArgString(wbargs, "CX_POPUP", "NO"), "Y", 1) == 0)
467 cx_popup = TRUE;
469 ArgArrayDone();
471 D(bug("ASCIITable Arguments pri %d popkey %s popup %d\n", cx_pri, cx_popkey, cx_popup));
474 /****************************************************************************/
475 static struct NewMenu nm[] =
477 {NM_TITLE, (STRPTR)MSG_MEN_PROJECT },
478 {NM_ITEM, (STRPTR)MSG_MEN_PROJECT_HIDE },
479 {NM_ITEM, (STRPTR)MSG_MEN_PROJECT_ICONIFY },
480 {NM_ITEM, NM_BARLABEL },
481 {NM_ITEM, (STRPTR)MSG_MEN_PROJECT_QUIT },
482 {NM_END }
485 /*** InitMenus **************************************************************/
486 static void InitMenus(void)
488 struct NewMenu *actnm = nm;
490 for(actnm = nm; actnm->nm_Type != NM_END; actnm++)
492 if (actnm->nm_Label != NM_BARLABEL)
494 ULONG id = (ULONG)actnm->nm_Label;
495 CONST_STRPTR str = _(id);
497 if (actnm->nm_Type == NM_TITLE)
499 actnm->nm_Label = str;
500 } else {
501 actnm->nm_Label = str + 2;
502 if (str[0] != ' ') actnm->nm_CommKey = str;
504 actnm->nm_UserData = (APTR)id;
506 } /* if (actnm->nm_Label != NM_BARLABEL) */
508 } /* for(actnm = nm; nm->nm_Type != NM_END; nm++) */
511 /*** showSimpleMessage ******************************************************/
512 static void showSimpleMessage(CONST_STRPTR msgString)
514 struct EasyStruct easyStruct;
516 easyStruct.es_StructSize = sizeof(easyStruct);
517 easyStruct.es_Flags = 0;
518 easyStruct.es_Title = _(MSG_ASCIITABLE_CXNAME);
519 easyStruct.es_TextFormat = msgString;
520 easyStruct.es_GadgetFormat = _(MSG_OK);
522 if (IntuitionBase != NULL && !Cli() )
524 EasyRequestArgs(NULL, &easyStruct, NULL, NULL);
526 else
528 PutStr(msgString);
532 /*** broker_func ************************************************************/
533 AROS_UFH3(void, broker_func,
534 AROS_UFHA(struct Hook *, h, A0),
535 AROS_UFHA(Object * , object, A2),
536 AROS_UFHA(CxMsg * , msg, A1))
538 AROS_USERFUNC_INIT
540 D(bug("ASCIITable: Broker hook called\n"));
541 if (CxMsgType(msg) == CXM_COMMAND)
543 if (CxMsgID(msg) == CXCMD_APPEAR)
545 //This opens window if application was started with cx_popup=no
546 set(app, MUIA_Application_Iconified, FALSE);
549 AROS_USERFUNC_EXIT
552 /*** MakeGUI ****************************************************************/
553 static void MakeGUI(void)
555 Object *menu;
556 static TEXT wintitle[100];
557 CxObj *popfilter;
559 menu = MUI_MakeObject(MUIO_MenustripNM, &nm, 0);
561 broker_hook.h_Entry = (HOOKFUNC)broker_func;
563 snprintf(wintitle, sizeof(wintitle), _(MSG_ASCIITABLE_WINTITLE), cx_popkey);
565 app = (Object *)ApplicationObject,
566 MUIA_Application_Title, __(MSG_ASCIITABLE_CXNAME),
567 MUIA_Application_Version, (IPTR)version,
568 MUIA_Application_Copyright, (IPTR)"Copyright © 2009, The AROS Development TEAM",
569 MUIA_Application_Author, (IPTR)"The AROS Development Team",
570 MUIA_Application_Description, __(MSG_ASCIITABLE_CXDESCR),
571 MUIA_Application_BrokerPri, cx_pri,
572 MUIA_Application_BrokerHook, (IPTR)&broker_hook,
573 MUIA_Application_Base, (IPTR)"ASCIITABLE",
574 MUIA_Application_SingleTask, TRUE,
575 MUIA_Application_Menustrip, (IPTR)menu,
576 SubWindow, (IPTR)(wnd = (Object *)WindowObject,
577 MUIA_Window_Title, (IPTR)wintitle,
578 MUIA_Window_ID, MAKE_ID('A', 'I', 'T', 'B'),
579 WindowContents, ASCIITableObject,
580 End,
581 End),
582 End;
584 if (! app)
585 Cleanup(NULL); // Propably double start
587 // enable hotkey
588 maintask = FindTask(NULL);
589 get(app, MUIA_Application_Broker, &broker);
590 get(app, MUIA_Application_BrokerPort, &brokermp);
591 if ( ! broker || ! brokermp)
592 Cleanup(_(MSG_CANT_CREATE_BROKER));
594 popfilter = CxFilter(cx_popkey);
595 if (popfilter)
597 CxObj *popsig = CxSignal(maintask, SIGBREAKB_CTRL_F);
598 if (popsig)
600 CxObj *trans;
601 AttachCxObj(popfilter, popsig);
602 trans = CxTranslate(NULL);
603 if (trans) AttachCxObj(popsig, trans);
605 AttachCxObj(broker, popfilter);
608 DoMethod(wnd, MUIM_Notify, MUIA_Window_CloseRequest, TRUE,
609 (IPTR)app, 3, MUIM_Set, MUIA_Application_Iconified, TRUE);
611 DoMethod(app, MUIM_Notify, MUIA_Application_DoubleStart, TRUE,
612 (IPTR)app, 3, MUIM_Set, MUIA_Application_Iconified, FALSE);
614 // Open the window when app isn't iconified
615 DoMethod(app, MUIM_Notify, MUIA_Application_Iconified, FALSE,
616 (IPTR)wnd, 3, MUIM_Set, MUIA_Window_Open, TRUE);
618 DoMethod(wnd, MUIM_Notify, MUIA_Window_MenuAction, MSG_MEN_PROJECT_QUIT,
619 (IPTR)app, 2, MUIM_Application_ReturnID, MUIV_Application_ReturnID_Quit);
621 DoMethod(wnd, MUIM_Notify, MUIA_Window_MenuAction, MSG_MEN_PROJECT_HIDE,
622 (IPTR)app, 3, MUIM_Set, MUIA_Application_Iconified, TRUE);
624 DoMethod(wnd, MUIM_Notify, MUIA_Window_MenuAction, MSG_MEN_PROJECT_ICONIFY,
625 (IPTR)app, 3, MUIM_Set, MUIA_Application_Iconified, TRUE);
628 /*** HandleAll **************************************************************/
629 static void HandleAll(void)
631 ULONG sigs = 0;
633 set(app, MUIA_Application_Iconified, cx_popup ? FALSE : TRUE);
635 while((LONG) DoMethod(app, MUIM_Application_NewInput, (IPTR)&sigs)
636 != MUIV_Application_ReturnID_Quit)
638 if (sigs)
640 sigs = Wait(sigs | SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_F);
641 if (sigs & SIGBREAKF_CTRL_C)
643 break;
645 if (sigs & SIGBREAKF_CTRL_F)
647 set(app, MUIA_Application_Iconified, FALSE);
653 /*** Cleanup ****************************************************************/
654 static void Cleanup(CONST_STRPTR txt)
656 MUI_DisposeObject(app);
657 FreeVec(cx_popkey);
658 if (txt)
660 showSimpleMessage(txt);
661 exit(RETURN_ERROR);
663 exit(RETURN_OK);
666 /*** main *******************************************************************/
667 int main(int argc, char **argv)
669 D(bug("ASCIITable started\n"));
670 GetArguments(argc, argv);
671 InitMenus();
672 MakeGUI();
673 HandleAll();
674 Cleanup(NULL);
675 return RETURN_OK;
678 /****************************************************************************/
679 ADD2INIT(Locale_Initialize, 90);
680 ADD2EXIT(Locale_Deinitialize, 90);