Unit KgStr;
interface

{This unit defines some generally useful utilities for manipluating
strings in Turbo Pascal 6.0 or greater. Unless noted otherwise, the
routines in this unit will function in either Real or Protected mode.
This unit is under constant development of course, and will be
frequently updated as more routines are added.

  Author: Keith Greer
          68 Tamworth Rd.
          Troy, OH  45373-1551

  C'Serve ID: 73457,3042
    Internet: greerk@wpdis11.hq.aflc.af.mil

}

function FixLen(AnyString:string; PadChar: char; FldSize:word) :string;
function SpaceOut(AnyString:string) :string;

implementation

{///////////////////////// FixLen ///////////////////////////

FixLen takes a string and pads it with PadChar until the result is
FldSize in length. This is typically useful for appending period leaders
(.....) to the end of a string, or creating dividers by passing a nul
string: FixLen('','=',80) for example.}

function FixLen(AnyString:string; PadChar: char; FldSize:word) :string;
                                                             assembler;
asm
        PUSH    DS              {Save Data Segment}
        CLD                     {Clear direction flag}
        LDS     SI,AnyString    {DS:SI-->AnyString}
        LES     DI,@Result      {ES:DI-->String to be returned}
        MOV     BX,DI           {Save DI value for later}
        LODSB                   {AL has Length(AnyString)}
        CBW                     {Make AL into word in AX}
        STOSB                   {Put the length into Result & Inc(DI)}
        MOV     CX,AX           {Length in CX}
        REP     MOVSB           {Pad=AnyString}
        MOV     CX,FldSize      {CX has FldSize}
        XOR     CH,CH           {Make FldSize=FldSize mod 256}
        MOV     ES:[BX],CL      {Make Length(Pad)=FldSize}
        SUB     CX,AX           {CX=FldSize-Length(AnyString)}
        JB      @1              {Return truncated string if CX<0}
        MOV     AL,PadChar      {else load character to pad}
        REP     STOSB           {and pad to FldSize}
@1:                             {Go back}
        POP     DS              {Restore Data Segment}
end;

{//////////////////////// SpaceOut /////////////////////////

SpaceOut trims the leading and trailing spaces from AnyString and
returns the result. Useful for bulletproofing your user interface.}

function SpaceOut(AnyString:string) :string; assembler;
asm
        PUSH    DS              {Save Data Segment}
        CLD                     {Clear direction flag (search forward)}
        LES     DI,AnyString    {ES:DI-->AnyString}
        MOV     AL,ES:[DI]      {Get the length of AnyString}
        CBW                     {Make it a word}
        MOV     CX,AX
        JCXZ    @1              {AnyString was ''!}
        INC     DI              {ES:DI-->First char of AnyString}
        MOV     DX,DI           {DX has first char offset}
        ADD     DX,AX           {Add the length}
        MOV     AL,' '          {What to look for}
        REPE    SCASB           {Keep looking till out of spaces or string}
        JE      @1              {Had a string full of spaces, jump}
        DEC     DI              {Move back to the first non-blank}
        MOV     SI,DI           {and put the offset into SI}
        STD                     {Search backwards}
        MOV     DI,DX
        DEC     DI              {DI->last character}
        MOV     CX,DX           {Calculate how many characters to search}
        SUB     CX,SI
        JCXZ    @3              {None to search}
        REPE    SCASB           {Do it}
        JE      @1              {All spaces}
        INC     DI              {DI->last non-blank character}
        INC     DI
        MOV     DX,DI           {Set new EOS}
@3:
        PUSH    ES
        POP     DS              {DS:SI-->First non-blank in AnyString}
        MOV     AX,DX           {AX has offset of last char}
        SUB     AX,SI           {minus current offset}
        LES     DI,@Result      {ES:DI-->Result}
        CLD                     {Make sure we go forward again}
        STOSB                   {Save the length into Result}
        MOV     CX,AX
        REP     MOVSB           {Get the remainder of AnyString into Result}
        JMP     @2              {All done}
@1:
        LES     DI,@Result
        MOV BYTE PTR ES:[DI],0  {Make Result=''}
@2:                             {Go back}
        POP     DS              {Restore Data Segment}
end;

end.
