Current area: HOME -> Blogs -> Actor's Blog -> Read Post

Detabbing

Posted on Tuesday, January 01, 2008 at 9:08 AM
DeTab is the inverse of EnTab. Here is the specification:

{
PROGRAM
      DeTab    -- convert tabs to blanks
USAGE
      DeTab
FUNCTION
      DeTab copies its input to its output, expanding horizontal tabs to 
      blanks along the way, so that the output is visually the same as the        
      input, but contains no tab chars.  Tab stops are assumed to be set
      every three columns (i.e., 1, 4, 7, 10, ...), so that each tab char
      is replaced by from one to three blanks.
BUGS
      1. DeTab is naive about backspace, vertical motions, and
         non-printing chars.
      2. Each line of output will be truncated at MAXSTR chars.
      3. Trailing BLANKS will be trimmed from each line of output.
}


DeTab's main routine echos EnTab's, reducing the problem to one of detabbing a single string. To detab the string we could try to simply apply EnTab's strategy in reverse, however, this is another chance to apply the "how would a human do it?" approach.

How would a human do it? If a human is sitting at a typewriter typing the incoming text, what is happening? First, he is looking at a blank sheet of paper. At least the current line is blank. If he hits any other than the TAB key the corresponding letter/character gets typed. Even if he hits the space bar a character, a BLANK, gets typed, even though what actually happens is that the carriage moves one space to the left (effectively moving the print head to the right). However, if he hits the TAB key the carriage moves to the left until it hits a tab stop, printing nothing and leaving the print head at the tab stop awaiting the next character.

This is the behavior we will try to emulate. We will copy the input string to an output string. But first we will fill the output string with BLANKS, effectively giving us a blank line. We will use an index i for the input string and j for the output string. If the char is not a TAB then we will copy the char and increment both i and j. However, if it is a TAB we increment i once but we increment j repeatedly until we get to a tab stop.

To deal with the situation of what happens when we encounter a TAB after the last tab stop we cease incrementing j once it exceeds MAXSTR. We also do an early exit from the routine should j exceed MAXSTR. In keeping with our previous philosophy we do not expect this to happen but it could. If it does the program exits cleanly, albeit with a corrupted output. We will simply live with this known bug.

Finally, we trim the end of the output string of any BLANKS. This means that any trailing BLANKS in the input string will not get copied to the output. Strictly speaking this is a bug but it is unlikely to cause problems. Again we will live with it.

The function RTrim gets rid of trailing BLANKS. We will add it to Tools. While we are at it we will also add LTrim, which gets rid of leading BLANKS, and Trim, which does both. I will post the code next time.

Program DeTab ;
{
   DeTab -- replace blanks with tabs and blanks
}
Uses
   Tools,
   TabsUnit ;
      Procedure DeTabStr (Var S : String) ;
      {
         Detab a string
      }
      Var
         i     :  Byte ;
         j     :  Word ;
         T     :  String ;
      begin { DeTabStr }
         {
            clear target string
         }
         T := '' ;
         while Length(T) < MAXSTR do
            T := T + BLANK ;
         j := 1 ;
         for i := 1 to Length(S) do begin
            if j > MAXSTR then      { not likely but not impossible }
               Break ;                  
            Case S[i] of
               TAB :
                  repeat
                     j := j + 1
                  until (j in TabSet) OR (j > MAXSTR)
               else
                  begin
                     if j <= MAXSTR then
                        T[j]  := S[i] ;
                     j     := j + 1
                  end
            end { Case }
         end ;
         S := RTrim(T)
      end ; { DeTabStr }
Var
   S      :  String ;
begin { DeTab }
   SetTabs ;
   while NOT eof do begin
      ReadLn (S) ;
      DeTabStr (S) ;
      WriteLn (S)
   end
end.  { DeTab }
Tags: Trim

Comments
No comments posted yet.


Sponsored links

Build IT Knowledge with Current & Trusted Content
Helps Employees Develop & Hone New Technical Programming Skills. Sign Up & Get Full Access.
Check Out IT Certification Preparation Materials
Sign Up With SkillSoft & Get Access to Training Materials for Over 50 Professional Certifications.
Localize software in three simple steps
Localize .Net, C/C++ & Delphi apps visually. HTML, HTML Help, XML & databases. Try Sisulizer now!
Delphi Localization Tool Sisulizer (WYSIWYG)
Create multilingual Delphi apps in three simple steps. Localize XML, HTML Help ... Try Sisulizer now
Web based bug tracking - AdminiTrack.com
AdminiTrack offers an effective web-based bug tracking system designed for professional software development teams.


Newsletter | Submit Content | About | Advertising | Awards | Contact Us | Link to us |
© 1996-2008 Community Networks Ltd All rights reserved. Reproduction in whole or in part, in any form or medium without express written permission is prohibited. Violators of this policy may be subject to legal action. Please read Terms Of Use and Privacy Statement for more information. Development by Synchron Data - .NET development.