1 /* @(#)edit.c	1.29 18/09/16 Copyright 1984-2018 J. Schilling */
2 #include <schily/mconfig.h>
3 #ifndef lint
4 static	UConst char sccsid[] =
5 	"@(#)edit.c	1.29 18/09/16 Copyright 1984-2018 J. Schilling";
6 #endif
7 /*
8  *	Main editing loop of VED (Visual EDitor)
9  *
10  *	Copyright (c) 1984-2018 J. Schilling
11  */
12 /*
13  * The contents of this file are subject to the terms of the
14  * Common Development and Distribution License, Version 1.0 only
15  * (the "License").  You may not use this file except in compliance
16  * with the License.
17  *
18  * See the file CDDL.Schily.txt in this distribution for details.
19  * A copy of the CDDL is also available via the Internet at
20  * http://www.opensource.org/licenses/cddl1.txt
21  *
22  * When distributing Covered Code, include this CDDL HEADER in each
23  * file and include the License file CDDL.Schily.txt from this distribution.
24  */
25 
26 #include "ved.h"
27 #include <schily/signal.h>
28 #include <schily/setjmp.h>
29 #include <schily/jmpdefs.h>
30 
31 extern	void	(*nctab[NCTAB])	__PR((ewin_t *));
32 extern	void	(*chartab[NCTAB][256])	__PR((ewin_t *));
33 extern	int	ctabidx;	/* The table idx where we take commands from */
34 
35 LOCAL	sigjmp_buf	jmp;
36 extern	sigjmps_t	*sjp;
37 
38 extern	long	charstyped;
39 
40 LOCAL	void	intr		__PR((int sig));
41 EXPORT	void	edit		__PR((ewin_t *wp));
42 
43 /* ARGSUSED */
44 LOCAL void
intr(sig)45 intr(sig)
46 	int	sig;
47 {
48 	signal(SIGINT, intr);
49 	if (sjp)
50 		siglongjmp(sjp->jb, TRUE);
51 	else
52 		siglongjmp(jmp, TRUE);
53 }
54 
55 EXPORT void
edit(wp)56 edit(wp)
57 	ewin_t	*wp;
58 {
59 	register void	(*f)			__PR((ewin_t *));
60 	register echar_t c;
61 	register Uchar	cc;		/* Used to index the binding arrays */
62 	register epos_t sdot;
63 		BOOL	in_command = FALSE;
64 
65 	extern	 int	intrchar;
66 	extern	 BOOL	interrupted;
67 
68 	vedstartstats();
69 
70 	sdot = wp->dot;
71 	if (sigsetjmp(jmp, 1)) {
72 		if (in_command) {
73 /*			dot = sdot;*/
74 			update(wp);
75 			writemsg(wp, C NULL);
76 			writenum(wp, wp->curnum = wp->number = 1L);
77 			abortmsg(wp);
78 			flush();
79 		} else {
80 			if (intrchar > 0)
81 				interrupted++;
82 		}
83 	} else {
84 		signal(SIGINT, intr);
85 	}
86 	for (;;) {
87 		sdot = wp->dot;
88 		in_command = FALSE;
89 		/*
90 		 * We never come here with c == EOF
91 		 */
92 		c = gchar(wp);
93 		charstyped++;
94 /*cdbg("got: '%c' (%d)", c, c);*/
95 		in_command = TRUE;
96 		cc = c & 0xFF;
97 		wp->lastch = c;
98 
99 		/*
100 		 * Choose the right function to call for the current character.
101 		 * Refresh the system line or parts of it if needed.
102 		 */
103 		if (c != cc) {
104 			/*
105 			 * Handle chars outside the single byte range as normal
106 			 */
107 			f = nctab[ctabidx];
108 		} else {
109 			f = chartab[ctabidx][cc];
110 		}
111 		ctabidx = CTAB;
112 		refreshsysline(wp);
113 
114 		/*
115 		 * Call the function bound to the current character and update
116 		 * the display if needed.
117 		 * esccmd/altcmd/altesccmd may be set here.
118 		 */
119 		(*f)(wp);
120 		update(wp);
121 
122 		/*
123 		 * We want to keep the cursor on the same column if possible
124 		 * but shorter lines may force us to move the cursor to the
125 		 * left. To achieve this, we keep a remembered copy of the
126 		 * actual column that is not updated on corsur up/down
127 		 * movement.
128 		 */
129 		if ((wp->eflags & COLUPDATE) != 0)
130 			wp->column = cursor.hp;
131 		else
132 			wp->eflags |= COLUPDATE;
133 
134 		/*
135 		 * Make a curnum copy of number to allow anyone to modify it.
136 		 * Reset number to 1 except when the last character changed
137 		 * only the state or the last command requested us to save it.
138 		 */
139 		wp->curnum = wp->number;
140 		if (wp->number != 1 && ctabidx == CTAB) {
141 			if ((wp->eflags & SAVENUM) != 0) {
142 				wp->eflags &= ~SAVENUM;
143 			} else {
144 				writenum(wp, wp->curnum = wp->number = 1L);
145 			}
146 		}
147 
148 		/*
149 		 * If KEEPDEL is not set the next delete operation will remove
150 		 * the current content of the delete/rubout buffer first.
151 		 * A delete operation will set DELDONE. We transform this
152 		 * into KEEPDEL if the current command did not only change
153 		 * the state. If the last command did not move the cursor
154 		 * keep the deletions too.
155 		 */
156 		if ((wp->eflags & KEEPDEL) != 0 && sdot == wp->dot)
157 			wp->eflags |= DELDONE;
158 
159 		if ((wp->eflags & (KEEPDEL|DELDONE)) != 0 && ctabidx == CTAB) {
160 			wp->eflags &= ~KEEPDEL;
161 
162 			if ((wp->eflags & DELDONE) != 0)
163 				wp->eflags |= KEEPDEL;
164 
165 			wp->eflags &= ~DELDONE;
166 		}
167 		/*
168 		 * Usually, all deletions are saved into the delete/rubout
169 		 * buffer. However take operations have their own buffer.
170 		 * Set SAVEDEL here to choose standard behavior, take routines
171 		 * will clear it later to prevent wasting the delete buffer.
172 		 */
173 		wp->eflags |= SAVEDEL;
174 
175 		/*
176 		 * Now write out everything that is in the screen buffer.
177 		 */
178 		flush();
179 /*		writeerr("wp, eflags: 0x%X", wp->eflags);*/
180 	}
181 }
182