;----------------------------------------------------------- ; ; Xetrion Source Code ; ; (c) NeXO Software, Benoit SCHERRER ; e-mail : p.c.scherrer@wanadoo.fr ; ; ; File> plugins.xas ; Utility> gestion of plugins ; ;----------------------------------------------------------- ;--------------------------------------------------------------------- ; Format of the PluginParameters structure : ; ( 28 bytes length ) ; ; 00.w : return value 1, reserved ; 02.l : User parameter and return value2 ; 06.w : Zero based index of selected item ; in the list buffer ; 08.w : Zero based index of selected item on ; the screen ; 10.l : Address of STYLE structure ; 14.w : Handle of buffer list used ; 16.w : Real handle of current folder ; 18.w : Handle of selected item ; 20.w : reserved, for futur functions ; 22.l : reserved, for futur functions ;--------------------------------------------------------------------- include "pctplug.h" htabRelocatedLibs dc.w 0 ;----------------------------------------------------- ; Init plugins ;----------------------------------------------------- loadPluginsLibraries: movem.l d0-d4/a0,-(a7) ;------------------------------------------ ; Show 'loading plugins' win ;------------------------------------------- lea winLoadPlugins(PC),a0 jsr apilib::InterfaceEngine ;------------------------------------------ ; Check if preos is used ;------------------------------------------- ;cmp.w #'PO',($32).w ;bne.s \notpreos ;------------------------------------------ ; Create a tab that will contain ; required libs by ALL plugins ;------------------------------------------- moveq.w #VAT_ENTRYHDL,d1 jsr apilib::array_Create move.w d0,htabRelocatedLibs ;save handle beq MemoryCatcher move.w d0,d4 ;table handle ;------------------------------------------ ; Get plugin table addr and nb detected plugins ;------------------------------------------- move.l PluginTableAddr(PC),a0 ;addr of buffer move.w (a0)+,d3 ;nb of plugin in table beq.s \exit subq.w #1,d3 ;for dbra ;------------------------------------------ ; Scan all plugins and get required libs ; by all plugins ;------------------------------------------ \loop move.w d4,d2 ;handle of array move.w (a0)+,d0 ;plugin hdl bclr.l #15,d0 ;clear tmp flag of Plugin list jsr apilib::util_GetRequiredLibraries cmp.w #EC_OUTOFMEMORY,d1 beq.s \memerror dbra.s d3,\loop ;------------------------------------------ ; Now works on created tab ;------------------------------------------- movem.l d0-d2/a0-a1,-(a7) move.w d4,-(a7) jsr tios::HeapLock addq.l #2,a7 movem.l (a7)+,d0-d2/a0-a1 move.w d4,d0 bsr DEREFd0a0 ;get addr of tab addq #2,a0 move.w (a0)+,d3 ;nb libs required beq.s \end subq.w #1,d3 move.l a0,a1 ;------------------------------------------ ; Load all libs ;------------------------------------------- \loop2 clr.w d1 jsr kernel::LibsBegin move.l a0,10(a1) ;save descriptor (or null) lea VAT_ENTRYSIZE(a1),a1 ; move.l a1,a0 ;for libsBegin dbra.s d3,\loop2 \end movem.l d0-d2/a0-a1,-(a7) move.w d4,-(a7) jsr tios::HeapUnlock addq.l #2,a7 movem.l (a7)+,d0-d2/a0-a1 \exit movem.l (a7)+,d0-d4/a0 rts \memerror move.w d4,-(a7) jsr tios::HeapUnlock addq.l #2,a7 bra MemoryCatcher ;----------------------------------------------------- ; Free ;----------------------------------------------------- freePluginsLibraries: movem.l d0-d3/a0-a1,-(a7) move.w htabRelocatedLibs,d0 beq.s \exit ;------------------------------------------ ; Get addr ;------------------------------------------ bsr DEREFd0a0 ;get addr of tab addq #2,a0 move.w (a0)+,d3 ;nb libs required beq.s \exit subq.w #1,d3 move.l a0,a1 ;------------------------------------------ ; Lock handle ;------------------------------------------ movem.l d0-d2/a0-a1,-(a7) move.w d0,-(a7) jsr tios::HeapLock addq.l #2,a7 movem.l (a7)+,d0-d2/a0-a1 ;------------------------------------------ ; Free all loaded libs ;------------------------------------------ \loop2 clr.w d1 move.l 10(a1),a0 ; descriptor (or null) beq.s \next jsr kernel::LibsEnd \next lea VAT_ENTRYSIZE(a1),a1 dbra.s d3,\loop2 ;------------------------------------------ ; Unlock handle and free it ;------------------------------------------ move.w d0,-(a7) jsr tios::HeapUnlock jsr tios::HeapFree addq.l #2,a7 clr.w htabRelocatedLibs \exit movem.l (a7)+,d0-d3/a0-a1 rts ;----------------------------------------------------- ; Function called to run plugins : loop of all plugins ; for a functions and execute it if right extension ; ; On the stack : the plugin rg1 register ; d4.w : Function Index to call ;out> d0.w : return value of plugins ;----------------------------------------------------- ExecPlugin: move.l a0,-(a7) move.l 8(a7),d0 ;value given lea _exec_plg(PC),a0 bsr _common_ExecPlugin move.l (a7)+,a0 rts _exec_plg: moveq.w #1,d1 ;use extension bsr RunPlugin rts ;----------------------------------------------------- ; Function called to run plugins : loop of all plugins ; for a functions discarding extension info ; ; On the stack : the plugin rg1 register ; d4.w : Function Index to call ;out> d0.w : return value of plugins ;----------------------------------------------------- ExecPluginDiscardingExt: move.l a0,-(a7) move.l 8(a7),d0 ;value given lea _exec_plg_noext(PC),a0 bsr _common_ExecPlugin move.l (a7)+,a0 rts _exec_plg_noext: clr.w d1 ;discard extension bsr RunPlugin rts ;----------------------------------------------------- ; Internal function ; Loop all plugins and run a callback function ; ;Input> d0.l : User value ; a0.l : addr of callback fct ;Out> d0.w : ; d1.l : return value 2 ;----------------------------------------------------- _common_ExecPlugin: movem.l d2-d5/a0-a6,-(a7) ;don't save d6 d7 if ExitPlugin ;modify it move.l a0,a5 ;save it move.l a7,a4 ;for _plugin_prep1 suba.w #34,a7 ;create stack frame bsr CreatePluginStruct ; move.l PluginTableAddr(PC),a3 ;addr of buffer clr.w d3 ;default return value (0 even if d2=0) move.w (a3)+,d2 ;nb of plugin in table beq \exit subq.w #1,d2 ;for dbra \loop move.w (a3)+,d0 ;plugin hdl bclr.l #15,d0 jsr (a5) ;run callback function btst.l #31,d1 ;check if error bne.s \nextplug or.w d0,d3 ;General return btst.b #3,d0 ;SKIP next plugins ? bne.s \endplug \nextplug dbra.s d2,\loop \endplug bsr ExitPluginExec \exit move.l 4(a4),d1 ;return value2 adda.w #34,a7 ;clear buffer struct move.w d3,d0 ;return value and.w #1,d0 ;keep only SKIP_PCTPROCESS \ex movem.l (a7)+,d2-d5/a0-a6 rts ;----------------------------------------------------------- ; three internal functions that are used by ExecPlugin ; and ExecOnePlugin ;----------------------------------------------------------- ;--------------------------------------- ; Internal function ; Create the structure and set d5=extension ; ;input> d0.l : LongWord usable ; a4.l : addr of end of buffer ; d6/d7/a6 : general registers ; d4.w : function ID ;Out> d5.w : Extension ; a4.l : addr of struct ;--------------------------------------- CreatePluginStruct: _plugin_fct1: movem.l d0-d2/a0,-(a7) ;save d0 move.l d0,-(a7) ;parameter clr.w d0 ;default handle of selected file clr.w d5 ;by default : 0 tst.w d6 ;first item ? beq.s \skip btst.b #0,S_MODE(a6) ;Check if true VAT beq.s \skip ;if not, skip bsr GetCurrentVATAddr ;else get addr of select VAT btst.b #VAT_FOLDERBIT,VAT_ENTRYFLAG(a0) ;if a folder bne.s \skip ;add move.w ENTRYHDL(a0),d0 ;hdl of selected file bsr DEREFd0a0 ;selected file addr bsr GetFileExt ;its extension move.w d2,d5 ;Save extension of file \skip clr.l -(a4) ;For future clr.l -(a4) clr.l -(a4) move.w d0,-(a4) ;Handle of selected item btst.b #0,(a6) ;style table beq.s \normal ;if no true VAT tst.w ListBuf_Hdl ;If listbuf==0 we are in Tree Style, Folder side bne.s \normal API92_FOLDHDL -(a4) move.w ListReal_Hdl(PC),-(a4) bra.s \skip2 \normal move.w ListReal_Hdl(PC),-(a4) ;Handle of real list move.w ListBuf_Hdl(PC),-(a4) ;Handle of buffer \skip2 move.l a6,-(a4) ;Addr of STYLE structure move.w d7,-(a4) ;Screen Item Index move.w d6,-(a4) ;Item Index move.l (a7)+,-(a4) ;LongWord usable clr.w -(a4) ;Return value 1 move.w d4,-(a4) ;Function ID movem.l (a7)+,d0-d2/a0 rts ;--------------------------------------- ; Internal function ; Run a plugin, using extension or not ; ;input> d0.w : Handle of plugin ; d1.w : 0 = don't use extension ; else use extension ; d4.w : function ID ; d5.w : Extension of current file ; a4.l : addr of plugin struct ;Out> d0.w : ret value 1, 0 if error ; d1.l : ret value 2 $FFFF=error, $FFFE : execution error ;--------------------------------------- RunPlugin: _plugin_fct2: bsr GetPluginAddr tst.w d1 beq.s \no_ext move.l 12(a1),d1 ;get offset of EXTENSION_FILTER ;#ifdef TIPLUS lea 2(a0,d1.w),a2 ;#else lea 0(a0,d1.w),a2 ;#endif clr.l d1 move.b (a2)+,d1 ;nb of extension beq.s \no_ext subq.w #1,d1 \cmp_ext cmp.b (a2)+,d5 beq.s \no_ext dbra.s d1,\cmp_ext bra.s \nextplug \no_ext move.l 8(a1),d1 ;get offset of PLUGIN_TABLE lsl.w #2,d4 ;d4 * 4 add.w d4,d1 lsr.w #2,d4 ;restore d4 ;#ifdef TIPLUS tst.l 2(a0,d1) ;#else tst.l 0(a0,d1) ;#endif beq.s \nextplug move.l a4,(a1) ;put addr of struct if no error movem.l d1-d7/a0-a6,-(a7) move.w d0,-(a7) ;don't use ExecFile because jsr kernel::exec ;it refresh the screen addq.l #2,a7 movem.l (a7)+,d1-d7/a0-a6 btst.l #31,d0 ;test if error bne.s \errorexec \noerror move.w 2(a4),d0 ;return1 value move.l 4(a4),d1 ;return2 value \exit rts \nextplug clr.l d1 ;put -1 subq.l #1,d1 clr.l d0 ;d0=0 bra.s \exit \errorexec clr.l d0 clr.l d1 subq.w #2,d1 bra.s \exit ;--------------------------------------- ; Internal function ; End of plugin execution ; ;input> d3.w : flags ; d4.w : plugin function called ; ; (refresh plugin table only if ; REFRESH_PLUGIN_TABLE is set ;--------------------------------------- _plugin_fct3: ExitPluginExec move.l d1,-(a7) btst.b #4,d3 ;refresh plugin table? beq.s \norefresh bsr RefreshPluginTable ;refresh plugin table \norefresh jsr apilib::nf_CheckIfValid ;and check nested folders \skip moveq.w #1,d1 ;don't forget to set bsr FontSet ;the font 1 again btst.b #1,d3 ;REDRAW_SCREEN if needeed beq.s \nord bsr RedrawKeepingStatusBar bra.s \exit \nord btst.b #2,d3 ;REDRAW_LIST beq.s \exit bsr RedrawListArea \exit move.l (a7)+,d1 rts ;----------------------------------------------------------------- ; Execute only one plugin (no loop on all plugins), ; using extension or not ; (used for plugin menu) ; ;Input> d0.w : Plugin Handle ; d1.w : Function ID ; d2.w : 0 = don't use extension ; else use extension ;Out> d0.l : 0 if error ; else value given in plugin ; d1.l : ReturnValue2 of plugin ;----------------------------------------------------------------- ExecOnePlugin: movem.l d2-d5/a0-a6,-(a7) ;don't save d6 d7 if ExitPluginExec ;modify it move.w d1,d4 ;for functions move.l a7,a4 ;for CreatePluginStruct suba.w #34,a7 ;create stack frame move.w d0,-(a7) ;Save plugin handle move.w d2,-(a7) ;save use extension or not move.l 4+14*4+34+2*2(a7),d0 ;LongWord passed bsr CreatePluginStruct ; move.w (a7)+,d1 ;Use extension or not move.w (a7)+,d0 ;plugin handle bsr RunPlugin ;plugin fct move.w d0,d3 ;save return bsr ExitPluginExec \exit adda.w #34,a7 move.l d3,d0 and.l #1,d0 movem.l (a7)+,d2-d5/a0-a6 rts ;----------------------------------------------------------------- ; GetPluginAddr ; Get addr of param_addr offset of plugin ;Input> d0.w : Handle of plugin ;Out> a0.l : Addr of beginning of file ; a1.l : Addr of beginning of plugin ;----------------------------------------------------------------- GetPluginAddr: move.l d1,-(a7) bsr DEREFd0a0 ;addr of plugin ;#ifdef TIPLUS move.w $0C+2(a0),d1 ;get _main offset lea 2+6(a0,d1.w),a1 ;and get addr of fctnum ;#else lea $1A+$6(a0),a1 ;offset in plugin ;#endif move.l (a7)+,d1 rts ;----------------------------------------------------------------- ; Refresh the Plugin Table ; (on a stack frame) ;----------------------------------------------------------------- RefreshPluginTable: movem.l d0-d7/a0-a6,-(a7) ;--------------------------------------- ; first delete old unarchived plugins ;--------------------------------------- bsr DeleteUnarchivedPlugins ;--------------------------------------- ; Creates new list ;--------------------------------------- move.l PluginTableAddr(PC),a3 ;addr of buffer lea 2(a3),a2 ;keep a word for plugin nb API92_FOLDHDL d0 bsr DEREFd0a0 ;address of folder list lea 2(a0),a4 ;skip first word move.w (a4)+,d7 ;d7=nb of folders subq.w #1,d7 clr.w d6 ;number of copied plugins ;--------------------------------------- ; Loop that looks for folders ;--------------------------------------- \allfold move.w ENTRYHDL(a4),d0 beq.s \nextfold bsr DEREFd0a0 lea 2(a0),a1 ;skip first word move.w (a1)+,d5 ;nb files in folder beq.s \nextfold ;if 0 skip subq.w #1,d5 ;for dbra ;--------------------------------------- ; loop that looks for files ;--------------------------------------- \loop move.w ENTRYHDL(a1),d0 ;handle of prog beq.s \goloop ;check if not null bsr DEREFd0a0 ;address of program ;--------------------------------------- ; Check if valid plugin ;--------------------------------------- bsr GetFileExt ;get file extension cmp.w #EXT_PLUG,d2 ;check if a plugin bne.s \goloop ;#ifdef TIPLUS move.w $0C+2(a0),d1 ;get _main offset lea 12+2(a0,d1.w),a0 ; ;#else adda.w #($1A+12),a0 ;offset in plugin ;#endif cmp.w #NB_PLUGINFCT,(a0) ;Check nb of plugin bne.s \goloop ;-------------------------------------- ; if archived plugin unarchives it ; and get new handle ;-------------------------------------- ;#ifdef TIPLUS btst.b #ARCH_BIT,ENTRYFLG(a1) ;TEST if archived bne.s \arch cmp.l #$03FFFF,a0 bls.s \ok \arch bsr TmpUnarchiveProg ;if archived try to tst.w d0 ;unarchive beq.s \goloop bset.l #15,d0 ;set archived \ok ;#endif move.w d0,(a2)+ ;if archived handle addq.w #1,d6 ;inc nb of plugins copied \goloop lea VATENTRY_SIZE(a1),a1 dbra.s d5,\loop \nextfold lea VATENTRY_SIZE(a4),a4 dbra.s d7,\allfold move.w d6,(a3) ;put nb of plugin \exit movem.l (a7)+,d0-d7/a0-a6 rts ;----------------------------------------------------- ; Copy plugin into a tmp handle in RAM (used when ; plugin is archived) ;INput> d0.w : file hdl ;Out> d0.w : 0 if error ; else hdl created ;----------------------------------------------------- TmpUnarchiveProg: movem.l d1-d4/a0-a2,-(a7) move.w d0,d3 ;save it bsr DEREFd0a0 clr.l d4 ;get file size move.w (a0),d4 addq.l #2+4,d4 ;+4 for rounding move.l d4,-(a7) ;alloc mem TIOS_CALL HeapAlloc addq.l #4,a7 tst.w d0 ;if error exit beq.s \exit bsr DEREFd0a0 ;get move.l a0,a1 ;dest addr exg.l d0,d3 bsr DEREFd0a0 ;src addr lsr.w #2,d4 beq.s \copy ;if something strange... subq.w #1,d4 ;for dbra \copy move.l (a0)+,(a1)+ dbra.s d4,\copy move.w d3,d0 ;set dest hdl \exit movem.l (a7)+,d1-d4/a0-a2 rts ;----------------------------------------------------- ; Loop on plugin table and delete all tmp handle ;----------------------------------------------------- DeleteUnarchivedPlugins: ;#ifdef TIPLUS movem.l d0-d4/a0-a4,-(a7) move.l PluginTableAddr(PC),a3 ;addr of buffer move.w (a3),d3 ;nb of plugins beq.s \exit subq.w #1,d3 ;for dbra clr.w (a3)+ ;clear nb plugins in list \loop move.w (a3)+,d0 btst.l #15,d0 ;get hdl beq.s \noarch bclr.l #15,d0 move.w d0,-(a7) ;else delete it bsr _HeapFree addq.l #2,a7 \noarch dbra.s d3,\loop \exit movem.l (a7)+,d0-d4/a0-a4 ;#endif rts ;-------------------------------------------------- ; exec a viewer or a plugin ;input> a0.l : addr of viewer/plugin name ; d4.l : hdl of the argument file (for viewer) ; num of the function (for plugins) ;-------------------------------------------------- ExecViewer: movem.l d1-d7/a0-a2,-(a7) clr.w d5 ;default: no handle created ;-------------------------------------- ; Look for viewer everywhere ;-------------------------------------- jsr apilib::vat_FindVarEverywhere lea viewerr(PC),a2 tst.w d2 ;if not found, exit beq.s \error move.w ENTRYHDL(a1),d0 ;d0=hdl of viewer/plugin bsr DEREFd0a0 ;-------------------------------------- ; if archived viewer make a copy ; in RAM ;-------------------------------------- ;#ifdef TIPLUS cmp.l #$200000,a0 bcs.s \not_archived bsr TmpUnarchiveProg ;unarchive viewer move.w d0,d5 ;check if error beq.s \memerror bsr DEREFd0a0 ;get new addr \not_archived ;#endif ;-------------------------------------- ; Run viewer ;-------------------------------------- ;#ifdef FRENCH adda.w #14,a2 ;#else adda.w #17,a2 ;invalid viewer txt ;#endif ;#ifdef TIPLUS move.w $0C+2(a0),d1 btst.b #0,d1 bne.s \error lea 2(a0,d1.w),a0 ;#else adda.w #$1A,a0 ;offset in viewer prog ;#endif cmp.w #$6002,(a0)+ bne.s \error move.w d4,(a0) ;put hdl of the file to view movem.l d0-d7/a0-a6,-(a7) move.w d0,-(a7) jsr kernel::exec addq.l #2,a7 movem.l (a7)+,d0-d7/a0-a6 ;-------------------------------------- ; if archived viewer, delete created buffer ;-------------------------------------- \exit ;#ifdef TIPLUS move.w d5,-(a7) beq.s \nofree bsr _HeapFree \nofree addq.l #2,a7 ;#endif bsr RedrawKeepingStatusBar \ex movem.l (a7)+,d1-d7/a0-a2 rts \error bsr ST_Message clr.w d0 ;error value bra.s \exit \memerror lea vmemerr(PC),a2 bra.s \error vmemerr dc.b "Out of memory",0 viewerr: ;#ifdef FRENCH dc.b "Viewer absent",0 dc.b "Viewer non valide",0 ;#else dc.b "Viewer not found",0 dc.b "Invalid Viewer",0 ;#endif