/* * CiderPress * Copyright (C) 2007, 2008 by faddenSoft, LLC. All Rights Reserved. * See the file LICENSE for distribution terms. */ /* * Save and restore preferences from the config file. */ #include "stdafx.h" #include "Preferences.h" #include "NufxArchive.h" #include "MyApp.h" #include "../util/UtilLib.h" static const char* kDefaultTempPath = "."; /* registry section for columns */ static const char* kColumnSect = _T("columns"); /* registry section for file add options */ static const char* kAddSect = _T("add"); /* registry section for extraction options */ static const char* kExtractSect = _T("extract"); /* registry section for view options */ static const char* kViewSect = _T("view"); /* registry section for logical/physical volume operations */ static const char* kVolumeSect = _T("volume"); /* registry section for file-to-disk options */ //static const char* kConvDiskSect = _T("conv-disk"); /* registry section for disk-to-file options */ static const char* kConvFileSect = _T("conv-file"); /* registry section for folders */ static const char* kFolderSect = _T("folders"); /* registry section for preferences on property pages */ static const char* kPrefsSect = _T("prefs"); /* registry section for miscellaneous settings */ static const char* kMiscSect = _T("misc"); /* * Map PrefNum to type and registry string. * * To make life easier, we require that the PrefNum (first entry) match the * offset in the table. That way instead of searching for a match we can just * index into the table. */ const Preferences::PrefMap Preferences::fPrefMaps[kPrefNumLastEntry] = { /**/ { kPrefNumUnknown, kPTNone, nil, nil }, { kPrAddIncludeSubFolders, kBool, kAddSect, _T("include-sub-folders") }, { kPrAddStripFolderNames, kBool, kAddSect, _T("strip-folder-names") }, { kPrAddOverwriteExisting, kBool, kAddSect, _T("overwrite-existing") }, { kPrAddTypePreservation, kLong, kAddSect, _T("type-preservation") }, { kPrAddConvEOL, kLong, kAddSect, _T("conv-eol") }, // { kPrExtractPath, kString, kExtractSect, _T("path") }, { kPrExtractConvEOL, kLong, kExtractSect, _T("conv-eol") }, { kPrExtractConvHighASCII, kBool, kExtractSect, _T("conv-high-ascii") }, { kPrExtractIncludeData, kBool, kExtractSect, _T("include-data") }, { kPrExtractIncludeRsrc, kBool, kExtractSect, _T("include-rsrc") }, { kPrExtractIncludeDisk, kBool, kExtractSect, _T("include-disk") }, { kPrExtractEnableReformat, kBool, kExtractSect, _T("enable-reformat") }, { kPrExtractDiskTo2MG, kBool, kExtractSect, _T("disk-to-2mg") }, { kPrExtractAddTypePreservation, kBool, kExtractSect, _T("add-type-preservation") }, { kPrExtractAddExtension, kBool, kExtractSect, _T("add-extension") }, { kPrExtractStripFolderNames, kBool, kExtractSect, _T("strip-folder-names") }, { kPrExtractOverwriteExisting, kBool, kExtractSect, _T("overwrite-existing") }, // { kPrViewIncludeDataForks, kBool, kViewSect, _T("include-data-forks") }, // { kPrViewIncludeRsrcForks, kBool, kViewSect, _T("include-rsrc-forks") }, // { kPrViewIncludeDiskImages, kBool, kViewSect, _T("include-disk-images") }, // { kPrViewIncludeComments, kBool, kViewSect, _T("include-comments") }, { kPrConvFileEmptyFolders, kBool, kConvFileSect, _T("preserve-empty-folders") }, { kPrOpenArchiveFolder, kString, kFolderSect, _T("open-archive") }, { kPrConvertArchiveFolder, kString, kFolderSect, _T("convert-archive") }, { kPrAddFileFolder, kString, kFolderSect, _T("add-file") }, { kPrExtractFileFolder, kString, kFolderSect, _T("extract-file") }, { kPrVolumeFilter, kLong, kVolumeSect, _T("open-filter") }, //{ kPrVolumeReadOnly, kBool, kVolumeSect, _T("read-only") }, { kPrCassetteAlgorithm, kLong, kVolumeSect, _T("cassette-algorithm") }, { kPrOpenWAVFolder, kString, kFolderSect, _T("open-wav") }, { kPrMimicShrinkIt, kBool, kPrefsSect, _T("mimic-shrinkit") }, { kPrBadMacSHK, kBool, kPrefsSect, _T("bad-mac-shk") }, { kPrReduceSHKErrorChecks, kBool, kPrefsSect, _T("reduce-shk-error-checks") }, { kPrCoerceDOSFilenames, kBool, kPrefsSect, _T("coerce-dos-filenames") }, { kPrSpacesToUnder, kBool, kPrefsSect, _T("spaces-to-under") }, { kPrPasteJunkPaths, kBool, kPrefsSect, _T("paste-junk-paths") }, { kPrBeepOnSuccess, kBool, kPrefsSect, _T("beep-on-success") }, { kPrQueryImageFormat, kBool, kPrefsSect, _T("query-image-format") }, { kPrOpenVolumeRO, kBool, kPrefsSect, _T("open-volume-ro") }, { kPrOpenVolumePhys0, kBool, kPrefsSect, _T("open-volume-phys0") }, { kPrProDOSAllowLower, kBool, kPrefsSect, _T("prodos-allow-lower") }, { kPrProDOSUseSparse, kBool, kPrefsSect, _T("prodos-use-sparse") }, { kPrCompressionType, kLong, kPrefsSect, _T("compression-type") }, { kPrMaxViewFileSize, kLong, kPrefsSect, _T("max-view-file-size") }, { kPrNoWrapText, kBool, kPrefsSect, _T("no-wrap-text") }, { kPrHighlightHexDump, kBool, kPrefsSect, _T("highlight-hex-dump") }, { kPrHighlightBASIC, kBool, kPrefsSect, _T("highlight-basic") }, { kPrConvHiResBlackWhite, kBool, kPrefsSect, _T("conv-hi-res-black-white") }, { kPrConvDHRAlgorithm, kLong, kPrefsSect, _T("dhr-algorithm") }, { kPrRelaxGfxTypeCheck, kBool, kPrefsSect, _T("relax-gfx-type-check") }, { kPrDisasmOneByteBrkCop, kBool, kPrefsSect, _T("disasm-onebytebrkcop") }, //{ kPrEOLConvRaw, kBool, kPrefsSect, _T("eol-conv-raw") }, { kPrConvTextEOL_HA, kBool, kPrefsSect, _T("conv-eol-ha") }, { kPrConvPascalText, kBool, kPrefsSect, _T("conv-pascal-text") }, { kPrConvPascalCode, kBool, kPrefsSect, _T("conv-pascal-code") }, { kPrConvCPMText, kBool, kPrefsSect, _T("conv-cpm-text") }, { kPrConvApplesoft, kBool, kPrefsSect, _T("conv-applesoft") }, { kPrConvInteger, kBool, kPrefsSect, _T("conv-integer") }, { kPrConvBusiness, kBool, kPrefsSect, _T("conv-business") }, { kPrConvGWP, kBool, kPrefsSect, _T("conv-gwp") }, { kPrConvText8, kBool, kPrefsSect, _T("conv-text8") }, { kPrConvAWP, kBool, kPrefsSect, _T("conv-awp") }, { kPrConvADB, kBool, kPrefsSect, _T("conv-adb") }, { kPrConvASP, kBool, kPrefsSect, _T("conv-asp") }, { kPrConvSCAssem, kBool, kPrefsSect, _T("conv-scassem") }, { kPrConvDisasm, kBool, kPrefsSect, _T("conv-disasm") }, { kPrConvHiRes, kBool, kPrefsSect, _T("conv-hi-res") }, { kPrConvDHR, kBool, kPrefsSect, _T("conv-dhr") }, { kPrConvSHR, kBool, kPrefsSect, _T("conv-shr") }, { kPrConvPrintShop, kBool, kPrefsSect, _T("conv-print-shop") }, { kPrConvMacPaint, kBool, kPrefsSect, _T("conv-mac-paint") }, { kPrConvProDOSFolder, kBool, kPrefsSect, _T("conv-prodos-folder") }, { kPrConvResources, kBool, kPrefsSect, _T("conv-resources") }, { kPrTempPath, kString, kPrefsSect, _T("temp-path") }, { kPrExtViewerExts, kString, kPrefsSect, _T("extviewer-exts") }, { kPrLastOpenFilterIndex, kLong, kMiscSect, _T("open-filter-index") }, /**/ { kPrefNumLastRegistry, kPTNone, nil, nil }, { kPrViewTextTypeFace, kString, nil, nil }, { kPrViewTextPointSize, kLong, nil, nil }, { kPrFileViewerWidth, kLong, nil, nil }, { kPrFileViewerHeight, kLong, nil, nil }, { kPrDiskImageCreateFormat, kLong, nil, nil }, }; /* * Constructor. There should be only one Preferences object in the * application, so this should only be run once. */ Preferences::Preferences(void) { WMSG0("Initializing Preferences\n"); ScanPrefMaps(); // sanity-check the table memset(fValues, 0, sizeof(fValues)); SetPrefBool(kPrAddIncludeSubFolders, true); SetPrefBool(kPrAddStripFolderNames, false); SetPrefBool(kPrAddOverwriteExisting, false); SetPrefLong(kPrAddTypePreservation, 1); // kPreserveTypes SetPrefLong(kPrAddConvEOL, 1); // kConvEOLType InitFolders(); // set default add/extract folders; overriden by reg SetPrefLong(kPrExtractConvEOL, 0); // kConvEOLNone SetPrefBool(kPrExtractConvHighASCII, true); SetPrefBool(kPrExtractIncludeData, true); SetPrefBool(kPrExtractIncludeRsrc, false); SetPrefBool(kPrExtractIncludeDisk, true); SetPrefBool(kPrExtractEnableReformat, false); SetPrefBool(kPrExtractDiskTo2MG, false); SetPrefBool(kPrExtractAddTypePreservation, true); SetPrefBool(kPrExtractAddExtension, false); SetPrefBool(kPrExtractStripFolderNames, false); SetPrefBool(kPrExtractOverwriteExisting, false); // SetPrefBool(kPrViewIncludeDataForks, true); // SetPrefBool(kPrViewIncludeRsrcForks, false); // SetPrefBool(kPrViewIncludeDiskImages, false); // SetPrefBool(kPrViewIncludeComments, false); SetPrefBool(kPrConvFileEmptyFolders, true); // string kPrOpenArchiveFolder // string kPrAddFileFolder // string kPrExtractFileFolder SetPrefLong(kPrVolumeFilter, 0); //SetPrefBool(kPrVolumeReadOnly, true); SetPrefLong(kPrCassetteAlgorithm, 0); // string kPrOpenWAVFolder SetPrefBool(kPrMimicShrinkIt, false); SetPrefBool(kPrBadMacSHK, false); SetPrefBool(kPrReduceSHKErrorChecks, false); SetPrefBool(kPrCoerceDOSFilenames, false); SetPrefBool(kPrSpacesToUnder, false); SetPrefBool(kPrPasteJunkPaths, true); SetPrefBool(kPrBeepOnSuccess, true); SetPrefBool(kPrQueryImageFormat, false); SetPrefBool(kPrOpenVolumeRO, true); SetPrefBool(kPrOpenVolumePhys0, false); SetPrefBool(kPrProDOSAllowLower, false); SetPrefBool(kPrProDOSUseSparse, true); SetPrefLong(kPrCompressionType, DefaultCompressionType()); SetPrefLong(kPrMaxViewFileSize, 1024*1024); // 1MB SetPrefBool(kPrNoWrapText, false); SetPrefBool(kPrHighlightHexDump, false); SetPrefBool(kPrHighlightBASIC, false); SetPrefBool(kPrConvHiResBlackWhite, false); SetPrefLong(kPrConvDHRAlgorithm, 1); // latched SetPrefBool(kPrRelaxGfxTypeCheck, true); SetPrefBool(kPrDisasmOneByteBrkCop, false); //SetPrefBool(kPrEOLConvRaw, true); SetPrefBool(kPrConvTextEOL_HA, true); SetPrefBool(kPrConvPascalText, true); SetPrefBool(kPrConvPascalCode, true); SetPrefBool(kPrConvCPMText, true); SetPrefBool(kPrConvApplesoft, true); SetPrefBool(kPrConvInteger, true); SetPrefBool(kPrConvBusiness, true); SetPrefBool(kPrConvGWP, true); SetPrefBool(kPrConvText8, true); SetPrefBool(kPrConvAWP, true); SetPrefBool(kPrConvADB, true); SetPrefBool(kPrConvASP, true); SetPrefBool(kPrConvSCAssem, true); SetPrefBool(kPrConvDisasm, true); SetPrefBool(kPrConvHiRes, true); SetPrefBool(kPrConvDHR, true); SetPrefBool(kPrConvSHR, true); SetPrefBool(kPrConvPrintShop, true); SetPrefBool(kPrConvMacPaint, true); SetPrefBool(kPrConvProDOSFolder, true); SetPrefBool(kPrConvResources, true); InitTempPath(); // set default for kPrTempPath SetPrefString(kPrExtViewerExts, "gif; jpg; jpeg"); SetPrefLong(kPrLastOpenFilterIndex, 0); SetPrefString(kPrViewTextTypeFace, "Courier New"); SetPrefLong(kPrViewTextPointSize, 10); long width = 680; /* exact width for 80-column text */ long height = 510; /* exact height for file viewer to show IIgs graphic */ if (GetSystemMetrics(SM_CXSCREEN) < width) width = GetSystemMetrics(SM_CXSCREEN); if (GetSystemMetrics(SM_CYSCREEN) < height) height = GetSystemMetrics(SM_CYSCREEN); // may overlap system bar //width = 640; height = 480; SetPrefLong(kPrFileViewerWidth, width); SetPrefLong(kPrFileViewerHeight, height); SetPrefLong(kPrDiskImageCreateFormat, -1); } /* * ========================================================================== * ColumnLayout * ========================================================================== */ /* * Restore column widths. */ void ColumnLayout::LoadFromRegistry(const char* section) { char numBuf[8]; int i; for (i = 0; i < kNumVisibleColumns; i++) { sprintf(numBuf, "%d", i); fColumnWidth[i] = gMyApp.GetProfileInt(section, numBuf, fColumnWidth[i]); fColumnWidth[i] = gMyApp.GetProfileInt(section, numBuf, fColumnWidth[i]); } fSortColumn = gMyApp.GetProfileInt(section, _T("sort-column"), fSortColumn); fAscending = (gMyApp.GetProfileInt(section, _T("ascending"), fAscending) != 0); } /* * Store column widths. */ void ColumnLayout::SaveToRegistry(const char* section) { char numBuf[8]; int i; for (i = 0; i < kNumVisibleColumns; i++) { sprintf(numBuf, "%d", i); gMyApp.WriteProfileInt(section, numBuf, fColumnWidth[i]); } gMyApp.WriteProfileInt(section, _T("sort-column"), fSortColumn); gMyApp.WriteProfileInt(section, _T("ascending"), fAscending); } /* * ========================================================================== * Preferences * ========================================================================== */ /* * Get a default value for the temp path. */ void Preferences::InitTempPath(void) { char buf[MAX_PATH]; DWORD len; CString tempPath; len = ::GetTempPath(sizeof(buf), buf); if (len == 0) { DWORD err = ::GetLastError(); WMSG1("GetTempPath failed, err=%d\n", err); tempPath = kDefaultTempPath; } else if (len >= sizeof(buf)) { /* sheesh! */ WMSG1("GetTempPath wants a %d-byte buffer\n", len); tempPath = kDefaultTempPath; } else { tempPath = buf; } PathName path(tempPath); WMSG1("Temp path is '%s'\n", tempPath); path.SFNToLFN(); tempPath = path.GetPathName(); WMSG1("Temp path (long form) is '%s'\n", tempPath); SetPrefString(kPrTempPath, tempPath); // ::GetFullPathName(fTempPath, sizeof(buf), buf, &foo); // ::SetCurrentDirectory(buf); // ::GetCurrentDirectory(sizeof(buf2), buf2); } /* * Set default values for the various folders. */ void Preferences::InitFolders(void) { CString path; if (GetMyDocuments(&path)) { SetPrefString(kPrOpenArchiveFolder, path); SetPrefString(kPrConvertArchiveFolder, path); SetPrefString(kPrAddFileFolder, path); SetPrefString(kPrExtractFileFolder, path); SetPrefString(kPrOpenWAVFolder, path); } else { char buf[MAX_PATH]; ::GetCurrentDirectory(sizeof(buf), buf); SetPrefString(kPrOpenArchiveFolder, buf); SetPrefString(kPrConvertArchiveFolder, buf); SetPrefString(kPrAddFileFolder, buf); SetPrefString(kPrExtractFileFolder, buf); SetPrefString(kPrOpenWAVFolder, buf); } WMSG1("Default folder is '%s'\n", GetPrefString(kPrExtractFileFolder)); } /* * Get the path to the "My Documents" folder. */ bool Preferences::GetMyDocuments(CString* pPath) { LPITEMIDLIST pidl = nil; LPMALLOC lpMalloc = nil; HRESULT hr; bool result = false; hr = ::SHGetMalloc(&lpMalloc); if (FAILED(hr)) return nil; hr = SHGetSpecialFolderLocation(nil, CSIDL_PERSONAL, &pidl); if (FAILED(hr)) { WMSG0("WARNING: unable to get CSIDL_PERSONAL\n"); goto bail; } result = (Pidl::GetPath(pidl, pPath) != FALSE); if (!result) { WMSG0("WARNING: unable to convert CSIDL_PERSONAL to path\n"); /* fall through with "result" */ } bail: lpMalloc->Free(pidl); lpMalloc->Release(); return result; } /* * Determine the type of compression to use as a default, based on what this * version of NufxLib supports. * * Note this happens *before* the AppInit call, so we should restrict this to * things that are version-safe for all of NufxLib v2.x. */ int Preferences::DefaultCompressionType(void) { if (NufxArchive::IsCompressionSupported(kNuThreadFormatLZW2)) return kNuThreadFormatLZW2; else return kNuThreadFormatUncompressed; } /* * Preference getters and setters. */ bool Preferences::GetPrefBool(PrefNum num) const { if (!ValidateEntry(num, kBool)) return false; //return (bool) (fValues[num]); return (bool) ((long) (fValues[num]) != 0); } void Preferences::SetPrefBool(PrefNum num, bool val) { if (!ValidateEntry(num, kBool)) return; fValues[num] = (void*) val; } long Preferences::GetPrefLong(PrefNum num) const { if (!ValidateEntry(num, kLong)) return -1; return (long) fValues[num]; } void Preferences::SetPrefLong(PrefNum num, long val) { if (!ValidateEntry(num, kLong)) return; fValues[num] = (void*) val; } const char* Preferences::GetPrefString(PrefNum num) const { if (!ValidateEntry(num, kString)) return nil; return (const char*) fValues[num]; } void Preferences::SetPrefString(PrefNum num, const char* str) { if (!ValidateEntry(num, kString)) return; free(fValues[num]); if (str == nil) fValues[num] = nil; else { fValues[num] = new char[strlen(str) +1]; if (fValues[num] != nil) strcpy((char*)fValues[num], str); } } /* * Free storage for any string entries. */ void Preferences::FreeStringValues(void) { int i; for (i = 0; i < kPrefNumLastEntry; i++) { if (fPrefMaps[i].type == kString) { delete[] fValues[i]; } } } /* * Do a quick scan of the PrefMaps to identify duplicate, misplaced, and * missing entries. */ void Preferences::ScanPrefMaps(void) { int i, j; /* scan PrefNum */ for (i = 0; i < kPrefNumLastEntry; i++) { if (fPrefMaps[i].num != i) { WMSG2("HEY: PrefMaps[%d] has num=%d\n", i, fPrefMaps[i].num); ASSERT(false); break; } } /* look for duplicate strings */ for (i = 0; i < kPrefNumLastEntry; i++) { for (j = i+1; j < kPrefNumLastEntry; j++) { if (fPrefMaps[i].registryKey == nil || fPrefMaps[j].registryKey == nil) { continue; } if (strcasecmp(fPrefMaps[i].registryKey, fPrefMaps[j].registryKey) == 0 && strcasecmp(fPrefMaps[i].registrySection, fPrefMaps[j].registrySection) == 0) { WMSG4("HEY: PrefMaps[%d] and [%d] both have '%s'/'%s'\n", i, j, fPrefMaps[i].registrySection, fPrefMaps[i].registryKey); ASSERT(false); break; } } } } /* * Load preferences from the registry. */ int Preferences::LoadFromRegistry(void) { CString sval; bool bval; long lval; WMSG0("Loading preferences from registry\n"); fColumnLayout.LoadFromRegistry(kColumnSect); int i; for (i = 0; i < kPrefNumLastRegistry; i++) { if (fPrefMaps[i].registryKey == nil) continue; switch (fPrefMaps[i].type) { case kBool: bval = GetPrefBool(fPrefMaps[i].num); SetPrefBool(fPrefMaps[i].num, GetBool(fPrefMaps[i].registrySection, fPrefMaps[i].registryKey, bval)); break; case kLong: lval = GetPrefLong(fPrefMaps[i].num); SetPrefLong(fPrefMaps[i].num, GetInt(fPrefMaps[i].registrySection, fPrefMaps[i].registryKey, lval)); break; case kString: sval = GetPrefString(fPrefMaps[i].num); SetPrefString(fPrefMaps[i].num, GetString(fPrefMaps[i].registrySection, fPrefMaps[i].registryKey, sval)); break; default: WMSG2("Invalid type %d on num=%d\n", fPrefMaps[i].type, i); ASSERT(false); break; } } return 0; } /* * Save preferences to the registry. */ int Preferences::SaveToRegistry(void) { WMSG0("Saving preferences to registry\n"); fColumnLayout.SaveToRegistry(kColumnSect); int i; for (i = 0; i < kPrefNumLastRegistry; i++) { if (fPrefMaps[i].registryKey == nil) continue; switch (fPrefMaps[i].type) { case kBool: WriteBool(fPrefMaps[i].registrySection, fPrefMaps[i].registryKey, GetPrefBool(fPrefMaps[i].num)); break; case kLong: WriteInt(fPrefMaps[i].registrySection, fPrefMaps[i].registryKey, GetPrefLong(fPrefMaps[i].num)); break; case kString: WriteString(fPrefMaps[i].registrySection, fPrefMaps[i].registryKey, GetPrefString(fPrefMaps[i].num)); break; default: WMSG2("Invalid type %d on num=%d\n", fPrefMaps[i].type, i); ASSERT(false); break; } } return 0; }