diff --git a/CMakeLists.txt b/CMakeLists.txt index 879671d..2e26241 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,11 +17,16 @@ set(CMAKE_CXX_CLANG_TIDY clang-tidy;-header-filter=.;) file(GLOB_RECURSE SOURCES src/*.cpp) file(GLOB_RECURSE HEADERS src/*.h) file(GLOB_RECURSE TESTS test/*.cpp) +include_directories(src) +include_directories(test) + +#toml +include_directories(lib/toml) set(LIB_PATH "${CMAKE_SOURCE_DIR}/../library") include_directories(${LIB_PATH}/include) -add_executable(Terminal ${SOURCES} ${HEADERS} main/main.cpp src/Buchstaben.hpp src/Buchstaben.cpp) +add_executable(Terminal ${SOURCES} ${HEADERS} main/main.cpp src/Terminal.h src/Terminal.cpp src/Bitmap.cpp src/Bitmap.h src/Font.cpp src/Font.h) target_link_libraries(Terminal ${LIB_PATH}/lib/liblibrary.a) diff --git a/README.md b/README.md index 509e398..61c3404 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,17 @@ # vKVM Terminal +Terminal calls the methods from library in order to get data from shared memory +and control the output content in GUI. + +## Features + +- If all the lines of the screen are occupied and a new line is added, all lines +will be moved up. +- Terminal can handle the backspace. +- If a line is too long for the screen, terminal will word wrap. +- A cursor can be simulated to insert text anywhere. +- Terminal can use the arrow keys to move the cursor. +- The input from terminal will be wise selected. ## Installation Use the installation script provided in the Scripts repository diff --git a/main/main.cpp b/main/main.cpp index 4a628d6..6d9c9b8 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -2,19 +2,104 @@ #include #include #include "internal.hpp" -#include "../src/Buchstaben.hpp" +#include "../src/Terminal.h" int main() { vkvm::initialize(0); - while(1){ - vkvm::registerEvent(vkvm::KeyDown, []() { - vkvm::KeyCode keycode = buchstabeneinlesen(); - char c = keycode + 65256; - std::cout << c << std::endl; - std::string s(1, c); - buchstabenschreiben(s); + + Terminal terminal = Terminal(); + + vkvm::registerEvent(vkvm::KeyDown, [&terminal]() { + vkvm::KeyCode keycode = vkvm::getLastPressedKey(); + std::cout << keycode << std::endl; + + if(((vkvm::KeyCode::ShiftLeft & 0xfff) == keycode) ||((vkvm::KeyCode::ShiftRight & 0xfff) == keycode)){ + terminal.shiftpressed(); + } + + if(((vkvm::KeyCode::Zero & 0xfff) <= keycode) && (keycode <= (vkvm::Nine & 0xfff))){ + char ch = keycode - (vkvm::KeyCode::Zero & 0xfff) + '0'; + std::cout << ch << std::endl; + terminal.setString(ch); + vkvm::setText(terminal.getString()); + std::cout<< vkvm::getText()<< std::endl; + vkvm::callEvent(vkvm::EventType::RenderText); + } + + if(((vkvm::KeyCode::A & 0xfff) <= keycode) && (keycode <= (vkvm::KeyCode::Z & 0xfff))){ + int status = terminal.getstatus(); + char ch; + if(status == 0){ + ch = keycode - (vkvm::KeyCode::A & 0xfff) + 'a'; + } + else{ + ch = keycode - (vkvm::KeyCode::A & 0xfff) + 'A'; + } + std::cout << ch << std::endl; + terminal.setString(ch); + vkvm::setText(terminal.getString()); + std::cout<< vkvm::getText()<< std::endl; + vkvm::callEvent(vkvm::EventType::RenderText); + } + + if((vkvm::KeyCode::Space & 0xfff) == keycode){ + char ch = keycode - (vkvm::KeyCode::Space & 0xfff) + ' '; + std::cout << ch << std::endl; + terminal.setString(ch); + vkvm::setText(terminal.getString()); + std::cout<< vkvm::getText()<< std::endl; + vkvm::callEvent(vkvm::EventType::RenderText); + } + + if((vkvm::KeyCode::Backspace & 0xfff) == keycode){ + char ch = keycode - (vkvm::KeyCode::Backspace & 0xfff) + ' '; + std::cout << ch << std::endl; + terminal.subString(); + vkvm::setText(terminal.getString()); + std::cout<< vkvm::getText()<< std::endl; + vkvm::callEvent(vkvm::EventType::RenderText); + } + + if((vkvm::KeyCode::Tab & 0xfff) == keycode){ + char ch = keycode - (vkvm::KeyCode::Tab & 0xfff) + ' '; + for(int i = 0; i < 3; i++) { + std::cout << ch << std::endl; + terminal.setString(ch); + } + vkvm::setText(terminal.getString()); + std::cout<< vkvm::getText()<< std::endl; + vkvm::callEvent(vkvm::EventType::RenderText); + } + + if((vkvm::KeyCode::Enter & 0xfff) == keycode){ + char ch = '\n'; + std::cout << ch << std::endl; + terminal.setString(ch); + vkvm::setText(terminal.getString()); + std::cout<< vkvm::getText()<< std::endl; + vkvm::callEvent(vkvm::EventType::RenderText); + } + }); + + vkvm::registerEvent(vkvm::KeyUp, [&terminal]() { + vkvm::KeyCode keycode = vkvm::getLastPressedKey(); + if(((vkvm::KeyCode::ShiftLeft & 0xfff) == keycode) ||((vkvm::KeyCode::ShiftRight & 0xfff) == keycode)){ + terminal.shiftup(); + } +// char ch = keycode - (vkvm::KeyCode::A & 0xfff) + 'A'; +// std::cout << ch << std::endl; +// terminal.setString(ch); +// vkvm::setText(terminal.getString()); +// std::cout<< vkvm::getText()<< std::endl; +// vkvm::callEvent(vkvm::EventType::RenderText); + }); + + + + while(1){ + sleep(0.1); } } \ No newline at end of file diff --git a/src/Bitmap.cpp b/src/Bitmap.cpp new file mode 100644 index 0000000..a264e50 --- /dev/null +++ b/src/Bitmap.cpp @@ -0,0 +1,63 @@ +#include "Bitmap.h" +#include +#include + +Bitmap::Bitmap() { + offset = 0; + width = 0; + height = 0; + bpp = 0; +} + +Bitmap::Bitmap(const std::string &file) { + offset = 0; + width = 0; + height = 0; + bpp = 0; + load(file); +} + +void Bitmap::load(const std::string &file) { + std::ifstream stream; + stream.open(file); + if(stream.is_open()){ + std::string str((std::istreambuf_iterator(stream)),std::istreambuf_iterator()); + data.resize(str.size()); + for(int i = 0; i < str.size();i++){ + data[i] = str[i]; + } + + offset = (int)*(unsigned int*)(&data[10]); + width = (int)*(unsigned int*)(&data[18]); + height = (int)*(unsigned int*)(&data[22]); + bpp = (int)*(unsigned short*)(&data[28]); + } +} + +int Bitmap::getWidth() { + return width; +} + +int Bitmap::getHeight() { + return height; +} + +char *Bitmap::getData() { + return &data[offset]; +} + +int Bitmap::getBitsPerPixel() { + return bpp; +} + +unsigned int Bitmap::getPixel(int x, int y) { + unsigned int pixel = 0; + char *ptr = getData() + ((getHeight() - 1 - y) * getWidth() + x) * (getBitsPerPixel() / 8); + for(int i = 0; i < getBitsPerPixel() / 8;i++){ + *((char*)&pixel+i) = ptr[i]; + } + if(pixel != 0){ + return pixel; + } + return pixel; +} diff --git a/src/Bitmap.h b/src/Bitmap.h new file mode 100644 index 0000000..e1b61a9 --- /dev/null +++ b/src/Bitmap.h @@ -0,0 +1,67 @@ +#ifndef TERMINAL_BITMAP_H +#define TERMINAL_BITMAP_H + +#include +#include + +/** + * @author: Julian Hinxlage + * @since: v0.0.0 + * @brief: Used to load a Bitmap from a file. + */ +class Bitmap { +public: + Bitmap(); + explicit Bitmap(const std::string &file); + + /** + * @author: Julian Hinxlage + * @since: v0.0.0 + * @brief: Used to load a Bitmap from a file. + */ + void load(const std::string &file); + + /** + * @author: Julian Hinxlage + * @since: v0.0.0 + * @return: the width of the image. + */ + int getWidth(); + + /** + * @author: Julian Hinxlage + * @since: v0.0.0 + * @return: the height of the image + */ + int getHeight(); + + /** + * @author: Julian Hinxlage + * @since: v0.0.0 + * @return: the pixel data as an byte array + */ + char *getData(); + + /** + * @author: Julian Hinxlage + * @since: v0.0.0 + * @return: the number of bits uses per pixel + */ + int getBitsPerPixel(); + + /** + * @author: Julian Hinxlage + * @since: v0.0.0 + * @return: the pixel value by coordinates, (0,0) is on the top left + */ + unsigned int getPixel(int x, int y); + +private: + int width; + int height; + int offset; + int bpp; + std::vector data; +}; + +#endif //TERMINAL_BITMAP_H diff --git a/src/Buchstaben.cpp b/src/Buchstaben.cpp deleted file mode 100644 index 9d243e5..0000000 --- a/src/Buchstaben.cpp +++ /dev/null @@ -1,14 +0,0 @@ -// -// Created by yukun on 29.11.19. -// -#include "vkvm.hpp" - -auto buchstabeneinlesen() ->vkvm::KeyCode { - vkvm::KeyCode keycode; - keycode = vkvm::getLastPressedKey(); - return keycode; -} - -auto buchstabenschreiben(std::string s) ->void { - vkvm::setText(s); -} \ No newline at end of file diff --git a/src/Buchstaben.hpp b/src/Buchstaben.hpp deleted file mode 100644 index a748681..0000000 --- a/src/Buchstaben.hpp +++ /dev/null @@ -1,13 +0,0 @@ -// -// Created by yukun on 29.11.19. -// - -#ifndef TERMINAL_BUCHSTABEN_HPP -#define TERMINAL_BUCHSTABEN_HPP - -#include "vkvm.hpp" - -auto buchstabeneinlesen() ->vkvm::KeyCode ; - -auto buchstabenschreiben(std::string s) ->void; -#endif //TERMINAL_BUCHSTABEN_HPP diff --git a/src/Font.cpp b/src/Font.cpp new file mode 100644 index 0000000..e9cb8ea --- /dev/null +++ b/src/Font.cpp @@ -0,0 +1,79 @@ +#include "Font.h" +#include + + +Font::Font() { + xOffset = 0; + yOffset = 0; + xSize = 0; + ySize = 0; + xCount = 0; + yCount = 0; + xStart = 0; + yStart = 0; + fillValue = 0; + firstChar = ' '; +} + +Font::Font(const std::string &file, const std::string &configFile) : Font() { + load(file, configFile); +} + +void Font::load(const std::string &file, const std::string &configFile) { + bitmap.load(file); + auto config = cpptoml::parse_file(configFile); + xOffset = config->get_as("xOffset").value_or(0); + yOffset = config->get_as("yOffset").value_or(0); + xSize = config->get_as("xSize").value_or(0); + ySize = config->get_as("ySize").value_or(0); + xCount = config->get_as("xCount").value_or(0); + yCount = config->get_as("yOffset").value_or(0); + xStart = config->get_as("xStart").value_or(0); + yStart = config->get_as("yStart").value_or(0); + fillValue = config->get_as("fillValue").value_or(0); + firstChar = (char)config->get_as("firstChar").value_or(0); + pixelSize = config->get_as("pixelSize").value_or(0); + gap = config->get_as("gap").value_or(-1); + invertedColors = config->get_as("invertedColors").value_or(0); +} + +int Font::width() { + return xSize; +} + +int Font::height() { + return ySize; +} + +bool Font::getPixel(char character, int x, int y) { + //index of character(x and y) + int index = (character - firstChar); + + if(gap != -1){ + if (index >= gap){ + index++; + } + } + + int xIndex = index % xCount; + int yIndex = index / xCount; + + if(index < 0){ + yIndex--; + xIndex += xCount; + } + + //character index to pixel index conversion + int xPos = xIndex * (xSize + xOffset) + xStart; + int yPos = yIndex * (ySize + yOffset) + yStart; + + bool value = bitmap.getPixel((xPos + x) * pixelSize, (yPos + y) * pixelSize) == fillValue; + if(invertedColors){ + return !value; + }else{ + return value; + } +} + + + diff --git a/src/Font.h b/src/Font.h new file mode 100644 index 0000000..8274834 --- /dev/null +++ b/src/Font.h @@ -0,0 +1,51 @@ +// +// Created by yukun on 05.12.19. +// + +#ifndef TERMINAL_FONT_H +#define TERMINAL_FONT_H +#include "Bitmap.h" + +/** + * @author: Julian Hinxlage + * @since: v0.0.0 + * @brief: this class provides pixel access based on characters + */ +class Font { +public: + Bitmap bitmap; + + //space between characters + int xOffset; + int yOffset; + + //size of a character + int xSize; + int ySize; + + //count of characters per row + int xCount; + //count of rows + int yCount; + + //pixel offset of first character + int xStart; + int yStart; + + unsigned int fillValue; + char firstChar; + int pixelSize; + int gap; + + bool invertedColors; + + Font(); + explicit Font(const std::string &file, const std::string &configFile); + void load(const std::string &file, const std::string &configFile); + + int width(); + int height(); + bool getPixel(char character, int x, int y); +}; + +#endif //TERMINAL_FONT_H diff --git a/src/Terminal.cpp b/src/Terminal.cpp new file mode 100644 index 0000000..1ad63ff --- /dev/null +++ b/src/Terminal.cpp @@ -0,0 +1,32 @@ +// +// Created by yukun on 29.11.19. +// +#include "vkvm.hpp" +#include "Terminal.h" + +std::string Terminal::getString() { + return s; +} + +void Terminal::setString(char c) { + s = s + c; +} + +void Terminal::subString(){ + s = s.substr(0, s.length() - 1); +} + +void Terminal::shiftpressed() { + status = 1; + +} + +void Terminal::shiftup() { + status = 0; + +} + +int Terminal::getstatus() { + return status; +} + diff --git a/src/Terminal.h b/src/Terminal.h new file mode 100644 index 0000000..7ad1ed7 --- /dev/null +++ b/src/Terminal.h @@ -0,0 +1,23 @@ +// +// Created by yukun on 29.11.19. +// + +#ifndef TERMINAL_TERMINAL_H +#define TERMINAL_TERMINAL_H + +#include "vkvm.hpp" + +class Terminal { +public: + std::string getString(); + void setString(char c); + void subString(); + void shiftpressed(); + void shiftup(); + int getstatus(); + +private: + std::string s=""; + int status = 0; +}; +#endif //TERMINAL_TERMINAL_H