Browse code

bugfix: selection was moving when inserting/deleting text before the selection

Dario Rodriguez authored on 12/03/2021 22:54:34
Showing 1 changed files
... ...
@@ -639,6 +639,8 @@ fprintf(stderr,"SDL_KEYDOWN: fake setup ok\n");
639 639
                 int at_end;
640 640
                 int nspaces;
641 641
                 long cursorpos;
642
+                long selstart,selend;
643
+                int fixsel;
642 644
                 if(re->ignorenkeys>0) {
643 645
                         re->ignorenkeys--;
644 646
                         return(0); /* this is an already processed key, ignore it */
... ...
@@ -650,6 +652,13 @@ fprintf(stderr,"SDL_TEXTINPUT:\"%s\"\n",event->text.text);
650 652
                   || redata_line_realend(re->data,cursorpos,&realend)==-1) {
651 653
                         return(-1); /* couldn't get current line info */
652 654
                 }
655
+                fixsel=0;
656
+                selstart=selend=0;
657
+                if(re->selactive
658
+                  && redata_linecol2pos(re->data,re->sellinefrom,re->selcolfrom,&selstart,NULL)==0
659
+                  && redata_linecol2pos(re->data,re->sellineto,re->selcolto,&selend,NULL)==0) {
660
+                        fixsel=1;
661
+                }
653 662
                 at_end=(cursorpos==realend)?1:0;
654 663
                 for(nspaces=0;event->text.text[nspaces]==' ';nspaces++)
655 664
                         ;
... ...
@@ -671,6 +680,12 @@ fprintf(stderr,"SDL_TEXTINPUT:\"%s\"\n",event->text.text);
671 680
                 len=strlen(event->text.text);
672 681
                 if(redata_op_add(re->data,cursorpos,event->text.text,len,NULL)!=0)
673 682
                         return(-1); /* couldn't add requested text */
683
+                if(fixsel) {
684
+                        if(cursorpos<=selstart)
685
+                                redata_pos2linecol(re->data,selstart+len,&(re->sellinefrom),&(re->selcolfrom));
686
+                        if(cursorpos<=selend)
687
+                                redata_pos2linecol(re->data,selend+len,&(re->sellineto),&(re->selcolto));
688
+                }
674 689
                 cursorpos+=len;
