home *** CD-ROM | disk | FTP | other *** search
/ World of Shareware - Software Farm 2 / wosw_2.zip / wosw_2 / QBAS / PRINTROM.ZIP / PRINTROM.BAS < prev    next >
BASIC Source File  |  1991-09-03  |  33KB  |  664 lines

  1. TYPE RegTypeX
  2.      ax    AS INTEGER
  3.      bx    AS INTEGER
  4.      cx    AS INTEGER
  5.      dx    AS INTEGER
  6.      bp    AS INTEGER
  7.      si    AS INTEGER
  8.      di    AS INTEGER
  9.      flags AS INTEGER
  10.      ds    AS INTEGER
  11.      es    AS INTEGER
  12. END TYPE
  13.  
  14. DECLARE SUB InterruptX (intnum AS INTEGER, inreg AS RegTypeX, outreg AS RegTypeX)
  15.  
  16. ' $INCLUDE: 'printrom.bi'
  17.  
  18. DIM SHARED BitValue(15) AS INTEGER      'Create an array for bit values
  19.  
  20. DEFINT A-Z
  21. SUB PrintROMtable (a$, PR AS PrntROM) STATIC
  22. '****************************************************************************
  23. '*                          PrintROMtable Subroutine                        *
  24. '*                                                                          *
  25. '*    BY:           Larry Stone   1991                                      *
  26. '*    INSPIRED BY:  Code from PC Magazine posted in the Quik_BAS inter-     *
  27. '*                  national echo by Richard Randles.   1991                *
  28. '*    CONTRIBUTORS: Rob Smetana @ 914/201  1991 - provided "ItalicSlant"    *
  29. '*                             and language for extended character sets     *
  30. '*                             for CGA monitors in SCREEN 0 or 1.  Note     *
  31. '*                             that you can force the use of these          *
  32. '*                             high character sets using ReadHiAscFile      *
  33. '*                  Francois Roy - provided example code for "Elongate"     *
  34. '*                  Mike Kelly - provide code to write 8, 14, 16, 28 & 32   *
  35. '*                             pixel height characters.  His code also      *
  36. '*                             enables printing high ASCII set (>= 128)     *
  37. '*                             (except for CGA using 8 "Height" chars.)     *
  38. '*                  Bill Beasley - provided code for "Tall" which doubles   *
  39. '*                             pixel height, effectively providing          *
  40. '*                             extended character heights of 16, 28,        *
  41. '*                             32, 56, and 64 pixels.                       *
  42. '*                  Larry Stone  provided all of the rest of this code.     *
  43. '*                                                                          *
  44. '*                         Passed as argument variable:                     *
  45. '*                         ----------------------------                     *
  46. '*   a$             String of characters to print.                          *
  47. '*   PR             106 byte TYPE variable PrntROM, DIMmed as PR,           *
  48. '*                  containing the following elements:                      *
  49. '*                                                                          *
  50. '*             Passed as TYPE variable (defined in 'printrom.bi'):          *
  51. '*             ---------------------------------------------------          *
  52. '*                                                                          *
  53. '*   PR.xAxis      Starting column, in pixel points.                        *
  54. '*   PR.yAxis      Starting row in pixel points.                            *
  55. '*   PR.StepX      Count from 1st dot of character, right/left # pixels.    *
  56. '*                 Example: 8 = 8 right; -8 = 8 left (prints reverse).      *
  57. '*   PR.StepY      Count from 1st dot of character, down/up # pixels.       *
  58. '*                 Example: 1 = 1 down; -8 = 8 up (prints bottom - up).     *
  59. '*   PR.CharClr    The color to make each character.                        *
  60. '*   PR.BGclr      Non-zero values determine the background color           *
  61. '*                 for the string.  Background is neutral when BGclr is     *
  62. '*                 set to 0.  Set BGclr = 256 for black background.         *
  63. '*   PR.Shadow     True or false Boolian variable.                          *
  64. '*   PR.ItalicSlant     Set to zero or 7 or -7 for no slant.  Positives     *
  65. '*                 create a forward slant (right-handed).  Negative         *
  66. '*                 numbers for backward slant (left-handed).  Maximum       *
  67. '*                 slant is 1 or -1.  An attractive italic is 2 or -2.      *
  68. '*   PR.Inverted   True or false Boolean variable - turns characters        *
  69. '*                 upside down.                                             *
  70. '*   PR.Backwards  True or false Boolean variable - makes individual        *
  71. '*                 characters of a string print backwards.                  *
  72. '*   PR.Underline  True of false Boolean variable.                          *
  73. '*   PR.Elongate   Zero for normal size character, set to 1 for bold        *
  74. '*                 characters, set to 2 = double wide (truly fat).          *
  75. '*   PR.Stencil    True or false Boolean variable - makes stencil           *
  76. '*   PR.Height     An integer specified as 8, 14, 16, 28, or 32.  This      *
  77. '*                 the height, in pixels, of the character printed.         *
  78. '*                 NOTE: CGA can only print 8.  Use PR.Tall for 16.         *
  79. '*                 NOTE: EGA cannot do 16 or 32.  PrintROMtable will force  *
  80. '*                       16 to 14 and will force 32 to 28.  EGA can access  *
  81. '*                       16 by using 8 with Tall.                           *
  82. '*   PR.Tall       Boolean variable that doubles pixel height effec-        *
  83. '*                 providing pixels heights of 16, 28, 32, 56, and 64.      *
  84. '*                 NOTE: CGA can only access 16.                            *
  85. '*                 NOTE: EGA cannot access 32 or 64.                        *
  86. '*   PR.StrikeThrough   True or false Boolean variable - a dash is          *
  87. '*                 placed in the middle of each character.                  *
  88. '*   PR.Condensed  True or False Boolean variable - forces 8 scan line      *
  89. '*                 character into four scan lines.  Not very readable but   *
  90. '*                 can be used for superscripts/subscripts or that fine,    *
  91. '*                 legal (and unreadable) print in contracts agreements.    *
  92. '*                 Also useful for printer preview modes.                   *
  93. '*   PR.ForceAddress    True or False Boolean variable to force ROM charac- *
  94. '*                 ter shape table address to &HFFA6.  Set this to true     *
  95. '*                 to force systems to this memory segment.                 *
  96. '*   PR.ScreenMode Integer variable that equals the SCREEN mode used.       *
  97. '*                 YOU MUST SUPPLY THIS VARIABLE if you intend to use       *
  98. '*                 screen modes above CGA ("0" defaults to CGA font sizes). *
  99. '*                 At the top of your code, do something like:              *
  100. '*                                PR.ScreenMode = 9                         *
  101. '*                                SCREEN PR.ScreenMode                      *
  102. '*   PR.DefaultFile     Integer variable that defines which font file the   *
  103. '*                 program defaults to (for access to chars > 127).         *
  104. '*   PR.DiskFontLoc     String defining path to the disk font files.  If    *
  105. '*                 the font files are not in your program's default path,   *
  106. '*                 then this variable need to be addressed before your      *
  107. '*                 program makes it's first call to PrintROMtable.          *
  108. '*   PR.ReadHiAscFile   Integer variable to force characters > 127 to be    *
  109. '*                 read from a font file.  Use this feature with any type   *
  110. '*                 monitor (CGA/EGA/VGA) to force any special characters    *
  111. '*                 from font file to memory, i.e., a true copyright symbol  *
  112. '*                 (US file, ASCII = 184), trade mark (US, ASCII = 169).    *
  113. '*                 You can also build your own font files then load your    *
  114. '*                 special built fonts as the upper 128 characters.         *
  115. '*                                                                          *
  116. '*                 PrintROMtable DOES NOT CHECK FOR EXISTENCE OF:           *
  117. '*                                                                          *
  118. '*                     ReadHiAscFile = 1:                                   *
  119. '*                       File = rsCODES.INT - International (we want)       *
  120. '*                     ReadHiAscFile = 2:                                   *
  121. '*                       File = rsCODES.US - United States                  *
  122. '*                     ReadHiAscFile = 3:                                   *
  123. '*                       File = rsCODES.POR - Portuguese                    *
  124. '*                     ReadHiAscFile = 4:                                   *
  125. '*                       File = rsCODES.CAN - French-Canadian               *
  126. '*                                                                          *
  127. '*                 It is your responsibility to have your code check for    *
  128. '*                 the appropriate file above unless your program does not  *
  129. '*                 operate on CGA systems and/or, if your program does      *
  130. '*                 not access the upper 128 ASCII characters and/or, your   *
  131. '*                 program doesn't set ReadHiAscFile.                       *
  132. '*                                                                          *
  133. '*                     ReadHiAscFile = -1                                   *
  134. '*                       Resets this subprogram to use ROM BIOS table for   *
  135. '*                       characters above ASCII 127.  Usage:                *
  136. '*                       PR.ReadHiAscFile = -1: PrintROMtable a$, PR        *
  137. '*                                                                          *
  138. '*  OUT:  1)  String of characters printed to the graphics screen.          *
  139. '*        2)  Location and slant of displayed string are pixel based.       *
  140. '*        3)  Strings can be printed normal, reverse, top to bottom and     *
  141. '*            upside down.                                                  *
  142. '*        4)  Strings can have both foreground and background colors or     *
  143. '*            possess a neutral, non-destructive background.                *
  144. '*        5)  "CPI" can be adjusted along horizontal or vertical planes     *
  145. '*            with StepX and StepY variables (ie, StepX = 7 would be a      *
  146. '*            condenced font, StepX = 8 a normal font, etc).                *
  147. '*        6)  Characters can be printed with a shadow.                      *
  148. '*        7)  Characters can be printed with "right-hand" or "left-hand"    *
  149. '*            italicized slant.                                             *
  150. '*        8)  Characters can be inverted for mirror images along the        *
  151. '*            verticle plane (like a reflection on a lake).                 *
  152. '*        9)  Characters can be printed backwards for mirror images on      *
  153. '*            horizontal plane (horizontal mirror images should have        *
  154. '*            StepX set to a negative value for a "true mirror image").     *
  155. '*        10) Characters can be elongate by 2 or 4 times normal length.     *
  156. '*        11) Characters can be displayed as "stencil" characters.          *
  157. '*        12) Characters can be displayed with a strike through mark.       *
  158. '*        13) Characters can be 8, 14, 16, 28, or 32 pixels high.           *
  159. '*        14) Characters can be printed "Tall" effectively producing hights *
  160. '*            of 16, 28, 32, 56, or 64 pixels high.                         *
  161. '*        15) Characters can be printed "Condensed" for use as super or sub *
  162. '*            script type or printer preview modes.                         *
  163. '*        16) The high ASCII character set (128 through 254) can be altered *
  164. '*            from 1 of four, pre-defined files (1024 bytes each).          *
  165. '*                                                                          *
  166. '****************************************************************************
  167.  
  168.     IF NOT BitsCreated THEN
  169.         BitValue(False) = 1              'Set bit zero
  170.         FOR N% = 1 TO 14                 'Set bits 1 through 14
  171.             BitValue(N%) = BitValue(N% - 1) * 2
  172.         NEXT
  173.         BitValue(15) = -32768            'Set bit 15
  174.  
  175.         DIM Mask%(15), TallMask%(64)     'Create arrays for scan lines
  176.         BitsCreated = True               'Flag that bits are created
  177.     END IF
  178.  
  179.     DIM reg AS RegTypeX             'Establish the register variables
  180.     extX% = PR.StepX: extY% = PR.StepY    'Don't destroy StepX or StepY
  181.     dub% = False                    'Reset dub% variable
  182.  
  183.     '**** Can't accept a zero
  184.     IF PR.ItalicSlant = False THEN PR.ItalicSlant = 7
  185.  
  186.     '**** If PR.ScreenMode < 7 then PR.Height is automatically set to 8
  187.     '     and ROM address used is &HFFA6.
  188.     IF PR.ScreenMode < 7 THEN PR.Height = 8: HiAscii = True
  189.  
  190.     '**** If no default file established then set default to 1 (international)
  191.     IF PR.DefaultFile = False THEN PR.DefaultFile = 1
  192.  
  193.     '**** If instructed to read high ASCII or, if HiAscii set but we haven't
  194.     '     acknowledged HiAsciRead (CGA will cause this condition when CGA
  195.     '     system first calls this routine) then read the appropriate file.
  196.     IF PR.ReadHiAscFile OR (HiAscii AND NOT HiAsciiRead) THEN
  197.         HiAscii = True                      'Set flag
  198.  
  199.         '**** If ReadHiAscFile not established, assign it to DefaultFile
  200.         IF PR.ReadHiAscFile = False THEN PR.ReadHiAscFile = PR.DefaultFile
  201.  
  202.         '**** If DiskFontLoc hasn't been assigned then QB will have
  203.         '     initialized the string with character zeros.  Clear zeros!
  204.         N = INSTR(PR.DiskFontLoc, CHR$(0))
  205.         IF N THEN MID$(PR.DiskFontLoc, N) = SPACE$(LEN(PR.DiskFontLoc) - N + 1)
  206.         
  207.         '**** If disk fonts have an assigned path...
  208.         Temp$ = RTRIM$(PR.DiskFontLoc)
  209.             
  210.         IF LEN(Temp$) THEN
  211.             IF NOT RIGHT$(Temp$, 1) = "\" THEN Temp$ = Temp$ + "\"
  212.         END IF
  213.  
  214.         '**** You could create your own 1024 byte font files and add them here
  215.         SELECT CASE PR.ReadHiAscFile    'Select a font style to use
  216.             CASE -1                         'No special chars - use ROM table
  217.                 HiAsciiRead = False: HiAscii = False
  218.                 PR.ReadHiAscFile = False: EXIT SUB
  219.             CASE 1                          'International (our default)
  220.                 FontFile$ = Temp$ + "rsCODES.INT"
  221.             CASE 2                          'United States
  222.                 FontFile$ = Temp$ + "rsCODES.US"
  223.             CASE 3                          'Portuguese
  224.                 FontFile$ = Temp$ + "rsCODES.POR"
  225.             CASE 4                          'French-Canadian
  226.                 FontFile$ = Temp$ + "rsCODES.CAN"
  227.             CASE ELSE
  228.                 PRINT "Error - Font File Not Defined!": END
  229.         END SELECT
  230.  
  231.         PR.ReadHiAscFile = False               'Clear flag
  232.  
  233.         j% = FREEFILE                          'Get a handle
  234.         OPEN FontFile$ FOR BINARY AS #j%       'Open with this handle
  235.         font$ = SPACE$(1024) '...Our fonts need just 1024 bytes (128 * 8).
  236.         GET #1, , font$: CLOSE #j%             'Close file with handle j%
  237.  
  238.         HiAsciiRead = True                     'Flag we've read 'em
  239.     END IF
  240.  
  241.     '**** EGA screens cannot access 16 pixel high characters so force 14
  242.     IF PR.ScreenMode < 12 AND PR.ScreenMode > 2 THEN
  243.         IF PR.Height = 16 THEN PR.Height = 14
  244.         IF PR.Height = 32 THEN PR.Height = 28
  245.     END IF
  246.  
  247.     '**** Figure out where the font is
  248.     SELECT CASE PR.Height
  249.         CASE 8               ' 8x8 font
  250.             reg.bx = &H300
  251.         CASE 14, 28          ' 8x14 font or 8x14 font double high
  252.             reg.bx = &H200
  253.         CASE 16, 32          ' 8x16 font or 8x16 font double high
  254.             reg.bx = &H600
  255.         CASE ELSE
  256.             CLS : PRINT "Invalid Character Size": END
  257.     END SELECT
  258.     IF PR.Height > 16 THEN dub% = True
  259.  
  260.     IF dub% THEN
  261.         Two% = 2
  262.         one% = 1
  263.         h% = PR.Height \ Two%
  264.     ELSE
  265.         h% = PR.Height
  266.         Two% = 1
  267.         one% = False
  268.     END IF
  269.     
  270.     ' **** Get ROM segment for character shape tables
  271.     reg.ax = &H1130
  272.     InterruptX &H10, reg, reg
  273.     ofst& = reg.bp
  274.     sgmt& = reg.es
  275.  
  276.     IF PR.ForceAddress OR PR.ScreenMode < 7 THEN sgmt& = &HFFA6
  277.     
  278.     DEF SEG = sgmt&             'ROM segment for character shape tables
  279.     FOR i% = 1 TO LEN(a$)
  280.         IF PR.BGclr THEN                    'Color background
  281.             '**** Backgrounds equal to 256 are really color zero.
  282.             IF PR.BGclr = 256 THEN BG% = False ELSE BG% = PR.BGclr
  283.  
  284.             '**** Prevent coloring background beyond range of string.
  285.             IF i% = LEN(a$) THEN
  286.                 IF PR.Elongate = 1 THEN
  287.                     extX% = extX% \ 2 + 2
  288.                 ELSEIF NOT PR.Elongate = 2 THEN
  289.                     extX% = False
  290.                 END IF
  291.                 extY% = False
  292.             END IF
  293.             
  294.             '**** Adjust box start positions for reverse writing.
  295.             IF extY% < False THEN stpY% = 7 ELSE stpY% = False
  296.             IF extX% < False THEN stpX% = 7 ELSE stpX% = False
  297.             
  298.             '**** Set a few more variables to properly manipulate background
  299.             '     border areas, as well as, adjust for elongated characters
  300.             adjust% = False
  301.             N% = False
  302.  
  303.             Tx% = 1
  304.             IF dub% THEN
  305.                 adjust% = -4
  306.             ELSEIF PR.Height > 8 THEN
  307.                 Tx% = 2: adjust% = True: N% = h% \ 2
  308.             ELSEIF PR.Height = 8 AND PR.Tall AND PR.StepY < False AND PR.Elongate = False THEN
  309.                 Tx% = 2
  310.             END IF
  311.  
  312.             seven% = 7
  313.             IF PR.Tall THEN Tx% = Tx% * 2
  314.             T% = Two% * Tx%
  315.  
  316.             IF PR.Condensed THEN
  317.                 T% = 1
  318.                 IF PR.Height = 8 THEN seven% = 4        'Gets pretty tiny
  319.                 IF PR.Tall AND PR.Height > 8 THEN T% = T% * 2
  320.             END IF
  321.  
  322.             IF PR.Elongate <> 2 THEN
  323.                 Twoo% = False
  324.                 Ttoo% = False
  325.                 less2% = False
  326.             ELSE
  327.                 Twoo% = 2
  328.                 less2% = Twoo%
  329.                 IF StepY% > True THEN Ttoo% = False ELSE Ttoo% = Ttoo%
  330.             END IF
  331.  
  332.             IF PR.xAxis > True THEN ySlant = extY% ELSE ySlant = False
  333.  
  334.             '**** Box and paint a background for the character.
  335.             '     Drawing two boxes handles BG for any direction printed.
  336.             LINE (PR.xAxis + extX% + Twoo%, PR.yAxis + ySlant)-(PR.xAxis + stpX% + Ttoo%, PR.yAxis + N% + stpY% * Two% * Two%), BG%, BF
  337.             LINE (PR.xAxis + stpX% + Twoo% - less2%, PR.yAxis + stpY%)-(PR.xAxis + 7 + extX%, PR.yAxis + seven% * Two% * T% + extY% - Two%), BG%, BF
  338.         END IF
  339.  
  340.         '**** Get how far the character's address is within the table
  341.         addr% = ofst& + ASC(MID$(a$, i%, 1)) * h%
  342.         IF PR.ForceAddress OR PR.ScreenMode < 7 THEN addr% = 8 * ASC(MID$(a$, i%)) + 14
  343.  
  344.         z% = h% - 1                         'Establish last scan line to use
  345.         FOR j% = False TO z%
  346.             MidA = ASC(MID$(a$, i%, 1))     'Get ASCII value of char
  347.             IF HiAscii AND MidA > 128 THEN
  348.                 IF j% < 8 THEN
  349.                     '**** Get Font$ scan line as long integer
  350.                     Msk& = ASC(MID$(font$, (MidA - 128) * 8 + j% + 1, 1)) * 256&
  351.                     '**** Set into range of INTEGER numbers
  352.                     Mask% = Msk& + 65536 * (Msk& > 32767)
  353.                 ELSE
  354.                     Mask = False                'Set mask as zero
  355.                 END IF
  356.                 Mask(j%) = Mask%                'Set into the mask array
  357.             ELSE
  358.                 Mask(j%) = PEEK(addr% + j%)     'Load scan lines from ROM BIOS
  359.             END IF
  360.         NEXT
  361.  
  362.         IF PR.Condensed THEN
  363.             '**** Set Condensed fonts
  364.             k% = 0
  365.             FOR j% = False TO z% STEP 2
  366.                 Mask(k%) = Mask(j% + 1)
  367.                 k% = k% + 1
  368.             NEXT
  369.             
  370.             FOR j% = (z% + 1) \ 2 TO z%         'Clear rest of Mask array.
  371.                 Mask(j%) = False
  372.             NEXT
  373.         END IF
  374.         
  375.         IF PR.Tall THEN
  376.             '**** Load TallMask
  377.             FOR j% = False TO z% * 2 STEP 2
  378.                 TallMask(j%) = Mask(j% \ 2)
  379.                 TallMask(j% + 1) = Mask(j% \ 2)
  380.             NEXT
  381.             z% = z% * 2                     'Double scan lines for Tall letters
  382.         END IF
  383.  
  384.         k% = z%
  385.         FOR j% = False TO z%
  386.             '**** Establish either j% or k% as our scan line counter.
  387.             '     Use k%=j% for counting up and k%=k% for countin down
  388.             IF NOT PR.Inverted THEN k% = j%  'If not mirror then j% is scan line
  389.  
  390.             '**** Use either the Tall mask or normal mask
  391.             IF NOT PR.Tall THEN Mask% = Mask%(k%) ELSE Mask% = TallMask(k%)
  392.             
  393.             '**** Shift bits 8 places if not high ASCII from font file
  394.             IF NOT (HiAscii AND MidA > 128) THEN Mask% = Mask% * 128
  395.             
  396.             IF PR.Backwards THEN
  397.                 N1% = 15
  398.                 FOR N% = 8 TO 11
  399.                     t1% = TestBit%(Mask%, N%)   'Test low bit
  400.                     t2% = TestBit%(Mask%, N1%)  'Test high bit
  401.                     SetBit Mask%, N1%, t1%      'Set high bit to low value
  402.                     SetBit Mask%, N%, t2%       'Set low bit to high value
  403.                     N1% = N1% - 1
  404.                 NEXT
  405.             END IF
  406.  
  407.             '**** If "Stencil" then turn off middle bit of each scan line.
  408.             IF PR.Stencil AND PR.Elongate < 2 THEN SetBit Mask%, 11, False
  409.  
  410.             '**** Calculate the amount of slant for italic characters
  411.             Islant% = j% \ PR.ItalicSlant
  412.  
  413.             '**** Calculate variables needed for a "left-handed" italic
  414.             IF PR.ItalicSlant < False THEN
  415.                 Islant% = -Islant%          'Make number positive
  416.                 Mask% = Mask% \ BitValue(Islant%)      'Adjust the mask
  417.                 Islant% = 2                 'Neutralize slant variable
  418.                 Msk& = Mask% * 2&           'Shift left 1 bit
  419.                 Mask% = Msk& + 65536 * (Msk& > 32767)  'Put into INTEGER range
  420.             END IF
  421.  
  422.             '**** If "UnderLine" or "StrikeThrough" then turn on all bits in
  423.             '     the appropriate row of bits.
  424.             IF PR.UnderLine THEN
  425.                 IF PR.Condensed THEN
  426.                     IF NOT PR.Tall AND ((h% = 8 AND k% = 5) OR (h% = 16 AND k% = 7) OR (h% = 14 AND k% = 6)) THEN
  427.                         Mask% = True
  428.                     ELSEIF PR.Tall AND ((h% = 8 AND k% = 5) OR (h% = 14 AND k% = 11) OR (h% = 16 AND k% = 12)) THEN
  429.                         Mask% = True
  430.                     END IF
  431.                 ELSE
  432.                     IF NOT PR.Tall AND ((h% = 8 AND k% = 6) OR (h% = 16 AND k% = 13) OR (h% = 14 AND k% = 11)) THEN
  433.                         Mask% = True
  434.                     ELSEIF PR.Tall AND ((h% = 8 AND k% = 13) OR (h% = 14 AND k% = 22) OR (h% = 16 AND k% = 24)) THEN
  435.                         Mask% = True
  436.                     END IF
  437.                 END IF
  438.             END IF
  439.             
  440.             IF PR.StrikeThrough THEN
  441.                 IF PR.Condensed THEN
  442.                     IF NOT PR.Tall AND ((h% = 8 AND k% = 2) OR (h% = 16 AND k% = 4) OR (h% = 14 AND k% = 3)) THEN
  443.                         Mask% = True
  444.                     ELSEIF PR.Tall AND ((h% = 8 AND k% = 3) OR (h% = 14 AND k% = 7) OR (h% = 16 AND k% = 7)) THEN
  445.                         Mask% = True
  446.                     END IF
  447.                 ELSE
  448.                     IF NOT PR.Tall AND ((h% = 8 AND k% = 4) OR (h% = 16 AND k% = 7) OR (h% = 14 AND k% = 7)) THEN
  449.                         Mask% = True
  450.                     ELSEIF (h% = 8 AND k% = 8) OR (h% = 14 AND k% = 14) OR (h% = 16 AND k% = 16) THEN
  451.                         Mask% = True
  452.                     END IF
  453.                 END IF
  454.             END IF
  455.  
  456.             L% = False: R% = L%: L1% = L%: R1% = L%  'Reset Elongate variables
  457.  
  458.             IF Mask% THEN               'If Mask isn't cleared then print it
  459.                 '**** If we've used Islant then clean it up
  460.                 IF Islant% > 1 AND PR.ItalicSlant = 7 THEN Islant% = 1
  461.  
  462.                 GOSUB CalcXYparams
  463.                 
  464.                 '**** If shadow then displace line by 2 pixels and draw with
  465.                 '     black style mask
  466.                 IF PR.Elongate < 1 AND NOT dub% THEN
  467.                     '**** Below is Boolean logic and is faster than:
  468.                     '     IF (x7%) - (XlessI%) < 8 THEN N% = 7 ELSE N% = 6
  469.                     N% = 6 - ((x7%) - (XlessI%) < 8)
  470.  
  471.                     IF PR.Shadow THEN LINE (PR.xAxis + N% + 2, YandJlessAd% + 2)-(XlessI% + 2, YandJlessAd% + 2), False, , Mask%
  472.  
  473.                     '**** Draw the masked line with the assigned color attribute
  474.                     LINE (PR.xAxis + N%, YandJlessAd%)-(XlessI%, YandJlessAd%), PR.CharClr, , Mask%
  475.                 ELSEIF PR.Elongate THEN
  476.                     GOSUB SetElongated
  477.                 ELSEIF dub% THEN
  478.                     '**** Prevent an inappropriate adjustment
  479.                     IF PR.Inverted AND Islant% = False AND PR.ItalicSlant = 7 AND PR.Height = 32 THEN Islant% = 1
  480.  
  481.                     GOSUB CalcXYparams
  482.                     
  483.                     IF PR.Shadow% THEN
  484.                         LINE (PR.xAxis + 9, YtwoJ% + Two%)-(XlessI% + Two%, YtwoJ% + Two%), False, , Mask%
  485.                         LINE (PR.xAxis + 10, YtwoJ1% + Two%)-(XlessI% + Two%, YtwoJ1% + Two%), False, , Mask%
  486.                     END IF
  487.                     LINE (x7%, YtwoJ%)-(XlessI%, YtwoJ%), PR.CharClr, , Mask%
  488.                     LINE (PR.xAxis + 8, YtwoJ1%)-(XlessI%, YtwoJ1%), PR.CharClr, , Mask%
  489.                 END IF
  490.             END IF
  491.  
  492.             '**** Adjust location of the x axis per certain variables
  493.             
  494.             IF HiAscii AND ASC(MID$(a$, i%, 1)) > 128 AND NOT PR.Tall THEN
  495.                 IF k% = 6 THEN PR.xAxis = PR.xAxis + 1
  496.             ELSEIF h% = 8 AND PR.Tall AND Islant% = False AND NOT PR.Inverted THEN
  497.                 IF k% = h% \ 2 + 2 AND (PR.StepY = False OR PR.Elongate) THEN PR.xAxis = PR.xAxis + 1
  498.             ELSEIF h% > 8 AND Islant% = False THEN
  499.                 IF h% = 14 AND k% = h% \ 2 - 1 AND PR.StepY = False THEN
  500.                     PR.xAxis = PR.xAxis + 1
  501.                 ELSEIF h% = 16 AND k% = h% \ 2 - 2 AND PR.StepY = False THEN
  502.                     PR.xAxis = PR.xAxis + 1
  503.                 END IF
  504.             ELSEIF h% = 8 AND PR.Tall AND PR.ItalicSlant = 7 AND PR.Inverted THEN
  505.                 IF k% = h% THEN PR.xAxis = PR.xAxis + 1
  506.             END IF
  507.             
  508.             IF PR.Inverted THEN k% = k% - 1   'If "Inverted" then decrement k%
  509.         NEXT
  510.  
  511.         '**** INC xAxis and yAxis by values extX% and extY%
  512.         PR.xAxis = PR.xAxis + extX%
  513.         PR.yAxis = PR.yAxis + extY%
  514.     NEXT
  515.     DEF SEG                                'Return to BASIC DGROUP
  516.  
  517.     '**** Adjust the ending xAxis pixel location to correspond to the
  518.     '     correct location associated with the next letter that might
  519.     '     be displayed along the same axis.
  520.  
  521.     IF h% > 8 THEN PR.xAxis = PR.xAxis + h% \ 4 - 1
  522.     IF PR.Elongate = 1 THEN
  523.         PR.xAxis = PR.xAxis + PR.StepX \ 4 + 1
  524.     ELSEIF PR.Elongate = 2 THEN
  525.         PR.xAxis = PR.xAxis + PR.StepX \ 8
  526.     ELSEIF (PR.ItalicSlant = 7 OR PR.ItalicSlant = -7) THEN
  527.         PR.xAxis = PR.xAxis + PR.StepX - 1
  528.     ELSEIF PR.StepY THEN
  529.         PR.xAxis = PR.xAxis + PR.StepX + 1
  530.     END IF
  531.  
  532.     EXIT SUB
  533.  
  534. SetElongated:
  535.     StepFactor% = PR.Elongate * 2
  536.     N1% = 15
  537.     FOR N% = 15 TO StepFactor% + 10 STEP -1   'Left side of left half
  538.         BitOn% = TestBit%(Mask%, N%)
  539.         IF BitOn% THEN
  540.             SetBit L%, N1%, BitOn%
  541.             SetBit L%, N1% - 1, BitOn%
  542.             IF StepFactor% > 2 THEN
  543.                 SetBit L%, N1% - 2, BitOn%
  544.                 SetBit L%, N1% - 3, BitOn%
  545.             END IF
  546.         END IF
  547.         N1% = N1% - StepFactor%
  548.     NEXT
  549.  
  550.     N1% = 15: t1% = N%
  551.     IF StepFactor% = 2 THEN t2% = 7 ELSE t2% = 12
  552.     FOR N% = t1% TO t2% STEP -1            'Right side of left half
  553.         BitOn% = TestBit%(Mask%, N%)
  554.         IF BitOn% THEN
  555.             SetBit R%, N1%, BitOn%
  556.             SetBit R%, N1% - 1, BitOn%
  557.             IF StepFactor% > 2 THEN
  558.                 IF PR.Stencil AND N% = t2% THEN BitOn% = False ELSE BitOn% = True
  559.                 SetBit R%, N1% - 2, BitOn%
  560.                 SetBit R%, N1% - 3, BitOn%
  561.             END IF
  562.         END IF
  563.         IF PR.Stencil AND PR.Elongate = 1 AND N% = t2% THEN SetBit R%, N1% + 6, False
  564.         N1% = N1% - StepFactor%
  565.     NEXT
  566.  
  567.     IF StepFactor% > 2 THEN
  568.         N1% = 8
  569.         FOR N% = 11 TO 10 STEP -1          'Left side of right half
  570.             BitOn% = TestBit%(Mask%, N%)
  571.             IF BitOn% THEN
  572.                 SetBit L1%, N1%, BitOn%
  573.                 SetBit L1%, N1% - 1, BitOn%
  574.                 SetBit L1%, N1% - 2, BitOn%
  575.                 SetBit L1%, N1% - 3, BitOn%
  576.             END IF
  577.             IF PR.Stencil AND N% = 11 THEN SetBit L1%, N1%, False
  578.             N1% = N1% - 4
  579.         NEXT
  580.  
  581.         Bit9on = TestBit%(Mask%, 8)        'Left side of R1
  582.         Bit8on = TestBit%(Mask%, 9)        'Right side of R1
  583.  
  584.         IF Bit9on THEN                     'Gets tricky - doesn't it
  585.             N1% = 4
  586.             SetBit R1%, N1%, Bit9on
  587.             SetBit R1%, N1% - 1, Bit9on
  588.             SetBit R1%, N1% - 2, Bit9on
  589.             SetBit R1%, N1% - 3, Bit9on
  590.         END IF
  591.         IF Bit8on THEN
  592.             N1% = 7
  593.             SetBit R1%, N1%, Bit8on
  594.             SetBit R1%, N1% - 1, Bit8on
  595.             SetBit R1%, N1% - 2, Bit8on
  596.         END IF
  597.     END IF
  598.  
  599.     '**** Allow underline/StrikeThrough to be long enough to form a
  600.     '     continuous line (assuming spacing is within reason).
  601.     IF Mask% = True THEN L% = True: L1% = True: R% = True: R1% = True
  602.     IF Mask% = True THEN ExtR = 2 ELSE ExtR = False
  603.  
  604.     IF PR.Shadow THEN
  605.         LINE (PR.xAxis + 9, YtwoJ2%)-(XlessI% + 2, YtwoJ2%), False, , L%
  606.         LINE (PR.xAxis + 17, YtwoJ2%)-(XlessI% + 9, YtwoJ2%), False, , R%
  607.         LINE (PR.xAxis + 10, YtwoJ12%)-(XlessI% + 2, YtwoJ12%), False, , L%
  608.         LINE (PR.xAxis + 18, YtwoJ12%)-(XlessI% + 9, YtwoJ12%), False, , R%
  609.  
  610.         IF StepFactor% > 2 THEN
  611.             LINE (PR.xAxis + 25, YtwoJ2%)-(XlessI% + 9, YtwoJ2%), False, , L1%
  612.             LINE (PR.xAxis + 33, YtwoJ2%)-(XlessI% + 16, YtwoJ2%), False, , R1%
  613.             LINE (PR.xAxis + 26, YtwoJ12%)-(XlessI% + 9, YtwoJ12%), False, , L1%
  614.             LINE (PR.xAxis + 34, YtwoJ12%)-(XlessI% + 16, YtwoJ12%), False, , R1%
  615.         END IF
  616.     END IF
  617.  
  618.     '**** Draw the masked lines with the assigned color attribute
  619.     LINE (x7%, YtwoJ%)-(XlessI%, YtwoJ%), PR.CharClr, , L%
  620.     LINE (PR.xAxis + 15, YtwoJ%)-(XlessI% + 7, YtwoJ%), PR.CharClr, , R%
  621.     LINE (PR.xAxis + 8, YtwoJ1%)-(XlessI%, YtwoJ1%), PR.CharClr, , L%
  622.     LINE (PR.xAxis + 16, YtwoJ1%)-(XlessI% + 7, YtwoJ1%), PR.CharClr, , R%
  623.     
  624.     IF StepFactor% > 2 THEN
  625.         LINE (PR.xAxis + 23, YtwoJ%)-(XlessI% + 7, YtwoJ%), PR.CharClr, , L1%
  626.         LINE (PR.xAxis + 31, YtwoJ%)-(XlessI% + 14 + ExtR, YtwoJ%), PR.CharClr, , R1%
  627.         LINE (PR.xAxis + 24, YtwoJ1%)-(XlessI% + 7, YtwoJ1%), PR.CharClr, , L1%
  628.         LINE (PR.xAxis + 32, YtwoJ1%)-(XlessI% + 14 + ExtR, YtwoJ1%), PR.CharClr, , R1%
  629.     END IF
  630. RETURN
  631.  
  632. CalcXYparams:
  633.     XlessI% = PR.xAxis - Islant%           'Define PR.xAxis - Islant%
  634.     YtwoJ% = PR.yAxis + j% * Two%          'Define PR.yAxis + Two% * j%
  635.     YandJlessAd% = PR.yAxis + j% - adjust% 'Define PR.yAxis + j% - adjust%
  636.     x7% = PR.xAxis + 7                     'Define PR.xAxis + 7
  637.     YtwoJ1% = YtwoJ% + one%                'Define YtwoJ% + one%
  638.     YtwoJ2% = YtwoJ% + 2                   'Define YtwoJ% + 2
  639.     YtwoJ12% = YtwoJ1% + 2                 'Define YtwoJ1% + 2
  640. RETURN
  641.  
  642. END SUB
  643.  
  644. DEFINT A-Z
  645. SUB SetBit (Value%, BitNumber%, BitOn%) STATIC
  646.     '**** Sets an individual bit (BitNumber%) on if BitOn% is true,
  647.     '     otherwise if BitOn% is false then the bit is turned off.
  648.  
  649.     IF BitOn THEN
  650.         Value = Value OR BitValue(BitNumber)
  651.     ELSEIF NOT BitNumber = 15 THEN     'Turn off bit 0 - 14
  652.         Value = Value AND 32767 - BitValue(BitNumber)
  653.     ELSE                       'Turn off bit 15 - requires special handling
  654.         Value = Value AND -(BitValue(BitNumber) + 1)
  655.     END IF
  656. END SUB
  657.  
  658. DEFINT A-Z
  659. FUNCTION TestBit% (Value%, BitNumber%) STATIC
  660. '**** Test whether a bit is turned on or off
  661.     TestBit = (Value AND BitValue(BitNumber)) = BitValue(BitNumber)
  662. END FUNCTION
  663.  
  664.