#!/bin/sh # Flip-file shell script version 1 by Ben Collver # Roughly based on FLIP.BAS. # # cardfile="FLIP.DAT" exported="flip.tsv" # maximum number of cards mx=30 # maximum line length (80 - 9 - 3) il=68 # current card number card=1 # number of last card in file last=0 # flag for deleted card delmsg="' CARD DELETED '" type mktemp >/dev/null 2>&1 if [ $? -eq 127 ] then mktemp() { o=0 s=$(date +%s) while [ $o -lt 100 ] do t=$(echo $(($o + $s)) | md5sum | cut -c 1-6) f="/tmp/tmp.$t" if [ ! -f "$f" ] then break fi o=$(($o+1)) done if [ -f "$f" ] then exit 127 return 127 else touch "$f" echo "$f" fi return 0 } fi # session data file f=$(mktemp) # helper script file helper=$(mktemp) # output from dialog command RESULT=$(mktemp) # remove tempfiles on exit trap "rm -f $f $helper $RESULT" 0 export DIALOGOPTS="--no-mouse --title Flip-file" echo "form_item_readonly_color = (WHITE,BLUE,ON)" >flip.rc append_record() { infile=$1 awk -F "\n" -v OFS="\t" -v ORS="\r\n" -v RS="\xFF" '{ print $1, $2, $3, $4, $5, $6, $7 }' $infile >>$f return } add_card() { limit=$((mx - 1)) if [ $last -eq $limit ] then dialog --backtitle "$backtitle" \ --msgbox "File full. Save cards." 0 0 return fi card=$((last + 1)) last=$((last + 1)) backtitle=$(get_backtitle) dialog --backtitle "$backtitle" \ --no-cancel \ --ok-label "Back" \ --form "Add a card" 0 -1 7 \ Name: 1 1 "" 1 10 60 $il \ Street: 2 1 "" 2 10 60 $il \ Town: 3 1 "" 3 10 60 $il \ County: 4 1 "" 4 10 60 $il \ Code: 5 1 "" 5 10 60 $il \ Phone: 6 1 "" 6 10 60 $il \ Info: 7 1 "" 7 10 60 $il \ 2>$RESULT EXITCODE=$? case $EXITCODE in 255) exit ;; 0) append_record $RESULT ;; -1) error_exit $RESULT ;; esac return } browse() { while : do backtitle=$(get_backtitle) cat >$helper <<__EOF__ DIALOGRC=flip.rc dialog \\ --backtitle "$backtitle" \\ --extra-button \\ --help-button \\ --ok-label Previous \\ --extra-label Next \\ --cancel-label Search \\ --help-label Back \\ --form "Browse & search" 0 -1 7 \\ __EOF__ view_card_fields $card -60 $helper echo " 2>$RESULT" >>$helper sh $helper EXITCODE=$? case $EXITCODE in 255) exit ;; 3) [ $card -lt $last ] && card=$((card + 1)) ;; 2) break ;; 1) search ;; 0) [ $card -gt 1 ] && card=$((card - 1)) ;; -1) error_exit $RESULT ;; esac done return } del_card() { update=$(mktemp) backtitle=$(get_backtitle) while : do cat >$helper <<__EOF__ DIALOGRC=flip.rc dialog \\ --backtitle "$backtitle" \\ --cancel-label Back \\ --ok-label Delete \\ --form "Remove a card" 0 -1 7 \\ __EOF__ view_card_fields $card -60 $helper echo " 2>$RESULT" >>$helper sh $helper EXITCODE=$? case $EXITCODE in 255) exit ;; 1) break ;; -1) error_exit $RESULT ;; esac awk -F "\t" -v RS="\r\n" -v OFS="\t" -v ORS="\r\n" \ -v card=$card -v delmsg="$delmsg" ' NR != 1 + card {print $0} NR == 1 + card {print $1, $2, $3, $4, $5, $6, delmsg} ' $f >$update cat $update >$f done rm -f $update return } edit_card() { backtitle=$(get_backtitle) cat >$helper <<__EOF__ dialog --backtitle "$backtitle" \\ --no-cancel \\ --ok-label Back \\ --form "Edit a card" 0 -1 7 \\ __EOF__ view_card_fields $card 60 $helper echo " 2>$RESULT" >>$helper sh $helper EXITCODE=$? case $EXITCODE in 255) exit ;; 0) update_record $RESULT ;; -1) error_exit $RESULT ;; esac return } error_exit() { RESULT="$1" printf "Error: " cat $RESULT exit } find_record() { infile=$1 outfile=$(mktemp) pos=0 backtitle=$(get_backtitle) term=$(awk -v OFS="\t" '{ if (length($0) > 0) { print NR, $0 exit } }' $infile) while : do awk -F "\t" -v RS="\r\n" -v pos=$pos -v term="$term" ' BEGIN { OFS = FS found = 0 nextpos = 0 num = split(term, fields, /\t/) if (num == 2) { field = fields[1] value = fields[2] } else { field = 1 value = "" } } { result = 0 if (length(value) > 0) { if (value == $field) { result = 1 } } if (result == 1) { found++ if (nextpos == 0 && NR - 1 > pos) { nextpos = NR - 1 } lastpos = NR - 1 } } END { if (nextpos == lastpos) { islast = 1 } else { islast = 0 } print nextpos, found, islast, value }' $f >$outfile pos=$(cat $outfile | cut -f 1) found=$(cat $outfile | cut -f 2) islast=$(cat $outfile | cut -f 3) value=$(cat $outfile | cut -f 4) if [ $found -eq 0 ] then dialog --backtitle "$backtitle" \ --msgbox "Didn't find: $value" 0 0 break else card=$pos backtitle=$(get_backtitle) cat >$helper <<__EOF__ DIALOGRC=flip.rc dialog \\ --backtitle "$backtitle" \\ --ok-label Next \\ --cancel-label Back \\ --form "Searching for $value " 0 -1 7 \\ __EOF__ view_card_fields $card -60 $helper echo " 2>$RESULT" >>$helper sh $helper EXITCODE=$? case $EXITCODE in 255) exit ;; 1) break ;; 0) if [ $islast -eq 1 ] then msg="Search over\nFound: $found times" dialog --backtitle "$backtitle" \ --msgbox "$msg" 0 0 break fi ;; -1) error_exit $RESULT ;; esac fi done rm -f $outfile return } get_backtitle() { if [ $last -eq 0 ] then echo "No cards in file" elif [ $last -gt 0 ] then if [ $card -lt $((mx + 1)) ] then echo "$last cards on card $card " else echo "$last cards" fi fi return } load() { last=$(awk -v RS="\r\n" 'NR == 1 {print $1}' $cardfile) card=1 printf "Name\tStreet\tTown\tCounty\tCode\tPhone\tInfo\r\n" >$f awk -F "\t" -v RS="\r\n" -v OFS="\t" -v ORS="\r\n" ' NR > 1 { name=$0 getline street getline town getline county getline code getline phone getline info print name, street, town, county, code, phone, info }' $cardfile >>$f return } save() { # write count of not-deleted records awk -F "\t" -v RS="\r\n" -v ORS="\r\n" -v delmsg="$delmsg" ' NR > 1 { if ($7 != delmsg) { notdel++ } } END { print notdel }' $f >$cardfile # write lines for not-deleted records awk -F "\t" -v RS="\r\n" -v OFS="\r\n" -v ORS="\r\n" \ -v delmsg="$delmsg" ' NR > 1 { if ($7 != delmsg) { print $1, $2, $3, $4, $5, $6, $7 } }' $f >>$cardfile cat $f >$exported echo "Cards saved. You are no longer in Flip-file." exit 0 } search() { backtitle=$(get_backtitle) dialog --backtitle "$backtitle" \ --no-cancel \ --ok-label "Search" \ --form "Search" 0 -1 7 \ Name: 1 1 "" 1 10 60 $il \ Street: 2 1 "" 2 10 60 $il \ Town: 3 1 "" 3 10 60 $il \ County: 4 1 "" 4 10 60 $il \ Code: 5 1 "" 5 10 60 $il \ Phone: 6 1 "" 6 10 60 $il \ Info: 7 1 "" 7 10 60 $il \ 2>$RESULT EXITCODE=$? case $EXITCODE in 255) exit ;; 0) find_record $RESULT break ;; -1) error_exit $RESULT ;; esac return } update_record() { infile=$1 record=$(mktemp) update=$(mktemp) awk -F "\n" -v OFS="\t" -v RS="\xFF" '{ print $1, $2, $3, $4, $5, $6, $7 }' $infile >$record rec=$(cat $record) awk -F "\t" -v RS="\r\n" -v ORS="\r\n" -v card=$card \ -v rec="$rec" ' NR != 1 + card {print $0} NR == 1 + card {print rec} ' $f >$update cat $update >$f rm -f $record $update return } view_card_fields() { pos="$1" len="$2" out="$3" awk -F "\t" -v RS="\r\n" -v ORS="\r\n" -v card=$pos \ -v len=$len -v il=$il ' NR == 1 { for (i = 1; i <= NF; i++) { name[i] = toupper(substr($i, 1, 1)) substr($i, 2) ":" } } NR == 1 + card { for (i = 1; i <= NF; i++) { q = "\"" $i "\"" printf "%-7s %d 1 %-9s %d 10 %d %d \\\n", name[i], i, q, i, len, il } }' $f >>$out return } # ================================================================== main() { printf "Name\tStreet\tTown\tCounty\tCode\tPhone\tInfo\r\n" >$f while : do backtitle=$(get_backtitle) dialog --backtitle "$backtitle" \ --no-cancel \ --menu "Would you like to:" 0 0 7 \ ADD "Add a card" \ REMOVE "Remove a card" \ ALTER "Alter a card (edit/update)" \ BROWSE "Flip cards (browse/search)" \ LOAD "Load cards" \ SAVE "File these cards (save & quit)" \ 2>$RESULT EXITCODE=$? case $EXITCODE in 255) exit ;; -1) error_exit $RESULT ;; esac OUTPUT=$(cat $RESULT) if [ "$OUTPUT" != "ADD" -a "$OUTPUT" != "LOAD" ] then if [ $last -eq 0 ] then dialog --backtitle "$backtitle" \ --msgbox "No cards in file" 0 0 continue fi fi case "$OUTPUT" in REMOVE) del_card ;; ADD) add_card ;; ALTER) edit_card ;; BROWSE) browse ;; LOAD) load ;; SAVE) save ;; esac done exit 0 } main