diff options
Diffstat (limited to 'tk/generic/tkTextDisp.c')
-rw-r--r-- | tk/generic/tkTextDisp.c | 711 |
1 files changed, 433 insertions, 278 deletions
diff --git a/tk/generic/tkTextDisp.c b/tk/generic/tkTextDisp.c index 9d0afc19727..36906b8caba 100644 --- a/tk/generic/tkTextDisp.c +++ b/tk/generic/tkTextDisp.c @@ -18,6 +18,10 @@ #include "tkInt.h" #include "tkText.h" +#ifdef __WIN32__ +#include "tkWinInt.h" +#endif + /* * The following structure describes how to display a range of characters. * The information is generated by scanning all of the tags associated @@ -55,9 +59,10 @@ typedef struct StyleValues { * be NULL). */ int underline; /* Non-zero means draw underline underneath * text. */ - Tk_Uid wrapMode; /* How to handle wrap-around for this tag. - * One of tkTextCharUid, tkTextNoneUid, - * or tkTextWordUid. */ + int elide; /* Non-zero means draw text */ + TkWrapMode wrapMode; /* How to handle wrap-around for this tag. + * One of TEXT_WRAPMODE_CHAR, + * TEXT_WRAPMODE_NONE or TEXT_WRAPMODE_WORD.*/ } StyleValues; /* @@ -98,7 +103,7 @@ typedef struct TextStyle { typedef struct DLine { TkTextIndex index; /* Identifies first character in text * that is displayed on this line. */ - int count; /* Number of characters accounted for by this + int byteCount; /* Number of bytes accounted for by this * display line, including a trailing space * or newline that isn't actually displayed. */ int y; /* Y-position at which line is supposed to @@ -156,12 +161,14 @@ typedef struct DLine { * BOTTOM_LINE - Non-zero means that this was the bottom line * in the window the last time that the window * was laid out. + * IS_DISABLED - This Dline cannot be edited. */ #define HAS_3D_BORDER 1 #define NEW_LAYOUT 2 #define TOP_LINE 4 #define BOTTOM_LINE 8 +#define IS_DISABLED 16 /* * Overall display information for a text widget: @@ -199,7 +206,7 @@ typedef struct TextDInfo { * Information used for scrolling: */ - int newCharOffset; /* Desired x scroll position, measured as the + int newByteOffset; /* Desired x scroll position, measured as the * number of average-size characters off-screen * to the left for a line with no left * margin. */ @@ -222,8 +229,9 @@ typedef struct TextDInfo { * The following information is used to implement scanning: */ - int scanMarkChar; /* Character that was at the left edge of - * the window when the scan started. */ + int scanMarkIndex; /* Byte index of character that was at the + * left edge of the window when the scan + * started. */ int scanMarkX; /* X-position of mouse at time scan started. */ int scanTotalScroll; /* Total scrolling (in screen lines) that has * occurred since scanMarkY was set. */ @@ -254,9 +262,9 @@ typedef struct TextDInfo { */ typedef struct CharInfo { - int numChars; /* Number of characters to display. */ - char chars[4]; /* Characters to display. Actual size - * will be numChars, not 4. THIS MUST BE + int numBytes; /* Number of bytes to display. */ + char chars[4]; /* UTF characters to display. Actual size + * will be numBytes, not 4. THIS MUST BE * THE LAST FIELD IN THE STRUCTURE. */ } CharInfo; @@ -311,6 +319,21 @@ static int CharMeasureProc _ANSI_ARGS_((TkTextDispChunk *chunkPtr, int x)); static void CharUndisplayProc _ANSI_ARGS_((TkText *textPtr, TkTextDispChunk *chunkPtr)); + +/* + Definitions of elided procs. + Compiler can't inline these since we use pointers to these functions. + ElideDisplayProc, ElideUndisplayProc special-cased for speed, + as potentially many elided DLine chunks if large, tag toggle-filled + elided region. +*/ +static void ElideBboxProc _ANSI_ARGS_((TkTextDispChunk *chunkPtr, + int index, int y, int lineHeight, int baseline, + int *xPtr, int *yPtr, int *widthPtr, + int *heightPtr)); +static int ElideMeasureProc _ANSI_ARGS_((TkTextDispChunk *chunkPtr, + int x)); + static void DisplayDLine _ANSI_ARGS_((TkText *textPtr, DLine *dlPtr, DLine *prevPtr, Pixmap pixmap)); static void DisplayLineBackground _ANSI_ARGS_((TkText *textPtr, @@ -331,7 +354,7 @@ static void GetYView _ANSI_ARGS_((Tcl_Interp *interp, static DLine * LayoutDLine _ANSI_ARGS_((TkText *textPtr, TkTextIndex *indexPtr)); static int MeasureChars _ANSI_ARGS_((Tk_Font tkfont, - CONST char *source, int maxChars, int startX, + CONST char *source, int maxBytes, int startX, int maxX, int tabOrigin, int *nextXPtr)); static void MeasureUp _ANSI_ARGS_((TkText *textPtr, TkTextIndex *srcPtr, int distance, @@ -381,14 +404,14 @@ TkTextCreateDInfo(textPtr) dInfoPtr->scrollGC = Tk_GetGC(textPtr->tkwin, GCGraphicsExposures, &gcValues); dInfoPtr->topOfEof = 0; - dInfoPtr->newCharOffset = 0; + dInfoPtr->newByteOffset = 0; dInfoPtr->curPixelOffset = 0; dInfoPtr->maxLength = 0; dInfoPtr->xScrollFirst = -1; dInfoPtr->xScrollLast = -1; dInfoPtr->yScrollFirst = -1; dInfoPtr->yScrollLast = -1; - dInfoPtr->scanMarkChar = 0; + dInfoPtr->scanMarkIndex = 0; dInfoPtr->scanMarkX = 0; dInfoPtr->scanTotalScroll = 0; dInfoPtr->scanMarkY = 0; @@ -479,7 +502,7 @@ GetStyle(textPtr, indexPtr) int borderPrio, borderWidthPrio, reliefPrio, bgStipplePrio; int fgPrio, fontPrio, fgStipplePrio; - int underlinePrio, justifyPrio, offsetPrio; + int underlinePrio, elidePrio, justifyPrio, offsetPrio; int lMargin1Prio, lMargin2Prio, rMarginPrio; int spacing1Prio, spacing2Prio, spacing3Prio; int overstrikePrio, tabPrio, wrapPrio; @@ -494,7 +517,7 @@ GetStyle(textPtr, indexPtr) tagPtrs = TkBTreeGetTags(indexPtr, &numTags); borderPrio = borderWidthPrio = reliefPrio = bgStipplePrio = -1; fgPrio = fontPrio = fgStipplePrio = -1; - underlinePrio = justifyPrio = offsetPrio = -1; + underlinePrio = elidePrio = justifyPrio = offsetPrio = -1; lMargin1Prio = lMargin2Prio = rMarginPrio = -1; spacing1Prio = spacing2Prio = spacing3Prio = -1; overstrikePrio = tabPrio = wrapPrio = -1; @@ -508,6 +531,7 @@ GetStyle(textPtr, indexPtr) styleValues.spacing3 = textPtr->spacing3; styleValues.tabArrayPtr = textPtr->tabArrayPtr; styleValues.wrapMode = textPtr->wrapMode; + styleValues.elide = 0; for (i = 0 ; i < numTags; i++) { tagPtr = tagPtrs[i]; @@ -612,7 +636,12 @@ GetStyle(textPtr, indexPtr) styleValues.underline = tagPtr->underline; underlinePrio = tagPtr->priority; } - if ((tagPtr->wrapMode != NULL) + if ((tagPtr->elideString != NULL) + && (tagPtr->priority > elidePrio)) { + styleValues.elide = tagPtr->elide; + elidePrio = tagPtr->priority; + } + if ((tagPtr->wrapMode != TEXT_WRAPMODE_NULL) && (tagPtr->priority > wrapPrio)) { styleValues.wrapMode = tagPtr->wrapMode; wrapPrio = tagPtr->priority; @@ -648,22 +677,20 @@ GetStyle(textPtr, indexPtr) gcValues.fill_style = FillStippled; mask |= GCStipple|GCFillStyle; } - stylePtr->bgGC = Tk_GetGCColor(textPtr->tkwin, mask, &gcValues, - Tk_3DBorderColor(styleValues.border), - NULL); + stylePtr->bgGC = Tk_GetGC(textPtr->tkwin, mask, &gcValues); } else { stylePtr->bgGC = None; } - mask = GCForeground|GCFont; - gcValues.foreground = styleValues.fgColor->pixel; + mask = GCFont; gcValues.font = Tk_FontId(styleValues.tkfont); + mask |= GCForeground; + gcValues.foreground = styleValues.fgColor->pixel; if (styleValues.fgStipple != None) { gcValues.stipple = styleValues.fgStipple; gcValues.fill_style = FillStippled; mask |= GCStipple|GCFillStyle; } - stylePtr->fgGC = Tk_GetGCColor(textPtr->tkwin, mask, &gcValues, - styleValues.fgColor, NULL); + stylePtr->fgGC = Tk_GetGC(textPtr->tkwin, mask, &gcValues); stylePtr->sValuePtr = (StyleValues *) Tcl_GetHashKey(&textPtr->dInfoPtr->styleTable, hPtr); stylePtr->hPtr = hPtr; @@ -701,7 +728,9 @@ FreeStyle(textPtr, stylePtr) if (stylePtr->bgGC != None) { Tk_FreeGC(textPtr->display, stylePtr->bgGC); } - Tk_FreeGC(textPtr->display, stylePtr->fgGC); + if (stylePtr->fgGC != None) { + Tk_FreeGC(textPtr->display, stylePtr->fgGC); + } Tcl_DeleteHashEntry(stylePtr->hPtr); ckfree((char *) stylePtr); } @@ -742,16 +771,18 @@ LayoutDLine(textPtr, indexPtr) * point, if any. */ TkTextIndex breakIndex; /* Index of first character in * breakChunkPtr. */ - int breakCharOffset; /* Character within breakChunkPtr just - * to right of best break point. */ + int breakByteOffset; /* Byte offset of character within + * breakChunkPtr just to right of best + * break point. */ int noCharsYet; /* Non-zero means that no characters * have been placed on the line yet. */ int justify; /* How to justify line: taken from - * style for first character in line. */ + * style for the first character in + * line. */ int jIndent; /* Additional indentation (beyond * margins) due to justification. */ int rMargin; /* Right margin width for line. */ - Tk_Uid wrapMode; /* Wrap mode to use for this line. */ + TkWrapMode wrapMode; /* Wrap mode to use for this line. */ int x = 0, maxX = 0; /* Initializations needed only to * stop compiler warnings. */ int wholeLine; /* Non-zero means this display line @@ -761,17 +792,18 @@ LayoutDLine(textPtr, indexPtr) * contains a tab. */ TkTextDispChunk *tabChunkPtr; /* Pointer to the chunk containing * the previous tab stop. */ - int maxChars; /* Maximum number of characters to + int maxBytes; /* Maximum number of bytes to * include in this chunk. */ - TkTextTabArray *tabArrayPtr; /* Tab stops for line; taken from - * style for first character on line. */ + TkTextTabArray *tabArrayPtr; /* Tab stops for line; taken from + * style for the first character on + * line. */ int tabSize; /* Number of pixels consumed by current * tab stop. */ TkTextDispChunk *lastCharChunkPtr; /* Pointer to last chunk in display - * lines with numChars > 0. Used to + * lines with numBytes > 0. Used to * drop 0-sized chunks from the end * of the line. */ - int offset, ascent, descent, code; + int byteOffset, ascent, descent, code, elide, elidesize; StyleValues *sValuePtr; /* @@ -780,7 +812,7 @@ LayoutDLine(textPtr, indexPtr) dlPtr = (DLine *) ckalloc(sizeof(DLine)); dlPtr->index = *indexPtr; - dlPtr->count = 0; + dlPtr->byteCount = 0; dlPtr->y = 0; dlPtr->oldY = -1; dlPtr->height = 0; @@ -790,6 +822,37 @@ LayoutDLine(textPtr, indexPtr) dlPtr->flags = NEW_LAYOUT; /* + * Special case entirely elide line as there may be 1000s or more + */ + elide = TkTextIsElided(textPtr, indexPtr); /* save a malloc */ + if (elide && indexPtr->byteIndex==0) { + maxBytes = 0; + for (segPtr = indexPtr->linePtr->segPtr; + elide && (segPtr != NULL); + segPtr = segPtr->nextPtr) { + if ((elidesize = segPtr->size) > 0) { + maxBytes += elidesize; + /* + * If have we have a tag toggle, there is a chance + * that invisibility state changed, so bail out + */ + } else if ((segPtr->typePtr == &tkTextToggleOffType) + || (segPtr->typePtr == &tkTextToggleOnType)) { + if (segPtr->body.toggle.tagPtr->elideString != NULL) { + elide = (segPtr->typePtr == &tkTextToggleOffType) + ^ segPtr->body.toggle.tagPtr->elide; + } + } + } + + if (elide) { + dlPtr->byteCount = maxBytes; + dlPtr->spaceAbove = dlPtr->spaceBelow = dlPtr->length = 0; + return dlPtr; + } + } + + /* * Each iteration of the loop below creates one TkTextDispChunk for * the new display line. The line will always have at least one * chunk (for the newline character at the end, if there's nothing @@ -800,14 +863,15 @@ LayoutDLine(textPtr, indexPtr) lastChunkPtr = NULL; chunkPtr = NULL; noCharsYet = 1; + elide = 0; breakChunkPtr = NULL; - breakCharOffset = 0; + breakByteOffset = 0; justify = TK_JUSTIFY_LEFT; tabIndex = -1; tabChunkPtr = NULL; tabArrayPtr = NULL; rMargin = 0; - wrapMode = tkTextCharUid; + wrapMode = TEXT_WRAPMODE_CHAR; tabSize = 0; lastCharChunkPtr = NULL; @@ -817,16 +881,48 @@ LayoutDLine(textPtr, indexPtr) * with zero size (such as the insertion cursor's mark). */ - for (offset = curIndex.charIndex, segPtr = curIndex.linePtr->segPtr; - (offset > 0) && (offset >= segPtr->size); - offset -= segPtr->size, segPtr = segPtr->nextPtr) { + for (byteOffset = curIndex.byteIndex, segPtr = curIndex.linePtr->segPtr; + (byteOffset > 0) && (byteOffset >= segPtr->size); + byteOffset -= segPtr->size, segPtr = segPtr->nextPtr) { /* Empty loop body. */ } while (segPtr != NULL) { + /* + * Every line still gets at least one chunk due to expectations + * in the rest of the code, but we are able to skip elided portions + * of the line quickly. + * If current chunk is elided and last chunk was too, coalese + */ + if (elide && (lastChunkPtr != NULL) + && (lastChunkPtr->displayProc == NULL /*ElideDisplayProc*/)) { + if ((elidesize = segPtr->size - byteOffset) > 0) { + curIndex.byteIndex += elidesize; + lastChunkPtr->numBytes += elidesize; + breakByteOffset = lastChunkPtr->breakIndex = lastChunkPtr->numBytes; + /* + * If have we have a tag toggle, there is a chance + * that invisibility state changed, so bail out + */ + } else if ((segPtr->typePtr == &tkTextToggleOffType) + || (segPtr->typePtr == &tkTextToggleOnType)) { + if (segPtr->body.toggle.tagPtr->elideString != NULL) { + elide = (segPtr->typePtr == &tkTextToggleOffType) + ^ segPtr->body.toggle.tagPtr->elide; + } + } + + byteOffset = 0; + segPtr = segPtr->nextPtr; + if (segPtr == NULL && chunkPtr != NULL) { + ckfree((char *) chunkPtr); + } + continue; + } + if (segPtr->typePtr->layoutProc == NULL) { segPtr = segPtr->nextPtr; - offset = 0; + byteOffset = 0; continue; } if (chunkPtr == NULL) { @@ -834,6 +930,7 @@ LayoutDLine(textPtr, indexPtr) chunkPtr->nextPtr = NULL; } chunkPtr->stylePtr = GetStyle(textPtr, &curIndex); + elide = chunkPtr->stylePtr->sValuePtr->elide; /* * Save style information such as justification and indentation, @@ -846,11 +943,11 @@ LayoutDLine(textPtr, indexPtr) justify = chunkPtr->stylePtr->sValuePtr->justify; rMargin = chunkPtr->stylePtr->sValuePtr->rMargin; wrapMode = chunkPtr->stylePtr->sValuePtr->wrapMode; - x = ((curIndex.charIndex == 0) + x = ((curIndex.byteIndex == 0) ? chunkPtr->stylePtr->sValuePtr->lMargin1 : chunkPtr->stylePtr->sValuePtr->lMargin2); - if (wrapMode == tkTextNoneUid) { - maxX = INT_MAX; + if (wrapMode == TEXT_WRAPMODE_NONE) { + maxX = -1; } else { maxX = textPtr->dInfoPtr->maxX - textPtr->dInfoPtr->x - rMargin; @@ -866,24 +963,37 @@ LayoutDLine(textPtr, indexPtr) */ gotTab = 0; - maxChars = segPtr->size - offset; - if (justify == TK_JUSTIFY_LEFT) { + maxBytes = segPtr->size - byteOffset; + if (!elide && justify == TK_JUSTIFY_LEFT) { if (segPtr->typePtr == &tkTextCharType) { char *p; - for (p = segPtr->body.chars + offset; *p != 0; p++) { + for (p = segPtr->body.chars + byteOffset; *p != 0; p++) { if (*p == '\t') { - maxChars = (p + 1 - segPtr->body.chars) - offset; + maxBytes = (p + 1 - segPtr->body.chars) - byteOffset; gotTab = 1; break; } } } } - chunkPtr->x = x; + if (elide && maxBytes) { + /* don't free style here, as other code expects to be able to do that */ + /*breakByteOffset =*/ chunkPtr->breakIndex = chunkPtr->numBytes = maxBytes; + chunkPtr->width = 0; + chunkPtr->minAscent = chunkPtr->minDescent = chunkPtr->minHeight = 0; + + /* would just like to point to canonical empty chunk */ + chunkPtr->displayProc = (Tk_ChunkDisplayProc *) NULL; + chunkPtr->undisplayProc = (Tk_ChunkUndisplayProc *) NULL; + chunkPtr->measureProc = ElideMeasureProc; + chunkPtr->bboxProc = ElideBboxProc; + + code = 1; + } else code = (*segPtr->typePtr->layoutProc)(textPtr, &curIndex, segPtr, - offset, maxX-tabSize, maxChars, noCharsYet, wrapMode, + byteOffset, maxX-tabSize, maxBytes, noCharsYet, wrapMode, chunkPtr); if (code <= 0) { FreeStyle(textPtr, chunkPtr->stylePtr); @@ -894,7 +1004,7 @@ LayoutDLine(textPtr, indexPtr) */ segPtr = segPtr->nextPtr; - offset = 0; + byteOffset = 0; continue; } @@ -908,7 +1018,7 @@ LayoutDLine(textPtr, indexPtr) } break; } - if (chunkPtr->numChars > 0) { + if (chunkPtr->numBytes > 0) { noCharsYet = 0; lastCharChunkPtr = chunkPtr; } @@ -920,11 +1030,11 @@ LayoutDLine(textPtr, indexPtr) lastChunkPtr = chunkPtr; x += chunkPtr->width; if (chunkPtr->breakIndex > 0) { - breakCharOffset = chunkPtr->breakIndex; + breakByteOffset = chunkPtr->breakIndex; breakIndex = curIndex; breakChunkPtr = chunkPtr; } - if (chunkPtr->numChars != maxChars) { + if (chunkPtr->numBytes != maxBytes) { break; } @@ -943,16 +1053,17 @@ LayoutDLine(textPtr, indexPtr) tabIndex++; tabChunkPtr = chunkPtr; tabSize = SizeOfTab(textPtr, tabArrayPtr, tabIndex, x, maxX); - if (tabSize >= (maxX - x)) { + if ((maxX >= 0) && (tabSize >= maxX - x)) { break; } } - curIndex.charIndex += chunkPtr->numChars; - offset += chunkPtr->numChars; - if (offset >= segPtr->size) { - offset = 0; + curIndex.byteIndex += chunkPtr->numBytes; + byteOffset += chunkPtr->numBytes; + if (byteOffset >= segPtr->size) { + byteOffset = 0; segPtr = segPtr->nextPtr; } + chunkPtr = NULL; } if (noCharsYet) { @@ -976,10 +1087,10 @@ LayoutDLine(textPtr, indexPtr) */ breakChunkPtr = lastCharChunkPtr; - breakCharOffset = breakChunkPtr->numChars; + breakByteOffset = breakChunkPtr->numBytes; } if ((breakChunkPtr != NULL) && ((lastChunkPtr != breakChunkPtr) - || (breakCharOffset != lastChunkPtr->numChars))) { + || (breakByteOffset != lastChunkPtr->numBytes))) { while (1) { chunkPtr = breakChunkPtr->nextPtr; if (chunkPtr == NULL) { @@ -990,17 +1101,18 @@ LayoutDLine(textPtr, indexPtr) (*chunkPtr->undisplayProc)(textPtr, chunkPtr); ckfree((char *) chunkPtr); } - if (breakCharOffset != breakChunkPtr->numChars) { + if (breakByteOffset != breakChunkPtr->numBytes) { (*breakChunkPtr->undisplayProc)(textPtr, breakChunkPtr); - segPtr = TkTextIndexToSeg(&breakIndex, &offset); + segPtr = TkTextIndexToSeg(&breakIndex, &byteOffset); (*segPtr->typePtr->layoutProc)(textPtr, &breakIndex, - segPtr, offset, maxX, breakCharOffset, 0, + segPtr, byteOffset, maxX, breakByteOffset, 0, wrapMode, breakChunkPtr); } lastChunkPtr = breakChunkPtr; wholeLine = 0; } + /* * Make tab adjustments for the last tab stop, if there is one. */ @@ -1011,7 +1123,7 @@ LayoutDLine(textPtr, indexPtr) /* * Make one more pass over the line to recompute various things - * like its height, length, and total number of characters. Also + * like its height, length, and total number of bytes. Also * modify the x-locations of chunks to reflect justification. * If we're not wrapping, I'm not sure what is the best way to * handle left and center justification: should the total length, @@ -1022,7 +1134,7 @@ LayoutDLine(textPtr, indexPtr) * what is implemented below. */ - if (wrapMode == tkTextNoneUid) { + if (wrapMode == TEXT_WRAPMODE_NONE) { maxX = textPtr->dInfoPtr->maxX - textPtr->dInfoPtr->x - rMargin; } dlPtr->length = lastChunkPtr->x + lastChunkPtr->width; @@ -1037,7 +1149,7 @@ LayoutDLine(textPtr, indexPtr) for (chunkPtr = dlPtr->chunkPtr; chunkPtr != NULL; chunkPtr = chunkPtr->nextPtr) { chunkPtr->x += jIndent; - dlPtr->count += chunkPtr->numChars; + dlPtr->byteCount += chunkPtr->numBytes; if (chunkPtr->minAscent > ascent) { ascent = chunkPtr->minAscent; } @@ -1060,7 +1172,7 @@ LayoutDLine(textPtr, indexPtr) dlPtr->baseline = ascent + (dlPtr->height - ascent - descent)/2; } sValuePtr = dlPtr->chunkPtr->stylePtr->sValuePtr; - if (dlPtr->index.charIndex == 0) { + if (dlPtr->index.byteIndex == 0) { dlPtr->spaceAbove = sValuePtr->spacing1; } else { dlPtr->spaceAbove = sValuePtr->spacing2 - sValuePtr->spacing2/2; @@ -1213,7 +1325,7 @@ UpdateDisplayInfo(textPtr) * index within the line. */ - if (index.charIndex == dlPtr->index.charIndex) { + if (index.byteIndex == dlPtr->index.byteIndex) { /* * Case (a) -- can use existing display line as-is. */ @@ -1224,7 +1336,7 @@ UpdateDisplayInfo(textPtr) } goto lineOK; } - if (index.charIndex < dlPtr->index.charIndex) { + if (index.byteIndex < dlPtr->index.byteIndex) { goto makeNewDLine; } @@ -1251,7 +1363,7 @@ UpdateDisplayInfo(textPtr) lineOK: dlPtr->y = y; y += dlPtr->height; - TkTextIndexForwChars(&index, dlPtr->count, &index); + TkTextIndexForwBytes(&index, dlPtr->byteCount, &index); prevPtr = dlPtr; dlPtr = dlPtr->nextPtr; @@ -1302,7 +1414,7 @@ UpdateDisplayInfo(textPtr) */ if (y < maxY) { - int lineNum, spaceLeft, charsToCount; + int lineNum, spaceLeft, bytesToCount; DLine *lowestPtr; /* @@ -1315,22 +1427,24 @@ UpdateDisplayInfo(textPtr) spaceLeft = maxY - y; lineNum = TkBTreeLineIndex(dInfoPtr->dLinePtr->index.linePtr); - charsToCount = dInfoPtr->dLinePtr->index.charIndex; - if (charsToCount == 0) { - charsToCount = INT_MAX; + bytesToCount = dInfoPtr->dLinePtr->index.byteIndex; + if (bytesToCount == 0) { + bytesToCount = INT_MAX; lineNum--; } for ( ; (lineNum >= 0) && (spaceLeft > 0); lineNum--) { index.linePtr = TkBTreeFindLine(textPtr->tree, lineNum); - index.charIndex = 0; + index.byteIndex = 0; lowestPtr = NULL; + do { dlPtr = LayoutDLine(textPtr, &index); dlPtr->nextPtr = lowestPtr; lowestPtr = dlPtr; - TkTextIndexForwChars(&index, dlPtr->count, &index); - charsToCount -= dlPtr->count; - } while ((charsToCount > 0) + if (dlPtr->length == 0 && dlPtr->height == 0) { bytesToCount--; break; } /* elide */ + TkTextIndexForwBytes(&index, dlPtr->byteCount, &index); + bytesToCount -= dlPtr->byteCount; + } while ((bytesToCount > 0) && (index.linePtr == lowestPtr->index.linePtr)); /* @@ -1357,7 +1471,7 @@ UpdateDisplayInfo(textPtr) } } FreeDLines(textPtr, lowestPtr, (DLine *) NULL, 0); - charsToCount = INT_MAX; + bytesToCount = INT_MAX; } /* @@ -1444,13 +1558,13 @@ UpdateDisplayInfo(textPtr) } maxOffset = (dInfoPtr->maxLength - (dInfoPtr->maxX - dInfoPtr->x) + textPtr->charWidth - 1)/textPtr->charWidth; - if (dInfoPtr->newCharOffset > maxOffset) { - dInfoPtr->newCharOffset = maxOffset; + if (dInfoPtr->newByteOffset > maxOffset) { + dInfoPtr->newByteOffset = maxOffset; } - if (dInfoPtr->newCharOffset < 0) { - dInfoPtr->newCharOffset = 0; + if (dInfoPtr->newByteOffset < 0) { + dInfoPtr->newByteOffset = 0; } - pixelOffset = dInfoPtr->newCharOffset * textPtr->charWidth; + pixelOffset = dInfoPtr->newByteOffset * textPtr->charWidth; if (pixelOffset != dInfoPtr->curPixelOffset) { dInfoPtr->curPixelOffset = pixelOffset; for (dlPtr = dInfoPtr->dLinePtr; dlPtr != NULL; @@ -1557,6 +1671,8 @@ DisplayDLine(textPtr, dlPtr, prevPtr, pixmap) Display *display; int height, x; + if (dlPtr->chunkPtr == NULL) return; + /* * First, clear the area of the line to the background color for the * text widget. @@ -1580,11 +1696,7 @@ DisplayDLine(textPtr, dlPtr, prevPtr, pixmap) * to its left. */ -#ifndef __WIN32__ - /* CYGNUS LOCAL: On Windows, display the cursor even for disabled - text widgets. */ - if (textPtr->state == tkNormalUid) { -#endif /* __WIN32__ */ + if (textPtr->state == TK_STATE_NORMAL) { for (chunkPtr = dlPtr->chunkPtr; (chunkPtr != NULL); chunkPtr = chunkPtr->nextPtr) { x = chunkPtr->x + dInfoPtr->x - dInfoPtr->curPixelOffset; @@ -1595,9 +1707,7 @@ DisplayDLine(textPtr, dlPtr, prevPtr, pixmap) dlPtr->y + dlPtr->spaceAbove); } } -#ifndef __WIN32__ } -#endif /* __WIN32__ */ /* * Make yet another pass through all of the chunks to redraw all of @@ -1629,12 +1739,16 @@ DisplayDLine(textPtr, dlPtr, prevPtr, pixmap) * something is off to the right). */ + if (chunkPtr->displayProc != NULL) (*chunkPtr->displayProc)(chunkPtr, -chunkPtr->width, dlPtr->spaceAbove, dlPtr->height - dlPtr->spaceAbove - dlPtr->spaceBelow, dlPtr->baseline - dlPtr->spaceAbove, display, pixmap, dlPtr->y + dlPtr->spaceAbove); } else { + /* don't call if elide. This tax ok since not very many visible DLine's in + an area, but potentially many elide ones */ + if (chunkPtr->displayProc != NULL) (*chunkPtr->displayProc)(chunkPtr, x, dlPtr->spaceAbove, dlPtr->height - dlPtr->spaceAbove - dlPtr->spaceBelow, dlPtr->baseline - dlPtr->spaceAbove, display, pixmap, @@ -1723,6 +1837,7 @@ DisplayLineBackground(textPtr, dlPtr, prevPtr, pixmap) StyleValues *sValuePtr; Display *display; + /* * Pass 1: scan through dlPtr from left to right. For each range of * chunks with the same style, draw the main background for the style @@ -1796,7 +1911,7 @@ DisplayLineBackground(textPtr, dlPtr, prevPtr, pixmap) rightX = maxX; } chunkPtr2 = NULL; - if (prevPtr != NULL) { + if (prevPtr != NULL && prevPtr->chunkPtr != NULL) { /* * Find the chunk in the previous line that covers leftX. */ @@ -1917,7 +2032,7 @@ DisplayLineBackground(textPtr, dlPtr, prevPtr, pixmap) rightX = maxX; } chunkPtr2 = NULL; - if (dlPtr->nextPtr != NULL) { + if (dlPtr->nextPtr != NULL && dlPtr->nextPtr->chunkPtr != NULL) { /* * Find the chunk in the previous line that covers leftX. */ @@ -2243,17 +2358,19 @@ DisplayText(clientData) Tk_Height(textPtr->tkwin) - 2*textPtr->highlightWidth, textPtr->borderWidth, textPtr->relief); if (textPtr->highlightWidth != 0) { - GC gc; + GC fgGC, bgGC; + bgGC = Tk_GCForColor(textPtr->highlightBgColorPtr, + Tk_WindowId(textPtr->tkwin)); if (textPtr->flags & GOT_FOCUS) { - gc = Tk_GCForColor(textPtr->highlightColorPtr, + fgGC = Tk_GCForColor(textPtr->highlightColorPtr, Tk_WindowId(textPtr->tkwin)); + TkpDrawHighlightBorder(textPtr->tkwin, fgGC, bgGC, + textPtr->highlightWidth, Tk_WindowId(textPtr->tkwin)); } else { - gc = Tk_GCForColor(textPtr->highlightBgColorPtr, - Tk_WindowId(textPtr->tkwin)); + TkpDrawHighlightBorder(textPtr->tkwin, bgGC, bgGC, + textPtr->highlightWidth, Tk_WindowId(textPtr->tkwin)); } - Tk_DrawFocusHighlight(textPtr->tkwin, gc, textPtr->highlightWidth, - Tk_WindowId(textPtr->tkwin)); } borders = textPtr->borderWidth + textPtr->highlightWidth; if (textPtr->padY > 0) { @@ -2308,6 +2425,7 @@ DisplayText(clientData) for (prevPtr = NULL, dlPtr = textPtr->dInfoPtr->dLinePtr; (dlPtr != NULL) && (dlPtr->y < dInfoPtr->maxY); prevPtr = dlPtr, dlPtr = dlPtr->nextPtr) { + if (dlPtr->chunkPtr == NULL) continue; if (dlPtr->oldY != dlPtr->y) { if (tkTextDebug) { char string[TK_POS_CHARS]; @@ -2324,6 +2442,7 @@ DisplayText(clientData) dlPtr->oldY = dlPtr->y; dlPtr->flags &= ~NEW_LAYOUT; } + /*prevPtr = dlPtr;*/ } Tk_FreePixmap(Tk_Display(textPtr->tkwin), pixmap); } @@ -2600,7 +2719,7 @@ TkTextChanged(textPtr, index1Ptr, index2Ptr) */ rounded = *index1Ptr; - rounded.charIndex = 0; + rounded.byteIndex = 0; firstPtr = FindDLine(dInfoPtr->dLinePtr, &rounded); if (firstPtr == NULL) { return; @@ -2676,7 +2795,7 @@ TkTextRedrawTag(textPtr, index1Ptr, index2Ptr, tagPtr, withTag) */ if (index2Ptr == NULL) { - index2Ptr = TkTextMakeIndex(textPtr->tree, + index2Ptr = TkTextMakeByteIndex(textPtr->tree, TkBTreeNumLines(textPtr->tree), 0, &endOfText); } @@ -2730,13 +2849,13 @@ TkTextRedrawTag(textPtr, index1Ptr, index2Ptr, tagPtr, withTag) * previous character. */ - if (curIndexPtr->charIndex == 0) { + if (curIndexPtr->byteIndex == 0) { dlPtr = FindDLine(dlPtr, curIndexPtr); } else { TkTextIndex tmp; tmp = *curIndexPtr; - tmp.charIndex -= 1; + tmp.byteIndex -= 1; dlPtr = FindDLine(dlPtr, &tmp); } if (dlPtr == NULL) { @@ -2755,7 +2874,7 @@ TkTextRedrawTag(textPtr, index1Ptr, index2Ptr, tagPtr, withTag) } endPtr = FindDLine(dlPtr, endIndexPtr); if ((endPtr != NULL) && (endPtr->index.linePtr == endIndexPtr->linePtr) - && (endPtr->index.charIndex < endIndexPtr->charIndex)) { + && (endPtr->index.byteIndex < endIndexPtr->byteIndex)) { endPtr = endPtr->nextPtr; } @@ -2867,7 +2986,7 @@ TkTextRelayoutWindow(textPtr) * or options could change the way lines wrap. */ - if (textPtr->topIndex.charIndex != 0) { + if (textPtr->topIndex.byteIndex != 0) { MeasureUp(textPtr, &textPtr->topIndex, 0, &textPtr->topIndex); } @@ -2934,7 +3053,7 @@ TkTextSetYView(textPtr, indexPtr, pickPlace) * without redisplaying it all. */ - if (indexPtr->charIndex == 0) { + if (indexPtr->byteIndex == 0) { textPtr->topIndex = *indexPtr; } else { MeasureUp(textPtr, indexPtr, 0, &textPtr->topIndex); @@ -2962,7 +3081,7 @@ TkTextSetYView(textPtr, indexPtr, pickPlace) dlPtr = NULL; } else if ((dlPtr->index.linePtr == indexPtr->linePtr) - && (dlPtr->index.charIndex <= indexPtr->charIndex)) { + && (dlPtr->index.byteIndex <= indexPtr->byteIndex)) { return; } } @@ -3060,37 +3179,37 @@ MeasureUp(textPtr, srcPtr, distance, dstPtr) TkTextIndex *dstPtr; /* Index to fill in with result. */ { int lineNum; /* Number of current line. */ - int charsToCount; /* Maximum number of characters to measure - * in current line. */ + int bytesToCount; /* Maximum number of bytes to measure in + * current line. */ TkTextIndex bestIndex; /* Best candidate seen so far for result. */ TkTextIndex index; DLine *dlPtr, *lowestPtr; int noBestYet; /* 1 means bestIndex hasn't been set. */ noBestYet = 1; - charsToCount = srcPtr->charIndex + 1; + bytesToCount = srcPtr->byteIndex + 1; index.tree = srcPtr->tree; for (lineNum = TkBTreeLineIndex(srcPtr->linePtr); lineNum >= 0; lineNum--) { /* * Layout an entire text line (potentially > 1 display line). * For the first line, which contains srcPtr, only layout the - * part up through srcPtr (charsToCount is non-infinite to + * part up through srcPtr (bytesToCount is non-infinite to * accomplish this). Make a list of all the display lines * in backwards order (the lowest DLine on the screen is first * in the list). */ index.linePtr = TkBTreeFindLine(srcPtr->tree, lineNum); - index.charIndex = 0; + index.byteIndex = 0; lowestPtr = NULL; do { dlPtr = LayoutDLine(textPtr, &index); dlPtr->nextPtr = lowestPtr; lowestPtr = dlPtr; - TkTextIndexForwChars(&index, dlPtr->count, &index); - charsToCount -= dlPtr->count; - } while ((charsToCount > 0) && (index.linePtr == dlPtr->index.linePtr)); + TkTextIndexForwBytes(&index, dlPtr->byteCount, &index); + bytesToCount -= dlPtr->byteCount; + } while ((bytesToCount > 0) && (index.linePtr == dlPtr->index.linePtr)); /* * Scan through the display lines to see if we've covered enough @@ -3117,7 +3236,7 @@ MeasureUp(textPtr, srcPtr, distance, dstPtr) if (distance < 0) { return; } - charsToCount = INT_MAX; /* Consider all chars. in next line. */ + bytesToCount = INT_MAX; /* Consider all chars. in next line. */ } /* @@ -3125,7 +3244,7 @@ MeasureUp(textPtr, srcPtr, distance, dstPtr) * in the text. */ - TkTextMakeIndex(textPtr->tree, 0, 0, dstPtr); + TkTextMakeByteIndex(textPtr->tree, 0, 0, dstPtr); } /* @@ -3157,7 +3276,7 @@ TkTextSeeCmd(textPtr, interp, argc, argv) { TextDInfo *dInfoPtr = textPtr->dInfoPtr; TkTextIndex index; - int x, y, width, height, lineWidth, charCount, oneThird, delta; + int x, y, width, height, lineWidth, byteCount, oneThird, delta; DLine *dlPtr; TkTextDispChunk *chunkPtr; @@ -3166,7 +3285,6 @@ TkTextSeeCmd(textPtr, interp, argc, argv) argv[0], " see index\"", (char *) NULL); return TCL_ERROR; } - if (TkTextGetIndex(interp, textPtr, argv[2], &index) != TCL_OK) { return TCL_ERROR; } @@ -3203,27 +3321,12 @@ TkTextSeeCmd(textPtr, interp, argc, argv) */ dlPtr = FindDLine(dInfoPtr->dLinePtr, &index); - - /* - * CYGNUS LOCAL: I can sometimes get FindDLine to return a null - * pointer. I have not been able to find a simple test case, - * it happens in Gdbtk when you change the font for the debug window. - * Since you should not have to catch the see command, I have made - * the error silent... - */ - - if (dlPtr == NULL) { - Tcl_AppendResult(interp, "got a null dlinePtr from FindDLine in the see command.", - (char *) NULL); - return TCL_OK; - } - - charCount = index.charIndex - dlPtr->index.charIndex; - for (chunkPtr = dlPtr->chunkPtr; ; chunkPtr = chunkPtr->nextPtr) { - if (charCount < chunkPtr->numChars) { + byteCount = index.byteIndex - dlPtr->index.byteIndex; + for (chunkPtr = dlPtr->chunkPtr; chunkPtr!=NULL ; chunkPtr = chunkPtr->nextPtr) { + if (byteCount < chunkPtr->numBytes) { break; } - charCount -= chunkPtr->numChars; + byteCount -= chunkPtr->numBytes; } /* @@ -3231,7 +3334,8 @@ TkTextSeeCmd(textPtr, interp, argc, argv) * the character within the chunk. */ - (*chunkPtr->bboxProc)(chunkPtr, charCount, dlPtr->y + dlPtr->spaceAbove, + if (chunkPtr!=NULL) { /* chunkPtr==NULL iff trying to see in elided region */ + (*chunkPtr->bboxProc)(chunkPtr, byteCount, dlPtr->y + dlPtr->spaceAbove, dlPtr->height - dlPtr->spaceAbove - dlPtr->spaceBelow, dlPtr->baseline - dlPtr->spaceAbove, &x, &y, &width, &height); @@ -3239,24 +3343,24 @@ TkTextSeeCmd(textPtr, interp, argc, argv) oneThird = lineWidth/3; if (delta < 0) { if (delta < -oneThird) { - dInfoPtr->newCharOffset = (x - lineWidth/2)/textPtr->charWidth; + dInfoPtr->newByteOffset = (x - lineWidth/2)/textPtr->charWidth; } else { - dInfoPtr->newCharOffset -= ((-delta) + textPtr->charWidth - 1) + dInfoPtr->newByteOffset -= ((-delta) + textPtr->charWidth - 1) / textPtr->charWidth; } } else { delta -= (lineWidth - width); if (delta > 0) { if (delta > oneThird) { - dInfoPtr->newCharOffset = (x - lineWidth/2)/textPtr->charWidth; + dInfoPtr->newByteOffset = (x - lineWidth/2)/textPtr->charWidth; } else { - dInfoPtr->newCharOffset += (delta + textPtr->charWidth - 1) + dInfoPtr->newByteOffset += (delta + textPtr->charWidth - 1) / textPtr->charWidth; } } else { return TCL_OK; } - } + }} dInfoPtr->flags |= DINFO_OUT_OF_DATE; if (!(dInfoPtr->flags & REDRAW_PENDING)) { dInfoPtr->flags |= REDRAW_PENDING; @@ -3305,7 +3409,7 @@ TkTextXviewCmd(textPtr, interp, argc, argv) return TCL_OK; } - newOffset = dInfoPtr->newCharOffset; + newOffset = dInfoPtr->newByteOffset; type = Tk_GetScrollInfo(interp, argc, argv, &fraction, &count); switch (type) { case TK_SCROLL_ERROR: @@ -3326,14 +3430,14 @@ TkTextXviewCmd(textPtr, interp, argc, argv) if (charsPerPage < 1) { charsPerPage = 1; } - newOffset += charsPerPage*count; + newOffset += charsPerPage * count; break; case TK_SCROLL_UNITS: newOffset += count; break; } - dInfoPtr->newCharOffset = newOffset; + dInfoPtr->newByteOffset = newOffset; dInfoPtr->flags |= DINFO_OUT_OF_DATE; if (!(dInfoPtr->flags & REDRAW_PENDING)) { dInfoPtr->flags |= REDRAW_PENDING; @@ -3369,7 +3473,7 @@ ScrollByLines(textPtr, offset) * means that information earlier in the * text becomes visible. */ { - int i, charsToCount, lineNum; + int i, bytesToCount, lineNum; TkTextIndex new, index; TkTextLine *lastLinePtr; TextDInfo *dInfoPtr = textPtr->dInfoPtr; @@ -3382,21 +3486,21 @@ ScrollByLines(textPtr, offset) * it counts lines instead of pixels. */ - charsToCount = textPtr->topIndex.charIndex + 1; + bytesToCount = textPtr->topIndex.byteIndex + 1; index.tree = textPtr->tree; offset--; /* Skip line containing topIndex. */ for (lineNum = TkBTreeLineIndex(textPtr->topIndex.linePtr); lineNum >= 0; lineNum--) { index.linePtr = TkBTreeFindLine(textPtr->tree, lineNum); - index.charIndex = 0; + index.byteIndex = 0; lowestPtr = NULL; do { dlPtr = LayoutDLine(textPtr, &index); dlPtr->nextPtr = lowestPtr; lowestPtr = dlPtr; - TkTextIndexForwChars(&index, dlPtr->count, &index); - charsToCount -= dlPtr->count; - } while ((charsToCount > 0) + TkTextIndexForwBytes(&index, dlPtr->byteCount, &index); + bytesToCount -= dlPtr->byteCount; + } while ((bytesToCount > 0) && (index.linePtr == dlPtr->index.linePtr)); for (dlPtr = lowestPtr; dlPtr != NULL; dlPtr = dlPtr->nextPtr) { @@ -3406,7 +3510,7 @@ ScrollByLines(textPtr, offset) break; } } - + /* * Discard the display lines, then either return or prepare * for the next display line to lay out. @@ -3416,7 +3520,7 @@ ScrollByLines(textPtr, offset) if (offset >= 0) { goto scheduleUpdate; } - charsToCount = INT_MAX; + bytesToCount = INT_MAX; } /* @@ -3424,7 +3528,7 @@ ScrollByLines(textPtr, offset) * in the text. */ - TkTextMakeIndex(textPtr->tree, 0, 0, &textPtr->topIndex); + TkTextMakeByteIndex(textPtr->tree, 0, 0, &textPtr->topIndex); } else { /* * Scrolling down, to show later information in the text. @@ -3435,8 +3539,9 @@ ScrollByLines(textPtr, offset) TkBTreeNumLines(textPtr->tree)); for (i = 0; i < offset; i++) { dlPtr = LayoutDLine(textPtr, &textPtr->topIndex); + if (dlPtr->length == 0 && dlPtr->height == 0) offset++; dlPtr->nextPtr = NULL; - TkTextIndexForwChars(&textPtr->topIndex, dlPtr->count, &new); + TkTextIndexForwBytes(&textPtr->topIndex, dlPtr->byteCount, &new); FreeDLines(textPtr, dlPtr, (DLine *) NULL, 0); if (new.linePtr == lastLinePtr) { break; @@ -3480,7 +3585,7 @@ TkTextYviewCmd(textPtr, interp, argc, argv) * argv[1] is "yview". */ { TextDInfo *dInfoPtr = textPtr->dInfoPtr; - int pickPlace, lineNum, type, charsInLine; + int pickPlace, lineNum, type, bytesInLine; Tk_FontMetrics fm; int pixels, count; size_t switchLength; @@ -3518,7 +3623,7 @@ TkTextYviewCmd(textPtr, interp, argc, argv) } if ((argc == 3) || pickPlace) { if (Tcl_GetInt(interp, argv[2+pickPlace], &lineNum) == TCL_OK) { - TkTextMakeIndex(textPtr->tree, lineNum, 0, &index); + TkTextMakeByteIndex(textPtr->tree, lineNum, 0, &index); TkTextSetYView(textPtr, &index, 0); return TCL_OK; } @@ -3553,11 +3658,11 @@ TkTextYviewCmd(textPtr, interp, argc, argv) } fraction *= TkBTreeNumLines(textPtr->tree); lineNum = (int) fraction; - TkTextMakeIndex(textPtr->tree, lineNum, 0, &index); - charsInLine = TkBTreeCharsInLine(index.linePtr); - index.charIndex = (int)((charsInLine * (fraction-lineNum)) + 0.5); - if (index.charIndex >= charsInLine) { - TkTextMakeIndex(textPtr->tree, lineNum+1, 0, &index); + TkTextMakeByteIndex(textPtr->tree, lineNum, 0, &index); + bytesInLine = TkBTreeBytesInLine(index.linePtr); + index.byteIndex = (int)((bytesInLine * (fraction-lineNum)) + 0.5); + if (index.byteIndex >= bytesInLine) { + TkTextMakeByteIndex(textPtr->tree, lineNum + 1, 0, &index); } TkTextSetYView(textPtr, &index, 0); break; @@ -3595,7 +3700,7 @@ TkTextYviewCmd(textPtr, interp, argc, argv) do { dlPtr = LayoutDLine(textPtr, &textPtr->topIndex); dlPtr->nextPtr = NULL; - TkTextIndexForwChars(&textPtr->topIndex, dlPtr->count, + TkTextIndexForwBytes(&textPtr->topIndex, dlPtr->byteCount, &new); pixels -= dlPtr->height; FreeDLines(textPtr, dlPtr, (DLine *) NULL, 0); @@ -3647,13 +3752,14 @@ TkTextScanCmd(textPtr, interp, argc, argv) { TextDInfo *dInfoPtr = textPtr->dInfoPtr; TkTextIndex index; - int c, x, y, totalScroll, newChar, maxChar; + int c, x, y, totalScroll, newByte, maxByte, gain=10; Tk_FontMetrics fm; size_t length; - if (argc != 5) { + if ((argc != 5) && (argc != 6)) { Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " scan mark|dragto x y\"", (char *) NULL); + argv[0], " scan mark x y\" or \"", + argv[0], " scan dragto x y ?gain?\"", (char *) NULL); return TCL_ERROR; } if (Tcl_GetInt(interp, argv[3], &x) != TCL_OK) { @@ -3662,6 +3768,8 @@ TkTextScanCmd(textPtr, interp, argc, argv) if (Tcl_GetInt(interp, argv[4], &y) != TCL_OK) { return TCL_ERROR; } + if ((argc == 6) && (Tcl_GetInt(interp, argv[5], &gain) != TCL_OK)) + return TCL_ERROR; c = argv[2][0]; length = strlen(argv[2]); if ((c == 'd') && (strncmp(argv[2], "dragto", length) == 0)) { @@ -3677,33 +3785,35 @@ TkTextScanCmd(textPtr, interp, argc, argv) * moving again). */ - newChar = dInfoPtr->scanMarkChar + (10*(dInfoPtr->scanMarkX - x)) + newByte = dInfoPtr->scanMarkIndex + (gain*(dInfoPtr->scanMarkX - x)) / (textPtr->charWidth); - maxChar = 1 + (dInfoPtr->maxLength - (dInfoPtr->maxX - dInfoPtr->x) + maxByte = 1 + (dInfoPtr->maxLength - (dInfoPtr->maxX - dInfoPtr->x) + textPtr->charWidth - 1)/textPtr->charWidth; - if (newChar < 0) { - dInfoPtr->scanMarkChar = newChar = 0; + if (newByte < 0) { + newByte = 0; + dInfoPtr->scanMarkIndex = 0; dInfoPtr->scanMarkX = x; - } else if (newChar > maxChar) { - dInfoPtr->scanMarkChar = newChar = maxChar; + } else if (newByte > maxByte) { + newByte = maxByte; + dInfoPtr->scanMarkIndex = maxByte; dInfoPtr->scanMarkX = x; } - dInfoPtr->newCharOffset = newChar; + dInfoPtr->newByteOffset = newByte; Tk_GetFontMetrics(textPtr->tkfont, &fm); - totalScroll = (10*(dInfoPtr->scanMarkY - y)) / fm.linespace; + totalScroll = (gain*(dInfoPtr->scanMarkY - y)) / fm.linespace; if (totalScroll != dInfoPtr->scanTotalScroll) { index = textPtr->topIndex; ScrollByLines(textPtr, totalScroll-dInfoPtr->scanTotalScroll); dInfoPtr->scanTotalScroll = totalScroll; if ((index.linePtr == textPtr->topIndex.linePtr) && - (index.charIndex == textPtr->topIndex.charIndex)) { + (index.byteIndex == textPtr->topIndex.byteIndex)) { dInfoPtr->scanTotalScroll = 0; dInfoPtr->scanMarkY = y; } } } else if ((c == 'm') && (strncmp(argv[2], "mark", length) == 0)) { - dInfoPtr->scanMarkChar = dInfoPtr->newCharOffset; + dInfoPtr->scanMarkIndex = dInfoPtr->newByteOffset; dInfoPtr->scanMarkX = x; dInfoPtr->scanTotalScroll = 0; dInfoPtr->scanMarkY = y; @@ -3730,11 +3840,11 @@ TkTextScanCmd(textPtr, interp, argc, argv) * Tcl script to report them to the text's associated scrollbar. * * Results: - * If report is zero, then interp->result is filled in with + * If report is zero, then the interp's result is filled in with * two real numbers separated by a space, giving the position of * the left and right edges of the window as fractions from 0 to * 1, where 0 means the left edge of the text and 1 means the right - * edge. If report is non-zero, then interp->result isn't modified + * edge. If report is non-zero, then the interp's result isn't modified * directly, but instead a script is evaluated in interp to report * the new horizontal scroll position to the scrollbar (if the scroll * position hasn't changed then no script is invoked). @@ -3749,13 +3859,13 @@ static void GetXView(interp, textPtr, report) Tcl_Interp *interp; /* If "report" is FALSE, string * describing visible range gets - * stored in interp->result. */ + * stored in the interp's result. */ TkText *textPtr; /* Information about text widget. */ int report; /* Non-zero means report info to * scrollbar if it has changed. */ { TextDInfo *dInfoPtr = textPtr->dInfoPtr; - char buffer[200]; + char buffer[TCL_DOUBLE_SPACE * 2]; double first, last; int code; @@ -3772,7 +3882,8 @@ GetXView(interp, textPtr, report) last = 1.0; } if (!report) { - sprintf(interp->result, "%g %g", first, last); + sprintf(buffer, "%g %g", first, last); + Tcl_SetResult(interp, buffer, TCL_VOLATILE); return; } if ((first == dInfoPtr->xScrollFirst) && (last == dInfoPtr->xScrollLast)) { @@ -3800,11 +3911,11 @@ GetXView(interp, textPtr, report) * Tcl script to report them to the text's associated scrollbar. * * Results: - * If report is zero, then interp->result is filled in with + * If report is zero, then the interp's result is filled in with * two real numbers separated by a space, giving the position of * the top and bottom of the window as fractions from 0 to 1, where * 0 means the beginning of the text and 1 means the end. If - * report is non-zero, then interp->result isn't modified directly, + * report is non-zero, then the interp's result isn't modified directly, * but a script is evaluated in interp to report the new scroll * position to the scrollbar (if the scroll position hasn't changed * then no script is invoked). @@ -3819,22 +3930,22 @@ static void GetYView(interp, textPtr, report) Tcl_Interp *interp; /* If "report" is FALSE, string * describing visible range gets - * stored in interp->result. */ + * stored in the interp's result. */ TkText *textPtr; /* Information about text widget. */ int report; /* Non-zero means report info to * scrollbar if it has changed. */ { TextDInfo *dInfoPtr = textPtr->dInfoPtr; - char buffer[200]; + char buffer[TCL_DOUBLE_SPACE * 2]; double first, last; DLine *dlPtr; int totalLines, code, count; dlPtr = dInfoPtr->dLinePtr; totalLines = TkBTreeNumLines(textPtr->tree); - first = ((double) TkBTreeLineIndex(dlPtr->index.linePtr)) - + ((double) dlPtr->index.charIndex) - / (TkBTreeCharsInLine(dlPtr->index.linePtr)); + first = (double) TkBTreeLineIndex(dlPtr->index.linePtr) + + (double) dlPtr->index.byteIndex + / TkBTreeBytesInLine(dlPtr->index.linePtr); first /= totalLines; while (1) { if ((dlPtr->y + dlPtr->height) > dInfoPtr->maxY) { @@ -3846,17 +3957,18 @@ GetYView(interp, textPtr, report) break; } if (dlPtr->nextPtr == NULL) { - count = dlPtr->count; + count = dlPtr->byteCount; break; } dlPtr = dlPtr->nextPtr; } last = ((double) TkBTreeLineIndex(dlPtr->index.linePtr)) - + ((double) (dlPtr->index.charIndex + count)) - / (TkBTreeCharsInLine(dlPtr->index.linePtr)); + + ((double) (dlPtr->index.byteIndex + count)) + / (TkBTreeBytesInLine(dlPtr->index.linePtr)); last /= totalLines; if (!report) { - sprintf(interp->result, "%g %g", first, last); + sprintf(buffer, "%g %g", first, last); + Tcl_SetResult(interp, buffer, TCL_VOLATILE); return; } if ((first == dInfoPtr->yScrollFirst) && (last == dInfoPtr->yScrollLast)) { @@ -3865,8 +3977,7 @@ GetYView(interp, textPtr, report) dInfoPtr->yScrollFirst = first; dInfoPtr->yScrollLast = last; sprintf(buffer, " %g %g", first, last); - code = Tcl_VarEval(interp, textPtr->yScrollCmd, - buffer, (char *) NULL); + code = Tcl_VarEval(interp, textPtr->yScrollCmd, buffer, (char *) NULL); if (code != TCL_OK) { Tcl_AddErrorInfo(interp, "\n (vertical scrolling command executed by text)"); @@ -3938,7 +4049,7 @@ FindDLine(dlPtr, indexPtr) * Now get to the right position within the text line. */ - while (indexPtr->charIndex >= (dlPtr->index.charIndex + dlPtr->count)) { + while (indexPtr->byteIndex >= (dlPtr->index.byteIndex + dlPtr->byteCount)) { dlPtr = dlPtr->nextPtr; if ((dlPtr == NULL) || (dlPtr->index.linePtr != indexPtr->linePtr)) { break; @@ -3974,7 +4085,7 @@ TkTextPixelIndex(textPtr, x, y, indexPtr) * index of the character nearest to (x,y). */ { TextDInfo *dInfoPtr = textPtr->dInfoPtr; - register DLine *dlPtr; + register DLine *dlPtr, *validdlPtr; register TkTextDispChunk *chunkPtr; /* @@ -4007,8 +4118,9 @@ TkTextPixelIndex(textPtr, x, y, indexPtr) * Find the display line containing the desired y-coordinate. */ - for (dlPtr = dInfoPtr->dLinePtr; y >= (dlPtr->y + dlPtr->height); + for (dlPtr = validdlPtr = dInfoPtr->dLinePtr; y >= (dlPtr->y + dlPtr->height); dlPtr = dlPtr->nextPtr) { + if (dlPtr->chunkPtr !=NULL) validdlPtr = dlPtr; if (dlPtr->nextPtr == NULL) { /* * Y-coordinate is off the bottom of the displayed text. @@ -4019,6 +4131,8 @@ TkTextPixelIndex(textPtr, x, y, indexPtr) break; } } + if (dlPtr->chunkPtr == NULL) dlPtr = validdlPtr; + /* * Scan through the line's chunks to find the one that contains @@ -4030,21 +4144,22 @@ TkTextPixelIndex(textPtr, x, y, indexPtr) *indexPtr = dlPtr->index; x = x - dInfoPtr->x + dInfoPtr->curPixelOffset; for (chunkPtr = dlPtr->chunkPtr; x >= (chunkPtr->x + chunkPtr->width); - indexPtr->charIndex += chunkPtr->numChars, + indexPtr->byteIndex += chunkPtr->numBytes, chunkPtr = chunkPtr->nextPtr) { if (chunkPtr->nextPtr == NULL) { - indexPtr->charIndex += chunkPtr->numChars - 1; + indexPtr->byteIndex += chunkPtr->numBytes; + TkTextIndexBackChars(indexPtr, 1, indexPtr); return; } } /* - * If the chunk has more than one character in it, ask it which + * If the chunk has more than one byte in it, ask it which * character is at the desired location. */ - if (chunkPtr->numChars > 1) { - indexPtr->charIndex += (*chunkPtr->measureProc)(chunkPtr, x); + if (chunkPtr->numBytes > 1) { + indexPtr->byteIndex += (*chunkPtr->measureProc)(chunkPtr, x); } } @@ -4081,7 +4196,7 @@ TkTextCharBbox(textPtr, indexPtr, xPtr, yPtr, widthPtr, heightPtr) TextDInfo *dInfoPtr = textPtr->dInfoPtr; DLine *dlPtr; register TkTextDispChunk *chunkPtr; - int index; + int byteIndex; /* * Make sure that all of the screen layout information is up to date. @@ -4105,15 +4220,15 @@ TkTextCharBbox(textPtr, indexPtr, xPtr, yPtr, widthPtr, heightPtr) * index. */ - index = indexPtr->charIndex - dlPtr->index.charIndex; + byteIndex = indexPtr->byteIndex - dlPtr->index.byteIndex; for (chunkPtr = dlPtr->chunkPtr; ; chunkPtr = chunkPtr->nextPtr) { if (chunkPtr == NULL) { return -1; } - if (index < chunkPtr->numChars) { + if (byteIndex < chunkPtr->numBytes) { break; } - index -= chunkPtr->numChars; + byteIndex -= chunkPtr->numBytes; } /* @@ -4124,12 +4239,12 @@ TkTextCharBbox(textPtr, indexPtr, xPtr, yPtr, widthPtr, heightPtr) * horizontal scrolling. */ - (*chunkPtr->bboxProc)(chunkPtr, index, dlPtr->y + dlPtr->spaceAbove, + (*chunkPtr->bboxProc)(chunkPtr, byteIndex, dlPtr->y + dlPtr->spaceAbove, dlPtr->height - dlPtr->spaceAbove - dlPtr->spaceBelow, dlPtr->baseline - dlPtr->spaceAbove, xPtr, yPtr, widthPtr, heightPtr); *xPtr = *xPtr + dInfoPtr->x - dInfoPtr->curPixelOffset; - if ((index == (chunkPtr->numChars-1)) && (chunkPtr->nextPtr == NULL)) { + if ((byteIndex == (chunkPtr->numBytes - 1)) && (chunkPtr->nextPtr == NULL)) { /* * Last character in display line. Give it all the space up to * the line. @@ -4191,6 +4306,7 @@ TkTextDLineInfo(textPtr, indexPtr, xPtr, yPtr, widthPtr, heightPtr, basePtr) { TextDInfo *dInfoPtr = textPtr->dInfoPtr; DLine *dlPtr; + int dlx; /* * Make sure that all of the screen layout information is up to date. @@ -4209,8 +4325,9 @@ TkTextDLineInfo(textPtr, indexPtr, xPtr, yPtr, widthPtr, heightPtr, basePtr) return -1; } - *xPtr = dInfoPtr->x - dInfoPtr->curPixelOffset + dlPtr->chunkPtr->x; - *widthPtr = dlPtr->length - dlPtr->chunkPtr->x; + dlx = (dlPtr->chunkPtr != NULL? dlPtr->chunkPtr->x: 0); + *xPtr = dInfoPtr->x - dInfoPtr->curPixelOffset + dlx; + *widthPtr = dlPtr->length - dlx; *yPtr = dlPtr->y; if ((dlPtr->y + dlPtr->height) > dInfoPtr->maxY) { *heightPtr = dInfoPtr->maxY - dlPtr->y; @@ -4221,6 +4338,41 @@ TkTextDLineInfo(textPtr, indexPtr, xPtr, yPtr, widthPtr, heightPtr, basePtr) return 0; } +static void +ElideBboxProc(chunkPtr, index, y, lineHeight, baseline, xPtr, yPtr, + widthPtr, heightPtr) + TkTextDispChunk *chunkPtr; /* Chunk containing desired char. */ + int index; /* Index of desired character within + * the chunk. */ + int y; /* Topmost pixel in area allocated + * for this line. */ + int lineHeight; /* Height of line, in pixels. */ + int baseline; /* Location of line's baseline, in + * pixels measured down from y. */ + int *xPtr, *yPtr; /* Gets filled in with coords of + * character's upper-left pixel. + * X-coord is in same coordinate + * system as chunkPtr->x. */ + int *widthPtr; /* Gets filled in with width of + * character, in pixels. */ + int *heightPtr; /* Gets filled in with height of + * character, in pixels. */ +{ + *xPtr = chunkPtr->x; + *yPtr = y; + *widthPtr = *heightPtr = 0; +} + + +static int +ElideMeasureProc(chunkPtr, x) + TkTextDispChunk *chunkPtr; /* Chunk containing desired coord. */ + int x; /* X-coordinate, in same coordinate + * system as chunkPtr->x. */ +{ + return 0 /*chunkPtr->numBytes - 1*/; +} + /* *-------------------------------------------------------------- * @@ -4228,7 +4380,7 @@ TkTextDLineInfo(textPtr, indexPtr, xPtr, yPtr, widthPtr, heightPtr, basePtr) * * This procedure is the "layoutProc" for character segments. * - * Results: +n * Results: * If there is something to display for the chunk then a * non-zero value is returned and the fields of chunkPtr * will be filled in (see the declaration of TkTextDispChunk @@ -4245,29 +4397,29 @@ TkTextDLineInfo(textPtr, indexPtr, xPtr, yPtr, widthPtr, heightPtr, basePtr) */ int -TkTextCharLayoutProc(textPtr, indexPtr, segPtr, offset, maxX, maxChars, +TkTextCharLayoutProc(textPtr, indexPtr, segPtr, byteOffset, maxX, maxBytes, noCharsYet, wrapMode, chunkPtr) TkText *textPtr; /* Text widget being layed out. */ TkTextIndex *indexPtr; /* Index of first character to lay out * (corresponds to segPtr and offset). */ TkTextSegment *segPtr; /* Segment being layed out. */ - int offset; /* Offset within segment of first character - * to consider. */ + int byteOffset; /* Byte offset within segment of first + * character to consider. */ int maxX; /* Chunk must not occupy pixels at this * position or higher. */ - int maxChars; /* Chunk must not include more than this + int maxBytes; /* Chunk must not include more than this * many characters. */ int noCharsYet; /* Non-zero means no characters have been * assigned to this display line yet. */ - Tk_Uid wrapMode; /* How to handle line wrapping: tkTextCharUid, - * tkTextNoneUid, or tkTextWordUid. */ + TkWrapMode wrapMode; /* How to handle line wrapping: TEXT_WRAPMODE_CHAR, + * TEXT_WRAPMODE_NONE, or TEXT_WRAPMODE_WORD. */ register TkTextDispChunk *chunkPtr; /* Structure to fill in with information * about this chunk. The x field has already * been set by the caller. */ { Tk_Font tkfont; - int nextX, charsThatFit, count; + int nextX, bytesThatFit, count; CharInfo *ciPtr; char *p; TkTextSegment *nextPtr; @@ -4285,17 +4437,19 @@ TkTextCharLayoutProc(textPtr, indexPtr, segPtr, offset, maxX, maxChars, * is a white space character. */ - p = segPtr->body.chars + offset; + p = segPtr->body.chars + byteOffset; tkfont = chunkPtr->stylePtr->sValuePtr->tkfont; - charsThatFit = MeasureChars(tkfont, p, maxChars, chunkPtr->x, maxX, 0, + bytesThatFit = MeasureChars(tkfont, p, maxBytes, chunkPtr->x, maxX, 0, &nextX); - if (charsThatFit < maxChars) { - if ((charsThatFit == 0) && noCharsYet) { - charsThatFit = 1; - MeasureChars(tkfont, p, 1, chunkPtr->x, INT_MAX, 0, &nextX); + if (bytesThatFit < maxBytes) { + if ((bytesThatFit == 0) && noCharsYet) { + Tcl_UniChar ch; + + bytesThatFit = MeasureChars(tkfont, p, Tcl_UtfToUniChar(p, &ch), + chunkPtr->x, -1, 0, &nextX); } - if ((nextX < maxX) && ((p[charsThatFit] == ' ') - || (p[charsThatFit] == '\t'))) { + if ((nextX < maxX) && ((p[bytesThatFit] == ' ') + || (p[bytesThatFit] == '\t'))) { /* * Space characters are funny, in that they are considered * to fit if there is at least one pixel of space left on the @@ -4303,17 +4457,17 @@ TkTextCharLayoutProc(textPtr, indexPtr, segPtr, offset, maxX, maxChars, */ nextX = maxX; - charsThatFit++; + bytesThatFit++; } - if (p[charsThatFit] == '\n') { + if (p[bytesThatFit] == '\n') { /* * A newline character takes up no space, so if the previous * character fits then so does the newline. */ - charsThatFit++; + bytesThatFit++; } - if (charsThatFit == 0) { + if (bytesThatFit == 0) { return 0; } } @@ -4330,19 +4484,19 @@ TkTextCharLayoutProc(textPtr, indexPtr, segPtr, offset, maxX, maxChars, chunkPtr->undisplayProc = CharUndisplayProc; chunkPtr->measureProc = CharMeasureProc; chunkPtr->bboxProc = CharBboxProc; - chunkPtr->numChars = charsThatFit; + chunkPtr->numBytes = bytesThatFit; chunkPtr->minAscent = fm.ascent + chunkPtr->stylePtr->sValuePtr->offset; chunkPtr->minDescent = fm.descent - chunkPtr->stylePtr->sValuePtr->offset; chunkPtr->minHeight = 0; chunkPtr->width = nextX - chunkPtr->x; chunkPtr->breakIndex = -1; ciPtr = (CharInfo *) ckalloc((unsigned) - (sizeof(CharInfo) - 3 + charsThatFit)); + (sizeof(CharInfo) - 3 + bytesThatFit)); chunkPtr->clientData = (ClientData) ciPtr; - ciPtr->numChars = charsThatFit; - strncpy(ciPtr->chars, p, (size_t) charsThatFit); - if (p[charsThatFit-1] == '\n') { - ciPtr->numChars--; + ciPtr->numBytes = bytesThatFit; + strncpy(ciPtr->chars, p, (size_t) bytesThatFit); + if (p[bytesThatFit - 1] == '\n') { + ciPtr->numBytes--; } /* @@ -4352,22 +4506,22 @@ TkTextCharLayoutProc(textPtr, indexPtr, segPtr, offset, maxX, maxChars, * is not a character segment. */ - if (wrapMode != tkTextWordUid) { - chunkPtr->breakIndex = chunkPtr->numChars; + if (wrapMode != TEXT_WRAPMODE_WORD) { + chunkPtr->breakIndex = chunkPtr->numBytes; } else { - for (count = charsThatFit, p += charsThatFit-1; count > 0; + for (count = bytesThatFit, p += bytesThatFit - 1; count > 0; count--, p--) { if (isspace(UCHAR(*p))) { chunkPtr->breakIndex = count; break; } } - if ((charsThatFit+offset) == segPtr->size) { + if ((bytesThatFit + byteOffset) == segPtr->size) { for (nextPtr = segPtr->nextPtr; nextPtr != NULL; nextPtr = nextPtr->nextPtr) { if (nextPtr->size != 0) { if (nextPtr->typePtr != &tkTextCharType) { - chunkPtr->breakIndex = chunkPtr->numChars; + chunkPtr->breakIndex = chunkPtr->numBytes; } break; } @@ -4414,7 +4568,7 @@ CharDisplayProc(chunkPtr, x, y, height, baseline, display, dst, screenY) CharInfo *ciPtr = (CharInfo *) chunkPtr->clientData; TextStyle *stylePtr; StyleValues *sValuePtr; - int offsetChars, offsetX; + int offsetBytes, offsetX; if ((x + chunkPtr->width) <= 0) { /* @@ -4436,30 +4590,29 @@ CharDisplayProc(chunkPtr, x, y, height, baseline, display, dst, screenY) */ offsetX = x; - offsetChars = 0; + offsetBytes = 0; if (x < 0) { - offsetChars = MeasureChars(sValuePtr->tkfont, ciPtr->chars, - ciPtr->numChars, x, 0, x - chunkPtr->x, &offsetX); + offsetBytes = MeasureChars(sValuePtr->tkfont, ciPtr->chars, + ciPtr->numBytes, x, 0, x - chunkPtr->x, &offsetX); } /* * Draw the text, underline, and overstrike for this chunk. */ - if (ciPtr->numChars > offsetChars) { - int numChars = ciPtr->numChars - offsetChars; - char *string = ciPtr->chars + offsetChars; + if (!sValuePtr->elide && (ciPtr->numBytes > offsetBytes) && (stylePtr->fgGC != None)) { + int numBytes = ciPtr->numBytes - offsetBytes; + char *string = ciPtr->chars + offsetBytes; - if ((numChars > 0) && (string[numChars - 1] == '\t')) { - numChars--; + if ((numBytes > 0) && (string[numBytes - 1] == '\t')) { + numBytes--; } Tk_DrawChars(display, dst, stylePtr->fgGC, sValuePtr->tkfont, string, - numChars, offsetX, y + baseline - sValuePtr->offset); + numBytes, offsetX, y + baseline - sValuePtr->offset); if (sValuePtr->underline) { Tk_UnderlineChars(display, dst, stylePtr->fgGC, sValuePtr->tkfont, - ciPtr->chars + offsetChars, offsetX, - y + baseline - sValuePtr->offset, - 0, numChars); + ciPtr->chars + offsetBytes, offsetX, + y + baseline - sValuePtr->offset, 0, numBytes); } if (sValuePtr->overstrike) { @@ -4467,10 +4620,10 @@ CharDisplayProc(chunkPtr, x, y, height, baseline, display, dst, screenY) Tk_GetFontMetrics(sValuePtr->tkfont, &fm); Tk_UnderlineChars(display, dst, stylePtr->fgGC, sValuePtr->tkfont, - ciPtr->chars + offsetChars, offsetX, + ciPtr->chars + offsetBytes, offsetX, y + baseline - sValuePtr->offset - fm.descent - (fm.ascent * 3) / 10, - 0, numChars); + 0, numBytes); } } } @@ -4532,7 +4685,8 @@ CharMeasureProc(chunkPtr, x) int endX; return MeasureChars(chunkPtr->stylePtr->sValuePtr->tkfont, ciPtr->chars, - chunkPtr->numChars-1, chunkPtr->x, x, 0, &endX); + chunkPtr->numBytes - 1, chunkPtr->x, x, 0, &endX); + /* CHAR OFFSET */ } /* @@ -4559,11 +4713,11 @@ CharMeasureProc(chunkPtr, x) */ static void -CharBboxProc(chunkPtr, index, y, lineHeight, baseline, xPtr, yPtr, +CharBboxProc(chunkPtr, byteIndex, y, lineHeight, baseline, xPtr, yPtr, widthPtr, heightPtr) TkTextDispChunk *chunkPtr; /* Chunk containing desired char. */ - int index; /* Index of desired character within - * the chunk. */ + int byteIndex; /* Byte offset of desired character + * within the chunk. */ int y; /* Topmost pixel in area allocated * for this line. */ int lineHeight; /* Height of line, in pixels. */ @@ -4582,10 +4736,10 @@ CharBboxProc(chunkPtr, index, y, lineHeight, baseline, xPtr, yPtr, int maxX; maxX = chunkPtr->width + chunkPtr->x; - MeasureChars(chunkPtr->stylePtr->sValuePtr->tkfont, ciPtr->chars, index, - chunkPtr->x, 1000000, 0, xPtr); + MeasureChars(chunkPtr->stylePtr->sValuePtr->tkfont, ciPtr->chars, + byteIndex, chunkPtr->x, -1, 0, xPtr); - if (index == ciPtr->numChars) { + if (byteIndex == ciPtr->numBytes) { /* * This situation only happens if the last character in a line * is a space character, in which case it absorbs all of the @@ -4593,8 +4747,8 @@ CharBboxProc(chunkPtr, index, y, lineHeight, baseline, xPtr, yPtr, */ *widthPtr = maxX - *xPtr; - } else if ((ciPtr->chars[index] == '\t') - && (index == (ciPtr->numChars-1))) { + } else if ((ciPtr->chars[byteIndex] == '\t') + && (byteIndex == ciPtr->numBytes - 1)) { /* * The desired character is a tab character that terminates a * chunk; give it all the space left in the chunk. @@ -4603,7 +4757,7 @@ CharBboxProc(chunkPtr, index, y, lineHeight, baseline, xPtr, yPtr, *widthPtr = maxX - *xPtr; } else { MeasureChars(chunkPtr->stylePtr->sValuePtr->tkfont, - ciPtr->chars + index, 1, *xPtr, 1000000, 0, widthPtr); + ciPtr->chars + byteIndex, 1, *xPtr, -1, 0, widthPtr); if (*widthPtr > maxX) { *widthPtr = maxX - *xPtr; } else { @@ -4738,7 +4892,7 @@ AdjustForTab(textPtr, tabArrayPtr, index, chunkPtr) continue; } ciPtr = (CharInfo *) chunkPtr2->clientData; - for (p = ciPtr->chars, i = 0; i < ciPtr->numChars; p++, i++) { + for (p = ciPtr->chars, i = 0; i < ciPtr->numBytes; p++, i++) { if (isdigit(UCHAR(*p))) { gotDigit = 1; } else if ((*p == '.') || (*p == ',')) { @@ -4759,7 +4913,7 @@ AdjustForTab(textPtr, tabArrayPtr, index, chunkPtr) ciPtr = (CharInfo *) decimalChunkPtr->clientData; MeasureChars(decimalChunkPtr->stylePtr->sValuePtr->tkfont, - ciPtr->chars, decimal, decimalChunkPtr->x, 1000000, 0, &curX); + ciPtr->chars, decimal, decimalChunkPtr->x, -1, 0, &curX); desired = tabX - (curX - x); goto update; } else { @@ -4784,7 +4938,7 @@ AdjustForTab(textPtr, tabArrayPtr, index, chunkPtr) update: delta = desired - x; - MeasureChars(textPtr->tkfont, " ", 1, 0, INT_MAX, 0, &spaceWidth); + MeasureChars(textPtr->tkfont, " ", 1, 0, -1, 0, &spaceWidth); if (delta < spaceWidth) { delta = spaceWidth; } @@ -4889,7 +5043,7 @@ SizeOfTab(textPtr, tabArrayPtr, index, x, maxX) } done: - MeasureChars(textPtr->tkfont, " ", 1, 0, INT_MAX, 0, &spaceWidth); + MeasureChars(textPtr->tkfont, " ", 1, 0, -1, 0, &spaceWidth); if (result < spaceWidth) { result = spaceWidth; } @@ -4953,7 +5107,7 @@ NextTabStop(textPtr, tkfont, x, tabOrigin) * * Determine the number of characters from the string that will fit * in the given horizontal span. The measurement is done under the - * assumption that Tk_DisplayChars will be used to actually display + * assumption that Tk_DrawTextLayout will be used to actually display * the characters. * * If tabs are encountered in the string, they will be expanded @@ -4964,7 +5118,7 @@ NextTabStop(textPtr, tkfont, x, tabOrigin) * is specified. * * Results: - * The return value is the number of characters from source + * The return value is the number of bytes from source * that fit in the span given by startX and maxX. *nextXPtr * is filled in with the x-coordinate at which the first * character that didn't fit would be drawn, if it were to @@ -4977,11 +5131,11 @@ NextTabStop(textPtr, tkfont, x, tabOrigin) */ static int -MeasureChars(tkfont, source, maxChars, startX, maxX, tabOrigin, nextXPtr) +MeasureChars(tkfont, source, maxBytes, startX, maxX, tabOrigin, nextXPtr) Tk_Font tkfont; /* Font in which to draw characters. */ CONST char *source; /* Characters to be displayed. Need not * be NULL-terminated. */ - int maxChars; /* Maximum # of characters to consider from + int maxBytes; /* Maximum # of bytes to consider from * source. */ int startX; /* X-position at which first character will * be drawn. */ @@ -4998,7 +5152,7 @@ MeasureChars(tkfont, source, maxChars, startX, maxX, tabOrigin, nextXPtr) ch = 0; /* lint. */ curX = startX; special = source; - end = source + maxChars; + end = source + maxBytes; for (start = source; start < end; ) { if (start >= special) { /* @@ -5018,7 +5172,7 @@ MeasureChars(tkfont, source, maxChars, startX, maxX, tabOrigin, nextXPtr) * string). Process characters between start and special. */ - if (curX >= maxX) { + if ((maxX >= 0) && (curX >= maxX)) { break; } start += Tk_MeasureChars(tkfont, start, special - start, maxX - curX, @@ -5043,3 +5197,4 @@ MeasureChars(tkfont, source, maxChars, startX, maxX, tabOrigin, nextXPtr) *nextXPtr = curX; return start - source; } + |