;                           QView 1.0  by Lyman Epp
;
;        Another "File Viewer???"  What for?  It seems that all the other
;        file viewers have been written in "C".  This is okay, but the
;        programs are 10-20K.  This file viewer is written in assembler
;        and contains most of the features of the others, but the program
;        size is less than 3K bytes!  Also, the source is included so that
;        you can add more features (please send me a copy if you do.)
;        QView stands for "Quick View."
;
;        This is being distributed as ShareWare.  If you think that QView
;        is useful, please send $10.  Your response will insure the release
;        of more quality programs for your Amiga!  Programs already in the
;        works include: a disk based print spooler, a window dump that
;        converts the window bitmap back to text, and more.  Be sure to
;        check out the latest shareware version of QMouse.
;
;        The latest version of QView can always be found on the Wind Dragon
;        Inn BBS, (402)-291-8053.
;
;                Lyman R. Epp
;                10072 Wirt Plaza #15
;                Omaha, Nebraska 68134


        SECTION text,CODE

        INCLUDE "exec/types.i"
        INCLUDE "exec/ports.i"
        INCLUDE "exec/libraries.i"
        INCLUDE "exec/memory.i"
        INCLUDE "libraries/dos.i"
        INCLUDE "libraries/dosextens.i"
        INCLUDE "intuition/intuition.i"
        INCLUDE "intuition/intuitionbase.i"


NULL            EQU     0
RAW_ESCAPE      EQU     $45
RAW_SEARCH      EQU     $21      "S"
RAW_AGAIN       EQU     $20      "A"

fileNameSize    EQU     70
lineBfrSize     EQU     200
searchSize      EQU     100
titleSize       EQU     80

IDCMP_FLAGS     EQU     ACTIVEWINDOW!NEWSIZE!CLOSEWINDOW!RAWKEY!GADGETUP
WINDOW_FLAGS    EQU     NOCAREREFRESH!ACTIVATE!WINDOWSIZING!WINDOWDRAG!WINDOWDEPTH!WINDOWCLOSE

UPDATE_SCREEN   EQU     0
UPDATE_TITLE    EQU     1


        STRUCTURE work,0

        STRUCT  newWindowStruct,nw_SIZE

        LABEL   parms
        APTR    parmLen
        APTR    parmAddr

        APTR    dosBase
        APTR    intuitionBase
        APTR    gfxBase
        APTR    windowPtr
        APTR    rastPort

        UWORD   screenCols
        UWORD   screenRows
        UWORD   screenLineNum
        UWORD   screenLineOffset
        ULONG   screenMaxX
        ULONG   screenMaxY

        ULONG   borderLeft
        ULONG   borderRight
        ULONG   borderTop
        ULONG   borderBottom

        ULONG   filePtr
        ULONG   fileHandle
        UWORD   fileNameLen
        UWORD   fileNumLines
        ULONG   fileSize
        UWORD   numLength

        APTR    linePtr
        ULONG   linePtrSize

        ULONG   msgClass
        UWORD   msgCode
        UWORD   msgQual

        UBYTE   flags

        STRUCT  fileName,fileNameSize
        STRUCT  lineBuffer,lineBfrSize
        STRUCT  searchBuffer,searchSize
        STRUCT  titleBuffer,titleSize

        LABEL   work_SIZEOF



        xref    _AbsExecBase

CALLSYS MACRO
        xref    _LVO\1
        CALLLIB _LVO\1
        ENDM

LINKSYS MACRO
        xref    _LVO\1
        LINKLIB _LVO\1,\2
        ENDM


start:
        move.l  _AbsExecBase,a6             ; get ExecBase ptr
        move.l  #workarea,a5

        IFD     MANX
        move.l  a5,a1
        move.l  #(work_SIZEOF-1)/4,d1       ; round to the number of longs - 1 !!
