; Copyright 2019 RISC OS Open 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. ; ; > Wimp.s.CnPCaret [ CnP ; In: R0 = window handle ; R1 = icon handle ; R2 = X offset relative to window origin ; R3 = Y offset relative to window origin ; R4 = caret height/flags ; R5 = string index ; [+ R6 = maximum selection index] ;We are given x,y coords relative to window work area origin ; remove existing caret or selection or whatever first, depending on how we're called int_set_caret_position ROUT Push "R0-R7,R11,R14" ; if we're called with R5=-1 then R4,R5 are calculated from R0-R3 ; however, R4 is undefined on entry so could be anything. ; Internally we'd like to be able to use the call to put a ghost caret ; to a mouse click... ; we're doing the call by a SWI now, so need a way to get ghost caret calculations ; add R5=-2 for this purpose - calculate ghost caret details from x/y coords ; R4 *must* now be a valid flag set CMP R5,#-1 BNE %FT00 CMP R1,#-1 MOVNE R4,#-1 ; R4 now is -1 (ie no flags) 00 CMP R5,#-2 MOVEQ R5,#-1 ; validate existing caret blocks LDR handle,caretdata CMP handle,#nullptr BLNE checkhandle MOVVS handle,#nullptr STRVS handle,caretdata LDR handle,ghostcaretdata CMP handle,#nullptr BLNE checkhandle MOVVS handle,#nullptr STRVS handle,ghostcaretdata LDR R14,taskhandle ; calling task Push "R14" ; preserve for later CMP R4,#-2 MOVEQ R4,#-1 ; workaround bug in Filer 1.96-2.45 which calls with R4=-2 instead of -1 LDR R14,dragtype ; is there currently an icon selection drag? TEQ R14,#drag_icon_selection BNE %FT00 ; are we moving the main caret? If not, doesn't matter CMP R4,#-1 ; R4=-1 implies main caret TSTNE R4,#crf_ghostcaret :OR: crf_selection BNE %FT00 ; if so, then we need to see if we're relocating outside the icon ; if we are, then the drag should be cancelled LDR R14,caretdata+caretwindow TEQ R0,R14 LDREQ R14,caretdata+careticon TEQEQ R1,R14 BEQ %FT00 ; same window/icon so continue unchanged ; we need to stop the drag before proceeding Push "R0,x0,y0,x1,y1" LDR R0,caretdata+caretwindow Abs handle,R0 MOV R14,#0 STR R14,dragtype MOV R14,#bignum STR R14,[handle,#w_seldata+wselxoverride] BL clearpointerwindow ; corrupts x0,y0,x1,y1 BL iconautoscroll_stop Pull "R0,x0,y0,x1,y1" 00 AcceptLoosePointer_NegOrZero R0,nullptr CMP R0,R0,ASR #31 BEQ %FT07 ; we know this one's not valid MOV handle,R0 BL checkhandle ; valid window handle? BVC %FT01 BVS %FT08 ; destination isn't valid, so just remove the caret 07 ; if we've been called with r0=-1 then we may need to add some flags... LDR R14,taskidentifier1 ; 'TASK' CMP R2,R14 ; is R2 'TASK' MOVNE R4,#0 ; if we're called with TASK then R4 has correct flags. If not, we need ; to make sure we have some valid flags MOVEQ R2,#0 ; if we were called with R2='TASK' then STREQ R2,[sp,#(2+1+8)*4] ; ensure R2=0 on return - taskhandle stacked below r2 08 SavePSR R6 ; keep V flag for exiting later Push "R6" STR R0,[sp,#8] ; preserve error message MOV R0,#-1 ; carry on as an invalid window handle BL wscp_remove_current_caret ; remove the caret, queue redraw as necessary ; need to clear the appropriate data blocks MOV R14,#nullptr CMP R4,#-1 TSTNE R4,#crf_ghostcaret :OR: crf_selection ; normal caret? STREQ R14,caretdata BEQ exitsetcaret_abort TST R4,#crf_ghostcaret ; ghost caret? STRNE R14,ghostcaretdata BNE exitsetcaret_abort TST R4,#crf_selection ; unshaded selection? BEQ exitsetcaret_abort LDR R11,selectionwindow CMP R11,#nullptr BEQ exitsetcaret_abort BL clipboard_check_current_drag_op ; stop drag op if selection has been terminated Abs R11,R11 STR R14,[R11,#w_seldata] ; update if handle is valid STR R14,selectionwindow ; current selection window is now invalid too B exitsetcaret_abort 01 ; continues - r0 is a confirmed valid window handle ; is the window currently open and able to receive a focus? Push "R1,R10" MOV R1,#-1 BL setfocus Pull "R1,R10" BVS %BT08 ; no - abort and clear caret 02 ; set up the hascaret etc. blocks for the current state of the icon before gaining caret LDR R14,caretdata EORS R14,R14,R0 LDREQ R14,caretdata+careticon EOREQ R14,R14,R1 STR R14,hascaret LDR R14,ghostcaretdata EORS R14,R14,R0 LDREQ R14,ghostcaretdata+ghostcareticon EOREQ R14,R14,R1 STR R14,hasghostcaret LDR R14,[handle,#w_seldata] EOR R14,R14,R1 STR R14,hasselection ; work out which block we're playing with - main or ghost caret CMP R4,#-1 TSTNE R4,#crf_selection ; are we doing a selection caret? Different data blocks if we are. BNE %FT40 CMP R4,#-1 ; which caret block do we need? TSTNE R4,#crf_ghostcaret ADREQL R11,caretdata ADRNEL R11,ghostcaretdata LDR R14,[R11] STR R14,oldcaretwindow BL wscp_remove_current_caret ; was it OK? MOVVS R14,#nullptr STRVS R13,[R11] STRVS R0,[sp,#4] ; taskhandle stacked first BVS exitsetcaret ; mark this caret as invalid and exit ; are we setting caret to an icon or just the work area? CMP R1,#0 BLT wscp_workarea ; we're placing in an icon ; we either use string offset or the coords supplied ; is the icon handle valid? LDR R14,[handle,#w_nicons] CMP R1,R14 ; icon handle out of range? BGT exitsetcaret ; abort if so LDR R14,[handle,#w_taskhandle] Task R14,,"SetCaret" ; page in window owner task ; check string offsets to ensure valid (ie within string itself) CMP R5,#0 BLPL wscp_make_offsets_valid ; sort checksum for the string if need to CMP R4,#0 ADRMIL R14,caretx ; no flags in this situation, assume normal caret STRMI R14,caretx_dest BMI %FT18 TST R4,#crf_ghostcaret ADREQL R14,caretx ADRNEL R14,ghostcaretx STR R14,caretx_dest ; determine whose caretx gets set BEQ %FT17 Push "R0,R11" LDR R11,[handle,#w_icons] ADD R11,R11,R1,LSL #i_shift ; get icon address BL writable_calc_checksum STR R0,ghostcaretchecksum Pull "R0,R11" 17 ; CMP R4,#0 ; BMI %FT18 CMP R5,#0 BMI %FT18 Push "R4" BL setcaretcoords ; recompute. We may want to keep the height after BIC R14,R4,#&ff000000 BIC R14,R14,#&ff0000 Pull "R4" BIC R4,R4,#&ff BIC R4,R4,#&ff00 ORR R4,R4,R14 ; merge height and flags 18 CMP R5,#0 ; if R5<0 then R4,R5 <-- R0,R1,R2,R3 BGE %FT99 Push "R0,R1,R4" CMP R2,#&10000 MOVGT R2,#&10000 CMP R3,#&10000 MOVGT R3,#&10000 BL findcaret ; get R4,R5. We'll add the flags back in now. BIC R14,R4,#&ff000000 BIC R14,R14,#&ff0000 ; remove flags (if any) Pull "R0,R1,R4" CMP R4,#-1 MOVEQ R4,R14 BICNE R4,R4,#&ff BICNE R4,R4,#&ff00 ; remove old caret height ORRNE R4,R4,R14 ; merge in new caret height, keeping flags 99 CMP R4,#-1 ; if R4<0 then R2,R3,R4 <-- R0,R1,R5 MOVEQ R4,#0 ; fix up flags for the call BLEQ setcaretcoords TST R4,#crf_ghostcaret ADREQL R11,caretdata BEQ %FT98 ; override scrollx position? TST R4,#crf_nocentre MOVEQ R6,#bignum BEQ %FT96 ; if we were called with R5=-2, then new scrollx is in original R3, else it is in R2 LDR R6,[sp,#5*4] ; get R5 from stack CMP R6,#-2 LDREQ R6,[sp,#3*4] ; get R3 from stack if R5 was -2 LDRNE R6,[sp,#2*4] ; get R2 from stack otherwise 96 ; if ghost caret is on top of a selection, hide the ghost caret LDR R14,[handle,#w_seldata+wselicon] CMP R14,#nullptr BEQ %FT97 ; no selection CMP R14,R1 BNE %FT97 ; different icon, so no need to check LDR R14,[handle,#w_seldata+wsellowindex] ; low bound of selection CMP R14,R5 BGT %FT97 ; we're left of low bound LDR R14,[handle,#w_seldata+wselhighindex] ; high bound CMP R14,R5 ORRGE R4,R4,#crf_invisible ; we're in selection zone, so hide caret 97 ADRL R11,ghostcaretdata STMIA R11,{R0-R5} ; we've set/adjusted a ghost caret. ; was there a main caret in the same icon? ; if so, we'll need to recalculate its position BL refreshcaret_ghost_main B %FT20 98 STMIA R11,{R0-R5} ; processed values ; ** no r6 for scrollx now ; BL check_shaded_selection_window ; focus on? LDR R14,oldcaretwindow CMP R0,R14 BEQ %FT20 ; same window, no repeat messages BL check_shaded_selection_window BL send_gaincaret BL focuson MOVVS R14,#nullptr STRVS R14,[R11] BVS exitsetcaret 20 ; redraw the target icon Push "R0-R2" LDR handle,[R11,#0] Abs handle,handle ; window handle of current caret LDR R0,[R11,#4] ; icon handle of current caret MOV R1,#0 MOV R2,#0 BL int_set_icon_state Pull "R0-R2" B exitsetcaret wscp_workarea ; setting a caret (ghost or main) to the window work area ; no need to calculate string offsets etc ; just place the caret and leave BL upcaret BVS %FT22 ; upcaret corrupts R11 CMP R4,#-1 MOVEQ R4,#crf_invisible ; if no flags supplied, make the caret invisible TSTNE R4,#crf_ghostcaret ADREQL R11,caretdata ADRNEL R11,ghostcaretdata ; update stored data block STMIA R11,{R0-R5} TST R4,#crf_ghostcaret ; if we're a ghost caret we don't do messages BNE %FT21 LDR R14,oldcaretwindow CMP R0,R14 BEQ %FT21 ; same window, no repeat messages BL send_gaincaret BL check_shaded_selection_window BL focuson 21 MOVVS R14,#nullptr ; if not successful, clear the caret block STRVS R14,[R11,#0] B exitsetcaret 22 MOV R14,#nullptr CMP R4,#-1 TSTNE R4,#crf_ghostcaret ADREQL R11,caretdata ; upcaret may corrupt R11 ADRNEL R11,ghostcaretdata STR R14,[R11,#0] B exitsetcaret 40 ; we are updating a selection caret BL wscp_remove_current_caret BVS %FT49 ; need to sort out the positions of the start and end indices CMP R5,R6 BGT exitsetcaret ; invalid range, so abort 41 ; is the icon handle valid? LDR R14,[handle,#w_nicons] CMP R1,R14 ; icon handle out of range? Pull "R0-R7,R11,R14",HS ; abort if so BHS exitsetcaret LDR R14,[handle,#w_taskhandle] Task R14,,"SetCaret" ; page in window owner task BL wscp_make_offsets_valid ; ensure R5,R6 within string bounds Rel R11,handle BL clipboard_check_current_drag_op ; if we're messing with a drag selection, abort the drag CMP R5,R6 ; if we're the same, we need to remove the selection BNE %FT41 ; r5=r6, so remove the selection for now LDR R11,[handle,#w_seldata+wselicon] ; keep icon handle for later... MOV R14,#nullptr STR R14,[handle,#w_seldata+wselicon] ; was the selection the selection window? If so, remove that LDR R0,selectionwindow Abs R0,R0 TEQ R0,handle STREQ R14,selectionwindow ; do we need to recalculate the normal caret? LDR R1,caretdata Abs R1,R1 EOR R1,R1,handle LDR R2,caretdata+careticon EOR R1,R1,R2 EORS R1,R1,R11 BLEQ refreshcaret_main ; it's the same icon MOV R0,R11 MOV R1,#0 MOV R2,#0 BL int_set_icon_state B exitsetcaret 41 Push "R0,R11" LDR R11,[handle,#w_icons] ADD R11,R11,R1,LSL #i_shift ; icon address BL writable_calc_checksum STR R0,[handle,#w_seldata+wselchecksum] ; store checksum Pull "R0,R11" STR R1,[handle,#w_seldata+wselicon] ; store icon handle STR R5,[handle,#w_seldata+wsellowindex] ; store start offset STR R6,[handle,#w_seldata+wselhighindex] ; store end offset Push "R2" ; we may need this later... ; start index ; convert to X coord and also obtain height ; we lose flags from R4... preserve these MOV R11,R4 ADD R14,handle,#w_seldata+wselxoff STR R14,caretx_dest BL setcaretcoords ; sets r2,r3 ; keep r2,r3 ;str r2,[handle,#w_seldata+wselxoff] STR R3,[handle,#w_seldata+wselyoff] ; keep flags but add in the caret height part BIC R11,R11,#&ff00 BIC R11,R11,#&00ff ORR R4,R11,R4 STR R4,[handle,#w_seldata+wselflags] ; store flags in w_seldata ; do the end index LDR R5,[handle,#w_seldata+wselhighindex] ; get end index as R6 has been corrupted ADD R14,handle,#w_seldata+wselwidth STR R14,caretx_dest BL setcaretcoords LDR R14,[handle,#w_seldata+wselwidth] LDR R2,[handle,#w_seldata+wselxoff] SUB R14,R14,R2 STR R14,[handle,#w_seldata+wselwidth] ; make a width ; do we want to override the scrollx with a user value? Pull "R2" LDR R4,[sp,#(4+1)*4] ; get original R4 from entry to see if we have crf_nocentre TST R4,#crf_nocentre MOVEQ R2,#bignum STR R2,[handle,#w_seldata+wselxoverride] ; store scrollx directly ; does this window also have the current input focus? ; if not, then we need to transfer that too LDR R14,caretdata Abs R14,R14 TEQ handle,R14 MOVNE R14,#2 STRNE R14,refreshmaincaret ; refresh main caret by moving it to selection spot ; redraw the icon to reflect changes Rel R14,handle STR R14,selectionwindow LDR R0,[handle,#w_seldata+wselicon] MOV R1,#0 MOV R2,#0 BL int_set_icon_state B exitsetcaret 49 ; failed to set caret ; clean selection block and exit MOV R14,#nullptr STR R14,selectionwindow STR R14,[handle,#w_seldata+wselicon] ; fall through... exitsetcaret SavePSR R6 Push "R6" exitsetcaret_abort CheckAllWindows "int_set_caret_position (after)" ; do we need to recalculate the main caret? LDR R14,refreshmaincaret TEQ R14,#1 BLEQ refreshcaret_main 00 ; redraw anything queued LDR R10,redrawcaretwindow CMP R10,#nullptr LDRNE R0,redrawcareticon CMPNE R0,#nullptr Abs R10,R10,NE MOVNE R1,#0 MOVNE R2,#0 BLNE int_set_icon_state ; and return Pull "R6" ; get saved PSR Pull "R14" ; taskhandle is remembered Task R14,,"Restoring after SetCaret" ; did we need to move input focus to match the selection? LDR R14,refreshmaincaret TEQ R14,#2 BEQ %FT01 RestPSR R6 Pull "R0-R7,R11,PC" ; no, continue as normal by exiting 01 ; yes. We've finished our things, so we can re-call set_caret_position to set the input focus. ; that way losefocus/gainfocus messages etc will be sent properly and so on ; input focus goes to end point of selection, so LDMFD R13,{R0-R7,R11} MOV R5,R6 ; index into string is now the end point BIC R4,R4,#crf_selection :OR: crf_nocentre ; was selection, but make it the main caret ; everything else can stay the same BL int_set_caret_position ; back round again for another go RestPSR R6 Pull "R0-R7,R11,PC" ; finally quit wscp_remove_current_caret ROUT ; on entry, r0=window handle or -1 ; r1=icon handle if r0!=-1 ; r4=flags Push "R0-R5,R10,R11,R14" ; clear redraw block MOV R14,#nullptr STR R14,redrawcaretwindow STR R14,redrawcareticon MOV R14,#0 STR R14,refreshmaincaret ; have we changed to a different window for the main caret? CMP R4,#-1 ; invalid flags? assume main caret BEQ %FT00 TST R4,#crf_selection :OR: crf_ghostcaret BNE %FT01 00 ; we are dealing with the main caret, so do the checks ; is there a current selection in this window? CMP R0,#-1 ; no current window LDRNE R14,[R10,#w_seldata+wselicon] CMPNE R14,#-1 ; any current selection? CMPNE R14,R1 ; in the same icon as the new one? BEQ %FT50 ; remove current selection and redraw its icon Push "R0-R2,R10,R11" MOV R0,R14 MOV R14,#-1 STR R14,[R10,#w_seldata+wselicon] MOV R1,#0 MOV R2,#0 BL int_set_icon_state Pull "R0-R2,R10,R11" 50 LDR R14,caretdata CMP R0,R14 BEQ %FT01 Push "R0" MOV R0,R14 BL focusoff ; preserves flags BL send_losecaret BL check_unshaded_selection_window Pull "R0" 01 ; continue. ; need to pull a caret or a selection... CMP R4,#-1 ; invalid flags BEQ %FT02 TST R4,#crf_selection BNE wscp_rcc_selection_redraw 02 ; we are removing one of the carets ; is it an icon? If so, then the caret will be obliterated and redrawn in the new writeable icon redraw code ; so we can just request a redraw of the initial icon if it's different at this point ; work out which block we're playing with - main or ghost caret CMP R4,#-1 TSTNE R4,#crf_ghostcaret ADREQL R11,caretdata BEQ %FT03 ; ghost caret is on the move ADRL R11,ghostcaretdata ; if current ghost caret is same as current main caret, we'll need to refresh the main caret LDR R0,caretdata LDR R1,caretdata+careticon LDR R2,ghostcaretdata LDR R3,ghostcaretdata+ghostcareticon EOR R14,R0,R1 EOR R14,R14,R2 EORS R14,R14,R3 MOVEQ R14,#1 MOVNE R14,#0 STR R14,refreshmaincaret ; set up redraw on exit... 03 ; is there a previous window in use? ; if not, we can bail out LDR R0,[R11,#0] ; get window handle for current caret CMP R0,#nullptr Pull "R0-R5,R10,R11,PC",EQ ; is there a previous icon? LDR R14,[R11,#4] ; get icon handle for current caret CMP R14,#0 BGE wscp_rcc_queue_redraw ; request screen redraw for that area - this will remove the old caret by EOR LDMIA R11,{R0-R4} ; get previous caret state BL upcaret Pull "R0-R5,R10,R11,PC" wscp_rcc_selection_redraw ; if main caret present, it will need refreshing... LDR R5,caretdata LDR R14,selectionwindow TEQ R14,R5 BNE %FT60 LDR R5,caretdata+careticon LDR R14,[handle,#w_seldata+wselicon] TEQ R5,R14 MOVEQ R14,#1 STREQ R14,refreshmaincaret ; main caret will be in the selection 60 LDR R10,selectionwindow CMP R10,#nullptr BEQ %FT91 ; no unshaded selection window, so skip next bit CMP R10,R0 BEQ %FT91 ; moving within the same window Abs R10,R10 LDR R14,[handle,#w_seldata+wselicon] ; icon handle for redraw - current selection MOV R5,#nullptr STR R5,selectionwindow ; clear current unshaded selection window MOV R0,R14 MOV R1,#0 MOV R2,#0 BL int_set_icon_state ; redraw that icon to make it shaded Pull "R0-R5,R10,R11,PC" 91 ; new window becomes the unshaded selection as it will also gain the input focus ; we may have things to do to any other selection in the new window ; retrieve window handle for the destination Pull "R0" Abs R10,R0 LDR R14,[handle,#w_seldata] CMP R14,R1 ; moving to a new icon? Pull "R1-R5,R10,R11,PC",EQ ; no, same as before. So no need to redraw (we'll get redrawn later) STR R0,redrawcaretwindow ; queue window/icon for redraw STR R14,redrawcareticon Pull "R1-R5,R10,R11,PC" wscp_rcc_queue_redraw ROUT ; r11=pointer to window handle (ie caret data block or similar) ; r14=icon handle from the current caret state LDR R11,[R11] ; get the window handle itself CMP R10,R11 ; new window is the same as old? BNE %FT02 ; redraw regardless CMP R14,R1 ; different icon? ; if the same, then we rely on the icon redraw to follow when we set the updated caret position... Pull "R0-R5,R10,R11,PC",EQ 02 ; it's a different icon, so we redraw the one we're leaving STR R11,redrawcaretwindow STR R14,redrawcareticon Pull "R0-R5,R10,R11,PC" wscp_make_offsets_valid Push "R7,R14" ; if R5<=0, then don't need to alter this one CMP R5,#0 BLE %FT03 ; clamp R5 to string length MOV R7,R5 BL wscp_clamp_length MOV R5,R7 03 ; do we need to adjust R6 too? TST R4,#crf_selection Pull "R7,PC",EQ ; no, exit CMP R5,#0 MOVLT R5,#0 ; r5<0 is not valid for selections CMP R6,#0 Pull "R7,PC",EQ ; no need to clamp MOV R7,R6 BL wscp_clamp_length MOV R6,R7 Pull "R7,PC" wscp_clamp_length ; clamp offset to string length ; On entry, r7=current offset ; r0=window handle ; r1=icon handle ; On exit, r7=clamped offset Push "R8-R10,R14" LDR R14,[handle,#w_nicons] CMP R1,R14 LDR R10,[handle,#w_icons] ADD R10,R10,R1,LSL #i_shift ; R10 now points to icon data block LDR R9,[R10,#i_flags] TST R9,#if_indirected MOVEQ R9,#12 ADDEQ R8,R10,#i_data LDRNE R9,[R10,#i_data+8] ; max length LDRNE R8,[R10,#i_data] ; r9=maximum string length ; r8=pointer to string data MOV R14,#0 ; current string length 79 LDRB R10,[R8,R14] CMP R10,#32 BLT %FT80 ; we have hit the end of the string SUBS R9,R9,#1 ; any more allowed? BEQ %FT80 ; end of string ADD R14,R14,#1 ; next byte CMP R7,R14 ; have we matched the caret offset yet? BNE %BT79 ; no - try again Pull "R8-R10,PC" ; yes - offset is within string 80 ; end of string ; R7 can't be any greater than this MOV R7,R14 Pull "R8-R10,PC" check_unshaded_selection_window ; if the window losing the input focus has a selection, redraw it to ensure it becomes unshaded CMP R0,#nullptr MOVEQ PC,R14 Push "R0-R2,R10,R14" Abs R10,R0 LDR R14,[handle,#w_seldata+wselicon] CMP R14,#nullptr Pull "R0-R2,R10,PC",EQ ; nothing to do here MOV R2,#0 MOV R1,#0 MOV R0,R14 MOV R14,#nullptr STR R14,selectionwindow ; no active selection right now... BL int_set_icon_state Pull "R0-R2,R10,PC" check_shaded_selection_window ; if the window gaining the input focus has a selection, we need to make sure it is redrawn as active Push "R0-R2,R11,R14" LDR R14,[handle,#w_seldata+wselicon] ; selection icon CMP R14,#nullptr Pull "R0-R2,R11,PC",EQ ; nothing here ; we have a selection ; update the selectionwindow Rel R11,handle STR R11,selectionwindow ; redraw the icon with the selection MOV R2,#0 MOV R1,#0 MOV R0,R14 BL int_set_icon_state Pull "R0-R2,R11,PC" writable_calc_checksum ; calculate checksum on text from an icon ; In: r11 is pointer to icon block ; Out: r0 is checksum Push "R1-R4,R14" ; get max string length LDR R14,[R11,#i_flags] TST R14,#if_indirected MOVEQ R4,#12 ADDEQ R1,R11,#i_data LDRNE R4,[R11,#i_data+8] LDRNE R1,[R11,#i_data] ; r1 has string pointer ; r4 has max length in bytes ; get text string length MOV R2,R1 70 LDRB R0,[R2],#1 CMP R0,#32 BLT %FT71 SUBS R4,R4,#1 BNE %BT70 71 ; R1 points to start of block ; R2 now points to byte after end of block ; block potentially includes terminator, but not a problem MOV R0,#0 MOV R3,#1 SWI XOS_CRC Pull "R1-R4,PC" ; refresh caret states - recalculation of positions and redraw if there are changes ; needed as moving one caret may induce movement of another one. refreshcaret_main Push "R0-R5,R10,R11,R14" ADRL R11,caretdata LDMIA R11,{R0-R5} Abs handle,R0 ; make sure the task is paged in for checking LDR R14,[handle,#w_taskhandle] Task R14,,"Refreshcaret_main" ADRL R14,caretx STR R14,caretx_dest BL setcaretcoords STR R2,caretdata+caretxoff ; update store STR R3,caretdata+caretyoff Pull "R0-R5,R10,R11,PC" refreshcaret_ghost_main ; ghost caret has been updated ; if the main caret is in the same icon, it may have moved on screen (though string index unchanged) ; on entry, r0-r5 are the caret block as updated (ghost caret data) Push "R14" LDR R14,caretdata TEQ R14,R0 Pull "PC",NE LDR R14,caretdata+careticon TEQ R14,R1 Pull "PC",NE ; same icon. Do the recalculation. ADRL R11,caretdata LDMIA R11,{R0-R5} ADRL R14,caretx STR R14,caretx_dest BL setcaretcoords STR R2,caretdata+caretxoff ; update store STR R3,caretdata+caretyoff ; no need to redraw as we're redrawing due to ghost caret change already MOV R14,#0 STR R14,refreshmaincaret ; don't need to refresh again if we were planning to ; restore settings. ADRL R11,ghostcaretdata LDMIA R11,{R0-R5} Pull "PC" ghostcaret_checksum_fail ; the checksum failed, so we need to ; * remove ghost caret ; * remove selection if affected too ; * adjust screen coords of main caret if relevant ; Entry: r0=checksum ; r10=window handle ; Task already paged in ; Exit: all preserved Push "R0-R1,R14" ; if selection is in same icon, it may also be affected LDR R14,ghostcaretdata+ghostcareticon LDR R1,[handle,#w_seldata+wselicon] TEQ R1,R14 MOV R14,#nullptr BNE %FT01 ; not the same icon LDR R1,[handle,#w_seldata+wselchecksum] TEQ R0,R1 BEQ %FT01 ; the checksum is actually valid for the selection, so leave it alone STR R14,[handle,#w_seldata+wselicon] ; clear selection state STR R14,selectioniconaddr ; current selection window as well? LDR R0,selectionwindow Abs R0,R0 TEQ R0,handle STREQ R14,selectionwindow ; if so, clear it 01 ; check against the main caret LDR R0,caretdata LDR R1,ghostcaretdata STR R14,ghostcaretdata ; we can now reset this bit STR R14,ghostcareticonaddr TEQ R0,R1 Pull "R0-R1,PC",NE ; differs LDR R0,caretdata+careticon LDR R1,ghostcaretdata+ghostcareticon TEQ R0,R1 Pull "R0-R1,PC",NE ; recalc main caret Push "R2-R11" ADRL R14,caretdata LDMIA R14,{R0-R5} ; get current caret state ADRL R14,caretx STR R14,caretx_dest STR R14,hasghostcaret ; not any more ; do we still have the selection? LDR R14,[handle,#w_seldata+wselicon] TEQ R14,R1 MOV R14,#0 STREQ R14,hasselection ; we have it STRNE handle,hasselection ; not us STR R14,hascaret ; still have this one BL setcaretcoords ; do the recalculation STR R2,caretdata+caretxoff STR R3,caretdata+caretyoff Pull "R2-R11" Pull "R0-R1,PC" selectioncaret_checksum_fail ; the checksum failed so we need to ; * remove selection box ; * remove ghost caret if in same icon and its checksum is invalid ; * adjust screen coords of main caret if relevant ; Entry: r0=checksum ; r10=window handle ; Task already paged in ; Exit: all preserved Push "R0-R1,R14" ; ghost caret in same icon? LDR R14,ghostcaretdata Abs R14,R14 TEQ R14,R10 BNE %FT01 ; not same window LDR R14,ghostcaretdata+ghostcareticon LDR R1,[handle,#w_seldata] TEQ R1,R14 BNE %FT01 ; not same icon ; checksum LDR R1,ghostcaretchecksum TEQ R0,R1 BEQ %FT02 ; checksum is actually valid so we leave the ghost caret alone ; note that ghost caret overrides main caret, so we don't recalculate main caret coords ; remove ghost caret MOV R14,#nullptr STR R14,ghostcaretdata STR R14,ghostcareticonaddr 01 LDR R1,[handle,#w_seldata+wselicon] ; icon ; remove selection caret MOV R14,#nullptr STR R14,[handle,#w_seldata+wselicon] STR R14,selectioniconaddr LDR R0,selectionwindow Abs R0,R0 TEQ R0,handle STREQ R14,selectionwindow ; no active selection if it was us LDR R0,caretdata+careticon TEQ R0,R1 Pull "R0-R1,PC",NE ; not same icon LDR R0,caretdata Abs R0,R0 TEQ R0,handle Pull "R0-R1,PC",NE ; not same window ; recalc main caret Push "R2-R11" ADRL R14,caretdata LDMIA R14,{R0-R5} ; get current caret state ADRL R14,caretx STR R14,caretx_dest STR R14,hasghostcaret ; not any more as we're doing a main caret STR R14,hasselection ; definitely not MOV R14,#0 STR R14,hascaret ; still have this one BL setcaretcoords ; do the recalculation STR R2,caretdata+caretxoff STR R3,caretdata+caretyoff Pull "R2-R11" Pull "R0-R1,PC" 02 MOV R14,#nullptr STR R14,[handle,#w_seldata+wselicon] ; clear selection STR R14,selectioniconaddr LDR R0,selectionwindow Abs R0,R0 TEQ R0,handle STREQ R14,selectionwindow ; no active selection if it was us Pull "R0-R1,PC" ; return. No update of main caret as the ghost caret overrides it anyway clipboard_check_current_drag_op Push "R10,R14" ; Entry: R11=window handle LDR R10,clipboard_spritearea_addr TEQ R10,#0 Pull "R10,PC",EQ ; no drag system available ; check to see if we are currently dragging from this window ; if dragging==TRUE and drag_finished==FALSE (as drag_aborted==TRUE means drag_finished==TRUE too) LDRB R14,[R10,#cbtask_var_dragging] TEQ R14,#CNPTRUE LDREQB R14,[R10,#cbtask_var_drag_finished] TEQEQ R14,#CNPFALSE LDREQ R14,[R10,#cbtask_var_source_window] TEQEQ R14,R11 ; if R11==dragging source ; abort the drag as the selection is being messed with MOVEQ R14,#clipboard_pw_dragabort ADREQL R10,clipboard_pollword STREQ R14,[R10] Pull "R10,PC" ] END