;NOTE: The libstartup code generated by LibTool opens the exec, DOS, Intuition, ; and Graphics libraries for our library functions and stores the bases ; at the following variables respectively. Therefore, our library code ; doesn't have to open these libs in order use their routines, nor close ; these libs. The next XREF statement should always be included in any ; lib code. ;NOTE: If you need to open any other libraries, it would be good to do so from ; within an Init vector. Remember to also add an Expunge vector which ; closes those libs. XREF _SysBase,_DOSBase,_IntuitionBase,_GfxBase ;If you need to examine your lib base structure (for some reason) make it ;visible here XREF _LibBase XREF _LVOForbid,_LVOPermit,_LVOAllocMem,_LVOFreeMem XREF _LVOAddTail,_LVORemTail,_LVOWaitPort,_LVOGetMsg,_LVORemove XREF _LVOOpenWindow,_LVOCloseWindow XREF _LVOMove,_LVOText ;============================================================= ; This is the first function in the library. First it finds the mem that was ; allocated for this task when the task opened the library (i.e. from within ; GetMem). Then it copies a newWindow template to this mem. Note that it is ; ok to have newWindow global because we don't modify it at all. We simply ; copy it to a the mem that we use for the task. Actually, it would have been ; easier/quicker to get the mem from the stack, but I wanted to demo using ; the Open/Close vectors. Finally, it opens the window and returns the result. XDEF MakeWindow ;make it visible to our libstartup code MakeWindow: move.l a6,-(sp) ;no lib routine should destroy d2-d7/a2-a6 ;---Find this task's work buffer bsr.s FindMem beq.s 1$ ;---Copy the newWindow template to our work buffer movea.l d0,a0 moveq #48-1,d1 lea newWindow(pc),a1 2$ move.b (a1)+,(a0)+ dbra d1,2$(pc) ;---Open the window movea.l d0,a0 movea.l _IntuitionBase,a6 jsr _LVOOpenWindow(a6) 1$ movea.l (sp)+,a6 rts ;============================================================= ; This finds the address of the task's work buffer allocated when the task ; opened the library. Note that this is for internal use only, and is not ; XDEF or included as a callable function in our fd file. FindMem: ;---Stop another task from getting in here while we examine memList ; This is what you have to do when you use globals that can be modified ; (memList). movea.l _SysBase,a6 jsr _LVOForbid(a6) ;---Get this task's address move.l 276(a6),d1 ;---Find this task's allocated memory move.l memList(pc),d0 2$ movea.l d0,a0 move.l (a0),d0 beq.s 1$ ;return(0) if we can't find the mem!!! cmp.l 8(a0),d1 bne.s 2$ ;---Skip the first 12 bytes moveq #12,d0 add.l a0,d0 1$ move.l d0,-(sp) ;---Permit again jsr _LVOPermit(a6) ;---Return 0 or the address of our "work buffer" move.l (sp)+,d0 rts ;============================================================= ; This is the second function in the library. It moves to the passed x and ; y coordinates, prints the passed msg in the passed window, then waits for ; a CLOSEWINDOW press before returning. XDEF PrintMsg PrintMsg: movem.l a2/a3/a6,-(sp) movea.l a0,a2 movea.l a1,a3 ;---Move to (x,y) movea.l 50(a2),a1 ;RastPort movea.l _GfxBase,a6 jsr _LVOMove(a6) ;---(Get its length) and print the msg movea.l a3,a0 1$ move.b (a3)+,d0 bne.s 1$ subq.l #1,a3 suba.l a0,a3 move.l a3,d0 ;the # of bytes not counting end NULL beq.s 2$ movea.l 50(a2),a1 jsr _LVOText(a6) ;---Wait for CLOSEWINDOW (the only msg we expect), remove it, and return 2$ movea.l _SysBase,a6 movea.l 86(a2),a0 jsr _LVOWaitPort(a6) movea.l 86(a2),a0 jsr _LVOGetMsg(a6) movem.l (sp)+,a2/a3/a6 rts ;============================================================= ; This is the third function in the library. It closes the passed window. XDEF RemWindow RemWindow: move.l a6,-(sp) movea.l _IntuitionBase,a6 jsr _LVOCloseWindow(a6) movea.l (sp)+,a6 rts ;======================================================================= ; These next 2 are called when an application opens and closes the lib ; respectively. The Open vector allocates a work buffer of 48 bytes for ; a newWindow structure, plus 8 bytes to link it into memList, plus 4 bytes ; to store the app's task address (which is what we use to indentify its ; work buffer in the list). The Close vector simply removes/frees the closing ; task's work buffer. ; Note that we don't have to Forbid/Permit when we access the memList because ; the task switching is already forbidden when these routines are called. ; For this reason, we should never do any kind of Wait() in here. ; We also don't have to save a6 since that is already done for us as well XDEF OpenUp OpenUp: ;---Get a zeroed, work buffer movea.l _SysBase,a6 moveq #8+4+48,d0 moveq #1,d1 bset.l #16,d1 jsr _LVOAllocMem(a6) move.l d0,d1 beq.s 1$ ;return 0 ;---Store the task address movea.l d0,a1 move.l 276(a6),8(a1) ;---Link it into memList lea memList(pc),a0 jsr _LVOAddTail(a6) moveq #1,d0 ;OK 1$ rts XDEF CloseUp CloseUp move.l a2,-(sp) ;---Find the work buffer bsr FindMem beq.s 1$ ;---Remove it from the list movea.l d0,a2 suba.w #12,a2 movea.l a2,a1 jsr _LVORemove(a6) ;---Free it movea.l a2,a1 moveq #8+4+48,d0 jsr _LVOFreeMem(a6) 1$ movea.l (sp)+,a2 rts ;an initialized, empty list to hold the address of each task's work buffer memList dc.l memList+4 dc.l 0 dc.l memList ;a newWindow structure to be used as a template newWindow: dc.w 10,10,200,180 dc.b 0,1 ;CLOSEWINDOW dc.l $200 ;SMART_REFRESH|ACTIVATE|WINDOWDRAG|WINDOWDEPTH|WINDOWSIZING dc.l $100f dc.l 0,0 dc.l 0 dc.l 0,0 dc.w 100,35,-1,-1 dc.w 1