diff options
author | Robin Haberkorn <robin.haberkorn@googlemail.com> | 2014-11-14 02:43:23 +0100 |
---|---|---|
committer | Robin Haberkorn <robin.haberkorn@googlemail.com> | 2014-11-16 23:34:24 +0100 |
commit | 8be99d3863a305046f0133116782734e87be0822 (patch) | |
tree | 4954d200a10ca96123347dce9af089806b9a13f9 | |
parent | d9f04a78bf8679afc0c656f3440beb73b2dc8744 (diff) | |
download | sciteco-8be99d3863a305046f0133116782734e87be0822.tar.gz |
first working version of the one-view-per-buffer design
The user interface provides a Scintilla view abstraction and
every buffer is based on a view. All Q-Register strings use
a single dedicated view to save memory and initialization time
when using many string registers.
* this means we can finally implement a working lexer configuration
and it only has to be done once when the buffer is first added
to the ring. It is unnecessary to magically restore the lexer
styles upon rubout of EB (very hard to implement anyway). It
is also not necessary to rerun the lexer configuration macro
upon rubout which would be hard to reconcile with SciTECO's
basic design since every side-effect should be attached to a
character.
* this means that opening buffers is slightly slower now
because of the view initialization
* on the other hand, macros with many string q-reg operations
are faster now, since the document must no longer be changed
on the buffer's view and restored later on.
* also now we can make a difference between editing a document
in a view and changing the current view, which reduces UI calls
* the Document class has been retained as an abstraction about
Scintilla documents, used by QRegister Strings.
It had to be made virtual, so the view on which the document
is created can be specified by a virtual function.
There is no additional space overhead for Documents.
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/document.cpp | 71 | ||||
-rw-r--r-- | src/document.h | 53 | ||||
-rw-r--r-- | src/interface-gtk.cpp | 2 | ||||
-rw-r--r-- | src/interface-ncurses.cpp | 67 | ||||
-rw-r--r-- | src/interface-ncurses.h | 51 | ||||
-rw-r--r-- | src/interface.cpp | 114 | ||||
-rw-r--r-- | src/interface.h | 80 | ||||
-rw-r--r-- | src/main.cpp | 50 | ||||
-rw-r--r-- | src/parser.cpp | 26 | ||||
-rw-r--r-- | src/qregisters.cpp | 107 | ||||
-rw-r--r-- | src/qregisters.h | 25 | ||||
-rw-r--r-- | src/ring.cpp | 12 | ||||
-rw-r--r-- | src/ring.h | 20 | ||||
-rw-r--r-- | src/search.cpp | 14 | ||||
-rw-r--r-- | src/spawn.cpp | 4 | ||||
-rw-r--r-- | src/undo.cpp | 6 | ||||
-rw-r--r-- | src/undo.h | 23 |
18 files changed, 475 insertions, 252 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 60346bd..4833b6e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -33,7 +33,7 @@ libsciteco_base_a_SOURCES = main.cpp sciteco.h \ goto.cpp goto.h \ rbtree.cpp rbtree.h \ symbols.cpp symbols.h \ - interface.h + interface.cpp interface.h nodist_libsciteco_base_a_SOURCES = if INTERFACE_GTK diff --git a/src/document.cpp b/src/document.cpp index ff2ce2b..8ed5007 100644 --- a/src/document.cpp +++ b/src/document.cpp @@ -30,76 +30,43 @@ namespace SciTECO { -static inline void -set_representations(void) -{ - static const char *reps[] = { - "^@", "^A", "^B", "^C", "^D", "^E", "^F", "^G", - "^H", "TAB" /* ^I */, "LF" /* ^J */, "^K", "^L", "CR" /* ^M */, "^N", "^O", - "^P", "^Q", "^R", "^S", "^T", "^U", "^V", "^W", - "^X", "^Y", "^Z", "$" /* ^[ */, "^\\", "^]", "^^", "^_" - }; - - for (guint cc = 0; cc < G_N_ELEMENTS(reps); cc++) { - gchar buf[] = {(gchar)cc, '\0'}; - interface.ssm(SCI_SETREPRESENTATION, - (uptr_t)buf, (sptr_t)reps[cc]); - } -} - -class UndoSetRepresentations : public UndoToken { -public: - void - run(void) - { - set_representations(); - } -}; - void -Document::edit(void) +Document::edit(ViewCurrent *view) { - if (!is_initialized()) - doc = (SciDoc)interface.ssm(SCI_CREATEDOCUMENT); + maybe_create_document(); - interface.ssm(SCI_SETDOCPOINTER, 0, (sptr_t)doc); - interface.ssm(SCI_SETFIRSTVISIBLELINE, first_line); - interface.ssm(SCI_SETXOFFSET, xoffset); - interface.ssm(SCI_SETSEL, anchor, (sptr_t)dot); + view->ssm(SCI_SETDOCPOINTER, 0, (sptr_t)doc); + view->ssm(SCI_SETFIRSTVISIBLELINE, first_line); + view->ssm(SCI_SETXOFFSET, xoffset); + view->ssm(SCI_SETSEL, anchor, (sptr_t)dot); /* * Default TECO-style character representations. * They are reset on EVERY SETDOCPOINTER call by Scintilla. */ - set_representations(); + view->set_representations(); } void -Document::undo_edit(void) +Document::undo_edit(ViewCurrent *view) { - if (!is_initialized()) - doc = (SciDoc)interface.ssm(SCI_CREATEDOCUMENT); + maybe_create_document(); - /* - * see above: set TECO-style character representations - * NOTE: could be done with push_msg() but that requires - * making the entire mapping static constant - */ - undo.push(new UndoSetRepresentations()); + view->undo_set_representations(); - undo.push_msg(SCI_SETSEL, anchor, (sptr_t)dot); - undo.push_msg(SCI_SETXOFFSET, xoffset); - undo.push_msg(SCI_SETFIRSTVISIBLELINE, first_line); - undo.push_msg(SCI_SETDOCPOINTER, 0, (sptr_t)doc); + view->undo_ssm(SCI_SETSEL, anchor, (sptr_t)dot); + view->undo_ssm(SCI_SETXOFFSET, xoffset); + view->undo_ssm(SCI_SETFIRSTVISIBLELINE, first_line); + view->undo_ssm(SCI_SETDOCPOINTER, 0, (sptr_t)doc); } void -Document::update(void) +Document::update(ViewCurrent *view) { - anchor = interface.ssm(SCI_GETANCHOR); - dot = interface.ssm(SCI_GETCURRENTPOS); - first_line = interface.ssm(SCI_GETFIRSTVISIBLELINE); - xoffset = interface.ssm(SCI_GETXOFFSET); + anchor = view->ssm(SCI_GETANCHOR); + dot = view->ssm(SCI_GETCURRENTPOS); + first_line = view->ssm(SCI_GETFIRSTVISIBLELINE); + xoffset = view->ssm(SCI_GETXOFFSET); } /* diff --git a/src/document.h b/src/document.h index 81700b4..763db7a 100644 --- a/src/document.h +++ b/src/document.h @@ -36,7 +36,10 @@ class Document { typedef const void *SciDoc; SciDoc doc; - /* updated/restored only when required */ + /* + * The so called "parameters". + * Updated/restored only when required + */ gint anchor, dot; gint first_line, xoffset; @@ -47,8 +50,15 @@ public: } virtual ~Document() { - if (is_initialized()) - interface.ssm(SCI_RELEASEDOCUMENT, 0, (sptr_t)doc); + /* + * Cannot release document here, since we must + * do it on the same view that created it. + * We also cannot call get_create_document_view() + * since it is virtual. + * So we must demand that deriving classes call + * release_document() from their destructors. + */ + g_assert(doc == NULL); } inline bool @@ -57,10 +67,10 @@ public: return doc != NULL; } - void edit(void); - void undo_edit(void); + void edit(ViewCurrent *view); + void undo_edit(ViewCurrent *view); - void update(void); + void update(ViewCurrent *view); inline void update(const Document &from) { @@ -92,6 +102,37 @@ public: undo.push_var(doc); undo_reset(); } + +protected: + inline void + release_document(void) + { + if (is_initialized()) { + ViewCurrent *view = get_create_document_view(); + view->ssm(SCI_RELEASEDOCUMENT, 0, (sptr_t)doc); + doc = NULL; + } + } + +private: + /* + * Must be implemented by derived class. + * Documents must be released on the same view + * as they were created. + * Since we do not want to save this view + * per document, it must instead be returned by + * this method. + */ + virtual ViewCurrent *get_create_document_view(void) = 0; + + inline void + maybe_create_document(void) + { + if (!is_initialized()) { + ViewCurrent *view = get_create_document_view(); + doc = (SciDoc)view->ssm(SCI_CREATEDOCUMENT); + } + } }; } /* namespace SciTECO */ diff --git a/src/interface-gtk.cpp b/src/interface-gtk.cpp index 2b47019..b49a5fb 100644 --- a/src/interface-gtk.cpp +++ b/src/interface-gtk.cpp @@ -97,8 +97,6 @@ InterfaceGtk::main(int &argc, char **&argv) gtk_widget_grab_focus(cmdline_widget); - ssm(SCI_SETFOCUS, TRUE); - cmdline_update(""); } diff --git a/src/interface-ncurses.cpp b/src/interface-ncurses.cpp index a956fdf..bb88af1 100644 --- a/src/interface-ncurses.cpp +++ b/src/interface-ncurses.cpp @@ -56,6 +56,34 @@ static void scintilla_notify(Scintilla *sci, int idFrom, #define SCI_COLOR_ATTR(f, b) \ ((chtype)COLOR_PAIR(SCI_COLOR_PAIR(f, b))) +ViewNCurses::ViewNCurses() +{ + WINDOW *window; + + /* NOTE: Scintilla initializes color pairs */ + sci = scintilla_new(scintilla_notify); + window = get_window(); + + /* + * Window must have dimension before it can be + * positioned. + * Perhaps it's better to leave the window + * unitialized and set the position in + * InterfaceNCurses::show_view(). + */ + wresize(window, 1, 1); + /* Set up window position: never changes */ + mvwin(window, 1, 0); + + initialize(); +} + +ViewNCurses::~ViewNCurses() +{ + delwin(get_window()); + scintilla_delete(sci); +} + void InterfaceNCurses::main(int &argc, char **&argv) { @@ -69,19 +97,11 @@ InterfaceNCurses::main(int &argc, char **&argv) info_window = newwin(1, 0, 0, 0); info_current = g_strdup(PACKAGE_NAME); - /* NOTE: Scintilla initializes color pairs */ - sci = scintilla_new(scintilla_notify); - sci_window = scintilla_get_window(sci); - wresize(sci_window, LINES - 3, COLS); - mvwin(sci_window, 1, 0); - msg_window = newwin(1, 0, LINES - 2, 0); cmdline_window = newwin(0, 0, LINES - 1, 0); cmdline_current = NULL; - ssm(SCI_SETFOCUS, TRUE); - draw_info(); /* scintilla will be refreshed in event loop */ msg_clear(); @@ -140,7 +160,8 @@ InterfaceNCurses::resize_all_windows(void) getmaxyx(stdscr, lines, cols); wresize(info_window, 1, cols); - wresize(sci_window, lines - 3, cols); + wresize(current_view->get_window(), + lines - 3, cols); wresize(msg_window, 1, cols); mvwin(msg_window, lines - 2, 0); wresize(cmdline_window, 1, cols); @@ -195,6 +216,23 @@ InterfaceNCurses::msg_clear(void) } void +InterfaceNCurses::show_view(View *view) +{ + int lines, cols; /* screen dimensions */ + + /* We know that `view` is a ViewNCurses */ + current_view = (ViewNCurses *)view; + + /* + * screen size might have changed since + * this view's WINDOW was last active + */ + getmaxyx(stdscr, lines, cols); + wresize(current_view->get_window(), + lines - 3, cols); +} + +void InterfaceNCurses::draw_info(void) { if (isendwin()) /* batch mode */ @@ -343,8 +381,8 @@ InterfaceNCurses::popup_clear(void) redrawwin(info_window); wrefresh(info_window); - redrawwin(sci_window); - scintilla_refresh(sci); + redrawwin(current_view->get_window()); + current_view->refresh(); redrawwin(msg_window); wrefresh(msg_window); @@ -432,7 +470,7 @@ event_loop_iter() sigint_occurred = FALSE; - scintilla_refresh(interface.sci); + interface.current_view->refresh(); if (interface.popup.window) wrefresh(interface.popup.window); } @@ -441,7 +479,7 @@ void InterfaceNCurses::event_loop(void) { /* initial refresh: window might have been changed in batch mode */ - scintilla_refresh(sci); + current_view->refresh(); draw_info(); #ifdef EMSCRIPTEN @@ -465,9 +503,6 @@ InterfaceNCurses::~InterfaceNCurses() if (info_window) delwin(info_window); g_free(info_current); - /* also deletes curses window */ - if (sci) - scintilla_delete(sci); if (cmdline_window) delwin(cmdline_window); g_free(cmdline_current); diff --git a/src/interface-ncurses.h b/src/interface-ncurses.h index f1003de..647b1ef 100644 --- a/src/interface-ncurses.h +++ b/src/interface-ncurses.h @@ -31,19 +31,44 @@ namespace SciTECO { +typedef class ViewNCurses : public View { + Scintilla *sci; + +public: + ViewNCurses(); + ~ViewNCurses(); + + inline void + refresh(void) + { + scintilla_refresh(sci); + } + + inline WINDOW * + get_window(void) + { + return scintilla_get_window(sci); + } + + inline sptr_t + ssm(unsigned int iMessage, uptr_t wParam = 0, sptr_t lParam = 0) + { + return scintilla_send_message(sci, iMessage, wParam, lParam); + } +} ViewCurrent; + typedef class InterfaceNCurses : public Interface { SCREEN *screen; FILE *screen_tty; - Scintilla *sci; - WINDOW *info_window; gchar *info_current; - WINDOW *sci_window; WINDOW *msg_window; WINDOW *cmdline_window; gchar *cmdline_current; + ViewNCurses *current_view; + struct Popup { WINDOW *window; GSList *list; @@ -57,13 +82,12 @@ typedef class InterfaceNCurses : public Interface { public: InterfaceNCurses() : screen(NULL), screen_tty(NULL), - sci(NULL), info_window(NULL), info_current(NULL), - sci_window(NULL), msg_window(NULL), cmdline_window(NULL), - cmdline_current(NULL) {} + cmdline_current(NULL), + current_view(NULL) {} ~InterfaceNCurses(); void main(int &argc, char **&argv); @@ -71,10 +95,23 @@ public: void vmsg(MessageType type, const gchar *fmt, va_list ap); void msg_clear(void); + void show_view(View *view); + inline View * + get_current_view(void) + { + return current_view; + } + inline sptr_t ssm(unsigned int iMessage, uptr_t wParam = 0, sptr_t lParam = 0) { - return scintilla_send_message(sci, iMessage, wParam, lParam); + return current_view->ssm(iMessage, wParam, lParam); + } + inline void + undo_ssm(unsigned int iMessage, + uptr_t wParam = 0, sptr_t lParam = 0) + { + current_view->undo_ssm(iMessage, wParam, lParam); } void info_update(QRegister *reg); diff --git a/src/interface.cpp b/src/interface.cpp new file mode 100644 index 0000000..aecba4e --- /dev/null +++ b/src/interface.cpp @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2012-2014 Robin Haberkorn + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdarg.h> +#include <stdio.h> + +#include <glib.h> +#include <glib/gprintf.h> +#include <glib/gstdio.h> + +#include <Scintilla.h> +#include <SciLexer.h> + +#include "sciteco.h" +#include "interface.h" + +namespace SciTECO { + +void +View::set_representations(void) +{ + static const char *reps[] = { + "^@", "^A", "^B", "^C", "^D", "^E", "^F", "^G", + "^H", "TAB" /* ^I */, "LF" /* ^J */, "^K", "^L", "CR" /* ^M */, "^N", "^O", + "^P", "^Q", "^R", "^S", "^T", "^U", "^V", "^W", + "^X", "^Y", "^Z", "$" /* ^[ */, "^\\", "^]", "^^", "^_" + }; + + for (guint cc = 0; cc < G_N_ELEMENTS(reps); cc++) { + gchar buf[] = {(gchar)cc, '\0'}; + ssm(SCI_SETREPRESENTATION, (uptr_t)buf, (sptr_t)reps[cc]); + } +} + +void +View::initialize(void) +{ + ssm(SCI_SETFOCUS, TRUE); + + ssm(SCI_SETCARETSTYLE, CARETSTYLE_BLOCK); + ssm(SCI_SETCARETFORE, 0xFFFFFF); + + /* + * FIXME: Default styles should probably be set interface-based + * (system defaults) + */ + ssm(SCI_STYLESETFORE, STYLE_DEFAULT, 0xFFFFFF); + ssm(SCI_STYLESETBACK, STYLE_DEFAULT, 0x000000); + ssm(SCI_STYLESETFONT, STYLE_DEFAULT, (sptr_t)"Courier"); + ssm(SCI_STYLECLEARALL); + + ssm(SCI_STYLESETBACK, STYLE_LINENUMBER, 0x000000); +} + +void +Interface::UndoTokenShowView::run(void) +{ + /* + * Implementing this here allows us to reference + * `interface` + */ + interface.show_view(view); +} + +void +Interface::stdio_vmsg(MessageType type, const gchar *fmt, va_list ap) +{ + gchar buf[255]; + + g_vsnprintf(buf, sizeof(buf), fmt, ap); + + switch (type) { + case MSG_USER: + g_printf("%s\n", buf); + break; + case MSG_INFO: + g_printf("Info: %s\n", buf); + break; + case MSG_WARNING: + g_fprintf(stderr, "Warning: %s\n", buf); + break; + case MSG_ERROR: + g_fprintf(stderr, "Error: %s\n", buf); + break; + } +} + +void +Interface::process_notify(SCNotification *notify) +{ +#ifdef DEBUG + g_printf("SCINTILLA NOTIFY: code=%d\n", notify->nmhdr.code); +#endif +} + +} /* namespace SciTECO */ diff --git a/src/interface.h b/src/interface.h index e2d24de..f7bec85 100644 --- a/src/interface.h +++ b/src/interface.h @@ -34,6 +34,65 @@ class QRegister; class Buffer; extern sig_atomic_t sigint_occurred; +class View { + class UndoTokenMessage : public UndoToken { + View *view; + + unsigned int iMessage; + uptr_t wParam; + sptr_t lParam; + + public: + UndoTokenMessage(View *_view, unsigned int _iMessage, + uptr_t _wParam = 0, sptr_t _lParam = 0) + : UndoToken(), view(_view), + iMessage(_iMessage), + wParam(_wParam), lParam(_lParam) {} + + void + run(void) + { + view->ssm(iMessage, wParam, lParam); + } + }; + + class UndoTokenSetRepresentations : public UndoToken { + View *view; + + public: + UndoTokenSetRepresentations(View *_view) + : view(_view) {} + + void + run(void) + { + view->set_representations(); + } + }; + +public: + virtual ~View() {} + + virtual sptr_t ssm(unsigned int iMessage, + uptr_t wParam = 0, sptr_t lParam = 0) = 0; + inline void + undo_ssm(unsigned int iMessage, + uptr_t wParam = 0, sptr_t lParam = 0) + { + undo.push(new UndoTokenMessage(this, iMessage, wParam, lParam)); + } + + void set_representations(void); + inline void + undo_set_representations(void) + { + undo.push(new UndoTokenSetRepresentations(this)); + } + +protected: + void initialize(void); +}; + /* * Base class for all user interfaces - used mereley as a class interface. * The actual instance of the interface has the platform-specific type @@ -43,8 +102,19 @@ extern sig_atomic_t sigint_occurred; * There's only one Interface* instance in the system. */ class Interface { + class UndoTokenShowView : public UndoToken { + View *view; + + public: + UndoTokenShowView(View *_view) + : view(_view) {} + + void run(void); + }; + template <class Type> class UndoTokenInfoUpdate : public UndoToken { + /* FIXME: can be implement this in interface.cpp - avoid saving iface */ Interface *iface; Type *obj; @@ -86,8 +156,18 @@ public: } virtual void msg_clear(void) {} + virtual void show_view(View *view) = 0; + inline void + undo_show_view(View *view) + { + undo.push(new UndoTokenShowView(view)); + } + virtual View *get_current_view(void) = 0; + virtual sptr_t ssm(unsigned int iMessage, uptr_t wParam = 0, sptr_t lParam = 0) = 0; + virtual void undo_ssm(unsigned int iMessage, + uptr_t wParam = 0, sptr_t lParam = 0) = 0; virtual void info_update(QRegister *reg) = 0; virtual void info_update(Buffer *buffer) = 0; diff --git a/src/main.cpp b/src/main.cpp index ed46747..a713964 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -19,7 +19,6 @@ #include "config.h" #endif -#include <stdarg.h> #include <stdio.h> #include <string.h> #include <stdlib.h> @@ -30,9 +29,6 @@ #include <glib/gprintf.h> #include <glib/gstdio.h> -#include <Scintilla.h> -#include <SciLexer.h> - #include "sciteco.h" #include "cmdline.h" #include "interface.h" @@ -88,37 +84,6 @@ static void sigint_handler(int signal); } void -Interface::stdio_vmsg(MessageType type, const gchar *fmt, va_list ap) -{ - gchar buf[255]; - - g_vsnprintf(buf, sizeof(buf), fmt, ap); - - switch (type) { - case MSG_USER: - g_printf("%s\n", buf); - break; - case MSG_INFO: - g_printf("Info: %s\n", buf); - break; - case MSG_WARNING: - g_fprintf(stderr, "Warning: %s\n", buf); - break; - case MSG_ERROR: - g_fprintf(stderr, "Error: %s\n", buf); - break; - } -} - -void -Interface::process_notify(SCNotification *notify) -{ -#ifdef DEBUG - g_printf("SCINTILLA NOTIFY: code=%d\n", notify->nmhdr.code); -#endif -} - -void String::get_coord(const gchar *str, gint pos, gint &line, gint &column) { @@ -321,19 +286,12 @@ main(int argc, char **argv) interface.main(argc, argv); /* remaining arguments are arguments to the munged file */ - interface.ssm(SCI_SETCARETSTYLE, CARETSTYLE_BLOCK); - interface.ssm(SCI_SETCARETFORE, 0xFFFFFF); - /* - * FIXME: Default styles should probably be set interface-based - * (system defaults) + * QRegister view must be initialized only now + * (after Curses initialization) */ - interface.ssm(SCI_STYLESETFORE, STYLE_DEFAULT, 0xFFFFFF); - interface.ssm(SCI_STYLESETBACK, STYLE_DEFAULT, 0x000000); - interface.ssm(SCI_STYLESETFONT, STYLE_DEFAULT, (sptr_t)"Courier"); - interface.ssm(SCI_STYLECLEARALL); - - interface.ssm(SCI_STYLESETBACK, STYLE_LINENUMBER, 0x000000); + QRegisters::view = new ViewCurrent(); + // FIXME: view should be deallocated */ /* search string and status register */ QRegisters::globals.insert("_"); diff --git a/src/parser.cpp b/src/parser.cpp index f839840..61d43cc 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -512,7 +512,7 @@ StateStart::insert_integer(tecoInt v) ring.dirtify(); if (current_doc_must_undo()) - undo.push_msg(SCI_UNDO); + interface.undo_ssm(SCI_UNDO); } tecoInt @@ -554,7 +554,7 @@ StateStart::move_chars(tecoInt n) interface.ssm(SCI_GOTOPOS, pos + n); if (current_doc_must_undo()) - undo.push_msg(SCI_GOTOPOS, pos); + interface.undo_ssm(SCI_GOTOPOS, pos); return SUCCESS; } @@ -570,7 +570,7 @@ StateStart::move_lines(tecoInt n) interface.ssm(SCI_GOTOLINE, line); if (current_doc_must_undo()) - undo.push_msg(SCI_GOTOPOS, pos); + interface.undo_ssm(SCI_GOTOPOS, pos); return SUCCESS; } @@ -619,9 +619,9 @@ StateStart::delete_words(tecoInt n) return FAILURE; } - undo.push_msg(SCI_GOTOPOS, pos); + interface.undo_ssm(SCI_GOTOPOS, pos); if (current_doc_must_undo()) - undo.push_msg(SCI_UNDO); + interface.undo_ssm(SCI_UNDO); ring.dirtify(); return SUCCESS; @@ -1008,7 +1008,7 @@ StateStart::custom(gchar chr) interface.ssm(SCI_ENDUNDOACTION); /* must always support undo on global register */ - undo.push_msg(SCI_UNDO); + interface.undo_ssm(SCI_UNDO); break; case '}': @@ -1063,8 +1063,8 @@ StateStart::custom(gchar chr) v = expressions.pop_num_calc(1, 0); if (Validate::pos(v)) { if (current_doc_must_undo()) - undo.push_msg(SCI_GOTOPOS, - interface.ssm(SCI_GETCURRENTPOS)); + interface.undo_ssm(SCI_GOTOPOS, + interface.ssm(SCI_GETCURRENTPOS)); interface.ssm(SCI_GOTOPOS, v); if (eval_colon()) @@ -1202,7 +1202,7 @@ StateStart::custom(gchar chr) } if (v < 0) { if (current_doc_must_undo()) - undo.push_msg(SCI_GOTOPOS, pos); + interface.undo_ssm(SCI_GOTOPOS, pos); if (eval_colon()) expressions.push(SUCCESS); } else { @@ -1366,8 +1366,8 @@ StateStart::custom(gchar chr) break; if (current_doc_must_undo()) { - undo.push_msg(SCI_GOTOPOS, interface.ssm(SCI_GETCURRENTPOS)); - undo.push_msg(SCI_UNDO); + interface.undo_ssm(SCI_GOTOPOS, interface.ssm(SCI_GETCURRENTPOS)); + interface.undo_ssm(SCI_UNDO); } interface.ssm(SCI_BEGINUNDOACTION); @@ -2077,7 +2077,7 @@ StateInsert::initial(void) ring.dirtify(); if (current_doc_must_undo()) - undo.push_msg(SCI_UNDO); + interface.undo_ssm(SCI_UNDO); } void @@ -2091,7 +2091,7 @@ StateInsert::process(const gchar *str, gint new_chars) ring.dirtify(); if (current_doc_must_undo()) - undo.push_msg(SCI_UNDO); + interface.undo_ssm(SCI_UNDO); } State * diff --git a/src/qregisters.cpp b/src/qregisters.cpp index fa95c80..981db88 100644 --- a/src/qregisters.cpp +++ b/src/qregisters.cpp @@ -59,6 +59,7 @@ namespace States { namespace QRegisters { QRegisterTable *locals = NULL; QRegister *current = NULL; + ViewCurrent *view = NULL; void undo_edit(void) @@ -73,26 +74,19 @@ namespace QRegisters { static QRegister *register_argument = NULL; -static inline void -current_edit(void) -{ - if (ring.current) - ring.current->edit(); - else if (QRegisters::current) - QRegisters::current->edit(); -} - void QRegisterData::set_string(const gchar *str) { - edit(); + string.edit(QRegisters::view); string.reset(); - interface.ssm(SCI_BEGINUNDOACTION); - interface.ssm(SCI_SETTEXT, 0, (sptr_t)(str ? : "")); - interface.ssm(SCI_ENDUNDOACTION); + QRegisters::view->ssm(SCI_BEGINUNDOACTION); + QRegisters::view->ssm(SCI_SETTEXT, 0, + (sptr_t)(str ? : "")); + QRegisters::view->ssm(SCI_ENDUNDOACTION); - current_edit(); + if (QRegisters::current) + QRegisters::current->string.edit(QRegisters::view); } void @@ -104,30 +98,34 @@ QRegisterData::undo_set_string(void) if (!must_undo) return; - if (ring.current) - ring.current->undo_edit(); - else if (QRegisters::current) - QRegisters::current->undo_edit(); + if (QRegisters::current) + QRegisters::current->string.undo_edit(QRegisters::view); string.undo_reset(); - undo.push_msg(SCI_UNDO); + QRegisters::view->undo_ssm(SCI_UNDO); - undo_edit(); + string.undo_edit(QRegisters::view); } void QRegisterData::append_string(const gchar *str) { - if (!str) + /* + * NOTE: Will not create undo action + * if string is empty + */ + if (!str || !*str) return; - edit(); + string.edit(QRegisters::view); - interface.ssm(SCI_BEGINUNDOACTION); - interface.ssm(SCI_APPENDTEXT, strlen(str), (sptr_t)str); - interface.ssm(SCI_ENDUNDOACTION); + QRegisters::view->ssm(SCI_BEGINUNDOACTION); + QRegisters::view->ssm(SCI_APPENDTEXT, + strlen(str), (sptr_t)str); + QRegisters::view->ssm(SCI_ENDUNDOACTION); - current_edit(); + if (QRegisters::current) + QRegisters::current->string.edit(QRegisters::view); } gchar * @@ -140,13 +138,14 @@ QRegisterData::get_string(void) return g_strdup(""); current_doc_update(); - edit(); + string.edit(QRegisters::view); - size = interface.ssm(SCI_GETLENGTH) + 1; + size = QRegisters::view->ssm(SCI_GETLENGTH) + 1; str = (gchar *)g_malloc(size); - interface.ssm(SCI_GETTEXT, size, (sptr_t)str); + QRegisters::view->ssm(SCI_GETTEXT, size, (sptr_t)str); - current_edit(); + if (QRegisters::current) + QRegisters::current->string.edit(QRegisters::view); return str; } @@ -154,20 +153,26 @@ QRegisterData::get_string(void) void QRegisterData::edit(void) { - string.edit(); + string.edit(QRegisters::view); + interface.show_view(QRegisters::view); } void QRegisterData::undo_edit(void) { - if (must_undo) - string.undo_edit(); + if (!must_undo) + return; + + string.undo_edit(QRegisters::view); + interface.undo_show_view(QRegisters::view); } void QRegister::edit(void) { - string.edit(); + /* NOTE: could call QRegisterData::edit() */ + string.edit(QRegisters::view); + interface.show_view(QRegisters::view); interface.info_update(this); } @@ -178,7 +183,9 @@ QRegister::undo_edit(void) return; interface.undo_info_update(this); - string.undo_edit(); + /* NOTE: could call QRegisterData::undo_edit() */ + string.undo_edit(QRegisters::view); + interface.undo_show_view(QRegisters::view); } void @@ -213,17 +220,18 @@ QRegister::load(const gchar *filename) if (!g_file_get_contents(filename, &contents, &size, &gerror)) throw GlibError(gerror); - edit(); + string.edit(QRegisters::view); string.reset(); - interface.ssm(SCI_BEGINUNDOACTION); - interface.ssm(SCI_CLEARALL); - interface.ssm(SCI_APPENDTEXT, size, (sptr_t)contents); - interface.ssm(SCI_ENDUNDOACTION); + QRegisters::view->ssm(SCI_BEGINUNDOACTION); + QRegisters::view->ssm(SCI_CLEARALL); + QRegisters::view->ssm(SCI_APPENDTEXT, size, (sptr_t)contents); + QRegisters::view->ssm(SCI_ENDUNDOACTION); g_free(contents); - current_edit(); + if (QRegisters::current) + QRegisters::current->string.edit(QRegisters::view); } tecoInt @@ -245,23 +253,20 @@ QRegisterBufferInfo::get_integer(void) gchar * QRegisterBufferInfo::get_string(void) { - gchar *filename = ring.current ? ring.current->filename : NULL; - - return g_strdup(filename ? : ""); + return g_strdup(ring.current ? ring.current->filename : ""); } void QRegisterBufferInfo::edit(void) { - gchar *filename = ring.current ? ring.current->filename : NULL; - QRegister::edit(); - interface.ssm(SCI_BEGINUNDOACTION); - interface.ssm(SCI_SETTEXT, 0, (sptr_t)(filename ? : "")); - interface.ssm(SCI_ENDUNDOACTION); + QRegisters::view->ssm(SCI_BEGINUNDOACTION); + QRegisters::view->ssm(SCI_SETTEXT, 0, + (sptr_t)(ring.current ? ring.current->filename : "")); + QRegisters::view->ssm(SCI_ENDUNDOACTION); - undo.push_msg(SCI_UNDO); + QRegisters::view->undo_ssm(SCI_UNDO); } QRegisterTable::QRegisterTable(bool _undo) : RBTree(), must_undo(_undo) @@ -648,7 +653,7 @@ StateGetQRegString::got_register(QRegister ®) interface.ssm(SCI_ENDUNDOACTION); ring.dirtify(); - undo.push_msg(SCI_UNDO); + interface.undo_ssm(SCI_UNDO); } g_free(str); diff --git a/src/qregisters.h b/src/qregisters.h index 556ce7b..e0e8520 100644 --- a/src/qregisters.h +++ b/src/qregisters.h @@ -34,6 +34,11 @@ namespace SciTECO { +namespace QRegisters { + /* constructed after Interface.main() in main() */ + extern ViewCurrent *view; +} + /* * Classes */ @@ -41,7 +46,21 @@ namespace SciTECO { class QRegisterData { protected: tecoInt integer; - Document string; + + class QRegisterString : public Document { + public: + ~QRegisterString() + { + release_document(); + } + + private: + ViewCurrent * + get_create_document_view(void) + { + return QRegisters::view; + } + } string; public: /* @@ -70,9 +89,9 @@ public: } inline void - update_string(void) + update_string() { - string.update(); + string.update(QRegisters::view); } virtual void set_string(const gchar *str); diff --git a/src/ring.cpp b/src/ring.cpp index f7dc3bf..25a46ce 100644 --- a/src/ring.cpp +++ b/src/ring.cpp @@ -137,12 +137,10 @@ Buffer::load(const gchar *filename) if (!g_file_get_contents(filename, &contents, &size, &gerror)) throw GlibError(gerror); - edit(); - - interface.ssm(SCI_BEGINUNDOACTION); - interface.ssm(SCI_CLEARALL); - interface.ssm(SCI_APPENDTEXT, size, (sptr_t)contents); - interface.ssm(SCI_ENDUNDOACTION); + ssm(SCI_BEGINUNDOACTION); + ssm(SCI_CLEARALL); + ssm(SCI_APPENDTEXT, size, (sptr_t)contents); + ssm(SCI_ENDUNDOACTION); g_free(contents); @@ -263,6 +261,7 @@ Ring::edit(const gchar *filename) undo_close(); if (filename && g_file_test(filename, G_FILE_TEST_IS_REGULAR)) { + buffer->edit(); buffer->load(filename); interface.msg(Interface::MSG_INFO, @@ -489,7 +488,6 @@ Ring::close(void) { Buffer *buffer = current; - buffer->update(); close(buffer); current = buffer->next() ? : buffer->prev(); /* transfer responsibility to UndoToken object */ @@ -30,7 +30,6 @@ #include "sciteco.h" #include "interface.h" #include "undo.h" -#include "document.h" #include "qregisters.h" #include "parser.h" @@ -56,7 +55,7 @@ gchar *get_absolute_path(const gchar *path); * Classes */ -class Buffer : public Document { +class Buffer : private ViewCurrent { class UndoTokenClose : public UndoToken { Buffer *buffer; @@ -74,8 +73,12 @@ public: gint savepoint_id; bool dirty; - Buffer() : Document(), - filename(NULL), savepoint_id(0), dirty(false) {} + Buffer() : ViewCurrent(), + filename(NULL), savepoint_id(0), dirty(false) + { + set_representations(); + } + ~Buffer() { g_free(filename); @@ -106,14 +109,14 @@ public: inline void edit(void) { - Document::edit(); + interface.show_view(this); interface.info_update(this); } inline void undo_edit(void) { interface.undo_info_update(this); - Document::undo_edit(); + interface.undo_show_view(this); } void load(const gchar *filename); @@ -198,7 +201,6 @@ public: inline void undo_edit(void) { - current->update(); undo.push_var(QRegisters::current); undo.push_var(current)->undo_edit(); } @@ -243,9 +245,7 @@ namespace States { static inline void current_doc_update(void) { - if (ring.current) - ring.current->update(); - else if (QRegisters::current) + if (QRegisters::current) QRegisters::current->update_string(); } diff --git a/src/search.cpp b/src/search.cpp index bd0802e..16706ee 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -421,9 +421,9 @@ StateSearch::process(const gchar *str, gint new_chars) gint count = parameters.count; if (current_doc_must_undo()) - undo.push_msg(SCI_SETSEL, - interface.ssm(SCI_GETANCHOR), - interface.ssm(SCI_GETCURRENTPOS)); + interface.undo_ssm(SCI_SETSEL, + interface.ssm(SCI_GETANCHOR), + interface.ssm(SCI_GETCURRENTPOS)); search_reg->undo_set_integer(); search_reg->set_integer(FAILURE); @@ -510,7 +510,7 @@ StateSearch::done(const gchar *str) /* workaround: preserve selection (also on rubout) */ gint anchor = interface.ssm(SCI_GETANCHOR); if (current_doc_must_undo()) - undo.push_msg(SCI_SETANCHOR, anchor); + interface.undo_ssm(SCI_SETANCHOR, anchor); search_reg->undo_set_string(); search_reg->set_string(str); @@ -661,7 +661,7 @@ StateSearchKill::done(const gchar *str) gint anchor = interface.ssm(SCI_GETANCHOR); if (current_doc_must_undo()) - undo.push_msg(SCI_GOTOPOS, dot); + interface.undo_ssm(SCI_GOTOPOS, dot); interface.ssm(SCI_GOTOPOS, anchor); interface.ssm(SCI_DELETERANGE, @@ -674,7 +674,7 @@ StateSearchKill::done(const gchar *str) ring.dirtify(); if (current_doc_must_undo()) - undo.push_msg(SCI_UNDO); + interface.undo_ssm(SCI_UNDO); return &States::start; } @@ -708,7 +708,7 @@ StateSearchDelete::done(const gchar *str) ring.dirtify(); if (current_doc_must_undo()) - undo.push_msg(SCI_UNDO); + interface.undo_ssm(SCI_UNDO); } return &States::start; diff --git a/src/spawn.cpp b/src/spawn.cpp index 9e8f620..e346950 100644 --- a/src/spawn.cpp +++ b/src/spawn.cpp @@ -316,7 +316,7 @@ StateExecuteCommand::done(const gchar *str) if (!register_argument) { if (current_doc_must_undo()) - undo.push_msg(SCI_GOTOPOS, interface.ssm(SCI_GETCURRENTPOS)); + interface.undo_ssm(SCI_GOTOPOS, interface.ssm(SCI_GETCURRENTPOS)); interface.ssm(SCI_GOTOPOS, ctx.to); } @@ -331,7 +331,7 @@ StateExecuteCommand::done(const gchar *str) (ctx.from != ctx.to || ctx.text_added)) { /* undo action is only effective if it changed anything */ if (current_doc_must_undo()) - undo.push_msg(SCI_UNDO); + interface.undo_ssm(SCI_UNDO); interface.ssm(SCI_SCROLLCARET); ring.dirtify(); } diff --git a/src/undo.cpp b/src/undo.cpp index 55df610..d123a7c 100644 --- a/src/undo.cpp +++ b/src/undo.cpp @@ -39,12 +39,6 @@ namespace SciTECO { UndoStack undo; void -UndoTokenMessage::run(void) -{ - interface.ssm(iMessage, wParam, lParam); -} - -void UndoStack::push(UndoToken *token) { if (enabled) { @@ -23,8 +23,6 @@ #include <glib.h> #include <glib/gprintf.h> -#include <Scintilla.h> - #ifdef DEBUG #include "parser.h" #endif @@ -42,20 +40,6 @@ public: virtual void run() = 0; }; -class UndoTokenMessage : public UndoToken { - unsigned int iMessage; - uptr_t wParam; - sptr_t lParam; - -public: - UndoTokenMessage(unsigned int _iMessage, - uptr_t _wParam = 0, sptr_t _lParam = 0) - : UndoToken(), iMessage(_iMessage), - wParam(_wParam), lParam(_lParam) {} - - void run(void); -}; - template <typename Type> class UndoTokenVariable : public UndoToken { Type *ptr; @@ -140,13 +124,6 @@ public: void push(UndoToken *token); - inline void - push_msg(unsigned int iMessage, - uptr_t wParam = 0, sptr_t lParam = 0) - { - push(new UndoTokenMessage(iMessage, wParam, lParam)); - } - template <typename Type> inline Type & push_var(Type &variable, Type value) |