forcing device into host mode requires a full config - which we will do in opendevice...
[AROS.git] / rom / intuition / strgclass.c
blobbe43cb7f59a235e12f5df01e757a085dd144e4a8
1 /*
2 Copyright © 1995-2011, 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 #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)
34 char buf[64];
35 char *ptr = buf + sizeof(buf);
36 LONG value = StrInfo->LongInt;
37 int len;
39 if (value < 0)
40 value = -value;
44 *--ptr = '0' + value % 10;
45 value /= 10;
47 while (value != 0);
49 if (StrInfo->LongInt < 0)
50 *--ptr = '-';
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);
61 /*****************
62 ** StrG::Set() **
63 *****************/
64 #define SETFLAG(flagvar, boolvar, flag) \
65 if (boolvar) \
66 flagvar |= flag; \
67 else \
68 flagvar &= ~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;
82 BOOL notify = FALSE;
84 switch (tag->ti_Tag)
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;
99 retval = 1UL;
100 notify = TRUE;
102 break;
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;
111 retval = 1UL;
112 notify = TRUE;
114 break;
116 case STRINGA_MaxChars: /* [I] */
117 data->StrInfo.MaxChars = (WORD)tidata;
118 break;
120 case STRINGA_Buffer: /* [I] */
121 data->StrInfo.Buffer = (STRPTR)tidata;
122 break;
124 case STRINGA_UndoBuffer: /* [I] */
125 data->StrInfo.UndoBuffer = (STRPTR)tidata;
126 break;
128 case STRINGA_WorkBuffer: /* [I] */
129 data->StrExtend.WorkBuffer = (STRPTR)tidata;
130 break;
132 case STRINGA_BufferPos: /* [ISU] */
133 data->StrInfo.BufferPos = (WORD)tidata;
134 retval = 1UL;
135 break;
137 case STRINGA_DispPos: /* [ISU] */
138 data->StrInfo.DispPos = (WORD)tidata;
139 retval = 1UL;
140 break;
142 case STRINGA_AltKeyMap: /* [IS] */
143 data->StrInfo.AltKeyMap = (struct KeyMap *)tidata;
144 break;
146 case STRINGA_Font: /* [IS] */
147 data->StrExtend.Font = (struct TextFont *)tidata;
148 retval = 1UL;
149 break;
151 case STRINGA_Pens: /* [IS] */
152 data->StrExtend.Pens[0] = ((LONG)tidata) & 0x0000FFFF;
153 data->StrExtend.Pens[1] = (((LONG)tidata) & 0xFFFF0000) >> 16;
154 retval = 1UL;
155 break;
157 case STRINGA_ActivePens: /* [IS] */
158 data->StrExtend.ActivePens[0] = ((LONG)tidata) & 0x0000FFFF;
159 data->StrExtend.ActivePens[1] = (((LONG)tidata) & 0xFFFF0000) >> 16;
160 retval = 1UL;
161 break;
163 case STRINGA_EditHook: /* [I] */
164 data->StrExtend.EditHook = (struct Hook *)tidata;
165 break;
167 case STRINGA_EditModes: /* [IS] */
168 data->StrExtend.InitialModes = (ULONG)tidata;
169 break;
171 case STRINGA_ReplaceMode: /* [IS] */
172 SETFLAG(data->StrExtend.InitialModes, (ULONG)tidata, SGM_REPLACE);
173 break;
175 case STRINGA_FixedFieldMode: /* [IS] */
176 SETFLAG(data->StrExtend.InitialModes, (ULONG)tidata, SGM_FIXEDFIELD);
177 break;
179 case STRINGA_NoFilterMode: /* [IS] */
180 SETFLAG(data->StrExtend.InitialModes, (ULONG)tidata, SGM_NOFILTER);
181 break;
183 case STRINGA_Justification: /* [IS] */
184 g->Activation |= (UWORD)tidata;
185 retval = 1UL;
186 break;
188 case STRINGA_ExitHelp:
189 SETFLAG(data->StrExtend.InitialModes, (ULONG)tidata, SGM_EXITHELP);
190 break;
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[] =
200 { 0UL , 0UL },
201 { GA_ID , g->GadgetID },
202 { TAG_END }
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);
213 #endif
214 } /* if (the currently parsed attr supports notification) */
215 } /* for (each tag in taglist) */
217 return (retval);
218 } /* strg_set() */
220 /******************
221 ** StrG::Get() **
222 ******************/
224 IPTR StrGClass__OM_GET(Class *cl, struct Gadget * g, struct opGet *msg)
226 struct StrGData *data = INST_DATA(cl, g);
227 IPTR retval = 1UL;
229 switch (msg->opg_AttrID)
231 case STRINGA_LongVal: /* [ISGNU] */
232 if (g->Activation & GACT_LONGINT)
233 *(msg->opg_Storage) = (IPTR)data->StrInfo.LongInt;
234 else
235 *(msg->opg_Storage) = 0UL;
236 break;
238 case STRINGA_TextVal: /* [ISGNU] */
239 if (!(g->Activation & GACT_LONGINT))
240 *(msg->opg_Storage) = (IPTR)data->StrInfo.Buffer;
241 else
242 *(msg->opg_Storage) = 0UL;
243 break;
245 default:
246 retval = DoSuperMethodA(cl, (Object *)g, (Msg)msg);
247 break;
249 return (retval);
252 /******************
253 ** StrG::New() **
254 ******************/
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);
261 if (g)
263 struct TagItem *ti;
264 struct StrGData *data = INST_DATA(cl, g);
265 STRPTR textval;
266 WORD maxchars;
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)
286 goto failure;
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)
295 goto failure;
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)
304 goto failure;
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);
311 if (textval)
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);
319 if (ti != NULL)
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);
335 return (IPTR)g;
337 failure:
339 STACKULONG method = OM_DISPOSE;
340 CoerceMethodA(cl, (Object *)g, (Msg)&method);
342 return (IPTR)NULL;
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 /*********************
365 ** Strg::Render() **
366 *********************/
367 IPTR StrGClass__GM_RENDER(Class *cl, struct Gadget *g, struct gpRender *msg)
369 struct IntuitionBase *IntuitionBase = (struct IntuitionBase *)cl->cl_UserData;
370 UpdateStrGadget(g,
371 msg->gpr_GInfo->gi_Window,
372 msg->gpr_GInfo->gi_Requester,
373 IntuitionBase);
375 return (IPTR)0;
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;
385 IPTR ret;
386 IPTR retval = GMR_MEACTIVE;
387 UWORD imsgcode;
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",
399 ie->ie_X,
400 ie->ie_Y,
401 msg->gpi_Mouse.X,
402 msg->gpi_Mouse.Y,
403 container.Left,
404 container.Top,
405 container.Left + container.Width - 1,
406 container.Top + container.Height - 1,
407 container.Width,
408 container.Height));
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))
417 retval = GMR_REUSE;
420 else if (ie->ie_Code == MENUDOWN)
422 retval = GMR_REUSE;
424 /* Just to prevent a whole lot of MOUSE_MOVE messages being passed */
425 else if (ie->ie_Code == IECODE_NOBUTTON)
427 return (retval);
432 if (retval == GMR_MEACTIVE)
435 ret = HandleStrInput(g
436 ,msg->gpi_GInfo
438 ,&imsgcode
439 ,IntuitionBase
443 if (ret & (SGA_END|SGA_PREVACTIVE|SGA_NEXTACTIVE))
445 if (ret & SGA_REUSE)
446 retval = GMR_REUSE;
447 else
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;
458 else
460 retval = GMR_MEACTIVE;
462 } /* if (retval hasn't allreay been set) */
464 return (retval);
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;
473 struct RastPort *rp;
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);
482 if (rp)
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);
492 ReleaseGIRPort(rp);
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;
502 else
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;
515 nmsg.opu_Flags = 0;
517 DoSuperMethodA(cl, (Object *)g, (Msg)&nmsg);
519 return (IPTR)0;
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;
528 if (msg->gpi_IEvent)
530 UWORD imsgcode;
532 HandleStrInput(g, msg->gpi_GInfo,
533 msg->gpi_IEvent, &imsgcode, IntuitionBase
537 else
539 struct StrGData *data = INST_DATA(cl, g);
540 struct RastPort *rp;
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);
560 ReleaseGIRPort(rp);
563 return (IPTR)GMR_MEACTIVE;
566 /******************
567 ** Strg::Set() **
568 ******************/
569 IPTR StrGClass__OM_SET(Class *cl, struct Gadget *g, struct opSet *msg)
571 struct IntuitionBase *IntuitionBase = (struct IntuitionBase *)cl->cl_UserData;
572 IPTR retval;
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;
586 if (gi)
588 struct RastPort *rp = ObtainGIRPort(gi);
590 if (rp)
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);
601 ReleaseGIRPort(rp);
602 } /* if */
603 } /* if */
604 } /* if */
606 return retval;