Browse code

fix: correctly handling of spaces at start and end of doing a Ctrl+C/Ctrl+V.

Dario Rodriguez authored on 30/05/2021 15:04:46
Showing 3 changed files
... ...
@@ -236,6 +236,28 @@ redata_getposptr(redata_t *redata, long pos, int *numchunk, int *offset)
236 236
         return(-1);
237 237
 }
238 238
 
239
+int
240
+redata_getchar(redata_t *redata, long pos)
241
+{
242
+        int numchunk;
243
+        int offset;
244
+        int avail;
245
+        rechunk_t *chunk;
246
+        if(redata==NULL || pos<0 || pos>=redata_getsize(redata))
247
+                return(-1); /* sanity check failed */
248
+        if(redata_getposptr(redata,pos,&numchunk,&offset)!=0)
249
+                return(-1); /* couldn't get pos */
250
+        /* search for data starting at that pos */
251
+        for(;numchunk<redata->sizechunks;numchunk++,offset=0) {
252
+                chunk=redata->chunks[numchunk];
253
+                avail=chunk->useddata-offset;
254
+                if(avail>0) {
255
+                        return((int) (((unsigned char *)chunk->data)[offset]));
256
+                }
257
+        }
258
+        return(-1); /* not found */
259
+}
260
+
239 261
 int
240 262
 redata_wipe(redata_t *redata)
241 263
 {
... ...
@@ -108,7 +108,8 @@ long redata_getsize(redata_t *redata);
108 108
 long redata_getused(redata_t *redata);
109 109
 long redata_getavailable(redata_t *redata);
110 110
 int redata_getposptr(redata_t *redata, long pos, int *numchunk, int *offset);
111
-
111
+int redata_getchar(redata_t *redata, long pos);
112
+ 
112 113
 /* low level stuff */
113 114
 int redata_wipe(redata_t *redata);
114 115
 int redata_preallocate(redata_t *redata, long size);
... ...
@@ -116,6 +116,7 @@ int re_setuidata(re_t *re);
116 116
 int re_setfilename(re_t *re, char *filename);
117 117
 int re_fixorigin(re_t *re);
118 118
 int re_fixorigin_center(re_t *re);
119
+int re_textinsert(re_t *re, char *text, int sizetext);
119 120
 int re_processkey_editing(re_t *re, SDL_Event *event);
120 121
 int re_processkey_commandwait(re_t *re, SDL_Event *event);
121 122
 int re_processkey_commanddata(re_t *re, SDL_Event *event);
... ...
@@ -582,6 +583,78 @@ re_fixorigin_center(re_t *re)
582 583
         return(0);
583 584
 }
584 585
 
