home *** CD-ROM | disk | FTP | other *** search
/ Otherware / Otherware_1_SB_Development.iso / mac / developm / source / image144.sit / Utilities.p < prev   
Encoding:
Text File  |  1992-03-30  |  64.3 KB  |  2,727 lines

  1. unit Utilities;
  2.  
  3. {Miscellaneous utility routines used by Image program}
  4.  
  5. interface
  6.  
  7.     uses
  8.         QuickDraw, Palettes, Picker, PrintTraps, globals;{SANE}
  9.  
  10.  
  11.  
  12.     procedure SetDialogItem (TheDialog: DialogPtr; item, value: integer);
  13.     procedure OutlineButton (theDialog: DialogPtr; itemNo, CornerRad: integer);
  14.     function GetDNum (TheDialog: DialogPtr; item: integer): LongInt;
  15.     function GetDString (TheDialog: DialogPtr; item: integer): str255;
  16.     procedure SetDNum (TheDialog: DialogPtr; item: integer; n: LongInt);
  17.     procedure GetWindowRect (w: WindowPtr; var wrect: rect);
  18.     procedure SetDReal (TheDialog: DialogPtr; item: integer; n: extended; fwidth: integer);
  19.     procedure SetDString (TheDialog: DialogPtr; item: integer; str: str255);
  20.     procedure DrawSItem (itemnum, fontrqst, sizerqst: integer; d: dialogptr; s: str255);
  21.     function StringToReal (str: str255): real;
  22.     function GetDReal (TheDialog: DialogPtr; item: integer): extended;
  23.     procedure RealToString (Val: extended; width, fwidth: integer; var Str: Str255);
  24.     procedure DrawReal (Val: extended; width, fwidth: integer);
  25.     procedure DrawJReal (hloc, vloc: integer; Val: extended; fwidth: integer);
  26.     procedure DrawLong (i: LongInt);
  27.     function GetInt (message: str255; default: integer; var Canceled: boolean): integer;
  28.     function GetReal (message: str255; default: extended; var Canceled: boolean): extended;
  29.     function OptionKeyDown: boolean;
  30.     function ShiftKeyDown: boolean;
  31.     function ControlKeyDown: boolean;
  32.     function CommandPeriod: boolean;
  33.     function SpaceBarDown: boolean;
  34.  
  35.     procedure SysResume;
  36.     procedure beep;
  37.     procedure PutMessage (str: str255);
  38.     procedure UnprotectLUT;
  39.     procedure LoadLUT (table: MyCSpecArray);
  40.     procedure SetupLutUndo;
  41.     procedure UndoLutChange;
  42.     procedure DisableDensitySlice;
  43.     procedure LoadInputLookupTable (address: ptr);
  44.     procedure ResetQuickCapture;
  45.     procedure wait (ticks: LongInt);
  46.     function GetScrapCount: integer;
  47.     procedure DisplayText (update: boolean);
  48.     procedure ScreenToOffscreen (var loc: point);
  49.     procedure OffscreenToScreen (var loc: point);
  50.     procedure OffScreenToScreenRect (var r: rect);
  51.     procedure UpdateScreen (MaskRect: rect);
  52.     procedure RestoreRoi;
  53.     procedure Undo;
  54.     procedure CheckOnOffItem (MenuH: MenuHandle; item, fst, lst: Integer);
  55.     procedure SetMenuItem (menuh: menuhandle; itemnum: integer; on: boolean);
  56.     function GetFontSize (item: integer): integer;
  57.     function MyGetPixel (h, v: integer): integer;
  58.     procedure PutPixel (h, v, value: integer);
  59.     procedure GetLine (h, v, count: integer; var line: LineType);
  60.     procedure GetColumn (hstart, vstart, count: integer; var data: LineType);
  61.     procedure PutColumn (hstart, vstart, count: integer; var data: LineType);
  62.     procedure PutLine (h, v, count: integer; var line: LineType);
  63.     procedure Show1Value (rvalue, CalibratedValue: extended);
  64.     procedure Show2CalibratedValues (x, y: LongInt; ShowUncalibrated: boolean);
  65.     procedure Show2Values (current, total: LongInt);
  66.     procedure DrawXDimension (x: real; digits: integer);
  67.     procedure DrawYDimension (y: real; digits: integer);
  68.     procedure DrawRGB (index: integer);
  69.     procedure Show3Values (hloc, vloc, ivalue: LongInt);
  70.     procedure ShowDxDy (X, Y: real);
  71.     procedure PutChar (c: char);
  72.     procedure PutTab;
  73.     procedure PutString (str: str255);
  74.     procedure PutReal (n: extended; width, fwidth: integer);
  75.     procedure PutLong (n: LongInt; FieldWidth: integer);
  76.     procedure CopyResultsToBuffer (FirstCount, LastCount: integer; Headings: boolean);
  77.     procedure ShowWatch;
  78.     procedure UpdatePicWindow;
  79.     procedure DoOperation (Operation: OpType);
  80.     procedure SaveRoi;
  81.     procedure KillRoi;
  82.     procedure Paste;
  83.     procedure ShowRoi;
  84.     procedure SetupUndo;
  85.     procedure SetupUndoFromClip;
  86.     procedure GetLoi (var x1, y1, x2, y2: real);
  87.     function NotRectangular: boolean;
  88.     function NotInBounds: boolean;
  89.     function NoSelection: boolean;
  90.     function NoUndo: boolean;
  91.     function NewPicWindow (name: str255; width, height: integer): boolean;
  92.     procedure MakeRegion;
  93.     procedure SelectAll (visible: boolean);
  94.     procedure EraseScreen;
  95.     procedure RestoreScreen;
  96.     procedure UpdateTitleBar;
  97.     procedure Unzoom;
  98.     function FindMedian (var a: SortArray): integer;
  99.     procedure DrawBString (str: string);
  100.     procedure DrawMyGrowIcon (w: WindowPtr);
  101.     procedure PutMemoryAlert;
  102.     function GetImageMemory (SaveInfo: infoPtr; var PicBaseHandle: handle; double: boolean): ptr;
  103.     procedure UpdateAnalysisMenu;
  104.     procedure ExtendWindowsMenu (fname: str255; size: LongInt; wptr: WindowPtr);
  105.     procedure MakeNewWindow (name: str255);
  106.     procedure PutWarning;
  107.     procedure ScaleToFit;
  108.     procedure SetupRoiRect;
  109.     procedure SetForegroundColor (color: integer);
  110.     procedure SetBackgroundColor (color: integer);
  111.     procedure GetForegroundColor (event: EventRecord);
  112.     procedure GetBackgroundColor (event: EventRecord);
  113.     procedure GenerateValues;
  114.     procedure KillOperation;
  115.     procedure ScaleImageWindow (var trect: rect);
  116.     procedure InvertGrayLevels;
  117.     function TooWide: boolean;
  118.     procedure DrawTextString (str: str255; loc: point; just: integer);
  119.     procedure IncrementCounter;
  120.     procedure ClearResults (i: integer);
  121.     procedure UpdateFitEllipse;
  122.     procedure UpdateTextItems;
  123.  
  124.  
  125. implementation
  126.  
  127.  
  128.     type
  129.         KeyPtrType = ^KeyMap;
  130.  
  131.  
  132.  
  133. {$PUSH}
  134. {$D-}
  135.  
  136.     procedure MacsBug (str: str255);
  137.     inline
  138.         $abff;
  139.  
  140.  
  141.     procedure SetDialogItem;{(TheDialog:DialogPtr; item,value:integer)}
  142.         var
  143.             ItemType: integer;
  144.             ItemBox: rect;
  145.             ItemHdl: handle;
  146.     begin
  147.         GetDItem(TheDialog, item, ItemType, ItemHdl, ItemBox);
  148.         SetCtlValue(ControlHandle(ItemHdl), value)
  149.     end;
  150.  
  151.  
  152.     procedure OutlineButton;{(theDialog: DialogPtr; itemNo, CornerRad: integer)}
  153. { Draws a border around a button. 16 is the normal}
  154. {  cornerRad for small buttons }
  155.         var
  156.             itemType: Integer;
  157.             itemBox: Rect;
  158.             itemHdl: Handle;
  159.             tempPort: GrafPtr;
  160.     begin
  161.         GetPort(tempPort);
  162.         SetPort(GrafPtr(theDialog));
  163.         GetDItem(theDialog, itemNo, itemType, itemHdl, itemBox);
  164.         PenSize(3, 3);
  165.         InSetRect(itemBox, -4, -4);
  166.         FrameRoundRect(itemBox, cornerRad, cornerRad);
  167.         PenSize(1, 1);
  168.         SetPort(tempPort);
  169.     end;
  170.  
  171.  
  172.     function GetDNum;{(TheDialog:DialogPtr; item:integer):LongInt}
  173.         var
  174.             ItemType: integer;
  175.             ItemBox: rect;
  176.             ItemHdl: handle;
  177.             str: str255;
  178.             n: LongInt;
  179.     begin
  180.         GetDItem(TheDialog, item, ItemType, ItemHdl, ItemBox);
  181.         GetIText(ItemHdl, str);
  182.         StringToNum(str, n);
  183.         GetDNum := n;
  184.     end;
  185.  
  186.  
  187.     function GetDString;{(TheDialog:DialogPtr; item:integer):str255}
  188.         var
  189.             ItemType: integer;
  190.             ItemBox: rect;
  191.             ItemHdl: handle;
  192.             str: str255;
  193.     begin
  194.         GetDItem(TheDialog, item, ItemType, ItemHdl, ItemBox);
  195.         GetIText(ItemHdl, str);
  196.         GetDString := str;
  197.     end;
  198.  
  199.  
  200.     procedure SetDNum;{(TheDialog:DialogPtr; item:integer; n:LongInt)}
  201.         var
  202.             ItemType: integer;
  203.             ItemBox: rect;
  204.             ItemHdl: handle;
  205.             str: str255;
  206.     begin
  207.         GetDItem(TheDialog, item, ItemType, ItemHdl, ItemBox);
  208.         NumToString(n, str);
  209.         SetIText(ItemHdl, str)
  210.     end;
  211.  
  212.  
  213.     procedure GetWindowRect;{(w:WindowPtr; VAR wrect:rect)}
  214.   {Returns global coordinates of specified window.}
  215.     begin
  216.         if w <> nil then
  217.             wrect := WindowPeek(w)^.contRgn^^.rgnBBox
  218.         else
  219.             SetRect(wrect, 0, 0, 0, 0);
  220.     end;
  221.  
  222.  
  223.     procedure SetDReal;{(TheDialog:DialogPtr; item:integer; n:extended; fwidth:integer)}
  224.         var
  225.             ItemType: integer;
  226.             ItemBox: rect;
  227.             ItemHdl: handle;
  228.             str: str255;
  229.     begin
  230.         GetDItem(TheDialog, item, ItemType, ItemHdl, ItemBox);
  231.         RealToString(n, 1, fwidth, str);
  232.         SetIText(ItemHdl, str)
  233.     end;
  234.  
  235.     procedure SetDString;{(TheDialog:DialogPtr; item:integer; str:str255)}
  236.         var
  237.             ItemType: integer;
  238.             ItemBox: rect;
  239.             ItemHdl: handle;
  240.     begin
  241.         GetDItem(TheDialog, item, ItemType, ItemHdl, ItemBox);
  242.         SetIText(ItemHdl, str)
  243.     end;
  244.  
  245.  
  246.     function GetDReal;{(TheDialog:DialogPtr; item:integer):extended}
  247.         var
  248.             str: str255;
  249.     begin
  250.         str := GetDString(TheDialog, item);
  251.         GetDReal := StringToReal(str);
  252.     end;
  253.  
  254.  
  255.     procedure DrawLong;{(i:LongInt)}
  256.         var
  257.             str: str255;
  258.     begin
  259.         NumToString(i, str);
  260.         DrawString(str);
  261.     end;
  262.  
  263.  
  264.     procedure RealToString;{(Val:extended; width,fwidth:integer; var Str:Str255)}
  265.   {Does number to string conversion equivalent to write(val:width:fwidth).}
  266. {var}
  267. {form: DecForm;}
  268.     begin
  269.         if fwidth < 0 then begin
  270.                 if val < 1.0 then
  271.                     fwidth := 4
  272.                 else if trunc(val) = val then
  273.                     fwidth := 0
  274.                 else
  275.                     fwidth := 2;
  276.             end;
  277.         str := StringOf(val : width : fwidth); {Use LSP StringOf function because SANE Num2Str bombs out under A/UX}
  278. {form.digits := fwidth;}
  279. {form.style := FixedDecimal;}
  280. {Num2Str(form, val, DecStr(str));}
  281. {while length(Str) < width do begin}
  282. {str := concat(' ', Str)}
  283. {end;}
  284.     end;
  285.  
  286.  
  287.     procedure DrawReal;{(Val:extended; width,fwidth:integer)}
  288.   {Displays a real(or integer) number at the current location in}
  289.   {a form equivalent to write(val:width:fwidth) }
  290.         var
  291.             str: str255;
  292.     begin
  293.         RealToString(val, width, fwidth, str);
  294.         DrawString(str);
  295.     end;
  296.  
  297.  
  298.     procedure DrawJReal (hloc, vloc: integer; val: extended; fwidth: integer);
  299.   {Draws right justified real number.}
  300.         var
  301.             str: str255;
  302.     begin
  303.         if (val >= 1000.0) or (val <= -1000.0) then
  304.             fwidth := 0;
  305.         RealToString(val, 1, fwidth, str);
  306.         MoveTo(hloc - StringWidth(str) - 2, vloc);
  307.         DrawString(str);
  308.     end;
  309.  
  310.  
  311.     function GetInt (message: str255; default: integer; var Canceled: boolean): integer;
  312.         const
  313.             NumberID = 3;
  314.         var
  315.             mylog: DialogPtr;
  316.             item: integer;
  317.             temp: LongInt;
  318.     begin
  319.         ParamText(message, '', '', '');
  320.         mylog := GetNewDialog(3000, nil, pointer(-1));
  321.         SetDNum(MyLog, NumberID, default);
  322.         SelIText(MyLog, NumberID, 0, 32767);
  323.         OutlineButton(MyLog, ok, 16);
  324.         repeat
  325.             ModalDialog(nil, item);
  326.         until (item = ok) or (item = cancel);
  327.         if item = ok then begin
  328.                 Canceled := false;
  329.                 temp := GetDNum(MyLog, NumberID);
  330.                 if (temp > -MaxInt) and (temp <= MaxInt) then
  331.                     GetInt := temp
  332.                 else begin
  333.                         SysBeep(1);
  334.                         GetInt := default
  335.                     end;
  336.             end {item=ok}
  337.         else begin
  338.                 Canceled := true;
  339.                 GetInt := default;
  340.             end;
  341.         DisposDialog(mylog);
  342.     end;
  343.  
  344.  
  345.     function GetReal (message: str255; default: extended; var Canceled: boolean): extended;
  346.         const
  347.             NumberID = 3;
  348.         var
  349.             mylog: DialogPtr;
  350.             item: integer;
  351.     begin
  352.         InitCursor;
  353.         ParamText(message, '', '', '');
  354.         mylog := GetNewDialog(3000, nil, pointer(-1));
  355.         SetDReal(MyLog, NumberID, default, 2);
  356.         SelIText(MyLog, NumberID, 0, 32767);
  357.         OutlineButton(MyLog, ok, 16);
  358.         repeat
  359.             ModalDialog(nil, item);
  360.         until (item = ok) or (item = cancel);
  361.         if item = ok then begin
  362.                 GetReal := GetDReal(MyLog, NumberID);
  363.                 Canceled := false;
  364.             end
  365.         else begin
  366.                 GetReal := default;
  367.                 Canceled := true;
  368.             end;
  369.         DisposDialog(mylog);
  370.     end;
  371.  
  372.  
  373.     function OptionKeyDown;{:boolean}
  374.         var
  375.             KeyPtr: KeyPtrType;
  376.             keys: array[0..3] of LongInt;
  377.     begin
  378.         KeyPtr := KeyPtrType(@keys);
  379.         GetKeys(KeyPtr^);
  380.         OptionKeyDown := (BAND(keys[1], 4)) <> 0;
  381.     end;
  382.  
  383.  
  384.     function ShiftKeyDown;{:boolean}
  385.         var
  386.             KeyPtr: KeyPtrType;
  387.             keys: array[0..3] of LongInt;
  388.     begin
  389.         KeyPtr := KeyPtrType(@keys);
  390.         GetKeys(KeyPtr^);
  391.         ShiftKeyDown := (BAND(keys[1], 1)) <> 0;
  392.     end;
  393.  
  394.  
  395.     function ControlKeyDown;{:boolean}
  396.         type
  397.             KeyPtrType = ^KeyMap;
  398.         var
  399.             KeyPtr: KeyPtrType;
  400.             keys: array[0..3] of LongInt;
  401.     begin
  402.         KeyPtr := KeyPtrType(@keys);
  403.         GetKeys(KeyPtr^);
  404.         ControlKeyDown := (BAND(keys[1], 8)) <> 0;
  405.     end;
  406.  
  407.  
  408.     function CommandPeriod;{:boolean}
  409.         type
  410.             KeyPtrType = ^KeyMap;
  411.         var
  412.             KeyPtr: KeyPtrType;
  413.             keys: array[0..3] of LongInt;
  414.     begin
  415.         KeyPtr := KeyPtrType(@keys);
  416.         GetKeys(KeyPtr^);
  417.         CommandPeriod := (BAND(keys[1], $808000)) = $808000;
  418.     end;
  419.  
  420.  
  421.     function SpaceBarDown: boolean;
  422.         var
  423.             KeyPtr: KeyPtrType;
  424.             keys: array[0..3] of LongInt;
  425.     begin
  426.         KeyPtr := KeyPtrType(@keys);
  427.         GetKeys(KeyPtr^);
  428.         SpaceBarDown := (BAND(keys[1], 512)) <> 0;
  429.     end;
  430.  
  431.  
  432.     procedure DrawSItem; {(itemnum, fontrqst, sizerqst: integer; d: dialogptr; s: str255)}
  433. {Draw a string item in a dialog box.}
  434.         var
  435.             r: rect;
  436.             itype: integer;
  437.             ignore: handle;
  438.     begin
  439.         getditem(d, itemnum, itype, ignore, r);
  440.         textfont(fontrqst);
  441.         textsize(sizerqst);
  442.         textbox(pointer(ord(@s) + 1), length(s), r, TEJustRight);
  443.     end;
  444.  
  445.  
  446.     procedure SysResume;
  447.     begin
  448.         FlushEvents(EveryEvent, 0);
  449.         ExitToShell;
  450.     end;
  451.  
  452.  
  453.     procedure beep;
  454.     begin
  455.         SysBeep(1)
  456.     end;
  457.  
  458.  
  459.     procedure PutMessage;{(str:str255)}
  460.         var
  461.             ignore: integer;
  462.     begin
  463.         InitCursor;
  464.         ParamText(str, '', '', '');
  465.         Ignore := Alert(300, nil);
  466.     end;
  467.  
  468.     function GetFontSize;{(item:integer):integer}
  469.         var
  470.             TempSize: integer;
  471.             Canceled: boolean;
  472.     begin
  473.         case item of
  474.             1: 
  475.                 GetFontSize := 9;
  476.             2: 
  477.                 GetFontSize := 10;
  478.             3: 
  479.                 GetFontSize := 12;
  480.             4: 
  481.                 GetFontSize := 14;
  482.             5: 
  483.                 GetFontSize := 18;
  484.             6: 
  485.                 GetFontSize := 24;
  486.             7: 
  487.                 GetFontSize := 36;
  488.             8: 
  489.                 GetFontSize := 48;
  490.             9: 
  491.                 GetFontSize := 56;
  492.             10: 
  493.                 GetFontSize := 72;
  494.             12:  begin
  495.                     TempSize := GetInt('Font Size:', CurrentSize, Canceled);
  496.                     if TempSize < 1 then
  497.                         TempSize := 1;
  498.                     if TempSize > 1000 then
  499.                         TempSize := 1000;
  500.                     if not canceled then
  501.                         GetFontSize := TempSize
  502.                     else
  503.                         GetFontSize := CurrentSize;
  504.                 end;
  505.         end;
  506.     end;
  507.  
  508.  
  509.     procedure SetMenuItem; {(menuh:menuhandle; itemnum:integer; on:boolean)}
  510. {Enable or disable menuh's itemnum. }
  511.     begin
  512.         if on then
  513.             EnableItem(menuh, itemnum)
  514.         else
  515.             DisableItem(menuh, itemnum);
  516.         if ItemNum = 0 then
  517.             DrawMenuBar;
  518.     end;
  519.  
  520.  
  521.     procedure CheckOnOffItem;{(MenuH:MenuHandle; item,fst,lst:Integer)}
  522.         var
  523.             i: integer;
  524.     begin
  525.         for i := fst to lst do
  526.             if i = item then
  527.                 CheckItem(MenuH, i, true)
  528.             else
  529.                 CheckItem(MenuH, i, false);
  530.     end;
  531.  
  532.  
  533.     procedure UpdateTextItems;
  534.         var
  535.             size, i, MenuItem, FontID, item: integer;
  536.             FontName: str255;
  537.             FontFound, FoundIt: boolean;
  538.             str: str255;
  539.     begin
  540.         FontFound := false;
  541.         for item := 1 to NumFontItems do begin
  542.                 GetItem(FontMenuH, Item, FontName);
  543.                 GetFNum(FontName, FontID);
  544.                 if FontID = CurrentFontID then begin
  545.                         FontFound := true;
  546.                         CheckItem(FontMenuH, Item, True)
  547.                     end
  548.                 else
  549.                     CheckItem(FontMenuH, Item, false);
  550.             end;
  551.         if not FontFound then begin
  552.                 FoundIt := False;
  553.                 Item := 1;
  554.                 repeat
  555.                     GetItem(FontMenuH, Item, FontName);
  556.                     GetFNum(FontName, FontID);
  557.                     if FontID = Geneva then begin
  558.                             CheckItem(FontMenuH, Item, True);
  559.                             CurrentFontID := FontID;
  560.                             FoundIt := true;
  561.                         end;
  562.                     Item := Item + 1;
  563.                 until (Item > NumFontItems) or FoundIt;
  564.             end;
  565.  
  566.         for i := 1 to 10 do begin
  567.                 size := GetFontSize(i);
  568.                 if RealFont(CurrentFontID, size) then
  569.                     SetItemStyle(SizeMenuH, i, [outline])
  570.                 else
  571.                     SetItemStyle(SizeMenuH, i, [])
  572.             end;
  573.         NumToString(CurrentSize, str);
  574.         str := concat('Other[', str, ']╔');
  575.         SetItem(SizeMenuH, 12, str);
  576.  
  577.         for i := TxPlain to TxShadow do
  578.             CheckItem(StyleMenuH, i, false);
  579.         if CurrentStyle = [] then
  580.             CheckItem(StyleMenuH, TxPlain, true)
  581.         else begin
  582.                 if Bold in CurrentStyle then
  583.                     CheckItem(StyleMenuH, TxBold, true);
  584.                 if Italic in CurrentStyle then
  585.                     CheckItem(StyleMenuH, TxItalic, true);
  586.                 if Underline in CurrentStyle then
  587.                     CheckItem(StyleMenuH, TxUnderline, true);
  588.                 if Outline in CurrentStyle then
  589.                     CheckItem(StyleMenuH, TxOutline, true);
  590.                 if Shadow in CurrentStyle then
  591.                     CheckItem(StyleMenuH, Txshadow, true);
  592.             end;
  593.  
  594.         case CurrentSize of
  595.             9: 
  596.                 MenuItem := 1;
  597.             10: 
  598.                 MenuItem := 2;
  599.             12: 
  600.                 MenuItem := 3;
  601.             14: 
  602.                 MenuItem := 4;
  603.             18: 
  604.                 MenuItem := 5;
  605.             24: 
  606.                 MenuItem := 6;
  607.             36: 
  608.                 MenuItem := 7;
  609.             48: 
  610.                 MenuItem := 8;
  611.             56: 
  612.                 MenuItem := 9;
  613.             72: 
  614.                 MenuItem := 10;
  615.             otherwise
  616.                 MenuItem := 12;
  617.         end;
  618.         CheckOnOffItem(SizeMenuH, MenuItem, 1, 12);
  619.  
  620.         case TextJust of
  621.             teJustLeft: 
  622.                 MenuItem := LeftItem;
  623.             teJustCenter: 
  624.                 MenuItem := CenterItem;
  625.             teJustRight: 
  626.                 MenuItem := RightItem;
  627.         end;
  628.         CheckOnOffItem(StyleMenuH, MenuItem, LeftItem, RightItem);
  629.  
  630.         if TextBack = NoBack then
  631.             MenuItem := NoBackgroundItem
  632.         else
  633.             MenuItem := WithBackgroundItem;
  634.         CheckOnOffItem(StyleMenuH, MenuItem, NoBackgroundItem, WithBackgroundItem);
  635.     end;
  636.  
  637.  
  638. {$POP}
  639.  
  640.     procedure LoadLUT (table: MyCSpecArray);
  641.         var
  642.             i, entry, screen: integer;
  643.             cPtr: ^cSpecArray;
  644.             SaveDevice: GDHandle;
  645.     begin
  646.         if nExtraColors > 0 then begin
  647.                 entry := FirstExtraColorsEntry;
  648.                 for i := 1 to nExtraColors do begin
  649.                         table[entry].rgb := ExtraColors[i];
  650.                         entry := entry + 1;
  651.                     end;
  652.             end;
  653.         for i := 1 to 254 do {Work around needed for 32-bit QuickDraw}
  654.             with table[i].rgb do
  655.                 if (red = 0) and (green = 0) and (blue = 0) then begin
  656.                         red := 256;
  657.                         green := 256;
  658.                         blue := 256;
  659.                     end;
  660.         cPtr := @table[1];
  661.         SaveDevice := GetGDevice;
  662.         for screen := 1 to nMonitors do begin
  663.                 SetGDevice(Monitors[screen]);
  664.                 for i := 1 to 254 do begin
  665.                         ProtectEntry(i, false);
  666.                         ReserveEntry(i, false);
  667.                     end;
  668.                 SetEntries(1, 253, cPtr^);
  669.             end;
  670.         SetGDevice(SaveDevice);
  671.     end;
  672.  
  673.  
  674.     procedure SetupLutUndo;
  675.     begin
  676.         with info^ do begin
  677.                 UndoInfo^.RedLut := RedLut;
  678.                 UndoInfo^.GreenLut := GreenLut;
  679.                 UndoInfo^.BlueLut := BlueLut;
  680.                 UndoInfo^.nColors := nColors;
  681.                 UndoInfo^.ColorStart := ColorStart;
  682.                 UndoInfo^.ColorEnd := ColorEnd;
  683.                 UndoInfo^.FillColor1 := FillColor1;
  684.                 UndoInfo^.FillColor2 := FillColor2;
  685.                 UndoInfo^.LutMode := LutMode;
  686.                 UndoInfo^.ColorTable := ColorTable;
  687.                 UndoInfo^.IdentityFunction := IdentityFunction;
  688.                 UndoInfo^.cTable := cTable;
  689.                 WhatToUndo := UndoLUT;
  690.             end;
  691.     end;
  692.  
  693.  
  694.     procedure UndoLutChange;
  695.     begin
  696.         with info^ do begin
  697.                 RedLut := UndoInfo^.RedLut;
  698.                 GreenLut := UndoInfo^.GreenLut;
  699.                 BlueLut := UndoInfo^.BlueLut;
  700.                 nColors := UndoInfo^.nColors;
  701.                 ColorStart := UndoInfo^.ColorStart;
  702.                 ColorEnd := UndoInfo^.ColorEnd;
  703.                 FillColor1 := UndoInfo^.FillColor1;
  704.                 FillColor2 := UndoInfo^.FillColor2;
  705.                 LutMode := UndoInfo^.LutMode;
  706.                 LutMode := UndoInfo^.LutMode;
  707.                 ColorTable := UndoInfo^.ColorTable;
  708.                 cTable := UndoInfo^.cTable;
  709.                 LoadLut(cTable);
  710.                 Thresholding := false;
  711.                 WhatToUndo := NothingToUndo;
  712.             end;
  713.     end;
  714.  
  715.  
  716.     procedure DisableDensitySlice;
  717.     begin
  718.         if DensitySlicing then begin
  719.                 DensitySlicing := false;
  720.                 UndoLutChange;
  721.             end;
  722.         Thresholding := false;
  723.     end;
  724.  
  725.  
  726.     procedure LoadInputLookupTable;{(address:ptr)}
  727.         type
  728.             ilutType = packed array[0..1023] of byte;
  729.             ilutPtr = ^ilutType;
  730.         var
  731.             ilut: ilutPtr;
  732.             i: integer;
  733.     begin
  734.         ilut := ilutPtr(address);
  735.         if InvertVideo then begin
  736.                 for i := 0 to 255 do
  737.                     ilut^[i * 4] := i;
  738.                 ilut^[0] := 1;
  739.                 ilut^[255 * 4] := 254
  740.             end
  741.         else begin
  742.                 for i := 0 to 255 do
  743.                     ilut^[i * 4] := 255 - i;
  744.                 ilut^[0] := 254;
  745.                 ilut^[255 * 4] := 1
  746.             end;
  747.     end;
  748.  
  749.  
  750.     procedure ResetQuickCapture;
  751.         const
  752.             ilutOffset = $90000;
  753.     begin
  754.         ControlReg^ := 1; {reset}
  755.         while ControlReg^ < 0 do
  756.             ;
  757.         ChannelReg^ := VideoChannel * 64;
  758.         while ControlReg^ < 0 do
  759.             ;
  760.         LoadInputLookupTable(Ptr(DTSlotBase + ilutOffset));
  761.     end;
  762.  
  763.  
  764.     procedure wait;{(ticks:LongInt)}
  765.         var
  766.             SaveTicks: LongInt;
  767.     begin
  768.         SaveTicks := TickCount + ticks;
  769.         repeat
  770.         until TickCount > SaveTicks;
  771.     end;
  772.  
  773.  
  774.     function GetScrapCount;{:integer}
  775.         var
  776.             ScrapInfo: PScrapStuff;
  777.     begin
  778.         ScrapInfo := InfoScrap;
  779.         GetScrapCount := ScrapInfo^.ScrapCount;
  780.     end;
  781.  
  782.  
  783.     procedure DisplayText (update: boolean);
  784.         var
  785.             tPort: GrafPtr;
  786.             i, hstart, width, ff: integer;
  787.             MaskRect: rect;
  788.             p1, p2: point;
  789.     begin
  790.         if (info = NoInfo) or (not IsInsertionPoint) then
  791.             exit(DisplayText);
  792.         if update then
  793.             Undo;
  794.         GetPort(tPort);
  795.         SetPort(GrafPtr(Info^.osPort));
  796.         TextFont(CurrentFontID);
  797.         TextFace(CurrentStyle);
  798.         TextSize(CurrentSize);
  799.         if TextBack = NoBack then
  800.             TextMode(SrcOr)
  801.         else
  802.             TextMode(SrcCopy);
  803.         width := StringWidth(TextStr);
  804.         case TextJust of
  805.             teJustLeft: 
  806.                 hstart := TextStart.h;
  807.             teJustCenter: 
  808.                 hstart := TextStart.h - width div 2;
  809.             teJustRight: 
  810.                 hstart := TextStart.h - width;
  811.         end;
  812.         if hstart < 0 then
  813.             hstart := 0;
  814.         MoveTo(hstart, TextStart.v);
  815.         DrawString(TextStr);
  816.         GetPen(InsertionPoint);
  817.         ff := CurrentSize * 2;
  818.         p1.h := hstart - ff;
  819.         p1.v := TextStart.v - CurrentSize;
  820.         p2.h := TextStart.h + width + ff;
  821.         p2.v := TextStart.v + CurrentSize div 3;
  822.         Pt2Rect(p1, p2, MaskRect);
  823.         UpdateScreen(MaskRect);
  824.         SetPort(tPort);
  825.         Info^.changes := true;
  826.     end;
  827.  
  828.  
  829.     procedure OffScreenToScreenRect;{(VAR r:rect)}
  830.         var
  831.             p1, p2: point;
  832.     begin
  833.         with r do begin
  834.                 p1.h := left;
  835.                 p1.v := top;
  836.                 p2.h := right;
  837.                 p2.v := bottom;
  838.                 OffScreenToScreen(p1);
  839.                 OffScreenToScreen(p2);
  840.                 Pt2Rect(p1, p2, r);
  841.             end;
  842.     end;
  843.  
  844.  
  845.     procedure ScreenToOffscreen;{(VAR loc:point)}
  846.     begin
  847.         with loc, Info^ do begin
  848.                 h := SrcRect.left + trunc(h / magnification);
  849.                 v := SrcRect.top + trunc(v / magnification);
  850.             end;
  851.     end;
  852.  
  853.  
  854.     procedure OffscreenToScreen;{(VAR loc:point)}
  855.     begin
  856.         with loc, Info^ do begin
  857.                 h := trunc((h - SrcRect.left) * magnification);
  858.                 v := trunc((v - SrcRect.top) * magnification);
  859.             end;
  860.     end;
  861.  
  862.  
  863.     procedure UpdateScreen;{(MaskRect:rect)}
  864. {Refreshes the portion of the screen defined by}
  865. {MaskRect, where MaskRect is defined in offscreen coordinates.}
  866.         var
  867.             tPort: GrafPtr;
  868.             imag: integer;
  869.     begin
  870.         OffScreenToScreenRect(MaskRect);
  871.         with Info^ do
  872.             if info <> NoInfo then begin
  873.                     getPort(tPort);
  874.                     SetPort(wptr);
  875.                     pmForeColor(BlackIndex);
  876.                     pmBackColor(WhiteIndex);
  877.                     imag := trunc(magnification);
  878.                     InsetRect(MaskRect, -imag * 2 * LineWidth, -imag * 2 * LineWidth);
  879.                     InsetRect(MaskRect, 0, 0);
  880.                     RectRgn(MaskRgn, MaskRect);
  881.                     hlock(handle(osPort^.portPixMap));
  882.                     hlock(handle(CGrafPort(wptr^).PortPixMap));
  883.                     CopyBits(BitMapHandle(osPort^.PortPixMap)^^, BitMapHandle(CGrafPort(wptr^).PortPixMap)^^, SrcRect, wrect, SrcCopy, MaskRgn);
  884.                     hunlock(handle(osPort^.portPixMap));
  885.                     hunlock(handle(CGrafPort(wptr^).PortPixMap));
  886.                     SetPort(tPort);
  887.                 end;
  888.     end;
  889.  
  890.  
  891.     procedure RestoreRoi;
  892.     begin
  893.         with Info^ do begin
  894.                 SetupUndo;
  895.                 if RoiShowing then
  896.                     UpdateScreen(RoiRect);
  897.                 roiType := NoInfo^.roiType;
  898.                 RoiRect := NoInfo^.RoiRect;
  899.                 CopyRgn(NoInfo^.roiRgn, roiRgn);
  900.                 uLength := NoInfo^.uLength;
  901.                 cLength := NoInfo^.cLength;
  902.                 LX1 := NoInfo^.LX1;
  903.                 LY1 := NoInfo^.LY1;
  904.                 LX2 := NoInfo^.LX2;
  905.                 LY2 := NoInfo^.LY2;
  906.                 RoiShowing := true;
  907.                 measuring := false;
  908.                 nCoordinates := 0;
  909.             end;
  910.     end;
  911.  
  912.  
  913.     procedure Undo;
  914.         var
  915.             SrcPtr: ptr;
  916.             line: integer;
  917.     begin
  918.         if info^.PixMapSize <> CurrentUndoSize then
  919.             exit(Undo);
  920.         if UndoFromClip then begin
  921.                 if info^.PixMapSize > ClipBufSize then
  922.                     exit(Undo);
  923.                 SrcPtr := ClipBuf;
  924.             end
  925.         else
  926.             SrcPtr := UndoBuf;
  927.         with info^ do
  928.             BlockMove(SrcPtr, PicBaseAddr, PixMapSize);
  929.         if UndoFromClip and RestoreUndoBuf then
  930.             with info^ do
  931.                 BlockMove(SrcPtr, UndoBuf, PixMapSize);
  932.         if RedoSelection then
  933.             RestoreRoi;
  934.     end;
  935.  
  936.  
  937.     function MyGetPixel;{(h,v:integer):integer}
  938.         var
  939.             offset: LongInt;
  940.             p: ptr;
  941.     begin
  942.         with Info^ do begin
  943.                 if (h < 0) or (v < 0) or (h >= PixelsPerLine) or (v >= nlines) then begin
  944.                         MyGetPixel := BackgroundIndex;
  945.                         exit(MyGetPixel);
  946.                     end;
  947.                 offset := LongInt(v) * BytesPerRow + h;
  948.                 if offset >= PixMapSize then
  949.                     exit(MyGetPixel);
  950.                 p := ptr(ord4(PicBaseAddr) + offset);
  951.                 MyGetPixel := BAND(p^, 255);
  952.             end;
  953.     end;
  954.  
  955.  
  956.     procedure PutPixel;{(h,v,value:integer)}
  957.         type
  958.             uptr = ^UnsignedByte;
  959.         var
  960.             offset: LongInt;
  961.             p: ptr;
  962.     begin
  963.         with Info^ do begin
  964.                 if (h < 0) or (v < 0) or (h >= PixelsPerLine) or (v >= nlines) then
  965.                     exit(PutPixel);
  966.                 offset := LongInt(v) * BytesPerRow + h;
  967.                 p := ptr(ord4(PicBaseAddr) + offset);
  968.                 p^ := BAND(value, 255);
  969.             end;
  970.     end;
  971.  
  972.  
  973.     procedure GetLine (h, v, count: integer; var line: LineType);
  974.         var
  975.             offset: LongInt;
  976.             p: ptr;
  977.     begin
  978.         with Info^ do begin
  979.                 if (h < 0) or (v < 0) or ((h + count) > PixelsPerLine) or (v >= nlines) then begin
  980.                         line := BlankLine^;
  981.                         exit(GetLine);
  982.                     end;
  983.                 offset := LongInt(v) * BytesPerRow + h;
  984.                 p := ptr(ord4(PicBaseAddr) + offset);
  985.                 BlockMove(p, @line, count);
  986.             end;
  987.     end;
  988.  
  989.  
  990.     procedure GetColumn (hstart, vstart, count: integer; var data: LineType);
  991.         var
  992.             i, v: integer;
  993.     begin
  994.         if count > MaxLine then
  995.             count := MaxLine;
  996.         v := vstart;
  997.         for i := 0 to count - 1 do begin
  998.                 data[i] := MyGetPixel(hstart, v);
  999.                 v := v + 1;
  1000.             end;
  1001.     end;
  1002.  
  1003.  
  1004.     procedure PutColumn (hstart, vstart, count: integer; var data: LineType);
  1005.         var
  1006.             i, v: integer;
  1007.     begin
  1008.         if count > MaxLine then
  1009.             count := MaxLine;
  1010.         v := vstart;
  1011.         for i := 0 to count - 1 do begin
  1012.                 PutPixel(hstart, v, data[i]);
  1013.                 v := v + 1;
  1014.             end;
  1015.     end;
  1016.  
  1017.  
  1018.     procedure PutLine (h, v, count: integer; var line: LineType);
  1019.         var
  1020.             offset: LongInt;
  1021.             p: ptr;
  1022.     begin
  1023.         with Info^ do begin
  1024.                 if (h < 0) or (v < 0) or (v >= nlines) then
  1025.                     exit(PutLine);
  1026.                 if (h + count) > PixelsPerLine then
  1027.                     count := PixelsPerLine - h;
  1028.                 offset := LongInt(v) * BytesPerRow + h;
  1029.                 p := ptr(ord4(PicBaseAddr) + offset);
  1030.                 BlocKMove(@line, p, count);
  1031.             end;
  1032.     end;
  1033.  
  1034.  
  1035.     procedure Show1Value (rvalue, CalibratedValue: extended);
  1036.         var
  1037.             tPort: GrafPtr;
  1038.             hstart, vstart, ivalue: integer;
  1039.     begin
  1040.         hstart := ValuesHStart;
  1041.         vstart := ValuesVStart;
  1042.         GetPort(tPort);
  1043.         SetPort(ValuesWindow);
  1044.         TextSize(9);
  1045.         TextFont(Monaco);
  1046.         TextMode(SrcCopy);
  1047.         MoveTo(xValueLoc, vstart);
  1048.         if CalibratedValue <> NoValue then begin
  1049.                 DrawReal(CalibratedValue, 5, 2);
  1050.                 DrawString(' (');
  1051.                 DrawReal(rvalue, 3, 0);
  1052.                 DrawString(')');
  1053.             end
  1054.         else
  1055.             DrawReal(rvalue, 6, 2);
  1056.         DrawString('    ');
  1057.         SetPort(tPort);
  1058.     end;
  1059.  
  1060.  
  1061.     procedure Show2CalibratedValues; {(x, y: LongInt; ShowUncalibrated: boolean)}
  1062.         var
  1063.             tPort: GrafPtr;
  1064.             hstart, vstart, ivalue: integer;
  1065.     begin
  1066.         hstart := ValuesHStart;
  1067.         vstart := ValuesVStart;
  1068.         GetPort(tPort);
  1069.         SetPort(ValuesWindow);
  1070.         TextSize(9);
  1071.         TextFont(Monaco);
  1072.         TextMode(SrcCopy);
  1073.         MoveTo(xValueLoc, vstart);
  1074.         DrawLong(x);
  1075.         DrawString('     ');
  1076.         MoveTo(yValueLoc, vstart + 10);
  1077.         if info^.DensityCalibrated then begin
  1078.                 DrawReal(cvalue[y], 5, 2);
  1079.                 if ShowUncalibrated then begin
  1080.                         DrawString(' (');
  1081.                         DrawLong(y);
  1082.                         DrawString(')');
  1083.                     end;
  1084.             end
  1085.         else
  1086.             DrawLong(y);
  1087.         DrawString('     ');
  1088.         SetPort(tPort);
  1089.     end;
  1090.  
  1091.  
  1092.     procedure Show2Values (current, total: LongInt);
  1093.         var
  1094.             tPort: GrafPtr;
  1095.             hstart, vstart, ivalue: integer;
  1096.     begin
  1097.         hstart := ValuesHStart;
  1098.         vstart := ValuesVStart;
  1099.         GetPort(tPort);
  1100.         SetPort(ValuesWindow);
  1101.         TextSize(9);
  1102.         TextFont(Monaco);
  1103.         TextMode(SrcCopy);
  1104.         MoveTo(xValueLoc, vstart);
  1105.         DrawLong(current);
  1106.         DrawString('     ');
  1107.         MoveTo(yValueLoc, vstart + 10);
  1108.         DrawLong(total);
  1109.         DrawString('     ');
  1110.         SetPort(tPort);
  1111.     end;
  1112.  
  1113.  
  1114.     procedure DrawXDimension (x: real; digits: integer);
  1115.     begin
  1116.         with info^ do begin
  1117.                 if SpatiallyCalibrated then begin
  1118.                         DrawReal(x / xSpatialScale, 5, 2);
  1119.                         DrawString(units);
  1120.                         DrawString(' (');
  1121.                         DrawReal(x, 3, digits);
  1122.                         DrawString(')')
  1123.                     end
  1124.                 else
  1125.                     DrawReal(x, 1, digits);
  1126.                 DrawString('      ');
  1127.             end;
  1128.     end;
  1129.  
  1130.  
  1131.     procedure DrawYDimension (y: real; digits: integer);
  1132.     begin
  1133.         with info^ do begin
  1134.                 if SpatiallyCalibrated then begin
  1135.                         DrawReal(y / ySpatialScale, 5, 2);
  1136.                         DrawString(units);
  1137.                         DrawString(' (');
  1138.                         DrawReal(y, 3, digits);
  1139.                         DrawString(')')
  1140.                     end
  1141.                 else
  1142.                     DrawReal(y, 1, digits);
  1143.                 DrawString('      ');
  1144.             end;
  1145.     end;
  1146.  
  1147.  
  1148.     procedure DrawRGB (index: integer);
  1149.         var
  1150.             rStr, gStr, bStr: str255;
  1151.             TempRGB: rgbColor;
  1152.             i, entry: integer;
  1153.  
  1154.         procedure Convert (n: integer; var str: str255);
  1155.             var
  1156.                 i: integer;
  1157.         begin
  1158.             RealToString(n, 3, 0, str);
  1159.             for i := 1 to 3 do
  1160.                 if str[i] = ' ' then
  1161.                     str[i] := '0';
  1162.         end;
  1163.  
  1164.     begin
  1165.         TempRGB := cScreenPort^.portPixMap^^.pmTable^^.ctTable[index].rgb;
  1166.         with TempRGB do begin
  1167.                 Convert(band(bsr(red, 8), 255), rStr);
  1168.                 Convert(band(bsr(green, 8), 255), gStr);
  1169.                 Convert(band(bsr(blue, 8), 255), bStr);
  1170.                 DrawString(concat(rStr, ' ', gStr, ' ', bStr));
  1171.             end;
  1172.     end;
  1173.  
  1174.  
  1175.     procedure Show3Values;{(hloc,vloc,ivalue:LongInt)}
  1176.         var
  1177.             tPort: GrafPtr;
  1178.             hstart, vstart: integer;
  1179.     begin
  1180.         with info^ do begin
  1181.                 hstart := ValuesHStart;
  1182.                 vstart := ValuesVStart;
  1183.                 GetPort(tPort);
  1184.                 SetPort(ValuesWindow);
  1185.                 TextSize(9);
  1186.                 TextFont(Monaco);
  1187.                 TextMode(SrcCopy);
  1188.                 if hloc < 0 then
  1189.                     hloc := -hloc;
  1190.                 MoveTo(xValueLoc, vstart);
  1191.                 DrawXDimension(hloc, 0);
  1192.                 if InvertYCoordinates and (ivalue >= 0) then
  1193.                     vloc := PicRect.bottom - vloc - 1;
  1194.                 if vloc < 0 then
  1195.                     vloc := -vloc;
  1196.                 MoveTo(yValueLoc, vstart + 10);
  1197.                 DrawYDimension(vloc, 0);
  1198.                 DrawString('    ');
  1199.                 if ivalue >= 0 then begin
  1200.                         MoveTo(zValueLoc, vstart + 20);
  1201.                         if DensityCalibrated or (CurrentTool = PickerTool) then begin
  1202.                                 if CurrentTool = PickerTool then
  1203.                                     DrawRGB(ivalue)
  1204.                                 else
  1205.                                     DrawReal(cvalue[ivalue], 5, precision);
  1206.                                 DrawString(' (');
  1207.                                 DrawLong(ivalue);
  1208.                                 DrawString(')');
  1209.                             end
  1210.                         else
  1211.                             DrawLong(ivalue);
  1212.                     end;
  1213.                 DrawString('    ');
  1214.                 SetPort(tPort);
  1215.             end;
  1216.     end;
  1217.  
  1218.  
  1219.     procedure ShowDxDy (X, Y: real);
  1220.         var
  1221.             tPort: GrafPtr;
  1222.             hstart, vstart, ivalue: integer;
  1223.     begin
  1224.         with info^ do begin
  1225.                 hstart := ValuesHStart;
  1226.                 vstart := ValuesVStart;
  1227.                 GetPort(tPort);
  1228.                 SetPort(ValuesWindow);
  1229.                 TextSize(9);
  1230.                 TextFont(Monaco);
  1231.                 TextMode(SrcCopy);
  1232.                 MoveTo(xValueLoc, vstart);
  1233.                 DrawXDimension(x, 2);
  1234.                 MoveTo(yValueLoc, vstart + 10);
  1235.                 DrawYDimension(y, 2);
  1236.                 MoveTo(zValueLoc, vstart + 20);
  1237.                 if SpatiallyCalibrated then begin
  1238.                         DrawReal(sqrt(sqr(x / xSpatialScale) + sqr(y / ySpatialScale)), 5, 2);
  1239.                         DrawString(units);
  1240.                         DrawString(' (');
  1241.                         DrawReal(sqrt(sqr(x) + sqr(y)), 1, 2);
  1242.                         DrawString(')')
  1243.                     end
  1244.                 else
  1245.                     DrawReal(sqrt(sqr(x) + sqr(y)), 1, 2);
  1246.                 DrawString('    ');
  1247.                 SetPort(tPort);
  1248.             end;
  1249.     end;
  1250.  
  1251.  
  1252.     procedure PutChar;{(c:char)}
  1253.     begin
  1254.         if TextBufSize < MaxTextBufSize then begin
  1255.                 TextBufSize := TextBufSize + 1;
  1256.                 TextBufP^[TextBufSize] := c;
  1257.                 if c = cr then begin
  1258.                         TextBufColumn := 0;
  1259.                         TextBufLineCount := TextBufLineCount + 1
  1260.                     end
  1261.                 else
  1262.                     TextBufColumn := TextBufColumn + 1;
  1263.             end;
  1264.     end;
  1265.  
  1266.  
  1267.     procedure PutTab;
  1268.     begin
  1269.         if not printing then
  1270.             PutChar(tab)
  1271.     end;
  1272.  
  1273.  
  1274.     procedure PutString (str: str255);
  1275.         var
  1276.             i: integer;
  1277.     begin
  1278.         for i := 1 to length(str) do begin
  1279.                 if TextBufSize < MaxTextBufSize then
  1280.                     TextBufSize := TextBufSize + 1;
  1281.                 TextBufP^[TextBufSize] := str[i];
  1282.                 TextBufColumn := TextBufColumn + 1;
  1283.             end;
  1284.     end;
  1285.  
  1286.  
  1287.     procedure PutFString (str: str255; FieldWidth: integer);
  1288.         var
  1289.             LeadingSpaces: integer;
  1290.     begin
  1291.         LeadingSpaces := FieldWidth - length(str);
  1292.         if LeadingSpaces > 0 then
  1293.             str := concat(copy('            ', 1, LeadingSpaces), str);
  1294.         PutString(str);
  1295.     end;
  1296.  
  1297.  
  1298.     procedure PutReal;{(n:extended; width,fwidth:integer)}
  1299.         var
  1300.             str: str255;
  1301.     begin
  1302.         RealToString(n, width, fwidth, str);
  1303.         PutString(str);
  1304.     end;
  1305.  
  1306.  
  1307.     procedure PutLong (n: LongInt; FieldWidth: integer);
  1308.         var
  1309.             str: str255;
  1310.             LeadingSpaces: integer;
  1311.     begin
  1312.         NumToString(n, str);
  1313.         LeadingSpaces := FieldWidth - length(str);
  1314.         if LeadingSpaces > 0 then
  1315.             str := concat(copy('            ', 1, LeadingSpaces), str);
  1316.         PutString(str);
  1317.     end;
  1318.  
  1319.  
  1320.     procedure CopyResultsToBuffer (FirstCount, LastCount: integer; Headings: boolean);
  1321.         var
  1322.             i, column, fwidth: integer;
  1323.             m: MeasurementTypes;
  1324.  
  1325.         procedure PutSequenceNumber;
  1326.         begin
  1327.             PutLong(i, 4);
  1328.             PutChar('.');
  1329.             PutTab;
  1330.         end;
  1331.  
  1332.         procedure PutUnits;
  1333.         begin
  1334.             if info^.SpatiallyCalibrated then begin
  1335.                     PutString('  (');
  1336.                     PutString(info^.Units);
  1337.                     PutString(')')
  1338.                 end
  1339.             else
  1340.                 PutString('(Pixels)');
  1341.             PutChar(cr);
  1342.             PutChar(cr);
  1343.         end;
  1344.  
  1345.         procedure PutTabDelimeter;
  1346.         begin
  1347.             Column := Column + 1;
  1348.             if Column <> nListColumns then
  1349.                 PutTab;
  1350.         end;
  1351.  
  1352.     begin
  1353.         if mCount < 1 then begin
  1354.                 TextBufSize := 0;
  1355.                 TextBufLineCount := 0;
  1356.                 exit(CopyResultsToBuffer);
  1357.             end;
  1358.         ShowWatch;
  1359.         Headings := Headings or OptionKeyWasDown;
  1360.         TextBufSize := 0;
  1361.         TextBufColumn := 0;
  1362.         TextBufLineCount := 0;
  1363.         nListColumns := 0;
  1364.         for m := AreaM to StdDevM do
  1365.             if m in Measurements then
  1366.                 nListColumns := nListColumns + 1;
  1367.         if (xyLocM in measurements) or (nPoints > 0) then
  1368.             nListColumns := nListColumns + 2;
  1369.         if ModeM in measurements then
  1370.             nListColumns := nListColumns + 1;
  1371.         if (LengthM in measurements) or (nLengths > 0) then
  1372.             nListColumns := nListColumns + 1;
  1373.         if MajorAxisM in measurements then
  1374.             nListColumns := nListColumns + 1;
  1375.         if MinorAxisM in measurements then
  1376.             nListColumns := nListColumns + 1;
  1377.         if (AngleM in measurements) or (nAngles > 0) then
  1378.             nListColumns := nListColumns + 1;
  1379.         if IntDenM in measurements then
  1380.             nListColumns := nListColumns + 2;
  1381.         if MinMaxM in measurements then
  1382.             nListColumns := nListColumns + 2;
  1383.         if User1M in measurements then
  1384.             nListColumns := nListColumns + 1;
  1385.         if User2M in measurements then
  1386.             nListColumns := nListColumns + 1;
  1387.         with info^ do begin
  1388.                 fwidth := FieldWidth;
  1389.                 if Headings and (FirstCount = 1) then begin
  1390.                         PutFString(' ', 5);
  1391.                         PutTabDelimeter;
  1392.                         if AreaM in measurements then begin
  1393.                                 PutFString('Area', fwidth);
  1394.                                 PutTabDelimeter;
  1395.                             end;
  1396.                         if MeanM in measurements then begin
  1397.                                 PutFString('Mean', fwidth);
  1398.                                 PutTabDelimeter;
  1399.                             end;
  1400.                         if StdDevM in measurements then begin
  1401.                                 PutFString('S.D.', fwidth);
  1402.                                 PutTabDelimeter;
  1403.                             end;
  1404.                         if (xyLocM in measurements) or (nPoints > 0) then begin
  1405.                                 PutFString('X', fwidth);
  1406.                                 PutTabDelimeter;
  1407.                                 PutFString('Y', fwidth);
  1408.                                 PutTabDelimeter;
  1409.                             end;
  1410.                         if ModeM in measurements then begin
  1411.                                 PutFString('Mode', fwidth);
  1412.                                 PutTabDelimeter;
  1413.                             end;
  1414.                         if (LengthM in measurements) or (nLengths > 0) then begin
  1415.                                 PutFString('Length', fwidth);
  1416.                                 PutTabDelimeter;
  1417.                             end;
  1418.                         if MajorAxisM in measurements then begin
  1419.                                 PutFString(MajorLabel, fwidth);
  1420.                                 PutTabDelimeter;
  1421.                             end;
  1422.                         if MinorAxisM in measurements then begin
  1423.                                 PutFString(MinorLabel, fwidth);
  1424.                                 PutTabDelimeter;
  1425.                             end;
  1426.                         if (AngleM in measurements) or (nAngles > 0) then begin
  1427.                                 PutFString('Angle', fwidth);
  1428.                                 PutTabDelimeter;
  1429.                             end;
  1430.                         if IntDenM in measurements then begin
  1431.                                 PutFString('Int.Den.', fwidth + 2);
  1432.                                 PutTabDelimeter;
  1433.                                 PutFString('Back.', fwidth);
  1434.                                 PutTabDelimeter;
  1435.                             end;
  1436.                         if MinMaxM in measurements then begin
  1437.                                 PutFString('Min', fwidth);
  1438.                                 PutTabDelimeter;
  1439.                                 PutFString('Max', fwidth);
  1440.                                 PutTabDelimeter;
  1441.                             end;
  1442.                         if User1M in measurements then begin
  1443.                                 PutFString(User1Label, fwidth);
  1444.                                 PutTabDelimeter;
  1445.                             end;
  1446.                         if User2M in measurements then begin
  1447.                                 PutFString(User2Label, fwidth);
  1448.                                 PutTabDelimeter;
  1449.                             end;
  1450.                         PutChar(cr);
  1451.                         PutChar(cr);
  1452.                     end;
  1453.                 for i := FirstCount to LastCount do begin
  1454.                         column := 0;
  1455.                         if Headings then
  1456.                             PutSequenceNumber;
  1457.                         if AreaM in measurements then begin
  1458.                                 PutReal(mArea^[i], fwidth, precision);
  1459.                                 PutTabDelimeter;
  1460.                             end;
  1461.                         if MeanM in measurements then begin
  1462.                                 PutReal(mean^[i], fwidth, precision);
  1463.                                 PutTabDelimeter;
  1464.                             end;
  1465.                         if StdDevM in measurements then begin
  1466.                                 PutReal(sd^[i], fwidth, precision);
  1467.                                 PutTabDelimeter;
  1468.                             end;
  1469.                         if (xyLocM in measurements) or (nPoints > 0) then begin
  1470.                                 PutReal(xcenter^[i], fwidth, precision);
  1471.                                 PutTab;
  1472.                                 PutReal(ycenter^[i], fwidth, precision);
  1473.                                 PutTabDelimeter;
  1474.                             end;
  1475.                         if ModeM in measurements then begin
  1476.                                 PutReal(mode^[i], fwidth, precision);
  1477.                                 PutTabDelimeter;
  1478.                             end;
  1479.                         if (LengthM in measurements) or (nLengths > 0) then begin
  1480.                                 PutReal(plength^[i], fwidth, precision);
  1481.                                 PutTabDelimeter;
  1482.                             end;
  1483.                         if MajorAxisM in measurements then begin
  1484.                                 PutReal(MajorAxis^[i], fwidth, precision);
  1485.                                 PutTabDelimeter;
  1486.                             end;
  1487.                         if MinorAxisM in measurements then begin
  1488.                                 PutReal(MinorAxis^[i], fwidth, precision);
  1489.                                 PutTabDelimeter;
  1490.                             end;
  1491.                         if (AngleM in measurements) or (nAngles > 0) then begin
  1492.                                 PutReal(orientation^[i], fwidth, precision);
  1493.                                 PutTabDelimeter;
  1494.                             end;
  1495.                         if IntDenM in measurements then begin
  1496.                                 PutReal(IntegratedDensity^[i], fwidth + 2, precision);
  1497.                                 PutTabDelimeter;
  1498.                                 PutReal(idBackground^[i], fwidth, precision);
  1499.                                 PutTabDelimeter;
  1500.                             end;
  1501.                         if MinMaxM in measurements then begin
  1502.                                 PutReal(mMin^[i], fwidth, precision);
  1503.                                 PutTabDelimeter;
  1504.                                 PutReal(mMax^[i], fwidth, precision);
  1505.                                 PutTabDelimeter;
  1506.                             end;
  1507.                         if User1M in measurements then begin
  1508.                                 PutReal(User1^[i], fwidth, precision);
  1509.                                 PutTabDelimeter;
  1510.                             end;
  1511.                         if User2M in measurements then begin
  1512.                                 PutReal(User2^[i], fwidth, precision);
  1513.                                 PutTabDelimeter;
  1514.                             end;
  1515.                         PutChar(cr);
  1516.                     end; {for}
  1517.             end; {with}
  1518.     end;
  1519.  
  1520.  
  1521.     procedure ShowWatch;
  1522.     begin
  1523.         SetCursor(watch);
  1524.     end;
  1525.  
  1526.  
  1527.     procedure UpdatePicWindow;
  1528.         var
  1529.             tPort: GrafPtr;
  1530.     begin
  1531.         if info <> NoInfo then
  1532.             with Info^ do begin
  1533.                     getPort(tPort);
  1534.                     SetPort(wptr);
  1535.                     pmForeColor(BlackIndex);
  1536.                     pmBackColor(WhiteIndex);
  1537.                     hlock(handle(osPort^.portPixMap));
  1538.                     hlock(handle(CGrafPort(wptr^).PortPixMap));
  1539.                     CopyBits(BitMapHandle(osPort^.portPixMap)^^, BitMapHandle(CGrafPort(wptr^).PortPixMap)^^, SrcRect, wrect, SrcCopy, nil);
  1540.                     hunlock(handle(osPort^.portPixMap));
  1541.                     hunlock(handle(CGrafPort(wptr^).PortPixMap));
  1542.                     SetPort(tPort);
  1543.                     RoiUpdateTime := 0;
  1544.                 end;
  1545.     end;
  1546.  
  1547.  
  1548.     procedure DoOperation;{(Operation:OpType)}
  1549.         var
  1550.             tPort: GrafPtr;
  1551.             loc: point;
  1552.             width, height, SaveWidth: integer;
  1553.             tRect: rect;
  1554.     begin
  1555.         GetPort(tPort);
  1556.         with Info^ do begin
  1557.                 changes := true;
  1558.                 SetPort(GrafPtr(osPort));
  1559.                 PenNormal;
  1560.                 case Operation of
  1561.                     InvertOp: 
  1562.                         InvertRgn(roiRgn);
  1563.                     PaintOp: 
  1564.                         PaintRgn(roiRgn);
  1565.                     FrameOp:  begin
  1566.                             if (RoiType = LineRoi) or (RoiType = FreeLineRoi) or (RoiTYpe = SegLineRoi) then
  1567.                                 PenSize(1, 1)
  1568.                             else
  1569.                                 PenSize(LineWidth, LineWidth);
  1570.                             FrameRgn(roiRgn);
  1571.                         end;
  1572.                     EraseOp: 
  1573.                         EraseRgn(roiRgn);
  1574.                     PasteOp: 
  1575.                         Paste;
  1576.                     otherwise
  1577.                 end;
  1578.                 if not RoiShowing then
  1579.                     UpdateScreen(RoiRect);
  1580.                 if PixMapSize > UndoBufSize then
  1581.                     OpPending := false;
  1582.             end;
  1583.         SetPort(tPort);
  1584.     end;
  1585.  
  1586.  
  1587.     procedure SaveRoi;
  1588.     begin
  1589.         with info^ do
  1590.             if RoiType <> noRoi then begin
  1591.                     NoInfo^.roiType := roiType;
  1592.                     NoInfo^.RoiRect := RoiRect;
  1593.                     CopyRgn(roiRgn, NoInfo^.roiRgn);
  1594.                     NoInfo^.uLength := uLength;
  1595.                     NoInfo^.cLength := cLength;
  1596.                     NoInfo^.LX1 := LX1;
  1597.                     NoInfo^.LY1 := LY1;
  1598.                     NoInfo^.LX2 := LX2;
  1599.                     NoInfo^.LY2 := LY2;
  1600.                 end;
  1601.     end;
  1602.  
  1603.  
  1604.     procedure KillRoi;
  1605.         var
  1606.             trect: rect;
  1607.     begin
  1608.         with info^ do begin
  1609.                 if RoiShowing then begin
  1610.                         if OpPending then begin
  1611.                                 OpPending := false;
  1612.                                 DoOperation(CurrentOp);
  1613.                             end;
  1614.                         SaveRoi;
  1615.                         RoiShowing := false;
  1616.                         trect := RoiRect;
  1617.                         if RoiType = LineRoi then
  1618.                             InsetRect(trect, -RoiHandleSize, -RoiHandleSize);
  1619.                         UpdateScreen(trect);
  1620.                     end;
  1621.                 RoiType := NoRoi;
  1622.                 RoiUpdateTime := 0;
  1623.             end;
  1624.     end;
  1625.  
  1626.  
  1627.     procedure Paste;
  1628.         var
  1629.             srcPort: cGrafPtr;
  1630.     begin
  1631.         if info = NoInfo then begin
  1632.                 beep;
  1633.                 exit(Paste)
  1634.             end;
  1635.         with Info^ do begin
  1636.                 if not RoiShowing then
  1637.                     exit(Paste);
  1638.                 if PasteTransferMode = SrcCopy then begin
  1639.                         pmForeColor(BlackIndex);
  1640.                         pmBackColor(WhiteIndex);
  1641.                     end;
  1642.                 srcPort := ClipBufInfo^.osPort;
  1643.                 if LivePasteMode then
  1644.                     if (WhatsOnClip = CameraPic) and (QuickCaptureInfo <> nil) and (PictureType <> QuickCaptureType) then begin
  1645.                             ControlReg^ := BitAnd($80, 255); {Start frame capture}
  1646.                             while ControlReg^ < 0 do
  1647.                                 ;       {Wait for it to complete}
  1648.                             srcPort := qcPort;
  1649.                         end;
  1650.                 hlock(handle(srcPort^.portPixMap));
  1651.                 hlock(handle(osPort^.portPixMap));
  1652.                 CopyBits(BitMapHandle(srcPort^.portPixMap)^^, BitMapHandle(osPort^.PortPixMap)^^, ClipBufInfo^.RoiRect, RoiRect, PasteTransferMode, roiRgn);
  1653.                 hunlock(handle(srcPort^.portPixMap));
  1654.                 hunlock(handle(osPort^.PortPixMap));
  1655.                 if PasteTransferMode = SrcCopy then begin
  1656.                         pmForeColor(ForegroundIndex);
  1657.                         pmBackColor(BackgroundIndex);
  1658.                     end;
  1659.             end;
  1660.     end;
  1661.  
  1662.  
  1663.     procedure ShowRoi;
  1664.     begin
  1665.         with info^ do
  1666.             if RoiType <> NoRoi then begin
  1667.                     SetupUndo;
  1668.                     RoiShowing := true;
  1669.                 end;
  1670.     end;
  1671.  
  1672.  
  1673.     procedure SetupUndo;
  1674.         var
  1675.             line: integer;
  1676.     begin
  1677.         WhatToUndo := NothingToUndo;
  1678.         if info = NoInfo then begin
  1679.                 CurrentUndoSize := 0;
  1680.                 exit(SetupUndo)
  1681.             end;
  1682.         with info^ do begin
  1683.                 if PixMapSize > UndoBufSize then begin
  1684.                         CurrentUndoSize := 0;
  1685.                         exit(SetupUndo)
  1686.                     end;
  1687.                 if OpPending then begin
  1688.                         DoOperation(CurrentOp);
  1689.                         OpPending := false;
  1690.                     end;
  1691.                 CurrentUndoSize := PixMapSize;
  1692.                 BlockMove(PicBaseAddr, UndoBuf, PixMapSize);
  1693.                 UndoFromClip := false;
  1694.                 RedoSelection := false;
  1695.             end;
  1696.     end;
  1697.  
  1698.  
  1699.     procedure SetupUndoFromClip;
  1700.         var
  1701.             line: integer;
  1702.     begin
  1703.         WhatToUndo := NothingToUndo;
  1704.         if info = NoInfo then begin
  1705.                 CurrentUndoSize := 0;
  1706.                 exit(SetupUndoFromClip)
  1707.             end;
  1708.         with info^ do begin
  1709.                 if PixMapSize > ClipBufSize then begin
  1710.                         CurrentUndoSize := 0;
  1711.                         exit(SetupUndoFromClip)
  1712.                     end;
  1713.                 if OpPending then begin
  1714.                         DoOperation(CurrentOp);
  1715.                         OpPending := false;
  1716.                     end;
  1717.                 CurrentUndoSize := PixMapSize;
  1718.                 BlockMove(PicBaseAddr, ClipBuf, PixMapSize);
  1719.             end;
  1720.         WhatsOnClip := nothing;
  1721.         UndofromClip := true;
  1722.         RedoSelection := false;
  1723.     end;
  1724.  
  1725.  
  1726.     function NoSelection;{:boolean}
  1727.     begin
  1728.         if Info = NoInfo then begin
  1729.                 beep;
  1730.                 NoSelection := true;
  1731.                 exit(NoSelection);
  1732.             end;
  1733.         if not Info^.RoiShowing then begin
  1734.                 PutMessage('Please use a selection tool to make a selection or use the Select All command.');
  1735.                 macro := false;
  1736.             end;
  1737.         NoSelection := not Info^.RoiShowing;
  1738.     end;
  1739.  
  1740.  
  1741.     function NotRectangular;{:boolean}
  1742.     begin
  1743.         with info^ do
  1744.             if RoiShowing and (RoiType <> RectRoi) then begin
  1745.                     PutMessage('This operation requires a rectangular selection.');
  1746.                     NotRectangular := true;
  1747.                     macro := false;
  1748.                 end
  1749.             else
  1750.                 NotRectangular := false;
  1751.     end;
  1752.  
  1753.  
  1754.     procedure GetLoi (var x1, y1, x2, y2: real);
  1755.     begin
  1756.         with info^, info^.RoiRect do begin
  1757.                 x1 := left + LX1;
  1758.                 y1 := top + LY1;
  1759.                 x2 := left + LX2;
  1760.                 y2 := top + LY2;
  1761.             end;
  1762.     end;
  1763.  
  1764.  
  1765.     function NotInBounds;{:boolean}
  1766.         var
  1767.             x1, y1, x2, y2: real;
  1768.     begin
  1769.         NotInBounds := false;
  1770.         with info^, info^.RoiRect do
  1771.             if RoiShowing then begin
  1772.                     if RoiType = LineRoi then begin
  1773.                             GetLoi(x1, y1, x2, y2);
  1774.                             if (x1 >= 0.0) and (y1 >= 0.0) and (x2 <= right) and (y2 <= bottom) then
  1775.                                 exit(NotInBounds);
  1776.                         end;
  1777.                     if (left < 0) or (top < 0) or (right > PicRect.right) or (bottom > PicRect.bottom) then begin
  1778.                             PutMessage('This operation requires the selection to be entirely within the image.');
  1779.                             NotInBounds := true;
  1780.                             macro := false;
  1781.                         end;
  1782.                 end;
  1783.     end;
  1784.  
  1785.  
  1786.     function NoUndo: boolean;
  1787.         var
  1788.             ImageTooLarge: boolean;
  1789.     begin
  1790.         with info^ do
  1791.             ImageTooLarge := (PixMapSize > ClipBufSize) or (PixMapSize > UndoBufSize);
  1792.         if ImageTooLarge then
  1793.             PutMessage('This operation requires that the Undo and Clipboard buffers be at least as large as the image.');
  1794.         NoUndo := ImageTooLarge;
  1795.     end;
  1796.  
  1797.  
  1798.     procedure PutMemoryAlert;
  1799.     begin
  1800.         PutMessage('Sorry, but there is not enough memory available to open this image. Try closing some windows.');
  1801.         macro := false;
  1802.     end;
  1803.  
  1804.  
  1805.     procedure CompactMemory;
  1806.         var
  1807.             size: LongInt;
  1808.             TempInfo: InfoPtr;
  1809.             i: integer;
  1810.     begin
  1811.         for i := 1 to nPics do begin
  1812.                 TempInfo := pointer(WindowPeek(PicWindow[i])^.RefCon);
  1813.                 hunlock(TempInfo^.PicBaseHandle)
  1814.             end;
  1815.         size := 4000000;
  1816.         PurgeMem(size);
  1817.         size := CompactMem(size);
  1818.         for i := 1 to nPics do begin
  1819.                 TempInfo := pointer(WindowPeek(PicWindow[i])^.RefCon);
  1820.                 with TempInfo^ do begin
  1821.                         hlock(PicBaseHandle);
  1822.                         PicBaseAddr := StripAddress(PicBaseHandle^);
  1823.                         osPort^.PortPixMap^^.BaseAddr := PicBaseAddr;
  1824.                     end;
  1825.             end;
  1826.     end;
  1827.  
  1828.  
  1829.     function GetImageMemory (SaveInfo: infoPtr; var PicBaseHandle: handle; double: boolean): ptr;
  1830. {Allocates memory for the PixMap of new image windows. SaveInfo points to the InfoRec of the previous window.}
  1831. {A handle is used, rather than a pointer, since NewPtr(particularly on the ci and fx) is rediculously slow.}
  1832. {Would you believe up to 10 seconds when many windows are open?}
  1833.         var
  1834.             h: handle;
  1835.             FreeMem, NeededSize: LongInt;
  1836.     begin
  1837.         with info^ do begin
  1838.                 if odd(PixelsPerLine) then
  1839.                     BytesPerRow := PixelsPerLine + 1
  1840.                 else
  1841.                     BytesPerRow := PixelsPerLine;
  1842.                 PixMapSize := LongInt(nlines) * BytesPerRow;
  1843.                 ImageSize := LongInt(nlines) * PixelsPerLine;
  1844.                 NeededSize := PixMapSize;
  1845.                 if double then
  1846.                     NeededSize := NeededSize * 2;
  1847.                 h := NewHandle(NeededSize);
  1848.             end;
  1849.         FreeMem := MaxBlock;
  1850.         if (h = nil) or (FreeMem < MinFree) then begin
  1851.                 if h <> nil then
  1852.                     DisposHandle(h);
  1853.                 CompactMemory;
  1854.                 h := NewHandle(NeededSize);
  1855.                 FreeMem := MaxBlock;
  1856.             end;
  1857.         if (h = nil) or (FreeMem < MinFree) then begin
  1858.                 if h <> nil then
  1859.                     DisposHandle(h);
  1860.                 PutMemoryAlert;
  1861.                 DisposPtr(pointer(Info));
  1862.                 Info := SaveInfo;
  1863.                 GetImageMemory := nil;
  1864.                 exit(GetImageMemory);
  1865.             end;
  1866.         PicBaseHandle := h;
  1867.         hlock(PicBaseHandle);
  1868.         GetImageMemory := StripAddress(PicBaseHandle^);
  1869.     end;
  1870.  
  1871.  
  1872.     function OldGetMemory (Size: LongInt; SaveInfo: infoPtr; var PicBaseHandle: handle): ptr;
  1873.         var
  1874.             h1, h2: handle;
  1875.     begin
  1876.         h1 := NewHandle(size);
  1877.         h2 := NewHandle(MinFree);
  1878.         if (h1 = nil) or (h2 = nil) then begin
  1879.                 if h1 <> nil then
  1880.                     DisposHandle(h1);
  1881.                 if h2 <> nil then
  1882.                     DisposHandle(h2);
  1883.                 CompactMemory;
  1884.                 h1 := NewHandle(size);
  1885.                 h2 := NewHandle(MinFree);
  1886.             end;
  1887.         if (h1 = nil) or (h2 = nil) then begin
  1888.                 if h1 <> nil then
  1889.                     DisposHandle(h1);
  1890.                 if h2 <> nil then
  1891.                     DisposHandle(h2);
  1892.                 PutMemoryAlert;
  1893.                 DisposPtr(pointer(Info));
  1894.                 Info := SaveInfo;
  1895.                 OldGetMemory := nil;
  1896.                 exit(OldGetMemory);
  1897.             end;
  1898.         DisposHandle(h2);
  1899.         PicBaseHandle := h1;
  1900.         hlock(PicBaseHandle);
  1901.         OldGetMemory := PicBaseHandle^;
  1902.     end;
  1903.  
  1904.  
  1905.     procedure UpdateAnalysisMenu;
  1906.         var
  1907.             ShowItems: boolean;
  1908.             i: integer;
  1909.     begin
  1910.         ShowItems := Info <> NoInfo;
  1911.         SetMenuItem(AnalyzemenuH, MeasureItem, ShowItems);
  1912.         SetMenuItem(AnalyzemenuH, AnalyzeItem, ShowItems);
  1913.         SetMenuItem(AnalyzemenuH, HistogramItem, ShowItems);
  1914.         SetMenuItem(AnalyzemenuH, PlotItem, ShowItems);
  1915.         SetMenuItem(AnalyzemenuH, PlotSurfaceItem, ShowItems);
  1916.         SetMenuItem(AnalyzemenuH, SetScaleItem, ShowItems);
  1917.         SetMenuItem(AnalyzemenuH, CalibrateItem, ShowItems);
  1918.         SetMenuItem(AnalyzemenuH, RedoItem, mCount > 0);
  1919.         SetMenuItem(AnalyzemenuH, DeleteItem, mCount > 0);
  1920.         SetMenuItem(AnalyzemenuH, RestoreItem, ShowItems and (NoInfo^.RoiType <> NoRoi));
  1921.         SetMenuItem(AnalyzemenuH, MarkItem, info^.RoiShowing);
  1922.     end;
  1923.  
  1924.  
  1925.     procedure ExtendWindowsMenu;{(fname:str255; size:LongInt; wptr:WindowPtr)}
  1926.         var
  1927.             str, SizeStr: str255;
  1928.     begin
  1929.         if nPics < MaxPics then begin
  1930.                 nPics := nPics + 1;
  1931.                 PicWindow[nPics] := wptr;
  1932.                 NumToString(size div 1024, SizeStr);
  1933.                 str := concat(fname, '  ', SizeStr, 'K');
  1934.                 AppendMenu(WindowsMenuH, ' ');
  1935.                 SetItem(WindowsMenuH, nPics + WindowsMenuItems, str);
  1936.                 InsertMenu(WindowsMenuH, 0);
  1937.             end;
  1938.     end;
  1939.  
  1940.  
  1941.     procedure InvertGrayLevels;
  1942.     begin
  1943.         with info^ do begin
  1944.                 DensityCalibrated := true;
  1945.                 nCoefficients := 2;
  1946.                 fit := StraightLine;
  1947.                 Coefficient[1] := 255.0;
  1948.                 Coefficient[2] := -1.0;
  1949.                 ZeroClip := false;
  1950.                 UpdateTitleBar;
  1951.             end;
  1952.     end;
  1953.  
  1954.  
  1955.     procedure MakeNewWindow;{(name:str255)}
  1956.         var
  1957.             wwidth, wheight, wleft, wtop, i: integer;
  1958.             tPort: GrafPtr;
  1959.             rgb: RGBColor;
  1960.             err: OSErr;
  1961.             str: str255;
  1962.     begin
  1963.         with Info^ do begin
  1964.                 wleft := PicLeft;
  1965.                 wtop := PicTop;
  1966.                 PicLeft := PicLeft + hPicOffset;
  1967.                 PicTop := PicTop + vPicOffset;
  1968.                 if ((PicLeft + round(0.75 * PixelsPerLine)) > ScreenWidth) or ((PicTop + round(0.75 * nlines)) > ScreenHeight) then begin
  1969.                         PicLeft := PicLeftBase;
  1970.                         PicTop := PicTopBase;
  1971.                     end;
  1972.                 wwidth := PixelsPerLine;
  1973.                 if (wleft + wwidth) > ScreenWidth then
  1974.                     wwidth := ScreenWidth - wleft - 4;
  1975.                 wheight := nlines;
  1976.                 if (wtop + wheight) > ScreenHeight then
  1977.                     wheight := ScreenHeight - wtop - 4;
  1978.                 SetRect(wrect, wleft, wtop, wleft + wwidth, wtop + wheight);
  1979.                 str := name;
  1980.                 if SpatiallyCalibrated then
  1981.                     str := concat(str, chr($13)); {Black Diamond}
  1982.                 if DensityCalibrated then
  1983.                     str := concat(str, '╫');
  1984.                 wptr := NewCWindow(nil, wrect, str, true, DocumentProc + ZoomDocProc, nil, true, 0);
  1985.                 GetPort(tPort);
  1986.                 SetPort(wptr);
  1987.                 SetPalette(wptr, ExplicitPalette, false);
  1988.                 pmForeColor(BlackIndex);
  1989.                 pmBackColor(WhiteIndex);
  1990.                 SetRect(wrect, 0, 0, wwidth, wheight);
  1991.                 SetRect(PicRect, 0, 0, PixelsPerLine, nlines);
  1992.                 SelectWindow(wptr);
  1993.                 WindowPeek(wptr)^.WindowKind := PicKind;
  1994.                 WindowPeek(wptr)^.RefCon := ord4(Info);
  1995.                 title := name;
  1996.                 ExtendWindowsMenu(name, ImageSize, wptr);
  1997.                 PicNum := nPics;
  1998.                 new(osPort);
  1999.                 OpenCPort(osPort);
  2000.                 with osPort^ do begin
  2001.                         with PortPixMap^^ do begin
  2002.                                 BaseAddr := PicBaseAddr;
  2003.                                 bounds := PicRect;
  2004.                             end;
  2005.                         PortRect := PicRect;
  2006.                         RectRgn(visRgn, PicRect);
  2007.                         PortPixMap^^.RowBytes := BitOr(BytesPerRow, $8000);
  2008.                     end;
  2009.                 SetPalette(WindowPtr(osPort), ExplicitPalette, false);
  2010.                 pmForeColor(ForegroundIndex);
  2011.                 pmBackColor(BackgroundIndex);
  2012.                 SetPort(tPort);
  2013.                 SrcRect := wrect;
  2014.                 magnification := 1.0;
  2015.                 RoiShowing := false;
  2016.                 roiType := NoRoi;
  2017.                 initwrect := wrect;
  2018.                 savewrect := wrect;
  2019.                 SaveSrcRect := SrcRect;
  2020.                 SaveMagnification := magnification;
  2021.                 savehloc := wleft;
  2022.                 savevloc := wtop;
  2023.                 roiRgn := NewRgn;
  2024.                 NewPic := true;
  2025.                 ScaleToFitWindow := false;
  2026.                 OpPending := false;
  2027.                 Changes := false;
  2028.                 WindowState := NormalWindow;
  2029.                 if not DensityCalibrated and InvertPixelValues then
  2030.                     InvertGrayLevels;
  2031.                 Revertable := false;
  2032.                 nCoordinates := 0;
  2033.             end;
  2034.         WhatToUndo := NothingToUndo;
  2035.     end;
  2036.  
  2037.  
  2038.     procedure MakeRegion;
  2039.         var
  2040.             deltax, deltay, x1, y1, x2, y2, xt, yt: integer;
  2041.             tPort: GrafPtr;
  2042.  
  2043.         procedure SwapEnds;
  2044.         begin
  2045.             xt := x1;
  2046.             yt := y1;
  2047.             x1 := x2;
  2048.             y1 := y2;
  2049.             x2 := xt;
  2050.             y2 := yt;
  2051.         end;
  2052.  
  2053.     begin
  2054.         with info^ do begin
  2055.                 GetPort(tPort);
  2056.                 SetPort(wptr);
  2057.                 x1 := trunc(LX1);
  2058.                 y1 := trunc(LY1);
  2059.                 x2 := trunc(LX2);
  2060.                 y2 := trunc(LY2);
  2061.                 OpenRgn;
  2062.                 case RoiType of
  2063.                     LineRoi:  begin
  2064.                             deltax := abs(x2 - x1);
  2065.                             deltay := abs(y2 - y1);
  2066.                             if (deltax = 0) and (deltay = 0) then begin
  2067.                                     MoveTo(x1, y1);
  2068.                                     LineTo(x1 + LineWidth, y1);
  2069.                                     LineTo(x1 + LineWidth, y1 + LineWidth);
  2070.                                     LineTo(x1, y1 + LineWidth);
  2071.                                 end
  2072.                             else if deltax < deltay then begin
  2073.                                     if y1 > y2 then
  2074.                                         SwapEnds;
  2075.                                     MoveTo(x1, y1);
  2076.                                     LineTo(x2, y2);
  2077.                                     LineTo(X2, y2 + 1);
  2078.                                     LineTo(X2 + LineWidth, y2 + 1);
  2079.                                     LineTo(x2 + LineWidth, y2);
  2080.                                     LineTo(x1 + LineWidth, y1);
  2081.                                 end
  2082.                             else begin
  2083.                                     if x1 > x2 then
  2084.                                         SwapEnds;
  2085.                                     MoveTo(x1, y1);
  2086.                                     LineTo(x2, y2);
  2087.                                     LineTo(x2 + 1, y2);
  2088.                                     LineTo(x2 + 1, y2 + LineWidth);
  2089.                                     LineTo(x2, y2 + LineWidth);
  2090.                                     LineTo(x1, y1 + LineWidth);
  2091.                                 end;
  2092.                             LineTo(x1, y1);
  2093.                         end;
  2094.                     OvalRoi: 
  2095.                         FrameOval(RoiRect);
  2096.                     RectRoi: 
  2097.                         FrameRect(RoiRect);
  2098.                     otherwise
  2099.                 end;
  2100.                 CloseRgn(roiRgn);
  2101.                 if RoiType = LineRoi then begin
  2102.                         RoiRect := roiRgn^^.rgnBBox;
  2103.                         with RoiRect do begin
  2104.                                 LX1 := LX1 - left;
  2105.                                 LY1 := LY1 - top;
  2106.                                 LX2 := LX2 - left;
  2107.                                 LY2 := LY2 - top;
  2108.                             end;
  2109.                     end;
  2110.             end;
  2111.         SetPort(tPort);
  2112.     end;
  2113.  
  2114.  
  2115.     procedure SelectAll;{(visible:boolean)}
  2116.         var
  2117.             loc: point;
  2118.             tPort: GrafPtr;
  2119.     begin
  2120.         if info <> NoInfo then
  2121.             with Info^ do begin
  2122.                     KillRoi;
  2123.                     RoiType := RectRoi;
  2124.                     RoiRect := PicRect;
  2125.                     MakeRegion;
  2126.                     if visible then begin
  2127.                             SetupUndo;
  2128.                             RoiShowing := true;
  2129.                             if (magnification > 1.0) and not ScaleToFitWindow then
  2130.                                 Unzoom;
  2131.                             PreviousTool := CurrentTool;
  2132.                             CurrentTool := SelectionTool;
  2133.                             isSelectionTool := true;
  2134.                             GetPort(tPort);
  2135.                             SetPort(ToolWindow);
  2136.                             EraseRect(ToolRect[PreviousTool]);
  2137.                             EraseRect(ToolRect[CurrentTool]);
  2138.                             InvalRect(ToolRect[PreviousTool]);
  2139.                             InvalRect(ToolRect[CurrentTool]);
  2140.                             SetPort(tPort);
  2141.                         end;
  2142.                     IsInsertionPoint := false;
  2143.                     measuring := false;
  2144.                 end; {with}
  2145.     end;
  2146.  
  2147.  
  2148.     procedure KillOperation;
  2149.     begin
  2150.         if OpPending then
  2151.             with info^ do
  2152.                 if info <> NoInfo then begin
  2153.                         DoOperation(CurrentOp);
  2154.                         RoiShowing := false;
  2155.                         UpdateScreen(RoiRect);
  2156.                         OpPending := false;
  2157.                     end;
  2158.     end;
  2159.  
  2160.  
  2161.     function NewPicWindow;{(name:str255; width,height:integer):boolean}
  2162.         var
  2163.             iptr: ptr;
  2164.             lptr: ^LongInt;
  2165.             SaveInfo: InfoPtr;
  2166.             NeededSize: LongInt;
  2167.     begin
  2168.         NewPicWindow := false;
  2169.         if nPics = MaxPics then
  2170.             exit(NewPicWindow);
  2171.         KillOperation;
  2172.         DisableDensitySlice;
  2173.         SaveInfo := Info;
  2174.         iptr := NewPtr(SizeOf(PicInfo));
  2175.         if iptr = nil then begin
  2176.                 DisposPtr(iptr);
  2177.                 PutMemoryAlert;
  2178.                 macro := false;
  2179.                 exit(NewPicWindow);
  2180.             end;
  2181.         Info := pointer(iptr);
  2182.         info^ := SaveInfo^;
  2183.         with Info^ do begin
  2184.                 nlines := height;
  2185.                 PixelsPerLine := width;
  2186.                 PicBaseAddr := GetImageMemory(SaveInfo, PicBaseHandle, false);
  2187.                 if PicBaseAddr = nil then
  2188.                     exit(NewPicWindow);
  2189.                 PicLeft := PicLeftBase;
  2190.                 PicTop := PicTopBase;
  2191.                 MakeNewWindow(name);
  2192.                 PictureType := NewPicture;
  2193.                 SelectAll(false);
  2194.                 DoOperation(EraseOp);
  2195.                 RoiType := NoRoi;
  2196.                 changes := false;
  2197.                 BinaryPic := false;
  2198.                 StackInfo := nil;
  2199.                 nCoordinates := 0;
  2200.             end;
  2201.         NewPicWindow := true;
  2202.     end;
  2203.  
  2204.  
  2205.     procedure EraseScreen;
  2206.     begin
  2207.         SetPort(GrafPtr(CScreenPort));
  2208.         with CScreenPort^ do begin
  2209.                 HideCursor;
  2210.                 pmBackColor(BackgroundIndex);
  2211.                 EraseRect(portPixMap^^.Bounds);
  2212.                 pmBackColor(WhiteIndex);
  2213.             end;
  2214.     end;
  2215.  
  2216.  
  2217.     procedure RestoreScreen;
  2218.         var
  2219.             GrayRgn: RgnHandle;
  2220.             rptr: rhptr;
  2221.             wp: ^WindowPtr;
  2222.     begin
  2223.         rptr := rhptr(GrayRgnGlobal);
  2224.         GrayRgn := rptr^;
  2225.         wp := pointer(GhostWindow);
  2226.         wp^ := WindowPtr(nil);
  2227.         PaintBehind(WindowPeek(FrontWindow), GrayRgn);
  2228.         wp^ := PasteControl;
  2229.         DrawMenuBar;
  2230.     end;
  2231.  
  2232.  
  2233.     procedure UpdateTitleBar;
  2234.     {Updates the window title bar to show the current magnification or the current frame within a stack.}
  2235.         var
  2236.             str, str2, str3: str255;
  2237.     begin
  2238.         with info^ do begin
  2239.                 str := title;
  2240.                 if SpatiallyCalibrated then
  2241.                     str := concat(str, chr($13)); {Black Diamond}
  2242.                 if DensityCalibrated then
  2243.                     str := concat(str, '╫');
  2244.                 if StackInfo <> nil then
  2245.                     with StackInfo^ do begin
  2246.                             NumToString(CurrentSlice, str2);
  2247.                             NumToString(nSlices, str3);
  2248.                             str := concat(str, '(', str2, '/', str3, ')');
  2249.                         end
  2250.                 else if (magnification <> 1.0) or ScaleToFitWindow then begin
  2251.                         if ScaleToFitWindow then begin
  2252.                                 RealToString(magnification, 1, 2, str2);
  2253.                                 str := concat(str, '(', str2, ')');
  2254.                             end
  2255.                         else begin
  2256.                                 RealToString(magnification, 1, 0, str2);
  2257.                                 str := concat(str, '(', str2, ':1)');
  2258.                             end;
  2259.                     end;
  2260.                 if Digitizing then begin
  2261.                         if ExternalTrigger then
  2262.                             str := concat(str, '(Waiting for Trigger)')
  2263.                         else
  2264.                             str := concat(str, '(Live)');
  2265.                     end;
  2266.                 if wptr <> nil then
  2267.                     SetWTitle(wptr, str);
  2268.             end; {with}
  2269.     end;
  2270.  
  2271.  
  2272.     procedure ScaleToFit;
  2273.         var
  2274.             trect: rect;
  2275.     begin
  2276.         if digitizing then
  2277.             exit(ScaleToFit);
  2278.         if info <> NoInfo then
  2279.             with info^ do begin
  2280.                     ScaleToFitWindow := not ScaleToFitWindow;
  2281.                     KillRoi;
  2282.                     if ScaleToFitWindow then begin
  2283.                             savewrect := wrect;
  2284.                             SaveSrcRect := SrcRect;
  2285.                             SaveMagnification := magnification;
  2286.                             GetWindowRect(wptr, trect);
  2287.                             savehloc := trect.left;
  2288.                             savevloc := trect.top;
  2289.                             wrect := wptr^.PortRect;
  2290.                             SrcRect := PicRect;
  2291.                             ScaleImageWindow(wrect);
  2292.                             SizeWindow(wptr, wrect.right, wrect.bottom, true);
  2293.                         end
  2294.                     else begin
  2295.                             if WindowState = TiledBigScaled then begin
  2296.                                     wrect := initwrect;
  2297.                                     SrcRect := wrect;
  2298.                                     magnification := 1.0;
  2299.                                     WindowState := NormalWindow;
  2300.                                 end
  2301.                             else begin
  2302.                                     wrect := savewrect;
  2303.                                     SrcRect := SaveSrcRect;
  2304.                                     magnification := SaveMagnification;
  2305.                                 end;
  2306.                             HideWindow(wptr);
  2307.                             SizeWindow(wptr, wrect.right, wrect.bottom, true);
  2308.                             MoveWindow(wptr, savehloc, savevloc, true);
  2309.                             ShowWindow(wptr);
  2310.                             UpdateTitleBar;
  2311.                         end;
  2312.                     SetPort(wptr);
  2313.                     InvalRect(wrect);
  2314.                     WindowState := NormalWindow;
  2315.                 end;
  2316.     end;
  2317.  
  2318.  
  2319.     procedure DrawMyGrowIcon;{(w:WindowPtr)}
  2320.         var
  2321.             tPort: GrafPtr;
  2322.             tRect: rect;
  2323.     begin
  2324.         GetPort(tPort);
  2325.         SetPort(w);
  2326.         PenNormal;
  2327.         with w^.PortRect do begin
  2328.                 SetRect(tRect, right - 12, bottom - 12, right - 5, bottom - 5);
  2329.                 FrameRect(tRect);
  2330.                 MoveTo(right - 6, bottom - 10);
  2331.                 LineTo(right - 2, bottom - 10);
  2332.                 LineTo(right - 2, bottom - 2);
  2333.                 LineTo(right - 10, bottom - 2);
  2334.                 LineTo(right - 10, bottom - 6);
  2335.             end;
  2336.         SetPort(tPort);
  2337.     end;
  2338.  
  2339.  
  2340.     procedure Unzoom;
  2341.     begin
  2342.         if Info <> NoInfo then
  2343.             with Info^ do begin
  2344.                     if ScaleToFitWindow then
  2345.                         ScaleToFit
  2346.                     else begin
  2347.                             wrect := initwrect;
  2348.                             SrcRect := wrect;
  2349.                         end;
  2350.                     SizeWindow(wptr, wrect.right, wrect.bottom, true);
  2351.                     LoadLUT(info^.cTable);
  2352.                     UpdatePicWindow;
  2353.                     magnification := 1.0;
  2354.                     DrawMyGrowIcon(wptr);
  2355.                     UpdateTitleBar;
  2356.                     if WhatToUndo = UndoZoom then
  2357.                         WhatToUndo := NothingToUndo;
  2358.                     ShowRoi;
  2359.                 end;
  2360.     end;
  2361.  
  2362.  
  2363.     function FindMedian;{(VAR a:SortArray):integer}
  2364.   {Finds the 5th largest of 9 values}
  2365.         var
  2366.             i, j, mj, max: integer;
  2367.     begin
  2368.         for i := 1 to 4 do begin
  2369.                 max := 0;
  2370.                 mj := 1;
  2371.                 for j := 1 to 9 do
  2372.                     if a[j] > max then begin
  2373.                             max := a[j];
  2374.                             mj := j;
  2375.                         end;
  2376.                 a[mj] := 0;
  2377.             end;
  2378.         max := 0;
  2379.         for j := 1 to 9 do
  2380.             if a[j] > max then
  2381.                 max := a[j];
  2382.         FindMedian := max;
  2383.     end;
  2384.  
  2385.  
  2386.     procedure DrawBString;{(str:string)}
  2387.     begin
  2388.         TextFace([bold]);
  2389.         DrawString(str);
  2390.         TextFace([]);
  2391.     end;
  2392.  
  2393.  
  2394.     procedure PutWarning;
  2395.         var
  2396.             BufSizeStr: str255;
  2397.     begin
  2398.         NumToString(UndoBufSize div 1024, BufSizeStr);
  2399.         PutMessage(concat('This image is larger than the ', BufSizeStr, 'K Undo buffer. Many operations may fail or be Undoable.'));
  2400.     end;
  2401.  
  2402.  
  2403.     procedure SetupRoiRect;
  2404. {Copies the current image to Undo buffer so it can be used for drawing}
  2405. {the "marching ants". The copy of the previous image in the Clipboard buffer}
  2406. { buffer will be used for Undo.}
  2407.         var
  2408.             SaveWhatToUndo: WhatToUndoType;
  2409.     begin
  2410.         SaveWhatToUndo := WhatToUndo;
  2411.         SetupUndo;
  2412.         UndoFromClip := true;
  2413.         info^.RoiShowing := true;
  2414.         WhatToUndo := SaveWhatToUndo;
  2415.     end;
  2416.  
  2417.  
  2418.     procedure SetForegroundColor (color: integer);
  2419.         var
  2420.             tPort: GrafPtr;
  2421.     begin
  2422.         if (color >= 0) and (color <= 255) then
  2423.             with info^ do begin
  2424.                     ForegroundIndex := color;
  2425.                     GetPort(tPort);
  2426.                     SetPort(ToolWindow);
  2427.                     InvalRect(ToolRect[brush]);
  2428.                     if osPort <> nil then begin
  2429.                             SetPort(GrafPtr(osPort));
  2430.                             pmForeColor(ForegroundIndex);
  2431.                         end;
  2432.                     SetPort(tPort);
  2433.                     if isInsertionPoint then
  2434.                         DisplayText(true);
  2435.                 end;
  2436.     end;
  2437.  
  2438.  
  2439.     procedure SetBackgroundColor (color: integer);
  2440.         var
  2441.             tPort: GrafPtr;
  2442.     begin
  2443.         if (color >= 0) and (color <= 255) then
  2444.             with info^ do begin
  2445.                     BackgroundIndex := color;
  2446.                     GetPort(tPort);
  2447.                     SetPort(ToolWindow);
  2448.                     InvalRect(ToolRect[eraser]);
  2449.                     if osPort <> nil then begin
  2450.                             SetPort(GrafPtr(osPort));
  2451.                             pmBackColor(BackgroundIndex);
  2452.                         end;
  2453.                     SetPort(tPort);
  2454.                     if isInsertionPoint then
  2455.                         DisplayText(true);
  2456.                 end;
  2457.     end;
  2458.  
  2459.  
  2460.     procedure GetForegroundColor;{(event: EventRecord)}
  2461.         var
  2462.             loc: point;
  2463.             color: integer;
  2464.     begin
  2465.         loc := event.where;
  2466.         ScreenToOffScreen(loc);
  2467.         Color := MyGetPixel(loc.h, loc.v);
  2468.         SetForegroundColor(color);
  2469.     end;
  2470.  
  2471.  
  2472.     procedure GetBackgroundColor; {(event: EventRecord)}
  2473.         var
  2474.             loc: point;
  2475.             color: integer;
  2476.     begin
  2477.         loc := event.where;
  2478.         ScreenToOffScreen(loc);
  2479.         Color := MyGetPixel(loc.h, loc.v);
  2480.         SetBackgroundColor(color);
  2481.     end;
  2482.  
  2483.  
  2484.     procedure GenerateValues;
  2485.         var
  2486.             a, b, c, d, e, f, x, y: extended;
  2487.             i: integer;
  2488.     begin
  2489.         with info^ do begin
  2490.                 if not DensityCalibrated then begin
  2491.                         for i := 0 to 255 do
  2492.                             cvalue[i] := i;
  2493.                         MinValue := 0.0;
  2494.                         MaxValue := 255.0;
  2495.                         exit(GenerateValues);
  2496.                     end;
  2497.                 a := Coefficient[1];
  2498.                 b := Coefficient[2];
  2499.                 c := Coefficient[3];
  2500.                 d := Coefficient[4];
  2501.                 e := Coefficient[5];
  2502.                 f := Coefficient[6];
  2503.                 MinValue := 10e+12;
  2504.                 MaxValue := -MinValue;
  2505.                 for i := 0 to 255 do begin
  2506.                         x := i;
  2507.                         case fit of
  2508.                             StraightLine: 
  2509.                                 y := a + b * x;
  2510.                             Poly2: 
  2511.                                 y := a + b * x + c * x * x;
  2512.                             Poly3: 
  2513.                                 y := a + b * x + c * x * x + d * x * x * x;
  2514.                             Poly4: 
  2515.                                 y := a + b * x + c * x * x + d * x * x * x + e * x * x * x * x;
  2516.                             Poly5: 
  2517.                                 y := a + b * x + c * x * x + d * x * x * x + e * x * x * x * x + f * x * x * x * x * x;
  2518.                             ExpoFit: 
  2519.                                 y := a * exp(b * x);
  2520.                             PowerFit: 
  2521.                                 if x = 0.0 then
  2522.                                     y := 0.0
  2523.                                 else
  2524.                                     y := a * exp(b * ln(x)); {y=ax^b}
  2525.                             LogFit:  begin
  2526.                                     if x = 0.0 then
  2527.                                         x := 0.5;
  2528.                                     y := a * ln(b * x)
  2529.                                 end;
  2530.                             RodbardFit:  begin
  2531.                                     if x <= a then
  2532.                                         y := 0
  2533.                                     else begin
  2534.                                             y := (a - x) / (x - d);
  2535.                                             y := exp(ln(y) * (1 / b));  {y:=y**(1/b)}
  2536.                                             y := y * c;
  2537.                                         end;
  2538.                                 end;
  2539.                             UncalibratedOD:  begin
  2540.                                     if x = 255.0 then
  2541.                                         x := 254.5;
  2542.                                     y := 0.434294481 * ln(255 / (255 - x))  {log10}
  2543.                                 end;
  2544.                             otherwise
  2545.                                 y := x;
  2546.                         end; {case}
  2547.                         cvalue[i] := y;
  2548.                         if y > MaxValue then
  2549.                             MaxValue := y;
  2550.                         if y < MinValue then
  2551.                             MinValue := y;
  2552.                     end; {for}
  2553.                 if MinValue >= 0.0 then
  2554.                     ZeroClip := false;
  2555.                 if ZeroClip then begin
  2556.                         for i := 0 to 255 do
  2557.                             if cvalue[i] < 0.0 then
  2558.                                 cvalue[i] := 0.0;
  2559.                         MinValue := 0.0;
  2560.                     end;
  2561.             end;
  2562.     end;
  2563.  
  2564.  
  2565.     procedure ScaleImageWindow (var trect: rect);
  2566.         var
  2567.             WindowLeft, WindowTop: integer;
  2568.             PicAspectRatio, TempMagnification: extended;
  2569.     begin
  2570.         with info^ do begin
  2571.                 SrcRect := PicRect;
  2572.                 with CGrafPort(wptr^).PortPixMap^^.bounds do begin
  2573.                         WindowLeft := -left;
  2574.                         WindowTop := -top;
  2575.                     end;
  2576.                 with PicRect do
  2577.                     PicAspectRatio := right / bottom;
  2578.                 with trect do begin
  2579.                         if (WindowLeft + right) > (ScreenWidth - 5) then
  2580.                             right := ScreenWidth - 5 - WindowLeft;
  2581.                         bottom := round(right / PicAspectRatio);
  2582.                         if (WindowTop + bottom) > (ScreenHeight - 5) then
  2583.                             bottom := ScreenHeight - 5 - WindowTop;
  2584.                         right := round(bottom * PicAspectRatio);
  2585.                         magnification := right / PicRect.right;
  2586.                     end;
  2587.                 UpdateTitleBar;
  2588.             end; {with}
  2589.     end;
  2590.  
  2591.  
  2592.     function TooWide: boolean;
  2593.         var
  2594.             SelectionTooWide: boolean;
  2595.             MaxWidth: str255;
  2596.     begin
  2597.         with info^.RoiRect do
  2598.             SelectionTooWide := (right - left) > MaxLine;
  2599.         if SelectionTooWide then begin
  2600.                 NumToString(MaxLine, MaxWidth);
  2601.                 PutMessage(concat('This operation does not support selections wider than ', MaxWidth, ' pixels.'));
  2602.             end;
  2603.         TooWide := SelectionTooWide;
  2604.     end;
  2605.  
  2606.  
  2607.     procedure DrawTextString (str: str255; loc: point; just: integer);
  2608.         var
  2609.             SaveJust: integer;
  2610.     begin
  2611.         TextStr := str;
  2612.         IsInsertionPoint := true;
  2613.         TextStart := loc;
  2614.         SaveJust := TextJust;
  2615.         TextJust := just;
  2616.         DisplayText(false);
  2617.         TextJust := SaveJust;
  2618.         IsInsertionPoint := false;
  2619.     end;
  2620.  
  2621.  
  2622.     procedure IncrementCounter;
  2623.     begin
  2624.         if mCount < MaxRegions then begin
  2625.                 mCount := mCount + 1;
  2626.                 UnsavedResults := true;
  2627.             end
  2628.         else
  2629.             beep;
  2630.     end;
  2631.  
  2632.  
  2633.     procedure ClearResults (i: integer);
  2634.     begin
  2635.         mean^[i] := 0.0;
  2636.         sd^[i] := 0.0;
  2637.         PixelCount^[i] := 0;
  2638.         mArea^[i] := 0.0;
  2639.         mode^[i] := 0.0;
  2640.         IntegratedDensity^[i] := 0.0;
  2641.         idBackground^[i] := 0.0;
  2642.         xcenter^[i] := 0.0;
  2643.         ycenter^[i] := 0.0;
  2644.         MajorAxis^[i] := 0.0;
  2645.         MinorAxis^[i] := 0.0;
  2646.         orientation^[i] := 0.0;
  2647.         mMin^[i] := 0.0;
  2648.         mMax^[i] := 0.0;
  2649.         plength^[i] := 0.0;
  2650.     end;
  2651.  
  2652.     procedure UpdateFitEllipse;
  2653.     begin
  2654.         FitEllipse := (xyLocM in measurements) or (MajorAxisM in measurements) or (MinorAxisM in measurements) or (AngleM in measurements);
  2655.     end;
  2656.  
  2657.  
  2658.     function StringToReal (str: str255): real;
  2659.         var
  2660.             i, ndigits, StringLength: integer;
  2661.             c: char;
  2662.             n, m: real;
  2663.             negative, LeftOfPoint, NegExp: boolean;
  2664.             exponent: LongInt;
  2665.     begin
  2666.         negative := false;
  2667.         n := 0.0;
  2668.         LeftOfPoint := true;
  2669.         m := 0.1;
  2670.         ndigits := 0;
  2671.         StringLength := length(str);
  2672.         i := 0;
  2673.         repeat
  2674.             i := i + 1;
  2675.         until (str[i] in ['0'..'9', '-', '.']) or (i >= StringLength);
  2676.         c := str[i];
  2677.         repeat
  2678.             if c = '-' then
  2679.                 negative := true
  2680.             else if c = '.' then
  2681.                 LeftOfPoint := false
  2682.             else if (c >= '0') and (c <= '9') then begin
  2683.                     ndigits := ndigits + 1;
  2684.                     if LeftOfPoint then
  2685.                         n := n * 10.0 + ord(c) - ord('0')
  2686.                     else begin
  2687.                             n := n + (ord(c) - ord('0')) * m;
  2688.                             m := m * 0.1;
  2689.                         end;
  2690.                 end;
  2691.             i := i + 1;
  2692.             if i <= StringLength then
  2693.                 c := str[i];
  2694.         until not (c in ['0'..'9', '-', '.']) or (i > StringLength);
  2695.         if (c = 'e') or (c = 'E') then begin
  2696.                 NegExp := false;
  2697.                 exponent := 0;
  2698.                 i := i + 1;
  2699.                 if i <= StringLength then
  2700.                     c := str[i];
  2701.                 if (c = '+') or (c = '-') then begin
  2702.                         if c = '-' then
  2703.                             NegExp := true;
  2704.                         i := i + 1;
  2705.                         if i <= StringLength then
  2706.                             c := str[i];
  2707.                     end;
  2708.                 repeat
  2709.                     if (c >= '0') and (c <= '9') then
  2710.                         exponent := exponent * 10 + ord(c) - ord('0');
  2711.                     i := i + 1;
  2712.                     if i <= StringLength then
  2713.                         c := str[i];
  2714.                 until not (c in ['0'..'9']) or (i > StringLength);
  2715.                 if negExp then
  2716.                     exponent := -exponent;
  2717.                 if exponent <> 0 then
  2718.                     n := n * exp(exponent * ln(10));
  2719.             end; {if c='e'}
  2720.         if ndigits = 0 then
  2721.             n := BadReal
  2722.         else if negative then
  2723.             n := -n;
  2724.         StringToReal := n;
  2725.     end;
  2726.  
  2727. end.