|
|
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: #ifndef _EDITBUF_H ! 28: #define _EDITBUF_H ! 29: #ifdef __GNUG__ ! 30: #pragma interface ! 31: #pragma cplusplus ! 32: #endif ! 33: #include <stdio.h> ! 34: #include <fstream.h> ! 35: ! 36: typedef unsigned long mark_pointer; ! 37: // At some point, it might be nice to parameterize this code ! 38: // in terms of buf_char. ! 39: typedef /*unsigned*/ char buf_char; ! 40: ! 41: // Logical pos from start of buffer (does not count gap). ! 42: typedef long buf_index; ! 43: ! 44: // Pos from start of buffer, possibly including gap_size. ! 45: typedef long buf_offset; ! 46: ! 47: #if 0 ! 48: struct buf_cookie { ! 49: FILE *file; ! 50: struct edit_string *str; ! 51: struct buf_cookie *next; ! 52: buf_index tell(); ! 53: }; ! 54: #endif ! 55: ! 56: struct edit_buffer; ! 57: struct edit_mark; ! 58: ! 59: // A edit_string is defined as the region between the 'start' and 'end' marks. ! 60: // Normally (always?) 'start->insert_before()' should be false, ! 61: // and 'end->insert_before()' should be true. ! 62: ! 63: struct edit_string { ! 64: struct edit_buffer *buffer; // buffer that 'start' and 'end' belong to ! 65: struct edit_mark *start, *end; ! 66: int length() const; // count of buf_chars currently in string ! 67: edit_string(struct edit_buffer *b, ! 68: struct edit_mark *ms, struct edit_mark *me) ! 69: { buffer = b; start = ms; end = me; } ! 70: /* Make a fresh, contiguous copy of the data in STR. ! 71: Assign length of STR to *LENP. ! 72: (Output has extra NUL at out[*LENP].) */ ! 73: buf_char *copy_bytes(int *lenp) const; ! 74: // FILE *open_file(char *mode); ! 75: void assign(struct edit_string *src); // copy bytes from src to this ! 76: }; ! 77: ! 78: struct edit_streambuf : public streambuf { ! 79: friend edit_buffer; ! 80: edit_string *str; ! 81: edit_streambuf* next; // Chain of edit_streambuf's for a edit_buffer. ! 82: short _mode; ! 83: edit_streambuf(edit_string* bstr, int mode); ! 84: ~edit_streambuf(); ! 85: virtual int underflow(); ! 86: virtual int overflow(int c = EOF); ! 87: virtual streampos seekoff(streamoff, _seek_dir, int mode=ios::in|ios::out); ! 88: void flush_to_buffer(); ! 89: void flush_to_buffer(edit_buffer* buffer); ! 90: int _inserting; ! 91: int inserting() { return _inserting; } ! 92: void inserting(int i) { _inserting = i; } ! 93: // int delete_chars(int count, char* cut_buf); Not implemented. ! 94: int truncate(); ! 95: int is_reading() { return gptr() != NULL; } ! 96: buf_char* current() { return is_reading() ? gptr() : pptr(); } ! 97: void set_current(char *p, int is_reading); ! 98: protected: ! 99: void disconnect_gap_from_file(edit_buffer* buffer); ! 100: }; ! 101: ! 102: // A 'edit_mark' indicates a position in a buffer. ! 103: // It is "attached" the text (rather than the offset). ! 104: // There are two kinds of mark, which have different behavior ! 105: // when text is inserted at the mark: ! 106: // If 'insert_before()' is true the mark will be adjusted to be ! 107: // *after* the new text. ! 108: ! 109: struct edit_mark { ! 110: struct edit_mark *chain; ! 111: mark_pointer _pos; ! 112: inline int insert_before() { return _pos & 1; } ! 113: inline unsigned long index_in_buffer(struct edit_buffer *buffer) ! 114: { return _pos >> 1; } ! 115: inline buf_char *ptr(struct edit_buffer *buf); ! 116: buf_index tell(); ! 117: edit_mark() { } ! 118: edit_mark(struct edit_string *str, long delta); ! 119: edit_buffer *buffer(); ! 120: ~edit_mark(); ! 121: }; ! 122: ! 123: // A 'edit_buffer' consists of a sequence of buf_chars (the data), ! 124: // a list of edit_marks pointing into the data, and a list of FILEs ! 125: // also pointing into the data. ! 126: // A 'edit_buffer' coerced to a edit_string is the string of ! 127: // all the buf_chars in the buffer. ! 128: ! 129: // This implementation uses a conventional buffer gap (as in Emacs). ! 130: // The gap start is defined by de-referencing a (buf_char**). ! 131: // This is because sometimes a FILE is inserting into the buffer, ! 132: // so rather than having each putc adjust the gap, we use indirection ! 133: // to have the gap be defined as the write pointer of the FILE. ! 134: // (This assumes that putc adjusts a pointer (as in GNU's libc), not an index.) ! 135: ! 136: struct edit_buffer { ! 137: buf_char *data; /* == emacs buffer_text.p1+1 */ ! 138: buf_char *_gap_start; ! 139: edit_streambuf* _writer; // If non-NULL, currently writing stream ! 140: inline buf_char *gap_start() ! 141: { return _writer ? _writer->pptr() : _gap_start; } ! 142: buf_offset __gap_end_pos; // size of part 1 + size of gap ! 143: /* int gap; implicit: buf_size - size1 - size2 */ ! 144: int buf_size; ! 145: struct edit_streambuf *files; ! 146: struct edit_mark start_mark; ! 147: struct edit_mark end_mark; ! 148: edit_buffer(); ! 149: inline buf_offset gap_end_pos() { return __gap_end_pos; } ! 150: inline struct edit_mark *start_marker() { return &start_mark; } ! 151: inline struct edit_mark *end_marker() { return &end_mark; } ! 152: /* these should be protected, ultimately */ ! 153: buf_index tell(edit_mark*); ! 154: buf_index tell(buf_char*); ! 155: inline buf_char *gap_end() { return data + gap_end_pos(); } ! 156: inline int gap_size() { return gap_end() - gap_start(); } ! 157: inline int size1() { return gap_start() - data; } ! 158: inline int size2() { return buf_size - gap_end_pos(); } ! 159: inline struct edit_mark * mark_list() { return &start_mark; } ! 160: void make_gap (buf_offset); ! 161: void move_gap (buf_offset pos); ! 162: void move_gap (buf_char *pos) { move_gap(pos - data); } ! 163: void gap_left (int pos); ! 164: void gap_right (int pos); ! 165: void adjust_markers(mark_pointer low, mark_pointer high, ! 166: int amount, buf_char *old_data); ! 167: void delete_range(buf_index from, buf_index to); ! 168: void delete_range(struct edit_mark *start, struct edit_mark *end); ! 169: }; ! 170: ! 171: extern buf_char * bstr_copy(struct edit_string *str, int *lenp); ! 172: ! 173: // Convert a edit_mark to a (buf_char*) ! 174: ! 175: inline buf_char *edit_mark::ptr(struct edit_buffer *buf) ! 176: { return buf->data + index_in_buffer(buf); } ! 177: ! 178: inline void edit_streambuf::flush_to_buffer() ! 179: { ! 180: edit_buffer* buffer = str->buffer; ! 181: if (buffer->_writer == this) flush_to_buffer(buffer); ! 182: } ! 183: #endif /* !_EDITBUF_H*/ ! 184:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.