]> git.proxmox.com Git - spiceterm.git/commitdiff
allow to select text regions
authorDietmar Maurer <dietmar@proxmox.com>
Fri, 13 Sep 2013 07:53:24 +0000 (09:53 +0200)
committerDietmar Maurer <dietmar@proxmox.com>
Fri, 13 Sep 2013 08:02:59 +0000 (10:02 +0200)
screen.c
spiceterm.c
spiceterm.h

index 0646a3ffef62d21756abceb45dc01143c0025757..34ba4c607092cf79b5fdd8dd2ccac2581875b66c 100644 (file)
--- 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 {
index c3c7b7e8057a90309bf36707e1ffaf96705a1fc1..915b802d6a6095eb7d8f5c4d027aa1a2949e84fb 100644 (file)
@@ -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);
             }
         }
     }
index 3de1a0a81f2ac5650ff882cd7f93d9d2d73ba782..c2454f8b0ee0d5c39f844aa6dc6f963c8d091548 100644 (file)
@@ -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 {