diff options
Diffstat (limited to 'nx-X11/programs/Xserver/hw/nxagent/Font.c')
-rw-r--r-- | nx-X11/programs/Xserver/hw/nxagent/Font.c | 1690 |
1 files changed, 1690 insertions, 0 deletions
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Font.c b/nx-X11/programs/Xserver/hw/nxagent/Font.c new file mode 100644 index 000000000..ff968bcc5 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/Font.c @@ -0,0 +1,1690 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* + +Copyright 1993 by Davor Matic + +Permission to use, copy, modify, distribute, and sell this software +and its documentation for any purpose is hereby granted without fee, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation. Davor Matic makes no representations about +the suitability of this software for any purpose. It is provided "as +is" without express or implied warranty. + +*/ + +#include "scrnintstr.h" +#include "dixstruct.h" +#include "../../../../include/fonts/font.h" +#include "fontstruct.h" +#include "misc.h" +#include "miscstruct.h" +#include "opaque.h" + +#include "Agent.h" + +#include "Display.h" +#include "Font.h" +#include "Error.h" + +#include <stdio.h> +#include <sys/stat.h> +#include "resource.h" +#include "Reconnect.h" + +#include "Args.h" + +#include "NXlib.h" +#include "NXalert.h" + +#include <string.h> +#include <stdlib.h> + +#define PANIC +#define WARNING +#undef TEST +#undef DEBUG + +#define NXAGENT_DEFAULT_FONT_DIR "/usr/X11R6/lib/X11/fonts" +#define NXAGENT_ALTERNATE_FONT_DIR "/usr/share/X11/fonts" +#define NXAGENT_ALTERNATE_FONT_DIR_2 "/usr/share/fonts/X11" +#define NXAGENT_ALTERNATE_FONT_DIR_3 "/usr/share/fonts" + +#define NXAGENT_DEFAULT_FONT_PATH \ +"/usr/X11R6/lib/X11/fonts/misc/,/usr/X11R6/lib/X11/fonts/Speedo/,\ +/usr/X11R6/lib/X11/fonts/Type1/,/usr/X11R6/lib/X11/fonts/75dpi/,\ +/usr/X11R6/lib/X11/fonts/100dpi/,/usr/X11R6/lib/X11/fonts/TTF/" + +#define NXAGENT_ALTERNATE_FONT_PATH \ +"/usr/share/X11/fonts/misc/,/usr/share/X11/fonts/Speedo/,\ +/usr/share/X11/fonts/Type1/,/usr/share/X11/fonts/75dpi/,\ +/usr/share/X11/fonts/100dpi/,/usr/share/X11/fonts/TTF/" + +#define NXAGENT_ALTERNATE_FONT_PATH_2 \ +"/usr/share/fonts/X11/misc/,/usr/share/fonts/X11/Speedo/,\ +/usr/share/fonts/X11/Type1/,/usr/share/fonts/X11/75dpi/,\ +/usr/share/fonts/X11/100dpi/,/usr/share/fonts/X11/TTF/" + +#define NXAGENT_ALTERNATE_FONT_PATH_3 \ +"/usr/share/fonts/misc/,/usr/share/fonts/Speedo/,\ +/usr/share/fonts/Type1/,/usr/share/fonts/75dpi/,\ +/usr/share/fonts/100dpi/,/usr/share/fonts/TTF/" + +#undef NXAGENT_FONTCACHE_DEBUG +#undef NXAGENT_RECONNECT_FONT_DEBUG +#undef NXAGENT_FONTMATCH_DEBUG + +#define FIELDS 14 + +static int reconnectFlexibility; + +static void nxagentCleanCacheAfterReconnect(void); +static void nxagentFontReconnect(FontPtr, XID, pointer); +static XFontStruct *nxagentLoadBestQueryFont(Display* dpy, char *fontName, FontPtr pFont); +static XFontStruct *nxagentLoadQueryFont(register Display *dpy , char *fontName , FontPtr pFont); +int nxagentFreeFont(XFontStruct *fs); +static Bool nxagentGetFontServerPath(char * fontServerPath); + +RESTYPE RT_NX_FONT; + +#ifdef NXAGENT_RECONNECT_FONT_DEBUG +static void printFontCacheDump(char*); +#endif + +typedef struct _nxagentFontRec +{ + char *name; + int status; +} nxagentFontRec, *nxagentFontRecPtr; + +typedef struct _nxagentFontList +{ + nxagentFontRecPtr *list; + int length; + int listSize; +} nxagentFontList, *nxagentFontListPtr; + +nxagentFontList nxagentRemoteFontList = {NULL, (int)0, (int)0}; + +int nxagentFontPrivateIndex; + +typedef struct _nxCacheFontEntry +{ + Atom atom; + XFontStruct *font_struct; + char *name; +} nxCacheFontEntryRec, *nxCacheFontEntryRecPtr; + +static struct _nxagentFontCache +{ + nxCacheFontEntryRecPtr *entry; + int index; + int size; +} nxagentFontCache = { NULL, (int) 0, (int) 0 }; + +#define CACHE_ENTRY_PTR (nxagentFontCache.entry) +#define CACHE_INDEX (nxagentFontCache.index) +#define CACHE_SIZE (nxagentFontCache.size) +#define CACHE_ENTRY(A) (CACHE_ENTRY_PTR[A]) +#define CACHE_FSTRUCT(A) (CACHE_ENTRY(A) -> font_struct) +#define CACHE_NAME(A) (CACHE_ENTRY(A) -> name) +#define CACHE_ATOM(A) (CACHE_ENTRY(A) -> atom) + +static struct _nxagentFailedToReconnectFonts +{ + FontPtr *font; + XID *id; + int size; + int index; +} nxagentFailedToReconnectFonts = {NULL, NULL, 0, 0}; + +/* + * This is used if nxagentFullGeneration is true + * in CloseDisplay(). + */ + +void nxagentFreeFontCache(void) +{ + int i; + + #ifdef NXAGENT_FONTCACHE_DEBUG + fprintf(stderr, "Font: Freeing nxagent font cache\n"); + #endif + + if (CACHE_INDEX == 0) + return; + + #ifdef NXAGENT_FONTCACHE_DEBUG + fprintf(stderr, "Font: Freeing nxagent font cache, there are [%d] entries.\n", CACHE_INDEX); + #endif + + for (i = 0; i < CACHE_INDEX; i++) + { + #ifdef NXAGENT_FONTCACHE_DEBUG + fprintf(stderr, "Font: Freeing nxagent font cache entry [%d] entry pointer is [%p], name [%s]\n", + i, CACHE_ENTRY(i), CACHE_NAME(i)); + #endif + + if (CACHE_FSTRUCT(i)) + { + nxagentFreeFont(CACHE_FSTRUCT(i)); + } + + xfree(CACHE_NAME(i)); + xfree(CACHE_ENTRY(i)); + } + + xfree(CACHE_ENTRY_PTR); + CACHE_ENTRY_PTR = NULL; + CACHE_INDEX = 0; + CACHE_SIZE = 0; + + #ifdef NXAGENT_FONTCACHE_DEBUG + fprintf(stderr, "Font: nxagent font cache fully freed\n"); + #endif + + return; +} + +void nxagentListRemoteFonts(const char *searchPattern, const int maxNames) +{ + int i, q, p; + + char **xList; + int xLen = 0; + + const char *patterns[] = {"*", "-*-*-*-*-*-*-*-*-*-*-*-*-*-*"}; + int patternsQt = 2; + + if (NXDisplayError(nxagentDisplay) == 1) + { + return; + } + + /* + * Avoid querying again the remote + * fonts. + */ + + if (nxagentRemoteFontList.length > 0) + { + return; + } + + /* + * We can't retrieve the full remote font + * list with a single query, because the + * number of dashes in the pattern acts as + * a rule to select how to search for the + * font names, so the pattern '*' is useful + * to retrive the font aliases, while the + * other one will select the 'real' fonts. + */ + + for (p = 0; p < patternsQt; p++) + { + xList = XListFonts(nxagentDisplay, patterns[p], maxNames, &xLen); + + #ifdef NXAGENT_FONTMATCH_DEBUG + fprintf(stderr, "nxagentListRemoteFonts: NXagent remote list [%s] has %d elements.\n", patterns[p], xLen); + #endif + + /* + * Add the ListFont request pattern to the list with + * the last requested maxnames. + */ + + nxagentListRemoteAddName(searchPattern, maxNames); + + for (i = 0; i < xLen; i++) + { + q = 1; + + nxagentListRemoteAddName(xList[i], q); + } + + XFreeFontNames(xList); + } + + #ifdef NXAGENT_FONTMATCH_DEBUG + + fprintf(stderr, "nxagentListRemoteFonts: Printing remote font list.\n"); + + for (i = 0; i < nxagentRemoteFontList.length; i++) + { + fprintf(stderr, "Font# %d, \"%s\"\n", i, nxagentRemoteFontList.list[i]->name); + } + + fprintf(stderr, "nxagentListRemoteFonts: End of list\n"); + + #endif +} + +void nxagentListRemoteAddName(const char *name, int status) +{ + int pos; + + if (nxagentFontFind(name, &pos)) + { + if (nxagentRemoteFontList.list[pos]->status < status) + { + nxagentRemoteFontList.list[pos]->status = status; + + #ifdef NXAGENT_FONTMATCH_DEBUG + fprintf(stderr, "Font: Font# %d, [%s] change status to %s\n", + pos, nxagentRemoteFontList.list[pos]->name,nxagentRemoteFontList.list[pos]->status?"OK":"deleted"); + #endif + } + return; + } + + if (nxagentRemoteFontList.length == nxagentRemoteFontList.listSize) + { + nxagentRemoteFontList.list = xrealloc(nxagentRemoteFontList.list, sizeof(nxagentFontRecPtr) + * (nxagentRemoteFontList.listSize + 1000)); + + if (nxagentRemoteFontList.list == NULL) + { + FatalError("Font: remote list memory re-allocation failed!.\n"); + } + + nxagentRemoteFontList.listSize += 1000; + } + + if (pos < nxagentRemoteFontList.length) + { + #ifdef NXAGENT_FONTMATCH_DEBUG + fprintf(stderr, "Font: Going to move list from %p to %p len = %d!.\n", + &nxagentRemoteFontList.list[pos], &nxagentRemoteFontList.list[pos+1], + (nxagentRemoteFontList.length - pos) * sizeof(nxagentFontRecPtr)); + #endif + + memmove(&nxagentRemoteFontList.list[pos+1], + &nxagentRemoteFontList.list[pos], + (nxagentRemoteFontList.length - pos) * sizeof(nxagentFontRecPtr)); + } + + if ((nxagentRemoteFontList.list[pos] = xalloc(sizeof(nxagentFontRec)))) + { + nxagentRemoteFontList.list[pos]->name = xalloc(strlen(name) +1); + if (nxagentRemoteFontList.list[pos]->name == NULL) + { + fprintf(stderr, "Font: remote list name memory allocation failed!.\n"); + return; + } + } + else + { + fprintf(stderr, "Font: remote list record memory allocation failed!.\n"); + return; + } + strcpy(nxagentRemoteFontList.list[pos]->name,name); + nxagentRemoteFontList.list[pos]->status = status; + nxagentRemoteFontList.length++; + + #ifdef NXAGENT_FONTMATCH_DEBUG + fprintf(stderr, "Font: remote font list added [%s] in position [%d] as %s !.\n", + name, pos, status ? "OK" : "deleted"); + fprintf(stderr, "Font: remote font list total len is [%d] Size is [%d] !.\n", + nxagentRemoteFontList.length, nxagentRemoteFontList.listSize); + #endif +} + +static void nxagentFreeRemoteFontList(nxagentFontList *listRec) +{ + int l; + + for (l = 0; l < listRec -> length; l++) + { + if (listRec -> list[l]) + { + xfree(listRec -> list[l] -> name); + listRec -> list[l] -> name = NULL; + + xfree(listRec -> list[l]); + listRec -> list[l] = NULL; + } + } + + listRec -> length = listRec -> listSize = 0; + + free(listRec -> list); + listRec -> list = NULL; + + return; +} + +Bool nxagentFontFind(const char *name, int *pos) +{ + int low,high,res,iter,lpos; + + if (!nxagentRemoteFontList.length) + { + *pos=0; + return False; + } + low = 0; + high = nxagentRemoteFontList.length - 1; + iter = 0; + res = 1; + lpos = nxagentRemoteFontList.length; + while (low <= high) + { + *pos = (high + low)/2; + iter ++; + res = strcasecmp(nxagentRemoteFontList.list[*pos]->name,name); + if (res > 0) + { + high = *pos - 1; + lpos = *pos; + continue; + } + else if (res < 0) + { + low = *pos + 1; + lpos = low; + continue; + } + break; + } + *pos = (res == 0)?*pos:lpos; + + #ifdef NXAGENT_FONTMATCH_DEBUG + if (res == 0) + fprintf(stderr, "Font: font found in %d iterations in pos = %d\n", iter, *pos); + else + fprintf(stderr, "Font: not font found in %d iterations insertion pos is = %d\n", iter, *pos); + #endif + + return (res == 0); + +} + +Bool nxagentFontLookUp(const char *name) +{ + int i; + if (name) + if (!strlen(name)) + return 0; + if (nxagentFontFind(name, &i)) + return (nxagentRemoteFontList.list[i]->status > 0); + else + return 0; +} + +Bool nxagentRealizeFont(ScreenPtr pScreen, FontPtr pFont) +{ + pointer priv; + Atom name_atom, value_atom; + int nprops; + FontPropPtr props; + int i; + char *name; + char *origName = (char*) pScreen; + + FontSetPrivate(pFont, nxagentFontPrivateIndex, NULL); + + if (requestingClient && XpClientIsPrintClient(requestingClient, NULL)) + return True; + + name_atom = MakeAtom("FONT", 4, True); + value_atom = 0L; + + nprops = pFont->info.nprops; + props = pFont->info.props; + + for (i = 0; i < nprops; i++) + if ((Atom)props[i].name == name_atom) { + value_atom = props[i].value; + break; + } + + if (!value_atom) return False; + + name = (char *)NameForAtom(value_atom); + + #ifdef NXAGENT_FONTCACHE_DEBUG + fprintf(stderr, "Font: nxagentRealizeFont, realizing font: %s\n", validateString(name)); + fprintf(stderr, " atom: %ld\n", value_atom); + fprintf(stderr, "Font: Cache dump:\n"); + for (i = 0; i < CACHE_INDEX; i++) + { + fprintf(stderr, "nxagentFontCache.entry[%d]->name: %s font_struct at %p\n", + i, CACHE_NAME(i), CACHE_FSTRUCT(i)); + } + #endif + + if (!name) return False; + + if ((strcasecmp(origName, name) != 0) && !strchr(origName,'*')) + { + #ifdef NXAGENT_FONTMATCH_DEBUG + fprintf(stderr, "Font: Changing font name to realize from [%s] to [%s]\n", + validateString(name), origName); + #endif + + name = origName; + } + + priv = (pointer)xalloc(sizeof(nxagentPrivFont)); + FontSetPrivate(pFont, nxagentFontPrivateIndex, priv); + + nxagentFontPriv(pFont) -> mirrorID = 0; + + for (i = 0; i < nxagentFontCache.index; i++) + { +/* if (value_atom == CACHE_ATOM(i))*/ + if (strcasecmp(CACHE_NAME(i), name) == 0) + { + #ifdef NXAGENT_FONTCACHE_DEBUG + fprintf(stderr, "Font: nxagentFontCache hit [%s] = [%s]!\n", CACHE_NAME(i), validateString(name)); + #endif + + break; + } + } + + if (i < CACHE_INDEX) + { + nxagentFontPriv(pFont)->font_struct = CACHE_FSTRUCT(i); + strcpy(nxagentFontPriv(pFont)->fontName, name); + } + else + { + #ifdef NXAGENT_FONTCACHE_DEBUG + fprintf(stderr, "Font: nxagentFontCache fail.\n"); + #endif + + if (CACHE_INDEX == CACHE_SIZE) + { + CACHE_ENTRY_PTR = xrealloc(CACHE_ENTRY_PTR, sizeof(nxCacheFontEntryRecPtr) * (CACHE_SIZE + 100)); + + if (CACHE_ENTRY_PTR == NULL) + { + FatalError("Font: Cache list memory re-allocation failed.\n"); + } + + CACHE_SIZE += 100; + } + + CACHE_ENTRY(CACHE_INDEX) = xalloc(sizeof(nxCacheFontEntryRec)); + + if (CACHE_ENTRY(CACHE_INDEX) == NULL) + { + return False; + } + + CACHE_NAME(CACHE_INDEX) = xalloc(strlen(name) + 1); + + if (CACHE_NAME(CACHE_INDEX) == NULL) + { + return False; + } + + #ifdef NXAGENT_FONTMATCH_DEBUG + fprintf(stderr, "Font: Going to realize font [%s],[%s] on real X server.\n", validateString(name), origName); + #endif + + if (nxagentRemoteFontList.length == 0 && (NXDisplayError(nxagentDisplay) == 0)) + { + nxagentListRemoteFonts("*", nxagentMaxFontNames); + } + + nxagentFontPriv(pFont)->font_struct = nxagentLoadQueryFont(nxagentDisplay, name, pFont); + strcpy(nxagentFontPriv(pFont)->fontName, name); + if (nxagentFontPriv(pFont)->font_struct != NULL) + { + CACHE_ATOM(i) = value_atom; + strcpy(CACHE_NAME(i), name); + CACHE_FSTRUCT(i) = nxagentFontPriv(pFont)->font_struct; + CACHE_INDEX++; + + nxagentFontPriv(pFont) -> mirrorID = FakeClientID(serverClient -> index); + AddResource(nxagentFontPriv(pFont) -> mirrorID, RT_NX_FONT, pFont); + + #ifdef NXAGENT_FONTCACHE_DEBUG + fprintf(stderr, "Font: nxagentFontCache adds font [%s] in pos. [%d].\n", + validateString(name), CACHE_INDEX - 1); + #endif + } + } + + #ifdef NXAGENT_FONTMATCH_DEBUG + + if (nxagentFontPriv(pFont)->font_struct == NULL) + { + if (nxagentFontLookUp(name) == False) + { + fprintf(stderr, "Font: nxagentRealizeFont failed with font Font=%s, not in our remote list\n", + validateString(name)); + } + else + { + fprintf(stderr, "Font: nxagentRealizeFont failed with font Font=%s but the font is in our remote list\n", + validateString(name)); + } + } + else + fprintf(stderr, "Font: nxagentRealizeFont OK realizing font Font=%s\n", + validateString(name)); + + #endif + + return (nxagentFontPriv(pFont)->font_struct != NULL); +} + +Bool nxagentUnrealizeFont(ScreenPtr pScreen, FontPtr pFont) +{ + if (nxagentFontPriv(pFont)) + { + if (NXDisplayError(nxagentDisplay) == 0) + { + if (nxagentFontStruct(pFont)) + { + int i; + + for (i = 0; i < CACHE_INDEX; i++) + { + if (CACHE_FSTRUCT(i) == nxagentFontStruct(pFont)) + { + #ifdef NXAGENT_FONTCACHE_DEBUG + fprintf(stderr, "nxagentUnrealizeFont: Not freeing the font in cache.\n"); + #endif + + break; + } + } + + if (i == CACHE_INDEX) + { + /* + * This font is not in the cache. + */ + + #ifdef NXAGENT_FONTCACHE_DEBUG + fprintf(stderr, "nxagentUnrealizeFont: Freeing font not found in cache '%d'\n", + CACHE_ATOM(i)); + #endif + + XFreeFont(nxagentDisplay, nxagentFontStruct(pFont)); + } + } + } + + if (nxagentFontPriv(pFont) -> mirrorID) + FreeResource(nxagentFontPriv(pFont) -> mirrorID, RT_NONE); + + xfree(nxagentFontPriv(pFont)); + FontSetPrivate(pFont, nxagentFontPrivateIndex, NULL); + } + + return True; +} + +int nxagentDestroyNewFontResourceType(pointer p, XID id) +{ + #ifdef TEST + fprintf(stderr, "nxagentDestroyNewFontResourceType: Destroying mirror id [%ld] for font at [%p].\n", + nxagentFontPriv((FontPtr) p) -> mirrorID, (void *) p); + #endif + +/* +FIXME: It happens that this resource had been already + destroied. We should verify if the same font is + assigned both to the server client and another + client. We had a crash when freeing server client + resources. +*/ + if (nxagentFontPriv((FontPtr) p) != NULL) + { + nxagentFontPriv((FontPtr) p) -> mirrorID = None; + } + + return 1; +} + +static XFontStruct *nxagentLoadBestQueryFont(Display* dpy, char *fontName, FontPtr pFont) +{ + XFontStruct *fontStruct; + + char *substFontBuf; + + /* X Logical Font Description Conventions + * require 14 fields in the font names. + * + */ + char *searchFields[FIELDS+1]; + char *fontNameFields[FIELDS+1]; + int i; + int j; + int numSearchFields = 0; + int numFontFields = 0; + int weight = 0; + int tempWeight = 1; + int fieldOrder[14] = { 4, /* Slant */ + 11, /* Spacing */ + 12, /* Width info */ + 13, /* Charset */ + 14, /* Language */ + 7, /* Height */ + 6, /* Add-style */ + 3, /* Weight */ + 2, /* Name */ + 1, /* Foundry */ + 9, /* DPI_x */ + 5, /* Set-width */ + 8, /* Point size */ + 10 /* DPI_y */ + }; + + #ifdef NXAGENT_RECONNECT_FONT_DEBUG + fprintf(stderr, "nxagentLoadBestQueryFont: Searching font '%s' .\n", fontName); + #endif + + substFontBuf = (char *) xalloc(sizeof(char) * 512); + + + numFontFields = nxagentSplitString(fontName, fontNameFields, FIELDS, "-"); + + memcpy(substFontBuf, "fixed\0", strlen("fixed") + 1); + + if (numFontFields <= FIELDS) + { + #ifdef WARNING + if (nxagentVerbose == 1) + { + fprintf(stderr, "nxagentLoadBestQueryFont: WARNING! Font name in non standard format. \n"); + } + #endif + } + else + { + for (i = 1 ; i < nxagentRemoteFontList.length ; i++) + { + numSearchFields = nxagentSplitString(nxagentRemoteFontList.list[i]->name, searchFields, FIELDS+1, "-"); + + + /* The following code attemps to find an accurate approximation + * of the missing font. The current candidate and the missing font are + * compared on the 14 fields of the X Logical Font Description Convention. + * The selection is performed by the analysis of the matching fields, + * shifting left the value of the Weight variable on the right matches + * and shifting right the value of the Weight on the wrong ones; + * due a probability of overmuch right shifting, the starting weight is set + * to a high value. At the end of matching the selected font is the one + * with the bigger final Weight. The shift operation has been used instead + * of other operation for a performance issue. + * In some check the shift is performed by more than one position, because + * of the relevance of the field; for example a correct slant or a matching + * charset is more relevant than the size. + */ + + if (numSearchFields > FIELDS) + { + + tempWeight = 0; + + for (j = 0; j < FIELDS; j++) + { + if (strcasecmp(searchFields[fieldOrder[j]], fontNameFields[fieldOrder[j]]) == 0 || + strcmp(searchFields[fieldOrder[j]], "") == 0 || + strcmp(fontNameFields[fieldOrder[j]], "") != 0 || + strcmp(searchFields[fieldOrder[j]], "*") == 0 || + strcmp(fontNameFields[fieldOrder[j]], "*") == 0) + { + tempWeight ++; + } + + tempWeight <<= 1; + } + + } + + if (tempWeight > weight) + { + /* Found more accurate font */ + + weight = tempWeight; + memcpy(substFontBuf, nxagentRemoteFontList.list[i]->name, strlen(nxagentRemoteFontList.list[i]->name)); + substFontBuf[strlen(nxagentRemoteFontList.list[i]->name)] = '\0'; + + #ifdef NXAGENT_RECONNECT_FONT_DEBUG + fprintf(stderr, "nxagentLoadBestQueryFont: Weight '%d' of more accurate font '%s' .\n", weight, substFontBuf); + #endif + } + } + } + + #ifdef WARNING + if (nxagentVerbose == 1) + { + fprintf(stderr, "nxagentLoadBestQueryFont: WARNING! Failed to load font '%s'. Replacing with '%s'.\n", + fontName, substFontBuf); + } + #endif + + fontStruct = nxagentLoadQueryFont(dpy, substFontBuf, pFont); + + free (substFontBuf); + + return fontStruct; +} + +static void nxagentFontDisconnect(FontPtr pFont, XID param1, pointer param2) +{ + nxagentPrivFont *privFont; + Bool *pBool = (Bool*)param2; + int i; + + if (pFont == NULL || !*pBool) + return; + + privFont = nxagentFontPriv(pFont); + + #ifdef NXAGENT_RECONNECT_FONT_DEBUG + fprintf(stderr, "nxagentFontDisconnect: pFont %p, XID %lx\n", + (void *) pFont, privFont -> font_struct ? nxagentFont(pFont) : 0); + #endif + + for (i = 0; i < CACHE_INDEX; i++) + { + if (strcasecmp(CACHE_NAME(i), privFont -> fontName) == 0) + { + #ifdef NXAGENT_RECONNECT_FONT_DEBUG + fprintf(stderr, "nxagentFontDisconnect: font %s found in cache at position %d\n", + privFont -> fontName, i); + #endif + + privFont -> font_struct = NULL; + return; + } + } + + #ifdef NXAGENT_RECONNECT_FONT_DEBUG + fprintf(stderr, "nxagentFontDisconnect: WARNING font %s not found in cache freeing it now\n", + privFont -> fontName); + #endif + + if (privFont -> font_struct) + { + XFreeFont(nxagentDisplay, privFont -> font_struct); + privFont -> font_struct = NULL; + } +} + +static void nxagentCollectFailedFont(FontPtr fpt, XID id) +{ + + if (nxagentFailedToReconnectFonts.font == NULL) + { + nxagentFailedToReconnectFonts.size = 8; + + nxagentFailedToReconnectFonts.font = malloc(nxagentFailedToReconnectFonts.size * + sizeof(FontPtr)); + + nxagentFailedToReconnectFonts.id = malloc(nxagentFailedToReconnectFonts.size * sizeof(XID)); + + if (nxagentFailedToReconnectFonts.font == NULL || nxagentFailedToReconnectFonts.id == NULL) + { + FatalError("Font: font not reconnected memory allocation failed!.\n"); + } + + #ifdef NXAGENT_RECONNECT_FONT_DEBUG + fprintf(stderr, "nxagentCollectFailedFont: allocated [%d] bytes.\n", + 8 * (sizeof(FontPtr)+ sizeof(XID))); + #endif + } + else if (nxagentFailedToReconnectFonts.index == nxagentFailedToReconnectFonts.size - 1) + { + nxagentFailedToReconnectFonts.size *= 2; + + nxagentFailedToReconnectFonts.font = realloc(nxagentFailedToReconnectFonts.font, + nxagentFailedToReconnectFonts.size * + sizeof(FontPtr)); + + nxagentFailedToReconnectFonts.id = realloc(nxagentFailedToReconnectFonts.id, + nxagentFailedToReconnectFonts.size * + sizeof(XID)); + + if (nxagentFailedToReconnectFonts.font == NULL || nxagentFailedToReconnectFonts.id == NULL) + { + FatalError("Font: font not reconnected memory re-allocation failed!.\n"); + } + + #ifdef NXAGENT_RECONNECT_FONT_DEBUG + fprintf(stderr,"nxagentCollectFailedFont: reallocated memory.\n "); + #endif + } + + nxagentFailedToReconnectFonts.font[nxagentFailedToReconnectFonts.index] = fpt; + + nxagentFailedToReconnectFonts.id[nxagentFailedToReconnectFonts.index] = id; + + #ifdef NXAGENT_RECONNECT_FONT_DEBUG + fprintf(stderr, "nxagentCollectFailedFont: font not reconnected at [%p], " + "put in nxagentFailedToReconnectFonts.font[%d] = [%p], with XID = [%lu].\n", + (void*) fpt, nxagentFailedToReconnectFonts.index, + (void *)nxagentFailedToReconnectFonts.font[nxagentFailedToReconnectFonts.index], + nxagentFailedToReconnectFonts.id[nxagentFailedToReconnectFonts.index]); + #endif + + nxagentFailedToReconnectFonts.index++; +} + +static void nxagentFontReconnect(FontPtr pFont, XID param1, pointer param2) +{ + int i; + nxagentPrivFont *privFont; + Bool *pBool = (Bool*)param2; + + if (pFont == NULL) + return; + + privFont = nxagentFontPriv(pFont); + + #ifdef NXAGENT_RECONNECT_FONT_DEBUG + fprintf(stderr, "nxagentFontReconnect: pFont %p - XID %lx - name %s\n", + (void*) pFont, (privFont -> font_struct) ? nxagentFont(pFont) : 0, + privFont -> fontName); + #endif + + for (i = 0; i < CACHE_INDEX; i++) + { + if (strcasecmp(CACHE_NAME(i), privFont -> fontName) == 0) + { + #ifdef NXAGENT_RECONNECT_FONT_DEBUG + fprintf(stderr, "\tfound in cache"); + #endif + + if (!CACHE_FSTRUCT(i)) + { + #ifdef NXAGENT_RECONNECT_FONT_DEBUG + fprintf(stderr, " --- font struct not valid\n"); + #endif + + break; + } + + nxagentFontStruct(pFont) = CACHE_FSTRUCT(i); + + return; + } + } + + if (i == CACHE_INDEX) + { + FatalError("nxagentFontReconnect: font not found in cache."); + } + + privFont -> font_struct = nxagentLoadQueryFont(nxagentDisplay, privFont -> fontName, pFont); + + if ((privFont -> font_struct == NULL) && reconnectFlexibility) + { + privFont -> font_struct = nxagentLoadBestQueryFont(nxagentDisplay, privFont -> fontName, pFont); + } + + if (privFont->font_struct != NULL) + { + #ifdef NXAGENT_RECONNECT_FONT_DEBUG + fprintf(stderr, "\tXID %lx\n", privFont -> font_struct -> fid); + #endif + + CACHE_FSTRUCT(i) = privFont -> font_struct; + } + else + { + #ifdef NXAGENT_RECONNECT_FONT_DEBUG + fprintf(stderr, "nxagentFontReconnect: failed\n"); + #endif + + nxagentCollectFailedFont(pFont, param1); + + #ifdef NXAGENT_RECONNECT_FONT_DEBUG + fprintf(stderr, "nxagentFontReconnect: reconnection of font [%s] failed.\n", + privFont -> fontName); + #endif + + nxagentSetReconnectError(FAILED_RESUME_FONTS_ALERT, + "Couldn't restore the font '%s'", privFont -> fontName); + + *pBool = False; + } + + return; +} + +static void nxagentFreeCacheBeforeReconnect(void) +{ + int i; + + #ifdef NXAGENT_RECONNECT_FONT_DEBUG + printFontCacheDump("nxagentFreeCacheBeforeReconnect"); + #endif + + for (i = 0; i < CACHE_INDEX; i++) + { + if (CACHE_FSTRUCT(i)) + { + nxagentFreeFont(CACHE_FSTRUCT(i)); + CACHE_FSTRUCT(i) = NULL; + } + } +} + +static void nxagentCleanCacheAfterReconnect(void) +{ + int i, j; + int real_size = CACHE_INDEX; + nxCacheFontEntryRecPtr swapEntryPtr; + + #ifdef NXAGENT_RECONNECT_FONT_DEBUG + printFontCacheDump("nxagentCleanCacheAfterReconnect"); + #endif + + for (i = 0; i < CACHE_INDEX; i++) + { + if(CACHE_FSTRUCT(i) == NULL) + { + XFree(CACHE_NAME(i)); + real_size--; + } + } + + for (i = 0; i < real_size; i++) + { + /* Find - first bad occurrence if exist. */ + while ((i < real_size) && CACHE_FSTRUCT(i)) i++; + + /* Really nothing more to do. */ + if (i == real_size) + break; + + /* + * Find - first good occurrence (moving backward from right end) entry in + * order to replace the bad one. + */ + for (j = CACHE_INDEX - 1; CACHE_FSTRUCT(j) == NULL; j--); + + /* + * Now we can swap the two entry + * and reduce the Cache index + */ + swapEntryPtr = CACHE_ENTRY(i); + CACHE_ENTRY(i) = CACHE_ENTRY(j); + CACHE_ENTRY(j) = swapEntryPtr; + } + + CACHE_INDEX = real_size; +} + +#ifdef NXAGENT_RECONNECT_FONT_DEBUG +static void printFontCacheDump(char* msg) +{ + int i; + + fprintf(stderr, "%s - begin -\n", msg); + + for (i = 0; i < CACHE_INDEX; i++) + { + if (CACHE_FSTRUCT(i)) + { + fprintf(stderr, "\tXID %lx - %s\n", CACHE_FSTRUCT(i) -> fid, CACHE_NAME(i)); + } + else + { + fprintf(stderr, "\tdestroyed - %s\n", CACHE_NAME(i)); + } + } + fprintf(stderr, "%s - end -\n", msg); +} +#endif + +Bool nxagentReconnectAllFonts(void *p0) +{ + int cid; + Bool fontSuccess = True; + + reconnectFlexibility = *((int *) p0); + + #if defined(NXAGENT_RECONNECT_DEBUG) || defined(NXAGENT_RECONNECT_FONT_DEBUG) + fprintf(stderr, "nxagentReconnectAllFonts\n"); + #endif + + /* + * The resource type RT_NX_FONT is created on the + * server client only, so we can avoid to loop + * through all the clients. + */ + + FindClientResourcesByType(clients[serverClient -> index], RT_NX_FONT, + (FindResType) nxagentFontReconnect, &fontSuccess); + + for (cid = 0; cid < MAXCLIENTS; cid++) + { + if (clients[cid]) + { + FindClientResourcesByType(clients[cid], RT_FONT, + (FindResType) nxagentFontReconnect, &fontSuccess); + } + } + + if (fontSuccess) + { + nxagentCleanCacheAfterReconnect(); + } + + return fontSuccess; +} + +static void nxagentFailedFontReconnect(FontPtr pFont, XID param1, pointer param2) +{ + int i; + nxagentPrivFont *privFont; + Bool *pBool = (Bool*)param2; + + if (pFont == NULL) + return; + + privFont = nxagentFontPriv(pFont); + + #ifdef NXAGENT_RECONNECT_FONT_DEBUG + fprintf(stderr, "nxagentFailedFontReconnect: pFont %p - XID %lx - name %s\n", + (void*) pFont, (privFont -> font_struct) ? nxagentFont(pFont) : 0, + privFont -> fontName); + #endif + + for (i = 0; i < CACHE_INDEX; i++) + { + if (strcasecmp(CACHE_NAME(i), privFont -> fontName) == 0) + { + #ifdef NXAGENT_RECONNECT_FONT_DEBUG + fprintf(stderr, "\tfound in cache"); + #endif + + if (!CACHE_FSTRUCT(i)) + { + #ifdef NXAGENT_RECONNECT_FONT_DEBUG + fprintf(stderr, " --- font struct not valid\n"); + #endif + + break; + } + + nxagentFontStruct(pFont) = CACHE_FSTRUCT(i); + + return; + } + } + + if (i == CACHE_INDEX) + { + FatalError("nxagentFailedFontReconnect: font not found in cache."); + } + + privFont -> font_struct = nxagentLoadQueryFont(nxagentDisplay, privFont -> fontName, pFont); + + if (privFont -> font_struct == NULL) + { + privFont -> font_struct = nxagentLoadBestQueryFont(nxagentDisplay, privFont -> fontName, pFont); + } + + if (privFont->font_struct != NULL) + { + #ifdef NXAGENT_RECONNECT_FONT_DEBUG + fprintf(stderr, "\tXID %lx\n", privFont -> font_struct -> fid); + #endif + + CACHE_FSTRUCT(i) = privFont -> font_struct; + } + else + { + #ifdef NXAGENT_RECONNECT_FONT_DEBUG + fprintf(stderr, "nxagentFailedFontReconnect: failed\n"); + #endif + + #ifdef NXAGENT_RECONNECT_FONT_DEBUG + fprintf(stderr, "nxagentFailedFontReconnect: reconnection of font [%s] failed.\n", + privFont -> fontName); + #endif + + nxagentSetReconnectError(FAILED_RESUME_FONTS_ALERT, + "Couldn't restore the font '%s'", privFont -> fontName); + + *pBool = False; + } + + return; +} + +static void nxagentFreeFailedToReconnectFonts() +{ + if (nxagentFailedToReconnectFonts.font != NULL) + { + free(nxagentFailedToReconnectFonts.font); + nxagentFailedToReconnectFonts.font = NULL; + } + + if (nxagentFailedToReconnectFonts.id != NULL) + { + free(nxagentFailedToReconnectFonts.id); + nxagentFailedToReconnectFonts.id = NULL; + } + + nxagentFailedToReconnectFonts.size = 0; + nxagentFailedToReconnectFonts.index = 0; +} + +Bool nxagentReconnectFailedFonts(void *p0) +{ + int i; + int attempt = 1; + const int maxAttempt = 5; + + char **fontPaths, **localFontPaths, **newFontPaths; + char fontServerPath[256]; + int nPaths = 0; + + Bool repeat = True; + Bool fontSuccess = True; + + reconnectFlexibility = *((int *) p0); + + #ifdef NXAGENT_RECONNECT_FONT_DEBUG + fprintf(stderr, "nxagentReconnectFailedFonts: \n"); + #endif + + if (nxagentGetFontServerPath(fontServerPath) == False) + { + #ifdef WARNING + fprintf(stderr, "nxagentReconnectFailedFonts: WARNING! " + "Font server tunneling not retrieved.\n"); + #endif + } + + #ifdef NXAGENT_RECONNECT_FONT_DEBUG + fprintf(stderr, "nxagentReconnectFailedFonts: font server path [%s]\n", fontServerPath); + #endif + + fontPaths = XGetFontPath(nxagentDisplay, &nPaths); + + if ((newFontPaths = malloc((nPaths + 1) * sizeof(char *))) == NULL) + { + FatalError("nxagentReconnectFailedFonts: malloc failed."); + } + + memcpy(newFontPaths, fontPaths, nPaths * sizeof(char*)); + + localFontPaths = newFontPaths; + localFontPaths += nPaths; + *localFontPaths = fontServerPath; + + while(repeat) + { + #ifdef NXAGENT_RECONNECT_FONT_DEBUG + fprintf(stderr, "nxagentReconnectFailedFonts: attempt [%d].\n", attempt); + #endif + + repeat = False; + + XSetFontPath(nxagentDisplay, newFontPaths, nPaths + 1); + nxagentFreeRemoteFontList(&nxagentRemoteFontList); + nxagentListRemoteFonts("*", nxagentMaxFontNames); + + for(i = 0; i < nxagentFailedToReconnectFonts.index; i++) + { + fontSuccess = True; + + if(nxagentFailedToReconnectFonts.font[i]) + { + nxagentFailedFontReconnect(nxagentFailedToReconnectFonts.font[i], + nxagentFailedToReconnectFonts.id[i], + &fontSuccess); + + if (fontSuccess) + { + nxagentFailedToReconnectFonts.font[i] = NULL; + } + else + { + repeat = True; + } + + } + } + + attempt++; + + if (attempt > maxAttempt) + { + nxagentFreeFailedToReconnectFonts(); + + XSetFontPath(nxagentDisplay, fontPaths, nPaths); + nxagentFreeRemoteFontList(&nxagentRemoteFontList); + nxagentListRemoteFonts("*", nxagentMaxFontNames); + + XFreeFontPath(fontPaths); + free(newFontPaths); + + return False; + } + } + + nxagentFreeFailedToReconnectFonts(); + + XSetFontPath(nxagentDisplay, fontPaths, nPaths); + + XFreeFontPath(fontPaths); + free(newFontPaths); + + nxagentCleanCacheAfterReconnect(); + + return True; +} + +Bool nxagentDisconnectAllFonts() +{ + int cid; + Bool fontSuccess = True; + + #if defined(NXAGENT_RECONNECT_DEBUG) || defined(NXAGENT_RECONNECT_FONT_DEBUG) + fprintf(stderr, "nxagentDisconnectAllFonts\n"); + #endif + + nxagentFreeRemoteFontList(&nxagentRemoteFontList); + nxagentFreeCacheBeforeReconnect(); + + /* + * The resource type RT_NX_FONT is created on the + * server client only, so we can avoid to loop + * through all the clients. + */ + + FindClientResourcesByType(clients[serverClient -> index], RT_NX_FONT, + (FindResType) nxagentFontDisconnect, &fontSuccess); + + for(cid = 0; cid < MAXCLIENTS; cid++) + { + if( clients[cid] && fontSuccess ) + { + FindClientResourcesByType(clients[cid], RT_FONT, + (FindResType) nxagentFontDisconnect, &fontSuccess); + } + } + + return True; +} + +static Bool nxagentGetFontServerPath(char * fontServerPath) +{ + char path[256]; + + if (NXGetFontParameters(nxagentDisplay, 256, path) == True) + { + if (*path != '\0') + { + strncpy(fontServerPath, path + 1, *path); + + *(fontServerPath + *path) = '\0'; + + #ifdef TEST + fprintf(stderr, "nxagentGetFontServerPath: Got path [%s].\n", + fontServerPath); + #endif + } + else + { + #ifdef TEST + fprintf(stderr, "nxagentGetFontServerPath: WARNING! Font server tunneling not enabled.\n"); + #endif + + return False; + } + } + else + { + #ifdef TEST + fprintf(stderr, "nxagentGetFontServerPath: WARNING! Failed to get path for font server tunneling.\n"); + #endif + + return False; + } + + return True; +} + +void nxagentVerifyDefaultFontPath(void) +{ + struct stat dirStat; + static char *fontPath; + + #ifdef TEST + fprintf(stderr, "nxagentVerifyDefaultFontPath: Going to search for one or more valid font paths.\n"); + #endif + + fontPath = malloc(strlen(defaultFontPath) + 1); + + if (fontPath == NULL) + { + #ifdef WARNING + fprintf(stderr, "nxagentVerifyDefaultFontPath: WARNING! Unable to allocate memory for a new font path. " + "Using the default font path [%s].\n", validateString(defaultFontPath)); + #endif + + return; + } + + /* + * Set the default font path as the first choice. + */ + + strcpy(fontPath, defaultFontPath); + + if (stat(NXAGENT_DEFAULT_FONT_DIR, &dirStat) == 0 && + S_ISDIR(dirStat.st_mode) != 0) + { + /* + * Let's use the old "/usr/X11R6/lib/X11/fonts" style. + */ + + #ifdef TEST + fprintf(stderr, "nxagentVerifyDefaultFontPath: Assuming fonts in directory [%s].\n", + validateString(NXAGENT_DEFAULT_FONT_DIR)); + #endif + + if (*fontPath != '\0') + { + fontPath = realloc(fontPath, strlen(fontPath) + strlen(NXAGENT_DEFAULT_FONT_PATH) + 2); + strcat(fontPath, ","); + } + else + { + fontPath = realloc(fontPath, strlen(fontPath) + strlen(NXAGENT_DEFAULT_FONT_PATH) + 1); + } + + strcat(fontPath, NXAGENT_DEFAULT_FONT_PATH); + } + + if (stat(NXAGENT_ALTERNATE_FONT_DIR, &dirStat) == 0 && + S_ISDIR(dirStat.st_mode) != 0) + { + /* + * Let's use the new "/usr/share/X11/fonts" path. + */ + + #ifdef TEST + fprintf(stderr, "nxagentVerifyDefaultFontPath: Assuming fonts in directory [%s].\n", + validateString(NXAGENT_ALTERNATE_FONT_DIR)); + #endif + + if (*fontPath != '\0') + { + fontPath = realloc(fontPath, strlen(fontPath) + strlen(NXAGENT_ALTERNATE_FONT_PATH) + 2); + strcat(fontPath, ","); + } + else + { + fontPath = realloc(fontPath, strlen(fontPath) + strlen(NXAGENT_ALTERNATE_FONT_PATH) + 1); + } + + strcat(fontPath, NXAGENT_ALTERNATE_FONT_PATH); + } + + if (stat(NXAGENT_ALTERNATE_FONT_DIR_2, &dirStat) == 0 && + S_ISDIR(dirStat.st_mode) != 0) + { + /* + * Let's use the "/usr/share/fonts/X11" path. + */ + + #ifdef TEST + fprintf(stderr, "nxagentVerifyDefaultFontPath: Assuming fonts in directory [%s].\n", + validateString(NXAGENT_ALTERNATE_FONT_DIR_2)); + #endif + + if (*fontPath != '\0') + { + fontPath = realloc(fontPath, strlen(fontPath) + strlen(NXAGENT_ALTERNATE_FONT_PATH_2) + 2); + strcat(fontPath, ","); + } + else + { + fontPath = realloc(fontPath, strlen(fontPath) + strlen(NXAGENT_ALTERNATE_FONT_PATH_2) + 1); + } + + strcat(fontPath, NXAGENT_ALTERNATE_FONT_PATH_2); + } + + if (stat(NXAGENT_ALTERNATE_FONT_DIR_3, &dirStat) == 0 && + S_ISDIR(dirStat.st_mode) != 0) + { + /* + * Let's use the "/usr/share/fonts" path. + */ + + #ifdef TEST + fprintf(stderr, "nxagentVerifyDefaultFontPath: Assuming fonts in directory [%s].\n", + validateString(NXAGENT_ALTERNATE_FONT_DIR_3)); + #endif + + if (*fontPath != '\0') + { + fontPath = realloc(fontPath, strlen(fontPath) + strlen(NXAGENT_ALTERNATE_FONT_PATH_3) + 2); + strcat(fontPath, ","); + } + else + { + fontPath = realloc(fontPath, strlen(fontPath) + strlen(NXAGENT_ALTERNATE_FONT_PATH_3) + 1); + } + + strcat(fontPath, NXAGENT_ALTERNATE_FONT_PATH_3); + } + + if (*fontPath == '\0') + { + #ifdef WARNING + fprintf(stderr, "nxagentVerifyDefaultFontPath: WARNING! Can't find a valid font directory.\n"); + + fprintf(stderr, "nxagentVerifyDefaultFontPath: WARNING! Using font path [%s].\n", + validateString(defaultFontPath)); + #endif + } + else + { + defaultFontPath = fontPath; + + #ifdef TEST + fprintf(stderr, "nxagentVerifyDefaultFontPath: Using font path [%s].\n", + validateString(defaultFontPath)); + #endif + } + + return; +} + +XFontStruct* nxagentLoadQueryFont(register Display *dpy, char *name, FontPtr pFont) +{ + XFontStruct* fs; + xCharInfo *xcip; + + fs = (XFontStruct *) malloc (sizeof (XFontStruct)); + + if (fs == NULL) + { + #ifdef WARNING + fprintf(stderr, "nxagentLoadQueryFont: WARNING! Failed allocation of XFontStruct.\n"); + #endif + + return (XFontStruct *)NULL; + } + + #ifdef NXAGENT_RECONNECT_FONT_DEBUG + fprintf(stderr, "nxagentLoadQueryFont: Looking for font '%s'.\n", name); + #endif + + if (nxagentFontLookUp(name) == 0) + { + #ifdef DEBUG + fprintf(stderr, "nxagentLoadQueryFont: WARNING! Font not found '%s'.\n", name); + #endif + + Xfree(fs); + + return (XFontStruct *) NULL; + } + + fs -> ext_data = NULL; /* Hook for extension to hang data.*/ + fs -> fid = XLoadFont(dpy, name); /* Font id for this font. */ + fs -> direction = pFont->info.drawDirection; /* Hint about the direction font is painted. */ + fs -> min_char_or_byte2 = pFont->info.firstCol; /* First character. */ + fs -> max_char_or_byte2 = pFont->info.lastCol; /* Last character. */ + fs -> min_byte1 = pFont->info.firstRow; /* First row that exists. */ + fs -> max_byte1 = pFont->info.lastRow; /* Last row that exists. */ + fs -> all_chars_exist = pFont->info.allExist; /* Flag if all characters have nonzero size. */ + fs -> default_char = pFont->info.defaultCh; /* Char to print for undefined character. */ + fs -> n_properties = pFont->info.nprops; /* How many properties there are. */ + + /* + * If no properties defined for the font, then it is bad + * font, but shouldn't try to read nothing. + */ + + if (fs -> n_properties > 0) + { + register long nbytes; + + nbytes = pFont -> info.nprops * sizeof(XFontProp); + fs -> properties = (XFontProp *) Xalloc((unsigned) nbytes); + + if (fs -> properties == NULL) + { + #ifdef WARNING + fprintf(stderr, "nxagentLoadQueryFont: WARNING! Failed allocation of XFontProp."); + #endif + + Xfree((char *) fs); + return (XFontStruct *) NULL; + } + + memmove(fs -> properties, pFont -> info.props, nbytes); + } + + xcip = (xCharInfo *) &pFont -> info.ink_minbounds; + + fs -> min_bounds.lbearing = cvtINT16toShort(xcip -> leftSideBearing); + fs -> min_bounds.rbearing = cvtINT16toShort(xcip -> rightSideBearing); + fs -> min_bounds.width = cvtINT16toShort(xcip -> characterWidth); + fs -> min_bounds.ascent = cvtINT16toShort(xcip -> ascent); + fs -> min_bounds.descent = cvtINT16toShort(xcip -> descent); + fs -> min_bounds.attributes = xcip -> attributes; + + xcip = (xCharInfo *) &pFont -> info.ink_maxbounds; + + fs -> max_bounds.lbearing = cvtINT16toShort(xcip -> leftSideBearing); + fs -> max_bounds.rbearing = cvtINT16toShort(xcip -> rightSideBearing); + fs -> max_bounds.width = cvtINT16toShort(xcip -> characterWidth); + fs -> max_bounds.ascent = cvtINT16toShort(xcip -> ascent); + fs -> max_bounds.descent = cvtINT16toShort(xcip -> descent); + fs -> max_bounds.attributes = xcip -> attributes; + + fs -> per_char = NULL; /* First_char to last_char information. */ + fs -> ascent = pFont->info.fontAscent; /* Logical extent above baseline for spacing. */ + fs -> descent = pFont->info.fontDescent; /* Logical decent below baseline for spacing. */ + + return fs; +} + +int nxagentFreeFont(XFontStruct *fs) +{ + + if (fs -> per_char) + { + #ifdef USE_XF86BIGFONT + _XF86BigfontFreeFontMetrics(fs); + #else + Xfree ((char *) fs->per_char); + #endif + } + + if (fs -> properties) + { + Xfree (fs->properties); + } + + XFree(fs); + + return 1; +} + + +int nxagentSplitString(char *string, char *fields[], int nfields, char *sep) +{ + int seplen; + int fieldlen; + int last; + int len; + int i; + + char *current; + char *next; + + seplen = strlen(sep); + len = strlen(string); + + current = string; + + i = 0; + last = 0; + + for (;;) + { + next = NULL; + + if (current < string + len) + { + next = strstr(current, sep); + } + + if (next == NULL) + { + next = string + len; + last = 1; + } + + fieldlen = next - current; + + if (i < nfields) + { + fields[i] = (char *) malloc(fieldlen + 1); + strncpy(fields[i], current, fieldlen); + *(fields[i] + fieldlen) = 0; + } + + current = next + seplen; + + i++; + + if (last == 1) + { + break; + } + } + + return i; +} + |