; drawX.s ; ; An example of various Sapphire features (MDW) ; ; © 1994-1998 Straylight ; ;----- Licensing note ------------------------------------------------------- ; ; DrawX 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. ; ; DrawX 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 DrawX. If not, write to the Free Software Foundation, ; 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;----- Notes ---------------------------------------------------------------- ; ; This application is a DrawFile viewer -- not even slightly useful in ; itself (although it uses the same amount of memory as Draw needs ; workspace!), but it does provide quite a neat demonstration of the ; following Sapphire features, and provides examples of how to use them: ; ; * dialogue boxes and custom dialogue box controls (arrow and numWrite) ; * error handling ; * memory management ; * drawfile rendering ; * data transfer ; * menu handling ; * command line processing ; * loading preferences ; ; It demonstrates dragging objects inside windows -- the code is fairly ; similar in structure to Glass's drag code, except that in the interests ; of keeping code size down I've not done rotating dash boxes. ; ; The other interesting feature exhibited is that the image for this ; application is just over half the size of the Acorn equivalent `DrawEx', ; which (a) doesn't support multiple drawfiles unless you hack it, (b) ; doesn't do zooming or dragging, and (c) doesn't support Help. ; ; Mark Wooding ;----- Standard header ------------------------------------------------------ GET libs:header GET libs:swis GET libs:stream ;----- External dependencies ------------------------------------------------ ; --- Sapphire --- GET sapphire:sapphire GET sapphire:akbd GET sapphire:alloc GET sapphire:banner GET sapphire:buttons GET sapphire:cmdLine GET sapphire:dbox GET sapphire:defHandler GET sapphire:divide GET sapphire:drag GET sapphire:draw GET sapphire:errorBox GET sapphire:event GET sapphire:fastMove GET sapphire:flex GET sapphire:heap GET sapphire:help GET sapphire:hour GET sapphire:ibicon GET sapphire:idle GET sapphire:intKeys GET sapphire:libOpts GET sapphire:mbox GET sapphire:menu GET sapphire:menuDefs GET sapphire:msgs GET sapphire:progInfo GET sapphire:ptr GET sapphire:report GET sapphire:res GET sapphire:resources GET sapphire:screen GET sapphire:string GET sapphire:warning GET sapphire:wimp GET sapphire:win GET sapphire:winUtils GET sapphire:choices.choices GET sapphire:choices.options GET sapphire:choices.prefs GET sapphire:dbx.dbx GET sapphire:dbx.arrow GET sapphire:dbx.numWrite GET sapphire:xfer.load GET sapphire:xfer.save GET sapphire:xfer.saveAs ; --- Other external symbols --- IMPORT version IMPORT cright ;----- Constants ------------------------------------------------------------ ; --- Icon numbers --- bnr__version EQU 4 ;The version display area bnr__slider EQU 6 ;The progress slider bar scale__write EQU 0 ;The scale writable icon scale__up EQU 1 ;The scale up arrow button scale__down EQU 2 ;The scale down arrow button scale__toScreen EQU 4 ;The Scale to screen action scale__toWindow EQU 5 ;The Scale to window action scale__buttons EQU 6 ;The 8 set scale buttons scale__ok EQU 14 ;And the OK button info__name EQU 1 ;The DrawFile name area info__size EQU 3 ;The file size area ; --- Menu items --- im__info EQU 0 ;The program info option im__quit EQU 1 ;The quit application option mm__info EQU 0 ;The file info option mm__save EQU 1 ;The save drawfile option mm__scale EQU 2 ;The scale option ; --- Other constants --- drawX__topY EQU 940 ;Maximum height for diagrams drawX__bottomY EQU 700 ;Minimum height for diagrams drawX__startY EQU 844 ;Initial height for diagrams drawX__filetype EQU &AFF ;The filetype of a DrawFile ;----- Data structures ------------------------------------------------------ ; --- Window blocks --- ^ 0 dWin__window # 4 ;The window handle dWin__flags # 4 ;Various flags dWin__diagram # 4 ;Flex anchor for diagram dWin__diagSize # 4 ;Size of the diagram dWin__scale # 4 ;Scale of diagram (as 16.16) dWin__extent # 16 ;The window's extent size dWin__filename # 256 ;The diagram's filename dWin__titleBar # 256 ;The diagram's title buffer dWin__size # 0 dwFlag__loaded EQU (1<<0) ;File has a good filename dwFlag__hasDiag EQU (1<<1) ;There is an actual diagram dwFlag__saving EQU (1<<2) ;This diagram is being saved dwFlag__tent EQU (1<<3) ;Diagram block is tentative ; --- Preferences data --- ^ 0 dPref__defScale # 4 ;Default document scale dPref__size # 0 ;----- Workspace ------------------------------------------------------------ ^ 0,R12 drawX__wStart # 4 drawX__prefs # dPref__size ;User's preferences drawX__winY # 4 ;y position for next window drawX__flags # 4 ;Various interesting flags drawX__pollBlk # 256 ;The main polling block dxFlag__drag EQU (1<<0) ;In midst of drag operation dxFlag__ownPtr EQU (1<<1) ;We own the mouse pointer drawX__wSize EQU {VAR}-drawX__wStart ;----- Initialisation ------------------------------------------------------- AREA |Client$$Code|,CODE,READONLY ENTRY drawX__main ROUT ; --- Start up the library --- ADR R0,drawX__appName ;Point to application name MOV R1,#drawX__wSize ;Get my workspace size MOV R2,#0 ;Default stack size BL sapphire_init ;Initialise the library BL resources_init ;Use shared resource DLL BL hour_init ;Initialise hourglass system BL hour_on ;Turn on hourglass as needed MOV R0,#0 ;This is the first pass BL drawX__cmdLine ;Read the command line SWICS OS_Exit ;If helped, return to caller ; --- Do various bits of initialisation --- ADR R0,drawX__banner ;Point to banner block MOV R1,R12 ;Pass setup code my R12 value BL banner ;Initialise the library BL drawX__init ;Initialise workspace BL drawX__iconbar ;Put the icon on the iconbar BL drawX__getPrefs ;Load the preferences BL heap_useHeap ;Allocate things from heap BL ptr_blinkOn ;Enable caret blinking MOV R0,#1 ;This is the second pass BL drawX__cmdLine ;Parse the command line ; --- Enter the main loop --- BL drawX__errors ;Set up the error return pt 00drawX__main MOV R0,#1 ;Don't use idles pointlessly ADR R1,drawX__pollBlk ;Point to my poll block BL event_poll ;Get an event and handle it BLCC drawX__unknowns ;Handle any unknown events BLCC defHandler ;Supply a default action B %00drawX__main ;And go round for another one drawX__appName DCB "DrawX",0 drawX__banner BANNER BNSLIDE bnr__slider BNSETUP drawX__bnrSetup BNEND ; --- drawX__errors --- ; ; On entry: -- ; ; On exit: -- ; ; Use: Sets up the error handler to return to this routine's return ; address drawX__errors ROUT STMFD R13!,{R0-R2,R14} ;Save some registers BIC R0,R14,#&FC000003 ;Set up the resume address MOV R1,R12 ;Set up workspace on return ADD R2,R13,#16 ;And set up return stack ptr BL report_register ;Set up the return point LDMFD R13!,{R0-R2,PC}^ ;Return to caller LTORG ; --- drawX__init --- ; ; On entry: -- ; ; On exit: -- ; ; Use: Initialises DrawX's workspace. drawX__init ROUT STMFD R13!,{R14} ;Save the link register MOV R14,#drawX__startY ;Default diagram height STR R14,drawX__winY ;Save the y coordinate MOV R14,#0 ;Clear the flags word STR R14,drawX__flags ;Store that away LDMFD R13!,{PC}^ ;Return to caller LTORG ; --- drawX__bnrSetup --- ; ; On entry: R0 == banner dialogue handle ; ; On exit: -- ; ; Use: Fills in fields of the opening banner dialogue box. drawX__bnrSetup ROUT STMFD R13!,{R0-R2,R14} ;Save some registers MOV R1,#bnr__version ;Get the version icon LDR R2,=version ;Find the version string BL dbox_setField ;Fill in the icon nicely LDMFD R13!,{R0-R2,PC}^ ;Return to caller LTORG ; --- drawX__getPrefs --- ; ; On entry: -- ; ; On exit: -- ; ; Use: Loads the application's preferences file. drawX__getPrefs ROUT STMFD R13!,{R0-R4,R14} ;Save some registers ; --- Initialise the preferences area --- ADR R0,drawX__prefs ;Point to prefs buffer ADR R1,drawX__defaults ;Point to default values MOV R2,#dPref__size ;Size of the data BL fastMove ;Initialise the buffer ; --- Now read in the preferences --- BL prefs_find ;Find the prefs chunk file ADR R1,drawX__appName ;Use my name as the chunk ADR R2,drawX__optDefs ;Point to options definition ADR R3,drawX__prefs ;Point to preferences buffer MOV R4,#-1 ;It's not in a flex block BL options_read ;Read the preferences LDMFD R13!,{R0-R4,PC}^ ;Return to caller drawX__defaults DCD 100 ;Initialise default scale drawX__optDefs OPTINT dPref__defScale,"DefaultScale" OPTEND LTORG ; --- drawX__cmdLine --- ; ; On entry: R0 == 0 for first pass, 1 for second pass ; ; On exit: CS if help given, CC otherwise ; ; Use: Parses the DrawX command line, loading documents as required. drawX__cmdLine ROUT STMFD R13!,{R0-R4,R10,R14} ;Save a load of registers MOV R4,R0 ;Look after pass flag SWI OS_GetEnv ;Find the command line MOV R1,R11 ;Build in the scratchpad BL cl_next ;Skip the application name BCC %90drawX__cmdLine ;If nothing there, skip MOV R3,R0 ;Look after the cmdline ptr ; --- The main parsing loop --- 00 MOV R0,R3 ;Point to command line ADR R1,drawX__pollBlk ;Build in the poll block BL cl_next ;Get next word from cmdline BCC %90drawX__cmdLine ;If nothing there, skip MOV R3,R0 ;Keep place in string ADR R0,drawX__cmdTable ;Point to keyword table BL str_match ;Find which name matches ADDCS PC,PC,R0,LSL #2 ;If match, use branch table B %05drawX__cmdLine ;If no match, load file B %10drawX__cmdLine ;Give help to the user B %15drawX__cmdLine ;Enable Choices support B %20drawX__cmdLine ;Use a Dynamic Area ; --- Load a file --- 05 TST R4,#1 ;Which pass is this? BEQ %00drawX__cmdLine ;First -- don't load then MOV R0,R1 ;Point to filename again MOV R10,#0 ;No diagram handle yet BL drawX__loadFile ;Try loading the file BLVC drawX__loaded ;If loaded, make it nice MOVVS R1,#1 ;Otherwise set up error BLVS drawX__loadFail ;And tidy up after it B %00drawX__cmdLine ;And parse more command line ; --- Give command line help --- 10 ADR R0,drawX__cmdHelp ;Point to command line help MOV R1,#0 ;Use internal dictionary LDR R2,=version ;Find my version string SWI OS_PrettyPrint ;Print the string ORR R4,R4,#2 ;Remember we gave some help B %00drawX__cmdLine ;And parse more command line ; --- Enable the Choices application --- 15 TST R4,#1 ;Is this the first pass? MOVEQ R0,#1 ;Set Choices support on BLEQ choices_useChoices ;Turn the support on B %00drawX__cmdLine ;And parse more command line ; --- Enable use of Dynamic Areas --- 20 TST R4,#1 ;Is this the first pass? ADREQ R0,drawX__opts ;Yes -- point to options BLEQ libOpts_register ;And register them B %00drawX__cmdLine ;And parse more command line ; --- Return to caller nicely --- 90 TST R4,#2 ;Did we give any help? LDMFD R13!,{R0-R4,R10,R14} ;Restore registers ORRNES PC,R14,#C_flag ;If so, set C flag on exit BICEQS PC,R14,#C_flag ;Otherwise clear it drawX__cmdTable DCB "-help",0 DCB "-choices",0 DCB "-dynArea",0 DCB 0 drawX__cmdHelp DCB "DrawX v. ",27,0,13 DCB 13 DCB "Usage: *DrawX [] []...",13 DCB 13 DCB "Options allowed are:",13 DCB 13 DCB "-choices",9,"Store options in Acorn's `Choices' " DCB "directory",13 DCB "-dynArea",9,"Use a Dynamic Area for memory " DCB "management",13 DCB 0 drawX__opts LIBOPT "FLEX" ;Tell flex to use a dynamic DCD 1 ;area if it can LOEND LTORG ;----- The icon bar --------------------------------------------------------- ; --- drawX__iconbar --- ; ; On entry: -- ; ; On exit: -- ; ; Use: Installs the DrawX icon on the icon bar drawX__iconbar ROUT STMFD R13!,{R0-R6,R14} ;Save some registers ADR R0,drawX__sprName ;Point to the sprite name MOV R1,#0 ;No text required MOV R2,#-1 ;Left hand side of iconbar MOV R3,#0 ;Standard priority please ADR R4,drawX__ibHandler ;Point to my event handler MOV R5,#0 ;No value in R10 MOV R6,R12 ;Pass workspace in R12 BL ibicon_create ;Create the icon SWIVS OS_GenerateError ;If it failed, kill the app LDMFD R13!,{R0-R6,PC}^ ;Return to caller drawX__sprName DCB "!drawx",0 LTORG ; --- drawX__ibHandler --- ; ; On entry: R0 == icon bar event type ; R1-R9 == dependent on event type ; ; On exit: -- ; ; Use: Handles events directed at the icon bar. drawX__ibHandler ROUT CMP R0,#ibEvent_help ;Is it an event I recognise? ADDLS PC,PC,R0,LSL #2 ;Yes -- dispatch to handler MOVS PC,R14 ;Otherwise return to caller B drawX__ibSelect ;Handle a mouse click B drawX__ibMenu ;Handle a Menu click MOVS PC,R14 ;Ignore Adjust clicks B drawX__ibData ;Handle a data save B drawX__ibData ;Handle a data load B drawX__ibHelp ;Handle help requests ; --- Handle Select clicks on the icon --- drawX__ibSelect STMFD R13!,{R0,R1,R10,R14} ;Save the link register MOV R0,#0 ;No filename for the diagram BL drawX__newDiag ;Create a new diagram BLVC drawX__setTitle ;Set the window's title BLVC drawX__open ;Open the window nicely BLVC drawX__cascade ;If it worked, do cascading MOVVS R1,#1 ;Otherwise report the error BLVS errorBox ;With just an OK button LDMFD R13!,{R0,R1,R10,PC}^ ;Return to caller ; --- Handle data transfer to the icon --- drawX__ibData STMFD R13!,{R0,R1,R10,R14} ;Save some registers BL event_last ;Find the last event code LDR R0,[R1,#40] ;Load the data filetype MOV R10,#0 ;No diagram created currently BL drawX__load ;Load the file LDMFD R13!,{R0,R1,R10,PC}^ ;Return to caller ; --- Handle menu clicks on the icon --- drawX__ibMenu STMFD R13!,{R0-R3,R14} ;Save some registers ADR R0,drawX__imDef ;Point to the icon bar menu ADR R1,drawX__imHnd ;Point to the handler code MOV R2,R10 ;Pass my R10 value along MOV R3,R12 ;And my workspace pointer BL menu_create ;And create the menu LDMFD R13!,{R0-R3,PC}^ ;Return to caller ; --- Define the icon bar menu --- drawX__imDef MENU "DrawX" ITEM "drxIMINFO" SUBWARN ITEM "drxIMQUIT" MENUEND ; --- Handle help requests --- drawX__ibHelp STMFD R13!,{R0,R14} ;Save some registers ADR R0,drawX__ibHlpMsg ;Point to the message tag BL msgs_lookup ;Translate the message BL help_add ;Add it to the help message LDMFD R13!,{R0,PC}^ ;Return to caller drawX__ibHlpMsg DCB "drxhIB",0 LTORG ; --- drawX__imHnd --- ; ; On entry: R0 == menu event code ; R1 == item number in menu ; ; On exit: -- ; ; Use: Handles events for the icon bar menu. drawX__imHnd ROUT CMP R0,#mEvent_help ;Is it a help request? BEQ %50drawX__imHnd ;Yes -- handle it nicely CMP R0,#mEvent_select ;Is it a normal selection? CMPNE R0,#mEvent_subMenu ;Or opening a submenu MOVNES PC,R14 ;No -- ignore it then ; --- Handle a menu selection event --- CMP R1,#im__quit ;Is it the `Quit' option? SWIEQ OS_Exit ;Yes -- quit the program CMP R1,#im__info ;Or is it the `Info' option? MOVNES PC,R14 ;No -- ignore the event ; --- Display info about DrawX --- STMFD R13!,{R0-R2,R14} ;Save some registers ADR R0,drawX__purpose ;Point to the purpose string BL msgs_lookup ;Translate the message tag LDR R1,=cright ;Point to copyright string LDR R2,=version ;Find the version/date string BL progInfo ;Display the dialogue box MOVVS R1,#1 ;If it failed, report error BLVS errorBox ;With just an OK button LDMFD R13!,{R0-R2,PC}^ ;Return to caller drawX__purpose DCB "drxPUR",0 ; --- Handle help requests for the menu --- 50drawX__imHnd STMFD R13!,{R0,R1,R14} ;Save some registers ADR R0,drawX__imHlpMsg ;Point to the help string BL menu_help ;Add message to help string LDMFD R13!,{R0,R1,PC}^ ;Return to caller drawX__imHlpMsg DCB "drxhIM",0 LTORG ;----- Scale dialogue box --------------------------------------------------- ; --- drawX__scale --- ; ; On entry: R10 == diagram handle ; ; On exit: -- ; ; Use: Displays a dialogue box allowing the user to scale the ; a draw file. drawX__scale ROUT STMFD R13!,{R0-R3,R9,R14} ;Save some registers ; --- Create the dialogue box --- ADR R0,drawX__scaledb ;Point to the dialogue name BL dbox_create ;Try to create the dialogue MOVVS R1,#1 ;If it failed, report the BLVS errorBox ;error and quit BVS %90drawX__scale MOV R9,R0 ;Look after the dbox handle ; --- Set up the handler --- ADR R1,drawX__scHnd ;Point to the handler MOV R2,R10 ;Pass the diagram in R10 MOV R3,R12 ;Pass workspace in R12 BL dbox_eventHandler ;Set up the event handler ADR R1,drawX__scaleDbx ;Point to the dbx def BL dbx_declare ;Register the control types ; --- Fill in the dialogue box --- BL drawX__fillScale ;Fill in the scale ; --- Display it on the screen --- MOV R1,#dbOpen_pointer+dbOpen_trans BL dbox_open ;Display the dialogue box 90drawX__scale LDMFD R13!,{R0-R3,R9,PC}^ ;Return to caller drawX__scaledb DCB "scale",0 drawX__scaleDbx NUMWRT scale__write,1,800 ARROW scale__up,1 ARROW scale__down,-1 DBXEND ; --- drawX__fillScale --- ; ; On entry: R9 == dialogue box handle ; R10 == diagram handle ; ; On exit: -- ; ; Use: Resets the scale dialogue box. drawX__fillScale ROUT STMFD R13!,{R0-R2,R14} ;Save some registers LDR R2,[R10,#dWin__scale] ;Load the current scale ADD R2,R2,R2,LSL #2 ;Multiply it by 5 (x5) ADD R2,R2,R2,LSL #2 ;Multiply it by 5 (x25) MOV R2,R2,LSR #14 ;Divide it by 2^14 MOV R1,#scale__write ;Find the writable icon MOV R0,R9 ;Get the dialogue handle BL numWrite_set ;Set the field up nicely LDMFD R13!,{R0-R2,PC}^ ;Return to caller LTORG ; --- drawX__scHnd --- ; ; On entry: R0 == dialogue box event code ; R1-R7 == depend on the event ; R9 == dialogue box handle ; R10 == diagram handle ; ; On exit: -- ; ; Use: Handles events for the scale dialogue box. drawX__scHnd ROUT ; --- Dispatch interesting events --- CMP R0,#arrow_event ;Is it an arrow click? BEQ %10drawX__scHnd ;Yes -- handle it then CMP R0,#dbEvent_OK ;Is it an OK click? CMPNE R0,#scale__ok BEQ %30drawX__scHnd ;Yes -- handle it then CMP R0,#scale__toScreen ;Is it the to screen button? BEQ %50drawX__scHnd ;Yes -- handle it then CMP R0,#scale__toWindow ;Is it the to window button? BEQ %60drawX__scHnd ;Yes -- handle it then CMP R0,#dbEvent_close ;Is it a close event? BEQ %90drawX__scHnd ;Yes -- kill the dbox CMP R0,#dbEvent_help ;Is it a help event? BEQ %95drawX__scHnd ;Yes -- give the user help ; --- It must be one of the standard scale buttons --- STMFD R13!,{R0-R2,R14} ;Save some registers SUBS R1,R0,#scale__buttons ;Get the first one's handle CMP R1,#8 ;Is it in range? LDMCSFD R13!,{R0-R2,PC}^ ;No -- return then ADR R2,drawX__stdScale ;Point to the table LDR R2,[R2,R1,LSL #2] ;Load the correct one MOV R1,R0 ;Get the actual icon handle MOV R0,R9 ;Get the dialogue box BL dbox_slab ;Slab the button in nicely MOV R1,#scale__write ;Find the writable icon BL numWrite_set ;And fill it in nicely BL dbox_unslab ;Unslab the button now LDMFD R13!,{R0-R2,PC}^ ;Return to caller drawX__stdScale DCD 33,50,66,80,100,120,200,400 ; --- Handle an arrow click --- 10drawX__scHnd STMFD R13!,{R0-R2,R14} ;Save some registers MOV R1,#scale__write ;Find the writable icon MOV R0,R9 ;Get the dialogue box BL numWrite_bump ;Bump the writable icon LDMFD R13!,{R0-R2,PC}^ ;Return to caller ; --- Handle an OK click --- 30drawX__scHnd STMFD R13!,{R0-R2,R14} ;Save some registers MOV R0,R9 ;Get the dialogue box MOV R1,#scale__ok ;Find the OK button BL dbox_slab ;Slab the button nicely MOV R1,#scale__write ;Find the writable icon BL numWrite_read ;Read the icon value CMP R2,#1 ;Is the value too small? MOVLT R2,#1 ;Yes -- force it bigger MOV R0,R2,LSL #16 ;Scale the value up ADD R0,R0,#50 ;Make it round to nearest BL div10 ;Divide by 10 quickly BL div10 ;Divide by 10 again (/100) STR R0,[R10,#dWin__scale] ;This is the new scale BL drawX__doScale ;Set the scale nicely LDR R14,[R13,#4] ;Load the button status CMP R14,#1 ;Is this an Adjust click? MOVNE R0,R9 ;Not Adjust -- get dbox BLNE dbox_close ;Close the window BL dbox_unslab ;Unslab the icon BLNE dbox_destroy ;And destroy the dbox LDMFD R13!,{R0-R2,PC}^ ;Return to caller ; --- Scale the diagram to the screen --- 50drawX__scHnd STMFD R13!,{R0-R5,R14} ;Save some registers MOV R1,R0 ;Get the icon handle MOV R0,R9 ;Get the dialogue box BL dbox_slab ;Slab the button BL screen_getInfo ;Get the screen information ADD R14,R0,#screen_width ;Find the screen sizes LDMIA R14,{R0,R1} ;Load them out SUB R0,R0,#44 ;Lose the scroll bar width SUB R1,R1,#88 ;And the titlebar height B %70drawX__scHnd ;Do the scaling stuff ; --- Scale the diagram to the window --- 60drawX__scHnd STMFD R13!,{R0-R5,R14} ;Save some registers MOV R1,R0 ;Get the icon handle MOV R0,R9 ;Get the dialogue box BL dbox_slab ;Slab the button LDR R14,[R10,#dWin__window] ;Load the window handle STR R14,[R11,#0] ;Save it in the scratchpad MOV R1,R11 ;Point at it there SWI Wimp_GetWindowState ;Find the window's info LDMIB R11,{R0-R3} ;Load all the coordinates SUB R0,R2,R0 ;Get the window width SUB R1,R3,R1 ;Get the window height ; --- Scale the diagram to fit in R0,R1 --- 70drawX__scHnd LDR R14,[R10,#dWin__diagram] ;Find the diagram ADD R14,R14,#24 ;Find the bounding box LDMIA R14,{R2-R5} ;Load the coordinates out SUB R4,R4,R2 ;Get the diagram width SUB R5,R5,R3 ;And the height SUB R0,R0,#32 ;Compensate for the clearance SUB R1,R1,#32 ;On all four edges MOV R0,R0,LSL #16 ;Scale the target sizes up MOV R3,R1,LSL #16 MOV R1,R4 ;Get the original width BL div_round ;Get the x scale factor MOV R2,R0,LSL #8 ;Look after this value MOV R0,R3 ;Get the y target size MOV R1,R5 ;And the original height BL div_round ;Get the y scale factor CMP R2,R0,LSL #8 ;Which one's smaller? MOVGT R2,R0,LSL #8 ;Take that one STR R2,[R10,#dWin__scale] ;This is the new scale BL drawX__doScale ;Do everything nicely LDR R14,[R13,#4] ;Load the button status CMP R14,#1 ;Is this an Adjust click? BLEQ drawX__fillScale ;Yes -- reset writable area MOVNE R0,R9 ;Not Adjust -- get dbox BLNE dbox_close ;Close the window BL dbox_unslab ;Unslab the icon BLNE dbox_destroy ;And destroy the dbox LDMFD R13!,{R0-R5,PC}^ ;Return to caller ; --- Close the dialogue box --- 90drawX__scHnd STMFD R13!,{R0,R14} ;Save some registers MOV R0,R9 ;Get the dialogue handle BL dbox_destroy ;Destroy the dialogue box LDMFD R13!,{R0,PC}^ ;Return to caller ; --- Get some help on the dialogue --- 95drawX__scHnd STMFD R13!,{R0-R2,R14} ;Save some registers ADR R0,drawX__scHlpMsg ;Point to the help message BL msgs_lookup ;Translate it nicely BL help_add ;Add it into the message SUB R14,R1,#scale__buttons ;Subtract the buttons base CMP R14,#8 ;Is it in range? BCS %96drawX__scHnd ;No -- skip to the end MOV R0,R9 ;Get the dialogue handle BL dbox_getField ;Read the icon text ADR R0,drawX__scButMsg ;Point to the help text BL msgs_lookup ;Translate the message MOV R1,R11 ;Build it in the scratchpad BL str_subst ;Build the string up BL help_add ;Add this to the help message 96drawX__scHnd BL dbox_help ;Get icon-specific stuff LDMFD R13!,{R0-R2,PC}^ ;Return to caller drawX__scHlpMsg DCB "drxhSCALE",0 drawX__scButMsg DCB "drxhSCBUT",0 LTORG ; --- drawX__doScale --- ; ; On entry: R10 == diagram handle ; ; On exit: -- ; ; Use: Sets the diagram scale. The tricky bit is ensuring that ; the bit the user was looking at is still vaguely visible. ; We assume that he's looking at the centre of the window and ; do our best to keep that in the centre of the scaled view. drawX__doScale ROUT STMFD R13!,{R0-R7,R14} ;Save some registers ; --- Work out where the user's looking --- LDR R14,[R10,#dWin__window] ;Load the diagram window SUB R13,R13,#36 ;Make space for a window blk STR R14,[R13,#0] ;Save it in the block MOV R1,R13 ;Point to it there SWI Wimp_GetWindowState ;Read its current position LDMIB R13,{R0-R5} ;Load all that lot out SUB R6,R2,R0 ;Get the window width ADD R4,R4,R6,ASR #1 ;Find the horizontal centre SUB R7,R3,R1 ;Get the window height SUB R5,R5,R7,ASR #1 ;Find the vertical centre ; --- Find where that is, relatively --- ADD R14,R10,#dWin__extent ;Find the window extent LDMIA R14,{R0-R3} ;Load that lot out ADD R0,R0,#16 ;Compensate for the border ADD R1,R1,#16 SUB R2,R2,#16 SUB R3,R3,#16 SUB R4,R4,R0 ;Get pos rel. to wind left SUB R5,R5,R1 ;Get pos rel. to wind bottom SUB R2,R2,R0 ;Get window extent width SUB R3,R3,R1 ;Get window extent height MOV R0,R4,LSL #16 ;Scale up horizontal pos MOV R1,R2 ;Get extent width BL div_round ;Find the proportion nicely MOV R4,R0 ;Look after it MOV R0,R5,LSL #16 ;Scale up vertical pos MOV R1,R3 ;Get extent height BL div_round ;Find the proportion nicely MOV R5,R0 ;Look after that too ; --- Reset the extent and redo the scroll stuff --- BL drawX__setExtent ;Set the new extent ADD R14,R10,#dWin__extent ;Find the new window extent LDMIA R14,{R0-R3} ;Load that lot out ADD R0,R0,#16 ;Compensate for the border ADD R1,R1,#16 SUB R2,R2,#16 SUB R3,R3,#16 SUB R2,R2,R0 ;Get the new extent width SUB R3,R3,R1 ;Get the new extent height MUL R2,R4,R2 ;Work out the new relative MUL R3,R5,R3 ;scroll positions ADD R4,R0,R2,ASR #16 ;And convert them to ADD R5,R1,R3,ASR #16 ;absolute ones SUB R4,R4,R6,ASR #1 ;And uncentre them ADD R5,R5,R7,ASR #1 ; ; --- Scroll the window nicely --- ADD R14,R13,#20 ;Point to the scroll offsets STMIA R14,{R4,R5} ;Save them in there MOV R1,R13 ;Point to the block SWI Wimp_OpenWindow ;Open the window ADD R13,R13,#36 ;Reclaim the stack space ; --- Redraw the window --- LDR R0,[R10,#dWin__window] ;Load the window handle ADD R14,R10,#dWin__extent ;Find the window extent LDMIA R14,{R1-R4} ;Load the coordinates out SWI Wimp_ForceRedraw ;Redraw the whole view LDMFD R13!,{R0-R7,PC}^ ;Return to caller LTORG ; --- drawX__setExtent --- ; ; On entry: R10 == a diagram handle ; ; On exit: -- ; ; Use: Resets the diagram window's extent so that the diagram ; fits inside it at its current scale. drawX__setExtent ROUT STMFD R13!,{R0-R4,R14} ;Save some registers LDR R14,[R10,#dWin__diagram] ;Find the diagram address ADD R14,R14,#24 ;Point to the bounding box LDMIA R14,{R1-R4} ;Load them out nicely LDR R0,[R10,#dWin__scale] ;Load the scale factor MOV R0,R0,LSR #8 ;Scale that down a bit MUL R1,R0,R1 ;Scale up all the positions MUL R2,R0,R2 MUL R3,R0,R3 MUL R4,R0,R4 MOV R14,#16 ;Add a gap round the edge RSB R1,R14,R1,ASR #16 ;And scale them back down RSB R2,R14,R2,ASR #16 ADD R3,R14,R3,ASR #16 ADD R4,R14,R4,ASR #16 ADD R14,R10,#dWin__extent ;Point to the extent block STMIA R14,{R1-R4} ;Save them away there LDR R0,[R10,#dWin__window] ;Load the window handle ADD R1,R10,#dWin__extent ;Point to the coordinates SWI Wimp_SetExtent ;Set the new extent LDMFD R13!,{R0-R4,PC}^ ;Return to caller LTORG ; --- drawX__refresh --- ; ; On entry: R10 == diagram handle ; ; On exit: -- ; ; Use: Refreshes a diagram after changing its extent drawX__refresh ROUT STMFD R13!,{R0-R4,R14} LDR R0,[R10,#dWin__window] ;Load the window handle STR R0,[R11,#0] ;Save it in the scratchpad MOV R1,R11 ;Point to it there SWI Wimp_GetWindowState ;Get the window's position SWI Wimp_OpenWindow ;Open the window there LDR R0,[R10,#dWin__window] ;Load the window handle ADD R14,R10,#dWin__extent ;Find the window's extent LDMIA R14,{R1-R4} ;Load the coordinates SWI Wimp_ForceRedraw ;And clear the window LDMFD R13!,{R0-R4,PC}^ ;Return to caller LTORG ;----- The main window handler ---------------------------------------------- ; --- drawX__newDiag --- ; ; On entry: R0 == pointer to filename, or 0 for none ; ; On exit: VC and R10 == pointer to a pristine new diagram structure, or ; VS and R0 == pointer to error, and R10 corrupted ; ; Use: Creates a new diagram block and window, and opens it on ; the screen. drawX__newDiag ROUT STMFD R13!,{R0-R3,R14} ;Save some registers ; --- Allocate a block of memory for the diagram --- MOV R0,#dWin__size ;Get the size of the block BL alloc ;Try to get the memory BLCS alloc_error ;If no memory, get error BCS %99drawX__newDiag ;And tidy everything up MOV R10,R0 ;Look after the block handle ; --- Fill in the block and set things up --- MOV R14,#0 ;No diagram currently STR R14,[R10,#dWin__diagram] ;So clear the diagram LDR R0,drawX__prefs+dPref__defScale MOV R0,R0,LSL #16 ;Scale it up ADD R0,R0,#50 ;Round to nearest BL div10 ;And divide by 10 BL div10 ;And again -- now in 16.16 STR R0,[R10,#dWin__scale] ;And save that too MOV R0,#0 ;Left hand side MOV R1,#0 ;Bottom edge MOV R2,#640 ;Right hand side MOV R3,#512 ;Top edge ADD R14,R10,#dWin__extent ;Point to the extent block STMIA R14,{R0-R3} ;Save the initial extent MOV R3,#0 ;No flags currently ; --- Work out the file's name --- LDR R0,[R13,#0] ;Load the filename pointer CMP R0,#0 ;Is it defined properly? ORRNE R3,R3,#dwFlag__loaded ;Yes -- say the file's loaded ADREQ R0,drawX__untitled ;No -- point to default BLEQ msgs_lookup ;And translate the message MOV R1,R0 ;This is the source string ADD R0,R10,#dWin__filename ;Point to filename buffer BL str_cpy ;Copy it in there nicely STR R3,[R10,#dWin__flags] ;Save the flags word away ; --- Now create a new window --- MOV R0,R11 ;Point at the scratchpad ADR R1,drawX__winDef ;Point at the window def MOV R2,#drawX__winSize ;Get the size of the window BL fastMove ;Copy it to the scratchpad LDMIB R11,{R0-R2} ;Load top and bottom y SUB R0,R2,R0 ;Get height in R0 LDR R2,drawX__winY ;Get current cascade coord SUB R0,R2,R0 ;Work out correct bottom STMIB R11,{R0-R2} ;Store back in the scratchpad ADD R14,R10,#dWin__titleBar ;Point to the title buffer STR R14,[R11,#72] ;Save this as buffer pointer MOV R1,R11 ;Point to the scratchpad SWI XWimp_CreateWindow ;Try to create the window BVS %98drawX__newDiag ;If it failed, tidy up STR R0,[R10,#dWin__window] ;Save the window handle ; --- Register the window's event handler --- ADR R1,drawX__winHnd ;Point to the handler MOV R2,R10 ;Pass diagram block in R10 MOV R3,R12 ;And workspace in R12 BL win_eventHandler ;Register the event handler BVS %97drawX__newDiag ;If it failed, tidy up LDMFD R13!,{R0-R3,R14} ;Restore all the registers BICS PC,R14,#V_flag ;And return with V clear ; --- Various things went wrong --- 97 MOV R3,R0 ;Look after error pointer ADD R1,R10,#dWin__window ;Point at the window handle SWI Wimp_DeleteWindow ;Don't want it any more MOV R0,R3 ;Restore the error pointer 98 MOV R3,R0 ;Look after error pointer MOV R0,R10 ;Point at my diagram block BL free ;Don't want that any more MOV R0,R3 ;Restore the error pointer 99 ADD R2,R0,#4 ;Point at the error text ADR R0,drawX__newErr ;Point to error message BL msgs_error ;Do clever things with it ADD R13,R13,#4 ;Don't restore R0 on exit LDMFD R13!,{R1-R3,R14} ;Unstack all the registers ORRS PC,R14,#V_flag ;And return with V set drawX__newErr DCD 1 DCB "drxNEWERR",0 drawX__untitled DCB "drxUNT",0 drawX__winDef DCD 320,0,960,512,0,0,-1 ;Initial window position DCD &ff000002 ;All gadgets, moveable DCB 7,2,7,0,3,1,12,0 ;Normal window colours DCD 0,0,640,512 ;Initial work area size DCD &00000139 ;Indirect the title text DCD (7<<12) ;Respond to click and drag DCD 1 ;Use Wimp sprite area FWIW DCW 1,0 ;Allow title bar hiding DCD 0,-1,256 ;Title bar indirection stuff DCD 0 ;No icons defined drawX__winSize EQU {PC}-drawX__winDef ;Size of the window block LTORG ; --- drawX__winHnd --- ; ; On entry: R0 == event code ; R1 == pointer to event data ; R10 == diagram handle ; ; On exit: CS if I handled the event, CC otherwise ; ; Use: Handles events directed at a diagram window. drawX__winHnd ROUT CMP R0,#19 ;Do I recognise the event? ADDCC PC,PC,R0,LSL #2 ;Yes -- dispatch it then MOVS PC,R14 ;Otherwise ignore it MOVS PC,R14 ;NullReasonCode B drawX__redraw ;RedrawWindowRequest MOVS PC,R14 ;OpenWindowRequest B drawX__killDiag ;CloseWindowRequest B drawX__ptrLeave ;PointerLeavingWindow B drawX__ptrEnter ;PointerEnteringWindow B drawX__click ;MouseClicked MOVS PC,R14 ;UserDragBox MOVS PC,R14 ;KeyPressed MOVS PC,R14 ;MenuSelection MOVS PC,R14 ;ScrollRequest MOVS PC,R14 ;LoseCaret MOVS PC,R14 ;GainCaret MOVS PC,R14 ;PollWordNonZero MOVS PC,R14 ;UndefinedEvent_14 MOVS PC,R14 ;UndefinedEvent_15 MOVS PC,R14 ;UndefinedEvent_16 B drawX__message ;UserMessage B drawX__message ;UserMessageRecorded LTORG ; --- drawX__killDiag --- ; ; On entry: R10 == diagram handle ; ; On exit: CS ; ; Use: Destroys a diagram. drawX__killDiag ROUT STMFD R13!,{R0-R3,R14} ;Save some registers ; --- Kill the diagram itself, if it exists --- LDR R0,[R10,#dWin__diagram] ;Load the diagram anchor CMP R0,#0 ;Is it a sensible value? ADDNE R0,R10,#dWin__diagram ;Yes -- point to it then BLNE flex_free ;And free the memory it used ; --- Destroy the diagram's window --- LDR R0,[R10,#dWin__window] ;Get the window handle ADR R1,drawX__winHnd ;Point to the handler MOV R2,R10 ;Pass diagram block in R10 MOV R3,R12 ;And workspace in R12 BL win_removeEventHandler ;Remove my event handler ADD R1,R10,#dWin__window ;Point to the window handle SWI Wimp_DeleteWindow ;Destroy the window ; --- Destroy the diagram anchor block --- MOV R0,R10 ;Point at the diagram block BL free ;Destroy it LDMFD R13!,{R0-R3,R14} ;Return to caller ORRS PC,R14,#C_flag LTORG ; --- drawX__ptrEnter --- ; ; On entry: R10 == diagram handle ; ; On exit: -- ; ; Use: Makes the mouse pointer turn into a magnifying glass over ; a diagram window. drawX__ptrEnter ROUT STMFD R13!,{R0-R2,R14} ;Save some regisers LDR R14,drawX__flags ;Load the flags word ORR R14,R14,#dxFlag__ownPtr ;We own the pointer now STR R14,drawX__flags ;Store the flags back LDR R14,[R10,#dWin__diagram] ;Load the diagram pointer CMP R14,#0 ;Is it defined? ADRNE R0,drawX__ptrName ;Yes -- point to the name MOVNE R1,#12 ;Get the hot x position MOVNE R2,#6 ;And the hot y position BLNE ptr_setShape ;And set the pointer position LDMFD R13!,{R0-R2,PC}^ ;Return to caller drawX__ptrName DCB "ptr_zoom",0 LTORG ; --- drawX__ptrLeave --- ; ; On entry: -- ; ; On exit: -- ; ; Use: Makes the pointer look normal again when it leaves a ; diagram window. drawX__ptrLeave ROUT STMFD R13!,{R14} ;Save link register LDR R14,drawX__flags ;Load the flags word BIC R14,R14,#dxFlag__ownPtr ;Don't own pointer any more STR R14,drawX__flags ;Save the flags back TST R14,#dxFlag__drag ;Are we dragging? BLEQ ptr_resetShape ;No -- remove the pointer LDMFD R13!,{PC}^ ;And return to caller LTORG ; --- drawX__redraw --- ; ; On entry: R1 == pointer to a redraw block ; R10 == diagram handle ; ; On exit: -- ; ; Use: Redraws a diagram window. drawX__redraw ROUT STMFD R13!,{R0-R3,R14} ;Save some registers SWI Wimp_RedrawWindow ;Start the redraw operation CMP R0,#0 ;Is there anything to do? BEQ %90drawX__redraw ;No -- skip to the end ; --- Do a redraw of a diagram --- 10drawX__redraw LDR R0,[R10,#dWin__scale] ;Load the current scale ADD R14,R10,#dWin__diagram ;Point to the diagram LDMIA R14,{R2,R3} ;Load the address and size CMP R2,#0 ;Is there a diagram at all? BLNE draw_render ;Yes -- then render it BL drag_redraw ;And redraw the drag box SWI Wimp_GetRectangle ;Get another rectangle CMP R0,#0 ;Is there more to do? BNE %10drawX__redraw ;Yes -- do another rectangle ; --- The redraw's over --- 90drawX__redraw LDMFD R13!,{R0-R3,R14} ;Restore registers ORRS PC,R14,#C_flag ;Claim the event ; --- drawX__message --- ; ; On entry: R1 == pointer to a message block ; R10 == diagram handle ; ; On exit: CC or CS, depending on whether I handled it ; ; Use: Handles a message sent to a diagram window. drawX__message ROUT STMFD R13!,{R0,R14} ;Save some registers LDR R14,[R1,#16] ;Load the message type LDR R0,=&502 ;Get the help message code CMP R0,R14 ;Does it match? BEQ %10drawX__message ;Yes -- deal with it then CMP R14,#1 ;Is it a Message_DataSave? CMPNE R14,#3 ;Or a Message_DataLoad? LDMNEFD R13!,{R0,PC}^ ;No -- return to caller LDR R0,[R1,#40] ;Load the filetype word BL drawX__load ;Load the file LDMFD R13!,{R0,PC}^ ;And return to caller 10 ADR R0,drawX__viewHelp ;Point to the message BL msgs_lookup ;Translate it nicely BL help_add ;Add it to the help message LDMFD R13!,{R0,PC}^ ;Return to caller drawX__viewHelp DCB "drxhDIAG",0 LTORG ; --- drawX__open --- ; ; On entry: R10 == diagram handle ; ; On exit: -- ; ; Use: Opens a diagram window on the screen. drawX__open ROUT STMFD R13!,{R0,R1,R14} ;Save some registers LDR R14,[R10,#dWin__window] ;Get the window handle STR R14,[R11,#0] ;Save it in the scratchpad MOV R1,R11 ;Point at it nicely SWI Wimp_GetWindowState ;Find its current position MOV R14,#-1 ;Bring it to the top STR R14,[R11,#28] ;Save it in `behind' word SWI Wimp_OpenWindow ;And open the new window LDMFD R13!,{R0,R1,PC}^ ;Return to caller LTORG ; --- drawX__click --- ; ; On entry: R1 == pointer to mouse click block ; R10 == diagram handle ; ; On exit: -- ; ; Use: Handles mouse clicks on a diagram. drawX__click ROUT STMFD R13!,{R0-R5,R14} ;Save some registers LDR R14,[R1,#8] ;Load the button type TST R14,#&02 ;Is it a menu click? BNE %70drawX__click ;Yes -- handle it then LDR R3,[R10,#dWin__diagram] ;Load the diagram pointer CMP R3,#0 ;Is it valid? TSTNE R14,#&50 ;Yes -- some kind of drag? BEQ %90drawX__click ;No -- ignore it then ; --- Start a drag operation --- LDR R0,[R10,#dWin__window] ;Load the window handle MOV R1,#0 ;Give me update events ADR R2,drawX__dragHandler ;Point to handler routine MOV R3,#0 ;No magic number MOV R4,R10 ;Pass diagram handle in R10 MOV R5,R12 ;Pass workspace in R12 BL drag_start ;Start the drag operation LDR R14,drawX__flags ;Load the flags word ORR R14,R14,#dxFlag__drag ;We're now dragging something STR R14,drawX__flags ;Save the flags back B %90drawX__click ;And return to caller ; --- Handle a Menu click on the window --- 70drawX__click ADR R0,drawX__mainMenu ;Point to the menu definition ADR R1,drawX__mmHnd ;Point to the handler MOV R2,R10 ;Pass diagram handle in R10 MOV R3,R12 ;Pass workspace in R12 BL menu_create ;Create the menu nicely 90drawX__click LDMFD R13!,{R0-R5,PC}^ ;Return to caller drawX__mainMenu MENU "DrawX" ITEM "drxMMINFO" ISHADE dWin__flags,dwFlag__hasDiag SUBWARN NOWARN ITEM "drxMMSAVE" ISHADE dWin__flags,dwFlag__hasDiag SUBWARN NOWARN ITEM "drxMMSCALE" ISHADE dWin__flags,dwFlag__hasDiag SUBWARN NOWARN MENUEND LTORG ; --- drawX__dragHandler --- ; ; On entry: R0 == event code ; R10 == diagram handle ; ; On exit: -- ; ; Use: Handles a drag box. drawX__dragHandler ROUT CMP R0,#7 ;Is it in range? ADDCC PC,PC,R0,LSL #2 ;Yes -- dispatch MOVS PC,R14 ;Otherwise ignore it B drawX__redrawDragBox B drawX__redrawDragBox B drawX__redrawDragBox MOVS PC,R14 B drawX__dragScroll B drawX__dragDone B drawX__dragCancel LTORG ; --- drawX__dragScroll --- ; ; On entry: R1 == pointer to window state ; ; On exit: -- ; ; Use: Scrolls the window during the drag. drawX__dragScroll ROUT STMFD R13!,{R0-R3,R14} ;Save some registers BL drag_scroll ;Read the scroll position STMIA R14,{R2,R3} ;Save the new scroll position SWI Wimp_OpenWindow ;Do the open operation LDMFD R13!,{R0-R3,PC}^ ;And return to caller LTORG ; --- drawX__unknowns --- ; ; On entry: R0 == event code ; R1 == pointer to event data ; ; On exit: CS if I handled it, CC if I didn't ; ; Use: Handles unrecognised events. drawX__unknowns ROUT CMP R0,#17 ;Is it a UserMessage? CMPNE R0,#18 ;Or a UserMessageRecorded? MOVNES PC,R14 ;No -- ignore it then ; --- Handle messages --- STMFD R13!,{R14} ;Save a register LDR R14,[R1,#16] ;Load the message action CMP R14,#5 ;Is it Message_DataOpen? LDMNEFD R13!,{PC}^ ;No -- ignore it then STMFD R13!,{R1,R10} ;Save another register LDR R0,[R1,#40] ;Load the filetype MOV R10,#0 ;I don't have a diagram yet BL drawX__load ;Load a new diagram LDMFD R13!,{R1,R10,R14} ;Unstack the resulting regs ORRCSS PC,R14,#C_flag ;If it loaded, set C flag BICCCS PC,R14,#C_flag ;Otherwise clear it LTORG ; --- drawX__dragCancel --- ; ; On entry: -- ; ; On exit: -- ; ; Use: Cancels the drag. drawX__dragCancel ROUT STMFD R13!,{R14} ;Save a register LDR R14,drawX__flags ;Load the current flags BIC R14,R14,#dxFlag__drag ;Clear the dragging flag STR R14,drawX__flags ;Save the flags back again TST R14,#dxFlag__ownPtr ;Do we own the pointer? BLEQ ptr_resetShape ;No -- clear the shape then LDMFD R13!,{PC}^ ;Return to caller LTORG ; --- drawX__dragDone --- ; ; On entry: R1 == pointer to window state ; R2,R3 == drag start position ; R4,R5 == drag end position ; ; On exit: -- ; ; Use: Handles the end of a drag operation. drawX__dragDone ROUT STMFD R13!,{R0-R7,R14} ;Save some registers BL drawX__dragCancel ;Cancel the drag ; --- Now read the drag values --- ADD R14,R13,#8 ;Point to arguments on stack LDMIA R14,{R4-R7} ;Move them to different regs CMP R4,R6 ;Make sure they're the right EORGT R4,R4,R6 ;... way round EORGT R6,R4,R6 EORGT R4,R4,R6 CMP R5,R7 EORGT R5,R5,R7 EORGT R7,R5,R7 EORGT R5,R5,R7 ; --- Get the window sizes --- LDMIB R1,{R0-R3} ;Load the coordinates SUB R2,R2,R0 ;Get the window width SUB R3,R3,R1 ;And the window height ; --- Work out the new scale factor --- SUBS R1,R6,R4 ;Get the drag box width BEQ %90drawX__dragDone ;If it's bad, return now ADD R4,R4,R1,LSR #1 ;Find the box's centre MOV R0,R2,LSL #16 ;And the window width MOV R6,R2,LSR #1 ;Look after the width BL div_round ;Do the division MOV R2,R0 ;Look after the quotient SUBS R1,R7,R5 ;Get the drag box height BEQ %90drawX__dragDone ;If it's bad, return now ADD R5,R5,R1,LSR #1 ;Find the box's centre MOV R0,R3,LSL #16 ;And the window height BL div_round ;Do the division MOV R3,R3,LSR #1 ;Halve the height CMP R2,R0 ;Which one's smaller? MOVGT R2,R0 ;Use that one then LDR R7,[R10,#dWin__scale] ;Load the current scale MOV R1,R7,LSR #8 ;Divide it down a bit MOV R2,R2,LSR #8 ;And divide the new one MUL R0,R2,R1 ;Multiply them up CMP R0,#&300 ;Is it smaller than 1%? MOVLT R0,#&300 ;Yes -- force it to 1% CMP R0,#&80000 ;Is it bigger than 800%? MOVGT R0,#&80000 ;Yes - force it to 800% STR R0,[R10,#dWin__scale] ;Save the new scale factor BL drawX__setExtent ;Set the new window extent MOV R0,R0,LSL #8 ;Scale up the new factor MOV R1,R7 ;Get the old scale factor BL div_round ;Get the scale difference ; --- Set the new scroll positions --- LDR R1,[R13,#4] ;Find the window state MUL R4,R0,R4 ;Multiply left drag box side MUL R5,R0,R5 ;And the top edge RSB R4,R6,R4,ASR #8 ;Scale them down a bit ADD R5,R3,R5,ASR #8 ;Scale them down a bit ADD R14,R1,#20 ;Point to the scroll pos STMIA R14,{R4,R5} ;Save the new ones in there SWI Wimp_OpenWindow ;Open the window nicely ; --- Now redraw the window --- LDR R0,[R10,#dWin__window] ;Load the window handle ADD R14,R10,#dWin__extent ;Find the new extents LDMIA R14,{R1-R4} ;Load them out nicely SWI Wimp_ForceRedraw ;Redraw that lot nicely 90 LDMFD R13!,{R0-R7,PC}^ ;Return to caller LTORG ; --- drawX__mmHnd --- ; ; On entry: R0 == menu event code ; R1 == item number ; R10 == diagram handle ; ; On exit: -- ; ; Use: Handles events for the main diagram menu. drawX__mmHnd ROUT CMP R0,#mEvent_help ;Does the user want help? BEQ %70drawX__mmHnd ;Yes -- give him some CMP R0,#mEvent_subMenu ;Is it a submenu event? CMPNE R0,#mEvent_select ;Or a selection event? MOVNES PC,R14 ;No -- then quit ; --- Handle a menu selection --- CMP R1,#mm__scale ;Is it one I recognise? ADDLS PC,PC,R1,LSL #2 ;Yes -- then deal with it MOVS PC,R14 ;Otherwise ignore it B %10drawX__mmHnd ;Display the info box B drawX__save ;Start a save operation B drawX__scale ;Display the scale dialogue ; --- Display and handle the File info box --- 10drawX__mmHnd STMFD R13!,{R0-R3,R14} ;Save some registers ADR R0,drawX__fInfodb ;Point to the dialogue name BL dbox_create ;Try to create the dialogue BVS %30drawX__mmHnd ;Handle an error if if failed MOV R3,R0 ;Look after the dbox handle ADD R2,R10,#dWin__filename ;Point to the file's name MOV R1,#info__name+(1<<31) ;Get the right icon number BL dbox_setField ;Set the field up nicely LDR R0,[R10,#dWin__diagSize] ;Load the diagram's size MOV R1,R11 ;Point to the scratchpad MOV R2,#256 ;Assume it's nice and big SWI OS_ConvertFileSize ;Make it a nice size string MOV R2,R11 ;Point at the string MOV R0,R3 ;Get the dialogue handle MOV R1,#info__size ;And find the size icon BL dbox_setField ;Set the field up ADR R1,drawX__fInfoHlp ;Point to the help text BL dbox_setClickDrag ;Make dialogue box draggable BL mbox ;Display the dialogue box LDMFD R13!,{R0-R3,PC}^ ;Return to caller ; --- Couldn't create the dialogue --- 30drawX__mmHnd MOV R1,#1 ;Just an OK button please BL errorBox ;Display the error message LDMFD R13!,{R0-R3,PC}^ ;Return to caller drawX__fInfodb DCB "drawInfo",0 drawX__fInfoHlp DCB "drxhFINFO",0 ; --- Handle help requests for the menu --- 70drawX__mmHnd STMFD R13!,{R0,R1,R14} ;Save some registers ADR R0,drawX__mmHlpMsg ;Point to the help string BL menu_help ;Add message to help string LDMFD R13!,{R0,R1,PC}^ ;Return to caller drawX__mmHlpMsg DCB "drxhMM",0 LTORG ; --- drawX__redrawDragBox --- ; ; On entry: R1 == pointer to redraw block ; R2,R3 == start positions ; R4,R5 == end positions ; R6,R7 == window origin ; R10 == diagram handle ; ; On exit: -- ; ; Use: Draws the drag box. drawX__redrawDragBox ROUT STMFD R13!,{R0-R6,R14} ;Save some registers ; --- Set the coordinates up --- MOV R14,R6 ADD R6,R5,R7 ADD R5,R4,R14 ADD R4,R3,R7 ADD R3,R2,R14 ;Convert to screen coords ; --- Set the correct colour --- MOV R0,#0 ;Background colour is white MOV R1,#2 ;Drag box is grey BL drag_eorColour ;Set the EOR colour nicely ; --- Plot the actual rectangle --- MOV R0,#4 ;Move cursor absolute MOV R1,R3 ;Get left hand side MOV R2,R4 ;And bottom corner SWI OS_Plot ;And plot the first point MOV R0,#21 ;Draw line absolute MOV R1,R5 ;Get right hand side MOV R2,R4 ;And bottom corner SWI OS_Plot ;And plot the bottom edge MOV R0,#53 ;Draw line absolute MOV R1,R5 ;Get right hand side MOV R2,R6 ;And top corner SWI OS_Plot ;And plot the right hand edge MOV R0,#53 ;Draw line absolute MOV R1,R3 ;Get left hand side MOV R2,R6 ;And top corner SWI OS_Plot ;And plot the top edge MOV R0,#61 ;Draw line absolute MOV R1,R3 ;Get left hand side MOV R2,R4 ;And bottom corner SWI OS_Plot ;And plot the right edge 90 LDMFD R13!,{R0-R6,PC}^ ;Return to caller LTORG ; --- drawX__setTitle --- ; ; On entry: R10 == diagram handle ; ; On exit: -- ; ; Use: Updates a diagram window's title from its current state. drawX__setTitle ROUT STMFD R13!,{R0-R2,R14} ;Save some registers ADD R0,R10,#dWin__filename ;Point to the filename ADD R1,R10,#dWin__titleBar ;Point to the title buffer LDR R2,[R10,#dWin__window] ;Load the window handle BL winUtils_setTitle ;Set the window's title LDMFD R13!,{R0-R2,PC}^ ;Return to caller LTORG ; --- drawX__cascade --- ; ; On entry: -- ; ; On exit: -- ; ; Use: Updates the y position for the next diagram window so that ; it produces a pleasing `cascading' effect. drawX__cascade ROUT STMFD R13!,{R14} ;Save a register LDR R14,drawX__winY ;Load the current y position SUB R14,R14,#48 ;Decrement the counter CMP R14,#drawX__bottomY ;Is it within range? MOVLT R14,#drawX__topY ;No -- move it to the top STR R14,drawX__winY ;Save the cascaded position LDMFD R13!,{PC}^ ;And return to caller LTORG ;----- Data transfer -------------------------------------------------------- ; --- drawX__save --- ; ; On entry: R10 == diagram handle to save ; ; On exit: -- ; ; Use: Saves a diagram. drawX__save ROUT STMFD R13!,{R0-R5,R14} ;Save lots of registers LDR R14,[R10,#dWin__flags] ;Get the diagram's flags TST R14,#dwFlag__loaded ;Does it have a nice name? ADREQ R0,drawX__defName ;No -- find one then BLEQ msgs_lookup ;Translate it nicely ADDNE R0,R10,#dWin__filename ;Otherwise use the name MOV R2,R0 ;Put the name in R2 LDR R0,[R10,#dWin__diagSize] ;Load the diagram's size LDR R1,=drawX__filetype ;Get the filetype nicely ADR R3,drawX__saveTbl ;Point to the entry table MOV R4,R10 ;Pass diagram handle in R10 MOV R5,R12 ;Pass workspace in R12 BL saveAs ;Display the dialogue box BVS %90drawX__save ;If it failed, deal with it LDR R14,[R10,#dWin__flags] ;Load the flags word ORR R14,R14,#dwFlag__saving ;This window is saving STR R14,[R10,#dWin__flags] ;Save the flags back LDMFD R13!,{R0-R5,PC}^ ;Return to caller 90drawX__save MOV R1,#1 ;If it failed, report the BL errorBox ;error with just an OK button LDMFD R13!,{R0-R5,PC}^ ;Return to caller drawX__defName DCB "drxDEFN",0 drawX__saveTbl DCB "drxSVTB",0 B drawX__saveOver B drawX__saveFile B drawX__send MOVS PC,R14 B drawX__saveFail ; --- drawX__saveOver --- ; ; On entry: R10 == diagram handle ; ; On exit: -- ; ; Use: Clears the diagram's `saving' flag. drawX__saveOver ROUT STMFD R13!,{R14} ;Save a register LDR R14,[R10,#dWin__flags] ;Load the flags word BIC R14,R14,#dwFlag__saving ;Window not saving any more STR R14,[R10,#dWin__flags] ;Save the flags back LDMFD R13!,{PC}^ ;Return to caller LTORG ; --- drawX__saveFile --- ; ; On entry: R0 == pointer to filename ; R1 == 0 if file is unsafe ; R10 == diagram handle ; ; On exit: May return error ; ; Use: Saves a diagram to a given file. drawX__saveFile ROUT STMFD R13!,{R0-R5,R14} ;Save some registers MOV R2,R0 ;Keep pointer to name CMP R1,#0 ;Is the file safe? ADDNE R1,R10,#dWin__filename ;Find the file's current name BLNE str_icmp ;Do they match? BEQ %10drawX__saveFile ;Either -- don't confirm BL res_exists ;Does the file exist? BCC %10drawX__saveFile ;No -- skip onwards then ; --- Make sure user wants to overwrite file --- ADR R0,drawX__oWrite ;Point to skeleton BL msgs_lookup ;Translate the message MOV R1,R11 ;Build in scratchpad BL str_subst ;Build the warning message ADR R1,drawX__owWarn ;Point to warning block BL warning ;Get a response MOVCC R0,#0 ;If no then abort saving BCC %99drawX__saveFile ;By making a null error 10 MOV R1,R2 ;Get the filename in R1 MOV R0,#10 ;We're saving whole files LDR R2,=drawX__filetype ;Get the filetype number ADD R14,R10,#dWin__diagram ;Find the diagram address LDMIA R14,{R4,R5} ;Load the address and size ADD R5,R4,R5 ;Convert size to limit ptr SWI XOS_File ;Try to save the file BVS %99drawX__saveFile ;If it failed, skip on LDR R14,[R13,#4] ;Get the `safe' flag CMP R14,#0 ;Is the file safe? BEQ %90drawX__saveFile ;No -- skip to the end ADD R0,R10,#dWin__filename ;Point to the filename BL str_cpy ;Copy the new one over LDR R14,[R10,#dWin__flags] ;Load the flags word ORR R14,R14,#dwFlag__loaded ;File has a good name now STR R14,[R10,#dWin__flags] ;Save the flags back BL drawX__setTitle ;Set the window's title 90 LDMFD R13!,{R0-R5,PC}^ ;Return to caller 99 ADD R13,R13,#4 ;Don't restore R0 on exit LDMFD R13!,{R1-R5,R14} ;Restore registers ORRS PC,R14,#V_flag ;Return the error drawX__oWrite DCB "drxCWRT",0 drawX__owWarn BUTTON "drxRPL" BCANCEL BUTEND LTORG ; --- drawX__send --- ; ; On entry: R10 == diagram handle ; ; On exit: R0 == pointer to diagram ; R1 == size of diagram ; CS ; ; Use: Returns the diagram block so it can be sent to another ; application. drawX__send ROUT ADD R0,R10,#dWin__diagram ;Point to the diagram info LDMIA R0,{R0,R1} ;Load the address and size ORRS PC,R14,#C_flag ;No more data to send LTORG ; --- drawX__saveFail --- ; ; On entry: R0 == pointer to an error, or 0 ; R1 == 1 ; ; On exit: -- ; ; Use: Reports an error during a save attempt. drawX__saveFail ROUT CMP R0,#0 ;Is there an error MOVEQS PC,R14 ;No -- return now then STMFD R13!,{R0-R2,R14} ;Save some registers ADD R2,R0,#4 ;Point to error text ADR R0,drawX__badSave ;Point to the message BL msgs_error ;Translate it nicely MOV R1,#1 ;Set up the button count BL errorBox ;Report the error LDMFD R13!,{R0-R2,PC}^ ;Return to caller drawX__badSave DCD 1 DCB "drxESF",0 LTORG ; --- drawX__load --- ; ; On entry: R0 == filetype of data to send ; R10 == diagram handle, or 0 to create a new one ; ; On exit: CS if it was handled, CC otherwise ; ; Use: Loads a drawfile into a specified diagram, or into a newly ; created one. drawX__load ROUT STMFD R13!,{R0-R2,R14} ;Save some registers LDR R14,=drawX__filetype ;Get the drawfile filetype CMP R0,R14 ;Do they match properly? BNE %90drawX__load ;No -- return then ; --- Disallow save from a window to itself --- CMP R10,#0 ;Is there a diagram? LDRNE R14,[R10,#dWin__flags] ;Load the diagram's flags TSTNE R14,#dwFlag__saving ;Is it currently saving? BNE %80drawX__load ;Yes -- disallow this then ; --- Start a load operation --- ADR R0,drawX__loadTbl ;Point to the entry table MOV R1,R10 ;Pass on the diagram handle MOV R2,R12 ;And my workspace pointer BL load ;Start the load operation LDMFD R13!,{R0-R2,R14} ;Unstack registers ORRS PC,R14,#C_flag ;And say we handled it ; --- Report an error about saving --- 80drawX__load ADR R0,drawX__badLoad ;Point to the error block BL msgs_error ;Translate the message MOV R1,#1 ;Only have an OK button BL errorBox ;Report the error 90drawX__load LDMFD R13!,{R0-R2,R14} ;Unstack registers BICS PC,R14,#C_flag ;And don't claim the event drawX__loadTbl B drawX__newBuf B load_killBuf B load_extendBuf B drawX__doneBuf B drawX__loadFile B drawX__loaded B drawX__loadFail drawX__badLoad DCD 1 DCB "drxCSII",0 LTORG ; --- drawX__loadNew --- ; ; On entry: R0 == pointer to name to create new diagram with ; ; On exit: VC and R10 == pointer to diagram, or VS and R0 == pointer ; to error ; ; Use: Creates a new diagram for a drawfile to be loaded into. drawX__loadNew ROUT STMFD R13!,{R0-R3,R14} ;Save some registers BL drawX__newDiag ;Create a new diagram BVS %99drawX__loadNew ;Handle an error from that LDR R14,[R10,#dWin__flags] ;Load the current flags ORR R14,R14,#dwFlag__tent ;Remember it's tentative STR R14,[R10,#dWin__flags] ;Save the flags back again LDMFD R13!,{R0-R3,R14} ;Restore registers BICS PC,R14,#V_flag ;And return with V clear 99 ADD R13,R13,#4 ;Don't restore R0 on exit LDMFD R13!,{R1-R3,R14} ;Restore registers ORRS PC,R14,#V_flag ;And return with V set LTORG ; --- drawX__killOld --- ; ; On entry: R10 == diagram handle ; ; On exit: -- ; ; Use: Removes the current drawfile being showin in the diagram. drawX__killOld ROUT STMFD R13!,{R0,R14} ;Save some registers LDR R0,[R10,#dWin__diagram] ;Load the diagram anchor CMP R0,#0 ;Does it actually exist? ADDNE R0,R10,#dWin__diagram ;Yes -- point at the anchor BLNE flex_free ;And free the block MOVNE R14,#0 ;Zero it out nicely STRNE R14,[R10,#dWin__diagram] ;Save the new anchor ptr LDMFD R13!,{R0,PC}^ ;Return to caller LTORG ; --- drawX__newBuf --- ; ; On entry: R0 == pointer to leafname of file ; R1 == estimated size of file ; R10 == diagram handle, or 0 to create a new one ; ; On exit: If all went well, VC and ; R0 == pointer to load buffer ; R1 == size of load buffer ; R2 == pointer to flex anchor ; R10 == diagram handle ; Otherwise, VS, R0 == pointer to error, and R1, R2 corrupted ; ; Use: Creates a load buffer for loading a new diagram. drawX__newBuf ROUT STMFD R13!,{R14} ;Save the link register CMP R10,#0 ;Is there a diagram? BLEQ drawX__loadNew ;No -- get one then BLNE drawX__killOld ;Yes -- destroy the old one ADDVC R2,R10,#dWin__diagram ;If OK, point to anchor BLVC load_initBuf ;And find a new buffer LDMFD R13!,{PC} ;Return to caller LTORG ; --- drawX__doneBuf --- ; ; On entry: R0 == pointer to diagram name ; R1 == actual size of diagram ; R2 == pointer to diagram flex anchor ; R10 == diagram handle ; ; On exit: -- ; ; Use: Wraps up a successful RAM receive of a draw file. drawX__doneBuf ROUT STR R1,[R10,#dWin__diagSize] ;Save the diagram size B load_doneBuf ;And set the flex block up LTORG ; --- drawX__loadFile --- ; ; On entry: R0 == pointer to leafname of file to load ; R1 == pointer to filename to read ; R10 == diagram handle, or 0 to create a new one ; ; On exit: If all went well, VC and R10 == diagram handle ; Otherwise, VS, R0 == pointer to error ; ; Use: Loads a diagram from a file. drawX__loadFile STMFD R13!,{R0-R2,R14} ;Save some registers CMP R10,#0 ;Is there a diagram? BLEQ drawX__loadNew ;No -- get one then BLNE drawX__killOld ;Yes -- destroy the old one MOVVS R10,#0 ;If no diagram, clear R10 ADDVC R2,R10,#dWin__diagram ;If OK, point to anchor BLVC load_file ;And load the diagram STRVC R0,[R10,#dWin__diagSize] ;Save the diagram size STRVS R0,[R13,#0] ;Otherwise return error LDMFD R13!,{R0-R2,PC} ;Return to caller LTORG ; --- drawX__loaded --- ; ; On entry: R10 == diagram handle ; ; On exit: -- ; ; Use: Completes loading of a diagram. drawX__loaded ROUT STMFD R13!,{R0,R1,R14} ;Save lots of registers LDR R0,[R10,#dWin__diagram] ;Find the diagram address BL draw_checkValid ;Make sure it's kosher MOVVS R1,#1 ;If not, set R1 == 1 BLVS drawX__loadFail ;And kill off the diagram BVS %90drawX__loaded ;And return ; --- Set everything up for the new diagram --- BL drawX__setExtent ;Set the extents BL drawX__refresh ;Refresh the window contents BL drawX__setTitle ;Set the title string LDR R14,[R10,#dWin__flags] ;Load the diagram flags TST R14,#dwFlag__tent ;Was it tentative? BICNE R14,R14,#dwFlag__tent ;Diagram not tentative now ORR R14,R14,#dwFlag__hasDiag ;Diagram now has a drawfile STR R14,[R10,#dWin__flags] ;Save the flags back again BLNE drawX__open ;Yes -- open it on screen BLNE drawX__cascade ;And cascade the thing too 90drawX__loaded LDMFD R13!,{R0,R1,PC}^ ;Return to caller LTORG ; --- drawX__loadFail --- ; ; On entry: R0 == pointer to error, or 0 if none ; R1 == 1 ; R10 == diagram handle, or 0 if none ; ; On exit: -- ; ; Use: Handles an error during loading a diagram. drawX__loadFail ROUT STMFD R13!,{R0-R4,R14} ;Save some registers CMP R10,#0 ;Is there a diagram? BEQ %50drawX__loadFail ;No -- just report error ; --- Work out what to do --- ; ; If the window is new, delete it. Otherwise just leave it ; blank. LDR R14,[R10,#dWin__flags] ;Load the flags word TST R14,#dwFlag__tent ;Is it tentative? BLNE drawX__killDiag ;Yes -- kill the diagram BNE %50drawX__loadFail ;And skip ahead ; --- Blank out a diagram --- BIC R14,R14,#dwFlag__loaded+dwFlag__hasDiag STR R14,[R10,#dWin__flags] ;Save the flags back again ADRL R0,drawX__untitled ;Point to the blank name BL msgs_lookup ;Translate the message MOV R1,R0 ;This is the source string ADD R0,R10,#dWin__filename ;Point to filename buffer BL str_cpy ;Copy it over BL drawX__setTitle ;Set the window's title MOV R1,#0 ;Left hand side is 0 MOV R2,#0 ;Bottom edge is 0 too MOV R3,#640 ;Window is 640 units wide MOV R4,#512 ;And 512 units high ADD R14,R10,#dWin__extent ;Point to the extent block STMIA R14,{R1-R4} ;Save them all away LDR R0,[R10,#dWin__window] ;Load the window handle ADD R1,R10,#dWin__extent ;Point to the coordinates SWI Wimp_SetExtent ;Set the new extent BL drawX__refresh ;Refresh the window contents ; --- Report the error --- 50 LDR R2,[R13,#0] ;Load the error pointer CMP R2,#0 ;Is it interesting? ADDNE R2,R2,#4 ;Yes -- point to error text ADRNE R0,drawX__loadErr ;Point to the message BLNE msgs_error ;Translate the error MOVNE R1,#1 ;Only one button please BLNE errorBox ;And report the error LDMFD R13!,{R0-R4,PC}^ ;Return to caller drawX__loadErr DCD 1 DCB "drxELF",0 LTORG ;----- That's all, folks ---------------------------------------------------- END