2 * WINGs WMText multi-line/font/color/graphic text widget
4 * Copyright (c) 1999-2000 Nwanua Elumeze
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 /* README README README README README README README
22 * Nwanua: dont use // style comments please!
23 * It doesnt work in lots of compilers out there :/
25 * README README README README README README README
29 #include <X11/keysym.h>
30 #include <X11/Xatom.h>
38 use currentTextBlock
and neighbours
for fast paint
and layout
40 WMGetTextStreamAll
... WMGetTextStream
WMGetTextSelection(if(selected
) )
42 the bitfield arrangement in
this code assumes a little
-endian
43 machine
... might need a __BIG_ENDIAN__ define
for arranging
44 the bitfields efficiently
for those big boys
.
46 make a file named fontman
.c
, put that kind of
47 stuff in there
and not put the APIs in WINGs
.h
48 WMGetFontItalic() should some day be part of the font manager
49 instead
, just put a bunch of
extern WMGetFontbla in the top of wtext
.c
58 /* a Section is a section of a TextBlock that describes what parts
59 of a TextBlock has be layout on which "line"...
60 o this greatly aids redraw, scroll and selection.
61 o this is created during layoutLine, but may be later modified.
62 o there may be many regions per TextBlock, hence the array */
64 int x
, y
; /* where to draw it from */
65 int w
, h
; /* it's width and height (to aid selection) */
67 unsigned short begin
, end
; /* what part of the text block */
71 /* a TextBlock is a doubly-linked list of TextBlocks containing:
72 o text for the block, color and font
73 o or a pointer to the widget and the (text) description for its graphic
76 typedef struct _TextBlock
{
77 struct _TextBlock
*next
; /* next text block in linked list */
78 struct _TextBlock
*prior
; /* prior text block in linked list */
80 char *text
; /* pointer to 8- or 16-bit text */
81 /* or to the object's description */
83 WMFont
*font
; /* the font */
84 WMWidget
*widget
; /* the embedded widget */
85 } d
; /* description */
87 WMColor
*color
; /* the color */
88 Section
*sections
; /* the region for layouts (a growable array) */
89 /* an _array_! of size _nsections_ */
91 unsigned short used
; /* number of chars in this block */
92 unsigned short allocated
; /* size of allocation (in chars) */
94 unsigned int first
:1; /* first TextBlock in paragraph */
95 unsigned int blank
:1; /* ie. blank paragraph */
96 unsigned int kanji
:1; /* is of 16-bit characters or not */
97 unsigned int graphic
:1; /* embedded object or text: text=0 */
98 unsigned int underlined
:1; /* underlined or not */
99 unsigned int nsections
:8; /* over how many "lines" a TexBlock wraps */
100 int script
:8; /* script in points: negative for subscript */
101 unsigned int marginN
:10; /* which of the margins in WMText to use */
102 unsigned int RESERVED
:1;
106 /* somehow visible.h beats the hell outta visible.size.height :-) */
115 typedef struct W_Text
{
116 W_Class widgetClass
; /* the class number of this widget */
117 W_View
*view
; /* the view referring to this instance */
119 WMRuler
*ruler
; /* the ruler subwiget to manipulate paragraphs */
121 WMScroller
*vS
; /* the vertical scroller */
122 int vpos
; /* the current vertical position */
123 int prevVpos
; /* the previous vertical position */
125 WMScroller
*hS
; /* the horizontal scroller */
126 int hpos
; /* the current horizontal position */
127 int prevHpos
; /* the previous horizontal position */
128 /* in short: tPtr->hS?nowrap:wrap */
130 WMFont
*dFont
; /* the default font */
131 WMColor
*dColor
; /* the default color */
132 WMPixmap
*dBulletPix
; /* the default pixmap for bullets */
134 GC bgGC
; /* the background GC to draw with */
135 GC fgGC
; /* the foreground GC to draw with */
136 Pixmap db
; /* the buffer on which to draw */
138 WMRulerMargins
*margins
;/* a (growable) array of margins to be used */
139 /* by the various TextBlocks */
141 myRect visible
; /* the actual rectangle that can be drawn into */
142 myRect sel
; /* the selection rectangle */
143 int docWidth
; /* the width of the entire document */
144 int docHeight
; /* the height of the entire document */
147 TextBlock
*firstTextBlock
;
148 TextBlock
*lastTextBlock
;
149 TextBlock
*currentTextBlock
;
152 WMBag
*gfxItems
; /* a nice bag containing graphic items */
154 WMPoint clicked
; /* where in the _document_ was clicked */
155 unsigned short tpos
; /* the character position in the currentTextBlock */
156 unsigned short RESERVED
;/* space taker upper... */
163 unsigned int monoFont
:1; /* whether to ignore formats */
164 unsigned int focused
:1; /* whether this instance has input focus */
165 unsigned int editable
:1; /* "silly user, you can't edit me" */
166 unsigned int ownsSelection
:1; /* "I ownz the current selection!" */
167 unsigned int pointerGrabbed
:1;/* "heh, gib me pointer" */
168 unsigned int buttonHeld
:1; /* the user is holding down the button */
169 unsigned int waitingForSelection
:1; /* dum dee dumm... */
170 unsigned int extendSelection
:1; /* shift-drag to select more regions */
172 unsigned int rulerShown
:1; /* whether the ruler is shown or not */
173 unsigned int frozen
:1; /* whether screen updates are to be made */
174 unsigned int cursorShown
:1; /* whether to show the cursor */
175 unsigned int clickPos
:1; /* clicked before=0/after=1 a graphic: */
176 /* within counts as after too */
178 unsigned int ignoreNewLine
:1;/* "bleh XK_Return" ignore it when typed */
179 unsigned int laidOut
:1; /* have the TextBlocks all been laid out */
180 unsigned int prepend
:1; /* prepend=1, append=0 (for parsers) */
181 WMAlignment alignment
:2; /* the alignment for text */
182 WMReliefType relief
:3; /* the relief to display with */
183 unsigned int RESERVED
:4;
184 unsigned int nmargins
:10; /* the number of margin arrays */
188 static char *default_bullet
[] = {
190 " c None s None", ". c black",
191 "X c white", "o c #808080",
200 /* done purely for speed ... mostly same as WMWidthOfString */
201 static inline unsigned int
202 myWidthOfString(WMFont
*font
, char *text
, unsigned int length
)
204 if (font
->notFontSet
)
205 return XTextWidth(font
->font
.normal
, text
, length
);
207 XRectangle rect
, AIXsucks
;
208 XmbTextExtents(font
->font
.set
, text
, length
, &AIXsucks
, &rect
);
215 paintText(Text
*tPtr
)
217 TextBlock
*tb
= tPtr
->firstTextBlock
;
221 int len
, y
, c
, s
, done
=False
;
223 WMScreen
*scr
= tPtr
->view
->screen
;
224 Display
*dpy
= tPtr
->view
->screen
->display
;
225 Window win
= tPtr
->view
->window
;
229 if(!tPtr
->view
->flags
.realized
|| !tPtr
->db
)
232 XFillRectangle(dpy
, tPtr
->db
, tPtr
->bgGC
,
233 0, 0, tPtr
->visible
.w
, tPtr
->visible
.h
);
236 tb
= tPtr
->firstTextBlock
;
241 if(tPtr
->flags
.ownsSelection
) {
242 greyGC
= WMColorGC(WMGrayColor(scr
));
243 //XFillRectangle(dpy, tPtr->db, greyGC,
244 // tPtr->sel.x, tPtr->sel.y-tPtr->vpos, tPtr->sel.w, tPtr->sel.h);
245 // XDrawRectangle(dpy, tPtr->db, tPtr->fgGC,
246 // tPtr->sel.x, tPtr->sel.y-tPtr->vpos, tPtr->sel.w, tPtr->sel.h);
252 if(!tb
->sections
|| (!tPtr
->flags
.monoFont
&& tb
->graphic
)) {
257 for(s
=0; s
<tb
->nsections
&& !done
; s
++) {
260 if(tb
->sections
[s
]._y
> tPtr
->vpos
+ tPtr
->visible
.h
) {
265 if( tb
->sections
[s
].y
+ tb
->sections
[s
].h
< tPtr
->vpos
)
268 if(tPtr
->flags
.monoFont
) {
273 gc
= WMColorGC(tb
->color
);
276 if(tPtr
->flags
.ownsSelection
) {
278 if(prev_y
!= tb
->sections
[s
]._y
279 && (tb
->sections
[s
]._y
>= tPtr
->sel
.y
)
280 && (tb
->sections
[s
]._y
+ tb
->sections
[s
].h
281 <= tPtr
->sel
.y
+ tPtr
->sel
.h
)) {
282 XFillRectangle(dpy
, tPtr
->db
, greyGC
,
284 tPtr
->visible
.y
+ tb
->sections
[s
]._y
- tPtr
->vpos
,
285 tPtr
->visible
.w
, tb
->sections
[s
].h
);
287 } else if( prev_y
!= tb
->sections
[s
]._y
288 && (tb
->sections
[s
]._y
<= tPtr
->sel
.y
)
289 && (tb
->sections
[s
]._y
+ tb
->sections
[s
].h
291 && (tPtr
->sel
.x
>= tb
->sections
[s
].x
)
292 && (tPtr
->sel
.y
+ tPtr
->sel
.h
293 >= tb
->sections
[s
]._y
+ tb
->sections
[s
].h
)) {
294 XFillRectangle(dpy
, tPtr
->db
, greyGC
,
296 tPtr
->visible
.y
+ tb
->sections
[s
]._y
- tPtr
->vpos
,
297 tPtr
->visible
.w
- tPtr
->sel
.x
, tb
->sections
[s
].h
);
299 } else if(prev_y
!= tb
->sections
[s
]._y
300 && (tb
->sections
[s
]._y
<= tPtr
->sel
.y
+ tPtr
->sel
.h
)
301 && (tb
->sections
[s
]._y
>= tPtr
->sel
.y
)) {
302 XFillRectangle(dpy
, tPtr
->db
, greyGC
,
304 tPtr
->visible
.y
+ tb
->sections
[s
]._y
- tPtr
->vpos
,
305 tPtr
->sel
.x
+ tPtr
->sel
.w
-tPtr
->visible
.x
,
308 } else if( prev_y
!= tb
->sections
[s
]._y
309 && (tb
->sections
[s
]._y
<= tPtr
->sel
.y
)
310 && (tb
->sections
[s
]._y
+ tb
->sections
[s
].h
311 >= tPtr
->sel
.y
+ tPtr
->sel
.h
) ) {
312 XFillRectangle(dpy
, tPtr
->db
, greyGC
,
314 tPtr
->visible
.y
+ tb
->sections
[s
]._y
- tPtr
->vpos
,
315 tPtr
->sel
.w
,tb
->sections
[s
].h
);
320 prev_y
= tb
->sections
[s
]._y
;
322 len
= tb
->sections
[s
].end
- tb
->sections
[s
].begin
;
323 text
= &(tb
->text
[tb
->sections
[s
].begin
]);
324 y
= tb
->sections
[s
].y
- tPtr
->vpos
;
325 WMDrawString(scr
, tPtr
->db
, gc
, font
,
326 tb
->sections
[s
].x
, y
, text
, len
);
329 XDrawLine(dpy
, tPtr
->db
, gc
,
330 tb
->sections
[s
].x
, y
+ font
->y
+ 1,
331 tb
->sections
[s
].x
+ tb
->sections
[s
].w
, y
+ font
->y
+ 1);
336 tb
= (!done
? tb
->next
: NULL
);
340 c
= WMGetBagItemCount(tPtr
->gfxItems
);
341 if(c
> 0 && !tPtr
->flags
.monoFont
) {
345 tb
= (TextBlock
*)WMGetFromBag(tPtr
->gfxItems
, j
);
346 if(!tb
|| !tb
->sections
)
349 if(tb
->sections
[0]._y
+ tb
->sections
[0].h
351 || tb
->sections
[0]._y
352 >= tPtr
->vpos
+ tPtr
->visible
.h
) {
354 if((W_VIEW(wdt
))->flags
.mapped
) {
358 if(!(W_VIEW(wdt
))->flags
.mapped
) {
361 (W_VIEW(wdt
))->window
);
364 if(tPtr
->flags
.ownsSelection
&& 0
365 //&& (tb->sections[s]._y >= tPtr->sel.y)
366 //&& (tb->sections[s]._y + tb->sections[s].h
367 ){ // <= tPtr->sel.y + tPtr->sel.h)) {
368 XFillRectangle(dpy
, tPtr
->db
, greyGC
,
369 tb
->sections
[0].x
, tb
->sections
[0].y
- tPtr
->vpos
,
370 tb
->sections
[0].w
, tb
->sections
[0].h
);
373 WMMoveWidget(wdt
, 3 + tb
->sections
[0].x
+ tPtr
->visible
.x
,
374 tb
->sections
[0].y
- tPtr
->vpos
);
377 XDrawLine(dpy
, tPtr
->db
, WMColorGC(tb
->color
),
379 tb
->sections
[0].y
+ WMWidgetHeight(wdt
) + 1,
380 tb
->sections
[0].x
+ tb
->sections
[0].w
,
381 tb
->sections
[0].y
+ WMWidgetHeight(wdt
) + 1);
389 XCopyArea(dpy
, tPtr
->db
, win
, tPtr
->bgGC
,
391 tPtr
->visible
.w
, tPtr
->visible
.h
,
392 tPtr
->visible
.x
, tPtr
->visible
.y
);
394 W_DrawRelief(scr
, win
, 0, 0,
395 tPtr
->view
->size
.width
, tPtr
->view
->size
.height
,
398 if(tPtr
->ruler
&& tPtr
->flags
.rulerShown
)
401 tPtr
->view
->size
.width
-4, 42);
404 XFillRectangle(tPtr->view->screen->display, tPtr->view->window,
406 2, tPtr->view->size.height-3,
407 tPtr->view->size.width-4, 3);
414 cursorToTextPosition(Text
*tPtr
, int x
, int y
)
416 TextBlock
*tb
= NULL
;
417 int done
=False
, s
, len
, _w
, _y
, dir
=1; /* 1 == "down" */
422 y
+= tPtr
->vpos
- tPtr
->visible
.y
;
425 x
-= tPtr
->visible
.x
-2;
431 /* first, which direction?, most likely, newly clicked
432 position will be close to previous */
433 tb
= tPtr
->currentTextBlock
;
435 tb
= tPtr
->firstTextBlock
;
436 if(!tb
|| !tb
->sections
)
439 if(y
< tb
->sections
[0].y
)
442 //tb = tPtr->firstTextBlock;
446 if(y
== tb
->sections
[0].y
)
447 goto _doneV
; /* yeah yeah, goto, whatever... :-P */
449 /* get the first section of the first TextBlock based on v. position */
452 if(tPtr
->flags
.monoFont
&& tb
->graphic
) {
457 printf("tb %p t[%c] blank%d graphic %d\n", tb
,
458 *tb
->text
, tb
->blank
, tb
->graphic
);
460 printf("we have a bad thing!\n");
463 s
= (dir
? 0 : tb
->nsections
-1);
464 while( (dir
? (s
<tb
->nsections
) : (s
>=0) )) {
465 if( y
>= tb
->sections
[s
]._y
466 && y
<= tb
->sections
[s
]._y
+ tb
->sections
[s
].h
) {
472 if(!done
) tb
= (dir
? tb
->next
: tb
->prior
);
476 /* we have the line, which TextBlock on that line is it? */
478 _y
= tb
->sections
[s
]._y
;
483 if(_y
!= tb
->sections
[s
]._y
)
487 _w
= WMWidgetWidth(tb
->d
.widget
);
489 text
= &(tb
->text
[tb
->sections
[s
].begin
]);
490 len
= tb
->sections
[s
].end
- tb
->sections
[s
].begin
;
492 _w
= myWidthOfString(font
, text
, len
);
494 if(tb
->sections
[s
].x
+ _w
>= x
)
500 /* we have said TextBlock, now where within it? */
501 if(tb
&& !tb
->graphic
) {
502 int begin
= tb
->sections
[s
].begin
;
503 int end
= tb
->sections
[s
].end
;
506 text
= &(tb
->text
[begin
]);
509 _w
= x
- tb
->sections
[s
].x
;
512 while(i
<len
&& myWidthOfString(font
, text
, i
+1) < _w
)
516 tPtr
->tpos
= (i
<tb
->used
)?i
:tb
->used
;
520 //tb = tPtr->firstTextBlock;
521 tPtr
->currentTextBlock
= tb
;
523 if(tb
&&tb
->graphic
) printf("graphic\n");
527 updateScrollers(Text
*tPtr
)
531 if(tPtr
->docHeight
< tPtr
->visible
.h
) {
532 WMSetScrollerParameters(tPtr
->vS
, 0, 1);
535 float vmax
= (float)(tPtr
->docHeight
);
536 WMSetScrollerParameters(tPtr
->vS
,
537 ((float)tPtr
->vpos
)/(vmax
- (float)tPtr
->visible
.h
),
538 (float)tPtr
->visible
.h
/vmax
);
540 } else tPtr
->vpos
= 0;
547 scrollersCallBack(WMWidget
*w
, void *self
)
549 Text
*tPtr
= (Text
*)self
;
554 if(!tPtr
->view
->flags
.realized
) return;
559 vmax
= (float)(tPtr
->docHeight
);
560 height
= tPtr
->visible
.h
;
562 which
= WMGetScrollerHitPart(tPtr
->vS
);
564 case WSDecrementLine
:
566 if(tPtr
->vpos
>16) tPtr
->vpos
-=16;
570 case WSIncrementLine
: {
571 int limit
= tPtr
->docHeight
- height
;
572 if(tPtr
->vpos
< limit
) {
573 if(tPtr
->vpos
<limit
-16) tPtr
->vpos
+=16;
574 else tPtr
->vpos
=limit
;
577 case WSDecrementPage
:
578 tPtr
->vpos
-= height
;
584 printf("dimple needs to jump to mouse location ;-/\n");
586 case WSIncrementPage
:
587 tPtr
->vpos
+= height
;
588 if(tPtr
->vpos
> (tPtr
->docHeight
- height
))
589 tPtr
->vpos
= tPtr
->docHeight
- height
;
592 printf("dimple needs to jump to mouse location ;-/\n");
597 tPtr
->vpos
= WMGetScrollerValue(tPtr
->vS
)
598 * (float)(tPtr
->docHeight
- height
);
604 printf("WSNoPart, WSKnobSlot\n");
606 float vmax
= (float)(tPtr
->docHeight
);
607 ((float)tPtr
->vpos
)/(vmax
- (float)tPtr
->visible
.h
),
608 (float)tPtr
->visible
.h
/vmax
;
609 dimple
=where mouse is
.
613 scroll
= (tPtr
->vpos
!= tPtr
->prevVpos
);
614 tPtr
->prevVpos
= tPtr
->vpos
;
624 XClearArea(tPtr->view->screen->display, tPtr->view->window, 22, 47,
625 tPtr->view->size.width-24, tPtr->view->size.height-49, True);
627 XClearArea(tPtr->view->screen->display, tPtr->view->window, 22, 2,
628 tPtr->view->size.width-24, tPtr->view->size.height-4, True);
631 if(which
== WSDecrementLine
|| which
== WSIncrementLine
)
632 updateScrollers(tPtr
);
641 unsigned short begin
, end
; /* what part of the text block */
647 layOutLine(Text
*tPtr
, myLineItems
*items
, int nitems
, int x
, int y
,
648 int pwidth
, WMAlignment align
)
650 int i
, j
=0; /* j = justification */
651 int line_width
= 0, line_height
=0, max_descent
=0;
657 TextBlock
*tbsame
=NULL
;
659 for(i
=0; i
<nitems
; i
++) {
663 if(!tPtr
->flags
.monoFont
) {
664 WMWidget
*wdt
= tb
->d
.widget
;
665 line_height
= WMAX(line_height
, WMWidgetHeight(wdt
));
667 line_width
+= WMWidgetWidth(wdt
);
672 font
= (tPtr
->flags
.monoFont
)?tPtr
->dFont
: tb
->d
.font
;
673 max_descent
= WMAX(max_descent
, font
->height
-font
->y
);
674 line_height
= WMAX(line_height
, font
->height
); //+font->height-font->y);
675 text
= &(tb
->text
[items
[i
].begin
]);
676 len
= items
[i
].end
- items
[i
].begin
;
678 line_width
+= myWidthOfString(font
, text
, len
);
682 if(align
== WARight
) {
683 j
= pwidth
- line_width
;
684 } else if (align
== WACenter
) {
685 j
= (int) ((float)(pwidth
- line_width
))/2.0;
690 for(i
=0; i
<nitems
; i
++) {
693 if(tbsame
== tb
) { /*extend it, since it's on same line */
694 tb
->sections
[tb
->nsections
-1].end
= items
[i
].end
;
696 tb
->sections
= wrealloc(tb
->sections
,
697 (++tb
->nsections
)*sizeof(Section
));
698 tb
->sections
[tb
->nsections
-1]._y
= y
;
699 tb
->sections
[tb
->nsections
-1].x
= x
+j
;
700 tb
->sections
[tb
->nsections
-1].h
= line_height
;
701 tb
->sections
[tb
->nsections
-1].begin
= items
[i
].begin
;
702 tb
->sections
[tb
->nsections
-1].end
= items
[i
].end
;
707 if(!tPtr
->flags
.monoFont
) {
708 WMWidget
*wdt
= tb
->d
.widget
;
709 tb
->sections
[tb
->nsections
-1].y
= 1 +max_descent
+
710 y
+ line_height
- WMWidgetHeight(wdt
);
711 tb
->sections
[tb
->nsections
-1].w
= WMWidgetWidth(wdt
);
712 x
+= tb
->sections
[tb
->nsections
-1].w
;
715 font
= (tPtr
->flags
.monoFont
)? tPtr
->dFont
: tb
->d
.font
;
716 len
= items
[i
].end
- items
[i
].begin
;
718 text
= &(tb
->text
[items
[i
].begin
]);
720 tb
->sections
[tb
->nsections
-1].y
= y
+line_height
-font
->y
;
721 tb
->sections
[tb
->nsections
-1].w
=
722 myWidthOfString(font
,
723 &(tb
->text
[tb
->sections
[tb
->nsections
-1].begin
]),
724 tb
->sections
[tb
->nsections
-1].end
-
725 tb
->sections
[tb
->nsections
-1].begin
);
727 x
+= myWidthOfString(font
, text
, len
);
733 return line_height
+(gfx
?10:0);
739 output(char *ptr
, int len
)
744 printf(" s is [%s] (%d)\n", s
, strlen(s
));
749 #define MAX_TB_PER_LINE 64
752 layOutDocument(Text
*tPtr
)
755 myLineItems items
[MAX_TB_PER_LINE
];
756 WMAlignment align
= WALeft
;
758 Bool lhc
= !tPtr
->flags
.laidOut
; /* line height changed? */
761 int nitems
=0, x
=0, y
=0, line_width
= 0, width
=0;
762 int pwidth
= tPtr
->visible
.w
- tPtr
->visible
.x
;
764 char *start
=NULL
, *mark
=NULL
;
767 if(!(tb
= tPtr
->firstTextBlock
)) {
768 printf("clear view... *pos=0\n");
772 if(0&&tPtr
->flags
.laidOut
) {
773 tb
= tPtr
->currentTextBlock
;
774 if(tb
->sections
&& tb
->nsections
>0)
775 prev_y
= tb
->sections
[tb
->nsections
-1]._y
;
777 printf("1 prev_y %d \n", prev_y
);
779 /* search backwards for textblocks on same line */
781 if(!tb
->sections
|| tb
->nsections
<1) {
782 tb
= tPtr
->firstTextBlock
;
785 if(tb
->sections
[tb
->nsections
-1]._y
!= prev_y
) {
789 // prev_y = tb->sections[tb->nsections-1]._y;
792 y
= 0;//tb->sections[tb->nsections-1]._y;
793 printf("2 prev_y %d \n\n", tb
->sections
[tb
->nsections
-1]._y
);
799 if(tb
->sections
&& tb
->nsections
>0) {
806 y
+= layOutLine(tPtr
, items
, nitems
, x
, y
, pwidth
, align
);
807 x
= 0;//tPtr->visible.x+2;
813 if(!tPtr
->flags
.monoFont
) {
814 width
= WMWidgetWidth(tb
->d
.widget
);
815 if(width
> pwidth
)printf("rescale graphix to fit?\n");
817 if(line_width
>= pwidth
- x
818 || nitems
>= MAX_TB_PER_LINE
) {
819 y
+= layOutLine(tPtr
, items
, nitems
, x
, y
,
822 x
= 0;//tPtr->visible.x+2;
826 items
[nitems
].tb
= tb
;
827 items
[nitems
].begin
= 0;
828 items
[nitems
].end
= 0;
832 } else if((start
= tb
->text
)) {
834 font
= tPtr
->flags
.monoFont
?tPtr
->dFont
:tb
->d
.font
;
837 mark
= strchr(start
, ' ');
839 end
+= (int)(mark
-start
)+1;
842 end
+= strlen(start
);
848 width
= myWidthOfString(font
,
849 &tb
->text
[begin
], end
-begin
);
851 if(width
> pwidth
) { /* break this tb up */
852 char *t
= &tb
->text
[begin
];
853 int l
=end
-begin
, i
=0;
855 width
= myWidthOfString(font
, t
, ++i
);
856 } while (width
< pwidth
&& i
< l
);
858 if(start
) // and since (nil)-4 = 0xfffffffd
866 if((line_width
>= pwidth
- x
)
867 || nitems
>= MAX_TB_PER_LINE
) {
868 y
+= layOutLine(tPtr
, items
, nitems
, x
, y
,
871 x
= 0; //tPtr->visible.x+2;
875 items
[nitems
].tb
= tb
;
876 items
[nitems
].begin
= begin
;
877 items
[nitems
].end
= end
;
888 y
+= layOutLine(tPtr
, items
, nitems
, x
, y
, pwidth
, align
);
890 tPtr
->docHeight
= y
+10;
891 updateScrollers(tPtr
);
893 tPtr
->flags
.laidOut
= True
;
899 textDidResize(W_ViewDelegate
*self
, WMView
*view
)
901 Text
*tPtr
= (Text
*)view
->self
;
902 unsigned short w
= WMWidgetWidth(tPtr
);
903 unsigned short h
= WMWidgetHeight(tPtr
);
904 unsigned short rh
= 0, vw
= 0;
906 if(tPtr
->ruler
&& tPtr
->flags
.rulerShown
) {
907 WMMoveWidget(tPtr
->ruler
, 20, 2);
908 WMResizeWidget(tPtr
->ruler
, w
- 22, 40);
913 WMMoveWidget(tPtr
->vS
, 1, rh
+ 2);
914 WMResizeWidget(tPtr
->vS
, 20, h
- rh
- 3);
916 WMSetRulerOffset(tPtr
->ruler
, 22);
917 } else WMSetRulerOffset(tPtr
->ruler
, 2);
921 WMMoveWidget(tPtr
->hS
, vw
, h
- 21);
922 WMResizeWidget(tPtr
->hS
, w
- vw
- 1, 20);
924 WMMoveWidget(tPtr
->hS
, vw
+1, h
- 21);
925 WMResizeWidget(tPtr
->hS
, w
- vw
- 2, 20);
929 tPtr
->visible
.x
= (tPtr
->vS
)?22:0;
930 tPtr
->visible
.y
= (tPtr
->ruler
&& tPtr
->flags
.rulerShown
)?43:3;
931 tPtr
->visible
.w
= tPtr
->view
->size
.width
- tPtr
->visible
.x
- 12;
932 tPtr
->visible
.h
= tPtr
->view
->size
.height
- tPtr
->visible
.y
;
933 tPtr
->visible
.h
-= (tPtr
->hS
)?20:0;
935 tPtr
->margins
[0].left
= tPtr
->margins
[0].right
= tPtr
->visible
.x
;
936 tPtr
->margins
[0].body
= tPtr
->visible
.x
;
937 tPtr
->margins
[0].right
= tPtr
->visible
.w
;
939 WMRefreshText(tPtr
, tPtr
->vpos
, tPtr
->hpos
);
942 //if(tPtr->view->flags.realized)
943 //XFreePixmap(tPtr->view->screen->display, tPtr->db);
946 //if(size did not change
947 if(tPtr
->visible
.w
< 10) tPtr
->visible
.w
= 10;
948 if(tPtr
->visible
.h
< 10) tPtr
->visible
.h
= 10;
950 tPtr
->db
= XCreatePixmap(tPtr
->view
->screen
->display
,
951 tPtr
->view
->window
, tPtr
->visible
.w
,
952 tPtr
->visible
.h
, tPtr
->view
->screen
->depth
);
957 W_ViewDelegate _TextViewDelegate
=
965 /* nice, divisble-by-16 memory */
966 static inline unsigned short
967 reqBlockSize(unsigned short requested
)
969 return requested
+16-(requested
%16);
973 deleteTextInteractively(Text
*tPtr
, KeySym ksym
)
975 printf("deleting %ld\n", ksym
);
979 insertTextInteractively(Text
*tPtr
, char *text
, int len
)
983 // Chunk *tb=NULL, *newtb=NULL;
984 int height
= -23; /* should only be changed upon newline */
989 if(!tPtr
->flags
.editable
|| len
< 1 || !text
990 || (*text
== '\n' && tPtr
->flags
.ignoreNewLine
))
993 tb
= tPtr
->currentTextBlock
;
995 WMAppendTextStream(tPtr
, text
);
996 WMRefreshText(tPtr
, 0, 0);
1004 mark
= strchr(text
, '\n');
1006 len
= (int)(mark
-text
);
1010 printf("problem pasting text %d\n", len
);
1016 font
= (tPtr
->flags
.monoFont
|| !tb
)?tPtr
->dFont
:tb
->d
.font
;
1021 if(tb
) { /* there's a tb (or part of it) to detach from old */
1022 int current
= WMGetTextCurrentChunk(tPtr
);
1023 if(tPtr
->tpos
<=0) { /* at start of tb */
1024 if(current
<1) { /* the first tb... make old para blank */
1027 putParagraphOnPixmap(tPtr
, para
, True
);
1028 } else { /* not first tb... */
1029 printf("cut me out \n");
1031 } else if(tPtr
->tpos
< tb
->chars
&& tb
->type
== ctText
) {
1032 /* not at start of tb */
1033 char text
[tb
->chars
-tPtr
->tpos
+1];
1036 text
[i
] = tb
->text
[tPtr
->tpos
+i
];
1037 } while(++i
< tb
->chars
-tPtr
->tpos
);
1039 newtb
= (tPtr
->funcs
.createTChunk
) (text
, i
, tb
->font
,
1040 tb
->color
, tb
->script
, tb
->ul
);
1041 newtb
->next
= tb
->next
;
1043 /* might want to demalloc for LARGE cuts */
1044 //calcParaExtents(tPtr, para);
1045 para
->height
= putParagraphOnPixmap(tPtr
, para
, True
);
1046 //putParagraphOnPixmap(tPtr, para, True);
1047 } else if(tPtr
->tpos
>= tb
->chars
) {
1049 WMSetTextCurrentChunk(tPtr
, current
-1);
1050 prev
= tPtr
->currentChunk
;
1054 putParagraphOnPixmap(tPtr
, para
, True
);
1056 } else newtb
= NULL
;
1058 if(para
) /* the preceeding one */
1059 new_top
= para
->bottom
;
1061 WMAppendTextStream(tPtr
, "\n");
1062 para
= tPtr
->currentPara
;
1065 tPtr
->currentChunk
= newtb
;
1067 para
->top
= new_top
;
1068 calcParaExtents(tPtr
, para
);
1069 height
= para
->height
;
1072 WMAppendTextStream(tPtr
, text
);
1073 para
= tPtr
->currentPara
;
1074 } else if(!para
->tbs
|| !tb
) {
1075 //WMPrependTextStream(tPtr, text);
1076 WMAppendTextStream(tPtr
, text
);
1077 } else if(tb
->type
== ctImage
) {
1078 WMPrependTextStream(tPtr
, text
);
1080 printf("\n\nprepe\n\n");
1082 if(tPtr
->tpos
> tb
->chars
) {
1083 printf("\n\nmore\n\n");
1084 tPtr
->tpos
= tb
->chars
;
1088 printf("len is %d\n", len
);
1089 if(tb
->used
+len
>= tb
->allocated
) {
1090 tb
->allocated
= reqBlockSize(tb
->used
+len
);
1091 printf("ralloced %d\n", tb
->allocated
);
1092 tb
->text
= wrealloc(tb
->text
, tb
->allocated
);
1096 memmove(tb
->text
, text
, len
);
1101 memmove(&(tb
->text
[tPtr
->tpos
+len
]), &tb
->text
[tPtr
->tpos
],
1102 tb
->used
-tPtr
->tpos
+1);
1103 memmove(&tb
->text
[tPtr
->tpos
], text
, len
);
1107 w
= myWidthOfString(font
, text
, len
);
1111 WMAppendTextStream(tPtr
, mark
);
1112 WMRefreshText(tPtr
, tPtr
->vpos
, tPtr
->hpos
);
1113 printf("paste: use prev/post chunk's fmt...\n");
1115 layOutDocument(tPtr
);
1119 //doc->clickstart.cursor.x +=
1120 //myWidthOfString(tb->fmt->font, text,len);
1128 selectRegion(Text
*tPtr
, int x
, int y
)
1133 if(y
>10) y
-= 10; /* the original offset */
1135 x
-= tPtr
->visible
.x
-2;
1138 tPtr
->sel
.x
= WMAX(0, WMIN(tPtr
->clicked
.x
, x
));
1139 tPtr
->sel
.w
= abs(tPtr
->clicked
.x
- x
);
1140 tPtr
->sel
.y
= WMAX(0, WMIN(tPtr
->clicked
.y
, y
));
1141 tPtr
->sel
.h
= abs(tPtr
->clicked
.y
- y
);
1143 tPtr
->flags
.ownsSelection
= True
;
1149 pasteText(WMView
*view
, Atom selection
, Atom target
, Time timestamp
,
1150 void *cdata
, WMData
*data
)
1152 Text
*tPtr
= (Text
*)view
->self
;
1155 tPtr
->flags
.waitingForSelection
= False
;
1158 str
= (char*)WMDataBytes(data
);
1159 insertTextInteractively(tPtr
, str
, strlen(str
));
1162 str
= XFetchBuffer(tPtr
->view
->screen
->display
, &n
, 0);
1165 insertTextInteractively(tPtr
, str
, n
);
1172 releaseSelection(Text
*tPtr
)
1174 printf("I have %d selection\n", 1);
1175 tPtr
->flags
.ownsSelection
= False
;
1180 requestHandler(WMView
*view
, Atom selection
, Atom target
,
1181 void *cdata
, Atom
*type
)
1183 Text
*tPtr
= view
->self
;
1185 Display
*dpy
= tPtr
->view
->screen
->display
;
1186 Atom TEXT
= XInternAtom(dpy
, "TEXT", False
);
1187 Atom COMPOUND_TEXT
= XInternAtom(dpy
, "COMPOUND_TEXT", False
);
1190 if (target
== XA_STRING
|| target
== TEXT
|| target
== COMPOUND_TEXT
)
1191 return WMGetTextSelected(tPtr
);
1193 WMData
*data
= WMCreateDataWithBytes("bleh", 4);
1202 lostHandler(WMView
*view
, Atom selection
, void *cdata
)
1204 releaseSelection((WMText
*)view
->self
);
1207 static WMSelectionProcs selectionHandler
= {
1208 requestHandler
, lostHandler
, NULL
1212 _notification(void *observerData
, WMNotification
*notification
)
1214 WMText
*to
= (WMText
*)observerData
;
1215 WMText
*tw
= (WMText
*)WMGetNotificationClientData(notification
);
1217 lostHandler(to
->view
, XA_PRIMARY
, NULL
);
1221 handleTextKeyPress(Text
*tPtr
, XEvent
*event
)
1225 int control_pressed
= False
;
1228 if (((XKeyEvent
*) event
)->state
& ControlMask
)
1229 control_pressed
= True
;
1230 buffer
[XLookupString(&event
->xkey
, buffer
, 1, &ksym
, NULL
)] = '\0';
1237 printf("arrows %ld\n", ksym
);
1243 deleteTextInteractively(tPtr
, ksym
);
1250 if(buffer
[0] != '\0' && (buffer
[0] == '\n' || !control_pressed
))
1251 insertTextInteractively(tPtr
, buffer
, 1);
1252 else if(control_pressed
&& ksym
==XK_r
) {
1253 // Bool i = !tPtr->rulerShown; WMShowTextRuler(tPtr, i);
1254 // tPtr->rulerShown = i;
1255 printf("toggle ruler\n");
1257 else if(control_pressed
&& buffer
[0] == '\a')
1258 XBell(tPtr
->view
->screen
->display
, 0);
1261 if(tPtr
->flags
.ownsSelection
)
1262 releaseSelection(tPtr
);
1267 handleWidgetPress(XEvent
*event
, void *data
)
1269 TextBlock
*tb
= (TextBlock
*)data
;
1275 /* this little bit of nastiness here saves a boatload of trouble */
1276 w
= (WMWidget
*)(W_VIEW((W_VIEW(tb
->d
.widget
))->parent
))->self
;
1277 //if(W_CLASS(w) != WC_TextField && W_CLASS(w) != WC_Text)
1278 if( (((W_WidgetType
*)(w
))->widgetClass
) != WC_Text
)
1281 printf("%p clicked on tb %p wif: (%c)%c", tPtr
, tb
,
1282 tPtr
->firstTextBlock
->text
[0], tPtr
->firstTextBlock
->text
[1]);
1283 output(tb
->text
, tb
->used
);
1288 handleActionEvents(XEvent
*event
, void *data
)
1290 Text
*tPtr
= (Text
*)data
;
1291 Display
*dpy
= event
->xany
.display
;
1295 if(tPtr
->flags
.waitingForSelection
)
1298 switch (event
->type
) {
1300 ksym
= XLookupKeysym((XKeyEvent
*)event
, 0);
1301 if(ksym
== XK_Shift_R
|| ksym
== XK_Shift_L
) {
1302 tPtr
->flags
.extendSelection
= True
;
1305 if(!tPtr
->flags
.editable
|| tPtr
->flags
.buttonHeld
) {
1310 if (tPtr
->flags
.waitingForSelection
)
1312 if(tPtr
->flags
.focused
) {
1313 XGrabPointer(dpy
, W_VIEW(tPtr
)->window
, False
,
1314 PointerMotionMask
|ButtonPressMask
|ButtonReleaseMask
,
1315 GrabModeAsync
, GrabModeAsync
, None
,
1316 W_VIEW(tPtr
)->screen
->invisibleCursor
, CurrentTime
);
1317 tPtr
->flags
.pointerGrabbed
= True
;
1318 handleTextKeyPress(tPtr
, event
);
1323 ksym
= XLookupKeysym((XKeyEvent
*)event
, 0);
1324 if(ksym
== XK_Shift_R
|| ksym
== XK_Shift_L
) {
1325 tPtr
->flags
.extendSelection
= False
;
1327 //end modify flag so selection can be extended
1333 if(tPtr
->flags
.pointerGrabbed
) {
1334 tPtr
->flags
.pointerGrabbed
= False
;
1335 XUngrabPointer(dpy
, CurrentTime
);
1337 if((event
->xmotion
.state
& Button1Mask
)) {
1338 if(!tPtr
->flags
.ownsSelection
) {
1339 WMCreateSelectionHandler(tPtr
->view
, XA_PRIMARY
,
1340 event
->xbutton
.time
, &selectionHandler
, NULL
);
1341 tPtr
->flags
.ownsSelection
= True
;
1343 selectRegion(tPtr
, event
->xmotion
.x
, event
->xmotion
.y
);
1349 tPtr
->flags
.buttonHeld
= True
;
1350 if(tPtr
->flags
.extendSelection
) {
1351 selectRegion(tPtr
, event
->xmotion
.x
, event
->xmotion
.y
);
1354 if(event
->xbutton
.button
== Button1
) {
1355 if(tPtr
->flags
.ownsSelection
)
1356 releaseSelection(tPtr
);
1357 cursorToTextPosition(tPtr
, event
->xmotion
.x
, event
->xmotion
.y
);
1358 if (tPtr
->flags
.pointerGrabbed
) {
1359 tPtr
->flags
.pointerGrabbed
= False
;
1360 XUngrabPointer(dpy
, CurrentTime
);
1364 if(!tPtr
->flags
.focused
) {
1365 WMSetFocusToWidget(tPtr
);
1366 tPtr
->flags
.focused
= True
;
1370 if(event
->xbutton
.button
== WINGsConfiguration
.mouseWheelDown
)
1371 WMScrollText(tPtr
, -16);
1372 else if(event
->xbutton
.button
== WINGsConfiguration
.mouseWheelUp
)
1373 WMScrollText(tPtr
, 16);
1377 tPtr
->flags
.buttonHeld
= False
;
1378 if (tPtr
->flags
.pointerGrabbed
) {
1379 tPtr
->flags
.pointerGrabbed
= False
;
1380 XUngrabPointer(dpy
, CurrentTime
);
1383 if(event
->xbutton
.button
== WINGsConfiguration
.mouseWheelDown
1384 || event
->xbutton
.button
== WINGsConfiguration
.mouseWheelUp
)
1387 if(event
->xbutton
.button
== Button2
&& tPtr
->flags
.editable
) {
1390 if(!WMRequestSelection(tPtr
->view
, XA_PRIMARY
, XA_STRING
,
1391 event
->xbutton
.time
, pasteText
, NULL
)) {
1392 text
= XFetchBuffer(tPtr
->view
->screen
->display
, &n
, 0);
1395 insertTextInteractively(tPtr
, text
, n
-1);
1397 } else tPtr
->flags
.waitingForSelection
= True
;
1408 handleEvents(XEvent
*event
, void *data
)
1410 Text
*tPtr
= (Text
*)data
;
1412 switch(event
->type
) {
1414 if(!event
->xexpose
.count
&& tPtr
->view
->flags
.realized
)
1419 if (W_FocusedViewOfToplevel(W_TopLevelOfView(tPtr
->view
))!=tPtr
->view
)
1421 tPtr
->flags
.focused
= True
;
1425 tPtr
->flags
.focused
= False
;
1430 //for(...)WMRemoveTextParagraph(tPtr, para);
1439 clearText(Text
*tPtr
)
1442 if(!tPtr
->firstTextBlock
)
1445 while(tPtr
->currentTextBlock
)
1446 WMDestroyTextBlock(tPtr
, WMRemoveTextBlock(tPtr
));
1448 printf("yadda clearText\n");
1450 printf("remove the document\n");
1451 tPtr
->firstTextBlock
= NULL
;
1452 tPtr
->currentTextBlock
= NULL
;
1453 tPtr
->lastTextBlock
= NULL
;
1455 WMRefreshText(tPtr
, 0, 0);
1460 insertPlainText(WMText
*tPtr
, char *text
)
1474 mark
= strchr(start
, '\n');
1476 tb
= WMCreateTextBlockWithText(start
, tPtr
->dFont
,
1477 tPtr
->dColor
, True
, (int)(mark
-start
));
1480 if(start
&& strlen(start
)) {
1481 tb
= WMCreateTextBlockWithText(start
, tPtr
->dFont
,
1482 tPtr
->dColor
, False
, strlen(start
));
1487 if(tPtr
->flags
.prepend
)
1488 WMPrependTextBlock(tPtr
, tb
);
1490 WMAppendTextBlock(tPtr
, tb
);
1502 WMCreateText(WMWidget
*parent
)
1504 Text
*tPtr
= wmalloc(sizeof(Text
));
1506 printf("could not create text widget\n");
1511 printf("sizeof:\n");
1512 printf(" TextBlock %d\n", sizeof(TextBlock
));
1513 printf(" TextBlock *%d\n", sizeof(TextBlock
*));
1514 printf(" Section %d\n", sizeof(Section
));
1515 printf(" char * %d\n", sizeof(char *));
1516 printf(" void * %d\n", sizeof(void *));
1517 printf(" short %d\n", sizeof(short));
1518 printf(" Text %d\n", sizeof(Text
));
1521 memset(tPtr
, 0, sizeof(Text
));
1522 tPtr
->widgetClass
= WC_Text
;
1523 tPtr
->view
= W_CreateView(W_VIEW(parent
));
1525 perror("could not create text's view\n");
1529 tPtr
->view
->self
= tPtr
;
1530 tPtr
->view
->attribs
.cursor
= tPtr
->view
->screen
->textCursor
;
1531 tPtr
->view
->attribFlags
|= CWOverrideRedirect
| CWCursor
;
1532 W_ResizeView(tPtr
->view
, 250, 200);
1533 tPtr
->bgGC
= WMColorGC(tPtr
->view
->screen
->white
);
1534 tPtr
->fgGC
= WMColorGC(tPtr
->view
->screen
->black
);
1535 W_SetViewBackgroundColor(tPtr
->view
, tPtr
->view
->screen
->white
);
1542 //tPtr->dFont = WMCreateFont(tPtr->view->screen,
1543 // "-*-fixed-medium-r-normal--26-*-*-*-*-*-*-*");
1544 //"-sony-fixed-medium-r-normal--24-230-75-75-c-120-jisx0201.1976-0");
1545 // "-*-times-bold-r-*-*-12-*-*-*-*-*-*-*,"
1546 // "-*-fixed-medium-r-normal-*-12-*");
1548 tPtr
->dFont
= WMRetainFont(tPtr
->view
->screen
->normalFont
);
1550 tPtr
->dColor
= WMBlackColor(tPtr
->view
->screen
);
1552 tPtr
->view
->delegate
= &_TextViewDelegate
;
1554 WMCreateEventHandler(tPtr
->view
, ExposureMask
|StructureNotifyMask
1555 |EnterWindowMask
|LeaveWindowMask
|FocusChangeMask
,
1556 handleEvents
, tPtr
);
1558 WMCreateEventHandler(tPtr
->view
, ButtonReleaseMask
|ButtonPressMask
1559 |KeyReleaseMask
|KeyPressMask
|Button1MotionMask
,
1560 handleActionEvents
, tPtr
);
1562 WMAddNotificationObserver(_notification
, tPtr
, "_lostOwnership", tPtr
);
1565 tPtr
->firstTextBlock
= NULL
;
1566 tPtr
->lastTextBlock
= NULL
;
1567 tPtr
->currentTextBlock
= NULL
;
1570 tPtr
->gfxItems
= WMCreateArrayBag(4);
1572 tPtr
->parser
= NULL
;
1573 tPtr
->writer
= NULL
;
1575 tPtr
->sel
.x
= tPtr
->sel
.y
= 2;
1576 tPtr
->sel
.w
= tPtr
->sel
.h
= 0;
1578 tPtr
->clicked
.x
= tPtr
->clicked
.y
= 2;
1580 tPtr
->visible
.x
= tPtr
->visible
.y
= 2;
1581 tPtr
->visible
.h
= tPtr
->view
->size
.height
;
1582 tPtr
->visible
.w
= tPtr
->view
->size
.width
- 12;
1585 tPtr
->docHeight
= 0;
1586 tPtr
->dBulletPix
= WMCreatePixmapFromXPMData(tPtr
->view
->screen
,
1588 tPtr
->db
= (Pixmap
) NULL
;
1590 tPtr
->margins
= wmalloc(sizeof(WMRulerMargins
));
1591 tPtr
->margins
[0].left
= tPtr
->margins
[0].right
= tPtr
->visible
.x
;
1592 tPtr
->margins
[0].body
= tPtr
->visible
.x
;
1593 tPtr
->margins
[0].right
= tPtr
->visible
.w
;
1595 tPtr
->flags
.nmargins
= 1;
1596 tPtr
->flags
.rulerShown
= False
;
1597 tPtr
->flags
.monoFont
= !True
;
1598 tPtr
->flags
.focused
= False
;
1599 tPtr
->flags
.editable
= True
;
1600 tPtr
->flags
.ownsSelection
= False
;
1601 tPtr
->flags
.pointerGrabbed
= False
;
1602 tPtr
->flags
.buttonHeld
= False
;
1603 tPtr
->flags
.waitingForSelection
= False
;
1604 tPtr
->flags
.extendSelection
= False
;
1605 tPtr
->flags
.rulerShown
= False
;
1606 tPtr
->flags
.frozen
= False
;
1607 tPtr
->flags
.cursorShown
= True
;
1608 tPtr
->flags
.clickPos
= 1;
1609 tPtr
->flags
.ignoreNewLine
= False
;
1610 tPtr
->flags
.laidOut
= False
;
1611 tPtr
->flags
.prepend
= False
;
1612 tPtr
->flags
.relief
= WRFlat
;
1613 tPtr
->flags
.alignment
= WALeft
;
1620 WMPrependTextStream(WMText
*tPtr
, char *text
)
1624 //check for "{\rtf0" in the text...
1627 tPtr
->flags
.prepend
= True
;
1628 if(text
&& tPtr
->parser
)
1629 (tPtr
->parser
) (tPtr
, (void *) text
);
1631 insertPlainText(tPtr
, text
);
1636 WMAppendTextStream(WMText
*tPtr
, char *text
)
1640 //check for "{\rtf0" in the text...
1643 tPtr
->flags
.prepend
= False
;
1644 if(text
&& tPtr
->parser
)
1645 (tPtr
->parser
) (tPtr
, (void *) text
);
1647 insertPlainText(tPtr
, text
);
1652 WMGetTextSelected(WMText
*tPtr
)
1654 WMData
*data
= NULL
;
1660 //tb = tPtr->firstTextBlock;
1661 tb
= tPtr
->currentTextBlock
;
1665 data
= WMCreateDataWithBytes(tb
->text
, tb
->used
);
1667 WMSetDataFormat(data
, 8);
1672 WMCreateTextBlockWithObject(WMWidget
*w
, char *description
, WMColor
*color
,
1673 unsigned short first
, unsigned short reserved
)
1676 unsigned short length
;
1678 if(!w
|| !description
|| !color
)
1681 tb
= wmalloc(sizeof(TextBlock
));
1685 length
= strlen(description
);
1686 tb
->text
= (char *)wmalloc(length
);
1687 memset(tb
->text
, 0, length
);
1688 memcpy(tb
->text
, description
, length
);
1692 tb
->color
= WMRetainColor(color
);
1698 tb
->underlined
= False
;
1700 tb
->sections
= NULL
;
1709 WMCreateTextBlockWithText(char *text
, WMFont
*font
, WMColor
*color
,
1710 unsigned short first
, unsigned short length
)
1717 tb
= wmalloc(sizeof(TextBlock
));
1721 tb
->allocated
= reqBlockSize(length
);
1722 tb
->text
= (char *)wmalloc(tb
->allocated
);
1723 memset(tb
->text
, 0, tb
->allocated
);
1725 if(length
< 1|| !text
) { // || *text == '\n') {
1730 memcpy(tb
->text
, text
, length
);
1735 tb
->d
.font
= WMRetainFont(font
);
1736 tb
->color
= WMRetainColor(color
);
1740 tb
->graphic
= False
;
1741 tb
->underlined
= False
;
1743 tb
->sections
= NULL
;
1751 WMSetTextBlockProperties(void *vtb
, unsigned int first
,
1752 unsigned int kanji
, unsigned int underlined
, int script
,
1753 unsigned int marginN
)
1755 TextBlock
*tb
= (TextBlock
*) vtb
;
1761 tb
->underlined
= underlined
;
1762 tb
->script
= script
;
1763 tb
->marginN
= marginN
;
1767 WMGetTextBlockProperties(void *vtb
, unsigned int *first
,
1768 unsigned int *kanji
, unsigned int *underlined
, int *script
,
1769 unsigned int *marginN
)
1771 TextBlock
*tb
= (TextBlock
*) vtb
;
1775 if(first
) *first
= tb
->first
;
1776 if(kanji
) *kanji
= tb
->kanji
;
1777 if(underlined
) *underlined
= tb
->underlined
;
1778 if(script
) *script
= tb
->script
;
1779 if(marginN
) *marginN
= tb
->marginN
;
1785 WMPrependTextBlock(WMText
*tPtr
, void *vtb
)
1787 TextBlock
*tb
= (TextBlock
*)vtb
;
1794 WMWidget
*w
= tb
->d
.widget
;
1795 WMCreateEventHandler(W_VIEW(w
), ButtonPressMask
,
1796 handleWidgetPress
, tb
);
1797 //if(W_CLASS(w) != WC_TextField && W_CLASS(w) != WC_Text) {
1798 if(W_CLASS(w
) != WC_TextField
&&
1799 (((W_WidgetType
*)(w
))->widgetClass
) != WC_Text
) {
1800 (W_VIEW(w
))->attribs
.cursor
= tPtr
->view
->screen
->defaultCursor
;
1801 (W_VIEW(w
))->attribFlags
|= CWOverrideRedirect
| CWCursor
;
1803 WMPutInBag(tPtr
->gfxItems
, (void *)tb
);
1807 if(!tPtr
->lastTextBlock
|| !tPtr
->firstTextBlock
) {
1808 tb
->next
= tb
->prior
= NULL
;
1809 tPtr
->lastTextBlock
= tPtr
->firstTextBlock
1810 = tPtr
->currentTextBlock
= tb
;
1814 tb
->next
= tPtr
->currentTextBlock
;
1815 tb
->prior
= tPtr
->currentTextBlock
->prior
;
1816 if(tPtr
->currentTextBlock
->prior
)
1817 tPtr
->currentTextBlock
->prior
->next
= tb
;
1819 tPtr
->currentTextBlock
->prior
= tb
;
1821 tPtr
->firstTextBlock
= tb
;
1823 tPtr
->currentTextBlock
= tb
;
1828 WMAppendTextBlock(WMText
*tPtr
, void *vtb
)
1830 TextBlock
*tb
= (TextBlock
*)vtb
;
1836 WMWidget
*w
= tb
->d
.widget
;
1837 WMCreateEventHandler(W_VIEW(w
), ButtonPressMask
,
1838 handleWidgetPress
, tb
);
1839 //if(W_CLASS(w) != WC_TextField && W_CLASS(w) != WC_Text) {
1840 if(W_CLASS(w
) != WC_TextField
&&
1841 (((W_WidgetType
*)(w
))->widgetClass
) != WC_Text
) {
1842 (W_VIEW(w
))->attribs
.cursor
= tPtr
->view
->screen
->defaultCursor
;
1843 (W_VIEW(w
))->attribFlags
|= CWOverrideRedirect
| CWCursor
;
1845 WMPutInBag(tPtr
->gfxItems
, (void *)tb
);
1849 if(!tPtr
->lastTextBlock
|| !tPtr
->firstTextBlock
) {
1850 tb
->next
= tb
->prior
= NULL
;
1851 tPtr
->lastTextBlock
= tPtr
->firstTextBlock
1852 = tPtr
->currentTextBlock
= tb
;
1856 tb
->next
= tPtr
->currentTextBlock
->next
;
1857 tb
->prior
= tPtr
->currentTextBlock
;
1858 if(tPtr
->currentTextBlock
->next
)
1859 tPtr
->currentTextBlock
->next
->prior
= tb
;
1861 tPtr
->currentTextBlock
->next
= tb
;
1864 tPtr
->lastTextBlock
= tb
;
1866 tPtr
->currentTextBlock
= tb
;
1870 WMRemoveTextBlock(WMText
*tPtr
)
1872 TextBlock
*tb
= NULL
;
1874 if(!tPtr
|| !tPtr
->firstTextBlock
|| !tPtr
->lastTextBlock
1875 || !tPtr
->currentTextBlock
) {
1876 printf("cannot remove non existent TextBlock!\b");
1880 tb
= tPtr
->currentTextBlock
;
1882 WMDeleteEventHandler(W_VIEW(tb
->d
.widget
), ButtonPressMask
,
1883 handleWidgetPress
, tb
);
1884 WMRemoveFromBag(tPtr
->gfxItems
, (void *)tb
);
1885 WMUnmapWidget(tb
->d
.widget
);
1888 if(tPtr
->currentTextBlock
== tPtr
->firstTextBlock
) {
1889 if(tPtr
->currentTextBlock
->next
)
1890 tPtr
->currentTextBlock
->next
->prior
= NULL
;
1892 tPtr
->firstTextBlock
= tPtr
->currentTextBlock
->next
;
1893 tPtr
->currentTextBlock
= tPtr
->firstTextBlock
;
1895 } else if(tPtr
->currentTextBlock
== tPtr
->lastTextBlock
) {
1896 tPtr
->currentTextBlock
->prior
->next
= NULL
;
1897 tPtr
->lastTextBlock
= tPtr
->currentTextBlock
->prior
;
1898 tPtr
->currentTextBlock
= tPtr
->lastTextBlock
;
1900 tPtr
->currentTextBlock
->prior
->next
= tPtr
->currentTextBlock
->next
;
1901 tPtr
->currentTextBlock
->next
->prior
= tPtr
->currentTextBlock
->prior
;
1902 tPtr
->currentTextBlock
= tPtr
->currentTextBlock
->next
;
1909 WMDestroyTextBlock(WMText
*tPtr
, void *vtb
)
1911 TextBlock
*tb
= (TextBlock
*)vtb
;
1917 WMDestroyWidget(tb
->d
.widget
);
1918 wfree(tb
->d
.widget
);
1920 WMReleaseFont(tb
->d
.font
);
1923 WMReleaseColor(tb
->color
);
1924 if(tb
->sections
&& tb
->nsections
> 0)
1925 wfree(tb
->sections
);
1932 WMRefreshText(WMText
*tPtr
, int vpos
, int hpos
)
1936 if(!tPtr
|| vpos
<0 || hpos
<0)
1939 tPtr
->flags
.laidOut
= False
;
1940 layOutDocument(tPtr
);
1941 updateScrollers(tPtr
);
1948 WMSetTextForegroundColor(WMText
*tPtr
, WMColor
*color
)
1954 tPtr
->fgGC
= WMColorGC(color
);
1956 tPtr
->fgGC
= WMColorGC(WMBlackColor(tPtr
->view
->screen
));
1958 WMRefreshText(tPtr
, tPtr
->vpos
, tPtr
->hpos
);
1962 WMSetTextBackgroundColor(WMText
*tPtr
, WMColor
*color
)
1968 tPtr
->bgGC
= WMColorGC(color
);
1969 W_SetViewBackgroundColor(tPtr
->view
, color
);
1971 tPtr
->bgGC
= WMColorGC(WMWhiteColor(tPtr
->view
->screen
));
1972 W_SetViewBackgroundColor(tPtr
->view
,
1973 WMWhiteColor(tPtr
->view
->screen
));
1976 WMRefreshText(tPtr
, tPtr
->vpos
, tPtr
->hpos
);
1980 WMSetTextRelief(WMText
*tPtr
, WMReliefType relief
)
1984 tPtr
->flags
.relief
= relief
;
1989 WMSetTextHasHorizontalScroller(WMText
*tPtr
, Bool shouldhave
)
1994 if(shouldhave
&& !tPtr
->hS
) {
1995 tPtr
->hS
= WMCreateScroller(tPtr
);
1996 (W_VIEW(tPtr
->hS
))->attribs
.cursor
= tPtr
->view
->screen
->defaultCursor
;
1997 (W_VIEW(tPtr
->hS
))->attribFlags
|= CWOverrideRedirect
| CWCursor
;
1998 WMSetScrollerArrowsPosition(tPtr
->hS
, WSAMaxEnd
);
1999 WMSetScrollerAction(tPtr
->hS
, scrollersCallBack
, tPtr
);
2000 WMRealizeWidget(tPtr
->hS
);
2001 WMMapWidget(tPtr
->hS
);
2002 } else if(!shouldhave
&& tPtr
->hS
) {
2003 WMUnmapWidget(tPtr
->hS
);
2004 WMDestroyWidget(tPtr
->hS
);
2010 textDidResize(tPtr
->view
->delegate
, tPtr
->view
);
2015 WMSetTextHasVerticalScroller(WMText
*tPtr
, Bool shouldhave
)
2020 if(shouldhave
&& !tPtr
->vS
) {
2021 tPtr
->vS
= WMCreateScroller(tPtr
);
2022 (W_VIEW(tPtr
->vS
))->attribs
.cursor
= tPtr
->view
->screen
->defaultCursor
;
2023 (W_VIEW(tPtr
->vS
))->attribFlags
|= CWOverrideRedirect
| CWCursor
;
2024 WMSetScrollerArrowsPosition(tPtr
->vS
, WSAMaxEnd
);
2025 WMSetScrollerAction(tPtr
->vS
, scrollersCallBack
, tPtr
);
2026 WMRealizeWidget(tPtr
->vS
);
2027 WMMapWidget(tPtr
->vS
);
2028 } else if(!shouldhave
&& tPtr
->vS
) {
2029 WMUnmapWidget(tPtr
->vS
);
2030 WMDestroyWidget(tPtr
->vS
);
2036 textDidResize(tPtr
->view
->delegate
, tPtr
->view
);
2042 WMScrollText(WMText
*tPtr
, int amount
)
2047 if(amount
== 0 || !tPtr
->view
->flags
.realized
)
2051 if(tPtr
->vpos
> 0) {
2052 if(tPtr
->vpos
> amount
) tPtr
->vpos
+= amount
;
2056 int limit
= tPtr
->docHeight
- tPtr
->visible
.h
;
2057 if(tPtr
->vpos
< limit
) {
2058 if(tPtr
->vpos
< limit
-amount
) tPtr
->vpos
+= amount
;
2059 else tPtr
->vpos
= limit
;
2063 if(scroll
&& tPtr
->vpos
!= tPtr
->prevVpos
) {
2064 updateScrollers(tPtr
);
2067 tPtr
->prevVpos
= tPtr
->vpos
;
2072 WMPageText(WMText
*tPtr
, Bool direction
)
2074 if(!tPtr
) return False
;
2075 if(!tPtr
->view
->flags
.realized
) return False
;
2077 return WMScrollText(tPtr
, direction
?tPtr
->visible
.h
:-tPtr
->visible
.h
);
2082 WMSetTextUseMonoFont(WMText
*tPtr
, Bool mono
)
2086 if(mono
&& tPtr
->flags
.rulerShown
)
2087 ;//WMShowTextRuler(tPtr, False);
2089 tPtr
->flags
.monoFont
= mono
;
2090 WMRefreshText(tPtr
, tPtr
->vpos
, tPtr
->hpos
);
2094 WMGetTextUsesMonoFont(WMText
*tPtr
)
2098 return tPtr
->flags
.monoFont
;
2102 WMSetTextDefaultFont(WMText
*tPtr
, WMFont
*font
)
2110 tPtr
->dFont
= WMRetainFont(tPtr
->view
->screen
->normalFont
);
2114 WMGetTextDefaultFont(WMText
*tPtr
)
2123 WMSetTextParser(WMText
*tPtr
, WMAction
*parser
)
2127 tPtr
->parser
= parser
;
2132 WMSetTextWriter(WMText
*tPtr
, WMAction
*writer
)
2136 tPtr
->writer
= writer
;
2140 WMGetTextInsertType(WMText
*tPtr
)
2144 return tPtr
->flags
.prepend
;