Clear_Mem:
        clr.l   (a1)+                       ; manx doesn't set the length
        dbf     d1,Clear_Mem                ; of the BSS hunk, so the loader
        ENDC                                ; doesn't clear it !!!

        movem.l d0/a0,parms(a5)             ; save parm len/address

        lea     dosName(pc),a1              ; open "dos.library"
        moveq   #LIBRARY_VERSION,d0
        CALLSYS OpenLibrary
        move.l  d0,dosBase(a5)
        beq     ErrFatal

        lea     intuitionName(pc),a1        ; open "intuition.library"
        moveq   #LIBRARY_VERSION,d0
        CALLSYS OpenLibrary
        move.l  d0,intuitionBase(a5)
        beq     ErrFatal

        lea     graphicsName(pc),a1         ; open "graphics.library"
        moveq   #LIBRARY_VERSION,d0
        CALLSYS OpenLibrary
        move.l  d0,gfxBase(a5)
        beq     ErrFatal

        movem.l parms(a5),d0/a0             ; get parm len/address
        lea     fileName(a5),a1
        moveq   #0,d0                       ; length of filename
        moveq   #0,d1                       ; quote flag
        cmpi.b  #' ',(a0)                   ; make it work with MetaScope
        bne     MoveFileName
        addq.l  #1,a0
MoveFileName:
        cmpi.b  #10,(a0)
        beq     DoneFileName
        cmpi.b  #'"',(a0)
        beq     MoveQuoteChar
        btst    #0,d1                       ; quoted argument ?
        bne     MoveQuotedArg               ; yes - don't check for spaces
        cmpi.b  #' ',(a0)
        beq     DoneFileName
MoveQuotedArg:
        move.b  (a0)+,(a1)+
        addq.w  #1,d0
        bra     MoveFileName
MoveQuoteChar:
        addq.l  #1,a0
        bchg    #0,d1
        beq     MoveFileName
DoneFileName:
        btst    #0,d1
        bne     ErrUsage                    ; hanging quote ?
        clr.b   (a1)
        move.w  d0,fileNameLen(a5)

        lea     fileName(a5),a1
        tst.b   (a1)
        beq     ErrUsage
        cmpi.b  #'?',(a1)
        beq     ErrUsage

        move.l  a1,d1
        move.l  #MODE_OLDFILE,d2
        LINKSYS Open,dosBase(a5)
        move.l  d0,fileHandle(a5)
        beq     ErrNotFound

        move.l  fileHandle(a5),d1
        moveq   #0,d2
        moveq   #OFFSET_END,d3
        LINKSYS Seek,dosBase(a5)

        move.l  fileHandle(a5),d1
        moveq   #0,d2
        moveq   #OFFSET_BEGINNING,d3
        LINKSYS Seek,dosBase(a5)
        move.l  d0,fileSize(a5)

;       fileSize is still in d0!!
        move.l  #MEMF_PUBLIC,d1
        CALLSYS AllocMem
        move.l  d0,filePtr(a5)
        beq     ErrFatal

        move.l  fileHandle(a5),d1
        move.l  filePtr(a5),d2
        move.l  fileSize(a5),d3
        LINKSYS Read,dosBase(a5)
        cmp.l   fileSize(a5),d0
        bne     ErrFatal

;       fileSize is still in d0!!
        move.l  filePtr(a5),a0
        moveq   #0,d1
GetNumLines:
        cmpi.b  #10,(a0)+
        bne     GetNumNotLF
        addq.w  #1,d1
GetNumNotLF:
        subq.l  #1,d0
        bne     GetNumLines
        move.w  d1,fileNumLines(a5)
        move.w  d1,d0
        bsr     ILen
        move.w  d0,numLength(a5)

        move.l  d1,d0
        addq.l  #1,d0
        lsl.l   #2,d0
        move.l  d0,linePtrSize(a5)
        move.l  #MEMF_PUBLIC,d1
        CALLSYS AllocMem
        move.l  d0,linePtr(a5)
        beq     ErrFatal

        move.l  d0,a1
        move.l  filePtr(a5),a0
        move.l  fileSize(a5),d0
        move.l  a0,(a1)+
