예제 #1
0
/* ARGSUSED */
int
lowerregion(int f, int n)
{
	struct line	*linep;
	struct region	 region;
	int	 loffs, c, s;

	if ((s = checkdirty(curbp)) != TRUE)
		return (s);
	if (curbp->b_flag & BFREADONLY) {
		ewprintf("Buffer is read-only");
		return (FALSE);
	}

	if ((s = getregion(&region)) != TRUE)
		return (s);

	undo_add_change(region.r_linep, region.r_offset, region.r_size);

	lchange(WFFULL);
	linep = region.r_linep;
	loffs = region.r_offset;
	while (region.r_size--) {
		if (loffs == llength(linep)) {
			linep = lforw(linep);
			loffs = 0;
		} else {
			c = lgetc(linep, loffs);
			if (ISUPPER(c) != FALSE)
				lputc(linep, loffs, TOLOWER(c));
			++loffs;
		}
	}
	return (TRUE);
}
예제 #2
0
파일: word.c 프로젝트: SylvestreG/bitrig
/* 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));
}
예제 #3
0
파일: word.c 프로젝트: SylvestreG/bitrig
/* 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);
}
예제 #4
0
파일: word.c 프로젝트: SylvestreG/bitrig
/* 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));
}
예제 #5
0
파일: buffer.c 프로젝트: WizardGed/mg
/* ARGSUSED */
int
togglereadonly(int f, int n)
{
	int s;

	if ((s = checkdirty(curbp)) != TRUE)
		return (s);
	if (!(curbp->b_flag & BFREADONLY))
		curbp->b_flag |= BFREADONLY;
	else {
		curbp->b_flag &= ~BFREADONLY;
		if (curbp->b_flag & BFCHG)
			ewprintf("Warning: Buffer was modified");
	}
	curwp->w_rflag |= WFMODE;

	return (TRUE);
}
예제 #6
0
파일: region.c 프로젝트: SylvestreG/bitrig
/* ARGSUSED */
int
prefixregion(int f, int n)
{
	struct line	*first, *last;
	struct region	 region;
	char	*prefix = prefix_string;
	int	 nline;
	int	 s;

	if ((s = checkdirty(curbp)) != TRUE)
		return (s);
	if (curbp->b_flag & BFREADONLY) {
		dobeep();
		ewprintf("Buffer is read-only");
		return (FALSE);
	}
	if ((f == TRUE) && ((s = setprefix(FFRAND, 1)) != TRUE))
		return (s);

	/* get # of lines to affect */
	if ((s = getregion(&region)) != TRUE)
		return (s);
	first = region.r_linep;
	last = (first == curwp->w_dotp) ? curwp->w_markp : curwp->w_dotp;
	for (nline = 1; first != last; nline++)
		first = lforw(first);

	/* move to beginning of region */
	curwp->w_dotp = region.r_linep;
	curwp->w_doto = region.r_offset;
	curwp->w_dotline = region.r_lineno;

	/* for each line, go to beginning and insert the prefix string */
	while (nline--) {
		(void)gotobol(FFRAND, 1);
		for (prefix = prefix_string; *prefix; prefix++)
			(void)linsert(1, *prefix);
		(void)forwline(FFRAND, 1);
	}
	(void)gotobol(FFRAND, 1);
	return (TRUE);
}
예제 #7
0
int
checkfilesys(const char *fname)
{
	int dosfs;
	struct bootblock boot;
	struct fatEntry *fat = NULL;
	int finish_dosdirsection=0;
	u_int i;
	int mod = 0;
	int ret = 8;

	rdonly = alwaysno;
	if (!preen)
		printf("** %s", fname);

	dosfs = open(fname, rdonly ? O_RDONLY : O_RDWR, 0);
	if (dosfs < 0 && !rdonly) {
		dosfs = open(fname, O_RDONLY, 0);
		if (dosfs >= 0)
			pwarn(" (NO WRITE)\n");
		else if (!preen)
			printf("\n");
		rdonly = 1;
	} else if (!preen)
		printf("\n");

	if (dosfs < 0) {
		perror("Can't open");
		return 8;
	}

	if (readboot(dosfs, &boot) != FSOK) {
		close(dosfs);
		printf("\n");
		return 8;
	}

	if (skipclean && preen && checkdirty(dosfs, &boot)) {
		printf("%s: ", fname);
		printf("FILESYSTEM CLEAN; SKIPPING CHECKS\n");
		ret = 0;
		goto out;
	}

	if (!preen)  {
		if (boot.ValidFat < 0)
			printf("** Phase 1 - Read and Compare FATs\n");
		else
			printf("** Phase 1 - Read FAT\n");
	}

	mod |= readfat(dosfs, &boot, boot.ValidFat >= 0 ? boot.ValidFat : 0, &fat);
	if (mod & FSFATAL) {
		close(dosfs);
		return 8;
	}

	if (boot.ValidFat < 0)
		for (i = 1; i < boot.bpbFATs; i++) {
			struct fatEntry *currentFat;

			mod |= readfat(dosfs, &boot, i, &currentFat);

			if (mod & FSFATAL)
				goto out;

			mod |= comparefat(&boot, fat, currentFat, i);
			free(currentFat);
			if (mod & FSFATAL)
				goto out;
		}

	if (!preen)
		printf("** Phase 2 - Check Cluster Chains\n");

	mod |= checkfat(&boot, fat);
	if (mod & FSFATAL)
		goto out;
	/* delay writing FATs */

	if (!preen)
		printf("** Phase 3 - Checking Directories\n");

	mod |= resetDosDirSection(&boot, fat);
	finish_dosdirsection = 1;
	if (mod & FSFATAL)
		goto out;
	/* delay writing FATs */

	mod |= handleDirTree(dosfs, &boot, fat);
	if (mod & FSFATAL)
		goto out;

	if (!preen)
		printf("** Phase 4 - Checking for Lost Files\n");

	mod |= checklost(dosfs, &boot, fat);
	if (mod & FSFATAL)
		goto out;

	/* now write the FATs */
	if (mod & FSFATMOD) {
		if (ask(1, "Update FATs")) {
			mod |= writefat(dosfs, &boot, fat, mod & FSFIXFAT);
			if (mod & FSFATAL)
				goto out;
		} else
			mod |= FSERROR;
	}

	if (boot.NumBad)
		pwarn("%d files, %d free (%d clusters), %d bad (%d clusters)\n",
		      boot.NumFiles,
		      boot.NumFree * boot.ClusterSize / 1024, boot.NumFree,
		      boot.NumBad * boot.ClusterSize / 1024, boot.NumBad);
	else
		pwarn("%d files, %d free (%d clusters)\n",
		      boot.NumFiles,
		      boot.NumFree * boot.ClusterSize / 1024, boot.NumFree);

	if (mod && (mod & FSERROR) == 0) {
		if (mod & FSDIRTY) {
			if (ask(1, "MARK FILE SYSTEM CLEAN") == 0)
				mod &= ~FSDIRTY;

			if (mod & FSDIRTY) {
				pwarn("MARKING FILE SYSTEM CLEAN\n");
				mod |= writefat(dosfs, &boot, fat, 1);
			} else {
				pwarn("\n***** FILE SYSTEM IS LEFT MARKED AS DIRTY *****\n");
				mod |= FSERROR; /* file system not clean */
			}
		}
	}

	if (mod & (FSFATAL | FSERROR))
		goto out;

	ret = 0;

    out:
	if (finish_dosdirsection)
		finishDosDirSection();
	free(fat);
	close(dosfs);

	if (mod & (FSFATMOD|FSDIRMOD))
		pwarn("\n***** FILE SYSTEM WAS MODIFIED *****\n");

	return ret;
}
예제 #8
0
int
checkfilesys(const char *fname)
{
	int dosfs;
	struct bootblock boot;
	struct fatEntry *fat = NULL;
	int i;
	int mod = 0;
        int quiet = 0;
        int skip_fat_compare = 0;

	rdonly = alwaysno;
	if (!quiet)
		printf("** %s", fname);

	dosfs = open(fname, rdonly ? O_RDONLY : O_RDWR, 0);
	if (dosfs < 0 && !rdonly) {
		xlog_printf(ANDROID_LOG_INFO, FSCK_XLOG_TAG, "dosfs < 0 && !rdonly");
		dosfs = open(fname, O_RDONLY, 0);
		if (dosfs >= 0)
			pwarn(" (NO WRITE)\n");
		else if (!quiet)
			printf("\n");
		rdonly = 1;
	} else if (!quiet)
		printf("\n");

	if (dosfs < 0) {
		perror("Can't open");
		printf("%s() : Cannot open %s\n", __func__, fname) ;
		return 8;
	}

	if (readboot(dosfs, &boot) == FSFATAL) {
		close(dosfs);
		printf("\n");
		return 8;
	}

	if (skipclean && preen && checkdirty(dosfs, &boot)) {
		printf("%s: ", fname);
		printf("FILESYSTEM CLEAN; SKIPPING CHECKS\n");
		close(dosfs);
		return 0;
	}

        if (((boot.FATsecs * boot.BytesPerSec) / 1024) > FAT_COMPARE_MAX_KB) {
			xlog_printf(ANDROID_LOG_INFO, FSCK_XLOG_TAG, " - ((boot.FATsecs * boot.BytesPerSec) / 1024) = %d > FAT_COMPARE_MAX_KB(%d)", 
				((boot.FATsecs * boot.BytesPerSec) / 1024), 
				FAT_COMPARE_MAX_KB
			);		
			xlog_printf(ANDROID_LOG_INFO, FSCK_XLOG_TAG, " - Skip FAT compare!") ;
            skip_fat_compare = 1;
        }

	start_count(&fsck_p1_time) ;
	if (!quiet)  {
                if (skip_fat_compare) 
                        printf("** Phase 1 - Read FAT (compare skipped)\n");
		else if (boot.ValidFat < 0)
			printf("** Phase 1 - Read and Compare FATs\n");
		else
			printf("** Phase 1 - Read FAT\n");
	}

	mod |= readfat(dosfs, &boot, boot.ValidFat >= 0 ? boot.ValidFat : 0, &fat);
	if (mod & FSERROR) {
		printf("FSERROR after readfat()\n");
	}
	if (mod & FSFATAL) {
		printf("\nFatal error during readfat()\n");
		close(dosfs);
		return 8;
	}

	if (!skip_fat_compare && boot.ValidFat < 0)
		for (i = 1; i < (int)boot.FATs; i++) {
			struct fatEntry *currentFat;

			mod |= readfat(dosfs, &boot, i, &currentFat);

			if (mod & FSFATAL) {
				printf("Fatal error during readfat() for comparison\n");
				free(fat);
				(void)close(dosfs);
				return 8;
			}

			mod |= comparefat(&boot, fat, currentFat, i);
			free(currentFat);
			if (mod & FSFATAL) {
				printf("Fatal error during FAT comparison\n");
				free(fat);
				(void)close(dosfs);
				return 8;
			}
		}
	end_count("Phase#1", &fsck_p1_time) ;

	start_count(&fsck_p2_time) ;
	if (!quiet)
		printf("** Phase 2 - Check Cluster Chains\n");

	mod |= checkfat(&boot, fat);
	if (mod & FSERROR) {
		printf("FSERROR after checkfat()\n");
	}
	if (mod & FSFATAL) {
		printf("Fatal error during FAT check\n");
		free(fat);
		(void)close(dosfs);
		return 8;
	}
	end_count("Phase#2", &fsck_p2_time) ;
	
	/* delay writing FATs */
	start_count(&fsck_p3_time) ;
	if (!quiet)
		printf("** Phase 3 - Checking Directories\n");

	mod |= resetDosDirSection(&boot, fat);
	if (mod & FSERROR) {
		printf("FSERROR after resetDosDirSection()\n");
	}
	if (mod & FSFATAL) {
		printf("Fatal error during resetDosDirSection()\n");
		free(fat);
		close(dosfs);
		return 8;
	}
	/* delay writing FATs */

	mod |= handleDirTree(dosfs, &boot, fat);
	if (mod & FSERROR) {
		printf("FSERROR after handleDirTree()\n");
		/* try to recovery again */
		mod &= ~FSERROR;
		mod |= handleDirTree(dosfs, &boot, fat);
	}
	if (mod & FSFATAL) {
		printf("Fatal error during handleDirTree()\n");
		finishDosDirSection();
		free(fat);
		close(dosfs);
		return 8;
	}
	end_count("Phase#3", &fsck_p3_time) ;

	start_count(&fsck_p4_time) ;
	if (!quiet)
		printf("** Phase 4 - Checking for Lost Files\n");

	mod |= checklost(dosfs, &boot, fat);
	if (mod & FSERROR) {
		printf("FSERROR after checklost()\n");
	}
	if (mod & FSFATAL) {
		printf("Fatal error during checklost()\n");
		finishDosDirSection();
		free(fat);
		(void)close(dosfs);
		return 8;
	}
	end_count("Phase#4", &fsck_p4_time) ;

	/* now write the FATs */
	if (mod & FSFATMOD) {
		if (ask(1, "Update FATs")) {
			mod |= writefat(dosfs, &boot, fat, mod & FSFIXFAT);
			if (mod & FSFATAL) {
				printf("Fatal error during writefat()\n");
				finishDosDirSection();
				free(fat);
				(void)close(dosfs);
				return 8;
			}
		} else
			mod |= FSERROR;
	}

	if (boot.NumBad)
		pwarn("%d files, %d free (%d clusters), %d bad (%d clusters)\n",
		      boot.NumFiles,
		      boot.NumFree * boot.ClusterSize / 1024, boot.NumFree,
		      boot.NumBad * boot.ClusterSize / 1024, boot.NumBad);
	else
		pwarn("%d files, %d free (%d clusters)\n",
		      boot.NumFiles,
		      boot.NumFree * boot.ClusterSize / 1024, boot.NumFree);

	if (mod && (mod & FSERROR) == 0) {
		if (mod & FSDIRTY) {
			if (ask(1, "MARK FILE SYSTEM CLEAN") == 0)
				mod &= ~FSDIRTY;

			if (mod & FSDIRTY) {
				pwarn("MARKING FILE SYSTEM CLEAN\n");
				mod |= writefat(dosfs, &boot, fat, 1);
			} else {
				pwarn("\n***** FILE SYSTEM IS LEFT MARKED AS DIRTY *****\n");
				mod |= FSERROR; /* file system not clean */
			}
		}
	}

	finishDosDirSection();
	free(fat);
	(void)close(dosfs);

	if (mod & FSFATAL) {
		pwarn("\n***** FSFATAL *****\n");
		return 8;
	}
	if (mod & FSERROR) {
		pwarn("\n***** FSERROR *****\n");
		return 8;
	}
	if (mod) {
		pwarn("\n***** FILE SYSTEM WAS MODIFIED *****\n");
		return 4; 
	}

	return 0;
}
예제 #9
0
파일: word.c 프로젝트: masahino/mg-mruby
/* ARGSUSED */
int
upperword(int f, int n)
{
	int	c, s;
	RSIZE	size;

	if ((s = checkdirty(curbp)) != TRUE)
		return (s);
	if (curbp->b_flag & BFREADONLY) {
		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);

		while (inword() != FALSE) {
			c = lgetc(curwp->w_dotp, curwp->w_doto);
#ifndef MRUBY
			if (ISLOWER(c) != FALSE) {
				c = TOUPPER(c);
#else
			if (MG_ISLOWER(c) != FALSE) {
				c = MG_TOUPPER(c);
#endif /* !MRUBY */
				lputc(curwp->w_dotp, curwp->w_doto, c);
				lchange(WFFULL);
			}
			if (forwchar(FFRAND, 1) == FALSE)
				return (TRUE);
		}
	}
	return (TRUE);
}

