diff options
-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) |