updates from MirBSD CVS
[shellsnippets/shellsnippets.git] / mksh / uhr
index 1b6ad19..4ad4c99 100644 (file)
--- a/mksh/uhr
+++ b/mksh/uhr
@@ -1,7 +1,7 @@
 #!/bin/mksh
-# $MirOS: contrib/hosted/tg/uhr,v 1.5 2012/05/28 00:30:00 tg Exp $
+# $MirOS: contrib/hosted/tg/uhr,v 1.14 2013/02/19 18:07:46 tg Exp $
 #-
-# Copyright © 2012
+# Copyright © 2012, 2013
 #      Thorsten Glaser <tg@mirbsd.org>
 #
 # Provided that these terms and disclaimer and all copyright notices
 # of said person’s immediate fault when using the work as intended.
 #-
 # Analoguhr mit Digitalanzeige. Grundlegende Annahme: schnelles Ter‐
-# minal, d.h. keine Voroptimierung der Darstellung durch Shellcode.
+# minal, d.h. keine Voroptimierung der Darstellung durch das Skript;
+# Font im Seitenverhältnis 1:2 (z.B. 9x18 aus XFree86® fixed-misc).
+
+if [[ $KSH_VERSION != @(\@\(#\)MIRBSD KSH R)@(4[1-9]|[5-9][0-9]|[1-9][0-9]+([0-9]))\ +([0-9])/+([0-9])/+([0-9])?(\ *) ]]; then
+       print -u2 Uhr requires mksh R41 or newer.
+       exit 1
+fi
+typeset -Z6 tosleep
 
 # stupid GNU idiots breaking everything by default… grml…
 bcopt=
 bc --help >/dev/null 2>&1 && bcopt=-q
 
+function graceful {
+       print -n '\033[;H\033[J'
+       exit 0
+}
+trap graceful INT TERM HUP
+
 trap got_sigwinch=1 WINCH
 while :; do
 got_sigwinch=0
 
 print "\e[0m\nPregenerating arrays, please wait..."
-set -A dt -- $(stty size)
-LINES=${dt[0]} COLUMNS=${dt[1]}
 (( r = LINES * 2 ))
 (( r = (r > COLUMNS ? COLUMNS : r) / 2 - 1))
 (( n = 2 * r + 1 ))
@@ -186,7 +197,50 @@ while (( ++i < 12 )); do
        read -p S; [[ $S = ?(-).* ]] && S=0
        mky[i]=${S%%.*}
 done
-print -p quit
+exec 3>&p; exec 3>&-
+
+(( L = LINES >= (COLUMNS / 2) ? (COLUMNS / 2) : LINES ))
+# fine-tuning of roman numeral position via screen size
+(( ++mkx[7] ))
+(( ++mkx[8] ))
+case $L {
+(22|23)        (( ++mkx[6] )) ;|
+(23)
+       (( mky[1] += 2 ))
+       (( mky[2] += 2 ))
+       (( mky[10] += 2 ))
+       (( mky[11] += 2 ))
+       ;;
+(24|25|29|30|31|34)
+       (( mky[4] += 2 ))
+       (( mky[8] += 2 ))
+       ;|
+(27|28|29)
+       (( ++mkx[10] ))
+       (( mky[8] += 2 ))
+       (( mky[9] += 2 ))
+       (( mky[10] += 2 ))
+       ;|
+(27|29|31)
+       (( mky[0] -= 2 ))
+       ;|
+(27)
+       (( --mkx[4] ))
+       (( --mkx[5] ))
+       (( ++mkx[6] ))
+       (( mkx[7] += 2 ))
+       (( ++mkx[8] ))
+       (( ++mkx[10] ))
+       ;;
+(29)
+       (( mky[5] += 2 ))
+       (( mky[7] += 2 ))
+       ;;
+(30)
+       (( mky[11] -= 2 ))
+       ;;
+}
+(( mky[0] += 2 * (L & 1) ))
 
 # clear framebuffer and screen
 set -A fb
@@ -196,8 +250,8 @@ print -n -- '\e[H\e[J'
 # draw hour markers
 set -A lb
 integer e f=-1 k
-(( LINES > 21 )) && while (( ++f < 12 )); do
-       i=mkx[f]
+(( L > 21 )) && while (( ++f < 12 )); do
+       (( i=mkx[f] ))
        (( j = mky[f] & ~1 ))
        case $f {
        (0) e=7 S='# # # # #  # ## # # #' ;;
@@ -213,9 +267,17 @@ integer e f=-1 k
        (10) e=3 S='# # # # #' ;;
        (11) e=5 S='# # # #  ## # #' ;;
        }
+       Y='0 1 2'
+       if (( L > 26 )); then
+               d='###########'
+               S="${d::e+2} ${S::e}  ${S: e:e}  ${S:2*e} ${d::e+2}"
+               (( e += 2 ))
+               Y+=' 3 4'
+               (( j += 2 ))
+       fi
        (( i -= e / 2 ))
        k=0
-       for y in 0 1 2; do
+       for y in $Y; do
                (( y = j - y * 2 + 1 + (r & 1) ))
                (( dy = y + 1 ))
                (( x = i - 1 ))
@@ -253,16 +315,34 @@ retrace lc M_CC F_CC
 refresh "${px[@]}"; set -A px
 
 set -A do -- -1 -1 -1
+isfirst=1
 while (( !got_sigwinch )); do
+       if (( isfirst )); then
+               isfirst=0
+       else
+               (( tosleep = 1000000 - ${EPOCHREALTIME#*.} ))
+               if (( tosleep > 999999 )); then
+                       sleep 0.2
+                       (( tosleep = 1000000 - ${EPOCHREALTIME#*.} ))
+               fi
+               if (( tosleep > 999999 )); then
+                       # huh… maybe no gettimeofday(2) here
+                       while :; do
+                               d=$(date +'%H %M %S,%d %b %Y')
+                               set -A dt $d
+                               (( dt[2] == do[2] )) || break
+                               sleep 0.1
+                       done
+               else
+                       sleep 0.$tosleep
+               fi
+       fi
+
        d=$(date +'%H %M %S,%d %b %Y')
        S=${d#*,}
        d=${d%,*}
        set -A dt $d
 
-       if (( dt[2] == do[2] )); then
-               sleep 0.1
-               continue
-       fi
        (( dt[0] = (dt[0] % 12) * 5 + (dt[1] / 12) ))
        if (( do[2] != -1 )); then
                retrace lms$((do[2])) M_SP F_NO