/* * Kill backwards by "n" words. Move backwards by the desired number of words, * counting the characters. When dot is finally moved to its resting place, * fire off the kill command. Bound to "M-Rubout" and to "M-Backspace". */ int delbword(int f, int n) { register long size; if (curbp->b_mode&MDVIEW) /* don't allow this command if */ return(rdonly()); /* we are in read only mode */ if (n < 0) return (FALSE); if (backchar(FALSE, 1) == FALSE) return (FALSE); size = 0L; while (n--) { while (inword() == FALSE) { if (backchar(FALSE, 1) == FALSE) return (FALSE); ++size; } while (inword() != FALSE) { if (backchar(FALSE, 1) == FALSE) return (FALSE); ++size; } } if (forwchar(FALSE, 1) == FALSE) return (FALSE); return (ldelete(size, kinsert)); }
/* * Move the cursor forward by the specified number of words. As you move, * convert any characters to upper case. Error if you try and move beyond the * end of the buffer. Bound to "M-U" */ int upperword(int f, int n) { int c; if (n < 0) return (FALSE); while (n--) { while (inword() == FALSE) { if (forwchar(FALSE, 1) == FALSE) return (FALSE); } while (inword() != FALSE) { c = lgetc(curwp->w_dotp, curwp->w_doto); if (c >= 'a' && c <= 'z') { c -= 'a' - 'A'; lputc(curwp->w_dotp, curwp->w_doto, c); lchange(WFHARD); } if (forwchar(FALSE, 1) == FALSE) return (FALSE); } } return (TRUE); }
/* * Move the cursor forward by the specified number of words. All of the motion * is done by "forwchar". Error if you try and move beyond the buffer's end. */ int forwword(int f, int n) { if (n < 0) return (backword(f, -n)); while (n--) { #if NFWORD while (inword() != FALSE) { if (forwchar(FALSE, 1) == FALSE) return (FALSE); } #endif while (inword() == FALSE) { if (forwchar(FALSE, 1) == FALSE) return (FALSE); } #if NFWORD == 0 while (inword() != FALSE) { if (forwchar(FALSE, 1) == FALSE) return (FALSE); } #endif } return(TRUE); }
/* * Move the cursor forward by the specified number of words. As you move * convert characters to lower case. Error if you try and move over the end of * the buffer. Bound to "M-L". */ int lowerword(int f, int n) { register int c; CELL ac; ac.a = 0; if (curbp->b_mode&MDVIEW) /* don't allow this command if */ return(rdonly()); /* we are in read only mode */ if (n < 0) return (FALSE); while (n--) { while (inword() == FALSE) { if (forwchar(FALSE, 1) == FALSE) return (FALSE); } while (inword() != FALSE) { c = lgetc(curwp->w_dotp, curwp->w_doto).c; if (c>='A' && c<='Z') { ac.c (c += 'a'-'A'); lputc(curwp->w_dotp, curwp->w_doto, ac); lchange(WFHARD); } if (forwchar(FALSE, 1) == FALSE) return (FALSE); } } return (TRUE); }
/* * Kill forward by "n" words. Remember the location of dot. Move forward by * the right number of words. Put dot back where it was and issue the kill * command for the right number of characters. Bound to "M-D" */ int delfword(int f, int n) { LINE *dotp; int size, doto; if (n < 0) return (FALSE); dotp = curwp->w_dotp; doto = curwp->w_doto; size = 0; while (n--) { while (inword() != FALSE) { if (forwchar(FALSE, 1) == FALSE) return (FALSE); ++size; } while (inword() == FALSE) { if (forwchar(FALSE, 1) == FALSE) return (FALSE); ++size; } } curwp->w_dotp = dotp; curwp->w_doto = doto; return (ldelete(size, TRUE)); }
/* * Kill backwards by "n" words. Move backwards by the desired number of words, * counting the characters. When dot is finally moved to its resting place, * fire off the kill command. Bound to "M-Rubout" and to "M-Backspace" */ int delbword(int f, int n) { int size; if (n < 0) return (FALSE); if (backchar(FALSE, 1) == FALSE) return (FALSE); size = 0; while (n--) { while (inword() == FALSE) { if (backchar(FALSE, 1) == FALSE) return (FALSE); ++size; } while (inword() != FALSE) { if (backchar(FALSE, 1) == FALSE) return (FALSE); ++size; } } if (forwchar(FALSE, 1) == FALSE) return (FALSE); return (ldelete(size, TRUE)); }
/* go back to the begining of the current paragraph here we look for a * <NL><NL> or <NL><TAB> or <NL><SPACE> combination to delimit the begining of * a paragraph */ int gotobop (int f, int n) { int suc; /* success of last backchar */ if (n < 0) /* the other way.. */ return (gotoeop (f, -n)); while (n-- > 0) { /* for each one asked for */ /* first scan back until we are in a word */ suc = backchar (FALSE, 1); while (!inword () && suc) suc = backchar (FALSE, 1); curwp->w_doto = 0; /* and go to the B-O-Line */ /* and scan back until we hit a <NL><NL> or <NL><TAB> or a <NL><SPACE> */ while (lback (curwp->w_dotp) != curbp->b_linep) if (llength (curwp->w_dotp) != 0 && lgetc (curwp->w_dotp, curwp->w_doto) != TAB && lgetc (curwp->w_dotp, curwp->w_doto) != ' ') curwp->w_dotp = lback (curwp->w_dotp); else break; /* and then forward until we are in a word */ suc = forwchar (FALSE, 1); while (suc && !inword ()) suc = forwchar (FALSE, 1); } curwp->w_flag |= WFMOVE; /* force screen update */ return (TRUE); }
/* * ex_abbr -- :abbreviate [key replacement] * Create an abbreviation or display abbreviations. * * PUBLIC: int ex_abbr __P((SCR *, EXCMD *)); */ int ex_abbr(SCR *sp, EXCMD *cmdp) { CHAR_T *p; size_t len; switch (cmdp->argc) { case 0: if (seq_dump(sp, SEQ_ABBREV, 0) == 0) msgq(sp, M_INFO, "105|No abbreviations to display"); return (0); case 2: break; default: abort(); } /* * Check for illegal characters. * * !!! * Another fun one, historically. See vi/v_ntext.c:txt_abbrev() for * details. The bottom line is that all abbreviations have to end * with a "word" character, because it's the transition from word to * non-word characters that triggers the test for an abbreviation. In * addition, because of the way the test is done, there can't be any * transitions from word to non-word character (or vice-versa) other * than between the next-to-last and last characters of the string, * and there can't be any <blank> characters. Warn the user. */ if (!inword(cmdp->argv[0]->bp[cmdp->argv[0]->len - 1])) { msgq(sp, M_ERR, "106|Abbreviations must end with a \"word\" character"); return (1); } for (p = cmdp->argv[0]->bp; *p != '\0'; ++p) if (ISBLANK((UCHAR_T)p[0])) { msgq(sp, M_ERR, "107|Abbreviations may not contain tabs or spaces"); return (1); } if (cmdp->argv[0]->len > 2) for (p = cmdp->argv[0]->bp, len = cmdp->argv[0]->len - 2; len; --len, ++p) if (inword(p[0]) != inword(p[1])) { msgq(sp, M_ERR, "108|Abbreviations may not mix word/non-word characters, except at the end"); return (1); } if (seq_set(sp, NULL, 0, cmdp->argv[0]->bp, cmdp->argv[0]->len, cmdp->argv[1]->bp, cmdp->argv[1]->len, SEQ_ABBREV, SEQ_USERDEF)) return (1); F_SET(sp->gp, G_ABBREV); return (0); }
/* ARGSUSED */ int delbword(int f, int n) { RSIZE size; int s; if ((s = checkdirty(curbp)) != TRUE) return (s); if (curbp->b_flag & BFREADONLY) { dobeep(); ewprintf("Buffer is read-only"); return (FALSE); } if (n < 0) return (FALSE); /* purge kill buffer */ if ((lastflag & CFKILL) == 0) kdelete(); thisflag |= CFKILL; if (backchar(FFRAND, 1) == FALSE) /* hit buffer start */ return (TRUE); /* one deleted */ size = 1; while (n--) { while (inword() == FALSE) { if (backchar(FFRAND, 1) == FALSE) /* hit buffer start */ goto out; ++size; } while (inword() != FALSE) { if (backchar(FFRAND, 1) == FALSE) /* hit buffer start */ goto out; ++size; } } if (forwchar(FFRAND, 1) == FALSE) return (FALSE); /* undo assumed delete */ --size; out: return (ldelete(size, KBACK)); }
/* * v_curword -- * Get the word (or non-word) the cursor is on. * * PUBLIC: int v_curword __P((SCR *)); */ int v_curword(SCR *sp) { VI_PRIVATE *vip; size_t beg, end, len; int moved, state; CHAR_T *p; if (db_get(sp, sp->lno, DBG_FATAL, &p, &len)) return (1); /* * !!! * Historically, tag commands skipped over any leading whitespace * characters. Make this true in general when using cursor words. * If movement, getting a cursor word implies moving the cursor to * its beginning. Refresh now. * * !!! * Find the beginning/end of the keyword. Keywords are currently * used for cursor-word searching and for tags. Historical vi * only used the word in a tag search from the cursor to the end * of the word, i.e. if the cursor was on the 'b' in " abc ", the * tag was "bc". For consistency, we make cursor word searches * follow the same rule. */ for (moved = 0, beg = sp->cno; beg < len && ISSPACE((UCHAR_T)p[beg]); moved = 1, ++beg); if (beg >= len) { msgq(sp, M_BERR, "212|Cursor not in a word"); return (1); } if (moved) { sp->cno = beg; (void)vs_refresh(sp, 0); } /* Find the end of the word. */ for (state = inword(p[beg]), end = beg; ++end < len && state == inword(p[end]);); vip = VIP(sp); len = (end - beg); BINC_RETW(sp, vip->keyw, vip->klen, len+1); MEMMOVEW(vip->keyw, p + beg, len); vip->keyw[len] = '\0'; /* XXX */ return (0); }
/* ARGSUSED */ int capword(int f, int n) { int c, s; RSIZE size; if ((s = checkdirty(curbp)) != TRUE) return (s); if (curbp->b_flag & BFREADONLY) { dobeep(); ewprintf("Buffer is read-only"); return (FALSE); } if (n < 0) return (FALSE); while (n--) { while (inword() == FALSE) { if (forwchar(FFRAND, 1) == FALSE) return (TRUE); } size = countfword(); undo_add_change(curwp->w_dotp, curwp->w_doto, size); if (inword() != FALSE) { c = lgetc(curwp->w_dotp, curwp->w_doto); if (ISLOWER(c) != FALSE) { c = TOUPPER(c); lputc(curwp->w_dotp, curwp->w_doto, c); lchange(WFFULL); } if (forwchar(FFRAND, 1) == FALSE) return (TRUE); while (inword() != FALSE) { c = lgetc(curwp->w_dotp, curwp->w_doto); if (ISUPPER(c) != FALSE) { c = TOLOWER(c); lputc(curwp->w_dotp, curwp->w_doto, c); lchange(WFFULL); } if (forwchar(FFRAND, 1) == FALSE) return (TRUE); } } } return (TRUE); }
/* ARGSUSED */ int forwword(int f, int n) { if (n < 0) return (backword(f | FFRAND, -n)); while (n--) { while (inword() == FALSE) { if (forwchar(FFRAND, 1) == FALSE) return (TRUE); } while (inword() != FALSE) { if (forwchar(FFRAND, 1) == FALSE) return (TRUE); } } return (TRUE); }
/* ARGSUSED */ int delfword(int f, int n) { RSIZE size; struct line *dotp; int doto; int s; if ((s = checkdirty(curbp)) != TRUE) return (s); if (curbp->b_flag & BFREADONLY) { dobeep(); ewprintf("Buffer is read-only"); return (FALSE); } if (n < 0) return (FALSE); /* purge kill buffer */ if ((lastflag & CFKILL) == 0) kdelete(); thisflag |= CFKILL; dotp = curwp->w_dotp; doto = curwp->w_doto; size = 0; while (n--) { while (inword() == FALSE) { if (forwchar(FFRAND, 1) == FALSE) /* hit the end of the buffer */ goto out; ++size; } while (inword() != FALSE) { if (forwchar(FFRAND, 1) == FALSE) /* hit the end of the buffer */ goto out; ++size; } } out: curwp->w_dotp = dotp; curwp->w_doto = doto; return (ldelete(size, KFORW)); }
/* * v_searchw -- [count]^A * Search for the word under the cursor. * * PUBLIC: int v_searchw __P((SCR *, VICMD *)); */ int v_searchw(SCR *sp, VICMD *vp) { size_t blen, len; int rval; CHAR_T *bp, *p; /* An upper bound for the SIZE of the RE under construction. */ len = VIP(sp)->klen + MAX(RE_WSTART_LEN, 1) + MAX(RE_WSTOP_LEN, RE_NWSTOP_LEN); GET_SPACE_RETW(sp, bp, blen, len); p = bp; /* Only the first character can be non-word, see v_curword. */ if (inword(VIP(sp)->keyw[0])) { MEMCPY(p, RE_WSTART, RE_WSTART_LEN); p += RE_WSTART_LEN; } else if (is_special(VIP(sp)->keyw[0])) { MEMCPY(p, L("\\"), 1); p += 1; } MEMCPY(p, VIP(sp)->keyw, VIP(sp)->klen); p += VIP(sp)->klen; if (inword(p[-1])) { MEMCPY(p, RE_WSTOP, RE_WSTOP_LEN); p += RE_WSTOP_LEN; } else { /* * The keyword is a single non-word character. * We want it to stay the same when typing ^A several times * in a row, just the way the other cases behave. */ MEMCPY(p, RE_NWSTOP, RE_NWSTOP_LEN); p += RE_NWSTOP_LEN; } len = p - bp; rval = v_search(sp, vp, bp, len, SEARCH_SET, FORWARD); FREE_SPACEW(sp, bp, blen); return (rval); }
/* * Move the cursor backward by "n" words. All of the details of motion are * performed by the "backchar" and "forwchar" routines. Error if you try to * move beyond the buffers. */ int backword(int f, int n) { if (n < 0) return (forwword(f, -n)); if (backchar_no_header_editor(FALSE, 1) == FALSE) return (FALSE); while (n--) { while (inword() == FALSE) { if (backchar_no_header_editor(FALSE, 1) == FALSE) return (FALSE); } while (inword() != FALSE) { if (backchar_no_header_editor(FALSE, 1) == FALSE) return (FALSE); } } return (forwchar(FALSE, 1)); }
/* * Kill forward by "n" words. Remember the location of dot. Move forward by * the right number of words. Put dot back where it was and issue the kill * command for the right number of characters. Bound to "M-D". */ int delfword(int f, int n) { register long size; register LINE *dotp; register int doto; if (curbp->b_mode&MDVIEW) /* don't allow this command if */ return(rdonly()); /* we are in read only mode */ if (n < 0) return (FALSE); dotp = curwp->w_dotp; doto = curwp->w_doto; size = 0L; while (n--) { #if NFWORD while (inword() != FALSE) { if (forwchar(FALSE,1) == FALSE) return(FALSE); ++size; } #endif while (inword() == FALSE) { if (forwchar(FALSE, 1) == FALSE) return (FALSE); ++size; } #if NFWORD == 0 while (inword() != FALSE) { if (forwchar(FALSE, 1) == FALSE) return (FALSE); ++size; } #endif } curwp->w_dotp = dotp; curwp->w_doto = doto; return (ldelete(size, kinsert)); }
/* * v_searchw -- [count]^A * Search for the word under the cursor. * * PUBLIC: int v_searchw __P((SCR *, VICMD *)); */ int v_searchw(SCR *sp, VICMD *vp) { size_t blen, len; int rval; CHAR_T *bp, *p; len = VIP(sp)->klen + MAX(RE_WSTART_LEN, 1) + MAX(RE_WSTOP_LEN, RE_NWSTOP_LEN); GET_SPACE_RETW(sp, bp, blen, len); p = bp; /* Only the first character can be non-word, see v_curword. */ if (inword(VIP(sp)->keyw[0])) p = MEMPCPY(p, RE_WSTART, RE_WSTART_LEN); else if (is_especial(VIP(sp)->keyw[0])) p = MEMPCPY(p, L("\\"), 1); p = MEMPCPY(p, VIP(sp)->keyw, VIP(sp)->klen); if (inword(p[-1])) p = MEMPCPY(p, RE_WSTOP, RE_WSTOP_LEN); else /* * The keyword is a single non-word character. * We want it to stay the same when typing ^A several times * in a row, just the way the other cases behave. */ p = MEMPCPY(p, RE_NWSTOP, RE_NWSTOP_LEN); len = p - bp; rval = v_search(sp, vp, bp, len, SEARCH_SET | SEARCH_EXTEND, FORWARD); FREE_SPACEW(sp, bp, blen); return (rval); }
/* ARGSUSED */ int gotobop(int f, int n) { /* the other way... */ if (n < 0) return (gotoeop(f, -n)); while (n-- > 0) { /* first scan back until we are in a word */ while (backchar(FFRAND, 1) && inword() == 0); /* and go to the B-O-Line */ curwp->w_doto = 0; /* * and scan back until we hit a <NL><SP> <NL><TAB> or * <NL><NL> */ while (lback(curwp->w_dotp) != curbp->b_headp) if (llength(lback(curwp->w_dotp)) && lgetc(curwp->w_dotp, 0) != ' ' && lgetc(curwp->w_dotp, 0) != '.' && lgetc(curwp->w_dotp, 0) != '\t') curwp->w_dotp = lback(curwp->w_dotp); else { if (llength(lback(curwp->w_dotp)) && lgetc(curwp->w_dotp, 0) == '.') { curwp->w_dotp = lforw(curwp->w_dotp); if (curwp->w_dotp == curbp->b_headp) { /* * beyond end of buffer, * cleanup time */ curwp->w_dotp = lback(curwp->w_dotp); curwp->w_doto = llength(curwp->w_dotp); } } break; } } /* force screen update */ curwp->w_rflag |= WFMOVE; return (TRUE); }
/* * Count characters in word, from current position */ RSIZE countfword() { RSIZE size; struct line *dotp; int doto; dotp = curwp->w_dotp; doto = curwp->w_doto; size = 0; while (inword() != FALSE) { if (forwchar(FFRAND, 1) == FALSE) /* hit the end of the buffer */ goto out; ++size; } out: curwp->w_dotp = dotp; curwp->w_doto = doto; return (size); }
/* * Go forward to the end of the current paragraph. * We look for a <NL><NL> or <NL><TAB> or <NL><SPACE> * or <NL>@ or <NL>. (scribe and nroff commands) * combination to delimit the begining of a paragraph. */ int gotoeop (f, n, k) { register int c; /* first character in current line */ if (n < 0) /* the other way... */ return (gotobop (f, -n, KRANDOM)); while (n-- > 0) { /* for each one asked for */ /* Find the first word on/after the current line */ curwp->w_dot.o = 0; while (forwchar (FALSE, 1, KRANDOM)) if (inword ()) break; curwp->w_dot.o = 0; curwp->w_dot.p = lforw (curwp->w_dot.p); /* Scan forward until we hit a paragraph delimiter as * described above. */ while (curwp->w_dot.p != curbp->b_linep) { if (llength (curwp->w_dot.p) == 0) break; c = lgetc (curwp->w_dot.p, 0); if (c == ' ' || c == '\t' || c == '@' || c == '.') break; else curwp->w_dot.p = lforw (curwp->w_dot.p); } } if (curwp->w_dot.p == curbp->b_linep) /* at end of buffer? */ backchar (FALSE, 1, KRANDOM); /* back up to prev line */ curwp->w_flag |= WFMOVE; /* force screen update */ return (TRUE); }
/* * Go back to the begining of the current paragraph. * We look for a <NL><NL> or <NL><TAB> or <NL><SPACE> * or <NL>@ or <NL>. (scribe and nroff commands) * combination to delimit the begining of a paragraph. */ int gotobop (int f, int n, int k) { register int c; /* first character in current line */ register LINE *prev; /* previous line */ if (n < 0) /* the other way... */ return (gotoeop (f, -n, KRANDOM)); while (n-- > 0) { /* for each one asked for */ /* first scan back until we are in a word */ while (backchar (FALSE, 1, KRANDOM)) if (inword ()) break; curwp->w_dot.o = 0; /* and go to the B-O-Line */ /* and scan back until we hit a paragraph delimiter as * described above. */ while ((prev = lback (curwp->w_dot.p)) != curbp->b_linep) { if (llength (prev) == 0) break; c = lgetc (curwp->w_dot.p, 0); if (c == ' ' || c == '\t') break; c = lgetc (prev, 0); if (c == '@' || c == '.') break; else curwp->w_dot.p = prev; } } curwp->w_flag |= WFMOVE; /* force screen update */ return TRUE; }
/* ARGSUSED */ int gotoeop(int f, int n) { /* the other way... */ if (n < 0) return (gotobop(f, -n)); /* for each one asked for */ while (n-- > 0) { /* Find the first word on/after the current line */ curwp->w_doto = 0; while (forwchar(FFRAND, 1) && inword() == 0); curwp->w_doto = 0; curwp->w_dotp = lforw(curwp->w_dotp); /* and scan forword until we hit a <NL><SP> or ... */ while (curwp->w_dotp != curbp->b_headp) { if (llength(curwp->w_dotp) && lgetc(curwp->w_dotp, 0) != ' ' && lgetc(curwp->w_dotp, 0) != '.' && lgetc(curwp->w_dotp, 0) != '\t') curwp->w_dotp = lforw(curwp->w_dotp); else break; } if (curwp->w_dotp == curbp->b_headp) { /* beyond end of buffer, cleanup time */ curwp->w_dotp = lback(curwp->w_dotp); curwp->w_doto = llength(curwp->w_dotp); break; } } /* force screen update */ curwp->w_rflag |= WFMOVE; return (TRUE); }
/* set the current selection. Invoked by ioctl() or by kernel code. */ int set_selection(const struct tiocl_selection *sel, struct tty_struct *tty, int user) { int sel_mode, new_sel_start, new_sel_end, spc; char *bp, *obp; int i, ps, pe; unsigned int currcons = fg_console; poke_blanked_console(); { unsigned short xs, ys, xe, ye; if (user) { if (verify_area(VERIFY_READ, sel, sizeof(*sel))) return -EFAULT; __get_user(xs, &sel->xs); __get_user(ys, &sel->ys); __get_user(xe, &sel->xe); __get_user(ye, &sel->ye); __get_user(sel_mode, &sel->sel_mode); } else { xs = sel->xs; /* set selection from kernel */ ys = sel->ys; xe = sel->xe; ye = sel->ye; sel_mode = sel->sel_mode; } xs--; ys--; xe--; ye--; xs = limit(xs, video_num_columns - 1); ys = limit(ys, video_num_lines - 1); xe = limit(xe, video_num_columns - 1); ye = limit(ye, video_num_lines - 1); ps = ys * video_size_row + (xs << 1); pe = ye * video_size_row + (xe << 1); if (sel_mode == TIOCL_SELCLEAR) { /* useful for screendump without selection highlights */ clear_selection(); return 0; } if (mouse_reporting() && (sel_mode & TIOCL_SELMOUSEREPORT)) { mouse_report(tty, sel_mode & TIOCL_SELBUTTONMASK, xs, ys); return 0; } } if (ps > pe) /* make sel_start <= sel_end */ { int tmp = ps; ps = pe; pe = tmp; } if (sel_cons != fg_console) { clear_selection(); sel_cons = fg_console; } switch (sel_mode) { case TIOCL_SELCHAR: /* character-by-character selection */ new_sel_start = ps; new_sel_end = pe; break; case TIOCL_SELWORD: /* word-by-word selection */ spc = isspace(sel_pos(ps)); for (new_sel_start = ps; ; ps -= 2) { if ((spc && !isspace(sel_pos(ps))) || (!spc && !inword(sel_pos(ps)))) break; new_sel_start = ps; if (!(ps % video_size_row)) break; } spc = isspace(sel_pos(pe)); for (new_sel_end = pe; ; pe += 2) { if ((spc && !isspace(sel_pos(pe))) || (!spc && !inword(sel_pos(pe)))) break; new_sel_end = pe; if (!((pe + 2) % video_size_row)) break; } break; case TIOCL_SELLINE: /* line-by-line selection */ new_sel_start = ps - ps % video_size_row; new_sel_end = pe + video_size_row - pe % video_size_row - 2; break; case TIOCL_SELPOINTER: highlight_pointer(pe); return 0; default: return -EINVAL; } /* remove the pointer */ highlight_pointer(-1); /* select to end of line if on trailing space */ if (new_sel_end > new_sel_start && !atedge(new_sel_end, video_size_row) && isspace(sel_pos(new_sel_end))) { for (pe = new_sel_end + 2; ; pe += 2) if (!isspace(sel_pos(pe)) || atedge(pe, video_size_row)) break; if (isspace(sel_pos(pe))) new_sel_end = pe; } if (sel_start == -1) /* no current selection */ highlight(new_sel_start, new_sel_end); else if (new_sel_start == sel_start) { if (new_sel_end == sel_end) /* no action required */ return 0; else if (new_sel_end > sel_end) /* extend to right */ highlight(sel_end + 2, new_sel_end); else /* contract from right */ highlight(new_sel_end + 2, sel_end); } else if (new_sel_end == sel_end) { if (new_sel_start < sel_start) /* extend to left */ highlight(new_sel_start, sel_start - 2); else /* contract from left */ highlight(sel_start, new_sel_start - 2); } else /* some other case; start selection from scratch */ { clear_selection(); highlight(new_sel_start, new_sel_end); } sel_start = new_sel_start; sel_end = new_sel_end; /* Allocate a new buffer before freeing the old one ... */ bp = kmalloc((sel_end-sel_start)/2+1, GFP_KERNEL); if (!bp) { printk(KERN_WARNING "selection: kmalloc() failed\n"); clear_selection(); return -ENOMEM; } if (sel_buffer) kfree(sel_buffer); sel_buffer = bp; obp = bp; for (i = sel_start; i <= sel_end; i += 2) { *bp = sel_pos(i); if (!isspace(*bp++)) obp = bp; if (! ((i + 2) % video_size_row)) { /* strip trailing blanks from line and add newline, unless non-space at end of line. */ if (obp != bp) { bp = obp; *bp++ = '\r'; } obp = bp; } } sel_buffer_lth = bp - sel_buffer; return 0; }
/* * bword -- * Move backward by words. */ static int bword(SCR *sp, VICMD *vp, enum which type) { enum { INWORD, NOTWORD } state; VCS cs; u_long cnt; int nmw, omw; cnt = F_ISSET(vp, VC_C1SET) ? vp->count : 1; cs.cs_lno = vp->m_start.lno; cs.cs_cno = vp->m_start.cno; if (cs_init(sp, &cs)) return (1); /* * !!! * If in whitespace, or the previous character is whitespace, move * past it. (This doesn't count as a word move.) Stay at the * character before the current one, it sets word "state" for the * 'b' command. */ if (cs.cs_flags == 0 && !ISBLANK2(cs.cs_ch)) { if (cs_prev(sp, &cs)) return (1); if (cs.cs_flags == 0 && !ISBLANK2(cs.cs_ch)) goto start; } if (cs_bblank(sp, &cs)) return (1); /* * Cyclically move to the beginning of the previous word -- this * involves skipping over word characters and then any trailing * non-word characters. Note, for the 'b' command, the definition * of a word keeps switching. */ start: if (type == BIGWORD) while (cnt--) { nmw = ISMULTIWIDTH(sp, cs.cs_ch); for (;;) { omw = nmw; if (cs_prev(sp, &cs)) return (1); if (cs.cs_flags == CS_SOF) goto ret; if (cs.cs_flags != 0 || ISBLANK2(cs.cs_ch) || (nmw = ISMULTIWIDTH(sp, cs.cs_ch)) != omw) break; } /* * When we reach the end of the word before the last * word, we're done. If we changed state, move forward * one to the end of the next word. */ if (cnt == 0) { if (cs.cs_flags == 0 && cs_next(sp, &cs)) return (1); break; } /* Eat whitespace characters. */ if (nmw == omw && cs_bblank(sp, &cs)) return (1); if (cs.cs_flags == CS_SOF) goto ret; } else while (cnt--) { state = cs.cs_flags == 0 && inword(cs.cs_ch) ? INWORD : NOTWORD; nmw = ISMULTIWIDTH(sp, cs.cs_ch); for (;;) { omw = nmw; if (cs_prev(sp, &cs)) return (1); if (cs.cs_flags == CS_SOF) goto ret; if (cs.cs_flags != 0 || ISBLANK2(cs.cs_ch) || (nmw = ISMULTIWIDTH(sp, cs.cs_ch)) != omw) break; if (state == INWORD) { if (!inword(cs.cs_ch)) break; } else if (inword(cs.cs_ch)) break; } /* See comment above. */ if (cnt == 0) { if (cs.cs_flags == 0 && cs_next(sp, &cs)) return (1); break; } /* Eat whitespace characters. */ if (cs.cs_flags != 0 || ISBLANK2(cs.cs_ch)) if (cs_bblank(sp, &cs)) return (1); if (cs.cs_flags == CS_SOF) goto ret; } /* If we didn't move, we must be at SOF. */ ret: if (cs.cs_lno == vp->m_start.lno && cs.cs_cno == vp->m_start.cno) { v_sof(sp, &vp->m_start); return (1); } /* Set the end of the range for motion commands. */ vp->m_stop.lno = cs.cs_lno; vp->m_stop.cno = cs.cs_cno; /* * All commands move to the end of the range. Motion commands * adjust the starting point to the character before the current * one. * * !!! * The historic vi didn't get this right -- the `yb' command yanked * the right stuff and even updated the cursor value, but the cursor * was not actually updated on the screen. */ vp->m_final = vp->m_stop; if (ISMOTION(vp)) --vp->m_start.cno; return (0); }
/* * eword -- * Move forward to the end of the word. */ static int eword(SCR *sp, VICMD *vp, enum which type) { enum { INWORD, NOTWORD } state; VCS cs; u_long cnt; int nmw, omw; cnt = F_ISSET(vp, VC_C1SET) ? vp->count : 1; cs.cs_lno = vp->m_start.lno; cs.cs_cno = vp->m_start.cno; if (cs_init(sp, &cs)) return (1); /* * !!! * If in whitespace, or the next character is whitespace, move past * it. (This doesn't count as a word move.) Stay at the character * past the current one, it sets word "state" for the 'e' command. */ if (cs.cs_flags == 0 && !ISBLANK2(cs.cs_ch)) { if (cs_next(sp, &cs)) return (1); if (cs.cs_flags == 0 && !ISBLANK2(cs.cs_ch)) goto start; } if (cs_fblank(sp, &cs)) return (1); /* * Cyclically move to the next word -- this involves skipping * over word characters and then any trailing non-word characters. * Note, for the 'e' command, the definition of a word keeps * switching. */ start: if (type == BIGWORD) while (cnt--) { nmw = ISMULTIWIDTH(sp, cs.cs_ch); for (;;) { omw = nmw; if (cs_next(sp, &cs)) return (1); if (cs.cs_flags == CS_EOF) goto ret; if (cs.cs_flags != 0 || ISBLANK2(cs.cs_ch) || (nmw = ISMULTIWIDTH(sp, cs.cs_ch)) != omw) break; } /* * When we reach the start of the word after the last * word, we're done. If we changed state, back up one * to the end of the previous word. */ if (cnt == 0) { if (cs.cs_flags == 0 && cs_prev(sp, &cs)) return (1); break; } /* Eat whitespace characters. */ if (nmw == omw && cs_fblank(sp, &cs)) return (1); if (cs.cs_flags == CS_EOF) goto ret; } else while (cnt--) { state = cs.cs_flags == 0 && inword(cs.cs_ch) ? INWORD : NOTWORD; nmw = ISMULTIWIDTH(sp, cs.cs_ch); for (;;) { omw = nmw; if (cs_next(sp, &cs)) return (1); if (cs.cs_flags == CS_EOF) goto ret; if (cs.cs_flags != 0 || ISBLANK2(cs.cs_ch) || (nmw = ISMULTIWIDTH(sp, cs.cs_ch)) != omw) break; if (state == INWORD) { if (!inword(cs.cs_ch)) break; } else if (inword(cs.cs_ch)) break; } /* See comment above. */ if (cnt == 0) { if (cs.cs_flags == 0 && cs_prev(sp, &cs)) return (1); break; } /* Eat whitespace characters. */ if (cs.cs_flags != 0 || ISBLANK2(cs.cs_ch)) if (cs_fblank(sp, &cs)) return (1); if (cs.cs_flags == CS_EOF) goto ret; } /* * If we didn't move, we must be at EOF. * * !!! * That's okay for motion commands, however. */ ret: if (!ISMOTION(vp) && cs.cs_lno == vp->m_start.lno && cs.cs_cno == vp->m_start.cno) { v_eof(sp, &vp->m_start); return (1); } /* Set the end of the range for motion commands. */ vp->m_stop.lno = cs.cs_lno; vp->m_stop.cno = cs.cs_cno; /* * Non-motion commands move to the end of the range. * Delete and yank stay at the start, ignore others. */ vp->m_final = ISMOTION(vp) ? vp->m_start : vp->m_stop; return (0); }
/* * fword -- * Move forward by words. */ static int fword(SCR *sp, VICMD *vp, enum which type) { enum { INWORD, NOTWORD } state; VCS cs; u_long cnt; int nmw, omw; cnt = F_ISSET(vp, VC_C1SET) ? vp->count : 1; cs.cs_lno = vp->m_start.lno; cs.cs_cno = vp->m_start.cno; if (cs_init(sp, &cs)) return (1); /* * If in white-space: * If the count is 1, and it's a change command, we're done. * Else, move to the first non-white-space character, which * counts as a single word move. If it's a motion command, * don't move off the end of the line. */ if (cs.cs_flags == CS_EMP || (cs.cs_flags == 0 && ISBLANK2(cs.cs_ch))) { if (ISMOTION(vp) && cs.cs_flags != CS_EMP && cnt == 1) { if (ISCMD(vp->rkp, 'c')) return (0); if (ISCMD(vp->rkp, 'd') || ISCMD(vp->rkp, 'y')) { if (cs_fspace(sp, &cs)) return (1); goto ret; } } if (cs_fblank(sp, &cs)) return (1); --cnt; } /* * Cyclically move to the next word -- this involves skipping * over word characters and then any trailing non-word characters. * Note, for the 'w' command, the definition of a word keeps * switching. */ if (type == BIGWORD) while (cnt--) { nmw = ISMULTIWIDTH(sp, cs.cs_ch); for (;;) { omw = nmw; if (cs_next(sp, &cs)) return (1); if (cs.cs_flags == CS_EOF) goto ret; if (cs.cs_flags != 0 || ISBLANK2(cs.cs_ch) || (nmw = ISMULTIWIDTH(sp, cs.cs_ch)) != omw) break; } /* * If a motion command and we're at the end of the * last word, we're done. Delete and yank eat any * trailing blanks, but we don't move off the end * of the line regardless. */ if (cnt == 0 && ISMOTION(vp)) { if ((ISCMD(vp->rkp, 'd') || ISCMD(vp->rkp, 'y')) && cs_fspace(sp, &cs)) return (1); break; } /* Eat whitespace characters. */ if (nmw == omw && cs_fblank(sp, &cs)) return (1); if (cs.cs_flags == CS_EOF) goto ret; } else while (cnt--) { state = cs.cs_flags == 0 && inword(cs.cs_ch) ? INWORD : NOTWORD; nmw = ISMULTIWIDTH(sp, cs.cs_ch); for (;;) { omw = nmw; if (cs_next(sp, &cs)) return (1); if (cs.cs_flags == CS_EOF) goto ret; if (cs.cs_flags != 0 || ISBLANK2(cs.cs_ch) || (nmw = ISMULTIWIDTH(sp, cs.cs_ch)) != omw) break; if (state == INWORD) { if (!inword(cs.cs_ch)) break; } else if (inword(cs.cs_ch)) break; } /* See comment above. */ if (cnt == 0 && ISMOTION(vp)) { if ((ISCMD(vp->rkp, 'd') || ISCMD(vp->rkp, 'y')) && cs_fspace(sp, &cs)) return (1); break; } /* Eat whitespace characters. */ if (cs.cs_flags != 0 || ISBLANK2(cs.cs_ch)) if (cs_fblank(sp, &cs)) return (1); if (cs.cs_flags == CS_EOF) goto ret; } /* * If we didn't move, we must be at EOF. * * !!! * That's okay for motion commands, however. */ ret: if (!ISMOTION(vp) && cs.cs_lno == vp->m_start.lno && cs.cs_cno == vp->m_start.cno) { v_eof(sp, &vp->m_start); return (1); } /* Adjust the end of the range for motion commands. */ vp->m_stop.lno = cs.cs_lno; vp->m_stop.cno = cs.cs_cno; if (ISMOTION(vp) && cs.cs_flags == 0) --vp->m_stop.cno; /* * Non-motion commands move to the end of the range. Delete * and yank stay at the start, ignore others. */ vp->m_final = ISMOTION(vp) ? vp->m_start : vp->m_stop; return (0); }
/* * Fill the current paragraph according to the current fill column. */ int fillpara (int f, int n, int k) { register int c; /* current char durring scan */ register int wordlen; /* length of current word */ register int clength; /* position on line during fill */ register int eopflag; /* Are we at the End-Of-Paragraph? */ int firstflag; /* first word? (needs no space) */ int newlength; /* tentative new line length */ int eolflag; /* was at end of line */ LINE *eopline; /* pointer to line just past EOP */ char wbuf[MAXWORD]; /* buffer for current word */ /* Record the pointer to the line just past the * end of the paragraph. */ gotoeop (FALSE, 1, KRANDOM); eopline = curwp->w_dot.p; if (lforw (eopline) == curbp->b_linep) eopline = curbp->b_linep; /* Move to the begining of the paragraph. */ gotobop (FALSE, 1, KRANDOM); /* Skip to the start of the first word in the paragraph, * and set our current column position. */ while (!inword ()) if (forwchar (FALSE, 1, KRANDOM) == FALSE) break; clength = getcolpos () - 1; wordlen = 0; /* scan through lines, filling words */ firstflag = TRUE; eopflag = FALSE; while (!eopflag) { /* get the next character in the paragraph */ if ((eolflag = (curwp->w_dot.o == llength (curwp->w_dot.p))) == TRUE) { c = ' '; if (lforw (curwp->w_dot.p) == eopline) eopflag = TRUE; } else c = lgetc (curwp->w_dot.p, curwp->w_dot.o); /* and then delete it */ if (ldelete (1, FALSE) == FALSE) return (FALSE); /* if not a separator, just add it in */ if (c != ' ' && c != '\t') { if (wordlen < MAXWORD - 1) wbuf[wordlen++] = c; else { /* You lose chars beyond MAXWORD if the word * is to long. I'm to lazy to fix it now; it * just silently truncated the word before, so * I get to feel smug. */ eprintf ("Word too long!"); } } else if (wordlen) { /* calculate tenatitive new length with word added */ newlength = clength + 1 + wordlen; /* if at end of line or at doublespace and previous * character was one of '.','?','!' doublespace here. */ if ((eolflag || curwp->w_dot.o == llength (curwp->w_dot.p) || (c = lgetc (curwp->w_dot.p, curwp->w_dot.o)) == ' ' || c == '\t') && ISEOSP (wbuf[wordlen - 1]) && wordlen < MAXWORD - 1) wbuf[wordlen++] = ' '; /* at a word break with a word waiting */ if (newlength <= fillcol) { /* add word to current line */ if (!firstflag) { linsert (1, ' ', NULLPTR); ++clength; } firstflag = FALSE; } else { if (curwp->w_dot.o > 0 && lgetc (curwp->w_dot.p, curwp->w_dot.o - 1) == ' ') { curwp->w_dot.o -= 1; ldelete (1, FALSE); } /* start a new line */ lnewline (); clength = 0; } /* and add the word in in either case */ linsert (wordlen, 0, wbuf); clength += wordlen; wordlen = 0; } } /* and add a last newline for the end of our new paragraph */ lnewline (); /* we realy should wind up where we started, (which is hard to keep * track of) but I think the end of the last line is better than the * begining of the blank line. */ backchar (FALSE, 1, KRANDOM); return (TRUE); }
PASCAL NEAR gotoeop( /* go forword to the end of the current paragraph looking for a member of $paralead or $fmtlead or a blank line to delimit the start of the next paragraph OR A FOLDLINE (MJB: 03-Oct-89), */ int f, int n ) /* default Flag & Numeric argument */ { register int suc; /* success of last backchar */ register int c; /* current character in scan */ register char *sp; /* ptr into character leadin lists */ LINE *startp; if (n < 0) /* the other way...*/ return(gotobop(f, -n)); while (n-- > 0) { /* for each one asked for */ /* first scan forward until we are in a word */ suc = forwchar(FALSE, 1); startp = curwp->w_dotp; while (!inword() && suc && ((curwp->w_dotp->l_type == LNORMAL) || (curwp->w_dotp->l_type == LSOEFOLD))) suc = forwchar(FALSE, 1); /* and go to the B-O-Line */ curwp->w_doto = 0; /* of next line if not at EOF */ if (suc && ((curwp->w_dotp->l_type == LNORMAL) || (curwp->w_dotp->l_type == LSOEFOLD))) /* of next line if not at EOF or fold */ curwp->w_dotp = lforw(curwp->w_dotp); /* scan forward */ while (curwp->w_dotp != curbp->b_linep) { /* at blank line */ if (llength(curwp->w_dotp) == 0 || curwp->w_dotp->l_type != LNORMAL || lgetc(curwp->w_dotp, curwp->w_doto) == TAB || lgetc(curwp->w_dotp, curwp->w_doto) == ' ') break; /* current line start with member of $paralead? */ c = lgetc(curwp->w_dotp, 0); sp = paralead; while (*sp) { if (c == *sp) break; ++sp; } if (c == *sp) break; /* current line start with member of $fmtlead? */ c = lgetc(curwp->w_dotp, 0); sp = fmtlead; while (*sp) { if (c == *sp) break; ++sp; } if (c == *sp) break; /* forward one line... */ curwp->w_dotp = lforw(curwp->w_dotp); } /* and then backward until we are in a word */ /* don't do anything if fold line, just goto the EOL */ if (curwp->w_dotp->l_type == LNORMAL) { suc = backchar(FALSE, 1); while (suc && !inword()) suc = backchar(FALSE, 1); } /* goto end of line, unless LSOFOLD beyond start point */ if ((curwp->w_dotp->l_type == LSOFOLD) && (curwp->w_dotp != startp)) curwp->w_doto = 0; else curwp->w_doto = llength(curwp->w_dotp); /* and to the EOL */ } curwp->w_flag |= WFMOVE; /* force screen update */ return(TRUE); }
/* set the current selection. Invoked by ioctl() or by kernel code. */ int set_selection(const unsigned long arg, struct tty_struct *tty, int user) { int sel_mode, new_sel_start, new_sel_end, spc; char *bp, *obp; int i, ps, pe; do_unblank_screen(); { unsigned short *args, xs, ys, xe, ye; args = (unsigned short *)(arg + 1); if (user) { int err; err = verify_area(VERIFY_READ, args, sizeof(short) * 5); if (err) return err; xs = get_user(args++) - 1; ys = get_user(args++) - 1; xe = get_user(args++) - 1; ye = get_user(args++) - 1; sel_mode = get_user(args); } else { xs = *(args++) - 1; /* set selection from kernel */ ys = *(args++) - 1; xe = *(args++) - 1; ye = *(args++) - 1; sel_mode = *args; } xs = limit(xs, video_num_columns - 1); ys = limit(ys, video_num_lines - 1); xe = limit(xe, video_num_columns - 1); ye = limit(ye, video_num_lines - 1); ps = ys * video_size_row + (xs << 1); pe = ye * video_size_row + (xe << 1); if (sel_mode == 4) { /* useful for screendump without selection highlights */ clear_selection(); return 0; } if (mouse_reporting() && (sel_mode & 16)) { mouse_report(tty, sel_mode & 15, xs, ys); return 0; } } if (ps > pe) /* make sel_start <= sel_end */ { int tmp = ps; ps = pe; pe = tmp; } if (sel_cons != fg_console) { clear_selection(); sel_cons = fg_console; } switch (sel_mode) { case 0: /* character-by-character selection */ new_sel_start = ps; new_sel_end = pe; break; case 1: /* word-by-word selection */ spc = isspace(sel_pos(ps)); for (new_sel_start = ps; ; ps -= 2) { if ((spc && !isspace(sel_pos(ps))) || (!spc && !inword(sel_pos(ps)))) break; new_sel_start = ps; if (!(ps % video_size_row)) break; } spc = isspace(sel_pos(pe)); for (new_sel_end = pe; ; pe += 2) { if ((spc && !isspace(sel_pos(pe))) || (!spc && !inword(sel_pos(pe)))) break; new_sel_end = pe; if (!((pe + 2) % video_size_row)) break; } break; case 2: /* line-by-line selection */ new_sel_start = ps - ps % video_size_row; new_sel_end = pe + video_size_row - pe % video_size_row - 2; break; case 3: highlight_pointer(pe); return 0; default: return -EINVAL; } /* remove the pointer */ highlight_pointer(-1); /* select to end of line if on trailing space */ if (new_sel_end > new_sel_start && !atedge(new_sel_end) && isspace(sel_pos(new_sel_end))) { for (pe = new_sel_end + 2; ; pe += 2) if (!isspace(sel_pos(pe)) || atedge(pe)) break; if (isspace(sel_pos(pe))) new_sel_end = pe; } if (sel_start == -1) /* no current selection */ highlight(new_sel_start, new_sel_end); else if (new_sel_start == sel_start) { if (new_sel_end == sel_end) /* no action required */ return 0; else if (new_sel_end > sel_end) /* extend to right */ highlight(sel_end + 2, new_sel_end); else /* contract from right */ highlight(new_sel_end + 2, sel_end); } else if (new_sel_end == sel_end) { if (new_sel_start < sel_start) /* extend to left */ highlight(new_sel_start, sel_start - 2); else /* contract from left */ highlight(sel_start, new_sel_start - 2); } else /* some other case; start selection from scratch */ { clear_selection(); highlight(new_sel_start, new_sel_end); } sel_start = new_sel_start; sel_end = new_sel_end; if (sel_buffer) kfree(sel_buffer); sel_buffer = kmalloc((sel_end-sel_start)/2+1, GFP_KERNEL); if (!sel_buffer) { printk("selection: kmalloc() failed\n"); clear_selection(); return -ENOMEM; } obp = bp = sel_buffer; for (i = sel_start; i <= sel_end; i += 2) { *bp = sel_pos(i); if (!isspace(*bp++)) obp = bp; if (! ((i + 2) % video_size_row)) { /* strip trailing blanks from line and add newline, unless non-space at end of line. */ if (obp != bp) { bp = obp; *bp++ = '\r'; } obp = bp; } } sel_buffer_lth = bp - sel_buffer; return 0; }
/* ARGSUSED */ int fillpara(int f, int n) { int c; /* current char during scan */ int wordlen; /* length of current word */ int clength; /* position on line during fill */ int i; /* index during word copy */ int eopflag; /* Are we at the End-Of-Paragraph? */ int firstflag; /* first word? (needs no space) */ int newlength; /* tentative new line length */ int eolflag; /* was at end of line */ int retval; /* return value */ struct line *eopline; /* pointer to line just past EOP */ char wbuf[MAXWORD]; /* buffer for current word */ if (n == 0) return (TRUE); undo_boundary_enable(FFRAND, 0); /* record the pointer to the line just past the EOP */ (void)gotoeop(FFRAND, 1); if (curwp->w_doto != 0) { /* paragraph ends at end of buffer */ (void)lnewline(); eopline = lforw(curwp->w_dotp); } else eopline = curwp->w_dotp; /* and back top the beginning of the paragraph */ (void)gotobop(FFRAND, 1); /* initialize various info */ while (inword() == 0 && forwchar(FFRAND, 1)); clength = curwp->w_doto; wordlen = 0; /* scan through lines, filling words */ firstflag = TRUE; eopflag = FALSE; while (!eopflag) { /* get the next character in the paragraph */ if ((eolflag = (curwp->w_doto == llength(curwp->w_dotp)))) { c = ' '; if (lforw(curwp->w_dotp) == eopline) eopflag = TRUE; } else c = lgetc(curwp->w_dotp, curwp->w_doto); /* and then delete it */ if (ldelete((RSIZE) 1, KNONE) == FALSE && !eopflag) { retval = FALSE; goto cleanup; } /* if not a separator, just add it in */ if (c != ' ' && c != '\t') { if (wordlen < MAXWORD - 1) wbuf[wordlen++] = c; else { /* * You lose chars beyond MAXWORD if the word * is too long. I'm too lazy to fix it now; it * just silently truncated the word before, * so I get to feel smug. */ ewprintf("Word too long!"); } } else if (wordlen) { /* calculate tentative new length with word added */ newlength = clength + 1 + wordlen; /* * if at end of line or at doublespace and previous * character was one of '.','?','!' doublespace here. * behave the same way if a ')' is preceded by a * [.?!] and followed by a doublespace. */ if (dblspace && (!eopflag && ((eolflag || curwp->w_doto == llength(curwp->w_dotp) || (c = lgetc(curwp->w_dotp, curwp->w_doto)) == ' ' || c == '\t') && (ISEOSP(wbuf[wordlen - 1]) || (wbuf[wordlen - 1] == ')' && wordlen >= 2 && ISEOSP(wbuf[wordlen - 2])))) && wordlen < MAXWORD - 1)) wbuf[wordlen++] = ' '; /* at a word break with a word waiting */ if (newlength <= fillcol) { /* add word to current line */ if (!firstflag) { (void)linsert(1, ' '); ++clength; } firstflag = FALSE; } else { if (curwp->w_doto > 0 && lgetc(curwp->w_dotp, curwp->w_doto - 1) == ' ') { curwp->w_doto -= 1; (void)ldelete((RSIZE) 1, KNONE); } /* start a new line */ (void)lnewline(); clength = 0; } /* and add the word in in either case */ for (i = 0; i < wordlen; i++) { (void)linsert(1, wbuf[i]); ++clength; } wordlen = 0; } } /* and add a last newline for the end of our new paragraph */ (void)lnewline(); /* * We really should wind up where we started, (which is hard to keep * track of) but I think the end of the last line is better than the * beginning of the blank line. */ (void)backchar(FFRAND, 1); retval = TRUE; cleanup: undo_boundary_enable(FFRAND, 1); return (retval); }