Compare commits
28 Commits
d0dd41c080
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b88a59a420 | ||
|
|
0af0d8e561 | ||
|
|
1a8a68a631 | ||
|
|
58ef75e455 | ||
|
|
b3b86808ea | ||
|
|
d34e7fdc88 | ||
|
|
37f0d6d0ae | ||
|
|
a538ed14a2 | ||
|
|
463be06955 | ||
|
|
794f7216cd | ||
|
|
0dd701da37 | ||
|
|
80d28f7004 | ||
|
|
1c1331e166 | ||
|
|
03290f61e7 | ||
|
|
720ddd3d99 | ||
|
|
75b2b6e0b2 | ||
|
|
d14b748536 | ||
|
|
318e35242d | ||
|
|
be6d44343e | ||
|
|
7badf24576 | ||
|
|
b1f13bdcac | ||
| 2aff2ff45a | |||
|
|
0b6ba024aa | ||
|
|
a7fc1a84d2 | ||
|
|
4e6e0cad5e | ||
|
|
45425c91d1 | ||
|
|
b341fbe6ca | ||
|
|
51278b9d8f |
38
INSTALL.md
38
INSTALL.md
@@ -1,14 +1,18 @@
|
|||||||
# Installing
|
# Installing
|
||||||
|
|
||||||
## Dependencies
|
## Mandatory dependencies
|
||||||
|
|
||||||
- Xlib
|
- Xlib
|
||||||
- Xt
|
- Xt
|
||||||
- Motif
|
- Motif
|
||||||
- MWM
|
|
||||||
- A C compiler
|
- A C compiler
|
||||||
- brightnessctl (for xmbrightness)
|
|
||||||
- xwallpaper
|
# Optional dependencies
|
||||||
|
|
||||||
|
- MWM (the reccomended window manager for Xmd)
|
||||||
|
- xsct (display-temperature)
|
||||||
|
- brightnessctl (xmbrightness)
|
||||||
|
- xwallpaper (xmd-load-wallpaper)
|
||||||
|
|
||||||
Installing via APK:
|
Installing via APK:
|
||||||
|
|
||||||
@@ -47,8 +51,28 @@ in their respective subdirectories:
|
|||||||
# ./build.sh install
|
# ./build.sh install
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Glue
|
||||||
|
|
||||||
|
Xmd includes some scripts to provide a standard interface for common graphical
|
||||||
|
tasks like taking screenshots. These can be installed using `./install.sh` in
|
||||||
|
the `glue` directory.
|
||||||
|
|
||||||
## Session
|
## Session
|
||||||
|
|
||||||
Xmd includes a startup script and assorted "glue code" to facilitate using it as
|
Xmd includes several scripts to facilitate using it as a desktop environment. It
|
||||||
a desktop environment. It can be installed using `./install.sh` in the `session`
|
can be installed using `./install.sh` in the `session` directory. Note that
|
||||||
directory.
|
without a configuration in place, the session scripts don't really do anything
|
||||||
|
useful. The next section of this document describes how to install a default
|
||||||
|
configuration.
|
||||||
|
|
||||||
|
## Default configuration
|
||||||
|
|
||||||
|
A default configuration can be installed by running `./install.sh` in the
|
||||||
|
`defaults` directory. It contains:
|
||||||
|
|
||||||
|
- An MWM configuration
|
||||||
|
- .xinitrc and .xsession files
|
||||||
|
- Default startup items
|
||||||
|
- MWM
|
||||||
|
- XMPanel
|
||||||
|
- Default panel replicants
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
# Xmd
|
# Xmd
|
||||||
|
|
||||||
An X11/Motif desktop environment written in C99.
|
An X11/Motif desktop environment written in C99 and POSIX shell.
|
||||||
|
|
||||||
|

