home *** CD-ROM | disk | FTP | other *** search
- /*
- ** classes.C - contains definitions of the member functions which
- ** aren\'t defined in the relevant class declarations.
- **
- ** classes.C classes.C 1.9 Delta\'d: 12:28:24 9/23/92 Mike Lijewski, CNSF
- **
- ** Copyright \(c\) 1991, 1992 Cornell University
- ** All rights reserved.
- **
- ** Redistribution and use in source and binary forms are permitted
- ** provided that: \(1\) source distributions retain this entire copyright
- ** notice and comment, and \(2\) distributions including binaries display
- ** the following acknowledgement: ``This product includes software
- ** developed by Cornell University\'\' in the documentation or other
- ** materials provided with the distribution and in all advertising
- ** materials mentioning features or use of this software. Neither the
- ** name of the University nor the names of its contributors may be used
- ** to endorse or promote products derived from this software without
- ** specific prior written permission.
- **
- ** THIS SOFTWARE IS PROVIDED ``AS IS\'\' AND WITHOUT ANY EXPRESS OR
- ** IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- ** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- */
-
- #include <new.h>
- #include <stdlib.h>
- #include <string.h>
-
- #include "classes.h"
- #include "utilities.h"
-
- typedef void (*PEHF)();
-
- StringRep::StringRep()
- {
- rep = ::new char[1];
- len = 0;
- *rep = '\0';
- count = 1;
- }
-
- StringRep::StringRep(const char *s)
- {
- len = ::strlen(s);
- rep = ::new char[len + 1];
- ::strcpy(rep, s);
- count = 1;
- }
-
- String StringRep::operator+(const String& s) const
- {
- size_t slen = s.length() + length();
- char *buf = ::new char[slen + 1];
- ::strcpy(buf, rep);
- ::strcat(buf, s.p->rep);
- return String(&buf, slen);
- }
-
- /*
- ** The definition of the head of the freelist that StringRep::operator new\(\)
- ** uses to dole out StringReps efficiently.
- */
-
- StringRep *StringRep::freeList;
-
- void* StringRep::operator new(size_t size)
- {
- if (size != sizeof(StringRep)) return ::new char[size];
- StringRep *s = freeList;
- if (s)
- freeList = s->next;
- else
- {
- StringRep *block = (StringRep*)::new char[chunksize*sizeof(StringRep)];
- if (block == 0)
- {
- PEHF newHandler = set_new_handler(0);
- set_new_handler(newHandler);
- if (newHandler)
- newHandler();
- else
- return 0;
- }
- for (int i = 0; i < chunksize - 1; i++)
- block[i].next = (StringRep *)&block[i + 1];
- block[chunksize - 1].next = 0;
- s = block;
- freeList = &block[1];
- }
- return s;
- }
-
- void StringRep::operator delete(void *object)
- {
- StringRep *s = (StringRep *)object;
- s->next = freeList;
- freeList = s;
- }
-
- String::~String() { if (--p->count <= 0) delete p; }
-
- String& String::operator=(const String& rhs)
- {
- rhs.p->count++;
- if (--p->count <= 0) delete p;
- p = rhs.p;
- return *this;
- }
-
- void String::operator+=(const String& rhs)
- {
- size_t slen = p->length() + rhs.length();
- char *buf = ::new char[slen + 1];
- (void)strcpy(buf, p->rep);
- (void)strcat(buf, rhs.p->rep);
- if (p->count == 1)
- {
- DELETE p->rep;
- p->rep = buf;
- p->len = slen;
- }
- else
- operator=(String(&buf, slen));
- }
-
- void String::operator+=(const char *rhs)
- {
- size_t slen = p->length() + ::strlen(rhs);
- char *buf = ::new char[slen + 1];
- ::strcpy(buf, p->rep);
- ::strcat(buf, rhs);
- if (p->count == 1)
- {
- DELETE p->rep;
- p->rep = buf;
- p->len = slen;
- }
- else
- operator=(String(&buf, slen));
- }
-
- void String::range_error(int index)
- {
- ::error("range error: %d out of bounds", index);
- exit(1);
- }
-
- SBHelper String::operator[](int index)
- {
- if (index < 0 || index >= length()) range_error(index);
- return SBHelper(*this, index);
- }
-
- SBHelper::SBHelper(String& s, int i) : str(s), index(i) { };
-
- char SBHelper::operator=(char c)
- {
- if (str.p->count == 1)
- //
- // Only one reference to our String. Just assign the character to
- // the appropriate place. Note that String::operator\[\] does the
- // range checking.
- //
- str.p->rep[index] = c;
- else
- {
- // We have to uniquify our str.
- str = String(str.p->rep);
- str.p->rep[index] = c;
- }
- return c;
- }
-
- DLink::DLink(char **line) : _line(line) { _next = _prev = 0; }
-
- //
- // Update the line in DLink with a new version. The new
- // line should have been been allocated via new\(\).
- //
- void DLink::update(char **new_line) { _line = String(new_line); }
-
- DList::DList()
- {
- _head = _tail = 0;
- _next = _prev = 0;
- _firstLine = _lastLine = _currLine = 0;
- _nelems = _saved_x = _saved_y = 0;
- }
-
- //
- // Adds the DLink to the listing maintained by DList.
- //
-
- void DList::add(DLink *link)
- {
- if (nelems())
- {
- _tail->_next = link;
- _tail->_next->_prev = tail();
- _tail = link;
- _nelems++;
- }
- else
- {
- _head = _tail = link;
- _nelems = 1;
- }
- }
-
- //
- // Delete the current listing line in the window
- // and update our view. The width of our view
- // always decreases by one. If the calling procedure
- // adds more lines to the screen, they\'ll have to reset
- // lastLine\(\) and/or firstLine\(\), but currLine doesn\'t need to change.
- //
-
- void DList::deleteLine()
- {
- DLink *line = currLine();
-
- if (atBegOfList())
- {
- //
- // that is, firstLine\(\) == head\(\)
- //
- _head = _firstLine = _currLine = head()->next();
- _head->_prev = 0;
- }
- else if (atWindowTop())
- {
- //
- // but firstLine\(\) != head\(\)
- //
- _firstLine = _currLine = line->next();
- line->_next->_prev = line->prev();
- line->_prev->_next = line->next();
- }
- else if (atEndOfList())
- {
- //
- // lastLine\(\) == tail\(\)
- //
- _tail = _lastLine = _currLine = line->prev();
- _tail->_next = 0;
- }
- else
- {
- _currLine = line->next();
- line->_next->_prev = line->prev();
- line->_prev->_next = line->next();
- }
-
- _nelems--;
- delete line;
- }
-
- DList::~DList()
- {
- if (nelems())
- {
- DLink *tmp = tail(), *prev = tail()->prev();
- while(tmp)
- {
- delete tmp;
- if ((tmp = prev) != 0) prev = tmp->prev();
- }
- delete tmp;
- }
- }
-
- //
- // The definition of the head of the freelist that DLink::operator new\(\)
- // uses to dole out dirLines efficiently.
- //
- DLink *DLink::freeList;
-
- void *DLink::operator new(size_t)
- {
- DLink *line = freeList;
- if (line)
- freeList = line->next();
- else
- {
- DLink *block = (DLink *) ::new char[chunksize * sizeof(DLink)];
- if (block == 0)
- {
- PEHF newHandler = set_new_handler(0);
- set_new_handler(newHandler);
- if (newHandler)
- newHandler();
- else
- return 0;
- }
- for (int i = 0; i < chunksize - 1; i++)
- block[i]._next = (DLink *)&block[i + 1];
- block[chunksize - 1]._next = 0;
- line = block;
- freeList = &block[1];
- }
- return line;
- }
-
- void DLink::operator delete(void *object)
- {
- DLink *line = (DLink *)object;
- line->_next = freeList;
- freeList = line;
- }
-
-
-