// FILE: LineList.cc -- Implementation of a list of lines of text.
// BY: John Zelle
// LineList is maintained as a doubly-linked list.
#include
#include
#include
#include "LineList.h"
// List Node structure
struct LineList::ListNode
{ char* data;
LineList::ListNode* next;
LineList::ListNode* prev;
};
typedef LineList::ListNode* NodePtr;
// A LineList object has a pointer to the head of the chain, and a pointer
// to the "current" line.
// NodePtr _head
// NodePtr _current
LineList::LineList()
{ _head = new ListNode; // Header Node of doubly-linked list
_current = new ListNode; // Footer Node of doubly-linked list
_head->data = NULL;
_head->prev = NULL;
_head->next = _current;
_current->data = NULL;
_current->next = NULL;
_current->prev = _head;
}
LineList::LineList(const LineList& value)
{ cerr << "Error: Attempt to pass a LineList by value";
exit(1);
}
LineList::~LineList()
{ NodePtr ptr,tmp;
ptr = _head;
while(ptr != NULL)
{ if (ptr->data)
delete [] ptr->data;
tmp = ptr;
ptr = ptr->next;
delete tmp;
}
}
void LineList::insert(char* line)
{
// First make a copy of the line on the heap.
char* copy = new char[strlen(line)+1];
strcpy(copy, line);
// Create and fill in fields of Node
NodePtr Node = new ListNode;
Node->data = copy;
Node->next = _current;
Node->prev = _current->prev;
// Splice Node into proper sequence on next and prev chains.
_current->prev->next = Node;
_current->prev = Node;
}
void LineList::remove()
{
if (_current->data != NULL)
{
NodePtr tmp = _current; // Temporary pointer used to remove current data
_current = _current->next; // Adjust current pointer to successor
tmp->next->prev = tmp->prev; // Make next node point to prev node
tmp->prev->next = tmp->next; // Make prev node point to next node
delete [] tmp->data; // Remove allocated structure 'data' from the heap
delete tmp; // Remove the allocated structure from the heap
}
}
void LineList::display() const
{
NodePtr tmp;
tmp = _current;
while (tmp->next != NULL)
{ cout << tmp->data << endl;
tmp = tmp->next;
}
cout << "<>" << endl;
}
void LineList::display_current() const
{
if (_current->next != NULL)
cout << _current->data << endl; // Display the data field of the 'current' object
else
cout << "<>" << endl; // Do not display the NULL of the footer
}
void LineList::advance(int n)
{
while(_current->next != NULL && n>0)
{ _current = _current->next;
n--;
}
}
void LineList::backup(int n)
{
while (_current->prev->data != NULL && n<0)
{
_current = _current->prev;
n++;
}
}
ostream& operator<<(ostream& stream, const LineList& list)
{ NodePtr ptr = list._head;
cout << "" << endl;
while ( ptr != NULL )
{ cout << ptr->data << endl;
ptr = ptr->next;
}
cout << "" << endl;
return stream;
}