=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/mg/word.c,v retrieving revision 1.17 retrieving revision 1.18 diff -u -r1.17 -r1.18 --- src/usr.bin/mg/word.c 2015/03/19 21:22:15 1.17 +++ src/usr.bin/mg/word.c 2015/12/29 19:44:32 1.18 @@ -1,4 +1,4 @@ -/* $OpenBSD: word.c,v 1.17 2015/03/19 21:22:15 bcallah Exp $ */ +/* $OpenBSD: word.c,v 1.18 2015/12/29 19:44:32 lum Exp $ */ /* This file is in the public domain. */ @@ -10,11 +10,15 @@ #include #include +#include #include +#include +#include #include "def.h" RSIZE countfword(void); +int grabword(char **); /* * Move the cursor backward by "n" words. All of the details of motion are @@ -61,6 +65,162 @@ return (TRUE); } } + return (TRUE); +} + +/* + * Transpose 2 words. + * The function below is artifically restricted to only a maximum of 1 iteration + * at the moment because the 'undo' functionality within mg needs amended for + * multiple movements of point, backwards and forwards. + */ +int +transposeword(int f, int n) +{ + struct line *tmp1_w_dotp = NULL; + struct line *tmp2_w_dotp = NULL; + int tmp2_w_doto = 0; + int tmp1_w_dotline = 0; + int tmp2_w_dotline = 0; + int tmp1_w_doto; + int i; /* start-of-line space counter */ + int ret, s; + int newline; + int leave = 0; + int tmp_len; + char *word1 = NULL; + char *word2 = NULL; + char *chr; + + if (n == 0) + return (TRUE); + + n = 1; /* remove this line to allow muliple-iterations */ + + if ((s = checkdirty(curbp)) != TRUE) + return (s); + if (curbp->b_flag & BFREADONLY) { + dobeep(); + ewprintf("Buffer is read-only"); + return (FALSE); + } + undo_boundary_enable(FFRAND, 0); + + /* go backwards to find the start of a word to transpose. */ + (void)backword(FFRAND, 1); + ret = grabword(&word1); + if (ret == ABORT) { + ewprintf("No word to the left to tranpose."); + return (FALSE); + } + if (ret < 0) { + dobeep(); + ewprintf("Error copying word: %s", strerror(ret)); + free(word1); + return (FALSE); + } + tmp_len = strlen(word1); + + while (n-- > 0) { + i = 0; + newline = 0; + + tmp1_w_doto = curwp->w_doto; + tmp1_w_dotline = curwp->w_dotline; + tmp1_w_dotp = curwp->w_dotp; + + /* go forward and find next word. */ + while (inword() == FALSE) { + if (forwchar(FFRAND, 1) == FALSE) { + leave = 1; + if (tmp1_w_dotline < curwp->w_dotline) + curwp->w_dotline--; + ewprintf("Don't have two things to transpose"); + break; + } + if (curwp->w_doto == 0) { + newline = 1; + i = 0; + } else if (newline) + i++; + } + if (leave) { + tmp2_w_doto = tmp1_w_doto; + tmp2_w_dotline = tmp1_w_dotline; + tmp2_w_dotp = tmp1_w_dotp; + break; + } + tmp2_w_doto = curwp->w_doto; + tmp2_w_dotline = curwp->w_dotline; + tmp2_w_dotp = curwp->w_dotp; + + ret = grabword(&word2); + if (ret < 0) { + dobeep(); + ewprintf("Error copying word: %s", strerror(ret)); + free(word1); + return (FALSE); + } + tmp_len = strlen(word2); + tmp2_w_doto += tmp_len; + + curwp->w_doto = tmp1_w_doto; + curwp->w_dotline = tmp1_w_dotline; + curwp->w_dotp = tmp1_w_dotp; + + /* insert shuffled along word */ + for (chr = word2; *chr != '\0'; ++chr) + linsert(1, *chr); + + if (newline) + tmp2_w_doto = i; + + curwp->w_doto = tmp2_w_doto; + curwp->w_dotline = tmp2_w_dotline; + curwp->w_dotp = tmp2_w_dotp; + + word2 = NULL; + } + curwp->w_doto = tmp2_w_doto; + curwp->w_dotline = tmp2_w_dotline; + curwp->w_dotp = tmp2_w_dotp; + + /* insert very first word in its new position */ + for (chr = word1; *chr != '\0'; ++chr) + linsert(1, *chr); + + if (leave) + (void)backword(FFRAND, 1); + + free(word1); + free(word2); + + undo_boundary_enable(FFRAND, 1); + + return (TRUE); +} + +/* + * copy and delete word. +*/ +int +grabword(char **word) +{ + int c; + + while (inword() == TRUE) { + c = lgetc(curwp->w_dotp, curwp->w_doto); + if (*word == NULL) { + if (asprintf(word, "%c", c) == -1) + return (errno); + } else { + if (asprintf(word, "%s%c", *word, c) == -1) + return (errno); + } + (void)forwdel(FFRAND, 1); + } + if (*word == NULL) + return (ABORT); return (TRUE); }