FindNewLine:
        cmpi.b  #10,(a0)+
        bne     FindNotLF
        move.l  a0,(a1)+
FindNotLF:
        subq.l  #1,d0
        bne     FindNewLine

        move.l  intuitionBase(a5),a1
        move.l  ib_ActiveScreen(a1),a1
        lea     newWindowStruct(a5),a0

        move.w  sc_Width(a1),nw_Width(a0)
        move.w  sc_Height(a1),nw_Height(a0)
        move.b  #1,nw_BlockPen(a0)
        move.l  #IDCMP_FLAGS,nw_IDCMPFlags(a0)
        move.l  #WINDOW_FLAGS,nw_Flags(a0)
        move.w  #100,nw_MinWidth(a0)
        move.w  #30,nw_MinHeight(a0)
        move.w  #-1,nw_MaxWidth(a0)
        move.w  #-1,nw_MaxHeight(a0)
        move.w  #WBENCHSCREEN,nw_Type(a0)

        LINKSYS OpenWindow,intuitionBase(a5)
        move.l  d0,windowPtr(a5)
        beq     ErrFatal

        move.l  d0,a0
        moveq   #0,d0
        move.b  wd_BorderLeft(a0),d0
        move.l  d0,borderLeft(a5)
        move.b  wd_BorderRight(a0),d0
        move.l  d0,borderRight(a5)
        move.b  wd_BorderTop(a0),d0
        move.l  d0,borderTop(a5)
        move.b  wd_BorderBottom(a0),d0
        move.l  d0,borderBottom(a5)

        move.l  wd_RPort(a0),rastPort(a5)

        bset    #UPDATE_TITLE,flags(a5)
        bsr     UpdateTitle
        bsr     UpdateScreen


GetNextEvent:
        bclr    #UPDATE_SCREEN,flags(a5)
        beq     ScreenOK
        bsr     UpdateScreen
ScreenOK:

        move.l  windowPtr(a5),a0
        move.l  wd_UserPort(a0),a0
        CALLSYS WaitPort

        move.l  d0,a1
        CALLSYS Remove

        move.l  d0,a1
        move.l  im_Class(a1),msgClass(a5)
        move.w  im_Code(a1),msgCode(a5)
        move.w  im_Qualifier(a1),msgQual(a5)
        CALLSYS ReplyMsg

        move.l  msgClass(a5),d0

        cmpi.l  #CLOSEWINDOW,d0
        beq     Terminate

        cmpi.l  #NEWSIZE,d0
        bne     NotNewSize
        bset    #UPDATE_SCREEN,flags(a5)
        bra     GetNextEvent
NotNewSize:

        cmpi.l  #RAWKEY,d0
        bne     GetNextEvent

        move.w  msgCode(a5),d0

        cmpi.w  #CURSORUP,d0
        bne     NotCursorUp
        bsr     ScrollUp
        bra     GetNextEvent
NotCursorUp:

        cmpi.w  #CURSORDOWN,d0
        bne     NotCursorDown
        bsr     ScrollDown
        bra     GetNextEvent
NotCursorDown:

        cmpi.w  #CURSORLEFT,d0
        bne     NotCursorLeft
        bsr     ScrollLeft
        bra     GetNextEvent
NotCursorLeft:

        cmpi.w  #CURSORRIGHT,d0
        bne     NotCursorRight
        bsr     ScrollRight
        bra     GetNextEvent
NotCursorRight:

        cmpi.w  #RAW_SEARCH,d0
        bne     NotSearchKey
        bsr     ForwardSearch
        bra     GetNextEvent
NotSearchKey:

        cmpi.w  #RAW_AGAIN,d0
        bne     NotAgainKey
        bsr     ForwardSearch
        bra     GetNextEvent
