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   (*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
 | 
			
		||||
 | 
			
		||||
@ -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();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -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);
 | 
			
		||||
	
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user