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

  1. re DoSprayCan;
  2.     procedure DoBrush (event: EventRecord);
  3.     procedure DoText (loc: point);
  4.     procedure SetSprayCanSize;
  5.     procedure SetBrushSize;
  6.     procedure SetLineWidth;
  7.     procedure UpdateEditMenu;
  8.     procedure ConvertClipboard;
  9.     procedure ZoomOut;
  10.     procedure ZoomIn (event: EventRecord);
  11.     procedure Scroll (event: EventRecord);
  12.     procedure DoFill (event: EventRecord);
  13.     procedure DoGrow (WhichWindow: WindowPtr; event: EventRecord);
  14.     procedure DrawCharacter (ch: char);
  15.     procedure ConvertSystemClipboard;
  16.     procedure SetupOperation (item: integer);
  17.     procedure PastePicture;
  18.     procedure DoUndo;
  19.     procedure FindWhatToCopy;
  20.     procedure CopyResults;
  21.  
  22.  
  23. implementation
  24.  
  25.  
  26.     procedure PivotSelection (var SelectionRect: rect; WindowRect: rect);
  27.         var
  28.             OldWidth, NewWidth, OldHeight, NewHeight, hCenter, vCenter, NewLeft, NewTop: integer;
  29.     begin
  30.         with SelectionRect do begin
  31.                 OldWidth := right - left;
  32.                 OldHeight := bottom - top;
  33.                 hCenter := left + OldWidth div 2;
  34.                 vCenter := top + OldHeight div 2;
  35.             end;
  36.         NewWidth := OldHeight;
  37.         NewHeight := OldWidth;
  38.         NewLeft := hCenter - NewWidth div 2;
  39.         NewTop := vCenter - NewHeight div 2;
  40.         with WindowRect do begin
  41.                 if (NewLeft + NewWidth) > right then
  42.                     NewLeft := right - NewWidth;
  43.                 if (NewTop + NewHeight) > bottom then
  44.                     NewTop := bottom - NewHeight;
  45.                 if NewLeft < 0 then
  46.                     NewLeft := 0;
  47.                 if NewTop < 0 then
  48.                     NewTop := 0;
  49.             end;
  50.         with SelectionRect do begin
  51.                 left := NewLeft;
  52.                 top := NewTop;
  53.                 right := NewLeft + NewWidth;
  54.                 bottom := NewTop + NewHeight;
  55.             end;
  56.     end;
  57.  
  58.  
  59.     procedure FlipLine (var LineBuf: LineType; width: integer);
  60.         var
  61.             TempLine: LineType;
  62.             i, WidthLessOne: integer;
  63.     begin
  64.         TempLine := LineBuf;
  65.         WidthLessOne := width - 1;
  66.         for i := 0 to width - 1 do
  67.             LineBuf[i] := TempLine[WidthLessOne - i];
  68.     end;
  69.  
  70.  
  71.     procedure ScreenToOffscreenRect (var r: rect);
  72.         var
  73.             p1, p2: point;
  74.     begin
  75.         with r do begin
  76.                 p1.h := left;
  77.                 p1.v := top;
  78.                 p2.h := right;
  79.                 p2.v := bottom;
  80.                 ScreenToOffscreen(p1);
  81.                 ScreenToOffscreen(p2);
  82.                 Pt2Rect(p1, p2, r);
  83.             end;
  84.     end;
  85.  
  86.  
  87.     procedure FlipOrRotate (DoWhat: FlipRotateType);
  88.         var
  89.             SaveInfo: InfoPtr;
  90.             width, height, hDst, vSrc, vDst, hSrc, i, inc: integer;
  91.             LineBuf: LineType;
  92.             srect, drect, MaskRect: rect;
  93.             PixelCount: LongInt;
  94.             AutoSelectAll: boolean;
  95.  
  96.     begin
  97.         if NotRectangular or NotInBounds or NoUndo then
  98.             exit(FlipOrRotate);
  99.         AutoSelectAll := not Info^.RoiShowing;
  100.         if AutoSelectAll then
  101.             SelectAll(true);
  102.         if TooWide then
  103.             exit(FlipOrRotate);
  104.         ShowWatch;
  105.         SetupUndoFromClip;
  106.         SetupUndo;
  107.         if (DoWhat = RotateLeft) or (DoWhat = RotateRight) then
  108.             WhatToUndo := UndoRotate
  109.         else
  110.             WhatToUndo := UndoFlip;
  111.         SetupUndoInfoRec;
  112.         SaveInfo := Info;
  113.         srect := info^.RoiRect;
  114.         PixelCount := 0;
  115.         case DoWhat of
  116.  
  117.             RotateLeft, RotateRight: 
  118.                 with srect do begin
  119.                         if OptionKeyWasDown then
  120.                             DoOperation(EraseOp);
  121.                         drect := srect;
  122.                         with info^ do begin
  123.                                 PivotSelection(drect, PicRect);
  124.                                 MaskRect := drect;
  125.                                 RoiRect := drect;
  126.                                 RectRgn(roiRgn, RoiRect);
  127.                             end;
  128.                         width := right - left;
  129.                         if DoWhat = RotateLeft then begin
  130.                                 hDst := drect.left;
  131.                                 inc := 1
  132.                             end
  133.                         else begin
  134.                                 hDst := drect.right - 1;
  135.                                 inc := -1
  136.                             end;
  137.                         for vSrc := top to bottom - 1 do begin
  138.                                 Info := UndoInfo;
  139.                                 GetLine(left, vSrc, width, LineBuf);
  140.                                 if DoWhat = RotateLeft then
  141.                                     FlipLine(LineBuf, width);
  142.                                 Info := SaveInfo;
  143.                                 PutColumn(hDst, drect.top, width, LineBuf);
  144.                                 hDst := hDst + inc;
  145.                                 PixelCount := PixelCount + width;
  146.                                 if PixelCount > 40000 then begin
  147.                                         UpdateScreen(MaskRect);
  148.                                         PixelCount := 0;
  149.                                     end;
  150.                             end;
  151.                     end;
  152.  
  153.             FlipVertical: 
  154.                 with srect do begin
  155.                         MaskRect := srect;
  156.                         width := right - left;
  157.                         vDst := bottom;
  158.                         for vSrc := top to bottom - 1 do begin
  159.                                 Info := UndoInfo;
  160.                                 GetLine(left, vSrc, width, LineBuf);
  161.                                 Info := SaveInfo;
  162.                                 vDst := vDst - 1;
  163.                                 PutLine(left, vDst, width, LineBuf);
  164.                             end;
  165.                     end;
  166.  
  167.             FlipHorizontal: 
  168.                 with srect do begin
  169.                         MaskRect := srect;
  170.                         width := right - left;
  171.                         for vSrc := top to bottom - 1 do begin
  172.                                 Info := UndoInfo;
  173.                                 GetLine(left, vSrc, width, LineBuf);
  174.                                 FlipLine(LineBuf, width);
  175.                                 Info := SaveInfo;
  176.                                 PutLine(left, vSrc, width, LineBuf);
  177.                                 PixelCount := PixelCount + width;
  178.                                 if PixelCount > 10000 then begin
  179.                                         UpdateScreen(MaskRect);
  180.                                         PixelCount := 0;
  181.                                     end;
  182.                             end;
  183.                     end;
  184.  
  185.         end; {case}
  186.         Info := SaveInfo;
  187.         with info^ do begin
  188.                 UpdatePicWindow;
  189.                 changes := true;
  190.             end;
  191.         SetupRoiRect;
  192.         if AutoSelectAll then
  193.             KillRoi;
  194.     end;
  195.  
  196.  
  197.  
  198.     procedure RotateToNewWindow (DoWhat: FlipRotateType);
  199.         var
  200.             SrcInfo, DstInfo: InfoPtr;
  201.             Srcwidth, DstWidth, DstHeight, hDst, vSrc, vDst, hSrc, i, inc, ignore: integer;
  202.             LineBuf: LineType;
  203.             SourceRect, DstRect: rect;
  204.             PixelCount: LongInt;
  205.             AutoSelectAll, isStack: boolean;
  206.     begin
  207.         if NotRectangular or NotInBounds then
  208.             exit(RotateToNewWindow);
  209.         AutoSelectAll := not Info^.RoiShowing;
  210.         isStack := info^.StackInfo <> nil;
  211.         if AutoSelectAll then
  212.             SelectAll(true);
  213.         if TooWide then
  214.             exit(RotateToNewWindow);
  215.         ShowWatch;
  216.         SrcInfo := info;
  217.         with info^, info^.RoiRect do begin
  218.                 SourceRect := RoiRect;
  219.                 SrcWidth := right - left;
  220.                 DstWidth := bottom - top;
  221.                 DstHeight := right - left;
  222.                 if not NewPicWindow(title, DstWidth, DstHeight) then begin
  223.                         KillRoi;
  224.                         if macro then
  225.                             macro := false;
  226.                         exit(RotateToNewWindow)
  227.                     end;
  228.                 DstInfo := info;
  229.                 DstRect := info^.PicRect;
  230.             end;
  231.         PixelCount := 0;
  232.         if DoWhat = RotateLeft then begin
  233.                 hDst := 0;
  234.                 inc := 1
  235.             end
  236.         else begin
  237.                 hDst := DstWidth - 1;
  238.                 inc := -1
  239.             end;
  240.         with SourceRect do
  241.             for vSrc := top to bottom - 1 do begin
  242.                     Info := SrcInfo;
  243.                     GetLine(left, vSrc, SrcWidth, LineBuf);
  244.                     if DoWhat = RotateLeft then
  245.                         FlipLine(LineBuf, SrcWidth);
  246.                     Info := DstInfo;
  247.                     PutColumn(hDst, 0, SrcWidth, LineBuf);
  248.                     hDst := hDst + inc;
  249.                     PixelCount := PixelCount + SrcWidth;
  250.                     if PixelCount > 20000 then begin
  251.                             UpdatePicWindow;
  252.                             PixelCount := 0;
  253.                         end;
  254.                 end;
  255.         UpdatePicWindow;
  256.         info^.changes := true;
  257.         if AutoSelectAll and not isStack then
  258.             with SrcInfo^ do begin
  259.                     Changes := false;
  260.                     ignore := CloseAWindow(wptr);
  261.                     info := DstInfo;
  262.                 end;
  263.     end;
  264.  
  265.  
  266.     procedure Rotate; {(DoWhat: FlipRotateType)}
  267.         const
  268.             NewWindowID = 3;
  269.         var
  270.             mylog: DialogPtr;
  271.             item: integer;
  272.             NewWindow: boolean;
  273.     begin
  274.         with info^, info^.RoiRect do
  275.             if RoiShowing then
  276.                 NewWindow := ((right - left) > PicRect.bottom) or ((bottom - top) > PicRect.right)
  277.             else begin
  278.                     RotateToNewWindow(DoWhat);
  279.                     exit(Rotate);
  280.                 end;
  281.         InitCursor;
  282.         mylog := GetNewDialog(120, nil, pointer(-1));
  283.         SetDialogItem(mylog, NewWindowID, ord(NewWindow));
  284.         OutlineButton(MyLog, ok, 16);
  285.         repeat
  286.             if item = NewWindowID then begin
  287.                     NewWindow := not NewWindow;
  288.                     SetDialogItem(mylog, NewWindowID, ord(NewWindow));
  289.                 end;
  290.             ModalDialog(nil, item);
  291.         until (item = ok) or (item = cancel);
  292.         DisposDialog(mylog);
  293.         if item = cancel then
  294.             exit(Rotate);
  295.         if NewWindow then
  296.             RotateToNewWindow(DoWhat)
  297.         else
  298.             FlipOrRotate(DoWhat);
  299.     end;
  300.  
  301.  
  302.     procedure CopyImage;
  303.         var
  304.             err: LongInt;
  305.             line: integer;
  306.     begin
  307.         with info^ do begin
  308.                 if NoUndo then begin
  309.                         WhatsOnClip := NothingOnClip;
  310.                         exit(CopyImage)
  311.                     end;
  312.                 SetupUndo;
  313.                 BlockMove(PicBaseAddr, ClipBuf, PixMapSize);
  314.             end;
  315.         with ClipBufInfo^ do begin
  316.                 PixelsPerLine := info^.PixelsPerLine;
  317.                 BytesPerRow := info^.BytesPerRow;
  318.                 nLines := Info^.nLines;
  319.                 RoiRect := info^.RoiRect;
  320.                 roiType := Info^.roiType;
  321.                 PicRect := Info^.PicRect;
  322.                 with osPort^.portPixMap^^ do begin
  323.                         RowBytes := BitOr(BytesPerRow, $8000);
  324.                         bounds := PicRect;
  325.                     end;
  326.                 with osPort^ do begin
  327.                         PortRect := PicRect;
  328.                         RectRgn(visRgn, PicRect);
  329.                     end;
  330.                 if RoiType = RectRoi then begin
  331.                         if info^.PictureType = FrameGrabberType then
  332.                             WhatsOnClip := CameraPic
  333.                         else
  334.                             WhatsOnClip := RectPic
  335.                     end
  336.                 else
  337.                     WhatsOnClip := NonRectPic;
  338.                 CopyRgn(info^.roiRgn, roiRgn);
  339.                 ctable := info^.ctable;
  340.             end;
  341.     end;
  342.  
  343.  
  344.     procedure CopyWindow;
  345.         var
  346.             tPort: GrafPtr;
  347.             WindowSize: LongInt;
  348.             WindowRect: rect;
  349.             WhichWindow: WindowPtr;
  350.             kind, ignore: integer;
  351.             HidingPasteControl: boolean;
  352.     begin
  353.         WhichWindow := FrontWindow;
  354.         if WhichWindow = nil then
  355.             exit(CopyWindow);
  356.         WindowRect := WhichWindow^.PortRect;
  357.         kind := WindowPeek(WhichWindow)^.WindowKind;
  358.         HidingPasteControl := false;
  359.         with WindowRect do
  360.             WindowSize := LongInt(right) * bottom;
  361.         if kind = LUTKind then
  362.             WindowRect.bottom := 256;
  363.         case kind of
  364.             ProfilePlotKind:  begin
  365.                     ConvertPlotToText;
  366.                     ClipTextInBuffer := true;
  367.                 end;
  368.             CalibrationPlotKind:  begin
  369.                     ConvertCalibrationCurveToText;
  370.                     ClipTextInBuffer := true;
  371.                 end;
  372.             HistoKind, LUTKind, MapKind, ToolKind:  begin
  373.                     if PasteControl <> nil then begin
  374.                             ignore := CloseAWindow(PasteControl);
  375.                             HidingPasteControl := true;
  376.                         end;
  377.                     case kind of
  378.                         HistoKind:  begin
  379.                                 ConvertHistoToText;
  380.                                 ClipTextInBuffer := true;
  381.                                 DrawHistogram;
  382.                             end;
  383.                         MapKind: 
  384.                             DrawMap;
  385.                         LUTKind: 
  386.                             DrawLUT;
  387.                         ToolKind: 
  388.                             DrawTools;
  389.                     end; {case}
  390.                 end;
  391.             otherwise
  392.         end; {case}
  393.         if NoUndo then begin
  394.                 WhatsOnClip := NothingOnClip;
  395.                 exit(CopyWindow)
  396.             end;
  397.         ClipboardConverted := false;
  398.         with ClipBufInfo^ do begin
  399.                 RoiType := RectRoi;
  400.                 RoiRect := WindowRect;
  401.                 RectRgn(roiRgn, RoiRect);
  402.                 PicRect := WindowRect;
  403.                 PixelsPerLine := WindowRect.right;
  404.                 BytesPerRow := PixelsPerLine;
  405.                 if odd(BytesPerRow) then
  406.                     BytesPerRow := BytesPerRow + 1;
  407.                 nLines := WindowRect.bottom;
  408.                 with osPort^.portPixMap^^ do begin
  409.                         RowBytes := BitOr(BytesPerRow, $8000);
  410.                         bounds := WindowRect;
  411.                     end;
  412.                 with osPort^ do begin
  413.                         PortRect := PicRect;
  414.                         RectRgn(visRgn, PicRect);
  415.                         SetRectRgn(ClipRgn, 0, 0, 30000, 30000);
  416.                     end;
  417.                 WhatsOnClip := RectPic;
  418.                 GetPort(tPort);
  419.                 SetPort(GrafPtr(osPort));
  420.                 RGBForeColor(BlackRGB);
  421.                 RGBBackColor(WhiteRGB);
  422.                 if (kind = ProfilePlotKind) or (kind = CalibrationPlotKind) then begin
  423.                         EraseRect(osPort^.portRect);
  424.                         DrawPlot
  425.                     end
  426.                 else begin
  427.                         hlock(handle(osPort^.portPixMap));
  428.                         CopyBits(WhichWindow^.PortBits, BitMapHandle(osPort^.portPixMap)^^, WindowRect, WindowRect, SrcCopy, nil);
  429.                         hunlock(handle(osPort^.portPixMap));
  430.                     end;
  431.                 SetPort(tPort);
  432.             end; {with}
  433.         if HidingPasteControl then
  434.             ShowPasteControl;
  435.     end;
  436.  
  437.  
  438.     procedure CopyResults;
  439.         var
  440.             err: OSErr;
  441.     begin
  442.         CopyResultsToBuffer(1, mCount, ShowHeadings);
  443.         UnsavedResults := false;
  444.         err := ZeroScrap;
  445.         if err = NoErr then begin
  446.                 err := PutScrap(TextBufSize, 'TEXT', ptr(TextBufP));
  447.                 WhatsOnClip := NothingOnClip; {The text is on the System Scrap}
  448.             end;
  449.     end;
  450.  
  451.  
  452.     procedure DoCopy;
  453.         var
  454.             err: OSErr;
  455.     begin
  456.         err := ZeroScrap;
  457.         OldScrapCount := GetScrapCount;
  458.         case WhatToCopy of
  459.             CopyColor: 
  460.                 DoCopyColor;
  461.             CopySelection:  begin
  462.                     CopyImage;
  463.                     ClipTextInBuffer := false;
  464.                     ClipboardConverted := false;
  465.                 end;
  466.             CopyHistogram, CopyPlot, CopyCalibrationPlot, CopyCLUT, CopyGrayMap, CopyTools: 
  467.                 CopyWindow;
  468.             CopyMeasurements: 
  469.                 CopyResults;
  470.             CopyText: 
  471.                 DoTextCopy;
  472.             otherwise
  473.                 beep;
  474.         end;
  475.     end;
  476.  
  477.  
  478.     procedure DoCut;
  479.     begin
  480.         DoCopy;
  481.         DoClear;
  482.     end;
  483.  
  484.  
  485.     procedure CenterRect (inRect, outRect: rect; var ResultRect: rect);
  486. {Creates a new rectangle(ResultsRect) that is the same size as inRect, but centered within outRect.}
  487.         var
  488.             width, height, hcenter, vcenter: integer;
  489.     begin
  490.         with inRect do begin
  491.                 width := right - left;
  492.                 height := bottom - top;
  493.             end;
  494.         with outRect do begin
  495.                 hcenter := left + (right - left) div 2;
  496.                 vcenter := top + (bottom - top) div 2;
  497.             end;
  498.         with ResultRect do begin
  499.                 left := hcenter - width div 2;
  500.                 top := vcenter - height div 2;
  501.                 right := left + width;
  502.                 bottom := top + height;
  503.             end;
  504.     en        DisposHandle(phandle);
  505.     end;
  506.  
  507.  
  508.     procedure PasteText;
  509.         var
  510.             nTextLines, LineWidth, MaxLineWidth, MaxRectWidth, MaxRectHeight: integer;
  511.             LineStart, LineEnd, height, kind: integer;
  512.             fwptr: WindowPtr;
  513.             SaveGDevice: GDHandle;
  514.     begin
  515.         fwptr := FrontWindow;
  516.         if fwptr = nil then
  517.             exit(PasteText);
  518.         kind := WindowPeek(fwptr)^.WindowKind;
  519.         if Kind = TextKind then begin
  520.                 DoTextPaste;
  521.                 exit(PasteText);
  522.             end;
  523.         if TextBufSize > 5000 then begin
  524.                 PutMessage('The maximum number of characters that can be pasted is 5000.');
  525.                 exit(PasteText);
  526.             end;
  527.         if (Info = NoInfo) or NoUndo then
  528.             exit(PasteText);
  529.         with ClipBufInfo^ do begin
  530.                 SaveGDevice := GetGDevice;
  531.                 SetGDevice(osGDevice);
  532.                 SetPort(GrafPtr(osPort));
  533.                 RGBForeColor(BlackRGB);
  534.                 RGBBackColor(WhiteRGB);
  535.                 TextFont(CurrentFontID);
  536.                 TextFace(CurrentStyle);
  537.                 TextSize(CurrentSize);
  538.             end;
  539.         with info^ do begin
  540.                 if (not RoiShowing) or (RoiShowing and (RoiType <> RectRoi)) then begin
  541.                         KillRoi;
  542.                         nTextLines := 1;
  543.                         MaxLineWidth := 10;
  544.                         LineStart := 1;
  545.                         LineEnd := 0;
  546.                         repeat
  547.                             LineEnd := LineEnd + 1;
  548.                             if TextBufP^[LineEnd] = CR then begin
  549.                                     nTextLines := nTextLines + 1;
  550.                                     LineWidth := TextWidth(ptr(TextBufP), LineStart - 1, LineEnd - LineStart);
  551.                                     if LineWidth > MaxLineWidth then
  552.                                         MaxLineWidth := LineWidth;
  553.                                     LineStart := LineEnd;
  554.                                 end;
  555.                         until LineEnd >= TextBufSize;
  556.                         if LineEnd > LineStart then begin
  557.                                 LineWidth := TextWidth(ptr(TextBufP), LineStart - 1, LineEnd - LineStart);
  558.                                 if LineWidth > MaxLineWidth then
  559.                                     MaxLineWidth := LineWidth;
  560.                             end;
  561.                         height := nTextLines * CurrentSize + CurrentSize div 4;
  562.                         MaxRectHeight := (PicRect.bottom * 2) div 3;
  563.                         if height > MaxRectHeight then
  564.                             height := MaxRectHeight;
  565.                         MaxLineWidth := MaxLineWidth + CurrentSize div 2;
  566.                         MaxRectWidth := (PicRect.right * 2) div 3;
  567.                         if MaxLineWidth > MaxRectWidth then begin
  568.                                 MaxLineWidth := MaxRectWidth;
  569.                                 height := MaxRectHeight;
  570.                             end;
  571.                         with RoiRect do begin
  572.                                 left := 0;
  573.                                 top := 0;
  574.                                 right := MaxLineWidth;
  575.                                 bottom := height;
  576.                             end;
  577.                         RoiType := RectRoi;
  578.                         MakeRegion;
  579.                     end;
  580.                 CopyImage;
  581.                 WhatsOnClip := TextOnClip;
  582.             end;
  583.         SetRectRgn(ClipBufInfo^.osPort^.ClipRgn, 0, 0, 30000, 30000);  {Why is this needed?}
  584.         TextBox(ptr(TextBufP), TextBufSize, ClipBufInfo^.RoiRect, TextJust);
  585.         SetGDevice(SaveGDevice);
  586.         PastePicture;
  587.     end;
  588.  
  589.  
  590.     procedure DoPaste;
  591.         var
  592.             NewScrapCount: integer;
  593.     begin
  594.         if ((info = NoInfo) and (WhatsOnClip in [RectPic, NonRectPic, ImportedPic, CameraPic])) then begin
  595.                 if CurrentWindow <> TextKind then begin
  596.                         PutMessage('You must have an image window open to paste.');
  597.                         exit(DoPaste);
  598.                     end
  599.                 else
  600.                     WhatsOnClip := NothingOnClip;
  601.             end;
  602.         RoiUpdateTime := 0;
  603.         NewScrapCount := GetScrapCount;
  604.         if NewScrapCount <> OldScrapCount then begin
  605.                 WhatsOnClip := NothingOnClip;
  606.                 OldScrapCount := NewScrapCount;
  607.             end;
  608.         case WhatsOnClip of
  609.             aColor: 
  610.                 PasteColor;
  611.             RectPic, NonRectPic, ImportedPic, CameraPic: 
  612.                 PastePicture;
  613.             TextOnClip: 
  614.                 PasteText;
  615.             LivePic: 
  616.                 WhatsOnClip := NothingOnClip;
  617.             NothingOnClip:  begin
  618.                     ConvertSystemClipboard;
  619.                     if (WhatsOnClip = ImportedPic) and (info <> NoInfo) then
  620.                         PastePicture
  621.                     else if WhatsOnClip = textOnClip then
  622.                         PasteText
  623.                     else
  624.                         beep;
  625.                 end;
  626.         end;
  627.     end;
  628.  
  629.  
  630.     procedure DoClear;
  631.         var
  632.             fwptr: WindowPtr;
  633.             kind: integer;
  634.     begin
  635.         fwptr := FrontWindow;
  636.         if fwptr = nil then
  637.             exit(DoClear);
  638.         kind := WindowPeek(fwptr)^.WindowKind;
  639.         if Kind = TextKind then begin
  640.                 DoTextClear;
  641.                 exit(DoClear);
  642.             end;
  643.         if not NoSelection then begin
  644.                 SetupUndo;
  645.                 WhatToUndo := UndoClear;
  646.                 CurrentOp := EraseOp;
  647.                 OpPending := true;
  648.                 RoiUpdateTime := 0;
  649.             end;
  650.     end;
  651.  
  652.  
  653.     procedure ShowClipboard;
  654.         var
  655.             width, height, hstart, vstart, i, NewScrapCount: integer;
  656.     begin
  657.         NewScrapCount := GetScrapCount;
  658.         if NewScrapCount <> OldScrapCount then begin
  659.                 WhatsOnClip := NothingOnClip;
  660.                 OldScrapCount := NewScrapCount;
  661.             end;
  662.         if WhatsOnClip = NothingOnClip then
  663.             ConvertSystemClipboard;
  664.         if (WhatsOnClip = RectPic) or (WhatsOnClip = NonRectPic) or (WhatsOnClip = ImportedPic) or (WhatsOnClip = CameraPic) then
  665.             with ClipBufinfo^.RoiRect do begin
  666.                     width := right - left;
  667.                     height := bottom - top;
  668.                     if NewPicWindow('Clipboard', width, height) then begin
  669.                             PastePicture;
  670.                             KillRoi;
  671.                             SetupUndo;
  672.                             info^.changes := false;
  673.                         end;
  674.                 end;
  675.     end;
  676.  
  677.  
  678.     function ScreenToPixmapH (hloc: integer): real;
  679.     begin
  680.         with info^ do
  681.             ScreenToPixmapH := SrcRect.left + hloc / magnification;
  682.     end;
  683.  
  684.     function ScreenToPixmapV (vloc: integer): real;
  685.     begin
  686.         with info^ do
  687.             ScreenToPixmapV := SrcRect.top + vloc / magnification;
  688.     end;
  689.  
  690.  
  691.     procedure DoSelection (obj: ObjectType; start, finish: point);
  692.         var
  693.             tRect: rect;
  694.             temp, StartH, StartV, FinishH, FinishV: integer;
  695.             TempRgn: RgnHandle;
  696.     begin
  697.         WhatToUndo := NothingToUndo;
  698.         Info^.RoiShowing := false;
  699.         RoiUpdateTime := 0;
  700.         if (start.h = finish.h) or (start.v = finish.v) then
  701.             exit(DoSelection);
  702.         if start.h > finish.h then begin
  703.                 temp := start.h;
  704.                 start.h := finish.h;
  705.                 finish.h := temp;
  706.             end;
  707.         if start.v > finish.v then begin
  708.                 temp := start.v;
  709.                 start.v := finish.v;
  710.                 finish.v := temp;
  711.             end;
  712.         StartH := round(ScreenToPixmapH(start.h));
  713.         StartV := round(ScreenToPixmapV(start.v));
  714.         FinishH := round(ScreenToPixmapH(finish.h));
  715.         FinishV := round(ScreenToPixmapV(finish.v));
  716.         SetRect(tRect, StartH, StartV, FinishH, FinishV);
  717.         with info^ do begin
  718.                 RoiShowing := true;
  719.                 if SelectionMode <> NewSelection then
  720.                     TempRgn := NewRgn;
  721.                 OpenRgn;
  722.                 case obj of
  723.                     SelectionOval:  begin
  724.                             FrameOval(tRect);
  725.                             roiType := OvalRoi;
  726.                         end;
  727.                     SelectionRect:  begin
  728.                             FrameRect(tRect);
  729.                             roiType := RectRoi;
  730.                         end;
  731.                 end;
  732.                 if SelectionMode = NewSelection then
  733.                     CloseRgn(roiRgn)
  734.                 else begin
  735.                         CloseRgn(TempRgn);
  736.                         if RgnNotTooBig(roiRgn, TempRgn) then begin
  737.                                 if SelectionMode = AddSelection then
  738.                                     UnionRgn(roiRgn, TempRgn, roiRgn)
  739.                                 else begin
  740.                                         DiffRgn(roiRgn, TempRgn, roiRgn);
  741.                                         UpdatePicWindow;
  742.                                     end;
  743.                             end;
  744.                         DisposeRgn(TempRgn);
  745.                         if GetHandleSize(handle(roiRgn)) = 10 then
  746.                             roiType := RectRoi
  747.                         else
  748.                             roiType := FreehandRoi;
  749.                         nCoordinates := 0;
  750.                     end;
  751.                 RoiRect := roiRgn^^.rgnBBox;
  752.             end;{with}
  753.         measuring := false;
  754.     end;
  755.  
  756.  
  757.     procedure DoObject; {(obj: ObjectType; event: EventRecord)}
  758.         var
  759.             Start, Finish, ScreenStart, ScreenFinish, osStart, osFinish: point;
  760.             r: rect;
  761.             DeltaX, DeltaY, switch: integer;
  762.             Constrain: boolean;
  763.             StartH, StartV: real;
  764.     begin
  765.         SetPort(info^.wptr);
  766.         if obj = LineObj then
  767.             DrawLabels('DX:', 'DY:', 'Length:')
  768.         else
  769.             DrawLabels('Width:', 'Height:', '');
  770.         start := event.where;
  771.         StartH := ScreenToPixmapH(start.h);
  772.         StartV := ScreenToPixmapV(start.v);
  773.         osStart := start;
  774.         ScreenToOffscreen(osStart);
  775.         finish := start;
  776.         osFinish := finish;
  777.         ScreenToOffscreen(osFinish);
  778.         PenNormal;
  779.         PenMode(PatXor);
  780.         PenSize(1, 1);
  781.         while button do begin
  782.                 GetMouse(finish);
  783.                 with finish, Info^ do begin
  784.                         if h > wrect.right then
  785.                             h := wrect.right;
  786.                         if v > wrect.bottom then
  787.                             v := wrect.bottom;
  788.                         if h < 0 then
  789.                             h := 0;
  790.                         if v < 0 then
  791.                             v := 0;
  792.                     end;
  793.                 if ShiftKeyDown then begin
  794.                         DeltaX := finish.h - start.h;
  795.                         DeltaY := finish.v - start.v;
  796.                         if obj = lineObj then begin
  797.                                 if abs(DeltaX) > abs(DeltaY) then
  798.                                     finish.v := start.v
  799.                                 else
  800.                                     finish.h := start.h
  801.                             end
  802.                         else begin
  803.                                 if ((DeltaX > 0) and (DeltaY < 0)) or ((DeltaX < 0) and (DeltaY > 0)) then
  804.                                     switch := -1
  805.                                 else
  806.                                     switch := 1;
  807.                                 if abs(DeltaX) > abs(DeltaY) then
  808.                                     finish.h := start.h + switch * DeltaY
  809.                                 else
  810.                                     finish.v := start.v + switch * DeltaX;
  811.                             end;
  812.                     end;
  813.                 osFinish := finish;
  814.                 ScreenToOffscreen(osfinish);
  815.                 case obj of
  816.                     LineObj:  begin
  817.                             MoveTo(start.h, start.v);
  818.                             LineTo(finish.h, finish.v);
  819.                             ShowDxDy(abs(ScreenToPixMapH(finish.h) - StartH), abs(ScreenToPixMapV(finish.v) - StartV));
  820.                             MoveTo(start.h, start.v);
  821.                             LineTo(finish.h, finish.v);
  822.                         end;
  823.                     Rectangle, SelectionRect:  begin
  824.                             if obj = SelectionRect then begin
  825.                                     PatIndex := (PatIndex + 1) mod 8;
  826.                                     PenPat(pat[PatIndex]);
  827.                                 end;
  828.                             Pt2Rect(start, finish, r);
  829.                             FrameRect(r);
  830.                             Show3Values(osfinish.h - osstart.h, osfinish.v - osstart.v, -1);
  831.                             Pt2Rect(start, finish, r);
  832.                             FrameRect(r);
  833.                         end;
  834.                     SelectionOval:  begin
  835.                             PatIndex := (PatIndex + 1) mod 8;
  836.                             PenPat(pat[PatIndex]);
  837.                             Pt2Rect(start, finish, r);
  838.                             FrameOval(r);
  839.                             Show3Values(osfinish.h - osstart.h, osfinish.v - osstart.v, -1);
  840.                             Pt2Rect(start, finish, r);
  841.                             FrameOval(r);
  842.                         end;
  843.                 end; {case}
  844.             end;  {while button}
  845.         if (obj = SelectionRect) or (obj = SelectionOval) then begin
  846.                 DoSelection(obj, start, finish);
  847.                 exit(DoObject);
  848.             end;
  849.         if (obj = LineObj) and ((CurrentTool = LineTool) or (CurrentTool = PlotTool)) then begin
  850.                 MoveTo(start.h, start.v);
  851.                 LineTo(finish.h, finish.v);
  852.                 with info^ do begin
  853.                         LX1 := StartH;
  854.                         LY1 := StartV;
  855.                         LX2 := ScreenToPixmapH(finish.h);
  856.                         LY2 := ScreenToPixmapV(finish.v);
  857.                         if LX1 > (PicRect.right - 1) then
  858.                             LX1 := PicRect.right - 1;
  859.                         if LY1 > (PicRect.bottom - 1) then
  860.                             LY1 := PicRect.bottom - 1;
  861.                         if LX1 < 0 then
  862.                             LX1 := 0;
  863.                         if LY1 < 0 then
  864.                             LY1 := 0;
  865.                         if LX2 > (PicRect.right - 1) then
  866.                             LX2 := PicRect.right - 1;
  867.                         if LY2 > (PicRect.bottom - 1) then
  868.                             LY2 := PicRect.bottom - 1;
  869.                         if LX2 < 0 then
  870.                             LX2 := 0;
  871.                         if LY2 < 0 then
  872.                             LY2 := 0;
  873.                     end;
  874.                 exit(DoObject);
  875.             end;
  876.         DrawObject(obj, start, finish);
  877.     end;
  878.  
  879.  
  880.     procedure DrawSprayCan (xcenter, ycenter: integer);
  881.         var
  882.             i, xoffset, yoffset, nDots: integer;
  883.     begin
  884.         nDots := SprayCanDiameter div 4;
  885.         if nDots < 15 then
  886.             nDots := 15;
  887.         for i := 1 to nDots do begin
  888.                 repeat
  889.                     xoffset := random mod SprayCanRadius;
  890.                     yoffset := random mod SprayCanRadius;
  891.                 until xoffset * xoffset + yoffset * yoffset <= SprayCanRadius2;
  892.                 PutPixel(xcenter + xoffset, ycenter + yoffset, ForegroundIndex);
  893.             end;
  894.     end;
  895.  
  896.  
  897.     procedure DoSprayCan;
  898.   {Reference: "Spaying and Smudging", Dick Pountain, Byte, November 1987}
  899.         var
  900.             xcenter, ycenter, off: integer;
  901.             MaskRect: rect;
  902.             pt: point;
  903.     begin
  904.         info^.changes := true;
  905.         off := SprayCanRadius;
  906.         repeat
  907.             GetMouse(pt);
  908.             ScreenToOffscreen(pt);
  909.             with MaskRect, pt do begin
  910.                     left := h - off;
  911.                     top := v - off;
  912.                     right := h + off;
  913.                     bottom := v + off;
  914.                 end;
  915.             with pt do begin
  916.                     xcenter := h;
  917.                     ycenter := v
  918.                 end;
  919.             DrawSprayCan(xcenter, ycenter);
  920.             UpdateScreen(MaskRect);
  921.         until not button;
  922.         WhatToUndo := UndoEdit;
  923.     end;
  924.  
  925.  
  926.     procedure DoBrush; {(event: EventRecord)}
  927.         var
  928.             r, ScreenRect: rect;
  929.             p1, p2, p2x, start: point;
  930.             WhichWindow: WindowPtr;
  931.             SaveLineWidth, SaveForegroundColor: integer;
  932.             Constrained, MoreHorizontal, FirstTime: boolean;
  933.             offset, width: integer;
  934.     begin
  935.         SaveLineWidth := LineWidth;
  936.         p1 := event.where;
  937.         start := p1;
  938.         if OptionKeyDown then begin
  939.                 case CurrentTool of
  940.                     Brush, Pencil: 
  941.                         GetForegroundColor(event);
  942.                     Eraser: 
  943.                         GetBackgroundColor(event);
  944.                 end;
  945.                 if (CurrentTool = Brush) or (CurrentTool = Eraser) then
  946.                     exit(DoBrush);
  947.             end;
  948.         case CurrentTool of
  949.             Pencil: 
  950.                 LineWidth := 1;
  951.             Brush, Eraser:  begin
  952.                     if CurrentTool = Brush then
  953.                         width := BrushWidth
  954.                     else
  955.                         width := 16;
  956.                     LineWidth := round(width / info^.magnification);
  957.                     if LineWidth < 1 then
  958.                         LineWidth := 1;
  959.                 end;
  960.         end;
  961.         with info^ do
  962.             offset := round((LineWidth - 1) * info^.magnification / 2.0);
  963.         if CurrentTool <> Pencil then
  964.             with p1 do begin
  965.                     h := h - offset;
  966.                     v := v - offset
  967.                 end;
  968.         Constrained := ShiftKeyDown;
  969.         FirstTime := true;
  970.         if CurrentTool = eraser then begin
  971.                 SaveForegroundColor := ForegroundIndex;
  972.                 SetForegroundColor(BackgroundIndex)
  973.             end;
  974.         repeat
  975.             GetMouse(p2);
  976.             if CurrentTool <> Pencil then
  977.                 with p2 do begin
  978.                         h := h - offset;
  979.                         v := v - offset
  980.                     end;
  981.             if FirstTime then
  982.                 if not EqualPt(p1, p2) then begin
  983.                         MoreHorizontal := abs(p2.h - p1.h) >= abs(p2.v - p1.v);
  984.                         FirstTime := false;
  985.                     end;
  986.             if Constrained then
  987.                 if MoreHorizontal then
  988.                     p2.v := p1.v
  989.                 else
  990.                     p2.h := p1.h;
  991.             if CurrentTool = brush then
  992.                 DrawObject(BrushObj, p1, p2)
  993.             else
  994.                 DrawObject(LineObj, p1, p2);
  995.             p1 := p2;
  996.         until not button;
  997.         if CurrentTool = Eraser then
  998.             SetForegroundColor(SaveForegroundColor);
  999.         LineWidth := SaveLineWidth;
  1000.         WhatToUndo := UndoEdit;
  1001.     end;
  1002.  
  1003.  
  1004.     procedure DrawCharacter; {(ch: char)}
  1005.         var
  1006.             str: str255;
  1007.     begin
  1008.         if Info = NoInfo then begin
  1009.                 beep;
  1010.                 exit(DrawCharacter)
  1011.             end;
  1012.         if ch = cr then
  1013.             with InsertionPoint do begin
  1014.                     h := TextStart.h;
  1015.                     v := v + CurrentSize;
  1016.                     SetupUndo;
  1017.                     TextStr := '';
  1018.                     TextStart := InsertionPoint;
  1019.                     exit(DrawCharacter)
  1020.                 end;
  1021.         if ch = BackSpace then
  1022.             with InsertionPoint do begin
  1023.                     if length(TextStr) > 0 then begin
  1024.                             delete(TextStr, length(TextStr), 1);
  1025.                             DisplayText(true);
  1026.                         end;
  1027.                     exit(DrawCharacter)
  1028.                 end;
  1029.         str := ' '; {Needed for MPW}
  1030.         str[1] := ch;
  1031.         TextStr := Concat(TextStr, str);
  1032.         DisplayText(true);
  1033.     end;
  1034.  
  1035.  
  1036.     procedure DoText; {(loc: point)}
  1037.   {Handles text tool mouse clicks.}
  1038.         var
  1039.             value: extended;
  1040.             str: str255;
  1041.             isValue: boolean;
  1042.     begin
  1043.         ScreenToOffscreen(loc);
  1044.         with loc do begin
  1045.                 InsertionPoint.h := h;
  1046.                 InsertionPoint.v := v + 4;
  1047.             end;
  1048.         IsInsertionPoint := true;
  1049.         TextStart := InsertionPoint;
  1050.         TextStr := '';
  1051.         if OptionKeyDown then
  1052.             with info^ do begin
  1053.                     isValue := true;
  1054.                     if (PreviousTool = LineTool) and (nLengths > 0) then
  1055.                         value := plength^[mCount2]
  1056.                     else if (PreviousTool = AngleTool) and (nAngles > 0) then
  1057.                         value := orientation^[mCount2]
  1058.                     else if mCount > 0 then
  1059.                         if AreaM in Measurements then
  1060.                             value := mArea^[mCount2]
  1061.                         else if MeanM in Measurements then
  1062.                             value := mean^[mCount2]
  1063.                         else
  1064.                             isValue := false;
  1065.                     if isValue then begin
  1066.                             RealToString(value, 1, precision, str);
  1067.                             if mCount2 > 0 then
  1068.                                 mCount2 := mCount2 - 1;
  1069.                             DrawTextString(str, TextStart, TextJust);
  1070.                         end;
  1071.                 end;
  1072.         WhatToUndo := UndoEdit;
  1073.     end;
  1074.  
  1075.  
  1076.     procedure DoFill (event: EventRecord);
  1077.         var
  1078.             loc: point;
  1079.             MaskBits: BitMap;
  1080.             BitMapSize: LongInt;
  1081.             tPort: GrafPtr;
  1082.             trect: rect;
  1083.             SaveGDevice: GDHandle;
  1084.     begin
  1085.         ShowWatch;
  1086.         loc := event.where;
  1087.         ScreenToOffscreen(loc);
  1088.         with info^ do begin
  1089.                 tRect := PicRect;
  1090.                 with tRect do
  1091.                     if (right mod 16 <> 0) and not Has32BitQuickDraw then
  1092.                         right := (right div 16) * 16 + 16;  {Workaround for SeedCFill bug that results in  garbage along right edge.}
  1093.                 with MaskBits do begin
  1094.                         RowBytes := PixelsPerLine div 8 + 1;
  1095.                         if odd(RowBytes) then
  1096.                             RowBytes := RowBytes + 1;
  1097.                         bounds := tRect;
  1098.                         BitMapSize := LongInt(rowBytes) * nLines;
  1099.                         baseAddr := NewPtr(BitMapSize);
  1100.                         if baseAddr = nil then begin
  1101.                                 beep;
  1102.                                 exit(DoFill)
  1103.                             end;
  1104.                     end;
  1105.                 SaveGDevice := GetGDevice;
  1106.                 SetGDevice(osGDevice);
  1107.                 GetPort(tPort);
  1108.                 SetPort(GrafPtr(osPort));
  1109.                 pmForeColor(ForegroundIndex);
  1110.                 SeedCFill(BitMapHandle(osPort^.PortPixMap)^^, MaskBits, tRect, tRect, loc.h, loc.v, nil, 0);
  1111.                 CopyBits(MaskBits, BitMapHandle(osPort^.PortPixMap)^^, tRect, tRect, SrcOr, nil);
  1112.                 DisposPtr(MaskBits.baseAddr);
  1113.                 changes := true;
  1114.             end; {with}
  1115.         SetPort(tPort);
  1116.         SetGDevice(SaveGDevice);
  1117.         UpdatePicWindow;
  1118.         WhatToUndo := UndoEdit;
  1119.     end;
  1120.  
  1121.  
  1122.     procedure SetSprayCanSize;
  1123.         var
  1124.             TempSize: integer;
  1125.             Canceled: boolean;
  1126.     begin
  1127.         TempSize := GetInt('Spray can diameter in pixels(2-250):', SprayCanDiameter, Canceled);
  1128.         if Canceled then
  1129.             exit(SetSprayCanSize);
  1130.         if (TempSize > 1) and (TempSize <= 250) then begin
  1131.                 SprayCanDiameter := TempSize;
  1132.                 SprayCanRadius := SprayCanDiameter div 2;
  1133.                 SprayCanRadius2 := SprayCanRadius * SprayCanRadius
  1134.             end
  1135.         else
  1136.             beep;
  1137.     end;
  1138.  
  1139.  
  1140.     procedure SetBrushSize;
  1141.         var
  1142.             TempSize: integer;
  1143.             Canceled: boolean;
  1144.             i, ticks: LongInt;
  1145.     begin
  1146.         TempSize := GetInt('Brush Size in pixels(1..99):', BrushWidth, Canceled);
  1147.         if Canceled then
  1148.             exit(SetBrushSize);
  1149.         if (TempSize > 0) and (TempSize < 100) then begin
  1150.                 BrushWidth := TempSize;
  1151.                 BrushHeight := BrushWidth
  1152.             end
  1153.         else
  1154.             beep;
  1155.         exit(SetBrushSize);
  1156.         ticks := TickCount;
  1157.         for i := 1 to 10000 do
  1158.             PutPixel(100, 100, 50);
  1159.         ShowMessage(concat('ticks=', long2str(TickCount - ticks)));
  1160.     end;
  1161.  
  1162.  
  1163.     procedure SetLineWidth;
  1164.         var
  1165.             TempSize: integer;
  1166.             Canceled: boolean;
  1167.     begin
  1168.         TempSize := GetInt('Line Width in pixels(1..100):', LineWidth, Canceled);
  1169.         if Canceled then
  1170.             exit(SetLineWidth);
  1171.         if (TempSize > 0) and (TempSize <= 100) then begin
  1172.                 LineWidth := TempSize;
  1173.                 ShowLineWidth;
  1174.             end
  1175.         else
  1176.             beep;
  1177.     end;
  1178.  
  1179.  
  1180.     procedure FindWhatToCopy;
  1181.         var
  1182.             kind: integer;
  1183.             WhichWindow: WindowPtr;
  1184.     begin
  1185.         WhatToCopy := NothingToCopy;
  1186.         WhichWindow := FrontWindow;
  1187.         if WhichWindow = nil then
  1188.             exit(FindWhatToCopy);
  1189.         kind := WindowPeek(WhichWindow)^.WindowKind;
  1190.         if (CurrentTool = PickerTool) and (kind <> TextKind) then
  1191.             WhatToCopy := CopyColor
  1192.         else begin
  1193.                 if (kind = PicKind) and measuring and (not macro) then
  1194.                     kind := ResultsKind;
  1195.                 case kind of
  1196.                     PicKind: 
  1197.                         with info^, info^.RoiRect do
  1198.                             if RoiShowing and (left >= 0) and (top >= 0) and (right <= PicRect.right) and (bottom <= PicRect.bottom) then
  1199.                                 WhatToCopy := CopySelection;
  1200.                     HistoKind: 
  1201.                         WhatToCopy := CopyHistogram;
  1202.                     ProfilePlotKind: 
  1203.                         WhatToCopy := CopyPlot;
  1204.                     CalibrationPlotKind: 
  1205.                         WhatToCopy := CopyCalibrationPlot;
  1206.                     LUTKind: 
  1207.                         if info <> NoInfo then
  1208.                             WhatToCopy := CopyCLUT;
  1209.                     MapKind: 
  1210.                         if info <> NoInfo then
  1211.                             WhatToCopy := CopyGrayMap;
  1212.                     ToolKind: 
  1213.                         WhatToCopy := CopyTools;
  1214.                     TextKind:  begin
  1215.                             TextInfo := TextInfoPtr(WindowPeek(WhichWindow)^.RefCon);
  1216.                             if TextInfo <> nil then
  1217.                                 with TextInfo^.TextTE^^ do
  1218.                                     if selEnd > selStart then
  1219.                                         WhatToCopy := CopyText;
  1220.                         end;
  1221.                     InfoKind, ResultsKind: 
  1222.                         if mCount > 0 then
  1223.                             WhatToCopy := CopyMeasurements;
  1224.                     otherwise
  1225.                 end;
  1226.             end;
  1227.     end;
  1228.  
  1229.  
  1230.     procedure UpdateEditMenu;
  1231.         var
  1232.             DimUndo, ShowItems: boolean;
  1233.             str: str255;
  1234.             i: integer;
  1235.     begin
  1236.         with info^ do begin
  1237.                 if CurrentKind < 0 then begin   {DA is active, so activate Edit menu.}
  1238.                         SetItem(EditMenuH, UndoItem, 'Undo');
  1239.                         SetItem(EditMenuH, CutItem, 'Cut');
  1240.                         SetItem(EditMenuH, CopyItem, 'Copy');
  1241.                         SetMenuItem(EditMenuH, UndoItem, true);
  1242.                         for i := CutItem to ClearItem do
  1243.                             SetMenuItem(EditMenuH, i, true);
  1244.                         exit(UpdateEditMenu);
  1245.                     end;
  1246.                 if not (WhatToUndo in [UndoLUT, UndoMeasurement, UndoPoint]) and ((info = NoInfo) or (PixMapSize <> CurrentUndoSize)) then
  1247.                     WhatToUndo := NothingToUndo;
  1248.                 DimUndo := WhatToUndo = NothingToUndo;
  1249.                 SetMenuItem(EditMenuH, UndoItem, not DimUndo);
  1250.                 if DimUndo then
  1251.                     SetItem(EditMenuH, UndoItem, 'Undo');
  1252.                 case WhatToUndo of
  1253.                     UndoEdit: 
  1254.                         str := 'Editing';
  1255.                     UndoFlip: 
  1256.                         str := 'Flip';
  1257.                     UndoRotate: 
  1258.                         str := 'Rotate';
  1259.                     UndoFilter: 
  1260.                         str := 'Filtering';
  1261.                     UndoPaste: 
  1262.                         str := 'Paste';
  1263.                     UndoMeasurement, UndoPoint: 
  1264.                         str := 'Measurement';
  1265.                     UndoTransform: 
  1266.                         str := 'Transformation';
  1267.                     UndoClear: 
  1268.                         str := 'Clear';
  1269.                     UndoZoom: 
  1270.                         str := 'Zoom';
  1271.                     UndoOutline: 
  1272.                         str := 'Outline';
  1273.                     UndoSliceDelete, UndoFirstSliceDelete: 
  1274.                         str := 'Delete Slice';
  1275.                     UndoLUT: 
  1276.                         str := 'LUT Change';
  1277.                     otherwise
  1278.                         str := '';
  1279.                 end;
  1280.                 SetItem(EditMenuH, UndoItem, concat('Undo ', str));
  1281.                 FindWhatToCopy;
  1282.                 if WhatToCopy = CopySelection then
  1283.                     str := 'Cut Selection'
  1284.                 else
  1285.                     str := 'Cut';
  1286.                 SetItem(EditMenuH, CutItem, str);
  1287.                 SetMenuItem(EditMenuH, CutItem, (WhatToCopy = CopySelection) or (WhatToCopy = CopyText));
  1288.                 case WhatToCopy of
  1289.                     NothingToCopy, CopyText: 
  1290.                         str := '';
  1291.                     CopySelection: 
  1292.                         str := 'Selection';
  1293.                     CopyCLUT: 
  1294.                         str := 'LUT';
  1295.                     CopyGrayMap: 
  1296.                         str := 'Gray Map';
  1297.                     CopyTools: 
  1298.                         str := 'Tools';
  1299.                     CopyPlot: 
  1300.                         str := 'Plot';
  1301.                     CopyCalibrationPlot: 
  1302.                         str := 'Calibration Plot';
  1303.                     CopyHistogram: 
  1304.                         str := 'Histogram';
  1305.                     CopyMeasurements: 
  1306.                         str := 'Measurements';
  1307.                     CopyColor: 
  1308.                         str := 'Color';
  1309.                 end;
  1310.                 SetItem(EditMenuH, CopyItem, concat('Copy ', str));
  1311.                 SetMenuItem(EditMenuH, CopyItem, WhatToCopy <> NothingToCopy);
  1312.                 SetMenuItem(EditMenuH, ClearItem, (WhatToCopy = CopySelection) or (WhatToCopy = CopyText));
  1313.                 ShowItems := (WhatsOnClip <> NothingOnClip) or (OldScrapCount <> GetScrapCount);
  1314.                 SetMenuItem(EditMenuH, PasteItem, ShowItems);
  1315.                 SetMenuItem(EditMenuH, ShowClipboardItem, ShowItems and (WhatsOnClip <> TextOnClip));
  1316.                 ShowItems := info <> NoInfo;
  1317.                 if CurrentKind = TextKind then
  1318.                     SetItem(EditMenuH, FillItem, 'Find…')
  1319.                 else
  1320.                     SetItem(EditMenuH, FillItem, 'Fill');
  1321.                 SetMenuItem(EditMenuH, FillItem, ShowItems or (CurrentKind = TextKind));
  1322.                 SetMenuItem(EditMenuH, InvertItem, ShowItems);
  1323.                 SetMenuItem(EditMenuH, DrawBoundaryItem, ShowItems);
  1324.                 SetMenuItem(EditMenuH, DrawScaleItem, ShowItems);
  1325.                 if RoiShowing and EqualRect(RoiRect, PicRect) then
  1326.                     SetItem(EditMenuH, SelectAllItem, 'Deselect All')
  1327.                 else
  1328.                     SetItem(EditMenuH, SelectAllItem, 'Select All');
  1329.                 for i := SelectAllItem to ScaleAndRotateItem do
  1330.                     SetMenuItem(EditMenuH, i, ShowItems);
  1331.                 for i := RotateLeftItem to FlipHorizontalItem do
  1332.                     SetMenuItem(EditMenuH, i, ShowItems);
  1333.                 SetMenuItem(EditMenuH, UnZoomItem, ShowItems and ((magnification <> 1.0) or ScaleToFitWindow));
  1334.             end; {with}
  1335.     end;
  1336.  
  1337.  
  1338.     procedure ZoomOut;
  1339.         var
  1340.             Width, Height, divisor, NewWidth, NewHeight: integer;
  1341.             OldMagnification, xratio, yratio: extended;
  1342.     begin
  1343.         with Info^ do begin
  1344.                 if magnification < 2.0 then begin
  1345.                         beep;
  1346.                         exit(ZoomOut)
  1347.                     end;
  1348.                 OldMagnification := magnification;
  1349.                 if magnification = 2.0 then begin
  1350.                         magnification := 1.0;
  1351.                         divisor := 4
  1352.                     end
  1353.                 else if magnification = 3.0 then begin
  1354.                         magnification := 2.0;
  1355.                         divisor := 6
  1356.                     end
  1357.                 else if magnification = 4.0 then begin
  1358.                         magnification := 3.0;
  1359.                         divisor := 8
  1360.                     end
  1361.                 else begin
  1362.                         magnification := magnification / 2.0;
  1363.                         divisor := 4
  1364.                     end;
  1365.                 if EqualRect(SrcRect, PicRect) then begin {Make window smaller}
  1366.                         NewWidth := trunc(PicRect.right * magnification);
  1367.                         NewHeight := trunc(PicRect.bottom * magnification);
  1368.                         SizeWindow(wptr, NewWidth, NewHeight, true);
  1369.                         wrect.right := NewWidth;
  1370.                         wrect.bottom := NewHeight;
  1371.                         SrcRect := PicRect;
  1372.                         UpdateTitleBar;
  1373.                         UpdatePicWindow;
  1374.                         DrawMyGrowIcon(wptr);
  1375.                         exit(ZoomOut);
  1376.                     end;
  1377.                 if ((wrect.right > PicRect.right) or (wrect.bottom > PicRect.bottom)) then begin
  1378.                         xratio := wrect.right / PicRect.right;
  1379.                         yratio := wrect.bottom / PicRect.bottom;
  1380.                         if (xratio <> yratio) or ((xratio - trunc(xratio)) <> 0.0) then begin
  1381.                                 UnZoom;
  1382.                                 Exit(ZoomOut)
  1383.                             end;
  1384.                         SrcRect := PicRect;
  1385.                         Magnification := xratio;
  1386.                         UpdateTitleBar;
  1387.                         UpdatePicWindow;
  1388.                         DrawMyGrowIcon(wptr);
  1389.                         Exit(ZoomOut)
  1390.                     end;
  1391.             end; {with}
  1392.         with Info^.SrcRect, info^ do begin
  1393.                 if magnification = 1.0 then begin
  1394.                         width := wrect.right;
  1395.                         height := wrect.bottom;
  1396.                     end
  1397.                 else begin
  1398.                         width := round((right - left) * OldMagnification / Magnification);
  1399.                         height := round((bottom - top) * OldMagnification / Magnification);
  1400.                     end;
  1401.                 left := left - (width div divisor);
  1402.                 if left < 0 then
  1403.                     left := 0;
  1404.                 if (left + width) > Info^.PicRect.right then
  1405.                     left := Info^.PicRect.right - width;
  1406.                 top := top - (height div divisor);
  1407.                 if top < 0 then
  1408.                     top := 0;
  1409.                 if (top + height) > Info^.PicRect.bottom then
  1410.                     top := Info^.picRect.bottom - height;
  1411.                 right := left + width;
  1412.                 bottom := top + height;
  1413.                 RoiShowing := false;
  1414.                 UpdatePicWindow;
  1415.                 DrawMyGrowIcon(wptr);
  1416.                 UpdateTitleBar;
  1417.             end;
  1418.         ShowRoi;
  1419.     end;
  1420.  
  1421.  
  1422.     procedure DoGrow; {(WhichWindow: WindowPtr; event: EventRecord)}
  1423.         var
  1424.             NewSize: LongInt;
  1425.             trect, WinRect, SizeRect: rect;
  1426.             kind: integer;
  1427.             WasDigitizing: boolean;
  1428.             ZoomCenterH, ZoomCenterV, width, height: extended;
  1429.     begin
  1430.         kind := WindowPeek(WhichWindow)^.WindowKind;
  1431.         if (kind = PicKind) and (info^.PictureType = ScionType) then
  1432.             exit(DoGrow);
  1433.         if kind = PicKind then
  1434.             with info^, SizeRect do begin
  1435.                     if ScaleToFitWindow then
  1436.                         SizeRect := ScreenBits.bounds
  1437.                     else begin
  1438.                             right := PicRect.right + 1;
  1439.                             bottom := PicRect.bottom + 1;
  1440.                             if magnification > 1.0 then begin
  1441.                                     right := round(right * magnification);
  1442.                                     bottom := round(bottom * magnification);
  1443.                                 end;
  1444.                             left := 32;
  1445.                             top := 32;
  1446.                             if left > right then
  1447.                                 left := right;
  1448.                             if top > bottom then
  1449.                                 top := bottom;
  1450.                         end
  1451.                 end
  1452.         else
  1453.             SetRect(SizeRect, 64, 48, 2048, 2048);
  1454.         NewSize := GrowWindow(WhichWindow, event.where, SizeRect);
  1455.         if newSize = 0 then
  1456.             exit(DoGrow);
  1457.         if kind = PicKind then
  1458.             with Info^ do begin
  1459.                     SetPort(wptr);
  1460.                     WasDigitizing := digitizing;
  1461.                     StopDigitizing;
  1462.                     InvalRect(wrect);
  1463.                     with trect do begin
  1464.                             top := 0;
  1465.                             left := 0;
  1466.                             right := LoWord(NewSize);
  1467.                             bottom := HiWord(NewSize);
  1468.                         end;
  1469.                     if ScaleToFitWindow then begin
  1470.                             ScaleImageWindow(trect);
  1471.                             wrect := trect;
  1472.                         end
  1473.                     else begin
  1474.                             if trect.right > PicRect.right * magnification then
  1475.                                 trect.right := trunc(PicRect.right * magnification);
  1476.                             if trect.bottom > PicRect.bottom * magnification then
  1477.                                 trect.bottom := trunc(PicRect.bottom * magnification);
  1478.                             wrect := trect;
  1479.                             with SrcRect do begin
  1480.                                     ZoomCenterH := left + (wrect.right / 2.0) / magnification;
  1481.                                     ZoomCenterV := top + (wrect.bottom / 2.0) / magnification;
  1482.                                     width := wrect.right / magnification;
  1483.                                     height := wrect.bottom / magnification;
  1484.                                     left := round(ZoomCenterH - width / 2.0);
  1485.                                     if left < 0 then
  1486.                                         left := 0;
  1487.                                     if (left + width) > PicRect.right then
  1488.                                         left := round(PicRect.right - width);
  1489.                                     top := round(ZoomCenterV - height / 2.0);
  1490.                                     if top < 0 then
  1491.                                         top := 0;
  1492.                                     if (top + height) > PicRect.bottom then
  1493.                                         top := round(picRect.bottom - height);
  1494.                                     right := round(left + width);
  1495.                                     bottom := round(top + height);
  1496.                                     wrect.right := trunc((right - left) * magnification);
  1497.                                     wrect.bottom := trunc((bottom - top) * magnification);
  1498.                                 end;
  1499.                             savewrect := wrect;
  1500.                         end;
  1501.                     SizeWindow(WhichWindow, wrect.right, wrect.bottom, true);
  1502.                     WindowState := NormalWindow;
  1503.                     if WasDigitizing then
  1504.                         StartDigitizing;
  1505.                     exit(DoGrow)
  1506.                 end; {with info^}
  1507.         if WhichWindow = PlotWindow then begin
  1508.                 PlotWidth := LoWord(NewSize);
  1509.                 PlotHeight := hiWord(NewSize);
  1510.                 SetPort(PlotWindow);
  1511.                 SizeWindow(PlotWindow, PlotWidth, Plotheight, true);
  1512.                 InvalRect(PlotWindow^.PortRect);
  1513.                 exit(DoGrow)
  1514.             end;
  1515.         if (kind = TextKind) then begin
  1516.                 TextInfo := TextInfoPtr(WindowPeek(WhichWindow)^.RefCon);
  1517.                 GrowTextWindow(NewSize);
  1518.                 exit(DoGrow)
  1519.             end;
  1520.         if WhichWindow = ResultsWindow then begin
  1521.                 ResultsWidth := LoWord(NewSize);
  1522.                 ResultsHeight := hiWord(NewSize);
  1523.                 SetPort(ResultsWindow);
  1524.                 with ResultsWindow^.PortRect do
  1525.                     SetRect(tRect, right - 12, bottom - 12, right, bottom);
  1526.                 EraseRect(trect); {Erase Grow Box}
  1527.                 SizeWindow(ResultsWindow, ResultsWidth, ResultsHeight, true);
  1528.                 MoveControl(hScrollBar, -1, ResultsHeight - ScrollBarWidth);
  1529.                 MoveControl(vScrollBar, ResultsWidth - ScrollBarWidth, -1);
  1530.                 SizeControl(hScrollBar, ResultsWidth - 13, ScrollBarWidth + 1);
  1531.                 SizeControl(vScrollBar, ScrollBarWidth + 1, ResultsHeight - 13);
  1532.                 InvalRect(ResultsWindow^.PortRect);
  1533.                 with ListTE^^.viewRect do begin
  1534.                         right := left + ResultsWidth - ScrollBarWidth - 4;
  1535.                         bottom := top + ResultsHeight - ScrollBarWidth;
  1536.                     end;
  1537.                 UpdateResultsScrollBars;
  1538.                 ScrollResultsText;
  1539.             end;
  1540.     end;
  1541.  
  1542.  
  1543.     procedure ZoomIn; {(event: EventRecord)}
  1544.         var
  1545.             width, height, OldMagnification: extended;
  1546.             PicCenterH, PicCenterV, NewWidth, NewHeight: integer;
  1547.             trect: rect;
  1548.     begin
  1549.         if Info = NoInfo then begin
  1550.                 beep;
  1551.                 exit(ZoomIn)
  1552.             end;
  1553.         if Info^.ScaleToFitWindow then begin
  1554.                 PutMessage('The magnifying glass does not work in "Scale to Fit Window" mode.');
  1555.                 exit(ZoomIn)
  1556.             end;
  1557.         if BitAnd(Event.modifiers, OptionKey) = OptionKey then begin
  1558.                 ZoomOut;
  1559.                 WhatToUndo := NothingToUndo;
  1560.                 exit(ZoomIn)
  1561.             end;
  1562.         with Info^ do begin
  1563.                 OldMagnification := magnification;
  1564.                 if magnification = 1.0 then
  1565.                     magnification := 2.0
  1566.                 else if magnification = 2.0 then
  1567.                     magnification := 3.0
  1568.                 else if magnification = 3.0 then
  1569.                     magnification := 4.0
  1570.                 else begin
  1571.                         magnification := magnification * 2.0;
  1572.                         if magnification > 64.0 then begin
  1573.                                 magnification := 64.0;
  1574.                                 exit(ZoomIn)
  1575.                             end;
  1576.                     end;
  1577.                 if (WindowState = NormalWindow) and EqualRect(SrcRect, PicRect) then {Make window bigger?}
  1578.                     with trect do begin
  1579.                             NewWidth := trunc(PicRect.right * magnification);
  1580.                             NewHeight := trunc(PicRect.bottom * magnification);
  1581.                             if NewWidth <= 640 then begin
  1582.                                     GetWindowRect(wptr, trect);
  1583.                                     if ((left + NewWidth) <= ScreenWidth) and ((top + NewHeight) <= ScreenHeight) then begin
  1584.                                             SizeWindow(wptr, NewWidth, NewHeight, true);
  1585.                                             wrect.right := NewWidth;
  1586.                                             wrect.bottom := NewHeight;
  1587.                                         end;
  1588.                                 end;
  1589.                         end;
  1590.             end; {with}
  1591.         with Info^.SrcRect, Info^ do begin
  1592.                 PicCenterH := left + round(event.where.h / OldMagnification);
  1593.                 PicCenterV := top + round(event.where.v / OldMagnification);
  1594.                 width := wrect.right / magnification;
  1595.                 height := wrect.bottom / magnification;
  1596.                 left := PicCenterH - round(width / 2);
  1597.                 if left < 0 then
  1598.                     left := 0;
  1599.                 if (left + width) > PicRect.right then
  1600.                     left := PicRect.right - round(width);
  1601.                 top := PicCenterV - round(height / 2);
  1602.                 if top < 0 then
  1603.                     top := 0;
  1604.                 if (top + height) > PicRect.bottom then
  1605.                     top := picRect.bottom - round(height);
  1606.                 right := left + round(width);
  1607.                 bottom := top + round(height);
  1608.                 wrect.right := trunc((right - left) * magnification);
  1609.                 wrect.bottom := trunc((bottom - top) * magnification);
  1610.                 SizeWindow(wptr, wrect.right, wrect.bottom, true);
  1611.                 RoiShowing := false;
  1612.                 UpdatePicWindow;
  1613.                 DrawMyGrowIcon(wptr);
  1614.                 UpdateTitleBar;
  1615.                 WhatToUndo := UndoZoom;
  1616.                 ShowRoi;
  1617.             end; {with}
  1618.     end;
  1619.  
  1620.  
  1621.     procedure SynchScroll;
  1622.         var
  1623.             n: integer;
  1624.             TempInfo, SaveInfo: InfoPtr;
  1625.     begin
  1626.         SaveInfo := info;
  1627.         if allsamesize then
  1628.             for n := 1 to nPics do begin
  1629.                     TempInfo := pointer(WindowPeek(PicWindow[n])^.RefCon);
  1630.                     TempInfo^.SrcRect := info^.SrcRect;
  1631.                     TempInfo^.magnification := Info^.magnification;
  1632.                     info := TempInfo;
  1633.                     UpdatePicWindow;
  1634.                     Info := SaveInfo;
  1635.                 end
  1636.         else
  1637.             PutMessage('Synchronized scrolling requires all images and all windows to be the same size.');
  1638.     end;
  1639.  
  1640.  
  1641.     procedure Scroll; {(event: EventRecord)}
  1642.         var
  1643.             hstart, vstart, DeltaH, DeltaV, width, height: integer;
  1644.             loc: point;
  1645.             SaveSR: rect;
  1646.             WasDigitizing: boolean;
  1647.     begin
  1648.         with info^ do begin
  1649.                 if ScaleToFitWindow then begin
  1650.                         PutMessage('Scrolling does not work in "Scale to Fit Window" mode.');
  1651.                         exit(Scroll)
  1652.                     end;
  1653.                 WasDigitizing := digitizing;
  1654.                 StopDigitizing;
  1655.                 with event.where do begin
  1656.                         hstart := h;
  1657.                         vstart := v
  1658.                     end;
  1659.                 with SrcRect do begin
  1660.                         width := right - left;
  1661.                         height := bottom - top
  1662.                     end;
  1663.                 SaveSR := SrcRect;
  1664.                 while StillDown do begin
  1665.                         GetMouse(loc);
  1666.                         DeltaH := hstart - loc.h;
  1667.                         DeltaV := vstart - loc.v;
  1668.                         with SrcRect do begin
  1669.                                 left := SaveSR.left + DeltaH;
  1670.                                 if left < 0 then
  1671.                                     left := 0;
  1672.                                 if (left + width) > PicRect.right then
  1673.                                     left := PicRect.right - width;
  1674.                                 right := left + width;
  1675.                                 top := SaveSR.top + DeltaV;
  1676.                                 if top < 0 then
  1677.                                     top := 0;
  1678.                                 if (top + height) > PicRect.bottom then
  1679.                                     top := PicRect.bottom - height;
  1680.                                 bottom := top + height;
  1681.                             end;
  1682.                         UpdatePicWindow;
  1683.                         DrawMyGrowIcon(wptr);
  1684.                     end;
  1685.                 WhatToUndo := NothingToUndo;
  1686.                 ShowRoi;
  1687.                 if OptionKeyDown and (nPics > 1) then
  1688.                     SynchScroll;
  1689.                 if WasDigitizing then
  1690.                     StartDigitizing;
  1691.             end; {with info^}
  1692.     end;
  1693.  
  1694.  
  1695.     procedure ConvertClipboard;
  1696. {Converts local scrape to system scrape when quitting or}
  1697. {switching to other programs or DAs . }
  1698.         var
  1699.             PicH: PicHandle;
  1700.             frect: rect;
  1701.             err: LongInt;
  1702.     begin
  1703.         PicH := nil;
  1704.         if ((WhatsOnClip = RectPic) or (WhatsOnClip = CameraPic)) and (ClipBuf <> nil) and not ClipboardConverted then
  1705.             with ClipBufInfo^ do begin
  1706.                     ShowWatch;
  1707.                     SetPort(GrafPtr(osPort));
  1708.                     with RoiRect do
  1709.                         SetRect(frect, 0, 0, right - left, bottom - top);
  1710.                     ClipRect(frect);
  1711.                     LoadLUT(ctable);  {Switch to original LUT}
  1712.                     RGBForeColor(BlackRGB);
  1713.                     RGBBackColor(WhiteRGB);
  1714.                     PicH := OpenPicture(frect);
  1715.                     with osPort^ do begin
  1716.                             hlock(handle(portPixMap));
  1717.                             CopyBits(BitMapHandle(portPixMap)^^, BitMapHandle(portPixMap)^^, RoiRect, frect, SrcCopy, nil);
  1718.                             hunlock(handle(portPixMap));
  1719.                         end;
  1720.                     ClosePicture;
  1721.                     if info <> NoInfo then
  1722.                         LoadLUT(info^.ctable); {Restore LUT}
  1723.                     if (PicH <> nil) or ClipTextInBuffer then begin
  1724.                             err := ZeroScrap;
  1725.                             if err = NoErr then begin
  1726.                                     if PicH <> nil then begin
  1727.                                             hlock(handle(PicH));
  1728.                                             err := PutScrap(GetHandleSize(handle(PicH)), 'PICT', handle(PicH)^);
  1729.                                             hunlock(handle(PicH));
  1730.                                             DisposHandle(handle(PicH));
  1731.                                         end;
  1732.                                     if (err = noErr) and ClipTextInBuffer then
  1733.                                         err := PutScrap(TextBufSize, 'TEXT', ptr(TextBufP));
  1734.                                 end; {if err=NoErr}
  1735.                         end;
  1736.                     ClipboardConverted := true;
  1737.                 end; {with}
  1738.     end;
  1739.  
  1740.  
  1741.     procedure SetupOperation; {(item: integer)}
  1742.         var
  1743.             AutoSelectAll: boolean;
  1744.     begin
  1745.         if NotinBounds then
  1746.             exit(SetupOperation);
  1747.         if (item = 10) then
  1748.             if NoSelection then
  1749.                 exit(SetupOperation);
  1750.         StopDigitizing;
  1751.         AutoSelectAll := not Info^.RoiShowing;
  1752.         if AutoSelectAll then
  1753.             SelectAll(true);
  1754.         SetupUndo;
  1755.         WhatToUndo := UndoEdit;
  1756.         case Item of
  1757.             8:  begin
  1758.                     CurrentOp := PaintOp;
  1759.                     OpPending := true
  1760.                 end;
  1761.             9:  begin
  1762.                     CurrentOp := InvertOp;
  1763.                     OpPending := true
  1764.                 end;
  1765.             10:  begin
  1766.                     CurrentOp := FrameOp;
  1767.                     OpPending := true
  1768.                 end;
  1769.         end;
  1770.         if AutoSelectAll then
  1771.             KillRoi;
  1772.         RoiUpdateTime := 0; {Forces outline to be redrawn in scale-to-fit mode.}
  1773.     end;
  1774.  
  1775.  
  1776.     procedure DoUndo;
  1777.         var
  1778.             aok: boolean;
  1779.     begin
  1780.         case WhatToUndo of
  1781.             UndoMeasurement: 
  1782.                 UndoLastMeasurement(true);
  1783.             UndoPoint:  begin
  1784.                     Undo;
  1785.                     UpdatePicWindow;
  1786.                     UndoLastMeasurement(true);
  1787.                     WhatToUndo := NothingToUndo;
  1788.                 end;
  1789.             UndoZoom:  begin
  1790.                     ZoomOut;
  1791.                     if info^.magnification < 2 then
  1792.                         WhatToUndo := NothingToUndo;
  1793.                 end;
  1794.             UndoOutLine:  begin
  1795.                     undo;
  1796.                     if WandAutoMeasure then
  1797.                         UndoLastMeasurement(true);
  1798.                     WhatToUndo := NothingToUndo;
  1799.                     UpdatePicWindow;
  1800.                 end;
  1801.             UndoSliceDelete, UndoFirstSliceDelete: 
  1802.                 if info^.StackInfo <> nil then
  1803.                     with info^.StackInfo^ do begin
  1804.                             if WhatToUndo = UndoFirstSliceDelete then
  1805.                                 CurrentSlice := 0;
  1806.                             aok := AddSlice(false);
  1807.                             if aok then begin
  1808.                                     Undo;
  1809.                                     UpdatePicWindow;
  1810.                                 end
  1811.                             else if CurrentSlice = 0 then
  1812.                                 CurrentSlice := 1;
  1813.                         end;
  1814.             UndoLUT:  begin
  1815.                     UndoLutChange;
  1816.                     DrawMap;
  1817.                     DensitySlicing := false;
  1818.                 end;
  1819.             otherwise begin
  1820.                     if UndoFromClip then
  1821.                         OpPending := false;
  1822.                     if not OpPending then
  1823.                         undo;
  1824.                     WhatToUndo := NothingToUndo;
  1825.                     if IsInsertionPoint then begin
  1826.                             InsertionPoint := TextStart;
  1827.                             TextStr := '';
  1828.                         end;
  1829.                     UpdatePicWindow;
  1830.                     if OpPending and (CurrentOp = PasteOp) then begin
  1831.                             OpPending := false;
  1832.                             KillRoi;
  1833.                         end;
  1834.                     OpPending := false;
  1835.                 end;
  1836.         end; {case}
  1837.     end;
  1838.  
  1839.  
  1840.  
  1841. end.