ex_vops.c revision ec427229eba2c13696d3b36d96afa8f22d364072
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
/* Copyright (c) 1981 Regents of the University of California */
#pragma ident "%Z%%M% %I% %E% SMI"
#include "ex.h"
#include "ex_tty.h"
#include "ex_vis.h"
/*
* This file defines the operation sequences which interface the
* logical changes to the file buffer with the internal and external
* display representations.
*/
/*
* Undo.
*
* Undo is accomplished in two ways. We often for small changes in the
* current line know how (in terms of a change operator) how the change
* occurred. Thus on an intelligent terminal we can undo the operation
* by another such operation, using insert and delete character
* stuff. The pointers vU[AD][12] index the buffer vutmp when this
* is possible and provide the necessary information.
*
* The other case is that the change involved multiple lines or that
* we have moved away from the line or forgotten how the change was
* accomplished. In this case we do a redisplay and hope that the
* low level optimization routines (which don't look for winning
*/
vUndo()
{
/*
* Avoid UU which clobbers ability to do u.
*/
beep();
return;
}
getDOT();
return;
}
if(MB_CUR_MAX > 1)
vsyncCL();
if(MB_CUR_MAX > 1)
vfixcurs();
}
bool show; /* if true update the screen */
{
register int cnt;
register unsigned char *cp;
bool savenote;
int (*OO)();
unsigned multic[MULTI_BYTE_MAX];
int length;
switch (vundkind) {
case VMANYINS:
wcursor = 0;
vsave();
YANKreg('1');
notecnt = 0;
/* fall into ... */
case VMANY:
case VMCHNG:
vsave();
notecnt = 1;
beep();
break;
}
/*
* Undo() call below basically replaces undap1 to undap2-1
* with dol through unddol-1. Hack screen image to
* reflect this replacement.
*/
if (show)
else
undo(1);
killU();
if (show)
break;
}
if (!savenote)
notecnt = 0;
if (show) {
if(MB_CUR_MAX > 1)
if(MB_CUR_MAX > 1)
}
vmcurs = 0;
break;
case VCHNG:
case VCAPU:
if (!show)
break;
doomed = 0;
vsave();
break;
}
/*
* Pseudo insert command.
*/
vprepins();
if(length < 0) {
putoctal = 1;
putoctal = 0;
} else {
}
}
endim();
doomed = 0;
if(MB_CUR_MAX > 1)
vsyncCL();
if(MB_CUR_MAX > 1)
vfixcurs();
break;
case VNONE:
beep();
break;
}
}
/*
* Routine to handle a change inside a macro.
* Fromvis is true if we were called from a visual command (as
* opposed to an ex command). This has nothing to do with being
*/
bool fromvis;
{
unsigned char *savecursor;
unsigned char ch; /* DEBUG */
if (!inopen)
return;
if (!vmacp)
#ifdef UNDOTRACE
if (trace)
#endif
vsave();
#ifdef UNDOTRACE
if (trace)
#endif
switch(vch_mac) {
case VC_NOCHANGE:
break;
case VC_ONECHANGE:
/* Save current state somewhere */
#ifdef UNDOTRACE
vudump("before vmacchng hairy case");
#endif
if (morelines() < 0)
return; /* or could be fatal error */
#ifdef UNDOTRACE
visdump("before vundo");
#endif
/* Restore state as it was at beginning of macro */
vundo(0);
#ifdef UNDOTRACE
visdump("after vundo");
vudump("after vundo");
#endif
/* Do the saveall we should have done then */
saveall();
#ifdef UNDOTRACE
vudump("after saveall");
#endif
/* Restore current state from where saved */
if (more)
/* Arrange that no further undo saving happens within macro */
#ifdef UNDOTRACE
vudump("after vmacchng");
#endif
break;
case VC_NOTINMAC:
case VC_MANYCHANGE:
/* Nothing to do for various reasons. */
break;
}
}
/*
* Initialize undo information before an append.
*/
vnoapp()
{
}
/*
* All the rest of the motion sequences have one or more
* cases to deal with. In the case wdot == 0, operation
* is totally within current line, from cursor to wcursor.
* If wdot is given, but wcursor is 0, then operation affects
* the inclusive line range. The hardest case is when both wdot
* and wcursor are given, then operation affects from line dot at
* cursor to line wdot at wcursor.
*/
/*
* Move is simple, except for moving onto new lines in hardcopy open mode.
*/
vmove()
{
register int cnt;
if (wdot) {
beep();
return;
}
if (cnt)
killU();
return;
}
/*
* When we move onto a new line, save information for U undo.
*/
}
/*
* In hardcopy open, type characters to left of cursor
* on new line, or back cursor up if its to left of where we are.
* In any case if the current line is ``rubbled'' i.e. has trashy
* looking overstrikes on it or \'s from deletes, we reprint
* so it is more comprehensible (and also because we can't work
* if we let it get more out of sync since column() won't work right.
*/
register unsigned char *cp;
if (rubble) {
register int c;
sethard();
c = *cp;
*cp = 0;
*cp = c;
register int length;
char multic[MULTI_BYTE_MAX];
vfixcurs();
if(length == 0)
putchar(' ');
else if(length < 0) {
putoctal = 1;
putoctal = 0;
} else {
}
}
}
}
}
/*
* Delete operator.
*
* Hard case of deleting a range where both wcursor and wdot
* are specified is treated as a special case of change and handled
* by vchange (although vchange may pass it back if it degenerates
* to a full line range delete.)
*/
vdelete(c)
unsigned char c;
{
register unsigned char *cp;
register int i;
if (wdot) {
if (wcursor) {
vchange('d');
return;
}
if ((i = xdw()) < 0)
return;
vputchar('@');
}
notenam = (unsigned char *)"delete";
DEL[0] = 0;
killU();
vcline--;
return;
}
beep();
return;
}
i = vdcMID();
setDEL();
return;
}
if(MB_CUR_MAX > 1)
if(MB_CUR_MAX > 1)
vsyncCL();
}
/*
* Change operator.
*
* In a single line we mark the end of the changed area with '$'.
* On multiple whole lines, we clear the lines first.
* Across lines with both wcursor and wdot given, we delete
* and sync then append (but one operation for undo).
*/
vchange(c)
unsigned char c;
{
register unsigned char *cp;
if (wdot) {
/*
*/
return;
getDOT();
/*
* Not really.
*/
wdot = 0;
if (c == 'd') {
vdelete(c);
return;
}
goto smallchange;
}
/*
* Across line boundaries, but not
* necessarily whole lines.
* Construct what will be left.
*/
*cursor = 0;
getDOT();
beep();
return;
}
/*
* Although this is a delete
* spanning line boundaries, what
* would be left is all white space,
* so take it all away.
*/
wcursor = 0;
getDOT();
op = 0;
notpart('1');
vdelete(c);
return;
}
ind = -1;
} else if (c == 'd' && wcursor == 0) {
vdelete(c);
return;
} else
/*
* We are just substituting text for whole lines,
* so determine the first autoindent.
*/
else
/*
* Delete the lines from the buffer,
* and remember how the partial stuff came about in
* case we are told to put.
*/
setpk();
notenam = (unsigned char *)"delete";
if (c != 'd')
notenam = (unsigned char *)"change";
/*
* If DEL[0] were nonzero, put would put it back
* rather than the deleted lines.
*/
DEL[0] = 0;
if (cnt > 1)
killU();
/*
* Now hack the screen image coordination.
*/
noteit(0);
vcline--;
dot--;
/*
* cursor stays where it is; just splice together the pieces
* of the new line. Otherwise generate a autoindent
* after a S command.
*/
if (ind >= 0) {
} else {
}
/*
* Indicate a change on hardcopies by
* erasing the current line.
*/
}
/*
* Open the line (logically) on the screen, and
* update the screen tail. Unless we are really a delete
* go off and gather up inserted characters.
*/
vcline++;
if (vcline < 0)
vcline = 0;
vsyncCL();
noteit(1);
if (c != 'd') {
if (ind >= 0) {
linebuf[0] = 0;
vfixcurs();
} else {
ind = 0;
}
return;
}
return;
}
/*
* The rest of this is just low level hacking on changes
* of small numbers of characters.
*/
beep();
return;
}
i = vdcMID();
vfixcurs();
/*
* Put out the \\'s indicating changed text in hardcopy,
* or mark the end of the change with $ if not hardcopy.
*/
else {
putchar('$');
i = cindent();
}
/*
* Remember the deleted text for possible put,
* and then prepare and execute the input portion of the change.
*/
setDEL();
/* place cursor at beginning of changing text */
} else {
/*
sethard();
wcursor = cursor;
cursor = linebuf;
vgoto(outline, value(vi_NUMBER) << 3);
vmove();
*/
doomed = 0;
}
prepapp();
}
/*
* Open new lines.
*
* Tricky thing here is slowopen. This causes display updating
* to be held off so that 300 baud dumb terminals don't lose badly.
* This also suppressed counts, which otherwise say how many blank
* space to open up. Counts are also suppressed on intelligent terminals.
* Actually counts are obsoleted, since if your terminal is slow
* you are better off with slowopen.
*/
int c; /* mjm: char --> int */
register int cnt;
{
register int ind = 0, i;
cnt = 1;
vsave();
setLAST();
if (value(vi_AUTOINDENT))
if (c == 'O') {
vcline--;
dot--;
getDOT();
}
if (value(vi_AUTOINDENT)) {
}
killU();
prepapp();
if (FIXUNDO)
c = WBOT + 1;
else {
if (c < ZERO)
c = ZERO;
}
vcline++;
if (value(vi_SLOWOPEN))
/*
* Oh, so lazy!
*/
vscrap();
else
linebuf[0] = 0;
}
/*
* > < and = shift operators.
*
* Note that =, which aligns lisp, is just a ragged sort of shift,
* since it never distributes text between lines.
*/
vshftop()
{
register int cnt;
return;
vcnt = 0;
}
/*
* !.
*
* Filter portions of the buffer through unix commands.
*/
vfilter()
{
register int cnt;
unsigned char *oglobp;
short d;
return;
if (vglobp)
if (readecho('!'))
return;
fixech();
unix0(0, 0);
splitw = 0;
ungetchar(d);
return;
splitw = 0;
notenam = (unsigned char *)"";
/*
* BUG: we shouldn't be depending on what undap2 and undap1 are,
* since we may be inside a macro. What's really wanted is the
* number of lines we read from the filter. However, the mistake
* will be an overestimate so it only results in extra work,
* it shouldn't cause any real mess-ups.
*/
dot--;
vcline--;
}
}
/*
* Xdw exchanges dot and wdot if appropriate and also checks
* that wdot is reasonable. Its name comes from
* xchange dotand wdot
*/
xdw()
{
register unsigned char *cp;
register int cnt;
/*
register int notp = 0;
*/
beep();
return (-1);
}
vsave();
setLAST();
}
/*
* If a region is specified but wcursor is at the beginning
* of the last line, then we move it to be the end of the
* previous line (actually off the end).
*/
wdot--;
getDOT();
wcursor = 0;
else {
getDOT();
}
/*
* Should prepare in caller for possible dot == wdot.
*/
}
if (vreg) {
/*
if (notp)
notpart(vreg);
*/
}
/*
* Kill buffer code. If delete operator is c or d, then save
* the region in numbered buffers.
*
* BUG: This may be somewhat inefficient due
* to the way named buffer are implemented,
* necessitating some optimization.
*/
vreg = 0;
/*
if (notp)
notpart('1');
*/
}
return (cnt);
}
/*
* Routine for vremote to call to implement shifts.
*/
vshift()
{
}
/*
* Replace a single character with the next input character.
* A funny kind of insert.
*/
register int cnt;
{
register int i, c;
register unsigned char *endcurs;
for(i = 1; i <= cnt; i++) {
if(!*endcurs) {
beep();
return;
}
}
/*
* TRANSLATION_NOTE
* "r" is a terse mode message that corresponds to
* "REPLACE 1 CHAR".
* Translated message of "r" must be 1 character (not byte).
* Or, just leave it.
*/
else
if (!vglobp) {
c = getesc();
if (c == 0) {
vshowmode("");
vfixcurs();
return;
}
ungetkey(c);
}
if (FIXUNDO)
prepapp();
setLAST();
}
/*
* Yank.
*
* Yanking to string registers occurs for free (essentially)
* in the routine xdw().
*/
vyankit()
{
register int cnt;
if (wdot) {
return;
setpk();
notenam = (unsigned char *)"yank";
if (FIXUNDO)
DEL[0] = 0;
notecnt = 0;
return;
}
}
/*
* Set pkill variables so a put can
* know how to put back partial text.
* This is necessary because undo needs the complete
* line images to be saved, while a put wants to trim
* the first and last lines. The compromise
* is for put to be more clever.
*/
setpk()
{
if (wcursor) {
}
}