1 /* -*- tab-width: 4 -*-
2 *
3 * Electric(tm) VLSI Design System
4 *
5 * File: usreditemacs.c
6 * User interface tool: EMACS-like text window handler
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 /*
33 * This EMACS-like text editor accepts the following commands:
34 * ^A cursor to start-of-line
35 * ^B backup one character
36 * ^D delete the next character (cannot delete line breaks)
37 * ^E cursor to end-of-line
38 * ^F forward one character
39 * ^G flush state (and force evaluation of changed line)
40 * ^H delete the previous character (cannot delete line breaks)
41 * ^K delete to end-of-line (or kill line if on a null line)
42 * ^L redraw screen
43 * RETURN insert new line (only if at end of line)
44 * ^N next line
45 * ^O insert new line (only if at beginning of line)
46 * ^P previous line
47 * ^R reverse search
48 * ^S forward search
49 * ^V shift screen up one page
50 * ^X^V read a text file from disk (you are prompted for the file name)
51 * ^X^W write the text file to disk (you are prompted for the file name)
52 * ^Xd terminate this editor window
53 * ^Y restore line deleted with ^K
54 * ^Z shift screen up one line
55 * DEL delete the previous character (cannot delete line breaks)
56 * M(B) backup one word
57 * M(D) delete the next word (cannot delete line breaks)
58 * M(F) forward one word
59 * M(H) delete the previous word (cannot delete line breaks)
60 * M(V) shift screen down one page
61 * M(X) execute an Electric command
62 * M(Z) shift screen down one line
63 * M(<) cursor to beginning of file
64 * M(>) cursor to end of file
65 * M(DEL) delete the previous word (cannot delete line breaks)
66 *
67 * All printing characters "self-insert"
68 * Meta characters can be typed by holding the META key or by prefixing
69 * the character with an ESCAPE.
70 * In popup editor windows, all commands that would create a new line
71 * cause the editor to exit
72 */
73
74 #include "global.h"
75 #include "egraphics.h"
76 #include "usr.h"
77 #include "usreditemacs.h"
78
79 #define CTLA 01 /* ^A */
80 #define CTLB 02 /* ^B */
81 #define CTLC 03 /* ^C */
82 #define CTLD 04 /* ^D */
83 #define CTLE 05 /* ^E */
84 #define CTLF 06 /* ^F */
85 #define CTLG 07 /* ^G */
86 #define CTLH 010 /* ^H */
87 #define CTLK 013 /* ^K */
88 #define CTLL 014 /* ^L */
89 #define CTLN 016 /* ^N */
90 #define CTLO 017 /* ^O */
91 #define CTLP 020 /* ^P */
92 #define CTLR 022 /* ^R */
93 #define CTLS 023 /* ^S */
94 #define CTLV 026 /* ^V */
95 #define CTLW 027 /* ^W */
96 #define CTLX 030 /* ^X */
97 #define CTLY 031 /* ^Y */
98 #define CTLZ 032 /* ^Z */
99
100 /* the bits in us_lastemacschar */
101 #define CONTROLX 1 /* ^X was last character typed */
102 #define ESCAPE 2 /* ESCAPE was last character typed */
103
104 #define HEADERLINES 2
105
106 extern GRAPHICS us_ebox, us_menutext, us_menufigs;
107
108 INTBIG us_lastemacschar; /* state of last character typed */
109 static INTBIG us_twid, us_thei; /* size of a single letter */
110 static INTBIG us_editemacsfont; /* font size for editor */
111 static CHAR *us_killbuf; /* saved line when ^K is done */
112 static INTBIG us_killbufchars = 0; /* characters in kill buffer */
113 static CHAR *us_searchbuf = 0; /* search string for ^S and ^R */
114
115 /* prototypes for local routines */
116 static void us_editemacsgotbutton(WINDOWPART*, INTBIG, INTBIG, INTBIG);
117 static void us_editemacsredraweditor(WINDOWPART*);
118 static BOOLEAN us_editemacsimplementchar(WINDOWPART*, INTBIG, BOOLEAN, BOOLEAN);
119 static BOOLEAN us_editemacsbackupchar(WINDOWPART*, BOOLEAN);
120 static BOOLEAN us_editemacsadvancechar(WINDOWPART*, BOOLEAN);
121 static void us_editemacsdeletechar(WINDOWPART*, BOOLEAN fromuser);
122 static void us_editemacsshiftscreenup(WINDOWPART*);
123 static void us_editemacsshiftscreendown(WINDOWPART*);
124 static void us_editemacsensuretextshown(WINDOWPART*, INTBIG);
125 static void us_editemacsredrawscreen(WINDOWPART*);
126 static void us_editemacsredrawline(WINDOWPART*, INTBIG);
127 static void us_editemacssetheader(WINDOWPART*, CHAR*);
128 static void us_editemacsflashcursor(WINDOWPART*);
129 static void us_editemacsoffhighlight(WINDOWPART*);
130 static void us_editemacscleanupline(WINDOWPART*, INTBIG);
131 static void us_editemacsworkingoncurline(EDITOR*);
132 static void us_editemacsaddmorelines(EDITOR*);
133 static void us_editemacsaddmorechars(EDITOR*, INTBIG);
134 static void us_editemacsgetbuffers(EDITOR*);
135 static void us_editemacsmovebox(WINDOWPART*, INTBIG, INTBIG, INTBIG, INTBIG, INTBIG, INTBIG);
136 static void us_editemacsclearbox(WINDOWPART*, INTBIG, INTBIG, INTBIG, INTBIG);
137 static void us_editemacsinvertbox(WINDOWPART*, INTBIG, INTBIG, INTBIG, INTBIG);
138 static void us_editemacstext(WINDOWPART*, CHAR*, INTBIG, INTBIG);
139 static void us_editemacsdosearch(WINDOWPART *win, CHAR *str, BOOLEAN reverse,
140 BOOLEAN fromtop, BOOLEAN casesensitive, BOOLEAN fromuser);
141 static CHAR us_editemacsnextvalidcharacter(EDITOR *e);
142
143 /******************** INTERFACE FOR TEXT WINDOW ********************/
144
145 /*
146 * routine to convert window "oriwin" to an EMACS editor. If "oriwin" is
147 * NOWINDOWPART, create a popup window with one line. The window header is in
148 * "header". The number of characters and lines are placed in "chars" and
149 * "lines". Returns the window (NOWINDOWPART if the editor cannot be started).
150 */
us_editemacsmakeeditor(WINDOWPART * oriwin,CHAR * header,INTBIG * chars,INTBIG * lines)151 WINDOWPART *us_editemacsmakeeditor(WINDOWPART *oriwin, CHAR *header, INTBIG *chars, INTBIG *lines)
152 {
153 INTBIG i, x, y;
154 UINTBIG descript[TEXTDESCRIPTSIZE];
155 INTBIG swid, shei, pwid;
156 REGISTER EDITOR *e;
157 REGISTER VARIABLE *var;
158 REGISTER WINDOWPART *win;
159
160 /* if no window exists, create one as a popup */
161 win = oriwin;
162 if (win == NOWINDOWPART)
163 {
164 getpaletteparameters(&swid, &shei, &pwid);
165 if (el_curwindowpart == NOWINDOWPART)
166 {
167 x = swid / 2;
168 y = shei / 2;
169 } else
170 {
171 (void)getxy(&x, &y);
172 x = applyxscale(el_curwindowpart, x-el_curwindowpart->screenlx) +
173 el_curwindowpart->uselx;
174 y = applyyscale(el_curwindowpart, y-el_curwindowpart->screenly) +
175 el_curwindowpart->usely;
176 }
177
178 /* create a window that covers the popup */
179 startobjectchange((INTBIG)us_tool, VTOOL);
180 win = newwindowpart(x_("popup"), el_curwindowpart);
181 win->uselx = maxi(x-200, 0);
182 win->usely = maxi(y-us_thei-1, 0);
183 win->usehx = mini(win->uselx+400, swid-1);
184 win->usehy = mini(win->usely+us_thei*(HEADERLINES+1)+3, shei-1);
185 win->screenlx = win->uselx;
186 win->screenhx = win->usehx;
187 win->screenly = win->usely;
188 win->screenhy = win->usehy;
189 computewindowscale(win);
190 win->state = (win->state & ~WINDOWTYPE) | POPTEXTWINDOW;
191 } else
192 {
193 if ((win->state&WINDOWTYPE) == DISPWINDOW)
194 {
195 win->usehx += DISPLAYSLIDERSIZE;
196 win->usely -= DISPLAYSLIDERSIZE;
197 }
198 win->state = (win->state & ~(WINDOWTYPE|WINDOWMODE)) | TEXTWINDOW;
199 }
200
201 win->curnodeproto = NONODEPROTO;
202 win->buttonhandler = us_editemacsgotbutton;
203 win->charhandler = us_editemacsgotchar;
204 win->termhandler = us_editemacseditorterm;
205 win->redisphandler = us_editemacsredraweditor;
206 win->changehandler = 0;
207 win->screenlx = win->uselx; win->screenhx = win->usehx;
208 win->screenly = win->usely; win->screenhy = win->usehy;
209 computewindowscale(win);
210
211 /*
212 * the font that is used by the editor is the fixed-width font, TXTEDITOR.
213 * This can be changed by setting the variable "USER_textedit_font" on the user tool
214 * object. The value is the point size minus 4 divided by 2 (the value 0 is the
215 * default font TXTEDITOR). For example, to set the font to be 14 points, type:
216 * -var set tool:user.USER_textedit_font 5
217 */
218 us_editemacsfont = TXTEDITOR;
219 var = getval((INTBIG)us_tool, VTOOL, VINTEGER, x_("USER_textedit_font"));
220 if (var != NOVARIABLE && var->addr >= 4)
221 us_editemacsfont = var->addr;
222 TDCLEAR(descript);
223 TDSETSIZE(descript, us_editemacsfont);
224 screensettextinfo(win, NOTECHNOLOGY, descript);
225 screengettextsize(win, x_("X"), &us_twid, &us_thei);
226
227 /* create a new editor object */
228 e = us_alloceditor();
229 if (e == NOEDITOR) return(NOWINDOWPART);
230 e->state = (e->state & ~(EDITORTYPE|EGRAPHICSOFF|LINESFIXED)) | EMACSEDITOR;
231 (void)allocstring(&e->header, header, us_tool->cluster);
232 e->highlightedline = -1;
233 us_lastemacschar = 0;
234 e->curline = e->curchar = 0;
235 e->working = -1;
236 e->firstline = 0;
237 e->swid = win->usehx - win->uselx - 2;
238 e->shei = win->usehy - win->usely - us_thei*HEADERLINES - 1;
239 e->offx = win->uselx + 1;
240 e->revy = e->shei + win->usely + 1;
241 *chars = e->screenchars = e->swid / us_twid;
242 *lines = e->screenlines = e->shei / us_thei;
243
244 /* turn this window into an EMACS editor */
245 if ((e->state&EDITORINITED) == 0)
246 {
247 /* first time: allocate buffers */
248 e->state |= EDITORINITED;
249 e->maxlines = e->screenlines;
250 e->mostchars = e->screenchars;
251 e->textarray = (CHAR **)emalloc((e->maxlines * (sizeof (CHAR *))),
252 us_tool->cluster);
253 if (e->textarray == 0) ttyputnomemory();
254 e->maxchars = (INTBIG *)emalloc((e->maxlines * SIZEOFINTBIG), us_tool->cluster);
255 if (e->maxchars == 0) ttyputnomemory();
256 us_editemacsgetbuffers(e);
257 for(i=0; i<e->maxlines; i++)
258 {
259 e->textarray[i] = (CHAR *)emalloc((e->screenchars+1) * SIZEOFCHAR, us_tool->cluster);
260 if (e->textarray[i] == 0) ttyputnomemory();
261 e->textarray[i][0] = 0;
262 e->maxchars[i] = e->screenchars;
263 }
264 } else
265 {
266 /* make sure buffers cover the screen */
267 while (e->screenlines > e->maxlines) us_editemacsaddmorelines(e);
268 for(i=0; i<e->maxlines; i++)
269 {
270 e->textarray[i][0] = 0;
271 while (e->screenchars > e->maxchars[i])
272 us_editemacsaddmorechars(e, i);
273 }
274 }
275
276 /* now finish initializing window */
277 win->editor = e;
278 if (oriwin != NOWINDOWPART)
279 {
280 /* clear window and write header */
281 us_editemacssetheader(win, header);
282
283 /* show initial cursor */
284 us_editemacsflashcursor(win);
285 } else
286 {
287 /* finish initializing window if it is a new popup one */
288 e->savedbox = screensavebox(win, maxi(e->offx-2,0),
289 e->offx+e->swid+2, maxi(e->revy-e->shei-2,0),
290 e->revy+us_thei*HEADERLINES+1);
291 endobjectchange((INTBIG)us_tool, VTOOL);
292 }
293 return(win);
294 }
295
us_freeedemacsmemory(void)296 void us_freeedemacsmemory(void)
297 {
298 if (us_searchbuf != 0) efree(us_searchbuf);
299 }
300
301 /*
302 * routine to free all memory associated with this editor
303 */
us_editemacsterminate(EDITOR * e)304 void us_editemacsterminate(EDITOR *e)
305 {
306 REGISTER INTBIG i;
307
308 for(i=0; i<e->maxlines; i++)
309 efree((CHAR *)e->textarray[i]);
310 efree((CHAR *)e->textarray);
311 efree((CHAR *)e->maxchars);
312 efree((CHAR *)e->formerline);
313 efree((CHAR *)us_killbuf);
314 us_killbufchars = 0;
315 }
316
317 /*
318 * routine to return the total number of valid lines in the edit buffer
319 */
us_editemacstotallines(WINDOWPART * win)320 INTBIG us_editemacstotallines(WINDOWPART *win)
321 {
322 REGISTER INTBIG i;
323 REGISTER EDITOR *e;
324
325 e = win->editor;
326 if (e == NOEDITOR) return(0);
327 for(i = e->maxlines-1; i >= 0; i--) if (e->textarray[i][0] != 0) break;
328 return(i+1);
329 }
330
331 /*
332 * routine to get the string on line "lindex" (0 based). A negative line
333 * returns the current line. Returns -1 if the index is beyond the file limit
334 */
us_editemacsgetline(WINDOWPART * win,INTBIG lindex)335 CHAR *us_editemacsgetline(WINDOWPART *win, INTBIG lindex)
336 {
337 REGISTER EDITOR *e;
338
339 e = win->editor;
340 if (e == NOEDITOR) return(x_(""));
341 if (lindex < 0) lindex = e->curline;
342 if (lindex >= e->maxlines) return(NOSTRING);
343 return(e->textarray[lindex]);
344 }
345
346 /*
347 * routine to add line "str" to the text cell to become line "lindex"
348 */
us_editemacsaddline(WINDOWPART * win,INTBIG lindex,CHAR * str)349 void us_editemacsaddline(WINDOWPART *win, INTBIG lindex, CHAR *str)
350 {
351 REGISTER CHAR *pt;
352 REGISTER INTBIG savedline, savedchar;
353 REGISTER EDITOR *e;
354
355 e = win->editor;
356 if (e == NOEDITOR) return;
357 us_editemacsflashcursor(win);
358 savedchar = e->curchar; savedline = e->curline;
359 e->curline = lindex; e->curchar = 0;
360 (void)us_editemacsimplementchar(win, CTLO, FALSE, FALSE);
361 if (str[0] == 0) (void)us_editemacsimplementchar(win, ' ', FALSE, FALSE); else
362 for(pt = str; *pt != 0; pt++)
363 (void)us_editemacsimplementchar(win, *pt, FALSE, FALSE);
364 e->curchar = savedchar; e->curline = savedline;
365 us_editemacsflashcursor(win);
366 }
367
368 /*
369 * routine to replace the line number "lindex" with the string "str".
370 */
us_editemacsreplaceline(WINDOWPART * win,INTBIG lindex,CHAR * str)371 void us_editemacsreplaceline(WINDOWPART *win, INTBIG lindex, CHAR *str)
372 {
373 REGISTER CHAR *pt;
374 REGISTER INTBIG savedline, savedchar;
375 REGISTER EDITOR *e;
376
377 e = win->editor;
378 if (e == NOEDITOR) return;
379 us_editemacsflashcursor(win);
380 savedchar = e->curchar; savedline = e->curline;
381 if (e->curline == lindex) savedchar = 0;
382 e->curline = lindex; e->curchar = 0;
383 if (e->textarray[lindex][0] != 0)
384 (void)us_editemacsimplementchar(win, CTLK, FALSE, FALSE);
385 for(pt = str; *pt != 0; pt++)
386 (void)us_editemacsimplementchar(win, *pt, FALSE, FALSE);
387 e->curchar = savedchar; e->curline = savedline;
388 us_editemacsflashcursor(win);
389 }
390
391 /*
392 * routine to delete line number "lindex"
393 */
us_editemacsdeleteline(WINDOWPART * win,INTBIG lindex)394 void us_editemacsdeleteline(WINDOWPART *win, INTBIG lindex)
395 {
396 REGISTER INTBIG savedchar, savedline;
397 REGISTER EDITOR *e;
398
399 e = win->editor;
400 if (e == NOEDITOR) return;
401 us_editemacsflashcursor(win);
402 savedchar = e->curchar; savedline = e->curline;
403 if (e->curline == lindex) { savedline++; savedchar = 0; }
404 e->curline = lindex; e->curchar = 0;
405 if (e->textarray[lindex][0] != 0)
406 (void)us_editemacsimplementchar(win, CTLK, FALSE, FALSE);
407 (void)us_editemacsimplementchar(win, CTLK, FALSE, FALSE);
408 e->curchar = savedchar; e->curline = savedline;
409 us_editemacsflashcursor(win);
410 }
411
412 /*
413 * routine to highlight lines "lindex" to "hindex" in the text window
414 */
us_editemacshighlightline(WINDOWPART * win,INTBIG lindex,INTBIG hindex)415 void us_editemacshighlightline(WINDOWPART *win, INTBIG lindex, INTBIG hindex)
416 {
417 REGISTER EDITOR *e;
418
419 e = win->editor;
420 if (e == NOEDITOR) return;
421 us_editemacsoffhighlight(win);
422 if ((e->state&EGRAPHICSOFF) != 0) return;
423 if (hindex != lindex)
424 ttyputmsg(_("EMACS can only highlight a single line"));
425 e->highlightedline = lindex;
426 us_editemacsensuretextshown(win, e->highlightedline);
427 if (e->highlightedline-e->firstline < e->screenlines &&
428 e->highlightedline >= e->firstline)
429 us_editemacsinvertbox(win, 0, e->highlightedline-e->firstline,
430 e->swid, us_thei);
431 }
432
433 /*
434 * routine to stop the graphic display of changes (for batching)
435 */
us_editemacssuspendgraphics(WINDOWPART * win)436 void us_editemacssuspendgraphics(WINDOWPART *win)
437 {
438 REGISTER EDITOR *e;
439
440 e = win->editor;
441 if (e == NOEDITOR) return;
442 e->state |= EGRAPHICSOFF;
443 }
444
445 /*
446 * routine to restart the graphic display of changes and redisplay (for batching)
447 */
us_editemacsresumegraphics(WINDOWPART * win)448 void us_editemacsresumegraphics(WINDOWPART *win)
449 {
450 REGISTER EDITOR *e;
451
452 e = win->editor;
453 if (e == NOEDITOR) return;
454 e->state &= ~EGRAPHICSOFF;
455 us_editemacsredrawscreen(win);
456 us_editemacsflashcursor(win);
457 }
458
459 /*
460 * routine to write the text file to "file"
461 */
us_editemacswritetextfile(WINDOWPART * win,CHAR * file)462 void us_editemacswritetextfile(WINDOWPART *win, CHAR *file)
463 {
464 REGISTER EDITOR *e;
465 REGISTER INTBIG i, j;
466 REGISTER FILE *f;
467 CHAR *truename;
468
469 e = win->editor;
470 if (e == NOEDITOR) return;
471
472 /* find the last line */
473 for(j = e->maxlines-1; j >= 0; j--)
474 if (e->textarray[j][0] != 0) break;
475 if (j < 0)
476 {
477 ttyputerr(_("File is empty"));
478 return;
479 }
480
481 f = xcreate(file, el_filetypetext, _("Text File"), &truename);
482 if (f == NULL)
483 {
484 if (truename != 0) ttyputerr(_("Cannot write %s"), truename);
485 return;
486 }
487
488 for(i=0; i<=j; i++) xprintf(f, x_("%s\n"), e->textarray[i]);
489 xclose(f);
490 ttyputmsg(_("%s written"), truename);
491 }
492
493 /*
494 * routine to read the text file "file"
495 */
us_editemacsreadtextfile(WINDOWPART * win,CHAR * file)496 void us_editemacsreadtextfile(WINDOWPART *win, CHAR *file)
497 {
498 REGISTER EDITOR *e;
499 REGISTER INTBIG linecount, i, c;
500 REGISTER FILE *f;
501 CHAR *filename;
502
503 e = win->editor;
504 if (e == NOEDITOR) return;
505
506 /* get the file */
507 f = xopen(file, el_filetypetext, x_(""), &filename);
508 if (f == NULL)
509 {
510 ttyputerr(_("Cannot read %s"), file);
511 return;
512 }
513 ttyputmsg(_("Reading %s"), file);
514
515 /* erase the text that is there */
516 e->state |= EGRAPHICSOFF;
517 for(i=0; i<e->maxlines; i++)
518 e->textarray[i][0] = 0;
519 e->curline = e->curchar = e->firstline = 0;
520
521 /* read the file */
522 for(;;)
523 {
524 c = xgetc(f);
525 if (c == EOF) break;
526 (void)us_editemacsimplementchar(win, c&0177, FALSE, FALSE);
527 }
528 xclose(f);
529
530 /* announce the new text */
531 if (win->changehandler != 0)
532 {
533 linecount = e->curline;
534 if (e->curchar != 0) linecount++;
535 (*win->changehandler)(win, REPLACEALLTEXT, x_(""), (CHAR *)e->textarray,
536 linecount);
537 }
538
539 /* restore the display */
540 e->state &= ~EGRAPHICSOFF;
541 us_editemacsredrawscreen(win);
542 }
543
544 /******************** WINDOW CONTROL ********************/
545
us_editemacseditorterm(WINDOWPART * win)546 void us_editemacseditorterm(WINDOWPART *win)
547 {
548 REGISTER EDITOR *e;
549
550 e = win->editor;
551 if (e == NOEDITOR) return;
552
553 us_editemacsshipchanges(win);
554 if ((win->state&WINDOWTYPE) == POPTEXTWINDOW)
555 {
556 screenrestorebox(e->savedbox, 0);
557 }
558 }
559
us_editemacsgotbutton(WINDOWPART * win,INTBIG but,INTBIG x,INTBIG y)560 void us_editemacsgotbutton(WINDOWPART *win, INTBIG but, INTBIG x, INTBIG y)
561 {
562 REGISTER EDITOR *e;
563 REGISTER INTBIG xc, yc, len;
564
565 /* changes to the mouse-wheel are handled by the user interface */
566 if (wheelbutton(but))
567 {
568 us_buttonhandler(win, but, x, y);
569 return;
570 }
571 ttynewcommand();
572
573 e = win->editor;
574 if (e == NOEDITOR) return;
575 xc = (x-e->offx) / us_twid;
576 if (xc < 0) xc = 0;
577 yc = (e->revy-y) / us_thei + e->firstline;
578 if (yc < e->firstline) yc = e->firstline;
579 if (yc >= e->maxlines) yc = e->maxlines-1;
580 len = estrlen(e->textarray[yc]);
581 if (xc > len) xc = len;
582 us_editemacsflashcursor(win);
583 e->curchar = xc;
584 e->curline = yc;
585 us_editemacsflashcursor(win);
586 }
587
us_editemacsredraweditor(WINDOWPART * win)588 void us_editemacsredraweditor(WINDOWPART *win)
589 {
590 REGISTER INTBIG i;
591 REGISTER EDITOR *e;
592
593 e = win->editor;
594 if (e == NOEDITOR) return;
595
596 /* compute window extents */
597 e->swid = win->usehx - win->uselx - 2;
598 e->shei = win->usehy - win->usely - us_thei*HEADERLINES - 1;
599 e->offx = win->uselx + 1;
600 e->revy = e->shei + win->usely + 1;
601 e->screenlines = e->shei / us_thei;
602 e->screenchars = e->swid / us_twid;
603
604 while (e->screenlines > e->maxlines) us_editemacsaddmorelines(e);
605 for(i=0; i<e->maxlines; i++)
606 {
607 while (e->screenchars > e->maxchars[i])
608 us_editemacsaddmorechars(e, i);
609 }
610
611 us_editemacsredrawscreen(win);
612 us_editemacsflashcursor(win);
613 }
614
615 /*
616 * keyboard interrupt routine for the text window
617 */
us_editemacsgotchar(WINDOWPART * win,INTSML i,INTBIG special)618 BOOLEAN us_editemacsgotchar(WINDOWPART *win, INTSML i, INTBIG special)
619 {
620 REGISTER EDITOR *e;
621
622 e = win->editor;
623 if (e == NOEDITOR) return(TRUE);
624
625 /* convert arrow keys to movement keys */
626 if ((special&SPECIALKEYDOWN) != 0)
627 {
628 switch ((special&SPECIALKEY) >> SPECIALKEYSH)
629 {
630 case SPECIALKEYARROWL: i = 'b'; special = ACCELERATORDOWN; break;
631 case SPECIALKEYARROWR: i = 'f'; special = ACCELERATORDOWN; break;
632 case SPECIALKEYARROWU: i = 'p'; special = ACCELERATORDOWN; break;
633 case SPECIALKEYARROWD: i = 'n'; special = ACCELERATORDOWN; break;
634 }
635 }
636 if ((special&ACCELERATORDOWN) != 0)
637 {
638 us_editemacsflashcursor(win);
639 #ifndef MACOS
640 i = i - 'a' + CTLA;
641 if (us_editemacsimplementchar(win, i, FALSE, TRUE)) return(TRUE);
642 #else
643 if (us_editemacsimplementchar(win, i, TRUE, TRUE)) return(TRUE);
644 #endif
645 us_editemacsflashcursor(win);
646 } else
647 {
648 us_editemacsflashcursor(win);
649 if (us_editemacsimplementchar(win, i, FALSE, TRUE)) return(TRUE);
650 us_editemacsflashcursor(win);
651 }
652 setactivity(_("EMACS Editing"));
653 return(FALSE);
654 }
655
us_editemacscut(WINDOWPART * w)656 void us_editemacscut(WINDOWPART *w) { ttybeep(SOUNDBEEP, TRUE); }
657
us_editemacscopy(WINDOWPART * w)658 void us_editemacscopy(WINDOWPART *w) { ttybeep(SOUNDBEEP, TRUE); }
659
us_editemacspaste(WINDOWPART * w)660 void us_editemacspaste(WINDOWPART *w) { ttybeep(SOUNDBEEP, TRUE); }
661
us_editemacsundo(WINDOWPART * w)662 void us_editemacsundo(WINDOWPART *w) { ttybeep(SOUNDBEEP, TRUE); }
663
664 /*
665 * routine to search and/or replace text. If "replace" is nonzero, this is
666 * a replace. The meaning of "bits" is as follows:
667 * 1 search from top
668 * 2 replace all
669 * 4 case sensitive
670 * 8 search upwards
671 */
us_editemacssearch(WINDOWPART * w,CHAR * str,CHAR * replace,INTBIG bits)672 void us_editemacssearch(WINDOWPART *w, CHAR *str, CHAR *replace, INTBIG bits)
673 {
674 REGISTER BOOLEAN fromtop, reverse, casesensitive;
675
676 if (replace != 0)
677 {
678 ttyputerr(_("EMACS cannot replace yet"));
679 return;
680 }
681 if ((bits&1) != 0) fromtop = TRUE; else fromtop = FALSE;
682 if ((bits&4) != 0) casesensitive = TRUE; else casesensitive = FALSE;
683 if ((bits&8) != 0) reverse = TRUE; else reverse = FALSE;
684 us_editemacsflashcursor(w);
685 us_editemacsdosearch(w, str, reverse, fromtop, casesensitive, TRUE);
686 us_editemacsflashcursor(w);
687 }
688
us_editemacspan(WINDOWPART * win,INTBIG dx,INTBIG dy)689 void us_editemacspan(WINDOWPART *win, INTBIG dx, INTBIG dy)
690 {
691 REGISTER EDITOR *e;
692
693 e = win->editor;
694 if (e == NOEDITOR) return;
695
696 /* EMACS cannot handle horizontal panning */
697 if (dx != 0) return;
698 if (dy < 0)
699 {
700 if (e->firstline <= 0) return;
701 us_editemacsflashcursor(win);
702 e->firstline--;
703 } else
704 {
705 us_editemacsflashcursor(win);
706 e->firstline++;
707 }
708 us_editemacsredrawscreen(win);
709 us_editemacsflashcursor(win);
710 }
711
712 /******************** EDITOR CONTROL ********************/
713
714 /*
715 * routine to implement EMACS character "i", with meta key held down if "m" is
716 * 1. The key is issued internally if "fromuser" is zero. Routine returns
717 * true if the editor window has been terminated.
718 */
us_editemacsimplementchar(WINDOWPART * win,INTBIG i,BOOLEAN m,BOOLEAN fromuser)719 BOOLEAN us_editemacsimplementchar(WINDOWPART *win, INTBIG i, BOOLEAN m, BOOLEAN fromuser)
720 {
721 REGISTER EDITOR *e;
722 INTBIG j, k, savecur, len, nextlineno, nextcharno;
723 CHAR s[2], *pt, *nextline, ch;
724 REGISTER void *infstr;
725
726 e = win->editor;
727 if (e == NOEDITOR) return(TRUE);
728
729 /* make sure line highlighting is off */
730 us_editemacsoffhighlight(win);
731
732 /* if ESCAPE was typed, set meta bit */
733 if ((us_lastemacschar&ESCAPE) != 0)
734 {
735 m = TRUE;
736 us_lastemacschar &= ~ESCAPE;
737 }
738
739 /* separate interpreter for ^X prefix */
740 if ((us_lastemacschar&CONTROLX) != 0)
741 {
742 us_lastemacschar &= ~CONTROLX;
743
744 /* save the text in a disk file */
745 if (i == CTLW && !m)
746 {
747 if (fromuser) us_editemacsshipchanges(win);
748 us_editemacswritetextfile(win, x_("EMACSbuffer"));
749 return(FALSE);
750 }
751
752 /* read a text from a disk file */
753 if (i == CTLV && !m)
754 {
755 if (fromuser) us_editemacsshipchanges(win);
756 pt = (CHAR *)fileselect(_("File name: "), el_filetypetext, x_(""));
757 if (pt == 0 || *pt == 0)
758 {
759 us_abortedmsg();
760 return(FALSE);
761 }
762 us_editemacsreadtextfile(win, pt);
763 return(FALSE);
764 }
765
766 ttyputerr(_("The sequence '^X%s' is not valid in EMACS"),
767 us_describeboundkey((INTSML)i, (!m ? 0 : ACCELERATORDOWN), 1));
768 return(FALSE);
769 }
770
771 /* ESCAPE prefix for the next character */
772 if (i == ESCKEY && !m)
773 {
774 us_lastemacschar |= ESCAPE;
775 return(FALSE);
776 }
777
778 /* ^X prefix for the next character */
779 if (i == CTLX && !m)
780 {
781 us_lastemacschar |= CONTROLX;
782 return(FALSE);
783 }
784
785 /* self-insert of normal characters */
786 if (i == '\t') i = ' ';
787 if (i >= ' ' && i <= '~' && !m)
788 {
789 if (fromuser) us_editemacsworkingoncurline(e);
790
791 /* see if line needs to be extended */
792 if ((INTBIG)estrlen(e->textarray[e->curline]) >= e->maxchars[e->curline])
793 us_editemacsaddmorechars(e, e->curline);
794
795 /* see if new character is at end of line */
796 if (e->textarray[e->curline][e->curchar] != 0)
797 {
798 /* it is not: shift letters on the line */
799 for(j=e->maxchars[e->curline]; j>e->curchar; j--)
800 e->textarray[e->curline][j] = e->textarray[e->curline][j-1];
801 if (e->curline-e->firstline < e->screenlines &&
802 e->curline >= e->firstline && e->curchar < e->screenchars-1 &&
803 (e->state&EGRAPHICSOFF) == 0)
804 {
805 us_editemacsmovebox(win, e->curchar+1, e->curline-e->firstline,
806 e->swid-e->curchar*us_twid-us_twid, us_thei, e->curchar,
807 e->curline-e->firstline);
808 us_editemacscleanupline(win, e->curline);
809 }
810 } else e->textarray[e->curline][e->curchar+1] = 0;
811
812 /* put the character on the display and into image memory */
813 if (e->curline-e->firstline < e->screenlines &&
814 e->curline >= e->firstline && e->curchar < e->screenchars &&
815 (e->state&EGRAPHICSOFF) == 0)
816 {
817 us_editemacsclearbox(win, e->curchar, e->curline-e->firstline,
818 us_twid, us_thei);
819 s[0] = (CHAR)i; s[1] = 0;
820 us_editemacstext(win, s, e->curchar, e->curline-e->firstline);
821 us_editemacscleanupline(win, e->curline);
822 }
823 e->textarray[e->curline][e->curchar] = (CHAR)i;
824
825 /* advance the character pointer */
826 e->curchar++;
827 return(FALSE);
828 }
829
830 /* search for a string */
831 if (i == CTLS && !m)
832 {
833 if (us_searchbuf == 0)
834 {
835 pt = ttygetlinemessages(_("Search for: "));
836 } else
837 {
838 infstr = initinfstr();
839 formatinfstr(infstr, _("Search for [%s]: "), us_searchbuf);
840 pt = ttygetlinemessages(returninfstr(infstr));
841 }
842 if (pt == 0) return(FALSE);
843 if (*pt == 0)
844 {
845 if (us_searchbuf == 0)
846 {
847 ttyputmsg(_("No previous search string"));
848 return(FALSE);
849 }
850 pt = us_searchbuf;
851 } else
852 {
853 if (us_searchbuf != 0) efree(us_searchbuf);
854 (void)allocstring(&us_searchbuf, pt, us_tool->cluster);
855 }
856 us_editemacsdosearch(win, us_searchbuf, FALSE, FALSE, FALSE, fromuser);
857 return(FALSE);
858 }
859
860 /* reverse search for a string */
861 if (i == CTLR && !m)
862 {
863 if (us_searchbuf == 0)
864 {
865 pt = ttygetlinemessages(_("Reverse search for: "));
866 } else
867 {
868 infstr = initinfstr();
869 formatinfstr(infstr, _("Reverse search for [%s]: "), us_searchbuf);
870 pt = ttygetlinemessages(returninfstr(infstr));
871 }
872 if (pt == 0) return(FALSE);
873 if (*pt == 0)
874 {
875 if (us_searchbuf == 0)
876 {
877 ttyputmsg(_("No previous search string"));
878 return(FALSE);
879 }
880 pt = us_searchbuf;
881 } else
882 {
883 if (us_searchbuf != 0) efree(us_searchbuf);
884 (void)allocstring(&us_searchbuf, pt, us_tool->cluster);
885 }
886 us_editemacsdosearch(win, us_searchbuf, TRUE, FALSE, FALSE, fromuser);
887 return(FALSE);
888 }
889
890 /* delete next character on a line (cannot delete line break) */
891 if (i == CTLD && !m)
892 {
893 if (fromuser) us_editemacsworkingoncurline(e);
894 us_editemacsdeletechar(win, fromuser);
895 return(FALSE);
896 }
897
898 /* delete next word on a line (cannot delete line break) */
899 if (i == 'd' && m)
900 {
901 if (fromuser) us_editemacsworkingoncurline(e);
902
903 /* first delete all nonalphanumeric characters */
904 for(;;)
905 {
906 ch = us_editemacsnextvalidcharacter(e);
907 if (ch == 0) break;
908 if (isalnum(ch)) break;
909 us_editemacsdeletechar(win, fromuser);
910 }
911
912 for(;;)
913 {
914 us_editemacsdeletechar(win, fromuser);
915 if (!isalnum(e->textarray[e->curline][e->curchar])) break;
916 }
917 return(FALSE);
918 }
919
920 /* delete previous character on a line (cannot delete line break) */
921 if ((i == CTLH || i == DELETEKEY) && !m)
922 {
923 if (fromuser) us_editemacsworkingoncurline(e);
924 e->curchar--;
925 if (e->curchar < 0)
926 {
927 if (e->curline <= 0) { e->curchar++; return(FALSE); }
928 e->curline--;
929 e->curchar = estrlen(e->textarray[e->curline]);
930 }
931 us_editemacsdeletechar(win, fromuser);
932 return(FALSE);
933 }
934
935 /* delete previous word on a line (cannot delete line break) */
936 if ((i == 'h' || i == DELETEKEY) && m)
937 {
938 if (fromuser) us_editemacsworkingoncurline(e);
939
940 /* first backwards delete all nonalphanumeric characters */
941 for(;;)
942 {
943 e->curchar--;
944 if (e->curchar < 0)
945 {
946 if (e->curline <= 0) { e->curchar++; return(FALSE); }
947 e->curline--;
948 e->curchar = estrlen(e->textarray[e->curline]);
949 }
950 if (isalnum(e->textarray[e->curline][e->curchar])) break;
951 us_editemacsdeletechar(win, fromuser);
952 }
953
954 /* now backwards delete alphanumeric characters */
955 for(;;)
956 {
957 us_editemacsdeletechar(win, fromuser);
958 nextcharno = e->curchar - 1;
959 nextlineno = e->curline;
960 if (nextcharno < 0)
961 {
962 if (nextlineno <= 0) return(FALSE);
963 nextlineno--;
964 nextcharno = estrlen(e->textarray[nextlineno]);
965 }
966 if (!isalnum(e->textarray[nextlineno][nextcharno])) break;
967 e->curchar = nextcharno;
968 e->curline = nextlineno;
969 }
970 return(FALSE);
971 }
972
973 /* kill to end of line (delete line if at beginning of empty line) */
974 if (i == CTLK && !m)
975 {
976 if (e->curchar == 0 && e->textarray[e->curline][e->curchar] == 0)
977 {
978 /* exit editor if only editing one line */
979 if ((win->state&WINDOWTYPE) == POPTEXTWINDOW)
980 {
981 if (fromuser) us_editemacsshipchanges(win);
982 return(TRUE);
983 }
984
985 /* cannot change number of lines if not allowed */
986 if (fromuser && (e->state&LINESFIXED) != 0)
987 {
988 ttyputerr(_("Cannot delete lines in this edit session"));
989 return(FALSE);
990 }
991
992 /* delete line in memory */
993 if (fromuser) us_editemacsshipchanges(win);
994 savecur = e->curline;
995 for(; e->curline < e->maxlines; e->curline++)
996 {
997 if (e->curline == e->maxlines-1) nextline = x_(""); else
998 nextline = e->textarray[e->curline+1];
999 if (estrcmp(e->textarray[e->curline], nextline) == 0) continue;
1000 if (fromuser) us_editemacsworkingoncurline(e);
1001 len = estrlen(nextline);
1002 while (len > e->maxchars[e->curline])
1003 us_editemacsaddmorechars(e, e->curline);
1004 (void)estrcpy(e->textarray[e->curline], nextline);
1005 if (fromuser) us_editemacsshipchanges(win);
1006 }
1007 e->curline = savecur;
1008
1009 /* delete line on the screen */
1010 if (e->curline-e->firstline < e->screenlines-1 &&
1011 e->curline >= e->firstline && (e->state&EGRAPHICSOFF) == 0)
1012 {
1013 us_editemacsmovebox(win, 0, e->curline-e->firstline, e->swid,
1014 e->shei-(e->curline-e->firstline+1)*us_thei, 0,
1015 e->curline-e->firstline+1);
1016 if (e->screenlines < e->maxlines)
1017 {
1018 us_editemacsclearbox(win, 0, e->screenlines-1, e->swid, us_thei);
1019 us_editemacsredrawline(win, e->screenlines-1);
1020 }
1021 }
1022 } else
1023 {
1024 if (e->textarray[e->curline][e->curchar] == 0)
1025 {
1026 ttyputerr(_("Can only delete entire lines"));
1027 return(FALSE);
1028 }
1029
1030 /* kill to end of line */
1031 if (fromuser) us_editemacsworkingoncurline(e);
1032 (void)estrcpy(us_killbuf, &e->textarray[e->curline][e->curchar]);
1033 if (e->curline-e->firstline < e->screenlines &&
1034 e->curline >= e->firstline && (e->state&EGRAPHICSOFF) == 0)
1035 us_editemacsclearbox(win, e->curchar, e->curline-e->firstline,
1036 e->swid-e->curchar*us_twid, us_thei);
1037 e->textarray[e->curline][e->curchar] = 0;
1038 }
1039 return(FALSE);
1040 }
1041
1042 if (i == CTLY && !m)
1043 {
1044 for(pt = us_killbuf; *pt != 0; pt++)
1045 {
1046 if (*pt == CTLY || *pt == CTLK) continue;
1047 (void)us_editemacsimplementchar(win, *pt, FALSE, fromuser);
1048 }
1049 return(FALSE);
1050 }
1051
1052 if (i == CTLL && !m)
1053 {
1054 us_editemacsredrawscreen(win);
1055 return(FALSE);
1056 }
1057
1058 if (i == CTLB && !m)
1059 {
1060 (void)us_editemacsbackupchar(win, fromuser);
1061 return(FALSE);
1062 }
1063
1064 if (i == 'b' && m)
1065 {
1066 for(;;)
1067 {
1068 if (us_editemacsbackupchar(win, fromuser)) break;
1069 if (isalnum(e->textarray[e->curline][e->curchar])) break;
1070 }
1071 for(;;)
1072 {
1073 if (e->curchar <= 0) break;
1074 if (!isalnum(e->textarray[e->curline][e->curchar-1])) break;
1075 (void)us_editemacsbackupchar(win, fromuser);
1076 }
1077 return(FALSE);
1078 }
1079
1080 if (i == CTLF && !m)
1081 {
1082 /* exit editor if at end of line and only editing one line */
1083 if (e->textarray[e->curline][e->curchar] == 0 &&
1084 (win->state&WINDOWTYPE) == POPTEXTWINDOW)
1085 {
1086 if (fromuser) us_editemacsshipchanges(win);
1087 return(TRUE);
1088 }
1089
1090 (void)us_editemacsadvancechar(win, fromuser);
1091 return(FALSE);
1092 }
1093
1094 if (i == 'f' && m)
1095 {
1096 /* exit editor if at end of line and only editing one line */
1097 if (e->textarray[e->curline][e->curchar] == 0 &&
1098 (win->state&WINDOWTYPE) == POPTEXTWINDOW)
1099 {
1100 if (fromuser) us_editemacsshipchanges(win);
1101 return(TRUE);
1102 }
1103
1104 for(;;)
1105 {
1106 if (isalnum(e->textarray[e->curline][e->curchar])) break;
1107 if (us_editemacsadvancechar(win, fromuser)) break;
1108 }
1109 for(;;)
1110 {
1111 if (us_editemacsadvancechar(win, fromuser)) break;
1112 if (!isalnum(e->textarray[e->curline][e->curchar])) break;
1113 }
1114 return(FALSE);
1115 }
1116
1117 if (i == CTLA && !m)
1118 {
1119 e->curchar = 0;
1120 return(FALSE);
1121 }
1122
1123 if (i == CTLE && !m)
1124 {
1125 for(j=0; e->textarray[e->curline][j] != 0; j++) ;
1126 e->curchar = j;
1127 return(FALSE);
1128 }
1129
1130 if (i == CTLG && !m)
1131 {
1132 ttyputmsg(_("Analyzing this line"));
1133 if (fromuser) us_editemacsshipchanges(win);
1134 return(FALSE);
1135 }
1136
1137 if (i == CTLP && !m)
1138 {
1139 /* exit editor if only editing one line */
1140 if ((win->state&WINDOWTYPE) == POPTEXTWINDOW)
1141 {
1142 if (fromuser) us_editemacsshipchanges(win);
1143 return(TRUE);
1144 }
1145
1146 if (e->curline <= 0) return(FALSE);
1147 if (fromuser)
1148 {
1149 us_editemacsshipchanges(win);
1150 if (e->curline == e->firstline && e->firstline > 0)
1151 us_editemacsshiftscreendown(win);
1152 }
1153 e->curline--;
1154 for(j=0; e->textarray[e->curline][j] != 0; j++) ;
1155 if (e->curchar > j) e->curchar = j;
1156 return(FALSE);
1157 }
1158
1159 if (i == CTLN && !m)
1160 {
1161 /* exit editor if only editing one line */
1162 if ((win->state&WINDOWTYPE) == POPTEXTWINDOW)
1163 {
1164 if (fromuser) us_editemacsshipchanges(win);
1165 return(TRUE);
1166 }
1167
1168 if (e->curline >= e->maxlines-1) us_editemacsaddmorelines(e);
1169 if (fromuser)
1170 {
1171 us_editemacsshipchanges(win);
1172 if (e->curline == e->firstline+e->screenlines-1)
1173 us_editemacsshiftscreenup(win);
1174 }
1175 e->curline++;
1176 for(j=0; e->textarray[e->curline][j] != 0; j++) ;
1177 if (e->curchar > j) e->curchar = j;
1178 return(FALSE);
1179 }
1180
1181 if (i == CTLZ && !m)
1182 {
1183 /* exit editor if only editing one line */
1184 if ((win->state&WINDOWTYPE) == POPTEXTWINDOW)
1185 {
1186 if (fromuser) us_editemacsshipchanges(win);
1187 return(TRUE);
1188 }
1189
1190 us_editemacsshiftscreenup(win);
1191 if (fromuser && e->curline == e->firstline) e->curline++;
1192 return(FALSE);
1193 }
1194
1195 if (i == 'z' && m)
1196 {
1197 /* exit editor if only editing one line */
1198 if ((win->state&WINDOWTYPE) == POPTEXTWINDOW)
1199 {
1200 if (fromuser) us_editemacsshipchanges(win);
1201 return(TRUE);
1202 }
1203
1204 if (e->firstline <= 0) return(FALSE);
1205 us_editemacsshiftscreendown(win);
1206 if (fromuser && e->curline == e->firstline+e->screenlines-1)
1207 e->curline--;
1208 return(FALSE);
1209 }
1210
1211 if (i == CTLV && !m)
1212 {
1213 /* exit editor if only editing one line */
1214 if ((win->state&WINDOWTYPE) == POPTEXTWINDOW)
1215 {
1216 if (fromuser) us_editemacsshipchanges(win);
1217 return(TRUE);
1218 }
1219
1220 j = e->screenlines / 5 * 4;
1221 e->firstline += j;
1222 if ((e->state&EGRAPHICSOFF) == 0)
1223 {
1224 us_editemacsmovebox(win, 0, 0, e->swid, us_thei*(e->screenlines-j), 0, j);
1225 us_editemacsclearbox(win, 0, e->screenlines-j, e->swid, us_thei*j);
1226 for(k=0; k<j; k++)
1227 {
1228 if (e->screenlines-j+k+e->firstline < e->maxlines)
1229 us_editemacsredrawline(win, e->screenlines-j+k);
1230 }
1231 }
1232 if (fromuser && e->curline < e->firstline)
1233 {
1234 us_editemacsshipchanges(win);
1235 e->curline = e->firstline + e->screenlines/2;
1236 }
1237 return(FALSE);
1238 }
1239
1240 if (i == 'v' && m)
1241 {
1242 /* exit editor if only editing one line */
1243 if ((win->state&WINDOWTYPE) == POPTEXTWINDOW)
1244 {
1245 if (fromuser) us_editemacsshipchanges(win);
1246 return(TRUE);
1247 }
1248
1249 if (e->firstline == 0) return(FALSE);
1250 j = e->screenlines / 5 * 4;
1251 if (j > e->firstline) j = e->firstline;
1252 e->firstline -= j;
1253 if ((e->state&EGRAPHICSOFF) == 0)
1254 {
1255 us_editemacsmovebox(win, 0, j, e->swid, us_thei*(e->screenlines-j), 0, 0);
1256 us_editemacsclearbox(win, 0, 0, e->swid, us_thei*j);
1257 for(k=0; k<j; k++)
1258 {
1259 if (e->firstline+k < e->maxlines) us_editemacsredrawline(win, k);
1260 }
1261 }
1262 if (fromuser && e->curline >= e->screenlines+e->firstline)
1263 {
1264 us_editemacsshipchanges(win);
1265 e->curline = e->firstline + e->screenlines/2;
1266 }
1267 return(FALSE);
1268 }
1269
1270 if (i == '>' && m)
1271 {
1272 if (fromuser) us_editemacsshipchanges(win);
1273 for(j=e->maxlines-1; j>=0; j--) if (e->textarray[j][0] != 0) break;
1274 e->curline = j+1;
1275 if (fromuser && e->curline >= e->firstline+e->screenlines)
1276 {
1277 e->firstline = e->curline - e->screenlines/2;
1278 us_editemacsredrawscreen(win);
1279 }
1280 e->curchar = 0;
1281 return(FALSE);
1282 }
1283
1284 if (i == '<' && m)
1285 {
1286 if (fromuser)
1287 {
1288 us_editemacsshipchanges(win);
1289 if (e->firstline != 0)
1290 {
1291 e->firstline = 0;
1292 us_editemacsredrawscreen(win);
1293 }
1294 }
1295 e->curline = 0;
1296 e->curchar = 0;
1297 return(FALSE);
1298 }
1299
1300 if (i == CTLO && !m)
1301 {
1302 /* exit editor if only editing one line */
1303 if ((win->state&WINDOWTYPE) == POPTEXTWINDOW)
1304 {
1305 if (fromuser) us_editemacsshipchanges(win);
1306 return(TRUE);
1307 }
1308
1309 /* cannot change number of lines if not allowed */
1310 if (fromuser && (e->state&LINESFIXED) != 0)
1311 {
1312 ttyputerr(_("Cannot insert lines in this edit session"));
1313 return(FALSE);
1314 }
1315
1316 /* see if there is room in the file */
1317 for(i=e->maxlines-1; i>=0; i--) if (e->textarray[i][0] != 0) break;
1318 if (i >= e->maxlines-1) us_editemacsaddmorelines(e);
1319
1320 /* shift lines down */
1321 if (fromuser) us_editemacsworkingoncurline(e);
1322 for(j = i+1; j > e->curline; j--)
1323 {
1324 if (j == e->curline+1) nextline = &e->textarray[e->curline][e->curchar]; else
1325 nextline = e->textarray[j-1];
1326 len = estrlen(nextline) + 1;
1327 while (len > e->maxchars[j])
1328 us_editemacsaddmorechars(e, j);
1329 (void)estrcpy(e->textarray[j], nextline);
1330 }
1331 e->textarray[e->curline][e->curchar] = 0;
1332 if ((e->state&EGRAPHICSOFF) == 0 && e->curline-e->firstline < e->screenlines &&
1333 e->curline >= e->firstline)
1334 {
1335 us_editemacsclearbox(win, e->curchar, e->curline-e->firstline,
1336 e->swid-e->curchar*us_twid, us_thei);
1337 }
1338
1339 /* ship changes on the current line */
1340 if (fromuser)
1341 {
1342 us_editemacsshipchanges(win);
1343 if (win->changehandler != 0)
1344 (*win->changehandler)(win, INSERTTEXTLINE, x_(""), e->textarray[e->curline+1], e->curline+1);
1345 us_editemacsworkingoncurline(e);
1346 }
1347
1348 /* shift lines down */
1349 if (e->curline-e->firstline < e->screenlines-1 &&
1350 e->curline >= e->firstline && (e->state&EGRAPHICSOFF) == 0)
1351 us_editemacsmovebox(win, 0, e->curline+1-e->firstline,
1352 e->swid, e->shei-(e->curline+1-e->firstline)*us_thei, 0,
1353 e->curline-e->firstline);
1354
1355 /* draw next line */
1356 if (e->curline+1-e->firstline < e->screenlines &&
1357 e->curline+1 >= e->firstline && (e->state&EGRAPHICSOFF) == 0)
1358 {
1359 us_editemacsclearbox(win, 0, e->curline+1-e->firstline,
1360 e->swid, us_thei);
1361 us_editemacstext(win, e->textarray[e->curline+1], 0, e->curline+1-e->firstline);
1362 }
1363 return(FALSE);
1364 }
1365
1366 if ((i == '\n' || i == '\r') && !m)
1367 {
1368 /* exit editor if only editing one line */
1369 if ((win->state&WINDOWTYPE) == POPTEXTWINDOW)
1370 {
1371 if (fromuser) us_editemacsshipchanges(win);
1372 return(TRUE);
1373 }
1374
1375 /* cannot change number of lines if not allowed */
1376 if (fromuser && (e->state&LINESFIXED) != 0)
1377 {
1378 ttyputerr(_("Cannot insert lines in this edit session"));
1379 return(FALSE);
1380 }
1381
1382 /* see if there is room in the file */
1383 if (e->curline >= e->maxlines-1) us_editemacsaddmorelines(e);
1384
1385 /* shift lines down */
1386 for(i=e->maxlines-1; i>=0; i--) if (e->textarray[i][0] != 0) break;
1387 if (fromuser) us_editemacsworkingoncurline(e);
1388 for(j = i+1; j > e->curline; j--)
1389 {
1390 if (j == e->curline+1) nextline = &e->textarray[e->curline][e->curchar]; else
1391 nextline = e->textarray[j-1];
1392 len = estrlen(nextline) + 1;
1393 while (len > e->maxchars[j])
1394 us_editemacsaddmorechars(e, j);
1395 (void)estrcpy(e->textarray[j], nextline);
1396 }
1397 e->textarray[e->curline][e->curchar] = 0;
1398 if ((e->state&EGRAPHICSOFF) == 0 && e->curline-e->firstline < e->screenlines &&
1399 e->curline >= e->firstline)
1400 {
1401 us_editemacsclearbox(win, e->curchar, e->curline-e->firstline,
1402 e->swid-e->curchar*us_twid, us_thei);
1403 }
1404
1405 if (fromuser) us_editemacsshipchanges(win);
1406 e->curline++;
1407 e->curchar = 0;
1408 if (fromuser)
1409 {
1410 if (win->changehandler != 0)
1411 (*win->changehandler)(win, INSERTTEXTLINE, x_(""), e->textarray[e->curline], e->curline);
1412 if (e->curline == e->firstline+e->screenlines-1)
1413 us_editemacsshiftscreenup(win);
1414 us_editemacsworkingoncurline(e);
1415 }
1416
1417 /* shift lines down */
1418 if (e->curline-e->firstline < e->screenlines-1 &&
1419 e->curline >= e->firstline && (e->state&EGRAPHICSOFF) == 0)
1420 us_editemacsmovebox(win, 0, e->curline+1-e->firstline,
1421 e->swid, e->shei-(e->curline+1-e->firstline)*us_thei, 0,
1422 e->curline-e->firstline);
1423
1424 /* clear current line */
1425 if (e->curline-e->firstline < e->screenlines &&
1426 e->curline >= e->firstline && (e->state&EGRAPHICSOFF) == 0)
1427 {
1428 us_editemacsclearbox(win, 0, e->curline-e->firstline,
1429 e->swid, us_thei);
1430 us_editemacstext(win, e->textarray[e->curline], 0, e->curline-e->firstline);
1431 }
1432 return(FALSE);
1433 }
1434
1435 /* flash the display */
1436 ttyputerr(_("The key '%s' is not valid in EMACS"),
1437 us_describeboundkey((INTSML)i, (!m ? 0 : ACCELERATORDOWN), 1));
1438 return(FALSE);
1439 }
1440
1441 /*
1442 * routine to back the cursor by one character. Returns true if at the
1443 * start of the file
1444 */
us_editemacsbackupchar(WINDOWPART * win,BOOLEAN fromuser)1445 BOOLEAN us_editemacsbackupchar(WINDOWPART *win, BOOLEAN fromuser)
1446 {
1447 REGISTER EDITOR *e;
1448 REGISTER INTBIG j;
1449
1450 e = win->editor;
1451 if (e == NOEDITOR) return(TRUE);
1452
1453 if (e->curchar > 0)
1454 {
1455 e->curchar--;
1456 return(FALSE);
1457 }
1458 if (e->curline <= 0) return(TRUE);
1459
1460 if (fromuser)
1461 {
1462 us_editemacsshipchanges(win);
1463 if (e->curline == e->firstline && e->firstline > 0)
1464 us_editemacsshiftscreendown(win);
1465 }
1466 e->curline--;
1467 for(j=0; e->textarray[e->curline][j] != 0; j++) ;
1468 e->curchar = j;
1469 return(FALSE);
1470 }
1471
1472 /*
1473 * routine to advance the cursor by one character. Returns true if at the
1474 * end of the file
1475 */
us_editemacsadvancechar(WINDOWPART * win,BOOLEAN fromuser)1476 BOOLEAN us_editemacsadvancechar(WINDOWPART *win, BOOLEAN fromuser)
1477 {
1478 REGISTER EDITOR *e;
1479 REGISTER BOOLEAN atend;
1480 REGISTER INTBIG j;
1481
1482 e = win->editor;
1483 if (e == NOEDITOR) return(TRUE);
1484
1485 if (e->textarray[e->curline][e->curchar] != 0)
1486 {
1487 e->curchar++;
1488 return(FALSE);
1489 }
1490
1491 atend = TRUE;
1492 for(j=e->curline+1; j < e->maxlines; j++)
1493 {
1494 if (e->textarray[j][0] == 0) continue;
1495 atend = FALSE;
1496 break;
1497 }
1498 if (e->curline >= e->maxlines-1) us_editemacsaddmorelines(e);
1499 if (fromuser)
1500 {
1501 us_editemacsshipchanges(win);
1502 if (e->curline == e->firstline+e->screenlines-1)
1503 us_editemacsshiftscreenup(win);
1504 }
1505 e->curline++;
1506 e->curchar = 0;
1507 return(atend);
1508 }
1509
1510 /*
1511 * routine to delete the current character
1512 */
us_editemacsdeletechar(WINDOWPART * win,BOOLEAN fromuser)1513 void us_editemacsdeletechar(WINDOWPART *win, BOOLEAN fromuser)
1514 {
1515 REGISTER INTBIG j, curl, len;
1516 REGISTER CHAR *nextline;
1517 CHAR s[2];
1518 REGISTER EDITOR *e;
1519
1520 e = win->editor;
1521 if (e == NOEDITOR) return;
1522
1523 /* at end of line: delete an entire line */
1524 if (e->textarray[e->curline][e->curchar] == 0)
1525 {
1526 /* only continue if there is a valid next line */
1527 if (e->curline < e->maxlines-1)
1528 {
1529 /* start by appending the next line to this */
1530 if (fromuser) us_editemacsworkingoncurline(e);
1531 nextline = e->textarray[e->curline+1];
1532 len = estrlen(e->textarray[e->curline]) + estrlen(nextline);
1533 while (len > e->maxchars[e->curline])
1534 us_editemacsaddmorechars(e, e->curline);
1535 (void)estrcat(e->textarray[e->curline], nextline);
1536 us_editemacsshipchanges(win);
1537 us_editemacsredrawline(win, e->curline);
1538
1539 /* now report deletion of following line */
1540 if (win->changehandler != 0)
1541 (*win->changehandler)(win, DELETETEXTLINE, x_(""), e->textarray[e->curline+1], e->curline+1);
1542 us_editemacsworkingoncurline(e);
1543
1544 /* shift up lines in memory */
1545 for(curl = e->curline+1; curl < e->maxlines; curl++)
1546 {
1547 if (curl == e->maxlines-1) nextline = x_(""); else
1548 nextline = e->textarray[curl+1];
1549 if (estrcmp(e->textarray[curl], nextline) == 0) continue;
1550 len = estrlen(nextline);
1551 while (len > e->maxchars[curl])
1552 us_editemacsaddmorechars(e, curl);
1553 (void)estrcpy(e->textarray[curl], nextline);
1554 }
1555
1556 /* delete line on the screen */
1557 curl = e->curline + 1;
1558 if (curl-e->firstline < e->screenlines-1 &&
1559 curl >= e->firstline && (e->state&EGRAPHICSOFF) == 0)
1560 {
1561 us_editemacsmovebox(win, 0, curl-e->firstline, e->swid,
1562 e->shei-(curl-e->firstline+1)*us_thei, 0,
1563 curl-e->firstline+1);
1564 if (e->screenlines < e->maxlines)
1565 {
1566 us_editemacsclearbox(win, 0, e->screenlines-1, e->swid, us_thei);
1567 us_editemacsredrawline(win, e->screenlines-1);
1568 }
1569 }
1570 }
1571 return;
1572 }
1573
1574 /* just delete the character in the line */
1575 for(j=e->curchar; j<e->maxchars[e->curline]; j++)
1576 e->textarray[e->curline][j] = e->textarray[e->curline][j+1];
1577 if (e->curline-e->firstline < e->screenlines && e->curline >= e->firstline &&
1578 e->curchar < e->screenchars && (e->state&EGRAPHICSOFF) == 0)
1579 {
1580 us_editemacsmovebox(win, e->curchar, e->curline-e->firstline,
1581 e->swid-e->curchar*us_twid-us_twid, us_thei,
1582 e->curchar+1, e->curline-e->firstline);
1583 if ((INTBIG)estrlen(e->textarray[e->curline]) >= e->screenchars)
1584 {
1585 us_editemacsclearbox(win, e->screenchars-1, e->curline-e->firstline,
1586 us_twid, us_thei);
1587 s[0] = e->textarray[e->curline][e->screenchars-1]; s[1] = 0;
1588 us_editemacstext(win, s, e->screenchars-1, e->curline-e->firstline);
1589 }
1590 us_editemacscleanupline(win, e->curline);
1591 }
1592 }
1593
1594 /*
1595 * Routine to search for "str" (search in the reverse direction if "reverse" is true).
1596 * Start search from the top if "fromtop" is true. Issue proper calls if this was
1597 * made by the user ("fromuser" true).
1598 */
us_editemacsdosearch(WINDOWPART * win,CHAR * str,BOOLEAN reverse,BOOLEAN fromtop,BOOLEAN casesensitive,BOOLEAN fromuser)1599 void us_editemacsdosearch(WINDOWPART *win, CHAR *str, BOOLEAN reverse,
1600 BOOLEAN fromtop, BOOLEAN casesensitive, BOOLEAN fromuser)
1601 {
1602 REGISTER EDITOR *e;
1603 REGISTER INTBIG i, j, k, startchr, startlne, match;
1604
1605 /* search for the string */
1606 e = win->editor;
1607 i = estrlen(str);
1608 if (fromtop)
1609 {
1610 /* search from the top of the buffer */
1611 startchr = 0; startlne = 0;
1612 } else
1613 {
1614 /* search from the end of the current selection */
1615 startchr = e->curchar; startlne = e->curline;
1616 }
1617 j = startlne;
1618 k = startchr;
1619 for(;;)
1620 {
1621 if (reverse)
1622 {
1623 /* reverse search: backup one place */
1624 k--;
1625 if (k < 0)
1626 {
1627 j--;
1628 if (j < 0) j = e->maxlines - 1;
1629 k = estrlen(e->textarray[j]);
1630 }
1631 } else
1632 {
1633 /* forward search: advance by one character */
1634 if (e->textarray[j][k] != 0) k++; else
1635 {
1636 /* advance to the next line */
1637 k = 0;
1638 j++;
1639 if (j >= e->maxlines) j = 0;
1640 }
1641 }
1642
1643 /* if it came all the way around, stop */
1644 if (k == startchr && j == startlne)
1645 {
1646 ttyputmsg(_("Can't find \"%s\""), str);
1647 break;
1648 }
1649
1650 /* if string matches, set cursor pointers */
1651 if (casesensitive)
1652 {
1653 match = estrncmp(str, &e->textarray[j][k], i);
1654 } else
1655 {
1656 match = namesamen(str, &e->textarray[j][k], i);
1657 }
1658 if (match == 0)
1659 {
1660 if (fromuser) us_editemacsshipchanges(win);
1661 if (reverse) e->curchar = k; else e->curchar = k+i;
1662 e->curline = j;
1663 us_editemacsensuretextshown(win, e->curline);
1664 break;
1665 }
1666 }
1667 }
1668
1669 /*
1670 * routine to shift the text screen up one line
1671 */
us_editemacsshiftscreenup(WINDOWPART * win)1672 void us_editemacsshiftscreenup(WINDOWPART *win)
1673 {
1674 REGISTER EDITOR *e;
1675
1676 e = win->editor;
1677 if (e == NOEDITOR) return;
1678
1679 e->firstline++;
1680 if ((e->state&EGRAPHICSOFF) != 0) return;
1681 us_editemacsmovebox(win, 0, 0, e->swid, us_thei*(e->screenlines-1), 0, 1);
1682 us_editemacsclearbox(win, 0, e->screenlines-1, e->swid, us_thei);
1683 if (e->screenlines+e->firstline <= e->maxlines)
1684 us_editemacsredrawline(win, e->screenlines-1);
1685 }
1686
1687 /*
1688 * routine to shift the text screen down one line
1689 */
us_editemacsshiftscreendown(WINDOWPART * win)1690 void us_editemacsshiftscreendown(WINDOWPART *win)
1691 {
1692 REGISTER EDITOR *e;
1693
1694 e = win->editor;
1695 if (e == NOEDITOR) return;
1696
1697 e->firstline--;
1698 if ((e->state&EGRAPHICSOFF) != 0) return;
1699 us_editemacsmovebox(win, 0, 1, e->swid, us_thei*(e->screenlines-1), 0, 0);
1700 us_editemacsclearbox(win, 0, 0, e->swid, us_thei);
1701 us_editemacsredrawline(win, 0);
1702 }
1703
1704 /*
1705 * routine to ensure that line "line" is shown in the display
1706 */
us_editemacsensuretextshown(WINDOWPART * win,INTBIG line)1707 void us_editemacsensuretextshown(WINDOWPART *win, INTBIG line)
1708 {
1709 REGISTER EDITOR *e;
1710
1711 e = win->editor;
1712 if (e == NOEDITOR) return;
1713
1714 if (line-e->firstline >= e->screenlines || line < e->firstline)
1715 {
1716 e->firstline = maxi(0, line - e->screenlines/2);
1717 us_editemacsredrawscreen(win);
1718 }
1719 }
1720
1721 /*
1722 * routine to redisplay the text screen
1723 */
us_editemacsredrawscreen(WINDOWPART * win)1724 void us_editemacsredrawscreen(WINDOWPART *win)
1725 {
1726 REGISTER INTBIG j;
1727 REGISTER EDITOR *e;
1728
1729 e = win->editor;
1730 if (e == NOEDITOR) return;
1731 if ((e->state&EGRAPHICSOFF) != 0) return;
1732
1733 /* put header on display */
1734 us_editemacssetheader(win, e->header);
1735
1736 /* clear the screen */
1737 us_editemacsclearbox(win, 0, 0, e->swid, e->shei);
1738
1739 /* rewrite each line */
1740 for(j=0; j<e->screenlines; j++) if (j+e->firstline < e->maxlines)
1741 us_editemacsredrawline(win, j);
1742 }
1743
1744 /*
1745 * routine to write line "j" of the screen
1746 */
us_editemacsredrawline(WINDOWPART * win,INTBIG j)1747 void us_editemacsredrawline(WINDOWPART *win, INTBIG j)
1748 {
1749 REGISTER INTBIG save;
1750 REGISTER EDITOR *e;
1751
1752 e = win->editor;
1753 if (e == NOEDITOR) return;
1754
1755 if ((INTBIG)estrlen(e->textarray[j+e->firstline]) > e->screenchars)
1756 {
1757 save = e->textarray[j+e->firstline][e->screenchars];
1758 e->textarray[j+e->firstline][e->screenchars] = 0;
1759 } else save = 0;
1760 us_editemacstext(win, e->textarray[j+e->firstline], 0, j);
1761 if (save != 0) e->textarray[j+e->firstline][e->screenchars] = (CHAR)save;
1762 }
1763
1764 /*
1765 * routine to write the header string
1766 */
us_editemacssetheader(WINDOWPART * win,CHAR * header)1767 void us_editemacssetheader(WINDOWPART *win, CHAR *header)
1768 {
1769 REGISTER INTBIG save;
1770 REGISTER EDITOR *e;
1771
1772 e = win->editor;
1773 if (e == NOEDITOR) return;
1774 screendrawbox(win, win->uselx, win->usehx, win->usely, win->usehy, &us_ebox);
1775 if ((INTBIG)estrlen(header) > e->screenchars)
1776 {
1777 save = header[e->screenchars];
1778 header[e->screenchars] = 0;
1779 } else save = 0;
1780 us_editemacstext(win, header, 0, -2);
1781 if ((win->state&WINDOWTYPE) == POPTEXTWINDOW)
1782 us_editemacstext(win, _("EMACS editor: type RETURN when done"), 0, -1); else
1783 {
1784 if (estrcmp(win->location, x_("entire")) != 0)
1785 us_editemacstext(win, _("EMACS editor: type ^Xd when done"), 0, -1); else
1786 {
1787 if (graphicshas(CANUSEFRAMES))
1788 us_editemacstext(win, _("EMACS editor: close the window when done"), 0, -1); else
1789 us_editemacstext(win, _("EMACS editor: text-only cell"), 0, -1);
1790 }
1791 }
1792 if (save != 0) header[e->screenchars] = (CHAR)save;
1793 screeninvertbox(win, e->offx-1, e->offx+e->swid,
1794 e->revy+1, e->revy+us_thei*HEADERLINES);
1795 us_menufigs.col = el_colmengly;
1796 screendrawline(win, e->offx-1, e->revy, e->offx-1,
1797 e->revy-e->shei-1, &us_menufigs, 0);
1798 screendrawline(win, e->offx+e->swid+1, e->revy,
1799 e->offx+e->swid+1, e->revy-e->shei-1, &us_menufigs, 0);
1800 screendrawline(win, e->offx-1, e->revy-e->shei-1,
1801 e->offx+e->swid+1, e->revy-e->shei-1, &us_menufigs, 0);
1802 }
1803
1804 /*
1805 * Routine to return the next valid character (ignoring end-of-lines).
1806 */
us_editemacsnextvalidcharacter(EDITOR * e)1807 CHAR us_editemacsnextvalidcharacter(EDITOR *e)
1808 {
1809 INTBIG line, chr;
1810
1811 line = e->curline; chr = e->curchar;
1812 while (line < e->maxlines && e->textarray[line][chr] == 0)
1813 {
1814 line++;
1815 chr = 0;
1816 }
1817 return(e->textarray[line][chr]);
1818 }
1819
1820 /*
1821 * routine to invert the character cursor, turning it on or off
1822 */
us_editemacsflashcursor(WINDOWPART * win)1823 void us_editemacsflashcursor(WINDOWPART *win)
1824 {
1825 REGISTER EDITOR *e;
1826
1827 e = win->editor;
1828 if (e == NOEDITOR) return;
1829
1830 if (e->curline-e->firstline < e->screenlines && e->curline >= e->firstline &&
1831 e->curchar < e->screenchars && (e->state&EGRAPHICSOFF) == 0)
1832 us_editemacsinvertbox(win, e->curchar, e->curline-e->firstline, us_twid,
1833 us_thei);
1834 }
1835
1836 /*
1837 * turn off the highlighting of a line of text (if one is highlighted)
1838 */
us_editemacsoffhighlight(WINDOWPART * win)1839 void us_editemacsoffhighlight(WINDOWPART *win)
1840 {
1841 REGISTER EDITOR *e;
1842
1843 e = win->editor;
1844 if (e == NOEDITOR) return;
1845
1846 if (e->highlightedline < 0) return;
1847 if (e->highlightedline-e->firstline < e->screenlines &&
1848 e->highlightedline >= e->firstline && (e->state&EGRAPHICSOFF) == 0)
1849 us_editemacsinvertbox(win, 0, e->highlightedline-e->firstline,
1850 e->swid, us_thei);
1851 e->highlightedline = -1;
1852 }
1853
1854 /*
1855 * routine to cleanup the bits at the end of a line that are not a full-width
1856 * character
1857 */
us_editemacscleanupline(WINDOWPART * win,INTBIG line)1858 void us_editemacscleanupline(WINDOWPART *win, INTBIG line)
1859 {
1860 REGISTER INTBIG residue;
1861 REGISTER EDITOR *e;
1862
1863 e = win->editor;
1864 if (e == NOEDITOR) return;
1865
1866 residue = e->swid-e->screenchars*us_twid;
1867 if (residue == 0) return;
1868 us_editemacsclearbox(win, e->screenchars, line-e->firstline, residue, us_thei);
1869 }
1870
1871 /*
1872 * routine to declare that the user is now working on line "line"
1873 */
us_editemacsworkingoncurline(EDITOR * e)1874 void us_editemacsworkingoncurline(EDITOR *e)
1875 {
1876 if (e->working == -1)
1877 {
1878 /* first time: save the line */
1879 (void)estrcpy(e->formerline, e->textarray[e->curline]);
1880 e->working = e->curline;
1881 }
1882 }
1883
1884 /*
1885 * routine to declare that the user is done with line "line"
1886 */
us_editemacsshipchanges(WINDOWPART * win)1887 void us_editemacsshipchanges(WINDOWPART *win)
1888 {
1889 REGISTER EDITOR *e;
1890
1891 e = win->editor;
1892 if (e == NOEDITOR) return;
1893
1894 if (e->working == -1) return;
1895 us_editemacsflashcursor(win);
1896 if (win->changehandler != 0)
1897 (*win->changehandler)(win, REPLACETEXTLINE, e->formerline,
1898 e->textarray[e->curline], e->working);
1899 us_editemacsflashcursor(win);
1900 e->working = -1;
1901 }
1902
1903 /******************** ALLOCATION ********************/
1904
1905 /*
1906 * routine to double the number of lines in the text buffer
1907 */
us_editemacsaddmorelines(EDITOR * e)1908 void us_editemacsaddmorelines(EDITOR *e)
1909 {
1910 REGISTER INTBIG oldlines, i;
1911 REGISTER INTBIG *maxchars;
1912 REGISTER CHAR **textarray;
1913
1914 /* save former buffer size, double it */
1915 oldlines = e->maxlines;
1916 e->maxlines *= 2;
1917
1918 /* allocate new arrays */
1919 maxchars = (INTBIG *)emalloc((e->maxlines * SIZEOFINTBIG), us_tool->cluster);
1920 if (maxchars == 0) ttyputnomemory();
1921 textarray = (CHAR **)emalloc((e->maxlines * (sizeof (CHAR *))), us_tool->cluster);
1922 if (textarray == 0) ttyputnomemory();
1923
1924 /* copy old information */
1925 for(i=0; i<e->maxlines; i++)
1926 {
1927 if (i >= oldlines)
1928 {
1929 textarray[i] = (CHAR *)emalloc((e->screenchars+1) * SIZEOFCHAR, us_tool->cluster);
1930 if (textarray[i] == 0) ttyputnomemory();
1931 textarray[i][0] = 0;
1932 maxchars[i] = e->screenchars;
1933 } else
1934 {
1935 textarray[i] = (CHAR *)emalloc((e->maxchars[i]+1) * SIZEOFCHAR, us_tool->cluster);
1936 if (textarray[i] == 0) ttyputnomemory();
1937 (void)estrcpy(textarray[i], e->textarray[i]);
1938 maxchars[i] = e->maxchars[i];
1939 }
1940 }
1941
1942 /* free old arrays */
1943 for(i=0; i<oldlines; i++) efree(e->textarray[i]);
1944 efree((CHAR *)e->textarray);
1945 efree((CHAR *)e->maxchars);
1946
1947 /* setup pointers correctly */
1948 e->textarray = textarray;
1949 e->maxchars = maxchars;
1950 }
1951
1952 /*
1953 * routine to double the number of characters in line "line"
1954 */
us_editemacsaddmorechars(EDITOR * e,INTBIG line)1955 void us_editemacsaddmorechars(EDITOR *e, INTBIG line)
1956 {
1957 REGISTER CHAR *oldline;
1958
1959 oldline = e->textarray[line];
1960 e->maxchars[line] *= 2;
1961 e->textarray[line] = (CHAR *)emalloc((e->maxchars[line]+1) * SIZEOFCHAR, us_tool->cluster);
1962 (void)estrcpy(e->textarray[line], oldline);
1963 if (e->maxchars[line] > e->mostchars)
1964 {
1965 e->mostchars = e->maxchars[line];
1966 efree(e->formerline);
1967 us_editemacsgetbuffers(e);
1968 }
1969 }
1970
1971 /*
1972 * routine to allocate the single-line buffers
1973 */
us_editemacsgetbuffers(EDITOR * e)1974 void us_editemacsgetbuffers(EDITOR *e)
1975 {
1976 e->formerline = (CHAR *)emalloc((e->mostchars+1) * SIZEOFCHAR, us_tool->cluster);
1977 if (e->formerline == 0) ttyputnomemory();
1978 if (e->mostchars > us_killbufchars)
1979 {
1980 if (us_killbufchars != 0) efree(us_killbuf);
1981 us_killbuf = (CHAR *)emalloc(e->mostchars * SIZEOFCHAR, us_tool->cluster);
1982 if (us_killbuf == 0) ttyputnomemory();
1983 us_killbufchars = e->mostchars;
1984 }
1985 }
1986
1987 /******************** GRAPHIC SUPPORT ********************/
1988
1989 /*
1990 * move text starting at character position (sx,sy) to character position
1991 * (dx, dy).
1992 */
us_editemacsmovebox(WINDOWPART * win,INTBIG dx,INTBIG dy,INTBIG wid,INTBIG hei,INTBIG sx,INTBIG sy)1993 void us_editemacsmovebox(WINDOWPART *win, INTBIG dx, INTBIG dy, INTBIG wid,
1994 INTBIG hei, INTBIG sx, INTBIG sy)
1995 {
1996 REGISTER EDITOR *e;
1997
1998 e = win->editor;
1999 if (e == NOEDITOR) return;
2000 screenmovebox(win, sx*us_twid+e->offx, e->revy-(sy*us_thei+hei-1), wid, hei,
2001 dx*us_twid+e->offx, e->revy-(dy*us_thei+hei-1));
2002 }
2003
2004 /*
2005 * erase text starting at character position (dx,dy) for (wid, hei)
2006 */
us_editemacsclearbox(WINDOWPART * win,INTBIG dx,INTBIG dy,INTBIG wid,INTBIG hei)2007 void us_editemacsclearbox(WINDOWPART *win, INTBIG dx, INTBIG dy, INTBIG wid, INTBIG hei)
2008 {
2009 REGISTER EDITOR *e;
2010
2011 e = win->editor;
2012 if (e == NOEDITOR) return;
2013
2014 dx = (dx * us_twid) + e->offx;
2015 dy *= us_thei;
2016 screendrawbox(win, dx, dx+wid-1, e->revy-(dy+hei-1), e->revy-dy, &us_ebox);
2017 }
2018
2019 /*
2020 * invert text starting at character position (dx,dy) for (wid, hei)
2021 */
us_editemacsinvertbox(WINDOWPART * win,INTBIG dx,INTBIG dy,INTBIG wid,INTBIG hei)2022 void us_editemacsinvertbox(WINDOWPART *win, INTBIG dx, INTBIG dy, INTBIG wid, INTBIG hei)
2023 {
2024 REGISTER EDITOR *e;
2025
2026 e = win->editor;
2027 if (e == NOEDITOR) return;
2028
2029 dx = (dx * us_twid) + e->offx;
2030 dy *= us_thei;
2031 screeninvertbox(win, dx, dx+wid-1, e->revy-(dy+hei-1), e->revy-dy);
2032 }
2033
2034 /*
2035 * write text "str" starting at character position (x,y)
2036 */
us_editemacstext(WINDOWPART * win,CHAR * str,INTBIG x,INTBIG y)2037 void us_editemacstext(WINDOWPART *win, CHAR *str, INTBIG x, INTBIG y)
2038 {
2039 REGISTER EDITOR *e;
2040 UINTBIG descript[TEXTDESCRIPTSIZE];
2041
2042 e = win->editor;
2043 if (e == NOEDITOR) return;
2044
2045 TDCLEAR(descript);
2046 TDSETSIZE(descript, us_editemacsfont);
2047 screensettextinfo(win, NOTECHNOLOGY, descript);
2048 us_menutext.col = el_colmentxt;
2049 screendrawtext(win, x*us_twid + e->offx, e->revy-(y+1)*us_thei,
2050 str, &us_menutext);
2051 }
2052