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 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 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
|
/* tagset.c,v 1.1 2006/09/21 18:22:33 jenglish Exp
*
* Tile widget set: tag tables. Half-baked, work in progress.
*
* Copyright (C) 2005, Joe English. Freely redistributable.
*/
#include <string.h> /* for memset() */
#include <tcl.h>
#include <tk.h>
#include "tkTheme.h"
#include "widget.h"
/*------------------------------------------------------------------------
* +++ Internal data structures.
*/
struct TtkTag {
Tcl_Obj **tagRecord; /* ... hrmph. */
};
struct TtkTagTable {
Tk_OptionTable tagOptionTable; /* ... */
int tagRecordSize; /* size of tag record */
Tcl_HashTable tags; /* defined tags */
};
/*------------------------------------------------------------------------
* +++ Tags.
*/
static Ttk_Tag NewTag(Ttk_TagTable tagTable)
{
Ttk_Tag tag = (Ttk_Tag)ckalloc(sizeof(*tag));
tag->tagRecord = (Tcl_Obj **)ckalloc(tagTable->tagRecordSize);
memset(tag->tagRecord, 0, tagTable->tagRecordSize);
return tag;
}
static void DeleteTag(Ttk_Tag tag, int nOptions)
{
int i;
for (i = 0; i < nOptions; ++i) {
if (tag->tagRecord[i]) {
Tcl_DecrRefCount(tag->tagRecord[i]);
}
}
ckfree((void*)tag->tagRecord);
ckfree((void*)tag);
}
Tcl_Obj **Ttk_TagRecord(Ttk_Tag tag)
{
return tag->tagRecord;
}
/*------------------------------------------------------------------------
* +++ Tag tables.
*/
Ttk_TagTable Ttk_CreateTagTable(
Tk_OptionTable tagOptionTable, int tagRecordSize)
{
Ttk_TagTable tagTable = (Ttk_TagTable)ckalloc(sizeof(*tagTable));
tagTable->tagOptionTable = tagOptionTable;
tagTable->tagRecordSize = tagRecordSize;
Tcl_InitHashTable(&tagTable->tags, TCL_STRING_KEYS);
return tagTable;
}
void Ttk_DeleteTagTable(Ttk_TagTable tagTable)
{
Tcl_HashSearch search;
Tcl_HashEntry *entryPtr;
int nOptions = tagTable->tagRecordSize / sizeof(Tcl_Obj *);
entryPtr = Tcl_FirstHashEntry(&tagTable->tags, &search);
while (entryPtr != NULL) {
DeleteTag(Tcl_GetHashValue(entryPtr), nOptions);
entryPtr = Tcl_NextHashEntry(&search);
}
Tcl_DeleteHashTable(&tagTable->tags);
ckfree((void*)tagTable);
}
Ttk_Tag Ttk_GetTag(Ttk_TagTable tagTable, const char *tagName)
{
int isNew = 0;
Tcl_HashEntry *entryPtr = Tcl_CreateHashEntry(
&tagTable->tags, tagName, &isNew);
if (isNew) {
Tcl_SetHashValue(entryPtr, NewTag(tagTable));
}
return Tcl_GetHashValue(entryPtr);
}
Ttk_Tag Ttk_GetTagFromObj(Ttk_TagTable tagTable, Tcl_Obj *objPtr)
{
return Ttk_GetTag(tagTable, Tcl_GetString(objPtr));
}
/* Ttk_GetTagListFromObj --
* Extract an array of pointers to Ttk_Tags from a Tcl_Obj.
* (suitable for passing to Tk_BindEvent).
*
* Result must be passed to Ttk_FreeTagList().
*/
extern int Ttk_GetTagListFromObj(
Tcl_Interp *interp,
Ttk_TagTable tagTable,
Tcl_Obj *objPtr,
int *nTags_rtn,
void **taglist_rtn)
{
Tcl_Obj **objv;
int i, objc;
void **tags;
*taglist_rtn = NULL; *nTags_rtn = 0;
if (objPtr == NULL) {
return TCL_OK;
}
if (Tcl_ListObjGetElements(interp, objPtr, &objc, &objv) != TCL_OK) {
return TCL_ERROR;
}
tags = (void**)ckalloc((objc+1) * sizeof(void*));
for (i=0; i<objc; ++i) {
tags[i] = Ttk_GetTagFromObj(tagTable, objv[i]);
}
tags[i] = NULL;
*taglist_rtn = tags;
*nTags_rtn = objc;
return TCL_OK;
}
void Ttk_FreeTagList(void **taglist)
{
if (taglist)
ckfree((ClientData)taglist);
}
|