home *** CD-ROM | disk | FTP | other *** search
/ 8bitfiles.net/archives / archives.tar / archives / genie-commodore-file-library / GEOSApps / ROTPAGES.SRC (.txt) < prev    next >
GEOS ConVerT  |  2019-04-13  |  41KB  |  598 lines

  1. ROTPAGES.src
  2. SEQ formatted GEOS file V1.0
  3. Epson FX-80
  4. SIGIRL.MAC+
  5. BLASTER'S CONVERTER V2.5
  6. pEACHES
  7. 07-26-90GEOS
  8. Write Image V2.1
  9. geoWrite    V2.1
  10. .Student Forth source code for ROTPAGES, which prints "PAGE xy" files sideways.
  11. @ROTPAGES.src 
  12. by Hank Wilkinson
  13. @Using Student Forth to crop and rotate Paint PAGES files.
  14. GEOS, Paint DRIVERS and
  15. Paint PAGES are Berkeley Softworks
  16. '64 is is Commodore Business Machines
  17. PStudent Forth 
  18. @Anticipatory Design Science
  19. Freeman Building, Suite 303, 612 Pasteur Dr.
  20. Greensboro, NC 27403
  21. A booklet made from an 8-1/2 X 
  22. 5-1/2
  23.  page is comfortable to handle.  Folded accordian style, computer paper is perfect for this.
  24. Here are two sheets of computer paper with the sprocket holes still attached.
  25. Fold these two pages the way being described and you'll end up with four half-sized pages.  Here is the idea with the sprocket holes removed.
  26. Obviously, these pages may be folded all the way up to close like a book.  Just as obvious, you don't have to use exactly two sheets.  .
  27. The size of book is pleasing to hold, flip through and read.  Some of its appeal may be because the ratio of its sides is very close to the golden ratio (ie., ~1 to ~.616).  
  28. The size of book is pleasing to hold, flip through and read.  Some of its appeal may be because the ratio of its sides is very close to the golden ratio (ie., ~1 to ~.616).  
  29. It's also practical.  When I am through with a rough draft, I have only printed on one side.  By folding it as I have above I can write on the back easily.  Rather than throw paper in the trash can, I put all used computer paper in a box for use later
  30. The half-size page is also practical for the way I program.  I break a task up into the smallest practical size.  A small page encourages this.  Using the back of a used piece of paper keeps me from worrying about "wasting" paper to figure out my programs.
  31. So anyway, that is how I ended up thinking about folding paper this way.  The task of rotating and clipping a page to fit half a page is made easier by Paint PAGES.  
  32. The GEOWRITE file is actually clipped when made into a GEOPAINT page by Paint PAGES.
  33. The GEOWRITE file is actually clipped when made into a GEOPAINT page by Paint PAGES.  My GEOWRITE files (for my FX-80 printer driver) are clipped off at the bottom for Paint PAGES.  My GEOWRITE uses 94 print rows per page, GEOPAINT uses 90.
  34. We will need to clip this GEOPAINT page to 80 card rows in order to rotate it 90 degrees.  
  35. FThis is the idea.  By using the facility of Paint PAGES that we already have, a program that clips and rotates, putting two half pages per page is not that difficult.  All we have to do is set our margins, headers and footers correctly, and Paint PAGES will generate the images for us.
  36. We just have to make the clipping and rotating program that prints two half pages per page.  This is made easier by doing pieces of a page out to a temporary file in stages.
  37. Any confusion you have about setting margins, headers or footers will be cleared up the first time you use this routine.  On my set-up, GEOWRITE ma
  38. Any confusion you have about setting margins, headers or footers will be cleared up the first time you use this routine.  On my set-up, GEOWRITE may make one page contain 94 rows of 80 cards per row.  Without a whimper, error, or any other warning, Paint PAGES will trim this down to 90 rows of 80 cards per row.
  39. When 
  40. @ROTPAGES
  41.  gets through with it, your page will pass only 80 rows of 40 cards per.  That is what I meant by your confusion being cleared up quickly.  Using 40 cards means we clip the entire right half of the image, and some more off the bottom.
  42. Just like Paint PAGES leaves your GEOWRITE file alone, 
  43. @ROTPAGES
  44.  leaves the Paint PAGES files alone.  It writes no permanent changes back to disk.
  45. The image screen in GEOS is a large 8000 byte buffer.  Ignoring color, this huge buffer shows, pixel by pixel, what is in the buffer.  The way the '64 is made, and the way GEOS sets it up, there may be two of these: the background screen and the foreground screen.
  46. Because of the way things are hooked up inside our '64s, the image screen is further divide into cards.  A card is eight consecutive bytes, the first of which lies exactly on the addressing boundary.  The cards appear to a programmer as eight bytes stacked on top of each other.
  47. GThe "cards" are arranged next to each other in this 8000 byte image buffer, or screen, so that 40 cards make up one screen image row.
  48. HEach image scr
  49. GThe "cards" are arranged next to each other in this 8000 byte image buffer, or screen, so that 40 cards make up one screen image row.
  50. HEach image screen's card row is 320 bytes.  You may realize this to be exactly half as wide as a printer's row and GEOPAINT row.
  51. It may be hard to visualize, but it must be even harder to explain because I'm getting nowhere fast.
  52. Let's pause a minute, I have something to do here.
  53. { : copyright! ." Hank Wilkinson 1990" ; }
  54. Okay, let's go on.
  55. I'll say it this way.  Each GEOPAINT page is stored in a VLIR file as 45 records representing 
  56.  horizontal rows, each of which is 80 cards wide.  The actual data is not only compressed, but the c
  57. I'll say it this way.  Each GEOPAINT page is stored in a VLIR file as 45 records representing 
  58.  horizontal rows, each of which is 80 cards wide.  The actual data is not only compressed, but the color information is there also.  We will ignore color.
  59. This means that the GEOPAINT page represents a grid of pixels 640 wide in the horizontal direction and 720 high.  Our 
  60. @ROTPAGES
  61.  is going to take one of the pages and clip it into 320 pixels wide and 640 pixels high.  That way, the resultant clipped image will fit, if rotated 90 degrees, on a half sheet of paper.
  62. The easiest way I see of doing that is to fill a GEOS screen completely up with an image 320 pixels wide and 200 pixels high.  Then we rotate that entire screen out to a temporary disk file.  We repeat this procedure 2 and 1/5 more times to complete a half page.  This is then sent to the printer.  
  63. @This
  64.  is repeated until we have printed out all the Paint PAGES images that are on a disk.
  65. We are ready to start defining procedure now.
  66. 1) Fill screen with Paint PAGES GEOPAINT image.
  67. 2) Rotate screen image 90 degrees.
  68. 3) Save rotated image to disk.
  69. 4) Print image.
  70. Fill screen is furt
  71. Fill screen is further broken down into smaller parts.
  72. 1) Read image double row into buffer.
  73. 2) Expand the compacted image into another buffer.
  74. 3) Move image row from buffer into screen.
  75. Rotate screen image is divided into rotating a card 90 degrees, rotating a full column 90 degrees and rotating a partial column 90 degrees.  The screen card rotation has been written in assembly language and attached to 
  76. @Student Forth
  77.  before any of the other programming is done.
  78. In fact, just the action part of the word was written and assembled but not linked.  A short, one page, procedure was written that attached it into 
  79. @Student Forth
  80.  and it may be called by the word 
  81. @RotCard
  82. @RotCard
  83.  needs the 
  84.  address and the 
  85.  address on the stack.  Let's say we are rotating the first card on the screen to the first card position in a buffer.  Here is the syntax of that theoretical task,
  86. @SCREENBASE BUFFER RotCard
  87. @SCREENBASE
  88.  is the "from".  That is where 
  89. @RotCard
  90.  will start.  
  91. @BUFFER
  92.  is the "to".  That is where 
  93. @RotCard
  94.  will put the rotated card.
  95. Along with 
  96. @RotC
  97. Along with 
  98. @RotCard
  99.  we also made another word that rotates the 25 cards in a column of a GEOS screen.  Like 
  100. @RotCard
  101. @RotCol
  102.  needs a "from" and "to" address.  
  103. @RotCol
  104.  will rotate the whole screen column.
  105. GEOS is persnickety about entering the deskTop sometimes, like when you enter from drive 8 and exit from drive 10.   A variable may be used to save the initial, or entry drive.  Then, upon exit, this same drive will be set.
  106. { 0 Variable entry/ExitDisk }
  107. Also, with a variable, it is easier to keep track of which drive is being used.  For example, the "PAGE xy" may be on a disk drive, but we want to do our cropping and rotation on the RAM disk.
  108. { 0 Variable RAM   0 Variable Disk }
  109. Any error needing to return to the deskTop should return with the disks set correctly.
  110. :  GoBye
  111. ( first, an empty loop giving user time to react )
  112. 10000 0 Do Loop
  113. entry/ExitDisk C@ SetDevice Drop 
  114.     OpenDisk Drop
  115.         Bye
  116. The next few pages contain the basic GEOPAINT VLIR file reading and expansion commands.  If you want them explained, read my "PRINTPAGES.SRC" found on Q-Link.  Skip on over to page 14.
  117. 0 Variable #Printed
  118. 0 Variable PAGECount
  119. 21912 Constant pic
  120. 0 Variable picPtr
  121. : picAddress  (  --  address  ) pic picPtr @ + ;
  122. : pic@  (  --  value_pointed_to  )  picAddress C@ ;
  123. : NextpicPtr  (  --  ) 1 picPtr +! ;
  124. 23912 Constant row
  125. 0 Variable rowPtr
  126. : rowAddress  (  --  address  ) row rowPtr @ + ;
  127. : row! (  byte  --  )  rowAddress C! ;
  128. : NextrowPtr  (  --  ) 1 rowPtr +! ;
  129. : Type1  (  --  )
  130. pic@ 128 - rowAddress Over
  131. NextpicPtr pic@  NextpicPtr Fill rowPtr +! ; 
  132. : Type2  (  --  )
  133. : Type1  (  --  )
  134. pic@ 128 - rowAddress Over
  135. NextpicPtr pic@  NextpicPtr Fill rowPtr +! ; 
  136. : Type2  (  --  )
  137. pic@ NextpicPtr
  138. 63 And 0 Do
  139.     picAddress  rowAddress  8  CMove
  140.     8 rowPtr +!
  141. 8 picPtr +!
  142. : Type3  (  --  )
  143. pic@ >R NextpicPtr
  144.     picAddress  rowAddress  R  CMove
  145. R picPtr +!
  146. R> rowPtr +!
  147. : UnCompact  (  --  )
  148. Case    128 > Of Type1 Exit Then
  149. Case    63 > Of Type2 Exit Then
  150.             Type3
  151. : Expandpic  (  --  )
  152. : Expandpic  (  --  )
  153. 0 picPtr !
  154. 0 rowPtr !
  155.     Begin
  156.         UnCompact
  157.     rowPtr @ 960 > Until
  158. : Getpic  (  --  true=read,false=empty  )
  159. FN$ OpenVLIR
  160.     If ." Couldn't open " FN$ 16 Type CR GoBye Then
  161. PointRecord
  162.     If ." Couldn't point to record" CloseVLIR 
  163. GoBye
  164.                             Then
  165.         pic 2000 ReadRecord
  166.         If ." Couldn't read" CloseVLIR 
  167. GoBye
  168.  Then
  169.             (  true  )
  170.     Else
  171.         row 1280 Erase
  172.         FALSE
  173.     Then
  174. CloseVLIR
  175. :    PreparePixels    (  GEOPAINT_row#   --  )
  176.     GetPic            (  row#  --  flag  )
  177.         If ExpandPic Then
  178.             ?Terminal If 
  179. GoBye
  180.  Then
  181. :    PAGE$ ." PAGE  "
  182. :    InitializeName
  183.     FN$ 17 Erase
  184. :    PAGE$ ." PAGE  "
  185. :    InitializeName
  186.     FN$ 17 Erase
  187.         ' PAGE$ 2 + Count FN$ Swap CMove
  188. :    SetName
  189.     PAGECount @ S->D <# #S #>
  190.     Dup 1 > If
  191.         Else
  192.         Then
  193.         FN$ + Swap CMove
  194. These command words from "PRINTPAGES" are used 
  195. as is
  196. .   This is the "copy and modify" method of programming.  As a utility, understand them this way:  
  197. @PreparePixels
  198.  will read a compressed GEOPAINT VLIR record and expand it into two 640 byte printer rows at the buffer named 
  199. Each row of little squares above stands for 640 bytes.  The entire file needs to be "cropped" to rows 320 bytes wide.  This will be accomplished by moving only the first 320 bytes of each row to the GEOS image screen.  The screen (the foreground screen) will serve as a large buffer to gather together 25 half rows together for the 90 degree rotation.
  200. Conceptually then, the GEO
  201. Conceptually then, the GEOS image screen may be accessed as 25 rows, of 320 bytes of pixels.  By numbering the image row from 0 to 24, the offset into 
  202. @SCREENBASE
  203.  is computed by 
  204. @index*320
  205. .  Adding this offset to 
  206. @SCREENBASE
  207. , the effective address is obtained.  
  208. :  ToScreen  (  address_in_row  screen_row_0:24  --  )
  209.     320 * SCREENBASE + 320 CMove ;
  210. @ToScreen
  211.  needs either the address of 
  212. @row+640
  213.  and the screen row from 0 to 24.  Given that much it will move the 1/2 printer row to the GEOS image screen.
  214. Basically, every time we read another VLIR record, we have two printer rows.  Because there are 25 image screen rows, the movement from the 
  215.  buffer to the screen doesn't equal.  In other words, 12-
  216.  double printer rows fill the image screen.  It is apparent that a double row will be split between image screens from time to time.
  217. We either move the 1st half of the double row to the image screen or the second half.
  218. : 1stHalf (  screen_row_0:24  --  ) 
  219.     row Swap ToScreen ;
  220. Realizing each printer row is 640 bytes, adding 640 computes the offset to the second half of the image slice.  Note the difference betwe
  221. Realizing each printer row is 640 bytes, adding 640 computes the offset to the second half of the image slice.  Note the difference between 
  222. @1stHalf
  223.  and 
  224. @2ndHalf
  225.  is merely "640 +".
  226. : 2ndHalf (  screen_row_0:24  --  )
  227.     row 640 + Swap ToScreen ;
  228. @1stHalf
  229.  and 
  230. @2ndHalf
  231.  now form an ugly, but writable basis of moving and thus  clipping PAGES to the screen.  In the following words, the loop index, 
  232. , is first used to prepare the pixels.  Then it is used to compute the GEOS image screen rows to move the pixels, clipping them.
  233. :    1stScreen
  234.     12 0 Do
  235.         I PreparePixels
  236.         I 2 * 1stHalf 
  237.         I 2 * 1+ 2ndHalf
  238.     Loop
  239.     12 PreparePixels 24 1stHalf
  240. Note the 
  241. @Do/Loop
  242.  is from 0 to 12, or 0 to 11 inclusive.  At the end of the 
  243.  loop we have only expanded and moved 24 screen rows.  The 25th is handled after the loop.
  244. In the next word, the left over half of the double row is send to the screen firs
  245. In the next word, the left over half of the double row is send to the screen first.  The loop indices are changed to reflect the VLIR file records being accessed.  The math on indices correctly places the expanded images on the screen.
  246. :    2ndScreen
  247.     0 2ndHalf
  248.     25 13 Do
  249.         I PreparePixels 
  250.             I 13 - 2 * 1+ 1stHalf
  251.             I 13 - 2 * 2 + 2ndHalf
  252.     Loop
  253. Note the "gyrations" taken to equalize filling 25 image rows from 
  254. pairs
  255.  of image rows.  Again note the math on the index to aim at the correct screen rows (0:25) even though the VLIR file's record numbers range from 0:40.
  256. :    3rdScreen
  257.     37 25 Do
  258.         I PreparePixels 
  259.             I 25 - 2 * 1stHalf 
  260.             I 25 - 2 * 1+ 2ndHalf
  261.     Loop
  262.     37 PreparePixels 24 1stHalf
  263. The last word in the movement series reflect 1/5 of a screen, or five screen rows.  Again the loop indices reflect this.
  264. :    4thScreen
  265.     0 2ndHalf
  266.     40 38 Do
  267.         I PreparePixels 
  268.             I 38 - 2 * 1+ 1stHalf 
  269.             I 38 - 2 * 2 + 2ndHalf
  270.     Loop
  271. :  RotPartCol    ( from  --  )
  272.     PBP1 32 + PUTIT+1 !
  273. 5 0 Do
  274.     RotCard
  275.         320 8 +!
  276.         -8 PUTIT+1 +!
  277. We now have commands which read and expand the VLIR records, and commands that clip the file and buffer a screen full.  The next task would be to rotate the screen and save it in a temporary disk file.
  278. Commands to perform rotation and storing, and subsequent recalling and printing need to be developed.  We start with a few system calls.
  279. Looking for 
  280. Looking for the printer driver, or the "PAGE xy" files might require changing drives.  Any error encountered will stop the process after displaying the system call causing the error along with the actual error number.
  281. :  SetDrive    (  drive#  --  ) 
  282. SetDevice -Dup If ." SetDevice Error # " .
  283.                 GoBye Then
  284. OpenDisk  -Dup If ." OpenDisk Error # " . 
  285.                 GoBye Then
  286. Once the actual type is know, these words may be used to connect to
  287. Once the actual type is know, these words may be used to connect to the necessary drive.  For speed, we want the clipped and rotated images on the RAM disk.  We may want the "PAGE xy" files on a regular disk, if we fill up our RAM disk.
  288. :  ->RAM RAM C@ SetDrive ;
  289. :  ->Disk Disk C@ SetDrive ;
  290. If an error was encountered changing drives, the following variable may be accessed to see which drive is the current one.
  291. 8489 Constant curDrive 
  292. Decimal
  293. To check to see if there is enough room on a disk to do the cropping and rotating, we build a word that returns the number of blocks free on the stack.
  294. C1DB Constant CalcBlksFree
  295. Decimal
  296. :  CalcFree curDirHead r5 ! CalcBlksFree Jsr r4 @
  297. The search for a RAM disk should be straight forward, if that is achievable.  For readability, obtaining the actual type of a particular drive is contained in a command. 
  298. 848e Constant driveType
  299. Decimal
  300. :  DriveTypeA (  --  drive_type  ) driveType C@ ;
  301. :  DriveTypeB (  --  drive_type  )  driveType 1+ C@ ;
  302. :  DriveTypeC (  --  drive_type  )  driveType 2 + C@ ;
  303. To find the RAM disk, each drive is searched until it is found.  The search is accomplished by reading the type byte and testing bit 7.  (The RAM disk has bit 7 set.)  The program stops if no RAM disk is found.
  304. After finding the RAM disk, the amount of free space is checked.  Again the process is stopped if there is not enough room.
  305. :  InitRAM/Disk
  306. DriveTypeA 128 And
  307. If 8 RAM C! 
  308. Else 
  309.     DriveTypeB 128 And
  310.     If 9 RAM C! 
  311.     Else    DriveTypeC 128 And 
  312.         If 10 RAM C! 
  313.         Else    10 0 Do ." Need RAM Disk!!!" CR Loop
  314.             GoBye
  315.         Then
  316.     Then
  317. ->RAM CalcFree
  318.  124 < If 19 emit 10 0 Do 
  319.         ."      Need 32k free on RAM Disk!!" CR
  320.             Loop
  321.             GoBye Then
  322. To keep the disk file name "TEMP" in, a string buffer is made.
  323. { Create TEMP$ 17 Allot }
  324. The string itself is written in memory.
  325. { : TMP$ ." TEMP" ;  }
  326. The string will be moved to the buffer later.
  327. To create a file in GEOS, a 256 byte space is needed for the file header.  Rather than have this buffer in the program space, it extended past the program memory.  
  328. To create a file in GEOS, a 256 byte space is needed for the file header.  Rather than have this buffer in the program space, it extended past the program memory.  
  329. { : putb Here 256 + ; }
  330. Then the creation of the "TEMP" file is matter of following a list of things to do.
  331. C1ED Constant SaveFile
  332. C289 Constant AppendRecord
  333. Decimal
  334. : CreateTEMP
  335. TEMP$ 16 Erase ' TMP$ 2 + Count TEMP$ Swap 
  336. CMove TEMP$ putb !
  337. 3 putb 2 + C! 21 putb 3 + C!
  338. 128 63 + putb 4 + C!
  339. 3 putb 68 + C! 13 putb 69 + C! 1 putb 70 + C!
  340. 0 putb 71 + !
  341. -1 putb 73 + !
  342. 0 putb 75 + !
  343. putb 20 ! 1 22 C! SaveFile Jsr
  344. TEMP$ OpenVLIR Drop
  345. 120 0 Do 
  346.     AppendRecord Jsr 
  347. CloseVLIR
  348. Once used, the "TEMP" file has to be er
  349. Once used, the "TEMP" file has to be erased, gaining back the disk space.
  350. C238 Constant DeleteFile
  351. :  DeleteTEMP TEMP$ r0 ! DeleteFile Jsr ;
  352. Decimal
  353. The "TEMP" file is where we put the cropped and rotated image.  Once made, it is printed out.  The printing done by printer rows.  First, put the data into the PBP1 print buffer and the following word will send it to the printer via 
  354. @PrintBuffer
  355. , checking to see if the user wants to quit.
  356. :  PrintBuf        (  --  )
  357. PBP1 r0 ! PBP2 r1 ! 0 r2 ! PrintBuffer
  358.     ?Terminal If CloseVLIR 
  359. GoBye
  360.  Then
  361. There will be times a blank row is sent.  This allows "flushing" the GEOS print buffers and alignment of two pages per page.
  362. :  SendBlankRow PBP1 640 Erase PrintBuf ;
  363. With an "open" VLIR TEMP file, the record needs accessing.  Any error should be acknowledged and solved.
  364. :  AimRecord    (  record#  --  )
  365. PointRecord
  366.     -Dup If ." error # " . ." wh
  367. With an "open" VLIR TEMP file, the record needs accessing.  Any error should be acknowledged and solved.
  368. :  AimRecord    (  record#  --  )
  369. PointRecord
  370.     -Dup If ." error # " . ." while pointing"
  371.             CloseVLIR GoBye Then
  372.         Drop
  373. Also, what is stored in the TEMP file is a slice of the page.
  374. :  GetSlice    (  address_to_put  --  )
  375. 200 ReadRecord
  376.     -Dup If ." error # " . ." while reading"
  377.             CloseVLIR GoBye Then
  378.         Drop
  379. By reading the "TEMP" file, one record at a time, the printing is accomplished.  Here we read one record and send it to be printed.
  380. :  PutBuf        (  0:39  --  )
  381. Dup 8 * SCREENBASE + RotPartCol
  382. 80 Over + AimRecord PBP1 40 + GetSlice
  383. 40 Over + AimRecord PBP1 240 + GetSl
  384. :  PutBuf        (  0:39  --  )
  385. Dup 8 * SCREENBASE + RotPartCol
  386. 80 Over + AimRecord PBP1 40 + GetSlice
  387. 40 Over + AimRecord PBP1 240 + GetSlice
  388.     AimRecord PBP1 440 + GetSlice
  389. PrintBuf
  390. Then the whole process of printing the "TEMP" file is accomplished by looping.
  391. :  PrtTEMP        (  --  )
  392. TEMP$ OpenVLIR Drop
  393. 40 0 Do
  394.     I PutBuf
  395. CloseVLIR
  396. Writing records out to a VLIR file requires the beginning address and a count of the number of bytes to write to the record.
  397. C28F Constant (WriteRecord)
  398. Decimal
  399. :  WriteRecord    (  from  count  --  error  )
  400.     r7 !
  401.         0 0 0 0 (WriteRecord) Call  (  a  x  y  psw )
  402.         Drop Drop Swap 
  403. C28F Constant (WriteRecord)
  404. Decimal
  405. :  WriteRecord    (  from  count  --  error  )
  406.     r7 !
  407.         0 0 0 0 (WriteRecord) Call  (  a  x  y  psw )
  408.         Drop Drop Swap Drop         (  x=error  )
  409. :  Rot1stScreen
  410. 1stScreen
  411. TEMP$ OpenVLIR Drop
  412. 40 0 Do
  413. I AimRecord
  414. SCREENBASE I 8 * + PBP1 192 + RotCol
  415. PBP1 200 WriteRecord Drop
  416. CloseVLIR ?Terminal If GoBye Then
  417. :  Rot2ndScreen
  418. 2ndScreen
  419. TEMP$ OpenVLIR Drop
  420. 80 40 Do
  421. I PointRecord Drop Drop
  422. SCREENBASE I 40 - 8 * + PBP1 192 + RotCol
  423. PBP1 200 WriteRecord Drop
  424. CloseVLIR ?Terminal If GoBye Then
  425. :  Rot3rdScreen
  426. 3rdScreen
  427. TEMP$ OpenVLIR Drop
  428. 120 80 Do
  429. I PointRecord Drop Drop
  430. SCREENBASE I 80 - 8 * + PBP1 192 + RotCol
  431. PBP1 200 WriteRecord Drop
  432. CloseVLIR ?Terminal If 
  433. GoBye
  434.  Then
  435. : RotPage
  436. CreateTEMP
  437.     Rot1stScreen
  438.         Rot2ndScreen
  439.             Rot3rdScreen
  440.                 4thScreen
  441.                     PrtTEMP
  442. Delet
  443. : RotPage
  444. CreateTEMP
  445.     Rot1stScreen
  446.         Rot2ndScreen
  447.             Rot3rdScreen
  448.                 4thScreen
  449.                     PrtTEMP
  450. DeleteTEMP
  451. Now and again we crash.  I hate it, you hate it.  We probably hate the mo
  452. Now and again we crash.  I hate it, you hate it.  We probably hate the most a 
  453. @preventable
  454.  crash!  One sure way to crash is to forget remove the "Paint PAGES" driver and put back your regular printer driver.
  455. GEOS has a variable to keep the printer driver's file name in.
  456. { Hex
  457. 8465 Constant PrntFileName
  458. Decimal }
  459. Before we even load the printer driver, this location should be checked to be sure it contains our normal printer driver.  
  460. But we have no way of knowing what our normal printer driver is.  On the other hand, we do know what it 
  461. shouldn't be!  
  462. "Paint PAGES" and "Paint OVERLAY" both begin with "Paint ".  By simply adding up the ASCII value of "Paint ", our total to check for is 540, or $21C.
  463. { 540 Constant WRONGPRELUDE }
  464. By reading and summing the first six bytes of the ASCII string found at 
  465. @PrntFileName
  466. , a test may be performed ensuring we 
  467. don't
  468.  have "Paint whatever".
  469. :  ?PaintDriver    (  --  )
  470. :  ?PaintDriver    (  --  )
  471. 6 0 Do
  472.     PrntFileName I + C@ +
  473. WRONGPRELUDE =
  474.     If 19 Emit
  475.         10 0 Do 
  476.         ." You have wrong printer driver!" CR
  477.         Loop
  478.         GoBye
  479.     Then
  480. Simply put, this routine adds up the first six characters in the 
  481. @installed
  482.  printer driver and compares this to the ASCII sum of "Paint ".  If the two sums are equal, the screen is cleared, a message is printed and the program 
  483. @Abort
  484. s to the command line.
  485. Once a suitable printer driver 
  486.  is verified, the  next task is to 
  487. @find
  488.  the printer driver.  With GEOWRITE allowing 61 pages, space is a premium.  Neither the printer driver nor 
  489. @ROTPAGES
  490.  should have to be on the RAM disk, allowing more room for our "PAGE xy" files.
  491. Once a drive is set, it is a simple matter to see if our driver is there.
  492. :  ?PDriver        (  --  true=found  )
  493.             (  --  false= not found  )
  494. PrntFileName FindFile 0= 
  495. If the driver is
  496. Once a drive is set, it is a simple matter to see if our driver is there.
  497. :  ?PDriver        (  --  true=found  )
  498.             (  --  false= not found  )
  499. PrntFileName FindFile 0= 
  500. If the driver is not on the drive we look at, we should change drives and look there.  The following word needs either 8, 9 or 10.  
  501. :  SearchDrive    (  drive#  --  true=found  )
  502.             (  drive#  --  false=not found )
  503. SetDevice If FALSE Exit Then
  504. OpenDisk If FALSE Exit Then
  505. ?PDriver
  506. Basically we should first check the "current" drive.  If the driver isn't found we should check the other drives.  The following word includes a redundant search, but the computer is doing the searching, not us.
  507. :  Look    (  --  TRUE = found  )
  508.         (  --  FALSE = not found  )
  509. DriveTypeA If 8 SearchDrive -Dup If Exit Then Then
  510. DriveTypeB If 9 SearchDrive -Dup If Exit Then Then
  511. DriveTypeC If 10 SearchDrive Exit Then
  512. Wrapping the idea up in a big command is simple.  First check current
  513. Wrapping the idea up in a big command is simple.  First check current, if found we're though.  Otherwise, check all three drives.  If 
  514. @Look
  515.  couldn't find the driver, clear the screen and print the message four times.  Keep doing that until the user puts in a disk with driver on it.
  516. :  FindDriver
  517. curDrive C@ SearchDrive If GetPDriver Exit Then
  518. Begin
  519. Look 0= While
  520.     19 Emit 4 0 Do
  521.         ." Insert disk with printer driver " CR
  522.         PrntFileName 16 Type CR
  523.     Loop
  524.         ." THEN PRESS any key but a period!" CR
  525.         ." (A period will quit to deskTop)" CR
  526.         Key  ." Thanks" ASCII . = 
  527.         If GoBye Then
  528. Repeat
  529. GetPDriver
  530.     GetDimensions 127 And
  531.         79 > If ( okay ) Else
  532.              19 Emit 5 0 Do
  533.              ." Need 80 cards wide printer!" CR
  534.             Loop GoBye Then
  535. :    DoPAGEs    (  --  )
  536. curDrive C@ entry/ExitDisk C!
  537. InitRAM/Disk entry/ExitDisk C@ SetDevice
  538. ?PaintDriver FindDriver InitForPrint
  539. ->RAM
  540. InitializeName
  541. 1 PAGECount !
  542. 1 #Printe
  543. :    DoPAGEs    (  --  )
  544. curDrive C@ entry/ExitDisk C!
  545. InitRAM/Disk entry/ExitDisk C@ SetDevice
  546. ?PaintDriver FindDriver InitForPrint
  547. ->RAM
  548. InitializeName
  549. 1 PAGECount !
  550. 1 #Printed !
  551. Begin
  552.     PAGECount @ 62 < 
  553.     While
  554.         SetName
  555.         1 PAGECount +!
  556.         FN$ FindFile 
  557.         0= If
  558.             #Printed @ 1 And
  559.                 If StartPrint Drop
  560.                 RotPage
  561.                 26 0 Do
  562.                     SendBlankRow 
  563.                 Loop
  564.                 Else RotPage
  565.                 StopPrint
  566.                 Then
  567.                1 #Printed +!
  568.         Then
  569. Repeat
  570.     GoBye
  571. On disk:StudnetPub, 
  572. @ROTPAGES
  573. @.src
  574.   DATE, TIME
  575. Printing Files 
  576. Sideways 
  577.  In Batch Mode
  578. Copyright by Hank Wilkinson, 1990
  579.                                                                                                     
  580. @Student Forth 
  581. @Anticipatory Design Science
  582. Freeman Building, Suite 303, 612 Pasteur Dr.
  583. Greensboro, NC 27403
  584. page PAGE
  585. fc00fl
  586. vc00f
  587. fc00fl
  588. vc00f
  589. fc0>f
  590. ``00fl
  591. fc00f
  592. fc00fl
  593. fc00f
  594.  and the screen row from 
  595. A$    !Zb 
  596. $    %UV`
  597. UA$    )X*
  598.