; *******************************************************************
; *                                                                 *
; *                          scribble_16.asm                        *
; *                                                                 *
; *   This aplet is based on Darrin Massena's PILA sample code.     *
; *   It requires Darrin's PILOT.INC and STARTUP.INC include files. *
; *   For info on how to write apps for the world's best palmtop,   *
; *   aim your browser at                                           *
; *   http://www.massena.com/darrin/pilot                           *
; *                                                                 *
; *   If you have any questions about this source code,             *
; *   please send them to howlett@iosphere.net                      *
; *                                                                 *
; *   This code is freeware and you are free to modify it as you    *
; *   wish, however you must register your own Creator ID before    *
; *   you distribute any modifications.                             *
; *                                                                 *
; *                                                                 *
; *   Andrew Howlett                                                *
; *   howlett@iosphere.net                                          *
; *   2 Jan 97                                                      *
; *                                                                 *
; *******************************************************************

        Appl    "Scribble", 'Scrb'                      ; define name and creator ID
                                                        ; creator ID is sometimes called AppType
                                                        ; creator type is #$53637262

        include "Pilot.inc"                             ; structs, constants
        include "Startup.inc"                           ; common startup code

kidbAIB         equ             $7FFE                   ; Application-defined resource ids
kidrPREF        equ             1                       ; don't know who made up these names
kidrTVER        equ             1
kidrTAIB        equ             1000
kidfMain        equ             1000
kidmMain        equ             1000
kidmClear       equ             1001
kidmAbout       equ             1002
kidmNewPage     equ             1003
kidmRemovePage  equ             1004
kidmForwardPage equ             1005
kidmBackwardPage        equ     1006
kidrAboutAlert  equ             1000
ScribbleAppType equ             $53637262               ; 'Scrb'
ScribbleDBType  equ             $44617461               ; 'Data'

        data                                            ; global variables

global lastX.w                                          ; globals are offsets from a5
global lastY.w
global lastX1.w
global lastY1.w
global SkipNextEvent.w
global dbR.l
global CurrentIndex.w
global dbNumRecords.w

ScribbleDBName
        dc.b    'ScribbleDB',0
NumString
        dc.b    '00',0

        code

; *******************************************************************
; *                                                                 *
; *   DWord PilotMain(Word cmd, void *cmdPBP, Word launchflags)     *
; *                                                                 *
; *   PilotMain is called by the startup code and implements        *
; *   a simple event handling loop.                                 *
; *                                                                 *
; *******************************************************************

