1 #include "Directories.h"
2 #include "Font.h"
3 #include "Laptop.h"
4 #include "Finances.h"
5 #include "Game_Clock.h"
6 #include "LoadSaveData.h"
7 #include "Map_Screen_Interface_Bottom.h"
8 #include "VObject.h"
9 #include "Debug.h"
10 #include "Render_Dirty.h"
11 #include "Cursors.h"
12 #include "Soldier_Profile.h"
13 #include "Text.h"
14 #include "Strategic_Mines.h"
15 #include "LaptopSave.h"
16 #include "Campaign_Types.h"
17 #include "StrategicMap.h"
18 #include "VSurface.h"
19 #include "MemMan.h"
20 #include "Button_System.h"
21 #include "Font_Control.h"
22 #include "FileMan.h"
23
24 #include "ContentManager.h"
25 #include "GameInstance.h"
26
27 #include <string_theory/format>
28 #include <string_theory/string>
29
30
31 #define FINANCE_HEADER_SIZE 4
32 #define FINANCE_RECORD_SIZE (1 + 1 + 4 + 4 + 4)
33
34
35 // the financial structure
36 struct FinanceUnit
37 {
38 UINT8 ubCode; // the code index in the finance code table
39 UINT8 ubSecondCode; // secondary code
40 UINT32 uiDate; // time in the world in global time
41 INT32 iAmount; // the amount of the transaction
42 INT32 iBalanceToDate;
43 FinanceUnit* Next; // next unit in the list
44 };
45
46
47 // the global defines
48
49 // graphical positions
50 #define TOP_X 0+LAPTOP_SCREEN_UL_X
51 #define TOP_Y LAPTOP_SCREEN_UL_Y
52 #define BLOCK_HEIGHT 10
53 #define TOP_DIVLINE_Y (102 + STD_SCREEN_Y)
54 #define DIVLINE_X (130 + STD_SCREEN_X)
55 #define MID_DIVLINE_Y (205 + STD_SCREEN_Y)
56 #define BOT_DIVLINE_Y (180 + STD_SCREEN_Y)
57 #define MID_DIVLINE_Y2 (263 + 20 + STD_SCREEN_Y)
58 #define BOT_DIVLINE_Y2 MID_DIVLINE_Y2 + MID_DIVLINE_Y - BOT_DIVLINE_Y
59 #define TITLE_X (140 + STD_SCREEN_X)
60 #define TITLE_Y (33 + STD_SCREEN_Y)
61 #define TEXT_X (140 + STD_SCREEN_X)
62 #define PAGE_SIZE 17
63
64 // yesterdyas/todays income and balance text positions
65 #define YESTERDAYS_INCOME (STD_SCREEN_Y + 114)
66 #define YESTERDAYS_OTHER (STD_SCREEN_Y + 138)
67 #define YESTERDAYS_DEBITS (STD_SCREEN_Y + 162)
68 #define YESTERDAYS_BALANCE (STD_SCREEN_Y + 188)
69 #define TODAYS_INCOME (STD_SCREEN_Y + 215)
70 #define TODAYS_OTHER (STD_SCREEN_Y + 239)
71 #define TODAYS_DEBITS (STD_SCREEN_Y + 263)
72 #define TODAYS_CURRENT_BALANCE (STD_SCREEN_Y + 263 + 28)
73 #define TODAYS_CURRENT_FORCAST_INCOME (STD_SCREEN_Y + 330)
74 #define TODAYS_CURRENT_FORCAST_BALANCE (STD_SCREEN_Y + 354)
75 #define FINANCE_HEADER_FONT FONT14ARIAL
76 #define FINANCE_TEXT_FONT FONT12ARIAL
77 #define NUM_RECORDS_PER_PAGE PAGE_SIZE
78
79 // records text positions
80 #define RECORD_CREDIT_WIDTH (106-47)
81 #define RECORD_DEBIT_WIDTH RECORD_CREDIT_WIDTH
82 #define RECORD_DATE_X TOP_X+10
83 #define RECORD_TRANSACTION_X RECORD_DATE_X+RECORD_DATE_WIDTH
84 #define RECORD_TRANSACTION_WIDTH 500-280
85 #define RECORD_DEBIT_X RECORD_TRANSACTION_X+RECORD_TRANSACTION_WIDTH
86 #define RECORD_CREDIT_X RECORD_DEBIT_X+RECORD_DEBIT_WIDTH
87 #define RECORD_Y (107-10 + STD_SCREEN_Y)
88 #define RECORD_DATE_WIDTH 47
89 #define RECORD_BALANCE_X RECORD_DATE_X+385
90 #define RECORD_BALANCE_WIDTH 479-385
91 #define RECORD_HEADER_Y (90 + STD_SCREEN_Y)
92
93
94 #define PAGE_NUMBER_X TOP_X+297 //345
95 #define PAGE_NUMBER_Y TOP_Y+33
96
97
98 // BUTTON defines
99 enum{
100 PREV_PAGE_BUTTON=0,
101 NEXT_PAGE_BUTTON,
102 FIRST_PAGE_BUTTON,
103 LAST_PAGE_BUTTON,
104 };
105
106
107 // button positions
108
109 #define FIRST_PAGE_X (STD_SCREEN_X + 505)
110 #define NEXT_BTN_X (STD_SCREEN_X + 553)
111 #define PREV_BTN_X (STD_SCREEN_X + 529)
112 #define LAST_PAGE_X (STD_SCREEN_X + 577)
113 #define BTN_Y (STD_SCREEN_Y + 53)
114
115
116
117 // sizeof one record
118 #define RECORD_SIZE ( sizeof( UINT32 ) + sizeof( INT32 ) + sizeof( INT32 ) + sizeof( UINT8 ) + sizeof( UINT8 ) )
119
120
121
122
123 // the financial record list
124 static FinanceUnit* pFinanceListHead = NULL;
125
126 // current page displayed
127 static INT32 iCurrentPage = 0;
128
129 // video object id's
130 static SGPVObject* guiTITLE;
131 static SGPVObject* guiTOP;
132 static SGPVObject* guiLINE;
133 static SGPVObject* guiLONGLINE;
134 static SGPVObject* guiLISTCOLUMNS;
135
136 // are in the financial system right now?
137 static BOOLEAN fInFinancialMode = FALSE;
138
139
140 // the last page altogether
141 static UINT32 guiLastPageInRecordsList = 0;
142
143 // finance screen buttons
144 static GUIButtonRef giFinanceButton[4];
145 static BUTTON_PICS* giFinanceButtonImage[4];
146 static MOUSE_REGION g_scroll_region;
147
148 // internal functions
149 static void ProcessAndEnterAFinacialRecord(UINT8 ubCode, UINT32 uiDate, INT32 iAmount, UINT8 ubSecondCode, INT32 iBalanceToDate);
150 static void LoadFinances(void);
151 static void RemoveFinances(void);
152 static void ClearFinanceList(void);
153 static void DrawRecordsColumnHeadersText(void);
154 static void CreateFinanceButtons(void);
155 static void DestroyFinanceButtons(void);
156 static void GetBalanceFromDisk(void);
157 static void WriteBalanceToDisk(void);
158 static void AppendFinanceToEndOfFile(void);
159 static void SetLastPageInRecords(void);
160 static void LoadInRecords(UINT32 page);
161
162 static void SetFinanceButtonStates(void);
163 static INT32 GetTodaysDebits(void);
164 static INT32 GetYesterdaysDebits(void);
165
166
AddTransactionToPlayersBook(UINT8 ubCode,UINT8 ubSecondCode,UINT32 uiDate,INT32 iAmount)167 void AddTransactionToPlayersBook(UINT8 ubCode, UINT8 ubSecondCode, UINT32 uiDate, INT32 iAmount)
168 {
169 // adds transaction to player's book(Financial List)
170 // outside of the financial system(the code in this .c file), this is the only function you'll ever need
171
172 // read in balance from file
173
174 GetBalanceFromDisk( );
175 // process the actual data
176
177
178 //
179 // If this transaction is for the hiring/extending of a mercs contract
180 //
181 if( ubCode == HIRED_MERC ||
182 ubCode == IMP_PROFILE ||
183 ubCode == PAYMENT_TO_NPC ||
184 ubCode == EXTENDED_CONTRACT_BY_1_DAY ||
185 ubCode == EXTENDED_CONTRACT_BY_1_WEEK ||
186 ubCode == EXTENDED_CONTRACT_BY_2_WEEKS
187 )
188 {
189 gMercProfiles[ ubSecondCode ].uiTotalCostToDate += -iAmount;
190 }
191
192 // clear list
193 ClearFinanceList( );
194
195 // update balance
196 LaptopSaveInfo.iCurrentBalance += iAmount;
197
198 ProcessAndEnterAFinacialRecord(ubCode, uiDate, iAmount, ubSecondCode, LaptopSaveInfo.iCurrentBalance);
199
200 // write balance to disk
201 WriteBalanceToDisk( );
202
203 // append to end of file
204 AppendFinanceToEndOfFile();
205
206 // set number of pages
207 SetLastPageInRecords( );
208
209 if( !fInFinancialMode )
210 {
211 ClearFinanceList( );
212 }
213 else
214 {
215 SetFinanceButtonStates( );
216
217 // force update
218 fPausedReDrawScreenFlag = TRUE;
219 }
220
221 fMapScreenBottomDirty = TRUE;
222 }
223
224
GetCurrentBalance(void)225 INT32 GetCurrentBalance( void )
226 {
227 // get balance to this minute
228 return ( LaptopSaveInfo.iCurrentBalance );
229 }
230
231
GetProjectedTotalDailyIncome(void)232 INT32 GetProjectedTotalDailyIncome( void )
233 {
234 // return total projected income, including what is earned today already
235
236 // CJC: I DON'T THINK SO!
237 // The point is: PredictIncomeFromPlayerMines isn't dependant on the time of day
238 // (anymore) and this would report income of 0 at midnight!
239 /*
240 if (GetWorldMinutesInDay() <= 0)
241 {
242 return ( 0 );
243 }
244 */
245 // look at we earned today
246
247 // then there is how many deposits have been made, now look at how many mines we have, thier rate, amount of ore left and predict if we still
248 // had these mines how much more would we get?
249
250 return( PredictIncomeFromPlayerMines() );
251 }
252
253
GameInitFinances()254 void GameInitFinances()
255 {
256 // initialize finances on game start up
257 GCM->deleteTempFile(NEWTMP_FINANCES_DATA_FILE);
258 GetBalanceFromDisk( );
259 }
260
EnterFinances()261 void EnterFinances()
262 {
263 //entry into finanacial system, load graphics, set variables..draw screen once
264 // set the fact we are in the financial display system
265
266 fInFinancialMode=TRUE;
267
268 // get the balance
269 GetBalanceFromDisk( );
270
271 // set number of pages
272 SetLastPageInRecords( );
273
274 // load graphics into memory
275 LoadFinances( );
276
277 // create buttons
278 CreateFinanceButtons( );
279
280 // reset page we are on
281 LoadInRecords(LaptopSaveInfo.iCurrentFinancesPage);
282
283 RenderFinances( );
284 }
285
ExitFinances(void)286 void ExitFinances( void )
287 {
288 LaptopSaveInfo.iCurrentFinancesPage = iCurrentPage;
289
290
291 // not in finance system anymore
292 fInFinancialMode=FALSE;
293
294 // destroy buttons
295 DestroyFinanceButtons( );
296
297 // clear out list
298 ClearFinanceList( );
299
300
301 // remove graphics
302 RemoveFinances( );
303 }
304
305
306 static void DisplayFinancePageNumberAndDateRange(void);
307 static void DrawAPageOfRecords(void);
308 static void DrawFinanceTitleText(void);
309 static void DrawSummary(void);
310 static void RenderBackGround(void);
311
312
RenderFinances(void)313 void RenderFinances(void)
314 {
315 RenderBackGround();
316
317 // if we are on the first page, draw the summary
318 if(iCurrentPage==0)
319 DrawSummary( );
320 else
321 DrawAPageOfRecords( );
322
323 DrawFinanceTitleText( );
324
325 DisplayFinancePageNumberAndDateRange( );
326
327 BltVideoObject(FRAME_BUFFER, guiLaptopBACKGROUND, 0, STD_SCREEN_X + 108, STD_SCREEN_Y + 23);
328
329 BlitTitleBarIcons( );
330 }
331
332
LoadFinances(void)333 static void LoadFinances(void)
334 {
335 // load Finance video objects into memory
336
337 // title bar
338 guiTITLE = AddVideoObjectFromFile(LAPTOPDIR "/programtitlebar.sti");
339
340 // top portion of the screen background
341 guiTOP = AddVideoObjectFromFile(LAPTOPDIR "/financeswindow.sti");
342
343 // black divider line - long ( 480 length)
344 guiLONGLINE = AddVideoObjectFromFile(LAPTOPDIR "/divisionline480.sti");
345
346 // the records columns
347 guiLISTCOLUMNS = AddVideoObjectFromFile(LAPTOPDIR "/recordcolumns.sti");
348
349 // black divider line - long ( 480 length)
350 guiLINE = AddVideoObjectFromFile(LAPTOPDIR "/divisionline.sti");
351 }
352
353
RemoveFinances(void)354 static void RemoveFinances(void)
355 {
356 // delete Finance video objects from memory
357 DeleteVideoObject(guiLONGLINE);
358 DeleteVideoObject(guiLINE);
359 DeleteVideoObject(guiLISTCOLUMNS);
360 DeleteVideoObject(guiTOP);
361 DeleteVideoObject(guiTITLE);
362 }
363
364
RenderBackGround(void)365 static void RenderBackGround(void)
366 {
367 // render generic background for Finance system
368 BltVideoObject(FRAME_BUFFER, guiTITLE, 0, TOP_X, TOP_Y - 2);
369 BltVideoObject(FRAME_BUFFER, guiTOP, 0, TOP_X, TOP_Y + 22);
370 }
371
372
373 static void DrawSummaryLines(void);
374 static void DrawSummaryText(void);
375
376
DrawSummary(void)377 static void DrawSummary(void)
378 {
379 // draw day's summary to screen
380 DrawSummaryLines( );
381 DrawSummaryText( );
382 }
383
384
DrawSummaryLines(void)385 static void DrawSummaryLines(void)
386 {
387 // draw divider lines on screen
388 // blit summary LINE object to screen
389 BltVideoObject(FRAME_BUFFER, guiLINE, 0,DIVLINE_X, TOP_DIVLINE_Y);
390 BltVideoObject(FRAME_BUFFER, guiLINE, 0,DIVLINE_X, TOP_DIVLINE_Y+2);
391 //BltVideoObject(FRAME_BUFFER, guiLINE, 0,DIVLINE_X, MID_DIVLINE_Y);
392 BltVideoObject(FRAME_BUFFER, guiLINE, 0,DIVLINE_X, BOT_DIVLINE_Y);
393 BltVideoObject(FRAME_BUFFER, guiLINE, 0,DIVLINE_X, MID_DIVLINE_Y2);
394 //BltVideoObject(FRAME_BUFFER, guiLINE, 0,DIVLINE_X, BOT_DIVLINE_Y2);
395 }
396
397
398 static void DrawRecordsBackGround(void);
399 static void DrawRecordsText(void);
400
401
DrawAPageOfRecords(void)402 static void DrawAPageOfRecords(void)
403 {
404 // this procedure will draw a series of financial records to the screen
405
406 // (re-)render background
407 DrawRecordsBackGround( );
408
409 // error check
410 if(iCurrentPage==-1)
411 return;
412
413
414 // current page is found, render from here
415 DrawRecordsText( );
416 }
417
418
DrawRecordsBackGround(void)419 static void DrawRecordsBackGround(void)
420 {
421 // proceudre will draw the background for the list of financial records
422 INT32 iCounter;
423
424 // now the columns
425 for (iCounter = 6; iCounter < 35; iCounter++)
426 {
427 BltVideoObject(FRAME_BUFFER, guiLISTCOLUMNS, 0, TOP_X + 10, TOP_Y + 18 + iCounter * BLOCK_HEIGHT + 1);
428 }
429
430 // the divisorLines
431 BltVideoObject(FRAME_BUFFER, guiLONGLINE, 0, TOP_X + 10, TOP_Y + 17 + 6 * BLOCK_HEIGHT);
432 BltVideoObject(FRAME_BUFFER, guiLONGLINE, 0, TOP_X + 10, TOP_Y + 19 + 6 * BLOCK_HEIGHT);
433 BltVideoObject(FRAME_BUFFER, guiLONGLINE, 0, TOP_X + 10, TOP_Y + 19 + iCounter * BLOCK_HEIGHT);
434
435 // the header text
436 DrawRecordsColumnHeadersText( );
437 }
438
439
DrawRecordsColumnHeadersText(void)440 static void DrawRecordsColumnHeadersText(void)
441 {
442 // write the headers text for each column
443 SetFontAttributes(FINANCE_TEXT_FONT, FONT_BLACK, NO_SHADOW);
444
445 INT16 usX;
446 INT16 usY;
447
448 // the date header
449 FindFontCenterCoordinates(RECORD_DATE_X,0,RECORD_DATE_WIDTH,0, pFinanceHeaders[0], FINANCE_TEXT_FONT,&usX, &usY);
450 MPrint(usX, RECORD_HEADER_Y, pFinanceHeaders[0]);
451
452 // debit header
453 FindFontCenterCoordinates(RECORD_DEBIT_X,0,RECORD_DEBIT_WIDTH,0, pFinanceHeaders[1], FINANCE_TEXT_FONT,&usX, &usY);
454 MPrint(usX, RECORD_HEADER_Y, pFinanceHeaders[1]);
455
456 // credit header
457 FindFontCenterCoordinates(RECORD_CREDIT_X,0,RECORD_CREDIT_WIDTH,0, pFinanceHeaders[2], FINANCE_TEXT_FONT,&usX, &usY);
458 MPrint(usX, RECORD_HEADER_Y, pFinanceHeaders[2]);
459
460 // balance header
461 FindFontCenterCoordinates(RECORD_BALANCE_X,0,RECORD_BALANCE_WIDTH,0, pFinanceHeaders[4], FINANCE_TEXT_FONT,&usX, &usY);
462 MPrint(usX, RECORD_HEADER_Y, pFinanceHeaders[4]);
463
464 // transaction header
465 FindFontCenterCoordinates(RECORD_TRANSACTION_X,0,RECORD_TRANSACTION_WIDTH,0, pFinanceHeaders[3], FINANCE_TEXT_FONT,&usX, &usY);
466 MPrint(usX, RECORD_HEADER_Y, pFinanceHeaders[3]);
467
468 SetFontShadow(DEFAULT_SHADOW);
469 }
470
471
DrawStringCentered(INT32 x,INT32 y,INT32 w,const ST::string & str)472 static void DrawStringCentered(INT32 x, INT32 y, INT32 w, const ST::string& str)
473 {
474 INT16 sx;
475 INT16 sy;
476 FindFontCenterCoordinates(x, 0, w, 0, str, FINANCE_TEXT_FONT, &sx, &sy);
477 MPrint(sx, y, str);
478 }
479
480
481 static ST::string ProcessTransactionString(const FinanceUnit* pFinance);
482
483
484 // draws the text of the records
DrawRecordsText(void)485 static void DrawRecordsText(void)
486 {
487 SetFont(FINANCE_TEXT_FONT);
488 SetFontBackground(FONT_BLACK);
489 SetFontShadow(NO_SHADOW);
490
491 const FinanceUnit* fu = pFinanceListHead;
492 for (INT32 i = 0; i < NUM_RECORDS_PER_PAGE && fu != NULL; ++i, fu = fu->Next)
493 {
494 const INT32 y = 12 + RECORD_Y + i * (GetFontHeight(FINANCE_TEXT_FONT) + 6);
495
496 SetFontForeground(FONT_BLACK);
497
498 // get and write the date
499 DrawStringCentered(RECORD_DATE_X, y, RECORD_DATE_WIDTH, ST::format("{}", fu->uiDate / (24 * 60)));
500
501 // get and write debit/credit
502 if (fu->iAmount >= 0)
503 {
504 // increase in asset - debit
505 DrawStringCentered(RECORD_DEBIT_X, y, RECORD_DEBIT_WIDTH, SPrintMoney(fu->iAmount));
506 }
507 else
508 {
509 // decrease in asset - credit
510 SetFontForeground(FONT_RED);
511 DrawStringCentered(RECORD_CREDIT_X, y, RECORD_CREDIT_WIDTH, SPrintMoney(-fu->iAmount));
512 }
513
514 // the balance to this point
515 INT32 balance = fu->iBalanceToDate;
516 if (balance >= 0)
517 {
518 SetFontForeground(FONT_BLACK);
519 }
520 else
521 {
522 SetFontForeground(FONT_RED);
523 balance = -balance;
524 }
525 DrawStringCentered(RECORD_BALANCE_X, y, RECORD_BALANCE_WIDTH, SPrintMoney(balance));
526
527 // transaction string
528 DrawStringCentered(RECORD_TRANSACTION_X, y, RECORD_TRANSACTION_WIDTH, ProcessTransactionString(fu));
529 }
530 }
531
532
DrawFinanceTitleText(void)533 static void DrawFinanceTitleText(void)
534 {
535 // draw the pages title
536 SetFontAttributes(FINANCE_HEADER_FONT, FONT_WHITE);
537 MPrint(TITLE_X, TITLE_Y, pFinanceTitle);
538 }
539
540
541 static INT32 GetPreviousDaysIncome(void);
542 static INT32 GetTodaysBalance(void);
543 static INT32 GetTodaysDaysIncome(void);
544 static INT32 GetTodaysOtherDeposits(void);
545 static INT32 GetYesterdaysOtherDeposits(void);
546 static ST::string SPrintMoneyNoDollarOnZero(INT32 Amount);
547
548
DrawSummaryText(void)549 static void DrawSummaryText(void)
550 {
551 INT16 usX, usY;
552 ST::string pString;
553 INT32 iBalance = 0;
554
555 SetFontAttributes(FINANCE_TEXT_FONT, FONT_BLACK, NO_SHADOW);
556
557 // draw summary text to the screen
558 MPrint(TEXT_X, YESTERDAYS_INCOME, pFinanceSummary[2]);
559 MPrint(TEXT_X, YESTERDAYS_OTHER, pFinanceSummary[3]);
560 MPrint(TEXT_X, YESTERDAYS_DEBITS, pFinanceSummary[4]);
561 MPrint(TEXT_X, YESTERDAYS_BALANCE, pFinanceSummary[5]);
562 MPrint(TEXT_X, TODAYS_INCOME, pFinanceSummary[6]);
563 MPrint(TEXT_X, TODAYS_OTHER, pFinanceSummary[7]);
564 MPrint(TEXT_X, TODAYS_DEBITS, pFinanceSummary[8]);
565 MPrint(TEXT_X, TODAYS_CURRENT_BALANCE, pFinanceSummary[9]);
566 MPrint(TEXT_X, TODAYS_CURRENT_FORCAST_INCOME, pFinanceSummary[10]);
567 MPrint(TEXT_X, TODAYS_CURRENT_FORCAST_BALANCE, pFinanceSummary[11]);
568
569 // draw the actual numbers
570
571
572
573 // yesterdays income
574 pString = SPrintMoneyNoDollarOnZero(GetPreviousDaysIncome());
575 FindFontRightCoordinates(STD_SCREEN_X, 0, 580, 0,pString,FINANCE_TEXT_FONT, &usX, &usY);
576 MPrint(usX, YESTERDAYS_INCOME, pString);
577
578 SetFontForeground( FONT_BLACK );
579
580 // yesterdays other
581 pString = SPrintMoneyNoDollarOnZero(GetYesterdaysOtherDeposits());
582 FindFontRightCoordinates(STD_SCREEN_X, 0, 580, 0,pString,FINANCE_TEXT_FONT, &usX, &usY);
583 MPrint(usX, YESTERDAYS_OTHER, pString);
584
585 SetFontForeground( FONT_RED );
586
587 // yesterdays debits
588 iBalance = GetYesterdaysDebits( );
589 if( iBalance < 0 )
590 {
591 SetFontForeground( FONT_RED );
592 iBalance *= -1;
593 }
594
595 pString = SPrintMoneyNoDollarOnZero(iBalance);
596 FindFontRightCoordinates(STD_SCREEN_X, 0, 580, 0,pString,FINANCE_TEXT_FONT, &usX, &usY);
597 MPrint(usX, YESTERDAYS_DEBITS, pString);
598
599 SetFontForeground( FONT_BLACK );
600
601 // yesterdays balance..ending balance..so todays balance then
602 iBalance = GetTodaysBalance( );
603
604 if( iBalance < 0 )
605 {
606 SetFontForeground( FONT_RED );
607 iBalance *= -1;
608 }
609
610 pString = SPrintMoneyNoDollarOnZero(iBalance);
611 FindFontRightCoordinates(STD_SCREEN_X, 0, 580, 0,pString,FINANCE_TEXT_FONT, &usX, &usY);
612 MPrint(usX, YESTERDAYS_BALANCE, pString);
613
614 SetFontForeground( FONT_BLACK );
615
616 // todays income
617 pString = SPrintMoneyNoDollarOnZero(GetTodaysDaysIncome());
618 FindFontRightCoordinates(STD_SCREEN_X, 0, 580, 0,pString,FINANCE_TEXT_FONT, &usX, &usY);
619 MPrint(usX, TODAYS_INCOME, pString);
620
621 SetFontForeground( FONT_BLACK );
622
623 // todays other
624 pString = SPrintMoneyNoDollarOnZero(GetTodaysOtherDeposits());
625 FindFontRightCoordinates(STD_SCREEN_X, 0, 580, 0,pString,FINANCE_TEXT_FONT, &usX, &usY);
626 MPrint(usX, TODAYS_OTHER, pString);
627
628 SetFontForeground( FONT_RED );
629
630 // todays debits
631 iBalance = GetTodaysDebits( );
632
633 // absolute value
634 if( iBalance < 0 )
635 {
636 iBalance *= ( -1 );
637 }
638
639 pString = SPrintMoneyNoDollarOnZero(iBalance);
640 FindFontRightCoordinates(STD_SCREEN_X, 0, 580, 0,pString,FINANCE_TEXT_FONT, &usX, &usY);
641 MPrint(usX, TODAYS_DEBITS, pString);
642
643 SetFontForeground( FONT_BLACK );
644
645 // todays current balance
646 iBalance = GetCurrentBalance( );
647 if( iBalance < 0 )
648 {
649 iBalance *= -1;
650 SetFontForeground( FONT_RED );
651 }
652
653 pString = SPrintMoneyNoDollarOnZero(iBalance);
654 FindFontRightCoordinates(STD_SCREEN_X, 0, 580, 0,pString,FINANCE_TEXT_FONT, &usX, &usY);
655 MPrint(usX, TODAYS_CURRENT_BALANCE, pString);
656
657 SetFontForeground( FONT_BLACK );
658
659 // todays forcast income
660 pString = SPrintMoneyNoDollarOnZero(GetProjectedTotalDailyIncome());
661 FindFontRightCoordinates(STD_SCREEN_X, 0, 580, 0,pString,FINANCE_TEXT_FONT, &usX, &usY);
662 MPrint(usX, TODAYS_CURRENT_FORCAST_INCOME, pString);
663
664 SetFontForeground( FONT_BLACK );
665
666
667 // todays forcast balance
668 iBalance = GetCurrentBalance( ) + GetProjectedTotalDailyIncome( );
669 if( iBalance < 0 )
670 {
671 iBalance *= -1;
672 SetFontForeground( FONT_RED );
673 }
674
675 pString = SPrintMoneyNoDollarOnZero(iBalance);
676 FindFontRightCoordinates(STD_SCREEN_X, 0, 580, 0,pString,FINANCE_TEXT_FONT, &usX, &usY);
677 MPrint(usX, TODAYS_CURRENT_FORCAST_BALANCE, pString);
678
679 SetFontForeground( FONT_BLACK );
680
681 // reset the shadow
682 SetFontShadow(DEFAULT_SHADOW);
683 }
684
685
ClearFinanceList(void)686 static void ClearFinanceList(void)
687 {
688 // remove each element from list of transactions
689 FinanceUnit* pFinanceList = pFinanceListHead;
690 FinanceUnit* pFinanceNode = pFinanceList;
691
692 // while there are elements in the list left, delete them
693 while( pFinanceList )
694 {
695 // set node to list head
696 pFinanceNode=pFinanceList;
697
698 // set list head to next node
699 pFinanceList=pFinanceList->Next;
700
701 // delete current node
702 delete pFinanceNode;
703 }
704 pFinanceListHead = NULL;
705 }
706
707
ProcessAndEnterAFinacialRecord(const UINT8 ubCode,const UINT32 uiDate,const INT32 iAmount,const UINT8 ubSecondCode,const INT32 iBalanceToDate)708 static void ProcessAndEnterAFinacialRecord(const UINT8 ubCode, const UINT32 uiDate, const INT32 iAmount, const UINT8 ubSecondCode, const INT32 iBalanceToDate)
709 {
710 FinanceUnit* const fu = new FinanceUnit{};
711 fu->Next = NULL;
712 fu->ubCode = ubCode;
713 fu->ubSecondCode = ubSecondCode;
714 fu->uiDate = uiDate;
715 fu->iAmount = iAmount;
716 fu->iBalanceToDate = iBalanceToDate;
717
718 // Append to end of list
719 FinanceUnit** i = &pFinanceListHead;
720 while (*i != NULL) i = &(*i)->Next;
721 *i = fu;
722 }
723
724
725 static void LoadPreviousPage(void);
726 static void LoadNextPage(void);
727
728
ScrollRegionCallback(MOUSE_REGION * const,INT32 const reason)729 static void ScrollRegionCallback(MOUSE_REGION* const, INT32 const reason)
730 {
731 if (reason & MSYS_CALLBACK_REASON_WHEEL_UP)
732 {
733 LoadPreviousPage();
734 }
735 else if (reason & MSYS_CALLBACK_REASON_WHEEL_DOWN)
736 {
737 LoadNextPage();
738 }
739 }
740
741
BtnFinanceDisplayPrevPageCallBack(GUI_BUTTON * const,INT32 const reason)742 static void BtnFinanceDisplayPrevPageCallBack(GUI_BUTTON* const, INT32 const reason)
743 {
744 if (reason & MSYS_CALLBACK_REASON_LBUTTON_UP)
745 {
746 LoadPreviousPage();
747 }
748 }
749
750
BtnFinanceDisplayNextPageCallBack(GUI_BUTTON * const,INT32 const reason)751 static void BtnFinanceDisplayNextPageCallBack(GUI_BUTTON* const, INT32 const reason)
752 {
753 if (reason & MSYS_CALLBACK_REASON_LBUTTON_UP)
754 {
755 LoadNextPage();
756 }
757 }
758
759
BtnFinanceFirstPageCallBack(GUI_BUTTON * const,INT32 const reason)760 static void BtnFinanceFirstPageCallBack(GUI_BUTTON* const, INT32 const reason)
761 {
762 if (reason & MSYS_CALLBACK_REASON_LBUTTON_UP)
763 {
764 LoadInRecords(0);
765 }
766 }
767
768
BtnFinanceLastPageCallBack(GUI_BUTTON * const,INT32 const reason)769 static void BtnFinanceLastPageCallBack(GUI_BUTTON* const, INT32 const reason)
770 {
771 if (reason & MSYS_CALLBACK_REASON_LBUTTON_UP)
772 {
773 LoadInRecords(guiLastPageInRecordsList + 1);
774 }
775 }
776
777
MakeButton(size_t const idx,BUTTON_PICS * const img,INT16 const x,GUI_CALLBACK const callback)778 static void MakeButton(size_t const idx, BUTTON_PICS* const img, INT16 const x, GUI_CALLBACK const callback)
779 {
780 giFinanceButtonImage[idx] = img;
781 GUIButtonRef const btn = QuickCreateButton(img, x, BTN_Y, MSYS_PRIORITY_HIGHEST - 1, callback);
782 giFinanceButton[idx] = btn;
783 btn->SetCursor(CURSOR_LAPTOP_SCREEN);
784 }
785
786
CreateFinanceButtons(void)787 static void CreateFinanceButtons(void)
788 {
789 BUTTON_PICS* const img = LoadButtonImage(LAPTOPDIR "/arrows.sti", 0, 1);
790 MakeButton(PREV_PAGE_BUTTON, img, PREV_BTN_X, BtnFinanceDisplayPrevPageCallBack);
791 MakeButton(NEXT_PAGE_BUTTON, UseLoadedButtonImage(img, 6, 7), NEXT_BTN_X, BtnFinanceDisplayNextPageCallBack);
792 MakeButton(FIRST_PAGE_BUTTON, UseLoadedButtonImage(img, 3, 4), FIRST_PAGE_X, BtnFinanceFirstPageCallBack);
793 MakeButton(LAST_PAGE_BUTTON, UseLoadedButtonImage(img, 9, 10), LAST_PAGE_X, BtnFinanceLastPageCallBack);
794
795 UINT16 const x = TOP_X + 8;
796 UINT16 const y = TOP_Y + 53;
797 UINT16 const w = 482;
798 UINT16 const h = 354;
799 MSYS_DefineRegion(&g_scroll_region, x, y, x + w, y + h, MSYS_PRIORITY_HIGH, MSYS_NO_CURSOR, MSYS_NO_CALLBACK, ScrollRegionCallback);
800 }
801
802
DestroyFinanceButtons(void)803 static void DestroyFinanceButtons(void)
804 {
805 MSYS_RemoveRegion(&g_scroll_region);
806 for (UINT32 i = 0; i != 4; ++i)
807 {
808 RemoveButton(giFinanceButton[i]);
809 UnloadButtonImage(giFinanceButtonImage[i]);
810 }
811 }
812
813
ProcessTransactionString(const FinanceUnit * f)814 static ST::string ProcessTransactionString(const FinanceUnit* f)
815 {
816 UINT8 code = f->ubCode;
817 switch (code)
818 {
819 case DEPOSIT_FROM_SILVER_MINE:
820 code = DEPOSIT_FROM_GOLD_MINE;
821 /* FALLTHROUGH */
822
823 case ACCRUED_INTEREST:
824 case ANONYMOUS_DEPOSIT:
825 case BOBBYR_PURCHASE:
826 case DEPOSIT_FROM_GOLD_MINE:
827 case IMP_PROFILE:
828 case PAY_SPECK_FOR_MERC:
829 case PURCHASED_FLOWERS:
830 case TRANSACTION_FEE:
831 return pTransactionText[code];
832
833 case CANCELLED_INSURANCE:
834 case EXTENDED_CONTRACT_BY_1_DAY:
835 case EXTENDED_CONTRACT_BY_1_WEEK:
836 case EXTENDED_CONTRACT_BY_2_WEEKS:
837 case EXTENDED_INSURANCE:
838 case FULL_MEDICAL_REFUND:
839 case HIRED_MERC:
840 case INSURANCE_PAYOUT:
841 case MEDICAL_DEPOSIT:
842 case MERC_DEPOSITED_MONEY_TO_PLAYER_ACCOUNT:
843 case NO_MEDICAL_REFUND:
844 case PARTIAL_MEDICAL_REFUND:
845 case PAYMENT_TO_NPC:
846 case PURCHASED_INSURANCE:
847 case PURCHASED_ITEM_FROM_DEALER:
848 case REDUCED_INSURANCE:
849 case TRANSFER_FUNDS_FROM_MERC:
850 case TRANSFER_FUNDS_TO_MERC:
851 return st_format_printf(pTransactionText[code], GetProfile(f->ubSecondCode).zNickname);
852
853 case TRAIN_TOWN_MILITIA:
854 {
855 const UINT8 ubSectorX = SECTORX(f->ubSecondCode);
856 const UINT8 ubSectorY = SECTORY(f->ubSecondCode);
857 return st_format_printf(pTransactionText[TRAIN_TOWN_MILITIA], GetSectorIDString(ubSectorX, ubSectorY, 0, TRUE));
858 }
859
860 default:
861 return ST::null;
862 }
863 }
864
865
DisplayFinancePageNumberAndDateRange(void)866 static void DisplayFinancePageNumberAndDateRange(void)
867 {
868 SetFontAttributes(FINANCE_TEXT_FONT, FONT_BLACK, NO_SHADOW);
869 MPrint(PAGE_NUMBER_X, PAGE_NUMBER_Y, ST::format("{} {} / {}", pFinanceHeaders[5], iCurrentPage + 1, guiLastPageInRecordsList + 2));
870 SetFontShadow(DEFAULT_SHADOW);
871 }
872
873
WriteBalanceToDisk(void)874 static void WriteBalanceToDisk(void)
875 {
876 // will write the current balance to disk
877 AutoSGPFile hFileHandle(GCM->openTempFileForWriting(NEWTMP_FINANCES_DATA_FILE, false));
878 FileWrite(hFileHandle, &LaptopSaveInfo.iCurrentBalance, sizeof(INT32));
879 }
880
881
GetBalanceFromDisk(void)882 static void GetBalanceFromDisk(void)
883 {
884 // will grab the current blanace from disk
885 // assuming file already openned
886 // this procedure will open and read in data to the finance list
887 AutoSGPFile f;
888 try
889 {
890 f = GCM->openTempFileForReading(NEWTMP_FINANCES_DATA_FILE);
891 }
892 catch (...)
893 {
894 LaptopSaveInfo.iCurrentBalance = 0;
895 return; /* XXX TODO0019 ignore */
896 }
897
898 // get balance from disk first
899 FileRead(f, &LaptopSaveInfo.iCurrentBalance, sizeof(INT32));
900 }
901
902
903 // will write the current finance to disk
AppendFinanceToEndOfFile(void)904 static void AppendFinanceToEndOfFile(void)
905 {
906 AutoSGPFile f(GCM->openTempFileForAppend(NEWTMP_FINANCES_DATA_FILE));
907
908 const FinanceUnit* const fu = pFinanceListHead;
909 BYTE data[FINANCE_RECORD_SIZE];
910 DataWriter d{data};
911 INJ_U8(d, fu->ubCode);
912 INJ_U8(d, fu->ubSecondCode);
913 INJ_U32(d, fu->uiDate);
914 INJ_I32(d, fu->iAmount);
915 INJ_I32(d, fu->iBalanceToDate);
916 Assert(d.getConsumed() == lengthof(data));
917
918 FileWrite(f, data, sizeof(data));
919 }
920
921
922 // Grabs the size of the file and interprets number of pages it will take up
SetLastPageInRecords(void)923 static void SetLastPageInRecords(void)
924 {
925 AutoSGPFile f(GCM->openTempFileForReading(NEWTMP_FINANCES_DATA_FILE));
926
927 const UINT32 size = FileGetSize(f);
928
929 if (size < FINANCE_HEADER_SIZE + FINANCE_RECORD_SIZE)
930 {
931 guiLastPageInRecordsList = 0;
932 return;
933 }
934
935 guiLastPageInRecordsList =
936 (size - FINANCE_HEADER_SIZE - FINANCE_RECORD_SIZE) /
937 (FINANCE_RECORD_SIZE * NUM_RECORDS_PER_PAGE);
938 }
939
940
LoadPreviousPage(void)941 static void LoadPreviousPage(void)
942 {
943 if (iCurrentPage == 0) return;
944 LoadInRecords(iCurrentPage - 1);
945 }
946
947
LoadNextPage(void)948 static void LoadNextPage(void)
949 {
950 if (static_cast<UINT32>(iCurrentPage) > guiLastPageInRecordsList) return;
951 LoadInRecords(iCurrentPage + 1);
952 }
953
954
955 // Loads in records belonging to page
LoadInRecords(UINT32 const page)956 static void LoadInRecords(UINT32 const page)
957 {
958 iCurrentPage = page;
959 fReDrawScreenFlag = TRUE;
960 SetFinanceButtonStates();
961 ClearFinanceList();
962 if (page == 0) return; // check if bad page
963
964 AutoSGPFile f(GCM->openTempFileForReading(NEWTMP_FINANCES_DATA_FILE));
965
966 UINT32 const size = FileGetSize(f);
967 if (size < FINANCE_HEADER_SIZE) return;
968
969 UINT32 records = (size - FINANCE_HEADER_SIZE) / FINANCE_RECORD_SIZE;
970 UINT32 const skip_records = NUM_RECORDS_PER_PAGE * (page - 1);
971 if (records <= skip_records) return;
972
973 records -= skip_records;
974 FileSeek(f, FINANCE_HEADER_SIZE + FINANCE_RECORD_SIZE * skip_records, FILE_SEEK_FROM_START);
975
976 if (records > NUM_RECORDS_PER_PAGE) records = NUM_RECORDS_PER_PAGE;
977 for (; records > 0; --records)
978 {
979 BYTE data[FINANCE_RECORD_SIZE];
980 FileRead(f, data, sizeof(data));
981
982 UINT8 code;
983 UINT8 second_code;
984 UINT32 date;
985 INT32 amount;
986 INT32 balance_to_date;
987 DataReader d{data};
988 EXTR_U8(d, code);
989 EXTR_U8(d, second_code);
990 EXTR_U32(d, date);
991 EXTR_I32(d, amount);
992 EXTR_I32(d, balance_to_date);
993 Assert(d.getConsumed() == lengthof(data));
994
995 ProcessAndEnterAFinacialRecord(code, date, amount, second_code, balance_to_date);
996 }
997 }
998
999
InternalSPrintMoney(bool dollar,INT32 amount)1000 static ST::string InternalSPrintMoney(bool dollar, INT32 amount)
1001 {
1002 ST::utf32_buffer codepoints = ST::format("{}", amount).to_utf32();
1003 size_t start = amount < 0 ? 1 : 0;
1004 size_t end = codepoints.size();
1005 ST::string money;
1006 if (dollar)
1007 {
1008 money += U'$';
1009 }
1010 for (size_t i = 0; i < end; i++)
1011 {
1012 if (i > start && (end - i) % 3 == 0)
1013 {
1014 money += U',';
1015 }
1016 money += codepoints[i];
1017 }
1018 return money;
1019 }
1020
1021
SPrintMoney(INT32 amount)1022 ST::string SPrintMoney(INT32 amount)
1023 {
1024 return InternalSPrintMoney(true, amount);
1025 }
1026
1027
SPrintMoneyNoDollarOnZero(INT32 amount)1028 static ST::string SPrintMoneyNoDollarOnZero(INT32 amount)
1029 {
1030 return InternalSPrintMoney(amount != 0, amount);
1031 }
1032
1033
1034 // find out what today is, then go back 2 days, get balance for that day
GetPreviousDaysBalance(void)1035 static INT32 GetPreviousDaysBalance(void)
1036 {
1037 const UINT32 date_in_minutes = GetWorldTotalMin() - 60 * 24;
1038 const UINT32 date_in_days = date_in_minutes / (24 * 60);
1039
1040 if (date_in_days < 2) return 0;
1041
1042 AutoSGPFile f(GCM->openTempFileForReading(NEWTMP_FINANCES_DATA_FILE));
1043
1044 INT32 balance = 0;
1045 // start at the end, move back until Date / 24 * 60 on the record equals date_in_days - 2
1046 // loop, make sure we don't pass beginning of file, if so, we have an error, and check for condifition above
1047 for (UINT32 pos = FileGetSize(f); pos >= FINANCE_HEADER_SIZE + RECORD_SIZE;)
1048 {
1049 FileSeek(f, pos -= RECORD_SIZE, FILE_SEEK_FROM_START);
1050
1051 BYTE data[RECORD_SIZE];
1052 FileRead(f, data, sizeof(data));
1053
1054 UINT32 date;
1055 INT32 balance_to_date;
1056 DataReader d{data};
1057 EXTR_SKIP(d, 2);
1058 EXTR_U32(d, date);
1059 EXTR_SKIP(d, 4);
1060 EXTR_I32(d, balance_to_date);
1061 Assert(d.getConsumed() == lengthof(data));
1062
1063 // check to see if we are far enough
1064 if (date / (24 * 60) == date_in_days - 2)
1065 {
1066 balance = balance_to_date;
1067 break;
1068 }
1069
1070 // there are no entries for the previous day
1071 if (date / (24 * 60) < date_in_days - 2) break;
1072 }
1073
1074 return balance;
1075 }
1076
1077
GetTodaysBalance(void)1078 static INT32 GetTodaysBalance(void)
1079 {
1080 const UINT32 date_in_minutes = GetWorldTotalMin();
1081 const UINT32 date_in_days = date_in_minutes / (24 * 60);
1082
1083 AutoSGPFile f(GCM->openTempFileForReading(NEWTMP_FINANCES_DATA_FILE));
1084
1085 INT32 balance = 0;
1086 // loop, make sure we don't pass beginning of file, if so, we have an error, and check for condifition above
1087 for (UINT32 pos = FileGetSize(f); pos >= FINANCE_HEADER_SIZE + RECORD_SIZE;)
1088 {
1089 FileSeek(f, pos -= RECORD_SIZE, FILE_SEEK_FROM_START);
1090
1091 BYTE data[RECORD_SIZE];
1092 FileRead(f, data, sizeof(data));
1093
1094 UINT32 date;
1095 INT32 balance_to_date;
1096 DataReader d{data};
1097 EXTR_SKIP(d, 2);
1098 EXTR_U32(d, date);
1099 EXTR_SKIP(d, 4);
1100 EXTR_I32(d, balance_to_date);
1101 Assert(d.getConsumed() == lengthof(data));
1102
1103 // check to see if we are far enough
1104 if (date / (24 * 60) == date_in_days - 1)
1105 {
1106 balance = balance_to_date;
1107 break;
1108 }
1109 }
1110
1111 return balance;
1112 }
1113
1114
1115 /* will return the income from the previous day, which is todays starting
1116 * balance - yesterdays starting balance */
GetPreviousDaysIncome(void)1117 static INT32 GetPreviousDaysIncome(void)
1118 {
1119 const UINT32 date_in_minutes = GetWorldTotalMin();
1120 const UINT32 date_in_days = date_in_minutes / (24 * 60);
1121
1122 AutoSGPFile f(GCM->openTempFileForReading(NEWTMP_FINANCES_DATA_FILE));
1123
1124 INT32 iTotalPreviousIncome = 0;
1125 // start at the end, move back until Date / 24 * 60 on the record is = date_in_days - 2
1126 // loop, make sure we don't pass beginning of file, if so, we have an error, and check for condifition above
1127 BOOLEAN fOkToIncrement = FALSE;
1128 for (UINT32 pos = FileGetSize(f); pos >= FINANCE_HEADER_SIZE + RECORD_SIZE;)
1129 {
1130 FileSeek(f, pos -= RECORD_SIZE, FILE_SEEK_FROM_START);
1131
1132 BYTE data[RECORD_SIZE];
1133 FileRead(f, data, sizeof(data));
1134
1135 UINT8 code;
1136 UINT32 date;
1137 INT32 amount;
1138 DataReader d{data};
1139 EXTR_U8(d, code);
1140 EXTR_SKIP(d, 1);
1141 EXTR_U32(d, date);
1142 EXTR_I32(d, amount);
1143 EXTR_SKIP(d, 4);
1144 Assert(d.getConsumed() == lengthof(data));
1145
1146 // now ok to increment amount
1147 if (date / (24 * 60) == date_in_days - 1) fOkToIncrement = TRUE;
1148
1149 if (fOkToIncrement && (code == DEPOSIT_FROM_GOLD_MINE || code == DEPOSIT_FROM_SILVER_MINE))
1150 {
1151 // increment total
1152 iTotalPreviousIncome += amount;
1153 }
1154
1155 // check to see if we are far enough
1156 if (date / (24 * 60) <= date_in_days - 2) break;
1157 }
1158
1159 return iTotalPreviousIncome;
1160 }
1161
1162
GetTodaysDaysIncome(void)1163 static INT32 GetTodaysDaysIncome(void)
1164 {
1165 const UINT32 date_in_minutes = GetWorldTotalMin();
1166 const UINT32 date_in_days = date_in_minutes / (24 * 60);
1167
1168 AutoSGPFile f(GCM->openTempFileForReading(NEWTMP_FINANCES_DATA_FILE));
1169
1170 INT32 iTotalIncome = 0;
1171 // loop, make sure we don't pass beginning of file, if so, we have an error, and check for condifition above
1172 BOOLEAN fOkToIncrement = FALSE;
1173 for (UINT32 pos = FileGetSize(f); pos >= FINANCE_HEADER_SIZE + RECORD_SIZE;)
1174 {
1175 FileSeek(f, pos -= RECORD_SIZE, FILE_SEEK_FROM_START);
1176
1177 BYTE data[RECORD_SIZE];
1178 FileRead(f, data, sizeof(data));
1179
1180 UINT8 code;
1181 UINT32 date;
1182 INT32 amount;
1183 DataReader d{data};
1184 EXTR_U8(d, code);
1185 EXTR_SKIP(d, 1);
1186 EXTR_U32(d, date);
1187 EXTR_I32(d, amount);
1188 EXTR_SKIP(d, 4);
1189 Assert(d.getConsumed() == lengthof(data));
1190
1191 // now ok to increment amount
1192 if (date / (24 * 60) > date_in_days - 1) fOkToIncrement = TRUE;
1193
1194 if (fOkToIncrement && (code == DEPOSIT_FROM_GOLD_MINE || code == DEPOSIT_FROM_SILVER_MINE))
1195 {
1196 // increment total
1197 iTotalIncome += amount;
1198 fOkToIncrement = FALSE;
1199 }
1200
1201 // check to see if we are far enough
1202 if (date / (24 * 60) == date_in_days - 1) break;
1203 }
1204
1205 return iTotalIncome;
1206 }
1207
1208
SetFinanceButtonStates(void)1209 static void SetFinanceButtonStates(void)
1210 {
1211 // this function will look at what page we are viewing, enable and disable buttons as needed
1212
1213 bool const has_prev = iCurrentPage != 0;
1214 EnableButton(giFinanceButton[PREV_PAGE_BUTTON], has_prev);
1215 EnableButton(giFinanceButton[FIRST_PAGE_BUTTON], has_prev);
1216
1217 bool const has_next = iCurrentPage <= static_cast<INT32>(guiLastPageInRecordsList);
1218 EnableButton(giFinanceButton[NEXT_PAGE_BUTTON], has_next);
1219 EnableButton(giFinanceButton[LAST_PAGE_BUTTON], has_next);
1220 }
1221
1222
1223 // grab todays other deposits
GetTodaysOtherDeposits(void)1224 static INT32 GetTodaysOtherDeposits(void)
1225 {
1226 const UINT32 date_in_minutes = GetWorldTotalMin();
1227 const UINT32 date_in_days = date_in_minutes / (24 * 60);
1228
1229 AutoSGPFile f(GCM->openTempFileForReading(NEWTMP_FINANCES_DATA_FILE));
1230
1231 INT32 iTotalIncome = 0;
1232 // loop, make sure we don't pass beginning of file, if so, we have an error, and check for condifition above
1233 BOOLEAN fOkToIncrement = FALSE;
1234 for (UINT32 pos = FileGetSize(f); pos >= FINANCE_HEADER_SIZE + RECORD_SIZE;)
1235 {
1236 FileSeek(f, pos -= RECORD_SIZE, FILE_SEEK_FROM_START);
1237
1238 BYTE data[RECORD_SIZE];
1239 FileRead(f, data, sizeof(data));
1240
1241 UINT8 code;
1242 UINT32 date;
1243 INT32 amount;
1244 DataReader d{data};
1245 EXTR_U8(d, code);
1246 EXTR_SKIP(d, 1);
1247 EXTR_U32(d, date);
1248 EXTR_I32(d, amount);
1249 EXTR_SKIP(d, 4);
1250 Assert(d.getConsumed() == lengthof(data));
1251
1252 // now ok to increment amount
1253 if (date / (24 * 60) > date_in_days - 1) fOkToIncrement = TRUE;
1254
1255 if (fOkToIncrement &&
1256 (code != DEPOSIT_FROM_GOLD_MINE && code != DEPOSIT_FROM_SILVER_MINE) &&
1257 amount > 0)
1258 {
1259 // increment total
1260 iTotalIncome += amount;
1261 fOkToIncrement = FALSE;
1262 }
1263
1264 // check to see if we are far enough
1265 if (date / (24 * 60) == date_in_days - 1) break;
1266 }
1267
1268 return iTotalIncome;
1269 }
1270
1271
GetYesterdaysOtherDeposits(void)1272 static INT32 GetYesterdaysOtherDeposits(void)
1273 {
1274 const UINT32 iDateInMinutes = GetWorldTotalMin();
1275 const UINT32 date_in_days = iDateInMinutes / (24 * 60);
1276
1277 AutoSGPFile f(GCM->openTempFileForReading(NEWTMP_FINANCES_DATA_FILE));
1278
1279 INT32 iTotalPreviousIncome = 0;
1280 // start at the end, move back until Date / 24 * 60 on the record is = date_in_days - 2
1281 // loop, make sure we don't pass beginning of file, if so, we have an error, and check for condifition above
1282 BOOLEAN fOkToIncrement = FALSE;
1283 for (UINT32 pos = FileGetSize(f); pos >= FINANCE_HEADER_SIZE + RECORD_SIZE;)
1284 {
1285 FileSeek(f, pos -= RECORD_SIZE, FILE_SEEK_FROM_START);
1286
1287 BYTE data[RECORD_SIZE];
1288 FileRead(f, data, sizeof(data));
1289
1290 UINT8 code;
1291 UINT32 date;
1292 INT32 amount;
1293 DataReader d{data};
1294 EXTR_U8(d, code);
1295 EXTR_SKIP(d, 1);
1296 EXTR_U32(d, date);
1297 EXTR_I32(d, amount);
1298 EXTR_SKIP(d, 4);
1299 Assert(d.getConsumed() == lengthof(data));
1300
1301 // now ok to increment amount
1302 if (date / (24 * 60) == date_in_days - 1) fOkToIncrement = TRUE;
1303
1304 if (fOkToIncrement &&
1305 (code != DEPOSIT_FROM_GOLD_MINE && code != DEPOSIT_FROM_SILVER_MINE) &&
1306 amount > 0)
1307 {
1308 // increment total
1309 iTotalPreviousIncome += amount;
1310 }
1311
1312 // check to see if we are far enough
1313 if (date / (24 * 60) <= date_in_days - 2) break;
1314 }
1315
1316 return iTotalPreviousIncome;
1317 }
1318
1319
GetTodaysDebits(void)1320 static INT32 GetTodaysDebits(void)
1321 {
1322 // return the expenses for today
1323
1324 // currentbalance - todays balance - Todays income - other deposits
1325
1326 return( GetCurrentBalance( ) - GetTodaysBalance( ) - GetTodaysDaysIncome( ) - GetTodaysOtherDeposits( ) );
1327 }
1328
1329
GetYesterdaysDebits(void)1330 static INT32 GetYesterdaysDebits(void)
1331 {
1332 // return the expenses for yesterday
1333
1334 return( GetTodaysBalance( ) - GetPreviousDaysBalance( ) - GetPreviousDaysIncome( ) - GetYesterdaysOtherDeposits( ) );
1335 }
1336