#!/usr/bin/ksh93.att #!/bin/bash ################################################################ #### #### What is /usr/bin/ksh93.att? #### #### Answer: The latest release of Korn Shell 93 from www.kornshell.com #### You need it to run this script. #### ################################################################ #### #### Program: visualSelect - Menu / Menuing and Data Interface System #### #### Author: Dana French, Mt Xia Inc, dfrench@mtxia.com #### Copyright 2010 by Dana French, All Rights Reserved #### #### Date: 20100519 #### #### Description: #### #### Menu / Menuing and data interface system written in Korn Shell 93. #### #### This script will run in Korn Shell 93 or Bash, but the "shebang" line #### (#!/bin/bash) must be changed to the desired script interpreter. #### #### To begin modifying and using this script, search for the sections #### labeled "USER MODIFY" and change them to fit your requirements. #### #### The purpose of this program is to provide a visual interface into an #### array of values. This interface, written in Korn Shell, provides the #### user with the ability to use single key presses to peform cursor #### movement using the PC keyboard arrow keys, PgUp, PgDn, Home, and End #### keys. It also provides single key press execution for the PC Keyboard #### function keys. #### #### This program uses a Korn Shell array of values and displays that array #### in single or multi column format. The display look-and-feel is user #### configurable and allows the user to specify the number of rows and #### columns to display on the screen. The user can then navigate through #### the array values dislayed on one or more screens using the PC keyboard #### cursor movement keys. Items from the array can be selected by the #### user to perform further processing. #### #### AIX README: Download the current release of Korn Shell 93 from #### "http://www.kornshell.com" if you want to run this script under the IBM #### AIX operating system. Even on the latest Versions of AIX (5.3 and 6.1), #### the Korn Shell 93 instance is about 7 years old and is full of bugs. #### When you download the current release of Korn Shell 93, copy it to your #### system as "/usr/bin/ksh93.att" and give it "r-xr-xr-x" (555) #### permissions. #### #### The visualSelect functions were also tested with Cygwin Bash and Cygwin #### Bash in X-Windows; it was functional to varying degrees. #### ################################################################ visualSelect () { # Provides the mechanism of navigating through a array of values displayed # on the screen. The array can be much larger than the displayed area shown # on the screen. This function provides the user/programmer with the # ability to use single key presses (no ENTER key) to perform cursor # movement, such as with the arrow keys on a PC keyboard. displayArray ARY ${IDX} ${XS} ${XE} ${XI} ${YS} ${YE} ${YI} attrset rev mvaddstr ${YS} ${XS} "${ARY[0]}" attroff x=${XS} y=${YS} IDX=0 while : do showcommand "" refresh ANS=$( getresp ) attroff mvaddstr ${y} ${x} "${ARY[IDX]}" ################################################################ #### F1 Function Key / Help #### #### USER MODIFY: The user/programmer should edit and modify this #### section to provide the desired response to pressing the F1 key. #### An example is provided that displays the HELP screen. #### if [[ "_${ANS}" == _"${KEY_F1}" ]] || [[ "_${ANS}" == _"${CTL_F1}" ]] || [[ "_${ANS}" == _"${META_F1}" ]] || [[ "_${ANS}" == _"${VI_F1}" ]] || [[ "_${ANS}" == _"${TXT_F1}" ]] then if (( F1_TOGGLE == FALSE )) then (( F1_TOGGLE = TRUE )) #### Save the user defined screen display geometry settings. (( F1_IDX = IDX )) (( F1_SCR = SCR_NUM )) (( F1_ROWS = ROWS )) (( F1_COLS = COLS )) (( F1_XI = XI )) (( F1_XS = XS )) (( F1_XE = XE )) (( F1_YI = YI )) (( F1_YS = YS )) (( F1_YE = YE )) #### Reset the screen display geometry settings to a single column to #### display the HELP text array. (( ROWS = MAX_ROWS - 9 )) (( COLS = 1 )) (( XS = 5 )) (( XI = ( MAX_COLS - XS ) / COLS )) (( XE = ( COLS * XI ) - XI + XS )) (( YI = 1 )) (( YS = 6 )) (( YE = ( ROWS * YI ) + YS - 1 )) #### Change the screen display array ARY to point to the HELP array. [[ "_${CODE}" == "_ksh" ]] && nameref ARY=HELP [[ "_${CODE}" == "_bash" ]] && ARY=( "${HELP[@]}" ) [[ "_${CODE}" == "_other" ]] && ARY=( "${HELP[@]}" ) ARY_CNT="${#ARY[@]}" (( SCR_NUM = 1 )) (( SCR_CNT = ( ARY_CNT / ( ROWS * COLS ) ) + 1 )) (( IDX = 0 )) SCR_PREFIX="HELP" SCR_LABEL="${SCR_PREFIX} ${SCR_NUM} of ${SCR_CNT}" displayArray ARY ${IDX} ${XS} ${XE} ${XI} ${YS} ${YE} ${YI} refresh else showcommand "F1" (( F1_TOGGLE = FALSE )) #### Reset the screen display geometry settings back to the user #### defined settings, and redisplay the user defined ARY. (( ROWS = F1_ROWS )) (( COLS = F1_COLS )) (( XI = F1_XI )) (( XS = F1_XS )) (( XE = F1_XE )) (( YI = F1_YI )) (( YS = F1_YS )) (( YE = F1_YE )) (( SCR_NUM = F1_SCR )) (( IDX = F1_IDX )) #### Change the screen display array ARY to point back to the user defined #### list array, if the VIEW mode (F2) is false. Otherwise if VIEW (F2) mode #### is true, point the screen display array ARY to the CONTENT array. # DLF [[ "_${CODE}" == "_ksh" ]] && (( F2_TOGGLE == FALSE )) && nameref ARY=FILES # DLF [[ "_${CODE}" == "_ksh" ]] && (( F2_TOGGLE == TRUE )) && nameref ARY=CONTENT [[ "_${CODE}" == "_ksh" ]] && (( F2_TOGGLE == FALSE )) && nameref ARY=FILES [[ "_${CODE}" == "_ksh" ]] && (( F2_TOGGLE == TRUE )) && nameref ARY=CONTENT [[ "_${CODE}" == "_bash" ]] && (( F2_TOGGLE == FALSE )) && ARY=( "${FILES[@]}" ) [[ "_${CODE}" == "_bash" ]] && (( F2_TOGGLE == TRUE )) && ARY=( "${CONTENT[@]}" ) [[ "_${CODE}" == "_other" ]] && (( F2_TOGGLE == FALSE )) && ARY=( "${FILES[@]}" ) [[ "_${CODE}" == "_other" ]] && (( F2_TOGGLE == TRUE )) && ARY=( "${CONTENT[@]}" ) ARY_CNT="${#ARY[@]}" (( SCR_CNT = ( ARY_CNT / ( ROWS * COLS ) ) + 1 )) (( RELIDX = ( IDX / ( ROWS * COLS ) ) * ( ROWS * COLS ) )) SCR_PREFIX="SCRN" SCR_LABEL="${SCR_PREFIX} ${SCR_NUM} of ${SCR_CNT}" displayArray ARY ${RELIDX} ${XS} ${XE} ${XI} ${YS} ${YE} ${YI} refresh fi fi ################################################################ #### F2 Function Key / ENTER Key - View a selected file #### #### USER MODIFY: The user/programmer should edit and modify this #### section to provide the desired response to pressing the F2 key. #### An example is provided that views the contents of a file selected #### from the FILES array. #### if [[ "_${ANS}" == _"${KEY_F2}" ]] || [[ "_${ANS}" == _"${CTL_F2}" ]] || [[ "_${ANS}" == _"${META_F2}" ]] || [[ "_${ANS}" == _"${VI_F2}" ]] || [[ "_${ANS}" == _"${TXT_F2}" ]] || [[ "_${ANS}" == "_${KEY_RET}" ]] then if (( F2_TOGGLE == FALSE )) && (( F1_TOGGLE == FALSE )) then (( F2_TOGGLE = TRUE )) #### Save the user defined screen display geometry settings. (( F2_IDX = IDX )) (( F2_SCR = SCR_NUM )) (( F2_ROWS = ROWS )) (( F2_COLS = COLS )) (( F2_XI = XI )) (( F2_XS = XS )) (( F2_XE = XE )) (( F2_YI = YI )) (( F2_YS = YS )) (( F2_YE = YE )) #### Reset the screen display geometry settings to a single column to #### display the text content of the selected item from the array. (( ROWS = MAX_ROWS - 9 )) (( COLS = 1 )) (( XS = 5 )) (( XI = ( MAX_COLS - XS ) / COLS )) (( XE = ( COLS * XI ) - XI + XS )) (( YI = 1 )) (( YS = 6 )) (( YE = ( ROWS * YI ) + YS - 1 )) #### Load the text content of the selected item into an array called #### CONTENT, one line of text from the selected item per array element. if [[ -r "${ARY[IDX]}" ]] then IFS=$'\n' CONTENT=( $( < "${ARY[IDX]}" ) ) IFS=$' \t\n' else CONTENT[0]="visualSelect: WARNING" CONTENT[1]=" Unable to view contents of file." CONTENT[2]=" No read permission for file \"${ARY[IDX]}\"." fi #### Change the screen display array to point to the CONTENT array. [[ "_${CODE}" == "_ksh" ]] && nameref ARY=CONTENT [[ "_${CODE}" == "_bash" ]] && ARY=( "${CONTENT[@]}" ) [[ "_${CODE}" == "_other" ]] && ARY=( "${CONTENT[@]}" ) ARY_CNT="${#ARY[@]}" (( SCR_NUM = 1 )) (( SCR_CNT = ( ARY_CNT / ( ROWS * COLS ) ) + 1 )) (( IDX = 0 )) SCR_PREFIX="VIEW" SCR_LABEL="${SCR_PREFIX} ${SCR_NUM} of ${SCR_CNT}" displayArray ARY ${IDX} ${XS} ${XE} ${XI} ${YS} ${YE} ${YI} refresh elif (( F2_TOGGLE == TRUE )) && (( F1_TOGGLE == FALSE )) then showcommand "F2" (( F2_TOGGLE = FALSE )) #### Reset the screen display geometry settings back to the user #### defined settings, and redisplay the user defined ARY. (( ROWS = F2_ROWS )) (( COLS = F2_COLS )) (( XI = F2_XI )) (( XS = F2_XS )) (( XE = F2_XE )) (( YI = F2_YI )) (( YS = F2_YS )) (( YE = F2_YE )) (( SCR_NUM = F2_SCR )) (( IDX = F2_IDX )) #### Reset the screen display array ARY back to the user defined list of items. [[ "_${CODE}" == "_ksh" ]] && nameref ARY=FILES [[ "_${CODE}" == "_bash" ]] && ARY=( "${FILES[@]}" ) [[ "_${CODE}" == "_other" ]] && ARY=( "${FILES[@]}" ) unset CONTENT ARY_CNT="${#ARY[@]}" (( SCR_CNT = ( ARY_CNT / ( ROWS * COLS ) ) + 1 )) (( RELIDX = ( IDX / ( ROWS * COLS ) ) * ( ROWS * COLS ) )) SCR_PREFIX="SCRN" SCR_LABEL="${SCR_PREFIX} ${SCR_NUM} of ${SCR_CNT}" displayArray ARY ${RELIDX} ${XS} ${XE} ${XI} ${YS} ${YE} ${YI} refresh fi fi ################################################################ #### F3 Function Key / Quit / Exit #### #### USER MODIFY: The user/programmer should edit and modify this #### section to provide the desired response to pressing the F3 key. #### An example is provided that exits the program when the F3 key #### is pressed. #### if [[ "_${ANS}" == _"${KEY_F3}" ]] || [[ "_${ANS}" == _"${CTL_F3}" ]] || [[ "_${ANS}" == _"${META_F3}" ]] || [[ "_${ANS}" == _"${VI_F3}" ]] || [[ "_${ANS}" == _"${TXT_F3}" ]] || [[ "_${ANS}" == _[Qq][Uu][Ii][Tt] ]] || [[ "_${ANS}" == _[Ee][Xx][Ii][Tt] ]] then displayStatus move ${MAX_ROWS} 1 refresh VSIDX="${IDX}" return 0 fi ################################################################ #### F4 Function Key / Toggle VI command mode #### #### USER MODIFY: The user/programmer should edit and modify this #### section to provide the desired response to pressing the F4 key. #### An example is provided that toggles the VI mode cursor movement #### keys when F4 is pressed. #### if [[ "_${ANS}" == _"${KEY_F4}" ]] || [[ "_${ANS}" == _"${CTL_F4}" ]] || [[ "_${ANS}" == _"${META_F4}" ]] || [[ "_${ANS}" == _"${VI_F4}" ]] || [[ "_${ANS}" == _"${TXT_F4}" ]] then if (( F4_TOGGLE == TRUE )) then (( F4_TOGGLE = FALSE )) else (( F4_TOGGLE = TRUE )) fi displayStatus move ${MAX_ROWS} 1 refresh fi ################################################################ #### F5 Function Key #### #### USER MODIFY: The user/programmer should edit and modify this #### section to provide the desired response to pressing the F5 key. #### An example is provided that toggles the F5 mode when this key #### is pressed. #### if [[ "_${ANS}" == _"${KEY_F5}" ]] || [[ "_${ANS}" == _"${CTL_F5}" ]] || [[ "_${ANS}" == _"${META_F5}" ]] || [[ "_${ANS}" == _"${VI_F5}" ]] || [[ "_${ANS}" == _"${TXT_F5}" ]] then if (( F5_TOGGLE == TRUE )) then (( F5_TOGGLE = FALSE )) else (( F5_TOGGLE = TRUE )) fi displayStatus move ${MAX_ROWS} 1 refresh fi ################################################################ #### F6 Function Key #### #### USER MODIFY: The user/programmer should edit and modify this #### section to provide the desired response to pressing the F6 key. #### An example is provided that toggles the F6 mode when this key #### pressed. #### if [[ "_${ANS}" == _"${KEY_F6}" ]] || [[ "_${ANS}" == _"${CTL_F6}" ]] || [[ "_${ANS}" == _"${META_F6}" ]] || [[ "_${ANS}" == _"${VI_F6}" ]] || [[ "_${ANS}" == _"${TXT_F6}" ]] then if (( F6_TOGGLE == TRUE )) then (( F6_TOGGLE = FALSE )) else (( F6_TOGGLE = TRUE )) fi displayStatus move ${MAX_ROWS} 1 refresh fi ################################################################ #### F7 Function Key #### #### USER MODIFY: The user/programmer should edit and modify this #### section to provide the desired response to pressing the F7 key. #### An example is provided that toggles the F7 mode when this key #### pressed. #### if [[ "_${ANS}" == _"${KEY_F7}" ]] || [[ "_${ANS}" == _"${CTL_F7}" ]] || [[ "_${ANS}" == _"${META_F7}" ]] || [[ "_${ANS}" == _"${VI_F7}" ]] || [[ "_${ANS}" == _"${TXT_F7}" ]] then if (( F7_TOGGLE == TRUE )) then (( F7_TOGGLE = FALSE )) else (( F7_TOGGLE = TRUE )) fi displayStatus move ${MAX_ROWS} 1 refresh fi ################################################################ #### F8 Function Key #### #### USER MODIFY: The user/programmer should edit and modify this #### section to provide the desired response to pressing the F8 key. #### An example is provided that toggles the F8 mode when this key #### pressed. #### if [[ "_${ANS}" == _"${KEY_F8}" ]] || [[ "_${ANS}" == _"${CTL_F8}" ]] || [[ "_${ANS}" == _"${META_F8}" ]] || [[ "_${ANS}" == _"${VI_F8}" ]] || [[ "_${ANS}" == _"${TXT_F8}" ]] then if (( F8_TOGGLE == TRUE )) then (( F8_TOGGLE = FALSE )) else (( F8_TOGGLE = TRUE )) fi displayStatus move ${MAX_ROWS} 1 refresh fi ################################################################ #### F9 Function Key #### #### USER MODIFY: The user/programmer should edit and modify this #### section to provide the desired response to pressing the F9 key. #### An example is provided that toggles the F9 mode when this key #### pressed. #### if [[ "_${ANS}" == _"${KEY_F9}" ]] || [[ "_${ANS}" == _"${CTL_F9}" ]] || [[ "_${ANS}" == _"${META_F9}" ]] || [[ "_${ANS}" == _"${VI_F9}" ]] || [[ "_${ANS}" == _"${TXT_F9}" ]] then if (( F9_TOGGLE == TRUE )) then (( F9_TOGGLE = FALSE )) else (( F9_TOGGLE = TRUE )) fi displayStatus move ${MAX_ROWS} 1 refresh fi ################################################################ #### F10 Function Key #### #### USER MODIFY: The user/programmer should edit and modify this #### section to provide the desired response to pressing the F10 key. #### An example is provided that resizes the display screen to fit a new #### window size. The array displayed is also refreshed to fit the new #### display screen size. #### if [[ "_${ANS}" == _"${KEY_F10}" ]] || [[ "_${ANS}" == _"${CTL_F10}" ]] || [[ "_${ANS}" == _"${META_F10}" ]] || [[ "_${ANS}" == _"${VI_F10}" ]] || [[ "_${ANS}" == _"${TXT_F10}" ]] || [[ "_${ANS}" == _"${KEY_RFSH}" ]] || [[ "_${ANS}" == _"${CTL_RFSH}" ]] || [[ "_${ANS}" == _"${META_RFSH}" ]] || [[ "_${ANS}" == _"${VI_RFSH}" ]] || [[ "_${ANS}" == _"${TXT_RFSH}" ]] then #### Reset the screen display geometry settings the new window size #### and redraw the current array. MAX_ROWS=$( ${CMD_TPUT} lines ) [[ "_${MAX_ROWS}" != _[0-9]* ]] && (( MAX_ROWS = 24 )) (( MAX_ROWS <= 0 )) && (( MAX_ROWS = 24 )) MAX_COLS=$( ${CMD_TPUT} cols ) [[ "_${MAX_COLS}" != _[0-9]* ]] && (( MAX_COLS = 80 )) (( MAX_COLS <= 0 )) && (( MAX_COLS = 80 )) (( XI = ( MAX_COLS - XS ) / COLS )) (( XE = ( COLS * XI ) - XI + XS )) (( ROWS = MAX_ROWS - 9 )) (( YE = ( ROWS * YI ) + YS - 1 )) (( RELIDX = ( IDX / ( ROWS * COLS ) ) * ( ROWS * COLS ) )) displayArray ARY ${RELIDX} ${XS} ${XE} ${XI} ${YS} ${YE} ${YI} refresh fi ################################################################ #### Home Key #### #### The user/programmer should probably NOT edit this section. #### if [[ "_${ANS}" == _"${KEY_HOME}" ]] || [[ "_${ANS}" == _"${CTL_HOME}" ]] || [[ "_${ANS}" == _"${META_HOME}" ]] || [[ "_${ANS}" == _"${VI_HOME}" ]] || [[ "_${ANS}" == _"${TXT_HOME}" ]] then showcommand "HOME" (( SCR_NUM = 1 )) SCR_LABEL="${SCR_PREFIX} ${SCR_NUM} of ${SCR_CNT}" (( IDX = 0 )) displayArray ARY ${IDX} ${XS} ${XE} ${XI} ${YS} ${YE} ${YI} refresh fi ################################################################ #### End Key #### #### The user/programmer should probably NOT edit this section. #### if [[ "_${ANS}" == _"${KEY_END}" ]] || [[ "_${ANS}" == _"${CTL_END}" ]] || [[ "_${ANS}" == _"${META_END}" ]] || [[ "_${ANS}" == _"${VI_END}" ]] || [[ "_${ANS}" == _"${TXT_END}" ]] then showcommand "END" (( SCR_NUM = ( ARY_CNT / ( ROWS * COLS ) ) + 1 )) SCR_LABEL="${SCR_PREFIX} ${SCR_NUM} of ${SCR_CNT}" (( IDX = ( ( ARY_CNT - 1 ) / ( ROWS * COLS ) ) * ( ROWS * COLS ) )) (( RELIDX = ( IDX / ( ROWS * COLS ) ) * ( ROWS * COLS ) )) displayArray ARY ${IDX} ${XS} ${XE} ${XI} ${YS} ${YE} ${YI} (( IDX = ARY_CNT - 1)) refresh fi ################################################################ #### Tab Key #### #### The user/programmer should probably NOT edit this section. #### if [[ "_${ANS}" == _"${KEY_TAB}" ]] || [[ "_${ANS}" == _"${CTL_TAB}" ]] || [[ "_${ANS}" == _"${META_TAB}" ]] || [[ "_${ANS}" == _"${VI_TAB}" ]] || [[ "_${ANS}" == _"${TXT_TAB}" ]] then showcommand "TAB" (( RELIDX = ( IDX + 1 ) % ( ROWS * COLS ) )) if (( RELIDX == 0 )) then (( IDX = IDX + 1 )) (( RELIDX = ( IDX / ( ROWS * COLS ) ) * ( ROWS * COLS ) )) (( SCR_NUM = ( IDX / ( ROWS * COLS ) ) + 1 )) SCR_LABEL="${SCR_PREFIX} ${SCR_NUM} of ${SCR_CNT}" displayArray ARY ${RELIDX} ${XS} ${XE} ${XI} ${YS} ${YE} ${YI} refresh else (( IDX = IDX + 1 )) fi (( IDX >= ARY_CNT )) && (( IDX = ARY_CNT - 1 )) fi ################################################################ #### SHIFT-Tab Key #### #### The user/programmer should probably NOT edit this section. #### if [[ "_${ANS}" == _"${KEY_STB}" ]] || [[ "_${ANS}" == _"${CTL_STB}" ]] || [[ "_${ANS}" == _"${META_STB}" ]] || [[ "_${ANS}" == _"${VI_STB}" ]] || [[ "_${ANS}" == _"${TXT_STB}" ]] then showcommand "SHIFT-TAB" (( RELIDX = IDX % ROWS )) if (( RELIDX == 0 )) then (( IDX = IDX - 1 )) (( RELIDX = ( IDX / ( ROWS * COLS ) ) * ( ROWS * COLS ) )) (( SCR_NUM = ( IDX / ( ROWS * COLS ) ) + 1 )) SCR_LABEL="${SCR_PREFIX} ${SCR_NUM} of ${SCR_CNT}" displayArray ARY ${RELIDX} ${XS} ${XE} ${XI} ${YS} ${YE} ${YI} refresh else (( IDX = IDX - 1 )) fi (( IDX < 0 )) && (( IDX = 0 )) fi ################################################################ #### Down Arrow #### #### The user/programmer should probably NOT edit this section. #### if [[ "_${ANS}" == _"${KEY_DOWN}" ]] || [[ "_${ANS}" == _"${CTL_DOWN}" ]] || [[ "_${ANS}" == _"${META_DOWN}" ]] || [[ "_${ANS}" == _"${VI_DOWN}" ]] || [[ "_${ANS}" == _"${TXT_DOWN}" ]] then showcommand "DOWN" (( RELIDX = ( IDX + 1 ) % ROWS )) if (( RELIDX == 0 )) then (( IDX = IDX + ( ROWS * COLS ) - ROWS + 1)) (( IDX >= ARY_CNT )) && (( IDX = ARY_CNT - 1 )) (( RELIDX = ( IDX / ( ROWS * COLS ) ) * ( ROWS * COLS ) )) (( SCR_NUM = ( IDX / ( ROWS * COLS ) ) + 1 )) SCR_LABEL="${SCR_PREFIX} ${SCR_NUM} of ${SCR_CNT}" displayArray ARY ${RELIDX} ${XS} ${XE} ${XI} ${YS} ${YE} ${YI} refresh else (( IDX = IDX + 1 )) fi (( IDX >= ARY_CNT )) && (( IDX = ARY_CNT - 1 )) fi ################################################################ #### Right Arrow #### #### The user/programmer should probably NOT edit this section. #### if [[ "_${ANS}" == _"${KEY_RIGHT}" ]] || [[ "_${ANS}" == _"${CTL_RIGHT}" ]] || [[ "_${ANS}" == _"${META_RIGHT}" ]] || [[ "_${ANS}" == _"${VI_RIGHT}" ]] || [[ "_${ANS}" == _"${TXT_RIGHT}" ]] then showcommand "RIGHT" (( RELIDX = ( IDX % ( ROWS * COLS ) + ROWS ) - ( ROWS * COLS ) )) if (( RELIDX >= 0 )) then (( IDX = IDX + ROWS )) (( IDX >= ARY_CNT )) && (( IDX = ARY_CNT - 1 )) (( RELIDX = ( IDX / ( ROWS * COLS ) ) * ( ROWS * COLS ) )) (( SCR_NUM = ( IDX / ( ROWS * COLS ) ) + 1 )) SCR_LABEL="${SCR_PREFIX} ${SCR_NUM} of ${SCR_CNT}" displayArray ARY ${RELIDX} ${XS} ${XE} ${XI} ${YS} ${YE} ${YI} refresh else (( IDX = IDX + ROWS )) fi (( IDX >= ARY_CNT )) && (( IDX = ARY_CNT - 1 )) fi ################################################################ #### Up Arrow #### #### The user/programmer should probably NOT edit this section. #### if [[ "_${ANS}" == _"${KEY_UP}" ]] || [[ "_${ANS}" == _"${CTL_UP}" ]] || [[ "_${ANS}" == _"${META_UP}" ]] || [[ "_${ANS}" == _"${VI_UP}" ]] || [[ "_${ANS}" == _"${TXT_UP}" ]] then showcommand "UP" (( RELIDX = IDX % ROWS )) if (( RELIDX == 0 )) then (( IDX = IDX - ( ROWS * COLS ) + ROWS - 1 )) (( RELIDX = ( IDX / ( ROWS * COLS ) ) * ( ROWS * COLS ) )) (( SCR_NUM = ( IDX / ( ROWS * COLS ) ) + 1 )) SCR_LABEL="${SCR_PREFIX} ${SCR_NUM} of ${SCR_CNT}" displayArray ARY ${RELIDX} ${XS} ${XE} ${XI} ${YS} ${YE} ${YI} refresh else (( IDX = IDX - 1 )) fi (( IDX < 0 )) && (( IDX = 0 )) fi ################################################################ ##### Left Arrow #### #### The user/programmer should probably NOT edit this section. #### if [[ "_${ANS}" == _"${KEY_LEFT}" ]] || [[ "_${ANS}" == _"${CTL_LEFT}" ]] || [[ "_${ANS}" == _"${META_LEFT}" ]] || [[ "_${ANS}" == _"${VI_LEFT}" ]] || [[ "_${ANS}" == _"${TXT_LEFT}" ]] then showcommand "LEFT" (( RELIDX = ( IDX % ( ROWS * COLS ) - ROWS ) )) if (( RELIDX < 0 )) then (( IDX = IDX - ROWS )) (( RELIDX = ( IDX / ( ROWS * COLS ) ) * ( ROWS * COLS ) )) (( RELIDX < 0 )) && (( RELIDX = 0 )) (( SCR_NUM = ( IDX / ( ROWS * COLS ) ) + 1 )) SCR_LABEL="${SCR_PREFIX} ${SCR_NUM} of ${SCR_CNT}" displayArray ARY ${RELIDX} ${XS} ${XE} ${XI} ${YS} ${YE} ${YI} refresh else (( ( IDX - ROWS ) >= 0 )) && (( IDX = IDX - ROWS )) fi (( IDX < 0 )) && (( IDX = 0 )) fi ################################################################ ##### PageDown #### #### The user/programmer should probably NOT edit this section. #### if [[ "_${ANS}" == _"${KEY_PGDN}" ]] || [[ "_${ANS}" == _"${CTL_PGDN}" ]] || [[ "_${ANS}" == _"${META_PGDN}" ]] || [[ "_${ANS}" == _"${VI_PGDN}" ]] || [[ "_${ANS}" == _"${TXT_PGDN}" ]] then showcommand "PGDN" (( IDX = IDX + ( ROWS * COLS ) )) (( IDX >= ARY_CNT )) && (( IDX = ARY_CNT - 1)) (( RELIDX = ( IDX / ( ROWS * COLS ) ) * ( ROWS * COLS ) )) (( SCR_NUM = ( IDX / ( ROWS * COLS ) ) + 1 )) SCR_LABEL="${SCR_PREFIX} ${SCR_NUM} of ${SCR_CNT}" displayArray ARY ${RELIDX} ${XS} ${XE} ${XI} ${YS} ${YE} ${YI} refresh fi ################################################################ ##### PageUp #### #### The user/programmer should probably NOT edit this section. #### if [[ "_${ANS}" == _"${KEY_PGUP}" ]] || [[ "_${ANS}" == _"${CTL_PGUP}" ]] || [[ "_${ANS}" == _"${META_PGUP}" ]] || [[ "_${ANS}" == _"${VI_PGUP}" ]] || [[ "_${ANS}" == _"${TXT_PGUP}" ]] then showcommand "PGUP" (( IDX = IDX - ( ROWS * COLS ) )) (( IDX < 0 )) && (( IDX = 0 )) (( RELIDX = ( IDX / ( ROWS * COLS ) ) * ( ROWS * COLS ) )) (( RELIDX < 0 )) && (( RELIDX = 0 )) (( SCR_NUM = ( IDX / ( ROWS * COLS ) ) + 1 )) SCR_LABEL="${SCR_PREFIX} ${SCR_NUM} of ${SCR_CNT}" displayArray ARY ${RELIDX} ${XS} ${XE} ${XI} ${YS} ${YE} ${YI} refresh fi ################################################################ #### Forward Search "/" #### #### The user/programmer should probably NOT edit this section. #### if [[ "_${ANS}" == _"${KEY_FSCH}"* ]] || [[ "_${ANS}" == _"${CTL_FSCH}"* ]] || [[ "_${ANS}" == _"${META_FSCH}"* ]] || [[ "_${ANS}" == _"${VI_FSCH}"* ]] || [[ "_${ANS}" == _"${TXT_FSCH}"* ]] then showcommand "FSCH" [[ "_${ANS}" != _["${KEY_FSCH}${CTL_FSCH}${META_FSCH}${VI_FSCH}"] ]] && [[ "_${ANS}" != _"${TXT_FSCH}" ]] && SEARCHSTRING="${ANS#?}" [[ "_${ANS}" == _"${TXT_FSCH} "* ]] && SEARCHSTRING="${ANS#${TXT_FSCH} }" for (( i=IDX+1; i<=ARY_CNT; ++i )) do if [[ "_${ARY[i]}" == _*"${SEARCHSTRING}"* ]] then IDX="${i}" (( RELIDX = ( IDX / ( ROWS * COLS ) ) * ( ROWS * COLS ) )) (( RELIDX > ARY_CNT )) && (( RELIDX = ARY_CNT )) (( SCR_NUM = ( IDX / ( ROWS * COLS ) ) + 1 )) SCR_LABEL="${SCR_PREFIX} ${SCR_NUM} of ${SCR_CNT}" displayArray ARY ${RELIDX} ${XS} ${XE} ${XI} ${YS} ${YE} ${YI} refresh break fi done fi ################################################################ #### Reverse Search "?" #### #### The user/programmer should probably NOT edit this section. #### if [[ "_${ANS}" == _"${KEY_RSCH}"* ]] || [[ "_${ANS}" == _"${CTL_RSCH}"* ]] || [[ "_${ANS}" == _"${META_RSCH}"* ]] || [[ "_${ANS}" == _"${VI_RSCH}"* ]] || [[ "_${ANS}" == _"${TXT_RSCH}"* ]] then showcommand "RSCH" [[ "_${ANS}" != _["${KEY_RSCH}${CTL_RSCH}${META_RSCH}${VI_RSCH}"] ]] && [[ "_${ANS}" != _"${TXT_RSCH}" ]] && SEARCHSTRING="${ANS#?}" [[ "_${ANS}" == _"${TXT_RSCH} "* ]] && SEARCHSTRING="${ANS#${TXT_RSCH} }" for (( i=IDX-1; i>=0; --i )) do if [[ "_${ARY[i]}" == _*"${SEARCHSTRING}"* ]] then IDX="${i}" (( RELIDX = ( IDX / ( ROWS * COLS ) ) * ( ROWS * COLS ) )) (( RELIDX < 0 )) && (( RELIDX = 0 )) SCR_LABEL="${SCR_PREFIX} ${SCR_NUM} of ${SCR_CNT}" displayArray ARY ${RELIDX} ${XS} ${XE} ${XI} ${YS} ${YE} ${YI} refresh break fi done fi ################################################################ # Now the screen instance of the selected array item will be # highlighted in reverse video. (( RELIDX = IDX % ( ROWS * COLS ) )) (( XPOS = RELIDX / ROWS )) (( YPOS = RELIDX % ROWS )) (( x = XS + ( XPOS * XI ) )) (( y = YS + YPOS )) attrset rev mvaddstr ${y} ${x} "${ARY[IDX]}" attroff done ################################################################ # move the cursor to the bottom of the screen and exit the program. move ${MAX_ROWS} 1 refresh return 0 } ################################################################ ################################################################ ################################################################ function displayStatus { MODELABEL="SELECT" KEYLABEL="F3" (( F2_TOGGLE == TRUE )) && MODELABEL="VIEW ${MODELABEL}" && KEYLABEL="F2 ${KEYLABEL}" (( F3_TOGGLE == TRUE )) && MODELABEL="QUIT ${MODELABEL}" && KEYLABEL="F3 ${KEYLABEL}" (( F4_TOGGLE == TRUE )) && MODELABEL="VI ${MODELABEL}" && KEYLABEL="F4 ${KEYLABEL}" (( F5_TOGGLE == TRUE )) && MODELABEL="F5 ${MODELABEL}" && KEYLABEL="F5 ${KEYLABEL}" (( F6_TOGGLE == TRUE )) && MODELABEL="F6 ${MODELABEL}" && KEYLABEL="F6 ${KEYLABEL}" (( F7_TOGGLE == TRUE )) && MODELABEL="F7 ${MODELABEL}" && KEYLABEL="F7 ${KEYLABEL}" (( F8_TOGGLE == TRUE )) && MODELABEL="F8 ${MODELABEL}" && KEYLABEL="F8 ${KEYLABEL}" (( F9_TOGGLE == TRUE )) && MODELABEL="F9 ${MODELABEL}" && KEYLABEL="F9 ${KEYLABEL}" (( F10_TOGGLE == TRUE )) && MODELABEL="F10 ${MODELABEL}" && KEYLABEL="F10 ${KEYLABEL}" (( F11_TOGGLE == TRUE )) && MODELABEL="F11 ${MODELABEL}" && KEYLABEL="F11 ${KEYLABEL}" (( F12_TOGGLE == TRUE )) && MODELABEL="F12 ${MODELABEL}" && KEYLABEL="F12 ${KEYLABEL}" (( F1_TOGGLE == TRUE )) && MODELABEL="HELP ${MODELABEL}" && KEYLABEL="F1 ${KEYLABEL}" MLEN="${#MODELABEL}" (( MPOS = MAX_COLS - MLEN - 8 )) mvclrtoeol 3 1 mvaddstr 3 ${MPOS} "MODE: ${MODELABEL}" TMP="Use arrow keys to navigate, press ${KEYLABEL} to exit MODE shown above" mvclrtoeol $(( MAX_ROWS - 2 )) 1 mvaddstr $(( MAX_ROWS - 2 )) $(( ( MAX_COLS / 2 ) - ( ${#TMP} / 2 ) )) "${TMP}" return 0 } ################################################################ function displayArray { # Displays the portion of the array identified by the screen dimensions # defined by the user/programmer. [[ "_${CODE}" == "_ksh" ]] && nameref ARY=${1} DAIDX="${2}" DAXS="${3}" DAXE="${4}" DAXI="${5}" DAYS="${6}" DAYE="${7}" DAYI="${8}" clear header for (( x=${DAXS}; x<=${DAXE}; x=x+${DAXI} )) do for (( y=${DAYS}; y<=${DAYE}; y=y+${DAYI} )) do mvaddstr ${y} ${x} "${ARY[${DAIDX}]}" (( ++DAIDX )) refresh done done displayStatus return 0 } ################################################################ function getch { # Get a single character from standard input without requiring a CR/LF TMP_GETCH=$( stty raw 2>/dev/null; dd bs=1 count=1 conv=noerror 2>/dev/null; stty -raw 2>/dev/null ) echo "${TMP_GETCH}" return 0 } ################################################################ function getresp { # Retrieves from standard input, one or more characters sent # by each key press # RET=$'\r' # TAB=$'\t' C1=$( getch ) # checking to see if the first character is an ESC, if so collect # any subsequent characters following the ESC if [[ "_${C1}" == "_${ESC}" ]] then C2=$( getch ) # checking for MicroEMACS style META commands if [[ "_${C2}" == _[Vv0-9] ]] || [[ "_${C2}" == _'<' ]] || [[ "_${C2}" == _'>' ]] then ANS="${C1}${C2}" else C3=$( getch ) ANS="${C1}${C2}${C3}" # checking for PC keyboard style cursor movement commands if [[ "_${C3}" == _[0-9] ]] then C4=$( getch ) ANS="${C1}${C2}${C3}${C4}" # checking for AIX style cursor movement commands if [[ "_${C4}" == _[0-9] ]] then C5=$( getch ) ANS="${C1}${C2}${C3}${C4}${C5}" fi fi fi # checking for ENTER or RETURN key elif [[ "_${C1}" == "_${RET}" ]] then ANS="${RET}" # checking for TAB Key elif [[ "_${C1}" == "_${TAB}" ]] then ANS="${C1}" # checking for VI style colon key elif [[ "_${C1}" == "_:" ]] then C2=$( getch ) ANS="${C1}${C2}" # checking for MicroEMACS style control character keys # test C1 to determine if it matches any non-printing control character elif [[ "_${C1}" == _[${NPC[@]}] ]] then ANS="${C1}" # checking for VI style cursor movement keys elif (( F4_TOGGLE == TRUE )) && [[ "_${C1}" == _[\$hjkl0-9${CTL_D}${CTL_U}] ]] then ANS="${C1}" # otherwise assume it is just a command string being typed else ANS="${C1}"$( getstr ) fi echo "${ANS}" return 0 } ################################################################ function getstr { # Retrieves a string of characters from standard input terminated # when the ENTER key is pressed. read -r GETSTR echo "${GETSTR}" return 0 } ################################################################ function header { # Displays a two line screen header containg information about the program [[ "_${SCRDATE}" == "_" ]] && SCRDATE=$( date +"%m/%d/%y" ) [[ "_${SERVER}" == "_" ]] && SERVER="${LOGNAME}@$( uname -n )" # turn on reverse video attrset rev # Header Line 1 on the screen mvaddstr 1 1 "PGM${PRGNUM}" justifyCenter 1 "${HDRLIN1}" justifyLeft 1 "${SERVER}" # Header Line 2 on the screen mvaddstr 2 1 "${SCR_LABEL}" justifyCenter 2 "${HDRLIN2}" justifyLeft 2 "${SCRDATE}" # turn off reverse video attroff return 0 } ################################################################ function justifyCenter { # Display a string of characters centered on the screen mvaddstr ${1} "$(( ( ${MAX_COLS} - ${#2} ) / 2 ))" "${2}" } ################################################################ function justifyLeft { # Display a string of characters left justified on the screen mvaddstr ${1} "$(( ${MAX_COLS} - ${#2} ))" "${2}" } ################################################################ function showcommand { # Display a command field prompt on the screen, and the command # or name of the key that was pressed. mvclrtoeol 4 5 mvaddstr 4 5 "Command: ${1}" return 0 } ################################################################ function addstr { # "addstr" imported from "Shell Curses" function library [[ "_${1}" != "_" ]] && BUF_SCREEN="${BUF_SCREEN}${1}" return ${?} } ################################################################ function attroff { # "attroff" imported from "Shell Curses" function library addstr "${CMD_ATTROFF}" return ${?} } ################################################################ function attron { # "attron" imported from "Shell Curses" function library return 0 } ################################################################ function attrset { # "attrset" imported from "Shell Curses" function library addstr "$( ${CMD_ATTRSET} ${1} )" return ${?} } ################################################################ function clear { # "clear" imported from "Shell Curses" function library addstr "${CMD_CLEAR}" return ${?} } ################################################################ function clrtoeol { # "clrtoeol" imported from "Shell Curses" function library addstr "${CMD_CLRTOEOL}" return ${?} } ################################################################ function endwin { # "endwin" imported from "Shell Curses" function library unset MAX_ROWS unset MAX_COLS unset BUF_SCREEN return ${?} } ################################################################ function initscr { # "initscr" imported from "Shell Curses" function library PGMNAME="VisualSelect" DEV_NULL="/dev/null" CMD_TPUT="tput" # Terminal "put" command eval CMD_MOVE=\`echo \"`tput cup`\" \| sed \\\ -e \"s/%p1%d/\\\\\${1}/g\" \\\ -e \"s/%p2%d/\\\\\${2}/g\" \\\ -e \"s/%p1%02d/\\\\\${1}/g\" \\\ -e \"s/%p2%02d/\\\\\${2}/g\" \\\ -e \"s/%p1%03d/\\\\\${1}/g\" \\\ -e \"s/%p2%03d/\\\\\${2}/g\" \\\ -e \"s/%p1%03d/\\\\\${1}/g\" \\\ -e \"s/%d\\\;%dH/\\\\\${1}\\\;\\\\\${2}H/g\" \\\ -e \"s/%p1%c/'\\\\\\\`echo \\\\\\\${1} P | dc\\\\\\\`'/g\" \\\ -e \"s/%p2%c/'\\\\\\\`echo \\\\\\\${2} P | dc\\\\\\\`'/g\" \\\ -e \"s/%p1%\' \'%+%c/'\\\\\\\`echo \\\\\\\${1} 32 + P | dc\\\\\\\`'/g\" \\\ -e \"s/%p2%\' \'%+%c/'\\\\\\\`echo \\\\\\\${2} 32 + P | dc\\\\\\\`'/g\" \\\ -e \"s/%p1%\'@\'%+%c/'\\\\\\\`echo \\\\\\\${1} 100 + P | dc\\\\\\\`'/g\" \\\ -e \"s/%p2%\'@\'%+%c/'\\\\\\\`echo \\\\\\\${2} 100 + P | dc\\\\\\\`'/g\" \\\ -e \"s/%i//g\;s/%n//g\"\` CMD_CLEAR="$( ${CMD_TPUT} clear 2>${DEV_NULL} )" # Clear display CMD_LINES="$( ${CMD_TPUT} lines 2>${DEV_NULL} )" # Number of lines on display CMD_COLS="$( ${CMD_TPUT} cols 2>${DEV_NULL} )" # Number of columns on display CMD_CLRTOEOL="$( ${CMD_TPUT} el 2>${DEV_NULL} )" # Clear to end of line CMD_CLRTOBGN="$( ${CMD_TPUT} el1 2>${DEV_NULL} )" # Clear to beginning of line CMD_CLRTOEOD="$( ${CMD_TPUT} ed 2>${DEV_NULL} )" # Clear to end of display CMD_DELCH="$( ${CMD_TPUT} dch1 2>${DEV_NULL} )" # Delete current character CMD_DELETELN="$( ${CMD_TPUT} dl1 2>${DEV_NULL} )" # Delete current line CMD_INSCH="$( ${CMD_TPUT} ich1 2>${DEV_NULL} )" # Insert 1 character CMD_INSERTLN="$( ${CMD_TPUT} il1 2>${DEV_NULL} )" # Insert 1 Line CMD_ATTROFF="$( ${CMD_TPUT} sgr0 2>${DEV_NULL} )" # All Attributes OFF CMD_ATTRSET="${CMD_TPUT}" # requires arg ( rev, blink, etc ) CMD_BEEP="$( ${CMD_TPUT} bel 2>${DEV_NULL} )" # ring bell CMD_LISTER="cat" CMD_SYMLNK="ln -s" if [[ "_${CODE}" == "_ksh" ]] then CMD_ECHO="print" OPT_ECHO='-n --' elif [[ "_${CODE}" == "_bash" ]] then CMD_ECHO="echo" OPT_ECHO='-n' else CMD_ECHO="echo" OPT_ECHO='-n' fi CMD_MAIL="mail" WHOAMI="${LOGNAME}@$( uname -n )" WRITER="dfrench@mtxia.com" CMD_NOTIFY="\${CMD_ECHO} ${OPT_ECHO} \"\${PGMNAME} - \${WHOAMI} - \$( date )\" | \${CMD_MAIL} \${WRITER}" ERROR_PAUSE="sleep 2" IFS_CR=$'\n' IFS_NORM=$' \t\n' MAC_TIME="TIMESTAMP=\`date +\"%y:%m:%d:%H:%M:%S\"\`" MAX_ROWS=$( ${CMD_TPUT} lines ) [[ "_${MAX_ROWS}" != _[0-9]* ]] && (( MAX_ROWS = 24 )) (( MAX_ROWS <= 0 )) && (( MAX_ROWS = 24 )) MAX_COLS=$( ${CMD_TPUT} cols ) [[ "_${MAX_COLS}" != _[0-9]* ]] && (( MAX_COLS = 80 )) (( MAX_COLS <= 0 )) && (( MAX_COLS = 80 )) BUF_SCREEN="" BUF_TOT="" return 0 } ################################################################ function refresh { # "refresh" imported from "Shell Curses" function library if [[ "_${1}" != "_" ]] then eval \${CMD_ECHO} \${OPT_ECHO} \"\${${1}}\" else ${CMD_ECHO} ${OPT_ECHO} "${BUF_SCREEN}" BUF_TOT="${BUF_TOT}${BUF_SCREEN}" BUF_SCREEN="" fi return 0 } ################################################################ function move { # "move" imported from "Shell Curses" function library eval addstr \"${CMD_MOVE}\" return ${?} } ################################################################ function mvaddstr { # "mvaddstr" imported from "Shell Curses" function library move "${1}" "${2}" && addstr "${3}" return ${?} } ################################################################ function mvclrtoeol { # "mvclrtoeol" imported from "Shell Curses" function library move "${1}" "${2}" && clrtoeol return ${?} } ################################################################ function defineHelpContent { # Define the content of the Help Screen Array elements [[ "_${CODE}" == "_ksh" ]] && nameref HELP="${1}" IDX="0" #### #### USER MODIFY: The user/programmer may edit and modify the help #### screen array elements as desired. #### HELP[IDX++]="It is recommended that you download the latest release of" HELP[IDX++]="Korn Shell 93 from 'www.kornshell.com' to use as the command" HELP[IDX++]="interpreter for this script. If you don't, your results will" HELP[IDX++]="be unpredictable." HELP[IDX++]="" HELP[IDX++]="" HELP[IDX++]="======${TAB}=================================" HELP[IDX++]="${TAB}${TAB}Key Definitions" HELP[IDX++]="" HELP[IDX++]="ENTER${TAB}Selects the highlighted item from the array" HELP[IDX++]="TAB${TAB}${TAB}Moves the cursor one position forward in the array" HELP[IDX++]="SHIFT-TAB${TAB}Moves the cursor one position backward in the array" HELP[IDX++]="/string${TAB}Forward search for 'string'" HELP[IDX++]="?string${TAB}Reverse search for 'string'" HELP[IDX++]="" HELP[IDX++]="" HELP[IDX++]="======${TAB}=================================" HELP[IDX++]="${TAB}${TAB}Cursor Movement and Function Keys" HELP[IDX++]="" HELP[IDX++]="F1${TAB}${TAB}Toggle HELP Screen ON or OFF" HELP[IDX++]="F2${TAB}${TAB}View contents of selected array element" HELP[IDX++]="F3${TAB}${TAB}Exit the program" HELP[IDX++]="F4${TAB}${TAB}Toggle ON/OFF VI style command entry" HELP[IDX++]="F5${TAB}${TAB}Toggle ON/OFF F5 Function Key Mode" HELP[IDX++]="F6${TAB}${TAB}Toggle ON/OFF F6 Function Key Mode" HELP[IDX++]="F7${TAB}${TAB}Toggle ON/OFF F7 Function Key Mode" HELP[IDX++]="F8${TAB}${TAB}Toggle ON/OFF F8 Function Key Mode" HELP[IDX++]="F9${TAB}${TAB}Toggle ON/OFF F9 Function Key Mode" HELP[IDX++]="F10${TAB}${TAB}Refresh the Screen Geometry Size and redisplay" HELP[IDX++]="F11${TAB}${TAB}Toggle ON/OFF F11 Function Key Mode" HELP[IDX++]="F12${TAB}${TAB}Toggle ON/OFF F12 Function Key Mode" HELP[IDX++]="" HELP[IDX++]="Left Arrow${TAB}Moves cursor one column to the left" HELP[IDX++]="Right Arrow${TAB}Moves cursor one column to the right" HELP[IDX++]="Up Arrow${TAB}Moves cursor one row up" HELP[IDX++]="Down Arrow${TAB}Moves cursor one row down" HELP[IDX++]="PgUp${TAB}Moves cursor one page up" HELP[IDX++]="PgDn${TAB}Moves cursor one page down" HELP[IDX++]="Home${TAB}Moves cursor to the beginning of the array" HELP[IDX++]="End${TAB}${TAB}Moves cursor to the end of the array" HELP[IDX++]="^\\${TAB}${TAB}Repeat previous forward search" HELP[IDX++]="^]${TAB}${TAB}Repeat previous reverse search" HELP[IDX++]="" HELP[IDX++]="" HELP[IDX++]="======${TAB}=================================" HELP[IDX++]="${TAB}${TAB}Emacs Style Keys" HELP[IDX++]="" HELP[IDX++]="ESC-1${TAB}Toggle HELP Screen ON or OFF" HELP[IDX++]="ESC-2${TAB}View contents of selected array element" HELP[IDX++]="ESC-3${TAB}Exit the program" HELP[IDX++]="ESC-4${TAB}Toggle ON/OFF VI style command entry" HELP[IDX++]="ESC-5${TAB}Toggle ON/OFF F5 Function Key Mode" HELP[IDX++]="ESC-6${TAB}Toggle ON/OFF F6 Function Key Mode" HELP[IDX++]="ESC-7${TAB}Toggle ON/OFF F7 Function Key Mode" HELP[IDX++]="ESC-8${TAB}Toggle ON/OFF F8 Function Key Mode" HELP[IDX++]="ESC-9${TAB}Toggle ON/OFF F9 Function Key Mode" HELP[IDX++]="ESC-0${TAB}Refresh the Screen Geometry Size and redisplay" HELP[IDX++]="" HELP[IDX++]="^F${TAB}${TAB}Moves cursor one column to the left" HELP[IDX++]="^B${TAB}${TAB}Moves cursor one column to the right" HELP[IDX++]="^P${TAB}${TAB}Moves cursor one row up" HELP[IDX++]="^N${TAB}${TAB}Moves cursor one row down" HELP[IDX++]="ESC-V${TAB}Moves cursor one page up" HELP[IDX++]="^V${TAB}${TAB}Moves cursor one page down" HELP[IDX++]="ESC-<${TAB}Moves cursor to the beginning of the array" HELP[IDX++]="ESC->${TAB}Moves cursor to the end of the array" HELP[IDX++]="^L${TAB}${TAB}Refresh the Screen Geometry Size and redisplay" HELP[IDX++]="^S${TAB}${TAB}Repeat previous forward search" HELP[IDX++]="^R${TAB}${TAB}Repeat previous reverse search" HELP[IDX++]="" HELP[IDX++]="" HELP[IDX++]="======${TAB}=================================" HELP[IDX++]="${TAB}${TAB}VI Style Keys" HELP[IDX++]="" HELP[IDX++]=":1${TAB}${TAB}Toggle HELP Screen ON or OFF" HELP[IDX++]=":2${TAB}${TAB}View contents of selected array element" HELP[IDX++]=":3${TAB}${TAB}Exit the program" HELP[IDX++]=":4${TAB}${TAB}Toggle ON/OFF VI style command entry" HELP[IDX++]=":5${TAB}${TAB}Toggle ON/OFF F5 Function Key Mode" HELP[IDX++]=":6${TAB}${TAB}Toggle ON/OFF F6 Function Key Mode" HELP[IDX++]=":7${TAB}${TAB}Toggle ON/OFF F7 Function Key Mode" HELP[IDX++]=":8${TAB}${TAB}Toggle ON/OFF F8 Function Key Mode" HELP[IDX++]=":9${TAB}${TAB}Toggle ON/OFF F9 Function Key Mode" HELP[IDX++]=":0${TAB}${TAB}Refresh the Screen Geometry Size and redisplay" HELP[IDX++]="" HELP[IDX++]="l${TAB}${TAB}Moves cursor one column to the left" HELP[IDX++]="h${TAB}${TAB}Moves cursor one column to the right" HELP[IDX++]="k${TAB}${TAB}Moves cursor one row up" HELP[IDX++]="j${TAB}${TAB}Moves cursor one row down" HELP[IDX++]="^U${TAB}${TAB}Moves cursor one page up" HELP[IDX++]="^D${TAB}${TAB}Moves cursor one page down" HELP[IDX++]="0${TAB}${TAB}Moves cursor to the beginning of the array" HELP[IDX++]="\$${TAB}${TAB}Moves cursor to the end of the array" HELP[IDX++]=":l${TAB}${TAB}Refresh the Screen Geometry Size and redisplay" HELP[IDX++]="/string${TAB}Forward search for 'string'" HELP[IDX++]="?string${TAB}Reverse search for 'string'" HELP[IDX++]="/${TAB}${TAB}Repeat previous forward search" HELP[IDX++]="?${TAB}${TAB}Repeat previous reverse search" HELP[IDX++]="" HELP[IDX++]="" HELP[IDX++]="======${TAB}=================================" HELP[IDX++]="${TAB}${TAB}Text Keys" HELP[IDX++]="" HELP[IDX++]="SHIFT-F 1 ${TAB}Toggle HELP Screen ON or OFF" HELP[IDX++]="SHIFT-F 2 ${TAB}View contents of selected array element" HELP[IDX++]="SHIFT-F 3 ${TAB}Exit the program" HELP[IDX++]="SHIFT-F 4 ${TAB}Toggle ON/OFF VI style command entry" HELP[IDX++]="SHIFT-F 5 ${TAB}Toggle ON/OFF F5 Function Key Mode" HELP[IDX++]="SHIFT-F 6 ${TAB}Toggle ON/OFF F6 Function Key Mode" HELP[IDX++]="SHIFT-F 7 ${TAB}Toggle ON/OFF F7 Function Key Mode" HELP[IDX++]="SHIFT-F 8 ${TAB}Toggle ON/OFF F8 Function Key Mode" HELP[IDX++]="SHIFT-F 9 ${TAB}Toggle ON/OFF F9 Function Key Mode" HELP[IDX++]="SHIFT-F 10 ${TAB}Refresh the Screen Geometry Size and redisplay" HELP[IDX++]="SHIFT-F 11 ${TAB}Toggle ON/OFF F11 Function Key Mode" HELP[IDX++]="SHIFT-F 12 ${TAB}Toggle ON/OFF F12 Function Key Mode" HELP[IDX++]="" HELP[IDX++]="SHIFT-L ${TAB}Moves cursor one column to the left" HELP[IDX++]="SHIFT-R ${TAB}Moves cursor one column to the right" HELP[IDX++]="SHIFT-U ${TAB}Moves cursor one row up" HELP[IDX++]="SHIFT-D ${TAB}Moves cursor one row down" HELP[IDX++]="SHIFT-^ ${TAB}Moves cursor one page up" HELP[IDX++]="SHIFT-V ${TAB}Moves cursor one page down" HELP[IDX++]="SHIFT-H ${TAB}Moves cursor to the beginning of the array" HELP[IDX++]="SHIFT-E ${TAB}Moves cursor to the end of the array" HELP[IDX++]="refresh${TAB}${TAB}Refresh the Screen Geometry Size and redisplay" HELP[IDX++]="search string ${TAB}Forward search for 'string'" HELP[IDX++]="reverse string ${TAB}Reverse search for 'string'" HELP[IDX++]="search ${TAB}Repeat previous forward search" HELP[IDX++]="reverse ${TAB}Repeat previous reverse search" return 0 } ################################################################ ################################################################ ################################################################ #### #### Main body of program begins here #### ################################################################ # Determine the script interpreter from the "shebang" line of this script. read SHEBANG < "${0}" CODE="other" [[ "_${SHEBANG}" == _*ksh* ]] && typeset -r CODE="ksh" [[ "_${SHEBANG}" == _*bash* ]] && declare -r CODE="bash" if [[ "_${CODE}" == "_ksh" ]] then typeset -r TRUE="0" typeset -r FALSE="1" typeset -r ESC=$'\e' typeset -r RET=$'\r' typeset -r TAB=$'\t' elif [[ "_${CODE}" == "_bash" ]] then declare -r TRUE="0" declare -r FALSE="1" declare -r ESC=$'\e' declare -r RET=$'\r' declare -r TAB=$'\t' else TRUE="0" FALSE="1" ESC=$'\e' RET=$'\r' TAB=$'\t' fi ################################################################ # PC Keyboard Key Definitions # - The user should probably NOT modify these definitions # Non-Printing Control Keys (ASCII) NPC[0]=$'\000' NPC[10]=$'\010' NPC[20]=$'\020' NPC[30]=$'\030' NPC[1]=$'\001' NPC[11]=$'\011' NPC[21]=$'\021' NPC[31]=$'\031' NPC[2]=$'\002' NPC[12]=$'\012' NPC[22]=$'\022' NPC[32]=$'\032' NPC[3]=$'\003' NPC[13]=$'\013' NPC[23]=$'\023' NPC[33]=$'\033' NPC[4]=$'\004' NPC[14]=$'\014' NPC[24]=$'\024' NPC[34]=$'\034' NPC[5]=$'\005' NPC[15]=$'\015' NPC[25]=$'\025' NPC[35]=$'\035' NPC[6]=$'\006' NPC[16]=$'\016' NPC[26]=$'\026' NPC[36]=$'\036' NPC[7]=$'\007' NPC[17]=$'\017' NPC[27]=$'\027' NPC[37]=$'\037' # Non-Printing Control Keys (by name) NPC_NUL="${NPC[0]}" NPC_BS="${NPC[10]}" NPC_DLE="${NPC[20]}" NPC_CAN="${NPC[30]}" NPC_SOH="${NPC[1]}" NPC_HT="${NPC[11]}" NPC_DC1="${NPC[21]}" NPC_EM="${NPC[31]}" NPC_STX="${NPC[2]}" NPC_LF="${NPC[12]}" NPC_DC2="${NPC[22]}" NPC_SUB="${NPC[32]}" NPC_ETX="${NPC[3]}" NPC_VT="${NPC[13]}" NPC_DC3="${NPC[23]}" NPC_ESC="${NPC[33]}" NPC_EOT="${NPC[4]}" NPC_FF="${NPC[14]}" NPC_DC4="${NPC[24]}" NPC_FS="${NPC[34]}" NPC_ENQ="${NPC[5]}" NPC_CR="${NPC[15]}" NPC_NAK="${NPC[25]}" NPC_GS="${NPC[35]}" NPC_ACK="${NPC[6]}" NPC_SOL="${NPC[16]}" NPC_SYN="${NPC[26]}" NPC_RS="${NPC[36]}" NPC_BEL="${NPC[7]}" NPC_SI="${NPC[17]}" NPC_ETB="${NPC[27]}" NPC_US="${NPC[37]}" # Control Character Keys CTL_H="${NPC_BS}" CTL_P="${NPC_DLE}" CTL_X="${NPC_CAN}" CTL_A="${NPC_SOH}" CTL_I="${NPC_HT}" CTL_Q="${NPC_DC1}" CTL_Y="${NPC_EM}" CTL_B="${NPC_STX}" CTL_J="${NPC_LF}" CTL_R="${NPC_DC2}" CTL_Z="${NPC_SUB}" CTL_C="${NPC_ETX}" CTL_K="${NPC_VT}" CTL_S="${NPC_DC3}" CTL_D="${NPC_EOT}" CTL_L="${NPC_FF}" CTL_T="${NPC_DC4}" CTL_E="${NPC_ENQ}" CTL_M="${NPC_CR}" CTL_U="${NPC_NAK}" CTL_F="${NPC_ACK}" CTL_N="${NPC_SOL}" CTL_V="${NPC_SYN}" CTL_G="${NPC_BEL}" CTL_O="${NPC_SI}" CTL_W="${NPC_ETB}" # META Keys (variable number of characters) META_H="${ESC}[H" META_P="${ESC}[P" META_X="${ESC}[X" META_A="${ESC}[A" META_I="${ESC}[I" META_Q="${ESC}[Q" META_Y="${ESC}[Y" META_B="${ESC}[B" META_J="${ESC}[J" META_R="${ESC}[R" META_Z="${ESC}[Z" META_C="${ESC}[C" META_K="${ESC}[K" META_S="${ESC}[S" META_D="${ESC}[D" META_L="${ESC}[L" META_T="${ESC}[T" META_E="${ESC}[E" META_M="${ESC}[M" META_U="${ESC}[U" META_F="${ESC}[F" META_N="${ESC}[N" META_V="${ESC}[V" META_G="${ESC}[G" META_O="${ESC}[O" META_W="${ESC}[W" META_0="${ESC}[0~" META_10="${ESC}[10~" META_20="${ESC}[20~" META_30="${ESC}[30~" META_1="${ESC}[1~" META_11="${ESC}[11~" META_21="${ESC}[21~" META_31="${ESC}[31~" META_2="${ESC}[2~" META_12="${ESC}[12~" META_22="${ESC}[22~" META_32="${ESC}[32~" META_3="${ESC}[3~" META_13="${ESC}[13~" META_23="${ESC}[23~" META_33="${ESC}[33~" META_4="${ESC}[4~" META_14="${ESC}[14~" META_24="${ESC}[24~" META_34="${ESC}[34~" META_5="${ESC}[5~" META_15="${ESC}[15~" META_25="${ESC}[25~" META_35="${ESC}[35~" META_6="${ESC}[6~" META_16="${ESC}[16~" META_26="${ESC}[26~" META_36="${ESC}[36~" META_7="${ESC}[7~" META_17="${ESC}[17~" META_27="${ESC}[27~" META_37="${ESC}[37~" META_8="${ESC}[8~" META_18="${ESC}[18~" META_28="${ESC}[28~" META_38="${ESC}[38~" META_9="${ESC}[9~" META_19="${ESC}[19~" META_29="${ESC}[29~" META_39="${ESC}[39~" # Escape Keys ESC_0="${ESC}0" ESC_V="${ESC}v" ESC_1="${ESC}1" ESC_LT="${ESC}<" ESC_2="${ESC}2" ESC_GT="${ESC}>" ESC_3="${ESC}3" ESC_4="${ESC}4" ESC_5="${ESC}5" ESC_6="${ESC}6" ESC_7="${ESC}7" ESC_8="${ESC}8" ESC_9="${ESC}9" ################################################################ #### #### USER MODIFY: The user/programmer may edit and modify the key definitions #### associated with the function keys and cursor movement keys, to match the #### terminal emulation they wish to support. These can also be dynamically #### determined using "tput" with the appropriate TERM environment variable #### setting. #### # Function Keys: Define the various character combinations that should be # recognized for each function key. Each function key may have multiple # character combinations to accommodate a variety of keyboard and user # styles, such as on the PC keyboard: a row of 12 function keys, or the # user may want to press the "Escape" key followed by a number # representing the function key number, or the user may want to press the # colon ":" character followed by a number, or literally press the "F" # key, followed by a number, followed by the "ENTER" key. KEY_F1="${META_11}" CTL_F1="${ESC_1}" META_F1="${ESC}OP" VI_F1=':1' TXT_F1='F1' KEY_F2="${META_12}" CTL_F2="${ESC_2}" META_F2="${ESC}OQ" VI_F2=':2' TXT_F2='F2' KEY_F3="${META_13}" CTL_F3="${ESC_3}" META_F3="${ESC}OR" VI_F3=':3' TXT_F3='F3' KEY_F4="${META_14}" CTL_F4="${ESC_4}" META_F4="${ESC}OS" VI_F4=':4' TXT_F4='F4' KEY_F5="${META_15}" CTL_F5="${ESC_5}" META_F5="${ESC_5}" VI_F5=':5' TXT_F5='F5' KEY_F6="${META_17}" CTL_F6="${ESC_6}" META_F6="${ESC_6}" VI_F6=':6' TXT_F6='F6' KEY_F7="${META_18}" CTL_F7="${ESC_7}" META_F7="${ESC_7}" VI_F7=':7' TXT_F7='F7' KEY_F8="${META_19}" CTL_F8="${ESC_8}" META_F8="${ESC_8}" VI_F8=':8' TXT_F8='F8' KEY_F9="${META_20}" CTL_F9="${ESC_9}" META_F9="${ESC_9}" VI_F9=':9' TXT_F9='F9' KEY_F10="${META_21}" CTL_F10="${ESC_0}" META_F10="${ESC_0}" VI_F10=':0' TXT_F10='F10' KEY_F11="${META_23}" TXT_F11='F11' KEY_F12="${META_24}" TXT_F12='F12' # Cursor Movement Keys: Define the various character combinations that # should be recognized for each cursor movement key. Multiple key # combinations may defined for each cursor movement key to accommodate a # variety of keyboard and user styles (see function key explaination # above). KEY_UP="${META_A}" CTL_UP="${CTL_P}" META_UP="${CTL_P}" VI_UP='k' TXT_UP='U' KEY_LEFT="${META_D}" CTL_LEFT="${CTL_B}" META_LEFT="${CTL_B}" VI_LEFT='h' TXT_LEFT='L' KEY_DOWN="${META_B}" CTL_DOWN="${CTL_N}" META_DOWN="${CTL_N}" VI_DOWN='j' TXT_DOWN='D' KEY_RIGHT="${META_C}" CTL_RIGHT="${CTL_F}" META_RIGHT="${CTL_F}" VI_RIGHT='l' TXT_RIGHT='R' KEY_PGUP="${META_5}" CTL_PGUP="${ESC_V}" META_PGUP="${ESC_V}" VI_PGUP="${CTL_U}" TXT_PGUP='^' KEY_PGDN="${META_6}" CTL_PGDN="${CTL_V}" META_PGDN="${CTL_V}" VI_PGDN="${CTL_D}" TXT_PGDN='V' KEY_HOME="${META_H}" CTL_HOME="${CTL_A}" META_HOME="${ESC_LT}" VI_HOME='0' TXT_HOME='H' KEY_END="${META_F}" CTL_END="${CTL_E}" META_END="${ESC_GT}" VI_END='$' TXT_END='E' # Command Keys: Define the various character combinations that should be # recognized for each command key. Multiple key combinations may defined # for each command key to accommodate a variety of keyboard and user # styles (see function key explaination above). KEY_INS="${META_2}" CTL_INS="${CTL_I}" META_INS="${CTL_I}" VI_INS='i' TXT_INS='insert' KEY_DEL="${META_3}" CTL_DEL="${CTL_X}" META_DEL="${CTL_X}" VI_DEL='x' TXT_DEL='delete' KEY_QUIT="${META_3}" CTL_QUIT="${CTL_Q}" META_QUIT="${CTL_Q}" VI_QUIT=':q' TXT_QUIT='quit' KEY_EXIT="${META_3}" CTL_EXIT="${CTL_Q}" META_EXIT="${CTL_Q}" VI_EXIT=':q' TXT_EXIT='quit' KEY_RFSH="${KEY_F10}" CTL_RFSH="${CTL_L}" META_RFSH="${CTL_L}" VI_RFSH=':l' TXT_RFSH='refresh' KEY_FSCH='/' CTL_FSCH="${CTL_S}" META_FSCH="${NPC_FS}" VI_FSCH='/' TXT_FSCH='search' KEY_RSCH='?' CTL_RSCH="${CTL_R}" META_RSCH="${NPC_GS}" VI_RSCH='?' TXT_RSCH='reverse' # Array element selection keys KEY_TAB="${TAB}" CTL_TAB="${TAB}" META_TAB="${TAB}" VI_TAB="${TAB}" TXT_TAB="${TAB}" KEY_STB="${META_Z}" CTL_STB="${META_Z}" META_STB="${META_Z}" VI_STB="${META_Z}" TXT_STB="${META_Z}" KEY_RET="${RET}" CTL_RET="${RET}" META_RET="${RET}" VI_RET="${RET}" TXT_RET="${RET}" KEY_ESC="${ESC}" CTL_ESC="${ESC}" META_ESC="${ESC}" VI_ESC="${ESC}" TXT_ESC="${ESC}" ################################################################ # Function Toggle values (All initialized to FALSE) (( F1_TOGGLE = FALSE )) (( F2_TOGGLE = FALSE )) (( F3_TOGGLE = FALSE )) (( F4_TOGGLE = FALSE )) (( F5_TOGGLE = FALSE )) (( F6_TOGGLE = FALSE )) (( F7_TOGGLE = FALSE )) (( F8_TOGGLE = FALSE )) (( F9_TOGGLE = FALSE )) (( F10_TOGGLE = FALSE )) (( F11_TOGGLE = FALSE )) (( F12_TOGGLE = FALSE )) ################################################################ # Initialize the "Shell Curses" cursor movement utilities initscr #### #### USER MODIFY: Change the following values to reflect your #### desired header information displayed at the top of every screen. #### PRGNUM="20100601.1" HDRLIN1="VisualSelect Example" HDRLIN2="Copyright 2010 by Dana French" #### #### USER MODIFY: Change the following values to reflect your #### desired screen display geometry i.e. Number of columns. #### The number of ROWS is set to dynamically change with the screen #### size, so the user may not want to change ROWS. #### # How many columns of array elements do you want to display on the screen? (( COLS = 3 )) # Number of ROWS to display on screen (( ROWS = MAX_ROWS - 9 )) # dynamicaly changes with screen size # Starting character position for the first column displayed on the screen (( XS = 5 )) # Number of characters per column in the X direction (( XI = ( MAX_COLS - XS ) / COLS )) # dynamicaly changes with screen size # Starting character position for the last column displayed on the screen (( XE = ( COLS * XI ) - XI + XS )) # dynamicaly changes with screen size # Number of screen rows per data field in the Y direction (almost always 1) (( YI = 1 )) # Starting screen row number for the first data row displayed on the screen (( YS = 6 )) # Ending screen row number for the last data row displayed on the screen (( YE = ( ROWS * YI ) + YS - 1 )) # dynamicaly changes with screen size #### #### USER MODIFY: The user/programmer should insert their array values into #### the array named FILES, an example is shown below. In the example, all #### file names ending in ".conf" from the "/etc" directory are inserted #### into the array named FILES. #### #### Define or populate the data array "FILES" with as many elements as you #### desire. (index array only, associative arrays not supported) #### FILES=( /etc/*.conf ) # USER MODIFY: fill the FILES array with your items if [[ "_${CODE}" == "_ksh" ]] then nameref ARY=FILES else ARY=( "${FILES[@]}" ) fi #### #### Do not modify below this line #### ARY_CNT="${#ARY[@]}" (( SCR_NUM = 1 )) (( SCR_CNT = ( ARY_CNT / ( ROWS * COLS ) ) + 1 )) (( IDX = 0 )) SCR_PREFIX="SCRN" SCR_LABEL="${SCR_PREFIX} ${SCR_NUM} of ${SCR_CNT}" ################################################################ # Initialize the content of the Help Screen Array elements # In Korn Shell, initialize an indexed array named HELP [[ "_${CODE}" == "_ksh" ]] && set -A HELP defineHelpContent HELP ################################################################ # Here is where the screens are displayed (( IDX = 0 )) visualSelect #### The array index number of the user selected item is returned from the #### "visualSelect" function in the shell variable named VSIDX. The value of #### the user selected item from the array can be obtained using #### "${ARY[VSIDX]}". ################################################################ #### #### Example of displaying a second array of files after exiting from #### the first array, with a different number of columns on the screen. #### Uncomment the following lines of code to enable the second array. #### # unset FILES # Remove the existing shell array variable # FILES=( /dev/* ) # Fill an array with file names # nameref ARY=FILES # Establish a pointer to the Array # ARY_CNT="${#ARY[@]}" # Number of elements in the array # # (( COLS = 4 )) # Number of columns to display on screen # (( XI = ( MAX_COLS - XS ) / COLS )) # Column Width # (( XE = ( COLS * XI ) - XI + XS )) # Last column starting position # # (( SCR_NUM = 1 )) # Starting Screen Number # (( SCR_CNT = ( ARY_CNT / ( ROWS * COLS ) ) + 1 )) # Number of screens # (( IDX = 0 )) # Starting array element number # SCR_PREFIX="SCRN" # Screen lable prefix for header info # SCR_LABEL="${SCR_PREFIX} ${SCR_NUM} of ${SCR_CNT}" # # visualSelect # ################################################################ endwin exit 0