From 49e59ab367c7ce7f6b5bdc01ed000745345bd5fe Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 10 Sep 2001 03:56:00 +0000 Subject: [PATCH] more code for proplist handling (almost finished) --- WINGs/WINGs/WUtil.h | 60 +++- WINGs/error.c | 10 +- WINGs/hashtable.c | 43 ++- WINGs/proplist.c | 789 ++++++++++++++++++++++++++++++++++++++++---- configure.ac | 2 +- configure.in | 10 +- src/screen.h | 5 - src/session.c | 4 +- wrlib/jpeg.c | 2 + 9 files changed, 823 insertions(+), 102 deletions(-) diff --git a/WINGs/WINGs/WUtil.h b/WINGs/WINGs/WUtil.h index 0e6ec4b3..98c6fcf7 100644 --- a/WINGs/WINGs/WUtil.h +++ b/WINGs/WINGs/WUtil.h @@ -336,6 +336,17 @@ unsigned WMCountHashTable(WMHashTable *table); void* WMHashGet(WMHashTable *table, const void *key); +/* Returns True if there is a value associated with in the table, in + * which case and will contain the item's internal key + * address and the item's value respectively. + * If there is no value associated with it will return False and in + * this case and will be undefined. + * Use this when you need to perform your own custom retain/release mechanism + * which requires access to the keys too. + */ +Bool WMHashGetItemAndKey(WMHashTable *table, const void *key, + void **retItem, void **retKey); + /* put data in table, replacing already existing data and returning * the old value */ void* WMHashInsert(WMHashTable *table, const void *key, const void *data); @@ -680,17 +691,6 @@ WMTreeNode* WMFindInTree(WMTreeNode *aTree, WMMatchDataProc *match, void *cdata) #define WMGetFirstInTree(aTree, cdata) WMFindInTree(atree, NULL, cdata) -/*--------------------------------------------------------------------------*/ - -/* Dictionaries */ -/* -WMDictionary* WMCreateDictionaryFromElements(void *key, void *value, ...); - -#define WMGetDictionaryEntryForKey(dict, key) WMHashGet(dict, key) - -WMArray* WMGetAllDictionaryKeys(WMDictionary *dPtr); -*/ - /*--------------------------------------------------------------------------*/ @@ -758,6 +758,19 @@ WMPropList* WMCreatePropListArrayFromElements(WMPropList *elem, ...); WMPropList* WMCreatePropListDictionaryFromEntries(WMPropList *key, WMPropList *value, ...); +void WMInsertPropListArrayElement(WMPropList *plist, WMPropList *item, int index); + +void WMAppendPropListArrayElement(WMPropList *plist, WMPropList *item); + +void WMRemovePropListArrayElement(WMPropList *plist, int index); + +void WMInsertPropListDictionaryEntry(WMPropList *plist, WMPropList *key, + WMPropList *value); + +void WMRemovePropListDictionaryEntry(WMPropList *plist, WMPropList *key); + +WMPropList* WMMergePropListDictionaries(WMPropList *dest, WMPropList *source); + WMPropList* WMRetainPropList(WMPropList *plist); void WMReleasePropList(WMPropList *plist); @@ -774,8 +787,31 @@ Bool WMPropListIsSimple(WMPropList *plist); Bool WMPropListIsCompound(WMPropList *plist); -Bool WMArePropListsEqual(WMPropList *plist, WMPropList *other); +Bool WMIsPropListEqualToPropList(WMPropList *plist, WMPropList *other); +int WMGetPropListNumberOfElements(WMPropList *plist); + +char* WMGetPropListString(WMPropList *plist); + +WMData* WMGetPropListData(WMPropList *plist); + +const unsigned char* WMGetPropListDataBytes(WMPropList *plist); + +int WMGetPropListDataLength(WMPropList *plist); + +WMPropList* WMGetPropListArrayElement(WMPropList *plist, int index); + +WMPropList* WMGetPropListDictionaryEntry(WMPropList *plist, WMPropList *key); + +WMPropList* WMGetPropListAllDictionaryKeys(WMPropList *plist); + +char* WMGetPropListDescription(WMPropList *plist, Bool indented); + +Bool WMSavePropListToFile(WMPropList *plist, char *path, Bool atomically); + +WMPropList* WMShallowCopyPropList(WMPropList *plist); + +WMPropList* WMDeepCopyPropList(WMPropList *plist); /*......................................................................*/ diff --git a/WINGs/error.c b/WINGs/error.c index b02e3614..cd07fca4 100644 --- a/WINGs/error.c +++ b/WINGs/error.c @@ -81,7 +81,7 @@ wmessage(const char *msg, ...) vsnprintf(buf, MAXLINE-3, msg, args); strcat(buf,"\n"); fflush(stdout); - fputs(_WINGS_progname, stderr); + fputs(_WINGS_progname ? _WINGS_progname : "WINGs", stderr); fputs(": ",stderr); fputs(buf, stderr); fflush(stdout); @@ -108,7 +108,7 @@ wwarning(const char *msg, ...) vsnprintf(buf, MAXLINE-3, msg, args); strcat(buf,"\n"); fflush(stdout); - fputs(_WINGS_progname, stderr); + fputs(_WINGS_progname ? _WINGS_progname : "WINGs", stderr); fputs(_(" warning: "),stderr); fputs(buf, stderr); fflush(stdout); @@ -135,7 +135,7 @@ wfatal(const char *msg, ...) vsnprintf(buf, MAXLINE-3, msg, args); strcat(buf,"\n"); fflush(stdout); - fputs(_WINGS_progname, stderr); + fputs(_WINGS_progname ? _WINGS_progname : "WINGs", stderr); fputs(_(" fatal error: "),stderr); fputs(buf, stderr); fflush(stdout); @@ -161,7 +161,7 @@ wsyserror(const char *msg, ...) va_start(args, msg); vsnprintf(buf, MAXLINE-3, msg, args); fflush(stdout); - fputs(_WINGS_progname, stderr); + fputs(_WINGS_progname ? _WINGS_progname : "WINGs", stderr); fputs(_(" error: "), stderr); fputs(buf, stderr); fputs(": ", stderr); @@ -190,7 +190,7 @@ wsyserrorwithcode(int error, const char *msg, ...) va_start(args, msg); vsnprintf(buf, MAXLINE-3, msg, args); fflush(stdout); - fputs(_WINGS_progname, stderr); + fputs(_WINGS_progname ? _WINGS_progname : "WINGs", stderr); fputs(_(" error: "), stderr); fputs(buf, stderr); fputs(": ", stderr); diff --git a/WINGs/hashtable.c b/WINGs/hashtable.c index 2c67ebdb..964a0946 100644 --- a/WINGs/hashtable.c +++ b/WINGs/hashtable.c @@ -223,6 +223,43 @@ WMHashGet(WMHashTable *table, const void *key) } +Bool +WMHashGetItemAndKey(WMHashTable *table, const void *key, + void **retItem, void **retKey) +{ + unsigned h; + HashItem *item; + + h = HASH(table, key); + item = table->table[h]; + + if (table->callbacks.keyIsEqual) { + while (item) { + if ((*table->callbacks.keyIsEqual)(key, item->key)) { + break; + } + item = item->next; + } + } else { + while (item) { + if (key == item->key) { + break; + } + item = item->next; + } + } + if (item) { + if (retKey) + *retKey = (void*)item->key; + if (retItem) + *retItem = (void*)item->data; + return True; + } else { + return False; + } +} + + void* WMHashInsert(WMHashTable *table, const void *key, const void *data) @@ -414,8 +451,10 @@ WMNextHashEnumeratorItemAndKey(WMHashEnumerator *enumerator, } if (enumerator->nextItem) { - *item = (void*)((HashItem*)enumerator->nextItem)->data; - *key = (void*)((HashItem*)enumerator->nextItem)->key; + if (item) + *item = (void*)((HashItem*)enumerator->nextItem)->data; + if (key) + *key = (void*)((HashItem*)enumerator->nextItem)->key; enumerator->nextItem = ((HashItem*)enumerator->nextItem)->next; return True; diff --git a/WINGs/proplist.c b/WINGs/proplist.c index 1342e903..511628fe 100644 --- a/WINGs/proplist.c +++ b/WINGs/proplist.c @@ -2,6 +2,12 @@ #include #include +#include +#include +#include +#include +#include +#include #include "WUtil.h" #include "wconfig.h" @@ -31,12 +37,10 @@ typedef struct W_PropList { - static unsigned hashPropList(WMPropList *plist); - typedef unsigned (*hashFunc)(const void*); typedef Bool (*isEqualFunc)(const void*, const void*); typedef void* (*retainFunc)(const void*); @@ -44,14 +48,17 @@ typedef void (*releaseFunc)(const void*); static const WMHashTableCallbacks WMPropListHashCallbacks = { (hashFunc)hashPropList, - (isEqualFunc)WMArePropListsEqual, + (isEqualFunc)WMIsPropListEqualToPropList, (retainFunc)NULL, (releaseFunc)NULL }; + static WMCompareDataProc *strCmp = (WMCompareDataProc*) strcmp; +#define MaxHashLength 64 + static unsigned hashPropList(WMPropList *plist) @@ -59,32 +66,353 @@ hashPropList(WMPropList *plist) unsigned ret = 0; unsigned ctr = 0; const char *key; - int i; + int i, len; switch (plist->type) { case WPLString: key = plist->d.string; - while (*key) { - ret ^= *key++ << ctr; + len = WMIN(strlen(key), MaxHashLength); + for (i=0; id.string);*/ case WPLData: key = WMDataBytes(plist->d.data); - for (i=0; id.data); i++) { + len = WMIN(WMGetDataLength(plist->d.data), MaxHashLength); + for (i=0; id.data);*/ default: wwarning(_("Only string or data is supported for a proplist dictionary key")); wassertrv(False, 0); - break; } } +/*WMSetPropListStringComparisonCaseSensitive +WMSetPropListStringComparerIsCaseSensitive +WMSetPLStringComparisonCaseSensitive*/ + +static WMPropList* +retainPropListByCount(WMPropList *plist, int count) +{ + WMPropList *key, *value; + WMHashEnumerator e; + int i; + + plist->retainCount += count; + + switch(plist->type) { + case WPLString: + case WPLData: + break; + case WPLArray: + for (i=0; id.array); i++) { + retainPropListByCount(WMGetFromArray(plist->d.array, i), count); + } + break; + case WPLDictionary: + e = WMEnumerateHashTable(plist->d.dict); + while (WMNextHashEnumeratorItemAndKey(&e, (void**)&value, (void**)&key)) { + retainPropListByCount(key, count); + retainPropListByCount(value, count); + } + break; + default: + wwarning(_("Used proplist functions on non-WMPropLists objects")); + wassertrv(False, NULL); + } + + return plist; +} + + +static void +releasePropListByCount(WMPropList *plist, int count) +{ + WMPropList *key, *value; + WMHashEnumerator e; + int i; + + plist->retainCount -= count; + + switch(plist->type) { + case WPLString: + if (plist->retainCount < 1) { + wfree(plist->d.string); + wfree(plist); + } + break; + case WPLData: + if (plist->retainCount < 1) { + WMReleaseData(plist->d.data); + wfree(plist); + } + break; + case WPLArray: + for (i=0; id.array); i++) { + releasePropListByCount(WMGetFromArray(plist->d.array, i), count); + } + if (plist->retainCount < 1) { + WMFreeArray(plist->d.array); + wfree(plist); + } + break; + case WPLDictionary: + e = WMEnumerateHashTable(plist->d.dict); + while (WMNextHashEnumeratorItemAndKey(&e, (void**)&value, (void**)&key)) { + releasePropListByCount(key, count); + releasePropListByCount(value, count); + } + if (plist->retainCount < 1) { + WMFreeHashTable(plist->d.dict); + wfree(plist); + } + break; + default: + wwarning(_("Used proplist functions on non-WMPropLists objects")); + wassertr(False); + } +} + + +#define num2char(num) ((num) < 0xa ? ((num)+'0') : ((num)+0x57)) + +static char* +dataDescription(WMPropList *plist) +{ + const unsigned char *data; + char *retVal; + int i, j, length; + + data = WMDataBytes(plist->d.data); + length = WMGetDataLength(plist->d.data); + + retVal = (char*)wmalloc(2*length+length/4+3); + + retVal[0] = '<'; + for (i=0, j=1; i>4) & 0x0f); + retVal[j++] = num2char(data[i] & 0x0f); + if ((i & 0x03)==3 && i!=length-1) { + /* if we've just finished a 32-bit int, add a space */ + retVal[j++] = ' '; + } + } + retVal[j++] = '>'; + retVal[j] = '\0'; + + return retVal; +} + + +static char* +stringDescription(WMPropList *plist) +{ + const char *str; + char *retVal, *sPtr, *dPtr; + int len, quote; + unsigned char ch; + + str = plist->d.string; + + if (strlen(str) == 0) { + return wstrdup("\"\""); + } + + /* FIXME: make this work with unichars. */ + +#define inrange(ch, min, max) ((ch)>=(min) && (ch)<=(max)) +#define noquote(ch) (inrange(ch, 'a', 'z') || inrange(ch, 'A', 'Z') || inrange(ch, '0', '9') || ((ch)=='_') || ((ch)=='.') || ((ch)=='$')) +#define charesc(ch) (inrange(ch, 0x07, 0x0c) || ((ch)=='"') || ((ch)=='\\')) +#define numesc(ch) (((ch)<=0x06) || inrange(ch, 0x0d, 0x1f) || ((ch)>0x7e)) + + quote = 0; + sPtr = (char*) str; + len = 0; + while ((ch = *sPtr)) { + if (!noquote(ch)) { + quote = 1; + if (charesc(ch)) + len++; + else if (numesc(ch)) + len += 3; + } + sPtr++; + len++; + } + + if (quote) + len += 2; + + retVal = (char*)wmalloc(len+1); + + sPtr = (char*) str; + dPtr = retVal; + + if (quote) + *dPtr++ = '"'; + + while ((ch = *sPtr)) { + if (charesc(ch)) { + *(dPtr++) = '\\'; + switch (ch) { + case '\a': *dPtr = 'a'; break; + case '\b': *dPtr = 'b'; break; + case '\t': *dPtr = 't'; break; + case '\n': *dPtr = 'n'; break; + case '\v': *dPtr = 'v'; break; + case '\f': *dPtr = 'f'; break; + default: *dPtr = ch; /* " or \ */ + } + } else if (numesc(ch)) { + *(dPtr++) = '\\'; + *(dPtr++) = '0' + ((ch>>6)&07); + *(dPtr++) = '0' + ((ch>>3)&07); + *dPtr = '0' + (ch&07); + } else { + *dPtr = ch; + } + sPtr++; + dPtr++; + } + + if (quote) + *dPtr++ = '"'; + + *dPtr = '\0'; + + return retVal; +} + + +static char* +description(WMPropList *plist) +{ + WMPropList *key, *val; + char *retstr, *str, *tmp, *skey, *sval; + WMHashEnumerator e; + int i; + + switch (plist->type) { + case WPLString: + return stringDescription(plist); + case WPLData: + return dataDescription(plist); + case WPLArray: + retstr = wstrdup("("); + for (i=0; id.array); i++) { + str = description(WMGetFromArray(plist->d.array, i)); + if (i==0) { + retstr = wstrappend(retstr, str); + } else { + tmp = (char *)wmalloc(strlen(retstr)+strlen(str)+3); + sprintf(tmp, "%s, %s", retstr, str); + wfree(retstr); + retstr = tmp; + } + wfree(str); + } + retstr = wstrappend(retstr, ")"); + break; + case WPLDictionary: + retstr = wstrdup("{"); + e = WMEnumerateHashTable(plist->d.dict); + while (WMNextHashEnumeratorItemAndKey(&e, (void**)&val, (void**)&key)) { + skey = description(key); + sval = description(val); + tmp = (char*)wmalloc(strlen(retstr)+strlen(skey)+strlen(sval)+5); + sprintf(tmp, "%s%s = %s;", retstr, skey, sval); + wfree(skey); + wfree(sval); + wfree(retstr); + retstr = tmp; + } + retstr = wstrappend(retstr, "}"); + break; + default: + wwarning(_("Used proplist functions on non-WMPropLists objects")); + wassertrv(False, NULL); + } + + return retstr; +} + + +static char* +indentedDescription(WMPropList *plist, int level) +{ + WMPropList *key, *val; + char *retstr, *str, *tmp, *skey, *sval; + WMHashEnumerator e; + int i; + + switch (plist->type) { + case WPLString: + return stringDescription(plist); + case WPLData: + return dataDescription(plist); + case WPLArray: + retstr = wstrdup("(\n"); + for (i=0; id.array); i++) { + str = indentedDescription(WMGetFromArray(plist->d.array, i), + level+1); + if (i==0) { + tmp = (char*)wmalloc(2*(level+1)+strlen(retstr)+strlen(str)+1); + sprintf(tmp, "%s%*s%s", retstr, 2*(level+1), "", str); + wfree(retstr); + retstr = tmp; + } else { + tmp = (char*)wmalloc(2*(level+1)+strlen(retstr)+strlen(str)+3); + sprintf(tmp, "%s,\n%*s%s", retstr, 2*(level+1), "", str); + wfree(retstr); + retstr = tmp; + } + wfree(str); + } + tmp = (char*)wmalloc(strlen(retstr) + 2*level + 3); + sprintf(tmp, "%s\n%*s)", retstr, 2*level, ""); + wfree(retstr); + retstr = tmp; + break; + case WPLDictionary: + retstr = wstrdup("{\n"); + e = WMEnumerateHashTable(plist->d.dict); + while (WMNextHashEnumeratorItemAndKey(&e, (void**)&val, (void**)&key)) { + skey = indentedDescription(key, level+1); + sval = indentedDescription(val, level+1); + tmp = (char*)wmalloc(2*(level+1) + strlen(retstr) + strlen(skey) + + strlen(sval) + 6); + sprintf(tmp, "%s%*s%s = %s;\n", retstr, 2*(level+1), "", + skey, sval); + wfree(skey); + wfree(sval); + wfree(retstr); + retstr = tmp; + } + tmp = (char*)wmalloc(strlen(retstr) + 2*level + 2); + sprintf(tmp, "%s%*s}", retstr, 2*level, ""); + wfree(retstr); + retstr = tmp; + break; + default: + wwarning(_("Used proplist functions on non-WMPropLists objects")); + wassertrv(False, NULL); + } + + return retstr; +} + void WMSetPropListStringComparer(WMCompareDataProc *comparer) @@ -136,7 +464,7 @@ WMCreatePropListDataWithBytesNoCopy(unsigned char *bytes, unsigned int length, { WMPropList *plist; - wassertrv(length!=0 && bytes!=NULL, NULL); + wassertrv(bytes!=NULL, NULL); plist = (WMPropList*)wmalloc(sizeof(W_PropList)); @@ -197,6 +525,120 @@ WMCreatePropListArrayFromElements(WMPropList *elem, ...) WMPropList* WMCreatePropListDictionaryFromEntries(WMPropList *key, WMPropList *value, ...) { + WMPropList *plist, *nkey, *nvalue, *k, *v; + va_list ap; + + plist = (WMPropList*)wmalloc(sizeof(W_PropList)); + plist->type = WPLDictionary; + plist->d.dict = WMCreateHashTable(WMPropListHashCallbacks); + plist->retainCount = 1; + + if (!key || !value) + return plist; + + WMHashInsert(plist->d.dict, WMRetainPropList(key), WMRetainPropList(value)); + + va_start(ap, value); + + while (1) { + nkey = va_arg(ap, WMPropList*); + if (!nkey) { + va_end(ap); + return plist; + } + nvalue = va_arg(ap, WMPropList*); + if (!nvalue) { + va_end(ap); + return plist; + } + if (WMHashGetItemAndKey(plist->d.dict, nkey, (void**)&v, (void**)&k)) { + WMHashRemove(plist->d.dict, k); + WMReleasePropList(k); + WMReleasePropList(v); + } + WMHashInsert(plist->d.dict, WMRetainPropList(nkey), + WMRetainPropList(nvalue)); + } +} + + +void +WMInsertPropListArrayElement(WMPropList *plist, WMPropList *item, int index) +{ + wassertr(plist->type==WPLArray); + + retainPropListByCount(item, plist->retainCount); + WMInsertInArray(plist->d.array, index, item); +} + + +void +WMAppendPropListArrayElement(WMPropList *plist, WMPropList *item) +{ + wassertr(plist->type==WPLArray); + + retainPropListByCount(item, plist->retainCount); + WMAddToArray(plist->d.array, item); +} + + +void +WMRemovePropListArrayElement(WMPropList *plist, int index) +{ + WMPropList *item; + + wassertr(plist->type==WPLArray); + + item = WMGetFromArray(plist->d.array, index); + if (item != NULL) { + WMDeleteFromArray(plist->d.array, index); + releasePropListByCount(item, plist->retainCount); + } +} + + +void +WMInsertPropListDictionaryEntry(WMPropList *plist, WMPropList *key, + WMPropList *value) +{ + wassertr(plist->type==WPLDictionary); + + WMRemovePropListDictionaryEntry(plist, key); + retainPropListByCount(key, plist->retainCount); + retainPropListByCount(value, plist->retainCount); + WMHashInsert(plist->d.dict, key, value); +} + + +void +WMRemovePropListDictionaryEntry(WMPropList *plist, WMPropList *key) +{ + WMPropList *k, *v; + + wassertr(plist->type==WPLDictionary); + + if (WMHashGetItemAndKey(plist->d.dict, key, (void**)&v, (void**)&k)) { + WMHashRemove(plist->d.dict, k); + releasePropListByCount(k, plist->retainCount); + releasePropListByCount(v, plist->retainCount); + } +} + + +WMPropList* +WMMergePropListDictionaries(WMPropList *dest, WMPropList *source) +{ + WMPropList *key, *value; + WMHashEnumerator e; + + wassertr(source->type==WPLDictionary && dest->type==WPLDictionary); + + e = WMEnumerateHashTable(source->d.dict); + while (WMNextHashEnumeratorItemAndKey(&e, (void**)&value, (void**)&key)) { + WMInsertPropListDictionaryEntry(dest, key, value); + } + + return dest; } @@ -234,7 +676,6 @@ WMRetainPropList(WMPropList *plist) } -#if 0 void WMReleasePropList(WMPropList *plist) { @@ -282,61 +723,6 @@ WMReleasePropList(WMPropList *plist) wassertr(False); } } -#else - -void -WMReleasePropList(WMPropList *plist) -{ - WMPropList *key, *value; - WMHashEnumerator e; - int i; - - plist->retainCount--; - - switch(plist->type) { - case WPLString: - case WPLData: - break; - case WPLArray: - for (i=0; id.array); i++) { - WMReleasePropList(WMGetFromArray(plist->d.array, i)); - } - break; - case WPLDictionary: - e = WMEnumerateHashTable(plist->d.dict); - while (WMNextHashEnumeratorItemAndKey(&e, (void**)&value, (void**)&key)) { - WMReleasePropList(key); - WMReleasePropList(value); - } - break; - default: - wwarning(_("Used proplist functions on non-WMPropLists objects")); - wassertr(False); - } - - if (plist->retainCount > 0) - return; - - switch(plist->type) { - case WPLString: - wfree(plist->d.string); - break; - case WPLData: - WMReleaseData(plist->d.data); - break; - case WPLArray: - WMFreeArray(plist->d.array); - break; - case WPLDictionary: - WMFreeHashTable(plist->d.dict); - break; - default: - wwarning(_("Used proplist functions on non-WMPropLists objects")); - wassertr(False); - } - wfree(plist); -} -#endif Bool @@ -382,9 +768,9 @@ WMPropListIsCompound(WMPropList *plist) Bool -WMArePropListsEqual(WMPropList *plist, WMPropList *other) +WMIsPropListEqualToPropList(WMPropList *plist, WMPropList *other) { - WMPropList *key1, *key2, *item1, *item2; + WMPropList *key1, *item1, *item2; WMHashEnumerator enumerator; int n, i; @@ -393,7 +779,7 @@ WMArePropListsEqual(WMPropList *plist, WMPropList *other) switch(plist->type) { case WPLString: - return ((*strCmp)(plist->d.string, other->d.string) == 0); + return (strCmp(plist->d.string, other->d.string) == 0); case WPLData: return WMIsDataEqualToData(plist->d.data, other->d.data); case WPLArray: @@ -403,7 +789,7 @@ WMArePropListsEqual(WMPropList *plist, WMPropList *other) for (i=0; id.array, i); item2 = WMGetFromArray(other->d.array, i); - if (!WMArePropListsEqual(item1, item2)) + if (!WMIsPropListEqualToPropList(item1, item2)) return False; } return True; @@ -414,7 +800,7 @@ WMArePropListsEqual(WMPropList *plist, WMPropList *other) while (WMNextHashEnumeratorItemAndKey(&enumerator, (void**)&item1, (void**)&key1)) { item2 = WMHashGet(other->d.dict, key1); - if (!item2 || !item1 || !WMArePropListsEqual(item1, item2)) + if (!item2 || !item1 || !WMIsPropListEqualToPropList(item1, item2)) return False; } return True; @@ -427,6 +813,269 @@ WMArePropListsEqual(WMPropList *plist, WMPropList *other) } +int +WMGetPropListNumberOfElements(WMPropList *plist) +{ + switch(plist->type) { + case WPLString: + case WPLData: + return 0; /* should this be 1 instead? */ + case WPLArray: + return WMGetArrayItemCount(plist->d.array); + case WPLDictionary: + return (int)WMCountHashTable(plist->d.dict); + default: + wwarning(_("Used proplist functions on non-WMPropLists objects")); + wassertrv(False, 0); + } +} + + +char* +WMGetPropListString(WMPropList *plist) +{ + wassertrv(plist->type==WPLString, NULL); + + return plist->d.string; +} + + +WMData* +WMGetPropListData(WMPropList *plist) +{ + wassertrv(plist->type==WPLData, NULL); + + return plist->d.data; +} + + +const unsigned char* +WMGetPropListDataBytes(WMPropList *plist) +{ + wassertrv(plist->type==WPLData, NULL); + + return WMDataBytes(plist->d.data); +} + + +int +WMGetPropListDataLength(WMPropList *plist) +{ + wassertrv(plist->type==WPLData, 0); + + return WMGetDataLength(plist->d.data); +} + + +WMPropList* +WMGetPropListArrayElement(WMPropList *plist, int index) +{ + wassertrv(plist->type==WPLArray, NULL); + + return WMGetFromArray(plist->d.array, index); +} + + +WMPropList* +WMGetPropListDictionaryEntry(WMPropList *plist, WMPropList *key) +{ + wassertrv(plist->type==WPLDictionary, NULL); + + return WMHashGet(plist->d.dict, key); +} + + +WMPropList* +WMGetPropListAllDictionaryKeys(WMPropList *plist) +{ + WMPropList *array, *key; + WMHashEnumerator enumerator; + + wassertrv(plist->type==WPLDictionary, NULL); + + array = (WMPropList*)wmalloc(sizeof(W_PropList)); + array->type = WPLArray; + array->d.array = WMCreateArray(WMCountHashTable(plist->d.dict)); + array->retainCount = 1; + + enumerator = WMEnumerateHashTable(plist->d.dict); + while ((key = WMNextHashEnumeratorKey(&enumerator))) { + WMAddToArray(array->d.array, WMRetainPropList(key)); + } + + return array; +} + + +char* +WMGetPropListDescription(WMPropList *plist, Bool indented) +{ + return (indented ? indentedDescription(plist, 0) : description(plist)); +} + + + +/* TODO: review this function's code */ + +Bool +WMSavePropListToFile(WMPropList *plist, char *path, Bool atomically) +{ + char *thePath=NULL; + char *description; + FILE *theFile; + + if (atomically) { +#ifdef HAVE_MKSTEMP + int fd, mask; +#endif + + /* Use the path name of the destination file as a prefix for the + * mkstemp() call so that we can be sure that both files are on + * the same filesystem and the subsequent rename() will work. */ + thePath = wstrconcat(path, ".XXXXXX"); + +#ifdef HAVE_MKSTEMP + if ((fd = mkstemp(thePath)) < 0) { + wsyserror(_("mkstemp (%s) failed"), thePath); + goto failure; + } + mask = umask(0); + umask(mask); + fchmod(fd, 0644 & ~mask); + if ((theFile = fdopen(fd, "w")) == NULL) { + close(fd); + } +#else + if (mktemp(thePath) == NULL) { + wsyserror(_("mktemp (%s) failed"), thePath); + goto failure; + } + theFile = fopen(thePath, "wb"); +#endif + } else { + thePath = wstrdup(path); + theFile = fopen(thePath, "wb"); + } + + if (theFile == NULL) { + wsyserror(_("open (%s) failed"), thePath); + goto failure; + } + + description = indentedDescription(plist, 0); + + if (fprintf(theFile, "%s\n", description) != strlen(description)+1) { + wsyserror(_("writing to file: %s failed"), thePath); + wfree(description); + goto failure; + } + + wfree(description); + + if (fclose(theFile) != 0) { + wsyserror(_("fclose (%s) failed"), thePath); + goto failure; + } + + /* If we used a temporary file, we still need to rename() it be the + * real file. Also, we need to try to retain the file attributes of + * the original file we are overwriting (if we are) */ + if (atomically) { + if (rename(thePath, path) != 0) { + wsyserror(_("rename ('%s' to '%s') failed"), thePath, path); + goto failure; + } + } + + wfree(thePath); + return True; + +failure: + if (atomically) { + unlink(thePath); + wfree(thePath); + } + + return False; +} + + +WMPropList* +WMShallowCopyPropList(WMPropList *plist) +{ + WMPropList *ret, *key, *item; + WMHashEnumerator e; + int i; + + switch(plist->type) { + case WPLString: + case WPLData: + return WMDeepCopyPropList(plist); + case WPLArray: + ret = (WMPropList*)wmalloc(sizeof(W_PropList)); + ret->type = WPLArray; + ret->d.array = WMCreateArrayWithArray(plist->d.array); + ret->retainCount = 1; + + for(i=0; id.array); i++) + WMRetainPropList(WMGetFromArray(ret->d.array, i)); + + return ret; + case WPLDictionary: + ret = WMCreatePropListDictionaryFromEntries(NULL, NULL); + e = WMEnumerateHashTable(plist->d.dict); + while (WMNextHashEnumeratorItemAndKey(&e, (void**)&item, (void**)&key)) { + WMInsertPropListDictionaryEntry(ret, key, item); + } + return ret; + default: + wwarning(_("Used proplist functions on non-WMPropLists objects")); + wassertrv(False, NULL); + } +} + + +WMPropList* +WMDeepCopyPropList(WMPropList *plist) +{ + WMPropList *ret, *key, *item; + WMHashEnumerator e; + WMData *data; + int i; + + switch(plist->type) { + case WPLString: + return WMCreatePropListString(plist->d.string); + case WPLData: + data = WMCreateDataWithData(plist->d.data); + ret = WMCreatePropListDataWithData(data); + WMReleaseData(data); + return ret; + case WPLArray: + ret = WMCreatePropListArrayFromElements(NULL); + for(i=0; id.array); i++) { + item = WMDeepCopyPropList(WMGetFromArray(plist->d.array, i)); + WMAddToArray(ret->d.array, item); + } + return ret; + case WPLDictionary: + ret = WMCreatePropListDictionaryFromEntries(NULL, NULL); + e = WMEnumerateHashTable(plist->d.dict); + /* While we copy an existing dictionary there is no way that we can + * have duplicate keys, so we don't need to first remove a key/value + * pair before inserting the new key/value. + */ + while (WMNextHashEnumeratorItemAndKey(&e, (void**)&item, (void**)&key)) { + WMHashInsert(ret->d.dict, WMDeepCopyPropList(key), + WMDeepCopyPropList(item)); + } + return ret; + default: + wwarning(_("Used proplist functions on non-WMPropLists objects")); + wassertrv(False, NULL); + } +} + diff --git a/configure.ac b/configure.ac index db86f098..c76bbbaf 100644 --- a/configure.ac +++ b/configure.ac @@ -100,7 +100,7 @@ dnl not used anywhere dnl AC_FUNC_MEMCMP AC_FUNC_VPRINTF AC_FUNC_ALLOCA -AC_CHECK_FUNCS(gethostname select poll strerror strcasecmp strncasecmp setpgid atexit mallinfo vsnprintf vasprintf) +AC_CHECK_FUNCS(gethostname select poll strerror strcasecmp strncasecmp setpgid atexit mallinfo vsnprintf vasprintf mkstemp) diff --git a/configure.in b/configure.in index f937de22..c76bbbaf 100644 --- a/configure.in +++ b/configure.in @@ -100,7 +100,7 @@ dnl not used anywhere dnl AC_FUNC_MEMCMP AC_FUNC_VPRINTF AC_FUNC_ALLOCA -AC_CHECK_FUNCS(gethostname select poll strerror strcasecmp strncasecmp setpgid atexit mallinfo vsnprintf vasprintf) +AC_CHECK_FUNCS(gethostname select poll strerror strcasecmp strncasecmp setpgid atexit mallinfo vsnprintf vasprintf mkstemp) @@ -151,7 +151,7 @@ dnl Checks for header files. dnl ======================= AC_HEADER_SYS_WAIT AC_HEADER_TIME -AC_CHECK_HEADERS(fcntl.h limits.h sys/ioctl.h sys/time.h sys/types.h libintl.h sys/select.h poll.h malloc.h ctype.h stdlib.h) +AC_CHECK_HEADERS(fcntl.h limits.h sys/ioctl.h sys/time.h sys/types.h libintl.h sys/select.h poll.h malloc.h ctype.h stdlib.h string.h strings.h) @@ -436,9 +436,9 @@ fi dnl XINERAMA support dnl ================ xinerama=no -AC_ARG_ENABLE(xinerama, -[ --disable-xinerama disable XInerama extension support], - xinerama=$enableval, xinerama=yes) +#AC_ARG_ENABLE(xinerama, +#[ --disable-xinerama disable XInerama extension support], +# xinerama=$enableval, xinerama=yes) if test "$xinerama" = yes; then AC_CHECK_LIB(Xinerama, XineramaQueryScreens, [XLIBS="-lXinerama $XLIBS" diff --git a/src/screen.h b/src/screen.h index a4e6050e..e25f82a6 100644 --- a/src/screen.h +++ b/src/screen.h @@ -336,11 +336,6 @@ typedef struct _WScreen { typedef struct WWorkspaceState { int flags; int workspace; -#if 0 /* obsoleted by saving menus position in WMState */ - int menu_x, menu_y; - int smenu_x, smenu_y; - int wmenu_x, wmenu_y; -#endif } WWorkspaceState; diff --git a/src/session.c b/src/session.c index 824ef6d4..949c1a59 100644 --- a/src/session.c +++ b/src/session.c @@ -709,12 +709,12 @@ wSessionSendSaveYourself(WScreen *scr) * - this state file is not meant to be edited by users * * The old session code will become obsolete. When wmaker is - * compiled with R6 sm support compiled in, itll be better to + * compiled with R6 sm support compiled in, it'll be better to * use a totally rewritten state saving code, but we can keep * the current code for when XSMP_ENABLED is not compiled in. * * This will be confusing to old users (well get lots of "SAVE_SESSION broke!" - * messages), but itll be better. + * messages), but it'll be better. * * -readme */ diff --git a/wrlib/jpeg.c b/wrlib/jpeg.c index e6e05930..666ade90 100644 --- a/wrlib/jpeg.c +++ b/wrlib/jpeg.c @@ -22,6 +22,8 @@ #include +/* Avoid a compiler warning */ +#undef HAVE_STDLIB_H