ic-explorer/textbox.c

123 lines
3.9 KiB
C

#include "textbox.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define ERROR(...) fprintf(stderr, __VA_ARGS__)
TextBox *textBoxNew(const char *text, float x, float y, float textSize,
SDL_Color color, SDL_Texture *background, TTF_Font *font,
const Window *window) {
TextBox *box = malloc(sizeof(TextBox));
if (!box) {
ERROR("error: out of memory\n");
exit(EXIT_FAILURE);
}
box->text = strdup(text);
if (!box->text) {
ERROR("error: out of memory\n");
free(box);
exit(EXIT_FAILURE);
}
box->x = x;
box->y = y;
box->textColor = color;
box->background = background;
box->font = font;
box->textSize = textSize;
textBoxUpdate(box, window);
return box;
}
void textBoxDelete(TextBox *textBox) {
free(textBox->text);
size_t i;
for (i = 0; i < textBox->lineCount; ++i) {
SDL_DestroyTexture(textBox->renderedText[i]);
}
free(textBox->renderedText);
free(textBox);
}
static void getLineSizes(TextBox *textBox, int ww, int wh, int *widths,
int *width, int *height) {
int yInc = textBox->textSize * wh;
*width = 0;
size_t i;
for (i = 0; i < textBox->lineCount; ++i) {
int tw, th;
SDL_QueryTexture(textBox->renderedText[i], NULL, NULL, &tw, &th);
int lw = ((float)tw / (float)th) * (float)yInc;
widths[i] = lw;
if (lw > *width) {
*width = lw;
}
}
*width += ww * TEXT_BOX_PADDING;
*height = yInc * textBox->lineCount;
}
void textBoxDraw(TextBox *textBox, const Window *window) {
int ww, wh;
SDL_GetWindowSize(window->obj, &ww, &wh);
int widths[textBox->lineCount];
int bw, bh;
getLineSizes(textBox, ww, wh, widths, &bw, &bh);
SDL_Rect backArea = {textBox->x * ww, textBox->y * wh, bw, bh};
if (textBox->background != NULL) {
SDL_RenderCopy(window->render, textBox->background, NULL, &backArea);
}
int yInc = textBox->textSize * wh;
size_t i;
for (i = 0; i < textBox->lineCount; ++i) {
int th;
SDL_QueryTexture(textBox->renderedText[i], NULL, NULL, NULL, &th);
SDL_Rect area = {backArea.x * (1.0f + TEXT_BOX_PADDING),
(backArea.y * (1.0f + TEXT_BOX_PADDING)) + (yInc * i),
widths[i] * (1.0f - (2 * TEXT_BOX_PADDING)),
yInc * (1.0f - (2 * TEXT_BOX_PADDING))};
SDL_RenderCopy(window->render, textBox->renderedText[i], NULL, &area);
}
}
static SDL_Texture *renderLine(const char *text, const TextBox *textBox,
const Window *window) {
SDL_Surface *surface =
TTF_RenderText_Blended(textBox->font, text, textBox->textColor);
if (!surface) {
ERROR("error: sdl2: ttf: %s\n", TTF_GetError());
exit(EXIT_FAILURE);
}
SDL_Texture *texture =
SDL_CreateTextureFromSurface(window->render, surface);
SDL_FreeSurface(surface);
if (!texture) {
ERROR("error: sdl2: %s\n", SDL_GetError());
exit(EXIT_FAILURE);
}
return texture;
}
void textBoxUpdate(TextBox *textBox, const Window *window) {
textBox->renderedText = malloc(1);
if (!textBox->renderedText) {
ERROR("error: out of memory\n");
exit(EXIT_FAILURE);
}
char *savePtr;
char *line = strtok_r(textBox->text, "\n", &savePtr);
for (textBox->lineCount = 0; line != NULL; ++textBox->lineCount) {
textBox->renderedText =
realloc(textBox->renderedText,
sizeof(SDL_Texture *) * (textBox->lineCount + 1));
if (!textBox->renderedText) {
ERROR("error: out of memory\n");
exit(EXIT_FAILURE);
}
textBox->renderedText[textBox->lineCount] =
renderLine(line, textBox, window);
line = strtok_r(NULL, "\n", &savePtr);
}
}