diff options
author | fvogel <fvogelnew1@free.fr> | 2020-07-13 16:48:27 (GMT) |
---|---|---|
committer | fvogel <fvogelnew1@free.fr> | 2020-07-13 16:48:27 (GMT) |
commit | e3c3dc8cec595c0593949fa1a690e842ae88df76 (patch) | |
tree | 5cd95ac9a88a4f35c5067b2238a9e2b39b4308e4 | |
parent | 056dad5a85b3eb0404c0a805562fd207c8eb8217 (diff) | |
parent | 3513bf85582d9033914baf40f8e8a1fb42270d93 (diff) | |
download | tk-e3c3dc8cec595c0593949fa1a690e842ae88df76.zip tk-e3c3dc8cec595c0593949fa1a690e842ae88df76.tar.gz tk-e3c3dc8cec595c0593949fa1a690e842ae88df76.tar.bz2 |
Fix [7655f65ae7]: text positioning issues in entry widgets. Patch from Christopher Chavez.
-rw-r--r-- | generic/tkEntry.c | 68 | ||||
-rw-r--r-- | generic/tkFont.c | 35 | ||||
-rw-r--r-- | generic/tkInt.h | 4 | ||||
-rw-r--r-- | generic/ttk/ttkEntry.c | 39 | ||||
-rw-r--r-- | library/fontchooser.tcl | 2 | ||||
-rw-r--r-- | macosx/tkMacOSXFont.c | 20 | ||||
-rw-r--r-- | macosx/tkMacOSXInt.h | 2 | ||||
-rw-r--r-- | unix/tkUnixFont.c | 35 | ||||
-rw-r--r-- | unix/tkUnixRFont.c | 83 | ||||
-rw-r--r-- | win/tkWinFont.c | 36 |
10 files changed, 275 insertions, 49 deletions
diff --git a/generic/tkEntry.c b/generic/tkEntry.c index 906ba43..4c6c65f 100644 --- a/generic/tkEntry.c +++ b/generic/tkEntry.c @@ -1766,34 +1766,56 @@ DisplayEntry( } } - /* - * Draw the text in two pieces: first the unselected portion, then the - * selected portion on top of it. - */ + if ((entryPtr->numChars == 0) && (entryPtr->placeholderChars != 0)) { - if ((entryPtr->numChars != 0) || (entryPtr->placeholderChars == 0)) { - Tk_DrawTextLayout(entryPtr->display, pixmap, entryPtr->textGC, - entryPtr->textLayout, entryPtr->layoutX, entryPtr->layoutY, - entryPtr->leftIndex, entryPtr->numChars); - } else { - Tk_DrawTextLayout(entryPtr->display, pixmap, entryPtr->placeholderGC, + /* + * Draw the placeholder text. + */ + + Tk_DrawTextLayout(entryPtr->display, pixmap, entryPtr->placeholderGC, entryPtr->placeholderLayout, entryPtr->placeholderX, entryPtr->layoutY, entryPtr->placeholderLeftIndex, entryPtr->placeholderChars); - } - if (showSelection && (entryPtr->state != STATE_DISABLED) - && (entryPtr->selTextGC != entryPtr->textGC) - && (entryPtr->selectFirst + 1 < entryPtr->selectLast + 1)) { - int selFirst; + } else { - if (entryPtr->selectFirst + 1 < entryPtr->leftIndex + 1) { - selFirst = entryPtr->leftIndex; - } else { - selFirst = entryPtr->selectFirst; - } - Tk_DrawTextLayout(entryPtr->display, pixmap, entryPtr->selTextGC, - entryPtr->textLayout, entryPtr->layoutX, entryPtr->layoutY, - selFirst, entryPtr->selectLast); + if (showSelection && (entryPtr->state != STATE_DISABLED) + && (entryPtr->selTextGC != entryPtr->textGC) + && (entryPtr->selectFirst + 1 < entryPtr->selectLast + 1)) { + + /* + * Draw the selected and unselected portions separately. + */ + + int selFirst; + + if (entryPtr->selectFirst + 1 < entryPtr->leftIndex + 1) { + selFirst = entryPtr->leftIndex; + } else { + selFirst = entryPtr->selectFirst; + } + if (entryPtr->leftIndex < selFirst) { + Tk_DrawTextLayout(entryPtr->display, pixmap, entryPtr->textGC, + entryPtr->textLayout, entryPtr->layoutX, entryPtr->layoutY, + entryPtr->leftIndex, selFirst); + } + Tk_DrawTextLayout(entryPtr->display, pixmap, entryPtr->selTextGC, + entryPtr->textLayout, entryPtr->layoutX, entryPtr->layoutY, + selFirst, entryPtr->selectLast); + if (entryPtr->selectLast < entryPtr->numChars) { + Tk_DrawTextLayout(entryPtr->display, pixmap, entryPtr->textGC, + entryPtr->textLayout, entryPtr->layoutX, entryPtr->layoutY, + entryPtr->selectLast, entryPtr->numChars); + } + } else { + + /* + * Draw the entire visible text + */ + + Tk_DrawTextLayout(entryPtr->display, pixmap, entryPtr->textGC, + entryPtr->textLayout, entryPtr->layoutX, entryPtr->layoutY, + entryPtr->leftIndex, entryPtr->numChars); + } } if (entryPtr->type == TK_SPINBOX) { diff --git a/generic/tkFont.c b/generic/tkFont.c index 98a10f4..5fed4f3 100644 --- a/generic/tkFont.c +++ b/generic/tkFont.c @@ -13,6 +13,9 @@ #include "tkInt.h" #include "tkFont.h" +#if defined(MAC_OSX_TK) +#include "tkMacOSXInt.h" /* Defines TK_DRAW_IN_CONTEXT */ +#endif /* * The following structure is used to keep track of all the fonts that exist @@ -2291,12 +2294,16 @@ Tk_DrawTextLayout( int x, int y, /* Upper-left hand corner of rectangle in * which to draw (pixels). */ int firstChar, /* The index of the first character to draw - * from the given text item. 0 specfies the + * from the given text item. 0 specifies the * beginning. */ int lastChar) /* The index just after the last character to * draw from the given text item. A number < 0 * means to draw all characters. */ { +#if 0 + /* Use TkDrawAngledTextLayout() implementation - testing purposes at this point */ + TkDrawAngledTextLayout(display, drawable, gc, layout, x, y, 0.0, firstChar, lastChar); +#else TextLayout *layoutPtr = (TextLayout *) layout; int i, numDisplayChars, drawX; const char *firstByte, *lastByte; @@ -2326,8 +2333,15 @@ Tk_DrawTextLayout( numDisplayChars = lastChar; } lastByte = Tcl_UtfAtIndex(chunkPtr->start, numDisplayChars); +#if TK_DRAW_IN_CONTEXT + TkpDrawCharsInContext(display, drawable, gc, layoutPtr->tkfont, + chunkPtr->start, chunkPtr->numBytes, + firstByte - chunkPtr->start, lastByte - firstByte, + x+chunkPtr->x, y+chunkPtr->y); +#else /* !TK_DRAW_IN_CONTEXT */ Tk_DrawChars(display, drawable, gc, layoutPtr->tkfont, firstByte, lastByte - firstByte, x+chunkPtr->x+drawX, y+chunkPtr->y); +#endif /* TK_DRAW_IN_CONTEXT */ } firstChar -= chunkPtr->numChars; lastChar -= chunkPtr->numChars; @@ -2336,6 +2350,7 @@ Tk_DrawTextLayout( } chunkPtr++; } +#endif /* Use TkDrawAngledTextLayout() implementation */ } void @@ -2350,7 +2365,7 @@ TkDrawAngledTextLayout( * which to draw (pixels). */ double angle, int firstChar, /* The index of the first character to draw - * from the given text item. 0 specfies the + * from the given text item. 0 specifies the * beginning. */ int lastChar) /* The index just after the last character to * draw from the given text item. A number < 0 @@ -2388,6 +2403,21 @@ TkDrawAngledTextLayout( numDisplayChars = lastChar; } lastByte = Tcl_UtfAtIndex(chunkPtr->start, numDisplayChars); +#if TK_DRAW_IN_CONTEXT + dx = cosA * (chunkPtr->x) + sinA * (chunkPtr->y); + dy = -sinA * (chunkPtr->x) + cosA * (chunkPtr->y); + if (angle == 0.0) { + TkpDrawCharsInContext(display, drawable, gc, + layoutPtr->tkfont, chunkPtr->start, chunkPtr->numBytes, + firstByte - chunkPtr->start, lastByte - firstByte, + (int)(x + dx), (int)(y + dy)); + } else { + TkpDrawAngledCharsInContext(display, drawable, gc, + layoutPtr->tkfont, chunkPtr->start, chunkPtr->numBytes, + firstByte - chunkPtr->start, lastByte - firstByte, + x+dx, y+dy, angle); + } +#else /* !TK_DRAW_IN_CONTEXT */ dx = cosA * (chunkPtr->x + drawX) + sinA * (chunkPtr->y); dy = -sinA * (chunkPtr->x + drawX) + cosA * (chunkPtr->y); if (angle == 0.0) { @@ -2398,6 +2428,7 @@ TkDrawAngledTextLayout( TkDrawAngledChars(display, drawable, gc, layoutPtr->tkfont, firstByte, lastByte - firstByte, x+dx, y+dy, angle); } +#endif /* TK_DRAW_IN_CONTEXT */ } firstChar -= chunkPtr->numChars; lastChar -= chunkPtr->numChars; diff --git a/generic/tkInt.h b/generic/tkInt.h index efb5531..2131110 100644 --- a/generic/tkInt.h +++ b/generic/tkInt.h @@ -1317,6 +1317,10 @@ MODULE_SCOPE void TkpDrawCharsInContext(Display * display, Drawable drawable, GC gc, Tk_Font tkfont, const char *source, int numBytes, int rangeStart, int rangeLength, int x, int y); +MODULE_SCOPE void TkpDrawAngledCharsInContext(Display * display, + Drawable drawable, GC gc, Tk_Font tkfont, + const char *source, int numBytes, int rangeStart, + int rangeLength, double x, double y, double angle); MODULE_SCOPE int TkpMeasureCharsInContext(Tk_Font tkfont, const char *source, int numBytes, int rangeStart, int rangeLength, int maxLength, int flags, diff --git a/generic/ttk/ttkEntry.c b/generic/ttk/ttkEntry.c index cbc3b3f..4314a83 100644 --- a/generic/ttk/ttkEntry.c +++ b/generic/ttk/ttkEntry.c @@ -1317,16 +1317,27 @@ static void EntryDisplay(void *clientData, Drawable d) foregroundObj = es.foregroundObj; } gc = EntryGetGC(entryPtr, foregroundObj, clipRegion); - Tk_DrawTextLayout( - Tk_Display(tkwin), d, gc, entryPtr->entry.textLayout, - entryPtr->entry.layoutX, entryPtr->entry.layoutY, - leftIndex, rightIndex); - XSetClipMask(Tk_Display(tkwin), gc, None); - Tk_FreeGC(Tk_Display(tkwin), gc); - - /* Overwrite the selected portion (if any) in the -selectforeground color: - */ if (showSelection) { + + /* Draw the selected and unselected portions separately. + */ + if (leftIndex < selFirst) { + Tk_DrawTextLayout( + Tk_Display(tkwin), d, gc, entryPtr->entry.textLayout, + entryPtr->entry.layoutX, entryPtr->entry.layoutY, + leftIndex, selFirst); + } + if (selLast < rightIndex) { + Tk_DrawTextLayout( + Tk_Display(tkwin), d, gc, entryPtr->entry.textLayout, + entryPtr->entry.layoutX, entryPtr->entry.layoutY, + selLast, rightIndex); + } + XSetClipMask(Tk_Display(tkwin), gc, None); + Tk_FreeGC(Tk_Display(tkwin), gc); + + /* Draw the selected portion in the -selectforeground color: + */ gc = EntryGetGC(entryPtr, es.selForegroundObj, clipRegion); Tk_DrawTextLayout( Tk_Display(tkwin), d, gc, entryPtr->entry.textLayout, @@ -1334,6 +1345,16 @@ static void EntryDisplay(void *clientData, Drawable d) selFirst, selLast); XSetClipMask(Tk_Display(tkwin), gc, None); Tk_FreeGC(Tk_Display(tkwin), gc); + } else { + + /* Draw the entire visible text + */ + Tk_DrawTextLayout( + Tk_Display(tkwin), d, gc, entryPtr->entry.textLayout, + entryPtr->entry.layoutX, entryPtr->entry.layoutY, + leftIndex, rightIndex); + XSetClipMask(Tk_Display(tkwin), gc, None); + Tk_FreeGC(Tk_Display(tkwin), gc); } /* Drop the region. Note that we have to manually remove the reference to diff --git a/library/fontchooser.tcl b/library/fontchooser.tcl index 0510fb9..3e2b6df 100644 --- a/library/fontchooser.tcl +++ b/library/fontchooser.tcl @@ -280,7 +280,7 @@ proc ::tk::fontchooser::Create {} { # Arguments: # ok true if user pressed OK # -proc ::tk::::fontchooser::Done {ok} { +proc ::tk::fontchooser::Done {ok} { variable S if {! $ok} { diff --git a/macosx/tkMacOSXFont.c b/macosx/tkMacOSXFont.c index 7527429..0aab1cf 100644 --- a/macosx/tkMacOSXFont.c +++ b/macosx/tkMacOSXFont.c @@ -93,10 +93,6 @@ static void InitFont(NSFont *nsFont, static int CreateNamedSystemFont(Tcl_Interp *interp, Tk_Window tkwin, const char *name, TkFontAttributes *faPtr); -static void DrawCharsInContext(Display *display, Drawable drawable, - GC gc, Tk_Font tkfont, const char *source, - int numBytes, int rangeStart, int rangeLength, - int x, int y, double angle); #pragma mark - #pragma mark Font Helpers: @@ -1066,7 +1062,7 @@ done: * Draw a string of characters on the screen. * * With ATSUI we need the line context to do this right, so we have the - * actual implementation in TkpDrawCharsInContext(). + * actual implementation in TkpDrawAngledCharsInContext(). * * Results: * None. @@ -1095,7 +1091,7 @@ Tk_DrawChars( int x, int y) /* Coordinates at which to place origin of the * string when drawing. */ { - DrawCharsInContext(display, drawable, gc, tkfont, source, numBytes, + TkpDrawAngledCharsInContext(display, drawable, gc, tkfont, source, numBytes, 0, numBytes, x, y, 0.0); } @@ -1118,7 +1114,7 @@ TkDrawAngledChars( * string when drawing. */ double angle) /* What angle to put text at, in degrees. */ { - DrawCharsInContext(display, drawable, gc, tkfont, source, numBytes, + TkpDrawAngledCharsInContext(display, drawable, gc, tkfont, source, numBytes, 0, numBytes, x, y, angle); } @@ -1164,12 +1160,12 @@ TkpDrawCharsInContext( * drawing. */ { (void)display; - DrawCharsInContext(display, drawable, gc, tkfont, source, numBytes, + TkpDrawAngledCharsInContext(display, drawable, gc, tkfont, source, numBytes, rangeStart, rangeLength, x, y, 0.0); } -static void -DrawCharsInContext( +void +TkpDrawAngledCharsInContext( Display *display, /* Display on which to draw. */ Drawable drawable, /* Window or pixmap in which to draw. */ GC gc, /* Graphics context for drawing characters. */ @@ -1185,10 +1181,10 @@ DrawCharsInContext( int numBytes, /* Number of bytes in string. */ int rangeStart, /* Index of first byte to draw. */ int rangeLength, /* Length of range to draw in bytes. */ - int x, int y, /* Coordinates at which to place origin of the + double x, double y, /* Coordinates at which to place origin of the * whole (not just the range) string when * drawing. */ - double angle) + double angle) /* What angle to put text at, in degrees. */ { const MacFont *fontPtr = (const MacFont *) tkfont; NSString *string; diff --git a/macosx/tkMacOSXInt.h b/macosx/tkMacOSXInt.h index 5d03746..d658204 100644 --- a/macosx/tkMacOSXInt.h +++ b/macosx/tkMacOSXInt.h @@ -180,7 +180,7 @@ MODULE_SCOPE void TkpFreeGCCache(GC gc); #define TK_MACOSX_HANDLE_EVENT_IMMEDIATELY 1024 /* - * Defines for tkTextDisp.c + * Defines for tkTextDisp.c and tkFont.c */ #define TK_LAYOUT_WITH_BASE_CHUNKS 1 diff --git a/unix/tkUnixFont.c b/unix/tkUnixFont.c index 1b7b50d..400e610 100644 --- a/unix/tkUnixFont.c +++ b/unix/tkUnixFont.c @@ -1373,6 +1373,9 @@ Tk_DrawChars( * with access to all the characters on the line for context. On X11 this * context isn't consulted, so we just call Tk_DrawChars(). * + * Note: TK_DRAW_IN_CONTEXT being currently defined only on macOS, this + * function is unused (and possibly unfinished). See [7655f65ae7]. + * * Results: * None. * @@ -1410,6 +1413,38 @@ TkpDrawCharsInContext( rangeLength, x+widthUntilStart, y); } +void +TkpDrawAngledCharsInContext( + Display *display, /* Display on which to draw. */ + Drawable drawable, /* Window or pixmap in which to draw. */ + GC gc, /* Graphics context for drawing characters. */ + Tk_Font tkfont, /* Font in which characters will be drawn; must + * be the same as font used in GC. */ + const char * source, /* UTF-8 string to be displayed. Need not be + * '\0' terminated. All Tk meta-characters + * (tabs, control characters, and newlines) + * should be stripped out of the string that is + * passed to this function. If they are not + * stripped out, they will be displayed as + * regular printing characters. */ + int numBytes, /* Number of bytes in string. */ + int rangeStart, /* Index of first byte to draw. */ + int rangeLength, /* Length of range to draw in bytes. */ + double x, double y, /* Coordinates at which to place origin of the + * whole (not just the range) string when + * drawing. */ + double angle) /* What angle to put text at, in degrees. */ +{ + int widthUntilStart; + double sinA = sin(angle * PI/180.0), cosA = cos(angle * PI/180.0); + + (void) numBytes; /*unused*/ + + Tk_MeasureChars(tkfont, source, rangeStart, -1, 0, &widthUntilStart); + TkDrawAngledChars(display, drawable, gc, tkfont, source + rangeStart, + rangeLength, x+cosA*widthUntilStart, y-sinA*widthUntilStart, angle); +} + /* *------------------------------------------------------------------------- * diff --git a/unix/tkUnixRFont.c b/unix/tkUnixRFont.c index c154f96..d277db8 100644 --- a/unix/tkUnixRFont.c +++ b/unix/tkUnixRFont.c @@ -1306,6 +1306,89 @@ TkDrawAngledChars( } } +/* + *--------------------------------------------------------------------------- + * + * TkpDrawCharsInContext -- + * + * Draw a string of characters on the screen like Tk_DrawChars(), but + * with access to all the characters on the line for context. On X11 this + * context isn't consulted, so we just call Tk_DrawChars(). + * + * Note: TK_DRAW_IN_CONTEXT being currently defined only on macOS, this + * function is unused (and possibly unfinished). See [7655f65ae7]. + * + * Results: + * None. + * + * Side effects: + * Information gets drawn on the screen. + * + *--------------------------------------------------------------------------- + */ + +void +TkpDrawCharsInContext( + Display *display, /* Display on which to draw. */ + Drawable drawable, /* Window or pixmap in which to draw. */ + GC gc, /* Graphics context for drawing characters. */ + Tk_Font tkfont, /* Font in which characters will be drawn; + * must be the same as font used in GC. */ + const char *source, /* UTF-8 string to be displayed. Need not be + * '\0' terminated. All Tk meta-characters + * (tabs, control characters, and newlines) + * should be stripped out of the string that + * is passed to this function. If they are not + * stripped out, they will be displayed as + * regular printing characters. */ + int numBytes, /* Number of bytes in string. */ + int rangeStart, /* Index of first byte to draw. */ + int rangeLength, /* Length of range to draw in bytes. */ + int x, int y) /* Coordinates at which to place origin of the + * whole (not just the range) string when + * drawing. */ +{ + int widthUntilStart; + + (void) numBytes; /*unused*/ + + Tk_MeasureChars(tkfont, source, rangeStart, -1, 0, &widthUntilStart); + Tk_DrawChars(display, drawable, gc, tkfont, source + rangeStart, + rangeLength, x+widthUntilStart, y); +} + +void +TkpDrawAngledCharsInContext( + Display *display, /* Display on which to draw. */ + Drawable drawable, /* Window or pixmap in which to draw. */ + GC gc, /* Graphics context for drawing characters. */ + Tk_Font tkfont, /* Font in which characters will be drawn; must + * be the same as font used in GC. */ + const char * source, /* UTF-8 string to be displayed. Need not be + * '\0' terminated. All Tk meta-characters + * (tabs, control characters, and newlines) + * should be stripped out of the string that is + * passed to this function. If they are not + * stripped out, they will be displayed as + * regular printing characters. */ + int numBytes, /* Number of bytes in string. */ + int rangeStart, /* Index of first byte to draw. */ + int rangeLength, /* Length of range to draw in bytes. */ + double x, double y, /* Coordinates at which to place origin of the + * whole (not just the range) string when + * drawing. */ + double angle) /* What angle to put text at, in degrees. */ +{ + int widthUntilStart; + double sinA = sin(angle * PI/180.0), cosA = cos(angle * PI/180.0); + + (void) numBytes; /*unused*/ + + Tk_MeasureChars(tkfont, source, rangeStart, -1, 0, &widthUntilStart); + TkDrawAngledChars(display, drawable, gc, tkfont, source + rangeStart, + rangeLength, x+cosA*widthUntilStart, y-sinA*widthUntilStart, angle); +} + void TkUnixSetXftClipRegion( Region clipRegion) /* The clipping region to install. */ diff --git a/win/tkWinFont.c b/win/tkWinFont.c index 75578de..e1bbd53 100644 --- a/win/tkWinFont.c +++ b/win/tkWinFont.c @@ -1361,7 +1361,10 @@ TkDrawAngledChars( * Draw a string of characters on the screen like Tk_DrawChars(), but * with access to all the characters on the line for context. On Windows * this context isn't consulted, so we just call Tk_DrawChars(). - * + * + * Note: TK_DRAW_IN_CONTEXT being currently defined only on macOS, this + * function is unused (and possibly unfinished). See [7655f65ae7]. +* * Results: * None. * @@ -1399,6 +1402,37 @@ TkpDrawCharsInContext( rangeLength, x+widthUntilStart, y); } +void +TkpDrawAngledCharsInContext( + Display *display, /* Display on which to draw. */ + Drawable drawable, /* Window or pixmap in which to draw. */ + GC gc, /* Graphics context for drawing characters. */ + Tk_Font tkfont, /* Font in which characters will be drawn; must + * be the same as font used in GC. */ + const char * source, /* UTF-8 string to be displayed. Need not be + * '\0' terminated. All Tk meta-characters + * (tabs, control characters, and newlines) + * should be stripped out of the string that is + * passed to this function. If they are not + * stripped out, they will be displayed as + * regular printing characters. */ + int numBytes, /* Number of bytes in string. */ + int rangeStart, /* Index of first byte to draw. */ + int rangeLength, /* Length of range to draw in bytes. */ + double x, double y, /* Coordinates at which to place origin of the + * whole (not just the range) string when + * drawing. */ + double angle) /* What angle to put text at, in degrees. */ +{ + int widthUntilStart; + double sinA = sin(angle * PI/180.0), cosA = cos(angle * PI/180.0); + (void) numBytes; /*unused*/ + + Tk_MeasureChars(tkfont, source, rangeStart, -1, 0, &widthUntilStart); + TkDrawAngledChars(display, drawable, gc, tkfont, source + rangeStart, + rangeLength, x+cosA*widthUntilStart, y-sinA*widthUntilStart, angle); +} + /* *------------------------------------------------------------------------- * |