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

  1. unit Utilities;
  2.  
  3. {Miscellaneous utility routines used by NIH Image}
  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 GeString('Back.', fwidth);
  18.                                 PutTabDelimeter;
  19.                             end;
  20.                         if MinMaxM in measurements then begin
  21.                                 PutFString('Min', fwidth);
  22.                                 PutTabDelimeter;
  23.                                 PutFString('Max', fwidth);
  24.                                 PutTabDelimeter;
  25.                             end;
  26.                         if User1M in measurements then begin
  27.                                 PutFString(User1Label, fwidth);
  28.                                 PutTabDelimeter;
  29.                             end;
  30.                         if User2M in measurements then begin
  31.                                 PutFString(User2Label, fwidth);
  32.                                 PutTabDelimeter;
  33.                             end;
  34.                         PutChar(cr);
  35.                         PutChar(cr);
  36.                     end;
  37.                 for i := FirstCount to LastCount do begin
  38.                         column := 0;
  39.                         if Headings then
  40.                             PutSequenceNumber;
  41.                         if AreaM in measurements then begin
  42.                                 PutReal(mArea^[i], fwidth, precision);
  43.                                 PutTabDelimeter;
  44.                             end;
  45.                         if MeanM in measurements then begin
  46.                                 PutReal(mean^[i], fwidth, precision);
  47.                                 PutTabDelimeter;
  48.                             end;
  49.                         if StdDevM in measurements then begin
  50.                                 PutReal(sd^[i], fwidth, precision);
  51.                                 PutTabDelimeter;
  52.                             end;
  53.                         if (xyLocM in measurements) or (nPoints > 0) then begin
  54.                                 PutReal(xcenter^[i], fwidth, precision);
  55.                                 PutTab;
  56.                                 PutReal(ycenter^[i], fwidth, precision);
  57.                                 PutTabDelimeter;
  58.                             end;
  59.                         if ModeM in measurements then begin
  60.                                 PutReal(mode^[i], fwidth, precision);
  61.                                 PutTabDelimeter;
  62.                             end;
  63.                         if (LengthM in measurements) or (nLengths > 0) then begin
  64.                                 PutReal(plength^[i], fwidth, precision);
  65.                                 PutTabDelimeter;
  66.                             end;
  67.                         if MajorAxisM in measurements then begin
  68.                                 PutReal(MajorAxis^[i], fwidth, precision);
  69.                                 PutTabDelimeter;
  70.                             end;
  71.                         if MinorAxisM in measurements then begin
  72.                                 PutReal(MinorAxis^[i], fwidth, precision);
  73.                                 PutTabDelimeter;
  74.                             end;
  75.                         if (AngleM in measurements) or (nAngles > 0) then begin
  76.                                 PutReal(orientation^[i], fwidth, precision);
  77.                                 PutTabDelimeter;
  78.                             end;
  79.                         if IntDenM in measurements then begin
  80.                                 PutReal(IntegratedDensity^[i], fwidth + 2, precision);
  81.                                 PutTabDelimeter;
  82.                                 PutReal(idBackground^[i], fwidth, precision);
  83.                                 PutTabDelimeter;
  84.                             end;
  85.                         if MinMaxM in measurements then begin
  86.                                 PutReal(mMin^[i], fwidth, precision);
  87.                                 PutTabDelimeter;
  88.                                 PutReal(mMax^[i], fwidth, precision);
  89.                                 PutTabDelimeter;
  90.                             end;
  91.                         if User1M in measurements then begin
  92.                                 PutReal(User1^[i], fwidth, precision);
  93.                                 PutTabDelimeter;
  94.                             end;
  95.                         if User2M in measurements then begin
  96.                                 PutReal(User2^[i], fwidth, precision);
  97.                                 PutTabDelimeter;
  98.                             end;
  99.                         PutChar(cr);
  100.                     end; {for}
  101.             end; {with}
  102.     end;
  103.  
  104.  
  105.     procedure ShowWatch;
  106.     begin
  107.         SetCursor(watch);
  108.     end;
  109.  
  110.  
  111.     procedure ShowAnimatedWatch;
  112.     begin
  113.         SetCursor(AnimatedWatch[WatchIndex]);
  114.         WatchIndex := WatchIndex + 1;
  115.         if WatchIndex > 8 then
  116.             WatchIndex := 1;
  117.     end;
  118.  
  119.  
  120.     procedure DoOperation;{(Operation:OpType)}
  121.         var
  122.             tPort: GrafPtr;
  123.             loc: point;
  124.             width, height, SaveWidth: integer;
  125.             tRect: rect;
  126.             SaveGDevice: GDHandle;
  127.     begin
  128.         SaveGDevice := GetGDevice;
  129.         GetPort(tPort);
  130.         with Info^ do begin
  131.                 changes := true;
  132.                 SetGDevice(osGDevice);
  133.                 SetPort(GrafPtr(osPort));
  134.                 pmForeColor(ForegroundIndex);
  135.                 pmBackColor(BackgroundIndex);
  136.                 PenNormal;
  137.                 case Operation of
  138.                     InvertOp: 
  139.                         InvertRgn(roiRgn);
  140.                     PaintOp: 
  141.                         PaintRgn(roiRgn);
  142.                     FrameOp:  begin
  143.                             if (RoiType = LineRoi) or (RoiType = FreeLineRoi) or (RoiTYpe = SegLineRoi) then
  144.                                 PenSize(1, 1)
  145.                             else
  146.                                 PenSize(LineWidth, LineWidth);
  147.                             FrameRgn(roiRgn);
  148.                         end;
  149.                     EraseOp: 
  150.                         EraseRgn(roiRgn);
  151.                     PasteOp: 
  152.                         Paste;
  153.                     otherwise
  154.                 end;
  155.                 if not RoiShowing then
  156.                     UpdateScreen(RoiRect);
  157.                 if PixMapSize > UndoBufSize then
  158.                     OpPending := false;
  159.             end;
  160.         SetPort(tPort);
  161.         SetGDevice(SaveGDevice);
  162.     end;
  163.  
  164.  
  165.     procedure SaveRoi;
  166.     begin
  167.         with info^ do
  168.             if RoiType <> noRoi then begin
  169.                     NoInfo^.roiType := roiType;
  170.                     NoInfo^.RoiRect := RoiRect;
  171.                     CopyRgn(roiRgn, NoInfo^.roiRgn);
  172.                     NoInfo^.LX1 := LX1;
  173.                     NoInfo^.LY1 := LY1;
  174.                     NoInfo^.LX2 := LX2;
  175.                     NoInfo^.LY2 := LY2;
  176.                     NoInfo^.LAngle := LAngle;
  177.                 end;
  178.     end;
  179.  
  180.  
  181.     procedure KillRoi;
  182.         var
  183.             trect: rect;
  184.     begin
  185.         with info^ do begin
  186.                 if RoiShowing then begin
  187.                         if OpPending then begin
  188.                                 OpPending := false;
  189.                                 DoOperation(CurrentOp);
  190.                             end;
  191.                         SaveRoi;
  192.                         RoiShowing := false;
  193.                         trect := RoiRect;
  194.                         if RoiType = LineRoi then
  195.                             InsetRect(trect, -RoiHandleSize, -RoiHandleSize);
  196.                         UpdateScreen(trect);
  197.                     end;
  198.                 RoiType := NoRoi;
  199.                 RoiUpdateTime := 0;
  200.             end;
  201.     end;
  202.  
  203.  
  204.     procedure CaptureImage;
  205.         var
  206.             Timeout: LongInt;
  207.     begin
  208.         case FrameGrabber of
  209.             QuickCapture:  begin
  210.                     ControlReg^ := BitAnd($80, 255); {Start frame capture}
  211.                     while ControlReg^ < 0 do
  212.                         ;       {Wait for it to complete}
  213.                 end;
  214.             ScionLG3:  begin
  215.                     TimeOut := TickCount + 30;  {1/2sec. timeout}
  216.                     ControlReg^ := $80; {Start frame capture}
  217.                     while BitAnd(ControlReg^, $80) = $00 do begin    {Wait for it to complete}
  218.                             if TickCount > TimeOut then begin
  219.                                     ControlReg^ := $00;
  220.                                     leave
  221.                                 end;
  222.                         end;
  223.                     ControlReg^ := $00;
  224.                 end;
  225.         end; {case}
  226.     end;
  227.  
  228.  
  229.     procedure Paste;
  230.         var
  231.             srcPort: cGrafPtr;
  232.     begin
  233.         if info = NoInfo then begin
  234.                 beep;
  235.                 exit(Paste)
  236.             end;
  237.         with Info^ do begin
  238.                 if not RoiShowing then
  239.                     exit(Paste);
  240.                 if PasteTransferMode = SrcCopy then begin
  241.                         pmForeColor(BlackIndex);
  242.                         pmBackColor(WhiteIndex);
  243.                     end;
  244.                 srcPort := ClipBufInfo^.osPort;
  245.                 if LivePasteMode then
  246.                     if ((WhatsOnClip = CameraPic) or (WhatsOnClip = LivePic)) and (PictureType <> FrameGrabberType) then begin
  247.                             CaptureImage;
  248.                             srcPort := fgPort;
  249.                         end;
  250.                 hlock(handle(srcPort^.portPixMap));
  251.                 hlock(handle(osPort^.portPixMap));
  252.                 CopyBits(BitMapHandle(srcPort^.portPixMap)^^, BitMapHandle(osPort^.PortPixMap)^^, ClipBufInfo^.RoiRect, RoiRect, PasteTransferMode, roiRgn);
  253.                 hunlock(handle(srcPort^.portPixMap));
  254.                 hunlock(handle(osPort^.PortPixMap));
  255.                 if PasteTransferMode = SrcCopy then begin
  256.                         pmForeColor(ForegroundIndex);
  257.                         pmBackColor(BackgroundIndex);
  258.                     end;
  259.             end;
  260.     end;
  261.  
  262.  
  263.     procedure ShowRoi;
  264.     begin
  265.         with info^ do
  266.             if RoiType <> NoRoi then begin
  267.                     SetupUndo;
  268.                     RoiShowing := true;
  269.                 end;
  270.     end;
  271.  
  272.  
  273.     procedure SetupUndo;
  274.         var
  275.             line: integer;
  276.     begin
  277.         WhatToUndo := NothingToUndo;
  278.         if info = NoInfo then begin
  279.                 CurrentUndoSize := 0;
  280.                 exit(SetupUndo)
  281.             end;
  282.         with info^ do begin
  283.                 if PixMapSize > UndoBufSize then begin
  284.                         CurrentUndoSize := 0;
  285.                         exit(SetupUndo)
  286.                     end;
  287.                 if OpPending then begin
  288.                         DoOperation(CurrentOp);
  289.                         OpPending := false;
  290.                     end;
  291.                 CurrentUndoSize := PixMapSize;
  292.                 BlockMove(PicBaseAddr, UndoBuf, PixMapSize);
  293.                 UndoFromClip := false;
  294.                 RedoSelection := false;
  295.             end;
  296.     end;
  297.  
  298.  
  299.     procedure SetupUndoFromClip;
  300.         var
  301.             line: integer;
  302.     begin
  303.         WhatToUndo := NothingToUndo;
  304.         if info = NoInfo then begin
  305.                 CurrentUndoSize := 0;
  306.                 exit(SetupUndoFromClip)
  307.             end;
  308.         with info^ do begin
  309.                 if PixMapSize > ClipBufSize then begin
  310.                         CurrentUndoSize := 0;
  311.                         exit(SetupUndoFromClip)
  312.                     end;
  313.                 if OpPending then begin
  314.                         DoOperation(CurrentOp);
  315.                         OpPending := false;
  316.                     end;
  317.                 CurrentUndoSize := PixMapSize;
  318.                 BlockMove(PicBaseAddr, ClipBuf, PixMapSize);
  319.             end;
  320.         WhatsOnClip := NothingOnClip;
  321.         UndofromClip := true;
  322.         RedoSelection := false;
  323.     end;
  324.  
  325.  
  326.     function NoSelection;{:boolean}
  327.     begin
  328.         if Info = NoInfo then begin
  329.                 beep;
  330.                 NoSelection := true;
  331.                 exit(NoSelection);
  332.             end;
  333.         if not Info^.RoiShowing then begin
  334.                 PutMessage('Please use a selection tool to make a selection or use the Select All command.');
  335.                 macro := false;
  336.             end;
  337.         NoSelection := not Info^.RoiShowing;
  338.     end;
  339.  
  340.  
  341.     function NotRectangular;{:boolean}
  342.     begin
  343.         with info^ do
  344.             if RoiShowing and (RoiType <> RectRoi) then begin
  345.                     PutMessage('This operation requires a rectangular selection.');
  346.                     NotRectangular := true;
  347.                     macro := false;
  348.                 end
  349.             else
  350.                 NotRectangular := false;
  351.     end;
  352.  
  353.  
  354.     procedure GetLoi (var x1, y1, x2, y2: real);
  355.     begin
  356.         with info^, info^.RoiRect do begin
  357.                 x1 := left + LX1;
  358.                 y1 := top + LY1;
  359.                 x2 := left + LX2;
  360.                 y2 := top + LY2;
  361.             end;
  362.     end;
  363.  
  364.  
  365.     function NotInBounds;{:boolean}
  366.         var
  367.             x1, y1, x2, y2: real;
  368.     begin
  369.         NotInBounds := false;
  370.         with info^, info^.RoiRect do
  371.             if RoiShowing then begin
  372.                     if RoiType = LineRoi then begin
  373.                             GetLoi(x1, y1, x2, y2);
  374.                             if (x1 >= 0.0) and (y1 >= 0.0) and (x2 <= right) and (y2 <= bottom) then
  375.                                 exit(NotInBounds);
  376.                         end;
  377.                     if (left < 0) or (top < 0) or (right > PicRect.right) or (bottom > PicRect.bottom) then begin
  378.                             PutMessage('This operation requires the selection to be entirely within the image.');
  379.                             NotInBounds := true;
  380.                             macro := false;
  381.                         end;
  382.                 end;
  383.     end;
  384.  
  385.  
  386.     function NoUndo: boolean;
  387.         var
  388.             ImageTooLarge: boolean;
  389.     begin
  390.         with info^ do
  391.             ImageTooLarge := (PixMapSize > ClipBufSize) or (PixMapSize > UndoBufSize);
  392.         if ImageTooLarge then
  393.             PutMessage('This operation requires that the Undo and Clipboard buffers be at least as large as the image.');
  394.         NoUndo := ImageTooLarge;
  395.     end;
  396.  
  397.  
  398. {$POP}
  399.  
  400.  
  401.     procedure PutMemoryAlert;
  402.     begin
  403.         PutMessage('There is not enough free memory to open this image. Try closing some windows or allocating more memory to NIH Image.');
  404.         macro := false;
  405.     end;
  406.  
  407.  
  408.     procedure CompactMemory;
  409.         var
  410.             size: LongInt;
  411.             TempInfo: InfoPtr;
  412.             i: integer;
  413.     begin
  414.         for i := 1 to nPics do begin
  415.                 TempInfo := pointer(WindowPeek(PicWindow[i])^.RefCon);
  416.                 hunlock(TempInfo^.PicBaseHandle)
  417.             end;
  418.         size := MaxSize;
  419.         size := MaxMem(size);
  420.         for i := 1 to nPics do begin
  421.                 TempInfo := pointer(WindowPeek(PicWindow[i])^.RefCon);
  422.                 with TempInfo^ do begin
  423.                         hlock(PicBaseHandle);
  424.                         PicBaseAddr := StripAddress(PicBaseHandle^);
  425.                         osPort^.PortPixMap^^.BaseAddr := PicBaseAddr;
  426.                     end;
  427.             end;
  428.     end;
  429.  
  430.  
  431.  
  432.     function GetBigHandle (NeededSize: LongInt): handle;
  433. {Allocates a handle and guarantees MinFree contiguous free bytes after allocation . }
  434. {Does NOT arrange for the new handle to be unlocked during CompactMemory. }
  435. {GetBigHandle returns nil if CompactMemory fails to obtain enough contiguous free space . }
  436.         var
  437.             h: handle;
  438.             FreeMem: LongInt;
  439.     begin
  440.         h := NewHandle(NeededSize);
  441.         FreeMem := MaxBlock;
  442.         if (h = nil) or (FreeMem < MinFree) then begin
  443.                 if h <> nil then
  444.                     DisposHandle(h);
  445.                 if FreeMem > 0 then {Why does FreeMem get set to 0 sometimes and MaxMem}
  446.                     CompactMemory       {crash, but only when using the Modern Memory Manager?}
  447.                 else
  448.                     beep;
  449.                 h := NewHandle(NeededSize);
  450.                 FreeMem := MaxBlock;
  451.             end;
  452.         if (h = nil) or (FreeMem < MinFree) then begin
  453.                 if h <> nil then
  454.                     DisposHandle(h);
  455.                 h := nil;
  456.             end;
  457.         GetBigHandle := h;
  458.     end;
  459.  
  460.  
  461.     function GetImageMemory (SaveInfo: infoPtr): ptr;
  462. {Allocates memory for the PixMap of new image windows. SaveInfo points to the InfoRec of the previous window.}
  463. {A handle is used, rather than a pointer, since NewPtr(particularly on the ci and fx) is rediculously slow.}
  464.         var
  465.             h: handle;
  466.             NeededSize: LongInt;
  467.     begin
  468.         with info^ do begin
  469.                 if odd(PixelsPerLine) then
  470.                     BytesPerRow := PixelsPerLine + 1
  471.                 else
  472.                     BytesPerRow := PixelsPerLine;
  473.                 PixMapSize := LongInt(nlines) * BytesPerRow;
  474.                 ImageSize := LongInt(nlines) * PixelsPerLine;
  475.                 NeededSize := PixMapSize;
  476.             end;
  477.         h := GetBigHandle(NeededSize);
  478.         if h = nil then begin
  479.                 DisposPtr(pointer(Info));
  480.                 PutMemoryAlert;
  481.                 Info := SaveInfo;
  482.                 GetImageMemory := nil;
  483.                 exit(GetImageMemory);
  484.             end;
  485.         with info^ do begin
  486.                 PicBaseHandle := h;
  487.                 hlock(PicBaseHandle);
  488.                 GetImageMemory := StripAddress(PicBaseHandle^);
  489.             end;
  490.     end;
  491.  
  492.  
  493. {$PUSH}
  494. {$D-}
  495.  
  496.     procedure UpdateAnalysisMenu;
  497.         var
  498.             ShowItems: boolean;
  499.             i: integer;
  500.     begin
  501.         ShowItems := Info <> NoInfo;
  502.         SetMenuItem(AnalyzemenuH, MeasureItem, ShowItems);
  503.         SetMenuItem(AnalyzemenuH, AnalyzeItem, ShowItems);
  504.         SetMenuItem(AnalyzemenuH, HistogramItem, ShowItems);
  505.         SetMenuItem(AnalyzemenuH, PlotItem, ShowItems);
  506.         SetMenuItem(AnalyzemenuH, PlotSurfaceItem, ShowItems);
  507.         SetMenuItem(AnalyzemenuH, SetScaleItem, ShowItems);
  508.         SetMenuItem(AnalyzemenuH, CalibrateItem, ShowItems);
  509.         SetMenuItem(AnalyzemenuH, RedoItem, mCount > 0);
  510.         SetMenuItem(AnalyzemenuH, DeleteItem, mCount > 0);
  511.         SetMenuItem(AnalyzemenuH, RestoreItem, ShowItems and (NoInfo^.RoiType <> NoRoi));
  512.         SetMenuItem(AnalyzemenuH, MarkItem, info^.RoiShowing);
  513.     end;
  514.  
  515.  
  516.     procedure ExtendWindowsMenu;{(fname:str255; size:LongInt; wptr:WindowPtr)}
  517.         var
  518.             str, SizeStr: str255;
  519.     begin
  520.         if nPics < MaxPics then begin
  521.                 nPics := nPics + 1;
  522.                 PicWindow[nPics] := wptr;
  523.                 NumToString((size + 511) div 1024, SizeStr);
  524.                 str := concat(fname, '  ', SizeStr, 'K');
  525.                 AppendMenu(WindowsMenuH, ' ');
  526.                 SetItem(WindowsMenuH, nPics + WindowsMenuItems + nTextWindows, str);
  527.                 InsertMenu(WindowsMenuH, 0);
  528.             end;
  529.     end;
  530.  
  531.  
  532.     procedure InvertGrayLevels;
  533.     begin
  534.         with info^ do begin
  535.                 DensityCalibrated := true;
  536.                 nCoefficients := 2;
  537.                 fit := StraightLine;
  538.                 Coefficient[1] := 255.0;
  539.                 Coefficient[2] := -1.0;
  540.                 ZeroClip := false;
  541.                 UpdateTitleBar;
  542.                 GenerateValues;
  543.             end;
  544.     end;
  545.  
  546.  
  547.     procedure GetAngle (dx, dy: real; var angle: real);
  548.         var
  549.             quadrant: (q1, q2orq3, q4);
  550.     begin
  551.         if dx <> 0.0 then
  552.             angle := arctan(dy / dx)
  553.         else begin
  554.                 if dy >= 0.0 then
  555.                     angle := pi / 2.0
  556.                 else
  557.                     angle := -pi / 2.0
  558.             end;
  559.         angle := (180.0 / pi) * angle;
  560.         if (dx >= 0.0) and (dy >= 0.0) then
  561.             quadrant := q1
  562.         else if dx < 0.0 then
  563.             quadrant := q2orq3
  564.         else
  565.             quadrant := q4;
  566.         case quadrant of
  567.             q1: 
  568.                 ;
  569.             q2orq3: 
  570.                 angle := angle + 180.0;
  571.             q4: 
  572.                 angle := angle + 360.0;
  573.         end;
  574.     end;
  575.  
  576.  
  577.     procedure MakeRegion;
  578.         var
  579.             deltax, deltay, x1, y1, x2, y2, xt, yt: integer;
  580.             dx, dy, pAngle: real;
  581.             add: boolean;
  582.             tPort: GrafPtr;
  583.     begin
  584.         with info^ do begin
  585.                 GetPort(tPort);
  586.                 SetPort(wptr);
  587.                 OpenRgn;
  588.                 case RoiType of
  589.                     LineRoi:  begin
  590.                             GetAngle(LX2 - LX1, LY1 - LY2, LAngle);
  591.                             x1 := round(LX1);
  592.                             y1 := round(LY1);
  593.                             x2 := round(LX2);
  594.                             y2 := round(LY2);
  595.                             if (x1 = x2) and (y1 = y2) then begin
  596.                                     MoveTo(x1, y1);
  597.                                     LineTo(x1 + 1, y1);
  598.                                     LineTo(x1 + 1, y1 + 1);
  599.                                     LineTo(x1, y1 + 1);
  600.                                     LineTo(x1, y1);
  601.                                 end
  602.                             else begin
  603.                                     add := (LAngle > 90.0) and (LAngle <= 270.0);
  604.                                     pAngle := (LAngle / 180.0) * pi;
  605.                                     if add then
  606.                                         pAngle := pAngle + pi / 2.0
  607.                                     else
  608.                                         pAngle := pAngle - pi / 2.0;
  609.                                     dx := cos(pAngle) * LineWidth;
  610.                                     dy := -sin(pAngle) * LineWidth;
  611.                                     MoveTo(x1, y1);
  612.                                     LineTo(round(x1 + dx), round(y1 + dy));
  613.                                     LineTo(round(x2 + dx), round(y2 + dy));
  614.                                     LineTo(x2, y2);
  615.                                     LineTo(x1, y1);
  616.                                 end;
  617.                         end;
  618.                     OvalRoi: 
  619.                         FrameOval(RoiRect);
  620.                     RectRoi: 
  621.                         FrameRect(RoiRect);
  622.                     otherwise
  623.                 end;
  624.                 CloseRgn(roiRgn);
  625.                 if RoiType = LineRoi then begin
  626.                         RoiRect := roiRgn^^.rgnBBox;
  627.                         with RoiRect do begin
  628.                                 LX1 := LX1 - left;
  629.                                 LY1 := LY1 - top;
  630.                                 LX2 := LX2 - left;
  631.                                 LY2 := LY2 - top;
  632.                             end;
  633.                     end;
  634.             end;
  635.         SetPort(tPort);
  636.     end;
  637.  
  638.  
  639.     procedure SelectAll;{(visible:boolean)}
  640.         var
  641.             loc: point;
  642.             tPort: GrafPtr;
  643.     begin
  644.         if info <> NoInfo then
  645.             with Info^ do begin
  646.                     KillRoi;
  647.                     RoiType := RectRoi;
  648.                     RoiRect := PicRect;
  649.                     MakeRegion;
  650.                     if visible then begin
  651.                             SetupUndo;
  652.                             RoiShowing := true;
  653.                             if (magnification > 1.0) and not ScaleToFitWindow then
  654.                                 Unzoom;
  655.                             if not macro then begin
  656.                                     PreviousTool := CurrentTool;
  657.                                     CurrentTool := SelectionTool;
  658.                                     isSelectionTool := true;
  659.                                     GetPort(tPort);
  660.                                     SetPort(ToolWindow);
  661.                                     EraseRect(ToolRect[PreviousTool]);
  662.                                     EraseRect(ToolRect[CurrentTool]);
  663.                                     InvalRect(ToolRect[PreviousTool]);
  664.                                     InvalRect(ToolRect[CurrentTool]);
  665.                                     SetPort(tPort);
  666.                                 end;
  667.                         end;
  668.                     IsInsertionPoint := false;
  669.                     measuring := false;
  670.                 end; {with}
  671.     end;
  672.  
  673.  
  674.     procedure KillOperation;
  675.     begin
  676.         if OpPending then
  677.             with info^ do
  678.                 if info <> NoInfo then begin
  679.                         DoOperation(CurrentOp);
  680.                         RoiShowing := false;
  681.                         UpdateScreen(RoiRect);
  682.                         OpPending := false;
  683.                     end;
  684.     end;
  685.  
  686.  
  687.     procedure CloneInfo (var OldInfo, NewInfo: PicInfo);
  688.     begin
  689.         NewInfo := OldInfo;
  690.         with NewInfo do begin
  691.                 PicBaseAddr := nil;
  692.                 PicBaseHandle := nil;
  693.                 osPort := nil;
  694.                 roiRgn := nil;
  695.                 RoiType := NoRoi;
  696.                 RoiShowing := false;
  697.                 Magnification := 1.0;
  698.                 vref := 0;
  699.                 wPtr := nil;
  700.                 ScaleToFitWindow := false;
  701.                 WindowState := NormalWindow;
  702.                 StackInfo := nil;
  703.                 iversion := 0;
  704.                 PictureType := NewPicture;
  705.                 DataType := EightBits;
  706.                 changes := false;
  707.                 DataH := nil;
  708.                 LittleEndian := false;
  709.             end;
  710.     end;
  711.  
  712.  
  713.     function NewPicWindow (name: str255; width, height: integer): boolean;
  714.         var
  715.             iptr, p: ptr;
  716.             lptr: ^LongInt;
  717.             SaveInfo: InfoPtr;
  718.             NeededSize: LongInt;
  719.             trect: rect;
  720.     begin
  721.         NewPicWindow := false;
  722.         PicLeft := PicLeftBase;
  723.         PicTop := PicTopBase;
  724.         if (info <> noInfo) then begin
  725.                 with info^ do begin
  726.                         GetWindowRect(wptr, trect);
  727.                         if trect.left = PicLeftBase then
  728.                             if pos('Camera', name) = 0 then begin
  729.                                     PicLeft := trect.left + hPicOffset;
  730.                                     PicTop := trect.top + vPicOffset;
  731.                                 end;
  732.                     end;
  733.             end;
  734.         if nPics = MaxPics then
  735.             exit(NewPicWindow);
  736.         KillOperation;
  737.         DisableDensitySlice;
  738.         SaveInfo := Info;
  739.         iptr := NewPtr(SizeOf(PicInfo));
  740.         if iptr = nil then begin
  741.                 PutMemoryAlert;
  742.                 macro := false;
  743.                 exit(NewPicWindow);
  744.             end;
  745.         Info := pointer(iptr);
  746.         CloneInfo(SaveInfo^, Info^);
  747.         with Info^ do begin
  748.                 nlines := height;
  749.                 PixelsPerLine := width;
  750.                 p := GetImageMemory(SaveInfo);
  751.                 if p = nil then
  752.                     exit(NewPicWindow);
  753.                 PicBaseAddr := p;
  754.                 MakeNewWindow(name);
  755.                 SelectAll(false);
  756.                 DoOperation(EraseOp);
  757.                 KillRoi;
  758.                 Changes := false;
  759.                 BinaryPic := false;
  760.             end;
  761.         NewPicWindow := true;
  762.     end;
  763.  
  764.  
  765.     procedure EraseScreen;
  766.     begin
  767.         SetPort(GrafPtr(CScreenPort));
  768.         with CScreenPort^ do begin
  769.                 HideCursor;
  770.                 pmBackColor(BackgroundIndex);
  771.                 EraseRect(portPixMap^^.Bounds);
  772.                 pmBackColor(WhiteIndex);
  773.             end;
  774.     end;
  775.  
  776.  
  777.     procedure RestoreScreen;
  778.         var
  779.             GrayRgn: RgnHandle;
  780.             rptr: rhptr;
  781.             wp: ^WindowPtr;
  782.     begin
  783.         rptr := rhptr(GrayRgnGlobal);
  784.         GrayRgn := rptr^;
  785.         wp := pointer(GhostWindow);
  786.         wp^ := WindowPtr(nil);
  787.         PaintBehind(WindowPeek(FrontWindow), GrayRgn);
  788.         wp^ := PasteControl;
  789.         DrawMenuBar;
  790.     end;
  791.  
  792.  
  793.     procedure UpdateTitleBar;
  794.     {Updates the window title bar to show the current magnification or the current frame within a stack.}
  795.         var
  796.             str, str2, str3: str255;
  797.     begin
  798.         with info^ do begin
  799.                 str := title;
  800.                 if SpatiallyCalibrated then
  801.                     str := concat(str, chr($13)); {Black Diamond}
  802.                 if DensityCalibrated then
  803.                     str := concat(str, 'â—Š');
  804.                 if StackInfo <> nil then
  805.                     with StackInfo^ do begin
  806.                             NumToString(CurrentSlice, str2);
  807.                             NumToString(nSlices, str3);
  808.                             str := concat(str, '(', str2, '/', str3, ')');
  809.                         end
  810.                 else if (magnification <> 1.0) or ScaleToFitWindow then begin
  811.                         if ScaleToFitWindow then begin
  812.                                 RealToString(magnification, 1, 2, str2);
  813.                                 str := concat(str, '(', str2, ')');
  814.                             end
  815.                         else begin
  816.                                 RealToString(magnification, 1, 0, str2);
  817.                                 str := concat(str, '(', str2, ':1)');
  818.                             end;
  819.                     end;
  820.                 if Digitizing then begin
  821.                         if ExternalTrigger then
  822.                             str := concat(str, '(Waiting for Trigger)')
  823.                         else
  824.                             str := concat(str, '(Live)');
  825.                     end;
  826.                 if wptr <> nil then
  827.                     SetWTitle(wptr, str);
  828.             end; {with}
  829.     end;
  830.  
  831.  
  832.     procedure ScaleToFit;
  833.         var
  834.             trect: rect;
  835.     begin
  836.         if digitizing then
  837.             exit(ScaleToFit);
  838.         if info <> NoInfo then
  839.             with info^ do begin
  840.                     ScaleToFitWindow := not ScaleToFitWindow;
  841.                     KillRoi;
  842.                     if ScaleToFitWindow then begin
  843.                             savewrect := wrect;
  844.                             SaveSrcRect := SrcRect;
  845.                             SaveMagnification := magnification;
  846.                             GetWindowRect(wptr, trect);
  847.                             savehloc := trect.left;
  848.                             savevloc := trect.top;
  849.                             wrect := wptr^.PortRect;
  850.                             SrcRect := PicRect;
  851.                             ScaleImageWindow(wrect);
  852.                             SizeWindow(wptr, wrect.right, wrect.bottom, true);
  853.                         end
  854.                     else begin
  855.                             if WindowState = TiledBigScaled then begin
  856.                                     wrect := initwrect;
  857.                                     SrcRect := wrect;
  858.                                     magnification := 1.0;
  859.                                     WindowState := NormalWindow;
  860.                                 end
  861.                             else begin
  862.                                     wrect := savewrect;
  863.                                     SrcRect := SaveSrcRect;
  864.                                     magnification := SaveMagnification;
  865.                                 end;
  866.                             HideWindow(wptr);
  867.                             SizeWindow(wptr, wrect.right, wrect.bottom, true);
  868.                             MoveWindow(wptr, savehloc, savevloc, true);
  869.                             ShowWindow(wptr);
  870.                             UpdateTitleBar;
  871.                         end;
  872.                     SetPort(wptr);
  873.                     InvalRect(wrect);
  874.                     WindowState := NormalWindow;
  875.                 end;
  876.     end;
  877.  
  878.  
  879.     procedure DrawMyGrowIcon;{(w:WindowPtr)}
  880.         var
  881.             tPort: GrafPtr;
  882.             tRect: rect;
  883.     begin
  884.         GetPort(tPort);
  885.         SetPort(w);
  886.         PenNormal;
  887.         with w^.PortRect do begin
  888.                 SetRect(tRect, right - 12, bottom - 12, right - 5, bottom - 5);
  889.                 FrameRect(tRect);
  890.                 MoveTo(right - 6, bottom - 10);
  891.                 LineTo(right - 2, bottom - 10);
  892.                 LineTo(right - 2, bottom - 2);
  893.                 LineTo(right - 10, bottom - 2);
  894.                 LineTo(right - 10, bottom - 6);
  895.             end;
  896.         SetPort(tPort);
  897.     end;
  898.  
  899.  
  900.     procedure Unzoom;
  901.     begin
  902.         if Info <> NoInfo then
  903.             with Info^ do begin
  904.                     if ScaleToFitWindow then
  905.                         ScaleToFit
  906.                     else begin
  907.                             wrect := initwrect;
  908.                             SrcRect := wrect;
  909.                         end;
  910.                     SizeWindow(wptr, wrect.right, wrect.bottom, true);
  911.                     LoadLUT(info^.cTable);
  912.                     UpdatePicWindow;
  913.                     magnification := 1.0;
  914.                     DrawMyGrowIcon(wptr);
  915.                     UpdateTitleBar;
  916.                     if WhatToUndo = UndoZoom then
  917.                         WhatToUndo := NothingToUndo;
  918.                     ShowRoi;
  919.                 end;
  920.     end;
  921.  
  922.  
  923.     procedure DrawBString;{(str:string)}
  924.     begin
  925.         TextFace([bold]);
  926.         DrawString(str);
  927.         TextFace([]);
  928.     end;
  929.  
  930.  
  931.     function long2str (num: LongInt): str255;
  932.         var
  933.             str: str255;
  934.     begin
  935.         NumToString(num, str);
  936.         long2str := str;
  937.     end;
  938.  
  939.  
  940.     procedure PutWarning;
  941.     begin
  942.         PutMessage(concat('This ', long2str((info^.PixmapSize + 511) div 1024), 'K image is larger than the ', long2str(UndoBufSize div 1024), 'K Undo buffer. Many operations may fail or be Undoable.'));
  943.     end;
  944.  
  945.  
  946.     procedure SetupRoiRect;
  947. {Copies the current image to Undo buffer so it can be used for drawing}
  948. {the "marching ants". The copy of the previous image in the Clipboard buffer}
  949. { buffer will be used for Undo.}
  950.         var
  951.             SaveWhatToUndo: WhatToUndoType;
  952.     begin
  953.         SaveWhatToUndo := WhatToUndo;
  954.         SetupUndo;
  955.         UndoFromClip := true;
  956.         info^.RoiShowing := true;
  957.         WhatToUndo := SaveWhatToUndo;
  958.     end;
  959.  
  960.  
  961.     procedure SetForegroundColor (color: integer);
  962.         var
  963.             tPort: GrafPtr;
  964.             SaveGDevice: GDHandle;
  965.     begin
  966.         if (color >= 0) and (color <= 255) then
  967.             with info^ do begin
  968.                     ForegroundIndex := color;
  969.                     GetPort(tPort);
  970.                     SetPort(ToolWindow);
  971.                     InvalRect(ToolRect[brush]);
  972.                     SaveGDevice := GetGDevice;
  973.                     SetGDevice(osGDevice);
  974.                     if osPort <> nil then begin
  975.                             SetPort(GrafPtr(osPort));
  976.                             pmForeColor(ForegroundIndex);
  977.                         end;
  978.                     SetPort(tPort);
  979.                     SetGDevice(SaveGDevice);
  980.                     if isInsertionPoint then
  981.                         DisplayText(true);
  982.                 end;
  983.     end;
  984.  
  985.  
  986.     procedure SetBackgroundColor (color: integer);
  987.         var
  988.             tPort: GrafPtr;
  989.             SaveGDevice: GDHandle;
  990.     begin
  991.         if (color >= 0) and (color <= 255) then
  992.             with info^ do begin
  993.                     BackgroundIndex := color;
  994.                     GetPort(tPort);
  995.                     SetPort(ToolWindow);
  996.                     InvalRect(ToolRect[eraser]);
  997.                     SaveGDevice := GetGDevice;
  998.                     SetGDevice(osGDevice);
  999.                     if osPort <> nil then begin
  1000.                             SetPort(GrafPtr(osPort));
  1001.                             pmBackColor(BackgroundIndex);
  1002.                         end;
  1003.                     SetPort(tPort);
  1004.                     SetGDevice(SaveGDevice);
  1005.                     if isInsertionPoint then
  1006.                         DisplayText(true);
  1007.                 end;
  1008.     end;
  1009.  
  1010.  
  1011.     procedure GetForegroundColor;{(event: EventRecord)}
  1012.         var
  1013.             loc: point;
  1014.             color: integer;
  1015.     begin
  1016.         loc := event.where;
  1017.         ScreenToOffScreen(loc);
  1018.         Color := MyGetPixel(loc.h, loc.v);
  1019.         SetForegroundColor(color);
  1020.     end;
  1021.  
  1022.  
  1023.     procedure GetBackgroundColor; {(event: EventRecord)}
  1024.         var
  1025.             loc: point;
  1026.             color: integer;
  1027.     begin
  1028.         loc := event.where;
  1029.         ScreenToOffScreen(loc);
  1030.         Color := MyGetPixel(loc.h, loc.v);
  1031.         SetBackgroundColor(color);
  1032.     end;
  1033.  
  1034.  
  1035.     procedure GenerateValues;
  1036.         var
  1037.             a, b, c, d, e, f, x, y: extended;
  1038.             i: integer;
  1039.     begin
  1040.         with info^ do begin
  1041.                 if not DensityCalibrated then begin
  1042.                         for i := 0 to 255 do
  1043.                             cvalue[i] := i;
  1044.                         MinValue := 0.0;
  1045.                         MaxValue := 255.0;
  1046.                         exit(GenerateValues);
  1047.                     end;
  1048.                 a := Coefficient[1];
  1049.                 b := Coefficient[2];
  1050.                 c := Coefficient[3];
  1051.                 d := Coefficient[4];
  1052.                 e := Coefficient[5];
  1053.                 f := Coefficient[6];
  1054.                 MinValue := 10e+12;
  1055.                 MaxValue := -MinValue;
  1056.                 for i := 0 to 255 do begin
  1057.                         x := i;
  1058.                         case fit of
  1059.                             StraightLine: 
  1060.                                 y := a + b * x;
  1061.                             Poly2: 
  1062.                                 y := a + b * x + c * x * x;
  1063.                             Poly3: 
  1064.                                 y := a + b * x + c * x * x + d * x * x * x;
  1065.                             Poly4: 
  1066.                                 y := a + b * x + c * x * x + d * x * x * x + e * x * x * x * x;
  1067.                             Poly5: 
  1068.                                 y := a + b * x + c * x * x + d * x * x * x + e * x * x * x * x + f * x * x * x * x * x;
  1069.                             ExpoFit: 
  1070.                                 y := a * exp(b * x);
  1071.                             PowerFit: 
  1072.                                 if x = 0.0 then
  1073.                                     y := 0.0
  1074.                                 else
  1075.                                     y := a * exp(b * ln(x)); {y=ax^b}
  1076.                             LogFit:  begin
  1077.                                     if x = 0.0 then
  1078.                                         x := 0.5;
  1079.                                     y := a * ln(b * x)
  1080.                                 end;
  1081.                             RodbardFit:  begin
  1082.                                     if x <= a then
  1083.                                         y := 0
  1084.                                     else begin
  1085.                                             y := (a - x) / (x - d);
  1086.                                             y := exp(ln(y) * (1 / b));  {y:=y**(1/b)}
  1087.                                             y := y * c;
  1088.                                         end;
  1089.                                 end;
  1090.                             UncalibratedOD:  begin
  1091.                                     if x = 255.0 then
  1092.                                         x := 254.5;
  1093.                                     y := 0.434294481 * ln(255 / (255 - x))  {log10}
  1094.                                 end;
  1095.                             otherwise
  1096.                                 y := x;
  1097.                         end; {case}
  1098.                         cvalue[i] := y;
  1099.                         if y > MaxValue then
  1100.                             MaxValue := y;
  1101.                         if y < MinValue then
  1102.                             MinValue := y;
  1103.                     end; {for}
  1104.                 if MinValue >= 0.0 then
  1105.                     ZeroClip := false;
  1106.                 if ZeroClip then begin
  1107.                         for i := 0 to 255 do
  1108.                             if cvalue[i] < 0.0 then
  1109.                                 cvalue[i] := 0.0;
  1110.                         MinValue := 0.0;
  1111.                     end;
  1112.             end;
  1113.     end;
  1114.  
  1115.  
  1116.     procedure ScaleImageWindow (var trect: rect);
  1117.         var
  1118.             WindowLeft, WindowTop: integer;
  1119.             PicAspectRatio, TempMagnification: extended;
  1120.     begin
  1121.         with info^ do begin
  1122.                 SrcRect := PicRect;
  1123.                 with CGrafPort(wptr^).PortPixMap^^.bounds do begin
  1124.                         WindowLeft := -left;
  1125.                         WindowTop := -top;
  1126.                     end;
  1127.                 with PicRect do
  1128.                     PicAspectRatio := right / bottom;
  1129.                 with trect do begin
  1130.                         if (WindowLeft + right) > (ScreenWidth - 5) then
  1131.                             right := ScreenWidth - 5 - WindowLeft;
  1132.                         bottom := round(right / PicAspectRatio);
  1133.                         if (WindowTop + bottom) > (ScreenHeight - 5) then
  1134.                             bottom := ScreenHeight - 5 - WindowTop;
  1135.                         right := round(bottom * PicAspectRatio);
  1136.                         magnification := right / PicRect.right;
  1137.                     end;
  1138.                 UpdateTitleBar;
  1139.             end; {with}
  1140.     end;
  1141.  
  1142.  
  1143.     function TooWide: boolean;
  1144.         var
  1145.             SelectionTooWide: boolean;
  1146.             MaxWidth: str255;
  1147.     begin
  1148.         with info^.RoiRect do
  1149.             SelectionTooWide := (right - left) > MaxLine;
  1150.         if SelectionTooWide then begin
  1151.                 NumToString(MaxLine, MaxWidth);
  1152.                 PutMessage(concat('This operation does not support selections wider than ', MaxWidth, ' pixels.'));
  1153.                 macro := false;
  1154.             end;
  1155.         TooWide := SelectionTooWide;
  1156.     end;
  1157.  
  1158.  
  1159.     procedure DrawTextString (str: str255; loc: point; just: integer);
  1160.         var
  1161.             SaveJust: integer;
  1162.     begin
  1163.         TextStr := str;
  1164.         IsInsertionPoint := true;
  1165.         TextStart := loc;
  1166.         SaveJust := TextJust;
  1167.         TextJust := just;
  1168.         DisplayText(false);
  1169.         TextJust := SaveJust;
  1170.         IsInsertionPoint := false;
  1171.     end;
  1172.  
  1173.  
  1174.     procedure IncrementCounter;
  1175.     begin
  1176.         if mCount < MaxMeasurements then begin
  1177.                 mCount := mCount + 1;
  1178.                 UnsavedResults := true;
  1179.             end
  1180.         else
  1181.             beep;
  1182.     end;
  1183.  
  1184.  
  1185.     procedure ClearResults (i: integer);
  1186.     begin
  1187.         mean^[i] := 0.0;
  1188.         sd^[i] := 0.0;
  1189.         PixelCount^[i] := 0;
  1190.         mArea^[i] := 0.0;
  1191.         mode^[i] := 0.0;
  1192.         IntegratedDensity^[i] := 0.0;
  1193.         idBackground^[i] := 0.0;
  1194.         xcenter^[i] := 0.0;
  1195.         ycenter^[i] := 0.0;
  1196.         MajorAxis^[i] := 0.0;
  1197.         MinorAxis^[i] := 0.0;
  1198.         orientation^[i] := 0.0;
  1199.         mMin^[i] := 0.0;
  1200.         mMax^[i] := 0.0;
  1201.         plength^[i] := 0.0;
  1202.     end;
  1203.  
  1204.     procedure UpdateFitEllipse;
  1205.     begin
  1206.         FitEllipse := (xyLocM in measurements) or (MajorAxisM in measurements) or (MinorAxisM in measurements) or (AngleM in measurements);
  1207.     end;;
  1208.                 savewrect := wrect;
  1209.                 SaveSrcRect := SrcRect;
  1210.                 SaveMagnification := magnification;
  1211.                 savehloc := wleft;
  1212.                 savevloc := wtop;
  1213.                 roiRgn := NewRgn;
  1214.                 NewPic := true;
  1215.                 ScaleToFitWindow := false;
  1216.                 OpPending := false;
  1217.                 Changes := false;
  1218.                 WindowState := NormalWindow;
  1219.                 if not DensityCalibrated and InvertPixelValues then
  1220.                     InvertGrayLevels;
  1221.                 Revertable := false;
  1222.             end;
  1223.         WhatToUndo := NothingToUndo;
  1224.     end;
  1225.  
  1226.  
  1227.     procedure MakeLowerCase (var str: str255);
  1228.         var
  1229.             i: integer;
  1230.             c: char;
  1231.     begin
  1232.         for i := 1 to length(str) do begin
  1233.                 c := str[i];
  1234.                 if (c >= 'A') and (c <= 'Z') then
  1235.                     str[i] := chr(ord(c) + 32);
  1236.             end;
  1237.     end;
  1238.  
  1239.  
  1240.     function PutMessageWithCancel (str: str255): integer;
  1241.     begin
  1242.         InitCursor;
  1243.         ParamText(str, '', '', '');
  1244.         PutMessageWithCancel := Alert(800, nil);
  1245.     end;
  1246.  
  1247.  
  1248.     function CurrentWindow: integer;
  1249.     begin
  1250.         CurrentWPtr := FrontWindow;
  1251.         if CurrentWPtr <> nil then begin
  1252.                 CurrentKind := WindowPeek(CurrentWPtr)^.WindowKind;
  1253.                 if CurrentKind = TextKind then
  1254.                     TextInfo := TextInfoPtr(WindowPeek(CurrentWPtr)^.RefCon);
  1255.                 CurrentWindow := CurrentKind;
  1256.             end
  1257.         else begin
  1258.                 CurrentWindow := 0;
  1259.                 CurrentKind := 0;
  1260.             end;
  1261.     end;
  1262.  
  1263.  
  1264.     procedure FindMonitors (NewScreenDepth: integer);
  1265.   {Generate a list of 8-bit monitors so we can update their LUTs.}
  1266.   {This wouldn't be necessary if we were using the Palette Manager.}
  1267.         var
  1268.             nextDevice: GDHandle;
  1269.     begin
  1270.         nMonitors := 0;
  1271.         nextDevice := GetDeviceList;
  1272.         while nextDevice <> nil do begin
  1273.                 if TestDeviceAttribute(nextDevice, screenDevice) and TestDeviceAttribute(nextDevice, screenActive) then
  1274.                     if nextDevice^^.gdPmap^^.PixelSize = 8 then begin
  1275.                             nMonitors := nMonitors + 1;
  1276.                             Monitors[nMonitors] := nextDevice;
  1277.                         end;
  1278.                 nextDevice := GetNextDevice(nextDevice);
  1279.             end; {while}
  1280.         if NewScreenDepth < 4 then
  1281.             gCopyMode := DitherCopy
  1282.         else
  1283.             gCopyMode := SrcCopy;
  1284.         SaveScreenDepth := NewScreenDepth;
  1285.     end;
  1286.  
  1287.  
  1288.     function ScreenDepth: integer;
  1289.         var
  1290.             depth: integer;
  1291.     begin
  1292.         depth := ScreenPixMap^^.PixelSize;
  1293.         if depth <> SaveScreenDepth then
  1294.             FindMonitors(depth);
  1295.         ScreenDepth := depth;
  1296.     end;
  1297.  
  1298.  
  1299.     procedure SetFColor (index: integer);
  1300.   {Sets the screen foreground color. Use pmForeColor to set the offscreen color.}
  1301.     begin
  1302.         if ScreenDepth = 8 then
  1303.             pmForeColor(index)
  1304.         else
  1305.             RGBForeColor(osGDevice^^.gdPMap^^.pmTable^^.ctTable[index].rgb);
  1306.     end;
  1307.  
  1308.     procedure SetBColor (index: integer);
  1309.   {Sets the screen background color.}
  1310.     begin
  1311.         if ScreenDepth = 8 then
  1312.             pmBackColor(index)
  1313.         else
  1314.             RGBBackColor(osGDevice^^.gdPMap^^.pmTable^^.ctTable[index].rgb);
  1315.     end;
  1316.  
  1317.  
  1318. end.