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