Allow multiple volumes with the same name if their creation dates differ.
[AROS.git] / workbench / libs / gadtools / textclass.c
blob6f52e474c3f038a55417ecaa3c68519b4a93f3ec
1 /*
2 Copyright © 1995-2005, The AROS Development Team. All rights reserved.
3 $Id$
5 Internal GadTools text class (NUMERIC_KIND and TEXT_KIND) .
6 */
9 #include <proto/exec.h>
10 #include <exec/libraries.h>
11 #include <exec/memory.h>
12 #include <proto/dos.h>
13 #include <intuition/classes.h>
14 #include <intuition/classusr.h>
15 #include <intuition/gadgetclass.h>
16 #include <intuition/imageclass.h>
17 #include <intuition/intuition.h>
18 #include <intuition/cghooks.h>
19 #include <graphics/rastport.h>
20 #include <graphics/text.h>
21 #include <utility/tagitem.h>
22 #include <devices/inputevent.h>
23 #include <proto/alib.h>
24 #include <proto/utility.h>
26 #include <string.h> /* memset() */
28 #define SDEBUG 0
29 #define DEBUG 0
30 #include <aros/debug.h>
32 #include "gadtools_intern.h"
34 /**********************************************************************************************/
36 #define GadToolsBase ((struct GadToolsBase_intern *)cl->cl_UserData)
38 /**********************************************************************************************/
40 #define TEXTF_CLIPPED (1 << 0)
41 #define TEXTF_BORDER (1 << 1)
42 #define TEXTF_COPYTEXT (1 << 2)
44 /**********************************************************************************************/
46 STATIC IPTR text_set(Class * cl, Object * o, struct opSet * msg)
48 IPTR retval = 0UL;
49 struct TagItem *tag, *tstate;
50 struct TextData *data = INST_DATA(cl, o);
51 struct RastPort *rport;
53 EnterFunc(bug("Text::Set()\n"));
55 tstate = msg->ops_AttrList;
57 while ((tag = NextTagItem(&tstate)))
59 IPTR tidata = tag->ti_Data;
61 switch (tag->ti_Tag)
63 case GTA_GadgetKind:
64 data->gadgetkind = (WORD)tidata;
65 break;
67 case GTNM_Number:
68 data->toprint = tidata;
69 D(bug("GTNM_Number: %ld\n", tidata));
70 if (data->dispfunc)
72 struct Gadget *g;
74 g = data->parentgadget ? data->parentgadget : (struct Gadget *)o;
75 #ifdef __MORPHOS__
76 REG_A7 -= 8;
77 ((ULONG *)REG_A7)[0] = (ULONG)g;
78 ((ULONG *)REG_A7)[1] = data->toprint;
79 data->toprint = MyEmulHandle->EmulCallDirect68k(data->dispfunc);
80 REG_A7 += 8;
81 #else
82 data->toprint = data->dispfunc(g, (WORD)data->toprint);
83 #endif
85 retval = 1UL;
86 break;
88 case GTTX_Text:
89 /* If the user has GT_SetGadgetAttrs() us to a different text,
90 ** then don't copy it anymore
92 if (msg->MethodID != OM_NEW)
94 if (data->flags & TEXTF_COPYTEXT)
96 FreeVec((APTR)data->toprint);
97 data->flags &= ~TEXTF_COPYTEXT;
99 data->toprint = tidata;
100 D(bug("GTTX_Text: %s\n", tidata));
102 retval = 1UL;
103 break;
105 case GTTX_Border: /* [I] */
106 case GTNM_Border: /* [I] */
107 if (tidata)
108 data->flags |= TEXTF_BORDER;
110 D(bug("Border: %d\n", tidata));
111 break;
114 /*case GTTX_FrontPen: [IS] */
115 case GTNM_FrontPen: /* [IS] */
116 data->frontpen = (UBYTE)tidata;
117 D(bug("FrontPen: %d\n", tidata));
118 retval = 1UL;
119 break;
121 /* case GTTX_BackPen: [IS] */
122 case GTNM_BackPen: /* [IS] */
123 data->backpen = (UBYTE)tidata;
124 D(bug("BackPen: %d\n", tidata));
125 retval = 1UL;
126 break;
128 /* case GTTX_Justification: [I] */
129 case GTNM_Justification: /* [I] */
130 data->justification = (UBYTE)tidata;
131 D(bug("Justification: %d\n", tidata));
132 break;
134 case GTNM_Format: /* [I] */
135 case GTA_Text_Format:
136 data->format = (STRPTR)tidata;
137 D(bug("Format: %s\n", tidata));
138 break;
140 /* case GTTX_Clipped: [I] */
141 case GTNM_Clipped:
142 if (tidata)
143 data->flags |= TEXTF_CLIPPED;
144 D(bug("Clipped: %d\n", tidata));
145 break;
147 case GTNM_MaxNumberLen: /* [I] */
148 data->maxnumberlength = tidata;
149 D(bug("MaxNumberLen: %d\n", tidata));
150 break;
152 } /* switch() */
154 } /* while (iterate taglist) */
156 /* Redraw the gadget, if an attribute was changed and if this is the
157 objects' base-class. */
158 if ((retval) && (OCLASS(o) == cl)) {
159 rport = ObtainGIRPort(msg->ops_GInfo);
160 if (rport) {
161 DoMethod(o, GM_RENDER, (IPTR) msg->ops_GInfo, (IPTR) rport, GREDRAW_UPDATE);
162 ReleaseGIRPort(rport);
163 retval = FALSE;
167 ReturnInt ("Text::Set", IPTR, retval);
170 /**********************************************************************************************/
172 IPTR GTText__OM_GET(Class * cl, Object * o, struct opGet *msg)
174 struct TextData *data = INST_DATA(cl, o);
175 IPTR retval;
177 switch (msg->opg_AttrID)
179 case GTA_GadgetKind:
180 case GTA_ChildGadgetKind:
181 *(msg->opg_Storage) = data->gadgetkind;
182 retval = 1UL;
183 break;
185 default:
186 retval = DoSuperMethodA(cl, o, (Msg)msg);
187 break;
190 return retval;
193 /**********************************************************************************************/
195 IPTR GTText__OM_NEW(Class * cl, Object * o, struct opSet *msg)
198 EnterFunc(bug("Text::New()\n"));
199 o = (Object *) DoSuperMethodA(cl, o, (Msg)msg);
200 if (o)
202 struct TextData *data = INST_DATA(cl, o);
203 struct TextAttr *tattr, def_tattr;
205 /* Set some defaults */
206 data->format = "%ld";
207 data->flags = 0;
208 data->frontpen = TEXTPEN;
209 data->backpen = BACKGROUNDPEN;
210 data->toprint = (IPTR) NULL;
211 data->font = NULL;
212 data->maxnumberlength = 0; /* This means "no limit" */
213 data->dispfunc = (APTR)GetTagData(GTA_Text_DispFunc, (IPTR) NULL, msg->ops_AttrList);
214 data->labelplace = GetTagData(GA_LabelPlace, GV_LabelPlace_Left, msg->ops_AttrList);
215 data->parentgadget = (struct Gadget *)GetTagData(GTA_Text_ParentGadget, 0, msg->ops_AttrList);
217 /* Open font to use for gadget */
219 /* We will *ALWAYS* have a valid DrawInfo struct */
220 data->dri = (struct DrawInfo *)GetTagData(GA_DrawInfo, (IPTR) NULL, msg->ops_AttrList);
222 def_tattr.ta_Name = data->dri->dri_Font->tf_Message.mn_Node.ln_Name;
223 def_tattr.ta_YSize = data->dri->dri_Font->tf_YSize;
224 def_tattr.ta_Style = 0;
225 def_tattr.ta_Flags = 0;
227 tattr = (struct TextAttr *)GetTagData(GA_TextAttr, (IPTR)&def_tattr, msg->ops_AttrList);
229 data->font = OpenFont(tattr);
230 if (!data->font)
231 goto error;
234 if (GetTagData(GTTX_CopyText, (IPTR)FALSE, msg->ops_AttrList))
236 STRPTR text;
238 D(bug("Got GTTX_CopyText\n"));
239 text = (STRPTR)GetTagData(GTTX_Text, (IPTR)"Text MUST be passed with OM_NEW", msg->ops_AttrList);
240 if (text)
242 D(bug("Text: %s\n", text));
243 /* Allocate copy buffer for the text */
244 data->toprint = (IPTR)AllocVec(strlen(text) + 1, MEMF_ANY);
245 if (data->toprint)
247 data->flags |= TEXTF_COPYTEXT;
248 D(bug("Copying text\n"));
249 strcpy((STRPTR)data->toprint, text);
251 else
253 goto error;
255 } else {
256 /* If text==NULL we have nothing to copy */
257 data->toprint = 0;
259 } else {
260 STRPTR text;
262 if ((text = (STRPTR)GetTagData(GTTX_Text, (IPTR) NULL, msg->ops_AttrList)))
264 data->toprint = (IPTR)text;
268 D(bug("calling text_set\n"));
269 text_set(cl, o, msg);
271 if (data->flags & TEXTF_BORDER)
273 struct TagItem frame_tags[] =
275 {IA_Width , GetTagData(GA_Width, 0, msg->ops_AttrList) },
276 {IA_Height , GetTagData(GA_Height, 0, msg->ops_AttrList) },
277 {IA_Resolution , (data->dri->dri_Resolution.X << 16) + data->dri->dri_Resolution.Y },
278 {IA_FrameType , FRAME_BUTTON },
279 {IA_Recessed , TRUE },
280 {TAG_DONE , 0UL }
283 data->frame = NewObjectA(NULL, FRAMEICLASS, frame_tags);
287 ReturnPtr ("Text::New", IPTR, (IPTR)o);
289 error:
290 CoerceMethod(cl, o, OM_DISPOSE);
291 ReturnPtr ("Text::New", IPTR, (IPTR) NULL);
294 /**********************************************************************************************/
296 #define HBORDER 2
297 #define VBORDER 2
299 AROS_UFH2 (void, puttostr,
300 AROS_UFHA(UBYTE, chr, D0),
301 AROS_UFHA(STRPTR *,strPtrPtr,A3)
304 AROS_USERFUNC_INIT
305 D(bug("Putting character %c into buffer at adress %p\n",
306 chr, *strPtrPtr));
307 *(*strPtrPtr)= chr;
308 (*strPtrPtr) ++;
309 AROS_USERFUNC_EXIT
312 /**********************************************************************************************/
314 IPTR GTText__GM_RENDER(Class *cl, struct Gadget *g, struct gpRender *msg)
316 UWORD *pens = msg->gpr_GInfo->gi_DrInfo->dri_Pens;
317 UBYTE textbuf[256], *str;
318 struct TextData *data = INST_DATA(cl, g);
319 WORD left, left2, top, width, height, numchars, tlength;
320 struct TextFont *oldfont;
321 struct RastPort *rp = msg->gpr_RPort;
323 EnterFunc(bug("Text::Render()\n"));
325 left = g->LeftEdge;
326 top = g->TopEdge;
327 width = g->Width;
328 height = g->Height;
330 if (msg->gpr_Redraw == GREDRAW_REDRAW)
332 if (data->frame)
334 DrawImageState(msg->gpr_RPort,
335 (struct Image *)data->frame,
336 left,
337 top,
338 IDS_NORMAL,
339 msg->gpr_GInfo->gi_DrInfo);
342 renderlabel(GadToolsBase, g, msg->gpr_RPort, data->labelplace);
345 if (data->toprint || (data->gadgetkind != TEXT_KIND))
347 /* preserve font */
348 oldfont = rp->Font;
349 SetFont(rp, data->font);
351 str = textbuf;
352 if (data->gadgetkind == TEXT_KIND)
354 strncpy(str, (char *)data->toprint, sizeof(textbuf));
355 textbuf[sizeof(textbuf) - 1] = '\0';
357 else /* NUMERIC_KIND or label of SLIDER_KIND */
359 RawDoFmt(data->format, &(data->toprint), (VOID_FUNC)AROS_ASMSYMNAME(puttostr), &str);
362 D(bug("Text formatted into: %s\n", textbuf));
363 numchars = strlen(textbuf);
365 if (data->flags & TEXTF_BORDER)
367 left += VBORDER + 1;
368 top += HBORDER + 1;
369 width = g->Width - (VBORDER + 1) * 2;
370 height = g->Height - (HBORDER + 1) * 2;
373 if (data->flags & TEXTF_CLIPPED)
375 struct TextExtent te;
377 /* See how many chars fits into the display area */
378 numchars = TextFit(rp, textbuf, numchars, &te, NULL, 1, width, g->Height);
381 tlength = TextLength(rp, textbuf, numchars);
383 left2 = left;
384 switch (data->justification)
386 case GTJ_LEFT:
387 break;
388 case GTJ_RIGHT:
389 left2 += (width - tlength);
390 break;
391 case GTJ_CENTER:
392 left2 += ((width - tlength) / 2);
393 break;
396 /* Render text */
397 D(bug("Rendering text of lenghth %d at (%d, %d)\n", numchars, left, top));
398 SetABPenDrMd(rp, pens[data->backpen], pens[data->backpen], JAM2);
399 RectFill(rp, left, top, left + width - 1, top + height - 1);
400 SetAPen(rp, pens[data->frontpen]);
402 Move(rp, left2,
403 top + ((height - data->font->tf_YSize) / 2) + data->font->tf_Baseline);
404 Text(rp, textbuf, numchars);
406 SetFont(rp, oldfont);
408 } /* if (data->toprint || (data->gadgetkind != TEXT_KIND)) */
410 ReturnInt("Text::Render", IPTR, 0);
413 /**********************************************************************************************/
415 IPTR GTText__OM_DISPOSE(Class *cl, Object *o, Msg msg)
417 struct TextData *data = INST_DATA(cl, o);
419 if (data->flags & TEXTF_COPYTEXT) FreeVec((APTR)data->toprint);
420 if (data->font) CloseFont(data->font);
421 if (data->frame) DisposeObject(data->frame);
423 return DoSuperMethodA(cl, o, msg);
427 /**********************************************************************************************/
429 IPTR GTText__OM_SET(Class *cl, Object *o, struct opSet *msg)
431 IPTR retval;
433 retval = DoSuperMethodA(cl, o, (Msg)msg);
434 retval += text_set(cl, o, msg);
436 /* If we have been subclassed, OM_UPDATE should not cause a GM_RENDER
437 * because it would circumvent the subclass from fully overriding it.
438 * The check of cl == OCLASS(o) should fail if we have been
439 * subclassed, and we have gotten here via DoSuperMethodA().
441 if ( retval && ( msg->MethodID == OM_UPDATE ) && ( cl == OCLASS(o) ) )
443 struct GadgetInfo *gi = msg->ops_GInfo;
444 if (gi)
446 struct RastPort *rp = ObtainGIRPort(gi);
447 if (rp)
449 DoMethod(o, GM_RENDER, (IPTR) gi, (IPTR) rp, GREDRAW_REDRAW);
450 ReleaseGIRPort(rp);
451 } /* if */
452 } /* if */
453 } /* if */
455 return retval;
458 /**********************************************************************************************/
460 IPTR GTText__GM_GOACTIVE(Class *cl, Object *o, Msg msg)
462 return (IPTR)GMR_NOREUSE;
465 /**********************************************************************************************/