Check for SYS/GL during library init. Reason is that
[AROS.git] / rom / intuition / strgclass.c
blob8bfab4fd8409487dd27186f253d3bf444281948e
1 /*
2 Copyright © 1995-2014, 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;
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)
287 goto failure;
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)
296 goto failure;
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)
305 goto failure;
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);
312 if (textval)
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);
320 if (ti != NULL)
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);
336 return (IPTR)g;
338 failure:
340 STACKULONG method = OM_DISPOSE;
341 CoerceMethodA(cl, (Object *)g, (Msg)&method);
343 return (IPTR)NULL;
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 /*********************
366 ** Strg::Render() **
367 *********************/
368 IPTR StrGClass__GM_RENDER(Class *cl, struct Gadget *g, struct gpRender *msg)
370 struct IntuitionBase *IntuitionBase = (struct IntuitionBase *)cl->cl_UserData;
371 UpdateStrGadget(g,
372 msg->gpr_GInfo->gi_Window,
373 msg->gpr_GInfo->gi_Requester,
374 IntuitionBase);
376 return (IPTR)0;
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;
386 IPTR ret;
387 IPTR retval = GMR_MEACTIVE;
388 UWORD imsgcode;
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",
400 ie->ie_X,
401 ie->ie_Y,
402 msg->gpi_Mouse.X,
403 msg->gpi_Mouse.Y,
404 container.Left,
405 container.Top,
406 container.Left + container.Width - 1,
407 container.Top + container.Height - 1,
408 container.Width,
409 container.Height));
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))
418 retval = GMR_REUSE;
421 else if (ie->ie_Code == MENUDOWN)
423 retval = GMR_REUSE;
425 /* Just to prevent a whole lot of MOUSE_MOVE messages being passed */
426 else if (ie->ie_Code == IECODE_NOBUTTON)
428 return (retval);
433 if (retval == GMR_MEACTIVE)
436 ret = HandleStrInput(g
437 ,msg->gpi_GInfo
439 ,&imsgcode
440 ,IntuitionBase
444 if (ret & (SGA_END|SGA_PREVACTIVE|SGA_NEXTACTIVE))
446 if (ret & SGA_REUSE)
447 retval = GMR_REUSE;
448 else
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;
459 else
461 retval = GMR_MEACTIVE;
463 } /* if (retval hasn't allreay been set) */
465 return (retval);
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;
474 struct RastPort *rp;
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);
483 if (rp)
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);
493 ReleaseGIRPort(rp);
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;
503 else
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;
516 nmsg.opu_Flags = 0;
518 DoSuperMethodA(cl, (Object *)g, (Msg)&nmsg);
520 return (IPTR)0;
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;
529 if (msg->gpi_IEvent)
531 UWORD imsgcode;
533 HandleStrInput(g, msg->gpi_GInfo,
534 msg->gpi_IEvent, &imsgcode, IntuitionBase
538 else
540 struct StrGData *data = INST_DATA(cl, g);
541 struct RastPort *rp;
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);
561 ReleaseGIRPort(rp);
564 return (IPTR)GMR_MEACTIVE;
567 /******************
568 ** Strg::Set() **
569 ******************/
570 IPTR StrGClass__OM_SET(Class *cl, struct Gadget *g, struct opSet *msg)
572 struct IntuitionBase *IntuitionBase = (struct IntuitionBase *)cl->cl_UserData;
573 IPTR retval;
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;
587 if (gi)
589 struct RastPort *rp = ObtainGIRPort(gi);
591 if (rp)
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);
602 ReleaseGIRPort(rp);
603 } /* if */
604 } /* if */
605 } /* if */
607 return retval;