NotAgainKey:

        cmpi.w  #RAW_ESCAPE,d0
        beq     Terminate
        bra     GetNextEvent


ERR_USAGE       dc.b    $9b,'0;33mQView 1.0',$9b,'0m  by Lyman Epp',10
                dc.b    'Usage: QView filename',10
ERR_USAGE_SIZE  EQU     55

ERR_NOTFND      dc.b    'File not found',10
ERR_NOTFND_SIZE EQU     15

ERR_FATAL       dc.b    'QView: Fatal error',10
ERR_FATAL_SIZE  EQU     19

        CNOP    0,2

ErrUsage:
        lea     ERR_USAGE(pc),a0
        moveq   #ERR_USAGE_SIZE,d3
        bra     ErrDisplay

ErrNotFound:
        lea     ERR_NOTFND(pc),a0
        moveq   #ERR_NOTFND_SIZE,d3
        bra     ErrDisplay

ErrFatal:
        lea     ERR_FATAL(pc),a0
        moveq   #ERR_FATAL_SIZE,d3
        bra     ErrDisplay

ErrDisplay:
        move.l  a0,d2
        LINKSYS Output,dosBase(a5)
        move.l  d0,d1
        LINKSYS Write,dosBase(a5)


Terminate:
        move.l  linePtr(a5),d0
        beq     TermNoLineMem
        move.l  d0,a1
        move.l  linePtrSize(a5),d0
        CALLSYS FreeMem
TermNoLineMem:

        move.l  fileHandle(a5),d1
        beq     TermNoFileHandle
        LINKSYS Close,dosBase(a5)
TermNoFileHandle:

        move.l  filePtr(a5),d0
        beq     TermNoFileMem
        move.l  d0,a1
        move.l  fileSize(a5),d0
        CALLSYS FreeMem
TermNoFileMem:

        move.l  windowPtr(a5),d0
        beq     TermNoWindow
        move.l  d0,a0
        LINKSYS CloseWindow,intuitionBase(a5)
TermNoWindow:

        move.l  gfxBase(a5),d0
        beq     TermNogfxBase
        move.l  d0,a1
        CALLSYS CloseLibrary
TermNogfxBase:

        move.l  intuitionBase(a5),d0
        beq     TermNoIntBase
        move.l  d0,a1
        CALLSYS CloseLibrary
TermNoIntBase:

        moveq   #0,d1
        LINKSYS Exit,dosBase(a5)




ScrollUp:
        tst.w   screenLineNum(a5)
        beq     ScrollUpExit

        move.w  msgQual(a5),d0
        andi.w  #IEQUALIFIER_LSHIFT!IEQUALIFIER_RSHIFT,d0
        beq     ScrollUpNotShift
        move.w  screenLineNum(a5),d0
        sub.w   screenRows(a5),d0
        bpl     ScrollUpNotFirst
        moveq   #0,d0
ScrollUpNotFirst:
        move.w  d0,screenLineNum(a5)
        bset    #UPDATE_SCREEN,flags(a5)
        bra     ScrollUpExit

ScrollUpNotShift:
        move.w  msgQual(a5),d0
        andi.w  #IEQUALIFIER_LALT!IEQUALIFIER_RALT!IEQUALIFIER_CONTROL,d0
        beq     ScrollUpNotAlt
        clr.w   screenLineNum(a5)
        bset    #UPDATE_SCREEN,flags(a5)
        bra     ScrollUpExit

ScrollUpNotAlt:
        subq.w  #1,screenLineNum(a5)
        move.l  rastPort(a5),a1
        moveq   #0,d0
        moveq   #0,d1
        sub.w   rp_TxHeight(a1),d1
        move.l  borderLeft(a5),d2
        move.l  borderTop(a5),d3
        move.l  screenMaxX(a5),d4
        move.l  screenMaxY(a5),d5
        LINKSYS ScrollRaster,gfxBase(a5)

        moveq   #0,d0
        bsr     OutputLine

