Tk Source Code

Check-in [c24e8f56]
Login

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

Overview
Comment:merge trunk
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | bug-4955f5d8a4
Files: files | file ages | folders
SHA1: c24e8f56b913839a07fae43b851154de25e93ed4
User & Date: jan.nijtmans 2014-05-22 20:24:16
Context
2014-07-08
14:23
Workaround for 4955f5d8a4: tailcall splicing spot vs. raw TclInvokeObjectCommand. This commit can be reverted as soon as a solution for 4955f5d8a4 is committed to Tcl trunk, but I don't want to hold my breath until that is done, neither do I want to leave the Ocaml guys in the cold ... check-in: f748e311 user: jan.nijtmans tags: trunk
2014-05-22
20:24
merge trunk Closed-Leaf check-in: c24e8f56 user: jan.nijtmans tags: bug-4955f5d8a4
20:22
Make "scrollbar" a Tcl_Obj-based command Some more Tcl_Obj-related optimizations check-in: c0ab31ce user: jan.nijtmans tags: trunk
2014-05-19
13:43
Possible fix for 4955f5d8a4 check-in: 3322b5d9 user: jan.nijtmans tags: bug-4955f5d8a4
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to generic/tkCmds.c.

2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
    }
    return 0;
}

/*
 *----------------------------------------------------------------------
 *
 * TkDeadAppCmd --
 *
 *	If an application has been deleted then all Tk commands will be
 *	re-bound to this function.
 *
 * Results:
 *	A standard Tcl error is reported to let the user know that the
 *	application is dead.
 *
 * Side effects:
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
int
TkDeadAppCmd(
    ClientData clientData,	/* Dummy. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
{
    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
	    "can't invoke \"%s\" command: application has been destroyed",
	    argv[0]));
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
 * GetTopHierarchy --







|
















|


|
|



|







2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
    }
    return 0;
}

/*
 *----------------------------------------------------------------------
 *
 * TkDeadAppObjCmd --
 *
 *	If an application has been deleted then all Tk commands will be
 *	re-bound to this function.
 *
 * Results:
 *	A standard Tcl error is reported to let the user know that the
 *	application is dead.
 *
 * Side effects:
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
int
TkDeadAppObjCmd(
    ClientData clientData,	/* Dummy. */
    Tcl_Interp *interp,		/* Current interpreter. */
    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",
	    Tcl_GetString(objv[0])));
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
 * GetTopHierarchy --

Changes to generic/tkInt.h.

1106
1107
1108
1109
1110
1111
1112
1113
1114

1115
1116
1117
1118
1119
1120
1121
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tk_RaiseObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
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_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,







|
|
>







1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tk_RaiseObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tk_ScaleObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
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,
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
MODULE_SCOPE int	TkSetGeometryMaster(Tcl_Interp *interp,
			    Tk_Window tkwin, const char *master);
MODULE_SCOPE void	TkFreeGeometryMaster(Tk_Window tkwin,
			    const char *master);

MODULE_SCOPE void	TkEventInit(void);
MODULE_SCOPE void	TkRegisterObjTypes(void);
MODULE_SCOPE int	TkDeadAppCmd(ClientData clientData,
			    Tcl_Interp *interp, int argc, const char **argv);
MODULE_SCOPE int	TkCanvasGetCoordObj(Tcl_Interp *interp,
			    Tk_Canvas canvas, Tcl_Obj *obj,
			    double *doublePtr);
MODULE_SCOPE int	TkGetDoublePixels(Tcl_Interp *interp, Tk_Window tkwin,
			    const char *string, double *doublePtr);
MODULE_SCOPE int	TkPostscriptImage(Tcl_Interp *interp, Tk_Window tkwin,
			    Tk_PostscriptInfo psInfo, XImage *ximage,







|
|







1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
MODULE_SCOPE int	TkSetGeometryMaster(Tcl_Interp *interp,
			    Tk_Window tkwin, const char *master);
MODULE_SCOPE void	TkFreeGeometryMaster(Tk_Window tkwin,
			    const char *master);

MODULE_SCOPE void	TkEventInit(void);
MODULE_SCOPE void	TkRegisterObjTypes(void);
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);
MODULE_SCOPE int	TkGetDoublePixels(Tcl_Interp *interp, Tk_Window tkwin,
			    const char *string, double *doublePtr);
MODULE_SCOPE int	TkPostscriptImage(Tcl_Interp *interp, Tk_Window tkwin,
			    Tk_PostscriptInfo psInfo, XImage *ximage,

Changes to generic/tkScrollbar.c.

97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
};

/*
 * Forward declarations for functions defined later in this file:
 */

static int		ConfigureScrollbar(Tcl_Interp *interp,
			    TkScrollbar *scrollPtr, int argc,
			    const char **argv, int flags);
static void		ScrollbarCmdDeletedProc(ClientData clientData);
static int		ScrollbarWidgetCmd(ClientData clientData,
			    Tcl_Interp *, int argc, const char **argv);

/*
 *--------------------------------------------------------------
 *
 * Tk_ScrollbarCmd --
 *
 *	This function is invoked to process the "scrollbar" Tcl command. See
 *	the user documentation for details on what it does.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	See the user documentation.
 *
 *--------------------------------------------------------------
 */

