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>
31 * - use currentTextBlock and neighbours for fast paint and layout
32 * - replace copious uses of Refreshtext with appropriate layOut()...
33 * - code replaceSelection
34 * (deleteSelection is same cept replaceSelection(tPtr, NULL); )
35 * - WMFindInTextStream should also highlight found text...
36 * - add full support for Horizontal Scroll
41 /* a Section is a section of a TextBlock that describes what parts
42 of a TextBlock has been laid out on which "line"...
43 o this greatly aids redraw, scroll and selection.
44 o this is created during layoutLine, but may be later modified.
45 o there may be many Sections per TextBlock, hence the array */
47 int x
, y
; /* where to draw it from */
48 int w
, h
; /* it's width and height */
50 unsigned short begin
, end
; /* what part of the text block */
54 /* a TextBlock is a doubly-linked list of TextBlocks containing:
55 o text for the block, color and font
56 o or a pointer to the pixmap
57 o OR a pointer to the widget and the (text) description for its graphic
60 typedef struct _TextBlock
{
61 struct _TextBlock
*next
; /* next text block in linked list */
62 struct _TextBlock
*prior
; /* prior text block in linked list */
64 char *text
; /* pointer to 8- or 16-bit text */
65 /* or to the object's description */
67 WMFont
*font
; /* the font */
68 WMWidget
*widget
; /* the embedded widget */
69 WMPixmap
*pixmap
; /* the pixmap */
70 } d
; /* description */
72 WMColor
*color
; /* the color */
73 Section
*sections
; /* the region for layouts (a growable array) */
74 /* an _array_! of size _nsections_ */
77 unsigned short used
; /* number of chars in this block */
78 unsigned short allocated
; /* size of allocation (in chars) */
80 unsigned int first
:1; /* first TextBlock in paragraph */
81 unsigned int blank
:1; /* ie. blank paragraph */
82 unsigned int kanji
:1; /* is of 16-bit characters or not */
83 unsigned int graphic
:1; /* graphic or text: text=0 */
84 unsigned int object
:1; /* embedded object or pixmap */
85 unsigned int underlined
:1; /* underlined or not */
86 unsigned int nsections
:8; /* over how many "lines" a TexBlock wraps */
87 int script
:8; /* script in points: negative for subscript */
88 unsigned int marginN
:9; /* which of the margins in WMText to use */
89 unsigned int RESERVED
:1;
93 /* somehow visible.h beats the hell outta visible.size.height :-) */
102 typedef struct W_Text
{
103 W_Class widgetClass
; /* the class number of this widget */
104 W_View
*view
; /* the view referring to this instance */
106 WMRuler
*ruler
; /* the ruler subwiget to manipulate paragraphs */
108 WMScroller
*vS
; /* the vertical scroller */
109 int vpos
; /* the current vertical position */
110 int prevVpos
; /* the previous vertical position */
112 WMScroller
*hS
; /* the horizontal scroller */
113 int hpos
; /* the current horizontal position */
114 int prevHpos
; /* the previous horizontal position */
115 /* in short: tPtr->hS?nowrap:wrap */
117 WMFont
*dFont
; /* the default font */
118 WMColor
*dColor
; /* the default color */
119 WMPixmap
*dBulletPix
; /* the default pixmap for bullets */
121 GC bgGC
; /* the background GC to draw with */
122 GC fgGC
; /* the foreground GC to draw with */
123 Pixmap db
; /* the buffer on which to draw */
125 WMRulerMargins
*margins
;/* a (growable) array of margins to be used */
126 /* by the various TextBlocks */
128 myRect visible
; /* the actual rectangle that can be drawn into */
129 myRect cursor
; /* the position and (height) of cursor */
130 myRect sel
; /* the selection rectangle */
131 int docWidth
; /* the width of the entire document */
132 int docHeight
; /* the height of the entire document */
135 TextBlock
*firstTextBlock
;
136 TextBlock
*lastTextBlock
;
137 TextBlock
*currentTextBlock
;
140 WMBag
*gfxItems
; /* a nice bag containing graphic items */
143 WMHandlerID timerID
; /* for nice twinky-winky */
145 WMPoint clicked
; /* where in the _document_ was clicked */
146 unsigned short tpos
; /* the character position in the currentTextBlock */
147 unsigned short RESERVED
;/* space taker upper... */
154 unsigned int monoFont
:1; /* whether to ignore formats */
155 unsigned int focused
:1; /* whether this instance has input focus */
156 unsigned int editable
:1; /* "silly user, you can't edit me" */
157 unsigned int ownsSelection
:1; /* "I ownz the current selection!" */
158 unsigned int pointerGrabbed
:1;/* "heh, gib me pointer" */
159 unsigned int buttonHeld
:1; /* the user is holding down the button */
160 unsigned int waitingForSelection
:1; /* dum dee dumm... */
161 unsigned int extendSelection
:1; /* shift-drag to select more regions */
163 unsigned int rulerShown
:1; /* whether the ruler is shown or not */
164 unsigned int frozen
:1; /* whether screen updates are to be made */
165 unsigned int cursorShown
:1; /* whether to show the cursor */
166 unsigned int clickPos
:1; /* clicked before=0 or after=1 a graphic: */
167 /* within counts as after too */
169 unsigned int ignoreNewLine
:1;/* turn it into a ' ' when typed */
170 unsigned int laidOut
:1; /* have the TextBlocks all been laid out */
171 unsigned int prepend
:1; /* prepend=1, append=0 (for parsers) */
172 WMAlignment alignment
:2; /* the alignment for text */
173 WMReliefType relief
:3; /* the relief to display with */
174 unsigned int RESERVED
:4;
175 unsigned int nmargins
:10; /* the number of margin arrays */
179 static char *default_bullet
[] = {
181 " c None s None", ". c black",
182 "X c white", "o c #808080",
192 paintText(Text
*tPtr
)
194 TextBlock
*tb
= tPtr
->firstTextBlock
;
198 int len
, y
, c
, s
, done
=False
;
200 WMScreen
*scr
= tPtr
->view
->screen
;
201 Display
*dpy
= tPtr
->view
->screen
->display
;
202 Window win
= tPtr
->view
->window
;
205 if (!tPtr
->view
->flags
.realized
|| !tPtr
->db
|| tPtr
->flags
.frozen
)
208 XFillRectangle(dpy
, tPtr
->db
, tPtr
->bgGC
,
209 0, 0, WMWidgetWidth(tPtr
), WMWidgetWidth(tPtr
));
210 //tPtr->visible.w, tPtr->visible.h);
212 tb
= tPtr
->firstTextBlock
;
217 if (tPtr
->flags
.ownsSelection
) {
218 greyGC
= WMColorGC(WMGrayColor(scr
));
219 //XFillRectangle(dpy, tPtr->db, greyGC,
220 // tPtr->sel.x, tPtr->sel.y-tPtr->vpos, tPtr->sel.w, tPtr->sel.h);
221 // XDrawRectangle(dpy, tPtr->db, tPtr->fgGC,
222 // tPtr->sel.x, tPtr->sel.y-tPtr->vpos, tPtr->sel.w, tPtr->sel.h);
226 while (!done
&& tb
) {
233 for(s
=0; s
<tb
->nsections
&& !done
; s
++) {
236 if (tb
->sections
[s
]._y
> tPtr
->vpos
+ tPtr
->visible
.h
) {
241 if ( tb
->sections
[s
].y
+ tb
->sections
[s
].h
< tPtr
->vpos
)
244 if (tPtr
->flags
.monoFont
) {
249 gc
= WMColorGC(tb
->color
);
252 if (tPtr
->flags
.ownsSelection
) {
254 if (prev_y
!= tb
->sections
[s
]._y
255 && (tb
->sections
[s
]._y
>= tPtr
->visible
.y
+ tPtr
->sel
.y
)
256 && (tb
->sections
[s
]._y
+ tb
->sections
[s
].h
257 <= tPtr
->visible
.y
+ tPtr
->sel
.y
+ tPtr
->sel
.h
)) {
258 XFillRectangle(dpy
, tPtr
->db
, greyGC
,
260 tPtr
->visible
.y
+ tb
->sections
[s
]._y
- tPtr
->vpos
,
261 tPtr
->visible
.w
, tb
->sections
[s
].h
);
263 } else if ( prev_y
!= tb
->sections
[s
]._y
264 && (tb
->sections
[s
]._y
<= tPtr
->visible
.y
+ tPtr
->sel
.y
)
265 && (tb
->sections
[s
]._y
+ tb
->sections
[s
].h
266 >= tPtr
->visible
.y
+ tPtr
->sel
.y
)
267 && (tPtr
->sel
.x
>= tb
->sections
[s
].x
)
268 && (tPtr
->visible
.y
+ tPtr
->sel
.y
+ tPtr
->sel
.h
269 >= tb
->sections
[s
]._y
+ tb
->sections
[s
].h
)) {
270 XFillRectangle(dpy
, tPtr
->db
, greyGC
,
272 tPtr
->visible
.y
+ tb
->sections
[s
]._y
- tPtr
->vpos
,
273 tPtr
->visible
.w
- tPtr
->sel
.x
, tb
->sections
[s
].h
);
275 } else if (prev_y
!= tb
->sections
[s
]._y
276 && (tb
->sections
[s
]._y
<= tPtr
->sel
.y
+ tPtr
->sel
.h
)
277 && (tb
->sections
[s
]._y
>= tPtr
->sel
.y
)) {
278 XFillRectangle(dpy
, tPtr
->db
, greyGC
,
280 tPtr
->visible
.y
+ tb
->sections
[s
]._y
- tPtr
->vpos
,
281 tPtr
->sel
.x
+ tPtr
->sel
.w
-tPtr
->visible
.x
,
284 } else if ( prev_y
!= tb
->sections
[s
]._y
285 && (tb
->sections
[s
]._y
<= tPtr
->sel
.y
)
286 && (tb
->sections
[s
]._y
+ tb
->sections
[s
].h
287 >= tPtr
->visible
.y
+ tPtr
->sel
.y
+ tPtr
->sel
.h
) ) {
288 XFillRectangle(dpy
, tPtr
->db
, greyGC
,
290 tPtr
->visible
.y
+ tb
->sections
[s
]._y
- tPtr
->vpos
,
291 tPtr
->sel
.w
,tb
->sections
[s
].h
);
296 prev_y
= tb
->sections
[s
]._y
;
298 len
= tb
->sections
[s
].end
- tb
->sections
[s
].begin
;
299 text
= &(tb
->text
[tb
->sections
[s
].begin
]);
300 y
= tb
->sections
[s
].y
- tPtr
->vpos
;
301 WMDrawString(scr
, tPtr
->db
, gc
, font
,
302 tb
->sections
[s
].x
, y
, text
, len
);
304 if (tb
->underlined
) {
305 XDrawLine(dpy
, tPtr
->db
, gc
,
306 tb
->sections
[s
].x
, y
+ font
->y
+ 1,
307 tb
->sections
[s
].x
+ tb
->sections
[s
].w
, y
+ font
->y
+ 1);
312 tb
= (!done
? tb
->next
: NULL
);
316 c
= WMGetBagItemCount(tPtr
->gfxItems
);
317 if (c
> 0 && !tPtr
->flags
.monoFont
) {
321 tb
= (TextBlock
*) WMGetFromBag(tPtr
->gfxItems
, j
);
322 if (tb
->sections
[0]._y
+ tb
->sections
[0].h
<= tPtr
->vpos
323 || tb
->sections
[0]._y
>= tPtr
->vpos
+ tPtr
->visible
.h
) {
326 if ((W_VIEW(tb
->d
.widget
))->flags
.mapped
) {
327 WMUnmapWidget(tb
->d
.widget
);
332 if (!(W_VIEW(tb
->d
.widget
))->flags
.mapped
) {
333 if (!(W_VIEW(tb
->d
.widget
))->flags
.realized
)
334 WMRealizeWidget(tb
->d
.widget
);
335 WMMapWidget(tb
->d
.widget
);
336 WMLowerWidget(tb
->d
.widget
);
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
);
350 WMMoveWidget(tb
->d
.widget
,
351 3 + tb
->sections
[0].x
+ tPtr
->visible
.x
,
352 tb
->sections
[0].y
+ tPtr
->visible
.y
- tPtr
->vpos
);
353 h
= WMWidgetHeight(tb
->d
.widget
) + 1;
355 WMDrawPixmap(tb
->d
.pixmap
, tPtr
->db
,
356 tb
->sections
[0].x
, tb
->sections
[0].y
- tPtr
->vpos
);
357 h
= tb
->d
.pixmap
->height
+ 1;
360 if (tb
->underlined
) {
361 XDrawLine(dpy
, tPtr
->db
, WMColorGC(tb
->color
),
363 tb
->sections
[0].y
+ h
,
364 tb
->sections
[0].x
+ tb
->sections
[0].w
,
365 tb
->sections
[0].y
+ h
);
371 if (tPtr
->flags
.editable
&& tPtr
->flags
.cursorShown
372 && tPtr
->cursor
.x
!= -23 && tPtr
->flags
.focused
) {
373 int y
= tPtr
->cursor
.y
- tPtr
->vpos
;
374 XDrawLine(dpy
, tPtr
->db
, tPtr
->fgGC
,
376 tPtr
->cursor
.x
, y
+ tPtr
->cursor
.h
);
378 //printf("%d %d %d\n", tPtr->cursor.x, tPtr->cursor.y, tPtr->cursor.h);
381 XCopyArea(dpy
, tPtr
->db
, win
, tPtr
->bgGC
,
383 tPtr
->visible
.w
, tPtr
->visible
.h
,
384 tPtr
->visible
.x
, tPtr
->visible
.y
);
386 W_DrawRelief(scr
, win
, 0, 0,
387 tPtr
->view
->size
.width
, tPtr
->view
->size
.height
,
390 if (tPtr
->ruler
&& tPtr
->flags
.rulerShown
)
393 tPtr
->view
->size
.width
-4, 42);
400 #define CURSOR_BLINK_ON_DELAY 600
401 #define CURSOR_BLINK_OFF_DELAY 400
404 blinkCursor(void *data
)
406 Text
*tPtr
= (Text
*)data
;
408 if (tPtr
->flags
.cursorShown
) {
409 tPtr
->timerID
= WMAddTimerHandler(CURSOR_BLINK_OFF_DELAY
,
412 tPtr
->timerID
= WMAddTimerHandler(CURSOR_BLINK_ON_DELAY
,
416 tPtr
->flags
.cursorShown
= !tPtr
->flags
.cursorShown
;
421 getFirstNonGraphicBlockFor(TextBlock
*tb
, short dir
)
428 tb
= (dir
? tb
->next
: tb
->prior
);
436 cursorToTextPosition(Text
*tPtr
, int x
, int y
)
438 TextBlock
*tb
= NULL
;
439 int done
=False
, s
, pos
, len
, _w
, _y
, dir
=1; /* 1 == "down" */
442 printf("%d %d\n",x
,y
);
443 y
+= (tPtr
->vpos
- tPtr
->visible
.y
);
447 x
-= (tPtr
->visible
.x
- 2);
451 /* clicked is relative to document, not window... */
455 if (! (tb
= tPtr
->currentTextBlock
)) {
456 if (! (tb
= tPtr
->firstTextBlock
)) {
458 tPtr
->cursor
.h
= tPtr
->dFont
->height
;
465 /* first, which direction? Most likely, newly clicked
466 position will be close to previous */
467 dir
= !(y
<= tb
->sections
[0].y
);
468 if ( ( y
<= tb
->sections
[0]._y
+ tb
->sections
[0].h
)
469 && (y
>= tb
->sections
[0]._y
) ) {
470 /* if it's on the same line */
471 if(x
< tb
->sections
[0].x
)
473 if(x
>= tb
->sections
[0].x
)
477 tb
= tPtr
->firstTextBlock
;
480 if (tPtr
->flags
.monoFont
&& tb
->graphic
) {
481 tb
= getFirstNonGraphicBlockFor(tb
, 1);
483 tPtr
->currentTextBlock
=
484 (dir
? tPtr
->lastTextBlock
: tPtr
->firstTextBlock
);
490 s
= (dir
? 0 : tb
->nsections
-1);
491 if ( y
>= tb
->sections
[s
]._y
492 && y
<= tb
->sections
[s
]._y
+ tb
->sections
[s
].h
) {
496 /* get the first section of the TextBlock that lies about
497 the vertical click point */
499 while (!done
&& tb
) {
501 if (tPtr
->flags
.monoFont
&& tb
->graphic
) {
507 s
= (dir
? 0 : tb
->nsections
-1);
508 while (!done
&& (dir
? (s
<tb
->nsections
) : (s
>=0) )) {
510 if ( y
>= tb
->sections
[s
]._y
511 && y
<= tb
->sections
[s
]._y
+ tb
->sections
[s
].h
) {
519 if ( (dir
? tb
->next
: tb
->prior
)) {
520 tb
= (dir
? tb
->next
: tb
->prior
);
523 break; //goto _doneH;
529 if (s
<0 || s
>=tb
->nsections
) {
530 s
= (dir
? tb
->nsections
-1 : 0);
534 /* we have the line, which TextBlock on that line is it? */
536 if (tPtr
->flags
.monoFont
&& tb
->graphic
)
537 tb
= getFirstNonGraphicBlockFor(tb
, dir
);
539 if ((dir
? tb
->sections
[s
].x
>= x
: tb
->sections
[s
].x
< x
))
547 text
= &(tb
->text
[tb
->sections
[s
].begin
]);
548 len
= tb
->sections
[s
].end
- tb
->sections
[s
].begin
;
549 _w
= WMWidthOfString(tb
->d
.font
, text
, len
);
551 printf("here %d %d \n", tb
->sections
[s
].x
+ _w
, x
);
552 if ((dir
? tb
->sections
[s
].x
+ _w
< x
: tb
->sections
[s
].x
+ _w
>= x
)) {
553 pos
= tb
->sections
[s
].end
;
554 tPtr
->cursor
.x
= tb
->sections
[s
].x
+ _w
;
558 _y
= tb
->sections
[s
]._y
;
563 if (tPtr
->flags
.monoFont
&& tb
->graphic
) {
564 tb
= (dir
? tb
->next
: tb
->prior
);
571 _w
= WMWidgetWidth(tb
->d
.widget
);
573 _w
= tb
->d
.pixmap
->width
;
575 text
= &(tb
->text
[tb
->sections
[s
].begin
]);
576 len
= tb
->sections
[s
].end
- tb
->sections
[s
].begin
;
577 _w
= WMWidthOfString(tb
->d
.font
, text
, len
);
578 if (tb
->sections
[s
].x
+ _w
>= x
)
583 if (tb
->sections
[s
].x
<= x
)
587 if ((dir
? tb
->next
: tb
->prior
)) {
588 TextBlock
*nxt
= (dir
? tb
->next
: tb
->prior
);
589 if (tPtr
->flags
.monoFont
&& nxt
->graphic
) {
590 nxt
= getFirstNonGraphicBlockFor(nxt
, dir
);
593 tPtr
->cursor
.x
= tb
->sections
[s
].x
;
598 if (_y
!= nxt
->sections
[0]._y
) {
599 /* this must be the last/first on this line. stop */
600 pos
= (dir
? tb
->sections
[s
].end
: 0);
601 tPtr
->cursor
.x
= tb
->sections
[s
].x
;
605 tPtr
->cursor
.x
+= WMWidgetWidth(tb
->d
.widget
);
607 tPtr
->cursor
.x
+= tb
->d
.pixmap
->width
;
608 } else if (pos
> tb
->sections
[s
].begin
) {
610 WMWidthOfString(tb
->d
.font
,
611 &(tb
->text
[tb
->sections
[s
].begin
]),
612 pos
- tb
->sections
[s
].begin
);
619 if ( (dir
? tb
->next
: tb
->prior
)) {
620 tb
= (dir
? tb
->next
: tb
->prior
);
627 s
= (dir
? 0 : tb
->nsections
-1);
630 /* we have said TextBlock, now where within it? */
631 if (tb
&& !tb
->graphic
) {
632 WMFont
*f
= tb
->d
.font
;
633 len
= tb
->sections
[s
].end
- tb
->sections
[s
].begin
;
634 text
= &(tb
->text
[tb
->sections
[s
].begin
]);
636 _w
= x
- tb
->sections
[s
].x
;
639 while (pos
<len
&& WMWidthOfString(f
, text
, pos
+1) < _w
)
642 tPtr
->cursor
.x
= tb
->sections
[s
].x
+
643 (pos
? WMWidthOfString(f
, text
, pos
) : 0);
645 pos
+= tb
->sections
[s
].begin
;
647 tPtr
->tpos
= (pos
<tb
->used
)? pos
: tb
->used
;
650 tPtr
->currentTextBlock
= tb
;
651 tPtr
->cursor
.h
= tb
->sections
[s
].h
;
652 tPtr
->cursor
.y
= tb
->sections
[s
]._y
;
655 printf("will hang :-)\n");
660 updateScrollers(Text
*tPtr
)
663 if (tPtr
->flags
.frozen
)
667 if (tPtr
->docHeight
< tPtr
->visible
.h
) {
668 WMSetScrollerParameters(tPtr
->vS
, 0, 1);
671 float vmax
= (float)(tPtr
->docHeight
);
672 WMSetScrollerParameters(tPtr
->vS
,
673 ((float)tPtr
->vpos
)/(vmax
- (float)tPtr
->visible
.h
),
674 (float)tPtr
->visible
.h
/vmax
);
676 } else tPtr
->vpos
= 0;
683 scrollersCallBack(WMWidget
*w
, void *self
)
685 Text
*tPtr
= (Text
*)self
;
690 if (!tPtr
->view
->flags
.realized
|| tPtr
->flags
.frozen
)
696 vmax
= (float)(tPtr
->docHeight
);
697 height
= tPtr
->visible
.h
;
699 which
= WMGetScrollerHitPart(tPtr
->vS
);
701 case WSDecrementLine
:
702 if (tPtr
->vpos
> 0) {
703 if (tPtr
->vpos
>16) tPtr
->vpos
-=16;
707 case WSIncrementLine
: {
708 int limit
= tPtr
->docHeight
- height
;
709 if (tPtr
->vpos
< limit
) {
710 if (tPtr
->vpos
<limit
-16) tPtr
->vpos
+=16;
711 else tPtr
->vpos
=limit
;
714 case WSDecrementPage
:
715 tPtr
->vpos
-= height
;
721 printf("dimple needs to jump to mouse location ;-/\n");
723 case WSIncrementPage
:
724 tPtr
->vpos
+= height
;
725 if (tPtr
->vpos
> (tPtr
->docHeight
- height
))
726 tPtr
->vpos
= tPtr
->docHeight
- height
;
729 printf("dimple needs to jump to mouse location ;-/\n");
734 tPtr
->vpos
= WMGetScrollerValue(tPtr
->vS
)
735 * (float)(tPtr
->docHeight
- height
);
741 printf("WSNoPart, WSKnobSlot\n");
743 float vmax
= (float)(tPtr
->docHeight
);
744 ((float)tPtr
->vpos
)/(vmax
- (float)tPtr
->visible
.h
),
745 (float)tPtr
->visible
.h
/vmax
;
746 dimple
=where mouse is
.
750 scroll
= (tPtr
->vpos
!= tPtr
->prevVpos
);
751 tPtr
->prevVpos
= tPtr
->vpos
;
760 if (tPtr->rulerShown)
761 XClearArea(tPtr->view->screen->display, tPtr->view->window, 22, 47,
762 tPtr->view->size.width-24, tPtr->view->size.height-49, True);
764 XClearArea(tPtr->view->screen->display, tPtr->view->window, 22, 2,
765 tPtr->view->size.width-24, tPtr->view->size.height-4, True);
768 if (which
== WSDecrementLine
|| which
== WSIncrementLine
)
769 updateScrollers(tPtr
);
778 unsigned short begin
, end
; /* what part of the text block */
784 layOutLine(Text
*tPtr
, myLineItems
*items
, int nitems
, int x
, int y
,
787 int i
, j
=0, lw
= 0, line_height
=0, max_d
=0, len
, n
;
792 TextBlock
*tbsame
=NULL
;
794 for(i
=0; i
<nitems
; i
++) {
798 if (!tPtr
->flags
.monoFont
) {
800 WMWidget
*wdt
= tb
->d
.widget
;
801 line_height
= WMAX(line_height
, WMWidgetHeight(wdt
));
802 if (tPtr
->flags
.alignment
!= WALeft
)
803 lw
+= WMWidgetWidth(wdt
);
805 line_height
= WMAX(line_height
, tb
->d
.pixmap
->height
);
806 if (tPtr
->flags
.alignment
!= WALeft
)
807 lw
+= tb
->d
.pixmap
->width
;
813 font
= (tPtr
->flags
.monoFont
)?tPtr
->dFont
: tb
->d
.font
;
814 max_d
= WMAX(max_d
, font
->height
-font
->y
);
815 line_height
= WMAX(line_height
, font
->height
);
816 text
= &(tb
->text
[items
[i
].begin
]);
817 len
= items
[i
].end
- items
[i
].begin
;
818 if (tPtr
->flags
.alignment
!= WALeft
)
819 lw
+= WMWidthOfString(font
, text
, len
);
823 if (tPtr
->flags
.alignment
== WARight
) {
825 } else if (tPtr
->flags
.alignment
== WACenter
) {
826 j
= (int) ((float)(pwidth
- lw
))/2.0;
831 for(i
=0; i
<nitems
; i
++) {
834 if (tbsame
== tb
) { /*extend it, since it's on same line */
835 tb
->sections
[tb
->nsections
-1].end
= items
[i
].end
;
838 tb
->sections
= wrealloc(tb
->sections
,
839 (++tb
->nsections
)*sizeof(Section
));
841 tb
->sections
[n
]._y
= y
;
842 tb
->sections
[n
].x
= x
+j
;
843 tb
->sections
[n
].h
= line_height
;
844 tb
->sections
[n
].begin
= items
[i
].begin
;
845 tb
->sections
[n
].end
= items
[i
].end
;
848 if (!tPtr
->flags
.monoFont
) {
850 WMWidget
*wdt
= tb
->d
.widget
;
851 tb
->sections
[n
].y
= 1 + max_d
+
852 y
+ line_height
- WMWidgetHeight(wdt
);
853 tb
->sections
[n
].w
= WMWidgetWidth(wdt
);
855 tb
->sections
[n
].y
= 1 + max_d
+
856 y
+ line_height
- tb
->d
.pixmap
->height
;
857 tb
->sections
[n
].w
= tb
->d
.pixmap
->width
;
859 x
+= tb
->sections
[n
].w
;
862 font
= (tPtr
->flags
.monoFont
)? tPtr
->dFont
: tb
->d
.font
;
863 len
= items
[i
].end
- items
[i
].begin
;
864 text
= &(tb
->text
[items
[i
].begin
]);
866 tb
->sections
[n
].y
= y
+line_height
-font
->y
;
868 WMWidthOfString(font
,
869 &(tb
->text
[tb
->sections
[n
].begin
]),
870 tb
->sections
[n
].end
- tb
->sections
[n
].begin
);
872 x
+= WMWidthOfString(font
, text
, len
);
878 return line_height
+(gfx
?10:0);
884 output(char *ptr
, int len
)
889 //printf(" s is [%s] (%d)\n", s, strlen(s));
894 /* tb->text doesn't necessarily end in '\0' hmph! (strchr) */
896 mystrchr(char *s
, char needle
, unsigned short len
)
900 if (!haystack
|| len
< 1)
903 while ( (int) (haystack
- s
) < len
) {
904 if (*haystack
== needle
)
911 #define MAX_TB_PER_LINE 64
914 layOutDocument(Text
*tPtr
)
917 myLineItems items
[MAX_TB_PER_LINE
];
919 Bool lhc
= !tPtr
->flags
.laidOut
; /* line height changed? */
922 int nitems
=0, x
=0, y
=0, lw
= 0, width
=0;
923 int pwidth
= tPtr
->visible
.w
- tPtr
->visible
.x
;
925 char *start
=NULL
, *mark
=NULL
;
928 if (tPtr
->flags
.frozen
)
931 if (!(tb
= tPtr
->firstTextBlock
))
934 if (0&&tPtr
->flags
.laidOut
) {
935 tb
= tPtr
->currentTextBlock
;
936 if (tb
->sections
&& tb
->nsections
>0)
937 prev_y
= tb
->sections
[tb
->nsections
-1]._y
;
939 printf("1 prev_y %d \n", prev_y
);
941 /* search backwards for textblocks on same line */
943 if (!tb
->sections
|| tb
->nsections
<1) {
944 tb
= tPtr
->firstTextBlock
;
947 if (tb
->sections
[tb
->nsections
-1]._y
!= prev_y
) {
951 // prev_y = tb->sections[tb->nsections-1]._y;
954 y
= 0;//tb->sections[tb->nsections-1]._y;
955 printf("2 prev_y %d \n\n", tb
->sections
[tb
->nsections
-1]._y
);
961 if (tb
->sections
&& tb
->nsections
>0) {
968 y
+= layOutLine(tPtr
, items
, nitems
, x
, y
, pwidth
);
969 x
= 0;//tPtr->visible.x+2;
975 if (!tPtr
->flags
.monoFont
) {
977 width
= WMWidgetWidth(tb
->d
.widget
);
979 width
= tb
->d
.pixmap
->width
;
981 if (width
> pwidth
)printf("rescale graphix to fit?\n");
984 || nitems
>= MAX_TB_PER_LINE
) {
985 y
+= layOutLine(tPtr
, items
, nitems
, x
, y
, pwidth
);
987 x
= 0;//tPtr->visible.x+2;
991 items
[nitems
].tb
= tb
;
992 items
[nitems
].begin
= 0;
993 items
[nitems
].end
= 0;
997 } else if ((start
= tb
->text
)) {
999 font
= tPtr
->flags
.monoFont
?tPtr
->dFont
:tb
->d
.font
;
1002 mark
= mystrchr(start
, ' ', tb
->used
);
1004 end
+= (int)(mark
-start
)+1;
1007 end
+= strlen(start
);
1014 if (end
-begin
> 0) {
1016 width
= WMWidthOfString(font
,
1017 &tb
->text
[begin
], end
-begin
);
1019 if (width
> pwidth
) { /* break this tb up */
1020 char *t
= &tb
->text
[begin
];
1021 int l
=end
-begin
, i
=0;
1023 width
= WMWidthOfString(font
, t
, ++i
);
1024 } while (width
< pwidth
&& i
< l
);
1026 if (start
) // and since (nil)-4 = 0xfffffffd
1033 if ((lw
>= pwidth
- x
)
1034 || nitems
>= MAX_TB_PER_LINE
) {
1035 y
+= layOutLine(tPtr
, items
, nitems
, x
, y
, pwidth
);
1037 x
= 0; //tPtr->visible.x+2;
1041 items
[nitems
].tb
= tb
;
1042 items
[nitems
].begin
= begin
;
1043 items
[nitems
].end
= end
;
1054 y
+= layOutLine(tPtr
, items
, nitems
, x
, y
, pwidth
);
1056 tPtr
->docHeight
= y
+10;
1057 updateScrollers(tPtr
);
1059 tPtr
->flags
.laidOut
= True
;
1065 textDidResize(W_ViewDelegate
*self
, WMView
*view
)
1067 Text
*tPtr
= (Text
*)view
->self
;
1068 unsigned short w
= WMWidgetWidth(tPtr
);
1069 unsigned short h
= WMWidgetHeight(tPtr
);
1070 unsigned short rh
= 0, vw
= 0;
1072 if (tPtr
->ruler
&& tPtr
->flags
.rulerShown
) {
1073 WMMoveWidget(tPtr
->ruler
, 2, 2);
1074 WMResizeWidget(tPtr
->ruler
, w
- 4, 40);
1079 WMMoveWidget(tPtr
->vS
, 1, rh
+ 2);
1080 WMResizeWidget(tPtr
->vS
, 20, h
- rh
- 3);
1082 WMSetRulerOffset(tPtr
->ruler
,22);
1083 } else WMSetRulerOffset(tPtr
->ruler
, 2);
1087 WMMoveWidget(tPtr
->hS
, vw
, h
- 21);
1088 WMResizeWidget(tPtr
->hS
, w
- vw
- 1, 20);
1090 WMMoveWidget(tPtr
->hS
, vw
+1, h
- 21);
1091 WMResizeWidget(tPtr
->hS
, w
- vw
- 2, 20);
1095 tPtr
->visible
.x
= (tPtr
->vS
)?22:2;
1096 tPtr
->visible
.y
= (tPtr
->ruler
&& tPtr
->flags
.rulerShown
)?43:3;
1097 tPtr
->visible
.w
= tPtr
->view
->size
.width
- tPtr
->visible
.x
- 12;
1098 tPtr
->visible
.h
= tPtr
->view
->size
.height
- tPtr
->visible
.y
;
1099 tPtr
->visible
.h
-= (tPtr
->hS
)?20:0;
1101 tPtr
->margins
[0].left
= tPtr
->margins
[0].right
= tPtr
->visible
.x
;
1102 tPtr
->margins
[0].body
= tPtr
->visible
.x
;
1103 tPtr
->margins
[0].right
= tPtr
->visible
.w
;
1106 if (tPtr
->view
->flags
.realized
) {
1109 XFreePixmap(tPtr
->view
->screen
->display
, tPtr
->db
);
1110 tPtr
->db
= (Pixmap
) NULL
;
1113 if (tPtr
->visible
.w
< 40)
1114 tPtr
->visible
.w
= 40;
1115 if (tPtr
->visible
.h
< 20)
1116 tPtr
->visible
.h
= 20;
1118 //if (size change or !db
1120 tPtr
->db
= XCreatePixmap(tPtr
->view
->screen
->display
,
1121 tPtr
->view
->window
, tPtr
->visible
.w
,
1122 tPtr
->visible
.h
, tPtr
->view
->screen
->depth
);
1126 WMRefreshText(tPtr
, tPtr
->vpos
, tPtr
->hpos
);
1129 W_ViewDelegate _TextViewDelegate
=
1137 /* nice, divisble-by-16 blocks */
1138 static inline unsigned short
1139 reqBlockSize(unsigned short requested
)
1141 return requested
+ 16 - (requested
%16);
1146 clearText(Text
*tPtr
)
1148 if (!tPtr
->firstTextBlock
)
1151 while (tPtr
->currentTextBlock
)
1152 WMDestroyTextBlock(tPtr
, WMRemoveTextBlock(tPtr
));
1154 tPtr
->firstTextBlock
= NULL
;
1155 tPtr
->currentTextBlock
= NULL
;
1156 tPtr
->lastTextBlock
= NULL
;
1160 deleteTextInteractively(Text
*tPtr
, KeySym ksym
)
1162 TextBlock
*tb
= tPtr
->currentTextBlock
;
1163 Bool back
= (Bool
) (ksym
== XK_BackSpace
);
1166 if (!tPtr
->flags
.editable
|| tPtr
->flags
.buttonHeld
) {
1167 XBell(tPtr
->view
->screen
->display
, 0);
1174 if (back
&& tPtr
->tpos
< 1) {
1177 tPtr
->tpos
= tb
->used
;
1178 tPtr
->currentTextBlock
= tb
;
1183 if ( (tb
->used
> 0) && ((back
?tPtr
->tpos
> 0:1))
1184 && (tPtr
->tpos
<= tb
->used
) && !tb
->graphic
) {
1187 memmove(&(tb
->text
[tPtr
->tpos
]),
1188 &(tb
->text
[tPtr
->tpos
+ 1]), tb
->used
- tPtr
->tpos
);
1193 if ( (back
? (tPtr
->tpos
< 1 && !done
) : ( tPtr
->tpos
>= tb
->used
))
1196 TextBlock
*sibling
= (back
? tb
->prior
: tb
->next
);
1198 printf("tb->graphic %d\n", tb
->graphic
);
1199 if(tb
->used
== 0 || tb
->graphic
)
1200 WMDestroyTextBlock(tPtr
, WMRemoveTextBlock(tPtr
));
1203 tPtr
->currentTextBlock
= sibling
;
1204 tPtr
->tpos
= (back
? sibling
->used
: 0);
1211 if (tPtr
->tpos
< 1 && !done
) {
1212 TextBlock
*prior
= tb
->prior
;
1214 WMDestroyTextBlock(tPtr
, WMRemoveTextBlock(tPtr
));
1216 tPtr
->currentTextBlock
= prior
;
1217 tPtr
->tpos
= prior
->used
;
1221 if(tPtr
->tpos
>= tb
->used
) {
1222 TextBlock
*next
= tb
->next
;
1224 WMDestroyTextBlock(tPtr
, WMRemoveTextBlock(tPtr
));
1227 tPtr
->currentTextBlock
= next
;
1237 insertTextInteractively(Text
*tPtr
, char *text
, int len
)
1240 char *newline
= NULL
;
1242 if (!tPtr
->flags
.editable
|| tPtr
->flags
.buttonHeld
) {
1243 XBell(tPtr
->view
->screen
->display
, 0);
1247 if (!tPtr
->flags
.editable
|| len
< 1 || !text
)
1250 if(tPtr
->flags
.ignoreNewLine
&& *text
== '\n' && len
== 1)
1253 if (tPtr
->flags
.ignoreNewLine
) {
1255 for(i
=0; i
<len
; i
++) {
1256 if (text
[i
] == '\n')
1261 tb
= tPtr
->currentTextBlock
;
1262 if (!tb
|| tb
->graphic
) {
1264 WMAppendTextStream(tPtr
, text
);
1265 if (tPtr
->currentTextBlock
) {
1266 tPtr
->tpos
= tPtr
->currentTextBlock
->used
;
1271 if ((newline
= strchr(text
, '\n'))) {
1272 int nlen
= (int)(newline
-text
);
1273 int s
= tb
->used
- tPtr
->tpos
;
1276 printf("got newline %d\n", s
);
1277 if (!tb
->blank
&& nlen
>0) {
1279 memcpy(save
, &tb
->text
[tPtr
->tpos
], s
);
1280 tb
->used
-= (tb
->used
- tPtr
->tpos
);
1283 insertTextInteractively(tPtr
, text
, nlen
);
1285 WMAppendTextStream(tPtr
, newline
);
1287 insertTextInteractively(tPtr
, save
, s
);
1290 WMAppendTextStream(tPtr
, text
);
1292 printf("split me\n");
1299 if (tb
->used
+ len
>= tb
->allocated
) {
1300 tb
->allocated
= reqBlockSize(tb
->used
+len
);
1301 tb
->text
= wrealloc(tb
->text
, tb
->allocated
);
1305 memcpy(tb
->text
, text
, len
);
1310 memmove(&(tb
->text
[tPtr
->tpos
+len
]), &tb
->text
[tPtr
->tpos
],
1311 tb
->used
-tPtr
->tpos
+1);
1312 memmove(&tb
->text
[tPtr
->tpos
], text
, len
);
1322 selectRegion(Text
*tPtr
, int x
, int y
)
1326 y
+= (tPtr
->flags
.rulerShown
? 40: 0);
1328 if (y
>10) y
-= 10; /* the original offset */
1330 x
-= tPtr
->visible
.x
-2;
1333 tPtr
->sel
.x
= WMAX(0, WMIN(tPtr
->clicked
.x
, x
));
1334 tPtr
->sel
.w
= abs(tPtr
->clicked
.x
- x
);
1335 tPtr
->sel
.y
= WMAX(0, WMIN(tPtr
->clicked
.y
, y
));
1336 tPtr
->sel
.h
= abs(tPtr
->clicked
.y
- y
);
1338 tPtr
->flags
.ownsSelection
= True
;
1344 pasteText(WMView
*view
, Atom selection
, Atom target
, Time timestamp
,
1345 void *cdata
, WMData
*data
)
1347 Text
*tPtr
= (Text
*)view
->self
;
1350 tPtr
->flags
.waitingForSelection
= False
;
1353 str
= (char*)WMDataBytes(data
);
1354 if (0&&tPtr
->parser
) {
1355 /* parser is not yet well behaved to do this properly..*/
1356 (tPtr
->parser
) (tPtr
, (void *) str
);
1358 insertTextInteractively(tPtr
, str
, strlen(str
));
1360 WMRefreshText(tPtr
, tPtr
->vpos
, tPtr
->hpos
);
1363 str
= XFetchBuffer(tPtr
->view
->screen
->display
, &n
, 0);
1366 if (0&&tPtr
->parser
) {
1367 /* parser is not yet well behaved to do this properly..*/
1368 (tPtr
->parser
) (tPtr
, (void *) str
);
1370 insertTextInteractively(tPtr
, str
, n
);
1372 WMRefreshText(tPtr
, tPtr
->vpos
, tPtr
->hpos
);
1379 releaseSelection(Text
*tPtr
)
1381 tPtr
->flags
.ownsSelection
= False
;
1386 requestHandler(WMView
*view
, Atom selection
, Atom target
,
1387 void *cdata
, Atom
*type
)
1389 Text
*tPtr
= view
->self
;
1390 Display
*dpy
= tPtr
->view
->screen
->display
;
1391 Atom TEXT
= XInternAtom(dpy
, "TEXT", False
);
1392 Atom COMPOUND_TEXT
= XInternAtom(dpy
, "COMPOUND_TEXT", False
);
1395 if (target
== XA_STRING
|| target
== TEXT
|| target
== COMPOUND_TEXT
) {
1396 char *text
= WMGetTextSelected(tPtr
);
1397 WMData
*data
= WMCreateDataWithBytes(text
, strlen(text
));
1401 Atom PIXMAP
= XInternAtom(dpy
, "PIXMAP", False
);
1402 WMData
*data
= WMCreateDataWithBytes("bleh", 4);
1403 if(target
== PIXMAP
) {
1404 printf("whoa! pixmap WMGetTextSelectedObjects\n");
1414 lostHandler(WMView
*view
, Atom selection
, void *cdata
)
1416 releaseSelection((WMText
*)view
->self
);
1419 static WMSelectionProcs selectionHandler
= {
1420 requestHandler
, lostHandler
, NULL
1424 ownershipObserver(void *observerData
, WMNotification
*notification
)
1426 WMText
*to
= (WMText
*)observerData
;
1427 WMText
*tw
= (WMText
*)WMGetNotificationClientData(notification
);
1429 lostHandler(to
->view
, XA_PRIMARY
, NULL
);
1434 handleTextKeyPress(Text
*tPtr
, XEvent
*event
)
1438 int control_pressed
= False
;
1441 if (((XKeyEvent
*) event
)->state
& ControlMask
)
1442 control_pressed
= True
;
1443 buffer
[XLookupString(&event
->xkey
, buffer
, 1, &ksym
, NULL
)] = 0;
1450 TextBlock
*tb
= tPtr
->currentTextBlock
;
1451 int x
= tPtr
->cursor
.x
+ tPtr
->visible
.x
;
1458 w
= WMWidgetWidth(tb
->d
.widget
);
1460 w
= tb
->d
.pixmap
->width
;
1464 w
= WMWidthOfString(tb
->d
.font
, &tb
->text
[pos
], 1);
1467 cursorToTextPosition(tPtr
, w
+ tPtr
->cursor
.x
+ tPtr
->visible
.x
,
1468 tPtr
->visible
.y
+ tPtr
->cursor
.y
+ tPtr
->cursor
.h
);
1469 if(x
== tPtr
->cursor
.x
+ tPtr
->visible
.x
) {
1470 printf("same %d %d\n", x
, tPtr
->cursor
.x
+ tPtr
->visible
.x
);
1471 cursorToTextPosition(tPtr
, tPtr
->visible
.x
,
1472 3 + tPtr
->visible
.y
+ tPtr
->cursor
.y
+ tPtr
->cursor
.h
);
1481 deleteTextInteractively(tPtr
, ksym
);
1482 WMRefreshText(tPtr
, tPtr
->vpos
, tPtr
->hpos
);
1487 control_pressed
= True
;
1493 if (buffer
[0] != 0 && !control_pressed
) {
1494 insertTextInteractively(tPtr
, buffer
, 1);
1495 WMRefreshText(tPtr
, tPtr
->vpos
, tPtr
->hpos
);
1497 } else if (control_pressed
&& ksym
==XK_r
) {
1498 Bool i
= !tPtr
->flags
.rulerShown
;
1499 WMShowTextRuler(tPtr
, i
);
1500 tPtr
->flags
.rulerShown
= i
;
1502 else if (control_pressed
&& buffer
[0] == '\a')
1503 XBell(tPtr
->view
->screen
->display
, 0);
1506 if (!control_pressed
&& tPtr
->flags
.ownsSelection
)
1507 releaseSelection(tPtr
);
1511 handleWidgetPress(XEvent
*event
, void *data
)
1513 TextBlock
*tb
= (TextBlock
*)data
;
1519 /* this little bit of nastiness here saves a boatload of trouble */
1520 w
= (WMWidget
*)(((W_VIEW(tb
->d
.widget
))->parent
)->self
);
1521 if (W_CLASS(w
) != WC_Text
)
1524 tPtr
->currentTextBlock
= getFirstNonGraphicBlockFor(tb
, 1);
1525 if (!tPtr
->currentTextBlock
)
1526 tPtr
->currentTextBlock
= tb
;
1528 output(tPtr
->currentTextBlock
->text
, tPtr
->currentTextBlock
->used
);
1529 //if (!tPtr->flags.focused) {
1530 // WMSetFocusToWidget(tPtr);
1531 // tPtr->flags.focused = True;
1537 handleActionEvents(XEvent
*event
, void *data
)
1539 Text
*tPtr
= (Text
*)data
;
1540 Display
*dpy
= event
->xany
.display
;
1544 switch (event
->type
) {
1546 ksym
= XLookupKeysym((XKeyEvent
*)event
, 0);
1547 if (ksym
== XK_Shift_R
|| ksym
== XK_Shift_L
) {
1548 tPtr
->flags
.extendSelection
= True
;
1552 if (tPtr
->flags
.waitingForSelection
)
1554 if (tPtr
->flags
.focused
) {
1555 XGrabPointer(dpy
, W_VIEW(tPtr
)->window
, False
,
1556 PointerMotionMask
|ButtonPressMask
|ButtonReleaseMask
,
1557 GrabModeAsync
, GrabModeAsync
, None
,
1558 tPtr
->view
->screen
->invisibleCursor
, CurrentTime
);
1559 tPtr
->flags
.pointerGrabbed
= True
;
1560 handleTextKeyPress(tPtr
, event
);
1565 ksym
= XLookupKeysym((XKeyEvent
*)event
, 0);
1566 if (ksym
== XK_Shift_R
|| ksym
== XK_Shift_L
) {
1567 tPtr
->flags
.extendSelection
= False
;
1569 //end modify flag so selection can be extended
1575 if (tPtr
->flags
.pointerGrabbed
) {
1576 tPtr
->flags
.pointerGrabbed
= False
;
1577 XUngrabPointer(dpy
, CurrentTime
);
1579 if ((event
->xmotion
.state
& Button1Mask
)) {
1580 if (!tPtr
->flags
.ownsSelection
) {
1581 WMCreateSelectionHandler(tPtr
->view
, XA_PRIMARY
,
1582 event
->xbutton
.time
, &selectionHandler
, NULL
);
1583 tPtr
->flags
.ownsSelection
= True
;
1585 selectRegion(tPtr
, event
->xmotion
.x
, event
->xmotion
.y
);
1591 tPtr
->flags
.buttonHeld
= True
;
1592 if (tPtr
->flags
.extendSelection
) {
1593 selectRegion(tPtr
, event
->xmotion
.x
, event
->xmotion
.y
);
1596 if (event
->xbutton
.button
== Button1
) {
1598 if (!tPtr
->flags
.focused
) {
1599 WMSetFocusToWidget(tPtr
);
1600 tPtr
->flags
.focused
= True
;
1603 if (tPtr
->flags
.ownsSelection
)
1604 releaseSelection(tPtr
);
1605 cursorToTextPosition(tPtr
, event
->xmotion
.x
, event
->xmotion
.y
);
1607 if (tPtr
->flags
.pointerGrabbed
) {
1608 tPtr
->flags
.pointerGrabbed
= False
;
1609 XUngrabPointer(dpy
, CurrentTime
);
1614 if (event
->xbutton
.button
== WINGsConfiguration
.mouseWheelDown
)
1615 WMScrollText(tPtr
, -16);
1616 else if (event
->xbutton
.button
== WINGsConfiguration
.mouseWheelUp
)
1617 WMScrollText(tPtr
, 16);
1621 tPtr
->flags
.buttonHeld
= False
;
1622 if (tPtr
->flags
.pointerGrabbed
) {
1623 tPtr
->flags
.pointerGrabbed
= False
;
1624 XUngrabPointer(dpy
, CurrentTime
);
1627 if (event
->xbutton
.button
== WINGsConfiguration
.mouseWheelDown
1628 || event
->xbutton
.button
== WINGsConfiguration
.mouseWheelUp
)
1631 if (event
->xbutton
.button
== Button2
) {
1635 if (!tPtr
->flags
.editable
) {
1640 if (!WMRequestSelection(tPtr
->view
, XA_PRIMARY
, XA_STRING
,
1641 event
->xbutton
.time
, pasteText
, NULL
)) {
1642 text
= XFetchBuffer(tPtr
->view
->screen
->display
, &n
, 0);
1645 if (0&&tPtr
->parser
) {
1646 /* parser is not yet well behaved to do this properly..*/
1647 (tPtr
->parser
) (tPtr
, (void *) text
);
1649 insertTextInteractively(tPtr
, text
, n
-1);
1651 WMRefreshText(tPtr
, tPtr
->vpos
, tPtr
->hpos
);
1653 } else tPtr
->flags
.waitingForSelection
= True
;
1664 handleEvents(XEvent
*event
, void *data
)
1666 Text
*tPtr
= (Text
*)data
;
1668 switch(event
->type
) {
1672 if (!(W_VIEW(tPtr
->hS
))->flags
.realized
)
1673 WMRealizeWidget(tPtr
->hS
);
1674 if (!((W_VIEW(tPtr
->hS
))->flags
.mapped
))
1675 WMMapWidget(tPtr
->hS
);
1679 if (!(W_VIEW(tPtr
->vS
))->flags
.realized
)
1680 WMRealizeWidget(tPtr
->vS
);
1681 if (!((W_VIEW(tPtr
->vS
))->flags
.mapped
))
1682 WMMapWidget(tPtr
->vS
);
1686 if (!(W_VIEW(tPtr
->ruler
))->flags
.realized
)
1687 WMRealizeWidget(tPtr
->ruler
);
1689 if (!((W_VIEW(tPtr
->ruler
))->flags
.mapped
)
1690 && tPtr
->flags
.rulerShown
)
1691 WMMapWidget(tPtr
->ruler
);
1694 textDidResize(tPtr
->view
->delegate
, tPtr
->view
);
1696 if (!event
->xexpose
.count
&& tPtr
->view
->flags
.realized
)
1701 if (W_FocusedViewOfToplevel(W_TopLevelOfView(tPtr
->view
))
1704 tPtr
->flags
.focused
= True
;
1706 if (tPtr
->flags
.editable
&& !tPtr
->timerID
) {
1707 tPtr
->timerID
= WMAddTimerHandler(12+0*CURSOR_BLINK_ON_DELAY
,
1715 tPtr
->flags
.focused
= False
;
1718 if (tPtr
->timerID
) {
1719 WMDeleteTimerHandler(tPtr
->timerID
);
1720 tPtr
->timerID
= NULL
;
1728 WMDestroyWidget(tPtr
->hS
);
1730 WMDestroyWidget(tPtr
->vS
);
1732 WMDestroyWidget(tPtr
->ruler
);
1734 XFreePixmap(tPtr
->view
->screen
->display
, tPtr
->db
);
1736 WMFreeBag(tPtr
->gfxItems
);
1739 WMDeleteTimerHandler(tPtr
->timerID
);
1741 WMReleaseFont(tPtr
->dFont
);
1742 WMReleaseColor(tPtr
->dColor
);
1743 WMDeleteSelectionHandler(tPtr
->view
, XA_PRIMARY
, CurrentTime
);
1744 WMRemoveNotificationObserver(tPtr
);
1755 insertPlainText(WMText
*tPtr
, char *text
)
1767 mark
= strchr(start
, '\n');
1769 tb
= WMCreateTextBlockWithText(start
, tPtr
->dFont
,
1770 tPtr
->dColor
, True
, (int)(mark
-start
));
1773 if (start
&& strlen(start
)) {
1774 tb
= WMCreateTextBlockWithText(start
, tPtr
->dFont
,
1775 tPtr
->dColor
, False
, strlen(start
));
1780 if (tPtr
->flags
.prepend
)
1781 WMPrependTextBlock(tPtr
, tb
);
1783 WMAppendTextBlock(tPtr
, tb
);
1791 rulerMoveCallBack(WMWidget
*w
, void *self
)
1793 Text
*tPtr
= (Text
*)self
;
1796 if (W_CLASS(tPtr
) != WC_Text
)
1804 rulerReleaseCallBack(WMWidget
*w
, void *self
)
1806 Text
*tPtr
= (Text
*)self
;
1809 if (W_CLASS(tPtr
) != WC_Text
)
1812 WMRefreshText(tPtr
, tPtr
->vpos
, tPtr
->hpos
);
1819 draggingEntered(WMView
*self
, WMDraggingInfo
*info
)
1821 printf("draggingEntered\n");
1822 return WDOperationCopy
;
1827 draggingUpdated(WMView
*self
, WMDraggingInfo
*info
)
1829 printf("draggingUpdated\n");
1830 return WDOperationCopy
;
1835 draggingExited(WMView
*self
, WMDraggingInfo
*info
)
1837 printf("draggingExited\n");
1841 prepareForDragOperation(WMView
*self
, WMDraggingInfo
*info
)
1843 printf("draggingExited\n");
1844 return;//"bll"; //"application/X-color";
1849 performDragOperation(WMView
*self
, WMDraggingInfo
*info
) //, WMData *data)
1851 char *colorName
= "Blue";// (char*)WMDataBytes(data);
1853 WMText
*tPtr
= (WMText
*)self
->self
;
1858 if (tPtr
->flags
.monoFont
)
1861 color
= WMCreateNamedColor(W_VIEW_SCREEN(self
), colorName
, True
);
1862 printf("color [%s] %p\n", colorName
, color
);
1864 WMSetTextSelectionColor(tPtr
, color
);
1865 WMReleaseColor(color
);
1872 concludeDragOperation(WMView
*self
, WMDraggingInfo
*info
)
1874 printf("concludeDragOperation\n");
1878 static WMDragDestinationProcs _DragDestinationProcs
= {
1882 prepareForDragOperation
,
1883 performDragOperation
,
1884 concludeDragOperation
1890 WMCreateText(WMWidget
*parent
)
1892 Text
*tPtr
= wmalloc(sizeof(Text
));
1894 printf("could not create text widget\n");
1899 printf("sizeof:\n");
1900 printf(" TextBlock %d\n", sizeof(TextBlock
));
1901 printf(" Section %d\n", sizeof(Section
));
1902 printf(" char * %d\n", sizeof(char *));
1903 printf(" void * %d\n", sizeof(void *));
1904 printf(" short %d\n", sizeof(short));
1905 printf(" Text %d\n", sizeof(Text
));
1908 memset(tPtr
, 0, sizeof(Text
));
1909 tPtr
->widgetClass
= WC_Text
;
1910 tPtr
->view
= W_CreateView(W_VIEW(parent
));
1912 perror("could not create text's view\n");
1916 tPtr
->view
->self
= tPtr
;
1917 tPtr
->view
->attribs
.cursor
= tPtr
->view
->screen
->textCursor
;
1918 tPtr
->view
->attribFlags
|= CWOverrideRedirect
| CWCursor
;
1919 W_ResizeView(tPtr
->view
, 250, 200);
1920 tPtr
->bgGC
= WMColorGC(tPtr
->view
->screen
->white
);
1921 tPtr
->fgGC
= WMColorGC(tPtr
->view
->screen
->black
);
1922 W_SetViewBackgroundColor(tPtr
->view
, tPtr
->view
->screen
->white
);
1929 //tPtr->dFont = WMCreateFont(tPtr->view->screen,
1930 // "-*-fixed-medium-r-normal--26-*-*-*-*-*-*-*");
1931 //"-sony-fixed-medium-r-normal--24-230-75-75-c-120-jisx0201.1976-0");
1932 // "-*-times-bold-r-*-*-12-*-*-*-*-*-*-*,"
1933 // "-*-fixed-medium-r-normal-*-12-*");
1935 tPtr
->dFont
= WMRetainFont(tPtr
->view
->screen
->normalFont
);
1937 tPtr
->dColor
= WMBlackColor(tPtr
->view
->screen
);
1939 tPtr
->view
->delegate
= &_TextViewDelegate
;
1942 tPtr
->timerID
= NULL
;
1945 WMCreateEventHandler(tPtr
->view
, ExposureMask
|StructureNotifyMask
1946 |EnterWindowMask
|LeaveWindowMask
|FocusChangeMask
,
1947 handleEvents
, tPtr
);
1949 WMCreateEventHandler(tPtr
->view
, ButtonReleaseMask
|ButtonPressMask
1950 |KeyReleaseMask
|KeyPressMask
|Button1MotionMask
,
1951 handleActionEvents
, tPtr
);
1953 WMAddNotificationObserver(ownershipObserver
, tPtr
, "_lostOwnership", tPtr
);
1956 WMSetViewDragDestinationProcs(tPtr
->view
, &_DragDestinationProcs
);
1958 char *types
[2] = {"application/X-color", NULL
};
1959 WMRegisterViewForDraggedTypes(tPtr
->view
, types
);
1966 tPtr
->firstTextBlock
= NULL
;
1967 tPtr
->lastTextBlock
= NULL
;
1968 tPtr
->currentTextBlock
= NULL
;
1971 tPtr
->gfxItems
= WMCreateArrayBag(4);
1973 tPtr
->parser
= NULL
;
1974 tPtr
->writer
= NULL
;
1976 tPtr
->sel
.x
= tPtr
->sel
.y
= 2;
1977 tPtr
->sel
.w
= tPtr
->sel
.h
= 0;
1979 tPtr
->clicked
.x
= tPtr
->clicked
.y
= 2;
1981 tPtr
->visible
.x
= tPtr
->visible
.y
= 2;
1982 tPtr
->visible
.h
= tPtr
->view
->size
.height
;
1983 tPtr
->visible
.w
= tPtr
->view
->size
.width
- 12;
1985 tPtr
->cursor
.x
= -23;
1988 tPtr
->docHeight
= 0;
1989 tPtr
->dBulletPix
= WMCreatePixmapFromXPMData(tPtr
->view
->screen
,
1991 tPtr
->db
= (Pixmap
) NULL
;
1993 tPtr
->margins
= wmalloc(sizeof(WMRulerMargins
));
1994 tPtr
->margins
[0].left
= tPtr
->margins
[0].right
= tPtr
->visible
.x
;
1995 tPtr
->margins
[0].body
= tPtr
->visible
.x
;
1996 tPtr
->margins
[0].right
= tPtr
->visible
.w
;
1998 tPtr
->flags
.nmargins
= 1;
1999 tPtr
->flags
.rulerShown
= False
;
2000 tPtr
->flags
.monoFont
= False
;
2001 tPtr
->flags
.focused
= False
;
2002 tPtr
->flags
.editable
= True
;
2003 tPtr
->flags
.ownsSelection
= False
;
2004 tPtr
->flags
.pointerGrabbed
= False
;
2005 tPtr
->flags
.buttonHeld
= False
;
2006 tPtr
->flags
.waitingForSelection
= False
;
2007 tPtr
->flags
.extendSelection
= False
;
2008 tPtr
->flags
.rulerShown
= False
;
2009 tPtr
->flags
.frozen
= False
;
2010 tPtr
->flags
.cursorShown
= True
;
2011 tPtr
->flags
.clickPos
= 1;
2012 tPtr
->flags
.ignoreNewLine
= False
;
2013 tPtr
->flags
.laidOut
= False
;
2014 tPtr
->flags
.prepend
= False
;
2015 tPtr
->flags
.relief
= WRFlat
;
2016 tPtr
->flags
.alignment
= WALeft
;
2023 WMPrependTextStream(WMText
*tPtr
, char *text
)
2028 tPtr
->flags
.prepend
= True
;
2029 if (text
&& tPtr
->parser
)
2030 (tPtr
->parser
) (tPtr
, (void *) text
);
2032 insertPlainText(tPtr
, text
);
2037 WMAppendTextStream(WMText
*tPtr
, char *text
)
2042 tPtr
->flags
.prepend
= False
;
2043 if (text
&& tPtr
->parser
)
2044 (tPtr
->parser
) (tPtr
, (void *) text
);
2046 insertPlainText(tPtr
, text
);
2052 WMGetTextStream(WMText
*tPtr
)
2054 TextBlock
*tb
= NULL
;
2056 unsigned long length
= 0, where
= 0;
2061 if (!(tb
= tPtr
->firstTextBlock
))
2065 (tPtr
->writer
) (tPtr
, (void *) text
);
2069 /* first, how large a buffer would we want? */
2071 if (!tPtr
->flags
.ignoreNewLine
&& (tb
->first
|| tb
->blank
))
2078 text
= wmalloc(length
+1); /* +1 for the end of string, let's be nice */
2079 tb
= tPtr
->firstTextBlock
;
2082 if (!tPtr
->flags
.ignoreNewLine
&& (tb
->first
|| tb
->blank
))
2083 text
[where
++] = '\n';
2084 memcpy(&text
[where
], tb
->text
, tb
->used
);
2098 WMGetTextStreamObjects(WMText
*tPtr
)
2108 WMGetTextSelected(WMText
*tPtr
)
2116 //tb = tPtr->firstTextBlock;
2117 tb
= tPtr
->currentTextBlock
;
2121 text
= wmalloc(tb
->used
+1);
2122 memcpy(text
, tb
->text
, tb
->used
);
2128 WMGetTextSelectedObjects(WMText
*tPtr
)
2137 WMCreateTextBlockWithObject(WMWidget
*w
, char *description
, WMColor
*color
,
2138 unsigned short first
, unsigned short reserved
)
2141 unsigned short length
;
2143 if (!w
|| !description
|| !color
)
2146 tb
= wmalloc(sizeof(TextBlock
));
2150 length
= strlen(description
);
2151 tb
->text
= (char *)wmalloc(length
);
2152 memset(tb
->text
, 0, length
);
2153 memcpy(tb
->text
, description
, length
);
2157 tb
->color
= WMRetainColor(color
);
2164 tb
->underlined
= False
;
2166 tb
->sections
= NULL
;
2176 WMCreateTextBlockWithPixmap(WMPixmap
*p
, char *description
, WMColor
*color
,
2177 unsigned short first
, unsigned short reserved
)
2180 unsigned short length
;
2182 if (!p
|| !description
|| !color
)
2185 tb
= wmalloc(sizeof(TextBlock
));
2189 length
= strlen(description
);
2190 tb
->text
= (char *)wmalloc(length
);
2191 memset(tb
->text
, 0, length
);
2192 memcpy(tb
->text
, description
, length
);
2196 tb
->color
= WMRetainColor(color
);
2203 tb
->underlined
= False
;
2205 tb
->sections
= NULL
;
2214 WMCreateTextBlockWithText(char *text
, WMFont
*font
, WMColor
*color
,
2215 unsigned short first
, unsigned short length
)
2219 if (!font
|| !color
)
2222 tb
= wmalloc(sizeof(TextBlock
));
2226 tb
->allocated
= reqBlockSize(length
);
2227 tb
->text
= (char *)wmalloc(tb
->allocated
);
2228 memset(tb
->text
, 0, tb
->allocated
);
2230 if (length
< 1|| !text
) { // || *text == '\n') {
2235 memcpy(tb
->text
, text
, length
);
2240 tb
->d
.font
= WMRetainFont(font
);
2241 tb
->color
= WMRetainColor(color
);
2245 tb
->graphic
= False
;
2246 tb
->underlined
= False
;
2248 tb
->sections
= NULL
;
2256 WMSetTextBlockProperties(void *vtb
, unsigned int first
,
2257 unsigned int kanji
, unsigned int underlined
, int script
,
2258 unsigned int marginN
)
2260 TextBlock
*tb
= (TextBlock
*) vtb
;
2266 tb
->underlined
= underlined
;
2267 tb
->script
= script
;
2268 tb
->marginN
= marginN
;
2272 WMGetTextBlockProperties(void *vtb
, unsigned int *first
,
2273 unsigned int *kanji
, unsigned int *underlined
, int *script
,
2274 unsigned int *marginN
)
2276 TextBlock
*tb
= (TextBlock
*) vtb
;
2280 if (first
) *first
= tb
->first
;
2281 if (kanji
) *kanji
= tb
->kanji
;
2282 if (underlined
) *underlined
= tb
->underlined
;
2283 if (script
) *script
= tb
->script
;
2284 if (marginN
) *marginN
= tb
->marginN
;
2290 WMPrependTextBlock(WMText
*tPtr
, void *vtb
)
2292 TextBlock
*tb
= (TextBlock
*)vtb
;
2300 WMWidget
*w
= tb
->d
.widget
;
2301 WMCreateEventHandler(W_VIEW(w
), ButtonPressMask
,
2302 handleWidgetPress
, tb
);
2303 if (W_CLASS(w
) != WC_TextField
&& W_CLASS(w
) != WC_Text
) {
2304 (W_VIEW(w
))->attribs
.cursor
= tPtr
->view
->screen
->defaultCursor
;
2305 (W_VIEW(w
))->attribFlags
|= CWOverrideRedirect
| CWCursor
;
2308 WMPutInBag(tPtr
->gfxItems
, (void *)tb
);
2310 } else tPtr
->tpos
= tb
->used
;
2312 if (!tPtr
->lastTextBlock
|| !tPtr
->firstTextBlock
) {
2313 tb
->next
= tb
->prior
= NULL
;
2314 tPtr
->lastTextBlock
= tPtr
->firstTextBlock
2315 = tPtr
->currentTextBlock
= tb
;
2319 tb
->next
= tPtr
->currentTextBlock
;
2320 tb
->prior
= tPtr
->currentTextBlock
->prior
;
2321 if (tPtr
->currentTextBlock
->prior
)
2322 tPtr
->currentTextBlock
->prior
->next
= tb
;
2324 tPtr
->currentTextBlock
->prior
= tb
;
2326 tPtr
->firstTextBlock
= tb
;
2328 tPtr
->currentTextBlock
= tb
;
2333 WMAppendTextBlock(WMText
*tPtr
, void *vtb
)
2335 TextBlock
*tb
= (TextBlock
*)vtb
;
2342 WMWidget
*w
= tb
->d
.widget
;
2343 WMCreateEventHandler(W_VIEW(w
), ButtonPressMask
,
2344 handleWidgetPress
, tb
);
2345 if (W_CLASS(w
) != WC_TextField
&& W_CLASS(w
) != WC_Text
) {
2346 (W_VIEW(w
))->attribs
.cursor
=
2347 tPtr
->view
->screen
->defaultCursor
;
2348 (W_VIEW(w
))->attribFlags
|= CWOverrideRedirect
| CWCursor
;
2351 WMPutInBag(tPtr
->gfxItems
, (void *)tb
);
2353 } else tPtr
->tpos
= tb
->used
;
2355 if (!tPtr
->lastTextBlock
|| !tPtr
->firstTextBlock
) {
2356 tb
->next
= tb
->prior
= NULL
;
2357 tPtr
->lastTextBlock
= tPtr
->firstTextBlock
2358 = tPtr
->currentTextBlock
= tb
;
2362 tb
->next
= tPtr
->currentTextBlock
->next
;
2363 tb
->prior
= tPtr
->currentTextBlock
;
2364 if (tPtr
->currentTextBlock
->next
)
2365 tPtr
->currentTextBlock
->next
->prior
= tb
;
2367 tPtr
->currentTextBlock
->next
= tb
;
2370 tPtr
->lastTextBlock
= tb
;
2372 tPtr
->currentTextBlock
= tb
;
2376 WMRemoveTextBlock(WMText
*tPtr
)
2378 TextBlock
*tb
= NULL
;
2380 if (!tPtr
|| !tPtr
->firstTextBlock
|| !tPtr
->lastTextBlock
2381 || !tPtr
->currentTextBlock
) {
2382 printf("cannot remove non existent TextBlock!\b");
2386 tb
= tPtr
->currentTextBlock
;
2388 WMRemoveFromBag(tPtr
->gfxItems
, (void *)tb
);
2391 WMDeleteEventHandler(W_VIEW(tb
->d
.widget
), ButtonPressMask
,
2392 handleWidgetPress
, tb
);
2393 WMUnmapWidget(tb
->d
.widget
);
2397 if (tPtr
->currentTextBlock
== tPtr
->firstTextBlock
) {
2398 if (tPtr
->currentTextBlock
->next
)
2399 tPtr
->currentTextBlock
->next
->prior
= NULL
;
2401 tPtr
->firstTextBlock
= tPtr
->currentTextBlock
->next
;
2402 tPtr
->currentTextBlock
= tPtr
->firstTextBlock
;
2404 } else if (tPtr
->currentTextBlock
== tPtr
->lastTextBlock
) {
2405 tPtr
->currentTextBlock
->prior
->next
= NULL
;
2406 tPtr
->lastTextBlock
= tPtr
->currentTextBlock
->prior
;
2407 tPtr
->currentTextBlock
= tPtr
->lastTextBlock
;
2409 tPtr
->currentTextBlock
->prior
->next
= tPtr
->currentTextBlock
->next
;
2410 tPtr
->currentTextBlock
->next
->prior
= tPtr
->currentTextBlock
->prior
;
2411 tPtr
->currentTextBlock
= tPtr
->currentTextBlock
->next
;
2418 WMDestroyTextBlock(WMText
*tPtr
, void *vtb
)
2420 TextBlock
*tb
= (TextBlock
*)vtb
;
2426 /* naturally, there's a danger to destroying
2427 widgets whose action brings us here:
2428 ie. press a button to destroy it... need to
2429 find a safer way. till then... this stays commented out */
2430 //WMDestroyWidget(tb->d.widget);
2431 //wfree(tb->d.widget);
2432 tb
->d
.widget
= NULL
;
2434 WMReleasePixmap(tb
->d
.pixmap
);
2435 tb
->d
.pixmap
= NULL
;
2438 WMReleaseFont(tb
->d
.font
);
2441 WMReleaseColor(tb
->color
);
2442 if (tb
->sections
&& tb
->nsections
> 0)
2443 wfree(tb
->sections
);
2451 WMRefreshText(WMText
*tPtr
, int vpos
, int hpos
)
2453 if (!tPtr
|| vpos
<0 || hpos
<0)
2456 if (tPtr
->flags
.frozen
)
2460 if (tPtr
->vpos
!= vpos
) {
2461 if (vpos
< 0 || tPtr
->docHeight
< tPtr
->visible
.h
) {
2463 } else if(tPtr
->docHeight
- vpos
> tPtr
->visible
.h
- tPtr
->visible
.y
) {
2466 tPtr
->vpos
= tPtr
->docHeight
- tPtr
->visible
.h
;
2470 tPtr
->flags
.laidOut
= False
;
2471 layOutDocument(tPtr
);
2472 updateScrollers(tPtr
);
2478 WMSetTextForegroundColor(WMText
*tPtr
, WMColor
*color
)
2484 tPtr
->fgGC
= WMColorGC(color
);
2486 tPtr
->fgGC
= WMColorGC(WMBlackColor(tPtr
->view
->screen
));
2488 WMRefreshText(tPtr
, tPtr
->vpos
, tPtr
->hpos
);
2492 WMSetTextBackgroundColor(WMText
*tPtr
, WMColor
*color
)
2498 tPtr
->bgGC
= WMColorGC(color
);
2499 W_SetViewBackgroundColor(tPtr
->view
, color
);
2501 tPtr
->bgGC
= WMColorGC(WMWhiteColor(tPtr
->view
->screen
));
2502 W_SetViewBackgroundColor(tPtr
->view
,
2503 WMWhiteColor(tPtr
->view
->screen
));
2506 WMRefreshText(tPtr
, tPtr
->vpos
, tPtr
->hpos
);
2510 WMSetTextRelief(WMText
*tPtr
, WMReliefType relief
)
2514 tPtr
->flags
.relief
= relief
;
2519 WMSetTextHasHorizontalScroller(WMText
*tPtr
, Bool shouldhave
)
2524 if (shouldhave
&& !tPtr
->hS
) {
2525 tPtr
->hS
= WMCreateScroller(tPtr
);
2526 (W_VIEW(tPtr
->hS
))->attribs
.cursor
= tPtr
->view
->screen
->defaultCursor
;
2527 (W_VIEW(tPtr
->hS
))->attribFlags
|= CWOverrideRedirect
| CWCursor
;
2528 WMSetScrollerArrowsPosition(tPtr
->hS
, WSAMaxEnd
);
2529 WMSetScrollerAction(tPtr
->hS
, scrollersCallBack
, tPtr
);
2530 } else if (!shouldhave
&& tPtr
->hS
) {
2531 WMUnmapWidget(tPtr
->hS
);
2532 WMDestroyWidget(tPtr
->hS
);
2538 textDidResize(tPtr
->view
->delegate
, tPtr
->view
);
2543 WMSetTextHasRuler(WMText
*tPtr
, Bool shouldhave
)
2548 if(shouldhave
&& !tPtr
->ruler
) {
2549 tPtr
->ruler
= WMCreateRuler(tPtr
);
2550 (W_VIEW(tPtr
->ruler
))->attribs
.cursor
=
2551 tPtr
->view
->screen
->defaultCursor
;
2552 (W_VIEW(tPtr
->ruler
))->attribFlags
|= CWOverrideRedirect
| CWCursor
;
2553 WMSetRulerReleaseAction(tPtr
->ruler
, rulerReleaseCallBack
, tPtr
);
2554 WMSetRulerMoveAction(tPtr
->ruler
, rulerMoveCallBack
, tPtr
);
2555 } else if(!shouldhave
&& tPtr
->ruler
) {
2556 WMShowTextRuler(tPtr
, False
);
2557 WMDestroyWidget(tPtr
->ruler
);
2560 textDidResize(tPtr
->view
->delegate
, tPtr
->view
);
2564 WMShowTextRuler(WMText
*tPtr
, Bool show
)
2571 if(tPtr
->flags
.monoFont
)
2574 tPtr
->flags
.rulerShown
= show
;
2576 WMMapWidget(tPtr
->ruler
);
2578 WMUnmapWidget(tPtr
->ruler
);
2581 textDidResize(tPtr
->view
->delegate
, tPtr
->view
);
2585 WMGetTextRulerShown(WMText
*tPtr
)
2593 return tPtr
->flags
.rulerShown
;
2598 WMSetTextHasVerticalScroller(WMText
*tPtr
, Bool shouldhave
)
2603 if (shouldhave
&& !tPtr
->vS
) {
2604 tPtr
->vS
= WMCreateScroller(tPtr
);
2605 (W_VIEW(tPtr
->vS
))->attribs
.cursor
= tPtr
->view
->screen
->defaultCursor
;
2606 (W_VIEW(tPtr
->vS
))->attribFlags
|= CWOverrideRedirect
| CWCursor
;
2607 WMSetScrollerArrowsPosition(tPtr
->vS
, WSAMaxEnd
);
2608 WMSetScrollerAction(tPtr
->vS
, scrollersCallBack
, tPtr
);
2609 } else if (!shouldhave
&& tPtr
->vS
) {
2610 WMUnmapWidget(tPtr
->vS
);
2611 WMDestroyWidget(tPtr
->vS
);
2617 textDidResize(tPtr
->view
->delegate
, tPtr
->view
);
2623 WMScrollText(WMText
*tPtr
, int amount
)
2628 if (amount
== 0 || !tPtr
->view
->flags
.realized
)
2632 if (tPtr
->vpos
> 0) {
2633 if (tPtr
->vpos
> amount
) tPtr
->vpos
+= amount
;
2637 int limit
= tPtr
->docHeight
- tPtr
->visible
.h
;
2638 if (tPtr
->vpos
< limit
) {
2639 if (tPtr
->vpos
< limit
-amount
) tPtr
->vpos
+= amount
;
2640 else tPtr
->vpos
= limit
;
2644 if (scroll
&& tPtr
->vpos
!= tPtr
->prevVpos
) {
2645 updateScrollers(tPtr
);
2648 tPtr
->prevVpos
= tPtr
->vpos
;
2653 WMPageText(WMText
*tPtr
, Bool direction
)
2655 if (!tPtr
) return False
;
2656 if (!tPtr
->view
->flags
.realized
) return False
;
2658 return WMScrollText(tPtr
, direction
?tPtr
->visible
.h
:-tPtr
->visible
.h
);
2662 WMSetTextEditable(WMText
*tPtr
, Bool editable
)
2666 tPtr
->flags
.editable
= editable
;
2670 WMGetTextEditable(WMText
*tPtr
)
2674 return tPtr
->flags
.editable
;
2678 WMSetTextIgnoresNewline(WMText
*tPtr
, Bool ignore
)
2682 tPtr
->flags
.ignoreNewLine
= ignore
;
2686 WMGetTextIgnoresNewline(WMText
*tPtr
)
2690 return tPtr
->flags
.ignoreNewLine
;
2694 WMSetTextUsesMonoFont(WMText
*tPtr
, Bool mono
)
2698 if (mono
&& tPtr
->flags
.rulerShown
)
2699 WMShowTextRuler(tPtr
, False
);
2701 tPtr
->flags
.monoFont
= mono
;
2702 WMRefreshText(tPtr
, tPtr
->vpos
, tPtr
->hpos
);
2706 WMGetTextUsesMonoFont(WMText
*tPtr
)
2710 return tPtr
->flags
.monoFont
;
2715 WMSetTextDefaultFont(WMText
*tPtr
, WMFont
*font
)
2720 WMReleaseFont(tPtr
->dFont
);
2724 tPtr
->dFont
= WMRetainFont(tPtr
->view
->screen
->normalFont
);
2728 WMGetTextDefaultFont(WMText
*tPtr
)
2737 WMSetTextAlignment(WMText
*tPtr
, WMAlignment alignment
)
2741 tPtr
->flags
.alignment
= alignment
;
2742 WMRefreshText(tPtr
, tPtr
->vpos
, tPtr
->hpos
);
2746 WMSetTextParser(WMText
*tPtr
, WMAction
*parser
)
2750 tPtr
->parser
= parser
;
2754 WMSetTextWriter(WMText
*tPtr
, WMAction
*writer
)
2758 tPtr
->writer
= writer
;
2762 WMGetTextInsertType(WMText
*tPtr
)
2766 return tPtr
->flags
.prepend
;
2771 WMSetTextSelectionColor(WMText
*tPtr
, WMColor
*color
)
2774 if (!tPtr
|| !color
)
2777 tb
= tPtr
->firstTextBlock
;
2778 if (!tb
|| !tPtr
->flags
.ownsSelection
)
2783 WMReleaseColor(tb
->color
);
2784 tb
->color
= WMRetainColor(color
);
2787 WMRefreshText(tPtr
, tPtr
->vpos
, tPtr
->hpos
);
2791 WMSetTextSelectionFont(WMText
*tPtr
, WMFont
*font
)
2797 tb
= tPtr
->firstTextBlock
;
2798 if (!tb
|| !tPtr
->flags
.ownsSelection
)
2803 tb
->d
.font
= WMRetainFont(font
);
2806 WMRefreshText(tPtr
, tPtr
->vpos
, tPtr
->hpos
);
2810 WMFreezeText(WMText
*tPtr
)
2815 tPtr
->flags
.frozen
= True
;
2819 WMThawText(WMText
*tPtr
)
2824 tPtr
->flags
.frozen
= False
;
2829 WMFindInTextStream(WMText
*tPtr
, char *needle
)
2831 char *haystack
= NULL
;
2834 if (!tPtr
|| !needle
)
2837 if ( !(haystack
= WMGetTextStream(tPtr
)))
2840 result
= (Bool
) strstr(haystack
, needle
);