define __KERNEL_STRICT_NAMES to avoid inclusion of kernel types on systems that carry...
[cake.git] / rom / intuition / strgclass.c
blob221a4697c280e5b9daecb778ef6c16a1ae672543
1 /*
2 Copyright © 1995-2005, The AROS Development Team. All rights reserved.
3 Copyright © 2001-2003, The MorphOS Development Team. All Rights Reserved.
4 $Id$
5 */
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>
18 #include <string.h>
19 #include <stdio.h>
21 #include "intuition_intern.h"
22 #include "strgadgets.h"
24 #undef DEBUG
25 #define DEBUG 0
26 #include <aros/debug.h>
28 #undef IntuitionBase
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)
37 char buf[64];
38 char *ptr = buf + sizeof(buf);
39 LONG value = StrInfo->LongInt;
40 int len;
42 if (value < 0)
43 value = -value;
47 *--ptr = '0' + value % 10;
48 value /= 10;
50 while (value != 0);
52 if (StrInfo->LongInt < 0)
53 *--ptr = '-';
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);
64 /*****************
65 ** StrG::Set() **
66 *****************/
67 #define SETFLAG(flagvar, boolvar, flag) \
68 if (boolvar) \
69 flagvar |= flag; \
70 else \
71 flagvar &= ~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;
83 BOOL notify = FALSE;
85 switch (tag->ti_Tag)
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;
100 retval = 1UL;
101 notify = TRUE;
103 break;
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;
112 retval = 1UL;
113 notify = TRUE;
115 break;
117 case STRINGA_MaxChars: /* [I] */
118 data->StrInfo.MaxChars = (WORD)tidata;
119 break;
121 case STRINGA_Buffer: /* [I] */
122 data->StrInfo.Buffer = (STRPTR)tidata;
123 break;
125 case STRINGA_UndoBuffer: /* [I] */
126 data->StrInfo.UndoBuffer = (STRPTR)tidata;
127 break;
129 case STRINGA_WorkBuffer: /* [I] */
130 data->StrExtend.WorkBuffer = (STRPTR)tidata;
131 break;
133 case STRINGA_BufferPos: /* [ISU] */
134 data->StrInfo.BufferPos = (WORD)tidata;
135 retval = 1UL;
136 break;
138 case STRINGA_DispPos: /* [ISU] */
139 data->StrInfo.DispPos = (WORD)tidata;
140 retval = 1UL;
141 break;
143 case STRINGA_AltKeyMap: /* [IS] */
144 data->StrInfo.AltKeyMap = (struct KeyMap *)tidata;
145 break;
147 case STRINGA_Font: /* [IS] */
148 data->StrExtend.Font = (struct TextFont *)tidata;
149 retval = 1UL;
150 break;
152 case STRINGA_Pens: /* [IS] */
153 data->StrExtend.Pens[0] = ((LONG)tidata) & 0x0000FFFF;
154 data->StrExtend.Pens[1] = (((LONG)tidata) & 0xFFFF0000) >> 16;
155 retval = 1UL;
156 break;
158 case STRINGA_ActivePens: /* [IS] */
159 data->StrExtend.ActivePens[0] = ((LONG)tidata) & 0x0000FFFF;
160 data->StrExtend.ActivePens[1] = (((LONG)tidata) & 0xFFFF0000) >> 16;
161 retval = 1UL;
162 break;
164 case STRINGA_EditHook: /* [I] */
165 data->StrExtend.EditHook = (struct Hook *)tidata;
166 break;
168 case STRINGA_EditModes: /* [IS] */
169 data->StrExtend.InitialModes = (ULONG)tidata;
170 break;
172 case STRINGA_ReplaceMode: /* [IS] */
173 SETFLAG(data->StrExtend.InitialModes, (ULONG)tidata, SGM_REPLACE);
174 break;
176 case STRINGA_FixedFieldMode: /* [IS] */
177 SETFLAG(data->StrExtend.InitialModes, (ULONG)tidata, SGM_FIXEDFIELD);
178 break;
180 case STRINGA_NoFilterMode: /* [IS] */
181 SETFLAG(data->StrExtend.InitialModes, (ULONG)tidata, SGM_NOFILTER);
182 break;
184 case STRINGA_Justification: /* [IS] */
185 g->Activation |= (UWORD)tidata;
186 retval = 1UL;
187 break;
189 case STRINGA_ExitHelp:
190 SETFLAG(data->StrExtend.InitialModes, (ULONG)tidata, SGM_EXITHELP);
191 break;
194 } /* switch (currently parsed tag) */
196 #if 0
197 if (notify && (msg->MethodID != OM_NEW))
199 struct TagItem notify_tags[] =
201 { 0UL , 0UL },
202 { GA_ID , g->GadgetID },
203 { TAG_END }
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) */
215 #endif
216 } /* for (each tag in taglist) */
218 return (retval);
219 } /* strg_set() */
221 /******************
222 ** StrG::Get() **
223 ******************/
225 IPTR StrGClass__OM_GET(Class *cl, struct Gadget * g, struct opGet *msg)
227 struct StrGData *data = INST_DATA(cl, g);
228 IPTR retval = 1UL;
230 switch (msg->opg_AttrID)
232 case STRINGA_LongVal: /* [ISGNU] */
233 if (g->Activation & GACT_LONGINT)
234 *(msg->opg_Storage) = (IPTR)data->StrInfo.LongInt;
235 else
236 *(msg->opg_Storage) = 0UL;
237 break;
239 case STRINGA_TextVal: /* [ISGNU] */
240 if (!(g->Activation & GACT_LONGINT))
241 *(msg->opg_Storage) = (IPTR)data->StrInfo.Buffer;
242 else
243 *(msg->opg_Storage) = 0UL;
244 break;
246 default:
247 retval = DoSuperMethodA(cl, (Object *)g, (Msg)msg);
248 break;
250 return (retval);
253 /******************
254 ** StrG::New() **
255 ******************/
257 IPTR StrGClass__OM_NEW(Class *cl, Object * o, struct opSet *msg)
259 struct Gadget *g = (struct Gadget *)DoSuperMethodA(cl, o, (Msg)msg);
260 if (g)
262 struct TagItem *ti;
263 struct StrGData *data = INST_DATA(cl, g);
264 STRPTR textval;
265 WORD maxchars;
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)
285 goto failure;
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)
294 goto failure;
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)
303 goto failure;
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);
310 if (textval)
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);
318 if (ti != NULL)
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);
334 return (IPTR)g;
336 failure:
338 STACKULONG method = OM_DISPOSE;
339 CoerceMethodA(cl, (Object *)g, (Msg)&method);
341 return (IPTR)NULL;
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 /*********************
364 ** Strg::Render() **
365 *********************/
366 IPTR StrGClass__GM_RENDER(Class *cl, struct Gadget *g, struct gpRender *msg)
368 UpdateStrGadget(g,
369 msg->gpr_GInfo->gi_Window,
370 msg->gpr_GInfo->gi_Requester,
371 IntuitionBase);
373 return (IPTR)0;
377 /**************************
378 ** StrG::HandleInput() **
379 **************************/
380 IPTR StrGClass__GM_HANDLEINPUT(Class *cl, struct Gadget *g, struct gpInput *msg)
383 IPTR ret;
384 IPTR retval = GMR_MEACTIVE;
385 UWORD imsgcode;
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",
397 ie->ie_X,
398 ie->ie_Y,
399 msg->gpi_Mouse.X,
400 msg->gpi_Mouse.Y,
401 container.Left,
402 container.Top,
403 container.Left + container.Width - 1,
404 container.Top + container.Height - 1,
405 container.Width,
406 container.Height));
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))
415 retval = GMR_REUSE;
418 else if (ie->ie_Code == MENUDOWN)
420 retval = GMR_REUSE;
422 /* Just to prevent a whole lot of MOUSE_MOVE messages being passed */
423 else if (ie->ie_Code == IECODE_NOBUTTON)
425 return (retval);
430 if (retval == GMR_MEACTIVE)
433 ret = HandleStrInput(g
434 ,msg->gpi_GInfo
436 ,&imsgcode
437 ,IntuitionBase
441 if (ret & (SGA_END|SGA_PREVACTIVE|SGA_NEXTACTIVE))
443 if (ret & SGA_REUSE)
444 retval = GMR_REUSE;
445 else
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;
456 else
458 retval = GMR_MEACTIVE;
460 } /* if (retval hasn't allreay been set) */
462 return (retval);
465 /*************************
466 ** Strg::GoInactive() **
467 *************************/
468 IPTR StrGClass__GM_GOINACTIVE(Class *cl, struct Gadget *g, struct gpGoInactive *msg)
470 struct RastPort *rp;
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);
479 if (rp)
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);
489 ReleaseGIRPort(rp);
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;
499 else
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;
512 nmsg.opu_Flags = 0;
514 DoSuperMethodA(cl, (Object *)g, (Msg)&nmsg);
516 return (IPTR)0;
519 /***********************
520 ** Strg::GoActive() **
521 ***********************/
522 IPTR StrGClass__GM_GOACTIVE(Class *cl, struct Gadget *g, struct gpInput *msg)
524 if (msg->gpi_IEvent)
526 UWORD imsgcode;
528 HandleStrInput(g, msg->gpi_GInfo,
529 msg->gpi_IEvent, &imsgcode, IntuitionBase
533 else
535 struct StrGData *data = INST_DATA(cl, g);
536 struct RastPort *rp;
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);
556 ReleaseGIRPort(rp);
559 return (IPTR)GMR_MEACTIVE;
562 /******************
563 ** Strg::Set() **
564 ******************/
565 IPTR StrGClass__OM_SET(Class *cl, struct Gadget *g, struct opSet *msg)
567 IPTR retval;
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;
581 if (gi)
583 struct RastPort *rp = ObtainGIRPort(gi);
585 if (rp)
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);
596 ReleaseGIRPort(rp);
597 } /* if */
598 } /* if */
599 } /* if */
601 return retval;