586
+int
587
+re_textinsert(re_t *re, char *text, int sizetext)
588
+{
589
+        long realend;
590
+        int at_end;
591
+        int nspaces;
592
+        long cursorpos;
593
+        long selstart,selend;
594
+        int fixsel;
595
+        char *ptr,*next;
596
+        int len;
597
+        int trimmed;
598
+        if(re==NULL || text==NULL || sizetext<=0)
599
+                return(-1); /* sanity check failed */
600
+        if(redata_linecol2pos(re->data,re->curline,re->curcol,&cursorpos,NULL)!=0
601
+          || redata_line_realend(re->data,cursorpos,&realend)==-1) {
602
+                return(-1); /* couldn't get current line info */
603
+        }
604
+        fixsel=0;
605
+        selstart=selend=0;
606
+        if(re->selactive
607
+          && redata_linecol2pos(re->data,re->sellinefrom,re->selcolfrom,&selstart,NULL)==0
608
+          && redata_linecol2pos(re->data,re->sellineto,re->selcolto,&selend,NULL)==0) {
609
+                fixsel=1;
610
+        }
611
+        at_end=(cursorpos==realend)?1:0;
612
+        for(nspaces=0;nspaces<sizetext && text[nspaces]==' ';nspaces++)
613
+                ;
614
+        if(nspaces>0 && nspaces==sizetext && at_end) {
615
+                /* instead of adding spaces at the end of the line, we move the cursor to the right */
616
+                re_moveleftright(re,nspaces);
617
+                return(0); /* no need to add spaces at the end of the line */
618
+        }
619
+        redata_undo_groupinit(re->data,NULL);
620
+        if(!(text[0]=='\n' && sizetext==1) && at_end) {
621
+                int col;
622
+                if(redata_pos2linecol(re->data,cursorpos,NULL,&col)==-1)
623
+                        return(-1); /* couldn't get line info */
624
+                if(redata_op_addn(re->data,cursorpos,' ',re->curcol-col,NULL)!=0)
625
+                        return(-1); /* couldn't add spaces up to current displayed pos */
626
+                /* increment cursorpos; spaces are 1 byte, so the number of columns advanced is the number of bytes advanced */
627
+                cursorpos+=re->curcol-col;
628
+        }
629
+        if(redata_op_add(re->data,cursorpos,text,sizetext,NULL)!=0)
630
+                return(-1); /* couldn't add requested text */
631
+        if(fixsel) {
632
+                if(cursorpos<=selstart)
633
+                        redata_pos2linecol(re->data,selstart+sizetext,&(re->sellinefrom),&(re->selcolfrom));
634
+                if(cursorpos<=selend)
635
+                        redata_pos2linecol(re->data,selend+sizetext,&(re->sellineto),&(re->selcolto));
636
+        }
637
+        for(ptr=text,next=memchr(text,'\n',sizetext);ptr!=NULL;ptr=(next!=NULL)?next+1:NULL,next=(ptr!=NULL)?memchr(ptr,'\n',sizetext-(ptr-text)):NULL) {
638
+                len=(next!=NULL)?(next-ptr):sizetext-(ptr-text);
639
+                re->curcol+=redata_generic_utf8len(ptr,len);
640
+                cursorpos+=len;
641
+                if(next!=NULL) {
642
+                        cursorpos++;
643
+                        if(re_rtrim(re,cursorpos-1,&trimmed)!=-1)
644
+                                cursorpos-=trimmed;
645
+                        re->curline++;
646
+                        re->curcol=0;
647
+                }
648
+        }
649
+        /* trim last line inserted */
650
+        if(redata_getchar(re->data,cursorpos)=='\n' && re_rtrim(re,cursorpos,&trimmed)!=-1)
651
+                cursorpos-=trimmed;
652
+        redata_undo_groupcommit(re->data,NULL);
653
+        re_fixorigin(re);
654
+        re->headerdirty=1;
655
+        re->contentsdirty=1;
656
+        return(0);
657
+}
585 658
 
586 659
 int
587 660
 re_processkey_editing(re_t *re, SDL_Event *event)
... ...
@@ -641,13 +714,6 @@ fprintf(stderr,"SDL_KEYDOWN: fake setup ok\n");
641 714
         }
642 715
         /* special case: text editing event */
