2 Copyright © 1995-2014, 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;
276 data
->StrExtend
.Pens
[0] = data
->StrExtend
.ActivePens
[0] = 1;
278 strg_set(cl
, g
, msg
);
280 /* If no buffers have been supplied, then allocate them */
281 maxchars
= data
->StrInfo
.MaxChars
;
283 if (!data
->StrInfo
.Buffer
)
285 data
->StrInfo
.Buffer
= (STRPTR
)AllocVec(maxchars
, MEMF_ANY
);
286 if (!data
->StrInfo
.Buffer
)
288 data
->StrInfo
.Buffer
[0] = '\0';
289 data
->Flags
|= SFLG_BUFFER_ALLOCATED
;
292 if (!data
->StrInfo
.UndoBuffer
)
294 data
->StrInfo
.UndoBuffer
= (STRPTR
)AllocVec(maxchars
, MEMF_ANY
);
295 if (!data
->StrInfo
.UndoBuffer
)
297 data
->StrInfo
.UndoBuffer
[0] = '\0';
298 data
->Flags
|= SFLG_UNDOBUF_ALLOCATED
;
301 if (!data
->StrExtend
.WorkBuffer
)
303 data
->StrExtend
.WorkBuffer
= (STRPTR
)AllocVec(maxchars
, MEMF_ANY
);
304 if (!data
->StrExtend
.WorkBuffer
)
306 data
->StrExtend
.WorkBuffer
[0] = '\0';
307 data
->Flags
|= SFLG_WORKBUF_ALLOCATED
;
310 /* Get inital string contents */
311 textval
= (STRPTR
)GetTagData(STRINGA_TextVal
, 0, msg
->ops_AttrList
);
314 strcpy(data
->StrInfo
.Buffer
, textval
);
315 D(bug("strgclass:Initializing string gadget to text value %s\n", textval
));
316 g
->Activation
&= ~GACT_LONGINT
;
319 ti
= FindTagItem(STRINGA_LongVal
, msg
->ops_AttrList
);
322 LONG val
= (LONG
)ti
->ti_Data
;
324 data
->StrInfo
.LongInt
= val
;
325 set_buffer_str(&data
->StrInfo
);
326 //snprintf(data->StrInfo.Buffer, data->StrInfo.MaxChars, "%d", val);
328 D(bug("strgclass:Initializing string gadget to integer value %d\n", val
));
329 g
->Activation
|= GACT_LONGINT
;
332 g
->SpecialInfo
= &(data
->StrInfo
);
333 g
->Flags
|= GFLG_STRINGEXTEND
;
334 data
->StrInfo
.Extension
= &(data
->StrExtend
);
340 STACKULONG method
= OM_DISPOSE
;
341 CoerceMethodA(cl
, (Object
*)g
, (Msg
)&method
);
346 /**********************
347 ** StrG::Dispose() **
348 **********************/
349 IPTR
StrGClass__OM_DISPOSE(Class
*cl
, Object
*o
, Msg msg
)
351 struct StrGData
*data
= INST_DATA(cl
, o
);
353 if ((data
->StrInfo
.Buffer
) && (data
->Flags
& SFLG_BUFFER_ALLOCATED
))
354 FreeVec(data
->StrInfo
.Buffer
);
356 if ((data
->StrInfo
.UndoBuffer
) && (data
->Flags
& SFLG_UNDOBUF_ALLOCATED
))
357 FreeVec(data
->StrInfo
.UndoBuffer
);
359 if ((data
->StrExtend
.WorkBuffer
) && (data
->Flags
& SFLG_WORKBUF_ALLOCATED
))
360 FreeVec(data
->StrExtend
.WorkBuffer
);
362 return DoSuperMethodA(cl
, o
, msg
);
365 /*********************
367 *********************/
368 IPTR
StrGClass__GM_RENDER(Class
*cl
, struct Gadget
*g
, struct gpRender
*msg
)
370 struct IntuitionBase
*IntuitionBase
= (struct IntuitionBase
*)cl
->cl_UserData
;
372 msg
->gpr_GInfo
->gi_Window
,
373 msg
->gpr_GInfo
->gi_Requester
,
380 /**************************
381 ** StrG::HandleInput() **
382 **************************/
383 IPTR
StrGClass__GM_HANDLEINPUT(Class
*cl
, struct Gadget
*g
, struct gpInput
*msg
)
385 struct IntuitionBase
*IntuitionBase
= (struct IntuitionBase
*)cl
->cl_UserData
;
387 IPTR retval
= GMR_MEACTIVE
;
389 struct InputEvent
*ie
= msg
->gpi_IEvent
;
391 if (ie
->ie_Class
== IECLASS_RAWMOUSE
)
393 if (ie
->ie_Code
== SELECTDOWN
)
395 struct IBox container
;
397 GetGadgetIBox(g
, msg
->gpi_GInfo
, &container
);
399 D(bug("*** click: mouse = %d,%d (%d %d) box = %d,%d - %d %d (%d x %d)\n ***\n",
406 container
.Left
+ container
.Width
- 1,
407 container
.Top
+ container
.Height
- 1,
411 /* Click outside gadget ? */
412 if ( (msg
->gpi_Mouse
.X
>= container
.Width
)
413 || (msg
->gpi_Mouse
.X
< 0)
414 || (msg
->gpi_Mouse
.Y
>= container
.Height
)
415 || (msg
->gpi_Mouse
.Y
< 0))
421 else if (ie
->ie_Code
== MENUDOWN
)
425 /* Just to prevent a whole lot of MOUSE_MOVE messages being passed */
426 else if (ie
->ie_Code
== IECODE_NOBUTTON
)
433 if (retval
== GMR_MEACTIVE
)
436 ret
= HandleStrInput(g
444 if (ret
& (SGA_END
|SGA_PREVACTIVE
|SGA_NEXTACTIVE
))
449 retval
= GMR_NOREUSE
;
451 if (ret
& SGA_PREVACTIVE
)
452 retval
|= GMR_PREVACTIVE
;
453 else if (ret
& SGA_NEXTACTIVE
)
454 retval
|= GMR_NEXTACTIVE
;
456 retval
|= GMR_VERIFY
;
457 *(msg
->gpi_Termination
) = (LONG
)imsgcode
;
461 retval
= GMR_MEACTIVE
;
463 } /* if (retval hasn't allreay been set) */
468 /*************************
469 ** Strg::GoInactive() **
470 *************************/
471 IPTR
StrGClass__GM_GOINACTIVE(Class
*cl
, struct Gadget
*g
, struct gpGoInactive
*msg
)
473 struct IntuitionBase
*IntuitionBase
= (struct IntuitionBase
*)cl
->cl_UserData
;
475 struct opUpdate nmsg
;
476 struct TagItem tags
[3];
477 struct StrGData
*data
= INST_DATA(cl
, g
);
479 g
->Flags
&= ~GFLG_SELECTED
;
481 /* Rerender gadget in inactive state */
482 rp
= ObtainGIRPort(msg
->gpgi_GInfo
);
485 struct gpRender method
;
487 method
.MethodID
= GM_RENDER
;
488 method
.gpr_GInfo
= msg
->gpgi_GInfo
;
489 method
.gpr_RPort
= rp
;
490 method
.gpr_Redraw
= GREDRAW_REDRAW
;
491 DoMethodA((Object
*)g
, (Msg
)&method
);
496 /* Notify evt. change of string gadget contents */
498 if (g
->Activation
& GACT_LONGINT
)
500 tags
[0].ti_Tag
= STRINGA_LongVal
;
501 tags
[0].ti_Data
= (IPTR
)data
->StrInfo
.LongInt
;
505 tags
[0].ti_Tag
= STRINGA_TextVal
;
506 tags
[0].ti_Data
= (IPTR
)data
->StrInfo
.Buffer
;
509 tags
[1].ti_Tag
= GA_ID
;
510 tags
[1].ti_Data
= g
->GadgetID
;
511 tags
[2].ti_Tag
= TAG_END
;
513 nmsg
.MethodID
= OM_NOTIFY
;
514 nmsg
.opu_AttrList
= tags
;
515 nmsg
.opu_GInfo
= msg
->gpgi_GInfo
;
518 DoSuperMethodA(cl
, (Object
*)g
, (Msg
)&nmsg
);
523 /***********************
524 ** Strg::GoActive() **
525 ***********************/
526 IPTR
StrGClass__GM_GOACTIVE(Class
*cl
, struct Gadget
*g
, struct gpInput
*msg
)
528 struct IntuitionBase
*IntuitionBase
= (struct IntuitionBase
*)cl
->cl_UserData
;
533 HandleStrInput(g
, msg
->gpi_GInfo
,
534 msg
->gpi_IEvent
, &imsgcode
, IntuitionBase
540 struct StrGData
*data
= INST_DATA(cl
, g
);
542 struct GadgetInfo
*gi
= msg
->gpi_GInfo
;
544 g
->Flags
|= GFLG_SELECTED
;
545 if (data
->StrInfo
.UndoBuffer
)
547 strcpy(data
->StrInfo
.UndoBuffer
, data
->StrInfo
.Buffer
);
550 if ((rp
= ObtainGIRPort(gi
)))
552 struct gpRender method
;
554 method
.MethodID
= GM_RENDER
;
555 method
.gpr_GInfo
= gi
;
556 method
.gpr_RPort
= rp
;
557 method
.gpr_Redraw
= GREDRAW_REDRAW
;
559 DoMethodA((Object
*)g
, (Msg
)&method
);
564 return (IPTR
)GMR_MEACTIVE
;
570 IPTR
StrGClass__OM_SET(Class
*cl
, struct Gadget
*g
, struct opSet
*msg
)
572 struct IntuitionBase
*IntuitionBase
= (struct IntuitionBase
*)cl
->cl_UserData
;
575 retval
= DoSuperMethodA(cl
, (Object
*)g
, (Msg
)msg
);
576 retval
+= (IPTR
)strg_set(cl
, g
, msg
);
578 /* If we have been subclassed, OM_UPDATE should not cause a GM_RENDER
579 * because it would circumvent the subclass from fully overriding it.
580 * The check of cl == OCLASS(o) should fail if we have been
581 * subclassed, and we have gotten here via DoSuperMethodA().
583 if ( retval
&& ( (msg
->MethodID
!= OM_UPDATE
) || (cl
== OCLASS(g
)) ) )
585 struct GadgetInfo
*gi
= msg
->ops_GInfo
;
589 struct RastPort
*rp
= ObtainGIRPort(gi
);
593 struct gpRender method
;
595 method
.MethodID
= GM_RENDER
;
596 method
.gpr_GInfo
= gi
;
597 method
.gpr_RPort
= rp
;
598 method
.gpr_Redraw
= GREDRAW_REDRAW
;
600 DoMethodA((Object
*)g
, (Msg
)&method
);