; Copyright 1998 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. ; ; Sources.Entries ;-------------------------------------------------------- Alphabet Debug xx,"Territory : Alphabet entry" MOV r0,#AlphNum MOV PC,LR ;-------------------------------------------------------- AlphabetIdent Debug xx,"Territory : AlphabetIdentifier entry" ADR r0,Alphabet_IdentString MOV PC,LR Alphabet_IdentString DCB "$AlphabetName",0 ALIGN ;-------------------------------------------------------- SelectKeyboardHandler Push "r0-r2,LR" MOV r0,#OsByte_Alphabet MOV r1,#128+TerrNum SWI XOS_Byte STRVS r0,[SP] Pull "r0-r2,PC" ;-------------------------------------------------------- WriteDirection MOV r0,#WriteDir MOV PC,LR ;-------------------------------------------------------- IME LDR r0,=IMESWIChunk MOV PC,LR ;-------------------------------------------------------- CharacterPropertyTable TEQ r1,#Property_Control ADREQL r0,ControlTable MOVEQ PC,LR TEQ r1,#Property_Uppercase ADREQL r0,UppercaseTable MOVEQ PC,LR TEQ r1,#Property_Lowercase ADREQL r0,LowercaseTable MOVEQ PC,LR TEQ r1,#Property_Alpha ADREQL r0,AlphaTable MOVEQ PC,LR TEQ r1,#Property_Punctuation ADREQL r0,PunctuationTable MOVEQ PC,LR TEQ r1,#Property_Space ADREQL r0,SpaceTable MOVEQ PC,LR TEQ r1,#Property_Digit ADREQL r0,DigitTable MOVEQ PC,LR TEQ r1,#Property_XDigit ADREQL r0,XDigitTable MOVEQ PC,LR TEQ r1,#Property_Accented ADREQL r0,AccentedTable MOVEQ PC,LR TEQ r1,#Property_ForwardFlow ADREQL r0,ForwardFlowTable MOVEQ PC,LR TEQ r1,#Property_BackwardFlow ADREQL r0,BackwardFlowTable MOVEQ PC,LR ADR r0,ErrorBlock_UnknownProperty B message_errorlookup ErrorBlock_UnknownProperty DCD TerritoryError_UnknownProperty DCB "UnkProp",0 ALIGN ;-------------------------------------------------------- GetLowerCaseTable ADRL r0,ToLowerTable MOV PC,LR ;-------------------------------------------------------- GetUpperCaseTable ADRL r0,ToUpperTable MOV PC,LR ;-------------------------------------------------------- GetControlTable ADRL r0,ToControlTable MOV PC,LR ;-------------------------------------------------------- GetPlainTable ADRL r0,ToPlainTable MOV PC,LR ;-------------------------------------------------------- GetValueTable ADRL r0,ToValueTable MOV PC,LR ;-------------------------------------------------------- GetRepresentationTable ADRL r0,ToRepresentationTable MOV PC,LR ;-------------------------------------------------------- ; Collate ; Entry: ; R1 -> String 1 (0 terminated) ; R2 -> String 2 (0 terminated) ; R3 = flags ; bit 0 - Ignore case. ; bit 1 - Ignore accents ; bit 2 - Interpret cardinals numerically ; Exit: ; R0 <0 if S1 < S2 ; =0 if S1 = S2 ; >0 if S1 > S2 ; Other registers preserved. ; ; Z set if equal (EQ). ; C set and Z clear if S1 > S2 (HI) ; N set and V clear if S1 < S2 (LT) ; ; V set if error. Collate Push "r1-r8,LR" MOV r3, r3, LSL #16 MOV r3, r3, LSR #16 ; We start off ignoring case and accents ORR r3,r3,#Collate_IgnoreCase :OR: Collate_IgnoreAccent ADRL r4,ToLowerTable ADRL r5,ToPlainForCollateTable ADRL r7,SortValueTable ADRL r8,ToRepresentationTable 01 LDRB r12,[r1],#1 LDRB r6 ,[r2],#1 Debug xx,"r12,r6",r12,r6 [ CollateDanishAA TEQ r12,#'A' TEQNE r12,#'a' TEQNE r6, #'A' TEQNE r6, #'a' BNE %FT35 TEQ r12,#'A' TEQNE r12,#'a' BNE %FT33 ; r6 must be an A/a LDRB r0, [r1] TEQ r0, r12 BEQ %FT31 TEQ r12,#'A' TEQEQ r0,#'a' BNE %FT32 31 TEQ r12,#'A' ; Got aa, Aa or AA. MOVEQ r12,#'�' MOVNE r12,#'�' ADD r1, r1, #1 32 TEQ r6,#'A' TEQNE r6,#'a' BNE %FT35 33 LDRB r0, [r2] TEQ r0, r6 BEQ %FT34 TEQ r6,#'A' TEQEQ r0,#'a' BNE %FT35 34 TEQ r6,#'A' ; Got aa, Aa or AA. MOVEQ r6,#'�' MOVNE r6,#'�' ADD r2, r2, #1 35 ] TST r3,#Collate_InterpretCardinals BEQ %FT37 MOV r0,r12 BL is_digit MOVEQ r0,r6 BLEQ is_digit BEQ %FT60 ; Both are digits 37 TST r3,#Collate_IgnoreAccent LDRNEB r12,[r5,r12] LDRNEB r6 ,[r5,r6] Debug xx,"r12,r6",r12,r6 TST r3,#Collate_IgnoreCase LDRNEB r12,[r4,r12] LDRNEB r6 ,[r4,r6] Debug xx,"r12,r6",r12,r6 [ CollateLatin1Ligatures TEQ r12,#'�' TEQNE r12,#'�' TEQNE r6, #'�' TEQNE r6, #'�' BNE %FT05 TEQ r12,#'�' TEQNE r12,#'�' BNE %FT03 ; r6 must be a ligature EOR r3, r3, #&20000000 TST r3, #&20000000 MOVNE r12, #'f' SUBNE r1, r1, #1 BNE %FT02 TEQ r12, #'�' MOVEQ r12, #'i' MOVNE r12, #'l' 02 TEQ r6,#'�' TEQNE r6,#'�' BNE %FT05 03 EOR r3, r3, #&10000000 TST r3, #&10000000 MOVNE r6, #'f' SUBNE r2, r2, #1 BNE %FT05 TEQ r6, #'�' MOVEQ r6, #'i' MOVNE r6, #'l' 05 ] [ CollateOELigatures TEQ r12,#'�' TEQNE r12,#'�' TEQNE r6, #'�' TEQNE r6, #'�' BNE %FT15 TEQ r12,#'�' TEQNE r12,#'�' BNE %FT13 ; r6 must be a ligature EOR r3, r3, #&08000000 TST r3, #&08000000 BEQ %FT11 SUB r1, r1, #1 TEQ r12,#'�' MOVEQ r12,#'O' MOVNE r12,#'o' B %FT12 11 TEQ r12,#'�' MOVEQ r12,#'E' MOVNE r12,#'e' 12 TEQ r6,#'�' TEQNE r6,#'�' BNE %FT15 13 EOR r3, r3, #&04000000 TST r3, #&04000000 BEQ %FT14 SUB r2, r2, #1 TEQ r6,#'�' MOVEQ r6,#'O' MOVNE r6,#'o' B %FT15 14 TEQ r6,#'�' MOVEQ r6,#'E' MOVNE r6,#'e' 15 ] [ CollateThornAsTH TEQ r12,#'�' TEQNE r12,#'�' TEQNE r6, #'�' TEQNE r6, #'�' BNE %FT25 TEQ r12,#'�' TEQNE r12,#'�' BNE %FT23 ; r6 must be a thorn EOR r3, r3, #&02000000 TST r3, #&02000000 BEQ %FT21 SUB r1, r1, #1 TEQ r12,#'�' MOVEQ r12,#'T' MOVNE r12,#'t' B %FT22 21 TEQ r12,#'�' MOVEQ r12,#'H' MOVNE r12,#'h' 22 TEQ r6,#'�' TEQNE r6,#'�' BNE %FT25 23 EOR r3, r3, #&01000000 TST r3, #&01000000 BEQ %FT24 SUB r1, r1, #1 TEQ r6,#'�' MOVEQ r6,#'T' MOVNE r6,#'t' B %FT25 24 TEQ r6,#'�' MOVEQ r6,#'H' MOVNE r6,#'h' 25 ] [ CollateGermanSharpS TEQ r12, #'�' EOREQS r3, r3, #&00800000 TST r3, #&00800000 MOVNE r12, #'s' SUBNE r1, r1, #1 TEQ r6, #'�' EOREQS r3, r3, #&00400000 TST r3, #&00400000 MOVNE r6, #'s' SUBNE r2, r2, #1 ] LDRB r12,[r7,r12] LDRB r6 ,[r7,r6] Debug xx,"r12,r6",r12,r6 SUBS r0,r12,r6 Pull "r1-r8,PC",NE ; Not equal, result is result of compare. TEQ r12,#0 BNE %BT01 ; Equal but not 0, get next char. 30 LDR r12,[sp,#8] ; Get original flags EORS r12,r3,r12 Pull "r1-r8,PC",EQ ; Done desired comparison - they're equal [ :LNOT:CollateAccentsBackwards LDMIA sp,{r1,r2} ; Restore string pointers ] TST r12,#Collate_IgnoreAccent ; Do they want us to differ accents? BICNE r3,r3,#Collate_IgnoreAccent [ CollateAccentsBackwards BNE %FT40 LDMIA sp,{r1,r2} | BNE %BT01 ; Back to the top, doing accents this time. ] BIC r3,r3,#Collate_IgnoreCase ; Already obeying accent directive, so B %BT01 ; must be disobeying case - check case. [ CollateAccentsBackwards 40 ; At this point the strings have just compared equal when ignoring case and ; accents. We are about to go around again, looking at accents this time. But ; the important point is that we must scan the string backwards. This is only ; required for French as far as I know, so for now, the following assertions ; will simplify things. ASSERT :LNOT: CollateThornAsTH ASSERT :LNOT: CollateDanishAA ; We know that the two strings must be of equivalent length, so as we rewind, ; r1 and r2 will hit the start simultaneously (as long as there's nothing ; really bizarre about the ToPlainForCollate table, such as ToPlain(f)='�'). LDR r5, [sp,#0] ; get back start of first string 41 LDRB r12,[r1,#-1]! LDRB r6 ,[r2,#-1]! LDRB r12,[r4,r12] ; We must be ignoring case at this point LDRB r6 ,[r4,r6] [ CollateLatin1Ligatures TEQ r12,#'�' TEQNE r12,#'�' TEQNE r6, #'�' TEQNE r6, #'�' BNE %FT45 TEQ r12,#'�' TEQNE r12,#'�' BNE %FT43 ; r6 must be a ligature EOR r3, r3, #&20000000 TST r3, #&20000000 MOVEQ r12, #'f' BEQ %FT42 ADD r1, r1, #1 TEQ r12, #'�' MOVEQ r12, #'i' MOVNE r12, #'l' 42 TEQ r6,#'�' TEQNE r6,#'�' BNE %FT45 43 EOR r3, r3, #&10000000 TST r3, #&10000000 MOVEQ r6, #'f' BEQ %FT45 ADD r2, r2, #1 TEQ r6, #'�' MOVEQ r6, #'i' MOVNE r6, #'l' 45 ] [ CollateOELigatures TEQ r12,#'�' TEQNE r12,#'�' TEQNE r6, #'�' TEQNE r6, #'�' BNE %FT55 TEQ r12,#'�' TEQNE r12,#'�' BNE %FT53 ; r6 must be a ligature EOR r3, r3, #&08000000 TST r3, #&08000000 BNE %FT51 TEQ r12,#'�' MOVEQ r12,#'O' MOVNE r12,#'o' B %FT52 51 TEQ r12,#'�' MOVEQ r12,#'E' MOVNE r12,#'e' ADD r1, r1, #1 52 TEQ r6,#'�' TEQNE r6,#'�' BNE %FT55 53 EOR r3, r3, #&04000000 TST r3, #&04000000 BNE %FT54 TEQ r6,#'�' MOVEQ r6,#'O' MOVNE r6,#'o' B %FT55 54 TEQ r6,#'�' MOVEQ r6,#'E' MOVNE r6,#'e' ADD r2, r2, #1 55 ] LDRB r12,[r7,r12] LDRB r6 ,[r7,r6] SUBS r0,r12,r6 Pull "r1-r8,PC",NE ; Not equal, result is result of compare. CMP r1, r5 ; are we now pointing at the start of the string? BNE %BT41 ; no, so get next character B %BT30 ; finished this pass - they're equal. Back to normal processing. ] 60 ; Cardinal compare algorithm (ignores sign, decimal point & exponents) ; * Skip leading zeros in both numbers ; * Count length of both numbers ; * If equal length, just do strcmp() ; * If different length, longest wins Push "r1-r2,r4-r5" MOV r0,r12 61 BL is_zero LDREQB r0,[r1],#1 BEQ %BT61 SUB r4,r1,#1 ; First non '0' 62 BL is_digit LDREQB r0,[r1],#1 BEQ %BT62 ; Is a digit MOV r0,r6 63 BL is_zero LDREQB r0,[r2],#1 BEQ %BT63 SUB r5,r2,#1 ; First non '0' 64 BL is_digit LDREQB r0,[r2],#1 BEQ %BT64 ; Is a digit SUB r1,r1,r4 ; Lengths SUB r2,r2,r5 SUBS r0,r1,r2 LDREQB r12,[r4],#1 LDREQB r6 ,[r5],#1 STMEQIA sp,{r4-r5} Pull "r1-r2,r4-r5" BEQ %BT37 ; Carry on collating from that digit Pull "r1-r8,PC" ; We have a winner is_digit ROUT ; R0 = char, R8 -> representation table ; Returns Z=1 if char is entry 0-9 in the table Push "r1,lr" MOV r1,#9 10 LDRB r14,[r8,r1] TEQ r14,r0 Pull "r1,PC",EQ SUBS r1,r1,#1 BPL %BT10 Pull "r1,PC" ; R1 -ve, therefore also NE is_zero Push "r1,lr" MOV r1,#0 B %BT10 ; ------------------------------------------------------------------------ ; ReadTimeZones ; ; In: ; IF R4 = 'ZONE' ; R1 = timezone to lookup, 0 to NumberOfTZ - 1 ; ; Out: ; R0 -> name of standard TZ if this territory was in use ; R1 -> name of summer TZ if this territory was in use ; R2 = Offset from UTC to standard time ; R3 = Offset from UTC to summer time. ; IF R4 = 'ZONE' on entry, R4 = 0 ; ReadTimeZones LDR r0, =ReadTimeZones_Extension TEQ r0, r4 MOVNE r1, #0 ; Behave as no extension MOVEQ r4, #0 ; Denote extension is supported CMP r1, #NumberOfTZ ADRCS r0,ErrorBlock_NoMoreZones BCS message_errorlookup GBLA tz_aligned GBLA tz_tableentry tz_aligned SETA ((MaxTZLength + 1) + 3) :AND: :NOT: 3 tz_tableentry SETA (tz_aligned * 2) + 4 + 4 ADR r0, tz_table MOV r3, #tz_tableentry MLA r0, r1, r3, r0 ADD r1, r0, #tz_aligned LDR r2, [r0, #0 + (2 * tz_aligned)] LDR r3, [r0, #4 + (2 * tz_aligned)] MOV pc, lr ErrorBlock_NoMoreZones DCD TerritoryError_NoMoreZones DCB "NMZones",0 ALIGN tz_table GBLA counter GBLS suffix GBLS strstd GBLS strdst GBLS offstd GBLS offdst WHILE counter < NumberOfTZ [ counter >= 16 suffix SETS :STR:counter:RIGHT:2 | suffix SETS :STR:counter:RIGHT:1 ] strstd SETS "NODST":CC:suffix strdst SETS "DST":CC:suffix offstd SETS "NODSTOffset":CC:suffix offdst SETS "DSTOffset":CC:suffix DCB $strstd, 0 SPACE tz_aligned - 1 - :LEN:$strstd DCB $strdst, 0 SPACE tz_aligned - 1 - :LEN:$strdst DCD $offstd DCD $offdst counter SETA counter + 1 WEND ; ------------------------------------------------------------------------ ; ReadSymbols ; ; In: ; R1 - Reason code: ; 0 Return pointer to 0 terminated decimal point string. ; 1 Return pointer to 0 terminated thousands separator ; 2 Return pointer byte list containing the size of each ; group of digits in formatted nonmonetary quantities. ; 255 = No further grouping ; 0 = Repeat last grouping for rest of number ; other = Size of current group, the next byte contains ; the size of the next group of dogits before the ; current group. ; 3 Return pointer to 0 terminated international currency symbol. ; 4 Return pointer to 0 terminated currency symbol in local alphabet. ; 5 Return pointer to 0 terminated decimal point used for monetary quantities ; 6 Return pointer to 0 terminated thousands separator for monetary quantities ; 7 Return pointer byte list containing the size of each ; group of digits in formatted monetary quantities. ; 8 Return pointer to 0 terminated positive sign used for monetary quantities ; 9 Return pointer to 0 terminated negative sign used for monetary quantities ; 10 Return number of fractional digits to be displayed in an internationally ; formatted monetay quantity ; 11 Return number of fractional digits to be displayed in a formatted monetay ; quantity ; 12 Return 1 If the currency symbol precedes the value for a nonnegative ; formatted monetary quantity ; 0 If the currency symbol succeeds the value for a nonnegative ; formatted monetary quantity ; 13 Return 1 If the currency symbol is separated by a space from the value for a ; nonnegative formatted monetary quantity ; 0 If the currency symbol is not separated by a space from the value for a ; nonnegative formatted monetary quantity ; 14 Return 1 If the currency symbol precedes the value for a negative ; formatted monetary quantity ; 0 If the currency symbol succeeds the value for a negative ; formatted monetary quantity ; 15 Return 1 If the currency symbol is separated by a space from the value for a ; negative formatted monetary quantity ; 0 If the currency symbol is not separated by a space from the value for a ; negative formatted monetary quantity ; ; 16 Return for a nonnegative formatted monetary quantity ; 0 If there are parentheses arround the quantity and currency symbol. ; 1 If the sign string precedes the quantity and currency symbol. ; 2 If the sign string succeeds the quantity and currency symbol. ; 3 If the sign string immediately precedes the currency symbol. ; 4 If the sign string immediately succeeds the currency symbol. ; 17 Return for a negative formatted monetary quantity ; 0 If there are parentheses arround the quantity and currency symbol. ; 1 If the sign string precedes the quantity and currency symbol. ; 2 If the sign string succeeds the quantity and currency symbol. ; 3 If the sign string immediately precedes the currency symbol. ; 4 If the sign string immediately succeeds the currency symbol. ; 18 Return pointer to 0 terminated list separator ; Out: ; R0 - Requested value. ReadSymbols Push "LR" ADR R14,SymbolTable LDR R0,[R14,R1,ASL #2] CMP R0,#20 ADDGE R0,R0,R14 Pull "PC" SymbolTable DCD decimal_point - SymbolTable DCD thousands_sep - SymbolTable DCD grouping - SymbolTable DCD int_curr_symbol - SymbolTable DCD currency_symbol - SymbolTable DCD mon_decimal_point - SymbolTable DCD mon_thousands_sep - SymbolTable DCD mon_grouping - SymbolTable DCD positive_sign - SymbolTable DCD negative_sign - SymbolTable DCD int_frac_digits DCD frac_digits DCD p_cs_precedes DCD p_sep_by_space DCD n_cs_precedes DCD n_sep_by_space DCD p_sign_posn DCD n_sign_posn DCD list_symbol - SymbolTable decimal_point DCB "$Decimal",0 thousands_sep DCB "$Thousand",0 grouping DCB $Grouping int_curr_symbol DCB "$IntCurr",0 currency_symbol DCB "$Currency",0 mon_decimal_point DCB "$MDecimal",0 mon_thousands_sep DCB "$MThousand",0 mon_grouping DCB $MGrouping positive_sign DCB "$MPositive",0 negative_sign DCB "$MNegative",0 list_symbol DCB "$ListSymbol",0 ALIGN ;--------------------------------------------------------------------------------- ;ReadCalendarInformation ; ;In: ; R1 = Pointer to 5 byte UTC time value. ; R2 = Pointer to a 12 word buffer ; ;Out: ; ; R1,R2 Preserved. ; ; [R2+0] = Number of first working day in the week. ; [R2+4] = Number of last working day in the week. ; [R2+8] = Number of months in the current year. ; (current = one in which given time falls) ; [R2+12] = Number of days in the current month. ; (current = one in which given time falls) ; [R2+16] = Max length of AM/PM string. ; [R2+20] = Max length of WE string. ; [R2+24] = Max length of W3 string. ; [R2+28] = Max length of DY string. ; [R2+32] = Max length of ST string (May be 0). ; [R2+36] = Max length of MO string. ; [R2+40] = Max length of M3 string. ; [R2+44] = Max length of TZ string. ; GetCalendarInformation Push "r0-r11,LR" ADR LR,CalendarInfo LDMIA LR,{R0,R3-R11,LR} ; Load fixed 11 items STMIA R2!,{R0,R3,R4} ; First three STMIB R2,{R5-R11,LR} ; Skip one, then next 8 SWI XTerritory_ReadCurrentTimeZone BVS %FT02 MOV R2,R1 LDR R1,[SP,#1*4] BL GetTimeValues ADRL R0,MonthLengths LDRB R0,[R0,R1] ; Get length of month CMP R1,#2 ; Is Feb ? BNE %FT01 TST R6, #3 ; is year multiple of 4 MOVNE R0,#28 ; no, then 29 Feb is bad BNE %FT01 TEQ R6, #0 ; is it a century year ? BNE %FT01 ; no, then 29 Feb is good TST R5, #3 ; is it a multiple of 400 ? MOVNE R0,#28 ; no, then 29 Feb is bad 01 LDR R2,[SP,#2*4] STR R0,[R2,#12] 02 STRVS r0,[SP] Pull "r0-r11,PC" CalendarInfo DCD FirstWorkDay ; First working day in week 1=Sunday 7=Saturday DCD LastWorkDay ; Last working day in week 1=Sunday 7=Saturday DCD NumberOfMonths ; Number of month in a year DCD MaxAMPMLength ; Max length of AM PM String DCD MaxWELength ; Max length of full day name DCD MaxW3Length ; Max length of short day name DCD MaxDYLength ; Max length of day in month DCD MaxSTLength ; Max length of st nd rd th ... string DCD MaxMOLength ; Max length of full month name. DCD MaxM3Length ; Max length of short month name. DCD MaxTZLength ; Max length of time zone name. ;--------------------------------------------------------------------------------- ;NameToNumber ; ;In: ; R1 = Pointer to territory name. ; ;Out: ; R0 = 0 - Unknown territory ; Else territory number. NameToNumber ROUT Entry "r1-r7",8 ; We know tokens aren't long. BL open_messages_file ; Enumerate all territory name tokens (TRnn) ADR r0,message_file_block MOV R4,#0 ; First call ADR R7,ToLowerTable 01 ADR R1,territory_token MOV R2,SP MOV R3,#8 SWI XMessageTrans_EnumerateTokens EXIT VS CMP R2,#0 MOVEQ r0,#0 EXIT EQ ; Get Message DebugS xx,"Next token is ",R2 MOV R1,R2 ; Token. MOV R2,#0 ; Don't copy message ! SWI XMessageTrans_Lookup EXIT VS ; Got message, now compare with territory name in string. LDR R1,[SP,#8] ; get user R1 02 LDRB R14,[R2],#1 CMP R14,#10 BEQ %FT03 ; End of message LDRB R14,[R7,R14] ; Lower case LDRB R10,[R1],#1 CMP R10,#0 MOVEQ r0,#0 EXIT EQ LDRB R10,[R7,R10] ; Lower case CMP R14,R10 BEQ %BT02 ; Try next character. B %BT01 ; Try next token. 03 LDRB R10,[R1],#1 CMP R10,#" " BGE %BT01 ; Not end of user input ! MOV R0,#10 ; Check token number ADD R1,SP,#2 SWI XOS_ReadUnsigned MOVVC R0,R2 EXIT territory_token DCB "TR*",0 ALIGN LNK Tables.s