From d3d030410700cee3a6c80cc009767c03fb321254 Mon Sep 17 00:00:00 2001 From: nwanua Date: Thu, 13 Jul 2000 23:48:54 +0000 Subject: [PATCH] changes to wmtext --- WINGs/WINGs.h | 184 +- WINGs/testtext.c | 826 ++++---- WINGs/wtext.c | 4699 +++++++++++++++++++--------------------------- 3 files changed, 2519 insertions(+), 3190 deletions(-) diff --git a/WINGs/WINGs.h b/WINGs/WINGs.h index a19b35a4..3404ee5e 100644 --- a/WINGs/WINGs.h +++ b/WINGs/WINGs.h @@ -193,17 +193,6 @@ enum { }; -typedef enum { - WRulerLeft=0, - WRulerBody, - WRulerFirst, - WRulerRight, - WRulerBoth, - WRulerDocLeft -} WMRulerMarginType; - - - /* drag operations */ typedef enum { WDOperationNone, @@ -395,16 +384,16 @@ typedef struct WMInputPanel { } WMInputPanel; -/* WMRuler stuff */ -/* All indentation and tab markers are _relative_ to the left margin marker */ -/* a tabstop is a linked list of tabstops, each containing the position of the tabstop */ +/* WMRuler: a tabstop is a linked list of tabstops, + each containing the position of the tabstop */ typedef struct { int value; struct WMTabStops *next; } WMTabStops; +/* All indentation and tab markers are _relative_ to the left margin marker */ typedef struct { int left; /* left margin marker */ int right; /* right margin marker */ @@ -414,9 +403,6 @@ typedef struct { } WMRulerMargins; - - - typedef void *WMHandlerID; typedef void WMInputProc(int fd, int mask, void *clientData); @@ -490,6 +476,26 @@ typedef struct WMTextFieldDelegate { } WMTextFieldDelegate; +typedef struct WMTextDelegate { + void *data; + + void (*didBeginEditing)(struct WMTextDelegate *self, + WMNotification *notif); + + void (*didChange)(struct WMTextDelegate *self, + WMNotification *notif); + + void (*didEndEditing)(struct WMTextDelegate *self, + WMNotification *notif); + + Bool (*shouldBeginEditing)(struct WMTextDelegate *self, + WMText *tPtr); + + Bool (*shouldEndEditing)(struct WMTextDelegate *self, + WMText *tPtr); +} WMTextDelegate; + + typedef struct WMTabViewDelegate { void *data; @@ -523,25 +529,6 @@ typedef struct WMSelectionProcs { } WMSelectionProcs; - - -typedef void WMParseAction(WMWidget *self, void *clientData, short type); - -/* these are the things parsers (for text) do */ - -typedef struct _parserActions { - void *(*createParagraph) (short fmargin, short bmargin, - short rmargin, short *tabstops, short numTabs, WMAlignment a); - void (*insertParagraph) (WMText *tPtr, void *para, Bool prepend); - void *(*createPChunk) (WMPixmap *pixmap, short script, ushort ul); - void *(*createTChunk) (char *text, short chars, WMFont *font, - WMColor *color, short script, ushort ul); - void (*insertChunk) (WMText *tPtr, void *chunk, Bool prepend); -} WMParserActions; - - - - typedef struct W_DraggingInfo WMDraggingInfo; @@ -805,10 +792,6 @@ void WMUnmapWidget(WMWidget *w); void WMMapWidget(WMWidget *w); -void WMRaiseWidget(WMWidget *w); - -void WMLowerWidget(WMWidget *w); - void WMMoveWidget(WMWidget *w, int x, int y); void WMResizeWidget(WMWidget *w, unsigned int width, unsigned int height); @@ -980,8 +963,6 @@ void WMSetLabelImage(WMLabel *lPtr, WMPixmap *image); WMPixmap *WMGetLabelImage(WMLabel *lPtr); -char *WMGetLabelText(WMLabel *lPtr); - void WMSetLabelImagePosition(WMLabel *lPtr, WMImagePosition position); void WMSetLabelTextAlignment(WMLabel *lPtr, WMAlignment alignment); @@ -1410,7 +1391,7 @@ WMRuler *WMCreateRuler (WMWidget *parent); void WMShowRulerTabs(WMRuler *rPtr, Bool Show); -int WMGetRulerMargin(WMRuler *rPtr, int which); +WMRulerMargins WMGetRulerMargins(WMRuler *rPtr); void WMSetRulerMargins(WMRuler *rPtr, WMRulerMargins margins); @@ -1430,71 +1411,80 @@ void WMSetRulerReleaseAction(WMRuler *rPtr, WMAction *action, void *clientData); WMText *WMCreateText(WMWidget *parent); -int WMGetTextParagraphs(WMText *tPtr); -int WMGetTextCurrentParagraph(WMText *tPtr); -void WMSetTextCurrentParagraph(WMText *tPtr, int current); -void WMRemoveTextParagraph(WMText *tPtr, int which); - -int WMGetTextChunks(WMText *tPtr); -int WMGetTextCurrentChunk(WMText *tPtr); -void WMRemoveTextChunk(WMText *tPtr, int which); -void WMSetTextCurrentChunk(WMText *tPtr, int current); - -void W_InsertText(WMText *tPtr, void *data, Bool prepend); -#define WMAppendTextStream(t, d) W_InsertText(t, d, False) -#define WMPrependTextStream(t, d) W_InsertText(t, d, True) - - -void WMSetTextParser(WMText *tPtr, WMParseAction *parser); -WMParserActions WMGetTextParserActions(WMText *tPtr); -#if 0 -typedef enum { - WDPCreateParagraph=0, - WDPInsertParagraph=1, - WDPCreateText=2, - WDPCreateImage=3, - WDPInsertChunk -} WMDoParse; -void WMDoTextParse(WMText *tPtr, short action); -#endif - -char * WMGetTextAll(WMText *tPtr); -void WMSetTextWriter(WMText *tPtr, WMParseAction *writer); - -void WMSetTextHasHorizontalScroller(WMText *tPtr, Bool flag); -void WMSetTextHasVerticalScroller(WMText *tPtr, Bool flag); - void WMRefreshText(WMText *tPtr, int vpos, int hpos); -void WMFreezeText(WMText *tPtr); + +void WMFreezeText(WMText *tPtr); + void WMThawText(WMText *tPtr); -void WMSetTextMonoFont(WMText *tPtr, Bool mono); -Bool WMGetTextMonoFont(WMText *tPtr); -void WMSetTextEditable(WMText *tPtr, Bool editable); -Bool WMGetTextEditable(WMText *tPtr); -void WMForceTextFocus(WMText *tPtr); - -void WMSetTextAlignment(WMText *tPtr, WMAlignment alignment); -void WMIgnoreTextNewline(WMText *tPtr, Bool ignore); - - Bool WMScrollText(WMText *tPtr, int amount); -Bool WMPageText(WMText *tPtr, Bool scrollUp); +Bool WMPageText(WMText *tPtr, Bool direction); + +void WMSetTextHasHorizontalScroller(WMText *tPtr, Bool shouldhave); + +void WMSetTextHasVerticalScroller(WMText *tPtr, Bool shouldhave); + +void WMSetTextHasRuler(WMText *tPtr, Bool shouldhave); void WMShowTextRuler(WMText *tPtr, Bool show); -Bool WMGetTextRulerShown(WMText *tPtr); -void WMShowTextRulerTabs(WMText *tPtr, Bool show); -void WMSetTextRulerMargin(WMText *tPtr, char which, short pixels); -short WMGetTextRulerMargin(WMText *tPtr, char which); -void WMSetTextUseFixedPitchFont(WMText *tPtr, Bool fixed); -void WMSetTextDefaultColor(WMText *tPtr, WMColor *color); +void WMSetTextUseMonoFont(WMText *tPtr, Bool mono); + +int WMGetTextUsesMonoFont(WMText *tPtr); + void WMSetTextDefaultFont(WMText *tPtr, WMFont *font); -void WMSetTextDefaultAlignment(WMText *tPtr, WMAlignment alignment); + +WMFont * WMGetTextDefaultFont(WMText *tPtr); + +void WMSetTextRelief(WMText *tPtr, WMReliefType relief); + +void WMSetTextForegroundColor(WMText *tPtr, WMColor *color); + void WMSetTextBackgroundColor(WMText *tPtr, WMColor *color); +void WMPrependTextStream(WMText *tPtr, char *text); +void WMAppendTextStream(WMText *tPtr, char *text); + +WMData * WMGetTextSelected(WMText *tPtr); + +void *WMCreateTextBlockWithObject(WMWidget *w, char *description, + WMColor *color, unsigned short first, unsigned short reserved); + +void *WMCreateTextBlockWithText(char *text, WMFont *font, + WMColor *color, unsigned short first, unsigned short length); + +void WMSetTextBlockProperties(void *vtb, unsigned int first, + unsigned int kanji, unsigned int underlined, int script, + unsigned int marginN); + +void WMGetTextBlockProperties(void *vtb, unsigned int *first, + unsigned int *kanji, unsigned int *underlined, int *script, + unsigned int *marginN); + + +/* parser related stuff... see how it can be done in testtext.c */ + +void WMSetTextParser(WMText *tPtr, WMAction *parser); + +void WMSetTextWriter(WMText *tPtr, WMAction *writer); + +int WMGetTextInsertType(WMText *tPtr); + +int WMGetTextBlocks(WMText *tPtr); + +void WMSetCurrentTextBlock(WMText *tPtr, int current); + +int WMGetCurrentTextBlock(WMText *tPtr); + +void WMPrependTextBlock(WMText *tPtr, void *vtb); + +void WMAppendTextBlock(WMText *tPtr, void *vtb); + +void *WMRemoveTextBlock(WMText *tPtr); + +void WMDestroyTextBlock(WMText *tPtr, void *vtb); /* ....................................................................... */ @@ -1528,8 +1518,6 @@ void WMSelectTabViewItemAtIndex(WMTabView *tPtr, int index); void WMSetTabViewDelegate(WMTabView *tPtr, WMTabViewDelegate *delegate); -WMTabViewItem *WMCreateTabViewItem(int identifier, char *label); - WMTabViewItem *WMCreateTabViewItemWithIdentifier(int identifier); int WMGetTabViewItemIdentifier(WMTabViewItem *item); diff --git a/WINGs/testtext.c b/WINGs/testtext.c index 17a77807..2356a416 100644 --- a/WINGs/testtext.c +++ b/WINGs/testtext.c @@ -1,31 +1,36 @@ -/* WINGsP.h should NEVER be included from user applications */ -#include -#include -#include -#include -#include +#include "WINGs.h" +#include -#include + +WMScreen *scr; void wAbort() { - exit(0); + exit(0); } -void -Close(WMWidget *self, void *client) +void Close(WMWidget *self, void *client) { - exit(0); + exit(0); } +extern WMFont * WMGetFontPlain(WMScreen *scrPtr, WMFont *font); + +extern WMFont * WMGetFontBold(WMScreen *scrPtr, WMFont *font); + +extern WMFont * WMGetFontItalic(WMScreen *scrPtr, WMFont *font); + +extern WMFont * WMGetFontOfSize(WMScreen *scrPtr, WMFont *font, int size); + + /* =============== a rudimentary HTML parser ======================= */ /* due to the WMSetTextParser stuff, it should not - be too hard to add parsers. like dis :-] */ +be too hard to add parsers. like dis :-] */ /* @@ -35,61 +40,59 @@ Close(WMWidget *self, void *client) */ unsigned char map_table[256] = { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, - 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, - 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, - 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, - 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, - 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 91, 92, - 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, - 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, - 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, - 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, - 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, - 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, - 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, - 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, - 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, - 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, - 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, - 248, 249, 250, 251, 252, 253, 254, 255}; +0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, +17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, +33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, +49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, +97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, +111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 91, 92, +93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, +108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, +122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, +136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, +150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, +164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, +178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, +192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, +206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, +220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, +234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, +248, 249, 250, 251, 252, 253, 254, 255}; #define TOLOWER(x) (map_table[(int)x]) static int mystrcasecmp(const unsigned char *s1, const unsigned char *s2) { - if (!*s1 || !*s2) return 0; - while (*s2 != '\0') { - if (TOLOWER (*s1) != TOLOWER (*s2)) /* true if *s1 == 0 ! */ - return 0; - s1++; - s2++; - } - return (*s1=='\0' ||!isalnum(*s1))?1:0; + if (!*s1 || !*s2) return 0; + while (*s2 != '\0') { + if (TOLOWER (*s1) != TOLOWER (*s2)) /* true if *s1 == 0 ! */ + return 0; + s1++; + s2++; + } + return (*s1=='\0' ||!isalnum(*s1))?1:0; } - + typedef struct _currentFormat { - void *para; - WMBag *fonts; - WMBag *colors; - WMColor *ccolor; - WMFont *cfont; - WMParserActions actions; - //WMBag *aligns; // for tables... - /* the following are "nested" - i.e.: - 1 2 1 1 2 0 get it? */ - short i; - short b; - short u; - short fmargin; - short bmargin; - WMAlignment align:2; - short type:1; - short ul:3; /* how "nested"... up to 8 levels deep */ - short comment:1; /* ignore text till --> */ - short RESERVED:10; + WMBag *fonts; + WMBag *colors; + WMColor *ccolor; + WMFont *cfont; + //WMBag *aligns; // for tables... + /* the following are "nested" + i.e.: + 1 2 1 1 2 0 get it? */ + short i; + short b; + short u; + short fmargin; + short bmargin; + WMAlignment align:2; + short type:1; + short ul:3; /* how "nested"... up to 8 levels deep */ + short comment:1; /* ignore text till --> */ + short RESERVED:10; } CFMT; CFMT cfmt; @@ -98,348 +101,465 @@ CFMT cfmt; #if 0 getArg(char *t, short type, void *arg) { - short d=0; - while(*(++t) && !d) { - if(type==0) { - if(*t>='0' && *t<='9') { - sscanf(t, "%d", arg); - while(*t&& (*t<'0' || *t>'9')) - t++; - d=1; - } - } - } + short d=0; + while(*(++t) && !d) { + if(type==0) { + if(*t>='0' && *t<='9') { + sscanf(t, "%d", arg); + while(*t&& (*t<'0' || *t>'9')) + t++; + d=1; + } + } + } } #endif - -void -parseToken(WMText *tPtr, char *token, short tk) + +void parseToken(WMText *tPtr, char *token, short tk) { - short mode=0; /* 0 starts, 1 closes */ - WMScreen *scr = (W_VIEW(tPtr))->screen; + short mode=0; /* 0 starts, 1 closes */ + int first = True; + void *tb= NULL; + int prepend = WMGetTextInsertType(tPtr); - while(*token && isspace(*(token))) token++; - if(*token == '/') { - token++; - mode = 1; - while(isspace(*(token))) token++; - } + while(*token && isspace(*(token))) token++; + if(*token == '/') { + token++; + mode = 1; + while(isspace(*(token))) token++; + } - if(strlen(token)==1) { - /* nice and fast for small tokens... no need for too much brain - power here */ - switch(TOLOWER(*token)) { - case 'i': - if(!mode) { - cfmt.cfont = WMGetFontItalic(scr, cfmt.cfont); - WMPutInBag(cfmt.fonts, (void *)cfmt.cfont); - } else { /*dun wanna remove the baseFont eh? */ - int count = WMGetBagItemCount(cfmt.fonts); - if(count>1) - WMDeleteFromBag(cfmt.fonts, count-1); - cfmt.cfont = (WMFont *)WMGetFromBag(cfmt.fonts, - WMGetBagItemCount(cfmt.fonts)-1); - } break; - case 'b': - if(!mode) { - cfmt.cfont = WMGetFontBold(scr, cfmt.cfont); - WMPutInBag(cfmt.fonts, (void *)cfmt.cfont); - } else { /*dun wanna remove the baseFont eh? */ - int count = WMGetBagItemCount(cfmt.fonts); - if(count>1) - WMDeleteFromBag(cfmt.fonts, count-1); - cfmt.cfont = (WMFont *)WMGetFromBag(cfmt.fonts, - WMGetBagItemCount(cfmt.fonts)-1); - } break; - case 'p': - cfmt.para = (cfmt.actions.createParagraph) (cfmt.fmargin, cfmt.bmargin, - WMWidgetWidth(tPtr)-30, NULL, 0, cfmt.align); - (cfmt.actions.insertParagraph) (tPtr, cfmt.para, cfmt.type); - cfmt.para = (cfmt.actions.createParagraph) (cfmt.fmargin, cfmt.bmargin, - WMWidgetWidth(tPtr)-30, NULL, 0, cfmt.align); - (cfmt.actions.insertParagraph) (tPtr, cfmt.para, cfmt.type); - break; - case 'u': cfmt.u = !mode; break; - } - } else { /* the tag is, as far as I'm concerned, useless */ - if(mystrcasecmp(token, "br")) { - cfmt.para = (cfmt.actions.createParagraph) (cfmt.fmargin, cfmt.bmargin, - WMWidgetWidth(tPtr)-30, NULL, 0, cfmt.align); - (cfmt.actions.insertParagraph) (tPtr, cfmt.para, cfmt.type); - } - else if(mystrcasecmp(token, "ul")) { - if(mode) { - if(cfmt.ul>1) cfmt.ul--; - } else cfmt.ul++; - if(cfmt.ul) { - cfmt.bmargin = cfmt.ul*30; - cfmt.fmargin = cfmt.bmargin-10; - } else cfmt.fmargin = cfmt.bmargin = 0; - } else if(mystrcasecmp(token, "li")) { - cfmt.para = (cfmt.actions.createParagraph) (cfmt.fmargin, cfmt.bmargin, - WMWidgetWidth(tPtr)-30, NULL, 0, cfmt.align); - (cfmt.actions.insertParagraph) (tPtr, cfmt.para, cfmt.type); - } else if(mystrcasecmp(token, "align")) - ;//printf("align"); - else if(mystrcasecmp(token, "img")) { - if(!mode) { - char *mark=NULL; - WMPixmap *pixmap; - void *chunk; - token+=3; - while(isspace(*(token))) token++; - do { - switch(TOLOWER(*token)) { - case 's': - if(TOLOWER(*(1+token)) == 'r' && TOLOWER(*(2+token)) == 'c') { - mark = strchr(token, '='); - if(mark) { - char img[256], *iptr; - token = mark+1; - if(!token) return; - sscanf(token, "%s", img); - iptr = img; - if(*img == '\"') { img[strlen(img)-1] = 0; iptr++;} - pixmap = WMCreatePixmapFromFile(scr, iptr); - chunk = (cfmt.actions.createPChunk)(pixmap, 0, False); - (cfmt.actions.insertChunk) (tPtr, chunk, False); - printf("[%s]\n", iptr); - } } break; } } while(*(token++)); - } - } else if(mystrcasecmp(token, "font")) { + if(strlen(token)==1) { + /* nice and fast for small tokens... no need for too much brain + power here */ + switch(TOLOWER(*token)) { + case 'i': + if(!mode) { + cfmt.cfont = WMGetFontItalic(scr, cfmt.cfont); + WMPutInBag(cfmt.fonts, (void *)cfmt.cfont); + } else { /*dun wanna remove the baseFont eh? */ + int count = WMGetBagItemCount(cfmt.fonts); + if(count>1) + WMDeleteFromBag(cfmt.fonts, count-1); + cfmt.cfont = (WMFont *)WMGetFromBag(cfmt.fonts, + WMGetBagItemCount(cfmt.fonts)-1); + } break; + case 'b': + if(!mode) { + cfmt.cfont = WMGetFontBold(scr, cfmt.cfont); + WMPutInBag(cfmt.fonts, (void *)cfmt.cfont); + } else { /*dun wanna remove the baseFont eh? */ + int count = WMGetBagItemCount(cfmt.fonts); + if(count>1) + WMDeleteFromBag(cfmt.fonts, count-1); + cfmt.cfont = (WMFont *)WMGetFromBag(cfmt.fonts, + WMGetBagItemCount(cfmt.fonts)-1); + } break; + case 'p': + first = True; + tb = WMCreateTextBlockWithText(NULL, cfmt.cfont, + cfmt.ccolor, first, 0); + WMSetTextBlockProperties(tb, first, False, (cfmt.u?1:0), 0, 0); + WMAppendTextBlock(tPtr, tb); + break; + case 'u': cfmt.u = !mode; break; + } + } else { /* the tag is, as far as I'm concerned, useless */ + if(mystrcasecmp(token, "br")) { + first = True; + } + else if(mystrcasecmp(token, "ul")) { + if(mode) { + if(cfmt.ul>1) cfmt.ul--; + } else cfmt.ul++; + if(cfmt.ul) { + cfmt.bmargin = cfmt.ul*30; + cfmt.fmargin = cfmt.bmargin-10; + } else cfmt.fmargin = cfmt.bmargin = 0; + } else if(mystrcasecmp(token, "li")) { + first = True; +//change margins... create a new margin.... + //(cfmt.fmargin, cfmt.bmargin, + } else if(mystrcasecmp(token, "align")) + ;//printf("align"); + else if(mystrcasecmp(token, "img")) { + if(!mode) { + char *mark=NULL; + WMPixmap *pixmap; + WMLabel *l; + token+=3; + while(isspace(*(token))) token++; + do { + switch(TOLOWER(*token)) { + case 's': + if(TOLOWER(*(1+token)) == 'r' && TOLOWER(*(2+token)) == 'c') { + mark = strchr(token, '='); + if(mark) { + char img[256], *iptr; + token = mark+1; + if(!token) return; + sscanf(token, "%s", img); + iptr = img; + if(*img == '\"') { img[strlen(img)-1] = 0; iptr++;} + pixmap = WMCreatePixmapFromFile(scr, iptr); + if(pixmap) { + l = WMCreateLabel(tPtr); + WMResizeWidget(l, 48, 48); + WMSetLabelRelief(l, WRFlat); + WMSetLabelImagePosition(l, WIPImageOnly); + WMSetLabelImage(l, pixmap); + tb = WMCreateTextBlockWithObject(l, + iptr, cfmt.ccolor, first, 0); + WMSetTextBlockProperties(tb, first, + False, (cfmt.u?1:0), 0, 0); + WMAppendTextBlock(tPtr, tb); + } + printf("[%s]\n", iptr); + } } break; } } while(*(token++)); + } + } else if(mystrcasecmp(token, "font")) { #if 0 - if(mode) { - cfmt.cfont = (WMFont *)WMGetFromBag(cfmt.fonts, - WMGetBagItemCount(cfmt.fonts)-1); - } else - (WMColor *)WMGetFromBag(cfmt.colors, - WMGetBagItemCount(cfmt.colors)-1), -#endif - } - else if(mystrcasecmp(token, "center")) { - printf("center\n"); - if(mode) cfmt.align = WALeft; - else cfmt.align = WACenter; - cfmt.para = (cfmt.actions.createParagraph) (cfmt.fmargin, cfmt.bmargin, - WMWidgetWidth(tPtr)-30, NULL, 0, cfmt.align); - (cfmt.actions.insertParagraph) (tPtr, cfmt.para, cfmt.type); - } - } + if(mode) { + cfmt.cfont = (WMFont *)WMGetFromBag(cfmt.fonts, + WMGetBagItemCount(cfmt.fonts)-1); + } else + (WMColor *)WMGetFromBag(cfmt.colors, + WMGetBagItemCount(cfmt.colors)-1), +#endif + } + else if(mystrcasecmp(token, "center")) { +printf("center\n"); + if(mode) cfmt.align = WALeft; + else cfmt.align = WACenter; + first = True; +//change margins... + } + } + - - //printf("parse token (%s)[%s]\n", mode?"close":"open", token); + //printf("parse token (%s)[%s]\n", mode?"close":"open", token); #if 0 - i=0; - //while(*token && !isspace(*(token))) token++; - //printf("A:%d a:%d z%d Z%d\n", '1', 'a', 'Z', 'z'); - do { - if(!mm) { - if(c>=65 && c<=122) { major[i++] = c; - } else if(c==' ' || c=='='){ major[i] = 0; i=0; mm=1; - printf("\nmajor: [%s]", major);} - } else { - if(c!=' ') { - minor[i++] = c; - } else { minor[i] = 0; i=0; printf(" minor: [%s] ", minor);} - } - }while((c = *(++token))); + i=0; + //while(*token && !isspace(*(token))) token++; +//printf("A:%d a:%d z%d Z%d\n", '1', 'a', 'Z', 'z'); + do { + if(!mm) { + if(c>=65 && c<=122) { major[i++] = c; + } else if(c==' ' || c=='='){ major[i] = 0; i=0; mm=1; + printf("\nmajor: [%s]", major);} + } else { + if(c!=' ') { + minor[i++] = c; + } else { minor[i] = 0; i=0; printf(" minor: [%s] ", minor);} + } + }while((c = *(++token))); #endif - - - //printf("parse token (%s)[%s]\n", mode?"close":"open", token); + + + //printf("parse token (%s)[%s]\n", mode?"close":"open", token); } - -void -HTMLParser(WMWidget *w, void *clientData, short type) + +void HTMLParser(WMWidget *w, void *clientData) { - static short init=1; /* have we been here at least once before? */ + static short init=1; /* have we been here at least once before? */ char *stream = (char *) clientData; - WMText *tPtr = (WMText *)w; - WMScreen *scr; - void *chunk; - char c; -#define MAX_TOKEN_SIZE 255 - char token[MAX_TOKEN_SIZE+1]; -#define MAX_TEXT_SIZE 1023 - char text[MAX_TEXT_SIZE+1]; - short mode=0; - short tk=0, txt=0; - short wasspace=0; + WMText *tPtr = (WMText *)w; + void *tb = NULL; + char c; + #define MAX_TOKEN_SIZE 255 + char token[MAX_TOKEN_SIZE+1]; + #define MAX_TEXT_SIZE 1023 + char text[MAX_TEXT_SIZE+1]; + short mode=0; + short tk=0, textlen=0; + short wasspace=0; + int first = False; if(!tPtr || !stream) return; - scr = (W_VIEW(tPtr))->screen; - cfmt.type = type; - if(init) { - cfmt.actions = WMGetTextParserActions(tPtr); - cfmt.fonts = WMCreateBag(4); /* there sould always be at least 1 font... */ - cfmt.cfont = WMSystemFontOfSize(scr, 12); - WMPutInBag(cfmt.fonts, (void *)cfmt.cfont); - cfmt.colors = WMCreateBag(4); - cfmt.ccolor = WMBlackColor(scr); - WMPutInBag(cfmt.colors, (void *)cfmt.ccolor); - cfmt.i = cfmt.b = cfmt.u = cfmt.ul = 0; - cfmt.align = WALeft; - cfmt.fmargin = cfmt.bmargin = 0; - cfmt.para = (cfmt.actions.createParagraph) (cfmt.fmargin, cfmt.bmargin, - WMWidgetWidth(tPtr)-30, NULL, 0, cfmt.align); - (cfmt.actions.insertParagraph) (tPtr, cfmt.para, cfmt.type); - init = 0; - } + cfmt.type = WMGetTextInsertType(tPtr); + if(1||init) { + cfmt.fonts = WMCreateBag(4); /* there sould always be at least 1 font... */ + cfmt.cfont = WMGetTextDefaultFont(tPtr); + WMPutInBag(cfmt.fonts, (void *)cfmt.cfont); + cfmt.colors = WMCreateBag(4); + cfmt.ccolor = WMBlackColor(scr); + WMPutInBag(cfmt.colors, (void *)cfmt.ccolor); + cfmt.i = cfmt.b = cfmt.u = cfmt.ul = 0; + cfmt.align = WALeft; + cfmt.fmargin = cfmt.bmargin = 0; + init = 0; + } -#if 1 - if(strlen(stream) == 1 && stream[0] == '\n') { - /* sometimes if the text entered is a single char AND is a newline, - the user prolly typed it */ - cfmt.para = (cfmt.actions.createParagraph) (cfmt.fmargin, cfmt.bmargin, - WMWidgetWidth(tPtr)-30, NULL, 0, cfmt.align); - (cfmt.actions.insertParagraph) (tPtr, cfmt.para, cfmt.type); - return; - } +#if 0 + if(strlen(stream) == 1 && stream[0] == '\n') { + /* sometimes if the text entered is a single char AND is a newline, + the user prolly typed it */ + cfmt.para = (cfmt.actions.createParagraph) (cfmt.fmargin, cfmt.bmargin, + WMWidgetWidth(tPtr)-30, NULL, 0, cfmt.align); + (cfmt.actions.insertParagraph) (tPtr, cfmt.para, cfmt.type); + return; + } #endif - /* - */ +/* +*/ - while( (c=*(stream++))) { - //printf("%c", c); - if(c == '\n' || c =='\t') - //c = ' '; //continue; - continue; - if(c == ' ') { - if(wasspace) - continue; - wasspace = 1; - }else wasspace = 0; + while( (c=*(stream++))) { +//printf("%c", c); + if(c == '\n' || c =='\t') + //c = ' '; //continue; + continue; + if(c == ' ') { + if(wasspace) + continue; + wasspace = 1; + }else wasspace = 0; - if(c == '<' && !mode) { - mode=1; - if(txt>0) { - text[txt] = 0; - chunk = (cfmt.actions.createTChunk)(text, txt, cfmt.cfont, - cfmt.ccolor, 0, (cfmt.u?1:0)); - (cfmt.actions.insertChunk) (tPtr, chunk, cfmt.type); - //printf("%s\n", text); - } - txt = 0; - } else if(c == '>' && mode) { - token[tk] = 0; - if(tk>0) parseToken(tPtr, token, tk); - mode=0; - tk=0; - } else { - if(mode) { - if(tk < MAX_TOKEN_SIZE) token[tk++] = c; - } else if(txt < MAX_TEXT_SIZE) text[txt++] = c; - } - } - - if(tk>0) { token[tk] = 0; parseToken(tPtr, token, tk);} - if(txt>0) { - text[txt] = 0; - //printf("%s\n", text); - chunk = (cfmt.actions.createTChunk)(text, txt, - (WMFont *)WMGetFromBag(cfmt.fonts, - WMGetBagItemCount(cfmt.fonts)-1), - (WMColor *)WMGetFromBag(cfmt.colors, - WMGetBagItemCount(cfmt.colors)-1), - 0, (cfmt.u?1:0)); - (cfmt.actions.insertChunk) (tPtr, chunk, cfmt.type); - } + if(c == '<' && !mode) { + mode=1; + if(textlen>0) { + text[textlen] = 0; + tb = WMCreateTextBlockWithText(text, cfmt.cfont, + cfmt.ccolor, first, textlen); + WMSetTextBlockProperties(tb, first, False, (cfmt.u?1:0), 0, 0); + WMAppendTextBlock(tPtr, tb); +//printf("%s\n", text); + } + textlen = 0; + } else if(c == '>' && mode) { + token[tk] = 0; + if(tk>0) parseToken(tPtr, token, tk); + mode=0; + tk=0; + } else { + if(mode) { + if(tk < MAX_TOKEN_SIZE) token[tk++] = c; + } else if(textlen < MAX_TEXT_SIZE) text[textlen++] = c; + } + } + if(tk>0) { token[tk] = 0; parseToken(tPtr, token, tk);} + if(textlen>0) { + text[textlen] = 0; + //printf("%s\n", text); + tb = WMCreateTextBlockWithText(text, + (WMFont *)WMGetFromBag(cfmt.fonts, + WMGetBagItemCount(cfmt.fonts)-1), + (WMColor *)WMGetFromBag(cfmt.colors, + WMGetBagItemCount(cfmt.colors)-1), + first, textlen); + WMSetTextBlockProperties(tb, first, False, (cfmt.u?1:0), 0, 0); + WMAppendTextBlock(tPtr, tb); + } + } /* ================= the driver ================== */ -WMWidget *win; -WMText *text; - -void -NotificationObserver(void *self, WMNotification *notif) +static void +buttonPressCB(WMWidget *w, void *client) { - void *object = WMGetNotificationObject(notif); - unsigned short w = WMWidgetWidth(win); - unsigned short h = WMWidgetHeight(win); - - if (WMGetNotificationName(notif) == WMViewSizeDidChangeNotification) { - if (object == WMWidgetView(win)) { - WMResizeWidget(text, w-20, h-20); - } - } - - {static int i=0; - switch(i++) { - case 0: WMSetTextHasHorizontalScroller(text, False); break; - case 1: WMSetTextHasVerticalScroller(text, False); break; - case 2: WMSetTextHasVerticalScroller(text, True); break; - case 3: WMSetTextHasHorizontalScroller(text, True); break; - default: i=0; - } - } + WMText *tPtr = (WMText *)client; + WMAppendTextStream(tPtr, NULL); + WMAppendTextStream(tPtr, + "

You just had to press that button, didn't you? " + "Well, this sort of thing is bound to happen when you go about " + " pressing buttons :-)" + "

Cheers,

Nwanua"); + WMRefreshText(tPtr, 0, 0); } int main(int argc, char **argv) { - Display *dpy; - WMScreen *scr; + Display *dpy; + WMWidget *win; + WMText *text; + WMRulerMargins margins; + void *tb = NULL; - WMInitializeApplication("WMText", &argc, argv); - dpy = XOpenDisplay(NULL); - if(!dpy) exit(1); + WMInitializeApplication("WMText", &argc, argv); + dpy = XOpenDisplay(NULL); + if(!dpy) { printf("no display? *sniff* :~( "); exit(1);} - scr = WMCreateSimpleApplicationScreen(dpy); + scr = WMCreateSimpleApplicationScreen(dpy); - win = WMCreateWindow(scr, "WMText Test"); - WMRealizeWidget(win); - WMResizeWidget(win, 500, 300); - //WMResizeWidget(win, 900, 600); - WMSetWindowTitle(win,"WMText Test"); - WMSetWindowCloseAction(win, Close, NULL); + win = WMCreateWindow(scr, "WMText Test"); + WMRealizeWidget(win); + WMResizeWidget(win, 500, 300); + //WMResizeWidget(win, 900, 600); + WMSetWindowTitle(win,"WMText Test"); + WMSetWindowCloseAction(win, Close, NULL); - text = WMCreateText(win); - WMRealizeWidget(text); - WMResizeWidget(text, 480, 280); - WMMoveWidget(text, 10, 10); - WMSetTextUseFixedPitchFont(text, False); - WMSetTextMonoFont(text, False); - WMSetTextParser(text, HTMLParser); - WMSetTextEditable(text, True); - WMFreezeText(text); - if(1){ - FILE *f = fopen("./wm.html", "r"); - char data[1024]; - if(f) { - while(fgets(data, 1022,f)) - WMAppendTextStream(text, data); - fclose(f); - } else { - WMAppendTextStream(text, "can't open the wm.html file, but here's a text stream
that
needs parsing"); - } + text = WMCreateText(win); + WMRealizeWidget(text); + //WMSetTextHasHorizontalScroller(text, True); + WMResizeWidget(text, 480, 280); + WMMoveWidget(text, 10, 10); + WMSetTextRelief(text, WRSunken); + WMSetTextHasVerticalScroller(text, True); + WMSetTextUseMonoFont(text, !True); + WMSetTextParser(text, HTMLParser); +#if 0 + WMSetTextUseFixedPitchFont(text, False); + WMSetTextHasRuler(text, True); + WMShowTextRuler(text, True); + WMSetTextHasVerticalScroller(text, True); + //WMSetTextHasHorizontalScroller(text, True); + WMSetTextEditable(text, True); + WMFreezeText(text); +#endif + + //margins = WMGetTextRulerMargins(text); + + + + + WMAppendTextStream(text, +"

\ +WINGs is a small widget set with \ +a very nice look and feel. Its API is inspired \ +and its implementation borrows some ideas from interesting places.\ +

+The library is limited and its design is a little sloppy, \ +so it's not intended to build large or complex applications, just +small and complex ones. :-)\ +

Apart from the usual buttons and labels, it has some \ +interesting widgets like this list widget: "); + + { + WMList *list = WMCreateList(text); + char t[20]; + int i; + + WMResizeWidget(list, 60, 60); + for (i=0; i<7; i++) { + sprintf(t, "Item %i", i); + WMAddListItem(list, t); + } + + tb = WMCreateTextBlockWithObject(list, "{a list object or somesuch}", + WMBlackColor(scr), False, 0); + WMAppendTextBlock(text, tb); + + } + + + WMAppendTextStream(text, " a colour well such as this one: "); + { + WMColorWell *well; + well = WMCreateColorWell(text); + WMResizeWidget(well, 60, 40); + WMSetColorWellColor(well, + WMCreateRGBColor(scr, 0, 0, 0x8888, True)); + tb = WMCreateTextBlockWithObject(well, "{a button object}", + WMBlackColor(scr), False, 0); + WMAppendTextBlock(text, tb); + } + + WMAppendTextStream(text, + ", as well as a text widget: "); + + { + WMText *te = WMCreateText(text); + WMRealizeWidget(te); + WMResizeWidget(te, 120, 90); + WMSetTextParser(te, HTMLParser); + WMSetTextRelief(te, WRFlat); + // WMSetTextBackgroundColor(te, WMCreateNamedColor(scr, "Red", False)); + WMSetTextDefaultFont(te, WMSystemFontOfSize(scr, 10)); + WMAppendTextStream(te, "into which you can easily embed other " + "WINGs objects (such as this one), " + " without breaking a sweat (type in here)"); + tb = WMCreateTextBlockWithObject(te, "{a text object}", + WMBlackColor(scr), False, 0); + WMAppendTextBlock(text, tb); + WMSetTextHasVerticalScroller(te, False); + WMRefreshText(te, 0, 0); + } + + { + WMText *te = WMCreateText(text); + WMRealizeWidget(te); + WMResizeWidget(te, 120, 90); + WMSetTextParser(te, HTMLParser); + WMSetTextRelief(te, WRFlat); + // WMSetTextBackgroundColor(te, WMCreateNamedColor(scr, "Red", False)); + WMSetTextDefaultFont(te, WMSystemFontOfSize(scr, 10)); + WMAppendTextStream(te, "I always wanted to be able to have " + "a multi-column text editor in Unix for my reports, " + " now all I have to do is wait for someone to code it :-P"); + tb = WMCreateTextBlockWithObject(te, "{a text object}", + WMBlackColor(scr), False, 0); + WMAppendTextBlock(text, tb); + WMSetTextHasVerticalScroller(te, False); + WMRefreshText(te, 0, 0); } - //WMPrependTextStream(text, "this is prepended\n"); - //WMAppendTextStream(text, "blueplanet.rtf"); + + + + WMAppendTextStream(text, +" .

Not bad eh? \ +

Since WINGs is \ +written in C and is sort of \ +low-level, it is \ +small and faster than say, Motif or even Athena (just you try +embedding and clicking on buttons"); + + { + WMButton *b = WMCreateCommandButton(text); + WMSetButtonText(b, "like me"); + WMSetButtonAction(b, buttonPressCB, text); + WMResizeWidget(b, 60, 15); + tb = WMCreateTextBlockWithObject(b, "{a button object}", + WMBlackColor(scr), False, 0); + WMAppendTextBlock(text, tb); + } + + WMAppendTextStream(text, +" with those other tool-kits :-).

Knowing Xlib will help you to \ +workaround some of its limitations, although you'll probably be able to \ +write something like a trivial tic-tac-toe game "); + + { + WMTextField *t = WMCreateTextField(text); + WMInsertTextFieldText(t, "or an interesting text editor", 0); + WMResizeWidget(t, 160, 20); + WMSetTextFieldBordered(t, True); + WMSetTextFieldBeveled(t, True); + tb = WMCreateTextBlockWithObject(t, "{a textfield object}", + WMGrayColor(scr), False, 0); + WMAppendTextBlock(text, tb); + } - WMThawText(text); + WMAppendTextStream(text, " without knowing much Xlib. " + "

(BTW, don't press that button that is screeming" + " to be pressed!"); + + + +// WMThawText(text); WMRefreshText(text, 0, 0); - /* - WMAddNotificationObserver(NotificationObserver, win, - WMViewSizeDidChangeNotification, WMWidgetView(win)); - */ - WMSetViewNotifySizeChanges(WMWidgetView(win), True); - WMMapSubwidgets(win); - WMMapWidget(win); +/* + WMAddNotificationObserver(NotificationObserver, win, + WMViewSizeDidChangeNotification, WMWidgetView(win)); +*/ + WMSetViewNotifySizeChanges(WMWidgetView(win), True); + WMMapSubwidgets(win); + WMMapWidget(win); - WMScreenMainLoop(scr); + WMScreenMainLoop(scr); + return 0; } diff --git a/WINGs/wtext.c b/WINGs/wtext.c index 431da534..faab1550 100644 --- a/WINGs/wtext.c +++ b/WINGs/wtext.c @@ -1,2921 +1,2142 @@ -/* WMText: multi-line/font/color text widget for WINGs */ -/* Copyleft (>) 1999, 2000 Nwanua Elumeze */ +/* + * WINGs WMText multi-line/font/color/graphic text widget + * + * Copyright (c) 1999-2000 Nwanua Elumeze + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ -/* .( * . - .* . ) . - - . . POOF .* . - '* . ( .) ' - jgs ` ( . * */ - - -/* if monoFont, ignore pixmaps, colors, fonts, script, underline */ - - -#include -#include +#include "WINGsP.h" #include #include -#include -typedef enum { - ctText = 0, - ctImage = 1 -} ChunkType; +//_______ +//TODO: -typedef enum { - dtDelete = 0, - dtBackSpace -} DeleteType; +#if 0 + +use currentTextBlock and neighbours for fast paint and layout -typedef enum { - wrWord = 0, - wrChar = 1, - wrNone = 2 -} Wrapping; +WMGetTextStreamAll... WMGetTextStream WMGetTextSelection(if(selected) ) +the bitfield arrangement in this code assumes a little-endian + machine... might need a __BIG_ENDIAN__ define for arranging + the bitfields efficiently for those big boys. -void wgdbFree(void *ptr) -{ - if (!ptr) - printf("err... cannot "); - printf("gdbFree [%p]\n", ptr); - wfree(ptr); -} +make a file named fontman.c, put that kind of +stuff in there and not put the APIs in WINGs.h +WMGetFontItalic() should some day be part of the font manager +instead, just put a bunch of extern WMGetFontbla in the top of wtext.c + +#endif - -/* Why single-linked and not say double-linked? - 99% of the time (draw, append), the "prior" - member would have been a useless memory and CPU overhead, - and deletes _are_ relatively infrequent. - When the "prior" member needs to be used, the overhead of - doing things the hard way will be incurred... but seldomly. */ - - -/* a Chunk is a single-linked list of chunks containing: - * o text with a given format - * o or an image - * o but NOT both - */ -typedef struct _Chunk { - char *text; /* the text in the chunk */ - WMPixmap *pixmap; /* OR the pixmap it holds */ - short chars; /* the number of characters in this chunk */ - short mallocedSize; /* the number of characters that can be held */ - - WMFont *font; /* the chunk's font */ - WMColor *color; /* the chunk's color */ - short ul:1; /* underlined or not */ - ChunkType type:1; /* a "Text" or "Image" chunk */ - short script:4; /* script in points: negative for subscript */ - /* hrmm selec... */ - ushort selected; - ushort sStart; - ushort sEnd; - ushort RESERVED:10; - struct _Chunk *next; /*the next member in this list */ - -} Chunk; +//_______ -/* a Paragraph is a singly-linked list of paragraphs containing: - * o a list of chunks in that paragraph - * o the formats for that paragraph - * o its (draw) position relative to the entire document - */ -typedef struct _Paragraph { - Chunk *chunks; /* the list of text and/or image chunks */ - short fmargin; /* the start position of the first line */ - short bmargin; /* the start positions of the rest of the lines */ - short rmargin; /* the end position of the entire paragraph */ - short numTabs; /* the number of tabstops */ - short *tabstops; /* an array of tabstops */ - Pixmap drawbuffer; /* the pixmap onto which the (entire) - paragraph will be drawn */ - WMPixmap *bulletPix; /* the pixmap to use for bulleting */ - int top; /* the top of the paragraph relative to document */ - int bottom; /* the bottom of the paragraph relative to document */ - int width; /* the width of the paragraph */ - int height; /* the height of the paragraph */ - WMAlignment align:2; /* justification of this paragraph */ - ushort RESERVED:14; - - struct _Paragraph *next; /* the next member in this list */ -} Paragraph; +/* a Section is a section of a TextBlock that describes what parts + of a TextBlock has be layout on which "line"... + o this greatly aids redraw, scroll and selection. + o this is created during layoutLine, but may be later modified. + o there may be many regions per TextBlock, hence the array */ +typedef struct { + int x, y; /* where to draw it from */ + int w, h; /* it's width and height (to aid selection) */ + int _y; + unsigned short begin, end; /* what part of the text block */ +} Section; -static char *default_bullet[] = -{ - "6 6 4 1", - " c None s None", ". c black", - "X c white", "o c #808080", - " ... ", - ".XX.. ", - ".XX..o", - ".....o", - " ...oo", - " ooo " -}; +/* a TextBlock is a doubly-linked list of TextBlocks containing: + o text for the block, color and font + o or a pointer to the widget and the (text) description for its graphic + o but NOT both */ + +typedef struct _TextBlock { + struct _TextBlock *next; /* next text block in linked list */ + struct _TextBlock *prior; /* prior text block in linked list */ + + char *text; /* pointer to 8- or 16-bit text */ + /* or to the object's description */ + union { + WMFont *font; /* the font */ + WMWidget *widget; /* the embedded widget */ + } d; /* description */ + + WMColor *color; /* the color */ + Section *sections; /* the region for layouts (a growable array) */ + /* an _array_! of size _nsections_ */ + + unsigned short used; /* number of chars in this block */ + unsigned short allocated; /* size of allocation (in chars) */ + + unsigned int first:1; /* first TextBlock in paragraph */ + unsigned int blank:1; /* ie. blank paragraph */ + unsigned int kanji:1; /* is of 16-bit characters or not */ + unsigned int graphic:1; /* embedded object or text: text=0 */ + unsigned int underlined:1; /* underlined or not */ + unsigned int nsections:8; /* over how many "lines" a TexBlock wraps */ + int script:8; /* script in points: negative for subscript */ + unsigned int marginN:10; /* which of the margins in WMText to use */ + unsigned int RESERVED:1; +} TextBlock; + + +/* somehow visible.h beats the hell outta visible.size.height :-) */ +typedef struct { + unsigned int y; + unsigned int x; + unsigned int h; + unsigned int w; +} myRect; -/* this is really a shrunk down version of the original - "broken" icon... I did not draw it, I simply shrunk it */ -static char *unk_xpm[] = -{ - "24 24 17 1", - " c None", ". c #0B080C", "+ c #13A015", "@ c #5151B8", - "# c #992719", "$ c #5B1C20", "% c #1DF51D", "& c #D1500D", "* c #2F304A", - "= c #0C6A0C", "- c #F2F1DE", "; c #D59131", "> c #B2B083", ", c #DD731A", - "' c #CC3113", ") c #828238", "! c #6A6A94", - "......!@@@@@@@....$$....", - "...@!@@@@@@@**...$#'....", - "..!!@@@@@@@@.......#....", - "..!@@@@@@@@@*.......$...", - ".!@@@#,,#*@@*..*>.*.#...", - "*@@@@#'',,@@@...---!....", - "!@@@@@*.#;*@@..!--->....", - "@@@@@@@@#,.@@..!----@...", - "!@@@@@@*#;'$...!----@...", - "*@@@@@@..'&;;#.)----)...", - ".@@@@@@..$..&'.>----)...", - ".@@@@@@**---,'>-----!...", - ".@@@@@@**---,'>-----@...", - "..@@@@@@@---;;;,;---....", - "..*@@@@*@--->#',;,-*.)..", - "........)---->)@;#!..>..", - ".....)----------;$..>)..", - "=%%%*.*!-------);..)-*..", - "=%%%%+...*)>!@*$,.>--...", - "*+++++++.......*$@-->...", - "............**@)!)>->...", - "........................", - "........................", - "........................" -}; typedef struct W_Text { - W_Class widgetClass; /* the class number of this widget */ - W_View *view; /* the view referring to this instance */ - WMColor *bg; /* the background color to use when drawing */ + W_Class widgetClass; /* the class number of this widget */ + W_View *view; /* the view referring to this instance */ - WMRuler *ruler; /* the ruler subwiget to maipulate paragraphs */ + WMRuler *ruler; /* the ruler subwiget to manipulate paragraphs */ - WMScroller *hscroller; /* the horizontal scroller */ - short hpos; /* the current horizontal position */ - short prevHpos; /* the previous horizontal position */ + WMScroller *vS; /* the vertical scroller */ + int vpos; /* the current vertical position */ + int prevVpos; /* the previous vertical position */ - WMScroller *vscroller; /* the vertical scroller */ - int vpos; /* the current vertical position */ - int prevVpos; /* the previous vertical position */ + WMScroller *hS; /* the horizontal scroller */ + int hpos; /* the current horizontal position */ + int prevHpos; /* the previous horizontal position */ + /* in short: tPtr->hS?nowrap:wrap */ - int visibleW; /* the actual horizontal space available */ - int visibleH; /* the actual vertical space available */ + WMFont *dFont; /* the default font */ + WMColor *dColor; /* the default color */ + WMPixmap *dBulletPix; /* the default pixmap for bullets */ - Paragraph *paragraphs; /* the linked list of the paragraphs in the doc. */ - int docWidth; /* the width of the entire document */ - int docHeight; /* the height of the entire document */ + GC bgGC; /* the background GC to draw with */ + GC fgGC; /* the foreground GC to draw with */ + Pixmap db; /* the buffer on which to draw */ - WMFont *dFont; /* the default font */ - WMColor *dColor; /* the default color */ - WMPixmap *dBulletPix; /* the default pixmap for bullets */ - WMPixmap *dUnknownImg; /* the pixmap for (missing/broken) images */ + WMRulerMargins *margins;/* a (growable) array of margins to be used */ + /* by the various TextBlocks */ - WMRect sRect; /* the selected area */ - Paragraph *currentPara; /* the current paragraph, in which actions occur */ - Chunk *currentChunk; /* the current chunk, about which actions occur */ - short tpos; /* the cursor position (text position) */ - WMParseAction *parser; /* what action to use to parse input text */ - WMParseAction *writer; /* what action to use to write text */ - WMParserActions funcs; /* the "things" that parsers/writers might do */ - XPoint clicked; /* the position of the last mouse click */ - XPoint cursor; /* where the cursor is "placed" */ - short clheight; /* the height of the "line" clicked on */ - short clwidth; /* the width of the "line" clicked on */ + myRect visible; /* the actual rectangle that can be drawn into */ + myRect sel; /* the selection rectangle */ + int docWidth; /* the width of the entire document */ + int docHeight; /* the height of the entire document */ - WMReliefType relief:3; /* the relief to display with */ - Wrapping wrapping:2; /* the type of wrapping to use in drawing */ - WMAlignment dAlignment:2; /* default justification */ - ushort monoFont:1; /* whether to ignore "rich" commands */ - ushort fixedPitch:1; /* assume each char in dFont is the same size */ - ushort editable:1; /* whether to accept user changes or not */ - ushort rulerShown:1; /* whether the ruler is shown or not */ - ushort cursorShown:1; /* whether the cursor is currently being shown */ - ushort frozen:1; /* whether screen updates are to be made */ - ushort focused:1; /* whether this instance has input focus */ - ushort pointerGrabbed:1; /* whether this instance has the pointer */ - ushort buttonHeld:1; /* the user is still holding down the button */ - ushort ignoreNewLine:1; /* whether to ignore the newline character */ - ushort waitingForSelection:1; /* whether there is a pending paste event */ - ushort ownsSelection:1; /* whether it ownz the current selection */ - ushort findingClickPoint:1; /* whether the search for a clickpoint is on */ - ushort foundClickPoint:1; /* whether the clickpoint has been found */ - ushort hasVscroller:1; /* whether to enable the vertical scroller */ - ushort hasHscroller:1; /* whether to enable the horizontal scroller */ - ushort RESERVED:10; + + TextBlock *firstTextBlock; + TextBlock *lastTextBlock; + TextBlock *currentTextBlock; + + + WMBag *gfxItems; /* a nice bag containing graphic items */ + + WMPoint clicked; /* where in the _document_ was clicked */ + unsigned short tpos; /* the character position in the currentTextBlock */ + unsigned short RESERVED;/* space taker upper... */ + + + WMAction *parser; + WMAction *writer; + + struct { + unsigned int monoFont:1; /* whether to ignore formats */ + unsigned int focused:1; /* whether this instance has input focus */ + unsigned int editable:1; /* "silly user, you can't edit me" */ + unsigned int ownsSelection:1; /* "I ownz the current selection!" */ + unsigned int pointerGrabbed:1;/* "heh, gib me pointer" */ + unsigned int buttonHeld:1; /* the user is holding down the button */ + unsigned int waitingForSelection:1; /* dum dee dumm... */ + unsigned int extendSelection:1; /* shift-drag to select more regions */ + + unsigned int rulerShown:1; /* whether the ruler is shown or not */ + unsigned int frozen:1; /* whether screen updates are to be made */ + unsigned int cursorShown:1; /* whether to show the cursor */ + unsigned int clickPos:1; /* clicked before=0/after=1 a graphic: */ + /* within counts as after too */ + + unsigned int ignoreNewLine:1;/* "bleh XK_Return" ignore it when typed */ + unsigned int laidOut:1; /* have the TextBlocks all been laid out */ + unsigned int prepend:1; /* prepend=1, append=0 (for parsers) */ + WMAlignment alignment:2; /* the alignment for text */ + WMReliefType relief:3; /* the relief to display with */ + unsigned int RESERVED:4; + unsigned int nmargins:10; /* the number of margin arrays */ + } flags; } Text; +static char *default_bullet[] = { +"6 6 4 1", +" c None s None", ". c black", +"X c white", "o c #808080", +" ... ", +".XX.. ", +".XX..o", +".....o", +" ...oo", +" ooo "}; -/* --------- static functions that are "private". don't touch :-) --------- */ - - -/* max "characters per chunk that will be drawn at a time" */ -#define MAX_WORD_LENGTH 100 -/* max on a line */ -#define MAX_CHUNX 64 -#define MIN_DOC_WIDTH 200 - -typedef struct _LocalMargins { - short left, right, first, body; -} LocalMargins; - -typedef struct _MyTextItems { - char text[MAX_WORD_LENGTH + 1]; - WMPixmap *pix; - short chars; - short x; - Chunk *chunk; /* used for "click" events */ - short start; /* ditto... where in the chunk we start (ie. wrapped chunk) */ - ushort type:1; - ushort RESERVED:15; -} MyTextItems; - - -static WMRect - chunkSelectionRect(Text * tPtr, Paragraph * para, MyTextItems item, - short y, short j, short lh) +/* done purely for speed ... mostly same as WMWidthOfString */ +static inline unsigned int +myWidthOfString(WMFont *font, char *text, unsigned int length) { - WMRect rect; - short type = 0; /* 0:none 1:partial: 2:all */ - short rh = (tPtr->rulerShown) ? 45 : 5; - short w, lm; - WMFont *font = (tPtr->monoFont || item.chunk->type != ctText) ? - tPtr->dFont : item.chunk->font; - - rect.pos.x = -23; - if (y + para->top + rh > tPtr->sRect.pos.y + tPtr->sRect.size.height - || y + para->top + rh + lh < tPtr->sRect.pos.y) - return rect; - - if (item.chunk->type == ctText) - w = WMWidthOfString(font, item.text, item.chars); - else - w = item.chunk->pixmap->width; - - if (y + para->top + rh >= tPtr->sRect.pos.y && (y + para->top + rh + lh - <= tPtr->sRect.pos.y + tPtr->sRect.size.height)) - //&& item.x+j >= tPtr->sRect.pos.x+tPtr->sRect.size.width)) - type = 2; - else - type = 1; - - -#if 0 - if (item.x + j >= tPtr->sRect.pos.x && - item.x + j + w < tPtr->sRect.pos.x + tPtr->sRect.size.width) - type = 2; - - if (type == 1 && y + para->top + rh + lh <= - tPtr->sRect.pos.y + tPtr->sRect.size.height) - type = 2; -#endif - - - if (type == 1 && item.chunk->type == ctText) { /* partial coverage */ - lm = 2 + WMGetRulerMargin(tPtr->ruler, WRulerDocLeft); - /* even I am still confused, so don't ask please */ - if ((item.x + j + lm >= tPtr->sRect.pos.x && - item.x + j + lm <= tPtr->sRect.pos.x + tPtr->sRect.size.width) - || (item.x + j + lm >= tPtr->sRect.pos.x + tPtr->sRect.size.width - && y + para->top + rh + lh <= - tPtr->sRect.pos.y + tPtr->sRect.size.height) - || (tPtr->sRect.pos.y < y + para->top + rh - && tPtr->sRect.pos.x + tPtr->sRect.size.width > - item.x + j + lm)) { - rect.size.width = w; - rect.pos.x = item.x + j; - item.chunk->selected = True; - if (item.chunk->chars > 6) { - item.chunk->sStart = 3; - item.chunk->sEnd = item.chunk->chars; - } else { - item.chunk->sStart = 0; - item.chunk->sEnd = item.chunk->chars; - } + if (font->notFontSet) + return XTextWidth(font->font.normal, text, length); + else { + XRectangle rect, AIXsucks; + XmbTextExtents(font->font.set, text, length, &AIXsucks, &rect); + return rect.width; } - } else if (type == 2) { - rect.pos.x = item.x + j; - item.chunk->selected = True; - if (item.chunk->type == ctText) { - item.chunk->sStart = 0; - item.chunk->sStart = item.chunk->chars; - rect.size.width = WMWidthOfString(font, - item.text, item.chars); - } else { - rect.size.width = item.chunk->pixmap->width; - } - } - rect.pos.y = y; - rect.size.height = lh; - return rect; } -static int myDrawText(Text * tPtr, Paragraph * para, MyTextItems * items, - short nitems, short pwidth, int y, short draw, short spacepos) -{ - short i, ul_thick, u, j = 0; /* j = justification */ - short line_width = 0, line_height = 0, mx_descent = 0; - WMScreen *screen = tPtr->view->screen; - GC gc; - WMFont *font; - if (tPtr->findingClickPoint && tPtr->foundClickPoint) - return 0; - for (i = 0; i < nitems; i++) { - if (items[i].type == ctText) { - font = (tPtr->monoFont) ? tPtr->dFont : items[i].chunk->font; - mx_descent = WMIN(mx_descent, -font->y); - line_height = WMAX(line_height, font->height); - //printf("chunk.x %d xpoint.x %d\n", - // items[i].x, tPtr->clicked.x); +static void +paintText(Text *tPtr) +{ + TextBlock *tb = tPtr->firstTextBlock; + WMFont *font; + GC gc, greyGC; + char *text; + int len, y, c, s, done=False; + int prev_y=-23; + WMScreen *scr = tPtr->view->screen; + Display *dpy = tPtr->view->screen->display; + Window win = tPtr->view->window; + + - line_width += WMWidthOfString(font, - items[i].text, items[i].chars); - } else { - mx_descent = WMIN(mx_descent, -(items[i].pix->height - 3)); - /* replace -3 wif descent... */ - line_height = WMAX(line_height, items[i].pix->height); - if (para->align == WARight || para->align == WACenter) { - line_width += items[i].pix->width; - } + if(!tPtr->view->flags.realized || !tPtr->db) + return; + + XFillRectangle(dpy, tPtr->db, tPtr->bgGC, + 0, 0, tPtr->visible.w, tPtr->visible.h); + + + tb = tPtr->firstTextBlock; + if(!tb) + goto _copy_area; + + + if(tPtr->flags.ownsSelection) { + greyGC = WMColorGC(WMGrayColor(scr)); + //XFillRectangle(dpy, tPtr->db, greyGC, +// tPtr->sel.x, tPtr->sel.y-tPtr->vpos, tPtr->sel.w, tPtr->sel.h); + // XDrawRectangle(dpy, tPtr->db, tPtr->fgGC, + // tPtr->sel.x, tPtr->sel.y-tPtr->vpos, tPtr->sel.w, tPtr->sel.h); } - } - if (para->align == WARight) { - j = pwidth - line_width; - } else if (para->align == WACenter) { - j = (short) ((float) (pwidth - line_width)) / 2.0; - } - if (tPtr->findingClickPoint && (y + line_height >= tPtr->clicked.y)) { - tPtr->foundClickPoint = True; - tPtr->currentChunk = items[0].chunk; /* just first on this "line" */ - tPtr->tpos = items[0].start; /* where to "start" counting from */ - tPtr->clicked.x = j + items[0].x; - tPtr->clicked.y = y + line_height + mx_descent; - tPtr->clheight = line_height; /* to draw the cursor */ - tPtr->clwidth = line_width; /* where to stop searching */ - return 0; - } - if (!draw) - return line_height; - - for (i = 0; i < nitems; i++) { - - //account for vpos - if (tPtr->ownsSelection) { - WMRect rect = chunkSelectionRect(tPtr, para, - items[i], y, j, line_height); - - if (rect.pos.x != -23) { /* has been selected */ - XFillRectangle(tPtr->view->screen->display, para->drawbuffer, - WMColorGC(WMGrayColor(tPtr->view->screen)), - rect.pos.x, rect.pos.y, rect.size.width, rect.size.height); - } - } - if (items[i].type == ctText) { - gc = WMColorGC(items[i].chunk->color); - font = (tPtr->monoFont) ? tPtr->dFont : items[i].chunk->font; - WMDrawString(screen, para->drawbuffer, gc, font, - items[i].x + j, y - font->y - mx_descent, - items[i].text, items[i].chars); - if (items[i].chunk->ul && !tPtr->monoFont) { - ul_thick = (short) ((float) font->height) / 12.0; - if (ul_thick < 1) - ul_thick = 1; - for (u = 0; u < ul_thick; u++) { - XDrawLine(screen->display, para->drawbuffer, gc, items[i].x + j, - y + 1 + u - mx_descent, - items[i].x + j + WMWidthOfString(font, - items[i].text, items[i].chars), y + 1 + u - mx_descent); + done = False; + while(!done && tb) { + if(!tb->sections || (!tPtr->flags.monoFont && tb->graphic)) { + tb = tb->next; + continue; } - } - } else { - WMDrawPixmap(items[i].pix, para->drawbuffer, items[i].x + j, - y + 3 - mx_descent - items[i].pix->height); - } - } - return line_height; -} -static void drawPChunkPart(Text * tPtr, Chunk * chunk, LocalMargins m, Paragraph * para, - MyTextItems * items, short *nitems, short *Lmargin, XPoint * where, short draw) -{ - short p_width; - - if (!chunk) - return; - if (!chunk->pixmap) - chunk->pixmap = WMRetainPixmap(tPtr->dUnknownImg); - - p_width = m.right - WMIN(m.first, m.body) - WMGetRulerOffset(tPtr->ruler); - if (p_width < MIN_DOC_WIDTH) // need WMRuler to take care of this... - - return; - if (where->x + chunk->pixmap->width <= p_width - *Lmargin) { - /* it can fit on rest of line */ - items[*nitems].pix = chunk->pixmap; - items[*nitems].type = ctImage; - items[*nitems].chars = 0; - items[*nitems].x = *Lmargin + where->x; - items[*nitems].chunk = chunk; - items[*nitems].start = 0; - - if (*nitems >= MAX_CHUNX) { - items[*nitems].chars = 0; - items[*nitems].x = *Lmargin + where->x; - items[*nitems].chunk = chunk; - items[*nitems].start = 0; - where->y += myDrawText(tPtr, para, items, *nitems + 1, - p_width - *Lmargin, where->y, draw, 0); - if (tPtr->findingClickPoint && tPtr->foundClickPoint) - return; - *nitems = 0; - where->x = 0; - } else { - (*nitems)++; - where->x += chunk->pixmap->width; - } - } else if (chunk->pixmap->width <= p_width - *Lmargin) { - /* it can fit on an entire line, flush the myDrawText then wrap it */ - where->y += myDrawText(tPtr, para, items, *nitems + 1, - p_width - *Lmargin, where->y, draw, 0); - *nitems = 0; - *Lmargin = WMAX(0, m.body - m.first); - where->x = 0; - drawPChunkPart(tPtr, chunk, m, para, items, nitems, - Lmargin, where, draw); - } else { -#if 1 - *nitems = 0; - where->x = 0; - *Lmargin = WMAX(0, m.body - m.first); - items[*nitems].pix = chunk->pixmap; - items[*nitems].type = ctImage; - items[*nitems].chars = 0; - items[*nitems].x = *Lmargin + where->x; - items[*nitems].chunk = chunk; - items[*nitems].start = 0; - where->y += myDrawText(tPtr, para, items, *nitems + 1, - p_width - *Lmargin, where->y, draw, 0); -#endif - - /* scale image to fit, call self again */ - /* deprecated - the management */ - } - -} - -static void drawTChunkPart(Text * tPtr, Chunk * chunk, char *bufr, LocalMargins m, - Paragraph * para, MyTextItems * items, short *nitems, short len, short start, - short *Lmargin, XPoint * where, short draw, short spacepos) -{ - short t_chunk_width, p_width, chars; - WMFont *font = (tPtr->monoFont) ? tPtr->dFont : chunk->font; - - /* if(doc->clickstart.yes && doc->clickstart.done) return; */ - - if (len == 0) - return; - p_width = m.right - WMIN(m.first, m.body); - if (p_width < MIN_DOC_WIDTH) // need WMRuler to take care of this... - - return; + for(s=0; snsections && !done; s++) { - t_chunk_width = WMWidthOfString(font, bufr, len); - if ((where->x + t_chunk_width <= p_width - *Lmargin) - || (tPtr->wrapping == wrNone)) { - /* if it can fit on rest of line, append to line */ - chars = WMIN(len, MAX_WORD_LENGTH); - snprintf(items[*nitems].text, chars + 1, "%s", bufr); - items[*nitems].chars = chars; - items[*nitems].x = *Lmargin + where->x; - items[*nitems].type = ctText; - items[*nitems].chunk = chunk; - items[*nitems].start = start; + if(tb->sections[s]._y > tPtr->vpos + tPtr->visible.h) { + done = True; + break; + } - if (*nitems >= MAX_CHUNX) { - chars = WMIN(len, MAX_WORD_LENGTH); - snprintf(items[*nitems].text, chars + 1, "%s", bufr); - items[*nitems].chars = chars; - items[*nitems].x = *Lmargin + where->x; - items[*nitems].type = ctText; - items[*nitems].chunk = chunk; - items[*nitems].start = start; - where->y += myDrawText(tPtr, para, items, *nitems + 1, - p_width - *Lmargin, where->y, draw, spacepos); - if (tPtr->findingClickPoint && tPtr->foundClickPoint) - return; - *nitems = 0; - where->x = 0; - } else { - (*nitems)++; - where->x += t_chunk_width; - } - } else if (t_chunk_width <= p_width - *Lmargin) { - /* it can fit on an entire line, flush and wrap it to a new line */ - where->y += myDrawText(tPtr, para, items, *nitems, - p_width - *Lmargin, where->y, draw, spacepos); - if (tPtr->findingClickPoint && tPtr->foundClickPoint) - return; - *nitems = 0; - *Lmargin = WMAX(0, m.body - m.first); - where->x = 0; - drawTChunkPart(tPtr, chunk, bufr, m, para, items, nitems, - len, start, Lmargin, where, draw, spacepos); - } else { - /* otherwise, chop line, call ourself recursively until it's all gone */ - short J = 0; /* bufr */ - short j = 0; /* local tmp buffer */ - char tmp[len]; - short diff = p_width - *Lmargin - where->x; - short _start = 0; + if( tb->sections[s].y + tb->sections[s].h < tPtr->vpos) + continue; - if (diff < 20) { - where->y += myDrawText(tPtr, para, items, *nitems, - p_width - *Lmargin, where->y, draw, spacepos); - if (tPtr->findingClickPoint && tPtr->foundClickPoint) - return; - *nitems = 0; - *Lmargin = WMAX(0, m.body - m.first); - where->x = 0; - diff = p_width - *Lmargin - where->x; - } - for (J = 0; J < len; J++) { - tmp[j] = bufr[J]; - if (WMWidthOfString(font, tmp, j + 1) > diff) { - drawTChunkPart(tPtr, chunk, tmp, m, para, items, nitems, - j, start + _start, Lmargin, where, draw, spacepos); - _start = J; - J--; - j = 0; - } else - j++; - } - /* and there's always that last chunk, get it too */ - drawTChunkPart(tPtr, chunk, tmp, m, para, items, nitems, - j, start + _start, Lmargin, where, draw, spacepos); - } -} + if(tPtr->flags.monoFont) { + font = tPtr->dFont; + gc = tPtr->fgGC; + } else { + font = tb->d.font; + gc = WMColorGC(tb->color); + } -/* this function does what it's called :-) - o It is also used for calculating extents of para, - (returns height) so watch out for (Bool) draw - o Also used to determine where mouse was clicked */ -static int putParagraphOnPixmap(Text * tPtr, Paragraph * para, Bool draw) -{ - char bufr[MAX_WORD_LENGTH + 1]; /* a single word + '\0' */ - MyTextItems items[MAX_CHUNX + 1]; - short lmargin, spacepos, i, s, nitems, start; - LocalMargins m; - XPoint where; - Chunk *chunk; + if(tPtr->flags.ownsSelection) { - if (!tPtr->view->flags.realized || !para) - return 0; + if(prev_y != tb->sections[s]._y + && (tb->sections[s]._y >= tPtr->sel.y) + && (tb->sections[s]._y + tb->sections[s].h + <= tPtr->sel.y + tPtr->sel.h)) { + XFillRectangle(dpy, tPtr->db, greyGC, + tPtr->visible.x, + tPtr->visible.y + tb->sections[s]._y - tPtr->vpos, + tPtr->visible.w, tb->sections[s].h); - where.x = 0, where.y = 0, nitems = 0; - m.left = WMGetRulerMargin(tPtr->ruler, WRulerDocLeft); - m.right = WMGetRulerMargin(tPtr->ruler, WRulerRight) - m.left; - m.first = para->fmargin, m.body = para->bmargin; + } else if( prev_y != tb->sections[s]._y + && (tb->sections[s]._y <= tPtr->sel.y) + && (tb->sections[s]._y + tb->sections[s].h + >= tPtr->sel.y) + && (tPtr->sel.x >= tb->sections[s].x) + && (tPtr->sel.y + tPtr->sel.h + >= tb->sections[s]._y + tb->sections[s].h)) { + XFillRectangle(dpy, tPtr->db, greyGC, + tPtr->clicked.x, + tPtr->visible.y + tb->sections[s]._y - tPtr->vpos, + tPtr->visible.w - tPtr->sel.x, tb->sections[s].h); - if (draw) { - W_Screen *screen = tPtr->view->screen; + } else if(prev_y != tb->sections[s]._y + && (tb->sections[s]._y <= tPtr->sel.y + tPtr->sel.h) + && (tb->sections[s]._y >= tPtr->sel.y)) { + XFillRectangle(dpy, tPtr->db, greyGC, + tPtr->visible.x, + tPtr->visible.y + tb->sections[s]._y - tPtr->vpos, + tPtr->sel.x + tPtr->sel.w -tPtr->visible.x, + tb->sections[s].h); - if (para->drawbuffer) - XFreePixmap(screen->display, para->drawbuffer); - if (para->width < 2 * tPtr->dFont->height) - para->width = 2 * tPtr->dFont->height; - if (para->height < tPtr->dFont->height) - para->height = tPtr->dFont->height; - para->drawbuffer = XCreatePixmap(screen->display, - tPtr->view->window, para->width, para->height, screen->depth); - XFillRectangle(screen->display, para->drawbuffer, - WMColorGC(tPtr->bg), 0, 0, para->width, para->height); + } else if( prev_y != tb->sections[s]._y + && (tb->sections[s]._y <= tPtr->sel.y) + && (tb->sections[s]._y + tb->sections[s].h + >= tPtr->sel.y + tPtr->sel.h) ) { + XFillRectangle(dpy, tPtr->db, greyGC, + tPtr->sel.x, + tPtr->visible.y + tb->sections[s]._y - tPtr->vpos, + tPtr->sel.w,tb->sections[s].h); + } + + } - } - //if(para->align != tPtr->dAlignment) - // para->align = tPtr->dAlignment; + prev_y = tb->sections[s]._y; - /* draw the bullet if appropriate */ - if (m.body > m.first && !tPtr->monoFont) { - lmargin = m.body - m.first; - if (draw) { - if (para->bulletPix) - WMDrawPixmap(para->bulletPix, para->drawbuffer, lmargin - 10, 5); - else - WMDrawPixmap(tPtr->dBulletPix, para->drawbuffer, lmargin - 10, 5); - } - /* NeXT sez next tab, I say the m.body - m.first margin */ - } else { - lmargin = WMAX(0, m.first - m.body); - } + len = tb->sections[s].end - tb->sections[s].begin; + text = &(tb->text[tb->sections[s].begin]); + y = tb->sections[s].y - tPtr->vpos; + WMDrawString(scr, tPtr->db, gc, font, + tb->sections[s].x, y, text, len); - if (tPtr->findingClickPoint && !para->chunks) { - tPtr->currentChunk = NULL; - tPtr->foundClickPoint = True; - tPtr->tpos = 0; - tPtr->clicked.x = lmargin; - tPtr->clicked.y = 5; - tPtr->clheight = para->height; - tPtr->clwidth = 0; - return 0; - } - chunk = para->chunks; - while (chunk) { - - if (tPtr->findingClickPoint && tPtr->foundClickPoint) - return 0; - - if (chunk->type == ctImage && !tPtr->monoFont) { - drawPChunkPart(tPtr, chunk, m, para, items, &nitems, - &lmargin, &where, draw); - } else if (chunk->text && chunk->type == ctText) { - if (tPtr->wrapping == wrNone) { - drawTChunkPart(tPtr, chunk, chunk->text, m, para, items, &nitems, - chunk->chars, 0, &lmargin, &where, draw, spacepos); - } else if (tPtr->wrapping == wrWord) { - spacepos = 0, i = 0, start = 0; - while (spacepos < chunk->chars) { - bufr[i] = chunk->text[spacepos]; - if (bufr[i] == ' ' || i >= MAX_WORD_LENGTH) { - if (bufr[i] == ' ') - s = 1; - else - s = 0; - drawTChunkPart(tPtr, chunk, bufr, m, para, - items, &nitems, i + s, start, &lmargin, &where, - draw, spacepos); - start = spacepos + s; - if (i > MAX_WORD_LENGTH - 1) - spacepos--; - i = 0; - } else - i++; - spacepos++; + if(tb->underlined) { + XDrawLine(dpy, tPtr->db, gc, + tb->sections[s].x, y + font->y + 1, + tb->sections[s].x + tb->sections[s].w, y + font->y + 1); + } + } - /* catch that last onery one. */ - drawTChunkPart(tPtr, chunk, bufr, m, para, - items, &nitems, i, start, &lmargin, &where, draw, spacepos); - } + + tb = (!done? tb->next : NULL); + } - chunk = chunk->next; - } - /* we might have a few leftover items that need drawing */ - if (nitems > 0) { - where.y += myDrawText(tPtr, para, items, - nitems, m.right - m.left - lmargin, where.y, draw, spacepos); - if (tPtr->findingClickPoint && tPtr->foundClickPoint) - return 0; - } - return where.y; -} + + c = WMGetBagItemCount(tPtr->gfxItems); + if(c > 0 && !tPtr->flags.monoFont) { + int j; + WMWidget *wdt; + for(j=0; jgfxItems, j); + if(!tb || !tb->sections) + continue; + wdt = tb->d.widget; + if(tb->sections[0]._y + tb->sections[0].h + <= tPtr->vpos + || tb->sections[0]._y + >= tPtr->vpos + tPtr->visible.h ) { + + if((W_VIEW(wdt))->flags.mapped) { + WMUnmapWidget(wdt); + } + } else { + if(!(W_VIEW(wdt))->flags.mapped) { + WMMapWidget(wdt); + XLowerWindow(dpy, + (W_VIEW(wdt))->window); + } + + if(tPtr->flags.ownsSelection && 0 + //&& (tb->sections[s]._y >= tPtr->sel.y) + //&& (tb->sections[s]._y + tb->sections[s].h + ){ // <= tPtr->sel.y + tPtr->sel.h)) { + XFillRectangle(dpy, tPtr->db, greyGC, + tb->sections[0].x, tb->sections[0].y - tPtr->vpos, + tb->sections[0].w, tb->sections[0].h); + } -static int calcParaExtents(Text * tPtr, Paragraph * para) -{ - if (!para) - return 0; + WMMoveWidget(wdt, 3 + tb->sections[0].x + tPtr->visible.x, + tb->sections[0].y - tPtr->vpos); - if (tPtr->monoFont) { - para->width = tPtr->visibleW; - para->fmargin = 0; - para->bmargin = 0; - para->rmargin = tPtr->visibleW; - } else { - para->width = WMGetRulerMargin(tPtr->ruler, WRulerRight) - - WMIN(para->fmargin, para->bmargin) - - WMGetRulerOffset(tPtr->ruler); - } + if(tb->underlined) { + XDrawLine(dpy, tPtr->db, WMColorGC(tb->color), + tb->sections[0].x, + tb->sections[0].y + WMWidgetHeight(wdt) + 1, + tb->sections[0].x + tb->sections[0].w, + tb->sections[0].y + WMWidgetHeight(wdt) + 1); + } } } } + - if (!para->chunks) - para->height = tPtr->dFont->height; - else - para->height = putParagraphOnPixmap(tPtr, para, False); - - if (para->height < tPtr->dFont->height) - para->height = tPtr->dFont->height; - para->bottom = para->top + para->height; - return para->height; -} +_copy_area: -/* rather than bother with redrawing _all_ the pixmaps, simply - rearrange (i.e., push down or pull up) paragraphs after this one */ -static void affectNextParas(Text * tPtr, Paragraph * para, int move_y) -{ - Paragraph *next; - int old_y = 0; - if (!para || move_y == 0) - return; - if (move_y == -23) { - old_y = para->bottom; - calcParaExtents(tPtr, para); - old_y -= para->bottom; - if (old_y == 0) - return; - move_y = -old_y; - } - if (move_y == 0) - return; + XCopyArea(dpy, tPtr->db, win, tPtr->bgGC, + 0, 0, + tPtr->visible.w, tPtr->visible.h, + tPtr->visible.x, tPtr->visible.y); - next = para->next; - while (next) { - next->top += move_y; - next->bottom = next->top + next->height; - next = next->next; // I know, I know + W_DrawRelief(scr, win, 0, 0, + tPtr->view->size.width, tPtr->view->size.height, + tPtr->flags.relief); - } - tPtr->docHeight += move_y; + if(tPtr->ruler && tPtr->flags.rulerShown) + XDrawLine(dpy, win, + tPtr->fgGC, 2, 42, + tPtr->view->size.width-4, 42); -#if 0 - tPtr->vpos += move_y; - if (tPtr->vpos < 0) - tPtr->vpos = 0; - if (tPtr->vpos > tPtr->docHeight - tPtr->visibleH) - tPtr->vpos = tPtr->docHeight - tPtr->visibleH; -#endif +/* + XFillRectangle(tPtr->view->screen->display, tPtr->view->window, + tPtr->bgGC, + 2, tPtr->view->size.height-3, + tPtr->view->size.width-4, 3); +*/ } -static void calcDocExtents(Text * tPtr) +static void +cursorToTextPosition(Text *tPtr, int x, int y) { - Paragraph *para; + TextBlock *tb = NULL; + int done=False, s, len, _w, _y, dir=1; /* 1 == "down" */ + WMFont *font; + char *text; - if (tPtr->monoFont) { - tPtr->docWidth = tPtr->visibleW; - } else { - tPtr->docWidth = WMGetRulerMargins(tPtr->ruler, WRulerRight) - - WMGetRulerMargins(tPtr->ruler, WRulerDocLeft); - } - tPtr->docHeight = 0; - para = tPtr->paragraphs; - if (para) { - while (para) { - para->top = tPtr->docHeight; - tPtr->docHeight += calcParaExtents(tPtr, para); - para->bottom = tPtr->docHeight; - para = para->next; + + y += tPtr->vpos - tPtr->visible.y; + if(y<0) y = 0; + + x -= tPtr->visible.x-2; + if(x<0) x=0; + + tPtr->clicked.x = x; + tPtr->clicked.y = y; + + /* first, which direction?, most likely, newly clicked + position will be close to previous */ + tb = tPtr->currentTextBlock; + if(!tb) + tb = tPtr->firstTextBlock; + if(!tb || !tb->sections) + return; + + if(y < tb->sections[0].y) + dir = 0; /* "up" */ + +//tb = tPtr->firstTextBlock; +//dir = 1; + + + if(y == tb->sections[0].y) + goto _doneV; /* yeah yeah, goto, whatever... :-P */ + + /* get the first section of the first TextBlock based on v. position */ + done = False; + while(!done && tb) { + if(tPtr->flags.monoFont && tb->graphic) { + tb = tb->next; + continue; + } + +printf("tb %p t[%c] blank%d graphic %d\n", tb, +*tb->text, tb->blank, tb->graphic); + if(!tb->sections) { + printf("we have a bad thing!\n"); + exit(1); + } + s = (dir? 0 : tb->nsections-1); + while( (dir? (snsections) : (s>=0) )) { + if( y >= tb->sections[s]._y + && y <= tb->sections[s]._y + tb->sections[s].h) { + done = True; + break; + } else + dir? s++ : s--; + } + if(!done) tb = (dir ? tb->next : tb->prior); } - } else { /* default to this if no paragraphs */ - tPtr->docHeight = tPtr->dFont->height; - } -#if 0 - if (tPtr->editable) /* add space at bottom to enter new stuff */ - tPtr->docHeight += tPtr->dFont->height; -#endif -} +_doneV: + /* we have the line, which TextBlock on that line is it? */ + if(tb) + _y = tb->sections[s]._y; -/* If any part of a paragraph is viewable, the entire - paragraph is drawn on an otherwise empty (XFreePixmap) pixmap. - The actual viewable parts of the paragraph(s) are then pieced - together via paintText: - - ------------------------------------------- - || this is a paragraph in this document|| - ||========================================|| - || | only part of it is visible though. || - || |-------------------------------------|| - ||[.| This is another paragraph || - || | which I'll make relatively long || - || | just for the sake of writing a long || - || | paragraph with a picture: ^_^ || - || |-------------------------------------|| - ||==| Of the three paragraphs, only || - ||/\| the preceding was totally copied to || - ||\/| totally copied to the window, even || - ==========================================|| - though they are all on pixmaps. - ------------------------------------------- - This paragraph exists only in - memory and so has a NULL pixmap. - ------------------------------------------- - - - simple, right? Performance: the best of both worlds... - o fast scrolling: no need to rewrite what's already - on the screen, simply XCopy it. - o fast typing: only change current para, then simply - affect other (i.e., subsequent) paragraphs. - o If no part of para is on screen, gdbFree pixmap; else draw on - individual pixmap per para then piece several paras together - o Keep track of who to XCopy to window (see paintText) */ -static void drawDocumentPartsOnPixmap(Text * tPtr, Bool all) -{ - Paragraph *para; - - para = tPtr->paragraphs; - while (para) { - /* the 32 reduces jitter on the human eye by preparing paragraphs - in anticipation of when the _moving_ scrollbar reaches them */ - if (para->bottom + 32 < tPtr->vpos || - para->top > tPtr->visibleH + tPtr->vpos + 32) { - if (para->drawbuffer) { - XFreePixmap(tPtr->view->screen->display, para->drawbuffer); - para->drawbuffer = (Pixmap) NULL; - } - } else { - if (!para->drawbuffer || all) - putParagraphOnPixmap(tPtr, para, True); - } - para = para->next; - } -} - - - -/* this function blindly copies the "visible" parts of a pragraph - unto the view, (top-down approach). It starts drawing from - the top of the view (which paragraph to draw is determined by - drawDocumentPartsOnPixmap); it stops at the bottom of the view. */ -static void paintText(Text * tPtr) -{ - short lmargin, para_lmargin; - int from = 5, to = 5, height; - Paragraph *para; - short vS = 0, hS = 0, rh = 0; - - if (!tPtr->view->flags.realized) - return; - - if (tPtr->rulerShown) - rh = 40; - to += rh; - - if (tPtr->hasVscroller) - vS = 21; - if (tPtr->hasHscroller) - hS = 21; - - //XClearWindow(tPtr->view->screen->display, tPtr->view->window); - - lmargin = WMGetRulerMargin(tPtr->ruler, WRulerDocLeft); - if (tPtr->paragraphs) { - para = tPtr->paragraphs; - while (para) { - if (para->drawbuffer) { - from = (para->top <= tPtr->vpos) ? tPtr->vpos - para->top : 0; - height = para->height - from; - if (from >= 0 && height > 0) { - para_lmargin = WMIN(para->fmargin, para->bmargin); - if (lmargin - vS < WMIN(para->fmargin, para->bmargin)) { -#if 0 - XClearArea(tPtr->view->screen->display, tPtr->view->window, - lmargin, to, 2 + para_lmargin, height, False); -#else - XFillRectangle(tPtr->view->screen->display, tPtr->view->window, - WMColorGC(tPtr->dColor), lmargin, to, 2 + para_lmargin, height); -#endif - } - XCopyArea(tPtr->view->screen->display, para->drawbuffer, - tPtr->view->window, WMColorGC(tPtr->bg), 0, from, - para->width - 4, height, lmargin + para_lmargin + 2, to); - if ((to += height) > tPtr->visibleH + rh) + while(tb) { + if(!tb->sections) break; + if(_y != tb->sections[s]._y) + break; + + if(tb->graphic) { + _w = WMWidgetWidth(tb->d.widget); + } else { + text = &(tb->text[tb->sections[s].begin]); + len = tb->sections[s].end - tb->sections[s].begin; + font = tb->d.font; + _w = myWidthOfString(font, text, len); } - } - para = para->next; + if(tb->sections[s].x + _w >= x) + break; + s = 0; + tb = tb->next; } - } + + /* we have said TextBlock, now where within it? */ + if(tb && !tb->graphic) { + int begin = tb->sections[s].begin; + int end = tb->sections[s].end; + int i=0; + len = end-begin; + text = &(tb->text[begin]); + font = tb->d.font; + + _w = x - tb->sections[s].x; + + i = 0; + while(itpos = (iused)?i:tb->used; + } + +// if(!tb) + //tb = tPtr->firstTextBlock; + tPtr->currentTextBlock = tb; + + if(tb &&tb->graphic) printf("graphic\n"); +} + +static void +updateScrollers(Text *tPtr) +{ + + if(tPtr->vS) { + if(tPtr->docHeight < tPtr->visible.h) { + WMSetScrollerParameters(tPtr->vS, 0, 1); + tPtr->vpos = 0; + } else { + float vmax = (float)(tPtr->docHeight); + WMSetScrollerParameters(tPtr->vS, + ((float)tPtr->vpos)/(vmax - (float)tPtr->visible.h), + (float)tPtr->visible.h/vmax); + } + } else tPtr->vpos = 0; + + if(tPtr->hS) + ; +} + +static void +scrollersCallBack(WMWidget *w, void *self) +{ + Text *tPtr = (Text *)self; + Bool scroll = False; + Bool dimple = False; + int which; + + if(!tPtr->view->flags.realized) return; + + if(w == tPtr->vS) { + float vmax; + int height; + vmax = (float)(tPtr->docHeight); + height = tPtr->visible.h; + + which = WMGetScrollerHitPart(tPtr->vS); + switch(which) { + case WSDecrementLine: + if(tPtr->vpos > 0) { + if(tPtr->vpos>16) tPtr->vpos-=16; + else tPtr->vpos=0; + scroll=True; + }break; + case WSIncrementLine: { + int limit = tPtr->docHeight - height; + if(tPtr->vpos < limit) { + if(tPtr->vposvpos+=16; + else tPtr->vpos=limit; + scroll = True; + }}break; + case WSDecrementPage: + tPtr->vpos -= height; + + if(tPtr->vpos < 0) + tPtr->vpos = 0; + dimple = True; + scroll = True; + printf("dimple needs to jump to mouse location ;-/\n"); + break; + case WSIncrementPage: + tPtr->vpos += height; + if(tPtr->vpos > (tPtr->docHeight - height)) + tPtr->vpos = tPtr->docHeight - height; + dimple = True; + scroll = True; + printf("dimple needs to jump to mouse location ;-/\n"); + break; + + + case WSKnob: + tPtr->vpos = WMGetScrollerValue(tPtr->vS) + * (float)(tPtr->docHeight - height); + scroll = True; + break; + + case WSKnobSlot: + case WSNoPart: +printf("WSNoPart, WSKnobSlot\n"); #if 0 - /* clear any left over space (esp. during para deletes/ ruler changes) */ - if (tPtr->docHeight < tPtr->visibleH && tPtr->visibleH + rh + 5 - to > 0) { - XClearArea(tPtr->view->screen->display, tPtr->view->window, vS, to, - tPtr->view->size.width - vS, tPtr->visibleH + rh + hS + 5 - to, False); - } - if (lmargin > vS) - XClearArea(tPtr->view->screen->display, tPtr->view->window, - vS + 1, rh + 5, lmargin - vS, tPtr->visibleH + rh + 5 - vS, False); - - - // from the "selection" days... - W_DrawRelief(tPtr->view->screen, WMWidgetXID(tPtr), - tPtr->sRect.pos.x, tPtr->sRect.pos.y, - tPtr->sRect.size.width, tPtr->sRect.size.height, tPtr->relief); +float vmax = (float)(tPtr->docHeight); +((float)tPtr->vpos)/(vmax - (float)tPtr->visible.h), +(float)tPtr->visible.h/vmax; +dimple =where mouse is. #endif - - W_DrawRelief(tPtr->view->screen, WMWidgetXID(tPtr), 0, rh, - tPtr->visibleW + vS, tPtr->visibleH + hS, tPtr->relief); - - if (tPtr->editable && tPtr->clheight > 0) { - int top = tPtr->cursor.y - tPtr->vpos; - int bot = top + tPtr->clheight; - - if (bot > 5) { - if (top < 5) - top = 5; - if (bot > tPtr->visibleH + hS - 2) - bot = tPtr->visibleH + hS - 2; - if (bot - top > 1) { - //do something about italic text... - XDrawLine(tPtr->view->screen->display, tPtr->view->window, - WMColorGC(tPtr->dColor), lmargin + tPtr->cursor.x, top, - lmargin + tPtr->cursor.x, bot); - } + break; + } + scroll = (tPtr->vpos != tPtr->prevVpos); + tPtr->prevVpos = tPtr->vpos; + } + + if(w == tPtr->hS) + ; + + if(scroll) { +/* + if(0&&dimple) { + if(tPtr->rulerShown) + XClearArea(tPtr->view->screen->display, tPtr->view->window, 22, 47, + tPtr->view->size.width-24, tPtr->view->size.height-49, True); + else + XClearArea(tPtr->view->screen->display, tPtr->view->window, 22, 2, + tPtr->view->size.width-24, tPtr->view->size.height-4, True); + } +*/ + if(which == WSDecrementLine || which == WSIncrementLine) + updateScrollers(tPtr); + paintText(tPtr); } - } } -/* called anytime either the ruler, vscroller or hscroller is hidden/shown, - or when the widget is resized by some user action */ -static void resizeText(W_ViewDelegate * self, WMView * view) + +typedef struct { + TextBlock *tb; + unsigned short begin, end; /* what part of the text block */ + +} myLineItems; + + +static int +layOutLine(Text *tPtr, myLineItems *items, int nitems, int x, int y, +int pwidth, WMAlignment align) +{ + int i, j=0; /* j = justification */ + int line_width = 0, line_height=0, max_descent=0; + WMFont *font; + char *text; + int len; + TextBlock *tb; + Bool gfx=0; + TextBlock *tbsame=NULL; + + for(i=0; igraphic) { + if(!tPtr->flags.monoFont) { + WMWidget *wdt = tb->d.widget; + line_height = WMAX(line_height, WMWidgetHeight(wdt)); + if(align != WALeft) + line_width += WMWidgetWidth(wdt); + gfx = True; + } + + } else { + font = (tPtr->flags.monoFont)?tPtr->dFont : tb->d.font; + max_descent = WMAX(max_descent, font->height-font->y); + line_height = WMAX(line_height, font->height); //+font->height-font->y); + text = &(tb->text[items[i].begin]); + len = items[i].end - items[i].begin; + if(align != WALeft) + line_width += myWidthOfString(font, text, len); + } + } + + if(align == WARight) { + j = pwidth - line_width; + } else if (align == WACenter) { + j = (int) ((float)(pwidth - line_width))/2.0; + } + if(gfx) + y+=10; + + for(i=0; isections[tb->nsections-1].end = items[i].end; + } else { + tb->sections = wrealloc(tb->sections, + (++tb->nsections)*sizeof(Section)); + tb->sections[tb->nsections-1]._y = y; + tb->sections[tb->nsections-1].x = x+j; + tb->sections[tb->nsections-1].h = line_height; + tb->sections[tb->nsections-1].begin = items[i].begin; + tb->sections[tb->nsections-1].end = items[i].end; + } + + + if(tb->graphic) { + if(!tPtr->flags.monoFont) { + WMWidget *wdt = tb->d.widget; + tb->sections[tb->nsections-1].y = 1 +max_descent + + y + line_height - WMWidgetHeight(wdt); + tb->sections[tb->nsections-1].w = WMWidgetWidth(wdt); + x += tb->sections[tb->nsections-1].w; + } + } else { + font = (tPtr->flags.monoFont)? tPtr->dFont : tb->d.font; + len = items[i].end - items[i].begin; + + text = &(tb->text[items[i].begin]); + + tb->sections[tb->nsections-1].y = y+line_height-font->y; + tb->sections[tb->nsections-1].w = + myWidthOfString(font, + &(tb->text[tb->sections[tb->nsections-1].begin]), + tb->sections[tb->nsections-1].end - + tb->sections[tb->nsections-1].begin); + + x += myWidthOfString(font, text, len); + } + + tbsame = tb; + } + + return line_height+(gfx?10:0); + +} + + +static void +output(char *ptr, int len) +{ + char s[len+1]; + memcpy(s, ptr, len); + s[len] = 0; + printf(" s is [%s] (%d)\n", s, strlen(s)); +} + + + +#define MAX_TB_PER_LINE 64 + +static void +layOutDocument(Text *tPtr) { - Text *tPtr = (Text *) view->self; - short rh = 0; + TextBlock *tb; + myLineItems items[MAX_TB_PER_LINE]; + WMAlignment align = WALeft; + WMFont *font; + Bool lhc = !tPtr->flags.laidOut; /* line height changed? */ + int prev_y; - if (!tPtr->monoFont && tPtr->rulerShown) - rh = 40; + int nitems=0, x=0, y=0, line_width = 0, width=0; + int pwidth = tPtr->visible.w - tPtr->visible.x; + + char *start=NULL, *mark=NULL; + int begin, end; - W_ResizeView(view, view->size.width, view->size.height); - WMResizeWidget(tPtr->ruler, view->size.width, 40); + if(!(tb = tPtr->firstTextBlock)) { + printf("clear view... *pos=0\n"); + return; + } + + if(0&&tPtr->flags.laidOut) { + tb = tPtr->currentTextBlock; + if(tb->sections && tb->nsections>0) + prev_y = tb->sections[tb->nsections-1]._y; +y+=10; +printf("1 prev_y %d \n", prev_y); + + /* search backwards for textblocks on same line */ + while(tb) { + if(!tb->sections || tb->nsections<1) { + tb = tPtr->firstTextBlock; + break; + } + if(tb->sections[tb->nsections-1]._y != prev_y) { + tb = tb->next; + break; + } + // prev_y = tb->sections[tb->nsections-1]._y; + tb = tb->prior; + } + y = 0;//tb->sections[tb->nsections-1]._y; +printf("2 prev_y %d \n\n", tb->sections[tb->nsections-1]._y); + } - if (tPtr->hasVscroller) { - WMMoveWidget(tPtr->vscroller, 1, 1 + rh); - WMResizeWidget(tPtr->vscroller, 20, view->size.height - rh - 2); - tPtr->visibleW = view->size.width - 21; + while(tb) { - if (tPtr->hasHscroller) { - WMMoveWidget(tPtr->hscroller, 20, view->size.height - 21); - WMResizeWidget(tPtr->hscroller, view->size.width - 21, 20); - tPtr->visibleH = view->size.height - 21 - rh; - } else - tPtr->visibleH = view->size.height - rh; - } else { - tPtr->visibleW = view->size.width; - if (tPtr->hasHscroller) { - WMMoveWidget(tPtr->hscroller, 1, view->size.height - 21); - WMResizeWidget(tPtr->hscroller, view->size.width - 2, 20); - tPtr->visibleH = view->size.height - 21 - rh; - } else - tPtr->visibleH = view->size.width - 2 - rh; - } - WMRefreshText(tPtr, tPtr->vpos, tPtr->hpos); + if(tb->sections && tb->nsections>0) { + wfree(tb->sections); + tb->sections = NULL; + tb->nsections = 0; + } + + if(tb->first) { + y += layOutLine(tPtr, items, nitems, x, y, pwidth, align); + x = 0;//tPtr->visible.x+2; + nitems = 0; + line_width = 0; + } + + if(tb->graphic) { + if(!tPtr->flags.monoFont) { + width = WMWidgetWidth(tb->d.widget); + if(width > pwidth)printf("rescale graphix to fit?\n"); + line_width += width; + if(line_width >= pwidth - x + || nitems >= MAX_TB_PER_LINE) { + y += layOutLine(tPtr, items, nitems, x, y, + pwidth, align); + nitems = 0; + x = 0;//tPtr->visible.x+2; + line_width = width; + } + + items[nitems].tb = tb; + items[nitems].begin = 0; + items[nitems].end = 0; + nitems++; + } + + } else if((start = tb->text)) { + begin = end = 0; + font = tPtr->flags.monoFont?tPtr->dFont:tb->d.font; + + while(start) { + mark = strchr(start, ' '); + if(mark) { + end += (int)(mark-start)+1; + start = mark+1; + } else { + end += strlen(start); + start = mark; + } + + if(end-begin > 0) { + + width = myWidthOfString(font, + &tb->text[begin], end-begin); + + if(width > pwidth) { /* break this tb up */ + char *t = &tb->text[begin]; + int l=end-begin, i=0; + do { + width = myWidthOfString(font, t, ++i); + } while (width < pwidth && i < l); + end = begin+i; + if(start) // and since (nil)-4 = 0xfffffffd + start -= l-i; + + } + + line_width += width; + } + + if((line_width >= pwidth - x) + || nitems >= MAX_TB_PER_LINE) { + y += layOutLine(tPtr, items, nitems, x, y, + pwidth, align); + line_width = width; + x = 0; //tPtr->visible.x+2; + nitems = 0; + } + + items[nitems].tb = tb; + items[nitems].begin = begin; + items[nitems].end = end; + nitems++; + + begin = end; + } + } + tb = tb->next; + } + + + if(nitems > 0) + y += layOutLine(tPtr, items, nitems, x, y, pwidth, align); + if(lhc) { + tPtr->docHeight = y+10; + updateScrollers(tPtr); + } + tPtr->flags.laidOut = True; + +} + + +static void +textDidResize(W_ViewDelegate *self, WMView *view) +{ + Text *tPtr = (Text *)view->self; + unsigned short w = WMWidgetWidth(tPtr); + unsigned short h = WMWidgetHeight(tPtr); + unsigned short rh = 0, vw = 0; + + if(tPtr->ruler && tPtr->flags.rulerShown) { + WMMoveWidget(tPtr->ruler, 20, 2); + WMResizeWidget(tPtr->ruler, w - 22, 40); + rh = 40; + } + + if(tPtr->vS) { + WMMoveWidget(tPtr->vS, 1, rh + 2); + WMResizeWidget(tPtr->vS, 20, h - rh - 3); + vw = 20; + WMSetRulerOffset(tPtr->ruler, 22); + } else WMSetRulerOffset(tPtr->ruler, 2); + + if(tPtr->hS) { + if(tPtr->vS) { + WMMoveWidget(tPtr->hS, vw, h - 21); + WMResizeWidget(tPtr->hS, w - vw - 1, 20); + } else { + WMMoveWidget(tPtr->hS, vw+1, h - 21); + WMResizeWidget(tPtr->hS, w - vw - 2, 20); + } + } + + tPtr->visible.x = (tPtr->vS)?22:0; + tPtr->visible.y = (tPtr->ruler && tPtr->flags.rulerShown)?43:3; + tPtr->visible.w = tPtr->view->size.width - tPtr->visible.x - 12; + tPtr->visible.h = tPtr->view->size.height - tPtr->visible.y; + tPtr->visible.h -= (tPtr->hS)?20:0; + + tPtr->margins[0].left = tPtr->margins[0].right = tPtr->visible.x; + tPtr->margins[0].body = tPtr->visible.x; + tPtr->margins[0].right = tPtr->visible.w; + + WMRefreshText(tPtr, tPtr->vpos, tPtr->hpos); + + if(tPtr->db) { + //if(tPtr->view->flags.realized) + //XFreePixmap(tPtr->view->screen->display, tPtr->db); + } + + //if(size did not change + if(tPtr->visible.w < 10) tPtr->visible.w = 10; + if(tPtr->visible.h < 10) tPtr->visible.h = 10; + + tPtr->db = XCreatePixmap(tPtr->view->screen->display, + tPtr->view->window, tPtr->visible.w, + tPtr->visible.h, tPtr->view->screen->depth); + + paintText(tPtr); } W_ViewDelegate _TextViewDelegate = { - NULL, - NULL, - resizeText, - NULL, + NULL, + NULL, + textDidResize, + NULL, }; - - -/* a plain text parser */ -/* this gives useful hints on how to make a more - interesting parser for say HTML, RTF */ -static void defaultParser(Text * tPtr, void *data, short type) +/* nice, divisble-by-16 memory */ +static inline unsigned short +reqBlockSize(unsigned short requested) { - char *start, *mark, *text = (char *) data; - Chunk *chunk = NULL; - Paragraph *para = NULL; - - start = text; - while (start) { - mark = strchr(start, '\n'); - if (mark) { - /* there is a newline, indicating the need for a new paragraph */ - /* attach the chunk to the current paragraph */ - if ((short) (mark - start) > 1) { - /* ignore chunks with just a single newline but still make a - blank paragraph */ - chunk = (tPtr->funcs.createTChunk) (start, (short) (mark - start), - tPtr->dFont, tPtr->dColor, 0, False); - (tPtr->funcs.insertChunk) (tPtr, chunk, type); - } - /* _then_ create a new paragraph for the _next_ chunk */ - para = (tPtr->funcs.createParagraph) (0, 0, tPtr->visibleW, - NULL, 0, WALeft); - (tPtr->funcs.insertParagraph) (tPtr, para, type); - start = mark + 1; - } else { - /* just attach the chunk to the current paragraph */ - if (strlen(start) > 0) { - chunk = (tPtr->funcs.createTChunk) (start, strlen(start), - tPtr->dFont, tPtr->dColor, 0, False); - (tPtr->funcs.insertChunk) (tPtr, chunk, type); - } - start = mark; - } - } - + return requested+16-(requested%16); } -static void updateScrollers(Text * tPtr) +static void +deleteTextInteractively(Text *tPtr, KeySym ksym) { - if (tPtr->hasVscroller) { - if (tPtr->docHeight < tPtr->visibleH) { - WMSetScrollerParameters(tPtr->vscroller, 0, 1); - tPtr->vpos = 0; - } else { - float vmax = (float) (tPtr->docHeight); - - WMSetScrollerParameters(tPtr->vscroller, - ((float) tPtr->vpos) / (vmax - (float) tPtr->visibleH), - (float) tPtr->visibleH / vmax); - } - } - if (tPtr->hasHscroller); + printf("deleting %ld\n", ksym); } - -static void scrollersCallBack(WMWidget * w, void *self) + +static void +insertTextInteractively(Text *tPtr, char *text, int len) { - Text *tPtr = (Text *) self; - Bool scroll = False; - Bool dimple = False; + TextBlock *tb; - if (!tPtr->view->flags.realized) - return; +// Chunk *tb=NULL, *newtb=NULL; + int height = -23; /* should only be changed upon newline */ + int w=0; + WMFont *font; + char *mark = NULL; + + if(!tPtr->flags.editable || len < 1 || !text + || (*text == '\n' && tPtr->flags.ignoreNewLine)) + return; - if (w == tPtr->vscroller) { - float vmax; - int height; + tb = tPtr->currentTextBlock; + if(!tb) { + WMAppendTextStream(tPtr, text); + WMRefreshText(tPtr, 0, 0); + return; + } - vmax = (float) (tPtr->docHeight); - height = tPtr->visibleH; - if (height > 7) - height -= 7; /* the top border (5) + bottom (2) */ - - switch (WMGetScrollerHitPart(tPtr->vscroller)) { - case WSDecrementLine: - if (tPtr->vpos > 0) { - if (tPtr->vpos > 16) - tPtr->vpos -= 16; - else - tPtr->vpos = 0; - scroll = True; - } - break; - case WSIncrementLine:{ - int limit = tPtr->docHeight - height; - - if (tPtr->vpos < limit) { - if (tPtr->vpos < limit - 16) - tPtr->vpos += 16; - else - tPtr->vpos = limit; - scroll = True; - } - } - break; - case WSDecrementPage: - tPtr->vpos -= height; - - if (tPtr->vpos < 0) - tPtr->vpos = 0; - dimple = True; - scroll = True; - printf("dimple needs to jump to mouse location ;-/\n"); - break; - case WSIncrementPage: - tPtr->vpos += height; - if (tPtr->vpos > (tPtr->docHeight - height)) - tPtr->vpos = tPtr->docHeight - height; - dimple = True; - scroll = True; - printf("dimple needs to jump to mouse location ;-/\n"); - break; - - - case WSKnob: - tPtr->vpos = WMGetScrollerValue(tPtr->vscroller) - * (float) (tPtr->docHeight - height); - scroll = True; - break; + if(tb->graphic) + return; + if(len > 1) { + mark = strchr(text, '\n'); + if(mark) { + len = (int)(mark-text); + mark++; + } + if(len<1 && mark) { + printf("problem pasting text %d\n", len); + len = strlen(text); + mark = NULL; + } + } + + font = (tPtr->flags.monoFont || !tb)?tPtr->dFont:tb->d.font; + #if 0 - case WSKnobSlot: - case WSNoPart: - float vmax = (float) (tPtr->docHeight); - - ((float) tPtr->vpos) / (vmax - (float) tPtr->visibleH), - (float) tPtr->visibleH / vmax); - dimple = where mouse is. -#endif - break; - } - scroll = (tPtr->vpos != tPtr->prevVpos); - tPtr->prevVpos = tPtr->vpos; - } - if (w == tPtr->hscroller); - -//need scrollv || scrollh - if (scroll) { - /* - if(0&&dimple) { - if(tPtr->rulerShown) - XClearArea(tPtr->view->screen->display, tPtr->view->window, 22, 47, - tPtr->view->size.width-24, tPtr->view->size.height-49, True); - else - XClearArea(tPtr->view->screen->display, tPtr->view->window, 22, 2, - tPtr->view->size.width-24, tPtr->view->size.height-4, True); - } - */ - updateScrollers(tPtr); - drawDocumentPartsOnPixmap(tPtr, False); - paintText(tPtr); - } -} - - -void - W_InsertText(WMText * tPtr, void *data, Bool prepend) { - if (!tPtr) - return; - if (!data) { - Paragraph *para = tPtr->paragraphs, *ptmp; - Chunk *chunk, *ctmp; - WMFreezeText(tPtr); - while (para) { - chunk = para->chunks; - while (chunk) { - if (chunk->type == ctText && chunk->text) - wgdbFree(chunk->text); - else if (chunk->pixmap) - WMReleasePixmap(chunk->pixmap); - ctmp = chunk; - chunk = chunk->next; - wgdbFree(ctmp); - } ptmp = para; - - para = para->next; - if (ptmp->drawbuffer) - XFreePixmap(tPtr->view->screen->display, ptmp->drawbuffer); - wgdbFree(ptmp); - } - tPtr->paragraphs = NULL; - tPtr->currentPara = NULL; - tPtr->currentChunk = NULL; - WMThawText(tPtr); - WMRefreshText(tPtr, 0, 0); - return; - } - if (tPtr->parser) - (tPtr->parser) (tPtr, data, prepend); - else - defaultParser(tPtr, data, prepend); -} - -static void - cursorToTextPosition(Text * tPtr, int x, int y) { - Paragraph *para = NULL; - Chunk *chunk = NULL; - WMFont *font; - short line_width = 0; - short orig_x, orig_y; - - if (x < (tPtr->hasVscroller ? 21 : 1)) { - y -= tPtr->clheight; - x = tPtr->view->size.width; //tPtr->visibleW; - - } else if (x > tPtr->clwidth && x < tPtr->clicked.x) { - //x = (tPtr->hasVscroller)?21:1; - //y += tPtr->clheight; - } - if (x < 0) - x = 0; - orig_x = x; - - if (y < 0 || y > tPtr->view->size.height - 3) - return; - orig_y = y; - tPtr->clicked.x = orig_x; - tPtr->clicked.y = y; - tPtr->clicked.y += tPtr->vpos; - tPtr->clicked.y -= tPtr->rulerShown ? 40 : 0; - para = tPtr->paragraphs; - if (!para) - return; - while (para->next) { - if (tPtr->clicked.y >= para->top - 4 && - tPtr->clicked.y < para->bottom + 4) - break; - para = para->next; - } - if (!(tPtr->currentPara = para)) - return; - - tPtr->clicked.y -= para->top; - if (tPtr->clicked.y < 0) - tPtr->clicked.y = 0; - if (tPtr->hasVscroller) - x -= 21; - if (x < 0) - x = 0; - - tPtr->findingClickPoint = True; - tPtr->foundClickPoint = False; - /* also affects tPtr->currentChunk, tPtr->clicked.x and y, - tPtr->clheight and ->width */ - putParagraphOnPixmap(tPtr, para, False); - tPtr->findingClickPoint = False; - tPtr->clicked.y += para->top; - - if (tPtr->currentChunk) { - short _width = 0, start = tPtr->tpos, done = False, w = 0; - - chunk = tPtr->currentChunk; - while (!done && chunk && line_width < tPtr->clwidth) { - if (chunk->type == ctText) { - font = (tPtr->monoFont) ? tPtr->dFont : chunk->font; - for (w = start; w < chunk->chars; w++) { - _width = WMWidthOfString(font, &chunk->text[w], 1); - line_width += _width; - if (line_width + tPtr->clicked.x >= x) { - line_width -= _width; - done = True; - printf("break\n"); - break; - } - } - - if (0 && chunk->next) { - if (chunk->next->type == ctImage) { - if (x + 10 < line_width + chunk->next->pixmap->width) { - printf("true\n"); - done = True; - } - } - } - } else { - _width = chunk->pixmap->width; - line_width += _width; - if (line_width + tPtr->clicked.x >= x) { - line_width -= _width; - tPtr->tpos = 0; - done = True; - } - } - - if (!done) { - chunk = chunk->next; - start = w = 0; - } else { - tPtr->tpos = w; - tPtr->currentChunk = chunk; - break; - } - } - } else { - short vS = (tPtr->hasVscroller) ? 32 : 12; - - if (para->align == WARight) { - tPtr->clicked.x = tPtr->view->size.width - vS; - } else if (para->align == WACenter) { - tPtr->clicked.x = -(vS / 2) + (tPtr->view->size.width - vS) / 2; - } else { - tPtr->clicked.x = 2; - } - } - - tPtr->cursor.x = tPtr->clicked.x + 2 + line_width; - tPtr->cursor.y = tPtr->clicked.y; - tPtr->clicked.y = orig_y; - tPtr->clicked.x = orig_x; - putParagraphOnPixmap(tPtr, para, True); - paintText(tPtr); -} - -static void - deleteTextInteractively(Text * tPtr, DeleteType type) { - Paragraph *para; - Chunk *chunk; - short pos, w = 0, h = 0, doprev = False, doprevpara = False; - WMFont *font; - int current = WMGetTextCurrentChunk(tPtr); - - if (!(para = tPtr->currentPara)) - return; - if (!(chunk = tPtr->currentChunk)) - return; - font = (tPtr->monoFont) ? tPtr->dFont : chunk->font; - doprev = (tPtr->tpos < 2); - - switch (type) { - case dtDelete: /* delete _after_ cursor ... implement later */ - case dtBackSpace: /* delete _before_ cursor */ - if (chunk->chars > 1) { - pos = tPtr->tpos - 1; - printf("here %d\n", pos); - if (pos > 0) { - w = WMWidthOfString(font, &chunk->text[pos], 1); - memmove(&(chunk->text[pos]), - &(chunk->text[pos + 1]), chunk->chars - pos + 1); - tPtr->tpos--; - chunk->chars--; - } - } else { - WMRemoveTextChunk(tPtr, current); - doprev = True; - } - - if (doprev) { - if (current > 0) { - WMSetTextCurrentChunk(tPtr, current - 1); - if (!tPtr->currentChunk) { - printf("PREV PARA\n"); - } else { - tPtr->tpos = tPtr->currentChunk->chars; - } - } else if (0) { - int currentp = WMGetTextCurrentParagraph(tPtr); - - doprevpara = True; - if (currentp > 1) { - para->chunks = NULL; - WMRemoveTextParagraph(tPtr, currentp); - WMSetTextCurrentParagraph(tPtr, currentp - 1); - WMSetTextCurrentChunk(tPtr, -1); - para = tPtr->currentPara; - if (para) { - if (!tPtr->currentChunk || !para->chunks) { - para->chunks = chunk; - tPtr->currentChunk = chunk; - } else - tPtr->currentChunk->next = chunk; - } - } - } - } - } - - if (1) { //if(1||(para && !doprevpara)) { - - affectNextParas(tPtr, para, -23); - putParagraphOnPixmap(tPtr, para, True); - drawDocumentPartsOnPixmap(tPtr, False); - updateScrollers(tPtr); - paintText(tPtr); - //cursorToTextPosition(tPtr, tPtr->clicked.x-w, tPtr->clicked.y); - } else - WMRefreshText(tPtr, tPtr->vpos, tPtr->hpos); -} - - -/* give us nice chunk sizes (multiples of 16) */ -static short - reqBlockSize(short requested) { - return requested + 16 - (requested % 16); -} static void - insertTextInteractively(Text * tPtr, char *text) { - Paragraph *para = NULL; - Chunk *chunk = NULL, *newchunk = NULL; - int height = -23; /* should only be changed upon newline */ - short w = 0, h = 0; - WMFont *font; - - if (!tPtr->editable) - return; - if (*text == '\n' && tPtr->ignoreNewLine) - return; - - para = tPtr->currentPara; - chunk = tPtr->currentChunk; - font = (tPtr->monoFont || !chunk) ? tPtr->dFont : chunk->font; - - if (*text == '\n') { - int new_top = 0; - if (chunk) { /* there's a chunk (or part of it) to detach from old */ - int current = WMGetTextCurrentChunk(tPtr); - if (tPtr->tpos <= 0) { /* at start of chunk */ - if (current < 1) { /* the first chunk... make old para blank */ - newchunk = para->chunks; - para->chunks = NULL; - putParagraphOnPixmap(tPtr, para, True); - } else { /* not first chunk... */ - printf("cut me out \n"); - } - } else if (tPtr->tpos < chunk->chars && chunk->type == ctText) { - /* not at start of chunk */ - char text[chunk->chars - tPtr->tpos + 1]; - int i = 0; - - do { - text[i] = chunk->text[tPtr->tpos + i]; - } while (++i < chunk->chars - tPtr->tpos); - chunk->chars -= i; - newchunk = (tPtr->funcs.createTChunk) (text, i, chunk->font, - chunk->color, chunk->script, chunk->ul); - newchunk->next = chunk->next; - chunk->next = NULL; - /* might want to demalloc for LARGE cuts */ + if(*text == '\n') { + int new_top=0; + if(tb) { /* there's a tb (or part of it) to detach from old */ + int current = WMGetTextCurrentChunk(tPtr); + if(tPtr->tpos <=0) { /* at start of tb */ + if(current<1) { /* the first tb... make old para blank */ + newtb = para->tbs; + para->tbs = NULL; + putParagraphOnPixmap(tPtr, para, True); + } else { /* not first tb... */ + printf("cut me out \n"); + } + } else if(tPtr->tpos < tb->chars && tb->type == ctText) { + /* not at start of tb */ + char text[tb->chars-tPtr->tpos+1]; + int i=0; + do { + text[i] = tb->text[tPtr->tpos+i]; + } while(++i < tb->chars-tPtr->tpos); + tb->chars -= i; + newtb = (tPtr->funcs.createTChunk) (text, i, tb->font, + tb->color, tb->script, tb->ul); + newtb->next = tb->next; + tb->next = NULL; + /* might want to demalloc for LARGE cuts */ //calcParaExtents(tPtr, para); - para->height = putParagraphOnPixmap(tPtr, para, True); - //putParagraphOnPixmap(tPtr, para, True); - } else if (tPtr->tpos >= chunk->chars) { - Chunk *prev; + para->height = putParagraphOnPixmap(tPtr, para, True); + //putParagraphOnPixmap(tPtr, para, True); + } else if(tPtr->tpos >= tb->chars) { + Chunk *prev; + WMSetTextCurrentChunk(tPtr, current-1); + prev = tPtr->currentChunk; + if(!prev) return; + newtb = prev->next; + prev->next = NULL; + putParagraphOnPixmap(tPtr, para, True); + } + } else newtb = NULL; - WMSetTextCurrentChunk(tPtr, current - 1); - prev = tPtr->currentChunk; - if (!prev) - return; - newchunk = prev->next; - prev->next = NULL; - putParagraphOnPixmap(tPtr, para, True); - } - } else - newchunk = NULL; - - if (para) /* the preceeding one */ - new_top = para->bottom; - - WMAppendTextStream(tPtr, "\n"); - para = tPtr->currentPara; - if (!para) - return; - para->chunks = newchunk; - tPtr->currentChunk = newchunk; - tPtr->tpos = 0; - para->top = new_top; - calcParaExtents(tPtr, para); - height = para->height; - } else { - if (!para) { - WMAppendTextStream(tPtr, text); - para = tPtr->currentPara; - } else if (!para->chunks || !chunk) { - //WMPrependTextStream(tPtr, text); - WMAppendTextStream(tPtr, text); - } else if (chunk->type == ctImage) { - WMPrependTextStream(tPtr, text); - - printf("\n\nprepe\n\n"); + if(para) /* the preceeding one */ + new_top = para->bottom; + + WMAppendTextStream(tPtr, "\n"); + para = tPtr->currentPara; + if(!para) return; + para->tbs = newtb; + tPtr->currentChunk = newtb; + tPtr->tpos = 0; + para->top = new_top; + calcParaExtents(tPtr, para); + height = para->height; } else { - if (tPtr->tpos > chunk->chars) { - printf("\n\nmore\n\n"); - tPtr->tpos = chunk->chars; - } - if (chunk->chars + 1 >= chunk->mallocedSize) { - chunk->mallocedSize = reqBlockSize(chunk->chars + 1); - chunk->text = wrealloc(chunk->text, chunk->mallocedSize); - } - memmove(&(chunk->text[tPtr->tpos + 1]), &chunk->text[tPtr->tpos], - chunk->chars - tPtr->tpos + 1); - w = WMWidthOfString(font, text, 1); - memmove(&chunk->text[tPtr->tpos], text, 1); - chunk->chars++; - tPtr->tpos++; - //doc->clickstart.cursor.x += - //WMWidthOfString(chunk->fmt->font, text,len); + if(!para) { + WMAppendTextStream(tPtr, text); + para = tPtr->currentPara; + } else if(!para->tbs || !tb) { + //WMPrependTextStream(tPtr, text); + WMAppendTextStream(tPtr, text); + } else if(tb->type == ctImage) { + WMPrependTextStream(tPtr, text); + +printf("\n\nprepe\n\n"); + } else { + if(tPtr->tpos > tb->chars) { +printf("\n\nmore\n\n"); + tPtr->tpos = tb->chars; + } +#endif + +printf("len is %d\n", len); + if(tb->used+len >= tb->allocated) { + tb->allocated = reqBlockSize(tb->used+len); +printf("ralloced %d\n", tb->allocated); + tb->text = wrealloc(tb->text, tb->allocated); + } + + if(tb->blank) { + memmove(tb->text, text, len); + tb->used = len; + tPtr->tpos = len; + tb->blank = False; + } else { + memmove(&(tb->text[tPtr->tpos+len]), &tb->text[tPtr->tpos], + tb->used-tPtr->tpos+1); + memmove(&tb->text[tPtr->tpos], text, len); + tb->used += len; + tPtr->tpos += len; + } + w = myWidthOfString(font, text, len); + + + if(mark) { + WMAppendTextStream(tPtr, mark); + WMRefreshText(tPtr, tPtr->vpos, tPtr->hpos); +printf("paste: use prev/post chunk's fmt...\n"); + } else { + layOutDocument(tPtr); + paintText(tPtr); } - } +#if 0 +//doc->clickstart.cursor.x += +//myWidthOfString(tb->fmt->font, text,len); + } + } +#endif +} - if (para) { - affectNextParas(tPtr, para, height); - putParagraphOnPixmap(tPtr, para, True); - drawDocumentPartsOnPixmap(tPtr, False); - updateScrollers(tPtr); +static void +selectRegion(Text *tPtr, int x, int y) +{ + if(x < 0 || y < 0) + return; + y += tPtr->vpos; + if(y>10) y -= 10; /* the original offset */ + + x -= tPtr->visible.x-2; + if(x<0) x=0; + + tPtr->sel.x = WMAX(0, WMIN(tPtr->clicked.x, x)); + tPtr->sel.w = abs(tPtr->clicked.x - x); + tPtr->sel.y = WMAX(0, WMIN(tPtr->clicked.y, y)); + tPtr->sel.h = abs(tPtr->clicked.y - y); + + tPtr->flags.ownsSelection = True; paintText(tPtr); - //cursorToTextPosition(tPtr, tPtr->clicked.x+w, tPtr->clicked.y); - //check for "sneppah tahw" with blank paras... - //paintText(tPtr); - } } -static void - selectRegion(Text * tPtr, int x, int y) { - tPtr->sRect.pos.x = WMIN(tPtr->clicked.x, x); - tPtr->sRect.size.width = abs(tPtr->clicked.x - x); - tPtr->sRect.pos.y = WMIN(tPtr->clicked.y, y); - if (tPtr->sRect.pos.y < 0) - tPtr->sRect.pos.y = 0; - tPtr->sRect.size.height = abs(tPtr->clicked.y - y); - - /* - while(y>tPtr->visibleH && tPtr->vpos < tPtr->docHeight-tPtr->visibleH) { - WMRefreshText(tPtr, tPtr->vpos+16, tPtr->hpos); - } - */ - //printf("%d %d \n", y, tPtr->vpos); - - //foreach para in selection... - drawDocumentPartsOnPixmap(tPtr, True); - paintText(tPtr); -} -#define WM_EMACSKEYMASK ControlMask -#define WM_EMACSKEY_LEFT XK_b -#define WM_EMACSKEY_RIGHT XK_f -#define WM_EMACSKEY_HOME XK_a -#define WM_EMACSKEY_END XK_e -#define WM_EMACSKEY_BS XK_h -#define WM_EMACSKEY_DEL XK_d static void - handleTextKeyPress(Text * tPtr, XEvent * event) { - char buffer[2]; - KeySym ksym; - int control_pressed = False; - - if (!tPtr->editable) - return; - - if (((XKeyEvent *) event)->state & WM_EMACSKEYMASK) - control_pressed = True; - buffer[XLookupString(&event->xkey, buffer, 1, &ksym, NULL)] = '\0'; - - switch (ksym) { - - case XK_Right: - case XK_Left: - if (tPtr->currentChunk) { - short w; - Chunk *chunk = tPtr->currentChunk; - - if (chunk->type == ctText) { - WMFont *font = (tPtr->monoFont) ? tPtr->dFont : chunk->font; - - if (ksym == XK_Right) { - short pos = (tPtr->tpos < chunk->chars) ? tPtr->tpos + 1 : - chunk->chars; - - w = WMWidthOfString(font, &chunk->text[pos], 1); - } else { - short pos = (tPtr->tpos > 0) ? tPtr->tpos - 1 : 0; - - w = WMWidthOfString(font, &chunk->text[pos], 1); - } - } else { - w = chunk->pixmap->width; - } - if (ksym == XK_Right) - w = -w; - cursorToTextPosition(tPtr, tPtr->clicked.x - w, tPtr->clicked.y); - } else { - if (ksym == XK_Right) - ksym = XK_Down; - else - ksym = XK_Up; - goto noCChunk; - } - break; - - case XK_Down: - case XK_Up: - noCChunk:{ - short h = tPtr->clheight - 2; - - if (ksym == XK_Down) - h = -h; - cursorToTextPosition(tPtr, tPtr->clicked.x, tPtr->clicked.y - h); - } - break; - - case XK_BackSpace: - deleteTextInteractively(tPtr, dtBackSpace); - break; - - case XK_Delete: - case XK_KP_Delete: - deleteTextInteractively(tPtr, dtDelete); - break; - - case XK_Return: - buffer[0] = '\n'; - default: - if (buffer[0] != '\0' && (buffer[0] == '\n' || !iscntrl(buffer[0]))) - insertTextInteractively(tPtr, buffer); - else if (control_pressed && ksym == XK_r) { - Bool i = !tPtr->rulerShown; - - WMShowTextRuler(tPtr, i); - tPtr->rulerShown = i; - } - } - -} - - static void - pasteText(WMView * view, Atom selection, Atom target, Time timestamp, - void *cdata, WMData * data) { - Text *tPtr = (Text *) view->self; - char *str; +pasteText(WMView *view, Atom selection, Atom target, Time timestamp, + void *cdata, WMData *data) +{ + Text *tPtr = (Text *)view->self; + char *str; + + tPtr->flags.waitingForSelection = False; - - tPtr->waitingForSelection = False; - if (data) { - str = (char *) WMDataBytes(data); - if (tPtr->tpos < 1) - WMPrependTextStream(tPtr, str); - else - WMAppendTextStream(tPtr, str); - WMRefreshText(tPtr, tPtr->vpos, tPtr->hpos); - } else { - int n; - - str = XFetchBuffer(tPtr->view->screen->display, &n, 0); - if (str) { - str[n] = 0; - if (tPtr->tpos < 1) - WMPrependTextStream(tPtr, str); - else - WMAppendTextStream(tPtr, str); - XFree(str); - WMRefreshText(tPtr, tPtr->vpos, tPtr->hpos); + if(data) { + str = (char*)WMDataBytes(data); + insertTextInteractively(tPtr, str, strlen(str)); + } else { + int n; + str = XFetchBuffer(tPtr->view->screen->display, &n, 0); + if(str) { + str[n] = 0; + insertTextInteractively(tPtr, str, n); + XFree(str); + } } - } } - -static void - releaseSelection(Text * tPtr) { - Paragraph *para = tPtr->paragraphs; - Chunk *chunk; - - while (para) { - chunk = para->chunks; - while (chunk) { - chunk->selected = False; - chunk = chunk->next; - } - para = para->next; - } - WMDeleteSelectionHandler(tPtr->view, XA_PRIMARY, CurrentTime); - tPtr->ownsSelection = False; - drawDocumentPartsOnPixmap(tPtr, True); - paintText(tPtr); +static void +releaseSelection(Text *tPtr) +{ + printf("I have %d selection\n", 1); + tPtr->flags.ownsSelection = False; + paintText(tPtr); } - static WMData * - requestHandler(WMView * view, Atom selection, Atom target, - void *cdata, Atom * type) { - Text *tPtr = view->self; - int count; - Display *dpy = tPtr->view->screen->display; - Atom _TARGETS; - Atom TEXT = XInternAtom(dpy, "TEXT", False); - Atom COMPOUND_TEXT = XInternAtom(dpy, "COMPOUND_TEXT", False); - WMData *data = NULL; - - - if (!tPtr->ownsSelection || !tPtr->paragraphs) - return NULL; - //printf("got here\n"); - - if (target == XA_STRING || target == TEXT || target == COMPOUND_TEXT) { - //for bleh in selection... - char *s = NULL; - Paragraph *para = tPtr->paragraphs; - Chunk *chunk = NULL; - char pixmap[] = "[pixmap]"; - Bool first = True; - short len; - - while (para) { - chunk = para->chunks; - while (chunk) { - - if (chunk->selected && chunk->type == ctText) { - len = chunk->chars; //chunk->sEnd - chunk->sStart; - - if (len > 0) { - s = wmalloc(len + 1); - if (s) { - memcpy(s, &chunk->text[0 * chunk->sStart], len); - s[len] = 0; - if (first) { - data = WMCreateDataWithBytes(s, strlen(s)); - first = False; - } else { - printf("append: %c %d\n", *s, strlen(s)); - WMAppendDataBytes(data, s, strlen(s)); - } - //gdbFree(s); - } - } - } -#if 0 - printf("len is %d [%d %d] %d \n", len, chunk->sStart, chunk->sEnd, - chunk->chars); -#endif - chunk = chunk->next; - } - para = para->next; - } - - if (data) { - WMSetDataFormat(data, 8); - *type = target; - } - return data; - } -#if 0 - _TARGETS = XInternAtom(dpy, "TARGETS", False); - if (target == _TARGETS) { - Atom *ptr = wmalloc(4 * sizeof(Atom)); - - ptr[0] = _TARGETS; - ptr[1] = XA_STRING; - ptr[2] = TEXT; - ptr[3] = COMPOUND_TEXT; - - data = WMCreateDataWithBytes(ptr, 4 * 4); - WMSetDataFormat(data, 32); - +requestHandler(WMView *view, Atom selection, Atom target, + void *cdata, Atom *type) +{ + Text *tPtr = view->self; + int count; + Display *dpy = tPtr->view->screen->display; + Atom TEXT = XInternAtom(dpy, "TEXT", False); + Atom COMPOUND_TEXT = XInternAtom(dpy, "COMPOUND_TEXT", False); + *type = target; - return data; - } -#endif - - return NULL; + if (target == XA_STRING || target == TEXT || target == COMPOUND_TEXT) + return WMGetTextSelected(tPtr); + else { + WMData *data = WMCreateDataWithBytes("bleh", 4); + return data; + } + return NULL; } - + static void - lostHandler(WMView * view, Atom selection, void *cdata) { - WMText *tPtr = (WMText *) view->self; - releaseSelection(tPtr); -} static WMSelectionProcs selectionHandler = { +lostHandler(WMView *view, Atom selection, void *cdata) +{ + releaseSelection((WMText *)view->self); +} - requestHandler, lostHandler, NULL +static WMSelectionProcs selectionHandler = { + requestHandler, lostHandler, NULL }; static void - _notification(void *observerData, WMNotification * notification) { - WMText *to = (WMText *) observerData; - WMText *tw = (WMText *) WMGetNotificationClientData(notification); - if (to != tw) - lostHandler(to->view, XA_PRIMARY, NULL); -} static void - handleTextEvents(XEvent * event, void *data) { - Text *tPtr = (Text *) data; - Display *dpy = event->xany.display; - - if (tPtr->waitingForSelection) - return; - - switch (event->type) { - case KeyPress: - if (!tPtr->editable || tPtr->buttonHeld) { - XBell(dpy, 0); - return; - } - if (tPtr->ownsSelection) - releaseSelection(tPtr); - - //if (tPtr->waitingForSelection) return; - if (tPtr->focused) { -#if 0 - XGrabPointer(dpy, W_VIEW(tPtr)->window, False, - PointerMotionMask | ButtonPressMask | ButtonReleaseMask, - GrabModeAsync, GrabModeAsync, None, - W_VIEW(tPtr)->screen->invisibleCursor, CurrentTime); - tPtr->pointerGrabbed = True; -#endif - handleTextKeyPress(tPtr, event); - } - break; - - case MotionNotify: - if (tPtr->pointerGrabbed) { - tPtr->pointerGrabbed = False; - XUngrabPointer(dpy, CurrentTime); - } - if ((event->xmotion.state & Button1Mask)) { - selectRegion(tPtr, event->xmotion.x, event->xmotion.y); - if (!tPtr->ownsSelection) { - WMCreateSelectionHandler(tPtr->view, XA_PRIMARY, - event->xbutton.time, &selectionHandler, NULL); - tPtr->ownsSelection = True; - } - break; - } - case ButtonPress: - if (event->xbutton.button == Button1) { - if (tPtr->ownsSelection) - releaseSelection(tPtr); - cursorToTextPosition(tPtr, event->xmotion.x, event->xmotion.y); - if (tPtr->pointerGrabbed) { - tPtr->pointerGrabbed = False; - XUngrabPointer(dpy, CurrentTime); - break; - } - } - if (!tPtr->focused) { - WMSetFocusToWidget(tPtr); - tPtr->focused = True; - break; - } - if (event->xbutton.button == 4) - WMScrollText(tPtr, -16); - else if (event->xbutton.button == 5) - WMScrollText(tPtr, 16); - - break; - - case ButtonRelease: - tPtr->buttonHeld = False; - if (tPtr->pointerGrabbed) { - tPtr->pointerGrabbed = False; - XUngrabPointer(dpy, CurrentTime); - break; - } - if (event->xbutton.button == 4 || event->xbutton.button == 5) - break; - if (event->xbutton.button == Button2 && tPtr->editable) { - char *text = NULL; - int n; - - if (!WMRequestSelection(tPtr->view, XA_PRIMARY, XA_STRING, - event->xbutton.time, pasteText, NULL)) { - text = XFetchBuffer(tPtr->view->screen->display, &n, 0); - if (text) { - text[n] = 0; - WMAppendTextStream(tPtr, text); - XFree(text); - WMRefreshText(tPtr, tPtr->vpos, tPtr->hpos); - } else - tPtr->waitingForSelection = True; - } - } - break; - - } - -} - - -static void - handleNonTextEvents(XEvent * event, void *data) { - Text *tPtr = (Text *) data; - - switch (event->type) { - case Expose: - if (!event->xexpose.count && tPtr->view->flags.realized) - paintText(tPtr); - break; - - case FocusIn: - if (W_FocusedViewOfToplevel(W_TopLevelOfView(tPtr->view)) != tPtr->view) - return; - tPtr->focused = True; - //cursor...paintText(tPtr); - break; - - case FocusOut: - tPtr->focused = False; - //cursor...paintText(tPtr); - break; - - case DestroyNotify: - printf("destroy"); - //for(...)WMRemoveTextParagraph(tPtr, para); - break; - - } //printf("handleNonTextEvents\n"); -} static void - rulerCallBack(WMWidget * w, void *self) { - Text *tPtr = (Text *) self; - short which; - - if (tPtr->currentPara) { - Paragraph *para = tPtr->currentPara; - para->fmargin = WMGetRulerMargin(tPtr->ruler, WRulerFirst); - para->bmargin = WMGetRulerMargin(tPtr->ruler, WRulerBody); - para->rmargin = WMGetRulerMargin(tPtr->ruler, WRulerRight); - affectNextParas(tPtr, para, -23); - putParagraphOnPixmap(tPtr, para, True); - } -#if 0 - which = WMGetReleasedRulerMargin(tPtr->ruler); - - if (which != WRulerDocLeft && which != WRulerRight - /* && Selection.para.count > 0 */ ) { - printf("" - "//for(i=0; iruler, WRulerRight); - - - if (WMGetGrabbedRulerMargin(tPtr->ruler) == WRulerLeft) { - short lmargin = WMGetRulerMargin(tPtr->ruler, WRulerDocLeft); - XClearArea(tPtr->view->screen->display, tPtr->view->window, - 22, 42, lmargin - 21, tPtr->visibleH, True); - } else if (WMGetGrabbedRulerMargin(tPtr->ruler) == WRulerRight && - tPtr->docWidth + 11 < rmargin) { - XClearArea(tPtr->view->screen->display, tPtr->view->window, - rmargin - 3, 42, 10, tPtr->visibleH, True); - } - paintText(tPtr); -} - - - -/* ------------- non-static functions that are "friends" ------------- */ -/* ------------- called as (tPtr->funcs.foo)(bars...) ------------- */ - -/* create a new paragraph. Don't do anything with it just yet */ -//Paragraph * -void * - createParagraph(short fmargin, short bmargin, short rmargin, - short *tabstops, short numTabs, WMAlignment alignment) { - Paragraph *para = wmalloc(sizeof(Paragraph)); - if (!para) - return NULL; - - para->chunks = NULL; - para->next = NULL; - - - para->fmargin = (fmargin >= 0) ? fmargin : 0; - para->bmargin = (bmargin >= 0) ? bmargin : 0; - if (rmargin - bmargin >= 100 && rmargin - fmargin >= 100) - para->rmargin = rmargin; - else - para->rmargin = 100; - para->tabstops = tabstops; - para->numTabs = (tabstops) ? numTabs : 0; - - para->drawbuffer = (Pixmap) NULL; - para->bulletPix = NULL; - para->top = para->bottom = 0; - para->width = para->height = 0; - - para->align = alignment; - - return para; -} /* insert the new paragraph in the tPtr, either right before - or after the currentPara. It's the responsibility of the - calling code to set what currentPara is. via WMSetTextCurrentParagraph. - If currentPara is not set, set it as the first in the document. - This function then sets currentPara as _this_ paragraph. - NOTE: this means careless parser implementors might lose previous - paragraphs... but this keeps stuff small and non-buggy :-) */ void - insertParagraph(WMText * tPtr, void *v, Bool prepend) -//insertParagraph(WMText *tPtr, Paragraph *para, InsertType type) +_notification(void *observerData, WMNotification *notification) { - Paragraph *tmp; - Paragraph *para = (Paragraph *) v; - if (!para || !tPtr) - return; - - if (!tPtr->currentPara) { - tPtr->paragraphs = para; - } else { - tmp = tPtr->paragraphs; - if (!prepend) { - while (tmp->next && tmp != tPtr->currentPara) - tmp = tmp->next; - - para->next = tmp->next; - tmp->next = para; - } else { /* must be prepend */ - /* this "prior" member is that "doing things the hard way" - I spoke of. See? it's not too bad afterall... */ - Paragraph *prior = NULL; - - while (tmp->next && tmp != tPtr->currentPara) { - prior = tmp; - tmp = tmp->next; - } - /* if this is the first */ - if (tmp == tPtr->paragraphs) { - para->next = tmp; - tPtr->paragraphs = para; - } else { - prior->next = para; - para->next = tmp; - } - } - } - tPtr->currentPara = para; - + WMText *to = (WMText *)observerData; + WMText *tw = (WMText *)WMGetNotificationClientData(notification); + if (to != tw) + lostHandler(to->view, XA_PRIMARY, NULL); } -/* create a new chunk to contain exactly ONE pixmap */ -void * -//Chunk * - createPChunk(WMPixmap * pixmap, short script, ushort ul) { - Chunk *chunk; +static void +handleTextKeyPress(Text *tPtr, XEvent *event) +{ + char buffer[2]; + KeySym ksym; + int control_pressed = False; +// int h=1; - chunk = wmalloc(sizeof(Chunk)); - if (!chunk) - return NULL; + if (((XKeyEvent *) event)->state & ControlMask) + control_pressed = True; + buffer[XLookupString(&event->xkey, buffer, 1, &ksym, NULL)] = '\0'; + + switch(ksym) { + case XK_Right: + case XK_Left: + case XK_Down: + case XK_Up: + printf("arrows %ld\n", ksym); + break; - chunk->text = NULL; - if (!pixmap) - chunk->pixmap = NULL; /* if it's NULL, we'll draw the "broken" pixmap... */ - else - chunk->pixmap = WMRetainPixmap(pixmap); - chunk->chars = 0; - chunk->mallocedSize = 0; - chunk->type = ctImage; - chunk->font = NULL; - chunk->color = NULL; - chunk->script = script; - chunk->ul = ul; - chunk->selected = False; - chunk->next = NULL; - return chunk; -} /* create a new chunk to contain some text with the given format */ void * -//Chunk * - createTChunk(char *text, short chars, WMFont * font, - WMColor * color, short script, ushort ul) { - Chunk *chunk; + case XK_BackSpace: + case XK_Delete: + case XK_KP_Delete: + deleteTextInteractively(tPtr, ksym); + break; - if (!text || chars < 0 || !font || !color) - return NULL; - chunk = wmalloc(sizeof(Chunk)); - if (!chunk) - return NULL; - chunk->mallocedSize = reqBlockSize(chars); - chunk->text = (char *) wmalloc(chunk->mallocedSize); - memcpy(chunk->text, text, chars); - chunk->pixmap = NULL; - chunk->chars = chars; - chunk->type = ctText; - chunk->font = WMRetainFont(font); - chunk->color = WMRetainColor(color); - chunk->script = script; - chunk->ul = ul; - chunk->selected = False; - chunk->next = NULL; - - return chunk; -} /* insert the new chunk in the paragraph, either right before - or after the currentChunk. It's the responsibility of the - calling code to set what currentChunk is via WMSetTextCurrentChunk. - If currentChunk is not set, set it as the first in the existing - paragraph... if not even that, you lose... try again. - This function then sets currentChunk as _this_ chunk. - NOTE: this means careless parser implementors might lose previous - paragraphs/chunks... but this keeps stuff small and non-buggy :-) */ void - insertChunk(WMText * tPtr, void *v, Bool prepend) { - Chunk *tmp; - Chunk *chunk = (Chunk *) v; - - if (!tPtr || !chunk) - return; - - if (!tPtr->paragraphs) { /* i.e., first chunk via insertTextInteractively */ - Paragraph *para = (tPtr->funcs.createParagraph) (0, 0, tPtr->visibleW, - NULL, 0, WALeft); - (tPtr->funcs.insertParagraph) (tPtr, para, False); - } - if (!tPtr->currentPara) - return; - - if (!tPtr->currentChunk) { /* there is a current chunk */ - tPtr->currentPara->chunks = chunk; - } else if (!tPtr->currentPara->chunks) { - /* but it's not of this paragraph */ - tPtr->currentPara->chunks = chunk; - } else { - tmp = tPtr->currentPara->chunks; - - if (!prepend) { - while (tmp->next && tmp != tPtr->currentChunk) - tmp = tmp->next; - - chunk->next = tmp->next; - tmp->next = chunk; - - } else { /* must be prepend */ - /* this "prior" member is that "doing things the hard way" - I spoke of. See? it's not too bad afterall... */ - Chunk *prior = NULL; - - while (tmp->next && tmp != tPtr->currentChunk) { - prior = tmp; - tmp = tmp->next; - } - /* if this is the first */ - if (tmp == tPtr->currentPara->chunks) { - chunk->next = tmp; - tPtr->currentPara->chunks = chunk; - } else { - prior->next = chunk; - chunk->next = tmp; - } + case XK_Return: + buffer[0] = '\n'; + default: + if(buffer[0] != '\0' && (buffer[0] == '\n' || !control_pressed)) + insertTextInteractively(tPtr, buffer, 1); + else if(control_pressed && ksym==XK_r) { + // Bool i = !tPtr->rulerShown; WMShowTextRuler(tPtr, i); + // tPtr->rulerShown = i; +printf("toggle ruler\n"); + } + else if(control_pressed && buffer[0] == '') + XBell(tPtr->view->screen->display, 0); } - } - tPtr->currentChunk = chunk; - tPtr->tpos = chunk->chars; + + if(tPtr->flags.ownsSelection) + releaseSelection(tPtr); } -/* ------------- non-static functions (i.e., APIs) ------------- */ -/* ------------- called as WMVerbText[Subject] ------------- */ +static void +handleWidgetPress(XEvent *event, void *data) +{ + TextBlock *tb = (TextBlock *)data; + Text *tPtr; + WMWidget *w; + if(!tb) + return; +#if 0 + /* this little bit of nastiness here saves a boatload of trouble */ + w = (WMWidget *)(W_VIEW((W_VIEW(tb->d.widget))->parent))->self; + //if(W_CLASS(w) != WC_TextField && W_CLASS(w) != WC_Text) + if( (((W_WidgetType*)(w))->widgetClass) != WC_Text) + return; + *tPtr = (Text*)w; + printf("%p clicked on tb %p wif: (%c)%c", tPtr, tb, + tPtr->firstTextBlock->text[0], tPtr->firstTextBlock->text[1]); + output(tb->text, tb->used); +#endif +} + +static void +handleActionEvents(XEvent *event, void *data) +{ + Text *tPtr = (Text *)data; + Display *dpy = event->xany.display; + KeySym ksym; + + + if(tPtr->flags.waitingForSelection) + return; + + switch (event->type) { + case KeyPress: + ksym = XLookupKeysym((XKeyEvent*)event, 0); + if(ksym == XK_Shift_R || ksym == XK_Shift_L) { + tPtr->flags.extendSelection = True; + return; + } + if(!tPtr->flags.editable || tPtr->flags.buttonHeld) { + XBell(dpy, 0); + return; + } + + if (tPtr->flags.waitingForSelection) + return; + if(tPtr->flags.focused) { + XGrabPointer(dpy, W_VIEW(tPtr)->window, False, + PointerMotionMask|ButtonPressMask|ButtonReleaseMask, + GrabModeAsync, GrabModeAsync, None, + W_VIEW(tPtr)->screen->invisibleCursor, CurrentTime); + tPtr->flags.pointerGrabbed = True; + handleTextKeyPress(tPtr, event); + + } break; + + case KeyRelease: + ksym = XLookupKeysym((XKeyEvent*)event, 0); + if(ksym == XK_Shift_R || ksym == XK_Shift_L) { + tPtr->flags.extendSelection = False; + return; + //end modify flag so selection can be extended + } + break; + + + case MotionNotify: + if(tPtr->flags.pointerGrabbed) { + tPtr->flags.pointerGrabbed = False; + XUngrabPointer(dpy, CurrentTime); + } + if((event->xmotion.state & Button1Mask)) { + if(!tPtr->flags.ownsSelection) { + WMCreateSelectionHandler(tPtr->view, XA_PRIMARY, + event->xbutton.time, &selectionHandler, NULL); + tPtr->flags.ownsSelection = True; + } + selectRegion(tPtr, event->xmotion.x, event->xmotion.y); + } + break; + + + case ButtonPress: + tPtr->flags.buttonHeld = True; + if(tPtr->flags.extendSelection) { + selectRegion(tPtr, event->xmotion.x, event->xmotion.y); + return; + } + if(event->xbutton.button == Button1) { + if(tPtr->flags.ownsSelection) + releaseSelection(tPtr); + cursorToTextPosition(tPtr, event->xmotion.x, event->xmotion.y); + if (tPtr->flags.pointerGrabbed) { + tPtr->flags.pointerGrabbed = False; + XUngrabPointer(dpy, CurrentTime); + break; + } + } + if(!tPtr->flags.focused) { + WMSetFocusToWidget(tPtr); + tPtr->flags.focused = True; + break; + } + + if(event->xbutton.button == WINGsConfiguration.mouseWheelDown) + WMScrollText(tPtr, -16); + else if(event->xbutton.button == WINGsConfiguration.mouseWheelUp) + WMScrollText(tPtr, 16); + break; + + case ButtonRelease: + tPtr->flags.buttonHeld = False; + if (tPtr->flags.pointerGrabbed) { + tPtr->flags.pointerGrabbed = False; + XUngrabPointer(dpy, CurrentTime); + break; + } + if(event->xbutton.button == WINGsConfiguration.mouseWheelDown + || event->xbutton.button == WINGsConfiguration.mouseWheelUp) + break; + + if(event->xbutton.button == Button2 && tPtr->flags.editable) { + char *text = NULL; + int n; + if(!WMRequestSelection(tPtr->view, XA_PRIMARY, XA_STRING, + event->xbutton.time, pasteText, NULL)) { + text = XFetchBuffer(tPtr->view->screen->display, &n, 0); + if(text) { + text[n] = 0; + insertTextInteractively(tPtr, text, n-1); + XFree(text); + } else tPtr->flags.waitingForSelection = True; + } } + + break; + + } + +} + + +static void +handleEvents(XEvent *event, void *data) +{ + Text *tPtr = (Text *)data; + + switch(event->type) { + case Expose: + if(!event->xexpose.count && tPtr->view->flags.realized) + paintText(tPtr); + break; + + case FocusIn: + if (W_FocusedViewOfToplevel(W_TopLevelOfView(tPtr->view))!=tPtr->view) + return; + tPtr->flags.focused = True; + break; + + case FocusOut: + tPtr->flags.focused = False; + break; + + case DestroyNotify: + printf("destroy"); + //for(...)WMRemoveTextParagraph(tPtr, para); + break; + + } +} + + + +static void +clearText(Text *tPtr) +{ + void *tb; + if(!tPtr->firstTextBlock) + return; + + while(tPtr->currentTextBlock) + WMDestroyTextBlock(tPtr, WMRemoveTextBlock(tPtr)); + + printf("yadda clearText\n"); + + printf("remove the document\n"); + tPtr->firstTextBlock = NULL; + tPtr->currentTextBlock = NULL; + tPtr->lastTextBlock = NULL; + //WMThawText(tPtr); + WMRefreshText(tPtr, 0, 0); +} + + +static void +insertPlainText(WMText *tPtr, char *text) +{ + char *start, *mark; + void *tb = NULL; + + + if(!text) { + clearText(tPtr); + return; + } + + + start = text; + while(start) { + mark = strchr(start, '\n'); + if(mark) { + tb = WMCreateTextBlockWithText(start, tPtr->dFont, + tPtr->dColor, True, (int)(mark-start)); + start = mark+1; + } else { + if(start && strlen(start)) { + tb = WMCreateTextBlockWithText(start, tPtr->dFont, + tPtr->dColor, False, strlen(start)); + } else tb = NULL; + start = mark; + } + + if(tPtr->flags.prepend) + WMPrependTextBlock(tPtr, tb); + else + WMAppendTextBlock(tPtr, tb); + } + return; + +} + + -#define DEFAULT_TEXT_WIDTH 250 -#define DEFAULT_TEXT_HEIGHT 200 WMText * - WMCreateText(WMWidget * parent) { - Text *tPtr = wmalloc(sizeof(Text)); - - if (!tPtr) { - perror("could not create text widget\n"); - return NULL; - } - memset(tPtr, 0, sizeof(Text)); - tPtr->widgetClass = WC_Text; - tPtr->view = W_CreateView(W_VIEW(parent)); - if (!tPtr->view) { - perror("could not create text's view\n"); - wgdbFree(tPtr); - return NULL; - } - tPtr->view->self = tPtr; - tPtr->view->attribs.cursor = tPtr->view->screen->textCursor; - tPtr->view->attribFlags |= CWOverrideRedirect | CWCursor; - W_ResizeView(tPtr->view, DEFAULT_TEXT_WIDTH, DEFAULT_TEXT_HEIGHT); - tPtr->bg = tPtr->view->screen->white; - W_SetViewBackgroundColor(tPtr->view, tPtr->bg); - - - tPtr->ruler = WMCreateRuler(tPtr); - (W_VIEW(tPtr->ruler))->attribs.cursor = tPtr->view->screen->defaultCursor; - (W_VIEW(tPtr->ruler))->attribFlags |= CWOverrideRedirect | CWCursor; - WMMoveWidget(tPtr->ruler, 0, 0); - WMResizeWidget(tPtr->ruler, W_VIEW(parent)->size.width, 40); - WMShowRulerTabs(tPtr->ruler, True); - WMSetRulerAction(tPtr->ruler, rulerCallBack, tPtr); - WMSetRulerMoveAction(tPtr->ruler, rulerMoveCallBack, tPtr); - - tPtr->vpos = 0; - tPtr->prevVpos = 0; - tPtr->vscroller = WMCreateScroller(tPtr); - (W_VIEW(tPtr->vscroller))->attribs.cursor = - tPtr->view->screen->defaultCursor; - (W_VIEW(tPtr->vscroller))->attribFlags |= CWOverrideRedirect | CWCursor; - WMMoveWidget(tPtr->vscroller, 1, 1); - WMResizeWidget(tPtr->vscroller, 20, tPtr->view->size.height - 2); - WMSetScrollerArrowsPosition(tPtr->vscroller, WSAMaxEnd); - WMSetScrollerAction(tPtr->vscroller, scrollersCallBack, tPtr); - - tPtr->hpos = 0; - tPtr->prevHpos = 0; - tPtr->hscroller = WMCreateScroller(tPtr); - (W_VIEW(tPtr->hscroller))->attribs.cursor = - tPtr->view->screen->defaultCursor; - (W_VIEW(tPtr->hscroller))->attribFlags |= CWOverrideRedirect | CWCursor; - WMMoveWidget(tPtr->hscroller, 1, tPtr->view->size.height - 21); - WMResizeWidget(tPtr->hscroller, tPtr->view->size.width - 2, 20); - WMSetScrollerArrowsPosition(tPtr->hscroller, WSAMaxEnd); - WMSetScrollerAction(tPtr->hscroller, scrollersCallBack, tPtr); - - tPtr->visibleW = tPtr->view->size.width; - tPtr->visibleH = tPtr->view->size.height; - - tPtr->paragraphs = NULL; - tPtr->docWidth = 0; - tPtr->docHeight = 0; - tPtr->dBulletPix = WMCreatePixmapFromXPMData(tPtr->view->screen, - default_bullet); - tPtr->dUnknownImg = WMCreatePixmapFromXPMData(tPtr->view->screen, - unk_xpm); - - tPtr->sRect.pos.x = tPtr->sRect.pos.y = 0; - tPtr->sRect.size.width = tPtr->sRect.size.height = 0; - tPtr->currentPara = NULL; - tPtr->currentChunk = NULL; - tPtr->tpos = 0; - - tPtr->parser = NULL; - tPtr->writer = NULL; - tPtr->funcs.createParagraph = createParagraph; - tPtr->funcs.insertParagraph = insertParagraph; - tPtr->funcs.createPChunk = createPChunk; - tPtr->funcs.createTChunk = createTChunk; - tPtr->funcs.insertChunk = insertChunk; - - tPtr->clicked.x = tPtr->clicked.y = -23; - tPtr->cursor.x = tPtr->cursor.y = -23; - - tPtr->relief = WRSunken; - tPtr->wrapping = wrWord; - tPtr->editable = False; - tPtr->cursorShown = False; - tPtr->frozen = False; - tPtr->focused = False; - tPtr->pointerGrabbed = False; - tPtr->buttonHeld = False; - tPtr->ignoreNewLine = False; - tPtr->waitingForSelection = False; - tPtr->findingClickPoint = False; - tPtr->foundClickPoint = False; - tPtr->ownsSelection = False; - tPtr->clheight = 0; - tPtr->clwidth = 0; - - tPtr->dFont = WMRetainFont(tPtr->view->screen->normalFont); - tPtr->dColor = WMBlackColor(tPtr->view->screen); - - tPtr->view->delegate = &_TextViewDelegate; - WMCreateEventHandler(tPtr->view, ExposureMask | StructureNotifyMask - | EnterWindowMask | LeaveWindowMask | FocusChangeMask, - handleNonTextEvents, tPtr); - WMCreateEventHandler(tPtr->view, ButtonReleaseMask | ButtonPressMask - | KeyReleaseMask | KeyPressMask | Button1MotionMask, - handleTextEvents, tPtr); - - WMAddNotificationObserver(_notification, tPtr, "_lostOwnership", tPtr); - - WMSetTextMonoFont(tPtr, True); - WMShowTextRuler(tPtr, False); - WMSetTextHasHorizontalScroller(tPtr, False); - WMSetTextHasVerticalScroller(tPtr, True); - //printf("the sizeof chunk is %d\n", sizeof(Chunk)); - //printf("the sizeof para is %d\n", sizeof(Paragraph)); - //printf("the sizeof text is %d\n", sizeof(Text)); - return tPtr; -} - -//WMSetTextBullet() -//WRetainPixmap(tPtr->dBulletPix); - -void - WMRemoveTextParagraph(WMText * tPtr, int which) { - Paragraph *prior, *removed; - if (!tPtr || which < 0) - return; - - WMSetTextCurrentParagraph(tPtr, which); - removed = tPtr->currentPara; - if (!removed) - return; - if (removed->chunks) - printf("WMRemoveTextChunks\n"); - if (removed == tPtr->paragraphs || which == 0) { - tPtr->paragraphs = removed->next; - } else { - WMSetTextCurrentParagraph(tPtr, which - 1); - prior = tPtr->currentPara; - if (!prior) - return; - prior->next = removed->next; - } - wgdbFree(removed); - // removeChunks - removed = NULL; -} - - - -/* set what is known as the currentPara in the tPtr. */ -/* negative number means: "gib me last chunk" */ -void - WMSetTextCurrentParagraph(WMText * tPtr, int current) { - Paragraph *tmp; - int i = 0; - - if (!tPtr || current < 0) - return; - if (current == 0) { - tPtr->currentPara = tPtr->paragraphs; - return; - } - tmp = tPtr->paragraphs; - - while (tmp->next && ((current == -23) ? 1 : i++ < current)) { - //while(tmp && i++next; - } - tPtr->currentPara = tmp; - //? want to do this?if(tmp) tPtr->currentChunk = tmp -} - - -int - WMGetTextParagraphs(WMText * tPtr) { - int current = 0; - Paragraph *tmp; - - if (!tPtr) - return 0; - tmp = tPtr->paragraphs; - while (tmp) { - tmp = tmp->next; - current++; - } - return current; -} - - - -int - WMGetTextCurrentParagraph(WMText * tPtr) { - int current = -1; - Paragraph *tmp; - - if (!tPtr) - return current; - if (!tPtr->currentPara) - return current; - if (!tPtr->paragraphs) - return current; - tmp = tPtr->paragraphs; - while (tmp) { - current++; - if (tmp == tPtr->currentPara) - break; - tmp = tmp->next; - } - return current; -} - -/* set what is known as the currentChunk within the currently - selected currentPara (or the first paragraph in the document). */ -void - WMSetTextCurrentChunk(WMText * tPtr, int current) { - Chunk *tmp; - int i = 0; - - if (!tPtr) - return; - tPtr->currentChunk = NULL; - if (!tPtr->currentPara) { - tPtr->currentPara = tPtr->paragraphs; - if (!tPtr->currentPara) - return; - } - if (current == 0) { - tPtr->currentChunk = tPtr->currentPara->chunks; - return; - } - tmp = tPtr->currentPara->chunks; - if (tmp) { - while (tmp->next && ((current < 0) ? 1 : i++ < current)) - tmp = tmp->next; - } - tPtr->currentChunk = tmp; -} - - -void - WMRemoveTextChunk(WMText * tPtr, int which) { - Chunk *prior, *removed; - Paragraph *para; - if (!tPtr || which < 0) - return; - para = tPtr->currentPara; - if (!para) - return; - - WMSetTextCurrentChunk(tPtr, which); - removed = tPtr->currentChunk; - if (!removed) - return; - if (removed == tPtr->currentPara->chunks || which == 0) { - para->chunks = removed->next; - } else { - WMSetTextCurrentChunk(tPtr, which - 1); - prior = tPtr->currentChunk; - if (!prior) - return; - prior->next = removed->next; - } - if (removed->type == ctText) { - wgdbFree(removed->text); - WMReleaseFont(removed->font); - WMReleaseColor(removed->color); - } else { - WMReleasePixmap(removed->pixmap); - } - wgdbFree(removed); - removed = NULL; -} - -int - WMGetTextCurrentChunk(WMText * tPtr) { - int current = 0; - Chunk *tmp; - - if (!tPtr) - return 0; - if (!tPtr->currentChunk) - return 0; - if (!tPtr->currentPara) { - tPtr->currentPara = tPtr->paragraphs; - if (!tPtr->currentPara) - return 0; - } - tmp = tPtr->currentPara->chunks; - while (tmp) { - if (tmp == tPtr->currentChunk) - break; - tmp = tmp->next; - current++; - } - return current; -} - -int - WMGetTextChunks(WMText * tPtr) { - short current = 0; - Chunk *tmp; - - if (!tPtr || !tPtr->currentPara) - return 0; - tmp = tPtr->currentPara->chunks; - while (tmp) { - tmp = tmp->next; - current++; - } - return current; -} - -void - WMShowTextRuler(WMText * tPtr, Bool show) { - if (!tPtr) - return; - if (tPtr->monoFont) - show = False; - - tPtr->rulerShown = show; - if (show) - WMMapWidget(tPtr->ruler); - else - WMUnmapWidget(tPtr->ruler); - resizeText(tPtr->view->delegate, tPtr->view); -} - -Bool -WMGetTextRulerShown(WMText * tPtr) { - if (!tPtr) - return False; - return tPtr->rulerShown; -} - -void - WMSetTextRulerMargin(WMText * tPtr, char which, short pixels) { - if (!tPtr) - return; - if (tPtr->monoFont) - return; - WMSetRulerMargins(tPtr->ruler, which, pixels); - WMRefreshText(tPtr, tPtr->vpos, tPtr->hpos); -} short - WMGetTextRulerMargin(WMText * tPtr, char which) { - if (!tPtr) - return 0; - if (tPtr->monoFont) - return 0; - return WMGetRulerMargins(tPtr->ruler, which); -} void - WMShowTextRulerTabs(WMText * tPtr, Bool show) { - if (!tPtr) - return; - if (tPtr->monoFont) - return; - WMShowRulerTabs(tPtr->ruler, show); -} - -void - WMSetTextMonoFont(WMText * tPtr, Bool mono) { - if (!tPtr) - return; - if (mono && tPtr->rulerShown) - WMShowTextRuler(tPtr, False); - - tPtr->monoFont = mono; -} - -Bool -WMGetTextMonoFont(WMText * tPtr) { - if (!tPtr) - return True; - return tPtr->monoFont; -} - -void - WMForceTextFocus(WMText * tPtr) { - if (!tPtr) - return; - - if (tPtr->clicked.x == -23 || tPtr->clicked.y == 23) - cursorToTextPosition(tPtr, 100, 100); /* anyplace */ - else - cursorToTextPosition(tPtr, tPtr->clicked.x, tPtr->clicked.y); -} - - -void - WMSetTextEditable(WMText * tPtr, Bool editable) { - if (!tPtr) - return; - tPtr->editable = editable; -} - - -Bool -WMGetTextEditable(WMText * tPtr) { - if (!tPtr) - return 0; - return tPtr->editable; -} - - -Bool -WMScrollText(WMText * tPtr, int amount) { - Bool scroll = False; - - if (amount == 0 || !tPtr) - return; - if (!tPtr->view->flags.realized) - return; - - if (amount < 0) { - if (tPtr->vpos > 0) { - if (tPtr->vpos > amount) - tPtr->vpos += amount; - else - tPtr->vpos = 0; - scroll = True; +WMCreateText(WMWidget *parent) +{ + Text *tPtr = wmalloc(sizeof(Text)); + if(!tPtr) { + printf("could not create text widget\n"); + return NULL; } - } else { - int limit = tPtr->docHeight - tPtr->visibleH; - if (tPtr->vpos < limit) { - if (tPtr->vpos < limit - amount) - tPtr->vpos += amount; - else - tPtr->vpos = limit; - scroll = True; - } +#if 0 + printf("sizeof:\n"); + printf(" TextBlock %d\n", sizeof(TextBlock)); + printf(" TextBlock *%d\n", sizeof(TextBlock *)); + printf(" Section %d\n", sizeof(Section)); + printf(" char * %d\n", sizeof(char *)); + printf(" void * %d\n", sizeof(void *)); + printf(" short %d\n", sizeof(short)); + printf(" Text %d\n", sizeof(Text)); +#endif + + memset(tPtr, 0, sizeof(Text)); + tPtr->widgetClass = WC_Text; + tPtr->view = W_CreateView(W_VIEW(parent)); + if (!tPtr->view) { + perror("could not create text's view\n"); + free(tPtr); + return NULL; } + tPtr->view->self = tPtr; + tPtr->view->attribs.cursor = tPtr->view->screen->textCursor; + tPtr->view->attribFlags |= CWOverrideRedirect | CWCursor; + W_ResizeView(tPtr->view, 250, 200); + tPtr->bgGC = WMColorGC(tPtr->view->screen->white); + tPtr->fgGC = WMColorGC(tPtr->view->screen->black); + W_SetViewBackgroundColor(tPtr->view, tPtr->view->screen->white); - if (scroll && tPtr->vpos != tPtr->prevVpos) { - updateScrollers(tPtr); - drawDocumentPartsOnPixmap(tPtr, False); - paintText(tPtr); - } - tPtr->prevVpos = tPtr->vpos; - return scroll; -} + tPtr->ruler = NULL; + tPtr->vS = NULL; + tPtr->hS = NULL; -Bool -WMPageText(WMText * tPtr, Bool scrollUp) { - if (!tPtr) - return; - if (!tPtr->view->flags.realized) - return; + tPtr->dFont = NULL; + //tPtr->dFont = WMCreateFont(tPtr->view->screen, + // "-*-fixed-medium-r-normal--26-*-*-*-*-*-*-*"); + //"-sony-fixed-medium-r-normal--24-230-75-75-c-120-jisx0201.1976-0"); + // "-*-times-bold-r-*-*-12-*-*-*-*-*-*-*," + // "-*-fixed-medium-r-normal-*-12-*"); + if (!tPtr->dFont) + tPtr->dFont = WMRetainFont(tPtr->view->screen->normalFont); - return WMScrollText(tPtr, scrollUp - ? tPtr->visibleH : -tPtr->visibleH); -} - -void - WMIgnoreTextNewline(WMText * tPtr, Bool ignore) { - if (!tPtr) - return; - tPtr->ignoreNewLine = ignore; -} - - -void - WMSetTextHasHorizontalScroller(WMText * tPtr, Bool flag) { - if (tPtr) { - short rh; - - if (tPtr->monoFont) - return; - rh = tPtr->rulerShown ? 40 : 0; - tPtr->hasHscroller = flag; - if (flag) { - WMMapWidget(tPtr->hscroller); - tPtr->visibleH = tPtr->view->size.height - rh - 22; - } else { - WMUnmapWidget(tPtr->hscroller); - tPtr->visibleH = tPtr->view->size.height - rh; - } - resizeText(tPtr->view->delegate, tPtr->view); - } -} - - -void - WMSetTextHasVerticalScroller(WMText * tPtr, Bool flag) { - if (tPtr) { - tPtr->hasVscroller = flag; - if (flag) { - WMMapWidget(tPtr->vscroller); - tPtr->visibleW = tPtr->view->size.width - 22; - WMSetRulerOffset(tPtr->ruler, 22); /* scrollbar width + 2 */ - } else { - WMUnmapWidget(tPtr->vscroller); - tPtr->visibleW = tPtr->view->size.width; - WMSetRulerOffset(tPtr->ruler, 2); - } - resizeText(tPtr->view->delegate, tPtr->view); - } -} - - - -void - WMRefreshText(WMText * tPtr, int vpos, int hpos) { - - if (!tPtr) - return; - - if (tPtr->frozen || !tPtr->view->flags.realized) - return; - - - XClearArea(tPtr->view->screen->display, tPtr->view->window, - 22, (tPtr->rulerShown) ? 45 : 5, - tPtr->visibleW, tPtr->visibleH, True); - - calcDocExtents(tPtr); - /* - printf("vpos:%d tPtr->docHeight%d tPtr->visibleH%d \n", - vpos, tPtr->docHeight, tPtr->visibleH); - */ - - // tPtr->vpos = vpos; - /* - if(vpos < 0 || tPtr->docHeight < tPtr->visibleH) - tPtr->vpos = 0; - else if(vpos-tPtr->visibleH>tPtr->docHeight) - tPtr->vpos = vpos-tPtr->docHeight-tPtr->visibleH-tPtr->docHeight; - else - tPtr->vpos = tPtr->docHeight-tPtr->visibleH; - */ - - - if (hpos < 0 || hpos > tPtr->docWidth) - tPtr->hpos = 0; - else - tPtr->hpos = hpos; - - drawDocumentPartsOnPixmap(tPtr, True); - updateScrollers(tPtr); - paintText(tPtr); -} /* would be nice to have in WINGs proper... */ static void - changeFontProp(char *fname, char *newprop, short which) { - char before[128], prop[128], after[128]; - char *ptr, *bptr; - int part = 0; - - if (!fname || !prop) - return; - - ptr = fname; - bptr = before; - while (*ptr) { - if (*ptr == '-') { - *bptr = 0; - if (part == which) - bptr = prop; - else if (part == which + 1) - bptr = after; - *bptr++ = *ptr; - part++; - } else { - *bptr++ = *ptr; - } - ptr++; - } - *bptr = 0; - snprintf(fname, 255, "%s-%s%s", before, newprop, after); -} - -/* TODO: put in wfont? */ -WMFont * - WMGetFontPlain(WMScreen * scrPtr, WMFont * font) { - WMFont *nfont = NULL; - - if (!scrPtr || !font) - return NULL; - return font; - -} - -WMFont * - WMGetFontBold(WMScreen * scrPtr, WMFont * font) { - WMFont *newfont = NULL; - char fname[256]; - - if (!scrPtr || !font) - return NULL; - snprintf(fname, 255, font->name); - changeFontProp(fname, "bold", 2); - newfont = WMCreateNormalFont(scrPtr, fname); - if (!newfont) - newfont = font; - return newfont; -} - -WMFont * - WMGetFontItalic(WMScreen * scrPtr, WMFont * font) { - WMFont *newfont = NULL; - char fname[256]; - - if (!scrPtr || !font) - return NULL; - snprintf(fname, 255, font->name); - changeFontProp(fname, "o", 3); - newfont = WMCreateNormalFont(scrPtr, fname); - if (!newfont) - newfont = font; - return newfont; -} - -WMFont * - WMGetFontOfSize(WMScreen * scrPtr, WMFont * font, short size) { - WMFont *nfont = NULL; - - if (!scrPtr || !font || size < 1) - return NULL; - return font; -} -/* */ - -void - WMFreezeText(WMText * tPtr) { - if (!tPtr) - return; - tPtr->frozen = True; -} - -void - WMThawText(WMText * tPtr) { - if (!tPtr) - return; - tPtr->frozen = False; -} - - -void - WMSetTextDefaultAlignment(WMText * tPtr, WMAlignment alignment) { - if (!tPtr) - return; - if (tPtr->monoFont) - return; - - tPtr->dAlignment = alignment; - WMRefreshText(tPtr, tPtr->vpos, tPtr->hpos); -} - - - -void - WMSetTextBackgroundColor(WMText * tPtr, WMColor * color) { - if (!tPtr) - return; - - if (color) - tPtr->bg = color; - else - tPtr->bg = WMWhiteColor(tPtr->view->screen); - - W_SetViewBackgroundColor(tPtr->view, tPtr->bg); - WMRefreshText(tPtr, tPtr->vpos, tPtr->hpos); -} - -void - WMSetTextDefaultColor(WMText * tPtr, WMColor * color) { - if (!tPtr) - return; - - if (color) - tPtr->dColor = color; - else tPtr->dColor = WMBlackColor(tPtr->view->screen); -} -void - WMSetTextDefaultFont(WMText * tPtr, WMFont * font) { - if (!tPtr) - return; + tPtr->view->delegate = &_TextViewDelegate; - if (font) - tPtr->dFont = font; - else - tPtr->dFont = WMRetainFont(tPtr->view->screen->normalFont); -} + WMCreateEventHandler(tPtr->view, ExposureMask|StructureNotifyMask + |EnterWindowMask|LeaveWindowMask|FocusChangeMask, + handleEvents, tPtr); -void - WMSetTextUseFixedPitchFont(Text * tPtr, Bool fixed) { - if (!tPtr) - return; - if (fixed) - tPtr->dFont = WMCreateFontSet(tPtr->view->screen, - "lucidasanstypewriter-12"); - else - tPtr->dFont = WMRetainFont(tPtr->view->screen->normalFont); - tPtr->fixedPitch = fixed; -} + WMCreateEventHandler(tPtr->view, ButtonReleaseMask|ButtonPressMask + |KeyReleaseMask|KeyPressMask|Button1MotionMask, + handleActionEvents, tPtr); + + WMAddNotificationObserver(_notification, tPtr, "_lostOwnership", tPtr); + -void - WMSetTextParser(WMText * tPtr, WMParseAction * parser) { - if (!tPtr) - return; - if (tPtr->monoFont) - return; - tPtr->parser = parser; + tPtr->firstTextBlock = NULL; + tPtr->lastTextBlock = NULL; + tPtr->currentTextBlock = NULL; + tPtr->tpos = 0; + + tPtr->gfxItems = WMCreateArrayBag(4); + + tPtr->parser = NULL; + tPtr->writer = NULL; + + tPtr->sel.x = tPtr->sel.y = 2; + tPtr->sel.w = tPtr->sel.h = 0; + + tPtr->clicked.x = tPtr->clicked.y = 2; + + tPtr->visible.x = tPtr->visible.y = 2; + tPtr->visible.h = tPtr->view->size.height; + tPtr->visible.w = tPtr->view->size.width - 12; + + tPtr->docWidth = 0; + tPtr->docHeight = 0; + tPtr->dBulletPix = WMCreatePixmapFromXPMData(tPtr->view->screen, + default_bullet); + tPtr->db = (Pixmap) NULL; + + tPtr->margins = wmalloc(sizeof(WMRulerMargins)); + tPtr->margins[0].left = tPtr->margins[0].right = tPtr->visible.x; + tPtr->margins[0].body = tPtr->visible.x; + tPtr->margins[0].right = tPtr->visible.w; + + tPtr->flags.nmargins = 1; + tPtr->flags.rulerShown = False; + tPtr->flags.monoFont = !True; + tPtr->flags.focused = False; + tPtr->flags.editable = True; + tPtr->flags.ownsSelection = False; + tPtr->flags.pointerGrabbed = False; + tPtr->flags.buttonHeld = False; + tPtr->flags.waitingForSelection = False; + tPtr->flags.extendSelection = False; + tPtr->flags.rulerShown = False; + tPtr->flags.frozen = False; + tPtr->flags.cursorShown = True; + tPtr->flags.clickPos = 1; + tPtr->flags.ignoreNewLine = False; + tPtr->flags.laidOut = False; + tPtr->flags.prepend = False; + tPtr->flags.relief = WRFlat; + tPtr->flags.alignment = WALeft; + + return tPtr; } -WMParserActions -WMGetTextParserActions(WMText * tPtr) { - WMParserActions null; +void +WMPrependTextStream(WMText *tPtr, char *text) +{ + if(!tPtr) + return; + //check for "{\rtf0" in the text... + //insertRTF + //else + tPtr->flags.prepend = True; + if(text && tPtr->parser) + (tPtr->parser) (tPtr, (void *) text); + else + insertPlainText(tPtr, text); - if (!tPtr) - return null; - return tPtr->funcs; } +void +WMAppendTextStream(WMText *tPtr, char *text) +{ + if(!tPtr) + return; + //check for "{\rtf0" in the text... + //insertRTF + //else + tPtr->flags.prepend = False; + if(text && tPtr->parser) + (tPtr->parser) (tPtr, (void *) text); + else + insertPlainText(tPtr, text); -char * - WMGetTextAll(WMText * tPtr) { - char *text; - int length = 0; - int where = 0; - Paragraph *para; - Chunk *chunk; +} - if (!tPtr) - return NULL; +WMData * +WMGetTextSelected(WMText *tPtr) +{ + WMData *data = NULL; + TextBlock *tb; + + if(!tPtr) + return NULL; - para = tPtr->paragraphs; - while (para) { - chunk = para->chunks; - while (chunk) { - if (chunk->type == ctText) { - if (chunk->text) - length += chunk->chars; - } else { - printf("getting image \n"); - } - chunk = chunk->next; + //tb = tPtr->firstTextBlock; + tb = tPtr->currentTextBlock; + if(!tb) + return NULL; + + data = WMCreateDataWithBytes(tb->text, tb->used); + if(data) + WMSetDataFormat(data, 8); + return data; +} + +void * +WMCreateTextBlockWithObject(WMWidget *w, char *description, WMColor *color, + unsigned short first, unsigned short reserved) +{ + TextBlock *tb; + unsigned short length; + + if(!w || !description || !color) + return NULL; + + tb = wmalloc(sizeof(TextBlock)); + if(!tb) + return NULL; + + length = strlen(description); + tb->text = (char *)wmalloc(length); + memset(tb->text, 0, length); + memcpy(tb->text, description, length); + tb->used = length; + tb->blank = False; + tb->d.widget = w; + tb->color = WMRetainColor(color); + tb->marginN = 0; + tb->allocated = 0; + tb->first = first; + tb->kanji = False; + tb->graphic = True; + tb->underlined = False; + tb->script = 0; + tb->sections = NULL; + tb->nsections = 0; + tb->prior = NULL; + tb->next = NULL; + + return tb; +} + +void * +WMCreateTextBlockWithText(char *text, WMFont *font, WMColor *color, + unsigned short first, unsigned short length) +{ + TextBlock *tb; + + if(!font || !color) + return NULL; + + tb = wmalloc(sizeof(TextBlock)); + if(!tb) + return NULL; + + tb->allocated = reqBlockSize(length); + tb->text = (char *)wmalloc(tb->allocated); + memset(tb->text, 0, tb->allocated); + + if(length < 1|| !text ) { // || *text == '\n') { + *tb->text = ' '; + tb->used = 1; + tb->blank = True; + } else { + memcpy(tb->text, text, length); + tb->used = length; + tb->blank = False; } - if (tPtr->ignoreNewLine) - break; - length += 4; // newlines + tb->d.font = WMRetainFont(font); + tb->color = WMRetainColor(color); + tb->marginN = 0; + tb->first = first; + tb->kanji = False; + tb->graphic = False; + tb->underlined = False; + tb->script = 0; + tb->sections = NULL; + tb->nsections = 0; + tb->prior = NULL; + tb->next = NULL; + return tb; +} - para = para->next; - } +void +WMSetTextBlockProperties(void *vtb, unsigned int first, + unsigned int kanji, unsigned int underlined, int script, + unsigned int marginN) +{ + TextBlock *tb = (TextBlock *) vtb; + if(!tb) + return; - text = wmalloc(length + 1); + tb->first = first; + tb->kanji = kanji; + tb->underlined = underlined; + tb->script = script; + tb->marginN = marginN; +} + +void +WMGetTextBlockProperties(void *vtb, unsigned int *first, + unsigned int *kanji, unsigned int *underlined, int *script, + unsigned int *marginN) +{ + TextBlock *tb = (TextBlock *) vtb; + if(!tb) + return; - para = tPtr->paragraphs; - while (para) { - chunk = para->chunks; - while (chunk) { - if (chunk->type == ctText) { - if (chunk->text) { - snprintf(&text[where], chunk->chars + 1, "%s", chunk->text); - where += chunk->chars; + if(first) *first = tb->first; + if(kanji) *kanji = tb->kanji; + if(underlined) *underlined = tb->underlined; + if(script) *script = tb->script; + if(marginN) *marginN = tb->marginN; +} + + + +void +WMPrependTextBlock(WMText *tPtr, void *vtb) +{ + TextBlock *tb = (TextBlock *)vtb; + + + if(!tPtr || !tb) + return; + + if(tb->graphic) { + WMWidget *w = tb->d.widget; + WMCreateEventHandler(W_VIEW(w), ButtonPressMask, + handleWidgetPress, tb); + //if(W_CLASS(w) != WC_TextField && W_CLASS(w) != WC_Text) { + if(W_CLASS(w) != WC_TextField && + (((W_WidgetType*)(w))->widgetClass) != WC_Text) { + (W_VIEW(w))->attribs.cursor = tPtr->view->screen->defaultCursor; + (W_VIEW(w))->attribFlags |= CWOverrideRedirect | CWCursor; } - } else { - printf("writing image \n"); - } - chunk = chunk->next; + WMPutInBag(tPtr->gfxItems, (void *)tb); + WMRealizeWidget(w); } - if (tPtr->ignoreNewLine) - break; - snprintf(&text[where++], 2, "\n"); - para = para->next; - } - text[where] = '\0'; - return text; + if(!tPtr->lastTextBlock || !tPtr->firstTextBlock) { + tb->next = tb->prior = NULL; + tPtr->lastTextBlock = tPtr->firstTextBlock + = tPtr->currentTextBlock = tb; + return; + } + + tb->next = tPtr->currentTextBlock; + tb->prior = tPtr->currentTextBlock->prior; + if(tPtr->currentTextBlock->prior) + tPtr->currentTextBlock->prior->next = tb; + + tPtr->currentTextBlock->prior = tb; + if(!tb->prior) + tPtr->firstTextBlock = tb; + + tPtr->currentTextBlock = tb; +} + + +void +WMAppendTextBlock(WMText *tPtr, void *vtb) +{ + TextBlock *tb = (TextBlock *)vtb; + + if(!tPtr || !tb) + return; + + if(tb->graphic) { + WMWidget *w = tb->d.widget; + WMCreateEventHandler(W_VIEW(w), ButtonPressMask, + handleWidgetPress, tb); + //if(W_CLASS(w) != WC_TextField && W_CLASS(w) != WC_Text) { + if(W_CLASS(w) != WC_TextField && + (((W_WidgetType*)(w))->widgetClass) != WC_Text) { + (W_VIEW(w))->attribs.cursor = tPtr->view->screen->defaultCursor; + (W_VIEW(w))->attribFlags |= CWOverrideRedirect | CWCursor; + } + WMPutInBag(tPtr->gfxItems, (void *)tb); + WMRealizeWidget(w); + } + + if(!tPtr->lastTextBlock || !tPtr->firstTextBlock) { + tb->next = tb->prior = NULL; + tPtr->lastTextBlock = tPtr->firstTextBlock + = tPtr->currentTextBlock = tb; + return; + } + + tb->next = tPtr->currentTextBlock->next; + tb->prior = tPtr->currentTextBlock; + if(tPtr->currentTextBlock->next) + tPtr->currentTextBlock->next->prior = tb; + + tPtr->currentTextBlock->next = tb; + + if(!tb->next) + tPtr->lastTextBlock = tb; + + tPtr->currentTextBlock = tb; +} + +void * +WMRemoveTextBlock(WMText *tPtr) +{ + TextBlock *tb = NULL; + + if(!tPtr || !tPtr->firstTextBlock || !tPtr->lastTextBlock + || !tPtr->currentTextBlock) { + printf("cannot remove non existent TextBlock!\b"); + return tb; + } + + tb = tPtr->currentTextBlock; + if(tb->graphic) { + WMDeleteEventHandler(W_VIEW(tb->d.widget), ButtonPressMask, + handleWidgetPress, tb); + WMRemoveFromBag(tPtr->gfxItems, (void *)tb); + WMUnmapWidget(tb->d.widget); + } + + if(tPtr->currentTextBlock == tPtr->firstTextBlock) { + if(tPtr->currentTextBlock->next) + tPtr->currentTextBlock->next->prior = NULL; + + tPtr->firstTextBlock = tPtr->currentTextBlock->next; + tPtr->currentTextBlock = tPtr->firstTextBlock; + + } else if(tPtr->currentTextBlock == tPtr->lastTextBlock) { + tPtr->currentTextBlock->prior->next = NULL; + tPtr->lastTextBlock = tPtr->currentTextBlock->prior; + tPtr->currentTextBlock = tPtr->lastTextBlock; + } else { + tPtr->currentTextBlock->prior->next = tPtr->currentTextBlock->next; + tPtr->currentTextBlock->next->prior = tPtr->currentTextBlock->prior; + tPtr->currentTextBlock = tPtr->currentTextBlock->next; + } + + return (void *)tb; +} + +void +WMDestroyTextBlock(WMText *tPtr, void *vtb) +{ + TextBlock *tb = (TextBlock *)vtb; + if(!tPtr || !tb) + return; + + if(tb->graphic) { +return; + WMDestroyWidget(tb->d.widget); + wfree(tb->d.widget); + } else { + WMReleaseFont(tb->d.font); + } + + WMReleaseColor(tb->color); + if(tb->sections && tb->nsections > 0) + wfree(tb->sections); + wfree(tb->text); + wfree(tb); +} + + +void +WMRefreshText(WMText *tPtr, int vpos, int hpos) +{ + //TextBlock *tb; + + if(!tPtr || vpos<0 || hpos<0) + return; + + tPtr->flags.laidOut = False; + layOutDocument(tPtr); + updateScrollers(tPtr); + paintText(tPtr); + + } void - WMSetTextWriter(WMText * tPtr, WMParseAction * writer) { - if (!tPtr) - return; - if (tPtr->monoFont) - return; - tPtr->writer = writer; +WMSetTextForegroundColor(WMText *tPtr, WMColor *color) +{ + if(!tPtr) + return; + + if(color) + tPtr->fgGC = WMColorGC(color); + else + tPtr->fgGC = WMColorGC(WMBlackColor(tPtr->view->screen)); + + WMRefreshText(tPtr, tPtr->vpos, tPtr->hpos); } + +void +WMSetTextBackgroundColor(WMText *tPtr, WMColor *color) +{ + if(!tPtr) + return; + + if(color) { + tPtr->bgGC = WMColorGC(color); + W_SetViewBackgroundColor(tPtr->view, color); + } else { + tPtr->bgGC = WMColorGC(WMWhiteColor(tPtr->view->screen)); + W_SetViewBackgroundColor(tPtr->view, + WMWhiteColor(tPtr->view->screen)); + } + + WMRefreshText(tPtr, tPtr->vpos, tPtr->hpos); +} + +void +WMSetTextRelief(WMText *tPtr, WMReliefType relief) +{ + if(!tPtr) + return; + tPtr->flags.relief = relief; + paintText(tPtr); +} + +void +WMSetTextHasHorizontalScroller(WMText *tPtr, Bool shouldhave) +{ + if(!tPtr) + return; + + if(shouldhave && !tPtr->hS) { + tPtr->hS = WMCreateScroller(tPtr); + (W_VIEW(tPtr->hS))->attribs.cursor = tPtr->view->screen->defaultCursor; + (W_VIEW(tPtr->hS))->attribFlags |= CWOverrideRedirect | CWCursor; + WMSetScrollerArrowsPosition(tPtr->hS, WSAMaxEnd); + WMSetScrollerAction(tPtr->hS, scrollersCallBack, tPtr); + WMRealizeWidget(tPtr->hS); + WMMapWidget(tPtr->hS); + } else if(!shouldhave && tPtr->hS) { + WMUnmapWidget(tPtr->hS); + WMDestroyWidget(tPtr->hS); + tPtr->hS = NULL; + } + + tPtr->hpos = 0; + tPtr->prevHpos = 0; + textDidResize(tPtr->view->delegate, tPtr->view); +} + + +void +WMSetTextHasVerticalScroller(WMText *tPtr, Bool shouldhave) +{ + if(!tPtr) + return; + + if(shouldhave && !tPtr->vS) { + tPtr->vS = WMCreateScroller(tPtr); + (W_VIEW(tPtr->vS))->attribs.cursor = tPtr->view->screen->defaultCursor; + (W_VIEW(tPtr->vS))->attribFlags |= CWOverrideRedirect | CWCursor; + WMSetScrollerArrowsPosition(tPtr->vS, WSAMaxEnd); + WMSetScrollerAction(tPtr->vS, scrollersCallBack, tPtr); + WMRealizeWidget(tPtr->vS); + WMMapWidget(tPtr->vS); + } else if(!shouldhave && tPtr->vS) { + WMUnmapWidget(tPtr->vS); + WMDestroyWidget(tPtr->vS); + tPtr->vS = NULL; + } + + tPtr->vpos = 0; + tPtr->prevVpos = 0; + textDidResize(tPtr->view->delegate, tPtr->view); +} + + + +Bool +WMScrollText(WMText *tPtr, int amount) +{ + Bool scroll=False; + if(!tPtr) + return False; + if(amount == 0 || !tPtr->view->flags.realized) + return False; + + if(amount < 0) { + if(tPtr->vpos > 0) { + if(tPtr->vpos > amount) tPtr->vpos += amount; + else tPtr->vpos=0; + scroll=True; + } } else { + int limit = tPtr->docHeight - tPtr->visible.h; + if(tPtr->vpos < limit) { + if(tPtr->vpos < limit-amount) tPtr->vpos += amount; + else tPtr->vpos = limit; + scroll = True; + } } + + if(scroll && tPtr->vpos != tPtr->prevVpos) { + updateScrollers(tPtr); + paintText(tPtr); + } + tPtr->prevVpos = tPtr->vpos; + return scroll; +} + +Bool +WMPageText(WMText *tPtr, Bool direction) +{ + if(!tPtr) return False; + if(!tPtr->view->flags.realized) return False; + + return WMScrollText(tPtr, direction?tPtr->visible.h:-tPtr->visible.h); +} + + +void +WMSetTextUseMonoFont(WMText *tPtr, Bool mono) +{ + if(!tPtr) + return; + if(mono && tPtr->flags.rulerShown) + ;//WMShowTextRuler(tPtr, False); + + tPtr->flags.monoFont = mono; + WMRefreshText(tPtr, tPtr->vpos, tPtr->hpos); +} + +Bool +WMGetTextUsesMonoFont(WMText *tPtr) +{ + if(!tPtr) + return True; + return tPtr->flags.monoFont; +} + +void +WMSetTextDefaultFont(WMText *tPtr, WMFont *font) +{ + if(!tPtr) + return; + + if(font) + tPtr->dFont = font; + else + tPtr->dFont = WMRetainFont(tPtr->view->screen->normalFont); +} + +WMFont * +WMGetTextDefaultFont(WMText *tPtr) +{ + if(!tPtr) + return NULL; + else + return tPtr->dFont; +} + +void +WMSetTextParser(WMText *tPtr, WMAction *parser) +{ + if(!tPtr) + return; + tPtr->parser = parser; +} + + +void +WMSetTextWriter(WMText *tPtr, WMAction *writer) +{ + if(!tPtr) + return; + tPtr->writer = writer; +} + +int +WMGetTextInsertType(WMText *tPtr) +{ + if(!tPtr) + return 0; + return tPtr->flags.prepend; +} + + +