System 7 app boilerplate

Needs refinement/completion.

Written in C, can be compiled with MPW. Requires Color QuickDraw.

#include <Types.h>
#include <Memory.h>
#include <Quickdraw.h>
#include <Fonts.h>
#include <Events.h>
#include <Menus.h>
#include <Windows.h>
#include <TextEdit.h>
#include <Dialogs.h>
#include <Sound.h>
#include <ToolUtils.h>
#include <Processes.h>

void main(void);

// utility functions
Boolean IsColorQuickDrawAvailable(void);
Boolean IsSystem7Available(void);
Boolean TrapAvailable(short trap);
TrapType GetTrapType(short trap);
short GetNumToolboxTraps(void);
void PrintDebug(Str255 s);

// lifecycle
void Initialize(void);
void EventLoop(void);
void CleanUp(void); 

// event handlers
void HandleActivate(WindowPtr window, Boolean isActive);
void HandleIdle(EventRecord *event);
void HandleEvent(EventRecord *event);
void HandleMenuCommand(EventRecord *event);
void HandleUpdate();
void HandleMouseDown(EventRecord *event);
Boolean HandleCloseWindow(WindowPtr window);

// globals
QDGlobals qd;
RgnHandle global_cursorRegion;
WindowPtr global_window;
Rect global_rect;
Rect global_dragRect;
Boolean global_isQuitting;

void main(void) {
	Initialize();
	
	EventLoop();
	
	CleanUp();
	
	ExitToShell();
}

void Initialize(void) {
	global_isQuitting = false;
	
	if (!IsColorQuickDrawAvailable()) {
		SysBeep(50);
		global_isQuitting = true;
	} else {
		InitGraf(&qd.thePort);
		InitFonts();
		InitWindows();
		InitMenus();
		TEInit();
		InitDialogs(nil);
		InitCursor();
	
		SetRect(&global_rect, 100, 100, 640, 480);
		SetRect(&global_dragRect, 0, 0, 32767, 32767); // is there a proper way to handle this?
	
		// opens a color window
		global_window = NewCWindow(nil, &global_rect, "\pHello World", true, noGrowDocProc, (WindowPtr) -1, true, 0);
		SetPort(global_window);
	
		// SetUpMenus();
	}
}

void CleanUp(void) {
	if (!!global_window) {
		DisposeWindow(global_window);
	}
}

void EventLoop(void) {
	Boolean haveEvent;
	EventRecord event;

	while(!global_isQuitting) {
		// global_isQuitting = Button();
		
		// this should handle yielding to the os and other processes for multitasking...
		// but it doesnt seem to be working properly? (apps underneath do not redraw/update)
		haveEvent = WaitNextEvent(everyEvent, &event, 100, global_cursorRegion);
		
		if (haveEvent) {
			HandleEvent(&event);
		} else {
		  HandleIdle(&event);
		}
	}
}

void HandleEvent(EventRecord *event) {
  switch(event->what) {
		case updateEvt:
			if ((WindowPtr) event->message == global_window) {
				HandleUpdate();
			}
			break;
		case mouseDown:
			HandleMouseDown(event);
			break;
		case activateEvt:
			//HandleActivate((WindowPtr) event->message, (event->modifiers & activeFlag) != 0);
			break;
	}
}

void HandleIdle(EventRecord *event) {
  // TODO
}

void HandleUpdate(void) {
	BeginUpdate(global_window);
	
	// Updating/drawing goes here

	EndUpdate(global_window);
}

void HandleMouseDown(EventRecord *event) {
  WindowPtr clickWnd;
	int clickLoc = FindWindow(event->where, &clickWnd);
	
	// TODO: check if all of these are actually necessary in System 7+
	switch(clickLoc) {
		case inSysWindow:
			SystemClick(event, clickWnd);
			break;
		case inContent:
		  if (clickWnd != FrontWindow()) {
				SelectWindow(clickWnd);
			}
			break;
		case inGoAway:
		  // handles clicking close window
			if (TrackGoAway(clickWnd, event->where)) {
				global_isQuitting = true;
			}
			break;
		case inDrag:
			// allows dragging the window within the given drag rect
			DragWindow(clickWnd, event->where, &global_dragRect);
			break;
	}
}

// dunno really what to do with this yet
void HandleActivate(WindowPtr window, Boolean isActive) {
	if (isActive) {
	
	} else {
	
	}
}

Boolean IsColorQuickDrawAvailable(void) {
	SysEnvRec sysenv;
	OSErr error = SysEnvirons(1, &sysenv);
	return !error && sysenv.hasColorQD;
}