/* 
 * Motif Tools Library, Version 2.0
 * $Id: FontListCvt.c,v 1.3 1994/07/04 03:03:50 david Exp $
 * 
 * Written by David Flanagan.
 * Copyright (c) 1992, 1993, 1994 by Dovetail Systems.
 * All Rights Reserved.  See the file COPYRIGHT for details.
 * This is not free software.  See the file SHAREWARE for details.
 * There is no warranty for this software.  See NO_WARRANTY for details.
 */

#include <ctype.h>
#include <Xmt/Xmt.h>
#include <Xmt/ConvertersP.h>
#include <Xmt/LookupP.h>

/* ARGSUSED */
#if NeedFunctionPrototypes
Boolean XmtConvertStringToXmFontList(Display *dpy,
				     XrmValue *args, Cardinal *num_args,
				     XrmValue *from, XrmValue *to,
				     XtPointer *converter_data)
#else
Boolean XmtConvertStringToXmFontList(dpy, args, num_args,
				     from, to, converter_data)
Display *dpy;
XrmValue *args;
Cardinal *num_args;
XrmValue *from;
XrmValue *to;
XtPointer *converter_data;
#endif
{
    Screen *screen = *(Screen **)args[0].addr;
    String copy = XtNewString((String) from->addr);
    String s;
    String next_entry;
    String tag;
    String tmp;
    XFontStruct *font;
    XmFontList fontlist = NULL;

    /*
     * This XmFontList converter does not handle XFontSets defined in
     * X11R5 and Motif 1.2.  This is to make it easier to write, and
     * for portablity to R4 and 1.1.  Also, this converter uses the 1.1
     * XmFontList API.  Anyone using multi-charset Asian languages will
     * not want to use this converter.
     * This converter also does not support the (undocumented?) features
     * of the Motif converter that allows quotes in font names.
     * The main reason to use the converter is because it handles
     * font list indirection.  And because it doesn't have the bug
     * that 1.2.3 does...
     *
     * The syntax is:
     *    font-name [ `=' tag ] { `,' font-name [ `=' tag ] }
     * 
     * and we extend this also to allow:
     *    `$' symbolic-font-list-name
     * A symbolic name like this will be looked up under _Fonts_,
     * depending on display resolution, and other factors.
     */
    
    s = copy;

    /* handle a symbolic font list name by recursing */
    if (s[0] == '$') {
	String value;
	XrmValue new_from;

	/* get symbolic name */
	s++;
	while(isspace(*s)) s++;
	
	/*
	 * lookup value of that symbolic name under:
	 *   _FontLists_.fontFamily.language.territory.codeset
	 * Note that we don't have to free the return value.
	 */
	value = _XmtLookupResource(screen, "Ffltc", s);
	
	/* if no value defined, warn and fail */
	if (!value) {
	    XmtWarningMsg("XmtConvertStringToFontList", "nosymbol",
			  "No font list with name '%s' defined in resource file under _FontLists_",
			  s);
	    goto fail;
	}

	/*
	 * Otherwise, recurse to convert the definition we've found 
	 * The programmer must be smart enough to avoid infinite recursion
	 */
	XtFree(copy);
	new_from.addr = (XPointer) value;
	new_from.size = strlen(value) + 1;
	return XmtConvertStringToXmFontList(dpy, args, num_args,
					    &new_from, to, converter_data);
    }
    
    /* Otherwise, it is not a symbolic font name */
    while(s && *s) {
	/* skip white-space */
	while(isspace(*s)) s++;
	if (!*s) break;

	/* isolate the first entry, and remember start of next entry */
	next_entry = strchr(s, ',');
	if (next_entry) {
	    *next_entry = '\0';
	    next_entry++;
	}

	/*
	 * find the start of the font tag, if any
	 * and isolate the font name from it.
	 * remove whitespace from beginning and end of tag
	 */
	tag = strchr(s, '=');
	if (tag) {
	    *tag = '\0';
	    tag++;
	    while(isspace(*tag)) tag++;
	    for(tmp=tag; *tmp && !isspace(*tmp); tmp++)  ;
	    *tmp = '\0';
	}
	else tag = XmSTRING_DEFAULT_CHARSET;

	/* remove any whitespace from the end of the font name */
	tmp = s + strlen(s) - 1;
	while (isspace(*tmp)) tmp--;
	*(++tmp) = '\0';

	font = XLoadQueryFont(dpy, s);
	if (!font) {
	    XmtWarningMsg("XmtConvertStringToFontList", "badfont",
			  "unknown font '%s'.\n\tUsing default.",
			  s);
	    /* this default is from the X11R5 font converter */
	    font = XLoadQueryFont(dpy, "-*-*-*-R-*-*-*-120-*-*-*-*-ISO8859-1");

	    /* if still no font, then we fail */
	    if (!font) {
		XmtWarningMsg("XmtConvertStringToFontList", "nodefault",
			      "cannot load any default font.");
		goto fail;
	    }
	}

	/* and use this font and tag to create or append to the font list */
	if (!fontlist)
	    fontlist = XmFontListCreate(font, tag);
	else 
	    fontlist = XmFontListAdd(fontlist, font, tag);

	/* finally, move on to the next entry, and start the loop over */
	s = next_entry;
    }


    if (fontlist) {
	XtFree(copy);
	done(XmFontList, fontlist);  /* this macro returns */
    }

 fail:
    XtDisplayStringConversionWarning(dpy, copy, XmRFontList);
    XtFree(copy);
    return False;
}


/* ARGSUSED */
#if NeedFunctionPrototypes
static void FreeConvertedXmFontList(XtAppContext app, XrmValue *to,
				    XtPointer closure,
				    XrmValue *args, Cardinal *num_args)
#else
static void FreeConvertedXmFontList(app, to, closure, args, num_args)
XtAppContext app;
XrmValue *to;
XtPointer closure;
XrmValue *args;
Cardinal *num_args;
#endif
{
    XmFontList fontlist = *((XmFontList *) to->addr);
    Screen *screen = *(Screen **)args[0].addr;
    Display *dpy = DisplayOfScreen(screen);
    XmFontContext context;
    XFontStruct *font;
    XmStringCharSet tag;
    
    if (XmFontListInitFontContext(&context, fontlist)) {
	while(XmFontListGetNextFont(context, &tag, &font))
	    XFreeFont(dpy, font);
	XmFontListFreeFontContext(context);
    }
    XmFontListFree(fontlist);
}

#if NeedFunctionPrototypes
void XmtRegisterXmFontListConverter(void)
#else
void XmtRegisterXmFontListConverter()
#endif
{
    static Boolean registered = False;

    if (!registered) {
	XtSetTypeConverter(XtRString, XmRFontList,
			   XmtConvertStringToXmFontList,
			   (XtConvertArgRec *)screenConvertArg, (Cardinal) 1,
			   XtCacheByDisplay,
			   FreeConvertedXmFontList);
	registered = True;
    }
}


