Main Page   Data Structures   File List   Data Fields   Globals   Related Pages  

palm/simcity.c

Go to the documentation of this file.
00001 
00008 #include <PalmOS.h>
00009 #include <StringMgr.h>
00010 #include <KeyMgr.h>
00011 #include <StdIOPalm.h>
00012 #include <simcity.h>
00013 #include <savegame.h>
00014 #include <savegame_be.h>
00015 #include <options.h>
00016 #include <map.h>
00017 #include <budget.h>
00018 #include <zakdef.h>
00019 #include <ui.h>
00020 #include <drawing.h>
00021 #include <build.h>
00022 #include <query.h>
00023 #include <handler.h>
00024 #include <globals.h>
00025 #include <simulation.h>
00026 #include <disaster.h>
00027 #include <resCompat.h>
00028 #include <palmutils.h>
00029 #include <simcity_resconsts.h>
00030 #include <mem_compat.h>
00031 #include <minimap.h>
00032 #include <beam.h>
00033 #include <logging.h>
00034 #include <locking.h>
00035 
00036 #ifdef LOGGING
00037 #include <HostControl.h>
00038 #endif
00039 
00040 static RectangleType rPlayGround;
00041 
00043 static WinHandle winZones;
00045 static WinHandle winMonsters;
00047 static WinHandle winUnits;
00048 
00050 static WinHandle winSpeeds;
00051 
00052 BuildCode nSelectedBuildItem = Be_Bulldozer;
00053 BuildCode nPreviousBuildItem = Be_Bulldozer;
00054 
00055 UInt32 timeStamp = 0;
00056 UInt32 timeStampDisaster = 0;
00057 Int16 simState = 0;
00058 Coord XOFFSET = 0;
00059 Coord YOFFSET = 15;
00060 #ifdef SONY_CLIE
00061 UInt16 jog_lr = 0;
00062 #endif
00063 
00064 static Boolean hPocketCity(EventPtr event);
00065 static Boolean hQuickList(EventPtr event);
00066 static Boolean hExtraList(EventPtr event);
00067 
00068 static Int16 _PalmInit(void) LARD_SECTION;
00069 static void _PalmFini(void) LARD_SECTION;
00070 static void doPocketCityOpen(FormPtr form) LARD_SECTION;
00071 
00072 static void buildSilkList(void);
00073 static Int16 vkDoEvent(UInt16 key);
00074 static void UIDoQuickList(void);
00075 static void UIPopUpExtraBuildList(void);
00076 static void CleanUpExtraBuildForm(void);
00077 static FieldType * UpdateDescription(Int16 sel);
00078 
00079 static void _UIGetFieldToBuildOn(Int16 x, Int16 y);
00080 static Err RomVersionCompatible(UInt32 requiredVersion, UInt16 launchFlags);
00081 static void EventLoop(void);
00082 static void cycleSpeed(void);
00083 static void DoAbout(void) LARD_SECTION;
00084 static void CheckTextClick(Coord x, Coord y);
00085 static Int16 doButtonEvent(ButtonEvent key);
00086 static Int16 speedOffset(void);
00087 static void UISetSelectedBuildItem(BuildCode item);
00088 static void ClearScrolling(void);
00089 static void SetScrolling(void);
00090 static UInt16 IsScrolling(void);
00091 
00092 #if defined(SONY_CLIE)
00093 static void HoldHook(UInt32);
00094 #endif
00095 
00096 #if defined(HRSUPPORT)
00097 static void toolBarCheck(Coord);
00098 static void UIPaintToolBar(void);
00099 static void freeToolbarBitmap(void);
00100 static void pcResizeDisplay(FormPtr form, Int16 hOff, Int16 vOff, Boolean draw);
00101 #else
00102 #define freeToolbarBitmap()
00103 #define pcResizeDisplay(X,Y,A,B)
00104 #endif
00105 
00106 /* Collects what would otherwise be several variables */
00107 static UInt16 IsBuilding(void);
00108 static void SetBuilding(void);
00109 static void SetNotBuilding(void);
00110 static void SetDeferDrawing(void);
00111 static void SetDrawing(void);
00112 static UInt16 IsDeferDrawing(void);
00113 
00114 static void performPaintDisplay(void);
00115 
00116 void
00117 ResGetString(UInt16 index, char *buffer, UInt16 length)
00118 {
00119         if (NULL == SysStringByIndex(resstrings_base, index, buffer, length)) {
00120                 /* XXX: Error here ! */
00121         }
00122 }
00123 
00124 /*
00125  * The PilotMain routine.
00126  * Needed by all palm applications.
00127  * It checks the rom version and throws out to the user of it's too old.
00128  * Handles the auto-saving of the application at the end.
00129  */
00130 UInt32
00131 PilotMain(UInt16 cmd, MemPtr cmdPBP, UInt16 launchFlags)
00132 {
00133         UInt16 error;
00134         Int16 pir;
00135 
00136         switch (cmd) {
00137         case sysAppLaunchCmdNormalLaunch:
00138                 break;
00139         case sysAppLaunchCmdGoTo:
00140                 break;
00141         case sysAppLaunchCmdSystemReset:
00142                 if (((SysAppLaunchCmdSystemResetType *)cmdPBP)->createDefaultDB)
00143                         BeamRegister();
00144                 return (0);
00145         case sysAppLaunchCmdExgAskUser:
00146                 if (launchFlags & sysAppLaunchFlagSubCall) {
00147                         ((ExgAskParamPtr)cmdPBP)->result = exgAskOk;
00148                 }
00149                 return (0);
00150                 break;
00151         case sysAppLaunchCmdExgReceiveData:
00152                 if (errNone == BeamReceive((ExgSocketPtr)cmdPBP)) {
00153                         if (launchFlags & sysAppLaunchFlagSubCall) {
00154                                 if (IsGameInProgress())
00155                                         SaveGameByName(game.cityname);
00156                                 UILoadAutoGame();
00157                                 FrmGotoForm(formID_pocketCity);
00158                         } else {
00159                                 ((ExgSocketPtr)cmdPBP)->goToCreator =
00160                                     GetCreatorID();
00161                         }
00162                 }
00163                 return (0);
00164                 break;
00165         default:
00166                 return (0);
00167                 break;
00168         }
00169 
00170         error = RomVersionCompatible(
00171             sysMakeROMVersion(3, 5, 0, sysROMStageRelease, 0), launchFlags);
00172 
00173         BeamRegister();
00174 
00175         if (error)
00176                 return (error);
00177 
00178         WriteLog("Starting Pocket City\n");
00179         if (0 != (pir = _PalmInit())) {
00180                 WriteLog("Init Didn't Happen right [%d]\n", (int)pir);
00181                 _PalmFini();
00182                 return (1);
00183         }
00184 
00185         PCityMain();
00186         if (-1 != UILoadAutoGame()) {
00187                 FrmGotoForm(formID_pocketCity);
00188         } else {
00189                 FrmGotoForm(formID_files);
00190         }
00191 
00192         EventLoop();
00193 
00194         if (IsGameInProgress()) {
00195                 UISaveAutoGame();
00196         }
00197 
00198         PCityShutdown();
00199 
00200         _PalmFini();
00201         return (0);
00202 }
00203 
00204 static
00205 FormEventHandlerType *id2handler[] = {
00206         hPocketCity, /* formID_pocketCity */
00207         hBudget, /* formID_budget */
00208         hMap , /* formID_map */
00209         hFiles, /* formID_files */
00210         hFilesNew, /* formID_filesNew */
00211         hQuickList, /* formID_quickList */
00212         hExtraList, /* formID_extraBuild */
00213         hOptions, /* formID_options */
00214         hButtonConfig, /* formID_ButtonConfig */
00215         hQuery /* formID_Query */
00216 };
00217 #define IDARLEN (sizeof (id2handler) / sizeof (id2handler[0]))
00218 
00219 static FormEventHandlerType *
00220 gitForm(UInt16 formID)
00221 {
00222         if (formID < 1000)
00223                 return (NULL);
00224         formID -= 1000;
00225         if (formID > (IDARLEN - 1))
00226                 return (NULL);
00227         return (id2handler[formID]);
00228 }
00229 
00230 
00231 /*
00232  * Event loop for application level form events.
00233  * These are events that are not dealt with by the main event loop.
00234  * Returns true if the event has been handled, false otherwise.
00235  */
00236 static Boolean
00237 AppEvent(EventPtr event)
00238 {
00239         static UInt16 oldFormID = ~((UInt16)0);
00240         FormPtr form;
00241         UInt16 formID;
00242         FormEventHandlerType *fh;
00243 
00244         if (event->eType == frmLoadEvent) {
00245                 formID = event->data.frmLoad.formID;
00246                 WriteLog("Main::frmLoadEvent: %d -> %d\n", (int)oldFormID,
00247                     (int)formID);
00248                 oldFormID = formID;
00249                 form = FrmInitForm(formID);
00250                 FrmSetActiveForm(form);
00251                 fh = gitForm(formID);
00252                 if (fh != NULL)
00253                         FrmSetEventHandler(form, fh);
00254                 return (true);
00255         }
00256 
00257         if (event->eType == winExitEvent) {
00258                 if (event->data.winExit.exitWindow ==
00259                     (WinHandle)FrmGetFormPtr(formID_pocketCity)) {
00260                         WriteLog("Setting drawing to 0\n");
00261                         SetDeferDrawing();
00262                 }
00263                 return (true);
00264         }
00265 
00266         if (event->eType == winEnterEvent) {
00267                 if (event->data.winEnter.enterWindow ==
00268                     (WinHandle) FrmGetFormPtr(formID_pocketCity) &&
00269                     event->data.winEnter.enterWindow ==
00270                     (WinHandle)FrmGetFirstForm()) {
00271                         WriteLog("Setting drawing to 1\n");
00272                         SetDrawing();
00273                         RedrawAllFields(); /* update screen after menu etc. */
00274                 } else {
00275                         WriteLog("Setting drawing to 0\n");
00276                         SetDeferDrawing();
00277                 }
00278                 /* pass to form */
00279                 return (false);
00280         }
00281         return (false);
00282 }
00283 
00284 #if defined(LOGGING)
00285 static char *cstrings[] = {
00286         "bc_count_residential", 
00287         "bc_value_residential", 
00288         "bc_count_commercial", 
00289         "bc_value_commercial", 
00290         "bc_count_industrial", 
00291         "bc_value_industrial", 
00292         "bc_count_roads", 
00293         "bc_value_roads", 
00294         "bc_count_trees", 
00295         "bc_value_trees", 
00296         "bc_water", 
00297         "bc_coalplants", 
00298         "bc_nuclearplants", 
00299         "bc_powerlines", 
00300         "bc_waterpumps", 
00301         "bc_waterpipes", 
00302         "bc_waste", 
00303         "bc_radioactive", /*< count of radioactive areas */
00304         "bc_fire", 
00305         "bc_fire_stations", 
00306         "bc_police_departments", 
00307         "bc_military_bases", 
00308         "bc_cashflow", 
00309         "bc_pollution", 
00310         "bc_crime" 
00311 };
00312 #endif /* bcstrings */
00313 /*
00314  * Main event loop routine.
00315  * The standard one ... loop until the game terminates.
00316  */
00317 static void
00318 EventLoop(void)
00319 {
00320         EventType event;
00321         UInt32 timeTemp;
00322         UInt16 err;
00323 
00324         for (;;) {
00325                 EvtGetEvent(&event, (Int32)10);
00326                 if (event.eType == appStopEvent) break;
00327 
00328                 if (event.eType == keyDownEvent)
00329                         if (FrmDispatchEvent(&event)) continue;
00330 
00331                 if (SysHandleEvent(&event)) continue;
00332 
00333                 if (MenuHandleEvent((MenuBarType *)0, &event, &err)) continue;
00334 
00335                 if (AppEvent(&event)) continue;
00336 
00337                 if (FrmDispatchEvent(&event)) continue;
00338 
00339                 /*
00340                  * if we're faffing around in the savegame dialogs then
00341                  * we're not actually playing the game.
00342                  */
00343                 if (!IsGameInProgress()) continue;
00344 
00345                 /* Game is fully formally paused ? */
00346                 if (!IsGamePlaying())
00347                         continue;
00348 
00349                 if (IsBuilding()) continue;
00350 
00351                 if (IsScrolling()) {
00352                         if ((event.eType != keyDownEvent)) {
00353                                 if (KeyCurrentState() == 0) {
00354                                         ClearScrolling();
00355                                 } else {
00356                                         continue;
00357                                 }
00358                         }
00359                 }
00360 
00361                 /* the almighty homemade >>"multithreader"<< */
00362                 if (getLoopSeconds() != SPEED_PAUSED) {
00363                         if (simState == 0) {
00364                                 timeTemp = TimGetSeconds();
00365                                 if (timeTemp >=
00366                                     timeStamp + getLoopSeconds()) {
00367                                         simState = 1;
00368                                         timeStamp = timeTemp;
00369                                 }
00370                         } else  {
00371                                 simState = Sim_DoPhase(simState);
00372                                 if (simState == 0) {
00373                                         RedrawAllFields();
00374                                 }
00375                         }
00376                 }
00377 
00378                 /*
00379                  * Do a disaster update every 2 seconds.
00380                  * This is only disabled when difficulty is at easy and
00381                  * game is paused.
00382                  */
00383 
00384                 if (getDifficultyLevel() == 0 &&
00385                     getLoopSeconds() == SPEED_PAUSED) {
00386                         continue;
00387                 }
00388 
00389                 timeTemp = TimGetSeconds();
00390 
00391                 if (timeTemp >= (timeStampDisaster + SIM_GAME_LOOP_DISASTER)) {
00392 #ifdef LOGGING
00393                         Int16 q, pc = 0;
00394 #endif
00395                         MoveAllObjects();
00396 #ifdef LOGGING
00397                         /*
00398                          * This will print the BuildCount array
00399                          * don't forget to keep an eye on it
00400                          * in the log - should be up-to-date
00401                          * AT ALL TIMES!
00402                          */
00403                         for (q = 0; q < bc_tail; q++)
00404                                 if ((long)vgame.BuildCount[q] != 0) {
00405                                         WriteLogX("%s=%li ", cstrings[q], 
00406                                             (long)vgame.BuildCount[q]);
00407                                         pc++;
00408                                         if (pc == 3) {
00409                                                 pc = 0;
00410                                                 WriteLogX("\n");
00411                                         }
00412                                 }
00413                         WriteLogX("\n");
00414 #endif
00415                         if (UpdateDisasters()) {
00416                                 RedrawAllFields();
00417                         }
00418                         timeStampDisaster = timeTemp;
00419                         /*
00420                          * TODO: This would be the place to create animation...
00421                          * perhaps with a second offscreen window for the
00422                          * second animation frame of each zone
00423                          * Then swap the winZones between the two,
00424                          * and do the RedrawAllFields() from above here
00425                          */
00426                 }
00427         }
00428 }
00429 
00433 static const struct _bmphandles {
00434         WinHandle *handle; 
00435         const DmResID resourceID; 
00436 } handles[] = {
00437         { &winZones, (DmResID)bitmapID_zones },
00438         { &winMonsters, (DmResID)bitmapID_monsters },
00439         { &winUnits, (DmResID)bitmapID_units },
00440 /* XXX: { &winButtons, (DmResID)bitmapID_buttons }, */
00441         { &winSpeeds, (DmResID)bitmapID_Speed }
00442 };
00443 
00444 static DmOpenRef _refTiles;
00445 /*
00446  * Set up the game in relation to the screen mode.
00447  */
00448 static Int16
00449 _PalmInit(void)
00450 {
00451         UInt32          depth;
00452         Int16           err;
00453         UInt16          i;
00454         MemHandle       bitmaphandle;
00455         BitmapPtr       bitmap;
00456         //BitmapPtrV3   bmpv3;
00457         WinHandle       winHandle = NULL;
00458         WinHandle       privhandle;
00459         UInt16          prefSize;
00460         Int16           rv = 0;
00461         Coord           width;
00462         Coord           height;
00463 
00464         timeStamp = TimGetSeconds();
00465         timeStampDisaster = timeStamp;
00466 
00467         prefSize = sizeof (AppConfig_t);
00468         err = PrefGetAppPreferences(GetCreatorID(), 0, &gameConfig, &prefSize,
00469             true);
00470 
00471         /* section (2) */
00472 
00473         _refTiles = DmOpenDatabaseByTypeCreator(TILEDBTYPE, GetCreatorID(),
00474             dmModeReadOnly);
00475 
00476         if (_refTiles == 0) {
00477                 FrmAlert(alertID_tilesMissing);
00478                 return (2);
00479         }
00480 
00481         /* section (3) */
00482         StartSilk();
00483 
00484         /* set screen mode to colors if supported */
00485         if (Is35ROM()) {  /* must be v3.5+ for some functions in here */
00486                 WinScreenMode(winScreenModeGetSupportedDepths, 0, 0, &depth, 0);
00487                 if ((depth & (1 << (8-1))) != 0) {
00488                         /* 8bpp (color) is supported */
00489                         changeDepthRes(8, true);
00490                 } else if ((depth & (1 << (4-1))) != 0) {
00491                         /* 4bpp (greyscale) is supported */
00492                         changeDepthRes(4, true);
00493                 }
00494                 /* falls through if you've no color */
00495         }
00496 
00497         /* The 'playground'... built by the size of the screen */
00498         rPlayGround.topLeft.x = XOFFSET;
00499         rPlayGround.topLeft.y = YOFFSET; /* Padding for the menubar */
00500         rPlayGround.extent.x = GETWIDTH();
00501         rPlayGround.extent.y = GETHEIGHT() - 2*16; /* Space on the bottom */
00502 
00503         /* section (4) */
00504 
00505         /* Section (5); */
00506         /* create an offscreen window, and copy the zones to be used later */
00507         for (i = 0; i < (sizeof (handles) / sizeof (handles[0])); i++) {
00508                 bitmaphandle = DmGetResource(TBMP, handles[i].resourceID);
00509                 if (bitmaphandle == NULL) {
00510                         WriteLog("could not get bitmap handle[%d:%ld]\n",
00511                             (int)i, (long)handles[i].resourceID);
00512                         rv = 5;
00513                         goto returnWV;
00514                 }
00515                 bitmap = (BitmapPtr)MemHandleLock(bitmaphandle);
00516                 if (bitmap == NULL) {
00517                         WriteLog("MemHandleLock Failed handle[%d:%ld]\n",
00518                             (int)i, (long)handles[i].resourceID);
00519                         DmReleaseResource(bitmaphandle);
00520                         rv = 5;
00521                         goto returnWV;
00522                 }
00523                 compatBmpGetDimensions(bitmap, &width, &height, NULL);
00524 
00525                 privhandle = _WinCreateOffscreenWindow(width,
00526                     height, nativeFormat, (UInt16 *)&err);
00527                 if (err != errNone) {
00528                         /* TODO: alert user, and quit program */
00529                         WriteLog("Offscreen window for zone[%d] failed\n",
00530                             (int)i);
00531                         MemHandleUnlock(bitmaphandle);
00532                         DmReleaseResource(bitmaphandle);
00533                         rv = 5;
00534                         goto returnWV;
00535                 }
00536                 if (winHandle == NULL)
00537                         winHandle = WinSetDrawWindow(privhandle);
00538                 else
00539                         WinSetDrawWindow(privhandle);
00540 #if defined(HRSUPPORT)
00541                 if (IsScaleModes()) StartHiresDraw();
00542 #endif
00543                 _WinDrawBitmap(bitmap, 0, 0);
00544 #if defined(HRSUPPORT)
00545                 if (IsScaleModes()) EndHiresDraw();
00546 #endif
00547                 MemHandleUnlock(bitmaphandle);
00548                 DmReleaseResource(bitmaphandle);
00549                 *(handles[i].handle) = privhandle;
00550         }
00551 
00552         /* clean up */
00553 
00554         hookHoldSwitch(HoldHook);
00555         /* load application configuration */
00556         buildSilkList();
00557 
00558 returnWV:
00559         if (winHandle) WinSetDrawWindow(winHandle);
00560 
00561         return (rv);
00562 }
00563 
00564 /*
00565  * Clean up the application.
00566  * Save the button configuration and delete any windows that have been
00567  * allocated.
00568  * Everything is done in reverse order from having them done in the init.
00569  */
00570 static void
00571 _PalmFini(void)
00572 {
00573         UInt16 i;
00574 
00575         unhookHoldSwitch();
00576         freeToolbarBitmap();
00577 
00578         PurgeWorld();
00579         /* clean up handles */
00580         for (i = 0; i < (sizeof (handles) / sizeof (handles[0])); i++) {
00581                 if (*(handles[i].handle) != NULL)
00582                         WinDeleteWindow(*(handles[i].handle), 0);
00583         }
00584         restoreDepthRes();
00585         if (_refTiles != 0) DmCloseDatabase(_refTiles);
00586         PrefSetAppPreferences(GetCreatorID(), 0, CONFIG_VERSION,
00587             &gameConfig, sizeof (AppConfig_t), true);
00588         /* Close the forms */
00589         FrmCloseAllForms();
00590         CloseMyDB();
00591 
00592         EndSilk();
00593 }
00594 
00595 static void
00596 DoLoadAlert(void)
00597 {
00598         switch (FrmAlert(alertID_loadGame)) {
00599         case 0: /* save game */
00600                 UISaveMyCity();
00601                 UIClearAutoSaveSlot();
00602                 FrmGotoForm(formID_files);
00603                 break;
00604         case 1: /* don't save */
00605                 UIClearAutoSaveSlot();
00606                 FrmGotoForm(formID_files);
00607                 break;
00608         default: /* cancel */
00609                 break;
00610         }
00611 }
00612 
00613 static Boolean
00614 DoPCityMenuProcessing(UInt16 itemID)
00615 {
00616         Boolean handled = false;
00617 
00618         switch (itemID) {
00619                 /* First menu ... game */
00620         case menuitemID_loadGame:
00621                 DoLoadAlert();
00622                 handled = true;
00623                 break;
00624         case menuitemID_saveGame:
00625                 if (FrmAlert(alertID_saveGame) == 0) {
00626                         UISaveMyCity();
00627                 }
00628                 handled = true;
00629                 break;
00630         case menuitemID_Budget:
00631                 FrmGotoForm(formID_budget);
00632                 handled = true;
00633                 break;
00634         case menuitemID_Map:
00635                 FrmGotoForm(formID_map);
00636                 handled = true;
00637                 break;
00638         case menuitemID_Configuration:
00639                 FrmGotoForm(formID_options);
00640                 handled = true;
00641                 break;
00642 
00643         case menuitemID_Buttons:
00644                 FrmGotoForm(formID_ButtonConfig);
00645                 handled = true;
00646                 break;
00647 
00648         case menuitemID_ForceResupply:
00649                 AddGridUpdate(GRID_ALL);
00650                 handled = true;
00651                 break;
00652 
00653                 /* next menu ... build */
00654 
00655         case mi_removeDefence:
00656                 RemoveAllDefence();
00657                 handled = true;
00658                 break;
00659 
00660                 /* for a reason ... */
00661         case mi_buildExtra:
00662                 UIPopUpExtraBuildList();
00663                 handled = true;
00664                 break;
00665 
00666         case mi_CauseFire:
00667         case mi_CauseMeltDown:
00668         case mi_CauseMonster:
00669         case mi_CauseDragon:
00670         case mi_CauseMeteor:
00671                 DoSpecificDisaster((disaster_t)(itemID - mi_CauseFire +
00672                             diFireOutbreak));
00673                 handled = true;
00674                 break;
00675 
00676                 /* next menu ... speed */
00677 
00678         case menuID_SlowSpeed:
00679                 setLoopSeconds(SPEED_SLOW);
00680                 addGraphicUpdate(gu_speed);
00681                 handled = true;
00682                 break;
00683         case menuID_MediumSpeed:
00684                 setLoopSeconds(SPEED_MEDIUM);
00685                 addGraphicUpdate(gu_speed);
00686                 handled = true;
00687                 break;
00688         case menuID_FastSpeed:
00689                 setLoopSeconds(SPEED_FAST);
00690                 addGraphicUpdate(gu_speed);
00691                 handled = true;
00692                 break;
00693         case menuID_TurboSpeed:
00694                 setLoopSeconds(SPEED_TURBO);
00695                 addGraphicUpdate(gu_speed);
00696                 handled = true;
00697                 break;
00698         case menuID_PauseSpeed:
00699                 setLoopSeconds(SPEED_PAUSED);
00700                 addGraphicUpdate(gu_speed);
00701                 handled = true;
00702                 break;
00703 
00704                 /* next menu ... help */
00705 
00706         case menuitemID_about:
00707                 DoAbout();
00708                 handled = true;
00709                 break;
00710         case menuitemID_tips:
00711                 FrmHelp(StrID_tips);
00712                 handled = true;
00713                 break;
00714         case menuitemID_Beam:
00715                 UISaveMyCity();
00716                 BeamCityByName(game.cityname);
00717                 break;
00718 #if defined(CHEAT) || defined(DEBUG)
00719         case menuitemID_Funny:
00720                 /*
00721                  * change this to whatever testing you're doing.
00722                  * just handy with a 'trigger' button for testing
00723                  * ie. disaters... this item is erased if you've
00724                  * not compiled with CHEAT or DEBUG
00725                  */
00726 #ifdef CHEAT
00727                 game.credits += 10000;
00728 #endif
00729 #ifdef DEBUG
00730                 MeteorDisaster(20, 20);
00731 #endif
00732                 handled = true;
00733                 break;
00734 #endif
00735         }
00736         return (handled);
00737 }
00738 
00739 static void
00740 doPocketCityOpen(FormPtr form)
00741 {
00742 #if defined(HRSUPPORT)
00743         Int16 hOff = 0, vOff = 0;
00744 #endif
00745         RectangleType rect;
00746 
00747         FrmDrawForm(form);
00748         SetSilkResizable(form, true);
00749 
00750         rect.topLeft.x = normalizeCoord(GETWIDTH()) - 2 * gameTileSize();
00751         rect.topLeft.y = normalizeCoord(GETHEIGHT()) - 2 * gameTileSize();
00752         rect.extent.x = 2 * gameTileSize();
00753         rect.extent.y = rect.extent.x;
00754 
00755         minimapPlace(&rect);
00756         minimapSetShowing(GETMINIMAPVISIBLE());
00757 
00758 #if defined(HRSUPPORT)
00759         if (collapseMove(form, CM_DEFAULT, &hOff, &vOff)) {
00760                 pcResizeDisplay(form, hOff, vOff, false);
00761         }
00762 #endif
00763         SetGameInProgress();
00764         ResumeGame();
00765         FrmDrawForm(form);
00766         SetDrawing();
00767         DrawGame(1);
00768 }
00769 
00770 /*
00771  * Handler for the main pocketCity form.
00772  * This form performs all the updates to the main game screen.
00773  */
00774 static Boolean
00775 hPocketCity(EventPtr event)
00776 {
00777         FormPtr form;
00778         Boolean handled = false;
00779         PointType minimperc;
00780 #if defined(HRSUPPORT)
00781         Boolean redraw;
00782         Int16 hOff = 0, vOff = 0;
00783 #endif
00784 
00785         switch (event->eType) {
00786         case frmOpenEvent:
00787                 form = FrmGetActiveForm();
00788                 doPocketCityOpen(form);
00789                 handled = true;
00790                 break;
00791         case frmCloseEvent:
00792                 SetSilkResizable(NULL, false);
00793                 break;
00794         case penDownEvent:
00795 
00796                 if (GETMINIMAPVISIBLE()) {
00797                         minimperc.x = event->screenX;
00798                         minimperc.y = event->screenY;
00799 
00800                         if (minimapIsTapped(&minimperc, &minimperc)) {
00801                                 Goto((UInt16)minimperc.x,
00802                                     (UInt16)minimperc.y, 1);
00803                                 handled = true;
00804                                 break;
00805                         }
00806                 }
00807                 scaleEvent(event);
00808                 if (RctPtInRectangle(event->screenX, event->screenY,
00809                     &rPlayGround)) {
00810                         /* click was on the playground */
00811                         _UIGetFieldToBuildOn(event->screenX, event->screenY);
00812                         handled = true;
00813                         break;
00814                 }
00815                 if (event->screenY < 12) {
00816                         handled = true;
00817                         if (event->screenX >= (GETWIDTH() - 12)) {
00818                                 /* click was on change speed */
00819                                 cycleSpeed();
00820                                 addGraphicUpdate(gu_speed);
00821                                 break;
00822                         }
00823                         if (event->screenX < 12) {
00824                                 /* click was on toggle production */
00825                                 if (nSelectedBuildItem == Be_Bulldozer) {
00826                                         UISetSelectedBuildItem(nPreviousBuildItem);
00827                                 } else {
00828                                         nPreviousBuildItem = nSelectedBuildItem;
00829                                         UISetSelectedBuildItem(Be_Bulldozer);
00830                                 }
00831                                 addGraphicUpdate(gu_buildicon);
00832                                 break;
00833                         }
00834 #if defined(HRSUPPORT)
00835                         if (isHires())
00836                                 toolBarCheck(event->screenX);
00837 #endif
00838                         /* check for other 'penclicks' here */
00839                 }
00840 
00841                 CheckTextClick(event->screenX, event->screenY);
00842 
00843                 break;
00844         case penMoveEvent:
00845                 scaleEvent(event);
00846                 if (RctPtInRectangle(event->screenX, event->screenY,
00847                     &rPlayGround)) {
00848                         _UIGetFieldToBuildOn(event->screenX, event->screenY);
00849                         SetBuilding();
00850                         handled = true;
00851                 }
00852                 break;
00853         case penUpEvent:
00854                 SetNotBuilding();
00855                 timeStamp = TimGetSeconds() - getLoopSeconds() + 2;
00856                 /* so the simulation routine won't kick in right away */
00857                 timeStampDisaster = timeStamp - getLoopSeconds() + 1;
00858                 handled = true;
00859                 break;
00860         case menuEvent:
00861                 WriteLog("Menu Item: %d\n", (int)event->data.menu.itemID);
00862                 handled = DoPCityMenuProcessing(event->data.menu.itemID);
00863 
00864         case keyDownEvent:
00865                 handled = (Boolean)vkDoEvent(event->data.keyDown.chr);
00866                 break;
00867         case keyUpEvent:
00868                 handled = true;
00869 #if defined(HRSUPPORT)
00870         case winDisplayChangedEvent:
00871 #if defined(SONY_CLIE)
00872         case vchrSilkResize:
00873 #endif
00874                 redraw = collapseMove(FrmGetActiveForm(), CM_DEFAULT,
00875                     &hOff, &vOff);
00876                 if (redraw)
00877                         pcResizeDisplay(FrmGetActiveForm(), hOff, vOff, redraw);
00878                 handled = true;
00879                 break;
00880 #endif
00881         default:
00882                 break;
00883         }
00884         performPaintDisplay();
00885 
00886         return (handled);
00887 }
00888 
00889 /*
00890  * Do the about dialog
00891  */
00892 static void
00893 DoAbout(void)
00894 {
00895         MemHandle vh;
00896         MemPtr vs = NULL;
00897         MemHandle bh;
00898         MemPtr bs = NULL;
00899         const UInt8 *qq = (const UInt8 *)"??";
00900 
00901         vh = DmGetResource(TVER, 1);
00902         if (vh != NULL) vs = MemHandleLock(vh);
00903         if (vh == NULL) vs = (MemPtr)qq;
00904         bh = DmGetResource(TSTR, StrID_build);
00905         if (bh != NULL) bs = MemHandleLock(bh);
00906         if (bh == NULL) bs = (MemPtr)qq;
00907         FrmCustomAlert(alertID_about, (const Char *)vs, (const Char *)bs, NULL);
00908         if (vh) {
00909                 MemPtrUnlock(vs);
00910                 DmReleaseResource(vh);
00911         }
00912         if (bh) {
00913                 MemPtrUnlock(bs);
00914                 DmReleaseResource(bh);
00915         }
00916 }
00917 
00918 void
00919 UIPostLoadGame(void)
00920 {
00921         clearProblemFlags();
00922 }
00923 
00924 /*
00925  * Go to one of the Budget and map forms.
00926  * Only if we're not already at that form to begin with.
00927  */
00928 void
00929 UIGotoForm(Int16 n)
00930 {
00931         UInt16 formid = FrmGetActiveFormID();
00932         switch (n) {
00933         case 0:
00934                 if (formid != formID_budget) FrmGotoForm(formID_budget);
00935                 break;
00936         case 1:
00937                 if (formid != formID_map) FrmGotoForm(formID_map);
00938                 break;
00939         default:
00940                 break;
00941         }
00942 }
00943 
00944 /*
00945  * Pop up the extra build list.
00946  * Contains items that are not in the quicklist tool bar.
00947  * This is the only choice for Pre-PalmOS 3.5 users, as they
00948  * can't have bitmapped buttons.
00949  */
00950 void
00951 UIPopUpExtraBuildList(void)
00952 {
00953         FormType * form;
00954         UInt16 sfe;
00955         static Char **lp;
00956         UInt16 poplen;
00957 
00958         form = FrmInitForm(formID_extraBuild);
00959         FrmSetEventHandler(form, hExtraList);
00960         lp = FillStringList(strID_Items, &poplen);
00961         LstSetListChoices((ListPtr)GetObjectPtr(form, listID_extraBuildList),
00962             lp, (Int16)poplen);
00963 
00964         UpdateDescription(0);
00965         sfe = FrmDoDialog(form);
00966 
00967         FreeStringList(lp);
00968 
00969         switch (sfe) {
00970         case buttonID_extraBuildSelect:
00971                 /* List entries must match entries in BuildCode 0 .. */
00972                 UISetSelectedBuildItem((BuildCode)LstGetSelection(
00973                     (ListPtr)GetObjectPtr(form, listID_extraBuildList)));
00974                 break;
00975         case buttonID_extraBuildFireMen:
00976                 UISetSelectedBuildItem(Be_Defence_Fire);
00977                 break;
00978         case buttonID_extraBuildPolice:
00979                 UISetSelectedBuildItem(Be_Defence_Police);
00980                 break;
00981         case buttonID_extraBuildMilitary:
00982                 UISetSelectedBuildItem(Be_Defence_Military);
00983                 break;
00984         default:
00985                 break;
00986         }
00987 
00988         WriteLog("sfe = %u, bi = %u\n", (unsigned int)sfe,
00989             (unsigned int)nSelectedBuildItem);
00990 
00991         CleanUpExtraBuildForm();
00992         FrmDeleteForm(form);
00993 }
00994 
00995 /*
00996  * Update the description of the item in the extra build list.
00997  * XXX: Use MemHandles instead?
00998  */
00999 FieldPtr
01000 UpdateDescription(Int16 sel)
01001 {
01002         Int16 cost;
01003         Char *temp = (Char *)MemPtrNew(256);
01004         Int16 *ch;
01005         MemHandle mh;
01006         FormType *fp;
01007         FieldPtr ctl;
01008 
01009         fp = FrmGetFormPtr(formID_extraBuild);
01010         ctl = (FieldPtr)GetObjectPtr(fp, labelID_extraBuildDescription);
01011 
01012         SysStringByIndex(strID_Descriptions, (UInt16)sel, temp, (UInt16)256);
01013         FldSetTextPtr(ctl, temp);
01014         FldRecalculateField(ctl, true);
01015 
01016         mh = DmGetResource('wrdl', wdlID_Costs);
01017         if (mh != NULL) {
01018                 ch = (Int16 *)MemHandleLock(mh);
01019                 cost = ch[sel+1];
01020                 MemHandleUnlock(mh);
01021                 DmReleaseResource(mh);
01022         } else {
01023                 cost = -1;
01024         }
01025         temp = (Char *)MemPtrNew(16);
01026         ctl = (FieldPtr)GetObjectPtr(fp, labelID_extraBuildPrice);
01027         StrPrintF(temp, "%d", cost);
01028         FldSetTextPtr(ctl, temp);
01029         FldRecalculateField(ctl, true);
01030 
01031         return (ctl);
01032 }
01033 
01034 /*
01035  * Release any memory allocated to the
01036  * extra build list form.
01037  */
01038 void
01039 CleanUpExtraBuildForm(void)
01040 {
01041         FormPtr form = FrmGetFormPtr(formID_extraBuild);
01042         void * ptr = (void*)FldGetTextPtr(
01043             (FieldPtr)GetObjectPtr(form, labelID_extraBuildDescription));
01044         if (ptr != 0)
01045                 MemPtrFree(ptr);
01046         ptr = (void*)FldGetTextPtr((FieldPtr)GetObjectPtr(form,
01047                     labelID_extraBuildPrice));
01048         if (ptr != 0)
01049                 MemPtrFree(ptr);
01050 }
01051 
01052 /*
01053  * Handler for the Extra Build list form.
01054  * Doesn't clean up the description items;
01055  * that's done in UIPopupExtraBuildList()
01056  */
01057 static Boolean
01058 hExtraList(EventPtr event)
01059 {
01060         FormPtr form;
01061         void *ptr, *ptr2;
01062         Boolean handled = false;
01063 
01064         switch (event->eType) {
01065         case frmOpenEvent:
01066                 PauseGame();
01067                 form = FrmGetActiveForm();
01068                 WriteLog("open hExtraList\n");
01069                 FrmDrawForm(form);
01070                 handled = true;
01071                 break;
01072         case frmCloseEvent:
01073                 WriteLog("close hExtraList\n");
01074                 break;
01075         case lstSelectEvent:
01076                 WriteLog("list selection\n");
01077                 if ((event->data.lstSelect.listID) == listID_extraBuildList) {
01078                         /* clear old mem */
01079                         FormPtr form = FrmGetActiveForm();
01080                         ptr = (void *)FldGetTextPtr((FieldPtr)GetObjectPtr(form,
01081                                     labelID_extraBuildDescription));
01082                         ptr2 = (void *)FldGetTextPtr(
01083                             (FieldPtr)GetObjectPtr(form,
01084                                 labelID_extraBuildPrice));
01085                         FldDrawField(
01086                             UpdateDescription(event->data.lstSelect.selection));
01087                         if (ptr != 0)
01088                                 MemPtrFree(ptr);
01089                         if (ptr2 != 0)
01090                                 MemPtrFree(ptr2);
01091                         handled = true;
01092                 }
01093                 break;
01094         case keyDownEvent:
01095                 switch (event->data.keyDown.chr) {
01096                 case vchrCalc:
01097                         CtlHitControl((ControlPtr)GetObjectPtr(
01098                             FrmGetActiveForm(), buttonID_extraBuildCancel));
01099                         handled = true;
01100                         break;
01101                 case pageUpChr:
01102                         LstScrollList((ListPtr)GetObjectPtr(FrmGetActiveForm(),
01103                             listID_extraBuildList), winUp, 4);
01104                         handled = true;
01105                         break;
01106                 case pageDownChr:
01107                         LstScrollList((ListPtr)GetObjectPtr(FrmGetActiveForm(),
01108                             listID_extraBuildList), winDown, 4);
01109                         handled = true;
01110                         break;
01111                 }
01112         default:
01113                 break;
01114         }
01115 
01116         return (handled);
01117 }
01118 
01119 /*
01120  * Pop up the quick list.
01121  * Contains most of the commonly used icons in one place.
01122  * Will pop up the extra build list if the machine is Pre Palmos 3.5 as
01123  * it can't do bitmapped buttons.
01124  */
01125 void
01126 UIDoQuickList(void)
01127 {
01128         FormType * ftList;
01129 
01130         if (Is35ROM()) {
01131                 ftList = FrmInitForm(formID_quickList);
01132                 FrmSetEventHandler(ftList, hQuickList);
01133                 UISetSelectedBuildItem((BuildCode)(FrmDoDialog(ftList) -
01134                     gi_buildBulldoze));
01135 
01136                 if (nSelectedBuildItem >= OFFSET_EXTRA)
01137                         UIPopUpExtraBuildList();
01138                 addGraphicUpdate(gu_buildicon);
01139                 FrmDeleteForm(ftList);
01140         } else {
01141                 /*
01142          * darn, I hate that 3.1 - can't do bitmapped buttons.
01143          * I'll just throw the ExtraBuildList up
01144          */
01145                 UIPopUpExtraBuildList();
01146         }
01147 }
01148 
01149 /*
01150  * Handler for the Quick List form
01151  */
01152 static Boolean
01153 hQuickList(EventPtr event)
01154 {
01155         FormPtr form;
01156         Boolean handled = false;
01157 
01158         switch (event->eType) {
01159         case frmOpenEvent:
01160                 WriteLog("open quicklist\n");
01161                 PauseGame();
01162                 form = FrmGetActiveForm();
01163                 FrmDrawForm(form);
01164                 handled = true;
01165                 break;
01166         case frmCloseEvent:
01167                 WriteLog("close quicklist\n");
01168                 break;
01169         case keyDownEvent:
01170                 WriteLog("Key down\n");
01171                 switch (event->data.keyDown.chr) {
01172                 case vchrCalc:
01173                         /*
01174                          * simulate we pushed the bulldozer.
01175                          */
01176                         form = FrmGetActiveForm();
01177                         CtlHitControl((ControlPtr)GetObjectPtr(form,
01178                             gi_buildBulldoze));
01179                         handled = true;
01180                         break;
01181                 }
01182                 break;
01183         case penUpEvent:
01184                 if (event->screenY < 0) {
01185                         form = FrmGetActiveForm();
01186                         CtlHitControl((ControlPtr)GetObjectPtr(form,
01187                             gi_buildBulldoze));
01188                         handled = true;
01189                 }
01190                 break;
01191         default:
01192                 break;
01193         }
01194 
01195         return (handled);
01196 }
01197 
01198 /*
01199  * Get the selected build item.
01200  */
01201 BuildCode
01202 UIGetSelectedBuildItem(void)
01203 {
01204         return (nSelectedBuildItem);
01205 }
01206 
01207 /*
01208  * initialize graphics
01209  */
01210 void
01211 UIInitGraphic(void)
01212 {
01213         setGameTileSize(16);
01214         setMapTileSize(4);
01215 }
01216 
01217 /*
01218  * Save the selected build item.
01219  */
01220 static void
01221 UISetSelectedBuildItem(BuildCode item)
01222 {
01223         nSelectedBuildItem = item;
01224 }
01225 
01226 /* is Building logic and data */
01227 static UInt16 __state;
01228 
01229 /*
01230  * First the Macro.
01231  * You Define the Bit, Clearer, Setter and Tester
01232  * of the Bit field you care about.
01233  * If you need more than 16 bits (0..15) then change the return type here and
01234  * in any of the entries shared in the header file.
01235  */
01236 #define BUILD_STATEBITACCESSOR(BIT, CLEARER, SETTER, TESTER, VISIBILITY) \
01237 VISIBILITY void \
01238 CLEARER(void) \
01239 { \
01240         __state &= ~((UInt16)1<<(BIT)); \
01241 } \
01242 VISIBILITY void \
01243 SETTER(void) \
01244 { \
01245         __state |= ((UInt16)1<<(BIT)); \
01246 } \
01247 VISIBILITY UInt16 \
01248 TESTER(void) \
01249 { \
01250         return (__state & ((UInt16)1<<(BIT))); \
01251 }
01252 
01253 #define GLOBAL
01254 
01255 BUILD_STATEBITACCESSOR(0, PauseGame, ResumeGame, IsGamePlaying, GLOBAL)
01256 BUILD_STATEBITACCESSOR(1, SetNotBuilding, SetBuilding, IsBuilding, static)
01257 BUILD_STATEBITACCESSOR(2, SetGameNotInProgress, SetGameInProgress,
01258     IsGameInProgress, GLOBAL)
01259 BUILD_STATEBITACCESSOR(3, SetLowMoneyNotShown, SetLowMoneyShown, \
01260     IsLowMoneyShown, static)
01261 BUILD_STATEBITACCESSOR(4, SetOutMoneyNotShown, SetOutMoneyShown, \
01262     IsOutMoneyShown, static)
01263 BUILD_STATEBITACCESSOR(5, SetLowPowerNotShown, SetLowPowerShown, \
01264     IsLowPowerShown, static)
01265 BUILD_STATEBITACCESSOR(6, SetOutPowerNotShown, SetOutPowerShown, \
01266     IsOutPowerShown, static)
01267 BUILD_STATEBITACCESSOR(7, SetLowWaterNotShown, SetLowWaterShown, \
01268     IsLowWaterShown, static)
01269 BUILD_STATEBITACCESSOR(8, SetOutWaterNotShown, SetOutWaterShown, \
01270     IsOutWaterShown, static)
01271 BUILD_STATEBITACCESSOR(9, Clear35ROM, Set35ROM, Is35ROM, GLOBAL)
01272 BUILD_STATEBITACCESSOR(10, SetDrawing, SetDeferDrawing, IsDeferDrawing, static)
01273 BUILD_STATEBITACCESSOR(11, Clear40ROM, Set40ROM, Is40ROM, GLOBAL)
01274 BUILD_STATEBITACCESSOR(12, ClearScaleModes, SetScaleModes, IsScaleModes, GLOBAL)
01275 BUILD_STATEBITACCESSOR(13, ClearScrolling, SetScrolling, IsScrolling, static)
01276 
01277 
01280 static void
01281 ClearLowOutPowerFlags(void)
01282 {
01283         SetLowPowerNotShown();
01284         SetOutPowerNotShown();
01285 }
01286 
01290 static void
01291 ClearLowOutWaterFlags(void)
01292 {
01293         SetLowWaterNotShown();
01294         SetOutWaterNotShown();
01295 }
01296 
01300 static void
01301 ClearLowOutMoneyFlags(void)
01302 {
01303         SetLowMoneyNotShown();
01304         SetOutMoneyNotShown();
01305 }
01306 
01307 /*
01308  * Memory of what was clicked under the pen
01309  * Helps reduce the externally visible state,
01310  * and allows the query to run without having too much global access.
01311  */
01312 static UInt32 __clicker;
01313 
01314 /*
01315  * Get the item clicked on the main form last.
01316  */
01317 UInt32
01318 GetPositionClicked()
01319 {
01320         return (__clicker);
01321 }
01322 
01323 /*
01324  * Set the field value of the item clicked on the form.
01325  * Saves having to re-lookup the location in the WorldMap.
01326  */
01327 static void
01328 SetPositionClicked(UInt32 item)
01329 {
01330         __clicker = item;
01331 }
01332 
01333 /*
01334  * Check the location clicked on screen to see if it's in the build area.
01335  * If it is then either build there or perform a query.
01336  */
01337 void
01338 _UIGetFieldToBuildOn(Int16 x, Int16 y)
01339 {
01340         RectangleType rect;
01341         rect.extent.x = (Coord)(getVisibleX() * gameTileSize());
01342         rect.extent.y = (Coord)(getVisibleY() * gameTileSize());
01343         rect.topLeft.x = XOFFSET;
01344         rect.topLeft.y = YOFFSET;
01345 
01346         if (RctPtInRectangle(x, y, &rect)) {
01347                 Coord xpos = (x - XOFFSET) / gameTileSize() + getMapXPos();
01348                 Coord ypos = (y - YOFFSET) / gameTileSize() + getMapYPos();
01349                 LockZone(lz_world); // OK
01350                 SetPositionClicked(WORLDPOS(xpos, ypos));
01351                 UnlockZone(lz_world); // OK
01352                 if (UIGetSelectedBuildItem() != Be_Query)
01353                         BuildSomething((UInt16)xpos, (UInt16)ypos);
01354                 else
01355                         FrmGotoForm(formID_Query);
01356         }
01357 }
01358 
01359 void
01360 UIDisasterNotify(disaster_t disaster)
01361 {
01362         char string[512];
01363         SysStringByIndex(st_disasters, (UInt16)(disaster - diFireOutbreak), string, (UInt16)511);
01364         if (*string == '\0') StrPrintF(string, "generic disaster??");
01365 
01366         FrmCustomAlert(alertID_generic_disaster, string, 0, 0);
01367 }
01368 
01370 static struct problemtable {
01371         problem_t entry; 
01372         UInt16 (*test)(void); 
01373         void (*set)(void); 
01374         UInt16 alert; 
01375 } problem_table[] = {
01376         { peFineOnMoney, NULL, ClearLowOutMoneyFlags, 0 },
01377         { peLowOnMoney, IsLowMoneyShown, SetLowMoneyShown, alertID_lowFunds },
01378         { peOutOfMoney, IsOutMoneyShown, SetOutMoneyShown, alertID_outMoney },
01379         { peFineOnPower, NULL, ClearLowOutPowerFlags, 0 },
01380         { peLowOnPower, IsLowPowerShown, SetLowPowerShown, alertID_lowPower },
01381         { peOutOfPower, IsOutPowerShown, SetOutPowerShown, alertID_outPower },
01382         { peFineOnWater, NULL, ClearLowOutWaterFlags, 0 },
01383         { peLowOnWater, IsLowWaterShown, SetLowWaterShown, alertID_lowWater },
01384         { peOutOfWater, IsOutWaterShown, SetOutWaterShown, alertID_outWater }
01385 };
01386 
01387 #define PROBLEMTABLE_SIZE (sizeof (problem_table) / sizeof (problem_table[0]))
01388 
01389 void
01390 UIProblemNotify(problem_t problem)
01391 {
01392         UInt16 alert = 0;
01393         UInt16 i;
01394 
01395         for (i = 0; i < PROBLEMTABLE_SIZE; i++) {
01396                 if (problem_table[i].entry == problem) {
01397                         if (problem_table[i].test != NULL &&
01398                             problem_table[i].test()) return;
01399                         problem_table[i].set();
01400                         alert = problem_table[i].alert;
01401                         break;
01402                 }
01403         }
01404         if (alert == 0) return;
01405         FrmAlert(alert);
01406 }
01407 
01408 /*
01409  * Display an specific system error to the user
01410  */
01411 void
01412 UISystemErrorNotify(syserror_t error)
01413 {
01414         if (error == seOutOfMemory) {
01415                 FrmAlert(alertID_errorOutOfMemory);
01416         }
01417 }
01418 
01419 /*
01420  * Display an error that is simply an error string
01421  */
01422 void
01423 UIDisplayError1(char *message)
01424 {
01425         FrmCustomAlert(alertID_majorbad, message, 0, 0);
01426 }
01427 
01428 /*
01429  * Null Function.
01430  */
01431 void
01432 UIInitDrawing(void)
01433 {
01434 }
01435 
01436 /*
01437  * Null Function.
01438  */
01439 void
01440 UIFinishDrawing(void)
01441 {
01442 }
01443 
01450 static UInt8 *didLock = NULL;
01452 static UInt8 lockCalls = 0;
01453 
01459 void
01460 UILockScreen(void)
01461 {
01462         if (!Is35ROM()) return;
01463         ErrFatalDisplayIf(lockCalls > 0, "double lock on screen attempted");
01464         if (!didLock)
01465                 didLock = WinScreenLock(winLockCopy);
01466         lockCalls++;
01467 }
01468 
01469 /*
01470  * Unlock the display.
01471  * Allows any pending updates to proceed.
01472  */
01473 void
01474 UIUnlockScreen(void)
01475 {
01476         if (!Is35ROM()) return;
01477         ErrFatalDisplayIf(lockCalls == 0, "double free on screen attempted");
01478         if (didLock != NULL) {
01479                 WinScreenUnlock();
01480                 didLock = NULL;
01481         }
01482         lockCalls--;
01483 }
01484 
01485 /*
01486  * Get a month string
01487  */
01488 char *
01489 getMonthString(UInt16 month, char *string, UInt16 maxlen)
01490 {
01491         SysStringByIndex(strID_Months, month, string, maxlen);
01492         return (string);
01493 }
01494 
01495 /*
01496  * Draw a rectangle on the screen.
01497  * it will be exactly nHeight*nWidth pixels in size.
01498  * the frame's left border will be at nTop-1 and so on
01499  */
01500 void
01501 _UIDrawRect(Int16 nTop, Int16 nLeft, Int16 nHeight, Int16 nWidth)
01502 {
01503         RectangleType rect;
01504 
01505         rect.topLeft.x = nLeft;
01506         rect.topLeft.y = nTop;
01507         rect.extent.x = nWidth;
01508         rect.extent.y = nHeight;
01509 
01510         
01511         StartHiresDraw();
01512         _WinDrawRectangleFrame(1, &rect);
01513         EndHiresDraw();
01514 }
01515 
01516 /*
01517  * Draw the border around the play area
01518  */
01519 /*
01520 static void
01521 DrawBorder()
01522 {
01523         if (IsDeferDrawing())
01524                 return;
01525 
01526         _UIDrawRect(YOFFSET, XOFFSET, (Int16)(getVisibleY() * gameTileSize()),
01527             (Int16)(getVisibleX() * gameTileSize()));
01528 }
01529 */
01530 
01531 /*
01532  * Null Function.
01533  */
01534 void
01535 UISetUpGraphic(void)
01536 {
01537 }
01538 
01539 /*
01540  * Null Function.
01541  * Would be the tracking cursor on the screen in a bigger environment
01542  */
01543 void
01544 UIPaintCursor(UInt16 xpos __attribute__ ((unused)),
01545     UInt16 ypos __attribute__((unused)))
01546 {
01547 }
01548 
01559 static void
01560 PaintLossIcon(UInt16 xpos, UInt16 ypos, welem_t elem)
01561 {
01562         RectangleType rect;
01563 
01564         if (IsDeferDrawing() || UIClipped(xpos, ypos))
01565                 return;
01566 
01567         xpos -= getMapXPos();
01568         ypos -= getMapYPos();
01569 
01570         rect.topLeft.x = (Coord)(elem % HORIZONTAL_TILESIZE) * gameTileSize();
01571         rect.topLeft.y = (Coord)(elem / HORIZONTAL_TILESIZE) * gameTileSize();
01572         rect.extent.x = gameTileSize();
01573         rect.extent.y = gameTileSize();
01574 
01575         /* copy/paste the graphic from the offscreen image */
01576         StartHiresDraw();
01577         /* first draw the overlay */
01578         _WinCopyRectangle(winZones, WinGetActiveWindow(), &rect,
01579             (Coord)(xpos * gameTileSize() + XOFFSET), (Coord)(ypos * gameTileSize() + YOFFSET),
01580             winErase);
01581         /* now draw the powerloss icon */
01582         rect.topLeft.x -= gameTileSize();
01583         _WinCopyRectangle(winZones, WinGetActiveWindow(), &rect,
01584             (Coord)(xpos * gameTileSize() + XOFFSET),
01585             (Coord)(ypos * gameTileSize() + YOFFSET),
01586             winOverlay);
01587         EndHiresDraw();
01588 }
01589 
01595 void
01596 UIPaintWaterLoss(UInt16 xpos, UInt16 ypos)
01597 {
01598         PaintLossIcon(xpos, ypos, Z_WATER_OUT_MASK);
01599 }
01600 
01606 void
01607 UIPaintPowerLoss(UInt16 xpos, UInt16 ypos)
01608 {
01609         PaintLossIcon(xpos, ypos, Z_POWER_OUT_MASK);
01610 }
01611 
01618 void
01619 UIPaintSpecialUnit(UInt16 xpos, UInt16 ypos, Int8 i)
01620 {
01621         RectangleType rect;
01622         if (IsDeferDrawing() || UIClipped(xpos, ypos))
01623                 return;
01624 
01625         xpos -= getMapXPos();
01626         ypos -= getMapYPos();
01627 
01628         rect.topLeft.x = game.units[i].type * gameTileSize();
01629         rect.topLeft.y = gameTileSize();
01630         rect.extent.x = gameTileSize();
01631         rect.extent.y = gameTileSize();
01632 
01633         StartHiresDraw();
01634         _WinCopyRectangle(winUnits, WinGetActiveWindow(), &rect,
01635             (Coord)(xpos * gameTileSize() + XOFFSET),
01636             (Coord)(ypos * gameTileSize() + YOFFSET),
01637             winErase);
01638         rect.topLeft.y = 0;
01639         _WinCopyRectangle(winUnits, WinGetActiveWindow(), &rect,
01640             (Coord)(xpos * gameTileSize() + XOFFSET),
01641             (Coord)(ypos * gameTileSize() + YOFFSET),
01642             winOverlay);
01643         EndHiresDraw();
01644 }
01645 
01646 /*
01647  * Draw a special object a the location chosen.
01648  * Mostly monsters, but it coud be a train, palin, chopper
01649  */
01650 void
01651 UIPaintSpecialObject(UInt16 xpos, UInt16 ypos, Int8 i)
01652 {
01653         RectangleType rect;
01654 
01655         if (IsDeferDrawing() || UIClipped(xpos, ypos))
01656                 return;
01657 
01658         xpos -= getMapXPos();
01659         ypos -= getMapYPos();
01660 
01661         rect.topLeft.x = (Coord)(game.objects[i].dir * gameTileSize());
01662         rect.topLeft.y = (Coord)(((i * 2) + 1) * gameTileSize());
01663         rect.extent.x = gameTileSize();
01664         rect.extent.y = gameTileSize();
01665 
01666         StartHiresDraw();
01667         _WinCopyRectangle(winMonsters, WinGetActiveWindow(), &rect,
01668             (Coord)(xpos * gameTileSize() + XOFFSET),
01669             (Coord)(ypos * gameTileSize() + YOFFSET),
01670             winErase);
01671         rect.topLeft.y -= 16;
01672         _WinCopyRectangle(winMonsters, WinGetActiveWindow(), &rect,
01673             (Coord)(xpos * gameTileSize() + XOFFSET),
01674             (Coord)(ypos * gameTileSize() + YOFFSET),
01675             winOverlay);
01676         EndHiresDraw();
01677 }
01678 
01679 /*
01680  * Paint the location on screen with the field.
01681  */
01682 void
01683 UIPaintField(UInt16 xpos, UInt16 ypos, welem_t nGraphic)
01684 {
01685         RectangleType rect;
01686 
01687         if (IsDeferDrawing() || UIClipped(xpos, ypos))
01688                 return;
01689 
01690         xpos -= getMapXPos();
01691         ypos -= getMapYPos();
01692 
01693         rect.topLeft.x = (nGraphic % HORIZONTAL_TILESIZE) * gameTileSize();
01694         rect.topLeft.y = (nGraphic / HORIZONTAL_TILESIZE) * gameTileSize();
01695         rect.extent.x = gameTileSize();
01696         rect.extent.y = gameTileSize();
01697 
01698         /* copy/paste the graphic from the offscreen image */
01699         StartHiresDraw();
01700         _WinCopyRectangle(winZones, WinGetActiveWindow(), &rect,
01701             (Coord)(xpos * gameTileSize() + XOFFSET),
01702             (Coord)(ypos * gameTileSize() + YOFFSET),
01703             winPaint);
01704         EndHiresDraw();
01705 }
01706 
01714 static void
01715 performPaintDisplay(void)
01716 {
01717         UIInitDrawing();
01718         if (checkGraphicUpdate(gu_playarea))
01719                 UIPaintPlayArea();
01720         if (checkGraphicUpdate(gu_credits))
01721                 UIPaintCredits();
01722         if (checkGraphicUpdate(gu_population))
01723                 UIPaintPopulation();
01724         if (checkGraphicUpdate(gu_date))
01725                 UIPaintDate();
01726         if (checkGraphicUpdate(gu_location))
01727                 if (!GETMINIMAPVISIBLE())
01728                         UIPaintLocation();
01729         if (checkGraphicUpdate(gu_buildicon))
01730                 UIPaintBuildIcon();
01731         if (checkGraphicUpdate(gu_speed))
01732                 UIPaintSpeed();
01733         if (checkGraphicUpdate(gu_desires))
01734                 UIPaintDesires();
01735         clearGraphicUpdate();
01736         UIFinishDrawing();
01737 }
01738 
01742 void
01743 UIPaintPlayArea(void)
01744 {
01745         UInt16 x = getMapXPos();
01746         UInt16 y = getMapYPos();
01747 
01748         UInt16 maxx = x + getVisibleX() < getMapWidth() ? x + getVisibleX() :
01749             getMapWidth();
01750         UInt16 maxy = y + getVisibleY() < getMapHeight() ? y + getVisibleY() :
01751             getMapHeight();
01752 
01753         LockZone(lz_world);
01754         LockZone(lz_flags);
01755         for (; x < maxx; x++) {
01756                 for (; y < maxy; y++) {
01757                         DrawFieldWithoutInit(x, y);
01758                 }
01759                 y = getMapYPos();
01760         }
01761         if (GETMINIMAPVISIBLE())
01762                 minimapPaint();
01763         UnlockZone(lz_flags);
01764         UnlockZone(lz_world);
01765 }
01766 
01770 void
01771 UIPaintDesires(void)
01772 {
01773         return;
01774 }
01775 
01776 /*
01777  * Scroll the map in the direction specified
01778  */
01779 void
01780 UIScrollDisplay(dirType direction)
01781 {
01782         WinHandle screen;
01783         RectangleType rect;
01784         RectangleType overlap;
01785 
01786         Int16 to_x, to_y;
01787         UInt16 mapx, mapy;
01788         UInt16 x, y;
01789         UInt16 s_x, s_y, l_x, l_y, gs_m1;
01790 
01791         if (IsDeferDrawing())
01792                 return;
01793 
01794         mapx = getMapXPos();
01795         mapy = getMapYPos();
01796 
01797         SetScrolling();
01798 
01799         LockZone(lz_world);
01800         LockZone(lz_flags);
01801         UIInitDrawing();
01802 
01803         if (GETMINIMAPVISIBLE()) {
01804                 /* Repaint fhe area occluded by the minimap */
01805                 minimapIntersect(&rPlayGround, &overlap);
01806                 gs_m1 = gameTileSize() - 1;
01807                 s_x = mapx + scaleCoord(
01808                     inGameTiles(overlap.topLeft.x - XOFFSET));
01809                 s_y = mapy + scaleCoord(
01810                     inGameTiles(overlap.topLeft.y - YOFFSET));
01811                 l_x = s_x + scaleCoord(inGameTiles(overlap.extent.x + gs_m1));
01812                 l_y = s_y + scaleCoord(inGameTiles(overlap.extent.y + gs_m1));
01813                 WriteLog("(%d,%d)->(%d,%d)\n", s_x, s_y, l_x, l_y);
01814 
01815                 for (x = s_x; x <= l_x; x++) {
01816                         for(y = s_y; y <= l_y; y++) {
01817                                 DrawFieldWithoutInit(x, y);
01818                         }
01819                 }
01820         }
01821 
01822         rect.topLeft.x = XOFFSET + gameTileSize() * (direction == dtRight);
01823         rect.topLeft.y = YOFFSET + gameTileSize() * (direction == dtDown);
01824         rect.extent.x = (Coord)((getVisibleX() -
01825             ((direction == dtRight || direction == dtLeft) ? 1 : 0)) *
01826             gameTileSize());
01827         rect.extent.y = (Coord)((getVisibleY() -
01828             ((direction == dtUp || direction == dtDown) ? 1 : 0)) *
01829             gameTileSize());
01830         to_x = XOFFSET + gameTileSize() * (direction == dtLeft);
01831         to_y = YOFFSET + gameTileSize() * (direction == dtUp);
01832 
01833         screen = WinGetActiveWindow();
01834         StartHiresDraw();
01835         _WinCopyRectangle(screen, screen, &rect, to_x, to_y, winPaint);
01836         EndHiresDraw();
01837 
01838         /* and lastly, fill the gap */
01839 
01840         if (direction == dtRight || direction == dtLeft) {
01841                 for (y = mapy; y < getVisibleY() + mapy; y++) {
01842                         DrawFieldWithoutInit((UInt16)(mapx +
01843                             (getVisibleX() - 1) * (direction == dtRight)), y);
01844                 }
01845         } else {
01846                 for (x = mapx; x < getVisibleX() + mapx; x++) {
01847                         DrawFieldWithoutInit(x, (UInt16)(mapy +
01848                             (getVisibleY() - 1) * (direction == dtDown)));
01849                 }
01850         }
01851 
01852         UIPaintCursor(getCursorX(), getCursorY());
01853         if (GETMINIMAPVISIBLE()) {
01854                 minimapPaint();
01855         } else {
01856                 UIPaintLocation();
01857         }
01858         UIFinishDrawing();
01859 
01860         UnlockZone(lz_flags);
01861         UnlockZone(lz_world);
01862 }
01863 
01864 /*
01865  * Get a random number.
01866  */
01867 UInt32
01868 GetRandomNumber(UInt32 max)
01869 {
01870         if (max == 0)
01871                 return (0);
01872         return ((UInt16)SysRandom(0) % (UInt16)max);
01873 }
01874 
01875 /*
01876  * Layout (current|lores)
01877  * [Tool]                        [date]         [J][Speed]
01878  * [                                                    ]
01879  * [            Play Area                               ]
01880  * [                                                    ]
01881  * [money]                      [pop]              [loc]
01882  *
01883  * Layout (current|hires)
01884  * [tool]       [       Toolbar           ]     [J][Speed]
01885  * [                    Play Area                       ]
01886  * [Date]       [Money]  [pop]                  [loc]
01887  *
01888  * The J is for 'jog' item it's either updn or ltrt
01889  */
01890 
01891 typedef enum {
01892         loc_date = 0,
01893         loc_credits,
01894         loc_population,
01895         loc_position
01896 } loc_screen;
01897 
01898 #define MIDX    1
01899 #define MIDY    2
01900 #define ENDX    4
01901 #define ENDY    8
01902 
01904 struct StatusPositions {
01905         PointType point; 
01906         PointType offset; 
01907         UInt32 extents; 
01908 };
01909 
01911 static RectangleType shapes[] = {
01912         { {0, 0}, {0, 10} },  /* loc_date */
01913         { {0, 0}, {0, 10} }, /* loc_credits */
01914         { {0, 0}, {0, 10} }, /* loc_population */
01915         { {0, 0}, {0, 10} } /* loc_position */
01916 };
01917 
01919 static const struct StatusPositions lrpositions[] = {
01920         { {0, 0} , {0, 1}, MIDX },  /* loc_date */
01921         { {0, 0}, {0, 1}, ENDY }, /* loc_credits */
01922         { {0, 0}, {0, 1}, MIDX | ENDY }, /* loc_population */
01923         { {0, 0}, {0, 1}, ENDX | ENDY } /* loc_position */
01924 };
01925 
01926 #ifdef HRSUPPORT
01927 
01929 static const struct StatusPositions hrpositions[] = {
01930         { {1, 0}, {0, 1}, ENDY },  /* loc_date */
01931         { {40, 0}, {0, 1}, ENDY }, /* loc_credits */
01932         { {80, 0}, {0, 1}, ENDY }, /* loc_population */
01933         { {140, 0}, {0, 1}, ENDY } /* loc_position */
01934 };
01935 
01941 static struct StatusPositions *
01942 posAt(int pos)
01943 {
01944         static struct StatusPositions *sp = NULL;
01945         if (sp != NULL)
01946                 return (&(sp[pos]));
01947         if (isHires()) {
01948                 WriteLog("Plucking HiRes Positions (%d)\n",
01949                     (int)highDensityFeatureSet());
01950                 sp = (struct StatusPositions *)&(hrpositions[0]);
01951         } else {
01952                 WriteLog("Plucking Low Resolution Positions\n");
01953                 sp = (struct StatusPositions *)&(lrpositions[0]);
01954         }
01955         return (&(sp[pos]));
01956 }
01957 
01958 #else
01959 
01960 #define posAt(x)        &(lrpositions[(x)])
01961 #endif
01962 
01963 #define MAXLOC          (sizeof (lrpositions) / sizeof (lrpositions[0]))
01964 
01970 static void
01971 DrawItem(loc_screen location, char *text)
01972 {
01973         const struct StatusPositions *pos;
01974         Int16 sl;
01975         Coord tx;
01976         RectangleType *rt;
01977 
01978         pos = posAt(location);
01979         rt = shapes + location;
01980         if (rt->extent.x && rt->extent.y) {
01981                 StartHiresDraw();
01982                 _WinEraseRectangle(rt, 0);
01983                 EndHiresDraw();
01984         }
01985 
01986         if (isDoubleOrMoreResolution())
01987                 _FntSetFont(boldFont);
01988         sl = (Int16)StrLen(text);
01989         tx = FntCharsWidth(text, sl);
01990         switch (pos->extents & (MIDX | ENDX)) {
01991         case MIDX:
01992                 rt->topLeft.x = (GETWIDTH() - tx) / 2 + pos->offset.x;
01993                 break;
01994         case ENDX:
01995                 rt->topLeft.x = GETWIDTH() - (tx + pos->offset.x);
01996                 break;
01997         default:
01998                 rt->topLeft.x = (Coord)((Int32)GETWIDTH() * pos->point.x /
01999                     BASEWIDTH);
02000         }
02001         if (pos->extents & ENDY) {
02002                 rt->topLeft.y = GETHEIGHT() - (rt->extent.y + pos->offset.y);
02003         }
02004         rt->extent.x = tx;
02005         if (highDensityFeatureSet()) {
02006                 StartHiresFontDraw();
02007                 _WinDrawChars(text, sl, normalizeCoord(rt->topLeft.x),
02008                     normalizeCoord(rt->topLeft.y));
02009                 EndHiresFontDraw();
02010         } else {
02011                 _WinDrawChars(text, sl, rt->topLeft.x, rt->topLeft.y);
02012         }
02013         if (isDoubleOrMoreResolution())
02014                 _FntSetFont(stdFont);
02015 }
02016 
02025 static Int16
02026 UICheckOnClick(Coord x, Coord y)
02027 {
02028         UInt16 i;
02029         for (i = 0; i < MAXLOC; i++) {
02030                 RectangleType *rt = shapes + i;
02031                 if ((x >= rt->topLeft.x) &&
02032                     (x <= (rt->topLeft.x + rt->extent.x)) &&
02033                     (y >= rt->topLeft.y) &&
02034                     (y <= (rt->topLeft.y + rt->extent.y)))
02035                         return ((Int16)i);
02036         }
02037         return (-1);
02038 }
02039 
02045 static void
02046 CheckTextClick(Coord x, Coord y)
02047 {
02048         int t = UICheckOnClick(x, y);
02049         if (t == -1)
02050                 return;
02051         switch (t) {
02052         case loc_date:
02053                 break;
02054         case loc_credits:
02055                 doButtonEvent(BeBudget);
02056                 break;
02057         case loc_population:
02058                 doButtonEvent(BePopulation);
02059                 break;
02060         case loc_position:
02061                 if (!GETMINIMAPVISIBLE())
02062                         doButtonEvent(BeMap);
02063                 break;
02064         default:
02065                 break;
02066         }
02067 }
02068 
02069 void
02070 UIPaintDate(void)
02071 {
02072         char temp[20];
02073 
02074         if (IsDeferDrawing())
02075                 return;
02076 
02077         getDate((char *)temp);
02078         DrawItem(loc_date, temp);
02079 }
02080 
02081 void
02082 UIPaintCredits(void)
02083 {
02084         char temp[20];
02085         char scale;
02086         UInt32 credits;
02087 #ifdef HRSUPPORT
02088         MemHandle bitmapHandle;
02089         BitmapPtr bitmap;
02090 #endif
02091 
02092         if (IsDeferDrawing())
02093                 return;
02094 
02095         credits = scaleNumber((UInt32)getCredits(), &scale);
02096         StrPrintF(temp, "$: %ld%c", credits, scale);
02097         DrawItem(loc_credits, temp);
02098 #ifdef HRSUPPORT
02099         if (isHires()) {
02100                 bitmapHandle = DmGetResource(TBMP, bitmapID_coin);
02101                 if (bitmapHandle == NULL)
02102                         return;
02103                 bitmap = MemHandleLock(bitmapHandle);
02104                 StartHiresDraw();
02105                 _WinDrawBitmap(bitmap, shapes[loc_credits].topLeft.x - 11,
02106                     shapes[loc_credits].topLeft.y);
02107                 EndHiresDraw();
02108                 MemPtrUnlock(bitmap);
02109                 DmReleaseResource(bitmapHandle);
02110         }
02111 #endif
02112 }
02113 
02114 void
02115 UIPaintLocation(void)
02116 {
02117         char temp[20];
02118 #ifdef HRSUPPORT
02119         MemHandle bitmapHandle;
02120         BitmapPtr bitmap;
02121 #endif
02122 
02123         if (IsDeferDrawing())
02124                 return;
02125 
02126         StrPrintF(temp, "%02u,%02u", getMapXPos(), getMapYPos());
02127 
02128         DrawItem(loc_position, temp);
02129 #ifdef HRSUPPORT
02130         if (isHires()) {
02131                 bitmapHandle = DmGetResource(TBMP, bitmapID_loca);
02132                 if (bitmapHandle == NULL)
02133                         return;
02134                 bitmap = MemHandleLock(bitmapHandle);
02135                 StartHiresDraw();
02136                 _WinDrawBitmap(bitmap, shapes[loc_position].topLeft.x - 11,
02137                     shapes[loc_position].topLeft.y);
02138                 EndHiresDraw();
02139                 MemPtrUnlock(bitmap);
02140                 DmReleaseResource(bitmapHandle);
02141         }
02142 #endif
02143 }
02144 
02145 void
02146 UIPaintBuildIcon(void)
02147 {
02148         MemHandle bitmaphandle;
02149         BitmapPtr bitmap;
02150 
02151         if (IsDeferDrawing())
02152                 return;
02153 
02154         bitmaphandle = DmGetResource(TBMP,
02155             (UInt16)(bitmapID_iconBulldoze + (((nSelectedBuildItem <= Be_Extra)) ?
02156             nSelectedBuildItem : OFFSET_EXTRA)));
02157 
02158         if (bitmaphandle == NULL)
02159                 /* TODO: onscreen error? +save? */
02160                 return;
02161         bitmap = (BitmapPtr)MemHandleLock(bitmaphandle);
02162         StartHiresDraw();
02163         _WinDrawBitmap(bitmap, 2, 2);
02164         EndHiresDraw();
02165         MemPtrUnlock(bitmap);
02166         DmReleaseResource(bitmaphandle);
02167 #if defined(HRSUPPORT)
02168         if (isHires()) {
02169                 UIPaintToolBar();
02170         }
02171 #endif
02172 }
02173 
02174 Int8
02175 UIClipped(UInt16 xpos, UInt16 ypos)
02176 {
02177         return (xpos < (UInt16)getMapXPos() ||
02178             (xpos >= (UInt16)(getMapXPos() + getVisibleX())) ||
02179             ypos < (UInt16)getMapYPos() ||
02180             (ypos >= (UInt16)(getMapYPos() + getVisibleY())));
02181 }
02182 
02183 void
02184 UIPaintSpeed(void)
02185 {
02186         RectangleType rect;
02187 #if defined(SONY_CLIE)
02188         MemHandle bitmapHandle;
02189         BitmapPtr bitmap;
02190 #endif
02191 
02192         rect.topLeft.x = speedOffset() * 10;
02193         rect.topLeft.y = 0;
02194         rect.extent.x = 10;
02195         rect.extent.y = 10;
02196         StartHiresDraw();
02197         _WinCopyRectangle(winSpeeds, WinGetActiveWindow(), &rect,
02198             GETWIDTH() - 12, 2, winPaint);
02199         EndHiresDraw();
02200 
02201 #ifdef SONY_CLIE
02202         if (IsSony()) {
02203                 bitmapHandle = DmGetResource(TBMP, bitmapID_updn + jog_lr);
02204                 /* place at rt - (12 + 8), 1 */
02205                 if (bitmapHandle) {
02206                         bitmap = MemHandleLock(bitmapHandle);
02207                         if (bitmap) {
02208                                 StartHiresDraw();
02209                                 _WinDrawBitmap(bitmap,
02210                                     GETWIDTH() - (12 + 8), 1);
02211                                 EndHiresDraw();
02212                                 MemPtrUnlock(bitmap);
02213                         }
02214                         DmReleaseResource(bitmapHandle);
02215                 }
02216         }
02217 
02218 #endif
02219 }
02220 
02221 void
02222 UIPaintPopulation(void)
02223 {
02224         char temp[20];
02225         Char scale;
02226         UInt32 popul;
02227 
02228         if (IsDeferDrawing())
02229                 return;
02230 
02231         popul = getPopulation();
02232         popul = scaleNumber(popul, &scale);
02233 
02234         StrPrintF(temp, "Pop: %lu%c", popul, scale);
02235         DrawItem(loc_population, temp);
02236 #ifdef HRSUPPORT
02237         if (isHires()) {
02238                 MemHandle bitmapHandle;
02239                 BitmapPtr bitmap;
02240                 
02241                 bitmapHandle = DmGetResource(TBMP, bitmapID_popu);
02242                 if (bitmapHandle == NULL)
02243                         return;
02244                 bitmap = MemHandleLock(bitmapHandle);
02245                 StartHiresDraw();
02246                 _WinDrawBitmap(bitmap, shapes[loc_population].topLeft.x - 11,
02247                     shapes[loc_population].topLeft.y);
02248                 EndHiresDraw();
02249                 MemPtrUnlock(bitmap);
02250                 DmReleaseResource(bitmapHandle);
02251         }
02252 #endif
02253 }
02254 
02262 void
02263 UICheckMoney(void)
02264 {
02265         if (getCredits() == 0) {
02266                 UIProblemNotify(peOutOfMoney);
02267         } else if (getCredits() <= 1000) {
02268                 UIProblemNotify(peLowOnMoney);
02269         }
02270 }
02271 
02272 void
02273 MapHasJumped(void)
02274 {
02275 }
02276 
02287 static Err
02288 RomVersionCompatible(UInt32 requiredVersion, UInt16 launchFlags)
02289 {
02290         UInt32 version;
02291 
02292         /* See if we're on in minimum required version of the ROM or later. */
02293         FtrGet(sysFtrCreator, sysFtrNumROMVersion, &version);
02294 
02295         WriteLog("Rom Version: 0x%lx\n", (unsigned long)version);
02296         Clear35ROM();
02297 
02298         if (version < requiredVersion) {
02299                 if ((launchFlags &
02300                     (sysAppLaunchFlagNewGlobals | sysAppLaunchFlagUIApp)) ==
02301                     (sysAppLaunchFlagNewGlobals | sysAppLaunchFlagUIApp)) {
02302                         if (version > sysMakeROMVersion(3, 1, 0, 0, 0) &&
02303                             FrmAlert(alertID_RomIncompatible) == 1) {
02304                                 return (0);
02305                         }
02306 
02307                         /*
02308                          * Pilot 1.0 will continuously relaunch this app
02309                          * unless we switch to another safe one.
02310                          */
02311                         if (version < sysMakeROMVersion(2, 0, 0, 0, 0)) {
02312                                 AppLaunchWithCommand(sysFileCDefaultApp,
02313                                     sysAppLaunchCmdNormalLaunch, NULL);
02314                         }
02315                 }
02316                 return (sysErrRomIncompatible);
02317         }
02318         Set35ROM();
02319 
02320         if (version >= sysMakeROMVersion(4, 0, 0, sysROMStageRelease, 0))
02321                 Set40ROM();
02322         else
02323                 Clear40ROM();
02324 
02325         ClearScaleModes();
02326         if (errNone == FtrGet(sysFtrCreator, sysFtrNumWinVersion, &version)) {
02327                 if (version >= 5)
02328                         SetScaleModes();
02329         }
02330 
02331         return (0);
02332 }
02333 
02335 static UInt8 speedslist[] = {
02336         SPEED_PAUSED, SPEED_SLOW, SPEED_MEDIUM, SPEED_FAST, SPEED_TURBO
02337 };
02339 #define MAX_SPEED       (sizeof (speedslist) / sizeof (speedslist[0]))
02340 
02348 static Int16
02349 speedOffset(void)
02350 {
02351         UInt16 i;
02352 
02353         for (i = 0; i < MAX_SPEED; i++)
02354                 if (getLoopSeconds() == speedslist[i])
02355                         return ((Int16)i);
02356         return (0);
02357 }
02358 
02364 static void
02365 cycleSpeed(void)
02366 {
02367         UInt16 i = 0;
02368 
02369         while (i < MAX_SPEED) {
02370                 if (speedslist[i++] == getLoopSeconds())
02371                         break;
02372         }
02373         setLoopSeconds(speedslist[i == MAX_SPEED ? 0 : i]);
02374 }
02375 
02381 static Int16
02382 doButtonEvent(ButtonEvent event)
02383 {
02384         switch (event) {
02385         case BeIgnore:
02386                 break;
02387         case BeUp:
02388                 ScrollDisplay(dtUp);
02389                 break;
02390         case BeDown:
02391                 ScrollDisplay(dtDown);
02392                 break;
02393         case BeLeft:
02394                 ScrollDisplay(dtLeft);
02395                 break;
02396         case BeRight:
02397                 ScrollDisplay(dtRight);
02398                 break;
02399         case BePopup:
02400                 UIDoQuickList();
02401                 break;
02402         case BeMap:
02403                 FrmGotoForm(formID_map);
02404                 break;
02405         case BeBudget:
02406                 FrmGotoForm(formID_budget);
02407                 break;
02408         case BePopulation:
02409                 /* No-Op at moment */
02410                 break;
02411         case BePassthrough:
02412                 return (0);
02413 #ifdef SONY_CLIE
02414         /*
02415          * if the draw window doesn't occupy most of the screen ...
02416          *  - for example if it's a menu
02417          * allow jog assist to work.
02418          */
02419         case BeJogUp:
02420                 if (!IsDrawWindowMostOfScreen())
02421                         return (0);
02422                 if (jog_lr)
02423                         ScrollDisplay(dtLeft);
02424                 else
02425                         ScrollDisplay(dtUp);
02426                 break;
02427         case BeJogDown:
02428                 if (!IsDrawWindowMostOfScreen())
02429                         return (0);
02430                 if (jog_lr)
02431                         ScrollDisplay(dtRight);
02432                 else
02433                         ScrollDisplay(dtDown);
02434                 break;
02435         case BeJogRelease:
02436                 if (!IsDrawWindowMostOfScreen())
02437                         return (0);
02438                 jog_lr = 1 - jog_lr;
02439                 addGraphicUpdate(gu_location);
02440                 break;
02441 #endif
02442         default:
02443                 break;
02444         }
02445         return (1);
02446 }
02447 
02453 static Int16
02454 HardButtonEvent(ButtonKey key)
02455 {
02456         return (doButtonEvent(gameConfig.pc.keyOptions[key]));
02457 }
02458 
02459 void
02460 clearProblemFlags(void)
02461 {
02462         ClearLowOutMoneyFlags();
02463         ClearLowOutPowerFlags();
02464         ClearLowOutWaterFlags();
02465 }
02466 
02472 static struct _silkKeys {
02473         UInt16 vChar;   
02474         ButtonKey event; 
02475 } silky[] = {
02476         { pageUpChr, BkHardUp },
02477         { pageDownChr, BkHardDown },
02478         { vchrRockerUp, BkHardUp },
02479         { vchrRockerDown, BkHardDown },
02480         { vchrHard1, BkCalendar },
02481         { vchrHard2, BkAddress },
02482         { vchrHard3, BkToDo },
02483         { vchrHard4, BkMemo },
02484         { vchrFind, BkFind },
02485         { 1, BkCalc },
02486 #ifdef HIRES
02487 #ifdef SONY_CLIE
02488         { vchrJogUp, BkJogUp },
02489         { vchrJogDown, BkJogDown },
02490         { vchrJogRelease, BkJogRelease },
02491 #endif
02492 #endif
02493         { 0, BkEnd }
02494 };
02495 
02496 
02504 static void
02505 buildSilkList()
02506 {
02507         UInt16 btncount = 0;
02508         UInt16 atsilk = 0;
02509         UInt16 atbtn = 0;
02510 
02511         const PenBtnInfoType *silkinfo = EvtGetPenBtnList(&btncount);
02512         /* favorites / find */
02513         while (silky[atsilk].vChar != 1) atsilk++;
02514         /* Bail if we're not a Zire */
02515         if (!isZireOld()) {
02516                 silky[atsilk].vChar = vchrCalc;
02517                 return;
02518         }
02519         while (atbtn < btncount) {
02520                 WriteLog("btn: %ld char: %lx\n", (long)atbtn,
02521                     (long)silkinfo[atbtn].asciiCode);
02522                 /*
02523                  * Assumes the favourite/calculator button is one
02524                  * before the find button. Crap, really.
02525                  */
02526                 if (silkinfo[atbtn].asciiCode == vchrFind) {
02527                         if (atbtn > 0) { // XXX: fixme
02528                                 switch (silkinfo[atbtn-1].asciiCode) {
02529                                 case vchrCalc:
02530                                 case vchrMenu:
02531                                         break;
02532                                 default:
02533                                         silky[atsilk].vChar =
02534                                             silkinfo[atbtn-1].asciiCode;
02535                                         break;
02536                                 }
02537                                 break;
02538                         }
02539                 }
02540                 atbtn++;
02541         }
02542         if (silky[atsilk].vChar == 1) silky[atsilk].vChar = vchrCalc;
02543 }
02544 
02550 static Int16
02551 vkDoEvent(UInt16 key)
02552 {
02553         struct _silkKeys *atsilk = &(silky[0]);
02554         while (atsilk->vChar != 0) {
02555                 if (key == atsilk->vChar)
02556                         return (HardButtonEvent(atsilk->event));
02557                 atsilk++;
02558         }
02559         return (0);
02560 
02561 }
02562 
02563 #ifdef HRSUPPORT
02564 
02565 static BitmapType *pToolbarBitmap;
02567 static BitmapType *pOldBitmap;
02568 
02570 static void
02571 freeToolbarBitmap(void)
02572 {
02573         if (pOldBitmap != NULL) {
02574                 BmpDelete(pOldBitmap);
02575                 pOldBitmap = NULL;
02576         }
02577         if (pToolbarBitmap != NULL) {
02578                 BmpDelete(pToolbarBitmap);
02579                 pToolbarBitmap = NULL;
02580         }
02581 }
02582 
02591 static void
02592 drawToolBitmaps(Coord startx, Coord starty, Coord spacing)
02593 {
02594         MemHandle hBitmap;
02595         MemPtr pBitmap;
02596         UInt32 id;
02597 
02598         for (id = bitmapID_iconBulldoze; id <= bitmapID_iconExtra; id++) {
02599                 hBitmap = DmGetResource(TBMP, id);
02600                 if (hBitmap == NULL) continue;
02601                 pBitmap = MemHandleLock(hBitmap);
02602                 if (pBitmap == NULL) {
02603                         DmReleaseResource(hBitmap);
02604                         continue;
02605                 }
02606                 _WinDrawBitmap(pBitmap, startx, starty);
02607                 startx += spacing;
02608                 MemPtrUnlock(pBitmap);
02609                 DmReleaseResource(hBitmap);
02610         }
02611 }
02612 
02620 int
02621 GetBitmapDimensions(UInt16 resID, Coord *width, Coord *height)
02622 {
02623         BitmapPtr bmp;
02624         MemHandle mh = DmGetResource(bitmapRsc, resID);
02625 
02626         if (mh == NULL)
02627                 return (1);
02628 
02629         bmp = MemHandleLock(mh);
02630 
02631         if (bmp == NULL) {
02632                 DmReleaseResource(mh);
02633                 return (1);
02634         }
02635 
02636         compatBmpGetDimensions(bmp, width, height, NULL);
02637         MemHandleUnlock(mh);
02638         DmReleaseResource(mh);
02639         return (0);
02640 }
02641 
02643 static Coord tbWidth;
02645 static Coord bWidth;
02646 
02648 static void
02649 UIPaintToolBar(void)
02650 {
02651         WinHandle wh = NULL;
02652         WinHandle owh = NULL;
02653 
02654         if (pToolbarBitmap == NULL) {
02655                 UInt16 err;
02656                 Coord bHeight;
02657 
02658                 GetBitmapDimensions(bitmapID_iconBulldoze, &bWidth, &bHeight);
02659                 bWidth += 4; 
02660 
02661                 tbWidth = (1 + (bitmapID_iconExtra - bitmapID_iconBulldoze)) *
02662                     bWidth;
02663 
02664                 pToolbarBitmap = _BmpCreate(tbWidth, bHeight, getDepth(),
02665                     NULL, &err);
02666                 if (highDensityFeatureSet() && pToolbarBitmap != NULL) {
02667                         pOldBitmap = pToolbarBitmap;
02668                         pToolbarBitmap = (BitmapPtr)BmpCreateBitmapV3(
02669                             pToolbarBitmap, kDensityLow, 
02670                             BmpGetBits(pToolbarBitmap), NULL);
02671                 }
02672                 if (pToolbarBitmap != NULL) {
02673                         wh = _WinCreateBitmapWindow(pToolbarBitmap, &err);
02674                         if (wh != NULL) {
02675                                 owh = WinSetDrawWindow(wh);
02676                                 drawToolBitmaps(2, 0, bWidth);
02677                                 WinSetDrawWindow(owh);
02678                                 WinDeleteWindow(wh, false);
02679                         }
02680                 } else {
02681                         StartHiresDraw();
02682                         drawToolBitmaps(((GETWIDTH() - tbWidth) >> 1) + 2,
02683                             2, bWidth);
02684                         EndHiresDraw();
02685                         return;
02686                 }
02687         }
02688         if (pToolbarBitmap != NULL) {
02689                 StartHiresDraw();
02690                 WriteLog("Toolbar at: %ld (width=%ld) [ swidth=%ld ]\n",
02691                     (long)((GETWIDTH() - tbWidth) >> 1), (long)tbWidth,
02692                     (long)GETWIDTH());
02693                 _WinDrawBitmap(pToolbarBitmap, (GETWIDTH() - tbWidth) >> 1, 2);
02694                 EndHiresDraw();
02695         }
02696 }
02697 
02708 static void
02709 toolBarCheck(Coord xpos)
02710 {
02711         int id;
02712 
02713         /* We've already confirmed the y-axis. */
02714         if ((xpos < ((GETWIDTH() - tbWidth) >> 1)) ||
02715             (xpos > ((GETWIDTH() + tbWidth) >> 1))) return;
02716 
02717         id = (xpos - ((GETWIDTH() - tbWidth) >> 1)) / bWidth;
02718         WriteLog("Xpos: %ld [ %ld / %ld ] %d %d \n", (long)xpos,
02719             (long)tbWidth, (long)GETWIDTH(), id, (int)bWidth);
02720         if (id == (bitmapID_iconExtra - bitmapID_iconBulldoze)) {
02721                 UIPopUpExtraBuildList();
02722         } else {
02723                 UISetSelectedBuildItem(id);
02724         }
02725         addGraphicUpdate(gu_buildicon);
02726 }
02727 
02738 static void
02739 pcResizeDisplay(FormPtr form, Int16 hOff, Int16 vOff, Boolean draw)
02740 {
02741         RectangleType disRect;
02742         Int16 loc;
02743         Int16 nWidth;
02744         Int16 nHeight;
02745 
02746         if (hOff == 0 && vOff == 0)
02747                 return;
02748 
02749         WinGetDrawWindowBounds(&disRect);
02750 
02751         nWidth = GETWIDTH() + scaleCoord(hOff);
02752         nHeight = GETHEIGHT() + scaleCoord(vOff);
02753 
02754         SETWIDTH(nWidth);
02755         SETHEIGHT(nHeight);
02756 
02757         ResetViewable();
02758 
02759         for (loc = 0; loc < (Int16)MAXLOC; loc++)
02760                 shapes[loc].extent.x = 0;
02761 
02762         /* XXX: Resize the gadgets - coordinates are natural */
02763         rPlayGround.extent.x = normalizeCoord(GETWIDTH());
02764         rPlayGround.extent.y = normalizeCoord(GETHEIGHT()) - 2 * 10;
02765 
02766         /* Resize the minimap */
02767         disRect.topLeft.x = normalizeCoord(GETWIDTH()) - 32;
02768         disRect.topLeft.y = normalizeCoord(GETHEIGHT()) - 32;
02769         disRect.extent.x = 32;
02770         disRect.extent.y = 32;
02771         minimapPlace(&disRect);
02772 
02773         if (draw) {
02774                 collapsePreRedraw(form);
02775                 FrmDrawForm(form);
02776                 DrawGame(1);
02777         }
02778 }
02779 
02780 #endif /* HRSUPPORT */
02781 
02782 #ifdef  SONY_CLIE
02783 
02785 static void
02786 HoldHook(UInt32 held)
02787 {
02788         if (held) game.gameLoopSeconds = SPEED_PAUSED;
02789         addGraphicUpdate(gu_speed);
02790 }
02791 
02792 #endif
02793 
02794 #ifdef LOGGING
02795 
02796 #include <unix_stdarg.h>
02797 
02798 void
02799 WriteLog(char *s, ...)
02800 {
02801         va_list args;
02802         HostFILE * hf = NULL;
02803         Char text[0x100];
02804 
02805         hf = HostFOpen("\\pcity.log", "a");
02806         if (hf) {
02807                 va_start(args, s);
02808                 StrVPrintF(text, s, args);
02809 
02810                 HostFPrintF(hf, text);
02811                 HostFClose(hf);
02812                 va_end(args);
02813         }
02814 }
02815 
02816 void
02817 WriteLogX(char *s, ...)
02818 {
02819         va_list args;
02820         HostFILE * hf = NULL;
02821         Char text[0x100];
02822 
02823         hf = HostFOpen("\\pcity-buildcount.log", "a");
02824         if (hf) {
02825                 va_start(args, s);
02826                 StrVPrintF(text, s, args);
02827 
02828                 HostFPrintF(hf, text);
02829                 HostFClose(hf);
02830                 va_end(args);
02831         }
02832 }
02833 
02834 #endif

Generated on Mon Aug 30 19:44:16 2004 for pocketcity by doxygen1.2.18