source: mainline/uspace/lib/gui/terminal.c@ 1c635d6

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 1c635d6 was 1c635d6, checked in by Martin Sucha <sucha14@…>, 11 years ago

Do not hold a task's return value after it has disconnected.

Holding the task's return value meant that if nobody waited
for task's result, it polluted NS's memory. This was apparently
done because of a race between spawning a task and waiting for it.

We solve this problem in another way: ns discards the return value
as soon as the task disconnects from it. This typically happens
when the task finishes its execution. In order to avoid the race,
we send the wait request to ns while spawning the task (i.e. when
we talk to the loader), but before we allow the loaded program
to run.

Fixes #132

  • Property mode set to 100644
File size: 19.6 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);
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 bool back_visibility =
258 chargrid_get_cursor_visibility(term->backbuf);
259
260 if (front_visibility != back_visibility) {
261 chargrid_set_cursor_visibility(term->backbuf,
262 front_visibility);
263 term_update_char(term, surface, sx, sy, back_col, back_row);
264 damage = true;
265 }
266
267 if ((front_col != back_col) || (front_row != back_row)) {
268 chargrid_set_cursor(term->backbuf, front_col, front_row);
269 term_update_char(term, surface, sx, sy, back_col, back_row);
270 term_update_char(term, surface, sx, sy, front_col, front_row);
271 damage = true;
272 }
273
274 return damage;
275}
276
277static void term_update(terminal_t *term)
278{
279 fibril_mutex_lock(&term->mtx);
280
281 surface_t *surface = window_claim(term->widget.window);
282 if (!surface) {
283 window_yield(term->widget.window);
284 fibril_mutex_unlock(&term->mtx);
285 return;
286 }
287
288 bool damage = false;
289 sysarg_t sx = term->widget.hpos;
290 sysarg_t sy = term->widget.vpos;
291
292 if (term_update_scroll(term, surface, sx, sy)) {
293 damage = true;
294 } else {
295 for (sysarg_t y = 0; y < term->rows; y++) {
296 for (sysarg_t x = 0; x < term->cols; x++) {
297 charfield_t *front_field =
298 chargrid_charfield_at(term->frontbuf, x, y);
299 charfield_t *back_field =
300 chargrid_charfield_at(term->backbuf, x, y);
301 bool update = false;
302
303 if ((front_field->flags & CHAR_FLAG_DIRTY) ==
304 CHAR_FLAG_DIRTY) {
305 if (front_field->ch != back_field->ch) {
306 back_field->ch = front_field->ch;
307 update = true;
308 }
309
310 if (!attrs_same(front_field->attrs,
311 back_field->attrs)) {
312 back_field->attrs = front_field->attrs;
313 update = true;
314 }
315
316 front_field->flags &= ~CHAR_FLAG_DIRTY;
317 }
318
319 if (update) {
320 term_update_char(term, surface, sx, sy, x, y);
321 damage = true;
322 }
323 }
324 }
325 }
326
327 if (term_update_cursor(term, surface, sx, sy))
328 damage = true;
329
330 window_yield(term->widget.window);
331
332 if (damage)
333 window_damage(term->widget.window);
334
335 fibril_mutex_unlock(&term->mtx);
336}
337
338static void term_damage(terminal_t *term)
339{
340 fibril_mutex_lock(&term->mtx);
341
342 surface_t *surface = window_claim(term->widget.window);
343 if (!surface) {
344 window_yield(term->widget.window);
345 fibril_mutex_unlock(&term->mtx);
346 return;
347 }
348
349 sysarg_t sx = term->widget.hpos;
350 sysarg_t sy = term->widget.vpos;
351
352 if (!term_update_scroll(term, surface, sx, sy)) {
353 for (sysarg_t y = 0; y < term->rows; y++) {
354 for (sysarg_t x = 0; x < term->cols; x++) {
355 charfield_t *front_field =
356 chargrid_charfield_at(term->frontbuf, x, y);
357 charfield_t *back_field =
358 chargrid_charfield_at(term->backbuf, x, y);
359
360 back_field->ch = front_field->ch;
361 back_field->attrs = front_field->attrs;
362 front_field->flags &= ~CHAR_FLAG_DIRTY;
363
364 term_update_char(term, surface, sx, sy, x, y);
365 }
366 }
367 }
368
369 term_update_cursor(term, surface, sx, sy);
370
371 window_yield(term->widget.window);
372 window_damage(term->widget.window);
373
374 fibril_mutex_unlock(&term->mtx);
375}
376
377static int term_open(con_srvs_t *srvs, con_srv_t *srv)
378{
379 return EOK;
380}
381
382static int term_close(con_srv_t *srv)
383{
384 return EOK;
385}
386
387static int term_read(con_srv_t *srv, void *buf, size_t size)
388{
389 terminal_t *term = srv_to_terminal(srv);
390 uint8_t *bbuf = buf;
391 size_t pos = 0;
392
393 /*
394 * Read input from keyboard and copy it to the buffer.
395 * We need to handle situation when wchar is split by 2 following
396 * reads.
397 */
398 while (pos < size) {
399 /* Copy to the buffer remaining characters. */
400 while ((pos < size) && (term->char_remains_len > 0)) {
401 bbuf[pos] = term->char_remains[0];
402 pos++;
403
404 /* Unshift the array. */
405 for (size_t i = 1; i < term->char_remains_len; i++)
406 term->char_remains[i - 1] = term->char_remains[i];
407
408 term->char_remains_len--;
409 }
410
411 /* Still not enough? Then get another key from the queue. */
412 if (pos < size) {
413 link_t *link = prodcons_consume(&term->input_pc);
414 cons_event_t *event = list_get_instance(link, cons_event_t, link);
415
416 /* Accept key presses of printable chars only. */
417 if (event->type == CEV_KEY && event->ev.key.type == KEY_PRESS &&
418 event->ev.key.c != 0) {
419 wchar_t tmp[2] = {
420 event->ev.key.c,
421 0
422 };
423
424 wstr_to_str(term->char_remains, UTF8_CHAR_BUFFER_SIZE, tmp);
425 term->char_remains_len = str_size(term->char_remains);
426 }
427
428 free(event);
429 }
430 }
431
432 return size;
433}
434
435static void term_write_char(terminal_t *term, wchar_t ch)
436{
437 sysarg_t updated = 0;
438
439 fibril_mutex_lock(&term->mtx);
440
441 switch (ch) {
442 case '\n':
443 updated = chargrid_newline(term->frontbuf);
444 break;
445 case '\r':
446 break;
447 case '\t':
448 updated = chargrid_tabstop(term->frontbuf, 8);
449 break;
450 case '\b':
451 updated = chargrid_backspace(term->frontbuf);
452 break;
453 default:
454 updated = chargrid_putchar(term->frontbuf, ch, true);
455 }
456
457 fibril_mutex_unlock(&term->mtx);
458
459 if (updated > 1)
460 term_update(term);
461}
462
463static int term_write(con_srv_t *srv, void *data, size_t size)
464{
465 terminal_t *term = srv_to_terminal(srv);
466
467 size_t off = 0;
468 while (off < size)
469 term_write_char(term, str_decode(data, &off, size));
470
471 return size;
472}
473
474static void term_sync(con_srv_t *srv)
475{
476 terminal_t *term = srv_to_terminal(srv);
477
478 term_update(term);
479}
480
481static void term_clear(con_srv_t *srv)
482{
483 terminal_t *term = srv_to_terminal(srv);
484
485 fibril_mutex_lock(&term->mtx);
486 chargrid_clear(term->frontbuf);
487 fibril_mutex_unlock(&term->mtx);
488
489 term_update(term);
490}
491
492static void term_set_pos(con_srv_t *srv, sysarg_t col, sysarg_t row)
493{
494 terminal_t *term = srv_to_terminal(srv);
495
496 fibril_mutex_lock(&term->mtx);
497 chargrid_set_cursor(term->frontbuf, col, row);
498 fibril_mutex_unlock(&term->mtx);
499
500 term_update(term);
501}
502
503static int term_get_pos(con_srv_t *srv, sysarg_t *col, sysarg_t *row)
504{
505 terminal_t *term = srv_to_terminal(srv);
506
507 fibril_mutex_lock(&term->mtx);
508 chargrid_get_cursor(term->frontbuf, col, row);
509 fibril_mutex_unlock(&term->mtx);
510
511 return EOK;
512}
513
514static int term_get_size(con_srv_t *srv, sysarg_t *cols, sysarg_t *rows)
515{
516 terminal_t *term = srv_to_terminal(srv);
517
518 fibril_mutex_lock(&term->mtx);
519 *cols = term->cols;
520 *rows = term->rows;
521 fibril_mutex_unlock(&term->mtx);
522
523 return EOK;
524}
525
526static int term_get_color_cap(con_srv_t *srv, console_caps_t *caps)
527{
528 (void) srv;
529 *caps = TERM_CAPS;
530
531 return EOK;
532}
533
534static void term_set_style(con_srv_t *srv, console_style_t style)
535{
536 terminal_t *term = srv_to_terminal(srv);
537
538 fibril_mutex_lock(&term->mtx);
539 chargrid_set_style(term->frontbuf, style);
540 fibril_mutex_unlock(&term->mtx);
541}
542
543static void term_set_color(con_srv_t *srv, console_color_t bgcolor,
544 console_color_t fgcolor, console_color_attr_t attr)
545{
546 terminal_t *term = srv_to_terminal(srv);
547
548 fibril_mutex_lock(&term->mtx);
549 chargrid_set_color(term->frontbuf, bgcolor, fgcolor, attr);
550 fibril_mutex_unlock(&term->mtx);
551}
552
553static void term_set_rgb_color(con_srv_t *srv, pixel_t bgcolor,
554 pixel_t fgcolor)
555{
556 terminal_t *term = srv_to_terminal(srv);
557
558 fibril_mutex_lock(&term->mtx);
559 chargrid_set_rgb_color(term->frontbuf, bgcolor, fgcolor);
560 fibril_mutex_unlock(&term->mtx);
561}
562
563static void term_set_cursor_visibility(con_srv_t *srv, bool visible)
564{
565 terminal_t *term = srv_to_terminal(srv);
566
567 fibril_mutex_lock(&term->mtx);
568 chargrid_set_cursor_visibility(term->frontbuf, visible);
569 fibril_mutex_unlock(&term->mtx);
570
571 term_update(term);
572}
573
574static int term_get_event(con_srv_t *srv, cons_event_t *event)
575{
576 terminal_t *term = srv_to_terminal(srv);
577 link_t *link = prodcons_consume(&term->input_pc);
578 cons_event_t *ev = list_get_instance(link, cons_event_t, link);
579
580 *event = *ev;
581 free(ev);
582 return EOK;
583}
584
585void deinit_terminal(terminal_t *term)
586{
587 list_remove(&term->link);
588 widget_deinit(&term->widget);
589
590 if (term->frontbuf)
591 chargrid_destroy(term->frontbuf);
592
593 if (term->backbuf)
594 chargrid_destroy(term->backbuf);
595}
596
597static void terminal_destroy(widget_t *widget)
598{
599 terminal_t *term = (terminal_t *) widget;
600
601 deinit_terminal(term);
602 free(term);
603}
604
605static void terminal_reconfigure(widget_t *widget)
606{
607 /* No-op */
608}
609
610static void terminal_rearrange(widget_t *widget, sysarg_t hpos, sysarg_t vpos,
611 sysarg_t width, sysarg_t height)
612{
613 terminal_t *term = (terminal_t *) widget;
614
615 widget_modify(widget, hpos, vpos, width, height);
616 widget->width_ideal = width;
617 widget->height_ideal = height;
618
619 term_damage(term);
620}
621
622static void terminal_repaint(widget_t *widget)
623{
624 terminal_t *term = (terminal_t *) widget;
625
626 term_damage(term);
627}
628
629static void terminal_queue_cons_event(terminal_t *term, cons_event_t *ev)
630{
631 /* Got key press/release event */
632 cons_event_t *event =
633 (cons_event_t *) malloc(sizeof(cons_event_t));
634 if (event == NULL)
635 return;
636
637 *event = *ev;
638 link_initialize(&event->link);
639
640 prodcons_produce(&term->input_pc, &event->link);
641}
642
643/* Got key press/release event */
644static void terminal_handle_keyboard_event(widget_t *widget,
645 kbd_event_t kbd_event)
646{
647 terminal_t *term = (terminal_t *) widget;
648 cons_event_t event;
649
650 event.type = CEV_KEY;
651 event.ev.key = kbd_event;
652
653 terminal_queue_cons_event(term, &event);
654}
655
656static void terminal_handle_position_event(widget_t *widget, pos_event_t pos_event)
657{
658 cons_event_t event;
659 terminal_t *term = (terminal_t *) widget;
660 sysarg_t sx = term->widget.hpos;
661 sysarg_t sy = term->widget.vpos;
662
663 if (pos_event.type == POS_PRESS) {
664 event.type = CEV_POS;
665 event.ev.pos.type = pos_event.type;
666 event.ev.pos.pos_id = pos_event.pos_id;
667 event.ev.pos.btn_num = pos_event.btn_num;
668
669 event.ev.pos.hpos = (pos_event.hpos - sx) / FONT_WIDTH;
670 event.ev.pos.vpos = (pos_event.vpos - sy) / FONT_SCANLINES;
671 terminal_queue_cons_event(term, &event);
672 }
673}
674
675static void term_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
676{
677 terminal_t *term = NULL;
678
679 list_foreach(terms, link, terminal_t, cur) {
680 if (cur->dsid == (service_id_t) IPC_GET_ARG1(*icall)) {
681 term = cur;
682 break;
683 }
684 }
685
686 if (term == NULL) {
687 async_answer_0(iid, ENOENT);
688 return;
689 }
690
691 if (atomic_postinc(&term->refcnt) == 0)
692 chargrid_set_cursor_visibility(term->frontbuf, true);
693
694 con_conn(iid, icall, &term->srvs);
695}
696
697bool init_terminal(terminal_t *term, widget_t *parent, sysarg_t width,
698 sysarg_t height)
699{
700 widget_init(&term->widget, parent);
701
702 link_initialize(&term->link);
703 fibril_mutex_initialize(&term->mtx);
704 atomic_set(&term->refcnt, 0);
705
706 prodcons_initialize(&term->input_pc);
707 term->char_remains_len = 0;
708
709 term->widget.width = width;
710 term->widget.height = height;
711 term->widget.width_ideal = width;
712 term->widget.height_ideal = height;
713
714 term->widget.destroy = terminal_destroy;
715 term->widget.reconfigure = terminal_reconfigure;
716 term->widget.rearrange = terminal_rearrange;
717 term->widget.repaint = terminal_repaint;
718 term->widget.handle_keyboard_event = terminal_handle_keyboard_event;
719 term->widget.handle_position_event = terminal_handle_position_event;
720
721 term->cols = width / FONT_WIDTH;
722 term->rows = height / FONT_SCANLINES;
723
724 term->frontbuf = NULL;
725 term->backbuf = NULL;
726
727 term->frontbuf = chargrid_create(term->cols, term->rows,
728 CHARGRID_FLAG_NONE);
729 if (!term->frontbuf) {
730 widget_deinit(&term->widget);
731 return false;
732 }
733
734 term->backbuf = chargrid_create(term->cols, term->rows,
735 CHARGRID_FLAG_NONE);
736 if (!term->backbuf) {
737 widget_deinit(&term->widget);
738 return false;
739 }
740
741 chargrid_clear(term->frontbuf);
742 chargrid_clear(term->backbuf);
743 term->top_row = 0;
744
745 async_set_client_connection(term_connection);
746 con_srvs_init(&term->srvs);
747 term->srvs.ops = &con_ops;
748 term->srvs.sarg = term;
749
750 int rc = loc_server_register(NAME);
751 if (rc != EOK) {
752 widget_deinit(&term->widget);
753 return false;
754 }
755
756 char vc[LOC_NAME_MAXLEN + 1];
757 snprintf(vc, LOC_NAME_MAXLEN, "%s/%" PRIu64, NAMESPACE,
758 task_get_id());
759
760 rc = loc_service_register(vc, &term->dsid);
761 if (rc != EOK) {
762 widget_deinit(&term->widget);
763 return false;
764 }
765
766 list_append(&term->link, &terms);
767 getterm(vc, "/app/bdsh");
768
769 return true;
770}
771
772terminal_t *create_terminal(widget_t *parent, sysarg_t width, sysarg_t height)
773{
774 terminal_t *term = (terminal_t *) malloc(sizeof(terminal_t));
775 if (!term)
776 return NULL;
777
778 bool ret = init_terminal(term, parent, width, height);
779 if (!ret) {
780 free(term);
781 return NULL;
782 }
783
784 return term;
785}
786
787/** @}
788 */
Note: See TracBrowser for help on using the repository browser.