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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user