Tk Source Code

Changes On Branch 5d0bc3cf-text-blockcursor
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Changes In Branch 5d0bc3cf-text-blockcursor Excluding Merge-Ins

This is equivalent to a diff from f302dd87 to 82feefa9

2025-05-02
06:51
[5d0bc3cf] Second half of Androwish commit https://androwish.org/home/info/ae43177ce04ec244 Closed-Leaf check-in: 82feefa9 user: oehhar tags: 5d0bc3cf-text-blockcursor
06:44
[5d0bc3cf] add androwish commit https://androwish.org/home/info/85ea46a8c74b8f6f check-in: c3c9b7cd user: oehhar tags: 5d0bc3cf-text-blockcursor
2025-04-03
16:24
Merge 9.0 check-in: d112bcc7 user: jan.nijtmans tags: trunk, main
15:11
Ticket [5d0bc3cf] Fix block cursor of text widget. Original contribution for 8.6 by Christian Werner (thanks) check-in: 5263ef5e user: oehhar tags: 5d0bc3cf-text-blockcursor
2025-04-02
02:13
Merge trunk check-in: ba1f4e33 user: kevin_walzer tags: tka11y
00:25
alternative implementation for TIP#714 check-in: fd9694da user: emiliano tags: tip-714-alt
2025-03-29
21:54
Merge trunk check-in: 5db61557 user: erikleunissen tags: tk_collect_test_utils
20:55
tests/constraints.tcl [testmenubarheight]: correct condition that tests existence of C-level command Leaf check-in: c7bc16c1 user: erikleunissen tags: core-8-branch
20:50
tests/constraints.tcl [testmenubarheight]: correct condition that tests existence of C-level command check-in: 4d3b0805 user: erikleunissen tags: core-9-0-branch
20:42
tests/constraints.tcl [testmenubarheight]: correct condition that tests existence of C-level command check-in: f302dd87 user: erikleunissen tags: trunk, main
2025-03-27
10:15
Ticket [25b84e1246] Removal of old image code leftover check-in: 9087179e user: oehhar tags: trunk, main

Changes to generic/tkText.c.
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
	}
	indexPtr = TkTextGetIndexFromObj(interp, textPtr, objv[2]);
	if (indexPtr == NULL) {
	    result = TCL_ERROR;
	    goto done;
	}
	if (TkTextIndexBbox(textPtr, indexPtr, &x, &y, &width, &height,
		NULL) == 0) {
	    Tcl_Obj *listObj = Tcl_NewListObj(0, NULL);

	    Tcl_ListObjAppendElement(interp, listObj, Tcl_NewWideIntObj(x));
	    Tcl_ListObjAppendElement(interp, listObj, Tcl_NewWideIntObj(y));
	    Tcl_ListObjAppendElement(interp, listObj, Tcl_NewWideIntObj(width));
	    Tcl_ListObjAppendElement(interp, listObj, Tcl_NewWideIntObj(height));








|







716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
	}
	indexPtr = TkTextGetIndexFromObj(interp, textPtr, objv[2]);
	if (indexPtr == NULL) {
	    result = TCL_ERROR;
	    goto done;
	}
	if (TkTextIndexBbox(textPtr, indexPtr, &x, &y, &width, &height,
		NULL, NULL) == 0) {
	    Tcl_Obj *listObj = Tcl_NewListObj(0, NULL);

	    Tcl_ListObjAppendElement(interp, listObj, Tcl_NewWideIntObj(x));
	    Tcl_ListObjAppendElement(interp, listObj, Tcl_NewWideIntObj(y));
	    Tcl_ListObjAppendElement(interp, listObj, Tcl_NewWideIntObj(width));
	    Tcl_ListObjAppendElement(interp, listObj, Tcl_NewWideIntObj(height));

3729
3730
3731
3732
3733
3734
3735
3736

3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
    } else {
	textPtr->flags |= INSERT_ON;
	textPtr->insertBlinkHandler = Tcl_CreateTimerHandler(
		textPtr->insertOnTime, TextBlinkProc, textPtr);
    }
  redrawInsert:
    TkTextMarkSegToIndex(textPtr, textPtr->insertMarkPtr, &index);
    if (TkTextIndexBbox(textPtr, &index, &x, &y, &w, &h, &charWidth) == 0) {

	int insertWidth;
	Tk_GetPixelsFromObj(NULL, textPtr->tkwin, textPtr->insertWidthObj, &insertWidth);
	if (textPtr->insertCursorType) {
	    /* Block cursor */
	    TkTextRedrawRegion(textPtr, x - textPtr->width / 2, y,
		    charWidth + insertWidth / 2, h);
	} else {
	    /* I-beam cursor */
	    TkTextRedrawRegion(textPtr, x - insertWidth / 2, y,
		    insertWidth, h);
	}
    }







