source: mainline/uspace/lib/gui/terminal.c@ d55ab823

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since d55ab823 was 26653c9, checked in by Jiri Svoboda <jiri@…>, 5 years ago

Move fixed width font to its own library, libfbfont

We've actually three copies, one in kernel/, one in output server
(not used anymorei, removed), one in libdraw (now moved to separate library
libfbfont). So we are left with two copies, that could be coalesced
somehow in the future.

  • Property mode set to 100644
File size: 19.8 KB
Line 
1/*
2 * Copyright (c) 2012 Petr Koupy
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup gui
30 * @{
31 */
32/**
33 * @file
34 */
35
36#include <errno.h>
37#include <stdlib.h>
38#include <io/chargrid.h>
39#include <draw/surface.h>
40#include <draw/gfx.h>
41#include <fbfont/font-8x16.h>
42#include <io/con_srv.h>
43#include <io/concaps.h>
44#include <io/console.h>
45#include <loc.h>
46#include <task.h>
47#include <adt/list.h>
48#include <adt/prodcons.h>
49#include <stdarg.h>
50#include <str.h>
51#include "window.h"
52#include "terminal.h"
53
54#define NAME "vterm"
55#define NAMESPACE "vterm"
56
57#define LOCFS_MOUNT_POINT "/loc"
58
59#define APP_GETTERM "/app/getterm"
60
61#define TERM_CAPS \
62 (CONSOLE_CAP_STYLE | CONSOLE_CAP_INDEXED | CONSOLE_CAP_RGB)
63
64static LIST_INITIALIZE(terms);
65
66static errno_t term_open(con_srvs_t *, con_srv_t *);
67static errno_t term_close(con_srv_t *);
68static errno_t term_read(con_srv_t *, void *, size_t, size_t *);
69static errno_t term_write(con_srv_t *, void *, size_t, size_t *);
70static void term_sync(con_srv_t *);
71static void term_clear(con_srv_t *);
72static void term_set_pos(con_srv_t *, sysarg_t col, sysarg_t row);
73static errno_t term_get_pos(con_srv_t *, sysarg_t *, sysarg_t *);
74static errno_t term_get_size(con_srv_t *, sysarg_t *, sysarg_t *);
75static errno_t term_get_color_cap(con_srv_t *, console_caps_t *);
76static void term_set_style(con_srv_t *, console_style_t);
77static void term_set_color(con_srv_t *, console_color_t, console_color_t,
78 console_color_attr_t);
79static void term_set_rgb_color(con_srv_t *, pixel_t, pixel_t);
80static void term_set_cursor_visibility(con_srv_t *, bool);
81static errno_t term_get_event(con_srv_t *, cons_event_t *);
82
83static con_ops_t con_ops = {
84 .open = term_open,
85 .close = term_close,
86 .read = term_read,
87 .write = term_write,
88 .sync = term_sync,
89 .clear = term_clear,
90 .set_pos = term_set_pos,
91 .get_pos = term_get_pos,
92 .get_size = term_get_size,
93 .get_color_cap = term_get_color_cap,
94 .set_style = term_set_style,
95 .set_color = term_set_color,
96 .set_rgb_color = term_set_rgb_color,
97 .set_cursor_visibility = term_set_cursor_visibility,
98 .get_event = term_get_event
99};
100
101static terminal_t *srv_to_terminal(con_srv_t *srv)
102{
103 return srv->srvs->sarg;
104}
105
106static void getterm(const char *svc, const char *app)
107{
108 task_spawnl(NULL, NULL, APP_GETTERM, APP_GETTERM, svc,
109 LOCFS_MOUNT_POINT, "--msg", "--wait", "--", app, NULL);
110}
111
112static pixel_t color_table[16] = {
113 [COLOR_BLACK] = PIXEL(255, 0, 0, 0),
114 [COLOR_BLUE] = PIXEL(255, 0, 0, 240),
115 [COLOR_GREEN] = PIXEL(255, 0, 240, 0),
116 [COLOR_CYAN] = PIXEL(255, 0, 240, 240),
117 [COLOR_RED] = PIXEL(255, 240, 0, 0),
118 [COLOR_MAGENTA] = PIXEL(255, 240, 0, 240),
119 [COLOR_YELLOW] = PIXEL(255, 240, 240, 0),
120 [COLOR_WHITE] = PIXEL(255, 240, 240, 240),
121
122 [COLOR_BLACK + 8] = PIXEL(255, 0, 0, 0),
123 [COLOR_BLUE + 8] = PIXEL(255, 0, 0, 255),
124 [COLOR_GREEN + 8] = PIXEL(255, 0, 255, 0),
125 [COLOR_CYAN + 8] = PIXEL(255, 0, 255, 255),
126 [COLOR_RED + 8] = PIXEL(255, 255, 0, 0),
127 [COLOR_MAGENTA + 8] = PIXEL(255, 255, 0, 255),
128 [COLOR_YELLOW + 8] = PIXEL(255, 255, 255, 0),
129 [COLOR_WHITE + 8] = PIXEL(255, 255, 255, 255),
130};
131
132static inline void attrs_rgb(char_attrs_t attrs, pixel_t *bgcolor, pixel_t *fgcolor)
133{
134 switch (attrs.type) {
135 case CHAR_ATTR_STYLE:
136 switch (attrs.val.style) {
137 case STYLE_NORMAL:
138 *bgcolor = color_table[COLOR_WHITE];
139 *fgcolor = color_table[COLOR_BLACK];
140 break;
141 case STYLE_EMPHASIS:
142 *bgcolor = color_table[COLOR_WHITE];
143 *fgcolor = color_table[COLOR_RED];
144 break;
145 case STYLE_INVERTED:
146 *bgcolor = color_table[COLOR_BLACK];
147 *fgcolor = color_table[COLOR_WHITE];
148 break;
149 case STYLE_SELECTED:
150 *bgcolor = color_table[COLOR_RED];
151 *fgcolor = color_table[COLOR_WHITE];
152 break;
153 }
154 break;
155 case CHAR_ATTR_INDEX:
156 *bgcolor = color_table[(attrs.val.index.bgcolor & 7) |
157 ((attrs.val.index.attr & CATTR_BRIGHT) ? 8 : 0)];
158 *fgcolor = color_table[(attrs.val.index.fgcolor & 7) |
159 ((attrs.val.index.attr & CATTR_BRIGHT) ? 8 : 0)];
160 break;
161 case CHAR_ATTR_RGB:
162 *bgcolor = 0xff000000 | attrs.val.rgb.bgcolor;
163 *fgcolor = 0xff000000 | attrs.val.rgb.fgcolor;
164 break;
165 }
166}
167
168static void term_update_char(terminal_t *term, surface_t *surface,
169 sysarg_t sx, sysarg_t sy, sysarg_t col, sysarg_t row)
170{
171 charfield_t *field =
172 chargrid_charfield_at(term->backbuf, col, row);
173
174 bool inverted = chargrid_cursor_at(term->backbuf, col, row);
175
176 sysarg_t bx = sx + (col * FONT_WIDTH);
177 sysarg_t by = sy + (row * FONT_SCANLINES);
178
179 pixel_t bgcolor = 0;
180 pixel_t fgcolor = 0;
181
182 if (inverted)
183 attrs_rgb(field->attrs, &fgcolor, &bgcolor);
184 else
185 attrs_rgb(field->attrs, &bgcolor, &fgcolor);
186
187 // FIXME: Glyph type should be actually uint32_t
188 // for full UTF-32 coverage.
189
190 uint16_t glyph = fb_font_glyph(field->ch, NULL);
191
192 for (unsigned int y = 0; y < FONT_SCANLINES; y++) {
193 pixel_t *dst = pixelmap_pixel_at(
194 surface_pixmap_access(surface), bx, by + y);
195 pixel_t *dst_max = pixelmap_pixel_at(
196 surface_pixmap_access(surface), bx + FONT_WIDTH - 1, by + y);
197 if (!dst || !dst_max)
198 continue;
199 int count = FONT_WIDTH;
200 while (count-- != 0) {
201 *dst++ = (fb_font[glyph][y] & (1 << count)) ? fgcolor : bgcolor;
202 }
203 }
204 surface_add_damaged_region(surface, bx, by, FONT_WIDTH, FONT_SCANLINES);
205}
206
207static bool term_update_scroll(terminal_t *term, surface_t *surface,
208 sysarg_t sx, sysarg_t sy)
209{
210 sysarg_t top_row = chargrid_get_top_row(term->frontbuf);
211
212 if (term->top_row == top_row)
213 return false;
214
215 term->top_row = top_row;
216
217 for (sysarg_t row = 0; row < term->rows; row++) {
218 for (sysarg_t col = 0; col < term->cols; col++) {
219 charfield_t *front_field =
220 chargrid_charfield_at(term->frontbuf, col, row);
221 charfield_t *back_field =
222 chargrid_charfield_at(term->backbuf, col, row);
223 bool update = false;
224
225 if (front_field->ch != back_field->ch) {
226 back_field->ch = front_field->ch;
227 update = true;
228 }
229
230 if (!attrs_same(front_field->attrs, back_field->attrs)) {
231 back_field->attrs = front_field->attrs;
232 update = true;
233 }
234
235 front_field->flags &= ~CHAR_FLAG_DIRTY;
236
237 if (update)
238 term_update_char(term, surface, sx, sy, col, row);
239 }
240 }
241
242 return true;
243}
244
245static bool term_update_cursor(terminal_t *term, surface_t *surface,
246 sysarg_t sx, sysarg_t sy)
247{
248 bool damage = false;
249
250 sysarg_t front_col;
251 sysarg_t front_row;
252 chargrid_get_cursor(term->frontbuf, &front_col, &front_row);
253
254 sysarg_t back_col;
255 sysarg_t back_row;
256 chargrid_get_cursor(term->backbuf, &back_col, &back_row);
257
258 bool front_visibility =
259 chargrid_get_cursor_visibility(term->frontbuf) &&
260 term->widget.window->is_focused;
261 bool back_visibility =
262 chargrid_get_cursor_visibility(term->backbuf);
263
264 if (front_visibility != back_visibility) {
265 chargrid_set_cursor_visibility(term->backbuf,
266 front_visibility);
267 term_update_char(term, surface, sx, sy, back_col, back_row);
268 damage = true;
269 }
270
271 if ((front_col != back_col) || (front_row != back_row)) {
272 chargrid_set_cursor(term->backbuf, front_col, front_row);
273 term_update_char(term, surface, sx, sy, back_col, back_row);
274 term_update_char(term, surface, sx, sy, front_col, front_row);
275 damage = true;
276 }
277
278 return damage;
279}
280
281static void term_update(terminal_t *term)
282{
283 fibril_mutex_lock(&term->mtx);
284
285 surface_t *surface = window_claim(term->widget.window);
286 if (!surface) {
287 window_yield(term->widget.window);
288 fibril_mutex_unlock(&term->mtx);
289 return;
290 }
291
292 bool damage = false;
293 sysarg_t sx = term->widget.hpos;
294 sysarg_t sy = term->widget.vpos;
295
296 if (term_update_scroll(term, surface, sx, sy)) {
297 damage = true;
298 } else {
299 for (sysarg_t y = 0; y < term->rows; y++) {
300 for (sysarg_t x = 0; x < term->cols; x++) {
301 charfield_t *front_field =
302 chargrid_charfield_at(term->frontbuf, x, y);
303 charfield_t *back_field =
304 chargrid_charfield_at(term->backbuf, x, y);
305 bool update = false;
306
307 if ((front_field->flags & CHAR_FLAG_DIRTY) ==
308 CHAR_FLAG_DIRTY) {
309 if (front_field->ch != back_field->ch) {
310 back_field->ch = front_field->ch;
311 update = true;
312 }
313
314 if (!attrs_same(front_field->attrs,
315 back_field->attrs)) {
316 back_field->attrs = front_field->attrs;
317 update = true;
318 }
319
320 front_field->flags &= ~CHAR_FLAG_DIRTY;
321 }
322
323 if (update) {
324 term_update_char(term, surface, sx, sy, x, y);
325 damage = true;
326 }
327 }
328 }
329 }
330
331 if (term_update_cursor(term, surface, sx, sy))
332 damage = true;
333
334 window_yield(term->widget.window);
335
336 if (damage)
337 window_damage(term->widget.window);
338
339 fibril_mutex_unlock(&term->mtx);
340}
341
342static void term_damage(terminal_t *term)
343{
344 fibril_mutex_lock(&term->mtx);
345
346 surface_t *surface = window_claim(term->widget.window);
347 if (!surface) {
348 window_yield(term->widget.window);
349 fibril_mutex_unlock(&term->mtx);
350 return;
351 }
352
353 sysarg_t sx = term->widget.hpos;
354 sysarg_t sy = term->widget.vpos;
355
356 if (!term_update_scroll(term, surface, sx, sy)) {
357 for (sysarg_t y = 0; y < term->rows; y++) {
358 for (sysarg_t x = 0; x < term->cols; x++) {
359 charfield_t *front_field =
360 chargrid_charfield_at(term->frontbuf, x, y);
361 charfield_t *back_field =
362 chargrid_charfield_at(term->backbuf, x, y);
363
364 back_field->ch = front_field->ch;
365 back_field->attrs = front_field->attrs;
366 front_field->flags &= ~CHAR_FLAG_DIRTY;
367
368 term_update_char(term, surface, sx, sy, x, y);
369 }
370 }
371 }
372
373 term_update_cursor(term, surface, sx, sy);
374
375 window_yield(term->widget.window);
376 window_damage(term->widget.window);
377
378 fibril_mutex_unlock(&term->mtx);
379}
380
381static errno_t term_open(con_srvs_t *srvs, con_srv_t *srv)
382{
383 return EOK;
384}
385
386static errno_t term_close(con_srv_t *srv)
387{
388 return EOK;
389}
390
391static errno_t term_read(con_srv_t *srv, void *buf, size_t size, size_t *nread)
392{
393 terminal_t *term = srv_to_terminal(srv);
394 uint8_t *bbuf = buf;
395 size_t pos = 0;
396
397 /*
398 * Read input from keyboard and copy it to the buffer.
399 * We need to handle situation when wchar is split by 2 following
400 * reads.
401 */
402 while (pos < size) {
403 /* Copy to the buffer remaining characters. */
404 while ((pos < size) && (term->char_remains_len > 0)) {
405 bbuf[pos] = term->char_remains[0];
406 pos++;
407
408 /* Unshift the array. */
409 for (size_t i = 1; i < term->char_remains_len; i++)
410 term->char_remains[i - 1] = term->char_remains[i];
411
412 term->char_remains_len--;
413 }
414
415 /* Still not enough? Then get another key from the queue. */
416 if (pos < size) {
417 link_t *link = prodcons_consume(&term->input_pc);
418 cons_event_t *event = list_get_instance(link, cons_event_t, link);
419
420 /* Accept key presses of printable chars only. */
421 if (event->type == CEV_KEY && event->ev.key.type == KEY_PRESS &&
422 event->ev.key.c != 0) {
423 char32_t tmp[2] = {
424 event->ev.key.c,
425 0
426 };
427
428 wstr_to_str(term->char_remains, UTF8_CHAR_BUFFER_SIZE, tmp);
429 term->char_remains_len = str_size(term->char_remains);
430 }
431
432 free(event);
433 }
434 }
435
436 *nread = size;
437 return EOK;
438}
439
440static void term_write_char(terminal_t *term, char32_t ch)
441{
442 sysarg_t updated = 0;
443
444 fibril_mutex_lock(&term->mtx);
445
446 switch (ch) {
447 case '\n':
448 updated = chargrid_newline(term->frontbuf);
449 break;
450 case '\r':
451 break;
452 case '\t':
453 updated = chargrid_tabstop(term->frontbuf, 8);
454 break;
455 case '\b':
456 updated = chargrid_backspace(term->frontbuf);
457 break;
458 default:
459 updated = chargrid_putuchar(term->frontbuf, ch, true);
460 }
461
462 fibril_mutex_unlock(&term->mtx);
463
464 if (updated > 1)
465 term_update(term);
466}
467
468static errno_t term_write(con_srv_t *srv, void *data, size_t size, size_t *nwritten)
469{
470 terminal_t *term = srv_to_terminal(srv);
471
472 size_t off = 0;
473 while (off < size)
474 term_write_char(term, str_decode(data, &off, size));
475
476 *nwritten = size;
477 return EOK;
478}
479
480static void term_sync(con_srv_t *srv)
481{
482 terminal_t *term = srv_to_terminal(srv);
483
484 term_update(term);
485}
486
487static void term_clear(con_srv_t *srv)
488{
489 terminal_t *term = srv_to_terminal(srv);
490
491 fibril_mutex_lock(&term->mtx);
492 chargrid_clear(term->frontbuf);
493 fibril_mutex_unlock(&term->mtx);
494
495 term_update(term);
496}
497
498static void term_set_pos(con_srv_t *srv, sysarg_t col, sysarg_t row)
499{
500 terminal_t *term = srv_to_terminal(srv);
501
502 fibril_mutex_lock(&term->mtx);
503 chargrid_set_cursor(term->frontbuf, col, row);
504 fibril_mutex_unlock(&term->mtx);
505
506 term_update(term);
507}
508
509static errno_t term_get_pos(con_srv_t *srv, sysarg_t *col, sysarg_t *row)
510{
511 terminal_t *term = srv_to_terminal(srv);
512
513 fibril_mutex_lock(&term->mtx);
514 chargrid_get_cursor(term->frontbuf, col, row);
515 fibril_mutex_unlock(&term->mtx);
516
517 return EOK;
518}
519
520static errno_t term_get_size(con_srv_t *srv, sysarg_t *cols, sysarg_t *rows)
521{
522 terminal_t *term = srv_to_terminal(srv);
523
524 fibril_mutex_lock(&term->mtx);
525 *cols = term->cols;
526 *rows = term->rows;
527 fibril_mutex_unlock(&term->mtx);
528
529 return EOK;
530}
531
532static errno_t term_get_color_cap(con_srv_t *srv, console_caps_t *caps)
533{
534 (void) srv;
535 *caps = TERM_CAPS;
536
537 return EOK;
538}
539
540static void term_set_style(con_srv_t *srv, console_style_t style)
541{
542 terminal_t *term = srv_to_terminal(srv);
543
544 fibril_mutex_lock(&term->mtx);
545 chargrid_set_style(term->frontbuf, style);
546 fibril_mutex_unlock(&term->mtx);
547}
548
549static void term_set_color(con_srv_t *srv, console_color_t bgcolor,
550 console_color_t fgcolor, console_color_attr_t attr)
551{
552 terminal_t *term = srv_to_terminal(srv);
553
554 fibril_mutex_lock(&term->mtx);
555 chargrid_set_color(term->frontbuf, bgcolor, fgcolor, attr);
556 fibril_mutex_unlock(&term->mtx);
557}
558
559static void term_set_rgb_color(con_srv_t *srv, pixel_t bgcolor,
560 pixel_t fgcolor)
561{
562 terminal_t *term = srv_to_terminal(srv);
563
564 fibril_mutex_lock(&term->mtx);
565 chargrid_set_rgb_color(term->frontbuf, bgcolor, fgcolor);
566 fibril_mutex_unlock(&term->mtx);
567}
568
569static void term_set_cursor_visibility(con_srv_t *srv, bool visible)
570{
571 terminal_t *term = srv_to_terminal(srv);
572
573 fibril_mutex_lock(&term->mtx);
574 chargrid_set_cursor_visibility(term->frontbuf, visible);
575 fibril_mutex_unlock(&term->mtx);
576
577 term_update(term);
578}
579
580static errno_t term_get_event(con_srv_t *srv, cons_event_t *event)
581{
582 terminal_t *term = srv_to_terminal(srv);
583 link_t *link = prodcons_consume(&term->input_pc);
584 cons_event_t *ev = list_get_instance(link, cons_event_t, link);
585
586 *event = *ev;
587 free(ev);
588 return EOK;
589}
590
591void deinit_terminal(terminal_t *term)
592{
593 list_remove(&term->link);
594 widget_deinit(&term->widget);
595
596 if (term->frontbuf)
597 chargrid_destroy(term->frontbuf);
598
599 if (term->backbuf)
600 chargrid_destroy(term->backbuf);
601}
602
603static void terminal_destroy(widget_t *widget)
604{
605 terminal_t *term = (terminal_t *) widget;
606
607 deinit_terminal(term);
608 free(term);
609}
610
611static void terminal_reconfigure(widget_t *widget)
612{
613 /* No-op */
614}
615
616static void terminal_rearrange(widget_t *widget, sysarg_t hpos, sysarg_t vpos,
617 sysarg_t width, sysarg_t height)
618{
619 terminal_t *term = (terminal_t *) widget;
620
621 widget_modify(widget, hpos, vpos, width, height);
622 widget->width_ideal = width;
623 widget->height_ideal = height;
624
625 term_damage(term);
626}
627
628static void terminal_repaint(widget_t *widget)
629{
630 terminal_t *term = (terminal_t *) widget;
631
632 term_damage(term);
633}
634
635static void terminal_queue_cons_event(terminal_t *term, cons_event_t *ev)
636{
637 /* Got key press/release event */
638 cons_event_t *event =
639 (cons_event_t *) malloc(sizeof(cons_event_t));
640 if (event == NULL)
641 return;
642
643 *event = *ev;
644 link_initialize(&event->link);
645
646 prodcons_produce(&term->input_pc, &event->link);
647}
648
649/* Got key press/release event */
650static void terminal_handle_keyboard_event(widget_t *widget,
651 kbd_event_t kbd_event)
652{
653 terminal_t *term = (terminal_t *) widget;
654 cons_event_t event;
655
656 event.type = CEV_KEY;
657 event.ev.key = kbd_event;
658
659 terminal_queue_cons_event(term, &event);
660}
661
662static void terminal_handle_position_event(widget_t *widget, pos_event_t pos_event)
663{
664 cons_event_t event;
665 terminal_t *term = (terminal_t *) widget;
666 sysarg_t sx = term->widget.hpos;
667 sysarg_t sy = term->widget.vpos;
668
669 if (pos_event.type == POS_PRESS) {
670 event.type = CEV_POS;
671 event.ev.pos.type = pos_event.type;
672 event.ev.pos.pos_id = pos_event.pos_id;
673 event.ev.pos.btn_num = pos_event.btn_num;
674
675 event.ev.pos.hpos = (pos_event.hpos - sx) / FONT_WIDTH;
676 event.ev.pos.vpos = (pos_event.vpos - sy) / FONT_SCANLINES;
677 terminal_queue_cons_event(term, &event);
678 }
679}
680
681static void term_connection(ipc_call_t *icall, void *arg)
682{
683 terminal_t *term = NULL;
684
685 list_foreach(terms, link, terminal_t, cur) {
686 if (cur->dsid == (service_id_t) ipc_get_arg2(icall)) {
687 term = cur;
688 break;
689 }
690 }
691
692 if (term == NULL) {
693 async_answer_0(icall, ENOENT);
694 return;
695 }
696
697 if (!atomic_flag_test_and_set(&term->refcnt))
698 chargrid_set_cursor_visibility(term->frontbuf, true);
699
700 con_conn(icall, &term->srvs);
701}
702
703bool init_terminal(terminal_t *term, widget_t *parent, const void *data,
704 sysarg_t width, sysarg_t height)
705{
706 widget_init(&term->widget, parent, data);
707
708 link_initialize(&term->link);
709 fibril_mutex_initialize(&term->mtx);
710 atomic_flag_clear(&term->refcnt);
711
712 prodcons_initialize(&term->input_pc);
713 term->char_remains_len = 0;
714
715 term->widget.width = width;
716 term->widget.height = height;
717 term->widget.width_ideal = width;
718 term->widget.height_ideal = height;
719
720 term->widget.destroy = terminal_destroy;
721 term->widget.reconfigure = terminal_reconfigure;
722 term->widget.rearrange = terminal_rearrange;
723 term->widget.repaint = terminal_repaint;
724 term->widget.handle_keyboard_event = terminal_handle_keyboard_event;
725 term->widget.handle_position_event = terminal_handle_position_event;
726
727 term->cols = width / FONT_WIDTH;
728 term->rows = height / FONT_SCANLINES;
729
730 term->frontbuf = NULL;
731 term->backbuf = NULL;
732
733 term->frontbuf = chargrid_create(term->cols, term->rows,
734 CHARGRID_FLAG_NONE);
735 if (!term->frontbuf) {
736 widget_deinit(&term->widget);
737 return false;
738 }
739
740 term->backbuf = chargrid_create(term->cols, term->rows,
741 CHARGRID_FLAG_NONE);
742 if (!term->backbuf) {
743 widget_deinit(&term->widget);
744 return false;
745 }
746
747 chargrid_clear(term->frontbuf);
748 chargrid_clear(term->backbuf);
749 term->top_row = 0;
750
751 async_set_fallback_port_handler(term_connection, NULL);
752 con_srvs_init(&term->srvs);
753 term->srvs.ops = &con_ops;
754 term->srvs.sarg = term;
755
756 errno_t rc = loc_server_register(NAME);
757 if (rc != EOK) {
758 widget_deinit(&term->widget);
759 return false;
760 }
761
762 char vc[LOC_NAME_MAXLEN + 1];
763 snprintf(vc, LOC_NAME_MAXLEN, "%s/%" PRIu64, NAMESPACE,
764 task_get_id());
765
766 rc = loc_service_register(vc, &term->dsid);
767 if (rc != EOK) {
768 widget_deinit(&term->widget);
769 return false;
770 }
771
772 list_append(&term->link, &terms);
773 getterm(vc, "/app/bdsh");
774
775 return true;
776}
777
778terminal_t *create_terminal(widget_t *parent, const void *data, sysarg_t width,
779 sysarg_t height)
780{
781 terminal_t *term = (terminal_t *) malloc(sizeof(terminal_t));
782 if (!term)
783 return NULL;
784
785 bool ret = init_terminal(term, parent, data, width, height);
786 if (!ret) {
787 free(term);
788 return NULL;
789 }
790
791 return term;
792}
793
794/** @}
795 */
Note: See TracBrowser for help on using the repository browser.