--- ../generic/tkText.c.ORIG	Wed Mar 24 11:36:00 1999
+++ ../generic/tkText.c	Wed Mar 24 11:38:57 1999
@@ -947,6 +947,7 @@
 	    || (textPtr->selTagPtr->spacing2String != NULL)
 	    || (textPtr->selTagPtr->spacing3String != NULL)
 	    || (textPtr->selTagPtr->tabString != NULL)
+	    || (textPtr->selTagPtr->elideString != NULL)
 	    || (textPtr->selTagPtr->underlineString != NULL)
 	    || (textPtr->selTagPtr->wrapMode != NULL)) {
 	textPtr->selTagPtr->affectsDisplay = 1;
@@ -1521,7 +1522,7 @@
 		    }
 		}
 	    }
-	    if (segPtr->typePtr == &tkTextCharType) {
+	    if (segPtr->typePtr == &tkTextCharType && !TkTextIsElided(textPtr, &textPtr->selIndex)) {
 #ifdef TK_KANJI_OK
 		memcpy((VOID *) buffer, (VOID *) (str + offset), (size_t) numBytes);
 		offset = 0;
@@ -1829,7 +1830,7 @@
     int argc;			/* Number of arguments. */
     char **argv;		/* Argument strings. */
 {
-    int backwards, exact, c, i, argsLeft, noCase, leftToScan;
+    int backwards, exact, searchElide, c, i, argsLeft, noCase, leftToScan;
     size_t length;
     int numLines, startingLine, startingChar, lineNum, firstChar, lastChar;
     int code, matchLength, matchChar, passes, stopLine, searchWholeText;
@@ -1840,6 +1841,7 @@
     Tcl_DString line, patDString;
     TkTextSegment *segPtr;
     TkTextLine *linePtr;
+    TkTextIndex curIndex;
     Tcl_RegExp regexp = NULL;		/* Initialization needed only to
 					 * prevent compiler warning. */
 
@@ -1848,6 +1850,8 @@
      */
 
     exact = 1;
+    searchElide = 0;
+    curIndex.tree = textPtr->tree;
     backwards = 0;
     noCase = 0;
     varName = NULL;
@@ -1861,7 +1865,7 @@
 	    badSwitch:
 	    Tcl_AppendResult(interp, "bad switch \"", arg,
 		    "\": must be -forward, -backward, -exact, -regexp, ",
-		    "-nocase, -count, or --", (char *) NULL);
+		    "-nocase, -count, -elide, or --", (char *) NULL);
 	    return TCL_ERROR;
 	}
 	c = arg[1];
@@ -1882,6 +1886,8 @@
 	    noCase = 1;
 	} else if ((c == 'r') && (strncmp(argv[i], "-regexp", length) == 0)) {
 	    exact = 0;
+	} else if ((c == 'e') && (strncmp(argv[i], "-elide", length) == 0)) {
+	    searchElide = 1;
 	} else if ((c == '-') && (strncmp(argv[i], "--", length) == 0)) {
 	    i++;
 	    break;
@@ -1977,13 +1983,14 @@
 	 */
 
 	linePtr = TkBTreeFindLine(textPtr->tree, lineNum);
+	curIndex.linePtr = linePtr; curIndex.charIndex = 0;
 	for (segPtr = linePtr->segPtr; segPtr != NULL;
-		segPtr = segPtr->nextPtr) {
+		curIndex.charIndex += segPtr->size, segPtr = segPtr->nextPtr) {
 #ifdef TK_KANJI_OK
 	    int i;
 	    char *str;
 #endif /* TK_KANJI_OK */
-	    if (segPtr->typePtr != &tkTextCharType) {
+	    if (segPtr->typePtr != &tkTextCharType || (!searchElide && TkTextIsElided(textPtr, &curIndex))) {
 		continue;
 	    }
 #ifdef TK_KANJI_OK
@@ -2211,7 +2218,7 @@
     int argc;			/* Number of arguments. */
     char **argv;		/* Argument strings. */
 {
-    int backwards, exact, c, i, argsLeft, noCase, leftToScan;
+    int backwards, exact, searchElide, c, i, argsLeft, noCase, leftToScan;
     size_t length;
     int numLines, startingLine, startingChar, lineNum, firstChar, lastChar;
     int code, matchLength, matchChar, passes, stopLine, searchWholeText;
@@ -2231,6 +2238,7 @@
 #endif /* TK_KANJI_OK */
     TkTextSegment *segPtr;
     TkTextLine *linePtr;
+    TkTextIndex curIndex;
 #ifndef TK_KANJI_OK
     Tcl_RegExp regexp = NULL;		/* Initialization needed only to
 					 * prevent compiler warning. */
@@ -2241,6 +2249,8 @@
      */
 
     exact = 1;
+    searchElide = 0;
+    curIndex.tree = textPtr->tree;
     backwards = 0;
     noCase = 0;
     varName = NULL;
@@ -2254,7 +2264,7 @@
 	    badSwitch:
 	    Tcl_AppendResult(interp, "bad switch \"", arg,
 		    "\": must be -forward, -backward, -exact, -regexp, ",
-		    "-nocase, -count, or --", (char *) NULL);
+		    "-nocase, -count, -elide, or --", (char *) NULL);
 	    return TCL_ERROR;
 	}
 	c = arg[1];
@@ -2279,6 +2289,8 @@
 	    return TCL_ERROR;
 #endif /* TK_KANJI_OK */
 	    exact = 0;
+	} else if ((c == 'e') && (strncmp(argv[i], "-elide", length) == 0)) {
+	    searchElide = 1;
 	} else if ((c == '-') && (strncmp(argv[i], "--", length) == 0)) {
 	    i++;
 	    break;
@@ -2406,9 +2418,10 @@
 	 */
 
 	linePtr = TkBTreeFindLine(textPtr->tree, lineNum);
+	curIndex.linePtr = linePtr; curIndex.charIndex = 0;
 	for (segPtr = linePtr->segPtr; segPtr != NULL;
-		segPtr = segPtr->nextPtr) {
-	    if (segPtr->typePtr != &tkTextCharType) {
+		curIndex.charIndex += segPtr->size, segPtr = segPtr->nextPtr) {
+	    if (segPtr->typePtr != &tkTextCharType || (!searchElide && TkTextIsElided(textPtr, &curIndex))) {
 		continue;
 	    }
 #ifdef TK_KANJI_OK
--- ../generic/tkText.h.ORIG	Wed Mar 24 11:36:25 1999
+++ ../generic/tkText.h	Wed Mar 24 11:38:58 1999
@@ -378,6 +378,10 @@
 				 * Must be tkTextCharUid, tkTextNoneUid,
 				 * tkTextWordUid, or NULL to use wrapMode
 				 * for whole widget. */
+    char *elideString;	/* -elide option string (malloc-ed).
+				 * NULL means option not specified. */
+    int elide;		/* Non-zero means text is elided.
+				 * Only valid if elideString is non-NULL. */
     int affectsDisplay;		/* Non-zero means that this tag affects the
 				 * way information is displayed on the screen
 				 * (so need to redisplay if tag changes). */
@@ -808,6 +812,8 @@
 			    ClientData clientData));
 extern TkTextIndex *	TkTextMakeIndex _ANSI_ARGS_((TkTextBTree tree,
 			    int lineIndex, int charIndex,
+			    TkTextIndex *indexPtr));
+extern int		TkTextIsElided _ANSI_ARGS_((TkText *textPtr,
 			    TkTextIndex *indexPtr));
 extern int		TkTextMarkCmd _ANSI_ARGS_((TkText *textPtr,
 			    Tcl_Interp *interp, int argc, char **argv));
--- ../generic/tkTextBTree.c.ORIG	Wed Mar 24 11:36:47 1999
+++ ../generic/tkTextBTree.c	Wed Mar 24 11:38:58 1999
@@ -2447,6 +2447,132 @@
     }
     return tagInfo.tagPtrs;
 }
