Use (mostly) the same capitalisation in the replacement string as in
authorflorian <florian@openbsd.org>
Thu, 12 Jul 2018 12:38:56 +0000 (12:38 +0000)
committerflorian <florian@openbsd.org>
Thu, 12 Jul 2018 12:38:56 +0000 (12:38 +0000)
the replaced string:

replacing foo with bar turns

foo
Foo
FOO

into

bar
Bar
BAR

OK phessler, benno

usr.bin/mg/line.c

index ae5d4a7..7c292db 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: line.c,v 1.59 2017/09/09 13:10:28 florian Exp $       */
+/*     $OpenBSD: line.c,v 1.60 2018/07/12 12:38:56 florian Exp $       */
 
 /* This file is in the public domain. */
 
@@ -18,6 +18,7 @@
  */
 
 #include <sys/queue.h>
+#include <ctype.h>
 #include <limits.h>
 #include <signal.h>
 #include <stdio.h>
@@ -511,7 +512,11 @@ int
 lreplace(RSIZE plen, char *st)
 {
        RSIZE   rlen;   /* replacement length            */
-       int s;
+       struct line *lp;
+       RSIZE n;
+       int s, doto, is_query_capitalised = 0, is_query_allcaps = 0;
+       int is_replace_alllower = 0;
+       char *repl;
 
        if ((s = checkdirty(curbp)) != TRUE)
                return (s);
@@ -520,16 +525,59 @@ lreplace(RSIZE plen, char *st)
                ewprintf("Buffer is read only");
                return (FALSE);
        }
+
+       if ((repl = strdup(st)) == NULL) {
+               dobeep();
+               ewprintf("out of memory");
+               return (FALSE);
+       }
+
        undo_boundary_enable(FFRAND, 0);
 
        (void)backchar(FFARG | FFRAND, (int)plen);
+
+       lp = curwp->w_dotp;
+       doto = curwp->w_doto;
+       n = plen;
+
+       is_query_capitalised = isupper((unsigned char)lgetc(lp, doto));
+
+       if (is_query_capitalised) {
+               for (n = 0, is_query_allcaps = 1; n < plen && is_query_allcaps;
+                   n++) {
+                       is_query_allcaps = !isalpha((unsigned char)lgetc(lp,
+                           doto)) || isupper((unsigned char)lgetc(lp, doto));
+                       doto++;
+                       if (doto == llength(lp)) {
+                               doto = 0;
+                               lp = lforw(lp);
+                               n++; /* \n is implicit in the buffer */
+                       }
+               }
+       }
+
        (void)ldelete(plen, KNONE);
 
-       rlen = strlen(st);
-       region_put_data(st, rlen);
+       rlen = strlen(repl);
+       for (n = 0, is_replace_alllower = 1; n < rlen && is_replace_alllower;
+           n++)
+               is_replace_alllower = !isupper((unsigned char)repl[n]);
+
+       if (is_replace_alllower) {
+               if (is_query_allcaps) {
+                       for (n = 0; n < rlen; n++)
+                               repl[n] = toupper((unsigned char)repl[n]);
+               } else if (is_query_capitalised) {
+                       repl[0] = toupper((unsigned char)repl[0]);
+               }
+       }
+
+       region_put_data(repl, rlen);
        lchange(WFFULL);
 
        undo_boundary_enable(FFRAND, 1);
+
+       free(repl);
        return (TRUE);
 }