/* Displays the current national debt, updated once a second.
   Public domain.  By Jamie Zawinski <jwz@lucid.com>.

   More mods by sonroc@nemesis.zycad.com [a/k/a twk@zycad.com] to include
   per-capita

   More mods by Perry Metzger, (pmetzger@shearson.com);
   eliminated silly cents field, uped the updates to
   once a second.

   Converted to a simple MicroSoft Windows program.
	By Mark C. DiVecchio, K3FWT,  619-549-9841
	Silogic Systems
	9888 Carroll Center Road   Suite 113
	San Diego, CA 92126
	markd@silogic.uucp.
	Using Borland C++ 3.1 and ObjectWindows.

 */
#define WIN31
/* The US Population, and its rate of increase, as of July 1, 1990        */
/* (in people/second) based on numbers from the CIA's World Factbook 1990 */
/*  .... thanks to tom@genie.slhs.udel.edu                                */
#define POP  		250410000.0		/* people */
#define POP_DELTA	0.0714151266		/* increase in people per second */

/* The US National Debt, and its rate of increase as of June 30, 1992      */
/* (in $/second) based on numbers from the 5 July 1992 Albuquerque Journal */
/*  .... thanks to Brooke King brooke@fuchsia.albuq.ingr.com               */
#define DEBT		3965170506502.395	/* in dollars */
#define DEBT_DELTA	14132.887		/* Dollars per second */

#include <static.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <owl.h>
#include <sys/types.h>

#include <time.h>
typedef double debt_t;
typedef double pop_t;


#define WM_INFO 0x600
#define WM_ABOUT 0x601

class TMyApp : public TApplication
{
public:
  TMyApp(LPSTR AName, HANDLE hInstance, HANDLE hPrevInstance,
    LPSTR lpCmdLine, int nCmdShow)
    : TApplication(AName, hInstance, hPrevInstance, lpCmdLine, nCmdShow) {};
  virtual void InitMainWindow();
};

_CLASSDEF(TMyWindow)
class TMyWindow : public TWindow
{
public:
  struct tm pop_tm;
  struct tm debt_tm;
  int running;
  char the_debt[64];
  DWORD oldextent;
  char     debtBuf[256], shareBuf[256];
  TMyWindow(PTWindowsObject AParent, LPSTR ATitle);
  ~TMyWindow();
  virtual BOOL CanClose();
  virtual void Paint(HDC DC, PAINTSTRUCT& PS);
  virtual debt_t national_debt_at (time_t );
  virtual pop_t national_pop_at (time_t );
  virtual void pretty_number(double, char *);
  virtual void construct_string (time_t , char *);
  virtual void timer ();
  virtual void MenuAbout ();
  virtual void MenuInfo ();
  virtual void GetWindowClass(WNDCLASS& WndClass)
  {
	TWindow::GetWindowClass( WndClass );
	WndClass.hIcon = LoadIcon( GetApplication()->hInstance,"ICON_4");
  }
  virtual void SetupWindow()
  {
      TWindow::SetupWindow();  // call base class setup

      sysmenu = GetSystemMenu(HWindow, NULL);

      InsertMenu(sysmenu, -1, MF_BYPOSITION | MF_SEPARATOR ,
	0, NULL);
      InsertMenu(sysmenu, -1, MF_BYPOSITION | MF_STRING | MF_ENABLED ,
	WM_FIRST + WM_INFO, "&Information");
      InsertMenu(sysmenu, -1, MF_BYPOSITION | MF_STRING | MF_ENABLED ,
	WM_FIRST + WM_ABOUT, "&About");

  }

  HMENU sysmenu;

  virtual void WMTimer(RTMessage Msg)
    = [WM_FIRST + WM_TIMER];
  virtual void WMRButtonDown(RTMessage Msg)
    = [WM_FIRST + WM_RBUTTONDOWN];
  virtual void WMSysCommand(RTMessage Msg)
    = [WM_SYSCOMMAND];
};

TMyWindow::TMyWindow(PTWindowsObject AParent, LPSTR ATitle)
  : TWindow(AParent, ATitle)
{

  Attr.X = 10;
  Attr.Y = 10;
  Attr.W = 440;
  Attr.H =  0;  // there seems to be a minimum height no matter what I do here

  oldextent = ((DWORD)Attr.H << 16) + (DWORD)Attr.W;

  Attr.Style &= ~WS_MAXIMIZEBOX;	// gets rid of Maximize icon
  Attr.Style &= ~WS_MINIMIZEBOX;	// gets rid of Minimize icon

running = FALSE;
// epoch date for population calculations
pop_tm.tm_sec = 0;
pop_tm.tm_min = 0;
pop_tm.tm_hour = 0;
pop_tm.tm_mday = 1;
pop_tm.tm_mon = 6;
pop_tm.tm_year = 90;
// epoch date for debt calculations
debt_tm.tm_sec = 0;
debt_tm.tm_min = 0;
debt_tm.tm_hour = 0;
debt_tm.tm_mday = 30;
debt_tm.tm_mon = 5;
debt_tm.tm_year = 92;

}

TMyWindow::~TMyWindow()
{
}

