Tk Source Code

Check-in [95390ea2]
Login
EuroTcl/OpenACS 11 - 12 JULY 2024, VIENNA

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

Overview
Comment:ttk state implementation improvements
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | core-8-6-branch
Files: files | file ages | folders
SHA3-256: 95390ea209c045ed3261017b4c602cda6aec0ce8f7c4648784827a79c95a94c9
User & Date: jan.nijtmans 2024-05-19 17:09:12
Context
2024-05-24
16:53
Make compilable with strict C99 compiler (missing declaration for XUnionRegion()) check-in: f2f2900e user: jan.nijtmans tags: core-8-6-branch
15:59
Another attempt, adding "csaba magic" for [tk scaling] initialization Closed-Leaf check-in: d1221183 user: jan.nijtmans tags: bug-8162e9b7a9-with-csaba-magic
2024-05-23
17:18
Merge core-8-6-branch check-in: fb4137fd user: culler tags: bug-22349fc78a-v2
2024-05-19
17:20
ttk state implementation improvements. This gives 32 possible flags in stead of only 16 check-in: 7a3149d6 user: jan.nijtmans tags: core-8-branch
17:09
ttk state implementation improvements check-in: 95390ea2 user: jan.nijtmans tags: core-8-6-branch
2024-05-18
20:34
Document user1-user3 ttk widget states check-in: e76f222a user: jan.nijtmans tags: core-8-6-branch
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to generic/ttk/ttkState.c.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16



17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57

58
59
60
61
62
63
64
/*
 * Tk widget state utilities.
 *
 * Copyright (c) 2003 Joe English.  Freely redistributable.
 *
 */

#include "tkInt.h"
#include "ttkTheme.h"

/*
 * Table of state names.  Must be kept in sync with TTK_STATE_*
 * #defines in ttkTheme.h.
 */
static const char *const stateNames[] =
{



    "active",		/* Mouse cursor is over widget or element */
    "disabled",		/* Widget is disabled */
    "focus",		/* Widget has keyboard focus */
    "pressed",		/* Pressed or "armed" */
    "selected",		/* "on", "true", "current", etc. */
    "background",	/* Top-level window lost focus (Mac,Win "inactive") */
    "alternate",	/* Widget-specific alternate display style */
    "invalid",		/* Bad value */
    "readonly",		/* Editing/modification disabled */
    "hover",		/* Mouse cursor is over widget */
    "user6",		/* User-definable state */
    "user5",		/* User-definable state */
    "user4",		/* User-definable state */
    "user3",		/* User-definable state */
    "user2",		/* User-definable state */
    "user1",		/* User-definable state */
    NULL

};

/*------------------------------------------------------------------------
 * +++ StateSpec object type:
 *
 * The string representation consists of a list of state names,
 * each optionally prefixed by an exclamation point (!).
 *
 * The internal representation uses the upper half of the longValue
 * to store the on bits and the lower half to store the off bits.
 * If we ever get more than 16 states, this will need to be reconsidered...
 */

static int  StateSpecSetFromAny(Tcl_Interp *interp, Tcl_Obj *obj);
/* static void StateSpecFreeIntRep(Tcl_Obj *); */
#define StateSpecFreeIntRep 0		/* not needed */
static void StateSpecDupIntRep(Tcl_Obj *, Tcl_Obj *);
static void StateSpecUpdateString(Tcl_Obj *);

static
struct Tcl_ObjType StateSpecObjType =
{
    "StateSpec",
    StateSpecFreeIntRep,

    StateSpecDupIntRep,
    StateSpecUpdateString,
    StateSpecSetFromAny
};

