Extract rendering function out and render a few lines
This commit is contained in:
parent
177f73f78a
commit
8117e9250a
242
bt.c
242
bt.c
@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
const int SCREEN_WIDTH = 900;
|
const int SCREEN_WIDTH = 900;
|
||||||
const int SCREEN_HEIGHT = 700;
|
const int SCREEN_HEIGHT = 700;
|
||||||
|
const int SCROLLBACK_DEFAULT_SIZE = 4096;
|
||||||
const SDL_Color WHITE = {255, 255, 255, 255};
|
const SDL_Color WHITE = {255, 255, 255, 255};
|
||||||
const SDL_Color BLACK = {0, 0, 0, 255};
|
const SDL_Color BLACK = {0, 0, 0, 255};
|
||||||
const SDL_Color RED = {255, 0, 0, 255};
|
const SDL_Color RED = {255, 0, 0, 255};
|
||||||
@ -26,20 +27,26 @@ const SDL_Color MAGENTA = {255, 0, 255, 255};
|
|||||||
const SDL_Color SKYBLUE = {0, 255, 255, 255};
|
const SDL_Color SKYBLUE = {0, 255, 255, 255};
|
||||||
const SDL_Color RAYWHITE = {200, 200, 200, 255};
|
const SDL_Color RAYWHITE = {200, 200, 200, 255};
|
||||||
|
|
||||||
typedef struct scrollback {
|
typedef struct {
|
||||||
float height;
|
float height;
|
||||||
float ypos;
|
float ypos;
|
||||||
int capacity;
|
int capacity;
|
||||||
int length;
|
int length;
|
||||||
char *buf;
|
char *buf;
|
||||||
} scrollback;
|
} Scrollback;
|
||||||
|
|
||||||
typedef struct file_descriptors {
|
typedef struct {
|
||||||
int master;
|
int master;
|
||||||
int child;
|
int child;
|
||||||
} file_descriptors;
|
} FileDescriptors;
|
||||||
|
|
||||||
void spawn(file_descriptors *fds) {
|
typedef struct {
|
||||||
|
Scrollback* sb;
|
||||||
|
TTF_Font* font;
|
||||||
|
SDL_Renderer* renderer;
|
||||||
|
} Context;
|
||||||
|
|
||||||
|
void spawn(FileDescriptors *fds) {
|
||||||
openpty(&fds->master, &fds->child, NULL, NULL, NULL);
|
openpty(&fds->master, &fds->child, NULL, NULL, NULL);
|
||||||
pid_t p = fork();
|
pid_t p = fork();
|
||||||
if (p == 0) {
|
if (p == 0) {
|
||||||
@ -57,7 +64,7 @@ void spawn(file_descriptors *fds) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int read_pty(file_descriptors *fds, scrollback *sb) {
|
int read_pty(FileDescriptors *fds, Scrollback *sb) {
|
||||||
ssize_t nread;
|
ssize_t nread;
|
||||||
char readbuf[256];
|
char readbuf[256];
|
||||||
switch (nread = read(fds->master, readbuf, sizeof(readbuf))) {
|
switch (nread = read(fds->master, readbuf, sizeof(readbuf))) {
|
||||||
@ -84,9 +91,115 @@ int read_pty(file_descriptors *fds, scrollback *sb) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void render_scrollback(Context* ctx) {
|
||||||
|
SDL_RenderClear(ctx->renderer);
|
||||||
|
|
||||||
|
SDL_Color current_color = WHITE;
|
||||||
|
int col_max = 80;
|
||||||
|
char row_buf[col_max];
|
||||||
|
int nrow = 0;
|
||||||
|
int ncol = 0;
|
||||||
|
int row_height = 18;
|
||||||
|
float row_posx = 0;
|
||||||
|
Scrollback sb = *ctx->sb;
|
||||||
|
for (int c = 0; c <= sb.length; c++) {
|
||||||
|
// for (int c = 0; c <= -1; c++) {
|
||||||
|
if (sb.buf[c] == '\r') {
|
||||||
|
continue;
|
||||||
|
} else if (sb.buf[c] == '\n' || sb.buf[c] == '\0' || ncol >= col_max) {
|
||||||
|
row_buf[ncol] = '\0';
|
||||||
|
// TODO: Render new line or something?
|
||||||
|
// Vector2 pos = { row_posx, nrow * row_height + sb.ypos };
|
||||||
|
// DrawTextEx(*fontDefault, row_buf, pos, fontsize, 0, current_color);
|
||||||
|
SDL_Surface* surface =
|
||||||
|
TTF_RenderText_Blended(ctx->font, row_buf, WHITE);
|
||||||
|
|
||||||
|
// now you can convert it into a texture
|
||||||
|
SDL_Texture* texture = SDL_CreateTextureFromSurface(ctx->renderer, surface);
|
||||||
|
|
||||||
|
SDL_Rect rect;
|
||||||
|
rect.x = 0;
|
||||||
|
rect.y = nrow * 15;
|
||||||
|
rect.w = surface->w;
|
||||||
|
rect.h = surface->h;
|
||||||
|
|
||||||
|
|
||||||
|
SDL_RenderCopy(ctx->renderer, texture, NULL, &rect);
|
||||||
|
|
||||||
|
SDL_DestroyTexture(texture);
|
||||||
|
SDL_FreeSurface(surface);
|
||||||
|
|
||||||
|
nrow++;
|
||||||
|
ncol = 0;
|
||||||
|
row_posx = 0;
|
||||||
|
// Control sequence
|
||||||
|
} else if (sb.buf[c] == '\x1b') {
|
||||||
|
int c2 = c + 1;
|
||||||
|
// Control Sequence Introducer
|
||||||
|
int csi_args[16];
|
||||||
|
char csi_code;
|
||||||
|
int nargs = 0;
|
||||||
|
if (sb.buf[c2] == '[') {
|
||||||
|
char *esc_buf = sb.buf + c2 + 1;
|
||||||
|
while (true) {
|
||||||
|
char *substr;
|
||||||
|
long num = strtol(esc_buf, &substr, 10);
|
||||||
|
if (esc_buf != substr) {
|
||||||
|
csi_args[nargs++] = num;
|
||||||
|
esc_buf = substr;
|
||||||
|
if (substr[0] == ';') {
|
||||||
|
esc_buf++;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
csi_code = substr[0];
|
||||||
|
SDL_Color new_color = WHITE;
|
||||||
|
switch (csi_code) {
|
||||||
|
case 'm':
|
||||||
|
for (int i = 0; i < nargs; i++) {
|
||||||
|
if (csi_args[i] == 31) {
|
||||||
|
new_color = RED;
|
||||||
|
} else if (csi_args[i] == 32) {
|
||||||
|
new_color = GREEN;
|
||||||
|
} else if (csi_args[i] == 33) {
|
||||||
|
new_color = YELLOW;
|
||||||
|
} else if (csi_args[i] == 34) {
|
||||||
|
new_color = BLUE;
|
||||||
|
} else if (csi_args[i] == 35) {
|
||||||
|
new_color = MAGENTA;
|
||||||
|
} else if (csi_args[i] == 36) {
|
||||||
|
new_color = SKYBLUE;
|
||||||
|
} else if (csi_args[i] == 0) {
|
||||||
|
new_color = RAYWHITE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
row_buf[ncol] = '\0';
|
||||||
|
// TODO: This looks like the actual place where we
|
||||||
|
// draw the text at a line
|
||||||
|
// Vector2 pos = { row_posx, nrow * row_height + sb.ypos };
|
||||||
|
// DrawTextEx(*fontDefault, row_buf, pos, fontsize, 0, current_color);
|
||||||
|
current_color = new_color;
|
||||||
|
ncol = 0;
|
||||||
|
c += (substr) - (sb.buf + c);
|
||||||
|
// TODO: Get the text height
|
||||||
|
// int width = MeasureTextEx(*fontDefault, row_buf, fontsize, 1).x;
|
||||||
|
// row_posx += width + 0.85;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
row_buf[ncol++] = sb.buf[c];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_RenderPresent(ctx->renderer);
|
||||||
|
}
|
||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
scrollback sb = { 0 };
|
Scrollback sb = { 0 };
|
||||||
file_descriptors fds = { 0 };
|
FileDescriptors fds = { 0 };
|
||||||
|
|
||||||
spawn(&fds);
|
spawn(&fds);
|
||||||
|
|
||||||
@ -94,10 +207,11 @@ int main(void) {
|
|||||||
printf("error initializing SDL: %s\n", SDL_GetError());
|
printf("error initializing SDL: %s\n", SDL_GetError());
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
int start_x = 20;
|
||||||
|
int start_y = 20;
|
||||||
SDL_Window* window = SDL_CreateWindow("bt",
|
SDL_Window* window = SDL_CreateWindow("bt",
|
||||||
SDL_WINDOWPOS_UNDEFINED,
|
start_x,
|
||||||
SDL_WINDOWPOS_UNDEFINED,
|
start_y,
|
||||||
SCREEN_WIDTH,
|
SCREEN_WIDTH,
|
||||||
SCREEN_HEIGHT,
|
SCREEN_HEIGHT,
|
||||||
SDL_WINDOW_SHOWN);
|
SDL_WINDOW_SHOWN);
|
||||||
@ -107,7 +221,7 @@ int main(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
|
SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
|
||||||
SDL_SetRenderDrawColor(renderer, 130, 163, 255, 1);
|
// SDL_SetRenderDrawColor(renderer, 130, 163, 255, 1);
|
||||||
TTF_Init();
|
TTF_Init();
|
||||||
TTF_Font* font = TTF_OpenFont( "./fira.ttf", 16);
|
TTF_Font* font = TTF_OpenFont( "./fira.ttf", 16);
|
||||||
|
|
||||||
@ -120,7 +234,7 @@ int main(void) {
|
|||||||
// TODO: It would be nice to figure out how to do this in SDL
|
// TODO: It would be nice to figure out how to do this in SDL
|
||||||
// SetTargetFPS(60);
|
// SetTargetFPS(60);
|
||||||
|
|
||||||
sb.capacity = 2048;
|
sb.capacity = SCROLLBACK_DEFAULT_SIZE;
|
||||||
sb.buf = malloc(sb.capacity);
|
sb.buf = malloc(sb.capacity);
|
||||||
sb.buf[0] = '\0';
|
sb.buf[0] = '\0';
|
||||||
sb.length = 0;
|
sb.length = 0;
|
||||||
@ -136,6 +250,11 @@ int main(void) {
|
|||||||
|
|
||||||
sb.ypos = 0;
|
sb.ypos = 0;
|
||||||
|
|
||||||
|
Context ctx = {
|
||||||
|
.sb = &sb,
|
||||||
|
.font = font,
|
||||||
|
.renderer = renderer
|
||||||
|
};
|
||||||
bool new_read = false;
|
bool new_read = false;
|
||||||
bool new_char = false;
|
bool new_char = false;
|
||||||
SDL_Event e;
|
SDL_Event e;
|
||||||
@ -203,108 +322,13 @@ int main(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Drawing
|
|
||||||
int nread = read_pty(&fds, &sb);
|
int nread = read_pty(&fds, &sb);
|
||||||
if (nread > 0) {
|
if (nread > 0) {
|
||||||
sb.length += nread;
|
sb.length += nread;
|
||||||
new_read = true;
|
new_read = true;
|
||||||
}
|
}
|
||||||
SDL_RenderClear(renderer);
|
|
||||||
SDL_Surface* surfaceMessage =
|
|
||||||
TTF_RenderText_Blended(font, "put your text here", WHITE);
|
|
||||||
|
|
||||||
// now you can convert it into a texture
|
render_scrollback(&ctx);
|
||||||
SDL_Texture* texture = SDL_CreateTextureFromSurface(renderer, surfaceMessage);
|
|
||||||
SDL_Rect rect;
|
|
||||||
rect.x = 0;
|
|
||||||
rect.y = 0;
|
|
||||||
rect.w = surfaceMessage->w;
|
|
||||||
rect.h = surfaceMessage->h;
|
|
||||||
|
|
||||||
SDL_RenderCopy(renderer, texture, NULL, &rect);
|
|
||||||
|
|
||||||
SDL_Color current_color = WHITE;
|
|
||||||
int col_max = 200;
|
|
||||||
char row_buf[col_max];
|
|
||||||
int nrow = 0;
|
|
||||||
int ncol = 0;
|
|
||||||
int row_height = 18;
|
|
||||||
float row_posx = 0;
|
|
||||||
// for (int c = 0; c <= sb.length; c++) {
|
|
||||||
for (int c = 0; c <= -1; c++) {
|
|
||||||
if (sb.buf[c] == '\r') {
|
|
||||||
continue;
|
|
||||||
} else if (sb.buf[c] == '\n' || sb.buf[c] == '\0' || ncol >= col_max) {
|
|
||||||
row_buf[ncol] = '\0';
|
|
||||||
// TODO: Render new line or something?
|
|
||||||
// Vector2 pos = { row_posx, nrow * row_height + sb.ypos };
|
|
||||||
// DrawTextEx(*fontDefault, row_buf, pos, fontsize, 0, current_color);
|
|
||||||
nrow++;
|
|
||||||
ncol = 0;
|
|
||||||
row_posx = 0;
|
|
||||||
} else if (sb.buf[c] == '\x1b') {
|
|
||||||
int c2 = c + 1;
|
|
||||||
// Control Sequence Introducer
|
|
||||||
int csi_args[16];
|
|
||||||
char csi_code;
|
|
||||||
int nargs = 0;
|
|
||||||
if (sb.buf[c2] == '[') {
|
|
||||||
char *esc_buf = sb.buf + c2 + 1;
|
|
||||||
while (true) {
|
|
||||||
char *substr;
|
|
||||||
long num = strtol(esc_buf, &substr, 10);
|
|
||||||
if (esc_buf != substr) {
|
|
||||||
csi_args[nargs++] = num;
|
|
||||||
esc_buf = substr;
|
|
||||||
if (substr[0] == ';') {
|
|
||||||
esc_buf++;
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
csi_code = substr[0];
|
|
||||||
SDL_Color new_color = WHITE;
|
|
||||||
switch (csi_code) {
|
|
||||||
case 'm':
|
|
||||||
for (int i = 0; i < nargs; i++) {
|
|
||||||
if (csi_args[i] == 31) {
|
|
||||||
new_color = RED;
|
|
||||||
} else if (csi_args[i] == 32) {
|
|
||||||
new_color = GREEN;
|
|
||||||
} else if (csi_args[i] == 33) {
|
|
||||||
new_color = YELLOW;
|
|
||||||
} else if (csi_args[i] == 34) {
|
|
||||||
new_color = BLUE;
|
|
||||||
} else if (csi_args[i] == 35) {
|
|
||||||
new_color = MAGENTA;
|
|
||||||
} else if (csi_args[i] == 36) {
|
|
||||||
new_color = SKYBLUE;
|
|
||||||
} else if (csi_args[i] == 0) {
|
|
||||||
new_color = RAYWHITE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
row_buf[ncol] = '\0';
|
|
||||||
// TODO: This looks like the actual place where we
|
|
||||||
// draw the text at a line
|
|
||||||
// Vector2 pos = { row_posx, nrow * row_height + sb.ypos };
|
|
||||||
// DrawTextEx(*fontDefault, row_buf, pos, fontsize, 0, current_color);
|
|
||||||
current_color = new_color;
|
|
||||||
ncol = 0;
|
|
||||||
c += (substr) - (sb.buf + c);
|
|
||||||
// TODO: Get the text height
|
|
||||||
// int width = MeasureTextEx(*fontDefault, row_buf, fontsize, 1).x;
|
|
||||||
// row_posx += width + 0.85;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
row_buf[ncol++] = sb.buf[c];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SDL_RenderPresent(renderer);
|
|
||||||
SDL_DestroyTexture(texture);
|
|
||||||
SDL_FreeSurface(surfaceMessage);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
free(sb.buf);
|
free(sb.buf);
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
#-*- mode: org -*-
|
#-*- mode: org -*-
|
||||||
#+TODO: BLOCKED TODO INPROGRESS | DONE BACKLOG
|
#+TODO: TODO | DONE
|
||||||
#+STARTUP: overview
|
#+STARTUP: overview
|
||||||
|
|
||||||
|
|
||||||
* DONE Render with Raylib
|
* DONE Render with Raylib
|
||||||
* DONE Load custom Mono font
|
* DONE Load custom Mono font
|
||||||
* DONE Render input from user
|
* DONE Render input from user
|
||||||
@ -12,17 +11,12 @@
|
|||||||
* DONE Auto-scrolling
|
* DONE Auto-scrolling
|
||||||
* DONE Render scrollback by rows
|
* DONE Render scrollback by rows
|
||||||
* DONE Handle color escape sequences
|
* DONE Handle color escape sequences
|
||||||
* TODO Backspace and Return aren't repeating [[https://github.com/raysan5/raylib/issues/2041][Issue Here]]
|
* DONE Switch to SDL2
|
||||||
* TODO Switch to SDL2
|
* TODO Clean up the rendering of the scrollback buffer
|
||||||
|
* TODO Get Backspace and Return to repeat properly [[https://github.com/raysan5/raylib/issues/2041][Why we switched to SDL]]
|
||||||
|
* TODO Render the scrollback line by line
|
||||||
* TODO Only draw scrollback that is visible
|
* TODO Only draw scrollback that is visible
|
||||||
* TODO Improve the scrolling to match first and last lines
|
|
||||||
* TODO Handle unicode characters
|
* TODO Handle unicode characters
|
||||||
* TODO Handle canonical and raw commands
|
* TODO Handle canonical and raw commands
|
||||||
* TODO Mouse copy/paste
|
* TODO Mouse copy/paste
|
||||||
* TODO Manually control when raylib updates/draws
|
* TODO Create basic vertical splits?
|
||||||
* TODO Create basic vertical splits
|
|
||||||
|
|
||||||
* COMMENT Local variables
|
|
||||||
;; Local Variables:
|
|
||||||
;; eval: (olivetti-mode t)
|
|
||||||
;; End:
|
|
Loading…
x
Reference in New Issue
Block a user