I.T. Discussion Community!
-Collapse +Expand
C++
Search C++ Group:

Advanced
-Collapse +Expand C++ To/From
To/FromCODEGuides
-Collapse +Expand C++ Study Test
PRESTWOODCERTIFIED
-Collapse +Expand C++ Store
PRESTWOODSTORE

Prestwood eMagazine

December Edition
Subscribe now! It's Free!
Enter your email:

   ► KBProgrammingC++Classic C La...   Print This     
 
C++ Classic C Language:
Old MS DOS Based Borland Turbo C For Text Word Processor
 
Posted 5 months ago on 7/25/2017
Take Away:

This article describes the procedural C programming for an old MS-DOS based application to perform text based word processing.

KB102799



INTRODUCTION

This is an example of procedural C code from an actual word processing application I made for a small insurance company in 1990. At the time, they were using a word processing software package called “Easypost”, which was designed specifically for the insurance industry. The customer needed something made that was more tailored to their specific needs. I was brought on board to create their new word processing program.



This was actually my first procedural C program. I had no prior experience in C programming at all, so this was going to be quite an experience. I was using a Borland Turbo C 2.0 compiler to do this.

I had to pull myself up by the bootstraps very quickly to learn this coding. I had to make the customer think I was progressing faster on this custom software project than I actually was. Half of the time I was on the telephone with Borland technical support to get answers for my many, many questions and problems. Fortunately back in 1990, they had not yet started charging for technical support and demanding credit card numbers before they would even speak to you.

Thankfully, I was able to muddle through all the learning curves and customer doubts about my ability and get the project done. There were still some glitches down the road, but for the most part the “letter processor” (that’s what the customer called it), did in fact work. They seemed much more happy with my program since it was streamlined exactly for their purposes - a crystal ball for great things to come in my new career.

EXPLANATION OF PROGRAMMING VARIABLES

Here is an overview of some of the variables I used in the word processing code. The character variable, char_receive1 contains a numerical value representing a function or navigation key. The character char_receive2 will contain the null character for these keys, because the function and navigation key taps are preceded by the null character and then their designated code. char_receive2 contains the typed character for the document, otherwise.

left_margin = left margin; 15th space in the "word_processing_matrix" character array by default, which can be changed.

overwrite_insert_mode = 0 for overwrite mode and 1 for insert mode.

reached_right_margin = 0 for no and 1 for yes.

right_margin = right margin; 79th space in the "word_processing_matrix" character array by default, which can be changed.

staging_area_wordwrap; this is the 1 dimensional character array used as a staging area to facilitate word wrap around the right hand margin as the operator is typing characters. It can hold as many characters as are in a completely filled up "word_processing_matrix" character array.

word_processing_matrix; this is the 2 dimensional character array that holds the typed characters in the positions as they would appear in the displayed screen. It is 83 single character columns across by 51 single character rows down.

HERE'S THE PROGRAMMING FOR WORD PROCESSING

Next, I present the word processing code that shows how typed characters are captured, lines of text are processed and word wrapped, scrolling, paging, etc.



// initialize text editing variables.

horizontal_row_position = left_margin;

view_port_row_cntr = 1;

overwrite_insert_mode = 0;

reached_right_margin = 0;

internal_record_cntr = 1;

// begin the "do while loop" to facilitate

// word processing logic.

