home *** CD-ROM | disk | FTP | other *** search
- /*
- Program: POPCALC.PRG
- System: GRUMPFISH LIBRARY
- Author: Greg Lief
- Copyright (c) 1988-90, Greg Lief
- Clipper 5.x version
- Compile instructions: clipper popcalc /n/w/a
-
- Procs & Fncts: MEMKEYS()
- : PASTE
- : PAPER_TAPE()
- : DRAWCALCBX()
-
- Calls: SHADOWBOX() (function in $SHADOWB.PRG)
- CHECKMOVE() (function in $MOVING.PRG)
-
- */
-
- //───── begin preprocessor directives
-
- #include "grump.ch"
- #include "inkey.ch"
-
- //───── end preprocessor directives
-
- //───── begin global declarations
-
- static num := 0, calctop := 5, calcleft := 28, ndecimals := 4
- static mpic := '###########.####' // PICTURE string for displaying numbers
- #translate ShowMemKeys() => @ calctop+6, calcleft+2 SAY 'R + -' ;;
- @ calctop+7, calcleft+2 SAY 'C * /'
-
- //───── end global declarations
-
-
- function popcalc(gfproc, line, var)
- local num1 := 0, mem := 0, decplace := 0, tnum, justcalced := .f., ;
- oldscrn := savescreen(calctop, calcleft, calctop + 12, calcleft + 26), ;
- op := 0, opstr := '+-*/^%', hotkey := 0, key := 0, papertape := .f., ;
- olddecimals := set(_SET_DECIMALS, 4), ;
- maincolor := ColorSet(C_CALCULATOR_BOX, .T.)
-
- GFSaveEnv(, 0) // shut off cursor
-
- //───── determine whether this was called via hot-key; if so, disable it
- if (gfproc != NIL)
- setkey(hotkey := lastkey(), NIL)
- endif
-
- /*
- Variables:
-
- NUM = primary number to be manipulated
- NUM1 = second number when operator has been introduced
- MEM = stored in memory
- OP = current operator: 1=add, 2=sub, 3=mult, 4=div, 5=exp
- NDECIMALS= number of decimals to display
- DECPLACE = decimal place counter - if decplace is 0, decimal point
- has not been activated; otherwise indicates # of digits to the right of it
-
- User-configurable color/screen coordinates: Current hot-key to change
- color is Alt-F10, although you can easily change this (see line 236
- below). Press any arrow key, Home, End, PgUp, PgDn to move window.
- */
-
- DrawCalcBx()
-
- //───── main loop
- do while key != K_ESC
-
- //───── display M if there is a number currently in memory
- @ calctop+3, calcleft+21 ssay if(mem != 0, 'M', chr(32))
- @ calctop+3, calcleft+4 say num picture mpic
- setcolor(maincolor)
-
- //───── display 1st number if an operator has been introduced
- if num1 != 0
- @ calctop+1,calcleft+4 say num1 picture mpic
- @ calctop+1,calcleft+21 ssay substr(opstr,op,1)
- else
- @ calctop+1,calcleft+4 ssay space(18)
- endif
-
- key := ginkey(0)
-
- do case
-
- //───── numeric key was pressed
- case key > 47 .and. key < 58
- tnum := val(chr(key)) // determine numeric value
- do case
-
- case (num=0 .or. justcalced) .and. decplace == 0
- num := tnum
- justcalced := .f.
-
- case num != 0 .and. decplace == 0 .and. num < 10000000000 //integer
- num := num * 10 + tnum
-
- case decplace > 0 .and. decplace <= ndecimals // real number
- num += (tnum / (10 ^ decplace))
- decplace++
-
- case justcalced .and. decplace <= ndecimals
- num := (tnum / (10 ^ decplace))
- justcalced := .f.
-
- endcase
-
- //───── backspace was pressed
- case key == K_BS .and. (num != 0 .or. decplace > 0)
- if decplace == 0 // if number is still an integer
- num := int(num / 10) // kill the least significant digit
- else
- decplace--
- if decplace > 0
- num := ltrim(str(num, 16, decplace))
- num := val(substr(num, 1, len(num) - 1))
- else
- num := 0
- endif
- endif
-
- //───── decimal point (period) was pressed
- case key == 46 .and. decplace == 0
- decplace++
-
- //───── operator pressed (43='+' 45='-' 42='*' 47='/' 94='^', 37='%')
- //───── with no pending operations
- case (key == 43 .or. key == 45 .or. key == 42 .or. ;
- key == 47 .or. key == 94 .or. key == 37) .and. ;
- op == 0 .and. num1 == 0
- num1 := num
- num := decplace := 0
- op := at(chr(key), opstr)
- justcalced := .f.
- if papertape
- Paper_Tape(str(num1) + ' ' + substr(opstr, op, 1))
- endif
-
- //───── '=', return or operator was pressed -- perform calculation
- case (key == 61 .or. key == 13 .or. key == 43 .or. key == 45 ;
- .or. key == 42 .or. key == 47 .or. key == 94) .and. op > 0
- if papertape
- Paper_Tape(str(num) + ' ' + substr(opstr, op, 1))
- endif
- do case
- case op == 1 // addition
- num += num1
- case op == 2 // subtraction
- num = num1 - num
- case op == 3 // multiplication
- num *= num1
- case op == 4 .and. num != 0 // division (don't allow by zero)
- num = num1 / num
- case op == 5 // exponent
- num = num1 ^ num
- case op == 6 // percentage
- num = num1 / 100 * num
- endcase
- decplace := 0
- op := at(chr(key), opstr)
- justcalced := .t.
- if op == 0
- num1 := 0
- if papertape
- Paper_Tape(str(num) + ' =')
- Paper_Tape()
- endif
- else
- num1 := num
- num := 0
- endif
-
- //───── 'c' was pressed to clear number
- case key == 67 .or. key == 99
- num := num1 := decplace := op := 0
-
- //───── 'd' was pressed to change decimals
- case key == 68 .or. key == 100
- setcolor('+' + maincolor)
- @ calctop+1, calcleft+2 ssay 'How many decimals?'
- key := ginkey(0)
- scroll(calctop+1, calcleft+2, calctop+1, calcleft+20, 0)
- if key > 47 .and. key < 58
- ndecimals := val(chr(key))
- mpic := replicate('#', 15 - ndecimals) + '.' + ;
- if(ndecimals > 0, replicate('#', ndecimals), '')
- set(_SET_DECIMALS, ndecimals)
- endif
-
- //───── 'r' was pressed to round number (truncate some decimals)
- case key == 82 .or. key == 114
- setcolor('+' + maincolor)
- @ calctop+1, calcleft+2 ssay 'Decimals to round to?'
- key := ginkey(0)
- scroll(calctop+1, calcleft+2, calctop+1, calcleft+23, 0)
- if (key > 47 .and. key < 58)
- key := val(chr(key))
- if key <= ndecimals
- num := round(num, key)
- endif
- endif
-
- //───── 'e' was pressed to clear entry
- case key == 69 .or. key == 101
- num := decplace := 0
-
- //───── 'p' was pressed for paper-tape function
- case key == 80 .or. key == 112
- papertape := (! papertape)
- @ calctop+3, calcleft+23 ssay if(papertape, 'P', ' ')
- if papertape
- Paper_Tape()
- endif
-
- //───── 'm' was pressed to access memory functions
- case key == 77 .or. key == 109
- setcolor('+*' + maincolor)
- ShowMemKeys()
- key := ginkey(0) // we need to get another key before taking action
- do case
- case key == 43 // '+' -- add number to memory
- mem += num
- case key == 45 // '-' -- subtract number from memory
- mem -= num
- case key == 42 // '*' -- multiple memory by number
- mem *= num
- case key == 47 // '/' -- divide memory by number
- mem /= num
- case key == 82 .or. key == 114 // 'r' -- recall memory
- num := mem
- case key == 67 .or. key == 99 // 'c' -- clear memory
- mem := 0
- endcase
- setcolor('+' + maincolor)
- ShowMemKeys()
-
- case key == K_ALT_F10 // change color!
- maincolor := ColorPal(maincolor, 16, IF(calcleft > 39, 0, 64))
- //───── if color was changed, redraw calculator box
- if lastkey() != 27
- ColorSet(C_CALCULATOR_BOX, maincolor)
- DrawCalcBx()
- endif
-
- case key < SPACEBAR .and. key != K_ESC
- checkmove(key, 12, 26, @calctop, @calcleft, @oldscrn)
-
- endcase
- ColorSet(C_CALCULATOR_WINDOW)
- enddo
-
- //───── restore hot-key
- if hotkey != 0
- setkey( hotkey, {|p, l, v| popcalc(p, l, v)} )
- endif
-
- //───── restore previous environment
- GFRestEnv()
- restscreen(calctop, calcleft, calctop+12, calcleft+26, oldscrn)
- set(_SET_DECIMALS, olddecimals)
- return NIL
-
- * end function PopCalc()
- *--------------------------------------------------------------------*
-
-
- /*
- Paste() -- paste current calculator value
- */
- function paste(a, b, c) // internal Clipper parameters
- local get := getactive()
- if get != NIL
- if get:type == "N"
- get:varPut(num)
- elseif get:type == "C"
- get:varPut(str(num))
- endif
- endif
- return NIL
-
- * end function Paste()
- *--------------------------------------------------------------------*
-
-
- /*
- Paper_Tape() -- send calculation to printer
- */
- static function Paper_Tape(mvar)
- default mvar to ''
- if isprinter()
- set device to printer
- @ prow()+1,1 say mvar picture mpic
- set device to screen
- endif
- return NIL
-
- * end static function Paper_Tape()
- *--------------------------------------------------------------------*
-
-
- /*
- DrawCalcBx() -- draw calculator box
- */
- static function drawcalcbx
- ColorSet(C_CALCULATOR_BOX)
- shadowbox(calctop, calcleft, calctop+11, calcleft + 24, 3)
- SINGLEBOX(calctop+2, calcleft+2, calctop+4, calcleft+22)
- @ calctop+5, calcleft+3 ssay 'emory│'
- @ row()+1, calcleft+2 ssay 'R + - │'
- @ row()+1, calcleft+2 ssay 'C * / │'
- @ row()+1, calcleft+1 ssay replicate(chr(196), 7) + chr(217)
- @ row()+1, calcleft+3 ssay 'lear rint c ntry'
- @ row()+1, calcleft+3 ssay 'ound ecimals'
- @ calctop+5, calcleft+10 ssay '+ 7 8 9 -'
- @ row()+1, calcleft+10 ssay '* 4 5 6 /'
- @ row()+1, calcleft+10 ssay '% 1 2 3 ^'
- @ row()+1, calcleft+13 ssay '= 0 .'
- ColorSet(C_CALCULATOR_WINDOW)
- @ calctop+3, calcleft+3 ssay space(19)
- @ row()+2, calcleft+2 ssay 'M'
- @ row()+4, calcleft+2 ssay 'C'
- @ row(), col()+6 ssay 'P'
- @ row(), col()+8 ssay 'E'
- @ row()+1, calcleft+2 ssay 'R'
- @ row(), col()+6 ssay 'D'
- @ row(), col()+10 ssay 'Esc'
- return NIL
-
- * end static function DrawCalcBx()
- *--------------------------------------------------------------------*
-
- * eof popcalc.prg
-