home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / Pascal / Applications / NIH Image 1.55 / Source / Image.p < prev    next >
Encoding:
Text File  |  1994-04-26  |  68.5 KB  |  2,693 lines  |  [TEXT/PJMM]

  1. program Image;
  2.  
  3. {NIH Image is a public domain program for the Macintosh for acquiring, }
  4. {enhancing, analyzing, editing, printing, and animating 8-bit images.}
  5.  
  6.  
  7. {Version 1.55, 25 April1994}
  8.  
  9.  
  10. {Developed using Think Pascal 4.0.2}
  11. {Note: requires at least a 5MB partition for Think Pascal.}
  12.  
  13. {Author :}
  14.  
  15. {Wayne Rasband}
  16. {National Institutes of Health}
  17.  
  18. {Internet: wayne@helix.nih.gov}
  19. {Anonymous ftp: zippy.nimh.nih.gov}
  20. {Phone: 301-496-4957}
  21.  
  22.  
  23.     uses
  24.         QuickDraw, Palettes, PrintTraps, Globals, Utilities, Initialization, File1, File2, Analysis, Graphics, {}
  25.         Edit, Filters, Camera, User, Macros1, Macros2, Stacks, Background,  {,UMacroDef, UMacroRun}
  26.         Lut, Projection, Plugins, Text, Math, Registration;
  27.  
  28.  
  29. {Turn off automatic toolbox initialization.}
  30. {$I-}
  31.  
  32.  
  33. {PROCEDURE MacsBug; inline $a9ff;}
  34.  
  35.  
  36.     procedure UpdateOptionsMenu;
  37.         var
  38.             CheckIt: boolean;
  39.             i: integer;
  40.     begin
  41.         with info^ do begin
  42.                 CheckItem(OptionsMenuH, GrayscaleItem, (LutMode = Grayscale) or (LutMode = CustomGrayscale));
  43.                 if LutMode <> PseudoColor then
  44.                     ColorTable := CustomTable;
  45.                 CheckItem(ColorTablesMenuH, SystemPaletteItem, ColorTable = AppleDefault);
  46.                 CheckItem(ColorTablesMenuH, Pseudo20Item, ColorTable = Pseudo20);
  47.                 CheckItem(ColorTablesMenuH, Pseudo32Item, ColorTable = Pseudo32);
  48.                 CheckItem(ColorTablesMenuH, RainbowItem, ColorTable = Rainbow);
  49.                 CheckItem(ColorTablesMenuH, Fire1Item, ColorTable = Fire1);
  50.                 CheckItem(ColorTablesMenuH, Fire2Item, ColorTable = Fire2);
  51.                 CheckItem(ColorTablesMenuH, IceItem, ColorTable = Ice);
  52.                 CheckItem(ColorTablesMenuH, GraysItem, ColorTable = Grays);
  53.                 CheckItem(ColorTablesMenuH, SpectrumItem, ColorTable = Spectrum);
  54.                 SetMenuItem(OptionsMenuH, ScaleToFitItem, info <> NoInfo);
  55.                 CheckIt := ScaleToFitWindow;
  56.                 CheckItem(OptionsMenuH, ScaleToFitItem, CheckIt);
  57.                 CheckItem(OptionsMenuH, ThresholdItem, Thresholding);
  58.                 CheckItem(OptionsMenuH, SliceItem, DensitySlicing);
  59.                 SetMenuItem(OptionsMenuH, PropagateItem, nPics > 1);
  60.             end;
  61.     end;
  62.  
  63.  
  64.     procedure UpdateEnhanceMenu;
  65.         var
  66.             ShowItems: boolean;
  67.             i: integer;
  68.             str: str255;
  69.     begin
  70.         ShowItems := Info <> NoInfo;
  71.         for i := SmoothItem to FilterItem do
  72.             SetMenuItem(EnhanceMenuH, i, ShowItems);
  73.         with info^ do
  74.             if (LutMode = GrayScale) or (LutMode = CustomGrayscale) or DensitySlicing then
  75.                 SetItem(EnhanceMenuH, ApplyItem, 'Apply LUT')
  76.             else
  77.                 SetItem(EnhanceMenuH, ApplyItem, 'Convert to Grayscale');
  78.         if CurrentWindow = TextKind then
  79.             SetItem(EnhanceMenuH, ConvolveItem, 'Convolve')
  80.         else
  81.             SetItem(EnhanceMenuH, ConvolveItem, 'Convolve…');
  82.         for i := BinaryItem to FixColorsItem do
  83.             SetMenuItem(EnhanceMenuH, i, ShowItems);
  84.         NumToString(BinaryCount, str);
  85.         str := concat('Set Count[', str, ']…');
  86.         SetItem(BinaryMenuH, SetCountItem, str);
  87.         NumToString(BinaryIterations, str);
  88.         str := concat('Set Iterations[', str, ']…');
  89.         SetItem(BinaryMenuH, IterationsItem, str);
  90.         CheckItem(BackgroundMenuH, FasterItem, FasterBackgroundSubtraction);
  91.         NumToString(BallRadius, str);
  92.         str := concat('Set Radius[', str, ']…');
  93.         SetItem(BackgroundMenuH, RadiusItem, str);
  94.     end;
  95.  
  96.  
  97.  
  98.  
  99.     procedure UpdateSpecialMenu;
  100.         var
  101.             ShowItems: boolean;
  102.     begin
  103.         ShowItems := Info <> NoInfo;
  104.         SetMenuItem(SpecialMenuH, SaveBlankFieldItem, ShowItems);
  105.         SetMenuItem(SpecialMenuH, PhotoModeItem, ShowItems);
  106.         if CurrentWindow = TextKind then
  107.             SetItem(SpecialMenuH, LoadMacrosItem, 'Load Macros from Window')
  108.         else
  109.             SetItem(SpecialMenuH, LoadMacrosItem, 'Load Macros…')
  110.     end;
  111.  
  112.  
  113.     procedure UpdateStacksMenu;
  114.         var
  115.             ShowItems: boolean;
  116.             isStack: boolean;
  117.     begin
  118.         ShowItems := Info <> NoInfo;
  119.         SetMenuItem(StacksMenuH, StackFromWindowsItem, nPics > 0);
  120.         isStack := info^.StackInfo <> nil;
  121.         SetMenuItem(StacksMenuH, WindowsFromStackItem, isStack);
  122.         SetMenuItem(StacksMenuH, AddSliceItem, isStack);
  123.         SetMenuItem(StacksMenuH, DeleteSliceItem, isStack);
  124.         SetMenuItem(StacksMenuH, NextSliceItem, isStack);
  125.         SetMenuItem(StacksMenuH, PreviousSliceItem, isStack);
  126.         SetMenuItem(StacksMenuH, MakeMovieItem, ShowItems);
  127.         SetMenuItem(StacksMenuH, CaptureFramesItem, ShowItems);
  128.         SetMenuItem(StacksMenuH, AnimateItem, isStack);
  129.         SetMenuItem(StacksMenuH, AverageSlicesItem, isStack);
  130.         SetMenuItem(StacksMenuH, MakeMontageItem, isStack);
  131.         SetMenuItem(StacksMenuH, RegisterItem, isStack);
  132.         SetMenuItem(StacksMenuH, CaptureColorItem, ShowItems);
  133.         SetMenuItem(StacksMenuH, RGBToColorItem, isStack);
  134.         SetMenuItem(StacksMenuH, ColorToRGBItem, ShowItems and (not isStack));
  135.         SetMenuItem(StacksMenuH, RGBToHSVItem, isStack);
  136.         SetMenuItem(StacksMenuH, ProjectItem, isStack);
  137.         SetMenuItem(StacksMenuH, ResliceItem, isStack);
  138.         SetMenuItem(StacksMenuH, ResliceOptionsItem, isStack);
  139.     end;
  140.  
  141.  
  142.     function AboutFilter (d: DialogPtr; var event: EventRecord; var ItemHit: integer): boolean;
  143. { simple filter proc for about box -- must be at top level! % }
  144.     begin
  145.         if (event.what in [MouseDown, KeyDown, AutoKey]) then begin
  146.                 AboutFilter := true;
  147.                 ItemHit := OK;
  148.             end
  149.         else begin
  150.                 AboutFilter := false;
  151.                 ItemHit := 0;
  152.             end;
  153.     end;
  154.  
  155.  
  156.     procedure AboutUProc (d: DialogPtr; item: integer);
  157. { About box user proc -- must be at top level!}
  158.         var
  159.             s: str255;
  160.             saveport: grafptr;
  161.             VersInfo: str255;
  162.     begin
  163.         getport(saveport);
  164.         setport(d);
  165.         if (item = MemItem) then begin
  166.                 NumToString(FreeMem div 1024, s);
  167.                 s := concat(s, 'K free');
  168.                 DrawSItem(MemItem, Geneva, 9, d, s);
  169.             end
  170.         else if (item = VersItem) then begin
  171.                 RealToString(version / 100.0, 4, 2, VersInfo);
  172.                 VersInfo := concat('Version ', VersInfo);
  173.                 DrawSItem(VersItem, Geneva, 9, d, VersInfo);
  174.             end;
  175.         setport(saveport);
  176.     end;
  177.  
  178.  
  179.     procedure DoAbout;
  180.   {About Box by David Powell}
  181.         var
  182.             i: integer;
  183.             d: dialogptr;
  184.             midscreen: point;
  185.             r: rect;
  186.             h: handle;
  187.             itype: integer;
  188.     begin
  189.         d := getnewdialog(AboutID, nil, pointer(-1));
  190.         if (d <> nil) then begin
  191.                 SetPort(d);
  192.                 GetDItem(d, VersItem, itype, h, r);
  193.                 SetDItem(d, VersItem, itype, @AboutUProc, r);
  194.                 GetDItem(d, MemItem, itype, h, r);
  195.                 SetDItem(d, MemItem, itype, @AboutUProc, r);
  196.                 ShowWindow(d);
  197.                 repeat
  198.                     ModalDialog(@aboutfilter, i);
  199.                 until (i = OK);
  200.                 DisposDialog(d);
  201.                 FlushEvents(EveryEvent, 0);
  202.             end;
  203.     end;
  204.  
  205.  
  206.     procedure DoPreferences;
  207.         const
  208.             BufferSizeID = 4;
  209.             ScaleArithmeticID = 6;
  210.             ScaleConvolutionsID = 7;
  211.             InvertValuesID = 8;
  212.             InvertYID = 9;
  213.             LW6ID = 10;
  214.             SwitchingID = 11;
  215.             HighlightID = 12;
  216.             CreatorID = 14;
  217.         var
  218.             mylog: DialogPtr;
  219.             item, i: integer;
  220.             SaveScale, SaveLW6, SaveScaleC: boolean;
  221.             SaveInvertValues, SaveInvertY: boolean;
  222.             SaveBufferSize: LongInt;
  223.             SaveCreator: packed array[1..4] of char;
  224.     begin
  225.         InitCursor;
  226.         SaveBufferSize := BufferSize;
  227.         SaveScale := ScaleArithmetic;
  228.         SaveInvertY := InvertYCoordinates;
  229.         SaveLW6 := DriverHalftoning;
  230.         SaveScaleC := ScaleConvolutions;
  231.         SaveCreator := TextCreator;
  232.         mylog := GetNewDialog(6000, nil, pointer(-1));
  233.         SetDNum(MyLog, BufferSizeID, BufferSize div 1024);
  234.         SetDialogItem(mylog, ScaleArithmeticID, ord(ScaleArithmetic));
  235.         SetDialogItem(mylog, ScaleConvolutionsID, ord(ScaleConvolutions));
  236.         SetDialogItem(mylog, InvertYID, ord(InvertYCoordinates));
  237.         SetDialogItem(mylog, LW6ID, ord(not DriverHalftoning));
  238.         SetDialogItem(mylog, SwitchingID, ord(SwitchLUTOnSuspend));
  239.         SetDialogItem(mylog, HighlightID, ord(HighlightMode));
  240.         SaveInvertValues := InvertPixelValues;
  241.         if InvertPixelValues then
  242.             SetDialogItem(mylog, InvertValuesID, 1);
  243.         SetDString(mylog, CreatorID, TextCreator);
  244.         repeat
  245.             ModalDialog(nil, item);
  246.             if item = BufferSizeID then begin
  247.                     BufferSize := GetDNum(MyLog, BufferSizeID) * 1024;
  248.                     if BufferSize < 1 then begin
  249.                             beep;
  250.                             BufferSize := 1;
  251.                             SetDNum(MyLog, BufferSizeID, BufferSize);
  252.                         end;
  253.                 end;
  254.             if item = ScaleArithmeticID then begin
  255.                     ScaleArithmetic := not ScaleArithmetic;
  256.                     SetDialogItem(mylog, ScaleArithmeticID, ord(ScaleArithmetic));
  257.                     if PasteControl <> nil then
  258.                         DrawPasteControl
  259.                 end;
  260.             if item = ScaleConvolutionsID then begin
  261.                     ScaleConvolutions := not ScaleConvolutions;
  262.                     SetDialogItem(mylog, ScaleConvolutionsID, ord(ScaleConvolutions));
  263.                 end;
  264.             if item = InvertValuesID then begin
  265.                     InvertPixelValues := not InvertPixelValues;
  266.                     SetDialogItem(mylog, InvertValuesID, ord(InvertPixelValues));
  267.                 end;
  268.             if item = InvertYID then begin
  269.                     InvertYCoordinates := not InvertYCoordinates;
  270.                     SetDialogItem(mylog, InvertYID, ord(InvertYCoordinates));
  271.                 end;
  272.             if item = LW6ID then begin
  273.                     DriverHalftoning := not DriverHalftoning;
  274.                     SetDialogItem(mylog, LW6ID, ord(not DriverHalftoning));
  275.                 end;
  276.             if item = SwitchingID then begin
  277.                     SwitchLUTOnSuspend := not SwitchLUTOnSuspend;
  278.                     SetDialogItem(mylog, SwitchingID, ord(SwitchLUTOnSuspend));
  279.                 end;
  280.             if item = HighlightID then begin
  281.                     HighlightMode := not HighlightMode;
  282.                     SetDialogItem(mylog, HighlightID, ord(HighlightMode));
  283.                     LoadLUT(info^.ctable);
  284.                 end;
  285.             if item = CreatorID then
  286.                 TextCreator := GetDString(mylog, item);
  287.         until (item = ok) or (item = cancel);
  288.         DisposDialog(mylog);
  289.         if item = cancel then begin
  290.                 BufferSize := SaveBufferSize;
  291.                 ScaleArithmetic := SaveScale;
  292.                 ScaleConvolutions := SaveScaleC;
  293.                 InvertYCoordinates := SaveInvertY;
  294.                 DriverHalftoning := SaveLW6;
  295.                 if PasteControl <> nil then
  296.                     DrawPasteControl;
  297.                 TextCreator := SaveCreator;
  298.             end
  299.         else
  300.             with info^ do begin
  301.                     if InvertPixelValues and (SaveInvertValues = false) then
  302.                         InvertgrayLevels
  303.                     else if (InvertPixelValues = false) and SaveInvertValues then begin
  304.                             DensityCalibrated := false;
  305.                             DrawLabels('', '', '');
  306.                         end;
  307.                     UpdateTitleBar;
  308.                 end;
  309.         if BufferSize <> SaveBufferSIze then
  310.             PutMessage('You must "Record Preferences" and restart before the Undo and Clipboard buffer size change will take effect.');
  311.     end;
  312.  
  313.  
  314.     procedure UpdateWindowsMenu;
  315.         var
  316.             i, n: integer;
  317.     begin
  318.         for i := NextImageItem to CascadeImagesItem do
  319.             SetMenuItem(WindowsMenuH, i, nPics > 1);
  320.         for i := SelectToolsItem to SelectResultsItem do
  321.             CheckItem(WindowsMenuH, i, false);
  322.         SetMenuItem(WindowsMenuH, SelectHistogramItem, HistoWindow <> nil);
  323.         SetMenuItem(WindowsMenuH, SelectPlotItem, PlotWindow <> nil);
  324.         SetMenuItem(WindowsMenuH, SelectResultsItem, ResultsWindow <> nil);
  325.         for i := 1 to nTextWindows do
  326.             CheckItem(WindowsMenuH, WindowsMenuItems - 1 + i, false);
  327.         for i := 1 to nPics do
  328.             CheckItem(WindowsMenuH, WindowsMenuItems + nTextWindows + i, false);
  329.         if PasteControl = nil then
  330.             SetItem(WindowsMenuH, PasteControlItem, 'Show Paste Control')
  331.         else
  332.             SetItem(WindowsMenuH, PasteControlItem, 'Hide Paste Control');
  333.         if CurrentKind < 0 then
  334.             exit(UpdateWindowsMenu); {System Window}
  335.         case CurrentKind of
  336.             ToolKind: 
  337.                 CheckItem(WindowsMenuH, SelectToolsItem, true);
  338.             MapKind: 
  339.                 CheckItem(WindowsMenuH, SelectGrayMapItem, true);
  340.             LUTKind: 
  341.                 CheckItem(WindowsMenuH, SelectLutItem, true);
  342.             InfoKind: 
  343.                 CheckItem(WindowsMenuH, SelectInfoItem, true);
  344.             HistoKind: 
  345.                 CheckItem(WindowsMenuH, SelectHistogramItem, true);
  346.             ProfilePlotKind, CalibrationPLotKind: 
  347.                 CheckItem(WindowsMenuH, SelectPlotItem, true);
  348.             ResultsKind: 
  349.                 CheckItem(WindowsMenuH, SelectResultsItem, true);
  350.             TextKind:  begin
  351.                     if TextInfo <> nil then
  352.                         CheckItem(WindowsMenuH, WindowsMenuItems - 1 + TextInfo^.WindowNum, true);
  353.                 end;
  354.             PicKind: 
  355.                 CheckItem(WindowsMenuH, WindowsMenuItems + nTextWindows + info^.PicNum, true);
  356.             otherwise
  357.         end;
  358.     end;
  359.  
  360.  
  361.  
  362.  
  363.     procedure CloseAll;
  364.     FORWARD;
  365.  
  366.  
  367.     procedure DoNew;
  368.         const
  369.             ImageID = 4;
  370.             TextID = 5;
  371.             WidthID = 6;
  372.             HeightID = 7;
  373.             TitleID = 8;
  374.         var
  375.             mylog: DialogPtr;
  376.             item, i: integer;
  377.             SaveWidth, SaveHeight: integer;
  378.             SaveTitle: string[31];
  379.             okay, OpenImage: boolean;
  380.  
  381.         procedure SetButtons;
  382.         begin
  383.             SetDialogItem(mylog, ImageID, ord(OpenImage));
  384.             SetDialogItem(mylog, TextID, ord(not OpenImage));
  385.         end;
  386.  
  387.     begin
  388.         InitCursor;
  389.         OpenImage := true;
  390.         SaveWidth := NewPicWidth;
  391.         SaveHeight := NewPicHeight;
  392.         SaveTitle := NewTitle;
  393.         mylog := GetNewDialog(180, nil, pointer(-1));
  394.         SetButtons;
  395.         SetDNum(MyLog, WidthID, NewPicWidth);
  396.         SelIText(MyLog, WidthID, 0, 32767);
  397.         SetDNum(MyLog, HeightID, NewPicHeight);
  398.         SetDString(MyLog, TitleID, NewTitle);
  399.         repeat
  400.             ModalDialog(nil, item);
  401.             if item = ImageID then begin
  402.                     OpenImage := true;
  403.                     SetButtons;
  404.                 end;
  405.             if item = TextID then begin
  406.                     OpenImage := false;
  407.                     SetButtons;
  408.                 end;
  409.             if item = WidthID then begin
  410.                     NewPicWidth := GetDNum(MyLog, WidthID);
  411.                     if (NewPicWidth < 0) or (NewPicWidth > MaxPicSize) then begin
  412.                             NewPicWidth := SaveWidth;
  413.                             SetDNum(MyLog, WidthID, NewPicWidth);
  414.                         end;
  415.                 end;
  416.             if item = HeightID then begin
  417.                     NewPicHeight := GetDNum(MyLog, HeightID);
  418.                     if (NewPicHeight < 0) or (NewPicHeight > MaxPicSize) then begin
  419.                             NewPicHeight := SaveHeight;
  420.                             SetDNum(MyLog, HeightID, NewPicHeight);
  421.                         end;
  422.                 end;
  423.         until (item = ok) or (item = cancel);
  424.         if item = ok then
  425.             NewTitle := GetDString(MyLog, TitleID);
  426.         DisposDialog(mylog);
  427.         if NewPicWidth < 32 then
  428.             NewPicWidth := 32;
  429.         if odd(NewPicWidth) then
  430.             NewPicWidth := NewPicWidth + 1;
  431.         if NewPicHeight < 16 then
  432.             NewPicHeight := 16;
  433.         if item = cancel then begin
  434.                 NewPicWidth := SaveWidth;
  435.                 NewPicHeight := SaveHeight;
  436.                 NewTitle := SaveTitle;
  437.                 exit(DoNew);
  438.             end;
  439.         if OpenImage then begin
  440.                 okay := NewPicWindow(NewTitle, NewPicWidth, NewPicHeight);
  441.                 if okay then
  442.                     if info^.PixMapSize > UndoBufSize then
  443.                         PutWarning;
  444.             end
  445.         else
  446.             okay := MakeNewTextWindow(NewTitle, 500, 400);
  447.     end;
  448.  
  449.  
  450.     procedure DoMenuEvent (MenuChoice: LongInt);
  451.         var
  452.             MenuID, MenuItem, i, ignore: integer;
  453.             name, str: str255;
  454.             dna, RefNum: integer;
  455.             ItemName: str255;
  456.             FontName: str255;
  457.             ok, isSelection: boolean;
  458.             NewStyle: StyleItem;
  459.             t: FateTable;  {Only needed for MakeSkeleton}
  460.             SaveBFInfo: InfoPtr;
  461.     begin
  462.         MenuID := HiWord(MenuChoice);
  463.         MenuItem := LoWord(MenuChoice);
  464.         case MenuID of
  465.  
  466.             AppleMenu:  begin
  467.                     if MenuItem = 1 then
  468.                         DoAbout
  469.                     else begin
  470.                             GetItem(GetMHandle(AppleMenu), MenuItem, name);
  471.                             ignore := OpenDeskAcc(name)
  472.                         end;
  473.                 end;
  474.  
  475.             FileMenu:  begin
  476.                     StopDigitizing;
  477.                     isInsertionPoint := false;
  478.                     case MenuItem of
  479.                         NewItem: 
  480.                             DoNew;
  481.                         OpenItem: 
  482.                             ok := DoOpen('', 0);
  483.                         ImportItem: 
  484.                             ok := ImportFile('', 0);
  485.             {-}
  486.                         CloseItem: 
  487.                             if OptionKeyWasDown and (CurrentWindow <> TextKInd) then
  488.                                 CloseAll
  489.                             else
  490.                                 DoClose;
  491.                         SaveItem: 
  492.                             if OptionKeyWasDown and (info^.StackInfo = nil) and (CurrentWindow <> TextKind) then
  493.                                 SaveAll
  494.                             else
  495.                                 SaveFile;
  496.                         SaveAsItem: 
  497.                             case CurrentWindow of
  498.                                 TextKind: 
  499.                                     SaveTextAs;
  500.                                 ResultsKind: 
  501.                                     Export('', 0);
  502.                                 otherwise
  503.                                     SaveAs('', 0);
  504.                             end;
  505.                         ExportItem: 
  506.                             Export('', 0);
  507.            {-}
  508.                         RecordPreferencesItem: 
  509.                             SaveSettings;
  510.                         RevertItem: 
  511.                             with info^ do
  512.                                 if DataType = EightBits then
  513.                                     RevertToSaved
  514.                                 else
  515.                                     RescaleToEightBits;
  516.                         DuplicateItem: 
  517.                             ok := Duplicate('', false);
  518.                         GetInfoItem: 
  519.                             GetInfo;
  520.        {-}
  521.                         SetHalftoneItem: 
  522.                             SetHalftone;
  523.                         PageSetupItem: 
  524.                             DoPageSetup;
  525.                         PrintItem: 
  526.                             Print(true);
  527.        {-}
  528.                         QuitItem: 
  529.                             finished := true;
  530.                     end;
  531.                 end;
  532.  
  533.             AcquireMenu: 
  534.                 RunAcqPlugIn(MenuItem);
  535.  
  536.             ExportMenu: 
  537.                 RunExportPlugIn(MenuItem);
  538.  
  539.             EditMenu:  begin
  540.                     StopDigitizing;
  541.                     GetItem(GetMHandle(EditMenu), MenuItem, ItemName);
  542.                     if not SystemEdit(MenuItem - 1) then
  543.                         case MenuItem of
  544.                             UndoItem: 
  545.                                 DoUndo;
  546.              {-}
  547.                             CutItem: 
  548.                                 DoCut;
  549.                             CopyItem: 
  550.                                 DoCopy;
  551.                             PasteItem: 
  552.                                 DoPaste;
  553.                             ClearItem: 
  554.                                 DoClear;
  555.             {-}
  556.                             FillItem: 
  557.                                 if CurrentWindow = TextKind then
  558.                                     DoFind
  559.                                 else
  560.                                     SetupOperation(FillItem);
  561.                             InvertItem, DrawBoundaryItem: 
  562.                                 SetupOperation(MenuItem);
  563.                             DrawScaleItem: 
  564.                                 DrawScale;
  565.              {-}
  566.                             SelectAllItem: 
  567.                                 with info^ do
  568.                                     if RoiShowing and EqualRect(RoiRect, PicRect) then
  569.                                         KillRoi
  570.                                     else
  571.                                         SelectAll(true);
  572.                             ScaleAndRotateItem: 
  573.                                 ScaleAndRotate;
  574.               {-}
  575.                             RotateLeftItem: 
  576.                                 Rotate(RotateLeft);
  577.                             RotateRightItem: 
  578.                                 Rotate(RotateRight);
  579.                             FlipVerticalItem: 
  580.                                 FlipOrRotate(FlipVertical);
  581.                             FlipHorizontalItem: 
  582.                                 FlipOrRotate(FlipHorizontal);
  583.               {-}
  584.                             UnzoomItem: 
  585.                                 Unzoom;
  586.                             ShowClipboardItem: 
  587.                                 ShowClipboard;
  588.                         end;
  589.                 end;
  590.  
  591.             OptionsMenu:  begin
  592.                     case MenuItem of
  593.                         GrayscaleItem: 
  594.                             ResetGrayMap;
  595.                         LutOptionsItem: 
  596.                             DoLutOptions;
  597.            {-}
  598.                         PreferencesItem: 
  599.                             DoPreferences;
  600.                         PlotOptionsItem: 
  601.                             DoProfilePlotOptions;
  602.                         ScaleToFitItem: 
  603.                             ScaleToFit;
  604.                         ThresholdItem:  begin
  605.                                 if DensitySlicing then
  606.                                     DisableDensitySlice;
  607.                                 if Info^.Thresholding then
  608.                                     DisableThresholding
  609.                                 else begin
  610.                                         SetupLutUndo;
  611.                                         AutoThreshold;
  612.                                     end;
  613.                             end;
  614.                         SliceItem: 
  615.                             if DensitySlicing then
  616.                                 DisableDensitySlice
  617.                             else begin
  618.                                     if info^.thresholding then
  619.                                         DisableThresholding;
  620.                                     EnableDensitySlice;
  621.                                 end;
  622.                     end;
  623.                 end;
  624.  
  625.             ColorTablesMenu: 
  626.                 SwitchColorTables(MenuItem, true);
  627.  
  628.             FontMenu:  begin
  629.                     GetItem(FontMenuH, MenuItem, FontName);
  630.                     GetFNum(FontName, CurrentFontID);
  631.                     DisplayText(true);
  632.                     if CurrentWindow = TextKind then
  633.                         ChangeFontOrSize;
  634.                 end;
  635.  
  636.             SizeMenu:  begin
  637.                     case MenuItem of
  638.                         1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12: 
  639.                             CurrentSize := GetFontSize(MenuItem);
  640.                     end;
  641.                     DisplayText(true);
  642.                     if IsInsertionPoint then
  643.                         UpdatePicWindow;
  644.                     if CurrentWindow = TextKind then
  645.                         ChangeFontOrSize;
  646.                 end;
  647.  
  648.             StyleMenu:  begin
  649.                     case MenuItem of
  650.                         1: 
  651.                             CurrentStyle := [];
  652.                         2, 3, 4, 5, 6:  begin
  653.                                 case MenuItem of
  654.                                     TxBold: 
  655.                                         NewStyle := Bold;
  656.                                     TxItalic: 
  657.                                         NewStyle := Italic;
  658.                                     TxUnderLine: 
  659.                                         NewStyle := Underline;
  660.                                     TxOutLine: 
  661.                                         NewStyle := Outline;
  662.                                     TxShadow: 
  663.                                         NewStyle := Shadow;
  664.                                 end;
  665.                                 if NewStyle in CurrentStyle then
  666.                                     CurrentStyle := CurrentStyle - [NewStyle]
  667.                                 else
  668.                                     CurrentStyle := CurrentStyle + [NewStyle];
  669.                             end;
  670.                         LeftItem: 
  671.                             TextJust := teJustLeft;
  672.                         CenterItem: 
  673.                             TextJust := teJustCenter;
  674.                         RightItem: 
  675.                             TextJust := teJustRight;
  676.                         NoBackgroundItem: 
  677.                             TextBack := NoBack;
  678.                         WithBackgroundItem: 
  679.                             TextBack := WithBack;
  680.                     end; {case}
  681.                     DisplayText(true);
  682.                 end;
  683.  
  684.             PropagateMenu: 
  685.                 DoPropagate(MenuItem);
  686.  
  687.             EnhanceMenu:  begin
  688.                     StopDigitizing;
  689.                     SetupUndo;
  690.                     case MenuItem of
  691.                         SmoothItem: 
  692.                             if OptionKeyDown then
  693.                                 Filter(UnweightedAvg, 0, t)
  694.                             else
  695.                                 Filter(WeightedAvg, 0, t);
  696.                         SharpenItem: 
  697.                             Filter(fsharpen, 0, t);
  698.                         ShadowItem: 
  699.                             Filter(fshadow, 0, t);
  700.                         EdgeDetectItem: 
  701.                             Filter(EdgeDetect, 0, t);
  702.                         ReduceNoiseItem: 
  703.                             Filter(ReduceNoise, 0, t);
  704.                         DitherItem: 
  705.                             Filter(Dither, 0, t);
  706.                         ConvolveItem: 
  707.                             if CurrentWindow = TextKind then
  708.                                 ConvolveUsingText
  709.                             else
  710.                                 Convolve('', 0);
  711.            {-}
  712.                         ImageMathItem: 
  713.                             DoImageMath;
  714.                         ApplyItem: 
  715.                             ApplyLookupTable;
  716.                         EnhanceItem: 
  717.                             EnhanceContrast;
  718.                         EqualizeItem: 
  719.                             EqualizeHistogram;
  720.                         FixColorsItem: 
  721.                             if not isBinaryImage then
  722.                                 FixColors;
  723.                     end;
  724.                 end;
  725.  
  726.             FilterMenu: 
  727.                 RunFilterPlugin(menuItem);
  728.  
  729.             BinaryMenu: 
  730.                 case MenuItem of
  731.                     MakeBinaryItem: 
  732.                         MakeBinary;
  733.                     ErosionItem: 
  734.                         DoErosion;
  735.                     DilationItem: 
  736.                         DoDilation;
  737.                     OpeningItem: 
  738.                         DoOpening;
  739.                     ClosingItem: 
  740.                         DoClosing;
  741.                     SetCountItem: 
  742.                         SetBinaryCount;
  743.                     IterationsItem: 
  744.                         SetIterations;
  745.                     OutlineItem: 
  746.                         filter(OutlineFilter, 0, t);
  747.                     SkeletonizeItem: 
  748.                         MakeSkeleton;
  749.                 end;
  750.  
  751.             ArithmeticMenu: 
  752.                 DoArithmetic(MenuItem, 0);
  753.  
  754.             BackgroundMenu: 
  755.                 DoBackgroundMenuEvent(MenuItem);
  756.  
  757.             AnalyzeMenu:  begin
  758.                     if MenuItem <> HistogramItem then
  759.                         StopDigitizing;
  760.                     SetupUndo;
  761.                     case MenuItem of
  762.                         MeasureItem: 
  763.                             Measure;
  764.                         AnalyzeItem: 
  765.                             AnalyzeParticles;
  766.                         ShowItem: 
  767.                             ShowResults;
  768.                         OptionsItem: 
  769.                             DoMeasurementOptions;
  770.                         HistogramItem: 
  771.                             DoHistogram;
  772.                         PlotItem: 
  773.                             PlotDensityProfile;
  774.                         PlotSurfaceItem: 
  775.                             PlotSurface;
  776.           {-}
  777.                         SetScaleItem: 
  778.                             SetScale;
  779.                         CalibrateItem: 
  780.                             Calibrate;
  781.                         RedoItem: 
  782.                             RedoMeasurement;
  783.                         DeleteItem: 
  784.                             DeleteMeasurement;
  785.                         ResetItem: 
  786.                             ResetCounter;
  787.                         RestoreItem: 
  788.                             RestoreRoi;
  789.                         MarkItem: 
  790.                             MarkSelection(mCount);
  791.                     end;
  792.                 end;
  793.  
  794.             SpecialMenu:  begin
  795.                     case MenuItem of
  796.                         StartItem: 
  797.                             StartDigitizing;
  798.                         AverageItem: 
  799.                             AverageFrames;
  800.                         SaveBlankFieldItem:  begin
  801.                                 SaveBFInfo := BlankFieldInfo;
  802.                                 BlankFieldInfo := nil; {Prevents shading correction.}
  803.                                 StopDigitizing;
  804.                                 BlankFieldInfo := SaveBFInfo;
  805.                                 SaveBlankField;
  806.                             end;
  807.                         VideoControlItem: 
  808.                             if VideoControl = nil then
  809.                                 ShowVideoControl
  810.                             else
  811.                                 SelectWindow(VideoControl);
  812.                         PhotoModeItem: 
  813.                             PhotoMode;
  814.                         LoadMacrosItem:  begin
  815.                                 LoadMacros;
  816.                                 UnloadSeg(@LoadMacros)
  817.                             end;
  818.                         otherwise
  819.                             if MenuItem >= FirstMacroItem then
  820.                                 RunMacro(MenuItem - FirstMacroItem + 1);
  821.                     end;
  822.                 end;
  823.  
  824.             StacksMenu:  begin
  825.                     StopDigitizing;
  826.                     case MenuItem of
  827.                         StackFromWindowsItem: 
  828.                             MakeStack;
  829.                         WindowsFromStackItem: 
  830.                             MakeWindowsFromStack;
  831.                         AddSliceItem: 
  832.                             ok := AddSlice(true);
  833.                         DeleteSliceItem: 
  834.                             DeleteSlice;
  835.                         NextSliceItem, PreviousSliceItem: 
  836.                             ShowNextSlice(MenuItem);
  837.                         MakeMovieItem: 
  838.                             MakeMovie;
  839.                         CaptureFramesItem: 
  840.                             CaptureFrames;
  841.                         AnimateItem: 
  842.                             Animate;
  843.                         AverageSlicesItem: 
  844.                             AverageSlices;
  845.                         MakeMontageItem: 
  846.                             MakeMontage;
  847.                         CaptureColorItem: 
  848.                             CaptureColor;
  849.                         RGBToColorItem: 
  850.                             ConvertRGBToEightBitColor(false);
  851.                         ColorToRGBItem: 
  852.                             ConvertEightBitColorToRGB;
  853.                         RGBToHSVItem: 
  854.                             ConvertRGBToHSV;
  855.                         RegisterItem: 
  856.                             DoRegister;
  857.                         ProjectItem: 
  858.                             Project;
  859.                         ResliceItem: 
  860.                             Reslice;
  861.                         ResliceOptionsItem: 
  862.                             DoResliceOptions;
  863.                         otherwise
  864.                             beep
  865.                     end;
  866.                 end;
  867.  
  868.             WindowsMenu:  begin
  869.                     if MenuItem <> PasteControlItem then
  870.                         StopDigitizing;
  871.                     case MenuItem of
  872.                         NextImageItem: 
  873.                             ShowNextImage;
  874.                         StackImagesItem: 
  875.                             StackImages;
  876.                         CascadeImagesItem: 
  877.                             CascadeImages;
  878.                         PasteControlItem: 
  879.                             if PasteControl = nil then
  880.                                 ShowPasteControl
  881.                             else
  882.                                 ignore := CloseAWindow(PasteControl);
  883.             {-}
  884.                         SelectToolsItem: 
  885.                             SelectWindow(ToolWindow);
  886.                         SelectGrayMapItem: 
  887.                             SelectWindow(MapWindow);
  888.                         SelectLutItem: 
  889.                             SelectWindow(LUTWindow);
  890.                         SelectInfoItem: 
  891.                             SelectWindow(InfoWindow);
  892.                         SelectHistogramItem: 
  893.                             if HistoWindow <> nil then
  894.                                 SelectWindow(HistoWindow);
  895.                         SelectPlotItem: 
  896.                             if PlotWindow <> nil then
  897.                                 SelectWindow(PlotWindow);
  898.                         SelectResultsItem: 
  899.                             if ResultsWindow <> nil then
  900.                                 SelectWindow(ResultsWindow);
  901.           {-}
  902.                         otherwise
  903.                             if MenuItem <= (WindowsMenuItems - 1 + nTextWindows) then
  904.                                 SelectWindow(TextWindow[MenuItem - (WindowsMenuItems - 1)])
  905.                             else
  906.                                 SelectWindow(PicWindow[MenuItem - (WindowsMenuItems + nTextWindows)]);
  907.                     end;
  908.                 end;
  909.  
  910.             UserMenu: 
  911.                 DoUserMenuEvent(MenuItem);
  912.             otherwise
  913.         end;
  914.         HiliteMenu(0);
  915.         RoiUpdateTime := 0;
  916.     end;
  917.  
  918.  
  919.     procedure DoFreehand;
  920.         var
  921.             finish: point;
  922.             event: EventRecord;
  923.             wright, wbottom: integer;
  924.             b: boolean;
  925.     begin
  926.         SetPort(info^.wptr);
  927.         PenPat(pat[PatIndex]);
  928.         PenSize(1, 1);
  929.         with info^.wptr^.PortRect do begin
  930.                 wright := right;
  931.                 wbottom := bottom;
  932.             end;
  933.         while Button do begin
  934.                 GetMouse(finish);
  935.                 with finish do begin
  936.                         if h < 0 then
  937.                             h := 0;
  938.                         if v < 0 then
  939.                             v := 0;
  940.                         if h > wright then
  941.                             h := wright;
  942.                         if v > wbottom then
  943.                             v := wbottom;
  944.                         if (xCoordinates^[nCoordinates] <> h) or (yCoordinates^[nCoordinates] <> v) then begin
  945.                                 if nCoordinates < MaxCoordinates then
  946.                                     nCoordinates := nCoordinates + 1
  947.                                 else
  948.                                     beep;
  949.                                 LineTo(h, v);
  950.                                 xCoordinates^[nCoordinates] := h;
  951.                                 yCoordinates^[nCoordinates] := v;
  952.                                 wait(1);
  953.                             end; {if mouse has moved}
  954.                     end; {with}
  955.             end; {while Button}
  956.     end;
  957.  
  958.  
  959.     procedure DoPolygon (start: point);
  960.         var
  961.             Finish, OldFinish: point;
  962.             finished, DoubleClick, done: boolean;
  963.             ticks, MouseUpTime, LastMouseUpTime: LongInt;
  964.             wright, wbottom: integer;
  965.             StartRect: rect;
  966.             MouseDown, MouseUpEvent: boolean;
  967.     begin
  968.         DrawLabels('DX:', 'DY:', 'Length:');
  969.         SetPort(info^.wptr);
  970.         PenMode(PatXor);
  971.         PenSize(1, 1);
  972.         if CurrentTool = PolygonTool then begin
  973.                 Pt2Rect(Start, Start, StartRect);
  974.                 InsetRect(StartRect, -4, -4);
  975.                 FrameRect(StartRect);
  976.             end
  977.         else
  978.             SetRect(StartRect, 0, 0, 0, 0);
  979.         finish := start;
  980.         finished := false;
  981.         with info^.wptr^.PortRect do begin
  982.                 wright := right;
  983.                 wbottom := bottom;
  984.             end;
  985.         MouseUpTime := 0;
  986.         done := false;
  987.         MouseUpEvent := false;
  988.         MouseDown := button;
  989.         repeat
  990.             ShowDxDy(0, 0);
  991.             repeat
  992.                 OldFinish := finish;
  993.                 GetMouse(finish);
  994.                 with finish do begin
  995.                         if h < 0 then begin
  996.                                 h := 0;
  997.                                 done := CurrentTool = LineTool;
  998.                             end;
  999.                         if v < 0 then begin
  1000.                                 v := 0;
  1001.                                 done := CurrentTool = LineTool;
  1002.                             end;
  1003.                         if h > wright then begin
  1004.                                 h := wright;
  1005.                                 done := CurrentTool = LineTool;
  1006.                             end;
  1007.                         if v > wbottom then begin
  1008.                                 v := wbottom;
  1009.                                 done := CurrentTool = LineTool;
  1010.                             end;
  1011.                     end;
  1012.                 if not EqualPt(finish, OldFinish) then begin
  1013.                         ticks := TickCount;
  1014.                         repeat
  1015.                         until TickCount <> ticks;
  1016.                         MoveTo(start.h, start.v);
  1017.                         LineTo(OldFinish.h, OldFinish.v);
  1018.                         MoveTo(start.h, start.v);
  1019.                         LineTo(finish.h, finish.v);
  1020.                         ShowDxDy(abs(finish.h - start.h), abs(finish.v - start.v));
  1021.                     end;
  1022.                 if button <> MouseDown then begin
  1023.                         MouseUpEvent := not button;
  1024.                         MouseDown := button;
  1025.                     end;
  1026.             until MouseUpEvent;
  1027.             MouseUpEvent := false;
  1028.             LastMouseUpTime := MouseUpTime;
  1029.             MouseUpTime := TickCount;
  1030.             DoubleClick := ((MouseUpTime - LastMouseUpTime) < GetDblTime) and EqualPt(start, finish);
  1031.             if nCoordinates < MaxCoordinates then
  1032.                 nCoordinates := nCoordinates + 1
  1033.             else
  1034.                 beep;
  1035.             xCoordinates^[nCoordinates] := finish.h;
  1036.             yCoordinates^[nCoordinates] := finish.v;
  1037.             start := finish;
  1038.             Finished := (PtInRect(finish, StartRect) or DoubleClick or done) and (nCoordinates > 2);
  1039.         until finished;
  1040.         FlushEvents(EveryEvent, 0);
  1041.     end;
  1042.  
  1043.  
  1044.     procedure MakePolygon (event: EventRecord);
  1045.         var
  1046.             Start: point;
  1047.             i: integer;
  1048.     begin
  1049.         with info^ do begin
  1050.                 start := event.where;
  1051.                 SetPort(wptr);
  1052.                 PenNormal;
  1053.                 xCoordinates^[1] := Start.h;
  1054.                 yCoordinates^[1] := Start.v;
  1055.                 nCoordinates := 1;
  1056.                 MoveTo(start.h, start.v);
  1057.                 case CurrentTool of
  1058.                     FreehandTool:  begin
  1059.                             DoFreehand;
  1060.                             with Start do
  1061.                                 LineTo(h, v);
  1062.                         end;
  1063.                     PolygonTool: 
  1064.                         DoPolygon(start);
  1065.                 end;
  1066.                 if nCoordinates > 2 then begin
  1067.                         ConvertCoordinates;
  1068.                         if CurrentTool = PolygonTool then
  1069.                             MakeOutline(PolygonRoi)
  1070.                         else
  1071.                             MakeOutline(FreehandRoi);
  1072.                     end
  1073.                 else begin
  1074.                         KillRoi;
  1075.                         UpdatePicWindow;
  1076.                     end;
  1077.             end; {with}
  1078.     end;
  1079.  
  1080.  
  1081.     procedure MakeLineRoi (event: EventRecord);
  1082.         var
  1083.             Start: point;
  1084.     begin
  1085.         start := event.where;
  1086.         with Info^ do begin
  1087.                 if PixMapSize > UndoBufSize then begin
  1088.                         beep;
  1089.                         exit(MakeLineRoi);
  1090.                     end;
  1091.                 WhatToUndo := NothingToUndo;
  1092.                 measuring := false;
  1093.                 if LOIType = Straight then begin
  1094.                         DoObject(LineObj, event);
  1095.                         RoiType := LineRoi;
  1096.                         MakeRegion;
  1097.                         RoiShowing := true;
  1098.                         SetupUndo;
  1099.                         exit(MakeLineRoi);
  1100.                     end;
  1101.                 SetPort(wptr);
  1102.                 PenNormal;
  1103.                 MoveTo(start.h, start.v);
  1104.                 xCoordinates^[1] := Start.h;
  1105.                 yCoordinates^[1] := Start.v;
  1106.                 nCoordinates := 1;
  1107.             end; {with info}
  1108.         if LOIType = Freehand then
  1109.             DoFreehand
  1110.         else
  1111.             DoPolygon(start);
  1112.         if nCoordinates > 1 then
  1113.             case LoiType of
  1114.                 freehand: 
  1115.                     MakeNonStraightLineRoi(FreeLineRoi);
  1116.                 segmented: 
  1117.                     MakeNonStraightLineRoi(SegLineRoi);
  1118.             end
  1119.         else
  1120.             with info^ do begin
  1121.                     RoiShowing := false;
  1122.                     RoiType := NoRoi;
  1123.                     UpdatePicWindow;
  1124.                 end;
  1125.     end;
  1126.  
  1127.  
  1128.     procedure DoProfilePlot (event: EventRecord);
  1129.         var
  1130.             ulength, clength: real;
  1131.     begin
  1132.         with Info^ do begin
  1133.                 WhatToUndo := NothingToUndo;
  1134.                 measuring := false;
  1135.                 DoObject(LineObj, event);
  1136.                 RoiType := LineRoi;
  1137.                 MakeRegion;
  1138.                 RoiShowing := true;
  1139.                 SetupUndo;
  1140.                 GetLengthOrPerimeter(ulength, clength);
  1141.                 if ulength > 0 then
  1142.                     PlotDensityProfile
  1143.             end;
  1144.     end;
  1145.  
  1146.  
  1147.     procedure DoMouseDownInWindow (event: EventRecord; WhichWindow: WindowPtr);
  1148.   {Handles mouse down events in the content region of image windows.}
  1149.         var
  1150.             r: rect;
  1151.             str: str255;
  1152.             hloc, vloc: integer;
  1153.             tool: ToolType;
  1154.             start: Point;
  1155.     begin
  1156.         if (WindowPeek(WhichWindow)^.WindowKind <> PicKind) then
  1157.             exit(DoMouseDownInWindow);
  1158.         SetPort(info^.wptr);
  1159.         if Digitizing then
  1160.             if (CurrentTool <> MagnifyingGlass) and (CurrentTool <> Grabber) then
  1161.                 StopDigitizing;
  1162.         GlobalToLocal(event.where);
  1163.         IsInsertionPoint := false;
  1164.         with info^ do
  1165.             if RoiShowing then
  1166.                 if EqualRect(RoiRect, PicRect) and (SelectionMode = NewSelection) then {if Select All}
  1167.                     if not (OpPending and (CurrentOp = PasteOp)) then begin
  1168.                             KillRoi;
  1169.                             MouseState := NotInRoi;
  1170.                             exit(DoMouseDownInWindow);
  1171.                         end;
  1172.         if MouseState <> NotInRoi then
  1173.             exit(DoMouseDownInWindow);
  1174.         if SpaceBarDown and (CurrentTool <> TextTool) then
  1175.             tool := grabber
  1176.         else
  1177.             tool := CurrentTool;
  1178.         if (SelectionMode = NewSelection) and not ((tool = MagnifyingGlass) or (tool = Grabber)) then
  1179.             KillRoi;
  1180.         SetupUndo;
  1181.         case tool of
  1182.             SelectionTool: 
  1183.                 DoObject(SelectionRect, event);
  1184.             PolygonTool, FreehandTool: 
  1185.                 MakePolygon(event);
  1186.             OvalSelectionTool: 
  1187.                 DoObject(SelectionOval, event);
  1188.             LineTool: 
  1189.                 MakeLineRoi(event);
  1190.             MagnifyingGlass: 
  1191.                 ZoomIn(event);
  1192.             Grabber: 
  1193.                 Scroll(event);
  1194.             Pencil, Brush, Eraser: 
  1195.                 DoBrush(event);
  1196.             SprayCanTool: 
  1197.                 DoSprayCan;
  1198.             Ruler: 
  1199.                 if OptionKeyDown or ControlKeyDown then
  1200.                     PutMessage('Use the line selection tool and Measure to measure path lengths.')
  1201.                 else begin
  1202.                         DoObject(LineObj, event);
  1203.                         WhatToUndo := UndoEdit;
  1204.                     end;
  1205.             PaintBucket: 
  1206.                 DoFill(event);
  1207.             TextTool: 
  1208.                 DoText(event.where);
  1209.             PlotTool: 
  1210.                 DoProfilePlot(event);
  1211.             PickerTool: 
  1212.                 if BitAnd(Event.modifiers, OptionKey) = OptionKey then
  1213.                     GetBackgroundColor(event)
  1214.                 else
  1215.                     GetForegroundColor(event);
  1216.             CrossHairTool: 
  1217.                 DoPoints(event);
  1218.             AngleTool: 
  1219.                 FindAngle(event);
  1220.             Wand:  begin
  1221.                     if Digitizing then
  1222.                         StopDigitizing;
  1223.                     start := event.where;
  1224.                     ScreenToOffscreen(start);
  1225.                     AutoOutline(start);
  1226.                 end;
  1227.             otherwise
  1228.                 beep;
  1229.         end;
  1230.     end;
  1231.  
  1232.  
  1233.     procedure DoPopupMenusInTools;
  1234.         var
  1235.             Item: integer;
  1236.             ticks: LongInt;
  1237.  
  1238.         procedure DrawCurrentTool;
  1239.         begin
  1240.             InvalRect(ToolRect[CurrentTool]);
  1241.             BeginUpdate(ToolWindow);
  1242.             DrawTools;
  1243.             EndUpdate(ToolWindow);
  1244.         end;
  1245.  
  1246.     begin
  1247.         DrawCurrentTool;
  1248.         ticks := TickCount;
  1249.         repeat
  1250.         until (not button) or (TickCount > ticks + 20);
  1251.         if button and (TickCount > (ticks + 20)) then
  1252.             with ToolRect[CurrentTool] do begin
  1253.                     Item := PopUpMenu(LineToolMenuH, left, top, ord(LOIType) + 1);
  1254.                     case Item of
  1255.                         1: 
  1256.                             LOIType := Straight;
  1257.                         2: 
  1258.                             LOIType := Freehand;
  1259.                         3: 
  1260.                             LOIType := Segmented;
  1261.                         otherwise
  1262.                     end;
  1263.                     DrawCurrentTool;
  1264.                 end;
  1265.     end;
  1266.  
  1267.  
  1268.     procedure DoMouseDownInTools (loc: point);
  1269.  {Handles mouse down events in the tool palette.}
  1270.         var
  1271.             r: rect;
  1272.             OddTool, DoubleClick: boolean;
  1273.             ToolNum, i: integer;
  1274.     begin
  1275.         SetPort(ToolWindow);
  1276.         GlobalToLocal(loc);
  1277.         if loc.v <= StartOfLines then begin
  1278.                 PreviousTool := CurrentTool;
  1279.                 OddTool := loc.h < tmiddle;
  1280.                 ToolNum := (loc.v div tmiddle) * 2;
  1281.                 if not OddTool then
  1282.                     ToolNum := ToolNum + 1;
  1283.                 CurrentTool := ToolType(ToolNum);
  1284.                 isSelectionTool := (CurrentTool = SelectionTool) or (CurrentTool = OvalSelectionTool) or (CurrentTool = PolygonTool) or (CurrentTool = FreehandTool) or (CurrentTool = LineTool);
  1285.                 DoubleClick := (TickCount - ToolTime) < GetDblTime;
  1286.                 ToolTime := TickCount;
  1287.                 InvalRect(ToolRect[CurrentTool]);
  1288.                 InvalRect(ToolRect[PreviousTool]);
  1289.                 IsInsertionPoint := false;
  1290.                 if DoubleClick and (CurrentTool = PreviousTool) then
  1291.                     case CurrentTool of
  1292.                         MagnifyingGlass: 
  1293.                             Unzoom;
  1294.                         SelectionTool:  begin
  1295.                                 StopDigitizing;
  1296.                                 SelectAll(true);
  1297.                             end;
  1298.                         SprayCanTool: 
  1299.                             SetSprayCanSize;
  1300.                         Brush: 
  1301.                             SetBrushSize;
  1302.                         LineTool: 
  1303.                             SetScale;
  1304.                         PolygonTool: 
  1305.                             DoMeasurementOptions;
  1306.                         FreehandTool: 
  1307.                             Calibrate;
  1308.                         ruler: 
  1309.                             SetLineWidth;
  1310.                         PlotTool: 
  1311.                             DoProfilePlotOptions;
  1312.                         Eraser: 
  1313.                             if info <> NoInfo then begin
  1314.                                     KillRoi;
  1315.                                     SetupUndo;
  1316.                                     WhatToUndo := UndoClear;
  1317.                                     StopDigitizing;
  1318.                                     SelectAll(false);
  1319.                                     DoOperation(eraseOp);
  1320.                                 end;
  1321.                         LutTool, Wand: 
  1322.                             if DensitySlicing then
  1323.                                 DisableDensitySlice
  1324.                             else begin
  1325.                                     if Info^.Thresholding then
  1326.                                         ResetGrayMap;
  1327.                                     if OptionKeyDown then
  1328.                                         AutoDensitySlice;
  1329.                                     EnableDensitySlice;
  1330.                                 end;
  1331.                         PickerTool: 
  1332.                             if info^.LutMode <> PseudoColor then begin  {Switch to pseudocolor mode}
  1333.                                     DisableDensitySlice;
  1334.                                     UpdateLUT;
  1335.                                     CurrentTool := LutTool;
  1336.                                     isSelectionTool := false;
  1337.                                     InvalRect(ToolRect[CurrentTool]);
  1338.                                 end
  1339.                             else
  1340.                                 ResetGrayMap;
  1341.                         otherwise
  1342.                     end; {case}
  1343.                 if (not isSelectionTool) and (CurrentTool <> MagnifyingGlass) and (CurrentTool <> Grabber) and (CurrentTool <> Wand) then
  1344.                     KillRoi;
  1345.                 if not DoubleClick and (CurrentTool = LineTool) then
  1346.                     KillRoi;
  1347.                 with info^ do
  1348.                     if RoiShowing then
  1349.                         if EqualRect(RoiRect, PicRect) and not isSelectionTool then {if Select All}
  1350.                             KillRoi;
  1351.                 if (CurrentTool = SelectionTool) or (CurrentTool = CrossHairTool) then begin
  1352.                         InfoMessage := '';
  1353.                         if mCount > 0 then
  1354.                             ShowInfo;
  1355.                     end;
  1356.                 RoiMode := MoveMode;
  1357.                 if CurrentTool = LineTool then begin
  1358.                         if Button then
  1359.                             DoPopUpMenusInTools;
  1360.                         if (LoiType = Straight) and (LineWidth <> 1) then begin
  1361.                                 LineWidth := 1;
  1362.                                 UpdateRoiLineWidth;
  1363.                                 ShowLineWidth;
  1364.                             end;
  1365.                     end;
  1366.             end
  1367.         else begin
  1368.                 for i := 1 to nLineTypes do begin
  1369.                         r := lines[i];
  1370.                         with r do begin
  1371.                                 left := left - 13;
  1372.                                 top := top - 2;
  1373.                                 right := right + 2;
  1374.                                 bottom := bottom + 2;
  1375.                             end;
  1376.                         if i = 1 then
  1377.                             with r do
  1378.                                 top := top - 7;
  1379.                         if PtInRect(loc, r) then begin
  1380.                                 with lines[i] do
  1381.                                     LineWidth := bottom - top;
  1382.                                 LineIndex := i;
  1383.                             end;
  1384.                     end;
  1385.                 EraseRect(CheckRect);
  1386.                 InvalRect(CheckRect);
  1387.                 UpdateRoiLineWidth;
  1388.             end;
  1389.     end;
  1390.  
  1391.  
  1392.     procedure ScaleToFitScreen;
  1393.         var
  1394.             trect: rect;
  1395.             ignore: boolean;
  1396.     begin
  1397.         with info^ do begin
  1398.                 MoveWindow(wptr, PicLeftBase, PicTopBase, true);
  1399.                 SetRect(trect, 0, 0, ScreenWidth, ScreenHeight);
  1400.                 ScaleImageWindow(trect);
  1401.                 wrect := trect;
  1402.                 SizeWindow(wptr, trect.right, trect.bottom, true);
  1403.             end;
  1404.     end;
  1405.  
  1406.  
  1407.     procedure DoDrag (WhichWindow: WindowPtr; loc: point);
  1408.         var
  1409.             WinRect, DragBounds, trect: rect;
  1410.             kind: integer;
  1411.     begin
  1412.         kind := WindowPeek(WhichWindow)^.WindowKind;
  1413.         if kind = PicKind then begin
  1414.                 if info^.PictureType = ScionType then
  1415.                     exit(DoDrag);
  1416.                 with info^ do begin  {Save window location}
  1417.                         GetWindowRect(wptr, trect);
  1418.                         savehloc := trect.left;
  1419.                         savevloc := trect.top;
  1420.                     end;
  1421.                 PicLeft := PicLeftBase;
  1422.                 PicTop := PicTopBase;
  1423.             end;
  1424.         DragBounds := ScreenBits.bounds;
  1425.         DragWindow(WhichWindow, loc, DragBounds);
  1426.         if (info^.PictureType = FrameGrabberType) or OptionKeyDown then begin
  1427.                 GetWindowRect(WhichWindow, trect);
  1428.                 MoveWindow(WhichWindow, band(trect.left, $fffc), trect.top, true);
  1429.             end;
  1430.         if WhichWindow = InfoWindow then
  1431.             ShowInfo;
  1432.         if WhichWindow = ResultsWindow then begin
  1433.                 GetWindowRect(WhichWindow, trect);
  1434.                 ResultsTop := trect.top;
  1435.                 ResultsLeft := trect.left;
  1436.             end;
  1437.     end;
  1438.  
  1439.  
  1440.     procedure UpdateMenus;
  1441.     begin
  1442.         OptionKeyWasDown := OptionKeyDown;
  1443.         CurrentKind := CurrentWindow;
  1444.         UpdateFileMenu;
  1445.         UpdateEditMenu;
  1446.         UpdateOptionsMenu;
  1447.         UpdateTextItems;
  1448.         UpdateEnhanceMenu;
  1449.         UpdateAnalysisMenu;
  1450.         UpdateSpecialMenu;
  1451.         UpdateStacksMenu;
  1452.         UpdateWindowsMenu;
  1453.     end;
  1454.  
  1455.  
  1456.     function HMGetBalloons: BOOLEAN;
  1457.     inline
  1458.         $303C, $0003, $A830;
  1459.  
  1460.  
  1461.     function BalloonHelp: boolean;
  1462.     begin
  1463.         if not System7 then begin
  1464.                 BalloonHelp := false;
  1465.                 exit(BalloonHelp);
  1466.             end;
  1467.         BalloonHelp := HMGetBalloons;
  1468.     end;
  1469.  
  1470.  
  1471.     procedure DoMouseDown (event: EventRecord);
  1472.         var
  1473.             WhichWindow: WindowPtr;
  1474.             ThePart, ignore, kind: integer;
  1475.             trect: rect;
  1476.     begin
  1477.         ThePart := FindWindow(event.where, WhichWindow);
  1478.         kind := WindowPeek(WhichWindow)^.WindowKind;
  1479.         case ThePart of
  1480.             InDesk: 
  1481.                 ;
  1482.             InMenuBar:  begin
  1483.                     UpdateMenus;
  1484.                     DoMenuEvent(MenuSelect(event.where));
  1485.                 end;
  1486.             InSysWindow: 
  1487.                 SystemClick(Event, WhichWindow);
  1488.             InContent:  begin
  1489.                     RoiUpdateTime := 0;
  1490.                     if WhichWindow = ToolWindow then begin
  1491.                             if BalloonHelp then
  1492.                                 SelectWindow(ToolWindow);
  1493.                             DoMouseDownInTools(event.where);
  1494.                             exit(DoMouseDown);
  1495.                         end;
  1496.                     if WhichWindow = MapWindow then begin
  1497.                             if BalloonHelp then
  1498.                                 SelectWindow(MapWindow);
  1499.                             DoMouseDownInMap;
  1500.                             exit(DoMouseDown)
  1501.                         end;
  1502.                     if WhichWindow = LUTWindow then begin
  1503.                             if BalloonHelp then
  1504.                                 SelectWindow(LUTWindow);
  1505.                             DoMouseDownInLUT(event);
  1506.                             exit(DoMouseDown)
  1507.                         end;
  1508.                     if WhichWindow = PasteControl then begin
  1509.                             DoMouseDownInPasteControl(event.where);
  1510.                             exit(DoMouseDown)
  1511.                         end;
  1512.                     if WhichWindow = ResultsWindow then begin
  1513.                             DoMouseDownInResults(event.where);
  1514.                             exit(DoMouseDown)
  1515.                         end;
  1516.                     if kind = TextKind then begin
  1517.                             DoMouseDownInText(Event, WhichWindow);
  1518.                             exit(DoMouseDown)
  1519.                         end;
  1520.                     if WhichWindow <> FrontWindow then
  1521.                         SelectWindow(WhichWindow)
  1522.                     else
  1523.                         DoMouseDownInWindow(Event, WhichWindow);
  1524.                 end;
  1525.             InDrag: 
  1526.                 DoDrag(WhichWindow, event.where);
  1527.             InGrow: 
  1528.                 DoGrow(WhichWindow, event);
  1529.             InGoAway: 
  1530.                 if TrackGoAway(WhichWindow, event.where) then
  1531.                     if OptionKeyDown and (kind = PicKind) then
  1532.                         CloseAll
  1533.                     else begin
  1534.                             if WhichWindow <> VideoControl then
  1535.                                 StopDigitizing;
  1536.                             ignore := CloseAWindow(WhichWindow);
  1537.                         end;
  1538.             InZoomIn, InZoomOut: 
  1539.                 with info^ do
  1540.                     case WindowState of
  1541.                         NormalWindow:  begin
  1542.                                 if digitizing then
  1543.                                     exit(DoMouseDown);
  1544.                                 ScaleToFit;
  1545.                                 if ScaleToFitWindow then
  1546.                                     ScaleToFitScreen;
  1547.                             end;
  1548.                         TiledSmall, TiledSmallScaled:  begin
  1549.                                 if WindowState = TiledSmall then begin
  1550.                                         ScaleToFitWindow := true;
  1551.                                         WindowState := TiledBig;
  1552.                                     end
  1553.                                 else
  1554.                                     WindowState := TiledBigScaled;
  1555.                                 savewrect := wrect;
  1556.                                 SaveSrcRect := SrcRect;
  1557.                                 SaveMagnification := magnification;
  1558.                                 GetWindowRect(wptr, trect);
  1559.                                 savehloc := trect.left;
  1560.                                 savevloc := trect.top;
  1561.                                 ScaleToFitScreen;
  1562.                                 UpdatePicWindow;
  1563.                             end;
  1564.                         TiledBig:  begin
  1565.                                 ScaleToFitWindow := false;
  1566.                                 WindowState := TiledSmall;
  1567.                                 wrect := savewrect;
  1568.                                 SrcRect := SaveSrcRect;
  1569.                                 magnification := SaveMagnification;
  1570.                                 HideWindow(wptr);
  1571.                                 SizeWindow(wptr, wrect.right, wrect.bottom, true);
  1572.                                 MoveWindow(wptr, savehloc, savevloc, true);
  1573.                                 ShowWindow(wptr);
  1574.                                 UpdatePicWindow;
  1575.                                 magnification := 1.0;
  1576.                                 UpdateTitleBar;
  1577.                             end;
  1578.                         TiledBigScaled:  begin
  1579.                                 WindowState := TiledSmallScaled;
  1580.                                 wrect := savewrect;
  1581.                                 SrcRect := PicRect;
  1582.                                 HideWindow(wptr);
  1583.                                 SizeWindow(wptr, wrect.right, wrect.bottom, true);
  1584.                                 MoveWindow(wptr, savehloc, savevloc, true);
  1585.                                 ShowWindow(wptr);
  1586.                                 UpdatePicWindow;
  1587.                                 if PicRect.right <> 0 then
  1588.                                     magnification := wrect.right / PicRect.right;
  1589.                                 UpdateTitleBar;
  1590.                             end;
  1591.                     end; {case WindowState}
  1592.         end; {case thePart}
  1593.     end;
  1594.  
  1595.  
  1596.     procedure NudgeRoi (key: integer);
  1597.         var
  1598.             dh, dv: integer;
  1599.     begin
  1600.         with info^ do begin
  1601.                 if not RoiShowing then
  1602.                     exit(NudgeRoi);
  1603.                 case key of
  1604.                     LeftArrow:  begin
  1605.                             dh := -1;
  1606.                             dv := 0
  1607.                         end;
  1608.                     RightArrow:  begin
  1609.                             dh := 1;
  1610.                             dv := 0
  1611.                         end;
  1612.                     UpArrow:  begin
  1613.                             dh := 0;
  1614.                             dv := -1
  1615.                         end;
  1616.                     DownArrow:  begin
  1617.                             dh := 0;
  1618.                             dv := 1
  1619.                         end;
  1620.                 end;
  1621.                 if OptionKeyDown then begin
  1622.                         if RoiType = RectRoi then
  1623.                             with RoiRect do begin
  1624.                                     right := right + dh;
  1625.                                     if right < left + 2 then
  1626.                                         right := left + 2;
  1627.                                     bottom := bottom + dv;
  1628.                                     if bottom < top + 2 then
  1629.                                         bottom := top + 2;
  1630.                                     MakeRegion;
  1631.                                 end
  1632.                         else
  1633.                             beep;
  1634.                     end
  1635.                 else begin
  1636.                         OffsetRgn(roiRgn, dh, dv);
  1637.                         RoiRect := roiRgn^^.rgnBBox;
  1638.                     end;
  1639.                 RoiNudged := true;
  1640.                 RoiUpdateTime := 0;
  1641.             end;
  1642.     end;
  1643.  
  1644.  
  1645.     procedure DoKeyDown (event: EventRecord);
  1646.         var
  1647.             ch: char;
  1648.             ich, KeyCode: integer;
  1649.     begin
  1650.         Ch := chr(band(Event.message, CharCodeMask));
  1651.         ich := ord(ch);
  1652. {ShowMessage(long2str(ich));}
  1653.         KeyCode := bsr(band(Event.message, KeyCodeMask), 8);
  1654.         if BitAnd(Event.modifiers, CmdKey) = CmdKey then begin
  1655.                 UpdateMenus;
  1656.                 if OptionKeyWasDown then begin
  1657.                         case KeyCode of
  1658.                             1: 
  1659.                                 ch := 'S';
  1660.                             3: 
  1661.                                 ch := 'F';
  1662.                             5: 
  1663.                                 ch := 'G';
  1664.                             8: 
  1665.                                 ch := 'C';
  1666.                             9: 
  1667.                                 ch := 'V';
  1668.                             13: 
  1669.                                 ch := 'W';
  1670.                             17: 
  1671.                                 ch := 'T';
  1672.                             24: 
  1673.                                 ch := '=';
  1674.                             35: 
  1675.                                 ch := 'P';
  1676.                             44: 
  1677.                                 ch := '/';
  1678.                         end;
  1679.                     end;
  1680.                 DoMenuEvent(MenuKey(Ch));
  1681.                 exit(DoKeyDown)
  1682.             end;
  1683.         if CurrentWindow = TextKind then begin
  1684.                 DoKeyDownInText(ch);
  1685.                 exit(DoKeyDown)
  1686.             end;
  1687.         with info^ do
  1688.             if (CurrentTool = TextTool) and IsInsertionPoint and (ord(ch) <> FunctionKey) then
  1689.                 DrawCharacter(ch)
  1690.             else if ch = BackSpace then
  1691.                 DoClear
  1692.             else if RoiShowing and (ich >= LeftArrow) and (ich <= DownArrow) then
  1693.                 NudgeRoi(ich)
  1694.             else if (StackInfo <> nil) and (ch in ['<', ',', chr(PageUp), '>', '.', chr(PageDown), chr(HomeKey), chr(EndKey)]) then begin
  1695.                     if ch in ['<', ',', chr(PageUp)] then
  1696.                         ShowNextSlice(PreviousSliceItem)
  1697.                     else if ch in ['>', '.', chr(PageDown)] then
  1698.                         ShowNextSlice(NextSliceItem)
  1699.                     else if (ich = HomeKey) or (ich = EndKey) then
  1700.                         ShowFirstOrLastSlice(ich);
  1701.                 end
  1702.             else if nMacros > 0 then
  1703.                 RunKeyMacro(ch, KeyCode);
  1704.     end;
  1705.  
  1706.  
  1707.     procedure DoActivate (event: EventRecord);
  1708.         var
  1709.             WhichWindow: WindowPtr;
  1710.             Activating, SwitchingWindows, isOK: boolean;
  1711.             I, kind: integer;
  1712.             NewInfo: InfoPtr;
  1713.     begin
  1714.         WhichWindow := WindowPtr(event.message);
  1715.         kind := WindowPeek(WhichWindow)^.WindowKind;
  1716.         Activating := odd(event.modifiers);
  1717.         case kind of
  1718.             PicKind:  begin
  1719.                     if Activating then begin
  1720.                             NewInfo := pointer(WindowPeek(WhichWindow)^.RefCon);
  1721.                             SwitchingWindows := NewInfo <> Info;
  1722.                             if SwitchingWindows then begin
  1723.                                     StopDigitizing;
  1724.                                     SaveRoi;
  1725.                                     DisableDensitySlice;
  1726.                                 end;
  1727.                             Info := NewInfo;
  1728.                             if SwitchingWindows then
  1729.                                 ActivateWindow;
  1730.                             Measuring := false;
  1731.                             with info^ do begin
  1732.                                     LoadLUT(cTable);
  1733.                                     DrawMap;
  1734.                                     if digitizing and HighlightSaturatedPixels then
  1735.                                         HighlightPixels;
  1736.                                     GenerateValues;
  1737.                                     if not DensityCalibrated then
  1738.                                         DrawLabels('', '', '');
  1739.                                 end; {with}
  1740.                         end
  1741.                     else
  1742.                         KillOperation; {Deactivate}
  1743.                 end;
  1744.             ResultsKind: 
  1745.                 UpdateResultsWindow;
  1746.             TextKind: 
  1747.                 ActivateTextWindow(WhichWindow, Activating);
  1748.             otherwise
  1749.         end; {case}
  1750.         if not activating then begin
  1751.                 WhichWindow := FrontWindow;
  1752.                 if WhichWindow <> nil then begin
  1753.                         kind := WindowPeek(WhichWindow)^.WindowKind;
  1754.                         if kind < 0 then
  1755.                             ConvertClipboard; {DA has become active}
  1756.                     end;
  1757.             end;
  1758.     end;
  1759.  
  1760.  
  1761.     procedure DoUpdate (event: EventRecord);
  1762.         var
  1763.             WhichWindow: WindowPtr;
  1764.             SaveInfo: InfoPtr;
  1765.             kind: integer;
  1766.     begin
  1767.         WhichWindow := WindowPtr(event.message);
  1768.         kind := WindowPeek(WhichWindow)^.WindowKind;
  1769.         BeginUpdate(WhichWindow);
  1770.         case kind of
  1771.             Pickind:  begin
  1772.                     SaveInfo := info;
  1773.                     Info := pointer(WindowPeek(WhichWindow)^.RefCon);
  1774.                     if not digitizing then begin
  1775.                             UpdatePicWindow;
  1776.                             DrawMyGrowIcon(info^.wptr);
  1777.                         end;
  1778.                     info := SaveInfo;
  1779.                 end;
  1780.             ToolKind: 
  1781.                 DrawTools;
  1782.             MapKind: 
  1783.                 DrawMap;
  1784.             LutKind: 
  1785.                 DrawLUT;
  1786.             InfoKind:  begin
  1787.                     DrawLabels('', '', '');
  1788.                     if (mCount > 0) or (InfoMessage <> '') then
  1789.                         ShowInfo;
  1790.                 end;
  1791.             HistoKind: 
  1792.                 DrawHistogram;
  1793.             ProfilePlotKind, CalibrationPlotKind: 
  1794.                 UpdatePlotWindow;
  1795.             ResultsKind: 
  1796.                 UpdateResultsWindow;
  1797.             PasteControlKind: 
  1798.                 DrawPasteControl;
  1799.             TextKind: 
  1800.                 UpdateTextWindow(WhichWindow);
  1801.         end;
  1802.         EndUpdate(WhichWindow);
  1803.     end;
  1804.  
  1805.  
  1806.     procedure DoDiskInsert (event: EventRecord);
  1807. { Process disk insertion event, check for damaged or uninitialized disks. }
  1808.         var
  1809.             p: point;
  1810.             intjunk: integer;
  1811.     begin
  1812.         if (HiWord(event.message) <> NoErr) then begin
  1813.                 DiLoad;
  1814.                 SetPt(p, 100, 80);
  1815.                 intjunk := DiBadMount(p, event.message);
  1816.                 DiUnload;
  1817.             end;
  1818.     end;
  1819.  
  1820.  
  1821.     procedure DoDialogEvent (event: EventRecord);
  1822.   {Handles modeless dialog box events}
  1823.         var
  1824.             isItemHit: boolean;
  1825.             theDialog: DialogPtr;
  1826.             ItemHit: integer;
  1827.             ch: char;
  1828.     begin
  1829.         if (Event.what = KeyDown) and (BitAnd(Event.modifiers, CmdKey) = CmdKey) then begin
  1830.                 UpdateMenus;
  1831.                 ch := chr(band(Event.message, CharCodeMask));
  1832.                 DoMenuEvent(MenuKey(ch));
  1833.                 exit(DoDialogEvent);
  1834.             end;
  1835.         isItemHit := DialogSelect(event, theDialog, ItemHit);
  1836.         if isItemHit and (theDialog = VideoControl) then
  1837.             DoVideoControl(ItemHit);
  1838.     end;
  1839.  
  1840.  
  1841.     function HandleEvents: boolean;
  1842.         const
  1843.             mousemovedmessage = $FA;
  1844.             SuspendResumeMessage = 1;
  1845.             ResumeMask = 1;
  1846.         var
  1847.             Event: EventRecord;
  1848.             result: boolean;
  1849.             theDialog: DialogPtr;
  1850.             ItemHit: integer;
  1851.             SleepTicks: LongInt;
  1852.             okay: boolean;
  1853.     begin
  1854.         if Digitizing then
  1855.             SleepTicks := 0
  1856.         else
  1857.             SleepTicks := 2;
  1858.         if WaitNextEvent(EveryEvent, Event, SleepTicks, nil) then begin
  1859.                 if isDialogEvent(event) then
  1860.                     DoDialogEvent(event)
  1861.                 else
  1862.                     case Event.what of
  1863.                         KeyDown, AutoKey: 
  1864.                             DoKeyDown(Event);
  1865.                         MouseDown: 
  1866.                             DoMouseDown(Event);
  1867.                         ActivateEvt: 
  1868.                             DoActivate(Event);
  1869.                         DiskEvt: 
  1870.                             DoDiskInsert(Event);
  1871.                         UpdateEvt: 
  1872.                             DoUpdate(Event);
  1873.                         app4Evt: 
  1874.                             case BSR(event.message, 24) of
  1875.                                 MouseMovedMessage: 
  1876.                                     ;
  1877.                                 SuspendResumeMessage: 
  1878.                                     if BAND(event.message, ResumeMask) <> 0 then begin{Resume event}
  1879.                                             if SwitchLUTOnSuspend and (WhatToUndo = UndoLUT) then begin
  1880.                                                     UndoLUTChange;
  1881.                                                     WhatToUndo := NothingToUndo;
  1882.                                                 end
  1883.                                             else
  1884.                                                 LoadLUT(info^.ctable);
  1885.                                         end
  1886.                                     else begin {Suspend event}
  1887.                                             KillOperation;
  1888.                                             ConvertClipboard;
  1889.                                             if SwitchLUTOnSuspend then begin
  1890.                                                     SetupLUTUndo;
  1891.                                                     okay := LoadCLUTResource(AppleDefaultCLUT);
  1892.                                                 end;
  1893.                                         end;
  1894.                             end;
  1895.                         otherwise {Do nothing}
  1896.                     end; {case}
  1897.                 HandleEvents := true
  1898.             end
  1899.         else
  1900.             HandleEvents := false;
  1901.     end;
  1902.  
  1903.  
  1904.     procedure ShowInsertionPoint;
  1905.         var
  1906.             tRect: rect;
  1907.             Loc: point;
  1908.             height, imag: integer;
  1909.     begin
  1910.         if (not isInsertionPoint) or (info = NoInfo) then
  1911.             exit(ShowInsertionPoint);
  1912.         if CurrentWindow <> PicKind then
  1913.             exit(ShowInsertionPoint);
  1914.         if (TickCount mod (BlinkTime * 2)) < BlinkTime then
  1915.             exit(ShowInsertionPoint);
  1916.         Loc := InsertionPoint;
  1917.         OffscreenToScreen(loc);
  1918.         with info^, tRect do begin
  1919.                 SetPort(wptr);
  1920.                 imag := trunc(magnification + 0.5);
  1921.                 height := CurrentSize * imag;
  1922.                 height := height - height div 4;
  1923.                 left := loc.h;
  1924.                 bottom := loc.v - imag + 1;
  1925.                 top := bottom - height;
  1926.                 right := left + 1;
  1927.                 PenNormal;
  1928.                 PenSize(imag, imag);
  1929.                 PenMode(PatXor);
  1930.                 FrameRect(tRect);
  1931.                 ticks := TickCount + 3;
  1932.                 repeat
  1933.                 until TickCount > ticks;
  1934.                 FrameRect(tRect);
  1935.             end;
  1936.     end;
  1937.  
  1938.  
  1939.     procedure UndoRoi;
  1940.         var
  1941.             SrcPtr, DstPtr: ptr;
  1942.             offset, ByteCount, tTop, tBottom: LongInt;
  1943.             tRect: rect;
  1944.     begin
  1945.         with info^ do begin
  1946.                 if PixMapSize <> CurrentUndoSize then
  1947.                     exit(UndoRoi);
  1948.                 tRect := RoiRect;
  1949.                 if RoiType = LineRoi then
  1950.                     InsetRect(tRect, -RoiHandleSize, -RoiHandleSize);
  1951.                 with tRect do begin
  1952.                         tTop := top;
  1953.                         tBottom := bottom;
  1954.                         if tTop < 0 then
  1955.                             tTop := 0;
  1956.                         if tTop > PicRect.bottom then
  1957.                             tTop := PicRect.bottom;
  1958.                         if tBottom < 0 then
  1959.                             tBottom := 0;
  1960.                         if tBottom > PicRect.bottom then
  1961.                             tBottom := PicRect.bottom;
  1962.                     end;
  1963.                 offset := tTop * BytesPerRow;
  1964.                 if offset < 0 then
  1965.                     offset := 0;
  1966.                 SrcPtr := ptr(ord4(UndoBuf) + offset);
  1967.                 DstPtr := ptr(ord4(PicBaseAddr) + offset);
  1968.                 ByteCount := (tBottom - tTop) * BytesPerRow;
  1969.                 BlockMove(SrcPtr, DstPtr, ByteCount);
  1970.             end;
  1971.     end;
  1972.  
  1973.  
  1974.     procedure GetLineHandles (var LeftHandle, MiddleHandle, RightHandle: rect);
  1975.         var
  1976.             offset1, offset2, xcenter, ycenter, x1, y1, x2, y2: integer;
  1977.             rx1, ry1, rx2, ry2: real;
  1978.     begin
  1979.         offset1 := RoiHandleSize div 2;
  1980.         offset2 := offset1 + 1;
  1981.         GetLoi(rx1, ry1, rx2, ry2);
  1982.         x1 := trunc(rx1);
  1983.         y1 := trunc(ry1);
  1984.         x2 := trunc(rx2);
  1985.         y2 := trunc(ry2);
  1986.         SetRect(LeftHandle, x1 - offset1, y1 - offset1, x1 + offset2, y1 + offset2);
  1987.         with info^.RoiRect do begin
  1988.                 xcenter := left + (right - left) div 2;
  1989.                 ycenter := top + (bottom - top) div 2;
  1990.             end;
  1991.         SetRect(MiddleHandle, xcenter - offset1, ycenter - offset1, xcenter + offset2, ycenter + offset2);
  1992.         SetRect(RightHandle, x2 - offset1, y2 - offset1, x2 + offset2, y2 + offset2);
  1993.     end;
  1994.  
  1995.  
  1996.     procedure DrawROI;
  1997.         var
  1998.             tRect: rect;
  1999.             RoiHandle, LeftHandle, MiddleHandle, RightHandle: rect;
  2000.             psize: integer;
  2001.             StartTicks: LongInt;
  2002.             SaveGDevice: GDHandle;
  2003.     begin
  2004.         with Info^ do begin
  2005.                 StartTicks := TickCount;
  2006.                 if OpPending then
  2007.                     DoOperation(CurrentOp);
  2008.                 SaveGDevice := GetGDevice;
  2009.                 SetGDevice(osGDevice);
  2010.                 SetPort(GrafPtr(Info^.osPort));
  2011.                 PenNormal;
  2012.                 if ScaleToFitWindow then
  2013.                     if (magnification < 1.0) and (magnification <> 0.0) then begin
  2014.                             psize := round(1.0 / magnification + 1.5);
  2015.                             PenSize(psize, psize);
  2016.                         end;
  2017.                 if not ((MouseState = DownInRoi) and OpPending) then
  2018.                     if PixMapSize <= UndoBufSize then begin
  2019.                             pmForeColor(BlackIndex);
  2020.                             pmBackColor(WhiteIndex);
  2021.                             case RoiType of
  2022.                                 RectRoi: 
  2023.                                     with RoiRect do begin
  2024.                                             SetRect(RoiHandle, right - RoiHandleSize, bottom - RoiHandleSize, right, bottom);
  2025.                                             if ((right - left) > RoiHandleSize) and ((bottom - top) > RoiHandleSize) then
  2026.                                                 PaintRect(RoiHandle);
  2027.                                         end;
  2028.                                 LineRoi: 
  2029.                                     if Magnification <= 2.0 then begin
  2030.                                             GetLineHandles(LeftHandle, MiddleHandle, RightHandle);
  2031.                                             PaintRect(LeftHandle);
  2032.                                             if LineWidth < 4 then
  2033.                                                 PaintRect(MiddleHandle);
  2034.                                             PaintRect(RightHandle);
  2035.                                             pmForeColor(WhiteIndex);
  2036.                                             FrameRect(LeftHandle);
  2037.                                             if LineWidth < 4 then
  2038.                                                 FrameRect(MiddleHandle);
  2039.                                             FrameRect(RightHandle);
  2040.                                             pmForeColor(BlackIndex);
  2041.                                         end;
  2042.                                 otherwise
  2043.                             end;
  2044.                             PatIndex := (PatIndex + 1) mod 8;
  2045.                             PenPat(pat[PatIndex]);
  2046.                             FrameRgn(roiRgn);
  2047.                             pmForeColor(ForegroundIndex);
  2048.                             pmBackColor(BackgroundIndex);
  2049.                         end;
  2050.                 if PixMapSize > UndoBufSize then begin
  2051.                         if magnification < 1.0 then
  2052.                             PenSize(2, 2);
  2053.                         PatIndex := (PatIndex + 1) mod 8;
  2054.                         PenPat(pat[PatIndex]);
  2055.                         PenMode(PatXor);
  2056.                         FrameRgn(roiRgn);
  2057.                         if MouseState = DownInRoi then begin
  2058.                                 UnionRect(RoiRect, OldRoiRect, tRect);
  2059.                                 UpdateScreen(tRect);
  2060.                             end
  2061.                         else
  2062.                             UpdateScreen(RoiRect);
  2063.                         FrameRgn(roiRgn);
  2064.                     end
  2065.                 else begin
  2066.                         tRect := RoiRect;
  2067.                         if MouseState = DownInRoi then
  2068.                             UnionRect(RoiRect, OldRoiRect, tRect)
  2069.                         else if RoiNudged then begin
  2070.                                 tRect := RoiRect;
  2071.                                 RoiNudged := false;
  2072.                             end;
  2073.                         if RoiType = LineRoi then
  2074.                             InsetRect(tRect, -RoiHandleSize * 2, -RoiHandleSize * 2)
  2075.                         else
  2076.                             InsetRect(tRect, -2, -2);
  2077.                         UpdateScreen(tRect);
  2078.                         UndoRoi;  {Erase offscreen ROI}
  2079.                     end;
  2080.                 RoiUpdateTime := TickCount - StartTicks;
  2081.             end; {with}
  2082.         SetGDevice(SaveGDevice);
  2083.     end;
  2084.  
  2085.  
  2086.     procedure MoveLineEndPoint (osloc: point);
  2087.         var
  2088.             deltax, deltay: real;
  2089.     begin
  2090.         with info^, osloc, info^.RoiRect do begin
  2091.                 if h < 0 then
  2092.                     h := 0;
  2093.                 if h > PicRect.right then
  2094.                     h := PicRect.right;
  2095.                 if v < 0 then
  2096.                     v := 0;
  2097.                 if v > PicRect.bottom then
  2098.                     v := PicRect.bottom;
  2099.                 if RoiMode = LeftEndMode then begin
  2100.                         LX1 := h;
  2101.                         LY1 := v;
  2102.                         LX2 := left + LX2;
  2103.                         LY2 := top + LY2;
  2104.                     end
  2105.                 else begin
  2106.                         LX2 := h;
  2107.                         LY2 := v;
  2108.                         LX1 := left + LX1;
  2109.                         LY1 := top + LY1;
  2110.                     end;
  2111.                 if ShiftKeyDown then begin
  2112.                         deltax := LX2 - LX1;
  2113.                         deltay := LY2 - LY1;
  2114.                         if abs(deltax) > abs(deltay) then begin
  2115.                                 if RoiMode = LeftEndMode then
  2116.                                     LY2 := LY1
  2117.                                 else
  2118.                                     LY1 := LY2
  2119.                             end
  2120.                         else begin
  2121.                                 if RoiMode = LeftEndMode then
  2122.                                     LX2 := LX1
  2123.                                 else
  2124.                                     LX1 := LX2
  2125.                             end;
  2126.                     end; {if ShiftKeyDown}
  2127.                 MakeRegion;
  2128.                 osMouseDownLoc := osloc;
  2129.                 RoiUpdateTime := 0;
  2130.                 Show3Values(h, v, MyGetPixel(h, v));
  2131.             end;
  2132.     end;
  2133.  
  2134.  
  2135.     procedure MoveRoi (osloc: point);
  2136.         var
  2137.             dh, dv: integer;
  2138.     begin
  2139.         with info^, info^.RoiRect, osloc do begin
  2140.                 dh := h - osMouseDownLoc.h;
  2141.                 dv := v - osMouseDownLoc.v;
  2142.                 OldRoiRect := RoiRect;
  2143.                 if RoiType = LineRoi then
  2144.                     if (RoiMode = LeftEndMode) or (RoiMode = RightEndMode) then begin
  2145.                             MoveLineEndPoint(osloc);
  2146.                             exit(MoveRoi);
  2147.                         end;
  2148.                 if RoiMode = MoveMode then begin
  2149.                         if RoiMovementState = Constrained then begin
  2150.                                 if dv <> 0 then
  2151.                                     RoiMovementState := ConstrainedV
  2152.                                 else if dh <> 0 then
  2153.                                     RoiMovementState := ConstrainedH
  2154.                             end;
  2155.                         if RoiMovementState = ConstrainedH then
  2156.                             dv := 0
  2157.                         else if RoiMovementState = ConstrainedV then
  2158.                             dh := 0;
  2159.                         if not OpPending then begin
  2160.                                 if left + dh < 0 then
  2161.                                     dh := -left;
  2162.                                 if top + dv < 0 then
  2163.                                     dv := -top;
  2164.                             end;
  2165.                     end;
  2166.                 if not OpPending then begin
  2167.                         if right + dh > PicRect.right then
  2168.                             dh := PicRect.right - right;
  2169.                         if bottom + dv > PicRect.bottom then
  2170.                             dv := PicRect.bottom - bottom;
  2171.                     end;
  2172.                 if RoiMode = StretchMode then begin
  2173.                         measuring := false;
  2174.                         DrawLabels('Width:', 'Height:', '');
  2175.                         if h > left then begin
  2176.                                 right := right + dh;
  2177.                                 if right < (left + 1) then
  2178.                                     right := left + 1;
  2179.                                 if (right - h) > 5 then
  2180.                                     right := h + 2;
  2181.                             end
  2182.                         else
  2183.                             right := left + 1;
  2184.                         if v > top then begin
  2185.                                 bottom := bottom + dv;
  2186.                                 if bottom < (top + 1) then
  2187.                                     bottom := top + 1;
  2188.                                 if (bottom - v) > 5 then
  2189.                                     bottom := v + 2;
  2190.                             end
  2191.                         else
  2192.                             bottom := top + 1;
  2193.                         Show3Values(right - left, bottom - top, -1);
  2194.                         MakeRegion;
  2195.                     end
  2196.                 else begin
  2197.                         OffsetRgn(roiRgn, dh, dv);
  2198.                         Show3Values(left, top, MyGetPixel(left, top));
  2199.                     end;
  2200.                 RoiRect := roiRgn^^.rgnBBox;
  2201.                 osMouseDownLoc := osloc;
  2202.                 RoiUpdateTime := 0; {Forces ROI outline to be redrawn}
  2203.             end; {with Info}
  2204.     end;
  2205.  
  2206.  
  2207.     procedure ShowHistogramValues (GrayLevel: LongInt);
  2208.         var
  2209.             hstart, vstart, ivalue: integer;
  2210.     begin
  2211.         hstart := InfoHStart;
  2212.         vstart := InfoVStart;
  2213.         SetPort(InfoWindow);
  2214.         TextSize(9);
  2215.         TextFont(Monaco);
  2216.         TextMode(SrcCopy);
  2217.         MoveTo(xValueLoc, vstart);
  2218.         with info^ do
  2219.             if DensityCalibrated then begin
  2220.                     if InvertingCalibrationFunction then
  2221.                         DrawReal(cvalue[255 - GrayLevel], 8, 2)
  2222.                     else
  2223.                         DrawReal(cvalue[GrayLevel], 8, 2);
  2224.                     DrawString(' (');
  2225.                     DrawLong(GrayLevel);
  2226.                     DrawString(' )');
  2227.                 end
  2228.             else
  2229.                 DrawLong(GrayLevel);
  2230.         DrawString('          ');
  2231.         MoveTo(yValueLoc, vstart + 10);
  2232.         if InvertingCalibrationFunction then
  2233.             DrawLong(histogram[255 - GrayLevel])
  2234.         else
  2235.             DrawLong(histogram[GrayLevel]);
  2236.         DrawString('          ');
  2237.     end;
  2238.  
  2239.  
  2240.     procedure DoPlotCursor (loc: point; kind: integer);
  2241.         var
  2242.             xscale, angle: extended;
  2243.             xvalue, xinc, yinc: integer;
  2244.             pt: point;
  2245.     begin
  2246.         DrawLabels('X:', 'Y:', '');
  2247.         SetCursor(ToolCursor[SelectionTool]);
  2248.         SetPort(PlotWindow);
  2249.         GlobalToLocal(loc);
  2250.         xscale := PlotCount / (PlotWidth - PlotRightMargin - PlotLeftMargin);
  2251.         xvalue := trunc((loc.h - PlotLeftMargin) * xscale);
  2252.         if (xvalue < 0) or (xvalue >= PlotCount) then
  2253.             exit(DoPlotCursor);
  2254.         Show2PlotValues(xvalue, PlotData^[xvalue]);
  2255.         if (kind = CalibrationPlotKind) or (info^.RoiType <> LineRoi) then
  2256.             exit(DoPlotCursor);
  2257.         if button and (info <> NoInfo) then
  2258.             with loc do begin
  2259.                     SetPort(info^.wptr);
  2260.                     PenMode(PatXor);
  2261.                     PenSize(1, 1);
  2262.                     angle := (PlotAngle / 180.0) * pi;
  2263.                     xinc := round(cos(angle) * xvalue);
  2264.                     yinc := round(-sin(angle) * xvalue);
  2265.                     h := PlotStart.h + xinc;
  2266.                     v := PlotStart.v + yinc;
  2267.                     OffscreenToScreen(loc);
  2268.                     MoveTo(h - 7, v);
  2269.                     LineTo(h + 7, v);
  2270.                     MoveTo(h, v - 7);
  2271.                     LineTo(h, v + 7);
  2272.                     wait(2);
  2273.                     MoveTo(h - 7, v);
  2274.                     LineTo(h + 7, v);
  2275.                     MoveTo(h, v - 7);
  2276.                     LineTo(h, v + 7);
  2277.                 end;
  2278.     end;
  2279.  
  2280.  
  2281.     procedure SelectCursor;
  2282.         var
  2283.             loc, osloc, gloc: point;
  2284.             where, kind, i, color, x, y, margin: integer;
  2285.             WhichWindow: WindowPtr;
  2286.             MouseInRoi: boolean;
  2287.             fwptr: WindowPtr;
  2288.             CalValue: extended;
  2289.             RoiStretchHandle, LeftHandle, MiddleHandle, RightHandle: rect;
  2290.             MovingRoi: boolean;
  2291.             pvalue: integer;
  2292.     begin
  2293.         if PasteControl <> nil then begin
  2294.                 fwptr := FrontWindow;
  2295.                 if fwptr <> nil then
  2296.                     if WindowPeek(fwptr)^.WindowKind <> PasteControlKind then
  2297.                         BringToFront(PasteControl);
  2298.             end;
  2299.         SetPort(ScreenPort);
  2300.         GetMouse(gloc);
  2301.         loc := gloc;
  2302.         where := FindWindow(gloc, WhichWindow);
  2303.         if WhichWindow = nil then begin
  2304.                 InitCursor;
  2305.                 exit(SelectCursor)
  2306.             end;
  2307.         kind := WindowPeek(WhichWindow)^.WindowKind;
  2308.         if kind < 0 then
  2309.             exit(SelectCursor); {System Window}
  2310.         if where <> InContent then begin
  2311.                 InitCursor;
  2312.                 exit(SelectCursor)
  2313.             end;
  2314.         case kind of
  2315.             PicKind:  begin
  2316.                     if Info = NoInfo then begin
  2317.                             InitCursor;
  2318.                             exit(SelectCursor)
  2319.                         end;
  2320.                     SetPort(info^.wptr);
  2321.                     GlobalToLocal(loc);
  2322.                     osloc := loc;
  2323.                     ScreenToOffscreen(osloc);
  2324.                     MovingRoi := false;
  2325.                     with info^ do begin
  2326.                             SelectionMode := NewSelection;
  2327.                             if RoiShowing and ((isSelectionTool) or (CurrentTool = Wand)) and (currentTool <> LineTool) then begin
  2328.                                     if OptionKeyDown then
  2329.                                         SelectionMode := SubSelection
  2330.                                     else if ControlKeyDown or (ShiftKeyDown and (CurrentTool <> OvalSelectionTool) and (CurrentTool <> SelectionTool)) then
  2331.                                         SelectionMode := AddSelection;
  2332.                                 end;
  2333.                             if RoiShowing and (SelectionMode = NewSelection) then begin
  2334.                                     MouseInRoi := PtInRgn(osloc, roiRgn);
  2335.                                     if RoiType = LineRoi then begin
  2336.                                             GetLineHandles(LeftHandle, MiddleHandle, RightHandle);
  2337.                                             if magnification <= 2.0 then begin
  2338.                                                     InsetRect(LeftHandle, -2, -2);
  2339.                                                     InsetRect(MiddleHandle, -2, -2);
  2340.                                                     InsetRect(RightHandle, -2, -2);
  2341.                                                 end;
  2342.                                             MouseInRoi := MouseInRoi or PtInRect(osloc, LeftHandle) or MouseInRoi or PtInRect(osloc, MiddleHandle) or MouseInRoi or PtInRect(osloc, RightHandle);
  2343.                                         end;
  2344.                                 end
  2345.                             else
  2346.                                 MouseInRoi := false
  2347.                         end; {with}
  2348.                     if MouseInRoi or (MouseState = DownInRoi) then begin
  2349.                             if MouseState = NotInRoi then
  2350.                                 MouseState := InRoi;
  2351.                             InitCursor;
  2352.                             if button then begin
  2353.                                     if MouseState = InRoi then begin
  2354.                                             if OpPending and (CurrentOp <> PasteOp) then
  2355.                                                 SetupUndo;
  2356.                                             MouseState := DownInRoi;
  2357.                                             osMouseDownLoc := osloc;
  2358.                                             with info^ do
  2359.                                                 case RoiType of
  2360.                                                     RectRoi:  begin
  2361.                                                             if magnification > 1.0 then
  2362.                                                                 margin := 0
  2363.                                                             else
  2364.                                                                 margin := 2;
  2365.                                                             with RoiRect do
  2366.                                                                 SetRect(RoiStretchHandle, right - RoiHandleSize - margin, bottom - RoiHandleSize - margin, right, bottom);
  2367.                                                             if PtInRect(osloc, RoiStretchHandle) then
  2368.                                                                 RoiMode := StretchMode
  2369.                                                             else
  2370.                                                                 RoiMode := MoveMode;
  2371.                                                         end;
  2372.                                                     LineRoi: 
  2373.                                                         if PtInRect(osloc, LeftHandle) then
  2374.                                                             RoiMode := LeftEndMode
  2375.                                                         else if PtInRect(osloc, RightHandle) then
  2376.                                                             RoiMode := RightEndMode
  2377.                                                         else
  2378.                                                             RoiMode := MoveMode;
  2379.                                                     otherwise
  2380.                                                 end; {case}
  2381.                                             if ShiftKeyDown then
  2382.                                                 RoiMovementState := Constrained
  2383.                                             else
  2384.                                                 RoiMovementState := Unconstrained;
  2385.                                         end;
  2386.                                     MoveRoi(osloc);
  2387.                                     MovingRoi := true;
  2388.                                 end
  2389.                             else
  2390.                                 MouseState := InRoi
  2391.                         end
  2392.                     else begin
  2393.                             MouseState := NotInRoi;
  2394.                             if SpaceBarDown and (CurrentTool <> TextTool) then
  2395.                                 SetCursor(ToolCursor[Grabber])
  2396.                             else if (SelectionMode = AddSelection) and (CurrentTool = Wand) then
  2397.                                 SetCursor(WandPlusCursor)
  2398.                             else if (SelectionMode = SubSelection) and (CurrentTool = Wand) then
  2399.                                 SetCursor(WandMinusCursor)
  2400.                             else if SelectionMode = AddSelection then
  2401.                                 SetCursor(CrossPlusCursor)
  2402.                             else if SelectionMode = SubSelection then
  2403.                                 SetCursor(CrossMinusCursor)
  2404.                             else if (CurrentTool = MagnifyingGlass) and OptionKeyDown then
  2405.                                 SetCursor(GlassMinusCursor)
  2406.                             else
  2407.                                 SetCursor(ToolCursor[CurrentTool]);
  2408.                         end;
  2409.                     if not MovingRoi then begin
  2410.                             if CurrentTool = PickerTool then
  2411.                                 DrawLabels('X:', 'Y:', 'RGB:')
  2412.                             else
  2413.                                 DrawLabels('X:', 'Y:', 'Value:');
  2414.                             with osloc do begin
  2415.                                     if Digitizing then
  2416.                                         pvalue := GetFGPixel(h, v)
  2417.                                     else
  2418.                                         pvalue := MyGetPixel(h, v);
  2419.                                     Show3Values(h, v, pvalue);
  2420.                                 end;
  2421.                         end;
  2422.                 end;
  2423.             HistoKind:  begin
  2424.                     DrawLabels('Level:', 'Count:', '');
  2425.                     SetCursor(ToolCursor[SelectionTool]);
  2426.                     SetPort(HistoWindow);
  2427.                     GlobalToLocal(loc);
  2428.                     ShowHistogramValues(loc.h);
  2429.                 end;
  2430.             ProfilePlotKind, CalibrationPlotKind: 
  2431.                 DoPlotCursor(loc, kind);
  2432.             LUTKind:  begin
  2433.                     if info^.DensityCalibrated then
  2434.                         DrawLabels('Index:', 'Value:', '  RGB:')
  2435.                     else
  2436.                         DrawLabels('Index:', '  RGB:', '');
  2437.                     SetPort(LUTWindow);
  2438.                     GlobalToLocal(loc);
  2439.                     if (CurrentTool = LutTool) or (CurrentTool = Wand) then begin
  2440.                             if loc.v < 256 then
  2441.                                 SetCursor(LUTCursor)
  2442.                             else
  2443.                                 InitCursor
  2444.                         end
  2445.                     else
  2446.                         SetCursor(PickerCursor);
  2447.                     if loc.v < 256 then begin
  2448.                             ShowRGBValues(loc.v);
  2449.                         end
  2450.                     else begin
  2451.                             color := 0;
  2452.                             for i := 1 to nExtraColors + 2 do
  2453.                                 if PtInRect(loc, ExtraColorsRect[i]) then
  2454.                                     Color := ExtraColorsEntry[i];
  2455.                             ShowRGBValues(color);
  2456.                         end;
  2457.                 end;
  2458.             MapKind: 
  2459.                 if OptionKeyDown then
  2460.                     SetCursor(ToolCursor[SelectionTool])
  2461.                 else
  2462.                     SetCursor(gmCursor);
  2463.             TextKind:  begin
  2464.                     TextInfo := TextInfoPtr(WindowPeek(WhichWindow)^.RefCon);
  2465.                     if TextInfo <> nil then
  2466.                         with TextInfo^ do begin
  2467.                                 SetPort(TextWindowPtr);
  2468.                                 GlobalToLocal(loc);
  2469.                                 TEIdle(TextTE);
  2470.                                 with TextWindowPtr^.portRect do begin
  2471.                                         if (loc.h < (right - ScrollBarWidth)) and (loc.v < (bottom - ScrollBarWidth)) then
  2472.                                             SetCursor(ToolCursor[TextTool])
  2473.                                         else
  2474.                                             InitCursor;
  2475.                                     end;
  2476.                             end;
  2477.                 end;
  2478.             otherwise
  2479.                 InitCursor;
  2480.         end; {case}
  2481.     end;
  2482.  
  2483.  
  2484.     procedure CloseAll;
  2485.         var
  2486.             i, j, result: integer;
  2487.             WPeek, NextWPeek: WindowPeek;
  2488.             ignore: boolean;
  2489.     begin
  2490.         InitCursor;
  2491.         WPeek := WindowPeek(FrontWindow);
  2492.         StopDigitizing;
  2493.         while wpeek <> nil do begin
  2494.                 NextWPeek := WPeek^.NextWindow;
  2495.                 case wPeek^.WindowKind of
  2496.                     PicKind:  begin
  2497.                             Info := pointer(WPeek^.RefCon);
  2498.                             result := CloseAWindow(info^.wptr);
  2499.                             if not CommandPeriod then
  2500.                                 for j := 1 to 2 do
  2501.                                     ignore := HandleEvents;
  2502.                             if result = cancel then begin
  2503.                                     ActivateWindow;
  2504.                                     finished := false;
  2505.                                     exit(CloseAll)
  2506.                                 end;
  2507.                         end;
  2508.                     TextKind:  begin
  2509.                             result := CloseAWindow(WindowPtr(wPeek));
  2510.                             if result = cancel then begin
  2511.                                     finished := false;
  2512.                                     exit(CloseAll)
  2513.                                 end;
  2514.                         end;
  2515.                     otherwise
  2516.                         ;
  2517.                 end; {case}
  2518.                 wpeek := NextWPeek;
  2519.             end;
  2520.     end;
  2521.  
  2522.  
  2523.     procedure DoStartup;
  2524.   {Process Finder startup information}
  2525.         var
  2526.             message, ndocs, err, i, j: integer;
  2527.             DocInfo: AppFile;
  2528.             DefaultPalette, OpenedOK: boolean;
  2529.             PaletteName, OutlineName: str255;
  2530.             PaletteFile, OutlineFile: boolean;
  2531.             ignore, PrintDocs: boolean;
  2532.  
  2533.         procedure PrintDocument;
  2534.             var
  2535.                 i: integer;
  2536.         begin
  2537.             WhatToPrint := PrintImage;
  2538.             if PrintOptionsSet then
  2539.                 Print(false)
  2540.             else begin
  2541.                     Print(true);
  2542.                     PrintOptionsSet := true
  2543.                 end;
  2544.             DoClose;
  2545.             for i := 1 to 10 do
  2546.                 ignore := HandleEvents;
  2547.         end;
  2548.  
  2549.     begin
  2550.         for j := 1 to 10 do
  2551.             ignore := HandleEvents;
  2552.         PrintOptionsSet := false;
  2553.         PaletteFile := false;
  2554.         OutlineFile := false;
  2555.         CountAppFiles(message, ndocs);
  2556.         PrintDocs := message = appPrint;
  2557.         if ndocs >= 1 then
  2558.             for i := 1 to ndocs do begin
  2559.                     GetAppFiles(i, DocInfo);
  2560.                     with DocInfo do begin
  2561.                             if ftype = 'ICOL' then begin
  2562.                                     PaletteFile := true;
  2563.                                     PaletteName := docinfo.fname;
  2564.                                     ClrAppFiles(i)
  2565.                                 end;
  2566.                             if fType = 'IPIC' then begin
  2567.                                     WhatToOpen := OpenImage;
  2568.                                     OpenedOK := OpenFile(fName, vRefNum);
  2569.                                     for j := 1 to 10 do
  2570.                                         ignore := HandleEvents;
  2571.                                     ClrAppFiles(i);
  2572.                                     if not OpenedOK then
  2573.                                         exit(DoStartup);
  2574.                                     if PrintDocs then
  2575.                                         PrintDocument;
  2576.                                 end;
  2577.                             if fType = 'TIFF' then begin
  2578.                                     WhatToOpen := OpenTIFF;
  2579.                                     OpenedOK := OpenFile(fName, vRefNum);
  2580.                                     for j := 1 to 10 do
  2581.                                         ignore := HandleEvents;
  2582.                                     ClrAppFiles(i);
  2583.                                     if not OpenedOK then
  2584.                                         exit(DoStartup);
  2585.                                     if PrintDocs then
  2586.                                         PrintDocument;
  2587.                                 end;
  2588.                             if fType = 'PICT' then begin
  2589.                                     OpenedOK := OpenPICT(fName, vRefNum, false);
  2590.                                     for j := 1 to 10 do
  2591.                                         ignore := HandleEvents;
  2592.                                     ClrAppFiles(i);
  2593.                                     if not OpenedOK then
  2594.                                         exit(DoStartup);
  2595.                                     if PrintDocs then
  2596.                                         PrintDocument;
  2597.                                 end;
  2598.                             if fType = 'PICS' then begin
  2599.                                     OpenedOK := OpenPICS(fName, vRefNum);
  2600.                                     for j := 1 to 10 do
  2601.                                         ignore := HandleEvents;
  2602.                                     ClrAppFiles(i);
  2603.                                     if not OpenedOK then
  2604.                                         exit(DoStartup);
  2605.                                 end;
  2606.                             if ftype = 'Iout' then begin
  2607.                                     OutlineFile := true;
  2608.                                     OutlineName := docinfo.fname;
  2609.                                     ClrAppFiles(i)
  2610.                                 end;
  2611.                             if fType = 'TEXT' then begin
  2612.                                     OpenedOK := OpenTextFile(fName, vRefNum);
  2613.                                     ClrAppFiles(i);
  2614.                                     if not OpenedOK then
  2615.                                         exit(DoStartup);
  2616.                                 end;
  2617.                         end; {with}
  2618.                 end;
  2619.         if PaletteFile then
  2620.             OpenColorTable(PaletteName, DocInfo.vRefNum);
  2621.         if OutlineFile then
  2622.             OpenOutline(OutlineName, DocInfo.vRefNum);
  2623.     end;
  2624.  
  2625.  
  2626.     procedure LoadDefaultMacros;
  2627.   {Looks for a text file named "Image Macros" in the same folder as}
  2628.   {Image, and, if found,  loads the macros contained in it.}
  2629.         var
  2630.             err: OSErr;
  2631.             LaunchRefNum: integer;
  2632.             FinderInfo: FInfo;
  2633.             id: LongInt;
  2634.     begin
  2635.         err := GetVol(nil, LaunchRefNum);
  2636.         if err = noerr then
  2637.             err := GetFInfo('Image Macros', LaunchRefNum, FinderInfo);
  2638.         if err = NoErr then begin
  2639.                 LoadMacrosFromFile('Image Macros', LaunchRefNum);
  2640.                 UnloadSeg(@LoadMacros);
  2641.             end;
  2642.     end;
  2643.  
  2644.  
  2645.     procedure Shutdown;
  2646.         var
  2647.             AlertID: integer;
  2648.     begin
  2649.         if (UnsavedResults and (mCount > 10)) or (UnsavedResults and (ResultsWindow <> nil)) then begin
  2650.                 InitCursor;
  2651.                 AlertID := alert(500, nil);
  2652.                 if AlertID = CancelResetID then begin
  2653.                         finished := false;
  2654.                         exit(Shutdown)
  2655.                     end;
  2656.             end;
  2657.         CloseAll;
  2658.         if finished then
  2659.             ConvertClipboard;
  2660.     end;
  2661.  
  2662.  
  2663. begin
  2664.     Init;
  2665.   {InitUserMacros;}
  2666.     SetupMenus;
  2667.     GetSettings;
  2668.     AllocateBuffers;
  2669.     AllocateArrays;
  2670.     ConvertSystemClipboard;
  2671.     DoStartup;
  2672.     LoadDefaultMacros;
  2673.     FindPlugIns;
  2674.     UnloadSeg(@Init);
  2675. {InitUser;}
  2676.     repeat
  2677.         if not HandleEvents then
  2678.             if info^.RoiShowing and (RoiUpdateTime < 30) then
  2679.                 DrawRoi;
  2680.         ShowInsertionPoint;
  2681.         SelectCursor;
  2682.         if Digitizing then begin
  2683.                 CaptureAndDisplayFrame;
  2684.                 if ContinuousHistogram then
  2685.                     ShowContinuousHistogram;
  2686.             end;
  2687.         if Finished then
  2688.             Shutdown;
  2689.     until finished;
  2690.     CloseSerialPorts;
  2691.     isOK := LoadCLUTResource(AppleDefaultCLUT);
  2692.     RestoreScreen; {Force Finder to redraw color icons}
  2693. end.