Subject: -underlinefg tag configuration option: implementation

From: fvogel <[email-masked]>
Date: Tue, 9 Feb 2016 21:40:51 +0000

---
 generic/tkText.c     |  3 ++-
 generic/tkText.h     |  4 +++-
 generic/tkTextDisp.c | 19 +++++++++++++++++--
 generic/tkTextTag.c  |  6 +++++-
 4 files changed, 27 insertions(+), 5 deletions(-)

diff --git a/generic/tkText.c b/generic/tkText.c
index ccc9691..7010601 100644
--- a/generic/tkText.c
+++ b/generic/tkText.c
@@ -2294,7 +2294,8 @@ ConfigureText(
 	    || (textPtr->selTagPtr->fgStipple != None)
 	    || (textPtr->selTagPtr->selFgStipple != None)
 	    || (textPtr->selTagPtr->overstrikeString != NULL)
-	    || (textPtr->selTagPtr->underlineString != NULL)) {
+	    || (textPtr->selTagPtr->underlineString != NULL)
+	    || (textPtr->selTagPtr->underlineColor != NULL)) {
 	textPtr->selTagPtr->affectsDisplay = 1;
     }
     TkTextRedrawTag(NULL, textPtr, NULL, NULL, textPtr->selTagPtr, 1);
diff --git a/generic/tkText.h b/generic/tkText.h
index 1a7d986..815841c 100644
--- a/generic/tkText.h
+++ b/generic/tkText.h
@@ -398,7 +398,9 @@ typedef struct TkTextTag {
     int underline;		/* Non-zero means draw underline underneath
 				 * text. Only valid if underlineString is
 				 * non-NULL. */
-    TkWrapMode wrapMode;	/* How to handle wrap-around for this tag.
+    XColor *underlineColor;     /* Color for the underline. NULL means same
+                                 * color as foreground. */
+    TkWrapMode wrapMode;	/* How to hsandle wrap-around for this tag.
 				 * Must be TEXT_WRAPMODE_CHAR,
 				 * TEXT_WRAPMODE_NONE, TEXT_WRAPMODE_WORD, or
 				 * TEXT_WRAPMODE_NULL to use wrapmode for
diff --git a/generic/tkTextDisp.c b/generic/tkTextDisp.c
index d0c1483..f246818 100644
--- a/generic/tkTextDisp.c
+++ b/generic/tkTextDisp.c
@@ -149,6 +149,8 @@ typedef struct StyleValues {
     int tabStyle;		/* One of TABULAR or WORDPROCESSOR. */
     int underline;		/* Non-zero means draw underline underneath
 				 * text. */
+    XColor *underlineColor;	/* Foreground color for underline underneath
+                                 * text. */
     int elide;			/* Zero means draw text, otherwise not. */
     TkWrapMode wrapMode;	/* How to handle wrap-around for this tag.
 				 * One of TEXT_WRAPMODE_CHAR,
@@ -166,6 +168,7 @@ typedef struct TextStyle {
 				 * referenced in Chunks. */
     GC bgGC;			/* Graphics context for background. None means
 				 * use widget background. */
+    GC ulGC;			/* Graphics context for underline. */
     GC fgGC;			/* Graphics context for foreground. */
     StyleValues *sValuePtr;	/* Raw information from which GCs were
 				 * derived. */
@@ -778,6 +781,7 @@ GetStyle(
     memset(&styleValues, 0, sizeof(StyleValues));
     styleValues.relief = TK_RELIEF_FLAT;
     styleValues.fgColor = textPtr->fgColor;
+    styleValues.underlineColor = textPtr->fgColor;
     styleValues.tkfont = textPtr->tkfont;
     styleValues.justify = TK_JUSTIFY_LEFT;
     styleValues.spacing1 = textPtr->spacing1;
@@ -937,6 +941,11 @@ GetStyle(
 		&& (tagPtr->priority > underlinePrio)) {
 	    styleValues.underline = tagPtr->underline;
 	    underlinePrio = tagPtr->priority;
+            if (tagPtr->underlineColor != None) {
+                 styleValues.underlineColor = tagPtr->underlineColor;
+            } else if (fgColor != None) {
+                 styleValues.underlineColor = fgColor;
+            }
 	}
 	if ((tagPtr->elideString != NULL)
 		&& (tagPtr->priority > elidePrio)) {
@@ -993,6 +1002,9 @@ GetStyle(
 	mask |= GCStipple|GCFillStyle;
     }
     stylePtr->fgGC = Tk_GetGC(textPtr->tkwin, mask, &gcValues);
+    mask = GCForeground;
+    gcValues.foreground = styleValues.underlineColor->pixel;
+    stylePtr->ulGC = Tk_GetGC(textPtr->tkwin, mask, &gcValues);
     stylePtr->sValuePtr = (StyleValues *)
 	    Tcl_GetHashKey(&textPtr->dInfoPtr->styleTable, hPtr);
     stylePtr->hPtr = hPtr;
@@ -1033,6 +1045,9 @@ FreeStyle(
 	if (stylePtr->fgGC != None) {
 	    Tk_FreeGC(textPtr->display, stylePtr->fgGC);
 	}
+	if (stylePtr->ulGC != None) {
+	    Tk_FreeGC(textPtr->display, stylePtr->ulGC);
+	}
 	Tcl_DeleteHashEntry(stylePtr->hPtr);
 	ckfree(stylePtr);
     }
@@ -7876,7 +7891,7 @@ CharDisplayProc(
 		y + baseline - sValuePtr->offset);
 
 	if (sValuePtr->underline) {
-	    TkUnderlineCharsInContext(display, dst, stylePtr->fgGC,
+	    TkUnderlineCharsInContext(display, dst, stylePtr->ulGC,
 		    sValuePtr->tkfont, string, numBytes,
 		    ciPtr->baseChunkPtr->x + xDisplacement,
 		    y + baseline - sValuePtr->offset,
@@ -7903,7 +7918,7 @@ CharDisplayProc(
 	Tk_DrawChars(display, dst, stylePtr->fgGC, sValuePtr->tkfont, string,
 		numBytes, offsetX, y + baseline - sValuePtr->offset);
 	if (sValuePtr->underline) {
-	    Tk_UnderlineChars(display, dst, stylePtr->fgGC, sValuePtr->tkfont,
+	    Tk_UnderlineChars(display, dst, stylePtr->ulGC, sValuePtr->tkfont,
 		    string, offsetX,
 		    y + baseline - sValuePtr->offset,
 		    0, numBytes);
diff --git a/generic/tkTextTag.c b/generic/tkTextTag.c
index bb512e4..ed0ef98 100644
--- a/generic/tkTextTag.c
+++ b/generic/tkTextTag.c
@@ -92,6 +92,8 @@ static const Tk_OptionSpec tagOptionSpecs[] = {
     {TK_OPTION_STRING, "-underline", NULL, NULL,
 	NULL, -1, Tk_Offset(TkTextTag, underlineString),
 	TK_OPTION_NULL_OK, 0, 0},
+    {TK_OPTION_COLOR, "-underlinefg", NULL, NULL,
+	NULL, -1, Tk_Offset(TkTextTag, underlineColor), TK_OPTION_NULL_OK, 0, 0},
     {TK_OPTION_STRING_TABLE, "-wrap", NULL, NULL,
 	NULL, -1, Tk_Offset(TkTextTag, wrapMode),
 	TK_OPTION_NULL_OK, wrapStrings, 0},
@@ -534,7 +536,8 @@ TkTextTagCmd(
 		    || (tagPtr->fgStipple != None)
 		    || (tagPtr->selFgStipple != None)
 		    || (tagPtr->overstrikeString != NULL)
-		    || (tagPtr->underlineString != NULL)) {
+		    || (tagPtr->underlineString != NULL)
+                    || (tagPtr->underlineColor != NULL)) {
 		tagPtr->affectsDisplay = 1;
 	    }
 	    if (!newTag) {
@@ -1052,6 +1055,7 @@ TkTextCreateTag(
     tagPtr->tabStyle = TK_TEXT_TABSTYLE_NONE;
     tagPtr->underlineString = NULL;
     tagPtr->underline = 0;
+    tagPtr->underlineColor = NULL;
     tagPtr->elideString = NULL;
     tagPtr->elide = 0;
     tagPtr->wrapMode = TEXT_WRAPMODE_NULL;
-- 
cgit v0.12