home *** CD-ROM | disk | FTP | other *** search
/ Crawly Crypt Collection 2 / crawlyvol2.bin / apps / database / hypergem / hypergem.lst < prev    next >
File List  |  1994-09-02  |  84KB  |  2,610 lines

  1. '  TITLE   : Hierarchical Database
  2. '  BY      : Timothy Raine
  3. '  VERSION : 1.1
  4. '  DATE    : 30th May 1994
  5. ' ---------------------------------
  6. '
  7. $m600000                                         ! Reserve Program Memory
  8. RESERVE 600000
  9. GOSUB start_up
  10. GOSUB main_routine
  11. GOSUB close_down
  12. '
  13. > PROCEDURE start_up
  14.   '  General Initialisation
  15.   ' ------------------------
  16.   VOID FRE(0)                                    ! Memory Garbage Collection
  17.   ON ERROR GOSUB close_down                      ! Trap Errors
  18.   ~APPL_INIT()                                   ! Announce Application
  19.   ~WIND_GET(0,4,scrx%,scry%,scrb%,scrh%)         ! Max screen size
  20.   GOSUB get_textsize(chrb%,chrh%,chrbb%,chrbh%)  ! System Font Size
  21.   GRAPHMODE 0                                    ! Set Graphics Mode
  22.   DEFFILL ,0                                     ! Set Fill Pattern
  23.   '  Call Initialisation Routines
  24.   ' ------------------------------
  25.   LET path$=CHR$(GEMDOS(25)+65)+":"+DIR$(0)+"\"  ! Current File Directory
  26.   GOSUB load_resource(path$)                     ! Load Resource File
  27.   GOSUB load_mouse(path$)                        ! Load Mouse Shapes
  28.   GOSUB define_cursor                            ! Define Cursor Shape
  29.   GOSUB define_datastructure                     ! Define Datastructure
  30.   GOSUB reset_datastructure                      ! Reset Datastructure
  31.   GOSUB hypergem_info                            ! Load Info Graphic
  32.   GOSUB init_menu                                ! Define Menu Bar
  33.   GOSUB init_bitblt                              ! Initialise BitBlt
  34.   GOSUB init_sample                              ! Initialise Sample
  35. RETURN
  36. '
  37. > PROCEDURE close_down
  38.   ' PURPOSE : Closes any open windows, removes menu bar,
  39.   '           frees reserved memory used for resource file
  40.   '           and alerts the user if an error occurred.
  41.   IF ERR<>0
  42.     ALERT 1,"CLOSING HYPERSYSTEM DOWN!|"+ERR$(ERR),1," Ok! ",void%
  43.   ENDIF
  44.   MENU KILL
  45.   GOSUB close_old(handle&)
  46.   ~RSRC_FREE()                                   ! Free reserved memory
  47.   ~APPL_EXIT()                                   ! Close Application
  48.   EDIT                                           ! Return to editor
  49. RETURN                                           ! Dummy Return
  50. '
  51. '
  52. '  SECTION : Resource File, Mouse & Cursor Definitions
  53. ' -----------------------------------------------------
  54. '
  55. > PROCEDURE load_resource(path$)
  56.   ' PURPOSE : Load resource file & tree objects.
  57.   '
  58.   ' PARAMS  : (path$) Default file path from which system was loaded.
  59.   '
  60.   LOCAL tree%
  61.   IF EXIST(path$+"HYPERGEM.RSC")                ! Found Resource File?
  62.     ~RSRC_LOAD(path$+"HYPERGEM.RSC")            ! YES, Load Resource File
  63.     ~RSRC_GADDR(0,1,tree%)                       ! Returns address of 2nd Object
  64.     CHAR{{OB_SPEC(tree%,3)}}="Next Window"       ! Sets input string of object to "Next Window"
  65.   ELSE                                           ! Else Error Alert User!
  66.     ALERT 1,"RESOURCE FILE NOT FOUND!|Please, locate the file called:|filename: HYPERGEM.RSC",1," OK! ",void%
  67.     GOSUB close_down                             ! Close down system.
  68.   ENDIF
  69. RETURN
  70. '
  71. > PROCEDURE load_mouse(path$)
  72.   ' PURPOSE : Load Mouse Definitions for file operations (floppy disk),
  73.   '           Fill colour table (paintcan) and draw graphic (pencil)
  74.   '
  75.   ' PARAMS  : (path$) Default file path from which system was loaded.
  76.   '
  77.   IF EXIST(path$+"LOADSAVE.DAT") AND EXIST(path$+"PAINTCAN.DAT") AND EXIST(path$+"PENCIL.DAT")
  78.     LET iomouse$=STRING$(74,0)                   ! YES, allocate Memory
  79.     BLOAD path$+"LOADSAVE.DAT",VARPTR(iomouse$) ! Load Definition File
  80.     LET paintcan$=STRING$(74,0)                  ! Allocate Memory
  81.     BLOAD path$+"PAINTCAN.DAT",VARPTR(paintcan$)! Load Definition File
  82.     LET pencil$=STRING$(74,0)                    ! Allocate Memory
  83.     BLOAD path$+"PENCIL.DAT",VARPTR(pencil$)    ! Load Definition File
  84.   ELSE                                           ! Else Error Alert User!
  85.     ALERT 1,"MOUSE SHAPE FILES NOT FOUND!|Please, locate files called:|'LOADSAVE.DAT', 'PAINTCAN.DAT'|and 'PENCIL.DAT'",1," OK! ",void%
  86.     GOSUB close_down                             ! Close down system nicely.
  87.   ENDIF
  88. RETURN
  89. '
  90. > PROCEDURE define_cursor
  91.   ' PURPOSE : Define cursor shape as underscore character sprite.
  92.   '           (see manual for further details.)
  93.   '
  94.   LOCAL loop%
  95.   LET cursor$=MKI$(0)+MKI$(0)+MKI$(0)+MKI$(0)+MKI$(1)
  96.   FOR loop%=0 TO 28
  97.     LET cursor$=cursor$+MKI$(0)
  98.   NEXT loop%
  99.   LET cursor$=cursor$+MKI$(65280)+MKI$(65280)+MKI$(65280)
  100. RETURN
  101. '
  102. '
  103. '  SECTION : Define & Reset Datastructure
  104. ' ----------------------------------------
  105. '
  106. > PROCEDURE define_datastructure
  107.   ' PURPOSE : Main data structure for storing information on window
  108.   '           size and contents. It also stores data about buttons
  109.   '           and window link details.
  110.   '
  111.   DIM xpos%(255),ypos%(255),wsiz%(255),hsiz%(255),hpos%(255),vpos%(255)
  112.   DIM crea_date$(255),crea_time$(255),type$(255),file$(255),tail%(255)
  113.   DIM xbut%(255,25),ybut%(255,25),desc$(255,25),head%(255,25),txt$(4000)
  114. RETURN
  115. '
  116. > PROCEDURE reset_datastructure
  117.   ' PURPOSE : Initialises main datastructure to default values.
  118.   '
  119.   LOCAL loop%,i%
  120.   FOR loop%=1 TO 255
  121.     LET xpos%(loop%)=50                  ! Default window X position.
  122.     LET ypos%(loop%)=50                  ! Default window Y position.
  123.     LET wsiz%(loop%)=150                 ! Default window width.
  124.     LET hsiz%(loop%)=150                 ! Default window height.
  125.     LET hpos%(loop%)=0                   ! Horizonal slider position.
  126.     LET vpos%(loop%)=0                   ! Vertical slider position.
  127.     LET tail%(loop%)=0                   ! Pointer to previous window
  128.     LET crea_date$(loop%)=DATE$          ! Get current date.
  129.     LET crea_time$(loop%)=TIME$          ! Get current time.
  130.     LET type$(loop%)=""                  ! Window type.
  131.     LET file$(loop%)="FILENAME.TXT"      ! Filename of window contents.
  132.     FOR i%=1 TO 25
  133.       LET xbut%(loop%,i%)=0              ! Button x position.
  134.       LET ybut%(loop%,i%)=0              ! Button y position.
  135.       LET head%(loop%,i%)=0              ! pointer to next window.
  136.       LET desc$(loop%,i%)=""             ! button description.
  137.     NEXT i%
  138.   NEXT loop%
  139. RETURN
  140. '
  141. '
  142. '  SECTION : Initialise Menu Bar
  143. ' -------------------------------
  144. '
  145. > PROCEDURE init_menu
  146.   ' PURPOSE : drop down menu definition and creation.
  147.   '
  148.   LOCAL loop%
  149.   DIM m$(50)                      ! array to hold menu information
  150.   RESTORE menu
  151.   FOR loop%=0 TO 24
  152.     READ m$(loop%)
  153.   NEXT loop%
  154.   DEFMOUSE 0
  155.   MENU m$()
  156.   MENU 13,2   ! Run HyperSystem
  157.   MENU 16,2   ! Save HyperSystem
  158.   MENU 21,2   ! Add Button
  159.   MENU 22,2   ! Modify Button
  160.   MENU 23,2   ! Erase Button
  161.   GOSUB loading_message
  162. menu:
  163.   DATA Desk
  164.   DATA   Information on HyperGEM ◆I
  165.   DATA -----------------------------
  166.   DATA 1
  167.   DATA 2
  168.   DATA 3
  169.   DATA 4
  170.   DATA 5
  171.   DATA 6
  172.   DATA
  173.   DATA File
  174.   DATA   Generate HyperSystem ◆G
  175.   DATA --------------------------
  176.   DATA   Run HyperSystem      ◆R
  177.   DATA --------------------------
  178.   DATA   Load HyperSystem     ◆L
  179.   DATA   Save HyperSystem     ◆S
  180.   DATA --------------------------
  181.   DATA   Quit Program         ◆Q
  182.   DATA
  183.   DATA Window
  184.   DATA   Add Button       ◆A
  185.   DATA   Modify Button    ◆M
  186.   DATA   Erase Button     ◆E
  187.   DATA
  188. RETURN
  189. '
  190. > PROCEDURE loading_message
  191.   ' PURPOSE : Displaying HyperGEM Dialogue Message.
  192.   '
  193.   LOCAL tree%,dx%,dy%,dw%,dh%
  194.   DEFMOUSE 2
  195.   ~FORM_DIAL(3,scrx%,scry%,scrb%,scrh%,scrx%,scry%,scrb%,scrh%)
  196.   ~RSRC_GADDR(0,3,tree%)
  197.   ~FORM_CENTER(tree%,dx%,dy%,dw%,dh%)
  198.   ~GRAF_SHRINKBOX(dx%,dy%,dw%,dh%,scrx%,scry%,scrb%,scrh%)
  199.   ~FORM_DIAL(0,dx%,dy%,dw%,dh%,dx%,dy%,dw%,dh%)
  200.   ~OBJC_DRAW(tree%,0,3,dx%,dy%,dw%,dh%)
  201.   GOSUB init_dither_matrix
  202.   GOSUB init_dither_array
  203.   ~FORM_DIAL(3,dx%,dy%,dw%,dh%,dx%,dy%,dw%,dh%)
  204.   ~GRAF_GROWBOX(dx%,dy%,dw%,dh%,scrx%,scry%,scrb%,scrh%)
  205.   DEFMOUSE 0
  206. RETURN
  207. '
  208. '
  209. '  SECTION : Initialise Colour Dithering Arrays
  210. ' ----------------------------------------------
  211. '
  212. > PROCEDURE init_dither_matrix
  213.   ' PURPOSE : Initialising Ordered Dithering Array.
  214.   '
  215.   LOCAL y%,x%
  216.   DIM col|(16),dither|(3,3)
  217.   RESTORE graphics
  218.   FOR y%=0 TO 3
  219.     FOR x%=0 TO 3
  220.       READ dither|(x%,y%)
  221.     NEXT x%
  222.   NEXT y%
  223.   ' colour dithering matrix data
  224. graphics:
  225.   DATA  1, 9, 3,11
  226.   DATA 13, 5,15, 7
  227.   DATA  4,12, 2,10
  228.   DATA 16, 8,14, 6
  229. RETURN
  230. '
  231. > PROCEDURE init_dither_array
  232.   ' PURPOSE : Initialising Colour Conversion Array
  233.   '
  234.   LOCAL z%,y%,x%
  235.   DIM dither2|(64000),pic|(64000) ! for colour conversion
  236.   LET z%=1
  237.   FOR y%=1 TO 200
  238.     FOR x%=1 TO 320
  239.       LET dither2|(z%)=dither|(x% MOD 4,y% MOD 4)
  240.       INC z%
  241.     NEXT x%
  242.   NEXT y%
  243. RETURN
  244. '
  245. '
  246. '  SECTION : Initialise Bitblt Array & Sample Routines
  247. ' -----------------------------------------------------
  248. '
  249. > PROCEDURE init_bitblt
  250.   ' PURPOSE : Initialise BitBlt Array
  251.   '
  252.   DIM smfdb%(8),dmfdb%(8),p%(8)           ! for bitblt routine
  253.   LET dmfdb%(0)=XBIOS(3)
  254.   LET dmfdb%(1)=640                       ! screen horizontal resolution
  255.   LET dmfdb%(2)=400                       ! screen vertical resolution
  256.   LET dmfdb%(3)=40                        ! screen width in words
  257.   LET dmfdb%(5)=1                         ! screen number of bit planes
  258.   LET smfdb%(1)=640                       ! raster horizontal resolution
  259.   LET smfdb%(2)=400                       ! raster vertical resolution
  260.   LET smfdb%(3)=40                        ! screen width in words
  261.   LET smfdb%(5)=1                         ! raster number of bit planes
  262.   LET raster$=STRING$(32000,0)            ! fill arrays with blanks
  263. RETURN
  264. '
  265. > PROCEDURE init_sample
  266.   ' PURPOSE : Initialise DVSM playback frequency array
  267.   '
  268.   LOCAL loop%
  269.   DIM freq%(7)                ! array to hold frequency information
  270.   RESTORE sample
  271.   FOR loop%=0 TO 7
  272.     READ freq%(loop%)
  273.   NEXT loop%
  274. sample:
  275.   DATA 8195,9834,12292,16490,20770,24585,33880,49170
  276. RETURN
  277. '
  278. '
  279. '  SECTION : Drop Down Menu Management Procedures
  280. ' ------------------------------------------------
  281. '
  282. > PROCEDURE main_routine
  283.   ' PURPOSE : Wait for window, menu and keyboard events.
  284.   '
  285.   ON MENU MESSAGE GOSUB message
  286.   ON MENU GOSUB evaluate_menu
  287.   ON MENU KEY GOSUB keyboard
  288.   DO
  289.     ON MENU 1000
  290.   LOOP
  291. RETURN
  292. '
  293. > PROCEDURE evaluate_menu
  294.   ' PURPOSE : gets menu selection result and branches to appropriate
  295.   '           menu option procedure.
  296.   '
  297.   MENU OFF                           ! Disables anymore menu events.
  298.   IF m$(MENU(0))="  Information on HyperGEM ◆I"
  299.     GOSUB display_dialog_box
  300.   ELSE IF m$(MENU(0))="  Generate HyperSystem ◆G"
  301.     GOSUB generate_hypersystem
  302.   ELSE IF m$(MENU(0))="  Run HyperSystem      ◆R"
  303.     GOSUB run_hypertext
  304.   ELSE IF m$(MENU(0))="  Load HyperSystem     ◆L"
  305.     GOSUB load_hypertext
  306.   ELSE IF m$(MENU(0))="  Save HyperSystem     ◆S"
  307.     GOSUB save_hypertext
  308.   ELSE IF m$(MENU(0))="  Quit Program         ◆Q"
  309.     GOSUB quit_program
  310.   ELSE IF m$(MENU(0))="  Add Button       ◆A"
  311.     GOSUB add_button
  312.   ELSE IF m$(MENU(0))="  Modify Button    ◆M"
  313.     GOSUB find_button_modify
  314.   ELSE IF m$(MENU(0))="  Erase Button     ◆E"
  315.     GOSUB erase_button
  316.   ENDIF
  317. RETURN
  318. '
  319. > PROCEDURE file_select(title$,filetype$,save!)
  320.   ' PURPOSE : Provides the user with a file selector box to choose the file
  321.   '           on which he wants to save or load.
  322.   '
  323.   SPRITE cursor$
  324.   REPEAT
  325.     FILESELECT #title$,path$+filetype$,"",filename$
  326.     IF EXIST(filename$)                               ! does file exist
  327.       LET extender$=RIGHT$(filename$,3)               ! NOTE: file extension
  328.     ELSE IF filename$<>""                             ! file NOT found
  329.       IF save!=TRUE
  330.         ALERT 1,"File does not exist|"+filename$+"!|Create new file with this|name!",2," Cancel | Ok! ",button1%
  331.         IF button1%=2 AND filename$<>path$
  332.           OPEN "O",#4,filename$
  333.           CLOSE #4
  334.         ELSE
  335.           ALERT 2,"Error Invalid Filename!|Please type in a filename.",1," Ok! ",void%
  336.         ENDIF
  337.       ELSE
  338.         ALERT 1,"File does not exist!|The file you selected does|not exist!",2," Retry! | Cancel! ",button2%
  339.       ENDIF
  340.     ENDIF
  341.   UNTIL EXIST(filename$) OR filename$<>path$
  342. RETURN
  343. '
  344. > PROCEDURE quit_program
  345.   ' PURPOSE : Asks the user whether he really wants to quit or not.
  346.   '
  347.   LOCAL button%
  348.   ALERT 3,"Exit Program!|Are you sure you|want to quit! ",2,"Exit|Cancel",button%
  349.   IF button%=1  ! YES really exit program
  350.     '
  351.     ' Check for alterations to database and if
  352.     ' not saved prompt user to save database.
  353.     ' ----------------------------------------
  354.     FOR size%=255 DOWNTO 1
  355.       EXIT IF type$(size%)<>""
  356.     NEXT size%
  357.     IF size%<>old_size%
  358.       ALERT 1,"HyperSystem has been modified|but not saved!",2," Ignore! | Save! ",button%
  359.       IF button%=2
  360.         GOSUB save_hypertext
  361.       ENDIF
  362.     ENDIF
  363.     GOSUB close_down
  364.   ENDIF
  365. RETURN
  366. '
  367. '
  368. '  SECTION : HyperGEM Information Dialog Box
  369. ' -------------------------------------------
  370. '
  371. > PROCEDURE hypergem_info
  372.   ' PURPOSE : Loads graphic image. (with version and logo information)
  373.   '
  374.   LET info$=raster$                  ! Store contents of graphic window.
  375.   OPEN "I",#1,path$+"HYPERGEM.IMG"   ! Open file.
  376.   GOSUB load_image                   ! Load and uncompress graphic
  377.   CLOSE #1                           ! Close file.
  378.   SWAP info$,raster$                 ! Restore contents of graphic window.
  379. RETURN
  380. '
  381. > PROCEDURE display_dialog_box
  382.   ' PURPOSE : Displays an empty dialog box on the screen ready for
  383.   '           BitBlt graphic to be moved inside it.
  384.   '
  385.   LOCAL tree%,button%,dx%,dy%,dw%,dh%
  386.   ~RSRC_GADDR(0,0,tree%)
  387.   ~FORM_CENTER(tree%,dx%,dy%,dw%,dh%)
  388.   ~OBJC_CHANGE(tree%,1,0,dx%,dy%,dw%,dh%,0,0)
  389.   ~FORM_DIAL(0,dx%,dy%,dw%,dh%,dx%,dy%,dw%,dh%)
  390.   ~OBJC_DRAW(tree%,0,1,dx%,dy%,dw%,dh%)
  391.   GOSUB bitblt_hypergem_info(dx%,dy%,dw%,dh%)
  392.   LET button%=FORM_DO(tree%,0)
  393.   ~FORM_DIAL(3,dx%,dy%,dw%,dh%,dx%,dy%,dw%,dh%)
  394. RETURN
  395. '
  396. > PROCEDURE bitblt_hypergem_info(dx%,dy%,dw%,dh%)
  397.   ' PURPOSE : BitBlt hypergem_info graphic inside empty dialog box.
  398.   '
  399.   LET p%(0)=0
  400.   LET p%(1)=0
  401.   LET p%(2)=p%(0)+dw%-2
  402.   LET p%(3)=p%(1)+dh%-15
  403.   LET p%(4)=dx%+3
  404.   LET p%(5)=dy%
  405.   LET p%(6)=dx%+dw%-6
  406.   LET p%(7)=dy%+dh%-12
  407.   LET p%(8)=3
  408.   LET smfdb%(0)=VARPTR(info$)
  409.   BITBLT smfdb%(),dmfdb%(),p%()
  410. RETURN
  411. '
  412. '
  413. '  SECTION : Generate New HyperSystem
  414. ' ------------------------------------
  415. '
  416. > PROCEDURE generate_hypersystem
  417.   ' PURPOSE : Allows the user to select which window he/she would
  418.   '           like to use as a title window.
  419.   '
  420.   LOCAL button%
  421.   ALERT 2,"Generate HyperSystem....|Please Select a Title Window|for this new system.",3," Graphic | Text | Abort! ",button%
  422.   IF button%=1
  423.     GOSUB file_select("Load Graphic File: ","*.*",FALSE)
  424.     IF EXIST(filename$)
  425.       GOSUB prepare_hypersystem
  426.       GOSUB load_graphic(filename$)
  427.     ENDIF
  428.   ELSE IF button%=2
  429.     GOSUB file_select("Load Text File: ","*.*",TRUE)
  430.     IF EXIST(filename$)
  431.       GOSUB prepare_hypersystem
  432.       GOSUB load_text(filename$)
  433.     ENDIF
  434.   ENDIF
  435. RETURN
  436. '
  437. > PROCEDURE prepare_hypersystem
  438.   ' PURPOSE : Prepares hypersystem before system generation.
  439.   '
  440.   GOSUB reset_datastructure
  441.   GOSUB find_slot
  442.   GOSUB close_old(handle&)
  443.   MENU 16,3  ! Activate Save
  444.   MENU 21,3  ! Activate Add Button
  445.   LET file$(posit%)=filename$
  446. RETURN
  447. '
  448. '
  449. '  SECTION : Add Button to Window
  450. ' --------------------------------
  451. '
  452. > PROCEDURE add_button
  453.   ' PURPOSE : Identifies the current open window and determines which
  454.   '           button type the user is allowed to draw on the screen.
  455.   '
  456.   SELECT type$(posit%)
  457.   CASE "G"
  458.     GOSUB add_graphic_description
  459.   CASE "T"
  460.     GOSUB add_text_button
  461.   ENDSELECT
  462. RETURN
  463. '
  464. > PROCEDURE add_graphic_description
  465.   ' PURPOSE : allows the user to give the new button a name.
  466.   '
  467.   LOCAL tree%,button%,dx%,dy%,dw%,dh%,desc$
  468.   SPRITE cursor$
  469.   ~RSRC_GADDR(0,1,tree%)
  470.   ~FORM_CENTER(tree%,dx%,dy%,dw%,dh%)
  471.   ~OBJC_CHANGE(tree%,5,0,dx%,dy%,dw%,dh%,0,0)
  472.   ~OBJC_CHANGE(tree%,6,0,dx%,dy%,dw%,dh%,0,0)
  473.   ~FORM_DIAL(0,dx%,dy%,dw%,dh%,dx%,dy%,dw%,dh%)
  474.   ~OBJC_DRAW(tree%,0,3,dx%,dy%,dw%,dh%)
  475.   LET button%=FORM_DO(tree%,3)
  476.   ~FORM_DIAL(3,dx%,dy%,dw%,dh%,dx%,dy%,dw%,dh%)
  477.   GOSUB do_redraw(0)
  478.   IF button%=5
  479.     LET desc$=CHAR{{OB_SPEC(tree%,3)}}
  480.     GOSUB add_graphic_button(desc$)
  481.   ENDIF
  482. RETURN
  483. '
  484. > PROCEDURE add_graphic_button(desc$)
  485.   ' PURPOSE : Allows the user to move a button in the window to its
  486.   '           final location.
  487.   '
  488.   ALERT 2,"POSITION BUTTON!|By clicking and holding|with the left button you|may position the button.",1," Ok! ",void%
  489.   LOCAL x1%,y1%,x2%,y2%,x3%,y3%,x4%,y4%,x%,y%,b%,h%,dx%,dy%,button%,loop%
  490.   ~VQT_EXTENT(desc$,x1%,y1%,x2%,y2%,x3%,y3%,x4%,y4%)
  491.   WHILE MOUSEK<>1                       ! Wait until left button is pressed
  492.   WEND
  493.   DEFMOUSE 3                            ! Redefine mouse as crosshair
  494.   ~WIND_GET(handle&,4,x%,y%,b%,h%)      ! Get current window size
  495.   IF b%>scrb%-x%                        ! Is window half on half off the screen
  496.     LET b%=PRED(scrb%-x%)               ! Reduce width to visible half of window
  497.   ENDIF
  498.   '  Draw button on the screen
  499.   ' ----------------------------------
  500.   GET x%,y%,b%+x%,h%+y%,block$          ! Store window area in block$
  501.   WHILE MOUSEK=1                        ! Loop while left button is pressed
  502.     LET dx%=MOUSEX                      ! Store top x co-ordinate of box
  503.     LET dy%=MOUSEY                      ! Store top y co-ordinate of box
  504.     PUT x%,y%,block$                    ! Replace window area with block$
  505.     PBOX dx%-5,dy%-4,dx%+x3%+5,dy%+y3%-3  ! Draw box on screen
  506.     TEXT dx%,dy%+10,desc$               ! Draw text inside box
  507.     VSYNC
  508.     WHILE dx%=MOUSEX AND dy%=MOUSEY AND MOUSEK=1
  509.     WEND                                ! Wait until mouse is moved
  510.   WEND
  511.   DEFMOUSE 0                            ! Define mouse as pointer
  512.   '  Validate position and box size
  513.   ' --------------------------------
  514.   IF dx%-5<0 OR dx%+x3%+5>b% OR dy%-4<0 OR dy%+y3%-3>h%
  515.     ALERT 1,"Button Outside Window|Please try again!",2," Abort! | Ok! ",button%
  516.     GOSUB do_redraw(0)
  517.     IF button%=2                        ! YES, Try drawing button again
  518.       GOSUB add_graphic_button(desc$)
  519.     ENDIF
  520.   ENDIF
  521.   '  Store box position and box size
  522.   ' ---------------------------------
  523.   IF button%<>2
  524.     FOR loop%=1 TO 25
  525.       EXIT IF desc$(posit%,loop%)=""            ! Find empty slot for window
  526.     NEXT loop%
  527.     IF loop%=26
  528.       ALERT 2,"NO MORE BUTTONS AVAILABLE!|There are no more buttons|available for this window.",1," Abort! ",button%
  529.     ELSE
  530.       LET desc$(posit%,loop%)=desc$               ! Store button description
  531.       LET xbut%(posit%,loop%)=dx%+hpos%(posit%)   ! Store button x position
  532.       LET ybut%(posit%,loop%)=dy%+vpos%(posit%)   ! Store button y position
  533.     ENDIF
  534.   ENDIF
  535. RETURN
  536. '
  537. > PROCEDURE add_text_button
  538.   ' PURPOSE : Allows the user to add a button to a text window by
  539.   '           dragging a box around a text phrase.
  540.   '
  541.   LOCAL button1%,button2%,bx%,by%,dx%,dy%,x%,y%,b%,h%,loop%
  542.   ALERT 1,"Add New Button:|Drag box around text phrase.",2," Abort | Ok!",button1%
  543.   IF button1%=2
  544.     WHILE MOUSEK<>1                  ! Wait until left mouse button is pressed
  545.     WEND
  546.     LET button2%=0                   ! Clear button2%
  547.     LET bx%=MOUSEX                   ! Store top x co-ordinate of box
  548.     LET by%=MOUSEY                   ! Store top y co-ordinate of box
  549.     DEFMOUSE 3                       ! Redefine mouse as cross hair
  550.     ~WIND_GET(handle&,4,x%,y%,b%,h%) ! Get current window size
  551.     IF b%>scrb%-x%                   ! Is window half on half off the screen
  552.       LET b%=PRED(scrb%-x%)          ! Reduce width to visible half of window
  553.     ENDIF
  554.     '  Draw expanding box on the screen
  555.     ' ----------------------------------
  556.     GET x%,y%,b%+x%,h%+y%,block$     ! Store window area in block$
  557.     WHILE MOUSEK=1                   ! Loop while left button is pressed
  558.       LET dx%=MOUSEX                 ! Store bottom x co-ordinate of box
  559.       LET dy%=MOUSEY                 ! Store bottom y co-ordinate of box
  560.       PUT x%,y%,block$               ! Replace window area with block$
  561.       BOX bx%,by%,dx%,dy%            ! Draw box on screen
  562.       WHILE dx%=MOUSEX AND dy%=MOUSEY AND MOUSEK=1
  563.       WEND                           ! Wait until mouse is moved
  564.     WEND
  565.     DEFMOUSE 0                       ! Define mouse as pointer
  566.     '  Validate position and box size
  567.     ' --------------------------------
  568.     IF bx%>=dx% OR by%>=dy%
  569.       ALERT 1,"Invalid Text Button Size|Please try again!",2," Abort! | Ok! ",button2%
  570.     ELSE IF bx%<0 OR by%<0 OR dx%>b% OR dy%>h%
  571.       ALERT 1,"Text Button Outside Window|Please try again!",2," Abort! | Ok! ",button2%
  572.     ENDIF
  573.     PUT x%,y%,block$                 ! Replace window area with block$
  574.     IF button2%=2                    ! YES, Try drawing button again
  575.       GOSUB add_text_button
  576.     ENDIF
  577.     '  Store box position and box size
  578.     ' ---------------------------------
  579.     IF button2%<>2
  580.       FOR loop%=1 TO 25
  581.         EXIT IF desc$(posit%,loop%)=""     ! Find empty slot for data
  582.       NEXT loop%
  583.       IF loop%=26
  584.         ALERT 2,"NO MORE BUTTONS AVAILABLE!|There are no more buttons|available for this window.",1," Abort! ",button%
  585.       ELSE
  586.         ' store box size as string spaces
  587.         LET desc$(posit%,loop%)=SPACE$(((dx%+4)-bx%) DIV chrbb%)
  588.         IF bx%>4                             ! In the middle of the window
  589.           LET bx%=((bx%-4) DIV chrbb%)+1     ! Resize box x position
  590.         ELSE                                 ! At the left most pos of the window
  591.           LET bx%=((bx%-4) DIV chrbb%)       ! Resize box x position
  592.         ENDIF
  593.         LET by%=((by%+4) DIV chrbh%)+1       ! Resize box y position
  594.         LET xbut%(posit%,loop%)=bx%+hpos%(posit%) ! Store button x position
  595.         LET ybut%(posit%,loop%)=by%+vpos%(posit%) ! Store button y position
  596.         GOSUB do_redraw(0)
  597.       ENDIF
  598.     ENDIF
  599.   ENDIF
  600. RETURN
  601. '
  602. '
  603. '  SECTION : Find & Evaluate Button
  604. ' ----------------------------------
  605. '
  606. > PROCEDURE find_button
  607.   ' PURPOSE : Locate button which was clicked.
  608.   '
  609.   LOCAL loop%,x1%,y1%,x2%,y2%,x3%,y3%,x4%,y4%,dx%,dy%
  610.   IF MOUSEK=1
  611.     WHILE MOUSEK=1
  612.     WEND
  613.     FOR loop%=1 TO 25
  614.       IF desc$(posit%,loop%)<>""
  615.         ' Get button x,y position and button size.
  616.         ' ----------------------------------------
  617.         ~VQT_EXTENT(desc$(posit%,loop%),x1%,y1%,x2%,y2%,x3%,y3%,x4%,y4%)
  618.         LET dx%=SUB(xbut%(posit%,loop%),hpos%(posit%))
  619.         LET dy%=SUB(ybut%(posit%,loop%),vpos%(posit%))
  620.         SELECT type$(posit%)
  621.         CASE "T"
  622.           IF (MOUSEX>MUL(dx%,chrbb%) AND MOUSEX<ADD(MUL(dx%,chrbb%),x3%)) AND (MOUSEY>SUB(MUL(dy%,chrbh%),18) AND MOUSEY<MUL(dy%,chrbh%))
  623.             ' Invert found button
  624.             ' -------------------
  625.             GET xpos%(posit%)+MUL(dx%,chrbb%),ypos%(posit%)+PRED(MUL(dy%,chrbh%))+20,xpos%(posit%)+ADD(MUL(dx%,chrbb%),x3%),ypos%(posit%)+PRED(MUL(dy%,chrbh%))+34,s$
  626.             PUT xpos%(posit%)+MUL(dx%,chrbb%),ypos%(posit%)+MUL(dy%,chrbh%)+20,s$,10
  627.             GOSUB process_button(loop%)
  628.           ENDIF
  629.         CASE "G"
  630.           IF (MOUSEX>SUB(dx%,5) AND MOUSEX<ADD(ADD(dx%,x3%),5)) AND (MOUSEY>SUB(dy%,4) AND MOUSEY<SUB(ADD(dy%,y3%),3))
  631.             ' Invert found button
  632.             ' -------------------
  633.             GET xpos%(posit%)+SUB(dx%,3),ypos%(posit%)+dy%+34,xpos%(posit%)+ADD(ADD(dx%,x3%),5),ypos%(posit%)+ADD(dy%,y3%)+33,s$
  634.             PUT xpos%(posit%)+SUB(dx%,3),ypos%(posit%)+dy%+34,s$,10
  635.             GOSUB process_button(loop%)
  636.           ENDIF
  637.         ENDSELECT
  638.       ENDIF
  639.     NEXT loop%
  640.   ENDIF
  641. RETURN
  642. '
  643. > PROCEDURE process_button(index%)
  644.   ' PURPOSE : Process button for correct event.
  645.   '
  646.   GOSUB modified_text
  647.   IF head%(posit%,index%)=0
  648.     IF type$(posit%)="T" OR type$(posit%)="G"
  649.       GOSUB add_window(index%)
  650.     ENDIF
  651.   ELSE
  652.     GOSUB display_next(index%)
  653.   ENDIF
  654. RETURN
  655. '
  656. > PROCEDURE add_window(index%)
  657.   ' PURPOSE : Draw dialog box to allow the user to select a
  658.   '           Text window, Graphic window or play a Sample.
  659.   '
  660.   LOCAL tree%,dx%,dy%,dw%,dh%,button%
  661.   SPRITE cursor$
  662.   ~RSRC_GADDR(0,2,tree%)
  663.   ~FORM_CENTER(tree%,dx%,dy%,dw%,dh%)
  664.   ~OBJC_CHANGE(tree%,10,0,dx%,dy%,dw%,dh%,0,0)
  665.   ~OBJC_CHANGE(tree%,11,0,dx%,dy%,dw%,dh%,0,0)
  666.   ~FORM_DIAL(0,dx%,dy%,dw%,dh%,dx%,dy%,dw%,dh%)
  667.   ~OBJC_DRAW(tree%,0,3,dx%,dy%,dw%,dh%)
  668.   LET button%=FORM_DO(tree%,0)
  669.   ~FORM_DIAL(3,dx%,dy%,dw%,dh%,dx%,dy%,dw%,dh%)
  670.   IF button%=10
  671.     GOSUB add_window2(index%,tree%)
  672.   ENDIF
  673.   ON MENU
  674.   GOSUB do_redraw(0)
  675. RETURN
  676. '
  677. > PROCEDURE add_window2(index%,tree%)
  678.   ' PURPOSE : Allows the user to load the next window event.
  679.   '
  680.   LET crea_date$(posit%)=DATE$
  681.   LET crea_time$(posit%)=TIME$
  682.   GOSUB find_slot
  683.   IF posit%=256
  684.     ALERT 1,"WINDOW LIMIT REACHED!|You have reached the window limit!",1," Sorry! ",button%
  685.     LET posit%=255
  686.   ELSE
  687.     IF OB_STATE(tree%,8)
  688.       GOSUB file_select("Load Text File: ","*.*",TRUE)
  689.       IF EXIST(filename$)
  690.         LET head%(old_posit%,index%)=posit%
  691.         LET tail%(posit%)=old_posit%
  692.         LET file$(posit%)=filename$
  693.         GOSUB load_text(filename$)
  694.       ELSE
  695.         LET posit%=old_posit%
  696.       ENDIF
  697.     ELSE IF OB_STATE(tree%,4)
  698.       GOSUB file_select("Load Graphic File: ","*.*",FALSE)
  699.       IF EXIST(filename$)
  700.         LET head%(old_posit%,index%)=posit%
  701.         LET tail%(posit%)=old_posit%
  702.         LET file$(posit%)=filename$
  703.         GOSUB load_graphic(filename$)
  704.       ELSE
  705.         LET posit%=old_posit%
  706.       ENDIF
  707.     ELSE IF OB_STATE(tree%,6)
  708.       GOSUB file_select("Load Sample File: ","*.*",FALSE)
  709.       IF EXIST(filename$)
  710.         LET head%(old_posit%,index%)=posit%
  711.         LET tail%(posit%)=old_posit%
  712.         LET file$(posit%)=filename$
  713.         LET type$(posit%)="S"
  714.         GOSUB load_sample(filename$)
  715.       ENDIF
  716.       LET posit%=old_posit%
  717.     ENDIF
  718.   ENDIF
  719. RETURN
  720. '
  721. > PROCEDURE find_slot
  722.   ' PURPOSE : Find empty slot for new window event.
  723.   '
  724.   LET old_posit%=posit%
  725.   FOR posit%=1 TO 255
  726.     EXIT IF type$(posit%)=""
  727.   NEXT posit%
  728. RETURN
  729. '
  730. > PROCEDURE display_next(index%)
  731.   ' PURPOSE : If a button already has a link to a new event this
  732.   '           procedure will activate that next event.
  733.   '
  734.   LET posit%=head%(posit%,index%)
  735.   SELECT type$(posit%)
  736.   CASE "T"
  737.     GOSUB load_text(file$(posit%))
  738.   CASE "S"
  739.     GOSUB load_sample(file$(posit%))
  740.     LET posit%=tail%(posit%)
  741.   CASE "G"
  742.     GOSUB load_graphic(file$(posit%))
  743.   ENDSELECT
  744. RETURN
  745. '
  746. '
  747. '  SECTION : Modify Existing Button
  748. ' ----------------------------------
  749. '
  750. > PROCEDURE find_button_modify
  751.   ' PURPOSE : Locate modify button which was clicked.
  752.   '
  753.   LET found!=FALSE
  754.   ALERT 1,"MODIFY EXISTING BUTTON!|Please Click on button|to modify.",2," Abort! | Ok! ",button%
  755.   IF button%=2
  756.     WHILE MOUSEK=0
  757.     WEND
  758.     IF MOUSEK=1
  759.       FOR found%=1 TO 25
  760.         IF desc$(posit%,found%)<>""
  761.           ' Get button x,y position and button size.
  762.           ' ----------------------------------------
  763.           ~VQT_EXTENT(desc$(posit%,found%),x1%,y1%,x2%,y2%,x3%,y3%,x4%,y4%)
  764.           LET dx%=SUB(xbut%(posit%,found%),hpos%(posit%))
  765.           LET dy%=SUB(ybut%(posit%,found%),vpos%(posit%))
  766.           SELECT type$(posit%)
  767.           CASE "T","S"
  768.             IF (MOUSEX>MUL(dx%,chrbb%) AND MOUSEX<ADD(MUL(dx%,chrbb%),x3%)) AND (MOUSEY>SUB(MUL(dy%,chrbh%),18) AND MOUSEY<MUL(dy%,chrbh%))
  769.               GOSUB modify_text_button
  770.             ENDIF
  771.           CASE "G","S"
  772.             IF (MOUSEX>SUB(dx%,5) AND MOUSEX<ADD(ADD(dx%,x3%),5)) AND (MOUSEY>SUB(dy%,4) AND MOUSEY<SUB(ADD(dy%,y3%),3))
  773.               ' Invert found button
  774.               ' -------------------
  775.               GET xpos%(posit%)+SUB(dx%,3),ypos%(posit%)+dy%+34,xpos%(posit%)+ADD(ADD(dx%,x3%),5),ypos%(posit%)+ADD(dy%,y3%)+33,s$
  776.               PUT xpos%(posit%)+SUB(dx%,3),ypos%(posit%)+dy%+34,s$,10
  777.               GOSUB modify_graphic_button
  778.             ENDIF
  779.           ENDSELECT
  780.         ENDIF
  781.       NEXT found%
  782.       IF found!=FALSE
  783.         ALERT 2,"BUTTON NOT SELECTED!|Please, click on a button.",2," Abort! | Retry! ",button1%
  784.         IF button1%=2
  785.           GOSUB find_button_modify
  786.         ENDIF
  787.       ENDIF
  788.     ENDIF
  789.   ENDIF
  790. RETURN
  791. '
  792. > PROCEDURE modify_text_button
  793.   ' PURPOSE : Allows the user to drag a box around a text phrase.
  794.   '
  795.   ALERT 1,"Draw New Text Button Position:|Drag box around text phrase.",2," Abort | Ok!",butt%
  796.   IF butt%=2
  797.     LET found!=TRUE
  798.     WHILE MOUSEK<>1
  799.     WEND
  800.     LET ans%=0
  801.     LET bx%=MOUSEX
  802.     LET by%=MOUSEY
  803.     DEFMOUSE 3
  804.     ~WIND_GET(handle&,4,x%,y%,b%,h%)
  805.     IF b%>scrb%-x%
  806.       LET b%=PRED(scrb%-x%)
  807.     ENDIF
  808.     '  Draw expanding box on the screen
  809.     ' ----------------------------------
  810.     GET x%,y%,b%+x%,h%+y%,block$
  811.     WHILE MOUSEK=1
  812.       LET dx%=MOUSEX
  813.       LET dy%=MOUSEY
  814.       PUT x%,y%,block$
  815.       BOX bx%,by%,dx%,dy%
  816.       WHILE dx%=MOUSEX AND dy%=MOUSEY AND MOUSEK=1
  817.       WEND
  818.     WEND
  819.     '  Validate position and box size
  820.     ' --------------------------------
  821.     DEFMOUSE 0
  822.     IF bx%>=dx% OR by%>=dy%
  823.       ALERT 1,"Invalid Text Button Size|Please try again!",2," Abort! | Ok! ",ans%
  824.     ENDIF
  825.     IF bx%<0 OR by%<0 OR dx%>b% OR dy%>h%
  826.       ALERT 1,"Text Button Outside Window|Please try again!",2," Abort! | Ok! ",ans%
  827.     ENDIF
  828.     PUT x%,y%,block$
  829.     IF ans%=2
  830.       GOSUB modify_text_button
  831.     ENDIF
  832.     '  Store box new position and box size
  833.     ' -------------------------------------
  834.     IF ans%<>2
  835.       LET desc$(posit%,found%)=SPACE$(((dx%+4)-bx%) DIV chrbb%)
  836.       IF bx%>4
  837.         LET bx%=((bx%-4) DIV chrbb%)+1
  838.       ELSE
  839.         LET bx%=((bx%-4) DIV chrbb%)
  840.       ENDIF
  841.       LET by%=((by%+4) DIV chrbh%)+1
  842.       LET xbut%(posit%,found%)=bx%+hpos%(posit%)
  843.       LET ybut%(posit%,found%)=by%+vpos%(posit%)
  844.       GOSUB do_redraw(0)
  845.     ENDIF
  846.   ENDIF
  847. RETURN
  848. '
  849. > PROCEDURE modify_graphic_button
  850.   ' PURPOSE : allows the user to change the description of an
  851.   '           existing graphic window button.
  852.   '
  853.   ~RSRC_GADDR(0,1,tree%)
  854.   CHAR{{OB_SPEC(tree%,3)}}=desc$(posit%,found%)
  855.   ~FORM_CENTER(tree%,dx%,dy%,dw%,dh%)
  856.   ~OBJC_CHANGE(tree%,5,0,dx%,dy%,dw%,dh%,0,0)
  857.   ~OBJC_CHANGE(tree%,6,0,dx%,dy%,dw%,dh%,0,0)
  858.   ~FORM_DIAL(0,dx%,dy%,dw%,dh%,dx%,dy%,dw%,dh%)
  859.   ~OBJC_DRAW(tree%,0,6,dx%,dy%,dw%,dh%)
  860.   LET but%=FORM_DO(tree%,3)
  861.   ~FORM_DIAL(3,dx%,dy%,dw%,dh%,dx%,dy%,dw%,dh%)
  862.   GOSUB do_redraw(0)
  863.   IF but%=5
  864.     LET desc$=CHAR{{OB_SPEC(tree%,3)}}
  865.     GOSUB modify_button(desc$)
  866.   ENDIF
  867. RETURN
  868. '
  869. > PROCEDURE modify_button(desc$)
  870.   ' PURPOSE : Allows the user to change the position of an
  871.   '           existing button.
  872.   '
  873.   ALERT 2,"RE-POSITION BUTTON!|By clicking and holding|with the left button you|may re-position the button.",1," Ok! ",void%
  874.   LET found!=TRUE
  875.   ~VQT_EXTENT(desc$,x1%,y1%,x2%,y2%,x3%,y3%,x4%,y4%)
  876.   WHILE MOUSEK<>1
  877.   WEND
  878.   DEFMOUSE 3
  879.   ~WIND_GET(handle&,4,x%,y%,b%,h%)
  880.   IF b%>scrb%-x%
  881.     LET b%=PRED(scrb%-x%)
  882.   ENDIF
  883.   LET desc$(posit%,found%)=""
  884.   GOSUB do_redraw(0)
  885.   '  Draw button on the screen
  886.   ' ----------------------------------
  887.   GET x%,y%,b%+x%,h%+y%,block$
  888.   WHILE MOUSEK=1
  889.     LET dx%=MOUSEX
  890.     LET dy%=MOUSEY
  891.     VSYNC
  892.     PUT x%,y%,block$
  893.     PBOX dx%-5,dy%-4,dx%+x3%+5,dy%+y3%-3
  894.     TEXT dx%,dy%+10,desc$
  895.     WHILE dx%=MOUSEX AND dy%=MOUSEY AND MOUSEK=1
  896.     WEND
  897.   WEND
  898.   DEFMOUSE 0
  899.   '  Validate position and box size
  900.   ' --------------------------------
  901.   IF dx%-5<0 OR dx%+x3%+5>b% OR dy%-4<0 OR dy%+y3%-3>h%
  902.     ALERT 1,"Button Outside Window|Please try again!",2," Abort! | Ok! ",ans%
  903.     GOSUB do_redraw(0)
  904.     '  Store box position and box size
  905.     ' ---------------------------------
  906.     IF ans%=2
  907.       GOSUB modify_button(desc$)
  908.     ENDIF
  909.   ELSE
  910.     LET desc$(posit%,found%)=desc$
  911.     LET xbut%(posit%,found%)=dx%+hpos%(posit%)
  912.     LET ybut%(posit%,found%)=dy%+vpos%(posit%)
  913.   ENDIF
  914. RETURN
  915. '
  916. '
  917. '  SECTION : Erase Existing Button
  918. ' ---------------------------------
  919. '
  920. > PROCEDURE erase_button
  921.   ' PURPOSE : Locate and erase button which was clicked.
  922.   '
  923.   LET found!=FALSE
  924.   ALERT 1,"REMOVE EXISTING BUTTON!|Please Click on button to|remove. It will also remove|any connecting windows|to this button.",2," Abort! | Ok! ",button%
  925.   IF button%=2
  926.     ALERT 2,"WARNING - This operation will|remove all windows linked|to this button.",2," Abort! | Do it! ",button%
  927.     IF button%=2
  928.       WHILE MOUSEK=0
  929.       WEND
  930.       IF MOUSEK=1
  931.         FOR found%=1 TO 25
  932.           IF desc$(posit%,found%)<>""
  933.             ' Get button x,y position and button size.
  934.             ' ----------------------------------------
  935.             ~VQT_EXTENT(desc$(posit%,found%),x1%,y1%,x2%,y2%,x3%,y3%,x4%,y4%)
  936.             LET dx%=SUB(xbut%(posit%,found%),hpos%(posit%))
  937.             LET dy%=SUB(ybut%(posit%,found%),vpos%(posit%))
  938.             SELECT type$(posit%)
  939.             CASE "T","S"
  940.               IF (MOUSEX>MUL(dx%,chrbb%) AND MOUSEX<ADD(MUL(dx%,chrbb%),x3%)) AND (MOUSEY>SUB(MUL(dy%,chrbh%),18) AND MOUSEY<MUL(dy%,chrbh%))
  941.                 GOSUB remove_links
  942.               ENDIF
  943.             CASE "G","S"
  944.               IF (MOUSEX>SUB(dx%,5) AND MOUSEX<ADD(ADD(dx%,x3%),5)) AND (MOUSEY>SUB(dy%,4) AND MOUSEY<SUB(ADD(dy%,y3%),3))
  945.                 GOSUB remove_links
  946.               ENDIF
  947.             ENDSELECT
  948.           ENDIF
  949.         NEXT found%
  950.       ENDIF
  951.       IF found!=FALSE
  952.         ALERT 2,"BUTTON NOT SELECTED!|Please, click on a button.",2," Abort! | Retry! ",button1%
  953.         IF button1%=2
  954.           GOSUB erase_button
  955.         ENDIF
  956.       ENDIF
  957.     ENDIF
  958.   ENDIF
  959. RETURN
  960. '
  961. > PROCEDURE remove_links
  962.   ' PURPOSE : Removes any links related to this button.
  963.   '
  964.   LET found!=TRUE
  965.   LET mark1%=posit%
  966.   LET old_posit%=posit%
  967.   LET posit%=head%(posit%,found%)
  968.   FOR loop%=found% TO 24
  969.     LET xbut%(old_posit%,loop%)=xbut%(old_posit%,SUCC(loop%))
  970.     LET ybut%(old_posit%,loop%)=ybut%(old_posit%,SUCC(loop%))
  971.     LET desc$(old_posit%,loop%)=desc$(old_posit%,SUCC(loop%))
  972.     LET head%(old_posit%,loop%)=head%(old_posit%,SUCC(loop%))
  973.   NEXT loop%
  974.   LET xbut%(old_posit%,25)=0
  975.   LET ybut%(old_posit%,25)=0
  976.   LET desc$(old_posit%,25)=""
  977.   LET head%(old_posit%,25)=0
  978.   IF posit%>0
  979.     DO
  980.       FOR loop%=1 TO 25
  981.         EXIT IF head%(posit%,loop%)<>0
  982.       NEXT loop%
  983.       IF loop%<26
  984.         IF head%(posit%,loop%)<>0
  985.           LET old_posit%=posit%
  986.           LET posit%=head%(posit%,loop%)
  987.           LET xbut%(old_posit%,loop%)=0
  988.           LET ybut%(old_posit%,loop%)=0
  989.           LET desc$(old_posit%,loop%)=""
  990.           LET head%(old_posit%,loop%)=0
  991.         ENDIF
  992.       ELSE
  993.         GOSUB clear_record
  994.       ENDIF
  995.     LOOP UNTIL posit%=mark1%
  996.   ENDIF
  997.   LET posit%=mark1%
  998.   GOSUB do_redraw(0)
  999. RETURN
  1000. '
  1001. > PROCEDURE clear_record
  1002.   ' PURPOSE : clears an existing record.
  1003.   '
  1004.   LET tail_posit%=tail%(posit%)
  1005.   LET xpos%(posit%)=50
  1006.   LET ypos%(posit%)=50
  1007.   LET wsiz%(posit%)=150
  1008.   LET hsiz%(posit%)=150
  1009.   LET hpos%(posit%)=0
  1010.   LET vpos%(posit%)=0
  1011.   LET crea_date$(posit%)=""
  1012.   LET crea_time$(posit%)=""
  1013.   LET type$(posit%)=""
  1014.   LET file$(posit%)=""
  1015.   LET tail%(posit%)=0
  1016.   FOR i%=1 TO 25
  1017.     LET xbut%(posit%,i%)=0
  1018.     LET ybut%(posit%,i%)=0
  1019.     LET desc$(posit%,i%)=""
  1020.     LET head%(posit%,i%)=0
  1021.   NEXT i%
  1022.   LET posit%=tail_posit%
  1023. RETURN
  1024. '
  1025. '
  1026. '  SECTION : Draw buttons
  1027. ' ------------------------
  1028. '
  1029. > PROCEDURE draw_button
  1030.   MENU 22,2  ! Modify Button
  1031.   MENU 23,2  ! Erase Button
  1032.   LET loop%=0
  1033.   REPEAT
  1034.     INC loop%
  1035.     IF desc$(posit%,loop%)<>""
  1036.       MENU 22,3  ! Modify Button
  1037.       MENU 23,3  ! Erase Button
  1038.       ~VQT_EXTENT(desc$(posit%,loop%),x1%,y1%,x2%,y2%,x3%,y3%,x4%,y4%)
  1039.       LET dx%=SUB(xbut%(posit%,loop%),hpos%(posit%))
  1040.       LET dy%=SUB(ybut%(posit%,loop%),vpos%(posit%))
  1041.       SELECT type$(posit%)
  1042.       CASE "G"
  1043.         PBOX SUB(dx%,5),SUB(dy%,4),ADD(ADD(dx%,x3%),5),SUB(ADD(dy%,y3%),3)
  1044.         TEXT dx%,ADD(dy%,10),desc$(posit%,loop%)
  1045.       CASE "T"
  1046.         LINE MUL(dx%,chrbb%),PRED(MUL(dy%,chrbh%)),ADD(MUL(dx%,chrbb%),x3%),PRED(MUL(dy%,chrbh%))
  1047.         LINE MUL(dx%,chrbb%),MUL(dy%,chrbh%),ADD(MUL(dx%,chrbb%),x3%),MUL(dy%,chrbh%)
  1048.       ENDSELECT
  1049.     ENDIF
  1050.   UNTIL desc$(posit%,loop%)=""
  1051. RETURN
  1052. '
  1053. '
  1054. '  HyperText Load & Save Procedures
  1055. ' ----------------------------------
  1056. '
  1057. > PROCEDURE load_hypertext
  1058.   ' PURPOSE : Load HyperText Database file.
  1059.   '
  1060.   LOCAL button%,loop%,i%,size%,buts%
  1061.   GOSUB file_select("Load HyperSystem: ","*.HYP",FALSE)
  1062.   IF EXIST(filename$)
  1063.     GOSUB close_old(handle&)
  1064.     DEFMOUSE iomouse$
  1065.     GOSUB prepare_hypersystem
  1066.     OPEN "I",#1,filename$
  1067.     INPUT #1;ver$
  1068.     IF ver$<>"HyperGEM 1.0"
  1069.       CLOSE #1
  1070.       DEFMOUSE 0
  1071.       ALERT 1,"HyperGEM File Error!|This is not a valid|HyperGEM data file.",1," Error! ",void%
  1072.     ELSE
  1073.       INPUT #1;size%
  1074.       LET old_size%=size%
  1075.       FOR loop%=1 TO size%
  1076.         INPUT #1;xpos%(loop%),ypos%(loop%),wsiz%(loop%),hsiz%(loop%),hpos%(loop%),vpos%(loop%)
  1077.         INPUT #1;crea_date$(loop%),crea_time$(loop%),type$(loop%),file$(loop%),tail%(loop%)
  1078.         INPUT #1;buts%
  1079.         FOR i%=1 TO buts%
  1080.           INPUT #1;xbut%(loop%,i%),ybut%(loop%,i%),desc$(loop%,i%),head%(loop%,i%)
  1081.         NEXT i%
  1082.       NEXT loop%
  1083.       CLOSE #1
  1084.       DEFMOUSE 0
  1085.       MENU 13,3  ! Run HyperSystem
  1086.       MENU 16,3  ! Activate Save
  1087.       ALERT 1,"HyperSystem Loaded!",2," Run! | Ready! ",button%
  1088.       IF button%=1
  1089.         GOSUB run_hypertext
  1090.       ENDIF
  1091.     ENDIF
  1092.   ENDIF
  1093. RETURN
  1094. '
  1095. > PROCEDURE save_hypertext
  1096.   ' PURPOSE : Save HyperText Database file.
  1097.   '
  1098.   GOSUB file_select("Save HyperSystem: ","*.HYP",TRUE)
  1099.   IF EXIST(filename$)
  1100.     IF EXIST(LEFT$(filename$,LEN(filename$)-3)+"BAK")
  1101.       KILL LEFT$(filename$,LEN(filename$)-3)+"BAK"
  1102.     ENDIF
  1103.     IF EXIST(filename$)
  1104.       NAME filename$ AS LEFT$(filename$,LEN(filename$)-3)+"BAK"
  1105.     ENDIF
  1106.     DEFMOUSE iomouse$
  1107.     FOR size%=255 DOWNTO 1
  1108.       EXIT IF type$(size%)<>""
  1109.     NEXT size%
  1110.     LET old_size%=size%
  1111.     OPEN "O",#1,filename$
  1112.     WRITE #1;"HyperGEM 1.0",size%
  1113.     FOR loop%=1 TO size%
  1114.       WRITE #1;xpos%(loop%),ypos%(loop%),wsiz%(loop%),hsiz%(loop%),hpos%(loop%),vpos%(loop%)
  1115.       WRITE #1;crea_date$(loop%),crea_time$(loop%),type$(loop%),file$(loop%),tail%(loop%)
  1116.       FOR buts%=25 DOWNTO 1
  1117.         EXIT IF desc$(loop%,buts%)<>""
  1118.       NEXT buts%
  1119.       WRITE #1;buts%
  1120.       FOR i%=1 TO buts%
  1121.         WRITE #1;xbut%(loop%,i%),ybut%(loop%,i%),desc$(loop%,i%),head%(loop%,i%)
  1122.       NEXT i%
  1123.     NEXT loop%
  1124.     CLOSE #1
  1125.     DEFMOUSE 0
  1126.     ALERT 1,"HyperSystem Saved!",1," Ready! ",button%
  1127.     ON MENU
  1128.   ENDIF
  1129. RETURN
  1130. '
  1131. > PROCEDURE run_hypertext
  1132.   ' PURPOSE : Run HyperText Database file.
  1133.   '
  1134.   MENU 21,3  ! Activate Add Button
  1135.   LET posit%=1
  1136.   SELECT type$(posit%)
  1137.   CASE "G"
  1138.     GOSUB load_graphic(file$(posit%))
  1139.   CASE "T"
  1140.     GOSUB load_text(file$(posit%))
  1141.   ENDSELECT
  1142. RETURN
  1143. '
  1144. '
  1145. '  Text Editor Management Procedures
  1146. ' -----------------------------------
  1147. '
  1148. PROCEDURE load_text(filename$)
  1149.   ' PURPOSE : Load Text File.
  1150.   '
  1151.   VOID (0)=FRE(0)
  1152.   LET ygrap%=9                             ! set minimum text lines to nine
  1153.   FOR loop%=0 TO 4000
  1154.     LET txt$(loop%)=""                     ! clear text array
  1155.   NEXT loop%
  1156.   IF EXIST(filename$)
  1157.     LET extender$=RIGHT$(filename$,3)      ! NOTE: file extension
  1158.     DEFMOUSE iomouse$
  1159.     OPEN "I",#1,filename$                  ! open file
  1160.     RECALL #1,txt$(),-1,ygrap%             ! load text file
  1161.     CLOSE #1                               ! close file
  1162.   ENDIF
  1163.   IF ygrap%<9
  1164.     LET ygrap%=9                           ! set minimum text lines to nine
  1165.   ENDIF
  1166.   LET xgrap%=80                            ! set line length to 80 characters
  1167.   DEFMOUSE 0
  1168.   GOSUB open_window("T")                   ! open text window
  1169.   GOSUB modwind(handle&,xpos%(posit%),ypos%(posit%),wsiz%(posit%),hsiz%(posit%))
  1170.   LET tpox%=hpos%(posit%)                  ! set text home x position
  1171.   LET tpoy%=vpos%(posit%)                  ! set text home y position
  1172.   GOSUB cursor_resize
  1173.   GOSUB insert_key
  1174. RETURN
  1175. '
  1176. > PROCEDURE modified_text
  1177.   ' PURPOSE : Give the user the option to save modified text or to lose it!
  1178.   '
  1179.   LOCAL button%
  1180.   IF edited!=TRUE
  1181.     ALERT 1,"TEXT FILE MODIFIED!|Text File has been modified|but not saved!",2," Lose! | Save! ",button%
  1182.     LET edited!=FALSE
  1183.     IF button%=2
  1184.       GOSUB esc_key
  1185.     ENDIF
  1186.   ENDIF
  1187. RETURN
  1188. '
  1189. > PROCEDURE keyboard
  1190.   GOSUB menu_key
  1191.   IF type$(posit%)="T"
  1192.     ~WIND_GET(handle&,4,x%,y%,b%,h%)
  1193.     GOSUB draw_cursor(tpox%,tpoy%,FALSE)
  1194.     GOSUB enter_text
  1195.   ENDIF
  1196. RETURN
  1197. '
  1198. > PROCEDURE menu_key
  1199.   ' PURPOSE : Gets a keypress and checks to see if it is
  1200.   '           a menu event keypress and if it is activates
  1201.   '           the appropriate menu option.
  1202.   '
  1203.   LET menu_key%=MENU(14)
  1204.   IF menu_key%>4607 AND menu_key%<12801
  1205.     MENU OFF
  1206.     IF menu_key%=5888                    ! Alt I
  1207.       GOSUB hypergem_info
  1208.     ELSE IF menu_key%=8704               ! Alt G
  1209.       GOSUB generate_hypersystem
  1210.     ELSE IF menu_key%=4864               ! Alt R
  1211.       GOSUB run_hypertext
  1212.     ELSE IF menu_key%=9728               ! Alt L
  1213.       GOSUB load_hypertext
  1214.     ELSE IF menu_key%=7936               ! Alt S
  1215.       GOSUB save_hypertext
  1216.     ELSE IF menu_key%=4096               ! Alt Q
  1217.       GOSUB quit_program
  1218.     ELSE IF menu_key%=7680               ! Alt A
  1219.       GOSUB add_button
  1220.     ELSE IF menu_key%=4608               ! Alt E
  1221.       GOSUB erase_button
  1222.     ELSE IF menu_key%=12800              ! Alt M
  1223.       GOSUB find_button_modify
  1224.     ENDIF
  1225.   ENDIF
  1226. RETURN
  1227. '
  1228. > PROCEDURE enter_text
  1229.   ' PURPOSE : Lets the user add text to a text window.
  1230.   '
  1231.   LET key%=BYTE(MENU(14))           ! get ASCII key code
  1232.   IF key%>31 AND key%<127           ! restrict keyboard input range
  1233.     LET edited!=TRUE                ! text is being edited flag!
  1234.     IF tpox%>LEN(txt$(PRED(tpoy%))) ! is cursor at end of string
  1235.       LET txt$(PRED(tpoy%))=txt$(PRED(tpoy%))+SPACE$(tpox%-LEN(txt$(PRED(tpoy%))))
  1236.       IF tpox%=xgrap%               ! wrap around cursor to next line
  1237.         GOSUB return_key
  1238.       ENDIF
  1239.     ENDIF
  1240.     IF insert!=TRUE                 ! if insert mode
  1241.       LET txt$(PRED(tpoy%))=LEFT$(txt$(PRED(tpoy%)),PRED(tpox%))+CHR$(key%)+RIGHT$(txt$(PRED(tpoy%)),LEN(txt$(PRED(tpoy%)))-PRED(tpox%))
  1242.       GOSUB right_key
  1243.     ELSE                            ! else overwrite mode
  1244.       MID$(txt$(PRED(tpoy%)),tpox%)=CHR$(key%)
  1245.       GOSUB right_key
  1246.     ENDIF
  1247.   ELSE
  1248.     GOSUB text_functions
  1249.     GOSUB draw_cursor(tpox%,tpoy%,TRUE)
  1250.   ENDIF
  1251. RETURN
  1252. '
  1253. > PROCEDURE text_functions
  1254.   ' PURPOSE : Interprets keypresses for 'Return', 'BackSpace', 'Delete'
  1255.   '           'ESc Key', 'Insert', 'Down', 'Up', 'Left' & 'Right Key'
  1256.   '
  1257.   IF key%=13
  1258.     GOSUB return_key
  1259.   ELSE IF key%=8
  1260.     GOSUB backspace_key
  1261.   ELSE IF key%=127
  1262.     GOSUB delete_key
  1263.   ELSE IF key%=27
  1264.     GOSUB esc_key
  1265.   ENDIF
  1266.   SELECT MENU(14)
  1267.   CASE 20480
  1268.     GOSUB down_key
  1269.   CASE 18432
  1270.     GOSUB up_key
  1271.   CASE 19200 ! left
  1272.     GOSUB left_key
  1273.   CASE 19712 ! right
  1274.     GOSUB right_key
  1275.   CASE 20992 ! insert
  1276.     GOSUB insert_key
  1277.   ENDSELECT
  1278. RETURN
  1279. '
  1280. > PROCEDURE draw_cursor(tpox%,tpoy%,state!)
  1281.   ' PURPOSE : Calculates the cursor position from the text position.
  1282.   '           It works by converting text co-ordinates into graphic
  1283.   '            co-ordinates. ie. 25 X 80 = 400 X 640
  1284.   '
  1285.   LET curx%=ADD(x%,SUB(SUB(MUL(tpox%,chrbb%),8),MUL(hpos%(posit%),chrbb%)))
  1286.   LET cury%=ADD(y%,SUB(MUL(PRED(tpoy%),chrbh%),MUL(vpos%(posit%),chrbh%)))
  1287.   IF state!=TRUE
  1288.     SPRITE cursor$,curx%,cury%
  1289.   ELSE
  1290.     SPRITE cursor$
  1291.   ENDIF
  1292. RETURN
  1293. '
  1294. > PROCEDURE esc_key
  1295.   ' PURPOSE : Allows the user to save the edited text window to disk.
  1296.   '
  1297.   ALERT 1,"SAVE TEXT FILE!|Save this edited text file|to disk.|",2," Cancel | Ok! ",button%
  1298.   IF button%=2
  1299.     LET edited!=FALSE
  1300.     SPRITE cursor$
  1301.     GOSUB file_select("Save Text File: ","*.ASC",TRUE)
  1302.     '
  1303.     ' if the file already exists rename as filename.bak
  1304.     ' -------------------------------------------------
  1305.     IF EXIST(filename$)
  1306.       IF EXIST(LEFT$(filename$,LEN(filename$)-3)+"BAK")
  1307.         KILL LEFT$(filename$,LEN(filename$)-3)+"BAK"
  1308.       ENDIF
  1309.       IF EXIST(filename$)
  1310.         NAME filename$ AS LEFT$(filename$,LEN(filename$)-3)+"BAK"
  1311.       ENDIF
  1312.       DEFMOUSE iomouse$
  1313.       LET file$(posit%)=filename$
  1314.       OPEN "O",#1,filename$                        ! create text file
  1315.       STORE #1,txt$(),0 TO ygrap%                  ! save text
  1316.       CLOSE #1                                     ! close file
  1317.       DEFMOUSE 0
  1318.       ALERT 1,"Text File Saved!",1," Ok! ",void%
  1319.     ENDIF
  1320.   ENDIF
  1321. RETURN
  1322. '
  1323. > PROCEDURE insert_key
  1324.   ' PURPOSE : Set text editor mode to insert or to overwrite mode.
  1325.   '
  1326.   LET insert!=NOT (insert!)
  1327.   IF insert!=TRUE
  1328.     LET insert$="Insert   "
  1329.   ELSE
  1330.     LET insert$="Overwrite"
  1331.   ENDIF
  1332.   GOSUB wind_title(handle&," Text Window ")
  1333.   GOSUB wind_info(handle&,"Col:"+STR$(tpox%)+"  Row:"+STR$(tpoy%)+"  "+insert$)
  1334. RETURN
  1335. '
  1336. > PROCEDURE up_key
  1337.   ' PURPOSE : Move the cursor up one character position.
  1338.   '
  1339.   IF tpoy%>1
  1340.     DEC tpoy%
  1341.     GOSUB draw_cursor(tpox%,tpoy%,FALSE)
  1342.     ' Move the window down one character position.
  1343.     ' --------------------------------------------
  1344.     IF cury%=SUB(y%,16)
  1345.       LET vpos%(posit%)=MAX(PRED(vpos%(posit%)),0)
  1346.       IF b%>SUB(scrb%,x%)
  1347.         LET b%=SUB(scrb%,x%)
  1348.       ENDIF
  1349.       GET x%,y%,PRED(ADD(x%,b%)),SUB(ADD(y%,h%),17),block$
  1350.       PUT x%,ADD(y%,16),block$
  1351.       GOSUB draw_cursor(tpox%,tpoy%,FALSE)
  1352.       GOSUB do_redraw(1)
  1353.       GOSUB draw_button
  1354.       GOSUB calc_slid(handle&)
  1355.     ENDIF
  1356.   ENDIF
  1357. RETURN
  1358. '
  1359. > PROCEDURE left_key
  1360.   ' PURPOSE : Move the cursor left one character position.
  1361.   '
  1362.   IF tpox%>1
  1363.     DEC tpox%
  1364.     GOSUB draw_cursor(tpox%,tpoy%,FALSE)
  1365.     ' Move the window right one character position.
  1366.     ' ---------------------------------------------
  1367.     IF curx%=SUB(x%,8)
  1368.       LET hpos%(posit%)=MAX(PRED(hpos%(posit%)),0)
  1369.       GOSUB do_redraw(0)
  1370.     ENDIF
  1371.     GOSUB do_redraw(1)
  1372.   ENDIF
  1373. RETURN
  1374. '
  1375. > PROCEDURE down_key
  1376.   ' PURPOSE : Move the cursor down one character position.
  1377.   '
  1378.   IF tpoy%<ygrap%
  1379.     INC tpoy%
  1380.     GOSUB draw_cursor(tpox%,tpoy%,FALSE)
  1381.     ' Move the window up one character position.
  1382.     ' ------------------------------------------
  1383.     IF cury%=>SUB(ADD(h%,y%),2)
  1384.       LET vpos%(posit%)=MIN(SUCC(vpos%(posit%)),SUB(ygrap%,DIV(h%,chrbh%)))
  1385.       IF b%>SUB(scrb%,x%)
  1386.         LET b%=SUB(scrb%,x%)
  1387.       ENDIF
  1388.       GET x%,ADD(y%,16),PRED(ADD(x%,b%)),PRED(ADD(y%,h%)),block$
  1389.       PUT x%,y%,block$
  1390.       COLOR 0
  1391.       LINE 0,SUB(h%,2),b%,SUB(h%,2)
  1392.       COLOR 1
  1393.       GOSUB draw_cursor(tpox%,tpoy%,FALSE)
  1394.       GOSUB do_redraw(1)
  1395.       GOSUB draw_button
  1396.       GOSUB calc_slid(handle&)
  1397.     ENDIF
  1398.   ENDIF
  1399. RETURN
  1400. '
  1401. > PROCEDURE right_key
  1402.   ' PURPOSE : Move the cursor right one character position.
  1403.   '
  1404.   IF tpox%<xgrap%
  1405.     INC tpox%
  1406.     GOSUB draw_cursor(tpox%,tpoy%,FALSE)
  1407.     ' Move the window left one character position.
  1408.     ' ------------------------------------------
  1409.     IF curx%=>ADD(b%,x%)
  1410.       LET hpos%(posit%)=MIN(SUCC(hpos%(posit%)),SUB(xgrap%,DIV(b%,chrbb%)))
  1411.       GOSUB do_redraw(0)
  1412.     ENDIF
  1413.     GOSUB do_redraw(1)
  1414.   ENDIF
  1415. RETURN
  1416. '
  1417. > PROCEDURE return_key
  1418.   ' PURPOSE : code for activation of return key.
  1419.   '
  1420.   LOCAL temp%
  1421.   ' handle insert mode with return.
  1422.   IF insert!=TRUE
  1423.     IF tpox%<=LEN(txt$(PRED(tpoy%))) AND tpox%>1! cursor in middle of line so split line
  1424.       INSERT txt$(tpoy%)=RIGHT$(txt$(PRED(tpoy%)),LEN(txt$(PRED(tpoy%)))-PRED(tpox%))
  1425.       LET txt$(PRED(tpoy%))=LEFT$(txt$(PRED(tpoy%)),PRED(tpox%))
  1426.     ELSE IF tpox%=1                         ! insert blank line on current line
  1427.       INSERT txt$(PRED(tpoy%))=""
  1428.     ELSE IF tpox%>LEN(txt$(PRED(tpoy%)))    ! insert blank line on next line
  1429.       INSERT txt$(tpoy%)=""
  1430.     ENDIF
  1431.     INC ygrap%
  1432.     ' move any buttons which are further down the document or equal to the
  1433.     ' current line down one character position.
  1434.     ' --------------------------------------------------------------------
  1435.     FOR loop%=1 TO 25
  1436.       IF ybut%(posit%,loop%)>=tpoy%
  1437.         LET ybut%(posit%,loop%)=SUCC(ybut%(posit%,loop%))
  1438.       ENDIF
  1439.     NEXT loop%
  1440.   ENDIF
  1441.   LET tpox%=1
  1442.   LET temp%=hpos%(posit%)
  1443.   LET hpos%(posit%)=0
  1444.   ' tidy up
  1445.   GOSUB draw_cursor(tpox%,tpoy%,FALSE)
  1446.   GOSUB calc_slid(handle&)
  1447.   IF temp%>0 OR insert!=TRUE
  1448.     GOSUB do_redraw(0)
  1449.   ENDIF
  1450.   GOSUB down_key
  1451. RETURN
  1452. '
  1453. > PROCEDURE backspace_key
  1454.   ' PURPOSE : code for activation of backspace key.
  1455.   '
  1456.   IF tpox%>1 AND tpox%<=SUCC(LEN(txt$(PRED(tpoy%)))) ! cursor in middle of line
  1457.     LET txt$(PRED(tpoy%))=LEFT$(txt$(PRED(tpoy%)),SUB(tpox%,2))+RIGHT$(txt$(PRED(tpoy%)),LEN(txt$(PRED(tpoy%)))-PRED(tpox%))
  1458.     GOSUB left_key
  1459.   ELSE IF tpox%=1 AND tpoy%>1                     ! cursor at beginning of line
  1460.     ' move remaining line to previous line and remove current line.
  1461.     ' -------------------------------------------------------------
  1462.     LET tpox%=MAX(1,SUCC(LEN(txt$(tpoy%-2))))
  1463.     LET txt$(tpoy%-2)=txt$(tpoy%-2)+txt$(PRED(tpoy%))
  1464.     DELETE txt$(PRED(tpoy%))
  1465.     IF ygrap%>5 ! limit text size to a minimum of 5 lines
  1466.       DEC ygrap%
  1467.     ENDIF
  1468.     ' move any buttons which are further down the document or equal to the
  1469.     ' current line down one character position.
  1470.     ' --------------------------------------------------------------------
  1471.     FOR loop%=1 TO 25
  1472.       IF ybut%(posit%,loop%)>=tpoy%
  1473.         LET ybut%(posit%,loop%)=PRED(ybut%(posit%,loop%))
  1474.       ENDIF
  1475.     NEXT loop%
  1476.     GOSUB up_key
  1477.     GOSUB calc_slid(handle&)
  1478.     GOSUB do_redraw(0)
  1479.     GOSUB cursor_resize
  1480.   ENDIF
  1481.   GOSUB draw_cursor(tpox%,tpoy%,FALSE)
  1482. RETURN
  1483. '
  1484. > PROCEDURE delete_key
  1485.   ' PURPOSE : code for activation of delete key.
  1486.   '
  1487.   IF tpox%<=LEN(txt$(PRED(tpoy%)))
  1488.     LET txt$(PRED(tpoy%))=LEFT$(txt$(PRED(tpoy%)),PRED(tpox%))+RIGHT$(txt$(PRED(tpoy%)),LEN(txt$(PRED(tpoy%)))-tpox%)
  1489.     GOSUB do_redraw(1)
  1490.   ENDIF
  1491.   ' if cursor position is greater than line length then add next line
  1492.   ' to current line and remove next line.
  1493.   ' -----------------------------------------------------------------
  1494.   IF tpox%>LEN(txt$(PRED(tpoy%)))
  1495.     LET txt$(PRED(tpoy%))=txt$(PRED(tpoy%))+txt$(tpoy%)
  1496.     DELETE txt$(tpoy%)
  1497.     IF ygrap%>5
  1498.       DEC ygrap%
  1499.     ENDIF
  1500.     ' move any buttons which are further down the document or equal to the
  1501.     ' current line down one character position.
  1502.     ' --------------------------------------------------------------------
  1503.     FOR loop%=1 TO 25
  1504.       IF ybut%(posit%,loop%)>=tpoy%
  1505.         LET ybut%(posit%,loop%)=PRED(ybut%(posit%,loop%))
  1506.       ENDIF
  1507.     NEXT loop%
  1508.     GOSUB calc_slid(handle&)
  1509.     GOSUB do_redraw(0)
  1510.     GOSUB cursor_resize
  1511.   ENDIF
  1512. RETURN
  1513. '
  1514. '
  1515. '  General Load Picture Procedures
  1516. ' ---------------------------------
  1517. '
  1518. > PROCEDURE load_graphic(filename$)
  1519.   ' PURPOSE : identify graphic file and branch to appropriate routine
  1520.   '
  1521.   DEFMOUSE iomouse$
  1522.   LET extender$=RIGHT$(filename$,3)  ! NOTE: file extension
  1523.   OPEN "I",#1,filename$
  1524.   IF extender$="PI3" OR extender$="PI1"
  1525.     GOSUB load_degas
  1526.   ELSE IF extender$="PC3" OR extender$="PC1"
  1527.     GOSUB load_degas_elite
  1528.   ELSE IF extender$="TN3" OR extender$="TN1"
  1529.     GOSUB load_tiny
  1530.   ELSE IF extender$="IMG"
  1531.     GOSUB load_image
  1532.     IF EXIST(filename$)
  1533.       GOSUB display_graphic
  1534.     ENDIF
  1535.   ELSE
  1536.     DEFMOUSE 0
  1537.     ALERT 1,"Picture Format NOT recognised|at this time.|"+filename$,1," Cancel! ",void%
  1538.     LET head%(old_posit%,index%)=0
  1539.     LET tail%(posit%)=0
  1540.     LET file$(posit%)="FILENAME.TXT"
  1541.     LET posit%=old_posit%
  1542.   ENDIF
  1543.   CLOSE #1
  1544. RETURN
  1545. '
  1546. > PROCEDURE display_graphic
  1547.   ' PURPOSE : Prepare and open graphic window.
  1548.   '
  1549.   GOSUB open_window("G")
  1550.   GOSUB modwind(handle&,xpos%(posit%),ypos%(posit%),wsiz%(posit%),hsiz%(posit%))
  1551.   DEFMOUSE 0
  1552.   LET wf!=FALSE
  1553. RETURN
  1554. '
  1555. > PROCEDURE get_palette
  1556.   ' PURPOSE : Load palette data and convert from RGB to single value.
  1557.   '
  1558.   LET pal$=INPUT$(32,#1)                    ! get palette data
  1559.   LET count%=1
  1560.   FOR loop%=0 TO 31 STEP 2
  1561.     LET r=(PEEK(VARPTR(pal$)+loop%)/7)*0.3  ! calculate red component
  1562.     LET g=(FN col(4,loop%)/7)*0.11          ! calculate green component
  1563.     LET b=(SHR(FN col(0,loop%),4)/7)*0.59   ! calculate blue component
  1564.     LET col|(count%)=(r+g+b)*18             ! create single intensity value
  1565.     INC count%
  1566.   NEXT loop%
  1567. RETURN
  1568. '
  1569. > FUNCTION col(cbit%,cpro%)
  1570. ' PURPOSE : get colour palette lookup entry.
  1571. '
  1572. LET cbuf%=PEEK(VARPTR(pal$)+SUCC(cpro%))
  1573. FOR cloop%=cbit% TO ADD(cbit%,4)
  1574.   LET cbuf%=BCLR(cbuf%,cloop%)
  1575. NEXT cloop%
  1576. RETURN cbuf%
  1577. ENDFUNC
  1578. '
  1579. '
  1580. '  Load Degas Uncompressed Picture
  1581. ' ---------------------------------
  1582. '
  1583. > PROCEDURE load_degas
  1584. ' PURPOSE : This procedure will load a uncompressed degas elite
  1585. '           format picture into memory.
  1586. '
  1587. LET res$=INPUT$(2,#1)
  1588. GOSUB get_palette
  1589. LET raster$=INPUT$(32000,#1)
  1590. LET xgrap%=640
  1591. LET ygrap%=400
  1592. IF extender$="PI1"
  1593.   GOSUB reorder_planes
  1594.   GOSUB prepare_dither
  1595.   GOSUB ordered_dither
  1596.   LET xgrap%=320
  1597.   LET ygrap%=200
  1598. ENDIF
  1599. GOSUB display_graphic
  1600. RETURN
  1601. '
  1602. > PROCEDURE reorder_planes
  1603. ' PURPOSE : Reorder bit planes for colour to mono conversion.
  1604. '
  1605. LET temp$=raster$
  1606. LET st%=VARPTR(temp$)
  1607. LET scr%=VARPTR(raster$)
  1608. LET line%=scr%
  1609. FOR loop%=st% TO ADD(st%,31999) STEP 8
  1610.   DPOKE line%,DPEEK(loop%)
  1611.   DPOKE ADD(line%,8000),DPEEK(ADD(loop%,2))
  1612.   DPOKE ADD(line%,16000),DPEEK(ADD(loop%,4))
  1613.   DPOKE ADD(line%,24000),DPEEK(ADD(loop%,6))
  1614.   ADD line%,2
  1615. NEXT loop%
  1616. RETURN
  1617. '
  1618. '
  1619. '  Load Degas Compressed Picture
  1620. ' -------------------------------
  1621. '
  1622. > PROCEDURE load_degas_elite
  1623. ' PURPOSE : This procedure will load a compressed degas elite format
  1624. '           picture into memory and uncompress it.
  1625. '
  1626. LET res$=INPUT$(2,#1)
  1627. GOSUB get_palette
  1628. LET st%=VARPTR(raster$)
  1629. LET size%=ADD(st%,32000)
  1630. WHILE (st%<size%)
  1631.   LET store%=INP(#1)
  1632.   IF (store%<128)
  1633.     GOSUB not_comp
  1634.   ELSE
  1635.     GOSUB compressed
  1636.   ENDIF
  1637. WEND
  1638. LET xgrap%=640
  1639. LET ygrap%=400
  1640. IF extender$="PC1"
  1641.   GOSUB reorder_planes_compressed
  1642.   GOSUB prepare_dither
  1643.   GOSUB ordered_dither
  1644.   LET xgrap%=320
  1645.   LET ygrap%=200
  1646. ENDIF
  1647. GOSUB display_graphic
  1648. RETURN
  1649. '
  1650. > PROCEDURE reorder_planes_compressed
  1651. ' PURPOSE : Reorder bit planes for colour to mono conversion.
  1652. '
  1653. LET temp$=raster$
  1654. LET st%=VARPTR(temp$)
  1655. LET scr%=VARPTR(raster$)
  1656. LET line%=st%
  1657. LET scan%=ADD(st%,40)
  1658. FOR loop%=scr% TO ADD(scr%,7999) STEP 2
  1659.   DPOKE loop%,DPEEK(line%)
  1660.   DPOKE ADD(loop%,8000),DPEEK(ADD(line%,40))
  1661.   DPOKE ADD(loop%,16000),DPEEK(ADD(line%,80))
  1662.   DPOKE ADD(loop%,24000),DPEEK(ADD(line%,120))
  1663.   ADD line%,2
  1664.   IF scan%=line%
  1665.     ADD line%,120
  1666.     scan%=ADD(line%,40)
  1667.   ENDIF
  1668. NEXT loop%
  1669. RETURN
  1670. '
  1671. > PROCEDURE compressed
  1672. ' PURPOSE : use the next byte  -store% + 1 times.
  1673. '
  1674. LET store%=SUCC((NOT store%) AND &HFF)
  1675. LET buf%=INP(#1)
  1676. WHILE NOT store%
  1677.   POKE st%,buf%
  1678.   INC st%
  1679.   DEC store%
  1680. WEND
  1681. RETURN
  1682. '
  1683. > PROCEDURE not_comp
  1684. ' PURPOSE : use the next store% + 1 bytes literally.
  1685. '
  1686. WHILE NOT store%
  1687.   POKE st%,INP(#1)
  1688.   INC st%
  1689.   DEC store%
  1690. WEND
  1691. RETURN
  1692. '
  1693. '
  1694. '  Load Tiny Compressed Picture
  1695. ' ------------------------------
  1696. '
  1697. > PROCEDURE load_tiny
  1698. ' PURPOSE : This procedure will load a compressed tiny format picture
  1699. '           into memory and uncompress it.
  1700. '
  1701. LET res%=INP(#1)
  1702. GOSUB get_palette
  1703. LET temp$=INPUT$(4,#1)           ! Get # of control bytes and data words
  1704. LET lcode%=DPEEK(VARPTR(temp$))  ! Length of code table
  1705. LET lcode$=INPUT$(lcode%,#1)     ! read in code table data
  1706. LET ldata$=INPUT$(DPEEK(VARPTR(temp$)+2)*2,#1) ! read in data words data
  1707. LET ptrco%=VARPTR(lcode$)        ! remove pointer evaluation from loops
  1708. LET ptrda%=VARPTR(ldata$)
  1709. LET raster$=STRING$(32000,0)
  1710. LET st%=VARPTR(raster$)
  1711. LET ixpic%=0
  1712. LET ixcode%=0
  1713. LET ixdata%=0
  1714. '
  1715. WHILE ixcode%<lcode%
  1716.   LET coval%=PEEK(ptrco%+ixcode%)
  1717.   IF coval%=0                     ! 0= 16 bit repeat count
  1718.     GOSUB repeat_count16
  1719.   ELSE IF coval%=1                ! 1= 16 bit string length
  1720.     GOSUB string_length16
  1721.   ELSE IF coval%<128              ! 2..127 = repeat count
  1722.     GOSUB repeat_count
  1723.   ELSE                            ! 128..255 = two's complement string length
  1724.     GOSUB twos_complement
  1725.   ENDIF
  1726. WEND
  1727. '
  1728. IF res%=0                         ! is it a low resolution graphic
  1729.   LET temp$=raster$
  1730.   GOSUB reorder_planes
  1731.   GOSUB prepare_dither
  1732.   GOSUB ordered_dither
  1733.   LET xgrap%=320                  ! picture width
  1734.   LET ygrap%=200                  ! picture height
  1735. ELSE                              ! is it a high resolution graphic
  1736.   LET xgrap%=640                  ! picture width
  1737.   LET ygrap%=400                  ! picture height
  1738. ENDIF
  1739. LET lcode$=""
  1740. LET ldata$=""
  1741. GOSUB display_graphic
  1742. RETURN
  1743. '
  1744. > PROCEDURE repeat_count16
  1745. ' PURPOSE : 1 word is taken from the control section which specifies the
  1746. '           number of times to repeat the next data word from (128 to 32767)
  1747. '
  1748. LET coval%=ADD(MUL(PEEK(SUCC(ADD(ptrco%,ixcode%))),256),PEEK(ADD(ADD(ptrco%,ixcode%),2)))
  1749. ADD ixcode%,3
  1750. GOSUB getdata
  1751. FOR loop%=1 TO coval%
  1752.   GOSUB putdata
  1753. NEXT loop%
  1754. RETURN
  1755. '
  1756. > PROCEDURE string_length16
  1757. ' PURPOSE : 1 word is taken from the control section which specifies the
  1758. '           number of unique words to be taken from the data section.
  1759. '           (from 128 - 32767)
  1760. '
  1761. LET coval%=ADD(MUL(PEEK(SUCC(ADD(ptrco%,ixcode%))),256),PEEK(ADD(ADD(ptrco%,ixcode%),2)))
  1762. ADD ixcode%,3
  1763. FOR loop%=1 TO coval%
  1764.   GOSUB getdata
  1765.   GOSUB putdata
  1766. NEXT loop%
  1767. RETURN
  1768. '
  1769. > PROCEDURE repeat_count
  1770. ' PURPOSE : specifies the number of times to repeat the next word
  1771. '           taken from the data section. (from 2 to 127)
  1772. '
  1773. INC ixcode%
  1774. GOSUB getdata
  1775. FOR loop%=1 TO coval%
  1776.   GOSUB putdata
  1777. NEXT loop%
  1778. RETURN
  1779. '
  1780. > PROCEDURE twos_complement
  1781. ' PURPOSE : absolute value specifies the number of unique words to
  1782. '           take from the data section. (from 1 to 127)
  1783. '
  1784. INC ixcode%
  1785. LET coval%=SUB(256,coval%)
  1786. FOR loop%=1 TO coval%
  1787.   GOSUB getdata
  1788.   GOSUB putdata
  1789. NEXT loop%
  1790. RETURN
  1791. '
  1792. > PROCEDURE getdata
  1793. ' PURPOSE : gets a word from the data string.
  1794. '
  1795. pword%=DPEEK(ADD(ptrda%,ixdata%))
  1796. ADD ixdata%,2
  1797. RETURN
  1798. '
  1799. > PROCEDURE putdata
  1800. ' PURPOSE : puts a word into the output string.
  1801. '
  1802. DPOKE ADD(st%,ixpic%),pword%
  1803. ADD ixpic%,160
  1804. IF ixpic%>=32000
  1805.   ADD ixpic%,8
  1806.   SUB ixpic%,32000
  1807.   IF ixpic%>=160
  1808.     ADD ixpic%,2
  1809.     SUB ixpic%,160
  1810.   ENDIF
  1811. ENDIF
  1812. RETURN
  1813. '
  1814. '
  1815. '  Load Compressed Image Picture
  1816. ' -------------------------------
  1817. '
  1818. > PROCEDURE load_image
  1819. ' PURPOSE : This procedure will load a compressed image format picture
  1820. '           into memory and uncompress it.
  1821. '
  1822. LET temp$=INPUT$(4,#1)
  1823. LET temp$=INPUT$((DPEEK(VARPTR(temp$)+2)*2)-4,#1) ! read in rest of header
  1824. LET pattern%=DPEEK(VARPTR(temp$)+2)               ! pattern length
  1825. LET width%=((DPEEK(VARPTR(temp$)+8)-1)/8)         ! line width in pixels
  1826. LET lines%=DPEEK(VARPTR(temp$)+10)                ! number of lines
  1827. IF lines%<=400 AND DPEEK(VARPTR(temp$)+8)<=640    ! is it suitable size
  1828.   LET xgrap%=DPEEK(VARPTR(temp$)+8)               ! width of graphic
  1829.   LET ygrap%=lines%                               ! height of graphic
  1830.   LET raster$=STRING$(32000,0)
  1831.   LET st%=VARPTR(raster$)
  1832.   LET start%=st%
  1833.   WHILE NOT EOF(#1)
  1834.     LET x%=INP(#1)
  1835.     IF x%=0                                       ! Pattern or Scanline Run
  1836.       LET n%=INP(#1)
  1837.       IF n%>0
  1838.         GOSUB pattern
  1839.       ELSE IF n%=0                                ! Scanline Run
  1840.         LET n%=INP(#1)
  1841.         LET scan%=INP(#1)
  1842.         LET scanrun!=TRUE
  1843.       ENDIF
  1844.     ELSE IF x%=&H80                               ! Uncompressed bit string
  1845.       GOSUB uncompressed
  1846.     ELSE                                          ! Solid run
  1847.       GOSUB solid_run
  1848.     ENDIF
  1849.   WEND
  1850. ELSE
  1851.   LET extender$=""
  1852.   ALERT 1,"The Image File is to large for|this application.",1," Cancel! ",void%
  1853. ENDIF
  1854. RETURN
  1855. '
  1856. > PROCEDURE pattern
  1857. ' PURPOSE : read a number of bytes equal to the "pattern length" word
  1858. '           in the header. Repeat this pattern n% times.
  1859. '
  1860. LET temp$=INPUT$(pattern%,#1)
  1861. FOR loop%=1 TO n%
  1862.   FOR nloop%=1 TO pattern%
  1863.     POKE st%,PRED(ADD(PEEK(VARPTR(temp$)),nloop%))
  1864.     GOSUB counter
  1865.   NEXT nloop%
  1866. NEXT loop%
  1867. RETURN
  1868. '
  1869. > PROCEDURE counter
  1870. ' PURPOSE : scanline run. Data for the next scanline is be used
  1871. '           multiple times and also handle output byte position.
  1872. '
  1873. INC st%
  1874. IF SUB(st%,start%)>width%
  1875.   LET start%=ADD(start%,80)
  1876.   LET st%=start%
  1877.   IF scanrun!=TRUE
  1878.     WHILE scan%>0
  1879.       POKE st%,PEEK(SUB(st%,80))
  1880.       INC st%
  1881.       IF SUB(st%,start%)>width%
  1882.         LET start%=ADD(start%,80)
  1883.         LET st%=start%
  1884.         DEC scan%
  1885.       ENDIF
  1886.     WEND
  1887.     LET scanrun!=FALSE
  1888.   ENDIF
  1889. ENDIF
  1890. RETURN
  1891. '
  1892. > PROCEDURE uncompressed
  1893. ' PURPOSE : uncompressed bit string. The next byte determines the
  1894. '           number of bytes to use literally. The literal data
  1895. '           bytes follow.
  1896. '
  1897. LET n%=INP(#1)
  1898. FOR loop%=1 TO n%
  1899.   POKE st%,INP(#1)
  1900.   GOSUB counter
  1901. NEXT loop%
  1902. RETURN
  1903. '
  1904. > PROCEDURE solid_run
  1905. ' PURPOSE : solid run. The value of x% determines what to draw.
  1906. '           The high bit specifies whether the pixels are set or
  1907. '           cleared. A 1 specifies a byte run using $FF, a 0
  1908. '           indicates a byte run using $00. The low 7 bits, taken
  1909. '           as an unsigned quantity, specify the length of the
  1910. '           run in bytes.
  1911. '
  1912. IF BTST(x%,7)
  1913.   LET x%=BCLR(x%,7)
  1914.   FOR loop%=1 TO x%
  1915.     POKE st%,&HFF
  1916.     GOSUB counter
  1917.   NEXT loop%
  1918. ELSE
  1919.   FOR loop%=1 TO x%
  1920.     GOSUB counter
  1921.   NEXT loop%
  1922. ENDIF
  1923. RETURN
  1924. '
  1925. '
  1926. '  Ordered Dither Procedures
  1927. ' ---------------------------
  1928. '
  1929. > PROCEDURE prepare_dither
  1930. ' PURPOSE : This procedure checks for the setting of each bit on each bit
  1931. '           plane and uses the combined value of these bit planes as a
  1932. '           index to the lookup palette table. It then moves this
  1933. '           intensity into a sequential array for every pixel.
  1934. '
  1935. LET st%=VARPTR(raster$)
  1936. DEFMOUSE paintcan$
  1937. LET x%=0
  1938. FOR y%=0 TO 7999 STEP 2
  1939.   LET p0%=ADD(y%,st%)
  1940.   LET p1%=DPEEK(p0%)
  1941.   LET p2%=DPEEK(ADD(p0%,8000))
  1942.   LET p3%=DPEEK(ADD(p0%,16000))
  1943.   LET p4%=DPEEK(ADD(p0%,24000))
  1944.   ' work on a complete word in one go.
  1945.   ' ----------------------------------
  1946.   LET pic|(x%)=col|(ADD(ADD(ADD(ADD(ABS(BTST(p1%,0)),MUL(ABS(BTST(p2%,0)),2)),MUL(ABS(BTST(p3%,0)),4)),MUL(ABS(BTST(p4%,0)),8)),1))
  1947.   LET pic|(SUCC(x%))=col|(ADD(ADD(ADD(ADD(ABS(BTST(p1%,1)),MUL(ABS(BTST(p2%,1)),2)),MUL(ABS(BTST(p3%,1)),4)),MUL(ABS(BTST(p4%,1)),8)),1))
  1948.   LET pic|(ADD(x%,2))=col|(ADD(ADD(ADD(ADD(ABS(BTST(p1%,2)),MUL(ABS(BTST(p2%,2)),2)),MUL(ABS(BTST(p3%,2)),4)),MUL(ABS(BTST(p4%,2)),8)),1))
  1949.   LET pic|(ADD(x%,3))=col|(ADD(ADD(ADD(ADD(ABS(BTST(p1%,3)),MUL(ABS(BTST(p2%,3)),2)),MUL(ABS(BTST(p3%,3)),4)),MUL(ABS(BTST(p4%,3)),8)),1))
  1950.   LET pic|(ADD(x%,4))=col|(ADD(ADD(ADD(ADD(ABS(BTST(p1%,4)),MUL(ABS(BTST(p2%,4)),2)),MUL(ABS(BTST(p3%,4)),4)),MUL(ABS(BTST(p4%,4)),8)),1))
  1951.   LET pic|(ADD(x%,5))=col|(ADD(ADD(ADD(ADD(ABS(BTST(p1%,5)),MUL(ABS(BTST(p2%,5)),2)),MUL(ABS(BTST(p3%,5)),4)),MUL(ABS(BTST(p4%,5)),8)),1))
  1952.   LET pic|(ADD(x%,6))=col|(ADD(ADD(ADD(ADD(ABS(BTST(p1%,6)),MUL(ABS(BTST(p2%,6)),2)),MUL(ABS(BTST(p3%,6)),4)),MUL(ABS(BTST(p4%,6)),8)),1))
  1953.   LET pic|(ADD(x%,7))=col|(ADD(ADD(ADD(ADD(ABS(BTST(p1%,7)),MUL(ABS(BTST(p2%,7)),2)),MUL(ABS(BTST(p3%,7)),4)),MUL(ABS(BTST(p4%,7)),8)),1))
  1954.   LET pic|(ADD(x%,8))=col|(ADD(ADD(ADD(ADD(ABS(BTST(p1%,8)),MUL(ABS(BTST(p2%,8)),2)),MUL(ABS(BTST(p3%,8)),4)),MUL(ABS(BTST(p4%,8)),8)),1))
  1955.   LET pic|(ADD(x%,9))=col|(ADD(ADD(ADD(ADD(ABS(BTST(p1%,9)),MUL(ABS(BTST(p2%,9)),2)),MUL(ABS(BTST(p3%,9)),4)),MUL(ABS(BTST(p4%,9)),8)),1))
  1956.   LET pic|(ADD(x%,10))=col|(ADD(ADD(ADD(ADD(ABS(BTST(p1%,10)),MUL(ABS(BTST(p2%,10)),2)),MUL(ABS(BTST(p3%,10)),4)),MUL(ABS(BTST(p4%,10)),8)),1))
  1957.   LET pic|(ADD(x%,11))=col|(ADD(ADD(ADD(ADD(ABS(BTST(p1%,11)),MUL(ABS(BTST(p2%,11)),2)),MUL(ABS(BTST(p3%,11)),4)),MUL(ABS(BTST(p4%,11)),8)),1))
  1958.   LET pic|(ADD(x%,12))=col|(ADD(ADD(ADD(ADD(ABS(BTST(p1%,12)),MUL(ABS(BTST(p2%,12)),2)),MUL(ABS(BTST(p3%,12)),4)),MUL(ABS(BTST(p4%,12)),8)),1))
  1959.   LET pic|(ADD(x%,13))=col|(ADD(ADD(ADD(ADD(ABS(BTST(p1%,13)),MUL(ABS(BTST(p2%,13)),2)),MUL(ABS(BTST(p3%,13)),4)),MUL(ABS(BTST(p4%,13)),8)),1))
  1960.   LET pic|(ADD(x%,14))=col|(ADD(ADD(ADD(ADD(ABS(BTST(p1%,14)),MUL(ABS(BTST(p2%,14)),2)),MUL(ABS(BTST(p3%,14)),4)),MUL(ABS(BTST(p4%,14)),8)),1))
  1961.   LET pic|(ADD(x%,15))=col|(ADD(ADD(ADD(ADD(ABS(BTST(p1%,15)),MUL(ABS(BTST(p2%,15)),2)),MUL(ABS(BTST(p3%,15)),4)),MUL(ABS(BTST(p4%,15)),8)),1))
  1962.   ADD x%,16
  1963. NEXT y%
  1964. RETURN
  1965. '
  1966. > PROCEDURE ordered_dither
  1967. ' PURPOSE : this procedure extracts the intensity of a pixel
  1968. '           and compares with the value in the dither matrix.
  1969. '           From this result the corresponding output bit is
  1970. '           set on or off.
  1971. '
  1972. DEFMOUSE pencil$
  1973. LET raster$=STRING$(32000,0)
  1974. LET scr%=VARPTR(raster$)
  1975. LET word%=scr%
  1976. LET scan%=ADD(word%,40)
  1977. FOR z%=0 TO 63999 STEP 16
  1978.   ' work on a complete word in one go.
  1979.   ' ----------------------------------
  1980.   LET p0%=ABS(pic|(z%)<dither2|(z%))
  1981.   LET p1%=MUL(ABS(pic|(SUCC(z%))<dither2|(SUCC(z%))),2)
  1982.   LET p2%=MUL(ABS(pic|(ADD(z%,2))<dither2|(ADD(z%,2))),4)
  1983.   LET p3%=MUL(ABS(pic|(ADD(z%,3))<dither2|(ADD(z%,3))),8)
  1984.   LET p4%=MUL(ABS(pic|(ADD(z%,4))<dither2|(ADD(z%,4))),16)
  1985.   LET p5%=MUL(ABS(pic|(ADD(z%,5))<dither2|(ADD(z%,5))),32)
  1986.   LET p6%=MUL(ABS(pic|(ADD(z%,6))<dither2|(ADD(z%,6))),64)
  1987.   LET p7%=MUL(ABS(pic|(ADD(z%,7))<dither2|(ADD(z%,7))),128)
  1988.   LET p8%=MUL(ABS(pic|(ADD(z%,8))<dither2|(ADD(z%,8))),256)
  1989.   LET p9%=MUL(ABS(pic|(ADD(z%,9))<dither2|(ADD(z%,9))),512)
  1990.   LET p10%=MUL(ABS(pic|(ADD(z%,10))<dither2|(ADD(z%,10))),1024)
  1991.   LET p11%=MUL(ABS(pic|(ADD(z%,11))<dither2|(ADD(z%,11))),2048)
  1992.   LET p12%=MUL(ABS(pic|(ADD(z%,12))<dither2|(ADD(z%,12))),4096)
  1993.   LET p13%=MUL(ABS(pic|(ADD(z%,13))<dither2|(ADD(z%,13))),8192)
  1994.   LET p14%=MUL(ABS(pic|(ADD(z%,14))<dither2|(ADD(z%,14))),16384)
  1995.   LET p15%=MUL(ABS(pic|(ADD(z%,15))<dither2|(ADD(z%,15))),32768)
  1996.   DPOKE word%,ADD(ADD(ADD(ADD(ADD(ADD(ADD(ADD(ADD(ADD(ADD(ADD(ADD(ADD(ADD(p0%,p1%),p2%),p3%),p4%),p5%),p6%),p7%),p8%),p9%),p10%),p11%),p12%),p13%),p14%),p15%)
  1997.   ADD word%,2
  1998.   IF word%=scan%
  1999.     ADD word%,40
  2000.     ADD scan%,80
  2001.   ENDIF
  2002. NEXT z%
  2003. RETURN
  2004. '
  2005. '
  2006. '  Load Sample Procedures
  2007. ' ------------------------
  2008. '
  2009. > PROCEDURE load_sample(filename$)
  2010. ' PURPOSE : identify sample file and branch to appropriate routine
  2011. '
  2012. LET extender$=RIGHT$(filename$,3)  ! NOTE: file extension
  2013. DEFMOUSE iomouse$
  2014. OPEN "I",#1,filename$
  2015. IF extender$="AVR"
  2016.   GOSUB load_avr
  2017. ELSE IF extender$="SND"
  2018.   GOSUB load_snd
  2019. ELSE IF extender$="WAV"
  2020.   GOSUB load_wav
  2021. ELSE IF extender$="DVS"
  2022.   GOSUB load_dvs
  2023. ELSE
  2024.   ALERT 1,"Sample Format NOT recognised|at this time.",1," Cancel! ",void%
  2025.   CLOSE #1
  2026.   LET head%(old_posit%,index%)=0
  2027.   LET tail%(posit%)=0
  2028.   LET file$(posit%)="FILENAME.TXT"
  2029.   LET type$(posit%)=""
  2030. ENDIF
  2031. DEFMOUSE 0
  2032. RETURN
  2033. '
  2034. > PROCEDURE load_avr
  2035. ' PURPOSE : load AVR sample, extract sample header and
  2036. '           call external sample player module.
  2037. '
  2038. LET header$=INPUT$(128,#1)
  2039. CLOSE #1
  2040. IF LEFT$(header$,4)<>"2BIT"
  2041.   ALERT 2,"Invalid AVR-SAMPLE||Sample has incorrect file|extender.",1," Cancel! ",void%
  2042. ELSE
  2043.   ' Sign Magnitude Yes/No
  2044.   IF DPEEK(VARPTR(header$)+16)=0
  2045.     LET mag$=" "
  2046.   ELSE
  2047.     LET mag$=" -z"
  2048.   ENDIF
  2049.   ' Mono or Stereo Sample
  2050.   IF DPEEK(VARPTR(header$)+12)=0
  2051.     LET st$=" "
  2052.   ELSE
  2053.     LET st$=" -2"
  2054.   ENDIF
  2055.   ' Hertz rate of sample
  2056.   LET hertz$=STR$(DPEEK(VARPTR(header$)+24))
  2057.   ' Load and play sample
  2058.   LET buf$=" "+filename$+" "+hertz$+" -q"+mag$+st$
  2059.   e%=EXEC(0,path$+"PLAY.EXE",CHR$(LEN(buf$))+buf$,"")
  2060. ENDIF
  2061. RETURN
  2062. '
  2063. > PROCEDURE load_snd
  2064. ' PURPOSE : load SND sample, extract sample header and
  2065. '           call external sample player module.
  2066. '
  2067. LET header$=INPUT$(28,#1)
  2068. CLOSE #1
  2069. IF LEFT$(header$,4)<>".snd"
  2070.   ALERT 2,"Invalid SND-SAMPLE||Sample has incorrect file|extender.",1," Cancel! ",void%
  2071. ELSE
  2072.   ' Sign Magnitude Yes/No
  2073.   LET mag$=" -z"
  2074.   ' Mono or Stereo Sample
  2075.   IF DPEEK(VARPTR(header$)+22)=1
  2076.     LET st$=""
  2077.   ELSE
  2078.     LET st$=" -2"
  2079.   ENDIF
  2080.   ' Hertz rate of sample
  2081.   LET hertz$=STR$(DPEEK(VARPTR(header$)+18))
  2082.   ' Load and play sample
  2083.   LET buf$=" "+filename$+" "+hertz$+" -q"+mag$+st$
  2084.   e%=EXEC(0,path$+"PLAY.EXE",CHR$(LEN(buf$))+buf$,"")
  2085. ENDIF
  2086. RETURN
  2087. '
  2088. > PROCEDURE load_wav
  2089. ' PURPOSE : load WAV sample, extract sample header and
  2090. '           call external sample player module.
  2091. '
  2092. LET header$=INPUT$(44,#1)
  2093. CLOSE #1
  2094. IF LEFT$(header$,4)<>"RIFF"
  2095.   ALERT 2,"Invalid WAVE-SAMPLE||Sample has incorrect file|extender.",1," Cancel! ",void%
  2096. ELSE
  2097.   ' Sign Magnitude Yes/No
  2098.   LET mag$=""
  2099.   ' Mono or Stereo Sample
  2100.   IF PEEK(VARPTR(header$)+22)=1
  2101.     LET st$=""
  2102.   ELSE
  2103.     LET st$=" -2"
  2104.   ENDIF
  2105.   ' Hertz rate of sample
  2106.   LET hertz$=STR$(PEEK(VARPTR(header$)+25)*256+PEEK(VARPTR(header$)+24))
  2107.   ' Load and play sample
  2108.   LET buf$=" "+filename$+" "+hertz$+" -q"+mag$+st$
  2109.   e%=EXEC(0,path$+"PLAY.EXE",CHR$(LEN(buf$))+buf$,"")
  2110. ENDIF
  2111. RETURN
  2112. '
  2113. > PROCEDURE load_dvs
  2114. ' PURPOSE : load DVSM sample, extract sample header and
  2115. '           call external sample player module.
  2116. '
  2117. LET header$=INPUT$(16,#1)
  2118. CLOSE #1
  2119. IF LEFT$(header$,4)<>"DVSM"
  2120.   ALERT 2,"Invalid DVSM-SAMPLE||Sample has incorrect file|extender.",1," Cancel! ",void%
  2121. ELSE
  2122.   ' Sign Magnitude Yes/No
  2123.   LET mag$=" -z"
  2124.   ' Mono or Stereo Sample
  2125.   IF PEEK(VARPTR(header$)+11)=0 OR PEEK(VARPTR(header$)+11)=1
  2126.     LET st$=" -2"
  2127.   ELSE
  2128.     LET st$=""
  2129.   ENDIF
  2130.   ' Hertz rate of sample
  2131.   LET hertz$=STR$(freq%(DPEEK(VARPTR(header$)+8)))
  2132.   ' Load and play sample
  2133.   LET buf$=" "+filename$+" "+hertz$+" -q"+mag$+st$
  2134.   e%=EXEC(0,path$+"PLAY.EXE",CHR$(LEN(buf$))+buf$,"")
  2135. ENDIF
  2136. RETURN
  2137. '
  2138. '
  2139. '  Window Management Procedures
  2140. ' ------------------------------
  2141. '
  2142. > PROCEDURE message
  2143. ' PURPOSE : Handle Event Multi-Events.
  2144. '           It handles window, mouse and menu events.
  2145. '
  2146. IF MENU(1)>19 AND MENU(1)<29
  2147.   LET handle&=MENU(4)
  2148.   ON MENU(1)-19 GOSUB wm_redraw,wm_topped,wm_closed,wm_fulled,wm_arrowed
  2149.   ON MENU(1)-24 GOSUB wm_hslid,wm_vslid,wm_sized,wm_moved
  2150.   ~WIND_GET(handle&,4,xx%,yy%,ww%,hh%)
  2151.   ON MENU IBOX 1,xx%,yy%,ww%,hh% GOSUB find_button
  2152. ENDIF
  2153. RETURN
  2154. '
  2155. > PROCEDURE wm_closed
  2156. ' PURPOSE : load previous window and prompt user to save current
  2157. '           text window if modified.
  2158. '
  2159. IF edited!=TRUE
  2160.   ALERT 1,"TEXT FILE MODIFIED!|Text File has been modified|but not saved!",2," Lose! | Save! ",but%
  2161.   LET edited!=FALSE
  2162.   IF but%=2
  2163.     GOSUB esc_key
  2164.   ENDIF
  2165. ENDIF
  2166. SPRITE cursor$
  2167. IF posit%>1
  2168.   LET posit%=tail%(posit%)
  2169.   SELECT type$(posit%)
  2170.   CASE "T"
  2171.     GOSUB load_text(file$(posit%))
  2172.   CASE "S"
  2173.     GOSUB load_sample(file$(posit%))
  2174.   CASE "G"
  2175.     GOSUB load_graphic(file$(posit%))
  2176.   ENDSELECT
  2177. ELSE
  2178.   ALERT 1,"At First Window|No previous window.",1," Ok! ",void%
  2179. ENDIF
  2180. RETURN
  2181. '
  2182. > PROCEDURE wm_topped
  2183. ' PURPOSE : top window, activate current window.
  2184. '
  2185. LET handle&=MENU(4)
  2186. ~WIND_SET(handle&,10,handle&,0,0,0)
  2187. RETURN
  2188. '
  2189. > PROCEDURE wm_moved
  2190. ' PURPOSE : get moved windows new location co-ordinates.
  2191. '           Move window and redraw contents.
  2192. '
  2193. SPRITE cursor$
  2194. ~WIND_SET(handle&,5,MENU(5),MENU(6),MENU(7),MENU(8))
  2195. CLIP  OFFSET MENU(5),MENU(6)
  2196. GOSUB modwind(handle&,MENU(5),MENU(6),MENU(7),MENU(8))
  2197. GOSUB calc_slid(handle&)
  2198. GOSUB do_redraw(0)
  2199. RETURN
  2200. '
  2201. > PROCEDURE wm_sized
  2202. ' PURPOSE : get windows new width and height position.
  2203. '           Set new window width and height position.
  2204. '           If text window also reposition cursor, if
  2205. '           location is now outside window co-ordinates.
  2206. '
  2207. GOSUB draw_cursor(tpox%,tpoy%,FALSE)
  2208. ~WIND_SET(handle&,5,MENU(5),MENU(6),MENU(7),MENU(8))
  2209. SELECT type$(posit%)
  2210. CASE "T"
  2211.   GOSUB modwind(handle&,MENU(5),MENU(6),MIN(MENU(7),(xgrap%*chrbb%)+19),MIN(MENU(8),(ygrap%*chrbh%)+55))
  2212.   GOSUB cursor_resize
  2213. CASE "G"
  2214.   GOSUB modwind(handle&,MENU(5),MENU(6),MIN(MENU(7),xgrap%+19),MIN(MENU(8),ygrap%+55))
  2215. ENDSELECT
  2216. LET wf!=FALSE
  2217. RETURN
  2218. '
  2219. > PROCEDURE cursor_resize
  2220. ' PURPOSE : If the cursors current position is outside the
  2221. '           current text window then it is repositioned inside
  2222. '           the window.
  2223. '
  2224. ~WIND_GET(handle&,4,x%,y%,b%,h%)
  2225. GOSUB draw_cursor(tpox%,tpoy%,FALSE)
  2226. IF cury%=>h%+y%-4
  2227.   LET tpoy%=vpos%(posit%)+(h% DIV chrbh%)
  2228. ELSE IF cury%<y%
  2229.   LET tpoy%=vpos%(posit%)+1
  2230. ENDIF
  2231. IF curx%=>b%+x%
  2232.   LET tpox%=hpos%(posit%)+(b% DIV chrbb%)
  2233. ELSE IF curx%<x%
  2234.   LET tpox%=hpos%(posit%)+1
  2235. ENDIF
  2236. GOSUB draw_cursor(tpox%,tpoy%,FALSE)
  2237. RETURN
  2238. '
  2239. > PROCEDURE wm_fulled
  2240. ' PURPOSE : resize window to fullsize or resize window to previous size.
  2241. '
  2242. SPRITE cursor$
  2243. IF wf!=TRUE
  2244.   GOSUB store_size(FALSE,0,0,0,0)
  2245.   ~WIND_SET(handle&,5,xpos%(posit%),ypos%(posit%),wsiz%(posit%),hsiz%(posit%))
  2246.   GOSUB modwind(handle&,xpos%(posit%),ypos%(posit%),wsiz%(posit%),hsiz%(posit%))
  2247.   LET wf!=NOT wf!
  2248.   IF type$(posit%)="T"
  2249.     GOSUB cursor_resize
  2250.   ENDIF
  2251. ELSE IF wf!=FALSE
  2252.   GOSUB store_size(TRUE,xpos%(posit%),ypos%(posit%),wsiz%(posit%),hsiz%(posit%))
  2253.   LET wf!=NOT wf!
  2254.   LET xpos%(posit%)=scrx%
  2255.   LET ypos%(posit%)=scry%
  2256.   SELECT type$(posit%)
  2257.   CASE "T"
  2258.     LET wsiz%(posit%)=MIN(scrb%-4,(xgrap%*chrbb%)+19)
  2259.     LET hsiz%(posit%)=MIN(scrh%,(ygrap%*chrbh%)+55)
  2260.   CASE "G"
  2261.     LET wsiz%(posit%)=MIN(scrb%,xgrap%+19)
  2262.     LET hsiz%(posit%)=MIN(scrh%,ygrap%+55)
  2263.   ENDSELECT
  2264.   ~WIND_SET(handle&,5,xpos%(posit%),ypos%(posit%),wsiz%(posit%),hsiz%(posit%))
  2265.   GOSUB modwind(handle&,xpos%(posit%),ypos%(posit%),wsiz%(posit%),hsiz%(posit%))
  2266. ENDIF
  2267. RETURN
  2268. '
  2269. > PROCEDURE store_size(store!,x%,y%,b%,h%)
  2270. ' PURPOSE : stores windows current position and size or returns
  2271. '           a windows previous window position and size.
  2272. '
  2273. IF store!=TRUE
  2274.   LET storex%=x%
  2275.   LET storey%=y%
  2276.   LET storeb%=b%
  2277.   LET storeh%=h%
  2278. ELSE
  2279.   LET xpos%(posit%)=storex%
  2280.   LET ypos%(posit%)=storey%
  2281.   LET wsiz%(posit%)=storeb%
  2282.   LET hsiz%(posit%)=storeh%
  2283. ENDIF
  2284. RETURN
  2285. '
  2286. > PROCEDURE modwind(handle&,x%,y%,b%,h%)
  2287. ' PURPOSE : modifies window width and height and slider positions.
  2288. '
  2289. IF type$(posit%)="T"
  2290.   LET h%=ADD(MUL((h% DIV chrbh%),16),8)
  2291.   LET b%=ADD(MUL((b% DIV chrbb%),8),4)
  2292. ENDIF
  2293. ~WIND_SET(handle&,5,x%,y%,b%,h%)
  2294. ~WIND_GET(handle&,4,x%,y%,b%,h%)
  2295. SELECT type$(posit%)
  2296. CASE "T"
  2297.   LET hpos%(posit%)=MIN(hpos%(posit%),xgrap%-b% DIV chrbb%)
  2298.   LET vpos%(posit%)=MIN(vpos%(posit%),ygrap%-h% DIV chrbh%)
  2299. CASE "G"
  2300.   LET hpos%(posit%)=MIN(hpos%(posit%),SUB(xgrap%,b%))
  2301.   LET vpos%(posit%)=MIN(vpos%(posit%),SUB(ygrap%,h%))
  2302. ENDSELECT
  2303. ~WIND_GET(handle&,5,xpos%(posit%),ypos%(posit%),wsiz%(posit%),hsiz%(posit%))
  2304. GOSUB calc_slid(handle&)
  2305. RETURN
  2306. '
  2307. '
  2308. '  Window Sliders Procedures
  2309. ' ---------------------------
  2310. '
  2311. > PROCEDURE calc_slid(handle&)
  2312. ' PURPOSE : calculates new slider size and position.
  2313. '
  2314. ~WIND_GET(handle&,4,x%,y%,b%,h%)
  2315. SELECT type$(posit%)
  2316. CASE "T"
  2317.   IF vpos%(posit%)<>0 AND h%/chrbh%<ygrap%
  2318.     ~WIND_SET(handle&,9,vpos%(posit%)/(ygrap%-h%/chrbh%)*1000+0.5,0,0,0)
  2319.   ELSE IF h%/chrbh%=>ygrap% OR vpos%(posit%)=0
  2320.     ~WIND_SET(handle&,9,1,0,0,0)
  2321.   ENDIF
  2322.   LET barv%=h%/ygrap%/chrbh%*1000+0.5
  2323.   IF barv%>0 AND barv%<1001 AND h%/chrbh%<ygrap%
  2324.     ~WIND_SET(handle&,16,barv%,0,0,0)
  2325.   ELSE
  2326.     ~WIND_SET(handle&,16,1000,0,0,0)
  2327.   ENDIF
  2328. CASE "G"
  2329.   GOSUB set_slid(handle&,b%/xgrap%,h%/ygrap%,hpos%(posit%)/SUB(xgrap%,b%),vpos%(posit%)/SUB(ygrap%,h%))
  2330. ENDSELECT
  2331. RETURN
  2332. '
  2333. > PROCEDURE set_slid(handle&,hs,vs,hp,vp)
  2334. ' PURPOSE : sets a windows slider position and size.
  2335. '
  2336. ~WIND_SET(handle&,15,hs*1000+0.5,0,0,0)
  2337. ~WIND_SET(handle&,16,vs*1000+0.5,0,0,0)
  2338. ~WIND_SET(handle&,8,hp*1000+0.5,0,0,0)
  2339. ~WIND_SET(handle&,9,vp*1000+0.5,0,0,0)
  2340. RETURN
  2341. '
  2342. > PROCEDURE wm_hslid
  2343. ' PURPOSE : gets a windows horizontal slider bars new position.
  2344. '
  2345. ~WIND_GET(handle&,4,x%,y%,b%,h%)
  2346. SELECT type$(posit%)
  2347. CASE "G"
  2348.   LET hpos%(posit%)=MUL(MENU(5),SUB(xgrap%,b%))/1000+0.5
  2349. ENDSELECT
  2350. GOSUB calc_slid(handle&)
  2351. GOSUB do_redraw(0)
  2352. RETURN
  2353. '
  2354. > PROCEDURE wm_vslid
  2355. ' PURPOSE : gets a windows vertical slider bars new position.
  2356. '
  2357. ~WIND_GET(handle&,4,x%,y%,b%,h%)
  2358. SELECT type$(posit%)
  2359. CASE "T"
  2360.   LET vpos%(posit%)=MUL(MENU(5),SUB(ygrap%,DIV(h%,chrbh%)))/1000+0.5
  2361.   GOSUB cursor_resize
  2362. CASE "G"
  2363.   LET vpos%(posit%)=MUL(MENU(5),SUB(ygrap%,h%))/1000+0.5
  2364. ENDSELECT
  2365. GOSUB calc_slid(handle&)
  2366. GOSUB do_redraw(0)
  2367. RETURN
  2368. '
  2369. > PROCEDURE wm_arrowed
  2370. ' PURPOSE : determines which window type arrows have been moved
  2371. '           and branches to the appropriate procedure.
  2372. '
  2373. ~WIND_GET(handle&,4,x%,y%,b%,h%)
  2374. SELECT type$(posit%)
  2375. CASE "T"
  2376.   GOSUB arrow_text
  2377. CASE "G"
  2378.   GOSUB arrow_graphic
  2379. ENDSELECT
  2380. RETURN
  2381. '
  2382. > PROCEDURE arrow_text
  2383. ' PURPOSE : updates a text windows contents according to a arrow button
  2384. '           event or before or after slider bar event.
  2385. '
  2386. SELECT MENU(5)
  2387. CASE 0                   ! move screen down complete window size position.
  2388.   LET vpos%(posit%)=MAX(SUB(vpos%(posit%),DIV(h%,chrbh%)),0)
  2389.   GOSUB cursor_resize
  2390.   GOSUB calc_slid(handle&)
  2391.   GOSUB do_redraw(0)
  2392. CASE 1                   ! move screen up complete window size position.
  2393.   LET vpos%(posit%)=MIN(ADD(vpos%(posit%),DIV(h%,chrbh%)),SUB(ygrap%,DIV(h%,chrbh%)))
  2394.   GOSUB cursor_resize
  2395.   GOSUB calc_slid(handle&)
  2396.   GOSUB do_redraw(0)
  2397. CASE 2                   ! move screen down one line or cursor down one line.
  2398.   GOSUB up_key
  2399.   GOSUB draw_cursor(tpox%,tpoy%,TRUE)
  2400. CASE 3
  2401.   GOSUB down_key         ! move screen up one line or cursor up one line.
  2402.   GOSUB draw_cursor(tpox%,tpoy%,TRUE)
  2403. ENDSELECT
  2404. RETURN
  2405. '
  2406. > PROCEDURE arrow_graphic
  2407. ' PURPOSE : updates a graphic windows contents according to a arrow button
  2408. '           event or before or after slider bar event.
  2409. '
  2410. SELECT MENU(5)
  2411. CASE 0                 ! move screen down one complete window size position.
  2412.   LET vpos%(posit%)=MAX(SUB(vpos%(posit%),h%),0)
  2413. CASE 1                 ! move screen up one complete window size position.
  2414.   LET vpos%(posit%)=MIN(ADD(vpos%(posit%),h%),SUB(ygrap%,h%))
  2415. CASE 2                 ! move screen down 10 pixels.
  2416.   LET vpos%(posit%)=MAX(SUB(vpos%(posit%),10),0)
  2417. CASE 3                 ! move screen up 10 pixels.
  2418.   LET vpos%(posit%)=MIN(ADD(vpos%(posit%),10),SUB(ygrap%,h%))
  2419. CASE 4                 ! move screen right one complete window size position.
  2420.   LET hpos%(posit%)=MAX(SUB(hpos%(posit%),b%),0)
  2421. CASE 5                 ! move screen left one complete window size position.
  2422.   LET hpos%(posit%)=MIN(ADD(hpos%(posit%),b%),SUB(xgrap%,b%))
  2423. CASE 6                 ! move screen right 10 pixels.
  2424.   LET hpos%(posit%)=MAX(SUB(hpos%(posit%),10),0)
  2425. CASE 7                 ! move screen left 10 pixels.
  2426.   LET hpos%(posit%)=MIN(ADD(hpos%(posit%),10),SUB(xgrap%,b%))
  2427. ENDSELECT
  2428. GOSUB calc_slid(handle&)
  2429. GOSUB do_redraw(0)
  2430. RETURN
  2431. '
  2432. '
  2433. '  Window Redraw Procedures
  2434. ' --------------------------
  2435. '
  2436. > PROCEDURE do_redraw(do_line%)
  2437. ' PURPOSE : prepare window for redraw by getting windows size.
  2438. '
  2439. ~WIND_GET(handle&,4,w1%,w2%,w3%,w4%)
  2440. GOSUB xredraw(w1%,w2%,w3%,w4%)
  2441. RETURN
  2442. '
  2443. > PROCEDURE wm_redraw
  2444. ' PURPOSE : get multi events first windows clip rectangle.
  2445. '
  2446. GOSUB xredraw(MENU(5),MENU(6),MENU(7),MENU(8))
  2447. RETURN
  2448. '
  2449. > PROCEDURE xredraw(m5%,m6%,m7%,m8%)
  2450. ' PURPOSE : is there any more clip rectangles and if there are
  2451. '           get clip rectangle size.
  2452. '
  2453. ~WIND_UPDATE(1)                             ! hide mouse
  2454. ~WIND_GET(handle&,11,w1%,w2%,w3%,w4%)
  2455. WHILE w3% OR w4%
  2456.   LET tb%=ADD(w1%,w3%)
  2457.   LET th%=ADD(w2%,w4%)
  2458.   LET tx%=MAX(w1%,m5%)
  2459.   LET ty%=MAX(w2%,m6%)
  2460.   LET tb%=SUB(MIN(tb%,ADD(m5%,m7%)),tx%)
  2461.   LET th%=SUB(MIN(th%,ADD(m6%,m8%)),ty%)
  2462.   IF tb%>0 AND th%>0
  2463.     GOSUB redraw(handle&,tx%,ty%,tb%,th%)
  2464.   ENDIF
  2465.   ~WIND_GET(handle&,12,w1%,w2%,w3%,w4%)
  2466. WEND
  2467. ~WIND_UPDATE(0)                             ! redraw mouse
  2468. RETURN
  2469. '
  2470. > PROCEDURE redraw(handle&,x%,y%,b%,h%)
  2471. ' PURPOSE : identify type of window and clip window before redraw.
  2472. '
  2473. IF b%>SUB(scrb%,x%)
  2474.   LET b%=SUB(scrb%,x%)
  2475. ENDIF
  2476. ~WIND_GET(handle&,4,w1%,w2%,w3%,w4%)
  2477. CLIP x%,y%,b%,h% OFFSET w1%,w2%
  2478. SELECT type$(posit%)
  2479. CASE "T"
  2480.   GOSUB redraw_text
  2481. CASE "G"
  2482.   GOSUB redraw_graphic
  2483. ENDSELECT
  2484. RETURN
  2485. '
  2486. > PROCEDURE redraw_line
  2487. ' PURPOSE : redraw text line.
  2488. '
  2489. IF tpoy%>=0
  2490.   ~WIND_GET(handle&,4,w1%,w2%,w3%,w4%)
  2491.   CLIP x%,y%,b%,h% OFFSET w1%,w2%
  2492.   TEXT -MUL(hpos%(posit%),chrbb%),ADD(SUB(cury%,y%),13),txt$(PRED(tpoy%))+SPACE$(80)
  2493. ENDIF
  2494. RETURN
  2495. '
  2496. > PROCEDURE redraw_text
  2497. ' PURPOSE : redraw complete text window.
  2498. '
  2499. IF do_line%=1
  2500.   GOSUB redraw_line
  2501. ELSE
  2502.   IF vpos%(posit%)<0
  2503.     LET vpos%(posit%)=0
  2504.   ENDIF
  2505.   PBOX -2,-2,999,999
  2506.   CLIP x%,y%,b%,h% OFFSET w1%,w2%
  2507.   FOR line%=0 TO (h% DIV chrbh%)
  2508.     TEXT -MUL(hpos%(posit%),chrbb%),ADD(MUL(line%,chrbh%),13),txt$(ADD(line%,vpos%(posit%)))
  2509.   NEXT line%
  2510.   GOSUB draw_button
  2511. ENDIF
  2512. GOSUB draw_cursor(tpox%,tpoy%,TRUE)
  2513. GOSUB wind_title(handle&," Text Window ")
  2514. GOSUB wind_info(handle&,"Col:"+STR$(tpox%)+"  Row:"+STR$(tpoy%)+"  "+insert$)
  2515. RETURN
  2516. '
  2517. > PROCEDURE redraw_graphic
  2518. ' PURPOSE : redraw complete graphic window.
  2519. '
  2520. LET p%(0)=SUB(ADD(hpos%(posit%),x%),w1%)
  2521. LET p%(1)=SUB(ADD(vpos%(posit%),y%),w2%)
  2522. LET p%(2)=PRED(ADD(p%(0),b%))
  2523. LET p%(3)=PRED(ADD(p%(1),h%))
  2524. LET p%(4)=x%
  2525. LET p%(5)=y%
  2526. LET p%(6)=PRED(ADD(x%,b%))
  2527. LET p%(7)=PRED(ADD(y%,h%))
  2528. LET p%(8)=3
  2529. LET smfdb%(0)=VARPTR(raster$)
  2530. BITBLT smfdb%(),dmfdb%(),p%()
  2531. GOSUB draw_button
  2532. RETURN
  2533. '
  2534. '
  2535. '  Miscellanous Window Procedures
  2536. ' --------------------------------
  2537. '
  2538. > FUNCTION generate_handle(attr&)
  2539. ' PURPOSE : generate new window handle and storage space.
  2540. '
  2541. hand&=WIND_CREATE(attr&,scrx%,scry%,scrb%,scrh%)
  2542. IF hand&=-1
  2543. ALERT 1,"TOO MANY OPEN WINDOW!|Try closing some windows!",1," Damn! ",void%
  2544. ENDIF
  2545. RETURN hand&
  2546. ENDFUNC
  2547. '
  2548. > PROCEDURE open_window(type$)
  2549. ' PURPOSE : open window and prepare title and info line.
  2550. '
  2551. ~WIND_UPDATE(1)
  2552. GOSUB close_old(handle&)
  2553. LET type$(posit%)=type$
  2554. SELECT type$
  2555. CASE "G"
  2556. LET handle&=FN generate_handle(CARD(4095))
  2557. GOSUB wind_title(handle&," Graphics Window ")
  2558. CASE "T"
  2559. LET handle&=FN generate_handle(CARD(511))
  2560. GOSUB wind_title(handle&," Text Window ")
  2561. ENDSELECT
  2562. GOSUB wind_info(handle&,file$(posit%)+"  "+STR$(posit%))
  2563. ~WIND_OPEN(handle&,xpos%(posit%),ypos%(posit%),wsiz%(posit%),hsiz%(posit%))
  2564. GOSUB calc_slid(handle&)
  2565. ~WIND_UPDATE(0)
  2566. RETURN
  2567. '
  2568. > PROCEDURE close_old(handle&)
  2569. ' PURPOSE : closes an existing window and deallocates its memory
  2570. '           and frees its handle.
  2571. '
  2572. IF handle&>0
  2573. GOSUB draw_cursor(tpox%,tpoy%,FALSE)
  2574. ~WIND_CLOSE(handle&)
  2575. ~WIND_DELETE(handle&)
  2576. ENDIF
  2577. RETURN
  2578. '
  2579. > PROCEDURE wind_title(handle&,title$)
  2580. ' PURPOSE : sets a windows title bar.
  2581. '
  2582. LET title$=title$+CHR$(0)
  2583. LET title%=V:title$
  2584. ~WIND_SET(handle&,2,CARD(SWAP(title%)),CARD(title%),0,0)
  2585. RETURN
  2586. '
  2587. > PROCEDURE wind_info(handle&,info$)
  2588. ' PURPOSE : sets a windows information line.
  2589. '
  2590. LET info$=info$+CHR$(0)
  2591. LET info%=V:info$
  2592. VSYNC
  2593. ~WIND_SET(handle&,3,CARD(SWAP(info%)),CARD(info%),0,0)
  2594. RETURN
  2595. '
  2596. > PROCEDURE get_textsize(VAR chrb%,chrh%,chrbb%,chrbh%)
  2597. ' PURPOSE : gets the systems current font size and type.
  2598. '
  2599. LET v%=CONTRL(6)
  2600. GEMSYS 77
  2601. CONTRL(6)=GINTOUT(0)
  2602. VDISYS 38
  2603. CONTRL(6)=v%
  2604. LET chrb%=PTSOUT(0)
  2605. LET chrh%=PTSOUT(1)
  2606. LET chrbb%=PTSOUT(2)                           ! Text Width pixels
  2607. LET chrbh%=PTSOUT(3)                           ! Text Height pixels
  2608. DEFTEXT 1,0,0,chrh%,1
  2609. RETURN
  2610.