1 #include "Directories.h"
2 #include "FileMan.h"
3 #include "Font.h"
4 #include "Font_Control.h"
5 #include "Input.h"
6 #include "Interface.h"
7 #include "LoadSaveData.h"
8 #include "Local.h"
9 #include "Timer.h"
10 #include "Timer_Control.h"
11 #include "VObject.h"
12 #include "VSurface.h"
13 #include "Render_Dirty.h"
14 #include "SysUtil.h"
15 #include "Screens.h"
16 #include "Cursors.h"
17 #include "Event_Pump.h"
18 #include "Laptop.h"
19 #include "AIM.h"
20 #include "AIMMembers.h"
21 #include "AIMFacialIndex.h"
22 #include "AIMSort.h"
23 #include "AIMArchives.h"
24 #include "AIMHistory.h"
25 #include "AIMLinks.h"
26 #include "AIMPolicies.h"
27 #include "Mercs.h"
28 #include "Mercs_Files.h"
29 #include "Mercs_Account.h"
30 #include "Mercs_No_Account.h"
31 #include "BobbyR.h"
32 #include "BobbyRGuns.h"
33 #include "BobbyRAmmo.h"
34 #include "BobbyRArmour.h"
35 #include "BobbyRMisc.h"
36 #include "BobbyRUsed.h"
37 #include "BobbyRMailOrder.h"
38 #include "CharProfile.h"
39 #include "Florist.h"
40 #include "Florist_Cards.h"
41 #include "Florist_Gallery.h"
42 #include "Florist_Order_Form.h"
43 #include "Insurance.h"
44 #include "Insurance_Contract.h"
45 #include "Insurance_Info.h"
46 #include "Insurance_Comments.h"
47 #include "Funeral.h"
48 #include "Finances.h"
49 #include "Personnel.h"
50 #include "History.h"
51 #include "Files.h"
52 #include "EMail.h"
53 #include "Interface_Control.h"
54 #include "Game_Event_Hook.h"
55 #include "WordWrap.h"
56 #include "Game_Init.h"
57 #include "Game_Clock.h"
58 #include "Soldier_Control.h"
59 #include "Soldier_Profile.h"
60 #include "Overhead.h"
61 #include "Environment.h"
62 #include "Music_Control.h"
63 #include "ContentMusic.h"
64 #include "LaptopSave.h"
65 #include "RenderWorld.h"
66 #include "GameLoop.h"
67 #include "English.h"
68 #include "Random.h"
69 #include "Merc_Hiring.h"
70 #include "Map_Screen_Interface.h"
71 #include "Ambient_Control.h"
72 #include "Sound_Control.h"
73 #include "Text.h"
74 #include "Message.h"
75 #include "Map_Screen_Interface_Bottom.h"
76 #include "Cursor_Control.h"
77 #include "Quests.h"
78 #include "Multi_Language_Graphic_Utils.h"
79 #include "BrokenLink.h"
80 #include "BobbyRShipments.h"
81 #include "Dialogue_Control.h"
82 #include "HelpScreen.h"
83 #include "Cheats.h"
84 #include "Video.h"
85 #include "MemMan.h"
86 #include "Debug.h"
87 #include "Button_System.h"
88 #include "JAScreens.h"
89 #include "UILayout.h"
90 
91 #include <string_theory/format>
92 #include <string_theory/string>
93 
94 #include <algorithm>
95 #include <iterator>
96 
97 // laptop programs
98 enum
99 {
100 	LAPTOP_PROGRAM_MAILER,
101 	LAPTOP_PROGRAM_WEB_BROWSER,
102 	LAPTOP_PROGRAM_FILES,
103 	LAPTOP_PROGRAM_PERSONNEL,
104 	LAPTOP_PROGRAM_FINANCES,
105 	LAPTOP_PROGRAM_HISTORY
106 };
107 
108 // laptop program states
109 enum
110 {
111 	LAPTOP_PROGRAM_MINIMIZED,
112 	LAPTOP_PROGRAM_OPEN
113 };
114 
115 #define BOOK_FONT     FONT10ARIAL
116 #define DOWNLOAD_FONT FONT12ARIAL
117 
118 
119 #define BOOK_X      (111 + STD_SCREEN_X)
120 #define BOOK_TOP_Y  ( 79 + STD_SCREEN_Y)
121 #define BOOK_HEIGHT  12
122 #define DOWN_HEIGHT  19
123 #define BOOK_WIDTH  100
124 
125 
126 #define LONG_UNIT_TIME        120
127 #define UNIT_TIME              40
128 #define FAST_UNIT_TIME          3
129 #define FASTEST_UNIT_TIME       2
130 #define ALMOST_FAST_UNIT_TIME  25
131 #define DOWNLOAD_X            (300 + STD_SCREEN_X)
132 #define DOWNLOAD_Y            (200 + STD_SCREEN_Y)
133 #define LAPTOP_WINDOW_X       DOWNLOAD_X + 12
134 #define LAPTOP_WINDOW_Y       DOWNLOAD_Y + 25
135 #define LAPTOP_BAR_Y          LAPTOP_WINDOW_Y + 2
136 #define LAPTOP_BAR_X          LAPTOP_WINDOW_X + 1
137 #define UNIT_WIDTH              4
138 #define DOWN_STRING_X         DOWNLOAD_X + 47
139 #define DOWN_STRING_Y         DOWNLOAD_Y +  5
140 #define LAPTOP_TITLE_ICONS_X  (113 + STD_SCREEN_X)
141 #define LAPTOP_TITLE_ICONS_Y  ( 27 + STD_SCREEN_Y)
142 
143 // HD flicker times
144 #define HD_FLICKER_TIME 3000
145 #define FLICKER_TIME      50
146 
147 
148 #define NUMBER_OF_LAPTOP_TITLEBAR_ITERATIONS  18
149 #define LAPTOP_TITLE_BAR_WIDTH               500
150 #define LAPTOP_TITLE_BAR_HEIGHT               24
151 
152 #define LAPTOP_TITLE_BAR_TOP_LEFT_X          (111 + STD_SCREEN_X)
153 #define LAPTOP_TITLE_BAR_TOP_LEFT_Y          ( 25 + STD_SCREEN_Y)
154 #define LAPTOP_TITLE_BAR_TOP_RIGHT_X         (610 + STD_SCREEN_X)
155 
156 #define LAPTOP_TITLE_BAR_ICON_OFFSET_X         (5 + STD_SCREEN_X)
157 #define LAPTOP_TITLE_BAR_ICON_OFFSET_Y         (2 + STD_SCREEN_Y)
158 #define LAPTOP_TITLE_BAR_TEXT_OFFSET_X        (29 + STD_SCREEN_X)
159 #define LAPTOP_TITLE_BAR_TEXT_OFFSET_Y         (8 + STD_SCREEN_Y)
160 
161 #define LAPTOP_PROGRAM_ICON_X      LAPTOP_TITLE_BAR_TOP_LEFT_X
162 #define LAPTOP_PROGRAM_ICON_Y      LAPTOP_TITLE_BAR_TOP_LEFT_Y
163 #define LAPTOP_PROGRAM_ICON_WIDTH  20
164 #define LAPTOP_PROGRAM_ICON_HEIGHT 20
165 #define DISPLAY_TIME_FOR_WEB_BOOKMARK_NOTIFY 2000
166 
167 // the wait time for closing of laptop animation/delay
168 #define EXIT_LAPTOP_DELAY_TIME 100
169 
170 static SGPVSurface* guiTitleBarSurface;
171 static BOOLEAN gfTitleBarSurfaceAlreadyActive = FALSE;
172 
173 #define LAPTOP__NEW_FILE_ICON_X  (83 + STD_SCREEN_X)
174 #define LAPTOP__NEW_FILE_ICON_Y (412 + STD_SCREEN_Y)
175 
176 #define LAPTOP__NEW_EMAIL_ICON_X ((83 - 16) + STD_SCREEN_X)
177 #define LAPTOP__NEW_EMAIL_ICON_Y LAPTOP__NEW_FILE_ICON_Y
178 
179 
180 // Mode values
181 LaptopMode        guiCurrentLaptopMode;
182 LaptopMode        guiPreviousLaptopMode;
183 // Used to prevent double free problems. Fixes Stracciatella issue #68:
184 LaptopMode        guiLastExitedLaptopMode = LAPTOP_MODE_NONE;
185 static LaptopMode guiCurrentWWWMode = LAPTOP_MODE_NONE;
186 INT32  giCurrentSubPage;
187 
188 
189 static INT32 iHighLightBookLine = -1;
190 BOOLEAN fFastLoadFlag = FALSE;
191 static BOOLEAN gfEnterLapTop=TRUE;
192 BOOLEAN gfShowBookmarks=FALSE;
193 
194 // in progress of loading a page?
195 BOOLEAN fLoadPendingFlag=FALSE;
196 
197 // mark buttons dirty?
198 static BOOLEAN fMarkButtonsDirtyFlag = TRUE;
199 
200 // redraw afer rendering buttons?
201 BOOLEAN fReDrawPostButtonRender = FALSE;
202 
203 // in laptop right now?
204 BOOLEAN fCurrentlyInLaptop = FALSE;
205 
206 // exit due to a message box pop up?..don't really leave LAPTOP
207 BOOLEAN fExitDueToMessageBox = FALSE;
208 
209 // exit laptop during a load?
210 static BOOLEAN fExitDuringLoad = FALSE;
211 
212 // done loading?
213 BOOLEAN fDoneLoadPending = FALSE;
214 
215 // going a subpage of a web page?..faster access time
216 BOOLEAN fConnectingToSubPage = FALSE;
217 
218 // is this our first time in laptop?
219 static BOOLEAN fFirstTimeInLaptop = TRUE;
220 
221 // redraw the book mark info panel .. for blitting on top of animations
222 BOOLEAN fReDrawBookMarkInfo = FALSE;
223 
224 // show the 2 second info about bookmarks being accessed by clicking on web
225 BOOLEAN fShowBookmarkInfo = FALSE;
226 
227 //GLOBAL FOR WHICH SCREEN TO EXIT TO FOR LAPTOP
228 static ScreenID guiExitScreen = MAP_SCREEN;
229 
230 // Laptop screen graphic handle
231 static SGPVObject* guiLAPTOP;
232 
233 static BOOLEAN fNewWWW = TRUE;
234 
235 //Used to store the site to go to after the 'rain delay' message
236 extern UINT32 guiRainLoop;
237 
238 
239 static INT32 giRainDelayInternetSite = -1;
240 
241 
242 // the laptop icons
243 static SGPVObject* guiBOOKHIGH;
244 static SGPVObject* guiBOOKMARK;
245 static SGPVObject* guiGRAPHWINDOW;
246 static SGPVObject* guiGRAPHBAR;
247 SGPVObject* guiLaptopBACKGROUND;
248 static SGPVObject* guiDOWNLOADTOP;
249 static SGPVObject* guiDOWNLOADMID;
250 static SGPVObject* guiDOWNLOADBOT;
251 static SGPVObject* guiTITLEBARLAPTOP;
252 static SGPVObject* guiLIGHTS;
253 SGPVObject* guiTITLEBARICONS;
254 static SGPVSurface* guiDESKTOP;
255 
256 // enter new laptop mode due to sliding bars
257 static BOOLEAN fEnteredNewLapTopDueToHandleSlidingBars = FALSE;
258 
259 
260 // whether or not we are initing the slide in title bar
261 static BOOLEAN fInitTitle = TRUE;
262 
263 // tab handled
264 static BOOLEAN fTabHandled = FALSE;
265 
266 static GUIButtonRef gLaptopButton[7];
267 
268 // minimize button
269 static GUIButtonRef gLaptopMinButton;
270 
271 
272 static INT32 gLaptopProgramStates[LAPTOP_PROGRAM_HISTORY + 1];
273 
274 // process of mazimizing
275 static BOOLEAN fMaximizingProgram = FALSE;
276 
277 // program we are maximizing
278 static INT8 bProgramBeingMaximized = -1;
279 
280 // are we minimizing
281 static BOOLEAN fMinizingProgram = FALSE;
282 
283 
284 // process openned queue
285 static INT32 gLaptopProgramQueueList[6];
286 
287 
288 BOOLEAN fExitingLaptopFlag = FALSE;
289 
290 // HD and power lights on
291 static BOOLEAN fPowerLightOn = TRUE;
292 static BOOLEAN fHardDriveLightOn = FALSE;
293 
294 // HD flicker
295 static BOOLEAN fFlickerHD = FALSE;
296 
297 // the screens limiting rect
298 static const SGPRect LaptopScreenRect = { LAPTOP_UL_X, (UINT16)(LAPTOP_UL_Y - 5), (UINT16)(LAPTOP_SCREEN_LR_X + 2), (UINT16)(LAPTOP_SCREEN_LR_Y + 5 + 19) };
299 
300 
301 // the sub pages vistsed or not status within the web browser
302 static bool gfWWWaitSubSitesVisitedFlags[LAPTOP_MODE_END - (LAPTOP_MODE_WWW + 1)];
303 
304 // mouse regions
305 static MOUSE_REGION gLapTopScreenRegion;
306 static MOUSE_REGION gBookmarkMouseRegions[MAX_BOOKMARKS];
307 static MOUSE_REGION gLapTopProgramMinIcon;
308 static MOUSE_REGION gNewMailIconRegion;
309 static MOUSE_REGION gNewFileIconRegion;
310 
311 
312 //used for global variables that need to be saved
313 LaptopSaveInfoStruct LaptopSaveInfo;
314 
315 
316 BOOLEAN fReDrawScreenFlag=FALSE;
317 BOOLEAN fPausedReDrawScreenFlag=FALSE; //used in the handler functions to redraw the screen, after the current frame
318 void PrintBalance(void);
319 
320 
321 void PrintDate(void);
322 void PrintNumberOnTeam(void);
323 
324 extern void ClearHistoryList(void);
325 
326 
SetLaptopExitScreen(ScreenID const uiExitScreen)327 void SetLaptopExitScreen(ScreenID const uiExitScreen)
328 {
329 	guiExitScreen = uiExitScreen;
330 }
331 
332 
SetLaptopNewGameFlag(void)333 void SetLaptopNewGameFlag(void)
334 {
335 	LaptopSaveInfo.gfNewGameLaptop = TRUE;
336 }
337 
338 
GetLaptopKeyboardInput(void)339 static void GetLaptopKeyboardInput(void)
340 {
341 	SGPPoint MousePos;
342 	GetMousePos(&MousePos);
343 
344 	fTabHandled = FALSE;
345 
346 	InputAtom InputEvent;
347 	while (DequeueEvent(&InputEvent))
348 	{
349 		MouseSystemHook(InputEvent.usEvent, MousePos.iX, MousePos.iY);
350 		HandleKeyBoardShortCutsForLapTop(InputEvent.usEvent, InputEvent.usParam, InputEvent.usKeyState);
351 	}
352 }
353 
354 
355 static void InitBookMarkList(void);
356 
357 
358 //This is called only once at game initialization.
LaptopScreenInit(void)359 void LaptopScreenInit(void)
360 {
361 	//Memset the whole structure, to make sure of no 'JUNK'
362 	LaptopSaveInfo = LaptopSaveInfoStruct{};
363 
364 	LaptopSaveInfo.gfNewGameLaptop = TRUE;
365 
366 	//reset the id of the last hired merc
367 	LaptopSaveInfo.sLastHiredMerc.iIdOfMerc = -1;
368 
369 	//reset the flag that enables the 'just hired merc' popup
370 	LaptopSaveInfo.sLastHiredMerc.fHaveDisplayedPopUpInLaptop = FALSE;
371 
372 	//Initialize all vars
373 	guiCurrentLaptopMode  = LAPTOP_MODE_EMAIL;
374 	guiPreviousLaptopMode = LAPTOP_MODE_NONE;
375 	guiCurrentWWWMode     = LAPTOP_MODE_NONE;
376 
377 	gfShowBookmarks = FALSE;
378 	InitBookMarkList();
379 	GameInitAIM();
380 	GameInitAimSort();
381 	GameInitMercs();
382 	GameInitBobbyRGuns();
383 	GameInitBobbyRMailOrder();
384 	GameInitEmail();
385 	GameInitCharProfile();
386 	GameInitFiles();
387 	GameInitPersonnel();
388 
389 	// init program states
390 	std::fill(std::begin(gLaptopProgramStates), std::end(gLaptopProgramStates), LAPTOP_PROGRAM_MINIMIZED);
391 
392 	gfAtLeastOneMercWasHired = FALSE;
393 
394 	//No longer inits the laptop screens, now InitLaptopAndLaptopScreens() does
395 }
396 
397 
InitLaptopAndLaptopScreens(void)398 void InitLaptopAndLaptopScreens(void)
399 {
400 	GameInitFinances();
401 	GameInitHistory();
402 
403 	//Reset the flag so we can create a new IMP character
404 	LaptopSaveInfo.fIMPCompletedFlag = FALSE;
405 
406 	//Reset the flag so that BOBBYR's isnt available at the begining of the game
407 	LaptopSaveInfo.fBobbyRSiteCanBeAccessed = FALSE;
408 }
409 
410 
411 //This is only called once at game shutdown.
LaptopScreenShutdown(void)412 void LaptopScreenShutdown(void)
413 {
414 	InsuranceContractEndGameShutDown();
415 	BobbyRayMailOrderEndGameShutDown();
416 	ShutDownEmailList();
417 	ClearHistoryList();
418 }
419 
420 
421 static void CreateDestroyMouseRegionForNewMailIcon(void);
422 static void CreateLapTopMouseRegions(void);
423 static void DrawDeskTopBackground(void);
424 static void EnterLaptopInitLaptopPages(void);
425 static void InitLaptopOpenQueue(void);
426 static void InitalizeSubSitesList(void);
427 static BOOLEAN IsItRaining(void);
428 static void LoadBookmark(void);
429 static void LoadDesktopBackground(void);
430 static void LoadLoadPending(void);
431 static void RenderLapTopImage(void);
432 
433 
EnterLaptop(void)434 static void EnterLaptop(void)
435 {
436 	//Create, load, initialize data -- just entered the laptop.
437 
438 	// we are re entering due to message box, leave NOW!
439 	if (fExitDueToMessageBox) return;
440 
441 	//if the radar map mouse region is still active, disable it.
442 	if (gRadarRegion.uiFlags & MSYS_REGION_ENABLED)
443 	{
444 		gRadarRegion.Disable();
445 	}
446 
447 	gfDontStartTransitionFromLaptop = FALSE;
448 
449 	// ATE: Disable messages....
450 	DisableScrollMessages();
451 
452 	// Stop any person from saying anything
453 	StopAnyCurrentlyTalkingSpeech();
454 
455 	// Don't play music....
456 	SetMusicMode(MUSIC_LAPTOP);
457 
458 	// Stop ambients...
459 	StopAmbients();
460 
461 	//if its raining, start the rain showers
462 	if (IsItRaining())
463 	{
464 		//Enable the rain delay warning
465 		giRainDelayInternetSite = -1;
466 
467 		//lower the volume
468 		guiRainLoop = PlayJA2Ambient(RAIN_1, LOWVOLUME, 0);
469 	}
470 
471 	//pause the game because we dont want time to advance in the laptop
472 	PauseGame();
473 
474 	// set the fact we are currently in laptop, for rendering purposes
475 	fCurrentlyInLaptop = TRUE;
476 
477 	// reset redraw flag and redraw new mail
478 	fReDrawScreenFlag  = FALSE;
479 	fReDrawNewMailFlag = TRUE;
480 
481 	// sub page
482 	giCurrentSubPage = 0;
483 
484 	// load the laptop graphic and add it
485 	guiLAPTOP = AddVideoObjectFromFile(LAPTOPDIR "/laptop3.sti");
486 
487 	// background for panel
488 	guiLaptopBACKGROUND = AddVideoObjectFromFile(LAPTOPDIR "/taskbar.sti");
489 
490 	// background for panel
491 	guiTITLEBARLAPTOP = AddVideoObjectFromFile(LAPTOPDIR "/programtitlebar.sti");
492 
493 	// lights for power and HD
494 	guiLIGHTS = AddVideoObjectFromFile(LAPTOPDIR "/lights.sti");
495 
496 	// icons for title bars
497 	guiTITLEBARICONS = AddVideoObjectFromFile(LAPTOPDIR "/icons.sti");
498 
499 	// load, blt and delete graphics
500 	guiEmailWarning = AddVideoObjectFromFile(LAPTOPDIR "/newmailwarning.sti");
501 	// load background
502 	LoadDesktopBackground();
503 
504 	guiCurrentLaptopMode  = LAPTOP_MODE_NONE;
505 	guiPreviousLaptopMode = LAPTOP_MODE_NONE;
506 	guiCurrentWWWMode     = LAPTOP_MODE_NONE;
507 	CreateLapTopMouseRegions();
508 	RenderLapTopImage();
509 
510 	// reset bookmarks flags
511 	fFirstTimeInLaptop = TRUE;
512 
513 	// reset all bookmark visits
514 	std::fill(std::begin(LaptopSaveInfo.fVisitedBookmarkAlready), std::end(LaptopSaveInfo.fVisitedBookmarkAlready), 0);
515 
516 	// init program states
517 	std::fill(std::begin(gLaptopProgramStates), std::end(gLaptopProgramStates), LAPTOP_PROGRAM_MINIMIZED);
518 
519 	// turn the power on
520 	fPowerLightOn = TRUE;
521 
522 	// we are not exiting laptop right now, we just got here
523 	fExitingLaptopFlag = FALSE;
524 
525 	// reset program we are maximizing
526 	bProgramBeingMaximized = -1;
527 
528 	// reset fact we are maximizing/ mining
529 	fMaximizingProgram = FALSE;
530 	fMinizingProgram = FALSE;
531 
532 
533 	// initialize open queue
534 	InitLaptopOpenQueue();
535 
536 
537 	gfShowBookmarks = FALSE;
538 	LoadBookmark();
539 	SetBookMark(AIM_BOOKMARK);
540 	LoadLoadPending();
541 
542 	DrawDeskTopBackground();
543 
544 	// create region for new mail icon
545 	CreateDestroyMouseRegionForNewMailIcon();
546 
547 	//DEF: Added to Init things in various laptop pages
548 	EnterLaptopInitLaptopPages();
549 	InitalizeSubSitesList();
550 
551 	InvalidateScreen();
552 }
553 
554 
555 static void CreateDestoryBookMarkRegions(void);
556 static void CreateDestroyMinimizeButtonForCurrentMode(void);
557 static void DeleteBookmark(void);
558 static void DeleteDesktopBackground(void);
559 static void DeleteLapTopButtons(void);
560 static void DeleteLapTopMouseRegions(void);
561 static void DeleteLoadPending(void);
562 static void ExitLaptopMode(LaptopMode uiMode);
563 
564 
ExitLaptop(void)565 void ExitLaptop(void)
566 {
567 	// exit is called due to message box, leave
568 	if (fExitDueToMessageBox)
569 	{
570 		fExitDueToMessageBox = FALSE;
571 		return;
572 	}
573 
574 	if (DidGameJustStart())
575 	{
576 		SetMusicMode(MUSIC_LAPTOP);
577 	}
578 	else
579 	{
580 		// Restore to old stuff...
581 		SetMusicMode(MUSIC_RESTORE);
582 	}
583 
584 	// Start ambients...
585 	BuildDayAmbientSounds();
586 
587 	//if its raining, start the rain showers
588 	if (IsItRaining())
589 	{
590 		//Raise the volume to where it was
591 		guiRainLoop = PlayJA2Ambient(RAIN_1, MIDVOLUME, 0);
592 	}
593 
594 	// release cursor
595 	FreeMouseCursor();
596 
597 	// set the fact we are currently not in laptop, for rendering purposes
598 	fCurrentlyInLaptop = FALSE;
599 
600 	//Deallocate, save data -- leaving laptop.
601 	SetRenderFlags(RENDER_FLAG_FULL);
602 
603 	ExitLaptopMode(fExitDuringLoad ? guiPreviousLaptopMode : guiCurrentLaptopMode);
604 
605 	fExitDuringLoad  = FALSE;
606 	fLoadPendingFlag = FALSE;
607 
608 
609 	DeleteVideoObject(guiLAPTOP);
610 	DeleteVideoObject(guiLaptopBACKGROUND);
611 	DeleteVideoObject(guiTITLEBARLAPTOP);
612 	DeleteVideoObject(guiLIGHTS);
613 	DeleteVideoObject(guiTITLEBARICONS);
614 	DeleteVideoObject(guiEmailWarning);
615 
616 	// destroy region for new mail icon
617 	CreateDestroyMouseRegionForNewMailIcon();
618 
619 	// get rid of desktop
620 	DeleteDesktopBackground();
621 
622 	if (MailToDelete != NULL)
623 	{
624 		MailToDelete = NULL;
625 		CreateDestroyDeleteNoticeMailButton();
626 	}
627 	if (fNewMailFlag)
628 	{
629 		fNewMailFlag = FALSE;
630 		CreateDestroyNewMailButton();
631 	}
632 
633 	// get rid of minize button
634 	CreateDestroyMinimizeButtonForCurrentMode();
635 
636 	//MSYS_SetCurrentCursor(CURSOR_NORMAL);
637 	gfEnterLapTop=TRUE;
638 	DeleteLapTopButtons();
639 	DeleteLapTopMouseRegions();
640 	gfShowBookmarks = FALSE;
641 	CreateDestoryBookMarkRegions();
642 
643 	fNewWWW = TRUE;
644 	DeleteBookmark();
645 	DeleteLoadPending();
646 	fReDrawNewMailFlag = FALSE;
647 
648 	//pause the game because we dont want time to advance in the laptop
649 	UnPauseGame();
650 }
651 
652 
RenderLapTopImage(void)653 static void RenderLapTopImage(void)
654 {
655 	if (fMaximizingProgram || fMinizingProgram) return;
656 
657 	BltVideoObject(FRAME_BUFFER, guiLAPTOP,           0, LAPTOP_X,      LAPTOP_Y);
658 	BltVideoObject(FRAME_BUFFER, guiLaptopBACKGROUND, 1, LAPTOP_X + 25, LAPTOP_Y + 23);
659 
660 	MarkButtonsDirty();
661 }
662 
663 
RenderLaptop(void)664 static void RenderLaptop(void)
665 {
666 	if (fMaximizingProgram || fMinizingProgram)
667 	{
668 		gfShowBookmarks = FALSE;
669 		return;
670 	}
671 
672 	LaptopMode uiTempMode = LAPTOP_MODE_NONE;
673 	if (fLoadPendingFlag || fExitDuringLoad)
674 	{
675 		uiTempMode           = guiCurrentLaptopMode;
676 		guiCurrentLaptopMode = guiPreviousLaptopMode;
677 	}
678 
679 	switch (guiCurrentLaptopMode)
680 	{
681 		case LAPTOP_MODE_NONE:                     DrawDeskTopBackground();   break;
682 
683 		case LAPTOP_MODE_AIM:                      RenderAIM();               break;
684 		case LAPTOP_MODE_AIM_MEMBERS:              RenderAIMMembers();        break;
685 		case LAPTOP_MODE_AIM_MEMBERS_FACIAL_INDEX: RenderAimFacialIndex();    break;
686 		case LAPTOP_MODE_AIM_MEMBERS_SORTED_FILES: RenderAimSort();           break;
687 		case LAPTOP_MODE_AIM_MEMBERS_ARCHIVES:     RenderAimArchives();       break;
688 		case LAPTOP_MODE_AIM_POLICIES:             RenderAimPolicies();       break;
689 		case LAPTOP_MODE_AIM_LINKS:                RenderAimLinks();          break;
690 		case LAPTOP_MODE_AIM_HISTORY:              RenderAimHistory();        break;
691 
692 		case LAPTOP_MODE_MERC:                     RenderMercs();             break;
693 		case LAPTOP_MODE_MERC_FILES:               RenderMercsFiles();        break;
694 		case LAPTOP_MODE_MERC_ACCOUNT:             RenderMercsAccount();      break;
695 		case LAPTOP_MODE_MERC_NO_ACCOUNT:          RenderMercsNoAccount();    break;
696 
697 		case LAPTOP_MODE_BOBBY_R:                  RenderBobbyR();            break;
698 		case LAPTOP_MODE_BOBBY_R_GUNS:             RenderBobbyRGuns();        break;
699 		case LAPTOP_MODE_BOBBY_R_AMMO:             RenderBobbyRAmmo();        break;
700 		case LAPTOP_MODE_BOBBY_R_ARMOR:            RenderBobbyRArmour();      break;
701 		case LAPTOP_MODE_BOBBY_R_MISC:             RenderBobbyRMisc();        break;
702 		case LAPTOP_MODE_BOBBY_R_USED:             RenderBobbyRUsed();        break;
703 		case LAPTOP_MODE_BOBBY_R_MAILORDER:        RenderBobbyRMailOrder();   break;
704 		case LAPTOP_MODE_BOBBYR_SHIPMENTS:         RenderBobbyRShipments();   break;
705 
706 		case LAPTOP_MODE_CHAR_PROFILE:             RenderCharProfile();       break;
707 
708 		case LAPTOP_MODE_FLORIST:                  RenderFlorist();           break;
709 		case LAPTOP_MODE_FLORIST_FLOWER_GALLERY:   RenderFloristGallery();    break;
710 		case LAPTOP_MODE_FLORIST_ORDERFORM:        RenderFloristOrderForm();  break;
711 		case LAPTOP_MODE_FLORIST_CARD_GALLERY:     RenderFloristCards();      break;
712 
713 		case LAPTOP_MODE_INSURANCE:                RenderInsurance();         break;
714 		case LAPTOP_MODE_INSURANCE_INFO:           RenderInsuranceInfo();     break;
715 		case LAPTOP_MODE_INSURANCE_CONTRACT:       RenderInsuranceContract(); break;
716 		case LAPTOP_MODE_INSURANCE_COMMENTS:       RenderInsuranceComments(); break;
717 
718 		case LAPTOP_MODE_FUNERAL:                  RenderFuneral();           break;
719 
720 		case LAPTOP_MODE_FINANCES:                 RenderFinances();          break;
721 		case LAPTOP_MODE_PERSONNEL:                RenderPersonnel();         break;
722 		case LAPTOP_MODE_HISTORY:                  RenderHistory();           break;
723 		case LAPTOP_MODE_FILES:                    RenderFiles();             break;
724 		case LAPTOP_MODE_EMAIL:                    RenderEmail();             break;
725 
726 		case LAPTOP_MODE_WWW:                      DrawDeskTopBackground();   break;
727 
728 		case LAPTOP_MODE_BROKEN_LINK:              RenderBrokenLink();        break;
729 				default:
730 						break;
731 	}
732 
733 	if (guiCurrentLaptopMode >= LAPTOP_MODE_WWW)
734 	{
735 		// render program bar for www program
736 		RenderWWWProgramTitleBar();
737 	}
738 
739 	if (fLoadPendingFlag)
740 	{
741 		guiCurrentLaptopMode = uiTempMode;
742 		return;
743 	}
744 
745 	DisplayProgramBoundingBox(FALSE);
746 
747 	// mark the buttons dirty at this point
748 	MarkButtonsDirty();
749 }
750 
751 
752 static void InitTitleBarMaximizeGraphics(const SGPVObject* uiBackgroundGraphic, const ST::string& str, const SGPVObject* uiIconGraphic, UINT16 usIconGraphicIndex);
753 static void SetSubSiteAsVisted(void);
754 
755 
EnterNewLaptopMode(void)756 static void EnterNewLaptopMode(void)
757 {
758 	static BOOLEAN fOldLoadFlag = FALSE;
759 
760 	if (fExitingLaptopFlag) return;
761 	// cause flicker, as we are going to a new program/WEB page
762 	fFlickerHD = TRUE;
763 
764 	// handle maximizing of programs
765 	UINT           prog;
766 	ST::string title;
767 	UINT16         gfx_idx;
768 	switch (guiCurrentLaptopMode)
769 	{
770 		case LAPTOP_MODE_EMAIL:
771 			prog    = LAPTOP_PROGRAM_MAILER;
772 			title   = pLaptopTitles[0];
773 			gfx_idx = 0;
774 			break;
775 
776 		case LAPTOP_MODE_FILES:
777 			prog    = LAPTOP_PROGRAM_FILES;
778 			title   = pLaptopTitles[1];
779 			gfx_idx = 2;
780 			break;
781 
782 		case LAPTOP_MODE_PERSONNEL:
783 			prog    = LAPTOP_PROGRAM_PERSONNEL;
784 			title   = pLaptopTitles[2];
785 			gfx_idx = 3;
786 			break;
787 
788 		case LAPTOP_MODE_FINANCES:
789 			prog    = LAPTOP_PROGRAM_FINANCES;
790 			title   = pLaptopTitles[3];
791 			gfx_idx = 5;
792 			break;
793 
794 		case LAPTOP_MODE_HISTORY:
795 			prog    = LAPTOP_PROGRAM_HISTORY;
796 			title   = pLaptopTitles[4];
797 			gfx_idx = 4;
798 			break;
799 
800 		case LAPTOP_MODE_NONE: goto do_nothing;
801 
802 		default:
803 			prog    = LAPTOP_PROGRAM_WEB_BROWSER;
804 			title   = pWebTitle;
805 			gfx_idx = 1;
806 			break;
807 	}
808 
809 	if (gLaptopProgramStates[prog] == LAPTOP_PROGRAM_MINIMIZED)
810 	{
811 		if (!fMaximizingProgram)
812 		{
813 			fInitTitle = TRUE;
814 			InitTitleBarMaximizeGraphics(guiTITLEBARLAPTOP, title, guiTITLEBARICONS, gfx_idx);
815 			ExitLaptopMode(guiPreviousLaptopMode);
816 		}
817 		fMaximizingProgram         = TRUE;
818 		bProgramBeingMaximized     = prog;
819 		gLaptopProgramStates[prog] = LAPTOP_PROGRAM_OPEN;
820 		return;
821 	}
822 
823 do_nothing:
824 	if (fMaximizingProgram || fMinizingProgram) return;
825 
826 	if (fOldLoadFlag && !fLoadPendingFlag)
827 	{
828 		fOldLoadFlag = FALSE;
829 	}
830 	else if (fLoadPendingFlag && !fOldLoadFlag)
831 	{
832 		ExitLaptopMode(guiPreviousLaptopMode);
833 		fOldLoadFlag = TRUE;
834 		return;
835 	}
836 	else if (fOldLoadFlag && fLoadPendingFlag)
837 	{
838 		return;
839 	}
840 	else
841 	{
842 		// do not exit previous mode if coming from sliding bar handler
843 		if (!fEnteredNewLapTopDueToHandleSlidingBars)
844 		{
845 			ExitLaptopMode(guiPreviousLaptopMode);
846 		}
847 	}
848 
849 	if (guiCurrentWWWMode == LAPTOP_MODE_NONE && guiCurrentLaptopMode >= LAPTOP_MODE_WWW)
850 	{
851 		RenderLapTopImage();
852 		guiCurrentLaptopMode = LAPTOP_MODE_WWW;
853 	}
854 	else if (guiCurrentLaptopMode > LAPTOP_MODE_WWW)
855 	{
856 		if (guiPreviousLaptopMode < LAPTOP_MODE_WWW)
857 		{
858 			guiCurrentLaptopMode = guiCurrentWWWMode;
859 		}
860 		else
861 		{
862 			guiCurrentWWWMode = guiCurrentLaptopMode;
863 			giCurrentSubPage  = 0;
864 		}
865 	}
866 
867 	if (guiCurrentLaptopMode >= LAPTOP_MODE_WWW)
868 	{
869 		RenderWWWProgramTitleBar();
870 		if (guiPreviousLaptopMode >= LAPTOP_MODE_WWW) gfShowBookmarks = FALSE;
871 	}
872 
873 	guiLastExitedLaptopMode = LAPTOP_MODE_NONE;
874 
875 	//Initialize the new mode.
876 	switch (guiCurrentLaptopMode)
877 	{
878 		case LAPTOP_MODE_AIM:                      EnterAIM();               break;
879 		case LAPTOP_MODE_AIM_MEMBERS:              EnterAIMMembers();        break;
880 		case LAPTOP_MODE_AIM_MEMBERS_FACIAL_INDEX: EnterAimFacialIndex();    break;
881 		case LAPTOP_MODE_AIM_MEMBERS_SORTED_FILES: EnterAimSort();           break;
882 		case LAPTOP_MODE_AIM_MEMBERS_ARCHIVES:     EnterAimArchives();       break;
883 		case LAPTOP_MODE_AIM_POLICIES:             EnterAimPolicies();       break;
884 		case LAPTOP_MODE_AIM_LINKS:                EnterAimLinks();          break;
885 		case LAPTOP_MODE_AIM_HISTORY:              EnterAimHistory();        break;
886 
887 		case LAPTOP_MODE_MERC:                     EnterMercs();             break;
888 		case LAPTOP_MODE_MERC_FILES:               EnterMercsFiles();        break;
889 		case LAPTOP_MODE_MERC_ACCOUNT:             EnterMercsAccount();      break;
890 		case LAPTOP_MODE_MERC_NO_ACCOUNT:          EnterMercsNoAccount();    break;
891 
892 		case LAPTOP_MODE_BOBBY_R:                  EnterBobbyR();            break;
893 		case LAPTOP_MODE_BOBBY_R_GUNS:             EnterBobbyRGuns();        break;
894 		case LAPTOP_MODE_BOBBY_R_AMMO:             EnterBobbyRAmmo();        break;
895 		case LAPTOP_MODE_BOBBY_R_ARMOR:            EnterBobbyRArmour();      break;
896 		case LAPTOP_MODE_BOBBY_R_MISC:             EnterBobbyRMisc();        break;
897 		case LAPTOP_MODE_BOBBY_R_USED:             EnterBobbyRUsed();        break;
898 		case LAPTOP_MODE_BOBBY_R_MAILORDER:        EnterBobbyRMailOrder();   break;
899 		case LAPTOP_MODE_BOBBYR_SHIPMENTS:         EnterBobbyRShipments();   break;
900 
901 		case LAPTOP_MODE_CHAR_PROFILE:             EnterCharProfile();       break;
902 
903 		case LAPTOP_MODE_FLORIST:                  EnterFlorist();           break;
904 		case LAPTOP_MODE_FLORIST_FLOWER_GALLERY:   EnterFloristGallery();    break;
905 		case LAPTOP_MODE_FLORIST_ORDERFORM:        EnterFloristOrderForm();  break;
906 		case LAPTOP_MODE_FLORIST_CARD_GALLERY:     EnterFloristCards();      break;
907 
908 		case LAPTOP_MODE_INSURANCE:                EnterInsurance();         break;
909 		case LAPTOP_MODE_INSURANCE_INFO:           EnterInsuranceInfo();     break;
910 		case LAPTOP_MODE_INSURANCE_CONTRACT:       EnterInsuranceContract(); break;
911 		case LAPTOP_MODE_INSURANCE_COMMENTS:       EnterInsuranceComments(); break;
912 
913 		case LAPTOP_MODE_FUNERAL:                  EnterFuneral();           break;
914 
915 		case LAPTOP_MODE_FINANCES:                 EnterFinances();          break;
916 		case LAPTOP_MODE_PERSONNEL:                EnterPersonnel();         break;
917 		case LAPTOP_MODE_HISTORY:                  EnterHistory();           break;
918 		case LAPTOP_MODE_FILES:                    EnterFiles();             break;
919 		case LAPTOP_MODE_EMAIL:                    EnterEmail();             break;
920 
921 		case LAPTOP_MODE_BROKEN_LINK:              EnterBrokenLink();        break;
922 				default:
923 						break;
924 	}
925 
926 	// first time using webbrowser in this laptop session
927 	if (fFirstTimeInLaptop && guiCurrentLaptopMode >= LAPTOP_MODE_WWW)
928 	{
929 		gfShowBookmarks    = TRUE;
930 		fFirstTimeInLaptop = FALSE;
931 	}
932 
933 	if (!fLoadPendingFlag)
934 	{
935 		CreateDestroyMinimizeButtonForCurrentMode();
936 		guiPreviousLaptopMode = guiCurrentLaptopMode;
937 		SetSubSiteAsVisted();
938 	}
939 
940 	DisplayProgramBoundingBox(TRUE);
941 }
942 
943 
HandleLapTopHandles(void)944 static void HandleLapTopHandles(void)
945 {
946 	if (fLoadPendingFlag) return;
947 
948 	if (fMaximizingProgram || fMinizingProgram) return;
949 
950 	switch (guiCurrentLaptopMode)
951 	{
952 		case LAPTOP_MODE_AIM:                      HandleAIM();               break;
953 		case LAPTOP_MODE_AIM_MEMBERS:              HandleAIMMembers();        break;
954 		case LAPTOP_MODE_AIM_MEMBERS_ARCHIVES:     HandleAimArchives();       break;
955 		case LAPTOP_MODE_AIM_POLICIES:             HandleAimPolicies();       break;
956 
957 		case LAPTOP_MODE_MERC:                     HandleMercs();             break;
958 		case LAPTOP_MODE_MERC_ACCOUNT:             HandleMercsAccount();      break;
959 
960 		case LAPTOP_MODE_BOBBY_R:                  HandleBobbyR();            break;
961 		case LAPTOP_MODE_BOBBY_R_MAILORDER:        HandleBobbyRMailOrder();   break;
962 		case LAPTOP_MODE_BOBBYR_SHIPMENTS:         HandleBobbyRShipments();   break;
963 
964 		case LAPTOP_MODE_CHAR_PROFILE:             HandleCharProfile();       break;
965 
966 		case LAPTOP_MODE_FLORIST_FLOWER_GALLERY:   HandleFloristGallery();    break;
967 		case LAPTOP_MODE_FLORIST_ORDERFORM:        HandleFloristOrderForm();  break;
968 
969 		case LAPTOP_MODE_INSURANCE_CONTRACT:       HandleInsuranceContract(); break;
970 
971 		case LAPTOP_MODE_PERSONNEL:                HandlePersonnel();         break;
972 		case LAPTOP_MODE_FILES:                    HandleFiles();             break;
973 		case LAPTOP_MODE_EMAIL:                    HandleEmail();             break;
974 				default:
975 						break;
976 	}
977 }
978 
979 
980 static void CheckIfNewWWWW(void);
981 static void CheckMarkButtonsDirtyFlag(void);
982 static void CreateLaptopButtons(void);
983 static void DisplayBookMarks(void);
984 static void DisplayLoadPending(void);
985 static void DisplayTaskBarIcons(void);
986 static void DisplayWebBookMarkNotify(void);
987 static void FlickerHDLight(void);
988 static void HandleSlidingTitleBar(void);
989 static void HandleWWWSubSites(void);
990 static void LeaveLapTopScreen(void);
991 static void PostButtonRendering(void);
992 static void ShouldNewMailBeDisplayed(void);
993 static void ShowLights(void);
994 static void UpdateStatusOfDisplayingBookMarks(void);
995 
996 
LaptopScreenHandle()997 ScreenID LaptopScreenHandle()
998 {
999 	//User just changed modes.  This is determined by the button callbacks
1000 	//created in LaptopScreenInit()
1001 
1002 	// just entered
1003 	if (gfEnterLapTop)
1004 	{
1005 		EnterLaptop();
1006 		CreateLaptopButtons();
1007 		gfEnterLapTop = FALSE;
1008 	}
1009 
1010 	if (gfStartMapScreenToLaptopTransition)
1011 	{ //Everything is set up to start the transition animation.
1012 		SetCurrentCursorFromDatabase(VIDEO_NO_CURSOR);
1013 		//Step 1:  Build the laptop image into the save buffer.
1014 		gfStartMapScreenToLaptopTransition = FALSE;
1015 		RestoreBackgroundRects();
1016 		RenderLapTopImage();
1017 		RenderLaptop();
1018 		RenderButtons();
1019 		PrintDate();
1020 		PrintBalance();
1021 		PrintNumberOnTeam();
1022 		ShowLights();
1023 
1024 		//Step 2:  The mapscreen image is in the EXTRABUFFER, and laptop is in the SAVEBUFFER
1025 		//         Start transitioning the screen.
1026 		SGPBox const DstRect = { STD_SCREEN_X, STD_SCREEN_Y, MAP_SCREEN_WIDTH, MAP_SCREEN_HEIGHT };
1027 		const UINT32 uiTimeRange = 1000;
1028 		INT32 iPercentage     = 0;
1029 		INT32 iRealPercentage = 0;
1030 		const UINT32 uiStartTime = GetClock();
1031 		BltVideoSurface(guiSAVEBUFFER, FRAME_BUFFER,   0, 0, NULL);
1032 		BltVideoSurface(FRAME_BUFFER,  guiEXTRABUFFER, 0, 0, NULL);
1033 		PlayJA2SampleFromFile(SOUNDSDIR "/laptop power up (8-11).wav", HIGHVOLUME, 1, MIDDLEPAN);
1034 		while (iRealPercentage < 100)
1035 		{
1036 			const UINT32 uiCurrTime = GetClock();
1037 			iPercentage = (uiCurrTime-uiStartTime) * 100 / uiTimeRange;
1038 			iPercentage = MIN(iPercentage, 100);
1039 
1040 			iRealPercentage = iPercentage;
1041 
1042 			//Factor the percentage so that it is modified by a gravity falling acceleration effect.
1043 			const INT32 iFactor = (iPercentage - 50) * 2;
1044 			if (iPercentage < 50)
1045 			{
1046 				iPercentage += iPercentage         * iFactor * 0.01 + 0.5;
1047 			}
1048 			else
1049 			{
1050 				iPercentage += (100 - iPercentage) * iFactor * 0.01 + 0.5;
1051 			}
1052 
1053 			INT32 iScalePercentage;
1054 			if (iPercentage < 99)
1055 			{
1056 				iScalePercentage = 10000 / (100 - iPercentage);
1057 			}
1058 			else
1059 			{
1060 				iScalePercentage = 5333;
1061 			}
1062 			const UINT16 uWidth  = 12 * iScalePercentage / 100;
1063 			const UINT16 uHeight =  9 * iScalePercentage / 100;
1064 			const UINT16 uX      = 472 - (472 - 320) * iScalePercentage / 5333;
1065 			const UINT16 uY      = 424 - (424 - 240) * iScalePercentage / 5333;
1066 
1067 			SGPBox const SrcRect2 = { (UINT16)(STD_SCREEN_X + uX - uWidth / 2), (UINT16)(STD_SCREEN_Y + uY - uHeight / 2), uWidth, uHeight };
1068 
1069 			BltStretchVideoSurface(FRAME_BUFFER, guiSAVEBUFFER, &DstRect, &SrcRect2);
1070 			InvalidateScreen();
1071 			RefreshScreen();
1072 		}
1073 		fReDrawScreenFlag = TRUE;
1074 	}
1075 
1076 	//DO NOT MOVE THIS FUNCTION CALL!!!
1077 
1078 	//This determines if the help screen should be active
1079 	if (ShouldTheHelpScreenComeUp(HELP_SCREEN_LAPTOP, FALSE))
1080 	{
1081 		// handle the help screen
1082 		HelpScreenHandler();
1083 		return LAPTOP_SCREEN;
1084 	}
1085 
1086 	RestoreBackgroundRects();
1087 
1088 	// lock cursor to screen
1089 	RestrictMouseCursor(&LaptopScreenRect);
1090 
1091 	// handle animated cursors
1092 	HandleAnimatedCursors();
1093 	// Deque all game events
1094 	DequeAllGameEvents();
1095 
1096 	// handle sub sites..like BR Guns, BR Ammo, Armour, Misc...for WW Wait..since they are not true sub pages
1097 	// and are not individual sites
1098 	HandleWWWSubSites();
1099 	UpdateStatusOfDisplayingBookMarks();
1100 
1101 	// check if we need to reset new WWW mode
1102 	CheckIfNewWWWW();
1103 
1104 	if (guiCurrentLaptopMode != guiPreviousLaptopMode)
1105 	{
1106 		if (guiCurrentLaptopMode <=LAPTOP_MODE_WWW) fLoadPendingFlag = FALSE;
1107 
1108 		if (!fMaximizingProgram && !fMinizingProgram)
1109 		{
1110 			if (guiCurrentLaptopMode <= LAPTOP_MODE_WWW)
1111 			{
1112 				EnterNewLaptopMode();
1113 				if (!fMaximizingProgram && !fMinizingProgram)
1114 				{
1115 					guiPreviousLaptopMode = guiCurrentLaptopMode;
1116 				}
1117 			}
1118 			else
1119 			{
1120 				if (!fLoadPendingFlag)
1121 				{
1122 					EnterNewLaptopMode();
1123 					guiPreviousLaptopMode = guiCurrentLaptopMode;
1124 				}
1125 			}
1126 		}
1127 	}
1128 	if (fPausedReDrawScreenFlag)
1129 	{
1130 		fReDrawScreenFlag       = TRUE;
1131 		fPausedReDrawScreenFlag = FALSE;
1132 	}
1133 
1134 	if (fReDrawScreenFlag)
1135 	{
1136 		RenderLapTopImage();
1137 		RenderLaptop();
1138 	}
1139 
1140 	// are we about to leave laptop
1141 	if (fExitingLaptopFlag)
1142 	{
1143 		if (fLoadPendingFlag)
1144 		{
1145 			fLoadPendingFlag = FALSE;
1146 			fExitDuringLoad  = TRUE;
1147 		}
1148 		LeaveLapTopScreen();
1149 	}
1150 
1151 	if (!fExitingLaptopFlag)
1152 	{
1153 		// handle handles for laptop input stream
1154 		HandleLapTopHandles();
1155 	}
1156 
1157 	// get keyboard input, handle it
1158 	GetLaptopKeyboardInput();
1159 
1160 	// check to see if new mail box needs to be displayed
1161 	CreateDestroyNewMailButton();
1162 	DisplayNewMailBox();
1163 
1164 	// create various mouse regions that are global to laptop system
1165 	CreateDestoryBookMarkRegions();
1166 
1167 	// check to see if buttons marked dirty
1168 	CheckMarkButtonsDirtyFlag();
1169 
1170 	// check to see if new mail box needs to be displayed
1171 	ShouldNewMailBeDisplayed();
1172 
1173 	// check to see if new mail box needs to be displayed
1174 	ReDrawNewMailBox();
1175 
1176 	// look for unread email
1177 	LookForUnread();
1178 	//Handle keyboard shortcuts...
1179 
1180 	if (!fLoadPendingFlag || fNewMailFlag)
1181 	{
1182 		// render buttons marked dirty
1183 		RenderButtons();
1184 	}
1185 
1186 	// check to see if bookmarks need to be displayed
1187 	if (gfShowBookmarks)
1188 	{
1189 		if (fExitingLaptopFlag)
1190 		{
1191 			gfShowBookmarks = FALSE;
1192 		}
1193 		else
1194 		{
1195 			DisplayBookMarks();
1196 		}
1197 	}
1198 
1199 	// check to see if laod pending flag is set
1200 	DisplayLoadPending();
1201 
1202 	// check if we are showing message?
1203 	DisplayWebBookMarkNotify();
1204 
1205 	if (fReDrawPostButtonRender)
1206 	{
1207 		// rendering AFTER buttons and button text
1208 		if (!fMaximizingProgram && !fMinizingProgram)
1209 		{
1210 			PostButtonRendering();
1211 		}
1212 	}
1213 
1214 	PrintDate();
1215 	PrintBalance();
1216 	PrintNumberOnTeam();
1217 	DisplayTaskBarIcons();
1218 
1219 	// handle if we are maximizing a program from a minimized state or vice versa
1220 	HandleSlidingTitleBar();
1221 
1222 	// flicker HD light as nessacary
1223 	FlickerHDLight();
1224 
1225 	// display power and HD lights
1226 	ShowLights();
1227 
1228 	// render frame rate
1229 	DisplayFrameRate();
1230 
1231 	// invalidate screen if redrawn
1232 	if (fReDrawScreenFlag)
1233 	{
1234 		InvalidateScreen();
1235 		fReDrawScreenFlag = FALSE;
1236 	}
1237 
1238 	ExecuteVideoOverlays();
1239 
1240 	SaveBackgroundRects();
1241 	RenderFastHelp();
1242 
1243 	// ex SAVEBUFFER queue
1244 	ExecuteBaseDirtyRectQueue();
1245 	ResetInterface();
1246 	EndFrameBufferRender();
1247 	return (LAPTOP_SCREEN);
1248 }
1249 
1250 
ExitLaptopMode(LaptopMode uiMode)1251 static void ExitLaptopMode(LaptopMode uiMode)
1252 {
1253 	if (guiLastExitedLaptopMode == uiMode) {
1254 		return;
1255 	}
1256 
1257 	// Deallocate the previous mode that you were in.
1258 	switch (uiMode)
1259 	{
1260 		case LAPTOP_MODE_AIM:                      ExitAIM();               break;
1261 		case LAPTOP_MODE_AIM_MEMBERS:              ExitAIMMembers();        break;
1262 		case LAPTOP_MODE_AIM_MEMBERS_FACIAL_INDEX: ExitAimFacialIndex();    break;
1263 		case LAPTOP_MODE_AIM_MEMBERS_SORTED_FILES: ExitAimSort();           break;
1264 		case LAPTOP_MODE_AIM_MEMBERS_ARCHIVES:     ExitAimArchives();       break;
1265 		case LAPTOP_MODE_AIM_POLICIES:             ExitAimPolicies();       break;
1266 		case LAPTOP_MODE_AIM_LINKS:                ExitAimLinks();          break;
1267 		case LAPTOP_MODE_AIM_HISTORY:              ExitAimHistory();        break;
1268 
1269 		case LAPTOP_MODE_MERC:                     ExitMercs();             break;
1270 		case LAPTOP_MODE_MERC_FILES:               ExitMercsFiles();        break;
1271 		case LAPTOP_MODE_MERC_ACCOUNT:             ExitMercsAccount();      break;
1272 		case LAPTOP_MODE_MERC_NO_ACCOUNT:          ExitMercsNoAccount();    break;
1273 
1274 		case LAPTOP_MODE_BOBBY_R:                  ExitBobbyR();            break;
1275 		case LAPTOP_MODE_BOBBY_R_GUNS:             ExitBobbyRGuns();        break;
1276 		case LAPTOP_MODE_BOBBY_R_AMMO:             ExitBobbyRAmmo();        break;
1277 		case LAPTOP_MODE_BOBBY_R_ARMOR:            ExitBobbyRArmour();      break;
1278 		case LAPTOP_MODE_BOBBY_R_MISC:             ExitBobbyRMisc();        break;
1279 		case LAPTOP_MODE_BOBBY_R_USED:             ExitBobbyRUsed();        break;
1280 		case LAPTOP_MODE_BOBBY_R_MAILORDER:        ExitBobbyRMailOrder();   break;
1281 		case LAPTOP_MODE_BOBBYR_SHIPMENTS:         ExitBobbyRShipments();   break;
1282 
1283 		case LAPTOP_MODE_CHAR_PROFILE:             ExitCharProfile();       break;
1284 
1285 		case LAPTOP_MODE_FLORIST:                  ExitFlorist();           break;
1286 		case LAPTOP_MODE_FLORIST_FLOWER_GALLERY:   ExitFloristGallery();    break;
1287 		case LAPTOP_MODE_FLORIST_ORDERFORM:        ExitFloristOrderForm();  break;
1288 		case LAPTOP_MODE_FLORIST_CARD_GALLERY:     ExitFloristCards();      break;
1289 
1290 		case LAPTOP_MODE_INSURANCE:                ExitInsurance();         break;
1291 		case LAPTOP_MODE_INSURANCE_INFO:           ExitInsuranceInfo();     break;
1292 		case LAPTOP_MODE_INSURANCE_CONTRACT:       ExitInsuranceContract(); break;
1293 		case LAPTOP_MODE_INSURANCE_COMMENTS:       ExitInsuranceComments(); break;
1294 
1295 		case LAPTOP_MODE_FUNERAL:                  ExitFuneral();           break;
1296 
1297 		case LAPTOP_MODE_FINANCES:                 ExitFinances();          break;
1298 		case LAPTOP_MODE_PERSONNEL:                ExitPersonnel();         break;
1299 		case LAPTOP_MODE_HISTORY:                  ExitHistory();           break;
1300 		case LAPTOP_MODE_FILES:                    ExitFiles();             break;
1301 		case LAPTOP_MODE_EMAIL:                    ExitEmail();             break;
1302 		case LAPTOP_MODE_BROKEN_LINK:              ExitBrokenLink();        break;
1303 
1304 		// nothing to do for other subwindows
1305 		default: break;
1306 	}
1307 
1308 	if (uiMode != LAPTOP_MODE_NONE && uiMode < LAPTOP_MODE_WWW)
1309 	{
1310 		CreateDestroyMinimizeButtonForCurrentMode();
1311 	}
1312 
1313 	guiLastExitedLaptopMode = uiMode;
1314 }
1315 
1316 
MakeButton(UINT idx,INT16 y,GUI_CALLBACK click,INT8 off_x,const ST::string & text,const ST::string & help_text)1317 static void MakeButton(UINT idx, INT16 y, GUI_CALLBACK click, INT8 off_x, const ST::string& text, const ST::string& help_text)
1318 {
1319 	GUIButtonRef const btn = QuickCreateButtonImg(LAPTOPDIR "/buttonsforlaptop.sti", idx, idx + 8, (29 + STD_SCREEN_X), (y + STD_SCREEN_Y), MSYS_PRIORITY_HIGH, click);
1320 	gLaptopButton[idx] = btn;
1321 	btn->SetFastHelpText(help_text);
1322 	btn->SpecifyTextOffsets(off_x, 11, TRUE);
1323 	btn->SpecifyGeneralTextAttributes(text, FONT10ARIAL, 2, 0);
1324 	btn->SetCursor(CURSOR_LAPTOP_SCREEN);
1325 }
1326 
1327 
1328 static void BtnOnCallback(                GUI_BUTTON* btn, INT32 reason);
1329 static void EmailRegionButtonCallback(    GUI_BUTTON* btn, INT32 reason);
1330 static void FilesRegionButtonCallback(    GUI_BUTTON* btn, INT32 reason);
1331 static void FinancialRegionButtonCallback(GUI_BUTTON* btn, INT32 reason);
1332 static void HistoryRegionButtonCallback(  GUI_BUTTON* btn, INT32 reason);
1333 static void PersonnelRegionButtonCallback(GUI_BUTTON* btn, INT32 reason);
1334 static void WWWRegionButtonCallback(      GUI_BUTTON* btn, INT32 reason);
1335 
1336 
CreateLaptopButtons(void)1337 static void CreateLaptopButtons(void)
1338 {
1339 	MakeButton(0,  66, EmailRegionButtonCallback,     30, pLaptopIcons[0], gzLaptopHelpText[LAPTOP_BN_HLP_TXT_VIEW_EMAIL]);
1340 	MakeButton(1,  98, WWWRegionButtonCallback,       30, pLaptopIcons[1], gzLaptopHelpText[LAPTOP_BN_HLP_TXT_BROWSE_VARIOUS_WEB_SITES]);
1341 	MakeButton(2, 130, FilesRegionButtonCallback,     30, pLaptopIcons[5], gzLaptopHelpText[LAPTOP_BN_HLP_TXT_VIEW_FILES_AND_EMAIL_ATTACHMENTS]);
1342 	MakeButton(3, 194, PersonnelRegionButtonCallback, 30, pLaptopIcons[3], gzLaptopHelpText[LAPTOP_BN_HLP_TXT_VIEW_TEAM_INFO]);
1343 	MakeButton(4, 162, HistoryRegionButtonCallback,   30, pLaptopIcons[4], gzLaptopHelpText[LAPTOP_BN_HLP_TXT_READ_LOG_OF_EVENTS]);
1344 	MakeButton(5, 241, FinancialRegionButtonCallback, 30, pLaptopIcons[2], gzLaptopHelpText[LAPTOP_BN_HLP_TXT_VIEW_FINANCIAL_SUMMARY_AND_HISTORY]);
1345 	MakeButton(6, 378, BtnOnCallback,                 25, pLaptopIcons[6], gzLaptopHelpText[LAPTOP_BN_HLP_TXT_CLOSE_LAPTOP]);
1346 }
1347 
1348 
DeleteLapTopButtons(void)1349 static void DeleteLapTopButtons(void)
1350 {
1351 	for (UINT32 i = 0; i < 7; ++i) RemoveButton(gLaptopButton[i]);
1352 }
1353 
1354 
1355 static BOOLEAN HandleExit(void);
1356 
1357 
BtnOnCallback(GUI_BUTTON * btn,INT32 reason)1358 static void BtnOnCallback(GUI_BUTTON *btn, INT32 reason)
1359 {
1360 	if (reason & MSYS_CALLBACK_REASON_LBUTTON_UP)
1361 	{
1362 		if (HandleExit()) fExitingLaptopFlag = TRUE;
1363 	}
1364 }
1365 
1366 
1367 static BOOLEAN ExitLaptopDone(void);
1368 
1369 
LeaveLapTopScreen(void)1370 static void LeaveLapTopScreen(void)
1371 {
1372 	if (ExitLaptopDone())
1373 	{
1374 		SetLaptopExitScreen(MAP_SCREEN);
1375 
1376 		if (gfAtLeastOneMercWasHired)
1377 		{
1378 			if (LaptopSaveInfo.gfNewGameLaptop)
1379 			{
1380 				LaptopSaveInfo.gfNewGameLaptop = FALSE;
1381 				fExitingLaptopFlag = TRUE;
1382 				InitNewGame();
1383 				gfDontStartTransitionFromLaptop = TRUE;
1384 				return;
1385 			}
1386 		}
1387 		else
1388 		{
1389 			gfDontStartTransitionFromLaptop = TRUE;
1390 		}
1391 
1392 		SetPendingNewScreen(guiExitScreen);
1393 
1394 		if (!gfDontStartTransitionFromLaptop)
1395 		{
1396 			gfDontStartTransitionFromLaptop = TRUE;
1397 			SetCurrentCursorFromDatabase(VIDEO_NO_CURSOR);
1398 			//Step 1:  Build the laptop image into the save buffer.
1399 			RestoreBackgroundRects();
1400 			RenderLapTopImage();
1401 			RenderLaptop();
1402 			RenderButtons();
1403 			PrintDate();
1404 			PrintBalance();
1405 			PrintNumberOnTeam();
1406 			ShowLights();
1407 
1408 			//Step 2:  The mapscreen image is in the EXTRABUFFER, and laptop is in the SAVEBUFFER
1409 			//         Start transitioning the screen.
1410 			SGPBox const SrcRect = { STD_SCREEN_X, STD_SCREEN_Y, MAP_SCREEN_WIDTH, MAP_SCREEN_HEIGHT };
1411 			const UINT32 uiTimeRange = 1000;
1412 			INT32 iPercentage     = 100;
1413 			INT32 iRealPercentage = 100;
1414 			const UINT32 uiStartTime = GetClock();
1415 			BltVideoSurface(guiSAVEBUFFER, FRAME_BUFFER, 0, 0, NULL);
1416 			PlayJA2SampleFromFile(SOUNDSDIR "/laptop power down (8-11).wav", HIGHVOLUME, 1, MIDDLEPAN);
1417 			while (iRealPercentage > 0)
1418 			{
1419 				BltVideoSurface(FRAME_BUFFER, guiEXTRABUFFER, 0, 0, NULL);
1420 
1421 				const UINT32 uiCurrTime = GetClock();
1422 				iPercentage = (uiCurrTime-uiStartTime) * 100 / uiTimeRange;
1423 				iPercentage = MIN(iPercentage, 100);
1424 				iPercentage = 100 - iPercentage;
1425 
1426 				iRealPercentage = iPercentage;
1427 
1428 				//Factor the percentage so that it is modified by a gravity falling acceleration effect.
1429 				const INT32 iFactor = (iPercentage - 50) * 2;
1430 				if (iPercentage < 50)
1431 				{
1432 					iPercentage += iPercentage       * iFactor * 0.01 + 0.5;
1433 				}
1434 				else
1435 				{
1436 					iPercentage += (100-iPercentage) * iFactor * 0.01 + 0.5;
1437 				}
1438 
1439 				//Scaled laptop
1440 				INT32 iScalePercentage;
1441 				if (iPercentage < 99)
1442 				{
1443 					iScalePercentage = 10000 / (100-iPercentage);
1444 				}
1445 				else
1446 				{
1447 					iScalePercentage = 5333;
1448 				}
1449 				const UINT16 uWidth  = 12 * iScalePercentage / 100;
1450 				const UINT16 uHeight =  9 * iScalePercentage / 100;
1451 				const UINT16 uX = 472 - (472 - 320) * iScalePercentage / 5333;
1452 				const UINT16 uY = 424 - (424 - 240) * iScalePercentage / 5333;
1453 
1454 				SGPBox const DstRect = { (UINT16)(STD_SCREEN_X + uX - uWidth / 2), (UINT16)(STD_SCREEN_Y + uY - uHeight / 2), uWidth, uHeight };
1455 
1456 				BltStretchVideoSurface(FRAME_BUFFER, guiSAVEBUFFER, &SrcRect, &DstRect);
1457 				InvalidateScreen();
1458 				RefreshScreen();
1459 			}
1460 		}
1461 	}
1462 }
1463 
1464 
HandleExit(void)1465 static BOOLEAN HandleExit(void)
1466 {
1467 	// new game, send email
1468 	if (LaptopSaveInfo.gfNewGameLaptop)
1469 	{
1470 		// Set an event to send this email (day 2 8:00-12:00)
1471 		if (!LaptopSaveInfo.fIMPCompletedFlag && !LaptopSaveInfo.fSentImpWarningAlready)
1472 		{
1473 			AddFutureDayStrategicEvent(EVENT_HAVENT_MADE_IMP_CHARACTER_EMAIL, (8 + Random(4)) * 60, 0, 1);
1474 			fExitingLaptopFlag = TRUE;
1475 			return FALSE;
1476 		}
1477 	}
1478 
1479 	return TRUE;
1480 }
1481 
HaventMadeImpMercEmailCallBack()1482 void HaventMadeImpMercEmailCallBack()
1483 {
1484 	//if the player STILL hasnt made an imp merc yet
1485 	if (!LaptopSaveInfo.fIMPCompletedFlag && !LaptopSaveInfo.fSentImpWarningAlready)
1486 	{
1487 		LaptopSaveInfo.fSentImpWarningAlready = TRUE;
1488 		AddEmail(IMP_EMAIL_AGAIN,IMP_EMAIL_AGAIN_LENGTH, 1, GetWorldTotalMin());
1489 	}
1490 }
1491 
1492 
CreateLapTopMouseRegions(void)1493 static void CreateLapTopMouseRegions(void)
1494 {
1495 	// the entire laptop display region
1496 	MSYS_DefineRegion(&gLapTopScreenRegion, LaptopScreenRect.iLeft, LaptopScreenRect.iTop, LaptopScreenRect.iRight, LaptopScreenRect.iBottom, MSYS_PRIORITY_NORMAL + 1, CURSOR_LAPTOP_SCREEN, MSYS_NO_CALLBACK, LapTopScreenCallBack);
1497 }
1498 
1499 
DeleteLapTopMouseRegions(void)1500 static void DeleteLapTopMouseRegions(void)
1501 {
1502 	MSYS_RemoveRegion(&gLapTopScreenRegion);
1503 }
1504 
1505 
1506 static void UpdateListToReflectNewProgramOpened(INT32 iOpenedProgram);
1507 
1508 
FinancialRegionButtonCallback(GUI_BUTTON * btn,INT32 reason)1509 static void FinancialRegionButtonCallback(GUI_BUTTON* btn, INT32 reason)
1510 {
1511 	if (reason & MSYS_CALLBACK_REASON_LBUTTON_UP)
1512 	{
1513 		if (gfShowBookmarks)
1514 		{
1515 			gfShowBookmarks = FALSE;
1516 			fReDrawScreenFlag = TRUE;
1517 		}
1518 		guiCurrentLaptopMode = LAPTOP_MODE_FINANCES;
1519 
1520 		UpdateListToReflectNewProgramOpened(LAPTOP_PROGRAM_FINANCES);
1521 	}
1522 }
1523 
1524 
PersonnelRegionButtonCallback(GUI_BUTTON * btn,INT32 reason)1525 static void PersonnelRegionButtonCallback(GUI_BUTTON *btn, INT32 reason)
1526 {
1527 	if (reason & MSYS_CALLBACK_REASON_LBUTTON_UP)
1528 	{
1529 		guiCurrentLaptopMode = LAPTOP_MODE_PERSONNEL;
1530 		if (gfShowBookmarks)
1531 		{
1532 			gfShowBookmarks = FALSE;
1533 			fReDrawScreenFlag = TRUE;
1534 		}
1535 		gfShowBookmarks = FALSE;
1536 
1537 		UpdateListToReflectNewProgramOpened(LAPTOP_PROGRAM_PERSONNEL);
1538 	}
1539 }
1540 
1541 
EmailRegionButtonCallback(GUI_BUTTON * btn,INT32 reason)1542 static void EmailRegionButtonCallback(GUI_BUTTON *btn, INT32 reason)
1543 {
1544 	if (reason & MSYS_CALLBACK_REASON_LBUTTON_UP)
1545 	{
1546 		guiCurrentLaptopMode = LAPTOP_MODE_EMAIL;
1547 		gfShowBookmarks = FALSE;
1548 		UpdateListToReflectNewProgramOpened(LAPTOP_PROGRAM_MAILER);
1549 		fReDrawScreenFlag = TRUE;
1550 	}
1551 }
1552 
1553 
WWWRegionButtonCallback(GUI_BUTTON * btn,INT32 reason)1554 static void WWWRegionButtonCallback(GUI_BUTTON *btn, INT32 reason)
1555 {
1556 	if (reason & MSYS_CALLBACK_REASON_LBUTTON_UP)
1557 	{
1558 		// reset show bookmarks
1559 		if (guiCurrentLaptopMode < LAPTOP_MODE_WWW)
1560 		{
1561 			gfShowBookmarks = FALSE;
1562 			fShowBookmarkInfo = TRUE;
1563 		}
1564 		else
1565 		{
1566 			gfShowBookmarks = !gfShowBookmarks;
1567 		}
1568 
1569 		if (fNewWWW)
1570 		{
1571 			// no longer a new WWW mode
1572 			fNewWWW = FALSE;
1573 
1574 			// make sure program is maximized
1575 			if (gLaptopProgramStates[LAPTOP_PROGRAM_WEB_BROWSER] == LAPTOP_PROGRAM_OPEN)
1576 			{
1577 				RenderLapTopImage();
1578 				DrawDeskTopBackground();
1579 			}
1580 		}
1581 
1582 		guiCurrentLaptopMode = (guiCurrentWWWMode == LAPTOP_MODE_NONE ? LAPTOP_MODE_WWW : guiCurrentWWWMode);
1583 
1584 		UpdateListToReflectNewProgramOpened(LAPTOP_PROGRAM_WEB_BROWSER);
1585 		fReDrawScreenFlag = TRUE;
1586 	}
1587 	else if (reason & MSYS_CALLBACK_REASON_RBUTTON_UP)
1588 	{
1589 		guiCurrentLaptopMode = (guiCurrentWWWMode == LAPTOP_MODE_NONE ? LAPTOP_MODE_WWW : guiCurrentWWWMode);
1590 		fReDrawScreenFlag = TRUE;
1591 	}
1592 }
1593 
1594 
HistoryRegionButtonCallback(GUI_BUTTON * btn,INT32 reason)1595 static void HistoryRegionButtonCallback(GUI_BUTTON *btn, INT32 reason)
1596 {
1597 	if (reason & MSYS_CALLBACK_REASON_LBUTTON_UP)
1598 	{
1599 		if (gfShowBookmarks)
1600 		{
1601 			gfShowBookmarks = FALSE;
1602 		}
1603 		guiCurrentLaptopMode = LAPTOP_MODE_HISTORY;
1604 		UpdateListToReflectNewProgramOpened(LAPTOP_PROGRAM_HISTORY);
1605 		gfShowBookmarks = FALSE;
1606 		fReDrawScreenFlag = TRUE;
1607 	}
1608 }
1609 
1610 
FilesRegionButtonCallback(GUI_BUTTON * btn,INT32 reason)1611 static void FilesRegionButtonCallback(GUI_BUTTON *btn, INT32 reason)
1612 {
1613 	if (reason & MSYS_CALLBACK_REASON_LBUTTON_UP)
1614 	{
1615 		if (gfShowBookmarks)
1616 		{
1617 			gfShowBookmarks = FALSE;
1618 		}
1619 		guiCurrentLaptopMode = LAPTOP_MODE_FILES;
1620 		UpdateListToReflectNewProgramOpened(LAPTOP_PROGRAM_FILES);
1621 		fReDrawScreenFlag = TRUE;
1622 	}
1623 }
1624 
1625 
InitBookMarkList(void)1626 static void InitBookMarkList(void)
1627 {
1628 	// sets bookmark list to -1
1629 	std::fill(std::begin(LaptopSaveInfo.iBookMarkList), std::end(LaptopSaveInfo.iBookMarkList), -1);
1630 }
1631 
1632 
SetBookMark(INT32 iBookId)1633 void SetBookMark(INT32 iBookId)
1634 {
1635 	// find first empty spot, set to iBookId
1636 	INT32 i;
1637 	for (i = 0; LaptopSaveInfo.iBookMarkList[i] != -1; ++i)
1638 	{
1639 		// move through list until empty
1640 		if (LaptopSaveInfo.iBookMarkList[i] == iBookId)
1641 		{
1642 			// found it, return
1643 			return;
1644 		}
1645 	}
1646 	LaptopSaveInfo.iBookMarkList[i] = iBookId;
1647 }
1648 
1649 
LoadBookmark(void)1650 static void LoadBookmark(void)
1651 {
1652 	// grab download bars too
1653 	guiDOWNLOADTOP = AddVideoObjectFromFile(LAPTOPDIR "/downloadtop.sti");
1654 	guiDOWNLOADMID = AddVideoObjectFromFile(LAPTOPDIR "/downloadmid.sti");
1655 	guiDOWNLOADBOT = AddVideoObjectFromFile(LAPTOPDIR "/downloadbot.sti");
1656 	guiBOOKMARK    = AddVideoObjectFromFile(LAPTOPDIR "/webpages.sti");
1657 	guiBOOKHIGH    = AddVideoObjectFromFile(LAPTOPDIR "/hilite.sti");
1658 }
1659 
1660 
DisplayBookMarks(void)1661 static void DisplayBookMarks(void)
1662 {
1663 	// check if we are maximizing or minimizing.. if so, do not display
1664 	if (fMaximizingProgram || fMinizingProgram) return;
1665 
1666 	SetFont(BOOK_FONT);
1667 	SetFontBackground(FONT_BLACK);
1668 	SetFontShadow(NO_SHADOW);
1669 
1670 	SetFontDestBuffer(FRAME_BUFFER, BOOK_X, BOOK_TOP_Y, BOOK_X + BOOK_WIDTH - 10, SCREEN_HEIGHT);
1671 
1672 	// blt in book mark background
1673 	INT32 const h  = BOOK_HEIGHT + 6;
1674 	INT32 const sy = BOOK_TOP_Y + 6 + h;
1675 	INT32       y  = sy;
1676 	for (INT32 i = 0;; ++i)
1677 	{
1678 		bool              const highlighted = iHighLightBookLine == i;
1679 		SGPVObject const* const vo          = highlighted ? guiBOOKHIGH : guiBOOKMARK;
1680 		BltVideoObject(FRAME_BUFFER, vo, 0, BOOK_X, y);
1681 
1682 		SetFontForeground(highlighted ? FONT_WHITE : FONT_BLACK);
1683 		INT32          const idx = LaptopSaveInfo.iBookMarkList[i];
1684 		ST::string txt = pBookMarkStrings[idx != -1 ? idx : CANCEL_STRING];
1685 		INT16                sX;
1686 		INT16                sY;
1687 		FindFontCenterCoordinates(BOOK_X + 3, y + 2, BOOK_WIDTH - 3, h, txt, BOOK_FONT, &sX, &sY);
1688 		MPrint(sX, sY, txt);
1689 		y += h;
1690 		if (idx == -1) break;
1691 	}
1692 
1693 	SetFontDestBuffer(FRAME_BUFFER);
1694 	SetFontShadow(DEFAULT_SHADOW);
1695 
1696 	InvalidateRegion(BOOK_X, sy, BOOK_X + BOOK_WIDTH, y);
1697 }
1698 
1699 
DeleteBookmark(void)1700 static void DeleteBookmark(void)
1701 {
1702 	DeleteVideoObject(guiBOOKHIGH);
1703 	DeleteVideoObject(guiBOOKMARK);
1704 	DeleteVideoObject(guiDOWNLOADTOP);
1705 	DeleteVideoObject(guiDOWNLOADMID);
1706 	DeleteVideoObject(guiDOWNLOADBOT);
1707 }
1708 
1709 
1710 static void BookmarkCallBack(MOUSE_REGION* pRegion, INT32 iReason);
1711 static void BookmarkMvtCallBack(MOUSE_REGION* pRegion, INT32 iReason);
1712 
1713 
CreateBookMarkMouseRegions(void)1714 static void CreateBookMarkMouseRegions(void)
1715 {
1716 	// creates regions based on number of entries
1717 	for (INT32 i = 0;; ++i)
1718 	{
1719 		UINT16        const y = BOOK_TOP_Y + (i + 1) * (BOOK_HEIGHT + 6) + 6;
1720 		MOUSE_REGION* const r = &gBookmarkMouseRegions[i];
1721 		MSYS_DefineRegion(r, BOOK_X, y, BOOK_X + BOOK_WIDTH, y + BOOK_HEIGHT + 6, MSYS_PRIORITY_HIGHEST - 2, CURSOR_LAPTOP_SCREEN, BookmarkMvtCallBack, BookmarkCallBack);
1722 		MSYS_SetRegionUserData(r, 0, i);
1723 		INT32 const idx = LaptopSaveInfo.iBookMarkList[i];
1724 		if (idx == -1) break; // just added region for cancel
1725 		r->SetFastHelpText(gzLaptopHelpText[BOOKMARK_TEXT_ASSOCIATION_OF_INTERNATION_MERCENARIES + idx]);
1726 	}
1727 }
1728 
1729 
DeleteBookmarkRegions(void)1730 static void DeleteBookmarkRegions(void)
1731 {
1732 	INT32 i;
1733 	// deletes bookmark regions
1734 	for (i = 0; LaptopSaveInfo.iBookMarkList[i] != -1; ++i)
1735 	{
1736 		MSYS_RemoveRegion(&gBookmarkMouseRegions[i]);
1737 	}
1738 
1739 	// now one for the cancel
1740 	MSYS_RemoveRegion(&gBookmarkMouseRegions[i]);
1741 }
1742 
1743 
CreateDestoryBookMarkRegions(void)1744 static void CreateDestoryBookMarkRegions(void)
1745 {
1746 	// checks to see if a bookmark needs to be created or destroyed
1747 	static BOOLEAN fOldShowBookmarks = FALSE;
1748 
1749 	if (gfShowBookmarks && !fOldShowBookmarks)
1750 	{
1751 		CreateBookMarkMouseRegions();
1752 		fOldShowBookmarks = TRUE;
1753 	}
1754 	else if (!gfShowBookmarks && fOldShowBookmarks)
1755 	{
1756 		DeleteBookmarkRegions();
1757 		fOldShowBookmarks = FALSE;
1758 	}
1759 }
1760 
1761 
BookmarkCallBack(MOUSE_REGION * pRegion,INT32 iReason)1762 static void BookmarkCallBack(MOUSE_REGION* pRegion, INT32 iReason)
1763 {
1764 	// we are in process of loading
1765 	if (fLoadPendingFlag) return;
1766 
1767 	if (iReason & MSYS_CALLBACK_REASON_LBUTTON_UP)
1768 	{
1769 		INT32 const i   = MSYS_GetRegionUserData(pRegion, 0);
1770 		INT32 const idx = LaptopSaveInfo.iBookMarkList[i];
1771 		if (idx != -1)
1772 		{
1773 			GoToWebPage(idx);
1774 		}
1775 		else
1776 		{
1777 			gfShowBookmarks   = FALSE;
1778 			fReDrawScreenFlag = TRUE;
1779 		}
1780 	}
1781 }
1782 
1783 
1784 static void InternetRainDelayMessageBoxCallBack(MessageBoxReturnValue);
1785 
1786 
GoToWebPage(INT32 iPageId)1787 void GoToWebPage(INT32 iPageId)
1788 {
1789 	//if it is raining, popup a warning first saying connection time may be slow
1790 	if (IsItRaining())
1791 	{
1792 		if (giRainDelayInternetSite == -1)
1793 		{
1794 			DoLapTopMessageBox(MSG_BOX_LAPTOP_DEFAULT, pErrorStrings, LAPTOP_SCREEN, MSG_BOX_FLAG_OK, InternetRainDelayMessageBoxCallBack);
1795 			giRainDelayInternetSite = iPageId;
1796 			return;
1797 		}
1798 	}
1799 	else
1800 	{
1801 		giRainDelayInternetSite = -1;
1802 	}
1803 
1804 	gfShowBookmarks   = FALSE;
1805 	fReDrawScreenFlag = TRUE;
1806 
1807 	switch (iPageId)
1808 	{
1809 		case AIM_BOOKMARK:
1810 			guiCurrentWWWMode    = LAPTOP_MODE_AIM;
1811 			guiCurrentLaptopMode = LAPTOP_MODE_AIM;
1812 			break;
1813 
1814 		case BOBBYR_BOOKMARK:
1815 			guiCurrentWWWMode    = LAPTOP_MODE_BOBBY_R;
1816 			guiCurrentLaptopMode = LAPTOP_MODE_BOBBY_R;
1817 			break;
1818 
1819 		case IMP_BOOKMARK:
1820 			guiCurrentWWWMode    = LAPTOP_MODE_CHAR_PROFILE;
1821 			guiCurrentLaptopMode = LAPTOP_MODE_CHAR_PROFILE;
1822 			iCurrentImpPage = IMP_HOME_PAGE;
1823 			break;
1824 
1825 		case MERC_BOOKMARK:
1826 			//if the mercs server has gone down, but hasnt come up yet
1827 			if (LaptopSaveInfo.fMercSiteHasGoneDownYet &&
1828 					LaptopSaveInfo.fFirstVisitSinceServerWentDown == FALSE)
1829 			{
1830 				guiCurrentWWWMode    = LAPTOP_MODE_BROKEN_LINK;
1831 				guiCurrentLaptopMode = LAPTOP_MODE_BROKEN_LINK;
1832 			}
1833 			else
1834 			{
1835 				guiCurrentWWWMode    = LAPTOP_MODE_MERC;
1836 				guiCurrentLaptopMode = LAPTOP_MODE_MERC;
1837 			}
1838 			break;
1839 
1840 		case FUNERAL_BOOKMARK:
1841 			guiCurrentWWWMode    = LAPTOP_MODE_FUNERAL;
1842 			guiCurrentLaptopMode = LAPTOP_MODE_FUNERAL;
1843 			break;
1844 
1845 		case FLORIST_BOOKMARK:
1846 			guiCurrentWWWMode    = LAPTOP_MODE_FLORIST;
1847 			guiCurrentLaptopMode = LAPTOP_MODE_FLORIST;
1848 			break;
1849 
1850 		case INSURANCE_BOOKMARK:
1851 			guiCurrentWWWMode    = LAPTOP_MODE_INSURANCE;
1852 			guiCurrentLaptopMode = LAPTOP_MODE_INSURANCE;
1853 			break;
1854 
1855 		default: return;
1856 	}
1857 
1858 	// do we have to have a World Wide Wait
1859 	fFastLoadFlag = LaptopSaveInfo.fVisitedBookmarkAlready[iPageId];
1860 	LaptopSaveInfo.fVisitedBookmarkAlready[iPageId] = TRUE;
1861 	fLoadPendingFlag = TRUE;
1862 }
1863 
1864 
BookmarkMvtCallBack(MOUSE_REGION * pRegion,INT32 iReason)1865 static void BookmarkMvtCallBack(MOUSE_REGION* pRegion, INT32 iReason)
1866 {
1867 	if (iReason == MSYS_CALLBACK_REASON_MOVE)
1868 	{
1869 		iHighLightBookLine=MSYS_GetRegionUserData(pRegion, 0);
1870 	}
1871 	if (iReason == MSYS_CALLBACK_REASON_LOST_MOUSE)
1872 	{
1873 		iHighLightBookLine = -1;
1874 	}
1875 }
1876 
1877 
LoadLoadPending(void)1878 static void LoadLoadPending(void)
1879 {
1880 	// function will load the load pending graphics
1881 	// reuse bookmark
1882 	// load graph window and bar
1883 	guiGRAPHWINDOW = AddVideoObjectFromFile(LAPTOPDIR "/graphwindow.sti");
1884 	guiGRAPHBAR    = AddVideoObjectFromFile(LAPTOPDIR "/graphsegment.sti");
1885 }
1886 
1887 
1888 static INT32 WWaitDelayIncreasedIfRaining(INT32 iUnitTime);
1889 
1890 
DisplayLoadPending(void)1891 static void DisplayLoadPending(void)
1892 {
1893 	// this function will display the load pending and return if the load is done
1894 	static INT32 iBaseTime  = 0;
1895 	static INT32 iTotalTime = 0;
1896 
1897 	// if merc webpage, make it longer
1898 	// TEMP disables the loadpending
1899 	INT32 iLoadTime;
1900 	INT32 iUnitTime;
1901 
1902 	if (fFastLoadFlag)
1903 	{
1904 		iUnitTime = (fConnectingToSubPage ? FASTEST_UNIT_TIME : FAST_UNIT_TIME);
1905 	}
1906 	else if (fConnectingToSubPage)
1907 	{
1908 		iUnitTime = ALMOST_FAST_UNIT_TIME;
1909 	}
1910 	else if (guiCurrentLaptopMode == LAPTOP_MODE_MERC && !LaptopSaveInfo.fMercSiteHasGoneDownYet)
1911 	{
1912 		// if we are connecting the MERC site, and the MERC site hasnt yet moved
1913 		// to their new site, have the sloooww wait
1914 		iUnitTime = LONG_UNIT_TIME;
1915 	}
1916 	else
1917 	{
1918 		iUnitTime = UNIT_TIME;
1919 	}
1920 
1921 	iUnitTime += WWaitDelayIncreasedIfRaining(iUnitTime);
1922 	iLoadTime  = iUnitTime * 30;
1923 
1924 	// we are now waiting on a web page to download, reset counter
1925 	if (!fLoadPendingFlag)
1926 	{
1927 		fDoneLoadPending     = FALSE;
1928 		fFastLoadFlag        = FALSE;
1929 		fConnectingToSubPage = FALSE;
1930 		iBaseTime            = 0;
1931 		iTotalTime           = 0;
1932 		return;
1933 	}
1934 	if (iBaseTime == 0) iBaseTime = GetJA2Clock();
1935 
1936 	// if total time is exceeded, return
1937 	if (iTotalTime >= iLoadTime)
1938 	{
1939 		// done loading, redraw screen
1940 		fLoadPendingFlag        = FALSE;
1941 		fFastLoadFlag           = FALSE;
1942 		iTotalTime              = 0;
1943 		iBaseTime               = 0;
1944 		fDoneLoadPending        = TRUE;
1945 		fConnectingToSubPage    = FALSE;
1946 		fPausedReDrawScreenFlag = TRUE;
1947 		return;
1948 	}
1949 
1950 	const INT32 iDifference = GetJA2Clock() - iBaseTime;
1951 
1952 	// difference has been long enough or we are redrawing the screen
1953 	if (iDifference > iUnitTime)
1954 	{
1955 		// LONG ENOUGH TIME PASSED
1956 		iBaseTime   = GetJA2Clock();
1957 		iTotalTime += iDifference;
1958 	}
1959 
1960 	// new mail, don't redraw
1961 	if (fNewMailFlag) return;
1962 
1963 	RenderButtons();
1964 
1965 	// display top middle and bottom of box
1966 	BltVideoObject(FRAME_BUFFER, guiDOWNLOADTOP,   0, DOWNLOAD_X,     DOWNLOAD_Y);
1967 	BltVideoObject(FRAME_BUFFER, guiDOWNLOADMID,   0, DOWNLOAD_X,     DOWNLOAD_Y + DOWN_HEIGHT);
1968 	BltVideoObject(FRAME_BUFFER, guiDOWNLOADBOT,   0, DOWNLOAD_X,     DOWNLOAD_Y + DOWN_HEIGHT * 2);
1969 	BltVideoObject(FRAME_BUFFER, guiTITLEBARICONS, 1, DOWNLOAD_X + 4, DOWNLOAD_Y + 1);
1970 
1971 	SetFontAttributes(DOWNLOAD_FONT, FONT_WHITE, NO_SHADOW);
1972 
1973 	// reload or download?
1974 	ST::string str = (fFastLoadFlag ? pDownloadString[1] : pDownloadString[0]);
1975 	INT16 sXPosition = 0;
1976 	INT16 sYPosition = 0;
1977 	FindFontCenterCoordinates(328, 0, 446 - 328, 0, str, DOWNLOAD_FONT, &sXPosition, &sYPosition);
1978 	MPrint(STD_SCREEN_X + sXPosition, DOWN_STRING_Y, str);
1979 
1980 	BltVideoObject(FRAME_BUFFER, guiGRAPHWINDOW, 0, LAPTOP_WINDOW_X, LAPTOP_WINDOW_Y);
1981 
1982 	// check to see if we are only updating screen, but not passed a new element in the load pending display
1983 
1984 	// decide how many time units are to be displayed, based on amount of time passed
1985 	for (INT32 i = 0, iTempTime = iTotalTime; i <= 30 && iTempTime > 0; ++i, iTempTime -= iUnitTime)
1986 	{
1987 		BltVideoObject(FRAME_BUFFER, guiGRAPHBAR, 0, LAPTOP_BAR_X + UNIT_WIDTH * i, LAPTOP_BAR_Y);
1988 	}
1989 
1990 	InvalidateRegion(DOWNLOAD_X, DOWNLOAD_Y, DOWNLOAD_X + 150, DOWNLOAD_Y + 100);
1991 
1992 	// re draw screen and new mail warning box
1993 	SetFontShadow(DEFAULT_SHADOW);
1994 
1995 	MarkButtonsDirty();
1996 
1997 	DisableMercSiteButton();
1998 }
1999 
2000 
DeleteLoadPending(void)2001 static void DeleteLoadPending(void)
2002 {
2003 	// this funtion will delete the load pending graphics
2004 	// reuse bookmark
2005 	DeleteVideoObject(guiGRAPHBAR);
2006 	DeleteVideoObject(guiGRAPHWINDOW);
2007 }
2008 
2009 
2010 // This function is called every time the laptop is FIRST initialized, ie whenever the laptop is loaded.  It calls
2011 // various init function in the laptop pages that need to be inited when the laptop is just loaded.
EnterLaptopInitLaptopPages(void)2012 static void EnterLaptopInitLaptopPages(void)
2013 {
2014 	EnterInitAimMembers();
2015 	EnterInitAimArchives();
2016 	EnterInitAimPolicies();
2017 	EnterInitAimHistory();
2018 	EnterInitFloristGallery();
2019 	EnterInitInsuranceInfo();
2020 	EnterInitBobbyRayOrder();
2021 	EnterInitMercSite();
2022 
2023 	// init sub pages for WW Wait
2024 	InitIMPSubPageList();
2025 }
2026 
2027 
CheckMarkButtonsDirtyFlag(void)2028 static void CheckMarkButtonsDirtyFlag(void)
2029 {
2030 	// this function checks the fMarkButtonsDirtyFlag, if true, mark buttons dirty
2031 	if (fMarkButtonsDirtyFlag)
2032 	{
2033 		// flag set, mark buttons and reset
2034 		MarkButtonsDirty();
2035 		fMarkButtonsDirtyFlag = FALSE;
2036 	}
2037 }
2038 
2039 
PostButtonRendering(void)2040 static void PostButtonRendering(void)
2041 {
2042 	// this function is in place to allow for post button rendering
2043 	switch (guiCurrentLaptopMode)
2044 	{
2045 		case LAPTOP_MODE_AIM_MEMBERS: RenderAIMMembersTopLevel(); break;
2046 				default:
2047 						break;
2048 	}
2049 }
2050 
2051 
ShouldNewMailBeDisplayed(void)2052 static void ShouldNewMailBeDisplayed(void)
2053 {
2054 	switch (guiCurrentLaptopMode)
2055 	{
2056 		case LAPTOP_MODE_AIM_MEMBERS: DisableNewMailMessage(); break;
2057 				default:
2058 						break;
2059 	}
2060 }
2061 
2062 
CheckIfNewWWWW(void)2063 static void CheckIfNewWWWW(void)
2064 {
2065 	// if no www mode, set new www flag..until new www mode that is not 0
2066 	fNewWWW = (guiCurrentWWWMode == LAPTOP_MODE_NONE);
2067 }
2068 
2069 
HandleLapTopESCKey(void)2070 void HandleLapTopESCKey(void)
2071 {
2072 	// will handle esc key events, since handling depends on state of laptop
2073 	if (fNewMailFlag)
2074 	{
2075 		// get rid of new mail warning box
2076 		fNewMailFlag = FALSE;
2077 		CreateDestroyNewMailButton();
2078 	}
2079 	else if (MailToDelete != NULL)
2080 	{
2081 		// get rid of delete mail box
2082 		MailToDelete = NULL;
2083 		CreateDestroyDeleteNoticeMailButton();
2084 	}
2085 	else if (gfShowBookmarks)
2086 	{
2087 		// get rid of bookmarks
2088 		gfShowBookmarks = FALSE;
2089 		RenderLapTopImage();
2090 	}
2091 	else
2092 	{
2093 		// leave
2094 		fExitingLaptopFlag = TRUE;
2095 		HandleExit();
2096 		return;
2097 	}
2098 
2099 	// force redraw
2100 	fReDrawScreenFlag = TRUE;
2101 	RenderLaptop();
2102 }
2103 
2104 
HandleRightButtonUpEvent(void)2105 void HandleRightButtonUpEvent(void)
2106 {
2107 	// will handle the right button up event
2108 	if (fNewMailFlag)
2109 	{
2110 		// get rid of new mail warning box
2111 		fNewMailFlag = FALSE;
2112 		CreateDestroyNewMailButton();
2113 	}
2114 	else if (MailToDelete != NULL)
2115 	{
2116 		// get rid of delete mail box
2117 		MailToDelete = NULL;
2118 		CreateDestroyDeleteNoticeMailButton();
2119 	}
2120 	else if (gfShowBookmarks)
2121 	{
2122 		// get rid of bookmarks
2123 		gfShowBookmarks = FALSE;
2124 		RenderLapTopImage();
2125 	}
2126 	else if (fDisplayMessageFlag)
2127 	{
2128 		fDisplayMessageFlag = FALSE;
2129 		RenderLapTopImage();
2130 	}
2131 	else
2132 	{
2133 		fShowBookmarkInfo = FALSE;
2134 		return;
2135 	}
2136 
2137 	// force redraw
2138 	fReDrawScreenFlag = TRUE;
2139 	RenderLaptop();
2140 }
2141 
2142 
HandleLeftButtonUpEvent(void)2143 static void HandleLeftButtonUpEvent(void)
2144 {
2145 	// will handle the left button up event
2146 	if (gfShowBookmarks)
2147 	{
2148 		// get rid of bookmarks
2149 		gfShowBookmarks = FALSE;
2150 
2151 		// force redraw
2152 		fReDrawScreenFlag = TRUE;
2153 		RenderLapTopImage();
2154 		RenderLaptop();
2155 	}
2156 	else if (fShowBookmarkInfo)
2157 	{
2158 		fShowBookmarkInfo = FALSE;
2159 	}
2160 }
2161 
LapTopScreenCallBack(MOUSE_REGION * pRegion,INT32 iReason)2162 void LapTopScreenCallBack(MOUSE_REGION* pRegion, INT32 iReason)
2163 {
2164 	if (iReason & MSYS_CALLBACK_REASON_LBUTTON_UP)
2165 	{
2166 		HandleLeftButtonUpEvent();
2167 	}
2168 	if (iReason & MSYS_CALLBACK_REASON_RBUTTON_UP)
2169 	{
2170 		HandleRightButtonUpEvent();
2171 	}
2172 }
2173 
2174 
DoLapTopMessageBox(MessageBoxStyleID ubStyle,const ST::string & str,ScreenID uiExitScreen,MessageBoxFlags ubFlags,MSGBOX_CALLBACK ReturnCallback)2175 void DoLapTopMessageBox(MessageBoxStyleID ubStyle, const ST::string& str, ScreenID uiExitScreen, MessageBoxFlags ubFlags, MSGBOX_CALLBACK ReturnCallback)
2176 {
2177 	SGPBox const centering_rect = { LAPTOP_SCREEN_UL_X, LAPTOP_SCREEN_UL_Y, LAPTOP_SCREEN_WIDTH, LAPTOP_SCREEN_HEIGHT };
2178 	DoLapTopSystemMessageBoxWithRect(ubStyle, str, uiExitScreen, ubFlags, ReturnCallback, &centering_rect);
2179 }
2180 
2181 
DoLapTopSystemMessageBoxWithRect(MessageBoxStyleID ubStyle,const ST::string & str,ScreenID uiExitScreen,MessageBoxFlags usFlags,MSGBOX_CALLBACK ReturnCallback,SGPBox const * centering_rect)2182 void DoLapTopSystemMessageBoxWithRect(MessageBoxStyleID ubStyle, const ST::string& str, ScreenID uiExitScreen, MessageBoxFlags usFlags, MSGBOX_CALLBACK ReturnCallback, SGPBox const* centering_rect)
2183 {
2184 	// reset exit mode
2185 	fExitDueToMessageBox = TRUE;
2186 
2187 	// do message box and return
2188 	DoMessageBox(ubStyle, str, uiExitScreen, usFlags, ReturnCallback, centering_rect);
2189 }
2190 
2191 
DoLapTopSystemMessageBox(const ST::string & str,ScreenID uiExitScreen,MessageBoxFlags usFlags,MSGBOX_CALLBACK ReturnCallback)2192 void DoLapTopSystemMessageBox(const ST::string& str, ScreenID uiExitScreen, MessageBoxFlags usFlags, MSGBOX_CALLBACK ReturnCallback)
2193 {
2194 	SGPBox const centering_rect = { 0, 0, SCREEN_WIDTH, INV_INTERFACE_START_Y };
2195 	DoLapTopSystemMessageBoxWithRect(MSG_BOX_LAPTOP_DEFAULT, str, uiExitScreen, usFlags, ReturnCallback, &centering_rect);
2196 }
2197 
2198 
2199 //places a tileable pattern down
WebPageTileBackground(const UINT8 ubNumX,const UINT8 ubNumY,const UINT16 usWidth,const UINT16 usHeight,const SGPVObject * const background)2200 void WebPageTileBackground(const UINT8 ubNumX, const UINT8 ubNumY, const UINT16 usWidth, const UINT16 usHeight, const SGPVObject* const background)
2201 {
2202 	UINT16 uiPosY = LAPTOP_SCREEN_WEB_UL_Y;
2203 	for (UINT16 y = 0; y < ubNumY; ++y)
2204 	{
2205 		UINT16 uiPosX = LAPTOP_SCREEN_UL_X;
2206 		for (UINT16 x = 0; x < ubNumX; ++x)
2207 		{
2208 			BltVideoObject(FRAME_BUFFER, background, 0, uiPosX, uiPosY);
2209 			uiPosX += usWidth;
2210 		}
2211 		uiPosY += usHeight;
2212 	}
2213 }
2214 
2215 
InitTitleBarMaximizeGraphics(const SGPVObject * uiBackgroundGraphic,const ST::string & str,const SGPVObject * uiIconGraphic,UINT16 usIconGraphicIndex)2216 static void InitTitleBarMaximizeGraphics(const SGPVObject* uiBackgroundGraphic, const ST::string& str, const SGPVObject* uiIconGraphic, UINT16 usIconGraphicIndex)
2217 {
2218 	Assert(uiBackgroundGraphic);
2219 
2220 	// Create a background video surface to blt the title bar onto
2221 	guiTitleBarSurface = AddVideoSurface(LAPTOP_TITLE_BAR_WIDTH + LAPTOP_TITLE_BAR_ICON_OFFSET_X,
2222 						LAPTOP_TITLE_BAR_HEIGHT + LAPTOP_TITLE_BAR_ICON_OFFSET_Y, PIXEL_DEPTH);
2223 
2224 	BltVideoObject(guiTitleBarSurface, uiBackgroundGraphic, 0, 0, 0);
2225 	BltVideoObject(guiTitleBarSurface, uiIconGraphic, usIconGraphicIndex, LAPTOP_TITLE_BAR_ICON_OFFSET_X, LAPTOP_TITLE_BAR_ICON_OFFSET_Y);
2226 
2227 	SetFontDestBuffer(guiTitleBarSurface);
2228 	DrawTextToScreen(str, LAPTOP_TITLE_BAR_TEXT_OFFSET_X, LAPTOP_TITLE_BAR_TEXT_OFFSET_Y, 0, FONT14ARIAL, FONT_MCOLOR_WHITE, FONT_MCOLOR_BLACK, LEFT_JUSTIFIED);
2229 	SetFontDestBuffer(FRAME_BUFFER);
2230 }
2231 
2232 
DisplayTitleBarMaximizeGraphic(BOOLEAN fForward,BOOLEAN fInit,UINT16 usTopLeftX,UINT16 usTopLeftY,UINT16 usTopRightX)2233 static BOOLEAN DisplayTitleBarMaximizeGraphic(BOOLEAN fForward, BOOLEAN fInit, UINT16 usTopLeftX, UINT16 usTopLeftY, UINT16 usTopRightX)
2234 {
2235 	static INT8   ubCount;
2236 	static SGPBox LastRect;
2237 
2238 	if (fInit)
2239 	{
2240 		if (gfTitleBarSurfaceAlreadyActive) return FALSE;
2241 		gfTitleBarSurfaceAlreadyActive = TRUE;
2242 		if (fForward)
2243 		{
2244 			ubCount = 1;
2245 		}
2246 		else
2247 		{
2248 			ubCount = NUMBER_OF_LAPTOP_TITLEBAR_ITERATIONS - 1;
2249 		}
2250 	}
2251 
2252 	FLOAT dTemp;
2253 	dTemp = (LAPTOP_TITLE_BAR_TOP_LEFT_X  - usTopLeftX)  / (FLOAT)NUMBER_OF_LAPTOP_TITLEBAR_ITERATIONS;
2254 	const INT16 sPosX       = usTopLeftX  + dTemp * ubCount;
2255 
2256 	dTemp = (LAPTOP_TITLE_BAR_TOP_RIGHT_X - usTopRightX) / (FLOAT)NUMBER_OF_LAPTOP_TITLEBAR_ITERATIONS;
2257 	const INT16 sPosRightX  = usTopRightX + dTemp * ubCount;
2258 
2259 	dTemp = (LAPTOP_TITLE_BAR_TOP_LEFT_Y  - usTopLeftY)  / (FLOAT)NUMBER_OF_LAPTOP_TITLEBAR_ITERATIONS;
2260 	const INT16 sPosY       = usTopLeftY  + dTemp * ubCount;
2261 
2262 	const INT16 sPosBottomY = LAPTOP_TITLE_BAR_HEIGHT;
2263 
2264 	SGPBox const SrcRect = { 0, 0, LAPTOP_TITLE_BAR_WIDTH, LAPTOP_TITLE_BAR_HEIGHT };
2265 
2266 	//if its the last fram, bit the tittle bar to the final position
2267 	SGPBox DestRect;
2268 	if (ubCount == NUMBER_OF_LAPTOP_TITLEBAR_ITERATIONS)
2269 	{
2270 		DestRect.x = LAPTOP_TITLE_BAR_TOP_LEFT_X;
2271 		DestRect.y = LAPTOP_TITLE_BAR_TOP_LEFT_Y;
2272 		DestRect.w = LAPTOP_TITLE_BAR_TOP_RIGHT_X - LAPTOP_TITLE_BAR_TOP_LEFT_X;
2273 		DestRect.h = sPosBottomY;
2274 	}
2275 	else
2276 	{
2277 		DestRect.x = sPosX;
2278 		DestRect.y = sPosY;
2279 		DestRect.w = sPosRightX - sPosX;
2280 		DestRect.h = sPosBottomY;
2281 	}
2282 
2283 	if (fForward)
2284 	{
2285 		//Restore the old rect
2286 		if (ubCount > 1)
2287 		{
2288 			BlitBufferToBuffer(guiSAVEBUFFER, FRAME_BUFFER, LastRect.x, LastRect.y, LastRect.w, LastRect.h);
2289 		}
2290 
2291 		//Save rectangle
2292 		if (ubCount > 0)
2293 		{
2294 			BlitBufferToBuffer(FRAME_BUFFER, guiSAVEBUFFER, DestRect.x, DestRect.y, DestRect.w, DestRect.h);
2295 		}
2296 	}
2297 	else
2298 	{
2299 		//Restore the old rect
2300 		if (ubCount < NUMBER_OF_LAPTOP_TITLEBAR_ITERATIONS - 1)
2301 		{
2302 			BlitBufferToBuffer(guiSAVEBUFFER, FRAME_BUFFER, LastRect.x, LastRect.y, LastRect.w, LastRect.h);
2303 		}
2304 
2305 		//Save rectangle
2306 		if (ubCount < NUMBER_OF_LAPTOP_TITLEBAR_ITERATIONS)
2307 		{
2308 			BlitBufferToBuffer(FRAME_BUFFER, guiSAVEBUFFER, DestRect.x, DestRect.y, DestRect.w, DestRect.h);
2309 		}
2310 	}
2311 
2312 	BltStretchVideoSurface(FRAME_BUFFER, guiTitleBarSurface, &SrcRect, &DestRect);
2313 
2314 	InvalidateRegion(DestRect.x, DestRect.y, DestRect.x + DestRect.w, DestRect.y + DestRect.h);
2315 	InvalidateRegion(LastRect.x, LastRect.y, LastRect.x + LastRect.w, LastRect.y + LastRect.h);
2316 
2317 	LastRect = DestRect;
2318 
2319 	if (fForward)
2320 	{
2321 		if (ubCount == NUMBER_OF_LAPTOP_TITLEBAR_ITERATIONS)
2322 		{
2323 			gfTitleBarSurfaceAlreadyActive = FALSE;
2324 			return TRUE;
2325 		}
2326 		else
2327 		{
2328 			ubCount++;
2329 			return FALSE;
2330 		}
2331 	}
2332 	else
2333 	{
2334 		if (ubCount == 0)
2335 		{
2336 			gfTitleBarSurfaceAlreadyActive = FALSE;
2337 			return TRUE;
2338 		}
2339 		else
2340 		{
2341 			ubCount--;
2342 			return FALSE;
2343 		}
2344 	}
2345 }
2346 
2347 
RemoveTitleBarMaximizeGraphics(void)2348 static void RemoveTitleBarMaximizeGraphics(void)
2349 {
2350 	DeleteVideoSurface(guiTitleBarSurface);
2351 }
2352 
2353 
HandleSlidingTitleBar(void)2354 static void HandleSlidingTitleBar(void)
2355 {
2356 	if (fExitingLaptopFlag) return;
2357 
2358 	if (fMaximizingProgram)
2359 	{
2360 		UINT16 y;
2361 		switch (bProgramBeingMaximized)
2362 		{
2363 			case LAPTOP_PROGRAM_MAILER:      y = STD_SCREEN_Y +  66; break;
2364 			case LAPTOP_PROGRAM_FILES:       y = STD_SCREEN_Y + 120; break;
2365 			case LAPTOP_PROGRAM_FINANCES:    y = STD_SCREEN_Y + 226; break;
2366 			case LAPTOP_PROGRAM_PERSONNEL:   y = STD_SCREEN_Y + 194; break;
2367 			case LAPTOP_PROGRAM_HISTORY:     y = STD_SCREEN_Y + 162; break;
2368 			case LAPTOP_PROGRAM_WEB_BROWSER: y = STD_SCREEN_Y +  99; break;
2369 			default: goto no_display_max;
2370 		}
2371 
2372 		fMaximizingProgram = !DisplayTitleBarMaximizeGraphic(TRUE, fInitTitle, STD_SCREEN_X + 29, y, STD_SCREEN_X + 29 + 20);
2373 		if (!fMaximizingProgram)
2374 		{
2375 			RemoveTitleBarMaximizeGraphics();
2376 			fEnteredNewLapTopDueToHandleSlidingBars = TRUE;
2377 			EnterNewLaptopMode();
2378 			fEnteredNewLapTopDueToHandleSlidingBars = FALSE;
2379 			fPausedReDrawScreenFlag = TRUE;
2380 		}
2381 
2382 no_display_max:
2383 		MarkButtonsDirty();
2384 	}
2385 	else if (fMinizingProgram)
2386 	{
2387 		// minimizing
2388 		UINT16 y;
2389 		switch (bProgramBeingMaximized)
2390 		{
2391 			case LAPTOP_PROGRAM_MAILER:      y = STD_SCREEN_Y +  66; break;
2392 			case LAPTOP_PROGRAM_FILES:       y = STD_SCREEN_Y + 130; break; // XXX only difference to max case
2393 			case LAPTOP_PROGRAM_FINANCES:    y = STD_SCREEN_Y + 226; break;
2394 			case LAPTOP_PROGRAM_PERSONNEL:   y = STD_SCREEN_Y + 194; break;
2395 			case LAPTOP_PROGRAM_HISTORY:     y = STD_SCREEN_Y + 162; break;
2396 			case LAPTOP_PROGRAM_WEB_BROWSER: y = STD_SCREEN_Y +  99; break;
2397 			default: goto no_display_min;
2398 		}
2399 
2400 		fMinizingProgram = !DisplayTitleBarMaximizeGraphic(FALSE, fInitTitle, STD_SCREEN_X + 29, y, STD_SCREEN_X + 29 + 20);
2401 		if (!fMinizingProgram)
2402 		{
2403 			RemoveTitleBarMaximizeGraphics();
2404 			EnterNewLaptopMode();
2405 			fEnteredNewLapTopDueToHandleSlidingBars = FALSE;
2406 			fPausedReDrawScreenFlag = TRUE;
2407 		}
2408 
2409 no_display_min:;
2410 	}
2411 	else
2412 	{
2413 		return;
2414 	}
2415 
2416 	// reset init
2417 	fInitTitle = FALSE;
2418 }
2419 
2420 
ShowLights(void)2421 static void ShowLights(void)
2422 {
2423 	// will show lights depending on state
2424 	BltVideoObject(FRAME_BUFFER, guiLIGHTS, fPowerLightOn     ? 0 : 1, STD_SCREEN_X + 44, STD_SCREEN_Y + 466);
2425 	BltVideoObject(FRAME_BUFFER, guiLIGHTS, fHardDriveLightOn ? 0 : 1, STD_SCREEN_X + 88, STD_SCREEN_Y + 466);
2426 }
2427 
2428 
FlickerHDLight(void)2429 static void FlickerHDLight(void)
2430 {
2431 	static INT32 iBaseTime        = 0;
2432 	static INT32 iTotalDifference = 0;
2433 
2434 	if (fLoadPendingFlag) fFlickerHD = TRUE;
2435 	if (!fFlickerHD) return;
2436 
2437 	if (iBaseTime == 0) iBaseTime = GetJA2Clock();
2438 
2439 	const INT32 iDifference = GetJA2Clock() - iBaseTime;
2440 
2441 	if (iTotalDifference > HD_FLICKER_TIME && !fLoadPendingFlag)
2442 	{
2443 		iBaseTime         = GetJA2Clock();
2444 		fHardDriveLightOn = FALSE;
2445 		iBaseTime         = 0;
2446 		iTotalDifference  = 0;
2447 		fFlickerHD        = FALSE;
2448 		InvalidateRegion(88, 466, 102, 477);
2449 		return;
2450 	}
2451 
2452 	if (iDifference > FLICKER_TIME)
2453 	{
2454 		iTotalDifference += iDifference;
2455 
2456 		if (fLoadPendingFlag) iTotalDifference = 0;
2457 
2458 		fHardDriveLightOn = (Random(2) == 0);
2459 		InvalidateRegion(88, 466, 102, 477);
2460 	}
2461 }
2462 
2463 
ExitLaptopDone(void)2464 static BOOLEAN ExitLaptopDone(void)
2465 {
2466 	// check if this is the first time, to reset counter
2467 	static BOOLEAN fOldLeaveLaptopState = FALSE;
2468 	static INT32 iBaseTime              = 0;
2469 
2470 	if (!fOldLeaveLaptopState)
2471 	{
2472 		fOldLeaveLaptopState = TRUE;
2473 		iBaseTime = GetJA2Clock();
2474 	}
2475 
2476 	fPowerLightOn = FALSE;
2477 
2478 	InvalidateRegion(44, 466, 58, 477);
2479 	// get the current difference
2480 	const INT32 iDifference = GetJA2Clock() - iBaseTime;
2481 
2482 	// did we wait long enough?
2483 	if (iDifference > EXIT_LAPTOP_DELAY_TIME)
2484 	{
2485 		iBaseTime = 0;
2486 		fOldLeaveLaptopState = FALSE;
2487 		return TRUE;
2488 	}
2489 	else
2490 	{
2491 		return FALSE;
2492 	}
2493 }
2494 
2495 
2496 static void CreateMinimizeButtonForCurrentMode(void);
2497 static void CreateMinimizeRegionsForLaptopProgramIcons(void);
2498 static void DestroyMinimizeButtonForCurrentMode(void);
2499 static void DestroyMinimizeRegionsForLaptopProgramIcons(void);
2500 
2501 
CreateDestroyMinimizeButtonForCurrentMode(void)2502 static void CreateDestroyMinimizeButtonForCurrentMode(void)
2503 {
2504 	// will create the minimize button
2505 	static BOOLEAN fAlreadyCreated = FALSE;
2506 	// state of creation of minimize button
2507 	BOOLEAN fCreateMinimizeButton = FALSE;
2508 	// check to see if created, if so, do nothing
2509 
2510 	// check current mode
2511 	if (guiCurrentLaptopMode == LAPTOP_MODE_NONE && guiPreviousLaptopMode != LAPTOP_MODE_NONE)
2512 	{
2513 		fCreateMinimizeButton = FALSE;
2514 	}
2515 	else if (guiCurrentLaptopMode != LAPTOP_MODE_NONE)
2516 	{
2517 		fCreateMinimizeButton = TRUE;
2518 	}
2519 	else if (guiPreviousLaptopMode != LAPTOP_MODE_NONE)
2520 	{
2521 		fCreateMinimizeButton = FALSE;
2522 	}
2523 
2524 	// leaving laptop, get rid of the button
2525 	if (fExitingLaptopFlag)
2526 	{
2527 		fCreateMinimizeButton = FALSE;
2528 	}
2529 
2530 	if (!fAlreadyCreated && fCreateMinimizeButton)
2531 	{
2532 		// not created, create
2533 		fAlreadyCreated = TRUE;
2534 		CreateMinimizeButtonForCurrentMode();
2535 		CreateMinimizeRegionsForLaptopProgramIcons();
2536 	}
2537 	else if (fAlreadyCreated && !fCreateMinimizeButton)
2538 	{
2539 		// created and must be destroyed
2540 		fAlreadyCreated = FALSE;
2541 		DestroyMinimizeButtonForCurrentMode();
2542 		DestroyMinimizeRegionsForLaptopProgramIcons();
2543 	}
2544 }
2545 
2546 
2547 static void LaptopMinimizeProgramButtonCallback(GUI_BUTTON* btn, INT32 reason);
2548 
2549 
CreateMinimizeButtonForCurrentMode(void)2550 static void CreateMinimizeButtonForCurrentMode(void)
2551 {
2552 	// create minimize button
2553 	gLaptopMinButton = QuickCreateButtonImg(LAPTOPDIR "/x.sti", 0, 1, STD_SCREEN_X + 590, STD_SCREEN_Y + 30, MSYS_PRIORITY_HIGH, LaptopMinimizeProgramButtonCallback);
2554 	gLaptopMinButton->SetCursor(CURSOR_LAPTOP_SCREEN);
2555 }
2556 
2557 
DestroyMinimizeButtonForCurrentMode(void)2558 static void DestroyMinimizeButtonForCurrentMode(void)
2559 {
2560 	// destroy minimize button
2561 	RemoveButton(gLaptopMinButton);
2562 }
2563 
2564 
2565 static void SetCurrentToLastProgramOpened(void);
2566 
2567 
LaptopMinimizeProgramButtonCallback(GUI_BUTTON * btn,INT32 reason)2568 static void LaptopMinimizeProgramButtonCallback(GUI_BUTTON* btn, INT32 reason)
2569 {
2570 	if (reason & MSYS_CALLBACK_REASON_LBUTTON_UP)
2571 	{
2572 		UINT           prog;
2573 		ST::string title;
2574 		UINT16         gfx_idx;
2575 		switch (guiCurrentLaptopMode)
2576 		{
2577 			case LAPTOP_MODE_EMAIL:
2578 				prog    = LAPTOP_PROGRAM_MAILER;
2579 				title   = pLaptopIcons[0];
2580 				gfx_idx = 0;
2581 				break;
2582 
2583 			case LAPTOP_MODE_FILES:
2584 				prog    = LAPTOP_PROGRAM_FILES;
2585 				title   = pLaptopIcons[5];
2586 				gfx_idx = 2;
2587 				break;
2588 
2589 			case LAPTOP_MODE_FINANCES:
2590 				prog    = LAPTOP_PROGRAM_FINANCES;
2591 				title   = pLaptopIcons[2];
2592 				gfx_idx = 5;
2593 				break;
2594 
2595 			case LAPTOP_MODE_HISTORY:
2596 				prog    = LAPTOP_PROGRAM_HISTORY;
2597 				title   = pLaptopIcons[4];
2598 				gfx_idx = 4;
2599 				break;
2600 
2601 			case LAPTOP_MODE_PERSONNEL:
2602 				prog    = LAPTOP_PROGRAM_PERSONNEL;
2603 				title   = pLaptopIcons[3];
2604 				gfx_idx = 3;
2605 				break;
2606 
2607 			case LAPTOP_MODE_NONE: return; // nothing
2608 
2609 			default:
2610 				gfShowBookmarks = FALSE;
2611 				prog    = LAPTOP_PROGRAM_WEB_BROWSER;
2612 				title   = pLaptopIcons[7];
2613 				gfx_idx = 1;
2614 				break;
2615 		}
2616 		gLaptopProgramStates[prog] = LAPTOP_PROGRAM_MINIMIZED;
2617 		InitTitleBarMaximizeGraphics(guiTITLEBARLAPTOP, title, guiTITLEBARICONS, gfx_idx);
2618 		SetCurrentToLastProgramOpened();
2619 		fMinizingProgram = TRUE;
2620 		fInitTitle = TRUE;
2621 	}
2622 }
2623 
2624 
FindLastProgramStillOpen(void)2625 static INT32 FindLastProgramStillOpen(void)
2626 {
2627 	INT32 iLowestValue = 6;
2628 	INT32 iLowestValueProgram = 6;
2629 
2630 	// returns ID of last program open and not minimized
2631 	for (INT32 i = 0; i < 6; ++i)
2632 	{
2633 		if (gLaptopProgramStates[i] != LAPTOP_PROGRAM_MINIMIZED)
2634 		{
2635 			if (gLaptopProgramQueueList[i] < iLowestValue)
2636 			{
2637 				iLowestValue = gLaptopProgramQueueList[i];
2638 				iLowestValueProgram = i;
2639 			}
2640 		}
2641 	}
2642 
2643 	return iLowestValueProgram;
2644 }
2645 
2646 
UpdateListToReflectNewProgramOpened(INT32 iOpenedProgram)2647 static void UpdateListToReflectNewProgramOpened(INT32 iOpenedProgram)
2648 {
2649 	// will update queue of opened programs to show thier states
2650 	// set iOpenedProgram to 1, and update others
2651 
2652 	// increment everyone
2653 	for (INT32 i = 0; i < 6; ++i)
2654 	{
2655 		gLaptopProgramQueueList[i]++;
2656 	}
2657 
2658 	gLaptopProgramQueueList[iOpenedProgram] = 1;
2659 }
2660 
2661 
InitLaptopOpenQueue(void)2662 static void InitLaptopOpenQueue(void)
2663 {
2664 	// set evereyone to 1
2665 	for (INT32 i = 0; i < 6; ++i)
2666 	{
2667 		gLaptopProgramQueueList[i] = 1;
2668 	}
2669 }
2670 
2671 
SetCurrentToLastProgramOpened(void)2672 static void SetCurrentToLastProgramOpened(void)
2673 {
2674 	guiCurrentLaptopMode = LAPTOP_MODE_NONE;
2675 
2676 	switch (FindLastProgramStillOpen())
2677 	{
2678 		case LAPTOP_PROGRAM_HISTORY:   guiCurrentLaptopMode = LAPTOP_MODE_HISTORY;   break;
2679 		case LAPTOP_PROGRAM_MAILER:    guiCurrentLaptopMode = LAPTOP_MODE_EMAIL;     break;
2680 		case LAPTOP_PROGRAM_PERSONNEL: guiCurrentLaptopMode = LAPTOP_MODE_PERSONNEL; break;
2681 		case LAPTOP_PROGRAM_FINANCES:  guiCurrentLaptopMode = LAPTOP_MODE_FINANCES;  break;
2682 		case LAPTOP_PROGRAM_FILES:     guiCurrentLaptopMode = LAPTOP_MODE_FILES;     break;
2683 
2684 		case LAPTOP_PROGRAM_WEB_BROWSER:
2685 			// last www mode
2686 			guiCurrentLaptopMode = (guiCurrentWWWMode == 0 ? LAPTOP_MODE_WWW : guiCurrentWWWMode);
2687 			fShowBookmarkInfo = TRUE;
2688 			break;
2689 	}
2690 }
2691 
2692 
BlitTitleBarIcons(void)2693 void BlitTitleBarIcons(void)
2694 {
2695 	// will blit the icons for the title bar of the program we are in
2696 	UINT32 Index;
2697 	switch (guiCurrentLaptopMode)
2698 	{
2699 		case LAPTOP_MODE_HISTORY:   Index = 4; break;
2700 		case LAPTOP_MODE_EMAIL:     Index = 0; break;
2701 		case LAPTOP_MODE_PERSONNEL: Index = 3; break;
2702 		case LAPTOP_MODE_FINANCES:  Index = 5; break;
2703 		case LAPTOP_MODE_FILES:     Index = 2; break;
2704 		case LAPTOP_MODE_NONE:      return;           // do nothing
2705 		default:                    Index = 1; break; // www pages
2706 	}
2707 	BltVideoObject(FRAME_BUFFER, guiTITLEBARICONS, Index, LAPTOP_TITLE_ICONS_X, LAPTOP_TITLE_ICONS_Y);
2708 }
2709 
2710 
DrawDeskTopBackground(void)2711 static void DrawDeskTopBackground(void)
2712 {
2713 	BltVideoSurface(FRAME_BUFFER, guiDESKTOP, LAPTOP_SCREEN_UL_X - 2, LAPTOP_SCREEN_UL_Y - 4, NULL);
2714 }
2715 
2716 
LoadDesktopBackground(void)2717 static void LoadDesktopBackground(void)
2718 {
2719 	const char* const ImageFile = GetMLGFilename(MLG_DESKTOP);
2720 	guiDESKTOP = AddVideoSurfaceFromFile(ImageFile);
2721 }
2722 
2723 
DeleteDesktopBackground(void)2724 static void DeleteDesktopBackground(void)
2725 {
2726 	DeleteVideoSurface(guiDESKTOP);
2727 }
2728 
2729 
PrintBalance(void)2730 void PrintBalance(void)
2731 {
2732 	SetFontAttributes(FONT10ARIAL, FONT_BLACK, NO_SHADOW);
2733 
2734 	ST::string pString = SPrintMoney(LaptopSaveInfo.iCurrentBalance);
2735 
2736 	INT32 x = STD_SCREEN_X + 47;
2737 	INT32 y = STD_SCREEN_Y + 257 + 15;
2738 	if (gLaptopButton[5]->Clicked())
2739 	{
2740 		++x;
2741 		++y;
2742 	}
2743 	MPrint(x, y, pString);
2744 
2745 	SetFontShadow(DEFAULT_SHADOW);
2746 }
2747 
2748 
PrintNumberOnTeam(void)2749 void PrintNumberOnTeam(void)
2750 {
2751 	SetFontAttributes(FONT10ARIAL, FONT_BLACK, NO_SHADOW);
2752 
2753 	const INT32 iCounter = NumberOfMercsOnPlayerTeam();
2754 
2755 	UINT16 usPosX = STD_SCREEN_X + 47;
2756 	UINT16 usPosY = STD_SCREEN_Y + 194 + 30;
2757 	if (gLaptopButton[3]->Clicked())
2758 	{
2759 		++usPosX;
2760 		++usPosY;
2761 	}
2762 	MPrint(usPosX, usPosY, ST::format("{} {}", pPersonnelString, iCounter));
2763 
2764 	SetFontShadow(DEFAULT_SHADOW);
2765 }
2766 
2767 
PrintDate(void)2768 void PrintDate(void)
2769 {
2770 	SetFontAttributes(FONT10ARIAL, FONT_BLACK, NO_SHADOW);
2771 	MPrint(STD_SCREEN_X + 30 + (70 - StringPixLength(WORLDTIMESTR, FONT10ARIAL)) / 2, (433 + STD_SCREEN_Y), WORLDTIMESTR);
2772 	SetFontShadow(DEFAULT_SHADOW);
2773 }
2774 
2775 
DisplayTaskBarIcons(void)2776 static void DisplayTaskBarIcons(void)
2777 {
2778 	// display the files icon, if there is any
2779 	if (fNewFilesInFileViewer)
2780 	{
2781 		BltVideoObject(FRAME_BUFFER, guiTITLEBARICONS, 7, LAPTOP__NEW_FILE_ICON_X, LAPTOP__NEW_FILE_ICON_Y);
2782 	}
2783 
2784 	// display the email icon, if there is email
2785 	if (fUnReadMailFlag)
2786 	{
2787 		BltVideoObject(FRAME_BUFFER, guiTITLEBARICONS, 6, LAPTOP__NEW_EMAIL_ICON_X, LAPTOP__NEW_EMAIL_ICON_Y);
2788 	}
2789 }
2790 
2791 
2792 static void HandleAltTabKeyInLaptop(void);
2793 static void HandleShiftAltTabKeyInLaptop(void);
2794 
2795 
HandleKeyBoardShortCutsForLapTop(UINT16 usEvent,UINT32 usParam,UINT16 usKeyState)2796 void HandleKeyBoardShortCutsForLapTop(UINT16 usEvent, UINT32 usParam, UINT16 usKeyState)
2797 {
2798 	// will handle keyboard shortcuts for the laptop ... to be added to later
2799 	if (fExitingLaptopFlag || fTabHandled) return;
2800 
2801 	if (usEvent != KEY_DOWN) return;
2802 
2803 	switch (usParam)
2804 	{
2805 		case SDLK_ESCAPE:
2806 			// esc hit, check to see if boomark list is shown, if so, get rid of it, otherwise, leave
2807 			HandleLapTopESCKey();
2808 			break;
2809 
2810 		case SDLK_TAB:
2811 			if (usKeyState & CTRL_DOWN)
2812 			{
2813 				HandleShiftAltTabKeyInLaptop();
2814 			}
2815 			else
2816 			{
2817 				HandleAltTabKeyInLaptop();
2818 			}
2819 			fTabHandled = TRUE;
2820 			break;
2821 
2822 		case 'b':
2823 			if (CHEATER_CHEAT_LEVEL())
2824 			{
2825 				if (usKeyState & ALT_DOWN)
2826 				{
2827 					LaptopSaveInfo.fBobbyRSiteCanBeAccessed = TRUE;
2828 				}
2829 				else if (usKeyState & CTRL_DOWN)
2830 				{
2831 					guiCurrentLaptopMode = LAPTOP_MODE_BROKEN_LINK;
2832 				}
2833 			}
2834 			break;
2835 
2836 		case 'x':
2837 			if (usKeyState & ALT_DOWN) HandleShortCutExitState();
2838 			break;
2839 
2840 		case SDLK_h:
2841 			ShouldTheHelpScreenComeUp(HELP_SCREEN_LAPTOP, TRUE);
2842 			break;
2843 
2844 		case '=':
2845 		case '+':
2846 			if (CHEATER_CHEAT_LEVEL())
2847 			{
2848 				// adding money
2849 				AddTransactionToPlayersBook(ANONYMOUS_DEPOSIT, 0, GetWorldTotalMin(), 100000);
2850 				MarkButtonsDirty();
2851 			}
2852 			break;
2853 
2854 		case '-':
2855 			if (CHEATER_CHEAT_LEVEL())
2856 			{
2857 				// subtracting money
2858 				AddTransactionToPlayersBook(ANONYMOUS_DEPOSIT, 0, GetWorldTotalMin(), -10000);
2859 				MarkButtonsDirty();
2860 			}
2861 			break;
2862 	}
2863 }
2864 
2865 
RenderWWWProgramTitleBar(void)2866 void RenderWWWProgramTitleBar(void)
2867 {
2868 	// will render the title bar for the www program
2869 	BltVideoObjectOnce(FRAME_BUFFER, LAPTOPDIR "/programtitlebar.sti", 0, LAPTOP_SCREEN_UL_X, LAPTOP_SCREEN_UL_Y - 2);
2870 
2871 	// now slapdown text
2872 	SetFontAttributes(FONT14ARIAL, FONT_WHITE);
2873 
2874 	// display title
2875 
2876 	// no page loaded yet, do not handle yet
2877 
2878 	if (guiCurrentLaptopMode == LAPTOP_MODE_WWW)
2879 	{
2880 		MPrint(STD_SCREEN_X + 140, STD_SCREEN_Y + 33, pWebTitle);
2881 	}
2882 	else
2883 	{
2884 		const INT32 iIndex = guiCurrentLaptopMode - LAPTOP_MODE_WWW-1;
2885 		MPrint(STD_SCREEN_X + 140, STD_SCREEN_Y + 33, ST::format("{}  -  {}", pWebTitle, pWebPagesTitles[iIndex]));
2886 	}
2887 
2888 	BlitTitleBarIcons();
2889 	DisplayProgramBoundingBox(FALSE);
2890 }
2891 
2892 
2893 static void LaptopProgramIconMinimizeCallback(MOUSE_REGION* pRegion, INT32 iReason);
2894 
2895 
CreateMinimizeRegionsForLaptopProgramIcons(void)2896 static void CreateMinimizeRegionsForLaptopProgramIcons(void)
2897 {
2898 	// will create the minizing region to lie over the icon for this particular laptop program
2899 	const UINT16 x = LAPTOP_PROGRAM_ICON_X;
2900 	const UINT16 y = LAPTOP_PROGRAM_ICON_Y;
2901 	const UINT16 w = LAPTOP_PROGRAM_ICON_WIDTH;
2902 	const UINT16 h = LAPTOP_PROGRAM_ICON_HEIGHT;
2903 	MSYS_DefineRegion(&gLapTopProgramMinIcon, x, y, x + w, y + h, MSYS_PRIORITY_NORMAL + 1, CURSOR_LAPTOP_SCREEN, MSYS_NO_CALLBACK, LaptopProgramIconMinimizeCallback);
2904 }
2905 
2906 
DestroyMinimizeRegionsForLaptopProgramIcons(void)2907 static void DestroyMinimizeRegionsForLaptopProgramIcons(void)
2908 {
2909 	// will destroy the minizmize regions to be placed over the laptop icons that will be
2910 	// displayed on the top of the laptop program bar
2911 	MSYS_RemoveRegion(&gLapTopProgramMinIcon);
2912 }
2913 
2914 
LaptopProgramIconMinimizeCallback(MOUSE_REGION * pRegion,INT32 iReason)2915 static void LaptopProgramIconMinimizeCallback(MOUSE_REGION* pRegion, INT32 iReason)
2916 {
2917 	// callback handler for the minize region that is attatched to the laptop program icon
2918 	if (iReason & MSYS_CALLBACK_REASON_LBUTTON_UP)
2919 	{
2920 		switch (guiCurrentLaptopMode)
2921 		{
2922 			case LAPTOP_MODE_EMAIL:
2923 				gLaptopProgramStates[LAPTOP_PROGRAM_MAILER] = LAPTOP_PROGRAM_MINIMIZED;
2924 				InitTitleBarMaximizeGraphics(guiTITLEBARLAPTOP, pLaptopIcons[0], guiTITLEBARICONS, 0);
2925 				SetCurrentToLastProgramOpened();
2926 				break;
2927 
2928 			case LAPTOP_MODE_FILES:
2929 				gLaptopProgramStates[LAPTOP_PROGRAM_FILES] = LAPTOP_PROGRAM_MINIMIZED;
2930 				InitTitleBarMaximizeGraphics(guiTITLEBARLAPTOP, pLaptopIcons[5], guiTITLEBARICONS, 2);
2931 				SetCurrentToLastProgramOpened();
2932 				break;
2933 
2934 			case LAPTOP_MODE_FINANCES:
2935 				gLaptopProgramStates[LAPTOP_PROGRAM_FINANCES] = LAPTOP_PROGRAM_MINIMIZED;
2936 				InitTitleBarMaximizeGraphics(guiTITLEBARLAPTOP, pLaptopIcons[2], guiTITLEBARICONS, 5);
2937 				SetCurrentToLastProgramOpened();
2938 				break;
2939 
2940 			case LAPTOP_MODE_HISTORY:
2941 				gLaptopProgramStates[LAPTOP_PROGRAM_HISTORY] = LAPTOP_PROGRAM_MINIMIZED;
2942 				InitTitleBarMaximizeGraphics(guiTITLEBARLAPTOP, pLaptopIcons[4], guiTITLEBARICONS, 4);
2943 				SetCurrentToLastProgramOpened();
2944 				break;
2945 
2946 			case LAPTOP_MODE_PERSONNEL:
2947 				gLaptopProgramStates[LAPTOP_PROGRAM_PERSONNEL] = LAPTOP_PROGRAM_MINIMIZED;
2948 				InitTitleBarMaximizeGraphics(guiTITLEBARLAPTOP, pLaptopIcons[3], guiTITLEBARICONS, 3);
2949 				SetCurrentToLastProgramOpened();
2950 				break;
2951 
2952 			case LAPTOP_MODE_NONE: return; // nothing
2953 
2954 			default:
2955 				gLaptopProgramStates[LAPTOP_PROGRAM_WEB_BROWSER] = LAPTOP_PROGRAM_MINIMIZED;
2956 				InitTitleBarMaximizeGraphics(guiTITLEBARLAPTOP, pWebTitle, guiTITLEBARICONS, 1);
2957 				SetCurrentToLastProgramOpened();
2958 				gfShowBookmarks = FALSE;
2959 				fShowBookmarkInfo = FALSE;
2960 				break;
2961 		}
2962 		fMinizingProgram = TRUE;
2963 		fInitTitle = TRUE;
2964 	}
2965 }
2966 
2967 
DisplayProgramBoundingBox(BOOLEAN fMarkButtons)2968 void DisplayProgramBoundingBox(BOOLEAN fMarkButtons)
2969 {
2970 	// the border for the program
2971 	BltVideoObject(FRAME_BUFFER, guiLaptopBACKGROUND, 1, STD_SCREEN_X + 25, STD_SCREEN_Y + 23);
2972 
2973 	// no laptop mode, no border around the program
2974 	if (guiCurrentLaptopMode != LAPTOP_MODE_NONE)
2975 	{
2976 		BltVideoObject(FRAME_BUFFER, guiLaptopBACKGROUND, 0, STD_SCREEN_X + 108, STD_SCREEN_Y + 23);
2977 	}
2978 
2979 	if (fMarkButtons || fLoadPendingFlag)
2980 	{
2981 		MarkButtonsDirty();
2982 		RenderButtons();
2983 	}
2984 
2985 	PrintDate();
2986 	PrintBalance();
2987 	PrintNumberOnTeam();
2988 	DisplayTaskBarIcons();
2989 }
2990 
2991 
2992 static void NewEmailIconCallback(MOUSE_REGION* pRegion, INT32 iReason);
2993 static void NewFileIconCallback(MOUSE_REGION* pRegion, INT32 iReason);
2994 
2995 
CreateDestroyMouseRegionForNewMailIcon(void)2996 static void CreateDestroyMouseRegionForNewMailIcon(void)
2997 {
2998 	static BOOLEAN fCreated = FALSE;
2999 
3000 	// will toggle creation/destruction of the mouse regions used by the new mail icon
3001 	if (!fCreated)
3002 	{
3003 		fCreated = TRUE;
3004 		{
3005 			const UINT16 x = LAPTOP__NEW_EMAIL_ICON_X;
3006 			const UINT16 y = LAPTOP__NEW_EMAIL_ICON_Y;
3007 			MSYS_DefineRegion(&gNewMailIconRegion, x, y + 5,  x + 16,  y + 16, MSYS_PRIORITY_HIGHEST - 3, CURSOR_LAPTOP_SCREEN, MSYS_NO_CALLBACK, NewEmailIconCallback);
3008 			CreateFileAndNewEmailIconFastHelpText(LAPTOP_BN_HLP_TXT_YOU_HAVE_NEW_MAIL, fUnReadMailFlag == 0);
3009 		}
3010 
3011 		{
3012 			const UINT16 x = LAPTOP__NEW_FILE_ICON_X;
3013 			const UINT16 y = LAPTOP__NEW_FILE_ICON_Y;
3014 			MSYS_DefineRegion(&gNewFileIconRegion, x, y + 5,  x + 16,  y + 16, MSYS_PRIORITY_HIGHEST - 3, CURSOR_LAPTOP_SCREEN, MSYS_NO_CALLBACK, NewFileIconCallback);
3015 			CreateFileAndNewEmailIconFastHelpText(LAPTOP_BN_HLP_TXT_YOU_HAVE_NEW_FILE, fNewFilesInFileViewer == 0);
3016 		}
3017 	}
3018 	else
3019 	{
3020 		fCreated = FALSE;
3021 		MSYS_RemoveRegion(&gNewMailIconRegion);
3022 		MSYS_RemoveRegion(&gNewFileIconRegion);
3023 	}
3024 }
3025 
3026 
NewEmailIconCallback(MOUSE_REGION * pRegion,INT32 iReason)3027 static void NewEmailIconCallback(MOUSE_REGION* pRegion, INT32 iReason)
3028 {
3029 	if (iReason & MSYS_CALLBACK_REASON_LBUTTON_UP)
3030 	{
3031 		if (fUnReadMailFlag)
3032 		{
3033 			fOpenMostRecentUnReadFlag = TRUE;
3034 			guiCurrentLaptopMode = LAPTOP_MODE_EMAIL;
3035 		}
3036 	}
3037 }
3038 
3039 
NewFileIconCallback(MOUSE_REGION * pRegion,INT32 iReason)3040 static void NewFileIconCallback(MOUSE_REGION* pRegion, INT32 iReason)
3041 {
3042 	if (iReason & MSYS_CALLBACK_REASON_LBUTTON_UP)
3043 	{
3044 		if (fNewFilesInFileViewer)
3045 		{
3046 			fEnteredFileViewerFromNewFileIcon = TRUE;
3047 			guiCurrentLaptopMode = LAPTOP_MODE_FILES;
3048 		}
3049 	}
3050 }
3051 
3052 
HandleWWWSubSites(void)3053 static void HandleWWWSubSites(void)
3054 {
3055 	// check to see if WW Wait is needed for a sub site within the Web Browser
3056 	if (guiCurrentLaptopMode == guiPreviousLaptopMode ||
3057 			guiCurrentLaptopMode < LAPTOP_MODE_WWW ||
3058 			fLoadPendingFlag ||
3059 			fDoneLoadPending ||
3060 			guiPreviousLaptopMode < LAPTOP_MODE_WWW)
3061 	{
3062 		// no go, leave
3063 		return;
3064 	}
3065 
3066 	fLoadPendingFlag = TRUE;
3067 	fConnectingToSubPage = TRUE;
3068 
3069 	// fast or slow load?
3070 	bool& visited = gfWWWaitSubSitesVisitedFlags[guiCurrentLaptopMode - (LAPTOP_MODE_WWW + 1)];
3071 	if (visited) fFastLoadFlag = TRUE;
3072 	visited = true; // Set fact we were here
3073 
3074 	//Dont show the dlownload screen when switching between these pages
3075 	if ((guiCurrentLaptopMode == LAPTOP_MODE_AIM_MEMBERS              && guiPreviousLaptopMode == LAPTOP_MODE_AIM_MEMBERS_FACIAL_INDEX) ||
3076 			(guiCurrentLaptopMode == LAPTOP_MODE_AIM_MEMBERS_FACIAL_INDEX && guiPreviousLaptopMode == LAPTOP_MODE_AIM_MEMBERS))
3077 	{
3078 		fFastLoadFlag = FALSE;
3079 		fLoadPendingFlag = FALSE;
3080 
3081 		// set fact we were here
3082 		gfWWWaitSubSitesVisitedFlags[LAPTOP_MODE_AIM_MEMBERS_FACIAL_INDEX - (LAPTOP_MODE_WWW + 1)] = true;
3083 		gfWWWaitSubSitesVisitedFlags[LAPTOP_MODE_AIM_MEMBERS              - (LAPTOP_MODE_WWW + 1)] = true;
3084 	}
3085 }
3086 
3087 
UpdateStatusOfDisplayingBookMarks(void)3088 static void UpdateStatusOfDisplayingBookMarks(void)
3089 {
3090 	// this function will disable showing of bookmarks if in process of download or if we miniming web browser
3091 	if (fLoadPendingFlag || guiCurrentLaptopMode < LAPTOP_MODE_WWW)
3092 	{
3093 		gfShowBookmarks = FALSE;
3094 	}
3095 }
3096 
3097 
InitalizeSubSitesList(void)3098 static void InitalizeSubSitesList(void)
3099 {
3100 	// init all subsites list to not visited
3101 	FOR_EACH(bool, i, gfWWWaitSubSitesVisitedFlags)
3102 	{
3103 		*i = false;
3104 	}
3105 }
3106 
3107 
SetSubSiteAsVisted(void)3108 static void SetSubSiteAsVisted(void)
3109 {
3110 	// sets a www sub site as visited
3111 	// not at a web page yet?
3112 	if (guiCurrentLaptopMode <= LAPTOP_MODE_WWW) return;
3113 
3114 	gfWWWaitSubSitesVisitedFlags[guiCurrentLaptopMode - (LAPTOP_MODE_WWW + 1)] = true;
3115 }
3116 
3117 
HandleShiftAltTabKeyInLaptop(void)3118 static void HandleShiftAltTabKeyInLaptop(void)
3119 {
3120 	// will handle the alt tab keying in laptop
3121 
3122 	// move to next program
3123 	if (fMaximizingProgram) return;
3124 
3125 	switch (guiCurrentLaptopMode)
3126 	{
3127 		case LAPTOP_MODE_FINANCES:  guiCurrentLaptopMode = LAPTOP_MODE_PERSONNEL; break;
3128 		case LAPTOP_MODE_PERSONNEL: guiCurrentLaptopMode = LAPTOP_MODE_HISTORY;   break;
3129 		case LAPTOP_MODE_HISTORY:   guiCurrentLaptopMode = LAPTOP_MODE_FILES;     break;
3130 		case LAPTOP_MODE_EMAIL:     guiCurrentLaptopMode = LAPTOP_MODE_FINANCES;  break;
3131 		case LAPTOP_MODE_FILES:     guiCurrentLaptopMode = LAPTOP_MODE_WWW;       break;
3132 		case LAPTOP_MODE_NONE:      guiCurrentLaptopMode = LAPTOP_MODE_FINANCES;  break;
3133 		case LAPTOP_MODE_WWW:       guiCurrentLaptopMode = LAPTOP_MODE_EMAIL;     break;
3134 		default:                    guiCurrentLaptopMode = LAPTOP_MODE_EMAIL;     break;
3135 	}
3136 
3137 	fPausedReDrawScreenFlag = TRUE;
3138 }
3139 
3140 
HandleAltTabKeyInLaptop(void)3141 static void HandleAltTabKeyInLaptop(void)
3142 {
3143 	// will handle the alt tab keying in laptop
3144 
3145 	// move to next program
3146 	if (fMaximizingProgram) return;
3147 
3148 	switch (guiCurrentLaptopMode)
3149 	{
3150 		case LAPTOP_MODE_FINANCES:  guiCurrentLaptopMode = LAPTOP_MODE_EMAIL;     break;
3151 		case LAPTOP_MODE_PERSONNEL: guiCurrentLaptopMode = LAPTOP_MODE_FINANCES;  break;
3152 		case LAPTOP_MODE_HISTORY:   guiCurrentLaptopMode = LAPTOP_MODE_PERSONNEL; break;
3153 		case LAPTOP_MODE_EMAIL:     guiCurrentLaptopMode = LAPTOP_MODE_WWW;       break;
3154 		case LAPTOP_MODE_FILES:     guiCurrentLaptopMode = LAPTOP_MODE_HISTORY;   break;
3155 		case LAPTOP_MODE_NONE:      guiCurrentLaptopMode = LAPTOP_MODE_EMAIL;     break;
3156 		default:                    guiCurrentLaptopMode = LAPTOP_MODE_FILES;     break;
3157 	}
3158 
3159 	fPausedReDrawScreenFlag = TRUE;
3160 }
3161 
3162 
3163 static void HandleWebBookMarkNotifyTimer(void);
3164 
3165 
3166 // display the 2 second book mark instruction
DisplayWebBookMarkNotify(void)3167 static void DisplayWebBookMarkNotify(void)
3168 {
3169 	static BOOLEAN fOldShow = FALSE;
3170 
3171 	// handle the timer for this thing
3172 	HandleWebBookMarkNotifyTimer();
3173 
3174 	// are we about to start showing box? or did we just stop?
3175 	if ((!fOldShow || fReDrawBookMarkInfo) && fShowBookmarkInfo)
3176 	{
3177 		fOldShow = TRUE;
3178 		fReDrawBookMarkInfo = FALSE;
3179 
3180 		// show background objects
3181 		BltVideoObject(FRAME_BUFFER, guiDOWNLOADTOP,   0,DOWNLOAD_X,     DOWNLOAD_Y);
3182 		BltVideoObject(FRAME_BUFFER, guiDOWNLOADMID,   0,DOWNLOAD_X,     DOWNLOAD_Y +     DOWN_HEIGHT);
3183 		BltVideoObject(FRAME_BUFFER, guiDOWNLOADBOT,   0,DOWNLOAD_X,     DOWNLOAD_Y + 2 * DOWN_HEIGHT);
3184 		BltVideoObject(FRAME_BUFFER, guiTITLEBARICONS, 1,DOWNLOAD_X + 4, DOWNLOAD_Y + 1);
3185 
3186 		SetFontAttributes(DOWNLOAD_FONT, FONT_WHITE, NO_SHADOW);
3187 
3188 		// display download string
3189 		MPrint(DOWN_STRING_X, DOWN_STRING_Y, pShowBookmarkString[0]);
3190 
3191 		// now draw the message
3192 		DisplayWrappedString(DOWN_STRING_X - 42, DOWN_STRING_Y + 20, BOOK_WIDTH + 45, 2, BOOK_FONT, FONT_BLACK, pShowBookmarkString[1], FONT_BLACK, CENTER_JUSTIFIED);
3193 
3194 		// invalidate region
3195 		InvalidateRegion(DOWNLOAD_X, DOWNLOAD_Y, DOWNLOAD_X + 150, DOWNLOAD_Y + 100);
3196 
3197 		SetFontShadow(DEFAULT_SHADOW);
3198 	}
3199 	else if (fOldShow && !fShowBookmarkInfo)
3200 	{
3201 		fOldShow = FALSE;
3202 		fPausedReDrawScreenFlag = TRUE;
3203 	}
3204 }
3205 
3206 
3207 // handle timer for bookmark notify
HandleWebBookMarkNotifyTimer(void)3208 static void HandleWebBookMarkNotifyTimer(void)
3209 {
3210 	static INT32 iBaseTime              = 0;
3211 	static BOOLEAN fOldShowBookMarkInfo = FALSE;
3212 
3213 	// check if maxing or mining?
3214 	if (fMaximizingProgram || fMinizingProgram)
3215 	{
3216 		fOldShowBookMarkInfo |= fShowBookmarkInfo;
3217 		fShowBookmarkInfo     = FALSE;
3218 		return;
3219 	}
3220 
3221 	// if we were going to show this pop up, but were delayed, then do so now
3222 	fShowBookmarkInfo |= fOldShowBookMarkInfo;
3223 
3224 	// reset old flag
3225 	fOldShowBookMarkInfo = FALSE;
3226 
3227 	// if current mode is too low, then reset
3228 	if (guiCurrentLaptopMode < LAPTOP_MODE_WWW)
3229 	{
3230 		fShowBookmarkInfo = FALSE;
3231 	}
3232 
3233 	// if showing bookmarks, don't show help
3234 	if (gfShowBookmarks) fShowBookmarkInfo = FALSE;
3235 
3236 	// check if flag false, is so, leave
3237 	if (!fShowBookmarkInfo)
3238 	{
3239 		iBaseTime = 0;
3240 		return;
3241 	}
3242 
3243 	// check if this is the first time in here
3244 	if (iBaseTime == 0)
3245 	{
3246 		iBaseTime = GetJA2Clock();
3247 		return;
3248 	}
3249 
3250 	const INT32 iDifference = GetJA2Clock() - iBaseTime;
3251 
3252 	fReDrawBookMarkInfo = TRUE;
3253 
3254 	if (iDifference > DISPLAY_TIME_FOR_WEB_BOOKMARK_NOTIFY)
3255 	{
3256 		// waited long enough, stop showing
3257 		iBaseTime = 0;
3258 		fShowBookmarkInfo = FALSE;
3259 	}
3260 }
3261 
3262 
ClearOutTempLaptopFiles(void)3263 void ClearOutTempLaptopFiles(void)
3264 {
3265 	// clear out all temp files from laptop
3266 	FileDelete("files.dat");
3267 	FileDelete("finances.dat");
3268 	FileDelete("email.dat");
3269 	FileDelete("history.dat");
3270 }
3271 
3272 
InjectStoreInvetory(DataWriter & d,STORE_INVENTORY const & i)3273 static void InjectStoreInvetory(DataWriter& d, STORE_INVENTORY const& i)
3274 {
3275 	size_t start = d.getConsumed();
3276 	INJ_U16( d, i.usItemIndex)
3277 	INJ_U8(  d, i.ubQtyOnHand)
3278 	INJ_U8(  d, i.ubQtyOnOrder)
3279 	INJ_U8(  d, i.ubItemQuality)
3280 	INJ_BOOL(d, i.fPreviouslyEligible)
3281 	INJ_SKIP(d, 2)
3282 	Assert(d.getConsumed() == start + 8);
3283 }
3284 
3285 
ExtractStoreInvetory(DataReader & d,STORE_INVENTORY & i)3286 static void ExtractStoreInvetory(DataReader& d, STORE_INVENTORY& i)
3287 {
3288 	size_t start = d.getConsumed();
3289 	EXTR_U16( d, i.usItemIndex)
3290 	EXTR_U8(  d, i.ubQtyOnHand)
3291 	EXTR_U8(  d, i.ubQtyOnOrder)
3292 	EXTR_U8(  d, i.ubItemQuality)
3293 	EXTR_BOOL(d, i.fPreviouslyEligible)
3294 	EXTR_SKIP(d, 2)
3295 	Assert(d.getConsumed() == start + 8);
3296 }
3297 
3298 
SaveLaptopInfoToSavedGame(HWFILE const f)3299 void SaveLaptopInfoToSavedGame(HWFILE const f)
3300 {
3301 	LaptopSaveInfoStruct const& l = LaptopSaveInfo;
3302 
3303 	BYTE  data[7440];
3304 	DataWriter d{data};
3305 	INJ_BOOL( d, l.gfNewGameLaptop)
3306 	INJ_BOOLA(d, l.fVisitedBookmarkAlready, lengthof(l.fVisitedBookmarkAlready))
3307 	INJ_SKIP( d, 3)
3308 	INJ_I32A( d, l.iBookMarkList, lengthof(l.iBookMarkList))
3309 	INJ_I32(  d, l.iCurrentBalance)
3310 	INJ_BOOL( d, l.fIMPCompletedFlag)
3311 	INJ_BOOL( d, l.fSentImpWarningAlready)
3312 	INJ_I16A( d, l.ubDeadCharactersList, lengthof(l.ubDeadCharactersList))
3313 	INJ_I16A( d, l.ubLeftCharactersList, lengthof(l.ubLeftCharactersList))
3314 	INJ_I16A( d, l.ubOtherCharactersList, lengthof(l.ubOtherCharactersList))
3315 	INJ_U8(   d, l.gubPlayersMercAccountStatus)
3316 	INJ_SKIP( d, 1)
3317 	INJ_U32(  d, l.guiPlayersMercAccountNumber)
3318 	INJ_U8(   d, l.gubLastMercIndex)
3319 	INJ_SKIP( d, 1)
3320 	FOR_EACH(STORE_INVENTORY const, i, l.BobbyRayInventory)
3321 	{
3322 		InjectStoreInvetory(d, *i);
3323 	}
3324 	FOR_EACH(STORE_INVENTORY const, i, l.BobbyRayUsedInventory)
3325 	{
3326 		InjectStoreInvetory(d, *i);
3327 	}
3328 	INJ_SKIP( d, 6)
3329 	Assert(l.BobbyRayOrdersOnDeliveryArray.size() <= UINT8_MAX);
3330 	INJ_U8(   d, static_cast<UINT8>(l.BobbyRayOrdersOnDeliveryArray.size()))
3331 	INJ_U8(   d, l.usNumberOfBobbyRayOrderUsed)
3332 	INJ_SKIP( d, 6)
3333 	Assert(l.pLifeInsurancePayouts.size() <= UINT8_MAX);
3334 	INJ_U8(   d, static_cast<UINT8>(l.pLifeInsurancePayouts.size()))
3335 	Assert(l.ubNumberLifeInsurancePayoutUsed <= l.pLifeInsurancePayouts.size());
3336 	INJ_U8(   d, l.ubNumberLifeInsurancePayoutUsed)
3337 	INJ_BOOL( d, l.fBobbyRSiteCanBeAccessed)
3338 	INJ_U8(   d, l.ubPlayerBeenToMercSiteStatus)
3339 	INJ_BOOL( d, l.fFirstVisitSinceServerWentDown)
3340 	INJ_BOOL( d, l.fNewMercsAvailableAtMercSite)
3341 	INJ_BOOL( d, l.fSaidGenericOpeningInMercSite)
3342 	INJ_BOOL( d, l.fSpeckSaidFloMarriedCousinQuote)
3343 	INJ_BOOL( d, l.fHasAMercDiedAtMercSite)
3344 	INJ_SKIP( d, 11)
3345 	INJ_U16A( d, l.usInventoryListLength, lengthof(l.usInventoryListLength))
3346 	INJ_I32(  d, l.iVoiceId)
3347 	INJ_U8(   d, l.ubHaveBeenToBobbyRaysAtLeastOnceWhileUnderConstruction)
3348 	INJ_BOOL( d, l.fMercSiteHasGoneDownYet)
3349 	INJ_U8(   d, l.ubSpeckCanSayPlayersLostQuote)
3350 	INJ_SKIP( d, 1)
3351 	INJ_BOOL( d, l.sLastHiredMerc.fHaveDisplayedPopUpInLaptop)
3352 	INJ_SKIP( d, 3)
3353 	INJ_I32(  d, l.sLastHiredMerc.iIdOfMerc)
3354 	INJ_U32(  d, l.sLastHiredMerc.uiArrivalTime)
3355 	INJ_I32(  d, l.iCurrentHistoryPage)
3356 	INJ_I32(  d, l.iCurrentFinancesPage)
3357 	INJ_I32(  d, l.iCurrentEmailPage)
3358 	INJ_U32(  d, l.uiSpeckQuoteFlags)
3359 	INJ_U32(  d, l.uiFlowerOrderNumber)
3360 	INJ_U32(  d, l.uiTotalMoneyPaidToSpeck)
3361 	INJ_U8(   d, l.ubLastMercAvailableId)
3362 	INJ_SKIP( d, 87)
3363 	Assert(d.getConsumed() == lengthof(data));
3364 
3365 	FileWrite(f, data, sizeof(data));
3366 
3367 	if (l.usNumberOfBobbyRayOrderUsed != 0)
3368 	{ // There is anything in the Bobby Ray Orders on delivery
3369 		size_t const size = sizeof(*l.BobbyRayOrdersOnDeliveryArray.data()) * l.BobbyRayOrdersOnDeliveryArray.size();
3370 		FileWrite(f, l.BobbyRayOrdersOnDeliveryArray.data(), size);
3371 	}
3372 
3373 	if (l.ubNumberLifeInsurancePayoutUsed != 0)
3374 	{ // There are any insurance payouts in progress
3375 		FileWrite(f, l.pLifeInsurancePayouts.data(), sizeof(LIFE_INSURANCE_PAYOUT) * l.pLifeInsurancePayouts.size());
3376 	}
3377 }
3378 
3379 
LoadLaptopInfoFromSavedGame(HWFILE const f)3380 void LoadLaptopInfoFromSavedGame(HWFILE const f)
3381 {
3382 	LaptopSaveInfoStruct& l = LaptopSaveInfo;
3383 
3384 	l.BobbyRayOrdersOnDeliveryArray.clear();
3385 
3386 	l.pLifeInsurancePayouts.clear();
3387 
3388 	BYTE data[7440];
3389 	FileRead(f, data, sizeof(data));
3390 
3391 	DataReader d{data};
3392 	EXTR_BOOL( d, l.gfNewGameLaptop)
3393 	EXTR_BOOLA(d, l.fVisitedBookmarkAlready, lengthof(l.fVisitedBookmarkAlready))
3394 	EXTR_SKIP( d, 3)
3395 	EXTR_I32A( d, l.iBookMarkList, lengthof(l.iBookMarkList))
3396 	EXTR_I32(  d, l.iCurrentBalance)
3397 	EXTR_BOOL( d, l.fIMPCompletedFlag)
3398 	EXTR_BOOL( d, l.fSentImpWarningAlready)
3399 	EXTR_I16A( d, l.ubDeadCharactersList, lengthof(l.ubDeadCharactersList))
3400 	EXTR_I16A( d, l.ubLeftCharactersList, lengthof(l.ubLeftCharactersList))
3401 	EXTR_I16A( d, l.ubOtherCharactersList, lengthof(l.ubOtherCharactersList))
3402 	EXTR_U8(   d, l.gubPlayersMercAccountStatus)
3403 	EXTR_SKIP( d, 1)
3404 	EXTR_U32(  d, l.guiPlayersMercAccountNumber)
3405 	EXTR_U8(   d, l.gubLastMercIndex)
3406 	EXTR_SKIP( d, 1)
3407 	FOR_EACH(STORE_INVENTORY, i, l.BobbyRayInventory)
3408 	{
3409 		ExtractStoreInvetory(d, *i);
3410 	}
3411 	FOR_EACH(STORE_INVENTORY, i, l.BobbyRayUsedInventory)
3412 	{
3413 		ExtractStoreInvetory(d, *i);
3414 	}
3415 	EXTR_SKIP( d, 6)
3416 	UINT8 BobbyRayOrdersOnDeliveryArraySize;
3417 	EXTR_U8(   d, BobbyRayOrdersOnDeliveryArraySize)
3418 	EXTR_U8(   d, l.usNumberOfBobbyRayOrderUsed)
3419 	EXTR_SKIP( d, 6)
3420 	UINT8 numLifeInsurancePayouts;
3421 	EXTR_U8(   d, numLifeInsurancePayouts)
3422 	EXTR_U8(   d, l.ubNumberLifeInsurancePayoutUsed)
3423 	Assert(l.ubNumberLifeInsurancePayoutUsed <= numLifeInsurancePayouts);
3424 	EXTR_BOOL( d, l.fBobbyRSiteCanBeAccessed)
3425 	EXTR_U8(   d, l.ubPlayerBeenToMercSiteStatus)
3426 	EXTR_BOOL( d, l.fFirstVisitSinceServerWentDown)
3427 	EXTR_BOOL( d, l.fNewMercsAvailableAtMercSite)
3428 	EXTR_BOOL( d, l.fSaidGenericOpeningInMercSite)
3429 	EXTR_BOOL( d, l.fSpeckSaidFloMarriedCousinQuote)
3430 	EXTR_BOOL( d, l.fHasAMercDiedAtMercSite)
3431 	EXTR_SKIP( d, 11)
3432 	EXTR_U16A( d, l.usInventoryListLength, lengthof(l.usInventoryListLength))
3433 	EXTR_I32(  d, l.iVoiceId)
3434 	EXTR_U8(   d, l.ubHaveBeenToBobbyRaysAtLeastOnceWhileUnderConstruction)
3435 	EXTR_BOOL( d, l.fMercSiteHasGoneDownYet)
3436 	EXTR_U8(   d, l.ubSpeckCanSayPlayersLostQuote)
3437 	EXTR_SKIP( d, 1)
3438 	EXTR_BOOL( d, l.sLastHiredMerc.fHaveDisplayedPopUpInLaptop)
3439 	EXTR_SKIP( d, 3)
3440 	EXTR_I32(  d, l.sLastHiredMerc.iIdOfMerc)
3441 	EXTR_U32(  d, l.sLastHiredMerc.uiArrivalTime)
3442 	EXTR_I32(  d, l.iCurrentHistoryPage)
3443 	EXTR_I32(  d, l.iCurrentFinancesPage)
3444 	EXTR_I32(  d, l.iCurrentEmailPage)
3445 	EXTR_U32(  d, l.uiSpeckQuoteFlags)
3446 	EXTR_U32(  d, l.uiFlowerOrderNumber)
3447 	EXTR_U32(  d, l.uiTotalMoneyPaidToSpeck)
3448 	EXTR_U8(   d, l.ubLastMercAvailableId)
3449 	EXTR_SKIP( d, 87)
3450 	Assert(d.getConsumed() == lengthof(data));
3451 
3452 	// Handle old saves in M.E.R.C. module
3453 	SyncLastMercFromSaveGame();
3454 
3455 	if (l.usNumberOfBobbyRayOrderUsed != 0)
3456 	{ // There is anything in the Bobby Ray Orders on Delivery
3457 		l.BobbyRayOrdersOnDeliveryArray.resize(BobbyRayOrdersOnDeliveryArraySize);
3458 		size_t const size = sizeof(*l.BobbyRayOrdersOnDeliveryArray.data()) * BobbyRayOrdersOnDeliveryArraySize;
3459 		FileRead(f, l.BobbyRayOrdersOnDeliveryArray.data(), size);
3460 	}
3461 	else
3462 	{
3463 		l.BobbyRayOrdersOnDeliveryArray.clear();
3464 	}
3465 
3466 	if (l.ubNumberLifeInsurancePayoutUsed != 0)
3467 	{ // There are any Insurance Payouts in progress
3468 		l.pLifeInsurancePayouts.assign(numLifeInsurancePayouts, LIFE_INSURANCE_PAYOUT{});
3469 		FileRead(f, l.pLifeInsurancePayouts.data(), sizeof(LIFE_INSURANCE_PAYOUT) * numLifeInsurancePayouts);
3470 	}
3471 	else
3472 	{
3473 		l.pLifeInsurancePayouts.clear();
3474 	}
3475 }
3476 
3477 
WWaitDelayIncreasedIfRaining(INT32 iUnitTime)3478 static INT32 WWaitDelayIncreasedIfRaining(INT32 iUnitTime)
3479 {
3480 	INT32 iRetVal = 0;
3481 	if (guiEnvWeather & WEATHER_FORECAST_THUNDERSHOWERS)
3482 	{
3483 		iRetVal = iUnitTime * 0.8f;
3484 	}
3485 	else if (guiEnvWeather & WEATHER_FORECAST_SHOWERS)
3486 	{
3487 		iRetVal = iUnitTime * 0.6f;
3488 	}
3489 	return iRetVal;
3490 }
3491 
3492 
3493 // Used to determine delay if its raining
IsItRaining(void)3494 static BOOLEAN IsItRaining(void)
3495 {
3496 	return
3497 		guiEnvWeather & WEATHER_FORECAST_SHOWERS ||
3498 		guiEnvWeather & WEATHER_FORECAST_THUNDERSHOWERS;
3499 }
3500 
3501 
InternetRainDelayMessageBoxCallBack(MessageBoxReturnValue const bExitValue)3502 static void InternetRainDelayMessageBoxCallBack(MessageBoxReturnValue const bExitValue)
3503 {
3504 	GoToWebPage(giRainDelayInternetSite);
3505 
3506 	//Set to -2 so we dont due the message for this occurence of laptop
3507 	giRainDelayInternetSite = -2;
3508 }
3509 
3510 
CreateFileAndNewEmailIconFastHelpText(UINT32 uiHelpTextID,BOOLEAN fClearHelpText)3511 void CreateFileAndNewEmailIconFastHelpText(UINT32 uiHelpTextID, BOOLEAN fClearHelpText)
3512 {
3513 	MOUSE_REGION* pRegion;
3514 	switch (uiHelpTextID)
3515 	{
3516 		case LAPTOP_BN_HLP_TXT_YOU_HAVE_NEW_MAIL: pRegion = &gNewMailIconRegion; break;
3517 		case LAPTOP_BN_HLP_TXT_YOU_HAVE_NEW_FILE: pRegion = &gNewFileIconRegion; break;
3518 
3519 		default:
3520 			SLOGA("CreateFileAndNewEmailIconFastHelpText: invalid HelpTextID");
3521 			return;
3522 	}
3523 
3524 	ST::string help = (fClearHelpText ? ST::null : gzLaptopHelpText[uiHelpTextID]);
3525 	pRegion->SetFastHelpText(help);
3526 }
3527 
3528 
3529 #ifdef WITH_UNITTESTS
3530 #include "gtest/gtest.h"
3531 
TEST(Laptop,asserts)3532 TEST(Laptop, asserts)
3533 {
3534 	EXPECT_EQ(sizeof(LIFE_INSURANCE_PAYOUT), 8u);
3535 	EXPECT_EQ(sizeof(BobbyRayPurchaseStruct), 8u);
3536 	EXPECT_EQ(sizeof(BobbyRayOrderStruct), 84u);
3537 }
3538 
3539 #endif
3540