; Copyright 1996 Acorn Computers Ltd ; ; Licensed under the Apache License, Version 2.0 (the "License"); ; you may not use this file except in compliance with the License. ; You may obtain a copy of the License at ; ; http://www.apache.org/licenses/LICENSE-2.0 ; ; Unless required by applicable law or agreed to in writing, software ; distributed under the License is distributed on an "AS IS" BASIS, ; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ; See the License for the specific language governing permissions and ; limitations under the License. ; ; > s.Wimp06 ;;---------------------------------------------------------------------------- ;; Template loading section ;;---------------------------------------------------------------------------- find_close * &00 find_openin * &40 find_openout * &80 find_openup * &C0 gbpb_writeR4 * 1 gbpb_write * 2 gbpb_readR4 * 3 gbpb_read * 4 ;;----------------------------------------------------------------------------- ;; int_setptr ;; ;; in [filehandle] = handle / =-1 if RAM resident file ;; R2 = offset to be used ;; out R4 = offset to be used if RAM based ;;----------------------------------------------------------------------------- int_setptr ENTRY "R1" LDR R1,filehandle ; RAM based transfer? CMP R1,#-1 CMPNE R1,#-2 ; resfs NK MOVEQ R4,R2 ; if -1 then set to be handle MOVNE R0,#OSArgs_SetPTR SWINE XOS_Args ; if file then use OS_Args EXIT ;;---------------------------------------------------------------------------- ;; int_bget - get a single character from the file, trapping EOF ;; ;; in [filehande] = handle / =-1 if RAM resident ;; [fileaddress] -> file if [filehandle] =-1 ;; [filelength] = size of file if RAM resident ;; R4 = index of byte to be obtained ;; out R0 = byte read ;; R1 preserved ;; R4 updated ;;----------------------------------------------------------------------------- int_bget ENTRY "R1-R2" LDR R1,filehandle ; get the handle CMP R1,#-1 ; is it a RAM based object? CMPNE R1,#-2 ; res fs BNE %FT10 LDR R1,fileaddress ; -> ram based object LDR R2,filelength ; = size of the file being read Debug tmp,"int_bget: fileat, filesize, ptr:",R1,R2,R4 CMP R4,R2 ; is the byte within this file LDRLTB R0,[R1,R4] ; get a byte ADDLT R4,R4,#1 EXIT LT ; and return if obtained MyXError TemplateEOF EXIT MakeErrorBlock TemplateEOF 10 SWI XOS_BGet ; get the byte if not EXIT ;;----------------------------------------------------------------------------- ;; int_gbpb - perform block transfer from file / memory ;; ;; in R2 -> buffer to fill ;; R3 = number of bytes to be read ;; R4 = offset to start reading from ;; [filehande] = handle / =-1 if RAM resident ;; [fileaddress] -> file if [filehandle] =-1 ;; [filelength] = size of file if RAM resident ;; out R2,R3,R4 updated ;;----------------------------------------------------------------------------- int_gbpb ENTRY "R1" LDR R1,filehandle ; get the handle of the file CMP R1,#-1 ; is it coming from memory rather than a file? CMPNE R1,#-2 BNE %FT10 LDR R0,filelength LDR R1,fileaddress ; get the address of the file Debug tmp,"int_gbpb: filelen, fileat, into, size, ptr:",R0,R1,R2,R3,R4 05 CMP R3,#0 ; finished transfer yet? EXIT EQ CMP R4,R0 ; have we reached the end of the file yet? MyXError TemplateEOF, GE EXIT VS LDRB R14,[R1,R4] STRB R14,[R2],#1 ; copy a byte SUB R3,R3,#1 ; decrease counter to transfer data ADD R4,R4,#1 ; and index into the file B %BT05 10 MOV R0,#gbpb_readR4 SWI XOS_GBPB EXIT ; fall back to old GBPB method ;---------------------------------------------------------------------------- ; Open template file - caches font table address and resets binding table ; Entry: R1 --> file name ; Exit: file opened (handle is held internally) ;---------------------------------------------------------------------------- SWIWimp_OpenTemplate MyEntry "OpenTemplate" BL int_open_template B ExitWimp int_open_template Push "LR" MOV R2,#0 ; zero all font bindings ADRL R3,fontbindings MOV R4,#&100 01 STR R2,[R3],#4 SUBS R4,R4,#4 BNE %BT01 ; check that the object exists, read its catalogue information and scan for resources: DebugS tmp,"filename =",R1 MOV R0,#OSFile_ReadNoPath SWI XOS_File ; attempt to read catalogue information on the file Pull "PC",VS ; if it fails then exit CMP R0,#object_file ; check that the object is valid MOVNE R2,R0 MOVNE R0,#OSFile_MakeError SWINE XOS_File ; and generate a meaningful error if its not DebugE tmp,"ERROR in template file type " MOVVC R0,#OSFind_ReadFile SWIVC XOS_Find ; attempt to open a file Pull "PC",VS ; return if it errors (may already have above) Debug tmp,"file handle, size =",R0,R4 MOVS R1,R0 MyXError WimpNoTemplateFile, EQ Pull "PC",VS ; if unable to open a stream then exit ; catch case of resources: object Push "R1" MOV R0,#FSControl_ReadFSHandle SWI XOS_FSControl DebugE tmp,"ERROR in template FSinfo " Debug tmp,"fshandle, fsinfo =",R1,R2 AND R2,R2,#&FF ; get FS that the file resides on TEQ R2,#fsnumber_resourcefs Pull "R1",NE ; restore the file handle BNE %FT10 ; exit the loop ; yeehaa its on resources so cache directly from there Debug tmp,"resources: object" STR R1,fileaddress STR R4,filelength ; setup information about file location Pull "R1" ; restore the file handle ready to be clopsed ; NK, stop wimp trying to free bits of ROM and other modules! MOV R0,#find_close SWI XOS_Find ; close the stream MOV R0,#-2 STR R0,filehandle ; flag as coming from resourcefs B %FT40 ; not a resources: object so attempt to read into ram and then exit 10 MOV R0,#ModHandReason_Claim MOV R3,R4 ; size of the block to allocate BL XROS_Module DebugE tmp,"ERROR in template cache claim " BVS %FT35 ; read directly from the file if this fails ; attempt to copy into ram/setup ram pointers worked Debug tmp,"file cache at, size =",R2,R3 STR R2,fileaddress STR R3,filelength ; store file block pointers MOV R0,#gbpb_readR4 MOV R4,#0 ; read directly from the file SWI XOS_GBPB DebugE tmp,"ERROR in caching template " BVS %FT30 ; failed so attempt to read from the file ; Cache successful, lose file and flag as in memory 20 MOV R0,#find_close SWI XOS_Find ; close the stream MOV R0,#-1 STR R0,filehandle ; flag as coming from RAM Debug tmp,"caching directly from file" B %FT40 ; and then read the header ; attempt to tidy up - an error occurred while block owned, release and fall back to file 30 MOV R0,#ModHandReason_Free LDR R2,fileaddress BL XROS_Module ; release the caching block 35 MOV R0,#0 STR R0,fileaddress STR R0,filelength ; flag as the block has been released STR R1,filehandle ; and setup a meaningful file handle Debug tmp,"reading from file handle =",R1 ; read the file header 40 ADRL R2,templatehdr MOV R3,#tf_hdr MOV R4,#0 BL int_gbpb DebugE tmp,"ERROR in int_gbpb " ; MOVVC R0,R1 ; put handle back in R0 Pull "PC" MakeErrorBlock WimpNoTemplateFile ;---------------------------------------------------------------------------- ; Close template file ;---------------------------------------------------------------------------- SWIWimp_CloseTemplate ROUT MyEntry "CloseTemplate" BL int_close_template B ExitWimp int_close_template Push "R1,LR" ; LDR R1,filehandle TEQ R1,#0 ; ignore this if file closed already BEQ %FT01 ; CMP R1,#-1 ; is it a file or in-memory block BLEQ %FT10 ; release RAM based object, or CMPNE R1,#-2 ; NK res fs MOVNE R0,#find_close SWINE XOS_Find ; attempt to close the file 01 MOV R14,#0 STR R14,filehandle STR R14,fileaddress STR R14,filelength ; flag as no file / no memory block ; Pull "R1,PC" ;.............................................................................. ; release the RAM based block - doesn't zap the pointers 10 MOV R1,LR ; MOV R0,#ModHandReason_Free LDR R2,fileaddress CMP R2,#0 BLGT XROS_Module ; release the RAM based object - ignoring errors! MOVGT R2,#0 STRGT R2,fileaddress ; MOVS PC,R1 ; return back - restoring the flags ;---------------------------------------------------------------------------- ; Load template definition from file to user workspace ; In: R1 --> user buffer to hold window defn (userblk=R1 on entry) ; R2 --> free space to put 'indirected' entries ; R3 --> end of free space ; R4 --> 256-byte reference count array (for font handles) ; R5 --> name of entry (may be wildcarded) ; R6 --> first index entry to look at (0 ==> all) ; Out: R2 --> new free space ; R6 --> next index entry (0 ==> not found) ; ; OR (Wimp 2.45 or later): ; ; In: R1 = -1 ; R5 --> name of entry (may be wildcarded) ; R6 --> first index entry to look at (0 ==> all) ; Out: R1 = size of scratch buffer required ; R2 = size of indirected data ; R6 --> next index entry (0 ==> not found) ;---------------------------------------------------------------------------- SWIWimp_LoadTemplate MyEntry "LoadTemplate" BL int_load_template B ExitWimp2 ; R1-R6 returned to user int_load_template Push "LR" ; LDR R1,filehandle STR R2,userfreeptr STR R3,userfreeend STR R4,userfontcounts ; MOVS R4,R6 MOVEQ R4,#tf_hdr ; if 0, start at first index entry srchindex ADRL R2,tempiconblk MOV R3,#tf_indexsize ; BL int_gbpb ; STR R4,templateindex BVS exittemplate ; unless last entry, check for match with (wildcarded) name LDR R6,tempiconblk TEQ R6,#0 BEQ exittemplate2 ; keep R6 ADRL R6,tempiconblk+12 BL matchnames ; EQ => matched, [tempworkspace] NE => wildcarded BNE srchindex ; if [R5..] was wildcarded, copy actual name back (R5 word-aligned) LDR R14,tempworkspace CMP R14,#0 ; don't copy if match name not wildcarded BEQ %FT01 ; TST R5,#3 ; must be word-aligned here! ADREQL R14,tempiconblk+12 LDMEQIA R14,{R0,R6,R14} ; safest thing is to just not do it STMEQIA R5,{R0,R6,R14} 01 ; load data into user buffer (unless R1 null on entry) Debug tmp,"Template: offset,size,type =",#tempiconblk,#tempiconblk+4,#tempiconblk+8 LDR R4,tempiconblk ; data offset in file LDR R3,tempiconblk+4 ; data size SUBS R2,userblk,#0 BGT %FT01 LDR R14,tempiconblk+8 ; is this a window? TEQ R14,#1 MOVNE R10,R3 ; R10 = size of buffer needed MOVNE R9,#0 ; R9 = size of indirected data BNE exittemplate_size ADR R2,tempworkspace ADD R4,R4,#w_nicons-w_cw0 MOV R3,#4 ; just read number of icons 01 Debug tmp,"XOS_GBPB:",R0,R1,R2,R3,R4 BL int_gbpb ; read from the file BVS exittemplate ; if userblk was null, we want to return R1 = size of scratch block, R2 = size of indirected data ; unless object type = 1 (window), all data is put into the scratch block LDR R14,tempiconblk+8 ; R14 = object type CMP userblk,#0 MOVGT R8,#-1 ; R8 < 0 => we're actually loading the data LDRLE userblk,tempiconblk+0 ; userblk = offset of data in file LDRLE R8,tempworkspace ; R8 = number of icons MOVLE R9,#0 ; R9 = total size of indirected data LDRLE R10,tempiconblk+4 ; R10 = total size of template entry ; LE => R14=1 (object type checked earlier) TEQ R14,#1 ; if loading item, just leave now BNE exittemplate ; process icons if this object is a window ; R8 < 0 => userblk -> user buffer containing data, else ; R8 = nicons => userblk = offset of data in file (we're counting it) ADDVC R1,userblk,#w_titleflags-w_cw0 ; R1 -> icon flags ADDVC R2,userblk,#w_title-w_cw0 ; R2 -> icon data BLVC templateicon BVS exittemplate ; ADD R14,userblk,#w_nicons-w_cw0 SUBS R6,R8,#0 ; if R8 < 0, LDRLT R6,[userblk,#w_nicons-w_cw0] ; get nicons from block CMP R6,#0 BLE %FT01 ADD R7,userblk,#w_size-w_cw0 doicons ADD R1,R7,#i_flags ; R1 -> icon flags ADD R2,R7,#i_data ; R2 -> icon data BL templateicon BVS exittemplate ADD R7,R7,#i_size SUBS R6,R6,#1 BNE doicons 01 CMP R8,#0 ; R8 >= 0 => we're counting: BGE exittemplate_size ; R9 = indirected data size, R10 = total size exittemplate LDR R6,templateindex exittemplate2 MOV R1,#1 BVS %FT05 CMP userblk,#0 STRGT R1,[userblk,#64] ; make sure window's sprite area is sensible CLRV ; cmp sets V !!!!! 05 MOV R1,userblk LDR R2,userfreeptr exittemplate3 ; returns R1,R2 = buffer sizes LDR R3,userfreeend LDR R4,userfontcounts Pull "PC" ; code goes to ExitWimp2 MakeErrorBlock WimpBadTemplate exittemplate_size LDR R6,templateindex MOV R1,R10 ; R1 = buffer size required MOV R2,R9 ; R2 = indirected data size required Debug tmp,"Template size =",R1,R2 B exittemplate3 ; In R1 --> flag word for icon ; R2 --> data for icon (could be indirected) ; R8 < 0 => R1,R2 are file offsets (we're just counting the size required) ; R9 = current size of indirected data ; Out R9 updated ; R0,R1,R3 corrupted templateicon Push "R2,R4,R7,LR" ; CMP R8,#0 ; if just counting, ignore font stuff BGE counttemplateicon ; LDR R14,[R1] TST R14,#if_fancyfont BEQ tryindirected ; LDR R14,userfontcounts CMP R14,#0 MyXError WimpBadFonts,LE Pull "R2,R4,R7,PC",VS ; ; if we already know about this font, just change the handle ; ASSERT (ib_fontno=24) LDRB R7,[R1,#3] ; R7 = internal font handle ADRL R14,fontbindings LDRB R0,[R14,R7] TEQ R0,#0 ; if not zero, we can use it direct STRNEB R0,[R1,#3] ; R0 = external font handle BNE tryindirected ; ; to find out the binding, we must get the data from the file ; Push "R1-R5" SUB R4,R7,#1 ; R4 = offset into file =base+48*(R7-1) ADD R4,R4,R4,ASL #1 ; mul by 3 MOV R4,R4,ASL #tf_log2fontsize ; mul by 16 LDR R14,templatehdr+0 ADD R4,R4,R14 MOV R3,#tf_fontsize ADRL R2,tempiconblk BL int_gbpb ; ADRVCL R1,tempiconblk+8 ; R1 --> font name LDRVC R2,tempiconblk+0 ; R2 = x-size * 16 LDRVC R3,tempiconblk+4 ; R3 = y-size * 16 MOVVC R4,#0 ; use default resolution MOVVC R5,#0 SWIVC XFont_FindFont BVS errinfont ; ADRL R14,fontbindings ; update bindings STRB R0,[R14,R7] ; ; having called FindFont, notify the user of this fact! ; LDR R14,userfontcounts LDRB R2,[R14,R0] ; user thinks in external handles ADD R2,R2,#1 STRB R2,[R14,R0] CMP R2,#255 ; stop the rot before it's too late! MyXError WimpBadFonts,GE ; (don't allow it to get to 256) errinfont Pull "R1-R5" Pull "R2,R4,R7,PC",VS STRB R0,[R1,#3] ; put back external handle ; ; now check for indirected icons ; tryindirected LDR R14,[R1] TST R14,#if_indirected Pull "R2,R4,R7,PC",EQ ; LDR R0,[R2,#8] ; size of buffer required CMP R0,#0 ; size <= 0 => leave pointer alone BLGT relocateitem Pull "R2,R4,R7,PC",VS ; LDR R14,[R2,#4]! ; now do the validation string CMP R14,#w_cw1-w_cw0-1 ; must point to an item after the icon itself Pull "R2,R4,R7,PC",LE ; no need ; ADD R14,userblk,R14 MOV R7,R14 getlen LDRB R0,[R14],#1 CMP R0,#32 BCS getlen SUB R0,R14,R7 BL relocateitem ; Pull "R2,R4,R7,PC" MakeErrorBlock WimpBadFonts ;........................................................................ ; count size of indirected icons counttemplateicon Push "R1-R3" SUB R14,R2,R1 ; if R2 = R1+4, ADRL R2,tempiconblk CMP R14,#4 MOVEQ R3,#16 ; read all 16 bytes at once BEQ %FT01 MOV R3,#4 BL readR1_R3 ; read 4 bytes of icon flags, updating R2 LDRVC R1,[sp,#4] MOVVC R3,#12 ; read 12 bytes of icon data 01 BLVC readR1_R3 ; read rest of icon Pull "R1-R3" Pull "R2,R4,R7,PC",VS LDR R14,tempiconblk+0 ; icon flags TST R14,#if_indirected Pull "R2,R4,R7,PC",EQ ; LDR R0,tempiconblk+12 ; size of buffer required CMP R0,#0 ; size <= 0 => this isn't really the size ADDGT R9,R9,R0 ; update indirected data size ; LDR R14,tempiconblk+8 ; now do the validation string CMP R14,#w_cw1-w_cw0-1 ; if ptr, must point past window block at least Pull "R2,R4,R7,PC",LE ; -1, or 0..87 => not a pointer ; ADD R2,userblk,R14 ; R2 -> address of first byte BL int_setptr ; Debug tmp,"Counting validation string at",R2 countlen BL int_bget Pull "R2,R4,R7,PC",VS ; CMP R0,#32 ADD R9,R9,#1 ; update indirected data size BCS countlen ; (including terminator!) ; Pull "R2,R4,R7,PC" ;........................................................................ ; In R1 = file offset ; R2 -> user buffer ; R3 = number of bytes to read ; Out R2 updated (new R2 = old R2 + R3) ; R0 corrupted readR1_R3 Push "R1,R3,R4,LR" MOV R4,R1 BL int_gbpb Debug tmp,"XOS_GBPB:",R0,R1,R2,R3,R4 Pull "R1,R3,R4,PC" ;........................................................................ ; In R0 = size of buffer required ; [R2] --> data (rel. to userblk) ; Out data copied into free space ; userfreeptr updated relocateitem Push "R7,LR" Debug tmp,"Relocate: ptr,size,end =",#userfreeptr,R0,#userfreeend LDR R7,userfreeptr ADD R14,R7,R0 LDR R0,userfreeend CMP R14,R0 STRLE R14,userfreeptr ; update free space ptr MyXError WimpTooBig,GT,L Pull "R7,PC",VS LDR R14,[R2] ; old pointer to data STR R7,[R2] ; new pointer ADD R14,userblk,R14 ; (old one is rel. to userblk) getwritem LDRB R0,[R14],#1 ; copy into user workspace STRB R0,[R7],#1 CMP R0,#32 BCS getwritem Pull "R7,PC" ;........................................................................ ; In R5 --> target name (wildcarded) ; R6 --> candidate name ; Out EQ => names match ; [tempworkspace] <> 0 => name was wildcarded matchnames Push "R5,R7,R8,LR" MOV R7,#0 ; for going back to (none yet) STR R7,tempworkspace matchlp LDRB R0,[R5],#1 CMP R0,#"*" STREQ R0,tempworkspace ; NE => name was wildcarded MOVEQ R7,R5 MOVEQ R8,R6 BEQ matchlp ; LDRB R14,[R6],#1 CMP R0,#32 CMPCC R14,#32 BCC yesmatch ; both terminated (OK) CMP R14,#32 BCC nomatch ; candidate terminated (not OK) ; CMP R0,#"#" STREQ R0,tempworkspace ; NE => name was wildcarded EORNE R14,R14,R0 TSTNE R14,#&DF ; equate case BEQ matchlp ; MOVS R5,R7 ; old match ptr (if any) MOVNE R6,R8 ADDNE R8,R8,#1 BNE matchlp nomatch CMP R0,#-1 Pull "R5,R7,R8,PC" yesmatch CMP R0,R0 Pull "R5,R7,R8,PC" END