diff --git a/CMakeLists.txt b/CMakeLists.txt index 2446374..4e84cff 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,6 +14,8 @@ add_executable(RISCB main.c cpu/memory.c cpu/memory.h cpu/core.c - cpu/core.h) # Ensure the target is defined before linking + cpu/core.h + util/texteditor.c + util/texteditor.h) # Ensure the target is defined before linking target_link_libraries(RISCB SDL2 SDL2_ttf m) diff --git a/main.c b/main.c index ae23a5e..ea41acf 100644 --- a/main.c +++ b/main.c @@ -3,6 +3,7 @@ #include #include "util/font.h" #include "assembler/assembler.h" +#include "util/texteditor.h" //Screen dimension constants const int SCREEN_WIDTH = 1280; @@ -16,15 +17,19 @@ SDL_Window *window = NULL; //The surface contained by the window SDL_Renderer *renderer = NULL; -SDL_Rect rect1; - BitmapFont smallFont; CPU cpu; +TextEditor codeEditor; + +TextEditor *activeEditor; + char programString[65535]; int init() { + + //Initialize SDL if (SDL_Init(SDL_INIT_EVERYTHING) < 0) { printf("SDL could not initialize! SDL_Error: %s\n", SDL_GetError()); @@ -52,13 +57,19 @@ int init() { return 1; } smallFont = prepText(renderer, 10, "../PublicPixel.ttf", 255, 255, 255, 255); + init_editor(&codeEditor, &smallFont, 50, 50, renderer); + activeEditor = &codeEditor; SDL_RenderSetLogicalSize(renderer, SCREEN_WIDTH, SCREEN_HEIGHT); SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, 0); + generate_string_display(&codeEditor, renderer); init_cpu(&cpu); return 0; } +SDL_Rect rect1; +SDL_Rect rect2; + int render() { SDL_SetRenderDrawColor(renderer, 128, 0, 0, 255); SDL_RenderClear(renderer); @@ -70,10 +81,7 @@ int render() { rect1.h = 10; SDL_RenderFillRect(renderer, &rect1); - char textTemp[12]; - sprintf(textTemp, "%d", rect1.x); - - renderText(renderer, smallFont, textTemp, 100, 100); + editor_render(&codeEditor, renderer); SDL_RenderPresent(renderer); return 0; @@ -85,9 +93,49 @@ int processEvent(SDL_Event e) { int newWidth = e.window.data1; int newHeight = e.window.data2; - // Adjust the viewport to match the new window size + // Adjust the viewport to match the new window size; SDL_Rect viewport = {0, 0, newWidth, newHeight}; SDL_RenderSetViewport(renderer, &viewport); + } else if (e.type == SDL_KEYDOWN) { + int keySym = e.key.keysym.sym; + switch (keySym) { + case SDLK_UP: + if (activeEditor) { + move_cursor_relative(activeEditor, -1, 0); + } + break; + case SDLK_DOWN: + if (activeEditor) { + move_cursor_relative(activeEditor, 1, 0); + } + break; + case SDLK_LEFT: + if (activeEditor) { + move_cursor_relative(activeEditor, 0, -1); + } + break; + case SDLK_RIGHT: + if (activeEditor) { + move_cursor_relative(activeEditor, 0, 1); + } + break; + case SDLK_RETURN: + case SDLK_RETURN2: + if (activeEditor && !activeEditor->readOnly) { + insert_line_rel(activeEditor); + } + break; + default: + break; + } + if (activeEditor && !activeEditor->readOnly) { + if (keySym >= 32 && keySym <= 126) { + if (keySym > 0x60 && keySym < 0x7b) { + keySym -= 0x20; + } + insert_character(activeEditor, (keySym & 0xff), renderer); + } + } } return 1; } diff --git a/util/font.c b/util/font.c index 1c07f55..4269767 100644 --- a/util/font.c +++ b/util/font.c @@ -12,21 +12,19 @@ prepText(SDL_Renderer *renderer, unsigned char pxSize, const char *file, uint8_t out.size = pxSize; out.color = (SDL_Color) {r, g, b, a}; unsigned char i = 0; - SDL_Surface *fontTempSurf = NULL; do { char tmpOut[2] = {i, 0}; - fontTempSurf = TTF_RenderText_Solid(gFont, tmpOut, out.color); + out.surface[i] = TTF_RenderText_Solid(gFont, tmpOut, out.color); SDL_Rect dstRect; dstRect.x = 0; dstRect.y = 0; dstRect.w = pxSize; dstRect.h = pxSize; - out.texture[i] = SDL_CreateTextureFromSurface(renderer, fontTempSurf); + out.texture[i] = SDL_CreateTextureFromSurface(renderer, out.surface[i]); i++; } while (i < 255); - SDL_FreeSurface(fontTempSurf); TTF_CloseFont(gFont); return out; } @@ -42,6 +40,12 @@ void renderText(SDL_Renderer *renderer, BitmapFont font, char *string, uint16_t outRect.y = y; while (*string) { + if (*string == '\n') { + outRect.x = x; + outRect.y += charRect.h + 4; + string++; + continue; + } SDL_RenderCopy(renderer, font.texture[*string], &charRect, &outRect); outRect.x += charRect.w + 1; string++; diff --git a/util/font.h b/util/font.h index 93f57b1..2dcb38d 100644 --- a/util/font.h +++ b/util/font.h @@ -11,6 +11,7 @@ typedef struct { SDL_Texture *texture[256]; + SDL_Surface *surface[256]; uint8_t size; SDL_Color color; } BitmapFont; diff --git a/util/texteditor.c b/util/texteditor.c new file mode 100644 index 0000000..69612ed --- /dev/null +++ b/util/texteditor.c @@ -0,0 +1,164 @@ +/// +// Created by bruno on 5.2.2025. +/// + +#include "texteditor.h" +#include "font.h" + +// Initialize the text editor +void init_editor(TextEditor *editor, BitmapFont *font, int x, int y, SDL_Renderer *renderer) { + for (int i = 0; i < MAX_LINES_ASM; i++) { + editor->lines[i].text[0] = '\0'; // Empty string + editor->lines[i].active = 0; + } + editor->lines[0].active = 1; + editor->line_count = 1; + editor->cursor_line = 0; + editor->cursor_line_offset = 0; + editor->cursor_pos = 0; + editor->readOnly = 0; + editor->rect.x = 0; + editor->rect.y = 0; + editor->rect.w = MAX_LINE_WIDTH * (font->size + 1); + editor->rect.h = MAX_LINES_DISPLAY * (font->size + 4); + editor->outRect = editor->rect; + editor->outRect.x = x; + editor->outRect.y = y; + editor->font = font; + editor->texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, editor->rect.w, + editor->rect.h); +} + +// Insert a new line at a specific position +void insert_line(TextEditor *editor, int position, const char *text) { + if (editor->line_count >= MAX_LINES_ASM || position < 0 || position > editor->line_count) { + printf("Invalid position or max lines reached!\n"); + return; + } + + // Shift lines down if necessary + for (int i = editor->line_count; i > position; i--) { + strcpy(editor->lines[i].text, editor->lines[i - 1].text); + editor->lines[i].active = editor->lines[i - 1].active; + } + + strncpy(editor->lines[position].text, text, MAX_LINE_WIDTH); + editor->lines[position].text[MAX_LINE_WIDTH] = '\0'; // Ensure null termination + editor->lines[position].active = 1; + + editor->line_count++; +} + +void insert_line_rel(TextEditor *editor) { + editor->cursor_pos = 0; + insert_line(editor, editor->cursor_line + 1, ""); + editor->cursor_line++; +} + +// Insert a character at the current cursor position +void insert_character(TextEditor *editor, char ch, SDL_Renderer *renderer) { + if (editor->cursor_line < 0 || editor->cursor_line >= editor->line_count) { + printf("Invalid cursor position!\n"); + return; + } + + Line *line = &editor->lines[editor->cursor_line]; + int len = strlen(line->text); + + if (len >= MAX_LINE_WIDTH || editor->cursor_pos > len) { + printf("Position out of bounds or line is full!\n"); + return; + } + + // Shift characters to the right + for (int i = len; i >= editor->cursor_pos; i--) { + line->text[i + 1] = line->text[i]; + } + + line->text[editor->cursor_pos] = ch; + editor->cursor_pos++; + generate_string_display(editor, renderer); +} + +// Move cursor +void move_cursor_relative(TextEditor *editor, int line_offset, int pos_offset) { + int new_line = editor->cursor_line + line_offset; + int new_pos = editor->cursor_pos + pos_offset; + + if (new_line < 0) new_line = 0; + if (new_line >= editor->line_count) new_line = editor->line_count - 1; + + move_cursor(editor, new_line, new_pos); +} + +// Move cursor +void move_cursor(TextEditor *editor, int new_line, int new_pos) { + if (new_line < 0) new_line = 0; + if (new_line >= editor->line_count) new_line = editor->line_count - 1; + + int line_length = strlen(editor->lines[new_line].text); + if (new_pos < 0) new_pos = 0; + if (new_pos > line_length) new_pos = line_length; + + editor->cursor_line = new_line; + editor->cursor_pos = new_pos; +} + +// Generate a string from a given offset with a max line count +void generate_string_display(TextEditor *editor, SDL_Renderer *renderer) { + if (editor->cursor_line_offset < 0 || editor->cursor_line_offset >= editor->line_count) { + printf("Invalid start line!\n"); + return; + } + + int end_line = editor->cursor_line_offset + MAX_LINES_DISPLAY; + if (end_line > editor->line_count) end_line = editor->line_count; + + + memset(editor->displayString, 0, sizeof(editor->displayString)); + + SDL_SetRenderTarget(renderer, editor->texture); + SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); + SDL_RenderClear(renderer); + + SDL_Rect charRect; + charRect.x = 0; + charRect.y = 0; + charRect.w = editor->font->size; + charRect.h = editor->font->size; + SDL_Rect outRect = charRect; + outRect.x = 0; + outRect.y = 0; + + for (int i = editor->cursor_line_offset; i < end_line; i++) { + if (editor->lines[i].active) { + strcat(editor->displayString, editor->lines[i].text); + char *linePTR = editor->lines[i].text; + while (*linePTR) { + SDL_RenderCopy(renderer, editor->font->texture[*linePTR], &charRect, &outRect); + outRect.x += charRect.w + 1; + linePTR++; + } + strcat(editor->displayString, "\n"); + outRect.x = 0; + outRect.y += charRect.h + 4; + } + } + SDL_SetRenderTarget(renderer, NULL); +} + +void editor_render(TextEditor *editor, SDL_Renderer * renderer) { + SDL_RenderCopy(renderer, editor->texture, &editor->rect, &editor->outRect); +} + +// Generate a string for assembling +void generate_string(TextEditor *editor) { + memset(editor->outputString, 0, sizeof(editor->outputString)); + + for (int i = 0; i < MAX_LINES_ASM; i++) { + if (editor->lines[i].active) { + strcat(editor->outputString, editor->lines[i].text); + strcat(editor->outputString, "\n"); + } + } +} \ No newline at end of file diff --git a/util/texteditor.h b/util/texteditor.h new file mode 100644 index 0000000..5781a55 --- /dev/null +++ b/util/texteditor.h @@ -0,0 +1,65 @@ +/// +// Created by bruno on 5.2.2025. +/// + +#ifndef RISCB_TEXTEDITOR_H +#define RISCB_TEXTEDITOR_H + +#define MAX_LINE_WIDTH 34 // Max chars per line (excluding '\0') +#define MAX_LINES_ASM 100 // Max number of lines +#define MAX_LINES_DISPLAY 10 // Max number of lines + +#include +#include +#include +#include +#include +#include +#include "font.h" + +typedef struct { + char text[MAX_LINE_WIDTH + 1]; // +1 for null terminator + int active; // Flag to check if the line is in use +} Line; + +typedef struct { + Line lines[MAX_LINES_ASM]; // Array of lines + int line_count; // Number of active lines + int cursor_line; // Current cursor line + int cursor_line_offset; // Current cursor line + int cursor_pos; // Current cursor position in line + char outputString[MAX_LINE_WIDTH * MAX_LINES_ASM]; + char displayString[MAX_LINE_WIDTH * MAX_LINES_DISPLAY]; + SDL_Rect rect; + SDL_Rect outRect; + SDL_Texture *texture; + bool readOnly; + BitmapFont *font; +} TextEditor; + +// Initialize the text editor +void init_editor(TextEditor *editor, BitmapFont *font, int x, int y, SDL_Renderer *renderer); + +// Insert a new line at a specific position +void insert_line(TextEditor *editor, int position, const char *text); + +// Insert a new line at a specific position +void insert_line_rel(TextEditor *editor); + +void editor_render(TextEditor *editor, SDL_Renderer * renderer); + +// Insert a character at the current cursor position +void insert_character(TextEditor *editor, char ch, SDL_Renderer *renderer); + +// Move cursor (handled externally) +void move_cursor(TextEditor *editor, int new_line, int new_pos); + +// Move cursor (handled externally) +void move_cursor_relative(TextEditor *editor, int line_offset, int pos_offset); + +// Generate a string from a given offset with a max line count +void generate_string_display(TextEditor *editor, SDL_Renderer *renderer); + +void generate_string(TextEditor *editor); + +#endif //RISCB_TEXTEDITOR_H \ No newline at end of file