*
* Utility to display text files. Roughly same as
* LIRE2.0 but with a custom screen
* Reads color codes "n]"
* Code reentrant.
*
* by     Charles VASSALLO                           Dec 89
* 33 route des Traouieros
* 22730 TREGASTEL - France
* 
* All rights reserved
* Can be freely distributed 
* Assembled with DEVPAC 2.0

* Color codes are the same as in Lire2.0
*  p]     sets color pen to 'p'
*  C]RGBXYZ.... sets a new palette
*  ] in front of a line announces special color codes in the line:
*           ]pb    => pen to 'p', background to 'b'



*----------------------------------------

********* From Include files and fd_files :

* Exec library
ExecBase=4
OpenLib=-408
CloseLibrary=-414
AllocMem=-198
FreeMem=-210
WaitPort=-384
GetMsg=-372
ReplyMsg=-378
Forbid=-132
Permit=-138
FindTask=-294

MEMF_CLEAR=65536

* calls to Amiga Dos:

Open=-30
Close=-30-6
Read=-30-12
Write=-30-18
Lock =-84
UnLock =-90
Examine=-102
CurrentDir=-126

MODE_NEWFILE=1006
MODE_OLDFILE=1005

*calls to Intuition
OpenScreen=-198
CloseScreen=-66
OpenWindow=-204
CloseWindow=-72
RefreshGadgets=-222
ViewAddress=-294

* calls to graphics
LoadRGB4=-192
Move=-240
Draw=-246
SetAPen=-342
SetBPen=-348
SetDrMd=-354
Text=-60
BltClear=-300
BltBitMap=-30
InitBitMap=-390
AllocRaster=-492
FreeRaster=-498

* end of amiga.lib call definitions





*************** Workbench/CLI interface ********************



start:
   move.l a0,a5
   move.l d0,d5

* First, opens general variables buffer. THIS BUFFER WILL BE POINTED
* BY A4 THROUGHOUT THE PROGRAM

   move.l ExecBase,a6
   move.l #BufferLength,d0
   move.l #MEMF_CLEAR+2,d1
   jsr    AllocMem(a6)
*   tst.l  d0
   beq   dosexit
   move.l d0,a4

* opens DosLibrary
   lea    dosname(pc),a1
   jsr    OpenLib(a6)
   move.l d0,dosbase(a4)
   beq    CloseDos         ; no dos.lib !!

   suba.l a1,a1
   jsr    FindTask(a6)     ; Process in d0
   move.l d0,a3
   tst.l  $AC(a3)          ; pr_CLI
   beq.s    FromWb         ; exit if started from CLI

* invocation from CLI - d5=number of character - a5 = CLI buffer
* we recopy the file name directly into the TempA buffer

   move.l a4,a2
   adda.l #TempA,a2
   move.l a2,file(a4)
   moveq  #0,d1    number of significant characters
* removes initial spaces or control characters
CLI1:   move.b (a5)+,d0
   subq.l #1,d5
   bmi.s  CLI3
   cmp.b  #' ',d0
   ble.s  CLI1
   
CLI2:   move.b d0,(a2)+
   addq.l #1,d1     one more significant character
   move.b (a5)+,d0
   subq.l #1,d5
   bmi.s  CLI3
   cmp.b  #' ',d0   we stop at the next space or control character
   bgt.s  CLI2

CLI3:    move.b #0,(a2)
   tst.w  d1
   beq.s  CloseDos   no significant character

   jsr    Main(pc)
   bra.s  CloseDos

*---------------------------------------------------------
* waits for Workbench message
FromWb:
   lea    $5C(a3),a0   ; pr_MsgPort
   jsr    WaitPort(a6)
   lea    $5C(a3),a0
   jsr    GetMsg(a6)
   move.l d0,WbMessage(a4)
   move.l d0,a2


* How many arguments ?
   move.l $1C(a2),d0
   cmp.w  #2,d0      ; there must be 2 arguments
   bne.s  fini
 
* Finds the file to be displayed and calls main program   
   move.l $24(a2),d0           ; sm_ArgList
   beq.s  CloseDos
   move.l d0,a2
   move.l 8(a2),d1             sets the currentdir
   move.l dosbase(a4),a6
   jsr    CurrentDir(a6)
   move.l 12(a2),file(a4)
   jsr    Main(pc)


