xref: /freebsd/usr.sbin/bsdconfig/share/dialog.subr (revision 2a664c03e55254b0f3b32dcdfc78179c0a57a8d2)
1if [ ! "$_DIALOG_SUBR" ]; then _DIALOG_SUBR=1
2#
3# Copyright (c) 2006-2012 Devin Teske
4# All Rights Reserved.
5#
6# Redistribution and use in source and binary forms, with or without
7# modification, are permitted provided that the following conditions
8# are met:
9# 1. Redistributions of source code must retain the above copyright
10#    notice, this list of conditions and the following disclaimer.
11# 2. Redistributions in binary form must reproduce the above copyright
12#    notice, this list of conditions and the following disclaimer in the
13#    documentation and/or other materials provided with the distribution.
14#
15# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, THE
17# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20# DAMAGES (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25# SUCH DAMAGE.
26#
27# $FreeBSD$
28#
29############################################################ INCLUDES
30
31BSDCFG_SHARE="/usr/share/bsdconfig"
32. $BSDCFG_SHARE/common.subr || exit 1
33f_include $BSDCFG_SHARE/strings.subr
34
35BSDCFG_LIBE="/usr/libexec/bsdconfig"
36f_include_lang $BSDCFG_LIBE/include/messages.subr
37
38############################################################ CONFIGURATION
39
40#
41# Default file descriptor to link to stdout for dialog(1) passthru allowing
42# execution of dialog from within a sub-shell (so-long as its standard output
43# is explicitly redirected to this file descriptor).
44#
45: ${DIALOG_TERMINAL_PASSTHRU_FD:=3}
46
47############################################################ GLOBALS
48
49#
50# Default name of dialog(1) utility
51# NOTE: This is changed to "Xdialog" by the optional `-X' argument
52#
53DIALOG="dialog"
54
55#
56# Default dialog(1) title and backtitle text
57#
58DIALOG_TITLE="$pgm"
59DIALOG_BACKTITLE="bsdconfig"
60
61#
62# Settings used while interacting with dialog(1)
63#
64DIALOG_MENU_TAGS="123456789ABCDEFGHIJKLMNOPQRSTUVWYZabcdefghijklmnopqrstuvwxyz"
65
66#
67# Declare that we are fully-compliant with Xdialog(1) by unset'ing all
68# compatibility settings.
69#
70unset XDIALOG_HIGH_DIALOG_COMPAT
71unset XDIALOG_FORCE_AUTOSIZE
72unset XDIALOG_INFOBOX_TIMEOUT
73
74#
75# Default behavior is to call f_dialog_init() automatically if not already
76# called manually by the time the first f_dialog_*() function is used.
77#
78: ${DIALOG_SELF_INITIALIZE=1}
79
80############################################################ GENERIC FUNCTIONS
81
82# f_dialog_title [$new_title]
83#
84# Set the title of future dialog(1) ($DIALOG_TITLE) or backtitle of Xdialog(1)
85# ($DIALOG_BACKTITLE) invocations. If no arguments are given or the first
86# argument is NULL, the current title is returned.
87#
88# Each time this function is called, a backup of the current values is made
89# allowing a one-time (single-level) restoration of the previous title using the
90# f_dialog_title_restore() function (below).
91#
92f_dialog_title()
93{
94	local new_title="$1"
95
96	if [ "$new_title" ]; then
97		if [ "$USE_XDIALOG" ]; then
98			_DIALOG_BACKTITLE="$DIALOG_BACKTITLE"
99			DIALOG_BACKTITLE="$new_title"
100		else
101			_DIALOG_TITLE="$DIALOG_TITLE"
102			DIALOG_TITLE="$new_title"
103		fi
104	else
105		if [ "$USE_XDIALOG" ]; then
106			echo "$DIALOG_BACKTITLE"
107		else
108			echo "$DIALOG_TITLE"
109		fi
110	fi
111}
112
113# f_dialog_title_restore
114#
115# Restore the previous title set by the last call to f_dialog_title().
116# Restoration is non-recursive and only works to restore the most-recent title.
117#
118f_dialog_title_restore()
119{
120	if [ "$USE_XDIALOG" ]; then
121		DIALOG_BACKTITLE="$_DIALOG_BACKTITLE"
122	else
123		DIALOG_TITLE="$_DIALOG_TITLE"
124	fi
125}
126
127# f_dialog_backtitle [$new_backtitle]
128#
129# Set the backtitle of future dialog(1) ($DIALOG_BACKTITLE) or title of
130# Xdialog(1) ($DIALOG_TITLE) invocations. If no arguments are given or the
131# first argument is NULL, the current backtitle is returned.
132#
133f_dialog_backtitle()
134{
135	local new_backtitle="$1"
136
137	if [ "$new_backtitle" ]; then
138		if [ "$USE_XDIALOG" ]; then
139			_DIALOG_TITLE="$DIALOG_TITLE"
140			DIALOG_TITLE="$new_backtitle"
141		else
142			_DIALOG_BACKTITLE="$DIALOG_BACKTITLE"
143			DIALOG_BACKTITLE="$new_backtitle"
144		fi
145	else
146		if [ "$USE_XDIALOG" ]; then
147			echo "$DIALOG_TITLE"
148		else
149			echo "$DIALOG_BACKTITLE"
150		fi
151	fi
152}
153
154# f_dialog_backtitle_restore
155#
156# Restore the previous backtitle set by the last call to f_dialog_backtitle().
157# Restoration is non-recursive and only works to restore the most-recent
158# backtitle.
159#
160f_dialog_backtitle_restore()
161{
162	if [ "$USE_XDIALOG" ]; then
163		DIALOG_TITLE="$_DIALOG_TITLE"
164	else
165		DIALOG_BACKTITLE="$_DIALOG_BACKTITLE"
166	fi
167}
168
169############################################################ SIZE FUNCTIONS
170
171# f_dialog_infobox_size $title $backtitle $prompt [$hline]
172#
173# Not all versions of dialog(1) perform auto-sizing of the width and height of
174# `--infobox' boxes sensibly.
175#
176# This function helps solve this issue by taking as arguments (in order of
177# appearance) the title, backtitle, prompt, and [optionally] hline returning
178# the optimal width and height for the box (not exceeding the actual terminal
179# width or height).
180#
181# Newline character sequences (``\n'') in $prompt are expanded as-is done by
182# dialog(1).
183#
184# Output is in the format of "height width".
185#
186f_dialog_infobox_size()
187{
188	[ "$DIALOG_SELF_INITIALIZE" ] && f_dialog_init
189
190	local title="$1" btitle="$2" prompt="$3" hline="$4" n=0
191	local min_width max_size
192
193	if [ "$USE_XDIALOG" ]; then
194		min_width=35
195		max_size="$XDIALOG_MAXSIZE" # see CONFIGURATION
196	else
197		min_width=24
198		max_size=$( stty size ) # usually "24 80"
199	fi
200
201	local max_height="${max_size%%[$IFS]*}"
202	local max_width="${max_size##*[$IFS]}"
203	local height width=$min_width
204
205	#
206	# Bump width for long titles (but don't exceed terminal width).
207	#
208	n=$(( ${#title} + 4 ))
209	if [ $n -gt $width -a $n -gt $min_width ]; then
210		# Add 16.6% width for Xdialog(1)
211		[ "$USE_XDIALOG" ] && n=$(( $n + $n / 6 ))
212
213		if [ $n -lt $max_width ]; then
214			width=$n
215		else
216			width=$max_width
217		fi
218	fi
219
220	#
221	# For Xdialog(1), bump width for long backtitles (which appear within
222	# the window; don't exceed maximum width).
223	#
224	if [ "$USE_XDIALOG" ]; then
225		n=$(( ${#btitle} + 4 ))
226		n=$(( $n + $n / 6 ))
227		if [ $n -gt $width -a $n -gt $min_width ]; then
228			if [ $n -lt $max_width ]; then
229				width=$n
230			else
231				width=$max_width
232			fi
233		fi
234	fi
235
236	#
237	# Bump width for long prompts (if not already at maximum width).
238	#
239	if [ $width -lt $max_width ]; then
240		n=$( echo "$prompt" | f_longest_line_length )
241		n=$(( $n + 4 ))
242
243		# Add 16.6% width for Xdialog(1)
244		[ "$USE_XDIALOG" ] && n=$(( $n + $n / 6 ))
245
246		if [ $n -gt $width -a $n -gt $min_width ]; then
247			if [ $n -lt $max_width ]; then
248				width=$n
249			else
250				width=$max_width
251			fi
252		fi
253	fi
254
255	#
256	# Bump width for long hlines (if not already at maximum width).
257	# NOTE: Though Xdialog(1) supports `--hline', it's not currently used.
258	#
259	if [ ! "$USE_XDIALOG" ]; then
260		if [ $width -lt $max_width ]; then
261			n=$(( ${#hline} + 10 ))
262			if [ $n -gt $width -a $n -gt $min_width ]; then
263				if [ $n -lt $max_width ]; then
264					width=$n
265				else
266					width=$max_width
267				fi
268			fi
269		fi
270	fi
271
272	#
273	# Set height based on number of rows in prompt
274	#
275	height=$( echo "$prompt" | f_number_of_lines )
276	height=$(( $height + 2 ))
277
278	#
279	# For Xdialog(1) bump height if backtitle is enabled (displayed in the
280	# X11 window with a separator line between the backtitle and msg text)
281	#
282	if [ "$USE_XDIALOG" -a "$btitle" ]; then
283		n=$( echo "$btitle" | f_number_of_lines )
284		height=$(( $height + $n + 2 ))
285	fi
286
287	# Make sure height is less than maximum screen size
288	[ $height -le $max_height ] || height=$max_height
289
290	# Return both
291	echo "$height $width"
292}
293
294# f_dialog_buttonbox_size $title $backtitle $prompt [$hline]
295#
296# Not all versions of dialog(1) perform auto-sizing of the width and height of
297# `--msgbox' and `--yesno' boxes sensibly.
298#
299# This function helps solve this issue by taking as arguments (in order of
300# appearance) the title, backtitle, prompt, and [optionally] hline returning
301# the optimal width and height for the box (not exceeding the actual terminal
302# width or height).
303#
304# Newline character sequences (``\n'') in $prompt are expanded as-is done by
305# dialog(1).
306#
307# Output is in the format of "height width".
308#
309f_dialog_buttonbox_size()
310{
311	[ "$DIALOG_SELF_INITIALIZE" ] && f_dialog_init
312
313	local title="$1" btitle="$2" prompt="$3" hline="$4"
314	local size="$( f_dialog_infobox_size \
315	               		"$title" "$btitle" "$prompt" "$hline" )"
316	local height="${size%%[$IFS]*}"
317	local width="${size##*[$IFS]}"
318
319	# Add height to accomodate the buttons
320	height=$(( $height + 2 ))
321
322	# Adjust for clipping with Xdialog(1) on Linux/GTK2
323	[ "$USE_XDIALOG" ] && height=$(( $height + 3 ))
324
325	#
326	# Enforce maximum height regardless
327	#
328	local max_size
329	if [ "$USE_XDIALOG" ]; then
330		max_size="$XDIALOG_MAXSIZE" # see CONFIGURATION
331	else
332		max_size=$( stty size ) # usually "24 80"
333	fi
334	local max_height="${max_size%%[$IFS]*}"
335	[ $height -le $max_height ] || height=$max_height
336
337	# Return both
338	echo "$height $width"
339}
340
341# f_dialog_inputbox_size $title $backtitle $prompt $init [$hline]
342#
343# Not all versions of dialog(1) perform auto-sizing of the width and height of
344# `--inputbox' boxes sensibly.
345#
346# This function helps solve this issue by taking as arguments (in order of
347# appearance) the title, backtitle, prompt, initial text, and [optionally]
348# hline returning the optimal width and height for the box (not exceeding the
349# actual terminal width and height).
350#
351# Newline character sequences (``\n'') in $prompt are expanded as-is done by
352# dialog(1).
353#
354# Output is in the format of "height width".
355#
356f_dialog_inputbox_size()
357{
358	[ "$DIALOG_SELF_INITIALIZE" ] && f_dialog_init
359
360	local title="$1" btitle="$2" prompt="$3" init="$4" hline="$5" n
361	local size="$( f_dialog_buttonbox_size \
362	               		"$title" "$btitle" "$prompt" "$hline" )"
363	local height="${size%%[$IFS]*}"
364	local width="${size##*[$IFS]}"
365
366	local min_width max_size
367	if [ "$USE_XDIALOG" ]; then
368		min_width=35
369		max_size="$XDIALOG_MAXSIZE" # see CONFIGURATION
370	else
371		min_width=24
372		max_size=$( stty size ) # usually "24 80"
373	fi
374	local max_height="${max_size%%[$IFS]*}"
375	local max_width="${max_size##*[$IFS]}"
376
377	#
378	# Add height to accomodate the input box
379	#
380	[ ! "$USE_XDIALOG" ] && height=$(( $height + 3 ))
381	[ $height -le $max_height ] || height=$max_height
382
383	#
384	# Bump width for initial text (if not already at maximum width).
385	# NOTE: Something neither dialog(1)/Xdialog(1) do, but worth it!
386	#
387	if [ $width -lt $max_width ]; then
388		n=$(( ${#init} + 7 ))
389
390		# Add 16.6% width for Xdialog(1)
391		[ "$USE_XDIALOG" ] && n=$(( $n + $n / 6 ))
392
393		if [ $n -gt $width -a $n -gt $min_width ]; then
394			if [ $n -lt $max_width ]; then
395				width=$n
396			else
397				width=$max_width
398			fi
399		fi
400	fi
401
402	# Return both
403	echo "$height $width"
404}
405
406# f_xdialog_2inputsbox_size $title $backtitle $prompt \
407#                           $label1 $init1 $label2 $init2
408#
409# Xdialog(1) does not perform auto-sizing of the width and height of
410# `--2inputsbox' boxes sensibly.
411#
412# This function helps solve this issue by taking as arguments (in order of
413# appearance) the title, backtitle, prompt, label for the first field, initial
414# text for said field, label for the second field, and initial text for said
415# field returning the optimal width and height for the box (not exceeding the
416# actual terminal width and height).
417#
418# Newline character sequences (``\n'') in $prompt are expanded as-is done by
419# Xdialog(1).
420#
421# Output is in the format of "height width".
422#
423f_xdialog_2inputsbox_size()
424{
425	[ "$DIALOG_SELF_INITIALIZE" ] && f_dialog_init
426
427	local title="$1" btitle="$2" prompt="$3"
428	local label1="$4" init1="$5" label2="$6" init2="$7" n
429	local size="$( f_dialog_inputbox_size \
430	               		"$title" "$btitle" "$prompt" "$init1" )"
431	local height="${size%%[$IFS]*}"
432	local width="${size##*[$IFS]}"
433
434	local min_width=35
435	local max_size="$XDIALOG_MAXSIZE" # see CONFIGURATION
436	local max_height="${max_size%%[$IFS]*}"
437	local max_width="${max_size##*[$IFS]}"
438
439	# Add height for first label
440	height=$(( $height + 2 ))
441
442	#
443	# Bump width for first label text (if not already at maximum width).
444	#
445	if [ $width -lt $max_width ]; then
446		n=$(( ${#label1} + 7 ))
447
448		# Add 16.6% width for Xdialog(1)
449		n=$(( $n + $n / 6 ))
450
451		if [ $n -gt $width -a $n -gt $min_width ]; then
452			if [ $n -lt $max_width ]; then
453				width=$n
454			else
455				width=$max_width
456			fi
457		fi
458	fi
459
460	# Add height for second label
461	height=$(( $height + 2 ))
462
463	#
464	# Bump width for second label text (if not already at maximum width).
465	#
466	if [ $width -lt $max_width ]; then
467		n=$(( ${#label2} + 7 ))
468
469		# Add 16.6% width for Xdialog(1)
470		n=$(( $n + $n / 6 ))
471
472		if [ $n -gt $width -a $n -gt $min_width ]; then
473			if [ $n -lt $max_width ]; then
474				width=$n
475			else
476				width=$max_width
477			fi
478		fi
479	fi
480
481	# Add height for a second inputbox
482	height=$(( $height + 2 ))
483
484	#
485	# Bump width for second initial text (if not already at maximum width).
486	# NOTE: Something neither dialog(1)/Xdialog(1) do, but worth it!
487	#
488	if [ $width -lt $max_width ]; then
489		n=$(( ${#init2} + 7 ))
490
491		# Add 16.6% width for Xdialog(1)
492		n=$(( $n + $n / 6 ))
493
494		if [ $n -gt $width -a $n -gt $min_width ]; then
495			if [ $n -lt $max_width ]; then
496				width=$n
497			else
498				width=$max_width
499			fi
500		fi
501	fi
502
503	# Return both
504	echo "$height $width"
505}
506
507# f_dialog_menu_size $title $backtitle $prompt $hline \
508#                    $tag1 $item1 $tag2 $item2 ...
509#
510# Not all versions of dialog(1) perform auto-sizing of the width and height of
511# `--menu' boxes sensibly.
512#
513# This function helps solve this issue by taking as arguments (in order of
514# appearance) the title, backtitle, prompt, hline and list of tag/item pairs,
515# returning the optimal width and height for the menu (not exceeding the actual
516# terminal width or height).
517#
518# Output is in the format of "height width rows".
519#
520f_dialog_menu_size()
521{
522	[ "$DIALOG_SELF_INITIALIZE" ] && f_dialog_init
523
524	local title="$1" btitle="$2" prompt="$3" hline="$4" n=0
525	local min_width min_rows max_size
526
527	if [ "$USE_XDIALOG" ]; then
528		min_width=35
529		min_rows=1
530		max_size="$XDIALOG_MAXSIZE" # see CONFIGURATION
531	else
532		min_width=24
533		min_rows=0
534		max_size=$( stty size ) # usually "24 80"
535	fi
536
537	local max_width="${max_size##*[$IFS]}"
538	local max_height="${max_size%%[$IFS]*}"
539	local box_size="$( f_dialog_infobox_size \
540	                   	"$title" "$btitle" "$prompt" "$hline" )"
541	local box_height="${box_size%%[$IFS]*}"
542	local box_width="${box_size##*[$IFS]}"
543	local max_rows=$(( $max_height - 8 ))
544	local height width=$box_width rows=$min_rows
545
546	shift 4 # title/btitle/prompt/hline
547
548	# If there's no prompt, bump the max-rows by 1
549	[ "$prompt" ] || max_rows=$(( $max_rows + 1 ))
550
551	#
552	# The sum total between the longest tag-length and longest item-length
553	# should be used for the menu width (not to exceed terminal width).
554	#
555	# Also, calculate the number of rows (not to exceed terminal height).
556	#
557	local longest_tag=0 longest_item=0
558	while [ $# -ge 2 ]; do
559		local tag="$1" item="$2"
560		shift 2 # tag/item
561
562		[ ${#tag} -gt $longest_tag ] && longest_tag=${#tag}
563		[ ${#item} -gt $longest_item ] && longest_item=${#item}
564		[ $rows -lt $max_rows ] && rows=$(( $rows + 1 ))
565	done
566
567	# Update width
568	n=$(( $longest_tag + $longest_item + 10 ))
569	[ "$USE_XDIALOG" ] && n=$(( $n + $n / 6 )) # Add 16.6% for Xdialog(1)
570	if [ $n -gt $width -a $n -gt $min_width ]; then
571		if [ $n -lt $max_width ]; then
572			width=$n
573		else
574			width=$max_width
575		fi
576	fi
577
578	# Fix rows and set height
579	[ $rows -gt 0 ] || rows=1
580	if [ "$USE_XDIALOG" ]; then
581		height=$(( $rows + $box_height + 7 ))
582	else
583		height=$(( $rows + $box_height + 4 ))
584	fi
585	[ $height -le $max_height ] || height=$max_height
586
587	# Return all three
588	echo "$height $width $rows"
589}
590
591# f_dialog_menu_with_help_size $title $backtitle $prompt $hline \
592#                              $tag1 $item1 $help1 $tag2 $item2 $help2 ...
593#
594# Not all versions of dialog(1) perform auto-sizing of the width and height of
595# `--menu' boxes sensibly.
596#
597# This function helps solve this issue by taking as arguments (in order of
598# appearance) the title, backtitle, prompt, hline and list of tag/item/help
599# triplets, returning the optimal width and height for the menu (not exceeding
600# the actual terminal width or height).
601#
602# Output is in the format of "height width rows".
603#
604f_dialog_menu_with_help_size()
605{
606	[ "$DIALOG_SELF_INITIALIZE" ] && f_dialog_init
607
608	local title="$1" btitle="$2" prompt="$3" hline="$4" n=0
609	local min_width min_rows max_size
610
611	if [ "$USE_XDIALOG" ]; then
612		min_width=35
613		min_rows=1
614		max_size="$XDIALOG_MAXSIZE" # see CONFIGURATION
615	else
616		min_width=24
617		min_rows=0
618		max_size=$( stty size ) # usually "24 80"
619	fi
620
621	local max_width="${max_size##*[$IFS]}"
622	local max_height="${max_size%%[$IFS]*}"
623	local box_size="$( f_dialog_infobox_size \
624	                   	"$title" "$btitle" "$prompt" "$hline" )"
625	local box_height="${box_size%%[$IFS]*}"
626	local box_width="${box_size##*[$IFS]}"
627	local max_rows=$(( $max_height - 8 ))
628	local height width=$box_width rows=$min_rows
629
630	shift 4 # title/btitle/prompt/hline
631
632	# If there's no prompt, bump the max-rows by 1
633	[ "$prompt" ] || max_rows=$(( $max_rows + 1 ))
634
635	#
636	# The sum total between the longest tag-length and longest item-length
637	# should be used for the menu width (not to exceed terminal width).
638	#
639	# Also, calculate the number of rows (not to exceed terminal height).
640	#
641	# Also, calculate the longest help while we're here. This will be used
642	# to influence the width of the menu if (and only-if) using Xdialog(1).
643	#
644	local longest_tag=0 longest_item=0 longest_help=0
645	while [ $# -ge 3 ]; do
646		local tag="$1" item="$2" help="$3"
647		shift 3 # tag/item/help
648
649		[ ${#tag} -gt $longest_tag ] && longest_tag=${#tag}
650		[ ${#item} -gt $longest_item ] && longest_item=${#item}
651		[ ${#help} -gt $longest_help ] && longest_help=${#help}
652		[ $rows -lt $max_rows ] && rows=$(( $rows + 1 ))
653	done
654
655	# Update width
656	n=$(( $longest_tag + $longest_item + 10 ))
657	[ "$USE_XDIALOG" ] && n=$(( $n + $n / 6 )) # Add 16.6% for Xdialog(1)
658	if [ $n -gt $width -a $n -gt $min_width ]; then
659		if [ $n -lt $max_width ]; then
660			width=$n
661		else
662			width=$max_width
663		fi
664	fi
665
666	# Update width for help text if using Xdialog(1)
667	if [ "$USE_XDIALOG" ]; then
668		n=$(( $longest_help + 10 ))
669		n=$(( $n + $n / 6 )) # +16.6%
670		if [ $n -gt $width -a $n -gt $min_width ]; then
671			if [ $n -lt $max_width ]; then
672				width=$n
673			else
674				width=$max_width
675			fi
676		fi
677	fi
678
679	# Fix rows and set height
680	[ $rows -gt 0 ] || rows=1
681	if [ "$USE_XDIALOG" ]; then
682		height=$(( $rows + $box_height + 8 ))
683	else
684		height=$(( $rows + $box_height + 4 ))
685	fi
686	[ $height -le $max_height ] || height=$max_height
687
688	# Return all three
689	echo "$height $width $rows"
690}
691
692# f_dialog_radiolist_size $title $backtitle $prompt $hline \
693#                         $tag1 $item1 $status1 $tag2 $item2 $status2 ...
694#
695# Not all versions of dialog(1) perform auto-sizing of the width and height of
696# `--radiolist' boxes sensibly.
697#
698# This function helps solve this issue by taking as arguments (in order of
699# appearance) the title, backtitle, prompt, hline and list of tag/item/status
700# triplets, returning the optimal width and height for the radiolist (not
701# exceeding the actual terminal width or height).
702#
703# Output is in the format of "height width rows".
704#
705f_dialog_radiolist_size()
706{
707	[ "$DIALOG_SELF_INITIALIZE" ] && f_dialog_init
708
709	local title="$1" btitle="$2" prompt="$3" hline="$4" n=0
710	local min_width min_rows max_size
711
712	if [ "$USE_XDIALOG" ]; then
713		min_width=35
714		min_rows=1
715		max_size="$XDIALOG_MAXSIZE" # see CONFIGURATION
716	else
717		min_width=24
718		min_rows=0
719		max_size=$( stty size ) # usually "24 80"
720	fi
721
722	local max_width="${max_size##*[$IFS]}"
723	local max_height="${max_size%%[$IFS]*}"
724	local box_size="$( f_dialog_infobox_size \
725	                   	"$title" "$btitle" "$prompt" "$hline" )"
726	local box_height="${box_size%%[$IFS]*}"
727	local box_width="${box_size##*[$IFS]}"
728	local max_rows=$(( $max_height - 8 ))
729	local height width=$box_width rows=$min_rows
730
731	shift 4 # title/btitle/prompt/hline
732
733	#
734	# The sum total between the longest tag-length, longest item-length,
735	# and radio-button width should be used for the menu width (not to
736	# exceed terminal width).
737	#
738	# Also, calculate the number of rows (not to exceed terminal height).
739	#
740	local longest_tag=0 longest_item=0
741	while [ $# -ge 2 ]; do
742		local tag="$1" item="$2" help="$3"
743		shift 3 # tag/item/status
744
745		[ ${#tag} -gt $longest_tag ] && longest_tag=${#tag}
746		[ ${#item} -gt $longest_item ] && longest_item=${#item}
747		[ $rows -lt $max_rows ] && rows=$(( $rows + 1 ))
748	done
749
750	# Update width
751	n=$(( $longest_tag + $longest_item + 13 ))
752	[ "$USE_XDIALOG" ] && n=$(( $n + $n / 6 )) # Add 16.6% for Xdialog(1)
753	if [ $n -gt $width -a $n -gt $min_width ]; then
754		if [ $n -lt $max_width ]; then
755			width=$n
756		else
757			width=$max_width
758		fi
759	fi
760
761	# Fix rows and set height
762	[ $rows -gt 0 ] || rows=1
763	if [ "$USE_XDIALOG" ]; then
764		height=$(( $rows + $box_height + 7 ))
765	else
766		height=$(( $rows + $box_height + 4 ))
767	fi
768	[ $height -le $max_height ] || height=$max_height
769
770	# Return all three
771	echo "$height $width $rows"
772}
773
774# f_dialog_calendar_size $title $backtitle $prompt [$hline]
775#
776# Not all versions of dialog(1) perform auto-sizing of the width and height of
777# `--calendar' boxes sensibly.
778#
779# This function helps solve this issue by taking as arguments (in order of
780# appearance) the title, backtitle, prompt, and [optionally] hline returning
781# the optimal width and height for the box (not exceeding the actual terminal
782# width and height).
783#
784# Newline character sequences (``\n'') in $prompt are expanded as-is done by
785# dialog(1).
786#
787# Output is in the format of "height width".
788#
789f_dialog_calendar_size()
790{
791	[ "$DIALOG_SELF_INITIALIZE" ] && f_dialog_init
792
793	local title="$1" btitle="$2" prompt="$3" hline="$4" n
794	local size="$( f_dialog_infobox_size \
795	               		"$title" "$btitle" "$prompt" "$hline" )"
796	local height="${size%%[$IFS]*}"
797	local width="${size##*[$IFS]}"
798
799	local min_width min_height max_size
800	if [ "$USE_XDIALOG" ]; then
801		min_height=15
802		min_width=55
803		max_size="$XDIALOG_MAXSIZE" # see CONFIGURATION
804	else
805		min_height=0
806		min_width=40
807		max_size=$( stty size ) # usually "24 80"
808	fi
809	local max_height="${max_size%%[$IFS]*}"
810	local max_width="${max_size##*[$IFS]}"
811
812	#
813	# Enforce the minimum width for displaying the calendar
814	#
815	[ $width -ge $min_width ] || width=$min_width
816
817	#
818	# When using dialog(1), the calendar box is unique from other dialog(1)
819	# boxes in-that the height passed should not accomodate the 15-lines
820	# required to display the calendar. This does not apply to Xdialog(1).
821	#
822	# When using Xdialog(1), the height must accomodate the 15-lines
823	# required to display the calendar.
824	#
825	# NOTE: Also under dialog(1), because we can't predict whether the user
826	# has disabled shadow's in their `$HOME/.dialogrc' file, we'll subtract
827	# 16 rather than 15. This does not apply to Xdialog(1).
828	#
829	max_height=$(( $max_height - 16 ))
830	height=$( echo "$prompt" | f_number_of_lines )
831	if [ "$USE_XDIALOG" ]; then
832		# Add height to accomodate for the embedded calendar widget
833		height=$(( $height + $min_height - 1 ))
834
835		# Also, bump height if backtitle is enabled
836		if [ "$btitle" ]; then
837			local n="$( echo "$btitle" | f_number_of_lines )"
838			height=$(( $height + $n + 2 ))
839		fi
840	else
841		[ "$prompt" ] && height=$(( $height + 1 ))
842	fi
843	[ $height -le $max_height ] || height=$max_height
844
845	#
846	# The calendar box refuses to display if too large.
847	#
848	max_width=$(( $max_width - 2 ))
849	[ $width -le $max_width ] || width=$max_width
850
851	# Return both
852	echo "$height $width"
853}
854
855# f_dialog_timebox_size $title $backtitle $prompt [$hline]
856#
857# Not all versions of dialog(1) perform auto-sizing of the width and height of
858# `--timebox' boxes sensibly.
859#
860# This function helps solve this issue by taking as arguments (in order of
861# appearance) the title, backtitle, prompt, and [optionally] hline returning
862# the optimal width and height for the box (not exceeding the actual terminal
863# width and height).
864#
865# Newline character sequences (``\n'') in $prompt are expanded as-is done by
866# dialog(1).
867#
868# Output is in the format of "height width".
869#
870f_dialog_timebox_size()
871{
872	[ "$DIALOG_SELF_INITIALIZE" ] && f_dialog_init
873
874	local title="$1" btitle="$2" prompt="$3" hline="$4" n
875	local size="$( f_dialog_infobox_size \
876	               		"$title" "$btitle" "$prompt" "$hline" )"
877	local height="${size%%[$IFS]*}"
878	local width="${size##*[$IFS]}"
879
880	local min_width min_height max_size
881	if [ "$USE_XDIALOG" ]; then
882		min_width=40
883		max_size="$XDIALOG_MAXSIZE" # see CONFIGURATION
884	else
885		min_height=0
886		min_width=20
887		max_size=$( stty size ) # usually "24 80"
888	fi
889	local max_height="${max_size%%[$IFS]*}"
890	local max_width="${max_size##*[$IFS]}"
891
892	#
893	# Enforce the minimum width for displaying the timebox
894	#
895	[ $width -ge $min_width ] || width=$min_width
896
897	#
898	# When using dialog(1), the timebox box is unique from other dialog(1)
899	# boxes in-that the height passed should not accomodate the 6-lines
900	# required to display the timebox. This does not apply to Xdialog(1).
901	#
902	# When using Xdialog(1), the height seems to have no effect. All values
903	# provide the same results.
904	#
905	# NOTE: Also under dialog(1), because we can't predict whether the user
906	# has disabled shadow's in their `$HOME/.dialogrc' file, we'll subtract
907	# 7 rather than 6. This does not apply to Xdialog(1).
908	#
909	if [ "$USE_XDIALOG" ]; then
910		height=0 # Autosize; all values produce same results
911	else
912		max_height=$(( $max_height - 7 ))
913		height=$( echo "$prompt" | f_number_of_lines )
914		height=$(( $height + 1 ))
915		[ $height -le $max_height ] || height=$max_height
916		[ "$prompt" ] && height=$(( $height + 1 ))
917	fi
918
919	#
920	# The timebox box refuses to display if too large.
921	#
922	max_width=$(( $max_width - 2 ))
923	[ $width -le $max_width ] || width=$max_width
924
925	# Return both
926	echo "$height $width"
927}
928
929############################################################ CLEAR FUNCTIONS
930
931# f_dialog_clear
932#
933# Clears any/all previous dialog(1) displays.
934#
935f_dialog_clear()
936{
937	[ "$DIALOG_SELF_INITIALIZE" ] && f_dialog_init
938
939	$DIALOG --clear
940}
941
942############################################################ INFO FUNCTIONS
943
944# f_dialog_info $info_text ...
945#
946# Throw up a dialog(1) infobox. The infobox remains until another dialog is
947# displayed or `dialog --clear' (or dialog_clear) is called.
948#
949f_dialog_info()
950{
951	[ "$DIALOG_SELF_INITIALIZE" ] && f_dialog_init
952
953	local info_text="$*"
954	local size="$( f_dialog_infobox_size \
955	               		"$DIALOG_TITLE"     \
956	               		"$DIALOG_BACKTITLE" \
957	               		"$info_text"        )"
958
959	eval $DIALOG \
960		--title \"\$DIALOG_TITLE\"         \
961		--backtitle \"\$DIALOG_BACKTITLE\" \
962		${USE_XDIALOG:+--ignore-eof}       \
963		${USE_XDIALOG:+--no-buttons}       \
964		--infobox \"\$info_text\" $size
965}
966
967# f_xdialog_info $info_text ...
968#
969# Throw up an Xdialog(1) infobox and do not dismiss it until stdin produces
970# EOF. This implies that you must execute this either as an rvalue to a pipe,
971# lvalue to indirection or in a sub-shell that provides data on stdin.
972#
973f_xdialog_info()
974{
975	[ "$DIALOG_SELF_INITIALIZE" ] && f_dialog_init
976
977	local info_text="$*"
978	local size="$( f_dialog_infobox_size \
979	               		"$DIALOG_TITLE"     \
980	               		"$DIALOG_BACKTITLE" \
981	               		"$info_text"        )"
982
983	eval $DIALOG \
984		--title \"\$DIALOG_TITLE\"         \
985		--backtitle \"\$DIALOG_BACKTITLE\" \
986		--no-close --no-buttons            \
987		--infobox \"\$info_text\" $size    \
988		-1 # timeout of -1 means abort when EOF on stdin
989}
990
991############################################################ MSGBOX FUNCTIONS
992
993# f_dialog_msgbox $msg_text ...
994#
995# Throw up a dialog(1) msgbox. The msgbox remains until the user presses ENTER
996# or ESC, acknowledging the modal dialog.
997#
998# If the user presses ENTER, the exit status is zero (success), otherwise if
999# the user presses ESC the exit status is 255.
1000#
1001f_dialog_msgbox()
1002{
1003	[ "$DIALOG_SELF_INITIALIZE" ] && f_dialog_init
1004
1005	local msg_text="$*"
1006	local size="$( f_dialog_buttonbox_size \
1007	               		"$DIALOG_TITLE"     \
1008	               		"$DIALOG_BACKTITLE" \
1009	               		"$msg_text"         )"
1010
1011	eval $DIALOG \
1012		--title \"\$DIALOG_TITLE\"         \
1013		--backtitle \"\$DIALOG_BACKTITLE\" \
1014		--ok-label \"\$msg_ok\"            \
1015		--msgbox \"\$msg_text\" $size
1016}
1017
1018############################################################ YESNO FUNCTIONS
1019
1020# f_dialog_yesno $msg_text ...
1021#
1022# Display a dialog(1) Yes/No prompt to allow the user to make some decision.
1023# The yesno prompt remains until the user presses ENTER or ESC, acknowledging
1024# the modal dialog.
1025#
1026# If the user chooses YES the exit status is zero, or chooses NO the exit
1027# status is one, or presses ESC the exit status is 255.
1028#
1029f_dialog_yesno()
1030{
1031	[ "$DIALOG_SELF_INITIALIZE" ] && f_dialog_init
1032
1033	local msg_text="$*"
1034	local hline="$hline_arrows_tab_enter"
1035	local size="$( f_dialog_buttonbox_size \
1036	               		"$DIALOG_TITLE"     \
1037	               		"$DIALOG_BACKTITLE" \
1038	               		"$msg_text"         \
1039	               		"$hline"            )"
1040
1041	if [ "$USE_XDIALOG" ]; then
1042		eval $DIALOG \
1043			--title \"\$DIALOG_TITLE\"         \
1044			--backtitle \"\$DIALOG_BACKTITLE\" \
1045			--hline \"\$hline\"                \
1046			--ok-label \"\$msg_yes\"           \
1047			--cancel-label \"\$msg_no\"        \
1048			--yesno \"\$msg_text\" $size
1049	else
1050		eval $DIALOG \
1051			--title \"\$DIALOG_TITLE\"         \
1052			--backtitle \"\$DIALOG_BACKTITLE\" \
1053			--hline \"\$hline\"                \
1054			--yes-label \"\$msg_yes\"          \
1055			--no-label \"\$msg_no\"            \
1056			--yesno \"\$msg_text\" $size
1057	fi
1058}
1059
1060# f_dialog_noyes $msg_text ...
1061#
1062# Display a dialog(1) No/Yes prompt to allow the user to make some decision.
1063# The noyes prompt remains until the user presses ENTER or ESC, acknowledging
1064# the modal dialog.
1065#
1066# If the user chooses YES the exit status is zero, or chooses NO the exit
1067# status is one, or presses ESC the exit status is 255.
1068#
1069# NOTE: This is just like the f_dialog_yesno function except "No" is default.
1070#
1071f_dialog_noyes()
1072{
1073	[ "$DIALOG_SELF_INITIALIZE" ] && f_dialog_init
1074
1075	local msg_text="$*"
1076	local hline="$hline_arrows_tab_enter"
1077	local size="$( f_dialog_buttonbox_size \
1078	               		"$DIALOG_TITLE"     \
1079	               		"$DIALOG_BACKTITLE" \
1080	               		"$msg_text"         \
1081	               		"$hline"            )"
1082
1083	if [ "$USE_XDIALOG" ]; then
1084		eval $DIALOG \
1085			--title \"\$DIALOG_TITLE\"         \
1086			--backtitle \"\$DIALOG_BACKTITLE\" \
1087			--hline \"\$hline\"                \
1088			--default-no                       \
1089			--ok-label \"\$msg_yes\"           \
1090			--cancel-label \"\$msg_no\"        \
1091			--yesno \"\$msg_text\" $size
1092	else
1093		eval $DIALOG \
1094			--title \"\$DIALOG_TITLE\"         \
1095			--backtitle \"\$DIALOG_BACKTITLE\" \
1096			--hline \"\$hline\"                \
1097			--defaultno                        \
1098			--yes-label \"\$msg_yes\"          \
1099			--no-label \"\$msg_no\"            \
1100			--yesno \"\$msg_text\" $size
1101	fi
1102}
1103
1104############################################################ INPUT FUNCTIONS
1105
1106# f_dialog_inputstr
1107#
1108# Obtain the inputstr entered by the user from the most recently displayed
1109# dialog(1) inputbox and clean up any temporary files.
1110#
1111f_dialog_inputstr()
1112{
1113	# Skip warnings and trim leading/trailing whitespace from user input
1114	eval echo \"\$DIALOG_INPUTBOX_$$\" | awk '
1115		BEGIN { found = 0 }
1116		{
1117			if ( ! found )
1118			{
1119				if ( $0 ~ /^$/ ) next
1120				if ( $0 ~ /^Gdk-WARNING \*\*:/ ) next
1121				found = 1
1122			}
1123			sub(/^[[:space:]]*/, "")
1124			sub(/[[:space:]]*$/, "")
1125			print
1126		}
1127	'
1128	setvar DIALOG_INPUTBOX_$$ "" # scrub memory in case data was sensitive
1129	return $SUCCESS
1130}
1131
1132############################################################ MENU FUNCTIONS
1133
1134# f_dialog_menutag
1135#
1136# Obtain the menutag chosen by the user from the most recently displayed
1137# dialog(1) menu and clean up any temporary files.
1138#
1139f_dialog_menutag()
1140{
1141	# Skip warnings
1142	eval echo \"\$DIALOG_MENU_$$\" | awk '
1143		BEGIN { found = 0 }
1144		{
1145			if ( found ) # ... just spew
1146			{
1147				print
1148				next
1149			}
1150			if ( $0 ~ /^$/ ) next
1151			if ( $0 ~ /^Gdk-WARNING \*\*:/ ) next
1152			found = 1
1153			print
1154		}
1155	'
1156	setvar DIALOG_MENU_$$ "" # scrub memory in case data was sensitive
1157	return $SUCCESS
1158}
1159
1160# f_dialog_menutag2item $tag_chosen $tag1 $item1 $tag2 $item2 ...
1161#
1162# To use the `--menu' option of dialog(1) you must pass an ordered list of
1163# tag/item pairs on the command-line. When the user selects a menu option the
1164# tag for that item is printed to stderr.
1165#
1166# This function allows you to dereference the tag chosen by the user back into
1167# the item associated with said tag.
1168#
1169# Pass the tag chosen by the user as the first argument, followed by the
1170# ordered list of tag/item pairs (HINT: use the same tag/item list as was
1171# passed to dialog(1) for consistency).
1172#
1173# If the tag cannot be found, NULL is returned.
1174#
1175f_dialog_menutag2item()
1176{
1177	local tag="$1" tagn item
1178	shift 1 # tag
1179
1180	while [ $# -gt 0 ]; do
1181		tagn="$1"
1182		item="$2"
1183		shift 2 # tagn/item
1184
1185		if [ "$tag" = "$tagn" ]; then
1186			echo "$item"
1187			return $SUCCESS
1188		fi
1189	done
1190	return $FAILURE
1191}
1192
1193# f_dialog_menutag2item_with_help $tag_chosen $tag1 $item1 $help1 \
1194#                                             $tag2 $item2 $help2 ...
1195#
1196# To use the `--menu' option of dialog(1) with the `--item-help' option, you
1197# must pass an ordered list of tag/item/help triplets on the command-line. When
1198# the user selects a menu option the tag for that item is printed to stderr.
1199#
1200# This function allows you to dereference the tag chosen by the user back into
1201# the item associated with said tag (help is discarded/ignored).
1202#
1203# Pass the tag chosen by the user as the first argument, followed by the
1204# ordered list of tag/item/help triplets (HINT: use the same tag/item/help list
1205# as was passed to dialog(1) for consistency).
1206#
1207# If the tag cannot be found, NULL is returned.
1208#
1209f_dialog_menutag2item_with_help()
1210{
1211	local tag="$1" tagn item
1212	shift 1 # tag
1213
1214	while [ $# -gt 0 ]; do
1215		tagn="$1"
1216		item="$2"
1217		shift 3 # tagn/item/help
1218
1219		if [ "$tag" = "$tagn" ]; then
1220			echo "$item"
1221			return $SUCCESS
1222		fi
1223	done
1224	return $FAILURE
1225}
1226
1227# f_dialog_menutag2index $tag_chosen $tag1 $item1 $tag2 $item2 ...
1228#
1229# To use the `--menu' option of dialog(1) you must pass an ordered list of
1230# tag/item pairs on the command-line. When the user selects a menu option the
1231# tag for that item is printed to stderr.
1232#
1233# This function allows you to dereference the tag chosen by the user back into
1234# the index associated with said tag. The index is the one-based tag/item pair
1235# array position within the ordered list of tag/item pairs passed to dialog(1).
1236#
1237# Pass the tag chosen by the user as the first argument, followed by the
1238# ordered list of tag/item pairs (HINT: use the same tag/item list as was
1239# passed to dialog(1) for consistency).
1240#
1241# If the tag cannot be found, NULL is returned.
1242#
1243f_dialog_menutag2index()
1244{
1245	local tag="$1" tagn n=1
1246	shift 1 # tag
1247
1248	while [ $# -gt 0 ]; do
1249		tagn="$1"
1250		shift 2 # tagn/item
1251
1252		if [ "$tag" = "$tagn" ]; then
1253			echo $n
1254			return $SUCCESS
1255		fi
1256		n=$(( $n + 1 ))
1257	done
1258	return $FAILURE
1259}
1260
1261# f_dialog_menutag2index_with_help $tag_chosen $tag1 $item1 $help1 \
1262#                                              $tag2 $item2 $help2 ...
1263#
1264# To use the `--menu' option of dialog(1) with the `--item-help' option, you
1265# must pass an ordered list of tag/item/help triplets on the command-line. When
1266# the user selects a menu option the tag for that item is printed to stderr.
1267#
1268# This function allows you to dereference the tag chosen by the user back into
1269# the index associated with said tag. The index is the one-based tag/item/help
1270# triplet array position within the ordered list of tag/item/help triplets
1271# passed to dialog(1).
1272#
1273# Pass the tag chosen by the user as the first argument, followed by the
1274# ordered list of tag/item/help triplets (HINT: use the same tag/item/help list
1275# as was passed to dialog(1) for consistency).
1276#
1277# If the tag cannot be found, NULL is returned.
1278#
1279f_dialog_menutag2index_with_help()
1280{
1281	local tag="$1" tagn n=1
1282	shift 1 # tag
1283
1284	while [ $# -gt 0 ]; do
1285		tagn="$1"
1286		shift 3 # tagn/item/help
1287
1288		if [ "$tag" = "$tagn" ]; then
1289			echo $n
1290			return $SUCCESS
1291		fi
1292		n=$(( $n + 1 ))
1293	done
1294	return $FAILURE
1295}
1296
1297############################################################ INIT FUNCTIONS
1298
1299# f_dialog_init
1300#
1301# Initialize (or re-initialize) the dialog module after setting/changing any
1302# of the following environment variables:
1303#
1304# 	USE_XDIALOG   Either NULL or Non-NULL. If given a value will indicate
1305# 	              that Xdialog(1) should be used instead of dialog(1).
1306#
1307# 	SECURE        Either NULL or Non-NULL. If given a value will indicate
1308# 	              that (while running as root) sudo(8) authentication is
1309# 	              required to proceed.
1310#
1311f_dialog_init()
1312{
1313	DIALOG_SELF_INITIALIZE=
1314
1315	#
1316	# Clone terminal stdout so we can redirect to it from within sub-shells
1317	#
1318	eval exec $DIALOG_TERMINAL_PASSTHRU_FD\>\&1
1319
1320	#
1321	# Process stored command-line arguments
1322	#
1323	SECURE=$( set -- "$ARGV"
1324		while getopts S flag > /dev/null; do
1325			case "$flag" in
1326			S) echo 1;;
1327			\?) continue;;
1328			esac
1329		done
1330	)
1331	USE_XDIALOG=$( set -- "$ARGV"
1332		while getopts SX flag > /dev/null; do
1333			case "$flag" in
1334			S|X) echo 1;;
1335			\?) continue;;
1336			esac
1337		done
1338	)
1339
1340	#
1341	# Process `-X' command-line option
1342	#
1343	[ "$USE_XDIALOG" ] && DIALOG=Xdialog
1344
1345	#
1346	# Sanity check, or die gracefully
1347	#
1348	if ! f_have $DIALOG; then
1349		unset USE_XDIALOG
1350		failed_dialog="$DIALOG"
1351		DIALOG=dialog
1352		f_die 1 "$msg_no_such_file_or_directory" "$pgm" "$failed_dialog"
1353	fi
1354
1355	#
1356	# If we're already running as root but we got there by way of sudo(8)
1357	# and we have X11, we should merge the xauth(1) credentials from our
1358	# original user.
1359	#
1360	if [ "$USE_XDIALOG" ] &&
1361	   [ "$( id -u )" = "0" ] &&
1362	   [ "$SUDO_USER" -a "$DISPLAY" ]
1363	then
1364		if ! f_have xauth; then
1365			# Die gracefully, as we [likely] can't use Xdialog(1)
1366			unset USE_XDIALOG
1367			DIALOG=dialog
1368			f_die 1 "$msg_no_such_file_or_directory" "$pgm" "xauth"
1369		fi
1370		HOSTNAME=$(hostname)
1371		displaynum="${DISPLAY#*:}"
1372		eval xauth -if \~$SUDO_USER/.Xauthority extract - \
1373			\"\$HOSTNAME/unix:\$displaynum\" \
1374			\"\$HOSTNAME:\$displaynum\" | sudo sh -c 'xauth -ivf \
1375			~root/.Xauthority merge - > /dev/null 2>&1'
1376	fi
1377
1378	#
1379	# Probe Xdialog(1) for maximum height/width constraints, or die
1380	# gracefully
1381	#
1382	if [ "$USE_XDIALOG" ]; then
1383		if ! maxsize=$( LANG= LC_ALL= $DIALOG --print-maxsize 2>&1 )
1384		then
1385			# Xdialog(1) failed, fall back to dialog(1)
1386			unset USE_XDIALOG
1387			size=$( f_dialog_buttonbox_size "$DIALOG_TITLE" \
1388			                                "$DIALOG_BACKTITLE" \
1389			                                "$maxsize" "" )
1390			eval dialog \
1391				--title \"\$DIALOG_TITLE\"         \
1392				--backtitle \"\$DIALOG_BACKTITLE\" \
1393				--ok-label \"\$msg_ok\"            \
1394				--msgbox \"\$maxsize\" $size
1395			exit $FAILURE
1396		fi
1397
1398		XDIALOG_MAXSIZE=$(
1399			set -- ${maxsize##*:}
1400
1401			height=${1%,}
1402			width=$2
1403
1404			echo $height $width
1405		)
1406		unset maxsize
1407	fi
1408
1409	#
1410	# If using Xdialog(1), swap DIALOG_TITLE with DIALOG_BACKTITLE.
1411	# The reason for this is because many dialog(1) applications use
1412	# --backtitle for the program name (which is better suited as
1413	# --title with Xdialog(1)).
1414	#
1415	if [ "$USE_XDIALOG" ]; then
1416		_DIALOG_TITLE="$DIALOG_TITLE"
1417		DIALOG_TITLE="$DIALOG_BACKTITLE"
1418		DIALOG_BACKTITLE="$_DIALOG_TITLE"
1419		unset _DIALOG_TITLE
1420	fi
1421}
1422
1423fi # ! $_DIALOG_SUBR
1424