; ; listbox.s ; ; Nice listbox handling routines (TMA) ; ; © 1994-1998 Straylight ; ;----- Licensing note ------------------------------------------------------- ; ; This file is part of Straylight's Sapphire library. ; ; Sapphire is free software; you can redistribute it and/or modify ; it under the terms of the GNU General Public License as published by ; the Free Software Foundation; either version 2, or (at your option) ; any later version. ; ; Sapphire is distributed in the hope that it will be useful, ; but WITHOUT ANY WARRANTY; without even the implied warranty of ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ; GNU General Public License for more details. ; ; You should have received a copy of the GNU General Public License ; along with Sapphire. If not, write to the Free Software Foundation, ; 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;----- Standard header ------------------------------------------------------ GET libs:header GET libs:swis ;----- External dependencies ------------------------------------------------ GET sapphire:alloc GET sapphire:fastMove GET sapphire:idle GET sapphire:divide GET sapphire:pane GET sapphire:resspr GET sapphire:sapphire GET sapphire:screen GET sapphire:tspr GET sapphire:win ;----- Main code ------------------------------------------------------------ AREA |Sapphire$$Code|,CODE,READONLY ; --- lb_create --- ; ; On entry: R0 == pointer to list manager description block ; R1 == pointer to the list ; R2 == pointer to a width function ; R3 == The height of each item ; R4 == parent window handle or ; pointer to window block if R5 == -1 ; R5 == parent icon handle or -1 if not a pane ; ; On exit: R0 == listbox handle ; R1 == window handle of list box ; May return an error (R1 corrupted) EXPORT lb_create lb_create ROUT STMFD R13!,{R2,R3,R10,R14} ;Stack some registers ; --- First, create the block --- MOV R10,R0 ;Preserve R0 MOV R0,#lb__size ;The structure size BL alloc ;Get the block BLCS alloc_error ;Get a message if no memory BCS %99lb_create ;Return on error MOV R14,R10 ;Do a swap type thing MOV R10,R0 ;Point to the block MOV R0,R14 ;Confused yet? STMIA R10,{R0-R5} ;Store information in block MOV R0,#0 ;No flags set yet STR R0,[R10,#lb__flags] ;Store this word STR R0,[R10,#lb__handler] ;No handler either BL lb__getMaxWidth ;Find length of longest item ; --- Calculate the minimum width and height of the box --- CMP R5,#-1 ;Is this a pane listbox? BNE %10lb_create ;No -- use icon then MOV R14,#176 ;A minimum height STR R14,[R10,#lb__height] ;Store the width LDR R0,[R4,#0] ;Load the minimum x position LDR R14,[R4,#8] ;Load the maximum x position SUB R0,R14,R0 ;Get the initial width STR R0,[R10,#lb__width] ;Store the width B %20lb_create ;And jump ahead a bit 10lb_create SUB R13,R13,#40 ;Get another block STR R4,[R13,#0] ;Store parent window handle STR R5,[R13,#4] ;And icon handle MOV R1,R13 ;Point to the block SWI Wimp_GetIconState ;Get the icon's state LDR R2,[R1,#16] ;Get the x1 coord LDR R14,[R1,#8] ;And x0 coord SUB R2,R2,R14 ;Calculate the icon width STR R2,[R10,#lb__width] ;Store the width LDR R2,[R1,#20] ;Get the y1 coord LDR R14,[R1,#12] ;And y0 coord SUB R2,R2,R14 ;Calculate the icon height STR R2,[R10,#lb__height] ;Store the height ADD R13,R13,#40 ;Get the block back ; --- Now create the window --- 20lb_create SUB R13,R13,#88 ;Get a block MOV R0,R13 ;Point to it CMP R5,#-1 ;Is this a pane listbox? ADRNE R1,lb__windowDef ;No -- point to my window def MOVEQ R1,R4 ;Yes -- use theirs then MOV R2,#lb__defSize ;Copy this much BL fastMove ;Copy the definition across LDR R1,[R10,#lb__height] ;y0 RSB R1,R1,#0 ;Negate it LDR R2,[R10,#lb__width] ;x1 ADD R14,R13,#44 ;The workarea extent block STMIA R14,{R1,R2} ;Store the desired extent BL resspr_area ;Find the sprite area STR R0,[R13,#64] ;Store this in the block MOV R1,R13 ;Point to the block SWI Wimp_CreateWindow ;Try to create the window ADD R13,R13,#88 ;Get the stack back BVS %98lb_create ;Return on error STR R0,[R10,#lb__wHandle] ;Store my window handle ; --- Set up the event handler --- ADR R1,lb__eventHandler ;Point to the event handler MOV R2,R10 ;R10 value to call with MOV R3,#0 ;R12 value to call with BL win_eventHandler ;Add in the event handler ; --- Add it as a pane to the parent (if we need to) --- MOV R2,R0 ;The window handle MOV R0,R4 ;Parent window handle MOVS R1,R5 ;Parent icon handle BLPL pane_add ;Register the pane (if reqd) ; --- Add scroll bars if we need too --- ORR R10,R10,#(1<<31) ;Don't open the window BL lb__rescanSize ;Re-scan the size nicely BIC R10,R10,#(1<<31) ;Clear silly bit again BVS %98lb_create ;Return om error LDR R1,[R10,#lb__wHandle] ;Return window handle in R1 MOV R0,R10 ;Return the listbox handle B %99lb_create ;Return to caller 98lb_create MOV R0,R10 ;Point to the allocated block BL free ;Free the block 99lb_create LDMFD R13!,{R2,R3,R10,R14} ;Get registers back ORRVSS PC,R14,#V_flag ;And return either with... BICVCS PC,R14,#V_flag ;...or without error LTORG lb__windowDef DCD 320,256,960,768 DCD 0,0 DCD -1 DCD &80000122 DCB 7,2,7,255,3,1,12,0 DCD 0,0,0,0 DCD &39,10<<12 DCD 0,0 DCB "ListBox",0,0 DCD 0 lb__defSize EQU {PC}-lb__windowDef ; --- lb__rescanSize --- ; ; On entry: R10 == pointer to listbox ; Bit 31 == don't call open the window ; ; On exit: VS and R0 == pointer to error or ; VC and R0 == window handle ; ; Use: Scans the list, and adds/removes scroll bars if necessary lb__rescanSize ROUT STMFD R13!,{R1-R10,R14} ;Stack some registers BIC R10,R10,#(1<<31) ;Clear the top bit ; --- First get the window state of the current window --- SUB R13,R13,#36 ;Get a block LDR R0,[R10,#lb__wHandle] ;Get the window handle STR R0,[R13,#0] ;Store in the block MOV R1,R13 ;Point to the block SWI Wimp_GetWindowState ;Get the window state LDR R6,[R1,#32] ;Get the window flags ADD R13,R13,#36 ;Get the block back again LDR R9,[R10,#lb__descriptor] ;Point to descriptor block LDR R0,[R10,#lb__list] ;Point to the list itself MOV R14,PC ;Set up the return address ADD PC,R9,#lb_items ;Call the function LDR R7,[R10,#lb__iHeight] ;The height of each item MUL R7,R1,R7 ;The required box y extent LDR R4,[R10,#lb__width] ;Overall box width LDR R5,[R10,#lb__height] ;Overall box height BL tspr_borderWidths ;Get the border widths BL screen_getInfo ;Get pixel sizes LDR R14,[R0,#screen_dx] ;x pixel size SUB R4,R4,R14,LSL#1 ;Correct overall width ADD R1,R1,R14 ;Set up border width LDR R14,[R0,#screen_dy] ;y pixel size SUB R5,R5,R14,LSL#1 ;Correct overall height SUB R2,R2,R14 ;Set up border height LDR R14,[R10,#lb__pIHandle] ;Get the parent icon handle CMP R14,#-1 ;Is this a pane dialogue? BEQ %50lb__rescanSize ;Yes -- jump ahead then ; --- Which scroll bars do we want? --- MOV R14,#0 ;No flags so far LDR R0,[R10,#lb__maxWidth] ;Get the width required CMP R0,R4 ;Is width>overall? ORRGT R14,R14,#(1<<30) ;Yes -- we need horz. scr bar SUBGT R5,R5,R2 ;Reduce overall height CMP R7,R5 ;Do we need a vertical bar? ORRGT R14,R14,#(1<<28) ;Yes -- make a note of this SUBGT R4,R4,R1 ;Reduce overall width TST R14,#(1<<30) ;Do we have a horz. bar? BNE %00lb__rescanSize ;Yes -- jump ahead CMP R0,R4 ;Is width>overall? ORRGT R14,R14,#(1<<30) ;Yes -- we need horz. scr bar SUBGT R5,R5,R2 ;Reduce overall height ; --- Do we need to add/remove scroll bars? --- 00 AND R0,R6,#&50000000 ;The scroll bars we have CMP R0,R14 ;Are the flags the same BEQ %50lb__rescanSize ;Yes -- jump ahead ; --- Now we need to recreate the window --- BIC R6,R6,#&50000000 ;No scroll bars at all ORR R6,R6,R14 ;Just the ones we want please ; --- Now create the new window --- SUB R13,R13,#88 ;Get a block MOV R0,R13 ;Point to it ADR R1,lb__windowDef ;Point to window definition MOV R2,#lb__defSize ;Copy this much BL fastMove ;Copy the definition across RSB R1,R7,#0 ;y0 LDR R2,[R10,#lb__maxWidth] ;x1 ADD R14,R13,#44 ;The workarea extent block STMIA R14,{R1,R2} ;Store the desired extent STR R6,[R13,#28] ;Store the flags word BL resspr_area ;Find the sprite area STR R0,[R13,#64] ;Store this in the block MOV R1,R13 ;Point to the block SWI Wimp_CreateWindow ;Try to create the window ADD R13,R13,#88 ;Get the block back LDRVS R0,[R10,#lb__pWHandle] ;On error, get window handle LDRVS R1,[R10,#lb__pIHandle] ;...get the icon handle BLVS pane_remove ;...remove the pane BVS %99lb__rescanSize ;...and Barf with error MOV R1,R0 ;Look after the window handle LDR R0,[R10,#lb__wHandle] ;Load the old handle BL win_swapWindow ;Tell win the handle changed MOV R2,R1 ;Look after new handle ADD R1,R10,#lb__wHandle ;Point to the old handle SWI Wimp_DeleteWindow ;Destroy the old window STR R2,[R10,#lb__wHandle] ;Store the new window handle LDR R0,[R10,#lb__pWHandle] ;Parent window handle LDR R1,[R10,#lb__pIHandle] ;Parent icon handle BL pane_swap ;Swap the pane B %50lb__rescanSize ;Jump ahead a little 50 ; --- Work out the correct extents --- BL screen_getInfo ;Get pixel sizes LDR R14,[R0,#screen_dx] ;x pixel size ADD R4,R4,R14,LSL#1 ;Correct overall width CMP R7,R5 ;Is requiredR2? MOVGT R7,R6 ;Yes == R0:=R2 CMP R7,R3 ;R0>R3? MOVGT R7,R3 ;Yes == R0:=R3 CMP R8,R6 ;R0current index? MOVGT R3,#0 ;Yes -- sel=0 B %30lb__idleHandler ;Jump ahead a bit 20 CMP R4,R5 ;i=current index? MOVEQ R3,#1 ;Yes -- sel=1 CMP R4,R6 ;i>initial index? MOVGT R3,#0 ;Yes -- sel=0 B %30lb__idleHandler ;Jump ahead a bit 30 CMP R4,R8 ;Are we at the end? BGT %50lb__idleHandler ;Yes -- jump out of loop ; --- Redraw the item if we need to --- CMP R3,#-1 ;Do we need to do anything? BEQ %00lb__idleHandler ;No -- keep going round STMFD R13!,{R0-R4} ;Stack some registers LDR R0,[R10,#lb__list] ;Get the list head MOV R4,R3 ;Look after thing in R3 MOV R2,#0 ;Read the flags MOV R3,#0 ;No writing here MOV R14,PC ;Set up return address ADD PC,R12,#lb_setFlags ;Read the flags ORR R3,R2,R2,LSR#1 ;Is bit 0 or 1 set? AND R3,R3,#1 ;Just interested in this bit CMP R3,R4 ;Is there a change to be made BEQ %40lb__idleHandler ;No -- keep on looping then ANDS R2,R2,#1 ;Just get selected bit BEQ %35lb__idleHandler ;If its clear -- jump ahead CMP R2,R4 ;Is this the same? BNE %40lb__idleHandler ;No -- return 35 MOV R2,#2 ;Just alter this bit MOV R3,R4,LSL#1 ;Set or clear appropriately LDR R0,[R10,#lb__list] ;Get the list head MOV R14,PC ;Set up return address ADD PC,R12,#lb_setFlags ;Set the flags MOV R0,R10 ;Put listbox handle in R0 BL lb_updateItem ;Update the item 40 LDMFD R13!,{R0-R4} ;Restore registers B %00lb__idleHandler ;Keep going round 50 LDMFD R13!,{R12} ;Get R12 back again STR R5,ws__dragLast ;Store last item visited ; --- Scroll the window nicely --- LDR R0,[R13,#44] ;Get the y scroll position CMP R9,R0 ;Is mouse y>y scroll? MOVGT R0,R9 ;Yes -- y scroll=mouse y BGT %55lb__idleHandler ;...and jump ahead LDR R2,[R13,#36] ;Get y1 coordinate LDR R3,[R13,#28] ;Get y0 coordinate SUB R3,R2,R3 ;Get window height ADD R9,R9,R3 ;Add on mouse position CMP R9,R0 ;Is it less than y scroll pos MOVLT R0,R9 ;Yes -- use y scroll pos 55 STR R0,[R13,#44] ;Store new scroll position ADD R1,R13,#20 ;Point to the block SWI Wimp_OpenWindow ;Open the window 99 ADD R13,R13,#56 ;Reclaim the stack 99 LDMFD R13!,{R0-R9,PC}^ ;Return to caller LTORG ; --- lb__unknownHandler --- ; ; On entry: R0 == event type ; R1 == event block ; R10 == listbox handle ; R12 == workspace pointer ; ; On exit: -- ; ; Use: Called when the drag is ended lb__unknownHandler ROUT CMP R0,#7 ;Are we interested? MOVNES PC,R14 ;No -- return PDQ STMFD R13!,{R0-R4,R14} ;Stack some registers ; --- First get rid of the idle claimer --- MOV R0,#0 ;Call very frequently ADR R1,lb__idleHandler ;Call this routine MOV R2,R10 ;Call with this R10 handle MOV R3,R12 ;And this R12 value BL idle_removeHandler ;Add in the handler ; --- Now this unknown handler --- ADR R0,lb__unknownHandler ;Call this routine MOV R1,#0 ;R4 value MOV R2,R10 ;Call with this R10 handle MOV R3,R12 ;And this R12 value BL win_removeUnknownHandler ;Add in the handler ; --- Make temporary selections permanant --- LDR R4,[R10,#lb__descriptor] ;Point to descriptor block LDR R0,[R10,#lb__list] ;Get the list head MOV R1,#0 ;Start from the top 00 MOV R2,#2 ;Just interested in this bit MOV R3,#2 ;And it must be set MOV R14,PC ;Set up the return address ADD PC,R4,#lb_enumerate ;Enumerate the list BCC %99lb__unknownHandler ;No more -- return LDR R0,[R10,#lb__list] ;Get the list head MOV R2,#3 ;Clear these bits MOV R3,#1 ;And set this one MOV R14,PC ;Set up the return address ADD PC,R4,#lb_setFlags ;And set the flags B %00lb__unknownHandler ;Keep going round for more 99 LDMFD R13!,{R0-R4,PC}^ ;Return to caller LTORG ; --- lb_drag --- ; ; On entry: R0 == listbox handle ; R1 == pointer to list item ; R3 == mouse button status ; ; On exit: -- ; ; Use: Starts a drag operation to allow for easy multiple ; selection. EXPORT lb_drag lb_drag ROUT STMFD R13!,{R0-R3,R10,R12,R14} ;Stack some registers WSPACE lb__wSpace ;Locate my workspace MOV R10,R0 ;Move listbox handle into R10 LDR R0,[R10,#lb__list] ;Point to the list head LDR R2,[R10,#lb__descriptor] ;Point to descriptor block CMP R1,#0 ;Is there an item MOVEQ R3,#lb_items ;No -- use the item count MOVNE R3,#lb_itemToIndex ;Yes -- find its index MOV R14,PC ;Set up return address ADD PC,R2,R3 ;Convert item to an index STR R1,ws__dragItem ;The start drag item STR R1,ws__dragLast ;Last item visited ; --- First we must start the drag box --- SUB R13,R13,#40 ;Get me a block MOV R1,R13 ;Point to the block SWI Wimp_GetPointerInfo ;Get mouse position LDR R0,[R1,#0] ;Get mouse x position LDR R1,=&9001 ;Parent y0 MOV R2,R0 ;Parent x1 LDR R3,=&6FFE ;Parent Parent y1 ADD R14,R13,#24 ;Point to right place STMIA R14,{R0-R3} ;Store parent coords MOV R0,#7 ;The drag type STR R0,[R13,#4] ;Store nicely in block MOV R1,R13 ;Point to the block SWI Wimp_DragBox ;Start the drag ; --- Set up the idle event handler --- MOV R0,#0 ;Call very frequently ADR R1,lb__idleHandler ;Call this routine MOV R2,R10 ;Call with this R10 handle MOV R3,R12 ;And this R12 value BL idle_handler ;Add in the handler ; --- Set up the unknown handler --- ADR R0,lb__unknownHandler ;Call this routine MOV R1,#0 ;R4 value MOV R2,R10 ;Call with this R10 handle MOV R3,R12 ;And this R12 value BL win_unknownHandler ;Add in the handler ; --- Now return to the caller --- ADD R13,R13,#40 ;Reclaim the stack LDMFD R13!,{R0-R3,R10,R12,PC}^ ;Return to caller LTORG ; --- lb_inserted --- ; ; On entry: R0 == pointer to the listbox ; R1 == pointer to the new item ; ; On exit: -- ; ; Use: Informs the listbox that an item has been inserted, ; and causes a flicker free insert to occur if possible. EXPORT lb_inserted lb_inserted ROUT STMFD R13!,{R0-R8,R10,R14} ;Stack some registers MOV R10,R0 ;Put listbox handle in R10 MOV R7,R1 ;Look after item BL lb__getMaxWidth ;Get the maximum width LDR R2,[R10,#lb__wHandle] ;Get the old window handle BL lb__rescanSize ;Ensure windows right size CMP R2,R0 ;Has the window changed? BNE %99lb_inserted ;Yes -- return ; --- Now do the block copy --- LDR R0,[R10,#lb__list] ;Get the list head LDR R2,[R10,#lb__descriptor] ;Get the descriptor MOV R14,PC ;Set up the return address ADD PC,R2,#lb_itemToIndex ;Convert item to index LDR R8,[R10,#lb__iHeight] ;Get the item height RSB R8,R8,#0 ;Negate it MUL R4,R8,R1 ;Get top of item MOV R14,PC ;Set up return address ADD PC,R2,#lb_items ;Get the item count MUL R2,R1,R8 ;The overall height LDR R0,[R10,#lb__wHandle] ;Get the window handle MOV R1,#0 ;The minimum x coord LDR R3,[R10,#lb__width] ;Load the window width LDR R6,[R10,#lb__maxWidth] ;And the widest item width CMP R6,R3 ;Which one is bigger? MOVGT R3,R6 ;Use the biggest one MOV R5,#0 ;x coord to move to ADD R6,R2,R8 ;y coord to move to SWI Wimp_BlockCopy ;Do a block copy ; --- Finally, update the new item --- MOV R0,R10 ;Point to the listbox MOV R1,R7 ;Put item pointer in R1 BL lb_updateItem ;Update the item 99lb_inserted LDMFD R13!,{R0-R8,R10,PC}^ ;Return to caller LTORG ; --- lb_removed --- ; ; On entry: R0 == pointer to the listbox ; R1 == index of item removed ; ; On exit: -- ; ; Use: Informs the listbox that an item has been removed, and ; causes a flicker free remove to occur, if possible. EXPORT lb_removed lb_removed ROUT STMFD R13!,{R0-R8,R10,R14} ;Stack some registers MOV R10,R0 ;Put listbox handle in R10 MOV R7,R1 ;Look after item BL lb__getMaxWidth ;Get the maximum width LDR R2,[R10,#lb__wHandle] ;Get the old window handle BL lb__rescanSize ;Ensure windows right size CMP R2,R0 ;Has the window changed? BNE %99lb_removed ;Yes -- return ; --- Now do the block copy --- LDR R2,[R10,#lb__descriptor] ;Get the descriptor block LDR R8,[R10,#lb__iHeight] ;Get the item height RSB R8,R8,#0 ;Negate it MUL R4,R8,R1 ;Get top of item ADD R4,R4,R8 ;Now get the bottom of it LDR R0,[R10,#lb__list] ;Get the list head MOV R14,PC ;Set up return address ADD PC,R2,#lb_items ;Get the item count MUL R2,R1,R8 ;The overall height LDR R3,[R10,#lb__height] ;Get overall window height SUB R2,R2,R3 ;Subtract that for luck LDR R0,[R10,#lb__wHandle] ;Get the window handle MOV R1,#0 ;The minimum x coord LDR R3,[R10,#lb__width] ;Load the window width LDR R6,[R10,#lb__maxWidth] ;And the widest item width CMP R6,R3 ;Which one is bigger? MOVGT R3,R6 ;Use the biggest one MOV R5,#0 ;x coord to move to SUB R6,R2,R8 ;y coord to move to SWI Wimp_BlockCopy ;Do a block copy 99lb_removed LDMFD R13!,{R0-R8,R10,PC}^ ;Return to caller LTORG ; --- lb_window --- ; ; On entry: R0 == listbox handle ; ; On exit: R0 == window handle ; ; Use: Returns the window handle of the listbox EXPORT lb_window lb_window ROUT LDR R0,[R0,#lb__wHandle] ;Load the window handle MOVS PC,R14 ;Return to caller LTORG ; --- lb_init --- ; ; On entry: -- ; ; On exit: -- ; ; Use: Initialises the listbox unit. EXPORT lb_init lb_init ROUT STMFD R13!,{R12,R14} ;Stack some registers WSPACE lb__wSpace ;Locate my workspace ; --- Ensure that we are not already initialised --- LDR R14,ws__flags ;Get the flags word TST R14,#wsFlag__inited ;Are we initialised? BNE %99lb_init ;Yes -- return ORR R14,R14,#wsFlag__inited ;We are initialised now STR R14,ws__flags ;Store back modified flags ; --- Return to caller --- 99lb_init LDMFD R13!,{R12,PC}^ ;Return to caller LTORG lb__wSpace DCD 0 ;----- List events ---------------------------------------------------------- ^ 0 lbEvent_close # 1 ;Listbox has been closed lbEvent_redraw # 1 ;Redraw a list item ;R1 == pointer to list item ;R2-R5 == window coords lbEvent_click # 1 ;Click/Double on listbox ;R1 == pointer to list item ;R2 == window relative y pos ;R3 == button type (10) lbEvent_menu # 1 ;Menu click ;R1 == pointer to list item ;R2 == window relative y pos ;R3 == button type (10) lbEvent_drag # 1 ;Drag on listbox ;R1 == pointer to list item ;R2 == window relative y pos ;R3 == button type (10) lbEvent_help # 1 ;R1 == pointer to list item lbEvent_drop # 1 ;R1 == pointer to list item ;R2 == filetype ;R3 == pointer to filename ;R4 == estimated file size ;R5 == subreason cde ^ 0 lbDrop_load # 1 lbDrop_save # 1 ;----- Workspace layout ----------------------------------------------------- ; --- listbox block descriptor --- ^ 0 lb_itemToIndex # 4 ;Item to index routine lb_indexToItem # 4 ;Index to item routine lb_enumerate # 4 ;Enumeration function lb_items # 4 ;Function to return items lb_setFlags # 4 ;Function to set/read flags ; --- listbox individual layout --- ^ 0 lb__descriptor # 4 ;Pointer to descriptor above lb__list # 4 ;The list itself lb__widthFun # 4 ;Function to return width lb__iHeight # 4 ;Height of each item lb__pWHandle # 4 ;Parent window handle lb__pIHandle # 4 ;Parent icon handle lb__handler # 4 ;The handler function lb__R10 # 4 ;The R10 value to pass lb__R12 # 4 ;The R12 value to pass lb__width # 4 ;Overall box width lb__height # 4 ;Overall box height lb__flags # 4 ;Listbox flags lb__wHandle # 4 ;The listbox window handle lb__maxWidth # 4 ;The maximum item width lb__size # 4 ;Size of this structure ; --- Main workspace --- ^ 0,R12 ws__flags # 4 ;The flags word ws__dragItem # 4 ;Item from which drag starts ws__dragLast # 4 ;Last drag item visited ws__size EQU {VAR}-ws__flags ;The size of the workspace wsFlag__inited EQU (1<<0) ;We are initialised AREA |Sapphire$$LibData|,CODE,READONLY DCD ws__size DCD lb__wSpace DCD 0 DCD lb_init ;----- That's all, folks ---------------------------------------------------- END