do {

// receive keyboard input.

displayed_character_received = 0;

char_receive1 = 0;

char_receive2 = getch();

if ( char_receive2 == 0 ) char_receive1 = getch();

// scroll up one line in the text edit window.

if ( char_receive1 == 72 ) {

displayed_character_received = 1;

view_port_row_cntr--;

internal_record_cntr--;

 if ( view_port_row_cntr < 1 && internal_record_cntr > 0 ) {

  view_port_row_cntr = 1;

   gotoxy(left_margin, 1);

    insline();

     for ( counter1 = left_margin; counter1 <= right_margin; counter1++ ) putch(word_processing_matrix[counter1][internal_record_cntr]);

      }

if ( internal_record_cntr < 1 ) internal_record_cntr = 1;

 if ( view_port_row_cntr < 1 ) view_port_row_cntr = 1;

  gotoxy(horizontal_row_position, view_port_row_cntr);

}

// scroll down one line in the text edit window.

if ( char_receive1 == 80 ) {

displayed_character_received = 1;

view_port_row_cntr++;

internal_record_cntr++;

 if ( view_port_row_cntr > 22 && internal_record_cntr < 51 ) {

  view_port_row_cntr = 22;

   gotoxy(left_margin, 1);

    delline();

     gotoxy(left_margin, 22);

      for ( counter1 = left_margin; counter1 <= right_margin; counter1++ ) putch(word_processing_matrix[counter1][internal_record_cntr]);

       }

// sound warning beep if you are at internal line 45 in the text edit window.

if ( internal_record_cntr == 45 ) printf("%c", 7);

 if ( internal_record_cntr > 50 ) internal_record_cntr = 50;

  if ( view_port_row_cntr > 22 ) view_port_row_cntr = 22;

   gotoxy(horizontal_row_position, view_port_row_cntr);

}

// page up 22 lines in the text edit window.

if ( char_receive1 == 73 ) {

displayed_character_received = 1;

paging_variable_1 = internal_record_cntr;

internal_record_cntr = internal_record_cntr - 22;

paging_variable_2 = internal_record_cntr - view_port_row_cntr + 1;

 if ( paging_variable_2 < 1 ) {

  paging_variable_2 = 1;

   internal_record_cntr = view_port_row_cntr;

    }

if ( paging_variable_1 < 23 ) internal_record_cntr = paging_variable_1;

 if ( paging_variable_1 > 22 ) {

  clrscr();

   counter1 = 1;

do {

 gotoxy(left_margin, counter1);

  for ( counter1 = left_margin; counter1 <= right_margin; counter1++ ) putch(word_processing_matrix[counter1][paging_variable_2]);

   counter1++;

    paging_variable_2++;

} while ( counter1 != 23 );

 }

gotoxy(horizontal_row_position, view_port_row_cntr);

}

// page down 22 lines in the text edit window.

if ( char_receive1 == 81 ) {

displayed_character_received = 1;

paging_variable_1 = internal_record_cntr;

internal_record_cntr = internal_record_cntr + 22;

paging_variable_2 = internal_record_cntr - view_port_row_cntr + 1;

 if ( paging_variable_2 > 29 ) {

  paging_variable_2 = 29;

   internal_record_cntr = 28 + view_port_row_cntr;

    }

if ( paging_variable_1 > 28 ) internal_record_cntr = paging_variable_1;

 if ( paging_variable_1 < 29 ) {

  clrscr();

   counter1 = 1;

do {

 gotoxy(left_margin, counter1);

  for ( counter1 = left_margin; counter1 <= right_margin; counter1++ ) putch(word_processing_matrix[counter1][paging_variable_2]);

   counter1++;

    paging_variable_2++;

} while ( counter1 != 23 );

 }

gotoxy(horizontal_row_position, view_port_row_cntr);

}

// if F2 key is pressed, insert one line at current cursor position.

if ( char_receive1 == 60 ) {

displayed_character_received = 1;

 insline();

  for ( counter2 = 50; counter2 > internal_record_cntr; counter2-- ) {

   for ( counter1 = 1; counter1 < 81; counter1++ ) word_processing_matrix[counter1][counter2] = word_processing_matrix[counter1][counter2-1];

  }

   for ( counter1 = 1; counter1 < 81; counter1++ ) word_processing_matrix[counter1][internal_record_cntr] = ' ';

}

// if F3 key is pressed, delete one line at current cursor position.

if ( char_receive1 == 61 ) {

displayed_character_received = 1;

 delline();

 for ( counter2 = internal_record_cntr + 1; counter2 < 51; counter2++ ) {

  for ( counter1 = 1; counter1 < 81; counter1++ ) word_processing_matrix[counter1][counter2-1] = word_processing_matrix[counter1][counter2];

 }

  for ( counter1 = 1; counter1 < 81; counter1++ ) word_processing_matrix[counter1][50] = ' ';

   gotoxy(left_margin, 22);

    for ( counter1 = left_margin; counter1 <= right_margin; counter1++ ) putch(word_processing_matrix[counter1][internal_record_cntr+22-view_port_row_cntr]);

     gotoxy(horizontal_row_position, view_port_row_cntr);

}

// if right arrow key is pressed, move cursor to the right

// by one space while not exceeding the right margin.

if ( char_receive1 == 77 ) {

displayed_character_received = 1;

 horizontal_row_position++;

  gotoxy(horizontal_row_position, view_port_row_cntr);

}

// if left arrow key is pressed, move cursor to the left by

// one space while not exceeding the left margin.

if ( char_receive1 == 75 ) {

displayed_character_received = 1;

 horizontal_row_position--;

  if ( horizontal_row_position < left_margin ) horizontal_row_position = left_margin;

   gotoxy(horizontal_row_position, view_port_row_cntr);

}

// if backspace key is pressed, blank the character to the

// left and move the cursor one space to the left.

if ( char_receive2 == 8 ) {

displayed_character_received = 1;

 horizontal_row_position--;

  if ( horizontal_row_position < left_margin ) horizontal_row_position = left_margin;

   word_processing_matrix[horizontal_row_position][internal_record_cntr] = 32;

    gotoxy(horizontal_row_position, view_port_row_cntr);

     putch(32);

      gotoxy(horizontal_row_position, view_port_row_cntr);

}

// if tab key is pressed, move the cursor to column 50.

if ( char_receive2 == 9 ) {

displayed_character_received = 1;

 horizontal_row_position = 50;

  gotoxy(50, view_port_row_cntr);

}

// if delete key is pressed, then delete the character

// to the right. next, pull all characters to the right one

// space to the left in that same row to finish the operation.

if ( char_receive1 == 83 ) {

for ( counter2 = horizontal_row_position; counter2 <= right_margin; counter2++ ) {

 word_processing_matrix[counter2][internal_record_cntr] = word_processing_matrix[counter2+1][internal_record_cntr];

  putch(word_processing_matrix[counter2][internal_record_cntr]);

}

// now, test to see if there is a large enough space just

// before the right margin to fit in the first word from the

// next line below.

counter4 = 0;

for ( counter1 = left_margin; word_processing_matrix[counter1][internal_record_cntr+1] != 32; counter1++ ) counter4++;

 counter5 = 0;

  for ( counter1 = right_margin; word_processing_matrix[counter1][internal_record_cntr] == 32; counter1-- ) counter5++;

if ( counter5 > counter4 ) {

 counter6 = left_margin;

  for ( counter1 = right_margin - counter4 + 1; counter1 < right_margin+1; counter1++ ) {

   word_processing_matrix[counter1][internal_record_cntr] = word_processing_matrix[counter6][internal_record_cntr+1];

    counter6++;

  }

gotoxy(left_margin, view_port_row_cntr);

 for ( counter1 = left_margin; counter1 <= right_margin; counter1++ ) putch(word_processing_matrix[counter1][internal_record_cntr]);

// if there is enough space, then put the first word of the

// next line in that space just before the right margin.

// take this paragraph and shift the text towards the

// left margin and upward by the number of characters that

// made up the word that was placed just before the right

// margin in the current line. this paragraph should now be

// perfect in appearance. this is also where reverse wordwrap occurs.

for ( counter1 = 0; counter1 < 4000; counter1++ ) staging_area_wordwrap[counter1] = 32;

 array_cntr = -1;

  word_wrap_var = 0;

for ( counter1 = internal_record_cntr + 1; word_wrap_var == 0; counter1++ ) {

 word_wrap_var = 1;

  temp_var = counter1;

   counter6 = left_margin;

 if ( counter1 == internal_record_cntr + 1 ) counter6 = left_margin + counter4 + 1;

  for ( counter2 = counter6; counter2 <= right_margin; counter2++ ) {

   if ( word_processing_matrix[counter2][counter1] != 32 ) word_wrap_var = 0;

    array_cntr++;

     staging_area_wordwrap[array_cntr] = word_processing_matrix[counter2][counter1];

  }

if ( staging_area_wordwrap[array_cntr] == 32 && word_wrap_var == 0 ) {

 while ( staging_area_wordwrap[array_cntr-1] == 32 ) array_cntr--;

}

if ( staging_area_wordwrap[array_cntr] != 32 && word_wrap_var == 0 ) {

 array_cntr++;

  staging_area_wordwrap[array_cntr] = 32;

}

counter6 = left_margin;

}

n_rows = view_port_row_cntr;

 counter6 = left_margin;

  array_cntr = 0;

for ( counter1 = internal_record_cntr + 1; counter1 <= temp_var; counter1++ ) {

 counter4 = array_cntr;

  array_cntr = array_cntr + right_margin - left_margin + 1;

   while ( staging_area_wordwrap[array_cntr] != 32 ) array_cntr--;

    for ( counter2 = left_margin; counter2 <= right_margin; counter2++ ) word_processing_matrix[counter2][counter1] = 32;

     for ( counter3 = counter4; counter3 <= array_cntr; counter3++) {

      word_processing_matrix[counter6][counter1] = staging_area_wordwrap[counter3];

       counter6++;

     }

counter6 = left_margin;

 array_cntr++;

  if ( n_rows < 22 ) {

   n_rows++;

    gotoxy(left_margin, n_rows);

     for ( counter2 = left_margin; counter2 <= right_margin; counter2++ ) putch(word_processing_matrix[counter2][counter1]);

  }

}

}

gotoxy(horizontal_row_position, view_port_row_cntr);

}

// if the insert key is pressed, do the following:

// if text edit window is in overwrite mode, toggle to

// insert mode. if the text edit window is in insert

// mode, toggle to overwrite mode.

if ( char_receive1 == 82 ) {

overwrite_insert_flag = 0;

if ( overwrite_insert_mode == 0 ) {

 overwrite_insert_mode = 1;

  overwrite_insert_flag = 1;

   window(1,1,80,25);

    gotoxy(75, 24);

     cputs("INS");

      window(1,1,80,22);

}

if ( overwrite_insert_mode == 1 && overwrite_insert_flag == 0 ) {

 overwrite_insert_mode = 0;

  window(1,1,80,25);

   gotoxy(75, 24);

    cputs("OVR");

     window(1,1,80,22);

}

gotoxy(horizontal_row_position, view_port_row_cntr);

}

// display the entered character in the text edit window and in the array.

// 'flag_var_1 = 0' means a character was entered, versus a non-displayed input

// command.

flag_var_1 = 0;

if ( displayed_character_received == 0 && char_receive2 != 13 && char_receive2 > 31 && char_receive2 < 126 ) {

if ( overwrite_insert_mode == 0 && reached_right_margin == 0 ) {

 putch(char_receive2);

  word_processing_matrix[horizontal_row_position][internal_record_cntr] = char_receive2;

   horizontal_row_position++;

}

if ( overwrite_insert_mode == 1 ) {

 if ( word_processing_matrix[right_margin][internal_record_cntr] != 32 ) {

  temp_char = word_processing_matrix[right_margin][internal_record_cntr];

   for ( counter1 = right_margin; counter1 >= horizontal_row_position; counter1-- ) word_processing_matrix[counter1][internal_record_cntr] = word_processing_matrix[counter1-1][internal_record_cntr];

    word_processing_matrix[horizontal_row_position][internal_record_cntr] = char_receive2;

     for ( counter1 = horizontal_row_position; counter1 <= right_margin; counter1++ ) putch(word_processing_matrix[counter1][internal_record_cntr]);

      horizontal_row_position++;

       horizontal_row_position_temp = horizontal_row_position;

        flag_var_1 = 1;

         flag_var_3 = view_port_row_cntr;

          flag_var_4 = internal_record_cntr;

           internal_record_cntr++;

            view_port_row_cntr++;

             char_receive2 = temp_char;

 }

if ( word_processing_matrix[right_margin][internal_record_cntr] == 32 && flag_var_1 == 0 ) {

 if ( reached_right_margin != 1 ) {

  for ( counter1 = right_margin; counter1 >= horizontal_row_position; counter1-- ) word_processing_matrix[counter1][internal_record_cntr] = word_processing_matrix[counter1-1][internal_record_cntr];

   word_processing_matrix[horizontal_row_position][internal_record_cntr] = char_receive2;

    for ( counter1 = horizontal_row_position; counter1 <= right_margin; counter1++ ) putch(word_processing_matrix[counter1][internal_record_cntr]);

     horizontal_row_position++;

      gotoxy(horizontal_row_position, view_port_row_cntr);

 }

}

}

}

// when part of a word runs off the right hand margin, this

// code segment will do forward wordwrap in both overwrite and

// insert modes. in overwrite mode, text to the right and downward

// will be written over by text from the left and preceding line.

// in insert mode, the text to the right and downward will be

// displaced in that direction as new text is inserted.

if ( ( reached_right_margin == 1 || flag_var_1 == 1 ) && char_receive2 != 13 && char_receive2 != 32 && ( word_processing_matrix[right_margin][internal_record_cntr-1] != 32 || flag_var_1 == 1 ) ) {

 flag_var_2 = 0;

  for ( counter1 = right_margin; word_processing_matrix[counter1][internal_record_cntr-1] != 32; counter1-- ) flag_var_2 = counter1;

   for ( counter1 = 0; counter1 < 4000; counter1++ ) staging_area_wordwrap[counter1] = 32;

    array_cntr = -1;

     word_wrap_var = 0;

for ( counter7 = internal_record_cntr; word_wrap_var == 0; counter7++ ) {

 word_wrap_var = 1;

  temp_var = counter7;

   for ( counter1 = left_margin; counter1 <= right_margin; counter1++ ) {

    if ( word_processing_matrix[counter1][counter7] != 32 ) word_wrap_var = 0;

     array_cntr++;

      staging_area_wordwrap[array_cntr] = word_processing_matrix[counter1][counter7];

   }

if ( staging_area_wordwrap[array_cntr] == 32 && word_wrap_var == 0 ) {

 while ( staging_area_wordwrap[array_cntr-1] == 32 ) array_cntr--;

}

  if ( staging_area_wordwrap[array_cntr] != 32 && word_wrap_var == 0 ) {

   array_cntr++;

    staging_area_wordwrap[array_cntr] = 32;

  }

}

counter6 = left_margin;

 if ( overwrite_insert_mode == 0 ) horizontal_row_position = left_margin + right_margin - flag_var_2 + 2;

  n_rows = view_port_row_cntr;

if ( flag_var_2 != 0 ) {

 do {

  word_processing_matrix[counter6][internal_record_cntr] = word_processing_matrix[flag_var_2][internal_record_cntr-1];

   gotoxy(flag_var_2, view_port_row_cntr-1);

    putch(32);

     word_processing_matrix[flag_var_2][internal_record_cntr-1] = 32;

      flag_var_2++;

       counter6++;

 } while( flag_var_2 <= right_margin );

}

word_processing_matrix[counter6][internal_record_cntr] = char_receive2;

counter6++;

if ( flag_var_1 == 1 ) {

 word_processing_matrix[counter6][internal_record_cntr] = 32;

  counter6++;

}

horizontal_space_differential = counter6 - left_margin;

array_cntr = 0;

for ( counter1 = internal_record_cntr; counter1 <= temp_var; counter1++ ) {

 flag_var_2 = array_cntr;

  if ( counter1 != internal_record_cntr ) array_cntr = array_cntr + right_margin - left_margin + 1;

   if ( counter1 == internal_record_cntr ) array_cntr = right_margin - left_margin - horizontal_space_differential;

    while ( staging_area_wordwrap[array_cntr] != 32 ) array_cntr--;

     for ( counter2 = counter6; counter2 <= right_margin; counter2++ ) word_processing_matrix[counter2][counter1] = 32;

      for ( counter3 = flag_var_2; counter3 <= array_cntr; counter3++ ) {

       word_processing_matrix[counter6][counter1] = staging_area_wordwrap[counter3];

        counter6++;

      }

array_cntr++;

 counter6 = left_margin;

  if ( view_port_row_cntr < 23 ) {

   gotoxy(left_margin, view_port_row_cntr);

    for ( counter2 = left_margin; counter2 <= right_margin; counter2++ ) putch(word_processing_matrix[counter2][counter1]);

     view_port_row_cntr++;

  }

}

if ( flag_var_1 == 1 ) {

 view_port_row_cntr = flag_var_3;

  internal_record_cntr = flag_var_4;

   horizontal_row_position = horizontal_row_position_temp;

    gotoxy(horizontal_row_position, view_port_row_cntr);

}

  if ( reached_right_margin == 1 ) {

   view_port_row_cntr = n_rows;

    gotoxy(horizontal_row_position, n_rows);

  }

}

// this section of code adjusts the text editing variables

// as the right margin is met in the text edit window. the row

// number is incremented, and the column counter is intialized

// to the value of the left margin. if line 45 is reached, a beep

// will sound to alert the user that there are only 5 more lines

// left in the text edit window, which is scrolled up one line when

// at the bottom of the window.

reached_right_margin = 0;

if ( horizontal_row_position > right_margin || char_receive2 == 13 ) {

 if ( horizontal_row_position > right_margin && word_processing_matrix[right_margin][internal_record_cntr] != 32 ) reached_right_margin = 1;

  view_port_row_cntr++;

   internal_record_cntr++;

if ( view_port_row_cntr > 22 && internal_record_cntr < 51 ) {

 view_port_row_cntr = 22;

  gotoxy(left_margin, 1);

   delline();

    gotoxy(left_margin, 22);

     for ( counter1 = left_margin; counter1 <= right_margin; counter1++ ) putch(word_processing_matrix[counter1][internal_record_cntr]);

}

if ( internal_record_cntr > 50 ) internal_record_cntr = 50;

 if ( view_port_row_cntr > 22) view_port_row_cntr = 22;

  if ( internal_record_cntr == 45) printf("%c", 7);

   gotoxy(left_margin, view_port_row_cntr);

    horizontal_row_position = left_margin;

}

// exit the text edit window when F1 or F4 function key is pressed.

} while ( char_receive1 != 59 && char_receive1 != 62 );

