PatchworkOS
Loading...
Searching...
No Matches
terminal.c
Go to the documentation of this file.
1#include "terminal.h"
2#include "ansi.h"
3
4#include <errno.h>
5#include <stdio.h>
6#include <stdlib.h>
7#include <string.h>
8#include <sys/io.h>
9#include <sys/proc.h>
10
11static terminal_char_t terminal_char_create(char chr, pixel_t foreground, pixel_t background, uint16_t row,
12 uint16_t col)
13{
14 terminal_char_t termChar;
15 termChar.chr = chr;
16 termChar.foreground = foreground;
17 termChar.background = background;
18 termChar.flags = 0;
19 termChar.physicalRow = row;
20 termChar.col = col;
21 return termChar;
22}
23
25{
26 return &term->screen[(term->firstRow + row) % TERMINAL_ROWS][col];
27}
28
30{
31 return (termChar->physicalRow + TERMINAL_ROWS - term->firstRow) % TERMINAL_ROWS;
32}
33
35{
36 const theme_t* theme = element_get_theme(elem);
37
38 uint16_t row = terminal_char_row(term, termChar);
39 uint16_t col = termChar->col;
40
41 return (point_t){
42 .x = (col * font_width(term->font, "a", 1)) + theme->frameSize + theme->bigPadding,
43 .y = (row * font_height(term->font)) + theme->frameSize + theme->bigPadding,
44 };
45}
46
48{
49 point_t clientPos = terminal_char_pos(term, elem, termChar);
50 return RECT_INIT_DIM(clientPos.x, clientPos.y, font_width(term->font, "a", 1), font_height(term->font));
51}
52
53static void terminal_char_draw(terminal_t* term, element_t* elem, drawable_t* draw, terminal_char_t* termChar)
54{
55 point_t clientPos = terminal_char_pos(term, elem, termChar);
56 rect_t charRect = terminal_char_rect(term, elem, termChar);
57 draw_rect(draw, &charRect, termChar->flags & TERMINAL_INVERSE ? termChar->foreground : termChar->background);
58 draw_string(draw, term->font, &clientPos,
59 termChar->flags & TERMINAL_INVERSE ? termChar->background : termChar->foreground, &termChar->chr, 1);
60
61 if (termChar->flags & TERMINAL_UNDERLINE)
62 {
63 rect_t underlineRect = RECT_INIT_DIM(charRect.left, charRect.bottom - 2, RECT_WIDTH(&charRect), 2);
64 draw_rect(draw, &underlineRect,
65 termChar->flags & TERMINAL_INVERSE ? termChar->background : termChar->foreground);
66 }
67}
68
69static void terminal_cursor_update(terminal_t* term, element_t* elem, drawable_t* draw)
70{
71 term->prevCursor->flags &= ~TERMINAL_INVERSE;
72 terminal_char_draw(term, elem, draw, term->prevCursor);
73 if (term->isCursorVisible)
74 {
76 }
77 terminal_char_draw(term, elem, draw, term->cursor);
78 term->prevCursor = term->cursor;
79}
80
81static void terminal_clear(terminal_t* term, element_t* elem, drawable_t* draw)
82{
84 const theme_t* theme = element_get_theme(elem);
85
88
89 draw_rect(draw, &rect, term->background);
90
91 term->cursor = &term->screen[0][0];
92 term->prevCursor = &term->screen[0][0];
93}
94
95static void terminal_scroll(terminal_t* term, element_t* elem, drawable_t* draw)
96{
97 const theme_t* theme = element_get_theme(elem);
98
99 term->prevCursor->flags &= ~TERMINAL_INVERSE;
100 terminal_char_draw(term, elem, draw, term->prevCursor);
101
102 for (uint64_t col = 0; col < TERMINAL_COLUMNS; col++)
103 {
104 term->screen[term->firstRow][col] =
105 terminal_char_create(' ', theme->ansi.bright[7], theme->ansi.normal[0], term->firstRow, col);
106 }
107 term->firstRow = (term->firstRow + 1) % TERMINAL_ROWS;
108
109 rect_t contentRect = element_get_content_rect(elem);
110 RECT_SHRINK(&contentRect, theme->frameSize);
111 RECT_SHRINK(&contentRect, theme->bigPadding);
112
113 uint64_t rowHeight = font_height(term->font);
114
115 rect_t destRect = RECT_INIT_DIM(contentRect.left, contentRect.top, RECT_WIDTH(&contentRect),
116 RECT_HEIGHT(&contentRect) - rowHeight);
117 point_t srcPoint = {contentRect.left, contentRect.top + rowHeight};
118
119 draw_transfer(draw, draw, &destRect, &srcPoint);
120
121 rect_t clearRect =
122 RECT_INIT_DIM(contentRect.left, contentRect.bottom - rowHeight, RECT_WIDTH(&contentRect), rowHeight);
123 draw_rect(draw, &clearRect, term->background);
124
125 term->cursor = terminal_get_char(term, TERMINAL_ROWS - 1, 0);
126 term->prevCursor = term->cursor;
127}
128
129static void terminal_put(terminal_t* term, element_t* elem, drawable_t* draw, char chr)
130{
131 rect_t rect = element_get_content_rect(elem);
132
133 uint16_t cursorRow = terminal_char_row(term, term->cursor);
134 switch (chr)
135 {
136 case '\n':
137 if (terminal_char_row(term, term->cursor) == TERMINAL_ROWS - 1)
138 {
139 terminal_scroll(term, elem, draw);
140 }
141 else
142 {
143 term->cursor = terminal_get_char(term, cursorRow + 1, 0);
144 }
145 break;
146 case '\r':
147 term->cursor = terminal_get_char(term, cursorRow, 0);
148 break;
149 case '\b':
150 {
151 if (term->cursor->col == 0)
152 {
153 if (cursorRow == 0)
154 {
155 break;
156 }
157 term->cursor = terminal_get_char(term, cursorRow - 1, TERMINAL_COLUMNS - 1);
158 }
159 else
160 {
161 term->cursor = terminal_get_char(term, cursorRow, term->cursor->col - 1);
162 }
163 terminal_char_t* backspaceChar = term->cursor;
164 backspaceChar->chr = ' ';
165 backspaceChar->foreground = term->foreground;
166 backspaceChar->background = term->background;
167 backspaceChar->flags = term->flags;
168 terminal_char_draw(term, elem, draw, backspaceChar);
169 }
170 break;
171 case '\t':
172 {
173 uint16_t spacesToNextTabStop = 4 - (term->cursor->col % 4);
174 for (uint16_t i = 0; i < spacesToNextTabStop; i++)
175 {
176 terminal_put(term, elem, draw, ' ');
177 }
178 }
179 break;
180 default:
181 {
182 terminal_char_t* currentChar = term->cursor;
183 currentChar->chr = chr;
184 currentChar->foreground = term->foreground;
185 currentChar->background = term->background;
186 currentChar->flags = term->flags;
187 terminal_char_draw(term, elem, draw, currentChar);
188
189 uint16_t cursorRow = terminal_char_row(term, term->cursor);
190 if (term->cursor->col == TERMINAL_COLUMNS - 1)
191 {
192 if (cursorRow == TERMINAL_ROWS - 1)
193 {
194 terminal_scroll(term, elem, draw);
195 }
196 else
197 {
198 term->cursor = terminal_get_char(term, cursorRow + 1, 0);
199 }
200 }
201 else
202 {
203 term->cursor = terminal_get_char(term, cursorRow, term->cursor->col + 1);
204 }
205 }
206 break;
207 }
208}
209
210static void terminal_handle_input(terminal_t* term, element_t* elem, drawable_t* draw, const event_kbd_t* kbd)
211{
212 (void)elem;
213 (void)draw;
214
215 ansi_receiving_t ansi;
217
218 if (ansi.length > 0)
219 {
220 write(term->stdin[PIPE_WRITE], ansi.buffer, ansi.length);
221 }
222}
223
225{
226 if (ansi->ascii)
227 {
228 terminal_put(term, elem, draw, ansi->command);
229 return;
230 }
231
232 switch (ansi->command)
233 {
234 case 'H': // Cursot to (0, 0) or specified position
235 if (ansi->paramCount >= 2)
236 {
237 uint16_t row = ansi->parameters[0] == 0 ? 0 : ansi->parameters[0] - 1;
238 uint16_t col = ansi->parameters[1] == 0 ? 0 : ansi->parameters[1] - 1;
239 row = MIN(row, TERMINAL_ROWS - 1);
240 col = MIN(col, TERMINAL_COLUMNS - 1);
241 term->cursor = terminal_get_char(term, row, col);
242 break;
243 }
244 term->cursor = terminal_get_char(term, 0, 0);
245 break;
246 case 'A': // Cursor Up
247 {
248 uint16_t cursorRow = terminal_char_row(term, term->cursor);
249 uint16_t moveBy = ansi->parameters[0] == 0 ? 1 : ansi->parameters[0];
250 uint16_t startPos = cursorRow < moveBy ? 0 : cursorRow - moveBy;
251 term->cursor = terminal_get_char(term, startPos, term->cursor->col);
252 }
253 break;
254 case 'B': // Cursor Down
255 {
256 uint16_t cursorRow = terminal_char_row(term, term->cursor);
257 uint16_t moveBy = ansi->parameters[0] == 0 ? 1 : ansi->parameters[0];
258 uint16_t endPos = MIN(TERMINAL_ROWS - 1, cursorRow + moveBy);
259 term->cursor = terminal_get_char(term, endPos, term->cursor->col);
260 }
261 break;
262 case 'C': // Cursor Forward
263 {
264 uint16_t moveBy = ansi->parameters[0] == 0 ? 1 : ansi->parameters[0];
265 uint16_t endPos = MIN(TERMINAL_COLUMNS - 1, term->cursor->col + moveBy);
266 term->cursor = terminal_get_char(term, terminal_char_row(term, term->cursor), endPos);
267 }
268 break;
269 case 'D': // Cursor Backward
270 {
271 uint16_t moveBy = ansi->parameters[0] == 0 ? 1 : ansi->parameters[0];
272 uint16_t startPos = term->cursor->col < moveBy ? 0 : term->cursor->col - moveBy;
273 term->cursor = terminal_get_char(term, terminal_char_row(term, term->cursor), startPos);
274 }
275 break;
276 case 'n':
277 {
278 if (ansi->parameters[0] != 6)
279 {
280 break;
281 }
282
283 // Report Cursor Position
284 uint16_t cursorRow = terminal_char_row(term, term->cursor) + 1;
285 uint16_t cursorCol = term->cursor->col + 1;
286 char response[MAX_NAME];
287 int responseLen = snprintf(response, sizeof(response), "\033[%d;%dR", cursorRow, cursorCol);
288 write(term->stdin[PIPE_WRITE], response, responseLen);
289 }
290 break;
291 case 's': // Save Cursor Position
292 term->savedCursor = term->cursor;
293 break;
294 case 'u': // Restore Cursor Position
295 terminal_cursor_update(term, elem, draw);
296 term->prevCursor = term->cursor;
297 term->cursor = term->savedCursor;
298 break;
299 case 'J': // Erase in Screen
300 {
301 uint16_t cursorRow = terminal_char_row(term, term->cursor);
302 uint16_t cursorCol = term->cursor->col;
303 uint16_t startRow = 0;
304 uint16_t startCol = 0;
305 uint16_t endRow = 0;
306 uint16_t endCol = 0;
307 switch (ansi->parameters[0])
308 {
309 case 0: // From cursor to end of screen
310 startRow = cursorRow;
311 startCol = cursorCol;
312 endRow = TERMINAL_ROWS - 1;
313 endCol = TERMINAL_COLUMNS - 1;
314 break;
315 case 1: // From beginning of screen to cursor
316 startRow = 0;
317 startCol = 0;
318 endRow = cursorRow;
319 endCol = cursorCol;
320 break;
321 case 2: // Entire screen
322 startRow = 0;
323 startCol = 0;
324 endRow = TERMINAL_ROWS - 1;
325 endCol = TERMINAL_COLUMNS - 1;
326 break;
327 default:
328 break;
329 }
330
331 for (uint16_t row = startRow; row <= endRow; row++)
332 {
333 uint16_t colStart = (row == startRow) ? startCol : 0;
334 uint16_t colEnd = (row == endRow) ? endCol : TERMINAL_COLUMNS - 1;
335 for (uint16_t col = colStart; col <= colEnd; col++)
336 {
337 terminal_char_t* screenChar = terminal_get_char(term, row, col);
338 screenChar->chr = ' ';
339 screenChar->foreground = term->foreground;
340 screenChar->background = term->background;
341 screenChar->flags = term->flags;
342 terminal_char_draw(term, elem, draw, screenChar);
343 }
344 }
345 }
346 break;
347 case 'K': // Erase in Line
348 {
349 uint16_t cursorRow = terminal_char_row(term, term->cursor);
350 uint16_t startCol = 0;
351 uint16_t endCol = 0;
352 switch (ansi->parameters[0])
353 {
354 case 0: // From cursor to end of line
355 startCol = term->cursor->col;
356 endCol = TERMINAL_COLUMNS - 1;
357 break;
358 case 1: // From beginning of line to cursor
359 startCol = 0;
360 endCol = term->cursor->col;
361 break;
362 case 2: // Entire line
363 startCol = 0;
364 endCol = TERMINAL_COLUMNS - 1;
365 break;
366 default:
367 break;
368 }
369
370 for (uint16_t col = startCol; col <= endCol; col++)
371 {
372 terminal_char_t* lineChar = terminal_get_char(term, cursorRow, col);
373 lineChar->chr = ' ';
374 lineChar->foreground = term->foreground;
375 lineChar->background = term->background;
376 lineChar->flags = term->flags;
377 terminal_char_draw(term, elem, draw, lineChar);
378 }
379 }
380 break;
381 case 'm': // Graphic Rendition
382 {
383 if (ansi->paramCount != 1)
384 {
385 // TODO: Implement support for more advanced color stuff
386 return;
387 }
388
389 const theme_t* theme = element_get_theme(elem);
390 switch (ansi->parameters[0])
391 {
392 case 0:
393 term->foreground = theme->ansi.bright[7];
394 term->background = theme->ansi.normal[0];
395 term->flags = 0;
396 break;
397 case 1:
398 term->flags |= TERMINAL_BOLD;
399 break;
400 case 2:
401 term->flags |= TERMINAL_DIM;
402 break;
403 case 3:
404 term->flags |= TERMINAL_ITALIC;
405 break;
406 case 4:
407 term->flags |= TERMINAL_UNDERLINE;
408 break;
409 case 5:
410 term->flags |= TERMINAL_BLINK;
411 break;
412 case 6:
413 term->flags |= TERMINAL_INVERSE;
414 break;
415 case 7:
416 term->flags |= TERMINAL_HIDDEN;
417 break;
418 case 8:
420 break;
421 case 9:
423 break;
424 case 22:
425 term->flags &= ~(TERMINAL_BOLD | TERMINAL_DIM);
426 break;
427 case 23:
428 term->flags &= ~TERMINAL_ITALIC;
429 break;
430 case 24:
431 term->flags &= ~TERMINAL_UNDERLINE;
432 break;
433 case 25:
434 term->flags &= ~TERMINAL_BLINK;
435 break;
436 case 27:
437 term->flags &= ~TERMINAL_INVERSE;
438 break;
439 case 28:
440 term->flags &= ~TERMINAL_HIDDEN;
441 break;
442 case 29:
443 term->flags &= ~TERMINAL_STRIKETHROUGH;
444 break;
445 default:
446 if (ansi->parameters[0] >= 30 && ansi->parameters[0] <= 37)
447 {
448 term->foreground = theme->ansi.normal[ansi->parameters[0] - 30];
449 }
450 else if (ansi->parameters[0] == 39)
451 {
452 term->foreground = theme->ansi.bright[7];
453 }
454 else if (ansi->parameters[0] >= 90 && ansi->parameters[0] <= 97)
455 {
456 term->foreground = theme->ansi.bright[ansi->parameters[0] - 90];
457 }
458 else if (ansi->parameters[0] >= 40 && ansi->parameters[0] <= 47)
459 {
460 term->background = theme->ansi.normal[ansi->parameters[0] - 40];
461 }
462 else if (ansi->parameters[0] == 49)
463 {
464 term->background = theme->ansi.normal[0];
465 }
466 else if (ansi->parameters[0] >= 100 && ansi->parameters[0] <= 107)
467 {
468 term->background = theme->ansi.bright[ansi->parameters[0] - 100];
469 }
470 break;
471 }
472 }
473 break;
474 default:
475 terminal_put(term, elem, draw, '\033');
476 terminal_put(term, elem, draw, '[');
477 for (uint64_t i = 0; i < ansi->paramCount; i++)
478 {
479 if (i > 0)
480 {
481 terminal_put(term, elem, draw, ';');
482 }
483 char paramStr[MAX_NAME];
484 int paramLen = snprintf(paramStr, sizeof(paramStr), "%d", ansi->parameters[i]);
485 for (int j = 0; j < paramLen; j++)
486 {
487 terminal_put(term, elem, draw, paramStr[j]);
488 }
489 }
490 terminal_put(term, elem, draw, ansi->command);
491 break;
492 }
493}
494
495static void terminal_handle_output(terminal_t* term, element_t* elem, drawable_t* draw, const char* buffer,
496 uint64_t length)
497{
498 for (uint64_t i = 0; i < length; i++)
499 {
500 if (ansi_sending_parse(&term->ansi, buffer[i]))
501 {
502 ternminal_execute_ansi(term, elem, draw, &term->ansi);
503 }
504 }
505
506 term->isCursorVisible = true;
507 terminal_cursor_update(term, elem, draw);
509}
510
511static uint64_t terminal_procedure(window_t* win, element_t* elem, const event_t* event)
512{
513 switch (event->type)
514 {
515 case LEVENT_INIT:
516 {
518
519 terminal_t* term = malloc(sizeof(terminal_t));
520 if (term == NULL)
521 {
522 return ERR;
523 }
524 term->win = win;
525 term->font = ctx->font;
526 term->isCursorVisible = false;
527
528 if (open2("/dev/pipe/new", term->stdin) == ERR)
529 {
530 font_free(term->font);
531 free(term);
532 return ERR;
533 }
534 if (open2("/dev/pipe/new", term->stdout) == ERR)
535 {
536 close(term->stdin[0]);
537 close(term->stdin[1]);
538 font_free(term->font);
539 free(term);
540 return ERR;
541 }
542
543 const theme_t* theme = element_get_theme(elem);
544 term->foreground = theme->ansi.bright[7];
545 term->background = theme->ansi.normal[0];
546 term->flags = 0;
547 ansi_sending_init(&term->ansi);
548 for (uint64_t row = 0; row < TERMINAL_ROWS; row++)
549 {
550 for (uint64_t col = 0; col < TERMINAL_COLUMNS; col++)
551 {
552 term->screen[row][col] = terminal_char_create(' ', term->foreground, term->background, row, col);
553 }
554 }
555 term->firstRow = 0;
556 term->savedCursor = &term->screen[0][0];
557 term->cursor = &term->screen[0][0];
558 term->prevCursor = &term->screen[0][0];
559
560 const char* argv[] = {"/bin/shell", NULL};
561 spawn_fd_t fds[] = {
562 {.child = STDIN_FILENO, .parent = term->stdin[PIPE_READ]},
563 {.child = STDOUT_FILENO, .parent = term->stdout[PIPE_WRITE]},
564 {.child = STDERR_FILENO, .parent = term->stdout[PIPE_WRITE]},
566 };
567 term->shell = spawn(argv, fds, NULL, NULL);
568 if (term->shell == ERR)
569 {
570 close(term->stdin[0]);
571 close(term->stdin[1]);
572 close(term->stdout[0]);
573 close(term->stdout[1]);
574 font_free(term->font);
575 free(term);
576 return ERR;
577 }
578
579 element_set_private(elem, term);
581 }
582 break;
583 case LEVENT_DEINIT:
584 {
585 terminal_t* term = element_get_private(elem);
586 if (term == NULL)
587 {
588 break;
589 }
590
591 close(term->stdin[0]);
592 close(term->stdin[1]);
593 close(term->stdout[0]);
594 close(term->stdout[1]);
595
596 fd_t shellNote = openf("/proc/%d/note", term->shell);
597 writef(shellNote, "kill");
598 close(shellNote);
599 }
600 break;
601 case LEVENT_QUIT:
602 {
604 }
605 break;
606 case LEVENT_REDRAW:
607 {
608 terminal_t* term = element_get_private(elem);
609
610 drawable_t draw;
611 element_draw_begin(elem, &draw);
612 terminal_clear(term, elem, &draw);
613 element_draw_end(elem, &draw);
614 }
615 break;
616 case EVENT_TIMER:
617 {
618 terminal_t* term = element_get_private(elem);
619
621
622 term->isCursorVisible = !term->isCursorVisible;
623 drawable_t draw;
624 element_draw_begin(elem, &draw);
625 terminal_cursor_update(term, elem, &draw);
626 element_draw_end(elem, &draw);
627 }
628 break;
629 case EVENT_KBD:
630 {
631 terminal_t* term = element_get_private(elem);
632
633 if (event->kbd.type != KBD_PRESS || event->kbd.code == 0)
634 {
635 break;
636 }
637
638 drawable_t draw;
639 element_draw_begin(elem, &draw);
640 terminal_handle_input(term, elem, &draw, &event->kbd);
641 element_draw_end(elem, &draw);
642 }
643 break;
645 {
646 terminal_t* term = element_get_private(elem);
648
649 drawable_t draw;
650 element_draw_begin(elem, &draw);
651 terminal_handle_output(term, elem, &draw, ueventData->buffer, ueventData->length);
652 element_draw_end(elem, &draw);
653 }
654 break;
655 default:
656 break;
657 }
658
659 return 0;
660}
661
663{
664 const theme_t* theme = theme_global_get();
665 return TERMINAL_COLUMNS * font_width(font, "a", 1) + theme->frameSize * 2 + theme->bigPadding * 2;
666}
667
669{
670 const theme_t* theme = theme_global_get();
671 return TERMINAL_ROWS * font_height(font) + theme->frameSize * 2 + theme->bigPadding * 2;
672}
673
675{
676 terminal_init_ctx_t ctx = {
677 .font = font_new(disp, "firacode", "retina", 16),
678 };
679 if (ctx.font == NULL)
680 {
681 return NULL;
682 }
683
685 window_t* win = window_new(disp, "Terminal", &rect, SURFACE_WINDOW, WINDOW_DECO, terminal_procedure, &ctx);
686 if (win == NULL)
687 {
688 font_free(ctx.font);
689 return NULL;
690 }
691
692 if (window_set_visible(win, true) == ERR)
693 {
694 window_free(win);
695 font_free(ctx.font);
696 return NULL;
697 }
698
699 return win;
700}
701
703{
705 display_t* disp = window_get_display(win);
706
707 event_t event = {0};
708 pollfd_t fds[1] = {
709 {
710 .fd = terminal->stdout[PIPE_READ],
711 .events = POLLIN,
712 },
713 };
714 while (display_poll(disp, fds, 1, CLOCKS_NEVER) != ERR)
715 {
716 if (fds[0].revents & POLLIN)
717 {
718 uevent_terminal_data_t ueventData;
719 uint64_t readCount = read(terminal->stdout[PIPE_READ], ueventData.buffer, TERMINAL_MAX_INPUT);
720 ueventData.length = MIN(readCount, TERMINAL_MAX_INPUT);
721
723 }
724
725 event_t event = {0};
726 if (display_next(disp, &event, 0) != ERR)
727 {
728 display_dispatch(disp, &event);
729 }
730 }
731}
#define MAX_NAME
Maximum length of names.
Definition MAX_NAME.h:11
#define CLOCKS_NEVER
Definition clock_t.h:16
@ TIMER_NONE
Definition cmd.h:76
uint64_t font_width(const font_t *font, const char *string, uint64_t length)
Definition font.c:130
void font_free(font_t *font)
Definition font.c:91
font_t * font_new(display_t *disp, const char *family, const char *weight, uint64_t size)
Definition font.c:17
uint64_t font_height(const font_t *font)
Definition font.c:158
void display_disconnect(display_t *disp)
Disconnect the display connection.
Definition display.c:161
uint64_t display_poll(display_t *disp, pollfd_t *fds, uint64_t nfds, clock_t timeout)
Poll the display connection for events together with other file descriptors.
Definition display.c:288
uint64_t display_next(display_t *disp, event_t *event, clock_t timeout)
Retrieve the next event from the display connection.
Definition display.c:213
uint64_t display_dispatch(display_t *disp, const event_t *event)
Dispatch an event to the appropriate surface.
Definition display.c:440
void display_push(display_t *disp, surface_id_t target, event_type_t type, void *data, uint64_t size)
Push an event to the display's internal event queue.
Definition display.c:349
void draw_string(drawable_t *draw, const font_t *font, const point_t *point, pixel_t pixel, const char *string, uint64_t length)
Draw a string.
Definition drawable.c:591
void draw_rect(drawable_t *draw, const rect_t *rect, pixel_t pixel)
Draw a filled rectangle.
Definition drawable.c:7
void draw_transfer(drawable_t *dest, drawable_t *src, const rect_t *destRect, const point_t *srcPoint)
Transfer pixels from one drawable to another.
Definition drawable.c:462
void element_set_private(element_t *elem, void *private)
Set private data for an element.
Definition element.c:163
theme_t * element_get_theme(element_t *elem)
Get the theme of an element.
Definition element.c:401
void element_draw_end(element_t *elem, drawable_t *draw)
End drawing to an element.
Definition element.c:427
rect_t element_get_content_rect(element_t *elem)
Get the element's rectangle in local coordinates.
Definition element.c:213
void element_draw_begin(element_t *elem, drawable_t *draw)
Begin drawing to an element.
Definition element.c:411
void * element_get_private(element_t *elem)
Get private data for an element.
Definition element.c:173
#define LEVENT_QUIT
Definition event.h:103
#define LEVENT_DEINIT
Definition event.h:100
#define LEVENT_REDRAW
Definition event.h:101
#define LEVENT_INIT
Definition event.h:99
#define EVENT_KBD
Definition event.h:84
#define EVENT_TIMER
Definition event.h:86
@ SURFACE_WINDOW
Definition surface.h:35
theme_t * theme_global_get(void)
Get the global theme.
Definition theme.c:97
uint64_t window_set_visible(window_t *win, bool isVisible)
Set the visibility of the window.
Definition window.c:692
surface_id_t window_get_id(window_t *win)
Get the surface ID of the window.
Definition window.c:477
uint64_t window_set_timer(window_t *win, timer_flags_t flags, clock_t timeout)
Set the window timer.
Definition window.c:533
window_t * window_new(display_t *disp, const char *name, const rect_t *rect, surface_type_t type, window_flags_t flags, procedure_t procedure, void *private)
Allocate and initialize a new window.
Definition window.c:301
element_t * window_get_client_element(window_t *win)
Get the client element of the window.
Definition window.c:497
void window_free(window_t *win)
Free a window.
Definition window.c:415
display_t * window_get_display(window_t *win)
Get the display associated with the window.
Definition window.c:467
@ WINDOW_DECO
Enable decorations (titlebar, close/minimize buttons, etc).
Definition window.h:46
uint64_t writef(fd_t fd, const char *_RESTRICT format,...)
Wrapper for writing a formatted string to a file.
Definition writef.c:9
#define PIPE_READ
Pipe read end.
Definition io.h:55
uint64_t close(fd_t fd)
System call for closing files.
Definition close.c:9
fd_t openf(const char *_RESTRICT format,...)
Wrapper for opening files with a formatted path.
Definition openf.c:9
#define PIPE_WRITE
Pipe write end.
Definition io.h:63
#define STDOUT_FILENO
Definition io.h:45
uint64_t read(fd_t fd, void *buffer, uint64_t count)
System call for reading from files.
Definition read.c:9
uint64_t open2(const char *path, fd_t fd[2])
System call for opening 2 file descriptors from one file.
Definition open2.c:9
#define STDERR_FILENO
Definition io.h:46
uint64_t write(fd_t fd, const void *buffer, uint64_t count)
System call for writing to files.
Definition write.c:9
#define STDIN_FILENO
Definition io.h:44
@ POLLIN
File descriptor is ready to read.
Definition io.h:290
@ KBD_PRESS
Key press event.
Definition kbd.h:287
#define MIN(x, y)
Definition math.h:16
pid_t spawn(const char **argv, const spawn_fd_t *fds, const char *cwd, spawn_attr_t *attr)
System call for creating child processes.
Definition spawn.c:6
#define SPAWN_FD_END
Spawn fds termination constant.
Definition proc.h:82
#define NULL
Pointer error value.
Definition NULL.h:23
#define ERR
Integer error value.
Definition ERR.h:17
__UINT64_TYPE__ fd_t
A file descriptor.
Definition fd_t.h:12
static bool ansi_sending_parse(ansi_sending_t *ansi, char chr)
Parse a character for ANSI sending.
Definition ansi.h:170
static void ansi_sending_init(ansi_sending_t *ansi)
Initialize an ANSI sending structure.
Definition ansi.h:153
static void ansi_kbd_to_receiving(ansi_receiving_t *ansi, const event_kbd_t *kbd)
Convert a keycode to an ANSI receiving sequence.
Definition ansi.h:40
void terminal_loop(window_t *win)
Terminal main loop.
Definition terminal.c:702
#define TERMINAL_BLINK_INTERVAL
Terminal blink rate.
Definition terminal.h:30
#define TERMINAL_MAX_INPUT
Maximum terminal input length.
Definition terminal.h:50
#define TERMINAL_COLUMNS
Terminal columns.
Definition terminal.h:35
#define UEVENT_TERMINAL_DATA
Event sent from the terminals io thread to the main thread when there is data available.
Definition terminal.h:45
window_t * terminal_new(display_t *disp)
Create a new terminal window.
Definition terminal.c:674
#define TERMINAL_ROWS
Terminal rows.
Definition terminal.h:40
@ TERMINAL_DIM
Definition terminal.h:74
@ TERMINAL_STRIKETHROUGH
Definition terminal.h:80
@ TERMINAL_BLINK
Definition terminal.h:77
@ TERMINAL_ITALIC
Definition terminal.h:75
@ TERMINAL_UNDERLINE
Definition terminal.h:76
@ TERMINAL_HIDDEN
Definition terminal.h:79
@ TERMINAL_INVERSE
Definition terminal.h:78
@ TERMINAL_BOLD
Definition terminal.h:73
EFI_PHYSICAL_ADDRESS buffer
Definition mem.c:15
uint32_t pixel_t
Definition pixel.h:11
static kbd_t * kbd
Definition ps2_kbd.c:10
#define RECT_SHRINK(rect, margin)
Definition rect.h:81
#define RECT_INIT_DIM(x, y, width, height)
Definition rect.h:32
#define RECT_HEIGHT(rect)
Definition rect.h:39
#define RECT_WIDTH(rect)
Definition rect.h:38
__UINT64_TYPE__ uint64_t
Definition stdint.h:17
__UINT16_TYPE__ uint16_t
Definition stdint.h:13
_PUBLIC int snprintf(char *_RESTRICT s, size_t n, const char *_RESTRICT format,...)
Definition snprintf.c:3
_PUBLIC void * malloc(size_t size)
Definition malloc.c:5
_PUBLIC void free(void *ptr)
Definition free.c:11
ANSI receiving structure.
Definition ansi.h:27
uint8_t length
Definition ansi.h:29
char buffer[ANSI_MAX_LENGTH]
Definition ansi.h:28
ANSI sending structure.
Definition ansi.h:139
uint8_t paramCount
Definition ansi.h:143
bool ascii
Definition ansi.h:145
char command
Definition ansi.h:144
uint8_t parameters[ANSI_MAX_LENGTH]
Definition ansi.h:142
Opaque display structure.
Definition internal.h:61
Drawable structure.
Definition drawable.h:35
Opaque element structure.
Definition internal.h:23
Keyboard event.
Definition event.h:138
kbd_event_type_t type
Definition event.h:139
keycode_t code
Definition event.h:141
Event structure.
Definition event.h:271
event_kbd_t kbd
Definition event.h:277
event_type_t type
Definition event.h:272
uint8_t raw[EVENT_MAX_DATA]
Definition event.h:290
int64_t y
Definition point.h:14
int64_t x
Definition point.h:13
Poll file descriptor structure.
Definition io.h:307
fd_t fd
The file descriptor to poll.
Definition io.h:308
Definition rect.h:13
int32_t bottom
Definition rect.h:17
int32_t top
Definition rect.h:15
int32_t left
Definition rect.h:14
Stucture used to duplicate fds in spawn().
Definition proc.h:55
fd_t child
The destination file descriptor in the child.
Definition proc.h:56
Terminal character.
Definition terminal.h:88
pixel_t foreground
Definition terminal.h:90
pixel_t background
Definition terminal.h:91
uint16_t col
Definition terminal.h:93
uint16_t physicalRow
Definition terminal.h:94
terminal_flags_t flags
Definition terminal.h:92
Terminal initialization context.
Definition terminal.h:127
Terminal structure.
Definition terminal.h:102
pixel_t background
Definition terminal.h:109
terminal_char_t * savedCursor
Definition terminal.h:114
terminal_char_t * prevCursor
Definition terminal.h:115
terminal_flags_t flags
Definition terminal.h:110
fd_t stdin[2]
Definition terminal.h:106
fd_t stdout[2]
Definition terminal.h:107
font_t * font
Definition terminal.h:104
window_t * win
Definition terminal.h:103
terminal_char_t screen[TERMINAL_ROWS][TERMINAL_COLUMNS]
Definition terminal.h:112
pid_t shell
Definition terminal.h:117
bool isCursorVisible
Definition terminal.h:105
pixel_t foreground
Definition terminal.h:108
uint64_t firstRow
Definition terminal.h:113
ansi_sending_t ansi
Definition terminal.h:111
terminal_char_t * cursor
Definition terminal.h:116
pixel_t bright[THEME_ANSI_COLOR_COUNT]
Definition theme.h:61
pixel_t normal[THEME_ANSI_COLOR_COUNT]
Definition theme.h:60
Theme structure.
Definition theme.h:71
int64_t smallPadding
Definition theme.h:88
theme_ansi_t ansi
Definition theme.h:90
int64_t frameSize
Definition theme.h:83
int64_t bigPadding
Definition theme.h:87
Terminal data event structure. struct uevent_terminal_data_t.
Definition terminal.h:59
char buffer[TERMINAL_MAX_INPUT]
Definition terminal.h:60
Opaque window structure.
Definition internal.h:44
static void terminal_put(terminal_t *term, element_t *elem, drawable_t *draw, char chr)
Definition terminal.c:129
static void terminal_clear(terminal_t *term, element_t *elem, drawable_t *draw)
Definition terminal.c:81
static rect_t terminal_char_rect(terminal_t *term, element_t *elem, terminal_char_t *termChar)
Definition terminal.c:47
static terminal_char_t * terminal_get_char(terminal_t *term, uint16_t row, uint16_t col)
Definition terminal.c:24
static uint64_t terminal_procedure(window_t *win, element_t *elem, const event_t *event)
Definition terminal.c:511
static void terminal_char_draw(terminal_t *term, element_t *elem, drawable_t *draw, terminal_char_t *termChar)
Definition terminal.c:53
static uint64_t terminal_pixel_width(font_t *font)
Definition terminal.c:662
static void ternminal_execute_ansi(terminal_t *term, element_t *elem, drawable_t *draw, ansi_sending_t *ansi)
Definition terminal.c:224
static void terminal_cursor_update(terminal_t *term, element_t *elem, drawable_t *draw)
Definition terminal.c:69
static void terminal_scroll(terminal_t *term, element_t *elem, drawable_t *draw)
Definition terminal.c:95
static void terminal_handle_input(terminal_t *term, element_t *elem, drawable_t *draw, const event_kbd_t *kbd)
Definition terminal.c:210
static uint64_t terminal_pixel_height(font_t *font)
Definition terminal.c:668
static void terminal_handle_output(terminal_t *term, element_t *elem, drawable_t *draw, const char *buffer, uint64_t length)
Definition terminal.c:495
static point_t terminal_char_pos(terminal_t *term, element_t *elem, terminal_char_t *termChar)
Definition terminal.c:34
static terminal_char_t terminal_char_create(char chr, pixel_t foreground, pixel_t background, uint16_t row, uint16_t col)
Definition terminal.c:11
static uint16_t terminal_char_row(terminal_t *term, terminal_char_t *termChar)
Definition terminal.c:29
static theme_t theme
Definition theme.c:12