Changes in uspace/app/terminal/terminal.c [266ec54:01cd15bc] in mainline
- File:
-
- 1 edited
-
uspace/app/terminal/terminal.c (modified) (32 diffs)
Legend:
- Unmodified
- Added
- Removed
-
uspace/app/terminal/terminal.c
r266ec54 r01cd15bc 1 1 /* 2 * Copyright (c) 202 0Jiri Svoboda2 * Copyright (c) 2025 Jiri Svoboda 3 3 * Copyright (c) 2012 Petr Koupy 4 4 * All rights reserved. … … 37 37 #include <adt/list.h> 38 38 #include <adt/prodcons.h> 39 #include <as.h> 39 40 #include <errno.h> 40 41 #include <fbfont/font-8x16.h> 41 #include < io/chargrid.h>42 #include <fibril.h> 42 43 #include <gfx/bitmap.h> 43 44 #include <gfx/context.h> 45 #include <gfx/render.h> 44 46 #include <io/con_srv.h> 45 47 #include <io/concaps.h> 46 48 #include <io/console.h> 47 49 #include <io/pixelmap.h> 50 #include <macros.h> 51 #include <stdarg.h> 52 #include <stdio.h> 53 #include <stdlib.h> 54 #include <str_error.h> 55 #include <str.h> 48 56 #include <task.h> 49 #include <stdarg.h>50 #include <stdlib.h>51 #include <str.h>52 57 #include <ui/resource.h> 53 58 #include <ui/ui.h> … … 65 70 66 71 #define TERM_CAPS \ 67 (CONSOLE_CAP_STYLE | CONSOLE_CAP_INDEXED | CONSOLE_CAP_RGB) 72 (CONSOLE_CAP_CURSORCTL | CONSOLE_CAP_STYLE | CONSOLE_CAP_INDEXED | \ 73 CONSOLE_CAP_RGB) 74 75 #define SCROLLBACK_MAX_LINES 1000 76 #define MIN_WINDOW_COLS 8 77 #define MIN_WINDOW_ROWS 4 68 78 69 79 static LIST_INITIALIZE(terms); 80 81 #define COLOR_BRIGHT 8 82 83 static const pixel_t _basic_colors[16] = { 84 [COLOR_BLACK] = PIXEL(255, 0, 0, 0), 85 [COLOR_RED] = PIXEL(255, 170, 0, 0), 86 [COLOR_GREEN] = PIXEL(255, 0, 170, 0), 87 [COLOR_YELLOW] = PIXEL(255, 170, 85, 0), 88 [COLOR_BLUE] = PIXEL(255, 0, 0, 170), 89 [COLOR_MAGENTA] = PIXEL(255, 170, 0, 170), 90 [COLOR_CYAN] = PIXEL(255, 0, 170, 170), 91 [COLOR_WHITE] = PIXEL(255, 170, 170, 170), 92 93 [COLOR_BLACK | COLOR_BRIGHT] = PIXEL(255, 85, 85, 85), 94 [COLOR_RED | COLOR_BRIGHT] = PIXEL(255, 255, 85, 85), 95 [COLOR_GREEN | COLOR_BRIGHT] = PIXEL(255, 85, 255, 85), 96 [COLOR_YELLOW | COLOR_BRIGHT] = PIXEL(255, 255, 255, 85), 97 [COLOR_BLUE | COLOR_BRIGHT] = PIXEL(255, 85, 85, 255), 98 [COLOR_MAGENTA | COLOR_BRIGHT] = PIXEL(255, 255, 85, 255), 99 [COLOR_CYAN | COLOR_BRIGHT] = PIXEL(255, 85, 255, 255), 100 [COLOR_WHITE | COLOR_BRIGHT] = PIXEL(255, 255, 255, 255), 101 }; 70 102 71 103 static errno_t term_open(con_srvs_t *, con_srv_t *); … … 84 116 static void term_set_rgb_color(con_srv_t *, pixel_t, pixel_t); 85 117 static void term_set_cursor_visibility(con_srv_t *, bool); 118 static errno_t term_set_caption(con_srv_t *, const char *); 86 119 static errno_t term_get_event(con_srv_t *, cons_event_t *); 120 static errno_t term_map(con_srv_t *, sysarg_t, sysarg_t, charfield_t **); 121 static void term_unmap(con_srv_t *); 122 static void term_buf_update(con_srv_t *, sysarg_t, sysarg_t, sysarg_t, 123 sysarg_t); 87 124 88 125 static con_ops_t con_ops = { … … 101 138 .set_rgb_color = term_set_rgb_color, 102 139 .set_cursor_visibility = term_set_cursor_visibility, 103 .get_event = term_get_event 140 .set_caption = term_set_caption, 141 .get_event = term_get_event, 142 .map = term_map, 143 .unmap = term_unmap, 144 .update = term_buf_update 104 145 }; 105 146 106 147 static void terminal_close_event(ui_window_t *, void *); 107 static void terminal_focus_event(ui_window_t *, void *); 148 static void terminal_focus_event(ui_window_t *, void *, unsigned); 149 static void terminal_resize_event(ui_window_t *, void *); 108 150 static void terminal_kbd_event(ui_window_t *, void *, kbd_event_t *); 109 151 static void terminal_pos_event(ui_window_t *, void *, pos_event_t *); 110 static void terminal_unfocus_event(ui_window_t *, void *); 152 static void terminal_unfocus_event(ui_window_t *, void *, unsigned); 153 static void terminal_maximize_event(ui_window_t *, void *); 154 static void terminal_unmaximize_event(ui_window_t *, void *); 111 155 112 156 static ui_window_cb_t terminal_window_cb = { 113 157 .close = terminal_close_event, 114 158 .focus = terminal_focus_event, 159 .resize = terminal_resize_event, 115 160 .kbd = terminal_kbd_event, 116 161 .pos = terminal_pos_event, 117 .unfocus = terminal_unfocus_event 162 .unfocus = terminal_unfocus_event, 163 .maximize = terminal_maximize_event, 164 .unmaximize = terminal_unmaximize_event, 118 165 }; 119 166 167 static errno_t terminal_wait_fibril(void *); 168 120 169 static terminal_t *srv_to_terminal(con_srv_t *srv) 121 170 { … … 123 172 } 124 173 125 static void getterm(const char *svc, const char *app)126 { 127 task_spawnl(NULL, NULL, APP_GETTERM, APP_GETTERM, svc,174 static errno_t getterm(task_wait_t *wait, const char *svc, const char *app) 175 { 176 return task_spawnl(NULL, wait, APP_GETTERM, APP_GETTERM, svc, 128 177 LOCFS_MOUNT_POINT, "--msg", "--wait", "--", app, NULL); 129 178 } 130 179 131 static pixel_t color_table[16] = { 132 [COLOR_BLACK] = PIXEL(255, 0, 0, 0), 133 [COLOR_BLUE] = PIXEL(255, 0, 0, 240), 134 [COLOR_GREEN] = PIXEL(255, 0, 240, 0), 135 [COLOR_CYAN] = PIXEL(255, 0, 240, 240), 136 [COLOR_RED] = PIXEL(255, 240, 0, 0), 137 [COLOR_MAGENTA] = PIXEL(255, 240, 0, 240), 138 [COLOR_YELLOW] = PIXEL(255, 240, 240, 0), 139 [COLOR_WHITE] = PIXEL(255, 240, 240, 240), 140 141 [COLOR_BLACK + 8] = PIXEL(255, 0, 0, 0), 142 [COLOR_BLUE + 8] = PIXEL(255, 0, 0, 255), 143 [COLOR_GREEN + 8] = PIXEL(255, 0, 255, 0), 144 [COLOR_CYAN + 8] = PIXEL(255, 0, 255, 255), 145 [COLOR_RED + 8] = PIXEL(255, 255, 0, 0), 146 [COLOR_MAGENTA + 8] = PIXEL(255, 255, 0, 255), 147 [COLOR_YELLOW + 8] = PIXEL(255, 255, 255, 0), 148 [COLOR_WHITE + 8] = PIXEL(255, 255, 255, 255), 149 }; 150 151 static inline void attrs_rgb(char_attrs_t attrs, pixel_t *bgcolor, pixel_t *fgcolor) 152 { 153 switch (attrs.type) { 180 static pixel_t termui_color_to_pixel(termui_color_t c) 181 { 182 uint8_t r, g, b; 183 termui_color_to_rgb(c, &r, &g, &b); 184 return PIXEL(255, r, g, b); 185 } 186 187 static termui_color_t termui_color_from_pixel(pixel_t pixel) 188 { 189 return termui_color_from_rgb(RED(pixel), GREEN(pixel), BLUE(pixel)); 190 } 191 192 static termui_cell_t charfield_to_termui_cell(terminal_t *term, const charfield_t *cf) 193 { 194 termui_cell_t cell = { }; 195 196 cell.glyph_idx = fb_font_glyph(cf->ch, NULL); 197 198 switch (cf->attrs.type) { 154 199 case CHAR_ATTR_STYLE: 155 switch ( attrs.val.style) {200 switch (cf->attrs.val.style) { 156 201 case STYLE_NORMAL: 157 *bgcolor = color_table[COLOR_WHITE];158 *fgcolor = color_table[COLOR_BLACK];202 cell.bgcolor = term->default_bgcolor; 203 cell.fgcolor = term->default_fgcolor; 159 204 break; 160 205 case STYLE_EMPHASIS: 161 *bgcolor = color_table[COLOR_WHITE];162 *fgcolor = color_table[COLOR_RED];206 cell.bgcolor = term->emphasis_bgcolor; 207 cell.fgcolor = term->emphasis_fgcolor; 163 208 break; 164 209 case STYLE_INVERTED: 165 *bgcolor = color_table[COLOR_BLACK]; 166 *fgcolor = color_table[COLOR_WHITE]; 210 cell.bgcolor = term->default_bgcolor; 211 cell.fgcolor = term->default_fgcolor; 212 cell.inverted = 1; 167 213 break; 168 214 case STYLE_SELECTED: 169 *bgcolor = color_table[COLOR_RED];170 *fgcolor = color_table[COLOR_WHITE];215 cell.bgcolor = term->selection_bgcolor; 216 cell.fgcolor = term->selection_fgcolor; 171 217 break; 172 218 } 173 219 break; 220 174 221 case CHAR_ATTR_INDEX: 175 *bgcolor = color_table[(attrs.val.index.bgcolor & 7) | 176 ((attrs.val.index.attr & CATTR_BRIGHT) ? 8 : 0)]; 177 *fgcolor = color_table[(attrs.val.index.fgcolor & 7) | 178 ((attrs.val.index.attr & CATTR_BRIGHT) ? 8 : 0)]; 222 char_attr_index_t index = cf->attrs.val.index; 223 224 int bright = (index.attr & CATTR_BRIGHT) ? COLOR_BRIGHT : 0; 225 pixel_t bgcolor = _basic_colors[index.bgcolor]; 226 pixel_t fgcolor = _basic_colors[index.fgcolor | bright]; 227 cell.bgcolor = termui_color_from_pixel(bgcolor); 228 cell.fgcolor = termui_color_from_pixel(fgcolor); 229 230 if (index.attr & CATTR_BLINK) 231 cell.blink = 1; 232 179 233 break; 234 180 235 case CHAR_ATTR_RGB: 181 *bgcolor = 0xff000000 | attrs.val.rgb.bgcolor;182 *fgcolor = 0xff000000 | attrs.val.rgb.fgcolor;236 cell.bgcolor = termui_color_from_pixel(cf->attrs.val.rgb.bgcolor); 237 cell.fgcolor = termui_color_from_pixel(cf->attrs.val.rgb.fgcolor); 183 238 break; 184 239 } 240 241 return cell; 185 242 } 186 243 … … 200 257 } 201 258 202 static void term_update_char(terminal_t *term, pixelmap_t *pixelmap, 203 sysarg_t sx, sysarg_t sy, sysarg_t col, sysarg_t row) 204 { 205 charfield_t *field = 206 chargrid_charfield_at(term->backbuf, col, row); 207 208 bool inverted = chargrid_cursor_at(term->backbuf, col, row); 209 210 sysarg_t bx = sx + (col * FONT_WIDTH); 211 sysarg_t by = sy + (row * FONT_SCANLINES); 212 213 pixel_t bgcolor = 0; 214 pixel_t fgcolor = 0; 215 216 if (inverted) 217 attrs_rgb(field->attrs, &fgcolor, &bgcolor); 218 else 219 attrs_rgb(field->attrs, &bgcolor, &fgcolor); 220 221 // FIXME: Glyph type should be actually uint32_t 222 // for full UTF-32 coverage. 223 224 uint16_t glyph = fb_font_glyph(field->ch, NULL); 259 static void term_draw_cell(terminal_t *term, pixelmap_t *pixelmap, int col, int row, const termui_cell_t *cell) 260 { 261 termui_color_t bg = cell->bgcolor; 262 if (bg == TERMUI_COLOR_DEFAULT) 263 bg = term->default_bgcolor; 264 265 termui_color_t fg = cell->fgcolor; 266 if (fg == TERMUI_COLOR_DEFAULT) 267 fg = term->default_fgcolor; 268 269 pixel_t bgcolor = termui_color_to_pixel(bg); 270 pixel_t fgcolor = termui_color_to_pixel(fg); 271 272 int bx = col * FONT_WIDTH; 273 int by = row * FONT_SCANLINES; 274 275 // TODO: support bold/italic/underline/strike/blink styling 276 277 if (cell->inverted ^ cell->cursor) { 278 pixel_t tmp = bgcolor; 279 bgcolor = fgcolor; 280 fgcolor = tmp; 281 } 282 283 uint32_t glyph = cell->glyph_idx; 284 assert(glyph < FONT_GLYPHS); 285 286 if (glyph == 0) 287 glyph = fb_font_glyph(U' ', NULL); 225 288 226 289 for (unsigned int y = 0; y < FONT_SCANLINES; y++) { … … 234 297 } 235 298 } 299 236 300 term_update_region(term, bx, by, FONT_WIDTH, FONT_SCANLINES); 237 301 } 238 302 239 static bool term_update_scroll(terminal_t *term, pixelmap_t *pixelmap, 240 sysarg_t sx, sysarg_t sy) 241 { 242 sysarg_t top_row = chargrid_get_top_row(term->frontbuf); 243 244 if (term->top_row == top_row) { 245 return false; 246 } 247 248 term->top_row = top_row; 249 250 for (sysarg_t row = 0; row < term->rows; row++) { 251 for (sysarg_t col = 0; col < term->cols; col++) { 252 charfield_t *front_field = 253 chargrid_charfield_at(term->frontbuf, col, row); 254 charfield_t *back_field = 255 chargrid_charfield_at(term->backbuf, col, row); 256 bool update = false; 257 258 if (front_field->ch != back_field->ch) { 259 back_field->ch = front_field->ch; 260 update = true; 261 } 262 263 if (!attrs_same(front_field->attrs, back_field->attrs)) { 264 back_field->attrs = front_field->attrs; 265 update = true; 266 } 267 268 front_field->flags &= ~CHAR_FLAG_DIRTY; 269 270 if (update) { 271 term_update_char(term, pixelmap, sx, sy, col, row); 272 } 273 } 274 } 275 276 return true; 277 } 278 279 static bool term_update_cursor(terminal_t *term, pixelmap_t *pixelmap, 280 sysarg_t sx, sysarg_t sy) 281 { 282 bool update = false; 283 284 sysarg_t front_col; 285 sysarg_t front_row; 286 chargrid_get_cursor(term->frontbuf, &front_col, &front_row); 287 288 sysarg_t back_col; 289 sysarg_t back_row; 290 chargrid_get_cursor(term->backbuf, &back_col, &back_row); 291 292 bool front_visibility = 293 chargrid_get_cursor_visibility(term->frontbuf) && 294 term->is_focused; 295 bool back_visibility = 296 chargrid_get_cursor_visibility(term->backbuf); 297 298 if (front_visibility != back_visibility) { 299 chargrid_set_cursor_visibility(term->backbuf, 300 front_visibility); 301 term_update_char(term, pixelmap, sx, sy, back_col, back_row); 302 update = true; 303 } 304 305 if ((front_col != back_col) || (front_row != back_row)) { 306 chargrid_set_cursor(term->backbuf, front_col, front_row); 307 term_update_char(term, pixelmap, sx, sy, back_col, back_row); 308 term_update_char(term, pixelmap, sx, sy, front_col, front_row); 309 update = true; 310 } 311 312 return update; 313 } 314 315 static void term_update(terminal_t *term) 316 { 317 pixelmap_t pixelmap; 303 static void term_render(terminal_t *term) 304 { 305 (void) gfx_bitmap_render(term->bmp, &term->update, &term->off); 306 307 term->update.p0.x = 0; 308 term->update.p0.y = 0; 309 term->update.p1.x = 0; 310 term->update.p1.y = 0; 311 } 312 313 static void termui_refresh_cb(void *userdata) 314 { 315 terminal_t *term = userdata; 316 317 termui_force_viewport_update(term->termui, 0, termui_get_rows(term->termui)); 318 } 319 320 static void termui_scroll_cb(void *userdata, int delta) 321 { 322 (void) delta; 323 324 // Until we have support for hardware accelerated scrolling, just redraw everything. 325 termui_refresh_cb(userdata); 326 } 327 328 static pixelmap_t term_get_pixelmap(terminal_t *term) 329 { 330 pixelmap_t pixelmap = { }; 318 331 gfx_bitmap_alloc_t alloc; 319 gfx_coord2_t pos; 320 errno_t rc; 321 322 rc = gfx_bitmap_get_alloc(term->bmp, &alloc); 323 if (rc != EOK) { 324 return; 325 } 326 327 fibril_mutex_lock(&term->mtx); 332 333 errno_t rc = gfx_bitmap_get_alloc(term->bmp, &alloc); 334 if (rc != EOK) 335 return pixelmap; 336 328 337 pixelmap.width = term->w; 329 338 pixelmap.height = term->h; 330 339 pixelmap.data = alloc.pixels; 331 332 bool update = false; 333 sysarg_t sx = 0/*term->widget.hpos*/; 334 sysarg_t sy = 0/*term->widget.vpos*/; 335 336 if (term_update_scroll(term, &pixelmap, sx, sy)) { 337 update = true; 338 } else { 339 for (sysarg_t y = 0; y < term->rows; y++) { 340 for (sysarg_t x = 0; x < term->cols; x++) { 341 charfield_t *front_field = 342 chargrid_charfield_at(term->frontbuf, x, y); 343 charfield_t *back_field = 344 chargrid_charfield_at(term->backbuf, x, y); 345 bool update = false; 346 347 if ((front_field->flags & CHAR_FLAG_DIRTY) == 348 CHAR_FLAG_DIRTY) { 349 if (front_field->ch != back_field->ch) { 350 back_field->ch = front_field->ch; 351 update = true; 352 } 353 354 if (!attrs_same(front_field->attrs, 355 back_field->attrs)) { 356 back_field->attrs = front_field->attrs; 357 update = true; 358 } 359 360 front_field->flags &= ~CHAR_FLAG_DIRTY; 361 } 362 363 if (update) { 364 term_update_char(term, &pixelmap, sx, sy, x, y); 365 update = true; 366 } 367 } 368 } 369 } 370 371 if (term_update_cursor(term, &pixelmap, sx, sy)) 372 update = true; 373 374 if (update) { 375 pos.x = 4; 376 pos.y = 26; 377 (void) gfx_bitmap_render(term->bmp, &term->update, &pos); 378 379 term->update.p0.x = 0; 380 term->update.p0.y = 0; 381 term->update.p1.x = 0; 382 term->update.p1.y = 0; 383 } 384 385 fibril_mutex_unlock(&term->mtx); 386 } 387 388 static void term_repaint(terminal_t *term) 389 { 390 pixelmap_t pixelmap; 391 gfx_bitmap_alloc_t alloc; 392 errno_t rc; 393 394 rc = gfx_bitmap_get_alloc(term->bmp, &alloc); 395 if (rc != EOK) { 396 printf("Error getting bitmap allocation info.\n"); 340 return pixelmap; 341 } 342 343 static void term_clear_bitmap(terminal_t *term, pixel_t color) 344 { 345 pixelmap_t pixelmap = term_get_pixelmap(term); 346 if (pixelmap.data == NULL) 397 347 return; 398 } 399 400 fibril_mutex_lock(&term->mtx); 401 402 pixelmap.width = term->w; 403 pixelmap.height = term->h; 404 pixelmap.data = alloc.pixels; 405 406 sysarg_t sx = 0; 407 sysarg_t sy = 0; 408 409 if (!term_update_scroll(term, &pixelmap, sx, sy)) { 410 for (sysarg_t y = 0; y < term->rows; y++) { 411 for (sysarg_t x = 0; x < term->cols; x++) { 412 charfield_t *front_field = 413 chargrid_charfield_at(term->frontbuf, x, y); 414 charfield_t *back_field = 415 chargrid_charfield_at(term->backbuf, x, y); 416 417 back_field->ch = front_field->ch; 418 back_field->attrs = front_field->attrs; 419 front_field->flags &= ~CHAR_FLAG_DIRTY; 420 421 term_update_char(term, &pixelmap, sx, sy, x, y); 422 } 423 } 424 } 425 426 term_update_cursor(term, &pixelmap, sx, sy); 427 428 fibril_mutex_unlock(&term->mtx); 348 349 sysarg_t pixels = pixelmap.height * pixelmap.width; 350 for (sysarg_t i = 0; i < pixels; i++) 351 pixelmap.data[i] = color; 352 353 term_update_region(term, 0, 0, pixelmap.width, pixelmap.height); 354 } 355 356 static void termui_update_cb(void *userdata, int col, int row, const termui_cell_t *cell, int len) 357 { 358 terminal_t *term = userdata; 359 360 pixelmap_t pixelmap = term_get_pixelmap(term); 361 if (pixelmap.data == NULL) 362 return; 363 364 for (int i = 0; i < len; i++) 365 term_draw_cell(term, &pixelmap, col + i, row, &cell[i]); 429 366 } 430 367 … … 466 403 if (pos < size) { 467 404 link_t *link = prodcons_consume(&term->input_pc); 468 cons_event_t *event = list_get_instance(link, cons_event_t, link); 405 terminal_event_t *qevent = list_get_instance(link, 406 terminal_event_t, link); 407 cons_event_t *event = &qevent->ev; 469 408 470 409 /* Accept key presses of printable chars only. */ … … 480 419 } 481 420 482 free( event);421 free(qevent); 483 422 } 484 423 } … … 490 429 static void term_write_char(terminal_t *term, wchar_t ch) 491 430 { 492 sysarg_t updated = 0;493 494 fibril_mutex_lock(&term->mtx);495 496 431 switch (ch) { 497 case '\n':498 updated = chargrid_newline(term->frontbuf);432 case L'\n': 433 termui_put_crlf(term->termui); 499 434 break; 500 case '\r': 435 case L'\r': 436 termui_put_cr(term->termui); 501 437 break; 502 case '\t':503 updated = chargrid_tabstop(term->frontbuf, 8);438 case L'\t': 439 termui_put_tab(term->termui); 504 440 break; 505 case '\b':506 updated = chargrid_backspace(term->frontbuf);441 case L'\b': 442 termui_put_backspace(term->termui); 507 443 break; 508 444 default: 509 updated = chargrid_putuchar(term->frontbuf, ch, true); 510 } 511 512 fibril_mutex_unlock(&term->mtx); 513 514 if (updated > 1) 515 term_update(term); 445 // TODO: For some languages, we might need support for combining 446 // characters. Currently, we assume every unicode code point is 447 // an individual printed character, which is not always the case. 448 termui_put_glyph(term->termui, fb_font_glyph(ch, NULL), 1); 449 break; 450 } 516 451 } 517 452 … … 519 454 { 520 455 terminal_t *term = srv_to_terminal(srv); 456 457 fibril_mutex_lock(&term->mtx); 521 458 522 459 size_t off = 0; … … 524 461 term_write_char(term, str_decode(data, &off, size)); 525 462 463 fibril_mutex_unlock(&term->mtx); 464 465 term_render(term); 466 gfx_update(term->gc); 526 467 *nwritten = size; 468 527 469 return EOK; 528 470 } … … 532 474 terminal_t *term = srv_to_terminal(srv); 533 475 534 term_update(term); 476 term_render(term); 477 gfx_update(term->gc); 535 478 } 536 479 … … 540 483 541 484 fibril_mutex_lock(&term->mtx); 542 chargrid_clear(term->frontbuf); 543 fibril_mutex_unlock(&term->mtx); 544 545 term_update(term); 485 termui_clear_screen(term->termui); 486 fibril_mutex_unlock(&term->mtx); 487 488 term_render(term); 489 gfx_update(term->gc); 546 490 } 547 491 … … 551 495 552 496 fibril_mutex_lock(&term->mtx); 553 chargrid_set_cursor(term->frontbuf, col, row); 554 fibril_mutex_unlock(&term->mtx); 555 556 term_update(term); 497 termui_set_pos(term->termui, col, row); 498 fibril_mutex_unlock(&term->mtx); 499 500 term_render(term); 501 gfx_update(term->gc); 557 502 } 558 503 … … 562 507 563 508 fibril_mutex_lock(&term->mtx); 564 chargrid_get_cursor(term->frontbuf, col, row); 565 fibril_mutex_unlock(&term->mtx); 509 int irow, icol; 510 termui_get_pos(term->termui, &icol, &irow); 511 fibril_mutex_unlock(&term->mtx); 512 513 *col = icol; 514 *row = irow; 566 515 567 516 return EOK; … … 573 522 574 523 fibril_mutex_lock(&term->mtx); 575 *cols = term ->cols;576 *rows = term ->rows;524 *cols = termui_get_cols(term->termui); 525 *rows = termui_get_rows(term->termui); 577 526 fibril_mutex_unlock(&term->mtx); 578 527 … … 592 541 terminal_t *term = srv_to_terminal(srv); 593 542 594 fibril_mutex_lock(&term->mtx); 595 chargrid_set_style(term->frontbuf, style); 543 termui_cell_t cellstyle = { }; 544 545 switch (style) { 546 case STYLE_NORMAL: 547 cellstyle.bgcolor = term->default_bgcolor; 548 cellstyle.fgcolor = term->default_fgcolor; 549 break; 550 case STYLE_EMPHASIS: 551 cellstyle.bgcolor = term->emphasis_bgcolor; 552 cellstyle.fgcolor = term->emphasis_fgcolor; 553 break; 554 case STYLE_INVERTED: 555 cellstyle.bgcolor = term->default_bgcolor; 556 cellstyle.fgcolor = term->default_fgcolor; 557 cellstyle.inverted = 1; 558 break; 559 case STYLE_SELECTED: 560 cellstyle.bgcolor = term->selection_bgcolor; 561 cellstyle.fgcolor = term->selection_fgcolor; 562 break; 563 } 564 565 fibril_mutex_lock(&term->mtx); 566 termui_set_style(term->termui, cellstyle); 596 567 fibril_mutex_unlock(&term->mtx); 597 568 } … … 602 573 terminal_t *term = srv_to_terminal(srv); 603 574 604 fibril_mutex_lock(&term->mtx); 605 chargrid_set_color(term->frontbuf, bgcolor, fgcolor, attr); 575 int bright = (attr & CATTR_BRIGHT) ? COLOR_BRIGHT : 0; 576 577 termui_cell_t cellstyle = { }; 578 cellstyle.bgcolor = termui_color_from_pixel(_basic_colors[bgcolor]); 579 cellstyle.fgcolor = termui_color_from_pixel(_basic_colors[fgcolor | bright]); 580 581 if (attr & CATTR_BLINK) 582 cellstyle.blink = 1; 583 584 fibril_mutex_lock(&term->mtx); 585 termui_set_style(term->termui, cellstyle); 606 586 fibril_mutex_unlock(&term->mtx); 607 587 } … … 611 591 { 612 592 terminal_t *term = srv_to_terminal(srv); 613 614 fibril_mutex_lock(&term->mtx); 615 chargrid_set_rgb_color(term->frontbuf, bgcolor, fgcolor); 593 termui_cell_t cellstyle = { 594 .bgcolor = termui_color_from_pixel(bgcolor), 595 .fgcolor = termui_color_from_pixel(fgcolor), 596 }; 597 598 fibril_mutex_lock(&term->mtx); 599 termui_set_style(term->termui, cellstyle); 616 600 fibril_mutex_unlock(&term->mtx); 617 601 } … … 622 606 623 607 fibril_mutex_lock(&term->mtx); 624 chargrid_set_cursor_visibility(term->frontbuf, visible); 625 fibril_mutex_unlock(&term->mtx); 626 627 term_update(term); 608 termui_set_cursor_visibility(term->termui, visible); 609 fibril_mutex_unlock(&term->mtx); 610 611 term_render(term); 612 gfx_update(term->gc); 613 } 614 615 static errno_t term_set_caption(con_srv_t *srv, const char *caption) 616 { 617 terminal_t *term = srv_to_terminal(srv); 618 const char *cap; 619 620 fibril_mutex_lock(&term->mtx); 621 622 if (str_size(caption) > 0) 623 cap = caption; 624 else 625 cap = "Terminal"; 626 627 ui_window_set_caption(term->window, cap); 628 fibril_mutex_unlock(&term->mtx); 629 630 term_render(term); 631 gfx_update(term->gc); 632 return EOK; 628 633 } 629 634 … … 632 637 terminal_t *term = srv_to_terminal(srv); 633 638 link_t *link = prodcons_consume(&term->input_pc); 634 cons_event_t *ev = list_get_instance(link, cons_event_t, link);635 636 *event = *ev;639 terminal_event_t *ev = list_get_instance(link, terminal_event_t, link); 640 641 *event = ev->ev; 637 642 free(ev); 638 643 return EOK; 639 644 } 640 645 641 static void deinit_terminal(terminal_t *term) 646 /** Create shared buffer for efficient rendering. 647 * 648 * @param srv Console server 649 * @param cols Number of columns in buffer 650 * @param rows Number of rows in buffer 651 * @param rbuf Place to store pointer to new sharable buffer 652 * 653 * @return EOK on sucess or an error code 654 */ 655 static errno_t term_map(con_srv_t *srv, sysarg_t cols, sysarg_t rows, 656 charfield_t **rbuf) 657 { 658 terminal_t *term = srv_to_terminal(srv); 659 void *buf; 660 661 fibril_mutex_lock(&term->mtx); 662 663 if (term->ubuf != NULL) { 664 fibril_mutex_unlock(&term->mtx); 665 return EBUSY; 666 } 667 668 buf = as_area_create(AS_AREA_ANY, cols * rows * sizeof(charfield_t), 669 AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE, AS_AREA_UNPAGED); 670 if (buf == AS_MAP_FAILED) { 671 fibril_mutex_unlock(&term->mtx); 672 return ENOMEM; 673 } 674 675 term->ucols = cols; 676 term->urows = rows; 677 term->ubuf = buf; 678 679 /* Scroll back to active screen. */ 680 termui_history_scroll(term->termui, INT_MAX); 681 682 fibril_mutex_unlock(&term->mtx); 683 684 *rbuf = buf; 685 return EOK; 686 } 687 688 /** Delete shared buffer. 689 * 690 * @param srv Console server 691 */ 692 static void term_unmap(con_srv_t *srv) 693 { 694 terminal_t *term = srv_to_terminal(srv); 695 void *buf; 696 697 fibril_mutex_lock(&term->mtx); 698 699 buf = term->ubuf; 700 term->ubuf = NULL; 701 702 termui_wipe_screen(term->termui, 0); 703 704 fibril_mutex_unlock(&term->mtx); 705 706 /* Update terminal */ 707 term_render(term); 708 gfx_update(term->gc); 709 710 if (buf != NULL) 711 as_area_destroy(buf); 712 } 713 714 /** Update area of terminal from shared buffer. 715 * 716 * @param srv Console server 717 * @param c0 Column coordinate of top-left corner (inclusive) 718 * @param r0 Row coordinate of top-left corner (inclusive) 719 * @param c1 Column coordinate of bottom-right corner (exclusive) 720 * @param r1 Row coordinate of bottom-right corner (exclusive) 721 */ 722 static void term_buf_update(con_srv_t *srv, sysarg_t c0, sysarg_t r0, 723 sysarg_t c1, sysarg_t r1) 724 { 725 terminal_t *term = srv_to_terminal(srv); 726 bool cursor; 727 728 fibril_mutex_lock(&term->mtx); 729 730 if (term->ubuf == NULL) { 731 fibril_mutex_unlock(&term->mtx); 732 return; 733 } 734 735 /* Make sure we have meaningful coordinates, within bounds */ 736 c1 = min(c1, term->ucols); 737 c1 = min(c1, (sysarg_t) termui_get_cols(term->termui)); 738 r1 = min(r1, term->urows); 739 r1 = min(r1, (sysarg_t) termui_get_rows(term->termui)); 740 741 if (c0 >= c1 || r0 >= r1) { 742 fibril_mutex_unlock(&term->mtx); 743 return; 744 } 745 746 /* Update front buffer from user buffer */ 747 748 for (sysarg_t row = r0; row < r1; row++) { 749 termui_cell_t *cells = termui_get_active_row(term->termui, row); 750 751 for (sysarg_t col = c0; col < c1; col++) { 752 cursor = cells[col].cursor; 753 cells[col] = charfield_to_termui_cell(term, &term->ubuf[row * term->ucols + col]); 754 cells[col].cursor = cursor; 755 } 756 757 termui_update_cb(term, c0, row, &cells[c0], c1 - c0); 758 } 759 760 fibril_mutex_unlock(&term->mtx); 761 762 /* Update terminal */ 763 term_render(term); 764 gfx_update(term->gc); 765 } 766 767 static errno_t terminal_window_resize(terminal_t *term) 768 { 769 gfx_rect_t rect; 770 ui_window_get_app_rect(term->window, &rect); 771 772 int width = rect.p1.x - rect.p0.x; 773 int height = rect.p1.y - rect.p0.y; 774 775 if (!term->gc) 776 term->gc = ui_window_get_gc(term->window); 777 else 778 assert(term->gc == ui_window_get_gc(term->window)); 779 780 if (!term->ui_res) 781 term->ui_res = ui_window_get_res(term->window); 782 else 783 assert(term->ui_res == ui_window_get_res(term->window)); 784 785 gfx_bitmap_t *new_bmp; 786 gfx_bitmap_params_t params; 787 gfx_bitmap_params_init(¶ms); 788 params.rect.p0.x = 0; 789 params.rect.p0.y = 0; 790 params.rect.p1.x = width; 791 params.rect.p1.y = height; 792 793 errno_t rc = gfx_bitmap_create(term->gc, ¶ms, NULL, &new_bmp); 794 if (rc != EOK) { 795 fprintf(stderr, "Error allocating new screen bitmap: %s\n", str_error(rc)); 796 return rc; 797 } 798 799 if (term->bmp) { 800 rc = gfx_bitmap_destroy(term->bmp); 801 if (rc != EOK) 802 fprintf(stderr, "Error deallocating old screen bitmap: %s\n", str_error(rc)); 803 } 804 805 term->bmp = new_bmp; 806 term->w = width; 807 term->h = height; 808 809 term_clear_bitmap(term, termui_color_to_pixel(term->default_bgcolor)); 810 811 return EOK; 812 } 813 814 void terminal_destroy(terminal_t *term) 642 815 { 643 816 list_remove(&term->link); 644 817 645 if (term->frontbuf) 646 chargrid_destroy(term->frontbuf); 647 648 if (term->backbuf) 649 chargrid_destroy(term->backbuf); 650 } 651 652 void terminal_destroy(terminal_t *term) 653 { 654 deinit_terminal(term); 818 termui_destroy(term->termui); 819 820 if (term->ubuf) 821 as_area_destroy(term->ubuf); 822 823 ui_destroy(term->ui); 655 824 free(term); 656 825 } … … 659 828 { 660 829 /* Got key press/release event */ 661 cons_event_t *event =662 ( cons_event_t *) malloc(sizeof(cons_event_t));830 terminal_event_t *event = 831 (terminal_event_t *) malloc(sizeof(terminal_event_t)); 663 832 if (event == NULL) 664 833 return; 665 834 666 *event= *ev;835 event->ev = *ev; 667 836 link_initialize(&event->link); 668 837 … … 675 844 terminal_t *term = (terminal_t *) arg; 676 845 677 (void) term; 678 679 // XXX This is not really a clean way of terminating 680 exit(0); 846 ui_quit(term->ui); 681 847 } 682 848 683 849 /** Handle window focus event. */ 684 static void terminal_focus_event(ui_window_t *window, void *arg) 850 static void terminal_focus_event(ui_window_t *window, void *arg, 851 unsigned nfocus) 685 852 { 686 853 terminal_t *term = (terminal_t *) arg; 687 854 855 (void)nfocus; 688 856 term->is_focused = true; 689 term_update(term); 857 term_render(term); 858 gfx_update(term->gc); 859 } 860 861 static void terminal_resize_handler(ui_window_t *window, void *arg) 862 { 863 terminal_t *term = (terminal_t *) arg; 864 865 fibril_mutex_lock(&term->mtx); 866 867 errno_t rc = terminal_window_resize(term); 868 if (rc == EOK) { 869 (void) termui_resize(term->termui, term->w / FONT_WIDTH, term->h / FONT_SCANLINES, SCROLLBACK_MAX_LINES); 870 termui_refresh_cb(term); 871 term_render(term); 872 gfx_update(term->gc); 873 874 cons_event_t event = { .type = CEV_RESIZE }; 875 terminal_queue_cons_event(term, &event); 876 } 877 878 fibril_mutex_unlock(&term->mtx); 879 } 880 881 static void terminal_resize_event(ui_window_t *window, void *arg) 882 { 883 ui_window_def_resize(window); 884 terminal_resize_handler(window, arg); 885 } 886 887 static void terminal_maximize_event(ui_window_t *window, void *arg) 888 { 889 ui_window_def_maximize(window); 890 terminal_resize_handler(window, arg); 891 } 892 893 static void terminal_unmaximize_event(ui_window_t *window, void *arg) 894 { 895 ui_window_def_unmaximize(window); 896 terminal_resize_handler(window, arg); 690 897 } 691 898 … … 700 907 event.ev.key = *kbd_event; 701 908 702 terminal_queue_cons_event(term, &event); 909 const int PAGE_ROWS = (termui_get_rows(term->termui) * 2) / 3; 910 911 fibril_mutex_lock(&term->mtx); 912 913 if (!term->ubuf && kbd_event->type == KEY_PRESS && 914 (kbd_event->key == KC_PAGE_UP || kbd_event->key == KC_PAGE_DOWN)) { 915 916 termui_history_scroll(term->termui, 917 (kbd_event->key == KC_PAGE_UP) ? -PAGE_ROWS : PAGE_ROWS); 918 919 term_render(term); 920 gfx_update(term->gc); 921 } else { 922 terminal_queue_cons_event(term, &event); 923 } 924 925 fibril_mutex_unlock(&term->mtx); 703 926 } 704 927 … … 709 932 terminal_t *term = (terminal_t *) arg; 710 933 711 sysarg_t sx = -term->off.x; 712 sysarg_t sy = -term->off.y; 713 714 if (event->type == POS_PRESS) { 715 cevent.type = CEV_POS; 716 cevent.ev.pos.type = event->type; 717 cevent.ev.pos.pos_id = event->pos_id; 718 cevent.ev.pos.btn_num = event->btn_num; 719 720 cevent.ev.pos.hpos = (event->hpos - sx) / FONT_WIDTH; 721 cevent.ev.pos.vpos = (event->vpos - sy) / FONT_SCANLINES; 934 switch (event->type) { 935 case POS_UPDATE: 936 return; 937 938 case POS_PRESS: 939 case POS_RELEASE: 940 case POS_DCLICK: 941 } 942 943 /* Ignore mouse events when we're in scrollback mode. */ 944 if (termui_scrollback_is_active(term->termui)) 945 return; 946 947 sysarg_t sx = term->off.x; 948 sysarg_t sy = term->off.y; 949 950 if (event->hpos < sx || event->vpos < sy) 951 return; 952 953 cevent.type = CEV_POS; 954 cevent.ev.pos.type = event->type; 955 cevent.ev.pos.pos_id = event->pos_id; 956 cevent.ev.pos.btn_num = event->btn_num; 957 958 cevent.ev.pos.hpos = (event->hpos - sx) / FONT_WIDTH; 959 cevent.ev.pos.vpos = (event->vpos - sy) / FONT_SCANLINES; 960 961 /* Filter out events outside the terminal area. */ 962 int cols = termui_get_cols(term->termui); 963 int rows = termui_get_rows(term->termui); 964 965 if (cevent.ev.pos.hpos < (sysarg_t) cols && cevent.ev.pos.vpos < (sysarg_t) rows) 722 966 terminal_queue_cons_event(term, &cevent); 723 }724 967 } 725 968 726 969 /** Handle window unfocus event. */ 727 static void terminal_unfocus_event(ui_window_t *window, void *arg) 970 static void terminal_unfocus_event(ui_window_t *window, void *arg, 971 unsigned nfocus) 728 972 { 729 973 terminal_t *term = (terminal_t *) arg; 730 974 731 term->is_focused = false; 732 term_update(term); 975 if (nfocus == 0) { 976 term->is_focused = false; 977 term_render(term); 978 gfx_update(term->gc); 979 } 733 980 } 734 981 … … 750 997 751 998 if (!atomic_flag_test_and_set(&term->refcnt)) 752 chargrid_set_cursor_visibility(term->frontbuf, true);999 termui_set_cursor_visibility(term->termui, true); 753 1000 754 1001 con_conn(icall, &term->srvs); 755 1002 } 756 1003 1004 static errno_t term_init_window(terminal_t *term, const char *display_spec, 1005 gfx_coord_t width, gfx_coord_t height, 1006 gfx_coord_t min_width, gfx_coord_t min_height, 1007 terminal_flags_t flags) 1008 { 1009 gfx_rect_t min_rect = { { 0, 0 }, { min_width, min_height } }; 1010 gfx_rect_t wmin_rect; 1011 gfx_rect_t wrect; 1012 1013 errno_t rc = ui_create(display_spec, &term->ui); 1014 if (rc != EOK) { 1015 printf("Error creating UI on %s.\n", display_spec); 1016 return rc; 1017 } 1018 1019 ui_wnd_params_t wparams; 1020 ui_wnd_params_init(&wparams); 1021 wparams.caption = "Terminal"; 1022 wparams.style |= ui_wds_maximize_btn | ui_wds_resizable; 1023 1024 if ((flags & tf_topleft) != 0) 1025 wparams.placement = ui_wnd_place_top_left; 1026 1027 if (ui_is_fullscreen(term->ui)) { 1028 wparams.placement = ui_wnd_place_full_screen; 1029 wparams.style &= ~ui_wds_decorated; 1030 } 1031 1032 /* Compute wrect such that application area corresponds to rect. */ 1033 ui_wdecor_rect_from_app(term->ui, wparams.style, &min_rect, &wrect); 1034 gfx_rect_rtranslate(&wrect.p0, &wrect, &wmin_rect); 1035 wparams.min_size = wmin_rect.p1; 1036 1037 gfx_rect_t rect = { { 0, 0 }, { width, height } }; 1038 ui_wdecor_rect_from_app(term->ui, wparams.style, &rect, &rect); 1039 term->off.x = -rect.p0.x; 1040 term->off.y = -rect.p0.y; 1041 printf("off=%d,%d\n", term->off.x, term->off.y); 1042 gfx_rect_translate(&term->off, &rect, &wparams.rect); 1043 printf("wparams.rect=%d,%d,%d,%d\n", 1044 wparams.rect.p0.x, 1045 wparams.rect.p1.x, 1046 wparams.rect.p0.y, 1047 wparams.rect.p1.y); 1048 1049 rc = ui_window_create(term->ui, &wparams, &term->window); 1050 if (rc != EOK) 1051 return rc; 1052 1053 ui_window_set_cb(term->window, &terminal_window_cb, (void *) term); 1054 return terminal_window_resize(term); 1055 } 1056 757 1057 errno_t terminal_create(const char *display_spec, sysarg_t width, 758 sysarg_t height, terminal_flags_t flags, terminal_t **rterm) 759 { 760 terminal_t *term; 761 gfx_bitmap_params_t params; 762 ui_wnd_params_t wparams; 763 gfx_rect_t rect; 764 gfx_coord2_t off; 765 gfx_rect_t wrect; 1058 sysarg_t height, terminal_flags_t flags, const char *command, 1059 terminal_t **rterm) 1060 { 766 1061 errno_t rc; 767 1062 768 term = calloc(1, sizeof(terminal_t));1063 terminal_t *term = calloc(1, sizeof(terminal_t)); 769 1064 if (term == NULL) { 770 1065 printf("Out of memory.\n"); … … 779 1074 term->char_remains_len = 0; 780 1075 781 term->w = width; 782 term->h = height; 783 784 term->cols = width / FONT_WIDTH; 785 term->rows = height / FONT_SCANLINES; 786 787 term->frontbuf = NULL; 788 term->backbuf = NULL; 789 790 term->frontbuf = chargrid_create(term->cols, term->rows, 791 CHARGRID_FLAG_NONE); 792 if (!term->frontbuf) { 793 printf("Error creating front buffer.\n"); 1076 term->default_bgcolor = termui_color_from_pixel(_basic_colors[COLOR_WHITE | COLOR_BRIGHT]); 1077 term->default_fgcolor = termui_color_from_pixel(_basic_colors[COLOR_BLACK]); 1078 1079 term->emphasis_bgcolor = termui_color_from_pixel(_basic_colors[COLOR_WHITE | COLOR_BRIGHT]); 1080 term->emphasis_fgcolor = termui_color_from_pixel(_basic_colors[COLOR_RED | COLOR_BRIGHT]); 1081 1082 term->selection_bgcolor = termui_color_from_pixel(_basic_colors[COLOR_RED | COLOR_BRIGHT]); 1083 term->selection_fgcolor = termui_color_from_pixel(_basic_colors[COLOR_WHITE | COLOR_BRIGHT]); 1084 1085 rc = term_init_window(term, display_spec, width, height, 1086 MIN_WINDOW_COLS * FONT_WIDTH, MIN_WINDOW_ROWS * FONT_SCANLINES, flags); 1087 if (rc != EOK) { 1088 printf("Error creating window (%s).\n", str_error(rc)); 1089 goto error; 1090 } 1091 1092 term->termui = termui_create(term->w / FONT_WIDTH, 1093 term->h / FONT_SCANLINES, SCROLLBACK_MAX_LINES); 1094 if (!term->termui) { 1095 printf("Error creating terminal UI.\n"); 794 1096 rc = ENOMEM; 795 1097 goto error; 796 1098 } 797 1099 798 term->backbuf = chargrid_create(term->cols, term->rows, 799 CHARGRID_FLAG_NONE); 800 if (!term->backbuf) { 801 printf("Error creating back buffer.\n"); 802 rc = ENOMEM; 803 goto error; 804 } 805 806 rect.p0.x = 0; 807 rect.p0.y = 0; 808 rect.p1.x = width; 809 rect.p1.y = height; 810 811 ui_wnd_params_init(&wparams); 812 wparams.caption = "Terminal"; 813 if ((flags & tf_topleft) != 0) 814 wparams.placement = ui_wnd_place_top_left; 815 816 /* 817 * Compute window rectangle such that application area corresponds 818 * to rect 819 */ 820 ui_wdecor_rect_from_app(wparams.style, &rect, &wrect); 821 off = wrect.p0; 822 gfx_rect_rtranslate(&off, &wrect, &wparams.rect); 823 824 term->off = off; 825 826 rc = ui_create(display_spec, &term->ui); 827 if (rc != EOK) { 828 printf("Error creating UI on %s.\n", display_spec); 829 goto error; 830 } 831 832 rc = ui_window_create(term->ui, &wparams, &term->window); 833 if (rc != EOK) { 834 printf("Error creating window.\n"); 835 goto error; 836 } 837 838 term->gc = ui_window_get_gc(term->window); 839 term->ui_res = ui_window_get_res(term->window); 840 841 ui_window_set_cb(term->window, &terminal_window_cb, (void *) term); 842 843 gfx_bitmap_params_init(¶ms); 844 params.rect.p0.x = 0; 845 params.rect.p0.y = 0; 846 params.rect.p1.x = width; 847 params.rect.p1.y = height; 848 849 rc = gfx_bitmap_create(term->gc, ¶ms, NULL, &term->bmp); 850 if (rc != EOK) { 851 printf("Error allocating screen bitmap.\n"); 852 goto error; 853 } 854 855 chargrid_clear(term->frontbuf); 856 chargrid_clear(term->backbuf); 857 term->top_row = 0; 1100 termui_set_refresh_cb(term->termui, termui_refresh_cb, term); 1101 termui_set_scroll_cb(term->termui, termui_scroll_cb, term); 1102 termui_set_update_cb(term->termui, termui_update_cb, term); 858 1103 859 1104 async_set_fallback_port_handler(term_connection, NULL); … … 862 1107 term->srvs.sarg = term; 863 1108 864 rc = loc_server_register(NAME );1109 rc = loc_server_register(NAME, &term->srv); 865 1110 if (rc != EOK) { 866 1111 printf("Error registering server.\n"); … … 873 1118 task_get_id()); 874 1119 875 rc = loc_service_register( vc, &term->dsid);1120 rc = loc_service_register(term->srv, vc, fallback_port_id, &term->dsid); 876 1121 if (rc != EOK) { 877 1122 printf("Error registering service.\n"); … … 881 1126 882 1127 list_append(&term->link, &terms); 883 getterm(vc, "/app/bdsh"); 1128 rc = getterm(&term->wait, vc, command); 1129 if (rc != EOK) 1130 goto error; 1131 1132 term->wfid = fibril_create(terminal_wait_fibril, term); 1133 if (term->wfid == 0) 1134 goto error; 1135 1136 fibril_add_ready(term->wfid); 884 1137 885 1138 term->is_focused = true; 886 1139 887 term->update.p0.x = 0; 888 term->update.p0.y = 0; 889 term->update.p1.x = 0; 890 term->update.p1.y = 0; 891 892 term_repaint(term); 1140 termui_refresh_cb(term); 893 1141 894 1142 *rterm = term; 895 1143 return EOK; 896 1144 error: 1145 if (term->dsid != 0) 1146 loc_service_unregister(term->srv, term->dsid); 1147 if (term->srv != NULL) 1148 loc_server_unregister(term->srv); 897 1149 if (term->window != NULL) 898 1150 ui_window_destroy(term->window); 899 1151 if (term->ui != NULL) 900 1152 ui_destroy(term->ui); 901 if (term->frontbuf != NULL) 902 chargrid_destroy(term->frontbuf); 903 if (term->backbuf != NULL) 904 chargrid_destroy(term->backbuf); 1153 if (term->termui != NULL) 1154 termui_destroy(term->termui); 905 1155 free(term); 906 1156 return rc; 907 1157 } 908 1158 1159 static errno_t terminal_wait_fibril(void *arg) 1160 { 1161 terminal_t *term = (terminal_t *)arg; 1162 task_exit_t texit; 1163 int retval; 1164 1165 /* 1166 * XXX There is no way to break the sleep if the task does not 1167 * exit. 1168 */ 1169 (void) task_wait(&term->wait, &texit, &retval); 1170 ui_quit(term->ui); 1171 return EOK; 1172 } 1173 909 1174 /** @} 910 1175 */
Note:
See TracChangeset
for help on using the changeset viewer.