// redraw the screen
void TMyWindow::Paint(HDC, PAINTSTRUCT&)
{
// starts the timer running once a second
timer();
}

//
// Displays dialog boxes
//
void TMyWindow::MenuAbout()
{
GetApplication()->ExecDialog(new TDialog(this, "Alldone"));
}
void TMyWindow::MenuInfo()
{
GetApplication()->ExecDialog(new TDialog(this, "Info"));
}

BOOL TMyWindow::CanClose()
{
MenuAbout();
return TRUE;
}
// button press only in client area
void TMyWindow::WMRButtonDown(RTMessage)
{
MenuInfo();
}

// this routine replaces the DefWindowProc and is called
// with the WM_SYSCOMMAND message
//
void TMyWindow::WMSysCommand(RTMessage Msg)
{
switch (Msg.WParam) {
	// Debt Information Screen
	case WM_INFO:
        	MenuInfo();
        	break;

	// Debt About Screen (same as the one when program is terminated
	case WM_ABOUT:
        	MenuAbout();
		break;

	}
// pass all remaing messages to the default window procedure
DefWindowProc(HWindow, WM_SYSCOMMAND, Msg.WParam,
	Msg.LParam);
}

debt_t
TMyWindow:: national_debt_at (time_t now)
{
  time_t debt_date = mktime (&debt_tm);
  time_t seconds_since_then = now - debt_date;
  debt_t delta_since_then = DEBT_DELTA * seconds_since_then;
  return DEBT + delta_since_then;
}

pop_t
TMyWindow:: national_pop_at (time_t now)
{
  time_t pop_date = mktime (&pop_tm);
  time_t seconds_since_then = now - pop_date;
  pop_t delta_since_then = POP_DELTA * seconds_since_then;
  return POP + delta_since_then;
}

void
TMyWindow:: pretty_number(double n, char *buf)
{
	char tmpBuf[256], *cp, *bp;
	int  len, count, digits;

/*	sprintf(tmpBuf, "%.2lf", n);*/
	sprintf(tmpBuf, "%.0lf", n);
	len = strlen(tmpBuf);
	cp = tmpBuf + len - 1;
	bp = buf;

	/* copy over the cents and first 3 digits */
	/* *bp++ = *cp--; *bp++ = *cp--; *bp++ = *cp--; */
	*bp++ = *cp--; *bp++ = *cp--; *bp++ = *cp--;
	digits = 7;

	/* Now every three digits gets a comma; at 10 digits insert a line at the
		comma  */
	while (cp >= tmpBuf)
	{
		/* MODIFY NEWLINE IN LARGE NUMBERS HERE */
/*		if (digits > 10)
		{
			*bp++ = ' '; *bp++ = '\n'; digits=0;
		}*/
		*bp++ = ','; digits++;
		for (count = 0; count < 3 && cp >= tmpBuf; count++)
		{
			*bp++ = *cp--; digits++;
		}
	}
	*bp++ = '\0';
	strcpy(tmpBuf, buf);

	len = strlen(tmpBuf);
	for (count = 0; count < len; count++)
	{
		buf[(len-1) - count] = tmpBuf[count];
	}
	buf[len] = '\0';
}

void
TMyWindow:: construct_string (time_t now, char *outBuf)
{
  debt_t   debt = national_debt_at(now);
  pop_t    pop  = national_pop_at(now);

  pretty_number(debt, debtBuf);
  pretty_number(debt/pop,  shareBuf);
  sprintf(outBuf, " U.S. National Debt: $%s   Your Share: $%s", debtBuf, shareBuf);
  
}

void
TMyWindow:: timer ()
{
  DWORD extent;
  HANDLE context;
  time_t now = time((time_t *)0);
  construct_string (now, the_debt);
// Get String size in Pixels  and add in size of SYSTEM Icon
  context = GetWindowDC(HWindow);
  if (context != NULL)
	extent = GetTextExtent(context, the_debt, strlen(the_debt)) +
		GetSystemMetrics(SM_CXSIZE) * 2;
	else
	extent = ( 40L << 16 ) + 200;    // default in case of error
  ReleaseDC(HWindow, context);

  // Now set the window size if necessary
  if (oldextent != extent) {
 	 SetWindowPos(HWindow,1,
		10,10,
		(int) (extent & 0x0000FFFF),
		(int)(extent >> 16),
		SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
	oldextent = extent;	// save for later use
	}
  SetCaption(the_debt);

  if (running == TRUE) return;	// don't start timer if its already running
  SetTimer(HWindow, 99, 1000, NULL);  // one second
  running = TRUE;
}

void TMyWindow::WMTimer(RTMessage)
{
running = FALSE;
timer();
}

void TMyApp::InitMainWindow()
{
  MainWindow = new TMyWindow(NULL, Name);
}

int PASCAL WinMain(HANDLE hInstance, HANDLE hPrevInstance,
  LPSTR lpCmdLine, int nCmdShow)
{
  TMyApp MyApp("Debt", hInstance, hPrevInstance,
	       lpCmdLine, nCmdShow);
  MyApp.Run();
  return MyApp.Status;
}
