/* * @OPENGROUP_COPYRIGHT@ * COPYRIGHT NOTICE * Copyright (c) 1990, 1991, 1992, 1993 Open Software Foundation, Inc. * Copyright (c) 1996, 1997, 1998, 1999, 2000 The Open Group * ALL RIGHTS RESERVED (MOTIF). See the file named COPYRIGHT.MOTIF for * the full copyright text. * * This software is subject to an open license. It may only be * used on, with or for operating systems which are themselves open * source systems. You must contact The Open Group for a license * allowing distribution and sublicensing of this software on, with, * or for operating systems which are not Open Source programs. * * See http://www.opengroup.org/openmotif/license for full * details of the license agreement. Any use, reproduction, or * distribution of the program constitutes recipient's acceptance of * this agreement. * * EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS * PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY * WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY * OR FITNESS FOR A PARTICULAR PURPOSE * * EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT * NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE * EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. */ /* * HISTORY */ #ifdef REV_INFO #ifndef lint static char rcsid[] = "$TOG: XmRenderT.c /main/14 1998/10/26 20:14:42 samborn $" #endif #endif #ifndef X_NOT_STDC_ENV #include #endif #include #include #include #ifdef __cplusplus extern "C" { /* some 'locale.h' do not have prototypes (sun) */ #endif #include #ifdef __cplusplus } /* Close scope of 'extern "C"' declaration */ #endif /* __cplusplus */ #include /* For ALLOCATE/DEALLOCATE_LOCAL */ #include #include #include #include /* For XmGetXmDisplay */ #include /* For direct access to callback fields */ #include "MessagesI.h" #include "XmI.h" #include "XmRenderTI.h" #include "XmStringI.h" #include "XmTabListI.h" /* Warning Messages */ #define NO_NULL_TAG_MSG _XmMMsgXmRenderT_0000 #define NULL_DISPLAY_MSG _XmMMsgXmRenderT_0001 #define INVALID_TYPE_MSG _XmMMsgXmRenderT_0002 #define CONVERSION_FAILED_MSG _XmMMsgXmRenderT_0003 #define NULL_FONT_TYPE_MSG _XmMMsgXmRenderT_0004 #define NULL_LOAD_IMMEDIATE_MSG _XmMMsgXmRenderT_0005 /* local macros */ #define GetHandle(type) (type *)XtMalloc(sizeof(type)) #define FreeHandle(handle) XtFree((char *)handle) #define SetPtr(handle, ptr) *(handle) = ptr #define GetPtr(handle) *(handle) #define NameIsString(fontname) \ (((fontname) != NULL) && ((fontname) != (String)XmAS_IS)) #define ListIsList(tablist) \ (((tablist) != NULL) && \ ((unsigned int)(unsigned long)(tablist) != XmAS_IS)) /********************************************************************** * IMPORTANT NOTE: IMPLEMENTATION OF SHARING * * Instances of XmRenderTable and XmRendition are shared via a * reference counting mechanism. This comment provides a general * overview of how this is done. * * First, both rendertable and renditions are indirectly * referenced via a handle mechanism. See the GetHandle, * FreeHandle, SetPtr and GetPtr macros above. This allows * either the handle to change without the underlying data * structure changing, or the underlying data structure to change * without the handle changing. I will indicate below where this * happens. * * Second, the real data structure for rendertable and rendition * contain a reference count. This count is incremented on copy * and decremented on free. If a decrement produces a zero * refcount, the actual memory is freed. If an increment * produces a zero refcount, then the refcount has overflowed. The * refcount is decremented, and new memory is allocated for a new * copy. * * Finally, I have defined a terminology for the different types * of "copying" that can done based on allocating a new handle or * not and allocating a new data structure or not. This probably * conflicts with some other existing terminology, probably in * object oriented programming. Sorry about that. * * Function: Clone Copy Renew Duplicate * (Mutate) (Update) * * handle new new old old * structure new inc new inc * (changed) (changed) * * (changed) indicates that the data in the new structure has * been changed from the data in the old structure. * * I will use these terms as a short hand in describing the * functions below. **********************************************************************/ /******** Static Function Declarations ********/ static void CopyInto(XmRendition toRend, XmRendition fromRend); static void MergeInto(XmRendition toRend, XmRendition fromRend); static XmRendition CloneRendition(XmRendition rend); static XmRendition CopyRendition(XmRendition rend); static XmRendition RenewRendition(XmRendition rend); static XmRendition DuplicateRendition(XmRendition rend); static Boolean FreeRendition(XmRendition rend); static void RenditionWarning(char *tag, char *type, char *message, Display *dpy); static void CleanupResources(XmRendition rend, Boolean copy); static void ValidateTag(XmRendition rend, XmStringTag dflt); static void ValidateAndLoadFont(XmRendition rend, Display *display); static void SetRend(XmRendition to, XmRendition from); static Boolean RendComplete(XmRendition rend); static void CopyFromArg(XtArgVal src, char *dst, unsigned int size); static void CopyToArg(char *src, XtArgVal *dst, unsigned int size); static Cardinal GetNamesAndClasses(Widget w, XrmNameList names, XrmClassList classes); static XrmResourceList CompileResourceTable(XtResourceList resources, Cardinal num_resources); static Boolean GetResources(XmRendition rend, Display *dsp, Widget wid, String resname, String resclass, XmStringTag tag, ArgList arglist, Cardinal argcount); static void SetDefault(XmRendition rend); /******** End Static Function Declarations ********/ /* Resource List. */ /************************************************************************/ /* N.B.: The SetDefault procedure has a hardcoded list of all the */ /* common resources. Be sure to update it when adding resources. */ /************************************************************************/ #define DEFAULT_loadModel XmAS_IS #define DEFAULT_tag XmS #define DEFAULT_fontName (String)XmAS_IS #define DEFAULT_fontType (XmFontType)XmAS_IS #define DEFAULT_font (XtPointer)XmAS_IS #define DEFAULT_tabs (XmTabList)XmAS_IS #define DEFAULT_background XmUNSPECIFIED_PIXEL #define DEFAULT_foreground XmUNSPECIFIED_PIXEL #define DEFAULT_underlineType XmAS_IS #define DEFAULT_strikethruType XmAS_IS #define DEFAULT_backgroundState XmAS_IS #define DEFAULT_foregroundState XmAS_IS static XtResource _XmRenditionResources[] = { { XmNtag, XmCTag, XmRString, sizeof(XmStringTag), XtOffsetOf(_XmRenditionRec, tag), XmRImmediate, (XtPointer) DEFAULT_tag }, { XmNfontName, XmCFontName, XmRString, sizeof(String), XtOffsetOf(_XmRenditionRec, fontName), XmRImmediate, (XtPointer) DEFAULT_fontName }, { XmNfontType, XmCFontType, XmRFontType, sizeof(XmFontType), XtOffsetOf(_XmRenditionRec, fontType), XmRImmediate, (XtPointer) DEFAULT_fontType }, { XmNfont, XmCFont, XmRFontStruct, sizeof(XtPointer), XtOffsetOf(_XmRenditionRec, font), XmRImmediate, (XtPointer) DEFAULT_font }, { XmNloadModel, XmCLoadModel, XmRLoadModel, sizeof(unsigned char), XtOffsetOf(_XmRenditionRec, loadModel), XmRImmediate, (XtPointer) DEFAULT_loadModel }, { XmNtabList, XmCTabList, XmRTabList, sizeof(XmTabList), XtOffsetOf(_XmRenditionRec, tabs), XmRImmediate, (XtPointer) DEFAULT_tabs }, { XmNrenditionBackground, XmCRenditionBackground, XmRRenditionPixel, sizeof(Pixel), XtOffsetOf(_XmRenditionRec, background), XmRImmediate, (XtPointer) DEFAULT_background }, { XmNrenditionForeground, XmCRenditionForeground, XmRRenditionPixel, sizeof(Pixel), XtOffsetOf(_XmRenditionRec, foreground), XmRImmediate, (XtPointer) DEFAULT_foreground }, { XmNunderlineType, XmCUnderlineType, XmRLineType, sizeof(unsigned char), XtOffsetOf(_XmRenditionRec, underlineType), XmRImmediate, (XtPointer) DEFAULT_underlineType }, { XmNstrikethruType, XmCStrikethruType, XmRLineType, sizeof(unsigned char), XtOffsetOf(_XmRenditionRec, strikethruType), XmRImmediate, (XtPointer) DEFAULT_strikethruType }, { XmNforegroundState, XmCGroundState, XmRGroundState, sizeof(unsigned char), XtOffsetOf(_XmRenditionRec, foregroundState), XmRImmediate, (XtPointer) DEFAULT_foregroundState }, { XmNbackgroundState, XmCGroundState, XmRGroundState, sizeof(unsigned char), XtOffsetOf(_XmRenditionRec, backgroundState), XmRImmediate, (XtPointer) DEFAULT_backgroundState }, }; static XmConst Cardinal _XmNumRenditionResources = XtNumber(_XmRenditionResources); /* Searches up widget hierarchy, quarkifying ancestor names and */ /* classes. */ static Cardinal GetNamesAndClasses(Widget w, XrmNameList names, XrmClassList classes) { Cardinal length, j; XrmQuark t; WidgetClass wc; /* Return null-terminated quark arrays, with length the number of quarks (not including NULL) */ for (length = 0; w != NULL; w = (Widget)w->core.parent) { names[length] = w->core.xrm_name; wc = XtClass(w); /* KLUDGE KLUDGE KLUDGE KLUDGE */ if (w->core.parent == NULL && XtIsApplicationShell(w)) { classes[length] = ((ApplicationShellWidget) w)->application.xrm_class; } else classes[length] = wc->core_class.xrm_class; length++; } /* They're in backwards order, flop them around */ for (j = 0; j < length/2; j++) { t = names[j]; names[j] = names[length-j-1]; names[length-j-1] = t; t = classes[j]; classes[j] = classes[length-j-1]; classes[length-j-1] = t; } names[length] = NULLQUARK; classes[length] = NULLQUARK; return length; } /* GetNamesAndClasses */ /* Converts resource list to quarkified list. */ static XrmResourceList CompileResourceTable(XtResourceList resources, Cardinal num_resources) { Cardinal count; XrmResourceList table, tPtr; XtResourceList rPtr; tPtr = table = (XrmResourceList)XtMalloc(num_resources * sizeof(XrmResource)); rPtr = resources; for (count = 0; count < num_resources; count++, tPtr++, rPtr++) { tPtr->xrm_name = XrmPermStringToQuark(rPtr->resource_name); tPtr->xrm_class = XrmPermStringToQuark(rPtr->resource_class); tPtr->xrm_type = XrmPermStringToQuark(rPtr->resource_type); tPtr->xrm_size = rPtr->resource_size; tPtr->xrm_offset = rPtr->resource_offset; tPtr->xrm_default_type = XrmPermStringToQuark(rPtr->default_type); tPtr->xrm_default_addr = rPtr->default_addr; } return(table); } /* Does resource database lookup for arglist, filling in defaults from */ /* resource list as necessary. */ static Boolean GetResources(XmRendition rend, Display *dsp, Widget wid, String resname, String resclass, XmStringTag tag, ArgList arglist, Cardinal argcount) { XrmName names[100]; XrmClass classes[100]; Cardinal length = 0; static XrmQuarkList quarks = NULL; static Cardinal num_quarks = 0; static Boolean *found = NULL; int i, j; static XrmResourceList table = NULL; static XrmQuark QString; static XrmQuark Qfont; Arg *arg; XrmName argName; XrmResource *res; XrmDatabase db = NULL; XrmHashTable stackSearchList[100]; XrmHashTable *searchList = stackSearchList; unsigned int searchListSize = 100; Boolean got_one = False; XrmValue value; XrmQuark rawType; XrmValue convValue; Boolean have_value, copied; #ifdef XTHREADS XtAppContext app=NULL; if (wid) app = XtWidgetToApplicationContext(wid); else if (dsp) app = XtDisplayToApplicationContext(dsp); if (app) { _XmAppLock(app); } _XmProcessLock(); #endif /* Initialize quark cache */ if (quarks == NULL) { quarks = (XrmQuark *)XtMalloc(_XmNumRenditionResources * sizeof(XrmQuark)); num_quarks = _XmNumRenditionResources; } /* Initialize found */ if (found == NULL) found = (Boolean *)XtMalloc(_XmNumRenditionResources * sizeof(Boolean)); bzero(found, _XmNumRenditionResources * sizeof(Boolean)); /* Compile names and classes. */ if (wid != NULL) length = GetNamesAndClasses(wid, names, classes); names[length] = XrmStringToQuark(resname); classes[length] = XrmStringToQuark(resclass); length++; if (tag != NULL) { names[length] = XrmStringToQuark(tag); classes[length] = XrmPermStringToQuark(XmCRendition); length++; } names[length] = NULLQUARK; classes[length] = NULLQUARK; /* Cache arglist */ if (num_quarks < argcount) { quarks = (XrmQuark *)XtRealloc((char *)quarks, argcount * sizeof(XrmQuark)); num_quarks = argcount; } for (i = 0; i < argcount; i++) quarks[i] = XrmStringToQuark(arglist[i].name); /* Compile resource description into XrmResourceList if not already done. */ if (table == NULL) { table = CompileResourceTable(_XmRenditionResources, _XmNumRenditionResources); QString = XrmPermStringToQuark(XtCString); Qfont = XrmPermStringToQuark(XmNfont); } /* Set resources from arglist. */ for (arg = arglist, i = 0; i < argcount; arg++, i++) { argName = quarks[i]; for (j = 0, res = table; j < _XmNumRenditionResources; j++, res++) { if (res->xrm_name == argName) { CopyFromArg((arg->value), ((char *)GetPtr(rend) + res->xrm_offset), res->xrm_size); found[j] = TRUE; break; } } } /* DB query */ /* Get database */ if ((wid != NULL) || (dsp != NULL)) { if (wid != NULL) db = XtScreenDatabase(XtScreenOfObject(wid)); else db = XtScreenDatabase(DefaultScreenOfDisplay(dsp)); /* Get searchlist */ while (!XrmQGetSearchList(db, names, classes, searchList, searchListSize)) { if (searchList == stackSearchList) searchList = NULL; searchList = (XrmHashTable *)XtRealloc((char*)searchList, sizeof(XrmHashTable) * (searchListSize *= 2)); } } /* Loop over table */ for (j = 0, res = table; j < _XmNumRenditionResources; j++, res++) { if (!found[j]) { copied = False; have_value = False; if ((db != NULL) && (XrmQGetSearchResource(searchList, res->xrm_name, res->xrm_class, &rawType, &value))) { /* convert if necessary */ if (rawType != res->xrm_type) { if (wid != NULL) { convValue.size = res->xrm_size; convValue.addr = (char *)GetPtr(rend) + res->xrm_offset; /* * Check for special font case. * Depending upon the fontType resource, try to convert * to a FontSet, else to a FontStruct. */ if ((res->xrm_name == Qfont) && (_XmRendFontType(rend) == XmFONT_IS_FONTSET)) copied = have_value = XtConvertAndStore(wid, XrmQuarkToString(rawType), &value, "FontSet", &convValue); else copied = have_value = XtConvertAndStore(wid, XrmQuarkToString(rawType), &value, XrmQuarkToString(res->xrm_type), &convValue); } else have_value = False; } else have_value = True; /* Check for special font case */ if (have_value) { if (res->xrm_name == Qfont) { _XmRendFontName(rend) = value.addr; copied = True; } } } if (!got_one && have_value) got_one = True; /* Set defaults */ if (!have_value) { CopyFromArg((XtArgVal)(res->xrm_default_addr), ((char *)GetPtr(rend) + res->xrm_offset), res->xrm_size); copied = True; } /* Copy if needed */ if (!copied) { if (res->xrm_type == QString) *((String *)((char *)GetPtr(rend) + res->xrm_offset)) = value.addr; else if (value.addr != NULL) memcpy(((char *)GetPtr(rend) + res->xrm_offset), value.addr, res->xrm_size); else bzero(((char *)GetPtr(rend) + res->xrm_offset), res->xrm_size); } } } if (searchList != stackSearchList) XtFree((char *)searchList); #ifdef XTHREADS _XmProcessUnlock(); if (app) { _XmAppUnlock(app); } #endif return(got_one); } /* Sets all resources to defaults from resource list. */ static void SetDefault(XmRendition rend) { /* A more robust implementation of this routine would to to loop * over _XmRenditionResources and use CopyFromArg to reset values * in rend, but to improve performance we use direct assignments. */ if (rend == NULL) return; /* Leave _XmRendFontOnly unchanged. */ /* Leave _XmRendRefcount unchanged. */ _XmRendLoadModel(rend) = DEFAULT_loadModel; _XmRendTag(rend) = DEFAULT_tag; _XmRendFontName(rend) = DEFAULT_fontName; _XmRendFontType(rend) = DEFAULT_fontType; _XmRendFont(rend) = DEFAULT_font; /* Leave _XmRendDisplay unchanged. */ /* Leave _XmRendGC unchanged. */ /* Leave _XmRendTags unchanged. */ /* Leave _XmRendCount unchanged. */ /* Leave _XmRendHadEnds unchanged. */ _XmRendTabs(rend) = DEFAULT_tabs; _XmRendBG(rend) = DEFAULT_background; _XmRendFG(rend) = DEFAULT_foreground; _XmRendUnderlineType(rend) = DEFAULT_underlineType; _XmRendStrikethruType(rend) = DEFAULT_strikethruType; _XmRendBGState(rend) = DEFAULT_backgroundState; _XmRendFGState(rend) = DEFAULT_foregroundState; } /* Extern function to pick out display from rendertable. */ Display * _XmRenderTableDisplay(XmRenderTable table) { return(_XmRTDisplay(table)); } /* Find a rendition in table with matching tag. Call callback if not */ /* found and callback available. Fail if need_font is true and */ /* rendition found does not provide font. */ XmRendition _XmRenderTableFindRendition(XmRenderTable table, XmStringTag tag, #if NeedWidePrototypes int cached_tag, int need_font, int call, #else Boolean cached_tag, Boolean need_font, Boolean call, #endif /* NeedWidePrototypes */ short *index) { int i, j; XmRendition rend; Boolean hit = FALSE; XmDisplayCallbackStruct cb; XmDisplay dsp; XmRenderTable copy; if ((table == NULL) || (tag == NULL)) return(NULL); for (;;) /* May have to try twice */ { for (i = 0; i < _XmRTCount(table); i++) { rend = _XmRTRenditions(table)[i]; if ((cached_tag) ? (_XmRendTag(rend) == tag) : (strcmp(_XmRendTag(rend), tag) == 0)) { hit = TRUE; if ((_XmRendFont(rend) == NULL) && NameIsString(_XmRendFontName(rend))) { if (_XmRendLoadModel(rend) == XmLOAD_DEFERRED) _XmRendLoadModel(rend) = XmLOAD_IMMEDIATE; ValidateAndLoadFont(rend, _XmRendDisplay(rend)); if (need_font && (_XmRendFont(rend) == NULL)) break; } if (index != NULL) *index = i; return(rend); } } /* Are we done? */ if (hit || !call) break; call = FALSE; /* Call callback */ if (_XmRTDisplay(table) != NULL) { dsp = (XmDisplay) XmGetXmDisplay(_XmRTDisplay(table)); /* CR 7964: XtHasCallbacks is surprisingly expensive, */ /* so we use a conservative approximation here. */ if (dsp && dsp->display.noRenditionCallback) { copy = XmRenderTableCopy(table, NULL, 0); cb.reason = XmCR_NO_RENDITION; cb.event = NULL; cb.render_table = copy; cb.tag = tag; XtCallCallbackList((Widget)dsp, dsp->display.noRenditionCallback, &cb); if (cb.render_table != copy) { /* Callback mutated table. Update table with */ /* substitution and search again. */ for (j = 0; j < _XmRTCount(table); j++) if (FreeRendition(_XmRTRenditions(table)[j])) FreeHandle(_XmRTRenditions(table)[j]); if (_XmRTRefcountDec(table) == 0) XtFree((char *)GetPtr(table)); SetPtr(table, GetPtr(cb.render_table)); FreeHandle(cb.render_table); } else break; } else break; } else break; } /* Didn't find it. */ if (index != NULL) *index = -1; return(NULL); } /* If to has resource unset and from has it set, set in to. */ static void SetRend(XmRendition to, XmRendition from) { if (NameIsString(_XmRendFontName(from)) && !NameIsString(_XmRendFontName(to))) _XmRendFontName(to) = _XmRendFontName(from); if ((_XmRendFontType(from) != XmAS_IS) && (_XmRendFontType(to) == XmAS_IS)) _XmRendFontType(to) = _XmRendFontType(from); if ((_XmRendLoadModel(from) != XmAS_IS) && (_XmRendLoadModel(to) == XmAS_IS)) _XmRendLoadModel(to) = _XmRendLoadModel(from); if ((_XmRendFont(from) != NULL) && ((unsigned int)(unsigned long)_XmRendFont(to) == XmAS_IS)) _XmRendFont(to) = _XmRendFont(from); if (ListIsList(_XmRendTabs(from)) && !ListIsList(_XmRendTabs(to))) _XmRendTabs(to) = _XmRendTabs(from); if ((_XmRendFG(from) != XmUNSPECIFIED_PIXEL) && (_XmRendFG(to) == XmUNSPECIFIED_PIXEL)) _XmRendFG(to) = _XmRendFG(from); if ((_XmRendBG(from) != XmUNSPECIFIED_PIXEL) && (_XmRendBG(to) == XmUNSPECIFIED_PIXEL)) _XmRendBG(to) = _XmRendBG(from); if ((_XmRendUnderlineType(from) != XmAS_IS) && (_XmRendUnderlineType(to) == XmAS_IS)) _XmRendUnderlineType(to) = _XmRendUnderlineType(from); if ((_XmRendStrikethruType(from) != XmAS_IS) && (_XmRendStrikethruType(to) == XmAS_IS)) _XmRendStrikethruType(to) = _XmRendStrikethruType(from); } /* Check that all resources are not default values. */ static Boolean RendComplete(XmRendition rend) { return(((unsigned int)(unsigned long)_XmRendFontName(rend) != XmAS_IS) && (_XmRendFontType(rend) != XmAS_IS) && (_XmRendLoadModel(rend) != XmAS_IS) && ((unsigned int)(unsigned long)_XmRendFont(rend) != XmAS_IS) && ((unsigned int)(unsigned long)_XmRendTabs(rend) != XmAS_IS) && (_XmRendFG(rend) != XmUNSPECIFIED_PIXEL) && (_XmRendBG(rend) != XmUNSPECIFIED_PIXEL) && (_XmRendUnderlineType(rend) != XmAS_IS) && (_XmRendStrikethruType(rend) != XmAS_IS)); } /* Search rt for all renditions matching tags, successively merging */ /* resource values in scr rendition. */ /*ARGSUSED*/ XmRendition _XmRenditionMerge(Display *d, /* unused */ XmRendition *scr, XmRendition base_rend, XmRenderTable rt, XmStringTag base_tag, XmStringTag *tags, #if NeedWidePrototypes unsigned int tag_count, unsigned int copy #else unsigned short tag_count, Boolean copy #endif /* NeedWidePrototypes */ ) { XmRendition rend, tmp; int i; if (scr == NULL) { rend = XmRenditionCreate(NULL, XmS, NULL, 0); /* Create new */ } else { rend = *scr; if (copy) { if (NameIsString(_XmRendFontName(rend))) XtFree(_XmRendFontName(rend)); if (ListIsList(_XmRendTabs(rend))) XmTabListFree(_XmRendTabs(rend)); } SetDefault(rend); /* Reset state */ } for (i = (tag_count - 1); i >= 0; i--) { tmp = _XmRenderTableFindRendition(rt, tags[i], TRUE, FALSE, TRUE, NULL); if (tmp == NULL) continue; SetRend(rend, tmp); if (RendComplete(rend)) break; } if (!RendComplete(rend)) { short index; _XmRenderTableFindFallback(rt, base_tag, TRUE, &index, &tmp); if (tmp != NULL) SetRend(rend, tmp); } if (base_rend != NULL) { SetRend(rend, base_rend); if (_XmRendFGState(base_rend) == XmFORCE_COLOR) _XmRendFG(rend) = _XmRendFG(base_rend); if (_XmRendBGState(base_rend) == XmFORCE_COLOR) _XmRendBG(rend) = _XmRendBG(base_rend); } CleanupResources(rend, copy); return(rend); } /**************** * If the cached_tag flag is true, _XmRenderTableFindFallback assumes that the * tag pointer is a pointer out of the (local) tag cache. * Since XmRenditionCreate also uses tag pointers out of this cache, * a string compare is avoided by simply comparing pointer values. ****************/ extern Boolean _XmRenderTableFindFallback( XmRenderTable rendertable, XmStringTag tag, #if NeedWidePrototypes int cached_tag, #else Boolean cached_tag, #endif /* NeedWidePrototypes */ short *indx, XmRendition *rend_ptr ) { XmStringTag search_cset = NULL; *indx = -1 ; if ((rendertable != NULL) && (_XmRTCount(rendertable) == 0)) { *rend_ptr = NULL; return(FALSE); } if (rendertable != NULL) { if (tag != NULL) { if (cached_tag) /* No XmSTRING_DEFAULT_CHARSET */ { *rend_ptr = (XmRendition) _XmRenderTableFindRendition(rendertable, tag, TRUE, TRUE, FALSE, indx); if (*rend_ptr != NULL) return(TRUE); } else { XmStringTag curtag; if ((strcmp(tag, XmSTRING_DEFAULT_CHARSET) == 0)) curtag = _XmStringGetCurrentCharset(); else curtag = tag; *rend_ptr = (XmRendition) _XmRenderTableFindRendition(rendertable, curtag, FALSE, TRUE, FALSE, indx); if (*rend_ptr != NULL) return(TRUE); } /* Didn't find a match. See if tag is one of the defaults and search for the other. */ if (_XmStringIsCurrentCharset(tag)) { search_cset = XmFONTLIST_DEFAULT_TAG; *rend_ptr = (XmRendition) _XmRenderTableFindRendition(rendertable, search_cset, TRUE, TRUE, FALSE, indx); if (*rend_ptr != NULL) return(TRUE); } else if ((tag == XmFONTLIST_DEFAULT_TAG) || (strcmp(tag, XmFONTLIST_DEFAULT_TAG) == 0)) { search_cset = _XmStringGetCurrentCharset(); *rend_ptr = (XmRendition) _XmRenderTableFindRendition(rendertable, search_cset, FALSE, TRUE, FALSE, indx); if (*rend_ptr != NULL) return(TRUE); } } /* Otherwise pick up first font(set) if tag a default value. */ if ((tag == NULL) || (tag == XmFONTLIST_DEFAULT_TAG) || (strcmp(tag, XmFONTLIST_DEFAULT_TAG) == 0) || _XmStringIsCurrentCharset(tag)) return(_XmRenderTableFindFirstFont(rendertable, indx, rend_ptr)); } *rend_ptr = NULL; *indx = -1; return(FALSE); } extern Boolean _XmRenderTableFindFirstFont(XmRenderTable rendertable, short *indx, XmRendition *rend_ptr) { int i, f_idx = -1, fs_idx = -1; for (i = _XmRTCount(rendertable) - 1; i >= 0; i--) { *rend_ptr = _XmRTRenditions(rendertable)[i]; if (_XmRendFont(*rend_ptr) != NULL) if (_XmRendFontType(*rend_ptr) == XmFONT_IS_FONT) f_idx = i; else if (_XmRendFontType(*rend_ptr) == XmFONT_IS_FONTSET) fs_idx = i; } if (fs_idx >= 0) { *rend_ptr = _XmRTRenditions(rendertable)[fs_idx]; *indx = fs_idx; } else if (f_idx >= 0) { *rend_ptr = _XmRTRenditions(rendertable)[f_idx]; *indx = f_idx; } else { *rend_ptr = NULL; *indx = -1; return(FALSE); } return(TRUE); } /* Put value of every resource in fromRend into toRend, copying where */ /* necessary. */ static void CopyInto(XmRendition toRend, XmRendition fromRend) { _XmRendTag(toRend) = _XmStringCacheTag(_XmRendTag(fromRend), XmSTRING_TAG_STRLEN); /* CR 7890 - the fontName might be XmAS_IS here - if so, we ** obviously don't want to do an XtNewString (implicit strcpy) */ if (!NameIsString(_XmRendFontName(fromRend))) _XmRendFontName(toRend) = NULL; else _XmRendFontName(toRend) = XtNewString(_XmRendFontName(fromRend)); _XmRendFontType(toRend) = _XmRendFontType(fromRend); _XmRendLoadModel(toRend) = _XmRendLoadModel(fromRend); _XmRendFont(toRend) = _XmRendFont(fromRend); _XmRendDisplay(toRend) = _XmRendDisplay(fromRend); if (!ListIsList(_XmRendTabs(fromRend))) _XmRendTabs(toRend) = NULL; else _XmRendTabs(toRend) = XmTabListCopy(_XmRendTabs(fromRend), 0, 0); _XmRendBG(toRend) = _XmRendBG(fromRend); _XmRendFG(toRend) = _XmRendFG(fromRend); _XmRendUnderlineType(toRend) = _XmRendUnderlineType(fromRend); _XmRendStrikethruType(toRend) = _XmRendStrikethruType(fromRend); } /* As above, except only change resources in toRend that are default. */ static void MergeInto(XmRendition toRend, XmRendition fromRend) { _XmRendTag(toRend) = _XmStringCacheTag(_XmRendTag(fromRend), XmSTRING_TAG_STRLEN); if ((_XmRendFontName(toRend) == NULL) && NameIsString(_XmRendFontName(fromRend))) _XmRendFontName(toRend) = XtNewString(_XmRendFontName(fromRend)); if (_XmRendFontType(toRend) == XmAS_IS) _XmRendFontType(toRend) = _XmRendFontType(fromRend); if (_XmRendLoadModel(toRend) == XmAS_IS) _XmRendLoadModel(toRend) = _XmRendLoadModel(fromRend); if (_XmRendFont(toRend) == NULL) _XmRendFont(toRend) = _XmRendFont(fromRend); if (!ListIsList(_XmRendTabs(toRend)) && ListIsList(_XmRendTabs(fromRend))) _XmRendTabs(toRend) = XmTabListCopy(_XmRendTabs(fromRend), 0, 0); if (_XmRendBG(toRend) == XmUNSPECIFIED_PIXEL) _XmRendBG(toRend) = _XmRendBG(fromRend); if (_XmRendFG(toRend) == XmUNSPECIFIED_PIXEL) _XmRendFG(toRend) = _XmRendFG(fromRend); if (_XmRendUnderlineType(toRend) == XmAS_IS) _XmRendUnderlineType(toRend) = _XmRendUnderlineType(fromRend); if (_XmRendUnderlineType(toRend) == XmAS_IS) _XmRendStrikethruType(toRend) = _XmRendStrikethruType(fromRend); } /* Make a Clone--new handle and new data structure--of a rendition. */ static XmRendition CloneRendition(XmRendition rend) { _XmRendition copy; XmRendition copy_handle; if (rend == NULL) return(NULL); copy = (_XmRendition)XtMalloc(sizeof(_XmRenditionRec)); bzero((char*)copy, sizeof(_XmRenditionRec)); copy_handle = GetHandle(_XmRendition); SetPtr(copy_handle, copy); _XmRendFontOnly(copy_handle) = FALSE; _XmRendRefcount(copy_handle) = 1; CopyInto(copy_handle, rend); return(copy_handle); } /* Set the old handle to point to a new data structure. */ static XmRendition RenewRendition(XmRendition rend) { _XmRendition copy; if (rend == NULL) return(NULL); copy = (_XmRendition)XtMalloc(sizeof(_XmRenditionRec)); memcpy((char *)copy, (char *)GetPtr(rend), sizeof(_XmRenditionRec)); SetPtr(rend, copy); _XmRendFontOnly(rend) = FALSE; _XmRendRefcount(rend) = 1; return(rend); } /* Allocate a new handle which points to the old data structure with */ /* an incremented refcount. */ static XmRendition CopyRendition(XmRendition rend) { XmRendition copy; if (rend == NULL) return(NULL); if (_XmRendRefcountInc(rend) == 0) { _XmRendRefcountDec(rend); return(CloneRendition(rend)); } else { copy = GetHandle(_XmRendition); SetPtr(copy, GetPtr(rend)); return(copy); } } /* Increment the refcount. Clone if overflow. */ static XmRendition DuplicateRendition(XmRendition rend) { if (rend == NULL) return(NULL); if (_XmRendRefcountInc(rend) == 0) { _XmRendRefcountDec(rend); return(CloneRendition(rend)); } else { return(rend); } } /* Make a copy of a rendition, *including* the "scratch" info (tags, * GC, hadEnds). * Shared indicates whether or not this is a shared copy. */ XmRendition _XmRenditionCopy(XmRendition rend, Boolean shared) { XmRendition toRend; int i; if (rend == NULL) return(NULL); if (shared) toRend = CopyRendition(rend); else toRend = CloneRendition(rend); /* If we had to clone, copy the 'scratch' info. */ if (*toRend != *rend) { _XmRendGC(toRend) = _XmRendGC(rend); _XmRendTagCount(toRend) = _XmRendTagCount(rend); _XmRendHadEnds(toRend) = _XmRendHadEnds(rend); _XmRendTags(toRend) = (XmStringTag *)XtMalloc(sizeof(XmStringTag) * _XmRendTagCount(rend)); for (i = 0; i < _XmRendTagCount(rend); i++) _XmRendTags(toRend)[i] = _XmRendTags(rend)[i]; } return(toRend); } /* Creates new rendertable, adding any new renditions. */ /* Mutate rendertable. Copy renditions. */ XmRenderTable XmRenderTableAddRenditions(XmRenderTable oldtable, XmRendition *renditions, Cardinal rendition_count, XmMergeMode merge_mode) { int i, next; int count = rendition_count; XmRendition rend, match; _XmRenderTable table; XmRenderTable newtable, tmptable = NULL; Boolean *matches; short idx; XtAppContext app=NULL; if ((renditions == NULL) || (rendition_count == 0)) return(oldtable); #ifdef XTHREADS if (_XmRendDisplay(renditions[0])) app = XtDisplayToApplicationContext(_XmRendDisplay(renditions[0])); if (app) { _XmAppLock(app); } else { _XmProcessLock(); } #endif if (oldtable == NULL) { /* Malloc new table */ table = (_XmRenderTable)XtMalloc(sizeof(_XmRenderTableRec) + (sizeof(XmRendition) * (rendition_count - RENDITIONS_IN_STRUCT))); oldtable = GetHandle(_XmRenderTable); SetPtr(oldtable, table); _XmRTCount(oldtable) = rendition_count; _XmRTDisplay(oldtable) = NULL; _XmRTRefcount(oldtable) = 1; /* Copy renditions */ for (i = 0; i < rendition_count; i++) { _XmRTRenditions(oldtable)[i] = CopyRendition(renditions[i]); if (_XmRTDisplay(oldtable) == NULL) _XmRTDisplay(oldtable) = _XmRendDisplay(renditions[i]); } } else { matches = (Boolean *)ALLOCATE_LOCAL(rendition_count * sizeof(Boolean)); bzero(matches, rendition_count * sizeof(Boolean)); /* May have to copy table if shared. */ if (_XmRTRefcount(oldtable) > 1) { /* Allocate new table */ table = (_XmRenderTable) XtMalloc(sizeof(_XmRenderTableRec) + (sizeof(XmRendition) * (_XmRTCount(oldtable) - RENDITIONS_IN_STRUCT))); newtable = GetHandle(_XmRenderTable); SetPtr(newtable, table); _XmRTDisplay(newtable) = _XmRTDisplay(oldtable); _XmRTRefcount(newtable) = 1; /* Move old Renditions. */ for (i = 0; i < _XmRTCount(oldtable); i++) _XmRTRenditions(newtable)[i] = _XmRTRenditions(oldtable)[i]; _XmRTCount(newtable) = _XmRTCount(oldtable); _XmRTRefcountDec(oldtable); /* Free at end so we don't get same memory from malloc. */ tmptable = oldtable; oldtable = newtable; } /* Merge matching renditions */ for (i = 0; i < rendition_count; i++) { rend = renditions[i]; match = _XmRenderTableFindRendition(oldtable, _XmRendTag(rend), TRUE, FALSE, FALSE, &idx); if ((match != NULL) && (merge_mode != XmDUPLICATE)) { /* Merge renditions. */ switch (merge_mode) { case XmMERGE_REPLACE: if (FreeRendition(match)) FreeHandle(match); _XmRTRenditions(oldtable)[idx] = CopyRendition(rend); break; case XmSKIP: break; case XmMERGE_OLD: if (_XmRendRefcount(match) > 1) { match = CloneRendition(match); _XmRTRenditions(oldtable)[idx] = match; } MergeInto(match, rend); break; case XmMERGE_NEW: rend = CloneRendition(rend); MergeInto(rend, match); _XmRTRenditions(oldtable)[idx] = rend; if (FreeRendition(match)) FreeHandle(match); break; default: printf("NYI"); break; } matches[i] = TRUE; --count; } } if (count > 0) /* Allocate new table */ { table = (_XmRenderTable) XtMalloc(sizeof(_XmRenderTableRec) + (sizeof(XmRendition) * (_XmRTCount(oldtable) + count - RENDITIONS_IN_STRUCT))); newtable = GetHandle(_XmRenderTable); SetPtr(newtable, table); _XmRTDisplay(newtable) = _XmRTDisplay(oldtable); _XmRTRefcount(newtable) = 1; /* Move old Renditions. */ for (i = 0; i < _XmRTCount(oldtable); i++) _XmRTRenditions(newtable)[i] = _XmRTRenditions(oldtable)[i]; /* Copy new renditions. */ next = _XmRTCount(oldtable); for (i = 0; i < rendition_count; i++) { if (!matches[i]) { _XmRTRenditions(newtable)[next] = CopyRendition(renditions[i]); if (_XmRTDisplay(newtable) == NULL) _XmRTDisplay(newtable) = _XmRTDisplay(oldtable); ++next; } } _XmRTCount(newtable) = _XmRTCount(oldtable) + count; /* Deallocate oldtable */ XtFree((char *)GetPtr(oldtable)); FreeHandle(oldtable); } /* Otherwise just return newhandle to oldtable */ else { table = GetPtr(oldtable); newtable = GetHandle(_XmRenderTable); SetPtr(newtable, table); FreeHandle(oldtable); } DEALLOCATE_LOCAL((char *)matches); oldtable = newtable; } if (tmptable != NULL) FreeHandle(tmptable); #ifdef XTHREADS if (app) { _XmAppUnlock(app); } else { _XmProcessUnlock(); } #endif return(oldtable); } /* Remove matching renditions. */ /* Mutates oldtable, decrements removed renditions. */ XmRenderTable XmRenderTableRemoveRenditions(XmRenderTable oldtable, XmStringTag *tags, int tag_count) { XmRenderTable ret_val; #ifdef XTHREADS XtAppContext app=NULL; if (_XmRTDisplay(oldtable)) app = XtDisplayToApplicationContext(_XmRTDisplay(oldtable)); if (app) { _XmAppLock(app); } else { _XmProcessLock(); } #endif ret_val = _XmRenderTableRemoveRenditions(oldtable, tags,tag_count, FALSE, XmFONT_IS_FONT, NULL); #ifdef XTHREADS if (app) { _XmAppUnlock(app); } else { _XmProcessUnlock(); } #endif return ret_val; } /* Remove matching renditions. */ /* Mutates oldtable, decrements removed renditions. */ /* If chk_font TRUE, checks that font and type also match. */ XmRenderTable _XmRenderTableRemoveRenditions(XmRenderTable oldtable, XmStringTag *tags, int tag_count, #if NeedWidePrototypes int chk_font, #else Boolean chk_font, #endif /* NeedWidePrototypes */ XmFontType type, XtPointer font) { int i, j; int count; _XmRenderTable table; XmRenderTable newtable = NULL; if ((oldtable == NULL) || (tags == NULL) || (tag_count == 0)) return(oldtable); count = 0; if (_XmRTRefcount(oldtable) > 1) { /* Allocate new table */ table = (_XmRenderTable) XtMalloc(sizeof(_XmRenderTableRec) + (sizeof(XmRendition) * (_XmRTCount(oldtable) - RENDITIONS_IN_STRUCT))); newtable = GetHandle(_XmRenderTable); SetPtr(newtable, table); _XmRTDisplay(newtable) = _XmRTDisplay(oldtable); _XmRTRefcount(newtable) = 1; /* Move old Renditions. */ for (i = 0; i < _XmRTCount(oldtable); i++) _XmRTRenditions(newtable)[i] = _XmRTRenditions(oldtable)[i]; _XmRTCount(newtable) = _XmRTCount(oldtable); if (_XmRTRefcountDec(oldtable) == 0) XtFree((char *)GetPtr(oldtable)); FreeHandle(oldtable); oldtable = newtable; } /* Iterate over renditions */ for (i = 0; i < _XmRTCount(oldtable); i++) { /* Match against tags */ for (j = 0; j < tag_count; j++) { if ((strcmp(_XmRendTag(_XmRTRenditions(oldtable)[i]), tags[j]) == 0) && (!chk_font || ((font == _XmRendFont(_XmRTRenditions(oldtable)[i])) && (type == _XmRendFontType(_XmRTRenditions(oldtable)[i]))))) { if (FreeRendition(_XmRTRenditions(oldtable)[i])) FreeHandle(_XmRTRenditions(oldtable)[i]); _XmRTRenditions(oldtable)[i] = NULL; break; } } if (_XmRTRenditions(oldtable)[i] != NULL) { if (count != i) _XmRTRenditions(oldtable)[count] = _XmRTRenditions(oldtable)[i]; count++; } } if (count == 0) /* No renditions left. Return NULL. */ { XmRenderTableFree(oldtable); return(NULL); } else if (count < _XmRTCount(oldtable)) { /* Realloc table */ table = (_XmRenderTable)XtRealloc((char *)*oldtable, sizeof(_XmRenderTableRec) + (sizeof(XmRendition) * (count - RENDITIONS_IN_STRUCT))); if (newtable == NULL) { newtable = GetHandle(_XmRenderTable); FreeHandle(oldtable); } SetPtr(newtable, table); _XmRTCount(newtable) = count; return(newtable); } return(oldtable); } static void CopyFromArg(XtArgVal src, char *dst, unsigned int size) { if (size > sizeof(XtArgVal)) memcpy((char *)dst, (char *)src, (size_t)size); else { union { long longval; short shortval; char charval; char* charptr; XtPointer ptr; } u; char *p = (char*)&u; if (size == sizeof(long)) u.longval = (long)src; else if (size == sizeof(short)) u.shortval = (short)src; else if (size == sizeof(char)) u.charval = (char)src; else if (size == sizeof(XtPointer)) u.ptr = (XtPointer)src; else if (size == sizeof(char*)) u.charptr = (char*)src; else p = (char*)&src; memcpy((char *)dst, p, (size_t)size); } } /* CopyFromArg */ static void CopyToArg(char *src, XtArgVal *dst, unsigned int size) { if ((void *)(*dst) == NULL) { /* old GetValues semantics (storing directly into arglists) are bad, * but preserve for compatibility as long as arglist contains NULL. */ if (size == sizeof(long)) *dst = (XtArgVal)*(long*)src; else if (size == sizeof(short)) *dst = (XtArgVal)*(short*)src; else if (size == sizeof(char)) *dst = (XtArgVal)*(char*)src; else if (size == sizeof(XtPointer)) *dst = (XtArgVal)*(XtPointer*)src; else if (size == sizeof(char*)) *dst = (XtArgVal)*(char**)src; else if (size == sizeof(XtArgVal)) *dst = *(XtArgVal*)src; else memcpy((char*)dst, (char*)src, (size_t)size); } else { /* proper GetValues semantics: argval is pointer to destination */ if (size == sizeof(long)) *((long*)*dst) = *(long*)src; else if (size == sizeof(short)) *((short*)*dst) = *(short*)src; else if (size == sizeof(char)) *((char*)*dst) = *(char*)src; else if (size == sizeof(XtPointer)) *((XtPointer*)*dst) = *(XtPointer*)src; else if (size == sizeof(char*)) *((char**)*dst) = *(char**)src; else if (size == sizeof(XtArgVal)) *((XtArgVal*)*dst)= *(XtArgVal*)src; else memcpy((char *)*dst, (char *)src, (size_t)size); } } /* CopyToArg */ /* Copies renditions matching tags to a new table. */ /* If all renditions copied then duplicate rendertable, duplicate */ /* renditions. Otherwise, mutate rendertable, duplicate renditions. */ XmRenderTable XmRenderTableCopy(XmRenderTable table, XmStringTag *tags, int tag_count) { XmRenderTable rt; _XmRenderTable t; int i, j, count; int size; XmRendition rend; XtAppContext app = NULL; if (table == NULL) return((XmRenderTable)NULL); #ifdef XTHREADS if (_XmRTDisplay(table)) app = XtDisplayToApplicationContext(_XmRTDisplay(table)); if (app) { _XmAppLock(app); } else { _XmProcessLock(); } #endif count = 0; if ((_XmRTRefcountInc(table) == 0) || (tags != NULL)) { /* Malloc new table */ _XmRTRefcountDec(table); if (tag_count > 0) size = (sizeof(_XmRendition) * (tag_count - RENDITIONS_IN_STRUCT)); else size = (sizeof(_XmRendition) * (_XmRTCount(table) - RENDITIONS_IN_STRUCT)); size = (size < 0) ? 0 : size; t = (_XmRenderTable)XtMalloc(sizeof(_XmRenderTableRec) + size); rt = GetHandle(_XmRenderTable); SetPtr(rt, t); _XmRTRefcount(rt) = 1; } if (tags == NULL) { /* Increment renditions. */ for (i = 0; i < _XmRTCount(table); i++) { rend = DuplicateRendition(_XmRTRenditions(table)[i]); /* Check for overflow. */ if (rend != _XmRTRenditions(table)[i]) break; } if (i < _XmRTCount(table)) /* Overflow! */ { /* Malloc new table. */ t = (_XmRenderTable)XtMalloc(sizeof(_XmRenderTableRec) + (sizeof(_XmRendition) * (_XmRTCount(table) - RENDITIONS_IN_STRUCT))); rt = GetHandle(_XmRenderTable); SetPtr(rt, t); _XmRTRefcount(rt) = 1; _XmRTCount(rt) = _XmRTCount(table); /* Move renditions done already. */ for (j = 0; j < i; j++) _XmRTRenditions(rt)[j] = _XmRTRenditions(table)[j]; _XmRTRenditions(rt)[i] = rend; /* Copy rest */ for (j = i + 1; j < _XmRTCount(rt); j++) _XmRTRenditions(rt)[j] = DuplicateRendition(_XmRTRenditions(table)[j]); } else { rt = GetHandle(_XmRenderTable); SetPtr(rt, GetPtr(table)); } } else { /* Copy matching renditions. */ for (i = 0; i < tag_count; i++) { XmRendition match; match = XmRenderTableGetRendition(table, tags[i]); if (match != NULL) { _XmRTRenditions(rt)[i] = match; ++count; } } /* Realloc table */ t = (_XmRenderTable)XtRealloc((char *)t, sizeof(_XmRenderTableRec) + (sizeof(XmRendition) * (count - RENDITIONS_IN_STRUCT))); SetPtr(rt, t); _XmRTCount(rt) = count; } _XmRTDisplay(rt) = _XmRTDisplay(table); #ifdef XTHREADS if (app) { _XmAppUnlock(app); } else { _XmProcessUnlock(); } #endif return(rt); } /* Decrement rendertable, free if refcount is zero. XmRenditionFree */ /* renditions. */ void XmRenderTableFree(XmRenderTable table) { int i; _XmProcessLock(); for (i = 0; i < _XmRTCount(table); i++) if (FreeRendition(_XmRTRenditions(table)[i])) FreeHandle(_XmRTRenditions(table)[i]); if (_XmRTRefcountDec(table) == 0) XtFree((char *)GetPtr(table)); FreeHandle(table); _XmProcessUnlock(); } /* Get list of tags of all renditions in table. */ int XmRenderTableGetTags(XmRenderTable table, XmStringTag **tag_list) { int i, ret_val; XtAppContext app = NULL; if (table == NULL) { *tag_list = NULL; return(0); } app = XtDisplayToApplicationContext(_XmRTDisplay(table)); _XmAppLock(app); *tag_list = (XmStringTag *)XtMalloc(sizeof(XmStringTag) * _XmRTCount(table)); for (i = 0; i < _XmRTCount(table); i++) (*tag_list)[i] = XtNewString(_XmRendTag(_XmRTRenditions(table)[i])); ret_val = _XmRTCount(table); _XmAppUnlock(app); return ret_val; } /* Returns copy of matching rendition. */ XmRendition XmRenderTableGetRendition(XmRenderTable table, XmStringTag tag) { XmRendition ret_val; _XmDisplayToAppContext(_XmRTDisplay(table)); _XmAppLock(app); ret_val = CopyRendition(_XmRenderTableFindRendition(table, tag, FALSE, FALSE, FALSE, NULL)); _XmAppUnlock(app); return ret_val; } /* Returns array of copies of matching renditions. */ XmRendition * XmRenderTableGetRenditions(XmRenderTable table, char **tags, Cardinal tag_count) { XmRendition rend, *rends; int i, count; XtAppContext app = NULL; if ((table == NULL) || (tags == NULL) || (tag_count == 0)) return(NULL); #ifdef XTHREADS if (_XmRTDisplay(table)) { app = XtDisplayToApplicationContext(_XmRTDisplay(table)); _XmAppLock(app); } #endif rends = (XmRendition *)XtMalloc(tag_count * sizeof(XmRendition)); count = 0; for (i = 0; i < tag_count; i++) { rend = _XmRenderTableFindRendition(table, tags[i], FALSE, FALSE, FALSE, NULL); if (rend != NULL) { rends[count] = CopyRendition(rend); count++; } } if (count < tag_count) rends = (XmRendition *)XtRealloc((char *)rends, count * sizeof(XmRendition)); #ifdef XTHREADS if (app) { _XmAppUnlock(app); } #endif return(rends); } /* Wrapper for calling XtWarning functions. */ static void RenditionWarning(char *tag, char *type, char *message, Display *dpy) { char *params[1]; Cardinal num_params = 1 ; Display *d; /* the MotifWarningHandler installed in VendorS.c knows about this convention */ params[0] = XME_WARNING; if (dpy) d = dpy; else d = _XmGetDefaultDisplay(); if (d) XtAppWarningMsg (XtDisplayToApplicationContext(d), tag, type, "XmRendition", message, params, &num_params); else XtWarning(message); } /* Replace XmAS_IS and copy as necessary. */ static void CleanupResources(XmRendition rend, Boolean copy) { if ((unsigned int)(unsigned long)_XmRendFont(rend) == XmAS_IS) _XmRendFont(rend) = NULL; else if (_XmRendFontType(rend) == XmAS_IS) _XmRendFontType(rend) = XmFONT_IS_FONT; if (((unsigned int)(unsigned long)_XmRendFontName(rend) == XmAS_IS) || (strcmp(_XmRendFontName(rend), XmSXmAS_IS) == 0)) _XmRendFontName(rend) = NULL; else if (copy) _XmRendFontName(rend) = XtNewString(_XmRendFontName(rend)); if ((unsigned int)(unsigned long)_XmRendTabs(rend) == XmAS_IS) _XmRendTabs(rend) = NULL; else if (copy) _XmRendTabs(rend) = XmTabListCopy(_XmRendTabs(rend), 0, 0); } /* Emit warning and set default if tag is NULL. */ static void ValidateTag(XmRendition rend, XmStringTag dflt) { if (_XmRendTag(rend) == NULL) { RenditionWarning(_XmRendTag(rend), "NO_NULL_TAG", NO_NULL_TAG_MSG, _XmRendDisplay(rend)); _XmRendTag(rend) = _XmStringCacheTag(dflt, XmSTRING_TAG_STRLEN); } } /* Make sure all the font related resources make sense together and */ /* then load the font specified by fontName if necessary. */ static void ValidateAndLoadFont(XmRendition rend, Display *display) { XrmString locale; XtPointer font; XrmValue args[2]; Cardinal num_args = 0; XrmValue fromVal; XrmValue toVal; Boolean result = False; _XmRendDisplay(rend) = display; if (_XmRendLoadModel(rend) != XmLOAD_DEFERRED) { XmDisplay dsp = NULL; XmDisplayCallbackStruct cb; if ((_XmRendFont(rend) == NULL) && (_XmRendFontName(rend) != NULL)) { if (_XmRendFontType(rend) != XmAS_IS) { if (display == NULL) { RenditionWarning(_XmRendTag(rend), "NULL_DISPLAY", NULL_DISPLAY_MSG, NULL); return; } args[0].addr = (XPointer) &display; args[0].size = sizeof(Display*); num_args++; fromVal.addr = _XmRendFontName(rend); fromVal.size = strlen(_XmRendFontName(rend)); toVal.addr = (XPointer) &font; toVal.size = sizeof (XtPointer); switch (_XmRendFontType(rend)) { case XmFONT_IS_FONT: result = XtCallConverter(display, XtCvtStringToFontStruct, args, num_args, &fromVal, &toVal, NULL); break; case XmFONT_IS_FONTSET: locale = XrmQuarkToString(XrmStringToQuark(setlocale(LC_ALL, NULL))); args[1].addr = (XPointer) &locale; args[1].size = sizeof(XrmString); num_args++; result = XtCallConverter (display, XtCvtStringToFontSet, args, num_args, &fromVal, &toVal, NULL); break; default: RenditionWarning(_XmRendTag(rend), "INVALID_TYPE", INVALID_TYPE_MSG, _XmRendDisplay(rend)); break; } /* NoFontCallback. */ if (!result) { if (display != NULL) { dsp = (XmDisplay) XmGetXmDisplay(display); cb.reason = XmCR_NO_FONT; cb.event = NULL; cb.rendition = rend; cb.font_name = _XmRendFontName(rend); /* We must know for sure whether there are any */ /* callbacks, so we have to use XtHasCallbacks. */ if (XtHasCallbacks((Widget)dsp, XmNnoFontCallback) == XtCallbackHasSome) { XtCallCallbackList((Widget)dsp, dsp->display.noFontCallback, &cb); return; } } RenditionWarning(_XmRendTag(rend), "CONVERSION_FAILED", CONVERSION_FAILED_MSG, _XmRendDisplay(rend)); } else { _XmRendFont(rend) = font; } } else { RenditionWarning(_XmRendTag(rend), "NULL_FONT_TYPE", NULL_FONT_TYPE_MSG, _XmRendDisplay(rend)); } } else if ((_XmRendLoadModel(rend) == XmLOAD_IMMEDIATE) && (_XmRendFont(rend) == NULL) && (_XmRendFontName(rend) == NULL)) { RenditionWarning(_XmRendTag(rend), "NULL_LOAD_IMMEDIATE", NULL_LOAD_IMMEDIATE_MSG, _XmRendDisplay(rend)); } } } /* Create new rendition. */ XmRendition XmRenditionCreate(Widget widget, XmStringTag tag, ArgList arglist, Cardinal argcount) { XmRendition ret_val; XtAppContext app=NULL; /* If cannot applock, assume its an internal call (from * fontlist code, etc.) and already process locked. */ if (widget) app = XtWidgetToApplicationContext(widget); if (app) { _XmAppLock(app); } else { _XmProcessLock(); } ret_val = _XmRenditionCreate(NULL, widget, XmS, XmCRenderTable, tag, arglist, argcount, NULL); if (app) { _XmAppUnlock(app); } else { _XmProcessUnlock(); } return ret_val; } /* Internal function. Called from XmRenditionCreate, resource */ /* converter, and Mrm create function. */ XmRendition _XmRenditionCreate(Display *display, Widget widget, String resname, String resclass, XmStringTag tag, ArgList arglist, Cardinal argcount, Boolean *in_db) { XmRendition rend; _XmRendition rend_int; Boolean result; if ((display == NULL) && (widget != NULL)) display = XtDisplayOfObject(widget); if ((tag != NULL) && (tag != XmFONTLIST_DEFAULT_TAG) && (strcmp(tag, XmSTRING_DEFAULT_CHARSET) == 0)) tag = _XmStringGetCurrentCharset(); /* Allocate rendition. */ rend_int = (_XmRendition)XtMalloc(sizeof(_XmRenditionRec)); bzero((char*)rend_int, sizeof(_XmRenditionRec)); rend = GetHandle(_XmRendition); SetPtr(rend, rend_int); _XmRendRefcount(rend) = 1; /* For now, FontOnly renditions aren't implemented. */ _XmRendFontOnly(rend) = FALSE; /* X resource DB query */ result = GetResources(rend, display, widget, resname, resclass, tag, arglist, argcount); if (in_db != NULL) *in_db = result; if (tag == NULL) { if (result == FALSE) { XtFree((char *)rend_int); FreeHandle(rend); return(NULL); } else tag = _MOTIF_DEFAULT_LOCALE; } _XmRendTag(rend) = _XmStringCacheTag(tag, XmSTRING_TAG_STRLEN); /* Cleanup and validate resources. */ CleanupResources(rend, TRUE); ValidateTag(rend, XmS); ValidateAndLoadFont(rend, display); return(rend); } /* Mrm create function for rendertables. */ /*ARGSUSED*/ Widget _XmCreateRenderTable(Widget parent, String name, /* unused */ ArgList arglist, /* unused */ Cardinal argcount) /* unused */ { XmRenderTable newtable; _XmRenderTable table; /* Malloc new table */ table = (_XmRenderTable)XtMalloc(sizeof(_XmRenderTableRec)); newtable = GetHandle(_XmRenderTable); SetPtr(newtable, table); _XmRTCount(newtable) = 0; _XmRTRefcount(newtable) = 1; _XmRTDisplay(newtable) = XtDisplay(parent); return((Widget)newtable); } /* Mrm create function for renditions. */ Widget _XmCreateRendition(Widget parent, String name, ArgList arglist, Cardinal argcount) { XmRenderTable rt = (XmRenderTable)parent; _XmRenderTable table; XmRendition rend; table = GetPtr(rt); rend = _XmRenditionCreate(_XmRTDisplay(rt), NULL, XmS, XmCRenderTable, name, arglist, argcount, NULL); /* Ignore repeats */ if (_XmRenderTableFindRendition(rt, _XmRendTag(rend), TRUE, FALSE, FALSE, NULL) != NULL) { if (FreeRendition(rend)) FreeHandle(rend); return((Widget)NULL); } table = (_XmRenderTable) XtRealloc((char *)table, sizeof(_XmRenderTableRec) + (sizeof(XmRendition) * ((_XmRTCount(rt) + 1) - RENDITIONS_IN_STRUCT))); SetPtr(rt, table); /* Copy new rendition. */ _XmRTRenditions(rt)[_XmRTCount(rt)] = CopyRendition(rend); _XmRTCount(rt)++; return((Widget)rend); } /* Free data structure and any copied values. */ /* TRUE return -> freed. FALSE -> just decremented. */ static Boolean FreeRendition(XmRendition rendition) { if (rendition == NULL) return(FALSE); if (_XmRendRefcountDec(rendition) == 0) { /* CR 7890 - the fontName might be XmAS_IS here */ if (NameIsString(_XmRendFontName(rendition))) XtFree(_XmRendFontName(rendition)); if (ListIsList(_XmRendTabs(rendition))) XmTabListFree(_XmRendTabs(rendition)); if (_XmRendTagCount(rendition) != 0) XtFree((char *)_XmRendTags(rendition)); XtFree((char *)GetPtr(rendition)); return(TRUE); } return(FALSE); } void XmRenditionFree(XmRendition rendition) { XtAppContext app; if (rendition == NULL) return; _XmProcessLock(); FreeRendition(rendition); FreeHandle(rendition); _XmProcessUnlock(); } /* Get resource values from rendition. */ void XmRenditionRetrieve(XmRendition rendition, ArgList arglist, Cardinal argcount) { int i, j; Arg *arg; XtResource *res; char *as_is = (char *)XmAS_IS; if (rendition == NULL) return; _XmProcessLock(); /* Get resources */ for (i = 0; i < argcount; i++) { arg = &(arglist[i]); for (j = 0; j < _XmNumRenditionResources; j++) { res = &(_XmRenditionResources[j]); if (strcmp(res->resource_name, arg->name) == 0) { /* CR 7890: Font hook - if there's a fontName but the ** font hasn't been fetched yet, now's a good time to ** get it - if the caller wants to use the font to, say, ** compute font metrics for layout (as CSText does), it won't ** like to get NULL back */ if (strcmp(res->resource_name, XmNfont) == 0) { if ((_XmRendFont(rendition) == NULL) && (_XmRendFontName(rendition) != NULL)) { if (_XmRendLoadModel(rendition) == XmLOAD_DEFERRED) _XmRendLoadModel(rendition) = XmLOAD_IMMEDIATE; ValidateAndLoadFont(rendition, _XmRendDisplay(rendition)); } if (_XmRendFont(rendition) == NULL) CopyToArg((char*)&as_is, &(arg->value), sizeof(char*)); else CopyToArg(((char *)GetPtr(rendition) + res->resource_offset), &(arg->value), res->resource_size); } else if (((strcmp(res->resource_name, XmNfontName) == 0) && (_XmRendFontName(rendition) == NULL)) || ((strcmp(res->resource_name, XmNtabList) == 0) && (_XmRendTabs(rendition) == NULL))) CopyToArg((char*)&as_is, &(arg->value), sizeof(char*)); else CopyToArg(((char *)GetPtr(rendition) + res->resource_offset), &(arg->value), res->resource_size); break; } } } _XmProcessUnlock(); } /* Set resources in rendition. */ /* Renew rendition if necessary, then update resources. */ void XmRenditionUpdate(XmRendition rendition, ArgList arglist, Cardinal argcount) { XmStringTag oldtag; char *oldname; XtPointer oldfont; XmTabList oldtabs; int i, j; XtResource *res; Arg *arg; Display *display = _XmGetDefaultDisplay(); Boolean can_free; XtAppContext app = NULL; if (rendition == NULL) return; #ifdef XTHREADS if (_XmRendDisplay(rendition)) { app = XtDisplayToApplicationContext(_XmRendDisplay(rendition)); _XmAppLock(app); } if (_XmRendDisplay(rendition) && (_XmRendDisplay(rendition) != display) ) display = _XmRendDisplay(rendition); #endif /* Save old values to check for dependencies and free memory. */ oldtag = _XmRendTag(rendition); oldname = _XmRendFontName(rendition); oldfont = _XmRendFont(rendition); oldtabs = _XmRendTabs(rendition); can_free = TRUE; /* New memory if needed. */ if (_XmRendRefcount(rendition) > 1) { _XmRendRefcountDec(rendition); RenewRendition(rendition); can_free = FALSE; } for (i = 0; i < argcount; i++) { arg = &(arglist[i]); for (j = 0; j < _XmNumRenditionResources; j++) { res = &(_XmRenditionResources[j]); if (strcmp(res->resource_name, arg->name) == 0) { CopyFromArg((arg->value), ((char *)GetPtr(rendition) + res->resource_offset), res->resource_size); break; } } } CopyInto(rendition, rendition); /** Validate resources **/ /* CR 7890 - handle cases of fontName == NULL and fontName == XmAS_IS */ /* If fontName changed but not font, NULL font so it's updated. ** (first make sure we won't crash on the strcmp) */ if (NameIsString(oldname) && NameIsString(_XmRendFontName(rendition))) { if (strcmp(oldname, _XmRendFontName(rendition)) != 0) { if (oldfont == _XmRendFont(rendition)) _XmRendFont(rendition) = NULL; } if (can_free) XtFree(oldname); } /* Also handle the case where we started with a NULL fontName and ** had a real fontName specified */ else if ((oldname == NULL) && NameIsString(_XmRendFontName(rendition))) { if (oldfont == _XmRendFontName(rendition)) _XmRendFont(rendition) = NULL; } if (_XmRendFont(rendition) == (XtPointer)XmAS_IS) _XmRendFont(rendition) = NULL; if ((oldtabs != _XmRendTabs(rendition)) && can_free) XmTabListFree(oldtabs); ValidateTag(rendition, oldtag); ValidateAndLoadFont(rendition, display); #ifdef XTHREADS if (app) { _XmAppUnlock(app); } #endif } /*****************************************************************************/ /* XmRenderTableCvtToProp takes a rendertable and converts it to */ /* an ascii string in the following format: */ /* tag : char* */ /* font : either fontid (integer) or [ fontid, fontid ... fontid ] or -1 */ /* tablist : [ tab1, ... tabn ] or -1 */ /* background : pixel or -1 */ /* foreground : pixel or -1 */ /* underlineType : integer (from enum in Xm.h ) or -1 */ /* strikethruType : integer (from enum in Xm.h ) or -1 */ /* */ /* example: */ /* "tag, font, tablist, background, foreground, underlineType, */ /* strikethruType\n */ /* bold, 10000031, -1, -1, -1, -1, -1\n */ /* underline, 10000029, -1, -1, -1, -1, -1\n */ /* default, 10000029, [ 1.234 1 0 0, 2.43 2 0 2], 1, 2, 0, 0\n */ /* japanese, [10000029, 10000030], -1, -1, -1, -1, -1" */ /* */ /* The first line gives a complete list of the attributes by name. */ /* on the destination side, attributes which are not understood */ /* or are outdated can be ignored. The conversion of each rendition */ /* passes a single "line" which contains the fields in order. */ /*****************************************************************************/ /* Note that this MUST be in the same order as the output conversion below!! */ static XmConst char *CVTproperties[] = { XmNtag, XmNfont, XmNtabList, XmNbackground, XmNforeground, XmNunderlineType, XmNstrikethruType, NULL, }; /* Must be big enough to take all the above strings concatenated with commas separating them */ static char CVTtransfervector[256]; static int CVTtvinited = 0; /* Use this macro to encapsulate the code that extends the output buffer as needed */ #define CVTaddString(dest, src, srcsize)\ {\ if ((chars_used + srcsize) > allocated_size) {\ allocated_size *= 2;\ buffer = XtRealloc(buffer, allocated_size);\ }\ strcat(buffer, src);\ chars_used += srcsize;\ } /*ARGSUSED*/ unsigned int XmRenderTableCvtToProp(Widget widget, /* unused */ XmRenderTable table, char **prop_return) { int i; int allocated_size = 256; int chars_used = 0, size; char *buffer; char *str; XmRendition rendition; _XmWidgetToAppContext(widget); _XmAppLock(app); buffer = XtMalloc(allocated_size); _XmProcessLock(); if (CVTtvinited == 0) { CVTtvinited = 1; strcpy(CVTtransfervector, ""); for(i = 0; CVTproperties[i] != NULL; i++) { strcat(CVTtransfervector, CVTproperties[i]); strcat(CVTtransfervector, ","); } strcat(CVTtransfervector, "\n"); } /* Copy the transfer vector into the output buffer. */ strcpy(buffer, CVTtransfervector); chars_used = strlen(buffer); _XmProcessUnlock(); /* Now iterate over the list of renditions */ for(i = 0; i < _XmRTCount(table); i++) { char temp[2048]; rendition = _XmRTRenditions(table)[i]; sprintf(temp, "\"%s\", ", _XmRendTag(rendition)); size = strlen(temp); CVTaddString(buffer, temp, size); if (_XmRendFontType(rendition) == XmAS_IS) str = "-1, "; else { sprintf(temp, "%d \"%s\" %d,", _XmRendFontType(rendition), _XmRendFontName(rendition), _XmRendLoadModel(rendition)); str = temp; } size = strlen(str); CVTaddString(buffer, str, size); if ((unsigned int)(unsigned long)_XmRendTabs(rendition) == XmAS_IS || _XmRendTabs(rendition) == NULL) str = "-1, "; else { _XmTab tab; _XmTabList tlist; int number; strcpy(temp, "[ "); tlist = (_XmTabList) _XmRendTabs(rendition); number = tlist -> count; tab = (_XmTab) tlist -> start; while(number > 0) { sprintf(temp, "%s %f %d %d %d, ", temp, tab -> value, tab -> units, tab -> alignment, tab -> offsetModel); tab = (_XmTab) tab -> next; number--; } strcat(temp, " ], "); str = temp; } size = strlen(str); CVTaddString(buffer, str, size); if (_XmRendBG(rendition) == XmAS_IS) str = "-1, "; else { sprintf(temp, "%d, ", _XmRendBG(rendition)); str = temp; } size = strlen(str); CVTaddString(buffer, str, size); if (_XmRendFG(rendition) == XmAS_IS) str = "-1, "; else { sprintf(temp, "%d, ", _XmRendFG(rendition)); str = temp; } size = strlen(str); CVTaddString(buffer, str, size); if (_XmRendUnderlineType(rendition) == XmAS_IS) str = "-1, "; else { sprintf(temp, "%d, ", _XmRendUnderlineType(rendition)); str = temp; } size = strlen(str); CVTaddString(buffer, str, size); if (_XmRendStrikethruType(rendition) == XmAS_IS) str = "-1, "; else { sprintf(temp, "%d, ", _XmRendStrikethruType(rendition)); str = temp; } size = strlen(str); CVTaddString(buffer, str, size); CVTaddString(buffer, "\n", size); } /* Return the converted rendertable string */ *prop_return = buffer; _XmAppUnlock(app); /* chars_used is always the size - the NULL terminator */ return(chars_used + 1); } typedef enum { T_NL, T_INT, T_FLOAT, T_SEP, T_OPEN, T_CLOSE, T_STR, T_EOF } TokenType; typedef struct _TokenRec { TokenType type; int integer; float real; char *string; } TokenRec, *Token; #ifndef XTHREADS static TokenRec reusetoken; #endif static Token ReadToken(char *string, int *position) { #ifdef XTHREADS TokenRec reusetoken; Token new_token = &reusetoken; #else Token new_token = &reusetoken; #endif int pos = *position; int count; /* Skip whitespace but not newlines */ while (isspace(string[pos]) && ! (string[pos] == '\n')) pos++; /* Select token type */ switch(string[pos]) { case '\0': new_token -> type = T_EOF; break; case '\n': new_token -> type = T_NL; pos++; break; case ',': new_token -> type = T_SEP; pos++; break; case '[': new_token -> type = T_OPEN; pos++; break; case ']': new_token -> type = T_CLOSE; pos++; break; case '"': /* String result */ count = 1; while (string[pos + count] != '"' && string[pos + count] != '\0') count++; /* Scan for end of string */ new_token -> type = T_STR; new_token -> string = NULL; count -= 1; if (count > 0) { new_token -> string = (char*) XtMalloc(count + 1); strncpy(new_token -> string, &string[pos + 1], count); pos += count + 2; /* Move past end quote */ new_token -> string[count] = 0; /* Null terminate */ } break; default: if (isalpha(string[pos])) /* String result */ { char temp[80]; int count; for(count = 0; isalpha(string[pos + count]) && count < 79; count++) temp[count] = string[pos + count]; temp[count] = 0; pos += count; new_token -> type = T_STR; new_token -> string = XtNewString(temp); } else { /* start converting a float number. If it is exactly integer then we return an int, otherwise return a float */ double result; int intresult; char *newpos; result=strtod(&(string[pos]), &newpos); intresult= (int) result; pos = newpos - string; if (((double) intresult) == result) /* Integer result */ { new_token -> type = T_INT; new_token -> integer = intresult; } else { new_token -> type = T_FLOAT; new_token -> real = (float) result; } } } *position = pos; return(new_token); } /*ARGSUSED*/ XmRenderTable XmRenderTableCvtFromProp(Widget w, char *prop, unsigned int len) /* unused */ { XmRenderTable new_rt; XmRendition rendition; XmRendition *rarray; int rarray_count, rarray_max; /* These must both be big enough for the number of passed parameters */ char *items[20]; char *name; Arg args[20]; /* This must be big enough to hold all the strings returned by readtoken */ char *freelater[5]; int scanpointer, j, count, freecount, i; Token token; _XmWidgetToAppContext(w); _XmAppLock(app); new_rt = NULL; scanpointer = 0; rarray_max = 10; rarray_count = 0; rarray = (XmRendition *) XtMalloc(sizeof(XmRendition) * rarray_max); name = ""; for(j = 0; j < 20; j++) items[j] = NULL; /* Read the list of items */ for(j = 0; j < 20; ) { token = ReadToken(prop, &scanpointer); if (token -> type == T_NL) break; if (token -> type == T_STR) { items[j] = token -> string; j++; } } j = -1; count = 0; freecount = 0; while(True) { token = ReadToken(prop, &scanpointer); /* We skip the separators */ while(token -> type == T_SEP && token -> type != T_EOF) token = ReadToken(prop, &scanpointer); if (token -> type == T_EOF) goto finish; j++; /* Go to next item in items array */ if (items[j] == NULL) { /* End of line processing. Scan for NewLine */ while(token -> type != T_NL && token -> type != T_EOF) token = ReadToken(prop, &scanpointer); /* Store rendition */ rendition = XmRenditionCreate(w, name, args, count); name = ""; count = 0; /* Reset index into namelist */ j = -1; /* Free temp strings returned by ReadToken */ for(i = 0; i < freecount; i++) XtFree(freelater[i]); freecount = 0; /* Record rendition in array */ if (rarray_count >= rarray_max) { /* Extend array if necessary */ rarray_max += 10; rarray = (XmRendition *) XtRealloc((char*) rarray, sizeof(XmRendition) * rarray_max); } if (token -> type == T_EOF) goto finish; rarray[rarray_count] = rendition; rarray_count++; } else if (strcmp(items[j], XmNtag) == 0) { /* Next item should be a string with the name of the new rendition to create */ if (token -> type == T_STR) { name = token -> string; freelater[freecount] = token -> string; freecount++; } else { goto error; } } else if (strcmp(items[j], XmNfont) == 0) { /* If the next item is a number then we have a font id, otherwise we are reading in a fontset */ if (token -> type != T_INT) goto error; if (token -> integer != -1) { /* AS IS */ XtSetArg(args[count], XmNfontType, token -> integer); count++; token = ReadToken(prop, &scanpointer); if (token -> type != T_STR) goto error; XtSetArg(args[count], XmNfontName, token -> string); count++; freelater[freecount] = token -> string; freecount++; token = ReadToken(prop, &scanpointer); if (token -> type != T_INT) goto error; XtSetArg(args[count], XmNloadModel, token -> integer); count++; } } else if (strcmp(items[j], XmNtabList) == 0) { /* This starts with an OPEN then a number of FLOAT INT INT INT then CLOSE and SEP */ if (token -> type == T_INT) { /* Should be AS IS */ if (token -> integer != -1) goto error; } else if (token -> type == T_OPEN) { float value; int units, align; XmOffsetModel model; XmTabList tablist; XmTab tabs[1]; tablist = NULL; token = ReadToken(prop, &scanpointer); while(token -> type != T_CLOSE) { if (token -> type != T_FLOAT && token -> type != T_INT) goto error; if (token -> type == T_FLOAT) value = token -> real; else value = (float) token -> integer; token = ReadToken(prop, &scanpointer); if (token -> type != T_INT) goto error; units = token -> integer; token = ReadToken(prop, &scanpointer); if (token -> type != T_INT) goto error; align = token -> integer; token = ReadToken(prop, &scanpointer); if (token -> type != T_INT) goto error; model = (XmOffsetModel) token -> integer; tabs[0] = XmTabCreate(value, units, model, align, NULL); tablist = XmTabListInsertTabs(tablist, tabs, 1, 1000); XtFree((char*) tabs[0]); /* Go to next separator to skip unknown future values */ while(token -> type != T_SEP) token = ReadToken(prop, &scanpointer); if (token -> type == T_SEP) token = ReadToken(prop, &scanpointer); } XtSetArg(args[count], XmNtabList, tablist); count++; } else goto error; } else if (strcmp(items[j], XmNbackground) == 0) { if (token -> type != T_INT) goto error; if (token -> type != -1) { XtSetArg(args[count], XmNrenditionBackground, token -> integer); count++; } } else if (strcmp(items[j], XmNforeground) == 0) { if (token -> type != T_INT) goto error; if (token -> type != -1) { XtSetArg(args[count], XmNrenditionForeground, token -> integer); count++; } } else if (strcmp(items[j], XmNunderlineType) == 0) { if (token -> type != T_INT) goto error; if (token -> type != -1) { XtSetArg(args[count], XmNunderlineType, token -> integer); count++; } } else if (strcmp(items[j], XmNstrikethruType) == 0) { if (token -> type != T_INT) goto error; if (token -> type != -1) { XtSetArg(args[count], XmNstrikethruType, token -> integer); count++; } } } finish: new_rt = XmRenderTableAddRenditions(new_rt, rarray, rarray_count, XmMERGE_REPLACE); for (i = 0; i < rarray_count; i++) XmRenditionFree(rarray[i]); _XmAppUnlock(app); return(new_rt); error: /* Free temp strings returned by ReadToken */ for(i = 0; i < freecount; i++) XtFree((char*) freelater[i]); freecount = 0; goto finish; }