+
+
+/*
+   special case to just return information about elided attribute
+   specialized from TkBTreeGetTags(indexPtr, numTagsPtr) and GetStyle(textPtr, indexPtr)
+   just need to keep track of invisibility settings for each priority, pick highest one active at end
+*/
+int
+TkTextIsElided(textPtr, indexPtr)
+    TkText *textPtr;		/* Overall information about text widget. */
+    TkTextIndex *indexPtr;	/* The character in the text for which
+				 * display information is wanted. */
+{
+#define LOTSA_TAGS 1000
+	int elide = 0;		/* if nobody says otherwise, it's visible */
+
+	int deftagCnts[LOTSA_TAGS];
+	int *tagCnts = deftagCnts;
+	TkTextTag *deftagPtrs[LOTSA_TAGS];
+	TkTextTag **tagPtrs = deftagPtrs;
+	int numTags = textPtr->numTags;
+    register Node *nodePtr;
+    register TkTextLine *siblingLinePtr;
+    register TkTextSegment *segPtr;
+    register TkTextTag *tagPtr;
+    register int i, index;
+
+	/* almost always avoid malloc, so stay out of system calls */
+	if (LOTSA_TAGS < numTags) {
+	    tagCnts = (int *)ckalloc((unsigned)sizeof(int) * numTags);
+	    tagPtrs = (TkTextTag **)ckalloc((unsigned)sizeof(TkTextTag *) * numTags);
+	}
+ 
+	for (i=0; i<numTags; i++) tagCnts[i]=0;
+
+
+    /*
+     * Record tag toggles within the line of indexPtr but preceding
+     * indexPtr.
+     */
+
+    for (index = 0, segPtr = indexPtr->linePtr->segPtr;
+	    (index + segPtr->size) <= indexPtr->charIndex;
+	    index += segPtr->size, segPtr = segPtr->nextPtr) {
+	if ((segPtr->typePtr == &tkTextToggleOnType)
+	    || (segPtr->typePtr == &tkTextToggleOffType)) {
+	    tagPtr = segPtr->body.toggle.tagPtr;
+	    if (tagPtr->elideString != NULL) {
+		   tagPtrs[tagPtr->priority] = tagPtr;
+		   tagCnts[tagPtr->priority]++;
+	    }
+	}
+    }
+
+    /*
+     * Record toggles for tags in lines that are predecessors of
+     * indexPtr->linePtr but under the same level-0 node.
+     */
+
+    for (siblingLinePtr = indexPtr->linePtr->parentPtr->children.linePtr;
+	    siblingLinePtr != indexPtr->linePtr;
+	    siblingLinePtr = siblingLinePtr->nextPtr) {
+	for (segPtr = siblingLinePtr->segPtr; segPtr != NULL;
+		segPtr = segPtr->nextPtr) {
+	    if ((segPtr->typePtr == &tkTextToggleOnType)
+		   || (segPtr->typePtr == &tkTextToggleOffType)) {
+		   tagPtr = segPtr->body.toggle.tagPtr;
+		   if (tagPtr->elideString != NULL) {
+			  tagPtrs[tagPtr->priority] = tagPtr;
+			  tagCnts[tagPtr->priority]++;
+		   }
+	    }
+	}
+    }
+
+    /*
+     * For each node in the ancestry of this line, record tag toggles
+     * for all siblings that precede that node.
+     */
+
+    for (nodePtr = indexPtr->linePtr->parentPtr; nodePtr->parentPtr != NULL;
+	    nodePtr = nodePtr->parentPtr) {
+	register Node *siblingPtr;
+	register Summary *summaryPtr;
+
+	for (siblingPtr = nodePtr->parentPtr->children.nodePtr; 
+		siblingPtr != nodePtr; siblingPtr = siblingPtr->nextPtr) {
+	    for (summaryPtr = siblingPtr->summaryPtr; summaryPtr != NULL;
+		    summaryPtr = summaryPtr->nextPtr) {
+		if (summaryPtr->toggleCount & 1) {
+		    tagPtr = summaryPtr->tagPtr;
+		    if (tagPtr->elideString != NULL) {
+			   tagPtrs[tagPtr->priority] = tagPtr;
+			   tagCnts[tagPtr->priority] += summaryPtr->toggleCount;
+		    }
+		}
+	    }
+	}
+    }
+
+
+    /*
+     * Now traverse from highest priority to lowest, 
+     * take elided value from first odd count (= on)
+     */
+
+    for (i = numTags-1; i >=0; i--) {
+	   if (tagCnts[i] & 1) {
+#ifndef ALWAYS_SHOW_SELECTION
+		  /* who would make the selection elided? */
+		  if ((tagPtr == textPtr->selTagPtr) && !(textPtr->flags & GOT_FOCUS)) {
+			 continue;
+		  }
+#endif
+		  elide = tagPtrs[i]->elide;
+		  break;
+	   }
+    }
+
+    if (LOTSA_TAGS < numTags) {
+	   ckfree((char *) tagCnts);
+	   ckfree((char *) tagPtrs);
+    }
+
+    return elide;
+}
 
 /*
  *----------------------------------------------------------------------
--- ../generic/tkTextDisp.c.ORIG	Wed Mar 24 11:37:14 1999
+++ ../generic/tkTextDisp.c	Wed Mar 24 11:38:59 1999
@@ -59,6 +59,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. */
@@ -321,6 +322,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,
@@ -495,7 +511,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;
@@ -510,7 +526,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;
@@ -628,6 +644,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;
@@ -784,7 +805,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;
 
     /*
@@ -802,6 +823,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
@@ -813,6 +862,7 @@
     lastChunkPtr = NULL;
     chunkPtr = NULL;
     noCharsYet = 1;
+    elide = 0;
     breakChunkPtr = NULL;
     breakCharOffset = 0;
     justify = TK_JUSTIFY_LEFT;
@@ -837,6 +887,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;
@@ -847,6 +922,7 @@
 	    chunkPtr->nextPtr = NULL;
 	}
 	chunkPtr->stylePtr = GetStyle(textPtr, &curIndex);
+	elide = chunkPtr->stylePtr->sValuePtr->elide;
 
 	/*
 	 * Save style information such as justification and indentation,
@@ -880,7 +956,7 @@
 
 	gotTab = 0;
 	maxChars = segPtr->size - offset;
-	if (justify == TK_JUSTIFY_LEFT) {
+	if (!elide && justify == TK_JUSTIFY_LEFT) {
 	    if (segPtr->typePtr == &tkTextCharType) {
 #ifdef TK_KANJI_OK
 		wchar *p;
@@ -896,8 +972,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);
@@ -969,6 +1058,7 @@
 	    offset = 0;
 	    segPtr = segPtr->nextPtr;
 	}
+
 	chunkPtr = NULL;
     }
     if (noCharsYet) {
@@ -1017,6 +1107,7 @@
 	wholeLine = 0;
     }
 
+
     /*
      * Make tab adjustments for the last tab stop, if there is one.
      */
