119304Speter/*- 219304Speter * Copyright (c) 1992, 1993, 1994 319304Speter * The Regents of the University of California. All rights reserved. 419304Speter * Copyright (c) 1992, 1993, 1994, 1995, 1996 519304Speter * Keith Bostic. All rights reserved. 619304Speter * 719304Speter * See the LICENSE file for redistribution information. 819304Speter */ 919304Speter 1019304Speter#include "config.h" 1119304Speter 1219304Speter#ifndef lint 13254225Speterstatic const char sccsid[] = "$Id: getc.c,v 10.13 2011/12/27 00:49:31 zy Exp $"; 1419304Speter#endif /* not lint */ 1519304Speter 1619304Speter#include <sys/types.h> 1719304Speter#include <sys/queue.h> 1819304Speter#include <sys/time.h> 1919304Speter 2019304Speter#include <bitstring.h> 2119304Speter#include <ctype.h> 2219304Speter#include <limits.h> 2319304Speter#include <stdio.h> 2419304Speter#include <stdlib.h> 2519304Speter 2619304Speter#include "../common/common.h" 2719304Speter#include "vi.h" 2819304Speter 2919304Speter/* 3019304Speter * Character stream routines -- 3119304Speter * These routines return the file a character at a time. There are two 3219304Speter * special cases. First, the end of a line, end of a file, start of a 3319304Speter * file and empty lines are returned as special cases, and no character 3419304Speter * is returned. Second, empty lines include lines that have only white 3519304Speter * space in them, because the vi search functions don't care about white 3619304Speter * space, and this makes it easier for them to be consistent. 3719304Speter */ 3819304Speter 3919304Speter/* 4019304Speter * cs_init -- 4119304Speter * Initialize character stream routines. 4219304Speter * 43281373Sbapt * PUBLIC: int cs_init(SCR *, VCS *); 4419304Speter */ 4519304Speterint 46254225Spetercs_init(SCR *sp, VCS *csp) 4719304Speter{ 4819304Speter int isempty; 4919304Speter 5019304Speter if (db_eget(sp, csp->cs_lno, &csp->cs_bp, &csp->cs_len, &isempty)) { 5119304Speter if (isempty) 5219304Speter msgq(sp, M_BERR, "177|Empty file"); 5319304Speter return (1); 5419304Speter } 5519304Speter if (csp->cs_len == 0 || v_isempty(csp->cs_bp, csp->cs_len)) { 5619304Speter csp->cs_cno = 0; 5719304Speter csp->cs_flags = CS_EMP; 5819304Speter } else { 5919304Speter csp->cs_flags = 0; 6019304Speter csp->cs_ch = csp->cs_bp[csp->cs_cno]; 6119304Speter } 6219304Speter return (0); 6319304Speter} 6419304Speter 6519304Speter/* 6619304Speter * cs_next -- 6719304Speter * Retrieve the next character. 6819304Speter * 69281373Sbapt * PUBLIC: int cs_next(SCR *, VCS *); 7019304Speter */ 7119304Speterint 72254225Spetercs_next(SCR *sp, VCS *csp) 7319304Speter{ 74254225Speter CHAR_T *p; 7519304Speter 7619304Speter switch (csp->cs_flags) { 7719304Speter case CS_EMP: /* EMP; get next line. */ 7819304Speter case CS_EOL: /* EOL; get next line. */ 7919304Speter if (db_get(sp, ++csp->cs_lno, 0, &p, &csp->cs_len)) { 8019304Speter --csp->cs_lno; 8119304Speter csp->cs_flags = CS_EOF; 8219304Speter } else { 8319304Speter csp->cs_bp = p; 8419304Speter if (csp->cs_len == 0 || 8519304Speter v_isempty(csp->cs_bp, csp->cs_len)) { 8619304Speter csp->cs_cno = 0; 8719304Speter csp->cs_flags = CS_EMP; 8819304Speter } else { 8919304Speter csp->cs_flags = 0; 9019304Speter csp->cs_ch = csp->cs_bp[csp->cs_cno = 0]; 9119304Speter } 9219304Speter } 9319304Speter break; 9419304Speter case 0: 9519304Speter if (csp->cs_cno == csp->cs_len - 1) 9619304Speter csp->cs_flags = CS_EOL; 9719304Speter else 9819304Speter csp->cs_ch = csp->cs_bp[++csp->cs_cno]; 9919304Speter break; 10019304Speter case CS_EOF: /* EOF. */ 10119304Speter break; 10219304Speter default: 10319304Speter abort(); 10419304Speter /* NOTREACHED */ 10519304Speter } 10619304Speter return (0); 10719304Speter} 10819304Speter 10919304Speter/* 11019304Speter * cs_fspace -- 11119304Speter * If on a space, eat forward until something other than a 11219304Speter * whitespace character. 11319304Speter * 11419304Speter * XXX 11519304Speter * Semantics of checking the current character were coded for the fword() 11619304Speter * function -- once the other word routines are converted, they may have 11719304Speter * to change. 11819304Speter * 119281373Sbapt * PUBLIC: int cs_fspace(SCR *, VCS *); 12019304Speter */ 12119304Speterint 122254225Spetercs_fspace(SCR *sp, VCS *csp) 12319304Speter{ 124254225Speter if (csp->cs_flags != 0 || !ISBLANK(csp->cs_ch)) 12519304Speter return (0); 12619304Speter for (;;) { 12719304Speter if (cs_next(sp, csp)) 12819304Speter return (1); 129254225Speter if (csp->cs_flags != 0 || !ISBLANK(csp->cs_ch)) 13019304Speter break; 13119304Speter } 13219304Speter return (0); 13319304Speter} 13419304Speter 13519304Speter/* 13619304Speter * cs_fblank -- 13719304Speter * Eat forward to the next non-whitespace character. 13819304Speter * 139281373Sbapt * PUBLIC: int cs_fblank(SCR *, VCS *); 14019304Speter */ 14119304Speterint 142254225Spetercs_fblank(SCR *sp, VCS *csp) 14319304Speter{ 14419304Speter for (;;) { 14519304Speter if (cs_next(sp, csp)) 14619304Speter return (1); 14719304Speter if (csp->cs_flags == CS_EOL || csp->cs_flags == CS_EMP || 148254225Speter (csp->cs_flags == 0 && ISBLANK(csp->cs_ch))) 14919304Speter continue; 15019304Speter break; 15119304Speter } 15219304Speter return (0); 15319304Speter} 15419304Speter 15519304Speter/* 15619304Speter * cs_prev -- 15719304Speter * Retrieve the previous character. 15819304Speter * 159281373Sbapt * PUBLIC: int cs_prev(SCR *, VCS *); 16019304Speter */ 16119304Speterint 162254225Spetercs_prev(SCR *sp, VCS *csp) 16319304Speter{ 16419304Speter switch (csp->cs_flags) { 16519304Speter case CS_EMP: /* EMP; get previous line. */ 16619304Speter case CS_EOL: /* EOL; get previous line. */ 16719304Speter if (csp->cs_lno == 1) { /* SOF. */ 16819304Speter csp->cs_flags = CS_SOF; 16919304Speter break; 17019304Speter } 17119304Speter if (db_get(sp, /* The line should exist. */ 17219304Speter --csp->cs_lno, DBG_FATAL, &csp->cs_bp, &csp->cs_len)) { 17319304Speter ++csp->cs_lno; 17419304Speter return (1); 17519304Speter } 17619304Speter if (csp->cs_len == 0 || v_isempty(csp->cs_bp, csp->cs_len)) { 17719304Speter csp->cs_cno = 0; 17819304Speter csp->cs_flags = CS_EMP; 17919304Speter } else { 18019304Speter csp->cs_flags = 0; 18119304Speter csp->cs_cno = csp->cs_len - 1; 18219304Speter csp->cs_ch = csp->cs_bp[csp->cs_cno]; 18319304Speter } 18419304Speter break; 18519304Speter case CS_EOF: /* EOF: get previous char. */ 18619304Speter case 0: 18719304Speter if (csp->cs_cno == 0) 18819304Speter if (csp->cs_lno == 1) 18919304Speter csp->cs_flags = CS_SOF; 19019304Speter else 19119304Speter csp->cs_flags = CS_EOL; 19219304Speter else 19319304Speter csp->cs_ch = csp->cs_bp[--csp->cs_cno]; 19419304Speter break; 19519304Speter case CS_SOF: /* SOF. */ 19619304Speter break; 19719304Speter default: 19819304Speter abort(); 19919304Speter /* NOTREACHED */ 20019304Speter } 20119304Speter return (0); 20219304Speter} 20319304Speter 20419304Speter/* 20519304Speter * cs_bblank -- 20619304Speter * Eat backward to the next non-whitespace character. 20719304Speter * 208281373Sbapt * PUBLIC: int cs_bblank(SCR *, VCS *); 20919304Speter */ 21019304Speterint 211254225Spetercs_bblank(SCR *sp, VCS *csp) 21219304Speter{ 21319304Speter for (;;) { 21419304Speter if (cs_prev(sp, csp)) 21519304Speter return (1); 21619304Speter if (csp->cs_flags == CS_EOL || csp->cs_flags == CS_EMP || 217254225Speter (csp->cs_flags == 0 && ISBLANK(csp->cs_ch))) 21819304Speter continue; 21919304Speter break; 22019304Speter } 22119304Speter return (0); 22219304Speter} 223