diff options
author | jan.nijtmans <nijtmans@users.sourceforge.net> | 2016-03-04 15:41:59 (GMT) |
---|---|---|
committer | jan.nijtmans <nijtmans@users.sourceforge.net> | 2016-03-04 15:41:59 (GMT) |
commit | 42e3af0d0ae489a65f7f3ce98429a394c0926c32 (patch) | |
tree | 0149222f25fa8bd0c3a1cb50b3e71a5419cf6021 /generic | |
parent | 3fa224a2450a99a43c66f5f85951bcadb65430c2 (diff) | |
parent | 2fd9fcf08d73f688888ef8784be0c5493b80d818 (diff) | |
download | tk-tip_415.zip tk-tip_415.tar.gz tk-tip_415.tar.bz2 |
merge trunktip_415
Diffstat (limited to 'generic')
97 files changed, 2783 insertions, 1866 deletions
diff --git a/generic/default.h b/generic/default.h index 6156f4d..e6ef132 100644 --- a/generic/default.h +++ b/generic/default.h @@ -14,8 +14,7 @@ #ifndef _DEFAULT #define _DEFAULT -#if defined(__WIN32__) || defined(_WIN32) || \ - defined(__MINGW32__) +#ifdef _WIN32 # include "tkWinDefault.h" #else # if defined(MAC_OSX_TK) diff --git a/generic/tk.decls b/generic/tk.decls index 11b4f87..9ceb3af 100644 --- a/generic/tk.decls +++ b/generic/tk.decls @@ -1069,13 +1069,6 @@ declare 273 { void Tk_CreateOldPhotoImageFormat(const Tk_PhotoImageFormat *formatPtr) } -declare 274 { - void reserved274(void) -} -declare 275 { - void reserved275(void) -} - # Define the platform specific public Tk interface. These functions are # only available on the designated platform. diff --git a/generic/tk.h b/generic/tk.h index add2822..6abb05e 100644 --- a/generic/tk.h +++ b/generic/tk.h @@ -18,9 +18,34 @@ #include <tcl.h> #if (TCL_MAJOR_VERSION != 8) || (TCL_MINOR_VERSION < 6) -# error Tk 8.6 must be compiled with tcl.h from Tcl 8.6 or better +# error Tk 8.7 must be compiled with tcl.h from Tcl 8.6 or better #endif - + +#ifndef CONST84 +# define CONST84 const +# define CONST84_RETURN const +#endif +#ifndef CONST86 +# define CONST86 CONST84 +#endif +#ifndef EXTERN +# define EXTERN extern TCL_STORAGE_CLASS +#endif + +/* + * Utility macros: STRINGIFY takes an argument and wraps it in "" (double + * quotation marks), JOIN joins two arguments. + */ + +#ifndef STRINGIFY +# define STRINGIFY(x) STRINGIFY1(x) +# define STRINGIFY1(x) #x +#endif +#ifndef JOIN +# define JOIN(a,b) JOIN1(a,b) +# define JOIN1(a,b) a##b +#endif + /* * For C++ compilers, use extern "C" */ @@ -48,12 +73,12 @@ extern "C" { */ #define TK_MAJOR_VERSION 8 -#define TK_MINOR_VERSION 6 -#define TK_RELEASE_LEVEL TCL_BETA_RELEASE -#define TK_RELEASE_SERIAL 3 +#define TK_MINOR_VERSION 7 +#define TK_RELEASE_LEVEL TCL_ALPHA_RELEASE +#define TK_RELEASE_SERIAL 0 -#define TK_VERSION "8.6" -#define TK_PATCH_LEVEL "8.6b3" +#define TK_VERSION "8.7" +#define TK_PATCH_LEVEL "8.7a0" /* * A special definition used to allow this header file to be included from @@ -1471,7 +1496,7 @@ typedef struct Tk_ElementSpec { #define Tk_Release Tcl_Release /* Removed Tk_Main, use macro instead */ -#if defined(__WIN32__) || defined(__CYGWIN__) +#if defined(_WIN32) || defined(__CYGWIN__) #define Tk_Main(argc, argv, proc) Tk_MainEx(argc, argv, proc, \ (Tcl_FindExecutable(0), (Tcl_CreateInterp)())) #else diff --git a/generic/tk3d.c b/generic/tk3d.c index dd7ab2f..87ddf76 100644 --- a/generic/tk3d.c +++ b/generic/tk3d.c @@ -624,8 +624,8 @@ Tk_GetReliefFromObj( * from. */ int *resultPtr) /* Where to place the answer. */ { - return Tcl_GetIndexFromObj(interp, objPtr, reliefStrings, "relief", 0, - resultPtr); + return Tcl_GetIndexFromObjStruct(interp, objPtr, reliefStrings, + sizeof(char *), "relief", 0, resultPtr); } /* diff --git a/generic/tkBind.c b/generic/tkBind.c index 7126e24..9cd3b7b 100644 --- a/generic/tkBind.c +++ b/generic/tkBind.c @@ -14,11 +14,11 @@ #include "tkInt.h" -#ifdef __WIN32__ +#ifdef _WIN32 #include "tkWinInt.h" -#endif - -#if !(defined(__WIN32__) || defined(MAC_OSX_TK)) /* UNIX */ +#elif defined(MAC_OSX_TK) +#include "tkMacOSXInt.h" +#else #include "tkUnixInt.h" #endif @@ -167,7 +167,7 @@ typedef struct { * button (0 means any buttons are OK). For * virtual events, specifies the Tk_Uid of the * virtual event name (never 0). */ -} Pattern; +} TkPattern; /* * The following structure defines a pattern sequence, which consists of one @@ -209,7 +209,7 @@ typedef struct PatSeq { * for end of list). Needed to implement * Tk_DeleteAllBindings. In a virtual event * table, always NULL. */ - Pattern pats[1]; /* Array of "numPats" patterns. Only one + TkPattern pats[1]; /* Array of "numPats" patterns. Only one * element is declared here but in actuality * enough space will be allocated for * "numPats" patterns. To match, pats[0] must @@ -612,7 +612,8 @@ static int DeleteVirtualEvent(Tcl_Interp *interp, const char *eventString); static void DeleteVirtualEventTable(VirtualEventTable *vetPtr); static void ExpandPercents(TkWindow *winPtr, const char *before, - XEvent *eventPtr,KeySym keySym,Tcl_DString *dsPtr); + XEvent *eventPtr,KeySym keySym, + unsigned int scriptCount, Tcl_DString *dsPtr); static PatSeq * FindSequence(Tcl_Interp *interp, Tcl_HashTable *patternTablePtr, ClientData object, const char *eventString, int create, @@ -635,7 +636,7 @@ static PatSeq * MatchPatterns(TkDisplay *dispPtr, static int NameToWindow(Tcl_Interp *interp, Tk_Window main, Tcl_Obj *objPtr, Tk_Window *tkwinPtr); static int ParseEventDescription(Tcl_Interp *interp, - const char **eventStringPtr, Pattern *patPtr, + const char **eventStringPtr, TkPattern *patPtr, unsigned long *eventMaskPtr); static void DoWarp(ClientData clientData); @@ -1221,6 +1222,7 @@ Tk_BindEvent( XEvent *ringPtr; PatSeq *vMatchDetailList, *vMatchNoDetailList; int flags, oldScreen; + unsigned int scriptCount; Tcl_Interp *interp; Tcl_DString scripts; Tcl_InterpState interpState; @@ -1372,6 +1374,7 @@ Tk_BindEvent( * each object. */ + scriptCount = 0; Tcl_DStringInit(&scripts); for ( ; numObjects > 0; numObjects--, objectPtr++) { @@ -1421,7 +1424,7 @@ Tk_BindEvent( if (matchPtr != NULL) { ExpandPercents(winPtr, sourcePtr->script, eventPtr, - detail.keySym, &scripts); + detail.keySym, scriptCount++, &scripts); /* * A "" is added to the scripts string to separate the various @@ -1601,7 +1604,7 @@ MatchPatterns( for ( ; psPtr != NULL; psPtr = psPtr->nextSeqPtr) { XEvent *eventPtr = &bindPtr->eventRing[bindPtr->curEvent]; Detail *detailPtr = &bindPtr->detailRing[bindPtr->curEvent]; - Pattern *patPtr = psPtr->pats; + TkPattern *patPtr = psPtr->pats; Window window = eventPtr->xany.window; int patCount, ringCount, flags, state, modMask, i; @@ -1815,7 +1818,7 @@ MatchPatterns( */ if (bestPtr != NULL) { - Pattern *patPtr2; + TkPattern *patPtr2; if (matchPtr->numPats != bestPtr->numPats) { if (bestPtr->numPats > matchPtr->numPats) { @@ -1903,6 +1906,8 @@ ExpandPercents( * in % replacements. */ KeySym keySym, /* KeySym: only relevant for KeyPress and * KeyRelease events). */ + unsigned int scriptCount, /* The number of script-based binding patterns + * matched so far for this event. */ Tcl_DString *dsPtr) /* Dynamic string in which to append new * command. */ { @@ -2184,6 +2189,9 @@ ExpandPercents( } } goto doString; + case 'M': + number = scriptCount; + goto doNumber; case 'N': if ((flags & KEY) && (eventPtr->type != MouseWheelEvent)) { number = (int) keySym; @@ -2297,7 +2305,7 @@ ChangeScreen( int code; Tcl_IncrRefCount(cmdObj); - code = Tcl_GlobalEvalObj(interp, cmdObj); + code = Tcl_EvalObjEx(interp, cmdObj, TCL_EVAL_GLOBAL); if (code != TCL_OK) { Tcl_AddErrorInfo(interp, "\n (changing screen in event binding)"); @@ -2349,8 +2357,8 @@ Tk_EventObjCmd( Tcl_WrongNumArgs(interp, 1, objv, "option ?arg?"); return TCL_ERROR; } - if (Tcl_GetIndexFromObj(interp, objv[1], optionStrings, "option", 0, - &index) != TCL_OK) { + if (Tcl_GetIndexFromObjStruct(interp, objv[1], optionStrings, + sizeof(char *), "option", 0, &index) != TCL_OK) { return TCL_ERROR; } @@ -2643,7 +2651,7 @@ DeleteVirtualEvent( eventPSPtr = FindSequence(interp, &vetPtr->patternTable, NULL, eventString, 0, 0, &eventMask); if (eventPSPtr == NULL) { - const char *string = Tcl_GetStringResult(interp); + const char *string = Tcl_GetString(Tcl_GetObjResult(interp)); return (string[0] != '\0') ? TCL_ERROR : TCL_OK; } @@ -2879,7 +2887,7 @@ HandleEventGenerate( const char *name, *windowName; int count, flags, synch, i, number, warp; Tcl_QueuePosition pos; - Pattern pat; + TkPattern pat; Tk_Window tkwin, tkwin2; TkWindow *mainPtr; unsigned long eventMask; @@ -3006,8 +3014,8 @@ HandleEventGenerate( optionPtr = objv[i]; valuePtr = objv[i + 1]; - if (Tcl_GetIndexFromObj(interp, optionPtr, fieldStrings, "option", - TCL_EXACT, &index) != TCL_OK) { + if (Tcl_GetIndexFromObjStruct(interp, optionPtr, fieldStrings, + sizeof(char *), "option", TCL_EXACT, &index) != TCL_OK) { return TCL_ERROR; } if (objc & 1) { @@ -3618,10 +3626,10 @@ FindSequence( unsigned long *maskPtr) /* *maskPtr is filled in with the event types * on which this pattern sequence depends. */ { - Pattern pats[EVENT_BUFFER_SIZE]; + TkPattern pats[EVENT_BUFFER_SIZE]; int numPats, virtualFound; const char *p; - Pattern *patPtr; + TkPattern *patPtr; PatSeq *psPtr; Tcl_HashEntry *hPtr; int flags, count, isNew; @@ -3707,7 +3715,7 @@ FindSequence( key.type = patPtr->eventType; key.detail = patPtr->detail; hPtr = Tcl_CreateHashEntry(patternTablePtr, (char *) &key, &isNew); - sequenceSize = numPats*sizeof(Pattern); + sequenceSize = numPats*sizeof(TkPattern); if (!isNew) { for (psPtr = Tcl_GetHashValue(hPtr); psPtr != NULL; psPtr = psPtr->nextSeqPtr) { @@ -3733,7 +3741,7 @@ FindSequence( return NULL; } - psPtr = ckalloc(sizeof(PatSeq) + (numPats-1)*sizeof(Pattern)); + psPtr = ckalloc(sizeof(PatSeq) + (numPats-1)*sizeof(TkPattern)); psPtr->numPats = numPats; psPtr->script = NULL; psPtr->flags = flags; @@ -3777,7 +3785,7 @@ ParseEventDescription( const char **eventStringPtr,/* On input, holds a pointer to start of event * string. On exit, gets pointer to rest of * string after parsed event. */ - Pattern *patPtr, /* Filled with the pattern parsed from the + TkPattern *patPtr, /* Filled with the pattern parsed from the * event string. */ unsigned long *eventMaskPtr)/* Filled with event mask of matched event. */ { @@ -4065,7 +4073,7 @@ static Tcl_Obj * GetPatternObj( PatSeq *psPtr) { - Pattern *patPtr; + TkPattern *patPtr; int patsLeft, needMods; const ModInfo *modPtr; const EventInfo *eiPtr; @@ -4113,15 +4121,15 @@ GetPatternObj( Tcl_AppendToObj(patternObj, "<", 1); if ((psPtr->flags & PAT_NEARBY) && (patsLeft > 1) - && (memcmp(patPtr, patPtr-1, sizeof(Pattern)) == 0)) { + && (memcmp(patPtr, patPtr-1, sizeof(TkPattern)) == 0)) { patsLeft--; patPtr--; if ((patsLeft > 1) && - (memcmp(patPtr, patPtr-1, sizeof(Pattern)) == 0)) { + (memcmp(patPtr, patPtr-1, sizeof(TkPattern)) == 0)) { patsLeft--; patPtr--; if ((patsLeft > 1) && - (memcmp(patPtr, patPtr-1, sizeof(Pattern)) == 0)) { + (memcmp(patPtr, patPtr-1, sizeof(TkPattern)) == 0)) { patsLeft--; patPtr--; Tcl_AppendToObj(patternObj, "Quadruple-", 10); diff --git a/generic/tkBitmap.c b/generic/tkBitmap.c index 729fff4..88f3e2b 100644 --- a/generic/tkBitmap.c +++ b/generic/tkBitmap.c @@ -305,7 +305,7 @@ GetBitmap( TkBitmap *bitmapPtr, *existingBitmapPtr; TkPredefBitmap *predefPtr; Pixmap bitmap; - int isNew, width, height, dummy2; + int isNew, width = 0, height = 0, dummy2; TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr; ThreadSpecificData *tsdPtr = Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); diff --git a/generic/tkBusy.c b/generic/tkBusy.c index 8f73d80..65248a2 100644 --- a/generic/tkBusy.c +++ b/generic/tkBusy.c @@ -43,7 +43,7 @@ static void BusyCustodyProc(ClientData clientData, static int ConfigureBusy(Tcl_Interp *interp, Busy *busyPtr, int objc, Tcl_Obj *const objv[]); static Busy * CreateBusy(Tcl_Interp *interp, Tk_Window tkRef); -static void DestroyBusy(char *dataPtr); +static void DestroyBusy(void *dataPtr); static void DoConfigureNotify(Tk_FakeWin *winPtr); static inline Tk_Window FirstChild(Tk_Window parent); static Busy * GetBusy(Tcl_Interp *interp, @@ -136,7 +136,7 @@ BusyCustodyProc( busyPtr); TkpHideBusyWindow(busyPtr); busyPtr->tkBusy = NULL; - Tcl_EventuallyFree(busyPtr, DestroyBusy); + Tcl_EventuallyFree(busyPtr, (Tcl_FreeProc *)DestroyBusy); } /* @@ -262,7 +262,7 @@ RefWinEventProc( * Arrange for the busy structure to be removed at a proper time. */ - Tcl_EventuallyFree(busyPtr, DestroyBusy); + Tcl_EventuallyFree(busyPtr, (Tcl_FreeProc *)DestroyBusy); break; case ConfigureNotify: @@ -333,9 +333,9 @@ RefWinEventProc( static void DestroyBusy( - char *data) /* Busy window structure record */ + void *data) /* Busy window structure record */ { - register Busy *busyPtr = (Busy *) data; + register Busy *busyPtr = data; if (busyPtr->hashPtr != NULL) { Tcl_DeleteHashEntry(busyPtr->hashPtr); @@ -383,7 +383,7 @@ BusyEventProc( if (eventPtr->type == DestroyNotify) { busyPtr->tkBusy = NULL; - Tcl_EventuallyFree(busyPtr, DestroyBusy); + Tcl_EventuallyFree(busyPtr, (Tcl_FreeProc *)DestroyBusy); } } @@ -816,8 +816,8 @@ Tk_BusyObjCmd( return HoldBusy(busyTablePtr, interp, objv[1], objc-2, objv+2); } - if (Tcl_GetIndexFromObj(interp, objv[1], optionStrings, "option", 0, - &index) != TCL_OK) { + if (Tcl_GetIndexFromObjStruct(interp, objv[1], optionStrings, + sizeof(char *), "option", 0, &index) != TCL_OK) { return TCL_ERROR; } switch ((enum options) index) { @@ -895,7 +895,7 @@ Tk_BusyObjCmd( return TCL_ERROR; } TkpHideBusyWindow(busyPtr); - Tcl_EventuallyFree(busyPtr, DestroyBusy); + Tcl_EventuallyFree(busyPtr, (Tcl_FreeProc *)DestroyBusy); return TCL_OK; case BUSY_HOLD: diff --git a/generic/tkButton.c b/generic/tkButton.c index e2c754e..b7e314e 100644 --- a/generic/tkButton.c +++ b/generic/tkButton.c @@ -797,8 +797,8 @@ ButtonWidgetObjCmd( Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?"); return TCL_ERROR; } - result = Tcl_GetIndexFromObj(interp, objv[1], commandNames[butPtr->type], - "option", 0, &index); + result = Tcl_GetIndexFromObjStruct(interp, objv[1], commandNames[butPtr->type], + sizeof(char *), "option", 0, &index); if (result != TCL_OK) { return result; } @@ -962,8 +962,8 @@ DestroyButton( Tcl_DeleteCommandFromToken(butPtr->interp, butPtr->widgetCmd); if (butPtr->textVarNamePtr != NULL) { - Tcl_UntraceVar(butPtr->interp, Tcl_GetString(butPtr->textVarNamePtr), - TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, + Tcl_UntraceVar2(butPtr->interp, Tcl_GetString(butPtr->textVarNamePtr), + NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, ButtonTextVarProc, butPtr); } if (butPtr->image != NULL) { @@ -997,8 +997,8 @@ DestroyButton( Tk_FreeTextLayout(butPtr->textLayout); } if (butPtr->selVarNamePtr != NULL) { - Tcl_UntraceVar(butPtr->interp, Tcl_GetString(butPtr->selVarNamePtr), - TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, + Tcl_UntraceVar2(butPtr->interp, Tcl_GetString(butPtr->selVarNamePtr), + NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, ButtonVarProc, butPtr); } Tk_FreeConfigOptions((char *) butPtr, butPtr->optionTable, @@ -1045,13 +1045,13 @@ ConfigureButton( */ if (butPtr->textVarNamePtr != NULL) { - Tcl_UntraceVar(interp, Tcl_GetString(butPtr->textVarNamePtr), - TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, + Tcl_UntraceVar2(interp, Tcl_GetString(butPtr->textVarNamePtr), + NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, ButtonTextVarProc, butPtr); } if (butPtr->selVarNamePtr != NULL) { - Tcl_UntraceVar(interp, Tcl_GetString(butPtr->selVarNamePtr), - TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, + Tcl_UntraceVar2(interp, Tcl_GetString(butPtr->selVarNamePtr), + NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, ButtonVarProc, butPtr); } @@ -1297,13 +1297,13 @@ ConfigureButton( */ if (butPtr->textVarNamePtr != NULL) { - Tcl_TraceVar(interp, Tcl_GetString(butPtr->textVarNamePtr), - TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, + Tcl_TraceVar2(interp, Tcl_GetString(butPtr->textVarNamePtr), + NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, ButtonTextVarProc, butPtr); } if (butPtr->selVarNamePtr != NULL) { - Tcl_TraceVar(interp, Tcl_GetString(butPtr->selVarNamePtr), - TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, + Tcl_TraceVar2(interp, Tcl_GetString(butPtr->selVarNamePtr), + NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, ButtonVarProc, butPtr); } @@ -1618,8 +1618,8 @@ ButtonVarProc( if (flags & TCL_TRACE_UNSETS) { butPtr->flags &= ~(SELECTED | TRISTATED); if ((flags & TCL_TRACE_DESTROYED) && !(flags & TCL_INTERP_DESTROYED)) { - Tcl_TraceVar(interp, Tcl_GetString(butPtr->selVarNamePtr), - TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, + Tcl_TraceVar2(interp, Tcl_GetString(butPtr->selVarNamePtr), + NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, ButtonVarProc, clientData); } goto redisplay; @@ -1643,7 +1643,7 @@ ButtonVarProc( } butPtr->flags |= SELECTED; butPtr->flags &= ~TRISTATED; - } else if (butPtr->offValuePtr + } else if (butPtr->offValuePtr && strcmp(value, Tcl_GetString(butPtr->offValuePtr)) == 0) { if (!(butPtr->flags & (SELECTED | TRISTATED))) { return NULL; @@ -1712,8 +1712,8 @@ ButtonTextVarProc( if ((flags & TCL_TRACE_DESTROYED) && !(flags & TCL_INTERP_DESTROYED)) { Tcl_ObjSetVar2(interp, butPtr->textVarNamePtr, NULL, butPtr->textPtr, TCL_GLOBAL_ONLY); - Tcl_TraceVar(interp, Tcl_GetString(butPtr->textVarNamePtr), - TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, + Tcl_TraceVar2(interp, Tcl_GetString(butPtr->textVarNamePtr), + NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, ButtonTextVarProc, clientData); } return NULL; diff --git a/generic/tkCanvArc.c b/generic/tkCanvArc.c index dfa0671..ef2ef72 100644 --- a/generic/tkCanvArc.c +++ b/generic/tkCanvArc.c @@ -300,7 +300,7 @@ CreateArc( arcPtr->fillGC = None; arcPtr->height = 0; - + /* * Process the arguments to fill in the item record. */ @@ -392,7 +392,7 @@ ArcCoords( arcPtr->startPoint[1] = arcPtr->bbox[1]; arcPtr->endPoint[0] = arcPtr->bbox[2]; arcPtr->endPoint[1] = arcPtr->bbox[3]; - + ComputeArcBbox(canvas, arcPtr); } else { Tcl_SetObjResult(interp, Tcl_ObjPrintf( @@ -474,7 +474,7 @@ ConfigureArc( ComputeArcFromHeight(arcPtr); ComputeArcBbox(canvas, arcPtr); } - + i = (int) (arcPtr->start/360.0); arcPtr->start -= i*360.0; if (arcPtr->start < 0) { @@ -499,7 +499,7 @@ ConfigureArc( } else if (flags & TK_OFFSET_BOTTOM) { tsoffset->yoffset = (int) (arcPtr->bbox[2] + 0.5); } - + mask = Tk_ConfigOutlineGC(&gcValues, canvas, itemPtr, &(arcPtr->outline)); if (mask) { gcValues.cap_style = CapButt; @@ -606,14 +606,14 @@ ComputeArcFromHeight( ArcItem* arcPtr) { double chordLen, chordDir[2], chordCen[2], arcCen[2], d, radToDeg, radius; - + /* The chord */ chordLen = hypot(arcPtr->endPoint[1]-arcPtr->startPoint[1], arcPtr->startPoint[0]-arcPtr->endPoint[0]); chordDir[0] = (arcPtr->endPoint[0]-arcPtr->startPoint[0])/chordLen; chordDir[1] = (arcPtr->endPoint[1]-arcPtr->startPoint[1])/chordLen; chordCen[0] = (arcPtr->startPoint[0]+arcPtr->endPoint[0])/2; chordCen[1] = (arcPtr->startPoint[1]+arcPtr->endPoint[1])/2; - + /* Calculate the radius (assumes height != 0) */ radius = (4*pow(arcPtr->height,2) + pow(chordLen,2))/(8*arcPtr->height); @@ -640,7 +640,7 @@ ComputeArcFromHeight( /* Set the height to 0 so that itemcget -height returns 0 */ arcPtr->height = 0; - + } /* diff --git a/generic/tkCanvLine.c b/generic/tkCanvLine.c index 9d68c37..087aa56 100644 --- a/generic/tkCanvLine.c +++ b/generic/tkCanvLine.c @@ -1743,11 +1743,10 @@ GetLineIndex( int *indexPtr) /* Where to store converted index. */ { LineItem *linePtr = (LineItem *) itemPtr; - int length; - const char *string = Tcl_GetStringFromObj(obj, &length); + const char *string = Tcl_GetString(obj); if (string[0] == 'e') { - if (strncmp(string, "end", (unsigned) length) == 0) { + if (strncmp(string, "end", obj->length) == 0) { *indexPtr = 2*linePtr->numPoints; } else { goto badIndex; diff --git a/generic/tkCanvPoly.c b/generic/tkCanvPoly.c index f8ea42b..b4ef098 100644 --- a/generic/tkCanvPoly.c +++ b/generic/tkCanvPoly.c @@ -1673,11 +1673,10 @@ GetPolygonIndex( int *indexPtr) /* Where to store converted index. */ { PolygonItem *polyPtr = (PolygonItem *) itemPtr; - int length; - const char *string = Tcl_GetStringFromObj(obj, &length); + const char *string = Tcl_GetString(obj); if (string[0] == 'e') { - if (strncmp(string, "end", (unsigned)length) != 0) { + if (strncmp(string, "end", obj->length) != 0) { goto badIndex; } *indexPtr = 2*(polyPtr->numPoints - polyPtr->autoClosed); diff --git a/generic/tkCanvPs.c b/generic/tkCanvPs.c index 0c7b0dd..c6470dd 100644 --- a/generic/tkCanvPs.c +++ b/generic/tkCanvPs.c @@ -193,7 +193,7 @@ TkCanvPostscriptCmd( * such. */ - result = Tcl_Eval(interp, "::tk::ensure_psenc_is_loaded"); + result = Tcl_EvalEx(interp, "::tk::ensure_psenc_is_loaded", -1, 0); if (result != TCL_OK) { return result; } @@ -1168,7 +1168,7 @@ GetPostscriptPoints( *-------------------------------------------------------------- */ -#ifdef WIN32 +#ifdef _WIN32 #include <windows.h> /* @@ -1178,15 +1178,15 @@ GetPostscriptPoints( #define GetBValue(rgb) ((BYTE)((rgb)>>16)) */ -#else /* !WIN32 */ +#else /* !_WIN32 */ #define GetRValue(rgb) ((rgb & cdata->red_mask) >> cdata->red_shift) #define GetGValue(rgb) ((rgb & cdata->green_mask) >> cdata->green_shift) #define GetBValue(rgb) ((rgb & cdata->blue_mask) >> cdata->blue_shift) -#endif /* WIN32 */ +#endif /* _WIN32 */ -#if defined(WIN32) || defined(MAC_OSX_TK) +#if defined(_WIN32) || defined(MAC_OSX_TK) static void TkImageGetColor( TkColormapData *cdata, /* Colormap data */ @@ -1198,7 +1198,7 @@ TkImageGetColor( *green = (double) GetGValue(pixel) / 255.0; *blue = (double) GetBValue(pixel) / 255.0; } -#else /* ! (WIN32 || MAC_OSX_TK) */ +#else /* ! (_WIN32 || MAC_OSX_TK) */ static void TkImageGetColor( TkColormapData *cdata, /* Colormap data */ @@ -1220,7 +1220,7 @@ TkImageGetColor( *blue = cdata->colors[pixel].blue / 65535.0; } } -#endif /* WIN32 || MAC_OSX_TK */ +#endif /* _WIN32 || MAC_OSX_TK */ /* *-------------------------------------------------------------- diff --git a/generic/tkCanvUtil.c b/generic/tkCanvUtil.c index 23c73e5..cbbc2b4 100644 --- a/generic/tkCanvUtil.c +++ b/generic/tkCanvUtil.c @@ -1432,7 +1432,7 @@ Tk_CanvasPsOutline( char *p = ptr; converted = Tcl_ObjPrintf("%d", *p++ & 0xff); - for (i = dash->number-1 ; i>=0 ; i--) { + for (i = dash->number-1 ; i>0 ; i--) { Tcl_AppendPrintfToObj(converted, " %d", *p++ & 0xff); } Tcl_AppendObjToObj(psObj, converted); diff --git a/generic/tkCanvas.c b/generic/tkCanvas.c index 07f1cfe..9c4d60a 100644 --- a/generic/tkCanvas.c +++ b/generic/tkCanvas.c @@ -1047,7 +1047,7 @@ CanvasWidgetCmd( command = Tk_GetBinding(interp, canvasPtr->bindingTable, object, Tcl_GetString(objv[3])); if (command == NULL) { - const char *string = Tcl_GetStringResult(interp); + const char *string = Tcl_GetString(Tcl_GetObjResult(interp)); /* * Ignore missing binding errors. This is a special hack that @@ -1242,14 +1242,15 @@ CanvasWidgetCmd( int isNew = 0; Tcl_HashEntry *entryPtr; const char *arg; - int length; + size_t length; if (objc < 3) { Tcl_WrongNumArgs(interp, 2, objv, "type coords ?arg ...?"); result = TCL_ERROR; goto done; } - arg = Tcl_GetStringFromObj(objv[2], &length); + arg = Tcl_GetString(objv[2]); + length = objv[2]->length; c = arg[0]; /* @@ -1261,7 +1262,7 @@ CanvasWidgetCmd( Tcl_MutexLock(&typeListMutex); for (typePtr = typeList; typePtr != NULL; typePtr = typePtr->nextPtr){ if ((c == typePtr->name[0]) - && (!strncmp(arg, typePtr->name, (unsigned)length))) { + && (!strncmp(arg, typePtr->name, length))) { if (matchPtr != NULL) { Tcl_MutexUnlock(&typeListMutex); goto badType; @@ -2446,6 +2447,19 @@ DisplayCanvas( goto done; } +#ifdef MAC_OSX_TK + /* + * If drawing is disabled, all we need to do is + * clear the REDRAW_PENDING flag. + */ + TkWindow *winPtr = (TkWindow *)(canvasPtr->tkwin); + MacDrawable *macWin = winPtr->privatePtr; + if (macWin && (macWin->flags & TK_DO_NOT_DRAW)){ + canvasPtr->flags &= ~REDRAW_PENDING; + return; + } +#endif + /* * Choose a new current item if that is needed (this could cause event * handlers to be invoked). @@ -5539,6 +5553,7 @@ CanvasUpdateScrollbars( int xOrigin, yOrigin, inset, width, height; int scrollX1, scrollX2, scrollY1, scrollY2; char *xScrollCmd, *yScrollCmd; + Tcl_DString buf; /* * Save all the relevant values from the canvasPtr, because it might be @@ -5569,8 +5584,12 @@ CanvasUpdateScrollbars( Tcl_Obj *fractions = ScrollFractions(xOrigin + inset, xOrigin + width - inset, scrollX1, scrollX2); - result = Tcl_VarEval(interp, xScrollCmd," ",Tcl_GetString(fractions), - NULL); + Tcl_DStringInit(&buf); + Tcl_DStringAppend(&buf, xScrollCmd, -1); + Tcl_DStringAppend(&buf, " ", -1); + Tcl_DStringAppend(&buf, Tcl_GetString(fractions), -1); + result = Tcl_EvalEx(interp, Tcl_DStringValue(&buf), -1, 0); + Tcl_DStringFree(&buf); Tcl_DecrRefCount(fractions); if (result != TCL_OK) { Tcl_BackgroundException(interp, result); @@ -5583,8 +5602,12 @@ CanvasUpdateScrollbars( Tcl_Obj *fractions = ScrollFractions(yOrigin + inset, yOrigin + height - inset, scrollY1, scrollY2); - result = Tcl_VarEval(interp, yScrollCmd," ",Tcl_GetString(fractions), - NULL); + Tcl_DStringInit(&buf); + Tcl_DStringAppend(&buf, yScrollCmd, -1); + Tcl_DStringAppend(&buf, " ", -1); + Tcl_DStringAppend(&buf, Tcl_GetString(fractions), -1); + result = Tcl_EvalEx(interp, Tcl_DStringValue(&buf), -1, 0); + Tcl_DStringFree(&buf); Tcl_DecrRefCount(fractions); if (result != TCL_OK) { Tcl_BackgroundException(interp, result); diff --git a/generic/tkCmds.c b/generic/tkCmds.c index 4e9494b..6196b17 100644 --- a/generic/tkCmds.c +++ b/generic/tkCmds.c @@ -14,7 +14,7 @@ #include "tkInt.h" -#if defined(WIN32) +#if defined(_WIN32) #include "tkWinInt.h" #elif defined(MAC_OSX_TK) #include "tkMacOSXInt.h" @@ -49,7 +49,7 @@ static int WindowingsystemCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv); -#if defined(__WIN32__) || defined(MAC_OSX_TK) +#if defined(_WIN32) || defined(MAC_OSX_TK) MODULE_SCOPE const TkEnsemble tkFontchooserEnsemble[]; #else #define tkFontchooserEnsemble NULL @@ -109,8 +109,8 @@ Tk_BellObjCmd( } for (i = 1; i < objc; i++) { - if (Tcl_GetIndexFromObj(interp, objv[i], bellOptions, "option", 0, - &index) != TCL_OK) { + if (Tcl_GetIndexFromObjStruct(interp, objv[i], bellOptions, + sizeof(char *), "option", 0, &index) != TCL_OK) { return TCL_ERROR; } switch ((enum options) index) { @@ -452,7 +452,7 @@ TkFreeBindingTags( * have to be freed. */ - ckfree(p); + ckfree((char *)p); } } ckfree(winPtr->tagPtr); @@ -649,7 +649,7 @@ TkInitTkCmd( ClientData clientData) { TkMakeEnsemble(interp, "::", "tk", clientData, tkCmdMap); -#if defined(__WIN32__) || defined(MAC_OSX_TK) +#if defined(_WIN32) || defined(MAC_OSX_TK) TkInitFontchooser(interp, clientData); #endif return TCL_OK; @@ -914,7 +914,7 @@ WindowingsystemCmd( Tcl_WrongNumArgs(interp, 1, objv, NULL); return TCL_ERROR; } -#if defined(WIN32) +#if defined(_WIN32) windowingsystem = "win32"; #elif defined(MAC_OSX_TK) windowingsystem = "aqua"; @@ -1018,8 +1018,8 @@ Tk_TkwaitObjCmd( switch ((enum options) index) { case TKWAIT_VARIABLE: - if (Tcl_TraceVar(interp, Tcl_GetString(objv[2]), - TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, + if (Tcl_TraceVar2(interp, Tcl_GetString(objv[2]), + NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, WaitVariableProc, &done) != TCL_OK) { return TCL_ERROR; } @@ -1031,8 +1031,8 @@ Tk_TkwaitObjCmd( } Tcl_DoOneEvent(0); } - Tcl_UntraceVar(interp, Tcl_GetString(objv[2]), - TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, + Tcl_UntraceVar2(interp, Tcl_GetString(objv[2]), + NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, WaitVariableProc, &done); break; @@ -2094,7 +2094,7 @@ TkGetDisplayOf( /* *---------------------------------------------------------------------- * - * TkDeadAppCmd -- + * TkDeadAppObjCmd -- * * If an application has been deleted then all Tk commands will be * re-bound to this function. @@ -2111,15 +2111,15 @@ TkGetDisplayOf( /* ARGSUSED */ int -TkDeadAppCmd( +TkDeadAppObjCmd( ClientData clientData, /* Dummy. */ Tcl_Interp *interp, /* Current interpreter. */ - int argc, /* Number of arguments. */ - const char **argv) /* Argument strings. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument strings. */ { Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "can't invoke \"%s\" command: application has been destroyed", - argv[0])); + "can't invoke \"%s\" command: application has been destroyed", + Tcl_GetString(objv[0]))); return TCL_ERROR; } diff --git a/generic/tkColor.c b/generic/tkColor.c index e4fa3f7..9abb448 100644 --- a/generic/tkColor.c +++ b/generic/tkColor.c @@ -829,7 +829,7 @@ TkDebugColor( return resultPtr; } -#ifndef __WIN32__ +#ifndef _WIN32 /* This function is not necessary for Win32, * since XParseColor already does the right thing */ @@ -937,7 +937,7 @@ TkParseColor( done: return XParseColor(display, map, name, color); } -#endif /* __WIN32__ */ +#endif /* _WIN32 */ /* * Local Variables: * mode: c diff --git a/generic/tkConfig.c b/generic/tkConfig.c index b3e76d2..9c159e6 100644 --- a/generic/tkConfig.c +++ b/generic/tkConfig.c @@ -27,11 +27,16 @@ #include "tkFont.h" /* - * The following definition is an AssocData key used to keep track of all of - * the option tables that have been created for an interpreter. + * The following definition keeps track of all of + * the option tables that have been created for a thread. */ -#define OPTION_HASH_KEY "TkOptionTable" +typedef struct ThreadSpecificData { + int initialized; /* 0 means table below needs initializing. */ + Tcl_HashTable hashTable; +} ThreadSpecificData; +static Tcl_ThreadDataKey dataKey; + /* * The following two structures are used along with Tk_OptionSpec structures @@ -100,8 +105,6 @@ typedef struct OptionTable { * chain. */ int numOptions; /* The number of items in the options array * below. */ - int refCount2; /* Reference counter for controlling the freeing - * of the memory occupied by this OptionTable */ Option options[1]; /* Information about the individual options in * the table. This must be the last field in * the structure: the actual size of the array @@ -115,8 +118,6 @@ typedef struct OptionTable { static int DoObjConfig(Tcl_Interp *interp, char *recordPtr, Option *optionPtr, Tcl_Obj *valuePtr, Tk_Window tkwin, Tk_SavedOption *savePtr); -static void DestroyOptionHashTable(ClientData clientData, - Tcl_Interp *interp); static void FreeResources(Option *optionPtr, Tcl_Obj *objPtr, char *internalPtr, Tk_Window tkwin); static Tcl_Obj * GetConfigList(char *recordPtr, @@ -128,7 +129,7 @@ static Option * GetOptionFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, OptionTable *tablePtr); static int ObjectIsEmpty(Tcl_Obj *objPtr); static void FreeOptionInternalRep(Tcl_Obj *objPtr); -static int SetOptionFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr); +static void DupOptionInternalRep(Tcl_Obj *, Tcl_Obj *); /* * The structure below defines an object type that is used to cache the result @@ -140,9 +141,9 @@ static int SetOptionFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr); static const Tcl_ObjType optionObjType = { "option", /* name */ FreeOptionInternalRep, /* freeIntRepProc */ - NULL, /* dupIntRepProc */ + DupOptionInternalRep, /* dupIntRepProc */ NULL, /* updateStringProc */ - SetOptionFromAny /* setFromAnyProc */ + NULL /* setFromAnyProc */ }; /* @@ -171,30 +172,26 @@ Tk_CreateOptionTable( /* Static information about the configuration * options. */ { - Tcl_HashTable *hashTablePtr; Tcl_HashEntry *hashEntryPtr; int newEntry; OptionTable *tablePtr; const Tk_OptionSpec *specPtr, *specPtr2; Option *optionPtr; int numOptions, i; + ThreadSpecificData *tsdPtr = + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); /* - * We use an AssocData value in the interpreter to keep a hash table of - * all the option tables we've created for this application. This is used - * for two purposes. First, it allows us to share the tables (e.g. in - * several chains) and second, we use the deletion callback for the - * AssocData to delete all the option tables when the interpreter is - * deleted. The code below finds the hash table or creates a new one if it + * We use an TSD in the thread to keep a hash table of + * all the option tables we've created for this application. This is + * used for allowing us to share the tables (e.g. in several chains). + * The code below finds the hash table or creates a new one if it * doesn't already exist. */ - hashTablePtr = Tcl_GetAssocData(interp, OPTION_HASH_KEY, NULL); - if (hashTablePtr == NULL) { - hashTablePtr = ckalloc(sizeof(Tcl_HashTable)); - Tcl_InitHashTable(hashTablePtr, TCL_ONE_WORD_KEYS); - Tcl_SetAssocData(interp, OPTION_HASH_KEY, DestroyOptionHashTable, - hashTablePtr); + if (!tsdPtr->initialized) { + Tcl_InitHashTable(&tsdPtr->hashTable, TCL_ONE_WORD_KEYS); + tsdPtr->initialized = 1; } /* @@ -202,7 +199,7 @@ Tk_CreateOptionTable( * reuse the existing table. */ - hashEntryPtr = Tcl_CreateHashEntry(hashTablePtr, (char *) templatePtr, + hashEntryPtr = Tcl_CreateHashEntry(&tsdPtr->hashTable, (char *) templatePtr, &newEntry); if (!newEntry) { tablePtr = Tcl_GetHashValue(hashEntryPtr); @@ -221,7 +218,6 @@ Tk_CreateOptionTable( } tablePtr = ckalloc(sizeof(OptionTable) + (numOptions * sizeof(Option))); tablePtr->refCount = 1; - tablePtr->refCount2 = 1; tablePtr->hashEntryPtr = hashEntryPtr; tablePtr->nextPtr = NULL; tablePtr->numOptions = numOptions; @@ -357,62 +353,7 @@ Tk_DeleteOptionTable( } } Tcl_DeleteHashEntry(tablePtr->hashEntryPtr); - tablePtr->refCount2--; - if (tablePtr->refCount2 <= 0) { - ckfree(tablePtr); - } -} - -/* - *---------------------------------------------------------------------- - * - * DestroyOptionHashTable -- - * - * This function is the deletion callback associated with the AssocData - * entry created by Tk_CreateOptionTable. It is invoked when an - * interpreter is deleted, and deletes all of the option tables - * associated with that interpreter. - * - * Results: - * None. - * - * Side effects: - * The option hash table is destroyed along with all of the OptionTable - * structures that it refers to. - * - *---------------------------------------------------------------------- - */ - -static void -DestroyOptionHashTable( - ClientData clientData, /* The hash table we are destroying */ - Tcl_Interp *interp) /* The interpreter we are destroying */ -{ - Tcl_HashTable *hashTablePtr = clientData; - Tcl_HashSearch search; - Tcl_HashEntry *hashEntryPtr; - - for (hashEntryPtr = Tcl_FirstHashEntry(hashTablePtr, &search); - hashEntryPtr != NULL; - hashEntryPtr = Tcl_NextHashEntry(&search)) { - OptionTable *tablePtr = Tcl_GetHashValue(hashEntryPtr); - - /* - * The following statements do two tricky things: - * 1. They ensure that the option table is deleted, even if there are - * outstanding references to it. - * 2. They ensure that Tk_DeleteOptionTable doesn't delete other - * tables chained from this one; we'll do it when we come across - * the hash table entry for the chained table (in fact, the chained - * table may already have been deleted). - */ - - tablePtr->refCount = 1; - tablePtr->nextPtr = NULL; - Tk_DeleteOptionTable((Tk_OptionTable) tablePtr); - } - Tcl_DeleteHashTable(hashTablePtr); - ckfree(hashTablePtr); + ckfree(tablePtr); } /* @@ -737,8 +678,8 @@ DoObjConfig( case TK_OPTION_STRING_TABLE: { int newValue; - if (Tcl_GetIndexFromObj(interp, valuePtr, - optionPtr->specPtr->clientData, + if (Tcl_GetIndexFromObjStruct(interp, valuePtr, + optionPtr->specPtr->clientData, sizeof(char *), optionPtr->specPtr->optionName+1, 0, &newValue) != TCL_OK) { return TCL_ERROR; } @@ -1004,7 +945,7 @@ ObjectIsEmpty( if (objPtr->bytes != NULL) { return (objPtr->length == 0); } - Tcl_GetStringFromObj(objPtr, &length); + (void)Tcl_GetStringFromObj(objPtr, &length); return (length == 0); } @@ -1152,7 +1093,7 @@ GetOptionFromObj( objPtr->internalRep.twoPtrValue.ptr1 = (void *) tablePtr; objPtr->internalRep.twoPtrValue.ptr2 = (void *) bestPtr; objPtr->typePtr = &optionObjType; - tablePtr->refCount2++; + tablePtr->refCount++; return bestPtr; error: @@ -1204,38 +1145,6 @@ TkGetOptionSpec( /* *---------------------------------------------------------------------- * - * SetOptionFromAny -- - * - * This function is called to convert a Tcl object to option internal - * form. However, this doesn't make sense (need to have a table of - * options in order to do the conversion) so the function always - * generates an error. - * - * Results: - * The return value is always TCL_ERROR, and an error message is left in - * interp's result if interp isn't NULL. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -static int -SetOptionFromAny( - Tcl_Interp *interp, /* Used for error reporting if not NULL. */ - register Tcl_Obj *objPtr) /* The object to convert. */ -{ - Tcl_SetObjResult(interp, Tcl_NewStringObj( - "can't convert value to option except via GetOptionFromObj API", - -1)); - Tcl_SetErrorCode(interp, "TK", "API_ABUSE", NULL); - return TCL_ERROR; -} - -/* - *---------------------------------------------------------------------- - * * FreeOptionInternalRep -- * * Part of the option Tcl object type implementation. Frees the storage @@ -1257,18 +1166,37 @@ static void FreeOptionInternalRep( register Tcl_Obj *objPtr) /* Object whose internal rep to free. */ { - register OptionTable *tablePtr = (OptionTable *) objPtr->internalRep.twoPtrValue.ptr1; + register Tk_OptionTable tablePtr = (Tk_OptionTable) objPtr->internalRep.twoPtrValue.ptr1; - tablePtr->refCount2--; - if (tablePtr->refCount2 <= 0) { - ckfree(tablePtr); - } + Tk_DeleteOptionTable(tablePtr); objPtr->typePtr = NULL; objPtr->internalRep.twoPtrValue.ptr1 = NULL; objPtr->internalRep.twoPtrValue.ptr2 = NULL; } /* + *--------------------------------------------------------------------------- + * + * DupOptionInternalRep -- + * + * When a cached option object is duplicated, this is called to update the + * internal reps. + * + *--------------------------------------------------------------------------- + */ + +static void +DupOptionInternalRep( + Tcl_Obj *srcObjPtr, /* The object we are copying from. */ + Tcl_Obj *dupObjPtr) /* The object we are copying to. */ +{ + register OptionTable *tablePtr = (OptionTable *) srcObjPtr->internalRep.twoPtrValue.ptr1; + tablePtr->refCount++; + dupObjPtr->typePtr = srcObjPtr->typePtr; + dupObjPtr->internalRep = srcObjPtr->internalRep; +} + +/* *-------------------------------------------------------------- * * Tk_SetOptions -- @@ -1347,7 +1275,7 @@ Tk_SetOptions( if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "value for \"%s\" missing", - Tcl_GetStringFromObj(*objv, NULL))); + Tcl_GetString(*objv))); Tcl_SetErrorCode(interp, "TK", "VALUE_MISSING", NULL); goto error; } @@ -1372,7 +1300,7 @@ Tk_SetOptions( : NULL) != TCL_OK) { Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf( "\n (processing \"%.40s\" option)", - Tcl_GetStringFromObj(*objv, NULL))); + Tcl_GetString(*objv))); goto error; } if (savePtr != NULL) { @@ -2146,14 +2074,14 @@ TkDebugConfig( * interpreter anymore. */ { OptionTable *tablePtr = (OptionTable *) table; - Tcl_HashTable *hashTablePtr; Tcl_HashEntry *hashEntryPtr; Tcl_HashSearch search; Tcl_Obj *objPtr; + ThreadSpecificData *tsdPtr = + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); objPtr = Tcl_NewObj(); - hashTablePtr = Tcl_GetAssocData(interp, OPTION_HASH_KEY, NULL); - if (hashTablePtr == NULL) { + if (!tablePtr || !tsdPtr->initialized) { return objPtr; } @@ -2162,7 +2090,7 @@ TkDebugConfig( * want still is valid. */ - for (hashEntryPtr = Tcl_FirstHashEntry(hashTablePtr, &search); + for (hashEntryPtr = Tcl_FirstHashEntry(&tsdPtr->hashTable, &search); hashEntryPtr != NULL; hashEntryPtr = Tcl_NextHashEntry(&search)) { if (tablePtr == (OptionTable *) Tcl_GetHashValue(hashEntryPtr)) { diff --git a/generic/tkConsole.c b/generic/tkConsole.c index 434350a..8bfbe9b 100644 --- a/generic/tkConsole.c +++ b/generic/tkConsole.c @@ -84,7 +84,7 @@ static const Tcl_ChannelType consoleChannelType = { NULL }; -#ifdef __WIN32__ +#ifdef _WIN32 #include <windows.h> /* @@ -220,11 +220,10 @@ Tk_InitConsoleChannels( Tcl_Channel consoleChannel; /* - * Ensure that we are getting a compatible version of Tcl. This is really - * only an issue when Tk is loaded dynamically. + * Ensure that we are getting a compatible version of Tcl. */ - if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) { + if (Tcl_InitStubs(interp, "8.6", 0) == NULL) { return; } @@ -439,7 +438,8 @@ Tk_CreateConsoleWindow( } Tcl_Preserve(consoleInterp); - result = Tcl_GlobalEval(consoleInterp, "source $tk_library/console.tcl"); + result = Tcl_EvalEx(consoleInterp, "source $tk_library/console.tcl", + -1, TCL_EVAL_GLOBAL); if (result == TCL_ERROR) { Tcl_SetReturnOptions(interp, Tcl_GetReturnOptions(consoleInterp, result)); @@ -531,7 +531,7 @@ ConsoleOutput( Tcl_DStringFree(&ds); Tcl_IncrRefCount(cmd); - Tcl_GlobalEvalObj(consoleInterp, cmd); + Tcl_EvalObjEx(consoleInterp, cmd, TCL_EVAL_GLOBAL); Tcl_DecrRefCount(cmd); } } @@ -697,8 +697,8 @@ ConsoleObjCmd( Tcl_WrongNumArgs(interp, 1, objv, "option ?arg?"); return TCL_ERROR; } - if (Tcl_GetIndexFromObj(interp, objv[1], options, "option", 0, &index) - != TCL_OK) { + if (Tcl_GetIndexFromObjStruct(interp, objv[1], options, + sizeof(char *), "option", 0, &index) != TCL_OK) { return TCL_ERROR; } @@ -741,7 +741,7 @@ ConsoleObjCmd( Tcl_IncrRefCount(cmd); if (consoleInterp && !Tcl_InterpDeleted(consoleInterp)) { Tcl_Preserve(consoleInterp); - result = Tcl_GlobalEvalObj(consoleInterp, cmd); + result = Tcl_EvalObjEx(consoleInterp, cmd, TCL_EVAL_GLOBAL); Tcl_SetReturnOptions(interp, Tcl_GetReturnOptions(consoleInterp, result)); Tcl_SetObjResult(interp, Tcl_GetObjResult(consoleInterp)); @@ -787,8 +787,8 @@ InterpreterObjCmd( Tcl_WrongNumArgs(interp, 1, objv, "option arg"); return TCL_ERROR; } - if (Tcl_GetIndexFromObj(interp, objv[1], options, "option", 0, &index) - != TCL_OK) { + if (Tcl_GetIndexFromObjStruct(interp, objv[1], options, + sizeof(char *), "option", 0, &index) != TCL_OK) { return TCL_ERROR; } @@ -807,7 +807,7 @@ InterpreterObjCmd( Tcl_Preserve(otherInterp); switch ((enum option) index) { case OTHER_EVAL: - result = Tcl_GlobalEvalObj(otherInterp, objv[2]); + result = Tcl_EvalObjEx(otherInterp, objv[2], TCL_EVAL_GLOBAL); /* * TODO: Should exceptions be filtered here? @@ -946,7 +946,7 @@ ConsoleEventProc( Tcl_Interp *consoleInterp = info->consoleInterp; if (consoleInterp && !Tcl_InterpDeleted(consoleInterp)) { - Tcl_GlobalEval(consoleInterp, "tk::ConsoleExit"); + Tcl_EvalEx(consoleInterp, "tk::ConsoleExit", -1, TCL_EVAL_GLOBAL); } if (--info->refCount <= 0) { diff --git a/generic/tkDecls.h b/generic/tkDecls.h index d080e93..64c32cd 100644 --- a/generic/tkDecls.h +++ b/generic/tkDecls.h @@ -25,6 +25,10 @@ /* !BEGIN!: Do not edit below this line. */ +#ifdef __cplusplus +extern "C" { +#endif + /* * Exported function declarations: */ @@ -860,12 +864,8 @@ EXTERN void Tk_CreateOldImageType(const Tk_ImageType *typePtr); /* 273 */ EXTERN void Tk_CreateOldPhotoImageFormat( const Tk_PhotoImageFormat *formatPtr); -/* 274 */ -EXTERN void reserved274(void); -/* 275 */ -EXTERN void reserved275(void); -typedef struct TkStubHooks { +typedef struct { const struct TkPlatStubs *tkPlatStubs; const struct TkIntStubs *tkIntStubs; const struct TkIntPlatStubs *tkIntPlatStubs; @@ -874,7 +874,7 @@ typedef struct TkStubHooks { typedef struct TkStubs { int magic; - const struct TkStubHooks *hooks; + const TkStubHooks *hooks; void (*tk_MainLoop) (void); /* 0 */ XColor * (*tk_3DBorderColor) (Tk_3DBorder border); /* 1 */ @@ -1150,14 +1150,10 @@ typedef struct TkStubs { Tcl_Interp * (*tk_Interp) (Tk_Window tkwin); /* 271 */ void (*tk_CreateOldImageType) (const Tk_ImageType *typePtr); /* 272 */ void (*tk_CreateOldPhotoImageFormat) (const Tk_PhotoImageFormat *formatPtr); /* 273 */ - void (*reserved274) (void); /* 274 */ - void (*reserved275) (void); /* 275 */ } TkStubs; -#ifdef __cplusplus -extern "C" { -#endif extern const TkStubs *tkStubsPtr; + #ifdef __cplusplus } #endif @@ -1714,10 +1710,6 @@ extern const TkStubs *tkStubsPtr; (tkStubsPtr->tk_CreateOldImageType) /* 272 */ #define Tk_CreateOldPhotoImageFormat \ (tkStubsPtr->tk_CreateOldPhotoImageFormat) /* 273 */ -#define reserved274 \ - (tkStubsPtr->reserved274) /* 274 */ -#define reserved275 \ - (tkStubsPtr->reserved275) /* 275 */ #endif /* defined(USE_TK_STUBS) */ diff --git a/generic/tkEntry.c b/generic/tkEntry.c index d78f396..ea8d7f1 100644 --- a/generic/tkEntry.c +++ b/generic/tkEntry.c @@ -133,7 +133,7 @@ static const Tk_OptionSpec entryOptSpec[] = { 0, DEF_ENTRY_SELECT_BD_MONO, 0}, {TK_OPTION_COLOR, "-selectforeground", "selectForeground", "Background", DEF_ENTRY_SELECT_FG_COLOR, -1, Tk_Offset(Entry, selFgColorPtr), - TK_CONFIG_NULL_OK, DEF_ENTRY_SELECT_FG_MONO, 0}, + TK_OPTION_NULL_OK, DEF_ENTRY_SELECT_FG_MONO, 0}, {TK_OPTION_STRING, "-show", "show", "Show", DEF_ENTRY_SHOW, -1, Tk_Offset(Entry, showChar), TK_OPTION_NULL_OK, 0, 0}, @@ -279,23 +279,23 @@ static const Tk_OptionSpec sbOptSpec[] = { 0, DEF_ENTRY_SELECT_BD_MONO, 0}, {TK_OPTION_COLOR, "-selectforeground", "selectForeground", "Background", DEF_ENTRY_SELECT_FG_COLOR, -1, Tk_Offset(Entry, selFgColorPtr), - TK_CONFIG_NULL_OK, DEF_ENTRY_SELECT_FG_MONO, 0}, + TK_OPTION_NULL_OK, DEF_ENTRY_SELECT_FG_MONO, 0}, {TK_OPTION_STRING_TABLE, "-state", "state", "State", DEF_ENTRY_STATE, -1, Tk_Offset(Entry, state), 0, stateStrings, 0}, {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus", DEF_ENTRY_TAKE_FOCUS, -1, Tk_Offset(Entry, takeFocus), - TK_CONFIG_NULL_OK, 0, 0}, + TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_STRING, "-textvariable", "textVariable", "Variable", DEF_ENTRY_TEXT_VARIABLE, -1, Tk_Offset(Entry, textVarName), - TK_CONFIG_NULL_OK, 0, 0}, + TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_DOUBLE, "-to", "to", "To", DEF_SPINBOX_TO, -1, Tk_Offset(Spinbox, toValue), 0, 0, 0}, {TK_OPTION_STRING_TABLE, "-validate", "validate", "Validate", DEF_ENTRY_VALIDATE, -1, Tk_Offset(Entry, validate), 0, validateStrings, 0}, {TK_OPTION_STRING, "-validatecommand", "validateCommand","ValidateCommand", - NULL, -1, Tk_Offset(Entry, validateCmd), TK_CONFIG_NULL_OK, 0, 0}, + NULL, -1, Tk_Offset(Entry, validateCmd), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_STRING, "-values", "values", "Values", DEF_SPINBOX_VALUES, -1, Tk_Offset(Spinbox, valueStr), TK_OPTION_NULL_OK, 0, 0}, @@ -307,7 +307,7 @@ static const Tk_OptionSpec sbOptSpec[] = { DEF_SPINBOX_WRAP, -1, Tk_Offset(Spinbox, wrap), 0, 0, 0}, {TK_OPTION_STRING, "-xscrollcommand", "xScrollCommand", "ScrollCommand", DEF_ENTRY_SCROLL_COMMAND, -1, Tk_Offset(Entry, scrollCmd), - TK_CONFIG_NULL_OK, 0, 0}, + TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, -1, 0, 0, 0} }; @@ -390,9 +390,9 @@ static const char *const selElementNames[] = { */ static int ConfigureEntry(Tcl_Interp *interp, Entry *entryPtr, - int objc, Tcl_Obj *const objv[], int flags); -static void DeleteChars(Entry *entryPtr, int index, int count); -static void DestroyEntry(char *memPtr); + int objc, Tcl_Obj *const objv[]); +static int DeleteChars(Entry *entryPtr, int index, int count); +static void DestroyEntry(void *memPtr); static void DisplayEntry(ClientData clientData); static void EntryBlinkProc(ClientData clientData); static void EntryCmdDeletedProc(ClientData clientData); @@ -417,7 +417,7 @@ static int EntryValidateChange(Entry *entryPtr, const char *change, static void ExpandPercents(Entry *entryPtr, const char *before, const char *change, const char *newStr, int index, int type, Tcl_DString *dsPtr); -static void EntryValueChanged(Entry *entryPtr, +static int EntryValueChanged(Entry *entryPtr, const char *newValue); static void EntryVisibleRange(Entry *entryPtr, double *firstPtr, double *lastPtr); @@ -427,7 +427,7 @@ static int EntryWidgetObjCmd(ClientData clientData, static void EntryWorldChanged(ClientData instanceData); static int GetEntryIndex(Tcl_Interp *interp, Entry *entryPtr, const char *string, int *indexPtr); -static void InsertChars(Entry *entryPtr, int index, const char *string); +static int InsertChars(Entry *entryPtr, int index, const char *string); /* * These forward declarations are the spinbox specific ones: @@ -554,7 +554,7 @@ Tk_EntryObjCmd( if ((Tk_InitOptions(interp, (char *) entryPtr, optionTable, tkwin) != TCL_OK) || - (ConfigureEntry(interp, entryPtr, objc-2, objv+2, 0) != TCL_OK)) { + (ConfigureEntry(interp, entryPtr, objc-2, objv+2) != TCL_OK)) { Tk_DestroyWindow(entryPtr->tkwin); return TCL_ERROR; } @@ -659,12 +659,12 @@ EntryWidgetObjCmd( } Tcl_SetObjResult(interp, objPtr); } else { - result = ConfigureEntry(interp, entryPtr, objc-2, objv+2, 0); + result = ConfigureEntry(interp, entryPtr, objc-2, objv+2); } break; case COMMAND_DELETE: { - int first, last; + int first, last, code; if ((objc < 3) || (objc > 4)) { Tcl_WrongNumArgs(interp, 2, objv, "firstIndex ?lastIndex?"); @@ -681,7 +681,10 @@ EntryWidgetObjCmd( goto error; } if ((last >= first) && (entryPtr->state == STATE_NORMAL)) { - DeleteChars(entryPtr, first, last - first); + code = DeleteChars(entryPtr, first, last - first); + if (code != TCL_OK) { + goto error; + } } break; } @@ -722,7 +725,7 @@ EntryWidgetObjCmd( } case COMMAND_INSERT: { - int index; + int index, code; if (objc != 4) { Tcl_WrongNumArgs(interp, 2, objv, "index text"); @@ -733,7 +736,10 @@ EntryWidgetObjCmd( goto error; } if (entryPtr->state == STATE_NORMAL) { - InsertChars(entryPtr, index, Tcl_GetString(objv[3])); + code = InsertChars(entryPtr, index, Tcl_GetString(objv[3])); + if (code != TCL_OK) { + goto error; + } } break; } @@ -1010,19 +1016,19 @@ EntryWidgetObjCmd( static void DestroyEntry( - char *memPtr) /* Info about entry widget. */ + void *memPtr) /* Info about entry widget. */ { - Entry *entryPtr = (Entry *) memPtr; + Entry *entryPtr = memPtr; /* * Free up all the stuff that requires special handling, then let * Tk_FreeOptions handle all the standard option-related stuff. */ - ckfree(entryPtr->string); + ckfree((char *)entryPtr->string); if (entryPtr->textVarName != NULL) { - Tcl_UntraceVar(entryPtr->interp, entryPtr->textVarName, - TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, + Tcl_UntraceVar2(entryPtr->interp, entryPtr->textVarName, + NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, EntryTextVarProc, entryPtr); entryPtr->flags &= ~ENTRY_VAR_TRACED; } @@ -1034,7 +1040,7 @@ DestroyEntry( } Tcl_DeleteTimerHandler(entryPtr->insertBlinkHandler); if (entryPtr->displayString != entryPtr->string) { - ckfree(entryPtr->displayString); + ckfree((char *)entryPtr->displayString); } if (entryPtr->type == TK_SPINBOX) { Spinbox *sbPtr = (Spinbox *) entryPtr; @@ -1082,8 +1088,7 @@ ConfigureEntry( Entry *entryPtr, /* Information about widget; may or may not * already have values for some fields. */ int objc, /* Number of valid entries in argv. */ - Tcl_Obj *const objv[], /* Argument objects. */ - int flags) /* Flags to pass to Tk_ConfigureWidget. */ + Tcl_Obj *const objv[]) /* Argument objects. */ { Tk_SavedOptions savedOptions; Tk_3DBorder border; @@ -1098,6 +1103,7 @@ ConfigureEntry( int valuesChanged = 0; /* lint initialization */ double oldFrom = 0.0; /* lint initialization */ double oldTo = 0.0; /* lint initialization */ + int code; /* * Eliminate any existing trace on a variable monitored by the entry. @@ -1105,7 +1111,7 @@ ConfigureEntry( if ((entryPtr->textVarName != NULL) && (entryPtr->flags & ENTRY_VAR_TRACED)) { - Tcl_UntraceVar(interp, entryPtr->textVarName, + Tcl_UntraceVar2(interp, entryPtr->textVarName, NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, EntryTextVarProc, entryPtr); entryPtr->flags &= ~ENTRY_VAR_TRACED; @@ -1303,8 +1309,19 @@ ConfigureEntry( if (entryPtr->textVarName != NULL) { const char *value; - value = Tcl_GetVar(interp, entryPtr->textVarName, TCL_GLOBAL_ONLY); + value = Tcl_GetVar2(interp, entryPtr->textVarName, NULL, TCL_GLOBAL_ONLY); if (value == NULL) { + + /* + * Since any trace on the textvariable was eliminated above, + * the only possible reason for EntryValueChanged to return + * an error is that the textvariable lives in a namespace + * that does not (yet) exist. Indeed, namespaces are not + * automatically created as needed. Don't trap this error + * here, better do it below when attempting to trace the + * variable. + */ + EntryValueChanged(entryPtr, NULL); } else { EntrySetValue(entryPtr, value); @@ -1323,7 +1340,13 @@ ConfigureEntry( */ Tcl_ListObjIndex(interp, sbPtr->listObj, 0, &objPtr); - EntryValueChanged(entryPtr, Tcl_GetString(objPtr)); + + /* + * No check for error return here as well, because any possible + * error will be trapped below when attempting tracing. + */ + + EntryValueChanged(entryPtr, Tcl_GetString(objPtr)); } else if ((sbPtr->valueStr == NULL) && !DOUBLES_EQ(sbPtr->fromValue, sbPtr->toValue) && (!DOUBLES_EQ(sbPtr->fromValue, oldFrom) @@ -1337,7 +1360,7 @@ ConfigureEntry( double dvalue; - if (sscanf(entryPtr->string, "%lf", &dvalue) == 0) { + if (sscanf(entryPtr->string, "%lf", &dvalue) <= 0) { /* Scan failure */ dvalue = sbPtr->fromValue; } else if (dvalue > sbPtr->toValue) { @@ -1346,6 +1369,12 @@ ConfigureEntry( dvalue = sbPtr->fromValue; } sprintf(sbPtr->formatBuf, sbPtr->valueFormat, dvalue); + + /* + * No check for error return here as well, because any possible + * error will be trapped below when attempting tracing. + */ + EntryValueChanged(entryPtr, sbPtr->formatBuf); } } @@ -1357,10 +1386,13 @@ ConfigureEntry( if ((entryPtr->textVarName != NULL) && !(entryPtr->flags & ENTRY_VAR_TRACED)) { - Tcl_TraceVar(interp, entryPtr->textVarName, - TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, + code = Tcl_TraceVar2(interp, entryPtr->textVarName, + NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, EntryTextVarProc, entryPtr); - entryPtr->flags |= ENTRY_VAR_TRACED; + if (code != TCL_OK) { + return TCL_ERROR; + } + entryPtr->flags |= ENTRY_VAR_TRACED; } EntryWorldChanged(entryPtr); @@ -1680,7 +1712,7 @@ DisplayEntry( Tk_CharBbox(entryPtr->textLayout, entryPtr->insertPos, &cursorX, NULL, NULL, NULL); cursorX += entryPtr->layoutX; - cursorX -= (entryPtr->insertWidth)/2; + cursorX -= (entryPtr->insertWidth == 1) ? 1 : (entryPtr->insertWidth)/2; Tk_SetCaretPos(entryPtr->tkwin, cursorX, baseY - fm.ascent, fm.ascent + fm.descent); if (entryPtr->insertPos >= entryPtr->leftIndex && cursorX < xBound) { @@ -1881,7 +1913,7 @@ EntryComputeGeometry( char *p; if (entryPtr->displayString != entryPtr->string) { - ckfree(entryPtr->displayString); + ckfree((char *)entryPtr->displayString); entryPtr->displayString = entryPtr->string; entryPtr->numDisplayBytes = entryPtr->numBytes; } @@ -1993,7 +2025,8 @@ EntryComputeGeometry( * Add new characters to an entry widget. * * Results: - * None. + * A standard Tcl result. If an error occurred then an error message is + * left in the interp's result. * * Side effects: * New information gets added to entryPtr; it will be redisplayed soon, @@ -2002,12 +2035,12 @@ EntryComputeGeometry( *---------------------------------------------------------------------- */ -static void +static int InsertChars( Entry *entryPtr, /* Entry that is to get the new elements. */ int index, /* Add the new elements before this character * index. */ - const char *value) /* New characters to add (NULL-terminated + const char *value) /* New characters to add (NULL-terminated * string). */ { ptrdiff_t byteIndex; @@ -2020,7 +2053,7 @@ InsertChars( byteIndex = Tcl_UtfAtIndex(string, index) - string; byteCount = strlen(value); if (byteCount == 0) { - return; + return TCL_OK; } newByteCount = entryPtr->numBytes + byteCount + 1; @@ -2034,10 +2067,10 @@ InsertChars( EntryValidateChange(entryPtr, value, newStr, index, VALIDATE_INSERT) != TCL_OK) { ckfree(newStr); - return; + return TCL_OK; } - ckfree(string); + ckfree((char *)string); entryPtr->string = newStr; /* @@ -2082,7 +2115,7 @@ InsertChars( if (entryPtr->insertPos >= index) { entryPtr->insertPos += charsAdded; } - EntryValueChanged(entryPtr, NULL); + return EntryValueChanged(entryPtr, NULL); } /* @@ -2093,7 +2126,8 @@ InsertChars( * Remove one or more characters from an entry widget. * * Results: - * None. + * A standard Tcl result. If an error occurred then an error message is + * left in the interp's result. * * Side effects: * Memory gets freed, the entry gets modified and (eventually) @@ -2102,7 +2136,7 @@ InsertChars( *---------------------------------------------------------------------- */ -static void +static int DeleteChars( Entry *entryPtr, /* Entry widget to modify. */ int index, /* Index of first character to delete. */ @@ -2116,7 +2150,7 @@ DeleteChars( count = entryPtr->numChars - index; } if (count <= 0) { - return; + return TCL_OK; } string = entryPtr->string; @@ -2138,11 +2172,11 @@ DeleteChars( VALIDATE_DELETE) != TCL_OK) { ckfree(newStr); ckfree(toDelete); - return; + return TCL_OK; } ckfree(toDelete); - ckfree(entryPtr->string); + ckfree((char *)entryPtr->string); entryPtr->string = newStr; entryPtr->numChars -= count; entryPtr->numBytes -= byteCount; @@ -2197,7 +2231,7 @@ DeleteChars( entryPtr->insertPos = index; } } - EntryValueChanged(entryPtr, NULL); + return EntryValueChanged(entryPtr, NULL); } /* @@ -2210,7 +2244,8 @@ DeleteChars( * is one, and does other bookkeeping such as arranging for redisplay. * * Results: - * None. + * A standard Tcl result. If an error occurred then an error message is + * left in the interp's result. * * Side effects: * None. @@ -2218,7 +2253,7 @@ DeleteChars( *---------------------------------------------------------------------- */ -static void +static int EntryValueChanged( Entry *entryPtr, /* Entry whose value just changed. */ const char *newValue) /* If this value is not NULL, we first force @@ -2231,8 +2266,8 @@ EntryValueChanged( if (entryPtr->textVarName == NULL) { newValue = NULL; } else { - newValue = Tcl_SetVar(entryPtr->interp, entryPtr->textVarName, - entryPtr->string, TCL_GLOBAL_ONLY); + newValue = Tcl_SetVar2(entryPtr->interp, entryPtr->textVarName, + NULL, entryPtr->string, TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG); } if ((newValue != NULL) && (strcmp(newValue, entryPtr->string) != 0)) { @@ -2254,6 +2289,19 @@ EntryValueChanged( EntryComputeGeometry(entryPtr); EventuallyRedraw(entryPtr); } + + /* + * An error may have happened when setting the textvariable in case there + * is a trace on that variable and the trace proc triggered an error. + * Another possibility is that the textvariable is in a namespace that + * does not (yet) exist. + * Signal this error. + */ + + if ((entryPtr->textVarName != NULL) && (newValue == NULL)) { + return TCL_ERROR; + } + return TCL_OK; } /* @@ -2318,13 +2366,13 @@ EntrySetValue( if (entryPtr->flags & VALIDATE_ABORT) { entryPtr->flags &= ~VALIDATE_ABORT; - ckfree(value); + ckfree((char *)value); return; } } oldSource = entryPtr->string; - ckfree(entryPtr->string); + ckfree((char *)entryPtr->string); if (malloced) { entryPtr->string = value; @@ -2429,7 +2477,7 @@ EntryEventProc( if (entryPtr->flags & REDRAW_PENDING) { Tcl_CancelIdleCall(DisplayEntry, clientData); } - Tcl_EventuallyFree(clientData, DestroyEntry); + Tcl_EventuallyFree(clientData, (Tcl_FreeProc *) DestroyEntry); } break; case ConfigureNotify: @@ -2560,7 +2608,7 @@ GetEntryIndex( case '@': { int x, roundUp, maxWidth; - if (Tcl_GetInt(interp, string + 1, &x) != TCL_OK) { + if (Tcl_GetInt(NULL, string + 1, &x) != TCL_OK) { goto badIndex; } if (x < entryPtr->inset) { @@ -2589,7 +2637,7 @@ GetEntryIndex( break; } default: - if (Tcl_GetInt(interp, string, indexPtr) != TCL_OK) { + if (Tcl_GetInt(NULL, string, indexPtr) != TCL_OK) { goto badIndex; } if (*indexPtr < 0){ @@ -2939,6 +2987,7 @@ EntryUpdateScrollbar( int code; double first, last; Tcl_Interp *interp; + Tcl_DString buf; if (entryPtr->scrollCmd == NULL) { return; @@ -2949,8 +2998,14 @@ EntryUpdateScrollbar( EntryVisibleRange(entryPtr, &first, &last); Tcl_PrintDouble(NULL, first, firstStr); Tcl_PrintDouble(NULL, last, lastStr); - code = Tcl_VarEval(interp, entryPtr->scrollCmd, " ", firstStr, " ", - lastStr, NULL); + Tcl_DStringInit(&buf); + Tcl_DStringAppend(&buf, entryPtr->scrollCmd, -1); + Tcl_DStringAppend(&buf, " ", -1); + Tcl_DStringAppend(&buf, firstStr, -1); + Tcl_DStringAppend(&buf, " ", -1); + Tcl_DStringAppend(&buf, lastStr, -1); + code = Tcl_EvalEx(interp, Tcl_DStringValue(&buf), -1, 0); + Tcl_DStringFree(&buf); if (code != TCL_OK) { Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf( "\n (horizontal scrolling command executed by %s)", @@ -3095,9 +3150,9 @@ EntryTextVarProc( if (flags & TCL_TRACE_UNSETS) { if ((flags & TCL_TRACE_DESTROYED) && !(flags & TCL_INTERP_DESTROYED)) { - Tcl_SetVar(interp, entryPtr->textVarName, entryPtr->string, - TCL_GLOBAL_ONLY); - Tcl_TraceVar(interp, entryPtr->textVarName, + Tcl_SetVar2(interp, entryPtr->textVarName, NULL, + entryPtr->string, TCL_GLOBAL_ONLY); + Tcl_TraceVar2(interp, entryPtr->textVarName, NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, EntryTextVarProc, clientData); entryPtr->flags |= ENTRY_VAR_TRACED; @@ -3111,7 +3166,7 @@ EntryTextVarProc( * value because we changed it because someone typed in the entry). */ - value = Tcl_GetVar(interp, entryPtr->textVarName, TCL_GLOBAL_ONLY); + value = Tcl_GetVar2(interp, entryPtr->textVarName, NULL, TCL_GLOBAL_ONLY); if (value == NULL) { value = ""; } @@ -3171,7 +3226,7 @@ EntryValidate( &bool) != TCL_OK) { Tcl_AddErrorInfo(interp, "\n (invalid boolean result from validation command)"); - Tcl_BackgroundError(interp); + Tcl_BackgroundException(interp, TCL_ERROR); Tcl_ResetResult(interp); return TCL_ERROR; } @@ -3604,7 +3659,7 @@ Tk_SpinboxObjCmd( Tk_DestroyWindow(entryPtr->tkwin); return TCL_ERROR; } - if (ConfigureEntry(interp, entryPtr, objc-2, objv+2, 0) != TCL_OK) { + if (ConfigureEntry(interp, entryPtr, objc-2, objv+2) != TCL_OK) { goto error; } @@ -3712,12 +3767,12 @@ SpinboxWidgetObjCmd( } Tcl_SetObjResult(interp, objPtr); } else { - result = ConfigureEntry(interp, entryPtr, objc-2, objv+2, 0); + result = ConfigureEntry(interp, entryPtr, objc-2, objv+2); } break; case SB_CMD_DELETE: { - int first, last; + int first, last, code; if ((objc < 3) || (objc > 4)) { Tcl_WrongNumArgs(interp, 2, objv, "firstIndex ?lastIndex?"); @@ -3736,7 +3791,10 @@ SpinboxWidgetObjCmd( } } if ((last >= first) && (entryPtr->state == STATE_NORMAL)) { - DeleteChars(entryPtr, first, last - first); + code = DeleteChars(entryPtr, first, last - first); + if (code != TCL_OK) { + goto error; + } } break; } @@ -3796,7 +3854,7 @@ SpinboxWidgetObjCmd( } case SB_CMD_INSERT: { - int index; + int index, code; if (objc != 4) { Tcl_WrongNumArgs(interp, 2, objv, "index text"); @@ -3807,7 +3865,10 @@ SpinboxWidgetObjCmd( goto error; } if (entryPtr->state == STATE_NORMAL) { - InsertChars(entryPtr, index, Tcl_GetString(objv[3])); + code = InsertChars(entryPtr, index, Tcl_GetString(objv[3])); + if (code != TCL_OK) { + goto error; + } } break; } @@ -4017,16 +4078,22 @@ SpinboxWidgetObjCmd( break; } - case SB_CMD_SET: + case SB_CMD_SET: { + int code = TCL_OK; + if (objc > 3) { Tcl_WrongNumArgs(interp, 2, objv, "?string?"); goto error; } if (objc == 3) { - EntryValueChanged(entryPtr, Tcl_GetString(objv[2])); + code = EntryValueChanged(entryPtr, Tcl_GetString(objv[2])); + if (code != TCL_OK) { + goto error; + } } Tcl_SetObjResult(interp, Tcl_NewStringObj(entryPtr->string, -1)); break; + } case SB_CMD_VALIDATE: { int code; @@ -4167,7 +4234,7 @@ GetSpinboxElement( * TCL_OK. * * Side effects: - * An background error condition may arise when invoking the callback. + * A background error condition may arise when invoking the callback. * The widget value may change. * *-------------------------------------------------------------- @@ -4198,6 +4265,7 @@ SpinboxInvoke( return TCL_OK; } + code = TCL_OK; if (fabs(sbPtr->increment) > MIN_DBL_VAL) { if (sbPtr->listObj != NULL) { Tcl_Obj *objPtr; @@ -4243,11 +4311,11 @@ SpinboxInvoke( } } Tcl_ListObjIndex(interp, sbPtr->listObj, sbPtr->eIndex, &objPtr); - EntryValueChanged(entryPtr, Tcl_GetString(objPtr)); + code = EntryValueChanged(entryPtr, Tcl_GetString(objPtr)); } else if (!DOUBLES_EQ(sbPtr->fromValue, sbPtr->toValue)) { double dvalue; - if (sscanf(entryPtr->string, "%lf", &dvalue) == 0) { + if (sscanf(entryPtr->string, "%lf", &dvalue) <= 0) { /* * If the string doesn't scan as a double value, just * use the -from value @@ -4290,9 +4358,12 @@ SpinboxInvoke( } } sprintf(sbPtr->formatBuf, sbPtr->valueFormat, dvalue); - EntryValueChanged(entryPtr, sbPtr->formatBuf); + code = EntryValueChanged(entryPtr, sbPtr->formatBuf); } } + if (code != TCL_OK) { + return TCL_ERROR; + } if (sbPtr->command != NULL) { Tcl_DStringInit(&script); diff --git a/generic/tkEvent.c b/generic/tkEvent.c index 463379a..95aeda1 100644 --- a/generic/tkEvent.c +++ b/generic/tkEvent.c @@ -356,7 +356,7 @@ CreateXIC( /* XCreateIC failed. */ return; } - + /* * Adjust the window's event mask if the IM requires it. */ @@ -2039,6 +2039,12 @@ TkFinalize( { ExitHandler *exitPtr; +#if defined(_WIN32) && !defined(STATIC_BUILD) + if (!tclStubsPtr) { + return; + } +#endif + Tcl_DeleteExitHandler(TkFinalize, NULL); Tcl_MutexLock(&exitMutex); @@ -2065,7 +2071,7 @@ TkFinalize( * TkFinalizeThread -- * * Runs our private thread exit handlers and removes itself from Tcl. - * This is benificial should we want to protect from dangling pointers + * This is beneficial should we want to protect from dangling pointers * should the Tk shared library be unloaded prior to Tcl which can happen * on Windows should the process be forcefully exiting from an exception * handler. diff --git a/generic/tkFocus.c b/generic/tkFocus.c index cfd2216..60f631d 100644 --- a/generic/tkFocus.c +++ b/generic/tkFocus.c @@ -162,8 +162,8 @@ Tk_FocusObjCmd( * We have a subcommand to parse and act upon. */ - if (Tcl_GetIndexFromObj(interp, objv[1], focusOptions, "option", 0, - &index) != TCL_OK) { + if (Tcl_GetIndexFromObjStruct(interp, objv[1], focusOptions, + sizeof(char *), "option", 0, &index) != TCL_OK) { return TCL_ERROR; } if (objc != 3) { diff --git a/generic/tkFont.c b/generic/tkFont.c index 4485df8..102fc6e 100644 --- a/generic/tkFont.c +++ b/generic/tkFont.c @@ -421,7 +421,7 @@ TkFontPkgFree( fontsLeft++; #ifdef DEBUG_FONTS fprintf(stderr, "Font %s still in cache.\n", - Tcl_GetHashKey(&fiPtr->fontCache, searchPtr)); + (char *) Tcl_GetHashKey(&fiPtr->fontCache, searchPtr)); #endif } @@ -600,40 +600,40 @@ Tk_FontObjCmd( return result; } case FONT_CONFIGURE: { - int result; - const char *string; - Tcl_Obj *objPtr; - NamedFont *nfPtr; - Tcl_HashEntry *namedHashPtr; - - if (objc < 3) { - Tcl_WrongNumArgs(interp, 2, objv, "fontname ?-option value ...?"); - return TCL_ERROR; - } - string = Tcl_GetString(objv[2]); - namedHashPtr = Tcl_FindHashEntry(&fiPtr->namedTable, string); + int result; + const char *string; + Tcl_Obj *objPtr; + NamedFont *nfPtr; + Tcl_HashEntry *namedHashPtr; + + if (objc < 3) { + Tcl_WrongNumArgs(interp, 2, objv, "fontname ?-option value ...?"); + return TCL_ERROR; + } + string = Tcl_GetString(objv[2]); + namedHashPtr = Tcl_FindHashEntry(&fiPtr->namedTable, string); nfPtr = NULL; /* lint. */ - if (namedHashPtr != NULL) { - nfPtr = Tcl_GetHashValue(namedHashPtr); - } - if ((namedHashPtr == NULL) || nfPtr->deletePending) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "named font \"%s\" doesn't exist", string)); - Tcl_SetErrorCode(interp, "TK", "LOOKUP", "FONT", string, NULL); - return TCL_ERROR; - } - if (objc == 3) { - objPtr = NULL; - } else if (objc == 4) { - objPtr = objv[3]; - } else { - result = ConfigAttributesObj(interp, tkwin, objc - 3, objv + 3, - &nfPtr->fa); - UpdateDependentFonts(fiPtr, tkwin, namedHashPtr); - return result; - } - return GetAttributeInfoObj(interp, &nfPtr->fa, objPtr); - } + if (namedHashPtr != NULL) { + nfPtr = Tcl_GetHashValue(namedHashPtr); + } + if ((namedHashPtr == NULL) || nfPtr->deletePending) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "named font \"%s\" doesn't exist", string)); + Tcl_SetErrorCode(interp, "TK", "LOOKUP", "FONT", string, NULL); + return TCL_ERROR; + } + if (objc == 3) { + objPtr = NULL; + } else if (objc == 4) { + objPtr = objv[3]; + } else { + result = ConfigAttributesObj(interp, tkwin, objc - 3, objv + 3, + &nfPtr->fa); + UpdateDependentFonts(fiPtr, tkwin, namedHashPtr); + return result; + } + return GetAttributeInfoObj(interp, &nfPtr->fa, objPtr); + } case FONT_CREATE: { int skip = 3, i; const char *name; @@ -1093,7 +1093,8 @@ Tk_AllocFontFromObj( int isNew, descent; NamedFont *nfPtr; - if (objPtr->typePtr != &tkFontObjType) { + if (objPtr->typePtr != &tkFontObjType + || objPtr->internalRep.twoPtrValue.ptr2 != fiPtr) { SetFontFromAny(interp, objPtr); } @@ -1133,6 +1134,7 @@ Tk_AllocFontFromObj( fontPtr->resourceRefCount++; fontPtr->objRefCount++; objPtr->internalRep.twoPtrValue.ptr1 = fontPtr; + objPtr->internalRep.twoPtrValue.ptr2 = fiPtr; return (Tk_Font) fontPtr; } } @@ -1243,6 +1245,7 @@ Tk_AllocFontFromObj( } objPtr->internalRep.twoPtrValue.ptr1 = fontPtr; + objPtr->internalRep.twoPtrValue.ptr2 = fiPtr; return (Tk_Font) fontPtr; } @@ -1275,7 +1278,8 @@ Tk_GetFontFromObj( TkFont *fontPtr; Tcl_HashEntry *hashPtr; - if (objPtr->typePtr != &tkFontObjType) { + if (objPtr->typePtr != &tkFontObjType + || objPtr->internalRep.twoPtrValue.ptr2 != fiPtr) { SetFontFromAny(NULL, objPtr); } @@ -1311,6 +1315,7 @@ Tk_GetFontFromObj( if (Tk_Screen(tkwin) == fontPtr->screen) { fontPtr->objRefCount++; objPtr->internalRep.twoPtrValue.ptr1 = fontPtr; + objPtr->internalRep.twoPtrValue.ptr2 = fiPtr; return (Tk_Font) fontPtr; } } @@ -1356,6 +1361,7 @@ SetFontFromAny( } objPtr->typePtr = &tkFontObjType; objPtr->internalRep.twoPtrValue.ptr1 = NULL; + objPtr->internalRep.twoPtrValue.ptr2 = NULL; return TCL_OK; } @@ -1517,8 +1523,9 @@ FreeFontObj( fontPtr->objRefCount--; if ((fontPtr->resourceRefCount == 0) && (fontPtr->objRefCount == 0)) { ckfree(fontPtr); - objPtr->internalRep.twoPtrValue.ptr1 = NULL; } + objPtr->internalRep.twoPtrValue.ptr1 = NULL; + objPtr->internalRep.twoPtrValue.ptr2 = NULL; } } @@ -1549,6 +1556,8 @@ DupFontObjProc( dupObjPtr->typePtr = srcObjPtr->typePtr; dupObjPtr->internalRep.twoPtrValue.ptr1 = fontPtr; + dupObjPtr->internalRep.twoPtrValue.ptr2 + = srcObjPtr->internalRep.twoPtrValue.ptr2; if (fontPtr != NULL) { fontPtr->objRefCount++; @@ -2058,14 +2067,14 @@ Tk_ComputeTextLayout( NewChunk(&layoutPtr, &maxChunks, start, 1, curX, newX, baseline)->numDisplayChars = -1; start++; + curX = newX; + flags &= ~TK_AT_LEAST_ONE; if ((start < end) && ((wrapLength <= 0) || (newX <= wrapLength))) { /* * More chars can still fit on this line. */ - curX = newX; - flags &= ~TK_AT_LEAST_ONE; continue; } } else { @@ -2985,13 +2994,6 @@ PointInQuadrilateral( } static inline int -sign( - double value) -{ - return (value < 0.0) ? -1 : (value > 0.0) ? 1 : 0; -} - -static inline int SidesIntersect( double ax1, double ay1, double ax2, double ay2, double bx1, double by1, double bx2, double by2) @@ -3366,7 +3368,6 @@ ConfigAttributesObj( for (i = 0; i < objc; i += 2) { optionPtr = objv[i]; - valuePtr = objv[i + 1]; if (Tcl_GetIndexFromObj(interp, optionPtr, fontOpt, "option", 1, &index) != TCL_OK) { @@ -3387,6 +3388,7 @@ ConfigAttributesObj( } return TCL_ERROR; } + valuePtr = objv[i + 1]; switch (index) { case FONT_FAMILY: diff --git a/generic/tkFrame.c b/generic/tkFrame.c index 8bc44ce..057b4b8 100644 --- a/generic/tkFrame.c +++ b/generic/tkFrame.c @@ -308,7 +308,7 @@ static int ConfigureFrame(Tcl_Interp *interp, Frame *framePtr, static int CreateFrame(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const argv[], enum FrameType type, const char *appName); -static void DestroyFrame(char *memPtr); +static void DestroyFrame(void *memPtr); static void DestroyFramePartly(Frame *framePtr); static void DisplayFrame(ClientData clientData); static void FrameCmdDeletedProc(ClientData clientData); @@ -727,8 +727,8 @@ FrameWidgetObjCmd( Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?"); return TCL_ERROR; } - if (Tcl_GetIndexFromObj(interp, objv[1], frameOptions, "option", 0, - &index) != TCL_OK) { + if (Tcl_GetIndexFromObjStruct(interp, objv[1], frameOptions, + sizeof(char *), "option", 0, &index) != TCL_OK) { return TCL_ERROR; } Tcl_Preserve(framePtr); @@ -834,10 +834,10 @@ FrameWidgetObjCmd( static void DestroyFrame( - char *memPtr) /* Info about frame widget. */ + void *memPtr) /* Info about frame widget. */ { - register Frame *framePtr = (Frame *) memPtr; - register Labelframe *labelframePtr = (Labelframe *) memPtr; + register Frame *framePtr = memPtr; + register Labelframe *labelframePtr = memPtr; if (framePtr->type == TYPE_LABELFRAME) { Tk_FreeTextLayout(labelframePtr->textLayout); @@ -1656,7 +1656,7 @@ FrameEventProc( Tcl_CancelIdleCall(DisplayFrame, framePtr); } Tcl_CancelIdleCall(MapFrame, framePtr); - Tcl_EventuallyFree(framePtr, DestroyFrame); + Tcl_EventuallyFree(framePtr, (Tcl_FreeProc *) DestroyFrame); } else if (eventPtr->type == FocusIn) { if (eventPtr->xfocus.detail != NotifyInferior) { framePtr->flags |= GOT_FOCUS; diff --git a/generic/tkGrab.c b/generic/tkGrab.c index 2df5552..00d4511 100644 --- a/generic/tkGrab.c +++ b/generic/tkGrab.c @@ -12,9 +12,9 @@ #include "tkInt.h" -#ifdef __WIN32__ +#ifdef _WIN32 #include "tkWinInt.h" -#elif !(defined(__WIN32__) || defined(MAC_OSX_TK)) +#elif !defined(MAC_OSX_TK) #include "tkUnixInt.h" #endif diff --git a/generic/tkGrid.c b/generic/tkGrid.c index 19e4442..2a88b76 100644 --- a/generic/tkGrid.c +++ b/generic/tkGrid.c @@ -242,7 +242,7 @@ typedef struct UniformGroup { * Tk will set its requested size to fit the * needs of its slaves. * ALLOCED_MASTER 1 means that Grid has allocated itself as - * geometry master for this window. + * geometry master for this window. */ #define REQUESTED_RELAYOUT 1 @@ -262,7 +262,7 @@ static int CheckSlotData(Gridder *masterPtr, int slot, int slotType, int checkOnly); static int ConfigureSlaves(Tcl_Interp *interp, Tk_Window tkwin, int objc, Tcl_Obj *const objv[]); -static void DestroyGrid(char *memPtr); +static void DestroyGrid(void *memPtr); static Gridder * GetGrid(Tk_Window tkwin); static int GridAnchorCommand(Tk_Window tkwin, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); @@ -361,8 +361,8 @@ Tk_GridObjCmd( return TCL_ERROR; } - if (Tcl_GetIndexFromObj(interp, objv[1], optionStrings, "option", 0, - &index) != TCL_OK) { + if (Tcl_GetIndexFromObjStruct(interp, objv[1], optionStrings, + sizeof(char *), "option", 0, &index) != TCL_OK) { return TCL_ERROR; } @@ -910,7 +910,7 @@ GridPropagateCommand( if (masterPtr->slavePtr != NULL) { if (TkSetGeometryMaster(interp, master, "grid") != TCL_OK) { - return TCL_ERROR; + return TCL_ERROR; } masterPtr->flags |= ALLOCED_MASTER; } @@ -1076,8 +1076,8 @@ GridRowColumnConfigureCommand( * returned. */ - if (Tcl_GetIndexFromObj(interp, objv[4], optionStrings, "option", 0, - &index) != TCL_OK) { + if (Tcl_GetIndexFromObjStruct(interp, objv[4], optionStrings, + sizeof(char *), "option", 0, &index) != TCL_OK) { Tcl_DecrRefCount(listCopy); return TCL_ERROR; } @@ -1175,8 +1175,8 @@ GridRowColumnConfigureCommand( */ for (i = 4; i < objc; i += 2) { - if (Tcl_GetIndexFromObj(interp, objv[i], optionStrings, - "option", 0, &index) != TCL_OK) { + if (Tcl_GetIndexFromObjStruct(interp, objv[i], optionStrings, + sizeof(char *), "option", 0, &index) != TCL_OK) { Tcl_DecrRefCount(listCopy); return TCL_ERROR; } @@ -1364,8 +1364,8 @@ GridSlavesCommand( } for (i = 3; i < objc; i += 2) { - if (Tcl_GetIndexFromObj(interp, objv[i], optionStrings, "option", 0, - &index) != TCL_OK) { + if (Tcl_GetIndexFromObjStruct(interp, objv[i], optionStrings, + sizeof(char *), "option", 0, &index) != TCL_OK) { return TCL_ERROR; } if (Tcl_GetIntFromObj(interp, objv[i+1], &value) != TCL_OK) { @@ -2018,7 +2018,7 @@ ResolveConstraints( if (slavePtr->numCols > 1) { slavePtr->binNextPtr = layoutPtr[rightEdge].binNextPtr; layoutPtr[rightEdge].binNextPtr = slavePtr; - } else { + } else if (rightEdge >= 0) { int size = slavePtr->size + layoutPtr[rightEdge].pad; if (size > layoutPtr[rightEdge].minSize) { @@ -2037,7 +2037,7 @@ ResolveConstraints( if (slavePtr->numRows > 1) { slavePtr->binNextPtr = layoutPtr[rightEdge].binNextPtr; layoutPtr[rightEdge].binNextPtr = slavePtr; - } else { + } else if (rightEdge >= 0) { int size = slavePtr->size + layoutPtr[rightEdge].pad; if (size > layoutPtr[rightEdge].minSize) { @@ -2807,9 +2807,9 @@ Unlink( static void DestroyGrid( - char *memPtr) /* Info about window that is now dead. */ + void *memPtr) /* Info about window that is now dead. */ { - register Gridder *gridPtr = (Gridder *) memPtr; + register Gridder *gridPtr = memPtr; if (gridPtr->masterDataPtr != NULL) { if (gridPtr->masterDataPtr->rowPtr != NULL) { @@ -2886,7 +2886,7 @@ GridStructureProc( Tcl_CancelIdleCall(ArrangeGrid, gridPtr); } gridPtr->tkwin = NULL; - Tcl_EventuallyFree(gridPtr, DestroyGrid); + Tcl_EventuallyFree(gridPtr, (Tcl_FreeProc *)DestroyGrid); } else if (eventPtr->type == MapNotify) { if ((gridPtr->slavePtr != NULL) && !(gridPtr->flags & REQUESTED_RELAYOUT)) { @@ -3058,8 +3058,8 @@ ConfigureSlaves( */ for (i = numWindows; i < objc; i += 2) { - if (Tcl_GetIndexFromObj(interp, objv[i], optionStrings, "option", 0, - &index) != TCL_OK) { + if (Tcl_GetIndexFromObjStruct(interp, objv[i], optionStrings, + sizeof(char *), "option", 0, &index) != TCL_OK) { return TCL_ERROR; } if (index == CONF_IN) { @@ -3161,8 +3161,8 @@ ConfigureSlaves( */ for (i = numWindows; i < objc; i += 2) { - Tcl_GetIndexFromObj(interp, objv[i], optionStrings, "option", 0, - &index); + Tcl_GetIndexFromObjStruct(interp, objv[i], optionStrings, + sizeof(char *), "option", 0, &index); switch ((enum options) index) { case CONF_COLUMN: if (Tcl_GetIntFromObj(NULL, objv[i+1], &tmp) != TCL_OK diff --git a/generic/tkImage.c b/generic/tkImage.c index ffa6f22..359d6c6 100644 --- a/generic/tkImage.c +++ b/generic/tkImage.c @@ -234,8 +234,8 @@ Tk_ImageObjCmd( return TCL_ERROR; } - if (Tcl_GetIndexFromObj(interp, objv[1], imageOptions, "option", 0, - &index) != TCL_OK) { + if (Tcl_GetIndexFromObjStruct(interp, objv[1], imageOptions, + sizeof(char *), "option", 0, &index) != TCL_OK) { return TCL_ERROR; } switch ((enum options) index) { @@ -283,13 +283,11 @@ Tk_ImageObjCmd( */ if ((objc == 3) || (*(arg = Tcl_GetString(objv[3])) == '-')) { - Tcl_CmdInfo dummy; - do { dispPtr->imageId++; sprintf(idString, "image%d", dispPtr->imageId); name = idString; - } while (Tcl_GetCommandInfo(interp, name, &dummy) != 0); + } while (Tcl_FindCommand(interp, name, NULL, 0) != NULL); firstOption = 3; } else { TkWindow *topWin; diff --git a/generic/tkImgBmap.c b/generic/tkImgBmap.c index cdd57dd..0906673 100644 --- a/generic/tkImgBmap.c +++ b/generic/tkImgBmap.c @@ -330,7 +330,7 @@ ImgBmapConfigureMaster( * None. * * Side effects: - * Generates errors via Tcl_BackgroundError if there are problems in + * Generates errors via Tcl_BackgroundException if there are problems in * setting up the instance. * *---------------------------------------------------------------------- @@ -448,7 +448,7 @@ ImgBmapConfigureInstance( Tcl_AppendObjToErrorInfo(masterPtr->interp, Tcl_ObjPrintf( "\n (while configuring image \"%s\")", Tk_NameOfImage( masterPtr->tkMaster))); - Tcl_BackgroundError(masterPtr->interp); + Tcl_BackgroundException(masterPtr->interp, TCL_ERROR); } /* @@ -764,8 +764,8 @@ ImgBmapCmd( Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?"); return TCL_ERROR; } - if (Tcl_GetIndexFromObj(interp, objv[1], bmapOptions, "option", 0, - &index) != TCL_OK) { + if (Tcl_GetIndexFromObjStruct(interp, objv[1], bmapOptions, + sizeof(char *), "option", 0, &index) != TCL_OK) { return TCL_ERROR; } switch (index) { diff --git a/generic/tkImgGIF.c b/generic/tkImgGIF.c index fed4da4..1c28b54 100644 --- a/generic/tkImgGIF.c +++ b/generic/tkImgGIF.c @@ -393,7 +393,8 @@ FileReadGIF( * image being read. */ { int fileWidth, fileHeight, imageWidth, imageHeight; - int nBytes, index = 0, argc = 0, i, result = TCL_ERROR; + unsigned int nBytes; + int index = 0, argc = 0, i, result = TCL_ERROR; Tcl_Obj **objv; unsigned char buf[100]; unsigned char *trashBuffer = NULL; @@ -410,6 +411,7 @@ FileReadGIF( * source and not a file. */ + memset(colorMap, 0, MAXCOLORMAPSIZE*4); memset(gifConfPtr, 0, sizeof(GIFImageConfig)); if (fileName == INLINE_DATA_BINARY || fileName == INLINE_DATA_BASE64) { gifConfPtr->fromData = fileName; @@ -425,8 +427,9 @@ FileReadGIF( return TCL_ERROR; } for (i = 1; i < argc; i++) { - if (Tcl_GetIndexFromObj(interp, objv[i], optionStrings, "option name", - 0, &nBytes) != TCL_OK) { + int optionIdx; + if (Tcl_GetIndexFromObjStruct(interp, objv[i], optionStrings, + sizeof(char *), "option name", 0, &optionIdx) != TCL_OK) { return TCL_ERROR; } if (i == (argc-1)) { @@ -590,8 +593,14 @@ FileReadGIF( */ if (trashBuffer == NULL) { + if (fileWidth > (int)((UINT_MAX/3)/fileHeight)) { + goto error; + } nBytes = fileWidth * fileHeight * 3; trashBuffer = ckalloc(nBytes); + if (trashBuffer) { + memset(trashBuffer, 0, nBytes); + } } /* @@ -675,9 +684,18 @@ FileReadGIF( block.offset[1] = 1; block.offset[2] = 2; block.offset[3] = (transparent>=0) ? 3 : 0; + if (imageWidth > INT_MAX/block.pixelSize) { + goto error; + } block.pitch = block.pixelSize * imageWidth; + if (imageHeight > (int)(UINT_MAX/block.pitch)) { + goto error; + } nBytes = block.pitch * imageHeight; block.pixelPtr = ckalloc(nBytes); + if (block.pixelPtr) { + memset(block.pixelPtr, 0, nBytes); + } if (ReadImage(gifConfPtr, interp, block.pixelPtr, chan, imageWidth, imageHeight, colorMap, srcX, srcY, BitSet(buf[8], INTERLACE), diff --git a/generic/tkImgPNG.c b/generic/tkImgPNG.c index b159c45..2ee515b 100644 --- a/generic/tkImgPNG.c +++ b/generic/tkImgPNG.c @@ -10,6 +10,7 @@ * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ +#include "assert.h" #include "tkInt.h" #define PNG_INT32(a,b,c,d) \ @@ -334,9 +335,11 @@ InitPNGImage( if (Tcl_ZlibStreamInit(NULL, dir, TCL_ZLIB_FORMAT_ZLIB, TCL_ZLIB_COMPRESS_DEFAULT, NULL, &pngPtr->stream) != TCL_OK) { - Tcl_SetObjResult(interp, Tcl_NewStringObj( - "zlib initialization failed", -1)); - Tcl_SetErrorCode(interp, "TK", "IMAGE", "PNG", "ZLIB_INIT", NULL); + if (interp) { + Tcl_SetObjResult(interp, Tcl_NewStringObj( + "zlib initialization failed", -1)); + Tcl_SetErrorCode(interp, "TK", "IMAGE", "PNG", "ZLIB_INIT", NULL); + } if (objPtr) { Tcl_DecrRefCount(objPtr); } @@ -799,7 +802,7 @@ SkipChunk( /* * 4.3. Summary of standard chunks * - * This table summarizes some properties of the standard chunk types. + * This table summarizes some properties of the standard chunk types. * * Critical chunks (must appear in this order, except PLTE is optional): * @@ -1844,6 +1847,13 @@ DecodeLine( if (UnfilterLine(interp, pngPtr) == TCL_ERROR) { return TCL_ERROR; } + if (pngPtr->currentLine >= pngPtr->block.height) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "PNG image data overflow")); + Tcl_SetErrorCode(interp, "TK", "IMAGE", "PNG", "DATA_OVERFLOW", NULL); + return TCL_ERROR; + } + if (pngPtr->interlace) { switch (pngPtr->phase) { @@ -2173,10 +2183,13 @@ ReadIDAT( /* * Try to read another line of pixels out of the buffer - * immediately. + * immediately, but don't allow write past end of block. */ - goto getNextLine; + if (pngPtr->currentLine < pngPtr->block.height) { + goto getNextLine; + } + } /* @@ -2281,10 +2294,10 @@ ParseFormat( Tcl_Obj **objv = NULL; int objc = 0; static const char *const fmtOptions[] = { - "png", "-alpha", NULL + "-alpha", NULL }; enum fmtOptions { - OPT_PNG, OPT_ALPHA + OPT_ALPHA }; /* @@ -2297,33 +2310,30 @@ ParseFormat( } for (; objc>0 ; objc--, objv++) { - int optIndex; - - if (Tcl_GetIndexFromObj(interp, objv[0], fmtOptions, "option", 0, - &optIndex) == TCL_ERROR) { - return TCL_ERROR; - } + int optIndex; /* * Ignore the "png" part of the format specification. */ - if (OPT_PNG == optIndex) { + if (!strcasecmp(Tcl_GetString(objv[0]), "png")) { continue; } - if (objc < 2) { + if (Tcl_GetIndexFromObjStruct(interp, objv[0], fmtOptions, + sizeof(char *), "option", 0, &optIndex) == TCL_ERROR) { + return TCL_ERROR; + } + + if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "value"); return TCL_ERROR; - } + } objc--; objv++; switch ((enum fmtOptions) optIndex) { - case OPT_PNG: - break; - case OPT_ALPHA: if (Tcl_GetDoubleFromObj(interp, objv[0], &pngPtr->alpha) == TCL_ERROR) { @@ -2667,11 +2677,8 @@ FileMatchPNG( { PNGImage png; int match = 0; - Tcl_SavedResult sya; - - Tcl_SaveResult(interp, &sya); - InitPNGImage(interp, &png, chan, NULL, TCL_ZLIB_STREAM_INFLATE); + InitPNGImage(NULL, &png, chan, NULL, TCL_ZLIB_STREAM_INFLATE); if (ReadIHDR(interp, &png) == TCL_OK) { *widthPtr = png.block.width; @@ -2680,7 +2687,6 @@ FileMatchPNG( } CleanupPNGImage(&png); - Tcl_RestoreResult(interp, &sya); return match; } @@ -2759,10 +2765,8 @@ StringMatchPNG( { PNGImage png; int match = 0; - Tcl_SavedResult sya; - Tcl_SaveResult(interp, &sya); - InitPNGImage(interp, &png, NULL, pObjData, TCL_ZLIB_STREAM_INFLATE); + InitPNGImage(NULL, &png, NULL, pObjData, TCL_ZLIB_STREAM_INFLATE); png.strDataBuf = Tcl_GetByteArrayFromObj(pObjData, &png.strDataLen); @@ -2773,7 +2777,6 @@ StringMatchPNG( } CleanupPNGImage(&png); - Tcl_RestoreResult(interp, &sya); return match; } @@ -3163,7 +3166,7 @@ WriteIDAT( *destPtr++ = srcPtr[blockPtr->offset[0]]; - /* + /* * If not grayscale, copy the green and blue channels. */ @@ -3353,7 +3356,7 @@ EncodePNG( pngPtr->colorType = PNG_COLOR_RGBA; pngPtr->bytesPerPixel = 4; } else { - pngPtr->colorType = PNG_COLOR_RGBA; + pngPtr->colorType = PNG_COLOR_RGB; pngPtr->bytesPerPixel = 3; } } else { diff --git a/generic/tkImgPPM.c b/generic/tkImgPPM.c index edd1b71..6f084f0 100644 --- a/generic/tkImgPPM.c +++ b/generic/tkImgPPM.c @@ -141,7 +141,7 @@ FileReadPPM( * image being read. */ { int fileWidth, fileHeight, maxIntensity; - int nLines, nBytes, h, type, count; + int nLines, nBytes, h, type, count, bytesPerChannel = 1; unsigned char *pixelPtr; Tk_PhotoImageBlock block; @@ -158,12 +158,14 @@ FileReadPPM( Tcl_SetErrorCode(interp, "TK", "IMAGE", "PPM", "DIMENSIONS", NULL); return TCL_ERROR; } - if ((maxIntensity <= 0) || (maxIntensity >= 256)) { + if ((maxIntensity <= 0) || (maxIntensity > 0xffff)) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "PPM image file \"%s\" has bad maximum intensity value %d", fileName, maxIntensity)); Tcl_SetErrorCode(interp, "TK", "IMAGE", "PPM", "INTENSITY", NULL); return TCL_ERROR; + } else if (maxIntensity > 0x00ff) { + bytesPerChannel = 2; } if ((srcX + width) > fileWidth) { @@ -173,20 +175,20 @@ FileReadPPM( height = fileHeight - srcY; } if ((width <= 0) || (height <= 0) - || (srcX >= fileWidth) || (srcY >= fileHeight)) { + || (srcX >= fileWidth) || (srcY >= fileHeight)) { return TCL_OK; } if (type == PGM) { - block.pixelSize = 1; + block.pixelSize = 1 * bytesPerChannel; block.offset[0] = 0; block.offset[1] = 0; block.offset[2] = 0; } else { - block.pixelSize = 3; + block.pixelSize = 3 * bytesPerChannel; block.offset[0] = 0; - block.offset[1] = 1; - block.offset[2] = 2; + block.offset[1] = 1 * bytesPerChannel; + block.offset[2] = 2 * bytesPerChannel; } block.offset[3] = 0; block.width = width; @@ -228,12 +230,21 @@ FileReadPPM( ckfree(pixelPtr); return TCL_ERROR; } - if (maxIntensity != 255) { + if (maxIntensity < 0x00ff) { unsigned char *p; for (p = pixelPtr; count > 0; count--, p++) { *p = (((int) *p) * 255)/maxIntensity; } + } else if (maxIntensity > 0x00ff) { + unsigned char *p; + unsigned int value; + + for (p = pixelPtr; count > 0; count--, p += 2) { + value = ((unsigned int) p[0]) * 256 + ((unsigned int) p[1]); + value = value * 255 / maxIntensity; + p[0] = p[1] = (unsigned char) value; + } } block.height = nLines; if (Tk_PhotoPutBlock(interp, imageHandle, &block, destX, destY, @@ -478,7 +489,7 @@ StringReadPPM( * image being read. */ { int fileWidth, fileHeight, maxIntensity; - int nLines, nBytes, h, type, count, dataSize; + int nLines, nBytes, h, type, count, dataSize, bytesPerChannel = 1; unsigned char *pixelPtr, *dataBuffer; Tk_PhotoImageBlock block; @@ -496,12 +507,14 @@ StringReadPPM( Tcl_SetErrorCode(interp, "TK", "IMAGE", "PPM", "DIMENSIONS", NULL); return TCL_ERROR; } - if ((maxIntensity <= 0) || (maxIntensity >= 256)) { + if ((maxIntensity <= 0) || (maxIntensity > 0xffff)) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "PPM image data has bad maximum intensity value %d", maxIntensity)); Tcl_SetErrorCode(interp, "TK", "IMAGE", "PPM", "INTENSITY", NULL); return TCL_ERROR; + } else if (maxIntensity > 0x00ff) { + bytesPerChannel = 2; } if ((srcX + width) > fileWidth) { @@ -516,15 +529,15 @@ StringReadPPM( } if (type == PGM) { - block.pixelSize = 1; + block.pixelSize = 1 * bytesPerChannel; block.offset[0] = 0; block.offset[1] = 0; block.offset[2] = 0; } else { - block.pixelSize = 3; + block.pixelSize = 3 * bytesPerChannel; block.offset[0] = 0; - block.offset[1] = 1; - block.offset[2] = 2; + block.offset[1] = 1 * bytesPerChannel; + block.offset[2] = 2 * bytesPerChannel; } block.offset[3] = 0; block.width = width; @@ -535,7 +548,7 @@ StringReadPPM( dataSize -= srcY * block.pitch; } - if (maxIntensity == 255) { + if (maxIntensity == 0x00ff) { /* * We have all the data in memory, so write everything in one go. */ @@ -582,8 +595,19 @@ StringReadPPM( Tcl_SetErrorCode(interp, "TK", "IMAGE", "PPM", "TRUNCATED", NULL); return TCL_ERROR; } - for (p=pixelPtr,count=nBytes ; count>0 ; count--,p++,dataBuffer++) { - *p = (((int) *dataBuffer) * 255)/maxIntensity; + if (maxIntensity < 0x00ff) { + for (p=pixelPtr,count=nBytes ; count>0 ; count--,p++,dataBuffer++) { + *p = (((int) *dataBuffer) * 255)/maxIntensity; + } + } else { + unsigned char *p; + unsigned int value; + + for (p = pixelPtr,count=nBytes; count > 1; count-=2, p += 2) { + value = ((unsigned int) p[0]) * 256 + ((unsigned int) p[1]); + value = value * 255 / maxIntensity; + p[0] = p[1] = (unsigned char) value; + } } dataSize -= nBytes; block.height = nLines; diff --git a/generic/tkImgPhInstance.c b/generic/tkImgPhInstance.c index 3097489..666a9b0 100644 --- a/generic/tkImgPhInstance.c +++ b/generic/tkImgPhInstance.c @@ -64,7 +64,7 @@ static int imgPhotoColorHashInitialized; * None. * * Side effects: - * Generates errors via Tcl_BackgroundError if there are problems in + * Generates errors via Tcl_BackgroundException if there are problems in * setting up the instance. * *---------------------------------------------------------------------- @@ -407,7 +407,7 @@ TkImgPhotoGet( *---------------------------------------------------------------------- */ -#ifndef __WIN32__ +#ifndef _WIN32 #define GetRValue(rgb) (UCHAR(((rgb) & red_mask) >> red_shift)) #define GetGValue(rgb) (UCHAR(((rgb) & green_mask) >> green_shift)) #define GetBValue(rgb) (UCHAR(((rgb) & blue_mask) >> blue_shift)) @@ -419,7 +419,7 @@ TkImgPhotoGet( (((r) * red_mask / 255) & red_mask) | \ (((g) * green_mask / 255) & green_mask) | \ (((b) * blue_mask / 255) & blue_mask) )) -#endif /* !__WIN32__ */ +#endif /* !_WIN32 */ static void BlendComplexAlpha( @@ -453,7 +453,7 @@ BlendComplexAlpha( * might be cached for better performance. */ -#ifndef __WIN32__ +#ifndef _WIN32 unsigned long red_mask, green_mask, blue_mask; unsigned long red_shift, green_shift, blue_shift; Visual *visual = iPtr->visualInfo.visual; @@ -473,7 +473,7 @@ BlendComplexAlpha( while ((0x0001 & (blue_mask >> blue_shift)) == 0) { blue_shift++; } -#endif /* !__WIN32__ */ +#endif /* !_WIN32 */ /* * Only UNIX requires the special case for <24bpp. It varies with 3 extra @@ -481,7 +481,7 @@ BlendComplexAlpha( * optimized. */ -#if !(defined(__WIN32__) || defined(MAC_OSX_TK)) +#if !(defined(_WIN32) || defined(MAC_OSX_TK)) if (bgImg->depth < 24) { unsigned char red_mlen, green_mlen, blue_mlen; @@ -529,7 +529,7 @@ BlendComplexAlpha( } return; } -#endif /* !__WIN32__ && !MAC_OSX_TK */ +#endif /* !_WIN32 && !MAC_OSX_TK */ for (y = 0; y < height; y++) { line = (y + yOffset) * iPtr->masterPtr->width; @@ -1336,12 +1336,12 @@ AllocateColors( * since we will be passing the color table into the TkPutImage call. */ -#ifndef __WIN32__ +#ifndef _WIN32 if ((colorPtr->visualInfo.class != DirectColor) && (colorPtr->visualInfo.class != TrueColor)) { colorPtr->flags |= MAP_COLORS; } -#endif /* __WIN32__ */ +#endif /* _WIN32 */ } colorPtr->numColors = numColors; @@ -1770,7 +1770,7 @@ TkImgDitherInstance( case NBBY: *destBytePtr++ = i; break; -#ifndef __WIN32__ +#ifndef _WIN32 /* * This case is not valid for Windows because the * image format is different from the pixel format in @@ -1832,7 +1832,7 @@ TkImgDitherInstance( case NBBY: *destBytePtr++ = i; break; -#ifndef __WIN32__ +#ifndef _WIN32 /* * This case is not valid for Windows because the * image format is different from the pixel format in diff --git a/generic/tkImgPhoto.c b/generic/tkImgPhoto.c index ce160a4..3e03f3d 100644 --- a/generic/tkImgPhoto.c +++ b/generic/tkImgPhoto.c @@ -230,7 +230,7 @@ PhotoFormatThreadExitProc( while (tsdPtr->formatList != NULL) { freePtr = tsdPtr->formatList; tsdPtr->formatList = tsdPtr->formatList->nextPtr; - ckfree(freePtr->name); + ckfree((char *)freePtr->name); ckfree(freePtr); } } @@ -886,6 +886,19 @@ ImgPhotoCmd( break; } dataWidth = listObjc; + /* + * Memory allocation overflow protection. + * May not be able to trigger/ demo / test this. + */ + + if (dataWidth > (int)((UINT_MAX/3) / dataHeight)) { + Tcl_SetObjResult(interp, Tcl_NewStringObj( + "photo image dimensions exceed Tcl memory limits", -1)); + Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO", + "OVERFLOW", NULL); + break; + } + pixelPtr = ckalloc(dataWidth * dataHeight * 3); block.pixelPtr = pixelPtr; } else if (listObjc != dataWidth) { @@ -2051,8 +2064,8 @@ static int ToggleComplexAlphaIfNeeded( PhotoMaster *mPtr) { - size_t len = MAX(mPtr->userWidth, mPtr->width) * - MAX(mPtr->userHeight, mPtr->height) * 4; + size_t len = (size_t)MAX(mPtr->userWidth, mPtr->width) * + (size_t)MAX(mPtr->userHeight, mPtr->height) * 4; unsigned char *c = mPtr->pix32; unsigned char *end = c + len; @@ -2062,6 +2075,9 @@ ToggleComplexAlphaIfNeeded( */ mPtr->flags &= ~COMPLEX_ALPHA; + if (c == NULL) { + return 0; + } c += 3; /* Start at first alpha byte. */ for (; c < end; c += 4) { if (*c && *c != 255) { @@ -2192,6 +2208,10 @@ ImgPhotoSetSize( height = masterPtr->userHeight; } + if (width > INT_MAX / 4) { + /* Pitch overflows int */ + return TCL_ERROR; + } pitch = width * 4; /* @@ -2201,11 +2221,12 @@ ImgPhotoSetSize( if ((width != masterPtr->width) || (height != masterPtr->height) || (masterPtr->pix32 == NULL)) { - /* - * Not a u-long, but should be one. - */ + unsigned newPixSize; - unsigned /*long*/ newPixSize = (unsigned /*long*/) (height * pitch); + if (pitch && height > (int)(UINT_MAX / pitch)) { + return TCL_ERROR; + } + newPixSize = height * pitch; /* * Some mallocs() really hate allocating zero bytes. [Bug 619544] @@ -2257,14 +2278,14 @@ ImgPhotoSetSize( if ((masterPtr->pix32 != NULL) && ((width == masterPtr->width) || (width == validBox.width))) { if (validBox.y > 0) { - memset(newPix32, 0, (size_t) (validBox.y * pitch)); + memset(newPix32, 0, ((size_t) validBox.y * pitch)); } h = validBox.y + validBox.height; if (h < height) { - memset(newPix32 + h*pitch, 0, (size_t) ((height - h) * pitch)); + memset(newPix32 + h*pitch, 0, ((size_t) (height - h) * pitch)); } } else { - memset(newPix32, 0, (size_t) (height * pitch)); + memset(newPix32, 0, ((size_t)height * pitch)); } if (masterPtr->pix32 != NULL) { @@ -2281,7 +2302,7 @@ ImgPhotoSetSize( offset = validBox.y * pitch; memcpy(newPix32 + offset, masterPtr->pix32 + offset, - (size_t) (validBox.height * pitch)); + ((size_t)validBox.height * pitch)); } else if ((validBox.width > 0) && (validBox.height > 0)) { /* @@ -2292,7 +2313,7 @@ ImgPhotoSetSize( srcPtr = masterPtr->pix32 + (validBox.y * masterPtr->width + validBox.x) * 4; for (h = validBox.height; h > 0; h--) { - memcpy(destPtr, srcPtr, (size_t) (validBox.width * 4)); + memcpy(destPtr, srcPtr, ((size_t)validBox.width * 4)); destPtr += width * 4; srcPtr += masterPtr->width * 4; } @@ -2772,7 +2793,7 @@ Tk_PhotoPutBlock( && (blockPtr->pitch == pitch))) && (compRule == TK_PHOTO_COMPOSITE_SET)) { memmove(destLinePtr, blockPtr->pixelPtr + blockPtr->offset[0], - (size_t) (height * width * 4)); + ((size_t)height * width * 4)); /* * We know there's an alpha offset and we're setting the data, so skip @@ -2804,7 +2825,7 @@ Tk_PhotoPutBlock( && (blueOffset == 2) && (alphaOffset == 3) && (width <= blockPtr->width) && compRuleSet) { - memcpy(destLinePtr, srcLinePtr, (size_t) (width * 4)); + memcpy(destLinePtr, srcLinePtr, ((size_t)width * 4)); srcLinePtr += blockPtr->pitch; destLinePtr += pitch; continue; @@ -3454,7 +3475,7 @@ Tk_PhotoBlank( */ memset(masterPtr->pix32, 0, - (size_t) (masterPtr->width * masterPtr->height * 4)); + ((size_t)masterPtr->width * masterPtr->height * 4)); for (instancePtr = masterPtr->instancePtr; instancePtr != NULL; instancePtr = instancePtr->nextPtr) { TkImgResetDither(instancePtr); @@ -3684,10 +3705,7 @@ ImgGetPhoto( } } if (!alphaOffset) { - blockPtr->pixelPtr--; - blockPtr->offset[0]++; - blockPtr->offset[1]++; - blockPtr->offset[2]++; + blockPtr->offset[3]= -1; /* Tell caller alpha need not be read */ } greenOffset = blockPtr->offset[1] - blockPtr->offset[0]; blueOffset = blockPtr->offset[2] - blockPtr->offset[0]; @@ -3702,6 +3720,10 @@ ImgGetPhoto( if ((greenOffset||blueOffset) && !(optPtr->options & OPT_GRAYSCALE)) { newPixelSize += 2; } + + if (blockPtr->height > (int)((UINT_MAX/newPixelSize)/blockPtr->width)) { + return NULL; + } data = attemptckalloc(newPixelSize*blockPtr->width*blockPtr->height); if (data == NULL) { return NULL; @@ -3803,9 +3825,11 @@ ImgGetPhoto( if (newPixelSize > 2) { blockPtr->offset[1] = 1; blockPtr->offset[2] = 2; + blockPtr->offset[3]= 3; } else { blockPtr->offset[1] = 0; blockPtr->offset[2] = 0; + blockPtr->offset[3]= 1; } return data; } @@ -3836,32 +3860,30 @@ ImgStringWrite( Tk_PhotoImageBlock *blockPtr) { int greenOffset, blueOffset; - Tcl_DString data; + Tcl_Obj *data; greenOffset = blockPtr->offset[1] - blockPtr->offset[0]; blueOffset = blockPtr->offset[2] - blockPtr->offset[0]; - Tcl_DStringInit(&data); + data = Tcl_NewObj(); if ((blockPtr->width > 0) && (blockPtr->height > 0)) { - char *line = ckalloc((8 * blockPtr->width) + 2); int row, col; for (row=0; row<blockPtr->height; row++) { + Tcl_Obj *line = Tcl_NewObj(); unsigned char *pixelPtr = blockPtr->pixelPtr + blockPtr->offset[0] + row * blockPtr->pitch; - char *linePtr = line; for (col=0; col<blockPtr->width; col++) { - sprintf(linePtr, " #%02x%02x%02x", *pixelPtr, + Tcl_AppendPrintfToObj(line, "%s#%02x%02x%02x", + col ? " " : "", *pixelPtr, pixelPtr[greenOffset], pixelPtr[blueOffset]); pixelPtr += blockPtr->pixelSize; - linePtr += 8; } - Tcl_DStringAppendElement(&data, line+1); + Tcl_ListObjAppendElement(NULL, data, line); } - ckfree(line); } - Tcl_DStringResult(interp, &data); + Tcl_SetObjResult(interp, data); return TCL_OK; } diff --git a/generic/tkImgPhoto.h b/generic/tkImgPhoto.h index 7bef76b..36bc6cb 100644 --- a/generic/tkImgPhoto.h +++ b/generic/tkImgPhoto.h @@ -17,7 +17,7 @@ */ #include "tkInt.h" -#ifdef __WIN32__ +#ifdef _WIN32 #include "tkWinInt.h" #elif defined(__CYGWIN__) #include "tkUnixInt.h" diff --git a/generic/tkInt.decls b/generic/tkInt.decls index 2ee9d1c..586b407 100644 --- a/generic/tkInt.decls +++ b/generic/tkInt.decls @@ -506,12 +506,12 @@ declare 154 { # entries needed only by tktest: declare 156 { - int TkpTestembedCmd(ClientData clientData, Tcl_Interp *interp, int argc, - const char **argv) + int TkpTestembedCmd(ClientData clientData, Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[]) } declare 157 { - int TkpTesttextCmd(ClientData dummy, Tcl_Interp *interp, int argc, - const char **argv) + int TkpTesttextCmd(ClientData dummy, Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[]) } declare 158 { int TkSelGetSelection(Tcl_Interp *interp, Tk_Window tkwin, @@ -684,8 +684,8 @@ declare 12 x11 { } # only needed by tktest: declare 13 x11 { - int TkpTestsendCmd(ClientData clientData, Tcl_Interp *interp, int argc, - const char **argv) + int TkpTestsendCmd(ClientData clientData, Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[]) } ################################ @@ -841,8 +841,8 @@ declare 44 win { } # only needed by tktest: declare 45 win { - int TkpTestsendCmd(ClientData clientData, Tcl_Interp *interp, int argc, - const char **argv) + int TkpTestsendCmd(ClientData clientData, Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[]) } ################################ @@ -1017,6 +1017,9 @@ declare 50 aqua { declare 51 aqua { void TkGenWMDestroyEvent(Tk_Window tkwin) } +declare 52 aqua { + void TkMacOSXSetDrawingEnabled(TkWindow *winPtr, int flag) +} # removed duplicate from tkPlat table (tk.decls) #declare 52 aqua { @@ -1032,6 +1035,9 @@ declare 53 aqua { declare 54 aqua { void *TkMacOSXDrawable(Drawable drawable) } +declare 55 aqua { + int TkpScanWindowId(Tcl_Interp *interp, const char *string, Window *idPtr) +} ############################################################################## diff --git a/generic/tkInt.h b/generic/tkInt.h index 21b882c..b644c5b 100644 --- a/generic/tkInt.h +++ b/generic/tkInt.h @@ -526,6 +526,7 @@ typedef struct TkDisplay { #define TK_DISPLAY_USE_IM (1 << 1) #define TK_DISPLAY_WM_TRACING (1 << 3) #define TK_DISPLAY_IN_WARP (1 << 4) +#define TK_DISPLAY_USE_XKB (1 << 5) /* * One of the following structures exists for each error handler created by a @@ -1076,6 +1077,9 @@ MODULE_SCOPE int Tk_ListboxObjCmd(ClientData clientData, MODULE_SCOPE int Tk_LowerObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); +MODULE_SCOPE int Tk_MenuObjCmd(ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[]); MODULE_SCOPE int Tk_MenubuttonObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); @@ -1106,13 +1110,15 @@ MODULE_SCOPE int Tk_RaiseObjCmd(ClientData clientData, MODULE_SCOPE int Tk_ScaleObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); -MODULE_SCOPE int Tk_ScrollbarCmd(ClientData clientData, - Tcl_Interp *interp, int argc, const char **argv); +MODULE_SCOPE int Tk_ScrollbarObjCmd(ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[]); MODULE_SCOPE int Tk_SelectionObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); -MODULE_SCOPE int Tk_SendCmd(ClientData clientData, - Tcl_Interp *interp, int argc, const char **argv); +MODULE_SCOPE int Tk_SendObjCmd(ClientData clientData, + Tcl_Interp *interp,int objc, + Tcl_Obj *const objv[]); MODULE_SCOPE int Tk_SendObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); @@ -1147,9 +1153,8 @@ MODULE_SCOPE void TkFreeGeometryMaster(Tk_Window tkwin, MODULE_SCOPE void TkEventInit(void); MODULE_SCOPE void TkRegisterObjTypes(void); -MODULE_SCOPE int TkCreateMenuCmd(Tcl_Interp *interp); -MODULE_SCOPE int TkDeadAppCmd(ClientData clientData, - Tcl_Interp *interp, int argc, const char **argv); +MODULE_SCOPE int TkDeadAppObjCmd(ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *const argv[]); MODULE_SCOPE int TkCanvasGetCoordObj(Tcl_Interp *interp, Tk_Canvas canvas, Tcl_Obj *obj, double *doublePtr); @@ -1213,7 +1218,7 @@ MODULE_SCOPE int TkInitFontchooser(Tcl_Interp *interp, ClientData clientData); MODULE_SCOPE void TkpWarpPointer(TkDisplay *dispPtr); -#ifdef __WIN32__ +#ifdef _WIN32 #define TkParseColor XParseColor #else MODULE_SCOPE Status TkParseColor (Display * display, @@ -1239,7 +1244,7 @@ MODULE_SCOPE int SquareObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj * const objv[]); MODULE_SCOPE int TkOldTestInit(Tcl_Interp *interp); -#if !(defined(__WIN32__) || defined(MAC_OSX_TK)) +#if !(defined(_WIN32) || defined(MAC_OSX_TK)) #define TkplatformtestInit(x) TCL_OK #else MODULE_SCOPE int TkplatformtestInit(Tcl_Interp *interp); diff --git a/generic/tkIntDecls.h b/generic/tkIntDecls.h index 8d36ec0..b8addbd 100644 --- a/generic/tkIntDecls.h +++ b/generic/tkIntDecls.h @@ -35,6 +35,10 @@ struct TkSharedText; /* !BEGIN!: Do not edit below this line. */ +#ifdef __cplusplus +extern "C" { +#endif + /* * Exported function declarations: */ @@ -429,11 +433,11 @@ EXTERN void TkDeleteThreadExitHandler(Tcl_ExitProc *proc, /* Slot 155 is reserved */ /* 156 */ EXTERN int TkpTestembedCmd(ClientData clientData, - Tcl_Interp *interp, int argc, - const char **argv); + Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[]); /* 157 */ EXTERN int TkpTesttextCmd(ClientData dummy, Tcl_Interp *interp, - int argc, const char **argv); + int objc, Tcl_Obj *const objv[]); /* 158 */ EXTERN int TkSelGetSelection(Tcl_Interp *interp, Tk_Window tkwin, Atom selection, Atom target, @@ -549,7 +553,7 @@ EXTERN void TkDrawAngledChars(Display *display, typedef struct TkIntStubs { int magic; - const struct TkIntStubHooks *hooks; + void *hooks; TkWindow * (*tkAllocWindow) (TkDisplay *dispPtr, int screenNum, TkWindow *parentPtr); /* 0 */ void (*tkBezierPoints) (double control[], int numSteps, double *coordPtr); /* 1 */ @@ -672,20 +676,20 @@ typedef struct TkIntStubs { void (*tkSetRegion) (Display *display, GC gc, TkRegion rgn); /* 118 */ void (*tkUnionRectWithRegion) (XRectangle *rect, TkRegion src, TkRegion dr_return); /* 119 */ void (*reserved120)(void); -#if !(defined(__WIN32__) || defined(MAC_OSX_TK)) /* X11 */ +#if !(defined(_WIN32) || defined(MAC_OSX_TK)) /* X11 */ void (*reserved121)(void); #endif /* X11 */ -#if defined(__WIN32__) /* WIN */ +#if defined(_WIN32) /* WIN */ void (*reserved121)(void); #endif /* WIN */ #ifdef MAC_OSX_TK /* AQUA */ void (*reserved121)(void); /* Dummy entry for stubs table backwards compatibility */ Pixmap (*tkpCreateNativeBitmap) (Display *display, const void *source); /* 121 */ #endif /* AQUA */ -#if !(defined(__WIN32__) || defined(MAC_OSX_TK)) /* X11 */ +#if !(defined(_WIN32) || defined(MAC_OSX_TK)) /* X11 */ void (*reserved122)(void); #endif /* X11 */ -#if defined(__WIN32__) /* WIN */ +#if defined(_WIN32) /* WIN */ void (*reserved122)(void); #endif /* WIN */ #ifdef MAC_OSX_TK /* AQUA */ @@ -693,10 +697,10 @@ typedef struct TkIntStubs { void (*tkpDefineNativeBitmaps) (void); /* 122 */ #endif /* AQUA */ void (*reserved123)(void); -#if !(defined(__WIN32__) || defined(MAC_OSX_TK)) /* X11 */ +#if !(defined(_WIN32) || defined(MAC_OSX_TK)) /* X11 */ void (*reserved124)(void); #endif /* X11 */ -#if defined(__WIN32__) /* WIN */ +#if defined(_WIN32) /* WIN */ void (*reserved124)(void); #endif /* WIN */ #ifdef MAC_OSX_TK /* AQUA */ @@ -734,8 +738,8 @@ typedef struct TkIntStubs { void (*tkCreateThreadExitHandler) (Tcl_ExitProc *proc, ClientData clientData); /* 153 */ void (*tkDeleteThreadExitHandler) (Tcl_ExitProc *proc, ClientData clientData); /* 154 */ void (*reserved155)(void); - int (*tkpTestembedCmd) (ClientData clientData, Tcl_Interp *interp, int argc, const char **argv); /* 156 */ - int (*tkpTesttextCmd) (ClientData dummy, Tcl_Interp *interp, int argc, const char **argv); /* 157 */ + int (*tkpTestembedCmd) (ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 156 */ + int (*tkpTesttextCmd) (ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 157 */ int (*tkSelGetSelection) (Tcl_Interp *interp, Tk_Window tkwin, Atom selection, Atom target, Tk_GetSelProc *proc, ClientData clientData); /* 158 */ int (*tkTextGetIndex) (Tcl_Interp *interp, struct TkText *textPtr, const char *string, struct TkTextIndex *indexPtr); /* 159 */ int (*tkTextIndexBackBytes) (const struct TkText *textPtr, const struct TkTextIndex *srcPtr, int count, struct TkTextIndex *dstPtr); /* 160 */ @@ -765,10 +769,8 @@ typedef struct TkIntStubs { void (*tkDrawAngledChars) (Display *display, Drawable drawable, GC gc, Tk_Font tkfont, const char *source, int numBytes, double x, double y, double angle); /* 184 */ } TkIntStubs; -#ifdef __cplusplus -extern "C" { -#endif extern const TkIntStubs *tkIntStubsPtr; + #ifdef __cplusplus } #endif @@ -1148,7 +1150,7 @@ extern const TkIntStubs *tkIntStubsPtr; /* * On X11, these macros are just wrappers for the equivalent X Region calls. */ -#if !(defined(__WIN32__) || defined(__CYGWIN__) || defined(MAC_OSX_TK)) /* X11 */ +#if !(defined(_WIN32) || defined(__CYGWIN__) || defined(MAC_OSX_TK)) /* X11 */ #undef TkClipBox #undef TkCreateRegion diff --git a/generic/tkIntPlatDecls.h b/generic/tkIntPlatDecls.h index e2528d8..e48e803 100644 --- a/generic/tkIntPlatDecls.h +++ b/generic/tkIntPlatDecls.h @@ -26,11 +26,15 @@ /* !BEGIN!: Do not edit below this line. */ +#ifdef __cplusplus +extern "C" { +#endif + /* * Exported function declarations: */ -#if defined(__WIN32__) || defined(__CYGWIN__) /* WIN */ +#if defined(_WIN32) || defined(__CYGWIN__) /* WIN */ /* 0 */ EXTERN char * TkAlignImageData(XImage *image, int alignment, int bitOrder); @@ -136,8 +140,8 @@ EXTERN void TkWmCleanup(TkDisplay *dispPtr); EXTERN void TkSendCleanup(TkDisplay *dispPtr); /* 45 */ EXTERN int TkpTestsendCmd(ClientData clientData, - Tcl_Interp *interp, int argc, - const char **argv); + Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[]); #endif /* WIN */ #ifdef MAC_OSX_TK /* AQUA */ /* 0 */ @@ -246,13 +250,17 @@ EXTERN int TkGenerateButtonEvent(int x, int y, Window window, unsigned int state); /* 51 */ EXTERN void TkGenWMDestroyEvent(Tk_Window tkwin); -/* Slot 52 is reserved */ +/* 52 */ +EXTERN void TkMacOSXSetDrawingEnabled(TkWindow *winPtr, int flag); /* 53 */ EXTERN unsigned long TkpGetMS(void); /* 54 */ EXTERN void * TkMacOSXDrawable(Drawable drawable); +/* 55 */ +EXTERN int TkpScanWindowId(Tcl_Interp *interp, + const char *string, Window *idPtr); #endif /* AQUA */ -#if !(defined(__WIN32__) || defined(__CYGWIN__) || defined(MAC_OSX_TK)) /* X11 */ +#if !(defined(_WIN32) || defined(__CYGWIN__) || defined(MAC_OSX_TK)) /* X11 */ /* 0 */ EXTERN void TkCreateXEventSource(void); /* Slot 1 is reserved */ @@ -279,15 +287,15 @@ EXTERN void TkSendCleanup(TkDisplay *dispPtr); EXTERN int TkpWmSetState(TkWindow *winPtr, int state); /* 13 */ EXTERN int TkpTestsendCmd(ClientData clientData, - Tcl_Interp *interp, int argc, - const char **argv); + Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[]); #endif /* X11 */ typedef struct TkIntPlatStubs { int magic; - const struct TkIntPlatStubHooks *hooks; + void *hooks; -#if defined(__WIN32__) || defined(__CYGWIN__) /* WIN */ +#if defined(_WIN32) || defined(__CYGWIN__) /* WIN */ char * (*tkAlignImageData) (XImage *image, int alignment, int bitOrder); /* 0 */ void (*reserved1)(void); void (*tkGenerateActivateEvents) (TkWindow *winPtr, int active); /* 2 */ @@ -333,7 +341,7 @@ typedef struct TkIntPlatStubs { void (*tkUnixSetMenubar) (Tk_Window tkwin, Tk_Window menubar); /* 42 */ void (*tkWmCleanup) (TkDisplay *dispPtr); /* 43 */ void (*tkSendCleanup) (TkDisplay *dispPtr); /* 44 */ - int (*tkpTestsendCmd) (ClientData clientData, Tcl_Interp *interp, int argc, const char **argv); /* 45 */ + int (*tkpTestsendCmd) (ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 45 */ #endif /* WIN */ #ifdef MAC_OSX_TK /* AQUA */ void (*tkGenerateActivateEvents) (TkWindow *winPtr, int active); /* 0 */ @@ -388,11 +396,12 @@ typedef struct TkIntPlatStubs { Window (*tkGetTransientMaster) (TkWindow *winPtr); /* 49 */ int (*tkGenerateButtonEvent) (int x, int y, Window window, unsigned int state); /* 50 */ void (*tkGenWMDestroyEvent) (Tk_Window tkwin); /* 51 */ - void (*reserved52)(void); + void (*tkMacOSXSetDrawingEnabled) (TkWindow *winPtr, int flag); /* 52 */ unsigned long (*tkpGetMS) (void); /* 53 */ void * (*tkMacOSXDrawable) (Drawable drawable); /* 54 */ + int (*tkpScanWindowId) (Tcl_Interp *interp, const char *string, Window *idPtr); /* 55 */ #endif /* AQUA */ -#if !(defined(__WIN32__) || defined(__CYGWIN__) || defined(MAC_OSX_TK)) /* X11 */ +#if !(defined(_WIN32) || defined(__CYGWIN__) || defined(MAC_OSX_TK)) /* X11 */ void (*tkCreateXEventSource) (void); /* 0 */ void (*reserved1)(void); void (*reserved2)(void); @@ -406,14 +415,12 @@ typedef struct TkIntPlatStubs { void (*tkSendCleanup) (TkDisplay *dispPtr); /* 10 */ void (*reserved11)(void); int (*tkpWmSetState) (TkWindow *winPtr, int state); /* 12 */ - int (*tkpTestsendCmd) (ClientData clientData, Tcl_Interp *interp, int argc, const char **argv); /* 13 */ + int (*tkpTestsendCmd) (ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 13 */ #endif /* X11 */ } TkIntPlatStubs; -#ifdef __cplusplus -extern "C" { -#endif extern const TkIntPlatStubs *tkIntPlatStubsPtr; + #ifdef __cplusplus } #endif @@ -424,7 +431,7 @@ extern const TkIntPlatStubs *tkIntPlatStubsPtr; * Inline function declarations: */ -#if defined(__WIN32__) || defined(__CYGWIN__) /* WIN */ +#if defined(_WIN32) || defined(__CYGWIN__) /* WIN */ #define TkAlignImageData \ (tkIntPlatStubsPtr->tkAlignImageData) /* 0 */ /* Slot 1 is reserved */ @@ -615,13 +622,16 @@ extern const TkIntPlatStubs *tkIntPlatStubsPtr; (tkIntPlatStubsPtr->tkGenerateButtonEvent) /* 50 */ #define TkGenWMDestroyEvent \ (tkIntPlatStubsPtr->tkGenWMDestroyEvent) /* 51 */ -/* Slot 52 is reserved */ +#define TkMacOSXSetDrawingEnabled \ + (tkIntPlatStubsPtr->tkMacOSXSetDrawingEnabled) /* 52 */ #define TkpGetMS \ (tkIntPlatStubsPtr->tkpGetMS) /* 53 */ #define TkMacOSXDrawable \ (tkIntPlatStubsPtr->tkMacOSXDrawable) /* 54 */ +#define TkpScanWindowId \ + (tkIntPlatStubsPtr->tkpScanWindowId) /* 55 */ #endif /* AQUA */ -#if !(defined(__WIN32__) || defined(__CYGWIN__) || defined(MAC_OSX_TK)) /* X11 */ +#if !(defined(_WIN32) || defined(__CYGWIN__) || defined(MAC_OSX_TK)) /* X11 */ #define TkCreateXEventSource \ (tkIntPlatStubsPtr->tkCreateXEventSource) /* 0 */ /* Slot 1 is reserved */ diff --git a/generic/tkIntXlibDecls.h b/generic/tkIntXlibDecls.h index 5b0f267..6ac7ccb 100644 --- a/generic/tkIntXlibDecls.h +++ b/generic/tkIntXlibDecls.h @@ -36,11 +36,15 @@ typedef int (*XAfterFunction) ( /* WARNING, this type not in Xlib spec */ /* !BEGIN!: Do not edit below this line. */ +#ifdef __cplusplus +extern "C" { +#endif + /* * Exported function declarations: */ -#if defined(__WIN32__) || defined(__CYGWIN__) /* WIN */ +#if defined(_WIN32) || defined(__CYGWIN__) /* WIN */ /* 0 */ EXTERN int XSetDashes(Display *display, GC gc, int dash_offset, _Xconst char *dash_list, int n); @@ -620,9 +624,9 @@ EXTERN int XSync(Display *display, Bool flag); typedef struct TkIntXlibStubs { int magic; - const struct TkIntXlibStubHooks *hooks; + void *hooks; -#if defined(__WIN32__) || defined(__CYGWIN__) /* WIN */ +#if defined(_WIN32) || defined(__CYGWIN__) /* WIN */ int (*xSetDashes) (Display *display, GC gc, int dash_offset, _Xconst char *dash_list, int n); /* 0 */ XModifierKeymap * (*xGetModifierMapping) (Display *d); /* 1 */ XImage * (*xCreateImage) (Display *d, Visual *v, unsigned int ui1, int i1, int i2, char *cp, unsigned int ui2, unsigned int ui3, int i3, int i4); /* 2 */ @@ -835,10 +839,8 @@ typedef struct TkIntXlibStubs { #endif /* AQUA */ } TkIntXlibStubs; -#ifdef __cplusplus -extern "C" { -#endif extern const TkIntXlibStubs *tkIntXlibStubsPtr; + #ifdef __cplusplus } #endif @@ -849,7 +851,7 @@ extern const TkIntXlibStubs *tkIntXlibStubsPtr; * Inline function declarations: */ -#if defined(__WIN32__) || defined(__CYGWIN__) /* WIN */ +#if defined(_WIN32) || defined(__CYGWIN__) /* WIN */ #define XSetDashes \ (tkIntXlibStubsPtr->xSetDashes) /* 0 */ #define XGetModifierMapping \ diff --git a/generic/tkListbox.c b/generic/tkListbox.c index 620f82f..c7effdd 100644 --- a/generic/tkListbox.c +++ b/generic/tkListbox.c @@ -15,7 +15,7 @@ #include "default.h" #include "tkInt.h" -#ifdef WIN32 +#ifdef _WIN32 #include "tkWinInt.h" #endif @@ -90,14 +90,14 @@ typedef struct { * display. */ int topIndex; /* Index of top-most element visible in * window. */ - int fullLines; /* Number of lines that fit are completely + int fullLines; /* Number of lines that are completely * visible in window. There may be one * additional line at the bottom that is * partially visible. */ int partialLine; /* 0 means that the window holds exactly * fullLines lines. 1 means that there is one * additional line that is partially - * visble. */ + * visible. */ int setGrid; /* Non-zero means pass gridding information to * window manager. */ @@ -114,7 +114,8 @@ typedef struct { int xOffset; /* The left edge of each string in the listbox * is offset to the left by this many pixels * (0 means no offset, positive means there is - * an offset). */ + * an offset). This is x scrolling information + * is not linked to justification. */ /* * Information about what's selected or active, if any. @@ -131,7 +132,7 @@ typedef struct { int active; /* Index of "active" element (the one that has * been selected by keyboard traversal). -1 * means none. */ - int activeStyle; /* style in which to draw the active element. + int activeStyle; /* Style in which to draw the active element. * One of: underline, none, dotbox */ /* @@ -165,6 +166,7 @@ typedef struct { Pixmap gray; /* Pixmap for displaying disabled text. */ int flags; /* Various flag bits: see below for * definitions. */ + Tk_Justify justify; /* Justification. */ } Listbox; /* @@ -197,7 +199,7 @@ typedef struct { * be updated. * GOT_FOCUS: Non-zero means this widget currently has the * input focus. - * MAXWIDTH_IS_STALE: Stored maxWidth may be out-of-date + * MAXWIDTH_IS_STALE: Stored maxWidth may be out-of-date. * LISTBOX_DELETED: This listbox has been effectively destroyed. */ @@ -275,6 +277,8 @@ static const Tk_OptionSpec optionSpecs[] = { {TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness", "HighlightThickness", DEF_LISTBOX_HIGHLIGHT_WIDTH, -1, Tk_Offset(Listbox, highlightWidth), 0, 0, 0}, + {TK_OPTION_JUSTIFY, "-justify", "justify", "Justify", + DEF_LISTBOX_JUSTIFY, -1, Tk_Offset(Listbox, justify), 0, 0, 0}, {TK_OPTION_RELIEF, "-relief", "relief", "Relief", DEF_LISTBOX_RELIEF, -1, Tk_Offset(Listbox, relief), 0, 0, 0}, {TK_OPTION_BORDER, "-selectbackground", "selectBackground", "Foreground", @@ -285,7 +289,7 @@ static const Tk_OptionSpec optionSpecs[] = { Tk_Offset(Listbox, selBorderWidth), 0, 0, 0}, {TK_OPTION_COLOR, "-selectforeground", "selectForeground", "Background", DEF_LISTBOX_SELECT_FG_COLOR, -1, Tk_Offset(Listbox, selFgColorPtr), - TK_CONFIG_NULL_OK, DEF_LISTBOX_SELECT_FG_MONO, 0}, + TK_OPTION_NULL_OK, DEF_LISTBOX_SELECT_FG_MONO, 0}, {TK_OPTION_STRING, "-selectmode", "selectMode", "SelectMode", DEF_LISTBOX_SELECT_MODE, -1, Tk_Offset(Listbox, selectMode), TK_OPTION_NULL_OK, 0, 0}, @@ -313,7 +317,7 @@ static const Tk_OptionSpec optionSpecs[] = { /* * The itemAttrOptionSpecs table defines the valid configuration options for - * listbox items + * listbox items. */ static const Tk_OptionSpec itemAttrOptionSpecs[] = { @@ -340,7 +344,7 @@ static const Tk_OptionSpec itemAttrOptionSpecs[] = { }; /* - * The following tables define the listbox widget commands (and sub- commands) + * The following tables define the listbox widget commands (and sub-commands) * and map the indexes into the string tables into enumerated types used to * dispatch the listbox widget command. */ @@ -386,13 +390,13 @@ enum indices { static void ChangeListboxOffset(Listbox *listPtr, int offset); static void ChangeListboxView(Listbox *listPtr, int index); static int ConfigureListbox(Tcl_Interp *interp, Listbox *listPtr, - int objc, Tcl_Obj *const objv[], int flags); + int objc, Tcl_Obj *const objv[]); static int ConfigureListboxItem(Tcl_Interp *interp, Listbox *listPtr, ItemAttr *attrs, int objc, Tcl_Obj *const objv[], int index); static int ListboxDeleteSubCmd(Listbox *listPtr, int first, int last); -static void DestroyListbox(char *memPtr); +static void DestroyListbox(void *memPtr); static void DestroyListboxOptionTables(ClientData clientData, Tcl_Interp *interp); static void DisplayListbox(ClientData clientData); @@ -408,6 +412,7 @@ static void ListboxEventProc(ClientData clientData, static int ListboxFetchSelection(ClientData clientData, int offset, char *buffer, int maxBytes); static void ListboxLostSelection(ClientData clientData); +static void GenerateListboxSelectEvent(Listbox *listPtr); static void EventuallyRedrawRange(Listbox *listPtr, int first, int last); static void ListboxScanTo(Listbox *listPtr, int x, int y); @@ -435,6 +440,7 @@ static char * ListboxListVarProc(ClientData clientData, const char *name2, int flags); static void MigrateHashEntries(Tcl_HashTable *table, int first, int last, int offset); +static int GetMaxOffset(Listbox *listPtr); /* * The structure below defines button class behavior by means of procedures @@ -545,6 +551,7 @@ Tk_ListboxObjCmd( listPtr->cursor = None; listPtr->state = STATE_NORMAL; listPtr->gray = None; + listPtr->justify = TK_JUSTIFY_LEFT; /* * Keep a hold of the associated tkwin until we destroy the listbox, @@ -566,7 +573,7 @@ Tk_ListboxObjCmd( return TCL_ERROR; } - if (ConfigureListbox(interp, listPtr, objc-2, objv+2, 0) != TCL_OK) { + if (ConfigureListbox(interp, listPtr, objc-2, objv+2) != TCL_OK) { Tk_DestroyWindow(listPtr->tkwin); return TCL_ERROR; } @@ -612,7 +619,7 @@ ListboxWidgetObjCmd( /* * Parse the command by looking up the second argument in the list of - * valid subcommand names + * valid subcommand names. */ result = Tcl_GetIndexFromObj(interp, objv[1], commandNames, @@ -697,7 +704,7 @@ ListboxWidgetObjCmd( Tcl_SetObjResult(interp, objPtr); result = TCL_OK; } else { - result = ConfigureListbox(interp, listPtr, objc-2, objv+2, 0); + result = ConfigureListbox(interp, listPtr, objc-2, objv+2); } break; @@ -1075,6 +1082,7 @@ ListboxBboxSubCmd( Listbox *listPtr, /* Information about the listbox */ int index) /* Index of the element to get bbox info on */ { + register Tk_Window tkwin = listPtr->tkwin; int lastVisibleIndex; /* @@ -1110,7 +1118,15 @@ ListboxBboxSubCmd( Tk_GetFontMetrics(listPtr->tkfont, &fm); pixelWidth = Tk_TextWidth(listPtr->tkfont, stringRep, stringLen); - x = listPtr->inset + listPtr->selBorderWidth - listPtr->xOffset; + if (listPtr->justify == TK_JUSTIFY_LEFT) { + x = (listPtr->inset + listPtr->selBorderWidth) - listPtr->xOffset; + } else if (listPtr->justify == TK_JUSTIFY_RIGHT) { + x = Tk_Width(tkwin) - (listPtr->inset + listPtr->selBorderWidth) + - pixelWidth - listPtr->xOffset + GetMaxOffset(listPtr); + } else { + x = (Tk_Width(tkwin) - pixelWidth)/2 + - listPtr->xOffset + GetMaxOffset(listPtr)/2; + } y = ((index - listPtr->topIndex)*listPtr->lineHeight) + listPtr->inset + listPtr->selBorderWidth; results[0] = Tcl_NewIntObj(x); @@ -1428,9 +1444,9 @@ ListboxGetItemAttributes( static void DestroyListbox( - char *memPtr) /* Info about listbox widget. */ + void *memPtr) /* Info about listbox widget. */ { - register Listbox *listPtr = (Listbox *) memPtr; + register Listbox *listPtr = memPtr; Tcl_HashEntry *entry; Tcl_HashSearch search; @@ -1444,7 +1460,7 @@ DestroyListbox( } if (listPtr->listVarName != NULL) { - Tcl_UntraceVar(listPtr->interp, listPtr->listVarName, + Tcl_UntraceVar2(listPtr->interp, listPtr->listVarName, NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, ListboxListVarProc, listPtr); } @@ -1542,8 +1558,7 @@ ConfigureListbox( register Listbox *listPtr, /* Information about widget; may or may not * already have values for some fields. */ int objc, /* Number of valid entries in argv. */ - Tcl_Obj *const objv[], /* Arguments. */ - int flags) /* Flags to pass to Tk_ConfigureWidget. */ + Tcl_Obj *const objv[]) /* Arguments. */ { Tk_SavedOptions savedOptions; Tcl_Obj *oldListObj = NULL; @@ -1552,7 +1567,7 @@ ConfigureListbox( oldExport = listPtr->exportSelection; if (listPtr->listVarName != NULL) { - Tcl_UntraceVar(interp, listPtr->listVarName, + Tcl_UntraceVar2(interp, listPtr->listVarName, NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, ListboxListVarProc, listPtr); } @@ -1629,9 +1644,6 @@ ConfigureListbox( if (Tcl_SetVar2Ex(interp, listPtr->listVarName, NULL, listVarObj, TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG) == NULL) { - if (oldListObj == NULL) { - Tcl_DecrRefCount(listVarObj); - } continue; } } @@ -1648,8 +1660,8 @@ ConfigureListbox( } listPtr->listObj = listVarObj; - Tcl_TraceVar(listPtr->interp, listPtr->listVarName, - TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, + Tcl_TraceVar2(listPtr->interp, listPtr->listVarName, + NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, ListboxListVarProc, listPtr); } else if (listPtr->listObj == NULL) { listPtr->listObj = Tcl_NewObj(); @@ -1840,6 +1852,7 @@ DisplayListbox( * or right edge of the listbox is * off-screen. */ Pixmap pixmap; + int textWidth; listPtr->flags &= ~REDRAW_PENDING; if (listPtr->flags & LISTBOX_DELETED) { @@ -2019,7 +2032,7 @@ DisplayListbox( } else { /* * If there is an item attributes record for this item, draw - * the background box and set the foreground color accordingly + * the background box and set the foreground color accordingly. */ if (entry != NULL) { @@ -2059,12 +2072,24 @@ DisplayListbox( * Draw the actual text of this item. */ + Tcl_ListObjIndex(listPtr->interp, listPtr->listObj, i, &curElement); + stringRep = Tcl_GetStringFromObj(curElement, &stringLen); + textWidth = Tk_TextWidth(listPtr->tkfont, stringRep, stringLen); + Tk_GetFontMetrics(listPtr->tkfont, &fm); y += fm.ascent + listPtr->selBorderWidth; - x = listPtr->inset + listPtr->selBorderWidth - listPtr->xOffset; - Tcl_ListObjIndex(listPtr->interp, listPtr->listObj, i, &curElement); - stringRep = Tcl_GetStringFromObj(curElement, &stringLen); - Tk_DrawChars(listPtr->display, pixmap, gc, listPtr->tkfont, + + if (listPtr->justify == TK_JUSTIFY_LEFT) { + x = (listPtr->inset + listPtr->selBorderWidth) - listPtr->xOffset; + } else if (listPtr->justify == TK_JUSTIFY_RIGHT) { + x = Tk_Width(tkwin) - (listPtr->inset + listPtr->selBorderWidth) + - textWidth - listPtr->xOffset + GetMaxOffset(listPtr); + } else { + x = (Tk_Width(tkwin) - textWidth)/2 + - listPtr->xOffset + GetMaxOffset(listPtr)/2; + } + + Tk_DrawChars(listPtr->display, pixmap, gc, listPtr->tkfont, stringRep, stringLen, x, y); /* @@ -2080,7 +2105,7 @@ DisplayListbox( Tk_UnderlineChars(listPtr->display, pixmap, gc, listPtr->tkfont, stringRep, x, y, 0, stringLen); } else if (listPtr->activeStyle == ACTIVE_STYLE_DOTBOX) { -#ifdef WIN32 +#ifdef _WIN32 /* * This provides for exact default look and feel on Windows. */ @@ -2097,7 +2122,7 @@ DisplayListbox( rect.bottom = rect.top + listPtr->lineHeight; DrawFocusRect(dc, &rect); TkWinReleaseDrawableDC(pixmap, dc, &state); -#else /* !WIN32 */ +#else /* !_WIN32 */ /* * Draw a dotted box around the text. */ @@ -2136,7 +2161,7 @@ DisplayListbox( gcValues.line_style = LineSolid; XChangeGC(listPtr->display, gc, GCLineStyle, &gcValues); } -#endif /* WIN32 */ +#endif /* _WIN32 */ } } @@ -2461,7 +2486,7 @@ ListboxDeleteSubCmd( /* * Check width of the element. We only have to check if widthChanged * has not already been set to 1, because we only need one maxWidth - * element to disappear for us to have to recompute the width + * element to disappear for us to have to recompute the width. */ if (widthChanged == 0) { @@ -2601,7 +2626,7 @@ ListboxEventProc( if (listPtr->flags & REDRAW_PENDING) { Tcl_CancelIdleCall(DisplayListbox, clientData); } - Tcl_EventuallyFree(clientData, DestroyListbox); + Tcl_EventuallyFree(clientData, (Tcl_FreeProc *) DestroyListbox); } } else if (eventPtr->type == ConfigureNotify) { int vertSpace; @@ -2738,7 +2763,11 @@ GetListboxIndex( stringRep = Tcl_GetString(indexObj); if (stringRep[0] == '@') { - /* @x,y index */ + + /* + * @x,y index + */ + int y; const char *start; char *end; @@ -2847,9 +2876,7 @@ ChangeListboxOffset( */ offset += listPtr->xScrollUnit / 2; - maxOffset = listPtr->maxWidth - (Tk_Width(listPtr->tkwin) - - 2*listPtr->inset - 2*listPtr->selBorderWidth) - + listPtr->xScrollUnit - 1; + maxOffset = GetMaxOffset(listPtr); if (offset > maxOffset) { offset = maxOffset; } @@ -2890,9 +2917,7 @@ ListboxScanTo( int newTopIndex, newOffset, maxIndex, maxOffset; maxIndex = listPtr->nElements - listPtr->fullLines; - maxOffset = listPtr->maxWidth + (listPtr->xScrollUnit - 1) - - (Tk_Width(listPtr->tkwin) - 2*listPtr->inset - - 2*listPtr->selBorderWidth - listPtr->xScrollUnit); + maxOffset = GetMaxOffset(listPtr); /* * Compute new top line for screen by amplifying the difference between @@ -3173,12 +3198,46 @@ ListboxLostSelection( if ((listPtr->exportSelection) && (listPtr->nElements > 0)) { ListboxSelect(listPtr, 0, listPtr->nElements-1, 0); + GenerateListboxSelectEvent(listPtr); } } /* *---------------------------------------------------------------------- * + * GenerateListboxSelectEvent -- + * + * Send an event that the listbox selection was updated. This is + * equivalent to event generate $listboxWidget <<ListboxSelect>> + * + * Results: + * None + * + * Side effects: + * Any side effect possible, depending on bindings to this event. + * + *---------------------------------------------------------------------- + */ + +static void +GenerateListboxSelectEvent( + Listbox *listPtr) /* Information about widget. */ +{ + union {XEvent general; XVirtualEvent virtual;} event; + + memset(&event, 0, sizeof(event)); + event.general.xany.type = VirtualEvent; + event.general.xany.serial = NextRequest(Tk_Display(listPtr->tkwin)); + event.general.xany.send_event = False; + event.general.xany.window = Tk_WindowId(listPtr->tkwin); + event.general.xany.display = Tk_Display(listPtr->tkwin); + event.virtual.name = Tk_GetUid("ListboxSelect"); + Tk_HandleEvent(&event.general); +} + +/* + *---------------------------------------------------------------------- + * * EventuallyRedrawRange -- * * Ensure that a given range of elements is eventually redrawn on the @@ -3244,6 +3303,7 @@ ListboxUpdateVScrollbar( double first, last; int result; Tcl_Interp *interp; + Tcl_DString buf; if (listPtr->yScrollCmd == NULL) { return; @@ -3269,8 +3329,14 @@ ListboxUpdateVScrollbar( interp = listPtr->interp; Tcl_Preserve(interp); - result = Tcl_VarEval(interp, listPtr->yScrollCmd, " ", firstStr, " ", - lastStr, NULL); + Tcl_DStringInit(&buf); + Tcl_DStringAppend(&buf, listPtr->yScrollCmd, -1); + Tcl_DStringAppend(&buf, " ", -1); + Tcl_DStringAppend(&buf, firstStr, -1); + Tcl_DStringAppend(&buf, " ", -1); + Tcl_DStringAppend(&buf, lastStr, -1); + result = Tcl_EvalEx(interp, Tcl_DStringValue(&buf), -1, 0); + Tcl_DStringFree(&buf); if (result != TCL_OK) { Tcl_AddErrorInfo(interp, "\n (vertical scrolling command executed by listbox)"); @@ -3307,6 +3373,7 @@ ListboxUpdateHScrollbar( int result, windowWidth; double first, last; Tcl_Interp *interp; + Tcl_DString buf; if (listPtr->xScrollCmd == NULL) { return; @@ -3334,8 +3401,14 @@ ListboxUpdateHScrollbar( interp = listPtr->interp; Tcl_Preserve(interp); - result = Tcl_VarEval(interp, listPtr->xScrollCmd, " ", firstStr, " ", - lastStr, NULL); + Tcl_DStringInit(&buf); + Tcl_DStringAppend(&buf, listPtr->xScrollCmd, -1); + Tcl_DStringAppend(&buf, " ", -1); + Tcl_DStringAppend(&buf, firstStr, -1); + Tcl_DStringAppend(&buf, " ", -1); + Tcl_DStringAppend(&buf, lastStr, -1); + result = Tcl_EvalEx(interp, Tcl_DStringValue(&buf), -1, 0); + Tcl_DStringFree(&buf); if (result != TCL_OK) { Tcl_AddErrorInfo(interp, "\n (horizontal scrolling command executed by listbox)"); @@ -3381,8 +3454,8 @@ ListboxListVarProc( if ((flags & TCL_TRACE_DESTROYED) && !(flags & TCL_INTERP_DESTROYED)) { Tcl_SetVar2Ex(interp, listPtr->listVarName, NULL, listPtr->listObj, TCL_GLOBAL_ONLY); - Tcl_TraceVar(interp, listPtr->listVarName, - TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, + Tcl_TraceVar2(interp, listPtr->listVarName, + NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, ListboxListVarProc, clientData); return NULL; } @@ -3420,7 +3493,7 @@ ListboxListVarProc( /* * If the list length has decreased, then we should clean up selection and - * attributes information for elements past the end of the new list + * attributes information for elements past the end of the new list. */ oldLength = listPtr->nElements; @@ -3538,6 +3611,42 @@ MigrateHashEntries( } /* + *---------------------------------------------------------------------- + * + * GetMaxOffset -- + * + * Passing in a listbox pointer, returns the maximum offset for the box, + * i.e. the maximum possible horizontal scrolling value (in pixels). + * + * Results: + * Listbox's maxOffset. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- +*/ +static int GetMaxOffset( + register Listbox *listPtr) +{ + int maxOffset; + + maxOffset = listPtr->maxWidth - + (Tk_Width(listPtr->tkwin) - 2*listPtr->inset - + 2*listPtr->selBorderWidth) + listPtr->xScrollUnit - 1; + if (maxOffset < 0) { + + /* + * Listbox is larger in width than its largest width item. + */ + + maxOffset = 0; + } + maxOffset -= maxOffset % listPtr->xScrollUnit; + + return maxOffset; +} +/* * Local Variables: * mode: c * c-basic-offset: 4 diff --git a/generic/tkMain.c b/generic/tkMain.c index 706f444..1b21223 100644 --- a/generic/tkMain.c +++ b/generic/tkMain.c @@ -54,8 +54,17 @@ extern int TkCygwinMainEx(int, char **, Tcl_AppInitProc *, Tcl_Interp *); * platforms which don't have <tchar.h> we have to translate that * to strcmp here. */ -#ifdef __WIN32__ -# include "tclInt.h" +#ifdef _WIN32 +/* Little hack to eliminate the need for "tclInt.h" here: + Just copy a small portion of TclIntPlatStubs, just + enough to make it work. See [600b72bfbc] */ +typedef struct { + int magic; + void *hooks; + void (*dummy[16]) (void); /* dummy entries 0-15, not used */ + int (*tclpIsAtty) (int fd); /* 16 */ +} TclIntPlatStubs; +extern const TclIntPlatStubs *tclIntPlatStubsPtr; # include "tkWinInt.h" #else # define TCHAR char @@ -95,7 +104,7 @@ extern int TkCygwinMainEx(int, char **, Tcl_AppInitProc *, Tcl_Interp *); * it will conflict with a declaration elsewhere on some systems. */ -#if defined(__WIN32__) || defined(_WIN32) +#if defined(_WIN32) #define isatty WinIsTty static int WinIsTty(int fd) { HANDLE handle; @@ -108,9 +117,9 @@ static int WinIsTty(int fd) { */ #if !defined(STATIC_BUILD) - if (tclStubsPtr->reserved9 && TclpIsAtty) { + if (tclStubsPtr->reserved9 && tclIntPlatStubsPtr->tclpIsAtty) { /* We are running on Cygwin */ - return TclpIsAtty(fd); + return tclIntPlatStubsPtr->tclpIsAtty(fd); } #endif handle = GetStdHandle(STD_INPUT_HANDLE + fd); @@ -184,15 +193,18 @@ Tk_MainEx( InteractiveState is; /* - * Ensure that we are getting a compatible version of Tcl. This is really - * only an issue when Tk is loaded dynamically. + * Ensure that we are getting a compatible version of Tcl. */ - if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) { - abort(); + if (Tcl_InitStubs(interp, "8.6", 0) == NULL) { + if (Tcl_InitStubs(interp, "8.1", 0) == NULL) { + abort(); + } else { + Tcl_Panic("%s", Tcl_GetString(Tcl_GetObjResult(interp))); + } } -#if defined(__WIN32__) && !defined(__WIN64__) && !defined(UNICODE) && !defined(STATIC_BUILD) +#if defined(_WIN32) && !defined(UNICODE) && !defined(STATIC_BUILD) if (tclStubsPtr->reserved9) { /* We are running win32 Tk under Cygwin, so let's check @@ -223,7 +235,7 @@ Tk_MainEx( is.gotPartial = 0; Tcl_Preserve(interp); -#if defined(__WIN32__) && !defined(__CYGWIN__) +#if defined(_WIN32) && !defined(__CYGWIN__) Tk_InitConsoleChannels(interp); #endif @@ -315,7 +327,7 @@ Tk_MainEx( */ if (appInitProc(interp) != TCL_OK) { - TkpDisplayWarning(Tcl_GetStringResult(interp), + TkpDisplayWarning(Tcl_GetString(Tcl_GetObjResult(interp)), "application-specific initialization failed"); } @@ -335,7 +347,7 @@ Tk_MainEx( */ Tcl_AddErrorInfo(interp, ""); - TkpDisplayWarning(Tcl_GetVar(interp, "errorInfo", + TkpDisplayWarning(Tcl_GetVar2(interp, "errorInfo", NULL, TCL_GLOBAL_ONLY), "Error in startup script"); Tcl_DeleteInterp(interp); Tcl_Exit(1); @@ -448,7 +460,7 @@ StdinProc( Tcl_CreateChannelHandler(isPtr->input, TCL_READABLE, StdinProc, isPtr); } Tcl_DStringFree(&isPtr->command); - if (Tcl_GetStringResult(interp)[0] != '\0') { + if (Tcl_GetString(Tcl_GetObjResult(interp))[0] != '\0') { if ((code != TCL_OK) || (isPtr->tty)) { chan = Tcl_GetStdChannel((code != TCL_OK) ? TCL_STDERR : TCL_STDOUT); if (chan) { @@ -511,7 +523,7 @@ Prompt( if (code != TCL_OK) { Tcl_AddErrorInfo(interp, "\n (script that generates prompt)"); - if (Tcl_GetStringResult(interp)[0] != '\0') { + if (Tcl_GetString(Tcl_GetObjResult(interp))[0] != '\0') { chan = Tcl_GetStdChannel(TCL_STDERR); if (chan != NULL) { Tcl_WriteObj(chan, Tcl_GetObjResult(interp)); diff --git a/generic/tkMenu.c b/generic/tkMenu.c index 12d6ebd..d24516f 100644 --- a/generic/tkMenu.c +++ b/generic/tkMenu.c @@ -81,6 +81,10 @@ typedef struct ThreadSpecificData { int menusInitialized; /* Flag indicates whether thread-specific * elements of the Windows Menu module have * been initialized. */ + Tk_OptionTable menuOptionTable; + /* The option table for menus. */ + Tk_OptionTable entryOptionTables[6]; + /* The tables for menu entries. */ } ThreadSpecificData; static Tcl_ThreadDataKey dataKey; @@ -338,7 +342,7 @@ static void DeleteMenuCloneEntries(TkMenu *menuPtr, static void DestroyMenuHashTable(ClientData clientData, Tcl_Interp *interp); static void DestroyMenuInstance(TkMenu *menuPtr); -static void DestroyMenuEntry(char *memPtr); +static void DestroyMenuEntry(void *memPtr); static int GetIndexFromCoords(Tcl_Interp *interp, TkMenu *menuPtr, const char *string, int *indexPtr); @@ -349,8 +353,6 @@ static int MenuDoXPosition(Tcl_Interp *interp, static int MenuAddOrInsert(Tcl_Interp *interp, TkMenu *menuPtr, Tcl_Obj *indexPtr, int objc, Tcl_Obj *const objv[]); -static int MenuCmd(ClientData clientData, Tcl_Interp *interp, - int objc, Tcl_Obj *const objv[]); static void MenuCmdDeletedProc(ClientData clientData); static TkMenuEntry * MenuNewEntry(TkMenu *menuPtr, int index, int type); static char * MenuVarProc(ClientData clientData, @@ -381,63 +383,7 @@ static const Tk_ClassProcs menuClass = { /* *-------------------------------------------------------------- * - * TkCreateMenuCmd -- - * - * Called by Tk at initialization time to create the menu command. - * - * Results: - * A standard Tcl result. - * - * Side effects: - * See the user documentation. - * - *-------------------------------------------------------------- - */ - -static void -FreeOptionTables( - ClientData clientData, - Tcl_Interp *interp) -{ - ckfree(clientData); -} - -int -TkCreateMenuCmd( - Tcl_Interp *interp) /* Interpreter we are creating the command - * in. */ -{ - TkMenuOptionTables *optionTablesPtr = ckalloc(sizeof(TkMenuOptionTables)); - - optionTablesPtr->menuOptionTable = - Tk_CreateOptionTable(interp, tkMenuConfigSpecs); - optionTablesPtr->entryOptionTables[TEAROFF_ENTRY] = - Tk_CreateOptionTable(interp, specsArray[TEAROFF_ENTRY]); - optionTablesPtr->entryOptionTables[COMMAND_ENTRY] = - Tk_CreateOptionTable(interp, specsArray[COMMAND_ENTRY]); - optionTablesPtr->entryOptionTables[CASCADE_ENTRY] = - Tk_CreateOptionTable(interp, specsArray[CASCADE_ENTRY]); - optionTablesPtr->entryOptionTables[SEPARATOR_ENTRY] = - Tk_CreateOptionTable(interp, specsArray[SEPARATOR_ENTRY]); - optionTablesPtr->entryOptionTables[RADIO_BUTTON_ENTRY] = - Tk_CreateOptionTable(interp, specsArray[RADIO_BUTTON_ENTRY]); - optionTablesPtr->entryOptionTables[CHECK_BUTTON_ENTRY] = - Tk_CreateOptionTable(interp, specsArray[CHECK_BUTTON_ENTRY]); - - Tcl_CreateObjCommand(interp, "menu", MenuCmd, optionTablesPtr, 0); - Tcl_CallWhenDeleted(interp, FreeOptionTables, optionTablesPtr); - - if (Tcl_IsSafe(interp)) { - Tcl_HideCommand(interp, "menu", "menu"); - } - - return TCL_OK; -} - -/* - *-------------------------------------------------------------- - * - * MenuCmd -- + * Tk_MenuObjCmd -- * * This function is invoked to process the "menu" Tcl command. See the * user documentation for details on what it does. @@ -451,21 +397,22 @@ TkCreateMenuCmd( *-------------------------------------------------------------- */ -static int -MenuCmd( +int +Tk_MenuObjCmd( ClientData clientData, /* Main window associated with interpreter. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument strings. */ { - Tk_Window tkwin = Tk_MainWindow(interp); + Tk_Window tkwin = clientData; Tk_Window newWin; register TkMenu *menuPtr; TkMenuReferences *menuRefPtr; int i, index, toplevel; const char *windowName; static const char *const typeStringList[] = {"-type", NULL}; - TkMenuOptionTables *optionTablesPtr = clientData; + ThreadSpecificData *tsdPtr = + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "pathName ?-option value ...?"); @@ -476,10 +423,10 @@ MenuCmd( toplevel = 1; for (i = 2; i < (objc - 1); i++) { - if (Tcl_GetIndexFromObj(NULL, objv[i], typeStringList, NULL, 0, - &index) != TCL_ERROR) { - if ((Tcl_GetIndexFromObj(NULL, objv[i + 1], menuTypeStrings, NULL, - 0, &index) == TCL_OK) && (index == MENUBAR)) { + if (Tcl_GetIndexFromObjStruct(NULL, objv[i], typeStringList, + sizeof(char *), NULL, 0, &index) != TCL_ERROR) { + if ((Tcl_GetIndexFromObjStruct(NULL, objv[i + 1], menuTypeStrings, + sizeof(char *), NULL, 0, &index) == TCL_OK) && (index == MENUBAR)) { toplevel = 0; } break; @@ -511,7 +458,6 @@ MenuCmd( menuPtr->cursorPtr = None; menuPtr->masterMenuPtr = menuPtr; menuPtr->menuType = UNKNOWN_TYPE; - menuPtr->optionTablesPtr = optionTablesPtr; TkMenuInitializeDrawingFields(menuPtr); Tk_SetClass(menuPtr->tkwin, "Menu"); @@ -520,7 +466,7 @@ MenuCmd( ExposureMask|StructureNotifyMask|ActivateMask, TkMenuEventProc, menuPtr); if (Tk_InitOptions(interp, (char *) menuPtr, - menuPtr->optionTablesPtr->menuOptionTable, menuPtr->tkwin) + tsdPtr->menuOptionTable, menuPtr->tkwin) != TCL_OK) { Tk_DestroyWindow(menuPtr->tkwin); return TCL_ERROR; @@ -675,13 +621,15 @@ MenuWidgetObjCmd( register TkMenuEntry *mePtr; int result = TCL_OK; int option; + ThreadSpecificData *tsdPtr = + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?"); return TCL_ERROR; } - if (Tcl_GetIndexFromObj(interp, objv[1], menuOptions, "option", 0, - &option) != TCL_OK) { + if (Tcl_GetIndexFromObjStruct(interp, objv[1], menuOptions, + sizeof(char *), "option", 0, &option) != TCL_OK) { return TCL_ERROR; } Tcl_Preserve(menuPtr); @@ -725,7 +673,7 @@ MenuWidgetObjCmd( goto error; } resultPtr = Tk_GetOptionValue(interp, (char *) menuPtr, - menuPtr->optionTablesPtr->menuOptionTable, objv[2], + tsdPtr->menuOptionTable, objv[2], menuPtr->tkwin); if (resultPtr == NULL) { goto error; @@ -745,7 +693,7 @@ MenuWidgetObjCmd( if (objc == 2) { resultPtr = Tk_GetOptionInfo(interp, (char *) menuPtr, - menuPtr->optionTablesPtr->menuOptionTable, NULL, + tsdPtr->menuOptionTable, NULL, menuPtr->tkwin); if (resultPtr == NULL) { result = TCL_ERROR; @@ -755,7 +703,7 @@ MenuWidgetObjCmd( } } else if (objc == 3) { resultPtr = Tk_GetOptionInfo(interp, (char *) menuPtr, - menuPtr->optionTablesPtr->menuOptionTable, objv[2], + tsdPtr->menuOptionTable, objv[2], menuPtr->tkwin); if (resultPtr == NULL) { result = TCL_ERROR; @@ -937,9 +885,14 @@ MenuWidgetObjCmd( * Tearoff menus are posted differently on Mac and Windows than * non-tearoffs. TkpPostMenu does not actually map the menu's window * on those platforms, and popup menus have to be handled specially. + * Also, menubar menues are not intended to be posted (bug 1567681, + * 2160206). */ - if (menuPtr->menuType != TEAROFF_MENU) { + if (menuPtr->menuType == MENUBAR) { + Tcl_AppendResult(interp, "a menubar menu cannot be posted", NULL); + return TCL_ERROR; + } else if (menuPtr->menuType != TEAROFF_MENU) { result = TkpPostMenu(interp, menuPtr, x, y); } else { result = TkPostTearoffMenu(interp, menuPtr, x, y); @@ -1061,7 +1014,7 @@ TkInvokeMenu( Tcl_DStringInit(&ds); Tcl_DStringAppend(&ds, "tk::TearOffMenu ", -1); Tcl_DStringAppend(&ds, Tk_PathName(menuPtr->tkwin), -1); - result = Tcl_Eval(interp, Tcl_DStringValue(&ds)); + result = Tcl_EvalEx(interp, Tcl_DStringValue(&ds), -1, 0); Tcl_DStringFree(&ds); } else if ((mePtr->type == CHECK_BUTTON_ENTRY) && (mePtr->namePtr != NULL)) { @@ -1144,6 +1097,8 @@ DestroyMenuInstance( Tcl_Obj *newObjv[2]; TkMenu *parentMasterMenuPtr; TkMenuEntry *parentMasterEntryPtr; + ThreadSpecificData *tsdPtr = + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); /* * If the menu has any cascade menu entries pointing to it, the cascade @@ -1225,7 +1180,7 @@ DestroyMenuInstance( * for menu entries (i+1)...numEntries. */ - DestroyMenuEntry((char *) menuPtr->entries[i]); + DestroyMenuEntry(menuPtr->entries[i]); menuPtr->numEntries = i; } if (menuPtr->entries != NULL) { @@ -1233,7 +1188,7 @@ DestroyMenuInstance( } TkMenuFreeDrawOptions(menuPtr); Tk_FreeConfigOptions((char *) menuPtr, - menuPtr->optionTablesPtr->menuOptionTable, menuPtr->tkwin); + tsdPtr->menuOptionTable, menuPtr->tkwin); if (menuPtr->tkwin != NULL) { Tk_Window tkwin = menuPtr->tkwin; @@ -1423,9 +1378,9 @@ UnhookCascadeEntry( static void DestroyMenuEntry( - char *memPtr) /* Pointer to entry to be freed. */ + void *memPtr) /* Pointer to entry to be freed. */ { - register TkMenuEntry *mePtr = (TkMenuEntry *) memPtr; + register TkMenuEntry *mePtr = memPtr; TkMenu *menuPtr = mePtr->menuPtr; if (menuPtr->postedCascade == mePtr) { @@ -1469,13 +1424,14 @@ DestroyMenuEntry( } } UnhookCascadeEntry(mePtr); + menuRefPtr = mePtr->childMenuRefPtr; if (menuRefPtr != NULL) { if (menuRefPtr->menuPtr == destroyThis) { menuRefPtr->menuPtr = NULL; } - if (destroyThis != NULL) { - TkDestroyMenu(destroyThis); - } + } + if (destroyThis != NULL) { + TkDestroyMenu(destroyThis); } } else { UnhookCascadeEntry(mePtr); @@ -1492,7 +1448,7 @@ DestroyMenuEntry( && (mePtr->namePtr != NULL)) { const char *varName = Tcl_GetString(mePtr->namePtr); - Tcl_UntraceVar(menuPtr->interp, varName, + Tcl_UntraceVar2(menuPtr->interp, varName, NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, MenuVarProc, mePtr); } @@ -1566,12 +1522,14 @@ ConfigureMenu( int i; TkMenu *menuListPtr, *cleanupPtr; int result; + ThreadSpecificData *tsdPtr = + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); for (menuListPtr = menuPtr->masterMenuPtr; menuListPtr != NULL; menuListPtr = menuListPtr->nextInstancePtr) { menuListPtr->errorStructPtr = ckalloc(sizeof(Tk_SavedOptions)); result = Tk_SetOptions(interp, (char *) menuListPtr, - menuListPtr->optionTablesPtr->menuOptionTable, objc, objv, + tsdPtr->menuOptionTable, objc, objv, menuListPtr->tkwin, menuListPtr->errorStructPtr, NULL); if (result != TCL_OK) { for (cleanupPtr = menuPtr->masterMenuPtr; @@ -1597,8 +1555,8 @@ ConfigureMenu( */ if (menuListPtr->menuType == UNKNOWN_TYPE) { - Tcl_GetIndexFromObj(NULL, menuListPtr->menuTypePtr, - menuTypeStrings, NULL, 0, &menuListPtr->menuType); + Tcl_GetIndexFromObjStruct(NULL, menuListPtr->menuTypePtr, + menuTypeStrings, sizeof(char *), NULL, 0, &menuListPtr->menuType); /* * Configure the new window to be either a pop-up menu or a @@ -1662,7 +1620,7 @@ ConfigureMenu( && (menuListPtr->entries[0]->type == TEAROFF_ENTRY)) { int i; - Tcl_EventuallyFree(menuListPtr->entries[0], DestroyMenuEntry); + Tcl_EventuallyFree(menuListPtr->entries[0], (Tcl_FreeProc *) DestroyMenuEntry); for (i = 0; i < menuListPtr->numEntries - 1; i++) { menuListPtr->entries[i] = menuListPtr->entries[i + 1]; @@ -1742,12 +1700,12 @@ PostProcessEntry( if (mePtr->labelPtr == NULL) { mePtr->labelLength = 0; } else { - Tcl_GetStringFromObj(mePtr->labelPtr, &mePtr->labelLength); + (void)Tcl_GetStringFromObj(mePtr->labelPtr, &mePtr->labelLength); } if (mePtr->accelPtr == NULL) { mePtr->accelLength = 0; } else { - Tcl_GetStringFromObj(mePtr->accelPtr, &mePtr->accelLength); + (void)Tcl_GetStringFromObj(mePtr->accelPtr, &mePtr->accelLength); } /* @@ -1906,8 +1864,8 @@ PostProcessEntry( } if (mePtr->namePtr != NULL) { name = Tcl_GetString(mePtr->namePtr); - Tcl_TraceVar(menuPtr->interp, name, - TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, + Tcl_TraceVar2(menuPtr->interp, name, + NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, MenuVarProc, mePtr); } } @@ -1959,7 +1917,7 @@ ConfigureMenuEntry( || (mePtr->type == RADIO_BUTTON_ENTRY))) { const char *name = Tcl_GetString(mePtr->namePtr); - Tcl_UntraceVar(menuPtr->interp, name, + Tcl_UntraceVar2(menuPtr->interp, name, NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, MenuVarProc, mePtr); } @@ -2287,6 +2245,8 @@ MenuNewEntry( TkMenuEntry *mePtr; TkMenuEntry **newEntries; int i; + ThreadSpecificData *tsdPtr = + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); /* * Create a new array of entries with an empty slot for the new entry. @@ -2308,7 +2268,7 @@ MenuNewEntry( mePtr = ckalloc(sizeof(TkMenuEntry)); menuPtr->entries[index] = mePtr; mePtr->type = type; - mePtr->optionTable = menuPtr->optionTablesPtr->entryOptionTables[type]; + mePtr->optionTable = tsdPtr->entryOptionTables[type]; mePtr->menuPtr = menuPtr; mePtr->labelPtr = NULL; mePtr->labelLength = 0; @@ -2406,8 +2366,8 @@ MenuAddOrInsert( * Figure out the type of the new entry. */ - if (Tcl_GetIndexFromObj(interp, objv[0], menuEntryTypeStrings, - "menu entry type", 0, &type) != TCL_OK) { + if (Tcl_GetIndexFromObjStruct(interp, objv[0], menuEntryTypeStrings, + sizeof(char *), "menu entry type", 0, &type) != TCL_OK) { return TCL_ERROR; } @@ -2430,7 +2390,7 @@ MenuAddOrInsert( errorMenuPtr != NULL; errorMenuPtr = errorMenuPtr->nextInstancePtr) { Tcl_EventuallyFree(errorMenuPtr->entries[index], - DestroyMenuEntry); + (Tcl_FreeProc *) DestroyMenuEntry); for (i = index; i < errorMenuPtr->numEntries - 1; i++) { errorMenuPtr->entries[i] = errorMenuPtr->entries[i + 1]; errorMenuPtr->entries[i]->index = i; @@ -2544,7 +2504,7 @@ MenuVarProc( if (flags & TCL_TRACE_UNSETS) { mePtr->entryFlags &= ~ENTRY_SELECTED; if (flags & TCL_TRACE_DESTROYED) { - Tcl_TraceVar(interp, name, + Tcl_TraceVar2(interp, name, NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, MenuVarProc, clientData); } @@ -2558,7 +2518,7 @@ MenuVarProc( * entry. */ - value = Tcl_GetVar(interp, name, TCL_GLOBAL_ONLY); + value = Tcl_GetVar2(interp, name, NULL, TCL_GLOBAL_ONLY); if (value == NULL) { value = ""; } @@ -2711,8 +2671,8 @@ CloneMenu( if (newMenuTypePtr == NULL) { menuType = MASTER_MENU; } else { - if (Tcl_GetIndexFromObj(menuPtr->interp, newMenuTypePtr, - menuTypeStrings, "menu type", 0, &menuType) != TCL_OK) { + if (Tcl_GetIndexFromObjStruct(menuPtr->interp, newMenuTypePtr, + menuTypeStrings, sizeof(char *), "menu type", 0, &menuType) != TCL_OK) { return TCL_ERROR; } } @@ -2987,10 +2947,10 @@ GetIndexFromCoords( *indexPtr = -1; - /* set the width of the final column to the remainder of the window + /* set the width of the final column to the remainder of the window * being aware of windows that may not be mapped yet. */ - max = Tk_IsMapped(menuPtr->tkwin) + max = Tk_IsMapped(menuPtr->tkwin) ? Tk_Width(menuPtr->tkwin) : Tk_ReqWidth(menuPtr->tkwin); max -= borderwidth; @@ -3090,7 +3050,6 @@ TkNewMenuName( char *destString; int i; int doDot; - Tcl_CmdInfo cmdInfo; Tcl_HashTable *nameTablePtr = NULL; TkWindow *winPtr = (TkWindow *) menuPtr->tkwin; const char *parentName = Tcl_GetString(parentPtr); @@ -3130,7 +3089,7 @@ TkNewMenuName( Tcl_DecrRefCount(intPtr); } destString = Tcl_GetString(resultPtr); - if ((Tcl_GetCommandInfo(interp, destString, &cmdInfo) == 0) + if ((Tcl_FindCommand(interp, destString, NULL, 0) == NULL) && ((nameTablePtr == NULL) || (Tcl_FindHashEntry(nameTablePtr, destString) == NULL))) { break; @@ -3540,7 +3499,7 @@ DeleteMenuCloneEntries( for (menuListPtr = menuPtr->masterMenuPtr; menuListPtr != NULL; menuListPtr = menuListPtr->nextInstancePtr) { for (i = last; i >= first; i--) { - Tcl_EventuallyFree(menuListPtr->entries[i], DestroyMenuEntry); + Tcl_EventuallyFree(menuListPtr->entries[i], (Tcl_FreeProc *) DestroyMenuEntry); } for (i = last + 1; i < menuListPtr->numEntries; i++) { j = i - numDeleted; @@ -3625,6 +3584,20 @@ TkMenuInit(void) } if (!tsdPtr->menusInitialized) { TkpMenuThreadInit(); + tsdPtr->menuOptionTable = + Tk_CreateOptionTable(NULL, tkMenuConfigSpecs); + tsdPtr->entryOptionTables[TEAROFF_ENTRY] = + Tk_CreateOptionTable(NULL, specsArray[TEAROFF_ENTRY]); + tsdPtr->entryOptionTables[COMMAND_ENTRY] = + Tk_CreateOptionTable(NULL, specsArray[COMMAND_ENTRY]); + tsdPtr->entryOptionTables[CASCADE_ENTRY] = + Tk_CreateOptionTable(NULL, specsArray[CASCADE_ENTRY]); + tsdPtr->entryOptionTables[SEPARATOR_ENTRY] = + Tk_CreateOptionTable(NULL, specsArray[SEPARATOR_ENTRY]); + tsdPtr->entryOptionTables[RADIO_BUTTON_ENTRY] = + Tk_CreateOptionTable(NULL, specsArray[RADIO_BUTTON_ENTRY]); + tsdPtr->entryOptionTables[CHECK_BUTTON_ENTRY] = + Tk_CreateOptionTable(NULL, specsArray[CHECK_BUTTON_ENTRY]); tsdPtr->menusInitialized = 1; } } diff --git a/generic/tkMenu.h b/generic/tkMenu.h index def7d19..bac51aa 100644 --- a/generic/tkMenu.h +++ b/generic/tkMenu.h @@ -359,10 +359,7 @@ typedef struct TkMenu { /* A pointer to the original menu for this * clone chain. Points back to this structure * if this menu is a master menu. */ - struct TkMenuOptionTables *optionTablesPtr; - /* A pointer to the collection of option - * tables that work with menus and menu - * entries. */ + void *reserved1; /* not used any more. */ Tk_Window parentTopLevelPtr;/* If this menu is a menubar, this is the * toplevel that owns the menu. Only * applicable for menubar clones. */ @@ -431,17 +428,6 @@ typedef struct TkMenuReferences { } TkMenuReferences; /* - * This structure contains all of the option tables that are needed by menus. - */ - -typedef struct TkMenuOptionTables { - Tk_OptionTable menuOptionTable; - /* The option table for menus. */ - Tk_OptionTable entryOptionTables[6]; - /* The tables for menu entries. */ -} TkMenuOptionTables; - -/* * Flag bits for menus: * * REDRAW_PENDING: Non-zero means a DoWhenIdle handler has diff --git a/generic/tkMenubutton.c b/generic/tkMenubutton.c index 545401c..1a4d5ae 100644 --- a/generic/tkMenubutton.c +++ b/generic/tkMenubutton.c @@ -355,8 +355,8 @@ MenuButtonWidgetObjCmd( Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?"); return TCL_ERROR; } - result = Tcl_GetIndexFromObj(interp, objv[1], commandNames, "option", 0, - &index); + result = Tcl_GetIndexFromObjStruct(interp, objv[1], commandNames, + sizeof(char *), "option", 0, &index); if (result != TCL_OK) { return result; } @@ -436,7 +436,7 @@ DestroyMenuButton( Tcl_DeleteCommandFromToken(mbPtr->interp, mbPtr->widgetCmd); if (mbPtr->textVarName != NULL) { - Tcl_UntraceVar(mbPtr->interp, mbPtr->textVarName, + Tcl_UntraceVar2(mbPtr->interp, mbPtr->textVarName, NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, MenuButtonTextVarProc, mbPtr); } @@ -506,7 +506,7 @@ ConfigureMenuButton( */ if (mbPtr->textVarName != NULL) { - Tcl_UntraceVar(interp, mbPtr->textVarName, + Tcl_UntraceVar2(interp, mbPtr->textVarName, NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, MenuButtonTextVarProc, mbPtr); } @@ -625,9 +625,9 @@ ConfigureMenuButton( */ const char *value; - value = Tcl_GetVar(interp, mbPtr->textVarName, TCL_GLOBAL_ONLY); + value = Tcl_GetVar2(interp, mbPtr->textVarName, NULL, TCL_GLOBAL_ONLY); if (value == NULL) { - Tcl_SetVar(interp, mbPtr->textVarName, mbPtr->text, + Tcl_SetVar2(interp, mbPtr->textVarName, NULL, mbPtr->text, TCL_GLOBAL_ONLY); } else { if (mbPtr->text != NULL) { @@ -636,7 +636,7 @@ ConfigureMenuButton( mbPtr->text = ckalloc(strlen(value) + 1); strcpy(mbPtr->text, value); } - Tcl_TraceVar(interp, mbPtr->textVarName, + Tcl_TraceVar2(interp, mbPtr->textVarName, NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, MenuButtonTextVarProc, mbPtr); } @@ -888,16 +888,16 @@ MenuButtonTextVarProc( if (flags & TCL_TRACE_UNSETS) { if ((flags & TCL_TRACE_DESTROYED) && !(flags & TCL_INTERP_DESTROYED)) { - Tcl_SetVar(interp, mbPtr->textVarName, mbPtr->text, + Tcl_SetVar2(interp, mbPtr->textVarName, NULL, mbPtr->text, TCL_GLOBAL_ONLY); - Tcl_TraceVar(interp, mbPtr->textVarName, + Tcl_TraceVar2(interp, mbPtr->textVarName, NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, MenuButtonTextVarProc, clientData); } return NULL; } - value = Tcl_GetVar(interp, mbPtr->textVarName, TCL_GLOBAL_ONLY); + value = Tcl_GetVar2(interp, mbPtr->textVarName, NULL, TCL_GLOBAL_ONLY); if (value == NULL) { value = ""; } diff --git a/generic/tkMessage.c b/generic/tkMessage.c index 4779e00..2b71998 100644 --- a/generic/tkMessage.c +++ b/generic/tkMessage.c @@ -318,8 +318,8 @@ MessageWidgetObjCmd( return TCL_ERROR; } - if (Tcl_GetIndexFromObj(interp, objv[1], optionStrings, "option", 0, - &index) != TCL_OK) { + if (Tcl_GetIndexFromObjStruct(interp, objv[1], optionStrings, + sizeof(char *), "option", 0, &index) != TCL_OK) { return TCL_ERROR; } @@ -405,7 +405,7 @@ DestroyMessage( Tk_FreeTextLayout(msgPtr->textLayout); } if (msgPtr->textVarName != NULL) { - Tcl_UntraceVar(msgPtr->interp, msgPtr->textVarName, + Tcl_UntraceVar2(msgPtr->interp, msgPtr->textVarName, NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, MessageTextVarProc, msgPtr); } @@ -450,7 +450,7 @@ ConfigureMessage( */ if (msgPtr->textVarName != NULL) { - Tcl_UntraceVar(interp, msgPtr->textVarName, + Tcl_UntraceVar2(interp, msgPtr->textVarName, NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, MessageTextVarProc, msgPtr); } @@ -470,9 +470,9 @@ ConfigureMessage( if (msgPtr->textVarName != NULL) { const char *value; - value = Tcl_GetVar(interp, msgPtr->textVarName, TCL_GLOBAL_ONLY); + value = Tcl_GetVar2(interp, msgPtr->textVarName, NULL, TCL_GLOBAL_ONLY); if (value == NULL) { - Tcl_SetVar(interp, msgPtr->textVarName, msgPtr->string, + Tcl_SetVar2(interp, msgPtr->textVarName, NULL, msgPtr->string, TCL_GLOBAL_ONLY); } else { if (msgPtr->string != NULL) { @@ -480,7 +480,7 @@ ConfigureMessage( } msgPtr->string = strcpy(ckalloc(strlen(value) + 1), value); } - Tcl_TraceVar(interp, msgPtr->textVarName, + Tcl_TraceVar2(interp, msgPtr->textVarName, NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, MessageTextVarProc, msgPtr); } @@ -845,16 +845,16 @@ MessageTextVarProc( if (flags & TCL_TRACE_UNSETS) { if ((flags & TCL_TRACE_DESTROYED) && !(flags & TCL_INTERP_DESTROYED)) { - Tcl_SetVar(interp, msgPtr->textVarName, msgPtr->string, + Tcl_SetVar2(interp, msgPtr->textVarName, NULL, msgPtr->string, TCL_GLOBAL_ONLY); - Tcl_TraceVar(interp, msgPtr->textVarName, + Tcl_TraceVar2(interp, msgPtr->textVarName, NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, MessageTextVarProc, clientData); } return NULL; } - value = Tcl_GetVar(interp, msgPtr->textVarName, TCL_GLOBAL_ONLY); + value = Tcl_GetVar2(interp, msgPtr->textVarName, NULL, TCL_GLOBAL_ONLY); if (value == NULL) { value = ""; } diff --git a/generic/tkObj.c b/generic/tkObj.c index ed947d3..7c09656 100644 --- a/generic/tkObj.c +++ b/generic/tkObj.c @@ -33,7 +33,7 @@ typedef struct PixelRep { (PTR2INT((objPtr)->internalRep.twoPtrValue.ptr1)) #define SET_COMPLEXPIXEL(objPtr, repPtr) \ - (objPtr)->internalRep.twoPtrValue.ptr1 = 0; \ + (objPtr)->internalRep.twoPtrValue.ptr1 = NULL; \ (objPtr)->internalRep.twoPtrValue.ptr2 = repPtr #define GET_COMPLEXPIXEL(objPtr) \ @@ -447,7 +447,7 @@ SetPixelFromAny( double d; int i, units; - string = Tcl_GetStringFromObj(objPtr, NULL); + string = Tcl_GetString(objPtr); d = strtod(string, &rest); if (rest == string) { @@ -553,7 +553,7 @@ Tk_GetMMFromObj( } } - mmPtr = objPtr->internalRep.otherValuePtr; + mmPtr = objPtr->internalRep.twoPtrValue.ptr1; if (mmPtr->tkwin != tkwin) { d = mmPtr->value; if (mmPtr->units == -1) { @@ -592,8 +592,8 @@ static void FreeMMInternalRep( Tcl_Obj *objPtr) /* MM object with internal rep to free. */ { - ckfree(objPtr->internalRep.otherValuePtr); - objPtr->internalRep.otherValuePtr = NULL; + ckfree(objPtr->internalRep.twoPtrValue.ptr1); + objPtr->internalRep.twoPtrValue.ptr1 = NULL; objPtr->typePtr = NULL; } @@ -623,13 +623,13 @@ DupMMInternalRep( MMRep *oldPtr, *newPtr; copyPtr->typePtr = srcPtr->typePtr; - oldPtr = srcPtr->internalRep.otherValuePtr; + oldPtr = srcPtr->internalRep.twoPtrValue.ptr1; newPtr = ckalloc(sizeof(MMRep)); newPtr->value = oldPtr->value; newPtr->units = oldPtr->units; newPtr->tkwin = oldPtr->tkwin; newPtr->returnValue = oldPtr->returnValue; - copyPtr->internalRep.otherValuePtr = newPtr; + copyPtr->internalRep.twoPtrValue.ptr1 = newPtr; } /* @@ -659,7 +659,7 @@ UpdateStringOfMM( char buffer[TCL_DOUBLE_SPACE]; register int len; - mmPtr = objPtr->internalRep.otherValuePtr; + mmPtr = objPtr->internalRep.twoPtrValue.ptr1; /* assert( mmPtr->units == -1 && objPtr->bytes == NULL ); */ if ((mmPtr->units != -1) || (objPtr->bytes != NULL)) { Tcl_Panic("UpdateStringOfMM: false precondition"); @@ -719,13 +719,13 @@ SetMMFromAny( * ints again from mm obj types. */ - (void) Tcl_GetStringFromObj(objPtr, NULL); + (void) Tcl_GetString(objPtr); } else { /* * It wasn't a known int or double, so parse it. */ - string = Tcl_GetStringFromObj(objPtr, NULL); + string = Tcl_GetString(objPtr); d = strtod(string, &rest); if (rest == string) { @@ -782,7 +782,7 @@ SetMMFromAny( mmPtr->tkwin = NULL; mmPtr->returnValue = d; - objPtr->internalRep.otherValuePtr = mmPtr; + objPtr->internalRep.twoPtrValue.ptr1 = mmPtr; return TCL_OK; } @@ -817,14 +817,15 @@ TkGetWindowFromObj( { TkMainInfo *mainPtr = ((TkWindow *) tkwin)->mainPtr; register WindowRep *winPtr; - int result; - result = Tcl_ConvertToType(interp, objPtr, &windowObjType); - if (result != TCL_OK) { - return result; + if (objPtr->typePtr != &windowObjType) { + int result = SetWindowFromAny(interp, objPtr); + if (result != TCL_OK) { + return result; + } } - winPtr = objPtr->internalRep.otherValuePtr; + winPtr = objPtr->internalRep.twoPtrValue.ptr1; if (winPtr->tkwin == NULL || winPtr->mainPtr == NULL || winPtr->mainPtr != mainPtr @@ -834,7 +835,7 @@ TkGetWindowFromObj( */ winPtr->tkwin = Tk_NameToWindow(interp, - Tcl_GetStringFromObj(objPtr, NULL), tkwin); + Tcl_GetString(objPtr), tkwin); if (winPtr->tkwin == NULL) { /* ASSERT: Tk_NameToWindow has left error message in interp */ return TCL_ERROR; @@ -880,7 +881,7 @@ SetWindowFromAny( * Free the old internalRep before setting the new one. */ - Tcl_GetStringFromObj(objPtr, NULL); + (void)Tcl_GetString(objPtr); typePtr = objPtr->typePtr; if ((typePtr != NULL) && (typePtr->freeIntRepProc != NULL)) { typePtr->freeIntRepProc(objPtr); @@ -891,7 +892,7 @@ SetWindowFromAny( winPtr->mainPtr = NULL; winPtr->epoch = 0; - objPtr->internalRep.otherValuePtr = winPtr; + objPtr->internalRep.twoPtrValue.ptr1 = winPtr; objPtr->typePtr = &windowObjType; return TCL_OK; @@ -922,12 +923,12 @@ DupWindowInternalRep( { register WindowRep *oldPtr, *newPtr; - oldPtr = srcPtr->internalRep.otherValuePtr; + oldPtr = srcPtr->internalRep.twoPtrValue.ptr1; newPtr = ckalloc(sizeof(WindowRep)); newPtr->tkwin = oldPtr->tkwin; newPtr->mainPtr = oldPtr->mainPtr; newPtr->epoch = oldPtr->epoch; - copyPtr->internalRep.otherValuePtr = newPtr; + copyPtr->internalRep.twoPtrValue.ptr1 = newPtr; copyPtr->typePtr = srcPtr->typePtr; } @@ -953,8 +954,8 @@ static void FreeWindowInternalRep( Tcl_Obj *objPtr) /* Window object with internal rep to free. */ { - ckfree(objPtr->internalRep.otherValuePtr); - objPtr->internalRep.otherValuePtr = NULL; + ckfree(objPtr->internalRep.twoPtrValue.ptr1); + objPtr->internalRep.twoPtrValue.ptr1 = NULL; objPtr->typePtr = NULL; } @@ -985,7 +986,7 @@ TkNewWindowObj( SetWindowFromAny(NULL, objPtr); - winPtr = objPtr->internalRep.otherValuePtr; + winPtr = objPtr->internalRep.twoPtrValue.ptr1; winPtr->tkwin = tkwin; winPtr->mainPtr = mainPtr; winPtr->epoch = mainPtr->deletionEpoch; diff --git a/generic/tkOldConfig.c b/generic/tkOldConfig.c index 5496076..920d93e 100644 --- a/generic/tkOldConfig.c +++ b/generic/tkOldConfig.c @@ -113,6 +113,10 @@ Tk_ConfigureWidget( staticSpecs = GetCachedSpecs(interp, specs); + for (specPtr = staticSpecs; specPtr->type != TK_CONFIG_END; specPtr++) { + specPtr->specFlags &= ~TK_CONFIG_OPTION_SPECIFIED; + } + /* * Pass one: scan through all of the arguments, processing those that * match entries in the specs. @@ -122,7 +126,7 @@ Tk_ConfigureWidget( const char *arg; if (flags & TK_CONFIG_OBJS) { - arg = Tcl_GetStringFromObj((Tcl_Obj *) *argv, NULL); + arg = Tcl_GetString((Tcl_Obj *) *argv); } else { arg = *argv; } @@ -167,7 +171,6 @@ Tk_ConfigureWidget( if ((specPtr->specFlags & TK_CONFIG_OPTION_SPECIFIED) || (specPtr->argvName == NULL) || (specPtr->type == TK_CONFIG_SYNONYM)) { - specPtr->specFlags &= ~TK_CONFIG_OPTION_SPECIFIED; continue; } if (((specPtr->specFlags & needFlags) != needFlags) @@ -718,7 +721,7 @@ FormatConfigInfo( result = Tcl_Merge(5, argv); if (freeProc != NULL) { if ((freeProc == TCL_DYNAMIC) || (freeProc == (Tcl_FreeProc *) free)) { - ckfree(argv[4]); + ckfree((char *) argv[4]); } else { freeProc((char *) argv[4]); } @@ -939,7 +942,7 @@ Tk_ConfigureValue( Tcl_SetObjResult(interp, Tcl_NewStringObj(result, -1)); if (freeProc != NULL) { if ((freeProc == TCL_DYNAMIC) || (freeProc == (Tcl_FreeProc *) free)) { - ckfree(result); + ckfree((char *) result); } else { freeProc((char *) result); } @@ -1126,7 +1129,6 @@ GetCachedSpecs( specPtr->defValue = Tk_GetUid(specPtr->defValue); } } - specPtr->specFlags &= ~TK_CONFIG_OPTION_SPECIFIED; } } else { cachedSpecs = Tcl_GetHashValue(entryPtr); diff --git a/generic/tkOldTest.c b/generic/tkOldTest.c index b0edf76..df1bb6c 100644 --- a/generic/tkOldTest.c +++ b/generic/tkOldTest.c @@ -81,8 +81,9 @@ static Tk_ImageType imageType = { * Forward declarations for functions defined later in this file: */ -static int ImageCmd(ClientData dummy, - Tcl_Interp *interp, int argc, const char **argv); +static int ImageObjCmd(ClientData dummy, + Tcl_Interp *interp, int objc, + Tcl_Obj * const objv[]); /* @@ -175,7 +176,7 @@ ImageCreate( strcpy(timPtr->imageName, name); timPtr->varName = ckalloc((unsigned) (strlen(varName) + 1)); strcpy(timPtr->varName, varName); - Tcl_CreateCommand(interp, name, ImageCmd, timPtr, NULL); + Tcl_CreateObjCommand(interp, name, ImageObjCmd, timPtr, NULL); *clientDataPtr = timPtr; Tk_ImageChanged(master, 0, 0, 30, 15, 30, 15); return TCL_OK; @@ -184,7 +185,7 @@ ImageCreate( /* *---------------------------------------------------------------------- * - * ImageCmd -- + * ImageObjCmd -- * * This function implements the commands corresponding to individual * images. @@ -200,38 +201,37 @@ ImageCreate( /* ARGSUSED */ static int -ImageCmd( +ImageObjCmd( ClientData clientData, /* Main window for application. */ Tcl_Interp *interp, /* Current interpreter. */ - int argc, /* Number of arguments. */ - const char **argv) /* Argument strings. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument strings. */ { TImageMaster *timPtr = clientData; int x, y, width, height; - if (argc < 2) { - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], "option ?arg ...?", NULL); + if (objc < 2) { + Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?"); return TCL_ERROR; } - if (strcmp(argv[1], "changed") == 0) { - if (argc != 8) { - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " changed x y width height imageWidth imageHeight", NULL); + if (strcmp(Tcl_GetString(objv[1]), "changed") == 0) { + if (objc != 8) { + Tcl_WrongNumArgs(interp, 1, objv, "changed x y width height" + " imageWidth imageHeight"); return TCL_ERROR; } - if ((Tcl_GetInt(interp, argv[2], &x) != TCL_OK) - || (Tcl_GetInt(interp, argv[3], &y) != TCL_OK) - || (Tcl_GetInt(interp, argv[4], &width) != TCL_OK) - || (Tcl_GetInt(interp, argv[5], &height) != TCL_OK) - || (Tcl_GetInt(interp, argv[6], &timPtr->width) != TCL_OK) - || (Tcl_GetInt(interp, argv[7], &timPtr->height) != TCL_OK)) { + if ((Tcl_GetIntFromObj(interp, objv[2], &x) != TCL_OK) + || (Tcl_GetIntFromObj(interp, objv[3], &y) != TCL_OK) + || (Tcl_GetIntFromObj(interp, objv[4], &width) != TCL_OK) + || (Tcl_GetIntFromObj(interp, objv[5], &height) != TCL_OK) + || (Tcl_GetIntFromObj(interp, objv[6], &timPtr->width) != TCL_OK) + || (Tcl_GetIntFromObj(interp, objv[7], &timPtr->height) != TCL_OK)) { return TCL_ERROR; } Tk_ImageChanged(timPtr->master, x, y, width, height, timPtr->width, timPtr->height); } else { - Tcl_AppendResult(interp, "bad option \"", argv[1], + Tcl_AppendResult(interp, "bad option \"", Tcl_GetString(objv[1]), "\": must be changed", NULL); return TCL_ERROR; } @@ -268,7 +268,7 @@ ImageGet( XGCValues gcValues; sprintf(buffer, "%s get", timPtr->imageName); - Tcl_SetVar(timPtr->interp, timPtr->varName, buffer, + Tcl_SetVar2(timPtr->interp, timPtr->varName, NULL, buffer, TCL_GLOBAL_ONLY|TCL_APPEND_VALUE|TCL_LIST_ELEMENT); instPtr = ckalloc(sizeof(TImageInstance)); @@ -315,8 +315,8 @@ ImageDisplay( sprintf(buffer, "%s display %d %d %d %d %d %d", instPtr->masterPtr->imageName, imageX, imageY, width, height, drawableX, drawableY); - Tcl_SetVar(instPtr->masterPtr->interp, instPtr->masterPtr->varName, buffer, - TCL_GLOBAL_ONLY|TCL_APPEND_VALUE|TCL_LIST_ELEMENT); + Tcl_SetVar2(instPtr->masterPtr->interp, instPtr->masterPtr->varName, NULL, + buffer, TCL_GLOBAL_ONLY|TCL_APPEND_VALUE|TCL_LIST_ELEMENT); if (width > (instPtr->masterPtr->width - imageX)) { width = instPtr->masterPtr->width - imageX; } @@ -358,8 +358,8 @@ ImageFree( char buffer[200]; sprintf(buffer, "%s free", instPtr->masterPtr->imageName); - Tcl_SetVar(instPtr->masterPtr->interp, instPtr->masterPtr->varName, buffer, - TCL_GLOBAL_ONLY|TCL_APPEND_VALUE|TCL_LIST_ELEMENT); + Tcl_SetVar2(instPtr->masterPtr->interp, instPtr->masterPtr->varName, NULL, + buffer, TCL_GLOBAL_ONLY|TCL_APPEND_VALUE|TCL_LIST_ELEMENT); Tk_FreeColor(instPtr->fg); Tk_FreeGC(display, instPtr->gc); ckfree(instPtr); @@ -392,7 +392,7 @@ ImageDelete( char buffer[100]; sprintf(buffer, "%s delete", timPtr->imageName); - Tcl_SetVar(timPtr->interp, timPtr->varName, buffer, + Tcl_SetVar2(timPtr->interp, timPtr->varName, NULL, buffer, TCL_GLOBAL_ONLY|TCL_APPEND_VALUE|TCL_LIST_ELEMENT); Tcl_DeleteCommand(timPtr->interp, timPtr->imageName); diff --git a/generic/tkOption.c b/generic/tkOption.c index ec9e465..24e7fb3 100644 --- a/generic/tkOption.c +++ b/generic/tkOption.c @@ -560,7 +560,7 @@ Tk_GetOption( count -= levelPtr[-1].bases[currentStack]; } - if (currentStack && CLASS) { + if (currentStack & CLASS) { nodeId = winClassId; } else { nodeId = winNameId; @@ -631,8 +631,8 @@ Tk_OptionObjCmd( return TCL_ERROR; } - result = Tcl_GetIndexFromObj(interp, objv[1], optionCmds, "option", 0, - &index); + result = Tcl_GetIndexFromObjStruct(interp, objv[1], optionCmds, + sizeof(char *), "option", 0, &index); if (result != TCL_OK) { return result; } @@ -1016,14 +1016,25 @@ AddFromString( Tcl_SetErrorCode(interp, "TK", "OPTIONDB", "NEWLINE", NULL); return TCL_ERROR; } - if ((src[0] == '\\') && (src[1] == '\n')) { - src += 2; - lineNum++; - } else { - *dst = *src; - dst++; - src++; + if (*src == '\\'){ + if (src[1] == '\n') { + src += 2; + lineNum++; + continue; + } else if (src[1] == 'n') { + src += 2; + *dst++ = '\n'; + continue; + } else if (src[1] == '\t' || src[1] == ' ' || src[1] == '\\') { + ++src; + } else if (src[1] >= '0' && src[1] <= '3' && src[2] >= '0' && + src[2] <= '9' && src[3] >= '0' && src[3] <= '9') { + *dst++ = ((src[1]&7)<<6) | ((src[2]&7)<<3) | (src[3]&7); + src += 4; + continue; + } } + *dst++ = *src++; } *dst = 0; @@ -1069,7 +1080,7 @@ ReadOptionFile( * TK_MAX_PRIO. */ { const char *realName; - char *buffer; + Tcl_Obj *buffer; int result, bufferSize; Tcl_Channel chan; Tcl_DString newName; @@ -1097,24 +1108,10 @@ ReadOptionFile( return TCL_ERROR; } - /* - * Compute size of file by seeking to the end of the file. This will - * overallocate if we are performing CRLF translation. - */ - - bufferSize = (int) Tcl_Seek(chan, (Tcl_WideInt) 0, SEEK_END); - Tcl_Seek(chan, (Tcl_WideInt) 0, SEEK_SET); - - if (bufferSize < 0) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "error seeking to end of file \"%s\": %s", - fileName, Tcl_PosixError(interp))); - Tcl_Close(NULL, chan); - return TCL_ERROR; - } - - buffer = ckalloc(bufferSize + 1); - bufferSize = Tcl_Read(chan, buffer, bufferSize); + buffer = Tcl_NewObj(); + Tcl_IncrRefCount(buffer); + Tcl_SetChannelOption(NULL, chan, "-encoding", "utf-8"); + bufferSize = Tcl_ReadChars(chan, buffer, -1, 0); if (bufferSize < 0) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "error reading file \"%s\": %s", @@ -1123,9 +1120,8 @@ ReadOptionFile( return TCL_ERROR; } Tcl_Close(NULL, chan); - buffer[bufferSize] = 0; - result = AddFromString(interp, tkwin, buffer, priority); - ckfree(buffer); + result = AddFromString(interp, tkwin, Tcl_GetString(buffer), priority); + Tcl_DecrRefCount(buffer); return result; } diff --git a/generic/tkPack.c b/generic/tkPack.c index 134b61f..88a4b2d 100644 --- a/generic/tkPack.c +++ b/generic/tkPack.c @@ -88,7 +88,7 @@ typedef struct Packer { * Tk will set its requested size to fit the * needs of its slaves. * ALLOCED_MASTER 1 means that Pack has allocated itself as - * geometry master for this window. + * geometry master for this window. */ #define REQUESTED_REPACK 1 @@ -120,7 +120,7 @@ static const Tk_GeomMgr packerType = { static void ArrangePacking(ClientData clientData); static int ConfigureSlaves(Tcl_Interp *interp, Tk_Window tkwin, int objc, Tcl_Obj *const objv[]); -static void DestroyPacker(char *memPtr); +static void DestroyPacker(void *memPtr); static Packer * GetPacker(Tk_Window tkwin); static int PackAfter(Tcl_Interp *interp, Packer *prevPtr, Packer *masterPtr, int objc,Tcl_Obj *const objv[]); @@ -217,8 +217,8 @@ Tk_PackObjCmd( return TCL_ERROR; } - if (Tcl_GetIndexFromObj(interp, objv[1], optionStrings, "option", 0, - &index) != TCL_OK) { + if (Tcl_GetIndexFromObjStruct(interp, objv[1], optionStrings, + sizeof(char *), "option", 0, &index) != TCL_OK) { /* * Call it again without the deprecated ones to get a proper error * message. This works well since there can't be any ambiguity between @@ -226,8 +226,8 @@ Tk_PackObjCmd( */ Tcl_ResetResult(interp); - Tcl_GetIndexFromObj(interp, objv[1], &optionStrings[4], "option", 0, - &index); + Tcl_GetIndexFromObjStruct(interp, objv[1], &optionStrings[4], + sizeof(char *), "option", 0, &index); return TCL_ERROR; } @@ -409,7 +409,7 @@ Tk_PackObjCmd( if (masterPtr->slavePtr != NULL) { if (TkSetGeometryMaster(interp, master, "pack") != TCL_OK) { - return TCL_ERROR; + return TCL_ERROR; } masterPtr->flags |= ALLOCED_MASTER; } @@ -1101,7 +1101,6 @@ PackAfter( { register Packer *packPtr; Tk_Window tkwin, ancestor, parent; - int length; Tcl_Obj **options; int index, optionCount, c; @@ -1170,24 +1169,25 @@ PackAfter( packPtr->flags |= OLD_STYLE; for (index = 0 ; index < optionCount; index++) { Tcl_Obj *curOptPtr = options[index]; - const char *curOpt = Tcl_GetStringFromObj(curOptPtr, &length); + const char *curOpt = Tcl_GetString(curOptPtr); + size_t length = curOptPtr->length; c = curOpt[0]; if ((c == 't') - && (strncmp(curOpt, "top", (size_t) length)) == 0) { + && (strncmp(curOpt, "top", length)) == 0) { packPtr->side = TOP; } else if ((c == 'b') - && (strncmp(curOpt, "bottom", (size_t) length)) == 0) { + && (strncmp(curOpt, "bottom", length)) == 0) { packPtr->side = BOTTOM; } else if ((c == 'l') - && (strncmp(curOpt, "left", (size_t) length)) == 0) { + && (strncmp(curOpt, "left", length)) == 0) { packPtr->side = LEFT; } else if ((c == 'r') - && (strncmp(curOpt, "right", (size_t) length)) == 0) { + && (strncmp(curOpt, "right", length)) == 0) { packPtr->side = RIGHT; } else if ((c == 'e') - && (strncmp(curOpt, "expand", (size_t) length)) == 0) { + && (strncmp(curOpt, "expand", length)) == 0) { packPtr->flags |= EXPAND; } else if ((c == 'f') && (strcmp(curOpt, "fill")) == 0) { @@ -1287,7 +1287,7 @@ PackAfter( != TCL_OK) { Tk_ManageGeometry(tkwin, NULL, NULL); Unlink(packPtr); - return TCL_ERROR; + return TCL_ERROR; } masterPtr->flags |= ALLOCED_MASTER; } @@ -1389,10 +1389,10 @@ Unlink( static void DestroyPacker( - char *memPtr) /* Info about packed window that is now + void *memPtr) /* Info about packed window that is now * dead. */ { - register Packer *packPtr = (Packer *) memPtr; + register Packer *packPtr = memPtr; ckfree(packPtr); } @@ -1463,7 +1463,7 @@ PackStructureProc( Tcl_CancelIdleCall(ArrangePacking, packPtr); } packPtr->tkwin = NULL; - Tcl_EventuallyFree(packPtr, DestroyPacker); + Tcl_EventuallyFree(packPtr, (Tcl_FreeProc *) DestroyPacker); } else if (eventPtr->type == MapNotify) { /* * When a master gets mapped, must redo the geometry computation so @@ -1593,8 +1593,8 @@ ConfigureSlaves( Tcl_SetErrorCode(interp, "TK", "PACK", "BAD_PARAMETER", NULL); return TCL_ERROR; } - if (Tcl_GetIndexFromObj(interp, objv[i], optionStrings, "option", - 0, &index) != TCL_OK) { + if (Tcl_GetIndexFromObjStruct(interp, objv[i], optionStrings, + sizeof(char *), "option", 0, &index) != TCL_OK) { return TCL_ERROR; } @@ -1725,8 +1725,8 @@ ConfigureSlaves( } break; case CONF_SIDE: - if (Tcl_GetIndexFromObj(interp, objv[i+1], sideNames, "side", - TCL_EXACT, &side) != TCL_OK) { + if (Tcl_GetIndexFromObjStruct(interp, objv[i+1], sideNames, + sizeof(char *), "side", TCL_EXACT, &side) != TCL_OK) { return TCL_ERROR; } slavePtr->side = (Side) side; @@ -1829,7 +1829,7 @@ ConfigureSlaves( != TCL_OK) { Tk_ManageGeometry(slave, NULL, NULL); Unlink(slavePtr); - return TCL_ERROR; + return TCL_ERROR; } masterPtr->flags |= ALLOCED_MASTER; } diff --git a/generic/tkPanedWindow.c b/generic/tkPanedWindow.c index 4a4af53..2451647 100644 --- a/generic/tkPanedWindow.c +++ b/generic/tkPanedWindow.c @@ -147,6 +147,10 @@ typedef struct PanedWindow { GC gc; /* Graphics context for copying from * off-screen pixmap onto screen. */ int proxyx, proxyy; /* Proxy x,y coordinates. */ + Tk_3DBorder proxyBackground;/* Background color used to draw proxy. If NULL, use background. */ + Tcl_Obj *proxyBorderWidthPtr; /* Tcl_Obj rep for proxyBorderWidth */ + int proxyBorderWidth; /* Borderwidth used to draw proxy. */ + int proxyRelief; /* Relief used to draw proxy, if TK_RELIEF_NULL then use relief. */ Slave **slaves; /* Pointer to array of Slaves. */ int numSlaves; /* Number of slaves. */ int sizeofSlaves; /* Number of elements in the slaves array. */ @@ -203,6 +207,8 @@ static void PanedWindowReqProc(ClientData clientData, static void ArrangePanes(ClientData clientData); static void Unlink(Slave *slavePtr); static Slave * GetPane(PanedWindow *pwPtr, Tk_Window tkwin); +static void GetFirstLastVisiblePane(PanedWindow *pwPtr, + int *firstPtr, int *lastPtr); static void SlaveStructureProc(ClientData clientData, XEvent *eventPtr); static int PanedWindowSashCommand(PanedWindow *pwPtr, @@ -296,6 +302,15 @@ static const Tk_OptionSpec optionSpecs[] = { {TK_OPTION_STRING_TABLE, "-orient", "orient", "Orient", DEF_PANEDWINDOW_ORIENT, -1, Tk_Offset(PanedWindow, orient), 0, orientStrings, GEOMETRY}, + {TK_OPTION_BORDER, "-proxybackground", "proxyBackground", "ProxyBackground", + 0, -1, Tk_Offset(PanedWindow, proxyBackground), TK_OPTION_NULL_OK, + (ClientData) DEF_PANEDWINDOW_BG_MONO}, + {TK_OPTION_PIXELS, "-proxyborderwidth", "proxyBorderWidth", "ProxyBorderWidth", + DEF_PANEDWINDOW_PROXYBORDER, Tk_Offset(PanedWindow, proxyBorderWidthPtr), + Tk_Offset(PanedWindow, proxyBorderWidth), 0, 0, GEOMETRY}, + {TK_OPTION_RELIEF, "-proxyrelief", "proxyRelief", "Relief", + 0, -1, Tk_Offset(PanedWindow, proxyRelief), + TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_RELIEF, "-relief", "relief", "Relief", DEF_PANEDWINDOW_RELIEF, -1, Tk_Offset(PanedWindow, relief), 0, 0, 0}, {TK_OPTION_CURSOR, "-sashcursor", "sashCursor", "Cursor", @@ -384,7 +399,7 @@ Tk_PanedWindowObjCmd( } tkwin = Tk_CreateWindowFromPath(interp, Tk_MainWindow(interp), - Tcl_GetStringFromObj(objv[1], NULL), NULL); + Tcl_GetString(objv[1]), NULL); if (tkwin == NULL) { return TCL_ERROR; } @@ -682,6 +697,15 @@ PanedWindowWidgetObjCmd( if (objc <= 4) { tkwin = Tk_NameToWindow(interp, Tcl_GetString(objv[2]), pwPtr->tkwin); + if (tkwin == NULL) { + /* + * Just a plain old bad window; Tk_NameToWindow filled in an + * error message for us. + */ + + result = TCL_ERROR; + break; + } for (i = 0; i < pwPtr->numSlaves; i++) { if (pwPtr->slaves[i]->tkwin == tkwin) { resultObj = Tk_GetOptionInfo(interp, @@ -1329,6 +1353,7 @@ PanedWindowEventProc( XEvent *eventPtr) /* Information about event. */ { PanedWindow *pwPtr = clientData; + int i; if (eventPtr->type == Expose) { if (pwPtr->tkwin != NULL && !(pwPtr->flags & REDRAW_PENDING)) { @@ -1343,6 +1368,14 @@ PanedWindowEventProc( } } else if (eventPtr->type == DestroyNotify) { DestroyPanedWindow(pwPtr); + } else if (eventPtr->type == UnmapNotify) { + for (i = 0; i < pwPtr->numSlaves; i++) { + Tk_UnmapWindow(pwPtr->slaves[i]->tkwin); + } + } else if (eventPtr->type == MapNotify) { + for (i = 0; i < pwPtr->numSlaves; i++) { + Tk_MapWindow(pwPtr->slaves[i]->tkwin); + } } } @@ -1411,6 +1444,7 @@ DisplayPanedWindow( Tk_Window tkwin = pwPtr->tkwin; int i, sashWidth, sashHeight; const int horizontal = (pwPtr->orient == ORIENT_HORIZONTAL); + int first, last; pwPtr->flags &= ~REDRAW_PENDING; if ((pwPtr->tkwin == NULL) || !Tk_IsMapped(tkwin)) { @@ -1457,9 +1491,10 @@ DisplayPanedWindow( * Draw the sashes. */ + GetFirstLastVisiblePane(pwPtr, &first, &last); for (i = 0; i < pwPtr->numSlaves - 1; i++) { slavePtr = pwPtr->slaves[i]; - if (slavePtr->hide) { + if (slavePtr->hide || i == last) { continue; } if (sashWidth > 0 && sashHeight > 0) { @@ -1705,17 +1740,10 @@ ArrangePanes( Tcl_Preserve(pwPtr); /* - * Find index of last visible pane. + * Find index of first and last visible panes. */ - for (i = 0, last = 0, first = -1; i < pwPtr->numSlaves; i++) { - if (pwPtr->slaves[i]->hide == 0) { - if (first < 0) { - first = i; - } - last = i; - } - } + GetFirstLastVisiblePane(pwPtr, &first, &last); /* * First pass; compute sizes @@ -2053,6 +2081,41 @@ GetPane( } /* + *---------------------------------------------------------------------- + * + * GetFirstLastVisiblePane -- + * + * Given panedwindow, find the index of the first and last visible panes + * of that paned window. + * + * Results: + * Index of the first and last visible panes. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static void +GetFirstLastVisiblePane( + PanedWindow *pwPtr, /* Pointer to the paned window info. */ + int *firstPtr, /* Returned index for first. */ + int *lastPtr) /* Returned index for last. */ +{ + int i; + + for (i = 0, *lastPtr = 0, *firstPtr = -1; i < pwPtr->numSlaves; i++) { + if (pwPtr->slaves[i]->hide == 0) { + if (*firstPtr < 0) { + *firstPtr = i; + } + *lastPtr = i; + } + } +} + +/* *-------------------------------------------------------------- * * SlaveStructureProc -- @@ -2553,7 +2616,7 @@ MoveSash( slavePtr->paneWidth = slavePtr->width = slavePtr->sashx - sashOffset - slavePtr->x - (2 * slavePtr->padx); } else { - slavePtr->paneWidth = slavePtr->height = slavePtr->sashy + slavePtr->paneHeight = slavePtr->height = slavePtr->sashy - sashOffset - slavePtr->y - (2 * slavePtr->pady); } } @@ -2726,8 +2789,10 @@ DisplayProxyWindow( * Redraw the widget's background and border. */ - Tk_Fill3DRectangle(tkwin, pixmap, pwPtr->background, 0, 0, - Tk_Width(tkwin), Tk_Height(tkwin), 2, pwPtr->sashRelief); + Tk_Fill3DRectangle(tkwin, pixmap, + pwPtr->proxyBackground ? pwPtr->proxyBackground : pwPtr->background, + 0, 0, Tk_Width(tkwin), Tk_Height(tkwin), pwPtr->proxyBorderWidth, + (pwPtr->proxyRelief != TK_RELIEF_NULL) ? pwPtr->proxyRelief : pwPtr->sashRelief); #ifndef TK_NO_DOUBLE_BUFFERING /* @@ -2771,6 +2836,7 @@ PanedWindowProxyCommand( PROXY_COORD, PROXY_FORGET, PROXY_PLACE }; int index, x, y, sashWidth, sashHeight; + int internalBW, pwWidth, pwHeight; Tcl_Obj *coords[2]; if (objc < 3) { @@ -2820,11 +2886,16 @@ PanedWindowProxyCommand( return TCL_ERROR; } + internalBW = Tk_InternalBorderWidth(pwPtr->tkwin); if (pwPtr->orient == ORIENT_HORIZONTAL) { if (x < 0) { x = 0; } - y = Tk_InternalBorderWidth(pwPtr->tkwin); + pwWidth = Tk_Width(pwPtr->tkwin) - (2 * internalBW); + if (x > pwWidth) { + x = pwWidth; + } + y = Tk_InternalBorderWidth(pwPtr->tkwin); sashWidth = pwPtr->sashWidth; sashHeight = Tk_Height(pwPtr->tkwin) - (2 * Tk_InternalBorderWidth(pwPtr->tkwin)); @@ -2832,6 +2903,10 @@ PanedWindowProxyCommand( if (y < 0) { y = 0; } + pwHeight = Tk_Height(pwPtr->tkwin) - (2 * internalBW); + if (y > pwHeight) { + y = pwHeight; + } x = Tk_InternalBorderWidth(pwPtr->tkwin); sashHeight = pwPtr->sashWidth; sashWidth = Tk_Width(pwPtr->tkwin) - @@ -2905,7 +2980,7 @@ ObjectIsEmpty( if (objPtr->bytes != NULL) { return (objPtr->length == 0); } - Tcl_GetStringFromObj(objPtr, &length); + (void)Tcl_GetStringFromObj(objPtr, &length); return (length == 0); } @@ -2966,6 +3041,7 @@ PanedWindowIdentifyCoords( { int i, sashHeight, sashWidth, thisx, thisy; int found, isHandle, lpad, rpad, tpad, bpad; + int first, last; if (pwPtr->orient == ORIENT_HORIZONTAL) { if (Tk_IsMapped(pwPtr->tkwin)) { @@ -3005,10 +3081,11 @@ PanedWindowIdentifyCoords( lpad = rpad = 0; } + GetFirstLastVisiblePane(pwPtr, &first, &last); isHandle = 0; found = -1; for (i = 0; i < pwPtr->numSlaves - 1; i++) { - if (pwPtr->slaves[i]->hide) { + if (pwPtr->slaves[i]->hide || i == last) { continue; } thisx = pwPtr->slaves[i]->sashx; diff --git a/generic/tkPlace.c b/generic/tkPlace.c index afba488..9fa406a 100644 --- a/generic/tkPlace.c +++ b/generic/tkPlace.c @@ -276,8 +276,8 @@ Tk_PlaceObjCmd( dispPtr->placeInit = 1; } - if (Tcl_GetIndexFromObj(interp, objv[1], optionStrings, "option", 0, - &index) != TCL_OK) { + if (Tcl_GetIndexFromObjStruct(interp, objv[1], optionStrings, + sizeof(char *), "option", 0, &index) != TCL_OK) { return TCL_ERROR; } diff --git a/generic/tkPlatDecls.h b/generic/tkPlatDecls.h index 057d38c..1e69c88 100644 --- a/generic/tkPlatDecls.h +++ b/generic/tkPlatDecls.h @@ -29,11 +29,15 @@ extern "C" { /* !BEGIN!: Do not edit below this line. */ +#ifdef __cplusplus +extern "C" { +#endif + /* * Exported function declarations: */ -#if defined(__WIN32__) || defined(__CYGWIN__) /* WIN */ +#if defined(_WIN32) || defined(__CYGWIN__) /* WIN */ /* 0 */ EXTERN Window Tk_AttachHWND(Tk_Window tkwin, HWND hwnd); /* 1 */ @@ -82,9 +86,9 @@ EXTERN int Tk_MacOSXIsAppInFront(void); typedef struct TkPlatStubs { int magic; - const struct TkPlatStubHooks *hooks; + void *hooks; -#if defined(__WIN32__) || defined(__CYGWIN__) /* WIN */ +#if defined(_WIN32) || defined(__CYGWIN__) /* WIN */ Window (*tk_AttachHWND) (Tk_Window tkwin, HWND hwnd); /* 0 */ HINSTANCE (*tk_GetHINSTANCE) (void); /* 1 */ HWND (*tk_GetHWND) (Window window); /* 2 */ @@ -107,10 +111,8 @@ typedef struct TkPlatStubs { #endif /* AQUA */ } TkPlatStubs; -#ifdef __cplusplus -extern "C" { -#endif extern const TkPlatStubs *tkPlatStubsPtr; + #ifdef __cplusplus } #endif @@ -121,7 +123,7 @@ extern const TkPlatStubs *tkPlatStubsPtr; * Inline function declarations: */ -#if defined(__WIN32__) || defined(__CYGWIN__) /* WIN */ +#if defined(_WIN32) || defined(__CYGWIN__) /* WIN */ #define Tk_AttachHWND \ (tkPlatStubsPtr->tk_AttachHWND) /* 0 */ #define Tk_GetHINSTANCE \ diff --git a/generic/tkPointer.c b/generic/tkPointer.c index 451373d..0141b64 100644 --- a/generic/tkPointer.c +++ b/generic/tkPointer.c @@ -14,7 +14,7 @@ #include "tkInt.h" -#ifdef __WIN32__ +#ifdef _WIN32 #include "tkWinInt.h" #endif diff --git a/generic/tkRectOval.c b/generic/tkRectOval.c index a51ca33..50b5f1a 100644 --- a/generic/tkRectOval.c +++ b/generic/tkRectOval.c @@ -671,11 +671,11 @@ ComputeRectOvalBbox( * correct place to solve it, but it works. */ -#ifdef __WIN32__ +#ifdef _WIN32 bloat = 1; #else bloat = 0; -#endif /* __WIN32__ */ +#endif /* _WIN32 */ } else { #ifdef MAC_OSX_TK /* diff --git a/generic/tkScale.c b/generic/tkScale.c index 3ca4a67..cc7c294 100644 --- a/generic/tkScale.c +++ b/generic/tkScale.c @@ -340,8 +340,8 @@ ScaleWidgetObjCmd( Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?"); return TCL_ERROR; } - result = Tcl_GetIndexFromObj(interp, objv[1], commandNames, - "option", 0, &index); + result = Tcl_GetIndexFromObjStruct(interp, objv[1], commandNames, + sizeof(char *), "option", 0, &index); if (result != TCL_OK) { return result; } @@ -504,8 +504,8 @@ DestroyScale( */ if (scalePtr->varNamePtr != NULL) { - Tcl_UntraceVar(scalePtr->interp, Tcl_GetString(scalePtr->varNamePtr), - TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, + Tcl_UntraceVar2(scalePtr->interp, Tcl_GetString(scalePtr->varNamePtr), + NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, ScaleVarProc, scalePtr); } if (scalePtr->troughGC != None) { @@ -561,8 +561,8 @@ ConfigureScale( */ if (scalePtr->varNamePtr != NULL) { - Tcl_UntraceVar(interp, Tcl_GetString(scalePtr->varNamePtr), - TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, + Tcl_UntraceVar2(interp, Tcl_GetString(scalePtr->varNamePtr), + NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, ScaleVarProc, scalePtr); } @@ -677,8 +677,8 @@ ConfigureScale( ScaleSetVariable(scalePtr); } } - Tcl_TraceVar(interp, Tcl_GetString(scalePtr->varNamePtr), - TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, + Tcl_TraceVar2(interp, Tcl_GetString(scalePtr->varNamePtr), + NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, ScaleVarProc, scalePtr); } @@ -800,6 +800,9 @@ ComputeFormat( */ numDigits = scalePtr->digits; + if (numDigits > TCL_MAX_PREC) { + numDigits = 0; + } if (numDigits <= 0) { if (scalePtr->resolution > 0) { /* @@ -880,7 +883,7 @@ static void ComputeScaleGeometry( register TkScale *scalePtr) /* Information about widget. */ { - char valueString[PRINT_CHARS]; + char valueString[TCL_DOUBLE_SPACE]; int tmp, valuePixels, x, y, extraSpace; Tk_FontMetrics fm; @@ -1180,8 +1183,8 @@ ScaleVarProc( if (flags & TCL_TRACE_UNSETS) { if ((flags & TCL_TRACE_DESTROYED) && !(flags & TCL_INTERP_DESTROYED)) { - Tcl_TraceVar(interp, Tcl_GetString(scalePtr->varNamePtr), - TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, + Tcl_TraceVar2(interp, Tcl_GetString(scalePtr->varNamePtr), + NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, ScaleVarProc, clientData); scalePtr->flags |= NEVER_SET; TkScaleSetValue(scalePtr, scalePtr->value, 1, 0); @@ -1296,7 +1299,7 @@ ScaleSetVariable( register TkScale *scalePtr) /* Info about widget. */ { if (scalePtr->varNamePtr != NULL) { - char string[PRINT_CHARS]; + char string[TCL_DOUBLE_SPACE]; sprintf(string, scalePtr->format, scalePtr->value); scalePtr->flags |= SETTING_VAR; diff --git a/generic/tkScale.h b/generic/tkScale.h index af35978..4fd9995 100644 --- a/generic/tkScale.h +++ b/generic/tkScale.h @@ -215,12 +215,6 @@ typedef struct TkScale { #define SPACING 2 /* - * How many characters of space to provide when formatting the scale's value: - */ - -#define PRINT_CHARS 150 - -/* * Declaration of procedures used in the implementation of the scale widget. */ diff --git a/generic/tkScrollbar.c b/generic/tkScrollbar.c index 2d91db6..5017d30 100644 --- a/generic/tkScrollbar.c +++ b/generic/tkScrollbar.c @@ -12,10 +12,6 @@ * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ -/* - * TODO: Convert scrollbars to the Tcl_Obj API. - */ - #include "tkInt.h" #include "tkScrollbar.h" #include "default.h" @@ -101,16 +97,16 @@ static const Tk_ConfigSpec configSpecs[] = { */ static int ConfigureScrollbar(Tcl_Interp *interp, - TkScrollbar *scrollPtr, int argc, - const char **argv, int flags); + TkScrollbar *scrollPtr, int objc, + Tcl_Obj *const objv[], int flags); static void ScrollbarCmdDeletedProc(ClientData clientData); -static int ScrollbarWidgetCmd(ClientData clientData, - Tcl_Interp *, int argc, const char **argv); +static int ScrollbarWidgetObjCmd(ClientData clientData, + Tcl_Interp *, int objc, Tcl_Obj *const objv[]); /* *-------------------------------------------------------------- * - * Tk_ScrollbarCmd -- + * Tk_ScrollbarObjCmd -- * * This function is invoked to process the "scrollbar" Tcl command. See * the user documentation for details on what it does. @@ -125,25 +121,22 @@ static int ScrollbarWidgetCmd(ClientData clientData, */ int -Tk_ScrollbarCmd( +Tk_ScrollbarObjCmd( ClientData clientData, /* Main window associated with interpreter. */ Tcl_Interp *interp, /* Current interpreter. */ - int argc, /* Number of arguments. */ - const char **argv) /* Argument strings. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument strings. */ { Tk_Window tkwin = clientData; register TkScrollbar *scrollPtr; Tk_Window newWin; - if (argc < 2) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "wrong # args: should be \"%s pathName ?-option value ...?\"", - argv[0])); - Tcl_SetErrorCode(interp, "TCL", "WRONGARGS", NULL); + if (objc < 2) { + Tcl_WrongNumArgs(interp, 1, objv, "pathName ?-option value ...?"); return TCL_ERROR; } - newWin = Tk_CreateWindowFromPath(interp, tkwin, argv[1], NULL); + newWin = Tk_CreateWindowFromPath(interp, tkwin, Tcl_GetString(objv[1]), NULL); if (newWin == NULL) { return TCL_ERROR; } @@ -162,8 +155,8 @@ Tk_ScrollbarCmd( scrollPtr->tkwin = newWin; scrollPtr->display = Tk_Display(newWin); scrollPtr->interp = interp; - scrollPtr->widgetCmd = Tcl_CreateCommand(interp, - Tk_PathName(scrollPtr->tkwin), ScrollbarWidgetCmd, + scrollPtr->widgetCmd = Tcl_CreateObjCommand(interp, + Tk_PathName(scrollPtr->tkwin), ScrollbarWidgetObjCmd, scrollPtr, ScrollbarCmdDeletedProc); scrollPtr->vertical = 0; scrollPtr->width = 0; @@ -196,7 +189,7 @@ Tk_ScrollbarCmd( scrollPtr->takeFocus = NULL; scrollPtr->flags = 0; - if (ConfigureScrollbar(interp, scrollPtr, argc-2, argv+2, 0) != TCL_OK) { + if (ConfigureScrollbar(interp, scrollPtr, objc-2, objv+2, 0) != TCL_OK) { Tk_DestroyWindow(scrollPtr->tkwin); return TCL_ERROR; } @@ -208,7 +201,7 @@ Tk_ScrollbarCmd( /* *-------------------------------------------------------------- * - * ScrollbarWidgetCmd -- + * ScrollbarWidgetObjCmd -- * * This function is invoked to process the Tcl command that corresponds * to a widget managed by this module. See the user documentation for @@ -224,30 +217,44 @@ Tk_ScrollbarCmd( */ static int -ScrollbarWidgetCmd( +ScrollbarWidgetObjCmd( ClientData clientData, /* Information about scrollbar widget. */ Tcl_Interp *interp, /* Current interpreter. */ - int argc, /* Number of arguments. */ - const char **argv) /* Argument strings. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument strings. */ { register TkScrollbar *scrollPtr = clientData; int result = TCL_OK; - size_t length; - int c; - - if (argc < 2) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "wrong # args: should be \"%s option ?arg ...?\"", argv[0])); - Tcl_SetErrorCode(interp, "TCL", "WRONGARGS", NULL); + int length, cmdIndex; + static const char *const commandNames[] = { + "activate", "cget", "configure", "delta", "fraction", + "get", "identify", "set", NULL + }; + enum command { + COMMAND_ACTIVATE, COMMAND_CGET, COMMAND_CONFIGURE, COMMAND_DELTA, + COMMAND_FRACTION, COMMAND_GET, COMMAND_IDENTIFY, COMMAND_SET + }; + + if (objc < 2) { + Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?"); return TCL_ERROR; } + /* + * Parse the command by looking up the second argument in the list of + * valid subcommand names + */ + + result = Tcl_GetIndexFromObj(interp, objv[1], commandNames, + "option", 0, &cmdIndex); + if (result != TCL_OK) { + return result; + } Tcl_Preserve(scrollPtr); - c = argv[1][0]; - length = strlen(argv[1]); - if ((c == 'a') && (strncmp(argv[1], "activate", length) == 0)) { - int oldActiveField; + switch (cmdIndex) { + case COMMAND_ACTIVATE: { + int oldActiveField, c; - if (argc == 2) { + if (objc == 2) { const char *zone = ""; switch (scrollPtr->activeField) { @@ -258,21 +265,17 @@ ScrollbarWidgetCmd( Tcl_SetObjResult(interp, Tcl_NewStringObj(zone, -1)); goto done; } - if (argc != 3) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "wrong # args: should be \"%s activate element\"", - argv[0])); - Tcl_SetErrorCode(interp, "TCL", "WRONGARGS", NULL); + if (objc != 3) { + Tcl_WrongNumArgs(interp, 1, objv, "activate element"); goto error; } - c = argv[2][0]; - length = strlen(argv[2]); + c = Tcl_GetStringFromObj(objv[2], &length)[0]; oldActiveField = scrollPtr->activeField; - if ((c == 'a') && (strcmp(argv[2], "arrow1") == 0)) { + if ((c == 'a') && (strcmp(Tcl_GetString(objv[2]), "arrow1") == 0)) { scrollPtr->activeField = TOP_ARROW; - } else if ((c == 'a') && (strcmp(argv[2], "arrow2") == 0)) { + } else if ((c == 'a') && (strcmp(Tcl_GetString(objv[2]), "arrow2") == 0)) { scrollPtr->activeField = BOTTOM_ARROW; - } else if ((c == 's') && (strncmp(argv[2], "slider", length) == 0)) { + } else if ((c == 's') && (strncmp(Tcl_GetString(objv[2]), "slider", length) == 0)) { scrollPtr->activeField = SLIDER; } else { scrollPtr->activeField = OUTSIDE; @@ -280,41 +283,40 @@ ScrollbarWidgetCmd( if (oldActiveField != scrollPtr->activeField) { TkScrollbarEventuallyRedraw(scrollPtr); } - } else if ((c == 'c') && (strncmp(argv[1], "cget", length) == 0) - && (length >= 2)) { - if (argc != 3) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "wrong # args: should be \"%s cget option\"", argv[0])); - Tcl_SetErrorCode(interp, "TCL", "WRONGARGS", NULL); + break; + } + case COMMAND_CGET: { + if (objc != 3) { + Tcl_WrongNumArgs(interp, 1, objv, "cget option"); goto error; } result = Tk_ConfigureValue(interp, scrollPtr->tkwin, - configSpecs, (char *) scrollPtr, argv[2], 0); - } else if ((c == 'c') && (strncmp(argv[1], "configure", length) == 0) - && (length >= 2)) { - if (argc == 2) { + configSpecs, (char *) scrollPtr, Tcl_GetString(objv[2]), 0); + break; + } + case COMMAND_CONFIGURE: { + if (objc == 2) { result = Tk_ConfigureInfo(interp, scrollPtr->tkwin, configSpecs, (char *) scrollPtr, NULL, 0); - } else if (argc == 3) { + } else if (objc == 3) { result = Tk_ConfigureInfo(interp, scrollPtr->tkwin, - configSpecs, (char *) scrollPtr, argv[2], 0); + configSpecs, (char *) scrollPtr, Tcl_GetString(objv[2]), 0); } else { - result = ConfigureScrollbar(interp, scrollPtr, argc-2, argv+2, - TK_CONFIG_ARGV_ONLY); + result = ConfigureScrollbar(interp, scrollPtr, objc-2, + objv+2, TK_CONFIG_ARGV_ONLY); } - } else if ((c == 'd') && (strncmp(argv[1], "delta", length) == 0)) { + break; + } + case COMMAND_DELTA: { int xDelta, yDelta, pixels, length; double fraction; - if (argc != 4) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "wrong # args: should be \"%s delta xDelta yDelta\"", - argv[0])); - Tcl_SetErrorCode(interp, "TCL", "WRONGARGS", NULL); + if (objc != 4) { + Tcl_WrongNumArgs(interp, 1, objv, "delta xDelta yDelta"); goto error; } - if ((Tcl_GetInt(interp, argv[2], &xDelta) != TCL_OK) - || (Tcl_GetInt(interp, argv[3], &yDelta) != TCL_OK)) { + if ((Tcl_GetIntFromObj(interp, objv[2], &xDelta) != TCL_OK) + || (Tcl_GetIntFromObj(interp, objv[3], &yDelta) != TCL_OK)) { goto error; } if (scrollPtr->vertical) { @@ -332,18 +334,18 @@ ScrollbarWidgetCmd( fraction = ((double) pixels / (double) length); } Tcl_SetObjResult(interp, Tcl_NewDoubleObj(fraction)); - } else if ((c == 'f') && (strncmp(argv[1], "fraction", length) == 0)) { + break; + } + case COMMAND_FRACTION: { int x, y, pos, length; double fraction; - if (argc != 4) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "wrong # args: should be \"%s fraction x y\"", argv[0])); - Tcl_SetErrorCode(interp, "TCL", "WRONGARGS", NULL); + if (objc != 4) { + Tcl_WrongNumArgs(interp, 1, objv, "fraction x y"); goto error; } - if ((Tcl_GetInt(interp, argv[2], &x) != TCL_OK) - || (Tcl_GetInt(interp, argv[3], &y) != TCL_OK)) { + if ((Tcl_GetIntFromObj(interp, objv[2], &x) != TCL_OK) + || (Tcl_GetIntFromObj(interp, objv[3], &y) != TCL_OK)) { goto error; } if (scrollPtr->vertical) { @@ -366,13 +368,13 @@ ScrollbarWidgetCmd( fraction = 1.0; } Tcl_SetObjResult(interp, Tcl_NewDoubleObj(fraction)); - } else if ((c == 'g') && (strncmp(argv[1], "get", length) == 0)) { + break; + } + case COMMAND_GET: { Tcl_Obj *resObjs[4]; - if (argc != 2) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "wrong # args: should be \"%s get\"", argv[0])); - Tcl_SetErrorCode(interp, "TCL", "WRONGARGS", NULL); + if (objc != 2) { + Tcl_WrongNumArgs(interp, 1, objv, "get"); goto error; } if (scrollPtr->flags & NEW_STYLE_COMMANDS) { @@ -386,18 +388,18 @@ ScrollbarWidgetCmd( resObjs[3] = Tcl_NewIntObj(scrollPtr->lastUnit); Tcl_SetObjResult(interp, Tcl_NewListObj(4, resObjs)); } - } else if ((c == 'i') && (strncmp(argv[1], "identify", length) == 0)) { + break; + } + case COMMAND_IDENTIFY: { int x, y; const char *zone = ""; - if (argc != 4) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "wrong # args: should be \"%s identify x y\"", argv[0])); - Tcl_SetErrorCode(interp, "TCL", "WRONGARGS", NULL); + if (objc != 4) { + Tcl_WrongNumArgs(interp, 1, objv, "identify x y"); goto error; } - if ((Tcl_GetInt(interp, argv[2], &x) != TCL_OK) - || (Tcl_GetInt(interp, argv[3], &y) != TCL_OK)) { + if ((Tcl_GetIntFromObj(interp, objv[2], &x) != TCL_OK) + || (Tcl_GetIntFromObj(interp, objv[3], &y) != TCL_OK)) { goto error; } switch (TkpScrollbarPosition(scrollPtr, x, y)) { @@ -408,16 +410,18 @@ ScrollbarWidgetCmd( case BOTTOM_ARROW: zone = "arrow2"; break; } Tcl_SetObjResult(interp, Tcl_NewStringObj(zone, -1)); - } else if ((c == 's') && (strncmp(argv[1], "set", length) == 0)) { + break; + } + case COMMAND_SET: { int totalUnits, windowUnits, firstUnit, lastUnit; - if (argc == 4) { + if (objc == 4) { double first, last; - if (Tcl_GetDouble(interp, argv[2], &first) != TCL_OK) { + if (Tcl_GetDoubleFromObj(interp, objv[2], &first) != TCL_OK) { goto error; } - if (Tcl_GetDouble(interp, argv[3], &last) != TCL_OK) { + if (Tcl_GetDoubleFromObj(interp, objv[3], &last) != TCL_OK) { goto error; } if (first < 0) { @@ -435,23 +439,23 @@ ScrollbarWidgetCmd( scrollPtr->lastFraction = last; } scrollPtr->flags |= NEW_STYLE_COMMANDS; - } else if (argc == 6) { - if (Tcl_GetInt(interp, argv[2], &totalUnits) != TCL_OK) { + } else if (objc == 6) { + if (Tcl_GetIntFromObj(interp, objv[2], &totalUnits) != TCL_OK) { goto error; } if (totalUnits < 0) { totalUnits = 0; } - if (Tcl_GetInt(interp, argv[3], &windowUnits) != TCL_OK) { + if (Tcl_GetIntFromObj(interp, objv[3], &windowUnits) != TCL_OK) { goto error; } if (windowUnits < 0) { windowUnits = 0; } - if (Tcl_GetInt(interp, argv[4], &firstUnit) != TCL_OK) { + if (Tcl_GetIntFromObj(interp, objv[4], &firstUnit) != TCL_OK) { goto error; } - if (Tcl_GetInt(interp, argv[5], &lastUnit) != TCL_OK) { + if (Tcl_GetIntFromObj(interp, objv[5], &lastUnit) != TCL_OK) { goto error; } if (totalUnits > 0) { @@ -474,23 +478,15 @@ ScrollbarWidgetCmd( } scrollPtr->flags &= ~NEW_STYLE_COMMANDS; } else { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "wrong # args: should be " - "\"%s set firstFraction lastFraction\" or " - "\"%s set totalUnits windowUnits firstUnit lastUnit\"", - argv[0], argv[0])); - Tcl_SetErrorCode(interp, "TCL", "WRONGARGS", NULL); + Tcl_WrongNumArgs(interp, 1, objv, "set firstFraction lastFraction"); + Tcl_AppendResult(interp, " or \"", Tcl_GetString(objv[0]), + " set totalUnits windowUnits firstUnit lastUnit\"", NULL); goto error; } TkpComputeScrollbarGeometry(scrollPtr); TkScrollbarEventuallyRedraw(scrollPtr); - } else { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "bad option \"%s\": must be activate, cget, configure," - " delta, fraction, get, identify, or set", argv[1])); - Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "INDEX", "option", - argv[1], NULL); - goto error; + break; + } } done: @@ -528,12 +524,12 @@ ConfigureScrollbar( register TkScrollbar *scrollPtr, /* Information about widget; may or may not * already have values for some fields. */ - int argc, /* Number of valid entries in argv. */ - const char **argv, /* Arguments. */ + int objc, /* Number of valid entries in argv. */ + Tcl_Obj *const objv[], /* Arguments. */ int flags) /* Flags to pass to Tk_ConfigureWidget. */ { - if (Tk_ConfigureWidget(interp, scrollPtr->tkwin, configSpecs, - argc, argv, (char *) scrollPtr, flags) != TCL_OK) { + if (Tk_ConfigureWidget(interp, scrollPtr->tkwin, configSpecs, objc, + (const char **)objv, (char *) scrollPtr, flags|TK_CONFIG_OBJS) != TCL_OK) { return TCL_ERROR; } @@ -626,6 +622,8 @@ TkScrollbarEventProc( TkScrollbarEventuallyRedraw(scrollPtr); } } + } else if (eventPtr->type == MapNotify) { + TkScrollbarEventuallyRedraw(scrollPtr); } } diff --git a/generic/tkSelect.c b/generic/tkSelect.c index 2414b3d..ab9018a 100644 --- a/generic/tkSelect.c +++ b/generic/tkSelect.c @@ -1193,7 +1193,7 @@ TkSelInit( * http://www.cl.cam.ac.uk/~mgk25/unicode.html#x11 */ -#if !defined(__WIN32__) +#if !defined(_WIN32) dispPtr->utf8Atom = Tk_InternAtom(tkwin, "UTF8_STRING"); #else dispPtr->utf8Atom = (Atom) 0; diff --git a/generic/tkSquare.c b/generic/tkSquare.c index 787630d..36d2d6e 100644 --- a/generic/tkSquare.c +++ b/generic/tkSquare.c @@ -98,7 +98,7 @@ static const Tk_OptionSpec optionSpecs[] = { static void SquareDeletedProc(ClientData clientData); static int SquareConfigure(Tcl_Interp *interp, Square *squarePtr); -static void SquareDestroy(char *memPtr); +static void SquareDestroy(void *memPtr); static void SquareDisplay(ClientData clientData); static void KeepInWindow(Square *squarePtr); static void SquareObjEventProc(ClientData clientData, @@ -237,8 +237,8 @@ SquareWidgetObjCmd( return TCL_ERROR; } - if (Tcl_GetIndexFromObj(interp, objv[1], squareOptions, "command", - 0, &index) != TCL_OK) { + if (Tcl_GetIndexFromObjStruct(interp, objv[1], squareOptions, + sizeof(char *), "command", 0, &index) != TCL_OK) { return TCL_ERROR; } @@ -410,7 +410,7 @@ SquareObjEventProc( if (squarePtr->updatePending) { Tcl_CancelIdleCall(SquareDisplay, squarePtr); } - Tcl_EventuallyFree(squarePtr, SquareDestroy); + Tcl_EventuallyFree(squarePtr, (Tcl_FreeProc *) SquareDestroy); } } @@ -554,9 +554,9 @@ SquareDisplay( static void SquareDestroy( - char *memPtr) /* Info about square widget. */ + void *memPtr) /* Info about square widget. */ { - Square *squarePtr = (Square *) memPtr; + Square *squarePtr = memPtr; ckfree(squarePtr); } diff --git a/generic/tkStubInit.c b/generic/tkStubInit.c index b1cdd53..f08d7f4 100644 --- a/generic/tkStubInit.c +++ b/generic/tkStubInit.c @@ -11,13 +11,13 @@ #include "tkInt.h" -#if !(defined(__WIN32__) || defined(MAC_OSX_TK)) +#if !(defined(_WIN32) || defined(MAC_OSX_TK)) /* UNIX */ #define UNIX_TK #include "tkUnixInt.h" #endif -#ifdef __WIN32__ +#ifdef _WIN32 #include "tkWinInt.h" #endif @@ -31,6 +31,7 @@ #include "tkIntXlibDecls.h" static const TkIntStubs tkIntStubs; +MODULE_SCOPE const TkStubs tkStubs; /* * Remove macro that might interfere with the definition below. @@ -38,7 +39,7 @@ static const TkIntStubs tkIntStubs; #undef Tk_MainEx -#ifdef __WIN32__ +#ifdef _WIN32 int TkpCmapStressed(Tk_Window tkwin, Colormap colormap) @@ -65,7 +66,7 @@ TkCreateXEventSource(void) # define TkSendCleanup (void (*)(TkDisplay *)) TkpSync # define TkpTestsendCmd 0 -#else /* !__WIN32__ */ +#else /* !_WIN32 */ /* * Make sure that extensions which call XParseColor through the stub @@ -224,10 +225,7 @@ void TkSubtractRegion (TkRegion a, TkRegion b, TkRegion c) # define TkUnionRectWithRegion (void (*) (XRectangle *, TkRegion, TkRegion)) XUnionRectWithRegion # define TkSubtractRegion (void (*) (TkRegion, TkRegion, TkRegion)) XSubtractRegion # endif -#endif /* !__WIN32__ */ - -#define reserved274 (void (*)(void)) Tk_DefineBitmap -#define reserved275 (void (*)(void)) Tk_GetBitmapFromData +#endif /* !_WIN32 */ /* * WARNING: The contents of this file is automatically generated by the @@ -361,20 +359,20 @@ static const TkIntStubs tkIntStubs = { TkSetRegion, /* 118 */ TkUnionRectWithRegion, /* 119 */ 0, /* 120 */ -#if !(defined(__WIN32__) || defined(MAC_OSX_TK)) /* X11 */ +#if !(defined(_WIN32) || defined(MAC_OSX_TK)) /* X11 */ 0, /* 121 */ #endif /* X11 */ -#if defined(__WIN32__) /* WIN */ +#if defined(_WIN32) /* WIN */ 0, /* 121 */ #endif /* WIN */ #ifdef MAC_OSX_TK /* AQUA */ 0, /* 121 */ /* Dummy entry for stubs table backwards compatibility */ TkpCreateNativeBitmap, /* 121 */ #endif /* AQUA */ -#if !(defined(__WIN32__) || defined(MAC_OSX_TK)) /* X11 */ +#if !(defined(_WIN32) || defined(MAC_OSX_TK)) /* X11 */ 0, /* 122 */ #endif /* X11 */ -#if defined(__WIN32__) /* WIN */ +#if defined(_WIN32) /* WIN */ 0, /* 122 */ #endif /* WIN */ #ifdef MAC_OSX_TK /* AQUA */ @@ -382,10 +380,10 @@ static const TkIntStubs tkIntStubs = { TkpDefineNativeBitmaps, /* 122 */ #endif /* AQUA */ 0, /* 123 */ -#if !(defined(__WIN32__) || defined(MAC_OSX_TK)) /* X11 */ +#if !(defined(_WIN32) || defined(MAC_OSX_TK)) /* X11 */ 0, /* 124 */ #endif /* X11 */ -#if defined(__WIN32__) /* WIN */ +#if defined(_WIN32) /* WIN */ 0, /* 124 */ #endif /* WIN */ #ifdef MAC_OSX_TK /* AQUA */ @@ -457,7 +455,7 @@ static const TkIntStubs tkIntStubs = { static const TkIntPlatStubs tkIntPlatStubs = { TCL_STUB_MAGIC, 0, -#if defined(__WIN32__) || defined(__CYGWIN__) /* WIN */ +#if defined(_WIN32) || defined(__CYGWIN__) /* WIN */ TkAlignImageData, /* 0 */ 0, /* 1 */ TkGenerateActivateEvents, /* 2 */ @@ -558,11 +556,12 @@ static const TkIntPlatStubs tkIntPlatStubs = { TkGetTransientMaster, /* 49 */ TkGenerateButtonEvent, /* 50 */ TkGenWMDestroyEvent, /* 51 */ - 0, /* 52 */ + TkMacOSXSetDrawingEnabled, /* 52 */ TkpGetMS, /* 53 */ TkMacOSXDrawable, /* 54 */ + TkpScanWindowId, /* 55 */ #endif /* AQUA */ -#if !(defined(__WIN32__) || defined(__CYGWIN__) || defined(MAC_OSX_TK)) /* X11 */ +#if !(defined(_WIN32) || defined(__CYGWIN__) || defined(MAC_OSX_TK)) /* X11 */ TkCreateXEventSource, /* 0 */ 0, /* 1 */ 0, /* 2 */ @@ -583,7 +582,7 @@ static const TkIntPlatStubs tkIntPlatStubs = { static const TkIntXlibStubs tkIntXlibStubs = { TCL_STUB_MAGIC, 0, -#if defined(__WIN32__) || defined(__CYGWIN__) /* WIN */ +#if defined(_WIN32) || defined(__CYGWIN__) /* WIN */ XSetDashes, /* 0 */ XGetModifierMapping, /* 1 */ XCreateImage, /* 2 */ @@ -799,7 +798,7 @@ static const TkIntXlibStubs tkIntXlibStubs = { static const TkPlatStubs tkPlatStubs = { TCL_STUB_MAGIC, 0, -#if defined(__WIN32__) || defined(__CYGWIN__) /* WIN */ +#if defined(_WIN32) || defined(__CYGWIN__) /* WIN */ Tk_AttachHWND, /* 0 */ Tk_GetHINSTANCE, /* 1 */ Tk_GetHWND, /* 2 */ @@ -1106,8 +1105,6 @@ const TkStubs tkStubs = { Tk_Interp, /* 271 */ Tk_CreateOldImageType, /* 272 */ Tk_CreateOldPhotoImageFormat, /* 273 */ - reserved274, /* 274 */ - reserved275, /* 275 */ }; /* !END!: Do not edit above this line. */ diff --git a/generic/tkStubLib.c b/generic/tkStubLib.c index b4063b5..ea48894 100644 --- a/generic/tkStubLib.c +++ b/generic/tkStubLib.c @@ -1,31 +1,19 @@ /* * tkStubLib.c -- * - * Stub object that will be statically linked into extensions that wish + * Stub object that will be statically linked into extensions that want * to access Tk. * - * Copyright (c) 1998 Paul Duffin. * Copyright (c) 1998-1999 by Scriptics Corporation. + * Copyright (c) 1998 Paul Duffin. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ -/* - * We need to ensure that we use the stub macros so that this file contains no - * references to any of the stub functions. This will make it possible to - * build an extension that references Tk_InitStubs but doesn't end up - * including the rest of the stub functions. - */ - -#undef USE_TCL_STUBS -#define USE_TCL_STUBS - -#define USE_TK_STUBS - #include "tkInt.h" -#ifdef __WIN32__ +#ifdef _WIN32 #include "tkWinInt.h" #endif @@ -33,7 +21,7 @@ #include "tkMacOSXInt.h" #endif -#if !(defined(__WIN32__) || defined(MAC_OSX_TK)) +#if !(defined(_WIN32) || defined(MAC_OSX_TK)) #include "tkUnixInt.h" #endif @@ -58,8 +46,7 @@ const TkIntXlibStubs *tkIntXlibStubsPtr = NULL; */ static int -isDigit( - const int c) +isDigit(const int c) { return (c >= '0' && c <= '9'); } @@ -81,61 +68,73 @@ isDigit( * *---------------------------------------------------------------------- */ - +#undef Tk_InitStubs MODULE_SCOPE const char * Tk_InitStubs( Tcl_Interp *interp, const char *version, int exact) { - ClientData pkgClientData = NULL; - const char *actualVersion = Tcl_PkgRequireEx(interp, "Tk", version, 0, - &pkgClientData); - const TkStubs *stubsPtr = pkgClientData; - - if (!actualVersion) { + const char *packageName = "Tk"; + const char *errMsg = NULL; + ClientData clientData = NULL; + const char *actualVersion = tclStubsPtr->tcl_PkgRequireEx(interp, + packageName, version, 0, &clientData); + const TkStubs *stubsPtr = clientData; + + if (actualVersion == NULL) { return NULL; } + if (exact) { - const char *p = version; - int count = 0; + const char *p = version; + int count = 0; - while (*p) { - count += !isDigit(*p++); - } - if (count == 1) { + while (*p) { + count += !isDigit(*p++); + } + if (count == 1) { const char *q = actualVersion; p = version; while (*p && (*p == *q)) { p++; q++; } - if (*p) { + if (*p || isDigit(*q)) { /* Construct error message */ - Tcl_PkgRequireEx(interp, "Tk", version, 1, NULL); - return NULL; - } - } else { - actualVersion = Tcl_PkgRequireEx(interp, "Tk", version, 1, NULL); - if (actualVersion == NULL) { - return NULL; - } - } + tclStubsPtr->tcl_PkgRequireEx(interp, packageName, version, 1, NULL); + return NULL; + } + } else { + actualVersion = tclStubsPtr->tcl_PkgRequireEx(interp, packageName, + version, 1, NULL); + if (actualVersion == NULL) { + return NULL; + } + } } - - if (!stubsPtr) { - Tcl_SetObjResult(interp, Tcl_NewStringObj( - "this implementation of Tk does not support stubs", -1)); - return NULL; + if (stubsPtr == NULL) { + errMsg = "missing stub table pointer"; + } else { + tkStubsPtr = stubsPtr; + if (stubsPtr->hooks) { + tkPlatStubsPtr = stubsPtr->hooks->tkPlatStubs; + tkIntStubsPtr = stubsPtr->hooks->tkIntStubs; + tkIntPlatStubsPtr = stubsPtr->hooks->tkIntPlatStubs; + tkIntXlibStubsPtr = stubsPtr->hooks->tkIntXlibStubs; + } else { + tkPlatStubsPtr = NULL; + tkIntStubsPtr = NULL; + tkIntPlatStubsPtr = NULL; + tkIntXlibStubsPtr = NULL; + } + return actualVersion; } - - tkPlatStubsPtr = stubsPtr->hooks->tkPlatStubs; - tkIntStubsPtr = stubsPtr->hooks->tkIntStubs; - tkIntPlatStubsPtr = stubsPtr->hooks->tkIntPlatStubs; - tkIntXlibStubsPtr = stubsPtr->hooks->tkIntXlibStubs; - tkStubsPtr = stubsPtr; - - return actualVersion; + tclStubsPtr->tcl_ResetResult(interp); + tclStubsPtr->tcl_AppendResult(interp, "Error loading ", packageName, + " (requested version ", version, ", actual version ", + actualVersion, "): ", errMsg, NULL); + return NULL; } /* diff --git a/generic/tkStyle.c b/generic/tkStyle.c index d5e1407..e7401df 100644 --- a/generic/tkStyle.c +++ b/generic/tkStyle.c @@ -146,8 +146,8 @@ static int SetStyleFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr); /* * The following structure defines the implementation of the "style" Tcl - * object, used for drawing. The internalRep.otherValuePtr field of each style - * object points to the Style structure for the stylefont, or NULL. + * object, used for drawing. The internalRep.twoPtrValue.ptr1 field of each + * style object points to the Style structure for the stylefont, or NULL. */ static const Tcl_ObjType styleObjType = { @@ -1410,7 +1410,7 @@ Tk_AllocStyleFromObj( if (objPtr->typePtr != &styleObjType) { SetStyleFromAny(interp, objPtr); } - stylePtr = objPtr->internalRep.otherValuePtr; + stylePtr = objPtr->internalRep.twoPtrValue.ptr1; return (Tk_Style) stylePtr; } @@ -1442,7 +1442,7 @@ Tk_GetStyleFromObj( SetStyleFromAny(NULL, objPtr); } - return objPtr->internalRep.otherValuePtr; + return objPtr->internalRep.twoPtrValue.ptr1; } /* @@ -1497,7 +1497,7 @@ SetStyleFromAny( } objPtr->typePtr = &styleObjType; - objPtr->internalRep.otherValuePtr = Tk_GetStyle(interp, name); + objPtr->internalRep.twoPtrValue.ptr1 = Tk_GetStyle(interp, name); return TCL_OK; } @@ -1520,7 +1520,7 @@ static void FreeStyleObjProc( Tcl_Obj *objPtr) /* The object we are releasing. */ { - objPtr->internalRep.otherValuePtr = NULL; + objPtr->internalRep.twoPtrValue.ptr1 = NULL; objPtr->typePtr = NULL; } @@ -1541,8 +1541,8 @@ DupStyleObjProc( Tcl_Obj *dupObjPtr) /* The object we are copying to. */ { dupObjPtr->typePtr = srcObjPtr->typePtr; - dupObjPtr->internalRep.otherValuePtr = - srcObjPtr->internalRep.otherValuePtr; + dupObjPtr->internalRep.twoPtrValue.ptr1 = + srcObjPtr->internalRep.twoPtrValue.ptr1; } /* diff --git a/generic/tkTest.c b/generic/tkTest.c index bd15739..fa9e073 100644 --- a/generic/tkTest.c +++ b/generic/tkTest.c @@ -24,7 +24,7 @@ #include "tkInt.h" #include "tkText.h" -#ifdef __WIN32__ +#ifdef _WIN32 #include "tkWinInt.h" #endif @@ -139,8 +139,9 @@ typedef struct TrivialCommandHeader { * Forward declarations for functions defined later in this file: */ -static int ImageCmd(ClientData dummy, - Tcl_Interp *interp, int argc, const char **argv); +static int ImageObjCmd(ClientData dummy, + Tcl_Interp *interp, int objc, + Tcl_Obj * const objv[]); static int TestbitmapObjCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj * const objv[]); @@ -153,20 +154,24 @@ static int TestcolorObjCmd(ClientData dummy, static int TestcursorObjCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj * const objv[]); -static int TestdeleteappsCmd(ClientData dummy, - Tcl_Interp *interp, int argc, const char **argv); +static int TestdeleteappsObjCmd(ClientData dummy, + Tcl_Interp *interp, int objc, + Tcl_Obj * const objv[]); static int TestfontObjCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); -static int TestmakeexistCmd(ClientData dummy, - Tcl_Interp *interp, int argc, const char **argv); -#if !(defined(__WIN32__) || defined(MAC_OSX_TK)) -static int TestmenubarCmd(ClientData dummy, - Tcl_Interp *interp, int argc, const char **argv); +static int TestmakeexistObjCmd(ClientData dummy, + Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[]); +#if !(defined(_WIN32) || defined(MAC_OSX_TK) || defined(__CYGWIN__)) +static int TestmenubarObjCmd(ClientData dummy, + Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[]); #endif -#if defined(__WIN32__) || defined(MAC_OSX_TK) -static int TestmetricsCmd(ClientData dummy, - Tcl_Interp *interp, int argc, const char **argv); +#if defined(_WIN32) || defined(MAC_OSX_TK) +static int TestmetricsObjCmd(ClientData dummy, + Tcl_Interp *interp, int objc, + Tcl_Obj * const objv[]); #endif static int TestobjconfigObjCmd(ClientData dummy, Tcl_Interp *interp, int objc, @@ -184,11 +189,13 @@ static void CustomOptionRestore(ClientData clientData, char *saveInternalPtr); static void CustomOptionFree(ClientData clientData, Tk_Window tkwin, char *internalPtr); -static int TestpropCmd(ClientData dummy, - Tcl_Interp *interp, int argc, const char **argv); -#if !(defined(__WIN32__) || defined(MAC_OSX_TK)) -static int TestwrapperCmd(ClientData dummy, - Tcl_Interp *interp, int argc, const char **argv); +static int TestpropObjCmd(ClientData dummy, + Tcl_Interp *interp, int objc, + Tcl_Obj * const objv[]); +#if !(defined(_WIN32) || defined(MAC_OSX_TK) || defined(__CYGWIN__)) +static int TestwrapperObjCmd(ClientData dummy, + Tcl_Interp *interp, int objc, + Tcl_Obj * const objv[]); #endif static void TrivialCmdDeletedProc(ClientData clientData); static int TrivialConfigObjCmd(ClientData dummy, @@ -223,7 +230,7 @@ Tktest_Init( if (Tcl_InitStubs(interp, "8.1", 0) == NULL) { return TCL_ERROR; } - if (Tk_InitStubs(interp, "8.1", 0) == NULL) { + if (Tk_InitStubs(interp, TK_VERSION, 0) == NULL) { return TCL_ERROR; } @@ -231,7 +238,7 @@ Tktest_Init( * Create additional commands for testing Tk. */ - if (Tcl_PkgProvide(interp, "Tktest", TK_VERSION) == TCL_ERROR) { + if (Tcl_PkgProvideEx(interp, "Tktest", TK_PATCH_LEVEL, NULL) == TCL_ERROR) { return TCL_ERROR; } @@ -244,32 +251,32 @@ Tktest_Init( (ClientData) Tk_MainWindow(interp), NULL); Tcl_CreateObjCommand(interp, "testcursor", TestcursorObjCmd, (ClientData) Tk_MainWindow(interp), NULL); - Tcl_CreateCommand(interp, "testdeleteapps", TestdeleteappsCmd, + Tcl_CreateObjCommand(interp, "testdeleteapps", TestdeleteappsObjCmd, (ClientData) Tk_MainWindow(interp), NULL); - Tcl_CreateCommand(interp, "testembed", TkpTestembedCmd, + Tcl_CreateObjCommand(interp, "testembed", TkpTestembedCmd, (ClientData) Tk_MainWindow(interp), NULL); Tcl_CreateObjCommand(interp, "testobjconfig", TestobjconfigObjCmd, (ClientData) Tk_MainWindow(interp), NULL); Tcl_CreateObjCommand(interp, "testfont", TestfontObjCmd, (ClientData) Tk_MainWindow(interp), NULL); - Tcl_CreateCommand(interp, "testmakeexist", TestmakeexistCmd, + Tcl_CreateObjCommand(interp, "testmakeexist", TestmakeexistObjCmd, (ClientData) Tk_MainWindow(interp), NULL); - Tcl_CreateCommand(interp, "testprop", TestpropCmd, + Tcl_CreateObjCommand(interp, "testprop", TestpropObjCmd, (ClientData) Tk_MainWindow(interp), NULL); - Tcl_CreateCommand(interp, "testtext", TkpTesttextCmd, + Tcl_CreateObjCommand(interp, "testtext", TkpTesttextCmd, (ClientData) Tk_MainWindow(interp), NULL); -#if defined(__WIN32__) || defined(MAC_OSX_TK) - Tcl_CreateCommand(interp, "testmetrics", TestmetricsCmd, +#if defined(_WIN32) || defined(MAC_OSX_TK) + Tcl_CreateObjCommand(interp, "testmetrics", TestmetricsObjCmd, (ClientData) Tk_MainWindow(interp), NULL); -#else - Tcl_CreateCommand(interp, "testmenubar", TestmenubarCmd, +#elif !defined(__CYGWIN__) + Tcl_CreateObjCommand(interp, "testmenubar", TestmenubarObjCmd, (ClientData) Tk_MainWindow(interp), NULL); - Tcl_CreateCommand(interp, "testsend", TkpTestsendCmd, + Tcl_CreateObjCommand(interp, "testsend", TkpTestsendCmd, (ClientData) Tk_MainWindow(interp), NULL); - Tcl_CreateCommand(interp, "testwrapper", TestwrapperCmd, + Tcl_CreateObjCommand(interp, "testwrapper", TestwrapperObjCmd, (ClientData) Tk_MainWindow(interp), NULL); -#endif /* __WIN32__ || MAC_OSX_TK */ +#endif /* _WIN32 || MAC_OSX_TK */ /* * Create test image type. @@ -436,7 +443,7 @@ TestcursorObjCmd( /* *---------------------------------------------------------------------- * - * TestdeleteappsCmd -- + * TestdeleteappsObjCmd -- * * This function implements the "testdeleteapps" command. It cleans up * all the interpreters left behind by the "testnewapp" command. @@ -453,11 +460,11 @@ TestcursorObjCmd( /* ARGSUSED */ static int -TestdeleteappsCmd( +TestdeleteappsObjCmd( ClientData clientData, /* Main window for application. */ Tcl_Interp *interp, /* Current interpreter. */ - int argc, /* Number of arguments. */ - const char **argv) /* Argument strings. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument strings. */ { NewApp *nextPtr; @@ -497,11 +504,11 @@ TestobjconfigObjCmd( Tcl_Obj *const objv[]) /* Argument objects. */ { static const char *const options[] = { - "alltypes", "chain1", "chain2", "configerror", "delete", "info", + "alltypes", "chain1", "chain2", "chain3", "configerror", "delete", "info", "internal", "new", "notenoughparams", "twowindows", NULL }; enum { - ALL_TYPES, CHAIN1, CHAIN2, CONFIG_ERROR, + ALL_TYPES, CHAIN1, CHAIN2, CHAIN3, CONFIG_ERROR, DEL, /* Can't use DELETE: VC++ compiler barfs. */ INFO, INTERNAL, NEW, NOT_ENOUGH_PARAMS, TWO_WINDOWS }; @@ -547,8 +554,8 @@ TestobjconfigObjCmd( return TCL_ERROR; } - if (Tcl_GetIndexFromObj(interp, objv[1], options, "command", 0, &index) - != TCL_OK) { + if (Tcl_GetIndexFromObjStruct(interp, objv[1], options, + sizeof(char *), "command", 0, &index)!= TCL_OK) { return TCL_ERROR; } @@ -720,7 +727,8 @@ TestobjconfigObjCmd( break; } - case CHAIN2: { + case CHAIN2: + case CHAIN3: { ExtensionWidgetRecord *recordPtr; static const Tk_OptionSpec extensionSpecs[] = { {TK_OPTION_STRING, "-three", "three", "Three", "three", @@ -797,12 +805,15 @@ TestobjconfigObjCmd( Tcl_WrongNumArgs(interp, 2, objv, "tableName"); return TCL_ERROR; } - if (Tcl_GetIndexFromObj(interp, objv[2], options, "table", 0, - &index) != TCL_OK) { + if (Tcl_GetIndexFromObjStruct(interp, objv[2], options, + sizeof(char *), "table", 0, &index) != TCL_OK) { return TCL_ERROR; } if (tables[index] != NULL) { Tk_DeleteOptionTable(tables[index]); + /* Make sure that Tk_DeleteOptionTable() is never done + * twice for the same table. */ + tables[index] = NULL; } break; @@ -811,8 +822,8 @@ TestobjconfigObjCmd( Tcl_WrongNumArgs(interp, 2, objv, "tableName"); return TCL_ERROR; } - if (Tcl_GetIndexFromObj(interp, objv[2], options, "table", 0, - &index) != TCL_OK) { + if (Tcl_GetIndexFromObjStruct(interp, objv[2], options, + sizeof(char *), "table", 0, &index) != TCL_OK) { return TCL_ERROR; } Tcl_SetObjResult(interp, TkDebugConfig(interp, tables[index])); @@ -1143,8 +1154,8 @@ TrivialConfigObjCmd( return TCL_ERROR; } - if (Tcl_GetIndexFromObj(interp, objv[1], options, "command", 0, - &index) != TCL_OK) { + if (Tcl_GetIndexFromObjStruct(interp, objv[1], options, + sizeof(char *), "command", 0, &index) != TCL_OK) { return TCL_ERROR; } @@ -1321,8 +1332,8 @@ TestfontObjCmd( return TCL_ERROR; } - if (Tcl_GetIndexFromObj(interp, objv[1], options, "command", 0, &index) - != TCL_OK) { + if (Tcl_GetIndexFromObjStruct(interp, objv[1], options, + sizeof(char *), "command", 0, &index)!= TCL_OK) { return TCL_ERROR; } @@ -1403,7 +1414,7 @@ ImageCreate( strcpy(timPtr->imageName, name); timPtr->varName = ckalloc(strlen(varName) + 1); strcpy(timPtr->varName, varName); - Tcl_CreateCommand(interp, name, ImageCmd, timPtr, NULL); + Tcl_CreateObjCommand(interp, name, ImageObjCmd, timPtr, NULL); *clientDataPtr = timPtr; Tk_ImageChanged(master, 0, 0, 30, 15, 30, 15); return TCL_OK; @@ -1412,7 +1423,7 @@ ImageCreate( /* *---------------------------------------------------------------------- * - * ImageCmd -- + * ImageObjCmd -- * * This function implements the commands corresponding to individual * images. @@ -1428,38 +1439,37 @@ ImageCreate( /* ARGSUSED */ static int -ImageCmd( +ImageObjCmd( ClientData clientData, /* Main window for application. */ Tcl_Interp *interp, /* Current interpreter. */ - int argc, /* Number of arguments. */ - const char **argv) /* Argument strings. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument strings. */ { TImageMaster *timPtr = (TImageMaster *) clientData; int x, y, width, height; - if (argc < 2) { - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], "option ?arg ...?", NULL); + if (objc < 2) { + Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?"); return TCL_ERROR; } - if (strcmp(argv[1], "changed") == 0) { - if (argc != 8) { - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " changed x y width height imageWidth imageHeight", NULL); + if (strcmp(Tcl_GetString(objv[1]), "changed") == 0) { + if (objc != 8) { + Tcl_WrongNumArgs(interp, 1, objv, "changed x y width height" + " imageWidth imageHeight"); return TCL_ERROR; } - if ((Tcl_GetInt(interp, argv[2], &x) != TCL_OK) - || (Tcl_GetInt(interp, argv[3], &y) != TCL_OK) - || (Tcl_GetInt(interp, argv[4], &width) != TCL_OK) - || (Tcl_GetInt(interp, argv[5], &height) != TCL_OK) - || (Tcl_GetInt(interp, argv[6], &timPtr->width) != TCL_OK) - || (Tcl_GetInt(interp, argv[7], &timPtr->height) != TCL_OK)) { + if ((Tcl_GetIntFromObj(interp, objv[2], &x) != TCL_OK) + || (Tcl_GetIntFromObj(interp, objv[3], &y) != TCL_OK) + || (Tcl_GetIntFromObj(interp, objv[4], &width) != TCL_OK) + || (Tcl_GetIntFromObj(interp, objv[5], &height) != TCL_OK) + || (Tcl_GetIntFromObj(interp, objv[6], &timPtr->width) != TCL_OK) + || (Tcl_GetIntFromObj(interp, objv[7], &timPtr->height) != TCL_OK)) { return TCL_ERROR; } Tk_ImageChanged(timPtr->master, x, y, width, height, timPtr->width, timPtr->height); } else { - Tcl_AppendResult(interp, "bad option \"", argv[1], + Tcl_AppendResult(interp, "bad option \"", Tcl_GetString(objv[1]), "\": must be changed", NULL); return TCL_ERROR; } @@ -1496,7 +1506,7 @@ ImageGet( XGCValues gcValues; sprintf(buffer, "%s get", timPtr->imageName); - Tcl_SetVar(timPtr->interp, timPtr->varName, buffer, + Tcl_SetVar2(timPtr->interp, timPtr->varName, NULL, buffer, TCL_GLOBAL_ONLY|TCL_APPEND_VALUE|TCL_LIST_ELEMENT); instPtr = ckalloc(sizeof(TImageInstance)); @@ -1543,8 +1553,8 @@ ImageDisplay( sprintf(buffer, "%s display %d %d %d %d %d %d", instPtr->masterPtr->imageName, imageX, imageY, width, height, drawableX, drawableY); - Tcl_SetVar(instPtr->masterPtr->interp, instPtr->masterPtr->varName, buffer, - TCL_GLOBAL_ONLY|TCL_APPEND_VALUE|TCL_LIST_ELEMENT); + Tcl_SetVar2(instPtr->masterPtr->interp, instPtr->masterPtr->varName, NULL, + buffer, TCL_GLOBAL_ONLY|TCL_APPEND_VALUE|TCL_LIST_ELEMENT); if (width > (instPtr->masterPtr->width - imageX)) { width = instPtr->masterPtr->width - imageX; } @@ -1586,8 +1596,8 @@ ImageFree( char buffer[200]; sprintf(buffer, "%s free", instPtr->masterPtr->imageName); - Tcl_SetVar(instPtr->masterPtr->interp, instPtr->masterPtr->varName, buffer, - TCL_GLOBAL_ONLY|TCL_APPEND_VALUE|TCL_LIST_ELEMENT); + Tcl_SetVar2(instPtr->masterPtr->interp, instPtr->masterPtr->varName, NULL, + buffer, TCL_GLOBAL_ONLY|TCL_APPEND_VALUE|TCL_LIST_ELEMENT); Tk_FreeColor(instPtr->fg); Tk_FreeGC(display, instPtr->gc); ckfree(instPtr); @@ -1620,7 +1630,7 @@ ImageDelete( char buffer[100]; sprintf(buffer, "%s delete", timPtr->imageName); - Tcl_SetVar(timPtr->interp, timPtr->varName, buffer, + Tcl_SetVar2(timPtr->interp, timPtr->varName, NULL, buffer, TCL_GLOBAL_ONLY|TCL_APPEND_VALUE|TCL_LIST_ELEMENT); Tcl_DeleteCommand(timPtr->interp, timPtr->imageName); @@ -1632,7 +1642,7 @@ ImageDelete( /* *---------------------------------------------------------------------- * - * TestmakeexistCmd -- + * TestmakeexistObjCmd -- * * This function implements the "testmakeexist" command. It calls * Tk_MakeWindowExist on each of its arguments to force the windows to be @@ -1649,18 +1659,18 @@ ImageDelete( /* ARGSUSED */ static int -TestmakeexistCmd( +TestmakeexistObjCmd( ClientData clientData, /* Main window for application. */ Tcl_Interp *interp, /* Current interpreter. */ - int argc, /* Number of arguments. */ - const char **argv) /* Argument strings. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument strings. */ { Tk_Window mainWin = (Tk_Window) clientData; int i; Tk_Window tkwin; - for (i = 1; i < argc; i++) { - tkwin = Tk_NameToWindow(interp, argv[i], mainWin); + for (i = 1; i < objc; i++) { + tkwin = Tk_NameToWindow(interp, Tcl_GetString(objv[i]), mainWin); if (tkwin == NULL) { return TCL_ERROR; } @@ -1673,7 +1683,7 @@ TestmakeexistCmd( /* *---------------------------------------------------------------------- * - * TestmenubarCmd -- + * TestmenubarObjCmd -- * * This function implements the "testmenubar" command. It is used to test * the Unix facilities for creating space above a toplevel window for a @@ -1689,53 +1699,50 @@ TestmakeexistCmd( */ /* ARGSUSED */ -#if !(defined(__WIN32__) || defined(MAC_OSX_TK)) +#if !(defined(_WIN32) || defined(MAC_OSX_TK) || defined(__CYGWIN__)) static int -TestmenubarCmd( +TestmenubarObjCmd( ClientData clientData, /* Main window for application. */ Tcl_Interp *interp, /* Current interpreter. */ - int argc, /* Number of arguments. */ - const char **argv) /* Argument strings. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument strings. */ { #ifdef __UNIX__ Tk_Window mainWin = (Tk_Window) clientData; Tk_Window tkwin, menubar; - if (argc < 2) { - Tcl_AppendResult(interp, "wrong # args; must be \"", argv[0], - " option ?arg ...?\"", NULL); + if (objc < 2) { + Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?"); return TCL_ERROR; } - if (strcmp(argv[1], "window") == 0) { - if (argc != 4) { - Tcl_AppendResult(interp, "wrong # args; must be \"", argv[0], - "window toplevel menubar\"", NULL); + if (strcmp(Tcl_GetString(objv[1]), "window") == 0) { + if (objc != 4) { + Tcl_WrongNumArgs(interp, 1, objv, "windows toplevel menubar"); return TCL_ERROR; } - tkwin = Tk_NameToWindow(interp, argv[2], mainWin); + tkwin = Tk_NameToWindow(interp, Tcl_GetString(objv[2]), mainWin); if (tkwin == NULL) { return TCL_ERROR; } - if (argv[3][0] == 0) { + if (Tcl_GetString(objv[3])[0] == 0) { TkUnixSetMenubar(tkwin, NULL); } else { - menubar = Tk_NameToWindow(interp, argv[3], mainWin); + menubar = Tk_NameToWindow(interp, Tcl_GetString(objv[3]), mainWin); if (menubar == NULL) { return TCL_ERROR; } TkUnixSetMenubar(tkwin, menubar); } } else { - Tcl_AppendResult(interp, "bad option \"", argv[1], + Tcl_AppendResult(interp, "bad option \"", Tcl_GetString(objv[1]), "\": must be window", NULL); return TCL_ERROR; } return TCL_OK; #else - Tcl_SetResult(interp, "testmenubar is supported only under Unix", - TCL_STATIC); + Tcl_AppendResult(interp, "testmenubar is supported only under Unix", NULL); return TCL_ERROR; #endif } @@ -1744,7 +1751,7 @@ TestmenubarCmd( /* *---------------------------------------------------------------------- * - * TestmetricsCmd -- + * TestmetricsObjCmd -- * * This function implements the testmetrics command. It provides a way to * determine the size of various widget components. @@ -1758,53 +1765,51 @@ TestmenubarCmd( *---------------------------------------------------------------------- */ -#if defined(__WIN32__) || defined(MAC_OSX_TK) +#if defined(_WIN32) || defined(MAC_OSX_TK) static int -TestmetricsCmd( +TestmetricsObjCmd( ClientData clientData, /* Main window for application. */ Tcl_Interp *interp, /* Current interpreter. */ - int argc, /* Number of arguments. */ - const char **argv) /* Argument strings. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument strings. */ { char buf[TCL_INTEGER_SPACE]; int val; -#ifdef __WIN32__ - if (argc < 2) { - Tcl_AppendResult(interp, "wrong # args; must be \"", argv[0], - " option ?arg ...?\"", NULL); +#ifdef _WIN32 + if (objc < 2) { + Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?"); return TCL_ERROR; } #else Tk_Window tkwin = (Tk_Window) clientData; TkWindow *winPtr; - if (argc != 3) { - Tcl_AppendResult(interp, "wrong # args; must be \"", argv[0], - " option window\"", NULL); + if (objc != 3) { + Tcl_WrongNumArgs(interp, 1, objv, "option window"); return TCL_ERROR; } - winPtr = (TkWindow *) Tk_NameToWindow(interp, argv[2], tkwin); + winPtr = (TkWindow *) Tk_NameToWindow(interp, Tcl_GetString(objv[2]), tkwin); if (winPtr == NULL) { return TCL_ERROR; } #endif - if (strcmp(argv[1], "cyvscroll") == 0) { -#ifdef __WIN32__ + if (strcmp(Tcl_GetString(objv[1]), "cyvscroll") == 0) { +#ifdef _WIN32 val = GetSystemMetrics(SM_CYVSCROLL); #else val = ((TkScrollbar *) winPtr->instanceData)->width; #endif - } else if (strcmp(argv[1], "cxhscroll") == 0) { -#ifdef __WIN32__ + } else if (strcmp(Tcl_GetString(objv[1]), "cxhscroll") == 0) { +#ifdef _WIN32 val = GetSystemMetrics(SM_CXHSCROLL); #else val = ((TkScrollbar *) winPtr->instanceData)->width; #endif } else { - Tcl_AppendResult(interp, "bad option \"", argv[1], + Tcl_AppendResult(interp, "bad option \"", Tcl_GetString(objv[1]), "\": must be cxhscroll or cyvscroll", NULL); return TCL_ERROR; } @@ -1817,7 +1822,7 @@ TestmetricsCmd( /* *---------------------------------------------------------------------- * - * TestpropCmd -- + * TestpropObjCmd -- * * This function implements the "testprop" command. It fetches and prints * the value of a property on a window. @@ -1833,11 +1838,11 @@ TestmetricsCmd( /* ARGSUSED */ static int -TestpropCmd( +TestpropObjCmd( ClientData clientData, /* Main window for application. */ Tcl_Interp *interp, /* Current interpreter. */ - int argc, /* Number of arguments. */ - const char **argv) /* Argument strings. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument strings. */ { Tk_Window mainWin = (Tk_Window) clientData; int result, actualFormat; @@ -1848,14 +1853,13 @@ TestpropCmd( Window w; char buffer[30]; - if (argc != 3) { - Tcl_AppendResult(interp, "wrong # args; must be \"", argv[0], - " window property\"", NULL); + if (objc != 3) { + Tcl_WrongNumArgs(interp, 1, objv, "window property"); return TCL_ERROR; } - w = strtoul(argv[1], &end, 0); - propName = Tk_InternAtom(mainWin, argv[2]); + w = strtoul(Tcl_GetString(objv[1]), &end, 0); + propName = Tk_InternAtom(mainWin, Tcl_GetString(objv[2])); property = NULL; result = XGetWindowProperty(Tk_Display(mainWin), w, propName, 0, 100000, False, AnyPropertyType, @@ -1868,7 +1872,7 @@ TestpropCmd( *p = '\n'; } } - Tcl_SetResult(interp, (/*!unsigned*/char*)property, TCL_VOLATILE); + Tcl_SetObjResult(interp, Tcl_NewStringObj((/*!unsigned*/char*)property, -1)); } else { for (p = property; length > 0; length--) { if (actualFormat == 32) { @@ -1892,11 +1896,11 @@ TestpropCmd( return TCL_OK; } -#if !(defined(__WIN32__) || defined(MAC_OSX_TK)) +#if !(defined(_WIN32) || defined(MAC_OSX_TK) || defined(__CYGWIN__)) /* *---------------------------------------------------------------------- * - * TestwrapperCmd -- + * TestwrapperObjCmd -- * * This function implements the "testwrapper" command. It provides a way * from Tcl to determine the extra window Tk adds in between the toplevel @@ -1913,23 +1917,22 @@ TestpropCmd( /* ARGSUSED */ static int -TestwrapperCmd( +TestwrapperObjCmd( ClientData clientData, /* Main window for application. */ Tcl_Interp *interp, /* Current interpreter. */ - int argc, /* Number of arguments. */ - const char **argv) /* Argument strings. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument strings. */ { TkWindow *winPtr, *wrapperPtr; Tk_Window tkwin; - if (argc != 2) { - Tcl_AppendResult(interp, "wrong # args; must be \"", argv[0], - " window\"", NULL); + if (objc != 2) { + Tcl_WrongNumArgs(interp, 1, objv, "window"); return TCL_ERROR; } tkwin = (Tk_Window) clientData; - winPtr = (TkWindow *) Tk_NameToWindow(interp, argv[1], tkwin); + winPtr = (TkWindow *) Tk_NameToWindow(interp, Tcl_GetString(objv[1]), tkwin); if (winPtr == NULL) { return TCL_ERROR; } @@ -1939,7 +1942,7 @@ TestwrapperCmd( char buf[TCL_INTEGER_SPACE]; TkpPrintWindowId(buf, Tk_WindowId(wrapperPtr)); - Tcl_SetResult(interp, buf, TCL_VOLATILE); + Tcl_SetObjResult(interp, Tcl_NewStringObj(buf, -1)); } return TCL_OK; } @@ -1982,7 +1985,7 @@ CustomOptionSet( char *saveInternalPtr, int flags) { - int objEmpty, length; + int objEmpty; char *newStr, *string, *internalPtr; objEmpty = 0; @@ -2003,25 +2006,24 @@ CustomOptionSet( } else if ((*value)->bytes != NULL) { objEmpty = ((*value)->length == 0); } else { - Tcl_GetStringFromObj((*value), &length); - objEmpty = (length == 0); + (void)Tcl_GetString(*value); + objEmpty = ((*value)->length == 0); } if ((flags & TK_OPTION_NULL_OK) && objEmpty) { *value = NULL; } else { - string = Tcl_GetStringFromObj((*value), &length); + string = Tcl_GetString(*value); Tcl_UtfToUpper(string); if (strcmp(string, "BAD") == 0) { - Tcl_SetResult(interp, "expected good value, got \"BAD\"", - TCL_STATIC); + Tcl_SetObjResult(interp, Tcl_NewStringObj("expected good value, got \"BAD\"", -1)); return TCL_ERROR; } } if (internalPtr != NULL) { - if ((*value) != NULL) { - string = Tcl_GetStringFromObj((*value), &length); - newStr = ckalloc(length + 1); + if (*value != NULL) { + string = Tcl_GetString(*value); + newStr = ckalloc((*value)->length + 1); strcpy(newStr, string); } else { newStr = NULL; diff --git a/generic/tkText.c b/generic/tkText.c index e7b1c4d..3079417 100644 --- a/generic/tkText.c +++ b/generic/tkText.c @@ -211,18 +211,18 @@ static const Tk_OptionSpec optionSpecs[] = { TK_OPTION_NULL_OK, DEF_TEXT_SELECT_BD_MONO, 0}, {TK_OPTION_COLOR, "-selectforeground", "selectForeground", "Background", DEF_TEXT_SELECT_FG_COLOR, -1, Tk_Offset(TkText, selFgColorPtr), - TK_CONFIG_NULL_OK, DEF_TEXT_SELECT_FG_MONO, 0}, + TK_OPTION_NULL_OK, DEF_TEXT_SELECT_FG_MONO, 0}, {TK_OPTION_BOOLEAN, "-setgrid", "setGrid", "SetGrid", DEF_TEXT_SET_GRID, -1, Tk_Offset(TkText, setGrid), 0, 0, 0}, {TK_OPTION_PIXELS, "-spacing1", "spacing1", "Spacing", DEF_TEXT_SPACING1, -1, Tk_Offset(TkText, spacing1), - TK_OPTION_DONT_SET_DEFAULT, 0 , TK_TEXT_LINE_GEOMETRY }, + 0, 0 , TK_TEXT_LINE_GEOMETRY }, {TK_OPTION_PIXELS, "-spacing2", "spacing2", "Spacing", DEF_TEXT_SPACING2, -1, Tk_Offset(TkText, spacing2), - TK_OPTION_DONT_SET_DEFAULT, 0 , TK_TEXT_LINE_GEOMETRY }, + 0, 0 , TK_TEXT_LINE_GEOMETRY }, {TK_OPTION_PIXELS, "-spacing3", "spacing3", "Spacing", DEF_TEXT_SPACING3, -1, Tk_Offset(TkText, spacing3), - TK_OPTION_DONT_SET_DEFAULT, 0 , TK_TEXT_LINE_GEOMETRY }, + 0, 0 , TK_TEXT_LINE_GEOMETRY }, {TK_OPTION_CUSTOM, "-startline", NULL, NULL, NULL, -1, Tk_Offset(TkText, start), TK_OPTION_NULL_OK, &lineOption, TK_TEXT_LINE_RANGE}, @@ -402,6 +402,7 @@ static Tcl_Obj * TextGetText(const TkText *textPtr, const TkTextIndex *index2, int visibleOnly); static void GenerateModifiedEvent(TkText *textPtr); static void UpdateDirtyFlag(TkSharedText *sharedPtr); +static void RunAfterSyncCmd(ClientData clientData); static void TextPushUndoAction(TkText *textPtr, Tcl_Obj *undoString, int insert, const TkTextIndex *index1Ptr, @@ -580,14 +581,6 @@ CreateWidget( textPtr->end = NULL; } - /* - * Register with the B-tree. In some sense it would be best if we could do - * this later (after configuration options), so that any changes to - * start,end do not require a total recalculation. - */ - - TkBTreeAddClient(sharedPtr->tree, textPtr, textPtr->charHeight); - textPtr->state = TK_TEXT_STATE_NORMAL; textPtr->relief = TK_RELIEF_FLAT; textPtr->cursor = None; @@ -598,6 +591,14 @@ CreateWidget( textPtr->prevHeight = Tk_Height(newWin); /* + * Register with the B-tree. In some sense it would be best if we could do + * this later (after configuration options), so that any changes to + * start,end do not require a total recalculation. + */ + + TkBTreeAddClient(sharedPtr->tree, textPtr, textPtr->charHeight); + + /* * This will add refCounts to textPtr. */ @@ -702,15 +703,16 @@ TextWidgetObjCmd( static const char *const optionStrings[] = { "bbox", "cget", "compare", "configure", "count", "debug", "delete", "dlineinfo", "dump", "edit", "get", "image", "index", "insert", - "mark", "peer", "replace", "scan", "search", "see", "tag", "window", - "xview", "yview", NULL + "mark", "peer", "pendingsync", "replace", "scan", "search", + "see", "sync", "tag", "window", "xview", "yview", NULL }; enum options { TEXT_BBOX, TEXT_CGET, TEXT_COMPARE, TEXT_CONFIGURE, TEXT_COUNT, TEXT_DEBUG, TEXT_DELETE, TEXT_DLINEINFO, TEXT_DUMP, TEXT_EDIT, TEXT_GET, TEXT_IMAGE, TEXT_INDEX, TEXT_INSERT, TEXT_MARK, - TEXT_PEER, TEXT_REPLACE, TEXT_SCAN, TEXT_SEARCH, TEXT_SEE, - TEXT_TAG, TEXT_WINDOW, TEXT_XVIEW, TEXT_YVIEW + TEXT_PEER, TEXT_PENDINGSYNC, TEXT_REPLACE, TEXT_SCAN, + TEXT_SEARCH, TEXT_SEE, TEXT_SYNC, TEXT_TAG, TEXT_WINDOW, + TEXT_XVIEW, TEXT_YVIEW }; if (objc < 2) { @@ -718,8 +720,8 @@ TextWidgetObjCmd( return TCL_ERROR; } - if (Tcl_GetIndexFromObj(interp, objv[1], optionStrings, "option", 0, - &index) != TCL_OK) { + if (Tcl_GetIndexFromObjStruct(interp, objv[1], optionStrings, + sizeof(char *), "option", 0, &index) != TCL_OK) { return TCL_ERROR; } textPtr->refCount++; @@ -859,9 +861,10 @@ TextWidgetObjCmd( for (i = 2; i < objc-2; i++) { int value, length; - const char *option = Tcl_GetStringFromObj(objv[i], &length); + const char *option = Tcl_GetString(objv[i]); char c; + length = objv[i]->length; if (length < 2 || option[0] != '-') { goto badOption; } @@ -880,7 +883,7 @@ TextWidgetObjCmd( } else if (c == 'd' && (length > 8) && !strncmp("-displaylines", option, (unsigned) length)) { TkTextLine *fromPtr, *lastPtr; - TkTextIndex index; + TkTextIndex index, index2; int compare = TkTextIndexCmp(indexFromPtr, indexToPtr); value = 0; @@ -915,35 +918,44 @@ TextWidgetObjCmd( /* * We're going to count up all display lines in the logical * line of 'indexFromPtr' up to, but not including the logical - * line of 'indexToPtr', and then subtract off what we didn't - * want from 'from' and add on what we didn't count from 'to. + * line of 'indexToPtr' (except if this line is elided), and + * then subtract off what came in too much from elided lines, + * also subtract off what we didn't want from 'from' and add + * on what we didn't count from 'to'. */ - while (index.linePtr != indexToPtr->linePtr) { - value += TkTextUpdateOneLine(textPtr, fromPtr,0,&index,0); - - /* - * We might have skipped past indexToPtr, if we have - * multiple logical lines in a single display line. - */ - if (TkTextIndexCmp(&index,indexToPtr) > 0) { - break; - } + while (TkTextIndexCmp(&index,indexToPtr) < 0) { + value += TkTextUpdateOneLine(textPtr, index.linePtr, + 0, &index, 0); } - /* - * Now we need to adjust the count to add on the number of - * display lines in the last logical line, and subtract off - * the number of display lines overcounted in the first - * logical line. This logic is still ok if both indices are in - * the same logical line. - */ + index2 = index; + + /* + * Now we need to adjust the count to: + * - subtract off the number of display lines between + * indexToPtr and index2, since we might have skipped past + * indexToPtr, if we have several logical lines in a + * single display line + * - subtract off the number of display lines overcounted + * in the first logical line + * - add on the number of display lines in the last logical + * line + * This logic is still ok if both indexFromPtr and indexToPtr + * are in the same logical line. + */ + index = *indexToPtr; + index.byteIndex = 0; + while (TkTextIndexCmp(&index,&index2) < 0) { + value -= TkTextUpdateOneLine(textPtr, index.linePtr, + 0, &index, 0); + } index.linePtr = indexFromPtr->linePtr; index.byteIndex = 0; while (1) { TkTextFindDisplayLineEnd(textPtr, &index, 1, NULL); - if (index.byteIndex >= indexFromPtr->byteIndex) { + if (TkTextIndexCmp(&index,indexFromPtr) >= 0) { break; } TkTextIndexForwBytes(textPtr, &index, 1, &index); @@ -955,7 +967,7 @@ TextWidgetObjCmd( index.byteIndex = 0; while (1) { TkTextFindDisplayLineEnd(textPtr, &index, 1, NULL); - if (index.byteIndex >= indexToPtr->byteIndex) { + if (TkTextIndexCmp(&index,indexToPtr) >= 0) { break; } TkTextIndexForwBytes(textPtr, &index, 1, &index); @@ -1260,12 +1272,14 @@ TextWidgetObjCmd( i = 2; if (objc > 3) { - name = Tcl_GetStringFromObj(objv[i], &length); + name = Tcl_GetString(objv[i]); + length = objv[i]->length; if (length > 1 && name[0] == '-') { if (strncmp("-displaychars", name, (unsigned) length) == 0) { i++; visible = 1; - name = Tcl_GetStringFromObj(objv[i], &length); + name = Tcl_GetString(objv[i]); + length = objv[i]->length; } if ((i < objc-1) && (length == 2) && !strcmp("--", name)) { i++; @@ -1380,6 +1394,16 @@ TextWidgetObjCmd( case TEXT_PEER: result = TextPeerCmd(textPtr, interp, objc, objv); break; + case TEXT_PENDINGSYNC: { + if (objc != 2) { + Tcl_WrongNumArgs(interp, 2, objv, NULL); + result = TCL_ERROR; + goto done; + } + Tcl_SetObjResult(interp, + Tcl_NewBooleanObj(TkTextPendingsync(textPtr))); + break; + } case TEXT_REPLACE: { const TkTextIndex *indexFromPtr, *indexToPtr; @@ -1494,6 +1518,39 @@ TextWidgetObjCmd( case TEXT_SEE: result = TkTextSeeCmd(textPtr, interp, objc, objv); break; + case TEXT_SYNC: { + if (objc == 4) { + Tcl_Obj *cmd = objv[3]; + const char *option = Tcl_GetString(objv[2]); + if (strncmp(option, "-command", objv[2]->length)) { + Tcl_AppendResult(interp, "wrong option \"", option, "\": should be \"-command\"", NULL); + result = TCL_ERROR; + goto done; + } + Tcl_IncrRefCount(cmd); + if (TkTextPendingsync(textPtr)) { + if (textPtr->afterSyncCmd) { + Tcl_DecrRefCount(textPtr->afterSyncCmd); + } + textPtr->afterSyncCmd = cmd; + } else { + textPtr->afterSyncCmd = cmd; + Tcl_DoWhenIdle(RunAfterSyncCmd, (ClientData) textPtr); + } + break; + } else if (objc != 2) { + Tcl_WrongNumArgs(interp, 2, objv, "?-command command?"); + result = TCL_ERROR; + goto done; + } + if (textPtr->afterSyncCmd) { + Tcl_DecrRefCount(textPtr->afterSyncCmd); + } + textPtr->afterSyncCmd = NULL; + TkTextUpdateLineMetrics(textPtr, 1, + TkBTreeNumLines(textPtr->sharedTextPtr->tree, textPtr), -1); + break; + } case TEXT_TAG: result = TkTextTagCmd(textPtr, interp, objc, objv); break; @@ -1559,8 +1616,8 @@ SharedTextObjCmd( return TCL_ERROR; } - if (Tcl_GetIndexFromObj(interp, objv[1], optionStrings, "option", 0, - &index) != TCL_OK) { + if (Tcl_GetIndexFromObjStruct(interp, objv[1], optionStrings, + sizeof(char *), "option", 0, &index) != TCL_OK) { return TCL_ERROR; } @@ -1664,8 +1721,8 @@ TextPeerCmd( return TCL_ERROR; } - if (Tcl_GetIndexFromObj(interp, objv[2], peerOptionStrings, - "peer option", 0, &index) != TCL_OK) { + if (Tcl_GetIndexFromObjStruct(interp, objv[2], peerOptionStrings, + sizeof(char *), "peer option", 0, &index) != TCL_OK) { return TCL_ERROR; } @@ -1983,6 +2040,10 @@ DestroyText( textPtr->tkwin = NULL; textPtr->refCount--; Tcl_DeleteCommandFromToken(textPtr->interp, textPtr->widgetCmd); + if (textPtr->afterSyncCmd){ + Tcl_DecrRefCount(textPtr->afterSyncCmd); + textPtr->afterSyncCmd = NULL; + } if (textPtr->refCount == 0) { ckfree(textPtr); } @@ -2332,6 +2393,7 @@ TextWorldChanged( { Tk_FontMetrics fm; int border; + int oldCharHeight = textPtr->charHeight; textPtr->charWidth = Tk_TextWidth(textPtr->tkfont, "0", 1); if (textPtr->charWidth <= 0) { @@ -2343,6 +2405,9 @@ TextWorldChanged( if (textPtr->charHeight <= 0) { textPtr->charHeight = 1; } + if (textPtr->charHeight != oldCharHeight) { + TkBTreeClientRangeChanged(textPtr, textPtr->charHeight); + } border = textPtr->borderWidth + textPtr->highlightWidth; Tk_GeometryRequest(textPtr->tkwin, textPtr->width * textPtr->charWidth + 2*textPtr->padX + 2*border, @@ -2552,9 +2617,9 @@ InsertChars( int *lineAndByteIndex; int resetViewCount; int pixels[2*PIXEL_CLIENTS]; + const char *string = Tcl_GetString(stringPtr); - const char *string = Tcl_GetStringFromObj(stringPtr, &length); - + length = stringPtr->length; if (sharedTextPtr == NULL) { sharedTextPtr = textPtr->sharedTextPtr; } @@ -3010,11 +3075,9 @@ DeleteIndexRange( * The code below is ugly, but it's needed to make sure there is always a * dummy empty line at the end of the text. If the final newline of the * file (just before the dummy line) is being deleted, then back up index - * to just before the newline. If there is a newline just before the first - * character being deleted, then back up the first index too, so that an - * even number of lines gets deleted. Furthermore, remove any tags that - * are present on the newline that isn't going to be deleted after all - * (this simulates deleting the newline and then adding a "clean" one back + * to just before the newline. Furthermore, remove any tags that are + * present on the newline that isn't going to be deleted after all (this + * simulates deleting the newline and then adding a "clean" one back * again). Note that index1 and index2 might now be equal again which * means that no text will be deleted but tags might be removed. */ @@ -3029,10 +3092,6 @@ DeleteIndexRange( oldIndex2 = index2; TkTextIndexBackChars(NULL, &oldIndex2, 1, &index2, COUNT_INDICES); line2--; - if ((index1.byteIndex == 0) && (line1 != 0)) { - TkTextIndexBackChars(NULL, &index1, 1, &index1, COUNT_INDICES); - line1--; - } arrayPtr = TkBTreeGetTags(&index2, NULL, &arraySize); if (arrayPtr != NULL) { for (i = 0; i < arraySize; i++) { @@ -3713,15 +3772,15 @@ TextSearchCmd( break; } - if (Tcl_GetIndexFromObj(NULL, objv[i], switchStrings, "switch", 0, - &index) != TCL_OK) { + if (Tcl_GetIndexFromObjStruct(NULL, objv[i], switchStrings, + sizeof(char *), "switch", 0, &index) != TCL_OK) { /* * Hide the -hidden option, generating the error description with * the side effects of T_GIFO. */ - (void) Tcl_GetIndexFromObj(interp, objv[i], switchStrings+1, - "switch", 0, &index); + (void) Tcl_GetIndexFromObjStruct(interp, objv[i], switchStrings+1, + sizeof(char *), "switch", 0, &index); return TCL_ERROR; } @@ -4093,7 +4152,8 @@ TextSearchAddNextLine( if (lenPtr != NULL) { if (searchSpecPtr->exact) { - Tcl_GetStringFromObj(theLine, lenPtr); + (void)Tcl_GetString(theLine); + *lenPtr = theLine->length; } else { *lenPtr = Tcl_GetCharLength(theLine); } @@ -4227,7 +4287,11 @@ TextSearchFoundMatch( matchOffset += Tcl_NumUtfChars(segPtr->body.chars, -1); } } else { - leftToScan -= segPtr->size; + if (searchSpecPtr->exact) { + leftToScan -= segPtr->size; + } else { + leftToScan -= Tcl_NumUtfChars(segPtr->body.chars, -1); + } } curIndex.byteIndex += segPtr->size; } @@ -4482,8 +4546,8 @@ TkTextGetTabs( } i += 1; - if (Tcl_GetIndexFromObj(interp, objv[i], tabOptionStrings, - "tab alignment", 0, &index) != TCL_OK) { + if (Tcl_GetIndexFromObjStruct(interp, objv[i], tabOptionStrings, + sizeof(char *), "tab alignment", 0, &index) != TCL_OK) { goto error; } tabPtr->alignment = (TkTextTabAlign) index; @@ -4560,8 +4624,8 @@ TextDumpCmd( if (Tcl_GetString(objv[arg])[0] != '-') { break; } - if (Tcl_GetIndexFromObj(interp, objv[arg], optStrings, "option", 0, - &index) != TCL_OK) { + if (Tcl_GetIndexFromObjStruct(interp, objv[arg], optStrings, + sizeof(char *), "option", 0, &index) != TCL_OK) { return TCL_ERROR; } switch ((enum opts) index) { @@ -4619,7 +4683,8 @@ TextDumpCmd( if (TkTextGetObjIndex(interp, textPtr, objv[arg], &index2) != TCL_OK) { return TCL_ERROR; } - str = Tcl_GetStringFromObj(objv[arg], &length); + str = Tcl_GetString(objv[arg]); + length = objv[arg]->length; if (strncmp(str, "end", (unsigned) length) == 0) { atEnd = 1; } @@ -4936,9 +5001,20 @@ DumpSegment( return 0; } else { int oldStateEpoch = TkBTreeEpoch(textPtr->sharedTextPtr->tree); - - Tcl_VarEval(interp, Tcl_GetString(command), " ", Tcl_GetString(tuple), - NULL); + Tcl_DString buf; + int code; + + Tcl_DStringInit(&buf); + Tcl_DStringAppend(&buf, Tcl_GetString(command), -1); + Tcl_DStringAppend(&buf, " ", -1); + Tcl_DStringAppend(&buf, Tcl_GetString(tuple), -1); + code = Tcl_EvalEx(interp, Tcl_DStringValue(&buf), -1, 0); + Tcl_DStringFree(&buf); + if (code != TCL_OK) { + Tcl_AddErrorInfo(interp, + "\n (segment dumping command executed by text)"); + Tcl_BackgroundException(interp, code); + } Tcl_DecrRefCount(tuple); return ((textPtr->flags & DESTROYED) || TkBTreeEpoch(textPtr->sharedTextPtr->tree) != oldStateEpoch); @@ -5077,8 +5153,8 @@ TextEditCmd( return TCL_ERROR; } - if (Tcl_GetIndexFromObj(interp, objv[2], editOptionStrings, - "edit option", 0, &index) != TCL_OK) { + if (Tcl_GetIndexFromObjStruct(interp, objv[2], editOptionStrings, + sizeof(char *), "edit option", 0, &index) != TCL_OK) { return TCL_ERROR; } @@ -5341,6 +5417,52 @@ UpdateDirtyFlag( /* *---------------------------------------------------------------------- * + * RunAfterSyncCmd -- + * + * This function is called by the event loop and executes the command + * scheduled by [.text sync -command $cmd]. + * + * Results: + * None. + * + * Side effects: + * Anything may happen, depending on $cmd contents. + * + *---------------------------------------------------------------------- + */ + +static void +RunAfterSyncCmd( + ClientData clientData) /* Information about text widget. */ +{ + register TkText *textPtr = (TkText *) clientData; + int code; + + if ((textPtr->tkwin == NULL) || (textPtr->flags & DESTROYED)) { + /* + * The widget has been deleted. Don't do anything. + */ + + if (--textPtr->refCount == 0) { + ckfree((char *) textPtr); + } + return; + } + + Tcl_Preserve((ClientData) textPtr->interp); + code = Tcl_EvalObjEx(textPtr->interp, textPtr->afterSyncCmd, TCL_EVAL_GLOBAL); + if (code == TCL_ERROR) { + Tcl_AddErrorInfo(textPtr->interp, "\n (text sync)"); + Tcl_BackgroundError(textPtr->interp); + } + Tcl_Release((ClientData) textPtr->interp); + Tcl_DecrRefCount(textPtr->afterSyncCmd); + textPtr->afterSyncCmd = NULL; +} + +/* + *---------------------------------------------------------------------- + * * SearchPerform -- * * Overall control of search process. Is given a pattern, a starting @@ -5541,7 +5663,8 @@ SearchCore( * it has dual purpose. */ - pattern = Tcl_GetStringFromObj(patObj, &matchLength); + pattern = Tcl_GetString(patObj); + matchLength = patObj->length; nl = strchr(pattern, '\n'); /* @@ -6609,16 +6732,14 @@ static int ObjectIsEmpty( Tcl_Obj *objPtr) /* Object to test. May be NULL. */ { - int length; - if (objPtr == NULL) { return 1; } if (objPtr->bytes != NULL) { return (objPtr->length == 0); } - Tcl_GetStringFromObj(objPtr, &length); - return (length == 0); + (void)Tcl_GetString(objPtr); + return (objPtr->length == 0); } /* @@ -6643,8 +6764,8 @@ int TkpTesttextCmd( ClientData clientData, /* Main window for application. */ Tcl_Interp *interp, /* Current interpreter. */ - int argc, /* Number of arguments. */ - const char **argv) /* Argument strings. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument strings. */ { TkText *textPtr; size_t len; @@ -6653,45 +6774,41 @@ TkpTesttextCmd( char buf[64]; Tcl_CmdInfo info; - if (argc < 3) { + if (objc < 3) { return TCL_ERROR; } - if (Tcl_GetCommandInfo(interp, argv[1], &info) == 0) { + if (Tcl_GetCommandInfo(interp, Tcl_GetString(objv[1]), &info) == 0) { return TCL_ERROR; } - if (info.isNativeObjectProc) { - textPtr = info.objClientData; - } else { - textPtr = info.clientData; - } - len = strlen(argv[2]); - if (strncmp(argv[2], "byteindex", len) == 0) { - if (argc != 5) { + textPtr = info.objClientData; + len = strlen(Tcl_GetString(objv[2])); + if (strncmp(Tcl_GetString(objv[2]), "byteindex", len) == 0) { + if (objc != 5) { return TCL_ERROR; } - lineIndex = atoi(argv[3]) - 1; - byteIndex = atoi(argv[4]); + lineIndex = atoi(Tcl_GetString(objv[3])) - 1; + byteIndex = atoi(Tcl_GetString(objv[4])); TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr, lineIndex, byteIndex, &index); - } else if (strncmp(argv[2], "forwbytes", len) == 0) { - if (argc != 5) { + } else if (strncmp(Tcl_GetString(objv[2]), "forwbytes", len) == 0) { + if (objc != 5) { return TCL_ERROR; } - if (TkTextGetIndex(interp, textPtr, argv[3], &index) != TCL_OK) { + if (TkTextGetIndex(interp, textPtr, Tcl_GetString(objv[3]), &index) != TCL_OK) { return TCL_ERROR; } - byteOffset = atoi(argv[4]); + byteOffset = atoi(Tcl_GetString(objv[4])); TkTextIndexForwBytes(textPtr, &index, byteOffset, &index); - } else if (strncmp(argv[2], "backbytes", len) == 0) { - if (argc != 5) { + } else if (strncmp(Tcl_GetString(objv[2]), "backbytes", len) == 0) { + if (objc != 5) { return TCL_ERROR; } - if (TkTextGetIndex(interp, textPtr, argv[3], &index) != TCL_OK) { + if (TkTextGetIndex(interp, textPtr, Tcl_GetString(objv[3]), &index) != TCL_OK) { return TCL_ERROR; } - byteOffset = atoi(argv[4]); + byteOffset = atoi(Tcl_GetString(objv[4])); TkTextIndexBackBytes(textPtr, &index, byteOffset, &index); } else { return TCL_ERROR; diff --git a/generic/tkText.h b/generic/tkText.h index fb9eab2..fc92644 100644 --- a/generic/tkText.h +++ b/generic/tkText.h @@ -168,7 +168,7 @@ typedef struct TkTextSegment { int size; /* Size of this segment (# of bytes of index * space it occupies). */ union { - char chars[1]; /* Characters that make up character info. + char chars[2]; /* Characters that make up character info. * Actual length varies to hold as many * characters as needed.*/ TkTextToggle toggle; /* Information about tag toggle. */ @@ -785,6 +785,8 @@ typedef struct TkText { * statements. */ int autoSeparators; /* Non-zero means the separators will be * inserted automatically. */ + Tcl_Obj *afterSyncCmd; /* Command to be executed when lines are up to + * date */ } TkText; /* @@ -1066,6 +1068,9 @@ MODULE_SCOPE void TkTextIndexBackChars(const TkText *textPtr, TkTextIndex *dstPtr, TkTextCountType type); MODULE_SCOPE int TkTextIndexCmp(const TkTextIndex *index1Ptr, const TkTextIndex *index2Ptr); +MODULE_SCOPE int TkTextIndexCountBytes(const TkText *textPtr, + const TkTextIndex *index1Ptr, + const TkTextIndex *index2Ptr); MODULE_SCOPE int TkTextIndexCount(const TkText *textPtr, const TkTextIndex *index1Ptr, const TkTextIndex *index2Ptr, @@ -1106,6 +1111,7 @@ MODULE_SCOPE int TkTextMarkNameToIndex(TkText *textPtr, MODULE_SCOPE void TkTextMarkSegToIndex(TkText *textPtr, TkTextSegment *markPtr, TkTextIndex *indexPtr); MODULE_SCOPE void TkTextEventuallyRepick(TkText *textPtr); +MODULE_SCOPE Bool TkTextPendingsync(TkText *textPtr); MODULE_SCOPE void TkTextPickCurrent(TkText *textPtr, XEvent *eventPtr); MODULE_SCOPE void TkTextPixelIndex(TkText *textPtr, int x, int y, TkTextIndex *indexPtr, int *nearest); diff --git a/generic/tkTextBTree.c b/generic/tkTextBTree.c index e34dae7..0fdc280 100644 --- a/generic/tkTextBTree.c +++ b/generic/tkTextBTree.c @@ -1112,7 +1112,7 @@ TkBTreeInsertChars( /* * I don't believe it's possible for either of the two lines passed to * this function to be the last line of text, but the function is robust - * to that case anyway. (We must never re-calculated the line height of + * to that case anyway. (We must never re-calculate the line height of * the last line). */ @@ -1879,8 +1879,7 @@ TkBTreePreviousLine( * number of pixels in the widget. * * Results: - * The result is the index of linePtr within the tree, where 0 - * corresponds to the first line in the tree. + * The result is the pixel height of the top of the given line. * * Side effects: * None. @@ -1989,7 +1988,7 @@ TkBTreeLinesTo( } } if (textPtr != NULL) { - /* + /* * The index to return must be relative to textPtr, not to the entire * tree. Take care to never return a negative index when linePtr * denotes a line before -startline, or an index larger than the @@ -3616,20 +3615,6 @@ TkTextIsElided( infoPtr->elidePriority = -1; for (i = infoPtr->numTags-1; i >=0; i--) { if (infoPtr->tagCnts[i] & 1) { - /* - * Who would make the selection elided? - */ - - if ((tagPtr == textPtr->selTagPtr) - && !(textPtr->flags & GOT_FOCUS) - && (textPtr->inactiveSelBorder == NULL -#ifdef MAC_OSX_TK - /* Don't show inactive selection in disabled widgets. */ - || textPtr->state == TK_TEXT_STATE_DISABLED -#endif - )) { - continue; - } infoPtr->elide = infoPtr->tagPtrs[i]->elide; /* diff --git a/generic/tkTextDisp.c b/generic/tkTextDisp.c index d75f61c..1eea37d 100644 --- a/generic/tkTextDisp.c +++ b/generic/tkTextDisp.c @@ -16,7 +16,7 @@ #include "tkInt.h" #include "tkText.h" -#ifdef __WIN32__ +#ifdef _WIN32 #include "tkWinInt.h" #elif defined(__CYGWIN__) #include "tkUnixInt.h" @@ -243,7 +243,8 @@ typedef struct DLine { * top to bottom. Note: the next DLine doesn't * always correspond to the next line of text: * (a) can have multiple DLines for one text - * line, and (b) can have gaps where DLine's + * line (wrapping), (b) can have elided newlines, + * and (c) can have gaps where DLine's * have been deleted because they're out of * date. */ int flags; /* Various flag bits: see below for values. */ @@ -543,7 +544,8 @@ static void DisplayDLine(TkText *textPtr, DLine *dlPtr, static void DisplayLineBackground(TkText *textPtr, DLine *dlPtr, DLine *prevPtr, Pixmap pixmap); static void DisplayText(ClientData clientData); -static DLine * FindDLine(DLine *dlPtr, const TkTextIndex *indexPtr); +static DLine * FindDLine(TkText *textPtr, DLine *dlPtr, + const TkTextIndex *indexPtr); static void FreeDLines(TkText *textPtr, DLine *firstPtr, DLine *lastPtr, int action); static void FreeStyle(TkText *textPtr, TextStyle *stylePtr); @@ -589,7 +591,10 @@ static int TextGetScrollInfoObj(Tcl_Interp *interp, Tcl_Obj *const objv[], double *dblPtr, int *intPtr); static void AsyncUpdateLineMetrics(ClientData clientData); +static void GenerateWidgetViewSyncEvent(TkText *textPtr, Bool InSync); static void AsyncUpdateYScrollbar(ClientData clientData); +static int IsStartOfNotMergedLine(TkText *textPtr, + CONST TkTextIndex *indexPtr); /* * Result values returned by TextGetScrollInfoObj: @@ -655,17 +660,8 @@ TkTextCreateDInfo( dInfoPtr->metricEpoch = -1; dInfoPtr->metricIndex.textPtr = NULL; dInfoPtr->metricIndex.linePtr = NULL; - - /* - * Add a refCount for each of the idle call-backs. - */ - - textPtr->refCount++; - dInfoPtr->lineUpdateTimer = Tcl_CreateTimerHandler(0, - AsyncUpdateLineMetrics, textPtr); - textPtr->refCount++; - dInfoPtr->scrollbarTimer = Tcl_CreateTimerHandler(200, - AsyncUpdateYScrollbar, textPtr); + dInfoPtr->lineUpdateTimer = NULL; + dInfoPtr->scrollbarTimer = NULL; textPtr->dInfoPtr = dInfoPtr; } @@ -1020,7 +1016,7 @@ FreeStyle( * whose leftmost character is given by indexPtr. * * Results: - * The return value is a pointer to a DLine structure desribing the + * The return value is a pointer to a DLine structure describing the * display line. All fields are filled in and correct except for y and * nextPtr. * @@ -1644,7 +1640,7 @@ LayoutDLine( * Make one more pass over the line to recompute various things like its * height, length, and total number of bytes. Also modify the x-locations * of chunks to reflect justification. If we're not wrapping, I'm not sure - * what is the best way to handle left and center justification: should + * what is the best way to handle right and center justification: should * the total length, for purposes of justification, be (a) the window * width, (b) the length of the longest line in the window, or (c) the * length of the longest line in the text? (c) isn't available, (b) seems @@ -1759,7 +1755,7 @@ UpdateDisplayInfo( */ index = textPtr->topIndex; - dlPtr = FindDLine(dInfoPtr->dLinePtr, &index); + dlPtr = FindDLine(textPtr, dInfoPtr->dLinePtr, &index); if ((dlPtr != NULL) && (dlPtr != dInfoPtr->dLinePtr)) { FreeDLines(textPtr, dInfoPtr->dLinePtr, dlPtr, DLINE_UNLINK); } @@ -1909,7 +1905,7 @@ UpdateDisplayInfo( prevPtr->index.linePtr) != lineHeight)) { /* * The logical line height we just calculated is actually - * differnt to the currently cached height of the text line. + * different to the currently cached height of the text line. * That is fine (the text line heights are only calculated * asynchronously), but we must update the cached height so * that any counts made with DLine pointers are the same as @@ -2222,7 +2218,7 @@ UpdateDisplayInfo( * Here's a problem: see the tests textDisp-29.2.1-4 * * If the widget is being created, but has not yet been configured it will - * have a maxY of 1 above, and we we won't have examined all the lines + * have a maxY of 1 above, and we won't have examined all the lines * (just the first line, in fact), and so maxOffset will not be a true * reflection of the widget's lines. Therefore we must not overwrite the * original newXPixelOffset in this case. @@ -2537,7 +2533,7 @@ DisplayLineBackground( * current x coordinate? */ int matchRight; /* Does line's style match its neighbor just * to the right of the current x-coord? */ - int minX, maxX, xOffset; + int minX, maxX, xOffset, bw; StyleValues *sValuePtr; Display *display; #ifndef TK_NO_DOUBLE_BUFFERING @@ -2608,16 +2604,25 @@ DisplayLineBackground( rightX = leftX + 32767; } + /* + * Prevent the borders from leaking on adjacent characters, + * which would happen for too large border width. + */ + + bw = sValuePtr->borderWidth; + if (leftX + sValuePtr->borderWidth > rightX) { + bw = rightX - leftX; + } + XFillRectangle(display, pixmap, chunkPtr->stylePtr->bgGC, leftX + xOffset, y, (unsigned int) (rightX - leftX), (unsigned int) dlPtr->height); if (sValuePtr->relief != TK_RELIEF_FLAT) { Tk_3DVerticalBevel(textPtr->tkwin, pixmap, sValuePtr->border, - leftX + xOffset, y, sValuePtr->borderWidth, - dlPtr->height, 1, sValuePtr->relief); + leftX + xOffset, y, bw, dlPtr->height, 1, + sValuePtr->relief); Tk_3DVerticalBevel(textPtr->tkwin, pixmap, sValuePtr->border, - rightX - sValuePtr->borderWidth + xOffset, - y, sValuePtr->borderWidth, dlPtr->height, 0, + rightX - bw + xOffset, y, bw, dlPtr->height, 0, sValuePtr->relief); } } @@ -2714,22 +2719,29 @@ DisplayLineBackground( matchRight = (nextPtr2 != NULL) && SAME_BACKGROUND(nextPtr2->stylePtr, chunkPtr->stylePtr); if (matchLeft && !matchRight) { + bw = sValuePtr->borderWidth; + if (rightX2 - sValuePtr->borderWidth < leftX) { + bw = rightX2 - leftX; + } if (sValuePtr->relief != TK_RELIEF_FLAT) { Tk_3DVerticalBevel(textPtr->tkwin, pixmap, sValuePtr->border, - rightX2 - sValuePtr->borderWidth + xOffset, y, - sValuePtr->borderWidth, sValuePtr->borderWidth, 0, - sValuePtr->relief); + rightX2 - bw + xOffset, y, bw, + sValuePtr->borderWidth, 0, sValuePtr->relief); } - leftX = rightX2 - sValuePtr->borderWidth; + leftX = rightX2 - bw; leftXIn = 0; } else if (!matchLeft && matchRight && (sValuePtr->relief != TK_RELIEF_FLAT)) { + bw = sValuePtr->borderWidth; + if (rightX2 + sValuePtr->borderWidth > rightX) { + bw = rightX - rightX2; + } Tk_3DVerticalBevel(textPtr->tkwin, pixmap, sValuePtr->border, - rightX2 + xOffset, y, sValuePtr->borderWidth, - sValuePtr->borderWidth, 1, sValuePtr->relief); + rightX2 + xOffset, y, bw, sValuePtr->borderWidth, + 1, sValuePtr->relief); Tk_3DHorizontalBevel(textPtr->tkwin, pixmap, sValuePtr->border, - leftX + xOffset, y, rightX2 + sValuePtr->borderWidth - - leftX, sValuePtr->borderWidth, leftXIn, 0, 1, + leftX + xOffset, y, rightX2 + bw - leftX, + sValuePtr->borderWidth, leftXIn, 0, 1, sValuePtr->relief); } @@ -2761,7 +2773,7 @@ DisplayLineBackground( chunkPtr2 = NULL; if (dlPtr->nextPtr != NULL && dlPtr->nextPtr->chunkPtr != NULL) { /* - * Find the chunk in the previous line that covers leftX. + * Find the chunk in the next line that covers leftX. */ nextPtr2 = dlPtr->nextPtr->chunkPtr; @@ -2817,26 +2829,33 @@ DisplayLineBackground( matchRight = (nextPtr2 != NULL) && SAME_BACKGROUND(nextPtr2->stylePtr, chunkPtr->stylePtr); if (matchLeft && !matchRight) { + bw = sValuePtr->borderWidth; + if (rightX2 - sValuePtr->borderWidth < leftX) { + bw = rightX2 - leftX; + } if (sValuePtr->relief != TK_RELIEF_FLAT) { Tk_3DVerticalBevel(textPtr->tkwin, pixmap, sValuePtr->border, - rightX2 - sValuePtr->borderWidth + xOffset, + rightX2 - bw + xOffset, y + dlPtr->height - sValuePtr->borderWidth, - sValuePtr->borderWidth, sValuePtr->borderWidth, 0, - sValuePtr->relief); + bw, sValuePtr->borderWidth, 0, sValuePtr->relief); } - leftX = rightX2 - sValuePtr->borderWidth; + leftX = rightX2 - bw; leftXIn = 1; } else if (!matchLeft && matchRight && (sValuePtr->relief != TK_RELIEF_FLAT)) { + bw = sValuePtr->borderWidth; + if (rightX2 + sValuePtr->borderWidth > rightX) { + bw = rightX - rightX2; + } Tk_3DVerticalBevel(textPtr->tkwin, pixmap, sValuePtr->border, - rightX2 + xOffset, y + dlPtr->height - - sValuePtr->borderWidth, sValuePtr->borderWidth, + rightX2 + xOffset, + y + dlPtr->height - sValuePtr->borderWidth, bw, sValuePtr->borderWidth, 1, sValuePtr->relief); Tk_3DHorizontalBevel(textPtr->tkwin, pixmap, sValuePtr->border, - leftX + xOffset, y + dlPtr->height - - sValuePtr->borderWidth, rightX2 + sValuePtr->borderWidth - - leftX, sValuePtr->borderWidth, leftXIn, 1, 0, - sValuePtr->relief); + leftX + xOffset, + y + dlPtr->height - sValuePtr->borderWidth, + rightX2 + bw - leftX, sValuePtr->borderWidth, leftXIn, + 1, 0, sValuePtr->relief); } nextChunk2b: @@ -2886,9 +2905,10 @@ AsyncUpdateLineMetrics( dInfoPtr->lineUpdateTimer = NULL; - if ((textPtr->tkwin == NULL) || (textPtr->flags & DESTROYED)) { + if ((textPtr->tkwin == NULL) || (textPtr->flags & DESTROYED) + || !Tk_IsMapped(textPtr->tkwin)) { /* - * The widget has been deleted. Don't do anything. + * The widget has been deleted, or is not mapped. Don't do anything. */ if (--textPtr->refCount == 0) { @@ -2922,6 +2942,8 @@ AsyncUpdateLineMetrics( lineNum = TkTextUpdateLineMetrics(textPtr, lineNum, dInfoPtr->lastMetricUpdateLine, 256); + dInfoPtr->currentMetricUpdateLine = lineNum; + if (tkTextDebug) { char buffer[2 * TCL_INTEGER_SPACE + 1]; @@ -2939,16 +2961,37 @@ AsyncUpdateLineMetrics( /* * We have looped over all lines, so we're done. We must release our * refCount on the widget (the timer token was already set to NULL - * above). + * above). If there is a registered aftersync command, run that first. */ + if (textPtr->afterSyncCmd) { + int code; + Tcl_Preserve((ClientData) textPtr->interp); + code = Tcl_EvalObjEx(textPtr->interp, textPtr->afterSyncCmd, + TCL_EVAL_GLOBAL); + if (code == TCL_ERROR) { + Tcl_AddErrorInfo(textPtr->interp, "\n (text sync)"); + Tcl_BackgroundError(textPtr->interp); + } + Tcl_Release((ClientData) textPtr->interp); + Tcl_DecrRefCount(textPtr->afterSyncCmd); + textPtr->afterSyncCmd = NULL; + } + + /* + * Fire the <<WidgetViewSync>> event since the widget view is in sync + * with its internal data (actually it will be after the next trip + * through the event loop, because the widget redraws at idle-time). + */ + + GenerateWidgetViewSyncEvent(textPtr, 1); + textPtr->refCount--; if (textPtr->refCount == 0) { ckfree(textPtr); } return; } - dInfoPtr->currentMetricUpdateLine = lineNum; /* * Re-arm the timer. We already have a refCount on the text widget so no @@ -2962,6 +3005,45 @@ AsyncUpdateLineMetrics( /* *---------------------------------------------------------------------- * + * GenerateWidgetViewSyncEvent -- + * + * Send the <<WidgetViewSync>> event related to the text widget + * line metrics asynchronous update. + * This is equivalent to: + * event generate $textWidget <<WidgetViewSync>> -detail $s + * where $s is the sync status: true (when the widget view is in + * sync with its internal data) or false (when it is not). + * + * Results: + * None + * + * Side effects: + * If corresponding bindings are present, they will trigger. + * + *---------------------------------------------------------------------- + */ + +static void +GenerateWidgetViewSyncEvent( + TkText *textPtr, /* Information about text widget. */ + Bool InSync) /* True if in sync, false otherwise */ +{ + union {XEvent general; XVirtualEvent virtual;} event; + + memset(&event, 0, sizeof(event)); + event.general.xany.type = VirtualEvent; + event.general.xany.serial = NextRequest(Tk_Display(textPtr->tkwin)); + event.general.xany.send_event = False; + event.general.xany.window = Tk_WindowId(textPtr->tkwin); + event.general.xany.display = Tk_Display(textPtr->tkwin); + event.virtual.name = Tk_GetUid("WidgetViewSync"); + event.virtual.user_data = Tcl_NewBooleanObj(InSync); + Tk_HandleEvent(&event.general); +} + +/* + *---------------------------------------------------------------------- + * * TkTextUpdateLineMetrics -- * * This function updates the pixel height calculations of a range of @@ -3334,6 +3416,7 @@ TextInvalidateLineMetrics( textPtr->refCount++; dInfoPtr->lineUpdateTimer = Tcl_CreateTimerHandler(1, AsyncUpdateLineMetrics, textPtr); + GenerateWidgetViewSyncEvent(textPtr, 0); } } @@ -3385,7 +3468,7 @@ TkTextFindDisplayLineEnd( { TkTextIndex index; - if (!end && indexPtr->byteIndex == 0) { + if (!end && IsStartOfNotMergedLine(textPtr, indexPtr)) { /* * Nothing to do. */ @@ -3463,7 +3546,8 @@ TkTextFindDisplayLineEnd( */ *xOffset = DlineXOfIndex(textPtr, dlPtr, - indexPtr->byteIndex - dlPtr->index.byteIndex); + TkTextIndexCountBytes(textPtr, &dlPtr->index, + indexPtr)); } if (end) { /* @@ -3533,6 +3617,27 @@ CalculateDisplayLineHeight( DLine *dlPtr; int pixelHeight; + if (tkTextDebug) { + int oldtkTextDebug = tkTextDebug; + /* + * Check that the indexPtr we are given really is at the start of a + * display line. The gymnastics with tkTextDebug is to prevent + * failure of a test suite test, that checks that lines are rendered + * exactly once. TkTextFindDisplayLineEnd is used here for checking + * indexPtr but it calls LayoutDLine/FreeDLine which makes the + * counting wrong. The debug mode shall therefore be switched off + * when calling TkTextFindDisplayLineEnd. + */ + + TkTextIndex indexPtr2 = *indexPtr; + tkTextDebug = 0; + TkTextFindDisplayLineEnd(textPtr, &indexPtr2, 0, NULL); + tkTextDebug = oldtkTextDebug; + if (TkTextIndexCmp(&indexPtr2,indexPtr) != 0) { + Tcl_Panic("CalculateDisplayLineHeight called with bad indexPtr"); + } + } + /* * Special case for artificial last line. May be better to move this * inside LayoutDLine. @@ -3599,26 +3704,44 @@ TkTextIndexYPixels( { int pixelHeight; TkTextIndex index; + int alreadyStartOfLine = 1; + + /* + * Find the index denoting the closest position being at the same time + * the start of a logical line above indexPtr and the start of a display + * line. + */ - pixelHeight = TkBTreePixelsTo(textPtr, indexPtr->linePtr); + index = *indexPtr; + while (1) { + TkTextFindDisplayLineEnd(textPtr, &index, 0, NULL); + if (index.byteIndex == 0) { + break; + } + TkTextIndexBackBytes(textPtr, &index, 1, &index); + alreadyStartOfLine = 0; + } + + pixelHeight = TkBTreePixelsTo(textPtr, index.linePtr); /* - * Iterate through all display-lines corresponding to the single logical - * line belonging to indexPtr, adding up the pixel height of each such - * display line as we go along, until we go past 'indexPtr'. + * Shortcut to avoid layout of a superfluous display line. We know there + * is nothing more to add up to the height if the index we were given was + * already on the first display line of a logical line. */ - if (indexPtr->byteIndex == 0) { - return pixelHeight; + if (alreadyStartOfLine) { + return pixelHeight; } - index.tree = textPtr->sharedTextPtr->tree; - index.linePtr = indexPtr->linePtr; - index.byteIndex = 0; - index.textPtr = NULL; + /* + * Iterate through display lines, starting at the logical line belonging + * to index, adding up the pixel height of each such display line as we + * go along, until we go past 'indexPtr'. + */ while (1) { - int bytes, height; + int bytes, height, compare; /* * Currently this call doesn't have many side-effects. However, if in @@ -3630,9 +3753,10 @@ TkTextIndexYPixels( height = CalculateDisplayLineHeight(textPtr, &index, &bytes, NULL); - index.byteIndex += bytes; + TkTextIndexForwBytes(textPtr, &index, bytes, &index); - if (index.byteIndex > indexPtr->byteIndex) { + compare = TkTextIndexCmp(&index,indexPtr); + if (compare > 0) { return pixelHeight; } @@ -3640,7 +3764,7 @@ TkTextIndexYPixels( pixelHeight += height; } - if (index.byteIndex == indexPtr->byteIndex) { + if (compare == 0) { return pixelHeight; } } @@ -3704,10 +3828,26 @@ TkTextUpdateOneLine( } /* + * CalculateDisplayLineHeight _must_ be called (below) with an index at + * the beginning of a display line. Force this to happen. This is needed + * when TkTextUpdateOneLine is called with a line that is merged with its + * previous line: the number of merged logical lines in a display line is + * calculated correctly only when CalculateDisplayLineHeight receives + * an index at the beginning of a display line. In turn this causes the + * merged lines to receive their correct zero pixel height in + * TkBTreeAdjustPixelHeight. + */ + + TkTextFindDisplayLineEnd(textPtr, indexPtr, 0, NULL); + linePtr = indexPtr->linePtr; + + /* * Iterate through all display-lines corresponding to the single logical - * line 'linePtr', adding up the pixel height of each such display line as - * we go along. The final total is, therefore, the height of the logical - * line. + * line 'linePtr' (and lines merged into this line due to eol elision), + * adding up the pixel height of each such display line as we go along. + * The final total is, therefore, the total height of all display lines + * made up by the logical line 'linePtr' and subsequent logical lines + * merged into this line. */ displayLines = 0; @@ -3724,7 +3864,7 @@ TkTextUpdateOneLine( * test below this while loop. */ - height = CalculateDisplayLineHeight(textPtr, indexPtr, &bytes, + height = CalculateDisplayLineHeight(textPtr, indexPtr, &bytes, &logicalLines); if (height > 0) { @@ -3738,44 +3878,31 @@ TkTextUpdateOneLine( break; } - if (logicalLines == 0) { - if (indexPtr->linePtr != linePtr) { - /* - * If we reached the end of the logical line, then either way - * we don't have a partial calculation. - */ + if (mergedLines == 0) { + if (indexPtr->linePtr != linePtr) { + /* + * If we reached the end of the logical line, then either way + * we don't have a partial calculation. + */ - partialCalc = 0; - break; - } - } else if (indexPtr->byteIndex != 0) { - /* - * We must still be on the same wrapped line. - */ - } else { - /* - * Must check if indexPtr is really a new logical line which is - * not merged with the previous line. The only code that would - * really know this is LayoutDLine, which doesn't pass the - * information on, so we have to check manually here. - */ - - TkTextIndex idx; - - TkTextIndexBackChars(textPtr, indexPtr, 1, &idx, COUNT_INDICES); - if (!TkTextIsElided(textPtr, &idx, NULL)) { - /* - * We've ended a logical line. - */ - - partialCalc = 0; - break; - } + partialCalc = 0; + break; + } + } else { + if (IsStartOfNotMergedLine(textPtr, indexPtr)) { + /* + * We've ended a logical line. + */ + + partialCalc = 0; + break; + } - /* - * We must still be on the same wrapped line. - */ - } + /* + * We must still be on the same wrapped line, on a new logical + * line merged with the logical line 'linePtr'. + */ + } if (partialCalc && displayLines > 50 && mergedLines == 0) { /* * Only calculate 50 display lines at a time, to avoid huge @@ -3900,6 +4027,19 @@ DisplayText( * warnings. */ Tcl_Interp *interp; +#ifdef MAC_OSX_TK + /* + * If drawing is disabled, all we need to do is + * clear the REDRAW_PENDING flag. + */ + TkWindow *winPtr = (TkWindow *)(textPtr->tkwin); + MacDrawable *macWin = winPtr->privatePtr; + if (macWin && (macWin->flags & TK_DO_NOT_DRAW)){ + dInfoPtr->flags &= ~REDRAW_PENDING; + return; + } +#endif + if ((textPtr->tkwin == NULL) || (textPtr->flags & DESTROYED)) { /* * The widget has been deleted. Don't do anything. @@ -3915,14 +4055,6 @@ DisplayText( Tcl_SetVar2(interp, "tk_textRelayout", NULL, "", TCL_GLOBAL_ONLY); } - if ((textPtr->tkwin == NULL) || (textPtr->flags & DESTROYED)) { - /* - * The widget has been deleted. Don't do anything. - */ - - goto end; - } - if (!Tk_IsMapped(textPtr->tkwin) || (dInfoPtr->maxX <= dInfoPtr->x) || (dInfoPtr->maxY <= dInfoPtr->y)) { UpdateDisplayInfo(textPtr); @@ -3934,14 +4066,6 @@ DisplayText( Tcl_SetVar2(interp, "tk_textRedraw", NULL, "", TCL_GLOBAL_ONLY); } - if ((textPtr->tkwin == NULL) || (textPtr->flags & DESTROYED)) { - /* - * The widget has been deleted. Don't do anything. - */ - - goto end; - } - /* * Choose a new current item if that is needed (this could cause event * handlers to be invoked, hence the preserve/release calls and the loop, @@ -4035,7 +4159,7 @@ DisplayText( */ if ((y + height) > dInfoPtr->maxY) { - height = dInfoPtr->maxY -y; + height = dInfoPtr->maxY - y; } oldY = dlPtr->oldY; if (y < dInfoPtr->y) { @@ -4091,6 +4215,7 @@ DisplayText( oldY, dInfoPtr->maxX-dInfoPtr->x, height, 0, y-oldY, damageRgn)) { TextInvalidateRegion(textPtr, damageRgn); + } numCopies++; TkDestroyRegion(damageRgn); @@ -4539,6 +4664,8 @@ TextChanged( TextDInfo *dInfoPtr = textPtr->dInfoPtr; DLine *firstPtr, *lastPtr; TkTextIndex rounded; + TkTextLine *linePtr; + int notBegin; /* * Schedule both a redisplay and a recomputation of display information. @@ -4564,23 +4691,78 @@ TextChanged( /* * Find the DLines corresponding to index1Ptr and index2Ptr. There is one * tricky thing here, which is that we have to relayout in units of whole - * text lines: round index1Ptr back to the beginning of its text line, and - * include all the display lines after index2, up to the end of its text - * line. This is necessary because the indices stored in the display lines - * will no longer be valid. It's also needed because any edit could change - * the way lines wrap. + * text lines: This is necessary because the indices stored in the display + * lines will no longer be valid. It's also needed because any edit could + * change the way lines wrap. + * To relayout in units of whole text (logical) lines, round index1Ptr + * back to the beginning of its text line (or, if this line start is + * elided, to the beginning of the text line that starts the display line + * it is included in), and include all the display lines after index2Ptr, + * up to the end of its text line (or, if this line end is elided, up to + * the end of the first non elided text line after this line end). */ rounded = *index1Ptr; rounded.byteIndex = 0; - firstPtr = FindDLine(dInfoPtr->dLinePtr, &rounded); + notBegin = 0; + while (!IsStartOfNotMergedLine(textPtr, &rounded) && notBegin) { + notBegin = !TkTextIndexBackBytes(textPtr, &rounded, 1, &rounded); + rounded.byteIndex = 0; + } + + /* + * 'rounded' now points to the start of a display line as well as the + * real (non elided) start of a logical line, and this index is the + * closest before index1Ptr. + */ + + firstPtr = FindDLine(textPtr, dInfoPtr->dLinePtr, &rounded); + if (firstPtr == NULL) { + /* + * index1Ptr pertains to no display line, i.e this index is after + * the last display line. Since index2Ptr is after index1Ptr, there + * is no display line to free/redisplay and we can return early. + */ + return; } - lastPtr = FindDLine(dInfoPtr->dLinePtr, index2Ptr); - while ((lastPtr != NULL) - && (lastPtr->index.linePtr == index2Ptr->linePtr)) { - lastPtr = lastPtr->nextPtr; + + rounded = *index2Ptr; + linePtr = index2Ptr->linePtr; + do { + linePtr = TkBTreeNextLine(textPtr, linePtr); + if (linePtr == NULL) { + break; + } + rounded.linePtr = linePtr; + rounded.byteIndex = 0; + } while (!IsStartOfNotMergedLine(textPtr, &rounded)); + + if (linePtr == NULL) { + lastPtr = NULL; + } else { + /* + * 'rounded' now points to the start of a display line as well as the + * start of a logical line not merged with its previous line, and + * this index is the closest after index2Ptr. + */ + + lastPtr = FindDLine(textPtr, dInfoPtr->dLinePtr, &rounded); + + /* + * At least one display line is supposed to change. This makes the + * redisplay OK in case the display line we expect to get here was + * unlinked by a previous call to TkTextChanged and the text widget + * did not update before reaching this point. This happens for + * instance when moving the cursor up one line. + * Note that lastPtr != NULL here, otherwise we would have returned + * earlier when we tested for firstPtr being NULL. + */ + + if (lastPtr == firstPtr) { + lastPtr = lastPtr->nextPtr; + } } /* @@ -4760,14 +4942,13 @@ TextRedrawTag( * the line containing the previous character. */ - if (curIndexPtr->byteIndex == 0) { - dlPtr = FindDLine(dlPtr, curIndexPtr); + if (IsStartOfNotMergedLine(textPtr, curIndexPtr)) { + dlPtr = FindDLine(textPtr, dlPtr, curIndexPtr); } else { - TkTextIndex tmp; + TkTextIndex tmp = *curIndexPtr; - tmp = *curIndexPtr; - tmp.byteIndex -= 1; - dlPtr = FindDLine(dlPtr, &tmp); + TkTextIndexBackBytes(textPtr, &tmp, 1, &tmp); + dlPtr = FindDLine(textPtr, dlPtr, &tmp); } if (dlPtr == NULL) { break; @@ -4783,9 +4964,9 @@ TextRedrawTag( curIndexPtr = &search.curIndex; endIndexPtr = curIndexPtr; } - endPtr = FindDLine(dlPtr, endIndexPtr); - if ((endPtr != NULL) && (endPtr->index.linePtr == endIndexPtr->linePtr) - && (endPtr->index.byteIndex < endIndexPtr->byteIndex)) { + endPtr = FindDLine(textPtr, dlPtr, endIndexPtr); + if ((endPtr != NULL) + && (TkTextIndexCmp(&endPtr->index,endIndexPtr) < 0)) { endPtr = endPtr->nextPtr; } @@ -4903,7 +5084,7 @@ TkTextRelayoutWindow( * could change the way lines wrap. */ - if (textPtr->topIndex.byteIndex != 0) { + if (!IsStartOfNotMergedLine(textPtr, &textPtr->topIndex)) { TkTextFindDisplayLineEnd(textPtr, &textPtr->topIndex, 0, NULL); } @@ -4940,6 +5121,7 @@ TkTextRelayoutWindow( textPtr->refCount++; dInfoPtr->lineUpdateTimer = Tcl_CreateTimerHandler(1, AsyncUpdateLineMetrics, textPtr); + GenerateWidgetViewSyncEvent(textPtr, 0); } } } @@ -5016,9 +5198,9 @@ TkTextSetYView( */ textPtr->topIndex = *indexPtr; - if (indexPtr->byteIndex != 0) { - TkTextFindDisplayLineEnd(textPtr, &textPtr->topIndex, 0, NULL); - } + if (!IsStartOfNotMergedLine(textPtr, indexPtr)) { + TkTextFindDisplayLineEnd(textPtr, &textPtr->topIndex, 0, NULL); + } dInfoPtr->newTopPixelOffset = pickPlace; goto scheduleUpdate; } @@ -5032,7 +5214,7 @@ TkTextSetYView( if (dInfoPtr->flags & DINFO_OUT_OF_DATE) { UpdateDisplayInfo(textPtr); } - dlPtr = FindDLine(dInfoPtr->dLinePtr, indexPtr); + dlPtr = FindDLine(textPtr, dInfoPtr->dLinePtr, indexPtr); if (dlPtr != NULL) { if ((dlPtr->y + dlPtr->height) > dInfoPtr->maxY) { /* @@ -5041,19 +5223,23 @@ TkTextSetYView( */ dlPtr = NULL; - } else if ((dlPtr->index.linePtr == indexPtr->linePtr) - && (dlPtr->index.byteIndex <= indexPtr->byteIndex)) { - if (dInfoPtr->dLinePtr == dlPtr && dInfoPtr->topPixelOffset != 0) { - /* - * It is on the top line, but that line is hanging off the top - * of the screen. Change the top overlap to zero and update. - */ - - dInfoPtr->newTopPixelOffset = 0; - goto scheduleUpdate; - } - return; - } + } else { + if (TkTextIndexCmp(&dlPtr->index, indexPtr) <= 0) { + if (dInfoPtr->dLinePtr == dlPtr && dInfoPtr->topPixelOffset != 0) { + /* + * It is on the top line, but that line is hanging off the top + * of the screen. Change the top overlap to zero and update. + */ + + dInfoPtr->newTopPixelOffset = 0; + goto scheduleUpdate; + } + /* + * The line is already on screen, with no need to scroll. + */ + return; + } + } } /* @@ -5064,7 +5250,9 @@ TkTextSetYView( * If the line is not close, place it in the center of the window. */ - lineHeight = CalculateDisplayLineHeight(textPtr, indexPtr, NULL, NULL); + tmpIndex = *indexPtr; + TkTextFindDisplayLineEnd(textPtr, &tmpIndex, 0, NULL); + lineHeight = CalculateDisplayLineHeight(textPtr, &tmpIndex, NULL, NULL); /* * It would be better if 'bottomY' were calculated using the actual height @@ -5105,12 +5293,21 @@ TkTextSetYView( MeasureUp(textPtr, indexPtr, close + lineHeight - textPtr->charHeight/2, &tmpIndex, &overlap); - if (FindDLine(dInfoPtr->dLinePtr, &tmpIndex) != NULL) { + if (FindDLine(textPtr, dInfoPtr->dLinePtr, &tmpIndex) != NULL) { bottomY = dInfoPtr->maxY - dInfoPtr->y; } } /* + * If the window height is smaller than the line height, prefer to make + * the top of the line visible. + */ + + if (dInfoPtr->maxY - dInfoPtr->y < lineHeight) { + bottomY = lineHeight; + } + + /* * Our job now is to arrange the display so that indexPtr appears as low * on the screen as possible but with its bottom no lower than bottomY. * BottomY is the bottom of the window if the desired line is just below @@ -5243,6 +5440,8 @@ MeasureUp( index.linePtr = TkBTreeFindLine(srcPtr->tree, textPtr, lineNum); index.byteIndex = 0; + TkTextFindDisplayLineEnd(textPtr, &index, 0, NULL); + lineNum = TkBTreeLinesTo(textPtr, index.linePtr); lowestPtr = NULL; do { dlPtr = LayoutDLine(textPtr, &index); @@ -5263,8 +5462,21 @@ MeasureUp( for (dlPtr = lowestPtr; dlPtr != NULL; dlPtr = dlPtr->nextPtr) { distance -= dlPtr->height; if (distance <= 0) { - *dstPtr = dlPtr->index; - if (overlap != NULL) { + *dstPtr = dlPtr->index; + + /* + * dstPtr is the start of a display line that is or is not + * the start of a logical line. If it is the start of a + * logical line, we must check whether this line is merged + * with the previous logical line, and if so we must adjust + * dstPtr to the start of the display line since a display + * line start needs to be returned. + */ + if (!IsStartOfNotMergedLine(textPtr, dstPtr)) { + TkTextFindDisplayLineEnd(textPtr, dstPtr, 0, NULL); + } + + if (overlap != NULL) { *overlap = -distance; } break; @@ -5364,16 +5576,24 @@ TkTextSeeCmd( } /* - * Find the chunk that contains the desired index. dlPtr may be NULL if - * the widget is not mapped. [Bug #641778] + * Find the display line containing the desired index. dlPtr may be NULL + * if the widget is not mapped. [Bug #641778] */ - dlPtr = FindDLine(dInfoPtr->dLinePtr, &index); + dlPtr = FindDLine(textPtr, dInfoPtr->dLinePtr, &index); if (dlPtr == NULL) { return TCL_OK; } - byteCount = index.byteIndex - dlPtr->index.byteIndex; + /* + * Find the chunk within the display line that contains the desired + * index. The chunks making the display line are skipped up to but not + * including the one crossing index. Skipping is done based on a + * byteCount offset possibly spanning several logical lines in case + * they are elided. + */ + + byteCount = TkTextIndexCountBytes(textPtr, &dlPtr->index, &index); for (chunkPtr = dlPtr->chunkPtr; chunkPtr != NULL ; chunkPtr = chunkPtr->nextPtr) { if (byteCount < chunkPtr->numBytes) { @@ -5389,29 +5609,30 @@ TkTextSeeCmd( */ if (chunkPtr != NULL) { - chunkPtr->bboxProc(textPtr, chunkPtr, byteCount, - dlPtr->y + dlPtr->spaceAbove, - dlPtr->height - dlPtr->spaceAbove - dlPtr->spaceBelow, - dlPtr->baseline - dlPtr->spaceAbove, &x, &y, &width, - &height); - delta = x - dInfoPtr->curXPixelOffset; - oneThird = lineWidth/3; - if (delta < 0) { - if (delta < -oneThird) { - dInfoPtr->newXPixelOffset = x - lineWidth/2; - } else { - dInfoPtr->newXPixelOffset += delta; - } - } else { - delta -= lineWidth - width; - if (delta <= 0) { - return TCL_OK; - } else if (delta > oneThird) { - dInfoPtr->newXPixelOffset = x - lineWidth/2; - } else { - dInfoPtr->newXPixelOffset += delta; - } - } + chunkPtr->bboxProc(textPtr, chunkPtr, byteCount, + dlPtr->y + dlPtr->spaceAbove, + dlPtr->height - dlPtr->spaceAbove - dlPtr->spaceBelow, + dlPtr->baseline - dlPtr->spaceAbove, &x, &y, &width, + &height); + delta = x - dInfoPtr->curXPixelOffset; + oneThird = lineWidth/3; + if (delta < 0) { + if (delta < -oneThird) { + dInfoPtr->newXPixelOffset = x - lineWidth/2; + } else { + dInfoPtr->newXPixelOffset += delta; + } + } else { + delta -= lineWidth - width; + if (delta <= 0) { + return TCL_OK; + } + if (delta > oneThird) { + dInfoPtr->newXPixelOffset = x - lineWidth/2; + } else { + dInfoPtr->newXPixelOffset += delta; + } + } } dInfoPtr->flags |= DINFO_OUT_OF_DATE; if (!(dInfoPtr->flags & REDRAW_PENDING)) { @@ -5648,7 +5869,25 @@ YScrollByLines( offset++; if (offset == 0) { textPtr->topIndex = dlPtr->index; - break; + + /* + * topIndex is the start of a logical line. However, if + * the eol of the previous logical line is elided, then + * topIndex may be elsewhere than the first character of + * a display line, which is unwanted. Adjust to the start + * of the display line, if needed. + * topIndex is the start of a display line that is or is + * not the start of a logical line. If it is the start of + * a logical line, we must check whether this line is + * merged with the previous logical line, and if so we + * must adjust topIndex to the start of the display line. + */ + if (!IsStartOfNotMergedLine(textPtr, &textPtr->topIndex)) { + TkTextFindDisplayLineEnd(textPtr, &textPtr->topIndex, + 0, NULL); + } + + break; } } @@ -5888,6 +6127,35 @@ TkTextYviewCmd( /* *-------------------------------------------------------------- * + * TkTextPendingsync -- + * + * This function checks if any line heights are not up-to-date. + * + * Results: + * Returns a boolean true if it is the case, or false if all line + * heights are up-to-date. + * + * Side effects: + * None. + * + *-------------------------------------------------------------- + */ + +Bool +TkTextPendingsync( + TkText *textPtr) /* Information about text widget. */ +{ + TextDInfo *dInfoPtr = textPtr->dInfoPtr; + + return ( + ((dInfoPtr->metricEpoch == -1) && + (dInfoPtr->lastMetricUpdateLine == dInfoPtr->currentMetricUpdateLine)) ? + 0 : 1); +} + +/* + *-------------------------------------------------------------- + * * TkTextScanCmd -- * * This function is invoked to process the "scan" option for the widget @@ -6064,12 +6332,18 @@ GetXView( if (textPtr->xScrollCmd != NULL) { char buf1[TCL_DOUBLE_SPACE+1]; char buf2[TCL_DOUBLE_SPACE+1]; + Tcl_DString buf; buf1[0] = ' '; buf2[0] = ' '; Tcl_PrintDouble(NULL, first, buf1+1); Tcl_PrintDouble(NULL, last, buf2+1); - code = Tcl_VarEval(interp, textPtr->xScrollCmd, buf1, buf2, NULL); + Tcl_DStringInit(&buf); + Tcl_DStringAppend(&buf, textPtr->xScrollCmd, -1); + Tcl_DStringAppend(&buf, buf1, -1); + Tcl_DStringAppend(&buf, buf2, -1); + code = Tcl_EvalEx(interp, Tcl_DStringValue(&buf), -1, 0); + Tcl_DStringFree(&buf); if (code != TCL_OK) { Tcl_AddErrorInfo(interp, "\n (horizontal scrolling command executed by text)"); @@ -6129,13 +6403,10 @@ GetYPixelCount( /* * For the common case where this dlPtr is also the start of the logical - * line, we can return right away. Note the implicit assumption here that - * the start of a logical line is always the start of a display line (if - * the 'elide won't elide first newline' bug is fixed, this will no longer - * necessarily be true). + * line, we can return right away. */ - if (dlPtr->index.byteIndex == 0) { + if (IsStartOfNotMergedLine(textPtr, &dlPtr->index)) { return count; } @@ -6346,12 +6617,18 @@ GetYView( if (textPtr->yScrollCmd != NULL) { char buf1[TCL_DOUBLE_SPACE+1]; char buf2[TCL_DOUBLE_SPACE+1]; + Tcl_DString buf; buf1[0] = ' '; buf2[0] = ' '; Tcl_PrintDouble(NULL, first, buf1+1); Tcl_PrintDouble(NULL, last, buf2+1); - code = Tcl_VarEval(interp, textPtr->yScrollCmd, buf1, buf2, NULL); + Tcl_DStringInit(&buf); + Tcl_DStringAppend(&buf, textPtr->yScrollCmd, -1); + Tcl_DStringAppend(&buf, buf1, -1); + Tcl_DStringAppend(&buf, buf2, -1); + code = Tcl_EvalEx(interp, Tcl_DStringValue(&buf), -1, 0); + Tcl_DStringFree(&buf); if (code != TCL_OK) { Tcl_AddErrorInfo(interp, "\n (vertical scrolling command executed by text)"); @@ -6416,11 +6693,13 @@ AsyncUpdateYScrollbar( static DLine * FindDLine( + TkText *textPtr, /* Widget record for text widget. */ register DLine *dlPtr, /* Pointer to first in list of DLines to * search. */ const TkTextIndex *indexPtr)/* Index of desired character. */ { - TkTextLine *linePtr; + DLine *dlPtrPrev; + TkTextIndex indexPtr2; if (dlPtr == NULL) { return NULL; @@ -6435,43 +6714,123 @@ FindDLine( } /* - * Find the first display line that covers the desired text line. + * The display line containing the desired index is such that the index + * of the first character of this display line is at or before the + * desired index, and the index of the first character of the next + * display line is after the desired index. */ - linePtr = dlPtr->index.linePtr; - while (linePtr != indexPtr->linePtr) { - while (dlPtr->index.linePtr == linePtr) { - dlPtr = dlPtr->nextPtr; - if (dlPtr == NULL) { - return NULL; - } - } + while (TkTextIndexCmp(&dlPtr->index,indexPtr) < 0) { + dlPtrPrev = dlPtr; + dlPtr = dlPtr->nextPtr; + if (dlPtr == NULL) { + /* + * We're past the last display line, either because the desired + * index lies past the visible text, or because the desired index + * is on the last display line. + */ + indexPtr2 = dlPtrPrev->index; + TkTextIndexForwBytes(textPtr, &indexPtr2, dlPtrPrev->byteCount, + &indexPtr2); + if (TkTextIndexCmp(&indexPtr2,indexPtr) > 0) { + /* + * The desired index is on the last display line. + * --> return this display line. + */ + dlPtr = dlPtrPrev; + } else { + /* + * The desired index is past the visible text. There is no + * display line displaying something at the desired index. + * --> return NULL. + */ + } + break; + } + if (TkTextIndexCmp(&dlPtr->index,indexPtr) > 0) { + /* + * If we're here then we would normally expect that: + * dlPtrPrev->index <= indexPtr < dlPtr->index + * i.e. we have found the searched display line being dlPtr. + * However it is possible that some DLines were unlinked + * previously, leading to a situation where going through + * the list of display lines skips display lines that did + * exist just a moment ago. + */ + indexPtr2 = dlPtrPrev->index; + TkTextIndexForwBytes(textPtr, &indexPtr2, dlPtrPrev->byteCount, + &indexPtr2); + if (TkTextIndexCmp(&indexPtr2,indexPtr) > 0) { + /* + * Confirmed: + * dlPtrPrev->index <= indexPtr < dlPtr->index + * --> return dlPtrPrev. + */ + dlPtr = dlPtrPrev; + } else { + /* + * The last (rightmost) index shown by dlPtrPrev is still + * before the desired index. This may be because there was + * previously a display line between dlPtrPrev and dlPtr + * and this display line has been unlinked. + * --> return dlPtr. + */ + } + break; + } + } - /* - * VMD: some concern here as to whether this logic, or the caller's - * logic will work well with partial peer widgets. - */ + return dlPtr; +} + +/* + *---------------------------------------------------------------------- + * + * IsStartOfNotMergedLine -- + * + * This function checks whether the given index is the start of a + * logical line that is not merged with the previous logical line + * (due to elision of the eol of the previous line). + * + * Results: + * Returns whether the given index denotes the first index of a +* logical line not merged with its previous line. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ - linePtr = TkBTreeNextLine(NULL, linePtr); - if (linePtr == NULL) { - Tcl_Panic("FindDLine reached end of text"); - } - } - if (indexPtr->linePtr != dlPtr->index.linePtr) { - return dlPtr; +static int +IsStartOfNotMergedLine( + TkText *textPtr, /* Widget record for text widget. */ + CONST TkTextIndex *indexPtr) /* Index to check. */ +{ + TkTextIndex indexPtr2; + + if (indexPtr->byteIndex != 0) { + /* + * Not the start of a logical line. + */ + return 0; } - /* - * Now get to the right position within the text line. - */ + if (TkTextIndexBackBytes(textPtr, indexPtr, 1, &indexPtr2)) { + /* + * indexPtr is the first index of the text widget. + */ + return 1; + } - while (indexPtr->byteIndex >= (dlPtr->index.byteIndex+dlPtr->byteCount)) { - dlPtr = dlPtr->nextPtr; - if ((dlPtr == NULL) || (dlPtr->index.linePtr != indexPtr->linePtr)) { - break; - } + if (!TkTextIsElided(textPtr, &indexPtr2, NULL)) { + /* + * The eol of the line just before indexPtr is elided. + */ + return 1; } - return dlPtr; + + return 0; } /* @@ -6642,10 +7001,15 @@ DlineIndexOfX( * We've reached the end of the text. */ + TkTextIndexBackChars(NULL, indexPtr, 1, indexPtr, COUNT_INDICES); return; } if (chunkPtr->nextPtr == NULL) { - TkTextIndexBackChars(NULL, indexPtr, 1, indexPtr, COUNT_INDICES); + /* + * We've reached the end of the display line. + */ + + TkTextIndexBackChars(NULL, indexPtr, 1, indexPtr, COUNT_INDICES); return; } chunkPtr = chunkPtr->nextPtr; @@ -6801,7 +7165,7 @@ TkTextIndexBbox( TextDInfo *dInfoPtr = textPtr->dInfoPtr; DLine *dlPtr; register TkTextDispChunk *chunkPtr; - int byteIndex; + int byteCount; /* * Make sure that all of the screen layout information is up to date. @@ -6815,24 +7179,37 @@ TkTextIndexBbox( * Find the display line containing the desired index. */ - dlPtr = FindDLine(dInfoPtr->dLinePtr, indexPtr); + dlPtr = FindDLine(textPtr, dInfoPtr->dLinePtr, indexPtr); + + /* + * Two cases shall be trapped here because the logic later really + * needs dlPtr to be the display line containing indexPtr: + * 1. if no display line contains the desired index (NULL dlPtr) + * 2. if indexPtr is before the first display line, in which case + * dlPtr currently points to the first display line + */ + if ((dlPtr == NULL) || (TkTextIndexCmp(&dlPtr->index, indexPtr) > 0)) { return -1; } /* - * Find the chunk within the line that contains the desired index. + * Find the chunk within the display line that contains the desired + * index. The chunks making the display line are skipped up to but not + * including the one crossing indexPtr. Skipping is done based on + * a byteCount offset possibly spanning several logical lines in case + * they are elided. */ - byteIndex = indexPtr->byteIndex - dlPtr->index.byteIndex; + byteCount = TkTextIndexCountBytes(textPtr, &dlPtr->index, indexPtr); for (chunkPtr = dlPtr->chunkPtr; ; chunkPtr = chunkPtr->nextPtr) { if (chunkPtr == NULL) { return -1; } - if (byteIndex < chunkPtr->numBytes) { + if (byteCount < chunkPtr->numBytes) { break; } - byteIndex -= chunkPtr->numBytes; + byteCount -= chunkPtr->numBytes; } /* @@ -6842,13 +7219,13 @@ TkTextIndexBbox( * coordinate on the screen. Translate it to reflect horizontal scrolling. */ - chunkPtr->bboxProc(textPtr, chunkPtr, byteIndex, + chunkPtr->bboxProc(textPtr, chunkPtr, byteCount, dlPtr->y + dlPtr->spaceAbove, dlPtr->height - dlPtr->spaceAbove - dlPtr->spaceBelow, dlPtr->baseline - dlPtr->spaceAbove, xPtr, yPtr, widthPtr, heightPtr); *xPtr = *xPtr + dInfoPtr->x - dInfoPtr->curXPixelOffset; - if ((byteIndex == chunkPtr->numBytes-1) && (chunkPtr->nextPtr == NULL)) { + if ((byteCount == chunkPtr->numBytes-1) && (chunkPtr->nextPtr == NULL)) { /* * Last character in display line. Give it all the space up to the * line. @@ -6946,7 +7323,16 @@ TkTextDLineInfo( * Find the display line containing the desired index. */ - dlPtr = FindDLine(dInfoPtr->dLinePtr, indexPtr); + dlPtr = FindDLine(textPtr, dInfoPtr->dLinePtr, indexPtr); + + /* + * Two cases shall be trapped here because the logic later really + * needs dlPtr to be the display line containing indexPtr: + * 1. if no display line contains the desired index (NULL dlPtr) + * 2. if indexPtr is before the first display line, in which case + * dlPtr currently points to the first display line + */ + if ((dlPtr == NULL) || (TkTextIndexCmp(&dlPtr->index, indexPtr) > 0)) { return -1; } @@ -8196,8 +8582,8 @@ TextGetScrollInfoObj( }; int index; - if (Tcl_GetIndexFromObj(interp, objv[2], subcommands, "option", 0, - &index) != TCL_OK) { + if (Tcl_GetIndexFromObjStruct(interp, objv[2], subcommands, + sizeof(char *), "option", 0, &index) != TCL_OK) { return TKTEXT_SCROLL_ERROR; } @@ -8216,8 +8602,8 @@ TextGetScrollInfoObj( Tcl_WrongNumArgs(interp, 3, objv, "number units|pages|pixels"); return TKTEXT_SCROLL_ERROR; } - if (Tcl_GetIndexFromObj(interp, objv[4], units, "argument", 0, - &index) != TCL_OK) { + if (Tcl_GetIndexFromObjStruct(interp, objv[4], units, + sizeof(char *), "argument", 0, &index) != TCL_OK) { return TKTEXT_SCROLL_ERROR; } switch ((enum viewUnits) index) { diff --git a/generic/tkTextImage.c b/generic/tkTextImage.c index 1770cb6..41dd448 100644 --- a/generic/tkTextImage.c +++ b/generic/tkTextImage.c @@ -138,8 +138,8 @@ TkTextImageCmd( Tcl_WrongNumArgs(interp, 2, objv, "option ?arg ...?"); return TCL_ERROR; } - if (Tcl_GetIndexFromObj(interp, objv[2], optionStrings, "option", 0, - &idx) != TCL_OK) { + if (Tcl_GetIndexFromObjStruct(interp, objv[2], optionStrings, + sizeof(char *), "option", 0, &idx) != TCL_OK) { return TCL_ERROR; } switch ((enum opts) idx) { @@ -786,6 +786,10 @@ TkTextImageIndex( Tcl_HashEntry *hPtr; TkTextSegment *eiPtr; + if (textPtr == NULL) { + return 0; + } + hPtr = Tcl_FindHashEntry(&textPtr->sharedTextPtr->imageTable, name); if (hPtr == NULL) { return 0; diff --git a/generic/tkTextIndex.c b/generic/tkTextIndex.c index 25888d8..8820191 100644 --- a/generic/tkTextIndex.c +++ b/generic/tkTextIndex.c @@ -40,6 +40,9 @@ static const char * StartEnd(TkText *textPtr, const char *string, static int GetIndex(Tcl_Interp *interp, TkSharedText *sharedPtr, TkText *textPtr, const char *string, TkTextIndex *indexPtr, int *canCachePtr); +static int IndexCountBytesOrdered(CONST TkText *textPtr, + CONST TkTextIndex *indexPtr1, + CONST TkTextIndex *indexPtr2); /* * The "textindex" Tcl_Obj definition: @@ -48,8 +51,6 @@ static int GetIndex(Tcl_Interp *interp, TkSharedText *sharedPtr, static void DupTextIndexInternalRep(Tcl_Obj *srcPtr, Tcl_Obj *copyPtr); static void FreeTextIndexInternalRep(Tcl_Obj *listPtr); -static int SetTextIndexFromAny(Tcl_Interp *interp, - Tcl_Obj *objPtr); static void UpdateStringOfTextIndex(Tcl_Obj *objPtr); /* @@ -75,7 +76,7 @@ const Tcl_ObjType tkTextIndexType = { FreeTextIndexInternalRep, /* freeIntRepProc */ DupTextIndexInternalRep, /* dupIntRepProc */ NULL, /* updateStringProc */ - SetTextIndexFromAny /* setFromAnyProc */ + NULL /* setFromAnyProc */ }; static void @@ -142,18 +143,6 @@ UpdateStringOfTextIndex( strcpy(objPtr->bytes, buffer); objPtr->length = len; } - -static int -SetTextIndexFromAny( - Tcl_Interp *interp, /* Used for error reporting if not NULL. */ - Tcl_Obj *objPtr) /* The object to convert. */ -{ - Tcl_SetObjResult(interp, Tcl_NewStringObj( - "can't convert value to textindex except via" - " TkTextGetIndexFromObj API", -1)); - Tcl_SetErrorCode(interp, "TK", "API_ABUSE", NULL); - return TCL_ERROR; -} /* *--------------------------------------------------------------------------- @@ -760,9 +749,11 @@ GetIndex( /* *--------------------------------------------------------------------- - * Stage 1: check to see if the index consists of nothing but a mark name. - * We do this check now even though it's also done later, in order to - * allow mark names that include funny characters such as spaces or "+1c". + * Stage 1: check to see if the index consists of nothing but a mark + * name, an embedded window or an embedded image. We do this check + * now even though it's also done later, in order to allow mark names, + * embedded window names or image names that include funny characters + * such as spaces or "+1c". *--------------------------------------------------------------------- */ @@ -770,6 +761,14 @@ GetIndex( goto done; } + if (TkTextWindowIndex(textPtr, string, indexPtr) != 0) { + goto done; + } + + if (TkTextImageIndex(textPtr, string, indexPtr) != 0) { + goto done; + } + /* *------------------------------------------------ * Stage 2: start again by parsing the base index. @@ -1620,6 +1619,90 @@ TkTextIndexForwChars( /* *--------------------------------------------------------------------------- * + * TkTextIndexCountBytes -- + * + * Given a pair of indices in a text widget, this function counts how + * many bytes are between the two indices. The two indices do not need + * to be ordered. + * + * Results: + * The number of bytes in the given range. + * + * Side effects: + * None. + * + *--------------------------------------------------------------------------- + */ + +int +TkTextIndexCountBytes( + CONST TkText *textPtr, + CONST TkTextIndex *indexPtr1, /* Index describing one location. */ + CONST TkTextIndex *indexPtr2) /* Index describing second location. */ +{ + int compare = TkTextIndexCmp(indexPtr1, indexPtr2); + + if (compare == 0) { + return 0; + } else if (compare > 0) { + return IndexCountBytesOrdered(textPtr, indexPtr2, indexPtr1); + } else { + return IndexCountBytesOrdered(textPtr, indexPtr1, indexPtr2); + } +} + +static int +IndexCountBytesOrdered( + CONST TkText *textPtr, + CONST TkTextIndex *indexPtr1, + /* Index describing location of character from + * which to count. */ + CONST TkTextIndex *indexPtr2) + /* Index describing location of last character + * at which to stop the count. */ +{ + int byteCount, offset; + TkTextSegment *segPtr, *segPtr1; + TkTextLine *linePtr; + + if (indexPtr1->linePtr == indexPtr2->linePtr) { + return indexPtr2->byteIndex - indexPtr1->byteIndex; + } + + /* + * indexPtr2 is on a line strictly after the line containing indexPtr1. + * Add up: + * bytes between indexPtr1 and end of its line + * bytes in lines strictly between indexPtr1 and indexPtr2 + * bytes between start of the indexPtr2 line and indexPtr2 + */ + + segPtr1 = TkTextIndexToSeg(indexPtr1, &offset); + byteCount = -offset; + for (segPtr = segPtr1; segPtr != NULL; segPtr = segPtr->nextPtr) { + byteCount += segPtr->size; + } + + linePtr = TkBTreeNextLine(textPtr, indexPtr1->linePtr); + while (linePtr != indexPtr2->linePtr) { + for (segPtr = linePtr->segPtr; segPtr != NULL; + segPtr = segPtr->nextPtr) { + byteCount += segPtr->size; + } + linePtr = TkBTreeNextLine(textPtr, linePtr); + if (linePtr == NULL) { + Tcl_Panic("TextIndexCountBytesOrdered ran out of lines"); + } + } + + byteCount += indexPtr2->byteIndex; + + return byteCount; +} + +/* + *--------------------------------------------------------------------------- + * * TkTextIndexCount -- * * Given an ordered pair of indices in a text widget, this function @@ -2122,7 +2205,7 @@ StartEnd( TkText *textPtr, /* Information about text widget. */ const char *string, /* String to parse for additional info about * modifier (count and units). Points to first - * character of modifer word. */ + * character of modifier word. */ TkTextIndex *indexPtr) /* Index to modify based on string. */ { const char *p; @@ -2244,7 +2327,7 @@ StartEnd( int offset; if (modifier == TKINDEX_DISPLAY) { - TkTextIndexForwChars(NULL, indexPtr, 0, indexPtr, + TkTextIndexForwChars(textPtr, indexPtr, 0, indexPtr, COUNT_DISPLAY_INDICES); } @@ -2273,11 +2356,20 @@ StartEnd( } firstChar = 0; } - offset -= chSize; - indexPtr->byteIndex -= chSize; + if (offset == 0) { + if (modifier == TKINDEX_DISPLAY) { + TkTextIndexBackChars(textPtr, indexPtr, 1, indexPtr, + COUNT_DISPLAY_INDICES); + } else { + TkTextIndexBackChars(NULL, indexPtr, 1, indexPtr, + COUNT_INDICES); + } + } else { + indexPtr->byteIndex -= chSize; + } + offset -= chSize; if (offset < 0) { - if (indexPtr->byteIndex < 0) { - indexPtr->byteIndex = 0; + if (indexPtr->byteIndex == 0) { goto done; } segPtr = TkTextIndexToSeg(indexPtr, &offset); diff --git a/generic/tkTextMark.c b/generic/tkTextMark.c index a306a05..6a41c77 100644 --- a/generic/tkTextMark.c +++ b/generic/tkTextMark.c @@ -40,9 +40,9 @@ static int MarkLayoutProc(TkText *textPtr, TkTextIndex *indexPtr, int maxChars, int noCharsYet, TkWrapMode wrapMode, TkTextDispChunk *chunkPtr); static int MarkFindNext(Tcl_Interp *interp, - TkText *textPtr, const char *markName); + TkText *textPtr, Tcl_Obj *markName); static int MarkFindPrev(Tcl_Interp *interp, - TkText *textPtr, const char *markName); + TkText *textPtr, Tcl_Obj *markName); /* @@ -118,8 +118,8 @@ TkTextMarkCmd( Tcl_WrongNumArgs(interp, 2, objv, "option ?arg ...?"); return TCL_ERROR; } - if (Tcl_GetIndexFromObj(interp, objv[2], markOptionStrings, "mark option", - 0, &optionIndex) != TCL_OK) { + if (Tcl_GetIndexFromObjStruct(interp, objv[2], markOptionStrings, + sizeof(char *), "mark option", 0, &optionIndex) != TCL_OK) { return TCL_ERROR; } @@ -205,13 +205,13 @@ TkTextMarkCmd( Tcl_WrongNumArgs(interp, 3, objv, "index"); return TCL_ERROR; } - return MarkFindNext(interp, textPtr, Tcl_GetString(objv[3])); + return MarkFindNext(interp, textPtr, objv[3]); case MARK_PREVIOUS: if (objc != 4) { Tcl_WrongNumArgs(interp, 3, objv, "index"); return TCL_ERROR; } - return MarkFindPrev(interp, textPtr, Tcl_GetString(objv[3])); + return MarkFindPrev(interp, textPtr, objv[3]); case MARK_SET: if (objc != 5) { Tcl_WrongNumArgs(interp, 3, objv, "markName index"); @@ -805,12 +805,13 @@ static int MarkFindNext( Tcl_Interp *interp, /* For error reporting */ TkText *textPtr, /* The widget */ - const char *string) /* The starting index or mark name */ + Tcl_Obj *obj) /* The starting index or mark name */ { TkTextIndex index; Tcl_HashEntry *hPtr; register TkTextSegment *segPtr; int offset; + const char *string = Tcl_GetString(obj); if (!strcmp(string, "insert")) { segPtr = textPtr->insertMarkPtr; @@ -838,7 +839,7 @@ MarkFindNext( * right at the index. */ - if (TkTextGetIndex(interp, textPtr, string, &index) != TCL_OK) { + if (TkTextGetObjIndex(interp, textPtr, obj, &index) != TCL_OK) { return TCL_ERROR; } for (offset = 0, segPtr = index.linePtr->segPtr; @@ -895,12 +896,13 @@ static int MarkFindPrev( Tcl_Interp *interp, /* For error reporting */ TkText *textPtr, /* The widget */ - const char *string) /* The starting index or mark name */ + Tcl_Obj *obj) /* The starting index or mark name */ { TkTextIndex index; Tcl_HashEntry *hPtr; register TkTextSegment *segPtr, *seg2Ptr, *prevPtr; int offset; + const char *string = Tcl_GetString(obj); if (!strcmp(string, "insert")) { segPtr = textPtr->insertMarkPtr; @@ -925,7 +927,7 @@ MarkFindPrev( * right at the index. */ - if (TkTextGetIndex(interp, textPtr, string, &index) != TCL_OK) { + if (TkTextGetObjIndex(interp, textPtr, obj, &index) != TCL_OK) { return TCL_ERROR; } for (offset = 0, segPtr = index.linePtr->segPtr; diff --git a/generic/tkTextTag.c b/generic/tkTextTag.c index beb7eb5..3363d25 100644 --- a/generic/tkTextTag.c +++ b/generic/tkTextTag.c @@ -44,11 +44,11 @@ static const Tk_OptionSpec tagOptionSpecs[] = { {TK_OPTION_BITMAP, "-bgstipple", NULL, NULL, NULL, -1, Tk_Offset(TkTextTag, bgStipple), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_PIXELS, "-borderwidth", NULL, NULL, - "0", Tk_Offset(TkTextTag, borderWidthPtr), Tk_Offset(TkTextTag, borderWidth), - TK_OPTION_DONT_SET_DEFAULT|TK_OPTION_NULL_OK, 0, 0}, + NULL, Tk_Offset(TkTextTag, borderWidthPtr), Tk_Offset(TkTextTag, borderWidth), + TK_OPTION_NULL_OK|TK_OPTION_DONT_SET_DEFAULT, 0, 0}, {TK_OPTION_STRING, "-elide", NULL, NULL, - "0", -1, Tk_Offset(TkTextTag, elideString), - TK_OPTION_DONT_SET_DEFAULT|TK_OPTION_NULL_OK, 0, 0}, + NULL, -1, Tk_Offset(TkTextTag, elideString), + TK_OPTION_NULL_OK|TK_OPTION_DONT_SET_DEFAULT, 0, 0}, {TK_OPTION_BITMAP, "-fgstipple", NULL, NULL, NULL, -1, Tk_Offset(TkTextTag, fgStipple), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_FONT, "-font", NULL, NULL, @@ -148,8 +148,8 @@ TkTextTagCmd( return TCL_ERROR; } - if (Tcl_GetIndexFromObj(interp, objv[2], tagOptionStrings, - "tag option", 0, &optionIndex) != TCL_OK) { + if (Tcl_GetIndexFromObjStruct(interp, objv[2], tagOptionStrings, + sizeof(char *), "tag option", 0, &optionIndex) != TCL_OK) { return TCL_ERROR; } @@ -169,6 +169,14 @@ TkTextTagCmd( return TCL_ERROR; } tagPtr = TkTextCreateTag(textPtr, Tcl_GetString(objv[3]), NULL); + if (tagPtr->elide) { + /* + * Indices are potentially obsolete after adding or removing + * elided character ranges, especially indices having "display" + * or "any" submodifier, therefore increase the epoch. + */ + textPtr->sharedTextPtr->stateEpoch++; + } for (i = 4; i < objc; i += 2) { if (TkTextGetObjIndex(interp, textPtr, objv[i], &index1) != TCL_OK) { @@ -289,7 +297,7 @@ TkTextTagCmd( textPtr->sharedTextPtr->bindingTable, (ClientData) tagPtr->name, Tcl_GetString(objv[4])); if (command == NULL) { - const char *string = Tcl_GetStringResult(interp); + const char *string = Tcl_GetString(Tcl_GetObjResult(interp)); /* * Ignore missing binding errors. This is a special hack that diff --git a/generic/tkTextWind.c b/generic/tkTextWind.c index d2998da..c9fc20f 100644 --- a/generic/tkTextWind.c +++ b/generic/tkTextWind.c @@ -153,8 +153,8 @@ TkTextWindowCmd( Tcl_WrongNumArgs(interp, 2, objv, "option ?arg ...?"); return TCL_ERROR; } - if (Tcl_GetIndexFromObj(interp, objv[2], windOptionStrings, - "window option", 0, &optionIndex) != TCL_OK) { + if (Tcl_GetIndexFromObjStruct(interp, objv[2], windOptionStrings, + sizeof(char *), "window option", 0, &optionIndex) != TCL_OK) { return TCL_ERROR; } switch ((enum windOptions) optionIndex) { @@ -911,10 +911,10 @@ EmbWinLayoutProc( if (dsPtr != NULL) { Tcl_DStringAppend(dsPtr, before, (int) (string-before)); - code = Tcl_GlobalEval(textPtr->interp, Tcl_DStringValue(dsPtr)); + code = Tcl_EvalEx(textPtr->interp, Tcl_DStringValue(dsPtr), -1, TCL_EVAL_GLOBAL); Tcl_DStringFree(dsPtr); } else { - code = Tcl_GlobalEval(textPtr->interp, ewPtr->body.ew.create); + code = Tcl_EvalEx(textPtr->interp, ewPtr->body.ew.create, -1, TCL_EVAL_GLOBAL); } if (code != TCL_OK) { Tcl_BackgroundException(textPtr->interp, code); @@ -927,7 +927,7 @@ EmbWinLayoutProc( Tcl_GetString(nameObj), textPtr->tkwin); Tcl_DecrRefCount(nameObj); if (ewPtr->body.ew.tkwin == NULL) { - Tcl_BackgroundError(textPtr->interp); + Tcl_BackgroundException(textPtr->interp, TCL_ERROR); goto gotWindow; } @@ -948,7 +948,7 @@ EmbWinLayoutProc( Tk_PathName(textPtr->tkwin))); Tcl_SetErrorCode(textPtr->interp, "TK", "GEOMETRY", "HIERARCHY", NULL); - Tcl_BackgroundError(textPtr->interp); + Tcl_BackgroundException(textPtr->interp, TCL_ERROR); ewPtr->body.ew.tkwin = NULL; goto gotWindow; } @@ -1134,6 +1134,16 @@ TkTextEmbWinDisplayProc( &lineX, &windowY, &width, &height); windowX = lineX - chunkPtr->x + x; + /* + * Mark the window as displayed so that it won't get unmapped. + * This needs to be done before the next instruction block because + * Tk_MaintainGeometry/Tk_MapWindow will run event handlers, in + * particular for the <Map> event, and if the bound script deletes + * the embedded window its clients will get freed. + */ + + client->displayed = 1; + if (textPtr->tkwin == Tk_Parent(tkwin)) { if ((windowX != Tk_X(tkwin)) || (windowY != Tk_Y(tkwin)) || (Tk_ReqWidth(tkwin) != Tk_Width(tkwin)) @@ -1145,12 +1155,6 @@ TkTextEmbWinDisplayProc( Tk_MaintainGeometry(tkwin, textPtr->tkwin, windowX, windowY, width, height); } - - /* - * Mark the window as displayed so that it won't get unmapped. - */ - - client->displayed = 1; } /* @@ -1340,6 +1344,10 @@ TkTextWindowIndex( Tcl_HashEntry *hPtr; TkTextSegment *ewPtr; + if (textPtr == NULL) { + return 0; + } + hPtr = Tcl_FindHashEntry(&textPtr->sharedTextPtr->windowTable, name); if (hPtr == NULL) { return 0; diff --git a/generic/tkUndo.c b/generic/tkUndo.c index a642e72..8359e0a 100644 --- a/generic/tkUndo.c +++ b/generic/tkUndo.c @@ -392,7 +392,7 @@ TkUndoSetDepth( prevelem = elem; elem = elem->next; } - CLANG_ASSERT(prevelem); + CLANG_ASSERT(prevelem); prevelem->next = NULL; while (elem != NULL) { prevelem = elem; diff --git a/generic/tkUtil.c b/generic/tkUtil.c index 385d1cb..7ff9ecb 100644 --- a/generic/tkUtil.c +++ b/generic/tkUtil.c @@ -729,8 +729,8 @@ Tk_GetScrollInfoObj( int *intPtr) /* Filled in with number of pages or lines to * scroll, if any. */ { - int length; - const char *arg = Tcl_GetStringFromObj(objv[2], &length); + const char *arg = Tcl_GetString(objv[2]); + size_t length = objv[2]->length; #define ArgPfxEq(str) \ ((arg[0] == str[0]) && !strncmp(arg, str, (unsigned)length)) @@ -753,7 +753,8 @@ Tk_GetScrollInfoObj( return TK_SCROLL_ERROR; } - arg = Tcl_GetStringFromObj(objv[4], &length); + arg = Tcl_GetString(objv[4]); + length = objv[4]->length; if (ArgPfxEq("pages")) { return TK_SCROLL_PAGES; } else if (ArgPfxEq("units")) { @@ -970,7 +971,7 @@ TkFindStateNumObj( * Not there. Look in the state map. */ - key = Tcl_GetStringFromObj(keyPtr, NULL); + key = Tcl_GetString(keyPtr); for (mPtr = mapPtr; mPtr->strKey != NULL; mPtr++) { if (strcmp(key, mPtr->strKey) == 0) { typePtr = keyPtr->typePtr; diff --git a/generic/tkWindow.c b/generic/tkWindow.c index f4138b2..b5cbbab 100644 --- a/generic/tkWindow.c +++ b/generic/tkWindow.c @@ -14,7 +14,7 @@ #include "tkInt.h" -#ifdef __WIN32__ +#ifdef _WIN32 #include "tkWinInt.h" #elif !defined(MAC_OSX_TK) #include "tkUnixInt.h" @@ -97,9 +97,8 @@ static const XSetWindowAttributes defAtts= { #define ISSAFE 1 #define PASSMAINWINDOW 2 -#define NOOBJPROC 4 -#define WINMACONLY 8 -#define USEINITPROC 16 +#define WINMACONLY 4 +#define USEINITPROC 8 typedef int (TkInitProc)(Tcl_Interp *interp, ClientData clientData); typedef struct { @@ -149,13 +148,13 @@ static const TkCmd commands[] = { {"label", Tk_LabelObjCmd, ISSAFE}, {"labelframe", Tk_LabelframeObjCmd, ISSAFE}, {"listbox", Tk_ListboxObjCmd, ISSAFE}, + {"menu", Tk_MenuObjCmd, PASSMAINWINDOW}, {"menubutton", Tk_MenubuttonObjCmd, ISSAFE}, {"message", Tk_MessageObjCmd, ISSAFE}, {"panedwindow", Tk_PanedWindowObjCmd, ISSAFE}, {"radiobutton", Tk_RadiobuttonObjCmd, ISSAFE}, {"scale", Tk_ScaleObjCmd, ISSAFE}, - {"scrollbar", (Tcl_ObjCmdProc *) Tk_ScrollbarCmd, - NOOBJPROC|PASSMAINWINDOW|ISSAFE}, + {"scrollbar", Tk_ScrollbarObjCmd, PASSMAINWINDOW|ISSAFE}, {"spinbox", Tk_SpinboxObjCmd, ISSAFE}, {"text", Tk_TextObjCmd, PASSMAINWINDOW|ISSAFE}, {"toplevel", Tk_ToplevelObjCmd, 0}, @@ -177,8 +176,7 @@ static const TkCmd commands[] = { {"::tk::panedwindow",Tk_PanedWindowObjCmd, ISSAFE}, {"::tk::radiobutton",Tk_RadiobuttonObjCmd, ISSAFE}, {"::tk::scale", Tk_ScaleObjCmd, ISSAFE}, - {"::tk::scrollbar", (Tcl_ObjCmdProc *) Tk_ScrollbarCmd, - NOOBJPROC|PASSMAINWINDOW|ISSAFE}, + {"::tk::scrollbar", Tk_ScrollbarObjCmd, PASSMAINWINDOW|ISSAFE}, {"::tk::spinbox", Tk_SpinboxObjCmd, ISSAFE}, {"::tk::text", Tk_TextObjCmd, PASSMAINWINDOW|ISSAFE}, {"::tk::toplevel", Tk_ToplevelObjCmd, 0}, @@ -188,7 +186,7 @@ static const TkCmd commands[] = { * these commands differently (via the script library). */ -#if defined(__WIN32__) || defined(MAC_OSX_TK) +#if defined(_WIN32) || defined(MAC_OSX_TK) {"tk_chooseColor", Tk_ChooseColorObjCmd, PASSMAINWINDOW}, {"tk_chooseDirectory", Tk_ChooseDirectoryObjCmd,WINMACONLY|PASSMAINWINDOW}, {"tk_getOpenFile", Tk_GetOpenFileObjCmd, WINMACONLY|PASSMAINWINDOW}, @@ -958,7 +956,7 @@ TkCreateMainWindow( Tcl_Panic("TkCreateMainWindow: builtin command with NULL string and object procs"); } -#if defined(__WIN32__) && !defined(STATIC_BUILD) +#if defined(_WIN32) && !defined(STATIC_BUILD) if ((cmdPtr->flags & WINMACONLY) && tclStubsPtr->reserved9) { /* * We are running on Cygwin, so don't use the win32 dialogs. @@ -966,7 +964,7 @@ TkCreateMainWindow( continue; } -#endif /* __WIN32__ && !STATIC_BUILD */ +#endif /* _WIN32 && !STATIC_BUILD */ if (cmdPtr->flags & PASSMAINWINDOW) { clientData = tkwin; @@ -975,9 +973,6 @@ TkCreateMainWindow( } if (cmdPtr->flags & USEINITPROC) { ((TkInitProc *) cmdPtr->objProc)(interp, clientData); - } else if (cmdPtr->flags & NOOBJPROC) { - Tcl_CreateCommand(interp, cmdPtr->name, - (Tcl_CmdProc *) cmdPtr->objProc, clientData, NULL); } else { Tcl_CreateObjCommand(interp, cmdPtr->name, cmdPtr->objProc, clientData, NULL); @@ -987,14 +982,12 @@ TkCreateMainWindow( } } - TkCreateMenuCmd(interp); - /* * Set variables for the intepreter. */ - Tcl_SetVar(interp, "tk_patchLevel", TK_PATCH_LEVEL, TCL_GLOBAL_ONLY); - Tcl_SetVar(interp, "tk_version", TK_VERSION, TCL_GLOBAL_ONLY); + Tcl_SetVar2(interp, "tk_patchLevel", NULL, TK_PATCH_LEVEL, TCL_GLOBAL_ONLY); + Tcl_SetVar2(interp, "tk_version", NULL, TK_VERSION, TCL_GLOBAL_ONLY); tsdPtr->numMainWindows++; return tkwin; @@ -1467,7 +1460,7 @@ Tk_DestroyWindow( TkWmRemoveFromColormapWindows(winPtr); } if (winPtr->window != None) { -#if defined(MAC_OSX_TK) || defined(__WIN32__) +#if defined(MAC_OSX_TK) || defined(_WIN32) XDestroyWindow(winPtr->display, winPtr->window); #else if ((winPtr->flags & TK_TOP_HIERARCHY) @@ -1544,11 +1537,11 @@ Tk_DestroyWindow( if ((winPtr->mainPtr->interp != NULL) && !Tcl_InterpDeleted(winPtr->mainPtr->interp)) { for (cmdPtr = commands; cmdPtr->name != NULL; cmdPtr++) { - Tcl_CreateCommand(winPtr->mainPtr->interp, cmdPtr->name, - TkDeadAppCmd, NULL, NULL); + Tcl_CreateObjCommand(winPtr->mainPtr->interp, cmdPtr->name, + TkDeadAppObjCmd, NULL, NULL); } - Tcl_CreateCommand(winPtr->mainPtr->interp, "send", - TkDeadAppCmd, NULL, NULL); + Tcl_CreateObjCommand(winPtr->mainPtr->interp, "send", + TkDeadAppObjCmd, NULL, NULL); Tcl_UnlinkVar(winPtr->mainPtr->interp, "tk_strictMotif"); Tcl_UnlinkVar(winPtr->mainPtr->interp, "::tk::AlwaysShowSelection"); @@ -1579,7 +1572,7 @@ Tk_DestroyWindow( * display now and relinquish its data structures. */ -#if !defined(WIN32) && defined(NOT_YET) +#if !defined(_WIN32) && defined(NOT_YET) if (dispPtr->refCount <= 0) { /* * I have disabled this code because on Windows there are @@ -1627,7 +1620,7 @@ Tk_DestroyWindow( TkCloseDisplay(dispPtr); } -#endif /* !WIN32 && NOT_YET */ +#endif /* !_WIN32 && NOT_YET */ } } Tcl_EventuallyFree(winPtr, TCL_DYNAMIC); @@ -2852,7 +2845,7 @@ DeleteWindowsExitProc( tsdPtr->initialized = 0; } -#if defined(__WIN32__) && !defined(__WIN64__) +#if defined(_WIN32) static HMODULE tkcygwindll = NULL; @@ -2898,7 +2891,7 @@ TkCygwinMainEx( tkmainex(argc, argv, appInitProc, interp); return 1; } -#endif /* __WIN32__ && !__WIN64__ */ +#endif /* _WIN32 */ /* *---------------------------------------------------------------------- @@ -2927,7 +2920,7 @@ int Tk_Init( Tcl_Interp *interp) /* Interpreter to initialize. */ { -#if defined(__WIN32__) && !defined(__WIN64__) +#if defined(_WIN32) if (tkcygwindll) { int (*tkinit)(Tcl_Interp *); @@ -2936,7 +2929,7 @@ Tk_Init( return tkinit(interp); } } -#endif /* __WIN32__ && !__WIN64__ */ +#endif /* _WIN32 */ return Initialize(interp); } @@ -3000,7 +2993,7 @@ Tk_SafeInit( * checked at several places to differentiate the two initialisations. */ -#if defined(__WIN32__) && !defined(__WIN64__) +#if defined(_WIN32) if (tkcygwindll) { int (*tksafeinit)(Tcl_Interp *); @@ -3010,7 +3003,7 @@ Tk_SafeInit( return tksafeinit(interp); } } -#endif /* __WIN32__ && !__WIN64__ */ +#endif /* _WIN32 */ return Initialize(interp); } @@ -3047,11 +3040,10 @@ Initialize( ThreadSpecificData *tsdPtr; /* - * Ensure that we are getting a compatible version of Tcl. This is really - * only an issue when Tk is loaded dynamically. + * Ensure that we are getting a compatible version of Tcl. */ - if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) { + if (Tcl_InitStubs(interp, "8.6", 0) == NULL) { return TCL_ERROR; } @@ -3136,14 +3128,14 @@ Initialize( Tcl_DStringInit(&ds); Tcl_DStringAppendElement(&ds, "::safe::TkInit"); - Tcl_DStringAppendElement(&ds, Tcl_GetStringResult(master)); + Tcl_DStringAppendElement(&ds, Tcl_GetString(Tcl_GetObjResult(master))); /* * Step 2 : Eval in the master. The argument is the *reversed* interp * path of the slave. */ - code = Tcl_Eval(master, Tcl_DStringValue(&ds)); + code = Tcl_EvalEx(master, Tcl_DStringValue(&ds), -1, 0); if (code != TCL_OK) { /* * We might want to transfer the error message or not. We don't. @@ -3164,7 +3156,7 @@ Initialize( * changing the code below. */ - argString = Tcl_GetStringResult(master); + argString = Tcl_GetString(Tcl_GetObjResult(master)); } else { /* * If there is an "argv" variable, get its value, extract out relevant @@ -3279,19 +3271,20 @@ Initialize( */ if (geometry != NULL) { - Tcl_SetVar(interp, "geometry", geometry, TCL_GLOBAL_ONLY); - code = Tcl_VarEval(interp, "wm geometry . ", geometry, NULL); + Tcl_DString buf; + + Tcl_SetVar2(interp, "geometry", NULL, geometry, TCL_GLOBAL_ONLY); + Tcl_DStringInit(&buf); + Tcl_DStringAppend(&buf, "wm geometry . ", -1); + Tcl_DStringAppend(&buf, geometry, -1); + code = Tcl_EvalEx(interp, Tcl_DStringValue(&buf), -1, 0); + Tcl_DStringFree(&buf); if (code != TCL_OK) { goto done; } geometry = NULL; } - if (Tcl_PkgRequire(interp, "Tcl", TCL_VERSION, 0) == NULL) { - code = TCL_ERROR; - goto done; - } - /* * Provide Tk and its stub table. */ @@ -3343,7 +3336,7 @@ Initialize( * an alternate [tkInit] command before calling Tk_Init(). */ - code = Tcl_Eval(interp, + code = Tcl_EvalEx(interp, "if {[namespace which -command tkInit] eq \"\"} {\n\ proc tkInit {} {\n\ global tk_library tk_version tk_patchLevel\n\ @@ -3351,7 +3344,7 @@ Initialize( tcl_findLibrary tk $tk_version $tk_patchLevel tk.tcl TK_LIBRARY tk_library\n\ }\n\ }\n\ -tkInit"); +tkInit", -1, 0); } if (code == TCL_OK) { /* @@ -3397,7 +3390,7 @@ Tk_PkgInitStubsCheck( const char * version, int exact) { - const char *actualVersion = Tcl_PkgRequire(interp, "Tk", version, 0); + const char *actualVersion = Tcl_PkgRequireEx(interp, "Tk", version, 0, NULL); if (exact && actualVersion) { const char *p = version; @@ -3409,11 +3402,11 @@ Tk_PkgInitStubsCheck( if (count == 1) { if (0 != strncmp(version, actualVersion, strlen(version))) { /* Construct error message */ - Tcl_PkgPresent(interp, "Tk", version, 1); + Tcl_PkgPresentEx(interp, "Tk", version, 1, NULL); return NULL; } } else { - return Tcl_PkgPresent(interp, "Tk", version, 1); + return Tcl_PkgPresentEx(interp, "Tk", version, 1, NULL); } } return actualVersion; diff --git a/generic/ttk/ttkButton.c b/generic/ttk/ttkButton.c index 2954184..bc44f25 100644 --- a/generic/ttk/ttkButton.c +++ b/generic/ttk/ttkButton.c @@ -413,8 +413,8 @@ typedef struct static Tk_OptionSpec CheckbuttonOptionSpecs[] = { {TK_OPTION_STRING, "-variable", "variable", "Variable", - "", Tk_Offset(Checkbutton, checkbutton.variableObj), -1, - TK_OPTION_DONT_SET_DEFAULT,0,0}, + NULL, Tk_Offset(Checkbutton, checkbutton.variableObj), -1, + TK_OPTION_NULL_OK,0,0}, {TK_OPTION_STRING, "-onvalue", "onValue", "OnValue", "1", Tk_Offset(Checkbutton, checkbutton.onValueObj), -1, 0,0,0}, diff --git a/generic/ttk/ttkCache.c b/generic/ttk/ttkCache.c index 39c76e0..0ae2372 100644 --- a/generic/ttk/ttkCache.c +++ b/generic/ttk/ttkCache.c @@ -270,7 +270,7 @@ static Tcl_Obj *Ttk_Use( } else { Tcl_DecrRefCount(cacheObj); Tcl_SetHashValue(entryPtr, NULL); - Tcl_BackgroundError(interp); + Tcl_BackgroundException(interp, TCL_ERROR); return NULL; } } @@ -341,7 +341,7 @@ Tk_Image Ttk_UseImage(Ttk_ResourceCache cache, Tk_Window tkwin, Tcl_Obj *objPtr) Tcl_SetHashValue(entryPtr, image); if (!image) { - Tcl_BackgroundError(cache->interp); + Tcl_BackgroundException(cache->interp, TCL_ERROR); } return image; diff --git a/generic/ttk/ttkClamTheme.c b/generic/ttk/ttkClamTheme.c index 572f630..15ebcb7 100644 --- a/generic/ttk/ttkClamTheme.c +++ b/generic/ttk/ttkClamTheme.c @@ -12,7 +12,7 @@ * off-by-one error in the end point. This is especially apparent with this * theme. Defining this macro as true handles this case. */ -#if defined(WIN32) && !defined(WIN32_XDRAWLINE_HACK) +#if defined(_WIN32) && !defined(WIN32_XDRAWLINE_HACK) # define WIN32_XDRAWLINE_HACK 1 #else # define WIN32_XDRAWLINE_HACK 0 diff --git a/generic/ttk/ttkDecls.h b/generic/ttk/ttkDecls.h index 3ff2f62..6701724 100644 --- a/generic/ttk/ttkDecls.h +++ b/generic/ttk/ttkDecls.h @@ -13,7 +13,7 @@ extern const char *TtkInitializeStubs( interp, TTK_VERSION, TTK_STUBS_EPOCH, TTK_STUBS_REVISION) #else -#define Ttk_InitStubs(interp) Tcl_PkgRequire(interp, "Ttk", TTK_VERSION, 0) +#define Ttk_InitStubs(interp) Tcl_PkgRequireEx(interp, "Ttk", TTK_VERSION, 0, NULL) #endif @@ -23,6 +23,10 @@ extern const char *TtkInitializeStubs( #define TTK_STUBS_EPOCH 0 #define TTK_STUBS_REVISION 31 +#ifdef __cplusplus +extern "C" { +#endif + /* * Exported function declarations: */ @@ -133,7 +137,7 @@ typedef struct TtkStubs { int magic; int epoch; int revision; - const struct TtkStubHooks *hooks; + void *hooks; Ttk_Theme (*ttk_GetTheme) (Tcl_Interp *interp, const char *name); /* 0 */ Ttk_Theme (*ttk_GetDefaultTheme) (Tcl_Interp *interp); /* 1 */ @@ -178,10 +182,8 @@ typedef struct TtkStubs { int (*ttk_GetOrientFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, int *orient); /* 40 */ } TtkStubs; -#ifdef __cplusplus -extern "C" { -#endif extern const TtkStubs *ttkStubsPtr; + #ifdef __cplusplus } #endif diff --git a/generic/ttk/ttkDefaultTheme.c b/generic/ttk/ttkDefaultTheme.c index d2deee8..81f8126 100644 --- a/generic/ttk/ttkDefaultTheme.c +++ b/generic/ttk/ttkDefaultTheme.c @@ -12,7 +12,7 @@ #include <X11/Xutil.h> #include "ttkTheme.h" -#if defined(WIN32) +#if defined(_WIN32) static const int WIN32_XDRAWLINE_HACK = 1; #else static const int WIN32_XDRAWLINE_HACK = 0; @@ -722,8 +722,8 @@ static void MenubuttonArrowElementDraw( int width = 0, height = 0; Tk_GetPixelsFromObj(NULL, tkwin, arrow->sizeObj, &size); - Tcl_GetIndexFromObj(NULL, arrow->directionObj, directionStrings, - ""/*message*/, 0/*flags*/, &postDirection); + Tcl_GetIndexFromObjStruct(NULL, arrow->directionObj, directionStrings, + sizeof(char *), ""/*message*/, 0/*flags*/, &postDirection); /* ... this might not be such a great idea ... */ switch (postDirection) { diff --git a/generic/ttk/ttkElements.c b/generic/ttk/ttkElements.c index 22af1d6..5c95dba 100644 --- a/generic/ttk/ttkElements.c +++ b/generic/ttk/ttkElements.c @@ -1145,7 +1145,7 @@ static void TabElementDraw( Tk_3DBorderGC(tkwin, border, TK_3D_FLAT_GC), pts, 6, Convex, CoordModeOrigin); -#ifndef WIN32 +#ifndef _WIN32 /* * Account for whether XDrawLines draws endpoints by platform */ @@ -1275,7 +1275,7 @@ void TtkElements_Init(Tcl_Interp *interp) /* * Register "default" as a user-loadable theme (for now): */ - Tcl_PkgProvide(interp, "ttk::theme::default", TTK_VERSION); + Tcl_PkgProvideEx(interp, "ttk::theme::default", TTK_VERSION, NULL); } /*EOF*/ diff --git a/generic/ttk/ttkEntry.c b/generic/ttk/ttkEntry.c index a962662..f395649 100644 --- a/generic/ttk/ttkEntry.c +++ b/generic/ttk/ttkEntry.c @@ -652,7 +652,7 @@ static void EntryRevalidateBG(Entry *entryPtr, VREASON reason) { Tcl_Interp *interp = entryPtr->core.interp; if (EntryRevalidate(interp, entryPtr, reason) == TCL_ERROR) { - Tcl_BackgroundError(interp); + Tcl_BackgroundException(interp, TCL_ERROR); } } @@ -758,8 +758,8 @@ static int EntrySetValue(Entry *entryPtr, const char *value) Tcl_GetString(entryPtr->entry.textVariableObj); if (textVarName && *textVarName) { entryPtr->core.flags |= SYNCING_VARIABLE; - value = Tcl_SetVar(entryPtr->core.interp, textVarName, - value, TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG); + value = Tcl_SetVar2(entryPtr->core.interp, textVarName, + NULL, value, TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG); entryPtr->core.flags &= ~SYNCING_VARIABLE; if (!value || WidgetDestroyed(&entryPtr->core)) { return TCL_ERROR; @@ -786,7 +786,7 @@ static void EntryTextVariableTrace(void *recordPtr, const char *value) } if (entryPtr->core.flags & SYNCING_VARIABLE) { - /* Trace was fired due to Tcl_SetVar call in EntrySetValue. + /* Trace was fired due to Tcl_SetVar2 call in EntrySetValue. * Don't do anything. */ return; @@ -1314,8 +1314,8 @@ EntryIndex( int *indexPtr) /* Return value */ { # define EntryWidth(e) (Tk_Width(entryPtr->core.tkwin)) /* Not Right */ - int length; - const char *string = Tcl_GetStringFromObj(indexObj, &length); + const char *string = Tcl_GetString(indexObj); + size_t length = indexObj->length; if (strncmp(string, "end", length) == 0) { *indexPtr = entryPtr->entry.numChars; @@ -1644,6 +1644,14 @@ static int EntryXViewCommand( void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Entry *entryPtr = recordPtr; + if (objc == 3) { + int newFirst; + if (EntryIndex(interp, entryPtr, objv[2], &newFirst) != TCL_OK) { + return TCL_ERROR; + } + TtkScrollTo(entryPtr->entry.xscrollHandle, newFirst); + return TCL_OK; + } return TtkScrollviewCommand(interp, objc, objv, entryPtr->entry.xscrollHandle); } diff --git a/generic/ttk/ttkGenStubs.tcl b/generic/ttk/ttkGenStubs.tcl index 269d3ef..56ba2fa 100644 --- a/generic/ttk/ttkGenStubs.tcl +++ b/generic/ttk/ttkGenStubs.tcl @@ -12,7 +12,7 @@ # # SOURCE: tcl/tools/genStubs.tcl, revision 1.44 # -# CHANGES: +# CHANGES: # + Second argument to "declare" is used as a status guard # instead of a platform guard. # + Allow trailing semicolon in function declarations @@ -290,14 +290,14 @@ proc genStubs::addPlatformGuard {plat iftxt {eltxt {}}} { set text "" switch $plat { win { - append text "#ifdef __WIN32__ /* WIN */\n${iftxt}" + append text "#ifdef _WIN32 /* WIN */\n${iftxt}" if {$eltxt ne ""} { append text "#else /* WIN */\n${eltxt}" } append text "#endif /* WIN */\n" } unix { - append text "#if !defined(__WIN32__) && !defined(MAC_OSX_TCL)\ + append text "#if !defined(_WIN32) && !defined(MAC_OSX_TCL)\ /* UNIX */\n${iftxt}" if {$eltxt ne ""} { append text "#else /* UNIX */\n${eltxt}" @@ -319,7 +319,7 @@ proc genStubs::addPlatformGuard {plat iftxt {eltxt {}}} { append text "#endif /* AQUA */\n" } x11 { - append text "#if !(defined(__WIN32__) || defined(MAC_OSX_TK))\ + append text "#if !(defined(_WIN32) || defined(MAC_OSX_TK))\ /* X11 */\n${iftxt}" if {$eltxt ne ""} { append text "#else /* X11 */\n${eltxt}" @@ -572,8 +572,8 @@ proc genStubs::makeSlot {name decl index} { append text $rtype " *" $lfname "; /* $index */\n" return $text } - if {[string range $rtype end-7 end] eq "CALLBACK"} { - append text [string trim [string range $rtype 0 end-8]] " (CALLBACK *" $lfname ") " + if {[string range $rtype end-8 end] eq "__stdcall"} { + append text [string trim [string range $rtype 0 end-9]] " (__stdcall *" $lfname ") " } else { append text $rtype " (*" $lfname ") " } @@ -678,7 +678,7 @@ proc genStubs::addGuard {status text} { set upName [string toupper $libraryName] switch -- $status { - current { + current { # No change } deprecated { @@ -691,7 +691,7 @@ proc genStubs::addGuard {status text} { puts stderr "Unrecognized status code $status" } } - return $text + return $text } proc genStubs::ifdeffed {macro text} { @@ -769,10 +769,12 @@ proc genStubs::emitHeader {name} { append text "#define ${CAPName}_STUBS_REVISION $revision\n" } + append text "\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n" + emitDeclarations $name text if {[info exists hooks($name)]} { - append text "\ntypedef struct ${capName}StubHooks {\n" + append text "\ntypedef struct {\n" foreach hook $hooks($name) { set capHook [string toupper [string index $hook 0]] append capHook [string range $hook 1 end] @@ -786,14 +788,17 @@ proc genStubs::emitHeader {name} { append text " int epoch;\n" append text " int revision;\n" } - append text " const struct ${capName}StubHooks *hooks;\n\n" + if {[info exists hooks($name)]} { + append text " const ${capName}StubHooks *hooks;\n\n" + } else { + append text " void *hooks;\n\n" + } emitSlots $name text append text "} ${capName}Stubs;\n\n" - append text "#ifdef __cplusplus\nextern \"C\" {\n#endif\n" - append text "extern const ${capName}Stubs *${name}StubsPtr;\n" + append text "extern const ${capName}Stubs *${name}StubsPtr;\n\n" append text "#ifdef __cplusplus\n}\n#endif\n" emitMacros $name text diff --git a/generic/ttk/ttkImage.c b/generic/ttk/ttkImage.c index 1d455d9..a5a3a52 100644 --- a/generic/ttk/ttkImage.c +++ b/generic/ttk/ttkImage.c @@ -36,7 +36,7 @@ static void NullImageChanged(ClientData clientData, /* TtkGetImageSpec -- * Constructs a Ttk_ImageSpec * from a Tcl_Obj *. - * Result must be released using TtkFreeImageSpec. + * Result must be released using TtkFreeImageSpec. * * TODO: Need a variant of this that takes a user-specified ImageChanged proc */ @@ -364,8 +364,8 @@ Ttk_CreateImageElement( } #endif - if (Tcl_GetIndexFromObj(interp, objv[i], optionStrings, - "option", 0, &option) != TCL_OK) { + if (Tcl_GetIndexFromObjStruct(interp, objv[i], optionStrings, + sizeof(char *), "option", 0, &option) != TCL_OK) { goto error; } diff --git a/generic/ttk/ttkInit.c b/generic/ttk/ttkInit.c index 78676c6..dc6e994 100644 --- a/generic/ttk/ttkInit.c +++ b/generic/ttk/ttkInit.c @@ -21,8 +21,8 @@ int Ttk_GetButtonDefaultStateFromObj( Tcl_Interp *interp, Tcl_Obj *objPtr, int *statePtr) { *statePtr = TTK_BUTTON_DEFAULT_DISABLED; - return Tcl_GetIndexFromObj(interp, objPtr, - ttkDefaultStrings, "default state", 0, statePtr); + return Tcl_GetIndexFromObjStruct(interp, objPtr, ttkDefaultStrings, + sizeof(char *), "default state", 0, statePtr); } /* @@ -38,8 +38,8 @@ int Ttk_GetCompoundFromObj( Tcl_Interp *interp, Tcl_Obj *objPtr, int *statePtr) { *statePtr = TTK_COMPOUND_NONE; - return Tcl_GetIndexFromObj(interp, objPtr, - ttkCompoundStrings, "compound layout", 0, statePtr); + return Tcl_GetIndexFromObjStruct(interp, objPtr, ttkCompoundStrings, + sizeof(char *), "compound layout", 0, statePtr); } /* @@ -54,8 +54,8 @@ int Ttk_GetOrientFromObj( Tcl_Interp *interp, Tcl_Obj *objPtr, int *resultPtr) { *resultPtr = TTK_ORIENT_HORIZONTAL; - return Tcl_GetIndexFromObj(interp, objPtr, - ttkOrientStrings, "orientation", 0, resultPtr); + return Tcl_GetIndexFromObjStruct(interp, objPtr, ttkOrientStrings, + sizeof(char *), "orientation", 0, resultPtr); } /* @@ -65,18 +65,18 @@ int Ttk_GetOrientFromObj( static const char *ttkStateStrings[] = { "normal", "readonly", "disabled", "active", NULL }; -enum { +enum { TTK_COMPAT_STATE_NORMAL, TTK_COMPAT_STATE_READONLY, TTK_COMPAT_STATE_DISABLED, TTK_COMPAT_STATE_ACTIVE }; -/* TtkCheckStateOption -- +/* TtkCheckStateOption -- * Handle -state compatibility option. * - * NOTE: setting -state disabled / -state enabled affects the - * widget state, but the internal widget state does *not* affect + * NOTE: setting -state disabled / -state enabled affects the + * widget state, but the internal widget state does *not* affect * the value of the -state option. * This option is present for compatibility only. */ @@ -86,7 +86,8 @@ void TtkCheckStateOption(WidgetCore *corePtr, Tcl_Obj *objPtr) unsigned all = TTK_STATE_DISABLED|TTK_STATE_READONLY|TTK_STATE_ACTIVE; # define SETFLAGS(f) TtkWidgetChangeState(corePtr, f, all^f) - (void)Tcl_GetIndexFromObj(NULL,objPtr,ttkStateStrings,"",0,&stateOption); + (void)Tcl_GetIndexFromObjStruct(NULL, objPtr, ttkStateStrings, + sizeof(char *), "", 0, &stateOption); switch (stateOption) { case TTK_COMPAT_STATE_NORMAL: default: @@ -174,7 +175,7 @@ int TtkGetOptionValue( * type name dbName dbClass default objOffset intOffset flags clientData mask */ -/* public */ +/* public */ Tk_OptionSpec ttkCoreOptionSpecs[] = { {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor", NULL, diff --git a/generic/ttk/ttkLabel.c b/generic/ttk/ttkLabel.c index 0f71970..1037840 100644 --- a/generic/ttk/ttkLabel.c +++ b/generic/ttk/ttkLabel.c @@ -293,6 +293,7 @@ static void ImageCleanup(ImageElement *image) TtkFreeImageSpec(image->imageSpec); } +#ifndef MAC_OSX_TK /* * StippleOver -- * Draw a stipple over the image area, to make it look "grayed-out" @@ -317,6 +318,7 @@ static void StippleOver( Tk_FreeBitmapFromObj(tkwin, image->stippleObj); } } +#endif static void ImageDraw( ImageElement *image, Tk_Window tkwin,Drawable d,Ttk_Box b,Ttk_State state) @@ -486,6 +488,7 @@ static Ttk_ElementOptionSpec LabelElementOptions[] = { * Calculate the text, image, and total width and height. */ +#undef MAX #define MAX(a,b) ((a) > (b) ? a : b); static void LabelSetup( LabelElement *c, Tk_Window tkwin, Ttk_State state) diff --git a/generic/ttk/ttkLayout.c b/generic/ttk/ttkLayout.c index de9d795..ba24589 100644 --- a/generic/ttk/ttkLayout.c +++ b/generic/ttk/ttkLayout.c @@ -636,8 +636,8 @@ Ttk_LayoutTemplate Ttk_ParseLayoutTemplate(Tcl_Interp *interp, Tcl_Obj *objPtr) if (optName[0] != '-') break; - if (Tcl_GetIndexFromObj( - interp, objv[i], optStrings, "option", 0, &option) + if (Tcl_GetIndexFromObjStruct(interp, objv[i], optStrings, + sizeof(char *), "option", 0, &option) != TCL_OK) { goto error; @@ -653,8 +653,8 @@ Ttk_LayoutTemplate Ttk_ParseLayoutTemplate(Tcl_Interp *interp, Tcl_Obj *objPtr) switch (option) { case OP_SIDE: /* <<NOTE-PACKSIDE>> */ - if (Tcl_GetIndexFromObj(interp, objv[i], packSideStrings, - "side", 0, &value) != TCL_OK) + if (Tcl_GetIndexFromObjStruct(interp, objv[i], packSideStrings, + sizeof(char *), "side", 0, &value) != TCL_OK) { goto error; } diff --git a/generic/ttk/ttkManager.c b/generic/ttk/ttkManager.c index cf98a6d..24a0fb1 100644 --- a/generic/ttk/ttkManager.c +++ b/generic/ttk/ttkManager.c @@ -237,7 +237,7 @@ void Ttk_DeleteManager(Ttk_Manager *mgr) ckfree(mgr->slaves); } - Tk_CancelIdleCall(ManagerIdleProc, mgr); + Tcl_CancelIdleCall(ManagerIdleProc, mgr); ckfree(mgr); } diff --git a/generic/ttk/ttkNotebook.c b/generic/ttk/ttkNotebook.c index 6849135..81a8b64 100644 --- a/generic/ttk/ttkNotebook.c +++ b/generic/ttk/ttkNotebook.c @@ -901,7 +901,7 @@ static int NotebookAddCommand( if (tab->state == TAB_STATE_HIDDEN) { tab->state = TAB_STATE_NORMAL; } - if (ConfigureTab(interp, nb, tab, slaveWindow, objc-4,objv+4) != TCL_OK) { + if (ConfigureTab(interp, nb, tab, slaveWindow, objc-3,objv+3) != TCL_OK) { return TCL_ERROR; } @@ -1058,9 +1058,8 @@ static int NotebookIdentifyCommand( if ( Tcl_GetIntFromObj(interp, objv[objc-2], &x) != TCL_OK || Tcl_GetIntFromObj(interp, objv[objc-1], &y) != TCL_OK - || (objc == 5 && - Tcl_GetIndexFromObj(interp, objv[2], whatTable, "option", 0, &what) - != TCL_OK) + || (objc == 5 && Tcl_GetIndexFromObjStruct(interp, objv[2], whatTable, + sizeof(char *), "option", 0, &what) != TCL_OK) ) { return TCL_ERROR; } diff --git a/generic/ttk/ttkPanedwindow.c b/generic/ttk/ttkPanedwindow.c index f4b14c9..adc2aef 100644 --- a/generic/ttk/ttkPanedwindow.c +++ b/generic/ttk/ttkPanedwindow.c @@ -731,9 +731,8 @@ static int PanedIdentifyCommand( if ( Tcl_GetIntFromObj(interp, objv[objc-2], &x) != TCL_OK || Tcl_GetIntFromObj(interp, objv[objc-1], &y) != TCL_OK - || (objc == 5 && - Tcl_GetIndexFromObj(interp, objv[2], whatTable, "option", 0, &what) - != TCL_OK) + || (objc == 5 && Tcl_GetIndexFromObjStruct(interp, objv[2], whatTable, + sizeof(char *), "option", 0, &what) != TCL_OK) ) { return TCL_ERROR; } diff --git a/generic/ttk/ttkScroll.c b/generic/ttk/ttkScroll.c index c02b868..2bd3ddb 100644 --- a/generic/ttk/ttkScroll.c +++ b/generic/ttk/ttkScroll.c @@ -7,7 +7,7 @@ * * Scrollable interface: * - * + 'first' is controlled by [xy]view widget command + * + 'first' is controlled by [xy]view widget command * and other scrolling commands like 'see'; * + 'total' depends on widget contents; * + 'last' depends on first, total, and widget size. @@ -16,15 +16,15 @@ * * 1. User adjusts scrollbar, scrollbar widget calls its -command * 2. Scrollbar -command invokes the scrollee [xy]view widget method - * 3. TtkScrollviewCommand calls TtkScrollTo(), which updates + * 3. TtkScrollviewCommand calls TtkScrollTo(), which updates * 'first' and schedules a redisplay. - * 4. Once the scrollee knows 'total' and 'last' (typically in - * the LayoutProc), call TtkScrolled(h,first,last,total) to + * 4. Once the scrollee knows 'total' and 'last' (typically in + * the LayoutProc), call TtkScrolled(h,first,last,total) to * synchronize the scrollbar. * 5. The scrollee -[xy]scrollcommand is called (in an idle callback) * 6. Which calls the scrollbar 'set' method and redisplays the scrollbar. * - * If the scrollee has internal scrolling (e.g., a 'see' method), + * If the scrollee has internal scrolling (e.g., a 'see' method), * it should TtkScrollTo() directly (step 2). * * If the widget value changes, it should call TtkScrolled() (step 4). @@ -34,7 +34,7 @@ * TtkScrollbarUpdateRequired, which will invoke step (5) (@@@ Fix this) */ -#include <tk.h> +#include <tkInt.h> #include "ttkTheme.h" #include "ttkWidget.h" @@ -78,6 +78,7 @@ static int UpdateScrollbar(Tcl_Interp *interp, ScrollHandle h) char arg1[TCL_DOUBLE_SPACE + 2]; char arg2[TCL_DOUBLE_SPACE + 2]; int code; + Tcl_DString buf; h->flags &= ~SCROLL_UPDATE_REQUIRED; @@ -88,9 +89,14 @@ static int UpdateScrollbar(Tcl_Interp *interp, ScrollHandle h) arg1[0] = arg2[0] = ' '; Tcl_PrintDouble(interp, (double)s->first / s->total, arg1+1); Tcl_PrintDouble(interp, (double)s->last / s->total, arg2+1); + Tcl_DStringInit(&buf); + Tcl_DStringAppend(&buf, s->scrollCmd, -1); + Tcl_DStringAppend(&buf, arg1, -1); + Tcl_DStringAppend(&buf, arg2, -1); Tcl_Preserve(corePtr); - code = Tcl_VarEval(interp, s->scrollCmd, arg1, arg2, NULL); + code = Tcl_EvalEx(interp, Tcl_DStringValue(&buf), -1, TCL_EVAL_GLOBAL); + Tcl_DStringFree(&buf); if (WidgetDestroyed(corePtr)) { Tcl_Release(corePtr); return TCL_ERROR; @@ -124,7 +130,7 @@ static void UpdateScrollbarBG(ClientData clientData) Tcl_Preserve((ClientData) interp); code = UpdateScrollbar(interp, h); if (code == TCL_ERROR && !Tcl_InterpDeleted(interp)) { - Tcl_BackgroundError(interp); + Tcl_BackgroundException(interp, code); } Tcl_Release((ClientData) interp); } @@ -135,7 +141,7 @@ static void UpdateScrollbarBG(ClientData clientData) void TtkScrolled(ScrollHandle h, int first, int last, int total) { Scrollable *s = h->scrollPtr; - + /* Sanity-check inputs: */ if (total <= 0) { diff --git a/generic/ttk/ttkTheme.c b/generic/ttk/ttkTheme.c index 5097abc..2f95962 100644 --- a/generic/ttk/ttkTheme.c +++ b/generic/ttk/ttkTheme.c @@ -508,8 +508,9 @@ static void ThemeChangedProc(ClientData clientData) static char ThemeChangedScript[] = "ttk::ThemeChanged"; StylePackageData *pkgPtr = clientData; - if (Tcl_GlobalEval(pkgPtr->interp, ThemeChangedScript) != TCL_OK) { - Tcl_BackgroundError(pkgPtr->interp); + int code = Tcl_EvalEx(pkgPtr->interp, ThemeChangedScript, -1, TCL_EVAL_GLOBAL); + if (code != TCL_OK) { + Tcl_BackgroundException(pkgPtr->interp, code); } pkgPtr->themeChangePending = 0; } @@ -1393,8 +1394,8 @@ static int StyleThemeCreateCmd( for (i=4; i < objc; i +=2) { int option; - if (Tcl_GetIndexFromObj( - interp, objv[i], optStrings, "option", 0, &option) != TCL_OK) + if (Tcl_GetIndexFromObjStruct(interp, objv[i], optStrings, + sizeof(char *), "option", 0, &option) != TCL_OK) { return TCL_ERROR; } @@ -1673,7 +1674,7 @@ StyleObjCmd( return Ttk_InvokeEnsemble(StyleEnsemble, 1, clientData,interp,objc,objv); } -MODULE_SCOPE +MODULE_SCOPE int Ttk_InvokeEnsemble( /* Run an ensemble command */ const Ttk_Ensemble *ensemble, int cmdIndex, void *clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) diff --git a/generic/ttk/ttkTrace.c b/generic/ttk/ttkTrace.c index e6234b8..ba66db4 100644 --- a/generic/ttk/ttkTrace.c +++ b/generic/ttk/ttkTrace.c @@ -54,7 +54,7 @@ VarTraceProc( ckfree((ClientData)tracePtr); return NULL; } - Tcl_TraceVar(interp, name, + Tcl_TraceVar2(interp, name, NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, VarTraceProc, clientData); tracePtr->callback(tracePtr->clientData, NULL); @@ -94,8 +94,8 @@ Ttk_TraceHandle *Ttk_TraceVariable( h->clientData = clientData; h->callback = callback; - status = Tcl_TraceVar(interp, Tcl_GetString(varnameObj), - TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, + status = Tcl_TraceVar2(interp, Tcl_GetString(varnameObj), + NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, VarTraceProc, (ClientData)h); if (status != TCL_OK) { @@ -150,8 +150,8 @@ void Ttk_UntraceVariable(Ttk_TraceHandle *h) h->interp = NULL; return; } - Tcl_UntraceVar(h->interp, Tcl_GetString(h->varnameObj), - TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, + Tcl_UntraceVar2(h->interp, Tcl_GetString(h->varnameObj), + NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, VarTraceProc, (ClientData)h); Tcl_DecrRefCount(h->varnameObj); ckfree(h); diff --git a/generic/ttk/ttkTreeview.c b/generic/ttk/ttkTreeview.c index dc0206c..d957ad2 100644 --- a/generic/ttk/ttkTreeview.c +++ b/generic/ttk/ttkTreeview.c @@ -340,8 +340,8 @@ static int GetEnumSetFromObj( for (i = 0; i < objc; ++i) { int index; - if (TCL_OK != Tcl_GetIndexFromObj( - interp, objv[i], table, "value", TCL_EXACT, &index)) + if (TCL_OK != Tcl_GetIndexFromObjStruct(interp, objv[i], table, + sizeof(char *), "value", TCL_EXACT, &index)) { return TCL_ERROR; } @@ -2287,8 +2287,8 @@ static int TreeviewIdentifyCommand( return TCL_ERROR; } - if ( Tcl_GetIndexFromObj(interp, objv[2], - submethodStrings, "command", TCL_EXACT, &submethod) != TCL_OK + if (Tcl_GetIndexFromObjStruct(interp, objv[2], submethodStrings, + sizeof(char *), "command", TCL_EXACT, &submethod) != TCL_OK || Tcl_GetIntFromObj(interp, objv[3], &x) != TCL_OK || Tcl_GetIntFromObj(interp, objv[4], &y) != TCL_OK ) { @@ -2955,8 +2955,8 @@ static int TreeviewSelectionCommand( return TCL_ERROR; } - if (Tcl_GetIndexFromObj(interp, objv[2], selopStrings, - "selection operation", 0, &selop) != TCL_OK) { + if (Tcl_GetIndexFromObjStruct(interp, objv[2], selopStrings, + sizeof(char *), "selection operation", 0, &selop) != TCL_OK) { return TCL_ERROR; } @@ -3170,6 +3170,8 @@ static int TreeviewTagAddCommand( AddTag(items[i], tag); } + TtkRedisplayWidget(&tv->core); + return TCL_OK; } @@ -3214,6 +3216,9 @@ static int TreeviewTagRemoveCommand( item=NextPreorder(item); } } + + TtkRedisplayWidget(&tv->core); + return TCL_OK; } diff --git a/generic/ttk/ttkWidget.c b/generic/ttk/ttkWidget.c index 016653d..c50efc5 100644 --- a/generic/ttk/ttkWidget.c +++ b/generic/ttk/ttkWidget.c @@ -198,7 +198,7 @@ WidgetInstanceObjCmdDeleted(ClientData clientData) * Final cleanup for widget; called via Tcl_EventuallyFree(). */ static void -FreeWidget(char *memPtr) +FreeWidget(void *memPtr) { ckfree(memPtr); } @@ -231,7 +231,7 @@ DestroyWidget(WidgetCore *corePtr) /* NB: this can reenter the interpreter via a command traces */ Tcl_DeleteCommandFromToken(corePtr->interp, cmd); } - Tcl_EventuallyFree(corePtr, FreeWidget); + Tcl_EventuallyFree(corePtr, (Tcl_FreeProc *) FreeWidget); } /* @@ -766,8 +766,8 @@ int TtkWidgetIdentifyCommand( } if (objc == 5) { /* $w identify element $x $y */ - if (Tcl_GetIndexFromObj(interp,objv[2],whatTable,"option",0,&what) - != TCL_OK) + if (Tcl_GetIndexFromObjStruct(interp, objv[2], whatTable, + sizeof(char *), "option", 0, &what) != TCL_OK) { return TCL_ERROR; } diff --git a/generic/ttk/ttkWidget.h b/generic/ttk/ttkWidget.h index 9e9ab69..e4dd712 100644 --- a/generic/ttk/ttkWidget.h +++ b/generic/ttk/ttkWidget.h @@ -260,7 +260,7 @@ MODULE_SCOPE int TtkGetLabelAnchorFromObj( * Platform-specific initialization. */ -#if defined(__WIN32__) +#ifdef _WIN32 #define Ttk_PlatformInit Ttk_WinPlatformInit MODULE_SCOPE int Ttk_PlatformInit(Tcl_Interp *); #elif defined(MAC_OSX_TK) |