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 # gnaw - a simple ksh93 technology demo
31 # Note that this script has been written with the main idea to show
32 # many of ksh93's new features (comparing to ksh88/bash) and not
33 # as an example of efficient&&clean script code (much of the code
34 # could be done more efficient using compound variables, this script
35 # focus is the usage of associative arrays).
38 # Solaris needs /usr/xpg6/bin:/usr/xpg4/bin because the tools in /usr/bin are not POSIX-conformant
39 export PATH
=/usr
/xpg
6/bin
:/usr
/xpg
4/bin
:/bin
:/usr
/bin
41 # Make sure all math stuff runs in the "C" locale to avoid problems
42 # with alternative # radix point representations (e.g. ',' instead of
43 # '.' in de_DE.*-locales). This needs to be set _before_ any
44 # floating-point constants are defined in this script).
45 if [[ "${LC_ALL}" != "" ]] ; then
47 LC_MONETARY
="${LC_ALL}" \
48 LC_MESSAGES
="${LC_ALL}" \
49 LC_COLLATE
="${LC_ALL}" \
55 function print_setcursorpos
57 print
-n -- "${vtcode[cup_${1}_${2}]}"
62 ${quiet} || print
-n -- "${vtcode["bel"]}"
67 print
-u2 "${progname}: $*"
71 # Get terminal size and put values into a compound variable with the integer
72 # members "columns" and "lines"
73 function get_term_size
77 rect.columns
=${ tput cols ; } ||
return 1
78 rect.lines
=${ tput lines ; } ||
return 1
83 function print_levelmap
85 integer screen_y_offset
=$1
86 integer start_y_pos
=$2 # start at this line in the map
87 integer max_numlines
=$3 # maximum lines we're allowed to render
92 print_setcursorpos
0 ${screen_y_offset}
94 for (( y
=start_y_pos
; (y-start_y_pos
) < max_numlines
&& y
< levelmap
["max_y"] ; y
++ )) ; do
96 for (( x
=0 ; x
< levelmap
["max_x"] ; x
++ )) ; do
97 line
+="${levelmap["${x}_${y}"]}"
103 # print lines filled with spaces for each line not filled
105 line
="${vtcode["spaceline"]:0:${levelmap["max_x"]}}"
106 for (( ; (y-start_y_pos
) < max_numlines
; y
++ )) ; do
112 function level_completed
116 typeset render_buffer
="$(
117 print -n -- "${vtcode["clear"]}"
120 # ###### # # ###### #
125 ###### ###### ## ###### ######
129 ##### #### # # ######
134 ##### #### # # ######
139 printf " SCORE
: --> %s
<--\n" "${player["score"]}"
140 printf " LIVES
: --> %s
<--\n" "${player["lives"]}"
142 print
-- "${render_buffer}${end_of_frame}"
144 # wait five seconds and swallow any user input
145 for (( i
=0 ; i
< 50 ; i
++ )) ; do
146 read -r -t 0.1 -n 1 dummy
149 print
"Press any key to continue...${end_of_frame}"
150 # wait five secs or for a key
151 read -r -t 5 -n 1 dummy
158 typeset render_buffer
="$(
159 print -n -- "${vtcode["clear"]}"
171 #### # # ###### #####
180 printf "\n SCORE
: --> %s
<--\n" "${player["score"]}"
182 print
-r -- "${render_buffer}${end_of_frame}"
184 # wait five seconds and swallow any user input
185 for (( i
=0 ; i
< 50 ; i
++ )) ; do
186 read -r -t 0.1 -n 1 dummy
189 print
"Press any key to continue...${end_of_frame}"
190 # wait five secs or for a key
191 read -r -t 5 -n 1 dummy
197 typeset render_buffer
="$(
201 # # ## # # # # # # ###
202 # # # # # # # # # ###
203 # #### # # # # # # # # #
204 # # # # # ####### # # #
205 # # # ## # # # # # ###
206 ##### # # # # ## ## ###
209 print
-- "${vtcode["clear"]}${render_buffer}"
211 # wait two seconds and swallow any user input
212 for (( i
=0 ; i
< 20 ; i
++ )) ; do
213 read -r -t 0.1 -n 1 dummy
216 print
"\n (The KornShell 93 maze game)"
222 function attract_mode
225 # Now present some info, line-by-line in an endless loop
226 # until the user presses a key (we turn the "magic" return
228 integer
-r magic_return_code
=69
230 IFS
='' ; # Make sure we do not swallow whitespaces
243 ########################
244 ############################
245 ####### ###### #######
246 ###### ###### ########
247 ####### ###### #######
248 ##############################
249 ##############################
250 ##############################
251 ##############################
252 ##############################
253 ######### ######## #########
264 (roland.mainz@nrubsig.org)
272 ########################
273 #################**############
274 ################################
275 ############################
276 ######################
278 ######################
279 ############################
280 ################################
281 ##############################
282 ########################
306 # clear screen, line-by-line
307 for (( i
=0 ; i
< termsize.lines
; i
++ )) ; do print
"" ; done
308 ) |
(while read -r line
; do
309 read -r -t 0.3 -n 1 c
<&5
310 [[ "$c" != "" ]] && exit ${magic_return_code}
313 (( $?
== magic_return_code
)) && exit ${magic_return_code}
315 (( $?
== magic_return_code
)) && return 0
325 integer selected_level
=0
328 # built list of available levels based on the "function levelmap_.*"
329 # built into this script
330 typeset
-f |
egrep "^function.*levelmap_.*" |
sed 's/^function //' |
332 levellist
[numlevels
]="$l"
336 # swallow any queued user input (e.g. drain stdin)
337 read -r -t 0.1 -n 100 dummy
340 # menu loop with timeout (which switches to "attract mode")
342 print
-n -- "${vtcode["clear"]}"
345 >======================================\
347 > | OO| / _.-' .-. .-. .-. .-. |
348 > | | \ '-. '-' '-' '-' '-' |
350 >======\ /================\ .-. |
352 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
354 print
" GNAW - the ksh93 maze game"
357 print
"\t - [L]evels:"
358 for (( i
=0 ; i
< numlevels
; i
++ )) ; do
359 printf "\t %s %s \n" "$( (( i == selected_level )) && print -n "*" || print -n " ")" "${levellist[i]##levelmap_}"
362 print
"\t - Rendering options:"
363 printf "\t [%s] Use [U]nicode\n" "$( (( game_use_unicode == 1 )) && print -n "x
" || print -n "_
" )"
364 printf "\t [%s] Use [C]olors\n" "$( (( game_use_colors == 1 )) && print -n "x
" || print -n "_
" )"
366 print
"\t - [S]tart - [Q]uit"
368 # wait 30 secs (before we switch to "attract mode")
369 c
="" ; read -r -t 30 -n 1 c
371 'l') (( selected_level
=(selected_level
+numlevels
+1) % numlevels
)) ;;
372 'L') (( selected_level
=(selected_level
+numlevels-1
) % numlevels
)) ;;
374 (( game_use_colors
== 1 )) && print
-- "${vtcode["bg_black"]}"
375 case "${game_use_colors}${game_use_unicode}" in
376 "00") main_loop
"${levellist[selected_level]}" ;;
377 "01") main_loop
"${levellist[selected_level]}" | map_filter
0 1 ;;
378 "10") main_loop
"${levellist[selected_level]}" | map_filter
1 0 ;;
379 "11") main_loop
"${levellist[selected_level]}" | map_filter
1 1 ;;
381 print
-- "${vtcode["vtreset"]}"
384 # make sure we do not exit on a cursor key (e.g. <esc>[A,B,C,D)
385 read -r -t 0.01 -n 1 c
386 if [[ "$c" == "[" ]] ; then
387 # this was a cursor key sequence, just eat the 3rd charcater
388 read -r -t 0.01 -n 1 c
393 ~
(Fi
)u
) (( game_use_unicode
=(game_use_unicode
+2+1) % 2)) ;;
394 ~
(Fi
)c
) (( game_use_colors
=(game_use_colors
+2+1) % 2)) ;;
395 "") break ;; # timeout, switch to attract mode
400 print
-n -- "${vtcode["clear"]}"
406 function levelmap_stripes
409 ###################################
410 #....... ............... P #
411 #########..#################..### #
412 #########..#################..### #
413 #....... .. ..............# #
414 ############### ################ #
415 ############### ################ #
416 #............. M ..............# #
417 ##..##################### ###### #
418 ##..##################### ###### #
419 #....... ........... .......# #
420 ######## ############ ######### #
421 # #### ############ ######### #
422 # #.................. ......# #
423 # ############################### #
425 ###################################
430 function levelmap_livad
433 #####################################################
435 # ############## ############### ################ #
436 # #............ P ..............# #
437 # .#############################################.# #
438 # #.#.......... ............#. #
439 # #.#.########## ############### ############.#.# #
440 # #...#........ ..........#...# #
441 # #...#.#####################################.#.#.# #
442 # #...#.#...... ........#...#.# #
443 # #.#.#...###### #########################.#.#.#.# #
444 # .#.....#.... M ......#...#.#.# #
445 # #.#.#...####################### ########.#.#.#.# #
446 # #...#.#...... ........#...#.# #
447 # #...#.######## ############### ##########.#.#.# #
448 # #...#........ ..........#...# #
449 # #.#.#########################################.#.# #
450 # #.#.......... ............#. #
451 # .############ ############### ##############.# #
452 # #............ ..............# #
453 # ################################################# #
455 #####################################################
460 function levelmap_classic1
463 #########################
464 #.P.........#...........#
465 #.####.####.#.####.####.#
466 #.# #.# #.#.# #.# #.#
467 #.# #.# #.#.# #.# #.#
468 #.####.####.#.####.####.#
469 #.......................#
470 #.####.#.#######.#.####.#
472 #.####.#.#######.#.####.#
473 #......#....#....#......#
474 ######.####.#.####.######
476 ###### # ## ## # ######
477 ###### # # # # ######
479 ###### # ####### # ######
481 ###### # ####### # ######
482 ###### # # # # ######
483 ######.#.#######.#.######
484 #...........#...........#
485 #.###.###...#...###.###.#
486 #...#...............#...#
487 ###.#....#######....#.###
488 # #.#..#.# #.#..#.# #
489 ###....#.#######.#....###
490 #......#....#....#......#
491 #.#########.#.#########.#
492 #.......................#
493 #########################
498 function levelmap_classic2
501 #######################
502 #.P...#.........#.....#
503 #.###.#.#######.#.###.#
504 #.....................#
505 ###.#.####.#.####.#.###
506 ###.#......#......#.###
507 ###.###.#######.###.###
508 ###.................###
509 ###.###.### ###.###.###
511 ###.#.#.#######.#.#.###
512 #.....#.........#.....#
513 ###.#####..#..#####.###
514 ###........#........###
515 ###.###.#######.###.###
516 #.....................#
517 #.###.####.#.####.###.#
518 #.###.#....#....#.###.#
519 #.###.#.#######.#.###.#
520 #.....................#
521 #######################
526 function levelmap_easy
545 function levelmap_sunsolaristext
548 ################################################
551 # #### # # #.#..# M #
556 # #### #### # ## ##### # #### #
557 # # #. .# # # # #....# # # #
558 # #### # # # # P # #....# # #### #
559 # # # ### #.#### #.### # # #
560 # # .# #. .. # # #...# # # # #
561 # #### #### ###### . # ....# # ####. #
562 ################################################
567 function read_levelmap
569 typeset map
="$( $1 )"
578 while read -r line
; do
579 for (( x
=0 ; x
< ${#line} ; x
++ )) ; do
585 # log start position of monsters
586 levelmap
["monsterstartpos_x"]="$x"
587 levelmap
["monsterstartpos_y"]="$y"
591 # log start position of player
592 levelmap
["playerstartpos_x"]="$x"
593 levelmap
["playerstartpos_y"]="$y"
598 levelmap
["${x}_${y}"]="$c"
603 levelmap
["max_x"]=${maxx}
604 levelmap
["max_y"]=${y}
605 levelmap
["numdots"]=${numdots}
608 if [[ "${levelmap["monsterstartpos_x"]}" == "" ]] ; then
609 fatal_error
"read_levelmap: monsterstartpos_x is empty."
611 if [[ "${levelmap["playerstartpos_x"]}" == "" ]] ; then
612 fatal_error
"read_levelmap: playerstartpos_x is empty."
620 case "${.sh.subscript}" in
622 if [[ "${levelmap["${player["pos_x"]}_${.sh.value}"]}" == "#" ]] ; then
623 .sh.value
=${player["pos_y"]}
629 if [[ "${levelmap["${.sh.value}_${player["pos_y"]}"]}" == "#" ]] ; then
630 .sh.value
=${player["pos_x"]}
640 case "${.sh.subscript}" in
642 if [[ "${levelmap["${monster[${currmonster}_"pos_x"]}_${.sh.value}"]}" == "#" ]] ; then
643 .sh.value
=${monster[${currmonster}_"pos_y"]}
644 # turn homing off when the monster hit a wall
645 monster
[${currmonster}_
"homing"]=0
650 if [[ "${levelmap["${.sh.value}_${monster[${currmonster}_"pos_y"]}"]}" == "#" ]] ; then
651 .sh.value
=${monster[${currmonster}_"pos_x"]}
652 # turn homing off when the monster hit a wall
653 monster
[${currmonster}_
"homing"]=0
662 # render_buffer is some kind of "background buffer" to "double buffer"
663 # all output and combine it in one write to reduce flickering in the
665 typeset render_buffer
="$(
666 integer screen_y_offset=1
667 integer start_y_pos=0
668 integer render_num_lines=${levelmap["max_y"]}
670 if (( (termsize.lines-3) < levelmap["max_y
"] )) ; then
671 (( start_y_pos=player["pos_y
"] / 2))
672 (( render_num_lines=termsize.lines-5))
675 #print -n -- "${vtcode["clear"]}"
676 print_setcursorpos 0 0
678 # print score (note the " " around "%d
" are neccesary to clean up cruft
679 # when we overwrite the level
680 printf "SCORE
: %05d DOTS
: %.3d LIVES
: %2.d
" "${player["score"]}" "${levelmap["numdots"]}" "${player["lives"]}"
681 print_levelmap ${screen_y_offset} ${start_y_pos} ${render_num_lines}
684 print_setcursorpos ${player["pos_x"]} $((player["pos_y
"]+screen_y_offset-start_y_pos))
688 for currmonster in ${monsterlist} ; do
689 (( m_pos_x=monster[${currmonster}_"pos_x
"] ))
690 (( m_pos_y=monster[${currmonster}_"pos_y
"]+screen_y_offset-start_y_pos ))
692 if (( m_pos_y >= screen_y_offset && m_pos_y < render_num_lines )) ; then
693 print_setcursorpos ${m_pos_x} ${m_pos_y}
699 print_setcursorpos 0 $((render_num_lines+screen_y_offset))
701 print -n " >> ${player["message"]} <<${emptyline:0:${#emptyline}-${#player["message"]}}"
703 print
-r -- "${render_buffer}${end_of_frame}"
704 # print "renderbuffersize=$(print "${render_buffer}" | wc -c) ${end_of_frame}"
710 float sleep_per_cycle
=0.2
711 float seconds_before_read
715 print
-n -- "${vtcode["clear"]}"
720 player
["pos_x"]=${levelmap["playerstartpos_x"]}
721 player
["pos_y"]=${levelmap["playerstartpos_y"]}
722 player
["score"]=0 # player score
723 player
["lives"]=5 # number of lives
724 player
["invulnerable"]=10 # cycles how long the player remains invulnerable
725 player
["message"]="Go..."
727 monsterlist
="maw claw jitterbug tentacle grendel"
729 for currmonster
in ${monsterlist} ; do
730 monster
[${currmonster}_
"pos_x"]=${levelmap["monsterstartpos_x"]}
731 monster
[${currmonster}_
"pos_y"]=${levelmap["monsterstartpos_y"]}
732 monster
[${currmonster}_
"xstep"]=0
733 monster
[${currmonster}_
"ystep"]=0
734 monster
[${currmonster}_
"homing"]=0
737 # main game cycle loop
740 seconds_before_read
=${SECONDS}
741 c
="" ; read -r -t ${sleep_per_cycle} -n 1 c
743 if [[ "$c" != "" ]] ; then
744 # special case handling for cursor keys which are usually composed
745 # of three characters (e.g. "<ESC>[D"). If only <ESC> is hit we
747 if [[ "$c" == $
'\E' ]] ; then
748 read -r -t 0.1 -n 1 c
749 if [[ "$c" != "[" ]] ; then
753 # we assume the user is using the cursor keys, this |read|
754 # should fetch the 3rd byte of the three-character sequence
755 # for the cursor keys
756 read -r -t 0.1 -n 1 c
759 # if the user hit a key the "read" above was interrupted
760 # and didn't wait exactly |sleep_per_cycle| seconds.
761 # We wait here some moments (|rs|="remaining seconds") to
762 # avoid that the game gets "faster" when more user input
764 (( rs
=sleep_per_cycle-
(SECONDS-seconds_before_read
) ))
765 (( rs
> 0.001 )) && sleep ${rs}
770 j|D|
4) (( player
["pos_x"]-=1 )) ;;
771 k|C|
6) (( player
["pos_x"]+=1 )) ;;
772 i|A|
8) (( player
["pos_y"]-=1 )) ;;
773 m|B|
2) (( player
["pos_y"]+=1 )) ;;
778 if [[ "${levelmap["${player["pos_x"]}_${player["pos_y"]}"]}" == "." ]] ; then
779 levelmap
["${player["pos_x"]}_${player["pos_y"]}"]=" "
780 (( levelmap
["numdots"]-=1 ))
782 (( player
["score"]+=10 ))
783 player
["message"]='GNAW!!'
785 if (( levelmap
["numdots"] <= 0 )) ; then
792 # generic player status change
793 if (( player
["invulnerable"] > 0 )) ; then
794 (( player
["invulnerable"]-=1 ))
796 if (( player
["lives"] <= 0 )) ; then
802 for currmonster
in ${monsterlist} ; do
803 # make monster as half as slow then the others when it is following the user
804 if (( monster
[${currmonster}_
"homing"] > 0 )) ; then
805 (( (num_cycles
%2) > 0 )) && continue
808 if [[ ${monster[${currmonster}_"pos_x"]} == ${player["pos_x"]} ]] ; then
809 if (( (monster
[${currmonster}_
"pos_y"]-player["pos_y"]) > 0 )) ; then
810 (( monster
[${currmonster}_
"xstep"]=+0 , monster
[${currmonster}_
"ystep"]=-1 ))
812 (( monster
[${currmonster}_
"xstep"]=+0 , monster
[${currmonster}_
"ystep"]=+1 ))
814 monster
[${currmonster}_
"homing"]=1
815 if (( player
["invulnerable"] <= 0 )) ; then
816 player
["message"]="Attention: ${currmonster} is chasing you"
818 elif (( monster
[${currmonster}_
"pos_y"] == player
["pos_y"] )) ; then
819 if (( (monster
[${currmonster}_
"pos_x"]-player["pos_x"]) > 0 )) ; then
820 (( monster
[${currmonster}_
"xstep"]=-1 , monster
[${currmonster}_
"ystep"]=-0 ))
822 (( monster
[${currmonster}_
"xstep"]=+1 , monster
[${currmonster}_
"ystep"]=+0 ))
824 monster
[${currmonster}_
"homing"]=1
825 if (( player
["invulnerable"] <= 0 )) ; then
826 player
["message"]="Attention: ${currmonster} is chasing you"
829 if (( monster
[${currmonster}_
"homing"] == 0 )) ; then
830 case $
((SECONDS
% 6 + RANDOM
% 4)) in
831 0) (( monster
[${currmonster}_
"xstep"]=+0 , monster
[${currmonster}_
"ystep"]=+0 )) ;;
832 2) (( monster
[${currmonster}_
"xstep"]=+0 , monster
[${currmonster}_
"ystep"]=+1 )) ;;
833 3) (( monster
[${currmonster}_
"xstep"]=+1 , monster
[${currmonster}_
"ystep"]=+0 )) ;;
834 5) (( monster
[${currmonster}_
"xstep"]=+0 , monster
[${currmonster}_
"ystep"]=-1 )) ;;
835 6) (( monster
[${currmonster}_
"xstep"]=-1 , monster
[${currmonster}_
"ystep"]=+0 )) ;;
840 (( monster
[${currmonster}_"pos_x"]=monster[${currmonster}_"pos_x"]+monster[${currmonster}_
"xstep"] ))
841 (( monster
[${currmonster}_"pos_y"]=monster[${currmonster}_"pos_y"]+monster[${currmonster}_
"ystep"] ))
843 # check if a monster hit the player
844 if (( player
["invulnerable"] <= 0 )) ; then
845 if (( monster
[${currmonster}_
"pos_x"] == player
["pos_x"] && \
846 monster
[${currmonster}_
"pos_y"] == player
["pos_y"] )) ; then
847 # if player was hit by a monster take one life and
848 # make him invulnerable for 10 cycles to avoid that
849 # the next cycle steals more lives
850 player
["message"]="Ouuuchhhh"
851 player
["invulnerable"]=10
852 (( player
["lives"]-=1 ))
854 beep
; beep
; sleep 0.2 ; beep
; beep
866 typeset ch_player ch_monster ch_wall var
868 if (( $1 == 1 )) ; then
869 ch_player
="${vtcode["fg_yellow"]}"
870 ch_monster
="${vtcode["fg_red"]}"
871 ch_wall
="${vtcode["fg_blue"]}"
878 if (( $2 == 1 )) ; then
880 ch_player
+="$(printf '\u[24d2]')"
881 ch_monster
+="$(printf '\u[2605]')"
882 ch_wall
+="$(printf '\u[25a6]')"
890 # note that this filter currently defeats the "double-buffering"
891 while IFS
='' read -r -d "${end_of_frame}" var
; do
892 var
="${var// /${vtcode["fg_grey"]} }"
893 var
="${var//\./${vtcode["fg_lightred"]}.}"
894 var
="${var//@/${ch_player}}"
895 var
="${var//x/${ch_monster}}"
896 var
="${var//#/${ch_wall}}"
905 # restore stty settings
915 getopts -a "${progname}" "${gnaw_usage}" OPT
'-?'
920 # make sure we use the ksh93 "cat" builtin which supports the "-u" option
925 typeset progname
="${ basename "${0}" ; }"
939 # global rendering options
940 integer game_use_colors
=0
941 integer game_use_unicode
=0
943 typeset
-r gnaw_usage
=$
'+
944 [-?\n@(#)\$Id: gnaw (Roland Mainz) 2009-05-09 \$\n]
945 [-author?Roland Mainz <roland.mainz@nrubsig.org>]
946 [+NAME?gnaw - maze game written in ksh93]
947 [+DESCRIPTION?\bgnaw\b is a maze game.
948 The player maneuvers a yellow "@" sign to navigate a maze while eating
949 small dots. A level is finished when all the dots are eaten. Five monsters
950 (maw, claw, jitterbug, tentacle and grendel) also wander the maze in an attempt
951 to catch the "@". Each level begins with all ghosts in their home, and "@" near
952 the bottom of the maze. The monsters are released from the home one by one at the
953 start of each level and start their rentless hunt after the player.]
954 [q:quiet?Disable use of terminal bell.]
955 [+SEE ALSO?\bksh93\b(1)]
958 while getopts -a "${progname}" "${gnaw_usage}" OPT
; do
959 # printmsg "## OPT=|${OPT}|, OPTARG=|${OPTARG}|"
968 # save stty values and register the exit trap which restores these values on exit
969 saved_stty
="$(stty -g)"
974 # set stty values, "-icanon min 1 time 0 -inpck" should improve input latency,
975 # "-echo" turns the terminal echo off
976 stty
-icanon min
1 time 0 -inpck -echo
978 get_term_size termsize || fatal_error
"Could not get terminal size."
981 (( termsize.columns
< 60 )) && fatal_error
"Terminal width must be larger than 60 columns (currently ${termsize.columns})."
984 # color values taken from http://frexx.de/xterm-256-notes/, other
985 # codes from http://vt100.net/docs/vt100-tm/
987 ["bg_black"]="$(print -n "\E
[40m
")"
988 ["fg_black"]="$(print -n "\E
[30m
")"
989 ["fg_red"]="$(print -n "\E
[31m
")"
990 ["fg_lightred"]="$(print -n "\E
[1;31m
")"
991 ["fg_green"]="$(print -n "\E
[32m
")"
992 ["fg_lightgreen"]="$(print -n "\E
[1;32m
")"
993 ["fg_yellow"]="$(print -n "\E
[33m
")"
994 ["fg_lightyellow"]="$(print -n "\E
[1;33m
")"
995 ["fg_blue"]="$(print -n "\E
[34m
")"
996 ["fg_lightblue"]="$(print -n "\E
[1;34m
")"
997 ["fg_grey"]="$(print -n "\E
[1;37m
")"
998 ["fg_white"]="$(print -n "\E
[37m
")"
1000 # misc other vt stuff
1001 ["vtreset"]="$(tput reset)"
1002 ["clear"]="$(tput clear)"
1003 ["bel"]="$(tput bel)"
1004 ["spaceline"]="$(for (( i=0 ; i < termsize.columns ; i++ )) ; do print -n " " ; done)"
1007 # character used to as marker that a single frame ends at this point - this
1008 # is used by the "double buffering" code to make sure the "read" builtin
1009 # can read a whole "frame" instead of reading stuff line-by-line
1010 typeset
-r end_of_frame
=$
'\t'
1012 # get terminal sequence to move cursor to position x,y
1013 # (see http://vt100.net/docs/vt100-ug/chapter3.html#CPR)
1015 xterm | xterm-color | vt100 | vt220 | dtterm | sun | sun-color
)
1016 cup
="$(infocmp -1 | \
1017 egrep '^[[:space:]]*cup=' | \
1018 sed -e 's/.*cup=//' \
1019 -e 's/%[%id]*p1[%id]*/%2\\\$d/g' \
1020 -e 's/%[%id]*p2[%id]*/%1\\\$d/g' \
1022 for (( x
=0 ; x
< termsize.columns
; x
++ )) ; do
1023 for (( y
=0 ; y
< termsize.lines
; y
++ )) ; do
1024 vtcode
[cup_
${x}_${y}]="$(printf "${cup}" $((x + 1)) $((y + 1)) )"
1029 printf "# Unrecognised terminal type '%s', fetching %dx%d items from terminfo database, please wait...\n" "${TERM}" "${termsize.columns}" "${termsize.lines}"
1030 for (( x
=0 ; x
< termsize.columns
; x
++ )) ; do
1031 for (( y
=0 ; y
< termsize.lines
; y
++ )) ; do
1032 vtcode
[cup_
${x}_${y}]="$(tput cup ${y} ${x})"
1038 print -- "${vtcode["vtreset"]}"