Refactor replicant system a bit
This commit is contained in:
parent
a6fa746ef3
commit
192aa666ca
@ -15,7 +15,7 @@ typedef int (*XmdReplicantFnVersion) ();
|
|||||||
typedef void (*XmdReplicantFnConstruct) ();
|
typedef void (*XmdReplicantFnConstruct) ();
|
||||||
typedef void (*XmdReplicantFnDestruct) ();
|
typedef void (*XmdReplicantFnDestruct) ();
|
||||||
typedef Widget (*XmdReplicantFnCreate) (
|
typedef Widget (*XmdReplicantFnCreate) (
|
||||||
Widget parent, XmdReplicantState *state);
|
XtAppContext application, Widget parent, XmdReplicantState *state);
|
||||||
|
|
||||||
/* XmdReplicantOpen opens a replicant from the file located at path. Replicant
|
/* XmdReplicantOpen opens a replicant from the file located at path. Replicant
|
||||||
files hold state and point to shared object files containing their code.
|
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.
|
different API version will refuse to load it.
|
||||||
|
|
||||||
void NAME_XmdReplicantConstruct ();
|
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 ();
|
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.
|
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
|
/* XmdReplicantResolveName returns the file path of the given replicant shared
|
||||||
object name according to $XMD_REPLICANT_PATH. The returned string must be
|
object name according to $XMD_REPLICANT_PATH. The returned string must be
|
||||||
|
@ -21,80 +21,81 @@ typedef struct {
|
|||||||
XmdReplicantFnDestruct destruct;
|
XmdReplicantFnDestruct destruct;
|
||||||
XmdReplicantFnCreate create;
|
XmdReplicantFnCreate create;
|
||||||
} symbols;
|
} symbols;
|
||||||
} XmdReplicantSource;
|
} replicantSource;
|
||||||
|
|
||||||
struct _XmdReplicantState {
|
struct _XmdReplicantState {
|
||||||
String file;
|
String file;
|
||||||
String sourceName;
|
String sourceName;
|
||||||
XmdReplicantSource *source;
|
replicantSource *source;
|
||||||
XmdStringMap *map;
|
XmdStringMap *map;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void XmdReplicantHandleDestroy (
|
/* internal function prototypes */
|
||||||
Widget replicant,
|
static void handleDestroy (Widget, XtPointer, XtPointer);
|
||||||
XtPointer clientData,
|
static XmdError stateSave (XmdReplicantState *state);
|
||||||
XtPointer callData);
|
static XmdError stateLoad (XmdReplicantState *state);
|
||||||
static XmdError XmdReplicantStateSave (XmdReplicantState *state);
|
static XmdReplicantState *stateNew ();
|
||||||
static XmdError XmdReplicantStateLoad (XmdReplicantState *state);
|
static void stateFree (XmdReplicantState *state);
|
||||||
static XmdReplicantState *XmdReplicantStateNew ();
|
static replicantSource *sourceOpen (ConstString name);
|
||||||
static void XmdReplicantStateFree (XmdReplicantState *state);
|
static void sourceClose (replicantSource *source);
|
||||||
static XmdReplicantSource *XmdReplicantSourceOpen (ConstString name);
|
static replicantSource *sourceGet (ConstString name);
|
||||||
static void XmdReplicantSourceClose (XmdReplicantSource *source);
|
static String scanDir (ConstString path, ConstString name);
|
||||||
static XmdReplicantSource *XmdReplicantSourceGet (ConstString name);
|
static void ensure ();
|
||||||
static String XmdReplicantScanDir (
|
static String readEscapedMapString (FILE *, char);
|
||||||
ConstString path,
|
static void writeEscapedMapString (FILE *, ConstString);
|
||||||
ConstString name);
|
static Bool freeMapValue (XmdStringMap *, ConstString, void *, void *);
|
||||||
static void XmdReplicantEnsure ();
|
static Bool writeMapValue (XmdStringMap *, ConstString, void *, void *);
|
||||||
|
|
||||||
|
/* resident maps source names to source structs */
|
||||||
|
static XmdStringMap *resident = NULL;
|
||||||
static const String defaultReplicantPath =
|
static const String defaultReplicantPath =
|
||||||
"/usr/lib/Xmd/replicants:"
|
"/usr/local/lib/Xmd/replicants:"
|
||||||
"/usr/local/lib/Xmd/replicants";
|
"/usr/lib/Xmd/replicants";
|
||||||
static XmdStringMap *resident = NULL; /* source names to source structs */
|
|
||||||
|
|
||||||
Widget XmdReplicantOpen (Widget parent, ConstString path) {
|
Widget XmdReplicantOpen (XtAppContext app, Widget parent, ConstString path) {
|
||||||
/* create and load the state */
|
/* create and load the state */
|
||||||
XmdReplicantState *state = XmdReplicantStateNew();
|
XmdReplicantState *state = stateNew();
|
||||||
if (state == NULL) goto fail;
|
if (state == NULL) goto fail;
|
||||||
state->file = XtNewString(path);
|
state->file = XtNewString(path);
|
||||||
if (state->file == NULL) goto fail;
|
if (state->file == NULL) goto fail;
|
||||||
XmdReplicantStateLoad(state);
|
stateLoad(state);
|
||||||
|
|
||||||
/* retrieve the replicant's source */
|
/* retrieve the replicant's source */
|
||||||
XmdReplicantSource *source = XmdReplicantSourceGet(state->sourceName);
|
replicantSource *source = sourceGet(state->sourceName);
|
||||||
if (source == NULL) goto fail;
|
if (source == NULL) goto fail;
|
||||||
source->references ++;
|
source->references ++;
|
||||||
state->source = source;
|
state->source = source;
|
||||||
|
|
||||||
/* create replicant and bind its state */
|
/* create replicant and bind its state */
|
||||||
Widget replicant = source->symbols.create(parent, state);
|
Widget replicant = source->symbols.create(app, parent, state);
|
||||||
XtAddCallback (
|
XtAddCallback (
|
||||||
replicant, XmNdestroyCallback,
|
replicant, XmNdestroyCallback,
|
||||||
XmdReplicantHandleDestroy, state);
|
handleDestroy, state);
|
||||||
return replicant;
|
return replicant;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
XmdReplicantStateFree(state);
|
stateFree(state);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void XmdReplicantHandleDestroy (
|
static void handleDestroy (
|
||||||
Widget replicant,
|
Widget replicant,
|
||||||
XtPointer clientData,
|
XtPointer clientData,
|
||||||
XtPointer callData
|
XtPointer callData
|
||||||
) {
|
) {
|
||||||
(void)(replicant);
|
(void)(replicant);
|
||||||
(void)(callData);
|
(void)(callData);
|
||||||
XmdReplicantEnsure();
|
ensure();
|
||||||
|
|
||||||
XmdReplicantState *state = clientData;
|
XmdReplicantState *state = clientData;
|
||||||
if (state == NULL) return;
|
if (state == NULL) return;
|
||||||
|
|
||||||
state->source->references --;
|
state->source->references --;
|
||||||
if (state->source->references < 1) {
|
if (state->source->references < 1) {
|
||||||
XmdReplicantSourceClose (
|
sourceClose (
|
||||||
XmdStringMapSet(resident, state->sourceName, NULL));
|
XmdStringMapSet(resident, state->sourceName, NULL));
|
||||||
}
|
}
|
||||||
XmdReplicantStateFree(state);
|
stateFree(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
String XmdReplicantResolveName (ConstString rawName) {
|
String XmdReplicantResolveName (ConstString rawName) {
|
||||||
@ -114,7 +115,7 @@ String XmdReplicantResolveName (ConstString rawName) {
|
|||||||
XmdBufferPush(dirBuffer, &null);
|
XmdBufferPush(dirBuffer, &null);
|
||||||
String dir = XmdBufferBreak(dirBuffer);
|
String dir = XmdBufferBreak(dirBuffer);
|
||||||
dirBuffer = NULL;
|
dirBuffer = NULL;
|
||||||
file = XmdReplicantScanDir(dir, name);
|
file = scanDir(dir, name);
|
||||||
XtFree(dir);
|
XtFree(dir);
|
||||||
} else {
|
} else {
|
||||||
XmdBufferPush(dirBuffer, &ch);
|
XmdBufferPush(dirBuffer, &ch);
|
||||||
@ -135,7 +136,7 @@ void XmdReplicantStateStore (
|
|||||||
) {
|
) {
|
||||||
String old = XmdStringMapSet(state->map, name, XtNewString(value));
|
String old = XmdStringMapSet(state->map, name, XtNewString(value));
|
||||||
XtFree(old);
|
XtFree(old);
|
||||||
XmdReplicantStateSave(state);
|
stateSave(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void writeEscapedMapString (FILE *file, ConstString string) {
|
static void writeEscapedMapString (FILE *file, ConstString string) {
|
||||||
@ -180,7 +181,7 @@ static Bool writeMapValue (
|
|||||||
return True;
|
return True;
|
||||||
}
|
}
|
||||||
|
|
||||||
static XmdError XmdReplicantStateSave (XmdReplicantState *state) {
|
static XmdError stateSave (XmdReplicantState *state) {
|
||||||
FILE *file = fopen(state->file, "w");
|
FILE *file = fopen(state->file, "w");
|
||||||
if (file == NULL) return XmdErrorCantOpenFile;
|
if (file == NULL) return XmdErrorCantOpenFile;
|
||||||
fprintf(file, "[%s]\n", state->sourceName);
|
fprintf(file, "[%s]\n", state->sourceName);
|
||||||
@ -217,7 +218,7 @@ static String readEscapedMapString (FILE *file, char delimiter) {
|
|||||||
return XmdBufferBreak(string);
|
return XmdBufferBreak(string);
|
||||||
}
|
}
|
||||||
|
|
||||||
static XmdError XmdReplicantStateLoad (XmdReplicantState *state) {
|
static XmdError stateLoad (XmdReplicantState *state) {
|
||||||
if (state->sourceName != NULL) XtFree(state->sourceName);
|
if (state->sourceName != NULL) XtFree(state->sourceName);
|
||||||
state->sourceName = NULL;
|
state->sourceName = NULL;
|
||||||
|
|
||||||
@ -256,7 +257,7 @@ static XmdError XmdReplicantStateLoad (XmdReplicantState *state) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static XmdReplicantState *XmdReplicantStateNew () {
|
static XmdReplicantState *stateNew () {
|
||||||
XmdReplicantState *state = XtNew(XmdReplicantState);
|
XmdReplicantState *state = XtNew(XmdReplicantState);
|
||||||
if (state == NULL) return NULL;
|
if (state == NULL) return NULL;
|
||||||
|
|
||||||
@ -266,7 +267,7 @@ static XmdReplicantState *XmdReplicantStateNew () {
|
|||||||
|
|
||||||
return state;
|
return state;
|
||||||
fail:
|
fail:
|
||||||
XmdReplicantStateFree(state);
|
stateFree(state);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -282,7 +283,7 @@ static Bool freeMapValue (
|
|||||||
return True;
|
return True;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void XmdReplicantStateFree (XmdReplicantState *state) {
|
static void stateFree (XmdReplicantState *state) {
|
||||||
if (state == NULL) return;
|
if (state == NULL) return;
|
||||||
XtFree(state->file);
|
XtFree(state->file);
|
||||||
XtFree(state->sourceName);
|
XtFree(state->sourceName);
|
||||||
@ -291,11 +292,11 @@ static void XmdReplicantStateFree (XmdReplicantState *state) {
|
|||||||
XtFree((char *)(state));
|
XtFree((char *)(state));
|
||||||
}
|
}
|
||||||
|
|
||||||
static XmdReplicantSource *XmdReplicantSourceOpen (ConstString name) {
|
static replicantSource *sourceOpen (ConstString name) {
|
||||||
/* allocate */
|
/* allocate */
|
||||||
XmdReplicantSource *source = XtNew(XmdReplicantSource);
|
replicantSource *source = XtNew(replicantSource);
|
||||||
if (source == NULL) goto fail;
|
if (source == NULL) goto fail;
|
||||||
memset(source, 0, sizeof(XmdReplicantSource));
|
memset(source, 0, sizeof(replicantSource));
|
||||||
|
|
||||||
/* open library */
|
/* open library */
|
||||||
String path = XmdReplicantResolveName(name);
|
String path = XmdReplicantResolveName(name);
|
||||||
@ -316,13 +317,11 @@ static XmdReplicantSource *XmdReplicantSourceOpen (ConstString name) {
|
|||||||
source->symbols.construct = (XmdReplicantFnConstruct) (
|
source->symbols.construct = (XmdReplicantFnConstruct) (
|
||||||
dlsym(source->handle, symbolName));
|
dlsym(source->handle, symbolName));
|
||||||
XtFree(symbolName);
|
XtFree(symbolName);
|
||||||
if (source->symbols.construct == NULL) goto fail;
|
|
||||||
|
|
||||||
XtAsprintf(&symbolName, "%s_XmdReplicantDestruct", name);
|
XtAsprintf(&symbolName, "%s_XmdReplicantDestruct", name);
|
||||||
source->symbols.destruct = (XmdReplicantFnDestruct) (
|
source->symbols.destruct = (XmdReplicantFnDestruct) (
|
||||||
dlsym(source->handle, symbolName));
|
dlsym(source->handle, symbolName));
|
||||||
XtFree(symbolName);
|
XtFree(symbolName);
|
||||||
if (source->symbols.destruct == NULL) goto fail;
|
|
||||||
|
|
||||||
XtAsprintf(&symbolName, "%s_XmdReplicantCreate", name);
|
XtAsprintf(&symbolName, "%s_XmdReplicantCreate", name);
|
||||||
source->symbols.create = (XmdReplicantFnCreate) (
|
source->symbols.create = (XmdReplicantFnCreate) (
|
||||||
@ -333,31 +332,33 @@ static XmdReplicantSource *XmdReplicantSourceOpen (ConstString name) {
|
|||||||
/* check if the version matches */
|
/* check if the version matches */
|
||||||
if (source->symbols.version() != XmdREPLICANT_VERSION) goto fail;
|
if (source->symbols.version() != XmdREPLICANT_VERSION) goto fail;
|
||||||
|
|
||||||
|
if (source->symbols.construct != NULL) source->symbols.construct();
|
||||||
return source;
|
return source;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
XmdReplicantSourceClose(source);
|
sourceClose(source);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void XmdReplicantSourceClose (XmdReplicantSource *source) {
|
static void sourceClose (replicantSource *source) {
|
||||||
if (source == NULL) return;
|
if (source == NULL) return;
|
||||||
|
if (source->symbols.destruct != NULL) source->symbols.destruct();
|
||||||
if (source->handle != NULL) dlclose(source->handle);
|
if (source->handle != NULL) dlclose(source->handle);
|
||||||
XtFree((char *)(source));
|
XtFree((char *)(source));
|
||||||
}
|
}
|
||||||
|
|
||||||
static XmdReplicantSource *XmdReplicantSourceGet (ConstString name) {
|
static replicantSource *sourceGet (ConstString name) {
|
||||||
XmdReplicantEnsure();
|
ensure();
|
||||||
|
|
||||||
/* check to see if it has already been loaded */
|
/* check to see if it has already been loaded */
|
||||||
XmdReplicantSource *source = XmdStringMapGet(resident, name);
|
replicantSource *source = XmdStringMapGet(resident, name);
|
||||||
if (source != NULL) return source;
|
if (source != NULL) return source;
|
||||||
|
|
||||||
/* open the 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);
|
DIR *dir = opendir(path);
|
||||||
if (dir == NULL) return NULL;
|
if (dir == NULL) return NULL;
|
||||||
|
|
||||||
@ -375,7 +376,7 @@ static String XmdReplicantScanDir (ConstString path, ConstString name) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void XmdReplicantEnsure () {
|
static void ensure () {
|
||||||
if (resident == NULL) {
|
if (resident == NULL) {
|
||||||
resident = XmdStringMapNew();
|
resident = XmdStringMapNew();
|
||||||
}
|
}
|
||||||
|
@ -47,7 +47,11 @@ void handleDestroyFreePixmap (
|
|||||||
XFreePixmap(XtDisplay(replicant), (Pixmap)(clientData));
|
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");
|
String iconName = XmdReplicantStateQuery(state, "Icon");
|
||||||
Pixmap icon;
|
Pixmap icon;
|
||||||
#define iconCase(name) if (strcmp(#name, iconName) == 0) {\
|
#define iconCase(name) if (strcmp(#name, iconName) == 0) {\
|
||||||
@ -61,6 +65,7 @@ Widget Launcher_XmdReplicantCreate (Widget parent, XmdReplicantState *state) {
|
|||||||
iconCase(WebBrowser)
|
iconCase(WebBrowser)
|
||||||
iconCase(Music)
|
iconCase(Music)
|
||||||
icon = XmdLoadBitmapIcon(parent, unknown);
|
icon = XmdLoadBitmapIcon(parent, unknown);
|
||||||
|
#undef iconCase
|
||||||
|
|
||||||
XtFree(iconName);
|
XtFree(iconName);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user