static void StateSpecDupIntRep(Tcl_Obj *srcPtr, Tcl_Obj *copyPtr)
{











|
<

|
<
>
>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<
>














<
<







<
>







1
2
3
4
5
6
7
8
9
10
11
12

13
14

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

34
35
36
37
38
39
40
41
42
43
44
45
46
47
48


49
50
51
52
53
54
55

56
57
58
59
60
61
62
63
/*
 * Tk widget state utilities.
 *
 * Copyright (c) 2003 Joe English.  Freely redistributable.
 *
 */

#include "tkInt.h"
#include "ttkTheme.h"

/*
 * Table of state names.

 */
static const struct {

    char name[12];
    int value;
} stateNames[] = {
    {"active", TTK_STATE_ACTIVE},		/* Mouse cursor is over widget or element */
    {"disabled", TTK_STATE_DISABLED},		/* Widget is disabled */
    {"focus", TTK_STATE_FOCUS},		/* Widget has keyboard focus */
    {"pressed", TTK_STATE_PRESSED},		/* Pressed or "armed" */
    {"selected", TTK_STATE_SELECTED},		/* "on", "true", "current", etc. */
    {"background", TTK_STATE_BACKGROUND},	/* Top-level window lost focus (Mac,Win "inactive") */
    {"alternate", TTK_STATE_ALTERNATE},	/* Widget-specific alternate display style */
    {"invalid", TTK_STATE_INVALID},		/* Bad value */
    {"readonly", TTK_STATE_READONLY},		/* Editing/modification disabled */
    {"hover", TTK_STATE_HOVER},		/* Mouse cursor is over widget */
    {"user6", TTK_STATE_USER6},		/* User-definable state */
    {"user5", TTK_STATE_USER5},		/* User-definable state */
    {"user4", TTK_STATE_USER4},		/* User-definable state */
    {"user3", TTK_STATE_USER3},		/* User-definable state */
    {"user2", TTK_STATE_USER2},		/* User-definable state */
    {"user1", TTK_STATE_USER1},		/* User-definable state */

    {"", 0}
};

/*------------------------------------------------------------------------
 * +++ StateSpec object type:
 *
 * The string representation consists of a list of state names,
 * each optionally prefixed by an exclamation point (!).
 *
 * The internal representation uses the upper half of the longValue
 * to store the on bits and the lower half to store the off bits.
 * If we ever get more than 16 states, this will need to be reconsidered...
 */

static int  StateSpecSetFromAny(Tcl_Interp *interp, Tcl_Obj *obj);


static void StateSpecDupIntRep(Tcl_Obj *, Tcl_Obj *);
static void StateSpecUpdateString(Tcl_Obj *);

static
struct Tcl_ObjType StateSpecObjType =
{
    "StateSpec",

    0,
    StateSpecDupIntRep,
    StateSpecUpdateString,
    StateSpecSetFromAny
};

static void StateSpecDupIntRep(Tcl_Obj *srcPtr, Tcl_Obj *copyPtr)
{
85
86
87
88
89
90
91
92
93
94
95
96
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
	if (*stateName == '!') {
	    ++stateName;
	    on = 0;
	} else {
	    on = 1;
	}

	for (j = 0; stateNames[j] != 0; ++j) {
	    if (strcmp(stateName, stateNames[j]) == 0)
		break;
	}

    	if (stateNames[j] == 0) {
	    if (interp) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"Invalid state name %s", stateName));
		Tcl_SetErrorCode(interp, "TTK", "VALUE", "STATE", NULL);
	    }
	    return TCL_ERROR;
	}

	if (on) {
	    onbits |= (1<<j);
	} else {
	    offbits |= (1<<j);
	}
    }

    /* Invalidate old intrep:
     */
    if (objPtr->typePtr && objPtr->typePtr->freeIntRepProc) {
	objPtr->typePtr->freeIntRepProc(objPtr);
    }

    objPtr->typePtr = &StateSpecObjType;
    objPtr->internalRep.longValue = (onbits << 16) | offbits;

    return TCL_OK;
}