|
||||||
|
|||||||
BIN
assets/screenshot.png
Normal file
BIN
assets/screenshot.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 185 KiB |
4
defaults/Xmd/panel/10 Terminal.replicant
Normal file
4
defaults/Xmd/panel/10 Terminal.replicant
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
[Launcher]
|
||||||
|
Name=Terminal
|
||||||
|
Exec=uxterm
|
||||||
|
Icon=Terminal
|
||||||
2
defaults/Xmd/panel/80 Battery.replicant
Normal file
2
defaults/Xmd/panel/80 Battery.replicant
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
[Battery]
|
||||||
|
Interval=2
|
||||||
3
defaults/Xmd/panel/90 Clock.replicant
Normal file
3
defaults/Xmd/panel/90 Clock.replicant
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
[Clock]
|
||||||
|
Type=Digital
|
||||||
|
Format=%a, %b %d\n%H:%M
|
||||||
1
defaults/Xmd/startup/mwm.sh
Executable file
1
defaults/Xmd/startup/mwm.sh
Executable file
@@ -0,0 +1 @@
|
|||||||
|
mwm
|
||||||
1
defaults/Xmd/startup/panel.sh
Executable file
1
defaults/Xmd/startup/panel.sh
Executable file
@@ -0,0 +1 @@
|
|||||||
|
xmpanel
|
||||||
5
defaults/install.sh
Executable file
5
defaults/install.sh
Executable file
@@ -0,0 +1,5 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
. ../scripts/flags.sh
|
||||||
|
mkdir -p ~/.Xmd
|
||||||
|
cp -r misc/. ~
|
||||||
|
cp -r Xmd/. ~/.Xmd
|
||||||
74
defaults/misc/.mwmrc
Normal file
74
defaults/misc/.mwmrc
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
Menu DefaultRootMenu
|
||||||
|
{
|
||||||
|
"Root Menu" f.title
|
||||||
|
"Terminal" f.exec "uxterm &"
|
||||||
|
"Shuffle Up" f.circle_up
|
||||||
|
"Shuffle Down" f.circle_down
|
||||||
|
"Refresh" f.refresh
|
||||||
|
"Pack Icons" f.pack_icons
|
||||||
|
no-label f.separator
|
||||||
|
"Screen Shot" f.exec "screenshot selection clipboard"
|
||||||
|
no-label f.separator
|
||||||
|
"Restart MWM" f.restart
|
||||||
|
"Quit..." f.exec "xmd-end-session"
|
||||||
|
}
|
||||||
|
|
||||||
|
Menu DefaultWindowMenu
|
||||||
|
{
|
||||||
|
Restore _R Shift Mod4<Key>m f.restore
|
||||||
|
Move _M Mod4<Key>g f.move
|
||||||
|
Size _S Mod4<Key>s f.resize
|
||||||
|
Minimize _n Mod4<Key>h f.minimize
|
||||||
|
Maximize _x Mod4<Key>m f.maximize
|
||||||
|
no-label f.separator
|
||||||
|
"Screen Shot" _e Alt Ctrl<Key>Print f.exec "screenshot window clipboard"
|
||||||
|
no-label f.separator
|
||||||
|
Close _C Mod4<Key>q f.kill
|
||||||
|
}
|
||||||
|
|
||||||
|
Keys DefaultKeyBindings
|
||||||
|
{
|
||||||
|
Mod4<Key>Escape window|icon f.post_wmenu
|
||||||
|
Mod4<Key>Tab root|icon|window f.next_key
|
||||||
|
Mod4 Shift<Key>Tab root|icon|window f.prev_key
|
||||||
|
Mod4<Key>Right root|icon|window f.next_key window
|
||||||
|
Mod4<Key>Left root|icon|window f.prev_key window
|
||||||
|
<Key>Tab icon f.next_key icon
|
||||||
|
Shift<Key>Tab icon f.prev_key icon
|
||||||
|
<Key>Right icon f.next_key icon
|
||||||
|
<Key>Left icon f.prev_key icon
|
||||||
|
Alt Shift Ctrl<Key>exclam root|icon|window f.set_behavior
|
||||||
|
Mod4 Shift<Key>r root|icon|window f.restart
|
||||||
|
Mod4 Shift<Key>q root|icon|window f.quit_mwm
|
||||||
|
Mod4<Key>Return root|icon|window f.exec "uxterm &"
|
||||||
|
Mod4<Key>R root|icon|window f.exec "rofi -show run &"
|
||||||
|
Mod4<Key>space root|icon|window f.exec "rofi -show drun &"
|
||||||
|
<Key>Return icon f.restore
|
||||||
|
<Key>space icon f.post_wmenu
|
||||||
|
|
||||||
|
<Key>XF86MonBrightnessUp root|icon|window f.exec "brightnessctl s --exponent=10 +5%"
|
||||||
|
<Key>XF86MonBrightnessDown root|icon|window f.exec "brightnessctl s --exponent=10 5%-"
|
||||||
|
<Key>XF86AudioRaiseVolume root|icon|window f.exec "pamixer -i 2"
|
||||||
|
<Key>XF86AudioLowerVolume root|icon|window f.exec "pamixer -d 2"
|
||||||
|
Mod4<Key>period root|icon|window f.exec "pamixer -i 2"
|
||||||
|
Mod4<Key>comma root|icon|window f.exec "pamixer -d 2"
|
||||||
|
|
||||||
|
<Key>Print root|icon|window f.exec "screenshot"
|
||||||
|
Ctrl<Key>Print root|icon|window f.exec "screenshot clipboard"
|
||||||
|
Shift<Key>Print root|icon|window f.exec "screenshot selection"
|
||||||
|
Shift Ctrl<Key>Print root|icon|window f.exec "screenshot selection clipboard"
|
||||||
|
Alt<Key>Print icon|window f.exec "screenshot window"
|
||||||
|
|
||||||
|
Mod4<Key>grave window f.next_key icon
|
||||||
|
Mod4<Key>grave root|icon f.next_key window
|
||||||
|
}
|
||||||
|
|
||||||
|
Buttons DefaultButtonBindings
|
||||||
|
{
|
||||||
|
<Btn1Down> icon|frame f.raise
|
||||||
|
<Btn3Down> icon|frame f.post_wmenu
|
||||||
|
<Btn1Down> root f.menu DefaultRootMenu
|
||||||
|
Mod4<Btn1Down> window|icon f.move
|
||||||
|
Mod4<Btn2Down> window|icon f.lower
|
||||||
|
Mod4<Btn3Down> window|icon f.resize
|
||||||
|
}
|
||||||
1
defaults/misc/.xinitrc
Normal file
1
defaults/misc/.xinitrc
Normal file
@@ -0,0 +1 @@
|
|||||||
|
. ~/.xsession
|
||||||
1
defaults/misc/.xsession
Normal file
1
defaults/misc/.xsession
Normal file
@@ -0,0 +1 @@
|
|||||||
|
exec dbus-run-session xmd
|
||||||
3
glue/install.sh
Executable file
3
glue/install.sh
Executable file
@@ -0,0 +1,3 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
. ../scripts/flags.sh
|
||||||
|
cp src/* "$PREFIX/bin"
|
||||||
61
glue/src/display-temperature
Executable file
61
glue/src/display-temperature
Executable file
@@ -0,0 +1,61 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
name=`basename "$0"`
|
||||||
|
|
||||||
|
isInstalled() {
|
||||||
|
type "$1" > /dev/null
|
||||||
|
}
|
||||||
|
|
||||||
|
mustHaveInstalled() {
|
||||||
|
if ! isInstalled "$1"; then
|
||||||
|
echo "$name: $1 is not installed" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
echo "Usage: $name day | night | daemon" >&2
|
||||||
|
exit 2
|
||||||
|
}
|
||||||
|
|
||||||
|
dayTemp=6500
|
||||||
|
nightTemp=4000
|
||||||
|
sunset=17
|
||||||
|
sunrise=7
|
||||||
|
|
||||||
|
if isInstalled xsct
|
||||||
|
then SCT=xsct
|
||||||
|
elif isInstalled sct
|
||||||
|
then SCT=sct
|
||||||
|
fi
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
"day" | "night" | "daemon")
|
||||||
|
mode="$1"
|
||||||
|
shift 1
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
usage
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
[ "$#" -gt 0 ] && usage
|
||||||
|
|
||||||
|
case "$mode" in
|
||||||
|
"day")
|
||||||
|
$SCT "$dayTemp"
|
||||||
|
;;
|
||||||
|
"night")
|
||||||
|
$SCT "$nightTemp"
|
||||||
|
;;
|
||||||
|
"daemon")
|
||||||
|
while
|
||||||
|
hour=`date +%H`
|
||||||
|
if [ "$hour" -gt "$sunset" ] || [ "$hour" -lt "$sunrise" ]
|
||||||
|
then temp="$nightTemp"
|
||||||
|
else temp="$dayTemp"
|
||||||
|
fi
|
||||||
|
$SCT "$temp"
|
||||||
|
do sleep 4; done
|
||||||
|
;;
|
||||||
|
esac
|
||||||
41
glue/src/mount-sftp
Executable file
41
glue/src/mount-sftp
Executable file
@@ -0,0 +1,41 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
name=`basename $0`
|
||||||
|
|
||||||
|
isInstalled() {
|
||||||
|
type "$1" > /dev/null
|
||||||
|
}
|
||||||
|
|
||||||
|
mustHaveInstalled() {
|
||||||
|
if ! isInstalled "$1"; then
|
||||||
|
echo "$name: $1 is not installed" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
echo "Usage: $name" >&2
|
||||||
|
exit 2
|
||||||
|
}
|
||||||
|
|
||||||
|
[ "$#" -gt 0 ] && usage
|
||||||
|
|
||||||
|
sshfsOptions="reconnect,ServerAliveInterval=4,ServerAliveCountMax=10"
|
||||||
|
|
||||||
|
mustHaveInstalled sshfs
|
||||||
|
mustHaveInstalled mountpoint
|
||||||
|
mustHaveInstalled fusermount
|
||||||
|
|
||||||
|
mountsDir="$HOME/Remote"
|
||||||
|
[ -n "$XMD_SFTP_DIR" ] && mountsDir="$XMD_SFTP_DIR"
|
||||||
|
|
||||||
|
for point in "$mountsDir"/*; do
|
||||||
|
# do not deal with files
|
||||||
|
[ -d "$point" ] || continue
|
||||||
|
|
||||||
|
mountpoint "$point" > /dev/null && fusermount -u "$point"
|
||||||
|
|
||||||
|
address=`basename "$point"`
|
||||||
|
echo "mounting $address on $point" >&2
|
||||||
|
sshfs "$address:/" "$point" -o $sshfsOptions
|
||||||
|
done
|
||||||
58
glue/src/screenshot
Executable file
58
glue/src/screenshot
Executable file
@@ -0,0 +1,58 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
name=`basename "$0"`
|
||||||
|
|
||||||
|
isInstalled() {
|
||||||
|
type "$1" > /dev/null
|
||||||
|
}
|
||||||
|
|
||||||
|
mustHaveInstalled() {
|
||||||
|
if ! isInstalled "$1"; then
|
||||||
|
echo "$name: $1 is not installed" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
echo "Usage: $name [selection | window | screen] [clipboard]" >&2
|
||||||
|
exit 2
|
||||||
|
}
|
||||||
|
|
||||||
|
picturesDir=`xdg-user-dir PICTURES`
|
||||||
|
test -z "$picturesDir" && picturesDir="$HOME/Pictures"
|
||||||
|
picturesDir="$picturesDir/Screen Shots"
|
||||||
|
|
||||||
|
if ! mkdir -p "$picturesDir"; then
|
||||||
|
echo "$name: can't create $picturesDir" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
outputFilePath="$picturesDir/`date -Iseconds`.png"
|
||||||
|
|
||||||
|
mustHaveInstalled scrot
|
||||||
|
case "$1" in
|
||||||
|
"selection" | "window" | "screen")
|
||||||
|
mode="$1"
|
||||||
|
shift 1
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
mode="screen"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if [ "$1" = "clipboard" ]; then
|
||||||
|
clipboard=true
|
||||||
|
shift 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
[ "$#" -gt 0 ] && usage
|
||||||
|
|
||||||
|
case "$mode" in
|
||||||
|
"selection") scrot --select --line style=dash --freeze --file "$outputFilePath";;
|
||||||
|
"window" ) scrot --focused --border --file "$outputFilePath";;
|
||||||
|
"screen" ) scrot --file "$outputFilePath";;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if [ -n "$copyToClipboard" ]; then
|
||||||
|
mustHaveInstalled xclip
|
||||||
|
xclip -selection clipboard -target image/png -i "$outputFilePath"
|
||||||
|
fi
|
||||||
@@ -5,23 +5,26 @@ BUILDFLAGS="$CFLAGS -Iinclude"
|
|||||||
LINTCHECKS="-checks=-*,clang-analyzer-*,bugprone-*,portability-*,cert-*"
|
LINTCHECKS="-checks=-*,clang-analyzer-*,bugprone-*,portability-*,cert-*"
|
||||||
SOURCE="src/*.c"
|
SOURCE="src/*.c"
|
||||||
|
|
||||||
function build() {
|
build() {
|
||||||
|
mkdir -p lib
|
||||||
cc $SOURCE -o "lib/libXmd.so" -shared $BUILDFLAGS || \
|
cc $SOURCE -o "lib/libXmd.so" -shared $BUILDFLAGS || \
|
||||||
echo "XXX FAIL!"
|
echo "XXX FAIL!"
|
||||||
}
|
}
|
||||||
|
|
||||||
function lint() {
|
lint() {
|
||||||
clang-tidy $SOURCE $LINTCHECKS -- $BUILDFLAGS || \
|
clang-tidy $SOURCE $LINTCHECKS -- $BUILDFLAGS || \
|
||||||
echo "XXX FAIL!"
|
echo "XXX FAIL!"
|
||||||
}
|
}
|
||||||
|
|
||||||
function clean() {
|
clean() {
|
||||||
rm -f lib/*
|
rm -f lib/*
|
||||||
}
|
}
|
||||||
|
|
||||||
case "$1" in
|
case "$1" in
|
||||||
install)
|
install)
|
||||||
clean; build
|
clean; build
|
||||||
|
mkdir -p "$PREFIX/lib"
|
||||||
|
mkdir -p "$PREFIX/include/Xmd"
|
||||||
cp lib/*.so "$PREFIX/lib"
|
cp lib/*.so "$PREFIX/lib"
|
||||||
cp include/Xmd/*.h "$PREFIX/include/Xmd"
|
cp include/Xmd/*.h "$PREFIX/include/Xmd"
|
||||||
clean
|
clean
|
||||||
|
|||||||
@@ -41,9 +41,9 @@ void XmdBufferResize (XmdBuffer *buffer, Cardinal length) {
|
|||||||
void XmdBufferFit (XmdBuffer *buffer) {
|
void XmdBufferFit (XmdBuffer *buffer) {
|
||||||
if (buffer->length > buffer->capacity) {
|
if (buffer->length > buffer->capacity) {
|
||||||
buffer->capacity *= XmdBUFFER_GROWTH_FACTOR;
|
buffer->capacity *= XmdBUFFER_GROWTH_FACTOR;
|
||||||
void *data = XtReallocArray (
|
void *data = XtRealloc (
|
||||||
buffer->data,
|
buffer->data,
|
||||||
buffer->capacity,
|
buffer->capacity *
|
||||||
buffer->size);
|
buffer->size);
|
||||||
if (data == NULL) {
|
if (data == NULL) {
|
||||||
/* TODO return error */
|
/* TODO return error */
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
#include "icons/appWebBrowser.xbm"
|
#include "icons/appWebBrowser.xbm"
|
||||||
#include "icons/unknown.xbm"
|
#include "icons/unknown.xbm"
|
||||||
|
|
||||||
void activateLauncher (Widget button, XtPointer clientData, XtPointer callData) {
|
static void activateLauncher (Widget button, XtPointer clientData, XtPointer callData) {
|
||||||
(void)(button);
|
(void)(button);
|
||||||
(void)(callData);
|
(void)(callData);
|
||||||
XmdReplicantState *state = (XmdReplicantState *)(clientData);
|
XmdReplicantState *state = (XmdReplicantState *)(clientData);
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
. `dirname $0`/flags.sh
|
. `dirname $0`/flags.sh
|
||||||
|
|
||||||
function build() {
|
build() {
|
||||||
if
|
if
|
||||||
mkdir -p bin && \
|
mkdir -p bin && \
|
||||||
cc $CFLAGS -c -o "bin/$1.o" src/*.c && \
|
cc $CFLAGS -c -o "bin/$1.o" src/*.c && \
|
||||||
@@ -16,7 +16,7 @@ function build() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
function clean() {
|
clean() {
|
||||||
rm -f bin/*
|
rm -f bin/*
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
. `dirname $0`/flags.sh
|
. `dirname $0`/flags.sh
|
||||||
|
|
||||||
function build() {
|
build() {
|
||||||
if
|
if
|
||||||
mkdir -p lib && \
|
mkdir -p lib && \
|
||||||
cc src/*.c -o "lib/$1.so" -shared $CFLAGS
|
cc src/*.c -o "lib/$1.so" -shared $CFLAGS
|
||||||
@@ -15,7 +15,7 @@ function build() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
function clean() {
|
clean() {
|
||||||
rm -f bin/*
|
rm -f bin/*
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,29 +1,48 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
|
name=`basename "$0"`
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
echo "Usage: $name" >&2
|
||||||
|
exit 2
|
||||||
|
}
|
||||||
|
|
||||||
|
[ "$#" -gt 0 ] && usage
|
||||||
|
|
||||||
|
# basic Xmd environment variables
|
||||||
|
export XMD_SESSION_PID="$$"
|
||||||
export XMD_USERDIR="${HOME}/.Xmd"
|
export XMD_USERDIR="${HOME}/.Xmd"
|
||||||
mkdir -p "${XMD_USERDIR}"
|
mkdir -p "${XMD_USERDIR}"
|
||||||
|
|
||||||
|
# environment vars that X applications tend to expect
|
||||||
|
export XDG_CURRENT_DESKTOP=Xmd
|
||||||
|
export XDG_SESSION_DESKTOP=Xmd
|
||||||
|
export XDG_SESSION_TYPE=X11
|
||||||
|
|
||||||
|
# replicant path
|
||||||
export XMD_REPLICANT_PATH="/usr/lib/Xmd/replicants:/usr/local/lib/Xmd/replicants"
|
export XMD_REPLICANT_PATH="/usr/lib/Xmd/replicants:/usr/local/lib/Xmd/replicants"
|
||||||
localReplicantDir="$HOME/.local/lib/Xmd/replicants"
|
localReplicantDir="$HOME/.local/lib/Xmd/replicants"
|
||||||
if [ -d "$localReplicantDir" ]; then
|
if [ -d "$localReplicantDir" ]; then
|
||||||
export XMD_REPLICANT_PATH="$localReplicantDir:$XMD_REPLICANT_PATH"
|
export XMD_REPLICANT_PATH="$localReplicantDir:$XMD_REPLICANT_PATH"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# load desktop configuration
|
||||||
xmd-load-xresources
|
xmd-load-xresources
|
||||||
appDefaults="${XMD_USERDIR}/app-defaults"
|
appDefaults="${XMD_USERDIR}/app-defaults"
|
||||||
if [ -d "$appDefaults" ]; then
|
if [ -d "$appDefaults" ]; then
|
||||||
export XAPPLRESDIR="$appDefaults"
|
export XAPPLRESDIR="$appDefaults"
|
||||||
else
|
else
|
||||||
echo "!!! cant find $appDefaults"
|
echo "$name cant find $appDefaults" >&2
|
||||||
fi
|
fi
|
||||||
xmd-load-wallpaper
|
xmd-load-wallpaper
|
||||||
|
|
||||||
|
# run startup items
|
||||||
startupDir="$XMD_USERDIR/startup"
|
startupDir="$XMD_USERDIR/startup"
|
||||||
if [ -d "$startupDir" ]; then
|
if [ -d "$startupDir" ]; then
|
||||||
export XMD_STARTUPDIR="$startupDir"
|
export XMD_STARTUPDIR="$startupDir"
|
||||||
xmd-run-startup-items
|
xmd-run-startup-items
|
||||||
else
|
else
|
||||||
echo "!!! cant find $startupDir"
|
echo "$name cant find $startupDir" >&2
|
||||||
fi
|
fi
|
||||||
|
|
||||||
exec mwm
|
sleep infinity
|
||||||
|
|||||||
17
session/src/xmd-end-session
Executable file
17
session/src/xmd-end-session
Executable file
@@ -0,0 +1,17 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
name=`basename "$0"`
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
echo "Usage: $name" >&2
|
||||||
|
exit 2
|
||||||
|
}
|
||||||
|
|
||||||
|
[ "$#" -gt 0 ] && usage
|
||||||
|
|
||||||
|
if [ -z "$XMD_SESSION_PID" ]; then
|
||||||
|
echo "$name: session is not running (\$XMD_SESSION_PID not set)" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
kill "$XMD_SESSION_PID"
|
||||||
@@ -1,9 +1,55 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
if type "$XMD_USERDIR/wallpaper" > /dev/null; then
|
name=`basename "$0"`
|
||||||
. "$XMD_USERDIR/wallpaper"
|
configFilePath="$XMD_USERDIR/wallpaper"
|
||||||
|
|
||||||
if type xwallpaper > /dev/null; then
|
isInstalled() {
|
||||||
xwallpaper "--${mode}" "$file"
|
type "$1" > /dev/null
|
||||||
|
}
|
||||||
|
|
||||||
|
shouldHaveInstalled() {
|
||||||
|
if ! isInstalled "$1"; then
|
||||||
|
echo "$name: $1 is not installed" >&2
|
||||||
|
return 1
|
||||||
fi
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
echo "Usage: $name" >&2
|
||||||
|
exit 2
|
||||||
|
}
|
||||||
|
|
||||||
|
[ "$#" -gt 0 ] && usage
|
||||||
|
|
||||||
|
echo $configFilePath
|
||||||
|
if type "$configFilePath" > /dev/null; then
|
||||||
|
color="black"
|
||||||
|
|
||||||
|
while read -r line; do
|
||||||
|
line=`echo $line | sed s/\#.\*$//g`
|
||||||
|
[ -z "$line" ] && continue
|
||||||
|
|
||||||
|
IFS="=" read key value << EOF
|
||||||
|
$line
|
||||||
|
EOF
|
||||||
|
case "$key" in
|
||||||
|
"mode") mode="$value";;
|
||||||
|
"file") file="$value";;
|
||||||
|
"color") color="$value";;
|
||||||
|
*) echo "$name: bad key $key in $configFilePath" >&2;;
|
||||||
|
esac
|
||||||
|
done < "$configFilePath"
|
||||||
|
|
||||||
|
case "$mode" in
|
||||||
|
"" | center | focus | maximize | stretch | tile | zoom) ;;
|
||||||
|
*)
|
||||||
|
echo "$name: bad mode $mode" >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
[ -n "$color" ] && shouldHaveInstalled xsetroot && \
|
||||||
|
xsetroot -solid "$color"
|
||||||
|
[ -n "$mode" ] && shouldHaveInstalled xwallpaper && \
|
||||||
|
xwallpaper "--${mode}" "$file"
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -1,10 +1,30 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
xrdb -remove
|
name=`basename "$0"`
|
||||||
|
|
||||||
xResources="${XMD_USERDIR}/Xresources"
|
xResources="${XMD_USERDIR}/Xresources"
|
||||||
|
|
||||||
|
isInstalled() {
|
||||||
|
type "$1" > /dev/null
|
||||||
|
}
|
||||||
|
|
||||||
|
mustHaveInstalled() {
|
||||||
|
if ! isInstalled "$1"; then
|
||||||
|
echo "$name: $1 is not installed" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
echo "Usage: $name" >&2
|
||||||
|
exit 2
|
||||||
|
}
|
||||||
|
|
||||||
|
[ "$#" -gt 0 ] && usage
|
||||||
|
|
||||||
|
cd ~
|
||||||
if [ -r "$xResources" ]; then
|
if [ -r "$xResources" ]; then
|
||||||
|
mustHaveInstalled xrdb
|
||||||
xrdb -cpp /usr/bin/cpp < "$xResources"
|
xrdb -cpp /usr/bin/cpp < "$xResources"
|
||||||
else
|
else
|
||||||
echo "!!! can't find $xResources"
|
echo "$name: can't find $xResources" >&2
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -1,10 +1,19 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
|
name=`basename "$0"`
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
echo "Usage: $name" >&2
|
||||||
|
exit 2
|
||||||
|
}
|
||||||
|
|
||||||
|
[ "$#" -gt 0 ] && usage
|
||||||
|
|
||||||
if [ -z "$XMD_STARTUPDIR" ]; then
|
if [ -z "$XMD_STARTUPDIR" ]; then
|
||||||
echo "!!! \$XMD_STARTUPDIR not set"
|
echo "$name \$XMD_STARTUPDIR not set" >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
for item in $XMD_STARTUPDIR/*; do
|
for item in "$XMD_STARTUPDIR"/*; do
|
||||||
if [ -x "$item" ]; then
|
if [ -x "$item" ]; then
|
||||||
"$item" &
|
"$item" &
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -1,35 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
if ! type scrot > /dev/null; then
|
|
||||||
>&2 echo "!!! scrot is not installed"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
picturesDir=`xdg-user-dir PICTURES`
|
|
||||||
test -z "$picturesDir" && picturesDir="$HOME/Pictures"
|
|
||||||
picturesDir="$picturesDir/Screen Shots"
|
|
||||||
|
|
||||||
if ! mkdir -p "$picturesDir"; then
|
|
||||||
>&2 echo "!!! can't create $picturesDir"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
output="$picturesDir/`date -Iseconds`.png"
|
|
||||||
|
|
||||||
case "$1" in
|
|
||||||
"selection")
|
|
||||||
scrot --select --line style=dash --freeze --file "$output"
|
|
||||||
clipArg="$2"
|
|
||||||
;;
|
|
||||||
"window")
|
|
||||||
scrot --focused --border --file "$output"
|
|
||||||
clipArg="$2"
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
scrot --file "$output"
|
|
||||||
clipArg="$1"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
if test "$clipArg" = "clipboard"; then
|
|
||||||
xclip -selection clipboard -target image/png -i "$output"
|
|
||||||
fi
|
|
||||||
9
xmdev/src/icons/mount.xbm
Normal file
9
xmdev/src/icons/mount.xbm
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#define mount_width 24
|
||||||
|
#define mount_height 24
|
||||||
|
static unsigned char mount_bits[] = {
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x80, 0xff, 0x01,
|
||||||
|
0xe0, 0x81, 0x07, 0x70, 0x00, 0x0e, 0x30, 0x00, 0x0c, 0x18, 0x00, 0x19,
|
||||||
|
0x18, 0x80, 0x18, 0x0c, 0x40, 0x30, 0x0c, 0x00, 0x30, 0x0c, 0xd8, 0x37,
|
||||||
|
0xec, 0x1b, 0x30, 0x0c, 0x00, 0x30, 0x0c, 0x02, 0x30, 0x18, 0x01, 0x1c,
|
||||||
|
0x98, 0x00, 0x14, 0x30, 0x00, 0x14, 0x70, 0x80, 0xf7, 0xe0, 0x81, 0x80,
|
||||||
|
0x80, 0xff, 0xf7, 0x00, 0x7e, 0x14, 0x00, 0x00, 0x14, 0x00, 0x00, 0x1c };
|
||||||
9
xmdev/src/icons/refresh.xbm
Normal file
9
xmdev/src/icons/refresh.xbm
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#define refresh_width 24
|
||||||
|
#define refresh_height 24
|
||||||
|
static unsigned char refresh_bits[] = {
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0xc0, 0xff, 0x00,
|
||||||
|
0xf0, 0xff, 0x03, 0xf8, 0xc0, 0x07, 0x38, 0x00, 0x07, 0x1c, 0x00, 0x0e,
|
||||||
|
0x1c, 0x00, 0x0e, 0x0e, 0x00, 0x1c, 0x0e, 0x00, 0x1c, 0x0e, 0x00, 0x7f,
|
||||||
|
0x0e, 0x00, 0x3e, 0x0e, 0x00, 0x1c, 0x0e, 0x00, 0x08, 0x1c, 0x00, 0x00,
|
||||||
|
0x1c, 0x00, 0x06, 0x38, 0x00, 0x07, 0xf8, 0xc0, 0x07, 0xf0, 0xff, 0x03,
|
||||||
|
0xc0, 0xff, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||||
9
xmdev/src/icons/unmount.xbm
Normal file
9
xmdev/src/icons/unmount.xbm
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#define unmount_width 24
|
||||||
|
#define unmount_height 24
|
||||||
|
static unsigned char unmount_bits[] = {
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x18, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x7e, 0x00, 0x00, 0xff, 0x00,
|
||||||
|
0x80, 0xff, 0x01, 0xc0, 0xff, 0x03, 0xe0, 0xff, 0x07, 0xf0, 0xff, 0x0f,
|
||||||
|
0xf8, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x1f,
|
||||||
|
0xf8, 0xff, 0x1f, 0xf8, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||||
315
xmdev/src/main.c
315
xmdev/src/main.c
@@ -1,8 +1,10 @@
|
|||||||
#define _XOPEN_SOURCE
|
#define _XOPEN_SOURCE 700
|
||||||
#include <Xm/Xm.h>
|
#include <Xm/Xm.h>
|
||||||
|
#include <Xm/Form.h>
|
||||||
|
#include <Xm/PushB.h>
|
||||||
#include <Xm/MainW.h>
|
#include <Xm/MainW.h>
|
||||||
#include <Xm/Container.h>
|
|
||||||
#include <Xm/IconG.h>
|
#include <Xm/IconG.h>
|
||||||
|
#include <Xm/Container.h>
|
||||||
#include <Xm/ScrolledW.h>
|
#include <Xm/ScrolledW.h>
|
||||||
|
|
||||||
#include <Xmd/Icon.h>
|
#include <Xmd/Icon.h>
|
||||||
@@ -12,10 +14,16 @@
|
|||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <libgen.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
|
|
||||||
|
#include "icons/refresh.xbm"
|
||||||
|
#include "icons/mount.xbm"
|
||||||
|
#include "icons/unmount.xbm"
|
||||||
#include "icons/generic.xbm"
|
#include "icons/generic.xbm"
|
||||||
#include "icons/generic-small.xbm"
|
#include "icons/generic-small.xbm"
|
||||||
#include "icons/icon.xbm"
|
#include "icons/icon.xbm"
|
||||||
@@ -45,6 +53,7 @@ typedef enum {
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
Widget widget;
|
Widget widget;
|
||||||
DeviceKind kind;
|
DeviceKind kind;
|
||||||
|
Bool orphaned;
|
||||||
String name;
|
String name;
|
||||||
String mountPoint;
|
String mountPoint;
|
||||||
String label;
|
String label;
|
||||||
@@ -52,6 +61,7 @@ typedef struct {
|
|||||||
|
|
||||||
void loadIconPixmaps (void);
|
void loadIconPixmaps (void);
|
||||||
void refreshDevices (void);
|
void refreshDevices (void);
|
||||||
|
void refreshDisks (void);
|
||||||
Device * DeviceNew (String name, DeviceKind kind);
|
Device * DeviceNew (String name, DeviceKind kind);
|
||||||
void DeviceDelete (ConstString name);
|
void DeviceDelete (ConstString name);
|
||||||
void DeviceFree (Device *this);
|
void DeviceFree (Device *this);
|
||||||
@@ -60,6 +70,7 @@ void DeviceSetMountPoint (Device *this, ConstString mountPoint);
|
|||||||
void DeviceSetLabel (Device *this, ConstString label);
|
void DeviceSetLabel (Device *this, ConstString label);
|
||||||
int readBlockDevice (FILE *stream, Device **);
|
int readBlockDevice (FILE *stream, Device **);
|
||||||
int readLsblkPair (FILE *stream, String *key, String *value);
|
int readLsblkPair (FILE *stream, String *key, String *value);
|
||||||
|
void handleRefresh (Widget, XtPointer, XtPointer);
|
||||||
|
|
||||||
int main (int argc, char *argv[]) {
|
int main (int argc, char *argv[]) {
|
||||||
devices = XmdStringMapNew();
|
devices = XmdStringMapNew();
|
||||||
@@ -69,16 +80,74 @@ int main (int argc, char *argv[]) {
|
|||||||
NULL, 0,
|
NULL, 0,
|
||||||
&argc, argv,
|
&argc, argv,
|
||||||
NULL,
|
NULL,
|
||||||
XmNtitle, "Devices",
|
XmNtitle, "Devices",
|
||||||
XmNiconName, "Devices",
|
XmNiconName, "Devices",
|
||||||
|
XmNwidth, 256,
|
||||||
|
XmNheight, 256,
|
||||||
NULL);
|
NULL);
|
||||||
Pixmap iconPixmap = XmdLoadBitmapIcon(window, icon);
|
|
||||||
|
Widget layout = XtVaCreateWidget (
|
||||||
|
"layout", xmFormWidgetClass, window,
|
||||||
|
XmNorientation, XmVERTICAL,
|
||||||
|
NULL);
|
||||||
|
Pixmap iconPixmap = XmdLoadBitmapIcon(layout, icon);
|
||||||
XtVaSetValues (
|
XtVaSetValues (
|
||||||
window,
|
window,
|
||||||
XmNiconPixmap, iconPixmap,
|
XmNiconPixmap, iconPixmap,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
|
Pixmap refreshPixmap = XmdLoadBitmapIcon(layout, refresh);
|
||||||
|
XmString string = XmStringCreateLocalized("Refresh");
|
||||||
|
Widget refreshButton = XtVaCreateManagedWidget (
|
||||||
|
"refreshButton", xmPushButtonWidgetClass, layout,
|
||||||
|
XmNleftAttachment, XmATTACH_FORM,
|
||||||
|
XmNbottomAttachment, XmATTACH_FORM,
|
||||||
|
XmNlabelType, XmPIXMAP_AND_STRING,
|
||||||
|
XmNlabelPixmap, refreshPixmap,
|
||||||
|
XmNlabelString, string,
|
||||||
|
NULL);
|
||||||
|
XmStringFree(string);
|
||||||
|
XtAddCallback (
|
||||||
|
refreshButton, XmNactivateCallback,
|
||||||
|
handleRefresh, NULL);
|
||||||
|
|
||||||
|
Pixmap mountPixmap = XmdLoadBitmapIcon(layout, mount);
|
||||||
|
string = XmStringCreateLocalized("Mount");
|
||||||
|
Widget mountButton = XtVaCreateManagedWidget (
|
||||||
|
"mountButton", xmPushButtonWidgetClass, layout,
|
||||||
|
XmNleftAttachment, XmATTACH_WIDGET,
|
||||||
|
XmNleftWidget, refreshButton,
|
||||||
|
XmNbottomAttachment, XmATTACH_FORM,
|
||||||
|
XmNlabelType, XmPIXMAP_AND_STRING,
|
||||||
|
XmNlabelPixmap, mountPixmap,
|
||||||
|
XmNlabelString, string,
|
||||||
|
NULL);
|
||||||
|
XmStringFree(string);
|
||||||
|
|
||||||
|
Pixmap unmountPixmap = XmdLoadBitmapIcon(layout, unmount);
|
||||||
|
string = XmStringCreateLocalized("Unmount");
|
||||||
|
/*Widget unmountButton = */XtVaCreateManagedWidget (
|
||||||
|
"unmountButton", xmPushButtonWidgetClass, layout,
|
||||||
|
XmNleftAttachment, XmATTACH_WIDGET,
|
||||||
|
XmNleftWidget, mountButton,
|
||||||
|
XmNbottomAttachment, XmATTACH_FORM,
|
||||||
|
XmNlabelType, XmPIXMAP_AND_STRING,
|
||||||
|
XmNlabelPixmap, unmountPixmap,
|
||||||
|
XmNlabelString, string,
|
||||||
|
NULL);
|
||||||
|
XmStringFree(string);
|
||||||
|
|
||||||
|
Widget scroller = XtVaCreateWidget (
|
||||||
|
"scroll", xmScrolledWindowWidgetClass, layout,
|
||||||
|
XmNscrollingPolicy, XmAUTOMATIC,
|
||||||
|
XmNleftAttachment, XmATTACH_FORM,
|
||||||
|
XmNtopAttachment, XmATTACH_FORM,
|
||||||
|
XmNrightAttachment, XmATTACH_FORM,
|
||||||
|
XmNbottomAttachment, XmATTACH_WIDGET,
|
||||||
|
XmNbottomWidget, refreshButton,
|
||||||
|
NULL);
|
||||||
container = XtVaCreateManagedWidget (
|
container = XtVaCreateManagedWidget (
|
||||||
"container", xmContainerWidgetClass, window,
|
"container", xmContainerWidgetClass, scroller,
|
||||||
XmNlayoutType, XmSPATIAL,
|
XmNlayoutType, XmSPATIAL,
|
||||||
XmNspatialStyle, XmGRID,
|
XmNspatialStyle, XmGRID,
|
||||||
NULL);
|
NULL);
|
||||||
@@ -86,6 +155,8 @@ int main (int argc, char *argv[]) {
|
|||||||
loadIconPixmaps();
|
loadIconPixmaps();
|
||||||
refreshDevices();
|
refreshDevices();
|
||||||
|
|
||||||
|
XtManageChild(scroller);
|
||||||
|
XtManageChild(layout);
|
||||||
XtRealizeWidget(window);
|
XtRealizeWidget(window);
|
||||||
XtAppMainLoop(application);
|
XtAppMainLoop(application);
|
||||||
}
|
}
|
||||||
@@ -101,145 +172,123 @@ void loadIconPixmaps (void) {
|
|||||||
dev(TTY, tty);
|
dev(TTY, tty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void handleRefresh (Widget button, XtPointer clientData, XtPointer callData) {
|
||||||
|
(void)(button);
|
||||||
|
(void)(clientData);
|
||||||
|
(void)(callData);
|
||||||
|
refreshDevices();
|
||||||
|
}
|
||||||
|
|
||||||
|
Bool markDevice (XmdStringMap *map, ConstString key, void *value, void *data) {
|
||||||
|
(void)(map);
|
||||||
|
(void)(key);
|
||||||
|
(void)(data);
|
||||||
|
Device *this = value;
|
||||||
|
this->orphaned = True;
|
||||||
|
return True;
|
||||||
|
}
|
||||||
|
|
||||||
|
Bool transferDevice (XmdStringMap *map, ConstString key, void *value, void *data) {
|
||||||
|
(void)(map);
|
||||||
|
(void)(key);
|
||||||
|
(void)(data);
|
||||||
|
Device *this = value;
|
||||||
|
if (this->orphaned) {
|
||||||
|
DeviceFree(this);
|
||||||
|
} else {
|
||||||
|
XmdStringMapSet(devices, key, value);
|
||||||
|
}
|
||||||
|
return True;
|
||||||
|
}
|
||||||
|
|
||||||
void refreshDevices (void) {
|
void refreshDevices (void) {
|
||||||
XtUnmanageChild(container);
|
XtUnmanageChild(container);
|
||||||
|
|
||||||
pid_t child = 0;
|
/* pre-mark all devices as orphaned */
|
||||||
FILE *stream = XmdVaPipedExecPath (
|
XmdStringMapIterate(devices, markDevice, NULL);
|
||||||
"lsblk", &child, "r",
|
|
||||||
"", "-P", "-o", "NAME,TYPE,MOUNTPOINTS,LABEL", NULL);
|
/* refresh devices by category */
|
||||||
if (stream == NULL) {
|
refreshDisks();
|
||||||
/* TODO error */
|
|
||||||
return;
|
/* create a new map, only moving over extant devices */
|
||||||
}
|
XmdStringMap *oldMap = devices;
|
||||||
Device *device = NULL;
|
devices = XmdStringMapNew();
|
||||||
while (readBlockDevice(stream, &device) != EOF) {
|
XmdStringMapIterate(oldMap, transferDevice, NULL);
|
||||||
/* do something with device? */
|
XmdStringMapFree(oldMap);
|
||||||
}
|
|
||||||
fclose(stream);
|
|
||||||
waitpid(child, NULL, 0);
|
|
||||||
|
|
||||||
XtManageChild(container);
|
XtManageChild(container);
|
||||||
}
|
}
|
||||||
|
|
||||||
int readBlockDevice (FILE *stream, Device **device) {
|
String diskName (ConstString directory, ConstString name) {
|
||||||
DeviceKind kind = DeviceKindGeneric;
|
char fullpath[PATH_MAX];
|
||||||
String name = NULL;
|
snprintf(fullpath, XtNumber(fullpath), "%s/%s", directory, name);
|
||||||
String mountPoint = NULL;
|
char resolved[PATH_MAX];
|
||||||
String label = NULL;
|
return XtNewString(basename(realpath(fullpath, resolved)));
|
||||||
|
|
||||||
int ch = 0;
|
|
||||||
while (1) {
|
|
||||||
String key = NULL;
|
|
||||||
String value = NULL;
|
|
||||||
ch = readLsblkPair(stream, &key, &value);
|
|
||||||
|
|
||||||
if (strcmp(key, "NAME") == 0) {
|
|
||||||
XtFree(name);
|
|
||||||
name = value;
|
|
||||||
} else if (strcmp(key, "TYPE") == 0) {
|
|
||||||
if (strcmp(value, "disk") == 0) {
|
|
||||||
kind = DeviceKindDisk;
|
|
||||||
} else if (strcmp(value, "rom") == 0) {
|
|
||||||
kind = DeviceKindRom;
|
|
||||||
} else if (strcmp(value, "part") == 0) {
|
|
||||||
kind = DeviceKindFilesystem;
|
|
||||||
}
|
|
||||||
XtFree(value);
|
|
||||||
} else if (strcmp(key, "MOUNTPOINTS") == 0) {
|
|
||||||
XtFree(mountPoint);
|
|
||||||
mountPoint = value;
|
|
||||||
} else if (strcmp(key, "LABEL") == 0) {
|
|
||||||
XtFree(label);
|
|
||||||
label = value;
|
|
||||||
} else {
|
|
||||||
XtFree(value);
|
|
||||||
}
|
|
||||||
XtFree(key);
|
|
||||||
|
|
||||||
while ((ch = fgetc(stream)) == ' ');
|
|
||||||
if (ch == EOF || ch == '\n') break;
|
|
||||||
ungetc(ch, stream);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (name != NULL) {
|
|
||||||
*device = XmdStringMapGet(devices, name);
|
|
||||||
if (*device == NULL) {
|
|
||||||
*device = DeviceNew(name, kind);
|
|
||||||
} else {
|
|
||||||
DeviceSetKind(*device, kind);
|
|
||||||
}
|
|
||||||
DeviceSetMountPoint(*device, mountPoint);
|
|
||||||
DeviceSetLabel(*device, label);
|
|
||||||
}
|
|
||||||
|
|
||||||
XtFree(name);
|
|
||||||
XtFree(mountPoint);
|
|
||||||
XtFree(label);
|
|
||||||
return ch;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int readLsblkPair (FILE *stream, String *key, String *value) {
|
void refreshDisks (void) {
|
||||||
int ch = 0;
|
/* get disks */
|
||||||
int escapeCh = 0;
|
ConstString disksById = "/dev/disk/by-id";
|
||||||
char null = 0;
|
ConstString disksByLabel = "/dev/disk/by-label";
|
||||||
|
ConstString disksByPartuuid = "/dev/disk/by-partuuid";
|
||||||
|
|
||||||
*key = NULL;
|
struct dirent **entries = NULL;
|
||||||
*value = NULL;
|
int entriesCount = scandir(disksById, &entries, NULL, alphasort);
|
||||||
|
if (entriesCount < 0) {
|
||||||
XmdBuffer *keyBuffer = XmdBufferNew(char);
|
/* TODO error message */
|
||||||
while (isalpha(ch = fgetc(stream))) XmdBufferPush(keyBuffer, &ch);
|
return;
|
||||||
XmdBufferPush(keyBuffer, &null);
|
}
|
||||||
*key = XmdBufferBreak(keyBuffer);
|
for (int index = 0; index < entriesCount; index ++) {
|
||||||
|
struct dirent *entry = entries[index];
|
||||||
fgetc(stream); /* skip = */
|
if (entry->d_name[0] == '.') {
|
||||||
|
XtFree((char *)(entry));
|
||||||
XmdBuffer *valueBuffer = XmdBufferNew(char);
|
continue;
|
||||||
enum {
|
|
||||||
stateGetString,
|
|
||||||
stateGetEscape,
|
|
||||||
|
|
||||||
} state = stateGetString;
|
|
||||||
while (1) {
|
|
||||||
ch = fgetc(stream);
|
|
||||||
if (ch == EOF) goto end;
|
|
||||||
|
|
||||||
switch (state) {
|
|
||||||
case stateGetString:
|
|
||||||
switch (ch) {
|
|
||||||
case '"': goto end;
|
|
||||||
case '\\': state = stateGetEscape; break;
|
|
||||||
default: XmdBufferPush(valueBuffer, &ch); break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case stateGetEscape:
|
|
||||||
ch = fgetc(stream); /* skip x */
|
|
||||||
int digit = tolower(ch);
|
|
||||||
if (
|
|
||||||
(digit < '0' || digit > '9') &&
|
|
||||||
(digit < 'a' || digit > 'f')
|
|
||||||
) {
|
|
||||||
ungetc(ch, stream);
|
|
||||||
XmdBufferPush(valueBuffer, &escapeCh);
|
|
||||||
state = stateGetString;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
digit -= '0';
|
|
||||||
if (digit > 9) digit -= 'a' - '9' - 1;
|
|
||||||
escapeCh *= 16;
|
|
||||||
escapeCh += digit;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
String deviceName = diskName(disksById, entry->d_name);
|
||||||
|
XtFree((char *)(entry));
|
||||||
|
|
||||||
|
Device *device = XmdStringMapGet(devices, deviceName);
|
||||||
|
if (device == NULL) {
|
||||||
|
device = DeviceNew(deviceName, DeviceKindDisk);
|
||||||
|
} else {
|
||||||
|
device->orphaned = False;
|
||||||
|
DeviceSetKind(device, DeviceKindDisk);
|
||||||
|
}
|
||||||
|
|
||||||
|
XtFree(deviceName);
|
||||||
}
|
}
|
||||||
end:
|
XtFree((char *)(entries));
|
||||||
XmdBufferPush(valueBuffer, &null);
|
|
||||||
*value = XmdBufferBreak(valueBuffer);
|
/* determine disk types */
|
||||||
if (strlen(*value) == 0) {
|
DIR *dir = opendir(disksByPartuuid);
|
||||||
XtFree(*value);
|
if (dir == NULL) {
|
||||||
*value = NULL;
|
/* TODO error message */
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
return ch;
|
struct dirent *entry;
|
||||||
|
while ((entry = readdir(dir)) != NULL) {
|
||||||
|
if (entry->d_name[0] == '.') continue;
|
||||||
|
String deviceName = diskName(disksByPartuuid, entry->d_name);
|
||||||
|
Device *device = XmdStringMapGet(devices, deviceName);
|
||||||
|
if (device != NULL) DeviceSetKind(device, DeviceKindFilesystem);
|
||||||
|
XtFree(deviceName);
|
||||||
|
}
|
||||||
|
closedir(dir);
|
||||||
|
|
||||||
|
/* determine partition labels */
|
||||||
|
dir = opendir(disksByLabel);
|
||||||
|
if (dir == NULL) {
|
||||||
|
/* TODO error message */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
while ((entry = readdir(dir)) != NULL) {
|
||||||
|
if (entry->d_name[0] == '.') continue;
|
||||||
|
String deviceName = diskName(disksByLabel, entry->d_name);
|
||||||
|
Device *device = XmdStringMapGet(devices, deviceName);
|
||||||
|
if (device != NULL) DeviceSetLabel(device, entry->d_name);
|
||||||
|
XtFree(deviceName);
|
||||||
|
}
|
||||||
|
closedir(dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
Device *DeviceNew (String name, DeviceKind kind) {
|
Device *DeviceNew (String name, DeviceKind kind) {
|
||||||
@@ -247,10 +296,11 @@ Device *DeviceNew (String name, DeviceKind kind) {
|
|||||||
this->mountPoint = NULL;
|
this->mountPoint = NULL;
|
||||||
this->label = NULL;
|
this->label = NULL;
|
||||||
this->name = XtNewString(name);
|
this->name = XtNewString(name);
|
||||||
|
this->orphaned = False;
|
||||||
XmString string = XmStringCreateLocalized(name);
|
XmString string = XmStringCreateLocalized(name);
|
||||||
this->widget = XtVaCreateManagedWidget (
|
this->widget = XtVaCreateManagedWidget (
|
||||||
"device", xmIconGadgetClass, container,
|
"device", xmIconGadgetClass, container,
|
||||||
XmNalignment, XmALIGNMENT_CENTER,
|
XmNalignment, XmALIGNMENT_BEGINNING,
|
||||||
XmNlabelString, string,
|
XmNlabelString, string,
|
||||||
NULL);
|
NULL);
|
||||||
XmStringFree(string);
|
XmStringFree(string);
|
||||||
@@ -265,6 +315,7 @@ void DeviceDelete (ConstString name) {
|
|||||||
|
|
||||||
void DeviceFree (Device *this) {
|
void DeviceFree (Device *this) {
|
||||||
if (this == NULL) return;
|
if (this == NULL) return;
|
||||||
|
XtUnmanageChild(this->widget);
|
||||||
XtDestroyWidget(this->widget);
|
XtDestroyWidget(this->widget);
|
||||||
XtFree((char *)(this->name));
|
XtFree((char *)(this->name));
|
||||||
XtFree((char *)(this->mountPoint));
|
XtFree((char *)(this->mountPoint));
|
||||||
|
|||||||
2
xmfile/build.sh
Executable file
2
xmfile/build.sh
Executable file
@@ -0,0 +1,2 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
../scripts/buildapp.sh xmpackage "$@"
|
||||||
9
xmfile/src/icons/block-small.xbm
Normal file
9
xmfile/src/icons/block-small.xbm
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#define block_small_width 24
|
||||||
|
#define block_small_height 24
|
||||||
|
static unsigned char block_small_bits[] = {
|
||||||
|
0xff, 0xff, 0x0f, 0x01, 0x00, 0x10, 0x01, 0x3c, 0x20, 0x81, 0xc3, 0x41,
|
||||||
|
0xc1, 0x00, 0x83, 0x21, 0x00, 0x84, 0x11, 0x00, 0x88, 0x19, 0x00, 0x99,
|
||||||
|
0x09, 0x80, 0x90, 0x09, 0x40, 0x90, 0xe5, 0x00, 0xa0, 0x05, 0x1b, 0xa0,
|
||||||
|
0x05, 0xd8, 0xa0, 0x05, 0x00, 0xa7, 0x09, 0x02, 0x90, 0x09, 0x01, 0x90,
|
||||||
|
0x99, 0x0c, 0x98, 0x11, 0xf8, 0x88, 0x21, 0xe0, 0x8f, 0xc1, 0x80, 0xbf,
|
||||||
|
0x81, 0xc3, 0xbf, 0x01, 0x3c, 0xbc, 0x01, 0x00, 0x80, 0xff, 0xff, 0xff };
|
||||||
27
xmfile/src/icons/block.xbm
Normal file
27
xmfile/src/icons/block.xbm
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
#define block_width 48
|
||||||
|
#define block_height 48
|
||||||
|
static unsigned char block_bits[] = {
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0xfc, 0xff, 0xff, 0xff, 0xff, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x02,
|
||||||
|
0xf4, 0xff, 0xff, 0xff, 0xff, 0x04, 0x14, 0x00, 0xf0, 0x0f, 0x00, 0x09,
|
||||||
|
0xf4, 0xff, 0xff, 0xff, 0xff, 0x13, 0x14, 0x80, 0x0f, 0xf0, 0x01, 0x24,
|
||||||
|
0xf4, 0xff, 0x01, 0x80, 0xff, 0x2f, 0x14, 0x70, 0x00, 0x00, 0x0e, 0x28,
|
||||||
|
0xf4, 0x3f, 0x00, 0x00, 0xfc, 0x2f, 0x14, 0x0c, 0x00, 0x00, 0x30, 0x28,
|
||||||
|
0xf4, 0x07, 0x00, 0x00, 0xe0, 0x2f, 0x14, 0x07, 0x00, 0x00, 0xe4, 0x28,
|
||||||
|
0xf4, 0x03, 0x00, 0x00, 0xc2, 0x2f, 0x94, 0x01, 0x00, 0x00, 0x81, 0x29,
|
||||||
|
0xf4, 0x01, 0x00, 0x80, 0x80, 0x2f, 0xd4, 0x00, 0x00, 0x40, 0x00, 0x2b,
|
||||||
|
0xf4, 0x00, 0x00, 0x20, 0x30, 0x2f, 0xd4, 0x00, 0x00, 0x10, 0x0c, 0x2b,
|
||||||
|
0x74, 0x00, 0xc0, 0x03, 0x03, 0x2e, 0x74, 0x00, 0x60, 0xc5, 0x00, 0x2e,
|
||||||
|
0x74, 0x00, 0x30, 0x0a, 0x00, 0x2e, 0x74, 0x00, 0x90, 0x0d, 0x00, 0x2e,
|
||||||
|
0x74, 0x00, 0xb0, 0x09, 0x00, 0x2e, 0x74, 0x00, 0x50, 0x0c, 0x00, 0x2e,
|
||||||
|
0x74, 0x00, 0xa6, 0x06, 0x00, 0x2e, 0x74, 0xe0, 0xc1, 0x03, 0x00, 0x2e,
|
||||||
|
0xf4, 0x1c, 0x08, 0x00, 0x00, 0x2f, 0xd4, 0x00, 0x04, 0x00, 0x00, 0x2b,
|
||||||
|
0xf4, 0x00, 0x02, 0x00, 0x00, 0x2f, 0x94, 0x01, 0x01, 0x00, 0x80, 0x29,
|
||||||
|
0xf4, 0x81, 0xc0, 0x01, 0x80, 0x2f, 0x14, 0x43, 0x80, 0x0f, 0xc0, 0x28,
|
||||||
|
0xf4, 0x27, 0x00, 0xf6, 0xe0, 0x2f, 0x14, 0x06, 0x00, 0x18, 0x6f, 0x28,
|
||||||
|
0xf4, 0x0f, 0x00, 0x20, 0xf0, 0x2f, 0x14, 0x38, 0x00, 0xc0, 0x00, 0x2b,
|
||||||
|
0xf4, 0x7f, 0x00, 0x00, 0x43, 0x2e, 0x14, 0xe0, 0x01, 0x80, 0x87, 0x2a,
|
||||||
|
0xf4, 0xff, 0x0f, 0xf0, 0x1f, 0x2e, 0x14, 0x00, 0xfe, 0x7f, 0xe0, 0x29,
|
||||||
|
0xf4, 0xff, 0xff, 0xff, 0xff, 0x2f, 0xf4, 0xff, 0xff, 0xff, 0xff, 0x2f,
|
||||||
|
0x04, 0x00, 0x00, 0x00, 0x00, 0x20, 0xfc, 0xff, 0xff, 0xff, 0xff, 0x3f,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||||
9
xmfile/src/icons/character-small.xbm
Normal file
9
xmfile/src/icons/character-small.xbm
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#define character_small_width 24
|
||||||
|
#define character_small_height 24
|
||||||
|
static unsigned char character_small_bits[] = {
|
||||||
|
0x80, 0xff, 0x01, 0x40, 0x00, 0x02, 0x40, 0x00, 0x02, 0xf8, 0xff, 0x1f,
|
||||||
|
0x44, 0x00, 0x22, 0x44, 0x00, 0x22, 0xfc, 0xaa, 0x3e, 0x4c, 0x00, 0x32,
|
||||||
|
0x4c, 0x00, 0x32, 0x48, 0xff, 0x12, 0x48, 0x81, 0x12, 0x68, 0xff, 0x16,
|
||||||
|
0x68, 0x81, 0x16, 0xf8, 0x7e, 0x1f, 0x80, 0x81, 0x01, 0x00, 0xff, 0x00,
|
||||||
|
0x00, 0x3e, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x32, 0x00, 0x00, 0x26, 0x00,
|
||||||
|
0x00, 0x08, 0x00, 0x00, 0x32, 0x00, 0x00, 0x26, 0x00, 0x00, 0x14, 0x00 };
|
||||||
27
xmfile/src/icons/character.xbm
Normal file
27
xmfile/src/icons/character.xbm
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
#define character_width 48
|
||||||
|
#define character_height 48
|
||||||
|
static unsigned char character_bits[] = {
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0xe0, 0xff, 0xff, 0x07, 0x00, 0x00, 0x30, 0x00, 0x00, 0x0c, 0x00,
|
||||||
|
0x00, 0x30, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x30, 0x00, 0x20, 0x0d, 0x00,
|
||||||
|
0x00, 0x30, 0x00, 0x00, 0x0c, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x07,
|
||||||
|
0x30, 0x20, 0x00, 0x00, 0x04, 0x0c, 0x10, 0x20, 0x00, 0x00, 0x04, 0x08,
|
||||||
|
0x10, 0x20, 0x00, 0x00, 0x04, 0x08, 0x10, 0x20, 0x00, 0x00, 0x04, 0x08,
|
||||||
|
0x10, 0x20, 0x00, 0x00, 0x04, 0x08, 0x10, 0x20, 0x00, 0x00, 0x04, 0x08,
|
||||||
|
0x10, 0xf0, 0xff, 0xff, 0x0f, 0x08, 0xd0, 0xff, 0xff, 0xff, 0xff, 0x0b,
|
||||||
|
0xf0, 0x1f, 0x00, 0x00, 0xf8, 0x0f, 0x70, 0x18, 0x00, 0x00, 0x18, 0x0e,
|
||||||
|
0x70, 0x18, 0x00, 0x00, 0x18, 0x0e, 0x60, 0x98, 0xff, 0xff, 0x19, 0x06,
|
||||||
|
0x40, 0x98, 0x00, 0x00, 0x19, 0x02, 0x40, 0x98, 0xff, 0xff, 0x19, 0x02,
|
||||||
|
0xc0, 0x9c, 0x00, 0x00, 0x39, 0x03, 0xc0, 0x9c, 0xff, 0xff, 0x39, 0x03,
|
||||||
|
0xc0, 0x9c, 0x00, 0x00, 0x39, 0x03, 0x80, 0x34, 0xff, 0xff, 0x2c, 0x01,
|
||||||
|
0x80, 0x74, 0x02, 0x40, 0x2e, 0x01, 0x80, 0xe7, 0xfc, 0x3f, 0xe7, 0x01,
|
||||||
|
0x80, 0xc7, 0x01, 0x80, 0xe3, 0x01, 0x00, 0x83, 0xff, 0xff, 0xc1, 0x00,
|
||||||
|
0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x7f, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x0c, 0x30, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x1f, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x58, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x98, 0x1c, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x38, 0x19, 0x00, 0x00, 0x00, 0x00, 0x58, 0x1a, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x98, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x38, 0x19, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x58, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x90, 0x14, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x38, 0x19, 0x00, 0x00, 0x00, 0x00, 0x48, 0x0a, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x90, 0x14, 0x00, 0x00, 0x00, 0x00, 0x28, 0x09, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||||
9
xmfile/src/icons/directory-small.xbm
Normal file
9
xmfile/src/icons/directory-small.xbm
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#define directory_small_width 24
|
||||||
|
#define directory_small_height 24
|
||||||
|
static unsigned char directory_small_bits[] = {
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x01, 0x00, 0x56, 0xff, 0x1f,
|
||||||
|
0xaa, 0xaa, 0x2a, 0xfe, 0xff, 0x7f, 0x02, 0x00, 0x40, 0x02, 0x00, 0x40,
|
||||||
|
0x02, 0x00, 0x40, 0x02, 0x00, 0x40, 0x02, 0x00, 0x40, 0x02, 0x00, 0x40,
|
||||||
|
0x02, 0x00, 0x40, 0x02, 0x00, 0x40, 0x02, 0x00, 0x40, 0x02, 0x00, 0x40,
|
||||||
|
0x02, 0x00, 0x40, 0x02, 0x00, 0x40, 0x02, 0x00, 0x40, 0xfa, 0xff, 0x5f,
|
||||||
|
0x02, 0x00, 0x40, 0xfe, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||||
27
xmfile/src/icons/directory.xbm
Normal file
27
xmfile/src/icons/directory.xbm
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
#define directory_width 48
|
||||||
|
#define directory_height 48
|
||||||
|
static unsigned char directory_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, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x07, 0x00, 0x00, 0x00,
|
||||||
|
0xf8, 0xff, 0x0f, 0x00, 0x00, 0x00, 0xb8, 0xaa, 0xfe, 0xff, 0xff, 0x0f,
|
||||||
|
0x58, 0x55, 0xfd, 0xff, 0xff, 0x1f, 0xb8, 0xaa, 0xaa, 0xaa, 0xaa, 0x1a,
|
||||||
|
0xf8, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xfc, 0xff, 0xff, 0xff, 0xff, 0x3f,
|
||||||
|
0x0c, 0x00, 0x00, 0x00, 0x00, 0x30, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x30,
|
||||||
|
0x0c, 0x00, 0x00, 0x00, 0x00, 0x30, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x30,
|
||||||
|
0x0c, 0x00, 0x00, 0x00, 0x00, 0x30, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x30,
|
||||||
|
0x0c, 0x00, 0x00, 0x00, 0x00, 0x30, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x30,
|
||||||
|
0x0c, 0x00, 0x00, 0x00, 0x00, 0x30, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x30,
|
||||||
|
0x0c, 0x00, 0x00, 0x00, 0x00, 0x30, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x30,
|
||||||
|
0x0c, 0x00, 0x00, 0x00, 0x00, 0x30, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x30,
|
||||||
|
0x0c, 0x00, 0x00, 0x00, 0x00, 0x30, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x30,
|
||||||
|
0x0c, 0x00, 0x00, 0x00, 0x00, 0x30, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x30,
|
||||||
|
0x0c, 0x00, 0x00, 0x00, 0x00, 0x30, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x30,
|
||||||
|
0x0c, 0x00, 0x00, 0x00, 0x00, 0x30, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x30,
|
||||||
|
0x0c, 0x00, 0x00, 0x00, 0x00, 0x30, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x30,
|
||||||
|
0x0c, 0x00, 0x00, 0x00, 0x00, 0x30, 0xec, 0xff, 0xff, 0xff, 0xff, 0x37,
|
||||||
|
0x0c, 0x00, 0x00, 0x00, 0x00, 0x30, 0xec, 0xff, 0xff, 0xff, 0xff, 0x37,
|
||||||
|
0x0c, 0x00, 0x00, 0x00, 0x00, 0x30, 0xfc, 0xff, 0xff, 0xff, 0xff, 0x3f,
|
||||||
|
0xf8, 0xff, 0xff, 0xff, 0xff, 0x1f, 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, 0x00 };
|
||||||
9
xmfile/src/icons/file-small.xbm
Normal file
9
xmfile/src/icons/file-small.xbm
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#define file_small_width 24
|
||||||
|
#define file_small_height 24
|
||||||
|
static unsigned char file_small_bits[] = {
|
||||||
|
0x00, 0x00, 0x00, 0xf0, 0xff, 0x00, 0x10, 0x80, 0x01, 0x10, 0x80, 0x02,
|
||||||
|
0x90, 0xaf, 0x04, 0x10, 0x80, 0x0f, 0x90, 0x3b, 0x08, 0x10, 0x00, 0x08,
|
||||||
|
0x10, 0x00, 0x08, 0x10, 0x00, 0x08, 0x10, 0x00, 0x08, 0x10, 0x00, 0x08,
|
||||||
|
0x10, 0x00, 0x08, 0x10, 0x00, 0x08, 0x10, 0x00, 0x08, 0x10, 0x00, 0x08,
|
||||||
|
0x10, 0x00, 0x08, 0x10, 0x00, 0x08, 0x10, 0x00, 0x08, 0x10, 0x00, 0x08,
|
||||||
|
0x10, 0x00, 0x08, 0x10, 0x00, 0x08, 0xf0, 0xff, 0x0f, 0x00, 0x00, 0x00 };
|
||||||
27
xmfile/src/icons/file.xbm
Normal file
27
xmfile/src/icons/file.xbm
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
#define file_width 48
|
||||||
|
#define file_height 48
|
||||||
|
static unsigned char file_bits[] = {
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0xff, 0xff, 0xff, 0x03, 0x00,
|
||||||
|
0x00, 0x03, 0x00, 0x00, 0x07, 0x00, 0x00, 0x03, 0x00, 0x00, 0x0d, 0x00,
|
||||||
|
0x00, 0x03, 0x00, 0x00, 0x19, 0x00, 0x00, 0x03, 0x00, 0x00, 0x31, 0x00,
|
||||||
|
0x00, 0x03, 0x00, 0x00, 0x61, 0x00, 0x00, 0xc3, 0xff, 0x2b, 0xff, 0x00,
|
||||||
|
0x00, 0x03, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xc3, 0xf7, 0x3f, 0xc0, 0x00,
|
||||||
|
0x00, 0x03, 0x00, 0x00, 0xc0, 0x00, 0x00, 0xc3, 0xfb, 0x37, 0xc0, 0x00,
|
||||||
|
0x00, 0x03, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x03, 0x00, 0x00, 0xc0, 0x00,
|
||||||
|
0x00, 0x03, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x03, 0x00, 0x00, 0xc0, 0x00,
|
||||||
|
0x00, 0x03, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x03, 0x00, 0x00, 0xc0, 0x00,
|
||||||
|
0x00, 0x03, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x03, 0x00, 0x00, 0xc0, 0x00,
|
||||||
|
0x00, 0x03, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x03, 0x00, 0x00, 0xc0, 0x00,
|
||||||
|
0x00, 0x03, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x03, 0x00, 0x00, 0xc0, 0x00,
|
||||||
|
0x00, 0x03, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x03, 0x00, 0x00, 0xc0, 0x00,
|
||||||
|
0x00, 0x03, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x03, 0x00, 0x00, 0xc0, 0x00,
|
||||||
|
0x00, 0x03, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x03, 0x00, 0x00, 0xc0, 0x00,
|
||||||
|
0x00, 0x03, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x03, 0x00, 0x00, 0xc0, 0x00,
|
||||||
|
0x00, 0x03, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x03, 0x00, 0x00, 0xc0, 0x00,
|
||||||
|
0x00, 0x03, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x03, 0x00, 0x00, 0xc0, 0x00,
|
||||||
|
0x00, 0x03, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x03, 0x00, 0x00, 0xc0, 0x00,
|
||||||
|
0x00, 0x03, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x03, 0x00, 0x00, 0xc0, 0x00,
|
||||||
|
0x00, 0x03, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x03, 0x00, 0x00, 0xc0, 0x00,
|
||||||
|
0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||||
27
xmfile/src/icons/icon.xbm
Normal file
27
xmfile/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, 0xfe, 0xff, 0xff, 0x7f, 0x00, 0x00, 0xfe, 0xff, 0xff, 0x7f, 0x00,
|
||||||
|
0x00, 0x06, 0x00, 0x00, 0x60, 0x00, 0x00, 0xf6, 0xff, 0xff, 0x6f, 0x00,
|
||||||
|
0x00, 0x16, 0x00, 0x00, 0x68, 0x00, 0x00, 0x56, 0x00, 0x00, 0x6a, 0x00,
|
||||||
|
0x00, 0x16, 0x00, 0x00, 0x68, 0x00, 0x00, 0x16, 0x00, 0x00, 0x68, 0x00,
|
||||||
|
0x00, 0x16, 0x00, 0x00, 0x68, 0x00, 0x00, 0x16, 0xf8, 0x1f, 0x68, 0x00,
|
||||||
|
0x00, 0x16, 0x08, 0x10, 0x68, 0x00, 0x00, 0x16, 0x08, 0x10, 0x68, 0x00,
|
||||||
|
0x00, 0x16, 0xf8, 0x1f, 0x68, 0x00, 0x00, 0x16, 0x00, 0x00, 0x68, 0x00,
|
||||||
|
0x00, 0x16, 0x08, 0x10, 0x68, 0x00, 0x00, 0x16, 0xf8, 0x1f, 0x68, 0x00,
|
||||||
|
0x00, 0x16, 0x00, 0x00, 0x68, 0x00, 0x00, 0x16, 0x00, 0x00, 0x68, 0x00,
|
||||||
|
0x00, 0x56, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x16, 0x00, 0x00, 0x68, 0x00,
|
||||||
|
0x00, 0xf6, 0xff, 0xff, 0x6f, 0x00, 0x00, 0x06, 0x00, 0x00, 0x60, 0x00,
|
||||||
|
0x00, 0xf6, 0xff, 0xff, 0x6f, 0x00, 0x00, 0x36, 0x00, 0x00, 0x6c, 0x00,
|
||||||
|
0x00, 0xf6, 0xff, 0xff, 0x6f, 0x00, 0x00, 0x36, 0x00, 0x00, 0x6c, 0x00,
|
||||||
|
0x00, 0xf6, 0xff, 0xff, 0x6f, 0x00, 0x00, 0x16, 0x00, 0x00, 0x68, 0x00,
|
||||||
|
0x00, 0x56, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x16, 0x00, 0x00, 0x68, 0x00,
|
||||||
|
0x00, 0x16, 0x00, 0x00, 0x68, 0x00, 0x00, 0x16, 0x00, 0x00, 0x68, 0x00,
|
||||||
|
0x00, 0x16, 0xf8, 0x1f, 0x68, 0x00, 0x00, 0x16, 0x08, 0x10, 0x68, 0x00,
|
||||||
|
0x00, 0x16, 0x08, 0x10, 0x68, 0x00, 0x00, 0x16, 0xf8, 0x1f, 0x68, 0x00,
|
||||||
|
0x00, 0x16, 0x00, 0x00, 0x68, 0x00, 0x00, 0x16, 0x08, 0x10, 0x68, 0x00,
|
||||||
|
0x00, 0x16, 0xf8, 0x1f, 0x68, 0x00, 0x00, 0x16, 0x00, 0x00, 0x68, 0x00,
|
||||||
|
0x00, 0x16, 0x00, 0x00, 0x68, 0x00, 0x00, 0x56, 0x00, 0x00, 0x6a, 0x00,
|
||||||
|
0x00, 0x1e, 0x00, 0x00, 0x78, 0x00, 0x00, 0xfe, 0xff, 0xff, 0x7f, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||||
9
xmfile/src/icons/link-small.xbm
Normal file
9
xmfile/src/icons/link-small.xbm
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#define link_small_width 24
|
||||||
|
#define link_small_height 24
|
||||||
|
static unsigned char link_small_bits[] = {
|
||||||
|
0x00, 0x00, 0x0c, 0x00, 0x00, 0x33, 0x00, 0x80, 0x4c, 0x00, 0x40, 0x52,
|
||||||
|
0x00, 0x20, 0xa1, 0x00, 0x90, 0xa0, 0x00, 0x48, 0xa0, 0x00, 0x24, 0x90,
|
||||||
|
0x00, 0x12, 0x48, 0x00, 0x79, 0x24, 0x80, 0x95, 0x12, 0x40, 0xa5, 0x09,
|
||||||
|
0x20, 0x45, 0x05, 0x90, 0x4a, 0x03, 0x48, 0xb2, 0x01, 0x24, 0x9c, 0x00,
|
||||||
|
0x12, 0x48, 0x00, 0x0a, 0x24, 0x00, 0x05, 0x12, 0x00, 0x05, 0x09, 0x00,
|
||||||
|
0x8a, 0x04, 0x00, 0x72, 0x02, 0x00, 0x0c, 0x01, 0x00, 0xf0, 0x00, 0x00 };
|
||||||
27
xmfile/src/icons/link.xbm
Normal file
27
xmfile/src/icons/link.xbm
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
#define link_width 48
|
||||||
|
#define link_height 48
|
||||||
|
static unsigned char link_bits[] = {
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x01,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x87, 0x07, 0x00, 0x00, 0x00, 0x80, 0x01, 0x0e,
|
||||||
|
0x00, 0x00, 0x00, 0xc0, 0x70, 0x18, 0x00, 0x00, 0x00, 0x60, 0xdc, 0x31,
|
||||||
|
0x00, 0x00, 0x00, 0x30, 0x06, 0x33, 0x00, 0x00, 0x00, 0x18, 0x03, 0x66,
|
||||||
|
0x00, 0x00, 0x00, 0x8c, 0x01, 0x64, 0x00, 0x00, 0x00, 0xc6, 0x00, 0xcc,
|
||||||
|
0x00, 0x00, 0x00, 0x63, 0x00, 0xc8, 0x00, 0x00, 0x80, 0x31, 0x00, 0xcc,
|
||||||
|
0x00, 0x00, 0xc0, 0x18, 0x00, 0xc4, 0x00, 0x00, 0x60, 0x0c, 0x00, 0x66,
|
||||||
|
0x00, 0x00, 0x30, 0x06, 0x00, 0x63, 0x00, 0x00, 0x18, 0x03, 0x80, 0x31,
|
||||||
|
0x00, 0x00, 0x8c, 0x03, 0xc0, 0x18, 0x00, 0x00, 0xc6, 0x0f, 0x60, 0x0c,
|
||||||
|
0x00, 0x00, 0xe3, 0x1d, 0x30, 0x06, 0x00, 0x80, 0xf3, 0x30, 0x18, 0x03,
|
||||||
|
0x00, 0xc0, 0xb1, 0x63, 0x8c, 0x01, 0x00, 0xe0, 0x19, 0x66, 0xc6, 0x00,
|
||||||
|
0x00, 0xb0, 0x09, 0xcc, 0x63, 0x00, 0x00, 0x98, 0x19, 0xc8, 0x31, 0x00,
|
||||||
|
0x00, 0x8c, 0x13, 0x98, 0x19, 0x00, 0x00, 0xc6, 0x33, 0x90, 0x0f, 0x00,
|
||||||
|
0x00, 0x63, 0x66, 0x98, 0x07, 0x00, 0x80, 0x31, 0xc6, 0x89, 0x03, 0x00,
|
||||||
|
0xc0, 0x18, 0x0c, 0xcf, 0x01, 0x00, 0x60, 0x0c, 0x38, 0xc7, 0x00, 0x00,
|
||||||
|
0x30, 0x06, 0xf0, 0x63, 0x00, 0x00, 0x18, 0x03, 0xc0, 0x31, 0x00, 0x00,
|
||||||
|
0x8c, 0x01, 0xc0, 0x18, 0x00, 0x00, 0xc6, 0x00, 0x60, 0x0c, 0x00, 0x00,
|
||||||
|
0x66, 0x00, 0x30, 0x06, 0x00, 0x00, 0x23, 0x00, 0x18, 0x03, 0x00, 0x00,
|
||||||
|
0x33, 0x00, 0x8c, 0x01, 0x00, 0x00, 0x13, 0x00, 0xc6, 0x00, 0x00, 0x00,
|
||||||
|
0x33, 0x00, 0x63, 0x00, 0x00, 0x00, 0x26, 0x80, 0x31, 0x00, 0x00, 0x00,
|
||||||
|
0x66, 0xc0, 0x18, 0x00, 0x00, 0x00, 0xcc, 0x60, 0x0c, 0x00, 0x00, 0x00,
|
||||||
|
0x8c, 0x3b, 0x06, 0x00, 0x00, 0x00, 0x18, 0x0e, 0x03, 0x00, 0x00, 0x00,
|
||||||
|
0x70, 0x80, 0x01, 0x00, 0x00, 0x00, 0xe0, 0xe1, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x80, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00 };
|
||||||
9
xmfile/src/icons/pipe-small.xbm
Normal file
9
xmfile/src/icons/pipe-small.xbm
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#define pipe_small_width 24
|
||||||
|
#define pipe_small_height 24
|
||||||
|
static unsigned char pipe_small_bits[] = {
|
||||||
|
0x00, 0x00, 0xff, 0x00, 0x00, 0x81, 0x00, 0x00, 0xa1, 0x00, 0x00, 0x81,
|
||||||
|
0x00, 0x00, 0xff, 0x00, 0x00, 0x52, 0x00, 0x00, 0x52, 0x00, 0x00, 0x52,
|
||||||
|
0x00, 0x7e, 0x52, 0xe0, 0xc3, 0x51, 0x18, 0x42, 0x40, 0x04, 0x42, 0x28,
|
||||||
|
0x84, 0x52, 0x23, 0x22, 0x5a, 0x18, 0x82, 0xc3, 0x07, 0x52, 0x7e, 0x00,
|
||||||
|
0x52, 0x00, 0x00, 0x52, 0x00, 0x00, 0x52, 0x00, 0x00, 0xff, 0x00, 0x00,
|
||||||
|
0x81, 0x00, 0x00, 0xa1, 0x00, 0x00, 0x81, 0x00, 0x00, 0xff, 0x00, 0x00 };
|
||||||
27
xmfile/src/icons/pipe.xbm
Normal file
27
xmfile/src/icons/pipe.xbm
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
#define pipe_width 48
|
||||||
|
#define pipe_height 48
|
||||||
|
static unsigned char pipe_bits[] = {
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0x7f,
|
||||||
|
0x00, 0x00, 0x00, 0x80, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x80, 0x01, 0x60,
|
||||||
|
0x00, 0x00, 0x00, 0x80, 0x01, 0x6d, 0x00, 0x00, 0x00, 0x80, 0x01, 0x6e,
|
||||||
|
0x00, 0x00, 0x00, 0x80, 0x41, 0x6d, 0x00, 0x00, 0x00, 0x80, 0x01, 0x60,
|
||||||
|
0x00, 0x00, 0x00, 0x80, 0x57, 0x7d, 0x00, 0x00, 0x00, 0x80, 0x03, 0x70,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x03, 0x34, 0x00, 0x00, 0x00, 0x00, 0x03, 0x34,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x03, 0x34, 0x00, 0x00, 0x00, 0x00, 0x03, 0x34,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x03, 0x34, 0x00, 0x00, 0x00, 0x00, 0x03, 0x34,
|
||||||
|
0x00, 0x00, 0xf8, 0x1f, 0x03, 0x34, 0x00, 0xf8, 0xff, 0xff, 0x03, 0x34,
|
||||||
|
0x00, 0xff, 0x1f, 0xf8, 0x01, 0x34, 0xc0, 0x07, 0x18, 0x18, 0x00, 0x34,
|
||||||
|
0xe0, 0x00, 0x10, 0x08, 0x00, 0x34, 0x70, 0x00, 0x18, 0x18, 0x00, 0x32,
|
||||||
|
0x30, 0x00, 0x10, 0x08, 0x00, 0x1a, 0x18, 0x00, 0x18, 0x18, 0x00, 0x18,
|
||||||
|
0x18, 0x00, 0x10, 0x0a, 0x00, 0x19, 0x18, 0x00, 0x58, 0x19, 0x80, 0x0c,
|
||||||
|
0x0c, 0x00, 0x90, 0x0a, 0x30, 0x0e, 0x0c, 0x80, 0xdf, 0xfb, 0x0f, 0x07,
|
||||||
|
0x0c, 0x20, 0xd0, 0x0b, 0xe0, 0x03, 0x0c, 0x80, 0x1f, 0xf8, 0xff, 0x00,
|
||||||
|
0x0c, 0xd0, 0xff, 0xff, 0x1f, 0x00, 0x0c, 0xd0, 0xf8, 0x1f, 0x00, 0x00,
|
||||||
|
0x0c, 0xd0, 0x00, 0x00, 0x00, 0x00, 0x0c, 0xd0, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x0c, 0xd0, 0x00, 0x00, 0x00, 0x00, 0x0c, 0xd0, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x0c, 0xd0, 0x00, 0x00, 0x00, 0x00, 0x0c, 0xd0, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0xee, 0xff, 0x01, 0x00, 0x00, 0x00, 0x5e, 0xf5, 0x01, 0x00, 0x00, 0x00,
|
||||||
|
0x06, 0x80, 0x01, 0x00, 0x00, 0x00, 0x06, 0xb4, 0x01, 0x00, 0x00, 0x00,
|
||||||
|
0x06, 0xb8, 0x01, 0x00, 0x00, 0x00, 0x06, 0xb5, 0x01, 0x00, 0x00, 0x00,
|
||||||
|
0x06, 0x80, 0x01, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x01, 0x00, 0x00, 0x00,
|
||||||
|
0xfe, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||||
9
xmfile/src/icons/socket-small.xbm
Normal file
9
xmfile/src/icons/socket-small.xbm
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#define socket_small_width 24
|
||||||
|
#define socket_small_height 24
|
||||||
|
static unsigned char socket_small_bits[] = {
|
||||||
|
0x00, 0x41, 0x00, 0x00, 0x51, 0x00, 0x00, 0x41, 0x00, 0x00, 0x51, 0x00,
|
||||||
|
0x00, 0x51, 0x00, 0x00, 0x51, 0x00, 0x00, 0x51, 0x00, 0x80, 0xd1, 0x00,
|
||||||
|
0xc0, 0xc1, 0x01, 0xc0, 0xa2, 0x01, 0x40, 0x5d, 0x01, 0x40, 0x3e, 0x01,
|
||||||
|
0x80, 0x80, 0x00, 0x00, 0x51, 0x00, 0x00, 0x41, 0x00, 0x00, 0x51, 0x00,
|
||||||
|
0x00, 0x51, 0x00, 0x00, 0x51, 0x00, 0x00, 0x41, 0x00, 0x80, 0xff, 0x00,
|
||||||
|
0x80, 0x80, 0x00, 0x80, 0xb8, 0x00, 0x80, 0x80, 0x00, 0x80, 0xff, 0x00 };
|
||||||
27
xmfile/src/icons/socket.xbm
Normal file
27
xmfile/src/icons/socket.xbm
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
#define socket_width 48
|
||||||
|
#define socket_height 48
|
||||||
|
static unsigned char socket_bits[] = {
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x04, 0x40, 0x00, 0x00, 0x00, 0x00, 0x02, 0x28, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x06, 0x60, 0x00, 0x00, 0x00, 0x00, 0x04, 0x48, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x06, 0x68, 0x00, 0x00, 0x00, 0x00, 0x06, 0x68, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x06, 0x68, 0x00, 0x00, 0x00, 0x00, 0x06, 0x68, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x06, 0x68, 0x00, 0x00, 0x00, 0x00, 0x06, 0x68, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x06, 0x68, 0x00, 0x00, 0x00, 0x00, 0x06, 0x68, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x07, 0xe8, 0x00, 0x00, 0x00, 0x80, 0x06, 0x68, 0x01, 0x00,
|
||||||
|
0x00, 0xc0, 0x07, 0xe8, 0x03, 0x00, 0x00, 0xe0, 0x06, 0x68, 0x07, 0x00,
|
||||||
|
0x00, 0xb0, 0x07, 0xe4, 0x0d, 0x00, 0x00, 0xb0, 0x0c, 0x32, 0x0d, 0x00,
|
||||||
|
0x00, 0x30, 0x1f, 0xf8, 0x0c, 0x00, 0x00, 0x30, 0xf3, 0xcf, 0x0c, 0x00,
|
||||||
|
0x00, 0x60, 0xfe, 0x7f, 0x06, 0x00, 0x00, 0x60, 0x0c, 0x30, 0x06, 0x00,
|
||||||
|
0x00, 0xc0, 0xf0, 0x0f, 0x03, 0x00, 0x00, 0x80, 0x01, 0x80, 0x03, 0x00,
|
||||||
|
0x00, 0x00, 0x03, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x06, 0x68, 0x00, 0x00, 0x00, 0x00, 0x06, 0x68, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x06, 0x68, 0x00, 0x00, 0x00, 0x00, 0x06, 0x68, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x06, 0x68, 0x00, 0x00, 0x00, 0x00, 0x06, 0x68, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x06, 0x68, 0x00, 0x00, 0x00, 0x00, 0x06, 0x68, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x06, 0x68, 0x00, 0x00, 0x00, 0x00, 0x06, 0x68, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0xf7, 0xff, 0x00, 0x00, 0x00, 0x00, 0xaf, 0xfa, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x03, 0xda, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x03, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x83, 0xda, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||||
386
xmfile/src/main.c
Normal file
386
xmfile/src/main.c
Normal file
@@ -0,0 +1,386 @@
|
|||||||
|
#define _XOPEN_SOURCE 700
|
||||||
|
|
||||||
|
#include <Xm/Xm.h>
|
||||||
|
#include <Xm/Form.h>
|
||||||
|
#include <Xm/PushB.h>
|
||||||
|
#include <Xm/MainW.h>
|
||||||
|
#include <Xm/IconG.h>
|
||||||
|
#include <Xm/Container.h>
|
||||||
|
#include <Xm/ScrolledW.h>
|
||||||
|
|
||||||
|
#include <Xmd/Icon.h>
|
||||||
|
#include <Xmd/Exec.h>
|
||||||
|
#include <Xmd/Buffer.h>
|
||||||
|
#include <Xmd/StringMap.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <libgen.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#include "icons/icon.xbm"
|
||||||
|
#include "icons/directory.xbm"
|
||||||
|
#include "icons/directory-small.xbm"
|
||||||
|
#include "icons/file.xbm"
|
||||||
|
#include "icons/file-small.xbm"
|
||||||
|
#include "icons/link.xbm"
|
||||||
|
#include "icons/link-small.xbm"
|
||||||
|
#include "icons/block.xbm"
|
||||||
|
#include "icons/block-small.xbm"
|
||||||
|
#include "icons/character.xbm"
|
||||||
|
#include "icons/character-small.xbm"
|
||||||
|
#include "icons/socket.xbm"
|
||||||
|
#include "icons/socket-small.xbm"
|
||||||
|
#include "icons/pipe.xbm"
|
||||||
|
#include "icons/pipe-small.xbm"
|
||||||
|
|
||||||
|
static XtAppContext application;
|
||||||
|
static XmdStringMap *trailFiles;
|
||||||
|
static XmdStringMap *viewFiles;
|
||||||
|
static Widget topLevel;
|
||||||
|
static Widget viewContainer;
|
||||||
|
static Widget trailContainer;
|
||||||
|
static Pixmap iconPixmap;
|
||||||
|
static Pixmap iconsLarge[7] = { 0 };
|
||||||
|
static Pixmap iconsSmall[7] = { 0 };
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
FileKindFile,
|
||||||
|
FileKindDirectory,
|
||||||
|
FileKindLink,
|
||||||
|
FileKindBlock,
|
||||||
|
FileKindCharacter,
|
||||||
|
FileKindSocket,
|
||||||
|
FileKindPipe
|
||||||
|
} FileKind;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
Widget widget;
|
||||||
|
FileKind kind;
|
||||||
|
String name;
|
||||||
|
String label;
|
||||||
|
String path;
|
||||||
|
} File;
|
||||||
|
|
||||||
|
void loadIconPixmaps (void);
|
||||||
|
int refreshDirectory ();
|
||||||
|
int makeTrailIn (ConstString path);
|
||||||
|
int makeFilesIn (ConstString directory, Bool showHidden);
|
||||||
|
int changeDirectory (ConstString path);
|
||||||
|
void handleActivate (Widget, XtPointer, XtPointer);
|
||||||
|
FileKind fileKind (ConstString path);
|
||||||
|
File * FileNew (XmdStringMap *set, Widget container, String name, ConstString path);
|
||||||
|
File * FileOfWidget (Widget widget);
|
||||||
|
void FileDelete (XmdStringMap *set, ConstString name);
|
||||||
|
void FileFree (File *this);
|
||||||
|
void FileSetLabel (File *this, ConstString label);
|
||||||
|
|
||||||
|
int main (int argc, char *argv[]) {
|
||||||
|
trailFiles = XmdStringMapNew();
|
||||||
|
viewFiles = XmdStringMapNew();
|
||||||
|
|
||||||
|
topLevel = XtVaAppInitialize (
|
||||||
|
&application, "FileBrowser",
|
||||||
|
NULL, 0,
|
||||||
|
&argc, argv,
|
||||||
|
NULL,
|
||||||
|
XmNtitle, "File Browser",
|
||||||
|
XmNiconName, "File Browser",
|
||||||
|
XmNwidth, 400,
|
||||||
|
XmNheight, 300,
|
||||||
|
NULL);
|
||||||
|
Widget window = XtVaCreateManagedWidget (
|
||||||
|
"window", xmMainWindowWidgetClass, topLevel,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
/* menu bar */
|
||||||
|
XmString fileString = XmStringCreateLocalized("File");
|
||||||
|
XmString helpString = XmStringCreateLocalized("Help");
|
||||||
|
Widget menuBar = XmVaCreateSimpleMenuBar (
|
||||||
|
window, "menuBar",
|
||||||
|
XmVaCASCADEBUTTON, fileString, 'F',
|
||||||
|
XmVaCASCADEBUTTON, helpString, 'H',
|
||||||
|
NULL);
|
||||||
|
XmStringFree(fileString);
|
||||||
|
XmStringFree(helpString);
|
||||||
|
XtManageChild(menuBar);
|
||||||
|
|
||||||
|
/* layout form */
|
||||||
|
Widget layout = XtVaCreateWidget (
|
||||||
|
"layout", xmFormWidgetClass, window,
|
||||||
|
XmNorientation, XmVERTICAL,
|
||||||
|
NULL);
|
||||||
|
iconPixmap = XmdLoadBitmapIcon(layout, icon);
|
||||||
|
XtVaSetValues (
|
||||||
|
topLevel,
|
||||||
|
XmNiconPixmap, iconPixmap,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
/* trail container */
|
||||||
|
Widget trailScroller = XtVaCreateWidget (
|
||||||
|
"trailScroller", xmScrolledWindowWidgetClass, layout,
|
||||||
|
XmNscrollingPolicy, XmAUTOMATIC,
|
||||||
|
XmNscrolledWindowChildType, XmSCROLL_HOR,
|
||||||
|
XmNleftAttachment, XmATTACH_FORM,
|
||||||
|
XmNtopAttachment, XmATTACH_FORM,
|
||||||
|
XmNrightAttachment, XmATTACH_FORM,
|
||||||
|
NULL);
|
||||||
|
trailContainer = XtVaCreateManagedWidget (
|
||||||
|
"trailContainer", xmContainerWidgetClass, trailScroller,
|
||||||
|
XmNlayoutType, XmOUTLINE,
|
||||||
|
XmNentryViewType, XmSMALL_ICON,
|
||||||
|
NULL);
|
||||||
|
XtAddCallback (
|
||||||
|
trailContainer, XmNdefaultActionCallback,
|
||||||
|
handleActivate,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
/* file object container */
|
||||||
|
Widget viewScroller = XtVaCreateWidget (
|
||||||
|
"viewScroller", xmScrolledWindowWidgetClass, layout,
|
||||||
|
XmNscrollingPolicy, XmAUTOMATIC,
|
||||||
|
XmNscrolledWindowChildType, XmSCROLL_VERT,
|
||||||
|
XmNleftAttachment, XmATTACH_FORM,
|
||||||
|
XmNtopAttachment, XmATTACH_WIDGET,
|
||||||
|
XmNtopWidget, trailScroller,
|
||||||
|
XmNrightAttachment, XmATTACH_FORM,
|
||||||
|
XmNbottomAttachment, XmATTACH_FORM,
|
||||||
|
NULL);
|
||||||
|
viewContainer = XtVaCreateManagedWidget (
|
||||||
|
"viewContainer", xmContainerWidgetClass, viewScroller,
|
||||||
|
XmNlayoutType, XmSPATIAL,
|
||||||
|
XmNspatialStyle, XmGRID,
|
||||||
|
XmNspatialIncludeModel, XmFIRST_FIT,
|
||||||
|
XmNspatialResizeModel, XmGROW_MINOR,
|
||||||
|
NULL);
|
||||||
|
XtAddCallback (
|
||||||
|
viewContainer, XmNdefaultActionCallback,
|
||||||
|
handleActivate,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
loadIconPixmaps();
|
||||||
|
refreshDirectory();
|
||||||
|
|
||||||
|
XtManageChild(viewScroller);
|
||||||
|
XtManageChild(trailScroller);
|
||||||
|
XtManageChild(layout);
|
||||||
|
|
||||||
|
XtVaSetValues (
|
||||||
|
window,
|
||||||
|
XmNmenuBar, menuBar,
|
||||||
|
XmNworkWindow, layout,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
XtRealizeWidget(topLevel);
|
||||||
|
XtAppMainLoop(application);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loadIconPixmaps (void) {
|
||||||
|
#define kind(kind, name) \
|
||||||
|
iconsLarge[FileKind##kind] = XmdLoadBitmapIcon(viewContainer, name); \
|
||||||
|
iconsSmall[FileKind##kind] = XmdLoadBitmapIcon(viewContainer, name##_small)
|
||||||
|
kind(File, file);
|
||||||
|
kind(Directory, directory);
|
||||||
|
kind(Link, link);
|
||||||
|
kind(Block, block);
|
||||||
|
kind(Character, character);
|
||||||
|
kind(Socket, socket);
|
||||||
|
kind(Pipe, pipe);
|
||||||
|
}
|
||||||
|
|
||||||
|
Bool freeFile (XmdStringMap *map, ConstString key, void *value, void *data) {
|
||||||
|
(void)(map);
|
||||||
|
(void)(key);
|
||||||
|
(void)(data);
|
||||||
|
File *this = value;
|
||||||
|
FileFree(this);
|
||||||
|
return True;
|
||||||
|
}
|
||||||
|
|
||||||
|
int refreshDirectory () {
|
||||||
|
char directory[PATH_MAX];
|
||||||
|
getcwd(directory, XtNumber(directory));
|
||||||
|
XtVaSetValues (
|
||||||
|
topLevel,
|
||||||
|
XmNtitle, directory,
|
||||||
|
XmNiconName, directory,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
int err = 0;
|
||||||
|
XtUnmanageChild(trailContainer); {
|
||||||
|
XmdStringMapIterate(trailFiles, freeFile, NULL);
|
||||||
|
XmdStringMapFree(trailFiles);
|
||||||
|
trailFiles = XmdStringMapNew();
|
||||||
|
err |= makeTrailIn(directory);
|
||||||
|
} XtManageChild(trailContainer);
|
||||||
|
|
||||||
|
XtUnmanageChild(viewContainer); {
|
||||||
|
XmdStringMapIterate(viewFiles, freeFile, NULL);
|
||||||
|
XmdStringMapFree(viewFiles);
|
||||||
|
viewFiles = XmdStringMapNew();
|
||||||
|
err |= makeFilesIn(directory, True);
|
||||||
|
} XtManageChild(viewContainer);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
int changeDirectory (ConstString path) {
|
||||||
|
int err = chdir(path);
|
||||||
|
if (err) return err;
|
||||||
|
refreshDirectory();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void handleActivate (Widget container, XtPointer clientData, XtPointer callData) {
|
||||||
|
(void)(container);
|
||||||
|
(void)(clientData);
|
||||||
|
XmContainerSelectCallbackStruct *event = callData;
|
||||||
|
if (event->selected_item_count < 1) return;
|
||||||
|
|
||||||
|
/* first, if a directory is selected, try to go into it */
|
||||||
|
for (int index = 0; index < event->selected_item_count; index ++) {
|
||||||
|
File *file = FileOfWidget(event->selected_items[index]);
|
||||||
|
if (file == NULL) continue;
|
||||||
|
if (file->kind == FileKindDirectory) {
|
||||||
|
changeDirectory(file->path);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if not, we worry about opening files and stuff */
|
||||||
|
/* TODO */
|
||||||
|
}
|
||||||
|
|
||||||
|
FileKind fileKind (ConstString path) {
|
||||||
|
struct stat info = { 0 };
|
||||||
|
stat(path, &info);
|
||||||
|
if (S_ISDIR (info.st_mode)) return FileKindDirectory;
|
||||||
|
if (S_ISCHR (info.st_mode)) return FileKindCharacter;
|
||||||
|
if (S_ISBLK (info.st_mode)) return FileKindBlock;
|
||||||
|
if (S_ISFIFO(info.st_mode)) return FileKindPipe;
|
||||||
|
if (S_ISLNK (info.st_mode)) return FileKindLink;
|
||||||
|
if (S_ISSOCK(info.st_mode)) return FileKindSocket;
|
||||||
|
return FileKindFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
int makeTrailIn (ConstString cwd) {
|
||||||
|
char name[PATH_MAX] = { 0 }; Cardinal nameIndex = 0;
|
||||||
|
char path[PATH_MAX] = { 0 }; Cardinal pathIndex = 0;
|
||||||
|
|
||||||
|
while (True) {
|
||||||
|
char ch = *(cwd ++);
|
||||||
|
|
||||||
|
if (nameIndex >= XtNumber(name)) return -1;
|
||||||
|
if (pathIndex >= XtNumber(path)) return -1;
|
||||||
|
|
||||||
|
name[ nameIndex] = ch;
|
||||||
|
name[++ nameIndex] = 0;
|
||||||
|
path[ pathIndex] = ch;
|
||||||
|
path[++ pathIndex] = 0;
|
||||||
|
|
||||||
|
if (ch == '/' || ch == 0) {
|
||||||
|
if (nameIndex == 0) {
|
||||||
|
name[0] = '/';
|
||||||
|
name[1] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
FileNew(trailFiles, trailContainer, name, path);
|
||||||
|
name[(nameIndex = 0)] = 0;
|
||||||
|
if (ch == 0) return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int makeFilesIn (ConstString directory, Bool showHidden) {
|
||||||
|
struct dirent **entries = NULL;
|
||||||
|
int entriesCount = scandir(directory, &entries, NULL, alphasort);
|
||||||
|
if (entriesCount < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
for (int index = 0; index < entriesCount; index ++) {
|
||||||
|
struct dirent *entry = entries[index];
|
||||||
|
if (entry->d_name[0] == '.' && !showHidden) {
|
||||||
|
XtFree((char *)(entry));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
char filePath[PATH_MAX];
|
||||||
|
snprintf (
|
||||||
|
filePath, XtNumber(filePath),
|
||||||
|
"%s/%s", directory, entry->d_name);
|
||||||
|
|
||||||
|
String fileName = XtNewString(entry->d_name);
|
||||||
|
XtFree((char *)(entry));
|
||||||
|
|
||||||
|
FileNew(viewFiles, viewContainer, fileName, filePath);
|
||||||
|
XtFree(fileName);
|
||||||
|
}
|
||||||
|
XtFree((char *)(entries));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
File *FileNew (XmdStringMap *set, Widget container, String name, ConstString path) {
|
||||||
|
File *this = XtNew(File);
|
||||||
|
this->label = NULL;
|
||||||
|
this->name = XtNewString(name);
|
||||||
|
this->path = XtNewString(path);
|
||||||
|
XmString string = XmStringCreateLocalized(name);
|
||||||
|
this->widget = XtVaCreateManagedWidget (
|
||||||
|
"file", xmIconGadgetClass, container,
|
||||||
|
XmNalignment, XmALIGNMENT_BEGINNING,
|
||||||
|
XmNlabelString, string,
|
||||||
|
XmNuserData, (XtPointer)(this),
|
||||||
|
NULL);
|
||||||
|
XmStringFree(string);
|
||||||
|
|
||||||
|
FileKind kind = fileKind(path);
|
||||||
|
XtVaSetValues (
|
||||||
|
this->widget,
|
||||||
|
XmNlargeIconPixmap, iconsLarge[kind],
|
||||||
|
XmNsmallIconPixmap, iconsSmall[kind],
|
||||||
|
NULL);
|
||||||
|
this->kind = kind;
|
||||||
|
|
||||||
|
XmdStringMapSet(set, name, this);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
File *FileOfWidget (Widget widget) {
|
||||||
|
File *file = NULL;
|
||||||
|
XtVaGetValues(widget, XmNuserData, &file, NULL);
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileDelete (XmdStringMap *set, ConstString name) {
|
||||||
|
FileFree(XmdStringMapSet(set, name, NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileFree (File *this) {
|
||||||
|
if (this == NULL) return;
|
||||||
|
XtUnmanageChild(this->widget);
|
||||||
|
XtDestroyWidget(this->widget);
|
||||||
|
XtFree((char *)(this->name));
|
||||||
|
XtFree((char *)(this->label));
|
||||||
|
XtFree((char *)(this->path));
|
||||||
|
XtFree((char *)(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileSetLabel (File *this, ConstString label) {
|
||||||
|
XtFree(this->label);
|
||||||
|
this->label = XtNewString(label);
|
||||||
|
|
||||||
|
XmString string = NULL;
|
||||||
|
if (label == NULL) {
|
||||||
|
string = XmStringCreateLocalized(this->name);
|
||||||
|
} else {
|
||||||
|
string = XmStringCreateLocalized(this->label);
|
||||||
|
}
|
||||||
|
XtVaSetValues (
|
||||||
|
this->widget,
|
||||||
|
XmNlabelString, string,
|
||||||
|
NULL);
|
||||||
|
XmStringFree(string);
|
||||||
|
}
|
||||||
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);
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
#define _XOPEN_SOURCE
|
#define _XOPEN_SOURCE 700
|
||||||
#include <Xm/Xm.h>
|
#include <Xm/Xm.h>
|
||||||
#include <Xm/RowColumn.h>
|
#include <Xm/RowColumn.h>
|
||||||
#include <Xm/PushB.h>
|
#include <Xm/PushB.h>
|
||||||
|
|||||||
2
xmshelf/build.sh
Executable file
2
xmshelf/build.sh
Executable file
@@ -0,0 +1,2 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
../scripts/buildapp.sh xmshell "$@"
|
||||||
27
xmshelf/src/icons/icon.xbm
Normal file
27
xmshelf/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,
|
||||||
|
0xfc, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xfc, 0xff, 0xff, 0xff, 0xff, 0x3f,
|
||||||
|
0xfc, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x0c, 0x1e, 0x00, 0xf0, 0x03, 0x30,
|
||||||
|
0xfc, 0xf3, 0xff, 0x0f, 0xfc, 0x3f, 0x0c, 0x09, 0x00, 0xf2, 0x13, 0x30,
|
||||||
|
0xfc, 0xf9, 0xff, 0x0d, 0xec, 0x3f, 0x0c, 0x09, 0x80, 0x02, 0x50, 0x30,
|
||||||
|
0xfc, 0xf9, 0xff, 0x02, 0xd0, 0x3f, 0x8c, 0x04, 0x40, 0x01, 0xa6, 0x30,
|
||||||
|
0xfc, 0xfc, 0x7f, 0x81, 0xa1, 0x3f, 0x8c, 0xfc, 0x4f, 0xe1, 0xa0, 0x30,
|
||||||
|
0xfc, 0x04, 0x78, 0x41, 0xa0, 0x3f, 0x4c, 0x06, 0x48, 0x41, 0xa0, 0x30,
|
||||||
|
0x7c, 0x06, 0x78, 0x81, 0xa0, 0x3f, 0x4c, 0x06, 0x88, 0x82, 0x50, 0x30,
|
||||||
|
0x7c, 0x06, 0xf8, 0x03, 0xf0, 0x3f, 0x2c, 0x05, 0x28, 0x0c, 0x0c, 0x31,
|
||||||
|
0x3c, 0x07, 0x38, 0xf0, 0x03, 0x3f, 0xfc, 0xff, 0xff, 0xff, 0xff, 0x3f,
|
||||||
|
0xac, 0x00, 0x00, 0x00, 0x00, 0x35, 0xfc, 0xff, 0xff, 0xff, 0xff, 0x3f,
|
||||||
|
0xfc, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x0c, 0x00, 0x00, 0x22, 0x00, 0x30,
|
||||||
|
0xfc, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x0c, 0x00, 0x00, 0x7f, 0x00, 0x30,
|
||||||
|
0xfc, 0xff, 0xff, 0xc1, 0xff, 0x3f, 0xcc, 0x3f, 0x00, 0x41, 0x3e, 0x31,
|
||||||
|
0x7c, 0xc0, 0xff, 0xe3, 0x23, 0x3f, 0x4c, 0xc0, 0x1f, 0x14, 0x22, 0x31,
|
||||||
|
0x7c, 0x00, 0xf0, 0xf7, 0x23, 0x31, 0x4c, 0x00, 0xf0, 0x94, 0x22, 0x31,
|
||||||
|
0x7c, 0x00, 0xd0, 0xf7, 0x22, 0x31, 0x4c, 0x00, 0xf0, 0x94, 0x22, 0x31,
|
||||||
|
0x7c, 0x00, 0xd0, 0xf7, 0xe2, 0x31, 0x4c, 0x00, 0xf0, 0x94, 0x22, 0x3f,
|
||||||
|
0x7c, 0x00, 0xd0, 0xf7, 0x36, 0x31, 0x4c, 0xff, 0xf7, 0x94, 0x22, 0x31,
|
||||||
|
0x7c, 0x00, 0xd0, 0xf7, 0x22, 0x31, 0xfc, 0xff, 0xff, 0xff, 0xff, 0x3f,
|
||||||
|
0xac, 0x00, 0x00, 0x00, 0x00, 0x35, 0xfc, 0xff, 0xff, 0xff, 0xff, 0x3f,
|
||||||
|
0xcc, 0xff, 0xff, 0xff, 0xff, 0x33, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x3f,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||||
336
xmshelf/src/main.c
Normal file
336
xmshelf/src/main.c
Normal file
@@ -0,0 +1,336 @@
|
|||||||
|
#define _XOPEN_SOURCE
|
||||||
|
#include <Xm/Xm.h>
|
||||||
|
#include <Xm/Form.h>
|
||||||
|
#include <Xm/PushB.h>
|
||||||
|
#include <Xm/MainW.h>
|
||||||
|
#include <Xm/IconG.h>
|
||||||
|
#include <Xm/Container.h>
|
||||||
|
#include <Xm/ScrolledW.h>
|
||||||
|
|
||||||
|
#include <Xmd/Icon.h>
|
||||||
|
#include <Xmd/Exec.h>
|
||||||
|
#include <Xmd/Buffer.h>
|
||||||
|
#include <Xmd/StringMap.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <libgen.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
|
||||||
|
#include "icons/icon.xbm"
|
||||||
|
|
||||||
|
XtAppContext application;
|
||||||
|
typedef enum {
|
||||||
|
DeviceKindGeneric,
|
||||||
|
DeviceKindDisk,
|
||||||
|
DeviceKindRom,
|
||||||
|
DeviceKindFilesystem,
|
||||||
|
DeviceKindTTY
|
||||||
|
} DeviceKind;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
Widget widget;
|
||||||
|
DeviceKind kind;
|
||||||
|
Bool orphaned;
|
||||||
|
String name;
|
||||||
|
String mountPoint;
|
||||||
|
String label;
|
||||||
|
} Device;
|
||||||
|
|
||||||
|
void loadIconPixmaps (void);
|
||||||
|
void refreshDevices (void);
|
||||||
|
void refreshDisks (void);
|
||||||
|
Device * DeviceNew (String name, DeviceKind kind);
|
||||||
|
void DeviceDelete (ConstString name);
|
||||||
|
void DeviceFree (Device *this);
|
||||||
|
void DeviceSetKind (Device *this, DeviceKind kind);
|
||||||
|
void DeviceSetMountPoint (Device *this, ConstString mountPoint);
|
||||||
|
void DeviceSetLabel (Device *this, ConstString label);
|
||||||
|
int readBlockDevice (FILE *stream, Device **);
|
||||||
|
int readLsblkPair (FILE *stream, String *key, String *value);
|
||||||
|
void handleRefresh (Widget, XtPointer, XtPointer);
|
||||||
|
|
||||||
|
int main (int argc, char *argv[]) {
|
||||||
|
devices = XmdStringMapNew();
|
||||||
|
|
||||||
|
Widget window = XtVaAppInitialize (
|
||||||
|
&application, "Shelf",
|
||||||
|
NULL, 0,
|
||||||
|
&argc, argv,
|
||||||
|
NULL,
|
||||||
|
XmNtitle, "Shelf",
|
||||||
|
XmNiconName, "Shelf",
|
||||||
|
XmNwidth, 256,
|
||||||
|
XmNheight, 256,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
Widget layout = XtVaCreateWidget (
|
||||||
|
"layout", xmFormWidgetClass, window,
|
||||||
|
XmNorientation, XmVERTICAL,
|
||||||
|
NULL);
|
||||||
|
Pixmap iconPixmap = XmdLoadBitmapIcon(layout, icon);
|
||||||
|
XtVaSetValues (
|
||||||
|
window,
|
||||||
|
XmNiconPixmap, iconPixmap,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
Pixmap refreshPixmap = XmdLoadBitmapIcon(layout, refresh);
|
||||||
|
XmString string = XmStringCreateLocalized("Refresh");
|
||||||
|
Widget refreshButton = XtVaCreateManagedWidget (
|
||||||
|
"refreshButton", xmPushButtonWidgetClass, layout,
|
||||||
|
XmNleftAttachment, XmATTACH_FORM,
|
||||||
|
XmNbottomAttachment, XmATTACH_FORM,
|
||||||
|
XmNlabelType, XmPIXMAP_AND_STRING,
|
||||||
|
XmNlabelPixmap, refreshPixmap,
|
||||||
|
XmNlabelString, string,
|
||||||
|
NULL);
|
||||||
|
XmStringFree(string);
|
||||||
|
XtAddCallback (
|
||||||
|
refreshButton, XmNactivateCallback,
|
||||||
|
handleRefresh, NULL);
|
||||||
|
|
||||||
|
Pixmap mountPixmap = XmdLoadBitmapIcon(layout, mount);
|
||||||
|
string = XmStringCreateLocalized("Mount");
|
||||||
|
Widget mountButton = XtVaCreateManagedWidget (
|
||||||
|
"mountButton", xmPushButtonWidgetClass, layout,
|
||||||
|
XmNleftAttachment, XmATTACH_WIDGET,
|
||||||
|
XmNleftWidget, refreshButton,
|
||||||
|
XmNbottomAttachment, XmATTACH_FORM,
|
||||||
|
XmNlabelType, XmPIXMAP_AND_STRING,
|
||||||
|
XmNlabelPixmap, mountPixmap,
|
||||||
|
XmNlabelString, string,
|
||||||
|
NULL);
|
||||||
|
XmStringFree(string);
|
||||||
|
|
||||||
|
Pixmap unmountPixmap = XmdLoadBitmapIcon(layout, unmount);
|
||||||
|
string = XmStringCreateLocalized("Unmount");
|
||||||
|
/*Widget unmountButton = */XtVaCreateManagedWidget (
|
||||||
|
"unmountButton", xmPushButtonWidgetClass, layout,
|
||||||
|
XmNleftAttachment, XmATTACH_WIDGET,
|
||||||
|
XmNleftWidget, mountButton,
|
||||||
|
XmNbottomAttachment, XmATTACH_FORM,
|
||||||
|
XmNlabelType, XmPIXMAP_AND_STRING,
|
||||||
|
XmNlabelPixmap, unmountPixmap,
|
||||||
|
XmNlabelString, string,
|
||||||
|
NULL);
|
||||||
|
XmStringFree(string);
|
||||||
|
|
||||||
|
Widget scroller = XtVaCreateWidget (
|
||||||
|
"scroll", xmScrolledWindowWidgetClass, layout,
|
||||||
|
XmNscrollingPolicy, XmAUTOMATIC,
|
||||||
|
XmNleftAttachment, XmATTACH_FORM,
|
||||||
|
XmNtopAttachment, XmATTACH_FORM,
|
||||||
|
XmNrightAttachment, XmATTACH_FORM,
|
||||||
|
XmNbottomAttachment, XmATTACH_WIDGET,
|
||||||
|
XmNbottomWidget, refreshButton,
|
||||||
|
NULL);
|
||||||
|
container = XtVaCreateManagedWidget (
|
||||||
|
"container", xmContainerWidgetClass, scroller,
|
||||||
|
XmNlayoutType, XmSPATIAL,
|
||||||
|
XmNspatialStyle, XmGRID,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
loadIconPixmaps();
|
||||||
|
refreshDevices();
|
||||||
|
|
||||||
|
XtManageChild(scroller);
|
||||||
|
XtManageChild(layout);
|
||||||
|
XtRealizeWidget(window);
|
||||||
|
XtAppMainLoop(application);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loadIconPixmaps (void) {
|
||||||
|
#define dev(kind, name) \
|
||||||
|
iconsLarge[DeviceKind##kind] = XmdLoadBitmapIcon(container, name); \
|
||||||
|
iconsSmall[DeviceKind##kind] = XmdLoadBitmapIcon(container, name##_small)
|
||||||
|
dev(Generic, generic);
|
||||||
|
dev(Disk, disk);
|
||||||
|
dev(Rom, rom);
|
||||||
|
dev(Filesystem, filesystem);
|
||||||
|
dev(TTY, tty);
|
||||||
|
}
|
||||||
|
|
||||||
|
void handleRefresh (Widget button, XtPointer clientData, XtPointer callData) {
|
||||||
|
(void)(button);
|
||||||
|
(void)(clientData);
|
||||||
|
(void)(callData);
|
||||||
|
refreshDevices();
|
||||||
|
}
|
||||||
|
|
||||||
|
Bool markDevice (XmdStringMap *map, ConstString key, void *value, void *data) {
|
||||||
|
(void)(map);
|
||||||
|
(void)(key);
|
||||||
|
(void)(data);
|
||||||
|
Device *this = value;
|
||||||
|
this->orphaned = True;
|
||||||
|
return True;
|
||||||
|
}
|
||||||
|
|
||||||
|
Bool transferDevice (XmdStringMap *map, ConstString key, void *value, void *data) {
|
||||||
|
(void)(map);
|
||||||
|
(void)(key);
|
||||||
|
(void)(data);
|
||||||
|
Device *this = value;
|
||||||
|
if (this->orphaned) {
|
||||||
|
DeviceFree(this);
|
||||||
|
} else {
|
||||||
|
XmdStringMapSet(devices, key, value);
|
||||||
|
}
|
||||||
|
return True;
|
||||||
|
}
|
||||||
|
|
||||||
|
void refreshDevices (void) {
|
||||||
|
XtUnmanageChild(container);
|
||||||
|
|
||||||
|
/* pre-mark all devices as orphaned */
|
||||||
|
XmdStringMapIterate(devices, markDevice, NULL);
|
||||||
|
|
||||||
|
/* refresh devices by category */
|
||||||
|
refreshDisks();
|
||||||
|
|
||||||
|
/* create a new map, only moving over extant devices */
|
||||||
|
XmdStringMap *oldMap = devices;
|
||||||
|
devices = XmdStringMapNew();
|
||||||
|
XmdStringMapIterate(oldMap, transferDevice, NULL);
|
||||||
|
XmdStringMapFree(oldMap);
|
||||||
|
|
||||||
|
XtManageChild(container);
|
||||||
|
}
|
||||||
|
|
||||||
|
String diskName (ConstString directory, ConstString name) {
|
||||||
|
char fullpath[PATH_MAX];
|
||||||
|
snprintf(fullpath, XtNumber(fullpath), "%s/%s", directory, name);
|
||||||
|
char resolved[PATH_MAX];
|
||||||
|
return XtNewString(basename(realpath(fullpath, resolved)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void refreshDisks (void) {
|
||||||
|
/* get disks */
|
||||||
|
ConstString disksById = "/dev/disk/by-id";
|
||||||
|
ConstString disksByLabel = "/dev/disk/by-label";
|
||||||
|
ConstString disksByPartuuid = "/dev/disk/by-partuuid";
|
||||||
|
|
||||||
|
struct dirent **entries = NULL;
|
||||||
|
int entriesCount = scandir(disksById, &entries, NULL, alphasort);
|
||||||
|
if (entriesCount < 0) {
|
||||||
|
/* TODO error message */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (int index = 0; index < entriesCount; index ++) {
|
||||||
|
struct dirent *entry = entries[index];
|
||||||
|
if (entry->d_name[0] == '.') {
|
||||||
|
XtFree((char *)(entry));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
String deviceName = diskName(disksById, entry->d_name);
|
||||||
|
XtFree((char *)(entry));
|
||||||
|
|
||||||
|
Device *device = XmdStringMapGet(devices, deviceName);
|
||||||
|
if (device == NULL) {
|
||||||
|
device = DeviceNew(deviceName, DeviceKindDisk);
|
||||||
|
} else {
|
||||||
|
device->orphaned = False;
|
||||||
|
DeviceSetKind(device, DeviceKindDisk);
|
||||||
|
}
|
||||||
|
|
||||||
|
XtFree(deviceName);
|
||||||
|
}
|
||||||
|
XtFree((char *)(entries));
|
||||||
|
|
||||||
|
/* determine disk types */
|
||||||
|
DIR *dir = opendir(disksByPartuuid);
|
||||||
|
if (dir == NULL) {
|
||||||
|
/* TODO error message */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
struct dirent *entry;
|
||||||
|
while ((entry = readdir(dir)) != NULL) {
|
||||||
|
if (entry->d_name[0] == '.') continue;
|
||||||
|
String deviceName = diskName(disksByPartuuid, entry->d_name);
|
||||||
|
Device *device = XmdStringMapGet(devices, deviceName);
|
||||||
|
if (device != NULL) DeviceSetKind(device, DeviceKindFilesystem);
|
||||||
|
XtFree(deviceName);
|
||||||
|
}
|
||||||
|
closedir(dir);
|
||||||
|
|
||||||
|
/* determine partition labels */
|
||||||
|
dir = opendir(disksByLabel);
|
||||||
|
if (dir == NULL) {
|
||||||
|
/* TODO error message */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
while ((entry = readdir(dir)) != NULL) {
|
||||||
|
if (entry->d_name[0] == '.') continue;
|
||||||
|
String deviceName = diskName(disksByLabel, entry->d_name);
|
||||||
|
Device *device = XmdStringMapGet(devices, deviceName);
|
||||||
|
if (device != NULL) DeviceSetLabel(device, entry->d_name);
|
||||||
|
XtFree(deviceName);
|
||||||
|
}
|
||||||
|
closedir(dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
Device *DeviceNew (String name, DeviceKind kind) {
|
||||||
|
Device *this = XtNew(Device);
|
||||||
|
this->mountPoint = NULL;
|
||||||
|
this->label = NULL;
|
||||||
|
this->name = XtNewString(name);
|
||||||
|
this->orphaned = False;
|
||||||
|
XmString string = XmStringCreateLocalized(name);
|
||||||
|
this->widget = XtVaCreateManagedWidget (
|
||||||
|
"device", xmIconGadgetClass, container,
|
||||||
|
XmNalignment, XmALIGNMENT_BEGINNING,
|
||||||
|
XmNlabelString, string,
|
||||||
|
NULL);
|
||||||
|
XmStringFree(string);
|
||||||
|
DeviceSetKind(this, kind);
|
||||||
|
XmdStringMapSet(devices, name, this);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeviceDelete (ConstString name) {
|
||||||
|
DeviceFree(XmdStringMapSet(devices, name, NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeviceFree (Device *this) {
|
||||||
|
if (this == NULL) return;
|
||||||
|
XtDestroyWidget(this->widget);
|
||||||
|
XtFree((char *)(this->name));
|
||||||
|
XtFree((char *)(this->mountPoint));
|
||||||
|
XtFree((char *)(this->label));
|
||||||
|
XtFree((char *)(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeviceSetKind (Device *this, DeviceKind kind) {
|
||||||
|
XtVaSetValues (
|
||||||
|
this->widget,
|
||||||
|
XmNlargeIconPixmap, iconsLarge[kind],
|
||||||
|
XmNsmallIconPixmap, iconsSmall[kind],
|
||||||
|
NULL);
|
||||||
|
this->kind = kind;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeviceSetMountPoint (Device *this, ConstString mountPoint) {
|
||||||
|
XtFree(this->mountPoint);
|
||||||
|
this->mountPoint = XtNewString(mountPoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeviceSetLabel (Device *this, ConstString label) {
|
||||||
|
XtFree(this->label);
|
||||||
|
this->label = XtNewString(label);
|
||||||
|
|
||||||
|
XmString string = NULL;
|
||||||
|
if (label == NULL) {
|
||||||
|
string = XmStringCreateLocalized(this->name);
|
||||||
|
} else {
|
||||||
|
string = XmStringCreateLocalized(this->label);
|
||||||
|
}
|
||||||
|
XtVaSetValues (
|
||||||
|
this->widget,
|
||||||
|
XmNlabelString, string,
|
||||||
|
NULL);
|
||||||
|
XmStringFree(string);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user