Changes in uspace/app/terminal/terminal.c [01cd15bc:266ec54] in mainline
- File:
-
- 1 edited
-
uspace/app/terminal/terminal.c (modified) (27 diffs)
Legend:
- Unmodified
- Added
- Removed
-
uspace/app/terminal/terminal.c
r01cd15bc r266ec54 1 1 /* 2 * Copyright (c) 202 5Jiri Svoboda2 * Copyright (c) 2020 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>40 39 #include <errno.h> 41 40 #include <fbfont/font-8x16.h> 42 #include < fibril.h>41 #include <io/chargrid.h> 43 42 #include <gfx/bitmap.h> 44 43 #include <gfx/context.h> 45 #include <gfx/render.h>46 44 #include <io/con_srv.h> 47 45 #include <io/concaps.h> 48 46 #include <io/console.h> 49 47 #include <io/pixelmap.h> 50 #include < macros.h>48 #include <task.h> 51 49 #include <stdarg.h> 52 #include <stdio.h>53 50 #include <stdlib.h> 54 #include <str_error.h>55 51 #include <str.h> 56 #include <task.h>57 52 #include <ui/resource.h> 58 53 #include <ui/ui.h> … … 70 65 71 66 #define TERM_CAPS \ 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 67 (CONSOLE_CAP_STYLE | CONSOLE_CAP_INDEXED | CONSOLE_CAP_RGB) 78 68 79 69 static LIST_INITIALIZE(terms); 80 81 #define COLOR_BRIGHT 882 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 };102 70 103 71 static errno_t term_open(con_srvs_t *, con_srv_t *); … … 116 84 static void term_set_rgb_color(con_srv_t *, pixel_t, pixel_t); 117 85 static void term_set_cursor_visibility(con_srv_t *, bool); 118 static errno_t term_set_caption(con_srv_t *, const char *);119 86 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);124 87 125 88 static con_ops_t con_ops = { … … 138 101 .set_rgb_color = term_set_rgb_color, 139 102 .set_cursor_visibility = term_set_cursor_visibility, 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 103 .get_event = term_get_event 145 104 }; 146 105 147 106 static void terminal_close_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 *); 107 static void terminal_focus_event(ui_window_t *, void *); 150 108 static void terminal_kbd_event(ui_window_t *, void *, kbd_event_t *); 151 109 static void terminal_pos_event(ui_window_t *, void *, pos_event_t *); 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 *); 110 static void terminal_unfocus_event(ui_window_t *, void *); 155 111 156 112 static ui_window_cb_t terminal_window_cb = { 157 113 .close = terminal_close_event, 158 114 .focus = terminal_focus_event, 159 .resize = terminal_resize_event,160 115 .kbd = terminal_kbd_event, 161 116 .pos = terminal_pos_event, 162 .unfocus = terminal_unfocus_event, 163 .maximize = terminal_maximize_event, 164 .unmaximize = terminal_unmaximize_event, 117 .unfocus = terminal_unfocus_event 165 118 }; 166 119 167 static errno_t terminal_wait_fibril(void *);168 169 120 static terminal_t *srv_to_terminal(con_srv_t *srv) 170 121 { … … 172 123 } 173 124 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,125 static void getterm(const char *svc, const char *app) 126 { 127 task_spawnl(NULL, NULL, APP_GETTERM, APP_GETTERM, svc, 177 128 LOCFS_MOUNT_POINT, "--msg", "--wait", "--", app, NULL); 178 129 } 179 130 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) { 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) { 199 154 case CHAR_ATTR_STYLE: 200 switch ( cf->attrs.val.style) {155 switch (attrs.val.style) { 201 156 case STYLE_NORMAL: 202 cell.bgcolor = term->default_bgcolor;203 cell.fgcolor = term->default_fgcolor;157 *bgcolor = color_table[COLOR_WHITE]; 158 *fgcolor = color_table[COLOR_BLACK]; 204 159 break; 205 160 case STYLE_EMPHASIS: 206 cell.bgcolor = term->emphasis_bgcolor;207 cell.fgcolor = term->emphasis_fgcolor;161 *bgcolor = color_table[COLOR_WHITE]; 162 *fgcolor = color_table[COLOR_RED]; 208 163 break; 209 164 case STYLE_INVERTED: 210 cell.bgcolor = term->default_bgcolor; 211 cell.fgcolor = term->default_fgcolor; 212 cell.inverted = 1; 165 *bgcolor = color_table[COLOR_BLACK]; 166 *fgcolor = color_table[COLOR_WHITE]; 213 167 break; 214 168 case STYLE_SELECTED: 215 cell.bgcolor = term->selection_bgcolor;216 cell.fgcolor = term->selection_fgcolor;169 *bgcolor = color_table[COLOR_RED]; 170 *fgcolor = color_table[COLOR_WHITE]; 217 171 break; 218 172 } 219 173 break; 220 221 174 case CHAR_ATTR_INDEX: 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 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)]; 233 179 break; 234 235 180 case CHAR_ATTR_RGB: 236 cell.bgcolor = termui_color_from_pixel(cf->attrs.val.rgb.bgcolor);237 cell.fgcolor = termui_color_from_pixel(cf->attrs.val.rgb.fgcolor);181 *bgcolor = 0xff000000 | attrs.val.rgb.bgcolor; 182 *fgcolor = 0xff000000 | attrs.val.rgb.fgcolor; 238 183 break; 239 184 } 240 241 return cell;242 185 } 243 186 … … 257 200 } 258 201 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); 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); 288 225 289 226 for (unsigned int y = 0; y < FONT_SCANLINES; y++) { … … 297 234 } 298 235 } 299 300 236 term_update_region(term, bx, by, FONT_WIDTH, FONT_SCANLINES); 301 237 } 302 238 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 = { }; 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; 331 318 gfx_bitmap_alloc_t alloc; 332 333 errno_t rc = gfx_bitmap_get_alloc(term->bmp, &alloc); 334 if (rc != EOK) 335 return pixelmap; 336 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); 337 328 pixelmap.width = term->w; 338 329 pixelmap.height = term->h; 339 330 pixelmap.data = alloc.pixels; 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) 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"); 347 397 return; 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]); 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); 366 429 } 367 430 … … 403 466 if (pos < size) { 404 467 link_t *link = prodcons_consume(&term->input_pc); 405 terminal_event_t *qevent = list_get_instance(link, 406 terminal_event_t, link); 407 cons_event_t *event = &qevent->ev; 468 cons_event_t *event = list_get_instance(link, cons_event_t, link); 408 469 409 470 /* Accept key presses of printable chars only. */ … … 419 480 } 420 481 421 free( qevent);482 free(event); 422 483 } 423 484 } … … 429 490 static void term_write_char(terminal_t *term, wchar_t ch) 430 491 { 492 sysarg_t updated = 0; 493 494 fibril_mutex_lock(&term->mtx); 495 431 496 switch (ch) { 432 case L'\n':433 termui_put_crlf(term->termui);497 case '\n': 498 updated = chargrid_newline(term->frontbuf); 434 499 break; 435 case L'\r': 436 termui_put_cr(term->termui); 500 case '\r': 437 501 break; 438 case L'\t':439 termui_put_tab(term->termui);502 case '\t': 503 updated = chargrid_tabstop(term->frontbuf, 8); 440 504 break; 441 case L'\b':442 termui_put_backspace(term->termui);505 case '\b': 506 updated = chargrid_backspace(term->frontbuf); 443 507 break; 444 508 default: 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 } 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); 451 516 } 452 517 … … 454 519 { 455 520 terminal_t *term = srv_to_terminal(srv); 456 457 fibril_mutex_lock(&term->mtx);458 521 459 522 size_t off = 0; … … 461 524 term_write_char(term, str_decode(data, &off, size)); 462 525 463 fibril_mutex_unlock(&term->mtx);464 465 term_render(term);466 gfx_update(term->gc);467 526 *nwritten = size; 468 469 527 return EOK; 470 528 } … … 474 532 terminal_t *term = srv_to_terminal(srv); 475 533 476 term_render(term); 477 gfx_update(term->gc); 534 term_update(term); 478 535 } 479 536 … … 483 540 484 541 fibril_mutex_lock(&term->mtx); 485 termui_clear_screen(term->termui); 486 fibril_mutex_unlock(&term->mtx); 487 488 term_render(term); 489 gfx_update(term->gc); 542 chargrid_clear(term->frontbuf); 543 fibril_mutex_unlock(&term->mtx); 544 545 term_update(term); 490 546 } 491 547 … … 495 551 496 552 fibril_mutex_lock(&term->mtx); 497 termui_set_pos(term->termui, col, row); 498 fibril_mutex_unlock(&term->mtx); 499 500 term_render(term); 501 gfx_update(term->gc); 553 chargrid_set_cursor(term->frontbuf, col, row); 554 fibril_mutex_unlock(&term->mtx); 555 556 term_update(term); 502 557 } 503 558 … … 507 562 508 563 fibril_mutex_lock(&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; 564 chargrid_get_cursor(term->frontbuf, col, row); 565 fibril_mutex_unlock(&term->mtx); 515 566 516 567 return EOK; … … 522 573 523 574 fibril_mutex_lock(&term->mtx); 524 *cols = term ui_get_cols(term->termui);525 *rows = term ui_get_rows(term->termui);575 *cols = term->cols; 576 *rows = term->rows; 526 577 fibril_mutex_unlock(&term->mtx); 527 578 … … 541 592 terminal_t *term = srv_to_terminal(srv); 542 593 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); 594 fibril_mutex_lock(&term->mtx); 595 chargrid_set_style(term->frontbuf, style); 567 596 fibril_mutex_unlock(&term->mtx); 568 597 } … … 573 602 terminal_t *term = srv_to_terminal(srv); 574 603 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); 604 fibril_mutex_lock(&term->mtx); 605 chargrid_set_color(term->frontbuf, bgcolor, fgcolor, attr); 586 606 fibril_mutex_unlock(&term->mtx); 587 607 } … … 591 611 { 592 612 terminal_t *term = srv_to_terminal(srv); 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); 613 614 fibril_mutex_lock(&term->mtx); 615 chargrid_set_rgb_color(term->frontbuf, bgcolor, fgcolor); 600 616 fibril_mutex_unlock(&term->mtx); 601 617 } … … 606 622 607 623 fibril_mutex_lock(&term->mtx); 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; 624 chargrid_set_cursor_visibility(term->frontbuf, visible); 625 fibril_mutex_unlock(&term->mtx); 626 627 term_update(term); 633 628 } 634 629 … … 637 632 terminal_t *term = srv_to_terminal(srv); 638 633 link_t *link = prodcons_consume(&term->input_pc); 639 terminal_event_t *ev = list_get_instance(link, terminal_event_t, link);640 641 *event = ev->ev;634 cons_event_t *ev = list_get_instance(link, cons_event_t, link); 635 636 *event = *ev; 642 637 free(ev); 643 638 return EOK; 644 639 } 645 640 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); 641 static void deinit_terminal(terminal_t *term) 642 { 643 list_remove(&term->link); 644 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); 655 free(term); 656 } 657 658 static void terminal_queue_cons_event(terminal_t *term, cons_event_t *ev) 659 { 660 /* Got key press/release event */ 661 cons_event_t *event = 662 (cons_event_t *) malloc(sizeof(cons_event_t)); 663 if (event == NULL) 664 return; 665 666 *event = *ev; 667 link_initialize(&event->link); 668 669 prodcons_produce(&term->input_pc, &event->link); 670 } 671 672 /** Handle window close event. */ 673 static void terminal_close_event(ui_window_t *window, void *arg) 674 { 675 terminal_t *term = (terminal_t *) arg; 676 677 (void) term; 678 679 // XXX This is not really a clean way of terminating 680 exit(0); 681 } 682 683 /** Handle window focus event. */ 684 static void terminal_focus_event(ui_window_t *window, void *arg) 685 { 686 terminal_t *term = (terminal_t *) arg; 687 688 term->is_focused = true; 689 term_update(term); 690 } 691 692 /** Handle window keyboard event */ 693 static void terminal_kbd_event(ui_window_t *window, void *arg, 694 kbd_event_t *kbd_event) 695 { 696 terminal_t *term = (terminal_t *) arg; 697 cons_event_t event; 698 699 event.type = CEV_KEY; 700 event.ev.key = *kbd_event; 701 702 terminal_queue_cons_event(term, &event); 703 } 704 705 /** Handle window position event */ 706 static void terminal_pos_event(ui_window_t *window, void *arg, pos_event_t *event) 707 { 708 cons_event_t cevent; 709 terminal_t *term = (terminal_t *) arg; 710 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; 722 terminal_queue_cons_event(term, &cevent); 723 } 724 } 725 726 /** Handle window unfocus event. */ 727 static void terminal_unfocus_event(ui_window_t *window, void *arg) 728 { 729 terminal_t *term = (terminal_t *) arg; 730 731 term->is_focused = false; 732 term_update(term); 733 } 734 735 static void term_connection(ipc_call_t *icall, void *arg) 736 { 737 terminal_t *term = NULL; 738 739 list_foreach(terms, link, terminal_t, cur) { 740 if (cur->dsid == (service_id_t) ipc_get_arg2(icall)) { 741 term = cur; 742 break; 743 } 744 } 745 746 if (term == NULL) { 747 async_answer_0(icall, ENOENT); 748 return; 749 } 750 751 if (!atomic_flag_test_and_set(&term->refcnt)) 752 chargrid_set_cursor_visibility(term->frontbuf, true); 753 754 con_conn(icall, &term->srvs); 755 } 756 757 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; 766 errno_t rc; 767 768 term = calloc(1, sizeof(terminal_t)); 769 if (term == NULL) { 770 printf("Out of memory.\n"); 672 771 return ENOMEM; 673 772 } 674 773 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; 774 link_initialize(&term->link); 775 fibril_mutex_initialize(&term->mtx); 776 atomic_flag_clear(&term->refcnt); 777 778 prodcons_initialize(&term->input_pc); 779 term->char_remains_len = 0; 780 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"); 794 rc = ENOMEM; 795 goto error; 796 } 797 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 787 843 gfx_bitmap_params_init(¶ms); 788 844 params.rect.p0.x = 0; … … 791 847 params.rect.p1.y = height; 792 848 793 errno_t rc = gfx_bitmap_create(term->gc, ¶ms, NULL, &new_bmp);849 rc = gfx_bitmap_create(term->gc, ¶ms, NULL, &term->bmp); 794 850 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) 815 { 816 list_remove(&term->link); 817 818 termui_destroy(term->termui); 819 820 if (term->ubuf) 821 as_area_destroy(term->ubuf); 822 823 ui_destroy(term->ui); 824 free(term); 825 } 826 827 static void terminal_queue_cons_event(terminal_t *term, cons_event_t *ev) 828 { 829 /* Got key press/release event */ 830 terminal_event_t *event = 831 (terminal_event_t *) malloc(sizeof(terminal_event_t)); 832 if (event == NULL) 833 return; 834 835 event->ev = *ev; 836 link_initialize(&event->link); 837 838 prodcons_produce(&term->input_pc, &event->link); 839 } 840 841 /** Handle window close event. */ 842 static void terminal_close_event(ui_window_t *window, void *arg) 843 { 844 terminal_t *term = (terminal_t *) arg; 845 846 ui_quit(term->ui); 847 } 848 849 /** Handle window focus event. */ 850 static void terminal_focus_event(ui_window_t *window, void *arg, 851 unsigned nfocus) 852 { 853 terminal_t *term = (terminal_t *) arg; 854 855 (void)nfocus; 856 term->is_focused = true; 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); 897 } 898 899 /** Handle window keyboard event */ 900 static void terminal_kbd_event(ui_window_t *window, void *arg, 901 kbd_event_t *kbd_event) 902 { 903 terminal_t *term = (terminal_t *) arg; 904 cons_event_t event; 905 906 event.type = CEV_KEY; 907 event.ev.key = *kbd_event; 908 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); 926 } 927 928 /** Handle window position event */ 929 static void terminal_pos_event(ui_window_t *window, void *arg, pos_event_t *event) 930 { 931 cons_event_t cevent; 932 terminal_t *term = (terminal_t *) arg; 933 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) 966 terminal_queue_cons_event(term, &cevent); 967 } 968 969 /** Handle window unfocus event. */ 970 static void terminal_unfocus_event(ui_window_t *window, void *arg, 971 unsigned nfocus) 972 { 973 terminal_t *term = (terminal_t *) arg; 974 975 if (nfocus == 0) { 976 term->is_focused = false; 977 term_render(term); 978 gfx_update(term->gc); 979 } 980 } 981 982 static void term_connection(ipc_call_t *icall, void *arg) 983 { 984 terminal_t *term = NULL; 985 986 list_foreach(terms, link, terminal_t, cur) { 987 if (cur->dsid == (service_id_t) ipc_get_arg2(icall)) { 988 term = cur; 989 break; 990 } 991 } 992 993 if (term == NULL) { 994 async_answer_0(icall, ENOENT); 995 return; 996 } 997 998 if (!atomic_flag_test_and_set(&term->refcnt)) 999 termui_set_cursor_visibility(term->termui, true); 1000 1001 con_conn(icall, &term->srvs); 1002 } 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 1057 errno_t terminal_create(const char *display_spec, sysarg_t width, 1058 sysarg_t height, terminal_flags_t flags, const char *command, 1059 terminal_t **rterm) 1060 { 1061 errno_t rc; 1062 1063 terminal_t *term = calloc(1, sizeof(terminal_t)); 1064 if (term == NULL) { 1065 printf("Out of memory.\n"); 1066 return ENOMEM; 1067 } 1068 1069 link_initialize(&term->link); 1070 fibril_mutex_initialize(&term->mtx); 1071 atomic_flag_clear(&term->refcnt); 1072 1073 prodcons_initialize(&term->input_pc); 1074 term->char_remains_len = 0; 1075 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)); 851 printf("Error allocating screen bitmap.\n"); 1089 852 goto error; 1090 853 } 1091 854 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"); 1096 rc = ENOMEM; 1097 goto error; 1098 } 1099 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); 855 chargrid_clear(term->frontbuf); 856 chargrid_clear(term->backbuf); 857 term->top_row = 0; 1103 858 1104 859 async_set_fallback_port_handler(term_connection, NULL); … … 1107 862 term->srvs.sarg = term; 1108 863 1109 rc = loc_server_register(NAME , &term->srv);864 rc = loc_server_register(NAME); 1110 865 if (rc != EOK) { 1111 866 printf("Error registering server.\n"); … … 1118 873 task_get_id()); 1119 874 1120 rc = loc_service_register( term->srv, vc, fallback_port_id, &term->dsid);875 rc = loc_service_register(vc, &term->dsid); 1121 876 if (rc != EOK) { 1122 877 printf("Error registering service.\n"); … … 1126 881 1127 882 list_append(&term->link, &terms); 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); 883 getterm(vc, "/app/bdsh"); 1137 884 1138 885 term->is_focused = true; 1139 886 1140 termui_refresh_cb(term); 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); 1141 893 1142 894 *rterm = term; 1143 895 return EOK; 1144 896 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);1149 897 if (term->window != NULL) 1150 898 ui_window_destroy(term->window); 1151 899 if (term->ui != NULL) 1152 900 ui_destroy(term->ui); 1153 if (term->termui != NULL) 1154 termui_destroy(term->termui); 901 if (term->frontbuf != NULL) 902 chargrid_destroy(term->frontbuf); 903 if (term->backbuf != NULL) 904 chargrid_destroy(term->backbuf); 1155 905 free(term); 1156 906 return rc; 1157 907 } 1158 908 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 not1167 * exit.1168 */1169 (void) task_wait(&term->wait, &texit, &retval);1170 ui_quit(term->ui);1171 return EOK;1172 }1173 1174 909 /** @} 1175 910 */
Note:
See TracChangeset
for help on using the changeset viewer.