fini:   
   move.l ExecBase,a6     
   jsr    Forbid(a6)            Forbid is urged by RKM
   move.l WbMessage(a4),a1
   jsr    ReplyMsg(a6)

* closes Dos
CloseDos:
   move.l ExecBase,a6
   move.l dosbase(a4),a1
   jsr    CloseLibrary(a6)
   move.l a4,a1                 frees general variables buffer
   move.l #BufferLength,d0
   jsr    FreeMem(a6)

dosexit:
   rts



**********************************************************************
*
* Main Program
*
**********************************************************************

Main:


* Opens libraries, workspaces, special display and gadgets
* Opens the text file and displays the first lines
* Fills the table of starts/ends of lines
   jsr  OpenAll(pc)
   beq  CloseAll   ; failure

* arrival of messages

www: move.l UserPort(a4),a0
     move.l ExecBase,a6
     jsr    WaitPort(a6)   
     move.l #$10000,delaynb(a4)

ww1: bsr     ReadMessage     ; => gadget address in d2
ww2: beq.s   www             ;  no message

   move.l FirstLine(a4),d7

* Now, gadget identification. Each gadget structure is 44 bytes.
* Successively : LineUp, LineDown,Exit, Page
* Only GADGETUP is meaningful for Page gadget

   sub.l  a4,d2              ;   d2 must
   sub.l  #Gadget1,d2        ;   be either 0, or 44, or 88, or 132

   cmpi.w #132,d2            ; is it Page Gadget ?
   bne.s  NoPage             ; ... no
   cmp.w  #$40,a5            ; GADGETUP ?
   beq    Page
   bra.s  ww1                ;  ... no -> no action
NoPage:
   cmp.w  #$20,a5            ; GADGETDOWN ?
   bne.s   ww1               ;  ...no
   cmpi.w  #44,d2
   bhi    CloseAll           ; exit
   bcs.s  LineUp  

* ---------------------------------------------------
LineDown:
   addq.l #1,d7
   cmp.l  LastFirstLine(a4),d7
   bhi.s    ld3
   bne.s    ld1               ; if FirstLine is LastFirstLine,
   lea    AddedLine2(pc),a5 ;   ".../..." => "end of text"
   jsr    DispLastLine(pc)

ld1: 
   move.l d7,FirstLine(a4)
   moveq  #10,d1
   moveq  #2,d3
   jsr    scroll(pc)
   move.l d7,d0
   move.l NL0(a4),d4
   add.l  d4,d0
   subq.l #1,d0
   jsr    ExtraLine(pc)

* repeat after a short delay, until a GADGETUP event

ld2:
   bsr.s  delay
   bne.s  LineDown           ; no GADGETUP

ld3:
   move.l FirstLine(a4),d0     ; after a GADGETUP, we refresh
   subq.l #1,d0                ; the prop. gadget
   swap   d0 
   move.l LastFirstLine(a4),d1
   divu   d1,d0
   move.w d0,HPot(a4)
   move.l a4,a0
   adda.l #Gadget1,a0
   move.l mywindow(a4),a1
   suba.l a2,a2
   move.l intuibase(a4),a6
   jsr    RefreshGadgets(a6)
   bra    ww1

delay:
   move.l delaynb(a4),d0
   move.l d0,d1
   lsr.l  #2,d1
   sub.l  d1,d0
   move.l d0,delaynb(a4)
aaa:    dbf  d0,aaa
   bsr.s  ReadMessage
   cmp.w  #$40,a5            ; GADGETUP checking
   rts

* --------------------------------------
* d7 is already loaded with FirstLine

LineUp: 
   cmp.l  #1,d7
   beq.s  ld3
   cmp.l  LastFirstLine(a4),d7 ; if FirstLine = LastFirstLine,
   bne.s  lu1                  ; we must replace "end of text"
   lea    AddedLine1(pc),a5    ; with ".../..." at the end.
   jsr    DispLastLine(pc)


