2 Copyright © 2002-2012, The AROS Development Team. All rights reserved.
6 #define MUIMASTER_YES_INLINE_STDARG
9 #include <aros/debug.h>
11 #include <exec/memory.h>
12 #include <clib/alib_protos.h>
13 #include <proto/exec.h>
14 #include <proto/dos.h>
15 #include <proto/intuition.h>
16 #include <proto/utility.h>
17 #include <proto/muimaster.h>
18 #include <proto/graphics.h>
23 #include "muimaster_intern.h"
25 #include "support_classes.h"
26 #include "floattext_private.h"
28 extern struct Library
*MUIMasterBase
;
30 // like strlen(), but \n ends string, too.
31 static long MyStrLen(const char *ptr
)
33 const char *start
= ptr
;
35 while (*ptr
&& (*ptr
!= '\n'))
38 return (((long)ptr
) - ((long)start
));
42 * Calculates the number of characters that will fit on a line of a given
45 static UWORD
FitParagraphLine(STRPTR text
, ULONG length
, WORD width
,
46 ULONG offset
, struct Window
*window
)
48 struct TextExtent temp_extent
;
50 UBYTE
*p
, *q
= text
+ offset
;
52 char_count
= TextFit(window
->RPort
, text
+ offset
,
53 length
- offset
, &temp_extent
, NULL
, 1, width
, 32767);
55 /* Find the last space in the fitted substring */
57 if (offset
+ char_count
!= length
)
59 for (p
= text
+ offset
+ char_count
; p
> q
&& *p
!= ' '; p
--);
60 for (; p
> q
&& *p
== ' '; p
--);
62 char_count
= p
- q
+ 1;
68 static void SetText(Object
*obj
, struct Floattext_DATA
*data
)
71 struct Window
*window
;
72 UWORD i
, count
, pos
, line_size
, space_count
, extra_space_count
,
73 space_width
, space_multiple
, bonus_space_count
,
74 bonus_space_mod
, space_no_in
, space_no_out
, stripped_pos
,
75 stripped_count
, control_count
, tab_count
;
76 UBYTE
*text
, *p
, *q
, *r
, c
, *line
= NULL
, *stripped_text
= NULL
;
77 LONG len
, stripped_len
;
78 BOOL justify
, found
, is_empty
;
80 /* Avoid redrawing list while inserting lines */
82 data
->typesetting
= TRUE
;
84 DoMethod(obj
, MUIM_List_Clear
);
86 window
= (struct Window
*)XGET(obj
, MUIA_Window
);
87 width
= XGET(obj
, MUIA_Width
) - XGET(obj
, MUIA_InnerLeft
)
88 - XGET(obj
, MUIA_InnerRight
) - 8;
90 /* Only do layout if we have some text and a window in which to put it */
92 if (data
->text
&& window
!= NULL
)
94 /* Get width of a space character */
96 space_width
= TextLength(window
->RPort
, " ", 1);
98 /* Lay out each paragraph */
100 for (text
= data
->text
; text
[0] != '\0'; text
+= pos
)
102 stripped_pos
= pos
= 0;
103 len
= MyStrLen(text
);
107 /* Allocate line/paragraph buffers */
109 if (line
== NULL
|| len
>= line_size
)
112 line
= AllocVec(len
+ 1, MEMF_ANY
);
113 stripped_text
= AllocVec(len
+ 1, MEMF_ANY
);
116 if (line
== NULL
|| stripped_text
== NULL
)
119 /* Make a copy of paragraph text without control sequences
120 * or skip-chars, and with tabs expanded to spaces */
122 for (p
= text
, q
= stripped_text
; *p
!= '\0' && *p
!= '\n'; )
128 for (i
= 0; i
< data
->tabsize
; i
++)
132 else if (data
->skipchars
!= NULL
)
134 for (r
= data
->skipchars
; *r
!= '\0' && *r
!= *p
; r
++);
143 stripped_len
= MyStrLen(stripped_text
);
145 /* Divide this paragraph into lines */
149 while ((stripped_count
= FitParagraphLine(stripped_text
,
150 stripped_len
, width
, stripped_pos
, window
)) != 0)
152 /* Count number of characters for this line in original
155 control_count
= tab_count
= 0;
156 for (i
= 0, p
= text
+ pos
; i
< stripped_count
157 || (i
== stripped_count
&& *p
!= ' ' && *p
!= '\t');
171 else if (data
->skipchars
!= NULL
)
173 for (r
= data
->skipchars
;
174 *r
!= '\0' && *r
!= *p
; r
++);
175 if (*r
!= '\0' || (*p
== ' ' && i
== 0))
184 stripped_count
+ control_count
185 - tab_count
* data
->tabsize
;
187 /* Default to justified text if it's enabled and this
188 * isn't the last line of the paragraph */
190 justify
= data
->justify
;
193 /* Count number of spaces in stripped line */
195 p
= stripped_text
+ stripped_pos
;
196 for (i
= 0, space_count
= 0; i
< stripped_count
; i
++)
201 space_count
-= tab_count
* data
->tabsize
;
203 if (space_count
== 0)
209 /* Find out how many extra spaces to insert for fully
212 extra_space_count
= (width
- TextLength(window
->RPort
,
213 stripped_text
+ stripped_pos
, stripped_count
))
216 space_multiple
= (space_count
+ extra_space_count
)
218 bonus_space_count
= (space_count
+ extra_space_count
)
219 - space_count
* space_multiple
;
220 if (bonus_space_count
> 0)
222 (space_count
+ 3) / bonus_space_count
;
224 bonus_space_mod
= space_count
;
226 /* Don't justify on last line if it will be too
229 if (space_multiple
> 5
230 && pos
+ count
== len
)
234 /* Prefix new line with all control characters contained
235 * in previous line */
237 for (p
= q
= line
; *p
!= '\0'; p
++)
246 /* Generate line to insert in List object */
252 space_no_in
= space_no_out
= 0;
255 if (*p
== ' ' && justify
&& !is_empty
)
257 /* Add extra spaces to justify text */
259 for (i
= 0; i
< space_multiple
; i
++)
261 space_no_out
+= space_multiple
;
263 if (bonus_space_count
> 0
264 && space_no_in
% bonus_space_mod
== 0)
274 /* Last input space? Make it as wide as
275 * necessary for line to reach right border */
277 if (space_no_in
== space_count
)
279 while (bonus_space_count
-- > 0)
285 /* Expand tab to spaces */
287 for (i
= 0; i
< data
->tabsize
; i
++)
291 else if (data
->skipchars
!= NULL
)
293 /* Filter out skip-chars */
295 for (r
= data
->skipchars
;
296 *r
!= '\0' && *r
!= *p
; r
++);
297 if (*r
== '\0' && !(*p
== ' ' && is_empty
))
306 /* No skip-chars, so direct copy */
314 /* Add line to list */
316 DoMethod(obj
, MUIM_List_InsertSingle
, line
,
317 MUIV_List_Insert_Bottom
);
320 /* Move on to first word of next line */
322 stripped_pos
+= stripped_count
;
326 if (data
->skipchars
!= NULL
)
328 for (found
= FALSE
, p
= text
+ pos
;
331 for (r
= data
->skipchars
;
332 *r
!= '\0' && *r
!= *p
; r
++);
333 if (*r
== '\0' && *p
!= ' ' && *p
!= '\t')
339 for (p
= text
+ pos
; *p
== ' ' || *p
== '\t';
341 for (p
= stripped_text
+ stripped_pos
; *(p
++) == ' ';
347 DoMethod(obj
, MUIM_List_InsertSingle
, "",
348 MUIV_List_Insert_Bottom
);
350 if (text
[pos
] == '\n')
355 data
->typesetting
= FALSE
;
357 DoMethod(obj
, MUIM_List_Redraw
, MUIV_List_Redraw_All
);
360 IPTR
Floattext__OM_NEW(struct IClass
*cl
, Object
*obj
, struct opSet
*msg
)
362 struct Floattext_DATA
*data
;
364 struct TagItem
*tags
;
366 obj
= (Object
*) DoSuperMethodA(cl
, obj
, (Msg
) msg
);
373 data
= INST_DATA(cl
, obj
);
375 SetAttrs(obj
, MUIA_List_ConstructHook
, MUIV_List_ConstructHook_String
,
376 MUIA_List_DestructHook
, MUIV_List_DestructHook_String
, TAG_DONE
);
378 for (tags
= msg
->ops_AttrList
; (tag
= NextTagItem(&tags
));)
382 case MUIA_Floattext_Justify
:
383 data
->justify
= tag
->ti_Data
;
386 case MUIA_Floattext_SkipChars
:
387 data
->skipchars
= (STRPTR
) tag
->ti_Data
;
390 case MUIA_Floattext_TabSize
:
391 data
->tabsize
= tag
->ti_Data
;
394 case MUIA_Floattext_Text
:
395 data
->text
= StrDup((STRPTR
) tag
->ti_Data
);
400 if (data
->tabsize
== 0)
402 else if (data
->tabsize
> 20)
410 IPTR
Floattext__OM_DISPOSE(struct IClass
*cl
, Object
*obj
,
413 struct Floattext_DATA
*data
= INST_DATA(cl
, obj
);
417 return DoSuperMethodA(cl
, obj
, (Msg
) msg
);
420 IPTR
Floattext__OM_GET(struct IClass
*cl
, Object
*obj
, struct opGet
*msg
)
422 struct Floattext_DATA
*data
= INST_DATA(cl
, obj
);
423 #define STORE *(msg->opg_Storage)
425 switch (msg
->opg_AttrID
)
427 case MUIA_Floattext_Justify
:
428 STORE
= data
->justify
;
431 case MUIA_Floattext_Text
:
432 STORE
= (IPTR
) data
->text
;
439 return DoSuperMethodA(cl
, obj
, (Msg
) msg
);
442 IPTR
Floattext__OM_SET(struct IClass
*cl
, Object
*obj
, struct opSet
*msg
)
444 struct Floattext_DATA
*data
= INST_DATA(cl
, obj
);
446 struct TagItem
*tags
;
447 BOOL changed
= FALSE
;
449 for (tags
= msg
->ops_AttrList
; (tag
= NextTagItem(&tags
));)
453 case MUIA_Floattext_Justify
:
454 data
->justify
= tag
->ti_Data
!= 0;
458 case MUIA_Floattext_SkipChars
:
459 data
->skipchars
= (STRPTR
) tag
->ti_Data
;
463 case MUIA_Floattext_TabSize
:
464 data
->tabsize
= tag
->ti_Data
;
468 case MUIA_Floattext_Text
:
470 data
->text
= StrDup((STRPTR
) tag
->ti_Data
);
477 if (changed
) // To avoid recursion
479 if (data
->tabsize
== 0)
481 else if (data
->tabsize
> 20)
487 return DoSuperMethodA(cl
, obj
, (Msg
) msg
);
490 /**************************************************************************
492 **************************************************************************/
493 IPTR
Floattext__MUIM_Draw(struct IClass
*cl
, Object
*obj
,
494 struct MUIP_Draw
*msg
)
496 struct Floattext_DATA
*data
= INST_DATA(cl
, obj
);
498 if (!data
->typesetting
)
499 DoSuperMethodA(cl
, obj
, (Msg
) msg
);
501 if ((msg
->flags
& MADF_DRAWOBJECT
) != 0 && data
->oldwidth
!= _width(obj
))
503 data
->oldwidth
= _width(obj
);
510 #if ZUNE_BUILTIN_FLOATTEXT
511 BOOPSI_DISPATCHER(IPTR
, Floattext_Dispatcher
, cl
, obj
, msg
)
513 switch (msg
->MethodID
)
516 return Floattext__OM_NEW(cl
, obj
, msg
);
518 return Floattext__OM_DISPOSE(cl
, obj
, msg
);
520 return Floattext__OM_GET(cl
, obj
, msg
);
522 return Floattext__OM_SET(cl
, obj
, msg
);
524 return Floattext__MUIM_Draw(cl
, obj
, (struct MUIP_Draw
*)msg
);
527 return DoSuperMethodA(cl
, obj
, msg
);
530 BOOPSI_DISPATCHER_END
532 const struct __MUIBuiltinClass _MUI_Floattext_desc
=
536 sizeof(struct Floattext_DATA
),
537 (void *) Floattext_Dispatcher
539 #endif /* ZUNE_BUILTIN_FLOATTEXT */