675 690
                 if(event->text.text[0]=='\n' && event->text.text[1]=='\0') {
676 691
                         int trimmed;
... ...
@@ -777,12 +792,15 @@ fprintf(stderr,"SDL_KEYDOWN: sym:%i\n",event->key.keysym.sym);
777 792
                 re->contentsdirty=1;
778 793
         } else if(event->key.keysym.sym==SDLK_BACKSPACE && (re->curline>0 || re->curcol>0)) {
779 794
                 int line,col;
780
-                long startpos,newpos,realstart,start;
795
+                long startpos,delpos,realstart,start;
796
+                long dellen;
781 797
                 char *ptr;
782 798
                 int len;
783 799
                 int trimmed;
784 800
                 int doneinc;
785 801
                 long cursorpos;
802
+                long selstart,selend;
803
+                int fixsel;
786 804
                 if(redata_linecol2pos(re->data,re->curline,re->curcol,&cursorpos,NULL)!=0)
787 805
 #if 0
788 806
 fprintf(stderr,"SDL_KEYDOWN: BACKSPACE%s\n",(event==&fakeevent)?" (fake)":"");
... ...
@@ -797,27 +815,34 @@ fprintf(stderr,"SDL_KEYDOWN: BACKSPACE%s\n",(event==&fakeevent)?" (fake)":"");
797 815
                 if(event!=&fakeevent)
798 816
                         redata_undo_groupinit(re->data,NULL);
799 817
                 /* delete the last character */
818
+                fixsel=0;
819
+                selstart=selend=0;
820
+                if(re->selactive
821
+                  && redata_linecol2pos(re->data,re->sellinefrom,re->selcolfrom,&selstart,NULL)==0
822
+                  && redata_linecol2pos(re->data,re->sellineto,re->selcolto,&selend,NULL)==0) {
823
+                        fixsel=1;
824
+                }           
800 825
                 if(col>0) {
801 826
                         if(redata_line_realstart(re->data,cursorpos,&realstart)==-1)
802 827
                                 return(-1); /* couldn't get line info */
803 828
                         /* get the start of the part to delete */
804 829
                         doneinc=0;
805
-                        for(ptr=NULL,len=0,start=0,newpos=cursorpos;doneinc!=1;) {
806
-                                if((newpos-1)<realstart)
830
+                        for(ptr=NULL,len=0,start=0,delpos=cursorpos;doneinc!=1;) {
831
+                                if((delpos-1)<realstart)
807 832
                                         break;
808
-                                newpos--;
809
-                                if(ptr==NULL || (start+len)<=newpos || newpos<start) {
810
-                                        if(redata_line_rawinfo(re->data,newpos,&start,&ptr,&len,NULL)==-1)
833
+                                delpos--;
834
+                                if(ptr==NULL || (start+len)<=delpos || delpos<start) {
835
+                                        if(redata_line_rawinfo(re->data,delpos,&start,&ptr,&len,NULL)==-1)
811 836
                                                 return(-1); /* couldn't get line data */
812 837
                                 }
813
-                                if(redata_generic_utf8isstartbyte(ptr[newpos-start]))
838
+                                if(redata_generic_utf8isstartbyte(ptr[delpos-start]))
814 839
                                         doneinc++;
815 840
                         }
816 841
                         /* delete */
817
-                        redata_op_del(re->data,newpos,cursorpos-newpos,NULL);
818
-                        cursorpos=newpos;
842
+                        dellen=cursorpos-delpos;
843
+                        redata_op_del(re->data,delpos,dellen,NULL);
844
+                        cursorpos=delpos;
819 845
                 } else {
820
-                        long delpos;
821 846
                         /* to make the code trivial, we're being lazy on '\n' deletion: we call ...rawinfo() for each byte in the multibyte utf-8 sequence */
822 847
                         for(delpos=cursorpos-1
823 848
                           ;delpos>0
... ...
@@ -825,10 +850,27 @@ fprintf(stderr,"SDL_KEYDOWN: BACKSPACE%s\n",(event==&fakeevent)?" (fake)":"");
825 850
                                 if(redata_generic_utf8isstartbyte(ptr[delpos-startpos]))
826 851
                                         break;
827 852
                         }
828
-                        redata_op_del(re->data,delpos,cursorpos-delpos,NULL);
853
+                        dellen=cursorpos-delpos;
854
+                        redata_op_del(re->data,delpos,dellen,NULL);
829 855
                         cursorpos=delpos;
830 856
                 }
831 857
                 redata_pos2linecol(re->data,cursorpos,&(re->curline),&(re->curcol));
858
+                if(fixsel) {
859
+                        if(delpos<=selstart) {
860
+                                /* if we deleted the start of selection, make the start of selection the cursorpos */
861
+                                if(selstart>=delpos && selstart<(delpos+dellen))
862
+                                        redata_pos2linecol(re->data,cursorpos,&(re->sellinefrom),&(re->selcolfrom));
863
+                                else
864
+                                        redata_pos2linecol(re->data,selstart-dellen,&(re->sellinefrom),&(re->selcolfrom));
865
+                        }
866
+                        if(delpos<=selend) {
867
+                                /* if we deleted the end of selection, make the start of selection the cursorpos */
868
+                                if(selend>=delpos && selend<(delpos+dellen))
869
+                                        redata_pos2linecol(re->data,cursorpos,&(re->sellineto),&(re->selcolto));
870
+                                else
871
+                                        redata_pos2linecol(re->data,selend-dellen,&(re->sellineto),&(re->selcolto));
872
+                        }
873
+                }
832 874
                 /* if cursor at end of line and there are trailing spaces at the end, delete them too */
833 875
                 if(re_rtrim(re,cursorpos,&trimmed))
834 876
                         cursorpos-=trimmed;