fa3ae4826a9e96062e5455c3969c6a9290ea4a26
[gsu.git] / gui
1 #!/bin/bash
2 # Copyright (C) 2006 Andre Noll
3 # Licensed under the LGPL, version 3. See COPYING and COPYING.LESSER.
4
5 if [[ "$(type -t _gsu_setup)" != "function" ]]; then
6 gsu_dir=${gsu_dir:-${BASH_SOURCE[0]%/*}}
7 . $gsu_dir/common || exit 1
8 _gsu_setup
9 fi
10
11 _gsu_node_name_pattern='[a-zA-Z_]'
12
13 _get_geometry()
14 {
15 local x y
16 result="$(stty size)"
17 if (($? != 0)); then
18 gsu_msg "fatal: could not get terminal geometry"
19 exit 1
20 fi
21 x="${result#* }"
22 y="${result%% *}"
23 (($x > 190)) && x=190
24 result="$y $x"
25 }
26
27 _set_dialog_ret()
28 {
29 local ec="$1"
30
31 case "$ec" in
32 0) ret=$GSU_SUCCESS;;
33 1) ret=1;; # cancelled
34 *)
35 result="dialog exit code $ec"
36 ret=-$E_GSU_DIALOG
37 esac
38 }
39
40 # Open a dialog box which asks the user to input a text
41 #
42 # Usage: gsu_input_box <text> <init>
43 #
44 # <text> is displayed above of the input field, which is is preset to <init>.
45 # The entered text is returned in $result. On success (user pressed OK)
46 # the function returns zero. If the user selected Cancel, the return value is
47 # one. On dialog errors, a negative error code is returned.
48 gsu_inputbox()
49 {
50 local g text="$1" init="$2"
51
52 _get_geometry
53 g="$result"
54 result="$(dialog --inputbox "$text" $g "$init" 3>&1 1>&2 2>&3 3>&-)"
55 _set_dialog_ret $?
56 }
57
58 # Show the given file in a text box
59 #
60 # Usage: gsu_textbox <path>
61 #
62 # The box has an OK button which closes the box when activated.
63 gsu_textbox()
64 {
65 local g file="$1"
66
67 _get_geometry
68 g="$result"
69
70 ret=-$E_GSU_DIALOG
71 result='textbox'
72 dialog --textbox "$file" $g
73 _set_dialog_ret $?
74 }
75
76 # Show a message in a text box
77 #
78 # Usage: gsu_msgbox <text>
79 #
80 # This is like gsu_textbox() but the text is passed as a string.
81 gsu_msgbox()
82 {
83 # Some versions of dialog segfault if the text is too long. Hence we
84 # always use a temporary file.
85 local tmp="$(mktemp gsu_msgbox.XXXXXXXXXX)"
86
87 if (($? != 0)); then
88 ret=-$E_GSU_MKTEMP
89 result='temp file for textbox'
90 return
91 fi
92 trap "rm -f $tmp" EXIT
93 echo "$1" > "$tmp"
94 gsu_textbox "$tmp"
95 rm -f "$tmp" # ignore errors
96 }
97
98 _gsu_menu()
99 {
100 local header="${1:-root}"
101 local items="$2"
102 local i state opts num=0
103
104 _get_geometry
105 opts="$result 16"
106 for i in $items; do
107 let num++
108 opts+=" $i $num"
109 done
110 result="$(dialog --menu "$gsu_banner_txt ($header)" $opts 3>&1 1>&2 2>&3 3>&-)"
111 _set_dialog_ret $?
112 }
113
114 _get_level()
115 {
116 local tmp="${1%%$_gsu_node_name_pattern*}"
117 result="${#tmp}"
118 }
119
120 _get_subtree()
121 {
122 local tree="$1" root="${2%/}"
123 local first TAB=' '
124
125 ret=-$E_GSU_MENU_TREE
126 result="subtree grep failed"
127 first="$(grep -n "$TAB\{1,\}$root/" <<< "$tree")" || return
128 [[ -z "$first" ]] && return
129
130 line_num="${first%%:*}"
131 _get_level "${first#*:}"
132 level="$result"
133
134 #echo "line: $line_num, root: $root, indent level: $level"
135 result="$(sed -e "1,${line_num}d;" <<< "$tree" \
136 | sed -e "/^$TAB\{1,$level\}$_gsu_node_name_pattern/,\$d" \
137 | sed -e "/^$TAB\{$(($level + 2))\}/d")"
138 if (($? != 0)); then
139 ret=-$E_GSU_MENU_TREE
140 result="sed command for subtree $root failed"
141 return
142 fi
143 ret=$GSU_SUCCESS
144 }
145
146 _get_root_nodes()
147 {
148 local tree="$1" TAB=' '
149
150 result="$(grep "^${TAB}${_gsu_node_name_pattern}" <<< "$tree")"
151 if (($? != 0)); then
152 ret=-$E_GSU_MENU_TREE
153 result="root node grep failed"
154 return
155 fi
156 ret=$GSU_SUCCESS
157 }
158
159 _browse()
160 {
161 local header="$1" old_header
162 local tree="$2" subtree="$3"
163
164 while :; do
165 _gsu_menu "$header" "$subtree"
166 (($ret < 0)) && return
167 [[ -z "$result" ]] && return # menu was cancelled
168 if [[ "${result%/}" != "$result" ]]; then
169 old_header="$header"
170 header="$result"
171 _get_subtree "$tree" "$header"
172 (($ret < 0)) && return
173 _browse "$header" "$tree" "$result"
174 (($ret < 0)) && return
175 header="$old_header"
176 continue
177 fi
178 eval ${gsu_name}_$result
179 done
180 }
181
182 gsu_gui()
183 {
184 local tree="$1" subtree
185
186 type -t dialog &> /dev/null
187 if (($? != 0)); then
188 gsu_msg "dialog executable not found"
189 exit 1
190 fi
191 _get_root_nodes "$tree"
192 subtree="$result"
193 _browse "main menu" "$tree" "$subtree"
194 }