static void StateSpecUpdateString(Tcl_Obj *objPtr)
{
    unsigned int onbits = (objPtr->internalRep.longValue & 0xFFFF0000) >> 16;
    unsigned int offbits = objPtr->internalRep.longValue & 0x0000FFFF;
    unsigned int mask = onbits | offbits;
    Tcl_DString result;
    int i;
    int len;

    Tcl_DStringInit(&result);

    for (i=0; stateNames[i] != NULL; ++i) {
	if (mask & (1<<i)) {
	    if (offbits & (1<<i))
		Tcl_DStringAppend(&result, "!", 1);

	    Tcl_DStringAppend(&result, stateNames[i], -1);
	    Tcl_DStringAppend(&result, " ", 1);
	}
    }

    len = Tcl_DStringLength(&result);
    if (len) {
	/* 'len' includes extra trailing ' ' */
	objPtr->bytes = ckalloc(len);
	objPtr->length = len-1;
	strncpy(objPtr->bytes, Tcl_DStringValue(&result), len-1);
	objPtr->bytes[len-1] = '\0';
    } else {
	/* empty string */
	objPtr->length = 0;
	objPtr->bytes = ckalloc(1);
	*objPtr->bytes = '\0';
    }

    Tcl_DStringFree(&result);
}

Tcl_Obj *Ttk_NewStateSpecObj(unsigned int onbits, unsigned int offbits)







|
|



|









|

|

















|








|
|
|

>
|







|






|







84
85
86
87
88
89
90
91
92
93
94
95
96
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
	if (*stateName == '!') {
	    ++stateName;
	    on = 0;
	} else {
	    on = 1;
	}

	for (j = 0; stateNames[j].value; ++j) {
	    if (strcmp(stateName, stateNames[j].name) == 0)
		break;
	}

    	if (stateNames[j].value == 0) {
	    if (interp) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"Invalid state name %s", stateName));
		Tcl_SetErrorCode(interp, "TTK", "VALUE", "STATE", NULL);
	    }
	    return TCL_ERROR;
	}

	if (on) {
	    onbits |= stateNames[j].value;
	} else {
	    offbits |= stateNames[j].value;
	}
    }

    /* Invalidate old intrep:
     */
    if (objPtr->typePtr && objPtr->typePtr->freeIntRepProc) {
	objPtr->typePtr->freeIntRepProc(objPtr);
    }

    objPtr->typePtr = &StateSpecObjType;
    objPtr->internalRep.longValue = (onbits << 16) | offbits;

    return TCL_OK;
}

static void StateSpecUpdateString(Tcl_Obj *objPtr)
{
    unsigned int onbits = objPtr->internalRep.longValue >> 16;
    unsigned int offbits = objPtr->internalRep.longValue & 0x0000FFFF;
    unsigned int mask = onbits | offbits;
    Tcl_DString result;
    int i;
    int len;

    Tcl_DStringInit(&result);

    for (i=0; stateNames[i].value; ++i) {
	if (mask & stateNames[i].value) {
	    if (offbits & stateNames[i].value) {
		Tcl_DStringAppend(&result, "!", 1);
	    }
	    Tcl_DStringAppend(&result, stateNames[i].name, -1);
	    Tcl_DStringAppend(&result, " ", 1);
	}
    }

    len = Tcl_DStringLength(&result);
    if (len) {
	/* 'len' includes extra trailing ' ' */
	objPtr->bytes = (char *)ckalloc(len);
	objPtr->length = len-1;
	strncpy(objPtr->bytes, Tcl_DStringValue(&result), len-1);
	objPtr->bytes[len-1] = '\0';
    } else {
	/* empty string */
	objPtr->length = 0;
	objPtr->bytes = (char *)ckalloc(1);
	*objPtr->bytes = '\0';
    }

    Tcl_DStringFree(&result);
}

Tcl_Obj *Ttk_NewStateSpecObj(unsigned int onbits, unsigned int offbits)
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
{
    if (objPtr->typePtr != &StateSpecObjType) {
	int status = StateSpecSetFromAny(interp, objPtr);
	if (status != TCL_OK)
	    return status;
    }

    spec->onbits = (objPtr->internalRep.longValue & 0xFFFF0000) >> 16;
    spec->offbits = objPtr->internalRep.longValue & 0x0000FFFF;
    return TCL_OK;
}


