/* $XConsortium: XmFontList.c /main/16 1996/11/20 15:15:34 drk $ */
/*
* Motif
*
* Copyright (c) 1987-2012, The Open Group. All rights reserved.
*
* These libraries and programs are free software; you can
* redistribute them and/or modify them under the terms of the GNU
* Lesser General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* These libraries and programs are distributed in the hope that
* they will be useful, but WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with these librararies and programs; if not, write
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
* Floor, Boston, MA 02110-1301 USA
*/
/*
* HISTORY
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#ifndef X_NOT_STDC_ENV
#include <stdlib.h>
#endif
#include <string.h>
#include <ctype.h>
#ifdef __cplusplus
extern "C" { /* some 'locale.h' do not have prototypes (sun) */
#endif
#include <X11/Xlocale.h>
#ifdef __cplusplus
} /* Close scope of 'extern "C"' declaration */
#endif /* __cplusplus */
#include <Xm/AtomMgr.h>
#include <Xm/XmosP.h>
#include "XmI.h"
#include "XmRenderTI.h"
#include "XmStringI.h"
#define FIX_1252
/*
* 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;
#ifdef USE_XFT
XtPointer ret_val2;
#endif
Arg args[3];
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++;
#ifdef USE_XFT
XtSetArg(args[n], XmNxftFont, &ret_val2); n++;
#endif
XmRenditionRetrieve(entry, args, n);
#ifdef USE_XFT
if (*typeReturn == XmFONT_IS_XFT)
ret_val = ret_val2;
#endif
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;
#ifdef FIX_1252
if (XFontsOfFontSet((XFontSet)font,
&font_struct_list, &font_name_list)
&& font_struct_list[0]->fid != 0)
#else
if (XFontsOfFontSet((XFontSet)font,
&font_struct_list, &font_name_list))
#endif
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 */