📄 editbuf.c
字号:
// This is part of the iostream library, providing input/output for C++.// Copyright (C) 1991 Per Bothner.//// This library is free software; you can redistribute it and/or// modify it under the terms of the GNU Library General Public// License as published by the Free Software Foundation; either// version 2 of the License, or (at your option) any later version.//// This library is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU// Library General Public License for more details.//// You should have received a copy of the GNU Library General Public// License along with this library; if not, write to the Free// Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.#include "ioprivate.h"#include "editbuf.h"#include <stddef.h>#ifdef __GNUG__#pragma implementation#endif/* NOTE: Some of the code here is taken from GNU emacs *//* Hence this file falls under the GNU License! */// Invariants for edit_streambuf:// An edit_streambuf is associated with a specific edit_string,// which again is a sub-string of a specific edit_buffer.// An edit_streambuf is always in either get mode or put mode, never both.// In get mode, gptr() is the current position,// and pbase(), pptr(), and epptr() are all NULL.// In put mode, pptr() is the current position,// and eback(), gptr(), and egptr() are all NULL.// Any edit_streambuf that is actively doing insertion (as opposed to// replacing) // must have its pptr() pointing to the start of the gap.// Only one edit_streambuf can be actively inserting into a specific// edit_buffer; the edit_buffer's _writer field points to that edit_streambuf.// That edit_streambuf "owns" the gap, and the actual start of the// gap is the pptr() of the edit_streambuf; the edit_buffer::_gap_start pointer// will only be updated on an edit_streambuf::overflow().int edit_streambuf::truncate(){ str->buffer->delete_range(str->buffer->tell((buf_char*)pptr()), str->buffer->tell(str->end)); return 0;}#ifdef OLD_STDIOinline void disconnect_gap_from_file(edit_buffer* buffer, FILE* fp){ if (buffer->gap_start_ptr != &fp->__bufp) return; buffer->gap_start_normal = fp->__bufp; buffer->gap_start_ptr = &buffer->gap_start_normal;}#endifvoid edit_streambuf::flush_to_buffer(edit_buffer* buffer){ if (pptr() > buffer->_gap_start && pptr() < buffer->gap_end()) buffer->_gap_start = pptr();}void edit_streambuf::disconnect_gap_from_file(edit_buffer* buffer){ if (buffer->_writer != this) return; flush_to_buffer(buffer); setp(pptr(),pptr()); buffer->_writer = NULL; }buf_index edit_buffer::tell(buf_char *ptr){ if (ptr <= gap_start()) return ptr - data; else return ptr - gap_end() + size1();}#if 0buf_index buf_cookie::tell(){ return str->buffer->tell(file->__bufp);}#endifbuf_index edit_buffer::tell(edit_mark*mark){ return tell(data + mark->index_in_buffer(this));}// adjust the position of the gapvoid edit_buffer::move_gap(buf_offset pos){ if (pos < size1()) gap_left (pos); else if (pos > size1()) gap_right (pos);}void edit_buffer::gap_left (int pos){ register buf_char *to, *from; register int i; int new_s1; i = size1(); from = gap_start(); to = from + gap_size(); new_s1 = size1(); /* Now copy the characters. To move the gap down, copy characters up. */ for (;;) { /* I gets number of characters left to copy. */ i = new_s1 - pos; if (i == 0) break;#if 0 /* If a quit is requested, stop copying now. Change POS to be where we have actually moved the gap to. */ if (QUITP) { pos = new_s1; break; }#endif /* Move at most 32000 chars before checking again for a quit. */ if (i > 32000) i = 32000; new_s1 -= i; while (--i >= 0) *--to = *--from; } /* Adjust markers, and buffer data structure, to put the gap at POS. POS is where the loop above stopped, which may be what was specified or may be where a quit was detected. */ adjust_markers (pos << 1, size1() << 1, gap_size(), data);#ifndef OLD_STDIO _gap_start = data + pos;#else if (gap_start_ptr == &gap_start_normal) gap_start_normal = data + pos;#endif __gap_end_pos = to - data;/* QUIT;*/}void edit_buffer::gap_right (int pos){ register buf_char *to, *from; register int i; int new_s1; i = size1(); to = gap_start(); from = i + gap_end(); new_s1 = i; /* Now copy the characters. To move the gap up, copy characters down. */ while (1) { /* I gets number of characters left to copy. */ i = pos - new_s1; if (i == 0) break;#if 0 /* If a quit is requested, stop copying now. Change POS to be where we have actually moved the gap to. */ if (QUITP) { pos = new_s1; break; }#endif /* Move at most 32000 chars before checking again for a quit. */ if (i > 32000) i = 32000; new_s1 += i; while (--i >= 0) *to++ = *from++; } adjust_markers ((size1() + gap_size()) << 1, (pos + gap_size()) << 1, - gap_size(), data);#ifndef OLD_STDIO _gap_start = data+pos;#else if (gap_start_ptr == &gap_start_normal) gap_start_normal = data + pos;#endif __gap_end_pos = from - data;/* QUIT;*/}/* make sure that the gap in the current buffer is at least k characters wide */void edit_buffer::make_gap(buf_offset k){ register buf_char *p1, *p2, *lim; buf_char *old_data = data; int s1 = size1(); if (gap_size() >= k) return; /* Get more than just enough */ if (buf_size > 1000) k += 2000; else k += /*200;*/ 20; // for testing! p1 = (buf_char *) realloc (data, s1 + size2() + k); if (p1 == 0) abort(); /*memory_full ();*/ k -= gap_size(); /* Amount of increase. */ /* Record new location of text */ data = p1; /* Transfer the new free space from the end to the gap by shifting the second segment upward */ p2 = data + buf_size; p1 = p2 + k; lim = p2 - size2(); while (lim < p2) *--p1 = *--p2; /* Finish updating text location data */ __gap_end_pos += k;#ifndef OLD_STDIO _gap_start = data + s1;#else if (gap_start_ptr == &gap_start_normal) gap_start_normal = data + s1;#endif /* adjust markers */ adjust_markers (s1 << 1, (buf_size << 1) + 1, k, old_data); buf_size += k;}/* Add `amount' to the position of every marker in the current buffer whose current position is between `from' (exclusive) and `to' (inclusive). Also, any markers past the outside of that interval, in the direction of adjustment, are first moved back to the near end of the interval and then adjusted by `amount'. */void edit_buffer::adjust_markers(register mark_pointer low, register mark_pointer high, int amount, buf_char *old_data){ register struct edit_mark *m; register mark_pointer mpos; /* convert to mark_pointer */ amount <<= 1; if (_writer) _writer->disconnect_gap_from_file(this); for (m = mark_list(); m != NULL; m = m->chain) { mpos = m->_pos; if (amount > 0) { if (mpos > high && mpos < high + amount) mpos = high + amount; } else { if (mpos > low + amount && mpos <= low) mpos = low + amount; } if (mpos > low && mpos <= high) mpos += amount; m->_pos = mpos; } // Now adjust files edit_streambuf *file; for (file = files; file != NULL; file = file->next) { mpos = file->current() - old_data; if (amount > 0) { if (mpos > high && mpos < high + amount) mpos = high + amount; } else { if (mpos > low + amount && mpos <= low) mpos = low + amount; } if (mpos > low && mpos <= high) mpos += amount; char* new_pos = data + mpos; file->set_current(new_pos, file->is_reading()); }}#if 0stdio_ __off == index at start of buffer (need only be valid after seek ? ) __buf ==if read/read_delete/overwrite mode: __endp <= min(*gap_start_ptr, edit_string->end->ptr(buffer))if inserting: must have *gap_start_ptr == __bufp && *gap_start_ptr+gap == __endp file->edit_string->end->ptr(buffer) == *gap_start_ptr+endif write_mode: if before gap#endifint edit_streambuf::underflow(){ if (!(_mode & ios::in)) return EOF; struct edit_buffer *buffer = str->buffer; if (!is_reading()) { // Must switch from put to get mode. disconnect_gap_from_file(buffer); set_current(pptr(), 1); } buf_char *str_end = str->end->ptr(buffer); retry: if (gptr() < egptr()) { return *gptr(); } if ((buf_char*)gptr() == str_end) return EOF; if (str_end <= buffer->gap_start()) { setg(eback(), gptr(), str_end); goto retry; } if (gptr() < buffer->gap_start()) { setg(eback(), gptr(), buffer->gap_start()); goto retry; } if (gptr() == buffer->gap_start()) { disconnect_gap_from_file(buffer);// fp->__offset += fp->__bufp - fp->__buffer; setg(buffer->gap_end(), buffer->gap_end(), str_end); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -