Annotation of GNUtools/libg++/libio/editbuf.cc, revision 1.1

1.1     ! root        1: /* This is part of libio/iostream, providing -*- C++ -*- input/output.
        !             2: Copyright (C) 1993 Free Software Foundation
        !             3: 
        !             4: This file is part of the GNU IO Library.  This library is free
        !             5: software; you can redistribute it and/or modify it under the
        !             6: terms of the GNU General Public License as published by the
        !             7: Free Software Foundation; either version 2, or (at your option)
        !             8: any later version.
        !             9: 
        !            10: This library is distributed in the hope that it will be useful,
        !            11: but WITHOUT ANY WARRANTY; without even the implied warranty of
        !            12: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        !            13: GNU General Public License for more details.
        !            14: 
        !            15: You should have received a copy of the GNU General Public License
        !            16: along with GNU CC; see the file COPYING.  If not, write to
        !            17: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
        !            18: 
        !            19: As a special exception, if you link this library with files
        !            20: compiled with a GNU compiler to produce an executable, this does not cause
        !            21: the resulting executable to be covered by the GNU General Public License.
        !            22: This exception does not however invalidate any other reasons why
        !            23: the executable file might be covered by the GNU General Public License.
        !            24: 
        !            25: Written by Per Bothner ([email protected]). */
        !            26: 
        !            27: #ifdef __GNUG__
        !            28: #pragma implementation
        !            29: #endif
        !            30: #include "libioP.h"
        !            31: #include "editbuf.h"
        !            32: #include <stddef.h>
        !            33: extern "C" {
        !            34: #include <stdlib.h>
        !            35: }
        !            36: /* NOTE: Some of the code here is taken from GNU emacs */
        !            37: /* Hence this file falls under the GNU License! */
        !            38: 
        !            39: // Invariants for edit_streambuf:
        !            40: // An edit_streambuf is associated with a specific edit_string,
        !            41: // which again is a sub-string of a specific edit_buffer.
        !            42: // An edit_streambuf is always in either get mode or put mode, never both.
        !            43: // In get mode, gptr() is the current position,
        !            44: // and pbase(), pptr(), and epptr() are all NULL.
        !            45: // In put mode, pptr() is the current position,
        !            46: // and eback(), gptr(), and egptr() are all NULL.
        !            47: // Any edit_streambuf that is actively doing insertion (as opposed to
        !            48: // replacing) // must have its pptr() pointing to the start of the gap.
        !            49: // Only one edit_streambuf can be actively inserting into a specific
        !            50: // edit_buffer; the edit_buffer's _writer field points to that edit_streambuf.
        !            51: // That edit_streambuf "owns" the gap, and the actual start of the
        !            52: // gap is the pptr() of the edit_streambuf; the edit_buffer::_gap_start pointer
        !            53: // will only be updated on an edit_streambuf::overflow().
        !            54: 
        !            55: int edit_streambuf::truncate()
        !            56: {
        !            57:     str->buffer->delete_range(str->buffer->tell((buf_char*)pptr()),
        !            58:                              str->buffer->tell(str->end));
        !            59:     return 0;
        !            60: }
        !            61: 
        !            62: #ifdef OLD_STDIO
        !            63: inline void  disconnect_gap_from_file(edit_buffer* buffer, FILE* fp)
        !            64: {
        !            65:     if (buffer->gap_start_ptr != &fp->__bufp)
        !            66:        return;
        !            67:     buffer->gap_start_normal = fp->__bufp;
        !            68:     buffer->gap_start_ptr = &buffer->gap_start_normal;
        !            69: }
        !            70: #endif
        !            71: 
        !            72: void edit_streambuf::flush_to_buffer(edit_buffer* buffer)
        !            73: {
        !            74:     if (pptr() > buffer->_gap_start && pptr() < buffer->gap_end())
        !            75:        buffer->_gap_start = pptr();
        !            76: }
        !            77: 
        !            78: void edit_streambuf::disconnect_gap_from_file(edit_buffer* buffer)
        !            79: {
        !            80:     if (buffer->_writer != this) return;
        !            81:     flush_to_buffer(buffer);
        !            82:     setp(pptr(),pptr());
        !            83:     buffer->_writer = NULL;    
        !            84: }
        !            85: 
        !            86: buf_index edit_buffer::tell(buf_char *ptr)
        !            87: {
        !            88:     if (ptr <= gap_start())
        !            89:        return ptr - data;
        !            90:     else
        !            91:        return ptr - gap_end() + size1();
        !            92: }
        !            93: 
        !            94: #if 0
        !            95: buf_index buf_cookie::tell()
        !            96: {
        !            97:     return str->buffer->tell(file->__bufp);
        !            98: }
        !            99: #endif
        !           100: 
        !           101: buf_index edit_buffer::tell(edit_mark*mark)
        !           102: {
        !           103:     return tell(data + mark->index_in_buffer(this));
        !           104: }
        !           105: 
        !           106: // adjust the position of the gap
        !           107: 
        !           108: void edit_buffer::move_gap(buf_offset pos)
        !           109: {
        !           110:   if (pos < size1())
        !           111:     gap_left (pos);
        !           112:   else if (pos > size1())
        !           113:     gap_right (pos);
        !           114: }
        !           115: 
        !           116: void edit_buffer::gap_left (int pos)
        !           117: {
        !           118:   register buf_char *to, *from;
        !           119:   register int i;
        !           120:   int new_s1;
        !           121: 
        !           122:   i = size1();
        !           123:   from = gap_start();
        !           124:   to = from + gap_size();
        !           125:   new_s1 = size1();
        !           126: 
        !           127:   /* Now copy the characters.  To move the gap down,
        !           128:      copy characters up.  */
        !           129: 
        !           130:   for (;;)
        !           131:     {
        !           132:       /* I gets number of characters left to copy.  */
        !           133:       i = new_s1 - pos;
        !           134:       if (i == 0)
        !           135:        break;
        !           136: #if 0
        !           137:       /* If a quit is requested, stop copying now.
        !           138:         Change POS to be where we have actually moved the gap to.  */
        !           139:       if (QUITP)
        !           140:        {
        !           141:          pos = new_s1;
        !           142:          break;
        !           143:        }
        !           144: #endif
        !           145:       /* Move at most 32000 chars before checking again for a quit.  */
        !           146:       if (i > 32000)
        !           147:        i = 32000;
        !           148:       new_s1 -= i;
        !           149:       while (--i >= 0)
        !           150:        *--to = *--from;
        !           151:     }
        !           152: 
        !           153:   /* Adjust markers, and buffer data structure, to put the gap at POS.
        !           154:      POS is where the loop above stopped, which may be what was specified
        !           155:      or may be where a quit was detected.  */
        !           156:   adjust_markers (pos << 1, size1() << 1, gap_size(), data);
        !           157: #ifndef OLD_STDIO
        !           158:   _gap_start = data + pos;
        !           159: #else
        !           160:   if (gap_start_ptr == &gap_start_normal)
        !           161:        gap_start_normal = data + pos;
        !           162: #endif
        !           163:   __gap_end_pos = to - data;
        !           164: /*  QUIT;*/
        !           165: }
        !           166: 
        !           167: void edit_buffer::gap_right (int pos)
        !           168: {
        !           169:   register buf_char *to, *from;
        !           170:   register int i;
        !           171:   int new_s1;
        !           172: 
        !           173:   i = size1();
        !           174:   to = gap_start();
        !           175:   from = i + gap_end();
        !           176:   new_s1 = i;
        !           177: 
        !           178:   /* Now copy the characters.  To move the gap up,
        !           179:      copy characters down.  */
        !           180: 
        !           181:   while (1)
        !           182:     {
        !           183:       /* I gets number of characters left to copy.  */
        !           184:       i = pos - new_s1;
        !           185:       if (i == 0)
        !           186:        break;
        !           187: #if 0
        !           188:       /* If a quit is requested, stop copying now.
        !           189:         Change POS to be where we have actually moved the gap to.  */
        !           190:       if (QUITP)
        !           191:        {
        !           192:          pos = new_s1;
        !           193:          break;
        !           194:        }
        !           195: #endif
        !           196:       /* Move at most 32000 chars before checking again for a quit.  */
        !           197:       if (i > 32000)
        !           198:        i = 32000;
        !           199:       new_s1 += i;
        !           200:       while (--i >= 0)
        !           201:        *to++ = *from++;
        !           202:     }
        !           203: 
        !           204:   adjust_markers ((size1() + gap_size()) << 1, (pos + gap_size()) << 1,
        !           205:        - gap_size(), data);
        !           206: #ifndef OLD_STDIO
        !           207:   _gap_start = data+pos;
        !           208: #else
        !           209:   if (gap_start_ptr == &gap_start_normal)
        !           210:        gap_start_normal = data + pos;
        !           211: #endif
        !           212:   __gap_end_pos = from - data;
        !           213: /*  QUIT;*/
        !           214: }
        !           215: 
        !           216: /* make sure that the gap in the current buffer is at least k
        !           217:    characters wide */
        !           218: 
        !           219: void edit_buffer::make_gap(buf_offset k)
        !           220: {
        !           221:   register buf_char *p1, *p2, *lim;
        !           222:   buf_char *old_data = data;
        !           223:   int s1 = size1();
        !           224: 
        !           225:   if (gap_size() >= k)
        !           226:     return;
        !           227: 
        !           228:   /* Get more than just enough */
        !           229:   if (buf_size > 1000) k += 2000;
        !           230:   else k += /*200;*/ 20; // for testing!
        !           231: 
        !           232:   p1 = (buf_char *) realloc (data, s1 + size2() + k);
        !           233:   if (p1 == 0)
        !           234:     abort(); /*memory_full ();*/
        !           235: 
        !           236:   k -= gap_size();                     /* Amount of increase.  */
        !           237: 
        !           238:   /* Record new location of text */
        !           239:   data = p1;
        !           240: 
        !           241:   /* Transfer the new free space from the end to the gap
        !           242:      by shifting the second segment upward */
        !           243:   p2 = data + buf_size;
        !           244:   p1 = p2 + k;
        !           245:   lim = p2 - size2();
        !           246:   while (lim < p2)
        !           247:     *--p1 = *--p2;
        !           248: 
        !           249:   /* Finish updating text location data */
        !           250:   __gap_end_pos += k;
        !           251: 
        !           252: #ifndef OLD_STDIO
        !           253:   _gap_start = data + s1;
        !           254: #else
        !           255:   if (gap_start_ptr == &gap_start_normal)
        !           256:        gap_start_normal = data + s1;
        !           257: #endif
        !           258: 
        !           259:   /* adjust markers */
        !           260:   adjust_markers (s1 << 1, (buf_size << 1) + 1, k, old_data);
        !           261:   buf_size += k;
        !           262: }
        !           263: 
        !           264: /* Add `amount' to the position of every marker in the current buffer
        !           265:    whose current position is between `from' (exclusive) and `to' (inclusive).
        !           266:    Also, any markers past the outside of that interval, in the direction
        !           267:    of adjustment, are first moved back to the near end of the interval
        !           268:    and then adjusted by `amount'.  */
        !           269: 
        !           270: void edit_buffer::adjust_markers(register mark_pointer low,
        !           271:                                 register mark_pointer high,
        !           272:                                 int amount, buf_char *old_data)
        !           273: {
        !           274:   register struct edit_mark *m;
        !           275:   register mark_pointer mpos;
        !           276:   /* convert to mark_pointer */
        !           277:   amount <<= 1;
        !           278: 
        !           279:   if (_writer)
        !           280:       _writer->disconnect_gap_from_file(this);
        !           281: 
        !           282:   for (m = mark_list(); m != NULL; m = m->chain)
        !           283:     {
        !           284:       mpos = m->_pos;
        !           285:       if (amount > 0)
        !           286:        {
        !           287:          if (mpos > high && mpos < high + amount)
        !           288:            mpos = high + amount;
        !           289:        }
        !           290:       else
        !           291:        {
        !           292:          if (mpos > low + amount && mpos <= low)
        !           293:            mpos = low + amount;
        !           294:        }
        !           295:       if (mpos > low && mpos <= high)
        !           296:        mpos += amount;
        !           297:       m->_pos = mpos;
        !           298:     }
        !           299: 
        !           300:     // Now adjust files
        !           301:     edit_streambuf *file;
        !           302: 
        !           303:     for (file = files; file != NULL; file = file->next) {
        !           304:        mpos = file->current() - old_data;
        !           305:        if (amount > 0)
        !           306:        {
        !           307:          if (mpos > high && mpos < high + amount)
        !           308:            mpos = high + amount;
        !           309:        }
        !           310:        else
        !           311:        {
        !           312:          if (mpos > low + amount && mpos <= low)
        !           313:            mpos = low + amount;
        !           314:        }
        !           315:        if (mpos > low && mpos <= high)
        !           316:            mpos += amount;
        !           317:        char* new_pos = data + mpos;
        !           318:        file->set_current(new_pos, file->is_reading());
        !           319:     }
        !           320: }
        !           321: 
        !           322: #if 0
        !           323: stdio_
        !           324:    __off == index at start of buffer (need only be valid after seek ? )
        !           325:    __buf ==
        !           326: 
        !           327: if read/read_delete/overwrite mode:
        !           328:      __endp <= min(*gap_start_ptr, edit_string->end->ptr(buffer))
        !           329: 
        !           330: if inserting:
        !           331:      must have *gap_start_ptr == __bufp && *gap_start_ptr+gap == __endp
        !           332:      file->edit_string->end->ptr(buffer) == *gap_start_ptr+end
        !           333: if write_mode:
        !           334:      if before gap
        !           335: #endif
        !           336: 
        !           337: int edit_streambuf::underflow()
        !           338: {
        !           339:     if (!(_mode & ios::in))
        !           340:        return EOF;
        !           341:     struct edit_buffer *buffer = str->buffer;
        !           342:     if (!is_reading()) { // Must switch from put to get mode.
        !           343:        disconnect_gap_from_file(buffer);
        !           344:        set_current(pptr(), 1);
        !           345:     }
        !           346:     buf_char *str_end = str->end->ptr(buffer);
        !           347:   retry:
        !           348:     if (gptr() < egptr()) {
        !           349:        return *gptr();
        !           350:     }
        !           351:     if ((buf_char*)gptr() == str_end)
        !           352:        return EOF;
        !           353:     if (str_end <= buffer->gap_start()) {
        !           354:        setg(eback(), gptr(), str_end);
        !           355:        goto retry;
        !           356:     }
        !           357:     if (gptr() < buffer->gap_start()) {
        !           358:        setg(eback(), gptr(), buffer->gap_start());
        !           359:        goto retry;
        !           360:     }
        !           361:     if (gptr() == buffer->gap_start()) {
        !           362:        disconnect_gap_from_file(buffer);
        !           363: //     fp->__offset += fp->__bufp - fp->__buffer;
        !           364:        setg(buffer->gap_end(), buffer->gap_end(), str_end);
        !           365:     }
        !           366:     else
        !           367:        setg(eback(), gptr(), str_end);
        !           368:     goto retry;
        !           369: }
        !           370: 
        !           371: int edit_streambuf::overflow(int ch)
        !           372: {
        !           373:     if (_mode == ios::in)
        !           374:        return EOF;
        !           375:     struct edit_buffer *buffer = str->buffer;
        !           376:     flush_to_buffer(buffer);
        !           377:     if (ch == EOF)
        !           378:        return 0;
        !           379:     if (is_reading()) { // Must switch from get to put mode.
        !           380:        set_current(gptr(), 0);
        !           381:     }
        !           382:     buf_char *str_end = str->end->ptr(buffer);
        !           383:   retry:
        !           384:     if (pptr() < epptr()) {
        !           385:        *pptr() = ch;
        !           386:        pbump(1);
        !           387:        return (unsigned char)ch;
        !           388:     }
        !           389:     if ((buf_char*)pptr() == str_end || inserting()) {
        !           390:        /* insert instead */
        !           391:        if (buffer->_writer)
        !           392:            buffer->_writer->flush_to_buffer(); // Redundant?
        !           393:        buffer->_writer = NULL;
        !           394:        if  (pptr() >= buffer->gap_end())
        !           395:            buffer->move_gap(pptr() - buffer->gap_size());
        !           396:        else
        !           397:            buffer->move_gap(pptr());
        !           398:        buffer->make_gap(1);
        !           399:        setp(buffer->gap_start(), buffer->gap_end());
        !           400:        buffer->_writer = this;
        !           401:        *pptr() = ch;
        !           402:        pbump(1);
        !           403:        return (unsigned char)ch;
        !           404:     }
        !           405:     if (str_end <= buffer->gap_start()) {
        !           406:        // Entire string is left of gap.
        !           407:        setp(pptr(), str_end);
        !           408:     }
        !           409:     else if (pptr() < buffer->gap_start()) {
        !           410:        // Current pos is left of gap.
        !           411:        setp(pptr(), buffer->gap_start());
        !           412:        goto retry;
        !           413:     }
        !           414:     else if (pptr() == buffer->gap_start()) {
        !           415:        // Current pos is at start of gap; move to end of gap.
        !           416: //     disconnect_gap_from_file(buffer);
        !           417:        setp(buffer->gap_end(), str_end);
        !           418: //     __offset += __bufp - __buffer;
        !           419:     }
        !           420:     else {
        !           421:        // Otherwise, current pos is right of gap.
        !           422:        setp(pptr(), str_end);
        !           423:     }
        !           424:     goto retry;
        !           425: }
        !           426: 
        !           427: void edit_streambuf::set_current(char *new_pos, int reading)
        !           428: {
        !           429:     if (reading) {
        !           430:        setg(new_pos, new_pos, new_pos);
        !           431:        setp(NULL, NULL);
        !           432:     }
        !           433:     else {
        !           434:        setg(NULL, NULL, NULL);
        !           435:        setp(new_pos, new_pos);
        !           436:     }
        !           437: }
        !           438: 
        !           439: // Called by fseek(fp, pos, whence) if fp is bound to a edit_buffer.
        !           440: 
        !           441: streampos edit_streambuf::seekoff(streamoff offset, _seek_dir dir,
        !           442:                                  int mode /* =ios::in|ios::out*/)
        !           443: {
        !           444:     struct edit_buffer *buffer = str->buffer;
        !           445:     disconnect_gap_from_file(buffer);
        !           446:     buf_index cur_pos = buffer->tell((buf_char*)current());;
        !           447:     buf_index start_pos = buffer->tell(str->start);
        !           448:     buf_index end_pos = buffer->tell(str->end);
        !           449:     switch (dir) {
        !           450:       case ios::beg:
        !           451:        offset += start_pos;
        !           452:        break;
        !           453:       case ios::cur:
        !           454:        offset += cur_pos;
        !           455:        break;
        !           456:       case ios::end:
        !           457:        offset += end_pos;
        !           458:        break;
        !           459:     }
        !           460:     if (offset < start_pos || offset > end_pos)
        !           461:        return EOF;
        !           462:     buf_char *new_pos = buffer->data + offset;
        !           463:     buf_char* gap_start = buffer->gap_start();
        !           464:     if (new_pos > gap_start) {
        !           465:        buf_char* gap_end = buffer->gap_end();
        !           466:        new_pos += gap_end - gap_start;
        !           467:        if (new_pos >= buffer->data + buffer->buf_size) abort(); // Paranoia.
        !           468:     }
        !           469:     set_current(new_pos, is_reading());
        !           470:     return EOF;
        !           471: }
        !           472: 
        !           473: #if 0
        !           474: int buf_seek(void *arg_cookie, fpos_t * pos, int whence)
        !           475: {
        !           476:     struct buf_cookie *cookie = arg_cookie;
        !           477:     FILE *file = cookie->file;
        !           478:     struct edit_buffer *buffer = cookie->str->buffer;
        !           479:     buf_char *str_start = cookie->str->start->ptr(buffer);
        !           480:     disconnect_gap_from_file(buffer, cookie->file);
        !           481:     fpos_t cur_pos, new_pos;
        !           482:     if (file->__bufp <= *buffer->gap_start_ptr
        !           483:        || str_start >= buffer->__gap_end)
        !           484:        cur_pos = str_start - file->__bufp;
        !           485:     else
        !           486:        cur_pos =
        !           487:            (*buffer->gap_start_ptr - str_start) + (file->__bufp - __gap_end);
        !           488:     end_pos = ...;
        !           489:     switch (whence) {
        !           490:       case SEEK_SET:
        !           491:        new_pos = *pos;
        !           492:        break;
        !           493:       case SEEK_CUR:
        !           494:        new_pos = cur_pos + *pos;
        !           495:        break;
        !           496:       case SEEK_END:
        !           497:        new_pos = end_pos + *pos;
        !           498:        break;
        !           499:     }
        !           500:     if (new_pos > end_pos) {
        !           501:        seek to end_pos;
        !           502:        insert_nulls(new_pos - end_pos);
        !           503:        return;
        !           504:     }
        !           505:     if (str_start + new_pos <= *gap_start_ptr &* *gap_start_ptr < end) {
        !           506:        __buffer = str_start;
        !           507:         __off = 0;
        !           508:        __bufp = str_start + new_pos;
        !           509:        file->__get_limit =
        !           510:            *buffer->gap_start_ptr; /* what if gap_start_ptr == &bufp ??? */
        !           511:     } else if () {
        !           512:        
        !           513:     }
        !           514:     *pos = new_pos;
        !           515: }
        !           516: #endif
        !           517: 
        !           518: /* Delete characters from `from' up to (but not incl) `to' */
        !           519: 
        !           520: void edit_buffer::delete_range (buf_index from, buf_index to)
        !           521: {
        !           522:   register int numdel;
        !           523: 
        !           524:   if ((numdel = to - from) <= 0)
        !           525:     return;
        !           526: 
        !           527:   /* Make sure the gap is somewhere in or next to what we are deleting */
        !           528:   if (from > size1())
        !           529:     gap_right (from);
        !           530:   if (to < size1())
        !           531:     gap_left (to);
        !           532: 
        !           533:   /* Relocate all markers pointing into the new, larger gap
        !           534:      to point at the end of the text before the gap.  */
        !           535:   adjust_markers ((to + gap_size()) << 1, (to + gap_size()) << 1,
        !           536:        - numdel - gap_size(), data);
        !           537: 
        !           538:    __gap_end_pos = to + gap_size();
        !           539:   _gap_start = data + from;
        !           540: }
        !           541: 
        !           542: void edit_buffer::delete_range(struct edit_mark *start, struct edit_mark *end)
        !           543: {
        !           544:     delete_range(tell(start), tell(end));
        !           545: }
        !           546: 
        !           547: void buf_delete_chars(struct edit_buffer *buf, struct edit_mark *mark, size_t count)
        !           548: {
        !           549:  abort();
        !           550: }
        !           551: 
        !           552: edit_streambuf::edit_streambuf(edit_string* bstr, int mode)
        !           553: {
        !           554:     _mode = mode;
        !           555:     str = bstr;
        !           556:     edit_buffer* buffer = bstr->buffer;
        !           557:     next = buffer->files;
        !           558:     buffer->files = this;
        !           559:     char* buf_ptr = bstr->start->ptr(buffer);
        !           560:     _inserting = 0;
        !           561: //    setb(buf_ptr, buf_ptr, 0);
        !           562:     set_current(buf_ptr, !(mode & ios::out+ios::trunc+ios::app));
        !           563:     if (_mode & ios::trunc)
        !           564:        truncate();
        !           565:     if (_mode & ios::ate)
        !           566:        seekoff(0, ios::end);
        !           567: }
        !           568: 
        !           569: // Called by fclose(fp) if fp is bound to a edit_buffer.
        !           570: 
        !           571: #if 0
        !           572: static int buf_close(void *arg)
        !           573: {
        !           574:     register struct buf_cookie *cookie = arg;
        !           575:     struct edit_buffer *buffer = cookie->str->buffer;
        !           576:     struct buf_cookie **ptr;
        !           577:     for (ptr = &buffer->files; *ptr != cookie; ptr = &(*ptr)->next) ;
        !           578:     *ptr = cookie->next;
        !           579:     disconnect_gap_from_file(buffer, cookie->file);
        !           580:     free (cookie);
        !           581:     return 0;
        !           582: }
        !           583: #endif
        !           584: 
        !           585: edit_streambuf::~edit_streambuf()
        !           586: {
        !           587:     if (_mode == ios::out)
        !           588:        truncate();
        !           589:     // Unlink this from list of files associated with bstr->buffer.
        !           590:     edit_streambuf **ptr = &str->buffer->files;
        !           591:     for (; *ptr != this; ptr = &(*ptr)->next) { }
        !           592:     *ptr = next;
        !           593: 
        !           594:     disconnect_gap_from_file(str->buffer);
        !           595: }
        !           596: 
        !           597: edit_buffer::edit_buffer()
        !           598: {
        !           599:     buf_size = /*200;*/ 15; /* for testing! */
        !           600:     data = (buf_char*)malloc(buf_size);
        !           601:     files = NULL;
        !           602: #ifndef OLD_STDIO
        !           603:     _gap_start = data;
        !           604:     _writer = NULL;
        !           605: #else
        !           606:     gap_start_normal = data;
        !           607:     gap_start_ptr = &gap_start_normal;
        !           608: #endif
        !           609:     __gap_end_pos = buf_size;
        !           610:     start_mark.chain = &end_mark;
        !           611:     start_mark._pos = 0;
        !           612:     end_mark.chain = NULL;
        !           613:     end_mark._pos = 2 * buf_size + 1;
        !           614: }
        !           615: 
        !           616: // Allocate a new mark, which is adjusted by 'delta' bytes from 'this'.
        !           617: // Restrict new mark to lie within 'str'.
        !           618: 
        !           619: edit_mark::edit_mark(struct edit_string *str, long delta)
        !           620: {
        !           621:     struct edit_buffer *buf = str->buffer;
        !           622:     chain = buf->start_mark.chain;
        !           623:     buf->start_mark.chain = this;
        !           624:     mark_pointer size1 = buf->size1() << 1;
        !           625:     int gap_size = buf->gap_size() << 1;
        !           626:     delta <<= 1;
        !           627: 
        !           628:     // check if new and old marks are opposite sides of gap
        !           629:     if (_pos <= size1 && _pos + delta > size1)
        !           630:        delta += gap_size;
        !           631:     else if (_pos >= size1 + gap_size && _pos + delta < size1 + gap_size)
        !           632:        delta -= gap_size;
        !           633: 
        !           634:     _pos = _pos + delta;
        !           635:     if (_pos < str->start->_pos & ~1)
        !           636:        _pos = (str->start->_pos & ~ 1) + (_pos & 1);
        !           637:     else if (_pos >= str->end->_pos)
        !           638:        _pos = (str->end->_pos & ~ 1) + (_pos & 1);
        !           639: }
        !           640: 
        !           641: // A (slow) way to find the buffer a mark belongs to.
        !           642: 
        !           643: edit_buffer * edit_mark::buffer()
        !           644: {
        !           645:     struct edit_mark *mark;
        !           646:     for (mark = this; mark->chain != NULL; mark = mark->chain) ;
        !           647:     // Assume that the last mark on the chain is the end_mark.
        !           648:     return (edit_buffer *)((char*)mark - offsetof(edit_buffer, end_mark));
        !           649: }
        !           650: 
        !           651: edit_mark::~edit_mark()
        !           652: {
        !           653:     // Must unlink mark from chain of owning buffer
        !           654:     struct edit_buffer *buf = buffer();
        !           655:     if (this == &buf->start_mark || this == &buf->end_mark) abort();
        !           656:     edit_mark **ptr;
        !           657:     for (ptr = &buf->start_mark.chain; *ptr != this; ptr = &(*ptr)->chain) ;
        !           658:     *ptr = this->chain;
        !           659: }
        !           660: 
        !           661: int edit_string::length() const
        !           662: {
        !           663:     ptrdiff_t delta = end->ptr(buffer) - start->ptr(buffer);
        !           664:     if (end->ptr(buffer) <= buffer->gap_start() ||
        !           665:        start->ptr(buffer) >= buffer->gap_end())
        !           666:        return delta;
        !           667:     return delta - buffer->gap_size();
        !           668: }
        !           669: 
        !           670: buf_char * edit_string::copy_bytes(int *lenp) const
        !           671: {
        !           672:     char *new_str;
        !           673:     int len1, len2;
        !           674:     buf_char *start1, *start2;
        !           675:     start1 = start->ptr(buffer);
        !           676:     if (end->ptr(buffer) <= buffer->gap_start()
        !           677:        || start->ptr(buffer) >= buffer->gap_end()) {
        !           678:        len1 = end->ptr(buffer) - start1;
        !           679:        len2 = 0;
        !           680:        start2 = NULL; // To avoid a warning from g++.
        !           681:     }
        !           682:     else {
        !           683:        len1 = buffer->gap_start() - start1;
        !           684:        start2 = buffer->gap_end();
        !           685:        len2 = end->ptr(buffer) - start2;
        !           686:     }
        !           687:     new_str = (char*)malloc(len1 + len2 + 1);
        !           688:     memcpy(new_str, start1, len1);
        !           689:     if (len2 > 0) memcpy(new_str + len1, start2, len2);
        !           690:     new_str[len1+len2] = '\0';
        !           691:     *lenp = len1+len2;
        !           692:     return new_str;
        !           693: }
        !           694: 
        !           695: // Replace the buf_chars in 'this' with ones from 'src'.
        !           696: // Equivalent to deleting this, then inserting src, except tries
        !           697: // to leave marks in place: Marks whose offset from the start
        !           698: // of 'this' is less than 'src->length()' will still have the
        !           699: // same offset in 'this' when done.
        !           700: 
        !           701: void edit_string::assign(struct edit_string *src)
        !           702: {
        !           703:     edit_streambuf dst_file(this, ios::out);
        !           704:     if (buffer == src->buffer /*&& ???*/) { /* overly conservative */
        !           705:        int src_len;
        !           706:        buf_char *new_str;
        !           707:        new_str = src->copy_bytes(&src_len);
        !           708:        dst_file.sputn(new_str, src_len);
        !           709:        free (new_str);
        !           710:     } else {
        !           711:        edit_streambuf src_file(src, ios::in);
        !           712:        for ( ; ; ) {
        !           713:            int ch = src_file.sbumpc();
        !           714:            if (ch == EOF) break;
        !           715:            dst_file.sputc(ch);
        !           716:        }
        !           717:     }
        !           718: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.