ScrollUpExit:
        bsr     UpdateTitle
        rts



ScrollDown:
        move.w  msgQual(a5),d0
        andi.w  #IEQUALIFIER_LALT!IEQUALIFIER_RALT!IEQUALIFIER_CONTROL,d0
        beq     ScrollDownNotAlt
        move.w  fileNumLines(a5),d0
        sub.w   screenRows(a5),d0
        bmi     ScrollDownExit
        cmp.w   screenLineNum(a5),d0
        beq     ScrollDownExit
        move.w  d0,screenLineNum(a5)
        bset    #UPDATE_SCREEN,flags(a5)
        bra     ScrollDownExit

ScrollDownNotAlt:
        move.w  fileNumLines(a5),d0
        sub.w   screenLineNum(a5),d0
        sub.w   screenRows(a5),d0
        ble     ScrollDownExit

        move.w  msgQual(a5),d0
        andi.w  #IEQUALIFIER_LSHIFT!IEQUALIFIER_RSHIFT,d0
        beq     ScrollDownNotShift
        move.w  screenLineNum(a5),d0
        add.w   screenRows(a5),d0
        move.w  d0,screenLineNum(a5)
        bset    #UPDATE_SCREEN,flags(a5)
        bra     ScrollDownExit

ScrollDownNotShift:
        addq.w  #1,screenLineNum(a5)
        move.l  rastPort(a5),a1
        moveq   #0,d0
        move.w  rp_TxHeight(a1),d1
        move.l  borderLeft(a5),d2
        move.l  borderTop(a5),d3
        move.l  screenMaxX(a5),d4
        move.l  screenMaxY(a5),d5
        LINKSYS ScrollRaster,gfxBase(a5)

        move.w  screenRows(a5),d0
        subq.w  #1,d0
        ext.w   d0
        bsr     OutputLine

ScrollDownExit:
        bsr     UpdateTitle
        rts



ScrollLeft:
        tst.w   screenLineOffset(a5)
        beq     ScrollLeftExit

        bset    #UPDATE_TITLE,flags(a5)
        bset    #UPDATE_SCREEN,flags(a5)
        subi.w  #20,screenLineOffset(a5)

        move.w  msgQual(a5),d0
        andi.w  #IEQUALIFIER_LALT!IEQUALIFIER_RALT!IEQUALIFIER_CONTROL,d0
        beq     ScrollLeftExit
        clr.w   screenLineOffset(a5)

ScrollLeftExit:
        bsr     UpdateTitle
        rts



ScrollRight:
        addi.w  #20,screenLineOffset(a5)
        bset    #UPDATE_TITLE,flags(a5)
        bset    #UPDATE_SCREEN,flags(a5)
        bsr     UpdateTitle

ScrollRightExit:
        rts



ItoA:             ; (a0:buffer, d0:integer, d1:length)
        subq.w  #1,d1
ItoA_Blank:
        move.b  #' ',(a0)+
        dbf     d1,ItoA_Blank
        move.l  a0,-(sp)

        ext.l   d0
ItoA_Next:
        divu    #10,d0
        move.l  d0,d1
        swap    d1
        ori.b   #'0',d1
        move.b  d1,-(a0)
        ext.l   d0
        bne     ItoA_Next

        move.l  (sp)+,a0
        rts



ILen:             ; (d0:integer)
        move.l  d1,-(sp)

        moveq   #0,d1
ILen_Loop:
        addq.w  #1,d1
        ext.l   d0
        divu    #10,d0
        bne     ILen_Loop

        move.l  d1,d0
        move.l  (sp)+,d1
        rts



UpdateTitle:
        lea     titleBuffer(a5),a0
        move.w  screenLineNum(a5),d0
        addq.w  #1,d0
        move.w  numLength(a5),d1
        bsr     ItoA

        move.b  #'/',(a0)+

        move.w  fileNumLines(a5),d0
        move.w  numLength(a5),d1
        bsr     ItoA

        tst.w   screenLineOffset(a5)
        beq     TitleNoOffset
        move.b  #'+',(a0)+
        move.w  screenLineOffset(a5),d0
        bsr     ILen
        move.w  d0,d1
        move.w  screenLineOffset(a5),d0
        bsr     ItoA