643 716
         if(event->type==SDL_TEXTINPUT) {
644
-                int len;
645
-                long realend;
646
-                int at_end;
647
-                int nspaces;
648
-                long cursorpos;
649
-                long selstart,selend;
650
-                int fixsel;
651 717
                 if(re->ignorenkeys>0) {
652 718
                         re->ignorenkeys--;
653 719
                         return(0); /* this is an already processed key, ignore it */
... ...
@@ -655,63 +721,7 @@ fprintf(stderr,"SDL_KEYDOWN: fake setup ok\n");
655 721
 #if 0
656 722
 fprintf(stderr,"SDL_TEXTINPUT:\"%s\"\n",event->text.text);
657 723
 #endif
658
-                if(redata_linecol2pos(re->data,re->curline,re->curcol,&cursorpos,NULL)!=0
659
-                  || redata_line_realend(re->data,cursorpos,&realend)==-1) {
660
-                        return(-1); /* couldn't get current line info */
661
-                }
662
-                fixsel=0;
663
-                selstart=selend=0;
664
-                if(re->selactive
665
-                  && redata_linecol2pos(re->data,re->sellinefrom,re->selcolfrom,&selstart,NULL)==0
666
-                  && redata_linecol2pos(re->data,re->sellineto,re->selcolto,&selend,NULL)==0) {
667
-                        fixsel=1;
668
-                }
669
-                at_end=(cursorpos==realend)?1:0;
670
-                for(nspaces=0;event->text.text[nspaces]==' ';nspaces++)
671
-                        ;
672
-                if(nspaces>0 && event->text.text[nspaces]=='\0' && at_end) {
673
-                        /* instead of adding spaces at the end of the line, we move the cursor to the right */
674
-                        re_moveleftright(re,nspaces);
675
-                        return(0); /* no need to add spaces at the end of the line */
676
-                }
677
-                redata_undo_groupinit(re->data,NULL);
678
-                if(!(event->text.text[0]=='\n' && event->text.text[1]=='\0') && at_end) {
679
-                        int col;
680
-                        if(redata_pos2linecol(re->data,cursorpos,NULL,&col)==-1)
681
-                                return(-1); /* couldn't get line info */
682
-                        if(redata_op_addn(re->data,cursorpos,' ',re->curcol-col,NULL)!=0)
683
-                                return(-1); /* couldn't add spaces up to current displayed pos */
684
-                        /* increment cursorpos; spaces are 1 byte, so the number of columns advanced is the number of bytes advanced */
685
-                        cursorpos+=re->curcol-col;
686
-                }
687
-                len=strlen(event->text.text);
688
-                if(redata_op_add(re->data,cursorpos,event->text.text,len,NULL)!=0)
689
-                        return(-1); /* couldn't add requested text */
690
-                if(fixsel) {
691
-                        if(cursorpos<=selstart)
692
-                                redata_pos2linecol(re->data,selstart+len,&(re->sellinefrom),&(re->selcolfrom));
693
-                        if(cursorpos<=selend)
694
-                                redata_pos2linecol(re->data,selend+len,&(re->sellineto),&(re->selcolto));
695
-                }
696
-                cursorpos+=len;
697
-                if(event->text.text[0]=='\n' && event->text.text[1]=='\0') {
698
-                        int trimmed;
699
-                        if(re_rtrim(re,cursorpos-len,&trimmed))
700
-                                cursorpos-=trimmed;
701
-#if 1
702
-#if 0
703
-fprintf(stderr,"SDL_TEXTINPUT: Insering newline\n");
704
-#endif
705
-#endif
706
-                        re->curline++;
707
-                        re->curcol=0;
708
-                } else {
709
-                        re->curcol+=redata_generic_utf8len(event->text.text,len);
710
-                }
711
-                redata_undo_groupcommit(re->data,NULL);
712
-                re_fixorigin(re);
713
-                re->headerdirty=1;
714
-                re->contentsdirty=1;
724
+                re_textinsert(re,event->text.text,strlen(event->text.text));
715 725
         }
716 726
 #if 0
717 727
         else if(event->type==SDL_TEXTEDITING) {
... ...
@@ -953,10 +963,13 @@ fprintf(stderr,"SDL_KEYDOWN: BACKSPACE%s\n",(event==&fakeevent)?" (fake)":"");
953 963
                         re_selectbuf_fill(re,frompos,topos-frompos,re->selcolto-coldone);
954 964
                         SDL_SetClipboardText(re->selectbuf);
955 965
                         if(is_cut) {
966
+                                int trimmed;
956 967
                                 redata_undo_groupinit(re->data,NULL);
957 968
                                 redata_op_del(re->data,frompos,topos-frompos,NULL);
958
-                                redata_undo_groupcommit(re->data,NULL);
959 969
                                 redata_pos2linecol(re->data,frompos,&(re->curline),&(re->curcol));
970
+                                if(redata_getchar(re->data,frompos)=='\n' && re_rtrim(re,frompos,&trimmed)!=-1)
971
+                                        frompos-=trimmed;
972
+                                redata_undo_groupcommit(re->data,NULL);
960 973
                                 re_fixorigin(re);
961 974
                                 re->headerdirty=1;
962 975
                         }
... ...
@@ -973,16 +986,11 @@ fprintf(stderr,"SDL_KEYDOWN: BACKSPACE%s\n",(event==&fakeevent)?" (fake)":"");
973 986
                         re_sel_toggle(re);
974 987
                 if(SDL_HasClipboardText())
975 988
                         re_selectbuf_replace(re,SDL_GetClipboardText());
976
-                if(re->usedselectbuf>0) {
977
-                        redata_undo_groupinit(re->data,NULL);
978
-                        redata_op_add(re->data,cursorpos,re->selectbuf,re->usedselectbuf,NULL);
979
-                        redata_undo_groupcommit(re->data,NULL);
980
-                        cursorpos+=re->usedselectbuf;
981
-                        redata_pos2linecol(re->data,cursorpos,&(re->curline),&(re->curcol));
982
-                        re_fixorigin(re);
983
-                        re->headerdirty=1;
984
-                        re->contentsdirty=1;
985
-                }
989
+#if 1
990
+fprintf(stderr,"SELECTBUF:\"%s\" len:%i\n",re->selectbuf,(int)strlen(re->selectbuf));
991
+#endif
992
+                if(re->usedselectbuf>0)
993
+                        re_textinsert(re, re->selectbuf,re->usedselectbuf);
986 994
                 re->ignorenkeys++;
987 995
         } else if(re->selactive && event->key.keysym.sym==SDLK_p && (SDL_GetModState()&KMOD_CTRL)!=0) {
988 996
                 re_addprint(re);