├── .editorconfig
├── .gitignore
├── .travis.yml
├── LICENSE
├── Makefile
├── README.md
├── assets
├── gadget_example.png
├── gadget_icon_med.png
└── gadget_title.png
└── src
├── Command.cpp
├── Command.h
├── CommandBar.cpp
├── CommandBar.h
├── Editor.cpp
├── Editor.h
├── FileHelper.cpp
├── FileHelper.h
├── FileTree.cpp
├── FileTree.h
├── Frame.cpp
├── Frame.h
├── Gadget.cpp
├── Gadget.h
├── HelpFile.cpp
├── HelpFile.h
├── Panel.cpp
├── Panel.h
├── StatusBar.cpp
├── StatusBar.h
├── StatusSection.cpp
├── StatusSection.h
├── Window.cpp
├── Window.h
└── res
└── gadget.xpm
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | charset = utf-8
5 | indent_style = space
6 | indent_size = 4
7 | insert_final_newline = true
8 | trim_trailing_whitespace = true
9 | end_of_line = lf
10 | insert_final_newline = true
11 |
12 | [*.md]
13 | trim_trailing_whitespace = false
14 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | gadget
2 | **/*.swp
3 | *.sh
4 | *.vim
5 | *.txt
6 | *.o
7 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | dist: bionic
2 | language: cpp
3 | compiler: gcc
4 |
5 | addons:
6 | apt:
7 | sources:
8 | - ubuntu-toolchain-r-test
9 | packages:
10 | - gcc-8
11 | - g++-8
12 |
13 | before_install:
14 | - sudo apt-get update
15 | - sudo apt-get -y install libgtk2.0-dev
16 |
17 | install:
18 | - sudo ln -s /usr/bin/gcc-8 /usr/local/bin/gcc
19 | - sudo ln -s /usr/bin/g++-8 /usr/local/bin/g++
20 | - export CC=/usr/bin/gcc-8
21 | - export CXX=/usr/bin/g++-8
22 | - gcc -v && g++ -v
23 | - cd $HOME
24 | - curl -fsSL -O https://github.com/wxWidgets/wxWidgets/releases/download/v3.0.5/wxWidgets-3.0.5.tar.bz2
25 | - tar -xjf wxWidgets-3.0.5.tar.bz2
26 | - cd wxWidgets-3.0.5
27 | - mkdir gtk-build
28 | - cd gtk-build
29 | - ../configure
30 | - make -j3
31 | - sudo make install
32 | - sudo ldconfig
33 |
34 | script:
35 | - cd $TRAVIS_BUILD_DIR
36 | - make
37 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 Christopher Lin
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | CC=gcc
2 | CXX=g++
3 | RM=rm -f
4 | CXXFLAGS=`wx-config --cxxflags` -std=c++17 -lstdc++fs
5 | LDLIBS=`wx-config --libs core,aui,richtext,stc`
6 |
7 | SRCS=Gadget.cpp Frame.cpp Window.cpp Editor.cpp FileTree.cpp Panel.cpp Command.cpp CommandBar.cpp StatusBar.cpp StatusSection.cpp HelpFile.cpp FileHelper.cpp
8 | OBJS=$(subst .cpp,.o,$(SRCS))
9 |
10 | VPATH=./src
11 |
12 | all: gadget
13 |
14 | gadget: $(OBJS)
15 | $(CXX) -o gadget $(OBJS) $(CXXFLAGS) $(LDLIBS)
16 |
17 | Gadget.o: Gadget.cpp Gadget.h ./src/res/gadget.xpm
18 | $(CXX) -c ./src/Gadget.cpp $(CXXFLAGS)
19 |
20 | Frame.o: Frame.cpp Frame.h
21 | $(CXX) -c ./src/Frame.cpp $(CXXFLAGS)
22 |
23 | Window.o: Window.cpp Window.h
24 | $(CXX) -c ./src/Window.cpp $(CXXFLAGS)
25 |
26 | Editor.o: Editor.cpp Editor.h
27 | $(CXX) -c ./src/Editor.cpp $(CXXFLAGS)
28 |
29 | FileTree.o: FileTree.cpp FileTree.h
30 | $(CXX) -c ./src/FileTree.cpp $(CXXFLAGS)
31 |
32 | Panel.o: Panel.cpp Panel.h
33 | $(CXX) -c ./src/Panel.cpp $(CXXFLAGS)
34 |
35 | Command.o: Command.cpp Command.h
36 | $(CXX) -c ./src/Command.cpp $(CXXFLAGS)
37 |
38 | CommandBar.o: CommandBar.cpp CommandBar.h
39 | $(CXX) -c ./src/CommandBar.cpp $(CXXFLAGS)
40 |
41 | StatusBar.o: StatusBar.cpp StatusBar.h
42 | $(CXX) -c ./src/StatusBar.cpp $(CXXFLAGS)
43 |
44 | StatusSection.o: StatusSection.cpp StatusSection.h
45 | $(CXX) -c ./src/StatusSection.cpp $(CXXFLAGS)
46 |
47 | HelpFile.o: HelpFile.cpp HelpFile.h
48 | $(CXX) -c ./src/HelpFile.cpp $(CXXFLAGS)
49 |
50 | FileHelper.o: FileHelper.cpp FileHelper.h
51 | $(CXX) -c ./src/FileHelper.cpp $(CXXFLAGS)
52 |
53 | clean:
54 | $(RM) $(OBJS)
55 |
56 | distclean: clean
57 | $(RM) gadget
58 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | A no-hassle GVim-inspired GUI text editor.
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | ## Installation
23 |
24 | ### Linux
25 |
26 | #### Debian-based distros
27 |
28 | Install via the latest corresponding Debian package:
29 |
30 | ```
31 | curl -L -O https://github.com/lintopher0315/gadget/releases/download/v1.0.0/gadget_1.0.0_amd64.deb
32 | sudo apt install ./gadget_1.0.0_amd64.deb
33 | ```
34 |
35 | Alternatively, navigate to https://github.com/lintopher0315/gadget/releases/, download the Debian package manually, and then run `sudo apt install ./gadget_1.0.0_amd64.deb`.
36 |
37 | ## Features
38 | * One-to-one functionality of numerous Vim commands
39 | * 4 editor modes: *Normal*, *Edit*, *Visual*, and *Line*
40 | * Similar to Vim, *Visual* mode can be activated by clicking and dragging with the mouse
41 | * Allows CTRL-C and CTRL-V to/from clipboard in *Visual* and *Line* modes
42 | * Minimalistic status bar
43 | * Displays unsaved and read-only files
44 | * Shows caret position and size of file by bytes and lines
45 | * Smart indentation
46 | * Color-coded file tree
47 | * Sorted by directories, dotfiles, then regular files by extension
48 | * Directories colored according to amount of files: pink if empty, red if <10, yellow if <30, green if <50, blue if <70, and purple for any higher quantity
49 | * Tab splitting
50 | * Syntax highlighting (only for C++ for now, work in progress)
51 | * Soon-to-be cross-platform (also work in progress)
52 |
53 | ## Usage
54 |
55 | After installing, run the following command to open Gadget:
56 |
57 | ```
58 | gadget &
59 | ```
60 |
61 | Gadget will open up in *Normal* mode which is the main mode for running commands for moving, editing, configuring, etc. Directly typing in *Normal* mode will begin forming a command underneath the status bar. Pressing `ESC` will clear the command bar. `ESC` will also switch from any other mode to *Normal* mode.
62 |
63 | | *Normal* mode commands | Behavior |
64 | | -------------------- | -------- |
65 | | `[num]h` | move caret left `[num]` times |
66 | | `[num]j` | move caret down `[num]` times |
67 | | `[num]k` | move caret up `[num]` times |
68 | | `[num]l` | move caret right `[num]` times |
69 | | `[num]w` | jump to the start of the next word `[num]` times |
70 | | `[num]b` | jump to the start of the previous word `[num]` times |
71 | | `gg` | jump to the beginning of the file |
72 | | `G` | jump to the end of the file |
73 | | `[num]G` | jump to the beginning of line `[num]` |
74 | | `_` | jump to the first non-whitespace character of the current line |
75 | | `0` | jump to the beginning of the current line |
76 | | `$` | jump to the end of the current line |
77 | | `[num]x` | cut the character the caret is currently on `[num]` times |
78 | | `[num]o` | append `[num]` empty lines below the current line |
79 | | `[num]O` | append `[num]` empty lines above the current line |
80 | | `[num]dd` | cut `[num]` lines |
81 | | `D` | cut to the end of the current line |
82 | | `f [char]` | jump to the next instance of `[char]` on the current line |
83 | | `F [char]` | jump to the previous instance of `[char]` on the current line |
84 | | `t [char]` | jump just before the next instance of `[char]` on the current line |
85 | | `T [char]` | jump just after the previous instance of `[char]` on the current line |
86 | | `p` | past the contents of the clipboard after the caret |
87 | | `P` | past the contents of the clipboard before the caret |
88 | | `[num]gt` | switch to the tab indicated by `[num]` |
89 | | `i` | change to *Edit* mode
90 | | `I` | change to *Edit* mode and jump before the first non-whitespace character of the current line |
91 | | `a` | change to *Edit* mode and move the caret right |
92 | | `A` | change to *Edit* mode and jump to the end of the current line |
93 | | `v` | switch to *Visual* mode |
94 | | `V` | switch to *Line* mode |
95 | | `:q` | quit and close the current document |
96 | | `:w` | save the document to the file it points to |
97 | | `:w [file]` | save the document to `[file]` and set it to point to `[file]` |
98 | | `:wq` | save and close the document |
99 | | `:e [file]` | open a new file, `[file]`, in the current editor |
100 | | `:tabedit` | create a new empty document in another tab |
101 | | `:tabedit [file]` | create a new document in another tab pointing to `[file]`
102 | | `:split` | split the current tab horizontally |
103 | | `:vsplit` | split the current tab vertically |
104 | | `:help` | open the help file in a new tab |
105 |
106 | *Edit* mode is for writing and acts as any standard text editor. *Edit* mode has no commands.
107 |
108 | *Visual* mode allows the performing of actions on blocks of text like copying, pasting, case-changing, etc. Once in visual mode, the anchor of the selection will begin from where the caret is positioned. All movement commands seen in *Normal* mode (e.g. `hjkl`, `gg`, `w`, etc.) can be used to extend the selection.
109 |
110 | | *Visual* mode commands | Behavior |
111 | | -------------------- | -------- |
112 | | `x` | cuts the selection |
113 | | `u` | changes selection to lowercase |
114 | | `U` | changes selection to uppercase |
115 | | `y` | copies selection to the clipboard |
116 |
117 | *Line* mode is similar to visual mode, but differs in that it only extends the selection line-by-line. This is useful for selecting blocks of text where only the lines matter. All *Visual* commands will also work in *Line* mode as well as *Normal* mode movement commands.
118 |
119 | | *Line* mode commands | Behavior |
120 | | -------------------- | -------- |
121 | | `[num]<` | shifts the selected lines `[num]` times to the left |
122 | | `[num]>` | shifts the selected lines `[num]` times to the right |
--------------------------------------------------------------------------------
/assets/gadget_example.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lintopher0315/gadget/9bcd399aa087f6e82a9353e883d004c50d92c9d5/assets/gadget_example.png
--------------------------------------------------------------------------------
/assets/gadget_icon_med.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lintopher0315/gadget/9bcd399aa087f6e82a9353e883d004c50d92c9d5/assets/gadget_icon_med.png
--------------------------------------------------------------------------------
/assets/gadget_title.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lintopher0315/gadget/9bcd399aa087f6e82a9353e883d004c50d92c9d5/assets/gadget_title.png
--------------------------------------------------------------------------------
/src/Command.cpp:
--------------------------------------------------------------------------------
1 | #include "Command.h"
2 |
3 | Command::Command(void) {
4 | prefix = NORMAL_PREFIX;
5 | }
6 |
7 | void Command::clear(void) {
8 | prefix = NORMAL_PREFIX;
9 | cmd = "";
10 | }
11 |
12 | bool Command::isClear(void) const {
13 | return prefix == NORMAL_PREFIX && cmd.empty();
14 | }
15 |
16 | int Command::isValidNormal(void) const {
17 | if (prefix == NORMAL_PREFIX) {
18 | for (int i = 0; i < sizeof(ACT_LIST) / sizeof(ACT_LIST[0]); ++i) {
19 | if (std::regex_match(cmd, std::regex(ACT_LIST[i]))) {
20 | return i;
21 | }
22 | }
23 | }
24 | return -1;
25 | }
26 |
27 | int Command::isValidCommand(void) const {
28 | if (prefix == COMMAND_PREFIX) {
29 | for (int i = 0; i < sizeof(CMD_LIST) / sizeof(CMD_LIST[0]); ++i) {
30 | if (std::regex_match(cmd, std::regex(CMD_LIST[i]))) {
31 | return i;
32 | }
33 | }
34 | }
35 | return -1;
36 | }
37 |
38 | int Command::isValidVisual(void) const {
39 | if (prefix == NORMAL_PREFIX) {
40 | for (int i = 0; i < sizeof(VIS_LIST) / sizeof(VIS_LIST[0]); ++i) {
41 | if (std::regex_match(cmd, std::regex(VIS_LIST[i]))) {
42 | return i;
43 | }
44 | }
45 | }
46 | return -1;
47 | }
48 |
49 | int Command::isValidLine(void) const {
50 | if (prefix == NORMAL_PREFIX) {
51 | for (int i = 0; i < sizeof(LIN_LIST) / sizeof(LIN_LIST[0]); ++i) {
52 | if (std::regex_match(cmd, std::regex(LIN_LIST[i]))) {
53 | return i;
54 | }
55 | }
56 | }
57 | return -1;
58 | }
59 |
60 | std::pair Command::parseNormal() const {
61 | int num = 0;
62 | int i = 0;
63 | while (i < cmd.size() && isdigit(cmd[i])) {
64 | num *= 10;
65 | num += cmd[i] - '0';
66 | ++i;
67 | }
68 | return {std::max(1, num), cmd.substr(i, cmd.size()-i)};
69 | }
70 |
71 | std::vector Command::parseCommand() const {
72 | std::vector result;
73 | std::string token;
74 | std::istringstream tokenStream(cmd);
75 | while (std::getline(tokenStream, token, ' ')) {
76 | result.push_back(token);
77 | }
78 | return result;
79 | }
80 |
--------------------------------------------------------------------------------
/src/Command.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | #define NORMAL_PREFIX 0
9 | #define COMMAND_PREFIX 1
10 |
11 | class Command {
12 | public:
13 | Command(void);
14 |
15 | void clear(void);
16 | bool isClear(void) const;
17 | int isValidNormal(void) const;
18 | int isValidCommand(void) const;
19 | int isValidVisual(void) const;
20 | int isValidLine(void) const;
21 | std::pair parseNormal(void) const;
22 | std::vector parseCommand(void) const;
23 |
24 | unsigned short prefix;
25 | std::string cmd;
26 |
27 | private:
28 | const std::string CMD_LIST[6]={"q", "(w|wq)( [^ ]+)?", "e [^ ]+", "tabedit( [^ ]+)*", "v?split", "help"};
29 | const std::string ACT_LIST[13]={"[iIaA]", "([1-9][0-9]*)?[hjkl]", "([1-9][0-9]*)?[oO]", "[_$0]", "(gg|G|[1-9][0-9]*G)", "[1-9][0-9]*gt", "([1-9][0-9]*)?[wb]", "[fFtT].", "v", "V", "[pP]", "x", "(([1-9][0-9]*)?dd|D)"};
30 | const std::string VIS_LIST[8]={"([1-9][0-9]*)?[hjkl]", "[xd]", "[uU]", "(gg|G|[1-9][0-9]*G)", "y", "([1-9][0-9]*)?[wb]", "[_$0]", "[fFtT]."};
31 | const std::string LIN_LIST[6]={"([1-9][0-9]*)?[jk]", "[xd]", "[uU]", "([1-9][0-9]*)?[<>]", "y", "(gg|G|[1-9][0-9]*G)"};
32 | };
33 |
--------------------------------------------------------------------------------
/src/CommandBar.cpp:
--------------------------------------------------------------------------------
1 | #include "CommandBar.h"
2 |
3 | CommandBar::CommandBar(wxWindow *parent) : wxRichTextCtrl(parent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(wxGetDisplaySize().GetWidth()/2, 30), wxRE_MULTILINE, wxDefaultValidator) {
4 | SetEditable(false);
5 | EnableVerticalScrollbar(false);
6 | wxFont *font = new wxFont(10, wxFONTFAMILY_TELETYPE, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxEmptyString);
7 | SetFont(*font);
8 |
9 | SetBackgroundColour(wxColour(37, 37, 38));
10 | wxRichTextAttr attr = GetBasicStyle();
11 | attr.SetTextColour(wxColour(224, 227, 23));
12 | SetBasicStyle(attr);
13 |
14 | Bind(wxEVT_LEFT_DOWN, &CommandBar::onClick, this);
15 | Bind(wxEVT_RIGHT_DOWN, &CommandBar::onClick, this);
16 | }
17 |
18 | void CommandBar::onClick(wxMouseEvent& event) {
19 | event.Skip(false);
20 | }
21 |
--------------------------------------------------------------------------------
/src/CommandBar.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 |
6 | class CommandBar : public wxRichTextCtrl {
7 | public:
8 | CommandBar(wxWindow *parent);
9 |
10 |
11 | private:
12 | void onClick(wxMouseEvent& event);
13 | };
14 |
--------------------------------------------------------------------------------
/src/Editor.cpp:
--------------------------------------------------------------------------------
1 | #include "Window.h"
2 | #include "Editor.h"
3 | #include "FileHelper.h"
4 |
5 | Editor::Editor(wxWindow *parent, int lexer) : wxStyledTextCtrl(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0, "editor") {
6 | SetCaretStyle(2);
7 | SetCaretPeriod(0);
8 | SetTabWidth(4);
9 | SetUseHorizontalScrollBar(false);
10 | SetWrapMode(1);
11 | SetMarginType(1, wxSTC_MARGIN_NUMBER);
12 | SetMarginWidth(1, 30);
13 | SetUseTabs(false);
14 |
15 | std::string whitespaceChars = std::string(GetWhitespaceChars().mb_str()) + "\n";
16 | SetWhitespaceChars(whitespaceChars);
17 |
18 | StyleSetBackground(wxSTC_STYLE_DEFAULT, wxColour(30, 30, 30));
19 | StyleSetForeground(wxSTC_STYLE_DEFAULT, wxColour(255, 255, 255));
20 | SetCaretForeground(wxColour(219, 131, 0));
21 |
22 | StyleClearAll();
23 |
24 | applyLexer(lexer);
25 |
26 | StyleSetBackground(wxSTC_STYLE_LINENUMBER, wxColour(37, 37, 38));
27 | StyleSetForeground(wxSTC_STYLE_LINENUMBER, wxColour(240, 240, 41));
28 |
29 | Bind(wxEVT_CHAR, &Editor::onChar, this);
30 | Bind(wxEVT_KEY_DOWN, &Editor::onKey, this);
31 | Bind(wxEVT_LEFT_UP, &Editor::onClickUp, this);
32 | Bind(wxEVT_LEFT_DOWN, &Editor::onClickDown, this);
33 | Bind(wxEVT_STC_CHANGE, &Editor::onChange, this);
34 |
35 | saved = true;
36 | readOnly = false;
37 | }
38 |
39 | Window *Editor::getWindow(void) {
40 | return (Window *)GetGrandParent();
41 | }
42 |
43 | void Editor::onChar(wxKeyEvent& event) {
44 | wxChar c = event.GetUnicodeKey();
45 | Window *w = getWindow();
46 | if (c != WXK_NONE) {
47 | if (c >= 32) {
48 | if (w->mode == NORMAL_MODE) {
49 | w->commandBar->AppendText(c);
50 | if (c == ':' && w->command->cmd.empty()) {
51 | w->command->prefix = COMMAND_PREFIX;
52 | return;
53 | }
54 | w->command->cmd += c;
55 |
56 | int ind = -1;
57 | if ((ind = w->command->isValidNormal()) >= 0) {
58 | w->executeNormal(ind);
59 | }
60 | }
61 | else if (w->mode == EDIT_MODE) {
62 | AddText(c);
63 | w->updateStatus();
64 | }
65 | else if (w->mode == VISUAL_MODE) {
66 | w->commandBar->AppendText(c);
67 | w->command->cmd += c;
68 |
69 | int ind = -1;
70 | if ((ind = w->command->isValidVisual()) >= 0) {
71 | w->executeVisual(ind);
72 | }
73 | }
74 | else if (w->mode == LINE_MODE) {
75 | w->commandBar->AppendText(c);
76 | w->command->cmd += c;
77 |
78 | int ind = -1;
79 | if ((ind = w->command->isValidLine()) >= 0) {
80 | w->executeLine(ind);
81 | }
82 | }
83 | }
84 | }
85 | }
86 |
87 | void Editor::onKey(wxKeyEvent& event) {
88 | Window *w = getWindow();
89 | int key = event.GetKeyCode();
90 | if (key >= 32 && key <= 127) {
91 | if (!event.ControlDown() || key == 67 || key == 86) {
92 | event.Skip();
93 | }
94 | }
95 | else if (key == WXK_ESCAPE) {
96 | if (w->mode == EDIT_MODE) {
97 | caretLeft(1);
98 | }
99 | else if (w->mode == VISUAL_MODE || w->mode == LINE_MODE) {
100 | removeSelection();
101 | if (GetCurrentPos() == lineEndPos()) {
102 | caretLeft(1);
103 | }
104 | }
105 | w->mode = NORMAL_MODE;
106 | w->command->clear();
107 | w->commandBar->Clear();
108 | }
109 | else if (key == WXK_RETURN) {
110 | if (w->mode == NORMAL_MODE) {
111 | int ind = -1;
112 | if ((ind = w->command->isValidCommand()) >= 0) {
113 | w->executeCommand(ind);
114 | }
115 | }
116 | else if (w->mode == EDIT_MODE) {
117 | std::string indentSpace = getIndentSpace(currLine());
118 | NewLine();
119 | AddText(indentSpace);
120 | }
121 | }
122 | else if (key == WXK_BACK) {
123 | if (w->mode == NORMAL_MODE) {
124 | if (!w->command->cmd.empty()) {
125 | w->command->cmd.pop_back();
126 | }
127 | else {
128 | w->command->prefix = NORMAL_PREFIX;
129 | }
130 | int l = w->commandBar->GetLineLength(0);
131 | w->commandBar->Remove(l-1, l);
132 | }
133 | else if (w->mode == EDIT_MODE) {
134 | std::string upToCaret = std::string(GetTextRange(lineStartPos(), GetCurrentPos()));
135 | if (upToCaret.empty() || upToCaret.find_first_not_of(' ') != std::string::npos) {
136 | DeleteBack();
137 | }
138 | else {
139 | DeleteRange(std::max(lineStartPos(), GetCurrentPos() - 4), std::min(linePos(), 4));
140 | }
141 | }
142 | }
143 | else if (key == WXK_TAB) {
144 | if (w->mode == EDIT_MODE) {
145 | Tab();
146 | }
147 | }
148 | else if (key == WXK_LEFT) {
149 | if (w->command->isClear()) {
150 | caretLeft(1);
151 | }
152 | }
153 | else if (key == WXK_RIGHT) {
154 | if (w->command->isClear()) {
155 | caretRight(1);
156 | }
157 | }
158 | else if (key == WXK_UP) {
159 | if (w->command->isClear()) {
160 | caretUp(1);
161 | }
162 | }
163 | else if (key == WXK_DOWN) {
164 | if (w->command->isClear()) {
165 | caretDown(1);
166 | }
167 | }
168 | else if (key == WXK_END) {
169 | if (w->command->isClear()) {
170 | LineEnd();
171 | caretLeft(1);
172 | }
173 | }
174 | else if (key == WXK_HOME) {
175 | if (w->command->isClear()) {
176 | VCHome();
177 | }
178 | }
179 | else if (key == WXK_PAGEUP) {
180 | if (w->command->isClear()) {
181 | PageUp();
182 | }
183 | }
184 | else if (key == WXK_PAGEDOWN) {
185 | if (w->command->isClear()) {
186 | PageDown();
187 | }
188 | }
189 | w->updateStatus();
190 | }
191 |
192 | void Editor::onClickUp(wxMouseEvent& event) {
193 | Window *w = getWindow();
194 |
195 | if (GetSelectionStart() != GetSelectionEnd()) {
196 | w->mode = VISUAL_MODE;
197 | }
198 | else {
199 | if (w->mode == VISUAL_MODE || w->mode == LINE_MODE) {
200 | w->mode = NORMAL_MODE;
201 | }
202 | }
203 | getWindow()->updateStatus();
204 | event.Skip();
205 | }
206 |
207 | void Editor::onClickDown(wxMouseEvent& event) {
208 | Window *w = getWindow();
209 |
210 | removeSelection();
211 | w->command->clear();
212 | w->commandBar->Clear();
213 | event.Skip();
214 | }
215 |
216 | void Editor::onChange(wxStyledTextEvent& event) {
217 | saved = false;
218 | event.Skip();
219 | }
220 |
221 | void Editor::applyLexer(const int& lexer) {
222 | if (lexer == CPP_LEX) {
223 | SetLexer(wxSTC_LEX_CPP);
224 |
225 | StyleSetForeground(wxSTC_C_COMMENTLINE, wxColor(60, 162, 2));
226 | StyleSetForeground(wxSTC_C_COMMENT, wxColor(60, 162, 2));
227 | StyleSetForeground(wxSTC_C_PREPROCESSOR, wxColor(250,128,114));
228 | StyleSetForeground(wxSTC_C_STRING, wxColor(222, 203, 62));
229 | StyleSetForeground(wxSTC_C_NUMBER, wxColor(83, 195, 230));
230 | StyleSetForeground(wxSTC_C_CHARACTER, wxColor(123, 224, 112));
231 | StyleSetForeground(wxSTC_C_WORD, wxColor(245, 113, 208));
232 | StyleSetForeground(wxSTC_C_WORD2, wxColor(230, 78, 86));
233 | SetKeyWords(0, wxT(
234 | "alignas alignof and and_eq asm atomic_cancel atomic_commit atomic_noexcept auto"
235 | " bitand bitor bool char char8_t char16_t char32_t compl string"
236 | " concept consteval constexpr constinit const_cast co_await co_return"
237 | " co_yield decltype default delete do double dynamic_cast enum explicit export"
238 | " extern float friend inline int long mutable namespace new noexcept"
239 | " not not_eq nullptr operator or or_eq reflexpr register"
240 | " reinterpret_cast requires short signed sizeof static static_assert static_cast"
241 | " struct synchronized template this thread_local typedef typeid"
242 | " typename union unsigned using virtual void volatile wchar_t xor xor_eq"
243 | ));
244 | SetKeyWords(1, wxT(
245 | "const class private protected public false true if for goto break case catch"
246 | " continue else return switch throw try while"
247 | ));
248 | SetProperty("styling.within.preprocessor", "1");
249 | }
250 | else {
251 | SetLexer(wxSTC_LEX_NULL);
252 | }
253 | wxFont *font = new wxFont(10, wxFONTFAMILY_TELETYPE, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxEmptyString);
254 | for (int i = 0; i < 32; ++i) {
255 | StyleSetFont(i, *font);
256 | }
257 | }
258 |
259 | void Editor::loadFormatted(const std::string& file) {
260 | LoadFile(file);
261 | convertTabs();
262 | }
263 |
264 | void Editor::convertTabs(void) {
265 | std::string oldText = std::string(GetText().mb_str());
266 | std::string newText;
267 | for (char c : oldText) {
268 | if (c == '\t') {
269 | newText.append(" ");
270 | }
271 | else {
272 | newText.push_back(c);
273 | }
274 | }
275 | wxString docText(newText);
276 | SetText(docText);
277 | }
278 |
279 | int Editor::linePos(void) const {
280 | return GetCurrentPos() - lineStartPos();
281 | }
282 |
283 | int Editor::currLine(void) const {
284 | return LineFromPosition(GetCurrentPos());
285 | }
286 |
287 | int Editor::lineStartPos(void) const {
288 | return PositionFromLine(currLine());
289 | }
290 |
291 | int Editor::lineEndPos(void) const {
292 | return GetLineEndPosition(currLine());
293 | }
294 |
295 | std::string Editor::getIndentSpace(const int& line) const {
296 | std::string lineIndent = std::string(GetLine(line).mb_str());
297 | int ind = 0;
298 | while (ind < lineIndent.size() && lineIndent[ind] == ' ') {
299 | ++ind;
300 | }
301 | return lineIndent.substr(0, ind);
302 | }
303 |
304 | void Editor::caretLeft(const int& num) {
305 | SetSelectionEnd(std::max(lineStartPos(), GetCurrentPos() - num));
306 | }
307 |
308 | void Editor::caretRight(const int& num) {
309 | if (lineStartPos() < lineEndPos()) {
310 | SetSelectionStart(std::min(lineEndPos() - 1, GetCurrentPos() + num));
311 | }
312 | }
313 |
314 | void Editor::caretUp(const int& num) {
315 | int pos = linePos();
316 | GotoLine(std::max(0, currLine() - num));
317 | caretRight(pos);
318 | }
319 |
320 | void Editor::caretDown(const int& num) {
321 | int pos = linePos();
322 | GotoLine(std::min(GetLineCount() - 1, currLine() + num));
323 | caretRight(pos);
324 | }
325 |
326 | void Editor::append(void) {
327 | if (lineEndPos() - 1 == GetCurrentPos()) {
328 | LineEnd();
329 | }
330 | else {
331 | caretRight(1);
332 | }
333 | }
334 |
335 | void Editor::insertLineBelow(const int& num) {
336 | LineEnd();
337 | std::string indentSpace = getIndentSpace(currLine());
338 | for (int i = 0; i < num; ++i) {
339 | NewLine();
340 | AddText(indentSpace);
341 | }
342 | Window *w = getWindow();
343 | w->mode = EDIT_MODE;
344 | }
345 |
346 | void Editor::insertLineAbove(const int& num) {
347 | std::string indentSpace = getIndentSpace(currLine());
348 | for (int i = 0; i < num; ++i) {
349 | Home();
350 | NewLine();
351 | caretUp(1);
352 | AddText(indentSpace);
353 | }
354 |
355 | Window *w = getWindow();
356 | w->mode = EDIT_MODE;
357 | }
358 |
359 | void Editor::wordLeft(const int& num) {
360 | for (int i = 0; i < num; ++i) {
361 | WordLeft();
362 | }
363 | }
364 |
365 | void Editor::wordRight(const int& num) {
366 | for (int i = 0; i < num; ++i) {
367 | WordRight();
368 | }
369 | }
370 |
371 | void Editor::charSearchAhead(const char& c, const bool& inc) {
372 | for (int i = GetCurrentPos() + 1; i < lineEndPos(); ++i) {
373 | if (GetCharAt(i) == c) {
374 | if (inc) {
375 | GotoPos(i);
376 | }
377 | else {
378 | GotoPos(i-1);
379 | }
380 | return;
381 | }
382 | }
383 | }
384 |
385 | void Editor::charSearchBehind(const char& c, const bool& inc) {
386 | for (int i = GetCurrentPos() - 1; i >= lineStartPos(); --i) {
387 | if (GetCharAt(i) == c) {
388 | if (inc) {
389 | GotoPos(i);
390 | }
391 | else {
392 | GotoPos(i+1);
393 | }
394 | return;
395 | }
396 | }
397 | }
398 |
399 | void Editor::cutToLineEnd(void) {
400 | SetAnchor(GetCurrentPos());
401 | SetCurrentPos(lineEndPos() - 1);
402 | cutSelection();
403 | caretLeft(1);
404 | }
405 |
406 | void Editor::cutLines(const int& num) {
407 | GotoPos(lineStartPos());
408 | DeleteBack();
409 | int endLine = std::min(GetLineCount() - 1, currLine() + num - 1);
410 | SetAnchor(GetLineEndPosition(endLine));
411 | cutSelection();
412 | caretDown(1);
413 | VCHome();
414 | }
415 |
416 | void Editor::removeSelection(void) {
417 | SetEmptySelection(GetCurrentPos());
418 | }
419 |
420 | void Editor::cutSelection(void) {
421 | if (GetAnchor() <= GetCurrentPos()) {
422 | CharRightExtend();
423 | }
424 | Cut();
425 | }
426 |
427 | void Editor::copySelection(void) {
428 | if (GetAnchor() <= GetCurrentPos()) {
429 | CharRightExtend();
430 | }
431 | Copy();
432 | }
433 |
434 | void Editor::caseChangeSelection(const bool& upper) {
435 | if (GetAnchor() <= GetCurrentPos()) {
436 | CharRightExtend();
437 | }
438 | if (upper) {
439 | UpperCase();
440 | }
441 | else {
442 | LowerCase();
443 | }
444 | if (GetAnchor() <= GetCurrentPos()) {
445 | CharLeftExtend();
446 | }
447 | }
448 |
449 | void Editor::caretLeftVis(const int& num) {
450 | int pos = std::max(lineStartPos(), GetCurrentPos() - num);
451 | if (GetCurrentPos() != pos && GetCurrentPos() == GetAnchor()) {
452 | SetAnchor(GetAnchor() + 1);
453 | }
454 | SetCurrentPos(pos);
455 | }
456 |
457 | void Editor::caretRightVis(const int& num) {
458 | int pos = std::min(lineEndPos() - 1, GetCurrentPos() + num);
459 | if (pos == GetAnchor() - 1) {
460 | SetAnchor(GetAnchor() - 1);
461 | }
462 | SetCurrentPos(pos);
463 | }
464 |
465 | void Editor::caretUpVis(const int& num) {
466 | int pos = linePos();
467 | int endLine = std::max(0, currLine() - num);
468 | int endPos = std::min(GetLineEndPosition(endLine) - 1, PositionFromLine(endLine) + pos);
469 | if (PositionFromLine(endLine) == GetLineEndPosition(endLine)) {
470 | ++endPos;
471 | }
472 | if (endPos < GetAnchor() && GetAnchor() <= GetCurrentPos()) {
473 | SetAnchor(GetAnchor() + 1);
474 | }
475 | SetCurrentPos(endPos);
476 | }
477 |
478 | void Editor::caretDownVis(const int& num) {
479 | int pos = linePos();
480 | int endLine = std::min(GetLineCount() - 1, currLine() + num);
481 | int endPos = std::min(GetLineEndPosition(endLine) - 1, PositionFromLine(endLine) + pos);
482 | if (PositionFromLine(endLine) == GetLineEndPosition(endLine)) {
483 | ++endPos;
484 | }
485 | if (endPos >= GetAnchor() - 1 && GetAnchor() > GetCurrentPos()) {
486 | SetAnchor(GetAnchor() - 1);
487 | }
488 | SetCurrentPos(endPos);
489 | }
490 |
491 | void Editor::jumpStartVis(void) {
492 | if (GetCurrentPos() >= GetAnchor()) {
493 | SetAnchor(GetAnchor() + 1);
494 | }
495 | SetCurrentPos(0);
496 | }
497 |
498 | void Editor::jumpEndVis(void) {
499 | if (GetCurrentPos() < GetAnchor()) {
500 | SetAnchor(GetAnchor() - 1);
501 | }
502 | SetCurrentPos(GetTextLength() - 1);
503 | }
504 |
505 | void Editor::jumpLineVis(const int& line) {
506 | int endPos = PositionFromLine(line);
507 | if (endPos >= GetAnchor() - 1 && GetAnchor() > GetCurrentPos()) {
508 | SetAnchor(GetAnchor() - 1);
509 | }
510 | else if (endPos < GetAnchor() && GetAnchor() <= GetCurrentPos()) {
511 | SetAnchor(GetAnchor() + 1);
512 | }
513 | SetCurrentPos(endPos);
514 | }
515 |
516 | void Editor::wordLeftVis(const int& num) {
517 | for (int i = 0; i < num; ++i) {
518 | int startPos = GetCurrentPos();
519 | WordLeftExtend();
520 | if (GetCurrentPos() == startPos) {
521 | return;
522 | }
523 | if (GetCurrentPos() < GetAnchor() && GetAnchor() <= startPos) {
524 | SetAnchor(GetAnchor() + 1);
525 | }
526 | }
527 | }
528 |
529 | void Editor::wordRightVis(const int& num) {
530 | for (int i = 0; i < num; ++i) {
531 | int startPos = GetCurrentPos();
532 | WordRightExtend();
533 | if (GetCurrentPos() == startPos) {
534 | return;
535 | }
536 | if (GetCurrentPos() >= GetAnchor() - 1 && GetAnchor() - 1 >= startPos) {
537 | SetAnchor(GetAnchor() - 1);
538 | }
539 | }
540 | }
541 |
542 | void Editor::lineEndVis(void) {
543 | int startPos = GetCurrentPos();
544 | LineEndExtend();
545 | if (GetCurrentPos() >= GetAnchor() - 1 && GetAnchor() - 1 >= startPos) {
546 | SetAnchor(GetAnchor() - 1);
547 | }
548 | caretLeftVis(1);
549 | }
550 |
551 | void Editor::lineStartVis(void) {
552 | int startPos = GetCurrentPos();
553 | HomeExtend();
554 | if (GetCurrentPos() != startPos && GetCurrentPos() < GetAnchor() && GetAnchor() <= startPos) {
555 | SetAnchor(GetAnchor() + 1);
556 | }
557 | }
558 |
559 | void Editor::lineHomeVis(void) {
560 | int startPos = GetCurrentPos();
561 | VCHomeExtend();
562 | if (GetCurrentPos() != startPos && GetCurrentPos() < GetAnchor() && GetAnchor() <= startPos) {
563 | SetAnchor(GetAnchor() + 1);
564 | }
565 | }
566 |
567 | void Editor::charSearchAheadVis(const char& c, const bool& inc) {
568 | int endPos = GetCurrentPos() + 1;
569 | while (endPos < lineEndPos() && GetCharAt(endPos) != c) {
570 | ++endPos;
571 | }
572 | if (endPos >= lineEndPos()) {
573 | return;
574 | }
575 | if (!inc) {
576 | --endPos;
577 | }
578 | if (endPos >= GetAnchor() - 1 && GetAnchor() - 1 >= GetCurrentPos()) {
579 | SetAnchor(GetAnchor() - 1);
580 | }
581 | SetCurrentPos(endPos);
582 | }
583 |
584 | void Editor::charSearchBehindVis(const char& c, const bool& inc) {
585 | int endPos = GetCurrentPos() - 1;
586 | while (endPos >= lineStartPos() && GetCharAt(endPos) != c) {
587 | --endPos;
588 | }
589 | if (endPos < lineStartPos()) {
590 | return;
591 | }
592 | if (!inc) {
593 | ++endPos;
594 | }
595 | if (endPos < GetAnchor() && GetAnchor() <= GetCurrentPos()) {
596 | SetAnchor(GetAnchor() + 1);
597 | }
598 | SetCurrentPos(endPos);
599 | }
600 |
601 | void Editor::caretUpLine(const int& num) {
602 | int endLine = std::max(currLine() - num, 0);
603 | int startLine = LineFromPosition(GetAnchor());
604 | if (endLine <= startLine) {
605 | SetAnchor(GetLineEndPosition(startLine));
606 | SetCurrentPos(PositionFromLine(endLine));
607 | }
608 | else {
609 | SetCurrentPos(GetLineEndPosition(endLine));
610 | }
611 | }
612 |
613 | void Editor::caretDownLine(const int& num) {
614 | int endLine = std::min(currLine() + num, GetLineCount() - 1);
615 | int startLine = LineFromPosition(GetAnchor());
616 | if (endLine >= startLine) {
617 | SetAnchor(PositionFromLine(startLine));
618 | SetCurrentPos(GetLineEndPosition(endLine));
619 | }
620 | else {
621 | SetCurrentPos(PositionFromLine(endLine));
622 | }
623 | }
624 |
625 | void Editor::shiftLine(const int& num, const bool& dir) {
626 | int startLine = LineFromPosition(GetSelectionStart());
627 | int endLine = LineFromPosition(GetSelectionEnd());
628 | if (dir == 1) {
629 | std::string indent(num * 4, ' ');
630 | for (int i = startLine; i <= endLine; ++i) {
631 | InsertText(PositionFromLine(i), indent);
632 | }
633 | }
634 | else {
635 | for (int i = startLine; i <= endLine; ++i) {
636 | int rem = std::min((int)getIndentSpace(i).size(), num * 4);
637 | DeleteRange(PositionFromLine(i), rem);
638 | }
639 | }
640 | }
641 |
642 | void Editor::jumpStartLine(void) {
643 | int startLine = LineFromPosition(GetAnchor());
644 | SetAnchor(GetLineEndPosition(startLine));
645 | SetCurrentPos(0);
646 | }
647 |
648 | void Editor::jumpEndLine(void) {
649 | int startLine = LineFromPosition(GetAnchor());
650 | SetAnchor(PositionFromLine(startLine));
651 | SetCurrentPos(GetTextLength() - 1);
652 | }
653 |
654 | void Editor::jumpLineLine(const int& line) {
655 | int startLine = LineFromPosition(GetAnchor());
656 | if (line >= startLine) {
657 | SetAnchor(PositionFromLine(startLine));
658 | SetCurrentPos(GetLineEndPosition(line));
659 | }
660 | else {
661 | SetAnchor(GetLineEndPosition(startLine));
662 | SetCurrentPos(PositionFromLine(line));
663 | }
664 | }
665 |
--------------------------------------------------------------------------------
/src/Editor.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 |
6 | class Window;
7 |
8 | class Editor : public wxStyledTextCtrl {
9 | public:
10 | Editor(wxWindow *parent, int lexer);
11 |
12 | Window *getWindow(void);
13 |
14 | void applyLexer(const int& lexer);
15 | void loadFormatted(const std::string& file);
16 | void convertTabs(void);
17 |
18 | int linePos(void) const;
19 | int currLine(void) const;
20 | int lineStartPos(void) const;
21 | int lineEndPos(void) const;
22 | std::string getIndentSpace(const int& line) const;
23 |
24 | void caretLeft(const int& num);
25 | void caretRight(const int& num);
26 | void caretUp(const int& num);
27 | void caretDown(const int& num);
28 | void append(void);
29 | void insertLineBelow(const int& num);
30 | void insertLineAbove(const int& num);
31 | void wordLeft(const int& num);
32 | void wordRight(const int& num);
33 | void charSearchAhead(const char& c, const bool& inc);
34 | void charSearchBehind(const char& c, const bool& inc);
35 | void cutToLineEnd(void);
36 | void cutLines(const int& num);
37 |
38 | void removeSelection(void);
39 | void cutSelection(void);
40 | void copySelection(void);
41 | void caseChangeSelection(const bool& upper);
42 |
43 | void caretLeftVis(const int& num);
44 | void caretRightVis(const int& num);
45 | void caretUpVis(const int& num);
46 | void caretDownVis(const int& num);
47 | void jumpStartVis(void);
48 | void jumpEndVis(void);
49 | void jumpLineVis(const int& line);
50 | void wordLeftVis(const int& num);
51 | void wordRightVis(const int& num);
52 | void lineEndVis(void);
53 | void lineStartVis(void);
54 | void lineHomeVis(void);
55 | void charSearchAheadVis(const char& c, const bool& inc);
56 | void charSearchBehindVis(const char& c, const bool& inc);
57 |
58 | void caretUpLine(const int& num);
59 | void caretDownLine(const int& num);
60 | void shiftLine(const int& num, const bool& dir);
61 | void jumpStartLine(void);
62 | void jumpEndLine(void);
63 | void jumpLineLine(const int& line);
64 |
65 | std::string relPath;
66 | bool saved;
67 | bool readOnly;
68 |
69 | private:
70 | void onChar(wxKeyEvent& event);
71 | void onKey(wxKeyEvent& event);
72 | void onClickUp(wxMouseEvent& event);
73 | void onClickDown(wxMouseEvent& event);
74 | void onChange(wxStyledTextEvent& event);
75 | };
76 |
--------------------------------------------------------------------------------
/src/FileHelper.cpp:
--------------------------------------------------------------------------------
1 | #include "FileHelper.h"
2 |
3 | bool FileHelper::isExistingPath(const std::string& cwd, const std::string& relPath) {
4 | if (relPath.empty()) {
5 | return false;
6 | }
7 | std::string absPath = cwd + relPath;
8 | if (std::filesystem::exists(absPath) && std::filesystem::is_regular_file(absPath)) {
9 | return true;
10 | }
11 | return false;
12 | }
13 |
14 | bool FileHelper::isValidPath(const std::string& cwd, const std::string& relPath) {
15 | // currently only allows relative paths from cwd
16 | if (relPath.empty()) {
17 | return false;
18 | }
19 | std::string absDir = cwd + relPath;
20 | // maybe check for backwards slash on Windows
21 | while (absDir.back() != '/') {
22 | absDir.pop_back();
23 | }
24 | if (std::filesystem::exists(absDir) && std::filesystem::is_directory(absDir)) {
25 | return true;
26 | }
27 | return false;
28 | }
29 |
30 | bool FileHelper::isReadOnlyFile(const std::string& cwd, const std::string& relPath) {
31 | std::string absPath = cwd + relPath;
32 | if (FileHelper::isExistingPath(cwd, relPath)) {
33 | std::filesystem::perms p = std::filesystem::status(absPath).permissions();
34 | if ((p & std::filesystem::perms::owner_write) == std::filesystem::perms::none) {
35 | return true;
36 | }
37 | }
38 | return false;
39 | }
40 |
41 | bool FileHelper::isDotFile(const std::string& relPath) {
42 | std::string cp = relPath;
43 | int dir = cp.find_last_of('/');
44 | if (dir != std::string::npos) {
45 | cp = cp.substr(dir + 1, cp.size() - dir - 1);
46 | }
47 | int dot = cp.find_last_of('.');
48 | if (dot == std::string::npos) {
49 | return false;
50 | }
51 | if (dot == 0) {
52 | return true;
53 | }
54 | return false;
55 | }
56 |
57 | std::string FileHelper::getExtension(const std::string& relPath) {
58 | int start = relPath.find_last_of('.');
59 | if (start == std::string::npos) {
60 | return "";
61 | }
62 | if (FileHelper::isDotFile(relPath)) {
63 | return "";
64 | }
65 | return relPath.substr(start + 1, relPath.size() - start - 1);
66 | }
67 |
68 | int FileHelper::getLexerFromExtension(const std::string& relPath) {
69 | std::string ext = getExtension(relPath);
70 | if (ext.empty()) {
71 | return NULL_LEX;
72 | }
73 | if (ext == "cpp" || ext == "cc" || ext == "cxx" || ext == "h" || ext == "hpp") {
74 | return CPP_LEX;
75 | }
76 | return NULL_LEX;
77 | }
78 |
--------------------------------------------------------------------------------
/src/FileHelper.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 |
7 | #define NULL_LEX 0
8 | #define CPP_LEX 1
9 |
10 | class FileHelper {
11 | public:
12 | static bool isExistingPath(const std::string& cwd, const std::string& relPath);
13 | static bool isValidPath(const std::string& cwd, const std::string& relPath);
14 | static bool isReadOnlyFile(const std::string& cwd, const std::string& relPath);
15 | static bool isDotFile(const std::string& relPath);
16 | static std::string getExtension(const std::string& relPath);
17 | static int getLexerFromExtension(const std::string& relPath);
18 | };
19 |
--------------------------------------------------------------------------------
/src/FileTree.cpp:
--------------------------------------------------------------------------------
1 | #include "Frame.h"
2 | #include "Window.h"
3 | #include "FileTree.h"
4 | #include "FileHelper.h"
5 |
6 | FileTree::FileTree(wxWindow *parent) : wxTreeCtrl(parent, wxID_ANY, wxDefaultPosition, wxSize(wxGetDisplaySize().GetWidth()/4, wxGetDisplaySize().GetHeight()/2), wxTR_DEFAULT_STYLE | wxTR_NO_LINES, wxDefaultValidator, wxTreeCtrlNameStr) {
7 | wxFont *font = new wxFont(10, wxFONTFAMILY_TELETYPE, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxEmptyString);
8 | SetFont(*font);
9 | SetMinClientSize(wxSize(100, 100));
10 | SetBackgroundColour(wxColour(37, 37, 38));
11 | SetIndent(20);
12 |
13 | cwd = getFrame()->cwd;
14 | root = AddRoot(cwd);
15 |
16 | int numFiles = loadTree(cwd, root);
17 | SortChildren(root);
18 | ClearFocusedItem();
19 | SetItemBold(root);
20 | SetItemBackgroundColour(root, getDirectoryColor(numFiles));
21 | Expand(root);
22 |
23 | Bind(wxEVT_TREE_ITEM_ACTIVATED, &FileTree::onActivate, this);
24 | Bind(wxEVT_KILL_FOCUS, &FileTree::onKillFocus, this);
25 | Bind(wxEVT_LEFT_DOWN, &FileTree::onClick, this);
26 | Bind(wxEVT_RIGHT_DOWN, &FileTree::onClick, this);
27 | }
28 |
29 | Frame *FileTree::getFrame(void) const {
30 | return (Frame *)GetParent();
31 | }
32 |
33 | void FileTree::onActivate(wxTreeEvent& event) {
34 | std::string relPath = getRelPathFromItem(event.GetItem());
35 | std::string absPath = cwd + relPath;
36 | if (std::filesystem::is_regular_file(absPath)) {
37 | Window *w = getFrame()->window;
38 | int lexer = FileHelper::getLexerFromExtension(relPath);
39 | w->panel->AddPage(new Editor(w->panel, lexer), relPath, true);
40 | w->getCurrentEditor()->relPath = relPath;
41 | w->getCurrentEditor()->loadFormatted(absPath);
42 | w->getCurrentEditor()->saved = true;
43 | }
44 | ClearFocusedItem();
45 | event.Skip();
46 | }
47 |
48 | void FileTree::onKillFocus(wxFocusEvent& event) {
49 | ClearFocusedItem();
50 | event.Skip();
51 | }
52 |
53 | void FileTree::onClick(wxMouseEvent& event) {
54 | ClearFocusedItem();
55 | event.Skip();
56 | }
57 |
58 | int FileTree::loadTree(const std::string& cwd, wxTreeItemId parent) {
59 | int numFiles = 0;
60 | for (const auto & file : std::filesystem::directory_iterator(cwd)) {
61 | wxTreeItemId item = AppendItem(parent, file.path().filename().string());
62 | std::string ext = file.path().extension();
63 | if (!ext.empty() && ext[0] == '.') {
64 | ext.erase(0, 1);
65 | }
66 | if (std::filesystem::is_directory(file.path())) {
67 | int num = loadTree(file.path().string(), item);
68 | numFiles += num;
69 | SortChildren(item);
70 | SetItemBackgroundColour(item, wxColour(getDirectoryColor(num)));
71 | SetItemBold(item);
72 | }
73 | else {
74 | SetItemTextColour(item, getColorFromExtension(ext));
75 | ++numFiles;
76 | }
77 | }
78 | return numFiles;
79 | }
80 |
81 | // every time a file is added or deleted, reload tree
82 | void FileTree::reloadTree(void) {
83 | DeleteChildren(root);
84 | int numFiles = loadTree(cwd, root);
85 | SortChildren(root);
86 | SetItemBackgroundColour(root, getDirectoryColor(numFiles));
87 | Expand(root);
88 | }
89 |
90 | std::string FileTree::getRelPathFromItem(const wxTreeItemId& item) const {
91 | std::string absPath;
92 | wxTreeItemId id = item;
93 | while (id != root) {
94 | absPath.insert(0, GetItemText(id).ToStdString() + "/");
95 | id = GetItemParent(id);
96 | }
97 | if (!absPath.empty()) {
98 | absPath.pop_back();
99 | }
100 | return absPath;
101 | }
102 |
103 | wxColour FileTree::getColorFromExtension(const std::string& ext) const {
104 | std::hash h;
105 | unsigned int value = h(ext);
106 | unsigned int r = 255 - (value >> 16 & 0xff);
107 | unsigned int g = 255 - ((value >> 8) & 0xff);
108 | unsigned int b = 255 - (value & 0xff);
109 | r = (255 - r) / 10 * 3 + r;
110 | g = (255 - g) / 10 * 3 + g;
111 | b = (255 - b) / 10 * 3 + b;
112 | return wxColour(r, g, b);
113 | }
114 |
115 | wxColour FileTree::getDirectoryColor(const int& num) const {
116 | if (num == 0) {
117 | return wxColour(225, 191, 227);
118 | }
119 | if (num <= 10) {
120 | return wxColour(207, 109, 109);
121 | }
122 | if (num <= 30) {
123 | return wxColour(173, 173, 76);
124 | }
125 | if (num <= 50) {
126 | return wxColour(76, 173, 76);
127 | }
128 | if (num <= 70) {
129 | return wxColour(76, 173, 173);
130 | }
131 | return wxColour(102, 102, 232);
132 | }
133 |
134 | int FileTree::OnCompareItems(const wxTreeItemId& item1, const wxTreeItemId& item2) {
135 | std::string text1 = std::string(GetItemText(item1).mb_str());
136 | std::string text2 = std::string(GetItemText(item2).mb_str());
137 | std::string ext1 = FileHelper::getExtension(text1);
138 | std::string ext2 = FileHelper::getExtension(text2);
139 |
140 | if (ItemHasChildren(item1) && ItemHasChildren(item2)) {
141 | return text1.compare(text2);
142 | }
143 | else if (ItemHasChildren(item1) && !ItemHasChildren(item2)) {
144 | return -1;
145 | }
146 | else if (!ItemHasChildren(item1) && ItemHasChildren(item2)) {
147 | return 1;
148 | }
149 |
150 | if (FileHelper::isDotFile(text1) && FileHelper::isDotFile(text2)) {
151 | return text1.compare(text2);
152 | }
153 | else if (FileHelper::isDotFile(text1) && !FileHelper::isDotFile(text2)) {
154 | return -1;
155 | }
156 | else if (!FileHelper::isDotFile(text1) && FileHelper::isDotFile(text2)) {
157 | return 1;
158 | }
159 |
160 | if (ext1.empty() && ext2.empty()) {
161 | return text1.compare(text2);
162 | }
163 | else if (ext1.empty() && !ext2.empty()) {
164 | return -1;
165 | }
166 | else if (!ext1.empty() && ext2.empty()) {
167 | return 1;
168 | }
169 |
170 | if (ext1 == ext2) {
171 | return text1.compare(text2);
172 | }
173 | return ext1.compare(ext2);
174 | }
175 |
--------------------------------------------------------------------------------
/src/FileTree.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | class Frame;
9 | class Window;
10 |
11 | class FileTree : public wxTreeCtrl {
12 | public:
13 | FileTree(wxWindow *parent);
14 |
15 | Frame *getFrame(void) const;
16 | void reloadTree(void);
17 |
18 | private:
19 | void onActivate(wxTreeEvent& event);
20 | void onKillFocus(wxFocusEvent& event);
21 | void onClick(wxMouseEvent& event);
22 |
23 | int loadTree(const std::string& cwd, wxTreeItemId parent);
24 | std::string getRelPathFromItem(const wxTreeItemId& item) const;
25 | wxColour getColorFromExtension(const std::string& ext) const;
26 | wxColour getDirectoryColor(const int& num) const;
27 |
28 | int OnCompareItems(const wxTreeItemId& item1, const wxTreeItemId& item2);
29 |
30 | std::string cwd;
31 | wxTreeItemId root;
32 | };
33 |
--------------------------------------------------------------------------------
/src/Frame.cpp:
--------------------------------------------------------------------------------
1 | #include "Frame.h"
2 |
3 | Frame::Frame(const wxSize& size) : wxFrame(NULL, wxID_ANY, "Gadget", wxDefaultPosition, size) {
4 | SetBackgroundColour(wxColour(54, 54, 54));
5 | sizer = new wxBoxSizer(wxHORIZONTAL);
6 |
7 | cwd = std::filesystem::current_path().string() + "/";
8 |
9 | window = new Window(this);
10 | tree = new FileTree(this);
11 |
12 | sizer->Add(tree, 1, wxEXPAND | wxALL, 0);
13 | sizer->Add(window, 3, wxEXPAND | wxALL, 0);
14 |
15 | SetSizerAndFit(sizer);
16 | SetSize(size);
17 | }
18 |
--------------------------------------------------------------------------------
/src/Frame.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 |
6 | #include "Window.h"
7 |
8 | class Frame : public wxFrame {
9 | public:
10 | Frame(const wxSize& size);
11 |
12 | Window *window;
13 | FileTree *tree;
14 |
15 | std::string cwd;
16 |
17 | private:
18 | wxBoxSizer *sizer;
19 | };
20 |
--------------------------------------------------------------------------------
/src/Gadget.cpp:
--------------------------------------------------------------------------------
1 | #include "Gadget.h"
2 | #include "Frame.h"
3 | #include "res/gadget.xpm"
4 |
5 | bool Gadget::OnInit() {
6 | wxSize s = wxGetDisplaySize();
7 | s.Scale(0.5, 0.5);
8 |
9 | Frame *f = new Frame(s);
10 | f->Show(true);
11 |
12 | wxIcon icon(gadget_icon);
13 | f->SetIcon(icon);
14 |
15 | return true;
16 | }
17 |
18 | wxIMPLEMENT_APP(Gadget);
19 |
--------------------------------------------------------------------------------
/src/Gadget.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | class Gadget : public wxApp {
6 | public:
7 | // App startup
8 | virtual bool OnInit();
9 | };
10 |
--------------------------------------------------------------------------------
/src/HelpFile.cpp:
--------------------------------------------------------------------------------
1 | #include "Window.h"
2 | #include "FileHelper.h"
3 |
4 | HelpFile::HelpFile(wxWindow *parent) : Editor(parent, NULL_LEX) {
5 | SetLexer(wxSTC_LEX_LUA);
6 |
7 | StyleSetForeground(wxSTC_LUA_WORD4, wxColor(209, 73, 94));
8 | StyleSetForeground(wxSTC_LUA_WORD5, wxColor(219, 131, 0));
9 | StyleSetForeground(wxSTC_LUA_WORD6, wxColor(120, 161, 109));
10 | StyleSetForeground(wxSTC_LUA_WORD7, wxColor(147, 196, 82));
11 | StyleSetForeground(wxSTC_LUA_WORD8, wxColor(222, 149, 222));
12 |
13 | SetKeyWords(3, wxT("Gadget"));
14 | SetKeyWords(4, wxT("NORMAL"));
15 | SetKeyWords(5, wxT("EDIT"));
16 | SetKeyWords(6, wxT("VISUAL"));
17 | SetKeyWords(7, wxT("LINE"));
18 |
19 | AddText(
20 | "Welcome to the Gadget help file!\n"
21 | "This file is read-only\n\n"
22 |
23 | "Gadget is a GUI text editor inspired by GVim, the interface variant of the popular text editor, Vim.\n\n"
24 |
25 | "Gadget features four modes: NORMAL EDIT VISUAL and LINE\n\n"
26 |
27 | "~~~~~~~~~~~~\nNORMAL MODE:\n~~~~~~~~~~~~\n\n"
28 |
29 | "hjkl\n\t\t\t\th - left, j - down, k - up, l - right; can be prepended with [num]\n"
30 | "w\n\t\t\t\tjump forward to the start of the next word; can be prepended with [num]\n"
31 | "b\n\t\t\t\tjump backward to the start of the previous word; can be prepended with [num]\n"
32 | "gg\n\t\t\t\tjump to the beginning of the file\n"
33 | "G\n\t\t\t\tjump to the end of the file\n"
34 | "[num]G\n\t\t\t\tjump to the beginning of the line indicated by [num]\n"
35 | "_\n\t\t\t\tjump to the first non-whitespace character of the current line\n"
36 | "0\n\t\t\t\tjump to the beginning of the current line\n"
37 | "$\n\t\t\t\tjump to the end of the current line\n"
38 | "x\n\t\t\t\tcuts the character the caret is currently on\n"
39 | "o\n\t\t\t\tappend an empty line below the current line; can be prepended with [num]\n"
40 | "O\n\t\t\t\tappend an empty line above the current line; can be prepended with [num]\n"
41 | "dd\n\t\t\t\tcut a line; can be prepended with [num]\n"
42 | "D\n\t\t\t\tcut to the end of the current line\n"
43 | "f [char]\n\t\t\t\tjump to the next instance of [char] on the current line\n"
44 | "F [char]\n\t\t\t\tjump to the previous instance of [char] on the current line\n"
45 | "t [char]\n\t\t\t\tjump just before the next instance of [char] on the current line\n"
46 | "T [char]\n\t\t\t\tjump just after the previous instance of [char] on the current line\n"
47 | "p\n\t\t\t\tpaste the contents of the clipboard after the caret\n"
48 | "P\n\t\t\t\tpaste the contents of the clipboard before the caret\n"
49 | "[num]gt\n\t\t\t\tswitch to the tab indicated by [num]\n"
50 | "i\n\t\t\t\tswitch to EDIT mode\n"
51 | "I\n\t\t\t\tswitch to EDIT mode and jump to the first non-whitespace character of the current line\n"
52 | "a\n\t\t\t\tswitch to EDIT mode and move caret right once\n"
53 | "A\n\t\t\t\tswitch to EDIT mode and jump to the end of the current line\n"
54 | "v\n\t\t\t\tswitch to VISUAL mode\n"
55 | "V\n\t\t\t\tswitch to LINE mode\n"
56 | ":q\n\t\t\t\tquit and close the buffer\n"
57 | ":w\n\t\t\t\tsave the buffer to the file it points to; can be postpended by [string] to specify a file\n"
58 | ":wq\n\t\t\t\tsave and close the buffer\n"
59 | ":e [string]\n\t\t\t\tedit a new file indicated by [string] in the current buffer\n"
60 | ":tabedit\n\t\t\t\topen a new buffer; can be postpended by [string] to specify a file\n"
61 | ":split\n\t\t\t\tsplit the window horizontally\n"
62 | ":vsplit\n\t\t\t\tsplit the window vertically\n"
63 | ":help\n\t\t\t\topen the help file\n\n"
64 |
65 | "~~~~~~~~~~~~\nVISUAL MODE:\n~~~~~~~~~~~~\n\n"
66 |
67 | "hjkl\n\t\t\t\textend the selection left, down, up, or right; can be prepended with [num]\n"
68 | "w\n\t\t\t\textend the selection to the start of the next word; can be prepended with [num]\n"
69 | "b\n\t\t\t\textend the selection to the start of the previous word; can be prepended with [num]\n"
70 | "gg\n\t\t\t\textend the selection to the beginning of the file\n"
71 | "G\n\t\t\t\textend the selection to the end of the file\n"
72 | "[num]G\n\t\t\t\textend the selection to the beginning of the line indicated by [num]\n"
73 | "_\n\t\t\t\textend the selection to the first non-whitespace character of the current line\n"
74 | "0\n\t\t\t\textend the selection to the beginning of the current line\n"
75 | "$\n\t\t\t\textend the selection to the end of the current line\n"
76 | "x\n\t\t\t\tcuts the selection\n"
77 | "d\n\t\t\t\tsame as x\n"
78 | "f [char]\n\t\t\t\textend the selection to the next instance of [char] on the current line\n"
79 | "F [char]\n\t\t\t\textend the selection to the previous instance of [char] on the current line\n"
80 | "t [char]\n\t\t\t\textend the selection just before the next instance of [char] on the current line\n"
81 | "T [char]\n\t\t\t\textend the selection just after the previous instance of [char] on the current line\n"
82 | "u\n\t\t\t\tswitch selection to lowercase\n"
83 | "U\n\t\t\t\tswitch selection to uppercase\n"
84 | "y\n\t\t\t\tcopy the selection to the clipboard\n\n"
85 |
86 | "~~~~~~~~~~\nLINE MODE:\n~~~~~~~~~~\n\n"
87 |
88 | "jk\n\t\t\t\textend the line selection down or up; can be prepended with [num]\n"
89 | "gg\n\t\t\t\textend the line selection to the beginning of the file\n"
90 | "G\n\t\t\t\textend the line selection to the end of the file\n"
91 | "[num]G\n\t\t\t\textend the line selection to the beginning of the line indicated by [num]\n"
92 | "x\n\t\t\t\tcuts the line selection\n"
93 | "d\n\t\t\t\tsame as x\n"
94 | "u\n\t\t\t\tswitch line selection to lowercase\n"
95 | "U\n\t\t\t\tswitch line selection to uppercase\n"
96 | "y\n\t\t\t\tcopy the line selection to the clipboard\n"
97 | "<\n\t\t\t\tshift the lines selected to the left; can be prepended with [num]\n"
98 | ">\n\t\t\t\tshift the lines selected to the right; can be prepended with [num]\n\n"
99 | );
100 |
101 | SetEditable(false);
102 | SetReadOnly(true);
103 | }
104 |
--------------------------------------------------------------------------------
/src/HelpFile.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | class Window;
6 |
7 | class HelpFile : public Editor {
8 | public:
9 | HelpFile(wxWindow *parent);
10 | };
11 |
--------------------------------------------------------------------------------
/src/Panel.cpp:
--------------------------------------------------------------------------------
1 | #include "Frame.h"
2 | #include "Window.h"
3 | #include "Panel.h"
4 | #include "FileHelper.h"
5 |
6 | Panel::Panel(wxWindow *parent) : wxAuiNotebook(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxAUI_NB_DEFAULT_STYLE) {
7 | SetBackgroundColour(wxColour(54, 54, 54));
8 | tabArt = new wxAuiSimpleTabArt();
9 | tabArt->SetColour(wxColour(77, 77, 77));
10 | tabArt->SetActiveColour(wxColour(227, 73, 73));
11 |
12 | SetArtProvider(tabArt);
13 |
14 | AddPage(new Editor(this, NULL_LEX), "[NO FILE]");
15 | AddPage(new Editor(this, NULL_LEX), "[NO FILE]");
16 | AddPage(new Editor(this, NULL_LEX), "[NO FILE]");
17 | // indicate it's a new file
18 |
19 | Bind(wxEVT_AUINOTEBOOK_PAGE_CHANGED, &Panel::onTabChange, this);
20 | Bind(wxEVT_AUINOTEBOOK_PAGE_CLOSED, &Panel::onTabRemove, this);
21 | }
22 |
23 | Window *Panel::getWindow(void) {
24 | return (Window *)GetParent();
25 | }
26 |
27 | void Panel::onTabChange(wxAuiNotebookEvent& event) {
28 | Window *w = getWindow();
29 | w->currEditor = event.GetSelection();
30 |
31 | w->command->clear();
32 | w->commandBar->Clear();
33 |
34 | // call window update status bar
35 | w->updateStatus();
36 | }
37 |
38 | void Panel::onTabRemove(wxAuiNotebookEvent& event) {
39 | Window *w = getWindow();
40 |
41 | w->command->clear();
42 | w->commandBar->Clear();
43 |
44 | if (GetPageCount() == 0) {
45 | w->getFrame()->Destroy();
46 | }
47 | }
48 |
49 | void Panel::deleteCurr(void) {
50 | DeletePage(GetSelection());
51 | if (GetPageCount() == 0) {
52 | getWindow()->getFrame()->Destroy();
53 | }
54 | }
55 |
56 | void Panel::setTab(const int& ind) {
57 | if (ind <= 0 || ind > GetPageCount()) {
58 | return;
59 | }
60 | SetSelection(ind - 1);
61 | }
62 |
--------------------------------------------------------------------------------
/src/Panel.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 |
6 | class Frame;
7 | class Window;
8 |
9 | #include "Editor.h"
10 |
11 | class Panel : public wxAuiNotebook {
12 | public:
13 | Panel(wxWindow *parent);
14 |
15 | Window *getWindow(void);
16 |
17 | void deleteCurr(void);
18 | void setTab(const int& ind);
19 |
20 | private:
21 | void onTabChange(wxAuiNotebookEvent& event);
22 | void onTabRemove(wxAuiNotebookEvent& event);
23 |
24 | wxAuiSimpleTabArt *tabArt;
25 | };
26 |
--------------------------------------------------------------------------------
/src/StatusBar.cpp:
--------------------------------------------------------------------------------
1 | #include "StatusBar.h"
2 |
3 | StatusBar::StatusBar(wxWindow *parent) : wxWindow(parent, wxID_ANY, wxDefaultPosition, wxSize(wxGetDisplaySize().GetWidth()/2, 30)) {
4 | wxFont *font = new wxFont(10, wxFONTFAMILY_TELETYPE, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxEmptyString);
5 | SetFont(*font);
6 |
7 | sizer = new wxBoxSizer(wxHORIZONTAL);
8 |
9 | modeDisplay = new StatusSection(this, wxSize(90, 30), wxSize(90, 30), wxColour(219, 131, 0), wxColour(0, 0, 0));
10 | modeDisplay->setText(" ~NORMAL~");
11 |
12 | pathDisplay = new StatusSection(this, wxSize(90, 30), parent->GetMaxClientSize(), wxColour(214, 141, 141), wxColour(227, 11, 11));
13 | pathDisplay->setText("[NO FILE]");
14 |
15 | positionDisplay = new StatusSection(this, wxSize(90, 30), wxSize(150, 30), wxColour(171, 141, 214), wxColour(0, 12, 4));
16 | positionDisplay->setText("1,1 | 100%");
17 |
18 | sizeDisplay = new StatusSection(this, wxSize(150, 30), wxSize(210, 30), wxColour(136, 178, 194), wxColour(13, 77, 122));
19 | sizeDisplay->setText("0 bytes | 1 lines");
20 |
21 | sizer->Add(modeDisplay, 1, wxEXPAND | wxALL, 0);
22 | sizer->Add(pathDisplay, 2, wxEXPAND | wxALL, 0);
23 | sizer->Add(positionDisplay, 1, wxEXPAND | wxALL, 0);
24 | sizer->Add(sizeDisplay, 2, wxEXPAND | wxALL, 0);
25 |
26 | SetSizer(sizer);
27 | }
28 |
--------------------------------------------------------------------------------
/src/StatusBar.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | #include "StatusSection.h"
6 |
7 | class StatusBar : public wxWindow {
8 | public:
9 | StatusBar(wxWindow *parent);
10 |
11 | StatusSection *modeDisplay;
12 | StatusSection *pathDisplay;
13 | StatusSection *positionDisplay;
14 | StatusSection *sizeDisplay;
15 |
16 | private:
17 | wxBoxSizer *sizer;
18 | };
19 |
--------------------------------------------------------------------------------
/src/StatusSection.cpp:
--------------------------------------------------------------------------------
1 | #include "StatusSection.h"
2 |
3 | StatusSection::StatusSection(wxWindow *parent, wxSize minSize, wxSize maxSize, wxColour background, wxColour foreground) : wxRichTextCtrl(parent) {
4 | SetEditable(false);
5 | EnableVerticalScrollbar(false);
6 |
7 | SetMinClientSize(minSize);
8 | SetMaxClientSize(maxSize);
9 |
10 | setForeground(foreground);
11 | setBackground(background);
12 |
13 | Bind(wxEVT_LEFT_DOWN, &StatusSection::onClick, this);
14 | Bind(wxEVT_RIGHT_DOWN, &StatusSection::onClick, this);
15 | }
16 |
17 | void StatusSection::onClick(wxMouseEvent& event) {
18 | event.Skip(false);
19 | }
20 |
21 | void StatusSection::setText(const std::string& text) {
22 | Clear();
23 | AppendText(text);
24 | }
25 |
26 | void StatusSection::setForeground(const wxColour& colour) {
27 | wxRichTextAttr attr = GetBasicStyle();
28 | attr.SetTextColour(colour);
29 | SetBasicStyle(attr);
30 | }
31 |
32 | void StatusSection::setBackground(const wxColour& colour) {
33 | SetBackgroundColour(colour);
34 | }
35 |
36 | wxColour StatusSection::getForeground(void) const {
37 | return GetBasicStyle().GetTextColour();
38 | }
39 |
40 | wxColour StatusSection::getBackground(void) const {
41 | return GetBackgroundColour();
42 | }
43 |
--------------------------------------------------------------------------------
/src/StatusSection.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 |
6 | class StatusSection : public wxRichTextCtrl {
7 | public:
8 | StatusSection(wxWindow *parent, wxSize minSize, wxSize maxSize, wxColour background, wxColour foreground);
9 |
10 | void setText(const std::string& text);
11 | void setForeground(const wxColour& colour);
12 | void setBackground(const wxColour& colour);
13 | wxColour getForeground(void) const;
14 | wxColour getBackground(void) const;
15 |
16 | private:
17 | void onClick(wxMouseEvent& event);
18 | };
19 |
--------------------------------------------------------------------------------
/src/Window.cpp:
--------------------------------------------------------------------------------
1 | #include "Window.h"
2 | #include "Frame.h"
3 | #include "FileHelper.h"
4 |
5 | Window::Window(wxWindow *parent) : wxWindow(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize) {
6 | SetMinClientSize(wxSize(500, 100));
7 |
8 | sizer = new wxBoxSizer(wxVERTICAL);
9 |
10 | panel = new Panel(this);
11 | statusBar = new StatusBar(this);
12 | commandBar = new CommandBar(this);
13 |
14 | sizer->Add(panel, 1, wxEXPAND | wxALL, 0);
15 | sizer->Add(statusBar, 0, wxEXPAND | wxALL, -3);
16 | sizer->Add(commandBar, 0, wxEXPAND | wxALL, 0);
17 |
18 | SetSizer(sizer);
19 |
20 | command = new Command();
21 |
22 | mode = NORMAL_MODE;
23 | currEditor = 0;
24 | lastCopiedMode = EDIT_MODE;
25 | }
26 |
27 | Frame *Window::getFrame(void) const {
28 | return (Frame *)GetParent();
29 | }
30 |
31 | Editor *Window::getCurrentEditor(void) const {
32 | return (Editor *)panel->GetPage(currEditor);
33 | }
34 |
35 | void Window::executeNormal(const int& cmdInd) {
36 | switch(cmdInd) {
37 | case 0:
38 | doInsertion();
39 | break;
40 | case 1:
41 | doBasicMovement();
42 | break;
43 | case 2:
44 | doNewLine();
45 | break;
46 | case 3:
47 | doIntraLineJump();
48 | break;
49 | case 4:
50 | doInterLineJump();
51 | break;
52 | case 5:
53 | doTabChange();
54 | break;
55 | case 6:
56 | doWordJump();
57 | break;
58 | case 7:
59 | doCharSearch();
60 | break;
61 | case 8:
62 | doVisualMode();
63 | break;
64 | case 9:
65 | doLineMode();
66 | break;
67 | case 10:
68 | doPaste();
69 | break;
70 | case 11:
71 | doVisOrLineOrNormalDelete();
72 | break;
73 | case 12:
74 | doLineCut();
75 | break;
76 | }
77 | command->clear();
78 | commandBar->Clear();
79 | updateStatus();
80 | }
81 |
82 | void Window::executeCommand(const int& cmdInd) {
83 | switch(cmdInd) {
84 | case 0:
85 | doQuitFile();
86 | break;
87 | case 1:
88 | doSaveFile();
89 | break;
90 | case 2:
91 | doOpenFile();
92 | break;
93 | case 3:
94 | doNewTab();
95 | break;
96 | case 4:
97 | doSplitTab();
98 | break;
99 | case 5:
100 | doOpenHelpFile();
101 | break;
102 | }
103 | command->clear();
104 | commandBar->Clear();
105 | updateStatus();
106 | }
107 |
108 | void Window::executeVisual(const int& cmdInd) {
109 | switch(cmdInd) {
110 | case 0:
111 | doBasicVisMovement();
112 | break;
113 | case 1:
114 | doVisOrLineOrNormalDelete();
115 | break;
116 | case 2:
117 | doVisOrLineCaseChange();
118 | break;
119 | case 3:
120 | doVisInterLineJump();
121 | break;
122 | case 4:
123 | doVisOrLineCopy();
124 | break;
125 | case 5:
126 | doVisWordJump();
127 | break;
128 | case 6:
129 | doVisIntraLineJump();
130 | break;
131 | case 7:
132 | doVisCharSearch();
133 | break;
134 | }
135 | command->clear();
136 | commandBar->Clear();
137 | updateStatus();
138 | }
139 |
140 | void Window::executeLine(const int& cmdInd) {
141 | switch(cmdInd) {
142 | case 0:
143 | doBasicLineMovement();
144 | break;
145 | case 1:
146 | doVisOrLineOrNormalDelete();
147 | break;
148 | case 2:
149 | doVisOrLineCaseChange();
150 | break;
151 | case 3:
152 | doLineShift();
153 | break;
154 | case 4:
155 | doVisOrLineCopy();
156 | break;
157 | case 5:
158 | doLineInterLineJump();
159 | break;
160 | }
161 | command->clear();
162 | commandBar->Clear();
163 | updateStatus();
164 | }
165 |
166 | void Window::doInsertion(void) {
167 | Editor *e = getCurrentEditor();
168 |
169 | mode = EDIT_MODE;
170 |
171 | if (command->cmd == "a") {
172 | e->append();
173 | }
174 | else if (command->cmd == "A") {
175 | e->LineEnd();
176 | }
177 | else if (command->cmd == "I") {
178 | e->VCHome();
179 | }
180 | }
181 |
182 | void Window::doBasicMovement(void) {
183 | std::pair parsedCmd = command->parseNormal();
184 | Editor *e = getCurrentEditor();
185 |
186 | if (parsedCmd.second == "h") {
187 | e->caretLeft(parsedCmd.first);
188 | }
189 | else if (parsedCmd.second == "j") {
190 | e->caretDown(parsedCmd.first);
191 | }
192 | else if (parsedCmd.second == "k") {
193 | e->caretUp(parsedCmd.first);
194 | }
195 | else if (parsedCmd.second == "l") {
196 | e->caretRight(parsedCmd.first);
197 | }
198 | }
199 |
200 | void Window::doNewLine(void) {
201 | std::pair parsedCmd = command->parseNormal();
202 | Editor *e = getCurrentEditor();
203 |
204 | if (parsedCmd.second == "o") {
205 | e->insertLineBelow(parsedCmd.first);
206 | }
207 | else if (parsedCmd.second == "O") {
208 | e->insertLineAbove(parsedCmd.first);
209 | }
210 | }
211 |
212 | void Window::doIntraLineJump(void) {
213 | Editor *e = getCurrentEditor();
214 |
215 | if (command->cmd == "_") {
216 | e->VCHome();
217 | }
218 | else if (command->cmd == "$") {
219 | e->LineEnd();
220 | e->caretLeft(1);
221 | }
222 | else if (command->cmd == "0") {
223 | e->Home();
224 | }
225 | }
226 |
227 | void Window::doInterLineJump(void) {
228 | Editor *e = getCurrentEditor();
229 |
230 | if (command->cmd == "gg") {
231 | e->GotoLine(0);
232 | }
233 | else if (command->cmd == "G") {
234 | e->GotoLine(e->GetLineCount() - 1);
235 | }
236 | else {
237 | std::pair parsedCmd = command->parseNormal();
238 | e->GotoLine(parsedCmd.first - 1);
239 | }
240 | }
241 |
242 | void Window::doTabChange(void) {
243 | std::pair parsedCmd = command->parseNormal();
244 | if (parsedCmd.first != panel->GetSelection() + 1) {
245 | panel->setTab(parsedCmd.first);
246 | }
247 | }
248 |
249 | void Window::doWordJump(void) {
250 | std::pair parsedCmd = command->parseNormal();
251 | Editor *e = getCurrentEditor();
252 |
253 | if (parsedCmd.second == "w") {
254 | e->wordRight(parsedCmd.first);
255 | }
256 | else {
257 | e->wordLeft(parsedCmd.first);
258 | }
259 | }
260 |
261 | void Window::doCharSearch(void) {
262 | Editor *e = getCurrentEditor();
263 |
264 | if (command->cmd[0] == 'f') {
265 | e->charSearchAhead(command->cmd[1], 1);
266 | }
267 | else if (command->cmd[0] == 'F') {
268 | e->charSearchBehind(command->cmd[1], 1);
269 | }
270 | else if (command->cmd[0] == 't') {
271 | e->charSearchAhead(command->cmd[1], 0);
272 | }
273 | else if (command->cmd[0] == 'T') {
274 | e->charSearchBehind(command->cmd[1], 0);
275 | }
276 | }
277 |
278 | void Window::doVisualMode(void) {
279 | mode = VISUAL_MODE;
280 | }
281 |
282 | void Window::doLineMode(void) {
283 | Editor *e = getCurrentEditor();
284 |
285 | mode = LINE_MODE;
286 |
287 | e->SetAnchor(e->lineStartPos());
288 | e->SetCurrentPos(e->lineEndPos());
289 | }
290 |
291 | void Window::doPaste(void) {
292 | Editor *e = getCurrentEditor();
293 |
294 | if (lastCopiedMode == EDIT_MODE) {
295 | return;
296 | }
297 | if (lastCopiedMode == VISUAL_MODE || lastCopiedMode == NORMAL_MODE) {
298 | if (command->cmd == "p") {
299 | e->CharRight();
300 | }
301 | e->Paste();
302 | }
303 | else if (lastCopiedMode == LINE_MODE) {
304 | if (command->cmd == "P") {
305 | e->Home();
306 | e->NewLine();
307 | e->caretUp(1);
308 | e->Paste();
309 | }
310 | else if (command->cmd == "p") {
311 | e->LineEnd();
312 | e->NewLine();
313 | e->Paste();
314 | }
315 | std::string line = std::string(e->GetCurLine().mb_str());
316 | if (line.empty() || line == "\n") {
317 | e->DeleteBack();
318 | }
319 | e->VCHome();
320 | }
321 | }
322 |
323 | void Window::doLineCut(void) {
324 | Editor *e = getCurrentEditor();
325 |
326 | if (command->cmd == "D") {
327 | e->cutToLineEnd();
328 | lastCopiedMode = NORMAL_MODE;
329 | }
330 | else {
331 | std::pair parsedCmd = command->parseNormal();
332 |
333 | e->cutLines(parsedCmd.first);
334 | lastCopiedMode = LINE_MODE;
335 | }
336 | mode = NORMAL_MODE;
337 | }
338 |
339 | void Window::doQuitFile(void) {
340 | // later: check if curr editor saved before exiting
341 | panel->deleteCurr();
342 | }
343 |
344 | void Window::doSaveFile(void) {
345 | std::vector parsedCmd = command->parseCommand();
346 | Editor *e = getCurrentEditor();
347 |
348 | if (parsedCmd.size() == 1) {
349 | if (e->relPath == "") {
350 | // later this should display an error: editor has no file
351 | return;
352 | }
353 | }
354 | else {
355 | if (FileHelper::isValidPath(getFrame()->cwd, parsedCmd[1])) {
356 | e->relPath = parsedCmd[1];
357 | panel->SetPageText(currEditor, parsedCmd[1]);
358 | }
359 | else {
360 | // also display error
361 | return;
362 | }
363 | }
364 | if (FileHelper::isValidPath(getFrame()->cwd, e->relPath)) {
365 | if (!FileHelper::isExistingPath(getFrame()->cwd, e->relPath)) {
366 | // reload file tree
367 | e->SaveFile(getFrame()->cwd + e->relPath);
368 | getFrame()->tree->reloadTree();
369 | }
370 | else {
371 | e->SaveFile(getFrame()->cwd + e->relPath);
372 | }
373 | e->saved = true;
374 | }
375 | if (parsedCmd[0] == "wq") {
376 | panel->deleteCurr();
377 | }
378 | }
379 |
380 | void Window::doOpenFile(void) {
381 | std::vector parsedCmd = command->parseCommand();
382 | Editor *e = getCurrentEditor();
383 |
384 | // later: check if curr editor saved before replacing
385 | if (FileHelper::isValidPath(getFrame()->cwd, parsedCmd[1])) {
386 | e->relPath = parsedCmd[1];
387 | panel->SetPageText(currEditor, parsedCmd[1]);
388 | e->SetEditable(true);
389 | e->SetReadOnly(false);
390 | e->ClearAll();
391 | int lexer = FileHelper::getLexerFromExtension(e->relPath);
392 | e->applyLexer(lexer);
393 | if (FileHelper::isExistingPath(getFrame()->cwd, parsedCmd[1])) {
394 | e->loadFormatted(getFrame()->cwd + e->relPath);
395 | if (FileHelper::isReadOnlyFile(getFrame()->cwd, e->relPath)) {
396 | e->SetEditable(false);
397 | e->SetReadOnly(true);
398 | e->readOnly = true;
399 | }
400 | else {
401 | e->readOnly = false;
402 | }
403 | e->saved = true;
404 | }
405 | // else indicate that it's a new file
406 | }
407 | }
408 |
409 | void Window::doNewTab(void) {
410 | std::vector parsedCmd = command->parseCommand();
411 |
412 | if (parsedCmd.size() == 1) {
413 | panel->AddPage(new Editor(panel, NULL_LEX), "[NO FILE]", true);
414 | return;
415 | }
416 | for (int i = 1; i < parsedCmd.size(); ++i) {
417 | if (!FileHelper::isValidPath(getFrame()->cwd, parsedCmd[i])) {
418 | continue;
419 | }
420 | int lexer = FileHelper::getLexerFromExtension(parsedCmd[i]);
421 | panel->AddPage(new Editor(panel, lexer), parsedCmd[i], true);
422 | Editor *e = getCurrentEditor();
423 | e->relPath = parsedCmd[i];
424 | if (FileHelper::isExistingPath(getFrame()->cwd, parsedCmd[i])) {
425 | e->loadFormatted(getFrame()->cwd + e->relPath);
426 | if (FileHelper::isReadOnlyFile(getFrame()->cwd, e->relPath)) {
427 | e->SetEditable(false);
428 | e->SetReadOnly(true);
429 | e->readOnly = true;
430 | }
431 | else {
432 | e->readOnly = false;
433 | }
434 | e->saved = true;
435 | }
436 | }
437 | }
438 |
439 | void Window::doSplitTab(void) {
440 | if (command->cmd == "split") {
441 | panel->Split(currEditor, wxBOTTOM);
442 | }
443 | else {
444 | panel->Split(currEditor, wxRIGHT);
445 | }
446 | }
447 |
448 | void Window::doOpenHelpFile(void) {
449 | panel->AddPage(new HelpFile(panel), "Help", true);
450 | }
451 |
452 | void Window::doBasicVisMovement(void) {
453 | std::pair parsedCmd = command->parseNormal();
454 | Editor *e = getCurrentEditor();
455 |
456 | if (parsedCmd.second == "h") {
457 | e->caretLeftVis(parsedCmd.first);
458 | }
459 | else if (parsedCmd.second == "j") {
460 | e->caretDownVis(parsedCmd.first);
461 | }
462 | else if (parsedCmd.second == "k") {
463 | e->caretUpVis(parsedCmd.first);
464 | }
465 | else if (parsedCmd.second == "l") {
466 | e->caretRightVis(parsedCmd.first);
467 | }
468 | }
469 |
470 | void Window::doVisOrLineOrNormalDelete(void) {
471 | Editor *e = getCurrentEditor();
472 |
473 | lastCopiedMode = mode;
474 | e->cutSelection();
475 | mode = NORMAL_MODE;
476 | }
477 |
478 | void Window::doVisOrLineCaseChange(void) {
479 | Editor *e = getCurrentEditor();
480 |
481 | if (command->cmd == "u") {
482 | e->caseChangeSelection(false);
483 | }
484 | else if (command->cmd == "U") {
485 | e->caseChangeSelection(true);
486 | }
487 |
488 | e->removeSelection();
489 | mode = NORMAL_MODE;
490 | }
491 |
492 | void Window::doVisInterLineJump(void) {
493 | Editor *e = getCurrentEditor();
494 |
495 | if (command->cmd == "gg") {
496 | e->jumpStartVis();
497 | }
498 | else if (command->cmd == "G") {
499 | e->jumpEndVis();
500 | }
501 | else {
502 | std::pair parsedCmd = command->parseNormal();
503 | e->jumpLineVis(parsedCmd.first - 1);
504 | }
505 | }
506 |
507 | void Window::doVisOrLineCopy(void) {
508 | Editor *e = getCurrentEditor();
509 |
510 | lastCopiedMode = mode;
511 | e->copySelection();
512 | e->removeSelection();
513 | mode = NORMAL_MODE;
514 | }
515 |
516 | void Window::doVisWordJump(void) {
517 | std::pair parsedCmd = command->parseNormal();
518 | Editor *e = getCurrentEditor();
519 |
520 | if (parsedCmd.second == "w") {
521 | e->wordRightVis(parsedCmd.first);
522 | }
523 | else {
524 | e->wordLeftVis(parsedCmd.first);
525 | }
526 | }
527 |
528 | void Window::doVisIntraLineJump(void) {
529 | Editor *e = getCurrentEditor();
530 |
531 | if (command->cmd == "_") {
532 | e->lineHomeVis();
533 | }
534 | else if (command->cmd == "$") {
535 | e->lineEndVis();
536 | }
537 | else if (command->cmd == "0") {
538 | e->lineStartVis();
539 | }
540 | }
541 |
542 | void Window::doVisCharSearch(void) {
543 | Editor *e = getCurrentEditor();
544 |
545 | if (command->cmd[0] == 'f') {
546 | e->charSearchAheadVis(command->cmd[1], 1);
547 | }
548 | else if (command->cmd[0] == 'F') {
549 | e->charSearchBehindVis(command->cmd[1], 1);
550 | }
551 | else if (command->cmd[0] == 't') {
552 | e->charSearchAheadVis(command->cmd[1], 0);
553 | }
554 | else if (command->cmd[0] == 'T') {
555 | e->charSearchBehindVis(command->cmd[1], 0);
556 | }
557 | }
558 |
559 | void Window::doBasicLineMovement(void) {
560 | std::pair parsedCmd = command->parseNormal();
561 | Editor *e = getCurrentEditor();
562 |
563 | if (parsedCmd.second == "j") {
564 | e->caretDownLine(parsedCmd.first);
565 | }
566 | else if (parsedCmd.second == "k") {
567 | e->caretUpLine(parsedCmd.first);
568 | }
569 | }
570 |
571 | void Window::doLineShift(void) {
572 | std::pair parsedCmd = command->parseNormal();
573 | Editor *e = getCurrentEditor();
574 |
575 | if (parsedCmd.second == "<") {
576 | e->shiftLine(parsedCmd.first, 0);
577 | }
578 | else if (parsedCmd.second == ">") {
579 | e->shiftLine(parsedCmd.first, 1);
580 | }
581 |
582 | e->removeSelection();
583 | mode = NORMAL_MODE;
584 | }
585 |
586 | void Window::doLineInterLineJump(void) {
587 | Editor *e = getCurrentEditor();
588 |
589 | if (command->cmd == "gg") {
590 | e->jumpStartLine();
591 | }
592 | else if (command->cmd == "G") {
593 | e->jumpEndLine();
594 | }
595 | else {
596 | std::pair parsedCmd = command->parseNormal();
597 | e->jumpLineLine(parsedCmd.first - 1);
598 | }
599 | }
600 |
601 | void Window::updateStatus(void) {
602 | if (panel->GetPageCount() == 0) {
603 | return;
604 | }
605 | Editor *e = getCurrentEditor();
606 |
607 | if (mode == NORMAL_MODE) {
608 | statusBar->modeDisplay->setText(" ~NORMAL~");
609 | statusBar->modeDisplay->setBackground(wxColour(219, 131, 0));
610 | e->SetCaretForeground(wxColour(219, 131, 0));
611 | }
612 | else if (mode == EDIT_MODE) {
613 | statusBar->modeDisplay->setText(" ~EDIT~");
614 | statusBar->modeDisplay->setBackground(wxColour(120, 161, 109));
615 | e->SetCaretForeground(wxColour(120, 161, 109));
616 | }
617 | else if (mode == VISUAL_MODE) {
618 | statusBar->modeDisplay->setText(" ~VISUAL~");
619 | statusBar->modeDisplay->setBackground(wxColour(147, 196, 82));
620 | e->SetCaretForeground(wxColour(147, 196, 82));
621 | }
622 | else if (mode == LINE_MODE) {
623 | statusBar->modeDisplay->setText(" ~LINE~");
624 | statusBar->modeDisplay->setBackground(wxColour(222, 149, 222));
625 | e->SetCaretForeground(wxColour(222, 149, 222));
626 | }
627 |
628 | if (e->relPath == "") {
629 | statusBar->pathDisplay->setText("[NO FILE]");
630 | statusBar->pathDisplay->setForeground(wxColour(227, 11, 11));
631 | statusBar->pathDisplay->setBackground(wxColour(214, 141, 141));
632 | }
633 | else {
634 | std::string pathText = getFrame()->cwd + e->relPath;
635 | std::string panelText = std::string(panel->GetPageText(currEditor).mb_str());
636 | if (!e->saved) {
637 | pathText += "***";
638 | statusBar->pathDisplay->setForeground(wxColour(82, 7, 7));
639 | statusBar->pathDisplay->setBackground(wxColour(214, 141, 141));
640 | statusBar->pathDisplay->BeginBold();
641 | statusBar->pathDisplay->setText(pathText);
642 | statusBar->pathDisplay->EndBold();
643 |
644 | if (panelText[0] != '*') {
645 | panel->SetPageText(currEditor, "*" + panelText);
646 | }
647 | }
648 | else {
649 | statusBar->pathDisplay->setForeground(wxColour(82, 7, 7));
650 | statusBar->pathDisplay->setBackground(wxColour(214, 141, 141));
651 | statusBar->pathDisplay->setText(pathText);
652 |
653 | if (panelText[0] == '*') {
654 | panel->SetPageText(currEditor, panelText.substr(1, panelText.size()-1));
655 | }
656 | }
657 | if (e->readOnly) {
658 | statusBar->pathDisplay->AppendText(" [R]");
659 | }
660 | }
661 |
662 | int curr = e->currLine() + 1;
663 | int len = e->GetLineCount();
664 | int percent = (int)((double)curr * 100 / len);
665 | statusBar->positionDisplay->setText(std::to_string(curr) + "," + std::to_string(e->linePos() + 1) + " | " + std::to_string(percent) + "%");
666 | wxColour colour = statusBar->positionDisplay->getForeground();
667 | colour.Set(255 - (int)((double)percent * 2.55), 12, 174 - (int)((double)percent * 1.7));
668 | statusBar->positionDisplay->setForeground(colour);
669 |
670 | statusBar->sizeDisplay->setText(std::to_string(e->GetLength()) + " bytes | " + std::to_string(len) + " lines");
671 | }
672 |
--------------------------------------------------------------------------------
/src/Window.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | class Frame;
6 |
7 | #include "Panel.h"
8 | #include "FileTree.h"
9 | #include "CommandBar.h"
10 | #include "Command.h"
11 | #include "StatusBar.h"
12 | #include "HelpFile.h"
13 |
14 | #define NORMAL_MODE 0
15 | #define EDIT_MODE 1
16 | #define VISUAL_MODE 2
17 | #define LINE_MODE 3
18 |
19 | class Window : public wxWindow {
20 | public:
21 | Window(wxWindow *parent);
22 |
23 | Frame *getFrame(void) const;
24 | Editor *getCurrentEditor(void) const;
25 | void executeNormal(const int& cmdInd);
26 | void executeCommand(const int& cmdInd);
27 | void executeVisual(const int& cmdInd);
28 | void executeLine(const int& cmdInd);
29 |
30 | void updateStatus(void);
31 |
32 | Panel *panel;
33 | StatusBar *statusBar;
34 | CommandBar *commandBar;
35 | Command *command;
36 |
37 | unsigned short mode;
38 | unsigned short currEditor;
39 | unsigned short lastCopiedMode;
40 |
41 | private:
42 | void doInsertion(void);
43 | void doBasicMovement(void);
44 | void doNewLine(void);
45 | void doIntraLineJump(void);
46 | void doInterLineJump(void);
47 | void doTabChange(void);
48 | void doWordJump(void);
49 | void doCharSearch(void);
50 | void doVisualMode(void);
51 | void doLineMode(void);
52 | void doPaste(void);
53 | void doLineCut(void);
54 |
55 | void doQuitFile(void);
56 | void doSaveFile(void);
57 | void doOpenFile(void);
58 | void doNewTab(void);
59 | void doSplitTab(void);
60 | void doOpenHelpFile(void);
61 |
62 | void doBasicVisMovement(void);
63 | void doVisOrLineOrNormalDelete(void);
64 | void doVisOrLineCaseChange(void);
65 | void doVisInterLineJump(void);
66 | void doVisOrLineCopy(void);
67 | void doVisWordJump(void);
68 | void doVisIntraLineJump(void);
69 | void doVisCharSearch(void);
70 |
71 | void doBasicLineMovement(void);
72 | void doLineShift(void);
73 | void doLineInterLineJump(void);
74 |
75 | wxBoxSizer *sizer;
76 | };
77 |
--------------------------------------------------------------------------------
/src/res/gadget.xpm:
--------------------------------------------------------------------------------
1 | /* XPM */
2 | static const char *gadget_icon[] = {
3 | /* columns rows colors chars-per-pixel */
4 | "39 39 220 2 ",
5 | " c None",
6 | ". c #3C2828",
7 | "X c #3C2829",
8 | "o c #3D2929",
9 | "O c #3E2A29",
10 | "+ c #3E2A2A",
11 | "@ c #3F2B2B",
12 | "# c #432B2A",
13 | "$ c #402C2C",
14 | "% c #412D2D",
15 | "& c #412E2D",
16 | "* c #412E2E",
17 | "= c #422E2E",
18 | "- c #432F2F",
19 | "; c #43302F",
20 | ": c #443030",
21 | "> c #443130",
22 | ", c #443131",
23 | "< c #453131",
24 | "1 c #463232",
25 | "2 c #473333",
26 | "3 c #473334",
27 | "4 c #483334",
28 | "5 c #483434",
29 | "6 c #493535",
30 | "7 c #4A3535",
31 | "8 c #4A3636",
32 | "9 c #4A3637",
33 | "0 c #4B3637",
34 | "q c #4B3737",
35 | "w c #4D3737",
36 | "e c #4C3838",
37 | "r c #4C3839",
38 | "t c #4D3939",
39 | "y c #4E3939",
40 | "u c #4E393A",
41 | "i c #4E3A3A",
42 | "p c #4F3B3B",
43 | "a c #513735",
44 | "s c #5E3A36",
45 | "d c #503B3B",
46 | "f c #513B3B",
47 | "g c #503C3C",
48 | "h c #503D3C",
49 | "j c #513D3D",
50 | "k c #523E3E",
51 | "l c #533F3F",
52 | "z c #543E3D",
53 | "x c #623735",
54 | "c c #673C37",
55 | "v c #5E413E",
56 | "b c #69443E",
57 | "n c #544040",
58 | "m c #554141",
59 | "M c #554242",
60 | "N c #564242",
61 | "B c #574343",
62 | "V c #5C4442",
63 | "C c #5E4443",
64 | "Z c #584444",
65 | "A c #594545",
66 | "S c #5A4646",
67 | "D c #5A4647",
68 | "F c #5B4747",
69 | "G c #5B4748",
70 | "H c #5C4848",
71 | "J c #5D4848",
72 | "K c #5D4948",
73 | "L c #5D4949",
74 | "P c #5D4A4A",
75 | "I c #5E4A4A",
76 | "U c #5F4A4A",
77 | "Y c #5F4B4B",
78 | "T c #634644",
79 | "R c #694642",
80 | "E c #694947",
81 | "W c #604C4C",
82 | "Q c #614D4D",
83 | "! c #624E4E",
84 | "~ c #634F4F",
85 | "^ c #644D4C",
86 | "/ c #6B4C4A",
87 | "( c #6E4F4E",
88 | ") c #714941",
89 | "_ c #784841",
90 | "` c #704C49",
91 | "' c #774F4C",
92 | "] c #784D48",
93 | "[ c #7E4F48",
94 | "{ c #7E524E",
95 | "} c #645050",
96 | "| c #655151",
97 | " . c #665252",
98 | ".. c #675353",
99 | "X. c #685353",
100 | "o. c #685454",
101 | "O. c #695555",
102 | "+. c #6A5656",
103 | "@. c #6B5656",
104 | "#. c #6A5756",
105 | "$. c #6B5757",
106 | "%. c #6B5858",
107 | "&. c #6C5858",
108 | "*. c #6D5959",
109 | "=. c #6E5858",
110 | "-. c #6E5A5A",
111 | ";. c #765251",
112 | ":. c #7C5351",
113 | ">. c #84524A",
114 | ",. c #8E5448",
115 | "<. c #91574C",
116 | "1. c #9E544A",
117 | "2. c #975A4F",
118 | "3. c #9D5B4D",
119 | "4. c #865450",
120 | "5. c #885551",
121 | "6. c #885654",
122 | "7. c #8D5755",
123 | "8. c #8F5856",
124 | "9. c #805858",
125 | "0. c #875A5B",
126 | "q. c #8D5959",
127 | "w. c #9D5C51",
128 | "e. c #935959",
129 | "r. c #935A58",
130 | "t. c #915B5C",
131 | "y. c #AE564D",
132 | "u. c #A7584C",
133 | "i. c #AF5F58",
134 | "p. c #A66150",
135 | "a. c #AC6255",
136 | "s. c #B16356",
137 | "d. c #B46457",
138 | "f. c #B66657",
139 | "g. c #B86554",
140 | "h. c #B66856",
141 | "j. c #BF6B56",
142 | "k. c #BF6C57",
143 | "l. c #B8615B",
144 | "z. c #BD6659",
145 | "x. c #C16B57",
146 | "c. c #C8675D",
147 | "v. c #C4685B",
148 | "b. c #C56D5A",
149 | "n. c #CD6A5D",
150 | "m. c #CB6D5C",
151 | "M. c #D46559",
152 | "N. c #D56C5F",
153 | "B. c #DC705D",
154 | "V. c #D8775E",
155 | "C. c #DA785F",
156 | "Z. c #E4675F",
157 | "A. c #D55F62",
158 | "S. c #DE7C60",
159 | "D. c #E16A62",
160 | "F. c #FC6266",
161 | "G. c #FA6466",
162 | "H. c #FF6567",
163 | "J. c #FC6667",
164 | "K. c #FF6867",
165 | "L. c #FC6E67",
166 | "P. c #FF6668",
167 | "I. c #FF6768",
168 | "U. c #FF6868",
169 | "Y. c #FF6968",
170 | "T. c #FF6A68",
171 | "R. c #FF6B68",
172 | "E. c #FF6C68",
173 | "W. c #FF6D68",
174 | "Q. c #FF6E68",
175 | "!. c #FF6F68",
176 | "~. c #E37561",
177 | "^. c #EA7261",
178 | "/. c #E97563",
179 | "(. c #ED7064",
180 | "). c #E67861",
181 | "_. c #FA7166",
182 | "`. c #FB7567",
183 | "'. c #FD7567",
184 | "]. c #F47E66",
185 | "[. c #F47F66",
186 | "{. c #F77E67",
187 | "}. c #FE7B67",
188 | "|. c #FA7D66",
189 | " X c #FD7D67",
190 | ".X c #FE7E67",
191 | "XX c #FF7068",
192 | "oX c #FF7168",
193 | "OX c #FF7268",
194 | "+X c #FF7368",
195 | "@X c #FF7468",
196 | "#X c #FF7568",
197 | "$X c #FF7768",
198 | "%X c #FF7868",
199 | "&X c #FF7968",
200 | "*X c #FF7A68",
201 | "=X c #FF7B68",
202 | "-X c #FF7C68",
203 | ";X c #FF7D68",
204 | ":X c #FF7E68",
205 | ">X c #FF7F68",
206 | ",X c #EF8364",
207 | ".a.2X.X` Z H W W ! ! ~ o.o. ",
244 | " + + + @ $ ; , 2 2 6 9 y y h.qXw.~.:Xv.F H H H ! ~ | | o.o. ",
245 | " . + $ $ $ ; 2 2 6 r r y g 2.5Xm.:X*X' H H ! ! ! | | X.o.o.*. ",
246 | " + @ $ , : 2 6 6 9 r i p g ] 5X.X.Xn.G H H ! ! } | o.o.o.*. ",
247 | " @ $ : : : 6 9 9 p p g N B :X*X*X4.H ! W ! } | | o.&.*. ",
248 | " : : 2 6 e r p p p n n N /.*XN.H H W ! | | o.o.$.*. ",
249 | " 2 6 6 r i p h n n N Z n.*X5.H ! ! ! | o.o.o.&.*. ",
250 | " e y y p p n n N Z Z c.'.H ! ! } | X.o.o.*.*. ",
251 | " y y p n n M B Z / `.'.( ! ! | | o.&.*.*. ",
252 | " g g v n n M Z Z i.#XXX:.| | | o.&.o.*. ",
253 | " g n n M A H H (.#XXX6.| | o.o.&.*. ",
254 | " N Z Z F H 5.#XE.E.8.| o.o.o.*. ",
255 | " Z Z H H l.XXXXR.e.o.o.*.*. ",
256 | " H H Y D.XXE.R.e.o.o.*.*. ",
257 | " H ! XXE.E.R.q.*.*.*. ",
258 | " ;.E.R.I.I.9.*.*. ",
259 | " 7.R.R.I.G.&.*. ",
260 | " R.I.I.A.*. ",
261 | " H.H.F.t. ",
262 | " 0.*. ",
263 | " ",
264 | " "
265 | };
266 |
--------------------------------------------------------------------------------