program Image; {NIH Image is a public domain program for the Macintosh for acquiring, } {processing, analyzing, editing, printing, and animating 8-bit images.} {Version 1.62, 27 Feb 1996} {Developed using Metrowerks CodeWarrior CW11 PPC and 68K Pascal compilers.} {Author :} {Wayne Rasband} {National Institutes of Health} {email: wayne@codon.nih.gov} {WWW: http://rsb.info.nih.gov/nih-image/} {Anonymous FTP: zippy.nimh.nih.gov} uses Types, Memory, QuickDraw, QuickDrawText, Packages, Menus, Events, Fonts, Scrap, ToolUtils, Resources, Errors, Palettes, StandardFile, Windows, OSUtils, Controls, TextEdit, Files, Dialogs, TextUtils, Finder, MixedMode, Processes, Devices, Balloons, AppleEvents, DiskInit, EPPC, SegLoad, Globals, Utilities, Init, File1, File2, Analysis, Graphics, Edit, Filters, Camera, User, Macros1, Macros2, Stacks, Background, Lut, Projection, Plugins, Text, Math, Registration, {Profiler,} fft, Edm; {Turn off automatic toolbox initialization.} {$I-} {PROCEDURE MacsBug; inline $a9ff;} procedure UpdateOptionsMenu; var CheckIt: boolean; i: integer; begin with info^ do begin CheckItem(OptionsMenuH, GrayscaleItem, (LutMode = Grayscale) or (LutMode = CustomGrayscale)); if LutMode <> PseudoColor then ColorTable := CustomTable; CheckItem(ColorTablesMenuH, SystemPaletteItem, ColorTable = AppleDefault); CheckItem(ColorTablesMenuH, Pseudo20Item, ColorTable = Pseudo20); CheckItem(ColorTablesMenuH, Pseudo32Item, ColorTable = Pseudo32); CheckItem(ColorTablesMenuH, RainbowItem, ColorTable = Rainbow); CheckItem(ColorTablesMenuH, Fire1Item, ColorTable = Fire1); CheckItem(ColorTablesMenuH, Fire2Item, ColorTable = Fire2); CheckItem(ColorTablesMenuH, IceItem, ColorTable = Ice); CheckItem(ColorTablesMenuH, GraysItem, ColorTable = Grays); CheckItem(ColorTablesMenuH, SpectrumItem, ColorTable = Spectrum); SetMenuItem(OptionsMenuH, ScaleToFitItem, info <> NoInfo); CheckIt := ScaleToFitWindow; CheckItem(OptionsMenuH, ScaleToFitItem, CheckIt); CheckItem(OptionsMenuH, ThresholdItem, Thresholding); CheckItem(OptionsMenuH, SliceItem, DensitySlicing); SetMenuItem(OptionsMenuH, PropagateItem, nPics > 1); end; end; procedure UpdateProcessMenu; var ShowItems: boolean; i: integer; str: str255; begin ShowItems := Info <> NoInfo; for i := SmoothItem to FilterItem do SetMenuItem(ProcessMenuH, i, ShowItems); with info^ do if (LutMode = GrayScale) or (LutMode = CustomGrayscale) or DensitySlicing then SetMenuItemText(ProcessMenuH, ApplyItem, 'Apply LUT') else SetMenuItemText(ProcessMenuH, ApplyItem, 'Convert to Grayscale'); if CurrentWindow = TextKind then SetMenuItemText(ProcessMenuH, ConvolveItem, 'Convolve') else SetMenuItemText(ProcessMenuH, ConvolveItem, 'ConvolveÉ'); for i := BinaryItem to FixColorsItem do SetMenuItem(ProcessMenuH, i, ShowItems); NumToString(BinaryCount, str); str := concat('Set Count[', str, ']É'); SetMenuItemText(BinaryMenuH, SetCountItem, str); NumToString(BinaryIterations, str); str := concat('Set Iterations[', str, ']É'); SetMenuItemText(BinaryMenuH, IterationsItem, str); CheckItem(BackgroundMenuH, FasterItem, FasterBackgroundSubtraction); NumToString(BallRadius, str); str := concat('Set Radius[', str, ']É'); SetMenuItemText(BackgroundMenuH, RadiusItem, str); end; procedure UpdateSpecialMenu; var ShowItems: boolean; begin ShowItems := Info <> NoInfo; SetMenuItem(SpecialMenuH, SaveBlankFieldItem, ShowItems); SetMenuItem(SpecialMenuH, PhotoModeItem, ShowItems); if CurrentWindow = TextKind then SetMenuItemText(SpecialMenuH, LoadMacrosItem, 'Load Macros from Window') else SetMenuItemText(SpecialMenuH, LoadMacrosItem, 'Load MacrosÉ') end; procedure UpdateStacksMenu; var ShowItems: boolean; isStack: boolean; begin ShowItems := Info <> NoInfo; SetMenuItem(StacksMenuH, StackFromWindowsItem, nPics > 0); isStack := info^.StackInfo <> nil; SetMenuItem(StacksMenuH, WindowsFromStackItem, isStack); SetMenuItem(StacksMenuH, AddSliceItem, isStack); SetMenuItem(StacksMenuH, DeleteSliceItem, isStack); SetMenuItem(StacksMenuH, NextSliceItem, isStack); SetMenuItem(StacksMenuH, PreviousSliceItem, isStack); SetMenuItem(StacksMenuH, MakeMovieItem, ShowItems); SetMenuItem(StacksMenuH, CaptureFramesItem, ShowItems); SetMenuItem(StacksMenuH, AnimateItem, isStack); SetMenuItem(StacksMenuH, AverageSlicesItem, isStack); SetMenuItem(StacksMenuH, MakeMontageItem, isStack); SetMenuItem(StacksMenuH, RegisterItem, isStack); SetMenuItem(StacksMenuH, CaptureColorItem, ShowItems); SetMenuItem(StacksMenuH, RGBToColorItem, isStack); SetMenuItem(StacksMenuH, ColorToRGBItem, ShowItems and (not isStack)); SetMenuItem(StacksMenuH, RGBToHSVItem, isStack); SetMenuItem(StacksMenuH, ProjectItem, isStack); SetMenuItem(StacksMenuH, ResliceItem, isStack); SetMenuItem(StacksMenuH, StackInfoItem, isStack); end; function AboutFilter (d: DialogPtr; var event: EventRecord; var ItemHit: integer): boolean; { simple filter proc for about box } begin if (event.what in [MouseDown, KeyDown, AutoKey]) then begin AboutFilter := true; ItemHit := OK; end else begin AboutFilter := false; ItemHit := 0; end; end; procedure AboutUProc (d: DialogPtr; item: integer); { About box user proc } var s: str255; saveport: grafptr; VersInfo: str255; begin getport(saveport); setport(d); if (item = MemItem) then begin NumToString(FreeMem div 1024, s); s := concat(s, 'K free'); DrawSItem(MemItem, Geneva, 9, d, s); end else if (item = VersItem) then begin RealToString(version / 100.0, 4, 2, VersInfo); VersInfo := concat('Version ', VersInfo); DrawSItem(VersItem, Geneva, 9, d, VersInfo); end; setport(saveport); end; procedure DoAbout; {About Box by David Powell} var i: integer; d: dialogptr; midscreen: point; r: rect; h: handle; itype: integer; begin if AboutBoxFilterProc=nil then AboutBoxFilterProc:=NewRoutineDescriptor(@AboutFilter, uppModalFilterProcInfo, GetCurrentISA); if AboutBoxUserProc=nil then AboutBoxUserProc:=NewRoutineDescriptor(@AboutUProc, uppUserItemProcInfo, GetCurrentISA); d := getnewdialog(AboutID, nil, pointer(-1)); if (d <> nil) then begin SetPort(d); GetDialogItem(d, VersItem, itype, h, r); SetDialogItem(d, VersItem, itype, handle(AboutBoxUserProc), r); GetDialogItem(d, MemItem, itype, h, r); SetDialogItem(d, MemItem, itype, handle(AboutBoxUserProc), r); ShowWindow(d); repeat ModalDialog(AboutBoxFilterProc, i); until (i = OK); DisposeDialog(d); FlushEvents(EveryEvent, 0); end; end; procedure DoPreferences; const BufferSizeID = 7; CreatorID = 8; ScaleConvolutionsID = 9; InvertValuesID =10; InvertYID = 11; SwitchingID = 12; HighlightID = 13; OscillatingID = 14; FriendlyID = 15; var mylog: DialogPtr; item, i: integer; SaveScaleC: boolean; SaveInvertValues, SaveInvertY, SaveMovies, NewFriendlyMode, okay: boolean; SaveBufferSize: LongInt; SaveCreator: packed array[1..4] of char; tCreator:str255; SaveInfo:InfoPtr; begin InitCursor; if isInvertingFunction then InvertPixelValues:=true; SaveBufferSize := BufferSize; SaveInvertY := InvertYCoordinates; SaveScaleC := ScaleConvolutions; SaveCreator := TextCreator; SaveMovies := OscillatingMovies; NewfriendlyMode := LutFriendlyMode; mylog := GetNewDialog(6000, nil, pointer(-1)); SetDNum(MyLog, BufferSizeID, BufferSize div 1024); SetDlogItem(mylog, ScaleConvolutionsID, ord(ScaleConvolutions)); SetDlogItem(mylog, InvertYID, ord(InvertYCoordinates)); SetDlogItem(mylog, SwitchingID, ord(SwitchLUTOnSuspend)); SetDlogItem(mylog, HighlightID, ord(HighlightMode)); SetDlogItem(mylog, OscillatingID, ord(OscillatingMovies)); SetDlogItem(mylog, FriendlyID, ord(LutFriendlyMode)); SaveInvertValues := InvertPixelValues; if InvertPixelValues then SetDlogItem(mylog, InvertValuesID, 1); tCreator:='1234'; tCreator[1]:=TextCreator[1]; tCreator[2]:=TextCreator[2]; tCreator[3]:=TextCreator[3]; tCreator[4]:=TextCreator[4]; SetDString(mylog, CreatorID, tCreator); repeat ModalDialog(nil, item); if item = BufferSizeID then begin BufferSize := GetDNum(MyLog, BufferSizeID) * 1024; if BufferSize < 1 then begin beep; BufferSize := 1; SetDNum(MyLog, BufferSizeID, BufferSize); end; end; if item = ScaleConvolutionsID then begin ScaleConvolutions := not ScaleConvolutions; SetDlogItem(mylog, ScaleConvolutionsID, ord(ScaleConvolutions)); end; if item = InvertValuesID then begin InvertPixelValues := not InvertPixelValues; SetDlogItem(mylog, InvertValuesID, ord(InvertPixelValues)); end; if item = InvertYID then begin InvertYCoordinates := not InvertYCoordinates; SetDlogItem(mylog, InvertYID, ord(InvertYCoordinates)); end; if item = SwitchingID then begin SwitchLUTOnSuspend := not SwitchLUTOnSuspend; SetDlogItem(mylog, SwitchingID, ord(SwitchLUTOnSuspend)); end; if item = HighlightID then begin HighlightMode := not HighlightMode; SetDlogItem(mylog, HighlightID, ord(HighlightMode)); LoadLUT(info^.ctable); end; if item = CreatorID then begin tCreator := GetDString(mylog, item); if length(tCreator)=4 then begin TextCreator[1]:=tCreator[1]; TextCreator[2]:=tCreator[2]; TextCreator[3]:=tCreator[3]; TextCreator[4]:=tCreator[4]; end; end; if item = OscillatingID then begin OscillatingMovies := not OscillatingMovies; SetDlogItem(mylog, OscillatingID, ord(OscillatingMovies)); end; if item = FriendlyID then begin NewFriendlyMode := not NewFriendlyMode; SetDlogItem(mylog, FriendlyID, ord(NewFriendlyMode)); end; until (item = ok) or (item = cancel); DisposeDialog(mylog); if item = cancel then begin BufferSize := SaveBufferSize; ScaleConvolutions := SaveScaleC; InvertYCoordinates := SaveInvertY; OscillatingMovies := SaveMovies; if PasteControl <> nil then DrawPasteControl; TextCreator := SaveCreator; end else with info^ do begin if InvertPixelValues then begin SaveInfo:=info; for i := 1 to nPics do begin Info := pointer(WindowPeek(PicWindow[i])^.RefCon); if info^.fit=uncalibrated then InvertGrayLevels end; {for} info:=SaveInfo; end else if (InvertPixelValues = false) and SaveInvertValues then begin SaveInfo:=info; for i := 1 to nPics do begin Info := pointer(WindowPeek(PicWindow[i])^.RefCon); if isInvertingFunction then RemoveDensityCalibration; end; {for} info:=SaveInfo; end; end; if BufferSize <> SaveBufferSIze then begin PutError('You must quit and restart NIH Image before the Undo and Clipboard buffer size change will take effect.'); SaveSettings; end; if (NewFriendlyMode <> LutFriendlyMode) then begin if (not LutFriendlyMode) and (ScreenDepth = 8) then begin SaveInfo := Info; Info := noInfo; okay := LoadCLUTResource(AppleDefaultCLUT); Info := SaveInfo; end; LutFriendlyMode := NewFriendlyMode; if ScreenDepth <= 8 then RestoreScreen; UpdateLUT; end; end; procedure UpdateWindowsMenu; var i, n: integer; begin for i := NextImageItem to TileImagesItem do SetMenuItem(WindowsMenuH, i, nPics > 1); for i := SelectToolsItem to SelectResultsItem do CheckItem(WindowsMenuH, i, false); SetMenuItem(WindowsMenuH, SelectHistogramItem, HistoWindow <> nil); SetMenuItem(WindowsMenuH, SelectPlotItem, PlotWindow <> nil); SetMenuItem(WindowsMenuH, SelectResultsItem, ResultsWindow <> nil); for i := 1 to nTextWindows do CheckItem(WindowsMenuH, WindowsMenuItems - 1 + i, false); for i := 1 to nPics do CheckItem(WindowsMenuH, WindowsMenuItems + nTextWindows + i, false); if PasteControl = nil then SetMenuItemText(WindowsMenuH, PasteControlItem, 'Show Paste Control') else SetMenuItemText(WindowsMenuH, PasteControlItem, 'Hide Paste Control'); if CurrentKind < 0 then exit(UpdateWindowsMenu); {System Window} case CurrentKind of ToolKind: CheckItem(WindowsMenuH, SelectToolsItem, true); MapKind: CheckItem(WindowsMenuH, SelectGrayMapItem, true); LUTKind: CheckItem(WindowsMenuH, SelectLutItem, true); InfoKind: CheckItem(WindowsMenuH, SelectInfoItem, true); HistoKind: CheckItem(WindowsMenuH, SelectHistogramItem, true); ProfilePlotKind, CalibrationPLotKind: CheckItem(WindowsMenuH, SelectPlotItem, true); ResultsKind: CheckItem(WindowsMenuH, SelectResultsItem, true); TextKind: begin if TextInfo <> nil then CheckItem(WindowsMenuH, WindowsMenuItems - 1 + TextInfo^.WindowNum, true); end; PicKind: CheckItem(WindowsMenuH, WindowsMenuItems + nTextWindows + info^.PicNum, true); otherwise end; end; procedure CloseAll; FORWARD; procedure DoNew; const ImageID = 4; TextID = 5; WidthID = 6; HeightID = 7; TitleID = 8; var mylog: DialogPtr; item, i: integer; SaveWidth, SaveHeight: integer; SaveTitle: string[31]; okay, OpenImage: boolean; procedure SetButtons; begin SetDlogItem(mylog, ImageID, ord(OpenImage)); SetDlogItem(mylog, TextID, ord(not OpenImage)); end; begin InitCursor; OpenImage := true; SaveWidth := NewPicWidth; SaveHeight := NewPicHeight; SaveTitle := NewTitle; mylog := GetNewDialog(180, nil, pointer(-1)); SetButtons; SetDNum(MyLog, WidthID, NewPicWidth); SelectdialogItemText(MyLog, WidthID, 0, 32767); SetDNum(MyLog, HeightID, NewPicHeight); SetDString(MyLog, TitleID, NewTitle); repeat ModalDialog(nil, item); if item = ImageID then begin OpenImage := true; SetButtons; end; if item = TextID then begin OpenImage := false; SetButtons; end; if item = WidthID then begin NewPicWidth := GetDNum(MyLog, WidthID); if (NewPicWidth < 0) or (NewPicWidth > MaxPicSize) then begin NewPicWidth := SaveWidth; SetDNum(MyLog, WidthID, NewPicWidth); end; end; if item = HeightID then begin NewPicHeight := GetDNum(MyLog, HeightID); if (NewPicHeight < 0) or (NewPicHeight > MaxPicSize) then begin NewPicHeight := SaveHeight; SetDNum(MyLog, HeightID, NewPicHeight); end; end; until (item = ok) or (item = cancel); if item = ok then NewTitle := GetDString(MyLog, TitleID); DisposeDialog(mylog); if NewPicWidth < 32 then NewPicWidth := 32; if NewPicHeight < 1 then NewPicHeight := 1; if item = cancel then begin NewPicWidth := SaveWidth; NewPicHeight := SaveHeight; NewTitle := SaveTitle; exit(DoNew); end; if OpenImage then begin okay := NewPicWindow(NewTitle, NewPicWidth, NewPicHeight); if okay then if info^.PixMapSize > UndoBufSize then PutWarning; end else okay := MakeNewTextWindow(NewTitle, 500, 400); end; procedure DoMenuEvent (MenuChoice: LongInt); var MenuID, MenuItem, i, ignore: integer; name, str: str255; dna, RefNum: integer; ItemName: str255; FontName: str255; ok, isSelection: boolean; NewStyle: StyleItem; t: FateTable; {Only needed for MakeSkeleton} SaveBFInfo: InfoPtr; err: OSErr; begin MenuID := HiWrd(MenuChoice); MenuItem := LoWrd(MenuChoice); case MenuID of AppleMenu: begin if MenuItem = 1 then DoAbout else begin GetMenuItemText(GetMenuHandle(AppleMenu), MenuItem, name); ignore := OpenDeskAcc(name) end; end; FileMenu: begin StopDigitizing; isInsertionPoint := false; case MenuItem of NewItem: DoNew; OpenItem: ok := DoOpen('', 0); ImportItem: ok := ImportFile('', 0); {-} CloseItem: if OptionKeyWasDown and (CurrentWindow <> TextKInd) then CloseAll else DoClose; SaveItem: if OptionKeyWasDown and (info^.StackInfo = nil) and (CurrentWindow <> TextKind) then SaveAll else SaveFile; SaveAsItem: case CurrentWindow of TextKind: SaveTextAs; ResultsKind: Export('', 0); otherwise SaveAs('', 0); end; ExportItem: Export('', 0); {-} RecordPreferencesItem: SaveSettings; RevertItem: with info^ do if DataType = EightBits then RevertToSaved else RescaleToEightBits; DuplicateItem: ok := Duplicate('', false); GetInfoItem: GetInfo; {-} PageSetupItem: if OptionKeyDown then SetHalftone else DoPageSetup; PrintItem: Print(true); {-} QuitItem: finished := true; end; if OpeningRGB then begin ConvertRGBToEightBitColor(true); OpeningRGB := false; end; end; AcquireMenu: RunAcqPlugIn(MenuItem); ExportMenu: RunExportPlugIn(MenuItem); EditMenu: begin StopDigitizing; GetMenuItemText(GetMenuHandle(EditMenu), MenuItem, ItemName); if not SystemEdit(MenuItem - 1) then case MenuItem of UndoItem: DoUndo; {-} CutItem: DoCut; CopyItem: DoCopy; PasteItem: DoPaste; ClearItem: DoClear; {-} FillItem: if CurrentWindow = TextKind then DoFind else SetupOperation(FillItem); InvertItem, DrawBoundaryItem: SetupOperation(MenuItem); DrawScaleItem: DrawScale; {-} SelectAllItem: with info^ do if CurrentWindow = TextKind then SelectAllText else if RoiShowing and EqualRect(RoiRect, PicRect) then KillRoi else SelectAll(true); DeselectItem: KillRoi; ScaleAndRotateItem: ScaleAndRotate; {-} RotateLeftItem: Rotate(RotateLeft); RotateRightItem: Rotate(RotateRight); FlipVerticalItem: FlipOrRotate(FlipVertical); FlipHorizontalItem: FlipOrRotate(FlipHorizontal); {-} UnzoomItem: Unzoom; ShowClipboardItem: ShowClipboard; end; end; OptionsMenu: begin case MenuItem of GrayscaleItem: ResetGrayMap; LutOptionsItem: DoLutOptions; {-} PreferencesItem: DoPreferences; PlotOptionsItem: DoProfilePlotOptions; ScaleToFitItem: ScaleToFit; ThresholdItem: begin if DensitySlicing then DisableDensitySlice; if Info^.Thresholding then DisableThresholding else begin SetupLutUndo; AutoThreshold; end; end; SliceItem: if DensitySlicing then DisableDensitySlice else begin if info^.thresholding then DisableThresholding; EnableDensitySlice; end; end; end; ColorTablesMenu: SwitchColorTables(MenuItem, true); FontMenu: begin GetMenuItemText(FontMenuH, MenuItem, FontName); GetFNum(FontName, CurrentFontID); DisplayText(true); if CurrentWindow = TextKind then ChangeFontOrSize; end; SizeMenu: begin case MenuItem of 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12: CurrentSize := GetFontSize(MenuItem); end; DisplayText(true); if IsInsertionPoint then UpdatePicWindow; if CurrentWindow = TextKind then ChangeFontOrSize; end; StyleMenu: begin case MenuItem of 1: CurrentStyle := []; 2, 3, 4, 5, 6: begin case MenuItem of TxBold: NewStyle := Bold; TxItalic: NewStyle := Italic; TxUnderLine: NewStyle := Underline; TxOutLine: NewStyle := Outline; TxShadow: NewStyle := Shadow; end; if NewStyle in CurrentStyle then CurrentStyle := CurrentStyle - [NewStyle] else CurrentStyle := CurrentStyle + [NewStyle]; end; LeftItem: TextJust := teJustLeft; CenterItem: TextJust := teJustCenter; RightItem: TextJust := teJustRight; NoBackgroundItem: TextBack := NoBack; WithBackgroundItem: TextBack := WithBack; end; {case} DisplayText(true); end; PropagateMenu: DoPropagate(MenuItem); ProcessMenu: begin StopDigitizing; SetupUndo; case MenuItem of SmoothItem: if OptionKeyDown then Filter(UnweightedAvg, 0, t) else Filter(WeightedAvg, 0, t); SharpenItem: Filter(fsharpen, 0, t); ShadowItem: DoShadowFilter; FindEdgesItem: Filter(FindEdges, 0, t); RankItem: DoRankFilter; DitherItem: Filter(Dither, 0, t); ConvolveItem: if CurrentWindow = TextKind then ConvolveUsingText else Convolve('', 0); {-} ImageMathItem: DoImageMath; ApplyItem: if CheckCalibration then ApplyLookupTable; EnhanceItem: EnhanceContrast; EqualizeItem: EqualizeHistogram; FixColorsItem: if not isBinaryImage then FixColors; end; end; FilterMenu: RunFilterPlugin(menuItem); BinaryMenu: case MenuItem of MakeBinaryItem: MakeBinary; ErosionItem: DoErosion; DilationItem: DoDilation; OpeningItem: DoOpening; ClosingItem: DoClosing; SetCountItem: SetBinaryCount; IterationsItem: SetIterations; OutlineItem: filter(OutlineFilter, 0, t); SkeletonizeItem: MakeSkeleton; EDMItem, UltimateItem, WatershedItem: MakeEDM(MenuItem); end; ArithmeticMenu: DoArithmetic(MenuItem, 0); fftMenu: case MenuItem of ForewardFFTItem: doFFT(ForewardFFT); InverseFFTItem: doFFT(InverseFFTWithMask); RedisplayItem: RedisplayPowerSpectrum; SwapItem: doSwapQuadrants; end; BackgroundMenu: DoBackgroundMenuEvent(MenuItem); AnalyzeMenu: begin if MenuItem <> HistogramItem then StopDigitizing; SetupUndo; case MenuItem of MeasureItem: Measure; AnalyzeItem: AnalyzeParticles; ShowItem: ShowResults; OptionsItem: DoMeasurementOptions; HistogramItem: DoHistogram; PlotItem: PlotDensityProfile; PlotSurfaceItem: PlotSurface; {-} SetScaleItem: SetScale; CalibrateItem: Calibrate; RedoItem: RedoMeasurement; DeleteItem: DeleteMeasurement; ResetItem: ResetCounter; RestoreItem: RestoreRoi; MarkItem: MarkSelection(mCount); end; end; SpecialMenu: begin case MenuItem of StartItem: StartDigitizing; AverageItem: AverageFrames; SaveBlankFieldItem: begin SaveBFInfo := BlankFieldInfo; BlankFieldInfo := nil; {Prevents shading correction.} StopDigitizing; BlankFieldInfo := SaveBFInfo; SaveBlankField; end; VideoControlItem: ShowVideoDialog; PhotoModeItem: PhotoMode; LoadMacrosItem: begin LoadMacros; {$ifc not PowerPC} UnloadSeg(@LoadMacros); {$endc} end; otherwise if MenuItem >= FirstMacroItem then RunMacro(MenuItem - FirstMacroItem + 1); {if MenuItem >= FirstMacroItem then begin if ProfilerInit(collectDetailed, bestTimeBase, 50, 25) = noErr then begin RunMacro(MenuItem - FirstMacroItem + 1); err := ProfilerDump('Image.prof'); ProfilerTerm; end; end;} end; end; StacksMenu: begin StopDigitizing; case MenuItem of StackFromWindowsItem: MakeStack; WindowsFromStackItem: MakeWindowsFromStack; AddSliceItem: ok := AddSlice(true); DeleteSliceItem: DeleteSlice; NextSliceItem, PreviousSliceItem: ShowNextSlice(MenuItem); MakeMovieItem: MakeMovie(true); CaptureFramesItem: CaptureFrames; AnimateItem: Animate; AverageSlicesItem: AverageSlices(0, 0); MakeMontageItem: MakeMontage; CaptureColorItem: CaptureColor; RGBToColorItem: ConvertRGBToEightBitColor(false); ColorToRGBItem: ConvertEightBitColorToRGB; RGBToHSVItem: ConvertRGBToHSV; RegisterItem: DoRegister; ProjectItem: Project; ResliceItem: Reslice; StackInfoItem: DoStackInfo; otherwise beep end; end; WindowsMenu: begin if MenuItem <> PasteControlItem then StopDigitizing; case MenuItem of NextImageItem: ShowNextImage; CascadeImagesItem: CascadeImages; TileImagesItem: TileImages; PasteControlItem: if PasteControl = nil then ShowPasteControl else ignore := CloseAWindow(PasteControl); {-} SelectToolsItem: SelectWindow(ToolWindow); SelectGrayMapItem: SelectWindow(MapWindow); SelectLutItem: SelectWindow(LUTWindow); SelectInfoItem: SelectWindow(InfoWindow); SelectHistogramItem: if HistoWindow <> nil then SelectWindow(HistoWindow); SelectPlotItem: if PlotWindow <> nil then SelectWindow(PlotWindow); SelectResultsItem: if ResultsWindow <> nil then SelectWindow(ResultsWindow); {-} otherwise if MenuItem <= (WindowsMenuItems - 1 + nTextWindows) then SelectWindow(TextWindow[MenuItem - (WindowsMenuItems - 1)]) else SelectWindow(PicWindow[MenuItem - (WindowsMenuItems + nTextWindows)]); end; end; UserMenu: DoUserMenuEvent(MenuItem); otherwise end; HiliteMenu(0); RoiUpdateTime := 0; end; procedure DoFreehand; var finish: point; event: EventRecord; wright, wbottom: integer; b: boolean; begin SetPort(info^.wptr); PenPat(AntPattern[PatIndex]); PenSize(1, 1); with info^.wptr^.PortRect do begin wright := right; wbottom := bottom; end; while Button do begin GetMouse(finish); with finish do begin if h < 0 then h := 0; if v < 0 then v := 0; if h > wright then h := wright; if v > wbottom then v := wbottom; if (xCoordinates^[nCoordinates] <> h) or (yCoordinates^[nCoordinates] <> v) then begin if nCoordinates < MaxCoordinates then nCoordinates := nCoordinates + 1 else beep; LineTo(h, v); xCoordinates^[nCoordinates] := h; yCoordinates^[nCoordinates] := v; wait(1); end; {if mouse has moved} end; {with} end; {while Button} end; procedure DoPolygon (start: point); var Finish, OldFinish: point; finished, DoubleClick, done: boolean; ticks, MouseUpTime, LastMouseUpTime: LongInt; wright, wbottom: integer; StartRect: rect; MouseDown, MouseUpEvent: boolean; begin DrawLabels('DX:', 'DY:', 'Length:'); SetPort(info^.wptr); PenMode(PatXor); PenSize(1, 1); if CurrentTool = PolygonTool then begin Pt2Rect(Start, Start, StartRect); InsetRect(StartRect, -4, -4); FrameRect(StartRect); end else SetRect(StartRect, 0, 0, 0, 0); finish := start; finished := false; with info^.wptr^.PortRect do begin wright := right; wbottom := bottom; end; MouseUpTime := 0; done := false; MouseUpEvent := false; MouseDown := button; repeat ShowDxDy(0, 0); repeat OldFinish := finish; GetMouse(finish); with finish do begin if h < 0 then begin h := 0; done := CurrentTool = LineTool; end; if v < 0 then begin v := 0; done := CurrentTool = LineTool; end; if h > wright then begin h := wright; done := CurrentTool = LineTool; end; if v > wbottom then begin v := wbottom; done := CurrentTool = LineTool; end; end; if not EqualPt(finish, OldFinish) then begin ticks := TickCount; repeat until TickCount <> ticks; MoveTo(start.h, start.v); LineTo(OldFinish.h, OldFinish.v); MoveTo(start.h, start.v); LineTo(finish.h, finish.v); ShowDxDy(abs(finish.h - start.h), abs(finish.v - start.v)); end; if button <> MouseDown then begin MouseUpEvent := not button; MouseDown := button; end; until MouseUpEvent; MouseUpEvent := false; LastMouseUpTime := MouseUpTime; MouseUpTime := TickCount; DoubleClick := ((MouseUpTime - LastMouseUpTime) < GetDblTime) and EqualPt(start, finish); if nCoordinates < MaxCoordinates then nCoordinates := nCoordinates + 1 else beep; xCoordinates^[nCoordinates] := finish.h; yCoordinates^[nCoordinates] := finish.v; start := finish; Finished := (PtInRect(finish, StartRect) or DoubleClick or done) and (nCoordinates > 2); until finished; FlushEvents(EveryEvent, 0); end; procedure MakePolygon (event: EventRecord); var Start: point; i: integer; begin with info^ do begin start := event.where; SetPort(wptr); PenNormal; xCoordinates^[1] := Start.h; yCoordinates^[1] := Start.v; nCoordinates := 1; MoveTo(start.h, start.v); case CurrentTool of FreehandTool: begin DoFreehand; with Start do LineTo(h, v); end; PolygonTool: DoPolygon(start); end; if nCoordinates > 2 then begin ConvertCoordinates; if CurrentTool = PolygonTool then MakeOutline(PolygonRoi) else MakeOutline(FreehandRoi); end else begin KillRoi; UpdatePicWindow; end; end; {with} end; procedure MakeLineRoi (event: EventRecord); var Start: point; begin if NoUndo then exit(MakeLineRoi); start := event.where; with Info^ do begin WhatToUndo := NothingToUndo; measuring := false; if LOIType = Straight then begin DoObject(LineObj, event); RoiType := LineRoi; MakeRegion; RoiShowing := true; SetupUndo; exit(MakeLineRoi); end; SetPort(wptr); PenNormal; MoveTo(start.h, start.v); xCoordinates^[1] := Start.h; yCoordinates^[1] := Start.v; nCoordinates := 1; end; {with info} if LOIType = Freehand then DoFreehand else DoPolygon(start); if nCoordinates > 1 then case LoiType of freehand: MakeNonStraightLineRoi(FreeLineRoi); segmented: MakeNonStraightLineRoi(SegLineRoi); end else with info^ do begin RoiShowing := false; RoiType := NoRoi; UpdatePicWindow; end; end; procedure DoProfilePlot (event: EventRecord); var ulength, clength: extended; begin with Info^ do begin WhatToUndo := NothingToUndo; measuring := false; DoObject(LineObj, event); RoiType := LineRoi; MakeRegion; RoiShowing := true; SetupUndo; GetLengthOrPerimeter(ulength, clength); if ulength > 0 then PlotDensityProfile end; end; procedure DoMouseDownInWindow (event: EventRecord; WhichWindow: WindowPtr); {Handles mouse down events in the content region of image windows.} var r: rect; str: str255; hloc, vloc: integer; tool: ToolType; start: Point; begin SetPort(info^.wptr); if Digitizing then if (CurrentTool <> MagnifyingGlass) and (CurrentTool <> Grabber) then StopDigitizing; GlobalToLocal(event.where); IsInsertionPoint := false; with info^ do if RoiShowing then if EqualRect(RoiRect, PicRect) and (SelectionMode = NewSelection) then {if Select All} if not (OpPending and (CurrentOp = PasteOp)) then begin KillRoi; MouseState := NotInRoi; exit(DoMouseDownInWindow); end; if MouseState <> NotInRoi then exit(DoMouseDownInWindow); if SpaceBarDown and (CurrentTool <> TextTool) then tool := grabber else tool := CurrentTool; if (SelectionMode = NewSelection) and not ((tool = MagnifyingGlass) or (tool = Grabber)) then KillRoi; SetupUndo; case tool of SelectionTool: DoObject(SelectionRect, event); PolygonTool, FreehandTool: MakePolygon(event); OvalSelectionTool: DoObject(SelectionOval, event); LineTool: MakeLineRoi(event); MagnifyingGlass: ZoomIn(event); Grabber: Scroll(event); Pencil, Brush, Eraser: DoBrush(event); SprayCanTool: DoSprayCan; Ruler: if OptionKeyDown or ControlKeyDown then PutError('Use the line selection tool and Measure to measure path lengths.') else begin DoObject(LineObj, event); WhatToUndo := UndoEdit; end; PaintBucket: DoFill(event); TextTool: DoText(event.where); PlotTool: DoProfilePlot(event); PickerTool: if BitAnd(Event.modifiers, OptionKey) = OptionKey then GetBackgroundColor(event) else GetForegroundColor(event); CrossHairTool: DoPoints(event); AngleTool: FindAngle(event); Wand: begin if Digitizing then StopDigitizing; start := event.where; ScreenToOffscreen(start); AutoOutline(start); end; otherwise beep; end; end; procedure DoPopupMenusInTools; var Item: integer; ticks: LongInt; procedure DrawCurrentTool; begin InvalRect(ToolRect[CurrentTool]); BeginUpdate(ToolWindow); DrawTools; EndUpdate(ToolWindow); end; begin DrawCurrentTool; ticks := TickCount; repeat until (not button) or (TickCount > ticks + 20); if button and (TickCount > (ticks + 20)) then with ToolRect[CurrentTool] do begin Item := PopUpMenu(LineToolMenuH, left, top, ord(LOIType) + 1); case Item of 1: LOIType := Straight; 2: LOIType := Freehand; 3: LOIType := Segmented; otherwise end; DrawCurrentTool; end; end; procedure DoMouseDownInTools (loc: point); {Handles mouse down events in the tool palette.} var r: rect; OddTool, DoubleClick: boolean; ToolNum, i: integer; begin SetPort(ToolWindow); GlobalToLocal(loc); if loc.v <= StartOfLines then begin PreviousTool := CurrentTool; OddTool := loc.h < tmiddle; ToolNum := (loc.v div tmiddle) * 2; if not OddTool then ToolNum := ToolNum + 1; CurrentTool := ToolType(ToolNum); isSelectionTool := (CurrentTool = SelectionTool) or (CurrentTool = OvalSelectionTool) or (CurrentTool = PolygonTool) or (CurrentTool = FreehandTool) or (CurrentTool = LineTool); DoubleClick := (TickCount - ToolTime) < GetDblTime; ToolTime := TickCount; InvalRect(ToolRect[CurrentTool]); InvalRect(ToolRect[PreviousTool]); IsInsertionPoint := false; if DoubleClick and (CurrentTool = PreviousTool) then case CurrentTool of MagnifyingGlass: Unzoom; SelectionTool: begin StopDigitizing; SelectAll(true); end; SprayCanTool: SetSprayCanSize; Brush: SetBrushSize; LineTool: SetScale; PolygonTool: DoMeasurementOptions; FreehandTool: Calibrate; ruler: SetLineWidth; PlotTool: DoProfilePlotOptions; Eraser: if info <> NoInfo then begin KillRoi; SetupUndo; WhatToUndo := UndoClear; StopDigitizing; SelectAll(false); DoOperation(eraseOp); end; LutTool, Wand: if DensitySlicing then DisableDensitySlice else begin if Info^.Thresholding then ResetGrayMap; if OptionKeyDown then AutoDensitySlice; EnableDensitySlice; end; PickerTool: if info^.LutMode <> PseudoColor then begin {Switch to pseudocolor mode} DisableDensitySlice; UpdateLUT; CurrentTool := LutTool; isSelectionTool := false; InvalRect(ToolRect[CurrentTool]); end else ResetGrayMap; otherwise end; {case} if (not isSelectionTool) and (CurrentTool <> MagnifyingGlass) and (CurrentTool <> Grabber) and (CurrentTool <> Wand) then KillRoi; if not DoubleClick and (CurrentTool = LineTool) then KillRoi; with info^ do if RoiShowing then if EqualRect(RoiRect, PicRect) and not isSelectionTool then {if Select All} KillRoi; if (CurrentTool = SelectionTool) or (CurrentTool = CrossHairTool) then begin InfoMessage := ''; if mCount > 0 then ShowInfo; end; RoiMode := MoveMode; if CurrentTool = LineTool then begin if Button then DoPopUpMenusInTools; if (LoiType = Straight) and (LineWidth <> 1) then begin LineWidth := 1; UpdateRoiLineWidth; ShowLineWidth; end; end; end else begin for i := 1 to nLineTypes do begin r := lines[i]; with r do begin left := left - 13; top := top - 2; right := right + 2; bottom := bottom + 2; end; if i = 1 then with r do top := top - 7; if PtInRect(loc, r) then begin with lines[i] do LineWidth := bottom - top; LineIndex := i; end; end; EraseRect(CheckRect); InvalRect(CheckRect); UpdateRoiLineWidth; end; end; procedure ScaleToFitScreen; var trect: rect; ignore: boolean; begin with info^ do begin MoveWindow(wptr, PicLeftBase, PicTopBase, true); SetRect(trect, 0, 0, ScreenWidth, ScreenHeight); ScaleImageWindow(trect); wrect := trect; SizeWindow(wptr, trect.right, trect.bottom, true); end; end; procedure DoDrag (WhichWindow: WindowPtr; loc: point); var WinRect, DragBounds, trect: rect; kind: integer; begin kind := WindowPeek(WhichWindow)^.WindowKind; if kind = PicKind then begin if (info^.PictureType = FrameGrabberType) and GrabbingToScreen then exit(DoDrag); with info^ do begin {Save window location} GetWindowRect(wptr, trect); savehloc := trect.left; savevloc := trect.top; end; PicLeft := PicLeftBase; PicTop := PicTopBase; end; DragBounds := qd.ScreenBits.bounds; DragWindow(WhichWindow, loc, DragBounds); if (info^.PictureType = FrameGrabberType) or OptionKeyDown then begin GetWindowRect(WhichWindow, trect); MoveWindow(WhichWindow, band(trect.left, $fffc), trect.top, true); end; if WhichWindow = InfoWindow then ShowInfo; if WhichWindow = ResultsWindow then begin GetWindowRect(WhichWindow, trect); ResultsTop := trect.top; ResultsLeft := trect.left; end; end; procedure UpdateMenus; begin OptionKeyWasDown := OptionKeyDown; CurrentKind := CurrentWindow; UpdateFileMenu; UpdateEditMenu; UpdateOptionsMenu; UpdateTextItems; UpdateProcessMenu; UpdateAnalysisMenu; UpdateSpecialMenu; UpdateStacksMenu; UpdateWindowsMenu; end; function BalloonHelp: boolean; begin if not System7 then begin BalloonHelp := false; exit(BalloonHelp); end; BalloonHelp := HMGetBalloons; end; procedure DoMouseDown (event: EventRecord); {Handle mouse-down events} var WhichWindow: WindowPtr; ThePart, ignore, kind: integer; trect: rect; begin ThePart := FindWindow(event.where, WhichWindow); case ThePart of InDesk: ; InMenuBar: begin UpdateMenus; DoMenuEvent(MenuSelect(event.where)); end; InSysWindow: SystemClick(Event, WhichWindow); InContent: begin {The Tools, Map, LUT and PasteControl windows do not have to be activated to process the mouse-down event.} RoiUpdateTime := 0; if WhichWindow = ToolWindow then begin if BalloonHelp then SelectWindow(ToolWindow); DoMouseDownInTools(event.where); exit(DoMouseDown); end; if WhichWindow = MapWindow then begin if BalloonHelp then SelectWindow(MapWindow); DoMouseDownInMap; exit(DoMouseDown) end; if WhichWindow = LUTWindow then begin if BalloonHelp then SelectWindow(LUTWindow); DoMouseDownInLUT(event); exit(DoMouseDown) end; if WhichWindow = PasteControl then begin DoMouseDownInPasteControl(event.where); exit(DoMouseDown) end; if WhichWindow <> FrontWindow then begin {Image windows, text windows and the Result window must be activated if they are not the current window.} SelectWindow(WhichWindow); exit(DoMouseDown); end; if WhichWindow = ResultsWindow then begin DoMouseDownInResults(event.where); exit(DoMouseDown) end; kind := WindowPeek(WhichWindow)^.WindowKind; if Kind = TextKind then begin DoMouseDownInText(Event, WhichWindow); exit(DoMouseDown) end; if kind = PicKind then DoMouseDownInWindow(Event, WhichWindow); end; InDrag: DoDrag(WhichWindow, event.where); InGrow: DoGrow(WhichWindow, event); InGoAway: if TrackGoAway(WhichWindow, event.where) then if OptionKeyDown and (CurrentWindow = PicKind) then CloseAll else begin if WhichWindow <> VideoControl then StopDigitizing; ignore := CloseAWindow(WhichWindow); end; InZoomIn, InZoomOut: with info^ do case WindowState of NormalWindow: begin if digitizing then exit(DoMouseDown); ScaleToFit; if ScaleToFitWindow then ScaleToFitScreen; end; TiledSmall, TiledSmallScaled: begin if WindowState = TiledSmall then begin ScaleToFitWindow := true; WindowState := TiledBig; end else WindowState := TiledBigScaled; savewrect := wrect; SaveSrcRect := SrcRect; SaveMagnification := magnification; GetWindowRect(wptr, trect); savehloc := trect.left; savevloc := trect.top; ScaleToFitScreen; UpdatePicWindow; end; TiledBig: begin ScaleToFitWindow := false; WindowState := TiledSmall; wrect := savewrect; SrcRect := SaveSrcRect; magnification := SaveMagnification; HideWindow(wptr); SizeWindow(wptr, wrect.right, wrect.bottom, true); MoveWindow(wptr, savehloc, savevloc, true); ShowWindow(wptr); UpdatePicWindow; magnification := 1.0; UpdateTitleBar; end; TiledBigScaled: begin WindowState := TiledSmallScaled; wrect := savewrect; SrcRect := PicRect; HideWindow(wptr); SizeWindow(wptr, wrect.right, wrect.bottom, true); MoveWindow(wptr, savehloc, savevloc, true); ShowWindow(wptr); UpdatePicWindow; if PicRect.right <> 0 then magnification := wrect.right / PicRect.right; UpdateTitleBar; end; end; {case WindowState} end; {case thePart} end; procedure NudgeRoi (key: integer); var dh, dv: integer; begin with info^ do begin if not RoiShowing then exit(NudgeRoi); if OpPending and (CurrentOp <> PasteOp) then begin KillRoi; RestoreRoi; end; case key of LeftArrow: begin dh := -1; dv := 0 end; RightArrow: begin dh := 1; dv := 0 end; UpArrow: begin dh := 0; dv := -1 end; DownArrow: begin dh := 0; dv := 1 end; end; if OptionKeyDown then begin if RoiType = RectRoi then with RoiRect do begin right := right + dh; if right < left + 2 then right := left + 2; bottom := bottom + dv; if bottom < top + 2 then bottom := top + 2; MakeRegion; end else beep; end else begin OffsetRgn(roiRgn, dh, dv); RoiRect := roiRgn^^.rgnBBox; end; RoiNudged := true; RoiUpdateTime := 0; end; end; procedure DoKeyDown (event: EventRecord); var ch: char; ich, KeyCode: integer; begin Ch := chr(band(Event.message, CharCodeMask)); ich := ord(ch); {ShowMessage(long2str(ich));} KeyCode := bsr(band(Event.message, KeyCodeMask), 8); if BitAnd(Event.modifiers, CmdKey) = CmdKey then begin UpdateMenus; if OptionKeyWasDown then begin case KeyCode of 1: ch := 'S'; 3: ch := 'F'; 5: ch := 'G'; 8: ch := 'C'; 9: ch := 'V'; 13: ch := 'W'; 17: ch := 'T'; 24: ch := '='; 35: ch := 'P'; 44: ch := '/'; end; end; DoMenuEvent(MenuKey(Ch)); exit(DoKeyDown) end; if CurrentWindow = TextKind then begin DoKeyDownInText(ch); exit(DoKeyDown) end; with info^ do if (CurrentTool = TextTool) and IsInsertionPoint and (ord(ch) <> FunctionKey) then DrawCharacter(ch) else if ch = BackSpace then DoClear else if RoiShowing and (ich >= LeftArrow) and (ich <= DownArrow) then NudgeRoi(ich) else if (StackInfo <> nil) and (ch in ['<', ',', chr(PageUp), '>', '.', chr(PageDown), chr(HomeKey), chr(EndKey)]) then begin if ch in ['<', ',', chr(PageUp)] then ShowNextSlice(PreviousSliceItem) else if ch in ['>', '.', chr(PageDown)] then ShowNextSlice(NextSliceItem) else if (ich = HomeKey) or (ich = EndKey) then ShowFirstOrLastSlice(ich); end else if nMacros > 0 then RunKeyMacro(ch, KeyCode); end; procedure DoActivate (event: EventRecord); var WhichWindow: WindowPtr; Activating, SwitchingWindows, isOK: boolean; I, kind: integer; NewInfo: InfoPtr; begin WhichWindow := WindowPtr(event.message); kind := WindowPeek(WhichWindow)^.WindowKind; Activating := odd(event.modifiers); case kind of PicKind: begin if Activating then begin NewInfo := pointer(WindowPeek(WhichWindow)^.RefCon); SwitchingWindows := NewInfo <> Info; if SwitchingWindows then begin StopDigitizing; SaveRoi; DisableDensitySlice; end; Info := NewInfo; if SwitchingWindows then ActivateWindow; Measuring := false; with info^ do begin LoadLUT(cTable); DrawMap; if digitizing and HighlightSaturatedPixels then HighlightPixels; GenerateValues; if fit = uncalibrated then DrawLabels('', '', ''); end; {with} end else KillOperation; {Deactivate} end; ResultsKind: UpdateResultsWindow; TextKind: ActivateTextWindow(WhichWindow, Activating); otherwise end; {case} if not activating then begin WhichWindow := FrontWindow; if WhichWindow <> nil then begin kind := WindowPeek(WhichWindow)^.WindowKind; if kind < 0 then ConverToSystemClipboard; {DA has become active} end; end; end; procedure DoUpdate (event: EventRecord); var WhichWindow: WindowPtr; SaveInfo: InfoPtr; kind: integer; begin WhichWindow := WindowPtr(event.message); kind := WindowPeek(WhichWindow)^.WindowKind; BeginUpdate(WhichWindow); case kind of Pickind: begin SaveInfo := info; Info := pointer(WindowPeek(WhichWindow)^.RefCon); if not digitizing then begin UpdatePicWindow; DrawMyGrowIcon(info^.wptr); end; info := SaveInfo; end; ToolKind: DrawTools; MapKind: DrawMap; LutKind: DrawLUT; InfoKind: begin DrawLabels('', '', ''); if (mCount > 0) or (InfoMessage <> '') then ShowInfo; end; HistoKind: DrawHistogram; ProfilePlotKind, CalibrationPlotKind: UpdatePlotWindow; ResultsKind: UpdateResultsWindow; PasteControlKind: DrawPasteControl; TextKind: UpdateTextWindow(WhichWindow); end; EndUpdate(WhichWindow); end; procedure DoDiskInsert (event: EventRecord); { Process disk insertion event, check for damaged or uninitialized disks. } var p: point; intjunk: integer; begin if (HiWrd(event.message) <> NoErr) then begin DiLoad; SetPt(p, 100, 80); intjunk := DiBadMount(p, event.message); DiUnload; end; end; procedure DoDialogEvent (event: EventRecord); {Handles modeless dialog box events} var isItemHit: boolean; theDialog: DialogPtr; ItemHit: integer; ch: char; begin if (Event.what = KeyDown) and (BitAnd(Event.modifiers, CmdKey) = CmdKey) then begin UpdateMenus; ch := chr(band(Event.message, CharCodeMask)); DoMenuEvent(MenuKey(ch)); exit(DoDialogEvent); end; isItemHit := DialogSelect(event, theDialog, ItemHit); if isItemHit and (theDialog = VideoControl) then DoVideoControl(ItemHit); end; function MyGotRequiredParams(var theAppleEvent:AppleEvent):OSErr; var err:OSErr; returnedType:DescType; actualSize:Size; begin err:=AEGetAttributePtr(theAppleEvent, keyMissedKeywordAttr, typeWildCard, returnedType, nil, 0, actualSize); if err=errAEDescNotFound then myGotRequiredParams:=noErr else if err=noErr then myGotRequiredParams:=errAEParamMissed; end; procedure PrintDocument; begin UpdatePicWindow; WhatToPrint := PrintImage; Print(false); DoClose; end; function OpenFinderFile(myFSS:FSSpec; PrintDoc:boolean):OSErr; var theInfo: FInfo; err, err1, err2:OSErr; wdRefNum, f:integer; okay:boolean; begin OpenFinderFile:=fnfErr; with myFSS do begin err := OpenWD(VRefNum, parID, 0, wdRefNum); if err<>noErr then exit(OpenFinderFile); err := GetFInfo(name, wdRefNum, theInfo); if err<>noErr then exit(OpenFinderFile); okay:=false; OpeningFinderFiles:=true; if theInfo.fdType = 'TIFF' then begin WhatToOpen := OpenTIFF; okay := OpenFile(name, wdRefNum); if OpeningRGB then begin if okay then ConvertRGBToEightBitColor(true); OpeningRGB := false; end; if PrintDoc then PrintDocument; end; if theInfo.fdType = 'PICT' then begin okay := OpenPICT(name, wdRefNum, false); if PrintDoc then PrintDocument; end; if theInfo.fdType = 'TEXT' then begin ShowMessage(StringOf('Opening: ', name)); wait(30); okay := OpenTextFile(name, wdRefNum); end; if theInfo.fdType = 'PICS' then begin okay := OpenPICS(name, wdRefNum); end; if theInfo.fdType = 'Iout' then begin OpenOutline(name, wdRefNum); okay:=true; end; if theInfo.fdType = 'ICOL' then begin OpenColorTable(name, wdRefNum); okay:=true; end; if theInfo.fdType = 'IPIC' then begin WhatToOpen := OpenImage; okay := OpenFile(name, wdRefNum); if PrintDoc then PrintDocument; end; if theInfo.fdType = 'MooV' then begin okay := OpenQuickTime(name, wdRefNum, true); end; if (theInfo.fdType = 'PREF') or (theInfo.fdType = 'pref') then begin err := fsopen(name, wdRefNum, f); GetPreferences(f); if nExtraColors > 0 then RedrawLUTWindow; if InvertPixelValues then InvertGrayLevels; end; OpeningFinderFiles:=false; if okay then OpenFinderFile:=noErr; end; end; function HandleOpenOrPrint(var theAppleEvent, reply:AppleEvent; RefCon:LongInt; PrintDoc:boolean):OSerr; var err, ignoreErr:OSErr; docList:AEDescList; index, ItemsInList:LongInt; actualSize:Size; keywd:AEKeyword; returnedType:DescType; myFSS:FSSpec; begin err:=AEGetParamDesc(theAppleEvent, keyDirectObject, typeAEList, docList); if err=noErr then begin err:=myGotRequiredParams(theAppleEvent); if err=noErr then begin err:=AECountItems(docList, itemsInList); if err=noErr then for index:=1 to ItemsInList do begin err:=AEGetNthPtr(docList, index, typeFSS, keywd, returnedType, @myFSS, SizeOf(myFSS), actualSize); if err=noErr then begin err:=OpenFinderFile(myFSS, PrintDoc); end; end; end; ignoreErr:=AEDisposeDesc(docList); end; HandleOpenOrPrint:=err; end; function HandleOpenApp(var theAppleEvent, reply:AppleEvent; RefCon:LongInt):OSerr; begin HandleOpenApp:=noErr; end; function HandleOpenDoc(var theAppleEvent, reply:AppleEvent; RefCon:LongInt):OSerr; begin HandleOpenDoc:=HandleOpenOrPrint(theAppleEvent, reply, RefCon, false); end; function HandlePrintDoc(var theAppleEvent, reply: AppleEvent; RefCon:LongInt):OSerr; begin HandlePrintDoc:=HandleOpenOrPrint(theAppleEvent, reply, RefCon, true); end; function HandleQuit(var theAppleEvent, reply:AppleEvent; RefCon:LongInt):OSerr; begin Finished:=true; HandleQuit:=noErr; end; function HandleEvents: boolean; const mousemovedmessage = $FA; SuspendResumeMessage = 1; ResumeMask = 1; var Event: EventRecord; result: boolean; theDialog: DialogPtr; ItemHit: integer; SleepTicks: LongInt; okay: boolean; err:OSErr; begin if Digitizing then SleepTicks := 0 else SleepTicks := 2; if WaitNextEvent(EveryEvent, Event, SleepTicks, nil) then begin if isDialogEvent(event) then DoDialogEvent(event) else case Event.what of KeyDown, AutoKey: DoKeyDown(Event); MouseDown: DoMouseDown(Event); ActivateEvt: DoActivate(Event); DiskEvt: DoDiskInsert(Event); UpdateEvt: DoUpdate(Event); osEvt: case BSR(event.message, 24) of MouseMovedMessage: ; SuspendResumeMessage: if BAND(event.message, ResumeMask) <> 0 then begin{Resume event} if SwitchLUTOnSuspend and (WhatToUndo = UndoLUT) then begin UndoLUTChange; WhatToUndo := NothingToUndo; end else LoadLUT(info^.ctable); end else begin {Suspend event} KillOperation; ConverToSystemClipboard; if SwitchLUTOnSuspend then begin SetupLUTUndo; okay := LoadCLUTResource(AppleDefaultCLUT); end; end; end; kHighLevelEvent: err:=AEProcessAppleEvent (Event); otherwise {Do nothing} end; {case} HandleEvents := true end else HandleEvents := false; end; procedure ShowInsertionPoint; var tRect: rect; Loc: point; height, imag: integer; begin if (not isInsertionPoint) or (info = NoInfo) then exit(ShowInsertionPoint); if CurrentWindow <> PicKind then exit(ShowInsertionPoint); if (TickCount mod (BlinkTime * 2)) < BlinkTime then exit(ShowInsertionPoint); Loc := InsertionPoint; OffscreenToScreen(loc); with info^, tRect do begin SetPort(wptr); imag := trunc(magnification + 0.5); height := CurrentSize * imag; height := height - height div 4; left := loc.h; bottom := loc.v - imag + 1; top := bottom - height; right := left + 1; PenNormal; PenSize(imag, imag); PenMode(PatXor); FrameRect(tRect); ipTicks := TickCount + 3; repeat until TickCount > ipTicks; FrameRect(tRect); end; end; procedure UndoRoi; var SrcPtr, DstPtr: ptr; offset, ByteCount, tTop, tBottom: LongInt; tRect: rect; begin with info^ do begin if PixMapSize <> CurrentUndoSize then exit(UndoRoi); tRect := RoiRect; if RoiType = LineRoi then InsetRect(tRect, -RoiHandleSize, -RoiHandleSize); with tRect do begin tTop := top; tBottom := bottom; if tTop < 0 then tTop := 0; if tTop > PicRect.bottom then tTop := PicRect.bottom; if tBottom < 0 then tBottom := 0; if tBottom > PicRect.bottom then tBottom := PicRect.bottom; end; offset := tTop * BytesPerRow; if offset < 0 then offset := 0; SrcPtr := ptr(ord4(UndoBuf) + offset); DstPtr := ptr(ord4(PicBaseAddr) + offset); ByteCount := (tBottom - tTop) * BytesPerRow; BlockMove(SrcPtr, DstPtr, ByteCount); end; end; procedure GetLineHandles (var LeftHandle, MiddleHandle, RightHandle: rect); var offset1, offset2, xcenter, ycenter, x1, y1, x2, y2: integer; rx1, ry1, rx2, ry2: extended; begin offset1 := RoiHandleSize div 2; offset2 := offset1 + 1; GetLoi(rx1, ry1, rx2, ry2); x1 := trunc(rx1); y1 := trunc(ry1); x2 := trunc(rx2); y2 := trunc(ry2); SetRect(LeftHandle, x1 - offset1, y1 - offset1, x1 + offset2, y1 + offset2); with info^.RoiRect do begin xcenter := left + (right - left) div 2; ycenter := top + (bottom - top) div 2; end; SetRect(MiddleHandle, xcenter - offset1, ycenter - offset1, xcenter + offset2, ycenter + offset2); SetRect(RightHandle, x2 - offset1, y2 - offset1, x2 + offset2, y2 + offset2); end; procedure DrawROI; var tRect: rect; RoiHandle, LeftHandle, MiddleHandle, RightHandle: rect; psize: integer; StartTicks: LongInt; SaveGDevice: GDHandle; begin with Info^ do begin StartTicks := TickCount; if OpPending then DoOperation(CurrentOp); SaveGDevice := GetGDevice; SetGDevice(osGDevice); SetPort(GrafPtr(Info^.osPort)); PenNormal; if ScaleToFitWindow then if (magnification < 1.0) and (magnification <> 0.0) then begin psize := round(1.0 / magnification + 1.5); PenSize(psize, psize); end; if not ((MouseState = DownInRoi) and OpPending) then if PixMapSize <= UndoBufSize then begin IndexToRgbForeColor(BlackIndex); IndexToRgbBackColor(WhiteIndex); case RoiType of RectRoi: with RoiRect do begin SetRect(RoiHandle, right - RoiHandleSize, bottom - RoiHandleSize, right, bottom); if ((right - left) > RoiHandleSize) and ((bottom - top) > RoiHandleSize) then PaintRect(RoiHandle); end; LineRoi: if Magnification <= 2.0 then begin GetLineHandles(LeftHandle, MiddleHandle, RightHandle); PaintRect(LeftHandle); if LineWidth < 4 then PaintRect(MiddleHandle); PaintRect(RightHandle); IndexToRgbForeColor(WhiteIndex); FrameRect(LeftHandle); if LineWidth < 4 then FrameRect(MiddleHandle); FrameRect(RightHandle); IndexToRgbForeColor(BlackIndex); end; otherwise end; PatIndex := (PatIndex + 1) mod 8; PenPat(AntPattern[PatIndex]); FrameRgn(roiRgn); IndexToRgbForeColor(ForegroundIndex); IndexToRgbBackColor(BackgroundIndex); end; if PixMapSize > UndoBufSize then begin if magnification < 1.0 then PenSize(2, 2); PatIndex := (PatIndex + 1) mod 8; PenPat(AntPattern[PatIndex]); PenMode(PatXor); FrameRgn(roiRgn); if MouseState = DownInRoi then begin UnionRect(RoiRect, OldRoiRect, tRect); UpdateScreen(tRect); end else UpdateScreen(RoiRect); FrameRgn(roiRgn); end else begin tRect := RoiRect; if MouseState = DownInRoi then UnionRect(RoiRect, OldRoiRect, tRect) else if RoiNudged then begin tRect := RoiRect; RoiNudged := false; end; if RoiType = LineRoi then InsetRect(tRect, -RoiHandleSize * 2, -RoiHandleSize * 2) else InsetRect(tRect, -2, -2); UpdateScreen(tRect); UndoRoi; {Erase offscreen ROI} end; RoiUpdateTime := TickCount - StartTicks; end; {with} SetGDevice(SaveGDevice); end; procedure MoveLineEndPoint (osloc: point); var deltax, deltay: extended; begin with info^, osloc, info^.RoiRect do begin if h < 0 then h := 0; if h > PicRect.right then h := PicRect.right; if v < 0 then v := 0; if v > PicRect.bottom then v := PicRect.bottom; if RoiMode = LeftEndMode then begin LX1 := h; LY1 := v; LX2 := left + LX2; LY2 := top + LY2; end else begin LX2 := h; LY2 := v; LX1 := left + LX1; LY1 := top + LY1; end; if ShiftKeyDown then begin deltax := LX2 - LX1; deltay := LY2 - LY1; if abs(deltax) > abs(deltay) then begin if RoiMode = LeftEndMode then LY2 := LY1 else LY1 := LY2 end else begin if RoiMode = LeftEndMode then LX2 := LX1 else LX1 := LX2 end; end; {if ShiftKeyDown} MakeRegion; osMouseDownLoc := osloc; RoiUpdateTime := 0; Show3Values(h, v, MyGetPixel(h, v)); end; end; procedure MoveRoi (osloc: point); var dh, dv: integer; begin with info^, info^.RoiRect, osloc do begin dh := h - osMouseDownLoc.h; dv := v - osMouseDownLoc.v; OldRoiRect := RoiRect; if RoiType = LineRoi then if (RoiMode = LeftEndMode) or (RoiMode = RightEndMode) then begin MoveLineEndPoint(osloc); exit(MoveRoi); end; if RoiMode = MoveMode then begin if RoiMovementState = Constrained then begin if dv <> 0 then RoiMovementState := ConstrainedV else if dh <> 0 then RoiMovementState := ConstrainedH end; if RoiMovementState = ConstrainedH then dv := 0 else if RoiMovementState = ConstrainedV then dh := 0; if not OpPending then begin if left + dh < 0 then dh := -left; if top + dv < 0 then dv := -top; end; end; if not OpPending then begin if right + dh > PicRect.right then dh := PicRect.right - right; if bottom + dv > PicRect.bottom then dv := PicRect.bottom - bottom; end; if RoiMode = StretchMode then begin measuring := false; DrawLabels('Width:', 'Height:', ''); if h > left then begin right := right + dh; if right < (left + 1) then right := left + 1; if (right - h) > 5 then right := h + 2; end else right := left + 1; if v > top then begin bottom := bottom + dv; if bottom < (top + 1) then bottom := top + 1; if (bottom - v) > 5 then bottom := v + 2; end else bottom := top + 1; Show3Values(right - left, bottom - top, -1); MakeRegion; end else begin OffsetRgn(roiRgn, dh, dv); Show3Values(left, top, MyGetPixel(left, top)); end; RoiRect := roiRgn^^.rgnBBox; osMouseDownLoc := osloc; RoiUpdateTime := 0; {Forces ROI outline to be redrawn} end; {with Info} end; procedure ShowHistogramValues (GrayLevel: LongInt); var hstart, vstart, ivalue: integer; begin hstart := InfoHStart; vstart := InfoVStart; SetPort(InfoWindow); TextSize(9); TextFont(Monaco); TextMode(SrcCopy); MoveTo(xValueLoc, vstart); with info^ do if fit = uncalibrated then DrawLong(GrayLevel) else begin if InvertingCalibrationFunction then DrawReal(cvalue[255 - GrayLevel], 8, 2) else DrawReal(cvalue[GrayLevel], 8, 2); DrawString(' ('); DrawLong(GrayLevel); DrawString(' )'); end; DrawString(' '); MoveTo(yValueLoc, vstart + 10); if InvertingCalibrationFunction then DrawLong(histogram[255 - GrayLevel]) else DrawLong(histogram[GrayLevel]); DrawString(' '); end; procedure DoPlotCursor (loc: point; kind: integer); var xxscale, angle: extended; xvalue, xinc, yinc: integer; pt: point; begin DrawLabels('X:', 'Y:', ''); SetCursor(ToolCursor[SelectionTool]); SetPort(PlotWindow); GlobalToLocal(loc); xxscale := PlotCount / (PlotWidth - PlotRightMargin - PlotLeftMargin); xvalue := trunc((loc.h - PlotLeftMargin) * xxscale); if (xvalue < 0) or (xvalue >= PlotCount) then exit(DoPlotCursor); Show2PlotValues(xvalue, PlotData^[xvalue]); if (kind = CalibrationPlotKind) or (info^.RoiType <> LineRoi) then exit(DoPlotCursor); if button and (info <> NoInfo) then with loc do begin SetPort(info^.wptr); PenMode(PatXor); PenSize(1, 1); angle := (PlotAngle / 180.0) * pi; xinc := round(cos(angle) * xvalue); yinc := round(-sin(angle) * xvalue); h := PlotStart.h + xinc; v := PlotStart.v + yinc; OffscreenToScreen(loc); MoveTo(h - 7, v); LineTo(h + 7, v); MoveTo(h, v - 7); LineTo(h, v + 7); wait(2); MoveTo(h - 7, v); LineTo(h + 7, v); MoveTo(h, v - 7); LineTo(h, v + 7); end; end; procedure SelectCursor; var loc, osloc, gloc: point; where, kind, i, color, x, y, margin: integer; WhichWindow: WindowPtr; MouseInRoi: boolean; fwptr: WindowPtr; CalValue: extended; RoiStretchHandle, LeftHandle, MiddleHandle, RightHandle: rect; MovingRoi: boolean; pvalue: integer; begin if PasteControl <> nil then begin fwptr := FrontWindow; if fwptr <> nil then if WindowPeek(fwptr)^.WindowKind <> PasteControlKind then BringToFront(PasteControl); end; SetPort(ScreenPort); GetMouse(gloc); loc := gloc; where := FindWindow(gloc, WhichWindow); if WhichWindow = nil then begin InitCursor; exit(SelectCursor) end; kind := WindowPeek(WhichWindow)^.WindowKind; if kind < 0 then exit(SelectCursor); {System Window} if where <> InContent then begin InitCursor; exit(SelectCursor) end; case kind of PicKind: begin if Info = NoInfo then begin InitCursor; exit(SelectCursor) end; SetPort(info^.wptr); GlobalToLocal(loc); osloc := loc; ScreenToOffscreen(osloc); MovingRoi := false; with info^ do begin SelectionMode := NewSelection; if RoiShowing and ((isSelectionTool) or (CurrentTool = Wand)) and (currentTool <> LineTool) then begin if OptionKeyDown then SelectionMode := SubSelection else if ControlKeyDown or (ShiftKeyDown and (CurrentTool <> OvalSelectionTool) and (CurrentTool <> SelectionTool)) then SelectionMode := AddSelection; end; if RoiShowing and (SelectionMode = NewSelection) then begin MouseInRoi := PtInRgn(osloc, roiRgn); if RoiType = LineRoi then begin GetLineHandles(LeftHandle, MiddleHandle, RightHandle); if magnification <= 2.0 then begin InsetRect(LeftHandle, -2, -2); InsetRect(MiddleHandle, -2, -2); InsetRect(RightHandle, -2, -2); end; MouseInRoi := MouseInRoi or PtInRect(osloc, LeftHandle) or MouseInRoi or PtInRect(osloc, MiddleHandle) or MouseInRoi or PtInRect(osloc, RightHandle); end; end else MouseInRoi := false end; {with} if MouseInRoi or (MouseState = DownInRoi) then begin if MouseState = NotInRoi then MouseState := InRoi; InitCursor; if button then begin if MouseState = InRoi then begin if OpPending and (CurrentOp <> PasteOp) then SetupUndo; MouseState := DownInRoi; osMouseDownLoc := osloc; with info^ do case RoiType of RectRoi: begin if magnification > 1.0 then margin := 0 else margin := 2; with RoiRect do SetRect(RoiStretchHandle, right - RoiHandleSize - margin, bottom - RoiHandleSize - margin, right, bottom); if PtInRect(osloc, RoiStretchHandle) then RoiMode := StretchMode else RoiMode := MoveMode; end; LineRoi: if PtInRect(osloc, LeftHandle) then RoiMode := LeftEndMode else if PtInRect(osloc, RightHandle) then RoiMode := RightEndMode else RoiMode := MoveMode; otherwise end; {case} if ShiftKeyDown then RoiMovementState := Constrained else RoiMovementState := Unconstrained; end; MoveRoi(osloc); MovingRoi := true; end else MouseState := InRoi end else begin MouseState := NotInRoi; if SpaceBarDown and (CurrentTool <> TextTool) then SetCursor(ToolCursor[Grabber]) else if (SelectionMode = AddSelection) and (CurrentTool = Wand) then SetCursor(WandPlusCursor) else if (SelectionMode = SubSelection) and (CurrentTool = Wand) then SetCursor(WandMinusCursor) else if SelectionMode = AddSelection then SetCursor(CrossPlusCursor) else if SelectionMode = SubSelection then SetCursor(CrossMinusCursor) else if (CurrentTool = MagnifyingGlass) and OptionKeyDown then SetCursor(GlassMinusCursor) else SetCursor(ToolCursor[CurrentTool]); end; if not MovingRoi then begin if isFFT then begin DrawLabels('r:', 'theta:', 'Value:'); with osloc do ShowFFTValues(h, v, MyGetPixel(h, v)); exit(SelectCursor); end; if CurrentTool = PickerTool then DrawLabels('X:', 'Y:', 'RGB:') else DrawLabels('X:', 'Y:', 'Value:'); with osloc do begin if Digitizing then pvalue := GetFGPixel(h, v) else pvalue := MyGetPixel(h, v); Show3Values(h, v, pvalue); end; end; end; HistoKind: begin DrawLabels('Level:', 'Count:', ''); SetCursor(ToolCursor[SelectionTool]); SetPort(HistoWindow); GlobalToLocal(loc); ShowHistogramValues(loc.h); end; ProfilePlotKind, CalibrationPlotKind: DoPlotCursor(loc, kind); LUTKind: begin if info^.fit <> uncalibrated then DrawLabels('Index:', 'Value:', ' RGB:') else DrawLabels('Index:', ' RGB:', ''); SetPort(LUTWindow); GlobalToLocal(loc); if (CurrentTool = LutTool) or (CurrentTool = Wand) then begin if loc.v < 256 then SetCursor(LUTCursor) else InitCursor end else SetCursor(PickerCursor); if loc.v < 256 then begin ShowRGBValues(loc.v); end else begin color := 0; for i := 1 to nExtraColors + 2 do if PtInRect(loc, ExtraColorsRect[i]) then Color := ExtraColorsEntry[i]; ShowRGBValues(color); end; end; MapKind: if OptionKeyDown then SetCursor(ToolCursor[SelectionTool]) else SetCursor(gmCursor); TextKind: begin TextInfo := TextInfoPtr(WindowPeek(WhichWindow)^.RefCon); if TextInfo <> nil then with TextInfo^ do begin SetPort(TextWindowPtr); GlobalToLocal(loc); TEIdle(TextTE); with TextWindowPtr^.portRect do begin if (loc.h < (right - ScrollBarWidth)) and (loc.v < (bottom - ScrollBarWidth)) then SetCursor(ToolCursor[TextTool]) else InitCursor; end; end; end; otherwise InitCursor; end; {case} end; procedure CloseAll; var i, j, result: integer; WPeek, NextWPeek: WindowPeek; ignore: boolean; begin InitCursor; WPeek := WindowPeek(FrontWindow); StopDigitizing; while wpeek <> nil do begin NextWPeek := WPeek^.NextWindow; case wPeek^.WindowKind of PicKind: begin Info := pointer(WPeek^.RefCon); result := CloseAWindow(info^.wptr); if not CommandPeriod then for j := 1 to 2 do ignore := HandleEvents; if result = cancel then begin ActivateWindow; finished := false; exit(CloseAll) end; end; TextKind: begin result := CloseAWindow(WindowPtr(wPeek)); if result = cancel then begin finished := false; exit(CloseAll) end; end; otherwise ; end; {case} wpeek := NextWPeek; end; end; procedure LoadDefaultMacros; {Looks for a text file named "Image Macros" in the same folder as} {Image, and, if found, loads the macros contained in it.} var err: OSErr; LaunchRefNum: integer; FinderInfo: FInfo; id: LongInt; begin err := GetVol(nil, LaunchRefNum); if err = noerr then err := GetFInfo('Image Macros', LaunchRefNum, FinderInfo); if err = NoErr then begin LoadMacrosFromFile('Image Macros', LaunchRefNum); {$ifc not PowerPC} UnloadSeg(@LoadMacros); {$endc} end; end; procedure Shutdown; var AlertID: integer; begin if (UnsavedResults and (mCount > 10)) or (UnsavedResults and (ResultsWindow <> nil)) then begin InitCursor; AlertID := alert(500, nil); if AlertID = CancelResetID then begin finished := false; exit(Shutdown) end; end; CloseAll; if finished then ConverToSystemClipboard; end; procedure InstallEventHandlers; {Installs event handlers for the four required Apple Events.} var err:OSErr; begin err:=AEInstallEventHandler(kCoreEventClass, kAEOpenApplication, NewAEEventHandlerProc(@HandleOpenApp), 0, false); err:=AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments, NewAEEventHandlerProc(@HandleOpendoc), 0, false); err:=AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments, NewAEEventHandlerProc(@HandlePrintDoc), 0, false); err:=AEInstallEventHandler(kCoreEventClass, kAEQuitApplication, NewAEEventHandlerProc(@HandleQuit), 0, false); end; begin Init; InstallEventHandlers; SetupMenus; {GetSettings moved to Init} AllocateBuffers; AllocateArrays; ConvertFromSystemClipboard; LoadDefaultMacros; FindPlugIns; {$ifc not PowerPC} UnloadSeg(@Init); {$endc} {InitUser;} {Uncomment to activate User menu.} repeat if not HandleEvents then if info^.RoiShowing and (RoiUpdateTime < 30) then DrawRoi; ShowInsertionPoint; SelectCursor; if Digitizing then begin CaptureAndDisplayFrame; if ContinuousHistogram then ShowContinuousHistogram; end; if Finished then Shutdown; until finished; CloseSerialPorts; isOK := LoadCLUTResource(AppleDefaultCLUT); RestoreScreen; {Force Finder to redraw color icons} end.