/* * $Id$ */ /* * File......: popadder.prg * Author....: Keith A. Wire * CIS ID....: 73760,2427 * * This is an original work by Keith A. Wire and is placed in the * public domain. * * Modification history: * --------------------- * * Rev 1.4 03 Mar 1994 19:47:22 GLENN * Author made some enhancements and modifications. * * Rev 1.3 19 Jan 1993 19:52:52 GLENN * Removed reference to K_SPACE, as this has been defined in Clipper * 5.2's inkey.ch. * * Rev 1.2 17 Aug 1991 15:44:30 GLENN * Don Caton fixed some spelling errors in the doc * * Rev 1.1 15 Aug 1991 23:04:12 GLENN * Forest Belt proofread/edited/cleaned up doc * * Rev 1.0 14 Jun 1991 17:37:54 GLENN * Initial revision. * */ #include "inkey.ch" #include "setcurs.ch" #include "achoice.ch" // Set up manifest constants to access the window colors in the array aWinColor #define W_BORDER 1 #define W_ACCENT 2 #define W_PROMPT 3 #define W_SCREEN 4 #define W_TITLE 5 #define W_VARIAB 6 #define W_CURR NIL // Set up manifest constants to access the Standard screen colors in the array // aStdColor #define STD_ACCENT 1 #define STD_ERROR 2 #define STD_PROMPT 3 #define STD_SCREEN 4 #define STD_TITLE 5 #define STD_VARIABLE 6 #define STD_BORDER 7 #define K_DECIM 46 #define K_EQUAL 13 #define K_PLUS 43 #define K_MINUS 45 #define K_MULTIPLY 42 #define K_DIVIDE 47 #define K_ZERO 48 #define B_DOUBLE "╔═╗║╝═╚║ " #define B_SINGLE "+-+|+-+| " #define CRLF CHR(13)+CHR(10) #define nTotTran LEN(aTrans) #command DEFAULT

TO [, TO ] => ;

