1 /***************************************************************************
3 BetterString.mcc - A better String gadget MUI Custom Class
4 Copyright (C) 1997-2000 Allan Odgaard
5 Copyright (C) 2005-2009 by BetterString.mcc Open Source Team
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 2.1 of the License, or (at your option) any later version.
12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 BetterString class Support Site: http://www.sf.net/projects/bstring-mcc/
21 ***************************************************************************/
25 #include <clib/alib_protos.h>
26 #include <proto/exec.h>
27 #include <proto/intuition.h>
28 #include <proto/muimaster.h>
29 #include <proto/graphics.h>
30 #include <proto/utility.h>
31 #include <proto/locale.h>
36 struct NewMenu PopupMenuData[] =
38 NM_TITLE, "Stringgadget", NULL, 0L, 0, (APTR)0,
39 NM_ITEM, "Cut", NULL, 0L, 0, (APTR)1,
40 NM_ITEM, "Copy", NULL, 0L, 0, (APTR)2,
41 NM_ITEM, "Paste", NULL, 0L, 0, (APTR)3,
42 NM_ITEM, NM_BARLABEL, NULL, 0L, 0, (APTR)0,
43 NM_ITEM, "Undo", NULL, 0L, 0, (APTR)4,
44 NM_ITEM, "Redo", NULL, 0L, 0, (APTR)5,
45 NM_ITEM, "Original", NULL, 0L, 0, (APTR)6,
46 NM_ITEM, NM_BARLABEL, NULL, 0L, 0, (APTR)0,
47 NM_ITEM, "Complete path", NULL, 0L, 0, (APTR)7,
48 NM_ITEM, "Toggle case", NULL, 0L, 0, (APTR)0,
49 NM_SUB, "Character", NULL, 0L, 0, (APTR)8,
50 NM_SUB, "Word", NULL, 0L, 0, (APTR)9,
51 NM_ITEM, "Arithmetic", NULL, 0L, 0, (APTR)0,
52 NM_SUB, "Increase", NULL, 0L, 0, (APTR)10,
53 NM_SUB, "Decrease", NULL, 0L, 0, (APTR)11,
54 NM_SUB, "To decimal", NULL, 0L, 0, (APTR)12,
55 NM_SUB, "To hexadecimal", NULL, 0L, 0, (APTR)13,
56 NM_END, NULL, NULL, 0L, 0, (APTR)0
60 //#ifndef MUIM_Backfill
61 //#define MUIA_CustomBackfill 0x80420a63
62 //#define MUIM_Backfill 0x80428d73
63 //struct MUIP_Backfill { ULONG MethodID; LONG left; LONG top; LONG right; LONG bottom; LONG xoffset; LONG yoffset; };
66 IPTR
New(struct IClass
*cl
, Object
*obj
, struct opSet
*msg
)
68 if((obj
= (Object
*)DoSuperMethodA(cl
, obj
, (Msg
)msg
)))
70 struct InstData
*data
= (struct InstData
*)INST_DATA(cl
, obj
);
72 // kprintf("OM_NEW by %s\n", FindTask(NULL)->tc_Node.ln_Name);
74 data
->locale
= OpenLocale(NULL
);
75 data
->Contents
= (STRPTR
)SharedPoolAlloc(40);
76 *data
->Contents
= '\0';
78 // data->PopupMenu = MUI_MakeObject(MUIO_MenustripNM, PopupMenuData, NULL);
79 SetAttrs(obj
, MUIA_FillArea
, FALSE
,
80 // MUIA_ContextMenu, data->PopupMenu,
81 // MUIA_CustomBackfill, TRUE,
84 if(FindTagItem(MUIA_Font
, msg
->ops_AttrList
))
85 setFlag(data
->Flags
, FLG_OwnFont
);
87 if(FindTagItem(MUIA_Background
, msg
->ops_AttrList
))
88 setFlag(data
->Flags
, FLG_OwnBackground
);
93 if((tag
= FindTagItem(MUIA_Frame
, msg
->ops_AttrList
)))
95 if(tag
->ti_Data
== MUIV_Frame_String
)
96 setFlag(data
->Flags
, FLG_SetFrame
);
100 msg
->MethodID
= OM_SET
;
101 Set(cl
, obj
, (struct opSet
*)msg
);
102 msg
->MethodID
= OM_NEW
;
107 CoerceMethod(cl
, obj
, OM_DISPOSE
);
112 IPTR
Dispose(struct IClass
*cl
, Object
*obj
, Msg msg
)
114 struct InstData
*data
= (struct InstData
*)INST_DATA(cl
, obj
);
116 // kprintf("OM_DISPOSE by %s\n", FindTask(NULL)->tc_Node.ln_Name);
117 /* if(data->PopupMenu)
118 MUI_DisposeObject(data->PopupMenu);
121 if(data
->locale
!= NULL
)
123 CloseLocale(data
->locale
);
127 return(DoSuperMethodA(cl
, obj
, msg
));
130 IPTR
Export(struct IClass
*cl
, Object
*obj
, struct MUIP_Export
*msg
)
132 struct InstData
*data
= (struct InstData
*)INST_DATA(cl
, obj
);
135 if((id
= (muiNotifyData(obj
)->mnd_ObjectID
)) != 0)
136 DoMethod(msg
->dataspace
, MUIM_Dataspace_Add
, data
->Contents
, strlen(data
->Contents
)+1, id
);
141 IPTR
Import(UNUSED
struct IClass
*cl
, Object
*obj
, struct MUIP_Import
*msg
)
145 if((id
= (muiNotifyData(obj
)->mnd_ObjectID
)) != 0)
147 STRPTR contents
= (STRPTR
)DoMethod(msg
->dataspace
, MUIM_Dataspace_Find
, id
);
150 set(obj
, MUIA_String_Contents
, contents
);
156 IPTR
Setup(struct IClass
*cl
, Object
*obj
, struct MUI_RenderInfo
*rinfo
)
158 struct InstData
*data
= (struct InstData
*)INST_DATA(cl
, obj
);
162 InitConfig(obj
, data
);
164 if(DoSuperMethodA(cl
, obj
, (Msg
)rinfo
))
167 if(DoMethod(obj, MUIM_GetConfigItem, 132, &color))
172 strcat(image, (STRPTR)color);
173 set(obj, MUIA_Background, image);
177 _flags(obj
) |= (1<<7);
179 data
->ehnode
.ehn_Priority
= 0;
180 data
->ehnode
.ehn_Flags
= MUI_EHF_GUIMODE
;
181 data
->ehnode
.ehn_Object
= obj
;
182 data
->ehnode
.ehn_Class
= cl
;
183 data
->ehnode
.ehn_Events
= IDCMP_MOUSEBUTTONS
| IDCMP_RAWKEY
;
185 // setup the selection pointer
186 if(data
->SelectPointer
== TRUE
)
188 data
->ehnode
.ehn_Events
|= IDCMP_MOUSEMOVE
;
189 SetupSelectPointer(data
);
192 DoMethod(_win(obj
), MUIM_Window_AddEventHandler
, &data
->ehnode
);
202 IPTR
Cleanup(struct IClass
*cl
, Object
*obj
, Msg msg
)
204 struct InstData
*data
= (struct InstData
*)INST_DATA(cl
, obj
);
206 // cleanup the selection pointer
207 CleanupSelectPointer(data
);
209 DoMethod(_win(obj
), MUIM_Window_RemEventHandler
, &data
->ehnode
);
211 // make sure the gadget is being set to inactive state
213 if(isFlagSet(data->Flags, FLG_Active))
215 clearFlag(data->Flags, FLG_Active);
216 clearFlag(data->ehnode.ehn_Events, IDCMP_MOUSEMOVE);
218 if(isFlagClear(data->Flags, FLG_OwnBackground))
219 set(obj, MUIA_Background, data->InactiveBackground);
222 FreeConfig(muiRenderInfo(obj
), data
);
224 return(DoSuperMethodA(cl
, obj
, msg
));
227 IPTR
AskMinMax(struct IClass
*cl
, Object
*obj
, struct MUIP_AskMinMax
*msg
)
229 struct InstData
*data
= (struct InstData
*)INST_DATA(cl
, obj
);
230 struct TextFont
*font
;
233 DoSuperMethodA(cl
, obj
, (Msg
)msg
);
235 font
= data
->Font
? data
->Font
: muiAreaData(obj
)->mad_Font
;
236 Height
= font
->tf_YSize
;
237 msg
->MinMaxInfo
->MinHeight
+= Height
;
238 msg
->MinMaxInfo
->DefHeight
+= Height
;
239 msg
->MinMaxInfo
->MaxHeight
+= Height
;
245 SetFont(&data
->rport
, font
);
246 width
= data
->Width
* TextLength(&data
->rport
, "n", 1);
248 msg
->MinMaxInfo
->MinWidth
+= width
;
249 msg
->MinMaxInfo
->DefWidth
+= width
;
250 msg
->MinMaxInfo
->MaxWidth
+= width
;
254 msg
->MinMaxInfo
->MinWidth
+= 10;
255 msg
->MinMaxInfo
->DefWidth
+= 100;
256 msg
->MinMaxInfo
->MaxWidth
+= MBQ_MUI_MAXMAX
;
262 IPTR
Show(struct IClass
*cl
, Object
*obj
, Msg msg
)
264 struct InstData
*data
= (struct InstData
*)INST_DATA(cl
, obj
);
265 struct MUI_AreaData
*ad
= muiAreaData(obj
);
266 struct BitMap
*friendBMp
= muiRenderInfo(obj
)->mri_RastPort
->BitMap
;
267 WORD width
, height
, depth
;
268 struct TextFont
*font
= data
->Font
? data
->Font
: ad
->mad_Font
;
270 DoSuperMethodA(cl
, obj
, msg
);
272 width
= ad
->mad_Box
.Width
- ad
->mad_subwidth
;
273 height
= font
->tf_YSize
;
274 depth
= ((struct Library
*)GfxBase
)->lib_Version
>= 39 ? GetBitMapAttr(friendBMp
, BMA_DEPTH
) : friendBMp
->Depth
;
276 InitRastPort(&data
->rport
);
277 data
->rport
.BitMap
= MUIG_AllocBitMap(width
+40, height
, depth
, (IPTR
)NULL
, friendBMp
);
278 SetFont(&data
->rport
, font
);
279 SetDrMd(&data
->rport
, JAM1
);
281 setFlag(data
->Flags
, FLG_Shown
);
286 IPTR
Hide(struct IClass
*cl
, Object
*obj
, Msg msg
)
288 struct InstData
*data
= (struct InstData
*)INST_DATA(cl
, obj
);
291 if(isFlagSet(data
->Flags
, FLG_Shown
))
292 DeinitRastPort(&data
->rport
);
295 clearFlag(data
->Flags
, FLG_Shown
);
297 // hide the selection pointer
298 HideSelectPointer(obj
, data
);
300 MUIG_FreeBitMap(data
->rport
.BitMap
);
302 return(DoSuperMethodA(cl
, obj
, msg
));
305 IPTR
mDraw(struct IClass
*cl
, Object
*obj
, struct MUIP_Draw
*msg
)
307 DoSuperMethodA(cl
, obj
, (Msg
)msg
);
309 if(isFlagSet(msg
->flags
, MADF_DRAWUPDATE
) || isFlagSet(msg
->flags
, MADF_DRAWOBJECT
))
311 PrintString(cl
, obj
);
317 IPTR
HandleEvent(struct IClass
*cl
, Object
*obj
, struct MUIP_HandleEvent
*msg
)
319 struct InstData
*data
= (struct InstData
*)INST_DATA(cl
, obj
);
322 if(isFlagSet(data
->Flags
, FLG_Ghosted
) || isFlagClear(data
->Flags
, FLG_Shown
))
328 ULONG display_pos
= data
->DisplayPos
;
330 result
= HandleInput(cl
, obj
, msg
);
331 if(display_pos
!= data
->DisplayPos
)
332 set(obj
, MUIA_String_DisplayPos
, data
->DisplayPos
);
334 if(!result
&& data
->ForwardObject
!= NULL
)
341 attr
= MUIV_List_Active_Top
;
345 attr
= MUIV_List_Active_Bottom
;
349 attr
= MUIV_List_Active_Up
;
353 attr
= MUIV_List_Active_Down
;
357 attr
= MUIV_List_Active_PageUp
;
360 case MUIKEY_PAGEDOWN
:
361 attr
= MUIV_List_Active_PageDown
;
367 set(data
->ForwardObject
, MUIA_List_Active
, attr
);
368 result
= MUI_EventHandlerRC_Eat
;
376 IPTR
GoActive(struct IClass
*cl
, Object
*obj
, UNUSED Msg msg
)
378 struct InstData
*data
= (struct InstData
*)INST_DATA(cl
, obj
);
380 D(DBF_INPUT
, "GoActive: %08lx", obj
);
382 setFlag(data
->Flags
, FLG_Active
);
383 setFlag(data
->Flags
, FLG_FreshActive
);
385 DoMethod(_win(obj), MUIM_Window_RemEventHandler, &data->ehnode);
386 setFlag(data->ehnode.ehn_Events, IDCMP_RAWKEY);
387 DoMethod(_win(obj), MUIM_Window_AddEventHandler, &data->ehnode);
389 if(data
->Original
!= NULL
)
390 SharedPoolFree(data
->Original
);
392 if((data
->Original
= (STRPTR
)SharedPoolAlloc(strlen(data
->Contents
)+1)) != NULL
)
393 strlcpy(data
->Original
, data
->Contents
, strlen(data
->Contents
+1));
395 // select everything if this is necessary or requested
396 if((data
->SelectOnActive
== TRUE
&& isFlagClear(data
->Flags
, FLG_MouseButtonDown
) && isFlagClear(data
->Flags
, FLG_ForceSelectOff
)) ||
397 isFlagSet(data
->Flags
, FLG_ForceSelectOn
))
399 data
->BlockStart
= 0;
400 data
->BlockStop
= strlen(data
->Contents
);
401 setFlag(data
->Flags
, FLG_BlockEnabled
);
404 if(isFlagClear(data
->Flags
, FLG_OwnBackground
))
405 set(obj
, MUIA_Background
, data
->ActiveBackground
);
407 MUI_Redraw(obj
, MADF_DRAWUPDATE
);
412 IPTR
GoInactive(struct IClass
*cl
, Object
*obj
, UNUSED Msg msg
)
414 struct InstData
*data
= (struct InstData
*)INST_DATA(cl
, obj
);
416 D(DBF_INPUT
, "GoInActive: %08lx", obj
);
418 // clean an eventually marked block and the
419 // active state flag of the gadget
420 clearFlag(data
->Flags
, FLG_BlockEnabled
);
421 clearFlag(data
->Flags
, FLG_Active
);
422 clearFlag(data
->Flags
, FLG_FreshActive
);
424 DoMethod(_win(obj), MUIM_Window_RemEventHandler, &data->ehnode);
425 clearFlag(data->ehnode.ehn_Events, IDCMP_MOUSEMOVE);
426 DoMethod(_win(obj), MUIM_Window_AddEventHandler, &data->ehnode);
429 if(isFlagClear(data
->Flags
, FLG_OwnBackground
))
430 set(obj
, MUIA_Background
, data
->InactiveBackground
);
432 MUI_Redraw(obj
, MADF_DRAWUPDATE
);
437 DISPATCHER(_Dispatcher
)
443 switch(msg
->MethodID
)
446 result
= New(cl
, obj
, (struct opSet
*)msg
);
450 result
= Setup(cl
, obj
, (struct MUI_RenderInfo
*)msg
);
454 result
= Show(cl
, obj
, msg
);
458 result
= AskMinMax(cl
, obj
, (struct MUIP_AskMinMax
*)msg
);
462 result
= mDraw(cl
, obj
, (struct MUIP_Draw
*)msg
);
466 result
= Get(cl
, obj
, (struct opGet
*)msg
);
470 Set(cl
, obj
, (struct opSet
*)msg
);
471 result
= DoSuperMethodA(cl
, obj
, msg
);
474 case MUIM_HandleEvent
:
475 result
= HandleEvent(cl
, obj
, (struct MUIP_HandleEvent
*)msg
);
479 result
= GoActive(cl
, obj
, msg
);
482 case MUIM_GoInactive
:
483 result
= GoInactive(cl
, obj
, msg
);
487 result
= Hide(cl
, obj
, msg
);
491 result
= Cleanup(cl
, obj
, msg
);
495 result
= Dispose(cl
, obj
, msg
);
499 result
= Export(cl
, obj
, (struct MUIP_Export
*)msg
);
503 result
= Import(cl
, obj
, (struct MUIP_Import
*)msg
);
506 case MUIM_BetterString_ClearSelected
:
508 // forward the clear request to our new DoAction method
509 // which in fact will do the very same, but a bit more clever
510 DoMethod(obj
, MUIM_BetterString_DoAction
, MUIV_BetterString_DoAction_Delete
);
514 case MUIM_BetterString_Insert
:
516 struct InstData
*data
= (struct InstData
*)INST_DATA(cl
, obj
);
517 struct MUIP_BetterString_Insert
*ins_msg
= (struct MUIP_BetterString_Insert
*)msg
;
522 /* case MUIV_BetterString_Insert_StartOfString:
526 case MUIV_BetterString_Insert_EndOfString
:
527 pos
= strlen(data
->Contents
);
530 case MUIV_BetterString_Insert_BufferPos
:
531 pos
= data
->BufferPos
;
538 Overwrite(ins_msg
->text
, pos
, 0, data
);
539 clearFlag(data
->Flags
, FLG_BlockEnabled
);
540 MUI_Redraw(obj
, MADF_DRAWUPDATE
);
544 case MUIM_BetterString_DoAction
:
545 result
= mDoAction(cl
, obj
, (struct MUIP_BetterString_DoAction
*)msg
);
552 struct MUIP_Backfill *fill_msg = (struct MUIP_Backfill *)msg;
554 if(isFlagClear(data->Flags, FLG_Active))
555 DoMethod(obj, MUIM_DrawBackground, fill_msg->left, fill_msg->top, fill_msg->right-fill_msg->left+1, fill_msg->bottom-fill_msg->top+1, fill_msg->xoffset, fill_msg->yoffset);
556 // printf("%ld, %ld, %ld, %ld\n%ld, %ld\n", fill_msg->left, fill_msg->top, fill_msg->right, fill_msg->bottom, fill_msg->xoffset, fill_msg->yoffset);
559 case MUIM_BetterString_FileNameStart
:
560 result
= FileNameStart((struct MUIP_BetterString_FileNameStart
*)msg
);
564 result
= DoSuperMethodA(cl
, obj
, msg
);