TitleNoOffset:

        move.b  #' ',(a0)+

        lea     fileName(a5),a1
        move.w  fileNameLen(a5),d0
        subq.w  #1,d0
ShowFileName:
        move.b  (a1)+,(a0)+
        dbf     d0,ShowFileName

        move.b  #' ',(a0)+
        clr.b   (a0)

        bclr    #UPDATE_TITLE,flags(a5)
        beq     TitleOK
        move.l  windowPtr(a5),a0
        lea     titleBuffer(a5),a1
        move.l  #-1,a2
        LINKSYS SetWindowTitles,intuitionBase(a5)
TitleOK:

        move.l  rastPort(a5),a0
        lea     IText1(pc),a1
        moveq   #0,d0
        moveq   #0,d1
        LINKSYS PrintIText,intuitionBase(a5)

        rts



UpdateScreen:
        move.l  rastPort(a5),a1
        moveq   #0,d0
        LINKSYS SetAPen,gfxBase(a5)

        move.l  windowPtr(a5),a0
        move.l  borderLeft(a5),d0
        move.l  borderTop(a5),d1
        move.w  wd_Width(a0),d2
        ext.l   d2
        sub.l   borderRight(a5),d2
        move.w  wd_Height(a0),d3
        ext.l   d3
        sub.l   borderBottom(a5),d3
        move.l  rastPort(a5),a1
        LINKSYS RectFill,gfxBase(a5)

        move.l  rastPort(a5),a1
        moveq   #1,d0
        LINKSYS SetAPen,gfxBase(a5)

        move.l  windowPtr(a5),a0
        move.l  rastPort(a5),a1
        move.w  wd_Width(a0),d0
        ext.l   d0
        sub.l   borderLeft(a5),d0
        sub.l   borderRight(a5),d0
        divu    rp_TxWidth(a1),d0
        move.w  d0,screenCols(a5)
        mulu    rp_TxWidth(a1),d0
        add.l   borderLeft(a5),d0
        subq.l  #1,d0
        move.l  d0,screenMaxX(a5)

        move.w  wd_Height(a0),d0
        ext.l   d0
        sub.l   borderTop(a5),d0
        sub.l   borderBottom(a5),d0
        divu    rp_TxHeight(a1),d0
        move.w  d0,screenRows(a5)
        mulu    rp_TxHeight(a1),d0
        add.l   borderTop(a5),d0
        subq.l  #1,d0
        move.l  d0,screenMaxY(a5)


        moveq   #0,d0
UpdateLine:
        bsr     OutputLine
        addq.w  #1,d0
        cmp.w   screenRows(a5),d0
        bne     UpdateLine

        rts



OutputLine:
        movem.l d0-d7/a0-a1,-(sp)
        move.l  d0,d7
        add.w   screenLineNum(a5),d0
        cmp.w   fileNumLines(a5),d0
        bpl     OutputLineExit
        lsl.l   #2,d0
        move.l  linePtr(a5),a0
        move.l  0(a0,d0),a0

        lea     lineBuffer(a5),a1
        moveq   #0,d0
OutputLineNextChar:
        move.b  (a0)+,d1
        cmpi.b  #10,d1
        beq     OutputLineEnd
        cmpi.b  #13,d1
        beq     OutputLineNextChar
        cmpi.b  #9,d1
        beq     OutputLineTab

        move.b  d1,(a1)+
        addq.l  #1,d0
        cmpi.w  #lineBfrSize,d0
        bne     OutputLineNextChar
        bra     OutputLineEnd

