Updated PCI IDs to latest snapshot.
[tangerine.git] / workbench / libs / gadtools / textclass.c
blob05cc7a6e8017fa6758dc97d34459025a918bb815
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;
50 const struct TagItem *tstate;
51 struct TextData *data = INST_DATA(cl, o);
52 struct RastPort *rport;
54 EnterFunc(bug("Text::Set()\n"));
56 tstate = msg->ops_AttrList;
58 while ((tag = NextTagItem(&tstate)))
60 IPTR tidata = tag->ti_Data;
62 switch (tag->ti_Tag)
64 case GTA_GadgetKind:
65 data->gadgetkind = (WORD)tidata;
66 break;
68 case GTNM_Number:
69 data->toprint = tidata;
70 D(bug("GTNM_Number: %ld\n", tidata));
71 if (data->dispfunc)
73 #ifdef __MORPHOS__
74 REG_A7 -= 8;
75 ((ULONG *)REG_A7)[0] = (ULONG)o;
76 ((ULONG *)REG_A7)[1] = data->toprint;
77 data->toprint = MyEmulHandle->EmulCallDirect68k(data->dispfunc);
78 REG_A7 += 8;
79 #else
80 data->toprint = (ULONG)data->dispfunc((struct Gadget *)o,
81 (WORD)data->toprint);
82 #endif
84 retval = 1UL;
85 break;
87 case GTTX_Text:
88 /* If the user has GT_SetGadgetAttrs() us to a different text,
89 ** then don't copy it anymore
91 if (msg->MethodID != OM_NEW)
93 if (data->flags & TEXTF_COPYTEXT)
95 FreeVec((APTR)data->toprint);
96 data->flags &= ~TEXTF_COPYTEXT;
98 data->toprint = tidata;
99 D(bug("GTTX_Text: %s\n", tidata));
101 retval = 1UL;
102 break;
104 case GTTX_Border: /* [I] */
105 case GTNM_Border: /* [I] */
106 if (tidata)
107 data->flags |= TEXTF_BORDER;
109 D(bug("Border: %d\n", tidata));
110 break;
113 /*case GTTX_FrontPen: [IS] */
114 case GTNM_FrontPen: /* [IS] */
115 data->frontpen = (UBYTE)tidata;
116 D(bug("FrontPen: %d\n", tidata));
117 retval = 1UL;
118 break;
120 /* case GTTX_BackPen: [IS] */
121 case GTNM_BackPen: /* [IS] */
122 data->backpen = (UBYTE)tidata;
123 D(bug("BackPen: %d\n", tidata));
124 retval = 1UL;
125 break;
127 /* case GTTX_Justification: [I] */
128 case GTNM_Justification: /* [I] */
129 data->justification = (UBYTE)tidata;
130 D(bug("Justification: %d\n", tidata));
131 break;
133 case GTNM_Format: /* [I] */
134 case GTA_Text_Format:
135 data->format = (STRPTR)tidata;
136 D(bug("Format: %s\n", tidata));
137 break;
139 /* case GTTX_Clipped: [I] */
140 case GTNM_Clipped:
141 if (tidata)
142 data->flags |= TEXTF_CLIPPED;
143 D(bug("Clipped: %d\n", tidata));
144 break;
146 case GTNM_MaxNumberLen: /* [I] */
147 data->maxnumberlength = tidata;
148 D(bug("MaxNumberLen: %d\n", tidata));
149 break;
151 } /* switch() */
153 } /* while (iterate taglist) */
155 /* Redraw the gadget, if an attribute was changed and if this is the
156 objects' base-class. */
157 if ((retval) && (OCLASS(o) == cl)) {
158 rport = ObtainGIRPort(msg->ops_GInfo);
159 if (rport) {
160 DoMethod(o, GM_RENDER, (IPTR) msg->ops_GInfo, (IPTR) rport, GREDRAW_UPDATE);
161 ReleaseGIRPort(rport);
162 retval = FALSE;
166 ReturnInt ("Text::Set", IPTR, retval);
169 /**********************************************************************************************/
171 IPTR GTText__OM_GET(Class * cl, Object * o, struct opGet *msg)
173 struct TextData *data = INST_DATA(cl, o);
174 IPTR retval;
176 switch (msg->opg_AttrID)
178 case GTA_GadgetKind:
179 case GTA_ChildGadgetKind:
180 *(msg->opg_Storage) = data->gadgetkind;
181 retval = 1UL;
182 break;
184 default:
185 retval = DoSuperMethodA(cl, o, (Msg)msg);
186 break;
189 return retval;
192 /**********************************************************************************************/
194 IPTR GTText__OM_NEW(Class * cl, Object * o, struct opSet *msg)
197 EnterFunc(bug("Text::New()\n"));
198 o = (Object *) DoSuperMethodA(cl, o, (Msg)msg);
199 if (o)
201 struct TextData *data = INST_DATA(cl, o);
202 struct TextAttr *tattr, def_tattr;
204 /* Set some defaults */
205 data->format = "%ld";
206 data->flags = 0;
207 data->frontpen = TEXTPEN;
208 data->backpen = BACKGROUNDPEN;
209 data->toprint = (IPTR) NULL;
210 data->font = NULL;
211 data->maxnumberlength = 0; /* This means "no limit" */
212 data->dispfunc = (APTR)GetTagData(GTA_Text_DispFunc, (IPTR) NULL, msg->ops_AttrList);
213 data->labelplace = GetTagData(GA_LabelPlace, GV_LabelPlace_Left, msg->ops_AttrList);
215 /* Open font to use for gadget */
217 /* We will *ALWAYS* have a valid DrawInfo struct */
218 data->dri = (struct DrawInfo *)GetTagData(GA_DrawInfo, (IPTR) NULL, msg->ops_AttrList);
220 def_tattr.ta_Name = data->dri->dri_Font->tf_Message.mn_Node.ln_Name;
221 def_tattr.ta_YSize = data->dri->dri_Font->tf_YSize;
222 def_tattr.ta_Style = 0;
223 def_tattr.ta_Flags = 0;
225 tattr = (struct TextAttr *)GetTagData(GA_TextAttr, (IPTR)&def_tattr, msg->ops_AttrList);
227 data->font = OpenFont(tattr);
228 if (!data->font)
229 goto error;
232 if (GetTagData(GTTX_CopyText, (IPTR)FALSE, msg->ops_AttrList))
234 STRPTR text;
236 D(bug("Got GTTX_CopyText\n"));
237 text = (STRPTR)GetTagData(GTTX_Text, (IPTR)"Text MUST be passed with OM_NEW", msg->ops_AttrList);
238 if (text)
240 D(bug("Text: %s\n", text));
241 /* Allocate copy buffer for the text */
242 data->toprint = (IPTR)AllocVec(strlen(text) + 1, MEMF_ANY);
243 if (data->toprint)
245 data->flags |= TEXTF_COPYTEXT;
246 D(bug("Copying text\n"));
247 strcpy((STRPTR)data->toprint, text);
249 else
251 goto error;
253 } else {
254 /* If text==NULL we have nothing to copy */
255 data->toprint = 0;
257 } else {
258 STRPTR text;
260 if ((text = (STRPTR)GetTagData(GTTX_Text, (IPTR) NULL, msg->ops_AttrList)))
262 data->toprint = (IPTR)text;
266 D(bug("calling text_set\n"));
267 text_set(cl, o, msg);
269 if (data->flags & TEXTF_BORDER)
271 struct TagItem frame_tags[] =
273 {IA_Width , GetTagData(GA_Width, 0, msg->ops_AttrList) },
274 {IA_Height , GetTagData(GA_Height, 0, msg->ops_AttrList) },
275 {IA_Resolution , (data->dri->dri_Resolution.X << 16) + data->dri->dri_Resolution.Y },
276 {IA_FrameType , FRAME_BUTTON },
277 {IA_Recessed , TRUE },
278 {TAG_DONE , 0UL }
281 data->frame = NewObjectA(NULL, FRAMEICLASS, frame_tags);
285 ReturnPtr ("Text::New", IPTR, (IPTR)o);
287 error:
288 CoerceMethod(cl, o, OM_DISPOSE);
289 ReturnPtr ("Text::New", IPTR, (IPTR) NULL);
292 /**********************************************************************************************/
294 #define HBORDER 2
295 #define VBORDER 2
297 AROS_UFH2 (void, puttostr,
298 AROS_UFHA(UBYTE, chr, D0),
299 AROS_UFHA(STRPTR *,strPtrPtr,A3)
302 AROS_USERFUNC_INIT
303 D(bug("Putting character %c into buffer at adress %p\n",
304 chr, *strPtrPtr));
305 *(*strPtrPtr)= chr;
306 (*strPtrPtr) ++;
307 AROS_USERFUNC_EXIT
310 /**********************************************************************************************/
312 IPTR GTText__GM_RENDER(Class *cl, struct Gadget *g, struct gpRender *msg)
314 UWORD *pens = msg->gpr_GInfo->gi_DrInfo->dri_Pens;
315 UBYTE textbuf[256], *str;
316 struct TextData *data = INST_DATA(cl, g);
317 WORD left, left2, top, width, height, numchars, tlength;
318 struct TextFont *oldfont;
319 struct RastPort *rp = msg->gpr_RPort;
321 EnterFunc(bug("Text::Render()\n"));
323 left = g->LeftEdge;
324 top = g->TopEdge;
325 width = g->Width;
326 height = g->Height;
328 if (msg->gpr_Redraw == GREDRAW_REDRAW)
330 if (data->frame)
332 DrawImageState(msg->gpr_RPort,
333 (struct Image *)data->frame,
334 left,
335 top,
336 IDS_NORMAL,
337 msg->gpr_GInfo->gi_DrInfo);
340 renderlabel(GadToolsBase, g, msg->gpr_RPort, data->labelplace);
343 if (data->toprint || (data->gadgetkind != TEXT_KIND))
345 /* preserve font */
346 oldfont = rp->Font;
347 SetFont(rp, data->font);
349 str = textbuf;
350 if (data->gadgetkind == TEXT_KIND)
352 strncpy(str, (char *)data->toprint, sizeof(textbuf));
353 textbuf[sizeof(textbuf) - 1] = '\0';
355 else /* NUMERIC_KIND or label of SLIDER_KIND */
357 RawDoFmt(data->format, &(data->toprint), (VOID_FUNC)AROS_ASMSYMNAME(puttostr), &str);
360 D(bug("Text formatted into: %s\n", textbuf));
361 numchars = strlen(textbuf);
363 if (data->flags & TEXTF_BORDER)
365 left += VBORDER + 1;
366 top += HBORDER + 1;
367 width = g->Width - (VBORDER + 1) * 2;
368 height = g->Height - (HBORDER + 1) * 2;
371 if (data->flags & TEXTF_CLIPPED)
373 struct TextExtent te;
375 /* See how many chars fits into the display area */
376 numchars = TextFit(rp, textbuf, numchars, &te, NULL, 1, width, g->Height);
379 tlength = TextLength(rp, textbuf, numchars);
381 left2 = left;
382 switch (data->justification)
384 case GTJ_LEFT:
385 break;
386 case GTJ_RIGHT:
387 left2 += (width - tlength);
388 break;
389 case GTJ_CENTER:
390 left2 += ((width - tlength) / 2);
391 break;
394 /* Render text */
395 D(bug("Rendering text of lenghth %d at (%d, %d)\n", numchars, left, top));
396 SetABPenDrMd(rp, pens[data->backpen], pens[data->backpen], JAM2);
397 RectFill(rp, left, top, left + width - 1, top + height - 1);
398 SetAPen(rp, pens[data->frontpen]);
400 Move(rp, left2,
401 top + ((height - data->font->tf_YSize) / 2) + data->font->tf_Baseline);
402 Text(rp, textbuf, numchars);
404 SetFont(rp, oldfont);
406 } /* if (data->toprint || (data->gadgetkind != TEXT_KIND)) */
408 ReturnInt("Text::Render", IPTR, 0);
411 /**********************************************************************************************/
413 IPTR GTText__OM_DISPOSE(Class *cl, Object *o, Msg msg)
415 struct TextData *data = INST_DATA(cl, o);
417 if (data->flags & TEXTF_COPYTEXT) FreeVec((APTR)data->toprint);
418 if (data->font) CloseFont(data->font);
419 if (data->frame) DisposeObject(data->frame);
421 return DoSuperMethodA(cl, o, msg);
425 /**********************************************************************************************/
427 IPTR GTText__OM_SET(Class *cl, Object *o, struct opSet *msg)
429 IPTR retval;
431 retval = DoSuperMethodA(cl, o, (Msg)msg);
432 retval += text_set(cl, o, msg);
434 /* If we have been subclassed, OM_UPDATE should not cause a GM_RENDER
435 * because it would circumvent the subclass from fully overriding it.
436 * The check of cl == OCLASS(o) should fail if we have been
437 * subclassed, and we have gotten here via DoSuperMethodA().
439 if ( retval && ( msg->MethodID == OM_UPDATE ) && ( cl == OCLASS(o) ) )
441 struct GadgetInfo *gi = msg->ops_GInfo;
442 if (gi)
444 struct RastPort *rp = ObtainGIRPort(gi);
445 if (rp)
447 DoMethod(o, GM_RENDER, (IPTR) gi, (IPTR) rp, GREDRAW_REDRAW);
448 ReleaseGIRPort(rp);
449 } /* if */
450 } /* if */
451 } /* if */
453 return retval;
456 /**********************************************************************************************/
458 IPTR GTText__GM_GOACTIVE(Class *cl, Object *o, Msg msg)
460 return (IPTR)GMR_NOREUSE;
463 /**********************************************************************************************/