/* Filename: Screen.cpp * Size: 12.30kB * Last Modified: Sat Jun 24 17:36:04 2006 * Author: Ben Hearsum * * This comment was automatically generated by header.pl * http://www.wittydomain.com/software */ #include #include #include #include "screen.h" extern "C" { #include "dtio.h" } using namespace std; /* most commonly used constructor * set data to safe values and initialize it */ Field::Field(int r, int c, int l, const char *s, bool edit) { row = 0; col = 0; len = 0; c_pos = 0; d = NULL; init(r, c, l, s, edit); } /* copy constructor */ Field::Field(const Field &right):row(0), col(0), len(0), c_pos(-1), d(NULL) { *this = right; } /* default constructor -- set member data to safe values */ Field::Field():row(0), col(0), len(0), c_pos(-1), d(NULL) { setData("", len); } /* garbage collection */ Field::~Field() { if (d) { delete [] d; } } /* assignment operator * returns a reference to the left operand */ const Field& Field::operator=(const Field &right) { /* if the operands are different instances of Field */ if (this != &right) { /* initialize the left operand to be the same as the right */ init(right.getRow(), right.getCol(), right.getLen(), (char*)right.data(), right.editable()); } return *this; } /* is-equal-to operator, necessary for the use of deques * a Field is considered equal to another field if: * the starting coordinates are the same, the length is the same, * the data is the same, and the editability is the same * returns 1 for true and 0 for false */ bool Field::operator==(const Field &right) { bool ret = false; if ((*this).row == right.row && (*this).col == right.col && (*this).len == right.len && (*this).is_editable == right.is_editable && (strcmp((*this).d, right.d) == 0)) { ret = true; } return ret; } bool Field::operator!=(const Field &right) { bool ret = false; if ((*this).row != right.row || (*this).col != right.col || (*this).len != right.len || (*this).is_editable != right.is_editable || (strcmp((*this).d, right.d) != 0)) { ret = true; } return ret; } /* initialize this field */ void Field::init(int r, int c, int width, const char *s, bool edit) { setRow(r); setCol(c); setLen(width); /* if a value is specified for s, set the data to it */ if (s) { setData(s, len); } /* otherwise, set it to a safe value */ else { setData("\0", len); } is_editable = edit; } /* display this field */ void Field::display() { dtioDisplay(d, row, col, len); } /* displays the field and, if possible, puts it into edit mode * returns the key used to exit edit mode if editable * returns 0 if not editable */ int Field::edit(Screen *sptr) { int ret = 0; /* is the field editable? */ if (is_editable) { /* set c_pos to 0 if it is the first time being edited */ if (c_pos == -1) { setcPos(0); } /* if the requested cursor position is longer than the string * put c_pos at the end of the string */ else if (c_pos > len) { c_pos = len; } /* edit the string */ ret = dtioEdit(d, row, col, len, &c_pos); } else { display(); } return ret; } /* returns a pointer to a new copy of this field */ Field* Field::clone()const { return new(std::nothrow) Field(row, col, len, d, is_editable); } /* set the data of the field */ void Field::setData(const char *s, int l) { /* free the old one if necessary */ if (d) { delete [] d; } /* allocate memory for a new one */ d = new char[l + 1]; if (d) { /* write the new data and terminate the string */ strncpy(d, s, l); d[l] = '\0'; } } /* row cannot exceed the visible amount of rows (dtioRows() - 1) * it also must be positive */ void Field::setRow(int r) { int max_y = dtioRows() - 1; if (r < 0) { row = 0; } else if (r > max_y) { row = max_y; } else { row = r; } } /* same goes for col. it must be visible and greater than zero */ void Field::setCol(int c) { int max_x = dtioColumns() - 1; if (c < 0) { col = 0; } else if (c > max_x) { col = max_x; } else { col = c; } } /* the length of a field plus the starting column must be a visible column */ void Field::setLen(int l) { int max_x = dtioColumns() - 1; if ((col + l) > max_x) { len = max_x - col; } else { len = l; } } /* c_pos must be greater than 0 but not more than 1 past the last character */ void Field::setcPos(int c) { if (c < 0) { c_pos = 0; } else if (c <= len) { c_pos = c; } else { c_pos = len; } } /* the most common constructor for Screen * adds a field to this Screen based on the arguments provided */ Screen::Screen(int row, int col, int len, const char *s, bool editable) { f_pos = 0; size = 0; add(row, col, len, s, editable); } /* deconstructor does nothing (the deque handles memory management */ Screen::~Screen() { for (int i = 0; i < size; i++) { delete fields[i]; } } /* assignment operator * copies each field in the deque of the right operand to the left operand * returns a reference to the left operand */ Screen& Screen::operator=(const Screen &right) { if (this != &right) { for (int i = 0; i < size; i++) { *this += *(fields[i]); } } return *this; } /* adds the Field given as the right operand to this Screen */ Screen& Screen::operator+=(const Field &right) { add(right); return *this; } /* adds new field to the deque of this Screen based on the arguments provided * returns the total number of fields in the screen */ int Screen::add(int row, int col, int len, const char *s, bool editable) { if (size < MAX_FIELDS) { fields[size] = new Field(row, col, len, s, editable); size++; } return size; } /* makes a copy of the Field provided and appends it to fields */ int Screen::add(const Field &f) { if (size < MAX_FIELDS) { fields[size] = f.clone(); size++; } return size; } /* displays all of the Fields in this Screen */ void Screen::display(bool clear) { /* if we need to clear the screen first, do so now */ if (clear) { dtioClear(); } /* display every field on the screen */ for (int i = 0; i < size; i++) { (fields[i])->display(); } dtioFlush(); } /* edit the fields on the screen starting at '*pfield', if it exists * if clear is true, clear the screen before editing * tab and down both advance to the next field * up moves to the previous field * enter moves to the next field unless it is the last field on the screen * this function returns the key used to exit edit mode */ int Screen::edit(int *pfield, bool clear) { int editing = 1; int key; int row, col; /* if pfield exists set f_pos to pfield */ f_pos = (pfield) ? *pfield : f_pos; /* and check to make sure it is actually a field */ if (f_pos >= (size - 1)) { f_pos = (size - 1); } /* display all the fields on the screen, clearing it if necessary */ display(clear); /* find the next editable field */ int orig_f_pos = f_pos; do { if (fields[f_pos] == fields[size - 1]) { f_pos = 0; } else { f_pos++; } if (f_pos == orig_f_pos) { editing = 0; } } while (! fields[f_pos]->editable() && orig_f_pos != f_pos); /* edit the first field */ key = (fields[f_pos])->edit(this); while (editing) { switch(key) { /* move down one editable field */ case DOWN: case TAB: /* find the next editable field */ do { if (fields[f_pos] == fields[size - 1]) { f_pos = 0; } else { f_pos++; } } while (! fields[f_pos]->editable()); /* reset row/col and put the field into edit mode */ row = fields[f_pos]->getRow(); col = fields[f_pos]->getCol(); key = fields[f_pos]->edit(this); break; /* move up one editable field */ case UP: /* find the next editable field */ do { if (fields[f_pos] == fields[0]) { f_pos = size - 1; } else { f_pos--; } } while (! fields[f_pos]->editable()); /* reset row/col and put the field into edit mode */ row = fields[f_pos]->getRow(); col = fields[f_pos]->getCol(); key = fields[f_pos]->edit(this); break; /* if we are at the last field, exit edit mode */ case ENTER: if (fields[f_pos] == fields[size - 1]) { editing = 0; } /* otherwise, find the next editable field (like TAB/DOWN) */ else { do { if (fields[f_pos] == fields[size - 1]) { f_pos = 0; } else { f_pos++; } } while (! fields[f_pos]->editable()); /* reset row/col and put the field into mode */ row = fields[f_pos]->getRow(); col = fields[f_pos]->getCol(); key = fields[f_pos]->edit(this); } break; /* exit edit mode */ case ESCAPE: case PGUP: case PGDN: case F(1): case F(2): case F(3): case F(4): case F(5): case F(6): case F(7): case F(8): case F(9): case F(10): case F(11): case F(12): /* Field::edit returns 0 if the field cannot be edited */ case 0: editing = 0; break; default: break; } } /* if pfield was passed in, set it to the current field */ if (pfield) { *pfield = f_pos; } return key; } /* returns a pointer to the Field at 'n', or NULL if the Field doesn't exist */ Field* Screen::getField(int n) { Field* ret = NULL; if (n <= size) { ret = fields[n]; } return ret; } /* removes the Field at position 'n' if it exists * returns the new number of Fields in the Screen */ int Screen::remove(int n) { if (n >= 0 && n < size) { delete fields[n]; for (int i = n; i < size - 1; i++) { fields[i] = fields[i+1]; } size--; } return size; } /* START OF LABEL CLASS */ Label::Label(int r, int c, int width, const char *s) { row = 0; col = 0; len = 0; str = NULL; is_editable = false; init(r, c, width, s); } void Label::init(int r, int c, int width, const char *s) { setRow(r); setCol(c); setLen(width); if (str) { delete [] str; } if (s) { str = (char*)s; dynamic = false; } else { str = new char[width + 1]; str[0] = '\0'; dynamic = true; } } void Label::display() { dtioDisplay(str, row, col, len); } Label *Label::clone()const { return new(std::nothrow) Label(row, col, len, str); } Label::~Label() { if (dynamic) { if (str) { delete [] str; } } } /* START OF RESPONSE CLASS */ Response::Response(int r, int c, const char *s, int ch, void (*fptr)(Screen*)) { valid_chars = NULL; response_f = NULL; init(r, c, s, ch, fptr); } Response::~Response() { if (valid_chars) { delete [] valid_chars; } } void Response::init(int r, int c, const char *s, int ch, void (*fptr)(Screen *)) { setRow(r); setCol(c); setLen(1); setData(ch); if (valid_chars) { delete [] valid_chars; } valid_chars = new char[strlen(s) + 1]; strcpy(valid_chars, s); response_f = fptr; is_editable = true; } int Response::edit(Screen *sptr) { bool editing = true; int orig_d = d; dtioCursor(row, col); d = dtioGetchar(); display(); if (! index(valid_chars, d)) { d = orig_d; } if ((! index(valid_chars, d)) && response_f) { (*response_f)(sptr); } } void Response::display() { dtioCursor(row, col); dtioPutchar(d); } Response* Response::clone()const { return new(std::nothrow) Response(row, col, valid_chars, d, response_f); } /* START OF VFIELD CLASS */ VField::VField(int r, int c, int w, const char *s, int (*fptr)(char [], Screen *)) { d = NULL; init(r, c, w, s, fptr); } VField::~VField() { } int VField::edit(Screen *sptr) { bool editing = true; int exit_key; do { exit_key = Field::edit(); if (exit_key != ESCAPE) { if ((*validate_f)(d, sptr)) { editing = false; } } else { editing = false; } } while (editing); return exit_key; } /* set the data of the field */ void VField::setData(const char *s, int l) { /* free the old one if necessary */ if (d) { delete [] d; } /* allocate memory for a new one */ d = new char[l+1]; if (d) { /* write the new data and terminate the string */ strncpy(d, s, l); d[l] = '\0'; } } VField* VField::clone()const { return new(std::nothrow) VField(row, col, len, d, validate_f); } void VField::init(int r, int c, int w, const char *s, int (*fptr)(char [], Screen *)) { setRow(r); setCol(c); setLen(w); setData(s, w); is_editable = true; validate_f = fptr; }