3c89567cceae816d58cd9bd438ce0fe2d8cf2410
[gsu.git] / gui
1 #!/bin/bash
2
3 if [[ "$(type -t _gsu_setup)" != "function" ]]; then
4         gsu_dir=${gsu_dir:-${BASH_SOURCE[0]%/*}}
5         . $gsu_dir/common || exit 1
6         _gsu_setup
7 fi
8
9 _gsu_node_name_pattern='[a-zA-Z_]'
10
11 _get_geometry()
12 {
13         local x y
14         result="$(stty size)"
15         if (($? != 0)); then
16                 gsu_msg "fatal: could not get terminal geometry"
17                 exit 1
18         fi
19         x="${result#* }"
20         y="${result%% *}"
21         (($x > 190)) && x=190
22         result="$y $x"
23 }
24
25 gsu_inputbox()
26 {
27         local g text="$1" init="$2"
28
29         _get_geometry
30         g="$result"
31         result="$(dialog --inputbox "$text" $g "$init" 3>&1 1>&2 2>&3 3>&-)"
32         if (($? != 0)); then
33                 ret=-$E_GSU_DIALOG
34                 result='inputbox'
35                 return
36         fi
37         ret=$GSU_SUCCESS
38 }
39
40 gsu_textbox()
41 {
42         local g file="$1"
43
44         _get_geometry
45         g="$result"
46
47         ret=-$E_GSU_DIALOG
48         result='textbox'
49         dialog --textbox "$file" $g || return
50         ret=$GSU_SUCCESS
51 }
52
53 # dialog segfaults if message is too long. Hence we always use a temporary file
54 gsu_msgbox()
55 {
56         local tmp="$(mktemp gsu_msgbox.XXXXXXXXXX)"
57
58         if (($? != 0)); then
59                 ret=-$E_GSU_MKTEMP
60                 result='temp file for textbox'
61                 return
62         fi
63         echo "$1" > "$tmp"
64         gsu_textbox "$tmp"
65         rm -f "$tmp" # ignore errors
66 }
67
68 _gsu_menu()
69 {
70         local header="${1:-root}"
71         local items="$2"
72         local i state opts num=0
73
74         _get_geometry
75         opts="$result 16"
76         for i in $items; do
77                 let num++
78                 opts+=" $i $num"
79         done
80         result="$(dialog --menu "$gsu_banner_txt ($header)" $opts 3>&1 1>&2 2>&3 3>&-)"
81         case $? in
82         0) ret=$GSU_SUCCESS;;
83         1) ret=1;; # cancelled
84         *)
85                 result="menu error $ret"
86                 ret=-$E_GSU_DIALOG
87         esac
88 }
89
90 _get_level()
91 {
92         local tmp="${1%%$_gsu_node_name_pattern*}"
93         result="${#tmp}"
94 }
95
96 _get_subtree()
97 {
98         local tree="$1" root="${2%/}"
99         local first TAB='       '
100
101         ret=-$E_GSU_MENU_TREE
102         result="subtree grep failed"
103         first="$(grep -n "$TAB\{1,\}$root/" <<< "$tree")" || return
104         [[ -z "$first" ]] && return
105
106         line_num="${first%%:*}"
107         _get_level "${first#*:}"
108         level="$result"
109
110         #echo "line: $line_num, root: $root, indent level: $level"
111         result="$(sed -e "1,${line_num}d;" <<< "$tree" \
112                 | sed -e "/^$TAB\{1,$level\}$_gsu_node_name_pattern/,\$d" \
113                 | sed -e "/^$TAB\{$(($level + 2))\}/d")"
114         if (($? != 0)); then
115                 ret=-$E_GSU_MENU_TREE
116                 result="sed command for subtree $root failed"
117                 return
118         fi
119         ret=$GSU_SUCCESS
120 }
121
122 _get_root_nodes()
123 {
124         local tree="$1" TAB='   '
125
126         result="$(grep "^${TAB}${_gsu_node_name_pattern}" <<< "$tree")"
127         if (($? != 0)); then
128                 ret=-$E_GSU_MENU_TREE
129                 result="root node grep failed"
130                 return
131         fi
132         ret=$GSU_SUCCESS
133 }
134
135 _browse()
136 {
137         local header="$1" old_header
138         local tree="$2" subtree="$3"
139
140         while :; do
141                 _gsu_menu "$header" "$subtree"
142                 (($ret < 0)) && return
143                 [[ -z "$result" ]] && return # menu was cancelled
144                 if [[ "${result%/}" != "$result" ]]; then
145                         old_header="$header"
146                         header="$result"
147                         _get_subtree "$tree" "$header"
148                         (($ret < 0)) && return
149                         _browse "$header" "$tree" "$result"
150                         (($ret < 0)) && return
151                         header="$old_header"
152                         continue
153                 fi
154                 eval ${gsu_name}_$result
155         done
156 }
157
158 gsu_gui()
159 {
160         local tree="$1" subtree
161
162         type -t dialog &> /dev/null
163         if (($? != 0)); then
164                 gsu_msg "dialog executable not found"
165                 exit 1
166         fi
167         _get_root_nodes "$tree"
168         subtree="$result"
169         _browse "main menu" "$tree" "$subtree"
170 }