source: mainline/uspace/lib/gui/terminal.c@ 0dd16778

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

gradually introduce async ports, initial phase

The initial phase is to reimplement the traditional async client connections as an untyped fallback port. This creates the possibility to introduce ports typed by interface type gradually in later changesets.

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