7 * (C) Copyright 1998 Manuel Lemos.
8 * (C) Copyright 1996-1997 Ian J. Einman.
9 * (C) Copyright 1993-1996 Jaba Development.
10 * (C) Copyright 1993-1996 Jan van den Baard.
11 * All Rights Reserved.
14 * Revision 42.7 2004/06/16 20:16:48 verhaegs
15 * Use METHODPROTO, METHOD_END and REGFUNCPROTOn where needed.
17 * Revision 42.6 2003/01/18 19:10:02 chodorowski
18 * Instead of using the _AROS or __AROS preprocessor symbols, use __AROS__.
20 * Revision 42.5 2001/02/02 21:06:50 stegerg
21 * used TextFit() with strDirection param = 0, but it must be -1 or 1
24 * Revision 42.4 2001/01/28 04:53:21 bergers
25 * Fixed some compiler complaints (some casts were missing.).
27 * Revision 42.3 2000/08/09 11:45:57 chodorowski
28 * Removed a lot of #ifdefs that disabled the AROS_LIB* macros when not building on AROS. This is now handled in contrib/bgui/include/bgui_compilerspecific.h.
30 * Revision 42.2 2000/05/15 19:27:02 stegerg
31 * another hundreds of REG() macro replacements in func headers/protos.
33 * Revision 42.1 2000/05/14 23:32:48 stegerg
34 * changed over 200 function headers which all use register
35 * parameters (oh boy ...), because the simple REG() macro
36 * doesn't work with AROS. And there are still hundreds
37 * of headers left to be fixed :(
39 * Many of these functions would also work with stack
40 * params, but since i have fixed every single one
41 * I encountered up to now, I guess will have to do
42 * the same for the rest.
44 * Revision 42.0 2000/05/09 22:10:31 mlemos
45 * Bumped to revision 42.0 before handing BGUI to AROS team
47 * Revision 41.11 2000/05/09 19:55:21 mlemos
48 * Merged with the branch Manuel_Lemos_fixes.
50 * Revision 41.10.2.7 1999/08/10 22:38:03 mlemos
51 * Removed comments of escape sequences not implemented.
53 * Revision 41.10.2.6 1999/07/23 19:46:18 mlemos
54 * Added support to set draw mode to JAM1, JAM2 or complement in the text
57 * Revision 41.10.2.5 1998/12/06 22:30:11 mlemos
58 * Fixed bug of using the wrong RastPort to compute XPos of text string.
60 * Revision 41.10.2.4 1998/05/22 03:51:25 mlemos
61 * Added new line characters to the assertion debug messages that warn about
62 * NULL text strings being passed to TotalWidth and TotalHeight.
64 * Revision 41.10.2.3 1998/03/01 18:46:12 mlemos
65 * Fixed short allocation for label text string.
67 * Revision 41.10.2.2 1998/03/01 15:39:39 mlemos
68 * Added support to track BaseInfo memory leaks.
70 * Revision 41.10.2.1 1998/02/28 02:42:26 mlemos
71 * Added debug assert code to trap attempts to pass NULL text pointers to TextHeight and TextWidth functions.
73 * Revision 41.10 1998/02/25 21:13:23 mlemos
76 * Revision 1.1 1998/02/25 17:09:58 mlemos
82 /// Class definitions.
83 #include "include/classdefs.h"
86 * Object instance data.
89 ULONG td_Flags
; /* Flags. */
90 UBYTE
*td_Text
; /* The text itself. */
91 ULONG td_TextID
; /* Text ID. */
92 RAWARG td_Args
; /* Arguments for format string. */
95 #define TEXTF_COPY (1<<0) /* Copy text. */
96 #define TEXTF_COPIED (1<<1) /* This text is a copy. */
102 STATIC UBYTE
*Text_Get(TD
*td
)
106 if (td
->td_Text
&& td
->td_Args
)
108 if ((text
= BGUI_AllocPoolMem(CompStrlenF(td
->td_Text
, td
->td_Args
))))
110 DoSPrintF(text
, td
->td_Text
, td
->td_Args
);
120 STATIC VOID
Text_Clear(TD
*td
)
122 if (td
->td_Flags
& TEXTF_COPIED
)
124 BGUI_FreePoolMem(td
->td_Text
);
125 td
->td_Flags
&= ~TEXTF_COPIED
;
132 static void Text_Set(TD
*td
, char *text
)
136 if (text
&& (td
->td_Flags
& TEXTF_COPY
))
138 if ((td
->td_Text
= BGUI_AllocPoolMem(strlen(text
)+1)))
140 strcpy(td
->td_Text
, text
);
141 td
->td_Flags
|= TEXTF_COPIED
;
152 * Create a shiny new object.
154 METHOD(TextClassNew
, struct opSet
*, ops
)
159 * First we let the superclass
162 if ((rc
= AsmDoSuperMethodA(cl
, obj
, (Msg
)ops
)))
167 AsmCoerceMethod(cl
, (Object
*)rc
, RM_SETM
, ops
->ops_AttrList
, RAF_INITIAL
);
175 * Get the flags of an attribute.
177 METHOD(TextClassGetAttrFlags
, struct rmAttr
*, ra
)
179 static struct TagItem chart
[] =
181 { TEXTA_Text
, CHART_ATTR(td_
, td_Text
) | RAF_CUSTOM
| RAF_NOP
| RAF_RESIZE
, },
182 { TEXTA_TextID
, CHART_ATTR(td_
, td_TextID
), },
183 { TEXTA_Args
, CHART_ATTR(td_
, td_Args
) | RAF_RESIZE
, },
185 { TEXTA_CopyText
, CHART_FLAG(td_
, td_Flags
, TEXTF_COPY
) | RAF_CUSTOM
, },
190 IPTR rc
= GetTagData(ra
->ra_Attr
->ti_Tag
, 0, chart
);
198 * Set standard attributes.
200 METHOD(TextClassSet
, struct rmAttr
*, ra
)
202 return (IPTR
)BGUI_SetAttrChart(cl
, obj
, ra
);
208 * Set custom attributes.
210 METHOD(TextClassSetCustom
, struct rmAttr
*, ra
)
212 TD
*td
= INST_DATA(cl
, obj
);
213 Tag attr
= ra
->ra_Attr
->ti_Tag
;
214 IPTR data
= ra
->ra_Attr
->ti_Data
;
219 Text_Set(td
, (char *)data
);
223 if (data
&& !(td
->td_Flags
& TEXTF_COPIED
))
225 Text_Set(td
, td
->td_Text
);
237 METHOD(TextClassGet
, struct rmAttr
*, ra
)
239 return (IPTR
)BGUI_GetAttrChart(cl
, obj
, ra
);
245 * Get custom attributes.
247 METHOD(TextClassGetCustom
, struct rmAttr
*, ra
)
249 TD
*td
= INST_DATA(cl
, obj
);
250 Tag attr
= ra
->ra_Attr
->ti_Tag
;
251 IPTR
*store
= (IPTR
*)ra
->ra_Attr
->ti_Data
;
265 * Dispose of the object.
267 METHOD(TextClassDispose
, Msg
, msg
)
269 TD
*td
= INST_DATA(cl
, obj
);
277 * The rest goes to the superclass.
279 return AsmDoSuperMethodA(cl
, obj
, msg
);
285 * Render a text graphic.
287 METHOD(TextClassRender
, struct tmRender
*, tmr
)
289 TD
*td
= INST_DATA(cl
, obj
);
292 if ((text
= Text_Get(td
)))
294 RenderText(tmr
->tmr_BInfo
, text
, tmr
->tmr_Bounds
);
295 if (td
->td_Args
) BGUI_FreePoolMem(text
);
303 * Render a text graphic.
305 METHOD(TextClassDimensions
, struct tmDimensions
*, tmd
)
307 TD
*td
= INST_DATA(cl
, obj
);
310 if ((text
= Text_Get(td
)))
312 if (tmd
->tmd_Extent
.Width
) *(tmd
->tmd_Extent
.Width
) = TotalWidth (tmd
->tmd_RPort
, text
);
313 if (tmd
->tmd_Extent
.Height
) *(tmd
->tmd_Extent
.Height
) = TotalHeight(tmd
->tmd_RPort
, text
);
315 if (td
->td_Args
) BGUI_FreePoolMem(text
);
323 METHOD(TextClassLocalize
, struct bmLocalize
*, bml
)
325 TD
*td
= INST_DATA(cl
, obj
);
330 Text_Set(td
, BGUI_GetCatalogStr(bml
->bml_Locale
, td
->td_TextID
, td
->td_Text
));
338 /// Class initialization.
341 * Class function table.
343 STATIC DPFUNC ClassFunc
[] = {
344 { TEXTM_RENDER
, TextClassRender
},
345 { TEXTM_DIMENSIONS
, TextClassDimensions
},
347 { RM_GETATTRFLAGS
, TextClassGetAttrFlags
},
348 { RM_SET
, TextClassSet
},
349 { RM_SETCUSTOM
, TextClassSetCustom
},
350 { RM_GET
, TextClassGet
},
351 { RM_GETCUSTOM
, TextClassGetCustom
},
352 { OM_NEW
, TextClassNew
},
353 { OM_DISPOSE
, TextClassDispose
},
354 { BASE_LOCALIZE
, TextClassLocalize
},
359 * Simple class initialization.
361 makeproto Class
*InitTextClass(void)
363 return BGUI_MakeClass(CLASS_SuperClassBGUI
, BGUI_ROOT_OBJECT
,
364 CLASS_ObjectSize
, sizeof(TD
),
365 CLASS_DFTable
, ClassFunc
,
376 * Figure out the total text width and height
377 * of an text with info-style command sequences.
381 AROS_LH4(VOID
, BGUI_InfoTextSize
,
382 AROS_LHA(struct RastPort
*, rp
, A0
),
383 AROS_LHA(UBYTE
*, text
, A1
),
384 AROS_LHA(UWORD
*, wi
, A2
),
385 AROS_LHA(UWORD
*, wh
, A3
),
386 struct Library
*, BGUIBase
, 18, BGUI
)
388 makeproto SAVEDS ASM VOID
BGUI_InfoTextSize(REG(a0
) struct RastPort
*rp
, REG(a1
) UBYTE
*text
, REG(a2
) UWORD
*wi
, REG(a3
) UWORD
*wh
)
393 if (wi
) *wi
= TotalWidth( rp
, text
);
394 if (wh
) *wh
= TotalHeight(rp
, text
);
400 * Render the text with info-style command sequences
401 * inside the bounding box. Text is automatically
402 * trucated when out of bounds.
406 AROS_LH4(VOID
, BGUI_InfoText
,
407 AROS_LHA(struct RastPort
*, rp
, A0
),
408 AROS_LHA(UBYTE
*, text
, A1
),
409 AROS_LHA(struct IBox
*, bounds
, A2
),
410 AROS_LHA(struct DrawInfo
*, dri
, A3
),
411 struct Library
*, BGUIBase
, 19, BGUI
)
413 makeproto SAVEDS ASM VOID
BGUI_InfoText( REG(a0
) struct RastPort
*rp
, REG(a1
) UBYTE
*text
, REG(a2
) struct IBox
*bounds
, REG(a3
) struct DrawInfo
*dri
)
418 RenderInfoText(rp
, text
, PENS(dri
), bounds
, (UWORD
)~0);
426 #define TF_CENTER (1<<0)
427 #define TF_RIGHT (1<<1)
428 #define TF_SHADOW (1<<2)
429 #define TF_UNDERLINE (1<<3)
430 #define TF_HIGHUNDERLINE (1<<4)
431 #define TF_KEEP (1<<5)
432 #define TF_WRAP (1<<6)
437 * \33b Switch to bold
438 * \33i Switch to italic
439 * \33u Switch to underlined
440 * \33n Switch to normal
441 * \33s Switch to shadow
442 * \33z Switch to underlined, offset 2
443 * \33Z Switch to highlight underlined, offset 2
444 * \33c Center this and the following lines
445 * \33r Right-align this and the following lines
446 * \33l Left-align this and the following lines
447 * \33k Keep style flags.
449 * \33d<n> Switch to DrawInfo pen <n>
450 * \33p<n> Switch to pen <n>
451 * \33D<n> Switch to background DrawInfo pen <n>
452 * \33P<n> Switch to background pen <n>
458 * Parse a command sequence.
460 STATIC UBYTE
*ParseCommSeq(struct BaseInfo
*bi
, UBYTE
*text
, UWORD
*old_style
, UWORD
*flags
)
462 UWORD new_style
= *old_style
;
465 * Let's see what we have here...
469 case '-': /* Turn off. */
473 new_style
&= ~FSF_BOLD
;
476 new_style
&= ~FSF_ITALIC
;
479 new_style
&= ~FSF_UNDERLINED
;
482 *flags
&= ~TF_SHADOW
;
491 *flags
&= ~TF_UNDERLINE
;
494 *flags
&= ~TF_HIGHUNDERLINE
;
502 case 'b': /* Bold. */
503 new_style
|= FSF_BOLD
;
506 case 'i': /* Italic. */
507 new_style
|= FSF_ITALIC
;
510 case 'u': /* Underscore. */
511 new_style
|= FSF_UNDERLINED
;
514 case 'n': /* Normal. */
515 new_style
= FS_NORMAL
;
516 *flags
&= ~(TF_SHADOW
|TF_UNDERLINE
|TF_HIGHUNDERLINE
);
519 case 'k': /* Keep styles. */
523 case 'w': /* Wrap text. */
527 case 's': /* Shadowed. */
531 case 'z': /* Underlined offset = 2. */
532 *flags
|= TF_UNDERLINE
;
535 case 'Z': /* Highlight underlined offset = 2. */
536 *flags
|= TF_HIGHUNDERLINE
;
539 case 'c': /* Center. */
544 case 'r': /* Right. */
545 *flags
&= ~TF_CENTER
;
549 case 'l': /* Left. */
550 *flags
&= ~(TF_RIGHT
|TF_CENTER
);
553 case 'd': /* DriPen. */
554 BSetDPenA(bi
, strtol(text
, (char **)&text
, 0));
558 BSetDPenB(bi
, strtol(text
, (char **)&text
, 0));
562 BSetPenA(bi
, strtol(text
, (char **)&text
, 0));
566 BSetPenB(bi
, strtol(text
, (char **)&text
, 0));
576 BSetDrMd(bi
, COMPLEMENT
);
579 case '\33': /* Do nothing. */
594 if (new_style
!= *old_style
)
596 *old_style
= new_style
;
597 BSetFontStyle(bi
, new_style
);
604 * Determine the x position
605 * where to render the line.
607 STATIC WORD
XPos(struct BaseInfo
*bi
, UBYTE
*text
, UWORD
*old_style
, struct IBox
*domain
, UWORD
*flags
)
609 struct RastPort
*rp
= bi
->bi_RPort
;
610 struct RastPort rp2
= *rp
;
611 struct BaseInfo bi2
= *bi
;
613 UWORD new_style
= *old_style
;
621 while (*text
&& (*text
!= '\n'))
624 * What have we got...
632 text
= ParseCommSeq(&bi2
, text
+ 1, &new_style
, flags
);
638 * Count non-action characters.
640 while (text
[i
] && (text
[i
] != '\33') && (text
[i
] != '\n')) i
++;
645 * Determine their length.
647 line_len
+= TextWidthNum(&rp2
, text
, i
);
659 * Calculate x-position.
661 if (*flags
& TF_CENTER
) xpos
= domain
->Left
+ ((domain
->Width
- line_len
) >> 1);
662 else if (*flags
& TF_RIGHT
) xpos
= domain
->Left
+ domain
->Width
- 1 - line_len
;
663 else xpos
= domain
->Left
;
666 * Don't pass the left edge.
668 if (xpos
< domain
->Left
) xpos
= domain
->Left
;
675 * Determine the total height of the text.
677 makeproto UWORD ASM
TotalHeight( REG(a0
) struct RastPort
*rp
, REG(a1
) UBYTE
*text
)
683 * Count the number of lines.
687 D(bug("*** NULL text pointer in TotalHeight function (%s,%ld)\n",__FILE__
,__LINE__
));
690 while ((c
= *text
++))
694 return (UWORD
)(nl
* rp
->TxHeight
);
699 * Determine the total width
700 * of the information text.
702 makeproto UWORD ASM
TotalWidth(REG(a0
) struct RastPort
*rp
, REG(a1
) UBYTE
*text
)
704 struct RastPort rport
= *rp
;
705 ULONG line_len
= 0, len
= 0;
706 UWORD new_style
= FS_NORMAL
, flags
= 0, i
;
710 bi
.bi_Pens
= DefDriPens
;
711 bi
.bi_RPort
= &rport
;
714 * Start as FS_NORMAL.
716 BSetFontStyle(&bi
, FS_NORMAL
);
723 D(bug("*** NULL text pointer in TotalWidth function (%s,%ld)\n",__FILE__
,__LINE__
));
737 text
= ParseCommSeq(&bi
, ++text
, &new_style
, &flags
);
743 * Count the non-action characters.
745 while (text
[i
] && (text
[i
] != '\33') && (text
[i
] != '\n')) i
++;
748 * Determine their length.
750 line_len
+= TextWidthNum(&rport
, text
, i
);
753 * New line or end-of-line?
755 if (text
[i
] == '\n' || text
[i
] == '\0')
757 if (!(flags
& TF_WRAP
))
760 * Is it wider than the previous ones?
767 * Go on when this was a new line.
772 BSetFontStyle(&bi
, FS_NORMAL
);
789 * Render the information text.
791 makeproto
void RenderInfoText(struct RastPort
*rp
, UBYTE
*text
, UWORD
*pens
, struct IBox
*domain
, UWORD backpen
)
796 if ((bi
= AllocBaseInfoDebug(__FILE__
,__LINE__
,BI_RastPort
, rp
, BI_Pens
, pens
, TAG_DONE
)))
798 if ((bi
= AllocBaseInfo(BI_RastPort
, rp
, BI_Pens
, pens
, TAG_DONE
)))
801 if (!pens
) pens
= DefDriPens
;
806 * First we fill the background.
808 if (backpen
!= (UWORD
)~1)
810 if (backpen
!= (UWORD
)~0)
812 BSetPenA(bi
, backpen
);
813 BBoxFillA(bi
, domain
);
819 BSetDPenA(bi
, (backpen
== bi
->bi_Pens
[FILLPEN
]) ? FILLTEXTPEN
: TEXTPEN
);
821 RenderText(bi
, text
, domain
);
829 * Render the information text.
831 makeproto
void RenderText(struct BaseInfo
*bi
, UBYTE
*text
, struct IBox
*domain
)
833 struct RastPort
*rp
= bi
->bi_RPort
;
834 struct TextExtent extent
;
835 WORD xpos
, ypos
= domain
->Top
+ rp
->TxBaseline
;
836 UWORD style
= FS_NORMAL
, dubstyle
= FS_NORMAL
, flags
= 0, i
, nl
, numc
;
837 ULONG old_a
= 0, old_m
;
840 * Start as FS_NORMAL.
842 BSetFontStyle(bi
, FS_NORMAL
);
845 * Get the height of the text.
847 nl
= TotalHeight(rp
, text
);
853 if (nl
< domain
->Height
)
855 * Yes. Adjust the top size
856 * so that it get's centered.
858 ypos
+= (domain
->Height
- nl
) >> 1;
861 * Find out starting position.
863 xpos
= XPos(bi
, text
, &dubstyle
, domain
, &flags
);
866 BSetFontStyle(bi
, FS_NORMAL
);
867 flags
&= ~(TF_SHADOW
|TF_UNDERLINE
|TF_HIGHUNDERLINE
);
875 * What have we got...
883 text
= ParseCommSeq(bi
, ++text
, &style
, &flags
);
895 xpos
= XPos(bi
, text
, &dubstyle
, domain
, &flags
);
898 * Are we passing the bottom of the
901 if ((ypos
+= rp
->TxHeight
) > domain
->Top
+ domain
->Height
- 1)
904 Move(rp
, xpos
, ypos
);
905 if (!(flags
& TF_KEEP
))
907 BSetFontStyle(bi
, FS_NORMAL
);
908 flags
&= ~(TF_SHADOW
|TF_UNDERLINE
|TF_HIGHUNDERLINE
);
914 * Count non-action characters.
917 while (text
[i
] && (text
[i
] != '\33') && (text
[i
] != '\n')) i
++;
924 if ((numc
= TextFit(rp
, text
, i
, &extent
, NULL
, 1, max((LONG
)(domain
->Width
- (xpos
- domain
->Left
)), 0), rp
->TxHeight
)))
926 if (flags
& TF_SHADOW
)
928 old_a
= FGetAPen(rp
);
929 old_m
= FGetDrMd(rp
);
930 BSetDPenA(bi
, SHADOWPEN
);
931 Move(rp
, xpos
+ 1, ypos
+ 1);
932 Text(rp
, text
, numc
);
935 Move(rp
, xpos
, ypos
);
936 Text(rp
, text
, numc
);
941 if (flags
& (TF_UNDERLINE
|TF_HIGHUNDERLINE
))
943 if (flags
& TF_HIGHUNDERLINE
)
945 old_a
= FGetAPen(rp
);
946 BSetDPenA(bi
, SHINEPEN
);
948 Move(rp
, xpos
, ypos
+ 2);
949 Draw(rp
, xpos
+ TextLength(rp
, text
, numc
) - 2, ypos
+ 2);
950 if (flags
& TF_HIGHUNDERLINE
)
955 Move(rp
, xpos
, ypos
);
956 Text(rp
, text
, numc
);
960 * Skip remainder of the line
965 while (text
[i
] && text
[i
] != '\n')
971 xpos
+= TextWidthNum(rp
, text
, numc
);