]> git.lizzy.rs Git - plan9front.git/blobdiff - sys/src/cmd/acme/text.c
acme: import changes from plan9port (thanks jxy)
[plan9front.git] / sys / src / cmd / acme / text.c
index 7380d01636256247f11a2d70da794b51525801eb..484ec3de12d1e829f785503911e767b3e1b8e4e4 100644 (file)
@@ -502,6 +502,27 @@ textreadc(Text *t, uint q)
        return r;
 }
 
+static int
+spacesindentbswidth(Text *t)
+{
+       uint q, col;
+       Rune r;
+
+       col = textbswidth(t, 0x15);
+       q = t->q0;
+       while(q > 0){
+               r = textreadc(t, q-1);
+               if(r != ' ')
+                       break;
+               q--;
+               if(--col % t->tabstop == 0)
+                       break;
+       }
+       if(t->q0 == q)
+               return 1;
+       return t->q0-q;
+}
+
 int
 textbswidth(Text *t, Rune c)
 {
@@ -510,8 +531,11 @@ textbswidth(Text *t, Rune c)
        int skipping;
 
        /* there is known to be at least one character to erase */
-       if(c == 0x08)   /* ^H: erase character */
+       if(c == 0x08){  /* ^H: erase character */
+               if(t->what == Body && t->w->indent[SPACESINDENT])
+                       return spacesindentbswidth(t);
                return 1;
+       }
        q = t->q0;
        skipping = TRUE;
        while(q > 0){
@@ -775,8 +799,19 @@ texttype(Text *t, Rune r)
                for(i=0; i<t->file->ntext; i++)
                        textfill(t->file->text[i]);
                return;
+       case '\t':
+               if(t->what == Body && t->w->indent[SPACESINDENT]){
+                       nnb = textbswidth(t, 0x15);
+                       if(nnb == 1 && textreadc(t, t->q0-1) == '\n')
+                               nnb = 0;
+                       nnb = t->tabstop - nnb % t->tabstop;
+                       rp = runemalloc(nnb);
+                       for(nr = 0; nr < nnb; nr++)
+                               rp[nr] = ' ';
+               }
+               break;
        case '\n':
-               if(t->what == Body && t->w->autoindent){
+               if(t->what == Body && t->w->indent[AUTOINDENT]){
                        /* find beginning of previous line using backspace code */
                        nnb = textbswidth(t, 0x15); /* ^U case */
                        rp = runemalloc(nnb + 1);
@@ -833,6 +868,8 @@ textcommit(Text *t, int tofile)
 
 static Text    *clicktext;
 static uint    clickmsec;
+static int     clickcount;
+static Point   clickpt;
 static Text    *selecttext;
 static uint    selectq;
 
@@ -872,6 +909,7 @@ textframescroll(Text *t, int dl)
                        textsetselect(t, selectq, t->org+t->p1);
        }
        textsetorigin(t, q0, TRUE);
+       flushimage(display, 1);
 }
 
 
@@ -879,7 +917,7 @@ void
 textselect(Text *t)
 {
        uint q0, q1;
-       int b, x, y;
+       int b, x, y, dx, dy;
        int state;
 
        selecttext = t;
@@ -890,25 +928,36 @@ textselect(Text *t)
        b = mouse->buttons;
        q0 = t->q0;
        q1 = t->q1;
+       dx = abs(clickpt.x - mouse->xy.x);
+       dy = abs(clickpt.y - mouse->xy.y);
+       clickpt = mouse->xy;
        selectq = t->org+frcharofpt(t, mouse->xy);
-       if(clicktext==t && mouse->msec-clickmsec<500)
-       if(q0==q1 && selectq==q0){
-               textdoubleclick(t, &q0, &q1);
+       clickcount++;
+       if(mouse->msec-clickmsec >= 500 || selecttext != t || clickcount > 3 || dx > 3 || dy > 3)
+               clickcount = 0;
+       if(clickcount >= 1 && selecttext==t && mouse->msec-clickmsec < 500){
+               textstretchsel(t, selectq, &q0, &q1, clickcount);
                textsetselect(t, q0, q1);
                flushimage(display, 1);
                x = mouse->xy.x;
                y = mouse->xy.y;
                /* stay here until something interesting happens */
-               do
+               while(1){
                        readmouse(mousectl);
-               while(mouse->buttons==b && abs(mouse->xy.x-x)<3 && abs(mouse->xy.y-y)<3);
+                       dx = abs(mouse->xy.x - x);
+                       dy = abs(mouse->xy.y - y);
+                       if(mouse->buttons != b || dx >= 3 || dy >= 3)
+                               break;
+                       clickcount++;
+                       clickmsec = mouse->msec;
+               }
                mouse->xy.x = x;        /* in case we're calling frselect */
                mouse->xy.y = y;
                q0 = t->q0;     /* may have changed */
                q1 = t->q1;
-               selectq = q0;
+               selectq = t->org+frcharofpt(t, mouse->xy);;
        }
-       if(mouse->buttons == b){
+       if(mouse->buttons == b && clickcount == 0){
                t->Frame.scroll = framescroll;
                frselect(t, mousectl);
                /* horrible botch: while asleep, may have lost selection altogether */
@@ -925,13 +974,11 @@ textselect(Text *t)
                        q1 = t->org+t->p1;
        }
        if(q0 == q1){
-               if(q0==t->q0 && clicktext==t && mouse->msec-clickmsec<500){
-                       textdoubleclick(t, &q0, &q1);
-                       clicktext = nil;
-               }else{
+               if(q0==t->q0 && mouse->msec-clickmsec<500)
+                       textstretchsel(t, selectq, &q0, &q1, clickcount);
+               else
                        clicktext = t;
-                       clickmsec = mouse->msec;
-               }
+               clickmsec = mouse->msec;
        }else
                clicktext = nil;
        textsetselect(t, q0, q1);
@@ -970,7 +1017,8 @@ textselect(Text *t)
                flushimage(display, 1);
                while(mouse->buttons == b)
                        readmouse(mousectl);
-               clicktext = nil;
+               if(mouse->msec-clickmsec >= 500)
+                       clicktext = nil;
        }
 }
 
@@ -1253,13 +1301,21 @@ Rune *right[] = {
        nil
 };
 
+int
+inmode(Rune r, int mode)
+{
+       return (mode == 1) ? isalnum(r) : r && !isspace(r);
+}
+
 void
-textdoubleclick(Text *t, uint *q0, uint *q1)
+textstretchsel(Text *t, uint mp, uint *q0, uint *q1, int mode)
 {
        int c, i;
        Rune *r, *l, *p;
        uint q;
 
+       *q0 = mp;
+       *q1 = mp;
        for(i=0; left[i]!=nil; i++){
                q = *q0;
                l = left[i];
@@ -1292,10 +1348,10 @@ textdoubleclick(Text *t, uint *q0, uint *q1)
                }
        }
        /* try filling out word to right */
-       while(*q1<t->file->nc && isalnum(textreadc(t, *q1)))
+       while(*q1<t->file->nc && inmode(textreadc(t, *q1), mode))
                (*q1)++;
        /* try filling out word to left */
-       while(*q0>0 && isalnum(textreadc(t, *q0-1)))
+       while(*q0>0 && inmode(textreadc(t, *q0-1), mode))
                (*q0)--;
 }
 
@@ -1355,7 +1411,7 @@ textsetorigin(Text *t, uint org, int exact)
        Rune *r;
        uint n;
 
-       if(org>0 && !exact){
+       if(org>0 && !exact && textreadc(t, org-1) != '\n'){
                /* org is an estimate of the char posn; find a newline */
                /* don't try harder than 256 chars */
                for(i=0; i<256 && org<t->file->nc; i++){