lu1:   subq.l #1,d7
   move.l d7,FirstLine(a4)
   moveq  #10,d3
   moveq  #2,d1
   bsr.s  scroll
   move.l d7,d0
   moveq  #1,d4
   bsr.s  ExtraLine

lu2:
   bsr.s  delay
   beq.s  ld3                   ;  GADGETUP
   bra.s  LineUp



* ---------------------------------------
* Page change. 
Page:
   move.l LastFirstLine(a4),d0
   mulu   HPot(a4),d0
   swap   d0
   and.l  #$FFFF,d0
   addq.w #1,d0
   cmp.w  d7,d0       ; if first line unchanged
   beq    ww1         ;   no action
   move.l d0,FirstLine(a4)
   bsr.s  DisplayLines
   bra    ww1


*************** Reads  / Replies messages *********************

* IAddress -> d2 (gadget address)
* Class    -> a5 (GADGETUP/DOWN)

ReadMessage:
   move.l UserPort(a4),a0 
   move.l ExecBase,a6
   jsr    GetMsg(a6)
   tst.l  d0           ; if no message queueing,
   beq.s    rmxit      ;  return to wait
   move.l d0,a1        ; a1 = message address 
   move.l $1C(a1),d2   ; d2 = IAddress (gadget address)
   move.l $14(a1),a5   ; a5 = Class
   jsr    ReplyMsg(a6) ; answer (address already in a1)
rmxit: rts


************* writes the extra line for LineUp/Down ******
* Before calling, define :
*   d0 :  number of the line in the text
*   d4 :  number of this line in the screen

ExtraLine:
   asl.l  #3,d4   ; converts d1 into raster-Y
   move.l LineAddress(a4),a3   
   subq.l #1,d0
   asl.l  #2,d0
   adda.l d0,a3
   bsr    prtxt
   rts

************* scrolling by 1 line *************************
* d1 and d3 must be defined before the call

scroll:
   move.l  d7,-(sp)
   move.l  BitMap(a4),a0
   move.l  a0,a1
   moveq   #0,d0
   moveq   #0,d2
   move.l  #640,d4      ; sizeX (640 pixels)
   move.l  NL0(a4),d5   ; computing sizeY
   subq.l  #1,d5
   asl.l   #3,d5      ; ... into d5
   move.l  #$CC,d6      ; value found with trials/errors
   move.l  #$FF,d7
   move.l  TempA(a4),a2
   move.l  gfxbase(a4),a6
   jsr     BltBitMap(a6)
   move.l  (sp)+,d7
   rts 

********* displays N lines **********************

* displays NL0 lines (if possible) starting from 'FirstLine'
* adds a last line indicating whether the file is ended or not
* register conventions : d3=number of lines (NL0 or less)

DisplayLines:
   move.l NL0(a4),d3
   move.l FirstLine(a4),d0
   move.l LastFirstLine(a4),d1
   cmp.l  d1,d0
   blt.s  DisplayText
   move.l d1,FirstLine(a4)
   move.l LineNumber(a4),d3
   sub.l  d1,d3

* display d3 lines starting from number 'FirstLine'.
* Register conventions :
*  d4=current raster-Y 
*  a3 => current address of the next line to be displayed

DisplayText:


   moveq  #8,d4              ; initial raster-Y
   move.l LineAddress(a4),a3 ; => address of 1st line
   move.l FirstLine(a4),d0   ; each line corresponds
   subq.l #1,d0              ;    to an increment of 4 in the list
   asl.l  #2,d0              ;    of addresses
   adda.l d0,a3              ; => address of 'FirstLine' line
   subq.w #1,d3              ; d3 will be used as loop counter

disp:
   bsr.s  prtxt              ; prints the line pointed by a3 (post incremented)
   addq.w #8,d4              ; updates raster-Y   
   dbf    d3,disp

* addition of the last line (13 characters), if ShortNote non zero
*   (AddedLine1 or 2)
ddd:
   move.b ShortNote(a4),d0
   beq.s  dispExit

   lea    AddedLine1(pc),a5
   move.l LastFirstLine(a4),d0
   cmp.l  FirstLine(a4),d0
   bgt.s  DispLastLine       ; FirstLine < LastFirstLine
   lea    AddedLine2(pc),a5  ; we are at the end of the text

