home *** CD-ROM | disk | FTP | other *** search
/ POINT Software Programming / PPROG1.ISO / basic / qbasic / function.bas < prev   
Encoding:
BASIC Source File  |  1993-10-14  |  23.5 KB  |  843 lines

  1.  
  2.  
  3.  
  4.   ' DISCLAIMER/WARRANTY INFORMATION
  5.   ' ─────────────────────────────────────────────────────────────────
  6.   ' Users of these Routines must accept this disclaimer of warranty:
  7.   '
  8.   ' These Routines are supplied as is. The author disclaims all
  9.   ' warranties, expressed or implied, including, without limitation,
  10.   ' the warranties of merchantability and of fitness for any purpose.
  11.   ' The author assumes no liability for damages, direct or
  12.   ' consequential, which may result from the use of these routines.
  13.   '
  14.  
  15.  
  16.   ' Placed in the public domain October 1993
  17.   '
  18.   ' by David Cantrell  CIS# 73730,2741
  19.   '                    Fax# (914) 528-2613
  20.   '
  21.   '         ***** USE THESE ROUTINES AT YOUR OWN RISK *****
  22.   '
  23.  
  24.  
  25.  
  26.   DEFINT A-Z        ' These Lines are required in your program
  27.   %True = -1        ' for some of the routines to
  28.   %False = 0        ' operate properly
  29.  
  30.  
  31.  
  32.   ' FUNCTION DaysApart(STRING, STRING)
  33.   '
  34.   '          Returns the number of days between the two dates, Leap Year aware
  35.   '
  36.   ' FUNCTION DaysInMonth(INTEGER, INTEGER)
  37.   '
  38.   '          Returns the number of Days in the Month, Leap Year aware
  39.   '
  40.   ' FUNCTION DosVer!
  41.   '
  42.   '          Returns DOS Version Number
  43.   '
  44.   ' FUNCTION EVEN(INTEGER)
  45.   '
  46.   '          Returns True if even number, False if not
  47.   '
  48.   ' FUNCTION FileExists(STRING)
  49.   '
  50.   '          Returns True if file exists along with Date, Time, Size & Atrib
  51.   '
  52.   ' FUNCTION FormatMoney$(STRING)
  53.   '
  54.   '          Returns string in dollars and cents, ie. two decimal places
  55.   '
  56.   ' FUNCTION GetProgPath$
  57.   '
  58.   '          Returns the Full Path of the current Program now executing
  59.   '
  60.   ' FUNCTION GetUserInput$(STRING, INTEGER, INTEGER)
  61.   '
  62.   '          Returns User Input from keyboard with Editing & Window Scrolling
  63.   '
  64.   ' FUNCTION INCRDate$(STRING, INTEGER)
  65.   '
  66.   '          Increments date by a specified number of days, Leap Year aware
  67.   '
  68.   ' FUNCTION INCRSeries$(STRING)
  69.   '
  70.   '          Increments an alfa/numeric String Series
  71.   '
  72.   ' FUNCTION NameOfDay$(STRING)
  73.   '
  74.   '          Returns the Name of the day of the week
  75.   '
  76.   ' FUNCTION ODD(INTEGER)
  77.   '
  78.   '          Returns True if odd number, False if not
  79.   '
  80.   ' FUNCTION ShiftedKeys
  81.   '
  82.   '          Returns True if Shift, Control or Alternate & which one
  83.   '
  84.   ' FUNCTION TodaysDate$
  85.   '
  86.   '          Returns System Date in the "YYYYMMDD" (Year,Month,Day) Format
  87.   '
  88.   ' FUNCTION TRIM$(STRING)
  89.   '
  90.   '          Trims off Leading and Trailing spaces from a string
  91.   '
  92.   ' FUNCTION ValidDate(STRING)
  93.   '
  94.   '          Returns True if Valid Date, False if not, Leap Year aware
  95.   '
  96.   
  97.  
  98. FUNCTION DaysApart(BYVAL DateFrom$, BYVAL DateTo$)
  99.  
  100.   ' Returns the number of days between the two dates
  101.   ' This function is aware of leap years
  102.   ' No modifications are made to either Date
  103.  
  104.   ' Requires Dates to be in "YYYYMMDD" (Year,Month,Day) Format
  105.   ' Requires FUNCTION ValidDate
  106.   ' Requires FUNCTION DaysInMonth
  107.  
  108.   ' Example: Print DaysApart("19930101","19940101") prints to the screen 365
  109.   ' Example: Print DaysApart("19920101","19930101") prints to the screen 366
  110.   '                                                      1992 was a Leap Year
  111.  
  112.   LOCAL FD, FM, FY, TD, TM, TY, Days
  113.  
  114.   DaysApart = 0
  115.   Days = 0
  116.  
  117.   IF NOT(ValidDate(DateFrom$)) OR _
  118.      NOT(ValidDate(DateTo$))   OR _
  119.      VAL(DateFrom$) => VAL(DateTo$) THEN EXIT FUNCTION
  120.  
  121.   FY = VAL(LEFT$(DateFrom$, 4))                'From Year
  122.   FM = VAL(MID$(DateFrom$,5,2))                '     Month
  123.   FD = VAL(RIGHT$(DateFrom$,2))                '     Day
  124.  
  125.   TY = VAL(LEFT$(DateTo$,   4))                'To   Year
  126.   TM = VAL(MID$(DateTo$,  5,2))                '     Month
  127.   TD = VAL(RIGHT$(DateTo$,  2))                '     Day
  128.  
  129.   DO
  130.     INCR FD
  131.     INCR Days
  132.     IF FD > DaysInMonth(FY,FM) THEN
  133.       INCR FM
  134.       FD = 1
  135.       IF FM > 12 THEN
  136.         INCR FY
  137.         FM = 1
  138.       END IF
  139.     END IF
  140.   LOOP UNTIL FY = TY AND FM = TM AND FD = TD
  141.  
  142.   DaysApart = Days
  143.  
  144.  END FUNCTION
  145.  
  146. FUNCTION DaysInMonth(BYVAL Year, BYVAL Month)
  147.  
  148.   ' Returns the number of Days in the Month
  149.   ' No modifications are made to Year or Month
  150.   ' Year info must be in full ie. 1993 NOT 93
  151.   ' This function is aware of leap years
  152.  
  153.   ' Example PRINT DaysInMonth(1993,2) prints to the screen 28
  154.   ' Example PRINT DaysInMonth(1992,2) prints to the screen 29
  155.   '                                            1992 was a Leap Year
  156.  
  157.   DaysInMonth = 0
  158.  
  159.   IF Year < 1000 THEN EXIT FUNCTION
  160.  
  161.   SELECT CASE Month
  162.     CASE 2
  163.       IF (Year / 4) - FIX(Year / 4) = 0 THEN      'Leap Year
  164.         DaysInMonth = 29
  165.       ELSE                                        'Non-Leap Year
  166.         DaysInMonth = 28
  167.       END IF
  168.     CASE 4, 6, 9, 11
  169.       DaysInMonth = 30
  170.     CASE ELSE
  171.       DaysInMonth = 31
  172.   END SELECT
  173.  
  174.  END FUNCTION
  175.  
  176. FUNCTION DosVer!
  177.  
  178.   ' Returns DOS Version Number
  179.   ' i.e.  3.3  4.01  5.0 etc.
  180.  
  181.   REG 1, &H3000
  182.   CALL INTERRUPT &H21
  183.   DosVer! = REG(1) MOD 256 + (REG(1) \ 256) / 100
  184.  
  185.  END FUNCTION
  186.  
  187. FUNCTION EVEN(BYVAL Number)
  188.  
  189.   ' Returns True if even number, False if not
  190.   ' No modifications are made to Number
  191.  
  192.   IF (Number / 2) - FIX(Number / 2) = 0 THEN
  193.     EVEN = %True
  194.   ELSE
  195.     EVEN = %False
  196.   END IF
  197.  
  198.  END FUNCTION
  199.  
  200. FUNCTION FileExists(BYVAL FileSpec$)
  201.  
  202.   ' Returns True if file exists based on setting of FileAttribute% (see below)
  203.   ' No modifications are made to FileSpec$
  204.   ' If True then this function also returns as shared variables:
  205.   '    FileTime$ - "HH:MM:SS"
  206.   '    FileDate$ - "MM/DD/YYYY"
  207.   '    FileSize$ - "12345" - "12345678" etc.
  208.   '    FileAttb$ - "∙∙∙∙∙" - "SHRAD"  or combination of the two where:
  209.   '                           S = System
  210.   '                           H = Hidden
  211.   '                           R = Read Only
  212.   '                           A = Archive
  213.   '                           D = Directory
  214.   '
  215.   ' The Current Disk Transfer Area (DTA) is preserved!
  216.   ' Requires FUNCTION TRIM$
  217.  
  218.   SHARED FileTime$, FileDate$, FileSize$, FileAttb$
  219.  
  220.   LOCAL FileSpec1$, FileAttribute%
  221.   LOCAL OrigDTASeg??, OrigDTAOff??, TempDTA$, DTASeg??, DTAOff??
  222.   LOCAL DTAAttr??, DTADate??, DTASize??, DTATime??, FDate%, FTime%, FileAtt%
  223.   LOCAL Hours, Hours$, Minutes, Minutes$, Seconds, Seconds$
  224.   LOCAL Month, Month$, Day, Day$, Year, Year$
  225.  
  226.   TempDTA$  = STRING$(43,0)                    ' Create a temporary DTA
  227.   FileDate$ = ""
  228.   FileTime$ = ""
  229.   FileSize$ = ""
  230.   FileAttb$ = ""
  231.  
  232.   REG 1,&H2F00                                 ' Save original DTA address
  233.   CALL INTERRUPT &H21                          ' so that it is not altered
  234.   OrigDTASeg?? = REG(9)
  235.   OrigDTAOff?? = REG(2)
  236.  
  237.   DTASeg?? = STRSEG(TempDTA$)
  238.   DTAOff?? = STRPTR(TempDTA$)
  239.   DTAAttr?? = DTAOff?? + &H15
  240.   DTATime?? = DTAOff?? + &H16
  241.   DTADate?? = DTAOff?? + &H18
  242.   DTASize?? = DTAOff?? + &H1A
  243.  
  244.   REG 1, &H1A00                                ' Set New DTA address
  245.   REG 4, DTAOff??
  246.   REG 8, DTASeg??
  247.   CALL INTERRUPT &H21
  248.  
  249.   FileSpec1$ = FileSpec$ + CHR$(0)             ' Does file exist?
  250.  
  251.     ' File Attribute to search for: `FileAttribute%'
  252.     ' 0  = Normal
  253.     ' 2  = Normal & Hidden
  254.     ' 4  = Normal & System
  255.     ' 6  = Normal & Hidden & System
  256.     ' 8  = Volume Labels
  257.     ' 16 = Directories
  258.  
  259.     FileAttribute% = 6
  260.  
  261.   REG 1, &H4E00
  262.   REG 3, FileAttribute%
  263.   REG 4, STRPTR(FileSpec1$)
  264.   REG 8, STRSEG(FileSpec1$)
  265.   CALL INTERRUPT &H21
  266.   IF (REG(0) AND 1) = 0 THEN
  267.  
  268.     FileExists = %True
  269.  
  270.     DEF SEG = DTASeg??
  271.       FileAtt%  = PEEK(DTAAttr??)                   ' Read Temp DTA
  272.       FileSize$ = TRIM$(STR$(PEEKL(DTASize??)))     ' for File Attributes
  273.       FDate%    = PEEKI(DTADate??)                  ' Size, Date and Time
  274.       FTime%    = PEEKI(DTATime??)                  '
  275.     DEF SEG
  276.             
  277.     FileAttb$ = "∙∙∙∙∙"
  278.     IF (FileAtt% AND &H20) THEN MID$(FileAttb$, 4, 1) = "A"     ' Attributes
  279.     IF (FileAtt% AND &H10) THEN MID$(FileAttb$, 5, 1) = "D"
  280.     IF (FileAtt% AND &H04) THEN MID$(FileAttb$, 1, 1) = "S"
  281.     IF (FileAtt% AND &H02) THEN MID$(FileAttb$, 2, 1) = "H"
  282.     IF (FileAtt% AND &H01) THEN MID$(FileAttb$, 3, 1) = "R"
  283.  
  284.     Hours = FTime% AND &HF800                                   ' Hours
  285.     SHIFT RIGHT Hours, 11
  286.     Hours$ = TRIM$(STR$(Hours))
  287.     IF LEN(Hours$) = 1 THEN Hours$ = "0" + Hours$
  288.     Minutes = FTime% AND &H07E0                                 ' Minutes
  289.     SHIFT RIGHT Minutes, 5
  290.     Minutes$ = TRIM$(STR$(Minutes))
  291.     IF LEN(Minutes$) = 1 THEN Minutes$ = "0" + Minutes$
  292.     Seconds = FTime% AND &H001F                                 ' Seconds
  293.     Seconds$  = TRIM$(STR$(Seconds * 2))
  294.     IF LEN(Seconds$) = 1 THEN Seconds$  = "0" + Seconds$
  295.  
  296.     FileTime$ = Hours$ + ":" + Minutes$ + ":" + Seconds$
  297.  
  298.     Month = FDate% AND &H01E0                                   ' Month
  299.     SHIFT RIGHT Month, 5
  300.     Month$ = TRIM$(STR$(Month))
  301.     IF LEN(Month$) = 1 THEN Month$ = "0" + Month$
  302.     Day = FDate% AND &H001F                                     ' Day
  303.     Day$ = TRIM$(STR$(Day))
  304.     IF LEN(Day$) = 1 THEN Day$ = "0" + Day$
  305.     Year = FDate% AND &HFE00                                    ' Year
  306.     SHIFT RIGHT Year, 9
  307.     Year$ = TRIM$(STR$(Year + 1980))
  308.  
  309.     FileDate$ = Month$ + "/" + Day$ + "/" + Year$
  310.   ELSE
  311.     FileExists = %False
  312.   END IF
  313.   
  314.   REG 1,&H1A00                                 ' Restore the original DTA
  315.   REG 8,OrigDTASeg??
  316.   REG 4,OrigDTAOff??
  317.   CALL INTERRUPT &H21
  318.  
  319.  END FUNCTION
  320.  
  321. FUNCTION FormatMoney$(BYVAL MoneyVal$)
  322.  
  323.   ' Returns string formated in dollars and cents, ie. two decimal places
  324.   ' No modifications are made to MoneyVal$
  325.   ' Requires FUNCTION TRIM$
  326.  
  327.   ' Example PRINT FormatMoney$("25") prints to the screen 25.00
  328.   ' Example PRINT FormatMoney$("5.2") prints to the screen 5.20
  329.   ' Example PRINT FormatMoney$(" 5 ") prints to the screen 5.00
  330.  
  331.   LOCAL MVal$
  332.  
  333.   FormatMoney$ = ""
  334.  
  335.   MVal$ = TRIM$(MoneyVal$)
  336.  
  337.   IF VAL(MVal$) <> 0 THEN
  338.  
  339.     IF INSTR(MVal$, ".") = 0 THEN MVal$ = MVal$ + ".00"
  340.  
  341.     IF INSTR(MVal$, ".") > 0 AND _
  342.        MID$(MVal$, LEN(MVal$) -1, 1) = "." THEN _
  343.                                    MVal$ = MVal$ + "0"
  344.  
  345.     IF RIGHT$(MVal$, 1) = "." THEN MVal$ = MVal$ + "00"
  346.  
  347.     FormatMoney$ = MVal$
  348.  
  349.   END IF
  350.  
  351.  END FUNCTION
  352.  
  353. FUNCTION GetProgPath$
  354.  
  355.   ' Returns the Path of the current Program now executing
  356.   ' This function can only be used with DOS 3.0 & up
  357.   ' Requires FUNCTION DosVer!
  358.  
  359.   LOCAL EnvSeg??, LastBackSlash, Offset??, Path$, X
  360.  
  361.   GetProgPath$ = ""
  362.  
  363.   IF DosVer! < 3.0 THEN EXIT FUNCTION    ' This function is only available
  364.                                          ' in DOS 3.0 & up
  365.  
  366.   REG 1, &H6200                          '
  367.   CALL INTERRUPT &H21                    ' Get PSP Segment Address
  368.   DEF SEG = REG(2)                       '
  369.  
  370.   EnvSeg?? = PEEKI(&H2C)                 ' Get the Segment Address of the DOS
  371.   DEF SEG = EnvSeg??                     ' Environment from the PSP.
  372.  
  373.   Offset?? = 0
  374.   DO                                     ' Find the end of the DOS environment
  375.     INCR Offset??                        ' i.e. Two CHR$(0)'s in a row
  376.   LOOP UNTIL PEEKI(Offset??) = 0         '
  377.  
  378.   INCR Offset??, 4                       ' Skip the CHR$(0)'s + two bytes
  379.  
  380.   DO                                     ' Load the ASCIIZ string containing
  381.     Path$ = Path$ + CHR$(PEEK(Offset??)) ' the complete Drive, Path and Name
  382.     INCR Offset??                        ' of the Parent Program
  383.   LOOP UNTIL PEEK(Offset??) = 0          '
  384.  
  385.   DEF SEG
  386.  
  387.   LastBackSlash = 0                      ' find last occurance of "\"
  388.   DO
  389.     X = INSTR(MID$(Path$,LastBackSlash + 1), "\")
  390.     IF X = 0 THEN
  391.       EXIT LOOP
  392.     ELSE
  393.       LastBackSlash = LastBackSlash + X
  394.     END IF
  395.   LOOP
  396.  
  397.   GetProgPath$ = LEFT$(Path$,LastBackSlash)       'Return just the Path
  398.  
  399.  END FUNCTION
  400.  
  401. FUNCTION GetUserInput$(BYVAL OrigText$, BYVAL TextLength, BYVAL WindowLength)
  402.  
  403.   ' Returns User Input from keyboard
  404.   ' No modifications are made to OrigText$, TextLength or WindowLength
  405.   ' Programable Text and Window Length
  406.   ' Automatic Scrolling within a Window
  407.   ' Allows for editing of input: Insert, Overwrite, Backspace, Delete
  408.   '                              Home, End, Left Arrow, Right Arrow & Escape
  409.   ' Defaults to Overwrite mode (Insert Off)
  410.  
  411.   ' Text Length passed to Function or 0 = Unlimited
  412.   ' Window Length passed to Function or 0 = Starting column to end of Row
  413.   ' Escape Key returns the Original String
  414.   ' ExitKey$ holds value of exiting key stroke - CR or ESC
  415.   ' Changed is set to true if the original string <> exiting string
  416.  
  417.   ' Example  UserText$ = GetUserInput$("What ever", 10, 5)
  418.  
  419.   SHARED ExitKey$, Changed
  420.  
  421.   LOCAL CurrentPosInText, CurrentPosInWindow, InsertKey, KBD$
  422.   LOCAL ScrollingMode, SpecialKey, StartCol, StartRow, Text$, X
  423.  
  424.   StartRow = CSRLIN
  425.   StartCol = POS
  426.  
  427.   Text$ = OrigText$
  428.  
  429.   IF WindowLength = 0 THEN _            'Set WindowLength to whats left of the
  430.      WindowLength = 81 - StartCol       'screen width and scroll within it
  431.  
  432.   PRINT SPACE$(WindowLength);
  433.  
  434.   LOCATE StartRow, StartCol
  435.  
  436.   IF Text$ > SPACE$(TextLength) THEN
  437.     IF LEN(Text$) >= WindowLength THEN
  438.       PRINT LEFT$(Text$, WindowLength);
  439.       CurrentPosInWindow = WindowLength
  440.       CurrentPosInText = WindowLength
  441.     ELSE
  442.       PRINT Text$;
  443.       CurrentPosInWindow = LEN(Text$) + 1
  444.       CurrentPosInText = LEN(Text$) + 1
  445.     END IF
  446.   ELSE
  447.     CurrentPosInText = 1
  448.     CurrentPosInWindow = 1
  449.   END IF
  450.  
  451.   InsertKey = %False                    'Start in Overwrite mode
  452.   ScrollingMode = %False
  453.   SpecialKey = %True
  454.   KBD$ = ""
  455.  
  456.   DO
  457.  
  458.     IF InsertKey THEN
  459.       LOCATE ,,1,0,7                    'Insert Cursor On
  460.     ELSE
  461.       LOCATE ,,1,6,7                    'Overwrite Cursor On
  462.     END IF
  463.  
  464.     IF KBD$ > "" THEN
  465.       IF CurrentPosInText > LEN(Text$) THEN
  466.         Text$ = Text$ + KBD$
  467.       ELSE
  468.         IF InsertKey THEN
  469.           Text$ = LEFT$(Text$,CurrentPosInText - 1) + _
  470.                   KBD$ + MID$(Text$,CurrentPosInText)
  471.         ELSE
  472.           Text$ = LEFT$(Text$,CurrentPosInText - 1) + _
  473.                   KBD$ + MID$(Text$,CurrentPosInText + 1)
  474.         END IF
  475.         IF CurrentPosInWindow < WindowLength THEN SpecialKey = %True
  476.       END IF
  477.     END IF
  478.     IF LEN(Text$) + 1 >= WindowLength THEN
  479.       ScrollingMode = %True
  480.       LOCATE StartRow, StartCol
  481.       X = (CurrentPosInText + 1) - WindowLength
  482.       IF X < 1 THEN X = 1
  483.       IF NOT(SpecialKey) AND LEN(Text$) >= WindowLength THEN INCR X
  484.       PRINT MID$(Text$,X,WindowLength); " ";
  485.     ELSE
  486.       ScrollingMode = %False
  487.       LOCATE StartRow, StartCol
  488.       PRINT Text$; " ";
  489.     END IF
  490.  
  491.     IF KBD$ > "" THEN
  492.       INCR CurrentPosInText
  493.       IF CurrentPosInWindow < WindowLength THEN INCR CurrentPosInWindow
  494.     END IF
  495.  
  496.     LOCATE StartRow, StartCol + CurrentPosInWindow - 1
  497.  
  498.     SpecialKey = %False
  499.     
  500.     WHILE NOT INSTAT : WEND
  501.     KBD$ = INKEY$
  502.  
  503.     IF ASCII(KBD$) = 27 THEN                                   'Escape Key
  504.       Text$ = OrigText$
  505.     END IF
  506.  
  507.     IF ASCII(KBD$) = 8 THEN                                    'BackSpace Key
  508.  
  509.       IF CurrentPosInText > 1 THEN
  510.         DECR CurrentPosInText
  511.         Text$ = LEFT$(Text$,CurrentPosInText - 1) + _
  512.                 MID$(Text$,CurrentPosInText + 1)
  513.         IF ScrollingMode THEN
  514.           IF LEN(Text$) < WindowLength - 1 THEN
  515.             LOCATE StartRow,StartCol
  516.             PRINT Text$;
  517.           END IF
  518.           IF CurrentPosInText < WindowLength THEN DECR CurrentPosInWindow
  519.         ELSE
  520.           LOCATE StartRow,StartCol
  521.           PRINT Text$;
  522.           IF CurrentPosInWindow > 1 THEN DECR CurrentPosInWindow
  523.         END IF
  524.         IF CurrentPosInWindow <= WindowLength THEN PRINT " ";
  525.       END IF
  526.  
  527.       KBD$ = ""
  528.       SpecialKey = %True
  529.  
  530.     END IF  
  531.  
  532.     IF LEN(KBD$) > 1 THEN                   'If Extended Key has been pressed
  533.  
  534.       IF ASC(RIGHT$(KBD$,1)) = 82 THEN InsertKey = NOT(InsertKey)
  535.  
  536.       IF ASC(RIGHT$(KBD$,1)) = 83 THEN                            'Delete Key
  537.         Text$ = LEFT$(Text$,CurrentPosInText - 1) + _
  538.                 MID$(Text$,CurrentPosInText + 1)
  539.       END IF
  540.  
  541.       IF ASC(RIGHT$(KBD$,1)) = 75 AND CurrentPosInText > 1 THEN   'Left Arrow
  542.         DECR CurrentPosInText
  543.         IF CurrentPosInWindow > 1 AND CurrentPosInText <= WindowLength THEN
  544.           IF CurrentPosInText = WindowLength THEN
  545.           ELSE
  546.             DECR CurrentPosInWindow
  547.           END IF
  548.         END IF
  549.       END IF
  550.  
  551.       IF ASC(RIGHT$(KBD$,1)) = 77 AND _                           'Right Arrow
  552.          CurrentPosInText <= LEN(Text$) THEN
  553.         INCR CurrentPosInText
  554.         IF CurrentPosInWindow < WindowLength THEN INCR CurrentPosInWindow
  555.       END IF
  556.  
  557.       IF ASC(RIGHT$(KBD$,1)) = 71 THEN                            'Home Key
  558.         CurrentPosInText = 1
  559.         CurrentPosInWindow = 1
  560.       END IF
  561.  
  562.       IF ASC(RIGHT$(KBD$,1)) = 79 THEN                            'End Key
  563.         CurrentPosInText = LEN(Text$) + 1
  564.         IF LEN(Text$) >= WindowLength THEN
  565.           CurrentPosInWindow = WindowLength
  566.         ELSE
  567.           CurrentPosInWindow = LEN(Text$) + 1
  568.         END IF
  569.       END IF
  570.  
  571.       KBD$ = ""
  572.       SpecialKey = %True
  573.  
  574.     END IF
  575.  
  576.     IF TextLength > 0 AND _
  577.        LEN(Text$) = TextLength AND KBD$ <> CHR$(13) _
  578.        AND KBD$ <> CHR$(27) AND KBD$ > "" THEN       'Don't Allow Another Key
  579.       KBD$ = ""
  580.       SOUND 54, 1
  581.       SpecialKey = %True
  582.     END IF
  583.     
  584.   LOOP UNTIL (KBD$ = CHR$(13) OR KBD$ = CHR$(27))
  585.  
  586.   LOCATE ,,0,0,7                                     'Turn Cursor Off
  587.  
  588.   GetUserInput$ = Text$
  589.  
  590.   IF Text$ <> OrigText$ THEN
  591.     Changed = %True
  592.   ELSE
  593.     Changed = %False
  594.   END IF
  595.  
  596.   ExitKey$ = KBD$
  597.  
  598.  END FUNCTION
  599.  
  600. FUNCTION INCRDate$(BYVAL StartDate$, BYVAL Days)
  601.  
  602.   ' Increments the date by a specified number of days
  603.   ' This function is aware of leap years
  604.   ' No modifications are made to StartDate$ or Days
  605.  
  606.   ' Requires StartDate$ to be in "YYYYMMDD" (Year,Month,Day) Format
  607.   ' Requires FUNCTION DaysInMonth
  608.  
  609.   ' Example: Print INCRDate$("19920227",3) prints to the screen 19920301
  610.   '                                                    1992 was a Leap Year
  611.  
  612.   LOCAL Day, Day$, Month, Month$, X, Year, Year$
  613.  
  614.   Month = VAL(MID$(StartDate$,5,2))
  615.   Day   = VAL(RIGHT$(StartDate$,2))
  616.   Year  = VAL(LEFT$(StartDate$,4))
  617.  
  618.   FOR X = 1 TO Days
  619.    INCR Day
  620.    IF Day > DaysInMonth(Year,Month) THEN
  621.      INCR Month
  622.      Day = 1
  623.    END IF
  624.    IF Month > 12 THEN
  625.      INCR Year
  626.      Month = 1
  627.    END IF
  628.   NEXT X
  629.  
  630.   Year$  = TRIM$(STR$(Year))
  631.   Month$ = TRIM$(STR$(Month))
  632.   Day$   = TRIM$(STR$(Day))
  633.  
  634.   IF LEN(Month$) = 1 THEN Month$ = "0" + Month$
  635.   IF LEN(Day$) = 1 THEN Day$ = "0" + Day$
  636.  
  637.   INCRDate$ = Year$ + Month$ + Day$
  638.  
  639.  END FUNCTION
  640.  
  641.  
  642. FUNCTION INCRSeries$(BYVAL TheString$)
  643.  
  644.   ' Increments an alfa/numeric String Series
  645.   ' No modifications are made to TheString$
  646.   ' Acceptable values in the string are A-Z and 0-9
  647.   ' Anything else returns a Null String
  648.   ' Requires FUNCTION TRIM$
  649.  
  650.   ' Example PRINT INCRSeries$("SC97") prints to the screen SC98
  651.   ' Example PRINT INCRSeries$("SC99") prints to the screen SD00
  652.   ' Example PRINT INCRSeries$("AZ99") prints to the screen BA00
  653.  
  654.   ' Note: INCRSeries$("999") returns "000" not "1000", unlike PB's INCR X
  655.  
  656.   LOCAL NextTimeThruINCR, Series$, X, Y
  657.  
  658.   X = LEN(TRIM$(TheString$))
  659.   Series$ = SPACE$(X)
  660.  
  661.   NextTimeThruINCR = %True
  662.  
  663.   DO WHILE X > 0                        'Search the series to be incremented
  664.                                         'from right to left
  665.     Y = ASC(MID$(TRIM$(TheString$),X,1))
  666.  
  667.     IF NextTimeThruINCR THEN INCR Y
  668.  
  669.     IF Y < 59 AND Y > 47 THEN           'If 0-9
  670.       IF Y = 58 THEN
  671.         Y = 48
  672.       ELSE
  673.           NextTimeThruINCR = %False
  674.       END IF
  675.     ELSEIF Y < 92 AND Y > 64 THEN       'If A-Z
  676.       IF Y = 91 THEN
  677.         Y = 65
  678.       ELSE
  679.           NextTimeThruINCR = %False
  680.       END IF
  681.     ELSE                                'Otherwise Abort Function
  682.       Series$ = ""                      'not alfa/numeric
  683.       EXIT LOOP
  684.     END IF
  685.  
  686.     MID$(Series$,X,1) = CHR$(Y)
  687.     DECR X
  688.  
  689.   LOOP
  690.  
  691.   INCRSeries$ = Series$
  692.  
  693.  END FUNCTION
  694.  
  695. FUNCTION NameOfDay$(BYVAL DateCheck$)
  696.  
  697.   ' Returns the name of the day of the week
  698.   ' No modifications are made to DateCheck$
  699.   ' This function is based on The Zeller Congruence
  700.  
  701.   ' Requires DateCheck$ to be in "YYYYMMDD" (Year,Month,Day) Format
  702.   ' Requires FUNCTION ValidDate
  703.  
  704.   LOCAL Day%, Month%, WeekDay&, Year%
  705.  
  706.   NameOfDay$ = ""
  707.  
  708.   IF NOT(ValidDate(DateCheck$)) THEN EXIT FUNCTION
  709.  
  710.   Month%    = VAL(MID$(DateCheck$,5,2))
  711.   Day%      = VAL(RIGHT$(DateCheck$,2))
  712.   Year%     = VAL(LEFT$(DateCheck$,4))
  713.  
  714.   IF Month% < 3 THEN
  715.     INCR Month%,12                      'Jan and Feb = months 13 and 14
  716.     DECR Year%                          'of the previous year!
  717.   END IF
  718.  
  719.   WeekDay& = (Day% + ((26 * (Month% + 1)) \ 10)) + ((125 * Year%) \ 100)
  720.   WeekDay& = (WeekDay& - (Year% \ 100) + (Year% \ 400)) MOD 7
  721.  
  722.   SELECT CASE WeekDay&
  723.     CASE 0
  724.       NameOfDay$ = "Sat"
  725.     CASE 1
  726.       NameOfDay$ = "Sun"
  727.     CASE 2
  728.       NameOfDay$ = "Mon"
  729.     CASE 3
  730.       NameOfDay$ = "Tue"
  731.     CASE 4
  732.       NameOfDay$ = "Wed"
  733.     CASE 5
  734.       NameOfDay$ = "Thu"
  735.     CASE 6
  736.       NameOfDay$ = "Fri"
  737.   END SELECT
  738.  
  739.  END FUNCTION
  740.  
  741. FUNCTION ODD(BYVAL Number)
  742.  
  743.   ' Returns True if odd number, False if not
  744.   ' No modifications are made to Number
  745.  
  746.   IF (Number / 2) - FIX(Number / 2) = 0 THEN
  747.     ODD = %False
  748.   ELSE
  749.     ODD = %True
  750.   END IF
  751.  
  752.  END FUNCTION
  753.  
  754. FUNCTION ShiftedKeys
  755.  
  756.   ' Returns True if Shift, Control or Alternate
  757.   ' keys are held down
  758.   ' ShiftKey, CtrlKey and AltKey variables are
  759.   ' set to True or False accordingly
  760.  
  761.   SHARED ShiftKey, CtrlKey, AltKey
  762.  
  763.   REG 1, &H0200
  764.   CALL INTERRUPT &H16
  765.  
  766.   IF (REG(1) AND &H3)  > 0 THEN
  767.     ShiftKey = %True
  768.   ELSE
  769.     ShiftKey = %False
  770.   END IF
  771.  
  772.   IF (REG(1) AND &H4)  > 0 THEN
  773.     CtrlKey = %True
  774.   ELSE
  775.     CtrlKey = %False
  776.   END IF
  777.   
  778.   IF (REG(1) AND &H8)  > 0 THEN
  779.     AltKey = %True
  780.   ELSE
  781.     AltKey = %False
  782.   END IF
  783.  
  784.   IF (ShiftKey OR CtrlKey OR AltKey) THEN
  785.     ShiftedKeys = %True
  786.   ELSE
  787.     ShiftedKeys = %False
  788.   END IF
  789.   
  790.  END FUNCTION
  791.  
  792. FUNCTION TodaysDate$
  793.  
  794.   ' Returns System Date in the "YYYYMMDD" (Year,Month,Day) Format
  795.  
  796.   TodaysDate$ = RIGHT$(DATE$,4) + LEFT$(DATE$,2) + MID$(DATE$,4,2)
  797.  
  798.  END FUNCTION
  799.  
  800. FUNCTION TRIM$(BYVAL TheString$)
  801.  
  802.   ' Trims off leading and trailing spaces from a string
  803.   ' No modifications are made to TheString$
  804.  
  805.   ' Example A$ = TRIM$("  Test  ")  Sets A$ equal to "Test"
  806.  
  807.   TRIM$ = LTRIM$(RTRIM$(TheString$))
  808.  
  809.  END FUNCTION
  810.  
  811. FUNCTION ValidDate(BYVAL DateCheck$)
  812.  
  813.   ' Returns True if Valid Date, False if not
  814.   ' No modifications are made to DateCheck$
  815.   ' This function is aware of leap years
  816.  
  817.   ' Requires DateCheck$ to be in "YYYYMMDD" (Year,Month,Day) Format
  818.   ' Requires FUNCTION DaysInMonth
  819.  
  820.   ValidDate = %False
  821.  
  822.   IF LEN(DateCheck$) <> 8 THEN EXIT FUNCTION                'Check full date
  823.  
  824.   IF VAL(LEFT$(DateCheck$,4)) > 999 AND    _                'If valid Year
  825.      VAL(LEFT$(DateCheck$,4)) < 10000 THEN
  826.  
  827.     IF VAL(MID$(DateCheck$,5,2)) > 0 AND   _                'If valid Month
  828.        VAL(MID$(DateCheck$,5,2)) < 13 THEN
  829.  
  830.       IF VAL(RIGHT$(DateCheck$,2)) > 0 AND _                'If valid Day
  831.            VAL(RIGHT$(DateCheck$,2)) <=        _            'for the above
  832.            DaysInMonth(VAL(LEFT$(DateCheck$,4)),   _        'month & year
  833.            VAL(MID$(DateCheck$,5,2))) THEN
  834.  
  835.         ValidDate = %True
  836.  
  837.       END IF
  838.     END IF
  839.   END IF
  840.  
  841.  END FUNCTION
  842.  
  843.