OutputLineTab:
        move.l  d0,d2
        move.w  lineTabSize(pc),d3
        divu    d3,d2
        lsr.l   #8,d2
        lsr.l   #8,d2
        sub.w   d2,d3
        move.l  d0,d2
        add.w   d3,d2
        cmpi.w  #lineBfrSize,d2
        bpl     OutputLineEnd
        add.w   d3,d0
        subq.w  #1,d3
OutputLineMoveTab:
        move.b  #' ',(a1)+
        dbf     d3,OutputLineMoveTab
        bra     OutputLineNextChar

OutputLineEnd:
        move.w  d0,d6
        move.l  d7,d1
        move.l  rastPort(a5),a1
        mulu    rp_TxHeight(a1),d1
        add.l   borderTop(a5),d1
        add.w   rp_TxBaseline(a1),d1
        move.l  borderLeft(a5),d0
        LINKSYS Move,gfxBase(a5)

        move.w  d6,d0
        sub.w   screenLineOffset(a5),d0
        bmi     OutputLineExit
        cmp.w   screenCols(a5),d0
        ble     OutputLineLenOk
        move.w  screenCols(a5),d0
OutputLineLenOk:

        lea     lineBuffer(a5),a0
        add.w   screenLineOffset(a5),a0
        move.l  rastPort(a5),a1
        LINKSYS Text,gfxBase(a5)

OutputLineExit:
        movem.l (sp)+,d0-d7/a0-a1
        rts



ForwardSearch:
        move.w  fileNumLines(a5),d0
        sub.w   screenLineNum(a5),d0
        ble     Search_Exit

        cmpi.w  #RAW_AGAIN,msgCode(a5)
        beq     Search_Again

        bset    #UPDATE_SCREEN,flags(a5)

        bsr     GetString
        tst.l   d0                       ; did an error occur?
        bne     Search_Exit              ; yes, just leave

Search_Again:
        lea     GadgetInfo(pc),a0
        move.w  si_NumChars(a0),d2       ; length of search string
        beq     Search_Exit

        move.w  screenLineNum(a5),d3
        addq.w  #1,d3
        cmp.w   fileNumLines(a5),d3
        bge     Search_NotFound

        ext.l   d3
        lsl.l   #2,d3
        move.l  linePtr(a5),a0
        move.l  0(a0,d3.l),a0
        lsr.l   #2,d3

        ext.l   d2
        move.l  filePtr(a5),a2
        add.l   fileSize(a5),a2
        sub.l   d2,a2                    ; last address to search
        lea     searchBuffer(a5),a1      ; address of buffer

        moveq   #0,d2

Search_Loop:
        cmp.l   a2,a0
        bgt     Search_NotFound
        move.b  0(a1,d2.w),d1
        beq     Search_Found
        cmpi.b  #'A',d1
        blt     Search_Case1OK
        cmpi.b  #'Z',d1
        bgt     Search_Case1OK
        ori.b   #$20,d1
Search_Case1OK:
        move.b  0(a0,d2.w),d0
        cmpi.b  #'A',d0
        blt     Search_Case2OK
        cmpi.b  #'Z',d0
        bgt     Search_Case2OK
        ori.b   #$20,d0
Search_Case2OK:
        addq.w  #1,d2
        cmp.b   d1,d0
        beq     Search_Loop

        moveq   #0,d2
        cmpi.b  #10,(a0)+
        bne     Search_Loop
        addq.w  #1,d3
        bra     Search_Loop

Search_NotFound:
        move.l  windowPtr(a5),a0
        lea     NOT_FOUND(pc),a1
        move.l  #-1,a2
        LINKSYS SetWindowTitles,intuitionBase(a5)
        bset    #UPDATE_TITLE,flags(a5)
        bra     Search_Exit

Search_Found:
        move.w  d3,screenLineNum(a5)
        bset    #UPDATE_SCREEN,flags(a5)
        bsr     UpdateTitle

Search_Exit:
        rts



