home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 September / Chip_2001-09_cd1.bin / zkuste / delphi / kolekce / d12345 / MISC.ZIP / Misc.pas < prev    next >
Pascal/Delphi Source File  |  2001-05-10  |  32KB  |  1,117 lines

  1. unit Misc;
  2.  
  3. {$I Misc.inc}
  4.  
  5. {-----------------------------------------------------------------------------
  6. The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
  7.  
  8. http://www.mozilla.org/MPL/MPL-1.1.html
  9.  
  10. Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either expressed or implied. See the License for the specific language governing rights and limitations under the License.
  11.  
  12.  
  13. The Original Code is: PlotMisc.pas, released 1 July 2000.
  14.  
  15. The Initial Developer of the Original Code is Mat Ballard.
  16. Portions created by Mat Ballard are Copyright (C) 1999 Mat Ballard.
  17. Portions created by Microsoft are Copyright (C) 1998, 1999 Microsoft Corp.
  18. All Rights Reserved.
  19.  
  20. Contributor(s): Mat Ballard                 e-mail: mat.ballard@chemware.hypermart.net.
  21.  
  22. Last Modified: 02/25/2001
  23. Current Version: 2.00
  24.  
  25. You may retrieve the latest version of this file from:
  26.  
  27.         http://Chemware.hypermart.net/
  28.  
  29. This work was created with the Project JEDI VCL guidelines:
  30.  
  31.         http://www.delphi-jedi.org/Jedi:VCLVCL
  32.  
  33. in mind. 
  34.  
  35.  
  36. Purpose:
  37. Collection of miscellaneous routines and type definitions, mostly poor clones
  38. of those from the Math unit in the Pro versions.
  39.  
  40. Known Issues:
  41. -----------------------------------------------------------------------------}
  42.  
  43. interface
  44.  
  45. uses
  46.   Classes, SysUtils, TypInfo,
  47. {$IFDEF NO_MATH}
  48.   NoMath,
  49. {$ELSE}
  50.   Math,
  51. {$ENDIF}
  52. {$IFDEF WINDOWS}
  53.   WinTypes, WinProcs,
  54.   Controls, Dialogs, Forms, Graphics, ShellApi
  55. {$ENDIF}
  56. {$IFDEF WIN32}
  57.   Windows,
  58.   Clipbrd, Controls, Dialogs, Forms, Graphics, ShellApi
  59. {$ENDIF}
  60. {$IFDEF LINUX}
  61.   Libc, Types, Qt,
  62.   QControls, QDialogs, QForms, QGraphics
  63. {$ENDIF}
  64.   ;
  65.  
  66. type
  67.   pSingle = ^Single;
  68.   pDouble = ^Double;
  69.  
  70. {dynamic matrix definitions:}
  71. {$IFDEF DELPHI1}
  72.   TIntegerArray = array[0..MaxInt - 1] of Integer;
  73.   TSingleArray = array[0..MaxInt div 2 - 1] of Single;
  74.   TDoubleArray = array[0..MaxInt div 4 - 1] of Double;
  75. {$ELSE}
  76.   TIntegerArray = array[0..MaxInt div SizeOf(Integer) - 1] of Integer;
  77.   TSingleArray = array[0..MaxInt div SizeOf(Single) -1] of Single;
  78.   TDoubleArray = array[0..MaxInt div SizeOf(Double) - 1] of Double;
  79. {$ENDIF}
  80.  
  81. {NOTE: Multidimensional dynamic arrays DON'T WORK !
  82.   TIntegerMatrix = array[0..0] of array[0..0] of Integer;
  83.   TSingleMatrix = array[0..0] of array[0..0] of Single;
  84.   TDoubleMatrix = array[0..0] of array[0..0] of Double;}
  85.  
  86. {dynamic matrix definitions - pointers thereto:}
  87.   pIntegerArray = ^TIntegerArray;
  88.   pSingleArray = ^TSingleArray;
  89.   pDoubleArray = ^TDoubleArray;
  90.   {pIntegerMatrix = ^TIntegerMatrix;
  91.   pSingleMatrix = ^TSingleMatrix;
  92.   pDoubleMatrix = ^TDoubleMatrix;}
  93.  
  94. {$IFDEF LINUX}
  95. {$ENDIF}
  96.  
  97.   TPercent = 0..100;
  98.  
  99.   TXYPoint = record
  100.     X: Single;
  101.     Y: Single;
  102.   end;
  103.   pXYPoint = ^TXYPoint;
  104. {$IFDEF DELPHI1}
  105.   TXYArray = array[0..MaxInt div 4 - 1] of TXYPoint;
  106. {$ELSE}
  107.   TXYArray = array[0..MaxInt div SizeOf(Double) - 1] of TXYPoint;
  108. {$ENDIF}
  109.   pXYArray = ^TXYArray;
  110.  
  111.   TIdentMapEntry = record
  112.     Value: TColor;
  113.     Name: String;
  114.   end;
  115.  
  116. {$IFDEF LINUX}
  117.   TRGBTriple = packed record
  118.     rgbtBlue: Byte;
  119.     rgbtGreen: Byte;
  120.     rgbtRed: Byte;
  121.   end;
  122. {$ENDIF}
  123.   TRGBArray    = array[0..20000] OF TRGBTriple;
  124.   pRGBArray    = ^TRGBArray;
  125.   
  126.   TRainbowColor = record
  127.     R: Integer;
  128.     G: Integer;
  129.     B: Integer;
  130.   end;
  131.  
  132.   TFileList = class(TStringList)
  133.     private
  134.     protected
  135.     public
  136.       procedure AppendToFile(const FileName: string); virtual;
  137.     published
  138.   end;
  139.  
  140.   TMemoryStreamEx = class(TMemoryStream)
  141.     private
  142.     protected
  143.     public
  144.       procedure AppendToFile(const FileName: string); virtual;
  145.   end;
  146.  
  147.   function GetLineLengthFromStream(AStream: TMemoryStream): Integer;
  148.   function ReadLine(AStream: TMemoryStream): String;
  149.   function FindStringInStream(TheString: String; AStream: TMemoryStream): Boolean;
  150.   function CleanString(AString: String; TheChar: Char): String;
  151.   function StrRev(TheStr: String): String;
  152.  
  153.   procedure DeSci(ExtNumber: Extended; var Mantissa: Extended; var Exponent: Integer);
  154. {This method breaks a number down into its mantissa and exponent.
  155.  Eg: 0.00579 has a mantissa of 5.79, and an exponent of -3.}
  156.  
  157.   function GetWord (var This_Line: String; Delimiter: String): String;
  158. {The GetWord function returns all the characters up to Delimiter in This_Line,
  159.  and removes all characters up to and including Delimiter from ThisLine.}
  160. {}
  161. {This is very useful for extracting comma or tab-seperated strings (numbers)
  162.  from text data.}
  163.  
  164.   function IndexOfColorValue(Value: TColor): Integer;
  165.   function IndexOfColorName(Name: String): Integer;
  166.   function GetDarkerColor(Value: TColor; Brightness: Integer): TColor;
  167.   function GetInverseColor(Value: TColor): TColor;
  168.   function GetPalerColor(Value: TColor; Brightness: Integer): TColor;
  169.   function Rainbow(Fraction: Single): TColor;
  170.   function InputColor(var AColor: TColor): Boolean;
  171.   function BinToInt(Value: String): {$IFDEF DELPHI1}Longint{$ELSE}{$IFDEF BCB}Longint{$ELSE}Longword{$ENDIF}{$ENDIF};
  172.   function IntToBin(Value: {$IFDEF DELPHI1}Longint{$ELSE}{$IFDEF BCB}Longint{$ELSE}Longword{$ENDIF}{$ENDIF}): string;
  173.   function IsInteger(Value: String): Boolean;
  174.   function IsFixed(Value: String): Boolean;
  175.   function IsReal(Value: String): Boolean;
  176.  
  177.   procedure SetDialogGeometry(AForm: TForm; AButton: TControl; BorderWidth: Integer);
  178.  
  179. {$IFDEF MSWINDOWS}
  180.   procedure TextOutAnglePersist(
  181.     ACanvas: TCanvas;
  182.     Angle, Left, Top: Integer;
  183.     TheText: String);
  184. {$ENDIF}
  185.   procedure TextOutAngle(
  186.     ACanvas: TCanvas;
  187.     Angle, Left, Top: Integer;
  188.     TheText: String);
  189.   procedure ShellExec(Cmd: String);
  190.   {function FormOnHelp(
  191.     HelpType: THelpType;
  192.     HelpContext: Integer;
  193.     HelpKeyword: string;
  194.     HelpFile: string;
  195.     var Handled: Boolean): Boolean;}
  196.  
  197. {$IFDEF DELPHI1}
  198.   function GetCurrentDir: String;
  199. {$ENDIF}
  200.  
  201. const
  202.   TWO_PI = 6.28318530717958; {6476925286766559}
  203.   CRLF = #13+#10;
  204.   MY_COLORS_MAX = 15;
  205. {The number of MyColors runs from 0..15.}
  206.  
  207. {MyColors is based on the Colors definition in Graphics.pas,
  208.  restricted the the basic 16 colors, and in a different order
  209.  more suitable for graphs.}
  210.   MyColorValues: array[0..15] of TColor = (
  211.     clBlack,
  212.     clRed,
  213.     clBlue,
  214.     clGreen,
  215.     clPurple,
  216.     clFuchsia,
  217.     clAqua,
  218.     clMaroon,
  219.     clOlive,
  220.     clNavy,
  221.     clTeal,
  222.     clGray,
  223.     clSilver,
  224.     clLime,
  225.     clYellow,
  226.     clWhite);
  227.  
  228.   MAX_RAINBOW_COLORS = 5;
  229.   RainbowColors: array[0..MAX_RAINBOW_COLORS, 0..2] of Integer =
  230.     ({(0, 0, 0),          //black}
  231.      (255, 0, 0),        {red}
  232.      (255, 255, 0),      {yellow}
  233.      (0, 255, 0),        {green}
  234.      (0, 255, 255),      {aqua}
  235.      (0, 0, 255),        {blue}
  236.      (255, 0, 255));      {purple}
  237.      {(255, 255, 255));   //white}
  238. {Note: Black and white have been removed to avoid confusion with the background.}
  239.  
  240. implementation
  241.  
  242. {------------------------------------------------------------------------------
  243.     Procedure: TFileList.AppendToFile
  244.   Description: appends this stringlist to an existing file
  245.        Author: Mat Ballard
  246.  Date created: 04/25/2000
  247. Date modified: 04/25/2000 by Mat Ballard
  248.       Purpose: saving data to disk
  249.  Known Issues:
  250.  ------------------------------------------------------------------------------}
  251. procedure TFileList.AppendToFile(const FileName: string);
  252. var
  253.   Stream: TStream;
  254. begin
  255.   if (FileExists(FileName)) then
  256.   begin
  257.     Stream := TFileStream.Create(FileName, fmOpenReadWrite);
  258.     Stream.Seek(0, soFromEnd);
  259.   end
  260.   else
  261.   begin
  262.     Stream := TFileStream.Create(FileName, fmCreate);
  263.   end;
  264.  
  265.   try
  266.     SaveToStream(Stream);
  267.   finally
  268.     Stream.Free;
  269.   end;
  270. end;
  271. {end TFileList ----------------------------------------------------------------}
  272.  
  273. {------------------------------------------------------------------------------
  274.     Procedure: TMemoryStreamEx.AppendToFile
  275.   Description: appends this MemoryStream to an existing file
  276.        Author: Mat Ballard
  277.  Date created: 04/25/2000
  278. Date modified: 04/25/2000 by Mat Ballard
  279.       Purpose: saving data to disk
  280.  Known Issues:
  281.  ------------------------------------------------------------------------------}
  282. procedure TMemoryStreamEx.AppendToFile(const FileName: string);
  283. var
  284.   Stream: TStream;
  285. begin
  286.   if (FileExists(FileName)) then
  287.   begin
  288.     Stream := TFileStream.Create(FileName, fmOpenReadWrite);
  289.     Stream.Seek(0, soFromEnd);
  290.   end
  291.   else
  292.   begin
  293.     Stream := TFileStream.Create(FileName, fmCreate);
  294.   end;
  295.  
  296.   try
  297.     SaveToStream(Stream);
  298.   finally
  299.     Stream.Free;
  300.   end;
  301. end;
  302.  
  303. {end TMemoryStreamEx ----------------------------------------------------------------}
  304.  
  305. {------------------------------------------------------------------------------
  306.      Function: GetLineLengthFromStream
  307.   Description: gets the length of the line (of text) at AStream.Position
  308.        Author: Mat Ballard
  309.  Date created: 08/09/2000
  310. Date modified: 08/09/2000 by Mat Ballard
  311.       Purpose: Stream manipulation
  312.  Return Value: the length of the line, up to CRLF
  313.  Known Issues:
  314.  ------------------------------------------------------------------------------}
  315. function GetLineLengthFromStream(AStream: TMemoryStream): Integer;
  316. var
  317.   pCR,
  318.   pLF: PChar;
  319.   i: Longint;
  320. begin
  321.   pCR := AStream.Memory;
  322.   Inc(pCR, AStream.Position);
  323. {default is the entire stream:}
  324.   GetLineLengthFromStream := AStream.Size - AStream.Position;
  325.   for i := AStream.Position to AStream.Size-1 do
  326.   begin
  327.     if (pCR^ = #13) then
  328.     begin
  329.       pLF := pCR;
  330.       Inc(pLF);
  331.       if (pLF^ = #10) then
  332.       begin
  333.         GetLineLengthFromStream := i - AStream.Position;
  334.         break;
  335.       end;
  336.     end;
  337.     Inc(pCR);
  338.   end;
  339. end;
  340.  
  341. {------------------------------------------------------------------------------
  342.      Function: ReadLine
  343.   Description: gets line (of text) at AStream.Position
  344.        Author: Mat Ballard
  345.  Date created: 08/09/2000
  346. Date modified: 04/28/2001 by Mat Ballard
  347.       Purpose: Stream manipulation
  348.  Return Value: the line as a string
  349.  Known Issues: does not work against TBlobStream
  350.  ------------------------------------------------------------------------------}
  351. function ReadLine(AStream: TMemoryStream): String;
  352. var
  353.   LineLength: Integer;
  354.   pLine: array [0..1023] of char;
  355. begin
  356.   LineLength := GetLineLengthFromStream(AStream);
  357. {get the line of text:}
  358. {$IFDEF DELPHI1}
  359.   AStream.Read(pLine, LineLength);
  360.   Result := StrPas(pLine);
  361. {$ELSE}
  362.   SetString(Result, PChar(nil), LineLength);
  363.   AStream.Read(Pointer(Result)^, LineLength);
  364. {$ENDIF}
  365. {get the CRLF:}
  366.   AStream.Read(pLine, 2);
  367. end;
  368.  
  369. {------------------------------------------------------------------------------
  370.      Function: FindStringInStream
  371.   Description: Finds the first occurrence of TheString in AStream from
  372.                AStream.Position onwards
  373.        Author: Mat Ballard
  374.  Date created: 08/09/2000
  375. Date modified: 08/09/2000 by Mat Ballard
  376.       Purpose:
  377.  Return Value: TRUE if successful, FALSE otherwise
  378.  Known Issues:
  379.  ------------------------------------------------------------------------------}
  380. function FindStringInStream(TheString: String; AStream: TMemoryStream): Boolean;
  381. var
  382.   pStart,
  383.   pTheChar: PChar;
  384.   i,
  385.   j: Longint;
  386.   FoundIt: Boolean;
  387. begin
  388.   pStart := AStream.Memory;
  389.   Inc(pStart, AStream.Position);
  390. {default is the entire stream:}
  391.   FindStringInStream := FALSE;
  392.   for i := AStream.Position to AStream.Size-1 do
  393.   begin
  394.     pTheChar := pStart;
  395.     FoundIt := TRUE;
  396.     for j := 1 to Length(TheString) do
  397.     begin
  398.       if (pTheChar^ <> TheString[j]) then
  399.       begin
  400.         FoundIt := FALSE;
  401.         break;
  402.       end;
  403.       Inc(pTheChar);
  404.     end;
  405.  
  406.     if (FoundIt) then
  407.     begin
  408.       AStream.Position := i;
  409.       FindStringInStream := TRUE;
  410.       break;
  411.     end;
  412.  
  413.     Inc(pStart);
  414.   end;
  415. end;
  416.  
  417. {------------------------------------------------------------------------------
  418.      Function: CleanString
  419.   Description: removes offending characters from a string
  420.        Author: Mat Ballard
  421.  Date created: 04/25/2000
  422. Date modified: 04/25/2000 by Mat Ballard
  423.       Purpose: menu manipulation
  424.  Return Value: the cleaned string
  425.  Known Issues:
  426.  ------------------------------------------------------------------------------}
  427. function CleanString(AString: String; TheChar: Char): String;
  428. var
  429.   i: Integer;
  430.   NewString: String;
  431. begin
  432.   NewString := '';
  433.   for i := 1 to Length(AString) do
  434.   begin
  435.     if (AString[i] <> TheChar) then
  436.     begin
  437.       NewString := NewString + AString[i];
  438.     end;
  439.   end;
  440.   CleanString := NewString;
  441. end;
  442.  
  443. {------------------------------------------------------------------------------
  444.      Function: StrRev
  445.   Description: reverses a string
  446.        Author: Mat Ballard
  447.  Date created: 04/25/2000
  448. Date modified: 04/25/2000 by Mat Ballard
  449.       Purpose: string manipulation
  450.  Return Value: the reverse of a string
  451.  Known Issues:
  452.  ------------------------------------------------------------------------------}
  453. function StrRev(TheStr: String): String;
  454. var
  455.   i,
  456.   l: Integer;
  457.   RevStr: String;
  458. begin
  459.   l := Length(TheStr);
  460. {$IFDEF DELPHI1}
  461.   RevStr := TheStr;
  462. {$ELSE}
  463.   SetLength(RevStr, l);
  464. {$ENDIF}
  465.  
  466.   for i := 1 to l do
  467.   begin
  468.     RevStr[i] := TheStr[l-i+1];
  469.   end;
  470.   StrRev := RevStr;
  471. end;
  472.  
  473. {------------------------------------------------------------------------------
  474.     Procedure: DeSci
  475.   Description: breaks a number up into its Mantissa and Exponent
  476.        Author: Mat Ballard
  477.  Date created: 04/25/2000
  478. Date modified: 04/25/2000 by Mat Ballard
  479.       Purpose: Tick and Label scaling
  480.  Known Issues: Why not use Math.Frexp() - because that works on POWERS OF TWO !
  481.  ------------------------------------------------------------------------------}
  482. procedure DeSci(ExtNumber: Extended; var Mantissa: Extended; var Exponent: Integer);
  483. var
  484.   TheLog: Extended;
  485.   TheSign: Extended;
  486. begin
  487.   TheSign := 1;
  488.  
  489.   if (ExtNumber = 0) then
  490.   begin
  491.     Mantissa := 0;
  492.     Exponent := 0;
  493.     exit;
  494.   end;
  495.  
  496.   if (ExtNumber < 0) then
  497.   begin
  498.     TheSign := -1;
  499.     ExtNumber := -ExtNumber;
  500.   end;
  501.  
  502.   TheLog := Log10(ExtNumber);
  503.   Exponent := Floor(TheLog);
  504.   Mantissa := TheLog - Exponent;
  505.   Mantissa := Power(10.0, Mantissa);
  506.   if (TheSign < 0) then Mantissa := -Mantissa;
  507. end;
  508.  
  509. {------------------------------------------------------------------------------
  510.      Function: GetWord
  511.   Description: splits a phrase into two at the delimiter
  512.        Author: Mat Ballard
  513.  Date created: 04/25/2000
  514. Date modified: 04/25/2000 by Mat Ballard
  515.       Purpose: string manipulation
  516.  Return Value: the left side
  517.  Known Issues:
  518.  ------------------------------------------------------------------------------}
  519. Function GetWord (var This_Line: String; Delimiter: String): String;
  520. var
  521.   Delimiter_Position: Integer;
  522. begin
  523.   Delimiter_Position := Pos(Delimiter, This_Line);
  524.   If (Delimiter_Position > 0) Then
  525.   begin
  526.     GetWord := Copy(This_Line, 1, Delimiter_Position-1);
  527.     This_Line := Copy(This_Line, Delimiter_Position + Length(Delimiter), Length(This_Line));
  528.   end
  529.   Else
  530.   begin
  531.     GetWord := This_Line;
  532.     This_Line := '';
  533.   end;
  534. end;
  535.  
  536. {------------------------------------------------------------------------------
  537.      Function: IndexOfColorValue
  538.   Description: gets the index of a color
  539.        Author: Mat Ballard
  540.  Date created: 04/25/2000
  541. Date modified: 04/25/2000 by Mat Ballard
  542.       Purpose: color manipulation
  543.  Return Value: Index of a color
  544.  Known Issues:
  545.  ------------------------------------------------------------------------------}
  546. function IndexOfColorValue(Value: TColor): Integer;
  547. var
  548.   i: Integer;
  549. begin
  550.   IndexOfColorValue := -1;
  551.   for i := 0 to MY_COLORS_MAX do
  552.   begin
  553.     if (MyColorValues[i] = Value) then
  554.     begin
  555.       IndexOfColorValue := i;
  556.       break;
  557.     end;
  558.   end;
  559. end;
  560.  
  561. {------------------------------------------------------------------------------
  562.      Function: IndexOfColorName
  563.   Description: gets the name of a color
  564.        Author: Mat Ballard
  565.  Date created: 04/25/2000
  566. Date modified: 04/25/2000 by Mat Ballard
  567.       Purpose: color manipulation
  568.  Return Value: string containing the color name
  569.  Known Issues:
  570.  ------------------------------------------------------------------------------}
  571. function IndexOfColorName(Name: String): Integer;
  572. var
  573.   i: Integer;
  574. begin
  575.   IndexOfColorName := -1;
  576.   for i := 0 to MY_COLORS_MAX do
  577.   begin
  578.     if (ColorToString(MyColorValues[i]) = Name) then
  579.     begin
  580.       IndexOfColorName := i;
  581.       break;
  582.     end;
  583.   end;
  584. end;
  585.  
  586. {------------------------------------------------------------------------------
  587.      Function: GetPalerColor
  588.   Description: gets a paler shade of the input color
  589.        Author: Mat Ballard
  590.  Date created: 09/25/2000
  591. Date modified: 09/25/2000 by Mat Ballard
  592.       Purpose: color manipulation
  593.  Return Value: TColor
  594.  Known Issues:
  595.  ------------------------------------------------------------------------------}
  596. function GetPalerColor(Value: TColor; Brightness: Integer): TColor;
  597. var
  598.   iColor,
  599.   iRed,
  600.   iBlue,
  601.   iGreen: Longint;
  602. begin
  603.   iColor := ColorToRGB(Value);
  604.  
  605.   iRed := (iColor and $000000FF);
  606.   iRed := iRed + Brightness * ($FF-iRed) div 100;
  607.  
  608.   iGreen := (iColor and $0000FF00) shr 8;
  609.   iGreen := iGreen + Brightness * ($FF-iGreen) div 100;
  610.  
  611.   iBlue := (iColor and $00FF0000) shr 16;
  612.   iBlue := iBlue + Brightness * ($FF-iBlue) div 100;
  613.  
  614.   GetPalerColor := TColor(iRed  or (iGreen shl 8) or (iBlue shl 16));
  615. end;
  616.  
  617. {------------------------------------------------------------------------------
  618.      Function: GetDarkerColor
  619.   Description: gets a darker shade of the input color
  620.        Author: Mat Ballard
  621.  Date created: 09/25/2000
  622. Date modified: 09/25/2000 by Mat Ballard
  623.       Purpose: color manipulation
  624.  Return Value: TColor
  625.  Known Issues:
  626.  ------------------------------------------------------------------------------}
  627. function GetDarkerColor(Value: TColor; Brightness: Integer): TColor;
  628. var
  629.   iColor,
  630.   iRed,
  631.   iBlue,
  632.   iGreen: Longint;
  633. begin
  634.   iColor := ColorToRGB(Value);
  635.  
  636.   iRed := (iColor and $000000FF);
  637.   iRed := iRed * Brightness div 100;
  638.  
  639.   iGreen := (iColor and $0000FF00) shr 8;
  640.   iGreen := iGreen * Brightness div 100;
  641.  
  642.   iBlue := (iColor and $00FF0000) shr 16;
  643.   iBlue := iBlue * Brightness div 100;
  644.  
  645.   GetDarkerColor := TColor(iRed  or (iGreen shl 8) or (iBlue shl 16));
  646. end;
  647.  
  648. {------------------------------------------------------------------------------
  649.      Function: GetInverseColor
  650.   Description: gets the inverse of the input color
  651.        Author: Mat Ballard
  652.  Date created: 09/25/2000
  653. Date modified: 09/25/2000 by Mat Ballard
  654.       Purpose: color manipulation
  655.  Return Value: TColor
  656.  Known Issues: does not return an inverse if Value is close to grey, because the
  657.                inverse of gray is gray !
  658.  ------------------------------------------------------------------------------}
  659. function GetInverseColor(Value: TColor): TColor;
  660. var
  661.   iColor,
  662.   iRed,
  663.   iBlue,
  664.   iGreen,
  665.   Difference: Longint;
  666. begin
  667.   iColor := ColorToRGB(Value);
  668.  
  669.   iRed := (iColor and $000000FF);
  670.   iRed := 255 - iRed;
  671.  
  672.   iGreen := (iColor and $0000FF00) shr 8;
  673.   iGreen := 255 - iGreen;
  674.  
  675.   iBlue := (iColor and $00FF0000) shr 16;
  676.   iBlue := 255 - iBlue;
  677.  
  678.   Difference := Abs(255 - (2*iRed + 2*iGreen + 2*iBlue) div 3);
  679.  
  680.   if (Difference > 26) then
  681.     GetInverseColor := TColor(iRed  or (iGreen shl 8) or (iBlue shl 16))
  682.    else
  683.     GetInverseColor := clBlack;
  684. end;
  685.  
  686. {------------------------------------------------------------------------------
  687.      Function: Rainbow
  688.   Description: returns a rainbow color, depending on the Fraction
  689.        Author: Mat Ballard
  690.  Date created: 02/15/2001
  691. Date modified: 02/15/2001 by Mat Ballard
  692.       Purpose: color manipulation for contour graphs
  693.  Return Value: TColor
  694.  Known Issues:
  695.  ------------------------------------------------------------------------------}
  696. function Rainbow(Fraction: Single): TColor;
  697. var
  698.   i,
  699.   LowIndex,
  700.   HighIndex: Integer;
  701.   RainbowColor: array [0..2] of Integer;
  702.   HighFraction,
  703.   LowFraction,
  704.   CellWidth: Single;
  705. begin
  706.   CellWidth := 1 / MAX_RAINBOW_COLORS;
  707.   LowIndex := Trunc(Fraction / CellWidth);
  708.   HighIndex := LowIndex + 1;
  709.   HighFraction := (Fraction - LowIndex * CellWidth) / CellWidth;
  710.   LowFraction := 1.0 - HighFraction;
  711.  
  712.   if (LowIndex = MAX_RAINBOW_COLORS) then
  713.   begin
  714.     for i := 0 to 2 do
  715.       RainbowColor[i] := 255;
  716.   end
  717.   else
  718.   begin
  719.     for i := 0 to 2 do
  720.     RainbowColor[i] := Round(
  721.       LowFraction * RainbowColors[LowIndex, i] +
  722.       HighFraction * RainbowColors[HighIndex, i]);
  723.   end;
  724.   Result := TColor(
  725.     RainbowColor[0] +
  726.     RainbowColor[1] shl 8 +
  727.     RainbowColor[2] shl 16);
  728. end;
  729.  
  730. {------------------------------------------------------------------------------
  731.      Function: InputColor
  732.   Description: prompts the user for a color
  733.        Author: Mat Ballard
  734.  Date created: 01/15/2001
  735. Date modified: 01/15/2001 by Mat Ballard
  736.       Purpose: color management
  737.  Return Value: Boolean
  738.  Known Issues:
  739.  ------------------------------------------------------------------------------}
  740. function InputColor(var AColor: TColor): Boolean;
  741. var
  742.   ColorDialog: TColorDialog;
  743. begin
  744.   InputColor := FALSE;
  745.   ColorDialog := TColorDialog.Create(nil);
  746. {$IFDEF MSWINDOWS}
  747.   ColorDialog.Options := [cdFullOpen];
  748. {$ENDIF}
  749.   ColorDialog.Color := AColor;
  750.   ColorDialog.CustomColors.Add('Current=' + IntToHex(ColorToRGB(AColor), 6));
  751.  
  752.   if (ColorDialog.Execute) then
  753.   begin
  754.     AColor := ColorDialog.Color;
  755.     InputColor := TRUE;
  756.   end;
  757.   ColorDialog.Free;
  758. end;
  759.  
  760. {------------------------------------------------------------------------------
  761.     Procedure: SetDialogGeometry
  762.   Description: sets the dialog Geometry under Windows and Linux
  763.       Authors: Mat Ballard
  764.  Date created: 04/03/2001
  765. Date modified: 04/03/2001 by Mat Ballard
  766.       Purpose: Dialog Geometry control
  767.  Known Issues: an alternative approach is:
  768.  
  769.   Scaled := FALSE;
  770.   AutoScroll := FALSE;
  771. // DESIGNSCREENWIDTHPIX is a constant depending on the width at design time, eg: 1024
  772.   ScaleBy(Screen.Width, DESIGNSCREENWIDTHPIX);
  773.  ------------------------------------------------------------------------------}
  774. procedure SetDialogGeometry(AForm: TForm; AButton: TControl; BorderWidth: Integer);
  775. begin
  776. {$IFDEF MSWINDOWS}
  777.   {AForm.PixelsPerInch := 96;}
  778.   AForm.BorderStyle := bsDialog;
  779. {$ENDIF}
  780. {$IFDEF LINUX}
  781.   {AForm.PixelsPerInch := 75;}
  782.   AForm.BorderStyle := fbsDialog;
  783. {$ENDIF}
  784.   AForm.Scaled := FALSE;
  785.   AForm.HorzScrollBar.Visible := FALSE;
  786.   AForm.VertScrollBar.Visible := FALSE;
  787.  
  788.   AForm.Left := 10;
  789.   AForm.Top := 10;
  790.   AForm.ClientHeight := AButton.Top + 3 * AButton.Height div 2;
  791.   AForm.ClientWidth := AButton.Left + AButton.Width + BorderWidth;
  792. end;
  793.  
  794.  
  795. {------------------------------------------------------------------------------}
  796. function BinToInt(Value: String): {$IFDEF DELPHI1}Longint{$ELSE}{$IFDEF BCB}Longint{$ELSE}Longword{$ENDIF}{$ENDIF};
  797. var
  798.   i: Integer;
  799.   Pow2,
  800.   TheResult: {$IFDEF DELPHI1}Longint{$ELSE}{$IFDEF BCB}Longint{$ELSE}Longword{$ENDIF}{$ENDIF};
  801. begin
  802.   Pow2 := 1;
  803.   TheResult := 0;
  804.   for i := 1 to Length(Value) do
  805.   begin
  806.     if (Value[i] = '1') then
  807.       TheResult := TheResult + Pow2;
  808.     Pow2 := Pow2 shl 1;
  809.   end;
  810.   BinToInt := TheResult;
  811. end;
  812.  
  813. function IntToBin(Value: {$IFDEF DELPHI1}Longint{$ELSE}{$IFDEF BCB}Longint{$ELSE}Longword{$ENDIF}{$ENDIF}): string;
  814. var
  815.   i: Integer;
  816.   StrResult: String;
  817.  
  818. {$IFDEF DELPHI1}
  819.   function LTrim(Const Str: String): String;
  820.   var
  821.     len: Byte absolute Str;
  822.     i: Integer;
  823.   begin
  824.     i := 1;
  825.     while (i <= len) and (Str[i] = ' ') do Inc(i);
  826.     LTrim := Copy(Str,i,len)
  827.   end ;
  828. {$ENDIF}
  829.  
  830. begin
  831.   i := 1;
  832. {$IFDEF DELPHI1}
  833.   StrResult := '                                ';
  834. {$ELSE}
  835.   SetLength(StrResult, 32);
  836. {$ENDIF}
  837.   repeat
  838.     if ((Value and 1) > 0) then
  839.       StrResult[i] := '1'
  840.      else
  841.       StrResult[i] := '0';
  842.     Value := Value shr 1;
  843.     Inc(i);
  844.   until (Value = 0);
  845. {$IFDEF DELPHI1}
  846.   StrResult := LTrim(StrResult);
  847. {$ELSE}
  848.   SetLength(StrResult, i-1);
  849. {$ENDIF}
  850.   StrResult := StrRev(StrResult);
  851.  
  852.   IntToBin := StrResult;
  853. end;
  854.  
  855. function IsInteger(Value: String): Boolean;
  856. var
  857.   i: Integer;
  858.   TheStart: Integer;
  859. begin
  860.   Result := FALSE;
  861.   TheStart := 1;
  862.   if (Value[1] = '-') then
  863.     TheStart := 2;
  864.  
  865.   for i := TheStart to Length(Value) do
  866.   begin
  867.     if ((Value[i] < '0') or
  868.         (Value[i] > '9')) then
  869.       exit;
  870.   end;
  871.   Result := TRUE;
  872. end;
  873.  
  874. function IsFixed(Value: String): Boolean;
  875. var
  876.   i: Integer;
  877.   TheStart: Integer;
  878.   DotCount: Integer;
  879. begin
  880.   Result := FALSE;
  881.   TheStart := 1;
  882.   DotCount := 0;
  883.  
  884.   if (Value[1] = '-') then
  885.     TheStart := 2;
  886.  
  887.   for i := TheStart to Length(Value) do
  888.   begin
  889.     if ((Value[i] < '0') or
  890.         (Value[i] > '9')) then
  891.       if (Value[i] = '.') then
  892.       begin
  893.         Inc(DotCount);
  894.         if (DotCount > 1) then
  895.           exit;
  896.       end
  897.       else
  898.       begin
  899.         exit;
  900.       end;
  901.   end;
  902.   Result := TRUE;
  903. end;
  904.  
  905. function IsReal(Value: String): Boolean;
  906. var
  907.   i: Integer;
  908.   TheStart: Integer;
  909.   DotCount: Integer;
  910.   ECount: Integer;
  911.   NegCount: Integer;
  912. begin
  913.   Result := FALSE;
  914.  
  915.   if (Length(Value) = 0) then
  916.     exit;
  917.  
  918.   TheStart := 1;
  919.   DotCount := 0;
  920.   ECount := 0;
  921.   NegCount := 0;
  922.  
  923.   if (Value[1] = '-') then
  924.     TheStart := 1;
  925.  
  926.   for i := TheStart to Length(Value) do
  927.   begin
  928.     if ((Value[i] < '0') or
  929.         (Value[i] > '9')) then
  930.       if (Value[i] = '.') then
  931.       begin
  932.         Inc(DotCount);
  933.         if (DotCount > 1) then
  934.           exit;
  935.       end
  936.       else if (Value[i] = '-') then
  937.       begin
  938.         Inc(NegCount);
  939.         if (NegCount > 1) then
  940.           exit;
  941.         if (Value[i-1] <> 'E') then
  942.           exit;
  943.       end
  944.       else if ((Value[i] = 'e') or (Value[i] = 'E')) then
  945.       begin
  946.         Inc(ECount);
  947.         if (ECount > 1) then
  948.           exit;
  949.         if(i = Length(Value)) then
  950.           exit;
  951.         Value[i] := 'E';
  952.       end  
  953.       else
  954.       begin
  955.         exit;
  956.       end;
  957.   end;
  958.   Result := TRUE;
  959. end;
  960.  
  961.  
  962. {$IFDEF DELPHI1}
  963. function GetCurrentDir: String;
  964. var
  965.   ThisDir: String;
  966. begin
  967.   GetDir(0, ThisDir);
  968. end;
  969. {$ENDIF}
  970.  
  971. {------------------------------------------------------------------------------
  972.     Procedure: TextOutAngle
  973.   Description: draws text on the input canvas, at an angle
  974.       Authors: Borland Developer Support Staff (Creating a rotated font, FAQ615D.txt), modified by Mat Ballard
  975.  Date created: 02/15/2001
  976. Date modified: 02/15/2001 by Mat Ballard
  977.       Purpose: Vertical and angular fonts
  978.  Known Issues: ACanvas.Font remains rotated until re-assigned ?
  979.  ------------------------------------------------------------------------------}
  980. {$IFDEF MSWINDOWS}
  981. procedure TextOutAnglePersist(
  982.   ACanvas: TCanvas;
  983.   Angle, Left, Top: Integer;
  984.   TheText: String);
  985. var
  986.   lf: TLogFont;
  987.   tf: TFont;
  988. begin
  989.   tf := TFont.Create;
  990.   tf.Assign(ACanvas.Font);
  991.   {Windows.}GetObject(tf.Handle, sizeof(lf), @lf);
  992.   lf.lfEscapement := 10*Angle;;
  993.   lf.lfOrientation := lf.lfEscapement;
  994.   tf.Handle := {Windows.}CreateFontIndirect(lf);
  995.   ACanvas.Font.Assign(tf);
  996.   tf.Free;
  997.   ACanvas.TextOut(Left, Top, TheText);
  998. end;
  999. {$ENDIF}
  1000.  
  1001. {------------------------------------------------------------------------------
  1002.     Procedure: TextOutAngle
  1003.   Description: draws angled text on the input canvas
  1004.       Authors: Mat Ballard
  1005.  Date created: 04/15/2000
  1006. Date modified: 04/15/2000 by Mat Ballard
  1007.       Purpose: Vertical fonts
  1008.  Known Issues: derived from the very early GPC work;
  1009.                ACanvas.Font does not remain rotated
  1010.                Note: Angle of rotation is Anti-Clockwise in Winxx,
  1011.                Clockwise in Qt/Linux
  1012.  ------------------------------------------------------------------------------}
  1013. procedure TextOutAngle(
  1014.   ACanvas: TCanvas;
  1015.   Angle, Left, Top: Integer;
  1016.   TheText: String);
  1017. {$IFDEF MSWINDOWS}
  1018. var
  1019.   LogRec: TLogFont;
  1020.   OldFontHandle, NewFontHandle: hFont;
  1021. {$ENDIF}
  1022. {$IFDEF LINUX}
  1023. {$ENDIF}
  1024.  
  1025. begin
  1026. {$IFDEF MSWINDOWS}
  1027. {Gotta use Windows GDI functions to rotate the font:}
  1028.   {Windows.}GetObject(ACanvas.Font.Handle, SizeOf(LogRec), Addr(LogRec));
  1029.   LogRec.lfEscapement := 10*Angle;
  1030.   LogRec.lfOrientation := LogRec.lfEscapement;
  1031.   NewFontHandle := {Windows.}CreateFontIndirect(LogRec);
  1032. {select the new font:}
  1033.   OldFontHandle := {Windows.}SelectObject(ACanvas.Handle, NewFontHandle);
  1034. {Print the text:}
  1035.   ACanvas.TextOut(Left, Top, TheText);
  1036. {go back to original font:}
  1037.   NewFontHandle := {Windows.}SelectObject(ACanvas.Handle, OldFontHandle);
  1038. {and delete the old one:}
  1039.   {Windows.}DeleteObject(NewFontHandle);
  1040. {$ENDIF}
  1041.  
  1042. {$IFDEF LINUX}
  1043. {this code is courtesy of Jon Shemitz <jon@midnightbeach.com>}
  1044. {Outside of a Paint handler, bracket QPainter_ calls with a Start/Stop}
  1045.   ACanvas.Start;
  1046.   try
  1047.     Qt.QPainter_save(ACanvas.Handle);
  1048. {Move 0,0 to the center of the form}
  1049.     Qt.QPainter_translate(ACanvas.Handle, Left, Top);
  1050. {Rotate; note negative angle:}
  1051.     QPainter_rotate(ACanvas.Handle, -Angle);
  1052.     ACanvas.TextOut(0, 0, TheText);
  1053.   finally
  1054.     Qt.QPainter_restore(ACanvas.Handle);
  1055.     ACanvas.Stop;
  1056.   end;
  1057. {$ENDIF}
  1058. end;
  1059.  
  1060. {------------------------------------------------------------------------------
  1061.     Procedure: ShellExec
  1062.   Description: wrapper for the windows "ShellExecute" API call, extended to Linux
  1063.       Authors: Mat Ballard
  1064.  Date created: 04/15/2000
  1065. Date modified: 03/28/2001 by Mat Ballard
  1066.       Purpose: Execute an external program with arguments
  1067.  Known Issues: does not cope properly with spaces in arguments (eg: "My File.txt")
  1068.  ------------------------------------------------------------------------------}
  1069. procedure ShellExec(Cmd: String);
  1070. {$IFDEF WINDOWS} {Delphi 1}
  1071. var
  1072.   sObjectPath: array[0..1023] of Char;
  1073. {$ENDIF}
  1074. begin
  1075. {$IFDEF WINDOWS} {Delphi 1}
  1076.   StrPCopy(sObjectPath, Cmd);
  1077.   ShellExecute(0, Nil, sObjectPath, Nil, Nil, 3);  {?SW_SHOW ?}
  1078. {$ENDIF}
  1079. {$IFDEF WIN32}
  1080.   ShellExecute(0, Nil, PChar(Cmd), Nil, Nil, SW_NORMAL);
  1081. {$ENDIF}
  1082. {$IFDEF LINUX}
  1083.   Libc.system(PChar(Cmd));
  1084. {$ENDIF}
  1085. end;
  1086.  
  1087. {------------------------------------------------------------------------------
  1088.      Function: FormOnHelp
  1089.   Description: displays a topic from a HTML-based help website
  1090.        Author: Mat Ballard
  1091.  Date created: 05/10/2001
  1092. Date modified: 05/10/2001 by Mat Ballard
  1093.       Purpose: help management
  1094.  Return Value: Boolean
  1095.  Known Issues:
  1096.  ------------------------------------------------------------------------------}
  1097. {function FormOnHelp(
  1098.   HelpType: THelpType;
  1099.   HelpContext: Integer;
  1100.   HelpKeyword: string;
  1101.   HelpFile: string;
  1102.   var Handled: Boolean): Boolean;
  1103. var
  1104.   MyHTMLHelpTopicFile: String;
  1105.   HelpPath: String;
  1106. begin
  1107.   HelpPath := ExtractFilePath(HelpFile);
  1108.   MyHTMLHelpTopicFile := HelpPath + 'hs' + IntToStr(HelpContext) + '.htm';
  1109.   if FileExists(MyHTMLHelpTopicFile) then
  1110.   begin
  1111.     ShellExec('konqueror ' + MyHTMLHelpTopicFile);
  1112.     Handled := TRUE;
  1113.   end;
  1114. end;}
  1115.  
  1116. end.
  1117.