#include <stdlib.h>
#include <unistd.h>
#include <ctype.h>
#include <stdio.h>
#include <math.h>
#include <X11/IntrinsicP.h>
#include <X11/StringDefs.h>
#include <Xm/Xm.h>
#if XmVersion > 1001
#include <Xm/ManagerP.h>
#else
#include <Xm/XmP.h>
#endif
#include <Xm/Form.h>
#include <Xm/List.h>
#include <Xm/Label.h>
#include <Xm/LabelG.h>
#include <Xm/PushB.h>
#include <Xm/PanedW.h>
#include <Xm/PushBG.h>
#include <Xm/SeparatoG.h>
#include <Xm/TextF.h>
#include <Xm/RowColumn.h>
#include <Xm/DrawingA.h>
#include <Xm/MessageB.h>
#include <DPS/dpsXclient.h>
#include "dpsXcommonI.h"
#include <DPS/dpsXcommon.h>
#include <DPS/dpsXshare.h>
#include <DPS/PSres.h>
#include <DPS/FontSBP.h>
#include "FSBwraps.h"
#include "FontSBI.h"
#include <DPS/FontSample.h>
#include <DPS/FontCreato.h>
#include <pwd.h>
#define PATH_BUF_SIZE 1024
#define UnsharedCS(str) XmStringCreate(str, XmSTRING_DEFAULT_CHARSET)
#define CS(str, w) _FSBCreateSharedCS(str, w)
static XmString CSempty;
#define Canonical(str) XrmQuarkToString(XrmStringToQuark(str))
static float defaultSizeList[] = {
#ifndef DEFAULT_SIZE_LIST
8, 10, 12, 14, 16, 18, 24, 36, 48, 72
#else
DEFAULT_SIZE_LIST
#endif
};
#ifndef DEFAULT_SIZE_LIST_COUNT
#define DEFAULT_SIZE_LIST_COUNT 10
#endif
#ifndef DEFAULT_SIZE
static float default_size = 12.0;
#else
static float default_size = DEFAULT_SIZE
#endif
#ifndef DEFAULT_RESOURCE_PATH
#define DEFAULT_RESOURCE_PATH NULL
#endif
#ifndef DEFAULT_MAX_PENDING
#define DEFAULT_MAX_PENDING 10
#endif
#define Offset(field) XtOffsetOf(FontSelectionBoxRec, fsb.field)
static XtResource resources[] = {
{XtNcontext, XtCContext, XtRDPSContext, sizeof(DPSContext),
Offset(context), XtRDPSContext, (XtPointer) NULL},
{XtNpreviewString, XtCPreviewString, XtRString, sizeof(String),
Offset(preview_string), XtRString, (XtPointer) NULL},
{XtNsizes, XtCSizes, XtRFloatList, sizeof(float*),
Offset(sizes), XtRImmediate, (XtPointer) defaultSizeList},
{XtNsizeCount, XtCSizeCount, XtRInt, sizeof(int),
Offset(size_count), XtRImmediate, (XtPointer) DEFAULT_SIZE_LIST_COUNT},
{XtNdefaultResourcePath, XtCDefaultResourcePath, XtRString, sizeof(String),
Offset(default_resource_path), XtRImmediate,
(XtPointer) DEFAULT_RESOURCE_PATH},
{XtNresourcePathOverride, XtCResourcePathOverride,
XtRString, sizeof(String),
Offset(resource_path_override), XtRString, (XtPointer) NULL},
{XtNuseFontName, XtCUseFontName, XtRBoolean, sizeof(Boolean),
Offset(use_font_name), XtRImmediate, (XtPointer) True},
{XtNfontName, XtCFontName, XtRString, sizeof(String),
Offset(font_name), XtRString, (XtPointer) NULL},
{XtNfontFamily, XtCFontFamily, XtRString, sizeof(String),
Offset(font_family), XtRString, (XtPointer) NULL},
{XtNfontFace, XtCFontFace, XtRString, sizeof(String),
Offset(font_face), XtRString, (XtPointer) NULL},
{XtNfontBlend, XtCFontBlend, XtRString, sizeof(String),
Offset(font_blend), XtRString, (XtPointer) NULL},
{XtNfontSize, XtCFontSize, XtRFloat, sizeof(String),
Offset(font_size), XtRFloat, (XtPointer) &default_size},
{XtNfontNameMultiple, XtCFontNameMultiple, XtRBoolean, sizeof(Boolean),
Offset(font_name_multiple), XtRImmediate, (XtPointer) False},
{XtNfontFamilyMultiple, XtCFontFamilyMultiple, XtRBoolean, sizeof(Boolean),
Offset(font_family_multiple), XtRImmediate, (XtPointer) False},
{XtNfontFaceMultiple, XtCFontFaceMultiple, XtRBoolean, sizeof(Boolean),
Offset(font_face_multiple), XtRImmediate, (XtPointer) False},
{XtNfontSizeMultiple, XtCFontSizeMultiple, XtRBoolean, sizeof(Boolean),
Offset(font_size_multiple), XtRImmediate, (XtPointer) False},
{XtNgetServerFonts, XtCGetServerFonts, XtRBoolean, sizeof(Boolean),
Offset(get_server_fonts), XtRImmediate, (XtPointer) True},
{XtNgetAFM, XtCGetAFM, XtRBoolean, sizeof(Boolean),
Offset(get_afm), XtRImmediate, (XtPointer) False},
{XtNautoPreview, XtCAutoPreview, XtRBoolean, sizeof(Boolean),
Offset(auto_preview), XtRImmediate, (XtPointer) True},
{XtNpreviewOnChange, XtCPreviewOnChange, XtRBoolean, sizeof(Boolean),
Offset(preview_on_change), XtRImmediate, (XtPointer) True},
{XtNundefUnusedFonts, XtCUndefUnusedFonts, XtRBoolean, sizeof(Boolean),
Offset(undef_unused_fonts), XtRImmediate, (XtPointer) True},
{XtNmaxPendingDeletes, XtCMaxPendingDeletes, XtRCardinal, sizeof(Cardinal),
Offset(max_pending_deletes), XtRImmediate,
(XtPointer) DEFAULT_MAX_PENDING},
{XtNmakeFontsShared, XtCMakeFontsShared, XtRBoolean, sizeof(Boolean),
Offset(make_fonts_shared), XtRImmediate, (XtPointer) True},
{XtNshowSampler, XtCShowSampler, XtRBoolean, sizeof(Boolean),
Offset(show_sampler), XtRImmediate, (XtPointer) False},
{XtNshowSamplerButton, XtCShowSamplerButton, XtRBoolean, sizeof(Boolean),
Offset(show_sampler_button), XtRImmediate, (XtPointer) True},
{XtNtypographicSort, XtCTypographicSort, XtRBoolean, sizeof(Boolean),
Offset(typographic_sort), XtRImmediate, (XtPointer) True},
{XtNokCallback, XtCCallback, XtRCallback, sizeof(XtCallbackList),
Offset(ok_callback), XtRCallback, (XtPointer) NULL},
{XtNapplyCallback, XtCCallback, XtRCallback, sizeof(XtCallbackList),
Offset(apply_callback), XtRCallback, (XtPointer) NULL},
{XtNresetCallback, XtCCallback, XtRCallback, sizeof(XtCallbackList),
Offset(reset_callback), XtRCallback, (XtPointer) NULL},
{XtNcancelCallback, XtCCallback, XtRCallback, sizeof(XtCallbackList),
Offset(cancel_callback), XtRCallback, (XtPointer) NULL},
{XtNvalidateCallback, XtCCallback, XtRCallback, sizeof(XtCallbackList),
Offset(validate_callback), XtRCallback, (XtPointer) NULL},
{XtNfaceSelectCallback, XtCCallback, XtRCallback, sizeof(XtCallbackList),
Offset(face_select_callback), XtRCallback, (XtPointer) NULL},
{XtNcreateSamplerCallback, XtCCallback, XtRCallback,
sizeof(XtCallbackList), Offset(create_sampler_callback),
XtRCallback, (XtPointer) NULL},
{XtNcreateCreatorCallback, XtCCallback, XtRCallback,
sizeof(XtCallbackList), Offset(create_creator_callback),
XtRCallback, (XtPointer) NULL},
{XtNvalueChangedCallback, XtCCallback, XtRCallback, sizeof(XtCallbackList),
Offset(value_changed_callback), XtRCallback, (XtPointer) NULL},
{XtNpaneChild, XtCReadOnly, XtRWidget, sizeof(Widget),
Offset(pane_child), XtRWidget, (XtPointer) NULL},
{XtNpreviewChild, XtCReadOnly, XtRWidget, sizeof(Widget),
Offset(preview_child), XtRWidget, (XtPointer) NULL},
{XtNpanelChild, XtCReadOnly, XtRWidget, sizeof(Widget),
Offset(panel_child), XtRWidget, (XtPointer) NULL},
{XtNfamilyLabelChild, XtCReadOnly, XtRWidget, sizeof(Widget),
Offset(family_label_child), XtRWidget, (XtPointer) NULL},
{XtNfamilyMultipleLabelChild, XtCReadOnly, XtRWidget, sizeof(Widget),
Offset(family_multiple_label_child), XtRWidget, (XtPointer) NULL},
{XtNfamilyScrolledListChild, XtCReadOnly, XtRWidget, sizeof(Widget),
Offset(family_scrolled_list_child), XtRWidget, (XtPointer) NULL},
{XtNfaceLabelChild, XtCReadOnly, XtRWidget, sizeof(Widget),
Offset(face_label_child), XtRWidget, (XtPointer) NULL},
{XtNfaceMultipleLabelChild, XtCReadOnly, XtRWidget, sizeof(Widget),
Offset(face_multiple_label_child), XtRWidget, (XtPointer) NULL},
{XtNfaceScrolledListChild, XtCReadOnly, XtRWidget, sizeof(Widget),
Offset(face_scrolled_list_child), XtRWidget, (XtPointer) NULL},
{XtNsizeLabelChild, XtCReadOnly, XtRWidget, sizeof(Widget),
Offset(size_label_child), XtRWidget, (XtPointer) NULL},
{XtNsizeTextFieldChild, XtCReadOnly, XtRWidget, sizeof(Widget),
Offset(size_text_field_child), XtRWidget, (XtPointer) NULL},
{XtNsizeOptionMenuChild, XtCReadOnly, XtRWidget, sizeof(Widget),
Offset(size_option_menu_child), XtRWidget, (XtPointer) NULL},
{XtNsizeMultipleLabelChild, XtCReadOnly, XtRWidget, sizeof(Widget),
Offset(size_multiple_label_child), XtRWidget, (XtPointer) NULL},
{XtNpreviewButtonChild, XtCReadOnly, XtRWidget, sizeof(Widget),
Offset(preview_button_child), XtRWidget, (XtPointer) NULL},
{XtNsamplerButtonChild, XtCReadOnly, XtRWidget, sizeof(Widget),
Offset(sampler_button_child), XtRWidget, (XtPointer) NULL},
{XtNseparatorChild, XtCReadOnly, XtRWidget, sizeof(Widget),
Offset(separator_child), XtRWidget, (XtPointer) NULL},
{XtNokButtonChild, XtCReadOnly, XtRWidget, sizeof(Widget),
Offset(ok_button_child), XtRWidget, (XtPointer) NULL},
{XtNapplyButtonChild, XtCReadOnly, XtRWidget, sizeof(Widget),
Offset(apply_button_child), XtRWidget, (XtPointer) NULL},
{XtNresetButtonChild, XtCReadOnly, XtRWidget, sizeof(Widget),
Offset(reset_button_child), XtRWidget, (XtPointer) NULL},
{XtNcancelButtonChild, XtCReadOnly, XtRWidget, sizeof(Widget),
Offset(cancel_button_child), XtRWidget, (XtPointer) NULL},
{XtNmultipleMasterButtonChild, XtCReadOnly, XtRWidget, sizeof(Widget),
Offset(multiple_master_button_child), XtRWidget, (XtPointer) NULL}
};
static Boolean ChangeBlends(Widget w, String base_name, String blend_name, FSBBlendAction action, int *axis_values, float *axis_percents);
static Boolean DownloadFontName(Widget w, String name);
static Boolean MatchFontFace(Widget w, String old_face, String new_family, String *new_face);
static Boolean SetValues(Widget old, Widget req, Widget new, ArgList args, Cardinal *num_args);
static Boolean Verify(FontSelectionBoxWidget fsb, FSBValidateCallbackRec *cb, String afm, Boolean doIt);
static String FindAFM(Widget w, String name);
static String FindFontFile(Widget w, String name);
static XtGeometryResult GeometryManager(Widget w, XtWidgetGeometry *desired, XtWidgetGeometry *allowed);
static void ChangeManaged(Widget w);
static void ClassInitialize(void);
static void ClassPartInitialize(WidgetClass widget_class);
static void Destroy(Widget widget);
static void DisplayFontFamilies(FontSelectionBoxWidget fsb);
static void FontFamilyFaceBlendToName(Widget w, String family, String face, String blend, String *font_name);
static void FontFamilyFaceToName(Widget w, String family, String face, String *font_name);
static void FontNameToFamilyFace(Widget w, String font_name, String *family, String *face);
static void FontNameToFamilyFaceBlend(Widget w, String font_name, String *family, String *face, String *blend);
static void FreeFontRec(FontRec *f);
static void GetBlendInfo(Widget w, String name, int *num_axes_return, int *num_designs_return, String **axis_names_return, float **blend_positions_return, int **blend_map_count_return, int **blend_design_coords_return, float **blend_normalized_coords_return);
static void GetBlendList(Widget w, String name, int *count_return, String **blend_return, String **font_name_return, float **axis_values_return);
static void GetFaceList(Widget w, String family, int *count, String **face_list, String **font_list);
static void GetFamilyList(Widget w, int *count, String **list);
static void GetTextDimensions(Widget w, String text, String font, double size, double x, double y, float *dx, float *dy, float *left, float *right, float *top, float *bottom);
static void Initialize(Widget request, Widget new, ArgList args, Cardinal *num_args);
static void ReadBlends(FontSelectionBoxWidget fsb);
static void RefreshFontList(Widget w);
static void Resize(Widget widget);
static void SetFontFamilyFace(Widget w, String family, String face, Bool family_multiple, Bool face_multiple);
static void SetFontFamilyFaceBlend(Widget w, String family, String face, String blend, Bool family_multiple, Bool face_multiple);
static void SetFontName(Widget w, String name, Bool name_multiple);
static void SetFontSize(Widget w, double size, Bool size_multiple);
static void SetUpCurrentSelections(FontSelectionBoxWidget fsb);
static void UndefUnusedFonts(Widget w);
static void WriteBlends(FontSelectionBoxWidget fsb);
FontSelectionBoxClassRec fontSelectionBoxClassRec = {
{
(WidgetClass) &xmManagerClassRec,
"FontSelectionBox",
sizeof(FontSelectionBoxRec),
ClassInitialize,
ClassPartInitialize,
False,
Initialize,
NULL,
XtInheritRealize,
NULL,
0,
resources,
XtNumber(resources),
NULLQUARK,
True,
XtExposeCompressMultiple,
True,
False,
Destroy,
Resize,
NULL,
SetValues,
NULL,
XtInheritSetValuesAlmost,
NULL,
NULL,
XtVersion,
NULL,
NULL,
XtInheritQueryGeometry,
NULL,
NULL,
},
{
GeometryManager,
ChangeManaged,
XtInheritInsertChild,
XtInheritDeleteChild,
NULL,
},
{
NULL,
0,
0,
NULL,
NULL,
NULL,
NULL,
},
{
XtInheritTranslations,
NULL,
0,
NULL,
0,
XmInheritParentProcess,
NULL,
},
{
SetFontName,
SetFontFamilyFace,
SetFontSize,
RefreshFontList,
GetFamilyList,
GetFaceList,
UndefUnusedFonts,
DownloadFontName,
MatchFontFace,
FontNameToFamilyFace,
FontFamilyFaceToName,
FindAFM,
FindFontFile,
GetTextDimensions,
SetFontFamilyFaceBlend,
FontNameToFamilyFaceBlend,
FontFamilyFaceBlendToName,
GetBlendList,
GetBlendInfo,
ChangeBlends,
NULL,
}
};
WidgetClass fontSelectionBoxWidgetClass =
(WidgetClass) &fontSelectionBoxClassRec;
static Boolean CvtStringToFloatList(
Display *dpy,
XrmValuePtr args,
Cardinal *num_args,
XrmValuePtr from,
XrmValuePtr to,
XtPointer *data)
{
register int i, count = 1;
register char *ch, *start = from->addr;
static float *list;
char save;
if (*num_args != 0) {
XtAppErrorMsg(XtDisplayToApplicationContext(dpy),
"cvtStringToFloatList", "wrongParameters",
"XtToolkitError",
"String to integer list conversion needs no extra arguments",
(String *) NULL, (Cardinal *) NULL);
}
if (to->addr != NULL && to->size < sizeof(int *)) {
to->size = sizeof(int *);
return False;
}
if (start == NULL || *start == '\0') list = NULL;
else {
for (ch = start; *ch != '\0'; ch++) {
if (!isdigit(*ch) && *ch != '.' && *ch != ',') {
XtDisplayStringConversionWarning(dpy, from->addr, "FloatList");
return False;
}
if (*ch == ',') count++;
}
list = (float *) XtCalloc(count+1, sizeof(float));
for (i = 0; i < count; i++) {
for (ch = start; *ch != ',' && *ch != '\0'; ch++) {}
save = *ch;
*ch = '\0';
list[i] = atof(start);
*ch = save;
start = ch + 1;
}
}
if (to->addr == NULL) to->addr = (caddr_t) &list;
else *(float **) to->addr = list;
to->size = sizeof(int *);
return True;
}
static void FloatListDestructor(
XtAppContext app,
XrmValuePtr to,
XtPointer converter_data,
XrmValuePtr args,
Cardinal *num_args)
{
float *list = (float *) to->addr;
if (list == NULL) return;
XtFree((XtPointer) list);
}
XmString _FSBCreateSharedCS(String str, Widget w)
{
XrmValue src, dst;
XmString result;
src.addr = str;
src.size = strlen(str);
dst.addr = (caddr_t) &result;
dst.size = sizeof(result);
if (XtConvertAndStore(w, XtRString, &src, XmRXmString, &dst)) {
return result;
} else return NULL;
}
static Boolean ScanFloat(char *src, float *f, char **past)
{
char buf[20], *ch;
int countDecimals;
ch = buf;
countDecimals = 0;
while (*src == '.' || isdigit(*src)) {
if (*src == '.') {
if (countDecimals) return False;
else countDecimals++;
}
*ch++ = *src++;
}
if (ch == buf) return False;
*ch++ = '\0';
*f = atof(buf);
*past = src;
return True;
}
static Boolean ScanInt(char *src, int *i, char **past)
{
char buf[20], *ch;
ch = buf;
while (isdigit(*src)) *ch++ = *src++;
if (ch == buf) return False;
*ch++ = '\0';
*i = atoi(buf);
*past = src;
return True;
}
static void ClassInitialize(void)
{
XtSetTypeConverter(XtRString, XtRFloatList,
CvtStringToFloatList, (XtConvertArgList) NULL, 0,
XtCacheAll | XtCacheRefCount, FloatListDestructor);
CSempty = UnsharedCS("");
}
static void ClassPartInitialize(WidgetClass widget_class)
{
register FontSelectionBoxWidgetClass wc =
(FontSelectionBoxWidgetClass) widget_class;
FontSelectionBoxWidgetClass super =
(FontSelectionBoxWidgetClass) wc->core_class.superclass;
if (wc->fsb_class.set_font_name == InheritSetFontName) {
wc->fsb_class.set_font_name = super->fsb_class.set_font_name;
}
if (wc->fsb_class.set_font_family_face == InheritSetFontFamilyFace) {
wc->fsb_class.set_font_family_face =
super->fsb_class.set_font_family_face;
}
if (wc->fsb_class.set_font_size == InheritSetFontSize) {
wc->fsb_class.set_font_size = super->fsb_class.set_font_size;
}
if (wc->fsb_class.refresh_font_list == InheritRefreshFontList) {
wc->fsb_class.refresh_font_list = super->fsb_class.refresh_font_list;
}
if (wc->fsb_class.get_family_list == InheritGetFamilyList) {
wc->fsb_class.get_family_list = super->fsb_class.get_family_list;
}
if (wc->fsb_class.get_face_list == InheritGetFaceList) {
wc->fsb_class.get_face_list = super->fsb_class.get_face_list;
}
if (wc->fsb_class.undef_unused_fonts == InheritUndefUnusedFonts) {
wc->fsb_class.undef_unused_fonts = super->fsb_class.undef_unused_fonts;
}
if (wc->fsb_class.download_font_name == InheritDownloadFontName) {
wc->fsb_class.download_font_name = super->fsb_class.download_font_name;
}
if (wc->fsb_class.match_font_face == InheritMatchFontFace) {
wc->fsb_class.match_font_face = super->fsb_class.match_font_face;
}
if (wc->fsb_class.font_name_to_family_face ==
InheritFontNameToFamilyFace) {
wc->fsb_class.font_name_to_family_face =
super->fsb_class.font_name_to_family_face;
}
if (wc->fsb_class.font_family_face_to_name ==
InheritFontFamilyFaceToName) {
wc->fsb_class.font_family_face_to_name =
super->fsb_class.font_family_face_to_name;
}
if (wc->fsb_class.find_afm == InheritFindAFM) {
wc->fsb_class.find_afm = super->fsb_class.find_afm;
}
if (wc->fsb_class.find_font_file == InheritFindFontFile) {
wc->fsb_class.find_font_file = super->fsb_class.find_font_file;
}
if (wc->fsb_class.get_text_dimensions == InheritGetTextDimensions) {
wc->fsb_class.get_text_dimensions =
super->fsb_class.get_text_dimensions;
}
if (wc->fsb_class.set_font_family_face_blend ==
InheritSetFontFamilyFaceBlend) {
wc->fsb_class.set_font_family_face_blend =
super->fsb_class.set_font_family_face_blend;
}
if (wc->fsb_class.font_name_to_family_face_blend ==
InheritFontNameToFamilyFaceBlend) {
wc->fsb_class.font_name_to_family_face_blend =
super->fsb_class.font_name_to_family_face_blend;
}
if (wc->fsb_class.font_family_face_blend_to_name ==
InheritFontFamilyFaceBlendToName) {
wc->fsb_class.font_family_face_blend_to_name =
super->fsb_class.font_family_face_blend_to_name;
}
if (wc->fsb_class.get_blend_list == InheritGetBlendList) {
wc->fsb_class.get_blend_list =
super->fsb_class.get_blend_list;
}
if (wc->fsb_class.get_blend_info == InheritGetBlendInfo) {
wc->fsb_class.get_blend_info =
super->fsb_class.get_blend_info;
}
if (wc->fsb_class.change_blends == InheritChangeBlends) {
wc->fsb_class.change_blends =
super->fsb_class.change_blends;
}
}
static String bugFamilies[] = {
"Berkeley", "CaslonFiveForty", "CaslonThree", "GaramondThree",
"Music", "TimesTen", NULL
};
static String fixedFamilies[] = {
"ITC Berkeley Oldstyle", "Caslon 540", "Caslon 3", "Garamond 3",
"Sonata", "Times 10", NULL
};
static String missingFoundries[] = {
"Berthold ", "ITC ", "Linotype ", NULL
};
static int missingFoundryLen[] = {
9, 4, 9, 0
};
static void MungeFontNames(
String name, String family, String fullname, String weight,
String *familyReturn, String *fullnameReturn, String *faceReturn)
{
register char *src, *dst, prev;
char buf[256];
int digits = 0;
int i, diff;
static Bool inited = False;
static String FetteFrakturDfr, LinotextDfr;
if (!inited) {
for (i = 0; fixedFamilies[i] != NULL; i++) {
fixedFamilies[i] = Canonical(fixedFamilies[i]);
}
FetteFrakturDfr = Canonical("FetteFraktur-Dfr");
LinotextDfr = Canonical("Linotext-Dfr");
inited = True;
}
dst = buf;
prev = ' ';
src = fullname;
while (isdigit(*src)) src++;
while (*src == ' ' || *src == '\t') src++;
if (strncmp(src, "pt ", 3) == 0) src += 3;
else if (strncmp(src, "pt. ", 4) == 0) src += 4;
while (*src != '\0') {
if (*src == '*') {
src++;
continue;
}
if (*src == '.') {
if (*(src+1) != ' ') {
prev = *dst++ = ' ';
} else prev = *dst++ = '.';
src++;
continue;
}
if (isdigit(*src)) digits++;
else digits = 0;
if (isupper(*src)) {
if (prev != ' ' && (islower(*(src+1)) || islower(prev))) {
*dst++ = ' ';
prev = *dst++ = *src++;
} else prev = *dst++ = *src++;
} else if (*src == ' ' || *src == '\t') {
if (prev == ' ') {
src++;
continue;
}
prev = *dst++ = ' ';
src++;
} else prev = *dst++ = *src++;
}
if (digits == 5) {
dst -= 5;
}
if (dst > buf && *(dst-1) == ' ') dst--;
*dst = '\0';
if (name == FetteFrakturDfr) {
strcat(buf, " Black Dfr");
} else if (name == LinotextDfr) {
strcat(buf, " Dfr");
}
if (strncmp(fullname, "pt ", 3) == 0) {
src = buf + 2;
while (*++src != '\0') *(src-3) = *src;
*(src-3) = '\0';
}
*fullnameReturn = XtNewString(buf);
for (i = 0; bugFamilies[i] != NULL; i++) {
diff = strcmp(family, bugFamilies[i]);
if (diff < 0) break;
if (diff == 0) {
*familyReturn = fixedFamilies[i];
goto FAMILY_DONE;
}
}
dst = buf;
prev = ' ';
src = family;
while (*src != '\0') {
if (isupper(*src)) {
if (prev != ' ' && (islower(*(src+1)) || islower(prev))) {
*dst++ = ' ';
prev = *dst++ = *src++;
} else prev = *dst++ = *src++;
} else if (*src == ' ' || *src == '\t') {
if (prev == ' ') {
src++;
continue;
}
prev = *dst++ = ' ';
src++;
} else prev = *dst++ = *src++;
}
if (dst > buf && *(dst-1) == ' ') dst--;
*dst = '\0';
for (i = 0; missingFoundries[i] != NULL; i++) {
diff = strncmp(*fullnameReturn, missingFoundries[i],
missingFoundryLen[i]);
if (diff > 0) continue;
if (diff == 0 && strncmp(buf, missingFoundries[i],
missingFoundryLen[i] != 0)) {
while (dst >= buf) {
*(dst+missingFoundryLen[i]) = *dst;
dst--;
}
strncpy(buf, missingFoundries[i], missingFoundryLen[i]);
}
break;
}
if (strncmp(*fullnameReturn, "Helvetica Rounded ", 18) == 0) {
strcat(buf, " Rounded");
}
*familyReturn = Canonical(buf);
FAMILY_DONE:
src = *fullnameReturn;
dst = *familyReturn;
while (*dst == *src && *dst != '\0') {
src++;
dst++;
}
if (*src == ' ') src++;
if (*src != '\0') *faceReturn = Canonical(src);
else if (*weight != '\0') {
if (strcmp(weight, "All") == 0) *faceReturn = Canonical("Roman");
else {
if (islower(weight[0])) weight[0] = toupper(weight[0]);
*faceReturn = Canonical(weight);
}
} else *faceReturn = Canonical("Medium");
}
static String strip[] = {
"Adobe ", "Bauer ", "Berthold ", "ITC ", "Linotype ",
"New ", "Simoncini ", "Stempel ", NULL};
static int striplen[] = {6, 6, 9, 4, 9, 4, 10, 8, 0};
#define STEMPELINDEX 7
static Boolean CreateSortKey(String family, String key)
{
char newkey[256];
int len = strlen(family);
register int i, diff;
if (family[len-2] == 'P' && family[len-1] == 'i') {
key[0] = 'P';
key[1] = 'i';
key[2] = ' ';
strcpy(key+3, family);
key[len] = '\0';
return True;
}
for (i = 0; strip[i] != NULL; i++) {
diff = strncmp(family, strip[i], striplen[i]);
if (diff < 0) break;
if (diff == 0) {
if (i == STEMPELINDEX) {
if (strcmp(family, "Stempel Schneidler") == 0) break;
}
strcpy(key, family + striplen[i]);
key[len - striplen[i]] = ' ';
strcpy(key + len - striplen[i] + 1, strip[i]);
key[len] = '\0';
if (CreateSortKey(key, newkey)) strcpy(key, newkey);
return True;
}
}
strcpy(key, family);
return False;
}
#define SKIP_SPACE(buf) while (*buf == ' ' || *buf == '\t') buf++;
static int CountAxes(char *buf)
{
int count = 0;
while (*buf != '\0') {
SKIP_SPACE(buf)
if (*buf != '/') return 0;
buf++;
count++;
if (*buf == ' ' || *buf == '\t' || *buf == '\0') return 0;
while (*buf != ' ' && *buf != '\t' && *buf != '\0') buf++;
}
return count;
}
static Boolean ParseBlendPositions(
char *buf,
float *blendPos,
int *axes, int *designs)
{
int i, j = 0;
float f;
*designs = 0;
while (*buf != '\0') {
SKIP_SPACE(buf)
if (*buf++ != '[') return True;
SKIP_SPACE(buf)
for (i = 0; i < *axes; i++) {
if (!ScanFloat(buf, &f, &buf)) return True;
blendPos[j++] = f;
SKIP_SPACE(buf)
}
if (*buf++ != ']') return True;
(*designs)++;
}
return False;
}
static Boolean ParseBlendMap(
char *buf,
int *breakCount,
int *blendBreak,
float *blendBreakValue,
int *axes)
{
int i, j = 0;
int n;
float f;
for (i = 0; i < *axes; i++) {
breakCount[i] = 0;
SKIP_SPACE(buf)
if (*buf++ != '[') return True;
SKIP_SPACE(buf)
while (*buf == '[') {
buf++;
SKIP_SPACE(buf)
if (!ScanInt(buf, &n, &buf)) return True;
blendBreak[j] = n;
SKIP_SPACE(buf)
if (!ScanFloat(buf, &f, &buf)) return True;
blendBreakValue[j++] = f;
SKIP_SPACE(buf)
if (*buf++ != ']') return True;
SKIP_SPACE(buf)
breakCount[i]++;
if (breakCount[i] == 12 && *buf != ']') return True;
}
if (*buf++ != ']') return True;
}
SKIP_SPACE(buf)
if (*buf != '\0') return True;
return False;
}
static Boolean ParseAxisNames(
int axes,
char *buf,
char *names[])
{
int i = 0;
while (*buf != '\0') {
SKIP_SPACE(buf)
if (*buf == '/') buf++;
names[i] = buf;
while (*buf != ' ' && *buf != '\t' && *buf != '\0') buf++;
if (buf != names[i]) i++;
if (*buf != '\0') *buf++ = '\0';
if (i >= axes) return True;
}
return False;
}
#undef SKIP_SPACE
static void GetPSFontInfo(
FontSelectionBoxWidget fsb,
char *name,
int *axes,
int *designs,
char *axisNames,
float *blendPos,
int *breakCount,
int *blendBreak,
float *blendBreakValue)
{
int entries;
char **names, **data;
entries = ListPSResourceFiles(fsb->fsb.resource_path_override,
fsb->fsb.default_resource_path,
"FontAxes", name,
&names, &data);
if (entries < 1) {
*axes = 0;
return;
}
*axes = CountAxes(data[0]);
if (*axes == 0) return;
strcpy(axisNames, data[0]);
entries = ListPSResourceFiles(fsb->fsb.resource_path_override,
fsb->fsb.default_resource_path,
"FontBlendMap", name,
&names, &data);
if (entries < 1) {
*axes = 0;
return;
}
if (ParseBlendMap(data[0], breakCount,
blendBreak, blendBreakValue, axes)) {
*axes = 0;
return;
}
entries = ListPSResourceFiles(fsb->fsb.resource_path_override,
fsb->fsb.default_resource_path,
"FontBlendPositions", name,
&names, &data);
if (entries < 1) {
*axes = 0;
return;
}
if (ParseBlendPositions(data[0], blendPos, axes, designs)) {
*axes = 0;
return;
}
}
static void AddFontRecord(
FontSelectionBoxWidget fsb,
int serverNum,
String name, String family, String fullname, String weight,
Boolean resident)
{
FontFamilyRec *ff;
FontRec *f;
String familyReturn, fullnameReturn, faceReturn;
char axisNameBuf[256];
char *axisName[MAX_AXES];
int blendedFont, undefineIt, brokenFont;
int axes, designs, breakCount[MAX_AXES],
blendBreak[12 * MAX_AXES];
float blendBreakValue[12 * MAX_AXES], blendPos[MAX_AXES * MAX_BLENDS];
char key[256];
int i, j, k, n;
name = Canonical(name);
for (ff = fsb->fsb.known_families; ff != NULL; ff = ff->next) {
for (f = ff->fonts; f != NULL; f = f->next) {
if (f->font_name == name) {
if (!f->resident && resident) f->resident = True;
return;
}
}
}
if (resident) {
_DPSFGetFontInfo(fsb->fsb.context, serverNum, fsb->fsb.old_server,
family, fullname,
weight, &blendedFont, &undefineIt, &brokenFont);
if (brokenFont) return;
if (family[0] == '\0') {
if (fullname[0] == '\0') {
strcpy(family, name);
strcpy(fullname, name);
} else strcpy(family, fullname);
} else if (fullname[0] == '\0') strcpy(fullname, family);
MungeFontNames(name, family, fullname, weight,
&familyReturn, &fullnameReturn, &faceReturn);
if (blendedFont) {
_DPSFGetBlendedFontInfo(fsb->fsb.context, serverNum,
undefineIt, fsb->fsb.old_server,
&axes, &designs, axisNameBuf,
blendPos, breakCount, blendBreak,
blendBreakValue, &brokenFont);
if (brokenFont) axes = 0;
} else axes = 0;
} else {
familyReturn = Canonical(family);
fullnameReturn = XtNewString(fullname);
faceReturn = Canonical(weight);
GetPSFontInfo(fsb, name, &axes, &designs, axisNameBuf, blendPos,
breakCount, blendBreak, blendBreakValue);
}
for (ff = fsb->fsb.known_families; ff != NULL; ff = ff->next) {
if (ff->family_name == familyReturn) break;
}
if (ff == NULL) {
ff = (FontFamilyRec *) XtMalloc(sizeof(FontFamilyRec));
ff->next = fsb->fsb.known_families;
ff->family_name = familyReturn;
ff->fonts = NULL;
ff->font_count = 0;
ff->blend_count = 0;
if (fsb->fsb.typographic_sort) {
(void) CreateSortKey(familyReturn, key);
ff->sort_key = XtNewString(key);
} else ff->sort_key = ff->family_name;
fsb->fsb.known_families = ff;
fsb->fsb.family_count++;
}
f = (FontRec *) XtMalloc(sizeof(FontRec));
f->next = ff->fonts;
f->font_name = name;
f->full_name = fullnameReturn;
f->resident = resident;
f->temp_resident = False;
f->in_font_creator = False;
f->pending_delete_next = NULL;
f->face_name = faceReturn;
f->CS_face_name = CS(f->face_name, (Widget) fsb);
f->blend_count = 0;
if (axes != 0 && ParseAxisNames(axes, axisNameBuf, axisName)) {
BlendDataRec *b;
f->blend_data = b = XtNew(BlendDataRec);
b->num_axes = axes;
b->num_designs = designs;
k = 0;
for (i = 0; i < axes; i++) {
b->internal_points[i] = breakCount[i] - 2;
if (b->internal_points[i] <= 0) {
b->internal_break[i] = NULL;
b->internal_value[i] = NULL;
b->internal_points[i] = 0;
} else {
b->internal_break[i] = (int *)
XtMalloc(b->internal_points[i] * sizeof(int));
b->internal_value[i] = (float *)
XtMalloc(b->internal_points[i] * sizeof(float));
}
n = 0;
for (j = 0; j < breakCount[i]; j++) {
if (blendBreakValue[k] == 0.0) b->min[i] = blendBreak[k];
else if (blendBreakValue[k] == 1.0) b->max[i] = blendBreak[k];
else {
b->internal_break[i][n] = blendBreak[k];
b->internal_value[i][n++] = blendBreakValue[k];
}
k++;
}
b->name[i] = Canonical(axisName[i]);
}
b->design_positions =
(float *) XtMalloc(axes * designs * sizeof(float));
for (i = 0; i < axes * designs; i++) {
b->design_positions[i] = blendPos[i];
}
b->blends = NULL;
} else f->blend_data = NULL;
ff->fonts = f;
ff->font_count++;
}
static void SortFontNames(FontFamilyRec *ff)
{
FontRec *f, *highest, **prev, **highestPrev;
FontRec *newFontList = NULL;
while (ff->fonts != NULL) {
prev = highestPrev = &ff->fonts;
highest = ff->fonts;
for (f = ff->fonts->next; f != NULL; f = f->next) {
prev = &(*prev)->next;
if (strcmp(f->face_name, highest->face_name) > 0) {
highest = f;
highestPrev = prev;
}
}
*highestPrev = highest->next;
highest->next = newFontList;
newFontList = highest;
}
ff->fonts = newFontList;
}
static void SortFontFamilies(FontSelectionBoxWidget fsb)
{
FontFamilyRec *ff, *highest, **prev, **highestPrev;
FontFamilyRec *newFamilyList = NULL;
while (fsb->fsb.known_families != NULL) {
prev = highestPrev = &fsb->fsb.known_families;
highest = fsb->fsb.known_families;
for (ff = fsb->fsb.known_families->next; ff != NULL; ff = ff->next) {
prev = &(*prev)->next;
if (strcmp(ff->sort_key, highest->sort_key) > 0) {
highest = ff;
highestPrev = prev;
}
}
*highestPrev = highest->next;
highest->next = newFamilyList;
newFamilyList = highest;
SortFontNames(highest);
if (fsb->fsb.typographic_sort) XtFree(highest->sort_key);
highest->sort_key = NULL;
}
fsb->fsb.known_families = newFamilyList;
}
static void AddFamily(
FontSelectionBoxWidget fsb,
char *family, char *fonts, char *weight, char *fullname, char *name)
{
int j;
char *ch;
ch = fonts;
while (*ch != '\0') {
j = 0;
while (1) {
if (*ch == '\\' && (*(ch+1) == '\\' || *(ch+1) == ',')) {
ch++;
weight[j++] = *ch++;
} else if (*ch == '\0' || *ch == ',') {
weight[j] = '\0';
break;
} else weight[j++] = *ch++;
}
if (*ch == ',') {
j = 0;
ch++;
while (1) {
if (*ch == '\\' && (*(ch+1) == '\\' || *(ch+1) == ',')) {
ch++;
name[j++] = *ch++;
} else if (*ch == '\0' || *ch == ',') {
name[j] = '\0';
break;
} else name[j++] = *ch++;
}
strcpy(fullname, family);
strcat(fullname, " ");
strcat(fullname, weight);
AddFontRecord(fsb, 0, name, family, fullname, weight, False);
if (*ch == ',') ch++;
}
}
}
static void GetFontNames(FontSelectionBoxWidget fsb)
{
int i;
char name[256], family[256], fullname[256], weight[256];
char *buffer, *ch, *start;
int fontCount, totalLength;
char **loadableFamilies = NULL, **loadableFamilyFonts = NULL;
fsb->fsb.family_count = 0;
fontCount = ListPSResourceFiles(fsb->fsb.resource_path_override,
fsb->fsb.default_resource_path,
PSResFontFamily, NULL,
&loadableFamilies, &loadableFamilyFonts);
for (i = 0; i < fontCount; i++) {
AddFamily(fsb, loadableFamilies[i], loadableFamilyFonts[i],
weight, fullname, name);
}
XtFree((XtPointer) loadableFamilies);
XtFree((XtPointer) loadableFamilyFonts);
FreePSResourceStorage(False);
if (fsb->fsb.get_server_fonts) {
_DPSFEnumFonts(fsb->fsb.context, &fontCount, &totalLength);
buffer = XtMalloc(totalLength);
_DPSFGetAllFontNames(fsb->fsb.context, fontCount, totalLength, buffer);
ch = start = buffer;
for (i = 0; i < fontCount; i++) {
while (*ch != ' ') ch++;
*ch = '\0';
AddFontRecord(fsb, i, start, family, fullname, weight, True);
start = ch+1;
}
XtFree(buffer);
}
_DPSFFreeFontInfo(fsb->fsb.context);
SortFontFamilies(fsb);
ReadBlends(fsb);
}
static void SensitizeReset(FontSelectionBoxWidget fsb)
{
XtSetSensitive(fsb->fsb.reset_button_child, True);
}
static void DesensitizeReset(FontSelectionBoxWidget fsb)
{
XtSetSensitive(fsb->fsb.reset_button_child, False);
}
static void ManageFamilyMultiple(FontSelectionBoxWidget fsb)
{
XtManageChild(fsb->fsb.family_multiple_label_child);
XtVaSetValues(XtParent(fsb->fsb.family_scrolled_list_child),
XmNtopWidget, fsb->fsb.family_multiple_label_child, NULL);
}
static void ManageFaceMultiple(FontSelectionBoxWidget fsb)
{
XtManageChild(fsb->fsb.face_multiple_label_child);
XtVaSetValues(XtParent(fsb->fsb.face_scrolled_list_child),
XmNtopWidget, fsb->fsb.face_multiple_label_child, NULL);
}
static void ManageMultipleMaster(FontSelectionBoxWidget fsb)
{
XtManageChild(fsb->fsb.multiple_master_button_child);
XtVaSetValues(XtParent(fsb->fsb.face_scrolled_list_child),
XmNbottomWidget, fsb->fsb.multiple_master_button_child,
NULL);
}
static void ManageSizeMultiple(FontSelectionBoxWidget fsb)
{
XtManageChild(fsb->fsb.size_multiple_label_child);
}
static void UnmanageFamilyMultiple(FontSelectionBoxWidget fsb)
{
XtVaSetValues(XtParent(fsb->fsb.family_scrolled_list_child),
XmNtopWidget, fsb->fsb.family_label_child, NULL);
XtUnmanageChild(fsb->fsb.family_multiple_label_child);
}
static void UnmanageFaceMultiple(FontSelectionBoxWidget fsb)
{
XtVaSetValues(XtParent(fsb->fsb.face_scrolled_list_child),
XmNtopWidget, fsb->fsb.face_label_child, NULL);
XtUnmanageChild(fsb->fsb.face_multiple_label_child);
}
static void UnmanageMultipleMaster(FontSelectionBoxWidget fsb)
{
XtUnmanageChild(fsb->fsb.multiple_master_button_child);
XtVaSetValues(XtParent(fsb->fsb.face_scrolled_list_child),
XmNbottomWidget, fsb->fsb.size_text_field_child, NULL);
}
static void UnmanageSizeMultiple(FontSelectionBoxWidget fsb)
{
XtUnmanageChild(fsb->fsb.size_multiple_label_child);
}
static Boolean DownloadFont(
FontSelectionBoxWidget fsb,
String name,
DPSContext ctxt,
Boolean make_shared)
{
int count;
char **names, **files;
FILE *f;
#define BUFLEN 256
char buf[BUFLEN];
static char eobuf[] = "\n$Adobe$DPS$Lib$Dict /downloadSuccess true put\n\
stop\n\
Magic end of data line )))))))))) 99#2 2#99 <xyz> // 7gsad,32h4ghNmndFgj2\n";
int currentShared, ok;
count = ListPSResourceFiles(fsb->fsb.resource_path_override,
fsb->fsb.default_resource_path,
PSResFontOutline, name,
&names, &files);
if (count == 0) return False;
f = fopen(files[0], "r");
if (f == NULL) return False;
if (fsb->fsb.old_server) {
DPSPrintf(ctxt, "\ncurrentshared %s setshared\n",
(make_shared ? "true" : "false"));
while (fgets(buf, BUFLEN, f) != NULL) {
DPSWritePostScript(ctxt, buf, strlen(buf));
}
DPSWritePostScript(ctxt, "\nsetshared\n", 11);
ok = True;
} else {
_DPSFPrepareToDownload(ctxt, make_shared, ¤tShared);
DPSWriteData(ctxt, "\nexec\n", 6);
while (fgets(buf, BUFLEN, f) != NULL) {
DPSWriteData(ctxt, buf, strlen(buf));
}
DPSWriteData(ctxt, eobuf, strlen(eobuf));
_DPSFFinishDownload(ctxt, currentShared, &ok);
}
fclose (f);
free(names);
free(files);
return ok;
#undef BUFLEN
}
static void UndefSomeUnusedFonts(
FontSelectionBoxWidget fsb,
Boolean all)
{
FontRec *f, *nextf, **start;
int i;
if (!all
&& (Cardinal)fsb->fsb.pending_delete_count < fsb->fsb.max_pending_deletes) {
return;
}
if (all) start = &fsb->fsb.pending_delete_font;
else {
f = fsb->fsb.pending_delete_font;
for (i = 1; f != NULL && (Cardinal)i < fsb->fsb.max_pending_deletes; i++) {
f = f->pending_delete_next;
}
if (f == NULL) return;
start = &f->pending_delete_next;
}
for (f = *start; f != NULL; f = nextf) {
nextf = f->pending_delete_next;
if (f == fsb->fsb.currently_previewed) {
start = &f->pending_delete_next;
continue;
}
*start = nextf;
if (!f->resident && !f->in_font_creator) {
_DPSFUndefineFont(fsb->fsb.context, f->font_name,
fsb->fsb.old_server);
}
f->temp_resident = False;
fsb->fsb.pending_delete_count--;
f->pending_delete_next = NULL;
}
}
static void UndefUnusedFonts(Widget w)
{
FontSelectionBoxWidget fsb = (FontSelectionBoxWidget) w;
UndefSomeUnusedFonts(fsb, True);
}
Boolean _FSBDownloadFontIfNecessary(
FontRec *f,
FontSelectionBoxWidget fsb)
{
Boolean shared;
if (!f->resident && !f->temp_resident) {
shared = fsb->fsb.make_fonts_shared && !fsb->fsb.undef_unused_fonts;
if (!fsb->fsb.get_server_fonts) {
int resident;
_DPSFIsFontResident(fsb->fsb.context, f->font_name, &resident);
if (resident) {
f->resident = True;
return True;
}
}
if (!DownloadFont(fsb, f->font_name, fsb->fsb.context, shared)) {
_FSBFlushFont(fsb, f);
return False;
}
if (shared) f->resident = True;
else f->temp_resident = True;
if (f->pending_delete_next == NULL && fsb->fsb.undef_unused_fonts) {
f->pending_delete_next = fsb->fsb.pending_delete_font;
fsb->fsb.pending_delete_font = f;
fsb->fsb.pending_delete_count++;
UndefSomeUnusedFonts(fsb, False);
}
}
return True;
}
static void DoPreview(
FontSelectionBoxWidget fsb,
Boolean override)
{
int i, n;
int *selectList, selectCount;
float size;
FontFamilyRec *ff = fsb->fsb.known_families;
FontRec *f;
BlendRec *b;
char *chSize, *fontName;
Dimension height;
Cardinal depth;
int bogusFont;
if (!XtIsRealized(fsb)) return;
XtVaGetValues(fsb->fsb.preview_child, XmNheight, &height,
XmNdepth, &depth, NULL);
if (fsb->fsb.gstate == 0) {
XDPSSetContextParameters(fsb->fsb.context, XtScreen(fsb), depth,
XtWindow(fsb->fsb.preview_child), height,
(XDPSStandardColormap *) NULL,
(XDPSStandardColormap *) NULL,
XDPSContextScreenDepth | XDPSContextDrawable |
XDPSContextRGBMap | XDPSContextGrayMap);
XDPSCaptureContextGState(fsb->fsb.context, &fsb->fsb.gstate);
} else XDPSSetContextGState(fsb->fsb.context, fsb->fsb.gstate);
_DPSFClearWindow(fsb->fsb.context);
if (override) {
if (fsb->fsb.current_family_multiple ||
fsb->fsb.current_face_multiple ||
fsb->fsb.current_size_multiple) return;
f = fsb->fsb.currently_previewed;
size = fsb->fsb.currently_previewed_size;
b = fsb->fsb.currently_previewed_blend;
}
if (!override || f == NULL || size == 0.0) {
if (!XmListGetSelectedPos(fsb->fsb.family_scrolled_list_child,
&selectList, &selectCount)) return;
if (selectCount == 0 ||
*selectList < 1 || *selectList > fsb->fsb.family_count) return;
for (i = 1; i < *selectList; i++) ff = ff->next;
XtFree((XtPointer) selectList);
if (!XmListGetSelectedPos(fsb->fsb.face_scrolled_list_child,
&selectList, &selectCount)) return;
if (selectCount == 0 ||
*selectList < 1 ||
*selectList > ff->font_count + ff->blend_count) return;
f = ff->fonts;
n = 0;
while (1) {
n += f->blend_count + 1;
if (n >= *selectList) {
n -= f->blend_count;
if (n == *selectList) b = NULL;
else for (b = f->blend_data->blends;
n < *selectList - 1; b = b->next) n++;
break;
}
f = f->next;
}
XtFree((XtPointer) selectList);
XtVaGetValues(fsb->fsb.size_text_field_child,
XmNvalue, &chSize, NULL);
if (chSize == NULL || *chSize == '\0') return;
size = atof(chSize);
}
if (size <= 0.0) return;
fsb->fsb.currently_previewed = f;
fsb->fsb.currently_previewed_blend = b;
fsb->fsb.currently_previewed_size = size;
if (!_FSBDownloadFontIfNecessary(f, fsb)) return;
if (b == NULL) fontName = f->font_name;
else fontName = b->font_name;
if (fsb->fsb.preview_string == NULL) {
_DPSFPreviewString(fsb->fsb.context, fontName, size,
f->full_name, height, &bogusFont);
} else _DPSFPreviewString(fsb->fsb.context, fontName, size,
fsb->fsb.preview_string, height, &bogusFont);
if (bogusFont) {
_FSBBogusFont(fsb, f);
}
}
static void DoValueChangedCallback(FontSelectionBoxWidget fsb)
{
String afm = NULL;
FSBValidateCallbackRec cb;
if (fsb->fsb.get_afm) {
if (fsb->fsb.currently_selected_face == NULL) afm = NULL;
else afm = FindAFM((Widget) fsb,
fsb->fsb.currently_selected_face->font_name);
}
(void) Verify(fsb, &cb, afm, False);
cb.reason = FSBValueChanged;
XtCallCallbackList((Widget) fsb, fsb->fsb.value_changed_callback, &cb);
}
static void ValueChanged(FontSelectionBoxWidget fsb)
{
if (fsb->fsb.auto_preview) DoPreview(fsb, False);
DoValueChangedCallback(fsb);
}
static void PreviewText(
Widget widget,
XtPointer clientData, XtPointer callData)
{
FontSelectionBoxWidget fsb = (FontSelectionBoxWidget) clientData;
XmAnyCallbackStruct *cb = (XmAnyCallbackStruct *) callData;
if (!fsb->fsb.preview_fixed) {
XSetWindowAttributes att;
att.bit_gravity = ForgetGravity;
XChangeWindowAttributes(XtDisplay(fsb),
XtWindow(fsb->fsb.preview_child),
CWBitGravity, &att);
fsb->fsb.preview_fixed = True;
}
if (cb != NULL && cb->event->type == Expose &&
cb->event->xexpose.count != 0) return;
DoPreview(fsb, True);
}
static void PreviewCallback(
Widget widget,
XtPointer clientData, XtPointer callData)
{
FontSelectionBoxWidget fsb = (FontSelectionBoxWidget) clientData;
DoPreview(fsb, False);
}
static void DismissSamplerCallback(
Widget widget,
XtPointer clientData, XtPointer callData)
{
FontSelectionBoxWidget fsb = (FontSelectionBoxWidget) clientData;
fsb->fsb.show_sampler = False;
}
static void ShowSampler(FontSelectionBoxWidget fsb)
{
int i;
Arg args[2];
Widget s;
if (fsb->fsb.sampler == NULL) {
FSBCreateSamplerCallbackRec cs;
cs.sampler_shell = NULL;
XtCallCallbackList((Widget) fsb, fsb->fsb.create_sampler_callback,
(XtPointer) &cs);
if (cs.sampler_shell == NULL || cs.sampler == NULL) {
fsb->fsb.sampler =
XtCreatePopupShell("samplerShell",
transientShellWidgetClass,
(Widget) fsb, (ArgList) NULL, 0);
i = 0;
XtSetArg(args[i], XtNfontSelectionBox, fsb); i++;
s = XtCreateManagedWidget("sampler", fontSamplerWidgetClass,
fsb->fsb.sampler, args, i);
XtAddCallback(s, XtNdismissCallback,
DismissSamplerCallback, (XtPointer) fsb);
} else {
fsb->fsb.sampler = cs.sampler_shell;
XtAddCallback(cs.sampler, XtNdismissCallback,
DismissSamplerCallback, (XtPointer) fsb);
}
}
XtPopup(fsb->fsb.sampler, XtGrabNone);
XRaiseWindow(XtDisplay(fsb->fsb.sampler), XtWindow(fsb->fsb.sampler));
fsb->fsb.show_sampler = True;
}
static void ShowCreator(FontSelectionBoxWidget fsb)
{
int i;
Arg args[2];
FSBCreateCreatorCallbackRec cc;
if (fsb->fsb.creator == NULL) {
cc.creator_shell = NULL;
XtCallCallbackList((Widget) fsb, fsb->fsb.create_creator_callback,
(XtPointer) &cc);
if (cc.creator_shell == NULL || cc.creator == NULL) {
cc.creator_shell =
XtCreatePopupShell("creatorShell",
transientShellWidgetClass,
(Widget) fsb, (ArgList) NULL, 0);
i = 0;
XtSetArg(args[i], XtNfontSelectionBox, fsb); i++;
cc.creator =
XtCreateManagedWidget("creator", fontCreatorWidgetClass,
cc.creator_shell, args, i);
}
fsb->fsb.creator_shell = cc.creator_shell;
fsb->fsb.creator = cc.creator;
}
XtPopup(fsb->fsb.creator_shell, XtGrabNone);
XRaiseWindow(XtDisplay(fsb->fsb.creator_shell),
XtWindow(fsb->fsb.creator_shell));
_FSBSetCreatorFamily(fsb->fsb.creator, fsb->fsb.currently_selected_family);
}
static void ShowCreatorCallback(
Widget widget,
XtPointer clientData, XtPointer callData)
{
FontSelectionBoxWidget fsb = (FontSelectionBoxWidget) clientData;
ShowCreator(fsb);
}
static void ShowSamplerCallback(
Widget widget,
XtPointer clientData, XtPointer callData)
{
FontSelectionBoxWidget fsb = (FontSelectionBoxWidget) clientData;
ShowSampler(fsb);
}
static void PreviewDoubleClick(
Widget widget,
XtPointer clientData, XtPointer callData)
{
FontSelectionBoxWidget fsb = (FontSelectionBoxWidget) clientData;
DoPreview(fsb, False);
}
static void ResizePreview(
Widget widget,
XtPointer clientData, XtPointer callData)
{
Dimension height;
Cardinal depth;
FontSelectionBoxWidget fsb = (FontSelectionBoxWidget) clientData;
if (!XtIsRealized(widget) || fsb->fsb.gstate == 0) return;
XtVaGetValues(widget, XmNheight, &height, XmNdepth, &depth, NULL);
XDPSSetContextGState(fsb->fsb.context, fsb->fsb.gstate);
XDPSSetContextParameters(fsb->fsb.context, XtScreen(widget), depth,
XtWindow(widget), height,
(XDPSStandardColormap *) NULL,
(XDPSStandardColormap *) NULL,
XDPSContextScreenDepth | XDPSContextDrawable);
_DPSFReclip(fsb->fsb.context);
XDPSUpdateContextGState(fsb->fsb.context, fsb->fsb.gstate);
}
static String FindAFMRecursive(
Widget w,
String name,
Boolean recur)
{
FontSelectionBoxWidget fsb = (FontSelectionBoxWidget) w;
int count;
char **names, **files;
String ret, ch;
if (name == NULL) return NULL;
count = ListPSResourceFiles(fsb->fsb.resource_path_override,
fsb->fsb.default_resource_path,
PSResFontAFM,
name,
&names, &files);
if (count == 0 && recur) {
for (ch = name; *ch != '_' && *ch != '\0'; ch++) {}
if (*ch == '\0') return NULL;
*ch = '\0';
ret = FindAFMRecursive(w, name, False);
*ch = '_';
return ret;
}
if (count == 0) return NULL;
ret = files[0];
free(names);
free(files);
return ret;
}
static String FindAFM(Widget w, String name)
{
return FindAFMRecursive(w, name, True);
}
static String FindFontFileRecursive(
Widget w,
String name,
Boolean recur)
{
FontSelectionBoxWidget fsb = (FontSelectionBoxWidget) w;
int count;
char **names, **files;
String ret, ch;
if (name == NULL) return NULL;
count = ListPSResourceFiles(fsb->fsb.resource_path_override,
fsb->fsb.default_resource_path,
PSResFontOutline,
name,
&names, &files);
if (count == 0 && recur) {
for (ch = name; *ch != '_' && *ch != '\0'; ch++) {}
if (*ch == '\0') return NULL;
*ch = '\0';
ret = FindFontFileRecursive(w, name, False);
*ch = '_';
return ret;
}
if (count == 0) return NULL;
ret = files[0];
free(names);
free(files);
return ret;
}
static String FindFontFile(Widget w, String name)
{
return FindFontFileRecursive(w, name, True);
}
static Boolean Verify(
FontSelectionBoxWidget fsb,
FSBValidateCallbackRec *cb,
String afm,
Boolean doIt)
{
char *chSize;
int i;
if (fsb->fsb.current_family_multiple) {
cb->family = NULL;
cb->family_selection = FSBMultiple;
} else if (fsb->fsb.currently_selected_family == NULL) {
cb->family = NULL;
cb->family_selection = FSBNone;
} else {
cb->family = fsb->fsb.currently_selected_family->family_name;
cb->family_selection = FSBOne;
}
if (fsb->fsb.current_face_multiple) {
cb->face = NULL;
cb->face_selection = FSBMultiple;
} else if (fsb->fsb.currently_selected_face == NULL) {
cb->face = NULL;
cb->face_selection = FSBNone;
} else {
cb->face = fsb->fsb.currently_selected_face->face_name;
cb->face_selection = FSBOne;
}
if (cb->family_selection == FSBMultiple ||
cb->face_selection == FSBMultiple) {
cb->name = NULL;
cb->name_selection = FSBMultiple;
} else if (fsb->fsb.currently_selected_face == NULL) {
cb->name = NULL;
cb->name_selection = FSBNone;
} else {
if (fsb->fsb.currently_selected_blend != NULL) {
cb->name = fsb->fsb.currently_selected_blend->font_name;
} else cb->name = fsb->fsb.currently_selected_face->font_name;
cb->name_selection = FSBOne;
}
if (fsb->fsb.current_size_multiple) {
cb->size = 0.0;
cb->size_selection = FSBMultiple;
} else {
XtVaGetValues(fsb->fsb.size_text_field_child, XmNvalue, &chSize, NULL);
if (chSize == NULL || *chSize == '\0') {
cb->size = 0.0;
cb->size_selection = FSBNone;
} else {
cb->size = atof(chSize);
cb->size_selection = FSBOne;
}
}
cb->afm_filename = afm;
cb->afm_present = (afm != NULL);
cb->doit = True;
if (fsb->fsb.currently_selected_blend == NULL) {
cb->blend = cb->base_name = NULL;
for (i = 0; i < MAX_AXES; i++) cb->axis_percent[i] = 0.0;
} else {
cb->blend = fsb->fsb.currently_selected_blend->blend_name;
cb->base_name = fsb->fsb.currently_selected_face->font_name;
for (i = 0; i < MAX_AXES; i++) {
cb->axis_percent[i] = fsb->fsb.currently_selected_blend->data[i];
}
}
if (doIt) XtCallCallbackList((Widget) fsb, fsb->fsb.validate_callback, cb);
return cb->doit;
}
static Boolean VerifyAndCallback(
FontSelectionBoxWidget fsb,
FSBCallbackReason reason,
XtCallbackList callback)
{
String afm = NULL;
FSBValidateCallbackRec cb;
FontRec *fsave, *face;
if (fsb->fsb.get_afm) {
if (fsb->fsb.currently_selected_face == NULL) afm = NULL;
else afm = FindAFM((Widget) fsb,
fsb->fsb.currently_selected_face->font_name);
}
DoPreview(fsb, False);
cb.reason = reason;
if (!Verify(fsb, &cb, afm, True)) return False;
fsb->fsb.font_family_multiple = fsb->fsb.current_family_multiple;
if (!fsb->fsb.font_family_multiple &&
fsb->fsb.currently_selected_family != NULL) {
fsb->fsb.font_family =
fsb->fsb.currently_selected_family->family_name;
} else fsb->fsb.font_family = NULL;
fsb->fsb.font_face_multiple = fsb->fsb.current_face_multiple;
if (!fsb->fsb.font_face_multiple &&
fsb->fsb.currently_selected_face != NULL) {
fsb->fsb.font_face = fsb->fsb.currently_selected_face->face_name;
} else fsb->fsb.font_face = NULL;
fsb->fsb.font_name_multiple =
fsb->fsb.font_family_multiple || fsb->fsb.font_face_multiple;
if (!fsb->fsb.font_name_multiple &&
fsb->fsb.currently_selected_face != NULL) {
fsb->fsb.font_name = fsb->fsb.currently_selected_face->font_name;
} else fsb->fsb.font_name = NULL;
fsb->fsb.font_size_multiple = fsb->fsb.current_size_multiple;
if (!fsb->fsb.font_size_multiple) {
fsb->fsb.font_size = cb.size;
}
if (fsb->fsb.currently_selected_blend != NULL) {
fsb->fsb.font_blend = fsb->fsb.currently_selected_blend->blend_name;
} else fsb->fsb.font_blend = NULL;
if (fsb->fsb.undef_unused_fonts) {
fsave = fsb->fsb.currently_previewed;
if (fsb->fsb.make_fonts_shared) {
fsb->fsb.currently_previewed = NULL;
}
UndefUnusedFonts((Widget)fsb);
fsb->fsb.currently_previewed = fsave;
face = fsb->fsb.currently_selected_face;
if (face != NULL && !face->resident) {
face->resident = True;
if (fsb->fsb.make_fonts_shared) {
(void) DownloadFont(fsb, face->font_name,
fsb->fsb.context, True);
DPSWaitContext(fsb->fsb.context);
}
}
}
XtCallCallbackList((Widget) fsb, callback, &cb);
return True;
}
static void OKCallback(
Widget widget,
XtPointer clientData, XtPointer callData)
{
FontSelectionBoxWidget fsb = (FontSelectionBoxWidget) clientData;
if (!VerifyAndCallback(fsb, FSBOK, fsb->fsb.ok_callback)) return;
if (XtIsShell(XtParent(fsb))) XtPopdown(XtParent(fsb));
WriteBlends(fsb);
DesensitizeReset(fsb);
if (fsb->fsb.show_sampler) XtPopdown(fsb->fsb.sampler);
}
static void ApplyCallback(
Widget widget,
XtPointer clientData, XtPointer callData)
{
FontSelectionBoxWidget fsb = (FontSelectionBoxWidget) clientData;
(void) VerifyAndCallback(fsb, FSBApply, fsb->fsb.apply_callback);
WriteBlends(fsb);
DesensitizeReset(fsb);
}
static void ResetFSB(
FontSelectionBoxWidget fsb,
FSBCallbackReason reason)
{
FSBCallbackRec cb;
int i;
fsb->fsb.currently_previewed = NULL;
fsb->fsb.currently_previewed_size = fsb->fsb.currently_selected_size = 0.0;
SetUpCurrentSelections(fsb);
if (fsb->fsb.undef_unused_fonts) UndefUnusedFonts((Widget)fsb);
cb.reason = reason;
if (fsb->fsb.font_family_multiple) {
cb.family = NULL;
cb.family_selection = FSBMultiple;
} else if (fsb->fsb.font_family == NULL) {
cb.family = NULL;
cb.family_selection = FSBNone;
} else {
cb.family = fsb->fsb.font_family;
cb.family_selection = FSBOne;
}
if (fsb->fsb.font_face_multiple) {
cb.face = NULL;
cb.face_selection = FSBMultiple;
} else if (fsb->fsb.font_face == NULL) {
cb.face = NULL;
cb.face_selection = FSBNone;
} else {
cb.face = fsb->fsb.font_face;
cb.face_selection = FSBOne;
}
if (cb.family_selection == FSBMultiple ||
cb.face_selection == FSBMultiple) {
cb.name = NULL;
cb.name_selection = FSBMultiple;
} else if (fsb->fsb.font_face == NULL) {
cb.name = NULL;
cb.name_selection = FSBNone;
} else {
cb.name = fsb->fsb.font_name;
cb.name_selection = FSBOne;
}
if (fsb->fsb.font_size_multiple) {
cb.size = 0.0;
cb.size_selection = FSBMultiple;
} else {
cb.size = fsb->fsb.font_size;
cb.size_selection = FSBOne;
}
cb.afm_filename = NULL;
cb.afm_present = False;
cb.blend = fsb->fsb.font_blend;
if (cb.blend == NULL || fsb->fsb.currently_selected_blend == NULL) {
cb.base_name = NULL;
for (i = 0; i < MAX_AXES; i++) cb.axis_percent[i] = 0;
} else {
cb.base_name = fsb->fsb.currently_selected_face->font_name;
for (i = 0; i < MAX_AXES; i++) {
cb.axis_percent[i] = fsb->fsb.currently_selected_blend->data[i];
}
}
if (reason == FSBReset) {
XtCallCallbackList((Widget) fsb, fsb->fsb.reset_callback, &cb);
} else XtCallCallbackList((Widget) fsb, fsb->fsb.cancel_callback, &cb);
}
static void ResetCallback(
Widget widget,
XtPointer clientData, XtPointer callData)
{
FontSelectionBoxWidget fsb = (FontSelectionBoxWidget) clientData;
ResetFSB(fsb, FSBReset);
DesensitizeReset(fsb);
}
static void CancelCallback(
Widget widget,
XtPointer clientData, XtPointer callData)
{
FontSelectionBoxWidget fsb = (FontSelectionBoxWidget) clientData;
ResetFSB(fsb, FSBCancel);
if (XtIsShell(XtParent(fsb))) XtPopdown(XtParent(fsb));
DesensitizeReset(fsb);
if (fsb->fsb.show_sampler) XtPopdown(fsb->fsb.sampler);
}
static Boolean changingSize = False;
static void SizeSelect(
Widget widget,
XtPointer clientData, XtPointer callData)
{
String value;
Widget option;
FontSelectionBoxWidget fsb = (FontSelectionBoxWidget) clientData;
char *ch;
XtVaGetValues(widget, XmNvalue, &value, NULL);
if (value == NULL) option = fsb->fsb.other_size;
else {
if (value[0] != '\0' && fsb->fsb.current_size_multiple) {
fsb->fsb.current_size_multiple = False;
UnmanageSizeMultiple(fsb);
}
for (ch = value; *ch != '\0'; ch++) if (*ch == '.') *ch = '-';
option = XtNameToWidget(fsb->fsb.size_menu, value);
if (option == NULL) option = fsb->fsb.other_size;
}
XtVaSetValues(fsb->fsb.size_option_menu_child,
XmNmenuHistory, option, NULL);
if (value != NULL && value[0] != '\0') {
fsb->fsb.currently_selected_size = atof(value);
} else fsb->fsb.currently_selected_size = 0.0;
if (!changingSize) SensitizeReset(fsb);
fsb->fsb.current_size_multiple = False;
}
static void TextVerify(
Widget widget,
XtPointer clientData, XtPointer callData)
{
int i;
XmTextVerifyPtr v = (XmTextVerifyPtr) callData;
char ch, *cp;
int decimalPoints = 0;
FontSelectionBoxWidget fsb = (FontSelectionBoxWidget) clientData;
if (changingSize) return;
if (v->text->length == 0) return;
if (v->text->length == 1) {
ch = v->text->ptr[0];
if (ch == 'p' || ch == 'P') {
XtCallCallbacks(fsb->fsb.preview_button_child,
XmNactivateCallback, NULL);
v->doit = False;
return;
}
}
for (i = 0; i < v->text->length; i++) {
ch = v->text->ptr[i];
if (ch == '.') decimalPoints++;
else if (!isdigit(ch)) {
v->doit = False;
return;
}
}
if (decimalPoints > 1) {
v->doit = False;
return;
}
XtVaGetValues(widget, XmNvalue, &cp, NULL);
for (; *cp != '\0'; cp++) {
if (*cp == '.') decimalPoints++;
}
if (decimalPoints > 1) v->doit = False;
}
static void SetSize(
Widget widget,
XtPointer clientData, XtPointer callData)
{
char buf[20];
char *ch;
FontSelectionBoxWidget fsb = (FontSelectionBoxWidget) clientData;
if (fsb->fsb.current_size_multiple) {
fsb->fsb.current_size_multiple = False;
UnmanageSizeMultiple(fsb);
}
strcpy(buf, XtName(widget));
for (ch = buf; *ch != '\0'; ch++) if (*ch == '-') *ch++ = '.';
changingSize = True;
XtVaSetValues(fsb->fsb.size_text_field_child, XmNvalue, buf, NULL);
changingSize = False;
SensitizeReset(fsb);
ValueChanged(fsb);
}
static void ListSelectPos(
Widget w,
int pos,
Boolean notify)
{
int topPos, items, visible;
XmListSelectPos(w, pos, notify);
XtVaGetValues(w, XmNtopItemPosition, &topPos,
XmNvisibleItemCount, &visible, XmNitemCount, &items, NULL);
if (pos >= topPos && pos < topPos + visible) return;
topPos = pos - (visible-1)/2;
if (topPos + visible > items) topPos = items - visible + 1;
if (topPos < 1) topPos = 1;
XtVaSetValues(w, XmNtopItemPosition, topPos, NULL);
}
static String GetRootDirName(String buf)
{
#ifndef X_NOT_POSIX
uid_t uid;
#else
int uid;
extern int getuid();
#ifndef SYSV386
extern struct passwd *getpwuid(), *getpwnam();
#endif
#endif
struct passwd *pw;
static char *ptr = NULL;
if (ptr == NULL) {
if (!(ptr = getenv("HOME"))) {
if ((ptr = getenv("USER")) != NULL) pw = getpwnam(ptr);
else {
uid = getuid();
pw = getpwuid(uid);
}
if (pw) ptr = pw->pw_dir;
else {
ptr = NULL;
*buf = '\0';
}
}
}
if (ptr)
(void) strcpy(buf, ptr);
buf += strlen(buf);
*buf = '/';
buf++;
*buf = '\0';
return buf;
}
static void WriteBlendLine(
FILE *f,
String family, String face, String blend, String name,
int axes,
float *p)
{
register char *ch;
int i;
ch = family;
while (*ch != '\0') {
if (*ch == ',' || *ch == '\\') (void) putc('\\', f);
(void) putc(*ch++, f);
}
putc(',', f);
ch = face;
while (*ch != '\0') {
if (*ch == ',' || *ch == '\\') (void) putc('\\', f);
(void) putc(*ch++, f);
}
putc(',', f);
ch = blend;
while (*ch != '\0') {
if (*ch == ',' || *ch == '\\') (void) putc('\\', f);
(void) putc(*ch++, f);
}
(void) putc(',', f);
ch = name;
while (*ch != '\0') {
if (*ch == ',' || *ch == '\\') (void) putc('\\', f);
(void) putc(*ch++, f);
}
for (i = 0; i < axes; i++) fprintf(f, ",%f", p[i]);
(void) putc('\n', f);
}
static void WriteBlends(FontSelectionBoxWidget fsb)
{
FontFamilyRec *ff;
FontRec *f;
BlendRec *b;
String blendEnv;
char homeDir[PATH_BUF_SIZE];
FILE *blendFile = NULL;
char fileName[PATH_BUF_SIZE];
if (!fsb->fsb.blends_changed) return;
blendEnv = getenv("DPSFONTRC");
if (blendEnv != NULL) blendFile = fopen(blendEnv, "w");
if (blendFile == NULL) {
(void) GetRootDirName(homeDir);
sprintf(fileName, "%s/.dpsfontrc", homeDir);
blendFile = fopen(fileName, "w");
if (blendFile == NULL) return;
}
for (ff = fsb->fsb.known_families; ff != NULL; ff = ff->next) {
for (f = ff->fonts; f != NULL; f = f->next) {
if (f->blend_data != NULL) {
for (b = f->blend_data->blends; b != NULL; b = b->next) {
WriteBlendLine(blendFile, ff->family_name, f->face_name,
b->blend_name, b->font_name,
f->blend_data->num_axes, b->data);
}
}
}
}
fclose(blendFile);
fsb->fsb.blends_changed = False;
}
static Boolean ParseBlendLine(
String buf, String family, String face, String blend, String name,
float *p)
{
char *src, *dst;
int i;
float f;
src = buf;
dst = family;
while (*src != ',' && *src != '\0') {
if (*src == '\\') src++;
if (*src == '\0') return False;
*dst++ = *src++;
}
if (*src == '\0') return False;
*dst = '\0';
src++;
dst = face;
while (*src != ',' && *src != '\0') {
if (*src == '\\') src++;
if (*src == '\0') return False;
*dst++ = *src++;
}
if (*src == '\0') return False;
*dst = '\0';
src++;
dst = blend;
while (*src != ',' && *src != '\0') {
if (*src == '\\') src++;
if (*src == '\0') return False;
*dst++ = *src++;
}
if (*src == '\0') return False;
*dst = '\0';
src++;
dst = name;
while (*src != ',' && *src != '\0') {
if (*src == '\\') src++;
if (*src == '\0') return False;
*dst++ = *src++;
}
if (*src == '\0') return False;
*dst = '\0';
for (i = 0; i < MAX_AXES; i++) {
src++;
if (!ScanFloat(src, &f, &src)) {
for (; i < MAX_AXES; i++) p[i] = 0;
return True;;
}
else p[i] = f;
}
return True;
}
static void ReadBlends(FontSelectionBoxWidget fsb)
{
String blendEnv;
char homeDir[PATH_BUF_SIZE];
FILE *blendFile = NULL;
char fileName[PATH_BUF_SIZE];
#define BUF 256
char buf[BUF+1], family[BUF+1], face[BUF+1], blend[BUF+1], name[BUF+1];
char *cfamily, *cface;
float p[MAX_AXES];
FontRec *f;
FontFamilyRec *ff = 0;
BlendRec *b, *newb, **lastb;
char *spaceBlend;
char *lastFamily = NULL;
int cmp, i;
blendEnv = getenv("DPSFONTRC");
if (blendEnv != NULL) blendFile = fopen(blendEnv, "r");
if (blendFile == NULL) {
(void) GetRootDirName(homeDir);
sprintf(fileName, "%s/.dpsfontrc", homeDir);
blendFile = fopen(fileName, "r");
if (blendFile == NULL) return;
}
while (1) {
if (fgets(buf, BUF, blendFile) == NULL) {
fclose(blendFile);
return;
}
if (ParseBlendLine(buf, family, face, blend, name, p)) {
cfamily = Canonical(family);
if (cfamily != lastFamily) {
for (ff = fsb->fsb.known_families;
ff != NULL && ff->family_name != cfamily;
ff = ff->next) {}
}
if (ff == NULL) continue;
lastFamily = cfamily;
cface = Canonical(face);
for (f = ff->fonts; f != NULL && f->face_name != cface;
f = f->next) {}
if (f != NULL && f->blend_data != NULL) {
lastb = &f->blend_data->blends;
cmp = -1;
for (b = f->blend_data->blends; b != NULL; b = b->next) {
cmp = strcmp(blend, b->blend_name);
if (cmp < 0) break;
lastb = &b->next;
}
if (cmp != 0) {
newb = XtNew(BlendRec);
newb->blend_name = Canonical(blend);
newb->CS_blend_name = CS(newb->blend_name, (Widget) fsb);
spaceBlend = (char *) XtMalloc(strlen(blend) + 4);
spaceBlend[0] = spaceBlend[1] = spaceBlend[2] = ' ';
strcpy(spaceBlend+3, blend);
newb->CS_space_blend_name = CS(spaceBlend, (Widget) fsb);
XtFree((XtPointer) spaceBlend);
for (i = 0; i < MAX_AXES; i++) newb->data[i] = p[i];
newb->font_name = Canonical(name);
f->blend_count++;
ff->blend_count++;
newb->next = b;
*lastb = newb;
}
}
}
}
}
static void SetUpFaceList(
FontSelectionBoxWidget fsb,
FontFamilyRec *ff)
{
FontRec *f;
BlendRec *b;
XmString *CSfaces;
Boolean multiple = False;
int i;
for (f = ff->fonts; f != NULL; f = f->next) {
if (f->blend_data != NULL) {
multiple = True;
break;
}
}
if (multiple) ManageMultipleMaster(fsb);
else UnmanageMultipleMaster(fsb);
CSfaces = (XmString *) XtCalloc(ff->font_count + ff->blend_count,
sizeof(XmString));
i = 0;
for (f = ff->fonts; f != NULL; f = f->next) {
CSfaces[i++] = f->CS_face_name;
if (f->blend_data != NULL) {
for (b = f->blend_data->blends; b != NULL; b = b->next) {
CSfaces[i++] = b->CS_space_blend_name;
}
}
}
XtVaSetValues(fsb->fsb.face_scrolled_list_child,
XmNitemCount, ff->font_count + ff->blend_count,
XmNitems, CSfaces, NULL);
XtFree((XtPointer) CSfaces);
}
static void DeleteMessage(
Widget widget,
XtPointer clientData, XtPointer callData)
{
XtDestroyWidget(widget);
}
static void FlushFont(
FontSelectionBoxWidget fsb,
FontRec *font)
{
FontRec *f = 0, *f1;
FontFamilyRec *ff, *ff1;
Boolean previewedFamily = False;
for (ff = fsb->fsb.known_families; ff != NULL; ff = ff->next) {
for (f = ff->fonts; f != NULL; f = f->next) {
if (f == font) goto FOUND_BOGUS;
}
}
FOUND_BOGUS:
if (f != NULL) {
for (f1 = ff->fonts; f1 != NULL; f1 = f1->next) {
if (f1 == fsb->fsb.currently_previewed) {
previewedFamily = True;
break;
}
}
if (ff->fonts == f) {
ff->fonts = f->next;
} else {
for (f1 = ff->fonts; f1 != NULL && f1->next != f; f1 = f1->next) {}
if (f1 != NULL) f1->next = f->next;
}
ff->font_count--;
ff->blend_count -= f->blend_count;
if (f == fsb->fsb.currently_selected_face) {
fsb->fsb.currently_selected_face = NULL;
fsb->fsb.currently_selected_blend = NULL;
}
if (previewedFamily) SetUpFaceList(fsb, ff);
if (f == fsb->fsb.currently_previewed) {
fsb->fsb.currently_previewed = NULL;
fsb->fsb.currently_previewed_blend = NULL;
ValueChanged(fsb);
}
if (ff->fonts == NULL) {
if (fsb->fsb.known_families == ff) {
fsb->fsb.known_families = ff->next;
} else {
for (ff1 = fsb->fsb.known_families;
ff1 != NULL && ff1->next != ff; ff1 = ff1->next) {}
if (ff1 != NULL) ff1->next = ff->next;
}
fsb->fsb.family_count--;
if (ff == fsb->fsb.currently_selected_family) {
fsb->fsb.currently_selected_family = NULL;
}
DisplayFontFamilies(fsb);
}
}
}
void _FSBFlushFont(
FontSelectionBoxWidget fsb,
FontRec *font)
{
if (font == fsb->fsb.currently_previewed) _FSBBogusFont(fsb, font);
else FlushFont(fsb, font);
}
void _FSBBogusFont(
FontSelectionBoxWidget fsb,
FontRec *font)
{
Widget message, w;
message = XmCreateInformationDialog((Widget) fsb, "invalidFontMessage",
(ArgList) NULL, 0);
w = XmMessageBoxGetChild(message, XmDIALOG_CANCEL_BUTTON);
XtUnmanageChild(w);
w = XmMessageBoxGetChild(message, XmDIALOG_HELP_BUTTON);
XtUnmanageChild(w);
XtAddCallback(message, XmNokCallback, DeleteMessage, (XtPointer) NULL);
XtManageChild(message);
FlushFont(fsb, font);
}
void _FSBSetUpFaceList(
FontSelectionBoxWidget fsb,
Bool redisplay)
{
FontRec *f;
BlendRec *b;
int i;
SetUpFaceList(fsb, fsb->fsb.currently_selected_family);
f = fsb->fsb.currently_selected_family->fonts;
i = 1;
while (f != NULL) {
if (f == fsb->fsb.currently_selected_face) {
if (f->blend_data != NULL) {
b = f->blend_data->blends;
if (fsb->fsb.currently_selected_blend != NULL) {
i++;
while (b != NULL &&
b != fsb->fsb.currently_selected_blend) {
i++;
b = b->next;
}
}
}
break;
} else {
i += f->blend_count+1;
f = f->next;
}
}
ListSelectPos(fsb->fsb.face_scrolled_list_child, i, False);
if (redisplay) ValueChanged(fsb);
fsb->fsb.blends_changed = True;
}
static String categories[][6] = {
{"Regular", "Roman", "Medium", "Book", "Light", NULL},
{"Italic", "Slanted", "Oblique", NULL},
{"Demi", "Semibold", "Heavy", "Bold", NULL},
{NULL},
};
#define NORMALINDEX 0][0
#define ITALICINDEX 1][0
#define BOLDINDEX 2][3
#define DEMIINDEX 2][0
#define LIGHTINDEX 0][4
#define BOOKINDEX 0][3
static String extraNormalFaces[] = {"Demi", "Semibold", NULL};
static int MatchFaceName(
FSBFaceSelectCallbackRec *rec,
Boolean *gaveUp)
{
int i, j, k, face;
#define PIECEMAX 10
String pieces[PIECEMAX];
int numPieces;
int pass;
char *ch, *start, *compare;
char save;
static Boolean categoriesInited = False;
static char *canonicalBold, *canonicalLight, *canonicalBook;
*gaveUp = False;
if (!categoriesInited) {
for (i = 0; categories[i][0] != NULL; i++) {
for (j = 0; categories[i][j] != NULL; j++) {
categories[i][j] = Canonical(categories[i][j]);
}
}
for (i = 0; extraNormalFaces[i] != NULL; i++) {
extraNormalFaces[i] = Canonical(extraNormalFaces[i]);
}
canonicalBold = categories[BOLDINDEX];
canonicalLight = categories[LIGHTINDEX];
canonicalBook = categories[BOOKINDEX];
categoriesInited = True;
}
if (rec->current_face == NULL || rec->current_face[0] == '\0') {
goto GIVE_UP;
}
for (i = 0; i < rec->num_available_faces; i++) {
if (rec->available_faces[i] == rec->current_face) return i;
}
categories[BOLDINDEX] = categories[LIGHTINDEX] =
categories[BOOKINDEX] = NULL;
i = 0;
ch = rec->current_face;
while (*ch == ' ' || isdigit(*ch)) ch++;
start = ch;
while (1) {
while (*ch != ' ' && *ch != '\0') ch++;
save = *ch;
*ch = '\0';
compare = Canonical(start);
for (j = 0; categories[j][0] != NULL; j++) {
for (k = 0; categories[j][k] != NULL; k++) {
if (compare == categories[j][k]) {
pieces[i++] = categories[j][0];
goto FOUND_PIECE;
}
}
}
pieces[i++] = compare;
FOUND_PIECE:
*ch = save;
while (*ch == ' ') ch++;
if (*ch == '\0') break;
if (i >= PIECEMAX) goto GIVE_UP;
start = ch;
}
numPieces = i;
if (numPieces == 0) goto GIVE_UP;
if (pieces[0] == categories[ITALICINDEX] && numPieces < PIECEMAX-1) {
for (i = numPieces; i > 0; i--) pieces[i] = pieces[i-1];
pieces[0] = categories[NORMALINDEX];
numPieces++;
}
for (pass = 0; pass < 2; pass++) {
if (pass == 1) {
categories[BOLDINDEX] = canonicalBold;
categories[LIGHTINDEX] = canonicalLight;
categories[BOOKINDEX] = canonicalBook;
for (i = 0; i < numPieces; i++) {
if (pieces[i] == canonicalBold) {
pieces[i] = categories[DEMIINDEX];
} else if (pieces[i] == canonicalLight) {
pieces[i] = categories[NORMALINDEX];
} else if (pieces[i] == canonicalBook) {
pieces[i] = categories[NORMALINDEX];
}
}
}
for (face = 0; face < rec->num_available_faces; face++) {
i = 0;
ch = rec->available_faces[face];
while (*ch == ' ' || isdigit(*ch)) ch++;
start = ch;
while (1) {
while (*ch != ' ' && *ch != '\0') ch++;
save = *ch;
*ch = '\0';
compare = Canonical(start);
for (j = 0; categories[j][0] != NULL; j++) {
for (k = 0; categories[j][k] != NULL; k++) {
if (compare == categories[j][k]) {
compare = categories[j][0];
goto MATCH;
}
}
}
MATCH:
if (i == 0 && compare == categories[ITALICINDEX] &&
pieces[0] == categories[NORMALINDEX] &&
numPieces > 1 &&
pieces[1] == categories[ITALICINDEX]) i = 1;
if (pieces[i] != compare) {
*ch = save;
goto NEXT_FACE;
} else i++;
*ch = save;
while (*ch == ' ') ch++;
if (*ch == '\0') break;
if (i >= numPieces) goto NEXT_FACE;
start = ch;
}
if (i == numPieces) return face;
NEXT_FACE:
;
}
}
GIVE_UP:
*gaveUp = True;
categories[LIGHTINDEX] = canonicalLight;
categories[BOOKINDEX] = canonicalBook;
for (i = 0; categories[0][i] != NULL; i++) {
for (face = 0; face < rec->num_available_faces; face++) {
compare = rec->available_faces[face];
while (*compare == ' ' || isdigit(*compare)) compare++;
if (compare != rec->available_faces[face]) {
compare = Canonical(compare);
}
if (categories[0][i] == compare) return face;
}
}
for (i = 0; extraNormalFaces[i] != NULL; i++) {
for (face = 0; face < rec->num_available_faces; face++) {
compare = rec->available_faces[face];
while (*compare == ' ' || isdigit(*compare)) compare++;
if (compare != rec->available_faces[face]) {
compare = Canonical(compare);
}
if (extraNormalFaces[i] == compare) return face;
}
}
return 0;
}
static void GetInitialFace(
FontSelectionBoxWidget fsb,
FontFamilyRec *ff)
{
FSBFaceSelectCallbackRec rec;
String *faces;
int i, j;
FontRec *f;
Boolean junk;
faces = (String *) XtMalloc(ff->font_count * sizeof(String));
i = 0;
for (f = ff->fonts; f != NULL; f = f->next) faces[i++] = f->face_name;
rec.available_faces = faces;
rec.num_available_faces = ff->font_count;
if (fsb->fsb.currently_selected_face != NULL) {
rec.current_face = fsb->fsb.currently_selected_face->face_name;
} else rec.current_face = fsb->fsb.font_face;
rec.new_face = NULL;
XtCallCallbackList((Widget) fsb, fsb->fsb.face_select_callback, &rec);
if (rec.new_face != NULL) {
for (i = 0; i < ff->font_count; i++) {
if (rec.new_face == faces[i]) break;
}
}
if (rec.new_face == NULL || i >= ff->font_count) {
i = MatchFaceName(&rec, &junk);
}
XtFree((XtPointer) faces);
j = 0;
for (f = ff->fonts; i != 0; f= f->next) {
j += f->blend_count + 1;
i--;
}
ListSelectPos(fsb->fsb.face_scrolled_list_child, j+1, False);
fsb->fsb.currently_selected_face = f;
fsb->fsb.currently_selected_blend = NULL;
}
static void FamilySelect(
Widget widget,
XtPointer clientData, XtPointer callData)
{
XmListCallbackStruct *listCB = (XmListCallbackStruct *) callData;
FontSelectionBoxWidget fsb = (FontSelectionBoxWidget) clientData;
FontFamilyRec *ff = fsb->fsb.known_families;
int i;
if (fsb->fsb.current_family_multiple) {
fsb->fsb.current_family_multiple = False;
UnmanageFamilyMultiple(fsb);
}
for (i = 1; i < listCB->item_position; i++) ff = ff->next;
fsb->fsb.currently_selected_family = ff;
SensitizeReset(fsb);
SetUpFaceList(fsb, ff);
if (!fsb->fsb.current_face_multiple) GetInitialFace(fsb, ff);
ValueChanged(fsb);
}
static void FaceSelect(
Widget widget,
XtPointer clientData, XtPointer callData)
{
XmListCallbackStruct *listCB = (XmListCallbackStruct *) callData;
FontSelectionBoxWidget fsb = (FontSelectionBoxWidget) clientData;
FontRec *f;
BlendRec *b;
int n;
if (fsb->fsb.currently_selected_family == NULL) return;
f = fsb->fsb.currently_selected_family->fonts;
if (fsb->fsb.current_face_multiple) {
fsb->fsb.current_face_multiple = False;
UnmanageFaceMultiple(fsb);
}
n = 0;
while (1) {
n += f->blend_count + 1;
if (n >= listCB->item_position) {
n -= f->blend_count;
if (n == listCB->item_position) b = NULL;
else for (b = f->blend_data->blends; n < listCB->item_position - 1;
b = b->next) n++;
break;
}
f = f->next;
}
fsb->fsb.currently_selected_face = f;
fsb->fsb.currently_selected_blend = b;
SensitizeReset(fsb);
ValueChanged(fsb);
}
static void CreateSizeMenu(
FontSelectionBoxWidget fsb,
Boolean destroyOldChildren)
{
Arg args[20];
int i, j;
Widget *sizes;
char buf[20];
Widget *children;
Cardinal num_children;
XmString csName;
char *ch;
if (destroyOldChildren) {
XtVaGetValues(fsb->fsb.size_menu, XtNchildren, &children,
XtNnumChildren, &num_children, NULL);
for (j = 1; (Cardinal)j < num_children; j++) XtDestroyWidget(children[j]);
sizes = (Widget *) XtMalloc((fsb->fsb.size_count+1) * sizeof(Widget));
sizes[0] = children[0];
} else {
i = 0;
sizes = (Widget *) XtMalloc((fsb->fsb.size_count+1) * sizeof(Widget));
fsb->fsb.other_size = sizes[0] =
XtCreateManagedWidget("other", xmPushButtonGadgetClass,
fsb->fsb.size_menu, args, i);
}
for (j = 0; j < fsb->fsb.size_count; j++) {
(void) sprintf(buf, "%g", fsb->fsb.sizes[j]);
csName = UnsharedCS(buf);
for (ch = buf; *ch != '\0'; ch++) if (*ch == '.') *ch = '-';
i = 0;
XtSetArg(args[i], XmNlabelString, csName); i++;
sizes[j+1] =
XmCreatePushButtonGadget(fsb->fsb.size_menu, buf, args, i);
XmStringFree(csName);
XtAddCallback(sizes[j+1], XmNactivateCallback,
SetSize, (XtPointer) fsb);
}
XtManageChildren(sizes, j+1);
XtFree((char *) sizes);
}
static void CreateChildren(FontSelectionBoxWidget fsb)
{
Arg args[20];
int i;
Widget form;
i = 0;
fsb->fsb.pane_child =
XtCreateManagedWidget("pane", xmPanedWindowWidgetClass,
(Widget) fsb, args, i);
i = 0;
fsb->fsb.preview_child =
XtCreateManagedWidget("preview", xmDrawingAreaWidgetClass,
fsb->fsb.pane_child, args, i);
XtAddCallback(fsb->fsb.preview_child, XmNexposeCallback,
PreviewText, (XtPointer) fsb);
XtAddCallback(fsb->fsb.preview_child, XmNresizeCallback,
ResizePreview, (XtPointer) fsb);
i = 0;
form = XtCreateManagedWidget("panel", xmFormWidgetClass,
fsb->fsb.pane_child, args, i);
fsb->fsb.panel_child = form;
i = 0;
XtSetArg(args[i], XmNleftAttachment, XmATTACH_FORM); i++;
XtSetArg(args[i], XmNbottomAttachment, XmATTACH_FORM); i++;
fsb->fsb.ok_button_child =
XtCreateManagedWidget("okButton", xmPushButtonWidgetClass,
form, args, i);
XtAddCallback(fsb->fsb.ok_button_child, XmNactivateCallback,
OKCallback, (XtPointer) fsb);
i = 0;
XtSetArg(args[i], XmNleftAttachment, XmATTACH_WIDGET); i++;
XtSetArg(args[i], XmNleftWidget,fsb->fsb.ok_button_child ); i++;
XtSetArg(args[i], XmNbottomAttachment, XmATTACH_FORM); i++;
fsb->fsb.apply_button_child =
XtCreateManagedWidget("applyButton", xmPushButtonWidgetClass,
form, args, i);
XtAddCallback(fsb->fsb.apply_button_child, XmNactivateCallback,
ApplyCallback, (XtPointer) fsb);
i = 0;
XtSetArg(args[i], XmNleftAttachment, XmATTACH_WIDGET); i++;
XtSetArg(args[i], XmNleftWidget,fsb->fsb.apply_button_child ); i++;
XtSetArg(args[i], XmNbottomAttachment, XmATTACH_FORM); i++;
fsb->fsb.reset_button_child =
XtCreateManagedWidget("resetButton", xmPushButtonWidgetClass,
form, args, i);
XtAddCallback(fsb->fsb.reset_button_child, XmNactivateCallback,
ResetCallback, (XtPointer) fsb);
i = 0;
XtSetArg(args[i], XmNleftAttachment, XmATTACH_WIDGET); i++;
XtSetArg(args[i], XmNleftWidget,fsb->fsb.reset_button_child ); i++;
XtSetArg(args[i], XmNbottomAttachment, XmATTACH_FORM); i++;
fsb->fsb.cancel_button_child =
XtCreateManagedWidget("cancelButton", xmPushButtonWidgetClass,
form, args, i);
XtAddCallback(fsb->fsb.cancel_button_child, XmNactivateCallback,
CancelCallback, (XtPointer) fsb);
i = 0;
XtSetArg(args[i], XmNleftAttachment, XmATTACH_FORM); i++;
XtSetArg(args[i], XmNrightAttachment, XmATTACH_FORM); i++;
XtSetArg(args[i], XmNbottomAttachment, XmATTACH_WIDGET); i++;
XtSetArg(args[i], XmNbottomWidget, fsb->fsb.ok_button_child); i++;
fsb->fsb.separator_child =
XtCreateManagedWidget("separator", xmSeparatorGadgetClass,
form, args, i);
i = 0;
XtSetArg(args[i], XmNleftAttachment, XmATTACH_FORM); i++;
XtSetArg(args[i], XmNbottomAttachment, XmATTACH_WIDGET); i++;
XtSetArg(args[i], XmNbottomWidget, fsb->fsb.separator_child); i++;
fsb->fsb.size_label_child =
XtCreateManagedWidget("sizeLabel", xmLabelWidgetClass,
form, args, i);
i = 0;
XtSetArg(args[i], XmNleftAttachment, XmATTACH_WIDGET); i++;
XtSetArg(args[i], XmNleftWidget, fsb->fsb.size_label_child); i++;
XtSetArg(args[i], XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET); i++;
XtSetArg(args[i], XmNbottomWidget, fsb->fsb.size_label_child); i++;
fsb->fsb.size_text_field_child =
XtCreateManagedWidget("sizeTextField", xmTextFieldWidgetClass,
form, args, i);
XtAddCallback(fsb->fsb.size_text_field_child, XmNvalueChangedCallback,
SizeSelect, (XtPointer) fsb);
XtAddCallback(fsb->fsb.size_text_field_child, XmNmodifyVerifyCallback,
TextVerify, (XtPointer) fsb);
i = 0;
fsb->fsb.size_menu = XmCreatePulldownMenu(form, "sizeMenu", args, i);
CreateSizeMenu(fsb, False);
i = 0;
XtSetArg(args[i], XmNleftAttachment, XmATTACH_WIDGET); i++;
XtSetArg(args[i], XmNleftWidget, fsb->fsb.size_text_field_child); i++;
XtSetArg(args[i], XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET); i++;
XtSetArg(args[i], XmNbottomWidget, fsb->fsb.size_label_child); i++;
XtSetArg(args[i], XmNsubMenuId, fsb->fsb.size_menu); i++;
fsb->fsb.size_option_menu_child =
XmCreateOptionMenu(form, "sizeOptionMenu", args, i);
XtManageChild(fsb->fsb.size_option_menu_child);
i = 0;
XtSetArg(args[i], XmNleftAttachment, XmATTACH_WIDGET); i++;
XtSetArg(args[i], XmNleftWidget, fsb->fsb.size_option_menu_child); i++;
XtSetArg(args[i], XmNbottomAttachment, XmATTACH_WIDGET); i++;
XtSetArg(args[i], XmNbottomWidget, fsb->fsb.separator_child); i++;
fsb->fsb.size_multiple_label_child =
XtCreateWidget("sizeMultipleLabel", xmLabelWidgetClass,
form, args, i);
i = 0;
XtSetArg(args[i], XmNrightAttachment, XmATTACH_FORM); i++;
XtSetArg(args[i], XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET); i++;
XtSetArg(args[i], XmNbottomWidget, fsb->fsb.size_label_child); i++;
fsb->fsb.preview_button_child =
XtCreateManagedWidget("previewButton", xmPushButtonWidgetClass,
form, args, i);
XtAddCallback(fsb->fsb.preview_button_child, XmNactivateCallback,
PreviewCallback, (XtPointer) fsb);
i = 0;
XtSetArg(args[i], XmNrightAttachment, XmATTACH_WIDGET); i++;
XtSetArg(args[i], XmNrightWidget, fsb->fsb.preview_button_child); i++;
XtSetArg(args[i], XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET); i++;
XtSetArg(args[i], XmNbottomWidget, fsb->fsb.preview_button_child); i++;
fsb->fsb.sampler_button_child =
XtCreateWidget("samplerButton", xmPushButtonWidgetClass,
form, args, i);
if (fsb->fsb.show_sampler_button) {
XtManageChild(fsb->fsb.sampler_button_child);
}
XtAddCallback(fsb->fsb.sampler_button_child, XmNactivateCallback,
ShowSamplerCallback, (XtPointer) fsb);
i = 0;
XtSetArg(args[i], XmNtopAttachment, XmATTACH_FORM); i++;
XtSetArg(args[i], XmNleftAttachment, XmATTACH_FORM); i++;
XtSetArg(args[i], XmNrightAttachment, XmATTACH_POSITION); i++;
XtSetArg(args[i], XmNrightPosition, 50); i++;
fsb->fsb.family_label_child =
XtCreateManagedWidget("familyLabel", xmLabelGadgetClass,
form, args, i);
i = 0;
XtSetArg(args[i], XmNtopAttachment, XmATTACH_FORM); i++;
XtSetArg(args[i], XmNleftAttachment, XmATTACH_POSITION); i++;
XtSetArg(args[i], XmNleftPosition, 50); i++;
XtSetArg(args[i], XmNrightAttachment, XmATTACH_FORM); i++;
fsb->fsb.face_label_child =
XtCreateManagedWidget("faceLabel", xmLabelGadgetClass,
form, args, i);
i = 0;
XtSetArg(args[i], XmNtopAttachment, XmATTACH_WIDGET); i++;
XtSetArg(args[i], XmNtopWidget, fsb->fsb.family_label_child); i++;
XtSetArg(args[i], XmNleftAttachment, XmATTACH_FORM); i++;
XtSetArg(args[i], XmNrightAttachment, XmATTACH_POSITION); i++;
XtSetArg(args[i], XmNrightPosition, 50); i++;
fsb->fsb.family_multiple_label_child =
XtCreateWidget("familyMultipleLabel", xmLabelWidgetClass,
form, args, i);
i = 0;
XtSetArg(args[i], XmNtopAttachment, XmATTACH_WIDGET); i++;
XtSetArg(args[i], XmNtopWidget, fsb->fsb.face_label_child); i++;
XtSetArg(args[i], XmNleftAttachment, XmATTACH_POSITION); i++;
XtSetArg(args[i], XmNleftPosition, 50); i++;
XtSetArg(args[i], XmNrightAttachment, XmATTACH_FORM); i++;
fsb->fsb.face_multiple_label_child =
XtCreateWidget("faceMultipleLabel", xmLabelWidgetClass,
form, args, i);
i = 0;
XtSetArg(args[i], XmNitemCount, 1); i++;
XtSetArg(args[i], XmNitems, &CSempty); i++;
fsb->fsb.family_scrolled_list_child =
XmCreateScrolledList(form, "familyScrolledList", args, i);
XtAddCallback(fsb->fsb.family_scrolled_list_child,
XmNbrowseSelectionCallback, FamilySelect, (XtPointer) fsb);
XtAddCallback(fsb->fsb.family_scrolled_list_child,
XmNdefaultActionCallback,
PreviewDoubleClick, (XtPointer) fsb);
i = 0;
XtSetArg(args[i], XmNtopAttachment, XmATTACH_WIDGET); i++;
XtSetArg(args[i], XmNtopWidget, fsb->fsb.family_label_child); i++;
XtSetArg(args[i], XmNbottomAttachment, XmATTACH_WIDGET); i++;
XtSetArg(args[i], XmNbottomWidget, fsb->fsb.size_text_field_child); i++;
XtSetArg(args[i], XmNleftAttachment, XmATTACH_FORM); i++;
XtSetArg(args[i], XmNrightAttachment, XmATTACH_POSITION); i++;
XtSetArg(args[i], XmNrightPosition, 50); i++;
XtSetValues(XtParent(fsb->fsb.family_scrolled_list_child), args, i);
XtManageChild(fsb->fsb.family_scrolled_list_child);
i = 0;
XtSetArg(args[i], XmNitemCount, 1); i++;
XtSetArg(args[i], XmNitems, &CSempty); i++;
fsb->fsb.face_scrolled_list_child =
XmCreateScrolledList(form, "faceScrolledList", args, i);
XtAddCallback(fsb->fsb.face_scrolled_list_child,
XmNbrowseSelectionCallback, FaceSelect, (XtPointer) fsb);
XtAddCallback(fsb->fsb.face_scrolled_list_child,
XmNdefaultActionCallback, PreviewDoubleClick,
(XtPointer) fsb);
i = 0;
XtSetArg(args[i], XmNtopAttachment, XmATTACH_WIDGET); i++;
XtSetArg(args[i], XmNtopWidget, fsb->fsb.face_label_child); i++;
XtSetArg(args[i], XmNbottomAttachment, XmATTACH_WIDGET); i++;
XtSetArg(args[i], XmNbottomWidget, fsb->fsb.size_text_field_child); i++;
XtSetArg(args[i], XmNleftAttachment, XmATTACH_POSITION); i++;
XtSetArg(args[i], XmNleftPosition, 50); i++;
XtSetArg(args[i], XmNrightAttachment, XmATTACH_FORM); i++;
XtSetValues(XtParent(fsb->fsb.face_scrolled_list_child), args, i);
XtManageChild(fsb->fsb.face_scrolled_list_child);
i = 0;
XtSetArg(args[i], XmNbottomAttachment, XmATTACH_WIDGET); i++;
XtSetArg(args[i], XmNbottomWidget, fsb->fsb.size_text_field_child); i++;
XtSetArg(args[i], XmNleftAttachment, XmATTACH_POSITION); i++;
XtSetArg(args[i], XmNleftPosition, 50); i++;
XtSetArg(args[i], XmNrightAttachment, XmATTACH_FORM); i++;
fsb->fsb.multiple_master_button_child =
XtCreateWidget("multipleMasterButton", xmPushButtonWidgetClass,
form, args, i);
XtAddCallback(fsb->fsb.multiple_master_button_child, XmNactivateCallback,
ShowCreatorCallback, (XtPointer) fsb);
i = 0;
XtSetArg(args[i], XmNdefaultButton, fsb->fsb.ok_button_child); i++;
XtSetValues(form, args, i);
}
static void DisplayFontFamilies(FontSelectionBoxWidget fsb)
{
FontFamilyRec *ff;
XmString *CSlist, *str;
CSlist = (XmString *) XtMalloc(fsb->fsb.family_count * sizeof(XmString));
str = CSlist;
for (ff = fsb->fsb.known_families; ff != NULL; ff = ff->next) {
*str++ = UnsharedCS(ff->family_name);
}
XtVaSetValues(fsb->fsb.family_scrolled_list_child,
XmNitemCount, fsb->fsb.family_count,
XmNitems, CSlist, NULL);
XtFree((char *) CSlist);
}
static void SetUpCurrentFontFromName(FontSelectionBoxWidget fsb)
{
FontFamilyRec *ff;
FontRec *f;
BlendRec *b;
int i, j;
fsb->fsb.currently_selected_face = NULL;
fsb->fsb.currently_selected_family = NULL;
fsb->fsb.currently_selected_blend = NULL;
if (fsb->fsb.font_name_multiple || fsb->fsb.font_name == NULL) {
fsb->fsb.font_name = NULL;
fsb->fsb.font_family = NULL;
fsb->fsb.font_blend = NULL;
fsb->fsb.font_face = NULL;
if (fsb->fsb.font_name_multiple) {
fsb->fsb.current_family_multiple = True;
fsb->fsb.current_face_multiple = True;
ManageFamilyMultiple(fsb);
ManageFaceMultiple(fsb);
}
XmListDeselectAllItems(fsb->fsb.family_scrolled_list_child);
XmListDeselectAllItems(fsb->fsb.face_scrolled_list_child);
XmListDeleteAllItems(fsb->fsb.face_scrolled_list_child);
XmListAddItem(fsb->fsb.face_scrolled_list_child, CSempty, 1);
return;
}
if (!fsb->fsb.font_name_multiple) {
fsb->fsb.current_family_multiple = False;
fsb->fsb.current_face_multiple = False;
UnmanageFamilyMultiple(fsb);
UnmanageFaceMultiple(fsb);
}
fsb->fsb.font_name = Canonical(fsb->fsb.font_name);
i = 1;
for (ff = fsb->fsb.known_families; ff != NULL; ff = ff->next) {
j = 1;
for (f = ff->fonts; f != NULL; f = f->next) {
if (f->font_name == fsb->fsb.font_name) {
fsb->fsb.font_family = ff->family_name;
fsb->fsb.font_face = f->face_name;
SetUpFaceList(fsb, ff);
ListSelectPos(fsb->fsb.family_scrolled_list_child, i, False);
ListSelectPos(fsb->fsb.face_scrolled_list_child, j, False);
fsb->fsb.currently_selected_face = f;
fsb->fsb.currently_selected_family = ff;
fsb->fsb.currently_selected_blend = NULL;
return;
}
j++;
if (f->blend_data != NULL && f->blend_data->blends != NULL) {
for (b = f->blend_data->blends; b != NULL; b = b->next) {
if (b->font_name == fsb->fsb.font_name) {
fsb->fsb.font_family = ff->family_name;
fsb->fsb.font_face = f->face_name;
SetUpFaceList(fsb, ff);
ListSelectPos(fsb->fsb.family_scrolled_list_child, i,
False);
ListSelectPos(fsb->fsb.face_scrolled_list_child, j,
False);
fsb->fsb.currently_selected_face = f;
fsb->fsb.currently_selected_family = ff;
fsb->fsb.currently_selected_blend = b;
return;
}
j++;
}
}
}
i++;
}
fsb->fsb.font_name = NULL;
fsb->fsb.font_family = NULL;
fsb->fsb.font_face = NULL;
fsb->fsb.font_blend = NULL;
XmListDeselectAllItems(fsb->fsb.family_scrolled_list_child);
XmListDeselectAllItems(fsb->fsb.face_scrolled_list_child);
XmListDeleteAllItems(fsb->fsb.face_scrolled_list_child);
XmListAddItem(fsb->fsb.face_scrolled_list_child, CSempty, 1);
}
static void SetUpCurrentFontFromFamilyFace(FontSelectionBoxWidget fsb)
{
FontFamilyRec *ff;
FontRec *f;
BlendRec *b;
int i;
fsb->fsb.currently_selected_face = NULL;
fsb->fsb.currently_selected_family = NULL;
fsb->fsb.currently_selected_blend = NULL;
if (fsb->fsb.font_family_multiple) {
fsb->fsb.font_family = NULL;
fsb->fsb.current_family_multiple = True;
ManageFamilyMultiple(fsb);
} else {
fsb->fsb.current_family_multiple = False;
UnmanageFamilyMultiple(fsb);
}
if (fsb->fsb.font_face_multiple) {
fsb->fsb.font_face = NULL;
fsb->fsb.current_face_multiple = True;
ManageFaceMultiple(fsb);
} else {
fsb->fsb.current_face_multiple = False;
UnmanageFaceMultiple(fsb);
}
fsb->fsb.font_name_multiple =
fsb->fsb.font_family_multiple || fsb->fsb.font_face_multiple;
if (fsb->fsb.font_family != NULL) {
fsb->fsb.font_family = Canonical(fsb->fsb.font_family);
i = 1;
for (ff = fsb->fsb.known_families; ff != NULL; ff = ff->next) {
if (fsb->fsb.font_family == ff->family_name) {
ListSelectPos(fsb->fsb.family_scrolled_list_child, i, False);
fsb->fsb.currently_selected_family = ff;
SetUpFaceList(fsb, ff);
break;
}
i++;
}
if (ff == NULL) fsb->fsb.font_family = NULL;
}
if (fsb->fsb.font_family == NULL) {
fsb->fsb.font_face = NULL;
fsb->fsb.font_blend = NULL;
fsb->fsb.font_name = NULL;
XmListDeselectAllItems(fsb->fsb.family_scrolled_list_child);
XmListDeselectAllItems(fsb->fsb.face_scrolled_list_child);
XmListDeleteAllItems(fsb->fsb.face_scrolled_list_child);
XmListAddItem(fsb->fsb.face_scrolled_list_child, CSempty, 1);
return;
}
if (fsb->fsb.font_face != NULL) {
fsb->fsb.font_face = Canonical(fsb->fsb.font_face);
i = 1;
for (f = ff->fonts; f != NULL; f = f->next) {
if (fsb->fsb.font_face == f->face_name) {
fsb->fsb.currently_selected_face = f;
if (fsb->fsb.font_blend != NULL) {
fsb->fsb.font_blend = Canonical(fsb->fsb.font_blend);
for (b = f->blend_data->blends; b != NULL; b = b->next) {
i++;
if (b->blend_name == fsb->fsb.font_blend) {
fsb->fsb.currently_selected_blend = b;
break;
}
}
if (b == NULL) {
fsb->fsb.font_blend = NULL;
i -= f->blend_count;
}
}
ListSelectPos(fsb->fsb.face_scrolled_list_child, i, False);
break;
}
i += f->blend_count + 1;
}
if (f == NULL) fsb->fsb.font_face = NULL;
} else {
f = NULL;
XmListDeselectAllItems(fsb->fsb.face_scrolled_list_child);
}
if (f == NULL && !fsb->fsb.font_face_multiple) GetInitialFace(fsb, ff);
}
static void SetUpCurrentFont(FontSelectionBoxWidget fsb)
{
if (fsb->fsb.use_font_name) SetUpCurrentFontFromName(fsb);
else SetUpCurrentFontFromFamilyFace(fsb);
}
static void SetUpCurrentSize(FontSelectionBoxWidget fsb)
{
char buf[20];
if (fsb->fsb.font_size_multiple) {
changingSize = True;
XtVaSetValues(fsb->fsb.size_text_field_child, XmNvalue, "", NULL);
changingSize = False;
fsb->fsb.current_size_multiple = True;
ManageSizeMultiple(fsb);
return;
} else UnmanageSizeMultiple(fsb);
if (fsb->fsb.currently_selected_size == 0.0) {
sprintf(buf, "%g", fsb->fsb.font_size);
} else sprintf(buf, "%g", fsb->fsb.currently_selected_size);
changingSize = True;
XtVaSetValues(fsb->fsb.size_text_field_child, XmNvalue, buf, NULL);
changingSize = False;
}
static void SetUpCurrentSelections(FontSelectionBoxWidget fsb)
{
SetUpCurrentFont(fsb);
SetUpCurrentSize(fsb);
if (fsb->fsb.preview_on_change) DoPreview(fsb, False);
DoValueChangedCallback(fsb);
}
static void Initialize(
Widget request, Widget new,
ArgList args,
Cardinal *num_args)
{
FontSelectionBoxWidget fsb = (FontSelectionBoxWidget) new;
Bool inited;
char version[20];
if (fsb->fsb.size_count > 0 && fsb->fsb.sizes == NULL) {
XtAppWarningMsg(XtWidgetToApplicationContext(new),
"initializeFontBox", "sizeMismatch",
"FontSelectionBoxError",
"Size count specified but no sizes present",
(String *) NULL, (Cardinal *) NULL);
fsb->fsb.size_count = 0;
}
if (fsb->fsb.size_count < 0) {
XtAppWarningMsg(XtWidgetToApplicationContext(new),
"initializeFontBox", "negativeSize",
"FontSelectionBoxError",
"Size count should not be negative",
(String *) NULL, (Cardinal *) NULL);
fsb->fsb.size_count = 0;
}
if (fsb->fsb.max_pending_deletes <= 0) {
XtAppWarningMsg(XtWidgetToApplicationContext(new),
"initializeFontBox", "nonPositivePendingDelete",
"FontSelectionBoxError",
"Pending delete max must be positive",
(String *) NULL, (Cardinal *) NULL);
fsb->fsb.max_pending_deletes = 1;
}
if (fsb->fsb.preview_string != NULL) {
fsb->fsb.preview_string = XtNewString(fsb->fsb.preview_string);
}
if (fsb->fsb.default_resource_path != NULL) {
fsb->fsb.default_resource_path =
XtNewString(fsb->fsb.default_resource_path);
}
if (fsb->fsb.resource_path_override != NULL) {
fsb->fsb.resource_path_override =
XtNewString(fsb->fsb.resource_path_override);
}
if (fsb->fsb.context == NULL) {
fsb->fsb.context = XDPSGetSharedContext(XtDisplay(fsb));
}
if (_XDPSTestComponentInitialized(fsb->fsb.context,
dps_init_bit_fsb, &inited) ==
dps_status_unregistered_context) {
XDPSRegisterContext(fsb->fsb.context, False);
}
if (!inited) {
(void) _XDPSSetComponentInitialized(fsb->fsb.context,
dps_init_bit_fsb);
_DPSFDefineFontEnumFunctions(fsb->fsb.context);
}
DPSversion(fsb->fsb.context, 20, version);
fsb->fsb.old_server = (atof(version) < 1007);
fsb->fsb.gstate = 0;
fsb->fsb.sampler = fsb->fsb.creator = NULL;
fsb->fsb.known_families = NULL;
fsb->fsb.family_count = 0;
fsb->fsb.currently_previewed = NULL;
fsb->fsb.currently_selected_face = NULL;
fsb->fsb.currently_selected_family = NULL;
fsb->fsb.currently_previewed_blend = NULL;
fsb->fsb.currently_selected_blend = NULL;
fsb->fsb.currently_previewed_size = 0.0;
fsb->fsb.currently_selected_size = 0.0;
fsb->fsb.pending_delete_count = 0;
fsb->fsb.pending_delete_font = NULL;
fsb->fsb.preview_fixed = False;
fsb->fsb.current_family_multiple = False;
fsb->fsb.current_face_multiple = False;
fsb->fsb.current_size_multiple = False;
fsb->fsb.blends_changed = False;
GetFontNames(fsb);
CreateChildren(fsb);
DisplayFontFamilies(fsb);
SetUpCurrentSelections(fsb);
DesensitizeReset(fsb);
if (fsb->fsb.show_sampler) ShowSampler(fsb);
}
static void FreeFontRec(FontRec *f)
{
BlendDataRec *bd;
BlendRec *b, *next_b;
if (f->blend_data != NULL) {
bd = f->blend_data;
for (b = bd->blends; b != NULL; b = next_b) {
next_b = b->next;
XtFree((char *) b);
}
XtFree((char *) bd->internal_break);
XtFree((char *) bd->internal_value);
XtFree((char *) bd->design_positions);
XtFree((char *) bd);
}
XtFree(f->full_name);
}
static void FreeFontLists(
FontSelectionBoxWidget fsb)
{
FontFamilyRec *ff, *next_ff;
FontRec *f, *next_f;
for (ff = fsb->fsb.known_families; ff != NULL; ff = next_ff) {
for (f = ff->fonts; f != NULL; f = next_f) {
FreeFontRec(f);
next_f = f->next;
XtFree((char *) f);
}
next_ff = ff->next;
XtFree((char *) ff);
}
fsb->fsb.known_families = NULL;
}
static void Destroy(Widget widget)
{
FontSelectionBoxWidget fsb = (FontSelectionBoxWidget) widget;
if (fsb->fsb.gstate != 0) XDPSFreeContextGState(fsb->fsb.context,
fsb->fsb.gstate);
if (fsb->fsb.preview_string != NULL) XtFree(fsb->fsb.preview_string);
if (fsb->fsb.default_resource_path != NULL) {
XtFree(fsb->fsb.default_resource_path);
}
if (fsb->fsb.resource_path_override != NULL) {
XtFree(fsb->fsb.resource_path_override);
}
FreeFontLists(fsb);
}
static void Resize(Widget widget)
{
FontSelectionBoxWidget fsb = (FontSelectionBoxWidget) widget;
XtResizeWidget(fsb->fsb.pane_child, fsb->core.width, fsb->core.height, 0);
}
static Boolean SetValues(
Widget old, Widget req, Widget new,
ArgList args,
Cardinal *num_args)
{
FontSelectionBoxWidget oldfsb = (FontSelectionBoxWidget) old;
FontSelectionBoxWidget newfsb = (FontSelectionBoxWidget) new;
Boolean refreshLists = False, setSelection = False, do_preview = False;
Bool inited;
#define NE(field) newfsb->fsb.field != oldfsb->fsb.field
#define DONT_CHANGE(field) \
if (NE(field)) newfsb->fsb.field = oldfsb->fsb.field;
DONT_CHANGE(typographic_sort);
DONT_CHANGE(pane_child);
DONT_CHANGE(preview_child);
DONT_CHANGE(panel_child);
DONT_CHANGE(family_label_child);
DONT_CHANGE(family_multiple_label_child);
DONT_CHANGE(family_scrolled_list_child);
DONT_CHANGE(face_label_child);
DONT_CHANGE(face_multiple_label_child);
DONT_CHANGE(face_scrolled_list_child);
DONT_CHANGE(size_label_child);
DONT_CHANGE(size_text_field_child);
DONT_CHANGE(size_option_menu_child);
DONT_CHANGE(preview_button_child);
DONT_CHANGE(sampler_button_child);
DONT_CHANGE(separator_child);
DONT_CHANGE(ok_button_child);
DONT_CHANGE(apply_button_child);
DONT_CHANGE(reset_button_child);
DONT_CHANGE(cancel_button_child);
#undef DONT_CHANGE
if (newfsb->fsb.size_count > 0 && newfsb->fsb.sizes == NULL) {
XtAppWarningMsg(XtWidgetToApplicationContext(new),
"setValuesFontBox", "sizeMismatch",
"FontSelectionBoxError",
"Size count specified but no sizes present",
(String *) NULL, (Cardinal *) NULL);
newfsb->fsb.size_count = 0;
}
if (newfsb->fsb.size_count < 0) {
XtAppWarningMsg(XtWidgetToApplicationContext(new),
"setValuesFontBox", "negativeSize",
"FontSelectionBoxError",
"Size count should not be negative",
(String *) NULL, (Cardinal *) NULL);
newfsb->fsb.size_count = 0;
}
if (newfsb->fsb.max_pending_deletes <= 0) {
XtAppWarningMsg(XtWidgetToApplicationContext(new),
"setValuesFontBox", "nonPositivePendingDelete",
"FontSelectionBoxError",
"Pending delete max must be positive",
(String *) NULL, (Cardinal *) NULL);
newfsb->fsb.max_pending_deletes = 1;
}
if (NE(preview_string)) {
XtFree(oldfsb->fsb.preview_string);
newfsb->fsb.preview_string = XtNewString(newfsb->fsb.preview_string);
do_preview = True;
}
if (NE(default_resource_path)) {
XtFree(oldfsb->fsb.default_resource_path);
newfsb->fsb.default_resource_path =
XtNewString(newfsb->fsb.default_resource_path);
refreshLists = True;
}
if (NE(resource_path_override)) {
XtFree(oldfsb->fsb.resource_path_override);
newfsb->fsb.resource_path_override =
XtNewString(newfsb->fsb.resource_path_override);
refreshLists = True;
}
if (newfsb->fsb.undef_unused_fonts) UndefSomeUnusedFonts(newfsb, False);
if (NE(context)) {
if (newfsb->fsb.context == NULL) {
newfsb->fsb.context = XDPSGetSharedContext(XtDisplay(newfsb));
}
if (_XDPSTestComponentInitialized(newfsb->fsb.context,
dps_init_bit_fsb, &inited) ==
dps_status_unregistered_context) {
XDPSRegisterContext(newfsb->fsb.context, False);
}
if (!inited) {
(void) _XDPSSetComponentInitialized(newfsb->fsb.context,
dps_init_bit_fsb);
_DPSFDefineFontEnumFunctions(newfsb->fsb.context);
}
}
if (refreshLists) {
UndefUnusedFonts((Widget)newfsb);
newfsb->fsb.pending_delete_font = NULL;
newfsb->fsb.pending_delete_count = 0;
FreeFontLists(newfsb);
GetFontNames(newfsb);
DisplayFontFamilies(newfsb);
setSelection = True;
}
if (NE(sizes)) {
CreateSizeMenu(newfsb, True);
setSelection = True;
}
if (NE(show_sampler)) {
if (newfsb->fsb.show_sampler) ShowSampler(newfsb);
else XtPopdown(newfsb->fsb.sampler);
}
if (NE(show_sampler_button)) {
if (newfsb->fsb.show_sampler_button) {
XtManageChild(newfsb->fsb.sampler_button_child);
} else XtUnmanageChild(newfsb->fsb.sampler_button_child);
}
if (NE(font_size)) newfsb->fsb.currently_selected_size = 0.0;
if (NE(use_font_name) || NE(font_name) || NE(font_family) ||
NE(font_face) || NE(font_size) || NE(font_name_multiple) ||
NE(font_family_multiple) || NE(font_face_multiple) ||
NE(font_size_multiple) || NE(font_blend)) setSelection = True;
if (setSelection) SetUpCurrentSelections(newfsb);
else if (do_preview && newfsb->fsb.preview_on_change) {
DoPreview(newfsb, False);
}
if ((NE(font_name) || NE(font_size)) &&
XtIsSensitive(newfsb->fsb.reset_button_child)) {
if ((newfsb->fsb.font_size_multiple ||
newfsb->fsb.font_size == newfsb->fsb.currently_selected_size) &&
(newfsb->fsb.font_name_multiple ||
newfsb->fsb.currently_selected_face == NULL ||
newfsb->fsb.font_name ==
newfsb->fsb.currently_selected_face->font_name)) {
DesensitizeReset(newfsb);
}
}
return False;
#undef NE
}
static XtGeometryResult GeometryManager(
Widget w,
XtWidgetGeometry *desired, XtWidgetGeometry *allowed)
{
#define WANTS(flag) (desired->request_mode & flag)
if (WANTS(XtCWQueryOnly)) return XtGeometryYes;
if (WANTS(CWWidth)) w->core.width = desired->width;
if (WANTS(CWHeight)) w->core.height = desired->height;
if (WANTS(CWX)) w->core.x = desired->x;
if (WANTS(CWY)) w->core.y = desired->y;
if (WANTS(CWBorderWidth)) {
w->core.border_width = desired->border_width;
}
return XtGeometryYes;
#undef WANTS
}
static void ChangeManaged(Widget w)
{
FontSelectionBoxWidget fsb = (FontSelectionBoxWidget) w;
w->core.width = fsb->composite.children[0]->core.width;
w->core.height = fsb->composite.children[0]->core.height;
}
static void SetFontName(
Widget w,
String name,
Bool name_multiple)
{
XtVaSetValues(w, XtNfontName, name, XtNuseFontName, True,
XtNfontNameMultiple, name_multiple, NULL);
}
void FSBSetFontName(
Widget w,
String name,
Bool name_multiple)
{
XtCheckSubclass(w, fontSelectionBoxWidgetClass, NULL);
(*((FontSelectionBoxWidgetClass) XtClass(w))->fsb_class.set_font_name)
(w, name, name_multiple);
}
static void SetFontFamilyFace(
Widget w,
String family, String face,
Bool family_multiple, Bool face_multiple)
{
XtVaSetValues(w, XtNfontFamily, family, XtNfontFace, face,
XtNuseFontName, False,
XtNfontFamilyMultiple, family_multiple,
XtNfontFaceMultiple, face_multiple, NULL);
}
void FSBSetFontFamilyFace(
Widget w,
String family, String face,
Bool family_multiple, Bool face_multiple)
{
XtCheckSubclass(w, fontSelectionBoxWidgetClass, NULL);
(*((FontSelectionBoxWidgetClass)
XtClass(w))->fsb_class.set_font_family_face)
(w, family, face, family_multiple, face_multiple);
}
static void SetFontSize(
Widget w,
double size,
Bool size_multiple)
{
int i;
Arg args[2];
union {
int i;
float f;
} kludge;
kludge.f = size;
i = 0;
if (sizeof(float) > sizeof(XtArgVal)) {
XtSetArg(args[i], XtNfontSize, &kludge.f); i++;
} else XtSetArg(args[i], XtNfontSize, kludge.i); i++;
XtSetArg(args[i], XtNfontSizeMultiple, size_multiple); i++;
XtSetValues(w, args, i);
}
void FSBSetFontSize(
Widget w,
double size,
Bool size_multiple)
{
XtCheckSubclass(w, fontSelectionBoxWidgetClass, NULL);
(*((FontSelectionBoxWidgetClass) XtClass(w))->fsb_class.set_font_size)
(w, size, size_multiple);
}
static void RefreshFontList(Widget w)
{
FontSelectionBoxWidget fsb = (FontSelectionBoxWidget) w;
UndefUnusedFonts((Widget)fsb);
fsb->fsb.pending_delete_font = NULL;
fsb->fsb.pending_delete_count = 0;
FreeFontLists(fsb);
FreePSResourceStorage(True);
GetFontNames(fsb);
DisplayFontFamilies(fsb);
SetUpCurrentSelections(fsb);
}
void FSBRefreshFontList(
Widget w)
{
XtCheckSubclass(w, fontSelectionBoxWidgetClass, NULL);
(*((FontSelectionBoxWidgetClass)
XtClass(w))->fsb_class.refresh_font_list) (w);
}
static void GetFamilyList(
Widget w,
int *count,
String **list)
{
FontSelectionBoxWidget fsb = (FontSelectionBoxWidget) w;
String *buf;
FontFamilyRec *ff;
*count = fsb->fsb.family_count;
*list = buf = (String *) XtMalloc(*count * sizeof(String));
for (ff = fsb->fsb.known_families; ff != NULL; ff = ff->next) {
*buf++ = ff->family_name;
}
}
void FSBGetFamilyList(
Widget w,
int *count,
String **list)
{
XtCheckSubclass(w, fontSelectionBoxWidgetClass, NULL);
(*((FontSelectionBoxWidgetClass)
XtClass(w))->fsb_class.get_family_list) (w, count, list);
}
static void GetFaceList(
Widget w,
String family,
int *count,
String **face_list, String **font_list)
{
FontSelectionBoxWidget fsb = (FontSelectionBoxWidget) w;
String *buf1, *buf2;
FontFamilyRec *ff;
FontRec *f;
family = Canonical(family);
for (ff = fsb->fsb.known_families; ff != NULL; ff = ff->next) {
if (ff->family_name == family) break;
}
if (ff == NULL) {
*count = 0;
*face_list = *font_list = NULL;
return;
}
*count = ff->font_count;
*face_list = buf1 = (String *) XtMalloc(*count * sizeof(String));
*font_list = buf2 = (String *) XtMalloc(*count * sizeof(String));
for (f = ff->fonts; f != NULL; f = f->next) {
*buf1++ = f->face_name;
*buf2++ = f->font_name;
}
}
void FSBGetFaceList(
Widget w,
String family,
int *count_return,
String **face_list, String **font_list)
{
XtCheckSubclass(w, fontSelectionBoxWidgetClass, NULL);
(*((FontSelectionBoxWidgetClass)
XtClass(w))->fsb_class.get_face_list) (w, family, count_return,
face_list, font_list);
}
void FSBUndefineUnusedFonts(
Widget w)
{
XtCheckSubclass(w, fontSelectionBoxWidgetClass, NULL);
(*((FontSelectionBoxWidgetClass)
XtClass(w))->fsb_class.undef_unused_fonts) (w);
}
static Boolean DownloadFontName(Widget w, String name)
{
FontSelectionBoxWidget fsb = (FontSelectionBoxWidget) w;
FontFamilyRec *ff;
FontRec *f;
Boolean ret;
name = Canonical(name);
for (ff = fsb->fsb.known_families; ff != NULL; ff = ff->next) {
for (f = ff->fonts; f != NULL; f = f->next) {
if (f->font_name == name) {
if (!fsb->fsb.get_server_fonts) {
int resident;
_DPSFIsFontResident(fsb->fsb.context, f->font_name,
&resident);
if (resident) f->resident = True;
}
if (f->resident) return True;
else {
ret = DownloadFont(fsb, name, fsb->fsb.context,
fsb->fsb.make_fonts_shared);
if (fsb->fsb.make_fonts_shared && ret) f->resident = True;
return ret;
}
}
}
}
return DownloadFont(fsb, name, fsb->fsb.context,
fsb->fsb.make_fonts_shared);
}
Boolean FSBDownloadFontName(
Widget w,
String name)
{
XtCheckSubclass(w, fontSelectionBoxWidgetClass, NULL);
if (name == NULL) return False;
return (*((FontSelectionBoxWidgetClass)
XtClass(w))->fsb_class.download_font_name) (w, name);
}
static Boolean MatchFontFace(
Widget w,
String old_face, String new_family,
String *new_face)
{
FontSelectionBoxWidget fsb = (FontSelectionBoxWidget) w;
FSBFaceSelectCallbackRec rec;
String *faces;
int i;
FontFamilyRec *ff;
FontRec *f;
Boolean retVal;
new_family = Canonical(new_family);
old_face = Canonical(old_face);
for (ff = fsb->fsb.known_families; ff != NULL; ff = ff->next) {
if (ff->family_name == new_family) break;
}
if (ff == NULL) {
*new_face = NULL;
return False;
}
faces = (String *) XtMalloc(ff->font_count * sizeof(String));
i = 0;
for (f = ff->fonts; f != NULL; f = f->next) faces[i++] = f->face_name;
rec.available_faces = faces;
rec.num_available_faces = ff->font_count;
rec.current_face = old_face;
rec.new_face = NULL;
i = MatchFaceName(&rec, &retVal);
*new_face = faces[i];
XtFree((XtPointer) faces);
return !retVal;
}
Boolean FSBMatchFontFace(
Widget w,
String old_face, String new_family,
String *new_face)
{
XtCheckSubclass(w, fontSelectionBoxWidgetClass, NULL);
return (*((FontSelectionBoxWidgetClass)
XtClass(w))->fsb_class.match_font_face) (w, old_face,
new_family, new_face);
}
static void FontNameToFamilyFaceBlend(
Widget w,
String font_name,
String *family, String *face, String *blend)
{
FontSelectionBoxWidget fsb = (FontSelectionBoxWidget) w;
FontFamilyRec *ff;
FontRec *f;
BlendRec *b;
font_name = Canonical(font_name);
for (ff = fsb->fsb.known_families; ff != NULL; ff = ff->next) {
for (f = ff->fonts; f != NULL; f = f->next) {
if (f->font_name == font_name) {
*family = ff->family_name;
*face = f->face_name;
*blend = NULL;
return;
}
if (f->blend_data != NULL) {
for (b = f->blend_data->blends; b != NULL; b = b->next) {
if (b->font_name == font_name) {
*family = ff->family_name;
*face = f->face_name;
*blend = b->blend_name;
return;
}
}
}
}
}
*family = NULL;
*face = NULL;
*blend = NULL;
}
static void FontNameToFamilyFace(
Widget w,
String font_name,
String *family, String *face)
{
String blend;
FontNameToFamilyFaceBlend(w, font_name, family, face, &blend);
}
void FSBFontNameToFamilyFace(
Widget w,
String font_name,
String *family, String *face)
{
XtCheckSubclass(w, fontSelectionBoxWidgetClass, NULL);
(*((FontSelectionBoxWidgetClass)
XtClass(w))->fsb_class.font_name_to_family_face) (w, font_name,
family, face);
}
static void FontFamilyFaceBlendToName(
Widget w,
String family, String face, String blend,
String *font_name)
{
FontSelectionBoxWidget fsb = (FontSelectionBoxWidget) w;
FontFamilyRec *ff;
FontRec *f;
BlendRec *b;
family = Canonical(family);
for (ff = fsb->fsb.known_families; ff != NULL; ff = ff->next) {
if (ff->family_name == family) break;
}
if (ff == NULL) {
*font_name = NULL;
return;
}
face = Canonical(face);
for (f = ff->fonts; f != NULL; f = f->next) {
if (f->face_name == face) break;
}
if (f == NULL) {
*font_name = NULL;
return;
}
if (blend == NULL) {
*font_name = f->font_name;
return;
}
if (f->blend_data == NULL) {
*font_name = NULL;
return;
}
blend = Canonical(blend);
for (b = f->blend_data->blends; b != NULL; b = b->next) {
if (b->blend_name == blend) {
*font_name = b->font_name;
return;
}
}
*font_name = NULL;
}
static void FontFamilyFaceToName(
Widget w,
String family, String face,
String *font_name)
{
FontFamilyFaceBlendToName(w, family, face, NULL, font_name);
}
void FSBFontFamilyFaceToName(
Widget w,
String family, String face,
String *font_name)
{
XtCheckSubclass(w, fontSelectionBoxWidgetClass, NULL);
(*((FontSelectionBoxWidgetClass)
XtClass(w))->fsb_class.font_family_face_to_name) (w, family, face,
font_name);
}
String FSBFindAFM(
Widget w,
String font_name)
{
XtCheckSubclass(w, fontSelectionBoxWidgetClass, NULL);
return (*((FontSelectionBoxWidgetClass) XtClass(w))->
fsb_class.find_afm) (w, font_name);
}
String FSBFindFontFile(
Widget w,
String font_name)
{
XtCheckSubclass(w, fontSelectionBoxWidgetClass, NULL);
return (*((FontSelectionBoxWidgetClass) XtClass(w))->
fsb_class.find_font_file) (w, font_name);
}
static void GetTextDimensions(
Widget w,
String text, String font,
double size, double x, double y,
float *dx, float *dy, float *left, float *right, float *top, float *bottom)
{
FontSelectionBoxWidget fsb = (FontSelectionBoxWidget) w;
int bogusFont;
_DPSFGetTextDimensions(fsb->fsb.context, text, font, size, x, y,
dx, dy, left, right, top, bottom, &bogusFont);
}
void FSBGetTextDimensions(
Widget w,
String text, String font,
double size, double x, double y,
float *dx, float *dy, float *left, float *right, float *top, float *bottom)
{
XtCheckSubclass(w, fontSelectionBoxWidgetClass, NULL);
(*((FontSelectionBoxWidgetClass) XtClass(w))->
fsb_class.get_text_dimensions) (w, text, font, size, x, y,
dx, dy, left, right, top, bottom);
}
static void SetFontFamilyFaceBlend(
Widget w,
String family,
String face,
String blend,
Bool family_multiple,
Bool face_multiple)
{
XtVaSetValues(w, XtNfontFamily, family, XtNfontFace, face,
XtNfontBlend, blend, XtNuseFontName, False,
XtNfontFamilyMultiple, family_multiple,
XtNfontFaceMultiple, face_multiple, NULL);
}
void FSBSetFontFamilyFaceBlend(
Widget w,
String font_family,
String font_face,
String font_blend,
Bool font_family_multiple,
Bool font_face_multiple)
{
XtCheckSubclass(w, fontSelectionBoxWidgetClass, NULL);
(*((FontSelectionBoxWidgetClass) XtClass(w))->
fsb_class.set_font_family_face_blend) (w, font_family, font_face,
font_blend,
font_family_multiple,
font_face_multiple);
}
void FSBFontNameToFamilyFaceBlend(
Widget w,
String font_name,
String *family,
String *face,
String *blend)
{
XtCheckSubclass(w, fontSelectionBoxWidgetClass, NULL);
(*((FontSelectionBoxWidgetClass) XtClass(w))->
fsb_class.font_name_to_family_face_blend) (w, font_name, family,
face, blend);
}
void FSBFontFamilyFaceBlendToName(
Widget w,
String family,
String face,
String blend,
String *font_name)
{
XtCheckSubclass(w, fontSelectionBoxWidgetClass, NULL);
(*((FontSelectionBoxWidgetClass) XtClass(w))->
fsb_class.font_family_face_blend_to_name) (w, family, face,
blend, font_name);
}
static void GetBlendList(
Widget w,
String name,
int *count_return,
String **blend_return,
String **font_name_return,
float **axis_values_return)
{
FontSelectionBoxWidget fsb = (FontSelectionBoxWidget) w;
String *buf1, *buf2;
float *buf3;
FontFamilyRec *ff;
FontRec *f;
BlendRec *b;
int i;
name = Canonical(name);
for (ff = fsb->fsb.known_families; ff != NULL; ff = ff->next) {
for (f = ff->fonts; f != NULL; f = f->next) {
if (f->font_name == name) break;
}
}
if (ff == NULL || f == NULL || f->blend_data == NULL) {
*count_return = 0;
*blend_return = *font_name_return = NULL;
*axis_values_return = NULL;
return;
}
*count_return = f->blend_count;
*blend_return = buf1 = (String *) XtMalloc(*count_return * sizeof(String));
*font_name_return = buf2 =
(String *) XtMalloc(*count_return * sizeof(String));
*axis_values_return = buf3 =
(float *) XtMalloc(*count_return * MAX_AXES * sizeof(float));
for (b = f->blend_data->blends; b != NULL; b = b->next) {
*buf1++ = b->blend_name;
*buf2++ = b->font_name;
for (i = 0; i < MAX_AXES; i++) *buf3++ = b->data[i];
}
}
void FSBGetBlendList(
Widget w,
String name,
int *count_return,
String **blend_return,
String **font_name_return,
float **axis_values_return)
{
XtCheckSubclass(w, fontSelectionBoxWidgetClass, NULL);
(*((FontSelectionBoxWidgetClass) XtClass(w))->
fsb_class.get_blend_list) (w, name, count_return, blend_return,
font_name_return, axis_values_return);
}
static void GetBlendInfo(
Widget w,
String name,
int *num_axes_return,
int *num_designs_return,
String **axis_names_return,
float **blend_positions_return,
int **blend_map_count_return,
int **blend_design_coords_return,
float **blend_normalized_coords_return)
{
FontSelectionBoxWidget fsb = (FontSelectionBoxWidget) w;
FontFamilyRec *ff;
FontRec *f;
BlendDataRec *bd;
int i, j;
float *fbuf;
int *ibuf;
String *sbuf;
int coords;
name = Canonical(name);
if (fsb->fsb.currently_selected_face->font_name == name) {
bd = fsb->fsb.currently_selected_face->blend_data;
} else {
for (ff = fsb->fsb.known_families; ff != NULL; ff = ff->next) {
for (f = ff->fonts; f != NULL; f = f->next) {
if (f->font_name == name) goto FOUND_IT;
}
}
*num_axes_return = *num_designs_return = 0;
*axis_names_return = NULL;
*blend_positions_return = *blend_normalized_coords_return = NULL;
*blend_map_count_return = *blend_design_coords_return = NULL;
return;
FOUND_IT:
bd = f->blend_data;
}
*num_axes_return = bd->num_axes;
*num_designs_return = bd->num_designs;
*axis_names_return = sbuf =
(String *) XtMalloc(bd->num_axes * sizeof(String));
*blend_map_count_return = ibuf =
(int *) XtMalloc(bd->num_axes * sizeof(int));
coords = 0;
for (i = 0; i < bd->num_axes; i++) {
*sbuf++ = bd->name[i];
*ibuf++ = bd->internal_points[i] + 2;
coords += bd->internal_points[i] + 2;
}
*blend_positions_return = fbuf =
(float *) XtMalloc(bd->num_axes * bd->num_designs * sizeof(float));
for (i = 0; i < bd->num_axes * bd->num_designs; i++) {
*fbuf++ = bd->design_positions[i];
}
*blend_design_coords_return = ibuf =
(int *) XtMalloc(coords * sizeof(int));
*blend_normalized_coords_return = fbuf =
(float *) XtMalloc(coords * sizeof(float));
for (i = 0; i < bd->num_axes; i++) {
*ibuf++ = bd->min[i];
*fbuf++ = 0.0;
for (j = 0; j < bd->internal_points[i]; j++) {
*ibuf++ = bd->internal_break[i][j];
*fbuf++ = bd->internal_value[i][j];
}
*ibuf++ = bd->max[i];
*fbuf++ = 1.0;
}
}
void FSBGetBlendInfo(
Widget w,
String name,
int *num_axes_return,
int *num_designs_return,
String **axis_names_return,
float **blend_positions_return,
int **blend_map_count_return,
int **blend_design_coords_return,
float **blend_normalized_coords_return)
{
XtCheckSubclass(w, fontSelectionBoxWidgetClass, NULL);
(*((FontSelectionBoxWidgetClass) XtClass(w))->
fsb_class.get_blend_info) (w, name, num_axes_return,
num_designs_return, axis_names_return,
blend_positions_return,
blend_map_count_return,
blend_design_coords_return,
blend_normalized_coords_return);
}
static Boolean ChangeBlends(
Widget w,
String base_name,
String blend_name,
FSBBlendAction action,
int *axis_values,
float *axis_percents)
{
FontSelectionBoxWidget fsb = (FontSelectionBoxWidget) w;
FontFamilyRec *ff;
FontRec *f;
BlendRec *b = NULL, *newb, **lastb;
BlendDataRec *bd;
String spaceBlend;
int val[4];
float pct[4];
int i;
base_name = Canonical(base_name);
blend_name = Canonical(blend_name);
for (ff = fsb->fsb.known_families; ff != NULL; ff = ff->next) {
for (f = ff->fonts; f != NULL; f = f->next) {
if (f->font_name == base_name) {
if ((bd = f->blend_data) == NULL) return False;
for (b = f->blend_data->blends; b != NULL; b = b->next) {
if (b->blend_name == blend_name) break;
}
goto FOUND_BASE;
}
}
}
return False;
FOUND_BASE:
if (action != FSBDeleteBlend) {
if (axis_values != NULL) {
for (i = 0; i < bd->num_axes; i++) {
val[i] = axis_values[i];
pct[i] = _FSBNormalize(val[i], bd, i);
}
for (; i < 4; i++) pct[i] = 0.0;
} else {
if (axis_percents == NULL) return False;
for (i = 0; i < bd->num_axes; i++) {
pct[i] = axis_percents[i];
val[i] = _FSBUnnormalize(pct[i], bd, i);
}
for (; i < 4; i++) pct[i] = 0.0;
}
}
switch (action) {
case FSBAddBlend:
if (b != NULL) return False;
newb = XtNew(BlendRec);
newb->blend_name = blend_name;
newb->CS_blend_name = CS(blend_name, (Widget) fsb);
spaceBlend = (char *) XtMalloc(strlen(blend_name) + 4);
spaceBlend[0] = spaceBlend[1] = spaceBlend[2] = ' ';
strcpy(spaceBlend+3, blend_name);
newb->CS_space_blend_name = CS(spaceBlend, (Widget) fsb);
XtFree((XtPointer) spaceBlend);
for (i = 0; i < MAX_AXES; i++) newb->data[i] = pct[i];
newb->font_name = _FSBGenFontName(base_name, val, bd);
f->blend_count++;
ff->blend_count++;
lastb = &bd->blends;
for (b = bd->blends; b != NULL; b = b->next) {
if (strcmp(blend_name, b->blend_name) < 0) break;
lastb = &b->next;
}
newb->next = b;
*lastb = newb;
break;
case FSBReplaceBlend:
if (b == NULL) return False;
for (i = 0; i < MAX_AXES; i++) b->data[i] = pct[i];
b->font_name = _FSBGenFontName(base_name, val, bd);
if (b == fsb->fsb.currently_previewed_blend) DoPreview(fsb, False);
break;
case FSBDeleteBlend:
if (b == NULL) return False;
if (bd->blends == b) {
bd->blends = b->next;
} else {
for (newb = bd->blends; newb->next != b; newb = newb->next) {}
newb->next = b->next;
}
f->blend_count--;
ff->blend_count--;
break;
}
if (f->in_font_creator) _FSBSetCreatorFamily(fsb->fsb.creator, ff);
if (ff == fsb->fsb.currently_selected_family) SetUpFaceList(fsb, ff);
fsb->fsb.blends_changed = True;
WriteBlends(fsb);
return True;
}
Boolean FSBChangeBlends(
Widget w,
String base_name,
String blend_name,
FSBBlendAction action,
int *axis_values,
float *axis_percents)
{
XtCheckSubclass(w, fontSelectionBoxWidgetClass, NULL);
return (*((FontSelectionBoxWidgetClass) XtClass(w))->
fsb_class.change_blends) (w, base_name, blend_name, action,
axis_values, axis_percents);
}
void _FSBSetCurrentFont(
FontSelectionBoxWidget fsb,
String name)
{
FontFamilyRec *ff;
FontRec *f;
BlendRec *b;
int i, j;
fsb->fsb.current_family_multiple = False;
fsb->fsb.current_face_multiple = False;
UnmanageFamilyMultiple(fsb);
UnmanageFaceMultiple(fsb);
name = Canonical(name);
i = 1;
for (ff = fsb->fsb.known_families; ff != NULL; ff = ff->next) {
j = 1;
for (f = ff->fonts; f != NULL; f = f->next) {
if (f->font_name == name) {
b = NULL;
goto FOUND_NAME;
}
j++;
if (f->blend_data != NULL && f->blend_data->blends != NULL) {
for (b = f->blend_data->blends; b != NULL; b = b->next) {
if (b->font_name == name) {
goto FOUND_NAME;
}
j++;
}
}
}
i++;
}
return;
FOUND_NAME:
SetUpFaceList(fsb, ff);
ListSelectPos(fsb->fsb.family_scrolled_list_child, i, False);
ListSelectPos(fsb->fsb.face_scrolled_list_child, j, False);
fsb->fsb.currently_selected_face = f;
fsb->fsb.currently_selected_family = ff;
fsb->fsb.currently_selected_blend = b;
SensitizeReset(fsb);
DoPreview(fsb, False);
}
float _FSBNormalize(
int val,
BlendDataRec *bd,
int i)
{
int j;
int lessBreak, moreBreak;
float lessValue, moreValue;
if (bd->internal_points[i] == 0) {
return ((float) (val - bd->min[i])) /
((float) (bd->max[i] - bd->min[i]));
}
lessBreak = bd->min[i];
lessValue = 0.0;
moreBreak = bd->max[i];
moreValue = 1.0;
for (j = 0; j < bd->internal_points[i]; j++) {
if (bd->internal_break[i][j] > lessBreak &&
bd->internal_break[i][j] <= val) {
lessBreak = bd->internal_break[i][j];
lessValue = bd->internal_value[i][j];
}
if (bd->internal_break[i][j] < moreBreak &&
bd->internal_break[i][j] >= val) {
moreBreak = bd->internal_break[i][j];
moreValue = bd->internal_value[i][j];
}
}
if (moreBreak == lessBreak) return moreValue;
return lessValue + (moreValue - lessValue) *
((float) (val - lessBreak)) / ((float) (moreBreak - lessBreak));
}
int _FSBUnnormalize(val, bd, i)
float val;
BlendDataRec *bd;
int i;
{
int j;
int lessBreak, moreBreak;
float lessValue, moreValue;
if (bd->internal_points[i] == 0) {
return val * (bd->max[i] - bd->min[i]) + bd->min[i] + 0.5;
}
lessBreak = bd->min[i];
lessValue = 0.0;
moreBreak = bd->max[i];
moreValue = 1.0;
for (j = 0; j < bd->internal_points[i]; j++) {
if (bd->internal_value[i][j] > lessValue &&
bd->internal_value[i][j] <= val) {
lessBreak = bd->internal_break[i][j];
lessValue = bd->internal_value[i][j];
}
if (bd->internal_value[i][j] < moreBreak &&
bd->internal_value[i][j] >= val) {
moreBreak = bd->internal_break[i][j];
moreValue = bd->internal_value[i][j];
}
}
if (moreBreak == lessBreak) return moreBreak;
return ((float) (val - lessValue)) / ((float) (moreValue - lessValue)) *
(moreBreak - lessBreak) + lessBreak + 0.5;
}
String _FSBGenFontName(
String name,
int *val,
BlendDataRec *bd)
{
char nameBuf[256];
int i;
char *ch;
strcpy(nameBuf, name);
ch = nameBuf + strlen(nameBuf);
for (i = 0; i < bd->num_axes; i++) {
sprintf(ch, "_%d_%s", val[i], bd->name[i]);
ch = ch + strlen(ch);
}
return Canonical(nameBuf);
}