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

ref: deff0227a3d5004e863c2005fa0bf02183809dfb CTU-FEE-B0B35APO-Semestral-project/lib-gui/src/gui_component_text_view.c -rw-r--r-- 3.4 KiB
deff0227 — František Boháček feat: implement device mount using system 3 years 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;
  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