DispLastLine:
   move.l NL0(a4),d4          ; "end of text" at bottom
   asl.w  #3,d4
   addi.w #12,d4
   move.l #400,d0
   bsr.s  Cursor
   moveq  #13,d0
   bsr    prtxt3


dispExit:   rts


*********  print routines *************************

* pen position set at X=d0 and Y=d4

Cursor:
   move.l  d4,d1
   move.l myrp(a4),a1
   move.l gfxbase(a4),a6
   jsr    Move(a6)
   rts

* -------------------------------------   

*** prtxt = entry to print the line pointed by a3, on the raster line of
*           ordinate d4
* a3 is  incremented by 4

* REGISTERS NOT TO BE MODIFIED : d3,d4,d7/a3 (after incr.), a4
* CONVENTIONS : throughout the print routines, a5 will point to the first
*               printable character 
*               d6 = maximum number of characters not yet printed

prtxt:

* first clear the line

   move.l BitMap(a4),a2
   adda.l #8,a2         a2 points to 1st plane
   move.l gfxbase(a4),a6
   move.l d4,d2
   subq.w #6,d2                this function is never called with d2<8
   asl.w  #4,d2                16*d2
   move.l d2,d0
   asl.w  #2,d2                64*d2
   add.w  d0,d2                80*d2 (faster than mulu #80,d2)
Cll1:
   move.l (a2)+,d0
   beq.s  prtxt0
   move.l d0,a1
   adda.l d2,a1
   move.l #640,d0             for 8 lines of 80 bytes
   moveq  #0,d1
   jsr    BltClear(a6)
   bra.s  Cll1

prtxt0:
   movea.l (a3)+,a5            a5=address of current line
   cmp.b   #$0A,(a5)
   beq.s   prtexit             nothing to print

* initialises pen and character counter
   moveq   #80,d6
   moveq   #0,d0
   bsr.s   Cursor 

* special line ?
   move.b  (a5),d0
   cmp.b   #']',d0
   beq.s   special

* color code p] or palette code C] ?
   cmpi.b  #']',1(a5)
   bne.s   prtxt1
   cmpi.b  #'C',d0
   beq     ChangePalette
   bsr.s   GoodColor  
   bhi.s   prtxt1
   bsr     ColorPen
   adda.l  #2,a5
prtxtcolor:
   bsr.s   prtxt1             print the line and exit through ColorPen
   moveq   #1,d0                (reset pen/bg colors to 0/1)
   bra     ColorPen

* prints the line up to its end

prtxt1:
   move.l (a3),d0              address of next line
   subq.l #1,d0

* prints from address a5 to address d0

prtxt2:
   sub.l  a5,d0                 number of characters to be printed
   sub.w  d0,d6                 updates d6
   bpl.s  prtxt3
   add.w  d6,d0                 
prtxt3:
   move.l a5,a0
   move.l myrp(a4),a1
   move.l gfxbase(a4),a6
   jsr    Text(a6)
prtexit:
   rts



* --------------------------------------
* checks whether d0 is a correct color and returns with the 
* color number in d0 (0 to ColorMax). Must be followed with "bhi incorrect"

GoodColor:
   subq.b  #1,d0               because it's more friendly to number
   bsr     LoadHexd0             colors from 1 (instead of 0)
   bhi.s   GCexit              not a hex number
   cmp.b   #3,d0               d0 must be lower than ColorMax
GCexit:
   rts


*----------------------------------
* analysis of special lines

special:
   adda.l  #1,a5
spe0:
   move.l  a5,a0
spe1:
   move.b  (a0)+,d0
   cmp.b   #$0A,d0             final linefeed ?
   bne.s   spe11                ... no
   bra.s   prtxtcolor           ... yes : print the end of the line
*                               and reset pen/bg colors to 1/0

spe11:
   cmp.b   #']',d0
   bne.s   spe1
spe2:
   move.l  a0,d2               saves a0 (just after ']')
   move.l  a0,d0
   subq.l  #1,d0
   bsr.s   prtxt2              prints from a5 to d0
   move.l  d2,a5  
   move.l  a5,a0
   suba.l  #1,a5               (a5) => ']'
   moveq   #0,d0
   move.b  (a0)+,d0