/*
 * Move the cursor forward by the specified number of words.  As you move
 * convert characters to lower case.
 */
/* ARGSUSED */
int
lowerword(int f, int n)
{
	int	c, s;
	RSIZE	size;

	if ((s = checkdirty(curbp)) != TRUE)
		return (s);
	if (curbp->b_flag & BFREADONLY) {
		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);

		while (inword() != FALSE) {
			c = lgetc(curwp->w_dotp, curwp->w_doto);
#ifndef MRUBY
			if (ISUPPER(c) != FALSE) {
				c = TOLOWER(c);
#else
			if (MG_ISUPPER(c) != FALSE) {
				c = MG_TOLOWER(c);
#endif /* !MRUBY */
				lputc(curwp->w_dotp, curwp->w_doto, c);
				lchange(WFFULL);
			}
			if (forwchar(FFRAND, 1) == FALSE)
				return (TRUE);
		}
	}
	return (TRUE);
}

/*
 * Move the cursor forward by the specified number of words.  As you move
 * convert the first character of the word to upper case, and subsequent
 * characters to lower case.  Error if you try to move past the end of the
 * buffer.
 */
/* ARGSUSED */
int
capword(int f, int n)
{
	int	c, s;
	RSIZE	size;

	if ((s = checkdirty(curbp)) != TRUE)
		return (s);
	if (curbp->b_flag & BFREADONLY) {
		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);
#ifndef MRUBY
			if (ISLOWER(c) != FALSE) {
				c = TOUPPER(c);
#else
			if (MG_ISLOWER(c) != FALSE) {
				c = MG_TOUPPER(c);
#endif /* !MRUBY */
				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);
#ifndef MRUBY
				if (ISUPPER(c) != FALSE) {
					c = TOLOWER(c);
#else
				if (MG_ISUPPER(c) != FALSE) {
					c = MG_TOLOWER(c);
#endif /* !MRUBY */
					lputc(curwp->w_dotp, curwp->w_doto, c);
					lchange(WFFULL);
				}
				if (forwchar(FFRAND, 1) == FALSE)
					return (TRUE);
			}
		}
	}
	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);
}


/*
 * Kill forward by "n" words.
 */
/* 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) {
		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));
}

/*
 * Kill backwards by "n" words.  The rules for success and failure are now
 * different, to prevent strange behavior at the start of the buffer.  The
 * command only fails if something goes wrong with the actual delete of the
 * characters.  It is successful even if no characters are deleted, or if you
 * say delete 5 words, and there are only 4 words left.  I considered making
 * the first call to "backchar" special, but decided that that would just be
 * weird. Normally this is bound to "M-Rubout" and to "M-Backspace".
 */
/* ARGSUSED */
int
delbword(int f, int n)
{
	RSIZE	size;
	int s;

	if ((s = checkdirty(curbp)) != TRUE)
		return (s);
	if (curbp->b_flag & BFREADONLY) {
		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));
}