home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / PASCAL / TVTOOL.ZIP / TVSTRING.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1992-08-30  |  26.7 KB  |  825 lines

  1. {*
  2. *   TvString.pas
  3. *
  4. *   Copyright 1992 by Richard W. Hansen
  5. *
  6. *}
  7.  
  8. UNIT TvString;
  9. {$V-}
  10.  
  11.  
  12. INTERFACE
  13.  
  14.  
  15. USES
  16.   TvConst,
  17.   TvType;
  18.  
  19.  
  20. CONST
  21.   HexDigits       : Array[0..$F] of Char = '0123456789ABCDEF';
  22.  
  23.  
  24.  
  25. Procedure Pad(var S   : String;
  26.                   Len : Byte);
  27.   {- pad S to Len characters with spaces  }
  28.  
  29. Procedure LeftPad(var S   : String;
  30.                       Len : Byte);
  31.   {- left pad S to Len characters with spaces  }
  32.  
  33. Procedure PadCh(var S   : String;
  34.                     Len : Byte;
  35.                     Ch  : Char);
  36.   {- pad S to Len characters with Ch  }
  37.  
  38. Procedure LeftPadCh(var S   : String;
  39.                         Len : Byte;
  40.                         Ch  : Char);
  41.   {- left pad S to Len characters with Ch }
  42.  
  43. Procedure Trim(var S : String);
  44.   {- trim leading and trailing spaces from S }
  45.  
  46. Procedure TrimCh(var S  : String;
  47.                      Ch : Char);
  48.   {- trim leading and trailing Ch chars from S }
  49.  
  50. Procedure CopyInto(    InStr  : String;
  51.                        Column : Byte;
  52.                    var OutStr : String);
  53.   {- copy InStr into OutStr beginning at Col }
  54.  
  55. Procedure Strip(var S     : String;
  56.                     Chars : TCharSet);
  57.   {- remove the characters in Chars from S }
  58.  
  59. Function Blanks(Len : Byte): String;
  60.   {- return a string of Len spaces in S }
  61.  
  62. Procedure StrTruncate(var S   : String;
  63.                           Len : Byte);
  64.   {- Truncate S to the given length }
  65.  
  66. Function Chars(Len : Byte;
  67.                Ch  : Char): String;
  68.   {- return a string of Ch characters of Length Len in S }
  69.  
  70. Function AllBlanks(var S : String): Boolean;
  71.   {- test for an empty string (null or all spaces) }
  72.  
  73. Function HexString(I : LongInt): String;
  74.   {- return I as a Hexadecimal string }
  75.  
  76. {$IFOPT N+}
  77. Function FormatF(Mask : String;
  78.                  Flt  : Double;
  79.                  DP   : Integer): String;
  80. {$ELSE}
  81. Function FormatF(Mask : String;
  82.                  Flt  : Real;
  83.                  DP   : Integer): String;
  84. {$ENDIF}
  85.  
  86. Function FormatI(Mask : String;
  87.                  Long : LongInt): String;
  88.  
  89. {============================================================================}
  90. IMPLEMENTATION
  91.  
  92.  
  93. {+--------------------------------------------------------------------------+}
  94. {| Name       : Pad                                                         |}
  95. {| Purpose    : Return a string right-padded to length Len with blanks.     |}
  96. {| Parameters : S - string to pad                                           |}
  97. {|              Len - length to pad to                                      |}
  98. {| Returns    : Padded string in S.                                         |}
  99. {+--------------------------------------------------------------------------+}
  100. Procedure Pad(var S   : String;
  101.                   Len : Byte);
  102.  
  103.   var
  104.     SLen : Byte Absolute S;
  105.  
  106.   begin
  107.     if (SLen < Len) then
  108.     begin
  109.       FillChar(S[SLen + 1], Len - SLen, ' ');
  110.       SLen := Len;
  111.     end;
  112.   end;
  113.  
  114. {+--------------------------------------------------------------------------+}
  115. {| Name       : LeftPad                                                     |}
  116. {| Purpose    : Return a string left-padded to length Len with blanks.      |}
  117. {| Parameters : S - string to pad                                           |}
  118. {|              Len - length to pad to                                      |}
  119. {| Returns    : Padded string in S.                                         |}
  120. {+--------------------------------------------------------------------------+}
  121. Procedure LeftPad(var S   : String;
  122.                       Len : Byte);
  123.  
  124.   var
  125.     SLen : Byte Absolute S;
  126.     X    : Byte;
  127.  
  128.   begin
  129.     if (SLen < Len) then
  130.     begin
  131.       X := Len - SLen;
  132.       Move(S[1], S[X + 1], SLen);
  133.       FillChar(S[1], X, ' ');
  134.       SLen := Len;
  135.     end;
  136.   end;
  137.  
  138. {+--------------------------------------------------------------------------+}
  139. {| Name       : PadCh                                                       |}
  140. {| Purpose    : Return a string right-padded to length Len with Ch.         |}
  141. {| Parameters : S - string to pad                                           |}
  142. {|              Len - length to pad to                                      |}
  143. {|              Ch - the character to pad with                              |}
  144. {| Returns    : Padded string in S.                                         |}
  145. {+--------------------------------------------------------------------------+}
  146. Procedure PadCh(var S   : String;
  147.                     Len : Byte;
  148.                     Ch  : Char);
  149.  
  150.   var
  151.     SLen : Byte Absolute S;
  152.  
  153.   begin
  154.     if (SLen < Len) then
  155.     begin
  156.       FillChar(S[SLen + 1], Len - SLen, Ch);
  157.       SLen := Len;
  158.     end;
  159.   end;
  160.  
  161. {+--------------------------------------------------------------------------+}
  162. {| Name       : LeftPadCh                                                   |}
  163. {| Purpose    : Return a string left-padded to length Len with Ch.          |}
  164. {| Parameters : S - string to pad                                           |}
  165. {|              Len - length to pad to                                      |}
  166. {|              Ch - the character to pad with                              |}
  167. {| Returns    : Padded string in S.                                         |}
  168. {+--------------------------------------------------------------------------+}
  169. Procedure LeftPadCh(var S   : String;
  170.                         Len : Byte;
  171.                         Ch  : Char);
  172.  
  173.   var
  174.     SLen : Byte Absolute S;
  175.     X    : Byte;
  176.  
  177.   begin
  178.     if (SLen < Len) then
  179.     begin
  180.       X := Len - SLen;
  181.       Move(S[1], S[X + 1], SLen);
  182.       FillChar(S[1], X, Ch);
  183.       SLen := Len;
  184.     end;
  185.   end;
  186.  
  187. {+--------------------------------------------------------------------------+}
  188. {| Name       : Trim                                                        |}
  189. {| Purpose    : Return a string with leading and trailing blanks removed.   |}
  190. {| Parameters : S - string to trim                                          |}
  191. {| Returns    : Trimmed string in S.                                        |}
  192. {+--------------------------------------------------------------------------+}
  193. Procedure Trim(var S : String);
  194.  
  195.   var
  196.     i    : Word;
  197.     SLen : Byte absolute S;
  198.  
  199.   begin
  200.     while (SLen > 0) and (S[SLen] = ' ') do
  201.       Dec(SLen);
  202.  
  203.     i := 1;
  204.  
  205.     while (i <= SLen) and (S[I] = ' ') do
  206.       Inc(i);
  207.  
  208.     if (i > 1) then
  209.     begin
  210.       SLen := SLen - i + 1;
  211.       Move(S[i], S[1], SLen);
  212.     end;
  213.   end;
  214.  
  215. {+--------------------------------------------------------------------------+}
  216. {| Name       : TrimCh                                                      |}
  217. {| Purpose    : Return a string with leading and trailing blanks removed.   |}
  218. {| Parameters : S - string to trim                                          |}
  219. {|              Ch - the character to be trimmed                            |}
  220. {| Returns    : Trimmed string in S.                                        |}
  221. {+--------------------------------------------------------------------------+}
  222. Procedure Trimch(var S  : String;
  223.                      Ch : Char);
  224.  
  225.   var
  226.     i    : Word;
  227.     SLen : Byte absolute S;
  228.  
  229.   begin
  230.     while (SLen > 0) and (S[SLen] = Ch) do
  231.       Dec(SLen);
  232.  
  233.     i := 1;
  234.  
  235.     while (i <= SLen) and (S[I] = Ch) do
  236.       Inc(i);
  237.  
  238.     if (i > 1) then
  239.     begin
  240.       SLen := SLen - i + 1;
  241.       Move(S[i], S[1], SLen);
  242.     end;
  243.   end;
  244.  
  245. {+--------------------------------------------------------------------------+}
  246. {| Name       : Blanks                                                      |}
  247. {| Purpose    : Return a string of Len blanks.                              |}
  248. {| Parameters : Len - how many spaces                                       |}
  249. {| Returns    : A string.                                                   |}
  250. {| Notes      : Always seem to need a blank strings, so it is worth a       |}
  251. {|              separate routine.                                           |}
  252. {+--------------------------------------------------------------------------+}
  253. Function Blanks(Len : Byte): String;
  254.  
  255.   var
  256.     S    : String;
  257.     SLen : Byte Absolute S;
  258.  
  259.   begin
  260.     FillChar(S[1], Len, ' ');
  261.     SLen := Len;
  262.     Blanks := S;
  263.   end;
  264.  
  265. {+--------------------------------------------------------------------------+}
  266. {| Name       : Chars                                                       |}
  267. {| Purpose    : Return a string of Len char of Ch.                          |}
  268. {| Parameters : Len - hw many chars                                         |}
  269. {|              Ch - the desired character                                  |}
  270. {| Returns    : A string                                                    |}
  271. {+--------------------------------------------------------------------------+}
  272. Function Chars(Len : Byte;
  273.                Ch  : Char): String;
  274.  
  275.   var
  276.     S    : String;
  277.     SLen : Byte Absolute S;
  278.  
  279.   begin
  280.     FillChar(S[1], Len, Ch);
  281.     SLen := Len;
  282.     Chars := S;
  283.   end;
  284.  
  285. {+--------------------------------------------------------------------------+}
  286. {| Name       : CopyInto                                                    |}
  287. {| Purpose    : Copy InStr into OutStr at column Col.                       |}
  288. {| Parameters : InStr - the string to be inserted                           |}
  289. {|              Col   - where to insert                                     |}
  290. {|              OutStr- the string to insert into                           |}
  291. {| Returns    : The result in OutStr.                                       |}
  292. {| Notes      : This routine is great for for creating formated output.
  293. {|              This is not just another INSERT. It does not move any chars |}
  294. {|              like insert, it just overwrites the existing string. Will
  295. {|              not copy beyond the end of the Destination string.
  296. {|              Basically, you just make a string of all blanks the desired
  297. {|              length, then copy other strings into it at fixed columns.
  298. {+--------------------------------------------------------------------------+}
  299. Procedure CopyInto(    InStr  : String;
  300.                        Column : Byte;
  301.                    var OutStr : String);
  302.  
  303.   var
  304.     OutLen : Byte Absolute OutStr;
  305.     InLen  : Byte Absolute InStr;
  306.  
  307.   begin
  308.     if (InLen <> 0) then
  309.     begin
  310.       if (Column > OutLen) then
  311.         EXIT
  312.       else if (Column + InLen - 1 > OutLen) then
  313.         Move(InStr[1], OutStr[Column], OutLen - Column + 1)
  314.       else
  315.         Move(InStr[1], OutStr[Column], InLen);
  316.     end;
  317.   end;
  318.  
  319. {+--------------------------------------------------------------------------+}
  320. {| Name       : Strip                                                       |}
  321. {| Purpose    : Remove the characters in Chars from S.                      |}
  322. {| Parameters : S - the input string                                        |}
  323. {|              Chars - set of characters to be removed                     |}
  324. {| Returns    : The result in S.                                            |}
  325. {+--------------------------------------------------------------------------+}
  326. Procedure Strip(var S     : String;
  327.                     Chars : TCharSet);
  328.  
  329.   var
  330.     SLen : Byte Absolute S;
  331.     i,j  : Byte;
  332.  
  333.   begin
  334.     j := 0;
  335.  
  336.     for i := 1 to SLen do
  337.       if not (S[i] in Chars) then
  338.       begin
  339.         Inc(j);
  340.         S[j] := S[i];
  341.       end;
  342.  
  343.     Byte(S[0]) := j;
  344.   end;
  345.  
  346. {+--------------------------------------------------------------------------+}
  347. {| Name       : AllBlanks                                                   |}
  348. {| Purpose    : Test for an emtpy string.                                   |}
  349. {| Parameters : S - the string to test.                                     |}
  350. {| Returns    : Boolean - TRUE if string empty.                             |}
  351. {| Notes      : Tests for both spaces and a null string.                    |}
  352. {+--------------------------------------------------------------------------+}
  353. Function AllBlanks(var S : String): Boolean;
  354.  
  355.   var
  356.     i   : Byte;
  357.     Len : Byte Absolute S;
  358.  
  359.   begin
  360.     i := Len;
  361.  
  362.     While (i > 0) and (S[i] = ' ') do
  363.       Dec(i);
  364.  
  365.     AllBlanks := (i = 0);
  366.   end;
  367.  
  368. {+--------------------------------------------------------------------------+}
  369. {| Name       : StrTruncate                                                 |}
  370. {| Purpose    : Truncate a string to the given length.                      |}
  371. {| Parameters : S - the string to chop                                      |}
  372. {|              Len - the desired string length                             |}
  373. {| Returns    : The result in S.                                            |}
  374. {| Notes      : Only shortens does not lengthen.                            |}
  375. {+--------------------------------------------------------------------------+}
  376. Procedure StrTruncate(var S   : String;
  377.                           Len : Byte);
  378.  
  379.   var
  380.     SLen : Byte Absolute S;
  381.  
  382.   begin
  383.     if (SLen > Len) then
  384.       SLen := Len;
  385.   end;
  386.  
  387. {+--------------------------------------------------------------------------+}
  388. {| Name       : HexString                                                   |}
  389. {| Purpose    : Convert a LongInt to a hexadecimal string.                  |}
  390. {| Parameters : I - the number to convert                                   |}
  391. {| Returns    : A string                                                    |}
  392. {+--------------------------------------------------------------------------+}
  393. Function HexString(I : LongInt): String;
  394.  
  395.   var
  396.     S : String;
  397.  
  398.   begin
  399.     With THexLong(I) do
  400.     begin
  401.       S[0] := #9;
  402.       S[1] := '$';
  403.       S[2] := HexDigits[Hi(High) shr $4];
  404.       S[3] := HexDigits[Hi(High) and $F];
  405.       S[4] := HexDigits[Lo(High) shr $4];
  406.       S[5] := HexDigits[Lo(High) and $F];
  407.       S[6] := HexDigits[Hi(Low)  shr $4];
  408.       S[7] := HexDigits[Hi(Low)  and $F];
  409.       S[8] := HexDigits[Lo(Low)  shr $4];
  410.       S[9] := HexDigits[Lo(Low)  and $F];
  411.     end;
  412.  
  413.     { THIS WILL STRIP LEADING ZEROS
  414.     while (S[2] = '0') and (Length(S) > 2) do
  415.       Delete(S, 2, 1);
  416.     }
  417.     HexString := S;
  418.   end;
  419.  
  420. {+--------------------------------------------------------------------------+}
  421. {| Name       : FormatF                                                     |}
  422. {| Purpose    : Create a formatted string from a floating point number.     |}
  423. {| Parameters : Mask - the output formatting mask                           |}
  424. {|              Dbl  - the number to format                                 |}
  425. {|              DP   - Number of digits to the left of decimal place to     |}
  426. {|                     retain in the output. If DP is negative the number of|}
  427. {|                     the digits to the left is determined strictly for the|}
  428. {|                     output mask.                                         |}
  429. {| Returns    : string                                                      |}
  430. {| Notes      : The maximum mask size is 30 characters.                     |}
  431. {|                                                                          |}
  432. {|              The three characters #,@,& serve as place holders in the    |}
  433. {|              mask for the digits in the output. All other characters are |}
  434. {|              copied from the mask to the output unchanged.               |}
  435. {|                                                                          |}
  436. {|              In the output any unused # is replaced by a space, any      |}
  437. {|              unused @ is replaced by zero, and any unused & is deleted.  |}
  438. {|              The #,@,& can be mixed as desired in the mask. Given the    |}
  439. {|              same mask, calls to FormatF with different valuse of DP will|}
  440. {|              return strings with the decimal point aligned.              |}
  441. {|                                                                          |}
  442. {|              If a number is too large to fit in the given mask, all      |}
  443. {|              digits in the output will be set to *.                      |}
  444. {|                                                                          |}
  445. {|              Some examples :                                             |}
  446. {|                                                                          |}
  447. {|              Input                                     Output            |}
  448. {|              ────────────────────────────────────────────────────────────|}
  449. {|              FormatF('#####.####', 12345.6789, 4))     12345.6789        |}
  450. {|              FormatF('#####.####', 12345.6789, 3))     12345.679         |}
  451. {|              FormatF('#####.####', 1234.5678, 3))       1234.568         |}
  452. {|              FormatF('#####.####', 12345.6789, -1))    12345.6789        |}
  453. {|              FormatF('##,###.###,#', 12345.6789, 4)    12,345.678,9      |}
  454. {|              FormatF('$ ##,###.####', 12345.6789, 4)   $ 12,345.6789     |}
  455. {|              FormatF('$ ##,###.####', 123.4, 2)        $    123.4        |}
  456. {|              FormatF('$ ##,###.@@@@', 12345.6, 1)      $ 12,345.6000     |}
  457. {|              FormatF('$ &&,&&&.@@@@', 1234.56, 2)      $ 1,234.5600      |}
  458. {|              FormatF('$ &&,&&&.@@@@', 123.4, 2)        $ 123.4000        |}
  459. {|              FormatF('#####.####', 9999999.9999, 4)    *****.****        |}
  460. {|                                                                          |}
  461. {+--------------------------------------------------------------------------+}
  462. {$IFOPT N+}
  463. Function FormatF(Mask : String;
  464.                  Flt  : Double;
  465.                  DP   : Integer): String;
  466. {$ELSE}
  467. Function FormatF(Mask : String;
  468.                  Flt  : Real;
  469.                  DP   : Integer): String;
  470. {$ENDIF}
  471.  
  472.   var
  473.     RDigits : Byte;
  474.     LDigits : Byte;
  475.     DPos    : Byte;
  476.     Width   : Byte;
  477.     i       : Integer;
  478.     j       : Integer;
  479.     Left    : Boolean;
  480.     Num     : String[30];
  481.     Temp    : String[30];
  482.  
  483.   begin
  484.     if (Byte(Mask[0]) > 30) then
  485.       Byte(Mask[0]) := 30;
  486.  
  487.     Temp    := Mask;
  488.     { count digits to left and right of decimal point }
  489.     Left    := True;
  490.     RDigits := 0;
  491.     LDigits := 0;
  492.     DPos    := 0;
  493.  
  494.     for i := 1 to Length(Mask) do
  495.     begin
  496.       Case Mask[i] of
  497.         '@', '#', '&' :
  498.           begin
  499.             if Left then
  500.               Inc(LDigits)
  501.             else
  502.               Inc(RDigits);
  503.           end;
  504.  
  505.         '.' :
  506.           begin
  507.             Left := False;
  508.             DPos := i;
  509.           end;
  510.       end; {CASE}
  511.     end; {FOR}
  512.  
  513.     { adjust digits to right as needed  }
  514.     if (DP < 0) or (DP > RDigits) then
  515.       DP := RDigits;
  516.  
  517.     { calculate the total width, including decimal point  }
  518.     Width := LDigits + DP;
  519.  
  520.     if (DP > 0) then
  521.       Inc(Width);
  522.  
  523.     { convert value to string }
  524.     Str(Flt:Width:DP, Num);
  525.  
  526.     { copy the the digits left of decimal point,
  527.       from the decimal point and proceeding to the left
  528.     }
  529.     j := DPos - 1;
  530.     i := Length(Num) - DP;
  531.  
  532.     if (DP <> 0) then
  533.       Dec(i);
  534.  
  535.     While (i > 0) and (j > 0) do
  536.     begin
  537.       Case Temp[j] of
  538.         '@', '#', '&' :
  539.           begin
  540.             if (Num[i] = ' ') then
  541.             begin
  542.               i := 0;
  543.             end
  544.  
  545.             else
  546.             begin
  547.               Temp[j] := Num[i];
  548.               Dec(i);
  549.             end;
  550.           end;
  551.       end; {CASE}
  552.  
  553.       Dec(j);
  554.     end; {WHILE}
  555.  
  556.  
  557.     if (i = 0) then
  558.     begin
  559.       { copy the the digits right of decimal point,
  560.         from the decimal point and proceeding to the right
  561.       }
  562.       j := DPos + 1;
  563.       i := Length(Num) - DP + 1;
  564.  
  565.       While (i <= Length(Num)) and (j <= Length(Temp)) do
  566.       begin
  567.         Case Temp[j] of
  568.           '@', '#', '&' :
  569.             begin
  570.               Temp[j] := Num[i];
  571.               Inc(i);
  572.             end;
  573.         end; {CASE}
  574.  
  575.         Inc(j);
  576.       end; {WHILE}
  577.  
  578.       { get rid of any unneeded commas and formatting chars }
  579.       j := 0;
  580.       Num := '';
  581.  
  582.       for i := 1 to Length(Temp) do
  583.         Case Temp[i] of
  584.           '#' :
  585.             begin
  586.               Inc(j);
  587.               Num[j] := ' ';
  588.             end;
  589.  
  590.           '@' :
  591.             begin
  592.               Inc(j);
  593.               Num[j] := '0';
  594.             end;
  595.  
  596.           ',' :
  597.             begin
  598.               if (i > 1) and (i < Length(Temp)) then
  599.               begin
  600.                 if ((Temp[i - 1] = '#') or (Temp[i + 1] = '#')) then
  601.                 begin
  602.                   Inc(j);
  603.                   Num[j] := ' '
  604.                 end
  605.  
  606.                 else if (Temp[i - 1] <> '&') and (Temp[i + 1] <> '&') then
  607.                 begin
  608.                   Inc(j);
  609.                   Num[j] := Temp[i];
  610.                 end;
  611.               end
  612.  
  613.               else if (i < Length(Temp)) and (Temp[i + 1] <> '&') then
  614.               begin
  615.                 Inc(j);
  616.                 Num[j] := ' '
  617.               end
  618.  
  619.               else if (i > 1) and (Temp[i - 1] <> '&') then
  620.               begin
  621.                 Inc(j);
  622.                 Num[j] := ' '
  623.               end;
  624.             end;
  625.  
  626.           '&' :
  627.             begin
  628.             end;
  629.  
  630.           else
  631.           begin
  632.             Inc(j);
  633.             Num[j] := Temp[i];
  634.           end;
  635.         end; {CASE}
  636.  
  637.       Byte(Num[0]) := j;
  638.     end
  639.  
  640.     else  { ERROR!!!! - the number was to big for the mask  }
  641.     begin
  642.       Num := '';
  643.  
  644.       for i := 1 to Length(Mask) do
  645.         Case Mask[i] of
  646.           '@', '#', '&' :
  647.             Num[i] := '*';
  648.           else
  649.             Num[i] := Mask[i];
  650.         end; {CASE}
  651.  
  652.       Byte(Num[0]) := Length(Mask);
  653.     end;
  654.  
  655.     FormatF := Num;
  656.   end;
  657.  
  658. {+--------------------------------------------------------------------------+}
  659. {| Name       : FormatI                                                     |}
  660. {| Purpose    : Create a formatted string from an integer number.           |}
  661. {| Parameters : Mask - the output formatting mask                           |}
  662. {|              long - the number to format                                 |}
  663. {| Returns    : string                                                      |}
  664. {| Notes      : The maximum mask size is 30 characters.                     |}
  665. {|                                                                          |}
  666. {|              The three characters #,@,& serve as place holders in the    |}
  667. {|              mask for the digits in the output. All other characters are |}
  668. {|              copied from the mask to the output unchanged.               |}
  669. {|                                                                          |}
  670. {|              In the output any unused # is replaced by a space, any      |}
  671. {|              unused @ is replaced by zero, and any unused & is deleted.  |}
  672. {|              The #,@,& can be mixed as desired in the mask.              |}
  673. {|                                                                          |}
  674. {|              If a number is too large to fit in the given mask, all      |}
  675. {|              digits in the output will be set to *.                      |}
  676. {|                                                                          |}
  677. {|              Some examples :                                             |}
  678. {|                                                                          |}
  679. {|              Input                                     Output            |}
  680. {|              ────────────────────────────────────────────────────────────|}
  681. {|              FormatI('#####', 999)                      999              |}
  682. {|              FormatI('@@@@@', 999)                     0999              |}
  683. {|              FormatI('&&&&&', 999)                     999               |}
  684. {|              FormatI('##,###', 9999)                    9,999            |}
  685. {|              FormatI('&&,&&&', 9999)                   9,999             |}
  686. {|              FormatI('##,###', 999999)                 **,***            |}
  687. {|                                                                          |}
  688. {+--------------------------------------------------------------------------+}
  689. Function FormatI(Mask : String;
  690.                  Long : LongInt): String;
  691.  
  692.   var
  693.     Width   : Byte;
  694.     i       : Integer;
  695.     j       : Integer;
  696.     Num     : String[30];
  697.     Temp    : String[30];
  698.  
  699.   begin
  700.     Temp  := Mask;
  701.     { find the width of the output }
  702.     Width := 0;
  703.  
  704.     for i := 1 to Length(Mask) do
  705.     begin
  706.       Case Mask[i] of
  707.         '@', '#', '&' :
  708.           begin
  709.             Inc(Width)
  710.           end;
  711.       end; {CASE}
  712.     end; {FOR}
  713.  
  714.     { convert }
  715.     Str(Long:Width, Num);
  716.  
  717.     { Copy to output from right to left }
  718.     i := Length(Num);
  719.     j := Length(Temp);
  720.  
  721.     While (i > 0) and (j > 0) do
  722.     begin
  723.       Case Temp[j] of
  724.         '@', '#', '&' :
  725.           begin
  726.             if (Num[i] = ' ') then
  727.             begin
  728.               i := 0;
  729.             end
  730.  
  731.             else
  732.             begin
  733.               Temp[j] := Num[i];
  734.               Dec(i);
  735.             end;
  736.           end;
  737.       end; {CASE}
  738.  
  739.       Dec(j);
  740.     end; {WHILE}
  741.  
  742.     if (i = 0) then
  743.     begin
  744.       { get rid of any unneeded commas and formatting chars }
  745.       j := 0;
  746.       Num := '';
  747.  
  748.       for i := 1 to Length(Temp) do
  749.         Case Temp[i] of
  750.           '#' :
  751.             begin
  752.               Inc(j);
  753.               Num[j] := ' ';
  754.             end;
  755.  
  756.           '@' :
  757.             begin
  758.               Inc(j);
  759.               Num[j] := '0';
  760.             end;
  761.  
  762.           ',' :
  763.             begin
  764.               if (i > 1) and (i < Length(Temp)) then
  765.               begin
  766.                 if ((Temp[i - 1] = '#') or (Temp[i + 1] = '#')) then
  767.                 begin
  768.                   Inc(j);
  769.                   Num[j] := ' '
  770.                 end
  771.  
  772.                 else if (Temp[i - 1] <> '&') and (Temp[i + 1] <> '&') then
  773.                 begin
  774.                   Inc(j);
  775.                   Num[j] := Temp[i];
  776.                 end;
  777.               end
  778.  
  779.               else if (i < Length(Temp)) and (Temp[i + 1] <> '&') then
  780.               begin
  781.                 Inc(j);
  782.                 Num[j] := ' '
  783.               end
  784.  
  785.               else if (i > 1) and (Temp[i - 1] <> '&') then
  786.               begin
  787.                 Inc(j);
  788.                 Num[j] := ' '
  789.               end;
  790.             end;
  791.  
  792.           '&' :
  793.             begin
  794.             end;
  795.  
  796.           else
  797.           begin
  798.             Inc(j);
  799.             Num[j] := Temp[i];
  800.           end;
  801.         end; {CASE}
  802.  
  803.       Byte(Num[0]) := j;
  804.     end
  805.  
  806.     else  { ERROR!!!! - the number was to big for the mask  }
  807.     begin
  808.       Num := '';
  809.  
  810.       for i := 1 to Length(Mask) do
  811.         Case Mask[i] of
  812.           '@', '#', '&' :
  813.             Num[i] := '*';
  814.           else
  815.             Num[i] := Mask[i];
  816.         end; {CASE}
  817.  
  818.       Byte(Num[0]) := Length(Mask);
  819.     end;
  820.  
  821.     FormatI := Num;
  822.   end;
  823.  
  824.  
  825. END.