LibDoc documentation for C:\DEV\D2006\LogicLib\Release\LogicLib.dpk Created 5/31/2008 5:32:07 PM -------------------------------------------------------------------------------- LogicLib ©2007-2008 Illuminated Logic, LLC. http://www.illuminatedlogic.com Installation: Installation of LogicLib is very easy and works the same in all versions of Delphi. Create a folder for LogicLib. I generally install all my components and libraries under a single directory tree so they are easy to find. Double-click LogicLib.dpk and press Compile, then Install in the package manager. Add the LogicLib folder to Delphi's library path using the Tools menu. When you want to reference a function from LogicLib, simply add the required unit name to the uses clause of the file you're working in. License Agreement: A license to use LogicLib is granted on a per-developer or site-wide basis. It may be used in any number of applications, freeware or commercial, for internal use or distributed externally in staticly-linked binary form, without any additional royalty or payment. A single developer may install the source code on multiple computers (physical or virtual) but each developer with access to the code must have their own (or a site) license. The LogicLib source code may not be distributed under any circumstances, in its original or modified form, to any non-licensed party. If you produce a work-for-hire and the customer requires a copy of all source code needed to build the application, your customer is granted a limited-use license for building the specific work-for-hire ONLY, and you may provide them with a copy of the library and any modifications you may have made to the code. Illuminated Logic will not provide support to any such 3rd-party licensee unless support or a regular license is purchased separately. All other rights, including copyright, are reserved by the author. Warranty: Legal mumbo-jumo aside, Illuminated Logic, LLC. offers a 30-day money back guarantee on all software purchases and bug fixes always have been, and always will be free. Of course, Illuminated Logic reserves the sole right to determine if any given issue brought to our attention is classified as a "bug" or not. For example, design/scope changes are NOT bugs. Illuminated Logic, LLC. does not warrant that the operation of the LogicLib code library for Delphi (SOFTWARE PRODUCT) will meet your requirements or that the operation of the software will be uninterrupted, be error free, or that defects in software will be corrected. The SOFTWARE PRODUCT is provided "AS IS" without warranty of any kind. The entire risk as to the quality and performance of the SOFTWARE PRODUCT is with the purchaser. ILLUMINATED LOGIC, LLC. MAKES NO OTHER WARRANTY, EITHER EXPRESSED OR IMPLIED, WITH RESPECT TO THIS PRODUCT. ILLUMINATED LOGIC, LLC. SPECIFICALLY DISCLAIMS THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE REMEDIES PROVIDED HEREIN ARE CUSTOMER'S SOLE AND EXCLUSIVE REMEDIES. UNDER NO CIRCUMSTANCES (INCLUDING NEGLIGENCE), SHALL ILLUMINATED LOGIC, LLC. BE LIABLE FOR ANY LOST PROFITS, DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER BASED ON CONTRACT, TORT, OR ANY OTHER LEGAL THEORY, EVEN IF ILLUMINATED LOGIC, LLC. HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. IN NO EVENT SHALL ILLUMINATED LOGIC'S TOTAL LIABILITY FOR DAMAGES, LOSSES AND CAUSES OF ACTION, WHETHER IN CONTRACT, TORT (INCLUDING NEGLIGENCE), OR OTHERWISE, EXCEED THE AMOUNT PAID BY YOU FOR THE SOFTWARE. LogicLib.dpk -------------------------------------------------------------------------------- function A85Decode(const S: string): string; Decodes an ASCII85 encoded string. Null input = null output. Handles data with or without the surrounding ASCII85Prefix/Suffix strings. Raises an EConvertError exception if invalid input is encountered. llEncoding.pas -------------------------------------------------------------------------------- function A85Encode(const S: string; const Bookends: Boolean): string; ASCII85 encodes a string. Set Bookends to True to have the ASCII85Prefix and ASCII85Suffix surround the output, False to leave them off (you can use the constants later). Null input = null output (plus Bookends, if requested). llEncoding.pas -------------------------------------------------------------------------------- function AddSlash(const APath: string): string; Just a shorter way to write IncludeTrailingPathDelimiter (or IncludeTrailingBackslash in D5). llFiles.pas -------------------------------------------------------------------------------- function AgeOnDate(const ADOB, ADate: TDateTime): Integer; Returns a person's age on a given date as an integer number of years. llDates.pas -------------------------------------------------------------------------------- const ALPHA_LOWER = 'abcdefghijklmnopqrstuvwxyz'; ALPHA_UPPER = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; ALPHA_BOTH = ALPHA_LOWER + ALPHA_UPPER; Handy constants for the lower & upper case alphabets. llStrings.pas -------------------------------------------------------------------------------- function AssumeCentury(const y: Integer): Integer; Given a two-digit year, use TwoDigitYearCenturyWindow to assume a century and return the adjusted year value using the logic as described in the help. TODO: An overloaded version that takes a TFormatSettings parameter? llDates.pas -------------------------------------------------------------------------------- function AttributeStr(const Attr: Integer; const AFormat: string = 'ADHRS'): string; Turns a file attribute integer (TSearchRec.Attr) into a string of letters indicating the attributes present. The order, case and positioning of the letters are determined by the AFormat argument. If AFormat has a 6th character, it is used as a placeholder in the output for missing attributes, resulting in a fixed-length return value. The first five characters of AFormat MUST be the letters 'ADHRS' in any order. Examples (where Attr is faArchive + faReadOnly): AttributeStr(Attr) -> 'AR' AttributeStr(Attr, 'adhrs ') -> 'a r ' AttributeStr(Attr, 'DHRSA-') -> '--R-A' See also: StrToAttribute llFiles.pas -------------------------------------------------------------------------------- function B16Decode(const S: string): string; Decodes a Base16 (hex) encoded string. Null input = null output. Raises an EConvertError exception on bad input. Base16Table has no effect on this function - it will correctly handle either upper- or lower-case letters A..F. llEncoding.pas -------------------------------------------------------------------------------- function B16Encode(const S: string): string; Base16 (Hex) encodes a string. Null input = null output. Set the Base16Table variable if you want an encoding alphabet other than the one defined by the Base16Default constant, which uses upper case letters. When working with PChars/Buffers, use BinToHex. llEncoding.pas -------------------------------------------------------------------------------- function B32Decode(const S: string): string; Base32 decodes a string. Null input = null output. Raises an EConvertError exception if invalid input is encountered. Set the Base32Table variable if you need an encoding alphabet different than that defined by the Base32Default constant. The only restriction on the alphabet is that the equal sign (=) is reserved for padding. llEncoding.pas -------------------------------------------------------------------------------- function B32Encode(const S: string): string; Base32 encodes a string. Null input = null output. Set the Base32Table variable if you need an encoding alphabet different than that defined by the Base32Default constant. The only restriction on the alphabet is that the equal sign (=) is reserved for padding. llEncoding.pas -------------------------------------------------------------------------------- function B64Decode(const S: String): String; Base64 decodes a string. Null input = null output. Raises an EConvertError exception if invalid input is encountered. Set the Base64Table variable if you need an encoding alphabet different than that defined by the Base64Default constant. The only restriction on the alphabet is that the equal sign (=) is reserved for padding. llEncoding.pas -------------------------------------------------------------------------------- function B64Encode(const S: String): String; Base64 encodes a string. Null input = null output. Set the Base64Table variable if you need an encoding alphabet different than that defined by the Base64Default constant. The only restriction on the alphabet is that the equal sign (=) is reserved for padding. llEncoding.pas -------------------------------------------------------------------------------- function BinStrToInt(const S: string): Integer; Converts a binary string (e.g. '0101') into an integer value. If the string is smaller than the number of bits in an integer, the string is right- justified into the least significant bits of the number. If the string is longer than needed, only the rightmost characters are used. See also: IntToBinStr llNumbers.pas -------------------------------------------------------------------------------- function CenteredMsgDlg(const AMsg, ACaption: string; DlgType: TMsgDlgType; Buttons: TMsgDlgButtons; AForm: TForm = nil; const HelpCtx: Integer = 0; const HelpFileName: string = ''): Integer; An adaptation of Dialogs.MessageDlgPosHelp that accepts a caption, centers the dialog over the calling form, and plays a sound like Application.MessageBox. If the caption is blank, the default MessageDlg caption is used. If the form is not provided, the dialog appears in its default position of screen center. llMsgDlg.pas -------------------------------------------------------------------------------- function CharsOnly(const AInput, AAllowed: string): string; Returns a string consisting only of the characters in that match the list of characters given in . Case matters. Example: CharsOnly('FooBar1', '123abcABC') -> 'Ba1' llStrings.pas -------------------------------------------------------------------------------- procedure CheckListChange(Lbx: TCheckListBox; const AChange: String); Updates the check marks in a TCheckListBox depending on AChange: 'A' = All 'N' = None 'R' = Reverse llControls.pas -------------------------------------------------------------------------------- function CloseQuotePos(const S: string; const AStart: Integer): Integer; Given a string and an index to the opening quote mark, the function returns the index of the final closing quote character, properly skipping any doubled literals. If a closing quote can't be located, the function returns zero. If the character at the start position is the opening character of matched pair, i.e. "({[<", the matching closing character will be used to find the end. The doubled-literal logic still applies, although strangely based on the closing character. Example: CloseQuotePos('cow="moo" dog="bark"', 5) -> 9 llStrings.pas -------------------------------------------------------------------------------- function DateTrunc(const ADate: TDateTime; const P: TDateTimePrecision): TDateTime; Truncates a date at a certain precision, similar to the PostgreSQL function called "date_trunc". Examples where ADate is 1995-10-15 09:45:30.500: DateTrunc(ADate, dtpMinute) -> 1995-10-15 09:45:00.000 DateTrunc(ADate, dtpMonth) -> 1995-10-01 00:00:00.000 DateTrunc(ADate, dtpDecade) -> 1990-01-01 00:00:00.000 llDates.pas -------------------------------------------------------------------------------- function Dequote(const S: string; const AQuote: Char = '"'): string; Works just like AnsiDequotedStr, but that doesn't exist in Delphi 5. In addition, D6 & D7 have a bug where AnsiDequotedStr will return a pair of empty quotes ("" or '') unchanged instead of returning an empty string! See also: Enquote llStrings.pas -------------------------------------------------------------------------------- function Dice(const ARolls: Integer; const ASides: Integer = 6; const AModify: Integer = 0): Integer; overload; Returns the sum of one or more virtual dice rolls (random numbers). A die of sides is rolled times. Optionally, each roll can be modified by the value of , which can be negative. The total of these rolls is returned. If only the number of rolls is given, an unmodified 6-sided die is assumed. llNumbers.pas -------------------------------------------------------------------------------- function Dice(const AStr: string): Integer; overload; Nerd alert! Accepts a string in "gaming notation", such as "3d6" or "2d4+1" and returns the integer result of said dice roll(s). Returns zero on blank input and raises an EConvertError on bad input. Input without a "d" in it is considered a constant and will simply be converted to an integer. Examples: Dice('3d6') -> 3..18 Dice('10') -> 10 Dice('foo') -> EConvertError See also: TryDice llNumbers.pas -------------------------------------------------------------------------------- function DigitsOnly(const AInput: string): string; Returns a string consisting only of the numeric digits in . It translates directly to CharsOnly(AInput, '0123456789'). I use this a lot for stripping punctuation from phone number strings. Example: DigitsOnly('1(800)555-1212') -> '18005551212' llStrings.pas -------------------------------------------------------------------------------- function DtoS(const DT: TDateTime; const P: TDateTimePrecision = dtpDay): String; "Date to String" - Formats a TDateTime value as a string in a 'yyyymmddhhnnsszzz' format. This locale-netural format is handy for storage or transmission and naturally lends itself to sorting. The optional TDateTimePrecision argument will determine the length of the returned string and defaults to dtpDay, or 'yyyymmdd'. Precisions lower than dtpYear are ignored. The smallest supported return value is 'yyyy'. The inverse of DtoS is the StoD function. llDates.pas -------------------------------------------------------------------------------- function EndOfDay(const DT: TDateTime): TDateTime; Returns the very last possible instant of the given day. This is useful for date range queries like " BETWEEN :Start AND :End", where :Start would be Trunc(DT) and :End would be EndOfDay(DT) (however, I find it's usually better to say " >= :Start and < :End" where End is midnight on the day AFTER the range end). llDates.pas -------------------------------------------------------------------------------- function Enquote(const S: string; const AQuote: Char = '"'): string; Works much like QuotedStr & AnsiQuotedStr, but in one convenient function with a nice, short name. See also: Dequote llStrings.pas -------------------------------------------------------------------------------- function ExpandEnvars(const S: string): string; A handy string-based wrapper around ExpandEnvironmentStrings. Turns things like "%SystemRoot%" into "C:\WINDOWS", etc. llWinAPI.pas -------------------------------------------------------------------------------- function ExtractFileExtNoDot(const AFile: string): string; Just like ExtractFileExt, but removes the leading dot if present. llFiles.pas -------------------------------------------------------------------------------- function FFDate(const AFile: string; const Attr: Integer = 0): TDateTime; Retrieves a file's date/time from FindFirst. Returns zero if not found. Supply Attr if you need to find hidden files, etc. If you use a wildcard instead of a single filename, the date of the newest file will be returned. llFiles.pas -------------------------------------------------------------------------------- function FFSize(const AFile: string; const Attr: Integer = 0): Integer; Unlike the FileSize function that requires a handle to an open file, this one just gets it from the directory entry using FindFirst. Supply Attr if you need to find hidden files, etc. Works for a single filename or a wildcard, returning the sum of the files' sizes. Returns the size of the file(s) in bytes or -1 if not found. llFiles.pas -------------------------------------------------------------------------------- function FFSize64(const AFile: string; const Attr: Integer = 0): Int64; Just like FFSize, but returns an Int64 instead of an Integer for big files. llFiles.pas -------------------------------------------------------------------------------- function FileSizeStr(const ASize: Int64; const ADecimals: Integer = 1; const AKilo: Integer = 1024): string; Turns a file size into a "friendly" string in one of these formats: 999 B 999 KB 999[.9] MB 999[.9] GB The number of decimal places on MB & GB values is determined by ADecimals. By default, a kilobyte is 1024 bytes, a MB is 1024 KB, etc. You can change this to 1000 by assigning a new value to AKilo. llFiles.pas -------------------------------------------------------------------------------- function FirstOfMonth(const ADate: TDateTime): TDateTime; Returns the TDateTime argument adjusted to the first of the given month. llDates.pas -------------------------------------------------------------------------------- function FixFilePath(const AFile, APath: string): string; Expands a filename based on the fully qualified path provided. Essentially, it's just like Expand[UNC]FileName, but you don't need to worry about whether it's UNC or not, and it accepts a specific path rather than expanding based on the current directory. Examples: FixFilePath('..\foo.pas', 'c:\dev\project\') -> 'c:\dev\foo.pas' FixFilePath('foo.pas', '\\ray\shared') -> \\ray\shared\foo.pas' llFiles.pas -------------------------------------------------------------------------------- function FormatDigits(const ADigits, AFormat: string): string; Right-justifies/overlays a string of digits into a format string. Especially handy for phone number formatting, but it could conceivably be used on any type of input. Ex: FormatDigits('6025551212', '(099)999-9999') -> '(602)555-1212' FormatDigits('5551212', '(099)999-9999') -> '555-1212' FormatDigits('6025551212', '999.999.9999') -> '602.555.1212' FormatDigits('123456', 'blah') -> '123456blah' All digit characters are always output even if the format string is shorter or blank. Output stops when you run out of digit characters, even though there may be more format string remaining. Format string rules: 9 = Replace this character with a character from the digit string. 0 = Same as 9 but always includes the next format character to the left, even if you have run out of digit characters. * = Any other character is copied to the output as a literal. Known limitations: The only way to output a literal '0' or '9' is to the immediate left of a '0' in the format string. llStrings.pas -------------------------------------------------------------------------------- function GCD(const a, b: Integer): Integer; Calculates the greatest common divisor of two integers. (The Euclidian algorithm) llNumbers.pas -------------------------------------------------------------------------------- function GetAssociatedProgram(const AFile: string): string; Uses the FindExecutable API function to get the program associated with the given file's extension. The file must exist and should be a fully qualified filename. Returns an empty string if unsuccessful. Note: If the file itself is executable (.exe, .bat, etc.) the return value is the filename itself (usually as a short filename using ~1 notation). llWinAPI.pas -------------------------------------------------------------------------------- function GetAssociatedProgramByExt(const AExt: string): string; Get the program associated with a given extension. The extension can be provided with or without a leading period. This actually just creates a temp file with the given extension and calls GetAssociatedProgram. llWinAPI.pas -------------------------------------------------------------------------------- function GetItemObjectInt(Ctl: TComboBox): Integer; overload; function GetItemObjectInt(Ctl: TListBox): Integer; overload; function GetItemObjectInt(Ctl: TCheckListBox): Integer; overload; Gets an integer object value from the currently selected item in a combobox, listbox, or checklistbox. If no item is currently selected the function will return -1. Unassigned objects (nil) become zero when cast as integers. llControls.pas -------------------------------------------------------------------------------- function GetSaveWindowPosFlag(const RegKey: string): Boolean; Returns the current setting of the SaveWindowPos flag used by SaveWindowPos and LoadWindowPos. llForms.pas -------------------------------------------------------------------------------- function GetShellFolder(const CSIDL: Integer; const Slash: Boolean = False): string; Handy wrapper around the ShGetFolderPath function that returns a string. Adds/Strips a trailing slash based on the boolean argument. Delphi6+: The CSIDL constants are declared in the SHFolder unit. Delphi5: The CSIDL constants are declared here and in ShlObj. llWinAPI.pas -------------------------------------------------------------------------------- function GetTempFile(const APath: string; const APrefix: string = 'TMP'): string; Wrapper around GetTempFileName() that conveniently returns a string. llWinAPI.pas -------------------------------------------------------------------------------- function GetWinCompName: string; Returns the current Windows computer name or a null string if unsuccessful. llWinAPI.pas -------------------------------------------------------------------------------- function GetWinDir(const Slash: Boolean = False): string; Wrapper around GetWindowsDirectory() that conveniently returns a string. The Slash argument will add a traling backslash if True, and remove one if False (the default). llWinAPI.pas -------------------------------------------------------------------------------- function GetWinUserName: string; Returns the current Windows username or a null string if unsuccessful. llWinAPI.pas -------------------------------------------------------------------------------- function HexCharToInt(const C: Char): Integer; Returns a value 0..15 for a valid hex character, or -1 otherwise. Case insensitive. llEncoding.pas -------------------------------------------------------------------------------- function IIf(const ABool: Boolean; const ATrue, AFalse: string): string; overloa function IIf(const ABool: Boolean; const ATrue, AFalse: Integer): Integer; overl function IIf(const ABool: Boolean; const ATrue, AFalse: Int64): Int64; overload; function IIf(const ABool: Boolean; const ATrue, AFalse: Single): Single; overloa function IIf(const ABool: Boolean; const ATrue, AFalse: Double): Double; overloa function IIf(const ABool: Boolean; const ATrue, AFalse: Extended): Extended; ove function IIf(const ABool: Boolean; const ATrue, AFalse: Currency): Currency; ove Inline-If functions overloaded for common data types. The Double one works with TDateTime values. llMisc.pas -------------------------------------------------------------------------------- function IndexOfPartial(AItems: TStrings; const AValue: String; const ADefault: Integer = -1; const CaseSensitive: Boolean = True): Integer; Finds the index of a string value in a TStrings list. Unlike TStrings.IndexOf, this will match on the partial length of AValue using StartsWith(). Returns -1 if not found or ADefault if given and valid. llStrings.pas -------------------------------------------------------------------------------- function InterleaveStrings(const S1, S2: string): string; Combines two strings by alternating characters. Example: InterleaveStrings('abc', '1234') -> 'a1b2c34' llStrings.pas -------------------------------------------------------------------------------- function IntervalStr(const AInterval: TDateTime; const LoP: TDateTimePrecision = dtpHour; const HiP: TDateTimePrecision = dtpSecond): String; Returns the time interval between two datetime values as a string. AInterval would normally be the result of subtracting a start time from an end time. The format of the string depends on the LoP and HiP TDateTimePrecision values ("LowPrecision" and "HighPrecision", respectively). These default to dtpHours and dtpSeconds accordingly, which will return a format of "hh:nn:ss". If LoP is dtpDay the format will have the number of days and the letter 'd' prepended, e.g. "1d04:13:22". Otherwise, the hour value will be as large as it needs to be, e.g. "48:56:13". If HiP is dtpMillisecond, the format will have the milliseconds added as a decimal fraction of the seconds like "04:13:22.377" If LoP is less than dtpDay, the format will be the same as if LoP were dtpHour, but with any insignificant leading zeros removed. For example, "00:00:00.123" would become "0.123", "00:05:13" -> "5:13", etc. llDates.pas -------------------------------------------------------------------------------- function IntToBinStr(const Value: Integer; const Bits: Integer = 8): string; Converts an integer into a string of binary digits (e.g. '0110'). The length of the string is determined by the Bits argument and defaults to 8 (a byte). See also: BinToIntStr llNumbers.pas -------------------------------------------------------------------------------- function IsBlank(const S: string): Boolean; Returns True if the string is empty or contains only "trimmable" characters. If you're just going to discard it if blank, why waste time creating another copy by actually trimming it? llStrings.pas -------------------------------------------------------------------------------- function IsValidHex(const S: string): Boolean; Returns True if the string in question contains only an even number of valid hex characters. Case insensitive. A null string returns True. If you need to check just a single character, use HexCharToInt. Written in response to HexToBin's failure (D5) to properly notify the caller of bad input. HexToBin returns a number > 0 *only* if it encounters any characters outside the range of '0'..'f'. That range still includes plenty of invalid characters (like G..Z, colon, underscore, etc.). When one of these is encountered, the value of those four bits is arbitrarily set to 15 (-1). You get junk data and no indication of a problem! See B16Decode for a string-based version of HexToBin. llEncoding.pas -------------------------------------------------------------------------------- function LastDOM(const ADate: TDateTime): Integer; Returns the integer last day of the month for the given date. Example: LastDOM(<2005-01-16>) -> 31 Overloaded: LastDOM(const AMonth: Integer; const AYear: Integer) llDates.pas -------------------------------------------------------------------------------- function LastDOM(const AMonth: Integer; const AYear: Integer = 0): Integer; Returns the integer last day of the given month and year. The current year is used for leap year logic if not provided. Examples: LastDOM(9) -> 30 LastDOM(2, 2004) -> 29 Overloaded: LastDOM(const ADate: TDateTime) llDates.pas -------------------------------------------------------------------------------- function LastOfMonth(const ADate: TDateTime): TDateTime; Returns the TDateTime argument adjusted to the last day of the given month. llDates.pas -------------------------------------------------------------------------------- function LastPos(const Substr, S: string; const Offset: Integer = 0): Integer; Returns the position of the last occurence of the substring, or zero if not found. Accepts a starting offset like PosEx, the default of zero being the equivalent of Length(S). Actually, any value outside 1..Length(S) will become Length(S). Examples: LastPos('foo', 'foobarfoobar') -> 7 LastPos('foo', 'foobarfoobar', 6) -> 1 llStrings.pas -------------------------------------------------------------------------------- procedure ListFiles(FileList: TStrings; const Path: string; const Attr: Integer = 0; const IncludePath: Boolean = False); Adds filenames to a TStrings/TStringList list. The and arguments determine what files are added to the list and equate to the FindFirst arguments of the same name. If is negative, only files that match the attribute mask will be added to the list. For example, to include both normal and hidden files, use faHidden. To list directories only, use -faDirectory. By default the filenames are added to the list without modification. If IncludePath is True, Path (less the wildcard) will be prepended to the names. llFiles.pas -------------------------------------------------------------------------------- function LoadWindowPos(AForm: TForm; const RegKey: string; OtherInfo: TStrings = nil): Boolean; Loads a form's position and size from registry settings previously saved to HKCU by the SaveWindowPos function. Returns True if the settings were present and loaded. If OtherInfo is provided as a list of name-value pairs, matching items in the registry key will be retrieved and written to the list. Missing OtherInfo values do not affect the function's boolean return value, so it is suggested that you preload the list with sensible default values. llForms.pas -------------------------------------------------------------------------------- function LocalUTCOffset: TDateTime; Get the local UTC offset from Windows using GetTimeZoneInformation. Add this value to a local time in order to convert it to UTC time. Raises an exception if GetTimeZoneInformation returns TIME_ZONE_ID_INVALID. llDates.pas -------------------------------------------------------------------------------- function MinMax(const AMin, AValue, AMax: Integer): Integer; overload; function MinMax(const AMin, AValue, AMax: Int64): Int64; overload; function MinMax(const AMin, AValue, AMax: Single): Single; overload; function MinMax(const AMin, AValue, AMax: Double): Double; overload; function MinMax(const AMin, AValue, AMax: Extended): Extended; overload; function MinMax(const AMin, AValue, AMax: Currency): Currency; overload; Translates directly to Max(AMin, Min(AValue, AMax)), but with less chance of the programmer messing it up. :) Overloaded just like the Min and Max functions in the Math unit. llNumbers.pas -------------------------------------------------------------------------------- function MonthDiff(const AStart, AEnd: TDateTime): Currency; Calculates the difference between two dates in calendar months. A partial calendar month becomes a fraction in the form of # days divided by the total number of days in the month. For example: 2005-01-01 to 2005-02-10 = 1.3571 -> 1.0 for January plus 0.3571 for 10 out of 28 days in February. llDates.pas -------------------------------------------------------------------------------- function MonthStrToInt(const AMonth: string): Integer; Returns the integer month number 1..12 of the given month string. It works with full month names or their abbreviations as defined by the ShortMonthNames variable. It returns zero if the string is not valid. Case-insensitive. Example: MonthStrToInt('January') -> 1 llDates.pas -------------------------------------------------------------------------------- procedure MsgAlert(const Text: String; const Caption: String = ''; AForm: TForm = nil); Shows a CenteredMsgDlg with a warning icon and an OK button. llMsgDlg.pas -------------------------------------------------------------------------------- procedure MsgError(const Text: String; const Caption: String = ''; AForm: TForm = nil); Shows a CenteredMsgDlg with an error icon and an OK button. llMsgDlg.pas -------------------------------------------------------------------------------- procedure MsgInfo(const Text: String; const Caption: String = ''; AForm: TForm = nil); Shows a CenteredMsgDlg with an information icon and an OK button. llMsgDlg.pas -------------------------------------------------------------------------------- function MsgOKCancel(const Text: String; const Caption: String = ''; AForm: TForm = nil): Boolean; Returns a True/False answer to an OK/Cancel CenteredMsgDlg. llMsgDlg.pas -------------------------------------------------------------------------------- function MsgRetryCancel(const Text: String; const Caption: String = ''; AForm: TForm = nil): Boolean; Returns a True/False answer to a Retry/Cancel CenteredMsgDlg. llMsgDlg.pas -------------------------------------------------------------------------------- function MsgYesNo(const Text: String; const Caption: String = ''; AForm: TForm = nil): Boolean; Returns a True/False answer to a Yes/No CenteredMsgDlg. llMsgDlg.pas -------------------------------------------------------------------------------- function MsgYesNoCancel(const Text: String; const Caption: String = ''; AForm: TForm = nil): Integer; Returns mrYes, mrNo or mrCancel in response to a CenteredMsgDlg. llMsgDlg.pas -------------------------------------------------------------------------------- function NextMonthDay(const ADate: TDateTime; const ADay: Integer): TDateTime; Returns a TDateTime representing the given date adjusted to the nearest future date matching the desired day of the month. Examples: NextMonthDay(<2004-05-15>, 20) -> <2004-05-20> NextMonthDay(<2004-05-15>, 15) -> <2004-06-15> If the desired day would result in an invalid date, the last valid day of the month will be used: Examples: NextMonthDay(<2004-04-01>, 31) -> <2004-04-30> NextMonthDay(<2004-08-31>, 31) -> <2004-09-30> llDates.pas -------------------------------------------------------------------------------- procedure OpenWith(const AFileName: string; const hWindow: HWND = 0; const ShowCmd: Integer = SW_SHOWNORMAL); This is a ShellExecute equivalent but shows the "Open with..." dialog on file types without an existing association. llWinAPI.pas -------------------------------------------------------------------------------- function PadC(const AInput: string; const ALen: Integer; const AChar: Char = ' '): string; Pads a string equally on both sides with to a length of . If is longer than , the middle characters will be returned. llStrings.pas -------------------------------------------------------------------------------- function PadL(const AInput: string; const ALen: Integer; const AChar: Char = ' '): string; Pads a string on the left with to a length of . If is longer than , the rightmost characters of will be returned. llStrings.pas -------------------------------------------------------------------------------- function PadR(const AInput: string; const ALen: Integer; const AChar: Char = ' '): string; Pads a string on the right with to a length of . If is longer than , the leftmost characters of will be returned. llStrings.pas -------------------------------------------------------------------------------- function ParseCSVLine(const ALine: String; Fields: TStrings; var MultiLine: Boolean; const EatWhitespace: Boolean = False; const AQuote: Char = '"'; const ADelim: Char = ','; const ANewline: String = #10): Boolean; Parses a string of CSV-formatted text into individual fields and places them into a TStrings list. Unlike TStringList.CommmaText/DelimitedText*, it only recognizes a single delimiter character and will not break unquoted fields that contain spaces or tabs. It can also handle fields that span multiple lines. *As of BDS2006, TStrings has a StrictDelimiter property to ignore all but the specified delimiter character. --- Returns: A boolean indicating if ALine contained properly formatted CSV data. Currently, only improperly quoted fields will trigger a False result. --- Arguments: ALine - A line of text from a CSV file. Fields - A TStrings/TStringlist object to hold the parsed fields. MultiLine - A var parameter that gets set to True when the procedure needs the next line from the CSV file to continue the current field/record. EatWhitespace - A boolean to determine behavior with regards to unquoted whitespace. If False (the default), unquoted whitespace is preserved. If True, this whitespace is discarded. Quoted whitespace is always preserved, while whitespace between quoted fields and delimiters/EOL is always discarded. Examples: Given the following input: ' aaa , bbb , "ccc" , " d " ' EatWhitespace | Input is parsed equivalent to... ---------------+---------------------------------- False | '" aaa "," bbb ","ccc"," d "' True | '"aaa","bbb","ccc"," d "' AQuote - The text quote character. Default=double quote (") ADelim - The field delimiter character. Default=comma (,) ANewline - The character(s) to be used in place of the actual end-of-line characters (i.e. #13#10) when storing multiline fields in the Fields stringlist. Default=#10 --- Usage: Initially, call the procedure with MultiLine set to False. The Fields list will be cleared and the line parsed according to the other options. If the function encounters a quoted field that is continued on the next line it will set MultiLine to True and return. The caller should then call the procedure again, passing the next line from the CSV file with MultiLine still set to True. The parsing of the record will continue where it left off, adding to the Fields list. MultiLine will be set to False when it finds the end of the record. When the field list contains multiline fields, the ANewline character(s) will be inserted in place of the actual end-of-line characters (usually #13#10 aka CRLF). Select a character or characters that won't get confused with the rest of the data and won't cause Fields.Count to be erroneously increased. It can be as simple as #10 or as wacky as a dozen alternating tildes & underscores. The caller can then replace this value with the desired line terminator using something like this: Memo.Text := StringReplace(Fields[x], ANewLine, #13#10, [rfReplaceAll]); --- See Also: The CSV RFC: http://www.ietf.org/rfc/rfc4180.txt llCSV.pas -------------------------------------------------------------------------------- function PosEx(const Substr, S: string; Offset: Cardinal = 1): Integer; A D5/D6 equivalent of the D7+ StrUtils.PosEx function. Works just like Pos, but accepts a character offset for where to start looking. llStrings.pas -------------------------------------------------------------------------------- procedure PostKey(hWindow: HWND; Key: Word); Sends a WM_KEYDOWN & WM_KEYUP to a window/control/component. llWinAPI.pas -------------------------------------------------------------------------------- function PrettyInt(const Value: Integer): string; overload; function PrettyInt(const Value: Int64): string; overload; function PrettyInt(const Value: Cardinal): string; overload; Returns the integer as a string with thousands separators. llNumbers.pas -------------------------------------------------------------------------------- function PrevMonthDay(const ADate: TDateTime; const ADay: Integer): TDateTime; Returns a TDateTime representing the given date adjusted to the nearest past date matching the desired day of the month, the opposite of NextMonthDay(). Examples: PrevMonthDay(<2004-05-15>, 15) -> <2004-04-15> PrevMonthDay(<2004-05-31>, 31) -> <2004-04-30> llDates.pas -------------------------------------------------------------------------------- function RandRange(const ALo, AHi: Integer): Integer; Returns a random integer between and , inclusive. This is meant as an alternative to D5's System.RandomRange which is non- inclusive, and an equivalent to Math.RandomRange in D6+. llNumbers.pas -------------------------------------------------------------------------------- function ReverseString(const AInput: string): string; A D5/D6 equivalent of the D7+ StrUtils.ReverseString function. Simply returns a string reversed. llStrings.pas -------------------------------------------------------------------------------- function RightStr(const AInput: string; const ALen: Integer): string; A D5/D6 equivalent of the D7+ StrUtils.RightStr function. Returns the rightmost characters of . If is shorter than , all of will be returned. llStrings.pas -------------------------------------------------------------------------------- function RotX(const S: string; const ARot: Integer = 13): string; Rotates the 7-bit letters in a string by a given number or characters. The number defaults to 13, for the common "ROT13" usage. llEncoding.pas -------------------------------------------------------------------------------- function SaveWindowPos(AForm: TForm; const RegKey: string; const ChangeSaveFlag: Integer = 0; OtherInfo: TStrings = nil): Boolean; Saves a form's position and size to HKCU. Values named Top, Left, Height, Width and Maximized are saved. If you plan on storing the position of multiple windows, give each a unique registry key. Use the LoadWindowPos function to read these settings back. A boolean value in this key called "SaveWindowPos" controls whether these settings get saved or not. You can change this value (it defaults to True) using the ChangeSaveFlag argument: 1: Change it to True 0: Use the current or default value -1: Change it to False -2: Change it to False and delete any saved values (Top, Left, etc.) ChangeSaveFlag makes it easy to make this a user configurable preference. The function returns True if SaveWindowPos ends up True and the settings were saved. The optional OtherInfo argument allows you to provide a tag-along list of name-value pairs that will be stored to the same registry key (as strings) and can later be retrieved using LoadWindowPos. This is handy for other window state information like splitter positions, etc. llForms.pas -------------------------------------------------------------------------------- procedure SetItemIndex(Ctl: TComboBox; const AValue: String; const ADefault: Integer = -1); overload; procedure SetItemIndex(Ctl: TListBox; const AValue: String; const ADefault: Integer = -1); overload; procedure SetItemIndex(Ctl: TCheckListBox; const AValue: String; const ADefault: Integer = -1); overload; Finds a string value in a combobox/listbox/checklistbox Items property and sets the ItemIndex to that value, or to ADefault if not found. Uses IndexOfPartial to find partial matches. llControls.pas -------------------------------------------------------------------------------- function SlashPath(const APath: string; const ASlash: Boolean): string; Calls AddSlash/StripSlash based on a True/False value, respectively. llFiles.pas -------------------------------------------------------------------------------- function Spaces(const ALen: Integer): string; Returns a string of spaces. llStrings.pas -------------------------------------------------------------------------------- function StartsWith(const APart, AWhole: string; const CaseSensitive: Boolean = True): Boolean; Returns True if is the beginning of . It will also return True if happens to be null (''). CaseSensitive is self-explanatory. llStrings.pas -------------------------------------------------------------------------------- function StoD(const DS: String): TDateTime; "String to Date" - Converts a string in 'yyyymmddhhnnsszzz' format, or a subset thereof (see DtoS) to a TDateTime. Input strings shorter than the length of the full format will have their missing values defaulted appropriately: 1 for month or day, and zero for time values. Invalid input will raise an EConvertError exception. See StoDDef and TryStoD for additional options when dealing with untrusted input. llDates.pas -------------------------------------------------------------------------------- function StoDDef(const DS: String; const ADefault: TDateTime): TDateTime; StoDDef is to StoD as StrToIntDef is to StrToInt. See also: DtoS, StoD, TryStoD llDates.pas -------------------------------------------------------------------------------- function StoT(const TS: String): TDateTime; "String to Time" - Converts a time string in 'hhnnsszzz' format, or a subset thereof (see TtoS) to a TDateTime. Input strings shorter than the length of the full format will have their missing values defaulted to zero. Invalid input will raise an EConvertError exception. See StoTDef and TryStoT for additional options when dealing with untrusted input. llDates.pas -------------------------------------------------------------------------------- function StoTDef(const TS: String; const ADefault: TDateTime): TDateTime; StoTDef is to StoT as StrToIntDef is to StrToInt. See also: TtoS, StoT, TryStoT llDates.pas -------------------------------------------------------------------------------- function StripExt(const AFile: string): string; Just an easy-to-type wrapper for ChangeFileExt(AFilename, ''); llFiles.pas -------------------------------------------------------------------------------- function StripSlash(const APath: string): string; Just a shorter way to write ExcludeTrailingPathDelimiter (or ExcludeTrailingBackslash in D5). llFiles.pas -------------------------------------------------------------------------------- function StrToAttribute(const S: string): Integer; Converts a string containing letters (ADHRS) into a numeric file attribute Characters other than ADHRS and * are ignored. A blank or invalid string will return a result of zero. See also: AttributeStr llFiles.pas -------------------------------------------------------------------------------- type TDateTimePrecision = (dtpMillennium, dtpCentury, dtpDecade, dtpYear, dtpMonth, dtpDay, dtpHour, dtpMinute, dtpSecond, dtpMillisecond); llDates.pas -------------------------------------------------------------------------------- type TDayOfTheWeek = (dowAnyDay, dowSunday, dowMonday, dowTuesday, dowWednesday, dowThursday, dowFriday, dowSaturday); llDates.pas -------------------------------------------------------------------------------- function TimeZoneStr(const LocalOffset: TDateTime): string; Converts a local UTC offset TDateTime into a string in '+/-HH:NN' format. The string is suitable for concatenation to an ISO8601 date/time string. llDates.pas -------------------------------------------------------------------------------- TIntegerList = class(TObject) public constructor Create; overload; constructor Create(const AOwnsObjects: Boolean); overload; destructor Destroy; override; property Capacity: Integer read GetCapacity write SetCapacity; property CommaText: string read GetCommaText write SetCommaText; property Count: Integer read GetCount; property DelimitedText: string read GetDelimitedText write SetDelimitedText; property Delimiter: Char read FDelimiter write FDelimiter; property Descending: Boolean read FDescending write SetDescending; property Duplicates: TDuplicates read FDuplicates write FDuplicates; property NumberFormat: string read FNumberFormat write FNumberFormat; property Objects[Index: Integer]: TObject read GetObject write SetObject; property OnChange: TNotifyEvent read FOnChange write FOnChange; property OnChanging: TNotifyEvent read FOnChanging write FOnChanging; property OwnsObjects: Boolean read FOwnsObjects write FOwnsObjects; property QuoteChar: Char read FQuoteChar write FQuoteChar; property Sorted: Boolean read FSorted write SetSorted; property Sum: Integer read GetSum; property Sum64: Int64 read FSum64; property Values[Index: Integer]: Integer read GetValue write SetValue; default function Add(const Value: Integer): Integer; function AddObject(const Value: Integer; const AObject: TObject): Integer; procedure BeginUpdate; procedure Clear; procedure Clone(const Source: TIntegerList); procedure Delete(const Index: Integer); procedure EliminateDupes; procedure EndUpdate; procedure Exchange(const Index1, Index2: Integer); function Find(const Value: Integer; var Index: Integer): Boolean; function IndexOf(const Value: Integer): Integer; function IndexOfObject(const AObject: TObject): Integer; procedure Insert(const Index, Value: Integer); procedure InsertObject(const Index, Value: Integer; const AObject: TObject); procedure Sort; end; TIntegerList works just like TStringList, but carries Integers instead of strings. There are only a few significant differences: The Sum and Sum64 properties are the sum of all the numbers in the list as an Integer and Int64, respectively. If the actual sum overflows the range of an Integer, Sum will be set to MaxInt and Sum64 will contain the correct value. Should the sum exceed the range of an Int64, the class will fall over and die. The Descending property can be used to reverse the sorting order. Custom sorting is not supported. The OwnsObjects property allows the list's Objects to be freed automatically when deleted, just like TObjectList.OwnsObjects. When False, object lifetime is the responsibility of the programmer, as it is when using TStringList. The CommaText property allows you to get or set the list as a simple string of comma-delimited integers, such as '3,21,19,11'. Assigning a string that contains non-integer values will result in an EConvertError exception. The DelimitedText property works in a similar, but more flexible manner. When output, the NumberFormat property determines the format of each value written to the string. Set it to any valid numeric format string, e.g. '%.3d' or '%m', including non-decimal format strings. If the format string does not contain one of the decimal-format letters (d,u,x) it will be considered a float-type format. Quoting of the output is done only where required. On input, DelimitedText safely handles things like quoted values and non- numeric characters like thousands separators. Any fractional digits in the input are truncated. If the NumberFormat property contains the letter "x", the values will be interpreted as hex. Scientific notation is not supported as an input format. llIntegerList.pas -------------------------------------------------------------------------------- TLikePattern = class(TObject) public property Pattern: string read FPattern write SetPattern; function Match(const S: string; const CaseInsensitive: Boolean = False): Boolean; end; TLikePattern is used to do database-style LIKE pattern matching of strings. Assign a LIKE pattern using the Pattern property, then check one or more strings to see if they match the pattern using the Match method. The method returns True when the string matches the pattern. The LIKE pattern follows the same rules as described in the PostgreSQL database docs, using the underscore for a single character match, a percent sign for a 0..n match and the backslash to escape literal underscores and percent signs. The class supports percent signs at the beginning and/or end of the pattern only. Attempting to match a string against a blank or unassigned pattern will always return False. Usage: var LP: TLikePattern; begin LP := TLikePattern.Create; try LP.Pattern := '%ray%'; while (Necessary) do begin if LP.Match(sSomeString, True) then ... // Rinse and repeat end; finally LP.Free; end; end; llLike.pas -------------------------------------------------------------------------------- procedure TokenList(const AText, AToken: string; AList: TStrings); Breaks up a string at each occurrence of and adds these substrings to a TStrings descendant, . Note that the list is not cleared before adding any strings, so do this manually if desired. This is handy when you have a simple delimited list, but TStrings.CommaText would blow chunks because the values contain spaces. It also works on tokens longer than a single character. Quoting is not supported. llStrings.pas -------------------------------------------------------------------------------- function TryAnyStrToDateTime(const DS: string; var DayPos: Integer; out OutDate: TDateTime): Boolean; Works like TryStrToDateTime, but does its best to decipher formats other than the current locale formats (which it tries first). It also handles non- numeric months (see MonthStrToInt) and DtoS-type strings (StoD). The DayPos argument is used to help interpret ambiguous dates where both the month and day values are <= 12. DayPos can be set to -1..3 and behaves according to the following table: -1 Tries the current locale format first, then uses the default behavior of using the first value <= 12 as the month. DayPos will not be modified by the function. 0 Like -1, but allows itself to be updated to 1-3 if a non-ambiguous date is encountered, so that the "learned" format can be used on future calls. 1-3 Uses the number to choose the first, second or third part of the date as the day value when it otherwise can't tell the month and day apart. When DayPos is > 0, the function does not try the current locale format first. Requires DateUtils, so D6+ only. llDates.pas -------------------------------------------------------------------------------- function TryDice(const AStr: string; out Value: Integer): Boolean; TryDice is to Dice as TryStrToInt is to StrToInt. llNumbers.pas -------------------------------------------------------------------------------- function TryFormatToDateTime(const DS, AFormat: string; out OutDate: TDateTime): Boolean; Works like TryStrToDateTime, but uses a date/time format string so it knows how to parse the string. Shorthand formats like "c" and "tt" are interpreted correctly, as are "m"s that follow "h"s. Note: The format MUST include separators or whitespace between date and time elements. Mashed-together formats like "yyyymmdd" will NOT work! Example: TryFormatToDateTime('06/30/2007 2:21 PM', 'mm/dd/yyyy h:nn ampm', D) Requires DateUtils, so D6+ only. TODO: It doesn't currently handle single- or double-quoted literals. llDates.pas -------------------------------------------------------------------------------- function TryStoD(const DS: String; out ADate: TDateTime): Boolean; TryStoD is to StoD as TryStrToInt is to StrToInt. See also: DtoS, StoD, StoDDef llDates.pas -------------------------------------------------------------------------------- function TryStoT(const TS: String; out ATime: TDateTime): Boolean; TryStoT is to StoT as TryStrToInt is to StrToInt. See also: DtoT, StoT, StoTDef llDates.pas -------------------------------------------------------------------------------- function TtoS(const DT: TDateTIme; const P: TDateTimePrecision = dtpSecond): String; "Time to String" - Works much like DtoS, but on a time value only with a 'hhnnsszzz' format. Precisions lower than dtpHour are ignored. The inverse function is StoT. llDates.pas -------------------------------------------------------------------------------- function UnusedFileName(const AFile: string): string; Takes a fully qualfied filename and if it exists, adds a number to the end of it until it no longer exists and returns the new (or unmodified) filename. Useful for exports and things where you don't want to overwrite any earlier versions of a file. The number has at least two digits (file.txt, file00.txt, file01.txt, etc.) to improve name-based sorting should there be more than nine files. llFiles.pas -------------------------------------------------------------------------------- function WeekDayDiff(const AStart, AEnd: TDateTime): Integer; Calculates the difference between two dates in weekdays. If the last day is not a weekday it doesn't count, for example Wednesday to Saturday = 2 (w-th, th-f) llDates.pas -------------------------------------------------------------------------------- function WeekdayOfMonth(const ADate: TDateTime; const Nth: Integer; const DOW: TDayOfTheWeek): TDateTime; Returns the date that falls on the Nth weekday of the given month. is the TDateTime that contains the month & year you wish the result to fall in. specifies which instance of the day of the week you wish to find, such as first, second, etc. If this value is greater than the actual number of times the weekday occurs in the month, the last occurrence will be returned. is the day of the week you wish to find. If dowAnyDay is given, the day of the week will be taken from the current value of ADate. Example: To find the second Sunday in the month of February 2005: WeekdayOfMonth(<2005-02-25>, 2, dowSunday) -> <2005-02-13> llDates.pas -------------------------------------------------------------------------------- function WildExists(const AFileSpec: string; const Attr: Integer = 0): Boolean; Given a wildcard filespec (and optional attribute), it will return true if any file specified by the wildcard exists. Can also be used as a substitute for FileExists if you wish. llFiles.pas -------------------------------------------------------------------------------- function WordPos(const AWord, AText: string; const Offset: Integer = 1; const WordChars: string = ''): Integer; Returns the position of the first "separate word" substring of AWord found in AText. The word must be surrounded by non-word characters to be considered separate, otherwise it is considered to be part of a larger word. By default, letters, numbers and underscores make up the characters that are considered part of "words". If you need different ones, use the optional WordChars argument to supply the entire list, including both upper and lower case letters if needed. Offset indicates where to start searching within AText, just like the Offset argument to PosEx. Examples: WordPos('delete', 'Do not delete it!') -> 8 WordPos('delete', 'I deleted it!') -> 0 (part of a larger word) llStrings.pas -------------------------------------------------------------------------------- function X16Decrypt(const sKey, sData: string): string; Simply a combination of XCrypt(sKey, B16Decode(sData)); llEncoding.pas -------------------------------------------------------------------------------- function X16Encrypt(const sKey, sData: string): string; Simply a combination of B16Encode(XCrypt(sKey, sData)); llEncoding.pas -------------------------------------------------------------------------------- function X32Decrypt(const sKey, sData: String): String; Simply a combination of XCrypt(sKey, B32Decode(sData)); llEncoding.pas -------------------------------------------------------------------------------- function X32Encrypt(const sKey, sData: String): String; Simply a combination of B32Encode(XCrypt(sKey, sData)); llEncoding.pas -------------------------------------------------------------------------------- function X64Decrypt(const sKey, sData: String): String; Simply a combination of XCrypt(sKey, B64Decode(sData)); llEncoding.pas -------------------------------------------------------------------------------- function X64Encrypt(const sKey, sData: String): String; Simply a combination of B64Encode(XCrypt(sKey, sData)); llEncoding.pas -------------------------------------------------------------------------------- function XCrypt(const sKey, sData: String): String; Simple XOR "encryption". The same function decrypts the data as well. llEncoding.pas --------------------------------------------------------------------------------