Logo Search packages:      
Sourcecode: ocaml version File versions

editbuffer.c

/***********************************************************************/
/*                                                                     */
/*                           Objective Caml                            */
/*                                                                     */
/*  Developed by Jacob Navia.                                          */
/*  Copyright 2001 Institut National de Recherche en Informatique et   */
/*  en Automatique.  All rights reserved.  This file is distributed    */
/*  under the terms of the GNU Library General Public License, with    */
/*  the special exception on linking described in file ../LICENSE.     */
/*                                                                     */
/***********************************************************************/

/***********************************************************************/
/* Changes made by Chris Watford to enhance the source editor          */
/* Began 14 Sept 2003 - watford@uiuc.edu                               */
/***********************************************************************/

#include <string.h>
#include <stdlib.h>
#include "inriares.h"
#include "inria.h"

/*------------------------------------------------------------------------
 Procedure:     editbuffer_addline ID:1
 Author:          Chris Watford watford@uiuc.edu
 Purpose:       Adds a line to the current edit buffer
 Input:                 Line of text to append to the end
 Output:
 Errors:
--------------------------------------------------------------------------
 Edit History:
      18 Sept 2003 - Chris Watford watford@uiuc.edu
            - Corrected doubly linked list issue
------------------------------------------------------------------------*/
BOOL editbuffer_addline(EditBuffer* edBuf, char* line)
{
      LineList *tail = NULL; //head of the edit buffer line list
      LineList *newline = NULL;

      // sanity check
      if(edBuf == NULL)
      {
            return FALSE;
      }

      // perform edit buffer sanity checks
      if((edBuf->LineCount < 0) || (edBuf->Lines == NULL))
      {
            edBuf->LineCount = 0;
      }

      // move to the end of the line list in the edit buffer
      if((tail = edBuf->Lines) != NULL)
            for( ; tail->Next != NULL; tail = tail->Next);

      // create the new line entry
      newline = (LineList*)SafeMalloc(sizeof(LineList));
      newline->Next = NULL;
      newline->Prev = tail;
      newline->Text = (char*)SafeMalloc(strlen(line)+1);
      strncpy(newline->Text, line, strlen(line)+1);
      newline->Text[strlen(line)] = '\0';

      // add it to the list as the head or the tail
      if(tail != NULL)
      {
            tail->Next = newline;
      } else {
            edBuf->Lines = newline;
      }

      // update the number of lines in the buffer
      edBuf->LineCount++;

      return TRUE;
}

/*------------------------------------------------------------------------
 Procedure:     editbuffer_updateline ID:1
 Author:          Chris Watford watford@uiuc.edu
 Purpose:       Updates the edit buffer's internal contents for a line
 Input:                 idx - Line index
                        line - String to add
 Output:          if the line was updated or not
 Errors:
------------------------------------------------------------------------*/
BOOL editbuffer_updateline(EditBuffer* edBuf, int idx, char* line)
{
      LineList *update = edBuf->Lines; //head of the edit buffer line list
      LineList *newline = NULL;
      int i;

      // sanity checks
      if(edBuf == NULL)
      {
            return FALSE;
      } else if(  (edBuf->LineCount == 0) ||
                        (edBuf->Lines == NULL) ||
                        (idx >= edBuf->LineCount) ||
                        (idx < 0) ) {
            return FALSE;
      }

      // move to the index in the line list
      // i left in update != NULL as a sanity check
      for(i = 0; ((update != NULL) && (i != idx)); update = update->Next, i++);

      // did things mess up?
      if( (update == NULL) || (i != idx) )
      {
            return FALSE;
      }

      // get rid of the old line
      free(update->Text);

      // get the new line updated
      update->Text = (char*)SafeMalloc(strlen(line)+1);
      strncpy(update->Text, line, strlen(line)+1);
      update->Text[strlen(line)] = '\0';

      return TRUE;
}

/*------------------------------------------------------------------------
 Procedure:     editbuffer_updateoraddline ID:1
 Author:          Chris Watford watford@uiuc.edu
 Purpose:       Updates the edit buffer's internal contents for a line
 Input:                 idx - Line index
                        line - String to add
 Output:          if the line was updated or not
 Errors:
------------------------------------------------------------------------*/
BOOL editbuffer_updateoraddline(EditBuffer* edBuf, int idx, char* line)
{
      LineList *update;

      // sanity checks
      if(edBuf == NULL)
      {
            return FALSE;
      } else if((idx > edBuf->LineCount) || (idx < 0)) {
            return FALSE;
      }

      update = edBuf->Lines; //head of the edit buffer line list

      // do we update or add?
      if((idx < edBuf->LineCount) && (edBuf->Lines != NULL))
      {     //interior line, update
            return editbuffer_updateline(edBuf, idx, line);
      } else {
            //fence line, add
            return editbuffer_addline(edBuf, line);
      }
}

