Something is almost working

This commit is contained in:
2025-02-08 23:23:21 +01:00
parent aaf3dfb40c
commit 45653b6372
15 changed files with 969 additions and 326 deletions

168
util/cpustatusui.c Normal file
View File

@@ -0,0 +1,168 @@
//
// Created by bruno on 8.2.2025.
//
#include <SDL2/SDL_render.h>
#include "cpustatusui.h"
#include "font.h"
SDL_Texture *renderVals(CPU *cpu, BitmapFont *titleFont, BitmapFont *valueFont,
SDL_Renderer *renderer) {
CPUStatusPart *stats = NULL;
int statsCount = 0;
getStats(cpu, &stats, &statsCount);
const int padding = 4;
const int oneFieldW = (titleFont->size + 1) * (sizeof(stats[0].value) - 1) + padding - 1;
const int oneFieldH = (titleFont->size + 1) * 2 + (valueFont->size + 1);
SDL_Texture *out = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET,
oneFieldW * statsCount, oneFieldH);
SDL_SetRenderTarget(renderer, out);
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderClear(renderer);
for (int i = 0; i < statsCount; i++) {
int x = i * oneFieldW;
SDL_Rect rect = {x, 0, oneFieldW, oneFieldH};
SDL_SetRenderDrawColor(renderer, 50, 50, 50, 255);
SDL_RenderFillRect(renderer, &rect);
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
SDL_RenderDrawRect(renderer, &rect);
// Render the title
int textX = x + padding;
int textY = padding;
for (int j = 0; j < 6 && stats[i].name[j] != '\0'; j++) {
SDL_Texture *charTex = titleFont->texture[(uint8_t) stats[i].name[j]];
if (charTex) {
SDL_Rect dstRect = {textX, textY, titleFont->size, titleFont->size};
SDL_RenderCopy(renderer, charTex, NULL, &dstRect);
textX += titleFont->size;
}
}
// Render the value
char valueStr[12];
snprintf(valueStr, sizeof(valueStr), "%u", stats[i].value);
textX = x + padding;
textY += titleFont->size + padding;
for (int j = 0; valueStr[j] != '\0'; j++) {
SDL_Texture *charTex = valueFont->texture[(uint8_t) valueStr[j]];
if (charTex) {
SDL_Rect dstRect = {textX, textY, valueFont->size, valueFont->size};
SDL_RenderCopy(renderer, charTex, NULL, &dstRect);
textX += valueFont->size;
}
}
}
SDL_SetRenderTarget(renderer, NULL);
return out;
}
void getStats(CPU *cpu, CPUStatusPart **cpuStatus, int *cpuStatusCount) {
if (!cpu || !cpuStatus || !cpuStatusCount) return;
int count = 5 + REG_COUNT; // PC, SP, FLAGS, MODE, CYCLE + registers
// Free existing memory if allocated
if (*cpuStatus) {
free(*cpuStatus);
*cpuStatus = NULL;
}
// Allocate the required memory
*cpuStatus = (CPUStatusPart *) malloc(count * sizeof(CPUStatusPart));
if (!*cpuStatus) return; // Memory allocation failed
int index = 0;
strncpy((*cpuStatus)[index].name, "PC", sizeof((*cpuStatus)[index].name));
(*cpuStatus)[index].value = cpu->pc;
index++;
strncpy((*cpuStatus)[index].name, "SP", sizeof((*cpuStatus)[index].name));
(*cpuStatus)[index].value = cpu->stack_ptr;
index++;
strncpy((*cpuStatus)[index].name, "FLG", sizeof((*cpuStatus)[index].name));
(*cpuStatus)[index].value = cpu->flags;
index++;
strncpy((*cpuStatus)[index].name, "MOD", sizeof((*cpuStatus)[index].name));
(*cpuStatus)[index].value = cpu->mode;
index++;
strncpy((*cpuStatus)[index].name, "CYC", sizeof((*cpuStatus)[index].name));
(*cpuStatus)[index].value = cpu->cycle;
index++;
for (int i = 0; i < 25; i++) {
snprintf((*cpuStatus)[index].name, sizeof((*cpuStatus)[index].name), "R%d", i);
(*cpuStatus)[index].value = cpu->regs[i];
index++;
}
*cpuStatusCount = index; // Store the actual number of status parts
}
SDL_Texture *renderState(CPU *cpu, BitmapFont *titleFont, SDL_Renderer *renderer) {
// Render the value
char valueStr[20] = "";
if (cpu->mode & CPU_MODE_ERROR) {
strcat(valueStr, "ERR ");
} else if (cpu->mode & CPU_MODE_HALTED) {
strcat(valueStr, "HLT ");
} else if (cpu->mode & CPU_MODE_PAUSED) {
strcat(valueStr, "PAUS ");
} else {
strcat(valueStr, "RUN ");
}
if (cpu->mode & CPU_MODE_LOOP) {
strcat(valueStr, "LOOP ");
} else {
strcat(valueStr, "ONCE ");
}
if (cpu->mode & CPU_MODE_STEP) {
strcat(valueStr, "STP");
} else if (cpu->mode & CPU_MODE_SECOND) {
strcat(valueStr, "SEC");
} else {
strcat(valueStr, "BRR");
}
const int oneFieldW = (titleFont->size + 1);
const int allFieldW = oneFieldW * strlen(valueStr);
const int oneFieldH = (titleFont->size + 1);
SDL_Texture *out = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET,
allFieldW, oneFieldH);
SDL_SetRenderTarget(renderer, out);
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderClear(renderer);
SDL_Rect rect = {0, 0, allFieldW, oneFieldH};
SDL_SetRenderDrawColor(renderer, 50, 50, 50, 255);
SDL_RenderFillRect(renderer, &rect);
int x = 0;
for (int j = 0; valueStr[j] != '\0'; j++) {
SDL_Texture *charTex = titleFont->texture[(uint8_t) valueStr[j]];
if (charTex) {
SDL_Rect dstRect = {x, 0, titleFont->size, titleFont->size};
x += titleFont->size + 1;
SDL_RenderCopy(renderer, charTex, NULL, &dstRect);
}
}
SDL_SetRenderTarget(renderer, NULL);
return out;
}

