First replicant yay
This commit is contained in:
parent
55dfca6341
commit
a6fa746ef3
10
libXmd/include/Xmd/Dir.h
Normal file
10
libXmd/include/Xmd/Dir.h
Normal file
|
@ -0,0 +1,10 @@
|
|||
#ifndef _XmdDir_h
|
||||
#define _XmdDir_h
|
||||
|
||||
#include <X11/Intrinsic.h>
|
||||
|
||||
/* XmdDirGetUser returns the location of the Xmd user directory, which is
|
||||
located at $HOME/.Xmd */
|
||||
String XmdDirGetUser ();
|
||||
|
||||
#endif
|
12
libXmd/include/Xmd/Error.h
Normal file
12
libXmd/include/Xmd/Error.h
Normal file
|
@ -0,0 +1,12 @@
|
|||
#ifndef _XmdError_h
|
||||
#define _XmdError_h
|
||||
|
||||
typedef enum {
|
||||
XmdErrorNone,
|
||||
XmdErrorOutOfMemory,
|
||||
XmdErrorFileNotFound,
|
||||
XmdErrorCantOpenFile,
|
||||
XmdErrorBadSyntax
|
||||
} XmdError;
|
||||
|
||||
#endif
|
|
@ -11,8 +11,11 @@
|
|||
/* XmdReplicantState contains state information for a replicant instance. */
|
||||
typedef struct _XmdReplicantState XmdReplicantState;
|
||||
|
||||
typedef int (*XmdReplicantVersion) ();
|
||||
typedef Widget (*XmdReplicantCreate) (Widget parent, XmdReplicantState *state);
|
||||
typedef int (*XmdReplicantFnVersion) ();
|
||||
typedef void (*XmdReplicantFnConstruct) ();
|
||||
typedef void (*XmdReplicantFnDestruct) ();
|
||||
typedef Widget (*XmdReplicantFnCreate) (
|
||||
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.
|
||||
|
@ -37,6 +40,12 @@ typedef Widget (*XmdReplicantCreate) (Widget parent, XmdReplicantState *state);
|
|||
the API version that the replicant was compiled with, and applications with a
|
||||
different API version will refuse to load it.
|
||||
|
||||
void NAME_XmdReplicantConstruct ();
|
||||
Construct is called when the shared object is loaded.
|
||||
|
||||
void NAME_XmdReplicantDestruct ();
|
||||
Descruct is called before the shared object is unloaded.
|
||||
|
||||
Widget NAME_XmdReplicantCreate (Widget parent, XmdReplicantState *state);
|
||||
Create instantiates a new widget representing the replicant given by state.
|
||||
*/
|
||||
|
|
8
libXmd/src/Dir.c
Normal file
8
libXmd/src/Dir.c
Normal file
|
@ -0,0 +1,8 @@
|
|||
#include <Xmd/Dir.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
String XmdDirGetUser () {
|
||||
String dir = NULL;
|
||||
XtAsprintf(&dir, "%s/.Xmd", getenv("HOME"));
|
||||
return dir;
|
||||
}
|
|
@ -2,6 +2,7 @@
|
|||
#include <Xmd/StringMap.h>
|
||||
#include <Xmd/Map.h>
|
||||
#include <Xmd/Buffer.h>
|
||||
#include <Xmd/Error.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
@ -15,8 +16,10 @@ typedef struct {
|
|||
int references;
|
||||
|
||||
struct {
|
||||
XmdReplicantVersion version;
|
||||
XmdReplicantCreate create;
|
||||
XmdReplicantFnVersion version;
|
||||
XmdReplicantFnConstruct construct;
|
||||
XmdReplicantFnDestruct destruct;
|
||||
XmdReplicantFnCreate create;
|
||||
} symbols;
|
||||
} XmdReplicantSource;
|
||||
|
||||
|
@ -31,8 +34,8 @@ static void XmdReplicantHandleDestroy (
|
|||
Widget replicant,
|
||||
XtPointer clientData,
|
||||
XtPointer callData);
|
||||
static void XmdReplicantStateSave (XmdReplicantState *state);
|
||||
static void XmdReplicantStateLoad (XmdReplicantState *state);
|
||||
static XmdError XmdReplicantStateSave (XmdReplicantState *state);
|
||||
static XmdError XmdReplicantStateLoad (XmdReplicantState *state);
|
||||
static XmdReplicantState *XmdReplicantStateNew ();
|
||||
static void XmdReplicantStateFree (XmdReplicantState *state);
|
||||
static XmdReplicantSource *XmdReplicantSourceOpen (ConstString name);
|
||||
|
@ -41,6 +44,7 @@ static XmdReplicantSource *XmdReplicantSourceGet (ConstString name);
|
|||
static String XmdReplicantScanDir (
|
||||
ConstString path,
|
||||
ConstString name);
|
||||
static void XmdReplicantEnsure ();
|
||||
|
||||
static const String defaultReplicantPath =
|
||||
"/usr/lib/Xmd/replicants:"
|
||||
|
@ -80,6 +84,7 @@ static void XmdReplicantHandleDestroy (
|
|||
) {
|
||||
(void)(replicant);
|
||||
(void)(callData);
|
||||
XmdReplicantEnsure();
|
||||
|
||||
XmdReplicantState *state = clientData;
|
||||
if (state == NULL) return;
|
||||
|
@ -104,12 +109,15 @@ String XmdReplicantResolveName (ConstString rawName) {
|
|||
char ch = *list;
|
||||
if (dirBuffer == NULL) dirBuffer = XmdBufferNew(char);
|
||||
|
||||
XmdBufferPush(dirBuffer, &ch);
|
||||
if (ch == ':' || ch == 0) {
|
||||
char null = 0;
|
||||
XmdBufferPush(dirBuffer, &null);
|
||||
String dir = XmdBufferBreak(dirBuffer);
|
||||
dirBuffer = NULL;
|
||||
file = XmdReplicantScanDir(dir, name);
|
||||
XtFree(dir);
|
||||
} else {
|
||||
XmdBufferPush(dirBuffer, &ch);
|
||||
}
|
||||
list ++;
|
||||
}
|
||||
|
@ -172,12 +180,13 @@ static Bool writeMapValue (
|
|||
return True;
|
||||
}
|
||||
|
||||
static void XmdReplicantStateSave (XmdReplicantState *state) {
|
||||
static XmdError XmdReplicantStateSave (XmdReplicantState *state) {
|
||||
FILE *file = fopen(state->file, "w");
|
||||
if (file == NULL) return;
|
||||
if (file == NULL) return XmdErrorCantOpenFile;
|
||||
fprintf(file, "[%s]\n", state->sourceName);
|
||||
XmdStringMapIterate(state->map, writeMapValue, file);
|
||||
fclose(file);
|
||||
return XmdErrorNone;
|
||||
}
|
||||
|
||||
static String readEscapedMapString (FILE *file, char delimiter) {
|
||||
|
@ -208,23 +217,42 @@ static String readEscapedMapString (FILE *file, char delimiter) {
|
|||
return XmdBufferBreak(string);
|
||||
}
|
||||
|
||||
static void XmdReplicantStateLoad (XmdReplicantState *state) {
|
||||
FILE *file = fopen(state->file, "w");
|
||||
if (file == NULL) return;
|
||||
static XmdError XmdReplicantStateLoad (XmdReplicantState *state) {
|
||||
if (state->sourceName != NULL) XtFree(state->sourceName);
|
||||
state->sourceName = NULL;
|
||||
|
||||
int ch = 0;
|
||||
while (isspace((ch == fgetc(file))));
|
||||
if (ch != '[') return;
|
||||
FILE *file = fopen(state->file, "r");
|
||||
if (file == NULL) {
|
||||
return XmdErrorFileNotFound;
|
||||
};
|
||||
|
||||
int ch = ' ';
|
||||
while (isspace(ch)) ch = fgetc(file);
|
||||
if (ch != '[') {
|
||||
fclose(file);
|
||||
return XmdErrorBadSyntax;
|
||||
}
|
||||
state->sourceName = readEscapedMapString(file, ']');
|
||||
ch = fgetc(file);
|
||||
if (ch != '\n') return;
|
||||
if (ch != '\n') {
|
||||
fclose(file);
|
||||
return XmdErrorBadSyntax;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
String key = readEscapedMapString(file, '=');
|
||||
String value = readEscapedMapString(file, '\n');
|
||||
XmdStringMapSet(state->map, key, value);
|
||||
XtFree(key);
|
||||
if (value == NULL) break;
|
||||
if (value == NULL) {
|
||||
if (key == NULL) {
|
||||
fclose(file);
|
||||
return XmdErrorNone;
|
||||
} else {
|
||||
fclose(file);
|
||||
return XmdErrorBadSyntax;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -277,17 +305,29 @@ static XmdReplicantSource *XmdReplicantSourceOpen (ConstString name) {
|
|||
if (source->handle == NULL) goto fail;
|
||||
|
||||
/* find symbols */
|
||||
String versionName = NULL;
|
||||
XtAsprintf(&versionName, "%s_XmdReplicantVersion", name);
|
||||
source->symbols.version = (XmdReplicantVersion) (
|
||||
dlsym(source->handle, versionName));
|
||||
XtFree(versionName);
|
||||
String symbolName = NULL;
|
||||
XtAsprintf(&symbolName, "%s_XmdReplicantVersion", name);
|
||||
source->symbols.version = (XmdReplicantFnVersion) (
|
||||
dlsym(source->handle, symbolName));
|
||||
XtFree(symbolName);
|
||||
if (source->symbols.version == NULL) goto fail;
|
||||
String createName = NULL;
|
||||
XtAsprintf(&createName, "%s_XmdReplicantCreate", name);
|
||||
source->symbols.create = (XmdReplicantCreate) (
|
||||
dlsym(source->handle, createName));
|
||||
XtFree(createName);
|
||||
|
||||
XtAsprintf(&symbolName, "%s_XmdReplicantConstruct", 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) (
|
||||
dlsym(source->handle, symbolName));
|
||||
XtFree(symbolName);
|
||||
if (source->symbols.create == NULL) goto fail;
|
||||
|
||||
/* check if the version matches */
|
||||
|
@ -307,6 +347,8 @@ static void XmdReplicantSourceClose (XmdReplicantSource *source) {
|
|||
}
|
||||
|
||||
static XmdReplicantSource *XmdReplicantSourceGet (ConstString name) {
|
||||
XmdReplicantEnsure();
|
||||
|
||||
/* check to see if it has already been loaded */
|
||||
XmdReplicantSource *source = XmdStringMapGet(resident, name);
|
||||
if (source != NULL) return source;
|
||||
|
@ -316,7 +358,9 @@ static XmdReplicantSource *XmdReplicantSourceGet (ConstString name) {
|
|||
}
|
||||
|
||||
static String XmdReplicantScanDir (ConstString path, ConstString name) {
|
||||
DIR *dir = opendir(path);
|
||||
DIR *dir = opendir(path);
|
||||
if (dir == NULL) return NULL;
|
||||
|
||||
String result = NULL;
|
||||
while (1) {
|
||||
struct dirent *entry = readdir(dir);
|
||||
|
@ -330,3 +374,9 @@ static String XmdReplicantScanDir (ConstString path, ConstString name) {
|
|||
closedir(dir);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void XmdReplicantEnsure () {
|
||||
if (resident == NULL) {
|
||||
resident = XmdStringMapNew();
|
||||
}
|
||||
}
|
||||
|
|
2
replicants/Launcher/build.sh
Executable file
2
replicants/Launcher/build.sh
Executable file
|
@ -0,0 +1,2 @@
|
|||
#!/bin/sh
|
||||
../../scripts/buildreplicant.sh Launcher "$@"
|
27
replicants/Launcher/src/icons/unknown.xbm
Normal file
27
replicants/Launcher/src/icons/unknown.xbm
Normal file
|
@ -0,0 +1,27 @@
|
|||
#define unknown_width 48
|
||||
#define unknown_height 48
|
||||
static unsigned char unknown_bits[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7f, 0x00, 0x00,
|
||||
0x00, 0x00, 0xf0, 0xff, 0x01, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x01, 0x00,
|
||||
0x00, 0x00, 0xf8, 0xff, 0x03, 0x00, 0x00, 0x00, 0xf8, 0xf8, 0x03, 0x00,
|
||||
0x00, 0x00, 0x30, 0xf0, 0x03, 0x00, 0x00, 0x00, 0x10, 0xe0, 0x03, 0x00,
|
||||
0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00,
|
||||
0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x03, 0x00,
|
||||
0x00, 0x00, 0x00, 0xf0, 0x03, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x01, 0x00,
|
||||
0x00, 0x00, 0x00, 0xf8, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00,
|
||||
0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x80, 0x1f, 0x00, 0x00,
|
||||
0x00, 0x00, 0xc0, 0x0f, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00,
|
||||
0x00, 0x00, 0xe0, 0x03, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x01, 0x00, 0x00,
|
||||
0x00, 0x00, 0xf0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00,
|
||||
0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00,
|
||||
0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x80, 0x1f, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
80
replicants/Launcher/src/main.c
Normal file
80
replicants/Launcher/src/main.c
Normal file
|
@ -0,0 +1,80 @@
|
|||
#include <Xm/Xm.h>
|
||||
#include <Xm/PushB.h>
|
||||
#include <Xmd/Icon.h>
|
||||
#include <Xmd/Replicant.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "icons/appCalculator.xbm"
|
||||
#include "icons/appEditor.xbm"
|
||||
#include "icons/appFiles.xbm"
|
||||
#include "icons/appMail.xbm"
|
||||
#include "icons/appMusic.xbm"
|
||||
#include "icons/appTerminal.xbm"
|
||||
#include "icons/appWebBrowser.xbm"
|
||||
#include "icons/unknown.xbm"
|
||||
|
||||
void activateLauncher (Widget button, XtPointer clientData, XtPointer callData) {
|
||||
(void)(button);
|
||||
(void)(callData);
|
||||
XmdReplicantState *state = (XmdReplicantState *)(clientData);
|
||||
|
||||
String command = XmdReplicantStateQuery(state, "Exec");
|
||||
String fullCommand = NULL;
|
||||
XtAsprintf(&fullCommand, "%s &", command);
|
||||
XtFree(command);
|
||||
system(fullCommand);
|
||||
XtFree(fullCommand);
|
||||
}
|
||||
|
||||
int Launcher_XmdReplicantVersion () {
|
||||
return XmdREPLICANT_VERSION;
|
||||
}
|
||||
|
||||
void Launcher_XmdReplicantConstruct () {
|
||||
|
||||
}
|
||||
|
||||
void Launcher_XmdReplicantDestruct () {
|
||||
|
||||
}
|
||||
|
||||
void handleDestroyFreePixmap (
|
||||
Widget replicant,
|
||||
XtPointer clientData,
|
||||
XtPointer callData
|
||||
) {
|
||||
(void)(callData);
|
||||
XFreePixmap(XtDisplay(replicant), (Pixmap)(clientData));
|
||||
}
|
||||
|
||||
Widget Launcher_XmdReplicantCreate (Widget parent, XmdReplicantState *state) {
|
||||
String iconName = XmdReplicantStateQuery(state, "Icon");
|
||||
Pixmap icon;
|
||||
#define iconCase(name) if (strcmp(#name, iconName) == 0) {\
|
||||
icon = XmdLoadBitmapIcon(parent, app##name);\
|
||||
} else
|
||||
iconCase(Calculator)
|
||||
iconCase(Editor)
|
||||
iconCase(Files)
|
||||
iconCase(Mail)
|
||||
iconCase(Terminal)
|
||||
iconCase(WebBrowser)
|
||||
iconCase(Music)
|
||||
icon = XmdLoadBitmapIcon(parent, unknown);
|
||||
|
||||
XtFree(iconName);
|
||||
|
||||
Widget button = XtVaCreateManagedWidget (
|
||||
"launcher", xmPushButtonWidgetClass, parent,
|
||||
XmNleftAttachment, XmATTACH_FORM,
|
||||
XmNlabelType, XmPIXMAP,
|
||||
XmNlabelPixmap, icon,
|
||||
NULL);
|
||||
XtAddCallback (
|
||||
button, XmNactivateCallback,
|
||||
activateLauncher, (XtPointer)(state));
|
||||
XtAddCallback (
|
||||
button, XmNdestroyCallback,
|
||||
handleDestroyFreePixmap, (XtPointer)(icon));
|
||||
return button;
|
||||
}
|
34
scripts/buildreplicant.sh
Executable file
34
scripts/buildreplicant.sh
Executable file
|
@ -0,0 +1,34 @@
|
|||
#!/bin/sh
|
||||
|
||||
. `dirname $0`/flags.sh
|
||||
|
||||
function build() {
|
||||
if
|
||||
mkdir -p lib && \
|
||||
cc src/*.c -o "lib/$1.so" -shared $CFLAGS
|
||||
then
|
||||
echo ".// ok"
|
||||
return 0
|
||||
else
|
||||
echo "XXX FAIL!"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
function clean() {
|
||||
rm -f bin/*
|
||||
}
|
||||
|
||||
case "$2" in
|
||||
install)
|
||||
clean; build "$1"
|
||||
mkdir -p "$PREFIX/lib/Xmd/replicants"
|
||||
cp "lib/$1.so" "$PREFIX/lib/Xmd/replicants"
|
||||
clean
|
||||
;;
|
||||
clean)
|
||||
clean
|
||||
;;
|
||||
*)
|
||||
build "$1"
|
||||
esac
|
|
@ -2,4 +2,4 @@
|
|||
|
||||
CFLAGS="-std=c99 -Wall -Wextra -Werror -fPIC"
|
||||
PREFIX="/usr/local"
|
||||
APP_LIBS="-lXmd -lXm -lXt -lX11"
|
||||
APP_LIBS="-lXmd -lXm -lXt -lX11 -ldl"
|
||||
|
|
|
@ -2,32 +2,20 @@
|
|||
#include <Xm/Xm.h>
|
||||
#include <Xm/RowColumn.h>
|
||||
#include <Xm/PushB.h>
|
||||
#include <Xmd/Dir.h>
|
||||
#include <Xmd/Icon.h>
|
||||
#include <Xmd/Replicant.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "icons/appCalculator.xbm"
|
||||
#include "icons/appEditor.xbm"
|
||||
#include "icons/appFiles.xbm"
|
||||
#include "icons/appMail.xbm"
|
||||
#include "icons/appTerminal.xbm"
|
||||
#include "icons/appWebBrowser.xbm"
|
||||
#include "icons/appMusic.xbm"
|
||||
#include <dirent.h>
|
||||
|
||||
#include "icons/icon.xbm"
|
||||
|
||||
typedef struct {
|
||||
Pixmap icon;
|
||||
const char * command;
|
||||
} Launcher;
|
||||
|
||||
void createAllLaunchers (Widget);
|
||||
Widget createLauncher (Widget, Launcher);
|
||||
void activateLauncher (Widget, XtPointer, XtPointer);
|
||||
|
||||
XtAppContext application;
|
||||
|
||||
static void loadReplicants (Widget parent);
|
||||
|
||||
int main (int argc, char *argv[]) {
|
||||
Widget window = XtVaAppInitialize (
|
||||
&application, "Panel",
|
||||
|
@ -47,41 +35,42 @@ int main (int argc, char *argv[]) {
|
|||
"layout", xmRowColumnWidgetClass, window,
|
||||
XmNorientation, XmHORIZONTAL,
|
||||
NULL);
|
||||
createAllLaunchers(layout);
|
||||
loadReplicants(layout);
|
||||
|
||||
XtManageChild(layout);
|
||||
XtRealizeWidget(window);
|
||||
XtAppMainLoop(application);
|
||||
}
|
||||
|
||||
void createAllLaunchers (Widget parent) {
|
||||
#define add(name, cmd) createLauncher(parent, (Launcher){\
|
||||
.icon = XmdLoadBitmapIcon(parent, app##name),\
|
||||
.command = cmd " &"\
|
||||
} );
|
||||
add(Calculator, "xcalc");
|
||||
add(Editor, "nedit");
|
||||
add(Files, "caja");
|
||||
add(Mail, "nedit");
|
||||
add(Terminal, "uxterm");
|
||||
add(WebBrowser, "firefox");
|
||||
add(Music, "ymuse");
|
||||
#undef add
|
||||
}
|
||||
static void loadReplicants (Widget parent) {
|
||||
String userDir = XmdDirGetUser();
|
||||
String replicantsDir = NULL;
|
||||
XtAsprintf(&replicantsDir, "%s/panel", userDir);
|
||||
XtFree(userDir);
|
||||
|
||||
Widget createLauncher (Widget parent, Launcher launcher) {
|
||||
Widget button = XtVaCreateManagedWidget (
|
||||
"launcher", xmPushButtonWidgetClass, parent,
|
||||
XmNleftAttachment, XmATTACH_FORM,
|
||||
XmNlabelType, XmPIXMAP,
|
||||
XmNlabelPixmap, launcher.icon,
|
||||
NULL);
|
||||
XtAddCallback(button, XmNactivateCallback, activateLauncher, (XtPointer)(launcher.command));
|
||||
return button;
|
||||
}
|
||||
struct dirent **entries = NULL;
|
||||
int entriesCount = scandir(replicantsDir, &entries, NULL, alphasort);
|
||||
if (entriesCount < 0) {
|
||||
XtFree(replicantsDir);
|
||||
/* TODO error message */
|
||||
return;
|
||||
}
|
||||
|
||||
void activateLauncher (Widget button, XtPointer clientData, XtPointer callData) {
|
||||
(void)(button);
|
||||
(void)(callData);
|
||||
system((char *)(clientData));
|
||||
for (int index = 0; index < entriesCount; index ++) {
|
||||
struct dirent *entry = entries[index];
|
||||
String point = NULL;
|
||||
if ((point = strrchr(entry->d_name,'.')) != NULL) {
|
||||
if (strcmp(point, ".replicant") == 0) {
|
||||
String fullName = NULL;
|
||||
XtAsprintf (
|
||||
&fullName, "%s/%s",
|
||||
replicantsDir, entry->d_name);
|
||||
XmdReplicantOpen(parent, fullName);
|
||||
XtFree(fullName);
|
||||
}
|
||||
}
|
||||
XtFree((char *)(entry));
|
||||
}
|
||||
XtFree((char *)(entries));
|
||||
XtFree(replicantsDir);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user