proc PilotMain(cmd.w, cmdPBP.l, launchFlags.w)
local   err.w
local   evt.EventType
beginproc
        tst.w   cmd(a6)                                 ;sysAppLaunchCmdNormalLaunch is 0
        bne     PmReturn                                ;not a normal launch, bag out

        systrap FrmGotoForm(#kidfMain.w)

PmEventLoop                                             ; Doze until an event arrives
        systrap EvtGetEvent(&evt(a6), #evtWaitForever.w)

        systrap SysHandleEvent(&evt(a6))                ; First handler is system
        tst.b   d0                                      ; handled?
        bne.s   PmEventDone                             ; yep

                                                        ; Second is menu handler
        systrap MenuHandleEvent(&0, &evt(a6), &err(a6))
        tst.b   d0                                      ; handled?
        bne.s   PmEventDone                             ; yep

                                                        ; Third is application handler
        call    ApplicationHandleEvent(&evt(a6))
        tst.b   d0                                      ; handled?
        bne.s   PmEventDone                             ; yep

                                                        ; Fourth is form handler.
                                                        ; Form handler is where our
                                                        ; custom code is located
        call    MainFormHandleEvent(&evt(a6))
        tst.b   d0                                      ; handled?
        bne.s   PmEventDone                             ; yep

                                                        ; Still not handled.
                                                        ; We're not interested
                                                        ; in it anymore so let the                                          
        systrap FrmGetActiveForm()                      ; default form handler take it.
        systrap FrmHandleEvent(a0.l, &evt(a6))

                                                        ; Return from PilotMain when an
PmEventDone                                             ; appStopEvent is received
        cmpi.w  #appStopEvent,evt+EventType.eType(a6)   ; time to stop?
        bne.s   PmEventLoop                             ; nope, loop until it is

PmReturn
        moveq   #0, d0
endproc


; *******************************************************************
; *                                                                 *
; *   Boolean ApplicationHandleEvent(EventType *pevt)               *
; *                                                                 *
; *   Handles these events:    frmLoadEvent                         *
; *                                                                 *
; *******************************************************************

proc ApplicationHandleEvent(pevt.l)
beginproc
        movea.l pevt(a6),a0                             ;a0 = pevt

        cmp.w   #frmLoadEvent,EventType.eType(a0) 
        beq     FormLoadHandler
        cmpi.w  #appStopEvent,EventType.eType(a0) 
        beq     ApplicationStopHandler
        bra     ApplicationEventNotHandled

FormLoadHandler                                         ; Initialize the form and make it active

        systrap FrmInitForm(EventType.data+frmLoad.formID(a0).w)
        systrap FrmSetActiveForm(a0.l)        

OpenDatabase                                            ; try to open the database
        systrap DmOpenDatabaseByTypeCreator (#ScribbleDBType.l, #ScribbleAppType.l, #dmModeReadWrite.w)
        move.l  a0, dbR(a5)
        cmpa    #0, a0
        bne DrawForm                                    ; if the database exists, goto DrawForm

CreateDatabase                                          ; if the database doesn't exist, create it
        systrap DmCreateDatabase(#0.w, &ScribbleDBName(a5), #ScribbleAppType.l, #ScribbleDBType.l, #false.w)
        systrap DmOpenDatabaseByTypeCreator (#ScribbleDBType.l, #ScribbleAppType.l, #dmModeReadWrite.w)
        move.l  a0, dbR(a5)
        clr.w   CurrentIndex(a5)                                ; create a first record
        clr.w   dbNumRecords(a5)
        systrap DmNewRecord (dbR(a5).l, &CurrentIndex(a5), #2840.l)
        systrap DmReleaseRecord (dbR(a5).l, CurrentIndex(a5).w, #true.w)
        call    ClearScreen()
        bra     ApplicationEventNotHandled

DrawForm
        clr.w   CurrentIndex(a5)
        systrap PrefGetAppPreferences(#ScribbleAppType.l, #15.w, &CurrentIndex(a5), #2.w)

DrawForm1
        systrap DmNumRecords(dbR(a5).l)
        subq.w  #$0001, d0
        move.w  d0, dbNumRecords(a5)
        call    LoadScreen()
        bra     ApplicationEventNotHandled

ApplicationStopHandler                                  ; Application Stop Handler
        call    SaveScreen()
        systrap PrefSetAppPreferences(#ScribbleAppType.l, #15.w, &CurrentIndex(a5), #2.w)

ApplicationEventNotHandled
        clr.b   d0

ApplicationEventReturn

endproc


; *******************************************************************
; *                                                                 *
; *   Boolean MainFormHandleEvent(EventType *pevt)                  *
; *                                                                 *
; *   Handles these events:    frmOpenEvent                         *
; *                            frmMenuEvent                         *
; *                            penDownEvent                         *
; *                                                                 *
; *******************************************************************

proc MainFormHandleEvent(pevt.l)

beginproc

        movea.l pevt(a6),a0                             ;  a0 = pevt
        move.w  EventType.eType(a0),d0                  ;  d0 = event type

        cmp.w   #menuEvent,d0                           ; Handle Menu Events
        beq     MenuHandler
        cmp.w   #keyDownEvent,d0                        ; Handle key down Events
        beq     KeyboardHandler
PenHandler
        cmp.w   #penDownEvent, d0                       ; Handle pen Down Events
        beq     PenDownEventHandler
        cmp.w   #penUpEvent, d0                         ; Handle pen Up Events
        beq     PenEventHandler
        cmp.w   #penMoveEvent, d0                       ; Handle pen Move Events
        beq     PenEventHandler
        clr.b   d0                                      ; Not handled, d0=0
        bra MFHReturn

MenuHandler                                             ; Show "About" info box
        move.w  EventType.data+menu.itemID(a0), d0
        cmp.w   #kidmAbout, d0
        beq     MenuAboutHandler
        cmp.w   #kidmClear, d0
        beq     MenuClearHandler
        cmp.w   #kidmNewPage, d0
        beq     MenuNewPageHandler
        cmp.w   #kidmRemovePage, d0
        beq     MenuRemovePageHandler
        cmp.w   #kidmForwardPage, d0
        beq     MenuForwardPageHandler
        cmp.w   #kidmBackwardPage, d0
        beq     MenuBackwardPageHandler
        bra     MFHHandled

MenuAboutHandler
        systrap FrmAlert(#kidrAboutAlert.w)
        bra     MFHHandled

MenuClearHandler                                        ; Clear menu chosen
        call    ClearScreen ()
        bra     MFHHandled

MenuNewPageHandler
        call    SaveScreen()
        addq.w  #$0001, CurrentIndex(a5)
        systrap DmNewRecord (dbR(a5).l, &CurrentIndex(a5), #2840.l)
        cmpa    #0, a0
        bne     MenuNewPageHandler1
        subq.w  #$0001, CurrentIndex(a5)
        bra     MFHHandled
        
MenuNewPageHandler1
        systrap DmReleaseRecord (dbR(a5).l, CurrentIndex(a5).w, #true.w)
        call    ClearScreen()
        addq.w  #$0001, dbNumRecords(a5)
        bra MFHHandled

MenuRemovePageHandler
        tst.w   dbNumRecords(a5)
        beq     MFHHandled
        
MenuRemovePageHandler1
        subq.w  #$0001, dbNumRecords(a5)
        systrap DmRemoveRecord (dbR(a5).l, CurrentIndex(a5).w)
        subq.w  #$0001, CurrentIndex(a5)
        bpl     MenuRemovePageHandler2
        clr     CurrentIndex(a5)

MenuRemovePageHandler2
        call LoadScreen()
        bra     MFHHandled

MenuForwardPageHandler
        move.w  CurrentIndex(a5),d0
        cmp.w   dbNumRecords(a5), d0
        beq     MFHHandled
        call    SaveScreen()
        addq.w  #$0001, CurrentIndex(a5)
        call    LoadScreen()
        bra     MFHHandled

MenuBackwardPageHandler
        tst.w   CurrentIndex(a5)
        beq     MFHHandled
        call    SaveScreen()
        subq.w  #$0001, CurrentIndex(a5)
        call    LoadScreen()
        bra     MFHHandled

PenDownEventHandler
        move.w  EventType.screenX(a0), lastX(a5)         ; move x into lastX
        move.w  EventType.screenY(a0), lastY(a5)         ; move y into lastY
        move.w  #1,SkipNextEvent(a5)
        bra     MFHHandled

PenEventHandler
        tst.w   SkipNextEvent(a5)                 ; skip first event
        beq     MFHReturn
        clr.l d3
        clr.l d4
        move.w EventType.screenX(a0), d3                ; move x into d1
        move.w EventType.screenY(a0), d4                ; move y into d2
        cmp.w   #159, d4
        blt     CheckPenUpEvent
        move.w  #159, d4

CheckPenUpEvent
        cmp.w   #penUpEvent, d0
        bne     DrawLineHandler
        clr.w   SkipNextEvent(a5)

DrawLineHandler
        systrap WinDrawLine(lastX(a5).w, lastY(a5).w, d3.w, d4.w)
        move.w d3, lastX(a5)
        move.w d4, lastY(a5)
        bra     MFHHandled

KeyboardHandler
        move.w  EventType.data+keyDown.chr(a0), d0
        andi.w  #$1f, d0                                ;  mask #$1f for case-insensitive
        cmp.w   #01, d0                                 ;  a is 1
        beq     MenuAboutHandler
        cmp.w   #03, d0                                 ;  c is 3
        beq     MenuClearHandler
        cmp.w   #06, d0                                 ;  f is 6
        beq     MenuForwardPageHandler
        cmp.w   #02, d0                                 ;  b is 2
        beq     MenuBackwardPageHandler
        cmp.w   #14, d0                                 ;  e is 14
        beq     MenuNewPageHandler
        cmp.w   #18, d0                                 ;  r is 18
        beq     MenuRemovePageHandler
        cmp.w   #00, d0                                 ;  space is 0
        beq     MenuForwardPageHandler
        cmp.w   #08, d0                                 ;  backspace is 8
        beq     MenuBackwardPageHandler

MFHHandled
        moveq.l #1,d0

MFHReturn

endproc

; *******************************************************************
; *                                                                 *
; *    Void  ClearScreen (void)                                     *
; *                                                                 *
; *******************************************************************

proc ClearScreen()

        systrap WinEraseWindow()                        ; Erase the window
        systrap FrmGetActiveForm()                      ; Get form point a0
        systrap FrmDrawForm(a0.l)                       ; Draw the form
        call ShowCurrentIndex()

beginproc


endproc

; *******************************************************************
; *                                                                 *
; *    Void   SaveScreen (void)                                     *
; *                                                                 *
; *******************************************************************

proc SaveScreen()

beginproc

        systrap DmGetRecord (dbR(a5).l, CurrentIndex(a5).w)
        move.l  a0, a3                                          ; a3=RecordHandle
        systrap MemHandleLock (a3.l)
        systrap DmWrite (a0.l, #$00000000.l, #$00006518.l, #2840.l)
        systrap MemHandleUnlock (a3.l)
        systrap DmReleaseRecord (dbR(a5).l, CurrentIndex(a5).w, #true.w)

endproc

; *******************************************************************
; *                                                                 *
; *    Void   LoadScreen (void)                                     *
; *                                                                 *
; *******************************************************************

proc LoadScreen()

beginproc

        call ClearScreen()
        systrap DmQueryRecord (dbR(a5).l, CurrentIndex(a5).w)
        move.l  a0, a2                                  ; a2=RecordHandle
        systrap MemHandleLock (a0.l)

        move.l  #$00006518, a3                          ; copy screen from record
MoveLoop
        move.l  (a0)+, (a3)+
        cmpa    #$00007030, a3                          ; $6518 + 2840 = $7030
        blt     MoveLoop

        systrap MemHandleUnlock (a2.l)                  ; unlock record
                                                        ; record doesn't have to be released
                                                        ; because it was only queried

        call ShowCurrentIndex()

endproc

; *******************************************************************
; *                                                                 *
; *    Void   ShowCurrentIndex (void)                               *
; *                                                                 *
; *******************************************************************

proc ShowCurrentIndex()

beginproc

        move.w  CurrentIndex(a5),d0                     ; show page number
        addq.l  #1, d0
        move.l  d0,-(a7)
        pea.l   NumString(a5)
        trap    #15
        dc.w    sysTrapStrIToA
        addq.l  #8,a7
        systrap StrLen(&NumString(a5))
        systrap WinDrawChars (&NumString(a5),d0.w, #150.w, #150.w)

endproc


; *******************************************************************
; *                                                                 *
; *   Resources                                                     *
; *                                                                 *
; *   WBMP - Application Icon Bitmap resource.  Automatically       *
; *          converted from Windows format to Pilot format and      *
; *          written as a 'tAIB' rather than 'Tbmp' because kidbAIB *
; *          is a special value ($7ffe).                            *
; *   pref - Preference resource.  Defines app launch flags,        *
; *          stack and heap size.                                   *
; *   tFRM - Form resource.  Defined in scribble.rcp                *
; *   tver - Version resource                                       *                      *
; *   MBAR - Menu resource.  Defined in scribble.rcp                *
; *   Talt - Alert resource.  Defined in scribble.rcp               *
; *                                                                 *
; *   Filenames for scribble.rcp generated binaries are the         *
; *   resource type, followed by the ID in hexadecimal.             *
; *   E.g.  MBAR ID 1000 ==> mbar03e8.bin                           *
; *                                                                 *
; *******************************************************************

        res 'WBMP', kidbAIB, "Scribble.bmp"

        res 'pref', kidrPREF
        dc.w    sysAppLaunchFlagNewStack|sysAppLaunchFlagNewGlobals|sysAppLaunchFlagUIApp|sysAppLaunchFlagSubCall
        dc.l    $1000                   ; stack size
        dc.l    $1000                   ; heap size

        res 'tFRM', kidfMain, "tfrm03e8.bin"

        res 'tver', kidrTVER            
        dc.b    '1.5', 0

        res 'MBAR', kidmMain, "mbar03e8.bin"

        res 'Talt', kidrAboutAlert, "talt03e8.bin"

; ********************   debug code
;
;  this line can be used to insert a breakpoint
;
;       systrap ErrDisplayFileLineMsg (&ErrorString(a5), #163.w, &ErrorString(a5))
;