2 Copyright © 1995-2005, 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>
29 #define IntuitionBase ((struct IntuitionBase *)(cl->cl_UserData))
31 #define SFLG_BUFFER_ALLOCATED (1 << 2)
32 #define SFLG_WORKBUF_ALLOCATED (1 << 3)
33 #define SFLG_UNDOBUF_ALLOCATED (1 << 4)
35 static void set_buffer_str(struct StringInfo
*StrInfo
)
38 char *ptr
= buf
+ sizeof(buf
);
39 LONG value
= StrInfo
->LongInt
;
47 *--ptr
= '0' + value
% 10;
52 if (StrInfo
->LongInt
< 0)
55 len
= buf
+ sizeof(buf
) - ptr
;
57 if (len
>= StrInfo
->MaxChars
)
58 len
= StrInfo
->MaxChars
- 1;
60 StrInfo
->Buffer
[len
] = '\0';
61 memcpy(StrInfo
->Buffer
, ptr
, len
);
67 #define SETFLAG(flagvar, boolvar, flag) \
74 STATIC IPTR
strg_set(Class
*cl
, struct Gadget
* g
, struct opSet
*msg
)
76 const struct TagItem
*tag
, *tstate
;
77 struct StrGData
*data
= INST_DATA(cl
, g
);
78 IPTR retval
= (IPTR
)0;
80 for (tstate
= msg
->ops_AttrList
; (tag
= NextTagItem(&tstate
)); )
82 IPTR tidata
= tag
->ti_Data
;
88 case STRINGA_LongVal
: /* [ISGNU] */
89 if (msg
->MethodID
!= OM_NEW
)
92 /* OM_NEW STRINGA_LongVal is handled in strg_new! */
94 data
->StrInfo
.LongInt
= (LONG
)tidata
;
96 set_buffer_str(&data
->StrInfo
);
97 //snprintf(data->StrInfo.Buffer, data->StrInfo.MaxChars, "%d", data->StrInfo.LongInt);
99 g
->Activation
|= GACT_LONGINT
;
105 case STRINGA_TextVal
: /* [ISGNU] */
106 if (msg
->MethodID
!= OM_NEW
)
108 /* OM_NEW STRINGA_TextVal is handled in strg_new! */
110 strcpy(data
->StrInfo
.Buffer
, (STRPTR
)tidata
? (STRPTR
)tidata
: (STRPTR
)"");
111 g
->Activation
&= ~GACT_LONGINT
;
117 case STRINGA_MaxChars
: /* [I] */
118 data
->StrInfo
.MaxChars
= (WORD
)tidata
;
121 case STRINGA_Buffer
: /* [I] */
122 data
->StrInfo
.Buffer
= (STRPTR
)tidata
;
125 case STRINGA_UndoBuffer
: /* [I] */
126 data
->StrInfo
.UndoBuffer
= (STRPTR
)tidata
;
129 case STRINGA_WorkBuffer
: /* [I] */
130 data
->StrExtend
.WorkBuffer
= (STRPTR
)tidata
;
133 case STRINGA_BufferPos
: /* [ISU] */
134 data
->StrInfo
.BufferPos
= (WORD
)tidata
;
138 case STRINGA_DispPos
: /* [ISU] */
139 data
->StrInfo
.DispPos
= (WORD
)tidata
;
143 case STRINGA_AltKeyMap
: /* [IS] */
144 data
->StrInfo
.AltKeyMap
= (struct KeyMap
*)tidata
;
147 case STRINGA_Font
: /* [IS] */
148 data
->StrExtend
.Font
= (struct TextFont
*)tidata
;
152 case STRINGA_Pens
: /* [IS] */
153 data
->StrExtend
.Pens
[0] = ((LONG
)tidata
) & 0x0000FFFF;
154 data
->StrExtend
.Pens
[1] = (((LONG
)tidata
) & 0xFFFF0000) >> 16;
158 case STRINGA_ActivePens
: /* [IS] */
159 data
->StrExtend
.ActivePens
[0] = ((LONG
)tidata
) & 0x0000FFFF;
160 data
->StrExtend
.ActivePens
[1] = (((LONG
)tidata
) & 0xFFFF0000) >> 16;
164 case STRINGA_EditHook
: /* [I] */
165 data
->StrExtend
.EditHook
= (struct Hook
*)tidata
;
168 case STRINGA_EditModes
: /* [IS] */
169 data
->StrExtend
.InitialModes
= (ULONG
)tidata
;
172 case STRINGA_ReplaceMode
: /* [IS] */
173 SETFLAG(data
->StrExtend
.InitialModes
, (ULONG
)tidata
, SGM_REPLACE
);
176 case STRINGA_FixedFieldMode
: /* [IS] */
177 SETFLAG(data
->StrExtend
.InitialModes
, (ULONG
)tidata
, SGM_FIXEDFIELD
);
180 case STRINGA_NoFilterMode
: /* [IS] */
181 SETFLAG(data
->StrExtend
.InitialModes
, (ULONG
)tidata
, SGM_NOFILTER
);
184 case STRINGA_Justification
: /* [IS] */
185 g
->Activation
|= (UWORD
)tidata
;
189 case STRINGA_ExitHelp
:
190 SETFLAG(data
->StrExtend
.InitialModes
, (ULONG
)tidata
, SGM_EXITHELP
);
194 } /* switch (currently parsed tag) */
197 if (notify
&& (msg
->MethodID
!= OM_NEW
))
199 struct TagItem notify_tags
[] =
202 { GA_ID
, g
->GadgetID
},
205 struct opUpdate nmsg
=
207 OM_NOTIFY
, notify_tags
, msg
->ops_GInfo
, 0
209 notify_tags
[0].ti_Tag
= tag
->ti_Tag
;
210 notify_tags
[0].ti_Data
= tidata
;
212 DoSuperMethodA(cl
, (Object
*)g
, (Msg
)&nmsg
);
214 } /* if (the currently parsed attr supports notification) */
216 } /* for (each tag in taglist) */
225 IPTR
StrGClass__OM_GET(Class
*cl
, struct Gadget
* g
, struct opGet
*msg
)
227 struct StrGData
*data
= INST_DATA(cl
, g
);
230 switch (msg
->opg_AttrID
)
232 case STRINGA_LongVal
: /* [ISGNU] */
233 if (g
->Activation
& GACT_LONGINT
)
234 *(msg
->opg_Storage
) = (IPTR
)data
->StrInfo
.LongInt
;
236 *(msg
->opg_Storage
) = 0UL;
239 case STRINGA_TextVal
: /* [ISGNU] */
240 if (!(g
->Activation
& GACT_LONGINT
))
241 *(msg
->opg_Storage
) = (IPTR
)data
->StrInfo
.Buffer
;
243 *(msg
->opg_Storage
) = 0UL;
247 retval
= DoSuperMethodA(cl
, (Object
*)g
, (Msg
)msg
);
257 IPTR
StrGClass__OM_NEW(Class
*cl
, Object
* o
, struct opSet
*msg
)
259 struct Gadget
*g
= (struct Gadget
*)DoSuperMethodA(cl
, o
, (Msg
)msg
);
263 struct StrGData
*data
= INST_DATA(cl
, g
);
269 The instance object is cleared memory!
270 memset(data, 0, sizeof (struct StrGData));
273 /* Set some defaults */
274 data
->StrInfo
.MaxChars
= 80;
276 strg_set(cl
, g
, msg
);
278 /* If no buffers have been supplied, then allocate them */
279 maxchars
= data
->StrInfo
.MaxChars
;
281 if (!data
->StrInfo
.Buffer
)
283 data
->StrInfo
.Buffer
= (STRPTR
)AllocVec(maxchars
, MEMF_ANY
);
284 if (!data
->StrInfo
.Buffer
)
286 data
->StrInfo
.Buffer
[0] = '\0';
287 data
->Flags
|= SFLG_BUFFER_ALLOCATED
;
290 if (!data
->StrInfo
.UndoBuffer
)
292 data
->StrInfo
.UndoBuffer
= (STRPTR
)AllocVec(maxchars
, MEMF_ANY
);
293 if (!data
->StrInfo
.UndoBuffer
)
295 data
->StrInfo
.UndoBuffer
[0] = '\0';
296 data
->Flags
|= SFLG_UNDOBUF_ALLOCATED
;
299 if (!data
->StrExtend
.WorkBuffer
)
301 data
->StrExtend
.WorkBuffer
= (STRPTR
)AllocVec(maxchars
, MEMF_ANY
);
302 if (!data
->StrExtend
.WorkBuffer
)
304 data
->StrExtend
.WorkBuffer
[0] = '\0';
305 data
->Flags
|= SFLG_WORKBUF_ALLOCATED
;
308 /* Get inital string contents */
309 textval
= (STRPTR
)GetTagData(STRINGA_TextVal
, 0, msg
->ops_AttrList
);
312 strcpy(data
->StrInfo
.Buffer
, textval
);
313 D(bug("strgclass:Initializing string gadget to text value %s\n", textval
));
314 g
->Activation
&= ~GACT_LONGINT
;
317 ti
= FindTagItem(STRINGA_LongVal
, msg
->ops_AttrList
);
320 LONG val
= (LONG
)ti
->ti_Data
;
322 data
->StrInfo
.LongInt
= val
;
323 set_buffer_str(&data
->StrInfo
);
324 //snprintf(data->StrInfo.Buffer, data->StrInfo.MaxChars, "%d", val);
326 D(bug("strgclass:Initializing string gadget to integer value %d\n", val
));
327 g
->Activation
|= GACT_LONGINT
;
330 g
->SpecialInfo
= &(data
->StrInfo
);
331 g
->Flags
|= GFLG_STRINGEXTEND
;
332 data
->StrInfo
.Extension
= &(data
->StrExtend
);
338 STACKULONG method
= OM_DISPOSE
;
339 CoerceMethodA(cl
, (Object
*)g
, (Msg
)&method
);
344 /**********************
345 ** StrG::Dispose() **
346 **********************/
347 IPTR
StrGClass__OM_DISPOSE(Class
*cl
, Object
*o
, Msg msg
)
349 struct StrGData
*data
= INST_DATA(cl
, o
);
351 if ((data
->StrInfo
.Buffer
) && (data
->Flags
& SFLG_BUFFER_ALLOCATED
))
352 FreeVec(data
->StrInfo
.Buffer
);
354 if ((data
->StrInfo
.UndoBuffer
) && (data
->Flags
& SFLG_UNDOBUF_ALLOCATED
))
355 FreeVec(data
->StrInfo
.UndoBuffer
);
357 if ((data
->StrExtend
.WorkBuffer
) && (data
->Flags
& SFLG_WORKBUF_ALLOCATED
))
358 FreeVec(data
->StrExtend
.WorkBuffer
);
360 return DoSuperMethodA(cl
, o
, msg
);
363 /*********************
365 *********************/
366 IPTR
StrGClass__GM_RENDER(Class
*cl
, struct Gadget
*g
, struct gpRender
*msg
)
369 msg
->gpr_GInfo
->gi_Window
,
370 msg
->gpr_GInfo
->gi_Requester
,
377 /**************************
378 ** StrG::HandleInput() **
379 **************************/
380 IPTR
StrGClass__GM_HANDLEINPUT(Class
*cl
, struct Gadget
*g
, struct gpInput
*msg
)
384 IPTR retval
= GMR_MEACTIVE
;
386 struct InputEvent
*ie
= msg
->gpi_IEvent
;
388 if (ie
->ie_Class
== IECLASS_RAWMOUSE
)
390 if (ie
->ie_Code
== SELECTDOWN
)
392 struct IBox container
;
394 GetGadgetIBox(g
, msg
->gpi_GInfo
, &container
);
396 D(bug("*** click: mouse = %d,%d (%d %d) box = %d,%d - %d %d (%d x %d)\n ***\n",
403 container
.Left
+ container
.Width
- 1,
404 container
.Top
+ container
.Height
- 1,
408 /* Click outside gadget ? */
409 if ( (msg
->gpi_Mouse
.X
>= container
.Width
)
410 || (msg
->gpi_Mouse
.X
< 0)
411 || (msg
->gpi_Mouse
.Y
>= container
.Height
)
412 || (msg
->gpi_Mouse
.Y
< 0))
418 else if (ie
->ie_Code
== MENUDOWN
)
422 /* Just to prevent a whole lot of MOUSE_MOVE messages being passed */
423 else if (ie
->ie_Code
== IECODE_NOBUTTON
)
430 if (retval
== GMR_MEACTIVE
)
433 ret
= HandleStrInput(g
441 if (ret
& (SGA_END
|SGA_PREVACTIVE
|SGA_NEXTACTIVE
))
446 retval
= GMR_NOREUSE
;
448 if (ret
& SGA_PREVACTIVE
)
449 retval
|= GMR_PREVACTIVE
;
450 else if (ret
& SGA_NEXTACTIVE
)
451 retval
|= GMR_NEXTACTIVE
;
453 retval
|= GMR_VERIFY
;
454 *(msg
->gpi_Termination
) = (LONG
)imsgcode
;
458 retval
= GMR_MEACTIVE
;
460 } /* if (retval hasn't allreay been set) */
465 /*************************
466 ** Strg::GoInactive() **
467 *************************/
468 IPTR
StrGClass__GM_GOINACTIVE(Class
*cl
, struct Gadget
*g
, struct gpGoInactive
*msg
)
471 struct opUpdate nmsg
;
472 struct TagItem tags
[3];
473 struct StrGData
*data
= INST_DATA(cl
, g
);
475 g
->Flags
&= ~GFLG_SELECTED
;
477 /* Rerender gadget in inactive state */
478 rp
= ObtainGIRPort(msg
->gpgi_GInfo
);
481 struct gpRender method
;
483 method
.MethodID
= GM_RENDER
;
484 method
.gpr_GInfo
= msg
->gpgi_GInfo
;
485 method
.gpr_RPort
= rp
;
486 method
.gpr_Redraw
= GREDRAW_REDRAW
;
487 DoMethodA((Object
*)g
, (Msg
)&method
);
492 /* Notify evt. change of string gadget contents */
494 if (g
->Activation
& GACT_LONGINT
)
496 tags
[0].ti_Tag
= STRINGA_LongVal
;
497 tags
[0].ti_Data
= (IPTR
)data
->StrInfo
.LongInt
;
501 tags
[0].ti_Tag
= STRINGA_TextVal
;
502 tags
[0].ti_Data
= (IPTR
)data
->StrInfo
.Buffer
;
505 tags
[1].ti_Tag
= GA_ID
;
506 tags
[1].ti_Data
= g
->GadgetID
;
507 tags
[2].ti_Tag
= TAG_END
;
509 nmsg
.MethodID
= OM_NOTIFY
;
510 nmsg
.opu_AttrList
= tags
;
511 nmsg
.opu_GInfo
= msg
->gpgi_GInfo
;
514 DoSuperMethodA(cl
, (Object
*)g
, (Msg
)&nmsg
);
519 /***********************
520 ** Strg::GoActive() **
521 ***********************/
522 IPTR
StrGClass__GM_GOACTIVE(Class
*cl
, struct Gadget
*g
, struct gpInput
*msg
)
528 HandleStrInput(g
, msg
->gpi_GInfo
,
529 msg
->gpi_IEvent
, &imsgcode
, IntuitionBase
535 struct StrGData
*data
= INST_DATA(cl
, g
);
537 struct GadgetInfo
*gi
= msg
->gpi_GInfo
;
539 g
->Flags
|= GFLG_SELECTED
;
540 if (data
->StrInfo
.UndoBuffer
)
542 strcpy(data
->StrInfo
.UndoBuffer
, data
->StrInfo
.Buffer
);
545 if ((rp
= ObtainGIRPort(gi
)))
547 struct gpRender method
;
549 method
.MethodID
= GM_RENDER
;
550 method
.gpr_GInfo
= gi
;
551 method
.gpr_RPort
= rp
;
552 method
.gpr_Redraw
= GREDRAW_REDRAW
;
554 DoMethodA((Object
*)g
, (Msg
)&method
);
559 return (IPTR
)GMR_MEACTIVE
;
565 IPTR
StrGClass__OM_SET(Class
*cl
, struct Gadget
*g
, struct opSet
*msg
)
569 retval
= DoSuperMethodA(cl
, (Object
*)g
, (Msg
)msg
);
570 retval
+= (IPTR
)strg_set(cl
, g
, msg
);
572 /* If we have been subclassed, OM_UPDATE should not cause a GM_RENDER
573 * because it would circumvent the subclass from fully overriding it.
574 * The check of cl == OCLASS(o) should fail if we have been
575 * subclassed, and we have gotten here via DoSuperMethodA().
577 if ( retval
&& ( (msg
->MethodID
!= OM_UPDATE
) || (cl
== OCLASS(g
)) ) )
579 struct GadgetInfo
*gi
= msg
->ops_GInfo
;
583 struct RastPort
*rp
= ObtainGIRPort(gi
);
587 struct gpRender method
;
589 method
.MethodID
= GM_RENDER
;
590 method
.gpr_GInfo
= gi
;
591 method
.gpr_RPort
= rp
;
592 method
.gpr_Redraw
= GREDRAW_REDRAW
;
594 DoMethodA((Object
*)g
, (Msg
)&method
);