Browse code

Implement search-and-replace

Dario Rodriguez authored on 29/11/2020 22:22:12
Showing 1 changed files
... ...
@@ -73,6 +73,7 @@ typedef struct re_t {
73 73
         char *command;
74 74
         char commandbuf[COMMANDBUFSIZE];
75 75
         char cachelastsearch[COMMANDBUFSIZE];
76
+        char cachelastreplacewith[COMMANDBUFSIZE];
76 77
         question_t *question;
77 78
         int showingwarning;
78 79
         int ignorenkeys;
... ...
@@ -85,6 +86,7 @@ volatile int flag_sigpipe;
85 86
 static int setsignal(int num, void (*sighandler)(int));
86 87
 static void sighandler_sigint(int num);
87 88
 static void sighandler_sigpipe(int num);
89
+static int mystricmp(const char *s1, const char *s2);
88 90
 
89 91
 
90 92
 re_t *re_init(void);
... ...
@@ -324,6 +326,23 @@ sighandler_sigpipe(int num)
324 326
         flag_sigpipe=1;
325 327
 }
326 328
 
329
+static int
330
+mystricmp(const char *s1, const char *s2)
331
+{
332
+        int c1,c2;
333
+        for(;*s1!='\0' && *s2!='\0';s1++,s2++) {
334
+                if(*s1==*s2)
335
+                        continue;
336
+                c1=*((unsigned char *)s1);
337
+                c2=*((unsigned char *)s2);
338
+                c1=(c1>='A' && c1<='Z')?c1-'A'+'a':c1;
339
+                c2=(c2>='A' && c2<='Z')?c2-'A'+'a':c2;
340
+                if(c1==c2)
341
+                        continue;
342
+                return(c1-c2);
343
+        }
344
+        return(((int) (*((unsigned char *)s1)))-((int) (*((unsigned char *)s2))));
345
+}
327 346
 
328 347
 re_t *
329 348
 re_init(void)
... ...
@@ -772,7 +791,11 @@ re_processkey_commandwait(re_t *re, SDL_Event *event)
772 791
                 strncpy(re->commandbuf,re->cachelastsearch,sizeof(re->commandbuf));
773 792
                 re->commandbuf[sizeof(re->commandbuf)-1]='\0';
774 793
                 re->headerdirty=1;
