/* $XConsortium: XmFontList.c /main/16 1996/11/20 15:15:34 drk $ */ /* * @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 */ #include #ifndef X_NOT_STDC_ENV #include #endif #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 #include #include "XmI.h" #include "XmRenderTI.h" #include "XmStringI.h" /* * Data structure macros for fontlist access */ #define FLContextIndex(context) (((XmFontListContextRec *)(context))->index) #define FLContextTable(context) (((XmFontListContextRec *)(context))->table) #define FLContextError(context) (((XmFontListContextRec *)(context))->error) #define FLDisplay(fl) ((*fl)->display) /******** Static Function Declarations ********/ /******** End Static Function Declarations ********/ /* NOTE - this function XmFontListEntryCreate is NOT MT-safe if the application is using threads with multiple application contexts to use Font lists in threaded code with multiple application contexts it is necessary to use the new API XmFontListEntryCreate_r function which passes in an additional widget parameter ... this widget MUST be for the display that font will be used in Font should not be shared between displays in an MT environment */ XmFontListEntry XmFontListEntryCreate( char *tag, XmFontType type , XtPointer font ) { char *derived_tag; Cardinal n; Arg args[4]; XmFontListEntry ret_val; _XmProcessLock(); if ((font == NULL) || (tag == NULL) || ((type != XmFONT_IS_FONTSET) && (type != XmFONT_IS_FONT))) { _XmProcessUnlock(); return (NULL); } if ((tag != XmFONTLIST_DEFAULT_TAG) && (strcmp(tag, XmSTRING_DEFAULT_CHARSET) == 0)) derived_tag = _XmStringGetCurrentCharset(); else derived_tag = tag; n = 0; XtSetArg(args[n], XmNfontType, type); n++; XtSetArg(args[n], XmNloadModel, XmLOAD_IMMEDIATE); n++; XtSetArg(args[n], XmNfont, font); n++; ret_val = XmRenditionCreate(NULL, _XmStringCacheTag(derived_tag, XmSTRING_TAG_STRLEN), args, n); _XmProcessUnlock(); return ret_val; } /* * MT safe version of XmFontList - requires widget parameter * * A display variable is necessary to create a render table in an * MT safe environment * * the widget passed in DOES NOT need to be the widget which uses the * font however it MUST be on the same display * * Fonts can not be shared among displays in an MT environment */ XmFontListEntry XmFontListEntryCreate_r(char *tag, XmFontType type, XtPointer font, Widget wid ) { char *derived_tag; Cardinal n; Arg args[4]; XmFontListEntry ret_val; _XmWidgetToAppContext(wid); _XmAppLock(app); if ((font == NULL) || (tag == NULL) || ((type != XmFONT_IS_FONTSET) && (type != XmFONT_IS_FONT))) { _XmAppUnlock(app); return (NULL); } if ((tag != XmFONTLIST_DEFAULT_TAG) && (strcmp(tag, XmSTRING_DEFAULT_CHARSET) == 0)) derived_tag = _XmStringGetCurrentCharset(); else derived_tag = tag; n = 0; XtSetArg(args[n], XmNfontType, type); n++; XtSetArg(args[n], XmNloadModel, XmLOAD_IMMEDIATE); n++; XtSetArg(args[n], XmNfont, font); n++; ret_val = XmRenditionCreate(wid, _XmStringCacheTag(derived_tag, XmSTRING_TAG_STRLEN), args, n); _XmAppUnlock(app); return ret_val; } void XmFontListEntryFree( XmFontListEntry *entry ) { if (entry != NULL) XmRenditionFree(*entry); } XtPointer XmFontListEntryGetFont( XmFontListEntry entry , XmFontType *typeReturn ) { XtPointer ret_val; Arg args[2]; Cardinal n; XtAppContext app=NULL; if (entry == NULL) return (NULL); #ifdef XTHREADS if ( _XmRendDisplay((XmRendition)entry) ) app = XtDisplayToApplicationContext(_XmRendDisplay((XmRendition)entry)); if (app) _XmAppLock(app); else _XmProcessLock(); #endif n = 0; XtSetArg(args[n], XmNfontType, typeReturn); n++; XtSetArg(args[n], XmNfont, &ret_val); n++; XmRenditionRetrieve(entry, args, n); if (*typeReturn == XmAS_IS) *typeReturn = XmFONT_IS_FONT; if (ret_val == (char *)XmAS_IS) { #ifdef XTHREADS if (app) _XmAppUnlock(app); else _XmProcessUnlock(); #endif return(NULL); } else { #ifdef XTHREADS if (app) _XmAppUnlock(app); else _XmProcessUnlock(); #endif return(ret_val); } } char * XmFontListEntryGetTag( XmFontListEntry entry ) { Cardinal n; Arg args[1]; char *tag; char *ret_val; #ifdef XTHREADS XtAppContext app=NULL; #endif if (entry == NULL) return (NULL); #ifdef XTHREADS if ( _XmRendDisplay((XmRendition)entry) ) app = XtDisplayToApplicationContext(_XmRendDisplay((XmRendition)entry)); if (app) _XmAppLock(app); else _XmProcessLock(); #endif n = 0; XtSetArg(args[n], XmNtag, &tag); n++; XmRenditionRetrieve(entry, args, n); ret_val = XtNewString(tag); #ifdef XTHREADS if (app) _XmAppUnlock(app); else _XmProcessUnlock(); #endif return ret_val; } XmFontList XmFontListAppendEntry( XmFontList old , XmFontListEntry entry ) { XmRendition rends[1]; XmFontList ret_val; #ifdef XTHREADS XtAppContext app=NULL; #endif if (!entry) { return (old); } #ifdef XTHREADS if (_XmRendDisplay((XmRendition)entry)) app = XtDisplayToApplicationContext(_XmRendDisplay((XmRendition)entry)); if (app) _XmAppLock(app); else _XmProcessLock(); #endif rends[0] = entry; ret_val = XmRenderTableAddRenditions(old, rends, 1, XmDUPLICATE); #ifdef XTHREADS if (app) _XmAppUnlock(app); else _XmProcessUnlock(); #endif return ret_val; } XmFontListEntry XmFontListNextEntry( XmFontContext context ) { XmRendition entry; _XmProcessLock(); if ((context == NULL) || (FLContextError(context))) { _XmProcessUnlock(); return (NULL); } if (FLContextIndex(context) >= _XmRTCount(FLContextTable(context))) { FLContextError(context) = TRUE; _XmProcessUnlock(); return (NULL); } entry = _XmRTRenditions(FLContextTable(context))[FLContextIndex(context)]; FLContextIndex(context)++; _XmProcessUnlock(); return((XmFontListEntry)entry); } XmFontList XmFontListRemoveEntry( XmFontList old , XmFontListEntry entry ) { Cardinal n; Arg args[3]; XmStringTag tags[1]; XmFontType type1; XtPointer font1; #ifdef XTHREADS XtAppContext app=NULL; #endif if ((old == NULL) || (entry == NULL)) return (old); #ifdef XTHREADS if ( _XmRendDisplay((XmRendition)entry) ) app = XtDisplayToApplicationContext(_XmRendDisplay((XmRendition)entry)); if (app) _XmAppLock(app); else _XmProcessLock(); #endif n = 0; XtSetArg(args[n], XmNtag, &tags[0]); n++; XtSetArg(args[n], XmNfontType, &type1); n++; XtSetArg(args[n], XmNfont, &font1); n++; XmRenditionRetrieve(entry, args, n); old = _XmRenderTableRemoveRenditions(old, tags, 1, TRUE, type1, font1); #ifdef XTHREADS if (app) _XmAppUnlock(app); else _XmProcessUnlock(); #endif return(old); } XmFontListEntry XmFontListEntryLoad( Display *display , char *fontName , XmFontType type , char *tag ) { Cardinal n; Arg args[4]; XmFontListEntry ret_val; _XmDisplayToAppContext(display); _XmAppLock(app); n = 0; XtSetArg(args[n], XmNfontName, fontName); n++; XtSetArg(args[n], XmNfontType, type); n++; XtSetArg(args[n], XmNloadModel, XmLOAD_IMMEDIATE); n++; ret_val = _XmRenditionCreate(display, NULL, XmS, XmCFontList, _XmStringCacheTag(tag, XmSTRING_TAG_STRLEN), args, n, NULL); _XmAppUnlock(app); return ret_val; } /* NOTE - this function XmFontListCreate is NOT MT-safe if the application is using threads with multiple application contexts to use Font lists in threaded code with multiple application contexts it is necessary to use the new API XmFontListCreate_r function which passes in an additional widget parameter ... this widget MUST be for the display that font will be used in Font should not be shared between displays in an MT environment */ XmFontList XmFontListCreate( XFontStruct *font, XmStringCharSet charset ) { Cardinal n; Arg args[4]; XmRendition rends[1]; XmStringCharSet curcharset; XmRenderTable ret_val; _XmProcessLock(); if ((font == NULL) || (charset == NULL)) { _XmProcessUnlock(); return (NULL); } if ((charset != XmFONTLIST_DEFAULT_TAG) && (strcmp(charset, XmSTRING_DEFAULT_CHARSET) == 0)) curcharset = _XmStringGetCurrentCharset(); else curcharset = charset; n = 0; XtSetArg(args[n], XmNfontType, XmFONT_IS_FONT); n++; XtSetArg(args[n], XmNfont, (XtPointer)font); n++; XtSetArg(args[n], XmNloadModel, XmLOAD_IMMEDIATE); n++; rends[0] = XmRenditionCreate(NULL, _XmStringCacheTag(curcharset, XmSTRING_TAG_STRLEN), args, n); _XmProcessUnlock(); ret_val = XmRenderTableAddRenditions(NULL, rends, 1, XmDUPLICATE); XmRenditionFree(rends[0]); return(ret_val); } /* MT safe version of XmFontListCreate - requires widget parameter A display variable is necessary to create a render table in an MT safe environment the widget passed in DOES NOT need to be the widget which uses the font however it MUST be on the same display Fonts can not be shared among displays in an MT environment */ XmFontList XmFontListCreate_r( XFontStruct *font, XmStringCharSet charset, Widget wid ) { Cardinal n; Arg args[4]; XmRendition rends[1]; XmStringCharSet curcharset; XmRenderTable ret_val; _XmWidgetToAppContext(wid); _XmAppLock(app); if ((font == NULL) || (charset == NULL)) { _XmAppUnlock(app); return (NULL); } if ((charset != XmFONTLIST_DEFAULT_TAG) && (strcmp(charset, XmSTRING_DEFAULT_CHARSET) == 0)) curcharset = _XmStringGetCurrentCharset(); else curcharset = charset; n = 0; XtSetArg(args[n], XmNfontType, XmFONT_IS_FONT); n++; XtSetArg(args[n], XmNfont, (XtPointer)font); n++; XtSetArg(args[n], XmNloadModel, XmLOAD_IMMEDIATE); n++; rends[0] = XmRenditionCreate(wid, _XmStringCacheTag(curcharset, XmSTRING_TAG_STRLEN), args, n); ret_val = XmRenderTableAddRenditions(NULL, rends, 1, XmDUPLICATE); XmRenditionFree(rends[0]); _XmAppUnlock(app); return(ret_val); } /* NOTE - this function XmStringCreateFontList is NOT MT-safe if the application is using threads with multiple application contexts to use Font lists in threaded code with multiple application contexts it is necessary to use the new API XmFontListCreate_r function which passes in an additional widget parameter ... this widget MUST be for the display that font will be used in Font should not be shared between displays in an MT environment */ XmFontList XmStringCreateFontList( XFontStruct *font, XmStringCharSet charset ) { return (XmFontListCreate(font,charset)); } /* MT safe version of XmStringCreateFontList - requires widget parameter A display variable is necessary to create a render table in an MT safe environment the widget passed in DOES NOT need to be the widget which uses the font however it MUST be on the same display Fonts can not be shared among displays in an MT environment */ XmFontList XmStringCreateFontList_r( XFontStruct *font, XmStringCharSet charset, Widget wid ) { /* we dont need to lock since this is just a wrapper */ return (XmFontListCreate_r(font,charset, wid)); } /* * dump a font list */ void XmFontListFree ( XmFontList fontlist) { XmRenderTableFree(fontlist); } /* * extent a font list by one element, the old font list is gone */ XmFontList XmFontListAdd( XmFontList old, XFontStruct *font, XmStringCharSet charset ) { XmStringCharSet curcharset; Cardinal n; Arg args[4]; XmRendition rends[1]; XmFontList ret_val; #ifdef XTHREADS XtAppContext app=NULL; #endif if (!old) return((XmFontList) NULL); if (!charset || !font) return ((XmFontList) old); #ifdef XTHREADS if ( _XmRTDisplay((XmRenderTable)old) ) app = XtDisplayToApplicationContext(_XmRTDisplay((XmRenderTable)old)); if (app) _XmAppLock(app); else _XmProcessLock(); #endif if ((charset != XmFONTLIST_DEFAULT_TAG) && (strcmp(charset, XmSTRING_DEFAULT_CHARSET) == 0)) curcharset = _XmStringGetCurrentCharset(); else curcharset = charset; n = 0; XtSetArg(args[n], XmNfontType, XmFONT_IS_FONT); n++; XtSetArg(args[n], XmNfont, (XtPointer)font); n++; XtSetArg(args[n], XmNloadModel, XmLOAD_IMMEDIATE); n++; rends[0] = XmRenditionCreate(NULL, _XmStringCacheTag(curcharset, XmSTRING_TAG_STRLEN), args, n); ret_val = XmRenderTableAddRenditions(old, rends, 1, XmDUPLICATE); #ifdef XTHREADS if (app) _XmAppUnlock(app); else _XmProcessUnlock(); #endif return ret_val; } /* * replicate a font list */ XmFontList XmFontListCopy( XmFontList fontlist ) { return(XmRenderTableCopy(fontlist, NULL, 0)); } XFontStruct * _XmGetFirstFont( XmFontListEntry entry) { XFontStruct *font_struct; Cardinal n; Arg args[2]; XmFontType type; XtPointer font; n = 0; XtSetArg(args[n], XmNfontType, &type); n++; XtSetArg(args[n], XmNfont, &font); n++; XmRenditionRetrieve(entry, args, n); if (font == (XtPointer)XmAS_IS) { font_struct = NULL; } else if (type == XmFONT_IS_FONTSET) { XFontStruct **font_struct_list; char **font_name_list; if (XFontsOfFontSet((XFontSet)font, &font_struct_list, &font_name_list)) font_struct = font_struct_list[0]; else font_struct = NULL; } else font_struct = (XFontStruct *)font; return (font_struct); } /* * Find an entry in the fontlist which matches the current charset or * return the first font if none match. */ Boolean XmeRenderTableGetDefaultFont( XmFontList fontlist, XFontStruct **font_struct ) { XmStringTag tag = XmFONTLIST_DEFAULT_TAG; short indx = -1; Boolean retval; #ifdef XTHREADS XtAppContext app=NULL; if ( _XmRTDisplay((XmRenderTable)fontlist) ) app = XtDisplayToApplicationContext(_XmRTDisplay((XmRenderTable)fontlist)); if (app) _XmAppLock(app); else _XmProcessLock(); #endif retval = _XmFontListSearch (fontlist, tag, &indx, font_struct); #ifdef XTHREADS if (app) _XmAppUnlock(app); else _XmProcessUnlock(); #endif return(retval); } /* * find an entry in the font list which matches, return index (or -1) and * font stuct ptr (or first in list). */ Boolean _XmFontListSearch( XmFontList fontlist, XmStringCharSet charset, short *indx, XFontStruct **font_struct ) { XmFontListEntry entry; Boolean success; success = _XmRenderTableFindFallback(fontlist, charset, FALSE, indx, &entry); /* For backward compatibility we must try to return something for */ /* any non-null charset, not just XmFONTLIST_DEFAULT_TAG. */ if (fontlist && charset && !success) success = _XmRenderTableFindFirstFont(fontlist, indx, &entry); if (success) *font_struct = _XmGetFirstFont(entry); else *font_struct = NULL; return success && (*font_struct != NULL); } /* * Fontlist access routines */ Boolean XmFontListInitFontContext( XmFontContext *context, XmFontList fontlist ) { XmFontContext p; _XmProcessLock(); if ((!fontlist) || (!context)) { _XmProcessUnlock(); return(FALSE); } p = (XmFontContext) XtMalloc (sizeof (XmFontListContextRec)); FLContextIndex(p) = 0; FLContextTable(p) = fontlist; FLContextError(p) = FALSE; *context = p; _XmProcessUnlock(); return (TRUE); } Boolean XmFontListGetNextFont( XmFontContext context, XmStringCharSet *charset, XFontStruct **font ) { XmRenderTable table; XmRendition rend; Cardinal n; Arg args[1]; XmStringTag tag; _XmProcessLock(); if ((context == NULL) || FLContextError(context) || (charset == NULL) || (font == NULL)) { _XmProcessUnlock(); return (FALSE); } table = FLContextTable(context); if (FLContextIndex(context) >= _XmRTCount(table)) { FLContextError(context) = TRUE; _XmProcessUnlock(); return(FALSE); } rend = _XmRTRenditions(table)[FLContextIndex(context)]; *font = _XmGetFirstFont(rend); _XmProcessUnlock(); n = 0; XtSetArg(args[n], XmNtag, &tag); n++; XmRenditionRetrieve(rend, args, n); *charset = XtNewString(tag); FLContextIndex(context)++; return (TRUE); } void XmFontListFreeFontContext( XmFontContext context ) { _XmProcessLock(); if (context != NULL) XtFree((char *)context); _XmProcessUnlock(); } #ifdef _XmDEBUG_XMSTRING void _Xm_dump_fontlist( XmFontList f ) { int i = 0; for ( ; FontListFont(f) != NULL; f++, i++) { printf ("fontlist[%3d] of 0x%p\n", i, f); printf ("\ttype = %d\n", FontListType(f)); printf ("\tfont = %p\n", FontListFont(f)); printf ("\ttag = <%s>\n", FontListTag(f)); } } void _Xm_dump_fontlist_cache( void ) { FontlistEntry *cache; if (_fontlist_cache == NULL) { printf("fontlist cache is empty\n"); return; } for (cache = _fontlist_cache; cache; cache = FontCacheNext(cache)) { printf("cache pointer: %p\n", cache); _Xm_dump_fontlist(FontCacheFontList(cache)); printf("refcount: %d\n", FontCacheRefCount(cache)); printf("next: %p\n\n", FontCacheNext(cache)); } } #endif /* _XmDEBUG_XMSTRING */