PICTURES OF HOW IT WORKS

These snapshots show a progression of entering and word wrapping in the text based edit screen. 







CONCLUSION

As stated before, this was my first procedural C programming application I created for a customer in my business. The coding evolved through a long series of errors and missteps, but it worked consistently in the end. It never ceases to amaze me how people can somehow rise above their circumstances and accomplish things they had previously thought were way beyond their abilities. I took a leap of faith thinking I could create something like this in 1990 with zero experience. It just goes to show how far motivation and determination can take you.


Comments

0 Comments.
Share a thought or comment...
 
Write a Comment...
...
Sign in...

If you are a member, Sign In. Or, you can Create a Free account now.


Anonymous Post (text-only, no HTML):

Enter your name and security key.

Your Name:
Security key = P1156A1
Enter key:
Article Contributed By Douglas.M:

Please visit my software developer website for more information about my services. I offer application development as well as Android app coding services. My developer skills are best suited to dealing with custom software projects. I can perform programming for Corel Paradox as well as C# Sharp and PHP.

In my local area of northeast Ohio, I can cater to computer repair and "fix my computer" issues.

Use my contact web page today to reach me about any software design ideas you have.

Visit Profile

 KB Article #102799 Counter
439
Since 7/25/2017
-
   Contact Us!
 
PrestwoodBoards.com was developed and is maintainted by me. Do you have a question or suggestion? Do you see a problem? Contact me now. My goal is to build an ad-free and spam-free source of I.T. information with many contributers (ok to promote your website/company in your bio). Yes, my company Prestwood IT Solutions is mentioned in my bio which shows with every post, but you can contribute and promote your pet project too!

1,832 People Online Now!!  
Sign In to see who's online now!  Not a member? Join now. It's free!
Show more stats...


©1995-2017 PrestwoodBoards  [Security & Privacy]
Professional IT Services: Coding | Websites | Computer Tech