Refactor replicant system a bit

This commit is contained in:
Sasha Koshka 2023-11-14 00:18:51 -05:00
parent a6fa746ef3
commit 192aa666ca
3 changed files with 64 additions and 57 deletions

View File

@ -15,7 +15,7 @@ typedef int (*XmdReplicantFnVersion) ();
typedef void (*XmdReplicantFnConstruct) ();
typedef void (*XmdReplicantFnDestruct) ();
typedef Widget (*XmdReplicantFnCreate) (
Widget parent, XmdReplicantState *state);
XtAppContext application, Widget parent, XmdReplicantState *state);
/* XmdReplicantOpen opens a replicant from the file located at path. Replicant
files hold state and point to shared object files containing their code.
@ -41,15 +41,16 @@ typedef Widget (*XmdReplicantFnCreate) (
different API version will refuse to load it.
void NAME_XmdReplicantConstruct ();
Construct is called when the shared object is loaded.
Optional. Construct is called when the shared object is loaded.
void NAME_XmdReplicantDestruct ();
Descruct is called before the shared object is unloaded.
Optional. Descruct is called before the shared object is unloaded.
Widget NAME_XmdReplicantCreate (Widget parent, XmdReplicantState *state);
Widget NAME_XmdReplicantCreate (
XtAppContext application, Widget parent, XmdReplicantState *state);
Create instantiates a new widget representing the replicant given by state.
*/
Widget XmdReplicantOpen (Widget parent, ConstString path);
Widget XmdReplicantOpen (XtAppContext app, Widget parent, ConstString path);
/* XmdReplicantResolveName returns the file path of the given replicant shared
object name according to $XMD_REPLICANT_PATH. The returned string must be

View File

@ -21,80 +21,81 @@ typedef struct {
XmdReplicantFnDestruct destruct;
XmdReplicantFnCreate create;
} symbols;
} XmdReplicantSource;
} replicantSource;
struct _XmdReplicantState {
String file;
String sourceName;
XmdReplicantSource *source;
replicantSource *source;
XmdStringMap *map;
};
static void XmdReplicantHandleDestroy (
Widget replicant,
XtPointer clientData,
XtPointer callData);
static XmdError XmdReplicantStateSave (XmdReplicantState *state);
static XmdError XmdReplicantStateLoad (XmdReplicantState *state);
static XmdReplicantState *XmdReplicantStateNew ();
static void XmdReplicantStateFree (XmdReplicantState *state);
static XmdReplicantSource *XmdReplicantSourceOpen (ConstString name);
static void XmdReplicantSourceClose (XmdReplicantSource *source);
static XmdReplicantSource *XmdReplicantSourceGet (ConstString name);
static String XmdReplicantScanDir (
ConstString path,
ConstString name);
static void XmdReplicantEnsure ();
/* internal function prototypes */
static void handleDestroy (Widget, XtPointer, XtPointer);
static XmdError stateSave (XmdReplicantState *state);
static XmdError stateLoad (XmdReplicantState *state);
static XmdReplicantState *stateNew ();
static void stateFree (XmdReplicantState *state);
static replicantSource *sourceOpen (ConstString name);
static void sourceClose (replicantSource *source);
static replicantSource *sourceGet (ConstString name);
static String scanDir (ConstString path, ConstString name);
static void ensure ();
static String readEscapedMapString (FILE *, char);
static void writeEscapedMapString (FILE *, ConstString);
static Bool freeMapValue (XmdStringMap *, ConstString, void *, void *);
static Bool writeMapValue (XmdStringMap *, ConstString, void *, void *);
/* resident maps source names to source structs */
static XmdStringMap *resident = NULL;
static const String defaultReplicantPath =
"/usr/lib/Xmd/replicants:"
"/usr/local/lib/Xmd/replicants";
static XmdStringMap *resident = NULL; /* source names to source structs */
"/usr/local/lib/Xmd/replicants:"
"/usr/lib/Xmd/replicants";
Widget XmdReplicantOpen (Widget parent, ConstString path) {
Widget XmdReplicantOpen (XtAppContext app, Widget parent, ConstString path) {
/* create and load the state */
XmdReplicantState *state = XmdReplicantStateNew();
XmdReplicantState *state = stateNew();
if (state == NULL) goto fail;
state->file = XtNewString(path);
if (state->file == NULL) goto fail;
XmdReplicantStateLoad(state);
stateLoad(state);
/* retrieve the replicant's source */
XmdReplicantSource *source = XmdReplicantSourceGet(state->sourceName);
replicantSource *source = sourceGet(state->sourceName);
if (source == NULL) goto fail;
source->references ++;
state->source = source;
/* create replicant and bind its state */
Widget replicant = source->symbols.create(parent, state);
Widget replicant = source->symbols.create(app, parent, state);
XtAddCallback (
replicant, XmNdestroyCallback,
XmdReplicantHandleDestroy, state);
handleDestroy, state);
return replicant;
fail:
XmdReplicantStateFree(state);
stateFree(state);
return NULL;
}
static void XmdReplicantHandleDestroy (
static void handleDestroy (
Widget replicant,
XtPointer clientData,
XtPointer callData
) {
(void)(replicant);
(void)(callData);
XmdReplicantEnsure();
ensure();
XmdReplicantState *state = clientData;
if (state == NULL) return;
state->source->references --;
if (state->source->references < 1) {
XmdReplicantSourceClose (
sourceClose (
XmdStringMapSet(resident, state->sourceName, NULL));
}
XmdReplicantStateFree(state);
stateFree(state);
}
String XmdReplicantResolveName (ConstString rawName) {
@ -114,7 +115,7 @@ String XmdReplicantResolveName (ConstString rawName) {
XmdBufferPush(dirBuffer, &null);
String dir = XmdBufferBreak(dirBuffer);
dirBuffer = NULL;
file = XmdReplicantScanDir(dir, name);
file = scanDir(dir, name);
XtFree(dir);
} else {
XmdBufferPush(dirBuffer, &ch);
@ -135,7 +136,7 @@ void XmdReplicantStateStore (
) {
String old = XmdStringMapSet(state->map, name, XtNewString(value));
XtFree(old);
XmdReplicantStateSave(state);
stateSave(state);
}
static void writeEscapedMapString (FILE *file, ConstString string) {
@ -180,7 +181,7 @@ static Bool writeMapValue (
return True;
}
static XmdError XmdReplicantStateSave (XmdReplicantState *state) {
static XmdError stateSave (XmdReplicantState *state) {
FILE *file = fopen(state->file, "w");
if (file == NULL) return XmdErrorCantOpenFile;
fprintf(file, "[%s]\n", state->sourceName);
@ -217,7 +218,7 @@ static String readEscapedMapString (FILE *file, char delimiter) {
return XmdBufferBreak(string);
}
static XmdError XmdReplicantStateLoad (XmdReplicantState *state) {
static XmdError stateLoad (XmdReplicantState *state) {
if (state->sourceName != NULL) XtFree(state->sourceName);
state->sourceName = NULL;
@ -256,7 +257,7 @@ static XmdError XmdReplicantStateLoad (XmdReplicantState *state) {
}
}
static XmdReplicantState *XmdReplicantStateNew () {
static XmdReplicantState *stateNew () {
XmdReplicantState *state = XtNew(XmdReplicantState);
if (state == NULL) return NULL;
@ -266,7 +267,7 @@ static XmdReplicantState *XmdReplicantStateNew () {
return state;
fail:
XmdReplicantStateFree(state);
stateFree(state);
return NULL;
}
@ -282,7 +283,7 @@ static Bool freeMapValue (
return True;
}
static void XmdReplicantStateFree (XmdReplicantState *state) {
static void stateFree (XmdReplicantState *state) {
if (state == NULL) return;
XtFree(state->file);
XtFree(state->sourceName);
@ -291,11 +292,11 @@ static void XmdReplicantStateFree (XmdReplicantState *state) {
XtFree((char *)(state));
}
static XmdReplicantSource *XmdReplicantSourceOpen (ConstString name) {
static replicantSource *sourceOpen (ConstString name) {
/* allocate */
XmdReplicantSource *source = XtNew(XmdReplicantSource);
replicantSource *source = XtNew(replicantSource);
if (source == NULL) goto fail;
memset(source, 0, sizeof(XmdReplicantSource));
memset(source, 0, sizeof(replicantSource));
/* open library */
String path = XmdReplicantResolveName(name);
@ -316,13 +317,11 @@ static XmdReplicantSource *XmdReplicantSourceOpen (ConstString name) {
source->symbols.construct = (XmdReplicantFnConstruct) (
dlsym(source->handle, symbolName));
XtFree(symbolName);
if (source->symbols.construct == NULL) goto fail;
XtAsprintf(&symbolName, "%s_XmdReplicantDestruct", name);
source->symbols.destruct = (XmdReplicantFnDestruct) (
dlsym(source->handle, symbolName));
XtFree(symbolName);
if (source->symbols.destruct == NULL) goto fail;
XtAsprintf(&symbolName, "%s_XmdReplicantCreate", name);
source->symbols.create = (XmdReplicantFnCreate) (
@ -333,31 +332,33 @@ static XmdReplicantSource *XmdReplicantSourceOpen (ConstString name) {
/* check if the version matches */
if (source->symbols.version() != XmdREPLICANT_VERSION) goto fail;
if (source->symbols.construct != NULL) source->symbols.construct();
return source;
fail:
XmdReplicantSourceClose(source);
sourceClose(source);
return NULL;
}
static void XmdReplicantSourceClose (XmdReplicantSource *source) {
static void sourceClose (replicantSource *source) {
if (source == NULL) return;
if (source->symbols.destruct != NULL) source->symbols.destruct();
if (source->handle != NULL) dlclose(source->handle);
XtFree((char *)(source));
}
static XmdReplicantSource *XmdReplicantSourceGet (ConstString name) {
XmdReplicantEnsure();
static replicantSource *sourceGet (ConstString name) {
ensure();
/* check to see if it has already been loaded */
XmdReplicantSource *source = XmdStringMapGet(resident, name);
replicantSource *source = XmdStringMapGet(resident, name);
if (source != NULL) return source;
/* open the source */
return XmdReplicantSourceOpen(name);
return sourceOpen(name);
}
static String XmdReplicantScanDir (ConstString path, ConstString name) {
static String scanDir (ConstString path, ConstString name) {
DIR *dir = opendir(path);
if (dir == NULL) return NULL;
@ -375,7 +376,7 @@ static String XmdReplicantScanDir (ConstString path, ConstString name) {
return result;
}
static void XmdReplicantEnsure () {
static void ensure () {
if (resident == NULL) {
resident = XmdStringMapNew();
}

View File

@ -47,7 +47,11 @@ void handleDestroyFreePixmap (
XFreePixmap(XtDisplay(replicant), (Pixmap)(clientData));
}
Widget Launcher_XmdReplicantCreate (Widget parent, XmdReplicantState *state) {
Widget Launcher_XmdReplicantCreate (
XtAppContext application,
Widget parent,
XmdReplicantState *state,
) {
String iconName = XmdReplicantStateQuery(state, "Icon");
Pixmap icon;
#define iconCase(name) if (strcmp(#name, iconName) == 0) {\
@ -61,6 +65,7 @@ Widget Launcher_XmdReplicantCreate (Widget parent, XmdReplicantState *state) {
iconCase(WebBrowser)
iconCase(Music)
icon = XmdLoadBitmapIcon(parent, unknown);
#undef iconCase
XtFree(iconName);