From 9e27520ab16f28136e9cd5c9097d9ff48336ccdb Mon Sep 17 00:00:00 2001
From: Michael Ochmann <miko007@me.com>
Date: Mon, 6 Mar 2017 20:03:00 +0100
Subject: [PATCH] added standalone modes

---
 main.cpp             | 14 ++++---
 src/Editor.cpp       | 96 +++++---------------------------------------
 src/Editor.hpp       | 11 ++---
 src/modes/Insert.cpp | 94 +++++++++++++++++++++++++++++++++++++++++++
 src/modes/Insert.hpp | 18 +++++++++
 src/modes/Mode.cpp   |  9 +++++
 src/modes/Mode.hpp   | 22 ++++++++++
 7 files changed, 167 insertions(+), 97 deletions(-)
 create mode 100644 src/modes/Insert.cpp
 create mode 100644 src/modes/Insert.hpp
 create mode 100644 src/modes/Mode.cpp
 create mode 100644 src/modes/Mode.hpp

diff --git a/main.cpp b/main.cpp
index 71a702f..623e8a1 100644
--- a/main.cpp
+++ b/main.cpp
@@ -3,20 +3,22 @@
 #include <Editor.hpp>
 
 int main(int argc, char* argv[]) {
-	groove::Editor editor;
+	std::unique_ptr<groove::Editor> editor;
+
 	if (argc > 1)
-		editor = groove::Editor(argv[1]);
+		editor = std::make_unique<groove::Editor>(argv[1]);
 	else
-		editor = groove::Editor();
+		editor = std::make_unique<groove::Editor>();
+
 	groove::ncurses::ncurses curses;
 	curses.init();
 	curses.flush();
 
-	while(editor.mode() != groove::Mode::QUIT)
+	while(editor->mode() != groove::Mode::QUIT)
 	{
-		editor.render();
+		editor->render();
 		int input = getch();                // Blocking until input
-		editor.input(input);
+		editor->input(input);
 	}
 
 	curses.quit();
diff --git a/src/Editor.cpp b/src/Editor.cpp
index a76652f..c0ce8b2 100644
--- a/src/Editor.cpp
+++ b/src/Editor.cpp
@@ -6,9 +6,10 @@
 
 namespace groove {
 
-	Editor::Editor(std::string filename) : x(0), y(0), buffer(std::make_unique<Buffer>()),
-			mode_(Mode::EDIT), filename(filename), offset(0) {
-
+	Editor::Editor(std::string filename) : x(0), y(0),
+	 		buffer(std::make_unique<Buffer>()), mode_(Mode::EDIT),
+			filename(filename), offset(0) {
+		this->modes.emplace(Mode::INSERT, std::make_unique<modes::Insert>(*this));
 		if (!this->load()) {
 			std::cerr << "Could not open file: '" << this->filename << "', creating it on save.\n";
 			this->buffer->insert("");
@@ -16,6 +17,11 @@ namespace groove {
 	}
 
 	bool Editor::load() {
+		if (this->filename == "") {
+			this->filename = "unbenannt";
+
+			return false;
+		}
 		std::ifstream file(this->filename.c_str());
 		if(file.is_open()) {
 			while(!file.eof()) {
@@ -93,89 +99,7 @@ namespace groove {
 				}
 				break;
 			case Mode::INSERT:
-				switch (car) {
-					case 27:
-						this->mode_ = Mode::EDIT;
-						break;
-					case KEY_ENTER:
-					case 10:
-						{
-							std::string appendix;
-							appendix = "";
-							if (this->buffer->at(this->y).size() > this->x) {
-								appendix = this->buffer->at(this->y).substr(this->x, this->buffer->at(this->y).size());
-								this->buffer->at(this->y) = this->buffer->at(this->y).substr(0, this->x);
-							}
-							this->buffer->insert(this->y);
-							this->y++;
-							this->buffer->linebuffer().at(this->y) += appendix;
-							this->x = 0;
-							this->scrollDown();
-						}
-						break;
-					case KEY_BACKSPACE:
-						if (this->x - 1 >= 0) {
-							this->x--;
-							this->buffer->remove(this->y, this->x);
-						}
-						else {
-							if (this->buffer->at(this->y).size() > 0 && this->y > 0) {
-								int oldLength = static_cast<int>(this->buffer->at(this->y - 1).size());
-								this->buffer->at(this->y - 1) += this->buffer->at(this->y);
-								this->buffer->remove(this->y);
-								this->y--;
-								this->x = oldLength;
-							}
-							else {
-								if (this->y - 1 >= 0) {
-									this->buffer->remove(this->y);
-									this->y--;
-									this->x = static_cast<int>(this->buffer->at(this->y).length());
-								}
-							}
-						}
-						scrollUp();
-						break;
-					case KEY_DC:
-						if (this->buffer->at(this->y).length() > this->x)
-							this->buffer->deleteChar(this->y, this->x);
-						else {
-							if (this->buffer->at(this->y).empty() && this->buffer->linebuffer().size() - 1 > this->y)
-								this->buffer->remove(this->y);
-							else if (this->buffer->linebuffer().size() - 1 > this->y) {
-								this->buffer->at(this->y) += this->buffer->at(this->y + 1);
-								this->buffer->remove(this->y + 1);
-							}
-						}
-						break;
-					case KEY_BTAB:
-					case KEY_CTAB:
-					case KEY_STAB:
-					case KEY_CATAB:
-					case 9:
-						this->buffer->at(this->y).insert(this->x, 4, ' ');
-						this->x += 4;
-						break;
-					default:
-						{
-							switch (car) {
-								case '{':
-								case '[':
-									this->buffer->at(this->y).insert(this->x, 1, car + 2);
-									break;
-								case '(':
-									this->buffer->at(this->y).insert(this->x, 1, car + 1);
-									break;
-							}
-							std::ofstream log("log");
-							log << car << std::endl;
-							this->buffer->at(this->y).insert(this->x, 1, char(car));
-							if (this->lastChar != 195 && this->lastChar != 182)
-								this->x++;
-							this->lastChar = char(car);
-						}
-						break;
-				}
+				this->modes.at(Mode::INSERT)->input(car);
 				break;
 			case Mode::QUIT:
 				break;
diff --git a/src/Editor.hpp b/src/Editor.hpp
index 7c7cbff..fbe1c95 100644
--- a/src/Editor.hpp
+++ b/src/Editor.hpp
@@ -3,6 +3,8 @@
 #include <memory>
 #include <Buffer.hpp>
 #include <ncurses/ncurses.hpp>
+#include <modes/Insert.hpp>
+#include <unordered_map>
 
 namespace groove {
 
@@ -14,6 +16,8 @@ namespace groove {
 	};
 
 	class Editor {
+		friend class modes::Mode;
+		friend class modes::Insert;
 	private:
 		int x, y;
 		int offset;
@@ -22,6 +26,7 @@ namespace groove {
 		Mode mode_;
 		std::string clipboard = "";
 		std::string filename;
+		std::unordered_map<Mode, std::unique_ptr<modes::Mode>> modes;
 
 		bool load();
 		bool save();
@@ -67,11 +72,7 @@ namespace groove {
 			this->scrollDown();
 		}
 	public:
-		Editor() : x(0), y(0), buffer(std::make_unique<Buffer>()), mode_(Mode::EDIT), filename("unbenannt"),
-				offset(0) {
-			this->buffer->insert("");
-		}
-		Editor(std::string file);
+		Editor(std::string file = "ubenannt");
 		Mode mode() {
 			return this->mode_;
 		}
diff --git a/src/modes/Insert.cpp b/src/modes/Insert.cpp
new file mode 100644
index 0000000..a278330
--- /dev/null
+++ b/src/modes/Insert.cpp
@@ -0,0 +1,94 @@
+#include <modes/Insert.hpp>
+#include <Editor.hpp>
+#include <iostream>
+
+namespace groove {
+	namespace modes {
+		
+		void Insert::input(int c) {
+			switch (c) {
+				case 27:
+					this->editor.mode_ = groove::Mode::EDIT;
+					this->editor.x = 0;
+					this->editor.y = 0;
+					break;
+				case KEY_ENTER:
+				case 10:
+				{
+					std::string appendix;
+					appendix = "";
+					if (this->editor.buffer->at(this->editor.y).size() > this->editor.x) {
+						appendix = this->editor.buffer->at(this->editor.y).substr(this->editor.x, this->editor.buffer->at(this->editor.y).size());
+						this->editor.buffer->at(this->editor.y) = this->editor.buffer->at(this->editor.y).substr(0, this->editor.x);
+					}
+					this->editor.buffer->insert(this->editor.y);
+					this->editor.y++;
+					this->editor.buffer->linebuffer().at(this->editor.y) += appendix;
+					this->editor.x = 0;
+					this->editor.scrollDown();
+				}
+					break;
+				case KEY_BACKSPACE:
+					if (this->editor.x - 1 >= 0) {
+						this->editor.x--;
+						this->editor.buffer->remove(this->editor.y, this->editor.x);
+					}
+					else {
+						if (this->editor.buffer->at(this->editor.y).size() > 0 && this->editor.y > 0) {
+							int oldLength = static_cast<int>(this->editor.buffer->at(this->editor.y - 1).size());
+							this->editor.buffer->at(this->editor.y - 1) += this->editor.buffer->at(this->editor.y);
+							this->editor.buffer->remove(this->editor.y);
+							this->editor.y--;
+							this->editor.x = oldLength;
+						}
+						else {
+							if (this->editor.y - 1 >= 0) {
+								this->editor.buffer->remove(this->editor.y);
+								this->editor.y--;
+								this->editor.x = static_cast<int>(this->editor.buffer->at(this->editor.y).length());
+							}
+						}
+					}
+					this->editor.scrollUp();
+					break;
+				case KEY_DC:
+					if (this->editor.buffer->at(this->editor.y).length() > this->editor.x)
+						this->editor.buffer->deleteChar(this->editor.y, this->editor.x);
+					else {
+						if (this->editor.buffer->at(this->editor.y).empty() && this->editor.buffer->linebuffer().size() - 1 > this->editor.y)
+							this->editor.buffer->remove(this->editor.y);
+						else if (this->editor.buffer->linebuffer().size() - 1 > this->editor.y) {
+							this->editor.buffer->at(this->editor.y) += this->editor.buffer->at(this->editor.y + 1);
+							this->editor.buffer->remove(this->editor.y + 1);
+						}
+					}
+					break;
+				case KEY_BTAB:
+				case KEY_CTAB:
+				case KEY_STAB:
+				case KEY_CATAB:
+				case 9:
+					this->editor.buffer->at(this->editor.y).insert(this->editor.x, 4, ' ');
+					this->editor.x += 4;
+					break;
+				default:
+				{
+					switch (c) {
+						case '{':
+						case '[':
+							this->editor.buffer->at(this->editor.y).insert(this->editor.x, 1, c + 2);
+							break;
+						case '(':
+							this->editor.buffer->at(this->editor.y).insert(this->editor.x, 1, c + 1);
+							break;
+					}
+					this->editor.buffer->at(this->editor.y).insert(this->editor.x, 1, char(c));
+					if (this->editor.lastChar != 195 && this->editor.lastChar != 182)
+						this->editor.x++;
+					this->editor.lastChar = char(c);
+				}
+				break;
+			}
+		}
+	}
+}
\ No newline at end of file
diff --git a/src/modes/Insert.hpp b/src/modes/Insert.hpp
new file mode 100644
index 0000000..5ac43f8
--- /dev/null
+++ b/src/modes/Insert.hpp
@@ -0,0 +1,18 @@
+#pragma once
+
+#include <modes/Mode.hpp>
+
+namespace groove {
+	namespace modes {
+
+		class Insert : public Mode {
+		public:
+			using Mode::Mode;
+			std::string status() {
+				return this->status_;
+			}
+			void input(int c);
+		};
+
+	}
+}
\ No newline at end of file
diff --git a/src/modes/Mode.cpp b/src/modes/Mode.cpp
new file mode 100644
index 0000000..045eee8
--- /dev/null
+++ b/src/modes/Mode.cpp
@@ -0,0 +1,9 @@
+#include <modes/Mode.hpp>
+
+namespace groove {
+	namespace modes {
+
+		Mode::~Mode() {}
+
+	}
+}
\ No newline at end of file
diff --git a/src/modes/Mode.hpp b/src/modes/Mode.hpp
new file mode 100644
index 0000000..16a47f3
--- /dev/null
+++ b/src/modes/Mode.hpp
@@ -0,0 +1,22 @@
+#pragma once
+
+#include <string>
+
+namespace groove {
+	class Editor;
+
+	namespace modes {
+
+		class Mode {
+		protected:
+			groove::Editor& editor;
+			std::string status_;
+		public:
+			Mode(groove::Editor& editor) : editor(editor) , status_("") {}
+			virtual ~Mode() = 0;
+			virtual std::string status() = 0;
+			virtual void input(int c) = 0;
+		};
+
+	}
+}
\ No newline at end of file