* color codes ?
   bsr.s   GoodColor
   bhi.s   spe1
   swap    d0
   move.b  (a0)+,d0
   bsr.s   GoodColor
   bhi.s   spe1
   swap    d0
   bsr     ColorPen
   adda.l  #3,a5
   bra.s   spe0       



************* Opens libraries / file / initial display ************

* returns z=0 in case of failure (then : bne success/ beq failure)
* Within this section, a6=ExecBase, a5=dosbase (already defined)

* First, opens libraries. With Graphics.library, checks PAL/NTSC
* display
OpenExit1:  rts

OpenAll:
   move.l dosbase(a4),a5

* Looks for the file and reads its length. A temporary FileInfoBlock
* (260 bytes) is taken in the general buffer variable, just after
* fhandle and FileLength variables 

   move.l file(a4),d1   
   moveq  #-2,d2           ; -2 = SHARED_ACCESS
   jsr    Lock(a5)
   move.l d0,fhandle(a4)
   beq.s   OpenExit1

* prepares a FileInfoBlock structure
   move.l a4,d2
   add.l  #FileLength+4,d2            ; saves FileInfoBlock address

* reads the length of the file
   move.l fhandle(a4),d1
   jsr    Examine(a5)    ; loads FileInfoBlock structure
   tst.l  d0
   beq.s  OpenExit1      ; Examine failed
   move.l d2,a1
   move.l 124(a1),FileLength(a4) ; file length in 40(a4)

* unlocks the file
   move.l fhandle(a4),d1
   jsr    UnLock(a5)


* opens graphics and intui.libs. Checks PAL/NTSC
 
   lea    gfxname(pc),a1   ; opens graphics.library
   move.l ExecBase,a6
   jsr    OpenLib(a6)
   move.l d0,gfxbase(a4)
   beq.s  OpenExit1      ; if failure
   move.l d0,a1
   move.w $D8(a1),d0       ; NormalDisplayRows
   lea    NwHeight(pc),a0 
   move.w d0,(a0)
   lea    NewScreen(pc),a0
   move.w d0,6(a0)         ; Height in NewScreen
   lsr.w  #3,d0
   subq.w #3,d0
   move.w d0,NL0+2(a4)       ; number of displayed lines

   lea    intuiname(pc),a1 ; opens intuition.library
   jsr    OpenLib(a6)
   move.l d0,intuibase(a4)
   beq.s  OpenExit1       ; if failure


* allocates ram for copying the file

   move.l FileLength(a4),d0
   move.l #MEMF_CLEAR+2,d1
   jsr    AllocMem(a6)
   move.l d0,FileCopy(a4)
   beq    OpenExit



* Opens the file and copies it
   move.l file(a4),d1
   move.l #1005,d2       ; OLD_FILE
   jsr    Open(a5)
   move.l d0,d7          ; saves file handle
   beq    OpenExit

   move.l d0,d1
   move.l FileCopy(a4),d2
   move.l FileLength(a4),d3
   jsr    Read(a5)

* Closes the file
   move.l d7,d1
   jsr    Close(a5)

      
* Counts the number of lines (each line is ended by $0A)
* Splits lines larger than 80 characters
* This number + 1 => LineNumber
* LastFirstLine = number of the first line for the last page
* d3 contains the length of the text

LineCount:
   move.l FileLength(a4),d3
   clr.l  d0   ; will contain the line number
   move.l FileCopy(a4),a2

cnt00: move.l a2,a3
cnt0:  subq.l  #1,d3
   beq.s  cnt04 
   cmpi.b #$0A,(a2)+
   bne.s  cnt0
   addq.l #1,d0             one linefeed more
   move.l a2,d1    
   sub.l  a3,d1             is the line larger than 80?
   cmp.w  #81,d1
   bls.s  cnt00             ... no. Let's go on

* A line larger than 80 is split by replacing a space (as close to a3+81
* as possible) with a linefeed, EXCEPT if the first character is ']'
   cmp.b #']',(a3)
   beq.s  cnt00
