From: Dietmar Maurer Date: Fri, 13 Sep 2013 07:53:24 +0000 (+0200) Subject: allow to select text regions X-Git-Url: https://git.proxmox.com/?p=spiceterm.git;a=commitdiff_plain;h=1d11aa1227692acd2f3871562e838c6f6ce0f3a0 allow to select text regions --- diff --git a/screen.c b/screen.c index 0646a3f..34ba4c6 100644 --- a/screen.c +++ b/screen.c @@ -634,11 +634,19 @@ QXLInterface display_sif = { void -spice_screen_draw_char(SpiceScreen *spice_screen, int x, int y, gunichar2 ch, TextAttributes attrib) +spice_screen_draw_char(SpiceScreen *spice_screen, int x, int y, gunichar2 ch, + TextAttributes attrib) { int fg, bg; + int invers; if (attrib.invers) { + invers = attrib.selected ? 0 : 1; + } else { + invers = attrib.selected ? 1 : 0; + } + + if (invers) { bg = attrib.fgcol; fg = attrib.bgcol; } else { diff --git a/spiceterm.c b/spiceterm.c index c3c7b7e..915b802 100644 --- a/spiceterm.c +++ b/spiceterm.c @@ -86,32 +86,6 @@ print_usage(const char *msg) fprintf(stderr, "USAGE: spiceterm [spiceopts] [-c command [args]]\n"); } -/* Convert UCS2 to UTF8 sequence, trailing zero */ -/* -static int -ucs2_to_utf8 (gunichar2 c, char *out) -{ - if (c < 0x80) { - out[0] = c; // 0******* - out[1] = 0; - return 1; - } else if (c < 0x800) { - out[0] = 0xc0 | (c >> 6); // 110***** 10****** - out[1] = 0x80 | (c & 0x3f); - out[2] = 0; - return 2; - } else { - out[0] = 0xe0 | (c >> 12); // 1110**** 10****** 10****** - out[1] = 0x80 | ((c >> 6) & 0x3f); - out[2] = 0x80 | (c & 0x3f); - out[3] = 0; - return 3; - } - - return 0; -} -*/ - static void draw_char_at (spiceTerm *vt, int x, int y, gunichar2 ch, TextAttributes attrib) { @@ -159,6 +133,26 @@ spiceterm_clear_xy (spiceTerm *vt, int x, int y) } } +void +spiceterm_toggle_marked_cell(spiceTerm *vt, int pos) +{ + int x = (pos%vt->width); + int y = (pos/vt->width); + + if (x < 0 || y < 0 || x >= vt->width || y >= vt->height) { return; } + + int y1 = (vt->y_base + y) % vt->total_height; + int y2 = y1 - vt->y_displ; + if (y2 < 0) { + y2 += vt->total_height; + } + if (y2 < vt->height) { + TextCell *c = &vt->cells[y1 * vt->width + x]; + c->attrib.selected = c->attrib.selected ? 0 : 1; + spice_screen_draw_char(vt->screen, x, y, c->ch, c->attrib); + } +} + static void spiceterm_show_cursor (spiceTerm *vt, int show) { @@ -1290,170 +1284,43 @@ mouse_report(spiceTerm *vt, int butt, int mrx, int mry) spiceterm_update_watch_mask(vt, TRUE); } -void -spiceterm_toggle_marked_cell (spiceTerm *vt, int pos) -{ - -/* fixme: - int x= (pos%vt->width)*8; - int y= (pos/vt->width)*16; - - int i,j; - rfbScreenInfoPtr s=vt->screen; - - char *b = s->frameBuffer+y*s->width+x; - - for (j=0; j < 16; j++) { - for(i=0; i < 8; i++) { - b[j*s->width+i] ^= 0x0f; - rfbMarkRectAsModified (s, x, y, x+8, y+16); - } - } -*/ -} - -/* fixme: - -void -spiceterm_pointer_event (int buttonMask, int x, int y, rfbClientPtr cl) +static void +spiceterm_respond_unichar2(spiceTerm *vt, gunichar2 uc) { - - spiceTerm *vt =(spiceTerm *)cl->screen->screenData; - static int button2_released = 1; - static int last_mask = 0; - static int sel_start_pos = 0; - static int sel_end_pos = 0; - int i; - - int cx = x/8; - int cy = y/16; - - if (cx < 0) cx = 0; - if (cx >= vt->width) cx = vt->width - 1; - if (cy < 0) cy = 0; - if (cy >= vt->height) cy = vt->height - 1; - - if (vt->report_mouse && buttonMask != last_mask) { - last_mask = buttonMask; - if (buttonMask & 1) { - mouse_report (vt, 0, cx, cy); - } - if (buttonMask & 2) { - mouse_report (vt, 1, cx, cy); - } - if (buttonMask & 4) { - mouse_report (vt, 2, cx, cy); - } - if (!buttonMask) { - mouse_report (vt, 3, cx, cy); - } - } - - if (buttonMask & 2) { - if(button2_released && vt->selection) { - int i; - for(i = 0; i < vt->selection_len; i++) { - if (vt->ibuf_count < IBUFSIZE - 6) { // uft8 is max 6 characters wide - if (vt->utf8) { - vt->ibuf_count += ucs2_to_utf8 (vt->selection[i], &vt->ibuf[vt->ibuf_count]); - } else { - vt->ibuf[vt->ibuf_count++] = vt->selection[i]; - } - } - } - if (vt->y_displ != vt->y_base) { - vt->y_displ = vt->y_base; - spiceterm_refresh (vt); - } - } - button2_released = 0; - } else { - button2_released = 1; - } - - if (buttonMask & 1) { - int pos = cy*vt->width + cx; - - // code borrowed from libvncserver (VNCconsole.c) - - if (!vt->mark_active) { - - vt->mark_active = 1; - sel_start_pos = sel_end_pos = pos; - spiceterm_toggle_marked_cell (vt, pos); - + if (vt->utf8) { + gchar buf[10]; + gint len = g_unichar_to_utf8(uc, buf); + + if (len > 0) { + if ((vt->ibuf_count + len) < IBUFSIZE) { + int i; + for (i = 0; i < len; i++) { + vt->ibuf[vt->ibuf_count++] = buf[i]; + } + } else { + fprintf(stderr, "warning: input buffer overflow\n"); + } + } } else { - - if (pos != sel_end_pos) { - - if (pos > sel_end_pos) { - cx = sel_end_pos; cy=pos; - } else { - cx=pos; cy=sel_end_pos; - } - - if (cx < sel_start_pos) { - if (cy < sel_start_pos) cy--; - } else { - cx++; - } - - while (cx <= cy) { - spiceterm_toggle_marked_cell (vt, cx); - cx++; - } - - sel_end_pos = pos; - } - } - - } else if (vt->mark_active) { - vt->mark_active = 0; - - if (sel_start_pos > sel_end_pos) { - int tmp = sel_start_pos - 1; - sel_start_pos = sel_end_pos; - sel_end_pos = tmp; - } - - int len = sel_end_pos - sel_start_pos + 1; - - if (vt->selection) free (vt->selection); - vt->selection = (gunichar2 *)malloc (len*sizeof (gunichar2)); - vt->selection_len = len; - char *sel_latin1 = (char *)malloc (len + 1); - - for (i = 0; i < len; i++) { - int pos = sel_start_pos + i; - int x = pos % vt->width; - int y1 = ((pos / vt->width) + vt->y_displ) % vt->total_height; - TextCell *c = &vt->cells[y1*vt->width + x]; - vt->selection[i] = c->ch; - sel_latin1[i] = (char)c->ch; - c++; - } - sel_latin1[len] = 0; - rfbGotXCutText (vt->screen, sel_latin1, len); - free (sel_latin1); - - while (sel_start_pos <= sel_end_pos) { - spiceterm_toggle_marked_cell (vt, sel_start_pos++); + if ((vt->ibuf_count + 1) < IBUFSIZE) { + vt->ibuf[vt->ibuf_count++] = (char)uc; + } else { + fprintf(stderr, "warning: input buffer overflow\n"); + } } - - } - - rfbDefaultPtrAddEvent (buttonMask, x, y, cl); - } -*/ static void spiceterm_motion_event(spiceTerm *vt, uint32_t x, uint32_t y, uint32_t buttons) { - DPRINTF(0, "mask=%08x x=%d y=%d", buttons, x ,y); + DPRINTF(1, "mask=%08x x=%d y=%d", buttons, x ,y); static int last_mask = 0; + static int sel_start_pos = 0; + static int sel_end_pos = 0; + static int button2_released = 1; + int i; int cx = x/8; int cy = y/16; @@ -1463,8 +1330,6 @@ spiceterm_motion_event(spiceTerm *vt, uint32_t x, uint32_t y, uint32_t buttons) if (cy >= vt->height) cy = vt->height - 1; if (vt->report_mouse && buttons != last_mask) { - DPRINTF(0, "report=%d", vt->report_mouse); - last_mask = buttons; if (buttons & 2) { mouse_report(vt, 0, cx, cy); @@ -1479,6 +1344,95 @@ spiceterm_motion_event(spiceTerm *vt, uint32_t x, uint32_t y, uint32_t buttons) mouse_report (vt, 3, cx, cy); } } + + if (buttons & 4) { + if(button2_released && vt->selection) { + int i; + for(i = 0; i < vt->selection_len; i++) { + spiceterm_respond_unichar2(vt, vt->selection[i]); + } + spiceterm_update_watch_mask(vt, TRUE); + if (vt->y_displ != vt->y_base) { + vt->y_displ = vt->y_base; + spiceterm_refresh(vt); + } + } + button2_released = 0; + } else { + button2_released = 1; + } + + if (buttons & 2) { + int pos = cy*vt->width + cx; + + // code borrowed from libvncserver (VNCconsole.c) + + if (!vt->mark_active) { + + if (sel_start_pos != sel_end_pos) { + while (sel_start_pos <= sel_end_pos) { + spiceterm_toggle_marked_cell(vt, sel_start_pos++); + } + } + + vt->mark_active = 1; + sel_start_pos = sel_end_pos = pos; + spiceterm_toggle_marked_cell(vt, pos); + + } else { + + if (pos != sel_end_pos) { + + if (pos > sel_end_pos) { + cx = sel_end_pos; cy=pos; + } else { + cx=pos; cy=sel_end_pos; + } + + if (cx < sel_start_pos) { + if (cy < sel_start_pos) cy--; + } else { + cx++; + } + + while (cx <= cy) { + spiceterm_toggle_marked_cell(vt, cx); + cx++; + } + + sel_end_pos = pos; + } + } + + } else if (vt->mark_active) { + vt->mark_active = 0; + + if (sel_start_pos > sel_end_pos) { + int tmp = sel_start_pos - 1; + sel_start_pos = sel_end_pos; + sel_end_pos = tmp; + } + + int len = sel_end_pos - sel_start_pos + 1; + + if (vt->selection) free (vt->selection); + vt->selection = (gunichar2 *)malloc (len*sizeof(gunichar2)); + vt->selection_len = len; + + for (i = 0; i < len; i++) { + int pos = sel_start_pos + i; + int x = pos % vt->width; + int y1 = ((pos / vt->width) + vt->y_displ) % vt->total_height; + TextCell *c = &vt->cells[y1*vt->width + x]; + vt->selection[i] = c->ch; + c++; + } + + DPRINTF(1, "selection length = %d", vt->selection_len); + + // fixme: tell client we have something seletced + //rfbGotXCutText (vt->screen, sel_latin1, len); + } } static void @@ -1499,7 +1453,7 @@ my_kbd_push_keyval(SpiceKbdInstance *sin, uint32_t keySym, int flags) static int shift = 0; char *esc = NULL; - guint uc = 0; + gunichar2 uc = 0; DPRINTF(1, "flags=%d keySym=%08x", flags, keySym); @@ -1606,19 +1560,7 @@ my_kbd_push_keyval(SpiceKbdInstance *sin, uint32_t keySym, int flags) if (esc) { spiceterm_respond_esc(vt, esc); } else if (uc > 0) { - if (vt->utf8) { - gchar buf[10]; - gint len = g_unichar_to_utf8(uc, buf); - - if (len > 0) { - int i; - for (i = 0; i < len; i++) { - vt->ibuf[vt->ibuf_count++] = buf[i]; - } - } - } else { - vt->ibuf[vt->ibuf_count++] = (char)uc; - } + spiceterm_respond_unichar2(vt, uc); } } } diff --git a/spiceterm.h b/spiceterm.h index 3de1a0a..c2454f8 100644 --- a/spiceterm.h +++ b/spiceterm.h @@ -12,6 +12,7 @@ typedef struct TextAttributes { unsigned int blink:1; unsigned int invers:1; unsigned int unvisible:1; + unsigned int selected:1; } TextAttributes; typedef struct TextCell {