428 lines
14 KiB
Plaintext
428 lines
14 KiB
Plaintext
--- ../generic/tkTextDisp.c.orig Mon Sep 14 14:23:18 1998
|
||
+++ ../generic/tkTextDisp.c Wed Jan 5 23:20:56 2000
|
||
@@ -55,6 +55,7 @@
|
||
* be NULL). */
|
||
int underline; /* Non-zero means draw underline underneath
|
||
* text. */
|
||
+ int elide; /* Non-zero means draw text */
|
||
Tk_Uid wrapMode; /* How to handle wrap-around for this tag.
|
||
* One of tkTextCharUid, tkTextNoneUid,
|
||
* or tkTextWordUid. */
|
||
@@ -311,6 +312,21 @@
|
||
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,
|
||
@@ -479,7 +495,7 @@
|
||
|
||
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 +510,7 @@
|
||
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;
|
||
@@ -612,6 +628,11 @@
|
||
styleValues.underline = tagPtr->underline;
|
||
underlinePrio = tagPtr->priority;
|
||
}
|
||
+ if ((tagPtr->elideString != NULL)
|
||
+ && (tagPtr->priority > elidePrio)) {
|
||
+ styleValues.elide = tagPtr->elide;
|
||
+ elidePrio = tagPtr->priority;
|
||
+ }
|
||
if ((tagPtr->wrapMode != NULL)
|
||
&& (tagPtr->priority > wrapPrio)) {
|
||
styleValues.wrapMode = tagPtr->wrapMode;
|
||
@@ -768,7 +789,7 @@
|
||
* lines with numChars > 0. Used to
|
||
* drop 0-sized chunks from the end
|
||
* of the line. */
|
||
- int offset, ascent, descent, code;
|
||
+ int offset, ascent, descent, code, elide, elidesize;
|
||
StyleValues *sValuePtr;
|
||
|
||
/*
|
||
@@ -786,6 +807,34 @@
|
||
dlPtr->nextPtr = NULL;
|
||
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->charIndex==0) {
|
||
+ maxChars = 0;
|
||
+ for (segPtr = indexPtr->linePtr->segPtr; elide && segPtr!=NULL; segPtr = segPtr->nextPtr) {
|
||
+ if ((elidesize = segPtr->size) > 0) {
|
||
+ maxChars += elidesize;
|
||
+
|
||
+ /* if have tag toggle, 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==1);
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+
|
||
+ if (elide) {
|
||
+ dlPtr->count = maxChars;
|
||
+ 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
|
||
@@ -797,6 +846,7 @@
|
||
lastChunkPtr = NULL;
|
||
chunkPtr = NULL;
|
||
noCharsYet = 1;
|
||
+ elide = 0;
|
||
breakChunkPtr = NULL;
|
||
breakCharOffset = 0;
|
||
justify = TK_JUSTIFY_LEFT;
|
||
@@ -821,6 +871,31 @@
|
||
}
|
||
|
||
while (segPtr != NULL) {
|
||
+
|
||
+ /* every line still gets at least one chunk due to expectations in rest of code,
|
||
+ but able to skip elided portions of line quickly */
|
||
+ /* if current chunk elided and last chunk was too, coalese */
|
||
+ if (elide && lastChunkPtr!=NULL && lastChunkPtr->displayProc == NULL/*ElideDisplayProc*/) {
|
||
+ if ((elidesize = segPtr->size - offset) > 0) {
|
||
+ curIndex.charIndex += elidesize;
|
||
+ lastChunkPtr->numChars += elidesize;
|
||
+ breakCharOffset = lastChunkPtr->breakIndex = lastChunkPtr->numChars;
|
||
+
|
||
+ /* if have tag toggle, chance that invisibility state changed */
|
||
+ } else if (segPtr->typePtr == &tkTextToggleOffType || segPtr->typePtr == &tkTextToggleOnType) {
|
||
+ if (segPtr->body.toggle.tagPtr->elideString!=NULL) {
|
||
+ elide = (segPtr->typePtr == &tkTextToggleOffType) ^ (segPtr->body.toggle.tagPtr->elide==1);
|
||
+ }
|
||
+ }
|
||
+
|
||
+ offset = 0;
|
||
+ segPtr = segPtr->nextPtr;
|
||
+ if (segPtr == NULL && chunkPtr != NULL) ckfree((char *) chunkPtr);
|
||
+
|
||
+ continue;
|
||
+ }
|
||
+
|
||
+
|
||
if (segPtr->typePtr->layoutProc == NULL) {
|
||
segPtr = segPtr->nextPtr;
|
||
offset = 0;
|
||
@@ -831,6 +906,7 @@
|
||
chunkPtr->nextPtr = NULL;
|
||
}
|
||
chunkPtr->stylePtr = GetStyle(textPtr, &curIndex);
|
||
+ elide = chunkPtr->stylePtr->sValuePtr->elide;
|
||
|
||
/*
|
||
* Save style information such as justification and indentation,
|
||
@@ -864,7 +940,7 @@
|
||
|
||
gotTab = 0;
|
||
maxChars = segPtr->size - offset;
|
||
- if (justify == TK_JUSTIFY_LEFT) {
|
||
+ if (!elide && justify == TK_JUSTIFY_LEFT) {
|
||
if (segPtr->typePtr == &tkTextCharType) {
|
||
char *p;
|
||
|
||
@@ -877,8 +953,21 @@
|
||
}
|
||
}
|
||
}
|
||
-
|
||
chunkPtr->x = x;
|
||
+ if (elide && maxChars) {
|
||
+ /* don't free style here, as other code expects to be able to do that */
|
||
+ /*breakCharOffset =*/ chunkPtr->breakIndex = chunkPtr->numChars = maxChars;
|
||
+ 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,
|
||
chunkPtr);
|
||
@@ -950,6 +1039,7 @@
|
||
offset = 0;
|
||
segPtr = segPtr->nextPtr;
|
||
}
|
||
+
|
||
chunkPtr = NULL;
|
||
}
|
||
if (noCharsYet) {
|
||
@@ -998,6 +1088,7 @@
|
||
wholeLine = 0;
|
||
}
|
||
|
||
+
|
||
/*
|
||
* Make tab adjustments for the last tab stop, if there is one.
|
||
*/
|
||
@@ -1321,6 +1412,7 @@
|
||
index.linePtr = TkBTreeFindLine(textPtr->tree, lineNum);
|
||
index.charIndex = 0;
|
||
lowestPtr = NULL;
|
||
+
|
||
do {
|
||
dlPtr = LayoutDLine(textPtr, &index);
|
||
dlPtr->nextPtr = lowestPtr;
|
||
@@ -1554,6 +1646,8 @@
|
||
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.
|
||
@@ -1620,12 +1714,16 @@
|
||
* 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,
|
||
@@ -1714,6 +1812,7 @@
|
||
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
|
||
@@ -1787,7 +1886,7 @@
|
||
rightX = maxX;
|
||
}
|
||
chunkPtr2 = NULL;
|
||
- if (prevPtr != NULL) {
|
||
+ if (prevPtr != NULL && prevPtr->chunkPtr != NULL) {
|
||
/*
|
||
* Find the chunk in the previous line that covers leftX.
|
||
*/
|
||
@@ -1908,7 +2007,8 @@
|
||
rightX = maxX;
|
||
}
|
||
chunkPtr2 = NULL;
|
||
- if (dlPtr->nextPtr != NULL) {
|
||
+/* for (dlPtr2 = dlPtr; dlPtr2->nextPtr != NULL && dlPtr2->nextPtr->chunkPtr == NULL; dlPtr2 = dlPtr2->nextPtr) {}*/
|
||
+ if (dlPtr->nextPtr != NULL && dlPtr->nextPtr->chunkPtr != NULL) {
|
||
/*
|
||
* Find the chunk in the previous line that covers leftX.
|
||
*/
|
||
@@ -2299,6 +2399,7 @@
|
||
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];
|
||
@@ -2315,6 +2416,7 @@
|
||
dlPtr->oldY = dlPtr->y;
|
||
dlPtr->flags &= ~NEW_LAYOUT;
|
||
}
|
||
+ /*prevPtr = dlPtr;*/
|
||
}
|
||
Tk_FreePixmap(Tk_Display(textPtr->tkwin), pixmap);
|
||
}
|
||
@@ -3369,6 +3471,7 @@
|
||
dlPtr = LayoutDLine(textPtr, &index);
|
||
dlPtr->nextPtr = lowestPtr;
|
||
lowestPtr = dlPtr;
|
||
+ if (dlPtr->length == 0 && dlPtr->height == 0) { offset--; break; } /* elide */
|
||
TkTextIndexForwChars(&index, dlPtr->count, &index);
|
||
charsToCount -= dlPtr->count;
|
||
} while ((charsToCount > 0)
|
||
@@ -3381,7 +3484,7 @@
|
||
break;
|
||
}
|
||
}
|
||
-
|
||
+
|
||
/*
|
||
* Discard the display lines, then either return or prepare
|
||
* for the next display line to lay out.
|
||
@@ -3410,12 +3513,14 @@
|
||
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);
|
||
FreeDLines(textPtr, dlPtr, (DLine *) NULL, 0);
|
||
if (new.linePtr == lastLinePtr) {
|
||
break;
|
||
}
|
||
+
|
||
textPtr->topIndex = new;
|
||
}
|
||
}
|
||
@@ -3949,7 +4054,7 @@
|
||
* index of the character nearest to (x,y). */
|
||
{
|
||
TextDInfo *dInfoPtr = textPtr->dInfoPtr;
|
||
- register DLine *dlPtr;
|
||
+ register DLine *dlPtr, *validdlPtr;
|
||
register TkTextDispChunk *chunkPtr;
|
||
|
||
/*
|
||
@@ -3982,8 +4087,9 @@
|
||
* 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.
|
||
@@ -3994,6 +4100,8 @@
|
||
break;
|
||
}
|
||
}
|
||
+ if (dlPtr->chunkPtr == NULL) dlPtr = validdlPtr;
|
||
+
|
||
|
||
/*
|
||
* Scan through the line's chunks to find the one that contains
|
||
@@ -4005,12 +4113,12 @@
|
||
*indexPtr = dlPtr->index;
|
||
x = x - dInfoPtr->x + dInfoPtr->curPixelOffset;
|
||
for (chunkPtr = dlPtr->chunkPtr; x >= (chunkPtr->x + chunkPtr->width);
|
||
- indexPtr->charIndex += chunkPtr->numChars,
|
||
- chunkPtr = chunkPtr->nextPtr) {
|
||
+ indexPtr->charIndex += chunkPtr->numChars,
|
||
+ chunkPtr = chunkPtr->nextPtr) {
|
||
if (chunkPtr->nextPtr == NULL) {
|
||
indexPtr->charIndex += chunkPtr->numChars - 1;
|
||
return;
|
||
- }
|
||
+ }
|
||
}
|
||
|
||
/*
|
||
@@ -4166,6 +4274,7 @@
|
||
{
|
||
TextDInfo *dInfoPtr = textPtr->dInfoPtr;
|
||
DLine *dlPtr;
|
||
+ int dlx;
|
||
|
||
/*
|
||
* Make sure that all of the screen layout information is up to date.
|
||
@@ -4184,8 +4293,9 @@
|
||
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;
|
||
@@ -4196,6 +4306,41 @@
|
||
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->numChars - 1*/;
|
||
+}
|
||
+
|
||
/*
|
||
*--------------------------------------------------------------
|
||
*
|
||
@@ -4421,7 +4566,7 @@
|
||
* Draw the text, underline, and overstrike for this chunk.
|
||
*/
|
||
|
||
- if (ciPtr->numChars > offsetChars) {
|
||
+ if (!sValuePtr->elide && ciPtr->numChars > offsetChars) {
|
||
int numChars = ciPtr->numChars - offsetChars;
|
||
char *string = ciPtr->chars + offsetChars;
|
||
|