23
util/cpustatusui.h Normal file
View File

@@ -0,0 +1,23 @@
//
// Created by bruno on 8.2.2025.
//
#ifndef RISCB_CPUSTATUSUI_H
#define RISCB_CPUSTATUSUI_H
#include "font.h"
#include "../cpu/core.h"
typedef struct {
char name[4];
uint32_t value;
} CPUStatusPart;
SDL_Texture *renderVals(CPU *cpu, BitmapFont *titleFont, BitmapFont *valueFont,
SDL_Renderer *renderer);
SDL_Texture *renderState(CPU *cpu, BitmapFont *titleFont, SDL_Renderer *renderer);
void getStats(CPU *cpu, CPUStatusPart **cpuStatus, int *cpuStatusCount);
#endif //RISCB_CPUSTATUSUI_H

View File

@@ -10,13 +10,13 @@ prepText(SDL_Renderer *renderer, unsigned char pxSize, const char *file, uint8_t
BitmapFont out;
out.size = pxSize;
out.color = (SDL_Color) {r, g, b, a};
unsigned char i = 0;
unsigned int i = 1;
do {
char tmpOut[2] = {i, 0};
out.surface[i] = TTF_RenderText_Solid(gFont, tmpOut, out.color);
out.texture[i] = SDL_CreateTextureFromSurface(renderer, out.surface[i]);
i++;
} while (i < 255);
} while (i < 256);
TTF_CloseFont(gFont);
return out;
@@ -43,4 +43,11 @@ void renderText(SDL_Renderer *renderer, BitmapFont font, char *string, uint16_t
outRect.x += charRect.w + 1;
string++;
}
}
void destroyFont(BitmapFont *font) {
for (uint16_t i = 1; i < 256; i++) {
SDL_DestroyTexture(font->texture[i]);
SDL_FreeSurface(font->surface[i]);
}
}

