ZWindow.java (7373B)
1 // Z Machine V3/V4/V5 Runtime 2 // 3 // Copyright 2002-2003, Brian Swetland <swetland@frotz.net> 4 // Available under a BSD-Style License. Share and Enjoy. 5 // 6 // Hiptop Application Main Window 7 8 package net.frotz.zruntime; 9 10 import danger.app.Resource; 11 import danger.app.ResourceDatabase; 12 import danger.app.Event; 13 import danger.app.Registrar; 14 import danger.app.IPCMessage; 15 16 import danger.ui.ScreenWindow; 17 import danger.ui.Font; 18 import danger.ui.Pen; 19 import danger.ui.Color; 20 import danger.ui.Window; 21 import danger.ui.TextField; 22 import danger.ui.EditText; 23 import danger.ui.PopupMenu; 24 25 import danger.app.DataStore; 26 27 public class ZWindow extends ScreenWindow implements Resources, Events 28 { 29 public ZWindow(ZRuntime app) { 30 super("ZMachine"); 31 setFullScreen(true); 32 font = Font.findFont("Fixed5x7"); 33 CH = font.getAscent() + font.getDescent(); 34 CA = font.getAscent(); 35 CW = font.charWidth('M'); 36 w = getWidth() / CW; 37 h = getHeight() / CH; 38 System.err.println("[ " + w + " x " + h + " ]"); 39 scr = new ZDanger(this, w, h); 40 screen = scr.screen; 41 this.app = app; 42 rdb = app.getResources(); 43 rdb.addToMenuFromResource(getActionMenu(),MENU_MAIN,this,null); 44 } 45 46 byte[] GetGameFile() { 47 int b; 48 Resource rsrc; 49 rsrc = app.getResource(1000,1000); 50 51 if(rsrc != null) { 52 b = rsrc.getSize(); 53 System.err.println("Gamefile: "+b+" bytes"); 54 byte[] data = new byte[b]; 55 rsrc.getBytes(data, 0, b); 56 return data; 57 } else { 58 return null; 59 } 60 } 61 62 void ScrollLine(byte data[], int off) { 63 } 64 65 Window dw; 66 67 public void Email(String subject, String body) { 68 IPCMessage msg = new IPCMessage(); 69 msg.addItem("action", "send"); 70 msg.addItem("subject", subject); 71 msg.addItem("body", body); 72 Registrar.sendMessage("Email", msg, null); 73 } 74 75 public boolean receiveEvent(Event e) { 76 switch(e.type) { 77 case DO_VIEW_NOTEPAD: 78 if(notepad == null) { 79 notepad = rdb.getScreen(SCREEN_NOTEPAD, this); 80 } 81 dw = notepad; 82 dw.show(); 83 break; 84 case DO_VIEW_TRANSCRIPT: 85 dw = rdb.getScreen(SCREEN_TRANSCRIPT,this); 86 ((EditText)dw.getDescendantWithID(ID_TEXT_TRANSCRIPT)).setText(transcript.toString()); 87 dw.show(); 88 break; 89 case NOTEPAD_DISMISS: 90 case TRANSCRIPT_DISMISS: 91 show(); 92 dw.hide(); 93 dw = null; 94 break; 95 case DO_EMAIL_NOTEPAD: 96 Email("Game Notepad",((EditText)dw.getDescendantWithID(ID_TEXT_NOTEPAD)).toString()); 97 break; 98 case DO_EMAIL_TRANSCRIPT: 99 Email("Game Transcript",((EditText)dw.getDescendantWithID(ID_TEXT_TRANSCRIPT)).toString()); 100 break; 101 case DO_CLEAR_TRANSCRIPT: 102 transcript.setLength(0); 103 ((EditText)dw.getDescendantWithID(ID_TEXT_TRANSCRIPT)).setText(""); 104 break; 105 case DO_ABOUT: 106 (rdb.getDialog(DIALOG_ABOUT)).show(); 107 break; 108 case DO_RESTORE: 109 dw = rdb.getDialog(DIALOG_RESTORE,this); 110 String[] gamelist = getSavedGames(); 111 if((gamelist == null) || (gamelist.length == 0)) { 112 notifyEngine(false); 113 break; 114 } else { 115 PopupMenu pm = (PopupMenu) dw.getDescendantWithID(ID_NAME_RESTORE); 116 117 for(int i = 0; i < gamelist.length; i++) { 118 if(gamelist[i] != null) { 119 System.err.println("Game["+i+"] = '"+gamelist[i]+"'"); 120 pm.addItem(gamelist[i]); 121 } 122 } 123 } 124 dw.show(); 125 break; 126 case DO_SAVE: 127 dw = rdb.getDialog(DIALOG_SAVE, this); 128 dw.show(); 129 break; 130 case SAVE_CANCEL: 131 case RESTORE_CANCEL: 132 notifyEngine(false); 133 break; 134 case SAVE_OK: 135 TextField tf = (TextField) dw.getDescendantWithID(ID_NAME_SAVE); 136 savegame = tf.toString(); 137 notifyEngine(true); 138 break; 139 case RESTORE_OK: 140 PopupMenu pm = ((PopupMenu) dw.getDescendantWithID(ID_NAME_RESTORE)); 141 selection = pm.getValue(); 142 notifyEngine(true); 143 break; 144 default: 145 return super.receiveEvent(e); 146 } 147 return true; 148 } 149 150 public boolean eventKeyUp(char c, Event e) { 151 scr.KeyPress(c); 152 return true; 153 } 154 155 public boolean eventWidgetUp(int widget, Event event) { 156 switch(widget) { 157 case Event.DEVICE_BUTTON_BACK: 158 app.returnToLauncher(); 159 return true; 160 default: 161 return super.eventWidgetUp(widget,event); 162 } 163 } 164 public void paint(Pen p) { 165 int i, off; 166 p.setFont(font); 167 int BG = Color.WHITE; 168 int FG = Color.BLACK; 169 int sh = scr.win1h; 170 171 p.setColor(FG); 172 p.fillRect(0,0,w * CW,sh*CH); 173 174 p.setColor(BG); 175 for(i = 0, off = 0; i < sh; i++){ 176 p.drawText(2, i * CH + CA, screen, off, w); 177 off += w; 178 } 179 180 p.fillRect(0, sh*CH, w*CW, h*CH); 181 p.setColor(FG); 182 for(; i < h; i++){ 183 p.drawText(2, i * CH + CA, screen, off, w); 184 off += w; 185 } 186 p.setColor(BG); 187 p.fillRect(0, i*CH, getWidth(), getHeight()); 188 189 if(scr.input_active){ 190 p.setColor(Color.RED); 191 int x = scr.cx * CW + 2; 192 int y = scr.cy * CH; 193 p.fillRect(x, y, x + CW, y + CH); 194 } 195 } 196 197 public String[] getSavedGames() { 198 DataStore ds = getDataStore(); 199 int i, j; 200 int count = ds.getRecordCount(); 201 String[] out = new String[count]; 202 203 for(i = 0; i < count; i++) { 204 byte[] data = ds.getRecordData(i); 205 206 if(data[0] == 'Z' && data[1] == '!' && data[2] == '1' && data[3] == '0'){ 207 for(j = 32; j < 64; j++){ 208 if(data[j] == 0) break; 209 } 210 out[i] = new String(data, 32, j-32); 211 } else { 212 out[i] = null; 213 } 214 } 215 return out; 216 } 217 218 public void saveGame(String gamename, byte[] data) { 219 int i,j,count; 220 221 DataStore ds = getDataStore(); 222 223 byte str[] = gamename.getBytes(); 224 225 data[0] = 'Z'; 226 data[1] = '!'; 227 data[2] = '1'; 228 data[3] = '0'; 229 230 for(i = 4; i < 64; i++) data[i] = 0; 231 232 for(i = 0; i < str.length; i++){ 233 if(i == 32) break; 234 data[32 + i] = str[i]; 235 } 236 237 count = ds.getRecordCount(); 238 for(i = 0; i < count; i++){ 239 byte game[] = ds.getRecordData(i); 240 for(j = 0; j < 64; j++){ 241 if(game[j] != data[j]) break; 242 } 243 if(j == 64){ 244 ds.setRecordData(i, data); 245 return; 246 } 247 } 248 249 ds.addRecord(data); 250 } 251 252 String usename = "SaveGame"; 253 int count = 0; 254 255 DataStore getDataStore() { 256 DataStore ds = DataStore.findDataStore("saved-games"); 257 if (ds == null) { 258 return DataStore.createDataStore("saved-games", true); 259 } else { 260 return ds; 261 } 262 } 263 264 boolean waitForUI() { 265 System.err.println("WaitForUI"); 266 try { 267 synchronized(notify) { 268 success = false; 269 notify.wait(); 270 } 271 } catch(Throwable t) { 272 } 273 System.err.println("DoneWaiting: " +success); 274 275 return success; 276 } 277 278 boolean success; 279 String savegame; 280 int selection; 281 282 void notifyEngine(boolean status) { 283 synchronized(notify){ 284 success = status; 285 notify.notify(); 286 } 287 } 288 289 public boolean Save(byte[] state) { 290 sendEvent(DO_SAVE, 0, 0, null); 291 292 savegame = null; 293 if(waitForUI() && (savegame != null) && (savegame.length() > 0)){ 294 saveGame(savegame, state); 295 scr.Print("Saved game as '"+savegame+"'\n"); 296 } 297 return true; 298 } 299 300 public byte[] Restore() { 301 selection = -1; 302 sendEvent(DO_RESTORE, 0, 0, null); 303 if(waitForUI() && (selection != -1)){ 304 return getDataStore().getRecordData(selection); 305 } else { 306 return null; 307 } 308 } 309 310 public void show() { 311 super.show(); 312 if(!scr.running){ 313 scr.running = true; 314 (new Thread(scr,"ZMachine")).start(); 315 } 316 } 317 318 public void Transcript(char data[], int off, int len) { 319 transcript.append(data, off, len); 320 } 321 322 StringBuffer transcript = new StringBuffer(8192); 323 324 final static int DO_RESTORE = 1; 325 final static int DO_SAVE = 2; 326 327 Object notify = new Object(); 328 329 Font font; 330 ZDanger scr; 331 ZRuntime app; 332 Window notepad; 333 ResourceDatabase rdb; 334 int w,h; 335 int CW, CH, CA; 336 byte screen[]; 337 338 } 339