@@ -1340,6 +1431,7 @@
 	    index.linePtr = TkBTreeFindLine(textPtr->tree, lineNum);
 	    index.charIndex = 0;
 	    lowestPtr = NULL;
+
 	    do {
 		dlPtr = LayoutDLine(textPtr, &index);
 		dlPtr->nextPtr = lowestPtr;
@@ -1573,6 +1665,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.
@@ -1639,12 +1733,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,
@@ -1733,6 +1831,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
@@ -1806,7 +1905,7 @@
 	rightX = maxX;
     }
     chunkPtr2 = NULL;
-    if (prevPtr != NULL) {
+    if (prevPtr != NULL && prevPtr->chunkPtr != NULL) {
 	/*
 	 * Find the chunk in the previous line that covers leftX.
 	 */
@@ -1927,7 +2026,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.
 	 */
@@ -2318,6 +2418,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];
@@ -2334,6 +2435,7 @@
 		dlPtr->oldY = dlPtr->y;
 		dlPtr->flags &= ~NEW_LAYOUT;
 	    }
+	    /*prevPtr = dlPtr;*/
 	}
 	Tk_FreePixmap(Tk_Display(textPtr->tkwin), pixmap);
     }
@@ -3388,6 +3490,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)
@@ -3400,7 +3503,7 @@
 		    break;
 		}
 	    }
