Changeset 899bdfd in mainline for uspace/app/terminal/terminal.c
- Timestamp:
- 2024-09-12T13:14:20Z (6 months ago)
- Branches:
- master
- Children:
- 4c2339b
- Parents:
- dd50aa19
- git-author:
- Jiří Zárevúcky <zarevucky.jiri@…> (2024-09-12 11:47:56)
- git-committer:
- Jiří Zárevúcky <zarevucky.jiri@…> (2024-09-12 13:14:20)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/app/terminal/terminal.c
rdd50aa19 r899bdfd 40 40 #include <errno.h> 41 41 #include <fbfont/font-8x16.h> 42 #include <io/chargrid.h>43 42 #include <fibril.h> 44 43 #include <gfx/bitmap.h> … … 49 48 #include <io/console.h> 50 49 #include <io/pixelmap.h> 51 #include < task.h>50 #include <macros.h> 52 51 #include <stdarg.h> 53 52 #include <stdio.h> 54 53 #include <stdlib.h> 54 #include <str_error.h> 55 55 #include <str.h> 56 #include <task.h> 56 57 #include <ui/resource.h> 57 58 #include <ui/ui.h> … … 71 72 (CONSOLE_CAP_STYLE | CONSOLE_CAP_INDEXED | CONSOLE_CAP_RGB) 72 73 74 #define SCROLLBACK_MAX_LINES 1000 75 #define MIN_WINDOW_COLS 8 76 #define MIN_WINDOW_ROWS 4 77 73 78 static LIST_INITIALIZE(terms); 79 80 #define COLOR_BRIGHT 8 81 82 static const pixel_t _basic_colors[16] = { 83 [COLOR_BLACK] = PIXEL(255, 0, 0, 0), 84 [COLOR_RED] = PIXEL(255, 170, 0, 0), 85 [COLOR_GREEN] = PIXEL(255, 0, 170, 0), 86 [COLOR_YELLOW] = PIXEL(255, 170, 85, 0), 87 [COLOR_BLUE] = PIXEL(255, 0, 0, 170), 88 [COLOR_MAGENTA] = PIXEL(255, 170, 0, 170), 89 [COLOR_CYAN] = PIXEL(255, 0, 170, 170), 90 [COLOR_WHITE] = PIXEL(255, 170, 170, 170), 91 92 [COLOR_BLACK | COLOR_BRIGHT] = PIXEL(255, 85, 85, 85), 93 [COLOR_RED | COLOR_BRIGHT] = PIXEL(255, 255, 85, 85), 94 [COLOR_GREEN | COLOR_BRIGHT] = PIXEL(255, 85, 255, 85), 95 [COLOR_YELLOW | COLOR_BRIGHT] = PIXEL(255, 255, 255, 85), 96 [COLOR_BLUE | COLOR_BRIGHT] = PIXEL(255, 85, 85, 255), 97 [COLOR_MAGENTA | COLOR_BRIGHT] = PIXEL(255, 255, 85, 255), 98 [COLOR_CYAN | COLOR_BRIGHT] = PIXEL(255, 85, 255, 255), 99 [COLOR_WHITE | COLOR_BRIGHT] = PIXEL(255, 255, 255, 255), 100 }; 74 101 75 102 static errno_t term_open(con_srvs_t *, con_srv_t *); … … 119 146 static void terminal_close_event(ui_window_t *, void *); 120 147 static void terminal_focus_event(ui_window_t *, void *, unsigned); 148 static void terminal_resize_event(ui_window_t *, void *); 121 149 static void terminal_kbd_event(ui_window_t *, void *, kbd_event_t *); 122 150 static void terminal_pos_event(ui_window_t *, void *, pos_event_t *); 123 151 static void terminal_unfocus_event(ui_window_t *, void *, unsigned); 152 static void terminal_maximize_event(ui_window_t *, void *); 153 static void terminal_unmaximize_event(ui_window_t *, void *); 124 154 125 155 static ui_window_cb_t terminal_window_cb = { 126 156 .close = terminal_close_event, 127 157 .focus = terminal_focus_event, 158 .resize = terminal_resize_event, 128 159 .kbd = terminal_kbd_event, 129 160 .pos = terminal_pos_event, 130 .unfocus = terminal_unfocus_event 161 .unfocus = terminal_unfocus_event, 162 .maximize = terminal_maximize_event, 163 .unmaximize = terminal_unmaximize_event, 131 164 }; 132 165 … … 144 177 } 145 178 146 static pixel_t color_table[16] = { 147 [COLOR_BLACK] = PIXEL(255, 0, 0, 0), 148 [COLOR_BLUE] = PIXEL(255, 0, 0, 170), 149 [COLOR_GREEN] = PIXEL(255, 0, 170, 0), 150 [COLOR_CYAN] = PIXEL(255, 0, 170, 170), 151 [COLOR_RED] = PIXEL(255, 170, 0, 0), 152 [COLOR_MAGENTA] = PIXEL(255, 170, 0, 170), 153 [COLOR_YELLOW] = PIXEL(255, 170, 85, 0), 154 [COLOR_WHITE] = PIXEL(255, 170, 170, 170), 155 156 [COLOR_BLACK + 8] = PIXEL(255, 85, 85, 85), 157 [COLOR_BLUE + 8] = PIXEL(255, 85, 85, 255), 158 [COLOR_GREEN + 8] = PIXEL(255, 85, 255, 85), 159 [COLOR_CYAN + 8] = PIXEL(255, 85, 255, 255), 160 [COLOR_RED + 8] = PIXEL(255, 255, 85, 85), 161 [COLOR_MAGENTA + 8] = PIXEL(255, 255, 85, 255), 162 [COLOR_YELLOW + 8] = PIXEL(255, 255, 255, 85), 163 [COLOR_WHITE + 8] = PIXEL(255, 255, 255, 255), 164 }; 165 166 static inline void attrs_rgb(char_attrs_t attrs, pixel_t *bgcolor, pixel_t *fgcolor) 167 { 168 switch (attrs.type) { 179 static pixel_t termui_color_to_pixel(termui_color_t c) 180 { 181 uint8_t r, g, b; 182 termui_color_to_rgb(c, &r, &g, &b); 183 return PIXEL(255, r, g, b); 184 } 185 186 static termui_color_t termui_color_from_pixel(pixel_t pixel) 187 { 188 return termui_color_from_rgb(RED(pixel), GREEN(pixel), BLUE(pixel)); 189 } 190 191 static termui_cell_t charfield_to_termui_cell(terminal_t *term, const charfield_t *cf) 192 { 193 termui_cell_t cell = { }; 194 195 cell.glyph_idx = fb_font_glyph(cf->ch, NULL); 196 197 switch (cf->attrs.type) { 169 198 case CHAR_ATTR_STYLE: 170 switch ( attrs.val.style) {199 switch (cf->attrs.val.style) { 171 200 case STYLE_NORMAL: 172 *bgcolor = color_table[COLOR_WHITE + 8];173 *fgcolor = color_table[COLOR_BLACK];201 cell.bgcolor = term->default_bgcolor; 202 cell.fgcolor = term->default_fgcolor; 174 203 break; 175 204 case STYLE_EMPHASIS: 176 *bgcolor = color_table[COLOR_WHITE + 8];177 *fgcolor = color_table[COLOR_RED + 8];205 cell.bgcolor = term->emphasis_bgcolor; 206 cell.fgcolor = term->emphasis_fgcolor; 178 207 break; 179 208 case STYLE_INVERTED: 180 *bgcolor = color_table[COLOR_BLACK]; 181 *fgcolor = color_table[COLOR_WHITE + 8]; 209 cell.bgcolor = term->default_bgcolor; 210 cell.fgcolor = term->default_fgcolor; 211 cell.inverted = 1; 182 212 break; 183 213 case STYLE_SELECTED: 184 *bgcolor = color_table[COLOR_RED + 8];185 *fgcolor = color_table[COLOR_WHITE + 8];214 cell.bgcolor = term->selection_bgcolor; 215 cell.fgcolor = term->selection_fgcolor; 186 216 break; 187 217 } 188 218 break; 219 189 220 case CHAR_ATTR_INDEX: 190 *bgcolor = color_table[(attrs.val.index.bgcolor & 7)]; 191 *fgcolor = color_table[(attrs.val.index.fgcolor & 7) | 192 ((attrs.val.index.attr & CATTR_BRIGHT) ? 8 : 0)]; 221 char_attr_index_t index = cf->attrs.val.index; 222 223 int bright = (index.attr & CATTR_BRIGHT) ? COLOR_BRIGHT : 0; 224 pixel_t bgcolor = _basic_colors[index.bgcolor | bright]; 225 pixel_t fgcolor = _basic_colors[index.fgcolor | bright]; 226 cell.bgcolor = termui_color_from_pixel(bgcolor); 227 cell.fgcolor = termui_color_from_pixel(fgcolor); 228 229 if (index.attr & CATTR_BLINK) 230 cell.blink = 1; 231 193 232 break; 233 194 234 case CHAR_ATTR_RGB: 195 *bgcolor = 0xff000000 | attrs.val.rgb.bgcolor;196 *fgcolor = 0xff000000 | attrs.val.rgb.fgcolor;235 cell.bgcolor = termui_color_from_pixel(cf->attrs.val.rgb.bgcolor); 236 cell.fgcolor = termui_color_from_pixel(cf->attrs.val.rgb.fgcolor); 197 237 break; 198 238 } 239 240 return cell; 199 241 } 200 242 … … 214 256 } 215 257 216 static void term_update_char(terminal_t *term, pixelmap_t *pixelmap, 217 sysarg_t col, sysarg_t row) 218 { 219 charfield_t *field = 220 chargrid_charfield_at(term->backbuf, col, row); 221 222 bool inverted = chargrid_cursor_at(term->backbuf, col, row); 223 224 sysarg_t bx = col * FONT_WIDTH; 225 sysarg_t by = row * FONT_SCANLINES; 226 227 pixel_t bgcolor = 0; 228 pixel_t fgcolor = 0; 229 230 if (inverted) 231 attrs_rgb(field->attrs, &fgcolor, &bgcolor); 232 else 233 attrs_rgb(field->attrs, &bgcolor, &fgcolor); 234 235 // FIXME: Glyph type should be actually uint32_t 236 // for full UTF-32 coverage. 237 238 uint16_t glyph = fb_font_glyph(field->ch, NULL); 258 static void term_draw_cell(terminal_t *term, pixelmap_t *pixelmap, int col, int row, const termui_cell_t *cell) 259 { 260 termui_color_t bg = cell->bgcolor; 261 if (bg == TERMUI_COLOR_DEFAULT) 262 bg = term->default_bgcolor; 263 264 termui_color_t fg = cell->fgcolor; 265 if (fg == TERMUI_COLOR_DEFAULT) 266 fg = term->default_fgcolor; 267 268 pixel_t bgcolor = termui_color_to_pixel(bg); 269 pixel_t fgcolor = termui_color_to_pixel(fg); 270 271 int bx = col * FONT_WIDTH; 272 int by = row * FONT_SCANLINES; 273 274 // TODO: support bold/italic/underline/strike/blink styling 275 276 if (cell->inverted ^ cell->cursor) { 277 pixel_t tmp = bgcolor; 278 bgcolor = fgcolor; 279 fgcolor = tmp; 280 } 281 282 uint32_t glyph = cell->glyph_idx; 283 assert(glyph < FONT_GLYPHS); 284 285 if (glyph == 0) 286 glyph = fb_font_glyph(U' ', NULL); 239 287 240 288 for (unsigned int y = 0; y < FONT_SCANLINES; y++) { … … 248 296 } 249 297 } 298 250 299 term_update_region(term, bx, by, FONT_WIDTH, FONT_SCANLINES); 251 300 } 252 301 253 static bool term_update_scroll(terminal_t *term, pixelmap_t *pixelmap) 254 { 255 sysarg_t top_row = chargrid_get_top_row(term->frontbuf); 256 257 if (term->top_row == top_row) { 258 return false; 259 } 260 261 term->top_row = top_row; 262 263 for (sysarg_t row = 0; row < term->rows; row++) { 264 for (sysarg_t col = 0; col < term->cols; col++) { 265 charfield_t *front_field = 266 chargrid_charfield_at(term->frontbuf, col, row); 267 charfield_t *back_field = 268 chargrid_charfield_at(term->backbuf, col, row); 269 bool update = false; 270 271 if (front_field->ch != back_field->ch) { 272 back_field->ch = front_field->ch; 273 update = true; 274 } 275 276 if (!attrs_same(front_field->attrs, back_field->attrs)) { 277 back_field->attrs = front_field->attrs; 278 update = true; 279 } 280 281 front_field->flags &= ~CHAR_FLAG_DIRTY; 282 283 if (update) { 284 term_update_char(term, pixelmap, col, row); 285 } 286 } 287 } 288 289 return true; 290 } 291 292 static bool term_update_cursor(terminal_t *term, pixelmap_t *pixelmap) 293 { 294 bool update = false; 295 296 sysarg_t front_col; 297 sysarg_t front_row; 298 chargrid_get_cursor(term->frontbuf, &front_col, &front_row); 299 300 sysarg_t back_col; 301 sysarg_t back_row; 302 chargrid_get_cursor(term->backbuf, &back_col, &back_row); 303 304 bool front_visibility = 305 chargrid_get_cursor_visibility(term->frontbuf) && 306 term->is_focused; 307 bool back_visibility = 308 chargrid_get_cursor_visibility(term->backbuf); 309 310 if (front_visibility != back_visibility) { 311 chargrid_set_cursor_visibility(term->backbuf, 312 front_visibility); 313 term_update_char(term, pixelmap, back_col, back_row); 314 update = true; 315 } 316 317 if ((front_col != back_col) || (front_row != back_row)) { 318 chargrid_set_cursor(term->backbuf, front_col, front_row); 319 term_update_char(term, pixelmap, back_col, back_row); 320 term_update_char(term, pixelmap, front_col, front_row); 321 update = true; 322 } 323 324 return update; 325 } 326 327 static void term_update(terminal_t *term) 328 { 329 pixelmap_t pixelmap; 302 static void term_render(terminal_t *term) 303 { 304 gfx_coord2_t pos = { .x = 4, .y = 26 }; 305 (void) gfx_bitmap_render(term->bmp, &term->update, &pos); 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 = { }; 330 331 gfx_bitmap_alloc_t alloc; 331 gfx_coord2_t pos; 332 errno_t rc; 333 334 rc = gfx_bitmap_get_alloc(term->bmp, &alloc); 335 if (rc != EOK) { 336 return; 337 } 338 339 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 340 337 pixelmap.width = term->w; 341 338 pixelmap.height = term->h; 342 339 pixelmap.data = alloc.pixels; 343 344 bool update = false; 345 346 if (term_update_scroll(term, &pixelmap)) { 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, x, y); 375 update = true; 376 } 377 } 378 } 379 } 380 381 if (term_update_cursor(term, &pixelmap)) 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"); 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) 407 347 return; 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 if (!term_update_scroll(term, &pixelmap)) { 417 for (sysarg_t y = 0; y < term->rows; y++) { 418 for (sysarg_t x = 0; x < term->cols; x++) { 419 charfield_t *front_field = 420 chargrid_charfield_at(term->frontbuf, x, y); 421 charfield_t *back_field = 422 chargrid_charfield_at(term->backbuf, x, y); 423 424 back_field->ch = front_field->ch; 425 back_field->attrs = front_field->attrs; 426 front_field->flags &= ~CHAR_FLAG_DIRTY; 427 428 term_update_char(term, &pixelmap, x, y); 429 } 430 } 431 } 432 433 term_update_cursor(term, &pixelmap); 434 435 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]); 436 366 } 437 367 … … 497 427 static void term_write_char(terminal_t *term, wchar_t ch) 498 428 { 499 sysarg_t updated = 0;500 501 fibril_mutex_lock(&term->mtx);502 503 429 switch (ch) { 504 case '\n':505 updated = chargrid_newline(term->frontbuf);430 case L'\n': 431 termui_put_crlf(term->termui); 506 432 break; 507 case '\r': 433 case L'\r': 434 termui_put_cr(term->termui); 508 435 break; 509 case '\t':510 updated = chargrid_tabstop(term->frontbuf, 8);436 case L'\t': 437 termui_put_tab(term->termui); 511 438 break; 512 case '\b':513 updated = chargrid_backspace(term->frontbuf);439 case L'\b': 440 termui_put_backspace(term->termui); 514 441 break; 515 442 default: 516 updated = chargrid_putuchar(term->frontbuf, ch, true); 517 } 518 519 fibril_mutex_unlock(&term->mtx); 520 521 if (updated > 1) 522 term_update(term); 443 // TODO: For some languages, we might need support for combining 444 // characters. Currently, we assume every unicode code point is 445 // an individual printed character, which is not always the case. 446 termui_put_glyph(term->termui, fb_font_glyph(ch, NULL), 1); 447 break; 448 } 523 449 } 524 450 … … 526 452 { 527 453 terminal_t *term = srv_to_terminal(srv); 454 455 fibril_mutex_lock(&term->mtx); 528 456 529 457 size_t off = 0; … … 531 459 term_write_char(term, str_decode(data, &off, size)); 532 460 461 fibril_mutex_unlock(&term->mtx); 462 463 term_render(term); 533 464 gfx_update(term->gc); 534 465 *nwritten = size; 466 535 467 return EOK; 536 468 } … … 540 472 terminal_t *term = srv_to_terminal(srv); 541 473 542 term_ update(term);474 term_render(term); 543 475 gfx_update(term->gc); 544 476 } … … 549 481 550 482 fibril_mutex_lock(&term->mtx); 551 chargrid_clear(term->frontbuf);552 fibril_mutex_unlock(&term->mtx); 553 554 term_ update(term);483 termui_clear_screen(term->termui); 484 fibril_mutex_unlock(&term->mtx); 485 486 term_render(term); 555 487 gfx_update(term->gc); 556 488 } … … 561 493 562 494 fibril_mutex_lock(&term->mtx); 563 chargrid_set_cursor(term->frontbuf, col, row);564 fibril_mutex_unlock(&term->mtx); 565 566 term_ update(term);495 termui_set_pos(term->termui, col, row); 496 fibril_mutex_unlock(&term->mtx); 497 498 term_render(term); 567 499 gfx_update(term->gc); 568 500 } … … 573 505 574 506 fibril_mutex_lock(&term->mtx); 575 chargrid_get_cursor(term->frontbuf, col, row); 576 fibril_mutex_unlock(&term->mtx); 507 int irow, icol; 508 termui_get_pos(term->termui, &icol, &irow); 509 fibril_mutex_unlock(&term->mtx); 510 511 *col = icol; 512 *row = irow; 577 513 578 514 return EOK; … … 584 520 585 521 fibril_mutex_lock(&term->mtx); 586 *cols = term ->cols;587 *rows = term ->rows;522 *cols = termui_get_cols(term->termui); 523 *rows = termui_get_rows(term->termui); 588 524 fibril_mutex_unlock(&term->mtx); 589 525 … … 603 539 terminal_t *term = srv_to_terminal(srv); 604 540 605 fibril_mutex_lock(&term->mtx); 606 chargrid_set_style(term->frontbuf, style); 541 termui_cell_t cellstyle = { }; 542 543 switch (style) { 544 case STYLE_NORMAL: 545 cellstyle.bgcolor = term->default_bgcolor; 546 cellstyle.fgcolor = term->default_fgcolor; 547 break; 548 case STYLE_EMPHASIS: 549 cellstyle.bgcolor = term->emphasis_bgcolor; 550 cellstyle.fgcolor = term->emphasis_fgcolor; 551 break; 552 case STYLE_INVERTED: 553 cellstyle.bgcolor = term->default_bgcolor; 554 cellstyle.fgcolor = term->default_fgcolor; 555 cellstyle.inverted = 1; 556 break; 557 case STYLE_SELECTED: 558 cellstyle.bgcolor = term->selection_bgcolor; 559 cellstyle.fgcolor = term->selection_fgcolor; 560 break; 561 } 562 563 fibril_mutex_lock(&term->mtx); 564 termui_set_style(term->termui, cellstyle); 607 565 fibril_mutex_unlock(&term->mtx); 608 566 } … … 613 571 terminal_t *term = srv_to_terminal(srv); 614 572 615 fibril_mutex_lock(&term->mtx); 616 chargrid_set_color(term->frontbuf, bgcolor, fgcolor, attr); 573 int bright = (attr & CATTR_BRIGHT) ? COLOR_BRIGHT : 0; 574 575 termui_cell_t cellstyle = { }; 576 cellstyle.bgcolor = termui_color_from_pixel(_basic_colors[bgcolor | bright]); 577 cellstyle.fgcolor = termui_color_from_pixel(_basic_colors[fgcolor | bright]); 578 579 if (attr & CATTR_BLINK) 580 cellstyle.blink = 1; 581 582 fibril_mutex_lock(&term->mtx); 583 termui_set_style(term->termui, cellstyle); 617 584 fibril_mutex_unlock(&term->mtx); 618 585 } … … 622 589 { 623 590 terminal_t *term = srv_to_terminal(srv); 624 625 fibril_mutex_lock(&term->mtx); 626 chargrid_set_rgb_color(term->frontbuf, bgcolor, fgcolor); 591 termui_cell_t cellstyle = { 592 .bgcolor = termui_color_from_pixel(bgcolor), 593 .fgcolor = termui_color_from_pixel(fgcolor), 594 }; 595 596 fibril_mutex_lock(&term->mtx); 597 termui_set_style(term->termui, cellstyle); 627 598 fibril_mutex_unlock(&term->mtx); 628 599 } … … 633 604 634 605 fibril_mutex_lock(&term->mtx); 635 chargrid_set_cursor_visibility(term->frontbuf, visible);636 fibril_mutex_unlock(&term->mtx); 637 638 term_ update(term);606 termui_set_cursor_visibility(term->termui, visible); 607 fibril_mutex_unlock(&term->mtx); 608 609 term_render(term); 639 610 gfx_update(term->gc); 640 611 } … … 655 626 fibril_mutex_unlock(&term->mtx); 656 627 657 term_ update(term);628 term_render(term); 658 629 gfx_update(term->gc); 659 630 return EOK; … … 703 674 term->urows = rows; 704 675 term->ubuf = buf; 676 677 /* Scroll back to active screen. */ 678 termui_history_scroll(term->termui, INT_MAX); 679 705 680 fibril_mutex_unlock(&term->mtx); 706 681 … … 723 698 term->ubuf = NULL; 724 699 700 termui_wipe_screen(term->termui, 0); 701 702 fibril_mutex_unlock(&term->mtx); 703 704 /* Update terminal */ 705 term_render(term); 706 gfx_update(term->gc); 707 725 708 if (buf != NULL) 726 709 as_area_destroy(buf); 727 728 fibril_mutex_unlock(&term->mtx);729 710 } 730 711 … … 741 722 { 742 723 terminal_t *term = srv_to_terminal(srv); 743 charfield_t *ch;744 sysarg_t col, row;745 724 746 725 fibril_mutex_lock(&term->mtx); … … 752 731 753 732 /* Make sure we have meaningful coordinates, within bounds */ 754 755 if (c1 > term->ucols)756 c1 = term->ucols;757 if (c1 > term->cols)758 c1 = term->cols; 759 if (c0 >= c1 ) {733 c1 = min(c1, term->ucols); 734 c1 = min(c1, (sysarg_t) termui_get_cols(term->termui)); 735 r1 = min(r1, term->urows); 736 r1 = min(r1, (sysarg_t) termui_get_rows(term->termui)); 737 738 if (c0 >= c1 || r0 >= r1) { 760 739 fibril_mutex_unlock(&term->mtx); 761 740 return; 762 741 } 763 if (r1 > term->urows)764 r1 = term->urows;765 if (r1 > term->rows)766 r1 = term->rows;767 if (r0 >= r1) {768 fibril_mutex_unlock(&term->mtx);769 return;770 }771 742 772 743 /* Update front buffer from user buffer */ 773 744 774 for (row = r0; row < r1; row++) { 775 for (col = c0; col < c1; col++) { 776 ch = chargrid_charfield_at(term->frontbuf, col, row); 777 *ch = term->ubuf[row * term->ucols + col]; 745 for (sysarg_t row = r0; row < r1; row++) { 746 termui_cell_t *cells = termui_get_active_row(term->termui, row); 747 748 for (sysarg_t col = c0; col < c1; col++) { 749 cells[col] = charfield_to_termui_cell(term, &term->ubuf[row * term->ucols + col]); 778 750 } 751 752 termui_update_cb(term, c0, row, &cells[c0], c1 - c0); 779 753 } 780 754 … … 782 756 783 757 /* Update terminal */ 784 term_ update(term);758 term_render(term); 785 759 gfx_update(term->gc); 786 760 } 787 761 788 static void deinit_terminal(terminal_t *term) 762 static errno_t terminal_window_resize(terminal_t *term) 763 { 764 gfx_rect_t rect; 765 ui_window_get_app_rect(term->window, &rect); 766 767 int width = rect.p1.x - rect.p0.x; 768 int height = rect.p1.y - rect.p0.y; 769 770 if (!term->gc) 771 term->gc = ui_window_get_gc(term->window); 772 else 773 assert(term->gc == ui_window_get_gc(term->window)); 774 775 if (!term->ui_res) 776 term->ui_res = ui_window_get_res(term->window); 777 else 778 assert(term->ui_res == ui_window_get_res(term->window)); 779 780 gfx_bitmap_t *new_bmp; 781 gfx_bitmap_params_t params; 782 gfx_bitmap_params_init(¶ms); 783 params.rect.p0.x = 0; 784 params.rect.p0.y = 0; 785 params.rect.p1.x = width; 786 params.rect.p1.y = height; 787 788 errno_t rc = gfx_bitmap_create(term->gc, ¶ms, NULL, &new_bmp); 789 if (rc != EOK) { 790 fprintf(stderr, "Error allocating new screen bitmap: %s\n", str_error(rc)); 791 return rc; 792 } 793 794 if (term->bmp) { 795 rc = gfx_bitmap_destroy(term->bmp); 796 if (rc != EOK) 797 fprintf(stderr, "Error deallocating old screen bitmap: %s\n", str_error(rc)); 798 } 799 800 term->bmp = new_bmp; 801 term->w = width; 802 term->h = height; 803 804 term_clear_bitmap(term, termui_color_to_pixel(term->default_bgcolor)); 805 806 return EOK; 807 } 808 809 void terminal_destroy(terminal_t *term) 789 810 { 790 811 list_remove(&term->link); 791 812 792 if (term->frontbuf) 793 chargrid_destroy(term->frontbuf); 794 795 if (term->backbuf) 796 chargrid_destroy(term->backbuf); 797 } 798 799 void terminal_destroy(terminal_t *term) 800 { 801 deinit_terminal(term); 813 termui_destroy(term->termui); 814 815 if (term->ubuf) 816 as_area_destroy(term->ubuf); 817 802 818 free(term); 803 819 } … … 833 849 (void)nfocus; 834 850 term->is_focused = true; 835 term_ update(term);851 term_render(term); 836 852 gfx_update(term->gc); 853 } 854 855 static void terminal_resize_handler(ui_window_t *window, void *arg) 856 { 857 terminal_t *term = (terminal_t *) arg; 858 859 fibril_mutex_lock(&term->mtx); 860 861 errno_t rc = terminal_window_resize(term); 862 if (rc == EOK) { 863 (void) termui_resize(term->termui, term->w / FONT_WIDTH, term->h / FONT_SCANLINES, SCROLLBACK_MAX_LINES); 864 termui_refresh_cb(term); 865 term_render(term); 866 gfx_update(term->gc); 867 868 cons_event_t event = { .type = CEV_RESIZE }; 869 terminal_queue_cons_event(term, &event); 870 } 871 872 fibril_mutex_unlock(&term->mtx); 873 } 874 875 static void terminal_resize_event(ui_window_t *window, void *arg) 876 { 877 ui_window_def_resize(window); 878 terminal_resize_handler(window, arg); 879 } 880 881 static void terminal_maximize_event(ui_window_t *window, void *arg) 882 { 883 ui_window_def_maximize(window); 884 terminal_resize_handler(window, arg); 885 } 886 887 static void terminal_unmaximize_event(ui_window_t *window, void *arg) 888 { 889 ui_window_def_unmaximize(window); 890 terminal_resize_handler(window, arg); 837 891 } 838 892 … … 847 901 event.ev.key = *kbd_event; 848 902 849 terminal_queue_cons_event(term, &event); 903 const int PAGE_ROWS = (termui_get_rows(term->termui) * 2) / 3; 904 905 fibril_mutex_lock(&term->mtx); 906 907 if (!term->ubuf && kbd_event->type == KEY_PRESS && 908 (kbd_event->key == KC_PAGE_UP || kbd_event->key == KC_PAGE_DOWN)) { 909 910 termui_history_scroll(term->termui, 911 (kbd_event->key == KC_PAGE_UP) ? -PAGE_ROWS : PAGE_ROWS); 912 913 term_render(term); 914 gfx_update(term->gc); 915 } else { 916 terminal_queue_cons_event(term, &event); 917 } 918 919 fibril_mutex_unlock(&term->mtx); 850 920 } 851 921 … … 856 926 terminal_t *term = (terminal_t *) arg; 857 927 928 switch (event->type) { 929 case POS_UPDATE: 930 return; 931 932 case POS_PRESS: 933 case POS_RELEASE: 934 case POS_DCLICK: 935 } 936 937 /* Ignore mouse events when we're in scrollback mode. */ 938 if (termui_scrollback_is_active(term->termui)) 939 return; 940 858 941 sysarg_t sx = -term->off.x; 859 942 sysarg_t sy = -term->off.y; 860 943 861 if (event->type == POS_PRESS || event->type == POS_RELEASE || 862 event->type == POS_DCLICK) { 863 cevent.type = CEV_POS; 864 cevent.ev.pos.type = event->type; 865 cevent.ev.pos.pos_id = event->pos_id; 866 cevent.ev.pos.btn_num = event->btn_num; 867 868 cevent.ev.pos.hpos = (event->hpos - sx) / FONT_WIDTH; 869 cevent.ev.pos.vpos = (event->vpos - sy) / FONT_SCANLINES; 944 if (event->hpos < sx || event->vpos < sy) 945 return; 946 947 cevent.type = CEV_POS; 948 cevent.ev.pos.type = event->type; 949 cevent.ev.pos.pos_id = event->pos_id; 950 cevent.ev.pos.btn_num = event->btn_num; 951 952 cevent.ev.pos.hpos = (event->hpos - sx) / FONT_WIDTH; 953 cevent.ev.pos.vpos = (event->vpos - sy) / FONT_SCANLINES; 954 955 /* Filter out events outside the terminal area. */ 956 int cols = termui_get_cols(term->termui); 957 int rows = termui_get_rows(term->termui); 958 959 if (cevent.ev.pos.hpos < (sysarg_t) cols && cevent.ev.pos.vpos < (sysarg_t) rows) 870 960 terminal_queue_cons_event(term, &cevent); 871 }872 961 } 873 962 … … 880 969 if (nfocus == 0) { 881 970 term->is_focused = false; 882 term_ update(term);971 term_render(term); 883 972 gfx_update(term->gc); 884 973 } … … 902 991 903 992 if (!atomic_flag_test_and_set(&term->refcnt)) 904 chargrid_set_cursor_visibility(term->frontbuf, true);993 termui_set_cursor_visibility(term->termui, true); 905 994 906 995 con_conn(icall, &term->srvs); 996 } 997 998 static errno_t term_init_window(terminal_t *term, const char *display_spec, 999 gfx_coord_t width, gfx_coord_t height, 1000 gfx_coord_t min_width, gfx_coord_t min_height, 1001 terminal_flags_t flags) 1002 { 1003 gfx_rect_t min_rect = { { 0, 0 }, { min_width, min_height } }; 1004 1005 ui_wnd_params_t wparams; 1006 ui_wnd_params_init(&wparams); 1007 wparams.caption = "Terminal"; 1008 wparams.style |= ui_wds_maximize_btn | ui_wds_resizable; 1009 if ((flags & tf_topleft) != 0) 1010 wparams.placement = ui_wnd_place_top_left; 1011 1012 errno_t rc = ui_create(display_spec, &term->ui); 1013 if (rc != EOK) { 1014 printf("Error creating UI on %s.\n", display_spec); 1015 return rc; 1016 } 1017 1018 /* Compute wrect such that application area corresponds to rect. */ 1019 gfx_rect_t wrect; 1020 ui_wdecor_rect_from_app(term->ui, wparams.style, &min_rect, &wrect); 1021 gfx_rect_rtranslate(&wrect.p0, &wrect, &wparams.rect); 1022 1023 rc = ui_window_create(term->ui, &wparams, &term->window); 1024 if (rc != EOK) 1025 return rc; 1026 1027 gfx_rect_t rect = { { 0, 0 }, { width, height } }; 1028 ui_wdecor_rect_from_app(term->ui, wparams.style, &rect, &rect); 1029 term->off = rect.p0; 1030 gfx_rect_rtranslate(&term->off, &rect, &wrect); 1031 1032 ui_window_resize(term->window, &wrect); 1033 ui_window_set_cb(term->window, &terminal_window_cb, (void *) term); 1034 1035 return terminal_window_resize(term); 907 1036 } 908 1037 … … 911 1040 terminal_t **rterm) 912 1041 { 913 terminal_t *term; 914 gfx_bitmap_params_t params; 915 ui_wnd_params_t wparams; 916 gfx_rect_t rect; 917 gfx_coord2_t off; 918 gfx_rect_t wrect; 1042 printf("terminal_create(%zu, %zu)\n", width, height); 1043 919 1044 errno_t rc; 920 1045 921 term = calloc(1, sizeof(terminal_t));1046 terminal_t *term = calloc(1, sizeof(terminal_t)); 922 1047 if (term == NULL) { 923 1048 printf("Out of memory.\n"); … … 932 1057 term->char_remains_len = 0; 933 1058 934 term-> w = width;935 term-> h = height;936 937 term-> cols = width / FONT_WIDTH;938 term-> rows = height / FONT_SCANLINES;939 940 term-> frontbuf = NULL;941 term-> backbuf = NULL;942 943 term-> frontbuf = chargrid_create(term->cols, term->rows,944 CHARGRID_FLAG_NONE);945 if (!term-> frontbuf) {946 printf("Error creating front buffer.\n");1059 term->default_bgcolor = termui_color_from_pixel(_basic_colors[COLOR_WHITE | COLOR_BRIGHT]); 1060 term->default_fgcolor = termui_color_from_pixel(_basic_colors[COLOR_BLACK]); 1061 1062 term->emphasis_bgcolor = termui_color_from_pixel(_basic_colors[COLOR_WHITE | COLOR_BRIGHT]); 1063 term->emphasis_fgcolor = termui_color_from_pixel(_basic_colors[COLOR_RED | COLOR_BRIGHT]); 1064 1065 term->selection_bgcolor = termui_color_from_pixel(_basic_colors[COLOR_RED | COLOR_BRIGHT]); 1066 term->selection_fgcolor = termui_color_from_pixel(_basic_colors[COLOR_WHITE | COLOR_BRIGHT]); 1067 1068 term->termui = termui_create(width / FONT_WIDTH, height / FONT_SCANLINES, 1069 SCROLLBACK_MAX_LINES); 1070 if (!term->termui) { 1071 printf("Error creating terminal UI.\n"); 947 1072 rc = ENOMEM; 948 1073 goto error; 949 1074 } 950 1075 951 term->backbuf = chargrid_create(term->cols, term->rows, 952 CHARGRID_FLAG_NONE); 953 if (!term->backbuf) { 954 printf("Error creating back buffer.\n"); 955 rc = ENOMEM; 1076 termui_set_refresh_cb(term->termui, termui_refresh_cb, term); 1077 termui_set_scroll_cb(term->termui, termui_scroll_cb, term); 1078 termui_set_update_cb(term->termui, termui_update_cb, term); 1079 1080 rc = term_init_window(term, display_spec, width, height, 1081 MIN_WINDOW_COLS * FONT_WIDTH, MIN_WINDOW_ROWS * FONT_SCANLINES, flags); 1082 if (rc != EOK) { 1083 printf("Error creating window (%s).\n", str_error(rc)); 956 1084 goto error; 957 1085 } 958 959 rect.p0.x = 0;960 rect.p0.y = 0;961 rect.p1.x = width;962 rect.p1.y = height;963 964 ui_wnd_params_init(&wparams);965 wparams.caption = "Terminal";966 if ((flags & tf_topleft) != 0)967 wparams.placement = ui_wnd_place_top_left;968 969 rc = ui_create(display_spec, &term->ui);970 if (rc != EOK) {971 printf("Error creating UI on %s.\n", display_spec);972 goto error;973 }974 975 /*976 * Compute window rectangle such that application area corresponds977 * to rect978 */979 ui_wdecor_rect_from_app(term->ui, wparams.style, &rect, &wrect);980 off = wrect.p0;981 gfx_rect_rtranslate(&off, &wrect, &wparams.rect);982 983 term->off = off;984 985 rc = ui_window_create(term->ui, &wparams, &term->window);986 if (rc != EOK) {987 printf("Error creating window.\n");988 goto error;989 }990 991 term->gc = ui_window_get_gc(term->window);992 term->ui_res = ui_window_get_res(term->window);993 994 ui_window_set_cb(term->window, &terminal_window_cb, (void *) term);995 996 gfx_bitmap_params_init(¶ms);997 params.rect.p0.x = 0;998 params.rect.p0.y = 0;999 params.rect.p1.x = width;1000 params.rect.p1.y = height;1001 1002 rc = gfx_bitmap_create(term->gc, ¶ms, NULL, &term->bmp);1003 if (rc != EOK) {1004 printf("Error allocating screen bitmap.\n");1005 goto error;1006 }1007 1008 chargrid_clear(term->frontbuf);1009 chargrid_clear(term->backbuf);1010 term->top_row = 0;1011 1086 1012 1087 async_set_fallback_port_handler(term_connection, NULL); … … 1046 1121 term->is_focused = true; 1047 1122 1048 term->update.p0.x = 0; 1049 term->update.p0.y = 0; 1050 term->update.p1.x = 0; 1051 term->update.p1.y = 0; 1052 1053 term_repaint(term); 1123 termui_refresh_cb(term); 1054 1124 1055 1125 *rterm = term; … … 1064 1134 if (term->ui != NULL) 1065 1135 ui_destroy(term->ui); 1066 if (term->frontbuf != NULL) 1067 chargrid_destroy(term->frontbuf); 1068 if (term->backbuf != NULL) 1069 chargrid_destroy(term->backbuf); 1136 if (term->termui != NULL) 1137 termui_destroy(term->termui); 1070 1138 free(term); 1071 1139 return rc;
Note:
See TracChangeset
for help on using the changeset viewer.