1 /***
2 * Created by IntelliJ IDEA.
3 * User: gareth
4 * Date: Sep 11, 2003
5 * Time: 6:43:19 PM
6 */
7 package com.tapina.robe.swi;
8
9 import com.tapina.robe.runtime.*;
10 import com.tapina.robe.swi.msgtrans.MessageFile;
11
12 import java.lang.reflect.Method;
13 import java.util.Map;
14 import java.util.HashMap;
15 import java.util.logging.Level;
16 import java.io.IOException;
17
18 public final class MessageTrans extends SWIHandler {
19 private static MessageTrans ourInstance;
20
21 public synchronized static MessageTrans getInstance() {
22 if (ourInstance == null) {
23 ourInstance = new MessageTrans();
24 }
25 return ourInstance;
26 }
27
28 private MessageTrans() {
29 }
30
31 public static int getBase() {
32 return 0x41500;
33 }
34
35 private static final String[] methodNames = new String[] {
36 "FileInfo", "OpenFile", "Lookup", "", "", "", "", "",
37 "", "", "", "", "", "", "", "",
38 "", "", "", "", "", "", "", "",
39 "", "", "", "", "", "", "", "",
40 "", "", "", "", "", "", "", "",
41 "", "", "", "", "", "", "", "",
42 "", "", "", "", "", "", "", "",
43 "", "", "", "", "", "", "", ""
44 };
45
46 public static Method getMethod(Integer offset) throws NoSuchMethodException {
47 return getMethod(methodNames[offset.intValue()]);
48 }
49
50 private static final Method getMethod(String name) throws NoSuchMethodException {
51 return MessageTrans.class.getMethod(name, METHOD_PARAMETERS);
52 }
53
54 private static final Map messages = new HashMap(5);
55
56 /***
57 * Returns information about the size required to hold a message file before MessageTrans_OpenFile used.
58 * Entry:
59 * => R1 = pointer to filename
60 * Exit:
61 * <= R0 = bit 0 set if held in memory
62 * R2 = size of buffer needed
63 * @param env
64 */
65 public void FileInfo(Environment env) {
66 final int[] R = env.getCpu().R;
67
68 R[0] = 0;
69 R[2] = 4;
70 }
71
72 /***
73 * This SWI opens a message-file. If R2 = 0, then the data-structure in R0 and the filename in R1 both must
74 * be in the RMA.
75 * Entry:
76 * => R0 = pointer to 4-word data structure
77 * R1 = pointer to filename
78 * R2 = pointer to buffer for file data, or 0 to use RMA
79 * @param env
80 */
81 public void OpenFile(Environment env) {
82 final int[] R = env.getCpu().R;
83 final MemoryMap memoryMap = env.getMemoryMap();
84 final int handle = openFile(memoryMap.getString0(R[1])).getHandle();
85 memoryMap.storeWord(R[0], handle);
86 }
87
88 public MessageFile openFile(String filename) {
89 final MessageFile file;
90 try {
91 file = new MessageFile(FilenameUtils.acornToNative(filename));
92 messages.put(file.getHandleObject(), file);
93 return file;
94 } catch (IOException e) {
95 log.log(Level.WARNING, "Unable to open messages: ", e);
96 throw new SWIError(0, e);
97 }
98 }
99
100 /***
101 * This SWI looks up the token on the message file. If R2 = 0 on entry, you'll get a pointer to a read-only string,
102 * and no parameter substitution will be done, also the string will be terminated by 10, and not 0. If R2 != 0, %0
103 * to %3 in the string will be replaced by the strings in R4 to R7. Prior to this call, you must have called
104 * MessageTrans_OpenFile .
105 * If the token is not found in the message file specified, it will be searched for in the global message file.
106 * If R2 = 0 on entry and the file is not stored in your own workspace, then the pointer will become invalid after
107 * Service_MessageFileClosed is issued - your application must trap this service call so it can re-read pointers.
108 * Entry:
109 * => R0 = pointer to 4-word data structure, or 0 for global messages
110 * R1 = pointer to Token
111 * R2 = pointer to buffer
112 * R3 = buffer size
113 * R4 = pointer to parameter 0, or 0 if none
114 * R5 = pointer to parameter 1, or 0 if none
115 * R6 = pointer to parameter 2, or 0 if none
116 * R7 = pointer to parameter 3, or 0 if none
117 * Exit:
118 * <= R1 = pointer to token-terminator
119 * R2 = result string
120 * R3 = size of result
121 * @param env
122 */
123 public void Lookup(Environment env) {
124 final int[] R = env.getCpu().R;
125 final MemoryMap memoryMap = env.getMemoryMap();
126 final int handle = memoryMap.getWord(R[0]);
127 final MessageFile file = (MessageFile) messages.get(new Integer(handle));
128 if (file == null) {
129 throw new SWIError(0, "Messages not found");
130 }
131 final String token;
132 if (R[2] != 0) {
133 token = memoryMap.getString0(R[1]);
134 } else {
135 token = memoryMap.getString0_10_13(R[1]);
136 }
137 final int buffer = R[2];
138 final int bufferSize = R[3];
139 final String[] parameters = new String[4];
140 if (R[2] != 0) {
141 for (int i = 0; i < 4; i++) {
142 parameters[i] = R[4 + i] == 0? null : memoryMap.getString0(R[4 + i]);
143 }
144 }
145 String result = lookup(file, token, parameters);
146 R[1] += token.length();
147 if (buffer == 0) {
148
149 final RawDataBlock resultDataBlock = memoryMap.createSystemDataBlock(result);
150 R[2] = resultDataBlock.getAddress();
151 } else {
152 if (result.length() > bufferSize - 1) {
153 result = result.substring(0, bufferSize - 1);
154 }
155 memoryMap.storeString0(buffer, result);
156 }
157 R[3] = result.length() + 1;
158 }
159
160 public String lookup(MessageFile file, String token, String[] parameters) {
161 final int defaultValueIndex = token.indexOf(':') + 1;
162 for (int i = 0; i < parameters.length; i++) {
163 if (parameters[i] != null) {
164 log.warning("Parameter " + i + " ignored: " + parameters[i]);
165 }
166 }
167 final String value;
168 if (defaultValueIndex > 0) {
169 value = file.lookup(token.substring(0, defaultValueIndex - 1), token.substring(defaultValueIndex));
170 } else {
171 value = file.lookup(token, "");
172 }
173 return value;
174 }
175
176 }
177