#
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
# Common Development and Distribution License (the "License").
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# See the License for the specific language governing permissions
# and limitations under the License.
#
# When distributing Covered Code, include this CDDL HEADER in each
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
# If applicable, add the following below this CDDL HEADER, with the
# fields enclosed by brackets "[]" replaced with your own identifying
# information: Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
#
#
#
#
# termclock - a simple analog clock for terminals
#
# Make sure all math stuff runs in the "C" locale to avoid problems
# with alternative # radix point representations (e.g. ',' instead of
# '.' in de_DE.*-locales). This needs to be set _before_ any
# floating-point constants are defined in this script).
if [[ "${LC_ALL}" != "" ]] ; then
export \
LC_MONETARY="${LC_ALL}" \
LC_MESSAGES="${LC_ALL}" \
LC_COLLATE="${LC_ALL}" \
LC_CTYPE="${LC_ALL}"
unset LC_ALL
fi
export LC_NUMERIC=C
function fatal_error
{
print -u2 "${progname}: $*"
exit 1
}
# cache tput values (to avoid |fork()|'ing a "tput" child every second)
function tput_cup
{
# static variable as cache for "tput_cup"
typeset -S -A tput_cup_cache
integer y="$1" x="$2"
nameref c="tput_cup_cache[\"${y}_${x}\"]"
if [[ "$c" == "" ]] ; then
# fast path for known terminal types
else
fi
fi
print -r -n -- "$c"
return 0
}
# Get terminal size and put values into a compound variable with the integer
# members "columns" and "lines"
function get_term_size
{
nameref rect=$1
return 0
}
function draw_clock
{
float angle a
float x y
integer i=1
((
))
# add "mark" every 30 degrees
print -r -n "$(((++i)%12+1))"
else
print -r -n "x"
fi
done
return 0
}
function draw_hand
{
typeset ch="$2"
float length="$3"
float x y
for (( s=0.0 ; s < 10. ; s+=0.5 )) ; do
((
))
print -r -n -- "${ch}"
done
return 0
}
function draw_clock_hand
{
nameref hand=$1
return 0
}
function clear_clock_hand
{
nameref hand=$1
return 0
}
function main_loop
{
typeset c
# note: we can't use subshells when writing to the double-buffer file because this
# will render the tput value cache useless
while true ; do
if ${init_screen} ; then
init_screen="false"
get_term_size termsize || fatal_error $"Couldn't get terminal size."
((
clock.middle_x=termsize.columns/2.-.5 ,
clock.middle_y=termsize.lines/2.-.5 ,
clock.len_x=termsize.columns/2-2 ,
clock.len_y=termsize.lines/2-2 ,
))
{
} >&6
fi
{
# small trick to get a smooth "analog" flair
((
hours.val+=minutes.val/60. ,
minutes.val+=seconds.val/60.
))
# move cursor to home position
tput_cup 0 0
} >&6
6<#((0))
cat <&6
if [[ "$c" != "" ]] ; then
esac
fi
{
} >&6
done
}
function usage
{
OPTIND=0
exit 2
}
# program start
builtin basename
builtin cat
builtin date
builtin mktemp
builtin rm
float -r M_PI=3.14159265358979323846
# terminal size rect
compound termsize=(
integer columns=-1
integer lines=-1
)
typeset init_screen="true"
compound clock=(
float middle_x
float middle_y
integer len_x
integer len_y
)
# set clock properties
compound seconds=(
float val
typeset ch
float scale
integer length )
compound minutes=(
float val
typeset ch
float scale
integer length )
compound hours=(
float val
typeset ch
float scale
integer length )
float update_interval=0.9
typeset -r termclock_usage=$'+
[-?\n@(#)\$Id: termclock (Roland Mainz) 2009-12-02 \$\n]
[-author?Roland Mainz <roland.mainz@nrubsig.org>]
[-author?David Korn <dgk@research.att.com>]
[+NAME?termclock - analog clock for terminals]
[+DESCRIPTION?\btermclock\b is an analog clock for terminals.
The termclock program displays the time in analog or digital
form. The time is continuously updated at a frequency which
may be specified by the user.]
[u:update?Update interval (defaults to 0.9 seconds).]:[interval]
[+SEE ALSO?\bksh93\b(1), \bxclock\b(1)]
'
while getopts -a "${progname}" "${termclock_usage}" OPT ; do
# printmsg "## OPT=|${OPT}|, OPTARG=|${OPTARG}|"
u) update_interval=${OPTARG} ;;
*) usage ;;
esac
done
# prechecks
(( update_interval >= 0. && update_interval <= 7200. )) || fatal_error $"invalid update_interval value."
# create temporary file for double-buffering and register an EXIT trap
# to remove this file when the shell interpreter exits
trap 'rm -f "${scratchfile}"' EXIT
rm -f "${scratchfile}" ; redirect 6<> "${scratchfile}" || fatal_error $"Could not create temporary file."
# register trap to handle window size changes
trap 'init_screen="true"' WINCH
# exiting - put cursor below clock
exit 0
# EOF.