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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since f1380b7 was a35b458, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 7 years ago

style: Remove trailing whitespace on _all_ lines, including empty ones, for particular file types.

Command used: tools/srepl '\s\+$' '' -- *.c *.h *.py *.sh *.s *.S *.ag

Currently, whitespace on empty lines is very inconsistent.
There are two basic choices: Either remove the whitespace, or keep empty lines
indented to the level of surrounding code. The former is AFAICT more common,
and also much easier to do automatically.

Alternatively, we could write script for automatic indentation, and use that
instead. However, if such a script exists, it's possible to use the indented
style locally, by having the editor apply relevant conversions on load/save,
without affecting remote repository. IMO, it makes more sense to adopt
the simpler rule.

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