int
Tk_ScrollbarCmd(
    ClientData clientData,	/* Main window associated with interpreter. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* 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);
	return TCL_ERROR;
    }

    newWin = Tk_CreateWindowFromPath(interp, tkwin, argv[1], NULL);
    if (newWin == NULL) {
	return TCL_ERROR;
    }

    Tk_SetClass(newWin, "Scrollbar");
    scrollPtr = TkpCreateScrollbar(newWin);

    Tk_SetClassProcs(newWin, &tkpScrollbarProcs, scrollPtr);

    /*
     * Initialize fields that won't be initialized by ConfigureScrollbar, or
     * which ConfigureScrollbar expects to have reasonable values (e.g.
     * resource pointers).
     */

    scrollPtr->tkwin = newWin;
    scrollPtr->display = Tk_Display(newWin);
    scrollPtr->interp = interp;
    scrollPtr->widgetCmd = Tcl_CreateCommand(interp,
	    Tk_PathName(scrollPtr->tkwin), ScrollbarWidgetCmd,
	    scrollPtr, ScrollbarCmdDeletedProc);
    scrollPtr->vertical = 0;
    scrollPtr->width = 0;
    scrollPtr->command = NULL;
    scrollPtr->commandSize = 0;
    scrollPtr->repeatDelay = 0;
    scrollPtr->repeatInterval = 0;







|
|

|
|




|














|


|
|





|
<
|
<
<



|


















|
|







97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138

139


140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
};

/*
 * Forward declarations for functions defined later in this file:
 */

static int		ConfigureScrollbar(Tcl_Interp *interp,
			    TkScrollbar *scrollPtr, int objc,
			    Tcl_Obj *const objv[], int flags);
static void		ScrollbarCmdDeletedProc(ClientData clientData);
static int		ScrollbarWidgetObjCmd(ClientData clientData,
			    Tcl_Interp *, int objc, Tcl_Obj *const objv[]);

/*
 *--------------------------------------------------------------
 *
 * Tk_ScrollbarObjCmd --
 *
 *	This function is invoked to process the "scrollbar" Tcl command. See
 *	the user documentation for details on what it does.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	See the user documentation.
 *
 *--------------------------------------------------------------
 */

int
Tk_ScrollbarObjCmd(
    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 = clientData;
    register TkScrollbar *scrollPtr;
    Tk_Window newWin;

    if (objc < 2) {

	Tcl_WrongNumArgs(interp, 1, objv, "pathName ?-option value ...?");


	return TCL_ERROR;
    }

    newWin = Tk_CreateWindowFromPath(interp, tkwin, Tcl_GetString(objv[1]), NULL);
    if (newWin == NULL) {
	return TCL_ERROR;
    }

    Tk_SetClass(newWin, "Scrollbar");
    scrollPtr = TkpCreateScrollbar(newWin);

    Tk_SetClassProcs(newWin, &tkpScrollbarProcs, scrollPtr);

    /*
     * Initialize fields that won't be initialized by ConfigureScrollbar, or
     * which ConfigureScrollbar expects to have reasonable values (e.g.
     * resource pointers).
     */

    scrollPtr->tkwin = newWin;
    scrollPtr->display = Tk_Display(newWin);
    scrollPtr->interp = interp;
    scrollPtr->widgetCmd = Tcl_CreateObjCommand(interp,
	    Tk_PathName(scrollPtr->tkwin), ScrollbarWidgetObjCmd,
	    scrollPtr, ScrollbarCmdDeletedProc);
    scrollPtr->vertical = 0;
    scrollPtr->width = 0;
    scrollPtr->command = NULL;
    scrollPtr->commandSize = 0;
    scrollPtr->repeatDelay = 0;
    scrollPtr->repeatInterval = 0;
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235




236



237
238
239
240
241
242
243










244
245
246
247


248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284


285
286
287
288
289
290
291
292
293
294


295
296
297
298
299
300
301
302
303
304
305



306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335


336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
    scrollPtr->lastUnit = 0;
    scrollPtr->firstFraction = 0.0;
    scrollPtr->lastFraction = 0.0;
    scrollPtr->cursor = None;
    scrollPtr->takeFocus = NULL;
    scrollPtr->flags = 0;

    if (ConfigureScrollbar(interp, scrollPtr, argc-2, argv+2, 0) != TCL_OK) {
	Tk_DestroyWindow(scrollPtr->tkwin);
	return TCL_ERROR;
    }

    Tcl_SetObjResult(interp, TkNewWindowObj(scrollPtr->tkwin));
    return TCL_OK;
}

/*
 *--------------------------------------------------------------
 *
 * ScrollbarWidgetCmd --
 *
 *	This function is invoked to process the Tcl command that corresponds
 *	to a widget managed by this module. See the user documentation for
 *	details on what it does.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	See the user documentation.
 *
 *--------------------------------------------------------------
 */

