diff --git a/src/CRTerm.cpp b/src/CRTerm.cpp
index 299957a..3de52ce 100644
--- a/src/CRTerm.cpp
+++ b/src/CRTerm.cpp
@@ -19,7 +19,6 @@
#include "ConfigSelector.h"
#include "ContextMenu.h"
-
/* SDLmain requires this. It seems to define its own main. */
#undef main
@@ -119,8 +118,8 @@ int main()
/* Set the cursor to normal if a UI element is online */
SDL_SetCursor(normal_cur);
}
- }
- GPU_ClearColor(screen, SDL_Color{ 40, 40, 40, 255 });
+ }
+ GPU_ClearColor(screen, SDL_Color{ 52, 55, 64, 255 });
/* First render the terminal */
vt100_term->VT100Render();
/* Then the UI */
diff --git a/src/CRTerm.vcxproj b/src/CRTerm.vcxproj
index 6dee92b..de43169 100644
--- a/src/CRTerm.vcxproj
+++ b/src/CRTerm.vcxproj
@@ -108,7 +108,7 @@
true
_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
true
- $(ProjectDir)lib\SDL2_gpu\include;$(ProjectDir)lib\SDL2\include;$(ProjectDir)lib\imgui\include;%(AdditionalIncludeDirectories)
+ $(ProjectDir)lib\SDL2_gpu\include;$(ProjectDir)lib\SDL2\include;$(ProjectDir)lib\imgui\include;$(ProjectDir)include;%(AdditionalIncludeDirectories)
stdcpp17
@@ -126,12 +126,16 @@
true
NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
true
+ $(ProjectDir)lib\SDL2_gpu\include;$(ProjectDir)lib\SDL2\include;$(ProjectDir)lib\imgui\include;$(ProjectDir)include;%(AdditionalIncludeDirectories)
+ stdcpp17
Console
true
true
true
+ $(ProjectDir)lib\SDL2;$(ProjectDir)lib\SDL2_gpu;%(AdditionalLibraryDirectories)
+ SDL2main.lib;SDL2.lib;SDL2_gpu.lib;winmm.lib;Dwmapi.lib;%(AdditionalDependencies)
diff --git a/src/CRTermConfig.cpp b/src/CRTermConfig.cpp
index becc04c..6ea03f9 100644
--- a/src/CRTermConfig.cpp
+++ b/src/CRTermConfig.cpp
@@ -47,7 +47,7 @@ CRTermConfiguration::CRTermConfiguration(std::string json_path)
this->default_fore_color = configuration_data.at("default_fg");
this->default_back_color = configuration_data.at("default_bg");
this->crt_warp = configuration_data.at("crt_warp");
-
+ this->maxlines = configuration_data.at("maxlines");
int i = 0;
for (auto& color : configuration_data.at("color_scheme"))
{
@@ -67,9 +67,21 @@ CRTermConfiguration::CRTermConfiguration(std::string json_path)
MessageBox(GetActiveWindow(), (LPCWSTR)errW.c_str(), L"Error parsing default.json", MB_OK | MB_ICONERROR);
exit(-1);
}
+ catch (nlohmann::json::other_error& error)
+ {
+ std::string err = error.what();
+ std::wstring errW = std::wstring(err.begin(), err.end());
+ MessageBox(GetActiveWindow(), (LPCWSTR)errW.c_str(), L"Error loading default.json", MB_OK | MB_ICONERROR);
+ }
+ catch (nlohmann::json::type_error& error)
+ {
+ std::string err = error.what();
+ std::wstring errW = std::wstring(err.begin(), err.end());
+ MessageBox(GetActiveWindow(), (LPCWSTR)errW.c_str(), L"Error loading default.json", MB_OK | MB_ICONERROR);
+ }
catch (...)
{
- MessageBox(GetActiveWindow(), L"An exception occurred while loading default.json", L"Error loading default.json", MB_OK | MB_ICONERROR);
+ MessageBox(GetActiveWindow(), L"An unknown error occurred", L"Error loading default.json", MB_OK | MB_ICONERROR);
}
}
@@ -94,6 +106,7 @@ void CRTermConfiguration::Save(std::string filename)
output_json["default_fg"] = this->default_fore_color;
output_json["default_bg"] = this->default_back_color;
output_json["crt_warp"] = this->crt_warp;
+ output_json["maxlines"] = this->maxlines;
int color_scheme_arr[16][3];
@@ -104,7 +117,7 @@ void CRTermConfiguration::Save(std::string filename)
color_scheme_arr[i][2] = color_scheme[i].b;
}
- output_json["color_sheme"] = color_scheme_arr;
+ output_json["color_scheme"] = color_scheme_arr;
std::ofstream output(filename);
output << std::setw(4) << output_json;
diff --git a/src/CRTermConfig.h b/src/CRTermConfig.h
index 568bf2c..7bad885 100644
--- a/src/CRTermConfig.h
+++ b/src/CRTermConfig.h
@@ -39,6 +39,7 @@ class CRTermConfiguration
int default_fore_color;
int default_back_color;
int blink_interval;
+ int maxlines;
float crt_warp;
CRTermColor color_scheme[16];
diff --git a/src/ConfigEditor.cpp b/src/ConfigEditor.cpp
index aaa7de1..8c5d835 100644
--- a/src/ConfigEditor.cpp
+++ b/src/ConfigEditor.cpp
@@ -49,6 +49,10 @@ void ConfigEditor::Render(void)
ImGui::SameLine();
ImGui::InputInt("##blink_interval", &(cfg->blink_interval));
+ ImGui::Text("Maximum Lines");
+ ImGui::SameLine();
+ ImGui::InputInt("##maxlines", &(cfg->maxlines));
+
ImGui::Text("Default FG");
ImGui::SameLine();
ImGui::InputInt("##default_fg", &(cfg->default_fore_color));
diff --git a/src/Console.cpp b/src/Console.cpp
index c6c00e5..aa36e7e 100644
--- a/src/Console.cpp
+++ b/src/Console.cpp
@@ -20,6 +20,11 @@ Console::Console(CRTermConfiguration* cfg)
this->cursor_x = 0;
this->cursor_y = 0;
+ this->maxlines = cfg->maxlines;
+ /* Check the maxlines, if greater than 10000 or less than 500 default to 1000 */
+ if (this->maxlines < CONSOLE_MIN_LINES || this->maxlines > CONSOLE_MAX_LINES)
+ this->maxlines = CONSOLE_DEFAULT_LINES;
+
this->console_resolution_x = this->console_w * this->font_w;
this->console_resolution_y = this->console_h * this->font_h;
@@ -194,6 +199,14 @@ void Console::HistoryDown()
start_line++;
}
+void Console::SetSelection(bool selection, int start_x, int start_y, int end_x, int end_y)
+{
+ this->selected_start_x = start_x;
+ this->selected_start_y = start_y;
+ this->selected_end_x = end_x;
+ this->selected_end_y = end_y;
+ this->is_selected = selection;
+}
void Console::SetCursor(int x, int y)
{
this->cursor_x = x;
@@ -317,6 +330,8 @@ unsigned char Console::ReadChar(int x, int y)
return 0;
return this->buffer[this->start_line * this->console_w + y * this->console_w + x];
}
+
+/* The Console Render function, this is what makes the magic happen :) */
void Console::Render(GPU_Target* t, int xloc, int yloc, float scale)
{
GPU_Clear(this->render_buffer->target);
@@ -330,6 +345,8 @@ void Console::Render(GPU_Target* t, int xloc, int yloc, float scale)
this->show_cursor = !this->show_cursor;
this->cursor_clock = time;
}
+ /* Set text alpha to 1.0 */
+ GPU_SetUniformf(GPU_GetUniformLocation(this->text_shader_id, "alpha"), 1.0);
for (int y = 0; y < this->console_h; y++)
{
for (int x = 0; x < this->console_w; x++)
@@ -353,6 +370,35 @@ void Console::Render(GPU_Target* t, int xloc, int yloc, float scale)
}
}
+ /* Draw the scroll bar if we are scrolling i.e. last_line != start_line and the user has scrolled up */
+ if (start_line != last_line)
+ {
+ GPU_Rect scrollbar;
+ scrollbar.h = (((float)this->console_h) / ((float)this->last_line + this->console_h)) * (this->render_buffer->h);
+ scrollbar.y = scrollbar.h * 0.5 * ((float)this->start_line / (float)(this->last_line + 1.0));
+ scrollbar.w = 8;
+ scrollbar.x = this->render_buffer->w - 8;
+ GPU_SetUniformfv(GPU_GetUniformLocation(this->text_shader_id, "text_color"), 3, 1, this->color_scheme[this->default_fore_color].returnArray());
+ /* Set scroll bar alpha to 0.8 */
+ GPU_SetUniformf(GPU_GetUniformLocation(this->text_shader_id, "alpha"), 0.8);
+ GPU_RectangleFilled(this->render_buffer->target, scrollbar.x, scrollbar.y, scrollbar.x + scrollbar.w, scrollbar.y + scrollbar.h, SDL_Color{ 255, 255, 255, 255 });
+ }
+
+ /* Draw the selection rectangle if the user has selected some text, this bool passed from VT100 class */
+ if (this->is_selected)
+ {
+ GPU_SetUniformfv(GPU_GetUniformLocation(this->text_shader_id, "text_color"), 3, 1, this->color_scheme[this->default_fore_color].returnArray());
+ /* Set selected text alpha to 0.4 */
+ GPU_SetUniformf(GPU_GetUniformLocation(this->text_shader_id, "alpha"), 0.4);
+ for (int i = this->selected_start_x + this->selected_start_y * this->console_w; i < this->selected_end_x + this->selected_end_y * this->console_w; i++)
+ {
+
+ int y = i / this->console_w;
+ int x = i % this->console_w;
+ GPU_RectangleFilled(this->render_buffer->target, x * this->font_w, y * this->font_h, (x + 1) * this->font_w, (y + 1) * this->font_h, SDL_Color{ 255, 255, 255, 255 });
+ }
+ }
+
/* Draw the cursor, if we are not scrolling */
if (this->show_cursor && this->start_line == this->last_line)
{
@@ -370,6 +416,10 @@ void Console::Render(GPU_Target* t, int xloc, int yloc, float scale)
}
}
+ /*
+ We have now rendered the terminal to the local render buffer,
+ now we pass it through the CRT shader and scale it up.
+ */
GPU_ActivateShaderProgram(this->crt_shader_id, &this->crt_shader_block);
float resolution[2] = { (float)t->w, (float)t->h };
/* Set shader parameters */
@@ -383,17 +433,6 @@ void Console::Render(GPU_Target* t, int xloc, int yloc, float scale)
/* Now blit to screen! */
GPU_BlitScale(this->render_buffer, NULL, t, xloc + (int)(this->render_buffer->w / 2) * scale, yloc + (int)(this->render_buffer->h / 2) * scale, scale, scale);
GPU_DeactivateShaderProgram();
-
- /* Draw the scroll bar */
- if (start_line != last_line)
- {
- GPU_Rect scrollbar;
- scrollbar.h = (((float)this->console_h) / ((float)this->last_line + this->console_h)) * (t->h - TITLE_BAR_HEIGHT);
- scrollbar.y = TITLE_BAR_HEIGHT + scrollbar.h * 0.5 * ((float)this->start_line / (float)(this->last_line + 1.0));
- scrollbar.w = SCROLL_BAR_WIDTH;
- scrollbar.x = t->w - SIDES_WIDTH - SCROLL_BAR_WIDTH;
- GPU_RectangleFilled2(t, scrollbar, SDL_Color{ 100, 100, 100, 255 });
- }
/*
Now apply the CRT effect shader
The CRT effect shader applies CRT warp effect, CRT phosphor glow scanline effect, and noise.
diff --git a/src/Console.h b/src/Console.h
index b6c2d20..c866809 100644
--- a/src/Console.h
+++ b/src/Console.h
@@ -14,6 +14,10 @@
#include "CRTermConfig.h"
#include "SDL_gpu.h"
+#define CONSOLE_MIN_LINES 500
+#define CONSOLE_MAX_LINES 10000
+#define CONSOLE_DEFAULT_LINES 1000
+
/*
Helper function to construct console attributes,
which are basically VGA attributes that store
@@ -56,16 +60,35 @@ class Console
/* TODO: Some of these are better of in private. */
unsigned char* buffer;
unsigned char* attrib_buffer;
+ /* Character-wise resolution of the console */
int console_w, console_h;
GPU_Image* console_font;
GPU_Image* crt_background;
int font_w, font_h;
int cursor_x, cursor_y;
+ /* Actual resolution of the console (in pixels) */
int console_resolution_x, console_resolution_y;
int default_fore_color, default_back_color;
+ /* No. of millseconds after which the console must blink */
int blink_interval;
+ /*
+ For scrolling, console starts drawing from start_line*console_w, last_line is the latest start_line position
+ For all time, start_line <= last_line. start_line is decremented when the user hits mousewheel up
+ and Console->HistoryUp() is called.
+
+ maxlines is the maximum lines the console stores, beyond that, it starts to overwrite its old history.
+ Generally, the lower limit for maxlines is 500, and upper limit is 10000 lines.
+ */
int start_line, last_line;
- int maxlines = 1000;
+ int maxlines;
+
+ /* Selecting text into the terminal */
+ bool is_selected;
+ int selected_start_x = 0, selected_start_y = 0;
+ int selected_end_x = 0, selected_end_y = 0;
+ /*
+ Stores audio data for the bell sound.
+ */
std::string bell_wave_file;
Console(CRTermConfiguration*);
@@ -86,6 +109,7 @@ class Console
void ClearExt(int fromx, int fromy, int tox, int toy);
void HistoryUp();
void HistoryDown();
+ void SetSelection(bool selection, int start_x=0, int start_y=0, int end_x=0, int end_y=0);
/* The 256 letters glyphs extracted from the font image */
GPU_Image* char_blocks[256];
diff --git a/src/VT100.cpp b/src/VT100.cpp
index 6edfb30..2de84e6 100644
--- a/src/VT100.cpp
+++ b/src/VT100.cpp
@@ -92,7 +92,7 @@ void VT100::VT100Take(unsigned char c)
{
std::cout << "Unexpected identifier after VT_ESCAPE: " << c << std::endl;
parser_state = VTSTATE_NORMAL;
- VT100Putc(c);
+ //VT100Putc(c);
}
break;
case VTSTATE_ATTR:
@@ -551,9 +551,13 @@ void VT100::VT100HandleEvent(SDL_Event ev)
break;
case SDL_MOUSEWHEEL:
if (ev.wheel.y > 0)
+ {
this->con->HistoryUp();
+ }
else
+ {
this->con->HistoryDown();
+ }
break;
case SDL_MOUSEBUTTONUP:
if (ev.button.button == SDL_BUTTON_LEFT)
@@ -585,23 +589,18 @@ void VT100::VT100Send(std::string sequence)
void VT100::VT100Render(void)
{
- con->Render(this->render_target, this->screen_offsetx, this->screen_offsety, this->font_scale);
- GPU_DeactivateShaderProgram();
-
/* Draw overlay above the selected text if it is selected or dragging */
if (is_selected || is_dragging)
{
- /* In case the user has selected it from right to left, orient the selection coords */
orientSelectedCoords();
- for (int i = this->selected_start_x + this->selected_start_y * this->con->console_w; i < this->selected_end_x + this->selected_end_y * this->con->console_w; i++)
- {
- int y = i / this->con->console_w;
- int x = i % this->con->console_w;
- int sx, sy;
- consoleToScreenCoords(x, y, &sx, &sy);
- GPU_RectangleFilled(this->render_target, sx, sy, sx + con->font_w * this->font_scale, sy + con->font_h * this->font_scale, SDL_Color{255, 255, 255, 128});
- }
+ this->con->SetSelection(true, selected_start_x, selected_start_y, selected_end_x, selected_end_y);
}
+ else
+ {
+ this->con->SetSelection(false);
+ }
+ con->Render(this->render_target, this->screen_offsetx, this->screen_offsety, this->font_scale);
+ GPU_DeactivateShaderProgram();
}
void VT100::VT100Shutdown()
{
diff --git a/src/VT100.h b/src/VT100.h
index f315c68..7795896 100644
--- a/src/VT100.h
+++ b/src/VT100.h
@@ -115,8 +115,8 @@ class VT100
inline void consoleToScreenCoords(int conx, int cony, int* screenx, int* screeny)
{
- *screenx = screen_offsetx + conx * this->con->font_w * this->font_scale;
- *screeny = screen_offsety + cony * this->con->font_h * this->font_scale;
+ *screenx = (int)((double)screen_offsetx + (double)conx * (double)this->con->font_w * this->font_scale);
+ *screeny = (int)((double)screen_offsety + (double)cony * (double)this->con->font_h * this->font_scale);
}
inline void getConsoleMouseCoords(int* conx, int* cony)
diff --git a/src/resources/config/default_cmd.json b/src/resources/config/default_cmd.json
index 7c98598..f926609 100644
--- a/src/resources/config/default_cmd.json
+++ b/src/resources/config/default_cmd.json
@@ -1,8 +1,8 @@
{
"font": "font.png",
- "font_width": 16,
- "font_height": 32,
- "font_scale": 0.8,
+ "font_width": 8,
+ "font_height": 16,
+ "font_scale": 1.2,
"console_width": 120,
"console_height": 30,
"background": "crt.png",
@@ -10,10 +10,11 @@
"crt_shader": "shaders/crt",
"bell": "bell.wav",
"crt_warp": 0.0,
- "shell_command": "cmd.exe %userprofile%",
+ "shell_command": "cmd.exe %USERPROFILE%",
"blink_interval": 300,
"default_fg": 2,
"default_bg": 2,
+ "maxlines": 1000,
"color_scheme":
[
diff --git a/src/resources/config/default_wsl.json b/src/resources/config/default_wsl.json
index f770e8f..486c042 100644
--- a/src/resources/config/default_wsl.json
+++ b/src/resources/config/default_wsl.json
@@ -1,8 +1,8 @@
{
"font": "font.png",
- "font_width": 16,
- "font_height": 32,
- "font_scale": 0.8,
+ "font_width": 8,
+ "font_height": 16,
+ "font_scale": 1.2,
"console_width": 120,
"console_height": 30,
"background": "crt.png",
@@ -14,6 +14,7 @@
"blink_interval": 300,
"default_fg": 6,
"default_bg": 6,
+ "maxlines": 1000,
"color_scheme":
[
diff --git a/src/resources/default b/src/resources/default
index d9f90ec..e897746 100644
--- a/src/resources/default
+++ b/src/resources/default
@@ -1 +1 @@
-config\default_wsl.json
\ No newline at end of file
+config\default_cmd.json
\ No newline at end of file
diff --git a/src/resources/font.png b/src/resources/font.png
index 51ea10d..4e282ca 100644
Binary files a/src/resources/font.png and b/src/resources/font.png differ
diff --git a/src/resources/imgui.ini b/src/resources/imgui.ini
index c557cf3..ea4e0b0 100644
--- a/src/resources/imgui.ini
+++ b/src/resources/imgui.ini
@@ -45,7 +45,7 @@ Collapsed=0
[Window][##title]
Pos=32,0
-Size=1552,32
+Size=1168,32
Collapsed=0
[Window][##XButton]
@@ -54,7 +54,7 @@ Size=64,32
Collapsed=0
[Window][##Window_Buttons]
-Pos=1456,0
+Pos=1072,0
Size=96,32
Collapsed=0