|
>




|







3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
    } else {
	textPtr->flags |= INSERT_ON;
	textPtr->insertBlinkHandler = Tcl_CreateTimerHandler(
		textPtr->insertOnTime, TextBlinkProc, textPtr);
    }
  redrawInsert:
    TkTextMarkSegToIndex(textPtr, textPtr->insertMarkPtr, &index);
    if (TkTextIndexBbox(textPtr, &index, &x, &y, &w, &h,
	    &charWidth, NULL) == 0) {
	int insertWidth;
	Tk_GetPixelsFromObj(NULL, textPtr->tkwin, textPtr->insertWidthObj, &insertWidth);
	if (textPtr->insertCursorType) {
	    /* Block cursor */
	    TkTextRedrawRegion(textPtr, x - insertWidth / 2, y,
		    charWidth + insertWidth / 2, h);
	} else {
	    /* I-beam cursor */
	    TkTextRedrawRegion(textPtr, x - insertWidth / 2, y,
		    insertWidth, h);
	}
    }
Changes to generic/tkText.h.
1031
1032
1033
1034
1035
1036
1037
1038

1039
1040
1041
1042
1043
1044
1045
MODULE_SCOPE void	TkBTreeUnlinkSegment(TkTextSegment *segPtr,
			    TkTextLine *linePtr);
MODULE_SCOPE void	TkTextBindProc(void *clientData,
			    XEvent *eventPtr);
MODULE_SCOPE void	TkTextSelectionEvent(TkText *textPtr);
MODULE_SCOPE int	TkTextIndexBbox(TkText *textPtr,
			    const TkTextIndex *indexPtr, int *xPtr, int *yPtr,
			    int *widthPtr, int *heightPtr, int *charWidthPtr);

MODULE_SCOPE int	TkTextCharLayoutProc(TkText *textPtr,
			    TkTextIndex *indexPtr, TkTextSegment *segPtr,
			    Tcl_Size offset, int maxX, Tcl_Size maxChars, int noBreakYet,
			    TkWrapMode wrapMode, TkTextDispChunk *chunkPtr);