/*------------------------------------------------------------------------
 Procedure:     editbuffer_removeline ID:1
 Author:          Chris Watford watford@uiuc.edu
 Purpose:       Removes a line from the edit buffer
 Input:                 idx - Line index to remove
 Output:          if the line was removed or not
 Errors:
--------------------------------------------------------------------------
 Edit History:
      18 Sept 2003 - Chris Watford watford@uiuc.edu
            - Added to allow backspace and delete support
            - Corrected doubly linked list issue
------------------------------------------------------------------------*/
BOOL editbuffer_removeline(EditBuffer* edBuf, int idx)
{
      LineList *update = NULL;
      int i = 0;

      // sanity checks
      if(edBuf == NULL)
      {
            return FALSE;
      } else if(  (edBuf->LineCount == 0) ||
                        (edBuf->Lines == NULL) ||
                        (idx >= edBuf->LineCount) ||
                        (idx < 0) ) {
            return FALSE;
      }
      
      // move to the index in the line list
      // i left in update != NULL as a sanity check
      for(i = 0, update = edBuf->Lines; ((update != NULL) && (i != idx)); update = update->Next, i++);

      // remove this line
      if(update != NULL)
      {
            // break links, removing our line
            if(update->Prev != NULL)
            {
                  // we're not the first so just break the link
                  update->Prev->Next = update->Next;
                  
                  // fix the prev check
                  if(update->Next != NULL)
                        update->Next->Prev = update->Prev;
            } else {
                  // we're the first, attach the next guy to lines
                  edBuf->Lines = update->Next;
            }

            // one less line to worry about
            edBuf->LineCount--;

            // get rid of the text
            if(update->Text != NULL)
                  free(update->Text);

            // get rid of us
            free(update);

            return TRUE;
      }

      return FALSE;
}

/*------------------------------------------------------------------------
 Procedure:     editbuffer_getasline ID:1
 Author:          Chris Watford watford@uiuc.edu
 Purpose:       Returns the edit buffer as one big line, \n's and \t's
                        become spaces.
 Input:
 Output:
 Errors:
------------------------------------------------------------------------*/
char* editbuffer_getasline(EditBuffer* edBuf)
{
      LineList *line = NULL; //head of the edit buffer line list
      char* retline = (char*)realloc(NULL, 1);
      unsigned int i = 0;

      // fix retline bug
      retline[0] = '\0';

      // sanity checks
      if(edBuf == NULL)
      {
            return NULL;
      } else if (edBuf->LineCount == 0 || edBuf->Lines == NULL) {
            // fix any possible errors that may come from this
            edBuf->LineCount = 0;
            edBuf->Lines = NULL;
            return NULL;
      }

      // get the big line
      for(line = edBuf->Lines; line != NULL; line = line->Next)
      {
            if(line->Text != NULL)
            {
                  retline = (char*)realloc(retline, (strlen(retline) + strlen(line->Text) + (strlen(retline) > 0 ? 2 : 1)));

                  if(strlen(retline) > 0)
                        retline = strcat(retline, " ");

                  retline = strcat(retline, line->Text);

                  //concat in the hoouuusssseee!
            }
      }

      // now we have the big line, so lets ditch all \n's \t's and \r's
      for(i = 0; i < strlen(retline); i++)
      {
            switch(retline[i])
            {
                  case '\n':
                  case '\t':
                  case '\r':
                        retline[i] = ' ';
            }
      }

      return retline;
}

/*------------------------------------------------------------------------
 Procedure:     editbuffer_getasbuffer ID:1
 Author:          Chris Watford watford@uiuc.edu
 Purpose:       Returns the edit buffer as one big line, \n's and \t's
                        become spaces.
 Input:
 Output:
 Errors:
------------------------------------------------------------------------*/
char* editbuffer_getasbuffer(EditBuffer* edBuf)
{
      LineList *line = NULL; //head of the edit buffer line list
      char* retbuf = (char*)realloc(NULL, 1);
      unsigned int i = 0;

      // fix retline bug
      retbuf[0] = '\0';

      // sanity checks
      if(edBuf == NULL)
      {
            return NULL;
      } else if (edBuf->LineCount == 0 || edBuf->Lines == NULL) {
            // fix any possible errors that may come from this
            edBuf->LineCount = 0;
            edBuf->Lines = NULL;
            return NULL;
      }

      // get the big line
      for(line = edBuf->Lines; line != NULL; line = line->Next)
      {
            if(line->Text != NULL)
            {
                  int len = strlen(retbuf);
                  len += strlen(line->Text) + (len > 0 ? 3 : 1);

                  retbuf = (char*)realloc(retbuf, len);

                  if(strlen(retbuf) > 0)
                        retbuf = strcat(retbuf, "\r\n");

                  retbuf = strcat(retbuf, line->Text);

                  retbuf[len-1] = '\0';

                  //concat in the hoouuusssseee!
            }
      }

      return retbuf;
}