cnt2: move.l a3,d1 
   adda.l #81,a3   
   cmp.l  a3,a2
   bls.s  cnt00             the splitting is finished
cnt03: cmp.l a3,d1
   bcc.s  cnt00             we did not find any space. So much the worse!
   cmp.b  #$20,-(a3)         (the line will be truncated)
   bne.s  cnt03
   move.b #$0A,(a3)+
   addq.l #1,d0
   bra.s  cnt2

cnt04:
   addq.l #1,d0
   move.l d0,LineNumber(a4)
   move.l NL0(a4),d1
   move.l d1,d2
   subq.l #2,d1
   swap   d1
   divu   d0,d1
   move.w d1,HBody(a4)  ; size of the prop.gadget knob
   sub.l  d2,d0
   cmp.l  #1,d0
   bge.s  lfl
   moveq  #1,d0
lfl: 
   move.l d0,LastFirstLine(a4)
   subq.w #1,d0
   move.b d0,ShortNote(a4)  ; 0 if only one page
   

* memorizes the addresses of the start of each line in a list 
* beginning at (LineAddress). We begin in allocating the ram
* needed by this list,i.e. 4*(LineNumber+1) (this buffer must
* contain the beginning and the end of the file, in addition to
* the beginning of each line after a line-feed $0A)

   move.l LineNumber(a4),d0 
   move.l ExecBase,a6
   addq.l #2,d0
   asl.l  #2,d0             ; for each line, 1 address=4 bytes
   move.l #MEMF_CLEAR+3,d1 
   jsr    AllocMem(a6)    
   move.l d0,LineAddress(a4)
   beq    OpenExit

   move.l d0,a1
   move.l FileCopy(a4),a2
   move.l a2,(a1)+      ; start of line 1
   move.l FileLength(a4),d3 
cnt3:   cmpi.b #$0A,(a2)+           notice one can't use a dbcc loop
   bne.s  cnt4                      because possibly d3 > 32768
   move.l a2,(a1)+
cnt4: subq.l #1,d3
   bne.s  cnt3
   move.l a2,(a1)+       ; last (+1) line




* completes the NewWindow structure with Gadgets

   move.l a4,a1               ; clears 4*11 long words for
   adda.l #Gadget1,a1         ;  the 4 gadgets
   lea    FirstGadget(pc),a0
   move.l a1,(a0)             ; links gadget to NewWindow
   move.l a1,a0
   move.l #43,d0
gdg0: move.l #0,(a1)+
   dbf    d0,gdg0

   moveq  #3,d0               ; for 4 gadgets
   lea    Xgdg(pc),a1   
Gdgloop: move.l a0,d1
   addi.l #44,d1
   move.l d1,(a0)+            ; link with the next gadget
   move.w (a1)+,(a0)+         ; gadget-X
   lea    BoolGdg(pc),a2
gdgl: move.w (a2)+,(a0)+      ; fills Y, flags,... 
   bne.s  gdgl
   move.l d1,a0               ; other words remain cleared
   dbf    d0,Gdgloop
   suba.l #44,a0
   move.l  #0,(a0)            ; clears the last link

   move.b  ShortNote(a4),d0
   bne.s   propgdg
   move.l  #0,-44(a0)

* completes prop. gadget structure
propgdg:
   move.w #PropW,8(a0)
   move.w #3,16(a0)   
   move.l a4,a1
   adda.l #PropBorder,a1
   move.l a1,18(a0)           ; links Border to gadget structure
   adda.l #PropInfo-PropBorder,a1
   move.l a1,34(a0)           ; links PropInfo to gadget structure
   move.w #PropInfoFlag,(a1)


* Opens a 640 x 200 screen, with 'Depth(a4)' planes,
*  then a  borderless window with convenient gadgets

OpenScr:
   
   lea    NewScreen(pc),a0
   move.l intuibase(a4),a6
   jsr    OpenScreen(a6)
   move.l d0,myscreen(a4)
   beq    OpenExit
   lea    Nwindow(pc),a0
   move.l d0,$1E(a0)          ; ($1E=nw_Screen)
   addi.l #44,d0              ; d0=Viewport
   move.l d0,myvp(a4)
