home *** CD-ROM | disk | FTP | other *** search
- {$I-}
- {****************************************************}
- {CodeSuckerFKEY.p }
- {}
- {Written using Think Pascal v3.0}
- {Requires at least System 6 to run}
- {}
- {Main body for FKEY, a utility that copies active (application) resources to file}
- {}
- {⌐ 1991 Mike van Kleef - All rights Reserved}
- {----------------------------------------------------}
- {Address (mail & network) until September 1992 : }
- { 42 Melford Road, London, E11-4PS, England}
- { vankleef@uk.ac.qmc.dcs [Queen Mary College, London] }
- {Address after September 1992 :}
- { Flat 5, 4 St. Quintin Ave., London, W10-6NU, England}
- {----------------------------------------------------}
- {CodeSucker is distributed in the hope that it will be useful , but WITHOUT ANY WARRANTY}
- {Absolutely no-one on Earth accepts responsibility for the consequences of using this program}
- {Everyone is hereby granted permission to delete, copy, modify & redistribute CodeSucker}
- {}
- {Version History}
- {1/6/91 - CodeSucker program inception}
- {12/6/91 - v0.9 Normal unsorted lists.}
- { Creates a local list of open resource files by reading the FCB buffer on startup}
- {15/6/91 - v0.95 Added BubbleSort sorting to Resource types list}
- {18/6/91 - v1.0 Replaced slow BubbleSort with faster QuickSort}
- { Removed local files list: open resource files now continuously accessed through the FCB buffer}
- { Cleaned up minor bug that sometimes caused a FONT change in the lists upon scrolling}
- {20/6/91 - v1.01 Added sorting to Resource ID list}
- {26/6/91 - v1.02 Added 'Copy resource flags' option in Save menu}
- {Last Change 12/12/91}
- {****************************************************}
-
- unit CodeSuckerFKEY;
-
- interface
-
- uses
- SysEqu, {Contains System Globals}
- GlobalRoutines, {Some independent routines: FCB buffer things}
- CodeSuckerList, {List manager things}
- ResourceBits; {Routines regarding resource management/Filing etc}
-
- procedure Main; {Parameterless entry-Point for FKEY}
-
- {-----------------------------------------}
- implementation
-
- procedure Main;
-
- const
- {File Popup menu}
- FileMenuID = 9998; {ID for the file popUp menu}
- FileMenuTitle = 'File';
- {Save Popup menu}
- SaveMenuID = 9999; {ID for the Save popUp menu}
- SaveMenuTitle = 'Save';
- SaveRsrcFlags = 1; {Save menu item 1}
- SaveSelected = 3; {Save menu item 3}
- SaveRID = 4; {Save menu item 4}
- SaveRType = 5; {Save menu item 5}
- {Miscellaneous}
- programName = 'CodeSucker v1.02'; {Utility name+version}
-
- var
- oldPen: PenState; {Old Pen}
- oldResFile: Integer; {Resource file that was current before we started}
- myWindow: WindowPtr; {Pointer to main window}
- quitControl: ControlHandle; {Handle to quit button control}
- helpControl: ControlHandle; {Handle to help button control}
- typeList: ListHandle; {List of all resources}
- rsrcList: ListHandle; {List of all resources of a particular type}
- saveMenuHdl: MenuHandle; {Handle to 'save' PopUp menu}
- saveMenuRect: Rect; {Rectangle for 'save' PopUp Menu}
- fileMenuHdl: MenuHandle; {Handle to 'file' PopUp menu}
- fileMenuRect: Rect; {Rectangle for 'file' PopUp Menu}
- currentFileName: str255; {Current resource file Name}
- currentFileRef: Integer; {Current Resource file reference}
- watchHdl: CursHandle; {Handle to the Watch cursor}
- oldResLoad: Integer; {Old value of the SetResLoad function on entering this FKEY}
- copyRsrcFlags: Boolean; {Whether to copy the resource flags when saveing a resource}
-
- {-----------------------------------------}
- {This routine paints the little down-pointing triangle inside the popup menu}
- {h,v=position; size=size of triangle in pixels}
- procedure PaintTriangle (h, v, size: Integer);
- var
- polyHdl: PolyHandle; {temporary structure for drawing the triangle}
- begin
- polyHdl := OpenPoly;
- MoveTo(h, v);
- LineTo(h - size, v - size);
- LineTo(h + size, v - size);
- ClosePoly;
- PaintPoly(polyHdl);
- KillPoly(polyHdl);
- end;
- {-----------------------------------------}
- {Prints the name of the currently selected filename in the window}
- procedure PrintCurrentFile;
- var
- tmpRect: Rect; {Area of previouly displayed filename in window}
- begin
- SetRect(tmpRect, 185, 0, 300, 12);
- EraseRect(tmpRect);
- SetFont('Geneva', 9, []);
- MoveTo(185, 10);
- DrawString(currentFileName);
- end;
-
- {-----------------------------------------}
- {Routine that does the line-drawing in the main window.}
- {Framing the 2 lists, and drawing a nice line across the top of the window}
- procedure FrameLists;
- var
- tmpRect: Rect; {Rectangle surrounding lists}
- begin
- tmpRect := typeList^^.rView;
- InsetRect(tmpRect, -1, -1);
- FrameRect(tmpRect);
- tmpRect := rsrcList^^.rView;
- InsetRect(tmpRect, -1, -1);
- FrameRect(tmpRect);
- ForeColor(blueColor);
- MoveTo(2, 15);
- LineTo(276, 15);
- ForeColor(blackColor);
- end;
-
- {-----------------------------------------}
- procedure DrawPopMenu (tmpRect: Rect; theStr: Str255);
- begin
- EraseRect(tmpRect);
- FrameRect(tmpRect);
- MoveTo(tmpRect.left + 1, tmpRect.bottom);
- LineTo(tmpRect.right, tmpRect.bottom);
- LineTo(tmpRect.right, tmpRect.top + 1);
- SetFont('Chicago', 12, []);
- MoveTo(tmpRect.left + 5, tmpRect.top + 13);
- DrawString(theStr);
- PaintTriangle(tmpRect.left + 42, tmpRect.top + 12, 6);
- end;
-
- {-----------------------------------------}
- {Redraw the controls in the window (Buttons, Lists & Popup Menus)}
- procedure UpdateControls;
- begin
- {Button Controls╔}
- DrawControls(myWindow);
- {List Manager bits╔}
- SetFont('Monaco', 9, []);
- LUpdate(myWindow^.visRgn, typeList);
- LUpdate(myWindow^.visRgn, rsrcList);
- FrameLists;
- {PopUp menu╔}
- DrawPopMenu(fileMenuRect, FileMenuTitle);
- DrawPopMenu(saveMenuRect, SaveMenuTitle);
- end;
-
- {-----------------------------------------}
- {Routine to create the PopupMenu}
- procedure MakeSaveMenu (itsRect: Rect);
- begin
- saveMenuHdl := NewMenu(SaveMenuID, SaveMenuTitle);
- AppendMenu(saveMenuHdl, 'Copy resource flags');
- AppendMenu(saveMenuHdl, '-');
- AppendMenu(saveMenuHdl, 'Selected resource ID╒s╔');
- AppendMenu(saveMenuHdl, 'All resource ID╒s╔');
- AppendMenu(saveMenuHdl, 'All resources types╔');
- saveMenuRect := itsRect;
- saveMenuRect.top := saveMenuRect.top + 2;
- CheckItem(saveMenuHdl, SaveRsrcFlags, copyRsrcFlags);
- end;
-
- {-----------------------------------------}
- {Update the list displaying the occurences of a given resource after either : }
- {the selection of a new resource type OR selection of another resource file}
- procedure DoListUpdate;
- var
- rType: ResType; {Resource Type}
- begin
- SetFont('Monaco', 9, []);
- rType := GetSelectedRsrcItem(typeList); {Get the selected resource Type}
- ChangeRInfoList(rType, rsrcList);
- end;
-
- {-----------------------------------------}
- {Passed in is the command number chosen from the File menu.}
- procedure DoFileMenu (item: Integer);
- var
- fName: Str255; {File name}
- fRef: Integer; {File reference number}
- begin
- GetRsrcFile(fName, fRef, item);
- if fRef <> -1 then {if -1 then couldn't access the file properly}
- begin
- SetCursor(watchHdl^^);
- currentFileName := fName;
- currentFileRef := fRef;
- PrintCurrentFile;
- SetFont('Monaco', 9, []);
- UseResFile(currentFileRef);
- ChangeTypeList(typeList); {Update Resource type list}
- DoListUpdate; {Update list of resource ID's}
- CheckOnlyThisItem(fileMenuHdl, item);
- InitCursor;
- end
- else
- SysBeep(0); {Shouldn't ever get called, as invalid rsrc-file menu-items are disabled}
- end;
-
- {-----------------------------------------}
- {Called when the user has made a selection in the Save Popup menu}
- procedure DoSaveMenu (item: Integer);
- var
- rType: ResType; {Resource Type}
- begin
- rType := GetSelectedRsrcItem(typeList);
- case item of
- SaveRsrcFlags:
- begin
- copyRsrcFlags := not copyRsrcFlags;
- CheckItem(saveMenuHdl, SaveRsrcFlags, copyRsrcFlags);
- end;
- SaveSelected: {Save selected resource ID's}
- DoSave(currentFileRef, currentFileName, rType, ActionSelSave, rsrcList, copyRsrcFlags);
- SaveRID: {Save all resource ID's}
- DoSave(currentFileRef, currentFileName, rType, ActionIDSave, nil, copyRsrcFlags);
- SaveRType: {Save all resources}
- DoSave(currentFileRef, currentFileName, rType, ActionTypeSave, nil, copyRsrcFlags);
- otherwise
- ;
- end;
- end;
-
- {-----------------------------------------}
- {En- or disable certain menu-items in the save menu according to selections}
- {made in the resource lists. Called when user clicks on the Save Popup Menu}
- procedure UpdateSaveMenuItems;
- var
- start: Integer; {Cell to start looking from for enabled cell}
- theCell: Point; {A selected cell in the LDEF list}
- begin
- start := 0;
- if GetSelectedItem(start, theCell, rsrcList) then
- EnableItem(saveMenuHdl, SaveSelected)
- else
- DisableItem(saveMenuHdl, SaveSelected);
- if GetListArea(rsrcList) > 0 then
- EnableItem(saveMenuHdl, SaveRID)
- else
- DisableItem(saveMenuHdl, SaveRID);
- if GetListArea(typeList) > 0 then
- EnableItem(saveMenuHdl, SaveRType)
- else
- DisableItem(saveMenuHdl, SaveRType);
- end;
-
- {-----------------------------------------}
- {This routine is called when the user clicks in the area where the popup menu sits}
- procedure DoPopMenu (itsRect: Rect; whichMenu: MenuHandle; whichID: Integer);
- var
- result: LongInt; {Result from the Popup menu System call}
- menuPoint: Point; {Local coordinate where to place the revealed popUp menu}
- begin
- InsertMenu(whichMenu, -1);
- SetPt(menuPoint, itsRect.left + 1, itsRect.bottom + 1);
- InvertRect(itsRect);
- LocalToGlobal(menuPoint);
- if whichMenu = saveMenuHdl then
- UpdateSaveMenuItems;
- result := PopUpMenuSelect(whichMenu, menuPoint.v, menuPoint.h, 1);
- if result <> 0 then
- if whichMenu = saveMenuHdl then
- DoSaveMenu(LoWord(Result))
- else if whichMenu = fileMenuHdl then
- DoFileMenu(LoWord(Result));
- DrawPopMenu(fileMenuRect, FileMenuTitle);
- DrawPopMenu(saveMenuRect, SaveMenuTitle);
- DeleteMenu(whichID);
- end;
-
- {-----------------------------------------}
- {Routine to create the PopupMenu}
- procedure MakeFileMenu (itsRect: Rect);
- {------}
- procedure BuildFileMenu;
- var
- loop: Integer; {loop through all open resource files}
- fName: str255; {File Name}
- fRef: Integer; {Resource file reference number}
- setUp: Boolean; {True= found 1st enabled item in the popup menu, else False}
- begin
- setUp := False;
- loop := 0;
- repeat
- loop := loop + 1;
- GetRsrcFile(fName, fRef, loop);
- if fRef <> 0 then {File with resource fork found}
- begin
- AppendMenu(fileMenuHdl, fName);
- if (fRef <> -1) and (not SetUp) then {Let this menu item be the default}
- begin
- DoFileMenu(loop);
- currentFileName := fName;
- currentFileRef := fRef;
- PrintCurrentFile;
- setUp := True;
- CheckOnlyThisItem(fileMenuHdl, loop);
- end;
- if fRef = -1 then {Couldn't open this file's resource fork, so disable menu item}
- DisableItem(fileMenuHdl, loop);
- end;
- until fRef = 0;
- end;
- {------}
- begin
- fileMenuHdl := NewMenu(FileMenuID, FileMenuTitle);
- BuildFileMenu;
- fileMenuRect := itsRect;
- fileMenuRect.top := fileMenuRect.top + 2;
- end;
-
- {-----------------------------------------}
- {Print the informative text in the window}
- procedure PrintText;
- begin
- SetFont('Geneva', 12, [Bold]);
- MoveTo(2, 10);
- DrawString(programName);
- SetFont('Geneva', 9, []);
- MoveTo(5, 26);
- DrawString('Resource Types');
- MoveTo(107, 26);
- DrawString('ID# name size');
- MoveTo(135, 10);
- DrawString('Rsrc File :');
- PrintCurrentFile;
- end;
-
- {-----------------------------------------}
- {Create the Button controls}
- procedure MakeControls;
- const
- cTop = 124; {Control top}
- cLeft = 84; {Control left}
- cWidth = 40; {Control width}
- cHeight = 17; {Control height}
- cSpacing = 3; {Control horizontal spacing}
- lTop = 30; {List top}
- lHeight = 88; {List height}
- pWidth = 51; {popmenu width}
- var
- cntlRect: Rect; {Rectangle used to initialise list & control sizes}
- begin
- {Lists}
- SetFont('Monaco', 9, []);
- SetRect(cntlRect, 4, lTop, 62, lTop + lHeight + 22);
- typeList := BuildList(myWindow, cntlRect, 2, lOnlyOne + lNoNilHilite);
- SetRect(cntlRect, 85, lTop, 260, lTop + lHeight);
- rsrcList := BuildList(myWindow, cntlRect, 1, 0);
- FrameLists;
- {Buttons}
- SetRect(cntlRect, cLeft, cTop, cLeft + cWidth, cTop + cHeight);
- helpControl := NewControl(myWindow, cntlRect, 'Help', True, 1, 0, 1, pushButProc, 0);
- with cntlRect do
- begin
- left := right + cSpacing;
- right := left + cWidth;
- end;
- quitControl := NewControl(myWindow, cntlRect, 'Quit', True, 1, 0, 1, pushButProc, 0);
- {Menus}
- with cntlRect do
- begin
- left := right + cSpacing;
- right := left + pWidth;
- top := top - 2;
- end;
- MakeFileMenu(cntlRect);
- with cntlRect do
- begin
- left := right + cSpacing;
- right := left + pWidth;
- end;
- MakeSaveMenu(cntlRect);
- end;
-
- {-----------------------------------------}
- {Create the main display window}
- procedure MakeWindow;
- const
- top = 70; {Top of window}
- left = 80; {Left margin of window}
- bottom = top + 143; {Bottom margin of window}
- right = left + 280; {Right margin of window}
- var
- windRect: Rect; {Rectangle to use for window}
- begin
- SetRect(windRect, left, top, right, bottom);
- myWindow := NewWindow(nil, windRect, '', True, dBoxProc, pointer(-1), True, 0);
- end;
-
- {-----------------------------------------}
- {Redraw the window when an update event occurs}
- procedure DoUpdate;
- begin
- BeginUpdate(myWindow);
- PrintText;
- UpdateControls;
- EndUpdate(myWindow);
- end;
-
- {-----------------------------------------}
- {Give the user some information. Not very elegant...}
- procedure DoHelp;
- const
- s1 = '╞ This utility allows you to save resources belonging to a';
- s2 = ' currently open rsrc file as selected from the File menu.';
- s3 = '╞ Uses : Program debugging; Saving rsrc that change during';
- s4 = ' runtime; Breaking of some forms of CODE protection.';
- s5 = '╞ Instead of copying CODE-0, a cleaned-up $20(A5) jump';
- s6 = ' table is saved with the original CODE-0 header bytes;';
- s7 = '╞ Hold [OPTION] to get faster but unsorted lists.';
- s8 = '╞ Leading ╘Ñ╒ means resource is currently in memory.';
- s9 = '╞ Try saving resources without flags if you get copy errors';
- s10 = 'CodeSucker¬, ⌐1991 Michael van Kleef & Think Pascal¬';
- s11 = ' Comments, bugs, $1 if you think it╒s worth it etc. to :';
- s12 = ' Flat 5, 4 St.Quintin Ave., London W10-6NU, England.';
- hSpacing = 4; {Horizontal text line start}
- vSpacing = 10; {vertical text line spacing}
- vStart = 16; {Vertical coord to start text drawing}
- var
- tmpRect: Rect; {Rectangle within window which to erase}
- found: Boolean; {True=selected cell found in }
- begin
- tmpRect := myWindow^.PortRect;
- tmpRect.Top := tmpRect.top + 16;
- EraseRect(tmpRect);
- SetFont('Geneva', 9, []);
- MoveTo(hSpacing, vStart + (vSpacing * 1));
- DrawString(s1);
- MoveTo(hSpacing, vStart + (vSpacing * 2));
- DrawString(s2);
- MoveTo(hSpacing, vStart + (vSpacing * 3));
- DrawString(s3);
- MoveTo(hSpacing, vStart + (vSpacing * 4));
- DrawString(s4);
- MoveTo(hSpacing, vStart + (vSpacing * 5));
- DrawString(s5);
- MoveTo(hSpacing, vStart + (vSpacing * 6));
- DrawString(s6);
- MoveTo(hSpacing, vStart + (vSpacing * 7));
- DrawString(s7);
- MoveTo(hSpacing, vStart + (vSpacing * 8));
- DrawString(s8);
- MoveTo(hSpacing, vStart + (vSpacing * 9));
- DrawString(s9);
- MoveTo(hSpacing, vStart + (vSpacing * 10));
- DrawString(s10);
- MoveTo(hSpacing, vStart + (vSpacing * 11));
- DrawString(s11);
- MoveTo(hSpacing, vStart + (vSpacing * 12));
- DrawString(s12);
- repeat
- until Button;
- FlushEvents(mDownMask, 0); {Clear any mouseEvents to stop them interfering with the controls}
- EraseRect(tmpRect);
- InvalRect(tmpRect);
- end;
-
- {-----------------------------------------}
- {Routine called when a mouse-down event occurs}
- function DoMouse (theEvent: EventRecord): Boolean;
- var
- whichWindow: WindowPtr; {Handle to window in which clicked}
- answer: Integer; {Answer from FindWindow}
- whichControl: ControlHandle; {Which control clicked in}
- dummy: Boolean; {Unused result from LClick}
- begin
- DoMouse := False;
- answer := FindWindow(theEvent.where, whichWindow);
- if (whichWindow = myWindow) and (answer = inContent) then {Mousedown within our window}
- begin
- SetFont('Monaco', 9, []); {For the lists}
- GlobalToLocal(theEvent.where); {Global mouse coordinate localized to our window}
- if FindControl(theEvent.where, whichWindow, whichControl) <> 0 then {Click in a control}
- begin
- if whichControl = typeList^^.vScroll then {Type list scroll bar}
- dummy := LClick(theEvent.where, theEvent.modifiers, typeList)
- else if whichControl = rsrcList^^.vScroll then {ID# list scroll bar}
- dummy := LClick(theEvent.where, theEvent.modifiers, rsrcList)
- else if TrackControl(whichControl, theEvent.where, nil) <> 0 then
- if whichControl = quitControl then {Quit button}
- DoMouse := True
- else if whichControl = helpControl then {Help button}
- DoHelp
- end;
- if ptInRect(theEvent.where, typeList^^.rView) then {Type list area}
- begin
- dummy := LClick(theEvent.where, theEvent.modifiers, typeList);
- DoListUpdate;
- end;
- if ptInRect(theEvent.where, rsrcList^^.rView) then {ID# list area}
- dummy := LClick(theEvent.where, theEvent.modifiers, rsrcList);
- if PtInRect(theEvent.where, saveMenuRect) then {Save menu area}
- DoPopMenu(saveMenuRect, saveMenuHdl, SaveMenuID);
- if PtInRect(theEvent.where, fileMenuRect) then {File menu area}
- DoPopMenu(fileMenuRect, fileMenuHdl, FileMenuID);
- end
- else
- SysBeep(0); {MouseDown outside our window}
- end;
-
- {-----------------------------------------}
- {Catch bad disks which are inserted whilst we are up and running}
- procedure DiskEvent (whichEvent: EventRecord);
- var
- diskInitPt: Point; {Location of Disk initialisation dialog}
- ignore: integer; {An ignored result from the format routine}
- begin
- SetPt(diskInitPt, 100, 120);
- if (HiWord(whichEvent.message) <> noErr) then
- begin {The disk is bad, and needs (re)formatting}
- DILoad;
- ignore := DIBadMount(diskInitPt, whichEvent.message);
- DIUnload;
- end;
- end;
-
- {-----------------------------------------}
- {Main Event loop which will exit only when 'quit'=True. Sorry, No WaitNextEvent.}
- procedure MainLoop;
- var
- theEvent: EventRecord; {Get events}
- quit: Boolean; {True=Quit, False=Keep on looping}
- begin
- quit := False;
- repeat
- SystemTask;
- if GetNextEvent(everyEvent - keyDownMask, theEvent) then {Disallow keyboard events}
- {Allowing keyDownMask means that all hell breaks loose when multiple}
- {copies of CodeSucker are activated.}
- case theEvent.what of
- mouseDown:
- begin
- quit := DoMouse(theEvent);
- FlushEvents(mDownMask, 0); {Stop multiple clicking}
- end;
- updateEvt, ActivateEvt:
- DoUpdate;
- diskEvt:
- DiskEvent(theEvent); {Trap bad disks}
- otherwise
- end {Case}
- until quit;
- end;
-
- {-----------------------------------------}
- {As this utility is not an application, we have to release all our own data structures}
- procedure DisposeGlobals;
- begin
- LDispose(typeList); {release resource type list}
- LDispose(rsrcList); {release resource ID list}
- DisposeMenu(fileMenuHdl); {release file popup menu}
- DisposeMenu(saveMenuHdl); {release save popup menu}
- CloseWindow(myWindow); {Automatically free's associated Control structures (buttons)}
- end;
-
- {-----------------------------------------}
- begin {Main}
- oldResFile := CurResFile;{Save old resource file}
- oldResLoad := IntPtr(ResLoad)^;
- if oldResLoad = 0 then {Resource loading was disabled, so enable it as we need some system resources (LDEF etc)}
- SetResLoad(True);
- GetPenState(oldPen);
- watchHdl := GetCursor(watchCursor);
- SetCursor(watchHdl^^);
- copyRsrcFlags := True;
- PenNormal;
- MakeWindow;
- SetPort(myWindow);
- MakeControls;
- DoUpdate;
- PenMode(srcCopy);
- InitCursor;
- MainLoop;
- DisposeGlobals;
- SetPenState(oldPen); {Restore old pen}
- if oldResLoad = 0 then {Restore Resload global}
- SetResLoad(False);
- useResFile(oldResFile); {Restore old resource file}
- end; { main }
-
- end. { unit }