View File

@@ -19,6 +19,8 @@ typedef struct {
BitmapFont
prepText(SDL_Renderer *renderer, unsigned char pxSize, const char *file, uint8_t r, uint8_t g, uint8_t b, uint8_t a);
void destroyFont(BitmapFont *font);
void renderText(SDL_Renderer *renderer, BitmapFont font, char *string, uint16_t x, uint16_t y);
#endif //RISCB_FONT_H

50
util/hexdump.c Normal file
View File

@@ -0,0 +1,50 @@
//
// Created by bruno on 6.2.2025.
//
#include "hexdump.h"
#include <stdio.h>
#include <ctype.h>
#include <malloc.h>
#define BYTES_PER_LINE 16 // Adjust for different widths
char *hexdump_to_string(const unsigned char *data, size_t size) {
// Estimate max output size: each line is approx. 80 chars
size_t estimated_size = (size / BYTES_PER_LINE + 1) * 80;
// Allocate memory for output string
char *output = malloc(estimated_size);
if (!output) return NULL;
size_t offset = 0; // Track the write position
for (size_t i = 0; i < size; i += BYTES_PER_LINE) {
offset += snprintf(output + offset, estimated_size - offset, "%08zx ", i);
// Print hex values
for (size_t j = 0; j < BYTES_PER_LINE; j++) {
if (i + j < size)
offset += snprintf(output + offset, estimated_size - offset, "%02x ", data[i + j]);
else
offset += snprintf(output + offset, estimated_size - offset, " "); // Padding
if (j == 7) offset += snprintf(output + offset, estimated_size - offset, " "); // Extra space
}
offset += snprintf(output + offset, estimated_size - offset, " |");
// Print ASCII representation
for (size_t j = 0; j < BYTES_PER_LINE; j++) {
if (i + j < size)
offset += snprintf(output + offset, estimated_size - offset, "%c",
isprint(data[i + j]) ? data[i + j] : '.');
else
offset += snprintf(output + offset, estimated_size - offset, " ");
}
offset += snprintf(output + offset, estimated_size - offset, "|\n");
}
return output;
}

12
util/hexdump.h Normal file
View File

@@ -0,0 +1,12 @@
//
// Created by bruno on 6.2.2025.
//
#ifndef RISCB_HEXDUMP_H
#define RISCB_HEXDUMP_H
#include <stddef.h>
char *hexdump_to_string(const unsigned char *data, size_t size);
#endif //RISCB_HEXDUMP_H

View File

@@ -1,62 +1,120 @@
///
//
// Created by bruno on 5.2.2025.
///
// Modified to use dynamic limits.
//
#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;
// Initialize the text editor with dynamic sizes.
void init_editor(TextEditor *editor, BitmapFont *font, int x, int y, SDL_Renderer *renderer,
int max_line_width, int max_lines_asm, int max_lines_display, bool readOnly) {
editor->max_line_width = max_line_width;
editor->max_lines_asm = max_lines_asm;
editor->max_lines_display = max_lines_display;
editor->line_count = 0;
editor->cursor_line = 0;
editor->cursor_line_offset = 0;
editor->cursor_pos = 0;
editor->readOnly = 0;
editor->rect.x = 2;
editor->rect.y = 2;
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->readOnly = readOnly;
editor->font = font;
editor->texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, editor->rect.w,
editor->rect.h);
editor->outRect = malloc(sizeof(SDL_Rect));
editor->cursorRect = malloc(sizeof(SDL_Rect));
editor->rect = malloc(sizeof(SDL_Rect));
memset(editor->outRect, 0, sizeof(SDL_Rect));
memset(editor->cursorRect, 0, sizeof(SDL_Rect));
memset(editor->rect, 0, sizeof(SDL_Rect));
// Allocate dynamic array for lines.
editor->lines = (Line *) malloc(sizeof(Line) * editor->max_lines_asm);
if (!editor->lines) {
fprintf(stderr, "Failed to allocate memory for lines.\n");
exit(EXIT_FAILURE);
}
// For each line, allocate memory for the text (including space for '\0')
for (int i = 0; i < editor->max_lines_asm; i++) {
editor->lines[i].text = (char *) malloc(sizeof(char) * (editor->max_line_width + 1));
if (!editor->lines[i].text) {
fprintf(stderr, "Failed to allocate memory for line %d.\n", i);
exit(EXIT_FAILURE);
}
editor->lines[i].text[0] = '\0';
editor->lines[i].active = 0;
}
// Allocate output and display strings.
editor->outputString = (char *) malloc(sizeof(char) * (editor->max_line_width * editor->max_lines_asm + 1));
editor->displayString = (char *) malloc(sizeof(char) * (editor->max_line_width * editor->max_lines_display + 1));
if (!editor->outputString || !editor->displayString) {
fprintf(stderr, "Failed to allocate memory for output/display strings.\n");
exit(EXIT_FAILURE);
}
editor->outputString[0] = '\0';
editor->displayString[0] = '\0';
// Initialize with two active lines (like the original code).
editor->lines[0].active = 1;
editor->lines[1].active = 1;
editor->line_count = 2;
// Set up the editor rectangle based on font size and dynamic max_line_width and max_lines_display.
editor->rect->x = 2;
editor->rect->y = 2;
editor->rect->w = editor->max_line_width * (font->size + 1) + ((font->size + 1) / 2);
editor->rect->h = editor->max_lines_display * (font->size + 1) + 2;
editor->outRect->w = editor->rect->w;
editor->outRect->h = editor->rect->h;
editor->outRect->x = x;
editor->outRect->y = y;
editor->cursorRect->x = 3 + editor->cursor_pos * font->size + editor->outRect->x;
editor->cursorRect->y =
2 + (editor->cursor_line - editor->cursor_line_offset) * (font->size + 1) + editor->outRect->y;
editor->cursorRect->w = 2;
editor->cursorRect->h = editor->font->size;
// Create texture for rendering.
editor->texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888,
SDL_TEXTUREACCESS_TARGET,
editor->rect->w, editor->rect->h);
if (!editor->texture) {
fprintf(stderr, "Failed to create texture: %s\n", SDL_GetError());
exit(EXIT_FAILURE);
}
}
// Insert a new line at a specific position
// Insert a new line at a specific position.
void insert_line(TextEditor *editor, int position, const char *text, SDL_Renderer *renderer) {
if (editor->line_count >= MAX_LINES_ASM || position < 0 || position > editor->line_count) {
if (editor->line_count >= editor->max_lines_asm || position < 0 || position > editor->line_count) {
printf("Invalid position or max lines reached!\n");
return;
}
// Shift lines down if necessary
// Shift lines down.
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
// Copy the text into the new line, ensuring it does not exceed max_line_width.
strncpy(editor->lines[position].text, text, editor->max_line_width);
editor->lines[position].text[editor->max_line_width] = '\0';
editor->lines[position].active = 1;
editor->line_count++;
move_cursor(editor, editor->cursor_line + 1, 0, false, renderer);
generate_string_display(editor, renderer);
}
void insert_line_rel(TextEditor *editor, SDL_Renderer *renderer) {
insert_line(editor, editor->cursor_line + (editor->cursor_pos ? 1 : 0), "", renderer);
editor->cursor_pos = 0;
insert_line(editor, editor->cursor_line + 1, "", renderer);
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");
@@ -66,12 +124,12 @@ void insert_character(TextEditor *editor, char ch, SDL_Renderer *renderer) {
Line *line = &editor->lines[editor->cursor_line];
int len = strlen(line->text);
if (len >= MAX_LINE_WIDTH || editor->cursor_pos > len) {
if (len >= editor->max_line_width || editor->cursor_pos > len) {
printf("Position out of bounds or line is full!\n");
return;
}
// Shift characters to the right
// Shift characters to the right.
for (int i = len; i >= editor->cursor_pos; i--) {
line->text[i + 1] = line->text[i];
}
@@ -81,139 +139,220 @@ void insert_character(TextEditor *editor, char ch, SDL_Renderer *renderer) {
generate_string_display(editor, renderer);
}
void remove_character(TextEditor *editor, SDL_Renderer *renderer) {
void remove_character(TextEditor *editor, bool isDelete, SDL_Renderer *renderer) {
if (editor->cursor_line < 0 || editor->cursor_line >= editor->line_count) {
printf("Invalid cursor position!\n");
return;
}
if (editor->cursor_pos == 0 && editor->line_count > 1) {
// Remove the current line and shift lines up
for (int i = editor->cursor_line; i < editor->line_count - 1; i++) {
strcpy(editor->lines[i].text, editor->lines[i + 1].text);
editor->lines[i].active = editor->lines[i + 1].active;
Line *line = &editor->lines[editor->cursor_line];
int len = strlen(line->text);
if (isDelete) {
// Delete character after cursor
if (editor->cursor_pos < len) {
for (int i = editor->cursor_pos; i < len; i++) {
line->text[i] = line->text[i + 1];
}
}
editor->lines[editor->line_count - 1].text[0] = '\0';
editor->lines[editor->line_count - 1].active = 0;
editor->line_count--;
if (editor->cursor_line >= editor->line_count) {
editor->cursor_line = editor->line_count - 1;
}
editor->cursor_pos = strlen(editor->lines[editor->cursor_line].text);
} else {
Line *line = &editor->lines[editor->cursor_line];
int len = strlen(line->text);
if (editor->cursor_pos <= 0 || editor->cursor_pos > len) {
printf("Position out of bounds!\n");
return;
// Backspace behavior (delete character before cursor)
if (editor->cursor_pos == 0 && editor->line_count > 1) {
// Merge with the previous line
for (int i = editor->cursor_line; i < editor->line_count - 1; i++) {
strcpy(editor->lines[i].text, editor->lines[i + 1].text);
editor->lines[i].active = editor->lines[i + 1].active;
}
editor->lines[editor->line_count - 1].text[0] = '\0';
editor->lines[editor->line_count - 1].active = 0;
editor->line_count--;
if (editor->cursor_line >= editor->line_count) {
editor->cursor_line = editor->line_count - 1;
}
editor->cursor_pos = strlen(editor->lines[editor->cursor_line].text);
} else if (editor->cursor_pos > 0) {
for (int i = editor->cursor_pos - 1; i < len; i++) {
line->text[i] = line->text[i + 1];
}
editor->cursor_pos--;
}
// Shift characters to the left to remove the character
for (int i = editor->cursor_pos - 1; i < len; i++) {
line->text[i] = line->text[i + 1];
}
editor->cursor_pos--;
}
generate_string_display(editor, renderer);
}
// Move cursor
void move_cursor_relative(TextEditor *editor, int line_offset, int pos_offset) {
void move_cursor_relative(TextEditor *editor, int line_offset, int pos_offset, bool keepPos, SDL_Renderer *renderer) {
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(editor, new_line, new_pos, keepPos, renderer);
}
// Move cursor
void move_cursor(TextEditor *editor, int new_line, int new_pos) {
void move_cursor(TextEditor *editor, int new_line, int new_pos, bool keepPos, SDL_Renderer *renderer) {
if (new_line < 0) new_line = 0;
if (new_line >= editor->line_count) new_line = editor->line_count - 1;
if (keepPos) {
editor->cursor_line_offset = new_line;
}
if (new_line < editor->cursor_line_offset) {
editor->cursor_line_offset = new_line;
}
if (new_line >= editor->cursor_line_offset + editor->max_lines_display) {
editor->cursor_line_offset = new_line - editor->max_lines_display + 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_string_display(editor, renderer);
}
// 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;
int end_line = editor->cursor_line_offset + editor->max_lines_display;
if (end_line > editor->line_count)
end_line = editor->line_count;
memset(editor->displayString, 0, sizeof(editor->displayString));
// Clear the display string.
editor->displayString[0] = '\0';
SDL_SetRenderTarget(renderer, editor->texture);
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderClear(renderer);
SDL_Rect charDstRect;
charDstRect.x = 4;
charDstRect.y = 3;
charDstRect.w = editor->font->size;
charDstRect.h = editor->font->size;
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 = 3;
outRect.y = 2;
SDL_Rect cursorRect;
cursorRect.x = 0;
cursorRect.y = 0;
cursorRect.w = 1;
cursorRect.h = editor->font->size;
editor->cursorRect->x = 3 + editor->cursor_pos * (charDstRect.w + 1) + editor->outRect->x;
editor->cursorRect->y =
2 + (editor->cursor_line - editor->cursor_line_offset) * (charDstRect.h + 1) + editor->outRect->y;
for (int line = editor->cursor_line_offset; line < end_line; line++) {
if (editor->lines[line].active) {
strcat(editor->displayString, editor->lines[line].text);
char *linePTR = editor->lines[line].text;
int charIndex = 0;
while (*linePTR) {
SDL_RenderCopy(renderer, editor->font->texture[*linePTR], &charRect, &outRect);
outRect.x += charRect.w + 1;
if (line == editor->cursor_line && charIndex == editor->cursor_pos - 1) {
cursorRect.x = outRect.x;
cursorRect.y = outRect.y;
}
charIndex++;
SDL_RenderCopy(renderer, editor->font->texture[(unsigned char) *linePTR], &charRect, &charDstRect);
charDstRect.x += charDstRect.w + 1;
linePTR++;
}
strcat(editor->displayString, "\n");
outRect.x = 3;
outRect.y += charRect.h + 1;
charDstRect.x = 4;
charDstRect.y += charDstRect.h + 1;
}
}
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
SDL_RenderFillRect(renderer, &cursorRect);
SDL_SetRenderTarget(renderer, NULL);
}
void editor_render(TextEditor *editor, SDL_Renderer *renderer) {
SDL_RenderCopy(renderer, editor->texture, &editor->rect, &editor->outRect);
void editor_render(TextEditor *editor, SDL_Renderer *renderer, bool isActive, bool cursorBlink) {
if (isActive) {
SDL_Rect bgRect;
bgRect = *editor->outRect;
bgRect.x -= 6;
bgRect.y -= 6;
bgRect.w += 12;
bgRect.h += 12;
SDL_SetRenderDrawColor(renderer, editor->readOnly ? 128 : 0, editor->readOnly ? 0 : 128, 64, 255);
SDL_RenderFillRect(renderer, &bgRect);
}
SDL_RenderCopy(renderer, editor->texture, editor->rect, editor->outRect);
if (isActive && cursorBlink) {
SDL_SetRenderDrawColor(renderer, 0, 255, 255, 255);
SDL_RenderFillRect(renderer, editor->cursorRect);
}
}
// Generate a string for assembling
void generate_string(TextEditor *editor) {
memset(editor->outputString, 0, sizeof(editor->outputString));
editor->outputString[0] = '\0';
for (int i = 0; i < MAX_LINES_ASM; i++) {
for (int i = 0; i < editor->max_lines_asm; i++) {
if (editor->lines[i].active) {
strcat(editor->outputString, editor->lines[i].text);
strcat(editor->outputString, "\n");
if (strlen(editor->lines[i].text)) {
strcat(editor->outputString, editor->lines[i].text);
strcat(editor->outputString, "\n");
}
}
}
}
}
void fill_editor_from_string(TextEditor *editor, const char *content, SDL_Renderer *renderer) {
if (!editor || !content) {
printf("Invalid editor or content pointer!\n");
return;
}
// Clear the current editor content
for (int i = 0; i < editor->max_lines_asm; i++) {
editor->lines[i].text[0] = '\0';
editor->lines[i].active = 0;
}
editor->line_count = 0;
editor->cursor_line = 0;
editor->cursor_pos = 0;
// Parse the content and fill the editor lines
const char *ptr = content;
int line_index = 0;
while (*ptr && line_index < editor->max_lines_asm) {
int char_count = 0;
// Ensure the text buffer does not overflow
while (*ptr && *ptr != '\n' && char_count < editor->max_line_width - 1) {
editor->lines[line_index].text[char_count++] = *ptr++;
}
editor->lines[line_index].text[char_count] = '\0'; // Null-terminate
editor->lines[line_index].active = 1;
line_index++;
// Move past the newline character if present
if (*ptr == '\n') ptr++;
}
// Update the total number of lines in use
editor->line_count = line_index;
// Generate the visual representation
generate_string_display(editor, renderer);
}
// Free all dynamically allocated memory.
void destroy_editor(TextEditor *editor) {
if (editor->lines) {
for (int i = 0; i < editor->max_lines_asm; i++) {
free(editor->lines[i].text);
}
free(editor->lines);
}
free(editor->outputString);
free(editor->displayString);
free(editor->outRect);
free(editor->rect);
free(editor->cursorRect);
if (editor->texture) {
SDL_DestroyTexture(editor->texture);
}
}

View File

@@ -1,67 +1,72 @@
///
//
// Created by bruno on 5.2.2025.
///
// Modified to use dynamic limits.
//
#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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <SDL2/SDL_rect.h>
#include <SDL2/SDL_surface.h>
#include <SDL2/SDL_render.h>
#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
char *text; // Dynamically allocated string for this line
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;
Line *lines; // Dynamic array of lines
int line_count; // Number of active lines
int max_lines_asm; // Maximum number of lines (e.g. assembly lines)
int max_line_width; // Maximum characters per line (excluding '\0')
int max_lines_display; // Maximum number of lines for display
int cursor_line; // Current cursor line
int cursor_line_offset; // Display offset (first line in the display)
int cursor_pos; // Current cursor position in line
char *outputString; // Dynamically allocated output string (size: max_line_width * max_lines_asm + 1)
char *displayString; // Dynamically allocated display string (size: max_line_width * max_lines_display + 1)
SDL_Rect *rect;
SDL_Rect *outRect;
SDL_Texture *texture;
bool readOnly;
BitmapFont *font;
SDL_Rect *cursorRect;
} TextEditor;
// Initialize the text editor
void init_editor(TextEditor *editor, BitmapFont *font, int x, int y, SDL_Renderer *renderer);
// Initialize the text editor. The parameters max_line_width, max_lines_asm, and max_lines_display
// determine the dynamic sizes for the text editor.
void init_editor(TextEditor *editor, BitmapFont *font, int x, int y, SDL_Renderer *renderer,
int max_line_width, int max_lines_asm, int max_lines_display, bool readOnly);
// Insert a new line at a specific position
// Other function prototypes remain mostly unchanged but will use the dynamic limits:
void insert_line(TextEditor *editor, int position, const char *text, SDL_Renderer *renderer);
// Insert a new line at a specific position
void insert_line_rel(TextEditor *editor, SDL_Renderer *renderer);
void editor_render(TextEditor *editor, SDL_Renderer * renderer);
void editor_render(TextEditor *editor, SDL_Renderer *renderer, bool isActive, bool cursorBlink);
void remove_character(TextEditor *editor, SDL_Renderer *renderer);
void remove_character(TextEditor *editor, bool isDelete, 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);
void move_cursor(TextEditor *editor, int new_line, int new_pos, bool keepPos, SDL_Renderer *renderer);
// Move cursor (handled externally)
void move_cursor_relative(TextEditor *editor, int line_offset, int pos_offset);
void move_cursor_relative(TextEditor *editor, int line_offset, int pos_offset, bool keepPos, SDL_Renderer *renderer);
// 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
void fill_editor_from_string(TextEditor *editor, const char *content, SDL_Renderer *renderer);
// A cleanup function to free dynamically allocated memory.
void destroy_editor(TextEditor *editor);
#endif // RISCB_TEXTEDITOR_H