{***********************************************************************}
{									}
{ __DeTabStr  Return a string with tabs expanded to blanks		}
{									}
{ function __DeTabStr(Source : string; Incr : byte;			}
{				 var RemStr : string) : string; 	}
{									}
{	      Source	The string to be converted.			}
{	      Incr	Interval separating tab stops.			}
{	      RemStr	Portion of Source which could not be converted	}
{									}
{ Description __DeTabStr returns a 'detabified' string in which tab	}
{	      characters (#9) have been replaced with spaces (#32)	}
{	      to advance to the following tab position. 		}
{									}
{	      If Incr is greater than 0, tab stops are set every Incr	}
{	      characters starting from the first character in the	}
{	      returned string.	When a tab is encountered in Source,	}
{	      sufficient spaces are inserted into the returned		}
{	      string to advance to the next tab stop.  If Incr is 0,	}
{	      an unchanged copy of Source will be returned.  If part of }
{	      Source remains unconverted when the returned string	}
{	      length has reached the maximum string length (MAXSTR_)	}
{	      __DeTabStr truncates the returned string at that point	}
{	      and returns the unconverted part of Source in the string	}
{	      parameter RemStr. 					}
{									}
{ Version     4.00 (C)Copyright Blaise Computing Inc.  1987		}
{_______________________________________________________________________}

function __DeTabStr(Source : string; Incr : byte;
			       var RemStr : string) : string;

  const
    TAB   = #9;
    BLANK = #32;

  var
    NumSpaces : word;
    SourceIdx : word;		       { Index into the source		}
    TargetIdx : word;		       { Index into the target		}
    Len       : word;		       { Length of the returned string	}
    ThisCh    : char;

  begin {__DeTabStr}

    { If the source is NULL or Incr is nonpositive, then just exit	}
    { immediately.							}

    if ((Length(Source) = 0) or (Incr <= 0)) then
      begin
	__DeTabStr := Source;
	RemStr	   := '';
	Exit
      end;

    Len       := 0;
    SourceIdx := 0;
    TargetIdx := 0;

    repeat
      Inc(SourceIdx);
      ThisCh := Source[SourceIdx];
      if (ThisCh = TAB) then
	 begin
	   NumSpaces := Incr - (TargetIdx mod Incr);
	   if (NumSpaces > 0) then
	      repeat
		Inc(TargetIdx);        { Adjust index into returned	}
		Dec(NumSpaces);        { string.			}
		if (TargetIdx <= MAXSTR_) then
		  begin
		    Len 		  := TargetIdx;
		    __DeTabStr[TargetIdx] := BLANK
		  end
		else
		  NumSpaces := 0
	      until (NumSpaces = 0);
	 end
      else
	 begin
	   Inc(TargetIdx);
	   Len			 := TargetIdx;
	   __DeTabStr[TargetIdx] := ThisCh
	 end;
    until ((SourceIdx = Length(Source)) or (TargetIdx >= MAXSTR_));

    if (SourceIdx < Length(Source)) then
       RemStr := Copy(Source,SourceIdx,MAXSTR_)
    else
       RemStr := '';

    __DeTabStr[0] := Chr(Len)

  end; {__DeTabStr}
