1#!/bin/sh
2#
3# ---
4# SPDX-License-Identifier: BSD-2-Clause
5#
6# Copyright 2013 Devin Teske
7# Copyright 2018 Mateusz Piotrowski <0mp@FreeBSD.org>
8#
9# All rights reserved.
10#
11# Redistribution and use in source and binary forms, with or without
12# modification, are permitted provided that the following conditions are met:
13#
14# 1. Redistributions of source code must retain the above copyright notice,
15#    this list of conditions and the following disclaimer.
16#
17# 2. Redistributions in binary form must reproduce the above copyright notice,
18#    this list of conditions and the following disclaimer in the documentation
19#    and/or other materials provided with the distribution.
20#
21# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31# POSSIBILITY OF SUCH DAMAGE.
32
33# How much to increment % each time (must be even divisor of 100)
34: "${increment:=1}"
35
36# Time to sleep in-between increments
37: "${sleep_sec:=3}"
38
39# How big is the mini-progressbar?
40: "${pbar_size:=17}"
41
42# Maximum width for labels (file names)
43: "${txt_size:=28}"
44
45# Files to fake-fetch
46: "${files:="base.txz dict.txz doc.txz games.txz ports.txz src.txz"}"
47
48args="$(getopt f:i:p:s:w: $*)"
49set -- $args
50while :; do
51    case "$1" in
52        -i)
53            increment="$2"
54            shift 2
55            ;;
56        -f)
57            files="$2"
58            shift 2
59            ;;
60        -p)
61            pbar_size="$2"
62            shift 2
63            ;;
64        -s)
65            sleep_sec="$2"
66            shift 2
67            ;;
68        -w)
69            txt_size="$2"
70            shift 2
71            ;;
72        --)
73            shift
74            break
75            ;;
76    esac
77done
78
79### Rest below shouldn't need editing ###
80spin='/-\|'
81pct_lsize=$(( ( pbar_size - 4 ) / 2 ))
82pct_rsize=$pct_lsize
83[ $(( pct_lsize * 2 + 4 )) -ne "$pbar_size" ] &&
84	pct_rsize=$(( pct_rsize + 1 ))
85dun_lsize=$pct_lsize dun_rsize=$pct_rsize
86pen_lsize=$(( ( pbar_size - 7 ) / 2 ))
87pen_rsize=$pen_lsize
88[ $(( pen_lsize * 2 + 7 )) -ne "$pbar_size" ] &&
89	pen_rsize=$(( pen_rsize + 1 ))
90n=1
91nfiles=$( set -- $files; echo $# )
92for file in $files; do # Loop through each file, ...
93	pct=
94	while [ ${pct:-0} -lt 100 ]; do # ... incrementing 1% each sub-loop
95		[ "$sleep_sec" ] && sleep "$sleep_sec"
96		pct=$(( ${pct:--$increment} + increment ))
97		#
98		# Create the progress bar
99		#
100		pbar=$( printf "%${pct_lsize}s%3u%%%${pct_rsize}s" \
101		               "" $pct "" )
102		# Calculate the width thereof
103		width=$(( pct * pbar_size / 100 ))
104		# Round up based on one-tenth of a percent
105		[ $(( pct * pbar_size % 100 )) -gt 50 ] &&
106			width=$(( width + 1 ))
107		#
108		# Make a copy of the pbar and split the copy into two halves
109		# (we'll insert the ANSI delimiter in between)
110		#
111		lpbar="$pbar" rpbar="$pbar" rwidth=$(( pbar_size - width ))
112		while [ ${#lpbar} -gt $width ]; do lpbar="${lpbar%?}"; done
113		while [ ${#rpbar} -gt $rwidth ]; do rpbar="${rpbar#?}"; done
114		#
115		# Finalize the progress bar
116		#
117		pbar="\Zb\Zr\Z4$lpbar\ZR$rpbar\Zn"
118		#
119		# Build the prompt text
120		#
121		p=1 prompt=
122		for f in $files; do
123			flabel="$f"
124			while [ ${#flabel} -gt "$txt_size" ]; do
125				flabel="${flabel%?}"
126			done
127			if [ ${#flabel} -ne ${#f} ]; then
128				while [ ${#flabel} -gt $(( txt_size - 3 )) ]
129				do flabel="${flabel%?}"; done
130				flabel="$flabel..."
131			fi
132			if [ $n -eq $p -a $pct -ne 100 ]; then
133				# This is the file we're processing right now
134				while [ ${#flabel} -gt $(( txt_size - 3 )) ]
135				do flabel="${flabel%?}"; done
136				spin_char=$( echo "$spin" | sed -e \
137				 "s/.\{0,$(( pct % ${#spin} ))\}\(.\).*/\1/" )
138				prompt="$prompt$(
139					printf "\\\Zb%-${txt_size}s\\\ZB %c " \
140					       "${flabel%...}..." "$spin_char"
141				)"
142			else
143				prompt="$prompt$(
144					printf "%-${txt_size}s %c " \
145					       "$flabel" " "
146				)"
147			fi
148			if [ $p -eq $n ] && [ $pct -ne 100 ]; then
149				prompt="$prompt [$pbar]\n"
150			elif [ $p -gt $n ]; then
151				prompt="$prompt [$(
152					printf "%${pen_lsize}s" ""
153				)Pending$(
154					printf "%${pen_rsize}s" ""
155				)]\n"
156			else
157				prompt="$prompt [\Zb\Zr\Z2$(
158					printf "%${dun_lsize}s" ""
159				)Done$(
160					printf "%${dun_rsize}s" ""
161				)\Zn]\n"
162			fi
163			p=$(( p + 1 ))
164		done
165		#
166		# Add trailing information
167		#
168		prompt="$prompt\nFetching distribution files...\n"
169		prompt="$prompt\n  \ZbOverall Progress:\Zn"
170		#
171		# Calculate total overall progress
172		#
173		opct=$(( ( 100 * n - 100 + pct ) / nfiles ))
174		# Round up based on one-tenth of a percent
175		[ $(( (100*n - 100 + pct) * 10 / nfiles % 100 )) -gt 50 ] &&
176			opct=$(( opct + 1 ))
177
178		printf "XXX\n%s\nXXX\n%u\n" "$prompt" $opct
179	done
180	n=$(( n + 1 ))
181done | dialog --title 'Fetching Distribution' \
182	--backtitle 'FreeBSD Installer' --colors \
183	--gauge "$prompt" 14 $(( txt_size + pbar_size + 10 ))
184