-    
+
 	    /*
 	     * Discard the display lines, then either return or prepare
 	     * for the next display line to lay out.
@@ -3429,12 +3532,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;
 	}
     }
@@ -3968,7 +4073,7 @@
 				 * index of the character nearest to (x,y). */
 {
     TextDInfo *dInfoPtr = textPtr->dInfoPtr;
-    register DLine *dlPtr;
+    register DLine *dlPtr, *validdlPtr;
     register TkTextDispChunk *chunkPtr;
 
     /*
@@ -4001,8 +4106,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.
@@ -4013,6 +4119,8 @@
 	    break;
 	}
     }
+    if (dlPtr->chunkPtr == NULL) dlPtr = validdlPtr;
+
 
     /*
      * Scan through the line's chunks to find the one that contains
@@ -4024,12 +4132,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;
-	}
+	 }
     }
 
     /*
@@ -4185,6 +4293,7 @@
 {
     TextDInfo *dInfoPtr = textPtr->dInfoPtr;
     DLine *dlPtr;
+    int dlx;
 
     /*
      * Make sure that all of the screen layout information is up to date.
@@ -4203,8 +4312,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;
@@ -4215,6 +4325,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*/;
+}
+
 /*
  *--------------------------------------------------------------
  *
@@ -4480,7 +4625,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;
 #ifdef TK_KANJI_OK
 	wchar *string = ciPtr->chars + offsetChars;
--- ../generic/tkTextTag.c.ORIG	Wed Mar 24 11:37:36 1999
+++ ../generic/tkTextTag.c	Wed Mar 24 11:38:59 1999
@@ -63,6 +63,9 @@
     {TK_CONFIG_STRING, "-underline", (char *) NULL, (char *) NULL,
 	(char *) NULL, Tk_Offset(TkTextTag, underlineString),
 	TK_CONFIG_NULL_OK},
+    {TK_CONFIG_STRING, "-elide", (char *) NULL, (char *) NULL,
+	(char *) NULL, Tk_Offset(TkTextTag, elideString),
+	TK_CONFIG_NULL_OK},
     {TK_CONFIG_UID, "-wrap", (char *) NULL, (char *) NULL,
 	(char *) NULL, Tk_Offset(TkTextTag, wrapMode),
 	TK_CONFIG_NULL_OK},
@@ -378,6 +381,12 @@
 		    return TCL_ERROR;
 		}
 	    }
+	    if (tagPtr->elideString != NULL) {
+		if (Tcl_GetBoolean(interp, tagPtr->elideString,
+			&tagPtr->elide) != TCL_OK) {
+		    return TCL_ERROR;
+		}
+	    }
 	    if ((tagPtr->wrapMode != NULL)
 		    && (tagPtr->wrapMode != tkTextCharUid)
 		    && (tagPtr->wrapMode != tkTextNoneUid)
@@ -419,6 +428,7 @@
 		    || (tagPtr->spacing3String != NULL)
 		    || (tagPtr->tabString != NULL)
 		    || (tagPtr->underlineString != NULL)
+		    || (tagPtr->elideString != NULL)
 		    || (tagPtr->wrapMode != NULL)) {
 		tagPtr->affectsDisplay = 1;
 	    }
@@ -811,6 +821,8 @@
     tagPtr->tabArrayPtr = NULL;
     tagPtr->underlineString = NULL;
     tagPtr->underline = 0;
+    tagPtr->elideString = NULL;
+    tagPtr->elide = 0;
     tagPtr->wrapMode = NULL;
     tagPtr->affectsDisplay = 0;
     textPtr->numTags++;
@@ -934,6 +946,9 @@
     }
     if (tagPtr->underlineString != NULL) {
 	ckfree(tagPtr->underlineString);
+    }
+    if (tagPtr->elideString != NULL) {
+	ckfree(tagPtr->elideString);
     }
     ckfree((char *) tagPtr);
 }
--- ../tests/text.test.ORIG	Wed Mar 24 11:37:58 1999
+++ ../tests/text.test	Wed Mar 24 11:38:59 1999
@@ -862,7 +862,7 @@
 .t insert end "xxyz xyz x. the\nfoo -forward bar xxxxx BaR foo\nxyz xxyzx"
 test text-20.1 {TextSearchCmd procedure, argument parsing} {
     list [catch {.t search -} msg] $msg
-} {1 {bad switch "-": must be -forward, -backward, -exact, -regexp, -nocase, -count, or --}}
+} {1 {bad switch "-": must be -forward, -backward, -exact, -regexp, -nocase, -count, -elide, or --}}
 test text-20.2 {TextSearchCmd procedure, -backwards option} {
     .t search -backwards xyz 1.4
 } {1.1}
