Changeset ebb1489 in mainline for uspace/app/terminal/terminal.c
- Timestamp:
- 2024-10-13T08:23:40Z (8 weeks ago)
- Children:
- 0472cf17
- Parents:
- 2a0c827c (diff), b3b79981 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - git-author:
- boba-buba <120932204+boba-buba@…> (2024-10-13 08:23:40)
- git-committer:
- GitHub <noreply@…> (2024-10-13 08:23:40)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/app/terminal/terminal.c
r2a0c827c rebb1489 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> … … 69 70 70 71 #define TERM_CAPS \ 71 (CONSOLE_CAP_STYLE | CONSOLE_CAP_INDEXED | CONSOLE_CAP_RGB) 72 (CONSOLE_CAP_CURSORCTL | CONSOLE_CAP_STYLE | CONSOLE_CAP_INDEXED | \ 73 CONSOLE_CAP_RGB) 74 75 #define SCROLLBACK_MAX_LINES 1000 76 #define MIN_WINDOW_COLS 8 77 #define MIN_WINDOW_ROWS 4 72 78 73 79 static LIST_INITIALIZE(terms); 80 81 #define COLOR_BRIGHT 8 82 83 static const pixel_t _basic_colors[16] = { 84 [COLOR_BLACK] = PIXEL(255, 0, 0, 0), 85 [COLOR_RED] = PIXEL(255, 170, 0, 0), 86 [COLOR_GREEN] = PIXEL(255, 0, 170, 0), 87 [COLOR_YELLOW] = PIXEL(255, 170, 85, 0), 88 [COLOR_BLUE] = PIXEL(255, 0, 0, 170), 89 [COLOR_MAGENTA] = PIXEL(255, 170, 0, 170), 90 [COLOR_CYAN] = PIXEL(255, 0, 170, 170), 91 [COLOR_WHITE] = PIXEL(255, 170, 170, 170), 92 93 [COLOR_BLACK | COLOR_BRIGHT] = PIXEL(255, 85, 85, 85), 94 [COLOR_RED | COLOR_BRIGHT] = PIXEL(255, 255, 85, 85), 95 [COLOR_GREEN | COLOR_BRIGHT] = PIXEL(255, 85, 255, 85), 96 [COLOR_YELLOW | COLOR_BRIGHT] = PIXEL(255, 255, 255, 85), 97 [COLOR_BLUE | COLOR_BRIGHT] = PIXEL(255, 85, 85, 255), 98 [COLOR_MAGENTA | COLOR_BRIGHT] = PIXEL(255, 255, 85, 255), 99 [COLOR_CYAN | COLOR_BRIGHT] = PIXEL(255, 85, 255, 255), 100 [COLOR_WHITE | COLOR_BRIGHT] = PIXEL(255, 255, 255, 255), 101 }; 74 102 75 103 static errno_t term_open(con_srvs_t *, con_srv_t *); … … 119 147 static void terminal_close_event(ui_window_t *, void *); 120 148 static void terminal_focus_event(ui_window_t *, void *, unsigned); 149 static void terminal_resize_event(ui_window_t *, void *); 121 150 static void terminal_kbd_event(ui_window_t *, void *, kbd_event_t *); 122 151 static void terminal_pos_event(ui_window_t *, void *, pos_event_t *); 123 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 *); 124 155 125 156 static ui_window_cb_t terminal_window_cb = { 126 157 .close = terminal_close_event, 127 158 .focus = terminal_focus_event, 159 .resize = terminal_resize_event, 128 160 .kbd = terminal_kbd_event, 129 161 .pos = terminal_pos_event, 130 .unfocus = terminal_unfocus_event 162 .unfocus = terminal_unfocus_event, 163 .maximize = terminal_maximize_event, 164 .unmaximize = terminal_unmaximize_event, 131 165 }; 132 166 … … 144 178 } 145 179 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) { 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) { 169 199 case CHAR_ATTR_STYLE: 170 switch ( attrs.val.style) {200 switch (cf->attrs.val.style) { 171 201 case STYLE_NORMAL: 172 *bgcolor = color_table[COLOR_WHITE + 8];173 *fgcolor = color_table[COLOR_BLACK];202 cell.bgcolor = term->default_bgcolor; 203 cell.fgcolor = term->default_fgcolor; 174 204 break; 175 205 case STYLE_EMPHASIS: 176 *bgcolor = color_table[COLOR_WHITE + 8];177 *fgcolor = color_table[COLOR_RED + 8];206 cell.bgcolor = term->emphasis_bgcolor; 207 cell.fgcolor = term->emphasis_fgcolor; 178 208 break; 179 209 case STYLE_INVERTED: 180 *bgcolor = color_table[COLOR_BLACK]; 181 *fgcolor = color_table[COLOR_WHITE + 8]; 210 cell.bgcolor = term->default_bgcolor; 211 cell.fgcolor = term->default_fgcolor; 212 cell.inverted = 1; 182 213 break; 183 214 case STYLE_SELECTED: 184 *bgcolor = color_table[COLOR_RED + 8];185 *fgcolor = color_table[COLOR_WHITE + 8];215 cell.bgcolor = term->selection_bgcolor; 216 cell.fgcolor = term->selection_fgcolor; 186 217 break; 187 218 } 188 219 break; 220 189 221 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)]; 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 193 233 break; 234 194 235 case CHAR_ATTR_RGB: 195 *bgcolor = 0xff000000 | attrs.val.rgb.bgcolor;196 *fgcolor = 0xff000000 | attrs.val.rgb.fgcolor;236 cell.bgcolor = termui_color_from_pixel(cf->attrs.val.rgb.bgcolor); 237 cell.fgcolor = termui_color_from_pixel(cf->attrs.val.rgb.fgcolor); 197 238 break; 198 239 } 240 241 return cell; 199 242 } 200 243 … … 214 257 } 215 258 216 static void term_update_char(terminal_t *term, pixelmap_t *pixelmap, 217 sysarg_t sx, sysarg_t sy, 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 = sx + (col * FONT_WIDTH); 225 sysarg_t by = sy + (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); 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); 239 288 240 289 for (unsigned int y = 0; y < FONT_SCANLINES; y++) { … … 248 297 } 249 298 } 299 250 300 term_update_region(term, bx, by, FONT_WIDTH, FONT_SCANLINES); 251 301 } 252 302 253 static bool term_update_scroll(terminal_t *term, pixelmap_t *pixelmap, 254 sysarg_t sx, sysarg_t sy) 255 { 256 sysarg_t top_row = chargrid_get_top_row(term->frontbuf); 257 258 if (term->top_row == top_row) { 259 return false; 260 } 261 262 term->top_row = top_row; 263 264 for (sysarg_t row = 0; row < term->rows; row++) { 265 for (sysarg_t col = 0; col < term->cols; col++) { 266 charfield_t *front_field = 267 chargrid_charfield_at(term->frontbuf, col, row); 268 charfield_t *back_field = 269 chargrid_charfield_at(term->backbuf, col, row); 270 bool update = false; 271 272 if (front_field->ch != back_field->ch) { 273 back_field->ch = front_field->ch; 274 update = true; 275 } 276 277 if (!attrs_same(front_field->attrs, back_field->attrs)) { 278 back_field->attrs = front_field->attrs; 279 update = true; 280 } 281 282 front_field->flags &= ~CHAR_FLAG_DIRTY; 283 284 if (update) { 285 term_update_char(term, pixelmap, sx, sy, col, row); 286 } 287 } 288 } 289 290 return true; 291 } 292 293 static bool term_update_cursor(terminal_t *term, pixelmap_t *pixelmap, 294 sysarg_t sx, sysarg_t sy) 295 { 296 bool update = false; 297 298 sysarg_t front_col; 299 sysarg_t front_row; 300 chargrid_get_cursor(term->frontbuf, &front_col, &front_row); 301 302 sysarg_t back_col; 303 sysarg_t back_row; 304 chargrid_get_cursor(term->backbuf, &back_col, &back_row); 305 306 bool front_visibility = 307 chargrid_get_cursor_visibility(term->frontbuf) && 308 term->is_focused; 309 bool back_visibility = 310 chargrid_get_cursor_visibility(term->backbuf); 311 312 if (front_visibility != back_visibility) { 313 chargrid_set_cursor_visibility(term->backbuf, 314 front_visibility); 315 term_update_char(term, pixelmap, sx, sy, back_col, back_row); 316 update = true; 317 } 318 319 if ((front_col != back_col) || (front_row != back_row)) { 320 chargrid_set_cursor(term->backbuf, front_col, front_row); 321 term_update_char(term, pixelmap, sx, sy, back_col, back_row); 322 term_update_char(term, pixelmap, sx, sy, front_col, front_row); 323 update = true; 324 } 325 326 return update; 327 } 328 329 static void term_update(terminal_t *term) 330 { 331 pixelmap_t pixelmap; 303 static void term_render(terminal_t *term) 304 { 305 (void) gfx_bitmap_render(term->bmp, &term->update, &term->off); 306 307 term->update.p0.x = 0; 308 term->update.p0.y = 0; 309 term->update.p1.x = 0; 310 term->update.p1.y = 0; 311 } 312 313 static void termui_refresh_cb(void *userdata) 314 { 315 terminal_t *term = userdata; 316 317 termui_force_viewport_update(term->termui, 0, termui_get_rows(term->termui)); 318 } 319 320 static void termui_scroll_cb(void *userdata, int delta) 321 { 322 (void) delta; 323 324 // Until we have support for hardware accelerated scrolling, just redraw everything. 325 termui_refresh_cb(userdata); 326 } 327 328 static pixelmap_t term_get_pixelmap(terminal_t *term) 329 { 330 pixelmap_t pixelmap = { }; 332 331 gfx_bitmap_alloc_t alloc; 333 gfx_coord2_t pos; 334 errno_t rc; 335 336 rc = gfx_bitmap_get_alloc(term->bmp, &alloc); 337 if (rc != EOK) { 338 return; 339 } 340 341 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 342 337 pixelmap.width = term->w; 343 338 pixelmap.height = term->h; 344 339 pixelmap.data = alloc.pixels; 345 346 bool update = false; 347 sysarg_t sx = 0; 348 sysarg_t sy = 0; 349 350 if (term_update_scroll(term, &pixelmap, sx, sy)) { 351 update = true; 352 } else { 353 for (sysarg_t y = 0; y < term->rows; y++) { 354 for (sysarg_t x = 0; x < term->cols; x++) { 355 charfield_t *front_field = 356 chargrid_charfield_at(term->frontbuf, x, y); 357 charfield_t *back_field = 358 chargrid_charfield_at(term->backbuf, x, y); 359 bool cupdate = false; 360 361 if ((front_field->flags & CHAR_FLAG_DIRTY) == 362 CHAR_FLAG_DIRTY) { 363 if (front_field->ch != back_field->ch) { 364 back_field->ch = front_field->ch; 365 cupdate = true; 366 } 367 368 if (!attrs_same(front_field->attrs, 369 back_field->attrs)) { 370 back_field->attrs = front_field->attrs; 371 cupdate = true; 372 } 373 374 front_field->flags &= ~CHAR_FLAG_DIRTY; 375 } 376 377 if (cupdate) { 378 term_update_char(term, &pixelmap, sx, sy, x, y); 379 update = true; 380 } 381 } 382 } 383 } 384 385 if (term_update_cursor(term, &pixelmap, sx, sy)) 386 update = true; 387 388 if (update) { 389 pos.x = 4; 390 pos.y = 26; 391 (void) gfx_bitmap_render(term->bmp, &term->update, &pos); 392 393 term->update.p0.x = 0; 394 term->update.p0.y = 0; 395 term->update.p1.x = 0; 396 term->update.p1.y = 0; 397 } 398 399 fibril_mutex_unlock(&term->mtx); 400 } 401 402 static void term_repaint(terminal_t *term) 403 { 404 pixelmap_t pixelmap; 405 gfx_bitmap_alloc_t alloc; 406 errno_t rc; 407 408 rc = gfx_bitmap_get_alloc(term->bmp, &alloc); 409 if (rc != EOK) { 410 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) 411 347 return; 412 } 413 414 fibril_mutex_lock(&term->mtx); 415 416 pixelmap.width = term->w; 417 pixelmap.height = term->h; 418 pixelmap.data = alloc.pixels; 419 420 sysarg_t sx = 0; 421 sysarg_t sy = 0; 422 423 if (!term_update_scroll(term, &pixelmap, sx, sy)) { 424 for (sysarg_t y = 0; y < term->rows; y++) { 425 for (sysarg_t x = 0; x < term->cols; x++) { 426 charfield_t *front_field = 427 chargrid_charfield_at(term->frontbuf, x, y); 428 charfield_t *back_field = 429 chargrid_charfield_at(term->backbuf, x, y); 430 431 back_field->ch = front_field->ch; 432 back_field->attrs = front_field->attrs; 433 front_field->flags &= ~CHAR_FLAG_DIRTY; 434 435 term_update_char(term, &pixelmap, sx, sy, x, y); 436 } 437 } 438 } 439 440 term_update_cursor(term, &pixelmap, sx, sy); 441 442 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]); 443 366 } 444 367 … … 480 403 if (pos < size) { 481 404 link_t *link = prodcons_consume(&term->input_pc); 482 cons_event_t *event = list_get_instance(link, cons_event_t, link); 405 terminal_event_t *qevent = list_get_instance(link, 406 terminal_event_t, link); 407 cons_event_t *event = &qevent->ev; 483 408 484 409 /* Accept key presses of printable chars only. */ … … 494 419 } 495 420 496 free( event);421 free(qevent); 497 422 } 498 423 } … … 504 429 static void term_write_char(terminal_t *term, wchar_t ch) 505 430 { 506 sysarg_t updated = 0;507 508 fibril_mutex_lock(&term->mtx);509 510 431 switch (ch) { 511 case '\n':512 updated = chargrid_newline(term->frontbuf);432 case L'\n': 433 termui_put_crlf(term->termui); 513 434 break; 514 case '\r': 435 case L'\r': 436 termui_put_cr(term->termui); 515 437 break; 516 case '\t':517 updated = chargrid_tabstop(term->frontbuf, 8);438 case L'\t': 439 termui_put_tab(term->termui); 518 440 break; 519 case '\b':520 updated = chargrid_backspace(term->frontbuf);441 case L'\b': 442 termui_put_backspace(term->termui); 521 443 break; 522 444 default: 523 updated = chargrid_putuchar(term->frontbuf, ch, true); 524 } 525 526 fibril_mutex_unlock(&term->mtx); 527 528 if (updated > 1) 529 term_update(term); 445 // TODO: For some languages, we might need support for combining 446 // characters. Currently, we assume every unicode code point is 447 // an individual printed character, which is not always the case. 448 termui_put_glyph(term->termui, fb_font_glyph(ch, NULL), 1); 449 break; 450 } 530 451 } 531 452 … … 533 454 { 534 455 terminal_t *term = srv_to_terminal(srv); 456 457 fibril_mutex_lock(&term->mtx); 535 458 536 459 size_t off = 0; … … 538 461 term_write_char(term, str_decode(data, &off, size)); 539 462 463 fibril_mutex_unlock(&term->mtx); 464 465 term_render(term); 540 466 gfx_update(term->gc); 541 467 *nwritten = size; 468 542 469 return EOK; 543 470 } … … 547 474 terminal_t *term = srv_to_terminal(srv); 548 475 549 term_ update(term);476 term_render(term); 550 477 gfx_update(term->gc); 551 478 } … … 556 483 557 484 fibril_mutex_lock(&term->mtx); 558 chargrid_clear(term->frontbuf);559 fibril_mutex_unlock(&term->mtx); 560 561 term_ update(term);485 termui_clear_screen(term->termui); 486 fibril_mutex_unlock(&term->mtx); 487 488 term_render(term); 562 489 gfx_update(term->gc); 563 490 } … … 568 495 569 496 fibril_mutex_lock(&term->mtx); 570 chargrid_set_cursor(term->frontbuf, col, row);571 fibril_mutex_unlock(&term->mtx); 572 573 term_ update(term);497 termui_set_pos(term->termui, col, row); 498 fibril_mutex_unlock(&term->mtx); 499 500 term_render(term); 574 501 gfx_update(term->gc); 575 502 } … … 580 507 581 508 fibril_mutex_lock(&term->mtx); 582 chargrid_get_cursor(term->frontbuf, col, row); 583 fibril_mutex_unlock(&term->mtx); 509 int irow, icol; 510 termui_get_pos(term->termui, &icol, &irow); 511 fibril_mutex_unlock(&term->mtx); 512 513 *col = icol; 514 *row = irow; 584 515 585 516 return EOK; … … 591 522 592 523 fibril_mutex_lock(&term->mtx); 593 *cols = term ->cols;594 *rows = term ->rows;524 *cols = termui_get_cols(term->termui); 525 *rows = termui_get_rows(term->termui); 595 526 fibril_mutex_unlock(&term->mtx); 596 527 … … 610 541 terminal_t *term = srv_to_terminal(srv); 611 542 612 fibril_mutex_lock(&term->mtx); 613 chargrid_set_style(term->frontbuf, style); 543 termui_cell_t cellstyle = { }; 544 545 switch (style) { 546 case STYLE_NORMAL: 547 cellstyle.bgcolor = term->default_bgcolor; 548 cellstyle.fgcolor = term->default_fgcolor; 549 break; 550 case STYLE_EMPHASIS: 551 cellstyle.bgcolor = term->emphasis_bgcolor; 552 cellstyle.fgcolor = term->emphasis_fgcolor; 553 break; 554 case STYLE_INVERTED: 555 cellstyle.bgcolor = term->default_bgcolor; 556 cellstyle.fgcolor = term->default_fgcolor; 557 cellstyle.inverted = 1; 558 break; 559 case STYLE_SELECTED: 560 cellstyle.bgcolor = term->selection_bgcolor; 561 cellstyle.fgcolor = term->selection_fgcolor; 562 break; 563 } 564 565 fibril_mutex_lock(&term->mtx); 566 termui_set_style(term->termui, cellstyle); 614 567 fibril_mutex_unlock(&term->mtx); 615 568 } … … 620 573 terminal_t *term = srv_to_terminal(srv); 621 574 622 fibril_mutex_lock(&term->mtx); 623 chargrid_set_color(term->frontbuf, bgcolor, fgcolor, attr); 575 int bright = (attr & CATTR_BRIGHT) ? COLOR_BRIGHT : 0; 576 577 termui_cell_t cellstyle = { }; 578 cellstyle.bgcolor = termui_color_from_pixel(_basic_colors[bgcolor]); 579 cellstyle.fgcolor = termui_color_from_pixel(_basic_colors[fgcolor | bright]); 580 581 if (attr & CATTR_BLINK) 582 cellstyle.blink = 1; 583 584 fibril_mutex_lock(&term->mtx); 585 termui_set_style(term->termui, cellstyle); 624 586 fibril_mutex_unlock(&term->mtx); 625 587 } … … 629 591 { 630 592 terminal_t *term = srv_to_terminal(srv); 631 632 fibril_mutex_lock(&term->mtx); 633 chargrid_set_rgb_color(term->frontbuf, bgcolor, fgcolor); 593 termui_cell_t cellstyle = { 594 .bgcolor = termui_color_from_pixel(bgcolor), 595 .fgcolor = termui_color_from_pixel(fgcolor), 596 }; 597 598 fibril_mutex_lock(&term->mtx); 599 termui_set_style(term->termui, cellstyle); 634 600 fibril_mutex_unlock(&term->mtx); 635 601 } … … 640 606 641 607 fibril_mutex_lock(&term->mtx); 642 chargrid_set_cursor_visibility(term->frontbuf, visible);643 fibril_mutex_unlock(&term->mtx); 644 645 term_ update(term);608 termui_set_cursor_visibility(term->termui, visible); 609 fibril_mutex_unlock(&term->mtx); 610 611 term_render(term); 646 612 gfx_update(term->gc); 647 613 } … … 662 628 fibril_mutex_unlock(&term->mtx); 663 629 664 term_ update(term);630 term_render(term); 665 631 gfx_update(term->gc); 666 632 return EOK; … … 671 637 terminal_t *term = srv_to_terminal(srv); 672 638 link_t *link = prodcons_consume(&term->input_pc); 673 cons_event_t *ev = list_get_instance(link, cons_event_t, link);674 675 *event = *ev;639 terminal_event_t *ev = list_get_instance(link, terminal_event_t, link); 640 641 *event = ev->ev; 676 642 free(ev); 677 643 return EOK; … … 710 676 term->urows = rows; 711 677 term->ubuf = buf; 678 679 /* Scroll back to active screen. */ 680 termui_history_scroll(term->termui, INT_MAX); 681 712 682 fibril_mutex_unlock(&term->mtx); 713 683 … … 730 700 term->ubuf = NULL; 731 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 732 710 if (buf != NULL) 733 711 as_area_destroy(buf); 734 735 fibril_mutex_unlock(&term->mtx);736 712 } 737 713 … … 748 724 { 749 725 terminal_t *term = srv_to_terminal(srv); 750 charfield_t *ch;751 sysarg_t col, row;752 726 753 727 fibril_mutex_lock(&term->mtx); … … 759 733 760 734 /* Make sure we have meaningful coordinates, within bounds */ 761 762 if (c1 > term->ucols)763 c1 = term->ucols;764 if (c1 > term->cols)765 c1 = term->cols; 766 if (c0 >= c1 ) {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) { 767 741 fibril_mutex_unlock(&term->mtx); 768 742 return; 769 743 } 770 if (r1 > term->urows)771 r1 = term->urows;772 if (r1 > term->rows)773 r1 = term->rows;774 if (r0 >= r1) {775 fibril_mutex_unlock(&term->mtx);776 return;777 }778 744 779 745 /* Update front buffer from user buffer */ 780 746 781 for (row = r0; row < r1; row++) { 782 for (col = c0; col < c1; col++) { 783 ch = chargrid_charfield_at(term->frontbuf, col, row); 784 *ch = term->ubuf[row * term->ucols + col]; 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]); 785 752 } 753 754 termui_update_cb(term, c0, row, &cells[c0], c1 - c0); 786 755 } 787 756 … … 789 758 790 759 /* Update terminal */ 791 term_ update(term);760 term_render(term); 792 761 gfx_update(term->gc); 793 762 } 794 763 795 static void deinit_terminal(terminal_t *term) 764 static errno_t terminal_window_resize(terminal_t *term) 765 { 766 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; 784 gfx_bitmap_params_init(¶ms); 785 params.rect.p0.x = 0; 786 params.rect.p0.y = 0; 787 params.rect.p1.x = width; 788 params.rect.p1.y = height; 789 790 errno_t rc = gfx_bitmap_create(term->gc, ¶ms, NULL, &new_bmp); 791 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) 796 812 { 797 813 list_remove(&term->link); 798 814 799 if (term->frontbuf) 800 chargrid_destroy(term->frontbuf); 801 802 if (term->backbuf) 803 chargrid_destroy(term->backbuf); 804 } 805 806 void terminal_destroy(terminal_t *term) 807 { 808 deinit_terminal(term); 815 termui_destroy(term->termui); 816 817 if (term->ubuf) 818 as_area_destroy(term->ubuf); 819 820 ui_destroy(term->ui); 809 821 free(term); 810 822 } … … 813 825 { 814 826 /* Got key press/release event */ 815 cons_event_t *event =816 ( cons_event_t *) malloc(sizeof(cons_event_t));827 terminal_event_t *event = 828 (terminal_event_t *) malloc(sizeof(terminal_event_t)); 817 829 if (event == NULL) 818 830 return; 819 831 820 *event= *ev;832 event->ev = *ev; 821 833 link_initialize(&event->link); 822 834 … … 840 852 (void)nfocus; 841 853 term->is_focused = true; 842 term_ update(term);854 term_render(term); 843 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); 844 894 } 845 895 … … 854 904 event.ev.key = *kbd_event; 855 905 856 terminal_queue_cons_event(term, &event); 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); 857 923 } 858 924 … … 863 929 terminal_t *term = (terminal_t *) arg; 864 930 865 sysarg_t sx = -term->off.x; 866 sysarg_t sy = -term->off.y; 867 868 if (event->type == POS_PRESS || event->type == POS_RELEASE || 869 event->type == POS_DCLICK) { 870 cevent.type = CEV_POS; 871 cevent.ev.pos.type = event->type; 872 cevent.ev.pos.pos_id = event->pos_id; 873 cevent.ev.pos.btn_num = event->btn_num; 874 875 cevent.ev.pos.hpos = (event->hpos - sx) / FONT_WIDTH; 876 cevent.ev.pos.vpos = (event->vpos - sy) / FONT_SCANLINES; 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) 877 963 terminal_queue_cons_event(term, &cevent); 878 }879 964 } 880 965 … … 887 972 if (nfocus == 0) { 888 973 term->is_focused = false; 889 term_ update(term);974 term_render(term); 890 975 gfx_update(term->gc); 891 976 } … … 909 994 910 995 if (!atomic_flag_test_and_set(&term->refcnt)) 911 chargrid_set_cursor_visibility(term->frontbuf, true);996 termui_set_cursor_visibility(term->termui, true); 912 997 913 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); 914 1052 } 915 1053 … … 918 1056 terminal_t **rterm) 919 1057 { 920 terminal_t *term;921 gfx_bitmap_params_t params;922 ui_wnd_params_t wparams;923 gfx_rect_t rect;924 gfx_coord2_t off;925 gfx_rect_t wrect;926 1058 errno_t rc; 927 1059 928 term = calloc(1, sizeof(terminal_t));1060 terminal_t *term = calloc(1, sizeof(terminal_t)); 929 1061 if (term == NULL) { 930 1062 printf("Out of memory.\n"); … … 939 1071 term->char_remains_len = 0; 940 1072 941 term->w = width; 942 term->h = height; 943 944 term->cols = width / FONT_WIDTH; 945 term->rows = height / FONT_SCANLINES; 946 947 term->frontbuf = NULL; 948 term->backbuf = NULL; 949 950 term->frontbuf = chargrid_create(term->cols, term->rows, 951 CHARGRID_FLAG_NONE); 952 if (!term->frontbuf) { 953 printf("Error creating front buffer.\n"); 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)); 1086 goto error; 1087 } 1088 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"); 954 1093 rc = ENOMEM; 955 1094 goto error; 956 1095 } 957 1096 958 term->backbuf = chargrid_create(term->cols, term->rows, 959 CHARGRID_FLAG_NONE); 960 if (!term->backbuf) { 961 printf("Error creating back buffer.\n"); 962 rc = ENOMEM; 963 goto error; 964 } 965 966 rect.p0.x = 0; 967 rect.p0.y = 0; 968 rect.p1.x = width; 969 rect.p1.y = height; 970 971 ui_wnd_params_init(&wparams); 972 wparams.caption = "Terminal"; 973 if ((flags & tf_topleft) != 0) 974 wparams.placement = ui_wnd_place_top_left; 975 976 rc = ui_create(display_spec, &term->ui); 977 if (rc != EOK) { 978 printf("Error creating UI on %s.\n", display_spec); 979 goto error; 980 } 981 982 /* 983 * Compute window rectangle such that application area corresponds 984 * to rect 985 */ 986 ui_wdecor_rect_from_app(term->ui, wparams.style, &rect, &wrect); 987 off = wrect.p0; 988 gfx_rect_rtranslate(&off, &wrect, &wparams.rect); 989 990 term->off = off; 991 992 rc = ui_window_create(term->ui, &wparams, &term->window); 993 if (rc != EOK) { 994 printf("Error creating window.\n"); 995 goto error; 996 } 997 998 term->gc = ui_window_get_gc(term->window); 999 term->ui_res = ui_window_get_res(term->window); 1000 1001 ui_window_set_cb(term->window, &terminal_window_cb, (void *) term); 1002 1003 gfx_bitmap_params_init(¶ms); 1004 params.rect.p0.x = 0; 1005 params.rect.p0.y = 0; 1006 params.rect.p1.x = width; 1007 params.rect.p1.y = height; 1008 1009 rc = gfx_bitmap_create(term->gc, ¶ms, NULL, &term->bmp); 1010 if (rc != EOK) { 1011 printf("Error allocating screen bitmap.\n"); 1012 goto error; 1013 } 1014 1015 chargrid_clear(term->frontbuf); 1016 chargrid_clear(term->backbuf); 1017 term->top_row = 0; 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); 1018 1100 1019 1101 async_set_fallback_port_handler(term_connection, NULL); … … 1053 1135 term->is_focused = true; 1054 1136 1055 term->update.p0.x = 0; 1056 term->update.p0.y = 0; 1057 term->update.p1.x = 0; 1058 term->update.p1.y = 0; 1059 1060 term_repaint(term); 1137 termui_refresh_cb(term); 1061 1138 1062 1139 *rterm = term; … … 1071 1148 if (term->ui != NULL) 1072 1149 ui_destroy(term->ui); 1073 if (term->frontbuf != NULL) 1074 chargrid_destroy(term->frontbuf); 1075 if (term->backbuf != NULL) 1076 chargrid_destroy(term->backbuf); 1150 if (term->termui != NULL) 1151 termui_destroy(term->termui); 1077 1152 free(term); 1078 1153 return rc;
Note:
See TracChangeset
for help on using the changeset viewer.