#include #include #include #include #include #include "DSGlobals.h" #include "DSDialogs.h" #include "DSUtilsASG.h" enum { kPrefsDLOG = 149, kPrefsExtensionText = 1, kPrefsCreatorTypeText, kPrefsIconText, kPrefsListUser, kPrefsNewButton, kPrefsEditButton, kPrefsDeleteButton, kPrefsExtensionText2, kPrefsExtensionEdit, kPrefsExtensionStatic, kPrefsCreatorText, kPrefsCreatorEdit, kPrefsCreatorStatic, kPrefsTypeText, kPrefsTypeEdit, kPrefsTypeStatic, kPrefsApplicationText, kPrefsApplicationStatic, kPrefsIconText2, kPrefsIconUser, kPrefsDragAndDropText, kPrefsExampleButton, kPrefsTrashMenu }; static void InitPrefsList(void); static void AllocateIconGWorld(void); static void SetUpForDragging(void); static void UpdateSelection(void); static void UpdateButtons(void); static pascal void ListUserItem(DialogPtr theDialog, short theItem); static pascal void IconUserItem(DialogPtr theDialog, short theItem); static OSErr FindIcon(OSType creator, OSType type); static void EraseGWorld(GWorldPtr theGWorld); static void StartEditing(void); static void StopEditing(void); static void SaveChanges(void); static void SaveResults(void); static void SetExampleType(OSType creator, OSType type); static pascal OSErr DragTracker(DragTrackingMessage message, WindowPtr theWindow, void *handlerRefCon, DragReference theDragRef); static pascal OSErr DragReceiver(WindowPtr theWindow, void *handlerRefCon, DragReference theDragRef); static Boolean IsValidDrag(DragReference theDragRef, HFSFlavor *theFile); static UserItemUPP gListUserItem = nil, gIconUserItem = nil; static DragTrackingHandlerUPP gDragTracker = nil; static DragReceiveHandlerUPP gDragReceiver = nil; static DialogPtr gPrefsDialog = nil; static ListHandle gPrefsList = nil; static GWorldPtr gTheGWorld = nil; static OSErr gIconType = kLargeIcon; static Rect gIconBounds = { 0, 0, 32, 32 }; static Boolean gEditing = false; static Str255 gApplicationName; static char gIconBuffer[1024]; void OpenUserDialog(short menuID, short menuItem) { if (gPrefsDialog) { SelectWindow(gPrefsDialog); return; } gPrefsDialog = GetNewDialog(kPrefsDLOG, nil, (WindowPtr)-1); if (gPrefsDialog) { SetWindowPosition(gPrefsDialog, (*gPrefs)->prefsLoc); ShowWindow(gPrefsDialog); InitPrefsList(); if (gPrefsList) { AllocateIconGWorld(); if (!gIconUserItem) gIconUserItem = NewUserItemProc(IconUserItem); SetItemHandle(gPrefsDialog, kPrefsIconUser, (Handle)gIconUserItem); EnableItem(GetMHandle(kFileNum), 2); SetUpForDragging(); StopEditing(); UpdateSelection(); UpdateButtons(); SetCtlValue((ControlHandle)GetItemHandle(gPrefsDialog, kPrefsTrashMenu), (*gPrefs)->trashSource + 1); } } } void InitPrefsList(void) { Rect itemRect, listRect = { 0, 0, 0, 1 }; Handle itemHandle; Point cellSize; short itemType; GetDItem(gPrefsDialog, kPrefsListUser, &itemType, &itemHandle, &itemRect); itemRect.right -= 16; cellSize.v = 32 + 2; cellSize.h = itemRect.right - itemRect.left; gPrefsList = LNew(&itemRect, &listRect, cellSize, 128, gPrefsDialog, false, false, false, true); if (gPrefsList) { int count = *(short *)*gMapResource, offset = 0; Cell theCell = { 0, 0 }; (*gPrefsList)->selFlags = lOnlyOne + lNoNilHilite; LAddRow(count, 32767, gPrefsList); offset += 2; while (count--) { char data[16]; BlockMove(*gMapResource + offset, data, 16); LSetCell(data, 16, theCell, gPrefsList); theCell.v++; offset += 16; } } if (!gListUserItem) gListUserItem = NewUserItemProc(ListUserItem); SetItemHandle(gPrefsDialog, kPrefsListUser, (Handle)gListUserItem); LDoDraw(true, gPrefsList); } void AllocateIconGWorld(void) { short depth; if (((CGrafPtr)gPrefsDialog)->portVersion & 0xc000) { GDHandle mostDevice; GrafPtr oldPort; Rect globalRect; GetPort(&oldPort); SetPort(gPrefsDialog); globalRect = gPrefsDialog->portRect; LocalToGlobal((Point *)&globalRect.top); LocalToGlobal((Point *)&globalRect.bottom); mostDevice = GetMaxDevice(&globalRect); depth = (*(*mostDevice)->gdPMap)->pixelSize; if (depth == 4) gIconType = kLarge4BitIcon, depth = 4; else if (depth > 4) gIconType = kLarge8BitIcon, depth = 8; else gIconType = kLargeIcon, depth = 1; SetPort(oldPort); } else gIconType = kLargeIcon, depth = 1; OSErr theErr = NewGWorld(&gTheGWorld, depth, &gIconBounds, nil, nil, 0); if (theErr != noErr || !gTheGWorld) theErr = NewGWorld(&gTheGWorld, depth, &gIconBounds, nil, nil, useTempMem); } void SetUpForDragging(void) { long resp; if (Gestalt(gestaltDragMgrAttr, &resp) == noErr && (resp & (1L << gestaltDragMgrPresent)) #if defined(powerc) || defined(__powerc) && (Ptr)InstallTrackingHandler != kUnresolvedSymbolAddress #endif ) { if (!gDragTracker) { gDragTracker = NewDragTrackingHandlerProc(DragTracker); gDragReceiver = NewDragReceiveHandlerProc(DragReceiver); } InstallTrackingHandler(gDragTracker, gPrefsDialog, 0); InstallReceiveHandler(gDragReceiver, gPrefsDialog, 0); } } void DoUserDialog(DialogPtr theDialog, short itemHit) { static char defaultData[16] = { 4,'.','N','E','W',0, '?','?','?','?', '?','?','?','?', 0,0 }; static Str255 lastExtension, lastCreator, lastType; static short lastSelStart, lastSelEnd, lastItem; StandardFileReply reply; Cell theCell, tempCell; EventRecord theEvent; SFTypeList theTypes; Str255 string; switch (itemHit) { case kPrefsListUser: if (gEditing) SaveChanges(), StopEditing(); EventAvail(0, &theEvent); SetPort(theDialog); GlobalToLocal(&theEvent.where); Boolean dClick = LClick(theEvent.where, theEvent.modifiers, gPrefsList); UpdateSelection(); UpdateButtons(); if (dClick) StartEditing(); break; case kPrefsNewButton: if (gEditing) SaveChanges(), StopEditing(); theCell.v = LAddRow(1, 32767, gPrefsList); theCell.h = 0; tempCell.h = tempCell.v = 0; while (LGetSelect(true, &tempCell, gPrefsList)) LSetSelect(false, tempCell, gPrefsList); LSetCell(defaultData, 16, theCell, gPrefsList); LSetSelect(true, theCell, gPrefsList); LAutoScroll(gPrefsList); UpdateSelection(); StartEditing(); break; case kPrefsEditButton: if (!gEditing) StartEditing(); else { SaveChanges(), StopEditing(); UpdateSelection(); } break; case kPrefsDeleteButton: if (gEditing) StopEditing(); theCell.h = theCell.v = 0; LGetSelect(true, &theCell, gPrefsList); LDelRow(1, theCell.v, gPrefsList); if (theCell.v >= (*gPrefsList)->dataBounds.bottom) theCell.v--; LSetSelect(true, theCell, gPrefsList); UpdateSelection(); UpdateButtons(); lastItem = kPrefsDeleteButton; break; case kPrefsExtensionEdit: GetIText(GetItemHandle(gPrefsDialog, kPrefsExtensionEdit), string); if (*string > 5) { SysBeep(1); SetIText(GetItemHandle(gPrefsDialog, kPrefsExtensionEdit), lastExtension); SelIText(gPrefsDialog, kPrefsExtensionEdit, lastSelStart, lastSelEnd); } break; case kPrefsCreatorEdit: GetIText(GetItemHandle(gPrefsDialog, kPrefsCreatorEdit), string); if (*string > 4) { SysBeep(1); SetIText(GetItemHandle(gPrefsDialog, kPrefsCreatorEdit), lastCreator); SelIText(gPrefsDialog, kPrefsCreatorEdit, lastSelStart, lastSelEnd); } break; case kPrefsTypeEdit: GetIText(GetItemHandle(gPrefsDialog, kPrefsTypeEdit), string); if (*string > 4) { SysBeep(1); SetIText(GetItemHandle(gPrefsDialog, kPrefsTypeEdit), lastType); SelIText(gPrefsDialog, kPrefsTypeEdit, lastSelStart, lastSelEnd); } break; case kPrefsTrashMenu: (*gPrefs)->trashSource = GetCtlValue((ControlHandle)GetItemHandle(gPrefsDialog, kPrefsTrashMenu)) - 1; UpdateButtons(); break; case kPrefsExampleButton: StandardGetFile(nil, -1, theTypes, &reply); if (reply.sfGood) { FInfo theInfo; FSpGetFInfo(&reply.sfFile, &theInfo); SetExampleType(theInfo.fdCreator, theInfo.fdType); } break; } if (itemHit != lastItem && (lastItem == kPrefsExtensionEdit || lastItem == kPrefsTypeEdit || lastItem == kPrefsCreatorEdit) && (itemHit == kPrefsExtensionEdit || itemHit == kPrefsTypeEdit || itemHit == kPrefsCreatorEdit)) { SaveChanges(); UpdateSelection(); } GetIText(GetItemHandle(gPrefsDialog, kPrefsExtensionEdit), lastExtension); GetIText(GetItemHandle(gPrefsDialog, kPrefsCreatorEdit), lastCreator); GetIText(GetItemHandle(gPrefsDialog, kPrefsTypeEdit), lastType); lastSelStart = (*((DialogPeek)gPrefsDialog)->textH)->selStart; lastSelEnd = (*((DialogPeek)gPrefsDialog)->textH)->selEnd; lastItem = itemHit; } void UpdateButtons(void) { if (gPrefsList) { Cell theCell = { 0, 0 }; Boolean selected = LGetSelect(true, &theCell, gPrefsList); HiliteDControl(gPrefsDialog, kPrefsNewButton, 0); if (gEditing) SetCTitle((ControlHandle)GetItemHandle(gPrefsDialog, kPrefsEditButton), "\pDone"); else SetCTitle((ControlHandle)GetItemHandle(gPrefsDialog, kPrefsEditButton), "\pEdit"); HiliteDControl(gPrefsDialog, kPrefsEditButton, (selected || gEditing) ? 0 : 255); HiliteDControl(gPrefsDialog, kPrefsDeleteButton, selected ? 0 : 255); } else { HiliteDControl(gPrefsDialog, kPrefsNewButton, 255); HiliteDControl(gPrefsDialog, kPrefsEditButton, 255); HiliteDControl(gPrefsDialog, kPrefsDeleteButton, 255); } } void CloseUserDialog(DialogPtr theDialog) { Point thePoint; if (gPrefsDialog && theDialog == gPrefsDialog) { DisableItem(GetMHandle(kFileNum), 2); if (gEditing) SaveChanges(), StopEditing(); SaveResults(); if (gPrefsList) LDispose(gPrefsList), gPrefsList = nil; if (gTheGWorld) DisposeGWorld(gTheGWorld), gTheGWorld = nil; GetWindowPosition(gPrefsDialog, &thePoint); (*gPrefs)->prefsLoc = thePoint; SavePrefs(); DisposeDialog(gPrefsDialog); gPrefsDialog = nil; } } void UserDialogActivate(DialogPtr theDialog, Boolean nowActive) { ProcessSerialNumber thePSN, selfPSN = { 0, kCurrentProcess }; GetFrontProcess(&thePSN); Boolean inBackground; SameProcess(&selfPSN, &thePSN, &inBackground); inBackground = !inBackground; if (gPrefsDialog && theDialog == gPrefsDialog) { LActivate(nowActive && !inBackground, gPrefsList); } } void UpdateSelection(void) { short dataLen = 16, itemType; Cell theCell = { 0, 0 }; Handle itemHandle; Rect itemRect; char data[16]; if (!gPrefsList) return; SetPort(gPrefsDialog); if (LGetSelect(true, &theCell, gPrefsList)) { char string[5] = "\p "; LGetCell(data, &dataLen, theCell, gPrefsList); SetIText(GetItemHandle(gPrefsDialog, kPrefsExtensionStatic), (StringPtr)data); *(long *)&string[1] = *(long *)&data[10]; SetIText(GetItemHandle(gPrefsDialog, kPrefsCreatorStatic), (StringPtr)string); *(long *)&string[1] = *(long *)&data[6]; SetIText(GetItemHandle(gPrefsDialog, kPrefsTypeStatic), (StringPtr)string); if (FindIcon(*(long *)&data[10], *(long *)&data[6]) != noErr) EraseGWorld(gTheGWorld); SetIText(GetItemHandle(gPrefsDialog, kPrefsApplicationStatic), gApplicationName); } else { SetIText(GetItemHandle(gPrefsDialog, kPrefsExtensionStatic), "\p"); SetIText(GetItemHandle(gPrefsDialog, kPrefsCreatorStatic), "\p"); SetIText(GetItemHandle(gPrefsDialog, kPrefsTypeStatic), "\p"); SetIText(GetItemHandle(gPrefsDialog, kPrefsApplicationStatic), "\p"); EraseGWorld(gTheGWorld); } GetDItem(gPrefsDialog, kPrefsIconUser, &itemType, &itemHandle, &itemRect); InvalRect(&itemRect); GetDItem(gPrefsDialog, kPrefsListUser, &itemType, &itemHandle, &itemRect); } pascal void ListUserItem(DialogPtr theDialog, short theItem) { Handle itemHandle; short itemType; Rect itemRect; SetPort(theDialog); GetDItem(gPrefsDialog, theItem, &itemType, &itemHandle, &itemRect); if (gPrefsList) LUpdate(theDialog->visRgn, gPrefsList); InsetRect(&itemRect, -1, -1); itemRect.right--; FrameRect(&itemRect); } pascal void IconUserItem(DialogPtr theDialog, short theItem) { PixMapHandle thePixMap = GetGWorldPixMap(gTheGWorld); Handle itemHandle; short itemType; Rect itemRect; SetPort(theDialog); GetDItem(gPrefsDialog, theItem, &itemType, &itemHandle, &itemRect); if (gEditing) PenPat(&qd.black); else PenPat(&qd.white); FrameRect(&itemRect); InsetRect(&itemRect, 4, 4); PenPat(&qd.black); LockPixels(thePixMap); CopyBits((BitMap *)*thePixMap, &(*gPrefsList)->port->portBits, &gIconBounds, &itemRect, srcCopy, nil); UnlockPixels(thePixMap); } OSErr FindIcon(OSType creator, OSType type) { ParamBlockRec vol; DTPBRec dt; Str255 path; OSErr theErr; if (!gTheGWorld) return memFullErr; *gApplicationName = 0; vol.volumeParam.ioCompletion = nil; vol.volumeParam.ioVolIndex = 1; vol.volumeParam.ioNamePtr = path; while (true) { vol.volumeParam.ioVRefNum = 0; theErr = PBGetVInfoSync(&vol); if (theErr != noErr) break; dt.ioVRefNum = vol.volumeParam.ioVRefNum; dt.ioNamePtr = path; theErr = PBDTGetPath(&dt); if (theErr != noErr) continue; dt.ioCompletion = nil; dt.ioDTBuffer = gIconBuffer; dt.ioDTReqCount = 1024; dt.ioIconType = gIconType; dt.ioFileCreator = creator; dt.ioFileType = type; theErr = PBDTGetIconSync(&dt); if (theErr == noErr && gTheGWorld) { PixMapHandle thePixMap = GetGWorldPixMap(gTheGWorld); char *src, *dst; short row, size; LockPixels(thePixMap); src = gIconBuffer; dst = GetPixBaseAddr(thePixMap); size = 32 * (*thePixMap)->pixelSize / 8; for (row = 0; row < 32; row++) { BlockMove(src, dst, size); src += size; dst += (*thePixMap)->rowBytes & 0x3fff; } UnlockPixels(thePixMap); dt.ioNamePtr = gApplicationName; dt.ioIndex = 0; PBDTGetAPPLSync(&dt); return noErr; } vol.volumeParam.ioVolIndex++; } return theErr; } void EraseGWorld(GWorldPtr theGWorld) { GDHandle oldDevice; GWorldPtr oldPort; PixMapHandle thePixMap = GetGWorldPixMap(theGWorld); LockPixels(thePixMap); GetGWorld(&oldPort, &oldDevice); SetGWorld(gTheGWorld, nil); EraseRect(&gTheGWorld->portRect); SetGWorld(oldPort, oldDevice); UnlockPixels(thePixMap); } void StartEditing(void) { Handle itemHandle; Str255 theString; short itemType; Rect itemRect; GetIText(GetItemHandle(gPrefsDialog, kPrefsExtensionStatic), theString); SetIText(GetItemHandle(gPrefsDialog, kPrefsExtensionEdit), theString); GetIText(GetItemHandle(gPrefsDialog, kPrefsCreatorStatic), theString); SetIText(GetItemHandle(gPrefsDialog, kPrefsCreatorEdit), theString); GetIText(GetItemHandle(gPrefsDialog, kPrefsTypeStatic), theString); SetIText(GetItemHandle(gPrefsDialog, kPrefsTypeEdit), theString); HideDItem(gPrefsDialog, kPrefsExtensionStatic); ShowDItem(gPrefsDialog, kPrefsExtensionEdit); SelIText(gPrefsDialog, kPrefsExtensionEdit, 0, 32767); HideDItem(gPrefsDialog, kPrefsCreatorStatic); ShowDItem(gPrefsDialog, kPrefsCreatorEdit); HideDItem(gPrefsDialog, kPrefsTypeStatic); ShowDItem(gPrefsDialog, kPrefsTypeEdit); if (gDragTracker) ShowDItem(gPrefsDialog, kPrefsDragAndDropText); HiliteDControl(gPrefsDialog, kPrefsExampleButton, 0); gEditing = true; SetPort(gPrefsDialog); GetDItem(gPrefsDialog, kPrefsIconUser, &itemType, &itemHandle, &itemRect); InvalRect(&itemRect); UpdateButtons(); } void StopEditing(void) { Handle itemHandle; Str255 theString; short itemType; Rect itemRect; GetIText(GetItemHandle(gPrefsDialog, kPrefsExtensionEdit), theString); SetIText(GetItemHandle(gPrefsDialog, kPrefsExtensionStatic), theString); GetIText(GetItemHandle(gPrefsDialog, kPrefsCreatorEdit), theString); SetIText(GetItemHandle(gPrefsDialog, kPrefsCreatorStatic), theString); GetIText(GetItemHandle(gPrefsDialog, kPrefsTypeEdit), theString); SetIText(GetItemHandle(gPrefsDialog, kPrefsTypeStatic), theString); HideDItem(gPrefsDialog, kPrefsExtensionEdit); ShowDItem(gPrefsDialog, kPrefsExtensionStatic); HideDItem(gPrefsDialog, kPrefsCreatorEdit); ShowDItem(gPrefsDialog, kPrefsCreatorStatic); HideDItem(gPrefsDialog, kPrefsTypeEdit); ShowDItem(gPrefsDialog, kPrefsTypeStatic); HideDItem(gPrefsDialog, kPrefsDragAndDropText); HiliteDControl(gPrefsDialog, kPrefsExampleButton, 255); gEditing = false; SetPort(gPrefsDialog); GetDItem(gPrefsDialog, kPrefsIconUser, &itemType, &itemHandle, &itemRect); InvalRect(&itemRect); UpdateButtons(); } void SaveChanges(void) { Cell theCell = { 0, 0 }; Str255 theString; char data[16]; short i; GetIText(GetItemHandle(gPrefsDialog, kPrefsExtensionEdit), theString); for (i = 1; i <= *theString; i++) if (theString[i] >= 'a' && theString[i] <= 'z') theString[i] += 'A' - 'a'; SetIText(GetItemHandle(gPrefsDialog, kPrefsExtensionEdit), theString); data[0] = (*theString <= 5) ? *theString : 5; *(long *)&data[1] = *(long *)&theString[1]; data[5] = theString[5]; GetIText(GetItemHandle(gPrefsDialog, kPrefsCreatorEdit), theString); *(long *)&data[10] = *(long *)&theString[1]; GetIText(GetItemHandle(gPrefsDialog, kPrefsTypeEdit), theString); *(long *)&data[6] = *(long *)&theString[1]; LGetSelect(true, &theCell, gPrefsList); LSetCell(data, 16, theCell, gPrefsList); } void SaveResults(void) { if (gPrefsList) { short count = (*gPrefsList)->dataBounds.bottom - (*gPrefsList)->dataBounds.top; Handle theHandle = NewHandle(2 + count * 16); if (theHandle) { char data[16]; Cell theCell = { 0, 0 }; *(short *)*theHandle = count; for (theCell.v = 0; theCell.v < count; theCell.v++) { short len = 16; LGetCell(data, &len, theCell, gPrefsList); BlockMove(data, *theHandle + 2 + theCell.v * 16, 16); } DisposeHandle(gMapResource); gMapResource = theHandle; } else SysBeep(1); } } pascal OSErr DragTracker(DragTrackingMessage message, WindowPtr theWindow, void *handlerRefCon, DragReference theDragRef) { static Boolean hilited = false; HFSFlavor theFile; if (message == dragTrackingInWindow || message == dragTrackingLeaveWindow) if (IsValidDrag(theDragRef, &theFile)) { Handle itemHandle; GrafPtr oldPort; short itemType; Rect itemRect; Point where; GetDItem(gPrefsDialog, kPrefsIconUser, &itemType, &itemHandle, &itemRect); GetDragMouse(theDragRef, &where, nil); GetPort(&oldPort); SetPort(gPrefsDialog); GlobalToLocal(&where); SetPort(oldPort); if (PtInRect(where, &itemRect) && message == dragTrackingInWindow) { RgnHandle theRgn = NewRgn(); if (theRgn) { InsetRect(&itemRect, 1, 1); RectRgn(theRgn, &itemRect); ShowDragHilite(theDragRef, theRgn, true), hilited = true; DisposeRgn(theRgn); } } else if (hilited || message == dragTrackingLeaveWindow) HideDragHilite(theDragRef), hilited = false; } return noErr; } pascal OSErr DragReceiver(WindowPtr theWindow, void *handlerRefCon, DragReference theDragRef) { Boolean wasAliased, isFolder; HFSFlavor theFile; OSErr theErr; if (IsValidDrag(theDragRef, &theFile)) { Handle itemHandle; GrafPtr oldPort; short itemType; Rect itemRect; Point where; GetDItem(gPrefsDialog, kPrefsIconUser, &itemType, &itemHandle, &itemRect); GetDragMouse(theDragRef, &where, nil); GetPort(&oldPort); SetPort(gPrefsDialog); GlobalToLocal(&where); SetPort(oldPort); if (PtInRect(where, &itemRect)) { theErr = ResolveAliasFile(&theFile.fileSpec, true, &isFolder, &wasAliased); if (theErr == noErr && !isFolder) { SetExampleType(theFile.fileCreator, theFile.fileType); return noErr; } } } return dragNotAcceptedErr; } void SetExampleType(OSType creator, OSType type) { char string[5] = "\p "; *(long *)&string[1] = type; SetIText(GetItemHandle(gPrefsDialog, kPrefsTypeEdit), (StringPtr)string); *(long *)&string[1] = creator; SetIText(GetItemHandle(gPrefsDialog, kPrefsCreatorEdit), (StringPtr)string); SaveChanges(); UpdateSelection(); } Boolean IsValidDrag(DragReference theDragRef, HFSFlavor *theFile) { Size theSize = sizeof(HFSFlavor); ItemReference theItem; unsigned short count; OSErr theErr; if (!gEditing) return false; theErr = CountDragItems(theDragRef, &count); if (theErr == noErr && count == 1) { theErr = GetDragItemReferenceNumber(theDragRef, 1, &theItem); if (theErr == noErr) { theErr = GetFlavorData(theDragRef, theItem, flavorTypeHFS, theFile, &theSize, 0); if (theErr == noErr) return true; } } return false; }