static int
ScrollbarWidgetCmd(
    ClientData clientData,	/* Information about scrollbar widget. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* 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);
	return TCL_ERROR;
    }










    Tcl_Preserve(scrollPtr);
    c = argv[1][0];
    length = strlen(argv[1]);
    if ((c == 'a') && (strncmp(argv[1], "activate", length) == 0)) {


	int oldActiveField;

	if (argc == 2) {
	    const char *zone = "";

	    switch (scrollPtr->activeField) {
	    case TOP_ARROW:	zone = "arrow1"; break;
	    case SLIDER:	zone = "slider"; break;
	    case BOTTOM_ARROW:	zone = "arrow2"; break;
	    }
	    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);
	    goto error;
	}
	c = argv[2][0];
	length = strlen(argv[2]);
	oldActiveField = scrollPtr->activeField;
	if ((c == 'a') && (strcmp(argv[2], "arrow1") == 0)) {
	    scrollPtr->activeField = TOP_ARROW;
	} else if ((c == 'a') && (strcmp(argv[2], "arrow2") == 0)) {
	    scrollPtr->activeField = BOTTOM_ARROW;
	} else if ((c == 's') && (strncmp(argv[2], "slider", length) == 0)) {
	    scrollPtr->activeField = SLIDER;
	} else {
	    scrollPtr->activeField = OUTSIDE;
	}
	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);
	    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) {
	    result = Tk_ConfigureInfo(interp, scrollPtr->tkwin,
		    configSpecs, (char *) scrollPtr, NULL, 0);
	} else if (argc == 3) {
	    result = Tk_ConfigureInfo(interp, scrollPtr->tkwin,
		    configSpecs, (char *) scrollPtr, argv[2], 0);
	} else {
	    result = ConfigureScrollbar(interp, scrollPtr, argc-2, argv+2,
		    TK_CONFIG_ARGV_ONLY);
	}
    } else if ((c == 'd') && (strncmp(argv[1], "delta", length) == 0)) {



	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);
	    goto error;
	}
	if ((Tcl_GetInt(interp, argv[2], &xDelta) != TCL_OK)
		|| (Tcl_GetInt(interp, argv[3], &yDelta) != TCL_OK)) {
	    goto error;
	}
	if (scrollPtr->vertical) {
	    pixels = yDelta;
	    length = Tk_Height(scrollPtr->tkwin) - 1
		    - 2*(scrollPtr->arrowLength + scrollPtr->inset);
	} else {
	    pixels = xDelta;
	    length = Tk_Width(scrollPtr->tkwin) - 1
		    - 2*(scrollPtr->arrowLength + scrollPtr->inset);
	}
	if (length == 0) {
	    fraction = 0.0;
	} else {
	    fraction = ((double) pixels / (double) length);
	}
	Tcl_SetObjResult(interp, Tcl_NewDoubleObj(fraction));
    } else if ((c == 'f') && (strncmp(argv[1], "fraction", length) == 0)) {


	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);
	    goto error;
	}
	if ((Tcl_GetInt(interp, argv[2], &x) != TCL_OK)
		|| (Tcl_GetInt(interp, argv[3], &y) != TCL_OK)) {
	    goto error;
	}
	if (scrollPtr->vertical) {
	    pos = y - (scrollPtr->arrowLength + scrollPtr->inset);
	    length = Tk_Height(scrollPtr->tkwin) - 1
		    - 2*(scrollPtr->arrowLength + scrollPtr->inset);
	} else {







|











|















|


|
|



|
>
>
>
>
|
>
>
>

|
|
<
<


>
>
>
>
>
>
>
>
>
>

<
<
<
>
>
|

|










|
<
|
<
<


<
|

|

|

|







|
<
>
>
|
|
<
<



|
|
<
>
>
|


|

|

|
|

<
>
>
>



|
<
|
<
<


|
|

















|
>
>



|
<
|
<


|
|







189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243


244
245
246
247
248
249
250
251
252
253
254
255
256



257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272

273


274
275

276
277
278
279
280
281
282
283
284
285
286
287
288
289
290

291
292
293
294


295
296
297
298
299

300
301
302
303
304
305
306
307
308
309
310
311

312
313
314
315
316
317
318

319


320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347

348

349
350
351
352
353
354
355
356
357
358
359
    scrollPtr->lastUnit = 0;
    scrollPtr->firstFraction = 0.0;
    scrollPtr->lastFraction = 0.0;
    scrollPtr->cursor = None;
    scrollPtr->takeFocus = NULL;
    scrollPtr->flags = 0;

    if (ConfigureScrollbar(interp, scrollPtr, objc-2, objv+2, 0) != TCL_OK) {
	Tk_DestroyWindow(scrollPtr->tkwin);
	return TCL_ERROR;
    }

    Tcl_SetObjResult(interp, TkNewWindowObj(scrollPtr->tkwin));
    return TCL_OK;
}

/*
 *--------------------------------------------------------------
 *
 * ScrollbarWidgetObjCmd --
 *
 *	This function is invoked to process the Tcl command that corresponds
 *	to a widget managed by this module. See the user documentation for
 *	details on what it does.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	See the user documentation.
 *
 *--------------------------------------------------------------
 */

static int
ScrollbarWidgetObjCmd(
    ClientData clientData,	/* Information about scrollbar widget. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])		/* Argument strings. */
{
    register TkScrollbar *scrollPtr = clientData;
    int result = TCL_OK;
    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);



    switch (cmdIndex) {
    case COMMAND_ACTIVATE: {
	int oldActiveField, c;

	if (objc == 2) {
	    const char *zone = "";

	    switch (scrollPtr->activeField) {
	    case TOP_ARROW:	zone = "arrow1"; break;
	    case SLIDER:	zone = "slider"; break;
	    case BOTTOM_ARROW:	zone = "arrow2"; break;
	    }
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(zone, -1));
	    goto done;
	}
	if (objc != 3) {

		Tcl_WrongNumArgs(interp, 1, objv, "activate element");


	    goto error;
	}

	c = Tcl_GetStringFromObj(objv[2], &length)[0];
	oldActiveField = scrollPtr->activeField;
	if ((c == 'a') && (strcmp(Tcl_GetString(objv[2]), "arrow1") == 0)) {
	    scrollPtr->activeField = TOP_ARROW;
	} else if ((c == 'a') && (strcmp(Tcl_GetString(objv[2]), "arrow2") == 0)) {
	    scrollPtr->activeField = BOTTOM_ARROW;
	} else if ((c == 's') && (strncmp(Tcl_GetString(objv[2]), "slider", length) == 0)) {
	    scrollPtr->activeField = SLIDER;
	} else {
	    scrollPtr->activeField = OUTSIDE;
	}
	if (oldActiveField != scrollPtr->activeField) {
	    TkScrollbarEventuallyRedraw(scrollPtr);
	}
	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, 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 (objc == 3) {
	    result = Tk_ConfigureInfo(interp, scrollPtr->tkwin,
		    configSpecs, (char *) scrollPtr, Tcl_GetString(objv[2]), 0);
	} else {
	    result = ConfigureScrollbar(interp, scrollPtr, objc-2,
		    objv+2, TK_CONFIG_ARGV_ONLY);
	}

	break;
    }
    case COMMAND_DELTA: {
	int xDelta, yDelta, pixels, length;
	double fraction;

	if (objc != 4) {

		Tcl_WrongNumArgs(interp, 1, objv, "delta xDelta yDelta");


	    goto error;
	}
	if ((Tcl_GetIntFromObj(interp, objv[2], &xDelta) != TCL_OK)
		|| (Tcl_GetIntFromObj(interp, objv[3], &yDelta) != TCL_OK)) {
	    goto error;
	}
	if (scrollPtr->vertical) {
	    pixels = yDelta;
	    length = Tk_Height(scrollPtr->tkwin) - 1
		    - 2*(scrollPtr->arrowLength + scrollPtr->inset);
	} else {
	    pixels = xDelta;
	    length = Tk_Width(scrollPtr->tkwin) - 1
		    - 2*(scrollPtr->arrowLength + scrollPtr->inset);
	}
	if (length == 0) {
	    fraction = 0.0;
	} else {
	    fraction = ((double) pixels / (double) length);
	}
	Tcl_SetObjResult(interp, Tcl_NewDoubleObj(fraction));
	break;
    }
    case COMMAND_FRACTION: {
	int x, y, pos, length;
	double fraction;

	if (objc != 4) {

		Tcl_WrongNumArgs(interp, 1, objv, "fraction x y");

	    goto error;
	}
	if ((Tcl_GetIntFromObj(interp, objv[2], &x) != TCL_OK)
		|| (Tcl_GetIntFromObj(interp, objv[3], &y) != TCL_OK)) {
	    goto error;
	}
	if (scrollPtr->vertical) {
	    pos = y - (scrollPtr->arrowLength + scrollPtr->inset);
	    length = Tk_Height(scrollPtr->tkwin) - 1
		    - 2*(scrollPtr->arrowLength + scrollPtr->inset);
	} else {
362
363
364
365
366
367
368
369


370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389


390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411


412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
	}
	if (fraction < 0) {
	    fraction = 0;
	} else if (fraction > 1.0) {
	    fraction = 1.0;
	}
	Tcl_SetObjResult(interp, Tcl_NewDoubleObj(fraction));
    } else if ((c == 'g') && (strncmp(argv[1], "get", length) == 0)) {


	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);
	    goto error;
	}
	if (scrollPtr->flags & NEW_STYLE_COMMANDS) {
	    resObjs[0] = Tcl_NewDoubleObj(scrollPtr->firstFraction);
	    resObjs[1] = Tcl_NewDoubleObj(scrollPtr->lastFraction);
	    Tcl_SetObjResult(interp, Tcl_NewListObj(2, resObjs));
	} else {
	    resObjs[0] = Tcl_NewIntObj(scrollPtr->totalUnits);
	    resObjs[1] = Tcl_NewIntObj(scrollPtr->windowUnits);
	    resObjs[2] = Tcl_NewIntObj(scrollPtr->firstUnit);
	    resObjs[3] = Tcl_NewIntObj(scrollPtr->lastUnit);
	    Tcl_SetObjResult(interp, Tcl_NewListObj(4, resObjs));
	}
    } else if ((c == 'i') && (strncmp(argv[1], "identify", length) == 0)) {


	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);
	    goto error;
	}
	if ((Tcl_GetInt(interp, argv[2], &x) != TCL_OK)
		|| (Tcl_GetInt(interp, argv[3], &y) != TCL_OK)) {
	    goto error;
	}
	switch (TkpScrollbarPosition(scrollPtr, x, y)) {
	case TOP_ARROW:		zone = "arrow1";  break;
	case TOP_GAP:		zone = "trough1"; break;
	case SLIDER:		zone = "slider";  break;
	case BOTTOM_GAP:	zone = "trough2"; break;
	case BOTTOM_ARROW:	zone = "arrow2";  break;
	}
	Tcl_SetObjResult(interp, Tcl_NewStringObj(zone, -1));
    } else if ((c == 's') && (strncmp(argv[1], "set", length) == 0)) {


	int totalUnits, windowUnits, firstUnit, lastUnit;

	if (argc == 4) {
	    double first, last;

	    if (Tcl_GetDouble(interp, argv[2], &first) != TCL_OK) {
		goto error;
	    }
	    if (Tcl_GetDouble(interp, argv[3], &last) != TCL_OK) {
		goto error;
	    }
	    if (first < 0) {
		scrollPtr->firstFraction = 0;
	    } else if (first > 1.0) {
		scrollPtr->firstFraction = 1.0;
	    } else {
		scrollPtr->firstFraction = first;
	    }
	    if (last < scrollPtr->firstFraction) {
		scrollPtr->lastFraction = scrollPtr->firstFraction;
	    } else if (last > 1.0) {
		scrollPtr->lastFraction = 1.0;
	    } else {
		scrollPtr->lastFraction = last;
	    }
	    scrollPtr->flags |= NEW_STYLE_COMMANDS;
	} else if (argc == 6) {
	    if (Tcl_GetInt(interp, argv[2], &totalUnits) != TCL_OK) {
		goto error;
	    }
	    if (totalUnits < 0) {
		totalUnits = 0;
	    }
	    if (Tcl_GetInt(interp, argv[3], &windowUnits) != TCL_OK) {
		goto error;
	    }
	    if (windowUnits < 0) {
		windowUnits = 0;
	    }
	    if (Tcl_GetInt(interp, argv[4], &firstUnit) != TCL_OK) {
		goto error;
	    }
	    if (Tcl_GetInt(interp, argv[5], &lastUnit) != TCL_OK) {
		goto error;
	    }
	    if (totalUnits > 0) {
		if (lastUnit < firstUnit) {
		    lastUnit = firstUnit;
		}
	    } else {







|
>
>


|
|
<
<













|
>
>



|
|
<
<


|
|










|
>
>


|


|


|

















|
|





|





|


|







368
369
370
371
372
373
374
375
376
377
378
379
380
381


382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402


403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
	}
	if (fraction < 0) {
	    fraction = 0;
	} else if (fraction > 1.0) {
	    fraction = 1.0;
	}
	Tcl_SetObjResult(interp, Tcl_NewDoubleObj(fraction));
	break;
    }
    case COMMAND_GET: {
	Tcl_Obj *resObjs[4];

	if (objc != 2) {
		Tcl_WrongNumArgs(interp, 1, objv, "get");


	    goto error;
	}
	if (scrollPtr->flags & NEW_STYLE_COMMANDS) {
	    resObjs[0] = Tcl_NewDoubleObj(scrollPtr->firstFraction);
	    resObjs[1] = Tcl_NewDoubleObj(scrollPtr->lastFraction);
	    Tcl_SetObjResult(interp, Tcl_NewListObj(2, resObjs));
	} else {
	    resObjs[0] = Tcl_NewIntObj(scrollPtr->totalUnits);
	    resObjs[1] = Tcl_NewIntObj(scrollPtr->windowUnits);
	    resObjs[2] = Tcl_NewIntObj(scrollPtr->firstUnit);
	    resObjs[3] = Tcl_NewIntObj(scrollPtr->lastUnit);
	    Tcl_SetObjResult(interp, Tcl_NewListObj(4, resObjs));
	}
	break;
    }
    case COMMAND_IDENTIFY: {
	int x, y;
	const char *zone = "";

	if (objc != 4) {
		Tcl_WrongNumArgs(interp, 1, objv, "identify x y");


	    goto error;
	}
	if ((Tcl_GetIntFromObj(interp, objv[2], &x) != TCL_OK)
		|| (Tcl_GetIntFromObj(interp, objv[3], &y) != TCL_OK)) {
	    goto error;
	}
	switch (TkpScrollbarPosition(scrollPtr, x, y)) {
	case TOP_ARROW:		zone = "arrow1";  break;
	case TOP_GAP:		zone = "trough1"; break;
	case SLIDER:		zone = "slider";  break;
	case BOTTOM_GAP:	zone = "trough2"; break;
	case BOTTOM_ARROW:	zone = "arrow2";  break;
	}
	Tcl_SetObjResult(interp, Tcl_NewStringObj(zone, -1));
	break;
    }
    case COMMAND_SET: {
	int totalUnits, windowUnits, firstUnit, lastUnit;

	if (objc == 4) {
	    double first, last;

	    if (Tcl_GetDoubleFromObj(interp, objv[2], &first) != TCL_OK) {
		goto error;
	    }
	    if (Tcl_GetDoubleFromObj(interp, objv[3], &last) != TCL_OK) {
		goto error;
	    }
	    if (first < 0) {
		scrollPtr->firstFraction = 0;
	    } else if (first > 1.0) {
		scrollPtr->firstFraction = 1.0;
	    } else {
		scrollPtr->firstFraction = first;
	    }
	    if (last < scrollPtr->firstFraction) {
		scrollPtr->lastFraction = scrollPtr->firstFraction;
	    } else if (last > 1.0) {
		scrollPtr->lastFraction = 1.0;
	    } else {
		scrollPtr->lastFraction = last;
	    }
	    scrollPtr->flags |= NEW_STYLE_COMMANDS;
	} else if (objc == 6) {
	    if (Tcl_GetIntFromObj(interp, objv[2], &totalUnits) != TCL_OK) {
		goto error;
	    }
	    if (totalUnits < 0) {
		totalUnits = 0;
	    }
	    if (Tcl_GetIntFromObj(interp, objv[3], &windowUnits) != TCL_OK) {
		goto error;
	    }
	    if (windowUnits < 0) {
		windowUnits = 0;
	    }
	    if (Tcl_GetIntFromObj(interp, objv[4], &firstUnit) != TCL_OK) {
		goto error;
	    }
	    if (Tcl_GetIntFromObj(interp, objv[5], &lastUnit) != TCL_OK) {
		goto error;
	    }
	    if (totalUnits > 0) {
		if (lastUnit < firstUnit) {
		    lastUnit = firstUnit;
		}
	    } else {
470
471
472
473
474
475
476
477
478
479

480
481
482
483
484
485
486
487
488
489
490
491
492
493

494
495
496
497
498
499
500
		scrollPtr->lastFraction = 1.0;
	    } else {
		scrollPtr->firstFraction = ((double) firstUnit)/totalUnits;
		scrollPtr->lastFraction = ((double) (lastUnit+1))/totalUnits;
	    }
	    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);
	    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;

    }

  done:
    Tcl_Release(scrollPtr);
    return result;

  error:







<
<
|
>
|
<
<




|
<
<
<
<
<
<
>







478
479
480
481
482
483
484


485
486
487


488
489
490
491
492






493
494
495
496
497
498
499
500
		scrollPtr->lastFraction = 1.0;
	    } else {
		scrollPtr->firstFraction = ((double) firstUnit)/totalUnits;
		scrollPtr->lastFraction = ((double) (lastUnit+1))/totalUnits;
	    }
	    scrollPtr->flags &= ~NEW_STYLE_COMMANDS;
	} else {


		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);
	break;






    }
    }

  done:
    Tcl_Release(scrollPtr);
    return result;

  error:
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543

