XmPackage stub
This commit is contained in:
parent
d34e7fdc88
commit
b3b86808ea
2
xmpackage/build.sh
Executable file
2
xmpackage/build.sh
Executable file
@ -0,0 +1,2 @@
|
||||
#!/bin/sh
|
||||
../scripts/buildapp.sh xmpackage "$@"
|
27
xmpackage/src/icons/icon.xbm
Normal file
27
xmpackage/src/icons/icon.xbm
Normal file
@ -0,0 +1,27 @@
|
||||
#define icon_width 48
|
||||
#define icon_height 48
|
||||
static unsigned char icon_bits[] = {
|
||||
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, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00,
|
||||
0x00, 0x00, 0x78, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x78, 0x00, 0x00,
|
||||
0x00, 0x80, 0x07, 0xe0, 0x03, 0x00, 0x00, 0xe0, 0x01, 0x80, 0x0e, 0x00,
|
||||
0x00, 0x78, 0x00, 0x40, 0x38, 0x00, 0x00, 0x1e, 0x80, 0x31, 0x60, 0x00,
|
||||
0x80, 0x07, 0x40, 0x0e, 0x80, 0x01, 0xc0, 0x01, 0x20, 0x04, 0x00, 0x03,
|
||||
0xe0, 0x00, 0xc0, 0x08, 0x00, 0x07, 0x60, 0x03, 0x30, 0x07, 0x80, 0x06,
|
||||
0x60, 0x0c, 0x0c, 0x00, 0x20, 0x06, 0x60, 0x30, 0x03, 0x00, 0x08, 0x06,
|
||||
0x60, 0xc0, 0x06, 0x00, 0x02, 0x06, 0x60, 0x00, 0x0b, 0x80, 0x60, 0x06,
|
||||
0x60, 0x00, 0x3c, 0x20, 0x58, 0x06, 0x60, 0x00, 0xf0, 0x08, 0x46, 0x06,
|
||||
0x60, 0x00, 0xc0, 0x83, 0x41, 0x06, 0x60, 0x00, 0x00, 0x81, 0x60, 0x06,
|
||||
0x60, 0x00, 0x00, 0x80, 0x18, 0x06, 0x60, 0x00, 0x00, 0x81, 0x06, 0x06,
|
||||
0x60, 0x00, 0x00, 0x80, 0x01, 0x06, 0x60, 0x00, 0x00, 0x01, 0x00, 0x06,
|
||||
0x60, 0x00, 0x00, 0x00, 0x00, 0x06, 0x60, 0x00, 0x00, 0x01, 0x00, 0x06,
|
||||
0x60, 0x00, 0x00, 0x00, 0x00, 0x06, 0x60, 0x00, 0x00, 0x01, 0x02, 0x06,
|
||||
0x60, 0x00, 0x00, 0x80, 0x02, 0x06, 0x60, 0x00, 0x00, 0xa1, 0x02, 0x06,
|
||||
0xc0, 0x01, 0x00, 0xa8, 0x82, 0x03, 0x80, 0x07, 0x00, 0xa9, 0xe0, 0x01,
|
||||
0x00, 0x1e, 0x00, 0x28, 0x78, 0x00, 0x00, 0x78, 0x00, 0x09, 0x1e, 0x00,
|
||||
0x00, 0xe0, 0x01, 0x80, 0x07, 0x00, 0x00, 0x80, 0x07, 0xe1, 0x01, 0x00,
|
||||
0x00, 0x00, 0x1e, 0x78, 0x00, 0x00, 0x00, 0x00, 0x78, 0x1f, 0x00, 0x00,
|
||||
0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 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 };
|
640
xmpackage/src/main.c
Normal file
640
xmpackage/src/main.c
Normal file
@ -0,0 +1,640 @@
|
||||
#define _XOPEN_SOURCE
|
||||
|
||||
#include <Xm/Xm.h>
|
||||
#include <Xm/MainW.h>
|
||||
#include <Xm/RowColumn.h>
|
||||
#include <Xm/PushB.h>
|
||||
#include <Xm/Text.h>
|
||||
#include <Xm/Form.h>
|
||||
#include <Xm/PanedW.h>
|
||||
#include <Xm/TabStack.h>
|
||||
#include <Xm/List.h>
|
||||
#include <Xm/Frame.h>
|
||||
#include <Xm/TextF.h>
|
||||
#include <Xm/Separator.h>
|
||||
#include <Xm/ScrolledW.h>
|
||||
#include <Xm/LabelG.h>
|
||||
|
||||
#include <Xmd/Icon.h>
|
||||
#include <Xmd/Buffer.h>
|
||||
#include <Xmd/Exec.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include "icons/icon.xbm"
|
||||
|
||||
Widget createLabeledTextForm (Widget, String, String, XmString);
|
||||
Widget createScrolledInfoText (Widget, String);
|
||||
void selectPackage (String);
|
||||
void updatePackageList (void);
|
||||
void readPackageList (FILE *);
|
||||
void handleListModeSelectionChange (Widget, XtPointer, XtPointer);
|
||||
void handlePackageSelectionChange (Widget, XtPointer, XtPointer);
|
||||
void handleSearchQueryActivate (Widget, XtPointer, XtPointer);
|
||||
String parsePackageName (String);
|
||||
void parseInfoOutput (FILE *, String *, String *, String *, String *);
|
||||
|
||||
static XtAppContext application;
|
||||
static Pixmap iconPixmap;
|
||||
|
||||
static struct {
|
||||
Widget name;
|
||||
Widget description;
|
||||
Widget dependencies;
|
||||
Widget provides;
|
||||
Widget contents;
|
||||
String selected;
|
||||
} packageInfo = { 0 };
|
||||
|
||||
static struct {
|
||||
Widget query;
|
||||
Widget list;
|
||||
Widget modeMenu;
|
||||
enum {
|
||||
viewModeWorld,
|
||||
viewModeInstalled,
|
||||
viewModeUpgradable,
|
||||
viewModeOrphaned,
|
||||
viewModeSearch
|
||||
} viewMode;
|
||||
XmString viewModeStrings[4];
|
||||
} packageList = { 0 };
|
||||
|
||||
int main (int argc, char *argv[]) {
|
||||
Widget topLevel = XtVaAppInitialize (
|
||||
&application, "PackageManager",
|
||||
NULL, 0,
|
||||
&argc, argv,
|
||||
NULL,
|
||||
XmNtitle, "Package Manager",
|
||||
XmNiconName, "Package Manager",
|
||||
NULL);
|
||||
iconPixmap = XmdLoadBitmapIcon(topLevel, icon);
|
||||
XtVaSetValues (
|
||||
topLevel,
|
||||
XmNiconPixmap, iconPixmap,
|
||||
NULL);
|
||||
Widget window = XtVaCreateManagedWidget (
|
||||
"window", xmMainWindowWidgetClass, topLevel,
|
||||
NULL);
|
||||
Widget pane = XtVaCreateWidget (
|
||||
"pane", xmPanedWindowWidgetClass, window,
|
||||
XmNorientation, XmHORIZONTAL,
|
||||
NULL);
|
||||
|
||||
/* menu bar */
|
||||
XmString fileString = XmStringCreateLocalized("File");
|
||||
XmString systemString = XmStringCreateLocalized("System");
|
||||
XmString helpString = XmStringCreateLocalized("Help");
|
||||
Widget menuBar = XmVaCreateSimpleMenuBar (
|
||||
window, "menuBar",
|
||||
XmVaCASCADEBUTTON, fileString, 'F',
|
||||
XmVaCASCADEBUTTON, systemString, 'S',
|
||||
XmVaCASCADEBUTTON, helpString, 'H',
|
||||
NULL);
|
||||
XmStringFree(fileString);
|
||||
XmStringFree(systemString);
|
||||
XmStringFree(helpString);
|
||||
XtManageChild(menuBar);
|
||||
|
||||
/* package list pane */
|
||||
Widget packageListPane = XtVaCreateWidget (
|
||||
"packageListPane", xmFormWidgetClass, pane,
|
||||
XmNhorizontalSpacing, 4,
|
||||
XmNverticalSpacing, 4,
|
||||
XmNmarginHeight, 2,
|
||||
XmNmarginWidth, 2,
|
||||
NULL);
|
||||
XmString packageSearchLabelString = XmStringCreateLocalized("Search:");
|
||||
packageList.query = createLabeledTextForm (
|
||||
packageListPane,
|
||||
"packageSearchLabel",
|
||||
"packageSearchText",
|
||||
packageSearchLabelString);
|
||||
XmStringFree(packageSearchLabelString);
|
||||
XtAddCallback (
|
||||
packageList.query,
|
||||
XmNactivateCallback, handleSearchQueryActivate,
|
||||
NULL);
|
||||
XtVaSetValues (
|
||||
XtParent(packageList.query),
|
||||
XmNrightAttachment, XmATTACH_FORM,
|
||||
XmNtopAttachment, XmATTACH_FORM,
|
||||
XmNleftAttachment, XmATTACH_FORM,
|
||||
NULL);
|
||||
|
||||
/* list mode selector */
|
||||
Widget listModeFrame = XtVaCreateWidget (
|
||||
"listModeFrame", xmFrameWidgetClass, packageListPane,
|
||||
XmNshadowType, XmSHADOW_IN,
|
||||
XmNshadowThickness, 1,
|
||||
XmNleftAttachment, XmATTACH_FORM,
|
||||
XmNrightAttachment, XmATTACH_FORM,
|
||||
XmNbottomAttachment, XmATTACH_FORM,
|
||||
NULL);
|
||||
Widget listModeRc = XtVaCreateWidget (
|
||||
"listModeRc", xmRowColumnWidgetClass, listModeFrame,
|
||||
XmNmarginWidth, 0,
|
||||
XmNmarginHeight, 0,
|
||||
NULL);
|
||||
XmString listModeString = XmStringCreateLocalized("List:");
|
||||
packageList.viewModeStrings[viewModeWorld] = XmStringCreateLocalized("World");
|
||||
packageList.viewModeStrings[viewModeInstalled] = XmStringCreateLocalized("Installed");
|
||||
packageList.viewModeStrings[viewModeUpgradable] = XmStringCreateLocalized("Upgradable");
|
||||
packageList.viewModeStrings[viewModeOrphaned] = XmStringCreateLocalized("Orphaned");
|
||||
packageList.viewModeStrings[viewModeSearch] = XmStringCreateLocalized("Search");
|
||||
packageList.modeMenu = XmVaCreateSimpleOptionMenu (
|
||||
listModeRc, "packageListMode",
|
||||
listModeString, 'L', 0, handleListModeSelectionChange,
|
||||
XmVaPUSHBUTTON, packageList.viewModeStrings[viewModeWorld], 'W', NULL, NULL,
|
||||
XmVaPUSHBUTTON, packageList.viewModeStrings[viewModeInstalled], 'I', NULL, NULL,
|
||||
XmVaPUSHBUTTON, packageList.viewModeStrings[viewModeUpgradable], 'U', NULL, NULL,
|
||||
XmVaPUSHBUTTON, packageList.viewModeStrings[viewModeOrphaned], 'O', NULL, NULL,
|
||||
XmVaPUSHBUTTON, packageList.viewModeStrings[viewModeSearch], 'S', NULL, NULL,
|
||||
XmNtearOffModel, XmTEAR_OFF_ENABLED,
|
||||
NULL);
|
||||
XmStringFree(listModeString);
|
||||
XtManageChild(packageList.modeMenu);
|
||||
XtManageChild(listModeFrame);
|
||||
XtManageChild(listModeRc);
|
||||
|
||||
/* packageList */
|
||||
packageList.list = XmCreateScrolledList(packageListPane, "packageList", NULL, 0);
|
||||
XtVaSetValues (
|
||||
XtParent(packageList.list),
|
||||
XmNtopAttachment, XmATTACH_WIDGET,
|
||||
XmNtopWidget, XtParent(packageList.query),
|
||||
XmNleftAttachment, XmATTACH_FORM,
|
||||
XmNrightAttachment, XmATTACH_FORM,
|
||||
XmNbottomAttachment, XmATTACH_WIDGET,
|
||||
XmNbottomWidget, listModeFrame,
|
||||
NULL);
|
||||
XtAddCallback (
|
||||
packageList.list,
|
||||
XmNbrowseSelectionCallback, handlePackageSelectionChange,
|
||||
NULL);
|
||||
XtManageChild(packageList.list);
|
||||
|
||||
/* package viewer */
|
||||
Widget descriptionPane = XtVaCreateWidget (
|
||||
"descriptionPane", xmFormWidgetClass, pane,
|
||||
XmNhorizontalSpacing, 4,
|
||||
XmNverticalSpacing, 4,
|
||||
XmNmarginHeight, 2,
|
||||
XmNmarginWidth, 2,
|
||||
NULL);
|
||||
|
||||
/* package actions */
|
||||
Widget packageActionsFrame = XtVaCreateWidget (
|
||||
"packageActionsFrame", xmFrameWidgetClass, descriptionPane,
|
||||
XmNshadowType, XmSHADOW_OUT,
|
||||
XmNleftAttachment, XmATTACH_FORM,
|
||||
XmNrightAttachment, XmATTACH_FORM,
|
||||
XmNbottomAttachment, XmATTACH_FORM,
|
||||
NULL);
|
||||
Widget packageActionsRc = XtVaCreateWidget (
|
||||
"packageActionsRc", xmRowColumnWidgetClass, packageActionsFrame,
|
||||
XmNorientation, XmHORIZONTAL,
|
||||
NULL);
|
||||
XmString packageAddString = XmStringCreateLocalized("Install");
|
||||
Widget packageAdd = XtVaCreateManagedWidget (
|
||||
"packageAdd", xmPushButtonWidgetClass, packageActionsRc,
|
||||
XmNlabelString, packageAddString,
|
||||
NULL);
|
||||
XmStringFree(packageAddString);
|
||||
XmString packageDeleteString = XmStringCreateLocalized("Remove");
|
||||
XtVaCreateManagedWidget (
|
||||
"packageDelete", xmPushButtonWidgetClass, packageActionsRc,
|
||||
XmNlabelString, packageDeleteString,
|
||||
NULL);
|
||||
XmStringFree(packageDeleteString);
|
||||
XmString packageUpgradeString = XmStringCreateLocalized("Upgrade");
|
||||
XtVaCreateManagedWidget (
|
||||
"packageUpgrade", xmPushButtonWidgetClass, packageActionsRc,
|
||||
XmNlabelString, packageUpgradeString,
|
||||
NULL);
|
||||
XmStringFree(packageUpgradeString);
|
||||
XmString packageFixString = XmStringCreateLocalized("Fix");
|
||||
XtVaCreateManagedWidget (
|
||||
"packageFix", xmPushButtonWidgetClass, packageActionsRc,
|
||||
XmNlabelString, packageFixString,
|
||||
NULL);
|
||||
XmStringFree(packageFixString);
|
||||
XtManageChild(packageActionsRc);
|
||||
XtManageChild(packageActionsFrame);
|
||||
|
||||
/* visually separate package description and actions */
|
||||
Widget descriptionSeparator = XtVaCreateManagedWidget (
|
||||
"descriptionSeparator", xmSeparatorWidgetClass, descriptionPane,
|
||||
XmNleftAttachment, XmATTACH_FORM,
|
||||
XmNrightAttachment, XmATTACH_FORM,
|
||||
XmNbottomAttachment, XmATTACH_WIDGET,
|
||||
XmNbottomWidget, packageAdd,
|
||||
NULL);
|
||||
|
||||
/* package description */
|
||||
packageInfo.name = XtVaCreateManagedWidget (
|
||||
"name", xmLabelGadgetClass, descriptionPane,
|
||||
XmNleftAttachment, XmATTACH_FORM,
|
||||
XmNrightAttachment, XmATTACH_FORM,
|
||||
XmNtopAttachment, XmATTACH_FORM,
|
||||
NULL);
|
||||
Widget descriptionTabStack = XtVaCreateWidget (
|
||||
"descriptionTabStack", xmTabStackWidgetClass, descriptionPane,
|
||||
XmNleftAttachment, XmATTACH_FORM,
|
||||
XmNrightAttachment, XmATTACH_FORM,
|
||||
XmNtopAttachment, XmATTACH_WIDGET,
|
||||
XmNtopWidget, packageInfo.name,
|
||||
XmNbottomAttachment, XmATTACH_WIDGET,
|
||||
XmNbottomWidget, descriptionSeparator,
|
||||
XmNtabMarginWidth, 0,
|
||||
XmNtabMarginHeight, 0,
|
||||
XmNtabLabelSpacing, 0,
|
||||
XmNmarginWidth, 4,
|
||||
XmNmarginHeight, 4,
|
||||
XmNtabMode, XmTABS_STACKED,
|
||||
NULL);
|
||||
packageInfo.description = createScrolledInfoText(descriptionTabStack, "Description");
|
||||
packageInfo.dependencies = createScrolledInfoText(descriptionTabStack, "Dependencies");
|
||||
packageInfo.provides = createScrolledInfoText(descriptionTabStack, "Provides");
|
||||
packageInfo.contents = createScrolledInfoText(descriptionTabStack, "Contents");
|
||||
XtManageChild(descriptionTabStack);
|
||||
|
||||
/* final setup */
|
||||
|
||||
XtManageChild(packageListPane);
|
||||
XtManageChild(descriptionPane);
|
||||
XtManageChild(pane);
|
||||
|
||||
XtVaSetValues (
|
||||
window,
|
||||
XmNmenuBar, menuBar,
|
||||
XmNworkWindow, pane,
|
||||
NULL);
|
||||
|
||||
updatePackageList();
|
||||
selectPackage(NULL);
|
||||
|
||||
XtRealizeWidget(topLevel);
|
||||
XtAppMainLoop(application);
|
||||
}
|
||||
|
||||
Widget createLabeledTextForm (
|
||||
Widget parent,
|
||||
String labelName,
|
||||
String textName,
|
||||
XmString labelString
|
||||
) {
|
||||
Widget form = XtVaCreateWidget (
|
||||
"form", xmFormWidgetClass, parent,
|
||||
XmNorientation, XmHORIZONTAL,
|
||||
NULL);
|
||||
Widget label = XtVaCreateManagedWidget (
|
||||
labelName, xmLabelGadgetClass, form,
|
||||
XmNleftAttachment, XmATTACH_FORM,
|
||||
XmNtopAttachment, XmATTACH_FORM,
|
||||
XmNbottomAttachment, XmATTACH_FORM,
|
||||
XmNlabelString, labelString,
|
||||
NULL);
|
||||
Widget text = XtVaCreateManagedWidget (
|
||||
textName, xmTextWidgetClass, form,
|
||||
XmNleftAttachment, XmATTACH_WIDGET,
|
||||
XmNleftWidget, label,
|
||||
XmNtopAttachment, XmATTACH_FORM,
|
||||
XmNrightAttachment, XmATTACH_FORM,
|
||||
XmNbottomAttachment, XmATTACH_FORM,
|
||||
NULL);
|
||||
XtManageChild (form);
|
||||
return text;
|
||||
}
|
||||
|
||||
Widget createScrolledInfoText (Widget parent, String name) {
|
||||
Widget scroll = XtVaCreateWidget (
|
||||
name, xmScrolledWindowWidgetClass, parent,
|
||||
NULL);
|
||||
Widget info = XtVaCreateManagedWidget (
|
||||
"info", xmTextWidgetClass, scroll,
|
||||
XmNrows, 10,
|
||||
XmNcolumns, 60,
|
||||
XmNpaneMinimum, 35,
|
||||
XmNeditMode, XmMULTI_LINE_EDIT,
|
||||
XmNeditable, False,
|
||||
XmNwordWrap, True,
|
||||
XmNscrollHorizontal, False,
|
||||
NULL);
|
||||
XtManageChild(scroll);
|
||||
return info;
|
||||
}
|
||||
|
||||
void selectPackage (String name) {
|
||||
if (packageInfo.selected) XtFree(packageInfo.selected);
|
||||
packageInfo.selected = name;
|
||||
|
||||
XmString packageNameString = NULL;
|
||||
|
||||
if (name == NULL) {
|
||||
packageNameString = XmStringCreateLocalized("No package selected");
|
||||
XtVaSetValues (
|
||||
packageInfo.description,
|
||||
XmNvalue, "",
|
||||
NULL);
|
||||
} else {
|
||||
/* instruct apk to describe package */
|
||||
pid_t child;
|
||||
FILE *stream = XmdVaPipedExecPath (
|
||||
"apk", &child, "r",
|
||||
"apk", "info", name, "-dswLPR", "--license",
|
||||
NULL);
|
||||
if (stream == NULL) {
|
||||
/* TODO: error popup */
|
||||
return;
|
||||
}
|
||||
|
||||
/* parse data*/
|
||||
String description = NULL;
|
||||
String dependencies = NULL;
|
||||
String provides = NULL;
|
||||
String contents = NULL;
|
||||
parseInfoOutput (
|
||||
stream,
|
||||
&description, &dependencies,
|
||||
&provides, &contents);
|
||||
fclose(stream);
|
||||
waitpid(child, NULL, 0);
|
||||
|
||||
/* set tab contents to parsed data */
|
||||
packageNameString = XmStringCreateLocalized(name);
|
||||
XtVaSetValues (
|
||||
packageInfo.description,
|
||||
XmNvalue, description,
|
||||
NULL);
|
||||
XtVaSetValues (
|
||||
packageInfo.dependencies,
|
||||
XmNvalue, dependencies,
|
||||
NULL);
|
||||
XtVaSetValues (
|
||||
packageInfo.provides,
|
||||
XmNvalue, provides,
|
||||
NULL);
|
||||
XtVaSetValues (
|
||||
packageInfo.contents,
|
||||
XmNvalue, contents,
|
||||
NULL);
|
||||
XtFree(description);
|
||||
XtFree(dependencies);
|
||||
XtFree(provides);
|
||||
XtFree(contents);
|
||||
}
|
||||
|
||||
XtVaSetValues (
|
||||
packageInfo.name,
|
||||
XmNlabelString, packageNameString,
|
||||
NULL);
|
||||
XmStringFree(packageNameString);
|
||||
}
|
||||
|
||||
void parseInfoOutput (
|
||||
FILE *stream,
|
||||
String *description,
|
||||
String *dependencies,
|
||||
String *provides,
|
||||
String *contents
|
||||
) {
|
||||
char nullTerminator = 0;
|
||||
|
||||
enum {
|
||||
stateSkipUntilSpace,
|
||||
stateGetHeading,
|
||||
stateGetSection
|
||||
} state = stateSkipUntilSpace;
|
||||
int consecutiveNewlines = 0;
|
||||
XmdBuffer *activeBuffer = NULL;
|
||||
XmdBuffer *headingBuffer = NULL;
|
||||
|
||||
XmdBuffer *descriptionBuffer = XmdBufferNew(char);
|
||||
XmdBuffer *dependenciesBuffer = XmdBufferNew(char);
|
||||
XmdBuffer *providesBuffer = XmdBufferNew(char);
|
||||
XmdBuffer *contentsBuffer = XmdBufferNew(char);
|
||||
|
||||
int ch;
|
||||
while ((ch = fgetc(stream)) != EOF) switch (state) {
|
||||
/* discard stream until there is a space */
|
||||
case stateSkipUntilSpace:
|
||||
if (ch == ' ') {
|
||||
headingBuffer = XmdBufferNew(char);
|
||||
state = stateGetHeading;
|
||||
}
|
||||
break;
|
||||
|
||||
/* what is the next section about? */
|
||||
case stateGetHeading:
|
||||
if (ch == ':') {
|
||||
XmdBufferPush(headingBuffer, &nullTerminator);
|
||||
String heading = XmdBufferBreak(headingBuffer);
|
||||
|
||||
if (strcmp(heading, "depends on") == 0) {
|
||||
activeBuffer = dependenciesBuffer;
|
||||
} else if (strcmp(heading, "provides") == 0) {
|
||||
activeBuffer = providesBuffer;
|
||||
} else if (strcmp(heading, "contains") == 0) {
|
||||
activeBuffer = contentsBuffer;
|
||||
} else {
|
||||
activeBuffer = descriptionBuffer;
|
||||
}
|
||||
|
||||
XtFree(heading);
|
||||
consecutiveNewlines = 1;
|
||||
state = stateGetSection;
|
||||
fgetc(stream); /* skip newline */
|
||||
} else {
|
||||
XmdBufferPush(headingBuffer, &ch);
|
||||
}
|
||||
break;
|
||||
|
||||
/* read the section data into the active buffer */
|
||||
case stateGetSection:
|
||||
if (ch == '\n') {
|
||||
if (consecutiveNewlines > 0) {
|
||||
state = stateSkipUntilSpace;
|
||||
break;
|
||||
}
|
||||
consecutiveNewlines ++;
|
||||
} else {
|
||||
consecutiveNewlines = 0;
|
||||
}
|
||||
XmdBufferPush(activeBuffer, &ch);
|
||||
break;
|
||||
}
|
||||
|
||||
XmdBufferPush(descriptionBuffer, &nullTerminator);
|
||||
XmdBufferPush(dependenciesBuffer, &nullTerminator);
|
||||
XmdBufferPush(providesBuffer, &nullTerminator);
|
||||
XmdBufferPush(contentsBuffer, &nullTerminator);
|
||||
|
||||
*description = XmdBufferBreak(descriptionBuffer);
|
||||
*dependencies = XmdBufferBreak(dependenciesBuffer);
|
||||
*provides = XmdBufferBreak(providesBuffer);
|
||||
*contents = XmdBufferBreak(contentsBuffer);
|
||||
}
|
||||
|
||||
void updatePackageList (void) {
|
||||
FILE *stream = NULL;
|
||||
pid_t child = 0;
|
||||
|
||||
switch (packageList.viewMode) {
|
||||
case viewModeWorld:
|
||||
stream = fopen("/etc/apk/world", "r");
|
||||
break;
|
||||
case viewModeInstalled:
|
||||
stream = XmdVaPipedExecPath (
|
||||
"apk", &child, "r",
|
||||
"apk", "list", "--installed",
|
||||
NULL);
|
||||
break;
|
||||
case viewModeUpgradable:
|
||||
stream = XmdVaPipedExecPath (
|
||||
"apk", &child, "r",
|
||||
"apk", "list", "--upgradable",
|
||||
NULL);
|
||||
break;
|
||||
case viewModeOrphaned:
|
||||
stream = XmdVaPipedExecPath (
|
||||
"apk", &child, "r",
|
||||
"apk", "list", "--orphaned",
|
||||
NULL);
|
||||
break;
|
||||
case viewModeSearch:
|
||||
;String query = NULL;
|
||||
XtVaGetValues (
|
||||
packageList.query,
|
||||
XmNvalue, &query,
|
||||
NULL);
|
||||
stream = XmdVaPipedExecPath (
|
||||
"apk", &child, "r",
|
||||
"apk", "search", query,
|
||||
NULL);
|
||||
XtFree(query);
|
||||
break;
|
||||
}
|
||||
|
||||
if (stream == NULL) {
|
||||
/* TODO: error popup */
|
||||
return;
|
||||
}
|
||||
|
||||
readPackageList(stream);
|
||||
fclose(stream);
|
||||
if (child != 0) waitpid(child, NULL, 0);
|
||||
}
|
||||
|
||||
void readPackageList (FILE *list) {
|
||||
String line = NULL;
|
||||
size_t lineLength = 0;
|
||||
|
||||
char packageName[256] = { 0 };
|
||||
|
||||
XmdBuffer *itemsBuffer = XmdBufferNew(XmString);
|
||||
|
||||
while (getline(&line, &lineLength, list) != -1) {
|
||||
sscanf(line, "%256s", packageName);
|
||||
free(line);
|
||||
line = NULL;
|
||||
XmString packageNameString = XmStringCreateLocalized(packageName);
|
||||
XmdBufferPush(itemsBuffer, &packageNameString);
|
||||
}
|
||||
|
||||
Cardinal length = XmdBufferLength(itemsBuffer);
|
||||
XmStringTable items = (XmStringTable)(XmdBufferBreak(itemsBuffer));
|
||||
|
||||
XtVaSetValues (
|
||||
packageList.list,
|
||||
XmNitemCount, length,
|
||||
XmNitems, items,
|
||||
NULL);
|
||||
|
||||
/* free everything */
|
||||
if (line) free(line);
|
||||
for (size_t index = 0; index < length; index ++) {
|
||||
XmStringFree(items[index]);
|
||||
}
|
||||
XtFree((String)(items));
|
||||
}
|
||||
|
||||
void handleListModeSelectionChange (
|
||||
Widget widget,
|
||||
XtPointer clientData,
|
||||
XtPointer callData
|
||||
) {
|
||||
(void)(widget);
|
||||
(void)(callData);
|
||||
|
||||
int selected = *(int *)(&clientData);
|
||||
packageList.viewMode = selected;
|
||||
updatePackageList();
|
||||
}
|
||||
|
||||
void handlePackageSelectionChange (
|
||||
Widget widget,
|
||||
XtPointer clientData,
|
||||
XtPointer callData
|
||||
) {
|
||||
(void)(widget);
|
||||
(void)(clientData);
|
||||
|
||||
XmListCallbackStruct *event = (XmListCallbackStruct*)(callData);
|
||||
if (event->event == NULL) return;
|
||||
|
||||
String choice = (String)(XmStringUnparse (
|
||||
event->item,
|
||||
XmFONTLIST_DEFAULT_TAG,
|
||||
XmCHARSET_TEXT,
|
||||
XmCHARSET_TEXT,
|
||||
NULL, 0,
|
||||
XmOUTPUT_ALL));
|
||||
selectPackage(parsePackageName(choice));
|
||||
XtFree(choice);
|
||||
}
|
||||
|
||||
void handleSearchQueryActivate (
|
||||
Widget widget,
|
||||
XtPointer clientData,
|
||||
XtPointer callData
|
||||
) {
|
||||
(void)(widget);
|
||||
(void)(clientData);
|
||||
(void)(callData);
|
||||
|
||||
packageList.viewMode = viewModeSearch;
|
||||
|
||||
/* FIXME do this by activating the appropriate button. that way we dont
|
||||
have to call updatePackageList manually as well. */
|
||||
Widget button = XmOptionButtonGadget(packageList.modeMenu);
|
||||
XtVaSetValues (
|
||||
button,
|
||||
XmNlabelString, packageList.viewModeStrings[packageList.viewMode],
|
||||
NULL);
|
||||
|
||||
updatePackageList();
|
||||
}
|
||||
|
||||
String parsePackageName (String input) {
|
||||
XmdBuffer *output = XmdBufferNew(char);
|
||||
char ch;
|
||||
Boolean wasDash = False;
|
||||
for (size_t index = 0; (ch = input[index]); index ++) {
|
||||
if (wasDash && isdigit(ch)) {
|
||||
XmdBufferPop(output, NULL);
|
||||
break;
|
||||
} else {
|
||||
wasDash = ch == '-';
|
||||
XmdBufferPush(output, &ch);
|
||||
}
|
||||
}
|
||||
char nullTerminator = 0;
|
||||
XmdBufferPush(output, &nullTerminator);
|
||||
return XmdBufferBreak(output);
|
||||
}
|
Loading…
Reference in New Issue
Block a user