summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--buffer.c43
-rw-r--r--main.c17
-rw-r--r--text.c12
-rw-r--r--text.h3
4 files changed, 65 insertions, 10 deletions
diff --git a/buffer.c b/buffer.c
index cd6c353..0a19aa5 100644
--- a/buffer.c
+++ b/buffer.c
@@ -24,6 +24,8 @@ typedef struct {
u32 nblocks; // number of text blocks
double scroll_x, scroll_y; // number of characters scrolled in the x/y direction
TextBlock *blocks;
+ Font *font;
+ float x1, y1, x2, y2;
} TextBuffer;
// Returns a new block added at index `where`,
@@ -61,11 +63,15 @@ static TextBlock *text_buffer_add_block(TextBuffer *buffer, u32 where) {
return block;
}
+void text_buffer_create(TextBuffer *buffer, Font *font) {
+ util_zero_memory(buffer, sizeof *buffer);
+ buffer->font = font;
+}
+
Status text_buffer_load_file(TextBuffer *buffer, FILE *fp) {
char block_contents[TEXT_BLOCK_DEFAULT_SIZE];
size_t bytes_read;
-
- util_zero_memory(buffer, sizeof *buffer);
+ // @TODO: @TODO: IMPORTANT! make this work if buffer already has a file
// read file one block at a time
do {
@@ -118,13 +124,26 @@ void text_buffer_free(TextBuffer *buffer) {
free(blocks);
}
+// make sure we don't scroll too far
+static void text_buffer_correct_scroll(TextBuffer *buffer) {
+ if (buffer->scroll_x < 0)
+ buffer->scroll_x = 0;
+ if (buffer->scroll_y < 0)
+ buffer->scroll_y = 0;
+ // @TODO: maximum scroll_x and scroll_y
+}
+
void text_buffer_scroll(TextBuffer *buffer, double dx, double dy) {
buffer->scroll_x += dx;
buffer->scroll_y += dy;
+ text_buffer_correct_scroll(buffer);
}
// Render the text buffer in the given rectangle
-void text_buffer_render(TextBuffer *buffer, Font *font, float x1, float y1, float x2, float y2) {
+// NOTE: also corrects scroll
+void text_buffer_render(TextBuffer *buffer, float x1, float y1, float x2, float y2) {
+ buffer->x1 = x1; buffer->y1 = y1; buffer->x2 = x2; buffer->y2 = y2;
+ Font *font = buffer->font;
mbstate_t mbstate = {0};
uint nblocks = buffer->nblocks;
TextBlock *blocks = buffer->blocks;
@@ -140,14 +159,17 @@ void text_buffer_render(TextBuffer *buffer, Font *font, float x1, float y1, floa
glColor3f(1,1,1);
text_chars_begin(font);
+
+ // what x coordinate to start rendering the text from
+ float render_start_x = x1 - (float)buffer->scroll_x * char_height;
+
TextRenderState text_state = {
- .x = x1, .y = y1 + text_font_char_height(font),
+ .x = render_start_x, .y = y1 + text_font_char_height(font),
.min_x = x1, .min_y = y1,
.max_x = x2, .max_y = y2
};
// @TODO: make this better (we should figure out where to start rendering, etc.)
- text_state.x -= (float)buffer->scroll_x * char_height;
text_state.y -= (float)buffer->scroll_y * char_height;
for (uint block_idx = 0; block_idx < nblocks; ++block_idx) {
@@ -175,7 +197,7 @@ void text_buffer_render(TextBuffer *buffer, Font *font, float x1, float y1, floa
}
switch (c) {
case L'\n':
- text_state.x = x1;
+ text_state.x = render_start_x;
text_state.y += text_font_char_height(font);
break;
case L'\r': break; // for CRLF line endings
@@ -192,3 +214,12 @@ void text_buffer_render(TextBuffer *buffer, Font *font, float x1, float y1, floa
text_chars_end(font);
}
+// returns the number of rows of text that can fit in the buffer, rounded down.
+int text_buffer_num_rows(TextBuffer *buffer) {
+ return (int)((buffer->y2 - buffer->y1) / text_font_char_height(buffer->font));
+}
+
+// returns the number of columns of text that can fit in the buffer, rounded down.
+int text_buffer_num_cols(TextBuffer *buffer) {
+ return (int)((buffer->x2 - buffer->x1) / text_font_char_width(buffer->font));
+}
diff --git a/main.c b/main.c
index feb526a..3544919 100644
--- a/main.c
+++ b/main.c
@@ -66,6 +66,7 @@ int main(void) {
bool quit = false;
TextBuffer text_buffer;
+ text_buffer_create(&text_buffer, font);
{
FILE *fp = fopen("main.c", "r");
@@ -84,6 +85,7 @@ int main(void) {
while (SDL_PollEvent(&event)) {
+ // @TODO: make a function to handle text buffer events
switch (event.type) {
case SDL_QUIT:
quit = true;
@@ -94,6 +96,16 @@ int main(void) {
double scroll_speed = 2.5;
text_buffer_scroll(&text_buffer, dx * scroll_speed, dy * scroll_speed);
} break;
+ case SDL_KEYDOWN: {
+ switch (event.key.keysym.sym) {
+ case SDLK_PAGEUP:
+ text_buffer_scroll(&text_buffer, 0, -text_buffer_num_rows(&text_buffer));
+ break;
+ case SDLK_PAGEDOWN:
+ text_buffer_scroll(&text_buffer, 0, +text_buffer_num_rows(&text_buffer));
+ break;
+ }
+ } break;
}
}
@@ -115,13 +127,10 @@ int main(void) {
text_buffer_scroll(&text_buffer, 0, -scroll_amount);
if (keyboard_state[SDL_SCANCODE_DOWN])
text_buffer_scroll(&text_buffer, 0, +scroll_amount);
- // @TODO: get this to work
- #if 0
if (keyboard_state[SDL_SCANCODE_LEFT])
text_buffer_scroll(&text_buffer, -scroll_amount, 0);
if (keyboard_state[SDL_SCANCODE_RIGHT])
text_buffer_scroll(&text_buffer, +scroll_amount, 0);
- #endif
}
@@ -142,7 +151,7 @@ int main(void) {
{
float x1 = 50, y1 = 50, x2 = window_widthf-50, y2 = window_heightf-50;
- text_buffer_render(&text_buffer, font, x1, y1, x2, y2);
+ text_buffer_render(&text_buffer, x1, y1, x2, y2);
if (text_has_err()) {
printf("Text error: %s\n", text_get_err());
break;
diff --git a/text.c b/text.c
index 5906e5c..1913bfc 100644
--- a/text.c
+++ b/text.c
@@ -15,6 +15,7 @@ no_warn_end
#define CHAR_PAGE_COUNT UNICODE_CODE_POINTS / CHAR_PAGE_SIZE
struct Font {
+ float char_width; // width of the character 'a'. calculated when font is loaded.
float char_height;
GLuint textures[CHAR_PAGE_COUNT];
int tex_widths[CHAR_PAGE_COUNT], tex_heights[CHAR_PAGE_COUNT];
@@ -114,6 +115,13 @@ Font *text_font_load(char const *ttf_filename, float font_size) {
font->char_height = font_size;
font->ttf_data = file_data;
text_load_char_page(font, 0); // load page with Latin text, etc.
+ { // calculate width of the character 'a'
+ stbtt_aligned_quad q = {0};
+ float x = 0, y = 0;
+ stbtt_GetBakedQuad(font->char_pages[0], font->tex_widths[0], font->tex_heights[0],
+ 'a', &x, &y, &q, 1);
+ font->char_width = x;
+ }
font->curr_page = -1;
} else {
text_set_err("Couldn't read font file.");
@@ -140,6 +148,10 @@ float text_font_char_height(Font *font) {
return font->char_height;
}
+float text_font_char_width(Font *font) {
+ return font->char_width;
+}
+
static void text_render_with_page(Font *font, int page) {
if (font->curr_page != page) {
if (font->curr_page != -1) {
diff --git a/text.h b/text.h
index 9f0d351..25c5e49 100644
--- a/text.h
+++ b/text.h
@@ -25,6 +25,9 @@ extern void text_clear_err(void);
extern Font *text_font_load(char const *ttf_filename, float font_size);
// Height of a character of this font in pixels.
extern float text_font_char_height(Font *font);
+// Width of the character 'a' of this font in pixels.
+// This is meant to be only used for monospace fonts.
+extern float text_font_char_width(Font *font);
// Render some UTF-8 text to the screen (simple interface).
extern void text_render(Font *font, char const *text, float x, float y);
// Get the dimensions of some text.