~ruther/CTU-FEE-B0B35APO-Semestral-project

ref: 7aa0ada94624cf7cf1d81d2b5d0d7d43770b5757 CTU-FEE-B0B35APO-Semestral-project/lib-gui/src/gui_component_text_view.c -rw-r--r-- 3.4 KiB
7aa0ada9 — Rutherther chore: fix image in readme 1 year, 10 months ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#include "gui_component_text_view.h"
#include "display_utils.h"
#include "input.h"
#include "renderer.h"
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include "direction.h"
#include "keyboard_const.h"
#include "rotation_const.h"

multiline_text_t *gui_multiline_text_create(font_t *font, display_pixel_t color, char *text) {
  size_t len = strlen(text) + 1;
  size_t lines = 1;

  for (int i = 0; i < len; i++) {
    if (text[i] == '\n') {
      lines++;
    }
  }

  void* new = realloc(text, len + sizeof(multiline_text_t) + sizeof(line_t) * lines);
  if (new == NULL) {
    free(text);
    return NULL;
  }

  text = new;

  multiline_text_t *multiline_text = (multiline_text_t*)(new + len);
  line_t *line_ptr = (line_t*)(new + len + sizeof(multiline_text_t));

  multiline_text->font = font;
  multiline_text->color = color;
  multiline_text->lines = line_ptr;
  multiline_text->lines_count = lines;
  multiline_text->text = text;

  bool new_line = false;
  uint32_t line_index = 0;
  uint32_t line_length = 0;
  char *line_str_ptr = text;

  for (int i = 0; i < len; i++) {
    if (new_line) {
      line_ptr[line_index].line = line_str_ptr;
      line_ptr[line_index++].length = line_length;
      line_str_ptr += line_length + 1;
      line_length = 0;
      new_line = false;
    }

    if (text[i] == '\n') {
      text[i] = '\0';
      new_line = true;
    } else {
      line_length++;
    }
  }

  if (line_index < lines) {
    line_ptr[line_index].line = line_str_ptr;
    line_ptr[line_index].length = line_length;
  }

  return multiline_text;
}

void gui_text_view_scroll(component_t *text_view, int32_t x, int32_t y) {
  text_view->x -= x;
  text_view->y -= y;
}

void gui_text_view_reset_scroll(component_t *text_view) {
  text_view->x = 0;
  text_view->y = 0;
}

void gui_text_view_full_scroll(component_t *text_view) {
  text_view->x = 0;
  text_view->y = INT16_MIN; 
}

uint16_t gui_text_view_get_lines_scrolled(component_t *component) {
  multiline_text_t *text = (multiline_text_t *)component->state;
  return (-component->y) / (text->font->size + text->font->line_spacing);
}

void gui_text_view_render(container_t *container, component_t *component,
                          gui_t *gui) {
  multiline_text_t *text = (multiline_text_t*)component->state;
  font_t *font = text->font;
  int32_t x_offset = component->x, y_offset = component->y;

  if (x_offset > 0) {
    x_offset = 0;
  }

  if (y_offset >= 0) {
    y_offset = 0;
  } else if (y_offset < -(font->size + font->line_spacing) * (text->lines_count) + gui->size.y - container->y) {
    y_offset = -(font->size + font->line_spacing) * (text->lines_count) + gui->size.y - container->y;
  }

  component->x = x_offset;
  component->y = y_offset;

  int16_t first_line_index = -y_offset / (font->size + font->line_spacing);
  int16_t lines_count = gui->size.y / font->size + 1;
  if (first_line_index < 0) {
    first_line_index = 0;
  }
  int16_t last_line_index = lines_count + first_line_index;

  y_offset += first_line_index * (font->size + font->line_spacing);

  for (int i = first_line_index; i < last_line_index && i < text->lines_count;
       i++) {
    line_t *line = &text->lines[i];
    size2d_t size = renderer_write_string(gui->renderer, x_offset, y_offset,
                                          line->length, font, line->line, text->color);

    y_offset += size.y;
  }
}

void gui_text_view_update(container_t *container, component_t *component,
                          gui_t *gui) {
  // do nothing
}
Do not follow this link