2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
3 Copyright © 2001-2003, The MorphOS Development Team. All Rights Reserved.
7 #include <proto/graphics.h>
8 #include <proto/intuition.h>
9 #include <proto/utility.h>
10 #include <proto/exec.h>
11 #include <exec/memory.h>
12 #include <intuition/gadgetclass.h>
13 #include <intuition/imageclass.h>
14 #include <intuition/intuition.h>
15 #include <intuition/cghooks.h>
16 #include <intuition/sghooks.h>
17 #include <aros/asmcall.h>
21 #include "intuition_intern.h"
22 #include "strgadgets.h"
26 #include <aros/debug.h>
28 #define SFLG_BUFFER_ALLOCATED (1 << 2)
29 #define SFLG_WORKBUF_ALLOCATED (1 << 3)
30 #define SFLG_UNDOBUF_ALLOCATED (1 << 4)
32 static void set_buffer_str(struct StringInfo
*StrInfo
)
35 char *ptr
= buf
+ sizeof(buf
);
36 LONG value
= StrInfo
->LongInt
;
44 *--ptr
= '0' + value
% 10;
49 if (StrInfo
->LongInt
< 0)
52 len
= buf
+ sizeof(buf
) - ptr
;
54 if (len
>= StrInfo
->MaxChars
)
55 len
= StrInfo
->MaxChars
- 1;
57 StrInfo
->Buffer
[len
] = '\0';
58 memcpy(StrInfo
->Buffer
, ptr
, len
);
64 #define SETFLAG(flagvar, boolvar, flag) \
71 STATIC IPTR
strg_set(Class
*cl
, struct Gadget
* g
, struct opSet
*msg
)
73 struct IntuitionBase
*IntuitionBase
= (struct IntuitionBase
*)cl
->cl_UserData
;
74 struct Library
*UtilityBase
= GetPrivIBase(IntuitionBase
)->UtilityBase
;
75 struct TagItem
*tag
, *tstate
;
76 struct StrGData
*data
= INST_DATA(cl
, g
);
77 IPTR retval
= (IPTR
)0;
79 for (tstate
= msg
->ops_AttrList
; (tag
= NextTagItem(&tstate
)); )
81 IPTR tidata
= tag
->ti_Data
;
87 case STRINGA_LongVal
: /* [ISGNU] */
88 if (msg
->MethodID
!= OM_NEW
)
91 /* OM_NEW STRINGA_LongVal is handled in strg_new! */
93 data
->StrInfo
.LongInt
= (LONG
)tidata
;
95 set_buffer_str(&data
->StrInfo
);
96 //snprintf(data->StrInfo.Buffer, data->StrInfo.MaxChars, "%d", data->StrInfo.LongInt);
98 g
->Activation
|= GACT_LONGINT
;
104 case STRINGA_TextVal
: /* [ISGNU] */
105 if (msg
->MethodID
!= OM_NEW
)
107 /* OM_NEW STRINGA_TextVal is handled in strg_new! */
109 strcpy(data
->StrInfo
.Buffer
, (STRPTR
)tidata
? (STRPTR
)tidata
: (STRPTR
)"");
110 g
->Activation
&= ~GACT_LONGINT
;
116 case STRINGA_MaxChars
: /* [I] */
117 data
->StrInfo
.MaxChars
= (WORD
)tidata
;
120 case STRINGA_Buffer
: /* [I] */
121 data
->StrInfo
.Buffer
= (STRPTR
)tidata
;
124 case STRINGA_UndoBuffer
: /* [I] */
125 data
->StrInfo
.UndoBuffer
= (STRPTR
)tidata
;
128 case STRINGA_WorkBuffer
: /* [I] */
129 data
->StrExtend
.WorkBuffer
= (STRPTR
)tidata
;
132 case STRINGA_BufferPos
: /* [ISU] */
133 data
->StrInfo
.BufferPos
= (WORD
)tidata
;
137 case STRINGA_DispPos
: /* [ISU] */
138 data
->StrInfo
.DispPos
= (WORD
)tidata
;
142 case STRINGA_AltKeyMap
: /* [IS] */
143 data
->StrInfo
.AltKeyMap
= (struct KeyMap
*)tidata
;
146 case STRINGA_Font
: /* [IS] */
147 data
->StrExtend
.Font
= (struct TextFont
*)tidata
;
151 case STRINGA_Pens
: /* [IS] */
152 data
->StrExtend
.Pens
[0] = ((LONG
)tidata
) & 0x0000FFFF;
153 data
->StrExtend
.Pens
[1] = (((LONG
)tidata
) & 0xFFFF0000) >> 16;
157 case STRINGA_ActivePens
: /* [IS] */
158 data
->StrExtend
.ActivePens
[0] = ((LONG
)tidata
) & 0x0000FFFF;
159 data
->StrExtend
.ActivePens
[1] = (((LONG
)tidata
) & 0xFFFF0000) >> 16;
163 case STRINGA_EditHook
: /* [I] */
164 data
->StrExtend
.EditHook
= (struct Hook
*)tidata
;
167 case STRINGA_EditModes
: /* [IS] */
168 data
->StrExtend
.InitialModes
= (ULONG
)tidata
;
171 case STRINGA_ReplaceMode
: /* [IS] */
172 SETFLAG(data
->StrExtend
.InitialModes
, (ULONG
)tidata
, SGM_REPLACE
);
175 case STRINGA_FixedFieldMode
: /* [IS] */
176 SETFLAG(data
->StrExtend
.InitialModes
, (ULONG
)tidata
, SGM_FIXEDFIELD
);
179 case STRINGA_NoFilterMode
: /* [IS] */
180 SETFLAG(data
->StrExtend
.InitialModes
, (ULONG
)tidata
, SGM_NOFILTER
);
183 case STRINGA_Justification
: /* [IS] */
184 g
->Activation
|= (UWORD
)tidata
;
188 case STRINGA_ExitHelp
:
189 SETFLAG(data
->StrExtend
.InitialModes
, (ULONG
)tidata
, SGM_EXITHELP
);
193 } /* switch (currently parsed tag) */
195 if (notify
&& (msg
->MethodID
!= OM_NEW
))
197 #if 0 /* FIXME: Why don't we support notification? */
198 struct TagItem notify_tags
[] =
201 { GA_ID
, g
->GadgetID
},
204 struct opUpdate nmsg
=
206 OM_NOTIFY
, notify_tags
, msg
->ops_GInfo
, 0
208 notify_tags
[0].ti_Tag
= tag
->ti_Tag
;
209 notify_tags
[0].ti_Data
= tidata
;
211 DoSuperMethodA(cl
, (Object
*)g
, (Msg
)&nmsg
);
214 } /* if (the currently parsed attr supports notification) */
215 } /* for (each tag in taglist) */
224 IPTR
StrGClass__OM_GET(Class
*cl
, struct Gadget
* g
, struct opGet
*msg
)
226 struct StrGData
*data
= INST_DATA(cl
, g
);
229 switch (msg
->opg_AttrID
)
231 case STRINGA_LongVal
: /* [ISGNU] */
232 if (g
->Activation
& GACT_LONGINT
)
233 *(msg
->opg_Storage
) = (IPTR
)data
->StrInfo
.LongInt
;
235 *(msg
->opg_Storage
) = 0UL;
238 case STRINGA_TextVal
: /* [ISGNU] */
239 if (!(g
->Activation
& GACT_LONGINT
))
240 *(msg
->opg_Storage
) = (IPTR
)data
->StrInfo
.Buffer
;
242 *(msg
->opg_Storage
) = 0UL;
246 retval
= DoSuperMethodA(cl
, (Object
*)g
, (Msg
)msg
);
256 IPTR
StrGClass__OM_NEW(Class
*cl
, Object
* o
, struct opSet
*msg
)
258 struct IntuitionBase
*IntuitionBase
= (struct IntuitionBase
*)cl
->cl_UserData
;
259 struct Library
*UtilityBase
= GetPrivIBase(IntuitionBase
)->UtilityBase
;
260 struct Gadget
*g
= (struct Gadget
*)DoSuperMethodA(cl
, o
, (Msg
)msg
);
264 struct StrGData
*data
= INST_DATA(cl
, g
);
270 The instance object is cleared memory!
271 memset(data, 0, sizeof (struct StrGData));
274 /* Set some defaults */
275 data
->StrInfo
.MaxChars
= 80;
277 strg_set(cl
, g
, msg
);
279 /* If no buffers have been supplied, then allocate them */
280 maxchars
= data
->StrInfo
.MaxChars
;
282 if (!data
->StrInfo
.Buffer
)
284 data
->StrInfo
.Buffer
= (STRPTR
)AllocVec(maxchars
, MEMF_ANY
);
285 if (!data
->StrInfo
.Buffer
)
287 data
->StrInfo
.Buffer
[0] = '\0';
288 data
->Flags
|= SFLG_BUFFER_ALLOCATED
;
291 if (!data
->StrInfo
.UndoBuffer
)
293 data
->StrInfo
.UndoBuffer
= (STRPTR
)AllocVec(maxchars
, MEMF_ANY
);
294 if (!data
->StrInfo
.UndoBuffer
)
296 data
->StrInfo
.UndoBuffer
[0] = '\0';
297 data
->Flags
|= SFLG_UNDOBUF_ALLOCATED
;
300 if (!data
->StrExtend
.WorkBuffer
)
302 data
->StrExtend
.WorkBuffer
= (STRPTR
)AllocVec(maxchars
, MEMF_ANY
);
303 if (!data
->StrExtend
.WorkBuffer
)
305 data
->StrExtend
.WorkBuffer
[0] = '\0';
306 data
->Flags
|= SFLG_WORKBUF_ALLOCATED
;
309 /* Get inital string contents */
310 textval
= (STRPTR
)GetTagData(STRINGA_TextVal
, 0, msg
->ops_AttrList
);
313 strcpy(data
->StrInfo
.Buffer
, textval
);
314 D(bug("strgclass:Initializing string gadget to text value %s\n", textval
));
315 g
->Activation
&= ~GACT_LONGINT
;
318 ti
= FindTagItem(STRINGA_LongVal
, msg
->ops_AttrList
);
321 LONG val
= (LONG
)ti
->ti_Data
;
323 data
->StrInfo
.LongInt
= val
;
324 set_buffer_str(&data
->StrInfo
);
325 //snprintf(data->StrInfo.Buffer, data->StrInfo.MaxChars, "%d", val);
327 D(bug("strgclass:Initializing string gadget to integer value %d\n", val
));
328 g
->Activation
|= GACT_LONGINT
;
331 g
->SpecialInfo
= &(data
->StrInfo
);
332 g
->Flags
|= GFLG_STRINGEXTEND
;
333 data
->StrInfo
.Extension
= &(data
->StrExtend
);
339 STACKULONG method
= OM_DISPOSE
;
340 CoerceMethodA(cl
, (Object
*)g
, (Msg
)&method
);
345 /**********************
346 ** StrG::Dispose() **
347 **********************/
348 IPTR
StrGClass__OM_DISPOSE(Class
*cl
, Object
*o
, Msg msg
)
350 struct StrGData
*data
= INST_DATA(cl
, o
);
352 if ((data
->StrInfo
.Buffer
) && (data
->Flags
& SFLG_BUFFER_ALLOCATED
))
353 FreeVec(data
->StrInfo
.Buffer
);
355 if ((data
->StrInfo
.UndoBuffer
) && (data
->Flags
& SFLG_UNDOBUF_ALLOCATED
))
356 FreeVec(data
->StrInfo
.UndoBuffer
);
358 if ((data
->StrExtend
.WorkBuffer
) && (data
->Flags
& SFLG_WORKBUF_ALLOCATED
))
359 FreeVec(data
->StrExtend
.WorkBuffer
);
361 return DoSuperMethodA(cl
, o
, msg
);
364 /*********************
366 *********************/
367 IPTR
StrGClass__GM_RENDER(Class
*cl
, struct Gadget
*g
, struct gpRender
*msg
)
369 struct IntuitionBase
*IntuitionBase
= (struct IntuitionBase
*)cl
->cl_UserData
;
371 msg
->gpr_GInfo
->gi_Window
,
372 msg
->gpr_GInfo
->gi_Requester
,
379 /**************************
380 ** StrG::HandleInput() **
381 **************************/
382 IPTR
StrGClass__GM_HANDLEINPUT(Class
*cl
, struct Gadget
*g
, struct gpInput
*msg
)
384 struct IntuitionBase
*IntuitionBase
= (struct IntuitionBase
*)cl
->cl_UserData
;
386 IPTR retval
= GMR_MEACTIVE
;
388 struct InputEvent
*ie
= msg
->gpi_IEvent
;
390 if (ie
->ie_Class
== IECLASS_RAWMOUSE
)
392 if (ie
->ie_Code
== SELECTDOWN
)
394 struct IBox container
;
396 GetGadgetIBox(g
, msg
->gpi_GInfo
, &container
);
398 D(bug("*** click: mouse = %d,%d (%d %d) box = %d,%d - %d %d (%d x %d)\n ***\n",
405 container
.Left
+ container
.Width
- 1,
406 container
.Top
+ container
.Height
- 1,
410 /* Click outside gadget ? */
411 if ( (msg
->gpi_Mouse
.X
>= container
.Width
)
412 || (msg
->gpi_Mouse
.X
< 0)
413 || (msg
->gpi_Mouse
.Y
>= container
.Height
)
414 || (msg
->gpi_Mouse
.Y
< 0))
420 else if (ie
->ie_Code
== MENUDOWN
)
424 /* Just to prevent a whole lot of MOUSE_MOVE messages being passed */
425 else if (ie
->ie_Code
== IECODE_NOBUTTON
)
432 if (retval
== GMR_MEACTIVE
)
435 ret
= HandleStrInput(g
443 if (ret
& (SGA_END
|SGA_PREVACTIVE
|SGA_NEXTACTIVE
))
448 retval
= GMR_NOREUSE
;
450 if (ret
& SGA_PREVACTIVE
)
451 retval
|= GMR_PREVACTIVE
;
452 else if (ret
& SGA_NEXTACTIVE
)
453 retval
|= GMR_NEXTACTIVE
;
455 retval
|= GMR_VERIFY
;
456 *(msg
->gpi_Termination
) = (LONG
)imsgcode
;
460 retval
= GMR_MEACTIVE
;
462 } /* if (retval hasn't allreay been set) */
467 /*************************
468 ** Strg::GoInactive() **
469 *************************/
470 IPTR
StrGClass__GM_GOINACTIVE(Class
*cl
, struct Gadget
*g
, struct gpGoInactive
*msg
)
472 struct IntuitionBase
*IntuitionBase
= (struct IntuitionBase
*)cl
->cl_UserData
;
474 struct opUpdate nmsg
;
475 struct TagItem tags
[3];
476 struct StrGData
*data
= INST_DATA(cl
, g
);
478 g
->Flags
&= ~GFLG_SELECTED
;
480 /* Rerender gadget in inactive state */
481 rp
= ObtainGIRPort(msg
->gpgi_GInfo
);
484 struct gpRender method
;
486 method
.MethodID
= GM_RENDER
;
487 method
.gpr_GInfo
= msg
->gpgi_GInfo
;
488 method
.gpr_RPort
= rp
;
489 method
.gpr_Redraw
= GREDRAW_REDRAW
;
490 DoMethodA((Object
*)g
, (Msg
)&method
);
495 /* Notify evt. change of string gadget contents */
497 if (g
->Activation
& GACT_LONGINT
)
499 tags
[0].ti_Tag
= STRINGA_LongVal
;
500 tags
[0].ti_Data
= (IPTR
)data
->StrInfo
.LongInt
;
504 tags
[0].ti_Tag
= STRINGA_TextVal
;
505 tags
[0].ti_Data
= (IPTR
)data
->StrInfo
.Buffer
;
508 tags
[1].ti_Tag
= GA_ID
;
509 tags
[1].ti_Data
= g
->GadgetID
;
510 tags
[2].ti_Tag
= TAG_END
;
512 nmsg
.MethodID
= OM_NOTIFY
;
513 nmsg
.opu_AttrList
= tags
;
514 nmsg
.opu_GInfo
= msg
->gpgi_GInfo
;
517 DoSuperMethodA(cl
, (Object
*)g
, (Msg
)&nmsg
);
522 /***********************
523 ** Strg::GoActive() **
524 ***********************/
525 IPTR
StrGClass__GM_GOACTIVE(Class
*cl
, struct Gadget
*g
, struct gpInput
*msg
)
527 struct IntuitionBase
*IntuitionBase
= (struct IntuitionBase
*)cl
->cl_UserData
;
532 HandleStrInput(g
, msg
->gpi_GInfo
,
533 msg
->gpi_IEvent
, &imsgcode
, IntuitionBase
539 struct StrGData
*data
= INST_DATA(cl
, g
);
541 struct GadgetInfo
*gi
= msg
->gpi_GInfo
;
543 g
->Flags
|= GFLG_SELECTED
;
544 if (data
->StrInfo
.UndoBuffer
)
546 strcpy(data
->StrInfo
.UndoBuffer
, data
->StrInfo
.Buffer
);
549 if ((rp
= ObtainGIRPort(gi
)))
551 struct gpRender method
;
553 method
.MethodID
= GM_RENDER
;
554 method
.gpr_GInfo
= gi
;
555 method
.gpr_RPort
= rp
;
556 method
.gpr_Redraw
= GREDRAW_REDRAW
;
558 DoMethodA((Object
*)g
, (Msg
)&method
);
563 return (IPTR
)GMR_MEACTIVE
;
569 IPTR
StrGClass__OM_SET(Class
*cl
, struct Gadget
*g
, struct opSet
*msg
)
571 struct IntuitionBase
*IntuitionBase
= (struct IntuitionBase
*)cl
->cl_UserData
;
574 retval
= DoSuperMethodA(cl
, (Object
*)g
, (Msg
)msg
);
575 retval
+= (IPTR
)strg_set(cl
, g
, msg
);
577 /* If we have been subclassed, OM_UPDATE should not cause a GM_RENDER
578 * because it would circumvent the subclass from fully overriding it.
579 * The check of cl == OCLASS(o) should fail if we have been
580 * subclassed, and we have gotten here via DoSuperMethodA().
582 if ( retval
&& ( (msg
->MethodID
!= OM_UPDATE
) || (cl
== OCLASS(g
)) ) )
584 struct GadgetInfo
*gi
= msg
->ops_GInfo
;
588 struct RastPort
*rp
= ObtainGIRPort(gi
);
592 struct gpRender method
;
594 method
.MethodID
= GM_RENDER
;
595 method
.gpr_GInfo
= gi
;
596 method
.gpr_RPort
= rp
;
597 method
.gpr_Redraw
= GREDRAW_REDRAW
;
599 DoMethodA((Object
*)g
, (Msg
)&method
);