6 # The contents of this file are subject to the terms of the
7 # Common Development and Distribution License (the "License").
8 # You may not use this file except in compliance with the License.
10 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
11 # or http://www.opensolaris.org/os/licensing.
12 # See the License for the specific language governing permissions
13 # and limitations under the License.
15 # When distributing Covered Code, include this CDDL HEADER in each
16 # file and include the License file at usr/src/OPENSOLARIS.LICENSE.
17 # If applicable, add the following below this CDDL HEADER, with the
18 # fields enclosed by brackets "[]" replaced with your own identifying
19 # information: Portions Copyright [yyyy] [name of copyright owner]
25 # Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
29 # termclock - a simple analog clock for terminals
32 # Solaris needs /usr/xpg6/bin:/usr/xpg4/bin because the tools in /usr/bin are not POSIX-conformant
33 export PATH
=/usr
/xpg
6/bin
:/usr
/xpg
4/bin
:/bin
:/usr
/bin
35 # Make sure all math stuff runs in the "C" locale to avoid problems
36 # with alternative # radix point representations (e.g. ',' instead of
37 # '.' in de_DE.*-locales). This needs to be set _before_ any
38 # floating-point constants are defined in this script).
39 if [[ "${LC_ALL}" != "" ]] ; then
41 LC_MONETARY
="${LC_ALL}" \
42 LC_MESSAGES
="${LC_ALL}" \
43 LC_COLLATE
="${LC_ALL}" \
51 print
-u2 "${progname}: $*"
55 # cache tput values (to avoid |fork()|'ing a "tput" child every second)
58 # static variable as cache for "tput_cup"
59 typeset
-S -A tput_cup_cache
62 nameref c
="tput_cup_cache[\"${y}_${x}\"]"
64 if [[ "$c" == "" ]] ; then
65 # fast path for known terminal types
66 if [[ ${TERM} == ~
(Elr
)(vt100|vt220|xterm|xterm-color|dtterm
) ]] ; then
67 c
="${ printf "\E[%d;%dH" y+1 x+1 ; }"
69 c
="${ tput cup $y $x ; }"
77 # Get terminal size and put values into a compound variable with the integer
78 # members "columns" and "lines"
79 function get_term_size
83 rect.columns
=${ tput cols ; } ||
return 1
84 rect.lines
=${ tput lines ; } ||
return 1
95 for(( angle
=0.0 ; angle
< 360.
; angle
+=6 )) ; do
97 a
=angle
/360.
*(2*M_PI
) ,
99 x
=clock.len_x
*cos
(a
) ,
103 tput_cup $
(( y
+clock.middle_y
)) $
(( x
+clock.middle_x
))
105 # add "mark" every 30 degrees
106 if (( int
(angle
)%30 == 0 )) ; then
107 print
-r -n "$(((++i)%12+1))"
122 (( a
=angle
/360.
*(2*M_PI
) ))
124 for (( s
=0.0 ; s
< 10.
; s
+=0.5 )) ; do
126 x
=(clock.len_x
*(s
/10.
)*(length
/100.
))*cos
(a
) ,
127 y
=(clock.len_y
*(s
/10.
)*(length
/100.
))*sin
(a
)
130 tput_cup $
(( y
+clock.middle_y
)) $
(( x
+clock.middle_x
))
131 print
-r -n -- "${ch}"
136 function draw_clock_hand
139 draw_hand $
(( 360.
*(hand.val
/hand.scale
)-90.
)) "${hand.ch}" ${hand.length}
143 function clear_clock_hand
146 draw_hand $
(( 360.
*(hand.val
/hand.scale
)-90.
)) " " ${hand.length}
154 # note: we can't use subshells when writing to the double-buffer file because this
155 # will render the tput value cache useless
157 if ${init_screen} ; then
160 get_term_size termsize || fatal_error $
"Couldn't get terminal size."
163 clock.middle_x
=termsize.
columns
/2.
-.5 ,
164 clock.middle_y
=termsize.lines
/2.
-.5 ,
165 clock.len_x
=termsize.
columns
/2-2 ,
166 clock.len_y
=termsize.lines
/2-2 ,
176 (( ${ date +"hours.val=%H , minutes.val=%M , seconds.val=%S" ; } ))
178 # small trick to get a smooth "analog" flair
180 hours.val
+=minutes.val
/60.
,
181 minutes.val
+=seconds.val
/60.
184 draw_clock_hand seconds
185 draw_clock_hand minutes
186 draw_clock_hand hours
188 # move cursor to home position
195 redirect
6<&- ; rm -f "${scratchfile}" ; redirect
6<> "${scratchfile}"
197 c
="" ; read -r -t ${update_interval} -N 1 c
198 if [[ "$c" != "" ]] ; then
200 ~
(Fi
)q | $
'\E') return 0 ;;
205 clear_clock_hand hours
206 clear_clock_hand minutes
207 clear_clock_hand seconds
215 getopts -a "${progname}" "${termclock_usage}" OPT
'-?'
226 typeset progname
="${ basename "${0}" ; }"
228 float
-r M_PI
=3.14159265358979323846
236 typeset init_screen
="true"
246 # set clock properties
263 seconds.length
=90 seconds.scale
=60 seconds.ch
=$
"s"
264 minutes.length
=75 minutes.scale
=60 minutes.ch
=$
"m"
265 hours.length
=50 hours.scale
=12 hours.ch
=$
"h"
267 float update_interval
=0.9
269 typeset
-r termclock_usage
=$
'+
270 [-?\n@(#)\$Id: termclock (Roland Mainz) 2009-12-02 \$\n]
271 [-author?Roland Mainz <roland.mainz@nrubsig.org>]
272 [-author?David Korn <dgk@research.att.com>]
273 [+NAME?termclock - analog clock for terminals]
274 [+DESCRIPTION?\btermclock\b is an analog clock for terminals.
275 The termclock program displays the time in analog or digital
276 form. The time is continuously updated at a frequency which
277 may be specified by the user.]
278 [u:update?Update interval (defaults to 0.9 seconds).]:[interval]
279 [+SEE ALSO?\bksh93\b(1), \bxclock\b(1)]
282 while getopts -a "${progname}" "${termclock_usage}" OPT
; do
283 # printmsg "## OPT=|${OPT}|, OPTARG=|${OPTARG}|"
285 u
) update_interval
=${OPTARG} ;;
292 which tput >/dev
/null || fatal_error $
"tput not found."
293 (( update_interval
>= 0.
&& update_interval
<= 7200.
)) || fatal_error $
"invalid update_interval value."
295 # create temporary file for double-buffering and register an EXIT trap
296 # to remove this file when the shell interpreter exits
297 scratchfile
="${ mktemp -t "termclock.ppid${PPID}_pid$$.XXXXXX" ; }"
298 [[ "${scratchfile}" != "" ]] || fatal_error $
"Could not create temporary file name."
299 trap 'rm -f "${scratchfile}"' EXIT
300 rm -f "${scratchfile}" ; redirect
6<> "${scratchfile}" || fatal_error $
"Could not create temporary file."
302 # register trap to handle window size changes
303 trap 'init_screen="true"' WINCH
307 # exiting - put cursor below clock
308 tput_cup $
((termsize.lines-2
)) 0