775
-#warning TODO: Search and replace (control+q+a)
794
+        } else if(re->command_first_key=='q' && event->key.keysym.sym==SDLK_a) {
795
+                re->command=COMMAND_REPLACEWHAT;
796
+                strncpy(re->commandbuf,re->cachelastsearch,sizeof(re->commandbuf));
797
+                re->commandbuf[sizeof(re->commandbuf)-1]='\0';
798
+                re->headerdirty=1;
776 799
         } else if(re->command_first_key=='k' && event->key.keysym.sym==SDLK_q) {
777 800
                 re->command=COMMAND_EXIT;
778 801
                 re->commandbuf[0]='\0';
... ...
@@ -947,6 +970,79 @@ re_processcommand(re_t *re)
947 970
                 re_fixorigin_center(re);
948 971
                 re->headerdirty=1;
949 972
                 re->contentsdirty=1;
973
+        } else if(strcmp(re->command,COMMAND_REPLACEWHAT)==0) {
974
+                re->command=COMMAND_REPLACEWITH;
975
+                strncpy(re->cachelastsearch,re->commandbuf,sizeof(re->cachelastsearch));
976
+                re->cachelastsearch[sizeof(re->cachelastsearch)-1]='\0';
977
+                strncpy(re->commandbuf,re->cachelastreplacewith,sizeof(re->commandbuf));
978
+                re->commandbuf[sizeof(re->commandbuf)-1]='\0';
979
+                re->headerdirty=1;
980
+                return(0);
981
+        } else if(strcmp(re->command,COMMAND_REPLACEWITH)==0) {
982
+                re->command=COMMAND_REPLACEHOW;
983
+                strncpy(re->cachelastreplacewith,re->commandbuf,sizeof(re->cachelastreplacewith));
984
+                re->cachelastreplacewith[sizeof(re->cachelastreplacewith)-1]='\0';
985
+                re->commandbuf[0]='\0';
986
+                re->headerdirty=1;
987
+                return(0);
988
+        } else if(strcmp(re->command,COMMAND_REPLACEHOW)==0) {
989
+                int is_all;
990
+                int slen,rlen;
991
+                long oldpos,newpos,endpos;
992
+                long total;
993
+                is_all=(mystricmp(re->commandbuf,"ean")==0)?1:(mystricmp(re->commandbuf,"san")==0)?0:-1;
994
+                if(is_all==-1) {
995
+                        re->command=COMMAND_WARNING;
996
+                        snprintf(re->commandbuf,sizeof(re->commandbuf),"Sorry, unimplemented. For now use only EAN or SAN options.");
997
+                        re->commandbuf[sizeof(re->commandbuf)-1]='\0';
998
+                        re->headerdirty=1;
999
+                        return(-1);
1000
+                }
1001
+                if(is_all==0 && !re->selactive) {
1002
+                        re->command=COMMAND_WARNING;
1003
+                        snprintf(re->commandbuf,sizeof(re->commandbuf),"No active selection, nothing changed.");
1004
+                        re->commandbuf[sizeof(re->commandbuf)-1]='\0';
1005
+                        re->headerdirty=1;
1006
+                        return(-1);
1007
+                }
1008
+                oldpos=0;
1009
+                endpos=redata_getused(re->data);
1010
+                if(!is_all
1011
+                  && (redata_linecol2pos(re->data,re->sellinefrom,re->selcolfrom,&oldpos,NULL)!=0
1012
+                  || redata_linecol2pos(re->data,re->sellineto,re->selcolto,&endpos,NULL)!=0)) {
1013
+                        re->command=COMMAND_WARNING;
1014
+                        snprintf(re->commandbuf,sizeof(re->commandbuf),"Invalid selection.");
1015
+                        re->commandbuf[sizeof(re->commandbuf)-1]='\0';
1016
+                        re->headerdirty=1;
1017
+                        return(-1);
1018
+                }
1019
+                slen=strlen(re->cachelastsearch);
1020
+                rlen=strlen(re->cachelastreplacewith);
1021
+                redata_undo_groupinit(re->data,NULL);
1022
+                for(total=0
1023
+                  ;(oldpos+slen)<endpos && (newpos=redata_searchforward(re->data,oldpos,re->cachelastsearch,slen))!=-1
1024
+                    && (newpos+slen)<=endpos
1025
+                  ;total++,oldpos=newpos+rlen) {
1026
+#if 1
1027
+fprintf(stderr,"substituting %i bytes for %i bytes ar position:%li\n",slen,rlen,newpos);
1028
+#endif
1029
+                        redata_op_del(re->data,newpos,slen,NULL);
1030
+                        redata_op_add(re->data,newpos,re->cachelastreplacewith,rlen,NULL);
1031
+                }
1032
+                redata_undo_groupcommit(re->data,NULL);
1033
+#if 1
1034
+fprintf(stderr,"oldpos:%li\n",oldpos);
1035
+#endif
1036
+                re->cursorpos=oldpos;
1037
+                redata_pos2linecol(re->data,re->cursorpos,&(re->curline),&(re->curcol));
1038
+                re_fixorigin_center(re);
1039
+                re->headerdirty=1;
1040
+                re->contentsdirty=1;
1041
+                re->command=COMMAND_WARNING;
1042
+                snprintf(re->commandbuf,sizeof(re->commandbuf),"%li subst",total);
1043
+                re->commandbuf[sizeof(re->commandbuf)-1]='\0';
1044
+                re->headerdirty=1;
1045
+                return(0);
950 1046
         } else if(strcmp(re->command,COMMAND_QUESTION)==0) {
951 1047
                 /* validate reply */
952 1048
                 if(!(atoi(re->commandbuf)>0 && atoi(re->commandbuf)<=re->question->nopts)) {