* (the loading of myscreen in NewWindow makes the program non re-executable
*  in the case of two tasks opening the window at the same time. Highly
*  improbable. Could be fixed with forbidding)


OpenWdw:
   jsr    OpenWindow(a6)
   move.l d0,mywindow(a4)     ; mywindow
   beq.s  OpenExit            ; window not opened
   move.l d0,a1
   move.l 86(a1),UserPort(a4) ; wd_UserPort=86 => UserPort
   move.l $32(a1),d0         ; wd_RPort = $32
   move.l d0,myrp(a4)         ; => RastPort
   addq.l #4,d0
   move.l d0,a1
   move.l (a1),BitMap(a4)       BitMap


   lea    MyColors(pc),a1
   bsr    ChangeColorTable     sets up custom colors

* prints gadget captions. If ShortNote=0, only 'EXIT'

prgdg:
   moveq  #3,d0         ; for color 3
   bsr.s  ColorPen

wgdg:   move.l #Xgdg5+16,d0
   moveq  #0,d4
   move.w NwHeight(pc),d4
   subq.w #2,d4
   bsr    Cursor
   lea    TxtGdg2(pc),a5
   moveq  #4,d0
   bsr    prtxt3
   move.b ShortNote(a4),d0
   beq.s    wgdg1
   move.l #Xgdg1+16,d0
   bsr    Cursor
   lea    TxtGdg1(pc),a5
   moveq  #12,d0
   bsr    prtxt3
wgdg1:
   moveq   #1,d0         ; for color 1
   bsr.s   ColorPen

* displays the first lines

   move.l #1,FirstLine(a4)
   jsr    DisplayLines(pc)



   moveq  #1,d0   ; sets Z=0 (success flag)
OpenExit:  rts

**************************** colors ******************************
* d0 must be loaded with pen color in lower word, bg color in upper word

ColorPen:
   move.l gfxbase(a4),a6
   move.l myrp(a4),a1
   movem.l d0/a1,-(sp)
   jsr    SetAPen(a6)
   movem.l (sp)+,d0/a1
   swap   d0
   jsr    SetBPen(a6)
   rts



********* Changes the palette ****************************
* a5 points to a line C]0rgb0rgb0rgb0rgb. Loads the triplets rgb
* into ColorTable and calls RGB4 

ChangePalette:
   adda.l #2,a5
   move.l a4,a1
   adda.l #ColorTable,a1
   move.l a1,a0
   moveq  #0,d6

chp1: 
   bsr.s  LoadHexa
   bhi.s  chpexit
   move.b d0,(a0)+
   bsr.s  LoadHexa
   bhi.s  chpexit
   move.w d0,d1
   lsl.w  #4,d1
   bsr.s  LoadHexa
   bhi.s  chpexit
   add.b  d0,d1
   move.b d1,(a0)+
   addq.w #1,d6
   cmp.b  #$0A,(a5)
   bne.s  chp1
   move.w d6,d0

* Change ColorTable (address loaded in a1
*               and number of colors in d0)

ChangeColorTable:
   moveq  #4,d0
   move.l myvp(a4),a0
   move.l gfxbase(a4),a6
   jsr    LoadRGB4(a6)
chpexit:  rts

* changes a hex character (0,1..F) from (a5)+  into binary. Must be
* followed with a test "bhi non_hexa"

LoadHexa:
   move.b (a5)+,d0
LoadHexd0:
   sub.b  #$30,d0
   cmp.b  #9,d0
   bls.s  OK
   subq.b #7,d0
   cmp.b  #15,d0
   bls.s  OK
   sub.b  #$20,d0
   cmp.b  #15,d0
OK:  rts


******************* Closing ************************

* Closes the window/screen and all the elements opened in OpenAll 

CloseAll:



   move.l intuibase(a4),a6
   move.l mywindow(a4),d0
   beq.s  clscreen
   move.l d0,a0
   jsr    CloseWindow(a6)

clscreen:
   move.l myscreen(a4),d0
   beq.s  clbuf1
   move.l d0,a0
   jsr    CloseScreen(a6)


