#include "Settings.h" #include /* Display Manager code copied from Apple's DisplayVideo example */ /* I HATE THE DISPLAY MANAGER!! */ struct DepthInfo { VDSwitchInfoRec depthSwitchInfo; // This is the switch mode to choose this timing/depth VPBlock depthVPBlock; // VPBlock (including size, depth and format) }; typedef struct DepthInfo DepthInfo; struct ListIteratorDataRec { unsigned long displayModeFlags; VDSwitchInfoRec displayModeSwitchInfo; VDResolutionInfoRec displayModeResolutionInfo; VDTimingInfoRec displayModeTimingInfo; // Contains timing flags and such unsigned long depthBlockCount; // How many depths available for a particular timing DepthInfo * depthBlocks; // Array of DepthInfo Str255 displayModeName; // name of the timing mode }; typedef struct ListIteratorDataRec ListIteratorDataRec; static pascal void ModeListIterator(void * userData, DMListIndexType itemIndex, DMDisplayModeListEntryPtr displaymodeInfo) { #pragma unused(itemIndex) unsigned long depthCount; short iCount; ListIteratorDataRec * myIterateData = (ListIteratorDataRec *) userData; DepthInfo * myDepthInfo; myIterateData->displayModeFlags = displaymodeInfo->displayModeFlags; // Info on this particular display mode myIterateData->displayModeSwitchInfo = *displaymodeInfo->displayModeSwitchInfo; // not needed - depth info has this per depth myIterateData->displayModeResolutionInfo = *displaymodeInfo->displayModeResolutionInfo; // refresh rate, pixels/lines at max depth myIterateData->displayModeTimingInfo = *displaymodeInfo->displayModeTimingInfo; // to get the flags on timing mode myIterateData->displayModeName[0] = sprintf((char *) &myIterateData->displayModeName[1], "%.*s", displaymodeInfo->displayModeName[0], &displaymodeInfo->displayModeName[1]); // the name of the mode // now get the DMDepthInfo into memory we own depthCount = displaymodeInfo->displayModeDepthBlockInfo->depthBlockCount; myDepthInfo = (DepthInfo *) NewPtrClear(depthCount * sizeof(DepthInfo)); // set the info for the caller myIterateData->depthBlockCount = depthCount; myIterateData->depthBlocks = myDepthInfo; // and fill out all the entries for (iCount = 0; iCount < depthCount; iCount++) { myDepthInfo[iCount].depthSwitchInfo = *displaymodeInfo->displayModeDepthBlockInfo->depthVPBlock[iCount].depthSwitchInfo; myDepthInfo[iCount].depthVPBlock = *displaymodeInfo->displayModeDepthBlockInfo->depthVPBlock[iCount].depthVPBlock; } } static void SquashDisplayModeList(VSettings * s) { ScreenResolution * current, * target, * previous; current = s->Resolutions; while (current != NULL) { target = current->next; previous = current; while (target != NULL) { if (target->Width == current->Width && target->Height == current->Height && target->RefreshRate == current->RefreshRate) { previous->next = target->next; DisposePtr((Ptr) target); target = previous->next; continue; } previous = target; target = target->next; } current = current->next; } } static void GetDisplayCapabilities(VSettings * s) { GDHandle device; DisplayIDType displayID; DMListIndexType displayModeCount; DMListType displayModeList; ListIteratorDataRec searchData; short wDisplayMode, wDepth; DMDisplayModeListIteratorUPP iteratorProc; OSErr error; ScreenResolution ** currentScreenResHandle; s->NumberOfResolutions = 0; device = DMGetFirstScreenDevice(dmOnlyActiveDisplays); error = DMGetDisplayIDByGDevice(device, &displayID, 0); if (error != noErr) return; displayModeCount = 0; error = DMNewDisplayModeList(displayID, 0, 0, &displayModeCount, &displayModeList); if (error != noErr) return; currentScreenResHandle = &s->Resolutions; searchData.depthBlocks = NULL; iteratorProc = NewDMDisplayModeListIteratorUPP(ModeListIterator); for (wDisplayMode = 0; wDisplayMode < displayModeCount; wDisplayMode++) { DMGetIndexedDisplayModeFromList(displayModeList, wDisplayMode, 0, iteratorProc, &searchData); for (wDepth = 0; wDepth < searchData.depthBlockCount; wDepth++) { *currentScreenResHandle = (ScreenResolution *) NewPtr(sizeof(ScreenResolution)); if (*currentScreenResHandle == NULL) continue; s->NumberOfResolutions++; (**currentScreenResHandle).Width = searchData.depthBlocks[wDepth].depthVPBlock.vpBounds.right; (**currentScreenResHandle).Height = searchData.depthBlocks[wDepth].depthVPBlock.vpBounds.bottom; (**currentScreenResHandle).RefreshRate = (searchData.displayModeResolutionInfo.csRefreshRate >> 16); (**currentScreenResHandle).ColorDepth = searchData.depthBlocks[wDepth].depthVPBlock.vpPixelSize; (**currentScreenResHandle).next = NULL; currentScreenResHandle = &(**currentScreenResHandle).next; } if (searchData.depthBlocks != NULL) { DisposePtr((Ptr) searchData.depthBlocks); searchData.depthBlocks = NULL; } } DisposeDMDisplayModeListIteratorUPP(iteratorProc); SquashDisplayModeList(s); } static void ReadSettingsFromDisk(VSettings * s) { FSSpec file; long length; short refNum; OSErr error; error = FindFolder(kOnSystemDisk, kPreferencesFolderType, 1, &file.vRefNum, &file.parID); if (error != noErr) return; error = FSMakeFSSpec(file.vRefNum, file.parID, "\pInfiltration preferences", &file); if (error != noErr) return; error = FSpOpenDF(&file, fsRdPerm, &refNum); if (error != noErr) return; length = 4; FSRead(refNum, &length, &s->FullScreenResolution); if (s->FullScreenResolution > s->NumberOfResolutions || s->FullScreenResolution < -1) s->FullScreenResolution = FULLSCREENRESNOCHANGE; length = 1; FSRead(refNum, &length, &s->NoFilledPolys); length = 1; FSRead(refNum, &length, &s->StartInFullScreen); length = 2; FSRead(refNum, &length, &s->Left); length = 2; FSRead(refNum, &length, &s->Right); length = 2; FSRead(refNum, &length, &s->Up); length = 2; FSRead(refNum, &length, &s->Down); length = 2; FSRead(refNum, &length, &s->Forward); length = 2; FSRead(refNum, &length, &s->Backward); length = 2; FSRead(refNum, &length, &s->Bullet); length = 2; FSRead(refNum, &length, &s->Rocket); length = 2; FSRead(refNum, &length, &s->Brake); length = 2; FSRead(refNum, &length, &s->Pause); FSClose(refNum); } static void SaveSettingsToDisk(VSettings * s) { FSSpec file; long length; short refNum; OSErr error; error = FindFolder(kOnSystemDisk, kPreferencesFolderType, 1, &file.vRefNum, &file.parID); if (error != noErr) return; error = FSMakeFSSpec(file.vRefNum, file.parID, "\pInfiltration preferences", &file); if (error == fnfErr) error = FSpCreate(&file, 'Vect', 'Pref', smRoman); if (error != noErr) return; error = FSpOpenDF(&file, fsWrPerm, &refNum); if (error != noErr) return; SetEOF(refNum, 0); length = 4; FSWrite(refNum, &length, &s->FullScreenResolution); length = 1; FSWrite(refNum, &length, &s->NoFilledPolys); length = 1; FSWrite(refNum, &length, &s->StartInFullScreen); length = 2; FSWrite(refNum, &length, &s->Left); length = 2; FSWrite(refNum, &length, &s->Right); length = 2; FSWrite(refNum, &length, &s->Up); length = 2; FSWrite(refNum, &length, &s->Down); length = 2; FSWrite(refNum, &length, &s->Forward); length = 2; FSWrite(refNum, &length, &s->Backward); length = 2; FSWrite(refNum, &length, &s->Bullet); length = 2; FSWrite(refNum, &length, &s->Rocket); length = 2; FSWrite(refNum, &length, &s->Brake); length = 2; FSWrite(refNum, &length, &s->Pause); FSClose(refNum); } void InitSettings(VSettings * s) { SetSettings(s); s->Left = 28; s->Right = 29; s->Up = 30; s->Down = 31; s->Forward = ' '; s->Backward = (' ' | shiftKey); s->Bullet = 'f'; s->Rocket = 'r'; s->Brake = 'b'; s->Pause = 'p'; s->KeyBeingSet = NULL; s->NoFilledPolys = 0; s->StartInFullScreen = 0; s->FullScreenResolution = FULLSCREENRESNOCHANGE; s->Resolutions = NULL; s->NumberOfResolutions = 0; GetDisplayCapabilities(s); s->Window = NULL; ReadSettingsFromDisk(s); } void CleanUpSettings(VSettings * s) { ScreenResolution * next; while (s->Resolutions != NULL) { next = s->Resolutions->next; DisposePtr((Ptr) s->Resolutions); s->Resolutions = next; } if (s->Window != NULL) { DisposeWindow(s->Window); s->Window = NULL; } SaveSettingsToDisk(s); } static int GetKeyDescription(UInt16 key, char * string) { char charCode; int length = 0; if (key & optionKey) length += sprintf((string + length), "Option + "); if (key & cmdKey) length += sprintf((string + length), "Cmd + "); if (key & shiftKey) length += sprintf((string + length), "Shift + "); if (key & controlKey) length += sprintf((string + length), "Ctrl + "); charCode = (key & 0x00FF); switch (charCode) { case 3: length += sprintf((string + length), "Enter"); break; case 8: length += sprintf((string + length), "Backspace"); break; case 9: length += sprintf((string + length), "Tab"); break; case 10: case 13: length += sprintf((string + length), "Return"); break; case 27: length += sprintf((string + length), "Escape"); break; case 28: length += sprintf((string + length), "Left arrow"); break; case 29: length += sprintf((string + length), "Right arrow"); break; case 30: length += sprintf((string + length), "Up arrow"); break; case 31: length += sprintf((string + length), "Down arrow"); break; case ' ': /* Normal space */ case 'Ê': /* Non-breaking space */ length += sprintf((string + length), "Space"); break; case 127: length += sprintf((string + length), "Forward delete"); break; default: length += sprintf((string + length), "%c", charCode); break; } return length; } SInt16 KeyWithModifiers(unsigned char charCode, UInt32 modifiers) { switch (charCode) { case 3: case 8: case 9: case 10: case 13: case 27: case 28: case 29: case 30: case 31: case ' ': /* Space */ case 'Ê': /* Non-breaking space */ case 127: /* Char code is not visibly affected by modifiers */ return ((SInt16) charCode | modifiers); default: /* Char code is visibly affected by modifiers; don't bother displaying Shift + or Option + */ return ((SInt16) charCode | (modifiers & ~(shiftKey | optionKey))); } } static void UpdateKeySettingDisplay(VSettings * s) { ControlRef theControl = NULL; char string[256]; ControlID controlID; int length; controlID.signature = 'idsi'; if (s->KeyBeingSet == &s->Left) { controlID.id = LOOKLEFTKEYDISPLAY; GetControlByID(s->Window, &controlID, &theControl); } else if (s->KeyBeingSet == &s->Right) { controlID.id = LOOKRIGHTKEYDISPLAY; GetControlByID(s->Window, &controlID, &theControl); } else if (s->KeyBeingSet == &s->Down) { controlID.id = LOOKDOWNKEYDISPLAY; GetControlByID(s->Window, &controlID, &theControl); } else if (s->KeyBeingSet == &s->Up) { controlID.id = LOOKUPKEYDISPLAY; GetControlByID(s->Window, &controlID, &theControl); } else if (s->KeyBeingSet == &s->Forward) { controlID.id = MOVEFORWARDKEYDISPLAY; GetControlByID(s->Window, &controlID, &theControl); } else if (s->KeyBeingSet == &s->Backward) { controlID.id = MOVEBACKWARDKEYDISPLAY; GetControlByID(s->Window, &controlID, &theControl); } else if (s->KeyBeingSet == &s->Bullet) { controlID.id = BULLETKEYDISPLAY; GetControlByID(s->Window, &controlID, &theControl); } else if (s->KeyBeingSet == &s->Rocket) { controlID.id = ROCKETKEYDISPLAY; GetControlByID(s->Window, &controlID, &theControl); } else if (s->KeyBeingSet == &s->Brake) { controlID.id = BRAKEKEYDISPLAY; GetControlByID(s->Window, &controlID, &theControl); } else if (s->KeyBeingSet == &s->Pause) { controlID.id = PAUSEKEYDISPLAY; GetControlByID(s->Window, &controlID, &theControl); } if (theControl != NULL) { length = GetKeyDescription(*s->KeyBeingSet, string); SetControlData(theControl, kControlEditTextPart, kControlEditTextTextTag, length, string); Draw1Control(theControl); } } static void ClearKeyDisplayStyles(VSettings * s) { ControlRef theControl = NULL; ControlID controlID; ControlFontStyleRec fontStyle; controlID.signature = 'idsi'; if (s->KeyBeingSet == &s->Left) { controlID.id = LOOKLEFTKEYDISPLAY; GetControlByID(s->Window, &controlID, &theControl); } else if (s->KeyBeingSet == &s->Right) { controlID.id = LOOKRIGHTKEYDISPLAY; GetControlByID(s->Window, &controlID, &theControl); } else if (s->KeyBeingSet == &s->Down) { controlID.id = LOOKDOWNKEYDISPLAY; GetControlByID(s->Window, &controlID, &theControl); } else if (s->KeyBeingSet == &s->Up) { controlID.id = LOOKUPKEYDISPLAY; GetControlByID(s->Window, &controlID, &theControl); } else if (s->KeyBeingSet == &s->Forward) { controlID.id = MOVEFORWARDKEYDISPLAY; GetControlByID(s->Window, &controlID, &theControl); } else if (s->KeyBeingSet == &s->Backward) { controlID.id = MOVEBACKWARDKEYDISPLAY; GetControlByID(s->Window, &controlID, &theControl); } else if (s->KeyBeingSet == &s->Bullet) { controlID.id = BULLETKEYDISPLAY; GetControlByID(s->Window, &controlID, &theControl); } else if (s->KeyBeingSet == &s->Rocket) { controlID.id = ROCKETKEYDISPLAY; GetControlByID(s->Window, &controlID, &theControl); } else if (s->KeyBeingSet == &s->Brake) { controlID.id = BRAKEKEYDISPLAY; GetControlByID(s->Window, &controlID, &theControl); } else if (s->KeyBeingSet == &s->Pause) { controlID.id = PAUSEKEYDISPLAY; GetControlByID(s->Window, &controlID, &theControl); } if (theControl != NULL) { fontStyle.flags = (kControlUseSizeMask | kControlUseFontMask); fontStyle.size = 12; fontStyle.font = systemFont; SetControlFontStyle(theControl, &fontStyle); Draw1Control(theControl); } } static void HiliteKeySettingDisplay(ControlRef control) { ControlFontStyleRec fontStyle; fontStyle.flags = (kControlUseForeColorMask | kControlUseSizeMask | kControlUseFontMask | kControlUseFaceMask); fontStyle.foreColor.red = fontStyle.foreColor.green = 0x0000; fontStyle.foreColor.blue = 0x7FFF; fontStyle.size = 12; fontStyle.font = systemFont; fontStyle.style = italic; SetControlFontStyle(control, &fontStyle); Draw1Control(control); } /* Settings window code copied from Life */ static pascal OSStatus SettingsWindowEventHandler(EventHandlerCallRef nextEvent, EventRef theEvent, void * userData) { #pragma unused(nextEvent, theEvent, userData) short controlValue; ControlRef control; Rect bounds; VSettings * s; SInt32 controlReference; unsigned char charCode; UInt32 modifiers; ControlID controlID; s = (VSettings *) userData; switch (GetEventClass(theEvent)) { case kEventClassWindow: switch (GetEventKind(theEvent)) { case kEventWindowClose: TransWindow(s->Window, 0); DisposeWindow(s->Window); s->Window = NULL; return noErr; case kEventWindowDrawContent: GetWindowPortBounds(s->Window, &bounds); EraseRect(&bounds); DrawControls(s->Window); return eventNotHandledErr; } break; case kEventClassControl: switch (GetEventKind(theEvent)) { case kEventControlHit: GetEventParameter(theEvent, kEventParamDirectObject, typeControlRef, NULL, sizeof(ControlRef), NULL, &control); controlReference = GetControlReference(control); switch (controlReference) { case FULLSCREENRESMENU: controlValue = GetControlValue(control); if (controlValue < 3) s->FullScreenResolution = FULLSCREENRESNOCHANGE; else s->FullScreenResolution = (controlValue - 3); break; case STARTINFULLSCREENCHECKBOX: controlValue = !GetControlValue(control); SetControlValue(control, controlValue); s->StartInFullScreen = controlValue; break; case NOPOLYGONFILLCHECKBOX: controlValue = !GetControlValue(control); SetControlValue(control, controlValue); s->NoFilledPolys = controlValue; break; case SETLOOKLEFTKEYBUTTON: if (s->KeyBeingSet != NULL) ClearKeyDisplayStyles(s); s->KeyBeingSet = &s->Left; controlID.signature = 'idsi'; controlID.id = LOOKLEFTKEYDISPLAY; GetControlByID(s->Window, &controlID, &control); HiliteKeySettingDisplay(control); break; case SETLOOKRIGHTKEYBUTTON: if (s->KeyBeingSet != NULL) ClearKeyDisplayStyles(s); s->KeyBeingSet = &s->Right; controlID.signature = 'idsi'; controlID.id = LOOKRIGHTKEYDISPLAY; GetControlByID(s->Window, &controlID, &control); HiliteKeySettingDisplay(control); break; case SETLOOKDOWNKEYBUTTON: if (s->KeyBeingSet != NULL) ClearKeyDisplayStyles(s); s->KeyBeingSet = &s->Down; controlID.signature = 'idsi'; controlID.id = LOOKDOWNKEYDISPLAY; GetControlByID(s->Window, &controlID, &control); HiliteKeySettingDisplay(control); break; case SETLOOKUPKEYBUTTON: if (s->KeyBeingSet != NULL) ClearKeyDisplayStyles(s); s->KeyBeingSet = &s->Up; controlID.signature = 'idsi'; controlID.id = LOOKUPKEYDISPLAY; GetControlByID(s->Window, &controlID, &control); HiliteKeySettingDisplay(control); break; case SETMOVEFORWARDKEYBUTTON: if (s->KeyBeingSet != NULL) ClearKeyDisplayStyles(s); s->KeyBeingSet = &s->Forward; controlID.signature = 'idsi'; controlID.id = MOVEFORWARDKEYDISPLAY; GetControlByID(s->Window, &controlID, &control); HiliteKeySettingDisplay(control); break; case SETMOVEBACKWARDKEYBUTTON: if (s->KeyBeingSet != NULL) ClearKeyDisplayStyles(s); s->KeyBeingSet = &s->Backward; controlID.signature = 'idsi'; controlID.id = MOVEBACKWARDKEYDISPLAY; GetControlByID(s->Window, &controlID, &control); HiliteKeySettingDisplay(control); break; case SETBULLETKEYBUTTON: if (s->KeyBeingSet != NULL) ClearKeyDisplayStyles(s); s->KeyBeingSet = &s->Bullet; controlID.signature = 'idsi'; controlID.id = BULLETKEYDISPLAY; GetControlByID(s->Window, &controlID, &control); HiliteKeySettingDisplay(control); break; case SETROCKETKEYBUTTON: if (s->KeyBeingSet != NULL) ClearKeyDisplayStyles(s); s->KeyBeingSet = &s->Rocket; controlID.signature = 'idsi'; controlID.id = ROCKETKEYDISPLAY; GetControlByID(s->Window, &controlID, &control); HiliteKeySettingDisplay(control); break; case SETBRAKEKEYBUTTON: if (s->KeyBeingSet != NULL) ClearKeyDisplayStyles(s); s->KeyBeingSet = &s->Brake; controlID.signature = 'idsi'; controlID.id = BRAKEKEYDISPLAY; GetControlByID(s->Window, &controlID, &control); HiliteKeySettingDisplay(control); break; case SETPAUSEKEYBUTTON: if (s->KeyBeingSet != NULL) ClearKeyDisplayStyles(s); s->KeyBeingSet = &s->Pause; controlID.signature = 'idsi'; controlID.id = PAUSEKEYDISPLAY; GetControlByID(s->Window, &controlID, &control); HiliteKeySettingDisplay(control); break; } break; } break; case kEventClassKeyboard: switch (GetEventKind(theEvent)) { case kEventRawKeyDown: if (s->KeyBeingSet != NULL) { GetEventParameter(theEvent, kEventParamKeyMacCharCodes, typeChar, NULL, sizeof(char), NULL, &charCode); GetEventParameter(theEvent, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers); if (charCode != 27) { *s->KeyBeingSet = KeyWithModifiers(charCode, modifiers); UpdateKeySettingDisplay(s); } ClearKeyDisplayStyles(s); s->KeyBeingSet = NULL; return noErr; } break; } break; } return eventNotHandledErr; } /* Sorry for the scary code... I guess that's what I get for not using nibs. */ void OpenSettingsWindow(VSettings * s) { Rect bounds; GWorldPtr origGWorld; GDHandle origGDevice, mainDevice; Point screenSize; EventTypeSpec windowEventTypes[] = {{kEventClassWindow, kEventWindowClose}, {kEventClassWindow, kEventWindowDrawContent}, {kEventClassKeyboard, kEventRawKeyDown}}, controlEventTypes[] = {{kEventClassControl, kEventControlHit}}; ControlRef theControl; EventHandlerUPP eventHandlerUPP; MenuRef screenResMenu; ScreenResolution * screenRes; Str255 itemName; int currentItemNumber; ControlFontStyleRec controlFontStyle; CFStringRef string; Boolean locked = 1; char keyDescription[256]; ControlID controlID; if (s->Window != NULL) { BringToFront(s->Window); SelectWindow(s->Window); return; } mainDevice = GetMainDevice(); screenSize.h = (**mainDevice).gdRect.right; screenSize.v = (**mainDevice).gdRect.bottom; SetRect(&bounds, ((screenSize.h / 2) - 200), ((screenSize.v / 2) - 200), ((screenSize.h / 2) + 200), ((screenSize.v / 2) + 200)); s->Window = NewCWindow(NULL, &bounds, "\pSettings", 0, noGrowDocProc, (WindowPtr) -1, 1, 0); if (s->Window == NULL) return; GetGWorld(&origGWorld, &origGDevice); SetPortWindowPort(s->Window); SetThemeBackground(kThemeBrushDialogBackgroundActive, 32, 1); OffsetRect(&bounds, -bounds.left, -bounds.top); EraseRect(&bounds); InstallStandardEventHandler(GetWindowEventTarget(s->Window)); eventHandlerUPP = NewEventHandlerUPP(SettingsWindowEventHandler); InstallWindowEventHandler(s->Window, eventHandlerUPP, 3, windowEventTypes, s, NULL); CreateRootControl(s->Window, &theControl); screenResMenu = GetMenuHandle(140); if (screenResMenu == NULL) { screenResMenu = NewMenu(140, "\p"); AppendMenu(screenResMenu, "\pNo change"); if (s->NumberOfResolutions > 0) AppendMenu(screenResMenu, "\p(-"); currentItemNumber = 3; for (screenRes = s->Resolutions; screenRes != NULL; screenRes = screenRes->next) { itemName[0] = sprintf((char *) &itemName[1], "%d x %d, %dHz", screenRes->Width, screenRes->Height, screenRes->RefreshRate); AppendMenu(screenResMenu, "\pN"); SetMenuItemText(screenResMenu, currentItemNumber, itemName); currentItemNumber++; } InsertMenu(screenResMenu, kInsertHierarchicalMenu); } SetRect(&bounds, 10, 10, 390, 30); CreatePopupButtonControl(s->Window, &bounds, CFSTR("Fullscreen resolution"), 140, 0, 150, 0, 0, &theControl); if (s->FullScreenResolution == FULLSCREENRESNOCHANGE) SetControlValue(theControl, 1); else SetControlValue(theControl, (s->FullScreenResolution + 3)); SetControlReference(theControl, FULLSCREENRESMENU); InstallControlEventHandler(theControl, eventHandlerUPP, 1, controlEventTypes, s, NULL); SetRect(&bounds, 50, 40, 390, 54); CreateCheckBoxControl(s->Window, &bounds, CFSTR("Start in full screen mode"), s->StartInFullScreen, 0, &theControl); SetControlReference(theControl, STARTINFULLSCREENCHECKBOX); InstallControlEventHandler(theControl, eventHandlerUPP, 1, controlEventTypes, s, NULL); SetRect(&bounds, 50, 60, 390, 74); CreateCheckBoxControl(s->Window, &bounds, CFSTR("Don't fill polygons"), s->NoFilledPolys, 0, &theControl); SetControlReference(theControl, NOPOLYGONFILLCHECKBOX); InstallControlEventHandler(theControl, eventHandlerUPP, 1, controlEventTypes, s, NULL); controlFontStyle.flags = kControlUseJustMask; controlFontStyle.just = teCenter; SetRect(&bounds, 10, 88, 390, 104); CreateStaticTextControl(s->Window, &bounds, CFSTR("Keys"), &controlFontStyle, &theControl); controlFontStyle.flags = kControlUseJustMask; controlFontStyle.just = teFlushRight; SetRect(&bounds, 10, 114, 100, 130); CreateStaticTextControl(s->Window, &bounds, CFSTR("Look left:"), &controlFontStyle, &theControl); SetRect(&bounds, 110, 114, 290, 130); GetKeyDescription(s->Left, keyDescription); string = CFStringCreateWithFormat(NULL, NULL, CFSTR("%s"), keyDescription); controlFontStyle.flags = (kControlUseSizeMask | kControlUseFontMask); controlFontStyle.size = 12; controlFontStyle.font = systemFont; CreateEditTextControl(s->Window, &bounds, string, 0, 0, &controlFontStyle, &theControl); CFRelease(string); SetControlData(theControl, kControlEditTextPart, kControlEditTextLockedTag, sizeof(Boolean), &locked); controlID.signature = 'idsi'; controlID.id = LOOKLEFTKEYDISPLAY; SetControlID(theControl, &controlID); SetRect(&bounds, 300, 112, 390, 132); CreatePushButtonControl(s->Window, &bounds, CFSTR("Set"), &theControl); SetControlReference(theControl, SETLOOKLEFTKEYBUTTON); InstallControlEventHandler(theControl, eventHandlerUPP, 1, controlEventTypes, s, NULL); controlFontStyle.flags = kControlUseJustMask; controlFontStyle.just = teFlushRight; SetRect(&bounds, 10, 142, 100, 158); CreateStaticTextControl(s->Window, &bounds, CFSTR("Look right:"), &controlFontStyle, &theControl); SetRect(&bounds, 110, 142, 290, 158); GetKeyDescription(s->Right, keyDescription); string = CFStringCreateWithFormat(NULL, NULL, CFSTR("%s"), keyDescription); controlFontStyle.flags = (kControlUseSizeMask | kControlUseFontMask); controlFontStyle.size = 12; controlFontStyle.font = systemFont; CreateEditTextControl(s->Window, &bounds, string, 0, 0, &controlFontStyle, &theControl); CFRelease(string); SetControlData(theControl, kControlEditTextPart, kControlEditTextLockedTag, sizeof(Boolean), &locked); controlID.signature = 'idsi'; controlID.id = LOOKRIGHTKEYDISPLAY; SetControlID(theControl, &controlID); SetRect(&bounds, 300, 140, 390, 160); CreatePushButtonControl(s->Window, &bounds, CFSTR("Set"), &theControl); SetControlReference(theControl, SETLOOKRIGHTKEYBUTTON); InstallControlEventHandler(theControl, eventHandlerUPP, 1, controlEventTypes, s, NULL); controlFontStyle.flags = kControlUseJustMask; controlFontStyle.just = teFlushRight; SetRect(&bounds, 10, 170, 100, 186); CreateStaticTextControl(s->Window, &bounds, CFSTR("Look down:"), &controlFontStyle, &theControl); SetRect(&bounds, 110, 170, 290, 186); GetKeyDescription(s->Down, keyDescription); string = CFStringCreateWithFormat(NULL, NULL, CFSTR("%s"), keyDescription); controlFontStyle.flags = (kControlUseSizeMask | kControlUseFontMask); controlFontStyle.size = 12; controlFontStyle.font = systemFont; CreateEditTextControl(s->Window, &bounds, string, 0, 0, &controlFontStyle, &theControl); CFRelease(string); SetControlData(theControl, kControlEditTextPart, kControlEditTextLockedTag, sizeof(Boolean), &locked); controlID.signature = 'idsi'; controlID.id = LOOKDOWNKEYDISPLAY; SetControlID(theControl, &controlID); SetRect(&bounds, 300, 168, 390, 188); CreatePushButtonControl(s->Window, &bounds, CFSTR("Set"), &theControl); SetControlReference(theControl, SETLOOKDOWNKEYBUTTON); InstallControlEventHandler(theControl, eventHandlerUPP, 1, controlEventTypes, s, NULL); controlFontStyle.flags = kControlUseJustMask; controlFontStyle.just = teFlushRight; SetRect(&bounds, 10, 198, 100, 214); CreateStaticTextControl(s->Window, &bounds, CFSTR("Look up:"), &controlFontStyle, &theControl); SetRect(&bounds, 110, 198, 290, 214); GetKeyDescription(s->Up, keyDescription); string = CFStringCreateWithFormat(NULL, NULL, CFSTR("%s"), keyDescription); controlFontStyle.flags = (kControlUseSizeMask | kControlUseFontMask); controlFontStyle.size = 12; controlFontStyle.font = systemFont; CreateEditTextControl(s->Window, &bounds, string, 0, 0, &controlFontStyle, &theControl); CFRelease(string); SetControlData(theControl, kControlEditTextPart, kControlEditTextLockedTag, sizeof(Boolean), &locked); controlID.signature = 'idsi'; controlID.id = LOOKUPKEYDISPLAY; SetControlID(theControl, &controlID); SetRect(&bounds, 300, 196, 390, 216); CreatePushButtonControl(s->Window, &bounds, CFSTR("Set"), &theControl); SetControlReference(theControl, SETLOOKUPKEYBUTTON); InstallControlEventHandler(theControl, eventHandlerUPP, 1, controlEventTypes, s, NULL); controlFontStyle.flags = kControlUseJustMask; controlFontStyle.just = teFlushRight; SetRect(&bounds, 10, 226, 100, 242); CreateStaticTextControl(s->Window, &bounds, CFSTR("Accelerate:"), &controlFontStyle, &theControl); SetRect(&bounds, 110, 226, 290, 242); GetKeyDescription(s->Forward, keyDescription); string = CFStringCreateWithFormat(NULL, NULL, CFSTR("%s"), keyDescription); controlFontStyle.flags = (kControlUseSizeMask | kControlUseFontMask); controlFontStyle.size = 12; controlFontStyle.font = systemFont; CreateEditTextControl(s->Window, &bounds, string, 0, 0, &controlFontStyle, &theControl); CFRelease(string); SetControlData(theControl, kControlEditTextPart, kControlEditTextLockedTag, sizeof(Boolean), &locked); controlID.signature = 'idsi'; controlID.id = MOVEFORWARDKEYDISPLAY; SetControlID(theControl, &controlID); SetRect(&bounds, 300, 224, 390, 244); CreatePushButtonControl(s->Window, &bounds, CFSTR("Set"), &theControl); SetControlReference(theControl, SETMOVEFORWARDKEYBUTTON); InstallControlEventHandler(theControl, eventHandlerUPP, 1, controlEventTypes, s, NULL); controlFontStyle.flags = kControlUseJustMask; controlFontStyle.just = teFlushRight; SetRect(&bounds, 10, 254, 100, 270); CreateStaticTextControl(s->Window, &bounds, CFSTR("Reverse:"), &controlFontStyle, &theControl); SetRect(&bounds, 110, 254, 290, 270); GetKeyDescription(s->Backward, keyDescription); string = CFStringCreateWithFormat(NULL, NULL, CFSTR("%s"), keyDescription); controlFontStyle.flags = (kControlUseSizeMask | kControlUseFontMask); controlFontStyle.size = 12; controlFontStyle.font = systemFont; CreateEditTextControl(s->Window, &bounds, string, 0, 0, &controlFontStyle, &theControl); CFRelease(string); SetControlData(theControl, kControlEditTextPart, kControlEditTextLockedTag, sizeof(Boolean), &locked); controlID.signature = 'idsi'; controlID.id = MOVEBACKWARDKEYDISPLAY; SetControlID(theControl, &controlID); SetRect(&bounds, 300, 252, 390, 272); CreatePushButtonControl(s->Window, &bounds, CFSTR("Set"), &theControl); SetControlReference(theControl, SETMOVEBACKWARDKEYBUTTON); InstallControlEventHandler(theControl, eventHandlerUPP, 1, controlEventTypes, s, NULL); controlFontStyle.flags = kControlUseJustMask; controlFontStyle.just = teFlushRight; SetRect(&bounds, 10, 282, 100, 298); CreateStaticTextControl(s->Window, &bounds, CFSTR("Fire:"), &controlFontStyle, &theControl); SetRect(&bounds, 110, 282, 290, 298); GetKeyDescription(s->Bullet, keyDescription); string = CFStringCreateWithFormat(NULL, NULL, CFSTR("%s"), keyDescription); controlFontStyle.flags = (kControlUseSizeMask | kControlUseFontMask); controlFontStyle.size = 12; controlFontStyle.font = systemFont; CreateEditTextControl(s->Window, &bounds, string, 0, 0, &controlFontStyle, &theControl); CFRelease(string); SetControlData(theControl, kControlEditTextPart, kControlEditTextLockedTag, sizeof(Boolean), &locked); controlID.signature = 'idsi'; controlID.id = BULLETKEYDISPLAY; SetControlID(theControl, &controlID); SetRect(&bounds, 300, 280, 390, 300); CreatePushButtonControl(s->Window, &bounds, CFSTR("Set"), &theControl); SetControlReference(theControl, SETBULLETKEYBUTTON); InstallControlEventHandler(theControl, eventHandlerUPP, 1, controlEventTypes, s, NULL); controlFontStyle.flags = kControlUseJustMask; controlFontStyle.just = teFlushRight; SetRect(&bounds, 10, 310, 100, 326); CreateStaticTextControl(s->Window, &bounds, CFSTR("Rocket:"), &controlFontStyle, &theControl); SetRect(&bounds, 110, 310, 290, 326); GetKeyDescription(s->Rocket, keyDescription); string = CFStringCreateWithFormat(NULL, NULL, CFSTR("%s"), keyDescription); controlFontStyle.flags = (kControlUseSizeMask | kControlUseFontMask); controlFontStyle.size = 12; controlFontStyle.font = systemFont; CreateEditTextControl(s->Window, &bounds, string, 0, 0, &controlFontStyle, &theControl); CFRelease(string); SetControlData(theControl, kControlEditTextPart, kControlEditTextLockedTag, sizeof(Boolean), &locked); controlID.signature = 'idsi'; controlID.id = ROCKETKEYDISPLAY; SetControlID(theControl, &controlID); SetRect(&bounds, 300, 308, 390, 328); CreatePushButtonControl(s->Window, &bounds, CFSTR("Set"), &theControl); SetControlReference(theControl, SETROCKETKEYBUTTON); InstallControlEventHandler(theControl, eventHandlerUPP, 1, controlEventTypes, s, NULL); controlFontStyle.flags = kControlUseJustMask; controlFontStyle.just = teFlushRight; SetRect(&bounds, 10, 338, 100, 354); CreateStaticTextControl(s->Window, &bounds, CFSTR("Brake:"), &controlFontStyle, &theControl); SetRect(&bounds, 110, 338, 290, 354); GetKeyDescription(s->Brake, keyDescription); string = CFStringCreateWithFormat(NULL, NULL, CFSTR("%s"), keyDescription); controlFontStyle.flags = (kControlUseSizeMask | kControlUseFontMask); controlFontStyle.size = 12; controlFontStyle.font = systemFont; CreateEditTextControl(s->Window, &bounds, string, 0, 0, &controlFontStyle, &theControl); CFRelease(string); SetControlData(theControl, kControlEditTextPart, kControlEditTextLockedTag, sizeof(Boolean), &locked); controlID.signature = 'idsi'; controlID.id = BRAKEKEYDISPLAY; SetControlID(theControl, &controlID); SetRect(&bounds, 300, 336, 390, 356); CreatePushButtonControl(s->Window, &bounds, CFSTR("Set"), &theControl); SetControlReference(theControl, SETBRAKEKEYBUTTON); InstallControlEventHandler(theControl, eventHandlerUPP, 1, controlEventTypes, s, NULL); controlFontStyle.flags = kControlUseJustMask; controlFontStyle.just = teFlushRight; SetRect(&bounds, 10, 366, 100, 382); CreateStaticTextControl(s->Window, &bounds, CFSTR("Pause:"), &controlFontStyle, &theControl); SetRect(&bounds, 110, 366, 290, 382); GetKeyDescription(s->Pause, keyDescription); string = CFStringCreateWithFormat(NULL, NULL, CFSTR("%s"), keyDescription); controlFontStyle.flags = (kControlUseSizeMask | kControlUseFontMask); controlFontStyle.size = 12; controlFontStyle.font = systemFont; CreateEditTextControl(s->Window, &bounds, string, 0, 0, &controlFontStyle, &theControl); CFRelease(string); SetControlData(theControl, kControlEditTextPart, kControlEditTextLockedTag, sizeof(Boolean), &locked); controlID.signature = 'idsi'; controlID.id = PAUSEKEYDISPLAY; SetControlID(theControl, &controlID); SetRect(&bounds, 300, 364, 390, 384); CreatePushButtonControl(s->Window, &bounds, CFSTR("Set"), &theControl); SetControlReference(theControl, SETPAUSEKEYBUTTON); InstallControlEventHandler(theControl, eventHandlerUPP, 1, controlEventTypes, s, NULL); SetGWorld(origGWorld, origGDevice); TransWindow(s->Window, 1); } /* Silly function written to avoid using a global variable */ VSettings * SettingsAccessor(VSettings * s) { static VSettings * settings = NULL; if (s != NULL) settings = s; return settings; } void GetFullscreenSettings(VSettings * s, int * Width, int * Height, int * RefreshRate) { int count; if (s->FullScreenResolution == FULLSCREENRESNOCHANGE) { GDHandle mainDevice; mainDevice = GetMainDevice(); *Width = (**mainDevice).gdRect.right; *Height = (**mainDevice).gdRect.bottom; *RefreshRate = 0; } else { ScreenResolution * res = s->Resolutions; for (count = 0; count < s->FullScreenResolution && res != NULL; count++) { res = res->next; } *Width = res->Width; *Height = res->Height; *RefreshRate = res->RefreshRate; } } /* This function takes a key being pressed (KeyWithModifiers(charCode, modifiers)), and a key from the VSettings struct, and determines whether or not pressedKey can be considerered to be equivalent to setKey. The keys are equivalent if: 1. Their char codes are the same, 2. If there is no other key in the settings with the same modifiers as setKey, (pressedKey's modifiers & setKey's modifiers) >= setKey's modifiers, 3. If there is another key in the settings with the same modifiers as setKey, pressedKey's modifiers == setKey's modifiers. This code uses tolower to ignore case (the shift key). This is "good enough", but to work for all keys and modifiers, it would need to do such translations as ! -> 1, Œ -> a, ð -> k, etc. */ Boolean SettingsIsEquivalentKey(VSettings * s, SInt16 pressedKey, SInt16 setKey) { Boolean strict; if ((s->Left != setKey && (s->Left & 0xFF) == (setKey & 0xFF) && (s->Left & 0x7F00)) || (s->Right != setKey && (s->Right & 0xFF) == (setKey & 0xFF) && (s->Right & 0x7F00)) || (s->Down != setKey && (s->Down & 0xFF) == (setKey & 0xFF) && (s->Down & 0x7F00)) || (s->Up != setKey && (s->Up & 0xFF) == (setKey & 0xFF) && (s->Up & 0x7F00)) || (s->Forward != setKey && (s->Forward & 0xFF) == (setKey & 0xFF) && (s->Forward & 0x7F00)) || (s->Backward != setKey && (s->Backward & 0xFF) == (setKey & 0xFF) && (s->Backward & 0x7F00)) || (s->Bullet != setKey && (s->Bullet & 0xFF) == (setKey & 0xFF) && (s->Bullet & 0x7F00)) || (s->Rocket != setKey && (s->Rocket & 0xFF) == (setKey & 0xFF) && (s->Rocket & 0x7F00)) || (s->Brake != setKey && (s->Brake & 0xFF) == (setKey & 0xFF) && (s->Brake & 0x7F00)) || (s->Pause != setKey && (s->Pause & 0xFF) == (setKey & 0xFF) && (s->Pause & 0x7F00))) strict = 1; else strict = 0; if (strict && pressedKey != setKey) return 0; if (!strict) { pressedKey = (tolower(pressedKey & 0xFF) | (pressedKey & 0xFF00)); setKey = (tolower(setKey & 0xFF) | (setKey & 0xFF00)); } if ((pressedKey & (0xFF | (setKey & 0xFF00))) != setKey) return 0; return 1; }