summaryrefslogtreecommitdiff
path: root/tk/generic/tkTextDisp.c
diff options
context:
space:
mode:
Diffstat (limited to 'tk/generic/tkTextDisp.c')
-rw-r--r--tk/generic/tkTextDisp.c711
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;
}
+