/*
 * Tk_StateMapLookup --
 *
 * 	A state map is a paired list of StateSpec / value pairs.
 *	Returns the value corresponding to the first matching state
 *	specification, or NULL if not found or an error occurs.
 */
Tcl_Obj *Ttk_StateMapLookup(
    Tcl_Interp *interp,		/* Where to leave error messages; may be NULL */
    Ttk_StateMap map,		/* State map */
    Ttk_State state)    	/* State to look up */
{
    Tcl_Obj **specs;
    int nSpecs;
    int j, status;

    status = Tcl_ListObjGetElements(interp, map, &nSpecs, &specs);
    if (status != TCL_OK)
	return NULL;

    for (j = 0; j < nSpecs; j += 2) {
	Ttk_StateSpec spec;







|


















|
|







177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
{
    if (objPtr->typePtr != &StateSpecObjType) {
	int status = StateSpecSetFromAny(interp, objPtr);
	if (status != TCL_OK)
	    return status;
    }

    spec->onbits = objPtr->internalRep.longValue >> 16;
    spec->offbits = objPtr->internalRep.longValue & 0x0000FFFF;
    return TCL_OK;
}


/*
 * Tk_StateMapLookup --
 *
 * 	A state map is a paired list of StateSpec / value pairs.
 *	Returns the value corresponding to the first matching state
 *	specification, or NULL if not found or an error occurs.
 */
Tcl_Obj *Ttk_StateMapLookup(
    Tcl_Interp *interp,		/* Where to leave error messages; may be NULL */
    Ttk_StateMap map,		/* State map */
    Ttk_State state)    	/* State to look up */
{
    Tcl_Obj **specs;
    int j, nSpecs;
    int status;

    status = Tcl_ListObjGetElements(interp, map, &nSpecs, &specs);
    if (status != TCL_OK)
	return NULL;

    for (j = 0; j < nSpecs; j += 2) {
	Ttk_StateSpec spec;
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
 * 	this basically just checks for errors.
 */
Ttk_StateMap Ttk_GetStateMapFromObj(
    Tcl_Interp *interp,		/* Where to leave error messages; may be NULL */
    Tcl_Obj *mapObj)		/* State map */
{
    Tcl_Obj **specs;
    int nSpecs;
    int j, status;

    status = Tcl_ListObjGetElements(interp, mapObj, &nSpecs, &specs);
    if (status != TCL_OK)
	return NULL;

    if (nSpecs % 2 != 0) {
	if (interp) {







|
|







228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
 * 	this basically just checks for errors.
 */
Ttk_StateMap Ttk_GetStateMapFromObj(
    Tcl_Interp *interp,		/* Where to leave error messages; may be NULL */
    Tcl_Obj *mapObj)		/* State map */
{
    Tcl_Obj **specs;
    int j, nSpecs;
    int status;

    status = Tcl_ListObjGetElements(interp, mapObj, &nSpecs, &specs);
    if (status != TCL_OK)
	return NULL;

    if (nSpecs % 2 != 0) {
	if (interp) {
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
    return mapObj;
}

/*
 * Ttk_StateTableLooup --
 * 	Look up an index from a statically allocated state table.
 */
int Ttk_StateTableLookup(Ttk_StateTable *map, unsigned int state)
{
    while ((state & map->onBits) != map->onBits
	    || (~state & map->offBits) != map->offBits)
    {
	++map;
    }
    return map->index;
}

/*EOF*/







|










257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
    return mapObj;
}

/*
 * Ttk_StateTableLooup --
 * 	Look up an index from a statically allocated state table.
 */
int Ttk_StateTableLookup(Ttk_StateTable *map, Ttk_State state)
{
    while ((state & map->onBits) != map->onBits
	    || (~state & map->offBits) != map->offBits)
    {
	++map;
    }
    return map->index;
}

/*EOF*/