1 /* -*- tab-width: 4 -*-
2  *
3  * Electric(tm) VLSI Design System
4  *
5  * File: usreditpac.c
6  * Point-and-click editor
7  * Written by: Steven M. Rubin, Static Free Software
8  *
9  * Copyright (c) 2000 Static Free Software.
10  *
11  * Electric(tm) is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * Electric(tm) is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with Electric(tm); see the file COPYING.  If not, write to
23  * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
24  * Boston, Mass 02111-1307, USA.
25  *
26  * Static Free Software
27  * 4119 Alpine Road
28  * Portola Valley, California 94028
29  * info@staticfreesoft.com
30  */
31 
32 #include "global.h"
33 #include "egraphics.h"
34 #include "usr.h"
35 #include "usreditpac.h"
36 #include "usrtrack.h"
37 #include "edialogs.h"
38 
39 #define THUMBSIZE   16					/* width of the thumb area in scroll slider */
40 #define HEADERLINES  2					/* number of lines of text at top of editor */
41 #define LEFTINDENT   4					/* space between left edge and text */
42 #define DEFAULTWID   1					/* default number of characters on a line */
43 
44 static INTBIG      us_editpactwid, us_editpacthei;		/* size of a single letter */
45 static INTBIG      us_editpacfont;			/* font size for editor */
46 static CHAR       *us_editpacbuffer = 0;	/* the cut/copy/paste buffer */
47 
48 /* variables for cursor tracking */
49 static WINDOWPART *us_editpaccurrentwin;
50 static INTBIG      us_editpacdeltasofar;
51 static INTBIG      us_editpacinitialthumb;
52 static INTBIG      us_editpacorigcurline, us_editpacorigcurchar;
53 static INTBIG      us_editpacorigendline, us_editpacorigendchar;
54 static INTBIG      us_editpaclastc, us_editpaclastl;
55 
56 /* variables for undo */
57 static INTBIG      us_editpacundooldcurline, us_editpacundooldcurchar;
58 static INTBIG      us_editpacundonewcurline, us_editpacundonewcurchar;
59 static INTBIG      us_editpacundonewendline, us_editpacundonewendchar;
60 static CHAR       *us_editpacundobuffer;
61 static INTBIG      us_editpacundobuffersize = 0;
62 
63 extern GRAPHICS us_ebox, us_menutext, us_menufigs;
64 
65 /* prototypes for local routines */
66 static void    us_editpacredraweditor(WINDOWPART*);
67 static void    us_editpacgotbutton(WINDOWPART*, INTBIG, INTBIG, INTBIG);
68 static BOOLEAN us_editpacclickdown(INTBIG, INTBIG);
69 static BOOLEAN us_editpacdclickdown(INTBIG, INTBIG);
70 static BOOLEAN us_editpacdoclickdown(INTBIG, INTBIG, BOOLEAN);
71 static BOOLEAN us_editpacdownarrow(INTBIG, INTBIG);
72 static BOOLEAN us_editpacuparrow(INTBIG, INTBIG);
73 static BOOLEAN us_editpacdownpage(INTBIG, INTBIG);
74 static BOOLEAN us_editpacuppage(INTBIG, INTBIG);
75 static BOOLEAN us_editpacrightarrow(INTBIG, INTBIG);
76 static BOOLEAN us_editpacleftarrow(INTBIG, INTBIG);
77 static BOOLEAN us_editpacrightpage(INTBIG, INTBIG);
78 static BOOLEAN us_editpacleftpage(INTBIG, INTBIG);
79 static BOOLEAN us_editpacimplementchar(WINDOWPART*, INTSML, INTBIG, BOOLEAN);
80 static void    us_editpacremoveselection(WINDOWPART*);
81 static void    us_editpacredrawscreen(WINDOWPART*);
82 static void    us_editpacdrawsliders(WINDOWPART*);
83 static void    us_editpacdrawhscroll(WINDOWPART*);
84 static void    us_editpacdrawvscroll(WINDOWPART*);
85 static void    us_editpaccleanupline(WINDOWPART*, INTBIG);
86 static void    us_editpacredrawlines(WINDOWPART*);
87 static void    us_editpacsetheader(WINDOWPART*, CHAR*);
88 static void    us_editpacinvertselection(WINDOWPART*);
89 static void    us_editpacdonetyping(EDITOR*);
90 static void    us_editpacamtyping(EDITOR*);
91 static void    us_editpactypeddelete(EDITOR*);
92 static INTBIG  us_editpaccharstocurrent(EDITOR*, INTBIG, INTBIG);
93 static void    us_editpacloadselection(EDITOR*, CHAR*);
94 static void    us_editpaccomputebounds(WINDOWPART*, EDITOR*);
95 static void    us_editpacbeginwork(WINDOWPART*);
96 static void    us_editpacaddmorelines(EDITOR*);
97 static void    us_editpacaddmorechars(EDITOR*, INTBIG, INTBIG);
98 static void    us_editpacmovebox(WINDOWPART*, INTBIG, INTBIG, INTBIG, INTBIG, INTBIG, INTBIG);
99 static void    us_editpacclearbox(WINDOWPART*, INTBIG, INTBIG, INTBIG, INTBIG);
100 static void    us_editpactext(WINDOWPART*, CHAR*, INTBIG, INTBIG);
101 static void    us_editpacbackupposition(EDITOR *e, INTBIG *chr, INTBIG *lne);
102 static void    us_editpacadvanceposition(EDITOR *e, INTBIG *chr, INTBIG *lne);
103 static BOOLEAN us_editpacsinglesearch(WINDOWPART *win, CHAR *str, CHAR *replace, INTBIG bits);
104 static void    us_editpacpanwindow(WINDOWPART *w, INTBIG dx, INTBIG dy);
105 static void    us_editpachthumbtrackingtextcallback(INTBIG delta);
106 static void    us_editpacvthumbtrackingtextcallback(INTBIG delta);
107 static void    us_editpacensurelinevisible(WINDOWPART *win, INTBIG lindex, BOOLEAN showcursor);
108 
109 /******************** ROUTINES IN THE EDITOR TABLE ********************/
110 
111 /*
112  * routine to convert window "oriwin" to a point-and-click text editor.
113  * If "oriwin" is NOWINDOWPART, create a popup window with one line.  The window
114  * header is in "header".  The number of characters and lines are placed in
115  * "chars" and "lines".  Returns the window (NOWINDOWPART if the editor cannot be started).
116  */
us_editpacmakeeditor(WINDOWPART * oriwin,CHAR * header,INTBIG * chars,INTBIG * lines)117 WINDOWPART *us_editpacmakeeditor(WINDOWPART *oriwin, CHAR *header, INTBIG *chars, INTBIG *lines)
118 {
119 	INTBIG x, y, i, xs, ys, swid, shei, pwid;
120 	UINTBIG descript[TEXTDESCRIPTSIZE];
121 	REGISTER EDITOR *e;
122 	REGISTER VARIABLE *var;
123 	REGISTER WINDOWPART *win;
124 
125 	/*
126 	 * the font that is used by the editor is the fixed-width font, TXTEDITOR.
127 	 * This can be changed by setting the variable "USER_textedit_font" on the user tool
128 	 * object.  The value is the point size minus 4 divided by 2 (the value 0 is the
129 	 * default font TXTEDITOR).  For example, to set the font to be 14 points, type:
130 	 *     -var set tool:user.USER_textedit_font 5
131 	 */
132 	us_editpacfont = TXTEDITOR;
133 	var = getval((INTBIG)us_tool, VTOOL, VINTEGER, x_("USER_textedit_font"));
134 	if (var != NOVARIABLE && var->addr >= 4)
135 		us_editpacfont = var->addr;
136 
137 	/* if no window exists, create one as a popup */
138 	win = oriwin;
139 	if (win == NOWINDOWPART)
140 	{
141 		getpaletteparameters(&swid, &shei, &pwid);
142 		if (el_curwindowpart == NOWINDOWPART)
143 		{
144 			x = swid / 2;
145 			y = shei / 2;
146 		} else
147 		{
148 			(void)getxy(&x, &y);
149 			x = applyxscale(el_curwindowpart, x-el_curwindowpart->screenlx) + el_curwindowpart->uselx;
150 			y = applyyscale(el_curwindowpart, y-el_curwindowpart->screenly) + el_curwindowpart->usely;
151 		}
152 
153 		/* create a window that covers the popup */
154 		startobjectchange((INTBIG)us_tool, VTOOL);
155 		win = newwindowpart(x_("popup"), el_curwindowpart);
156 		TDCLEAR(descript);
157 		TDSETSIZE(descript, us_editpacfont);
158 		screensettextinfo(win, NOTECHNOLOGY, descript);
159 		screengettextsize(win, x_("X"), &us_editpactwid, &us_editpacthei);
160 		xs = 400;   ys = us_editpacthei*(HEADERLINES+1)+DISPLAYSLIDERSIZE+4;
161 		win->uselx = maxi(x-xs/2, 0);
162 		win->usehx = mini(win->uselx+xs, swid-1);
163 		win->usely = maxi(y-ys, 0);
164 		win->usehy = mini(win->usely+ys, shei-1);
165 		win->state = (win->state & ~WINDOWTYPE) | POPTEXTWINDOW;
166 	} else
167 	{
168 		/* make sure there is room for at least one line */
169 		if (win->usehy - win->usely - us_editpacthei*HEADERLINES - 1 - DISPLAYSLIDERSIZE < us_editpacthei)
170 			return(NOWINDOWPART);
171 
172 		if ((win->state&WINDOWTYPE) == DISPWINDOW)
173 		{
174 			win->usehx += DISPLAYSLIDERSIZE;
175 			win->usely -= DISPLAYSLIDERSIZE;
176 		}
177 		if ((win->state&WINDOWTYPE) == WAVEFORMWINDOW)
178 		{
179 			win->uselx -= DISPLAYSLIDERSIZE;
180 			win->usely -= DISPLAYSLIDERSIZE;
181 		}
182 		win->state = (win->state & ~(WINDOWTYPE|WINDOWMODE)) | TEXTWINDOW;
183 		TDCLEAR(descript);
184 		TDSETSIZE(descript, us_editpacfont);
185 		screensettextinfo(win, NOTECHNOLOGY, descript);
186 		screengettextsize(win, x_("X"), &us_editpactwid, &us_editpacthei);
187 	}
188 
189 	win->curnodeproto = NONODEPROTO;
190 	win->buttonhandler = us_editpacgotbutton;
191 	win->charhandler = us_editpacgotchar;
192 	win->termhandler = us_editpaceditorterm;
193 	win->redisphandler = us_editpacredraweditor;
194 	win->changehandler = 0;
195 	win->screenlx = win->uselx;   win->screenhx = win->usehx;
196 	win->screenly = win->usely;   win->screenhy = win->usehy;
197 	computewindowscale(win);
198 
199 	/* create a new editor object */
200 	e = us_alloceditor();
201 	if (e == NOEDITOR) return(NOWINDOWPART);
202 	e->state = (e->state & ~(EDITORTYPE|EGRAPHICSOFF|LINESFIXED|TEXTTYPING|TEXTTYPED)) | PACEDITOR;
203 	(void)allocstring(&e->header, header, us_tool->cluster);
204 	e->curline = e->curchar = 0;
205 	e->endline = e->endchar = 0;
206 	e->firstline = 0;
207 	e->horizfactor = 0;
208 	e->linecount = 1;
209 	e->charposition = 0;
210 	us_editpaccomputebounds(win, e);
211 	*chars = e->screenchars;
212 	*lines = e->screenlines;
213 
214 	/* initialize the EDITOR structure */
215 	if ((e->state&EDITORINITED) == 0)
216 	{
217 		/* first time: allocate buffers */
218 		e->state |= EDITORINITED;
219 		e->maxlines = e->screenlines;
220 		if (e->maxlines <= 0) e->maxlines = 1;
221 		e->mostchars = e->screenchars;
222 		e->formerline = (CHAR *)emalloc((e->mostchars+1) * SIZEOFCHAR, us_tool->cluster);
223 		if (e->formerline == 0) ttyputnomemory();
224 		e->textarray = (CHAR **)emalloc((e->maxlines * (sizeof (CHAR *))), us_tool->cluster);
225 		if (e->textarray == 0) ttyputnomemory();
226 		e->maxchars = (INTBIG *)emalloc((e->maxlines * SIZEOFINTBIG), us_tool->cluster);
227 		if (e->maxchars == 0) ttyputnomemory();
228 		for(i=0; i<e->maxlines; i++)
229 		{
230 			e->textarray[i] = (CHAR *)emalloc(DEFAULTWID * SIZEOFCHAR, us_tool->cluster);
231 			if (e->textarray[i] == 0) ttyputnomemory();
232 			e->maxchars[i] = DEFAULTWID;
233 		}
234 	} else
235 	{
236 		/* make sure buffers cover the screen */
237 		while (e->screenlines > e->maxlines) us_editpacaddmorelines(e);
238 	}
239 	for(i=0; i<e->maxlines; i++)
240 		e->textarray[i][0] = 0;
241 	e->formerline[0] = 0;
242 	e->working = 0;
243 	e->dirty = FALSE;
244 
245 	/* now finish initializing window */
246 	win->editor = e;
247 	if (oriwin != NOWINDOWPART)
248 	{
249 		/* clear window and write header */
250 		us_editpacredrawscreen(win);
251 	} else
252 	{
253 		/* finish initializing popup text window */
254 		e->savedbox = screensavebox(win, win->uselx, win->usehx, win->usely, win->usehy);
255 		endobjectchange((INTBIG)us_tool, VTOOL);
256 	}
257 	return(win);
258 }
259 
260 /*
261  * routine to free all memory associated with this module (at exit time)
262  */
us_freeedpacmemory(void)263 void us_freeedpacmemory(void)
264 {
265 	if (us_editpacbuffer != 0) efree(us_editpacbuffer);
266 }
267 
268 /*
269  * routine to free all memory associated with this editor
270  * Called prior to destruction of the window.
271  */
us_editpacterminate(EDITOR * e)272 void us_editpacterminate(EDITOR *e)
273 {
274 	REGISTER INTBIG i;
275 
276 	efree((CHAR *)e->formerline);
277 	for(i=0; i<e->maxlines; i++)
278 		efree((CHAR *)e->textarray[i]);
279 	efree((CHAR *)e->textarray);
280 	efree((CHAR *)e->maxchars);
281 	if (us_editpacundobuffersize > 0)
282 	{
283 		efree(us_editpacundobuffer);
284 		us_editpacundobuffersize = 0;
285 	}
286 }
287 
288 /*
289  * routine to return the total number of valid lines in the edit buffer
290  */
us_editpactotallines(WINDOWPART * win)291 INTBIG us_editpactotallines(WINDOWPART *win)
292 {
293 	REGISTER EDITOR *e;
294 
295 	e = win->editor;
296 	if (e == NOEDITOR) return(0);
297 	return(e->linecount);
298 }
299 
300 /*
301  * routine to get the string on line "lindex" (0 based).  A negative line
302  * returns the current line.  Returns -1 if the index is beyond the file limit
303  */
us_editpacgetline(WINDOWPART * win,INTBIG lindex)304 CHAR *us_editpacgetline(WINDOWPART *win, INTBIG lindex)
305 {
306 	REGISTER EDITOR *e;
307 
308 	e = win->editor;
309 	if (e == NOEDITOR) return(x_(""));
310 	if (lindex < 0) lindex = e->curline;
311 	if (lindex >= e->linecount) return(NOSTRING);
312 	return(e->textarray[lindex]);
313 }
314 
315 /*
316  * routine to add line "str" to the text cell to become line "lindex"
317  */
us_editpacaddline(WINDOWPART * win,INTBIG lindex,CHAR * str)318 void us_editpacaddline(WINDOWPART *win, INTBIG lindex, CHAR *str)
319 {
320 	REGISTER CHAR *pt;
321 	REGISTER INTBIG savedsline, savedschar, savedeline, savedechar;
322 	REGISTER EDITOR *e;
323 	UINTBIG descript[TEXTDESCRIPTSIZE];
324 
325 	e = win->editor;
326 	if (e == NOEDITOR) return;
327 	if ((e->state&EGRAPHICSOFF) == 0)
328 	{
329 		TDCLEAR(descript);
330 		TDSETSIZE(descript, us_editpacfont);
331 		screensettextinfo(win, NOTECHNOLOGY, descript);
332 	}
333 
334 	/* send out any pending changes */
335 	us_editpacshipchanges(win);
336 
337 	/* change selection to the current line */
338 	us_editpacinvertselection(win);
339 	savedschar = e->curchar;   savedsline = e->curline;
340 	savedechar = e->endchar;   savedeline = e->endline;
341 	e->curline = e->endline = lindex;   e->curchar = e->endchar = 0;
342 	us_editpacbeginwork(win);
343 
344 	/* fake the characters */
345 	for(pt = str; *pt != 0; pt++) (void)us_editpacimplementchar(win, *pt, 0, FALSE);
346 	(void)us_editpacimplementchar(win, '\n', 0, FALSE);
347 	e->state &= ~TEXTTYPED;
348 
349 	/* send out pending changes */
350 	us_editpacshipchanges(win);
351 
352 	/* restore selection */
353 	e->curchar = savedschar;   e->curline = savedsline;
354 	e->endchar = savedechar;   e->endline = savedeline;
355 	us_editpacinvertselection(win);
356 	us_editpacbeginwork(win);
357 }
358 
359 /*
360  * routine to replace the line number "lindex" with the string "str".
361  */
us_editpacreplaceline(WINDOWPART * win,INTBIG lindex,CHAR * str)362 void us_editpacreplaceline(WINDOWPART *win, INTBIG lindex, CHAR *str)
363 {
364 	REGISTER CHAR *pt;
365 	REGISTER INTBIG savedsline, savedschar, savedeline, savedechar;
366 	REGISTER EDITOR *e;
367 	UINTBIG descript[TEXTDESCRIPTSIZE];
368 
369 	e = win->editor;
370 	if (e == NOEDITOR) return;
371 	if ((e->state&EGRAPHICSOFF) == 0)
372 	{
373 		TDCLEAR(descript);
374 		TDSETSIZE(descript, us_editpacfont);
375 		screensettextinfo(win, NOTECHNOLOGY, descript);
376 	}
377 
378 	/* send out any pending changes */
379 	us_editpacshipchanges(win);
380 
381 	/* change selection to the current line */
382 	us_editpacinvertselection(win);
383 	savedschar = e->curchar;   savedsline = e->curline;
384 	savedechar = e->endchar;   savedeline = e->endline;
385 	e->curline = e->endline = lindex;
386 	e->curchar = 0;   e->endchar = estrlen(e->textarray[lindex]);
387 	us_editpacbeginwork(win);
388 
389 	/* fake the characters */
390 	for(pt = str; *pt != 0; pt++) (void)us_editpacimplementchar(win, *pt, 0, FALSE);
391 	e->state &= ~TEXTTYPED;
392 
393 	/* send out pending changes */
394 	us_editpacshipchanges(win);
395 
396 	/* restore selection */
397 	e->curchar = savedschar;   e->curline = savedsline;
398 	e->endchar = savedechar;   e->endline = savedeline;
399 	us_editpacinvertselection(win);
400 	us_editpacbeginwork(win);
401 }
402 
403 /*
404  * routine to delete line number "lindex"
405  */
us_editpacdeleteline(WINDOWPART * win,INTBIG lindex)406 void us_editpacdeleteline(WINDOWPART *win, INTBIG lindex)
407 {
408 	REGISTER INTBIG savedsline, savedschar, savedeline, savedechar;
409 	REGISTER EDITOR *e;
410 	UINTBIG descript[TEXTDESCRIPTSIZE];
411 
412 	e = win->editor;
413 	if (e == NOEDITOR) return;
414 	if ((e->state&EGRAPHICSOFF) == 0)
415 	{
416 		TDCLEAR(descript);
417 		TDSETSIZE(descript, us_editpacfont);
418 		screensettextinfo(win, NOTECHNOLOGY, descript);
419 	}
420 
421 	/* send out any pending changes */
422 	us_editpacshipchanges(win);
423 
424 	/* change selection to the current line */
425 	us_editpacinvertselection(win);
426 	savedschar = e->curchar;   savedsline = e->curline;
427 	savedechar = e->endchar;   savedeline = e->endline;
428 	e->curline = lindex;   e->endline = lindex+1;
429 	e->curchar = e->endchar = 0;
430 	us_editpacbeginwork(win);
431 
432 	/* fake the deletion character */
433 	(void)us_editpacimplementchar(win, BACKSPACEKEY, 0, FALSE);
434 	e->state &= ~TEXTTYPED;
435 
436 	/* send out pending changes */
437 	us_editpacshipchanges(win);
438 
439 	/* restore selection */
440 	e->curchar = savedschar;   e->curline = savedsline;
441 	e->endchar = savedechar;   e->endline = savedeline;
442 	us_editpacinvertselection(win);
443 	us_editpacbeginwork(win);
444 }
445 
446 /*
447  * routine to highlight lines "lindex" to "hindex" in the text window
448  */
us_editpachighlightline(WINDOWPART * win,INTBIG lindex,INTBIG hindex)449 void us_editpachighlightline(WINDOWPART *win, INTBIG lindex, INTBIG hindex)
450 {
451 	REGISTER EDITOR *e;
452 	UINTBIG descript[TEXTDESCRIPTSIZE];
453 
454 	e = win->editor;
455 	if (e == NOEDITOR) return;
456 	TDCLEAR(descript);
457 	TDSETSIZE(descript, us_editpacfont);
458 	screensettextinfo(win, NOTECHNOLOGY, descript);
459 	us_editpacinvertselection(win);
460 	e->curline = lindex;
461 	e->curchar = 0;
462 	e->endline = hindex;
463 	e->endchar = estrlen(e->textarray[hindex]);
464 	us_editpacinvertselection(win);
465 	us_editpacbeginwork(win);
466 
467 	/* ensure that line "lindex" is shown in the display */
468 	us_editpacensurelinevisible(win, lindex, TRUE);
469 }
470 
471 /*
472  * Routine to ensure that line "lindex" is visible in the edit window.
473  * If not, the text is shifted.
474  */
us_editpacensurelinevisible(WINDOWPART * win,INTBIG lindex,BOOLEAN showcursor)475 void us_editpacensurelinevisible(WINDOWPART *win, INTBIG lindex, BOOLEAN showcursor)
476 {
477 	REGISTER EDITOR *e;
478 
479 	e = win->editor;
480 	if (e == NOEDITOR) return;
481 	if (lindex-e->firstline >= e->screenlines || lindex < e->firstline)
482 	{
483 		e->firstline = maxi(0, lindex - e->screenlines/2);
484 		us_editpacredrawlines(win);
485 		if (!showcursor) us_editpacinvertselection(win);
486 		if ((win->state&WINDOWTYPE) != POPTEXTWINDOW)
487 			us_editpacdrawvscroll(win);
488 	}
489 }
490 
491 /*
492  * routine to stop the graphic display of changes (for batching)
493  */
us_editpacsuspendgraphics(WINDOWPART * win)494 void us_editpacsuspendgraphics(WINDOWPART *win)
495 {
496 	REGISTER EDITOR *e;
497 
498 	e = win->editor;
499 	if (e == NOEDITOR) return;
500 	e->state |= EGRAPHICSOFF;
501 }
502 
503 /*
504  * routine to restart the graphic display of changes and redisplay (for batching)
505  */
us_editpacresumegraphics(WINDOWPART * win)506 void us_editpacresumegraphics(WINDOWPART *win)
507 {
508 	REGISTER EDITOR *e;
509 	UINTBIG descript[TEXTDESCRIPTSIZE];
510 
511 	e = win->editor;
512 	if (e == NOEDITOR) return;
513 	e->state &= ~EGRAPHICSOFF;
514 	TDCLEAR(descript);
515 	TDSETSIZE(descript, us_editpacfont);
516 	screensettextinfo(win, NOTECHNOLOGY, descript);
517 	us_editpacredrawscreen(win);
518 }
519 
520 /*
521  * routine to write the text file to "file"
522  */
us_editpacwritetextfile(WINDOWPART * win,CHAR * file)523 void us_editpacwritetextfile(WINDOWPART *win, CHAR *file)
524 {
525 	REGISTER EDITOR *e;
526 	REGISTER INTBIG i;
527 	REGISTER FILE *f;
528 	CHAR *truename;
529 
530 	e = win->editor;
531 	if (e == NOEDITOR) return;
532 
533 	/* find the last line */
534 	if (e->linecount <= 0)
535 	{
536 		ttyputerr(_("File is empty"));
537 		return;
538 	}
539 
540 	f = xcreate(file, el_filetypetext, _("Text File"), &truename);
541 	if (f == NULL)
542 	{
543 		if (truename != 0) ttyputerr(_("Cannot write %s"), truename);
544 		return;
545 	}
546 
547 	for(i = 0; i < e->linecount; i++) xprintf(f, x_("%s\n"), e->textarray[i]);
548 	xclose(f);
549 	ttyputmsg(_("%s written"), truename);
550 }
551 
552 /*
553  * routine to read the text file "file"
554  */
us_editpacreadtextfile(WINDOWPART * win,CHAR * file)555 void us_editpacreadtextfile(WINDOWPART *win, CHAR *file)
556 {
557 	REGISTER EDITOR *e;
558 	REGISTER INTBIG i, filelength, charsread;
559 	REGISTER INTBIG c;
560 	REGISTER FILE *f;
561 	UINTBIG descript[TEXTDESCRIPTSIZE];
562 	CHAR *filename;
563 	REGISTER void *infstr, *dia;
564 
565 	e = win->editor;
566 	if (e == NOEDITOR) return;
567 
568 	/* get the file */
569 	f = xopen(file, el_filetypetext, x_(""), &filename);
570 	if (f == NULL)
571 	{
572 		ttyputerr(_("Cannot read %s"), file);
573 		return;
574 	}
575 	filelength = filesize(f);
576 	if (filelength > 0)
577 	{
578 		infstr = initinfstr();
579 		formatinfstr(infstr, _("Reading %s..."), file);
580 		dia = DiaInitProgress(returninfstr(infstr), 0);
581 		if (dia == 0)
582 		{
583 			xclose(f);
584 			return;
585 		}
586 		DiaSetProgress(dia, 1, filelength);
587 	} else
588 		ttyputmsg(_("Reading %s"), file);
589 
590 	e->state |= EGRAPHICSOFF;
591 	for(i=0; i<e->maxlines; i++) e->textarray[i][0] = 0;
592 	e->curline = e->curchar = e->firstline = 0;
593 	e->endline = e->endchar = 0;
594 	e->dirty = FALSE;
595 	e->linecount = 0;
596 
597 	/* read the file */
598 	charsread = 0;
599 	for(;;)
600 	{
601 		c = xgetc(f);
602 		if (c == EOF) break;
603 		charsread++;
604 		if (c == '\t') c = ' ';
605 		if (c == '\n' || c == '\r')
606 		{
607 			if (e->curline >= e->maxlines-1) us_editpacaddmorelines(e);
608 			e->linecount++;
609 			e->curline++;
610 			e->curchar = 0;
611 		} else
612 		{
613 			/* see if line needs to be extended */
614 			i = estrlen(e->textarray[e->curline]) + 2;
615 			if (i > e->maxchars[e->curline])
616 				us_editpacaddmorechars(e, e->curline, i+10);
617 
618 			e->textarray[e->curline][e->curchar] = (CHAR)c;
619 			e->textarray[e->curline][e->curchar+1] = 0;
620 			e->curchar++;
621 		}
622 		if (filelength > 0 && (charsread%100) == 0)
623 		{
624 			DiaSetProgress(dia, charsread, filelength);
625 		}
626 	}
627 	xclose(f);
628 
629 	/* announce the changes (go backwards so the array expands only once) */
630 	if (filelength > 0)
631 	{
632 		DiaSetProgress(dia, 999, 1000);
633 		DiaSetTextProgress(dia, _("Cleaning up..."));
634 	}
635 	(*win->changehandler)(win, REPLACEALLTEXT, x_(""), (CHAR *)e->textarray, e->linecount);
636 	if (filelength > 0) DiaDoneProgress(dia);
637 
638 	/* restore the display */
639 	e->state &= ~EGRAPHICSOFF;
640 	TDCLEAR(descript);
641 	TDSETSIZE(descript, us_editpacfont);
642 	screensettextinfo(win, NOTECHNOLOGY, descript);
643 	e->curline = e->curchar = 0;
644 	e->endline = e->endchar = 0;
645 	us_editpacbeginwork(win);
646 	us_editpacredrawlines(win);
647 	if ((win->state&WINDOWTYPE) != POPTEXTWINDOW) us_editpacdrawvscroll(win);
648 	us_editpacdrawhscroll(win);
649 }
650 
us_editpaceditorterm(WINDOWPART * win)651 void us_editpaceditorterm(WINDOWPART *win)
652 {
653 	REGISTER EDITOR *e;
654 
655 	e = win->editor;
656 	if (e == NOEDITOR) return;
657 
658 	/* first flush any pending edit changes */
659 	us_editpacshipchanges(win);
660 
661 	/* restore window state */
662 	if ((win->state&WINDOWTYPE) == POPTEXTWINDOW)
663 	{
664 		screenrestorebox(e->savedbox, 0);
665 	}
666 }
667 
us_editpacshipchanges(WINDOWPART * win)668 void us_editpacshipchanges(WINDOWPART *win)
669 {
670 	REGISTER EDITOR *e;
671 
672 	e = win->editor;
673 	if (e == NOEDITOR) return;
674 
675 	if (e->working >= 0 && e->dirty)
676 	{
677 		if (win->changehandler != 0)
678 			(*win->changehandler)(win, REPLACETEXTLINE, e->formerline, e->textarray[e->working],
679 				e->working);
680 		e->dirty = FALSE;
681 		e->working = -1;
682 	}
683 }
684 
685 /*
686  * keyboard interrupt routine for the text window
687  */
us_editpacgotchar(WINDOWPART * win,INTSML i,INTBIG special)688 BOOLEAN us_editpacgotchar(WINDOWPART *win, INTSML i, INTBIG special)
689 {
690 	REGISTER EDITOR *e;
691 	UINTBIG descript[TEXTDESCRIPTSIZE];
692 
693 	/* pass accelerated keys to the main system */
694 	if ((special&ACCELERATORDOWN) != 0)
695 	{
696 		return((*DEFAULTCHARHANDLER)(win, i, special));
697 	}
698 
699 	e = win->editor;
700 	if (e == NOEDITOR) return(TRUE);
701 	TDCLEAR(descript);
702 	TDSETSIZE(descript, us_editpacfont);
703 	screensettextinfo(win, NOTECHNOLOGY, descript);
704 	us_editpacinvertselection(win);
705 	if (us_editpacimplementchar(win, i, special, TRUE)) return(TRUE);
706 	us_editpacinvertselection(win);
707 	setactivity(_("Text Editing"));
708 	return(FALSE);
709 }
710 
us_editpaccut(WINDOWPART * win)711 void us_editpaccut(WINDOWPART *win)
712 {
713 	REGISTER EDITOR *e;
714 	UINTBIG descript[TEXTDESCRIPTSIZE];
715 
716 	e = win->editor;
717 	if (e == NOEDITOR) return;
718 
719 	/* copy the selection to the cut/copy buffer */
720 	us_editpaccopy(win);
721 
722 	/* remove the selection from the edit buffer */
723 	TDCLEAR(descript);
724 	TDSETSIZE(descript, us_editpacfont);
725 	screensettextinfo(win, NOTECHNOLOGY, descript);
726 	us_editpacinvertselection(win);
727 	(void)us_editpacimplementchar(win, BACKSPACEKEY, 0, TRUE);
728 	us_editpacinvertselection(win);
729 }
730 
us_editpaccopy(WINDOWPART * win)731 void us_editpaccopy(WINDOWPART *win)
732 {
733 	REGISTER EDITOR *e;
734 	REGISTER INTBIG len;
735 
736 	e = win->editor;
737 	if (e == NOEDITOR) return;
738 
739 	/* free the former cut/copy buffer */
740 	if (us_editpacbuffer != 0)
741 	{
742 		efree(us_editpacbuffer);
743 		us_editpacbuffer = 0;
744 	}
745 
746 	/* determine number of characters that are selected */
747 	len = us_editpaccharstocurrent(e, e->endchar, e->endline);
748 	if (len <= 0) return;
749 
750 	/* allocate a new cut/copy buffer */
751 	us_editpacbuffer = (CHAR *)emalloc((len+1) * SIZEOFCHAR, us_tool->cluster);
752 	if (us_editpacbuffer == 0) return;
753 
754 	/* fill the buffer */
755 	us_editpacloadselection(e, us_editpacbuffer);
756 
757 	/* store it in the system-wide cut buffer */
758 	setcutbuffer(us_editpacbuffer);
759 }
760 
us_editpacpaste(WINDOWPART * win)761 void us_editpacpaste(WINDOWPART *win)
762 {
763 	REGISTER EDITOR *e;
764 	REGISTER INTBIG i;
765 	UINTBIG descript[TEXTDESCRIPTSIZE];
766 	INTBIG len;
767 	CHAR *str;
768 
769 	/* flush the internal buffer and get the system-wide cut buffer */
770 	if (us_editpacbuffer != 0) efree(us_editpacbuffer);
771 	us_editpacbuffer = 0;
772 	str = getcutbuffer();
773 	len = estrlen(str);
774 	if (len > 0)
775 	{
776 		us_editpacbuffer = (CHAR *)emalloc((len+1) * SIZEOFCHAR, us_tool->cluster);
777 		if (us_editpacbuffer == 0) return;
778 		estrcpy(us_editpacbuffer, str);
779 	}
780 	if (us_editpacbuffer == 0) return;
781 
782 	e = win->editor;
783 	if (e == NOEDITOR) return;
784 	TDCLEAR(descript);
785 	TDSETSIZE(descript, us_editpacfont);
786 	screensettextinfo(win, NOTECHNOLOGY, descript);
787 
788 	us_editpacsuspendgraphics(win);
789 	us_editpacinvertselection(win);
790 	for(i=0; us_editpacbuffer[i] != 0; i++)
791 	{
792 		if (i > 0)
793 		{
794 			if (us_editpacbuffer[i] == '\n' && us_editpacbuffer[i-1] == '\r') continue;
795 		}
796 		(void)us_editpacimplementchar(win, us_editpacbuffer[i], 0, TRUE);
797 	}
798 	us_editpacinvertselection(win);
799 	us_editpacresumegraphics(win);
800 }
801 
us_editpacundo(WINDOWPART * win)802 void us_editpacundo(WINDOWPART *win)
803 {
804 	CHAR *savebuffer;
805 	REGISTER EDITOR *e;
806 	REGISTER INTBIG i;
807 	UINTBIG descript[TEXTDESCRIPTSIZE];
808 
809 	e = win->editor;
810 	if (e == NOEDITOR) return;
811 
812 	/* if no change made, stop */
813 	if ((e->state&TEXTTYPED) == 0) return;
814 
815 	/* finish a set of changes */
816 	us_editpacdonetyping(e);
817 
818 	/* save the replacement buffer */
819 	(void)allocstring(&savebuffer, us_editpacundobuffer, el_tempcluster);
820 
821 	/* replace what was typed */
822 	TDCLEAR(descript);
823 	TDSETSIZE(descript, us_editpacfont);
824 	screensettextinfo(win, NOTECHNOLOGY, descript);
825 	us_editpacinvertselection(win);
826 	e->curline = us_editpacundonewcurline;    e->curchar = us_editpacundonewcurchar;
827 	e->endline = us_editpacundonewendline;    e->endchar = us_editpacundonewendchar;
828 	us_editpacbeginwork(win);
829 	if (savebuffer[0] == 0) (void)us_editpacimplementchar(win, BACKSPACEKEY, 0, TRUE); else
830 		for(i=0; savebuffer[i] != 0; i++)
831 			(void)us_editpacimplementchar(win, savebuffer[i], 0, TRUE);
832 	us_editpacinvertselection(win);
833 
834 	efree(savebuffer);
835 }
836 
837 /*
838  * routine to search and/or replace text.  If "replace" is nonzero, this is
839  * a replace.  The meaning of "bits" is as follows:
840  *   1   search from top
841  *   2   replace all
842  *   4   case sensitive
843  *   8   search upwards
844  */
us_editpacsearch(WINDOWPART * win,CHAR * str,CHAR * replace,INTBIG bits)845 void us_editpacsearch(WINDOWPART *win, CHAR *str, CHAR *replace, INTBIG bits)
846 {
847 	if ((bits&2) != 0 && replace != 0)
848 	{
849 		for(;;)
850 		{
851 			if (!us_editpacsinglesearch(win, str, replace, bits)) break;
852 		}
853 	} else
854 	{
855 		(void)us_editpacsinglesearch(win, str, replace, bits);
856 	}
857 }
858 
us_editpacpan(WINDOWPART * win,INTBIG dx,INTBIG dy)859 void us_editpacpan(WINDOWPART *win, INTBIG dx, INTBIG dy)
860 {
861 	us_editpacpanwindow(win, dx, dy);
862 }
863 
864 /*
865  * Helper routine to do a search and replace.  Returns true if a replacement
866  * was done.
867  */
us_editpacsinglesearch(WINDOWPART * win,CHAR * str,CHAR * replace,INTBIG bits)868 BOOLEAN us_editpacsinglesearch(WINDOWPART *win, CHAR *str, CHAR *replace, INTBIG bits)
869 {
870 	REGISTER INTBIG i, want, mchr, mlne;
871 	INTBIG startchr, startlne, chr, lne;
872 	UINTBIG descript[TEXTDESCRIPTSIZE];
873 	REGISTER EDITOR *e;
874 
875 	e = win->editor;
876 	if (e == NOEDITOR) return(FALSE);
877 
878 	if ((bits&1) != 0)
879 	{
880 		/* search from the top of the buffer */
881 		startchr = 0;   startlne = 0;
882 	} else
883 	{
884 		/* search from current location */
885 		if ((bits&8) != 0)
886 		{
887 			/* search from before the start of the current selection */
888 			startchr = e->curchar;   startlne = e->curline;
889 			us_editpacbackupposition(e, &startchr, &startlne);
890 		} else
891 		{
892 			/* search from the end of the current selection */
893 			startchr = e->endchar;   startlne = e->endline;
894 		}
895 	}
896 	chr = startchr;   lne = startlne;
897 	for(;;)
898 	{
899 		/* see if the string matches at this point */
900 		mchr = chr;   mlne = lne;
901 		for(i=0; str[i] != 0; i++)
902 		{
903 			want = str[i];
904 			if (want == '\n') want = 0;
905 			if ((bits&4) != 0)
906 			{
907 				if (e->textarray[mlne][mchr] != str[i]) break;
908 			} else
909 			{
910 				if (tolower(e->textarray[mlne][mchr]) != tolower(str[i])) break;
911 			}
912 
913 			/* advance match pointer to the next character in the file */
914 			if (e->textarray[mlne][mchr] != 0) mchr++; else
915 			{
916 				mchr = 0;
917 				mlne++;
918 				if (mlne >= e->linecount) break;
919 			}
920 		}
921 		if (str[i] == 0) break;
922 
923 		/* advance to the next character in the file */
924 		if ((bits&8) != 0)
925 		{
926 			us_editpacbackupposition(e, &chr, &lne);
927 		} else
928 		{
929 			us_editpacadvanceposition(e, &chr, &lne);
930 		}
931 
932 		/* if it came all the way around, stop */
933 		if (chr == startchr && lne == startlne)
934 		{
935 			ttybeep(SOUNDBEEP, TRUE);
936 			return(FALSE);
937 		}
938 	}
939 
940 	/* string found */
941 	TDCLEAR(descript);
942 	TDSETSIZE(descript, us_editpacfont);
943 	screensettextinfo(win, NOTECHNOLOGY, descript);
944 	us_editpacdonetyping(e);
945 	us_editpacinvertselection(win);
946 	e->curline = lne;   e->curchar = chr;
947 	for(i=0; str[i] != 0; i++)
948 		us_editpacadvanceposition(e, &chr, &lne);
949 	e->endline = lne;   e->endchar = chr;
950 	us_editpacinvertselection(win);
951 	us_editpacbeginwork(win);
952 
953 	if (replace != 0)
954 	{
955 		us_editpacinvertselection(win);
956 		if (replace[0] == 0)
957 		{
958 			(void)us_editpacimplementchar(win, BACKSPACEKEY, 0, TRUE);
959 		} else
960 		{
961 			for(i=0; replace[i] != 0; i++)
962 				(void)us_editpacimplementchar(win, replace[i], 0, TRUE);
963 		}
964 		us_editpacinvertselection(win);
965 	}
966 
967 	/* ensure that line "e->curline" is shown in the display */
968 	us_editpacensurelinevisible(win, e->curline, TRUE);
969 	return(TRUE);
970 }
971 
972 /******************** ROUTINES IN THE WINDOW STRUCTURE ********************/
973 
us_editpacredraweditor(WINDOWPART * win)974 void us_editpacredraweditor(WINDOWPART *win)
975 {
976 	REGISTER EDITOR *e;
977 	UINTBIG descript[TEXTDESCRIPTSIZE];
978 
979 	e = win->editor;
980 	if (e == NOEDITOR) return;
981 	TDCLEAR(descript);
982 	TDSETSIZE(descript, us_editpacfont);
983 	screensettextinfo(win, NOTECHNOLOGY, descript);
984 
985 	/* compute window extents */
986 	us_editpaccomputebounds(win, e);
987 
988 	while (e->screenlines > e->maxlines) us_editpacaddmorelines(e);
989 
990 	us_editpacredrawscreen(win);
991 }
992 
us_editpacgotbutton(WINDOWPART * win,INTBIG but,INTBIG x,INTBIG y)993 void us_editpacgotbutton(WINDOWPART *win, INTBIG but, INTBIG x, INTBIG y)
994 {
995 	REGISTER EDITOR *e;
996 	REGISTER INTBIG xc, yc, len;
997 	BOOLEAN (*clickroutine)(INTBIG, INTBIG);
998 	UINTBIG descript[TEXTDESCRIPTSIZE];
999 
1000 	/* changes to the mouse-wheel are handled by the user interface */
1001 	if (wheelbutton(but))
1002 	{
1003 		us_buttonhandler(win, but, x, y);
1004 		return;
1005 	}
1006 	ttynewcommand();
1007 
1008 	e = win->editor;
1009 	if (e == NOEDITOR) return;
1010 	TDCLEAR(descript);
1011 	TDSETSIZE(descript, us_editpacfont);
1012 	screensettextinfo(win, NOTECHNOLOGY, descript);
1013 	us_editpaccurrentwin = win;
1014 
1015 	if ((win->state&WINDOWTYPE) != POPTEXTWINDOW && x > e->offx + e->swid)
1016 	{
1017 		/* cursor in vertical slider */
1018 		if (e->linecount <= e->screenlines) return;
1019 		if (y < e->revy - e->shei + DISPLAYSLIDERSIZE)
1020 		{
1021 			/* the down arrow */
1022 			trackcursor(FALSE, us_nullup, us_nullvoid, us_editpacdownarrow,
1023 				us_nullchar, us_nullvoid, TRACKNORMAL);
1024 			return;
1025 		}
1026 		if (y > e->revy - DISPLAYSLIDERSIZE)
1027 		{
1028 			/* the up arrow */
1029 			trackcursor(FALSE, us_nullup, us_nullvoid, us_editpacuparrow,
1030 				us_nullchar, us_nullvoid, TRACKNORMAL);
1031 			return;
1032 		}
1033 		if (y < e->vthumbpos-THUMBSIZE/2 && y >= e->revy - e->shei + DISPLAYSLIDERSIZE)
1034 		{
1035 			/* scroll down one page */
1036 			trackcursor(FALSE, us_nullup, us_nullvoid, us_editpacdownpage,
1037 				us_nullchar, us_nullvoid, TRACKNORMAL);
1038 			return;
1039 		}
1040 		if (y > e->vthumbpos+THUMBSIZE/2 && y <= e->revy - DISPLAYSLIDERSIZE)
1041 		{
1042 			/* scroll up one page */
1043 			trackcursor(FALSE, us_nullup, us_nullvoid, us_editpacuppage,
1044 				us_nullchar, us_nullvoid, TRACKNORMAL);
1045 			return;
1046 		}
1047 		if (y >= e->vthumbpos-THUMBSIZE/2 && y <= e->vthumbpos+THUMBSIZE/2)
1048 		{
1049 			/* drag slider appropriately */
1050 			us_editpacdeltasofar = 0;
1051 			us_editpacinitialthumb = e->vthumbpos;
1052 			us_vthumbbegin(y, win, win->usehx-DISPLAYSLIDERSIZE, win->usely+DISPLAYSLIDERSIZE,
1053 				win->usehy-us_editpacthei*HEADERLINES, FALSE, us_editpacvthumbtrackingtextcallback);
1054 			trackcursor(FALSE, us_nullup, us_nullvoid, us_vthumbdown, us_nullchar,
1055 				us_vthumbdone, TRACKNORMAL);
1056 			return;
1057 		}
1058 	}
1059 	if (y <= e->revy - e->shei)
1060 	{
1061 		/* cursor in horizontal slider */
1062 		if (x > e->offx + e->swid - DISPLAYSLIDERSIZE)
1063 		{
1064 			/* the right arrow */
1065 			trackcursor(FALSE, us_nullup, us_nullvoid, us_editpacrightarrow,
1066 				us_nullchar, us_nullvoid, TRACKNORMAL);
1067 			return;
1068 		}
1069 		if (x < e->offx + DISPLAYSLIDERSIZE - LEFTINDENT)
1070 		{
1071 			/* the left arrow */
1072 			trackcursor(FALSE, us_nullup, us_nullvoid, us_editpacleftarrow,
1073 				us_nullchar, us_nullvoid, TRACKNORMAL);
1074 			return;
1075 		}
1076 		if (x > e->hthumbpos+THUMBSIZE/2 && x <= e->offx + e->swid - DISPLAYSLIDERSIZE)
1077 		{
1078 			/* scroll right one page */
1079 			trackcursor(FALSE, us_nullup, us_nullvoid, us_editpacrightpage,
1080 				us_nullchar, us_nullvoid, TRACKNORMAL);
1081 			return;
1082 		}
1083 		if (x < e->hthumbpos-THUMBSIZE/2 && x >= e->offx + DISPLAYSLIDERSIZE - LEFTINDENT)
1084 		{
1085 			/* scroll left one page */
1086 			trackcursor(FALSE, us_nullup, us_nullvoid, us_editpacleftpage,
1087 				us_nullchar, us_nullvoid, TRACKNORMAL);
1088 			return;
1089 		}
1090 		if (x >= e->hthumbpos-THUMBSIZE/2 && x <= e->hthumbpos+THUMBSIZE/2)
1091 		{
1092 			/* drag slider appropriately */
1093 			us_editpacdeltasofar = 0;
1094 			us_editpacinitialthumb = (win->thumblx + win->thumbhx) / 2;
1095 			us_hthumbbegin(x, win, win->usely+DISPLAYSLIDERSIZE, win->uselx,
1096 				win->usehx-DISPLAYSLIDERSIZE, us_editpachthumbtrackingtextcallback);
1097 			trackcursor(FALSE, us_nullup, us_nullvoid, us_hthumbdown, us_nullchar,
1098 				us_hthumbdone, TRACKNORMAL);
1099 			return;
1100 		}
1101 	}
1102 
1103 	/* find the character position in the edit buffer */
1104 	if (y > e->revy) return;
1105 	yc = (e->revy-y) / us_editpacthei + e->firstline;
1106 	if (yc >= e->screenlines + e->firstline) yc = e->screenlines - 1 + e->firstline;
1107 	if (yc >= e->linecount)
1108 	{
1109 		yc = e->linecount-1;
1110 		xc = estrlen(e->textarray[yc]);
1111 	} else
1112 	{
1113 		xc = (x-e->offx+us_editpactwid/2) / us_editpactwid + e->horizfactor;
1114 		if (xc < 0) xc = 0;
1115 		len = estrlen(e->textarray[yc]);
1116 		if (xc > len) xc = len;
1117 	}
1118 
1119 	/* turn off the former selection */
1120 	us_editpacinvertselection(win);
1121 	us_editpacdonetyping(e);
1122 
1123 	/* determine the selection from this click */
1124 	if (shiftbutton(but))
1125 	{
1126 		if (yc < e->curline || (yc == e->curline && xc < e->curchar))
1127 		{
1128 			e->curline = yc;   e->curchar = xc;
1129 		} else
1130 		{
1131 			e->endline = yc;   e->endchar = xc;
1132 		}
1133 	} else
1134 	{
1135 		e->curline = e->endline = yc;
1136 		e->curchar = e->endchar = xc;
1137 	}
1138 	if (doublebutton(but))
1139 	{
1140 		/* double click: select word about cursor */
1141 		for(e->curchar = xc-1; e->curchar >= 0; e->curchar--)
1142 			if (!isalnum(e->textarray[yc][e->curchar])) break;
1143 		e->curchar++;
1144 		for(e->endchar = e->curchar; e->textarray[yc][e->endchar] != 0; e->endchar++)
1145 			if (!isalnum(e->textarray[yc][e->endchar])) break;
1146 		clickroutine = us_editpacdclickdown;
1147 	} else clickroutine = us_editpacclickdown;
1148 
1149 	/* show the new selection */
1150 	us_editpacinvertselection(win);
1151 
1152 	/* extend the selection while the cursor remains down */
1153 	us_editpacorigcurline = e->curline;   us_editpacorigcurchar = e->curchar;
1154 	us_editpacorigendline = e->endline;   us_editpacorigendchar = e->endchar;
1155 	us_editpaclastc = us_editpaclastl = -1;
1156 	trackcursor(FALSE, us_nullup, us_nullvoid, clickroutine,
1157 		us_nullchar, us_nullvoid, TRACKNORMAL);
1158 	us_editpacbeginwork(win);
1159 	e->charposition = e->endchar;
1160 }
1161 
1162 /******************** TRACKING ROUTINES ********************/
1163 
us_editpachthumbtrackingtextcallback(INTBIG delta)1164 void us_editpachthumbtrackingtextcallback(INTBIG delta)
1165 {
1166 	REGISTER INTBIG point, i;
1167 	REGISTER EDITOR *e;
1168 
1169 	us_editpacdeltasofar += delta;
1170 	e = us_editpaccurrentwin->editor;
1171 	point = us_editpacinitialthumb + us_editpacdeltasofar;
1172 	i = e->swid - DISPLAYSLIDERSIZE*2 + LEFTINDENT - THUMBSIZE;
1173 	i = ((point - (e->offx+DISPLAYSLIDERSIZE-LEFTINDENT+THUMBSIZE/2)) *
1174 		e->screenchars*10 + i/2) / i;
1175 	if (i < 0) i = 0;
1176 	if (i == e->horizfactor) return;
1177 	e->horizfactor = i;
1178 	us_editpacredrawlines(us_editpaccurrentwin);
1179 	us_editpacdrawhscroll(us_editpaccurrentwin);
1180 }
1181 
us_editpacvthumbtrackingtextcallback(INTBIG delta)1182 void us_editpacvthumbtrackingtextcallback(INTBIG delta)
1183 {
1184 	REGISTER INTBIG point, thumbarea, thumbpos;
1185 	REGISTER EDITOR *e;
1186 
1187 	us_editpacdeltasofar += delta;
1188 	e = us_editpaccurrentwin->editor;
1189 	thumbarea = e->linecount - e->screenlines;
1190 	thumbpos = us_editpacinitialthumb + us_editpacdeltasofar;
1191 	point = ((e->revy - DISPLAYSLIDERSIZE - THUMBSIZE/2 - thumbpos) * thumbarea - thumbarea/2) /
1192 		(e->shei-DISPLAYSLIDERSIZE*2-THUMBSIZE);
1193 	if (point < 0) point = 0;
1194 	e->firstline = point;
1195 	us_editpacredrawlines(us_editpaccurrentwin);
1196 	us_editpacdrawvscroll(us_editpaccurrentwin);
1197 }
1198 
us_editpacclickdown(INTBIG x,INTBIG y)1199 BOOLEAN us_editpacclickdown(INTBIG x, INTBIG y)
1200 {
1201 	return(us_editpacdoclickdown(x, y, FALSE));
1202 }
1203 
us_editpacdclickdown(INTBIG x,INTBIG y)1204 BOOLEAN us_editpacdclickdown(INTBIG x, INTBIG y)
1205 {
1206 	return(us_editpacdoclickdown(x, y, TRUE));
1207 }
1208 
us_editpacdoclickdown(INTBIG x,INTBIG y,BOOLEAN bywords)1209 BOOLEAN us_editpacdoclickdown(INTBIG x, INTBIG y, BOOLEAN bywords)
1210 {
1211 	REGISTER INTBIG c, l, len, low, high;
1212 	REGISTER EDITOR *e;
1213 
1214 	e = us_editpaccurrentwin->editor;
1215 
1216 	if (y > e->revy && (us_editpaccurrentwin->state&WINDOWTYPE) != POPTEXTWINDOW)
1217 	{
1218 		/* if cursor is above the window, may shift lines */
1219 		if (e->firstline == 0) return(FALSE);
1220 		e->firstline--;
1221 		us_editpacredrawlines(us_editpaccurrentwin);
1222 		us_editpacdrawvscroll(us_editpaccurrentwin);
1223 	}
1224 	if (y < e->revy-e->shei && (us_editpaccurrentwin->state&WINDOWTYPE) != POPTEXTWINDOW)
1225 	{
1226 		/* if cursor is below the window, may shift lines */
1227 		if (e->linecount-e->firstline <= e->screenlines) return(FALSE);
1228 		e->firstline++;
1229 		us_editpacredrawlines(us_editpaccurrentwin);
1230 		us_editpacdrawvscroll(us_editpaccurrentwin);
1231 	}
1232 	if (x < e->offx)
1233 	{
1234 		/* if cursor is to the left of the window, may shift screen */
1235 		if (e->horizfactor > 0)
1236 		{
1237 			e->horizfactor--;
1238 			us_editpacredrawlines(us_editpaccurrentwin);
1239 			us_editpacdrawhscroll(us_editpaccurrentwin);
1240 		}
1241 	}
1242 	if (x > e->offx+e->swid)
1243 	{
1244 		/* if cursor is to the right of the window, may shift screen */
1245 		if (e->horizfactor < e->screenchars*10)
1246 		{
1247 			e->horizfactor++;
1248 			us_editpacredrawlines(us_editpaccurrentwin);
1249 			us_editpacdrawhscroll(us_editpaccurrentwin);
1250 		}
1251 	}
1252 	l = (e->revy-y) / us_editpacthei + e->firstline;
1253 	if (l >= e->screenlines + e->firstline) l = e->screenlines - 1 + e->firstline;
1254 	if (l >= e->linecount)
1255 	{
1256 		l = e->linecount-1;
1257 		c = estrlen(e->textarray[l]);
1258 	} else
1259 	{
1260 		if (l < 0) l = 0;
1261 		c = (x-e->offx+us_editpactwid/2) / us_editpactwid + e->horizfactor;
1262 		if (c < 0) c = 0;
1263 		len = estrlen(e->textarray[l]);
1264 		if (c > len) c = len;
1265 	}
1266 
1267 	/* only interested if the character position changed */
1268 	if (us_editpaclastc != -1 && us_editpaclastl != -1 &&
1269 		us_editpaclastc == c && us_editpaclastl == l) return(FALSE);
1270 	us_editpaclastc = c;   us_editpaclastl = l;
1271 
1272 	/* if going by words, advance that much at a time */
1273 	if (bywords && isalnum(e->textarray[l][c]) && c > 0 && isalnum(e->textarray[l][c-1]))
1274 	{
1275 		for(low = c-1; low >= 0; low--)
1276 			if (!isalnum(e->textarray[l][low])) break;
1277 		low++;
1278 		for(high = low; e->textarray[l][high] != 0; high++)
1279 			if (!isalnum(e->textarray[l][high])) break;
1280 		if (l > us_editpacorigendline || (l == us_editpacorigendline && high > us_editpacorigendchar))
1281 			c = high;
1282 		if (l < us_editpacorigcurline || (l == us_editpacorigcurline && low < us_editpacorigcurchar))
1283 			c = low;
1284 	}
1285 
1286 	us_editpacinvertselection(us_editpaccurrentwin);
1287 	if (l > us_editpacorigendline || (l == us_editpacorigendline && c >= us_editpacorigendchar))
1288 	{
1289 		e->curline = us_editpacorigcurline;   e->curchar = us_editpacorigcurchar;
1290 		e->endline = l;                       e->endchar = c;
1291 	}
1292 	if (l < us_editpacorigcurline || (l == us_editpacorigcurline && c <= us_editpacorigcurchar))
1293 	{
1294 		e->curline = l;                       e->curchar = c;
1295 		e->endline = us_editpacorigendline;   e->endchar = us_editpacorigendchar;
1296 	}
1297 	us_editpacinvertselection(us_editpaccurrentwin);
1298 	return(FALSE);
1299 }
1300 
us_editpacdownarrow(INTBIG x,INTBIG y)1301 BOOLEAN us_editpacdownarrow(INTBIG x, INTBIG y)
1302 {
1303 	REGISTER EDITOR *e;
1304 
1305 	e = us_editpaccurrentwin->editor;
1306 	if (x <= e->offx + e->swid || x > e->offx + e->swid + DISPLAYSLIDERSIZE) return(FALSE);
1307 	if (y >= e->revy - e->shei + DISPLAYSLIDERSIZE || y < e->revy - e->shei) return(FALSE);
1308 	if (e->linecount-e->firstline <= e->screenlines) return(TRUE);
1309 
1310 	us_editpacpanwindow(us_editpaccurrentwin, 0, 1);
1311 	return(FALSE);
1312 }
1313 
us_editpacuparrow(INTBIG x,INTBIG y)1314 BOOLEAN us_editpacuparrow(INTBIG x, INTBIG y)
1315 {
1316 	REGISTER EDITOR *e;
1317 
1318 	e = us_editpaccurrentwin->editor;
1319 	if (x <= e->offx + e->swid || x > e->offx + e->swid + DISPLAYSLIDERSIZE) return(FALSE);
1320 	if (y <= e->revy - DISPLAYSLIDERSIZE || y > e->revy) return(FALSE);
1321 	if (e->firstline <= 0) return(TRUE);
1322 
1323 	us_editpacpanwindow(us_editpaccurrentwin, 0, -1);
1324 	return(FALSE);
1325 }
1326 
us_editpacdownpage(INTBIG x,INTBIG y)1327 BOOLEAN us_editpacdownpage(INTBIG x, INTBIG y)
1328 {
1329 	REGISTER EDITOR *e;
1330 
1331 	e = us_editpaccurrentwin->editor;
1332 	if (x <= e->offx + e->swid || x > e->offx + e->swid + DISPLAYSLIDERSIZE) return(FALSE);
1333 	if (y >= e->vthumbpos-THUMBSIZE/2 || y < e->revy - e->shei + DISPLAYSLIDERSIZE) return(FALSE);
1334 	if (e->linecount-e->firstline <= e->screenlines) return(TRUE);
1335 	e->firstline += e->screenlines-1;
1336 	if (e->linecount-e->firstline <= e->screenlines)
1337 		e->firstline = e->linecount-e->screenlines;
1338 	us_editpacredrawlines(us_editpaccurrentwin);
1339 	us_editpacdrawvscroll(us_editpaccurrentwin);
1340 	return(FALSE);
1341 }
1342 
us_editpacuppage(INTBIG x,INTBIG y)1343 BOOLEAN us_editpacuppage(INTBIG x, INTBIG y)
1344 {
1345 	REGISTER EDITOR *e;
1346 
1347 	e = us_editpaccurrentwin->editor;
1348 	if (x <= e->offx + e->swid || x > e->offx + e->swid + DISPLAYSLIDERSIZE) return(FALSE);
1349 	if (y <= e->vthumbpos+THUMBSIZE/2 || y > e->revy - DISPLAYSLIDERSIZE) return(FALSE);
1350 	if (e->firstline <= 0) return(TRUE);
1351 	e->firstline -= e->screenlines-1;
1352 	if (e->firstline < 0) e->firstline = 0;
1353 	us_editpacredrawlines(us_editpaccurrentwin);
1354 	us_editpacdrawvscroll(us_editpaccurrentwin);
1355 	return(FALSE);
1356 }
1357 
us_editpacrightarrow(INTBIG x,INTBIG y)1358 BOOLEAN us_editpacrightarrow(INTBIG x, INTBIG y)
1359 {
1360 	REGISTER EDITOR *e;
1361 
1362 	e = us_editpaccurrentwin->editor;
1363 	if (y > e->revy - e->shei || y < e->revy - e->shei - DISPLAYSLIDERSIZE) return(FALSE);
1364 	if (x <= e->offx + e->swid - DISPLAYSLIDERSIZE || x > e->offx + e->swid) return(FALSE);
1365 	us_editpacpanwindow(us_editpaccurrentwin, 1, 0);
1366 	return(FALSE);
1367 }
1368 
us_editpacleftarrow(INTBIG x,INTBIG y)1369 BOOLEAN us_editpacleftarrow(INTBIG x, INTBIG y)
1370 {
1371 	REGISTER EDITOR *e;
1372 
1373 	e = us_editpaccurrentwin->editor;
1374 	if (y > e->revy - e->shei || y < e->revy - e->shei - DISPLAYSLIDERSIZE) return(FALSE);
1375 	if (x >= e->offx + DISPLAYSLIDERSIZE - LEFTINDENT || x < e->offx - LEFTINDENT) return(FALSE);
1376 	us_editpacpanwindow(us_editpaccurrentwin, -1, 0);
1377 	return(FALSE);
1378 }
1379 
us_editpacrightpage(INTBIG x,INTBIG y)1380 BOOLEAN us_editpacrightpage(INTBIG x, INTBIG y)
1381 {
1382 	REGISTER EDITOR *e;
1383 
1384 	e = us_editpaccurrentwin->editor;
1385 	if (y > e->revy - e->shei || y < e->revy - e->shei - DISPLAYSLIDERSIZE) return(FALSE);
1386 	if (x <= e->hthumbpos+THUMBSIZE/2 || x > e->offx + e->swid - DISPLAYSLIDERSIZE) return(FALSE);
1387 	if (e->horizfactor >= e->screenchars*10) return(TRUE);
1388 	e->horizfactor += 10;
1389 	if (e->horizfactor >= e->screenchars*10) e->horizfactor = e->screenchars*10;
1390 	us_editpacredrawlines(us_editpaccurrentwin);
1391 	us_editpacdrawhscroll(us_editpaccurrentwin);
1392 	return(FALSE);
1393 }
1394 
us_editpacleftpage(INTBIG x,INTBIG y)1395 BOOLEAN us_editpacleftpage(INTBIG x, INTBIG y)
1396 {
1397 	REGISTER EDITOR *e;
1398 
1399 	e = us_editpaccurrentwin->editor;
1400 	if (y > e->revy - e->shei || y < e->revy - e->shei - DISPLAYSLIDERSIZE) return(FALSE);
1401 	if (x >= e->hthumbpos-THUMBSIZE/2 || x < e->offx + DISPLAYSLIDERSIZE - LEFTINDENT) return(FALSE);
1402 	if (e->horizfactor <= 0) return(TRUE);
1403 	e->horizfactor -= 10;
1404 	if (e->horizfactor <= 0) e->horizfactor = 0;
1405 	us_editpacredrawlines(us_editpaccurrentwin);
1406 	us_editpacdrawhscroll(us_editpaccurrentwin);
1407 	return(FALSE);
1408 }
1409 
1410 /******************** CHANGES TO EDIT BUFFER ********************/
1411 
1412 /*
1413  * routine to implement character "i".  The key is issued internally if "fromuser"
1414  * is false.  Routine returns true if the editor window has been terminated.
1415  */
us_editpacimplementchar(WINDOWPART * win,INTSML i,INTBIG special,BOOLEAN fromuser)1416 BOOLEAN us_editpacimplementchar(WINDOWPART *win, INTSML i, INTBIG special, BOOLEAN fromuser)
1417 {
1418 	REGISTER EDITOR *e;
1419 	INTBIG j, len;
1420 	CHAR save;
1421 	CHAR *nextline;
1422 
1423 	e = win->editor;
1424 	if (e == NOEDITOR) return(TRUE);
1425 
1426 	/* ESCAPE quits the editor */
1427 	if (i == ESCKEY) return(TRUE);
1428 
1429 	if ((special&SPECIALKEYDOWN) != 0)
1430 	{
1431 		switch ((special&SPECIALKEY) >> SPECIALKEYSH)
1432 		{
1433 			case SPECIALKEYARROWL:
1434 				us_editpacdonetyping(e);
1435 				if (e->curline == e->endline && e->curchar == e->endchar)
1436 				{
1437 					if (e->curchar != 0) e->curchar--; else
1438 					{
1439 						if (e->curline > 0)
1440 						{
1441 							e->curline--;
1442 							e->curchar = estrlen(e->textarray[e->curline]);
1443 							us_editpacbeginwork(win);
1444 						}
1445 					}
1446 				}
1447 				e->endline = e->curline;
1448 				e->endchar = e->curchar;
1449 				e->charposition = e->endchar;
1450 				us_editpacensurelinevisible(win, e->curline, FALSE);
1451 				return(FALSE);
1452 			case SPECIALKEYARROWR:
1453 				us_editpacdonetyping(e);
1454 				if (e->curline == e->endline && e->curchar == e->endchar)
1455 				{
1456 					if (e->textarray[e->endline][e->endchar] != 0) e->endchar++; else
1457 					{
1458 						if (e->endline < e->linecount-1)
1459 						{
1460 							e->endline++;
1461 							e->endchar = 0;
1462 							us_editpacbeginwork(win);
1463 						}
1464 					}
1465 				}
1466 				e->curline = e->endline;
1467 				e->curchar = e->endchar;
1468 				e->charposition = e->endchar;
1469 				us_editpacensurelinevisible(win, e->curline, FALSE);
1470 				return(FALSE);
1471 			case SPECIALKEYARROWU:
1472 				us_editpacdonetyping(e);
1473 				if (e->curline > 0)
1474 				{
1475 					e->curline--;
1476 					len = estrlen(e->textarray[e->curline]);
1477 					if (e->charposition > e->curchar) e->curchar = e->charposition;
1478 					if (e->curchar > len) e->curchar = len;
1479 					e->endline = e->curline;
1480 					e->endchar = e->curchar;
1481 					us_editpacbeginwork(win);
1482 					us_editpacensurelinevisible(win, e->curline, FALSE);
1483 				}
1484 				return(FALSE);
1485 			case SPECIALKEYARROWD:
1486 				us_editpacdonetyping(e);
1487 				if (e->endline < e->linecount-1)
1488 				{
1489 					e->endline++;
1490 					len = estrlen(e->textarray[e->endline]);
1491 					if (e->charposition > e->endchar) e->endchar = e->charposition;
1492 					if (e->endchar > len) e->endchar = len;
1493 					e->curline = e->endline;
1494 					e->curchar = e->endchar;
1495 					us_editpacbeginwork(win);
1496 					us_editpacensurelinevisible(win, e->curline, FALSE);
1497 				}
1498 				return(FALSE);
1499 		}
1500 	}
1501 
1502 	/* if delete key hit and nothing selected, set to erase previous character */
1503 	if (i == BACKSPACEKEY || i == DELETEKEY)
1504 	{
1505 		if (e->curline == e->endline && e->curchar == e->endchar)
1506 		{
1507 #ifdef WIN32
1508 			if (i == DELETEKEY)
1509 			{
1510 				/* advance the end character */
1511 				len = estrlen(e->textarray[e->endline]);
1512 				if (e->endchar < len) e->endchar++; else
1513 				{
1514 					if (e->endline < e->linecount)
1515 					{
1516 						e->endchar = 0;
1517 						e->endline++;
1518 					}
1519 				}
1520 			} else
1521 #endif
1522 			{
1523 				/* backup the start character */
1524 				if (e->curchar > 0) e->curchar--; else
1525 				{
1526 					if (e->curline > 0)
1527 					{
1528 						e->curline--;
1529 						e->curchar = estrlen(e->textarray[e->curline]);
1530 						us_editpacbeginwork(win);
1531 					}
1532 				}
1533 			}
1534 		}
1535 	}
1536 
1537 	/* see if lines are fixed */
1538 	if ((e->state&LINESFIXED) != 0)
1539 	{
1540 		/* disallow line insertion, deletion or any action on the last line */
1541 		if (e->curline != e->endline || i == '\n' || i == '\r' || e->curline == e->linecount-1)
1542 		{
1543 			ttybeep(SOUNDBEEP, TRUE);
1544 			return(FALSE);
1545 		}
1546 	}
1547 
1548 	us_editpacamtyping(e);
1549 	if (i == BACKSPACEKEY || i == DELETEKEY) us_editpactypeddelete(e);
1550 
1551 	/* remove the selected characters */
1552 	us_editpacremoveselection(win);
1553 	e->endline = e->curline;
1554 	e->endchar = e->curchar;
1555 	e->charposition = e->endchar;
1556 
1557 	/* mark a dirty edit buffer */
1558 	e->dirty = TRUE;
1559 
1560 	/* ignore delete or backspace characters */
1561 	if (i == BACKSPACEKEY || i == DELETEKEY) return(FALSE);
1562 
1563 	/* handle end-of-line characters */
1564 	if (i == '\n' || i == '\r')
1565 	{
1566 		/* exit editor if only editing one line */
1567 		if ((win->state&WINDOWTYPE) == POPTEXTWINDOW) return(TRUE);
1568 
1569 		/* see if there is room in the file */
1570 		if (e->linecount >= e->maxlines) us_editpacaddmorelines(e);
1571 
1572 		if (fromuser)
1573 		{
1574 			if (e->curline == e->firstline+e->screenlines-1)
1575 			{
1576 				e->firstline++;
1577 				if ((e->state&EGRAPHICSOFF) == 0)
1578 				{
1579 					us_editpacmovebox(win, 0, 0, e->swid, us_editpacthei*(e->screenlines-1), 0, 1);
1580 					us_editpacclearbox(win, 0, e->screenlines-1, e->swid, us_editpacthei);
1581 					if (e->screenlines+e->firstline <= e->linecount)
1582 						us_editpactext(win, e->textarray[e->screenlines-1+e->firstline], 0,
1583 							e->screenlines-1);
1584 				}
1585 			}
1586 		}
1587 
1588 		/* shift lines down */
1589 		for(j = e->linecount; j > e->curline; j--)
1590 		{
1591 			if (j == e->curline+1) nextline = &e->textarray[e->curline][e->curchar]; else
1592 				nextline = e->textarray[j-1];
1593 			len = estrlen(nextline) + 1;
1594 			if (len > e->maxchars[j])
1595 				us_editpacaddmorechars(e, j, len);
1596 			(void)estrcpy(e->textarray[j], nextline);
1597 		}
1598 		e->textarray[e->curline][e->curchar] = 0;
1599 		if ((e->state&EGRAPHICSOFF) == 0 && e->curline-e->firstline < e->screenlines &&
1600 			e->curline >= e->firstline) us_editpaccleanupline(win, e->curline);
1601 		e->curline = e->endline = e->curline+1;
1602 		e->linecount++;
1603 		e->curchar = 0;   e->endchar = 0;
1604 
1605 		/* ship changes on the current line */
1606 		us_editpacshipchanges(win);
1607 		if (win->changehandler != 0)
1608 			(*win->changehandler)(win, INSERTTEXTLINE, x_(""), e->textarray[e->curline], e->curline);
1609 		us_editpacbeginwork(win);
1610 
1611 		/* shift lines down */
1612 		if (e->curline+1-e->firstline < e->screenlines &&
1613 			e->curline+1 >= e->firstline && (e->state&EGRAPHICSOFF) == 0)
1614 				us_editpacmovebox(win, 0, e->curline+1-e->firstline,
1615 					e->swid, e->shei-(e->curline+1-e->firstline)*us_editpacthei, 0,
1616 						e->curline-e->firstline);
1617 
1618 		/* draw current line */
1619 		if (e->curline-e->firstline < e->screenlines &&
1620 			e->curline >= e->firstline && (e->state&EGRAPHICSOFF) == 0)
1621 		{
1622 			save = e->textarray[e->curline][0];
1623 			e->textarray[e->curline][0] = 0;
1624 			us_editpaccleanupline(win, e->curline);
1625 			e->textarray[e->curline][0] = save;
1626 			us_editpactext(win, e->textarray[e->curline], 0, e->curline-e->firstline);
1627 		}
1628 		if ((e->state&EGRAPHICSOFF) == 0) us_editpacdrawvscroll(win);
1629 		e->charposition = e->endchar;
1630 		return(FALSE);
1631 	}
1632 
1633 	/* self-insert of normal characters */
1634 	if (i == '\t') i = ' ';
1635 
1636 	/* see if line needs to be extended */
1637 	j = estrlen(e->textarray[e->curline]) + 2;
1638 	if (j > e->maxchars[e->curline])
1639 		us_editpacaddmorechars(e, e->curline, j+10);
1640 
1641 	/* see if new character is at end of line */
1642 	if (e->textarray[e->curline][e->curchar] != 0)
1643 	{
1644 		/* it is not: shift letters on the line */
1645 		len = estrlen(e->textarray[e->curline]);
1646 		for(j = len+1; j > e->curchar; j--)
1647 			e->textarray[e->curline][j] = e->textarray[e->curline][j-1];
1648 	} else e->textarray[e->curline][e->curchar+1] = 0;
1649 
1650 	/* clear from here to the end of the line */
1651 	if (e->curline-e->firstline < e->screenlines && e->curline >= e->firstline &&
1652 		(e->state&EGRAPHICSOFF) == 0)
1653 	{
1654 		e->textarray[e->curline][e->curchar] = 0;
1655 		us_editpaccleanupline(win, e->curline);
1656 	}
1657 
1658 	/* insert the character */
1659 	e->textarray[e->curline][e->curchar] = (CHAR)i;
1660 
1661 	/* put the rest of the line on the display */
1662 	if (e->curline-e->firstline < e->screenlines && e->curline >= e->firstline &&
1663 		e->curchar-e->horizfactor < e->screenchars && (e->state&EGRAPHICSOFF) == 0)
1664 	{
1665 		us_editpactext(win, &e->textarray[e->curline][e->curchar], e->curchar,
1666 			e->curline-e->firstline);
1667 	}
1668 
1669 	/* advance the character pointer */
1670 	e->curchar++;   e->endchar++;
1671 	e->charposition = e->endchar;
1672 	return(FALSE);
1673 }
1674 
us_editpacremoveselection(WINDOWPART * win)1675 void us_editpacremoveselection(WINDOWPART *win)
1676 {
1677 	REGISTER EDITOR *e;
1678 	REGISTER INTBIG j, k, diff;
1679 	REGISTER CHAR save;
1680 
1681 	e = win->editor;
1682 	if (e == NOEDITOR) return;
1683 
1684 	/* nothing to do if there is a null selection */
1685 	diff = e->endline - e->curline;
1686 	if (e->curline == e->endline && e->curchar == e->endchar) return;
1687 
1688 	/* report the deletion */
1689 	if (win->changehandler != 0)
1690 	{
1691 		/* send out changes made so far if this is a multiline delete */
1692 		if (diff > 0) us_editpacshipchanges(win);
1693 		for(j=diff-1; j>=0; j--)
1694 			(*win->changehandler)(win, DELETETEXTLINE, e->textarray[e->curline+j], x_(""),
1695 				e->curline+j);
1696 	}
1697 	if (diff > 0)
1698 		us_editpacbeginwork(win);
1699 
1700 	/* append text beyond end of selection to the start of the selection */
1701 	j = estrlen(&e->textarray[e->endline][e->endchar]) + e->curchar + 1;
1702 	if (j > e->maxchars[e->curline])
1703 		us_editpacaddmorechars(e, e->curline, j);
1704 	(void)estrcpy(&e->textarray[e->curline][e->curchar],
1705 		&e->textarray[e->endline][e->endchar]);
1706 
1707 	/* redraw this line */
1708 	if (e->curline-e->firstline < e->screenlines && e->curline >= e->firstline &&
1709 		e->curchar-e->horizfactor < e->screenchars-1 && (e->state&EGRAPHICSOFF) == 0)
1710 	{
1711 		save = e->textarray[e->curline][e->curchar];
1712 		e->textarray[e->curline][e->curchar] = 0;
1713 		us_editpaccleanupline(win, e->curline);
1714 		e->textarray[e->curline][e->curchar] = save;
1715 		us_editpactext(win, &e->textarray[e->curline][e->curchar], e->curchar,
1716 			e->curline-e->firstline);
1717 	}
1718 
1719 	/* now shift up text (if a multiline delete) */
1720 	if (diff > 0)
1721 	{
1722 		for(j=e->curline+1; j<e->linecount-diff; j++)
1723 		{
1724 			/* make sure there is room for the shifted line */
1725 			k = estrlen(e->textarray[j+diff]) + 1;
1726 			if (k > e->maxchars[j]) us_editpacaddmorechars(e, j, k);
1727 
1728 			/* copy new line */
1729 			if (j-e->firstline < e->screenlines && j >= e->firstline &&
1730 				(e->state&EGRAPHICSOFF) == 0)
1731 			{
1732 				/* erase this line */
1733 				e->textarray[j][0] = 0;
1734 				us_editpaccleanupline(win, j);
1735 
1736 				(void)estrcpy(e->textarray[j], e->textarray[j+diff]);
1737 				us_editpactext(win, e->textarray[j], 0, j-e->firstline);
1738 			} else (void)estrcpy(e->textarray[j], e->textarray[j+diff]);
1739 		}
1740 		for(j=e->linecount-diff; j<e->linecount; j++)
1741 		{
1742 			e->textarray[j][0] = 0;
1743 			if (j-e->firstline < e->screenlines && j >= e->firstline && (e->state&EGRAPHICSOFF) == 0)
1744 				us_editpaccleanupline(win, j);
1745 		}
1746 		e->linecount -= diff;
1747 	}
1748 }
1749 
1750 /******************** DISPLAY OF EDIT WINDOW ********************/
1751 
1752 /*
1753  * routine to redisplay the text screen
1754  */
us_editpacredrawscreen(WINDOWPART * win)1755 void us_editpacredrawscreen(WINDOWPART *win)
1756 {
1757 	REGISTER EDITOR *e;
1758 
1759 	e = win->editor;
1760 	if (e == NOEDITOR) return;
1761 	if ((e->state&EGRAPHICSOFF) != 0) return;
1762 
1763 	/* put header on display */
1764 	us_editpacsetheader(win, e->header);
1765 	us_editpacdrawsliders(win);
1766 
1767 	us_editpacredrawlines(win);
1768 }
1769 
us_editpacdrawsliders(WINDOWPART * win)1770 void us_editpacdrawsliders(WINDOWPART *win)
1771 {
1772 	REGISTER EDITOR *e;
1773 
1774 	e = win->editor;
1775 	if (e == NOEDITOR) return;
1776 
1777 	/* draw horizontal slider */
1778 	us_drawhorizontalslider(win, win->usely+DISPLAYSLIDERSIZE, win->uselx,
1779 		win->usehx-DISPLAYSLIDERSIZE, 0);
1780 	us_editpacdrawhscroll(win);
1781 
1782 	/* draw vertical slider if appropriate */
1783 	if ((win->state&WINDOWTYPE) != POPTEXTWINDOW)
1784 	{
1785 		us_drawverticalslider(win, win->usehx-DISPLAYSLIDERSIZE,
1786 			win->usely+DISPLAYSLIDERSIZE, win->usehy-us_editpacthei*HEADERLINES, FALSE);
1787 
1788 		/* the corner */
1789 		us_drawslidercorner(win, win->usehx-DISPLAYSLIDERSIZE+1, win->usehx, win->usely,
1790 			win->usely+DISPLAYSLIDERSIZE-1, FALSE);
1791 		us_editpacdrawvscroll(win);
1792 	}
1793 }
1794 
1795 /*
1796  * Routine to set the horizontal scroll bar
1797  */
us_editpacdrawhscroll(WINDOWPART * win)1798 void us_editpacdrawhscroll(WINDOWPART *win)
1799 {
1800 	INTBIG left, right;
1801 	INTBIG f;
1802 	REGISTER EDITOR *e;
1803 
1804 	e = win->editor;
1805 	if (e == NOEDITOR) return;
1806 
1807 	/* get the area of the slider without arrows */
1808 	left = e->offx+DISPLAYSLIDERSIZE-LEFTINDENT;
1809 	right = e->offx + e->swid - DISPLAYSLIDERSIZE;
1810 
1811 	/* compute position of vertical thumb area */
1812 	f = e->horizfactor;   f *= right-left-THUMBSIZE;   f /= e->screenchars*10;
1813 	e->hthumbpos = left + THUMBSIZE/2 + f;
1814 	if (e->hthumbpos > right-THUMBSIZE/2) e->hthumbpos = right-THUMBSIZE/2;
1815 
1816 	/* draw the thumb */
1817 	win->thumblx = e->hthumbpos - THUMBSIZE/2;   win->thumbhx = e->hthumbpos + THUMBSIZE/2;
1818 	us_drawhorizontalsliderthumb(win, win->usely+DISPLAYSLIDERSIZE, win->uselx,
1819 		win->usehx-DISPLAYSLIDERSIZE, win->thumblx, win->thumbhx, 0);
1820 }
1821 
1822 /*
1823  * Routine to set the vertical scroll bar
1824  */
us_editpacdrawvscroll(WINDOWPART * win)1825 void us_editpacdrawvscroll(WINDOWPART *win)
1826 {
1827 	INTBIG top, bottom;
1828 	INTBIG den;
1829 	REGISTER EDITOR *e;
1830 
1831 	e = win->editor;
1832 	if (e == NOEDITOR) return;
1833 
1834 	/* get the area of the slider without arrows */
1835 	top = e->revy - DISPLAYSLIDERSIZE;
1836 	bottom = e->revy - e->shei + DISPLAYSLIDERSIZE;
1837 
1838 	/* if there is nothing to scroll, clear this area */
1839 	if (e->linecount <= e->screenlines)
1840 	{
1841 		us_drawverticalsliderthumb(win, win->usehx-DISPLAYSLIDERSIZE, win->usely+DISPLAYSLIDERSIZE,
1842 			win->usehy-us_editpacthei*HEADERLINES, 1, 0);
1843 		return;
1844 	}
1845 
1846 	/* compute position of vertical thumb area */
1847 	den = e->linecount - e->screenlines;
1848 	e->vthumbpos = e->revy - DISPLAYSLIDERSIZE - THUMBSIZE/2 -
1849 		(e->firstline * (e->shei-DISPLAYSLIDERSIZE*2-THUMBSIZE) + den/2) / den;
1850 	if (e->vthumbpos >= top-THUMBSIZE/2) e->vthumbpos = top-THUMBSIZE/2-1;
1851 	if (e->vthumbpos <= bottom+THUMBSIZE/2) e->vthumbpos = bottom+THUMBSIZE/2+1;
1852 
1853 	win->thumbly = e->vthumbpos - THUMBSIZE/2;
1854 	win->thumbhy = e->vthumbpos + THUMBSIZE/2;
1855 	us_drawverticalsliderthumb(win, win->usehx-DISPLAYSLIDERSIZE, win->usely+DISPLAYSLIDERSIZE,
1856 		win->usehy-us_editpacthei*HEADERLINES, win->thumbly, win->thumbhy);
1857 }
1858 
1859 /*
1860  * routine to clear the bits from the last character to the end of the line
1861  */
us_editpaccleanupline(WINDOWPART * win,INTBIG line)1862 void us_editpaccleanupline(WINDOWPART *win, INTBIG line)
1863 {
1864 	REGISTER INTBIG residue, linelen;
1865 	REGISTER EDITOR *e;
1866 
1867 	e = win->editor;
1868 	if (e == NOEDITOR) return;
1869 	linelen = estrlen(e->textarray[line]);
1870 	residue = e->swid-(linelen - e->horizfactor)*us_editpactwid;
1871 	if (residue <= 0) return;
1872 	us_editpacclearbox(win, linelen - e->horizfactor, line-e->firstline,
1873 		residue, us_editpacthei);
1874 }
1875 
1876 /*
1877  * routine to redisplay the text screen
1878  */
us_editpacredrawlines(WINDOWPART * win)1879 void us_editpacredrawlines(WINDOWPART *win)
1880 {
1881 	REGISTER INTBIG j;
1882 	REGISTER INTBIG bottom;
1883 	REGISTER EDITOR *e;
1884 
1885 	e = win->editor;
1886 	if (e == NOEDITOR) return;
1887 	if ((e->state&EGRAPHICSOFF) != 0) return;
1888 
1889 	/* clear the screen */
1890 	bottom = e->revy - e->shei;
1891 	screendrawbox(win, e->offx-LEFTINDENT, e->offx+e->swid+1, bottom-1, e->revy,
1892 		&us_ebox);
1893 
1894 	/* rewrite each line */
1895 	for(j=0; j<e->screenlines; j++) if (j+e->firstline < e->linecount)
1896 		us_editpactext(win, e->textarray[j+e->firstline], 0, j);
1897 	us_editpacinvertselection(win);
1898 }
1899 
1900 /*
1901  * routine to write the header string
1902  */
us_editpacsetheader(WINDOWPART * win,CHAR * header)1903 void us_editpacsetheader(WINDOWPART *win, CHAR *header)
1904 {
1905 	REGISTER INTBIG save, formerhf, bottom;
1906 	REGISTER EDITOR *e;
1907 
1908 	e = win->editor;
1909 	if (e == NOEDITOR) return;
1910 	screendrawbox(win, win->uselx, win->usehx, e->revy+1,
1911 		e->revy+us_editpacthei*HEADERLINES, &us_ebox);
1912 	if ((INTBIG)estrlen(header) > e->screenchars)
1913 	{
1914 		save = header[e->screenchars];
1915 		header[e->screenchars] = 0;
1916 	} else save = 0;
1917 	formerhf = e->horizfactor;
1918 	e->horizfactor = 0;
1919 	us_editpactext(win, header, 0, -2);
1920 	if ((win->state&WINDOWTYPE) == POPTEXTWINDOW)
1921 		us_editpactext(win, _("Point-and-Click editor: type RETURN when done"), 0, -1); else
1922 	{
1923 		if (estrcmp(win->location, x_("entire")) != 0)
1924 			us_editpactext(win, _("Point-and-Click editor: type ESC when done"), 0, -1); else
1925 		{
1926 			if (graphicshas(CANUSEFRAMES))
1927 				us_editpactext(win, _("Point-and-Click editor: close the window when done"), 0, -1); else
1928 					us_editpactext(win, _("Point-and-Click editor: text-only cell"), 0, -1);
1929 		}
1930 	}
1931 	e->horizfactor = formerhf;
1932 
1933 	if (save != 0) header[e->screenchars] = (CHAR)save;
1934 	bottom = e->revy - e->shei - 1;
1935 	screeninvertbox(win, win->uselx, win->usehx, e->revy+1,
1936 		e->revy+us_editpacthei*HEADERLINES);
1937 	us_menufigs.col = el_colmengly;
1938 	screendrawline(win, win->uselx, e->revy, win->uselx, bottom, &us_menufigs, 0);
1939 	if ((win->state&WINDOWTYPE) == POPTEXTWINDOW)
1940 	{
1941 		screendrawline(win, win->uselx, win->usely, win->uselx, win->usehy, &us_menufigs, 0);
1942 		screendrawline(win, win->uselx, win->usely, win->usehx, win->usely, &us_menufigs, 0);
1943 		screendrawline(win, win->usehx, win->usely, win->usehx, win->usehy, &us_menufigs, 0);
1944 	}
1945 }
1946 
1947 /*
1948  * Routine to shift the edit window by the direction in the coordinates (dx, dy)
1949  */
us_editpacpanwindow(WINDOWPART * w,INTBIG dx,INTBIG dy)1950 void us_editpacpanwindow(WINDOWPART *w, INTBIG dx, INTBIG dy)
1951 {
1952 	REGISTER EDITOR *e;
1953 	REGISTER INTBIG i;
1954 
1955 	e = w->editor;
1956 	us_editpacinvertselection(w);
1957 	if (dx == 0)
1958 	{
1959 		/* vertical panning */
1960 		if (dy > 0)
1961 		{
1962 			/* pan down by 1 line */
1963 			if (e->firstline >= e->linecount) return;
1964 			e->firstline++;
1965 
1966 			/* shift the window contents up by 1 line (us_editpacthei) */
1967 			screenmovebox(w, e->offx-LEFTINDENT, e->revy-e->shei,
1968 				e->swid+LEFTINDENT, e->shei-us_editpacthei, e->offx-LEFTINDENT,
1969 					e->revy-e->shei+us_editpacthei);
1970 
1971 			/* fill in a new last line */
1972 			screendrawbox(w, e->offx-LEFTINDENT, e->offx+e->swid,
1973 				e->revy-e->shei, e->revy-e->shei+us_editpacthei, &us_ebox);
1974 			i = e->firstline + e->screenlines - 1;
1975 			if (i < e->linecount)
1976 				us_editpactext(w, e->textarray[i], 0, i-e->firstline);
1977 		} else
1978 		{
1979 			/* pan up by 1 line */
1980 			if (e->firstline <= 0) return;
1981 			e->firstline--;
1982 
1983 			/* shift the window contents down by 1 line (us_editpacthei) */
1984 			screenmovebox(w, e->offx-LEFTINDENT, e->revy-e->shei+us_editpacthei, e->swid+LEFTINDENT,
1985 				e->shei-us_editpacthei, e->offx-LEFTINDENT, e->revy-e->shei);
1986 
1987 			/* fill in a new first line */
1988 			screendrawbox(w, e->offx-LEFTINDENT, e->offx+e->swid,
1989 				e->revy-us_editpacthei, e->revy, &us_ebox);
1990 			us_editpactext(w, e->textarray[e->firstline], 0, 0);
1991 		}
1992 		us_editpacinvertselection(w);
1993 		us_editpacdrawvscroll(w);
1994 	} else
1995 	{
1996 		/* horizontal panning */
1997 		if (dx > 0)
1998 		{
1999 			/* pan to the right */
2000 			if (e->horizfactor >= e->screenchars*10) return;
2001 			e->horizfactor++;
2002 			us_editpacredrawlines(w);
2003 			us_editpacdrawhscroll(w);
2004 		} else
2005 		{
2006 			/* pan to the left */
2007 			if (e->horizfactor <= 0) return;
2008 			e->horizfactor--;
2009 			us_editpacredrawlines(w);
2010 			us_editpacdrawhscroll(w);
2011 		}
2012 	}
2013 }
2014 
2015 /*
2016  * routine to invert the selected text, turning it on or off
2017  */
us_editpacinvertselection(WINDOWPART * win)2018 void us_editpacinvertselection(WINDOWPART *win)
2019 {
2020 	INTBIG i, startchar, endchar, ll, lc, hl, hc, lx, hx, ly, hy;
2021 	REGISTER EDITOR *e;
2022 
2023 	e = win->editor;
2024 	if (e == NOEDITOR) return;
2025 
2026 	if ((e->state&EGRAPHICSOFF) != 0) return;
2027 	ll = e->curline;   lc = e->curchar;
2028 	hl = e->endline;   hc = e->endchar;
2029 	if (ll > hl || (ll == hl && lc > hc))
2030 	{
2031 		i = hl;   hl = ll;   ll = i;
2032 		i = hc;   hc = lc;   lc = i;
2033 	}
2034 	for(i = ll; i <= hl; i++)
2035 	{
2036 		if (i < e->firstline) continue;
2037 		if (i-e->firstline >= e->screenlines) continue;
2038 		if (i == ll) startchar = lc; else startchar = 0;
2039 		if (i == hl) endchar = hc; else endchar = e->mostchars+e->horizfactor;
2040 		if (endchar == 0 && ll != hl) continue;
2041 
2042 		/* compute bounds of box to invert */
2043 		lx = e->offx + (startchar-e->horizfactor) * us_editpactwid - 1;
2044 		hx = e->offx + (endchar-e->horizfactor) * us_editpactwid - 1;
2045 		ly = e->revy - (i-e->firstline) * us_editpacthei - us_editpacthei;
2046 		hy = e->revy - (i-e->firstline) * us_editpacthei - 1;
2047 
2048 		/* limit to display */
2049 		if (lx > e->offx + e->swid || hx < e->offx-1) continue;
2050 		if (lx < e->offx-1) lx = e->offx-1;
2051 		if (hx > e->offx + e->swid) hx = e->offx + e->swid;
2052 		if (ly > e->revy || hy < e->revy - e->shei) continue;
2053 		if (ly < e->revy - e->shei) ly = e->revy - e->shei;
2054 		if (hy > e->revy) hy = e->revy;
2055 
2056 		screeninvertbox(win, lx, hx, ly, hy);
2057 	}
2058 }
2059 
2060 /******************** UNDO CONTROL ********************/
2061 
us_editpacdonetyping(EDITOR * e)2062 void us_editpacdonetyping(EDITOR *e)
2063 {
2064 	if ((e->state&TEXTTYPING) == 0) return;
2065 
2066 	if (e->curline < us_editpacundonewcurline ||
2067 		(e->curline == us_editpacundonewcurline && e->curchar < us_editpacundonewcurchar))
2068 	{
2069 		us_editpacundonewcurline = e->curline;    us_editpacundonewcurchar = e->curchar;
2070 	}
2071 	if (e->endline > us_editpacundonewendline ||
2072 		(e->endline == us_editpacundonewendline && e->endchar > us_editpacundonewendchar))
2073 	{
2074 		us_editpacundonewendline = e->endline;    us_editpacundonewendchar = e->endchar;
2075 	}
2076 
2077 	e->state &= ~TEXTTYPING;
2078 }
2079 
us_editpacamtyping(EDITOR * e)2080 void us_editpacamtyping(EDITOR *e)
2081 {
2082 	REGISTER INTBIG len;
2083 
2084 	if ((e->state&TEXTTYPING) != 0)
2085 	{
2086 		if (e->curline < us_editpacundonewcurline ||
2087 			(e->curline == us_editpacundonewcurline && e->curchar < us_editpacundonewcurchar))
2088 		{
2089 			us_editpacundonewcurline = e->curline;
2090 			us_editpacundonewcurchar = e->curchar;
2091 		}
2092 		if (e->endline > us_editpacundonewendline ||
2093 			(e->endline == us_editpacundonewendline && e->endchar > us_editpacundonewendchar))
2094 		{
2095 			us_editpacundonewendline = e->endline;
2096 			us_editpacundonewendchar = e->endchar;
2097 		}
2098 		return;
2099 	}
2100 	e->state |= TEXTTYPING | TEXTTYPED;
2101 
2102 	/* start of typing: save current position for what is typed */
2103 	us_editpacundonewcurline = us_editpacundonewendline = e->curline;
2104 	us_editpacundonewcurchar = us_editpacundonewendchar = e->curchar;
2105 
2106 	/* remember former selection */
2107 	us_editpacundooldcurline = e->curline;    us_editpacundooldcurchar = e->curchar;
2108 
2109 	/* save what is selected */
2110 	len = us_editpaccharstocurrent(e, e->endchar, e->endline) + 1;
2111 	if (len > us_editpacundobuffersize)
2112 	{
2113 		if (us_editpacundobuffersize != 0) efree(us_editpacundobuffer);
2114 		us_editpacundobuffersize = 0;
2115 		us_editpacundobuffer = (CHAR *)emalloc(len * SIZEOFCHAR, us_tool->cluster);
2116 		if (us_editpacundobuffer == 0) return;
2117 		us_editpacundobuffersize = len;
2118 	}
2119 	us_editpacloadselection(e, us_editpacundobuffer);
2120 }
2121 
us_editpactypeddelete(EDITOR * e)2122 void us_editpactypeddelete(EDITOR *e)
2123 {
2124 	REGISTER INTBIG len, i;
2125 	REGISTER CHAR *newbuffer;
2126 
2127 	if ((e->state&TEXTTYPING) == 0) return;
2128 
2129 	/* if still beyond start of typing, quit */
2130 	if (e->curline > us_editpacundooldcurline ||
2131 		(e->curline == us_editpacundooldcurline && e->curchar >= us_editpacundooldcurchar))
2132 			return;
2133 
2134 	/* make sure there is room for one more character */
2135 	len = estrlen(us_editpacundobuffer) +
2136 		us_editpaccharstocurrent(e, us_editpacundooldcurchar, us_editpacundooldcurline) + 1;
2137 	if (len > us_editpacundobuffersize)
2138 	{
2139 		newbuffer = (CHAR *)emalloc(len * SIZEOFCHAR, us_tool->cluster);
2140 		if (newbuffer == 0) return;
2141 		(void)estrcpy(newbuffer, us_editpacundobuffer);
2142 		if (us_editpacundobuffersize > 0) efree(us_editpacundobuffer);
2143 		us_editpacundobuffer = newbuffer;
2144 		us_editpacundobuffersize = len;
2145 	}
2146 
2147 	/* shift the buffer up */
2148 	for(i=len-1; i>0; i--) us_editpacundobuffer[i] = us_editpacundobuffer[i-1];
2149 	us_editpacundobuffer[0] = e->textarray[e->curline][e->curchar];
2150 	if (us_editpacundobuffer[0] == 0) us_editpacundobuffer[0] = '\n';
2151 
2152 	us_editpacundooldcurline = e->curline;    us_editpacundooldcurchar = e->curchar;
2153 
2154 	us_editpacundonewcurline = us_editpacundonewendline = e->curline;
2155 	us_editpacundonewcurchar = us_editpacundonewendchar = e->curchar;
2156 }
2157 
us_editpaccharstocurrent(EDITOR * e,INTBIG endchar,INTBIG endline)2158 INTBIG us_editpaccharstocurrent(EDITOR *e, INTBIG endchar, INTBIG endline)
2159 {
2160 	REGISTER INTBIG len, line, startchar, startline, fromchar, tochar;
2161 
2162 	if (e->curline > endline || (e->curline == endline && e->curchar > endchar))
2163 	{
2164 		startchar = endchar;   endchar = e->curchar;
2165 		startline = endline;   endline = e->curline;
2166 	} else
2167 	{
2168 		startchar = e->curchar;
2169 		startline = e->curline;
2170 	}
2171 	len = 0;
2172 	for(line = startline; line <= endline; line++)
2173 	{
2174 		if (line == startline) fromchar = startchar; else fromchar = 0;
2175 		if (line == endline) tochar = endchar; else
2176 			tochar = estrlen(e->textarray[line])+1;
2177 		len += tochar - fromchar;
2178 	}
2179 	return(len);
2180 }
2181 
us_editpacloadselection(EDITOR * e,CHAR * buf)2182 void us_editpacloadselection(EDITOR *e, CHAR *buf)
2183 {
2184 	REGISTER INTBIG len, line, startch, endch, i, ch;
2185 
2186 	len = 0;
2187 	for(line = e->curline; line <= e->endline; line++)
2188 	{
2189 		if (line == e->curline) startch = e->curchar; else startch = 0;
2190 		if (line == e->endline) endch = e->endchar; else endch = estrlen(e->textarray[line])+1;
2191 		for(i=startch; i<endch; i++)
2192 		{
2193 			ch = e->textarray[line][i];
2194 			if (ch == 0) ch = '\n';
2195 			buf[len++] = (CHAR)ch;
2196 		}
2197 	}
2198 	buf[len] = 0;
2199 }
2200 
us_editpacadvanceposition(EDITOR * e,INTBIG * chr,INTBIG * lne)2201 void us_editpacadvanceposition(EDITOR *e, INTBIG *chr, INTBIG *lne)
2202 {
2203 	if (e->textarray[*lne][*chr] != 0) (*chr)++; else
2204 	{
2205 		*chr = 0;
2206 		(*lne)++;
2207 		if (*lne >= e->linecount) *lne = 0;
2208 	}
2209 }
2210 
us_editpacbackupposition(EDITOR * e,INTBIG * chr,INTBIG * lne)2211 void us_editpacbackupposition(EDITOR *e, INTBIG *chr, INTBIG *lne)
2212 {
2213 	(*chr)--;
2214 	if (*chr < 0)
2215 	{
2216 		(*lne)--;
2217 		if (*lne < 0) *lne = e->linecount - 1;
2218 		*chr = estrlen(e->textarray[*lne]) - 1;
2219 	}
2220 }
2221 
2222 /******************** SUPPORT ********************/
2223 
2224 /*
2225  * routine to determine the extents of the editing window
2226  */
us_editpaccomputebounds(WINDOWPART * win,EDITOR * e)2227 void us_editpaccomputebounds(WINDOWPART *win, EDITOR *e)
2228 {
2229 	REGISTER INTBIG offset;
2230 
2231 	e->offx = win->uselx + 1 + LEFTINDENT;
2232 	e->swid = win->usehx - e->offx - 1;
2233 	offset = 1;
2234 	if ((win->state&WINDOWTYPE) != POPTEXTWINDOW) e->swid -= DISPLAYSLIDERSIZE;
2235 		else offset++;
2236 	e->shei = win->usehy - win->usely - us_editpacthei*HEADERLINES - offset - DISPLAYSLIDERSIZE;
2237 	e->revy = e->shei + win->usely + offset + DISPLAYSLIDERSIZE;
2238 	e->screenlines = e->shei / us_editpacthei;
2239 	e->screenchars = e->swid / us_editpactwid;
2240 }
2241 
us_editpacbeginwork(WINDOWPART * win)2242 void us_editpacbeginwork(WINDOWPART *win)
2243 {
2244 	EDITOR *e;
2245 	REGISTER CHAR *newline;
2246 	REGISTER INTBIG len;
2247 
2248 	e = win->editor;
2249 	if (e == NOEDITOR) return;
2250 	if (e->working == e->curline) return;
2251 	us_editpacshipchanges(win);
2252 	e->working = e->curline;
2253 
2254 	/* make sure there is room in the line-change buffer */
2255 	len = estrlen(e->textarray[e->working]);
2256 	if (len >= e->mostchars)
2257 	{
2258 		newline = (CHAR *)emalloc((len+1) * SIZEOFCHAR, us_tool->cluster);
2259 		if (newline == 0) return;
2260 		efree(e->formerline);
2261 		e->formerline = newline;
2262 		e->mostchars = len;
2263 	}
2264 
2265 	/* save the current line */
2266 	(void)estrcpy(e->formerline, e->textarray[e->working]);
2267 }
2268 
2269 /*
2270  * routine to double the number of lines in the text buffer
2271  */
us_editpacaddmorelines(EDITOR * e)2272 void us_editpacaddmorelines(EDITOR *e)
2273 {
2274 	REGISTER INTBIG oldlines, i;
2275 	REGISTER INTBIG *maxchars;
2276 	REGISTER CHAR **textarray;
2277 
2278 	/* save former buffer size, double it */
2279 	oldlines = e->maxlines;
2280 	e->maxlines *= 2;
2281 	if (e->maxlines <= 0) e->maxlines = 1;
2282 
2283 	/* allocate new arrays */
2284 	maxchars = (INTBIG *)emalloc((e->maxlines * SIZEOFINTBIG), us_tool->cluster);
2285 	if (maxchars == 0) ttyputnomemory();
2286 	textarray = (CHAR **)emalloc((e->maxlines * (sizeof (CHAR *))), us_tool->cluster);
2287 	if (textarray == 0) ttyputnomemory();
2288 
2289 	/* copy old information */
2290 	for(i=0; i<e->maxlines; i++)
2291 	{
2292 		if (i >= oldlines)
2293 		{
2294 			textarray[i] = (CHAR *)emalloc(DEFAULTWID * SIZEOFCHAR, us_tool->cluster);
2295 			if (textarray[i] == 0) ttyputnomemory();
2296 			textarray[i][0] = 0;
2297 			maxchars[i] = DEFAULTWID;
2298 		} else
2299 		{
2300 			textarray[i] = e->textarray[i];
2301 			maxchars[i] = e->maxchars[i];
2302 		}
2303 	}
2304 
2305 	/* free old arrays */
2306 	efree((CHAR *)e->textarray);
2307 	efree((CHAR *)e->maxchars);
2308 
2309 	/* setup pointers correctly */
2310 	e->textarray = textarray;
2311 	e->maxchars = maxchars;
2312 }
2313 
2314 /*
2315  * routine to increase the number of characters in line "line" to "need" (+1 for the null)
2316  */
us_editpacaddmorechars(EDITOR * e,INTBIG line,INTBIG need)2317 void us_editpacaddmorechars(EDITOR *e, INTBIG line, INTBIG need)
2318 {
2319 	REGISTER CHAR *oldline;
2320 
2321 	/* extend the current line */
2322 	if (line >= e->maxlines) return;
2323 	oldline = e->textarray[line];
2324 	e->maxchars[line] = need+1;
2325 	e->textarray[line] = (CHAR *)emalloc((need+1) * SIZEOFCHAR, us_tool->cluster);
2326 	(void)estrcpy(e->textarray[line], oldline);
2327 	efree(oldline);
2328 }
2329 
2330 /******************** LOW LEVEL GRAPHICS ********************/
2331 
2332 /*
2333  * move text starting at character position (sx,sy) to character position
2334  * (dx, dy).
2335  */
us_editpacmovebox(WINDOWPART * win,INTBIG dx,INTBIG dy,INTBIG wid,INTBIG hei,INTBIG sx,INTBIG sy)2336 void us_editpacmovebox(WINDOWPART *win, INTBIG dx, INTBIG dy, INTBIG wid, INTBIG hei, INTBIG sx,
2337 	INTBIG sy)
2338 {
2339 	REGISTER EDITOR *e;
2340 
2341 	e = win->editor;
2342 	if (e == NOEDITOR) return;
2343 	screenmovebox(win, sx*us_editpactwid+e->offx, e->revy-(sy*us_editpacthei+hei-1), wid, hei,
2344 		dx*us_editpactwid+e->offx, e->revy-(dy*us_editpacthei+hei-1));
2345 }
2346 
2347 /*
2348  * erase text starting at character position (dx,dy) for (wid, hei)
2349  */
us_editpacclearbox(WINDOWPART * win,INTBIG dx,INTBIG dy,INTBIG wid,INTBIG hei)2350 void us_editpacclearbox(WINDOWPART *win, INTBIG dx, INTBIG dy, INTBIG wid, INTBIG hei)
2351 {
2352 	REGISTER EDITOR *e;
2353 
2354 	e = win->editor;
2355 	if (e == NOEDITOR) return;
2356 
2357 	dx = (dx * us_editpactwid) + e->offx;
2358 	dy *= us_editpacthei;
2359 	screendrawbox(win, dx, dx+wid-1, e->revy-(dy+hei-1), e->revy-dy, &us_ebox);
2360 }
2361 
2362 /*
2363  * write text "str" starting at character position (x,y)
2364  */
us_editpactext(WINDOWPART * win,CHAR * str,INTBIG x,INTBIG y)2365 void us_editpactext(WINDOWPART *win, CHAR *str, INTBIG x, INTBIG y)
2366 {
2367 	INTBIG xpos, len, diff, i, clip;
2368 	REGISTER EDITOR *e;
2369 	REGISTER void *infstr;
2370 
2371 	e = win->editor;
2372 	if (e == NOEDITOR) return;
2373 
2374 	len = estrlen(str);
2375 	diff = e->horizfactor - x;
2376 
2377 	/* make sure string doesn't start to left of edit window */
2378 	if (diff > 0)
2379 	{
2380 		if (diff > len) return;
2381 		str = &str[diff];
2382 		x = e->horizfactor;
2383 		len -= diff;
2384 	}
2385 
2386 	/* make sure string doesn't start to the right of the edit window */
2387 	if (x-e->horizfactor >= e->screenchars) return;
2388 
2389 	xpos = (x - e->horizfactor) * us_editpactwid;
2390 	us_menutext.col = el_colmentxt;
2391 
2392 	if (len + x - e->horizfactor > e->screenchars)
2393 	{
2394 		infstr = initinfstr();
2395 		clip = e->screenchars + e->horizfactor - x;
2396 		for(i=0; i<clip; i++) addtoinfstr(infstr, str[i]);
2397 		str = returninfstr(infstr);
2398 	}
2399 	screendrawtext(win, xpos + e->offx, e->revy-(y+1)*us_editpacthei, str, &us_menutext);
2400 }
2401