home *** CD-ROM | disk | FTP | other *** search
/ ftp.wwiv.com / ftp.wwiv.com.zip / ftp.wwiv.com / pub / BBS / NSDEDIT2.ZIP / EDTKT06B.ZIP / EDIT.CPP < prev    next >
C/C++ Source or Header  |  1994-12-23  |  29KB  |  1,118 lines

  1. /***********************************************************************
  2. *                                                                      *
  3. *  Implementation of all the edit stuff                                *
  4. *                                                                      *
  5. *  Purpose : Fullscreen editor functions                               *
  6. *                                                                      *
  7. *  Author  : Peter Bloemendaal                                         *
  8. *            Brainbox systems +31-70-3523661                           *
  9. *  eMail   : internet -> bloemendaal@rullf2.LeidenUniv.nl              *
  10. *            fidonet  -> 2:281/908                                     *
  11. *                                                                      *
  12. *----------------------------------------------------------------------*
  13. *                                                                      *
  14. *  Modified by Phil Ward                                               *                     *
  15. *           Nytech Software Design                                     *
  16. *                                                                      *
  17. *                                                                      *
  18. * $Log: edit.cpv $
  19. // Modification  Dec 23, 1994  14:44:12 UTC +5  Nytech Software Design
  20. // Added the Append File routine 
  21. //
  22. // Revision 1.4  1994/09/08  08:36:27  BRAINBOX
  23. // 1. Removed most #if 0 statements put in by I_A and beatified source
  24. //
  25. // Revision 1.3  1994/09/06  18:56:13  BRAINBOX
  26. // 1. Bounce checked by I_A
  27. //
  28. // Revision 1.2  1994/08/25  20:04:34  BRAINBOX
  29. // rcsco edit.cpp
  30. //
  31. // Revision 1.1  1994/08/23  21:56:12  BRAINBOX
  32. // Initial revision
  33. //
  34. *                                                                      *
  35. ************************************************************************
  36. */
  37.  
  38. // I_A: all txtlength /* strlen(txt) */  has been replaced by 'txtlength /* txtlength /* strlen(txt) */  */' ...
  39.  
  40. #ifndef _EDIT_CPP
  41. #define _EDIT_CPP
  42.  
  43. #ifndef _PB_SDK_H
  44. #include <stdio.h>
  45. #include <conio.h>
  46. #include <stdlib.h>
  47. #include <string.h>
  48. #include <io.h>
  49. #endif
  50.  
  51. #include "key_def.h"
  52. #include "edit_glb.h"
  53.  
  54.  
  55. #include "INPUT.CPP"
  56. #include "OUTPUT.CPP"
  57. #include "EDIT.HPP"
  58.  
  59. // Copy the current screen to the old screen
  60. void Edit::copyScreen(void)
  61. {
  62.      register int i ;
  63.  
  64.      for (i = 0 ; i < height ; i++)
  65.       memcpy(oldScreen[i],curScreen[i], width+1) ; // I_A: memcpy() is faster than strcpy()
  66. }
  67.  
  68. int Edit::setMargins(int top, int bottom, int tops, int bots)
  69. {
  70.    if (top + bottom + 1 >= width)
  71.       return 1 ;
  72.    if (top <= tops || bottom <= bots)
  73.       return 1 ;
  74.  
  75.    topMargin    = top ;
  76.    bottomMargin = bottom ;
  77.    topSens      = tops ;
  78.    bottomSens   = bottom ;
  79.    return 0 ;
  80. }
  81.  
  82.  
  83. // Add a character in the edit box at the currect position
  84. void Edit::addchar(char ch)
  85. {
  86.  
  87.    if(!c_fEditable) return;
  88.  
  89.    if (insertmode)
  90.      {
  91.      if (txtlength /* strlen(txt) */  + (_BLOCK/2) > memmaltxt)
  92.      {
  93.         if(memmaltxt == 0xFFFF) {
  94.            err = TRUE;
  95.            return;
  96.         }
  97.         // realloc more memory
  98.         if(memmaltxt > 0xFFFF - _BLOCK ) {
  99.            memmaltxt = 0xFFFF;
  100.                 } else {
  101.            memmaltxt += _BLOCK ;
  102.         }
  103.         // I_A: since I had to fix this code anyway, strtcols memory has become indepentdant of 'txt'
  104.         if ( (txt = (unsigned char*) realloc(txt, memmaltxt)) == NULL)
  105.            err = 1 ;
  106.      }
  107.      memmove(txt+curpos+1, txt+curpos, txtlength /* strlen(txt) */  - curpos + 1); // +1 for traling '\0'
  108.      txtlength++;  // I_A: update length
  109.      txt[curpos++] = ch ;
  110.    }
  111.    else         // Insert mode is false
  112.    {
  113.       if (curpos == txtlength   )
  114.       {
  115.          if (txtlength  + (_BLOCK/2) > memmaltxt)
  116.          {
  117.             // realloc more memory
  118.             memmaltxt += _BLOCK ;
  119.             if ( (txt = (unsigned char*) realloc(txt, memmaltxt)) == NULL)
  120.                err = 1 ;
  121.          }
  122.                  txt[curpos++] = ch ;
  123.          txt[curpos] = '\0' ;
  124.          txtlength++; // I_A: update length...
  125.       } else
  126.          txt[curpos++] = ch ;
  127.    }
  128. }
  129.  
  130. // Delete the character before the current position
  131. void Edit::backspace(void) // actually backspace()
  132. {
  133.      if(!c_fEditable) return;
  134.  
  135.    if (curpos != 0) {
  136.       if (insertmode) {
  137.          register char *txtp = txt + curpos;
  138.          memmove(txtp-1,txtp, txtlength - curpos +1) ; // +1 for trailing '\0'
  139.          curpos--;
  140.          txtlength--;
  141.       } else {
  142.          txt[--curpos] = ' ' ;
  143.       }
  144.    }
  145. }
  146.  
  147. // Delete the character at the current position
  148. void Edit::delpos(void)
  149. {
  150.    if(!c_fEditable) return;
  151.  
  152.    {
  153.    register char *txtp = txt + curpos;
  154.  
  155.    if (curpos == txtlength)
  156.       return ;
  157.    memmove(txtp, txtp + 1, txtlength - curpos) ; // seems to be ok!
  158.    }
  159.    txtlength--;
  160. }
  161.  
  162.  
  163. void Edit::cursorDown(void)
  164. {
  165.    register unsigned short newpos; // I_A: unsigned unsigned short newpos; ???
  166.    register unsigned short i ;
  167.  
  168.      newpos = strtcols[lincur+1] ;
  169.    if (newpos < txtlength )
  170.    {
  171.       for  (i = newpos ; i <= strtcols[lincur+2] && txt[i] != '\n'
  172.          && i < txtlength   && i - newpos < colpos ; i++)
  173.          ;
  174.       if (txt[i] == '\n' && txt[i+1] == '\n' )
  175.          i++ ;
  176.       curpos = i ;
  177.      }
  178. }
  179.  
  180.  
  181. void Edit::cursorUp(void)
  182. {
  183.    register unsigned short i ;
  184.    if (linpos)
  185.    {
  186.  
  187.       register unsigned int lincurpos_1 = strtcols[lincur-1];
  188.       register unsigned int lincurpos_0 = strtcols[lincur];
  189.  
  190.       for (i = lincurpos_1 ; i <= lincurpos_0 && txt[i] != '\n'
  191.          &&  i - lincurpos_1 < colpos ; i++)
  192.             ;
  193.  
  194.       if (txt[i] == '\n' && txt[i+1] == '\n' && i != 0)
  195.          i++ ;
  196.       curpos = i ;
  197.    }
  198. }
  199.  
  200. void Edit::pagedown(void)
  201. {
  202.    register int right ;
  203.  
  204.    right = curpos - strtcols[lincur]  ;
  205.      curpos = strtcols[min(linmax,lincur + height)] ;
  206.    for ( ; txt[curpos] != '\n' && txt[curpos] != '\0' && right ; right--)
  207.       curpos++ ;
  208. }
  209.  
  210. void Edit::pageup(void)
  211. {
  212.    register int right ;
  213.  
  214.      right = curpos - strtcols[lincur]  ;
  215.      curpos = strtcols[max(0,lincur - height)] ;
  216.    for ( ; txt[curpos] != '\n' && txt[curpos] != '\0' && right ; right--)
  217.       curpos++ ;
  218. }
  219.  
  220. // Newline
  221. // Implemented to override for special occasions
  222. void Edit::newline(void)
  223. {
  224.    if(!c_fEditable) {
  225.       cursorDown();
  226.    } else {
  227.       addchar('\n') ;
  228.    }
  229. }
  230.  
  231. // Cursor Home
  232. void Edit::home(void)
  233. {
  234.      curpos = strtcols[lincur] ;
  235. }
  236.  
  237. // Cursor End
  238. void Edit::end(void)
  239. {
  240.    register unsigned short i ;
  241.    register unsigned int lincurpos_1 = strtcols[lincur+1];
  242.  
  243.    for (i = strtcols[lincur] ; i < lincurpos_1 - 1
  244.       && i < txtlength /* strlen(txt) */  ; i++)
  245.       ;
  246.    if (txt[i+1] == '\n')
  247.          i++ ;
  248.    curpos =  i ;
  249. }
  250.  
  251. void Edit::deleteLine(void)
  252. {
  253.    unsigned short start, end ;
  254.  
  255.    if(!c_fEditable) return;
  256.  
  257.    if (curpos == txtlength)
  258.       return ;
  259.    start = strtcols[lincur] ;
  260.     end   = strtcols[min(linmax,lincur+1)] ;
  261.    if (lincur == linmax)
  262.       end = strlen(txt) ;
  263.    if (start != end)  // I_A added condition
  264.    {
  265.       memmove(txt+start, txt+end, strlen(txt)-end+1) ;  // I_A: changed (optimized strlen())
  266.       txtlength -= end - start;
  267.       curpos = strtcols[lincur] ;
  268.    }
  269.    else
  270.    {
  271.       this->delpos() ;
  272.       curpos = strtcols[lincur]+1 ;
  273.  
  274.    }
  275. }
  276.  
  277. void Edit::deleteWord(void)
  278. {
  279.    register unsigned short i ;
  280.  
  281.    if(!c_fEditable) return;
  282.  
  283.    for (i = curpos ; i <= txtlength  && txt[i] != ' ' && txt[i] != '\n' ; i++)
  284.       ;
  285.    // I_A: memmove() optimized (strlen())
  286.    memmove(txt+curpos,txt + i + 1, strlen(txt + i + 2)) ; // +1 for trailing '\0'
  287.    txtlength -= i + 1 - curpos;
  288. }
  289.  
  290. // Calculate the line and column number from which the
  291. // virtual screen starts displaying its text!
  292. // Calculate the value of variables to position the virtual window
  293. // later and position the cursor in the virtual window.
  294. //
  295. // strtcols[]  array to integers holding first position of a line
  296. // lincur      line in the text (a strtcol[]) at which the cursor stands
  297. // linorg      first line in virtual window
  298. // curpos      position in the txt of the cursor
  299. // linpos      line postion of the cursor in the virtual window
  300. // colpos      column position of the curosr in the virtual window
  301. //
  302. // lin         line counter
  303. // col         column counter
  304. // lastspace   position in txt of the last space (used for word wrapping)
  305. //
  306. // This routine is the speed bottleneck of this program
  307. //
  308. void Edit::calculateLineColumn(void)
  309. {
  310.      unsigned short lin, col, linorg, lastspace,
  311.                                     startline, startpos ;
  312.      register unsigned short i ;
  313. //     unsigned short linlast; // I_A added
  314.     unsigned short i_limit;
  315.  
  316.      col = lastspace = 0 ;
  317.      linpos = colpos = -1 ;
  318.      strtcols[0] = 0 ;
  319.  
  320.    // Calculate start line and position, so not the whole text has to be
  321.     // calculated. This works because the maximal cursor displacement is height
  322.    startline = max(0,lincur - height) ;
  323.    if (startline >= memmalint)
  324.    {
  325. #ifdef DEBUG
  326.       printf("%d[%s] >>> reallocating strtcol[] array.\n", __LINE__, __FILE__);
  327. #endif
  328.       if ( (strtcols = (unsigned int*) realloc(strtcols, (memmalint = startline + STRTCOLS_INCREMENT) * sizeof(*strtcols))) == NULL)
  329.       {
  330.          printf("out of memory allocating index array\n");
  331.          exit(1);
  332.       }
  333.    }
  334.    startpos  = strtcols[startline] ;
  335.     lin = startline ;
  336. //    linlast = lin + height * 2; // I_A added
  337.  
  338.     // Browse the text from the starting point height*width after curpos is reached
  339.      // I_A: 'invariant code motion' (wat een kreet! wow!) 'curpos + height*width does not change inside loop: optimize!
  340.     for (i=startpos, i_limit = curpos + height*width ;
  341.         txt[i] != '\0' && i < i_limit;
  342.                 i++)
  343.    {
  344.       if (txt[i] == '\n' || col >= width )// Cursor has to go to the next line
  345.         {
  346.            col = 0 ;
  347.            if ( i == curpos)
  348.                  linpos = lin ;
  349.            if (txt[i] != ' ' && txt[i] != '\n' && lastspace != 0 )
  350.                                                                              // Wrapping of words are needed!
  351.            {
  352.                  col = width - lastspace - 1 ; // Calculate new column
  353.                  if (i - (width - lastspace) < curpos && i >= curpos && linpos != -1)
  354.                        linpos++ ;                 /* If curpos was in wrapped part,
  355.                                                                                    increase linposition           */
  356.            }
  357.            lin++ ;
  358.       if (lin >= memmalint)
  359.       {
  360. #ifdef DEBUG
  361.          printf("%d[%s] >>> reallocating strtcol[] array.\n", __LINE__, __FILE__);
  362. #endif
  363.          if ( (strtcols = (unsigned int*) realloc(strtcols, (memmalint += STRTCOLS_INCREMENT) * sizeof(*strtcols))) == NULL)
  364.          {
  365.             printf("out of memory allocating index array\n");
  366.             exit(1);
  367.          }
  368.       }
  369.        if (col != 0 || txt[i] != ' ' || txt[i-1] == ' ' )
  370.            if (txt[i] == '\n')
  371.               strtcols[lin] = i ;
  372.             else
  373.                strtcols[lin] = i - col++ ;
  374.                 lastspace = 0 ;
  375.         }
  376.         else
  377.         {
  378.            if (txt[i] == ' ')
  379.                  lastspace = col ;
  380.            if ( i == curpos)
  381.                  linpos = lin ;
  382.            if ( txt[i] != ' ' || col != 0 || lin == 0 || txt[i-1] == ' ' )
  383.             strtcols[lin] = i - col++ ;
  384.       }
  385.    }  // Next i
  386.  
  387.    if (lin+2 >= memmalint)
  388.    {
  389. #ifdef DEBUG
  390.       printf("%d[%s] >>> reallocating strtcol[] array.\n", __LINE__, __FILE__);
  391. #endif
  392.       if ( (strtcols = ( unsigned int*) realloc(strtcols, (memmalint += STRTCOLS_INCREMENT) * sizeof(*strtcols))) == NULL)
  393.       {
  394.          printf("out of memory allocating index array\n");
  395.          exit(1);
  396.       }
  397.    }
  398.    strtcols[lin+1] = MAXINT ;
  399.     strtcols[lin+2] = MAXINT ;
  400.     linmax = lin ;
  401.  
  402.     // Calculate the column position
  403.     if (linpos == - 1)
  404.         linpos = lin ;
  405.     colpos = curpos - strtcols[linpos] ;
  406.     if (txt[curpos-1] == '\n' && linpos > 0)
  407.        colpos = max(0,curpos - strtcols[linpos] - 1);
  408.  
  409.     // Remember the actual position of the line in the text of the cursor
  410.     lincur = linpos ;
  411.  
  412.     // Calculate the virtual window position
  413.    for (linorg = 0 ; linorg <= lin ; linorg++)
  414.        if (strtcols[linorg] == virorg)
  415.       break ;
  416.    if (linorg == lin)
  417.       linorg = 0 ;
  418.  
  419.    if (linpos < linorg + topSens)
  420.         virorg = strtcols[max(0,linpos - topMargin + 1)] ;
  421.     if (linpos + bottomSens > linorg + height)
  422.         virorg = strtcols[max(0,linpos - (height - bottomMargin) - 1)] ;
  423.     for (linorg = 0 ; linorg <= lin ; linorg++)
  424.        if (strtcols[linorg] == virorg)
  425.            break ;
  426.     linpos = lincur - linorg ;
  427. }
  428.  
  429.  
  430.  
  431. void Edit::formatText(void)
  432. {
  433.      register unsigned short i;
  434.      short lin, col;
  435.      short lastspace;
  436.  
  437.    // Clear the whole textscreen
  438.    for (i = 0 ; i < height ; i++) // I_A
  439.    {
  440.       memset(curScreen[i], ' ', width);
  441.       curScreen[i][width] = '\0';
  442.    }
  443.  
  444.    lin = 0 ;
  445.    col = 0 ;
  446.     lastspace = 0 ;
  447.  
  448.    calculateLineColumn() ;
  449.  
  450.    // Now fill in the textscreenlines
  451.     for (i=virorg ; lin < height && txt[i] != '\0' ; i++)
  452.    {
  453.       if (txt[i] == '\n' || col >= width )
  454.       {
  455.          col = 0 ;
  456.          if (txt[i] != ' ' && txt[i] != '\n' && lastspace != 0)   // Wrapping of words are needed!
  457.          {
  458.             if ((lin + 1) < height) // I_A
  459.             {
  460.                strcpy(curScreen[lin+1],curScreen[lin]+lastspace+1) ;
  461.                col = width - lastspace - 1 ;
  462.             }
  463.             // I_A: you *know* how wide every line is!
  464.             // Clear from lastspace to \0
  465.             memset(curScreen[lin] + lastspace + 1, ' ', width - lastspace - 1);
  466.          }
  467.          if (i != virorg || txt[i] != '\n')
  468.             lin++ ;
  469.          if (i == 0 && txt[0]== '\n')
  470.             lin++ ;
  471.                 if (lin >= height) // I_A added
  472.               break;
  473.          if (col != 0 || txt[i] != ' ' || txt[i-1] == ' ')
  474.             if (txt[i] != '\n')
  475.                    curScreen[lin][col++] = txt[i] ;
  476.  
  477.          lastspace = 0 ;
  478.       }
  479.       else
  480.       {
  481.          if (txt[i] == ' ')
  482.             lastspace = col ;
  483.  
  484.             // don't show the space used for wrapping at the start of the new line
  485.          if (txt[i] != ' ' || col != 0 || lin == 0 || txt[i-1] == ' ')
  486.             curScreen[lin][col++] = txt[i] ;
  487.       }
  488.    }  // next i
  489. }
  490.  
  491.  
  492. // Only display changed parts of lines
  493. void Edit::display(void)
  494. {
  495.    register int  i, j, k;
  496.    char *st ;
  497.  
  498.  
  499.    st = (char*) malloc(width+1) ;
  500.  
  501.    this->formatText() ;
  502.  
  503.  
  504.    this->Output::outTextattr(color) ;
  505.  
  506.    for (i = 0 ; i < height ; i++)
  507.    {
  508.      register unsigned char *curScreen_i = curScreen[i];
  509.      register unsigned char *oldScreen_i = oldScreen[i];
  510.  
  511.      if (strcmp(curScreen_i,oldScreen_i) != 0)
  512.       {
  513.          for (j = 0 ; j < width ; j++)
  514.             if (curScreen_i[j] != oldScreen_i[j])
  515.                              break ;
  516.          for (k = width ; k > 0 ; k--)
  517.             if (curScreen_i[k] != oldScreen_i[k])
  518.                break ;
  519.          strncpy(st,curScreen_i+j,k-j+1) ;
  520.          st[k - j + 1] = '\0' ;
  521.  
  522.          this->Output::outGotoxy(x1 + j, y1 + i) ;
  523.                  this->Output::outPrintf(st) ;
  524.       }
  525.    }
  526.    // Place cursor
  527.    redrawCursor() ;
  528.  
  529.    copyScreen() ;
  530.  
  531.    free(st) ;
  532. }
  533.  
  534.  
  535. /***********************************************************************
  536. *                                                                      *
  537. *                                                                      *
  538. *                                                                      *
  539. *                                                                      *
  540. *                 Public member functions of Edit                      *
  541. *                                                                      *
  542. *                                                                      *
  543. *                                                                      *
  544. *                                                                      *
  545. ************************************************************************
  546. */
  547.  
  548.  
  549.  
  550. // You can not make an instance of edit this way
  551. Edit::Edit()
  552. {
  553.      err = TRUE ;
  554. }
  555.  
  556.  
  557. // The only constructor of edit
  558. Edit::Edit(int xx1, int yy1, int xx2, int yy2, unsigned char *txttxt)
  559. {
  560.      int i ;
  561.  
  562.      err    = FALSE ;
  563.                                                                         // Allocate memory for string
  564.                                                                         // and array of ints
  565.      memmaltxt = _BLOCK + strlen(txttxt) + 1  ;
  566.      memmalint = memmaltxt / _BLKPRT ;
  567.      if ( (txt = (unsigned char*) malloc(memmaltxt)) == NULL)
  568.             err = TRUE ;
  569.      if ( (strtcols = (unsigned int*) malloc(memmalint * sizeof(*strtcols))) == NULL)
  570.             err = TRUE ;
  571.  
  572.      strcpy(txt,txttxt) ;
  573.     txtlength = strlen(txt) ; // I_A added
  574.      x1 = xx1 ;
  575.      x2 = xx2 ;
  576.      y1 = yy1 ;
  577.      y2 = yy2 ;
  578.      width  = x2 - x1 + 1;
  579.      height = y2 - y1 + 1;
  580.  
  581.      // Allocate memory for virtual screen
  582.      if ( (curScreen = (char **) malloc(height * sizeof(char*))) == NULL)
  583.             err = TRUE ;
  584.      if ( (oldScreen = (char **) malloc(height * sizeof(char*))) == NULL)
  585.             err = TRUE ;
  586.      for (i = 0 ; i < height ; i++) // I_A
  587.      {
  588.             if ( (curScreen[i] = (char*) malloc(width + 1)) == NULL)
  589.                  err = TRUE ;
  590.       if ( (oldScreen[i] = (char*) calloc(1, width + 1)) == NULL) // I_A: watch it! >>>calloc<<<
  591.                  err = TRUE ;
  592.  
  593.    // I_A: for safe operation you need to initialize oldScreen. Only
  594.    //      than can you be sure the first display() will draw the
  595.    //      complete screen...
  596.    }
  597.  
  598.      curpos     = 0 ;                 // Set cursor always to first position
  599.      lincur     = 0 ;                 // Set current line at 0
  600.                                                                         // Calculate some default margins
  601.      topMargin  = bottomMargin = (height - 1) / 2 ;
  602.      topSens    = bottomSens   = bottomMargin / 2 ;
  603.      insertmode = TRUE ;
  604.      c_fEditable = TRUE;
  605.                                                                         // Set default input mode and emulation
  606.      inputmode  = INPUT_KEYBOARD ;
  607.      outputmode = OUTPUT_CON ;
  608.      Instream::termmode    = TERM_SCREEN ;
  609.      Output::termmode   = TERM_SCREEN ;
  610.      virorg = 0 ;
  611.  
  612.      color = (C_LIGHTGRAY << 4) + BLUE ;   // Set defaul color
  613.                                                                         // Make an outputfile and open it
  614.      doubleWidth = TRUE ;
  615.      border = -1 ;
  616.      topColor =  ( C_LIGHTGRAY << 4 ) | C_DARKGRAY ;
  617.      botColor =  ( C_LIGHTGRAY << 4 ) | C_WHITE ;
  618. }
  619.  
  620. Edit::~Edit()
  621. {
  622.    int i ;
  623.      for (i = 0 ; i < height ; i++) // I_A
  624.      {
  625.       free(curScreen[i]) ;
  626.       free(oldScreen[i]) ;
  627.    }
  628.    free(curScreen) ;
  629.    free(oldScreen) ;
  630.    free(txt) ;
  631.      free(strtcols) ;
  632.    fclose(Output::fpOut) ;
  633.    unlink(Output::outputFilename) ;       // This will fail if someone
  634.                                                       // still opens this file for
  635.                                           // read.
  636. }
  637.  
  638. int Edit::setCursorPos(unsigned short pos)
  639. {
  640.    if (pos > txtlength )
  641.       return 1 ;
  642.    curpos = pos ;
  643.    return 0 ;
  644. }
  645.  
  646. // Change the coordinates of a window
  647. int Edit::setWindow(int xx1, int yy1, int xx2, int yy2,  bool clear)
  648. {
  649.      int i ;
  650.  
  651.      if (xx1 < 0 || xx2 <= xx1 ||
  652.      yy1 < 0 || yy2 < yy1)
  653.             return 1 ;
  654.      if (clear)
  655.        this->clrWindow() ;              // Clear the screen
  656.  
  657.      // Delete all allocated memory
  658.      for (i = 0 ; i < height ; i++)   // I_A
  659.      {
  660.             free(curScreen[i]) ;
  661.             free(oldScreen[i]) ;
  662.      }
  663.      free(curScreen) ;
  664.      free(oldScreen) ;
  665. //     free(txt) ;
  666. //     free(strtcols) ;
  667.  
  668.      x1 = xx1 ;
  669.      x2 = xx2 ;
  670.      y1 = yy1 ;
  671.      y2 = yy2 ;
  672.      width  = x2 - x1 + 1;
  673.      height = y2 - y1 + 1;
  674.  
  675.  
  676.      // Allocate memory for virtual screen
  677.    if ( (curScreen = (char **) malloc(height * sizeof(char*))) == NULL)
  678.             err = TRUE ;
  679.    if ( (oldScreen = (char **) malloc(height * sizeof(char*))) == NULL)
  680.             err = TRUE ;
  681.    for (i = 0 ; i < height ; i++) // I_A
  682.      {
  683.        if ( (curScreen[i] = (char*) malloc(width + 1)) == NULL)
  684.                  err = TRUE ;
  685.       if ( (oldScreen[i] = (char*) calloc(1, width + 1)) == NULL) // I_A: calloc() !!!!
  686.                  err = TRUE ;
  687.    // I_A: for safe operation you need to initialize oldScreen. Only
  688.    //      than can you be sure the first display() will draw the
  689.    //      complete screen...
  690.    }
  691.      this->redraw() ;                // Re-display the whole screen
  692.      return 0 ;
  693. }
  694.  
  695. int Edit::setText(unsigned char *txttxt)
  696. {
  697.     err = TRUE ;
  698.     free(txt) ;
  699.     free(strtcols) ;
  700.     memmaltxt = _BLOCK + strlen(txttxt) + 1  ;
  701.     memmalint = memmaltxt / _BLKPRT ;
  702.     if ( (txt = (unsigned char*) malloc(memmaltxt + _BLOCK)) == NULL)
  703.        return 1 ;
  704.     if ( (strtcols = (unsigned int*) malloc(memmalint * sizeof(*strtcols))) == NULL)
  705.       return 1 ;
  706.    err = FALSE ;
  707.  
  708.     strcpy(txt,txttxt) ;
  709.    txtlength = strlen(txt);
  710.  
  711.    this->redraw() ;
  712.    return 0 ;
  713. }
  714.  
  715.  
  716.  
  717.  
  718. void  Edit::setColor(unsigned char col)
  719. {
  720.    color = col ;
  721. }
  722.  
  723. void Edit::setEditable(bool p_fEditable)
  724. {
  725.    c_fEditable = p_fEditable;
  726. }
  727.  
  728.  
  729. unsigned char *Edit::getText(void)
  730. {
  731.    return txt ;
  732. }
  733.  
  734.  
  735. int  Edit::loadFile(char *fileName)
  736. {
  737.    FILE *in ;
  738.    unsigned short i ;
  739.  
  740.    memmaltxt = fastFilelength(fileName) ;
  741.    if ( (in = fopen(fileName,"rt")) == NULL)
  742.             return 1 ;
  743.    err = TRUE ;
  744.    free(txt) ;
  745.      free(strtcols) ;
  746.      if ( (txt = ( unsigned char*) malloc(memmaltxt + _BLOCK)) == NULL) {
  747.       fclose(in);
  748.       return 1 ;
  749.    }
  750.  
  751.    err = FALSE ;
  752.    i = 0 ;
  753.  
  754.    // I_A: *much* faster!
  755.    i = fread(txt, 1, memmaltxt, in);
  756.    txt[i] = '\0' ;
  757.    txtlength = strlen(txt);
  758.  
  759.    // i == REAL length of file (incl \n\r => \n translation!)
  760.    memmalint = i / _BLKPRT;
  761.      if ( (strtcols = (unsigned int*) malloc(memmalint * sizeof(*strtcols))) == NULL) {
  762.       fclose(in);
  763.       return 1 ;
  764.    }
  765.  
  766.    // hieronder ook nog even naar kijken. while(i--) { /* etc */ }
  767.    while ( txtlength  > 0 && txt[txtlength /* strlen(txt) */ -1] ==  255) {
  768.       txt[txtlength -1] = '\0' ;
  769.    }
  770.  
  771.    fclose(in) ;
  772.    return 0 ;
  773. }
  774.  
  775. //
  776. // Modification made to allow for Importing text into the editor
  777. // and appending it to the text already there
  778. //
  779.  
  780. int  Edit::appendFile(char *fileName, char *FileName)
  781. {
  782. FILE *in;
  783. FILE *out;
  784. unsigned short i ;
  785.  
  786.    memmaltxt = fastFilelength(FileName) ;
  787.    if ( (in = fopen(FileName,"rt")) == NULL)
  788.             return 1 ;
  789.    err = TRUE ;
  790.    free(txt) ;
  791.      free(strtcols) ;
  792. if ( (txt = ( unsigned char*) malloc(memmaltxt + _BLOCK)) == NULL) {
  793.       fclose(in);
  794.       return 1 ;
  795.    }
  796.    i = fread(txt, 1, memmaltxt, in);
  797.    txt[i] = '\0' ;
  798.    txtlength = strlen(txt);
  799.  
  800.    // i == REAL length of file (incl \n\r => \n translation!)
  801.    memmalint = i / _BLKPRT;
  802.      if ( (strtcols = (unsigned int*) malloc(memmalint * sizeof(*strtcols))) == NULL) {
  803.       fclose(in);
  804.       return 1 ;
  805.    }
  806.  
  807.    // hieronder ook nog even naar kijken. while(i--) { /* etc */ }
  808.    while ( txtlength  > 0 && txt[txtlength /* strlen(txt) */ -1] ==  255) {
  809.       txt[txtlength -1] = '\0' ;
  810.    }
  811.  
  812.    fclose(in) ;
  813.     if ((out = fopen(fileName,"at")) == NULL )
  814.         return NULL;
  815.    if (fputs(txt,out) == EOF) {
  816.       fclose(out);
  817.       return EOF ;
  818.     }
  819.     fclose(out);
  820.  return 0;
  821. }
  822.  
  823.  
  824. int  Edit::saveFile(char *fileName)
  825. {
  826.    FILE *out ;
  827.  
  828.    if ( (out = fopen(fileName,"wt")) == NULL )
  829.       return NULL ;
  830.    if (fputs(txt,out) == EOF) {
  831.       fclose(out);
  832.       return EOF ;
  833.    }
  834.    fclose(out) ;
  835.    return 0 ;
  836. }
  837.  
  838.  
  839. void Edit::redraw(void)
  840. {
  841.    register int i ;
  842.  
  843.    this->drawborder() ;
  844.    this->formatText() ;
  845.    this->Output::outTextattr(color) ;
  846.  
  847.      for (i = 0 ; i < height ; i++)
  848.    {
  849.       this->Output::outGotoxy(x1,y1+i) ;
  850.       this->Output::outPrintf(curScreen[i]) ;
  851.     }
  852.    // Place cursor
  853.    this->redrawCursor() ;
  854.  
  855.    this->copyScreen() ;
  856. }
  857.  
  858.  
  859. void Edit::redrawCursor(void)
  860. {
  861.    this->Output::outGotoxy(min(x1 + width - 1,x1 + colpos),min(y1 + height - 1,linpos+y1)) ;
  862. }
  863.  
  864. // Clear the whole textscreen
  865. void Edit::clrWindow(void)
  866. {
  867.    register short i;
  868.  
  869.    for (i = 0 ; i < height ; i++) // I_A
  870.    {
  871.       memset(curScreen[i], ' ', width);
  872.       curScreen[i][width] = 0;
  873.    }
  874.  
  875.     for (i = 0 ; i < height ; i++) // I_A
  876.    {
  877.       this->Output::outGotoxy(x1,y1+i) ;
  878.       this->Output::outPrintf(curScreen[i]) ;
  879.    }
  880. }
  881.  
  882.  
  883.  
  884. // Poll for a key. Return NULL when there area none available
  885. int Edit::poll(void)
  886. {
  887.      if(err) {
  888.             return 0;
  889.      }
  890.  
  891.      return this->peekbuffer() == INPUT_NONE ? 0 : this->getkey() ;
  892. }
  893.  
  894. bool Edit::error(void)
  895. {
  896.    return err ;
  897. }
  898.  
  899. // Act on the key
  900. void Edit::interpKey(int key)
  901. {
  902.    if (key >=32 && key < 128)
  903.       addchar(key) ;
  904.    else
  905.       switch(key)
  906.       {
  907.          case KEY_ENT:
  908.             newline() ;
  909.             break ;
  910.          case KEY_BACK:
  911.             backspace() ;
  912.             break ;
  913.          case KEY_DEL:
  914.             delpos() ;
  915.             break ;
  916.          case KEY_DN:
  917.             cursorDown() ;
  918.             break ;
  919.          case KEY_UP :
  920.             cursorUp() ;
  921.             break ;
  922.          case KEY_LT:
  923.             if (curpos != 0)
  924.                curpos-- ;
  925.             break ;
  926.          case KEY_RT:
  927.             if(txt[curpos] == '\n') {
  928.                addchar(' ');
  929.             } else {
  930.                if (curpos < txtlength  )
  931.                   curpos++ ;
  932.             }
  933.             break ;
  934.          case KEY_HOME:
  935.             home() ;
  936.             break ;
  937.          case KEY_END:
  938.             end() ;
  939.             break ;
  940.          case KEY_INS:{
  941.         insertmode = !insertmode ;
  942.         isinsert = TRUE;  // added this for the INS OVR Display
  943.         break ;}
  944.          case KEY_CTLY:
  945.             deleteLine() ;
  946.             break ;
  947.          case KEY_CTLT:
  948.             deleteWord() ;
  949.             break ;
  950.          case KEY_PGDN:
  951.             pagedown() ;
  952.             break ;
  953.          case KEY_PGUP:
  954.             pageup() ;
  955.             break ;
  956.                  default:
  957.             processKey(key) ;
  958.          break ;
  959.       } // end switch
  960.    display() ;
  961. }
  962.  
  963. void Edit::change(void)
  964. {
  965.    int key ;
  966.  
  967.    key = NULL ;
  968.    while (key != KEY_ESC)
  969.    {
  970.       if ((key = poll()) != 0) // I_A: *not* compareing with NULL but with 0!
  971.          interpKey(key) ;
  972.    }
  973. }
  974.  
  975. void Edit::setTopColor(unsigned char col)
  976. {
  977.    topColor = col ;
  978. }
  979.  
  980. unsigned char Edit::getTopColor(void)
  981. {
  982.   return topColor ;
  983. }
  984.  
  985. void Edit::setBotColor(unsigned char col)
  986. {
  987.    botColor = col ;
  988. }
  989.  
  990. unsigned char Edit::getBotColor(void)
  991. {
  992.   return botColor ;
  993. }
  994.  
  995. void Edit::setBorder(int brd)
  996. {
  997.    border = brd ;
  998. }
  999.  
  1000. int Edit::getBorder(void)
  1001. {
  1002.    return border ;
  1003. }
  1004.  
  1005. void Edit::drawborder(void)
  1006. {
  1007.    int i ;
  1008. #if 0
  1009.    char vertline[7][8] ;
  1010.  
  1011.    if (border < 0)
  1012.       return ;
  1013.  
  1014.    strcpy(vertline[0],"╔┌░▒▓█") ;
  1015.    strcpy(vertline[1],"║│░▒▓█") ;
  1016.    strcpy(vertline[2],"╚└░▒▓█") ;
  1017.    strcpy(vertline[3],"╗┐░▒▓█") ;
  1018.    strcpy(vertline[4],"═─░▒▓█") ;
  1019.    strcpy(vertline[5],"╝┘░▒▓█") ;
  1020. #else
  1021.    static char vertline[6][7] =
  1022.    {
  1023.      "╔┌░▒▓█",
  1024.      "║│░▒▓█",
  1025.      "╚└░▒▓█",
  1026.      "╗┐░▒▓█",
  1027.      "═─░▒▓█",
  1028.      "╝┘░▒▓█"
  1029.    };
  1030.  
  1031.    if (border < 0 || border >= 7) // I_A: upper check '>= 7' added
  1032.       return ;
  1033. #endif
  1034.  
  1035.    // Draw top
  1036.    outTextattr(topColor) ;
  1037.    if (doubleWidth)
  1038.    {
  1039.       outGotoxy(x1 - 2,y1 - 1) ;
  1040.             outChar(' ') ;
  1041.       outChar(vertline[0][border]) ;
  1042.    }
  1043.    else
  1044.    {
  1045.       outGotoxy(x1 - 1,y1 - 1) ;
  1046.       outChar(vertline[0][border]) ;
  1047.    }
  1048.    for (i = x1 ; i <= x1 + width ; i++)
  1049.       outChar(vertline[4][border]) ;
  1050.    outTextattr(botColor) ;
  1051.    if (doubleWidth)
  1052.    {
  1053.       outGotoxy(width + x1 ,y1 - 1) ;
  1054.       outChar(vertline[3][border]) ;
  1055.       outChar(' ') ;
  1056.    }
  1057.    else
  1058.    {
  1059.       outGotoxy(width + x1 + 1,y1 - 1) ;
  1060.       outChar(vertline[3][border]) ;
  1061.    }
  1062.  
  1063.    // Draw body
  1064.      for (i = y1  ; i < height + y1  ; i++)
  1065.       if (doubleWidth)
  1066.       {
  1067.          outTextattr(topColor) ;
  1068.          outGotoxy(x1 - 2,i) ;
  1069.          outChar(' ') ;
  1070.          outChar(vertline[1][border]) ;
  1071.          outTextattr(botColor) ;
  1072.          outGotoxy(x1 + width ,i) ;
  1073.          outChar(vertline[1][border]) ;
  1074.          outChar(' ') ;
  1075.             }
  1076.       else
  1077.       {
  1078.          outTextattr(topColor) ;
  1079.          outGotoxy(x1 - 1,i) ;
  1080.          outChar(vertline[1][border]) ;
  1081.          outTextattr(botColor) ;
  1082.          outGotoxy(x1 + width + 1,i) ;
  1083.          outChar(vertline[1][border]) ;
  1084.       }
  1085.  
  1086.    // Draw bottom
  1087.    outTextattr(topColor) ;
  1088.    if (doubleWidth)
  1089.    {
  1090.             outGotoxy(x1 - 2,y1 +height ) ;
  1091.       outChar(' ') ;
  1092.       outChar(vertline[2][border]) ;
  1093.    }
  1094.    else
  1095.    {
  1096.             outGotoxy(x1 - 1,y1 +height ) ;
  1097.       outChar(vertline[2][border]) ;
  1098.    }
  1099.    outTextattr(botColor) ;
  1100.    for (i = x1 ; i <= x1 + width ; i++)
  1101.       outChar(vertline[4][border]) ;
  1102.    if (doubleWidth)
  1103.    {
  1104.             outGotoxy(width + x1 ,y1 + height ) ;
  1105.       outChar(vertline[5][border]) ;
  1106.       outChar(' ') ;
  1107.    }
  1108.    else
  1109.    {
  1110.        outGotoxy(width + x1 ,y1 + height ) ;
  1111.       outChar(vertline[5][border]) ;
  1112.    }
  1113.  
  1114. }
  1115.  
  1116.  
  1117. #endif
  1118.