static int
ConfigureScrollbar(
    Tcl_Interp *interp,		/* Used for error reporting. */
    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 flags)			/* Flags to pass to Tk_ConfigureWidget. */
{
    if (Tk_ConfigureWidget(interp, scrollPtr->tkwin, configSpecs,
	    argc, argv, (char *) scrollPtr, flags) != TCL_OK) {
	return TCL_ERROR;
    }

    /*
     * A few options need special processing, such as setting the background
     * from a 3-D border.
     */







|
|


|
|







524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543

static int
ConfigureScrollbar(
    Tcl_Interp *interp,		/* Used for error reporting. */
    register TkScrollbar *scrollPtr,
				/* 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. */
{
    if (Tk_ConfigureWidget(interp, scrollPtr->tkwin, configSpecs, objc,
	    (const char **)objv, (char *) scrollPtr, flags|TK_CONFIG_OBJS) != TCL_OK) {
	return TCL_ERROR;
    }

    /*
     * A few options need special processing, such as setting the background
     * from a 3-D border.
     */

Changes to generic/tkText.c.

6671
6672
6673
6674
6675
6676
6677
6678
6679
6680
6681
6682
6683
6684
6685
6686
6687
6688
6689
    if (argc < 3) {
	return TCL_ERROR;
    }

    if (Tcl_GetCommandInfo(interp, argv[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) {
	    return TCL_ERROR;
	}
	lineIndex = atoi(argv[3]) - 1;
	byteIndex = atoi(argv[4]);







<
|
<
<
<







6671
6672
6673
6674
6675
6676
6677

6678



6679
6680
6681
6682
6683
6684
6685
    if (argc < 3) {
	return TCL_ERROR;
    }

    if (Tcl_GetCommandInfo(interp, argv[1], &info) == 0) {
	return TCL_ERROR;
    }

    textPtr = info.objClientData;



    len = strlen(argv[2]);
    if (strncmp(argv[2], "byteindex", len) == 0) {
	if (argc != 5) {
	    return TCL_ERROR;
	}
	lineIndex = atoi(argv[3]) - 1;
	byteIndex = atoi(argv[4]);

Changes to generic/tkTextMark.c.

36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
static void		MarkCheckProc(TkTextSegment *segPtr,
			    TkTextLine *linePtr);
static int		MarkLayoutProc(TkText *textPtr, TkTextIndex *indexPtr,
			    TkTextSegment *segPtr, int offset, int maxX,
			    int maxChars, int noCharsYet, TkWrapMode wrapMode,
			    TkTextDispChunk *chunkPtr);
static int		MarkFindNext(Tcl_Interp *interp,
			    TkText *textPtr, const char *markName);
static int		MarkFindPrev(Tcl_Interp *interp,
			    TkText *textPtr, const char *markName);


/*
 * The following structures declare the "mark" segment types. There are
 * actually two types for marks, one with left gravity and one with right
 * gravity. They are identical except for their gravity property.
 */







|

|







36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
static void		MarkCheckProc(TkTextSegment *segPtr,
			    TkTextLine *linePtr);
static int		MarkLayoutProc(TkText *textPtr, TkTextIndex *indexPtr,
			    TkTextSegment *segPtr, int offset, int maxX,
			    int maxChars, int noCharsYet, TkWrapMode wrapMode,
			    TkTextDispChunk *chunkPtr);
static int		MarkFindNext(Tcl_Interp *interp,
			    TkText *textPtr, Tcl_Obj *markName);
static int		MarkFindPrev(Tcl_Interp *interp,
			    TkText *textPtr, Tcl_Obj *markName);


/*
 * The following structures declare the "mark" segment types. There are
 * actually two types for marks, one with left gravity and one with right
 * gravity. They are identical except for their gravity property.
 */
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
	break;
    }
    case MARK_NEXT:
	if (objc != 4) {
	    Tcl_WrongNumArgs(interp, 3, objv, "index");
	    return TCL_ERROR;
	}
	return MarkFindNext(interp, textPtr, Tcl_GetString(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]));
    case MARK_SET:
	if (objc != 5) {
	    Tcl_WrongNumArgs(interp, 3, objv, "markName index");
	    return TCL_ERROR;
	}
	if (TkTextGetObjIndex(interp, textPtr, objv[4], &index) != TCL_OK) {
	    return TCL_ERROR;







|





|







201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
	break;
    }
    case MARK_NEXT:
	if (objc != 4) {
	    Tcl_WrongNumArgs(interp, 3, objv, "index");
	    return TCL_ERROR;
	}
	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, objv[3]);
    case MARK_SET:
	if (objc != 5) {
	    Tcl_WrongNumArgs(interp, 3, objv, "markName index");
	    return TCL_ERROR;
	}
	if (TkTextGetObjIndex(interp, textPtr, objv[4], &index) != TCL_OK) {
	    return TCL_ERROR;
801
802
803
804
805
806
807
808
809
810
811
812
813

814
815
816
817
818
819
820
 *--------------------------------------------------------------
 */

static int
MarkFindNext(
    Tcl_Interp *interp,		/* For error reporting */
    TkText *textPtr,		/* The widget */
    const char *string)		/* The starting index or mark name */
{
    TkTextIndex index;
    Tcl_HashEntry *hPtr;
    register TkTextSegment *segPtr;
    int offset;


    if (!strcmp(string, "insert")) {
	segPtr = textPtr->insertMarkPtr;
	TkTextMarkSegToIndex(textPtr, segPtr, &index);
	segPtr = segPtr->nextPtr;
    } else if (!strcmp(string, "current")) {
	segPtr = textPtr->currentMarkPtr;







|





>







801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
 *--------------------------------------------------------------
 */

static int
MarkFindNext(
    Tcl_Interp *interp,		/* For error reporting */
    TkText *textPtr,		/* The widget */
    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;
	TkTextMarkSegToIndex(textPtr, segPtr, &index);
	segPtr = segPtr->nextPtr;
    } else if (!strcmp(string, "current")) {
	segPtr = textPtr->currentMarkPtr;
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
	    segPtr = segPtr->nextPtr;
	} else {
	    /*
	     * For non-mark name indices we want to return any marks that are
	     * right at the index.
	     */

	    if (TkTextGetIndex(interp, textPtr, string, &index) != TCL_OK) {
		return TCL_ERROR;
	    }
	    for (offset = 0, segPtr = index.linePtr->segPtr;
		    segPtr != NULL && offset < index.byteIndex;
		    offset += segPtr->size, segPtr = segPtr->nextPtr) {
		/* Empty loop body */ ;
	    }







|







835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
	    segPtr = segPtr->nextPtr;
	} else {
	    /*
	     * For non-mark name indices we want to return any marks that are
	     * right at the index.
	     */

	    if (TkTextGetObjIndex(interp, textPtr, obj, &index) != TCL_OK) {
		return TCL_ERROR;
	    }
	    for (offset = 0, segPtr = index.linePtr->segPtr;
		    segPtr != NULL && offset < index.byteIndex;
		    offset += segPtr->size, segPtr = segPtr->nextPtr) {
		/* Empty loop body */ ;
	    }
891
892
893
894
895
896
897
898
899
900
901
902
903

904
905
906
907
908
909
910
 *--------------------------------------------------------------
 */

static int
MarkFindPrev(
    Tcl_Interp *interp,		/* For error reporting */
    TkText *textPtr,		/* The widget */
    const char *string)		/* The starting index or mark name */
{
    TkTextIndex index;
    Tcl_HashEntry *hPtr;
    register TkTextSegment *segPtr, *seg2Ptr, *prevPtr;
    int offset;


    if (!strcmp(string, "insert")) {
	segPtr = textPtr->insertMarkPtr;
	TkTextMarkSegToIndex(textPtr, segPtr, &index);
    } else if (!strcmp(string, "current")) {
	segPtr = textPtr->currentMarkPtr;
	TkTextMarkSegToIndex(textPtr, segPtr, &index);







|





>







892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
 *--------------------------------------------------------------
 */

static int
MarkFindPrev(
    Tcl_Interp *interp,		/* For error reporting */
    TkText *textPtr,		/* The widget */
    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;
	TkTextMarkSegToIndex(textPtr, segPtr, &index);
    } else if (!strcmp(string, "current")) {
	segPtr = textPtr->currentMarkPtr;
	TkTextMarkSegToIndex(textPtr, segPtr, &index);
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
	    TkTextMarkSegToIndex(textPtr, segPtr, &index);
	} else {
	    /*
	     * For non-mark name indices we do not return any marks that are
	     * right at the index.
	     */

	    if (TkTextGetIndex(interp, textPtr, string, &index) != TCL_OK) {
		return TCL_ERROR;
	    }
	    for (offset = 0, segPtr = index.linePtr->segPtr;
		    segPtr != NULL && offset < index.byteIndex;
		    offset += segPtr->size, segPtr = segPtr->nextPtr) {
		/* Empty loop body */
	    }







|







923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
	    TkTextMarkSegToIndex(textPtr, segPtr, &index);
	} else {
	    /*
	     * For non-mark name indices we do not return any marks that are
	     * right at the index.
	     */

	    if (TkTextGetObjIndex(interp, textPtr, obj, &index) != TCL_OK) {
		return TCL_ERROR;
	    }
	    for (offset = 0, segPtr = index.linePtr->segPtr;
		    segPtr != NULL && offset < index.byteIndex;
		    offset += segPtr->size, segPtr = segPtr->nextPtr) {
		/* Empty loop body */
	    }

Changes to generic/tkWindow.c.

93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
/*
 * The following structure defines all of the commands supported by Tk, and
 * the C functions that execute them.
 */

#define ISSAFE 1
#define PASSMAINWINDOW 2
#define NOOBJPROC 4
#define WINMACONLY 8
#define USEINITPROC 16

typedef int (TkInitProc)(Tcl_Interp *interp, ClientData clientData);
typedef struct {
    const char *name;		/* Name of command. */
    Tcl_ObjCmdProc *objProc;	/* Command's object- (or string-) based
				 * function, or initProc. */
    int flags;







<
|
|







93
94
95
96
97
98
99

100
101
102
103
104
105
106
107
108
/*
 * The following structure defines all of the commands supported by Tk, and
 * the C functions that execute them.
 */

#define ISSAFE 1
#define PASSMAINWINDOW 2

#define WINMACONLY 4
#define USEINITPROC 8

typedef int (TkInitProc)(Tcl_Interp *interp, ClientData clientData);
typedef struct {
    const char *name;		/* Name of command. */
    Tcl_ObjCmdProc *objProc;	/* Command's object- (or string-) based
				 * function, or initProc. */
    int flags;
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
    {"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},
    {"spinbox",		Tk_SpinboxObjCmd,	ISSAFE},
    {"text",		Tk_TextObjCmd,		PASSMAINWINDOW|ISSAFE},
    {"toplevel",	Tk_ToplevelObjCmd,	0},

    /*
     * Classic widget class commands.
     */







<
|







150
151
152
153
154
155
156

157
158
159
160
161
162
163
164
    {"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",	Tk_ScrollbarObjCmd, PASSMAINWINDOW|ISSAFE},
    {"spinbox",		Tk_SpinboxObjCmd,	ISSAFE},
    {"text",		Tk_TextObjCmd,		PASSMAINWINDOW|ISSAFE},
    {"toplevel",	Tk_ToplevelObjCmd,	0},

    /*
     * Classic widget class commands.
     */
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
    {"::tk::labelframe",Tk_LabelframeObjCmd,	ISSAFE},
    {"::tk::listbox",	Tk_ListboxObjCmd,	ISSAFE},
    {"::tk::menubutton",Tk_MenubuttonObjCmd,	ISSAFE},
    {"::tk::message",	Tk_MessageObjCmd,	ISSAFE},
    {"::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::spinbox",	Tk_SpinboxObjCmd,	ISSAFE},
    {"::tk::text",	Tk_TextObjCmd,		PASSMAINWINDOW|ISSAFE},
    {"::tk::toplevel",	Tk_ToplevelObjCmd,	0},

    /*
     * Standard dialog support. Note that the Unix/X11 platform implements
     * these commands differently (via the script library).







<
|







172
173
174
175
176
177
178

179
180
181
182
183
184
185
186
    {"::tk::labelframe",Tk_LabelframeObjCmd,	ISSAFE},
    {"::tk::listbox",	Tk_ListboxObjCmd,	ISSAFE},
    {"::tk::menubutton",Tk_MenubuttonObjCmd,	ISSAFE},
    {"::tk::message",	Tk_MessageObjCmd,	ISSAFE},
    {"::tk::panedwindow",Tk_PanedWindowObjCmd,	ISSAFE},
    {"::tk::radiobutton",Tk_RadiobuttonObjCmd,	ISSAFE},
    {"::tk::scale",	Tk_ScaleObjCmd,		ISSAFE},

    {"::tk::scrollbar",	Tk_ScrollbarObjCmd, PASSMAINWINDOW|ISSAFE},
    {"::tk::spinbox",	Tk_SpinboxObjCmd,	ISSAFE},
    {"::tk::text",	Tk_TextObjCmd,		PASSMAINWINDOW|ISSAFE},
    {"::tk::toplevel",	Tk_ToplevelObjCmd,	0},

    /*
     * Standard dialog support. Note that the Unix/X11 platform implements
     * these commands differently (via the script library).
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
	if (cmdPtr->flags & PASSMAINWINDOW) {
	    clientData = tkwin;
	} else {
	    clientData = NULL;
	}
	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);
	}
	if (isSafe && !(cmdPtr->flags & ISSAFE)) {
	    Tcl_HideCommand(interp, cmdPtr->name, cmdPtr->name);
	}







<
<
<







969
970
971
972
973
974
975



976
977
978
979
980
981
982
	if (cmdPtr->flags & PASSMAINWINDOW) {
	    clientData = tkwin;
	} else {
	    clientData = NULL;
	}
	if (cmdPtr->flags & USEINITPROC) {
	    ((TkInitProc *) cmdPtr->objProc)(interp, clientData);



	} else {
	    Tcl_CreateObjCommand(interp, cmdPtr->name, cmdPtr->objProc,
		    clientData, NULL);
	}
	if (isSafe && !(cmdPtr->flags & ISSAFE)) {
	    Tcl_HideCommand(interp, cmdPtr->name, cmdPtr->name);
	}
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
	     * being deleted. If it *is*, the interpreter cleanup will do all
	     * the needed work.
	     */

	    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_CreateCommand(winPtr->mainPtr->interp, "send",
			TkDeadAppCmd, NULL, NULL);
		Tcl_UnlinkVar(winPtr->mainPtr->interp, "tk_strictMotif");
		Tcl_UnlinkVar(winPtr->mainPtr->interp,
			"::tk::AlwaysShowSelection");
	    }

	    Tcl_DeleteHashTable(&winPtr->mainPtr->busyTable);
	    Tcl_DeleteHashTable(&winPtr->mainPtr->nameTable);







|
|

|
|







1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
	     * being deleted. If it *is*, the interpreter cleanup will do all
	     * the needed work.
	     */

	    if ((winPtr->mainPtr->interp != NULL) &&
		    !Tcl_InterpDeleted(winPtr->mainPtr->interp)) {
		for (cmdPtr = commands; cmdPtr->name != NULL; cmdPtr++) {
		    Tcl_CreateObjCommand(winPtr->mainPtr->interp, cmdPtr->name,
			    TkDeadAppObjCmd, 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");
	    }

	    Tcl_DeleteHashTable(&winPtr->mainPtr->busyTable);
	    Tcl_DeleteHashTable(&winPtr->mainPtr->nameTable);

Changes to tests/scrollbar.test.

401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
    list [catch {.s set 1 2 3 4 5} msg] $msg
} {1 {wrong # args: should be ".s set firstFraction lastFraction" or ".s set totalUnits windowUnits firstUnit lastUnit"}}
test scrollbar-3.73 {ScrollbarWidgetCmd procedure} {
    list [catch {.s bogus} msg] $msg
} {1 {bad option "bogus": must be activate, cget, configure, delta, fraction, get, identify, or set}}
test scrollbar-3.74 {ScrollbarWidgetCmd procedure} {
    list [catch {.s c} msg] $msg
} {1 {bad option "c": must be activate, cget, configure, delta, fraction, get, identify, or set}}

test scrollbar-4.1 {ScrollbarEventProc procedure} {
    catch {destroy .s1}
    scrollbar .s1 -bg #543210
    rename .s1 .s2
    set x {}
    lappend x [winfo exists .s1]







|







401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
    list [catch {.s set 1 2 3 4 5} msg] $msg
} {1 {wrong # args: should be ".s set firstFraction lastFraction" or ".s set totalUnits windowUnits firstUnit lastUnit"}}
test scrollbar-3.73 {ScrollbarWidgetCmd procedure} {
    list [catch {.s bogus} msg] $msg
} {1 {bad option "bogus": must be activate, cget, configure, delta, fraction, get, identify, or set}}
test scrollbar-3.74 {ScrollbarWidgetCmd procedure} {
    list [catch {.s c} msg] $msg
} {1 {ambiguous option "c": must be activate, cget, configure, delta, fraction, get, identify, or set}}

test scrollbar-4.1 {ScrollbarEventProc procedure} {
    catch {destroy .s1}
    scrollbar .s1 -bg #543210
    rename .s1 .s2
    set x {}
    lappend x [winfo exists .s1]