X-Git-Url: https://git.proxmox.com/?p=vncterm.git;a=blobdiff_plain;f=vncterm.c;h=ff24953b8e6780ba24cc1a8489a7fb40de4bd820;hp=0614e4b2df9531d169f2d90cfc6d636ae1654bb8;hb=be9be7468af1a04fd48bf93311b807a6a3727ca2;hpb=b26ab9ab5a50f91381a2d8b8fe99c896a053a343 diff --git a/vncterm.c b/vncterm.c index 0614e4b..ff24953 100644 --- a/vncterm.c +++ b/vncterm.c @@ -26,6 +26,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -39,7 +42,6 @@ #include #include "vncterm.h" -#include "glyphs.h" #include #include @@ -50,8 +52,17 @@ char *auth_path = "/"; char *auth_perm = "Sys.Console"; +uint16_t screen_width = 744; +uint16_t screen_height = 400; + int use_x509 = 1; +extern int wcwidth (wchar_t wc); +unsigned char *fontdata; + +#define FONTFILE "/usr/share/vncterm/font.data" +#define GLYPHLINES 16 + static char * urlencode(char *buf, const char *value) { @@ -494,42 +505,10 @@ rfbVncAuthVencrypt(rfbClientPtr cl) return; } - /* optimize for speed */ - static const int cipher_priority_performance[] = { - GNUTLS_CIPHER_ARCFOUR_128, - GNUTLS_CIPHER_AES_128_CBC, - GNUTLS_CIPHER_3DES_CBC, 0 - }; - - if ((ret = gnutls_cipher_set_priority(sd->session, cipher_priority_performance)) < 0) { - rfbLog("gnutls_cipher_set_priority failed: %s\n", gnutls_strerror(ret)); - sd->session = NULL; - rfbCloseClient(cl); - return; - } - - static const int kx_anon[] = {GNUTLS_KX_ANON_DH, 0}; - static const int kx_x509[] = {GNUTLS_KX_DHE_DSS, GNUTLS_KX_RSA, GNUTLS_KX_DHE_RSA, GNUTLS_KX_SRP, 0}; - if ((ret = gnutls_kx_set_priority(sd->session, use_x509 ? kx_x509 : kx_anon)) < 0) { - rfbLog("gnutls_kx_set_priority failed: %s\n", gnutls_strerror(ret)); - sd->session = NULL; - rfbCloseClient(cl); - return; - } - - static const int cert_type_priority[] = { GNUTLS_CRT_X509, 0 }; - if ((ret = gnutls_certificate_type_set_priority(sd->session, cert_type_priority)) < 0) { - rfbLog("gnutls_certificate_type_set_priority failed: %s\n", - gnutls_strerror(ret)); - sd->session = NULL; - rfbCloseClient(cl); - return; - } - - static const int protocol_priority[]= { GNUTLS_TLS1_1, GNUTLS_TLS1_0, GNUTLS_SSL3, 0 }; - if ((ret = gnutls_protocol_set_priority(sd->session, protocol_priority)) < 0) { - rfbLog("gnutls_protocol_set_priority failed: %s\n", - gnutls_strerror(ret)); + static const char *priority_str_x509 = "NORMAL"; + static const char *priority_str_anon = "NORMAL:+ANON-ECDH:+ANON-DH"; + if ((ret = gnutls_priority_set_direct(sd->session, use_x509 ? priority_str_x509 : priority_str_anon, NULL)) < 0) { + rfbLog("gnutls_priority_set_direct failed: %s\n", gnutls_strerror(ret)); sd->session = NULL; rfbCloseClient(cl); return; @@ -658,21 +637,16 @@ ucs2_to_utf8 (unicode c, char *out) static void rfb_draw_char (rfbScreenInfoPtr rfbScreen, int x, int y, - unsigned short c, rfbPixel col) + unicode c, rfbPixel col, short width) { - if (c > vt_font_size) { - rfbLog ("undefined font glyph %d\n", c); - return; - } - int i,j; - unsigned char *data= vt_font_data + c*16; + unsigned char *data= fontdata + c*(GLYPHLINES*2); unsigned char d=*data; int rowstride=rfbScreen->paddedWidthInBytes; char *colour=(char*)&col; - for(j = 0; j < 16; j++) { - for(i = 0; i < 8; i++) { + for(j = 0; j < GLYPHLINES; j++) { + for(i = 0; i < 8*width; i++) { if ((i&7) == 0) { d=*data; data++; @@ -685,13 +659,16 @@ rfb_draw_char (rfbScreenInfoPtr rfbScreen, int x, int y, } static void -draw_char_at (vncTerm *vt, int x, int y, unicode ch, TextAttributes attrib) +draw_char_at (vncTerm *vt, int x, int y, unicode ch, TextAttributes attrib, short width, unicode combiningglyph) { if (x < 0 || y < 0 || x >= vt->width || y >= vt->height) { return; } + // non printable character + if (width < 1) return; + int rx = x*8; int ry = y*16; - int rxe = x*8+8; + int rxe = x*8+8*width; int rye = y*16+16; int fg, bg; @@ -704,8 +681,6 @@ draw_char_at (vncTerm *vt, int x, int y, unicode ch, TextAttributes attrib) fg = attrib.fgcol; } - int ec = vt_fontmap[ch]; - rfbFillRect (vt->screen, rx, ry, rxe, rye, bg); if (attrib.bold) { @@ -714,7 +689,11 @@ draw_char_at (vncTerm *vt, int x, int y, unicode ch, TextAttributes attrib) // unsuported attributes = (attrib.blink || attrib.unvisible) - rfb_draw_char (vt->screen, rx, ry, ec, fg); + rfb_draw_char (vt->screen, rx, ry, ch, fg, width); + + if (combiningglyph) { + rfb_draw_char (vt->screen, rx, ry, combiningglyph, fg, 1); + } if (attrib.uline) { rfbDrawLine (vt->screen, rx, ry + 14, rxe, ry + 14, fg); @@ -736,7 +715,7 @@ vncterm_update_xy (vncTerm *vt, int x, int y) } if (y2 < vt->height) { TextCell *c = &vt->cells[y1 * vt->width + x]; - draw_char_at (vt, x, y2, c->ch, c->attrib); + draw_char_at (vt, x, y2, c->ch, c->attrib, c->width, c->combiningglyph); } } @@ -756,8 +735,10 @@ vncterm_clear_xy (vncTerm *vt, int x, int y) c->attrib = vt->default_attrib; c->attrib.fgcol = vt->cur_attrib.fgcol; c->attrib.bgcol = vt->cur_attrib.bgcol; + c->width = 1; + c->combiningglyph = 0; - draw_char_at (vt, x, y, c->ch, c->attrib); + draw_char_at (vt, x, y, c->ch, c->attrib, c->width, c->combiningglyph); } } @@ -782,9 +763,9 @@ vncterm_show_cursor (vncTerm *vt, int show) if (show) { TextAttributes attrib = vt->default_attrib; attrib.invers = !(attrib.invers); /* invert fg and bg */ - draw_char_at (vt, x, y, c->ch, attrib); + draw_char_at (vt, x, y, c->ch, attrib, c->width, c->combiningglyph); } else { - draw_char_at (vt, x, y, c->ch, c->attrib); + draw_char_at (vt, x, y, c->ch, c->attrib, c->width, c->combiningglyph); } } } @@ -800,8 +781,8 @@ vncterm_refresh (vncTerm *vt) for(y = 0; y < vt->height; y++) { TextCell *c = vt->cells + y1 * vt->width; for(x = 0; x < vt->width; x++) { - draw_char_at (vt, x, y, c->ch, c->attrib); - c++; + draw_char_at (vt, x, y, c->ch, c->attrib, c->width, c->combiningglyph); + c += c->width; } if (++y1 == vt->total_height) y1 = 0; @@ -850,6 +831,8 @@ vncterm_scroll_down (vncTerm *vt, int top, int bottom, int lines) for(j = 0; j < vt->width; j++) { c->attrib = vt->default_attrib; c->ch = ' '; + c->width = 1; + c->combiningglyph = 0; c++; } } @@ -899,6 +882,8 @@ vncterm_scroll_up (vncTerm *vt, int top, int bottom, int lines, int moveattr) for(j = 0; j < vt->width; j++) { c->attrib = vt->default_attrib; c->ch = ' '; + c->width = 1; + c->combiningglyph = 0; c++; } } @@ -983,6 +968,8 @@ vncterm_put_lf (vncTerm *vt) int x; for (x = 0; x < vt->width; x++) { c->ch = ' '; + c->width = 1; + c->combiningglyph = 0; c->attrib = vt->default_attrib; c++; } @@ -1205,9 +1192,7 @@ vncterm_gotoxy (vncTerm *vt, int x, int y) if (x < 0) { x = 0; - } - - if (x >= vt->width) { + } else if (x >= vt->width) { x = vt->width - 1; } @@ -1215,9 +1200,7 @@ vncterm_gotoxy (vncTerm *vt, int x, int y) if (y < 0) { y = 0; - } - - if (y >= vt->height) { + } else if (y >= vt->height) { y = vt->height - 1; } @@ -1386,6 +1369,7 @@ vncterm_putchar (vncTerm *vt, unicode ch) } break; } else if (ch == ';') { + vt->esc_has_par = 1; vt->esc_count++; break; } else { @@ -1436,10 +1420,7 @@ vncterm_putchar (vncTerm *vt, unicode ch) if (vt->esc_buf[0] == 0) { vt->esc_buf[0] = 1; } - vt->cy -= vt->esc_buf[0]; - if (vt->cy < 0) { - vt->cy = 0; - } + vncterm_gotoxy (vt, vt->cx, vt->cy - vt->esc_buf[0]); break; case 'B': case 'e': @@ -1447,10 +1428,7 @@ vncterm_putchar (vncTerm *vt, unicode ch) if (vt->esc_buf[0] == 0) { vt->esc_buf[0] = 1; } - vt->cy += vt->esc_buf[0]; - if (vt->cy >= vt->height) { - vt->cy = vt->height - 1; - } + vncterm_gotoxy (vt, vt->cx, vt->cy + vt->esc_buf[0]); break; case 'C': case 'a': @@ -1458,20 +1436,14 @@ vncterm_putchar (vncTerm *vt, unicode ch) if (vt->esc_buf[0] == 0) { vt->esc_buf[0] = 1; } - vt->cx += vt->esc_buf[0]; - if (vt->cx >= vt->width) { - vt->cx = vt->width - 1; - } + vncterm_gotoxy (vt, vt->cx + vt->esc_buf[0], vt->cy); break; case 'D': /* move cursor left */ if (vt->esc_buf[0] == 0) { vt->esc_buf[0] = 1; } - vt->cx -= vt->esc_buf[0]; - if (vt->cx < 0) { - vt->cx = 0; - } + vncterm_gotoxy (vt, vt->cx - vt->esc_buf[0], vt->cy); break; case 'G': case '`': @@ -1593,6 +1565,8 @@ vncterm_putchar (vncTerm *vt, unicode ch) *dst = *src; vncterm_update_xy (vt, x + c, vt->cy); src->ch = ' '; + src->width = 1; + src->combiningglyph = 0; src->attrib = vt->default_attrib; vncterm_update_xy (vt, x, vt->cy); } @@ -1631,6 +1605,8 @@ vncterm_putchar (vncTerm *vt, unicode ch) *dst = *src; vncterm_update_xy (vt, x + c, vt->cy); src->ch = ' '; + src->width = 1; + src->combiningglyph = 0; src->attrib = vt->cur_attrib; vncterm_update_xy (vt, x, vt->cy); } @@ -1786,11 +1762,25 @@ vncterm_putchar (vncTerm *vt, unicode ch) } int y1 = (vt->y_base + vt->cy) % vt->total_height; - TextCell *c = &vt->cells[y1*vt->width + vt->cx]; - c->attrib = vt->cur_attrib; - c->ch = ch; - vncterm_update_xy (vt, vt->cx, vt->cy); - vt->cx++; + int width = wcwidth(ch); + if (width > 0) { + // normal/wide character + TextCell *c = &vt->cells[y1*vt->width + vt->cx]; + c->attrib = vt->cur_attrib; + c->ch = ch; + c->width = width; + c->combiningglyph = 0; + vncterm_update_xy (vt, vt->cx, vt->cy); + vt->cx += width; + } else if (width == 0) { + // combiningglyph + TextCell *c = &vt->cells[y1*vt->width + vt->cx - 1]; + c->attrib = vt->cur_attrib; + c->combiningglyph = ch; + vncterm_update_xy (vt, vt->cx - 1, vt->cy); + } else { + // non printable character, so we do not save them + } break; } break; @@ -1821,7 +1811,11 @@ vncterm_puts (vncTerm *vt, const char *buf, int len) vt->utf_char = (vt->utf_char << 6) | (c & 0x3f); vt->utf_count--; if (vt->utf_count == 0) { - tc = vt->utf_char; + if (vt->utf_char <= USHRT_MAX) { + tc = vt->utf_char; + } else { + tc = 0; + } } else { continue; } @@ -2207,6 +2201,63 @@ new_client (rfbClientPtr client) static char *vncticket = NULL; +static void +MakeRichCursor(rfbScreenInfoPtr rfbScreen) +{ + int w = 16, + h = 16; + rfbCursorPtr c = rfbScreen->cursor; + char bitmap[] = + " " + " x " + " xx " + " xxx " + " xxxx " + " xxxxx " + " xxxxxx " + " xxxxxxx " + " xxxxxxxx " + " xxxxxxxxx " + " xxxxxxxxxx " + " xxxx " + " xxx " + " xx " + " x " + " "; + char edge[] = + " " + " x " + " xx " + " x x " + " x x " + " x x " + " x x " + " x x " + " x x " + " x x " + " x xxxxxx " + " x x " + " x x " + " xx " + " x " + " "; + + c = rfbScreen->cursor = rfbMakeXCursor(w,h,bitmap,bitmap); + c->richSource = (unsigned char*)calloc(w*h, 1); + c->cleanupRichSource = TRUE; + + for(int j=0;jrichSource[pos] = 15; // white + } else { + c->richSource[pos] = 0; // black + } + } + } +} + vncTerm * create_vncterm (int argc, char** argv, int maxx, int maxy) { @@ -2214,6 +2265,7 @@ create_vncterm (int argc, char** argv, int maxx, int maxy) rfbScreenInfoPtr screen = rfbGetScreen (&argc, argv, maxx, maxy, 8, 1, 1); screen->frameBuffer=(char*)calloc(maxx*maxy, 1); + MakeRichCursor(screen); char **passwds = calloc(sizeof(char**), 2); @@ -2306,6 +2358,8 @@ main (int argc, char** argv) int i; char **cmdargv = NULL; char *command = "/bin/bash"; // execute normal shell as default + int fontfd; + struct stat sb; int pid; int master; char ptyname[1024]; @@ -2313,6 +2367,8 @@ main (int argc, char** argv) struct timeval tv, tv1; time_t elapsed, cur_time; struct winsize dimensions; + unsigned long width = 0; + unsigned long height = 0; if (gnutls_global_init () < 0) { fprintf(stderr, "gnutls_global_init failed\n"); @@ -2352,6 +2408,22 @@ main (int argc, char** argv) CHECK_ARGC (argc, argv, i); auth_perm = argv[i+1]; rfbPurgeArguments(&argc, &i, 2, argv); i--; + } else if (!strcmp (argv[i], "-width")) { + CHECK_ARGC (argc, argv, i); + errno = 0; + width = strtoul(argv[i+1], NULL, 10); + if (errno == 0 && width >= 16 && width < 0xFFFF) { + screen_width = width; + } + rfbPurgeArguments(&argc, &i, 2, argv); i--; + } else if (!strcmp (argv[i], "-height")) { + CHECK_ARGC (argc, argv, i); + errno = 0; + height = strtoul(argv[i+1], NULL, 10); + if (errno == 0 && height >= 32 && height < 0xFFFF) { + screen_height = height; + } + rfbPurgeArguments(&argc, &i, 2, argv); i--; } else if (!strcmp (argv[i], "-notls")) { rfbPurgeArguments(&argc, &i, 1, argv); i--; if ((vncticket = getenv("PVE_VNC_TICKET")) == NULL) { @@ -2371,7 +2443,24 @@ main (int argc, char** argv) rfbLogEnable (0); #endif - vncTerm *vt = create_vncterm (argc, argv, 745, 400); + // mmap font file + fontfd = open(FONTFILE, O_RDONLY); + if (fontfd == -1) { + perror("Error opening Fontfile 'FONTFILE'"); + exit (-1); + } + if (fstat(fontfd, &sb) == -1) { + perror("Stat on 'FONTFILE' failed"); + exit (-1); + } + fontdata = mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, fontfd, 0); + if (fontdata == MAP_FAILED) { + perror("Could not mmap 'FONTFILE'"); + exit (-1); + } + + close(fontfd); + vncTerm *vt = create_vncterm (argc, argv, screen_width, screen_height); setlocale(LC_ALL, ""); // set from environment @@ -2471,9 +2560,12 @@ main (int argc, char** argv) } } + rfbScreenCleanup(vt->screen); + kill (pid, 9); int status; waitpid(pid, &status, 0); + munmap(fontdata, sb.st_size); exit (0); }