:= iif(

== NIL, ,

) ; [; := iif( == NIL, , )] #command DISPMESSAGE ,,,, => ; _ftPushKeys(); KEYBOARD CHR(K_CTRL_PGDN)+CHR(K_CTRL_W) ;; MEMOEDIT(,,,,, .F., NIL, ()-()+1) ;; _ftPopKeys() #define ASHRINK(ar) ASIZE(ar,LEN(ar)-1) /* This INKEY UDC was posted by Don Caton on NanForum... Thanks Don */ #command FT_INKEY [ ] TO ; => ; WHILE (.T.) ;; := Inkey([ ]) ;; IF Setkey() # NIL ;; Eval( Setkey(), ProcName(), ProcLine(), # ) ;; ELSE ;; EXIT ;; END ;; END // Instead of using STATIC variables for these I'm using a LOCAL array // and passing aAdder[] all over the place.... Don't let this confuse // you. I wrote the Adder using the variable names & now let the // PreProcessor do all the work. #define nTotal aAdder[1] #define nNumTotal aAdder[2] #define nSavTotal aAdder[3] #define cTotPict aAdder[4] #define lClAdder aAdder[5] #define lDecSet aAdder[6] #define nDecDigit aAdder[7] #define nMaxDeci aAdder[8] #define lMultDiv aAdder[9] #define nAddMode aAdder[10] #define lSubRtn aAdder[11] #define lTotalOk aAdder[12] #define lAddError aAdder[13] #define lTape aAdder[14] #define lNewNum aAdder[15] #define nSavSubTot aAdder[16] #define lDivError aAdder[17] #define aTrans aAdder[18] #define nTopOS aAdder[19] #define nLeftOS aAdder[20] #define nAddSpace aAdder[21] #define nTapeSpace aAdder[22] #define cTapeScr aAdder[23] // I still use a few of STATICS, but most are set to NIL when quiting... THREAD STATIC lAdderOpen := .F., ; aKeys, aWindow, nWinColor, aWinColor, aStdColor #ifdef FT_TEST FUNCTION TEST LOCAL nSickHrs := 0, ; nPersHrs := 0, ; nVacaHrs := 0, ; GetList := {} SET SCOREBOARD OFF _ftSetScrColor(STD_SCREEN,STD_VARIABLE) CLS SET KEY K_ALT_A TO FT_Adder // Make call FT_Adder * SIMPLE Sample of program data entry! @ 12,5 SAY "Please enter the total Sick, Personal, and Vacation hours." @ 15,22 SAY "Sick hrs." @ 15,40 SAY "Pers. hrs." @ 15,60 SAY "Vaca. hrs." @ 23,20 SAY "Press to Pop - Up the Adder." @ 24,20 SAY "Press to Quit the adder Demo." DO WHILE .T. // Get the sick, personal, & vaca @ 16,24 GET nSickHrs PICTURE "9999.999" // Normally I have a VALID() @ 16,43 GET nPersHrs PICTURE "9999.999" // to make sure the value is @ 16,63 GET nVacaHrs PICTURE "9999.999" // within the allowable range. SET CURSOR ON // But, like I said it is a CLEAR TYPEAHEAD // SIMPLE example . READ SET CURSOR OFF IF LASTKEY() == K_ESC // - ABORT CLEAR TYPEAHEAD EXIT ENDIF ENDDO SET CURSOR ON SET KEY K_ALT_A // Reset RETURN NIL #endif /*+- Function ---------------------------------------------------------------+ | Name: FT_Adder() Docs: Keith A. Wire | | Description: Pop Up Adder / Calculator with Tape Display | | Author: Keith A. Wire | | Date created: 10-03-93 Date updated: 10-03-93 | | Time created: 11:18:40am Time updated: 11:18:40am | | Copyright: None - Public Domain | +--------------------------------------------------------------------------+ | Arguments: None | | Return Value: NIL | | Notes: To make FT_Adder() pop up from any wait state in your | | : application just insert the line: | | : SET KEY K_ALT_A TO FT_Adder | | : at the top of your application | +--------------------------------------------------------------------------+ */ FUNCTION FT_Adder() LOCAL nOldDecim, cMoveTotSubTot, cTotal, lDone, nKey, ; oGet := GetActive(), ; nOldCurs := SETCURSOR(SC_NONE), ; nOldRow := ROW(), ; nOldCol := COL(), ; bOldF10 := SETKEY(K_F10, NIL), ; nOldLastKey := LASTKEY(), ; lShowRight := .T., ; aAdder := ARRAY(23) // Must prevent recursive calls IF lAdderOpen RETURN NIL ELSE lAdderOpen := .T. ENDIF aTrans := {" 0.00 C "} nOldDecim := SET(_SET_DECIMALS,9) cTotPict := "999999999999999.99" cTapeScr := "" nTotal := nNumTotal := nSavTotal := nDecDigit := 0 lDone := .F. // Loop flag nKey := 0 nMaxDeci := 2 // Initial # of decimals nSavSubTot := 0 lNewNum := .F. nAddMode := 1 // Start in ADD mode lMultDiv := .F. // Start in ADD mode lClAdder := .F. // Clear adder flag lDecSet := .F. // Decimal ? - keyboard routine lSubRtn := lTotalOk := lTape := lAddError := lDivError := .F. nTopOS := INT((MAXROW()-24)/2) // Using the TopOffSet & LeftOffSet nLeftOS := INT((MAXCOL()-79)/2) // the Adder will always be centered nAddSpace := iif(lShowRight,40,0)+nLeftOS nTapeSpace := iif(lShowRight,0,40)+nLeftOS // Set Up the STATIC variables aKeys := {} aWindow := {} nWinColor := 0 _ftAddScreen(aAdder) // Set the decimals to 2 & display a cleared adder _ftChangeDec(aAdder, 2) @ 4+nTopOS, 7+nAddSpace SAY nTotal PICTURE cTotPict DO WHILE ! lDone // Input key & test loop FT_INKEY 0 TO nKey DO CASE CASE UPPER(CHR(nKey)) $"1234567890." _ftProcessNumb(aAdder, nKey) CASE nKey == K_PLUS // <+> sign _ftAddSub(aAdder, nKey) CASE nKey == K_MINUS // <-> sign _ftAddSub(aAdder, nKey) CASE nKey == K_MULTIPLY // <*> sign _ftMultDiv(aAdder, nKey) CASE nKey == K_DIVIDE // sign _ftMultDiv(aAdder, nKey) CASE nKey == K_RETURN // Total or Subtotal _ftAddTotal(aAdder) CASE nKey == K_ESC // Quit SET(_SET_DECIMALS,nOldDecim) SETCURSOR(nOldCurs) IF lTape RESTSCREEN(4+nTopOS,6+nTapeSpace,22+nTopOS,35+nTapeSpace,cTapeScr) ENDIF _ftPopWin() SETPOS(nOldRow,nOldCol) _ftSetLastKey(nOldLastKey) SETKEY(K_F10, bOldF10) lAdderOpen := .F. // Reset the recursive flag lDone := .T. CASE nKey == 68 .OR. nKey == 100 // Change number of decimal places _ftChangeDec(aAdder) CASE nKey == 84 .OR. nKey == 116 // Display Tape _ftDisplayTape(aAdder, nKey) CASE nKey == 77 .OR. nKey == 109 // Move Adder IF lTape RESTSCREEN(4+nTopOS,6+nTapeSpace,22+nTopOS,35+nTapeSpace,cTapeScr) ENDIF IF LEFT(SAVESCREEN(6+nTopOS,26+nAddSpace,6+nTopOS,27+nAddSpace),1) ; != " " IF LEFT(SAVESCREEN(6+nTopOS,19+nAddSpace,6+nTopOS,20+nAddSpace),1) ; == "S" cMoveTotSubTot := "S" ELSE cMoveTotSubTot := "T" ENDIF ELSE cMoveTotSubTot := " " ENDIF cTotal := _ftCharOdd(SAVESCREEN( 4 + nTopOS, 8 + nAddSpace, 4 + ; nTopOS,25+nAddSpace)) _ftPopWin() // Remove Adder lShowRight := !lShowRight nAddSpace := iif(lShowRight,40,0)+nLeftOS nTapeSpace := iif(lShowRight,0,40)+nLeftOS _ftAddScreen(aAdder) _ftDispTotal(aAdder) IF lTape lTape := .F. _ftDisplayTape(aAdder, nKey) ENDIF @ 4+nTopOS, 8+nAddSpace SAY cTotal IF !EMPTY(cMoveTotSubTot) _ftSetWinColor(W_CURR,W_SCREEN) @ 6+nTopOS,18+nAddSpace SAY iif(cMoveTotSubTot=="T", " ", ; "") _ftSetWinColor(W_CURR,W_PROMPT) ENDIF CASE (nKey == 83 .OR. nKey == 115) .AND. lTape // Scroll tape display IF nTotTran>16 // We need to scroll SETCOLOR("GR+/W") @ 21+nTopOS,8+nTapeSpace SAY " "+CHR(24)+CHR(25)+"-SCROLL -QUIT " SETCOLOR("N/W,W+/N") ACHOICE(5+nTopOS,7+nTapeSpace,20+nTopOS,32+nTapeSpace,aTrans,.T., ; "_ftAdderTapeUDF",nTotTran,20) SETCOLOR("R+/W") @ 21+nTopOS,8+nTapeSpace TO 21+nTopOS,30+nTapeSpace _ftSetWinColor(W_CURR,W_PROMPT) CLEAR TYPEAHEAD ELSE _ftError("there are " + iif(nTotTran > 0, "only " + ; LTRIM(STR(nTotTran, 3, 0)), "no") + ; " transactions entered so far." + ; " No need to scroll!") ENDIF CASE nKey == 7 // Delete - Clear adder _ftClearAdder(aAdder) CASE nKey == K_F1 // Help _ftAddHelp() CASE nKey == K_F10 // Quit - Return total IF lTotalOk // Did they finish the calculation IF oGet != NIL .AND. oGet:TYPE == "N" SET(_SET_DECIMALS,nOldDecim) SETCURSOR(nOldCurs) IF lTape RESTSCREEN(4+nTopOS,6+nTapeSpace,22+nTopOS,35+nTapeSpace,cTapeScr) ENDIF _ftPopWin() SETPOS(nOldRow,nOldCol) _ftSetLastKey(nOldLastKey) SETKEY(K_F10, bOldF10) oGet:VARPUT(nSavTotal) lAdderOpen := .F. // Reset the recursive flag lDone := .T. ELSE _ftError("but I can not return the total from the "+ ; "adder to this variable. You must quit the adder using"+ ; " the key and then enter the total manually.") ENDIF ELSE _ftError("the calculation is not finished yet! You must have"+ ; " a TOTAL before you can return it to the program.") ENDIF ENDCASE ENDDO (WHILE .T. Data entry from keyboard) // Reset the STATICS to NIL aKeys := aWindow := aWinColor := aStdColor := NIL RETURN NIL /*+- Function ---------------------------------------------------------------+ | Name: _ftAddScreen() Docs: Keith A. Wire | | Description: Display the Adder | | Author: Keith A. Wire | | Date created: 10-03-93 Date updated: 10-03-93 | | Time created: 11:24:29am Time updated: 11:24:29am | | Copyright: None - Public Domain | +--------------------------------------------------------------------------+ | Arguments: aAdder | | Return Value: NIL | +--------------------------------------------------------------------------+ */ STATIC FUNCTION _ftAddScreen(aAdder) LOCAL nCol _ftPushWin(2+nTopOS,2+nAddSpace,22+nTopOS,30+nAddSpace," Adder ", ; " for Help",,B_DOUBLE) nCol := 5+nAddSpace @ 7+nTopOS, nCol SAY hb_UTF8ToStr( ' ┌───┐ ┌───┐ ┌───┐' ) @ 8+nTopOS, nCol SAY hb_UTF8ToStr( ' │ │ │ │ │ │' ) @ 9+nTopOS, nCol SAY hb_UTF8ToStr( ' └───┘ └───┘ └───┘' ) @ 10+nTopOS, nCol SAY hb_UTF8ToStr( '┌───┐ ┌───┐ ┌───┐ ┌───┐' ) @ 11+nTopOS, nCol SAY hb_UTF8ToStr( '│ │ │ │ │ │ │ │' ) @ 12+nTopOS, nCol SAY hb_UTF8ToStr( '└───┘ └───┘ └───┘ │ │' ) @ 13+nTopOS, nCol SAY hb_UTF8ToStr( '┌───┐ ┌───┐ ┌───┐ │ │' ) @ 14+nTopOS, nCol SAY hb_UTF8ToStr( '│ │ │ │ │ │ │ │' ) @ 15+nTopOS, nCol SAY hb_UTF8ToStr( '└───┘ └───┘ └───┘ └───┘' ) @ 16+nTopOS, nCol SAY hb_UTF8ToStr( '┌───┐ ┌───┐ ┌───┐ ┌───┐' ) @ 17+nTopOS, nCol SAY hb_UTF8ToStr( '│ │ │ │ │ │ │ │' ) @ 18+nTopOS, nCol SAY hb_UTF8ToStr( '└───┘ └───┘ └───┘ │ │' ) @ 19+nTopOS, nCol SAY hb_UTF8ToStr( '┌─────────┐ ┌───┐ │ │' ) @ 20+nTopOS, nCol SAY hb_UTF8ToStr( '│ │ │ │ │ │' ) @ 21+nTopOS, nCol SAY hb_UTF8ToStr( '└─────────┘ └───┘ └───┘' ) _ftSetWinColor(W_CURR,W_TITLE) nCol := 7+nAddSpace @ 11+nTopOS, nCol SAY "7" @ 14+nTopOS, nCol SAY "4" @ 17+nTopOS, nCol SAY "1" nCol := 13+nAddSpace @ 8+nTopOS,nCol SAY "/" @ 11+nTopOS,nCol SAY "8" @ 14+nTopOS,nCol SAY "5" @ 17+nTopOS,nCol SAY "2" nCol := 19+nAddSpace @ 8+nTopOS,nCol SAY "X" @ 11+nTopOS,nCol SAY "9" @ 14+nTopOS,nCol SAY "6" @ 17+nTopOS,nCol SAY "3" @ 20+nTopOS,nCol SAY "." @ 20+nTopOS,10+nAddSpace SAY "0" nCol := 25+nAddSpace @ 8+nTopOS,nCol SAY "-" @ 13+nTopOS,nCol SAY "+" @ 18+nTopOS,nCol SAY "=" @ 19+nTopOS,nCol SAY "" _ftSetWinColor(W_CURR,W_PROMPT) @ 3+nTopOS, 6+nAddSpace, 5+nTopOS, 27+nAddSpace BOX B_DOUBLE RETURN NIL /*+- Function ---------------------------------------------------------------+ | Name: _ftChangeDec() Docs: Keith A. Wire | | Description: Change the decimal position in the display | | Author: Keith A. Wire | | Date created: 10-03-93 Date updated: 10-03-93 | | Time created: 11:25:17am Time updated: 11:25:17am | | Copyright: None - Public Domain | +--------------------------------------------------------------------------+ | Arguments: aAdder | | : nNumDec | | Return Value: NIL | +--------------------------------------------------------------------------+ */ STATIC FUNCTION _ftChangeDec(aAdder, nNumDec) LOCAL cDefTotPict := "9999999999999999999" IF nNumDec == NIL nNumDec := 0 nNumDec := _ftQuest("How many decimals do you want to display?", ; nNumDec, "9", {|oGet| _ftValDeci(oGet)}) cTotPict := _ftPosRepl(cDefTotPict, ".", 19 - ABS(nNumDec)) cTotPict := RIGHT(_ftStuffComma(cTotPict), 19 ) cTotPict := iif(nNumDec==2 .OR. nNumDec==6, " "+RIGHT(cTotPict,18),cTotPict) nMaxDeci := nNumDec IF lSubRtn _ftDispTotal(aAdder) ELSE _ftDispSubTot(aAdder) ENDIF ENDIF RETURN NIL /*+- Function ---------------------------------------------------------------+ | Name: _ftDispTotal() Docs: Keith A. Wire | | Description: Display total number to Adder Window | | Author: Keith A. Wire | | Date created: 10-03-93 Date updated: 10-03-93 | | Time created: 11:25:58am Time updated: 11:25:58am | | Copyright: None - Public Domain | +--------------------------------------------------------------------------+ | Arguments: aAdder | | Return Value: NIL | +--------------------------------------------------------------------------+ */ STATIC FUNCTION _ftDispTotal(aAdder) LOCAL cTotStr IF nTotal>VAL(_ftCharRem(",",cTotPict)) cTotStr := _ftStuffComma(LTRIM(STR(nTotal))) @ 4+nTopOS, 8+nAddSpace SAY "**** ERROR **** " _ftError("that number is to big to display! I believe the answer was " + ; cTotStr+".") lAddError := .T. _ftUpdateTrans(aAdder, .T., NIL) _ftClearAdder(aAdder) nTotal := 0 nNumTotal := 0 lAddError := .F. ELSE @ 4+nTopOS, 7+nAddSpace SAY nTotal PICTURE cTotPict ENDIF RETURN NIL /*+- Function ---------------------------------------------------------------+ | Name: _ftDispSubTot() Docs: Keith A. Wire | | Description: Display subtotal number | | Author: Keith A. Wire | | Date created: 10-03-93 Date updated: 10-03-93 | | Time created: 11:26:31am Time updated: 11:26:31am | | Copyright: None - Public Domain | +--------------------------------------------------------------------------+ | Arguments: aAdder | | Return Value: NIL | +--------------------------------------------------------------------------+ */ STATIC FUNCTION _ftDispSubTot(aAdder) LOCAL cStotStr IF nNumTotal>VAL(_ftCharRem(",",cTotPict)) cStotStr := _ftStuffComma(LTRIM(STR(nNumTotal))) @ 4+nTopOS, 8+nAddSpace SAY "**** ERROR **** " _ftError("that number is to big to display! I believe the answer was " + ; cStotStr+".") lAddError := .T. _ftUpdateTrans(aAdder, .T.,nNumTotal) _ftClearAdder(aAdder) nTotal := 0 nNumTotal := 0 lAddError := .F. ELSE @ 4+nTopOS, 7+nAddSpace SAY nNumTotal PICTURE cTotPict ENDIF RETURN NIL /*+- Function ---------------------------------------------------------------+ | Name: _ftProcessNumb() Docs: Keith A. Wire | | Description: Act on NUMBER key pressed | | Author: Keith A. Wire | | Date created: 10-03-93 Date updated: 10-03-93 | | Time created: 11:38:34am Time updated: 11:38:34am | | Copyright: None - Public Domain | +--------------------------------------------------------------------------+ | Arguments: aAdder | | : nKey | | Return Value: NIL | +--------------------------------------------------------------------------+ */ STATIC FUNCTION _ftProcessNumb(aAdder, nKey) LOCAL nNum _ftEraseTotSubTot(aAdder) lTotalOk := .F. lClAdder := .F. // Reset the Clear flag lAddError := .F. // Reset adder error flag IF nKey == Asc( "." ) // Period (.) decimal point IF lDecSet // Has decimal already been set TONE(800, 1) ELSE lDecSet := .T. ENDIF ELSE // It must be a number input lNewNum := .T. nNum := nKey-48 IF lDecSet // Decimal set IF nDecDigit" _ftSetWinColor(W_CURR,W_PROMPT) _ftUpdateTrans(aAdder, .T., NIL) _ftDispTotal(aAdder) lSubRtn := .F. // pressed the total key reset everyting nSavTotal := nTotal nTotal := 0 lTotalOk := .T. ENDIF ELSE // This was the first time they pressed IF !lMultDiv .AND. LASTKEY() == K_RETURN // total key lSubRtn := .T. ENDIF IF _ftRoundIt(nTotal,nMaxDeci)!=0 .OR. _ftRoundIt(nNumTotal,nMaxDeci)!=0 IF !lMultDiv _ftSetWinColor(W_CURR,W_SCREEN) @ 6+nTopOS, 18+nAddSpace SAY "" _ftSetWinColor(W_CURR,W_PROMPT) ENDIF IF _ftRoundIt(nNumTotal,nMaxDeci)!=0 lSubRtn := .F. _ftUpdateTrans(aAdder, .F.,nNumTotal) ENDIF IF !lMultDiv lSubRtn := .T. // total key ENDIF IF nAddMode == 1 // Add nTotal := nTotal+nNumTotal ELSEIF nAddMode == 2 // Subtract nTotal := nTotal-nNumTotal ELSEIF nAddMode == 3 // Multiply nTotal := nTotal*nNumTotal ELSEIF nAddMode == 4 // Divide nTotal := _ftDivide(aAdder, nTotal,nNumTotal) IF lDivError _ftError("you can't divide by ZERO!") lDivError := .F. ENDIF ENDIF ENDIF _ftDispTotal(aAdder) IF lMultDiv // This was a multiply or divide _ftSetWinColor(W_CURR,W_SCREEN) @ 6+nTopOS, 18+nAddSpace SAY " " _ftSetWinColor(W_CURR,W_PROMPT) lSubRtn := .F. // pressed total so key reset everything IF !lTotalOk // If you haven't printed total DO-IT lTotalOk := .T. _ftUpdateTrans(aAdder, .F., NIL) ENDIF nNumTotal := 0 nSavTotal := nTotal nTotal := 0 ELSE IF !lTotalOk // If you haven't printed total DO-IT _ftUpdateTrans(aAdder, .F., NIL) nNumTotal := 0 ENDIF ENDIF ENDIF RETURN NIL /*+- Function ---------------------------------------------------------------+ | Name: _ftAddSub() Docs: Keith A. Wire | | Description: Process + or - keypress | | Author: Keith A. Wire | | Date created: 10-03-93 Date updated: 10-03-93 | | Time created: 12:06:13pm Time updated: 12:06:13pm | | Copyright: None - Public Domain | +--------------------------------------------------------------------------+ | Arguments: aAdder | | : nKey | | Return Value: NIL | +--------------------------------------------------------------------------+ */ STATIC FUNCTION _ftAddSub(aAdder, nKey) lMultDiv := .F. _ftEraseTotSubTot(aAdder) lTotalOk := .F. lDecSet := .F. nDecDigit := 0 lSubRtn := .F. // They pressed the + or - key to process the previous total IF _ftRoundIt(nNumTotal,nMaxDeci)==0 .AND. _ftRoundIt(nTotal,nMaxDeci)==0 nNumTotal := nSavTotal lNewNum := .T. ENDIF IF nKey == K_PLUS // Add nAddMode := 1 IF !lNewNum // They pressed + again to add the same nNumTotal := nSavSubTot // number without re-entering ENDIF _ftUpdateTrans(aAdder, .F.,nNumTotal) nTotal := nTotal+nNumTotal lNewNum := .F. nSavSubTot := nNumTotal // Save this number in case they just press + or - nNumTotal := 0 ELSEIF nKey == K_MINUS // Subtract nAddMode := 2 IF !lNewNum // They pressed + again to add the same nNumTotal := nSavSubTot // number without re-entering lNewNum := .T. ENDIF _ftUpdateTrans(aAdder, .F.,nNumTotal) nTotal := nTotal-nNumTotal lNewNum := .F. nSavSubTot := nNumTotal // Save this number in case they just press + or - nNumTotal := 0 ENDIF _ftDispTotal(aAdder) RETURN NIL /*+- Function ---------------------------------------------------------------+ | Name: _ftMultDiv() Docs: Keith A. Wire | | Description: Process * or / keypress | | Author: Keith A. Wire | | Date created: 10-03-93 Date updated: 10-03-93 | | Time created: 12:06:43pm Time updated: 12:06:43pm | | Copyright: None - Public Domain | +--------------------------------------------------------------------------+ | Arguments: aAdder | | : nKey | | Return Value: NIL | +--------------------------------------------------------------------------+ */ STATIC FUNCTION _ftMultDiv(aAdder, nKey) lMultDiv := .T. _ftEraseTotSubTot(aAdder) lTotalOk := .F. lDecSet := .F. nDecDigit := 0 lSubRtn := .F. // They pressed the + or - key to process the previous total IF _ftRoundIt(nNumTotal,nMaxDeci)==0 .AND. _ftRoundIt(nTotal,nMaxDeci)==0 nNumTotal := nSavTotal ENDIF // Get the first number of the product or division IF _ftRoundIt(nTotal,nMaxDeci)==0 IF nKey == K_MULTIPLY // Setup mode nAddMode := 3 _ftUpdateTrans(aAdder, .F.,nNumTotal) ELSEIF nKey == K_DIVIDE nAddMode := 4 _ftUpdateTrans(aAdder, .F.,nNumTotal) ENDIF nTotal := nNumTotal nNumTotal := 0 ELSE IF nKey == K_MULTIPLY // Multiply nAddMode := 3 _ftUpdateTrans(aAdder, .F.,nNumTotal) nTotal := nTotal*nNumTotal nNumTotal := 0 ELSEIF nKey == K_MULTIPLY // Divide nAddMode := 4 _ftUpdateTrans(aAdder, .F.,nNumTotal) nTotal:=_ftDivide(aAdder, nTotal,nNumTotal) IF lDivError _ftError("you can't divide by ZERO!") lDivError := .F. ENDIF nNumTotal := 0 ENDIF ENDIF _ftDispTotal(aAdder) RETURN NIL /*+- Function ---------------------------------------------------------------+ | Name: _ftAddHelp Docs: Keith A. Wire | | Description: Help window | | Author: Keith A. Wire | | Date created: 10-03-93 Date updated: 10-03-93 | | Time created: 12:07:07pm Time updated: 12:07:07pm | | Copyright: None - Public Domain | +--------------------------------------------------------------------------+ | Arguments: None | | Return Value: NIL | +--------------------------------------------------------------------------+ */ STATIC FUNCTION _ftAddHelp LOCAL cMess := "This Adder works like a desk top calculator. You may add,"+; " subtract, multiply, or divide. " + CRLF + CRLF +; "When adding or subtracting, the first entry is entered " +; "into the accumulator and each sucessive entry is " +; "subtotaled. When you press the SubTotal is also " +; "shown on the tape. The second time you press the "+; "adder is Totaled. When multiplying or dividing the " +; " is a Total the first time pressed." + CRLF + CRLF +; "Hot Keys:" +CRLF+; " ecimals - change # of decimals" +CRLF+; " ove - the Adder from right to left" +CRLF+; " ape - turn Tape Display On or Off" +CRLF+; " croll - the tape display" + CRLF +CRLF+; " ---┬-- 1st Clear entry" +CRLF+; " +-- 2nd Clear ADDER" +CRLF+; " - Quit" +CRLF+; " - return a to the active get" _ftPushMessage(cMess, .T., "ADDER HELP", "press any key to continue...", ; "QUIET") RETURN NIL /*+- Function ---------------------------------------------------------------+ | Name: _ftClearAdder() Docs: Keith A. Wire | | Description: Clear entry / Clear Adder | | Author: Keith A. Wire | | Date created: 10-03-93 Date updated: 10-03-93 | | Time created: 12:07:33pm Time updated: 12:07:33pm | | Copyright: None - Public Domain | +--------------------------------------------------------------------------+ | Arguments: aAdder | | Return Value: NIL | +--------------------------------------------------------------------------+ */ STATIC FUNCTION _ftClearAdder(aAdder) _ftEraseTotSubTot(aAdder) lDecSet := .F. nDecDigit := 0 IF lClAdder // If it has alredy been pressed once nTotal := 0 // then we are clearing the total nSavTotal := 0 _ftUpdateTrans(aAdder, .F., NIL) lClAdder := .F. _ftDispTotal(aAdder) ELSE nNumTotal := 0 // Just clearing the last entry lClAdder := .T. _ftDispSubTot(aAdder) ENDIF RETURN NIL /*+- Function ---------------------------------------------------------------+ | Name: _ftUpdateTrans() Docs: Keith A. Wire | | Description: Update transactions array | | Author: Keith A. Wire | | Date created: 10-03-93 Date updated: 10-03-93 | | Time created: 12:07:55pm Time updated: 12:07:55pm | | Copyright: None - Public Domain | +--------------------------------------------------------------------------+ | Arguments: aAdder | | : lTypeTotal | | : nAmount | | Return Value: NIL | +--------------------------------------------------------------------------+ */ STATIC FUNCTION _ftUpdateTrans(aAdder, lTypeTotal, nAmount) LOCAL lUseTotal := (nAmount == NIL) nAmount := iif(nAmount==NIL,0,nAmount) IF lClAdder // Clear the adder (they pressed twice AADD(aTrans,STR(0,22,nMaxDeci)+" C") IF lTape // If there is a tape Show Clear _ftDisplayTape(aAdder) ENDIF RETU NIL ENDIF IF lTypeTotal // If lTypeTotal=.T. Update from total AADD(aTrans,STR(iif(lUseTotal,nTotal,nAmount),22,nMaxDeci) ) aTrans[nTotTran] := _ftStuffComma(aTrans[nTotTran], .T.) + " *"+ ; iif(lAddError,"ER","") ELSE // If lTypeTotal=.F. Update from nNumTotal AADD(aTrans,STR(iif(lUseTotal,nTotal,nAmount),22,nMaxDeci)) aTrans[nTotTran] := _ftStuffComma(aTrans[nTotTran], .T.) + ; iif(lSubRtn," S",iif(nAddMode==1," +",iif(nAddMode==2," -",IF ; (lTotalOk," =",iif(nAddMode==3," X"," /"))))) + iif(lAddError,"ER","") ENDIF IF lTape _ftDisplayTape(aAdder) ENDIF RETURN NIL /*+- Function ---------------------------------------------------------------+ | Name: _ftEraseTotSubTot() Docs: Keith A. Wire | | Description: Clear the & from Adder | | Author: Keith A. Wire | | Date created: 10-03-93 Date updated: 10-03-93 | | Time created: 12:08:14pm Time updated: 12:08:14pm | | Copyright: None - Public Domain | +--------------------------------------------------------------------------+ | Arguments: aAdder | | Return Value: NIL | +--------------------------------------------------------------------------+ */ STATIC FUNCTION _ftEraseTotSubTot(aAdder) _ftSetWinColor(W_CURR,W_SCREEN) @ 6+nTopOS, 18+nAddSpace SAY " " _ftSetWinColor(W_CURR,W_PROMPT) RETURN NIL /*+- Function ---------------------------------------------------------------+ | Name: _ftRoundIt() Docs: Keith A. Wire | | Description: Adder Rounding function | | Author: Keith A. Wire | | Date created: 10-03-93 Date updated: 10-03-93 | | Time created: 12:09:00pm Time updated: 12:09:00pm | | Copyright: None - Public Domain | +--------------------------------------------------------------------------+ | Arguments: nNumber | | : nPlaces | | Return Value: INT@( ABS@(nNumber@) @* 10 @^ nPlaces @+ 0@.50 @+ 10 @^ - ;| | : 12 @) / 10 @^ nPlaces | +--------------------------------------------------------------------------+ */ STATIC FUNCTION _ftRoundIt(nNumber, nPlaces) nPlaces := iif( nPlaces == NIL, 0, nPlaces ) RETURN iif(nNumber < 0.0, -1.0, 1.0) * ; INT( ABS(nNumber) * 10 ^ nPlaces + 0.50 + 10 ^ -12 ) / 10 ^ nPlaces /*+- Function ---------------------------------------------------------------+ | Name: _ftDivide() Docs: Keith A. Wire | | Description: Check divide by zero not allowed | | Author: Keith A. Wire | | Date created: 10-03-93 Date updated: 10-03-93 | | Time created: 12:10:41pm Time updated: 12:10:41pm | | Copyright: None - Public Domain | +--------------------------------------------------------------------------+ | Arguments: aAdder | | : nNumerator | | : nDenominator | | Return Value: @(nNumerator/nDenominator@) | +--------------------------------------------------------------------------+ */ STATIC FUNCTION _ftDivide(aAdder, nNumerator,nDenominator) IF nDenominator==0.0 lDivError := .T. RETU 0 ELSE lDivError := .F. ENDIF RETURN(nNumerator/nDenominator) /*+- Function ---------------------------------------------------------------+ | Name: _ftValDeci() Docs: Keith A. Wire | | Description: Validate the number of decimals | | Author: Keith A. Wire | | Date created: 10-03-93 Date updated: 10-03-93 | | Time created: 12:10:56pm Time updated: 12:10:56pm | | Copyright: None - Public Domain | +--------------------------------------------------------------------------+ | Arguments: oGet | | Return Value: lRtnValue | +--------------------------------------------------------------------------+ */ STATIC FUNCTION _ftValDeci(oGet) LOCAL lRtnValue := .T. IF oGet:VarGet() > 8 _ftError("no more than 8 decimal places please!") lRtnValue := .F. ENDIF RETURN lRtnValue /*+- Function ---------------------------------------------------------------+ | Name: _ftDisplayTape() Docs: Keith A. Wire | | Description: Display the Tape | | Author: Keith A. Wire | | Date created: 10-03-93 Date updated: 10-03-93 | | Time created: 12:11:28pm Time updated: 12:11:28pm | | Copyright: None - Public Domain | +--------------------------------------------------------------------------+ | Arguments: aAdder | | : nKey | | Return Value: NIL | +--------------------------------------------------------------------------+ */ STATIC FUNCTION _ftDisplayTape(aAdder, nKey) LOCAL nDispTape, nTopTape := 1 IF (nKey == 84 .OR. nKey == 116) .AND. lTape // Stop displaying tape lTape := .F. RESTSCREEN(4+nTopOS,6+nTapeSpace,22+nTopOS,35+nTapeSpace,cTapeScr) RETU NIL ENDIF IF lTape // Are we in the display mode SETCOLOR("N/W") SCROLL(5+nTopOS,7+nTapeSpace,20+nTopOS,32+nTapeSpace,1) IF nTotTran>0 // Any transactions been entered yet? @ 20+nTopOS,7+nTapeSpace SAY aTrans[nTotTran] ENDIF _ftSetWinColor(W_CURR,W_PROMPT) ELSE // Start displaying tape lTape := .T. SETCOLOR("N/W") cTapeScr := SAVESCREEN(4+nTopOS,6+nTapeSpace,22+nTopOS,35+nTapeSpace) _ftShadow(22+nTopOS,8+nTapeSpace,22+nTopOS,35+nTapeSpace) _ftShadow(5+nTopOS,33+nTapeSpace,21+nTopOS,35+nTapeSpace) SETCOLOR("R+/W") @ 4+nTopOS,6+nTapeSpace,21+nTopOS,33+nTapeSpace BOX B_SINGLE SETCOLOR("GR+/W") @ 4+nTopOS,17+nTapeSpace SAY " TAPE " SETCOLOR("N/W") IF nTotTran>15 nTopTape := nTotTran-15 ENDIF FOR nDispTape := nTotTran TO nTopTape STEP -1 @ 20+nDispTape-nTotTran+nTopOS,7+nTapeSpace SAY aTrans[nDispTape] NEXT ENDIF _ftSetWinColor(W_CURR,W_PROMPT) RETURN NIL /*+- Function ---------------------------------------------------------------+ | Name: _ftSetLastKey() Docs: Keith A. Wire | | Description: Sets the LASTKEY() value to value of nLastKey | | Author: Keith A. Wire | | Date created: 10-03-93 Date updated: 10-03-93 | | Time created: 12:12:00pm Time updated: 12:12:00pm | | Copyright: None - Public Domain | +--------------------------------------------------------------------------+ | Arguments: nLastKey | | Return Value: NIL | | Notes: I use this in most of my Pop-Up routines to reset the | | : original value of LASTKEY() when quitting. | +--------------------------------------------------------------------------+ */ STATIC FUNCTION _ftSetLastKey(nLastKey) _ftPushKeys() KEYBOARD CHR(nLastKey) INKEY() _ftPopKeys() RETURN NIL /*+- Function ---------------------------------------------------------------+ | Name: _ftPushKeys Docs: Keith A. Wire | | Description: Push any keys in the Keyboard buffer on the array aKeys[] | | Author: Keith A. Wire | | Date created: 10-03-93 Date updated: 10-03-93 | | Time created: 12:16:09pm Time updated: 12:16:09pm | | Copyright: None - Public Domain | +--------------------------------------------------------------------------+ | Arguments: None | | Return Value: NIL | | Notes: Save any keys in the buffer... for FAST typists . | +--------------------------------------------------------------------------+ */ STATIC FUNCTION _ftPushKeys DO WHILE NEXTKEY() != 0 AADD(aKeys,INKEY()) ENDDO RETURN NIL /*+- Function ---------------------------------------------------------------+ | Name: _ftPopKeys Docs: Keith A. Wire | | Description: Restore the keyboard with any keystrokes that were saved | | : with _ftPushKeys | | Author: Keith A. Wire | | Date created: 10-03-93 Date updated: 10-03-93 | | Time created: 12:17:58pm Time updated: 12:17:58pm | | Copyright: None - Public Domain | +--------------------------------------------------------------------------+ | Arguments: None | | Return Value: NIL | +--------------------------------------------------------------------------+ */ STATIC FUNCTION _ftPopKeys LOCAL cKeys := "" IF LEN(aKeys) != 0 AEVAL(aKeys, {|elem| cKeys += CHR(elem)}) ENDIF KEYBOARD cKeys aKeys := {} RETURN NIL /*+- Function ---------------------------------------------------------------+ | Name: _ftPushMessage() Docs: Keith A. Wire | | Description: Display a message on the screen in a window | | Author: Keith A. Wire | | Date created: 10-03-93 Date updated: 10-03-93 | | Time created: 12:18:53pm Time updated: 12:18:53pm | | Copyright: None - Public Domain | +--------------------------------------------------------------------------+ | Arguments: cMessage | | : lWait | | : cTitle | | : cBotTitle | | : xQuiet | | : nTop | | Return Value: NIL | | See Also: _ftPopMessage | +--------------------------------------------------------------------------+ */ STATIC FUNCTION _ftPushMessage(cMessage,lWait,cTitle,cBotTitle,xQuiet, nTop) LOCAL nMessLen, nNumRows, nWide, nLeft, nBottom, nRight, nKey, cOldDevic, ; lOldPrint, ; cOldColor := SETCOLOR(), ; nOldLastkey := LASTKEY(), ; nOldRow := ROW(), ; nOldCol := COL(), ; nOldCurs := SETCURSOR(SC_NONE), ; nWinColor := iif(nWinColor == NIL, W_CURR, nWinColor) cOldDevic := SET(_SET_DEVICE, "SCREEN") lOldPrint := SET(_SET_PRINTER, .F.) nMessLen := LEN(cMessage) nWide := iif(nMessLen>72,72,iif(nMessLen<12,12,nMessLen)) nNumRows := MLCOUNT(cMessage,nWide) // If they didn't say what the top row is, Center it on the screen DEFAULT nTop TO INT((MAXROW()-nNumRows)/2) nBottom := nTop+nNumRows+2 nLeft := INT((MAXCOL()-nWide)/2)-3 nRight := nLeft+nWide+4 lWait := iif(lWait == NIL, .F., lWait) _ftPushWin(nTop,nLeft,nBottom,nRight,cTitle,cBotTitle,nWinColor) DISPMESSAGE cMessage,nTop+1,nLeft+2,nBottom-1,nRight-2 IF xQuiet == NIL TONE(800, 1) ENDIF IF lWait FT_INKEY 0 TO nKey _ftPopMessage() ENDIF SETCURSOR(nOldCurs) SETCOLOR(cOldColor) SETPOS(nOldRow,nOldCol) SET(_SET_DEVICE, cOldDevic) SET(_SET_PRINTER, lOldPrint) _ftSetLastKey(nOldLastKey) RETURN NIL /*+- Function ---------------------------------------------------------------+ | Name: _ftPopMessage Docs: Keith A. Wire | | Description: Pop off the Message Box | | Author: Keith A. Wire | | Date created: 10-03-93 Date updated: 10-03-93 | | Time created: 12:24:22pm Time updated: 12:24:22pm | | Copyright: None - Public Domain | +--------------------------------------------------------------------------+ | Arguments: None | | Return Value: NIL | | See Also: _ftPushMessage() | +--------------------------------------------------------------------------+ */ STATIC FUNCTION _ftPopMessage _ftPopWin() RETURN NIL /*+- Function ---------------------------------------------------------------+ | Name: _ftQuest() Docs: Keith A. Wire | | Description: Push a Question Box on the Screen | | Author: Keith A. Wire | | Date created: 10-03-93 Date updated: 10-03-93 | | Time created: 12:25:32pm Time updated: 12:25:32pm | | Copyright: None - Public Domain | +--------------------------------------------------------------------------+ | Arguments: cMessage | | : xVarVal | | : cPict | | : bValid | | : lNoESC | | : nWinColor | | : nTop | | Return Value: xVarVal | | Notes: This function will work for all Data Types | +--------------------------------------------------------------------------+ */ STATIC FUNCTION _ftQuest(cMessage,xVarVal,cPict,bValid,lNoESC,nWinColor,nTop) LOCAL nOldRow, nOldCol, cOldColor, nMessLen, nWide, nNumRows, nBottom, nLeft LOCAL nRight, oNewGet, nNumMessRow, nLenLastRow, lGetOnNextLine, nOldCurs LOCAL cVarType := VALTYPE(xVarVal) LOCAL nVarLen := iif(cVarType=="C",LEN(xVarVal),iif(cVarType=="D",8, ; iif(cVarType=="L",1,iif(cVarType=="N",iif(cPict==NIL,9, ; LEN(cPict)),0)))) LOCAL nOldLastKey := LASTKEY() LOCAL cOldDevice := SET(_SET_DEVICE, "SCREEN"), ; lOldPrint := SET(_SET_PRINTER, .F.) nOldRow := ROW() nOldCol := COL() nOldCurs := SETCURSOR(SC_NONE) cOldColor := SETCOLOR() lNoESC := iif(lNoESC==NIL,.F.,lNoESC) nMessLen := LEN(cMessage)+nVarLen+1 nWide := iif(nMessLen>66,66,iif(nMessLen<12,12,nMessLen)) nNumMessRow := MLCOUNT(cMessage,nWide) nLenLastRow := LEN(TRIM(MEMOLINE(cMessage,nWide,nNumMessRow))) lGetOnNextLine := (nLenLastRow + nVarLen) > nWide nNumRows := nNumMessRow + iif(lGetOnNextLine,1,0) // Center it in the screen nTop := iif(nTop==NIL,INT((MAXROW() - nNumRows)/2),nTop) nBottom := nTop+nNumRows+1 nLeft := INT((MAXCOL()-nWide)/2)-4 nRight := nLeft+nWide+4 _ftPushWin(nTop,nLeft,nBottom,nRight,"QUESTION ?",iif(VALTYPE(xVarVal)=="C" ; .AND. nVarLen>nWide,CHR(27)+" scroll "+ CHR(26),NIL),nWinColor) DISPMESSAGE cMessage,nTop+1,nLeft+2,nBottom-1,nRight-2 oNewGet := GetNew( iif(lGetOnNextLine,Row()+1,Row()), ; iif(lGetOnNextLine,nLeft+2,Col()+1), ; {|x| iif(PCOUNT() > 0, xVarVal := x, xVarVal)}, ; "xVarVal" ) // If the input line is character & wider than window SCROLL IF lGetOnNextLine .AND. VALTYPE(xVarVal)=="C" .AND. nVarLen>nWide oNewGet:Picture := "@S"+LTRIM(STR(nWide,4,0))+iif(cPict==NIL,""," "+cPict) ENDIF IF cPict != NIL // Use the picture they passed oNewGet:Picture := cPict ELSE // Else setup default pictures IF VALTYPE(xVarVal)=="D" oNewGet:Picture := "99/99/99" ELSEIF VALTYPE(xVarVal)=="L" oNewGet:Picture := "Y" ELSEIF VALTYPE(xVarVal)=="N" oNewGet:Picture := "999999.99" // Guess that they are inputting dollars ENDIF ENDIF oNewGet:PostBlock := iif(bValid==NIL,NIL,bValid) oNewGet:Display() SETCURSOR(SC_NORMAL) DO WHILE .T. // Loop so we can check for // without reissuing the gets ReadModal({oNewGet}) IF LASTKEY() == K_ESC .AND. lNoESC // They pressed _ftError("you cannot Abort! Please enter an answer.") ELSE EXIT ENDIF ENDDO _ftPopWin() SETCURSOR(nOldCurs) SETCOLOR(cOldColor) SETPOS(nOldRow,nOldCol) SET(_SET_DEVICE, cOldDevice) SET(_SET_PRINTER, lOldPrint) _ftSetLastKey(nOldLastKey) RETURN xVarVal /*+- Function ---------------------------------------------------------------+ | Name: _ftAdderTapeUDF() Docs: Keith A. Wire | | Description: User function for ACHOICE() when scrolling tape | | Author: Keith A. Wire | | Date created: 10-03-93 Date updated: 10-03-93 | | Time created: 12:26:44pm Time updated: 12:26:44pm | | Copyright: None - Public Domain | +--------------------------------------------------------------------------+ | Arguments: mode | | : cur_elem | | : rel_pos | | Return Value: nRtnVal | +--------------------------------------------------------------------------+ */ FUNCTION _ftAdderTapeUDF(mode,cur_elem,rel_pos) LOCAL nKey,nRtnVal THREAD STATIC ac_exit_ok := .F. HB_SYMBOL_UNUSED( cur_elem ) HB_SYMBOL_UNUSED( rel_pos ) DO CASE CASE mode == AC_EXCEPT nKey := LASTKEY() DO CASE CASE nKey == 30 nRtnVal := AC_CONT CASE nKey == K_ESC KEYBOARD CHR(K_CTRL_PGDN)+CHR(K_RETURN) // Go to last item ac_exit_ok := .T. nRtnVal := AC_CONT CASE ac_exit_ok nRtnVal := AC_ABORT ac_exit_ok := .F. OTHERWISE nRtnVal := AC_CONT ENDCASE OTHERWISE nRtnVal := AC_CONT ENDCASE RETURN nRtnVal /*+- Function ---------------------------------------------------------------+ | Name: _ftError() Docs: Keith A. Wire | | Description: Display an ERROR message in a window | | Author: Keith A. Wire | | Date created: 10-03-93 Date updated: 10-03-93 | | Time created: 12:27:43pm Time updated: 12:27:43pm | | Copyright: None - Public Domain | +--------------------------------------------------------------------------+ | Arguments: cMessage | | : xDontReset | | Return Value: NIL | +--------------------------------------------------------------------------+ */ STATIC FUNCTION _ftError(cMessage, xDontReset) LOCAL nOldRow,nOldCol,nOldCurs,nTop,nLeft,nBot,nRight,cOldColor, ; nOldLastKey,cErrorScr,nMessLen,nWide,nNumRows,nKey, ; cOldDevic,lOldPrint, ; lResetLKey := iif(xDontReset==NIL, .T., .F.) nOldLastKey := LASTKEY() nOldRow := ROW() nOldCol := COL() nOldCurs := SETCURSOR(SC_NONE) cOldColor:= _ftSetSCRColor(STD_ERROR) cOldDevic := SET(_SET_DEVICE, "SCREEN") lOldPrint := SET(_SET_PRINTER, .F.) cMessage := "I'm sorry but, " + cMessage nMessLen := LEN(cMessage) nWide := iif(nMessLen>66,66,iif(nMessLen<12,12,nMessLen)) nNumRows := MLCOUNT(cMessage,nWide) nTop := INT((MAXROW() - nNumRows)/2) // Center it in the screen nBot := nTop+3+nNumRows nLeft := INT((MAXCOL()-nWide)/2)-2 nRight := nLeft+nWide+4 cErrorScr:=SAVESCREEN(nTop,nLeft,nBot+1,nRight+2) _ftShadow(nBot+1,nLeft+2,nBot+1,nRight+2,8) _ftShadow(nTop+1,nRight+1,nBot ,nRight+2,8) @ nTop,nLeft,nBot,nRight BOX B_SINGLE @ nTop,nLeft+INT(nWide/2)-1 SAY " ERROR " @ nBot-1,nLeft+INT(nWide-28)/2+3 SAY "Press any key to continue..." DISPMESSAGE cMessage,nTop+1,nLeft+3,nBot-2,nRight-3 TONE(70,5) FT_INKEY 0 TO nKey RESTSCREEN(nTop,nLeft,nBot+1,nRight+2,cErrorScr) SETCURSOR(nOldCurs) SETCOLOR(cOldColor) SETPOS(nOldRow,nOldCol) IF lResetLKey _ftSetLastKey(nOldLastKey) ENDIF SET(_SET_DEVICE, cOldDevic) SET(_SET_PRINTER, lOldPrint) RETURN NIL /*+- Function ---------------------------------------------------------------+ | Name: _ftStuffComma() Docs: Keith A. Wire | | Description: Stuff a Comma in a string | | Author: Keith A. Wire | | Date created: 10-03-93 Date updated: 10-03-93 | | Time created: 12:28:19pm Time updated: 12:28:19pm | | Copyright: None - Public Domain | +--------------------------------------------------------------------------+ | Arguments: cStrToStuff | | : lTrimStuffedStr | | Return Value: cStrToStuff | +--------------------------------------------------------------------------+ */ STATIC FUNCTION _ftStuffComma(cStrToStuff,lTrimStuffedStr) LOCAL nDecPosit, x lTrimStuffedStr := iif(lTrimStuffedStr==NIL,.F.,lTrimStuffedStr) IF !("." $ cStrToStuff) cStrToStuff := _ftPosIns(cStrToStuff,".",iif("C"$cStrToStuff .OR. ; "E"$cStrToStuff .OR. "+"$cStrToStuff .OR. "-"$cStrToStuff ; .OR. "X"$cStrToStuff .OR. "*"$cStrToStuff .OR. ; ""$cStrToStuff .OR. "/"$cStrToStuff .OR. "="$cStrToStuff,; LEN(cStrToStuff)-1,LEN(cStrToStuff)+1)) IF ASC(cStrToStuff) == K_SPACE .OR. ASC(cStrToStuff) == K_ZERO cStrToStuff := SUBSTR(cStrToStuff, 2) ENDIF ENDIF nDecPosit := AT(".",cStrToStuff) IF LEN(LEFT(LTRIM(_ftCharRem("-",cStrToStuff)), ; AT(".",LTRIM(_ftCharRem("-",cStrToStuff)))-1))>3 IF lTrimStuffedStr // Do we trim the number each time we insert a comma FOR x := nDecPosit-3 TO 2+_ftCountLeft(cStrToStuff," ") STEP -4 cStrToStuff := SUBSTR(_ftPosIns(cStrToStuff,",",x),2) NEXT ELSE FOR x := nDecPosit-3 TO 2+_ftCountLeft(cStrToStuff," ") STEP -3 cStrToStuff := _ftPosIns(cStrToStuff,",",x) NEXT ENDIF ENDIF RETURN cStrToStuff /*+- Function ---------------------------------------------------------------+ | Name: _ftSetSCRColor() Docs: Keith A. Wire | | Description: Set the standard screen colors to the color requested. | | Author: Keith A. Wire | | Date created: 10-03-93 Date updated: 10-03-93 | | Time created: 12:28:48pm Time updated: 12:28:48pm | | Copyright: None - Public Domain | +--------------------------------------------------------------------------+ | Arguments: nStd | | : nEnh | | : nBord | | : nBack | | : nUnsel | | Return Value: SETCOLOR(aStdColor[nStd] + "," + aStdColor[nEnh] + "," + ; | | : aStdColor[nBord] + "," + aStdColor[nBack] + "," + ; | | : aStdColor[nUnsel]) | | See Also: _ftSetWinColor() | +--------------------------------------------------------------------------+ */ STATIC FUNCTION _ftSetSCRColor(nStd,nEnh,nBord,nBack,nUnsel) IF EMPTY(aWinColor) _ftInitColors() ENDIF nStd := iif(nStd == NIL, 8, nStd) nEnh := iif(nEnh == NIL, 8, nEnh) nBord := iif(nBord == NIL, 8, nBord) nBack := iif(nBack == NIL, 8, nBack) nUnsel:= iif(nUnsel == NIL, nEnh, nUnsel) RETURN SETCOLOR(aStdColor[nStd]+","+aStdColor[nEnh]+","+aStdColor[nBord]+","+; aStdColor[nBack]+","+aStdColor[nUnsel]) /*+- Function ---------------------------------------------------------------+ | Name: _ftPushWin() Docs: Keith A. Wire | | Description: Push a new window on the screen | | Author: Keith A. Wire | | Date created: 10-03-93 Date updated: 10-03-93 | | Time created: 12:34:38pm Time updated: 12:34:38pm | | Copyright: None - Public Domain | +--------------------------------------------------------------------------+ | Arguments: t | | : l | | : b | | : r | | : cTitle | | : cBotTitle | | : nWinColor | | Return Value: NIL | | See Also: | | Notes: Push a new window on the screen in the position t,l,b,r | | : and if cTitle is not NIL print the title for the window | | : in centered in the top line of the box. Similarly do | | : the same for cBotTitle. If nWinColor==NIL get the next | | : window color and use it for all the colors. If | | : cTypeBord==NIL use the single line border, else use the | | : one they requested. Push the window coordinates, the | | : color number, the SAVESCREEN() value, and whether they | | : picked the window color they wanted to use. If | | : lAutoWindow=.F. then the window color was incremented | | : and we will will restore the color number when we pop | | : the window off. | | : | | : nWinColor DEFAULT == _ftNextWinColor() | +--------------------------------------------------------------------------+ */ STATIC FUNCTION _ftPushWin(t,l,b,r,cTitle,cBotTitle,nWinColor) LOCAL lAutoWindow := nWinColor==NIL nWinColor := iif(nWinColor==NIL,_ftNextWinColor(),nWinColor) AADD(aWindow,{t,l,b,r,nWinColor,SAVESCREEN(t,l,b+1,r+2),lAutoWindow}) _ftShadow(b+1,l+2,b+1,r+2) _ftShadow(t+1,r+1,b,r+2) _ftSetWinColor(nWinColor,W_BORDER) @ t,l,b,r BOX B_SINGLE IF cTitle!=NIL _ftSetWinColor(nWinColor,W_TITLE) _ftWinTitle(cTitle) ENDIF IF cBotTitle!=NIL _ftSetWinColor(nWinColor,W_TITLE) _ftWinTitle(cBotTitle,"bot") ENDIF _ftSetWinColor(nWinColor,W_SCREEN,W_VARIAB) @ t+1,l+1 CLEAR TO b-1,r-1 RETURN NIL /*+- Function ---------------------------------------------------------------+ | Name: _ftPopWin Docs: Keith A. Wire | | Description: Pop a Window off the screen | | Author: Keith A. Wire | | Date created: 10-03-93 Date updated: 10-03-93 | | Time created: 12:52:34pm Time updated: 12:52:34pm | | Copyright: None - Public Domain | +--------------------------------------------------------------------------+ | Arguments: None | | Return Value: NIL | | Notes: Pop the currently active window off the screen by restoring| | : it from the aWindow Array and if they pushed a new window| | : automatically selecting the color we will roll back the | | : current window setting using _ftLastWinColor() and reset | | : the color to the color setting when window was pushed. | +--------------------------------------------------------------------------+ */ STATIC FUNCTION _ftPopWin LOCAL nNumWindow:=LEN(aWindow) RESTSCREEN(aWindow[nNumWindow,1],aWindow[nNumWindow,2], ; aWindow[nNumWindow,3]+1,aWindow[nNumWindow,4]+2, ; aWindow[nNumWindow,6]) IF aWindow[nNumWindow,7] _ftLastWinColor() ENDIF ASHRINK(aWindow) IF !EMPTY(aWindow) _ftSetWinColor(W_CURR,W_SCREEN,W_VARIAB) ELSE _ftSetSCRColor(STD_SCREEN,STD_VARIABLE) ENDIF RETURN NIL /*+- Function ---------------------------------------------------------------+ | Name: _ftSetWinColor() Docs: Keith A. Wire | | Description: Set the Color to the Window Colors requested | | Author: Keith A. Wire | | Date created: 10-03-93 Date updated: 10-03-93 | | Time created: 01:37:32pm Time updated: 01:37:32pm | | Copyright: None - Public Domain | +--------------------------------------------------------------------------+ | Arguments: nWin | | : nStd | | : nEnh | | : nBord | | : nBack | | : nUnsel | | Return Value:SETCOLOR(aWinColor[nStd,nWin]+","+aWinColor[nEnh,nWin]+","+;| | : aWinColor[nBord,nWin]+","+aWinColor[nBack,nWin]+","+ ;| | : aWinColor[nUnsel,nWin]) | | See Also: _ftSetSCRColor() | | Notes: If the window number is not passed use the currently active| | : window number nWinColor. | +--------------------------------------------------------------------------+ */ STATIC FUNCTION _ftSetWinColor(nWin,nStd,nEnh,nBord,nBack,nUnsel) nWin := iif(nWin == NIL, nWinColor, nWin) nStd := iif(nStd == NIL, 7, nStd) nEnh := iif(nEnh == NIL, 7, nEnh) nBord := iif(nBord == NIL, 7, nBord) nBack := iif(nBack == NIL, 7, nBack) nUnsel:= iif(nUnsel == NIL, nEnh, nUnsel) RETURN SETCOLOR(aWinColor[nStd,nWin]+","+aWinColor[nEnh,nWin]+","+ ; aWinColor[nBord,nWin]+","+aWinColor[nBack,nWin]+","+aWinColor[nUnsel,nWin]) /*+- Function ---------------------------------------------------------------+ | Name: _ftShadow() Docs: Keith A. Wire | | Description: Create a shadow on the screen in the coordinates given | | Author: Keith A. Wire | | Date created: 10-03-93 Date updated: 10-03-93 | | Time created: 01:40:56pm Time updated: 01:40:56pm | | Copyright: None - Public Domain | +--------------------------------------------------------------------------+ | Arguments: nTop | | : nLeft | | : nBottom | | : nRight | | Return Value: NIL | | See Also: _ftPushWin() | +--------------------------------------------------------------------------+ */ STATIC FUNCTION _ftShadow( nTop, nLeft, nBottom, nRight ) LOCAL theShadow := SAVESCREEN(nTop, nLeft, nBottom, nRight) RESTSCREEN( nTop, nLeft, nBottom, nRight, ; TRANSFORM( theShadow,REPLICATE("X", LEN(theShadow)/2 ) ) ) RETURN NIL /*+- Function ---------------------------------------------------------------+ | Name: _ftLastWinColor Docs: Keith A. Wire | | Description: Decrement the active window color number and return the | | : current value | | Author: Keith A. Wire | | Date created: 10-03-93 Date updated: 10-03-93 | | Time created: 01:49:19pm Time updated: 01:49:19pm | | Copyright: None - Public Domain | +--------------------------------------------------------------------------+ | Arguments: None | | Return Value: nWinColor := iif(nWinColor==1,4,nWinColor-1) | | Notes: If we are already on window #1 restart count by using # 4. | +--------------------------------------------------------------------------+ */ STATIC FUNCTION _ftLastWinColor RETURN nWinColor := iif(nWinColor==1,4,nWinColor-1) /*+- Function ---------------------------------------------------------------+ | Name: _ftNextWinColor Docs: Keith A. Wire | | Description: Increment the active window color number and return the | | : current value | | Author: Keith A. Wire | | Date created: 10-03-93 Date updated: 10-03-93 | | Time created: 01:51:12pm Time updated: 01:51:12pm | | Copyright: None - Public Domain | +--------------------------------------------------------------------------+ | Arguments: None | | Return Value: nWinColor := (iif(nWinColor<4,nWinColor+1,1)) | | Notes: If we are already on window #4 restart count by using # 1. | +--------------------------------------------------------------------------+ */ STATIC FUNCTION _ftNextWinColor IF EMPTY(aWinColor) _ftInitColors() ENDIF RETURN nWinColor := (iif(nWinColor<4,nWinColor+1,1)) /*+- Function ---------------------------------------------------------------+ | Name: _ftWinTitle() Docs: Keith A. Wire | | Description: Print the top or bottom titles on the border of the | | : currently active window. | | Author: Keith A. Wire | | Date created: 10-03-93 Date updated: 10-03-93 | | Time created: 01:52:29pm Time updated: 01:52:29pm | | Copyright: None - Public Domain | +--------------------------------------------------------------------------+ | Arguments: cTheTitle | | : cTopOrBot | | Return Value: NIL | +--------------------------------------------------------------------------+ */ STATIC FUNCTION _ftWinTitle(cTheTitle,cTopOrBot) LOCAL nCurWin :=LEN(aWindow), ; nLenTitle:=LEN(cTheTitle) @ aWindow[nCurWin,iif(cTopOrBot==NIL,1,3)],(aWindow[nCurWin,4]- ; aWindow[nCurWin,2]-nLenTitle)/2+aWindow[nCurWin,2] SAY " "+cTheTitle+" " RETURN NIL /*+- Function ---------------------------------------------------------------+ | Name: _ftInitColors Docs: Keith A. Wire | | Description: Initilize the colors for the Adder | | Author: Keith A. Wire | | Date created: 10-03-93 Date updated: 10-03-93 | | Time created: 02:59:58pm Time updated: 02:59:58pm | | Copyright: None - Public Domain | +--------------------------------------------------------------------------+ | Arguments: None | | Return Value: NIL | +--------------------------------------------------------------------------+ */ STATIC FUNCTION _ftInitColors aWinColor := { {"GR+/BG","GR+/G", "B+/RB", "G+/R"} , ; {"R+/N", "W+/RB","W+/BG","GR+/B"} , ; {"GR+/N", "GR+/N","GR+/N", "GR+/N"} , ; { "B/BG","BG+/G", "W+/RB","BG+/R"} , ; { "W+/BG", "W+/G","GR+/RB", "W+/R"} , ; {"GR+/B", "GR+/R", "R+/B", "W+/BG"}, ; { "N/N", "N/N", "N/N", "N/N"} } aStdColor := { "BG+*/RB" , ; "GR+/R" , ; "GR+/N" , ; "W/B" , ; "GR+/N" , ; "GR+/GR" , ; { "W+/B", "W/B","G+/B","R+/B", ; "GR+/B","BG+/B","B+/B","G+/B"}, ; "N/N" } RETURN NIL /*+- Function ---------------------------------------------------------------+ | Name: _ftCharOdd() Docs: Keith A. Wire | | Description: Remove all the even numbered characters in a string. | | Author: Keith A. Wire | | Date created: 10-03-93 Date updated: 10-03-93 | | Time created: 01:41:50pm Time updated: 01:41:50pm | | Copyright: None - Public Domain | +--------------------------------------------------------------------------+ | Arguments: cString | | Return Value: STRTRAN(cString,"") | | Notes: Used for example to strip all the attribute characters | | : from a screen save. | +--------------------------------------------------------------------------+ */ STATIC FUNCTION _ftCharOdd(cString) cString := TRANSFORM(cString,REPLICATE("X", LEN(cString)/2 ) ) RETURN STRTRAN(cString,"") /*+- Function ---------------------------------------------------------------+ | Name: _ftPosRepl() Docs: Keith A. Wire | | Description: Replace the Character at nPosit in cString with cChar | | Author: Keith A. Wire | | Date created: 10-03-93 Date updated: 10-03-93 | | Time created: 01:44:21pm Time updated: 01:44:21pm | | Copyright: None - Public Domain | +--------------------------------------------------------------------------+ | Arguments: cString | | : cChar | | : nPosit | | Return Value: STRTRAN(cString,"9",cChar,nPosit,1)+"" | +--------------------------------------------------------------------------+ */ STATIC FUNCTION _ftPosRepl(cString,cChar,nPosit) RETURN STRTRAN(cString,"9",cChar,nPosit,1)+"" /*+- Function ---------------------------------------------------------------+ | Name: _ftCharRem() Docs: Keith A. Wire | | Description: Removes all occurances of cChar from cString. | | Author: Keith A. Wire | | Date created: 10-03-93 Date updated: 10-03-93 | | Time created: 01:45:41pm Time updated: 01:45:41pm | | Copyright: None - Public Domain | +--------------------------------------------------------------------------+ | Arguments: cChar | | : cString | | Return Value: STRTRAN(cString,cChar) | +--------------------------------------------------------------------------+ */ STATIC FUNCTION _ftCharRem(cChar,cString) RETURN STRTRAN(cString,cChar) /*+- Function ---------------------------------------------------------------+ | Name: _ftCountLeft() Docs: Keith A. Wire | | Description: Returns the number of spaces on the Left side of the String| | Author: Keith A. Wire | | Date created: 10-03-93 Date updated: 10-03-93 | | Time created: 01:47:00pm Time updated: 01:47:00pm | | Copyright: None - Public Domain | +--------------------------------------------------------------------------+ | Arguments: cString | | Return Value: LEN(cString)-LEN(LTRIM(cString)) | +--------------------------------------------------------------------------+ */ STATIC FUNCTION _ftCountLeft(cString) RETURN LEN(cString)-LEN(LTRIM(cString)) /*+- Function ---------------------------------------------------------------+ | Name: _ftPosIns() Docs: Keith A. Wire | | Description: Insert the Character cChar in cString at position nPosit | | Author: Keith A. Wire | | Date created: 10-03-93 Date updated: 10-03-93 | | Time created: 01:48:30pm Time updated: 01:48:30pm | | Copyright: None - Public Domain | +--------------------------------------------------------------------------+ | Arguments: cString | | : cChar | | : nPosit | | Return Value: LEFT(cString,nPosit-1)+cChar+SUBSTR(cString,nPosit) | +--------------------------------------------------------------------------+ */ STATIC FUNCTION _ftPosIns(cString,cChar,nPosit) RETURN LEFT(cString,nPosit-1)+cChar+SUBSTR(cString,nPosit)