clbuf1:   move.l ExecBase,a6
   move.l LineAddress(a4),d0 ; frees buffer LineAddress
   beq.s  clbuf2
   move.l d0,a1
   move.l LineNumber(a4),d0
   addq.l #1,d0
   asl.l  #2,d0
   jsr    FreeMem(a6)

clbuf2: 
   move.l FileCopy(a4),d0   ; frees buffer FileCopy
   beq.s  clintui
   move.l d0,a1
   Move.l FileLength(a4),d0 
   jsr    FreeMem(a6)


clintui:
   move.l intuibase(a4),d0   ; closes  intuition.library
   beq.s  clgfx
   move.l d0,a1
   jsr    CloseLibrary(a6)

clgfx: 
   move.l gfxbase(a4),d0   ; closes graphics.library
   beq.s  exit
   move.l d0,a1
   jsr    CloseLibrary(a6)   


exit:
   rts



**************** VARIABLES **********************

dosname: dc.b 'dos.library',0
gfxname: dc.b 'graphics.library',0
intuiname: dc.b 'intuition.library',0
   even

NewScreen:   dc.w 0,0,640,200,2
             dc.w $0102,$8000,15,0,0,0,0,0,0

* NewWindow structure 
* IDCMP:  GADGETDOWN($20)+GADGETUP($40)
* flags:  BORDERLESS($800)
Nwindow:     dc.w 0,0,640
NwHeight:    dc.w 200,$0102
             dc.l $60,$800
FirstGadget: dc.l 0,0,0,0,0,0,0
             dc.w 15      ; CUSTOMSCREEN


* Gadgets : 1st line at y=YGdg

YGdg=-8
Xgdg1=24
Xgdg2=96
Xgdg3=160
Xgdg5=520
Gflag=11    ;  flags : GADGHNONE(3),GRELBOTTOM(8) 
acti=$3     ;  activation : GADGIMMEDIATE(2) RELVERIFY(1)
Xgdg: dc.w Xgdg1,Xgdg2,Xgdg5,Xgdg3
BoolGdg: dc.w YGdg,48,8,Gflag,acti,1,0

PropW=196
PropH=8
PropInfoFlag=3    ; AUTOKNOB(1) + FREEHORIZ(2)

WbMessage=0
file=WbMessage+4
dosbase=file+4
fhandle=dosbase+4
FileLength=fhandle+4
gfxbase=FileLength+4
intuibase=gfxbase+4
myscreen=intuibase+4
myrp=myscreen+4
myvp=myrp+4
mywindow=myvp+4
UserPort=mywindow+4
BitMap=UserPort+4
FileCopy=BitMap+4
FigNumber=FileCopy+4      word  
FigBMap1=FigNumber+2      1st Figure BitMap
FigBMap2=FigBMap1+4       last Figure BitMap
TextStart=FigBMap2+4
LineNumber=TextStart+4
LineAddress=LineNumber+4
FirstLine=LineAddress+4
LastFirstLine=FirstLine+4
NL0=LastFirstLine+4          number of displayed lines
delaynb=NL0+4
ShortNote=delaynb+4
ESC=ShortNote+1
CTR=ShortNote+2              2 bytes
Depth=ShortNote+4            2 bytes
ColorMax=Depth+2             2 bytes (2**Depth - 1)
TempA=ColorMax+2             80-byte buffer for LineUp/Down
PropBorder=TempA+80          16-byte Border structure
PropInfo = PropBorder+16     22-byte PropInfo structure
HPot         = PropInfo+2
HBody        = PropInfo+6
Gadget1  = PropInfo+22       four 44-byte gadgets structures
ReadBuffer= Gadget1+176      128-byte buffer
ColorTable=ReadBuffer+128    ColorTable for 16 colors (16 words)
BrushDepth=ColorTable+32     word
BufferLength=BrushDepth+2

AddedLine1: dc.b '   .../...   '
AddedLine2: dc.b '(end of text)'
TxtGdg1:    dc.b '<<<<    >>>>'
   even
TxtGdg2:    dc.b 'EXIT'
MyColors:   dc.w $0AA9,$0004,$0A22,$0549

 end