/*------------------------------------------------------------------------
 Procedure:     editbuffer_lastline ID:1
 Author:          Chris Watford watford@uiuc.edu
 Purpose:       Returns the last line in the edit buffer
 Input:
 Output:
 Errors:
------------------------------------------------------------------------*/
char* editbuffer_lastline(EditBuffer* edBuf)
{
      LineList *line = NULL; //head of the edit buffer line list

      // sanity checks
      if(edBuf == NULL)
      {
            return NULL;
      } else if (edBuf->LineCount == 0 || edBuf->Lines == NULL) {
            // fix any possible errors that may come from this
            edBuf->LineCount = 0;
            edBuf->Lines = NULL;
            return NULL;
      }

      // go to the last line
      for(line = edBuf->Lines; line->Next != NULL; line = line->Next);

      return line->Text;
}

/*------------------------------------------------------------------------
 Procedure:     editbuffer_copy ID:1
 Author:          Chris Watford watford@uiuc.edu
 Purpose:       Makes an exact copy of an edit buffer
 Input:
 Output:
 Errors:
--------------------------------------------------------------------------
 Edit History:
      16 Sept 2003 - Chris Watford watford@uiuc.edu
            - Added to make copies of history entries
      18 Sept 2003 - Chris Watford watford@uiuc.edu
            - Corrected doubly linked list issue
      06 Oct  2003 - Chris Watford watford@uiuc.edu
            - Added isCorrect flag
------------------------------------------------------------------------*/
EditBuffer* editbuffer_copy(EditBuffer* edBuf)
{
      // sanity checks
      if(edBuf == NULL)
      {
            return NULL;
      } else {
            EditBuffer* copy = (EditBuffer*)SafeMalloc(sizeof(EditBuffer));
            LineList* lines = edBuf->Lines;
            LineList* lastLine = NULL;

            // clear its initial values
            copy->LineCount = 0;
            copy->Lines = NULL;
            copy->isCorrect = FALSE;

            // well we don't have to copy much
            if((lines == NULL) || (edBuf->LineCount <= 0))
            {
                  return copy;
            }

            // get if its correct
            copy->isCorrect = edBuf->isCorrect;

            // go through each line, malloc it and add it
            for( ; lines != NULL; lines = lines->Next)
            {
                  LineList* curline = (LineList*)SafeMalloc(sizeof(LineList));
                  curline->Next = NULL;
                  curline->Prev = NULL;

                  // if there was a last line, link them to us
                  if(lastLine != NULL)
                  {
                        lastLine->Next = curline;
                        curline->Prev = lastLine;
                  }

                  // are we the first line? add us to the edit buffer as the first
                  if(copy->Lines == NULL)
                  {
                        copy->Lines = curline;
                  }

                  // check if there is text on the line
                  if(lines->Text == NULL)
                  {     // no text, make it blankz0r
                        curline->Text = (char*)SafeMalloc(sizeof(char));
                        curline->Text[0] = '\0';
                  } else {
                        // there is text, copy it and null-terminate
                        curline->Text = (char*)SafeMalloc(strlen(lines->Text) + 1);
                        strncpy(curline->Text, lines->Text, strlen(lines->Text));
                        curline->Text[strlen(lines->Text)] = '\0';
                  }

                  // up the line count and make us the last line
                  copy->LineCount++;
                  lastLine = curline;
            }

            // return our new copy
            return copy;
      }
}

/*------------------------------------------------------------------------
 Procedure:     editbuffer_destroy ID:1
 Author:          Chris Watford watford@uiuc.edu
 Purpose:       Destroys an edit buffer
 Input:
 Output:
 Errors:
------------------------------------------------------------------------*/
void editbuffer_destroy(EditBuffer* edBuf)
{
      // sanity checks
      if(edBuf == NULL)
      {     // nothing to do
            return;
      } else if(edBuf->Lines != NULL) {
            LineList* lastline = NULL;

            // loop through each line free'ing its text
            for( ; edBuf->Lines != NULL; edBuf->Lines = edBuf->Lines->Next)
            {
                  if(edBuf->Lines->Text != NULL)
                        free(edBuf->Lines->Text);

                  // if there was a line before us, free it
                  if(lastline != NULL)
                  {
                        free(lastline);
                        lastline = NULL;
                  }

                  lastline = edBuf->Lines;
            }

            // free the last line
            free(lastline);
      }

      // free ourself
      free(edBuf);
}

/*------------------------------------------------------------------------
 Procedure:     editbuffer_new ID:1
 Author:          Chris Watford watford@uiuc.edu
 Purpose:       Creates an edit buffer
 Input:
 Output:
 Errors:
--------------------------------------------------------------------------
 Edit History:
      06 Oct  2003 - Chris Watford watford@uiuc.edu
            - Added isCorrect flag
------------------------------------------------------------------------*/
EditBuffer* editbuffer_new(void)
{
      // create a new one
      EditBuffer *edBuf = (EditBuffer*)SafeMalloc(sizeof(EditBuffer));
      
      // default vals
      edBuf->LineCount = 0;
      edBuf->Lines = NULL;
      edBuf->isCorrect = FALSE;
      
      // return it
      return edBuf;
}

Generated by  Doxygen 1.6.0   Back to index