MODULE_SCOPE void	TkTextCreateDInfo(TkText *textPtr);
MODULE_SCOPE int	TkTextDLineInfo(TkText *textPtr,
			    const TkTextIndex *indexPtr, int *xPtr, int *yPtr,







|
>







1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
MODULE_SCOPE void	TkBTreeUnlinkSegment(TkTextSegment *segPtr,
			    TkTextLine *linePtr);
MODULE_SCOPE void	TkTextBindProc(void *clientData,
			    XEvent *eventPtr);
MODULE_SCOPE void	TkTextSelectionEvent(TkText *textPtr);
MODULE_SCOPE int	TkTextIndexBbox(TkText *textPtr,
			    const TkTextIndex *indexPtr, int *xPtr, int *yPtr,
			    int *widthPtr, int *heightPtr, int *charWidthPtr,
				int *cursorWidthPtr);
MODULE_SCOPE int	TkTextCharLayoutProc(TkText *textPtr,
			    TkTextIndex *indexPtr, TkTextSegment *segPtr,
			    Tcl_Size offset, int maxX, Tcl_Size maxChars, int noBreakYet,
			    TkWrapMode wrapMode, TkTextDispChunk *chunkPtr);
MODULE_SCOPE void	TkTextCreateDInfo(TkText *textPtr);
MODULE_SCOPE int	TkTextDLineInfo(TkText *textPtr,
			    const TkTextIndex *indexPtr, int *xPtr, int *yPtr,
Changes to generic/tkTextDisp.c.
11
12
13
14
15
16
17

18
19
20
21
22
23
24
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tkInt.h"
#include "tkText.h"


#ifdef _WIN32
#include "tkWinInt.h"
#elif defined(__CYGWIN__)
#include "tkUnixInt.h"
#elif defined(MAC_OSX_TK)
#include "tkMacOSXInt.h"







>







11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tkInt.h"
#include "tkText.h"
#include "tk3d.h"

#ifdef _WIN32
#include "tkWinInt.h"
#elif defined(__CYGWIN__)
#include "tkUnixInt.h"
#elif defined(MAC_OSX_TK)
#include "tkMacOSXInt.h"
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437


2438
2439
2440
2441
2442





2443
2444
2445
2446
2447
2448
2449
    DLine *dlPtr,	/* Information about line to draw. */
    DLine *prevPtr,		/* Line just before one to draw, or NULL if
				 * dlPtr is the top line. */
    Pixmap pixmap)		/* Pixmap to use for double-buffering. Caller
				 * must make sure it's large enough to hold
				 * line. */
{
    TkTextDispChunk *chunkPtr;
    TextDInfo *dInfoPtr = textPtr->dInfoPtr;
    Display *display;
    int height, y_off;


#ifndef TK_NO_DOUBLE_BUFFERING
    const int y = 0;
#else
    const int y = dlPtr->y;
#endif /* TK_NO_DOUBLE_BUFFERING */






    if (dlPtr->chunkPtr == NULL) return;

    display = Tk_Display(textPtr->tkwin);

    height = dlPtr->height;
    if ((height + dlPtr->y) > dInfoPtr->maxY) {







|



>
>





>
>
>
>
>







2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
    DLine *dlPtr,	/* Information about line to draw. */
    DLine *prevPtr,		/* Line just before one to draw, or NULL if
				 * dlPtr is the top line. */
    Pixmap pixmap)		/* Pixmap to use for double-buffering. Caller
				 * must make sure it's large enough to hold
				 * line. */
{
    TkTextDispChunk *chunkPtr, tmpChunk, *otherChunkPtr = NULL;
    TextDInfo *dInfoPtr = textPtr->dInfoPtr;
    Display *display;
    int height, y_off;
    struct TextStyle tmpStyle;
    TkBorder *borderPtr;
#ifndef TK_NO_DOUBLE_BUFFERING
    const int y = 0;
#else
    const int y = dlPtr->y;
#endif /* TK_NO_DOUBLE_BUFFERING */
#ifdef TK_LAYOUT_WITH_BASE_CHUNKS
    BaseCharInfo bci;
#else
    CharInfo ci;
#endif /* TK_LAYOUT_WITH_BASE_CHUNKS */

    if (dlPtr->chunkPtr == NULL) return;

    display = Tk_Display(textPtr->tkwin);

    height = dlPtr->height;
    if ((height + dlPtr->y) > dInfoPtr->maxY) {
2521
2522
2523
2524
2525
2526
2527




































































2528
2529
2530
2531
2532
2533
2534
	    chunkPtr = chunkPtr->nextPtr) {
	if (chunkPtr->displayProc == TkTextInsertDisplayProc) {
	    /*
	     * Already displayed the insertion cursor above. Don't do it again
	     * here.
	     */





































































	    continue;
	}

	/*
	 * Don't call if elide. This tax OK since not very many visible DLines
	 * in an area, but potentially many elide ones.
	 */







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
	    chunkPtr = chunkPtr->nextPtr) {
	if (chunkPtr->displayProc == TkTextInsertDisplayProc) {
	    /*
	     * Already displayed the insertion cursor above. Don't do it again
	     * here.
	     */

	    if (textPtr->insertCursorType &&
		    ((textPtr->flags & (GOT_FOCUS | INSERT_ON)) ==
			(GOT_FOCUS | INSERT_ON)) &&
		    (chunkPtr->nextPtr != NULL) &&
		    (chunkPtr->nextPtr->displayProc == CharDisplayProc) &&
		    (chunkPtr->nextPtr->numBytes > 0)) {
		/*
		 * Make a temporary chunk for displaying the text
		 * within the block cursor later on.
		 */
		XGCValues gcValues;
		unsigned long mask;
		int endX, numBytes, ix, iy, iw, ih;
		int charWidth = 0, cursorWidth = 0;
		TkTextIndex index;

#ifdef TK_LAYOUT_WITH_BASE_CHUNKS
		CharInfo *ciPtr;
		BaseCharInfo *bciPtr;
		Tcl_UniChar ch;
		int chnum;
		char buf[16];
#endif

		otherChunkPtr = &tmpChunk;
		*otherChunkPtr = *(chunkPtr->nextPtr);
		TkTextMarkSegToIndex(textPtr, textPtr->insertMarkPtr, &index);
		TkTextIndexBbox(textPtr, &index, &ix, &iy, &iw, &ih,
			&charWidth, &cursorWidth);
		numBytes = CharChunkMeasureChars(otherChunkPtr, NULL, 0,
			0, -1, otherChunkPtr->x,
			otherChunkPtr->x + cursorWidth, 0, &endX);
		if (numBytes > 0) {
		    otherChunkPtr->undisplayProc = NULL;
		    tmpStyle = *otherChunkPtr->stylePtr;
		    otherChunkPtr->stylePtr = &tmpStyle;
		    tmpStyle.bgGC = None;
		    mask = GCFont;
		    gcValues.font = Tk_FontId(tmpStyle.sValuePtr->tkfont);
		    mask |= GCForeground;
		    borderPtr = (TkBorder *) textPtr->border;
		    gcValues.foreground = borderPtr->bgColorPtr->pixel;
		    tmpStyle.fgGC = Tk_GetGC(textPtr->tkwin, mask, &gcValues);
#ifdef TK_LAYOUT_WITH_BASE_CHUNKS
		    ciPtr = (CharInfo *) otherChunkPtr->clientData;
		    bciPtr = (BaseCharInfo *) ciPtr->baseChunkPtr->clientData;
		    bci.ci = *ciPtr;
		    Tcl_DStringInit(&bci.baseChars);
		    bci.width = -1;
		    Tcl_DStringAppend(&bci.baseChars,
			    Tcl_DStringValue(&bciPtr->baseChars) +
			    bci.ci.baseOffset, numBytes);
		    bci.ci.baseOffset = 0;
		    bci.ci.numBytes = Tcl_DStringLength(&bci.baseChars);
		    bci.ci.chars = Tcl_DStringValue(&bci.baseChars);
		    bci.ci.baseChunkPtr = otherChunkPtr;
		    otherChunkPtr->clientData = (ClientData) &bci;
		    otherChunkPtr->numBytes = bci.ci.numBytes;
#else
		    ci = *((CharInfo *) (otherChunkPtr->clientData));
		    otherChunkPtr->clientData = (ClientData) &ci;
		    ci.numBytes = numBytes;
		    otherChunkPtr->numBytes = ci.numBytes;
#endif /* TK_LAYOUT_WITH_BASE_CHUNKS */
		} else {
		    otherChunkPtr = NULL;
		}
	    }
	    continue;
	}

	/*
	 * Don't call if elide. This tax OK since not very many visible DLines
	 * in an area, but potentially many elide ones.
	 */
2550
2551
2552
2553
2554
2555
2556































2557
2558
2559
2560
2561
2562
2563
		x = -chunkPtr->width;
	    }
	    chunkPtr->displayProc(textPtr, chunkPtr, x,
		    y + dlPtr->spaceAbove, dlPtr->height - dlPtr->spaceAbove -
		    dlPtr->spaceBelow, dlPtr->baseline - dlPtr->spaceAbove,
		    display, pixmap, dlPtr->y + dlPtr->spaceAbove);
	}
































	if ((textPtr->tkwin == NULL) || (textPtr->flags & DESTROYED)) {
	    /*
	     * A displayProc called in the loop above invoked a binding
	     * that caused the widget to be deleted. Don't do anything.
	     */
	    return;







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
		x = -chunkPtr->width;
	    }
	    chunkPtr->displayProc(textPtr, chunkPtr, x,
		    y + dlPtr->spaceAbove, dlPtr->height - dlPtr->spaceAbove -
		    dlPtr->spaceBelow, dlPtr->baseline - dlPtr->spaceAbove,
		    display, pixmap, dlPtr->y + dlPtr->spaceAbove);
	}
	
	if (otherChunkPtr != NULL) {
	    if ((textPtr->tkwin != NULL) && !(textPtr->flags & DESTROYED)) {
		/*
		 * Draw text within the block cursor.
		 */

		int x = otherChunkPtr->x + dInfoPtr->x -
			dInfoPtr->curXPixelOffset;

		if ((x + otherChunkPtr->width <= 0) || (x >= dInfoPtr->maxX)) {
		    /*
		     * See note above.
		     */

		    x = -otherChunkPtr->width;
		}
		otherChunkPtr->displayProc(textPtr, otherChunkPtr, x,
			y + dlPtr->spaceAbove, dlPtr->height -
			dlPtr->spaceAbove - dlPtr->spaceBelow,
			dlPtr->baseline - dlPtr->spaceAbove,
			display, pixmap, dlPtr->y + dlPtr->spaceAbove);
	    }
	    if (otherChunkPtr->stylePtr->fgGC != NULL) {
		Tk_FreeGC(textPtr->display, otherChunkPtr->stylePtr->fgGC);
	    }
#ifdef TK_LAYOUT_WITH_BASE_CHUNKS
	    Tcl_DStringFree(&bci.baseChars);
#endif
	    otherChunkPtr = NULL;
	}

	if ((textPtr->tkwin == NULL) || (textPtr->flags & DESTROYED)) {
	    /*
	     * A displayProc called in the loop above invoked a binding
	     * that caused the widget to be deleted. Don't do anything.
	     */
	    return;
7359
7360
7361
7362
7363
7364
7365
7366
7367
7368
7369




7370
7371
7372
7373
7374

7375




7376
7377
7378
7379
7380
7381
7382
TkTextIndexBbox(
    TkText *textPtr,		/* Widget record for text widget. */
    const TkTextIndex *indexPtr,/* Index whose bounding box is desired. */
    int *xPtr, int *yPtr,	/* Filled with index's upper-left
				 * coordinate. */
    int *widthPtr, int *heightPtr,
				/* Filled in with index's dimensions. */
    int *charWidthPtr)		/* If the 'index' is at the end of a display
				 * line and therefore takes up a very large
				 * width, this is used to return the smaller
				 * width actually desired by the index. */




{
    TextDInfo *dInfoPtr = textPtr->dInfoPtr;
    DLine *dlPtr;
    TkTextDispChunk *chunkPtr;
    Tcl_Size byteCount;






    /*
     * Make sure that all of the screen layout information is up to date.
     */

    if (dInfoPtr->flags & DINFO_OUT_OF_DATE) {
	UpdateDisplayInfo(textPtr);
    }







|



>
>
>
>





>

>
>
>
>







7466
7467
7468
7469
7470
7471
7472
7473
7474
7475
7476
7477
7478
7479
7480
7481
7482
7483
7484
7485
7486
7487
7488
7489
7490
7491
7492
7493
7494
7495
7496
7497
7498
TkTextIndexBbox(
    TkText *textPtr,		/* Widget record for text widget. */
    const TkTextIndex *indexPtr,/* Index whose bounding box is desired. */
    int *xPtr, int *yPtr,	/* Filled with index's upper-left
				 * coordinate. */
    int *widthPtr, int *heightPtr,
				/* Filled in with index's dimensions. */
    int *charWidthPtr,		/* If the 'index' is at the end of a display
				 * line and therefore takes up a very large
				 * width, this is used to return the smaller
				 * width actually desired by the index. */
    int *cursorWidthPtr)	/* Receives same value as 'charWidthPtr'
				 * except for the text index pointing to
				 * a Tab which gets reduced to the width of
				 * a single space. */
{
    TextDInfo *dInfoPtr = textPtr->dInfoPtr;
    DLine *dlPtr;
    TkTextDispChunk *chunkPtr;
    Tcl_Size byteCount;
    int dummy;

    if (charWidthPtr == NULL) {
	charWidthPtr = &dummy;
    }
    
    /*
     * Make sure that all of the screen layout information is up to date.
     */

    if (dInfoPtr->flags & DINFO_OUT_OF_DATE) {
	UpdateDisplayInfo(textPtr);
    }
7433
7434
7435
7436
7437
7438
7439
7440
7441
7442
7443
7444
7445
7446
7447
7448
7449
7450
7451
7452
7453
7454
7455
7456
7457
7458
7459
7460
    *xPtr = *xPtr + dInfoPtr->x - dInfoPtr->curXPixelOffset;
    if ((byteCount == chunkPtr->numBytes-1) && (chunkPtr->nextPtr == NULL)) {
	/*
	 * Last character in display line. Give it all the space up to the
	 * line.
	 */

	if (charWidthPtr != NULL) {
	    *charWidthPtr = dInfoPtr->maxX - *xPtr;
	    if (*charWidthPtr > textPtr->charWidth) {
		*charWidthPtr = textPtr->charWidth;
	    }
	}
	if (*xPtr > dInfoPtr->maxX) {
	    *xPtr = dInfoPtr->maxX;
	}
	*widthPtr = dInfoPtr->maxX - *xPtr;
    } else {
	if (charWidthPtr != NULL) {
	    *charWidthPtr = *widthPtr;
	}
    }
    if (*widthPtr == 0) {
	/*
	 * With zero width (e.g. elided text) we just need to make sure it is
	 * onscreen, where the '=' case here is ok.
	 */








<
|
|
|
<






<
|
<







7549
7550
7551
7552
7553
7554
7555

7556
7557
7558

7559
7560
7561
7562
7563
7564

7565

7566
7567
7568
7569
7570
7571
7572
    *xPtr = *xPtr + dInfoPtr->x - dInfoPtr->curXPixelOffset;
    if ((byteCount == chunkPtr->numBytes-1) && (chunkPtr->nextPtr == NULL)) {
	/*
	 * Last character in display line. Give it all the space up to the
	 * line.
	 */


	*charWidthPtr = dInfoPtr->maxX - *xPtr;
	if (*charWidthPtr > textPtr->charWidth) {
	    *charWidthPtr = textPtr->charWidth;

	}
	if (*xPtr > dInfoPtr->maxX) {
	    *xPtr = dInfoPtr->maxX;
	}
	*widthPtr = dInfoPtr->maxX - *xPtr;
    } else {

	*charWidthPtr = *widthPtr;

    }
    if (*widthPtr == 0) {
	/*
	 * With zero width (e.g. elided text) we just need to make sure it is
	 * onscreen, where the '=' case here is ok.
	 */

7473
7474
7475
7476
7477
7478
7479























7480
7481
7482
7483
7484
7485
7486
	}
    }
    if ((*yPtr + *heightPtr) > dInfoPtr->maxY) {
	*heightPtr = dInfoPtr->maxY - *yPtr;
	if (*heightPtr <= 0) {
	    return -1;
	}























    }
    return 0;
}

/*
 *----------------------------------------------------------------------
 *







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







7585
7586
7587
7588
7589
7590
7591
7592
7593
7594
7595
7596
7597
7598
7599
7600
7601
7602
7603
7604
7605
7606
7607
7608
7609
7610
7611
7612
7613
7614
7615
7616
7617
7618
7619
7620
7621
	}
    }
    if ((*yPtr + *heightPtr) > dInfoPtr->maxY) {
	*heightPtr = dInfoPtr->maxY - *yPtr;
	if (*heightPtr <= 0) {
	    return -1;
	}
    }
    /*
     * Display a block cursor on a tab with whitespace width
     */

    if (cursorWidthPtr != NULL) {
	*cursorWidthPtr = *charWidthPtr;
	if (chunkPtr->bboxProc == CharBboxProc) {
	    CharInfo *ciPtr = (CharInfo *)chunkPtr->clientData;
#ifdef TK_LAYOUT_WITH_BASE_CHUNKS
	    BaseCharInfo *bciPtr =
		(BaseCharInfo *)ciPtr->baseChunkPtr->clientData;
	    char *chars = Tcl_DStringValue(&bciPtr->baseChars);

	    if (chars[ciPtr->baseOffset + byteCount] == '\t')
#else
	    if (ciPtr->chars[byteCount] == '\t')
#endif
	    {
		CharChunkMeasureChars(chunkPtr, " ", 1, 0, 1,
			0, -1, 0, cursorWidthPtr);
	    }
	}
    }
    return 0;
}

/*
 *----------------------------------------------------------------------
 *
Changes to generic/tkTextMark.c.
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635

636

637
638
639
640
641
642
643
     * We have no need for the clientData.
     */

    /* TkText *textPtr = chunkPtr->clientData; */
    TkTextIndex index;
    int halfWidth, insertWidth, insertBorderWidth;
    int rightSideWidth;
    int ix = 0, iy = 0, iw = 0, ih = 0, charWidth = 0;

    Tk_GetPixelsFromObj(NULL, textPtr->tkwin, textPtr->insertWidthObj, &insertWidth);
    Tk_GetPixelsFromObj(NULL, textPtr->tkwin, textPtr->insertBorderWidthObj, &insertBorderWidth);
    halfWidth = insertWidth/2;
    if (textPtr->insertCursorType) {
	TkTextMarkSegToIndex(textPtr, textPtr->insertMarkPtr, &index);
	TkTextIndexBbox(textPtr, &index, &ix, &iy, &iw, &ih, &charWidth);

	rightSideWidth = charWidth + halfWidth;

    } else {
	rightSideWidth = halfWidth;
    }

    if ((x + rightSideWidth) < 0) {
	/*
	 * The insertion cursor is off-screen. Indicate caret at 0,0 and







|






|
>

>







621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
     * We have no need for the clientData.
     */

    /* TkText *textPtr = chunkPtr->clientData; */
    TkTextIndex index;
    int halfWidth, insertWidth, insertBorderWidth;
    int rightSideWidth;
    int ix = 0, iy = 0, iw = 0, ih = 0, charWidth = 0, cursorWidth = 0;

    Tk_GetPixelsFromObj(NULL, textPtr->tkwin, textPtr->insertWidthObj, &insertWidth);
    Tk_GetPixelsFromObj(NULL, textPtr->tkwin, textPtr->insertBorderWidthObj, &insertBorderWidth);
    halfWidth = insertWidth/2;
    if (textPtr->insertCursorType) {
	TkTextMarkSegToIndex(textPtr, textPtr->insertMarkPtr, &index);
	TkTextIndexBbox(textPtr, &index, &ix, &iy, &iw, &ih, &charWidth,
		&cursorWidth);
	rightSideWidth = charWidth + halfWidth;
	charWidth = cursorWidth;
    } else {
	rightSideWidth = halfWidth;
    }

    if ((x + rightSideWidth) < 0) {
	/*
	 * The insertion cursor is off-screen. Indicate caret at 0,0 and