/* * ----------------------------------------------------- * CS2S03/SE2S03, November 2011 * Assignment 5, Question 4 * File: listbuf.cpp * ----------------------------------------------------- * This file implements the EditorBuffer class using a * circular doubly linked list (with dummy node) to * represent the buffer. * ----------------------------------------------------- */ #include "genlib.h" #include "buffer.h" #include /* * Implementation notes: EditorBuffer constructor * ---------------------------------------------- * This function initializes an empty editor buffer, represented * as a circular doubly linked list (with a dummy node). * To simplify the operations, this * implementation adopts the useful programming tactic of * keeping an extra "dummy" cell at the beginning of each list, * so that the empty buffer has the following representation: * * +-------+ +------+ * | o---+-----====>| | <== * +-------+ / +------+ | * | o---+---/ | o---+----- * +-------+ +------+ | * | o---+----- * +------+ */ EditorBuffer::EditorBuffer() { start = cursor = new cellT; start->prev = start; start->next = start; } /* * Implementation notes: EditorBuffer destructor * --------------------------------------------- * The destructor must delete every cell in the buffer. Note * that the loop structure is not exactly the standard idiom for * processing every cell within a linked list, because it is not * legal to delete a cell and later look at its link field. To * avoid selecting fields in the structure after it has been * deallocated, you have to copy the link pointer before calling * delete. */ EditorBuffer::~EditorBuffer() { cellT *cp = start; while (cp != start) { cellT *next = cp->next; delete cp; cp = next; } } /* * Implementation notes: cursor movement * ------------------------------------- * The four functions that move the cursor have same time * complexity since we are using a doubly linked list. * Moving forward one cell is simply a matter of picking up the * next pointer; moving backward requires picking the prev pointer. * Similarly, moving to the start and end of the buffer takes constant time. * NOTE: All 4 function have O(1) complexity. */ void EditorBuffer::moveCursorForward() { if (cursor->next != start) { cursor = cursor->next; } } void EditorBuffer::moveCursorBackward() { if (cursor->prev->next != start) { cursor = cursor->prev; } } void EditorBuffer::moveCursorToStart() { cursor = start; } void EditorBuffer::moveCursorToEnd() { cursor = start->prev; } /* * Implementation notes: insertCharacter * ------------------------------------- * The primary advantage of the linked list representation for * the buffer is that the insertCharacter operation can now be * accomplished in constant time. * Note: Function complexity is O(1) */ void EditorBuffer::insertCharacter(char ch) { cellT *cp = new cellT; cp->ch = ch; cp->prev = cursor; cp->next = cursor->next; cp->next->prev = cp; cursor->next = cp; cursor = cp; } /* * Implementation notes: deleteCharacter * ------------------------------------- * As with insertCharacter, the list representation makes it * possible to implement the deleteCharacter operation in * constant time. * Note: Function complexity is O(1) */ void EditorBuffer::deleteCharacter() { if (cursor->next != start) { cellT *oldCell = cursor->next; cursor->next = oldCell->next; oldCell->next->prev = cursor; delete oldCell; } } /* * Implementation notes: display * ----------------------------- * The display method uses the standard for loop idiom to loop * through the cells in the linked list. The first loop displays * the character; the second marks the cursor position. */ void EditorBuffer::display() { for (cellT *cp = start->next; cp != start; cp = cp->next) { cout << " " << cp->ch; } cout << endl; for (cellT *cp = start; cp != cursor; cp = cp->next) { cout << " "; } cout << "^" << endl; }