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.
23 #include <X11/keysym.h>
24 #include <X11/Xatom.h>
32 use currentTextBlock
and neighbours
for fast paint
and layout
34 WMGetTextStreamAll
... WMGetTextStream
WMGetTextSelection(if(selected
) )
36 the bitfield arrangement in
this code assumes a little
-endian
37 machine
... might need a __BIG_ENDIAN__ define
for arranging
38 the bitfields efficiently
for those big boys
.
40 make a file named fontman
.c
, put that kind of
41 stuff in there
and not put the APIs in WINGs
.h
42 WMGetFontItalic() should some day be part of the font manager
43 instead
, just put a bunch of
extern WMGetFontbla in the top of wtext
.c
52 /* a Section is a section of a TextBlock that describes what parts
53 of a TextBlock has be layout on which "line"...
54 o this greatly aids redraw, scroll and selection.
55 o this is created during layoutLine, but may be later modified.
56 o there may be many regions per TextBlock, hence the array */
58 int x
, y
; /* where to draw it from */
59 int w
, h
; /* it's width and height (to aid selection) */
61 unsigned short begin
, end
; /* what part of the text block */
65 /* a TextBlock is a doubly-linked list of TextBlocks containing:
66 o text for the block, color and font
67 o or a pointer to the widget and the (text) description for its graphic
70 typedef struct _TextBlock
{
71 struct _TextBlock
*next
; /* next text block in linked list */
72 struct _TextBlock
*prior
; /* prior text block in linked list */
74 char *text
; /* pointer to 8- or 16-bit text */
75 /* or to the object's description */
77 WMFont
*font
; /* the font */
78 WMWidget
*widget
; /* the embedded widget */
79 } d
; /* description */
81 WMColor
*color
; /* the color */
82 Section
*sections
; /* the region for layouts (a growable array) */
83 /* an _array_! of size _nsections_ */
85 unsigned short used
; /* number of chars in this block */
86 unsigned short allocated
; /* size of allocation (in chars) */
88 unsigned int first
:1; /* first TextBlock in paragraph */
89 unsigned int blank
:1; /* ie. blank paragraph */
90 unsigned int kanji
:1; /* is of 16-bit characters or not */
91 unsigned int graphic
:1; /* embedded object or text: text=0 */
92 unsigned int underlined
:1; /* underlined or not */
93 unsigned int nsections
:8; /* over how many "lines" a TexBlock wraps */
94 int script
:8; /* script in points: negative for subscript */
95 unsigned int marginN
:10; /* which of the margins in WMText to use */
96 unsigned int RESERVED
:1;
100 /* somehow visible.h beats the hell outta visible.size.height :-) */
109 typedef struct W_Text
{
110 W_Class widgetClass
; /* the class number of this widget */
111 W_View
*view
; /* the view referring to this instance */
113 WMRuler
*ruler
; /* the ruler subwiget to manipulate paragraphs */
115 WMScroller
*vS
; /* the vertical scroller */
116 int vpos
; /* the current vertical position */
117 int prevVpos
; /* the previous vertical position */
119 WMScroller
*hS
; /* the horizontal scroller */
120 int hpos
; /* the current horizontal position */
121 int prevHpos
; /* the previous horizontal position */
122 /* in short: tPtr->hS?nowrap:wrap */
124 WMFont
*dFont
; /* the default font */
125 WMColor
*dColor
; /* the default color */
126 WMPixmap
*dBulletPix
; /* the default pixmap for bullets */
128 GC bgGC
; /* the background GC to draw with */
129 GC fgGC
; /* the foreground GC to draw with */
130 Pixmap db
; /* the buffer on which to draw */
132 WMRulerMargins
*margins
;/* a (growable) array of margins to be used */
133 /* by the various TextBlocks */
135 myRect visible
; /* the actual rectangle that can be drawn into */
136 myRect sel
; /* the selection rectangle */
137 int docWidth
; /* the width of the entire document */
138 int docHeight
; /* the height of the entire document */
141 TextBlock
*firstTextBlock
;
142 TextBlock
*lastTextBlock
;
143 TextBlock
*currentTextBlock
;
146 WMBag
*gfxItems
; /* a nice bag containing graphic items */
148 WMPoint clicked
; /* where in the _document_ was clicked */
149 unsigned short tpos
; /* the character position in the currentTextBlock */
150 unsigned short RESERVED
;/* space taker upper... */
157 unsigned int monoFont
:1; /* whether to ignore formats */
158 unsigned int focused
:1; /* whether this instance has input focus */
159 unsigned int editable
:1; /* "silly user, you can't edit me" */
160 unsigned int ownsSelection
:1; /* "I ownz the current selection!" */
161 unsigned int pointerGrabbed
:1;/* "heh, gib me pointer" */
162 unsigned int buttonHeld
:1; /* the user is holding down the button */
163 unsigned int waitingForSelection
:1; /* dum dee dumm... */
164 unsigned int extendSelection
:1; /* shift-drag to select more regions */
166 unsigned int rulerShown
:1; /* whether the ruler is shown or not */
167 unsigned int frozen
:1; /* whether screen updates are to be made */
168 unsigned int cursorShown
:1; /* whether to show the cursor */
169 unsigned int clickPos
:1; /* clicked before=0/after=1 a graphic: */
170 /* within counts as after too */
172 unsigned int ignoreNewLine
:1;/* "bleh XK_Return" ignore it when typed */
173 unsigned int laidOut
:1; /* have the TextBlocks all been laid out */
174 unsigned int prepend
:1; /* prepend=1, append=0 (for parsers) */
175 WMAlignment alignment
:2; /* the alignment for text */
176 WMReliefType relief
:3; /* the relief to display with */
177 unsigned int RESERVED
:4;
178 unsigned int nmargins
:10; /* the number of margin arrays */
182 static char *default_bullet
[] = {
184 " c None s None", ". c black",
185 "X c white", "o c #808080",
194 /* done purely for speed ... mostly same as WMWidthOfString */
195 static inline unsigned int
196 myWidthOfString(WMFont
*font
, char *text
, unsigned int length
)
198 if (font
->notFontSet
)
199 return XTextWidth(font
->font
.normal
, text
, length
);
201 XRectangle rect
, AIXsucks
;
202 XmbTextExtents(font
->font
.set
, text
, length
, &AIXsucks
, &rect
);
209 paintText(Text
*tPtr
)
211 TextBlock
*tb
= tPtr
->firstTextBlock
;
215 int len
, y
, c
, s
, done
=False
;
217 WMScreen
*scr
= tPtr
->view
->screen
;
218 Display
*dpy
= tPtr
->view
->screen
->display
;
219 Window win
= tPtr
->view
->window
;
223 if(!tPtr
->view
->flags
.realized
|| !tPtr
->db
)
226 XFillRectangle(dpy
, tPtr
->db
, tPtr
->bgGC
,
227 0, 0, tPtr
->visible
.w
, tPtr
->visible
.h
);
230 tb
= tPtr
->firstTextBlock
;
235 if(tPtr
->flags
.ownsSelection
) {
236 greyGC
= WMColorGC(WMGrayColor(scr
));
237 //XFillRectangle(dpy, tPtr->db, greyGC,
238 // tPtr->sel.x, tPtr->sel.y-tPtr->vpos, tPtr->sel.w, tPtr->sel.h);
239 // XDrawRectangle(dpy, tPtr->db, tPtr->fgGC,
240 // tPtr->sel.x, tPtr->sel.y-tPtr->vpos, tPtr->sel.w, tPtr->sel.h);
246 if(!tb
->sections
|| (!tPtr
->flags
.monoFont
&& tb
->graphic
)) {
251 for(s
=0; s
<tb
->nsections
&& !done
; s
++) {
254 if(tb
->sections
[s
]._y
> tPtr
->vpos
+ tPtr
->visible
.h
) {
259 if( tb
->sections
[s
].y
+ tb
->sections
[s
].h
< tPtr
->vpos
)
262 if(tPtr
->flags
.monoFont
) {
267 gc
= WMColorGC(tb
->color
);
270 if(tPtr
->flags
.ownsSelection
) {
272 if(prev_y
!= tb
->sections
[s
]._y
273 && (tb
->sections
[s
]._y
>= tPtr
->sel
.y
)
274 && (tb
->sections
[s
]._y
+ tb
->sections
[s
].h
275 <= tPtr
->sel
.y
+ tPtr
->sel
.h
)) {
276 XFillRectangle(dpy
, tPtr
->db
, greyGC
,
278 tPtr
->visible
.y
+ tb
->sections
[s
]._y
- tPtr
->vpos
,
279 tPtr
->visible
.w
, tb
->sections
[s
].h
);
281 } else if( prev_y
!= tb
->sections
[s
]._y
282 && (tb
->sections
[s
]._y
<= tPtr
->sel
.y
)
283 && (tb
->sections
[s
]._y
+ tb
->sections
[s
].h
285 && (tPtr
->sel
.x
>= tb
->sections
[s
].x
)
286 && (tPtr
->sel
.y
+ tPtr
->sel
.h
287 >= tb
->sections
[s
]._y
+ tb
->sections
[s
].h
)) {
288 XFillRectangle(dpy
, tPtr
->db
, greyGC
,
290 tPtr
->visible
.y
+ tb
->sections
[s
]._y
- tPtr
->vpos
,
291 tPtr
->visible
.w
- tPtr
->sel
.x
, tb
->sections
[s
].h
);
293 } else if(prev_y
!= tb
->sections
[s
]._y
294 && (tb
->sections
[s
]._y
<= tPtr
->sel
.y
+ tPtr
->sel
.h
)
295 && (tb
->sections
[s
]._y
>= tPtr
->sel
.y
)) {
296 XFillRectangle(dpy
, tPtr
->db
, greyGC
,
298 tPtr
->visible
.y
+ tb
->sections
[s
]._y
- tPtr
->vpos
,
299 tPtr
->sel
.x
+ tPtr
->sel
.w
-tPtr
->visible
.x
,
302 } else if( prev_y
!= tb
->sections
[s
]._y
303 && (tb
->sections
[s
]._y
<= tPtr
->sel
.y
)
304 && (tb
->sections
[s
]._y
+ tb
->sections
[s
].h
305 >= tPtr
->sel
.y
+ tPtr
->sel
.h
) ) {
306 XFillRectangle(dpy
, tPtr
->db
, greyGC
,
308 tPtr
->visible
.y
+ tb
->sections
[s
]._y
- tPtr
->vpos
,
309 tPtr
->sel
.w
,tb
->sections
[s
].h
);
314 prev_y
= tb
->sections
[s
]._y
;
316 len
= tb
->sections
[s
].end
- tb
->sections
[s
].begin
;
317 text
= &(tb
->text
[tb
->sections
[s
].begin
]);
318 y
= tb
->sections
[s
].y
- tPtr
->vpos
;
319 WMDrawString(scr
, tPtr
->db
, gc
, font
,
320 tb
->sections
[s
].x
, y
, text
, len
);
323 XDrawLine(dpy
, tPtr
->db
, gc
,
324 tb
->sections
[s
].x
, y
+ font
->y
+ 1,
325 tb
->sections
[s
].x
+ tb
->sections
[s
].w
, y
+ font
->y
+ 1);
330 tb
= (!done
? tb
->next
: NULL
);
334 c
= WMGetBagItemCount(tPtr
->gfxItems
);
335 if(c
> 0 && !tPtr
->flags
.monoFont
) {
339 tb
= (TextBlock
*)WMGetFromBag(tPtr
->gfxItems
, j
);
340 if(!tb
|| !tb
->sections
)
343 if(tb
->sections
[0]._y
+ tb
->sections
[0].h
345 || tb
->sections
[0]._y
346 >= tPtr
->vpos
+ tPtr
->visible
.h
) {
348 if((W_VIEW(wdt
))->flags
.mapped
) {
352 if(!(W_VIEW(wdt
))->flags
.mapped
) {
355 (W_VIEW(wdt
))->window
);
358 if(tPtr
->flags
.ownsSelection
&& 0
359 //&& (tb->sections[s]._y >= tPtr->sel.y)
360 //&& (tb->sections[s]._y + tb->sections[s].h
361 ){ // <= tPtr->sel.y + tPtr->sel.h)) {
362 XFillRectangle(dpy
, tPtr
->db
, greyGC
,
363 tb
->sections
[0].x
, tb
->sections
[0].y
- tPtr
->vpos
,
364 tb
->sections
[0].w
, tb
->sections
[0].h
);
367 WMMoveWidget(wdt
, 3 + tb
->sections
[0].x
+ tPtr
->visible
.x
,
368 tb
->sections
[0].y
- tPtr
->vpos
);
371 XDrawLine(dpy
, tPtr
->db
, WMColorGC(tb
->color
),
373 tb
->sections
[0].y
+ WMWidgetHeight(wdt
) + 1,
374 tb
->sections
[0].x
+ tb
->sections
[0].w
,
375 tb
->sections
[0].y
+ WMWidgetHeight(wdt
) + 1);
383 XCopyArea(dpy
, tPtr
->db
, win
, tPtr
->bgGC
,
385 tPtr
->visible
.w
, tPtr
->visible
.h
,
386 tPtr
->visible
.x
, tPtr
->visible
.y
);
388 W_DrawRelief(scr
, win
, 0, 0,
389 tPtr
->view
->size
.width
, tPtr
->view
->size
.height
,
392 if(tPtr
->ruler
&& tPtr
->flags
.rulerShown
)
395 tPtr
->view
->size
.width
-4, 42);
398 XFillRectangle(tPtr->view->screen->display, tPtr->view->window,
400 2, tPtr->view->size.height-3,
401 tPtr->view->size.width-4, 3);
408 cursorToTextPosition(Text
*tPtr
, int x
, int y
)
410 TextBlock
*tb
= NULL
;
411 int done
=False
, s
, len
, _w
, _y
, dir
=1; /* 1 == "down" */
416 y
+= tPtr
->vpos
- tPtr
->visible
.y
;
419 x
-= tPtr
->visible
.x
-2;
425 /* first, which direction?, most likely, newly clicked
426 position will be close to previous */
427 tb
= tPtr
->currentTextBlock
;
429 tb
= tPtr
->firstTextBlock
;
430 if(!tb
|| !tb
->sections
)
433 if(y
< tb
->sections
[0].y
)
436 //tb = tPtr->firstTextBlock;
440 if(y
== tb
->sections
[0].y
)
441 goto _doneV
; /* yeah yeah, goto, whatever... :-P */
443 /* get the first section of the first TextBlock based on v. position */
446 if(tPtr
->flags
.monoFont
&& tb
->graphic
) {
451 printf("tb %p t[%c] blank%d graphic %d\n", tb
,
452 *tb
->text
, tb
->blank
, tb
->graphic
);
454 printf("we have a bad thing!\n");
457 s
= (dir
? 0 : tb
->nsections
-1);
458 while( (dir
? (s
<tb
->nsections
) : (s
>=0) )) {
459 if( y
>= tb
->sections
[s
]._y
460 && y
<= tb
->sections
[s
]._y
+ tb
->sections
[s
].h
) {
466 if(!done
) tb
= (dir
? tb
->next
: tb
->prior
);
470 /* we have the line, which TextBlock on that line is it? */
472 _y
= tb
->sections
[s
]._y
;
477 if(_y
!= tb
->sections
[s
]._y
)
481 _w
= WMWidgetWidth(tb
->d
.widget
);
483 text
= &(tb
->text
[tb
->sections
[s
].begin
]);
484 len
= tb
->sections
[s
].end
- tb
->sections
[s
].begin
;
486 _w
= myWidthOfString(font
, text
, len
);
488 if(tb
->sections
[s
].x
+ _w
>= x
)
494 /* we have said TextBlock, now where within it? */
495 if(tb
&& !tb
->graphic
) {
496 int begin
= tb
->sections
[s
].begin
;
497 int end
= tb
->sections
[s
].end
;
500 text
= &(tb
->text
[begin
]);
503 _w
= x
- tb
->sections
[s
].x
;
506 while(i
<len
&& myWidthOfString(font
, text
, i
+1) < _w
)
510 tPtr
->tpos
= (i
<tb
->used
)?i
:tb
->used
;
514 //tb = tPtr->firstTextBlock;
515 tPtr
->currentTextBlock
= tb
;
517 if(tb
&&tb
->graphic
) printf("graphic\n");
521 updateScrollers(Text
*tPtr
)
525 if(tPtr
->docHeight
< tPtr
->visible
.h
) {
526 WMSetScrollerParameters(tPtr
->vS
, 0, 1);
529 float vmax
= (float)(tPtr
->docHeight
);
530 WMSetScrollerParameters(tPtr
->vS
,
531 ((float)tPtr
->vpos
)/(vmax
- (float)tPtr
->visible
.h
),
532 (float)tPtr
->visible
.h
/vmax
);
534 } else tPtr
->vpos
= 0;
541 scrollersCallBack(WMWidget
*w
, void *self
)
543 Text
*tPtr
= (Text
*)self
;
548 if(!tPtr
->view
->flags
.realized
) return;
553 vmax
= (float)(tPtr
->docHeight
);
554 height
= tPtr
->visible
.h
;
556 which
= WMGetScrollerHitPart(tPtr
->vS
);
558 case WSDecrementLine
:
560 if(tPtr
->vpos
>16) tPtr
->vpos
-=16;
564 case WSIncrementLine
: {
565 int limit
= tPtr
->docHeight
- height
;
566 if(tPtr
->vpos
< limit
) {
567 if(tPtr
->vpos
<limit
-16) tPtr
->vpos
+=16;
568 else tPtr
->vpos
=limit
;
571 case WSDecrementPage
:
572 tPtr
->vpos
-= height
;
578 printf("dimple needs to jump to mouse location ;-/\n");
580 case WSIncrementPage
:
581 tPtr
->vpos
+= height
;
582 if(tPtr
->vpos
> (tPtr
->docHeight
- height
))
583 tPtr
->vpos
= tPtr
->docHeight
- height
;
586 printf("dimple needs to jump to mouse location ;-/\n");
591 tPtr
->vpos
= WMGetScrollerValue(tPtr
->vS
)
592 * (float)(tPtr
->docHeight
- height
);
598 printf("WSNoPart, WSKnobSlot\n");
600 float vmax
= (float)(tPtr
->docHeight
);
601 ((float)tPtr
->vpos
)/(vmax
- (float)tPtr
->visible
.h
),
602 (float)tPtr
->visible
.h
/vmax
;
603 dimple
=where mouse is
.
607 scroll
= (tPtr
->vpos
!= tPtr
->prevVpos
);
608 tPtr
->prevVpos
= tPtr
->vpos
;
618 XClearArea(tPtr->view->screen->display, tPtr->view->window, 22, 47,
619 tPtr->view->size.width-24, tPtr->view->size.height-49, True);
621 XClearArea(tPtr->view->screen->display, tPtr->view->window, 22, 2,
622 tPtr->view->size.width-24, tPtr->view->size.height-4, True);
625 if(which
== WSDecrementLine
|| which
== WSIncrementLine
)
626 updateScrollers(tPtr
);
635 unsigned short begin
, end
; /* what part of the text block */
641 layOutLine(Text
*tPtr
, myLineItems
*items
, int nitems
, int x
, int y
,
642 int pwidth
, WMAlignment align
)
644 int i
, j
=0; /* j = justification */
645 int line_width
= 0, line_height
=0, max_descent
=0;
651 TextBlock
*tbsame
=NULL
;
653 for(i
=0; i
<nitems
; i
++) {
657 if(!tPtr
->flags
.monoFont
) {
658 WMWidget
*wdt
= tb
->d
.widget
;
659 line_height
= WMAX(line_height
, WMWidgetHeight(wdt
));
661 line_width
+= WMWidgetWidth(wdt
);
666 font
= (tPtr
->flags
.monoFont
)?tPtr
->dFont
: tb
->d
.font
;
667 max_descent
= WMAX(max_descent
, font
->height
-font
->y
);
668 line_height
= WMAX(line_height
, font
->height
); //+font->height-font->y);
669 text
= &(tb
->text
[items
[i
].begin
]);
670 len
= items
[i
].end
- items
[i
].begin
;
672 line_width
+= myWidthOfString(font
, text
, len
);
676 if(align
== WARight
) {
677 j
= pwidth
- line_width
;
678 } else if (align
== WACenter
) {
679 j
= (int) ((float)(pwidth
- line_width
))/2.0;
684 for(i
=0; i
<nitems
; i
++) {
687 if(tbsame
== tb
) { /*extend it, since it's on same line */
688 tb
->sections
[tb
->nsections
-1].end
= items
[i
].end
;
690 tb
->sections
= wrealloc(tb
->sections
,
691 (++tb
->nsections
)*sizeof(Section
));
692 tb
->sections
[tb
->nsections
-1]._y
= y
;
693 tb
->sections
[tb
->nsections
-1].x
= x
+j
;
694 tb
->sections
[tb
->nsections
-1].h
= line_height
;
695 tb
->sections
[tb
->nsections
-1].begin
= items
[i
].begin
;
696 tb
->sections
[tb
->nsections
-1].end
= items
[i
].end
;
701 if(!tPtr
->flags
.monoFont
) {
702 WMWidget
*wdt
= tb
->d
.widget
;
703 tb
->sections
[tb
->nsections
-1].y
= 1 +max_descent
+
704 y
+ line_height
- WMWidgetHeight(wdt
);
705 tb
->sections
[tb
->nsections
-1].w
= WMWidgetWidth(wdt
);
706 x
+= tb
->sections
[tb
->nsections
-1].w
;
709 font
= (tPtr
->flags
.monoFont
)? tPtr
->dFont
: tb
->d
.font
;
710 len
= items
[i
].end
- items
[i
].begin
;
712 text
= &(tb
->text
[items
[i
].begin
]);
714 tb
->sections
[tb
->nsections
-1].y
= y
+line_height
-font
->y
;
715 tb
->sections
[tb
->nsections
-1].w
=
716 myWidthOfString(font
,
717 &(tb
->text
[tb
->sections
[tb
->nsections
-1].begin
]),
718 tb
->sections
[tb
->nsections
-1].end
-
719 tb
->sections
[tb
->nsections
-1].begin
);
721 x
+= myWidthOfString(font
, text
, len
);
727 return line_height
+(gfx
?10:0);
733 output(char *ptr
, int len
)
738 printf(" s is [%s] (%d)\n", s
, strlen(s
));
743 #define MAX_TB_PER_LINE 64
746 layOutDocument(Text
*tPtr
)
749 myLineItems items
[MAX_TB_PER_LINE
];
750 WMAlignment align
= WALeft
;
752 Bool lhc
= !tPtr
->flags
.laidOut
; /* line height changed? */
755 int nitems
=0, x
=0, y
=0, line_width
= 0, width
=0;
756 int pwidth
= tPtr
->visible
.w
- tPtr
->visible
.x
;
758 char *start
=NULL
, *mark
=NULL
;
761 if(!(tb
= tPtr
->firstTextBlock
)) {
762 printf("clear view... *pos=0\n");
766 if(0&&tPtr
->flags
.laidOut
) {
767 tb
= tPtr
->currentTextBlock
;
768 if(tb
->sections
&& tb
->nsections
>0)
769 prev_y
= tb
->sections
[tb
->nsections
-1]._y
;
771 printf("1 prev_y %d \n", prev_y
);
773 /* search backwards for textblocks on same line */
775 if(!tb
->sections
|| tb
->nsections
<1) {
776 tb
= tPtr
->firstTextBlock
;
779 if(tb
->sections
[tb
->nsections
-1]._y
!= prev_y
) {
783 // prev_y = tb->sections[tb->nsections-1]._y;
786 y
= 0;//tb->sections[tb->nsections-1]._y;
787 printf("2 prev_y %d \n\n", tb
->sections
[tb
->nsections
-1]._y
);
793 if(tb
->sections
&& tb
->nsections
>0) {
800 y
+= layOutLine(tPtr
, items
, nitems
, x
, y
, pwidth
, align
);
801 x
= 0;//tPtr->visible.x+2;
807 if(!tPtr
->flags
.monoFont
) {
808 width
= WMWidgetWidth(tb
->d
.widget
);
809 if(width
> pwidth
)printf("rescale graphix to fit?\n");
811 if(line_width
>= pwidth
- x
812 || nitems
>= MAX_TB_PER_LINE
) {
813 y
+= layOutLine(tPtr
, items
, nitems
, x
, y
,
816 x
= 0;//tPtr->visible.x+2;
820 items
[nitems
].tb
= tb
;
821 items
[nitems
].begin
= 0;
822 items
[nitems
].end
= 0;
826 } else if((start
= tb
->text
)) {
828 font
= tPtr
->flags
.monoFont
?tPtr
->dFont
:tb
->d
.font
;
831 mark
= strchr(start
, ' ');
833 end
+= (int)(mark
-start
)+1;
836 end
+= strlen(start
);
842 width
= myWidthOfString(font
,
843 &tb
->text
[begin
], end
-begin
);
845 if(width
> pwidth
) { /* break this tb up */
846 char *t
= &tb
->text
[begin
];
847 int l
=end
-begin
, i
=0;
849 width
= myWidthOfString(font
, t
, ++i
);
850 } while (width
< pwidth
&& i
< l
);
852 if(start
) // and since (nil)-4 = 0xfffffffd
860 if((line_width
>= pwidth
- x
)
861 || nitems
>= MAX_TB_PER_LINE
) {
862 y
+= layOutLine(tPtr
, items
, nitems
, x
, y
,
865 x
= 0; //tPtr->visible.x+2;
869 items
[nitems
].tb
= tb
;
870 items
[nitems
].begin
= begin
;
871 items
[nitems
].end
= end
;
882 y
+= layOutLine(tPtr
, items
, nitems
, x
, y
, pwidth
, align
);
884 tPtr
->docHeight
= y
+10;
885 updateScrollers(tPtr
);
887 tPtr
->flags
.laidOut
= True
;
893 textDidResize(W_ViewDelegate
*self
, WMView
*view
)
895 Text
*tPtr
= (Text
*)view
->self
;
896 unsigned short w
= WMWidgetWidth(tPtr
);
897 unsigned short h
= WMWidgetHeight(tPtr
);
898 unsigned short rh
= 0, vw
= 0;
900 if(tPtr
->ruler
&& tPtr
->flags
.rulerShown
) {
901 WMMoveWidget(tPtr
->ruler
, 20, 2);
902 WMResizeWidget(tPtr
->ruler
, w
- 22, 40);
907 WMMoveWidget(tPtr
->vS
, 1, rh
+ 2);
908 WMResizeWidget(tPtr
->vS
, 20, h
- rh
- 3);
910 WMSetRulerOffset(tPtr
->ruler
, 22);
911 } else WMSetRulerOffset(tPtr
->ruler
, 2);
915 WMMoveWidget(tPtr
->hS
, vw
, h
- 21);
916 WMResizeWidget(tPtr
->hS
, w
- vw
- 1, 20);
918 WMMoveWidget(tPtr
->hS
, vw
+1, h
- 21);
919 WMResizeWidget(tPtr
->hS
, w
- vw
- 2, 20);
923 tPtr
->visible
.x
= (tPtr
->vS
)?22:0;
924 tPtr
->visible
.y
= (tPtr
->ruler
&& tPtr
->flags
.rulerShown
)?43:3;
925 tPtr
->visible
.w
= tPtr
->view
->size
.width
- tPtr
->visible
.x
- 12;
926 tPtr
->visible
.h
= tPtr
->view
->size
.height
- tPtr
->visible
.y
;
927 tPtr
->visible
.h
-= (tPtr
->hS
)?20:0;
929 tPtr
->margins
[0].left
= tPtr
->margins
[0].right
= tPtr
->visible
.x
;
930 tPtr
->margins
[0].body
= tPtr
->visible
.x
;
931 tPtr
->margins
[0].right
= tPtr
->visible
.w
;
933 WMRefreshText(tPtr
, tPtr
->vpos
, tPtr
->hpos
);
936 //if(tPtr->view->flags.realized)
937 //XFreePixmap(tPtr->view->screen->display, tPtr->db);
940 //if(size did not change
941 if(tPtr
->visible
.w
< 10) tPtr
->visible
.w
= 10;
942 if(tPtr
->visible
.h
< 10) tPtr
->visible
.h
= 10;
944 tPtr
->db
= XCreatePixmap(tPtr
->view
->screen
->display
,
945 tPtr
->view
->window
, tPtr
->visible
.w
,
946 tPtr
->visible
.h
, tPtr
->view
->screen
->depth
);
951 W_ViewDelegate _TextViewDelegate
=
959 /* nice, divisble-by-16 memory */
960 static inline unsigned short
961 reqBlockSize(unsigned short requested
)
963 return requested
+16-(requested
%16);
967 deleteTextInteractively(Text
*tPtr
, KeySym ksym
)
969 printf("deleting %ld\n", ksym
);
973 insertTextInteractively(Text
*tPtr
, char *text
, int len
)
977 // Chunk *tb=NULL, *newtb=NULL;
978 int height
= -23; /* should only be changed upon newline */
983 if(!tPtr
->flags
.editable
|| len
< 1 || !text
984 || (*text
== '\n' && tPtr
->flags
.ignoreNewLine
))
987 tb
= tPtr
->currentTextBlock
;
989 WMAppendTextStream(tPtr
, text
);
990 WMRefreshText(tPtr
, 0, 0);
998 mark
= strchr(text
, '\n');
1000 len
= (int)(mark
-text
);
1004 printf("problem pasting text %d\n", len
);
1010 font
= (tPtr
->flags
.monoFont
|| !tb
)?tPtr
->dFont
:tb
->d
.font
;
1015 if(tb
) { /* there's a tb (or part of it) to detach from old */
1016 int current
= WMGetTextCurrentChunk(tPtr
);
1017 if(tPtr
->tpos
<=0) { /* at start of tb */
1018 if(current
<1) { /* the first tb... make old para blank */
1021 putParagraphOnPixmap(tPtr
, para
, True
);
1022 } else { /* not first tb... */
1023 printf("cut me out \n");
1025 } else if(tPtr
->tpos
< tb
->chars
&& tb
->type
== ctText
) {
1026 /* not at start of tb */
1027 char text
[tb
->chars
-tPtr
->tpos
+1];
1030 text
[i
] = tb
->text
[tPtr
->tpos
+i
];
1031 } while(++i
< tb
->chars
-tPtr
->tpos
);
1033 newtb
= (tPtr
->funcs
.createTChunk
) (text
, i
, tb
->font
,
1034 tb
->color
, tb
->script
, tb
->ul
);
1035 newtb
->next
= tb
->next
;
1037 /* might want to demalloc for LARGE cuts */
1038 //calcParaExtents(tPtr, para);
1039 para
->height
= putParagraphOnPixmap(tPtr
, para
, True
);
1040 //putParagraphOnPixmap(tPtr, para, True);
1041 } else if(tPtr
->tpos
>= tb
->chars
) {
1043 WMSetTextCurrentChunk(tPtr
, current
-1);
1044 prev
= tPtr
->currentChunk
;
1048 putParagraphOnPixmap(tPtr
, para
, True
);
1050 } else newtb
= NULL
;
1052 if(para
) /* the preceeding one */
1053 new_top
= para
->bottom
;
1055 WMAppendTextStream(tPtr
, "\n");
1056 para
= tPtr
->currentPara
;
1059 tPtr
->currentChunk
= newtb
;
1061 para
->top
= new_top
;
1062 calcParaExtents(tPtr
, para
);
1063 height
= para
->height
;
1066 WMAppendTextStream(tPtr
, text
);
1067 para
= tPtr
->currentPara
;
1068 } else if(!para
->tbs
|| !tb
) {
1069 //WMPrependTextStream(tPtr, text);
1070 WMAppendTextStream(tPtr
, text
);
1071 } else if(tb
->type
== ctImage
) {
1072 WMPrependTextStream(tPtr
, text
);
1074 printf("\n\nprepe\n\n");
1076 if(tPtr
->tpos
> tb
->chars
) {
1077 printf("\n\nmore\n\n");
1078 tPtr
->tpos
= tb
->chars
;
1082 printf("len is %d\n", len
);
1083 if(tb
->used
+len
>= tb
->allocated
) {
1084 tb
->allocated
= reqBlockSize(tb
->used
+len
);
1085 printf("ralloced %d\n", tb
->allocated
);
1086 tb
->text
= wrealloc(tb
->text
, tb
->allocated
);
1090 memmove(tb
->text
, text
, len
);
1095 memmove(&(tb
->text
[tPtr
->tpos
+len
]), &tb
->text
[tPtr
->tpos
],
1096 tb
->used
-tPtr
->tpos
+1);
1097 memmove(&tb
->text
[tPtr
->tpos
], text
, len
);
1101 w
= myWidthOfString(font
, text
, len
);
1105 WMAppendTextStream(tPtr
, mark
);
1106 WMRefreshText(tPtr
, tPtr
->vpos
, tPtr
->hpos
);
1107 printf("paste: use prev/post chunk's fmt...\n");
1109 layOutDocument(tPtr
);
1113 //doc->clickstart.cursor.x +=
1114 //myWidthOfString(tb->fmt->font, text,len);
1122 selectRegion(Text
*tPtr
, int x
, int y
)
1127 if(y
>10) y
-= 10; /* the original offset */
1129 x
-= tPtr
->visible
.x
-2;
1132 tPtr
->sel
.x
= WMAX(0, WMIN(tPtr
->clicked
.x
, x
));
1133 tPtr
->sel
.w
= abs(tPtr
->clicked
.x
- x
);
1134 tPtr
->sel
.y
= WMAX(0, WMIN(tPtr
->clicked
.y
, y
));
1135 tPtr
->sel
.h
= abs(tPtr
->clicked
.y
- y
);
1137 tPtr
->flags
.ownsSelection
= True
;
1143 pasteText(WMView
*view
, Atom selection
, Atom target
, Time timestamp
,
1144 void *cdata
, WMData
*data
)
1146 Text
*tPtr
= (Text
*)view
->self
;
1149 tPtr
->flags
.waitingForSelection
= False
;
1152 str
= (char*)WMDataBytes(data
);
1153 insertTextInteractively(tPtr
, str
, strlen(str
));
1156 str
= XFetchBuffer(tPtr
->view
->screen
->display
, &n
, 0);
1159 insertTextInteractively(tPtr
, str
, n
);
1166 releaseSelection(Text
*tPtr
)
1168 printf("I have %d selection\n", 1);
1169 tPtr
->flags
.ownsSelection
= False
;
1174 requestHandler(WMView
*view
, Atom selection
, Atom target
,
1175 void *cdata
, Atom
*type
)
1177 Text
*tPtr
= view
->self
;
1179 Display
*dpy
= tPtr
->view
->screen
->display
;
1180 Atom TEXT
= XInternAtom(dpy
, "TEXT", False
);
1181 Atom COMPOUND_TEXT
= XInternAtom(dpy
, "COMPOUND_TEXT", False
);
1184 if (target
== XA_STRING
|| target
== TEXT
|| target
== COMPOUND_TEXT
)
1185 return WMGetTextSelected(tPtr
);
1187 WMData
*data
= WMCreateDataWithBytes("bleh", 4);
1196 lostHandler(WMView
*view
, Atom selection
, void *cdata
)
1198 releaseSelection((WMText
*)view
->self
);
1201 static WMSelectionProcs selectionHandler
= {
1202 requestHandler
, lostHandler
, NULL
1206 _notification(void *observerData
, WMNotification
*notification
)
1208 WMText
*to
= (WMText
*)observerData
;
1209 WMText
*tw
= (WMText
*)WMGetNotificationClientData(notification
);
1211 lostHandler(to
->view
, XA_PRIMARY
, NULL
);
1215 handleTextKeyPress(Text
*tPtr
, XEvent
*event
)
1219 int control_pressed
= False
;
1222 if (((XKeyEvent
*) event
)->state
& ControlMask
)
1223 control_pressed
= True
;
1224 buffer
[XLookupString(&event
->xkey
, buffer
, 1, &ksym
, NULL
)] = '\0';
1231 printf("arrows %ld\n", ksym
);
1237 deleteTextInteractively(tPtr
, ksym
);
1244 if(buffer
[0] != '\0' && (buffer
[0] == '\n' || !control_pressed
))
1245 insertTextInteractively(tPtr
, buffer
, 1);
1246 else if(control_pressed
&& ksym
==XK_r
) {
1247 // Bool i = !tPtr->rulerShown; WMShowTextRuler(tPtr, i);
1248 // tPtr->rulerShown = i;
1249 printf("toggle ruler\n");
1251 else if(control_pressed
&& buffer
[0] == '\a')
1252 XBell(tPtr
->view
->screen
->display
, 0);
1255 if(tPtr
->flags
.ownsSelection
)
1256 releaseSelection(tPtr
);
1261 handleWidgetPress(XEvent
*event
, void *data
)
1263 TextBlock
*tb
= (TextBlock
*)data
;
1269 /* this little bit of nastiness here saves a boatload of trouble */
1270 w
= (WMWidget
*)(W_VIEW((W_VIEW(tb
->d
.widget
))->parent
))->self
;
1271 //if(W_CLASS(w) != WC_TextField && W_CLASS(w) != WC_Text)
1272 if( (((W_WidgetType
*)(w
))->widgetClass
) != WC_Text
)
1275 printf("%p clicked on tb %p wif: (%c)%c", tPtr
, tb
,
1276 tPtr
->firstTextBlock
->text
[0], tPtr
->firstTextBlock
->text
[1]);
1277 output(tb
->text
, tb
->used
);
1282 handleActionEvents(XEvent
*event
, void *data
)
1284 Text
*tPtr
= (Text
*)data
;
1285 Display
*dpy
= event
->xany
.display
;
1289 if(tPtr
->flags
.waitingForSelection
)
1292 switch (event
->type
) {
1294 ksym
= XLookupKeysym((XKeyEvent
*)event
, 0);
1295 if(ksym
== XK_Shift_R
|| ksym
== XK_Shift_L
) {
1296 tPtr
->flags
.extendSelection
= True
;
1299 if(!tPtr
->flags
.editable
|| tPtr
->flags
.buttonHeld
) {
1304 if (tPtr
->flags
.waitingForSelection
)
1306 if(tPtr
->flags
.focused
) {
1307 XGrabPointer(dpy
, W_VIEW(tPtr
)->window
, False
,
1308 PointerMotionMask
|ButtonPressMask
|ButtonReleaseMask
,
1309 GrabModeAsync
, GrabModeAsync
, None
,
1310 W_VIEW(tPtr
)->screen
->invisibleCursor
, CurrentTime
);
1311 tPtr
->flags
.pointerGrabbed
= True
;
1312 handleTextKeyPress(tPtr
, event
);
1317 ksym
= XLookupKeysym((XKeyEvent
*)event
, 0);
1318 if(ksym
== XK_Shift_R
|| ksym
== XK_Shift_L
) {
1319 tPtr
->flags
.extendSelection
= False
;
1321 //end modify flag so selection can be extended
1327 if(tPtr
->flags
.pointerGrabbed
) {
1328 tPtr
->flags
.pointerGrabbed
= False
;
1329 XUngrabPointer(dpy
, CurrentTime
);
1331 if((event
->xmotion
.state
& Button1Mask
)) {
1332 if(!tPtr
->flags
.ownsSelection
) {
1333 WMCreateSelectionHandler(tPtr
->view
, XA_PRIMARY
,
1334 event
->xbutton
.time
, &selectionHandler
, NULL
);
1335 tPtr
->flags
.ownsSelection
= True
;
1337 selectRegion(tPtr
, event
->xmotion
.x
, event
->xmotion
.y
);
1343 tPtr
->flags
.buttonHeld
= True
;
1344 if(tPtr
->flags
.extendSelection
) {
1345 selectRegion(tPtr
, event
->xmotion
.x
, event
->xmotion
.y
);
1348 if(event
->xbutton
.button
== Button1
) {
1349 if(tPtr
->flags
.ownsSelection
)
1350 releaseSelection(tPtr
);
1351 cursorToTextPosition(tPtr
, event
->xmotion
.x
, event
->xmotion
.y
);
1352 if (tPtr
->flags
.pointerGrabbed
) {
1353 tPtr
->flags
.pointerGrabbed
= False
;
1354 XUngrabPointer(dpy
, CurrentTime
);
1358 if(!tPtr
->flags
.focused
) {
1359 WMSetFocusToWidget(tPtr
);
1360 tPtr
->flags
.focused
= True
;
1364 if(event
->xbutton
.button
== WINGsConfiguration
.mouseWheelDown
)
1365 WMScrollText(tPtr
, -16);
1366 else if(event
->xbutton
.button
== WINGsConfiguration
.mouseWheelUp
)
1367 WMScrollText(tPtr
, 16);
1371 tPtr
->flags
.buttonHeld
= False
;
1372 if (tPtr
->flags
.pointerGrabbed
) {
1373 tPtr
->flags
.pointerGrabbed
= False
;
1374 XUngrabPointer(dpy
, CurrentTime
);
1377 if(event
->xbutton
.button
== WINGsConfiguration
.mouseWheelDown
1378 || event
->xbutton
.button
== WINGsConfiguration
.mouseWheelUp
)
1381 if(event
->xbutton
.button
== Button2
&& tPtr
->flags
.editable
) {
1384 if(!WMRequestSelection(tPtr
->view
, XA_PRIMARY
, XA_STRING
,
1385 event
->xbutton
.time
, pasteText
, NULL
)) {
1386 text
= XFetchBuffer(tPtr
->view
->screen
->display
, &n
, 0);
1389 insertTextInteractively(tPtr
, text
, n
-1);
1391 } else tPtr
->flags
.waitingForSelection
= True
;
1402 handleEvents(XEvent
*event
, void *data
)
1404 Text
*tPtr
= (Text
*)data
;
1406 switch(event
->type
) {
1408 if(!event
->xexpose
.count
&& tPtr
->view
->flags
.realized
)
1413 if (W_FocusedViewOfToplevel(W_TopLevelOfView(tPtr
->view
))!=tPtr
->view
)
1415 tPtr
->flags
.focused
= True
;
1419 tPtr
->flags
.focused
= False
;
1424 //for(...)WMRemoveTextParagraph(tPtr, para);
1433 clearText(Text
*tPtr
)
1436 if(!tPtr
->firstTextBlock
)
1439 while(tPtr
->currentTextBlock
)
1440 WMDestroyTextBlock(tPtr
, WMRemoveTextBlock(tPtr
));
1442 printf("yadda clearText\n");
1444 printf("remove the document\n");
1445 tPtr
->firstTextBlock
= NULL
;
1446 tPtr
->currentTextBlock
= NULL
;
1447 tPtr
->lastTextBlock
= NULL
;
1449 WMRefreshText(tPtr
, 0, 0);
1454 insertPlainText(WMText
*tPtr
, char *text
)
1468 mark
= strchr(start
, '\n');
1470 tb
= WMCreateTextBlockWithText(start
, tPtr
->dFont
,
1471 tPtr
->dColor
, True
, (int)(mark
-start
));
1474 if(start
&& strlen(start
)) {
1475 tb
= WMCreateTextBlockWithText(start
, tPtr
->dFont
,
1476 tPtr
->dColor
, False
, strlen(start
));
1481 if(tPtr
->flags
.prepend
)
1482 WMPrependTextBlock(tPtr
, tb
);
1484 WMAppendTextBlock(tPtr
, tb
);
1496 WMCreateText(WMWidget
*parent
)
1498 Text
*tPtr
= wmalloc(sizeof(Text
));
1500 printf("could not create text widget\n");
1505 printf("sizeof:\n");
1506 printf(" TextBlock %d\n", sizeof(TextBlock
));
1507 printf(" TextBlock *%d\n", sizeof(TextBlock
*));
1508 printf(" Section %d\n", sizeof(Section
));
1509 printf(" char * %d\n", sizeof(char *));
1510 printf(" void * %d\n", sizeof(void *));
1511 printf(" short %d\n", sizeof(short));
1512 printf(" Text %d\n", sizeof(Text
));
1515 memset(tPtr
, 0, sizeof(Text
));
1516 tPtr
->widgetClass
= WC_Text
;
1517 tPtr
->view
= W_CreateView(W_VIEW(parent
));
1519 perror("could not create text's view\n");
1523 tPtr
->view
->self
= tPtr
;
1524 tPtr
->view
->attribs
.cursor
= tPtr
->view
->screen
->textCursor
;
1525 tPtr
->view
->attribFlags
|= CWOverrideRedirect
| CWCursor
;
1526 W_ResizeView(tPtr
->view
, 250, 200);
1527 tPtr
->bgGC
= WMColorGC(tPtr
->view
->screen
->white
);
1528 tPtr
->fgGC
= WMColorGC(tPtr
->view
->screen
->black
);
1529 W_SetViewBackgroundColor(tPtr
->view
, tPtr
->view
->screen
->white
);
1536 //tPtr->dFont = WMCreateFont(tPtr->view->screen,
1537 // "-*-fixed-medium-r-normal--26-*-*-*-*-*-*-*");
1538 //"-sony-fixed-medium-r-normal--24-230-75-75-c-120-jisx0201.1976-0");
1539 // "-*-times-bold-r-*-*-12-*-*-*-*-*-*-*,"
1540 // "-*-fixed-medium-r-normal-*-12-*");
1542 tPtr
->dFont
= WMRetainFont(tPtr
->view
->screen
->normalFont
);
1544 tPtr
->dColor
= WMBlackColor(tPtr
->view
->screen
);
1546 tPtr
->view
->delegate
= &_TextViewDelegate
;
1548 WMCreateEventHandler(tPtr
->view
, ExposureMask
|StructureNotifyMask
1549 |EnterWindowMask
|LeaveWindowMask
|FocusChangeMask
,
1550 handleEvents
, tPtr
);
1552 WMCreateEventHandler(tPtr
->view
, ButtonReleaseMask
|ButtonPressMask
1553 |KeyReleaseMask
|KeyPressMask
|Button1MotionMask
,
1554 handleActionEvents
, tPtr
);
1556 WMAddNotificationObserver(_notification
, tPtr
, "_lostOwnership", tPtr
);
1559 tPtr
->firstTextBlock
= NULL
;
1560 tPtr
->lastTextBlock
= NULL
;
1561 tPtr
->currentTextBlock
= NULL
;
1564 tPtr
->gfxItems
= WMCreateArrayBag(4);
1566 tPtr
->parser
= NULL
;
1567 tPtr
->writer
= NULL
;
1569 tPtr
->sel
.x
= tPtr
->sel
.y
= 2;
1570 tPtr
->sel
.w
= tPtr
->sel
.h
= 0;
1572 tPtr
->clicked
.x
= tPtr
->clicked
.y
= 2;
1574 tPtr
->visible
.x
= tPtr
->visible
.y
= 2;
1575 tPtr
->visible
.h
= tPtr
->view
->size
.height
;
1576 tPtr
->visible
.w
= tPtr
->view
->size
.width
- 12;
1579 tPtr
->docHeight
= 0;
1580 tPtr
->dBulletPix
= WMCreatePixmapFromXPMData(tPtr
->view
->screen
,
1582 tPtr
->db
= (Pixmap
) NULL
;
1584 tPtr
->margins
= wmalloc(sizeof(WMRulerMargins
));
1585 tPtr
->margins
[0].left
= tPtr
->margins
[0].right
= tPtr
->visible
.x
;
1586 tPtr
->margins
[0].body
= tPtr
->visible
.x
;
1587 tPtr
->margins
[0].right
= tPtr
->visible
.w
;
1589 tPtr
->flags
.nmargins
= 1;
1590 tPtr
->flags
.rulerShown
= False
;
1591 tPtr
->flags
.monoFont
= !True
;
1592 tPtr
->flags
.focused
= False
;
1593 tPtr
->flags
.editable
= True
;
1594 tPtr
->flags
.ownsSelection
= False
;
1595 tPtr
->flags
.pointerGrabbed
= False
;
1596 tPtr
->flags
.buttonHeld
= False
;
1597 tPtr
->flags
.waitingForSelection
= False
;
1598 tPtr
->flags
.extendSelection
= False
;
1599 tPtr
->flags
.rulerShown
= False
;
1600 tPtr
->flags
.frozen
= False
;
1601 tPtr
->flags
.cursorShown
= True
;
1602 tPtr
->flags
.clickPos
= 1;
1603 tPtr
->flags
.ignoreNewLine
= False
;
1604 tPtr
->flags
.laidOut
= False
;
1605 tPtr
->flags
.prepend
= False
;
1606 tPtr
->flags
.relief
= WRFlat
;
1607 tPtr
->flags
.alignment
= WALeft
;
1614 WMPrependTextStream(WMText
*tPtr
, char *text
)
1618 //check for "{\rtf0" in the text...
1621 tPtr
->flags
.prepend
= True
;
1622 if(text
&& tPtr
->parser
)
1623 (tPtr
->parser
) (tPtr
, (void *) text
);
1625 insertPlainText(tPtr
, text
);
1630 WMAppendTextStream(WMText
*tPtr
, char *text
)
1634 //check for "{\rtf0" in the text...
1637 tPtr
->flags
.prepend
= False
;
1638 if(text
&& tPtr
->parser
)
1639 (tPtr
->parser
) (tPtr
, (void *) text
);
1641 insertPlainText(tPtr
, text
);
1646 WMGetTextSelected(WMText
*tPtr
)
1648 WMData
*data
= NULL
;
1654 //tb = tPtr->firstTextBlock;
1655 tb
= tPtr
->currentTextBlock
;
1659 data
= WMCreateDataWithBytes(tb
->text
, tb
->used
);
1661 WMSetDataFormat(data
, 8);
1666 WMCreateTextBlockWithObject(WMWidget
*w
, char *description
, WMColor
*color
,
1667 unsigned short first
, unsigned short reserved
)
1670 unsigned short length
;
1672 if(!w
|| !description
|| !color
)
1675 tb
= wmalloc(sizeof(TextBlock
));
1679 length
= strlen(description
);
1680 tb
->text
= (char *)wmalloc(length
);
1681 memset(tb
->text
, 0, length
);
1682 memcpy(tb
->text
, description
, length
);
1686 tb
->color
= WMRetainColor(color
);
1692 tb
->underlined
= False
;
1694 tb
->sections
= NULL
;
1703 WMCreateTextBlockWithText(char *text
, WMFont
*font
, WMColor
*color
,
1704 unsigned short first
, unsigned short length
)
1711 tb
= wmalloc(sizeof(TextBlock
));
1715 tb
->allocated
= reqBlockSize(length
);
1716 tb
->text
= (char *)wmalloc(tb
->allocated
);
1717 memset(tb
->text
, 0, tb
->allocated
);
1719 if(length
< 1|| !text
) { // || *text == '\n') {
1724 memcpy(tb
->text
, text
, length
);
1729 tb
->d
.font
= WMRetainFont(font
);
1730 tb
->color
= WMRetainColor(color
);
1734 tb
->graphic
= False
;
1735 tb
->underlined
= False
;
1737 tb
->sections
= NULL
;
1745 WMSetTextBlockProperties(void *vtb
, unsigned int first
,
1746 unsigned int kanji
, unsigned int underlined
, int script
,
1747 unsigned int marginN
)
1749 TextBlock
*tb
= (TextBlock
*) vtb
;
1755 tb
->underlined
= underlined
;
1756 tb
->script
= script
;
1757 tb
->marginN
= marginN
;
1761 WMGetTextBlockProperties(void *vtb
, unsigned int *first
,
1762 unsigned int *kanji
, unsigned int *underlined
, int *script
,
1763 unsigned int *marginN
)
1765 TextBlock
*tb
= (TextBlock
*) vtb
;
1769 if(first
) *first
= tb
->first
;
1770 if(kanji
) *kanji
= tb
->kanji
;
1771 if(underlined
) *underlined
= tb
->underlined
;
1772 if(script
) *script
= tb
->script
;
1773 if(marginN
) *marginN
= tb
->marginN
;
1779 WMPrependTextBlock(WMText
*tPtr
, void *vtb
)
1781 TextBlock
*tb
= (TextBlock
*)vtb
;
1788 WMWidget
*w
= tb
->d
.widget
;
1789 WMCreateEventHandler(W_VIEW(w
), ButtonPressMask
,
1790 handleWidgetPress
, tb
);
1791 //if(W_CLASS(w) != WC_TextField && W_CLASS(w) != WC_Text) {
1792 if(W_CLASS(w
) != WC_TextField
&&
1793 (((W_WidgetType
*)(w
))->widgetClass
) != WC_Text
) {
1794 (W_VIEW(w
))->attribs
.cursor
= tPtr
->view
->screen
->defaultCursor
;
1795 (W_VIEW(w
))->attribFlags
|= CWOverrideRedirect
| CWCursor
;
1797 WMPutInBag(tPtr
->gfxItems
, (void *)tb
);
1801 if(!tPtr
->lastTextBlock
|| !tPtr
->firstTextBlock
) {
1802 tb
->next
= tb
->prior
= NULL
;
1803 tPtr
->lastTextBlock
= tPtr
->firstTextBlock
1804 = tPtr
->currentTextBlock
= tb
;
1808 tb
->next
= tPtr
->currentTextBlock
;
1809 tb
->prior
= tPtr
->currentTextBlock
->prior
;
1810 if(tPtr
->currentTextBlock
->prior
)
1811 tPtr
->currentTextBlock
->prior
->next
= tb
;
1813 tPtr
->currentTextBlock
->prior
= tb
;
1815 tPtr
->firstTextBlock
= tb
;
1817 tPtr
->currentTextBlock
= tb
;
1822 WMAppendTextBlock(WMText
*tPtr
, void *vtb
)
1824 TextBlock
*tb
= (TextBlock
*)vtb
;
1830 WMWidget
*w
= tb
->d
.widget
;
1831 WMCreateEventHandler(W_VIEW(w
), ButtonPressMask
,
1832 handleWidgetPress
, tb
);
1833 //if(W_CLASS(w) != WC_TextField && W_CLASS(w) != WC_Text) {
1834 if(W_CLASS(w
) != WC_TextField
&&
1835 (((W_WidgetType
*)(w
))->widgetClass
) != WC_Text
) {
1836 (W_VIEW(w
))->attribs
.cursor
= tPtr
->view
->screen
->defaultCursor
;
1837 (W_VIEW(w
))->attribFlags
|= CWOverrideRedirect
| CWCursor
;
1839 WMPutInBag(tPtr
->gfxItems
, (void *)tb
);
1843 if(!tPtr
->lastTextBlock
|| !tPtr
->firstTextBlock
) {
1844 tb
->next
= tb
->prior
= NULL
;
1845 tPtr
->lastTextBlock
= tPtr
->firstTextBlock
1846 = tPtr
->currentTextBlock
= tb
;
1850 tb
->next
= tPtr
->currentTextBlock
->next
;
1851 tb
->prior
= tPtr
->currentTextBlock
;
1852 if(tPtr
->currentTextBlock
->next
)
1853 tPtr
->currentTextBlock
->next
->prior
= tb
;
1855 tPtr
->currentTextBlock
->next
= tb
;
1858 tPtr
->lastTextBlock
= tb
;
1860 tPtr
->currentTextBlock
= tb
;
1864 WMRemoveTextBlock(WMText
*tPtr
)
1866 TextBlock
*tb
= NULL
;
1868 if(!tPtr
|| !tPtr
->firstTextBlock
|| !tPtr
->lastTextBlock
1869 || !tPtr
->currentTextBlock
) {
1870 printf("cannot remove non existent TextBlock!\b");
1874 tb
= tPtr
->currentTextBlock
;
1876 WMDeleteEventHandler(W_VIEW(tb
->d
.widget
), ButtonPressMask
,
1877 handleWidgetPress
, tb
);
1878 WMRemoveFromBag(tPtr
->gfxItems
, (void *)tb
);
1879 WMUnmapWidget(tb
->d
.widget
);
1882 if(tPtr
->currentTextBlock
== tPtr
->firstTextBlock
) {
1883 if(tPtr
->currentTextBlock
->next
)
1884 tPtr
->currentTextBlock
->next
->prior
= NULL
;
1886 tPtr
->firstTextBlock
= tPtr
->currentTextBlock
->next
;
1887 tPtr
->currentTextBlock
= tPtr
->firstTextBlock
;
1889 } else if(tPtr
->currentTextBlock
== tPtr
->lastTextBlock
) {
1890 tPtr
->currentTextBlock
->prior
->next
= NULL
;
1891 tPtr
->lastTextBlock
= tPtr
->currentTextBlock
->prior
;
1892 tPtr
->currentTextBlock
= tPtr
->lastTextBlock
;
1894 tPtr
->currentTextBlock
->prior
->next
= tPtr
->currentTextBlock
->next
;
1895 tPtr
->currentTextBlock
->next
->prior
= tPtr
->currentTextBlock
->prior
;
1896 tPtr
->currentTextBlock
= tPtr
->currentTextBlock
->next
;
1903 WMDestroyTextBlock(WMText
*tPtr
, void *vtb
)
1905 TextBlock
*tb
= (TextBlock
*)vtb
;
1911 WMDestroyWidget(tb
->d
.widget
);
1912 wfree(tb
->d
.widget
);
1914 WMReleaseFont(tb
->d
.font
);
1917 WMReleaseColor(tb
->color
);
1918 if(tb
->sections
&& tb
->nsections
> 0)
1919 wfree(tb
->sections
);
1926 WMRefreshText(WMText
*tPtr
, int vpos
, int hpos
)
1930 if(!tPtr
|| vpos
<0 || hpos
<0)
1933 tPtr
->flags
.laidOut
= False
;
1934 layOutDocument(tPtr
);
1935 updateScrollers(tPtr
);
1942 WMSetTextForegroundColor(WMText
*tPtr
, WMColor
*color
)
1948 tPtr
->fgGC
= WMColorGC(color
);
1950 tPtr
->fgGC
= WMColorGC(WMBlackColor(tPtr
->view
->screen
));
1952 WMRefreshText(tPtr
, tPtr
->vpos
, tPtr
->hpos
);
1956 WMSetTextBackgroundColor(WMText
*tPtr
, WMColor
*color
)
1962 tPtr
->bgGC
= WMColorGC(color
);
1963 W_SetViewBackgroundColor(tPtr
->view
, color
);
1965 tPtr
->bgGC
= WMColorGC(WMWhiteColor(tPtr
->view
->screen
));
1966 W_SetViewBackgroundColor(tPtr
->view
,
1967 WMWhiteColor(tPtr
->view
->screen
));
1970 WMRefreshText(tPtr
, tPtr
->vpos
, tPtr
->hpos
);
1974 WMSetTextRelief(WMText
*tPtr
, WMReliefType relief
)
1978 tPtr
->flags
.relief
= relief
;
1983 WMSetTextHasHorizontalScroller(WMText
*tPtr
, Bool shouldhave
)
1988 if(shouldhave
&& !tPtr
->hS
) {
1989 tPtr
->hS
= WMCreateScroller(tPtr
);
1990 (W_VIEW(tPtr
->hS
))->attribs
.cursor
= tPtr
->view
->screen
->defaultCursor
;
1991 (W_VIEW(tPtr
->hS
))->attribFlags
|= CWOverrideRedirect
| CWCursor
;
1992 WMSetScrollerArrowsPosition(tPtr
->hS
, WSAMaxEnd
);
1993 WMSetScrollerAction(tPtr
->hS
, scrollersCallBack
, tPtr
);
1994 WMRealizeWidget(tPtr
->hS
);
1995 WMMapWidget(tPtr
->hS
);
1996 } else if(!shouldhave
&& tPtr
->hS
) {
1997 WMUnmapWidget(tPtr
->hS
);
1998 WMDestroyWidget(tPtr
->hS
);
2004 textDidResize(tPtr
->view
->delegate
, tPtr
->view
);
2009 WMSetTextHasVerticalScroller(WMText
*tPtr
, Bool shouldhave
)
2014 if(shouldhave
&& !tPtr
->vS
) {
2015 tPtr
->vS
= WMCreateScroller(tPtr
);
2016 (W_VIEW(tPtr
->vS
))->attribs
.cursor
= tPtr
->view
->screen
->defaultCursor
;
2017 (W_VIEW(tPtr
->vS
))->attribFlags
|= CWOverrideRedirect
| CWCursor
;
2018 WMSetScrollerArrowsPosition(tPtr
->vS
, WSAMaxEnd
);
2019 WMSetScrollerAction(tPtr
->vS
, scrollersCallBack
, tPtr
);
2020 WMRealizeWidget(tPtr
->vS
);
2021 WMMapWidget(tPtr
->vS
);
2022 } else if(!shouldhave
&& tPtr
->vS
) {
2023 WMUnmapWidget(tPtr
->vS
);
2024 WMDestroyWidget(tPtr
->vS
);
2030 textDidResize(tPtr
->view
->delegate
, tPtr
->view
);
2036 WMScrollText(WMText
*tPtr
, int amount
)
2041 if(amount
== 0 || !tPtr
->view
->flags
.realized
)
2045 if(tPtr
->vpos
> 0) {
2046 if(tPtr
->vpos
> amount
) tPtr
->vpos
+= amount
;
2050 int limit
= tPtr
->docHeight
- tPtr
->visible
.h
;
2051 if(tPtr
->vpos
< limit
) {
2052 if(tPtr
->vpos
< limit
-amount
) tPtr
->vpos
+= amount
;
2053 else tPtr
->vpos
= limit
;
2057 if(scroll
&& tPtr
->vpos
!= tPtr
->prevVpos
) {
2058 updateScrollers(tPtr
);
2061 tPtr
->prevVpos
= tPtr
->vpos
;
2066 WMPageText(WMText
*tPtr
, Bool direction
)
2068 if(!tPtr
) return False
;
2069 if(!tPtr
->view
->flags
.realized
) return False
;
2071 return WMScrollText(tPtr
, direction
?tPtr
->visible
.h
:-tPtr
->visible
.h
);
2076 WMSetTextUseMonoFont(WMText
*tPtr
, Bool mono
)
2080 if(mono
&& tPtr
->flags
.rulerShown
)
2081 ;//WMShowTextRuler(tPtr, False);
2083 tPtr
->flags
.monoFont
= mono
;
2084 WMRefreshText(tPtr
, tPtr
->vpos
, tPtr
->hpos
);
2088 WMGetTextUsesMonoFont(WMText
*tPtr
)
2092 return tPtr
->flags
.monoFont
;
2096 WMSetTextDefaultFont(WMText
*tPtr
, WMFont
*font
)
2104 tPtr
->dFont
= WMRetainFont(tPtr
->view
->screen
->normalFont
);
2108 WMGetTextDefaultFont(WMText
*tPtr
)
2117 WMSetTextParser(WMText
*tPtr
, WMAction
*parser
)
2121 tPtr
->parser
= parser
;
2126 WMSetTextWriter(WMText
*tPtr
, WMAction
*writer
)
2130 tPtr
->writer
= writer
;
2134 WMGetTextInsertType(WMText
*tPtr
)
2138 return tPtr
->flags
.prepend
;