1 /***************************************************************************
3 BetterString.mcc - A better String gadget MUI Custom Class
4 Copyright (C) 1997-2000 Allan Odgaard
5 Copyright (C) 2005-2013 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 ***************************************************************************/
26 #include <clib/alib_protos.h>
27 #include <proto/intuition.h>
28 #include <proto/muimaster.h>
29 #include <proto/utility.h>
30 #include <proto/dos.h>
35 IPTR
mGet(struct IClass
*cl
, Object
*obj
, struct opGet
*msg
)
37 struct InstData
*data
= (struct InstData
*)INST_DATA(cl
, obj
);
42 switch(msg
->opg_AttrID
)
44 case MUIA_ControlChar
:
45 ti_Data
= (IPTR
)data
->CtrlChar
;
48 case MUIA_String_AttachedList
:
49 ti_Data
= (IPTR
)data
->ForwardObject
;
52 case MUIA_String_BufferPos
:
53 ti_Data
= (IPTR
)data
->BufferPos
;
56 case MUIA_String_Acknowledge
:
57 case MUIA_String_Contents
:
58 ti_Data
= (IPTR
)data
->Contents
;
61 case MUIA_String_DisplayPos
:
62 ti_Data
= (IPTR
)data
->DisplayPos
;
65 case MUIA_String_Format
:
66 ti_Data
= (IPTR
)data
->Alignment
;
69 case MUIA_String_Integer
:
70 StrToLong(data
->Contents
, (LONG
*)&ti_Data
);
73 case MUIA_String_MaxLen
:
74 ti_Data
= (IPTR
)data
->MaxLength
;
77 case MUIA_String_Reject
:
78 ti_Data
= (IPTR
)data
->Reject
;
81 case MUIA_String_Secret
:
82 ti_Data
= isFlagSet(data
->Flags
, FLG_Secret
) ? TRUE
: FALSE
;
85 case MUIA_String_EditHook
:
86 ti_Data
= (IPTR
)data
->EditHook
;
89 case MUIA_String_AdvanceOnCR
:
90 ti_Data
= isFlagSet(data
->Flags
, FLG_AdvanceOnCr
) ? TRUE
: FALSE
;
93 case MUIA_BetterString_KeyUpFocus
:
94 ti_Data
= (IPTR
)data
->KeyUpFocus
;
97 case MUIA_BetterString_KeyDownFocus
:
98 ti_Data
= (IPTR
)data
->KeyDownFocus
;
101 case MUIA_BetterString_SelectSize
:
102 ti_Data
= isFlagSet(data
->Flags
, FLG_BlockEnabled
) ? data
->BlockStop
-data
->BlockStart
: 0;
105 case MUIA_BetterString_StayActive
:
106 ti_Data
= isFlagSet(data
->Flags
, FLG_StayActive
) ? TRUE
: FALSE
;
109 case MUIA_BetterString_NoInput
:
110 ti_Data
= isFlagSet(data
->Flags
, FLG_NoInput
) ? TRUE
: FALSE
;
113 case MUIA_BetterString_NoNotify
:
114 ti_Data
= isFlagSet(data
->Flags
, FLG_NoNotify
) ? TRUE
: FALSE
;
117 case MUIA_BetterString_InactiveContents
:
118 ti_Data
= (IPTR
)data
->InactiveContents
;
121 case MUIA_BetterString_NoShortcuts
:
122 ti_Data
= isFlagSet(data
->Flags
, FLG_NoShortcuts
) ? TRUE
: FALSE
;
125 case MUIA_BetterString_SelectOnActive
:
127 if((data
->SelectOnActive
== TRUE
&& isFlagClear(data
->Flags
, FLG_ForceSelectOff
)) ||
128 isFlagSet(data
->Flags
, FLG_ForceSelectOn
))
138 ti_Data
= LIB_VERSION
;
142 ti_Data
= LIB_REVISION
;
147 return DoSuperMethodA(cl
, obj
, (Msg
)msg
);
151 *msg
->opg_Storage
= ti_Data
;
157 IPTR
mSet(struct IClass
*cl
, Object
*obj
, struct opSet
*msg
)
159 struct InstData
*data
= (struct InstData
*)INST_DATA(cl
, obj
);
160 struct TagItem
*tags
, *tag
;
161 char IntegerString
[12];
166 const struct TagItem boolMap
[] =
168 { MUIA_Disabled
, FLG_Ghosted
},
169 { MUIA_String_AdvanceOnCR
, FLG_AdvanceOnCr
},
170 { MUIA_String_Secret
, FLG_Secret
},
171 { MUIA_BetterString_StayActive
, FLG_StayActive
},
172 { MUIA_BetterString_NoInput
, FLG_NoInput
},
173 { MUIA_BetterString_NoNotify
, FLG_NoNotify
},
174 { MUIA_BetterString_NoShortcuts
, FLG_NoShortcuts
},
180 tags
= msg
->ops_AttrList
;
181 // remember the old flags before calculating the new one
182 oldFlags
= data
->Flags
& (FLG_Ghosted
|FLG_Secret
);
183 data
->Flags
= PackBoolTags(data
->Flags
, tags
, (struct TagItem
*)boolMap
);
185 while((tag
= NextTagItem((APTR
)&tags
)) != NULL
)
187 IPTR ti_Data
= tag
->ti_Data
;
191 case MUIA_String_AttachedList
:
193 data
->ForwardObject
= (Object
*)ti_Data
;
197 case MUIA_String_Accept
:
199 data
->Accept
= (STRPTR
)ti_Data
;
203 case MUIA_String_BufferPos
:
205 data
->BufferPos
= (UWORD
)ti_Data
;
206 clearFlag(data
->Flags
, FLG_BlockEnabled
);
211 case MUIA_BetterString_Columns
:
213 data
->Width
= (UWORD
)ti_Data
;
217 case MUIA_String_Integer
:
219 tag
->ti_Tag
= TAG_IGNORE
;
221 // we are using snprintf() here not only to be on the safe
222 // side, but also because modern C runtime libraries should definitly
224 snprintf(IntegerString
, sizeof(IntegerString
), "%d", (int)ti_Data
);
225 ti_Data
= (IPTR
)IntegerString
;
227 // The missing break is intended!
229 case MUIA_String_Contents
:
231 STRPTR new_str
= (STRPTR
)ti_Data
;
232 BOOL circular
= FALSE
;
236 circular
= !strcmp(data
->Contents
, new_str
);
237 if(circular
== FALSE
&& data
->MaxLength
&& strlen(new_str
) > data
->MaxLength
)
238 circular
= !strncmp(data
->Contents
, new_str
, data
->MaxLength
);
241 if(circular
== FALSE
)
243 // we don't have a valid block anymore
244 clearFlag(data
->Flags
, FLG_BlockEnabled
);
248 LONG extra
= strlen(new_str
)-strlen(data
->Contents
);
252 ok
= ExpandContentString(&data
->Contents
, extra
);
258 strlcpy(data
->Contents
, new_str
, ContentStringSize(data
->Contents
));
259 data
->BufferPos
= strlen(data
->Contents
);
260 data
->DisplayPos
= 0;
261 if(data
->MaxLength
!= 0 && data
->BufferPos
>= data
->MaxLength
)
263 data
->Contents
[data
->MaxLength
-1] = '\0';
264 data
->BufferPos
= data
->MaxLength
-1;
267 // the start of a block cannot be behind the last character
268 if(data
->BlockStart
> strlen(data
->Contents
))
269 data
->BlockStart
= strlen(data
->Contents
);
273 E(DBF_ALWAYS
, "content expansion by %ld bytes failed", extra
);
278 data
->Contents
[0] = '\0';
279 data
->BlockStart
= 0;
282 data
->DisplayPos
= 0;
287 // if the no notify flag is set we set the queued
288 // flag and set the tag to IGNORE so that the superclass
289 // ignores it and thus does not trigger a notify.
290 if(isFlagSet(data
->Flags
, FLG_NoNotify
))
292 setFlag(data
->Flags
, FLG_NotifyQueued
);
293 tag
->ti_Tag
= TAG_IGNORE
;
297 tag
->ti_Tag
= TAG_IGNORE
; // set Tag to IGNORE so that superclass ignores it
301 case MUIA_ControlChar
:
303 data
->CtrlChar
= (UBYTE
)ti_Data
;
307 case MUIA_String_DisplayPos
:
309 data
->DisplayPos
= (UWORD
)ti_Data
;
314 case MUIA_String_Format
:
316 data
->Alignment
= (WORD
)ti_Data
;
321 case MUIA_String_MaxLen
:
323 data
->MaxLength
= (UWORD
)ti_Data
;
327 case MUIA_String_Reject
:
329 data
->Reject
= (STRPTR
)ti_Data
;
333 case MUIA_String_EditHook
:
335 data
->EditHook
= (struct Hook
*)ti_Data
;
339 case MUIA_String_Popup
:
341 data
->Popup
= (Object
*)ti_Data
;
345 case MUIA_BetterString_KeyUpFocus
:
347 data
->KeyUpFocus
= (Object
*)ti_Data
;
351 case MUIA_BetterString_KeyDownFocus
:
353 data
->KeyDownFocus
= (Object
*)ti_Data
;
357 case MUIA_BetterString_InactiveContents
:
359 data
->InactiveContents
= (STRPTR
)ti_Data
;
364 case MUIA_BetterString_SelectSize
:
366 data
->BlockStart
= data
->BufferPos
;
367 setFlag(data
->Flags
, FLG_BlockEnabled
);
369 data
->BlockStop
= data
->BufferPos
+ti_Data
;
371 if(data
->BlockStop
< 0)
374 if((ULONG
)data
->BlockStop
> strlen(data
->Contents
))
375 data
->BlockStop
= strlen(data
->Contents
);
381 case MUIA_BetterString_SelectOnActive
:
385 setFlag(data
->Flags
, FLG_ForceSelectOff
);
386 clearFlag(data
->Flags
, FLG_ForceSelectOn
);
388 RemWindowSleepNotify(cl
, obj
);
392 setFlag(data
->Flags
, FLG_ForceSelectOn
);
393 clearFlag(data
->Flags
, FLG_ForceSelectOff
);
394 // add notify for MUIA_Window_Sleep if "select on active" is enabled
395 AddWindowSleepNotify(cl
, obj
);
400 case MUIA_BetterString_InternalSelectOnActive
:
402 // this is the same as MUIA_BetterString_SelectOnActive, but without
403 // adding/removing the notify
406 setFlag(data
->Flags
, FLG_ForceSelectOff
);
407 clearFlag(data
->Flags
, FLG_ForceSelectOn
);
411 setFlag(data
->Flags
, FLG_ForceSelectOn
);
412 clearFlag(data
->Flags
, FLG_ForceSelectOff
);
417 case MUIA_BetterString_Nop
:
419 // as the name suggests, do nothing
423 case MUIA_BetterString_NoNotify
:
425 // trigger a notify only if a notification has been queued already
426 if(isFlagSet(data
->Flags
, FLG_NotifyQueued
))
428 TriggerNotify(cl
, obj
);
435 if(data
->BufferPos
> strlen(data
->Contents
))
437 data
->BufferPos
= strlen(data
->Contents
);
441 // check if some flags affecting the appearance have changed
442 newFlags
= data
->Flags
& (FLG_Ghosted
|FLG_Secret
);
443 if(oldFlags
!= newFlags
)
448 // redraw ourself only if something changed that affects the appearance
451 MUI_Redraw(obj
, MADF_DRAWOBJECT
);