GetString:
        movem.l d2/a1-a3,-(sp)

        clr.b   searchBuffer(a5)
        move.l  windowPtr(a5),a3

        move.w  wd_Width(a3),d0
        subi.w  #22,d0
        move.w  d0,BorderVectors+4

        move.l  a3,a0
        lea     StringGadget(pc),a1
        moveq   #-1,d0
        LINKSYS AddGadget,intuitionBase(a5)

        lea     StringGadget(pc),a0
        move.l  a3,a1
        sub.l   a2,a2
        LINKSYS RefreshGadgets,intuitionBase(a5)

        lea     StringGadget(pc),a0
        move.l  a3,a1
        LINKSYS ActivateGadget,intuitionBase(a5)

GetStringWait:
        move.l  wd_UserPort(a3),a0
        CALLSYS WaitPort

        move.l  d0,a1
        CALLSYS Remove

        move.l  d0,a1
        move.l  im_Class(a1),d2
        CALLSYS ReplyMsg

        cmpi.l  #NEWSIZE,d2
        beq     GetString_Exit

        cmpi.l  #GADGETUP,d2
        bne     GetStringWait
        moveq   #0,d2

GetString_Exit:
        move.l  a3,a0
        lea     StringGadget(pc),a1
        LINKSYS RemoveGadget,intuitionBase(a5)

        move.l  d2,d0
        movem.l (sp)+,d2/a1-a3
        rts




dosName         dc.b    'dos.library',0
intuitionName   dc.b    'intuition.library',0
graphicsName    dc.b    'graphics.library',0


lineTabSize     dc.w    8


NOT_FOUND:
        dc.b    'No match found',0
        CNOP    0,2



StringGadget:
        dc.l        NULL            ;next gadget
        dc.w        4,-9            ;origin XY of hit box relative to window TopLeft
        dc.w        -22,8           ;hit box width and height
        dc.w        GRELBOTTOM!GRELWIDTH   ;gadget flags
        dc.w        RELVERIFY       ;activation flags
        dc.w        STRGADGET       ;gadget type flags
        dc.l        GadgetBorder    ;gadget border or image to be rendered
        dc.l        NULL            ;alternate imagery for selection
        dc.l        NULL            ;first IntuiText structure
        dc.l        NULL            ;gadget mutual-exclude long word
        dc.l        GadgetInfo      ;SpecialInfo structure
        dc.w        NULL            ;user-definable data
        dc.l        NULL            ;pointer to user-definable data
GadgetInfo:
        dc.l        workarea+searchBuffer  ;buffer where text will be edited
        dc.l        NULL            ;optional undo buffer
        dc.w        0               ;character position in buffer
        dc.w        searchSize      ;maximum number of characters to allow
        dc.w        0               ;first displayed character buffer position
        dc.w        0,0,0,0,0       ;Intuition initialized and maintained variables
        dc.l        0               ;Rastport of gadget
        dc.l        0               ;initial value for integer gadgets
        dc.l        NULL            ;alternate keymap (fill in if you set the flag)
GadgetBorder:
        dc.w        -1,-1           ;XY origin relative to container TopLeft
        dc.b        3,0,RP_JAM1     ;front pen, back pen and drawmode
        dc.b        2               ;number of XY vectors
        dc.l        BorderVectors   ;pointer to XY vectors
        dc.l        NULL            ;next border in list
BorderVectors:
        dc.w        0,0
        dc.w        -1,0            ; GetString will modify this!


IText1:
        dc.b        0,1,RP_JAM2,0   ;front and back text pens, drawmode and fill byte
        dc.w        30,1            ;XY origin relative to container TopLeft
        dc.l        NULL            ;font pointer or NULL for default
        dc.l        workarea+titleBuffer  ;pointer to title text
        dc.l        NULL            ;next IntuiText structure




        IFD     MANX

        BSS     workarea,work_SIZEOF

        ENDC

        IFND    MANX

        SECTION uninit,BSS

workarea:
        ds.b    work_SIZEOF

        ENDC


        END

