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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since be1be2c7 was 984a9ba, checked in by Martin Decky <martin@…>, 7 years ago

do not expose the call capability handler from the async framework

Keep the call capability handler encapsulated within the async framework
and do not expose it explicitly via its API. Use the pointer to
ipc_call_t as the sole object identifying an IPC call in the code that
uses the async framework.

This plugs a major leak in the abstraction and also simplifies both the
async framework (slightly) and all IPC servers.

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