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
.
53 /* a Section is a section of a TextBlock that describes what parts
54 of a TextBlock has been laid out on which "line"...
55 o this greatly aids redraw, scroll and selection.
56 o this is created during layoutLine, but may be later modified.
57 o there may be many Sections per TextBlock, hence the array */
59 int x
, y
; /* where to draw it from */
60 int w
, h
; /* it's width and height (to aid selection) */
62 unsigned short begin
, end
; /* what part of the text block */
66 /* a TextBlock is a doubly-linked list of TextBlocks containing:
67 o text for the block, color and font
68 o or a pointer to the widget and the (text) description for its graphic
71 typedef struct _TextBlock
{
72 struct _TextBlock
*next
; /* next text block in linked list */
73 struct _TextBlock
*prior
; /* prior text block in linked list */
75 char *text
; /* pointer to 8- or 16-bit text */
76 /* or to the object's description */
78 WMFont
*font
; /* the font */
79 WMWidget
*widget
; /* the embedded widget */
80 } d
; /* description */
82 WMColor
*color
; /* the color */
83 Section
*sections
; /* the region for layouts (a growable array) */
84 /* an _array_! of size _nsections_ */
86 unsigned short used
; /* number of chars in this block */
87 unsigned short allocated
; /* size of allocation (in chars) */
89 unsigned int first
:1; /* first TextBlock in paragraph */
90 unsigned int blank
:1; /* ie. blank paragraph */
91 unsigned int kanji
:1; /* is of 16-bit characters or not */
92 unsigned int graphic
:1; /* embedded object or text: text=0 */
93 unsigned int underlined
:1; /* underlined or not */
94 unsigned int nsections
:8; /* over how many "lines" a TexBlock wraps */
95 int script
:8; /* script in points: negative for subscript */
96 unsigned int marginN
:10; /* which of the margins in WMText to use */
97 unsigned int RESERVED
:1;
101 /* somehow visible.h beats the hell outta visible.size.height :-) */
110 typedef struct W_Text
{
111 W_Class widgetClass
; /* the class number of this widget */
112 W_View
*view
; /* the view referring to this instance */
114 WMRuler
*ruler
; /* the ruler subwiget to manipulate paragraphs */
116 WMScroller
*vS
; /* the vertical scroller */
117 int vpos
; /* the current vertical position */
118 int prevVpos
; /* the previous vertical position */
120 WMScroller
*hS
; /* the horizontal scroller */
121 int hpos
; /* the current horizontal position */
122 int prevHpos
; /* the previous horizontal position */
123 /* in short: tPtr->hS?nowrap:wrap */
125 WMFont
*dFont
; /* the default font */
126 WMColor
*dColor
; /* the default color */
127 WMPixmap
*dBulletPix
; /* the default pixmap for bullets */
129 GC bgGC
; /* the background GC to draw with */
130 GC fgGC
; /* the foreground GC to draw with */
131 Pixmap db
; /* the buffer on which to draw */
133 WMRulerMargins
*margins
;/* a (growable) array of margins to be used */
134 /* by the various TextBlocks */
136 myRect visible
; /* the actual rectangle that can be drawn into */
137 myRect cursor
; /* the position and (height) of cursor */
138 myRect sel
; /* the selection rectangle */
139 int docWidth
; /* the width of the entire document */
140 int docHeight
; /* the height of the entire document */
143 TextBlock
*firstTextBlock
;
144 TextBlock
*lastTextBlock
;
145 TextBlock
*currentTextBlock
;
148 WMBag
*gfxItems
; /* a nice bag containing graphic items */
150 WMPoint clicked
; /* where in the _document_ was clicked */
151 unsigned short tpos
; /* the character position in the currentTextBlock */
152 unsigned short RESERVED
;/* space taker upper... */
159 unsigned int monoFont
:1; /* whether to ignore formats */
160 unsigned int focused
:1; /* whether this instance has input focus */
161 unsigned int editable
:1; /* "silly user, you can't edit me" */
162 unsigned int ownsSelection
:1; /* "I ownz the current selection!" */
163 unsigned int pointerGrabbed
:1;/* "heh, gib me pointer" */
164 unsigned int buttonHeld
:1; /* the user is holding down the button */
165 unsigned int waitingForSelection
:1; /* dum dee dumm... */
166 unsigned int extendSelection
:1; /* shift-drag to select more regions */
168 unsigned int rulerShown
:1; /* whether the ruler is shown or not */
169 unsigned int frozen
:1; /* whether screen updates are to be made */
170 unsigned int cursorShown
:1; /* whether to show the cursor */
171 unsigned int clickPos
:1; /* clicked before=0 or after=1 a graphic: */
172 /* within counts as after too */
174 unsigned int ignoreNewLine
:1;/* "bleh XK_Return" ignore it when typed */
175 unsigned int laidOut
:1; /* have the TextBlocks all been laid out */
176 unsigned int prepend
:1; /* prepend=1, append=0 (for parsers) */
177 WMAlignment alignment
:2; /* the alignment for text */
178 WMReliefType relief
:3; /* the relief to display with */
179 unsigned int RESERVED
:4;
180 unsigned int nmargins
:10; /* the number of margin arrays */
184 static char *default_bullet
[] = {
186 " c None s None", ". c black",
187 "X c white", "o c #808080",
197 paintText(Text
*tPtr
)
199 TextBlock
*tb
= tPtr
->firstTextBlock
;
203 int len
, y
, c
, s
, done
=False
;
205 WMScreen
*scr
= tPtr
->view
->screen
;
206 Display
*dpy
= tPtr
->view
->screen
->display
;
207 Window win
= tPtr
->view
->window
;
210 if(!tPtr
->view
->flags
.realized
|| !tPtr
->db
)
213 XFillRectangle(dpy
, tPtr
->db
, tPtr
->bgGC
,
214 0, 0, tPtr
->visible
.w
, tPtr
->visible
.h
);
217 tb
= tPtr
->firstTextBlock
;
222 if(tPtr
->flags
.ownsSelection
) {
223 greyGC
= WMColorGC(WMGrayColor(scr
));
224 //XFillRectangle(dpy, tPtr->db, greyGC,
225 // tPtr->sel.x, tPtr->sel.y-tPtr->vpos, tPtr->sel.w, tPtr->sel.h);
226 // XDrawRectangle(dpy, tPtr->db, tPtr->fgGC,
227 // tPtr->sel.x, tPtr->sel.y-tPtr->vpos, tPtr->sel.w, tPtr->sel.h);
238 for(s
=0; s
<tb
->nsections
&& !done
; s
++) {
241 if(tb
->sections
[s
]._y
> tPtr
->vpos
+ tPtr
->visible
.h
) {
246 if( tb
->sections
[s
].y
+ tb
->sections
[s
].h
< tPtr
->vpos
)
249 if(tPtr
->flags
.monoFont
) {
254 gc
= WMColorGC(tb
->color
);
257 if(tPtr
->flags
.ownsSelection
) {
259 if(prev_y
!= tb
->sections
[s
]._y
260 && (tb
->sections
[s
]._y
>= tPtr
->sel
.y
)
261 && (tb
->sections
[s
]._y
+ tb
->sections
[s
].h
262 <= tPtr
->sel
.y
+ tPtr
->sel
.h
)) {
263 XFillRectangle(dpy
, tPtr
->db
, greyGC
,
265 tPtr
->visible
.y
+ tb
->sections
[s
]._y
- tPtr
->vpos
,
266 tPtr
->visible
.w
, tb
->sections
[s
].h
);
268 } else if( prev_y
!= tb
->sections
[s
]._y
269 && (tb
->sections
[s
]._y
<= tPtr
->sel
.y
)
270 && (tb
->sections
[s
]._y
+ tb
->sections
[s
].h
272 && (tPtr
->sel
.x
>= tb
->sections
[s
].x
)
273 && (tPtr
->sel
.y
+ tPtr
->sel
.h
274 >= tb
->sections
[s
]._y
+ tb
->sections
[s
].h
)) {
275 XFillRectangle(dpy
, tPtr
->db
, greyGC
,
277 tPtr
->visible
.y
+ tb
->sections
[s
]._y
- tPtr
->vpos
,
278 tPtr
->visible
.w
- tPtr
->sel
.x
, tb
->sections
[s
].h
);
280 } else if(prev_y
!= tb
->sections
[s
]._y
281 && (tb
->sections
[s
]._y
<= tPtr
->sel
.y
+ tPtr
->sel
.h
)
282 && (tb
->sections
[s
]._y
>= tPtr
->sel
.y
)) {
283 XFillRectangle(dpy
, tPtr
->db
, greyGC
,
285 tPtr
->visible
.y
+ tb
->sections
[s
]._y
- tPtr
->vpos
,
286 tPtr
->sel
.x
+ tPtr
->sel
.w
-tPtr
->visible
.x
,
289 } else if( prev_y
!= tb
->sections
[s
]._y
290 && (tb
->sections
[s
]._y
<= tPtr
->sel
.y
)
291 && (tb
->sections
[s
]._y
+ tb
->sections
[s
].h
292 >= tPtr
->sel
.y
+ tPtr
->sel
.h
) ) {
293 XFillRectangle(dpy
, tPtr
->db
, greyGC
,
295 tPtr
->visible
.y
+ tb
->sections
[s
]._y
- tPtr
->vpos
,
296 tPtr
->sel
.w
,tb
->sections
[s
].h
);
301 prev_y
= tb
->sections
[s
]._y
;
303 len
= tb
->sections
[s
].end
- tb
->sections
[s
].begin
;
304 text
= &(tb
->text
[tb
->sections
[s
].begin
]);
305 y
= tb
->sections
[s
].y
- tPtr
->vpos
;
306 WMDrawString(scr
, tPtr
->db
, gc
, font
,
307 tb
->sections
[s
].x
, y
, text
, len
);
310 XDrawLine(dpy
, tPtr
->db
, gc
,
311 tb
->sections
[s
].x
, y
+ font
->y
+ 1,
312 tb
->sections
[s
].x
+ tb
->sections
[s
].w
, y
+ font
->y
+ 1);
317 tb
= (!done
? tb
->next
: NULL
);
321 c
= WMGetBagItemCount(tPtr
->gfxItems
);
322 if(c
> 0 && !tPtr
->flags
.monoFont
) {
326 tb
= (TextBlock
*) WMGetFromBag(tPtr
->gfxItems
, j
);
328 if(tb
->sections
[0]._y
+ tb
->sections
[0].h
<= tPtr
->vpos
329 || tb
->sections
[0]._y
>= tPtr
->vpos
+ tPtr
->visible
.h
) {
331 if((W_VIEW(wdt
))->flags
.mapped
) {
335 if(!(W_VIEW(wdt
))->flags
.mapped
) {
337 //WMLowerWidget(wdt);
340 if(tPtr
->flags
.ownsSelection
&& 0
341 //&& (tb->sections[s]._y >= tPtr->sel.y)
342 //&& (tb->sections[s]._y + tb->sections[s].h
343 ){ // <= tPtr->sel.y + tPtr->sel.h)) {
344 XFillRectangle(dpy
, tPtr
->db
, greyGC
,
345 tb
->sections
[0].x
, tb
->sections
[0].y
- tPtr
->vpos
,
346 tb
->sections
[0].w
, tb
->sections
[0].h
);
349 WMMoveWidget(wdt
, 3 + tb
->sections
[0].x
+ tPtr
->visible
.x
,
350 tb
->sections
[0].y
- tPtr
->vpos
);
353 XDrawLine(dpy
, tPtr
->db
, WMColorGC(tb
->color
),
355 tb
->sections
[0].y
+ WMWidgetHeight(wdt
) + 1,
356 tb
->sections
[0].x
+ tb
->sections
[0].w
,
357 tb
->sections
[0].y
+ WMWidgetHeight(wdt
) + 1);
361 if(tPtr
->cursor
.x
!= -23) {
362 int y
= tPtr
->cursor
.y
- tPtr
->vpos
;
363 XDrawLine(dpy
, tPtr
->db
, tPtr
->fgGC
,
365 tPtr
->cursor
.x
, y
+ tPtr
->cursor
.h
);
366 printf("%d %d %d\n", tPtr
->cursor
.x
, tPtr
->cursor
.y
, tPtr
->cursor
.h
);
371 XCopyArea(dpy
, tPtr
->db
, win
, tPtr
->bgGC
,
373 tPtr
->visible
.w
, tPtr
->visible
.h
,
374 tPtr
->visible
.x
, tPtr
->visible
.y
);
376 W_DrawRelief(scr
, win
, 0, 0,
377 tPtr
->view
->size
.width
, tPtr
->view
->size
.height
,
380 if(tPtr
->ruler
&& tPtr
->flags
.rulerShown
)
383 tPtr
->view
->size
.width
-4, 42);
386 XFillRectangle(tPtr->view->screen->display, tPtr->view->window,
388 2, tPtr->view->size.height-3,
389 tPtr->view->size.width-4, 3);
396 getFirstNonGraphicBlockFor(TextBlock
*tb
)
411 cursorToTextPosition(Text
*tPtr
, int x
, int y
)
413 TextBlock
*tb
= NULL
;
414 int done
=False
, s
, pos
, len
, _w
, _y
, dir
=1; /* 1 == "down" */
418 y
+= (tPtr
->vpos
- tPtr
->visible
.y
);
422 x
-= (tPtr
->visible
.x
- 2);
426 /* clicked is relative to document, not window... */
430 /* first, which direction? Most likely, newly clicked
431 position will be close to previous */
432 if(! (tb
= tPtr
->currentTextBlock
)) {
433 if(! (tb
= tPtr
->firstTextBlock
)) {
439 dir
= !(y
< tb
->sections
[0].y
);
440 tb
= tPtr
->firstTextBlock
;
443 if(tPtr
->flags
.monoFont
&& tb
->graphic
) {
444 tb
= getFirstNonGraphicBlockFor(tb
);
446 tPtr
->currentTextBlock
= tPtr
->firstTextBlock
;
452 if(y
== tb
->sections
[0].y
)
455 /* get the first section of the first visible TextBlock */
459 if(tPtr
->flags
.monoFont
&& tb
->graphic
) {
464 s
= (dir
? 0 : tb
->nsections
-1);
465 while( (dir
? (s
<tb
->nsections
) : (s
>=0) )) {
466 //printf("y:%d top:%d, bot%d :",
467 //y, tb->sections[s]._y, tb->sections[s].y + tb->sections[s].h);
468 //output(tb->text, tb->used);
469 if( y
>= tb
->sections
[s
]._y
470 && y
<= tb
->sections
[s
].y
+ tb
->sections
[s
].h
) {
480 if( (dir
? tb
->next
: tb
->prior
)) {
481 tb
= (dir
? tb
->next
: tb
->prior
);
490 if(s
<0 || s
>=tb
->nsections
) {
491 s
= (dir
? tb
->nsections
-1 : 0);
494 /* we have the line, which TextBlock on that line is it? */
496 if(tPtr
->flags
.monoFont
&& tb
->graphic
)
497 tb
= getFirstNonGraphicBlockFor(tb
);
499 if(tb
->sections
[s
].x
>= x
)
501 _y
= tb
->sections
[s
]._y
;
506 if(tPtr
->flags
.monoFont
&& tb
->graphic
) {
512 _w
= WMWidgetWidth(tb
->d
.widget
);
514 text
= &(tb
->text
[tb
->sections
[s
].begin
]);
515 len
= tb
->sections
[s
].end
- tb
->sections
[s
].begin
;
516 _w
= WMWidthOfString(tb
->d
.font
, text
, len
);
519 if(tb
->sections
[s
].x
+ _w
>= x
)
523 TextBlock
*nxt
= tb
->next
;
524 if(tPtr
->flags
.monoFont
&& nxt
->graphic
) {
525 nxt
= getFirstNonGraphicBlockFor(nxt
);
531 if(_y
!= nxt
->sections
[s
]._y
) {
532 /* this must be the last on this line. stop */
542 /* we have said TextBlock, now where within it? */
543 if(tb
&& !tb
->graphic
) {
544 len
= tb
->sections
[s
].end
- tb
->sections
[s
].begin
;
545 text
= &(tb
->text
[tb
->sections
[s
].begin
]);
547 _w
= x
- tb
->sections
[s
].x
;
549 while(pos
<len
&& WMWidthOfString(tb
->d
.font
, text
, pos
+1) < _w
)
552 pos
+= tb
->sections
[s
].begin
;
554 tPtr
->tpos
= (pos
<tb
->used
)? pos
: tb
->used
;
557 tPtr
->currentTextBlock
= tb
;
558 tPtr
->cursor
.h
= tb
->sections
[s
].h
;
560 tPtr
->cursor
.x
= tPtr
->clicked
.x
; //WMWidthOfString(tb->d.font, text,
562 printf("will hang :-)\n");
568 updateScrollers(Text
*tPtr
)
572 if(tPtr
->docHeight
< tPtr
->visible
.h
) {
573 WMSetScrollerParameters(tPtr
->vS
, 0, 1);
576 float vmax
= (float)(tPtr
->docHeight
);
577 WMSetScrollerParameters(tPtr
->vS
,
578 ((float)tPtr
->vpos
)/(vmax
- (float)tPtr
->visible
.h
),
579 (float)tPtr
->visible
.h
/vmax
);
581 } else tPtr
->vpos
= 0;
588 scrollersCallBack(WMWidget
*w
, void *self
)
590 Text
*tPtr
= (Text
*)self
;
595 if(!tPtr
->view
->flags
.realized
) return;
600 vmax
= (float)(tPtr
->docHeight
);
601 height
= tPtr
->visible
.h
;
603 which
= WMGetScrollerHitPart(tPtr
->vS
);
605 case WSDecrementLine
:
607 if(tPtr
->vpos
>16) tPtr
->vpos
-=16;
611 case WSIncrementLine
: {
612 int limit
= tPtr
->docHeight
- height
;
613 if(tPtr
->vpos
< limit
) {
614 if(tPtr
->vpos
<limit
-16) tPtr
->vpos
+=16;
615 else tPtr
->vpos
=limit
;
618 case WSDecrementPage
:
619 tPtr
->vpos
-= height
;
625 printf("dimple needs to jump to mouse location ;-/\n");
627 case WSIncrementPage
:
628 tPtr
->vpos
+= height
;
629 if(tPtr
->vpos
> (tPtr
->docHeight
- height
))
630 tPtr
->vpos
= tPtr
->docHeight
- height
;
633 printf("dimple needs to jump to mouse location ;-/\n");
638 tPtr
->vpos
= WMGetScrollerValue(tPtr
->vS
)
639 * (float)(tPtr
->docHeight
- height
);
645 printf("WSNoPart, WSKnobSlot\n");
647 float vmax
= (float)(tPtr
->docHeight
);
648 ((float)tPtr
->vpos
)/(vmax
- (float)tPtr
->visible
.h
),
649 (float)tPtr
->visible
.h
/vmax
;
650 dimple
=where mouse is
.
654 scroll
= (tPtr
->vpos
!= tPtr
->prevVpos
);
655 tPtr
->prevVpos
= tPtr
->vpos
;
665 XClearArea(tPtr->view->screen->display, tPtr->view->window, 22, 47,
666 tPtr->view->size.width-24, tPtr->view->size.height-49, True);
668 XClearArea(tPtr->view->screen->display, tPtr->view->window, 22, 2,
669 tPtr->view->size.width-24, tPtr->view->size.height-4, True);
672 if(which
== WSDecrementLine
|| which
== WSIncrementLine
)
673 updateScrollers(tPtr
);
682 unsigned short begin
, end
; /* what part of the text block */
688 layOutLine(Text
*tPtr
, myLineItems
*items
, int nitems
, int x
, int y
,
689 int pwidth
, WMAlignment align
)
691 int i
, j
=0, lw
= 0, line_height
=0, max_d
=0, len
, n
;
696 TextBlock
*tbsame
=NULL
;
698 for(i
=0; i
<nitems
; i
++) {
702 if(!tPtr
->flags
.monoFont
) {
703 WMWidget
*wdt
= tb
->d
.widget
;
704 line_height
= WMAX(line_height
, WMWidgetHeight(wdt
));
706 lw
+= WMWidgetWidth(wdt
);
711 font
= (tPtr
->flags
.monoFont
)?tPtr
->dFont
: tb
->d
.font
;
712 max_d
= WMAX(max_d
, font
->height
-font
->y
);
713 line_height
= WMAX(line_height
, font
->height
);
714 text
= &(tb
->text
[items
[i
].begin
]);
715 len
= items
[i
].end
- items
[i
].begin
;
717 lw
+= WMWidthOfString(font
, text
, len
);
721 if(align
== WARight
) {
723 } else if (align
== WACenter
) {
724 j
= (int) ((float)(pwidth
- lw
))/2.0;
729 for(i
=0; i
<nitems
; i
++) {
732 if(tbsame
== tb
) { /*extend it, since it's on same line */
733 tb
->sections
[tb
->nsections
-1].end
= items
[i
].end
;
736 tb
->sections
= wrealloc(tb
->sections
,
737 (++tb
->nsections
)*sizeof(Section
));
739 tb
->sections
[n
]._y
= y
;
740 tb
->sections
[n
].x
= x
+j
;
741 tb
->sections
[n
].h
= line_height
;
742 tb
->sections
[n
].begin
= items
[i
].begin
;
743 tb
->sections
[n
].end
= items
[i
].end
;
746 if(!tPtr
->flags
.monoFont
) {
747 WMWidget
*wdt
= tb
->d
.widget
;
748 tb
->sections
[n
].y
= 1 + max_d
+
749 y
+ line_height
- WMWidgetHeight(wdt
);
750 tb
->sections
[n
].w
= WMWidgetWidth(wdt
);
751 x
+= tb
->sections
[n
].w
;
754 font
= (tPtr
->flags
.monoFont
)? tPtr
->dFont
: tb
->d
.font
;
755 len
= items
[i
].end
- items
[i
].begin
;
756 text
= &(tb
->text
[items
[i
].begin
]);
758 tb
->sections
[n
].y
= y
+line_height
-font
->y
;
760 WMWidthOfString(font
,
761 &(tb
->text
[tb
->sections
[n
].begin
]),
762 tb
->sections
[n
].end
- tb
->sections
[n
].begin
);
764 x
+= WMWidthOfString(font
, text
, len
);
770 return line_height
+(gfx
?10:0);
776 output(char *ptr
, int len
)
781 printf(" s is [%s] (%d)\n", s
, strlen(s
));
786 #define MAX_TB_PER_LINE 64
789 layOutDocument(Text
*tPtr
)
792 myLineItems items
[MAX_TB_PER_LINE
];
793 WMAlignment align
= WALeft
;
795 Bool lhc
= !tPtr
->flags
.laidOut
; /* line height changed? */
798 int nitems
=0, x
=0, y
=0, lw
= 0, width
=0;
799 int pwidth
= tPtr
->visible
.w
- tPtr
->visible
.x
;
801 char *start
=NULL
, *mark
=NULL
;
804 if(!(tb
= tPtr
->firstTextBlock
))
807 if(0&&tPtr
->flags
.laidOut
) {
808 tb
= tPtr
->currentTextBlock
;
809 if(tb
->sections
&& tb
->nsections
>0)
810 prev_y
= tb
->sections
[tb
->nsections
-1]._y
;
812 printf("1 prev_y %d \n", prev_y
);
814 /* search backwards for textblocks on same line */
816 if(!tb
->sections
|| tb
->nsections
<1) {
817 tb
= tPtr
->firstTextBlock
;
820 if(tb
->sections
[tb
->nsections
-1]._y
!= prev_y
) {
824 // prev_y = tb->sections[tb->nsections-1]._y;
827 y
= 0;//tb->sections[tb->nsections-1]._y;
828 printf("2 prev_y %d \n\n", tb
->sections
[tb
->nsections
-1]._y
);
834 if(tb
->sections
&& tb
->nsections
>0) {
841 y
+= layOutLine(tPtr
, items
, nitems
, x
, y
, pwidth
, align
);
842 x
= 0;//tPtr->visible.x+2;
848 if(!tPtr
->flags
.monoFont
) {
849 width
= WMWidgetWidth(tb
->d
.widget
);
850 if(width
> pwidth
)printf("rescale graphix to fit?\n");
853 || nitems
>= MAX_TB_PER_LINE
) {
854 y
+= layOutLine(tPtr
, items
, nitems
, x
, y
,
857 x
= 0;//tPtr->visible.x+2;
861 items
[nitems
].tb
= tb
;
862 items
[nitems
].begin
= 0;
863 items
[nitems
].end
= 0;
867 } else if((start
= tb
->text
)) {
869 font
= tPtr
->flags
.monoFont
?tPtr
->dFont
:tb
->d
.font
;
872 mark
= strchr(start
, ' ');
874 end
+= (int)(mark
-start
)+1;
877 end
+= strlen(start
);
886 width
= WMWidthOfString(font
,
887 &tb
->text
[begin
], end
-begin
);
889 if(width
> pwidth
) { /* break this tb up */
890 char *t
= &tb
->text
[begin
];
891 int l
=end
-begin
, i
=0;
893 width
= WMWidthOfString(font
, t
, ++i
);
894 } while (width
< pwidth
&& i
< l
);
896 if(start
) // and since (nil)-4 = 0xfffffffd
904 if((lw
>= pwidth
- x
)
905 || nitems
>= MAX_TB_PER_LINE
) {
906 y
+= layOutLine(tPtr
, items
, nitems
, x
, y
,
909 x
= 0; //tPtr->visible.x+2;
913 items
[nitems
].tb
= tb
;
914 items
[nitems
].begin
= begin
;
915 items
[nitems
].end
= end
;
926 y
+= layOutLine(tPtr
, items
, nitems
, x
, y
, pwidth
, align
);
928 tPtr
->docHeight
= y
+10;
929 updateScrollers(tPtr
);
931 tPtr
->flags
.laidOut
= True
;
937 textDidResize(W_ViewDelegate
*self
, WMView
*view
)
939 Text
*tPtr
= (Text
*)view
->self
;
940 unsigned short w
= WMWidgetWidth(tPtr
);
941 unsigned short h
= WMWidgetHeight(tPtr
);
942 unsigned short rh
= 0, vw
= 0;
944 if(tPtr
->ruler
&& tPtr
->flags
.rulerShown
) {
945 WMMoveWidget(tPtr
->ruler
, 20, 2);
946 WMResizeWidget(tPtr
->ruler
, w
- 22, 40);
951 WMMoveWidget(tPtr
->vS
, 1, rh
+ 2);
952 WMResizeWidget(tPtr
->vS
, 20, h
- rh
- 3);
954 WMSetRulerOffset(tPtr
->ruler
, 22);
955 } else WMSetRulerOffset(tPtr
->ruler
, 2);
959 WMMoveWidget(tPtr
->hS
, vw
, h
- 21);
960 WMResizeWidget(tPtr
->hS
, w
- vw
- 1, 20);
962 WMMoveWidget(tPtr
->hS
, vw
+1, h
- 21);
963 WMResizeWidget(tPtr
->hS
, w
- vw
- 2, 20);
967 tPtr
->visible
.x
= (tPtr
->vS
)?22:0;
968 tPtr
->visible
.y
= (tPtr
->ruler
&& tPtr
->flags
.rulerShown
)?43:3;
969 tPtr
->visible
.w
= tPtr
->view
->size
.width
- tPtr
->visible
.x
- 12;
970 tPtr
->visible
.h
= tPtr
->view
->size
.height
- tPtr
->visible
.y
;
971 tPtr
->visible
.h
-= (tPtr
->hS
)?20:0;
973 tPtr
->margins
[0].left
= tPtr
->margins
[0].right
= tPtr
->visible
.x
;
974 tPtr
->margins
[0].body
= tPtr
->visible
.x
;
975 tPtr
->margins
[0].right
= tPtr
->visible
.w
;
977 WMRefreshText(tPtr
, tPtr
->vpos
, tPtr
->hpos
);
980 //if(tPtr->view->flags.realized)
981 //XFreePixmap(tPtr->view->screen->display, tPtr->db);
984 if(tPtr
->visible
.w
< 10) tPtr
->visible
.w
= 10;
985 if(tPtr
->visible
.h
< 10) tPtr
->visible
.h
= 10;
987 //if(size change or !db
988 tPtr
->db
= XCreatePixmap(tPtr
->view
->screen
->display
,
989 tPtr
->view
->window
, tPtr
->visible
.w
,
990 tPtr
->visible
.h
, tPtr
->view
->screen
->depth
);
995 W_ViewDelegate _TextViewDelegate
=
1003 /* nice, divisble-by-16 blocks */
1004 static inline unsigned short
1005 reqBlockSize(unsigned short requested
)
1007 return requested
+ 16 - (requested
%16);
1011 deleteTextInteractively(Text
*tPtr
, KeySym ksym
)
1013 printf("deleting %ld\n", ksym
);
1018 insertTextInteractively(Text
*tPtr
, char *text
, int len
)
1021 char *newline
= NULL
;
1023 if(!tPtr
->flags
.editable
|| len
< 1 || !text
)
1026 if(tPtr
->flags
.ignoreNewLine
) {
1028 for(i
=0; i
<len
; i
++) {
1034 tb
= tPtr
->currentTextBlock
;
1035 if(!tb
|| tb
->graphic
) {
1036 WMAppendTextStream(tPtr
, text
);
1037 if(tPtr
->currentTextBlock
) {
1038 tPtr
->tpos
= tPtr
->currentTextBlock
->used
-4;
1043 if((newline
= strchr(text
, '\n'))) {
1044 int nlen
= (int)(newline
-text
);
1045 int s
= tb
->used
- tPtr
->tpos
;
1048 if(!tb
->blank
&& nlen
>0 ) {
1050 memcpy(save
, &tb
->text
[tPtr
->tpos
], s
);
1051 tb
->used
-= (tb
->used
- tPtr
->tpos
);
1054 insertTextInteractively(tPtr
, text
, nlen
);
1056 WMAppendTextStream(tPtr
, newline
);
1058 insertTextInteractively(tPtr
, save
, s
);
1059 } else WMAppendTextStream(tPtr
, text
);
1062 if(tb
->used
+ len
>= tb
->allocated
) {
1063 tb
->allocated
= reqBlockSize(tb
->used
+len
);
1064 tb
->text
= wrealloc(tb
->text
, tb
->allocated
);
1068 memcpy(tb
->text
, text
, len
);
1073 memmove(&(tb
->text
[tPtr
->tpos
+len
]), &tb
->text
[tPtr
->tpos
],
1074 tb
->used
-tPtr
->tpos
+1);
1075 memmove(&tb
->text
[tPtr
->tpos
], text
, len
);
1085 selectRegion(Text
*tPtr
, int x
, int y
)
1090 if(y
>10) y
-= 10; /* the original offset */
1092 x
-= tPtr
->visible
.x
-2;
1095 tPtr
->sel
.x
= WMAX(0, WMIN(tPtr
->clicked
.x
, x
));
1096 tPtr
->sel
.w
= abs(tPtr
->clicked
.x
- x
);
1097 tPtr
->sel
.y
= WMAX(0, WMIN(tPtr
->clicked
.y
, y
));
1098 tPtr
->sel
.h
= abs(tPtr
->clicked
.y
- y
);
1100 tPtr
->flags
.ownsSelection
= True
;
1106 pasteText(WMView
*view
, Atom selection
, Atom target
, Time timestamp
,
1107 void *cdata
, WMData
*data
)
1109 Text
*tPtr
= (Text
*)view
->self
;
1112 tPtr
->flags
.waitingForSelection
= False
;
1115 str
= (char*)WMDataBytes(data
);
1117 (tPtr
->parser
) (tPtr
, (void *) str
);
1119 insertTextInteractively(tPtr
, str
, strlen(str
));
1121 WMRefreshText(tPtr
, 0, 0);
1124 str
= XFetchBuffer(tPtr
->view
->screen
->display
, &n
, 0);
1128 (tPtr
->parser
) (tPtr
, (void *) str
);
1130 insertTextInteractively(tPtr
, str
, n
);
1132 WMRefreshText(tPtr
, 0, 0);
1139 releaseSelection(Text
*tPtr
)
1141 tPtr
->flags
.ownsSelection
= False
;
1146 requestHandler(WMView
*view
, Atom selection
, Atom target
,
1147 void *cdata
, Atom
*type
)
1149 Text
*tPtr
= view
->self
;
1151 Display
*dpy
= tPtr
->view
->screen
->display
;
1152 Atom TEXT
= XInternAtom(dpy
, "TEXT", False
);
1153 Atom COMPOUND_TEXT
= XInternAtom(dpy
, "COMPOUND_TEXT", False
);
1156 if (target
== XA_STRING
|| target
== TEXT
|| target
== COMPOUND_TEXT
)
1157 return WMGetTextSelected(tPtr
);
1159 WMData
*data
= WMCreateDataWithBytes("bleh", 4);
1168 lostHandler(WMView
*view
, Atom selection
, void *cdata
)
1170 releaseSelection((WMText
*)view
->self
);
1173 static WMSelectionProcs selectionHandler
= {
1174 requestHandler
, lostHandler
, NULL
1178 _notification(void *observerData
, WMNotification
*notification
)
1180 WMText
*to
= (WMText
*)observerData
;
1181 WMText
*tw
= (WMText
*)WMGetNotificationClientData(notification
);
1183 lostHandler(to
->view
, XA_PRIMARY
, NULL
);
1187 handleTextKeyPress(Text
*tPtr
, XEvent
*event
)
1191 int control_pressed
= False
;
1194 if (((XKeyEvent
*) event
)->state
& ControlMask
)
1195 control_pressed
= True
;
1196 buffer
[XLookupString(&event
->xkey
, buffer
, 1, &ksym
, NULL
)] = '\0';
1203 printf("arrows %ld\n", ksym
);
1209 deleteTextInteractively(tPtr
, ksym
);
1216 if(buffer
[0] != '\0' && !control_pressed
) {
1217 insertTextInteractively(tPtr
, buffer
, 1);
1218 WMRefreshText(tPtr
, 0, 0);
1220 } else if(control_pressed
&& ksym
==XK_r
) {
1221 // Bool i = !tPtr->rulerShown; WMShowTextRuler(tPtr, i);
1222 // tPtr->rulerShown = i;
1223 printf("toggle ruler\n");
1225 else if(control_pressed
&& buffer
[0] == '\a')
1226 XBell(tPtr
->view
->screen
->display
, 0);
1229 if(tPtr
->flags
.ownsSelection
)
1230 releaseSelection(tPtr
);
1235 handleWidgetPress(XEvent
*event
, void *data
)
1237 TextBlock
*tb
= (TextBlock
*)data
;
1243 /* this little bit of nastiness here saves a boatload of trouble */
1244 w
= (WMWidget
*)(((W_VIEW(tb
->d
.widget
))->parent
)->self
);
1245 if(W_CLASS(w
) != WC_Text
)
1248 printf("%p clicked on tb %p wif: (%c)%c", tPtr
, tb
,
1249 tPtr
->firstTextBlock
->text
[0], tPtr
->firstTextBlock
->text
[1]);
1250 tPtr
->currentTextBlock
= getFirstNonGraphicBlockFor(tb
);
1251 if(!tPtr
->currentTextBlock
)
1252 tPtr
->currentTextBlock
= tb
;
1254 output(tPtr
->currentTextBlock
->text
, tPtr
->currentTextBlock
->used
);
1255 if(!tPtr
->flags
.focused
) {
1256 WMSetFocusToWidget(tPtr
);
1257 tPtr
->flags
.focused
= True
;
1263 handleActionEvents(XEvent
*event
, void *data
)
1265 Text
*tPtr
= (Text
*)data
;
1266 Display
*dpy
= event
->xany
.display
;
1270 if(tPtr
->flags
.waitingForSelection
)
1273 switch (event
->type
) {
1275 ksym
= XLookupKeysym((XKeyEvent
*)event
, 0);
1276 if(ksym
== XK_Shift_R
|| ksym
== XK_Shift_L
) {
1277 tPtr
->flags
.extendSelection
= True
;
1280 if(!tPtr
->flags
.editable
|| tPtr
->flags
.buttonHeld
) {
1285 if (tPtr
->flags
.waitingForSelection
)
1287 if(tPtr
->flags
.focused
) {
1288 XGrabPointer(dpy
, W_VIEW(tPtr
)->window
, False
,
1289 PointerMotionMask
|ButtonPressMask
|ButtonReleaseMask
,
1290 GrabModeAsync
, GrabModeAsync
, None
,
1291 W_VIEW(tPtr
)->screen
->invisibleCursor
, CurrentTime
);
1292 tPtr
->flags
.pointerGrabbed
= True
;
1293 handleTextKeyPress(tPtr
, event
);
1298 ksym
= XLookupKeysym((XKeyEvent
*)event
, 0);
1299 if(ksym
== XK_Shift_R
|| ksym
== XK_Shift_L
) {
1300 tPtr
->flags
.extendSelection
= False
;
1302 //end modify flag so selection can be extended
1308 if(tPtr
->flags
.pointerGrabbed
) {
1309 tPtr
->flags
.pointerGrabbed
= False
;
1310 XUngrabPointer(dpy
, CurrentTime
);
1312 if((event
->xmotion
.state
& Button1Mask
)) {
1313 if(!tPtr
->flags
.ownsSelection
) {
1314 WMCreateSelectionHandler(tPtr
->view
, XA_PRIMARY
,
1315 event
->xbutton
.time
, &selectionHandler
, NULL
);
1316 tPtr
->flags
.ownsSelection
= True
;
1318 selectRegion(tPtr
, event
->xmotion
.x
, event
->xmotion
.y
);
1324 tPtr
->flags
.buttonHeld
= True
;
1325 if(tPtr
->flags
.extendSelection
) {
1326 selectRegion(tPtr
, event
->xmotion
.x
, event
->xmotion
.y
);
1329 if(event
->xbutton
.button
== Button1
) {
1330 if(tPtr
->flags
.ownsSelection
)
1331 releaseSelection(tPtr
);
1332 cursorToTextPosition(tPtr
, event
->xmotion
.x
, event
->xmotion
.y
);
1333 if (tPtr
->flags
.pointerGrabbed
) {
1334 tPtr
->flags
.pointerGrabbed
= False
;
1335 XUngrabPointer(dpy
, CurrentTime
);
1339 if(!tPtr
->flags
.focused
) {
1340 WMSetFocusToWidget(tPtr
);
1341 tPtr
->flags
.focused
= True
;
1345 if(event
->xbutton
.button
== WINGsConfiguration
.mouseWheelDown
)
1346 WMScrollText(tPtr
, -16);
1347 else if(event
->xbutton
.button
== WINGsConfiguration
.mouseWheelUp
)
1348 WMScrollText(tPtr
, 16);
1352 tPtr
->flags
.buttonHeld
= False
;
1353 if (tPtr
->flags
.pointerGrabbed
) {
1354 tPtr
->flags
.pointerGrabbed
= False
;
1355 XUngrabPointer(dpy
, CurrentTime
);
1358 if(event
->xbutton
.button
== WINGsConfiguration
.mouseWheelDown
1359 || event
->xbutton
.button
== WINGsConfiguration
.mouseWheelUp
)
1362 if(event
->xbutton
.button
== Button2
&& tPtr
->flags
.editable
) {
1365 if(!WMRequestSelection(tPtr
->view
, XA_PRIMARY
, XA_STRING
,
1366 event
->xbutton
.time
, pasteText
, NULL
)) {
1367 text
= XFetchBuffer(tPtr
->view
->screen
->display
, &n
, 0);
1371 (tPtr
->parser
) (tPtr
, (void *) text
);
1373 insertTextInteractively(tPtr
, text
, n
-1);
1375 WMRefreshText(tPtr
, 0, 0);
1377 } else tPtr
->flags
.waitingForSelection
= True
;
1388 handleEvents(XEvent
*event
, void *data
)
1390 Text
*tPtr
= (Text
*)data
;
1392 switch(event
->type
) {
1394 if(!event
->xexpose
.count
&& tPtr
->view
->flags
.realized
)
1399 if (W_FocusedViewOfToplevel(W_TopLevelOfView(tPtr
->view
))!=tPtr
->view
)
1401 tPtr
->flags
.focused
= True
;
1405 tPtr
->flags
.focused
= False
;
1410 //for(...)WMRemoveTextParagraph(tPtr, para);
1419 clearText(Text
*tPtr
)
1422 if(!tPtr
->firstTextBlock
)
1425 while(tPtr
->currentTextBlock
)
1426 WMDestroyTextBlock(tPtr
, WMRemoveTextBlock(tPtr
));
1428 printf("yadda clearText\n");
1430 printf("remove the document\n");
1431 tPtr
->firstTextBlock
= NULL
;
1432 tPtr
->currentTextBlock
= NULL
;
1433 tPtr
->lastTextBlock
= NULL
;
1435 WMRefreshText(tPtr
, 0, 0);
1440 insertPlainText(WMText
*tPtr
, char *text
)
1454 mark
= strchr(start
, '\n');
1456 tb
= WMCreateTextBlockWithText(start
, tPtr
->dFont
,
1457 tPtr
->dColor
, True
, (int)(mark
-start
));
1460 if(start
&& strlen(start
)) {
1461 tb
= WMCreateTextBlockWithText(start
, tPtr
->dFont
,
1462 tPtr
->dColor
, False
, strlen(start
));
1467 if(tPtr
->flags
.prepend
)
1468 WMPrependTextBlock(tPtr
, tb
);
1470 WMAppendTextBlock(tPtr
, tb
);
1482 WMCreateText(WMWidget
*parent
)
1484 Text
*tPtr
= wmalloc(sizeof(Text
));
1486 printf("could not create text widget\n");
1491 printf("sizeof:\n");
1492 printf(" TextBlock %d\n", sizeof(TextBlock
));
1493 printf(" TextBlock *%d\n", sizeof(TextBlock
*));
1494 printf(" Section %d\n", sizeof(Section
));
1495 printf(" char * %d\n", sizeof(char *));
1496 printf(" void * %d\n", sizeof(void *));
1497 printf(" short %d\n", sizeof(short));
1498 printf(" Text %d\n", sizeof(Text
));
1501 memset(tPtr
, 0, sizeof(Text
));
1502 tPtr
->widgetClass
= WC_Text
;
1503 tPtr
->view
= W_CreateView(W_VIEW(parent
));
1505 perror("could not create text's view\n");
1509 tPtr
->view
->self
= tPtr
;
1510 tPtr
->view
->attribs
.cursor
= tPtr
->view
->screen
->textCursor
;
1511 tPtr
->view
->attribFlags
|= CWOverrideRedirect
| CWCursor
;
1512 W_ResizeView(tPtr
->view
, 250, 200);
1513 tPtr
->bgGC
= WMColorGC(tPtr
->view
->screen
->white
);
1514 tPtr
->fgGC
= WMColorGC(tPtr
->view
->screen
->black
);
1515 W_SetViewBackgroundColor(tPtr
->view
, tPtr
->view
->screen
->white
);
1522 //tPtr->dFont = WMCreateFont(tPtr->view->screen,
1523 // "-*-fixed-medium-r-normal--26-*-*-*-*-*-*-*");
1524 //"-sony-fixed-medium-r-normal--24-230-75-75-c-120-jisx0201.1976-0");
1525 // "-*-times-bold-r-*-*-12-*-*-*-*-*-*-*,"
1526 // "-*-fixed-medium-r-normal-*-12-*");
1528 tPtr
->dFont
= WMRetainFont(tPtr
->view
->screen
->normalFont
);
1530 tPtr
->dColor
= WMBlackColor(tPtr
->view
->screen
);
1532 tPtr
->view
->delegate
= &_TextViewDelegate
;
1534 WMCreateEventHandler(tPtr
->view
, ExposureMask
|StructureNotifyMask
1535 |EnterWindowMask
|LeaveWindowMask
|FocusChangeMask
,
1536 handleEvents
, tPtr
);
1538 WMCreateEventHandler(tPtr
->view
, ButtonReleaseMask
|ButtonPressMask
1539 |KeyReleaseMask
|KeyPressMask
|Button1MotionMask
,
1540 handleActionEvents
, tPtr
);
1542 WMAddNotificationObserver(_notification
, tPtr
, "_lostOwnership", tPtr
);
1545 tPtr
->firstTextBlock
= NULL
;
1546 tPtr
->lastTextBlock
= NULL
;
1547 tPtr
->currentTextBlock
= NULL
;
1550 tPtr
->gfxItems
= WMCreateArrayBag(4);
1552 tPtr
->parser
= NULL
;
1553 tPtr
->writer
= NULL
;
1555 tPtr
->sel
.x
= tPtr
->sel
.y
= 2;
1556 tPtr
->sel
.w
= tPtr
->sel
.h
= 0;
1558 tPtr
->clicked
.x
= tPtr
->clicked
.y
= 2;
1560 tPtr
->visible
.x
= tPtr
->visible
.y
= 2;
1561 tPtr
->visible
.h
= tPtr
->view
->size
.height
;
1562 tPtr
->visible
.w
= tPtr
->view
->size
.width
- 12;
1564 tPtr
->cursor
.x
= -23;
1567 tPtr
->docHeight
= 0;
1568 tPtr
->dBulletPix
= WMCreatePixmapFromXPMData(tPtr
->view
->screen
,
1570 tPtr
->db
= (Pixmap
) NULL
;
1572 tPtr
->margins
= wmalloc(sizeof(WMRulerMargins
));
1573 tPtr
->margins
[0].left
= tPtr
->margins
[0].right
= tPtr
->visible
.x
;
1574 tPtr
->margins
[0].body
= tPtr
->visible
.x
;
1575 tPtr
->margins
[0].right
= tPtr
->visible
.w
;
1577 tPtr
->flags
.nmargins
= 1;
1578 tPtr
->flags
.rulerShown
= False
;
1579 tPtr
->flags
.monoFont
= False
;
1580 tPtr
->flags
.focused
= False
;
1581 tPtr
->flags
.editable
= True
;
1582 tPtr
->flags
.ownsSelection
= False
;
1583 tPtr
->flags
.pointerGrabbed
= False
;
1584 tPtr
->flags
.buttonHeld
= False
;
1585 tPtr
->flags
.waitingForSelection
= False
;
1586 tPtr
->flags
.extendSelection
= False
;
1587 tPtr
->flags
.rulerShown
= False
;
1588 tPtr
->flags
.frozen
= False
;
1589 tPtr
->flags
.cursorShown
= True
;
1590 tPtr
->flags
.clickPos
= 1;
1591 tPtr
->flags
.ignoreNewLine
= False
;
1592 tPtr
->flags
.laidOut
= False
;
1593 tPtr
->flags
.prepend
= False
;
1594 tPtr
->flags
.relief
= WRFlat
;
1595 tPtr
->flags
.alignment
= WALeft
;
1602 WMPrependTextStream(WMText
*tPtr
, char *text
)
1606 //check for "{\rtf0" in the text...
1609 tPtr
->flags
.prepend
= True
;
1610 if(text
&& tPtr
->parser
)
1611 (tPtr
->parser
) (tPtr
, (void *) text
);
1613 insertPlainText(tPtr
, text
);
1618 WMAppendTextStream(WMText
*tPtr
, char *text
)
1622 //check for "{\rtf0" in the text...
1625 tPtr
->flags
.prepend
= False
;
1626 if(text
&& tPtr
->parser
)
1627 (tPtr
->parser
) (tPtr
, (void *) text
);
1629 insertPlainText(tPtr
, text
);
1634 WMGetTextSelected(WMText
*tPtr
)
1636 WMData
*data
= NULL
;
1642 //tb = tPtr->firstTextBlock;
1643 tb
= tPtr
->currentTextBlock
;
1647 data
= WMCreateDataWithBytes(tb
->text
, tb
->used
);
1649 WMSetDataFormat(data
, 8);
1654 WMCreateTextBlockWithObject(WMWidget
*w
, char *description
, WMColor
*color
,
1655 unsigned short first
, unsigned short reserved
)
1658 unsigned short length
;
1660 if(!w
|| !description
|| !color
)
1663 tb
= wmalloc(sizeof(TextBlock
));
1667 length
= strlen(description
);
1668 tb
->text
= (char *)wmalloc(length
);
1669 memset(tb
->text
, 0, length
);
1670 memcpy(tb
->text
, description
, length
);
1674 tb
->color
= WMRetainColor(color
);
1680 tb
->underlined
= False
;
1682 tb
->sections
= NULL
;
1691 WMCreateTextBlockWithText(char *text
, WMFont
*font
, WMColor
*color
,
1692 unsigned short first
, unsigned short length
)
1699 tb
= wmalloc(sizeof(TextBlock
));
1703 tb
->allocated
= reqBlockSize(length
);
1704 tb
->text
= (char *)wmalloc(tb
->allocated
);
1705 memset(tb
->text
, 0, tb
->allocated
);
1707 if(length
< 1|| !text
) { // || *text == '\n') {
1712 memcpy(tb
->text
, text
, length
);
1717 tb
->d
.font
= WMRetainFont(font
);
1718 tb
->color
= WMRetainColor(color
);
1722 tb
->graphic
= False
;
1723 tb
->underlined
= False
;
1725 tb
->sections
= NULL
;
1733 WMSetTextBlockProperties(void *vtb
, unsigned int first
,
1734 unsigned int kanji
, unsigned int underlined
, int script
,
1735 unsigned int marginN
)
1737 TextBlock
*tb
= (TextBlock
*) vtb
;
1743 tb
->underlined
= underlined
;
1744 tb
->script
= script
;
1745 tb
->marginN
= marginN
;
1749 WMGetTextBlockProperties(void *vtb
, unsigned int *first
,
1750 unsigned int *kanji
, unsigned int *underlined
, int *script
,
1751 unsigned int *marginN
)
1753 TextBlock
*tb
= (TextBlock
*) vtb
;
1757 if(first
) *first
= tb
->first
;
1758 if(kanji
) *kanji
= tb
->kanji
;
1759 if(underlined
) *underlined
= tb
->underlined
;
1760 if(script
) *script
= tb
->script
;
1761 if(marginN
) *marginN
= tb
->marginN
;
1767 WMPrependTextBlock(WMText
*tPtr
, void *vtb
)
1769 TextBlock
*tb
= (TextBlock
*)vtb
;
1776 WMWidget
*w
= tb
->d
.widget
;
1777 WMCreateEventHandler(W_VIEW(w
), ButtonPressMask
,
1778 handleWidgetPress
, tb
);
1779 if(W_CLASS(w
) != WC_TextField
&& W_CLASS(w
) != WC_Text
) {
1780 (W_VIEW(w
))->attribs
.cursor
= tPtr
->view
->screen
->defaultCursor
;
1781 (W_VIEW(w
))->attribFlags
|= CWOverrideRedirect
| CWCursor
;
1783 WMPutInBag(tPtr
->gfxItems
, (void *)tb
);
1786 } else tPtr
->tpos
= tb
->used
;
1788 if(!tPtr
->lastTextBlock
|| !tPtr
->firstTextBlock
) {
1789 tb
->next
= tb
->prior
= NULL
;
1790 tPtr
->lastTextBlock
= tPtr
->firstTextBlock
1791 = tPtr
->currentTextBlock
= tb
;
1795 tb
->next
= tPtr
->currentTextBlock
;
1796 tb
->prior
= tPtr
->currentTextBlock
->prior
;
1797 if(tPtr
->currentTextBlock
->prior
)
1798 tPtr
->currentTextBlock
->prior
->next
= tb
;
1800 tPtr
->currentTextBlock
->prior
= tb
;
1802 tPtr
->firstTextBlock
= tb
;
1804 tPtr
->currentTextBlock
= tb
;
1809 WMAppendTextBlock(WMText
*tPtr
, void *vtb
)
1811 TextBlock
*tb
= (TextBlock
*)vtb
;
1817 WMWidget
*w
= tb
->d
.widget
;
1818 WMCreateEventHandler(W_VIEW(w
), ButtonPressMask
,
1819 handleWidgetPress
, tb
);
1820 if(W_CLASS(w
) != WC_TextField
&& W_CLASS(w
) != WC_Text
) {
1821 (W_VIEW(w
))->attribs
.cursor
= tPtr
->view
->screen
->defaultCursor
;
1822 (W_VIEW(w
))->attribFlags
|= CWOverrideRedirect
| CWCursor
;
1824 WMPutInBag(tPtr
->gfxItems
, (void *)tb
);
1827 } else tPtr
->tpos
= tb
->used
;
1829 if(!tPtr
->lastTextBlock
|| !tPtr
->firstTextBlock
) {
1830 tb
->next
= tb
->prior
= NULL
;
1831 tPtr
->lastTextBlock
= tPtr
->firstTextBlock
1832 = tPtr
->currentTextBlock
= tb
;
1836 tb
->next
= tPtr
->currentTextBlock
->next
;
1837 tb
->prior
= tPtr
->currentTextBlock
;
1838 if(tPtr
->currentTextBlock
->next
)
1839 tPtr
->currentTextBlock
->next
->prior
= tb
;
1841 tPtr
->currentTextBlock
->next
= tb
;
1844 tPtr
->lastTextBlock
= tb
;
1846 tPtr
->currentTextBlock
= tb
;
1850 WMRemoveTextBlock(WMText
*tPtr
)
1852 TextBlock
*tb
= NULL
;
1854 if(!tPtr
|| !tPtr
->firstTextBlock
|| !tPtr
->lastTextBlock
1855 || !tPtr
->currentTextBlock
) {
1856 printf("cannot remove non existent TextBlock!\b");
1860 tb
= tPtr
->currentTextBlock
;
1862 WMDeleteEventHandler(W_VIEW(tb
->d
.widget
), ButtonPressMask
,
1863 handleWidgetPress
, tb
);
1864 WMRemoveFromBag(tPtr
->gfxItems
, (void *)tb
);
1865 WMUnmapWidget(tb
->d
.widget
);
1868 if(tPtr
->currentTextBlock
== tPtr
->firstTextBlock
) {
1869 if(tPtr
->currentTextBlock
->next
)
1870 tPtr
->currentTextBlock
->next
->prior
= NULL
;
1872 tPtr
->firstTextBlock
= tPtr
->currentTextBlock
->next
;
1873 tPtr
->currentTextBlock
= tPtr
->firstTextBlock
;
1875 } else if(tPtr
->currentTextBlock
== tPtr
->lastTextBlock
) {
1876 tPtr
->currentTextBlock
->prior
->next
= NULL
;
1877 tPtr
->lastTextBlock
= tPtr
->currentTextBlock
->prior
;
1878 tPtr
->currentTextBlock
= tPtr
->lastTextBlock
;
1880 tPtr
->currentTextBlock
->prior
->next
= tPtr
->currentTextBlock
->next
;
1881 tPtr
->currentTextBlock
->next
->prior
= tPtr
->currentTextBlock
->prior
;
1882 tPtr
->currentTextBlock
= tPtr
->currentTextBlock
->next
;
1889 WMDestroyTextBlock(WMText
*tPtr
, void *vtb
)
1891 TextBlock
*tb
= (TextBlock
*)vtb
;
1897 WMDestroyWidget(tb
->d
.widget
);
1898 wfree(tb
->d
.widget
);
1900 WMReleaseFont(tb
->d
.font
);
1903 WMReleaseColor(tb
->color
);
1904 if(tb
->sections
&& tb
->nsections
> 0)
1905 wfree(tb
->sections
);
1912 WMRefreshText(WMText
*tPtr
, int vpos
, int hpos
)
1916 if(!tPtr
|| vpos
<0 || hpos
<0)
1919 tPtr
->flags
.laidOut
= False
;
1920 layOutDocument(tPtr
);
1921 updateScrollers(tPtr
);
1928 WMSetTextForegroundColor(WMText
*tPtr
, WMColor
*color
)
1934 tPtr
->fgGC
= WMColorGC(color
);
1936 tPtr
->fgGC
= WMColorGC(WMBlackColor(tPtr
->view
->screen
));
1938 WMRefreshText(tPtr
, tPtr
->vpos
, tPtr
->hpos
);
1942 WMSetTextBackgroundColor(WMText
*tPtr
, WMColor
*color
)
1948 tPtr
->bgGC
= WMColorGC(color
);
1949 W_SetViewBackgroundColor(tPtr
->view
, color
);
1951 tPtr
->bgGC
= WMColorGC(WMWhiteColor(tPtr
->view
->screen
));
1952 W_SetViewBackgroundColor(tPtr
->view
,
1953 WMWhiteColor(tPtr
->view
->screen
));
1956 WMRefreshText(tPtr
, tPtr
->vpos
, tPtr
->hpos
);
1960 WMSetTextRelief(WMText
*tPtr
, WMReliefType relief
)
1964 tPtr
->flags
.relief
= relief
;
1969 WMSetTextHasHorizontalScroller(WMText
*tPtr
, Bool shouldhave
)
1974 if(shouldhave
&& !tPtr
->hS
) {
1975 tPtr
->hS
= WMCreateScroller(tPtr
);
1976 (W_VIEW(tPtr
->hS
))->attribs
.cursor
= tPtr
->view
->screen
->defaultCursor
;
1977 (W_VIEW(tPtr
->hS
))->attribFlags
|= CWOverrideRedirect
| CWCursor
;
1978 WMSetScrollerArrowsPosition(tPtr
->hS
, WSAMaxEnd
);
1979 WMSetScrollerAction(tPtr
->hS
, scrollersCallBack
, tPtr
);
1980 WMRealizeWidget(tPtr
->hS
);
1981 WMMapWidget(tPtr
->hS
);
1982 } else if(!shouldhave
&& tPtr
->hS
) {
1983 WMUnmapWidget(tPtr
->hS
);
1984 WMDestroyWidget(tPtr
->hS
);
1990 textDidResize(tPtr
->view
->delegate
, tPtr
->view
);
1995 WMSetTextHasVerticalScroller(WMText
*tPtr
, Bool shouldhave
)
2000 if(shouldhave
&& !tPtr
->vS
) {
2001 tPtr
->vS
= WMCreateScroller(tPtr
);
2002 (W_VIEW(tPtr
->vS
))->attribs
.cursor
= tPtr
->view
->screen
->defaultCursor
;
2003 (W_VIEW(tPtr
->vS
))->attribFlags
|= CWOverrideRedirect
| CWCursor
;
2004 WMSetScrollerArrowsPosition(tPtr
->vS
, WSAMaxEnd
);
2005 WMSetScrollerAction(tPtr
->vS
, scrollersCallBack
, tPtr
);
2006 WMRealizeWidget(tPtr
->vS
);
2007 WMMapWidget(tPtr
->vS
);
2008 } else if(!shouldhave
&& tPtr
->vS
) {
2009 WMUnmapWidget(tPtr
->vS
);
2010 WMDestroyWidget(tPtr
->vS
);
2016 textDidResize(tPtr
->view
->delegate
, tPtr
->view
);
2022 WMScrollText(WMText
*tPtr
, int amount
)
2027 if(amount
== 0 || !tPtr
->view
->flags
.realized
)
2031 if(tPtr
->vpos
> 0) {
2032 if(tPtr
->vpos
> amount
) tPtr
->vpos
+= amount
;
2036 int limit
= tPtr
->docHeight
- tPtr
->visible
.h
;
2037 if(tPtr
->vpos
< limit
) {
2038 if(tPtr
->vpos
< limit
-amount
) tPtr
->vpos
+= amount
;
2039 else tPtr
->vpos
= limit
;
2043 if(scroll
&& tPtr
->vpos
!= tPtr
->prevVpos
) {
2044 updateScrollers(tPtr
);
2047 tPtr
->prevVpos
= tPtr
->vpos
;
2052 WMPageText(WMText
*tPtr
, Bool direction
)
2054 if(!tPtr
) return False
;
2055 if(!tPtr
->view
->flags
.realized
) return False
;
2057 return WMScrollText(tPtr
, direction
?tPtr
->visible
.h
:-tPtr
->visible
.h
);
2062 WMSetTextUseMonoFont(WMText
*tPtr
, Bool mono
)
2066 if(mono
&& tPtr
->flags
.rulerShown
)
2067 ;//WMShowTextRuler(tPtr, False);
2069 tPtr
->flags
.monoFont
= mono
;
2070 WMRefreshText(tPtr
, tPtr
->vpos
, tPtr
->hpos
);
2074 WMGetTextUsesMonoFont(WMText
*tPtr
)
2078 return tPtr
->flags
.monoFont
;
2082 WMSetTextDefaultFont(WMText
*tPtr
, WMFont
*font
)
2090 tPtr
->dFont
= WMRetainFont(tPtr
->view
->screen
->normalFont
);
2094 WMGetTextDefaultFont(WMText
*tPtr
)
2103 WMSetTextParser(WMText
*tPtr
, WMAction
*parser
)
2107 tPtr
->parser
= parser
;
2112 WMSetTextWriter(WMText
*tPtr
, WMAction
*writer
)
2116 tPtr
->writer
= writer
;
2120 WMGetTextInsertType(WMText
*tPtr
)
2124 return tPtr
->flags
.prepend
;