1 /* AMIGADOS.C: Operating specific I/O and Spawning functions
2 for MicroEMACS 4.00
3 (C)Copyright 1995 by Daniel M. Lawrence
4 */
5
6 #include <stdio.h>
7 #include "estruct.h"
8 #if AMIGA
9 #include <exec/types.h>
10 #include <exec/io.h>
11 #include <intuition/intuition.h>
12 #include <devices/console.h>
13 #include "eproto.h"
14 #include "edef.h"
15 #include "elang.h"
16
17 #define INTUITION_REV 0L
18 #define NEW 1006L
19 #define CRWIDTH 8
20 #define CRHEIGHT 8
21
22 struct IntuitionBase *IntuitionBase;
23 struct Window *win;
24 struct IOStdReq con; /* ptr to console device driver handle */
25
26 /* Intuition Function type declarations */
27
28 struct IntuitionBase *OpenLibrary();
29 struct Window *OpenWindow();
30 struct IntuiMessage *GetMsg();
31
32 typedef struct {
33 short rw_code; /* normal keycode to generate */
34 short rw_scode; /* shifted " */
35 short rw_ccode; /* control " */
36 } RKEY;
37
38 /* raw keycode scan code to emacs keycode translation table */
39
40 RKEY keytrans[0x60] = {
41
42 /* CODE NORM SHIFT CTRL */
43 /* 0x00,*/ '`', '~', 0,
44 /* 0x01,*/ '1', '!', 0,
45 /* 0x02,*/ '2', '@', 0,
46 /* 0x03,*/ '3', '#', 0,
47 /* 0x04,*/ '4', '$', 0,
48 /* 0x05,*/ '5', '%', 0,
49 /* 0x06,*/ '6', '^', 0,
50 /* 0x07,*/ '7', '&', 0,
51 /* 0x08,*/ '8', '*', 0,
52 /* 0x09,*/ '9', '(', 0,
53 /* 0x0a,*/ '0', ')', 0,
54 /* 0x0b,*/ '-', '_', 0,
55 /* 0x0c,*/ '=', '+', 0,
56 /* 0x0d,*/ '\\', '|', 0,
57 /* 0x0e,*/ 0, 0, 0,
58 /* 0x0f,*/ 0, 0, 0,
59 /* 0x10,*/ 'q', 'Q', CTRL|'Q',
60 /* 0x11,*/ 'w', 'W', CTRL|'W',
61 /* 0x12,*/ 'e', 'E', CTRL|'E',
62 /* 0x13,*/ 'r', 'R', CTRL|'R',
63 /* 0x14,*/ 't', 'T', CTRL|'T',
64 /* 0x15,*/ 'y', 'Y', CTRL|'Y',
65 /* 0x16,*/ 'u', 'U', CTRL|'U',
66 /* 0x17,*/ 'i', 'I', CTRL|'I',
67 /* 0x18,*/ 'o', 'O', CTRL|'O',
68 /* 0x19,*/ 'p', 'P', CTRL|'P',
69 /* 0x1a,*/ '[', '{', 0,
70 /* 0x1b,*/ ']', '}', 0,
71 /* 0x1c,*/ 0, 0, 0,
72 /* 0x1d,*/ '1', SPEC|'>', 0,
73 /* 0x1e,*/ '2', SPEC|'N', 0,
74 /* 0x1f,*/ '3', SPEC|'V', 0,
75 /* 0x20,*/ 'a', 'A', CTRL|'A',
76 /* 0x21,*/ 's', 'S', CTRL|'S',
77 /* 0x22,*/ 'd', 'D', CTRL|'D',
78 /* 0x23,*/ 'f', 'F', CTRL|'F',
79 /* 0x24,*/ 'g', 'G', CTRL|'G',/* 0x25,*/ 'h', 'H', CTRL|'H',
80 /* 0x26,*/ 'j', 'J', CTRL|'J',
81 /* 0x27,*/ 'k', 'K', CTRL|'K',
82 /* 0x28,*/ 'l', 'L', CTRL|'L',
83 /* 0x29,*/ ';', ':', 0,
84 /* 0x2a,*/ 39, 34, 0,
85 /* 0x2b,*/ 0, 0, 0,
86 /* 0x2c,*/ 0, 0, 0,
87 /* 0x2d,*/ '4', SPEC|'B', 0,
88 /* 0x2e,*/ '5', 0, 0,
89 /* 0x2f,*/ '6', SPEC|'F', 0,
90 /* this key is probably mapped on forign AIMIGA keyboards */
91 /* 0x30,*/ 0, 0, 0,
92 /* 0x31,*/ 'z', 'Z', CTRL|'Z',
93 /* 0x32,*/ 'x', 'X', CTRL|'X',
94 /* 0x33,*/ 'c', 'C', CTRL|'C',
95 /* 0x34,*/ 'v', 'V', CTRL|'V',
96 /* 0x35,*/ 'b', 'B', CTRL|'B',
97 /* 0x36,*/ 'n', 'N', CTRL|'N',
98 /* 0x37,*/ 'm', 'M', CTRL|'M',
99 /* 0x38,*/ ',', '<', 0,
100 /* 0x39,*/ '.', '>', 0,
101 /* 0x3a,*/ '/', '?', 0,
102 /* 0x3b,*/ 0, 0, 0,
103 /* 0x3c,*/ '.', SPEC|'D', 0,
104 /* 0x3d,*/ '7', SPEC|'<', 0,
105 /* 0x3e,*/ '8', SPEC|'P', 0,
106 /* 0x3f,*/ '9', SPEC|'Z', 0,
107 /* 0x40,*/ ' ', SHFT|' ', 0,
108 /* 0x41,*/ CTRL|'H', SHFT|'D', 0,
109 /* 0x42,*/ CTRL|'I', SHFT|'I', 0,
110 /* 0x43,*/ CTRL|'M', CTRL|'M', CTRL|'M',
111 /* 0x44,*/ CTRL|'M', CTRL|'M', CTRL|'M',
112 /* 0x45,*/ CTRL|'[', 0, 0,
113 /* 0x46,*/ SPEC|'D', 0, 0,
114 /* 0x47,*/ 0, 0, 0,
115 /* 0x48,*/ 0, 0, 0,
116 /* 0x49,*/ 0, 0, 0,
117 /* 0x4a,*/ '-', 0, 0,
118 /* 0x4b,*/ 0, 0, 0,
119 /* 0x4c,*/ SPEC|'P', SHFT|SPEC|'P', CTRL|SPEC|'P',
120 /* 0x4d,*/ SPEC|'N', SHFT|SPEC|'N', CTRL|SPEC|'N',
121 /* 0x4e,*/ SPEC|'F', SHFT|SPEC|'F', CTRL|SPEC|'F',
122 /* 0x4f,*/ SPEC|'B', SHFT|SPEC|'B', CTRL|SPEC|'B',
123 /* 0x50,*/ SPEC|'1', SHFT|SPEC|'1', CTRL|SPEC|'1',
124 /* 0x51,*/ SPEC|'2', SHFT|SPEC|'2', CTRL|SPEC|'2',
125 /* 0x52,*/ SPEC|'3', SHFT|SPEC|'3', CTRL|SPEC|'3',
126 /* 0x53,*/ SPEC|'4', SHFT|SPEC|'4', CTRL|SPEC|'4',
127 /* 0x54,*/ SPEC|'5', SHFT|SPEC|'5', CTRL|SPEC|'5',
128 /* 0x55,*/ SPEC|'6', SHFT|SPEC|'6', CTRL|SPEC|'6',
129 /* 0x56,*/ SPEC|'7', SHFT|SPEC|'7', CTRL|SPEC|'7',
130 /* 0x57,*/ SPEC|'8', SHFT|SPEC|'8', CTRL|SPEC|'8',
131 /* 0x58,*/ SPEC|'9', SHFT|SPEC|'9', CTRL|SPEC|'9',
132 /* 0x59,*/ SPEC|'0', SHFT|SPEC|'0', CTRL|SPEC|'0',
133 /* 0x5a,*/ '(', 0, 0,
134 /* 0x5b,*/ ')', 0, 0,
135 /* 0x5c,*/ '/', 0, 0,
136 /* 0x5d,*/ '*', 0, 0,
137 /* 0x5e,*/ 0, 0, 0,
138 /* 0x5f,*/ SPEC|'?', 0, 0,
139 };
140
141 /* some keyboard keys current states */
142
143 int r_shiftflag; /* right shift key */
144 int l_shiftflag; /* left shift key */
145 int r_altflag; /* right alt key */
146 int l_altflag; /* left alt key */
147 int r_amiflag; /* right amiga key */
148 int l_amiflag; /* left amiga key */
149 int ctrlflag; /* control key */
150 int lockflag; /* shift lock key */
151
152 /* output buffers and pointers */
153
154 #define OBUFSIZE 1024L
155 #define IBUFSIZE 64 /* this must be a power of 2 */
156
157 char out_buf[OBUFSIZE+1]; /* output character buffer */
158 int out_ptr = 0; /* index to next char to put in buffer */
159
160 /* input buffers and pointers */
161
162 #define IBUFSIZE 64 /* this must be a power of 2 */
163
164 unsigned char in_buf[IBUFSIZE]; /* input character buffer */
165 int in_next = 0; /* pos to retrieve next input character */
166 int in_last = 0; /* pos to place most recent input character */
167
in_init()168 in_init() /* initialize the input buffer */
169
170 {
171 in_next = in_last = 0;
172 }
173
in_check()174 in_check() /* is the input buffer non-empty? */
175
176 {
177 if (in_next == in_last)
178 return(FALSE);
179 else
180 return(TRUE);
181 }
182
in_put(event)183 in_put(event)
184
185 int event; /* event to enter into the input buffer */
186
187 {
188 in_buf[in_last++] = event;
189 in_last &= (IBUFSIZE - 1);
190 }
191
in_get()192 int in_get() /* get an event from the input buffer */
193
194 {
195 register int event; /* event to return */
196
197 event = in_buf[in_next++];
198 in_next &= (IBUFSIZE - 1);
199 return(event);
200 }
201
202 /*
203 * This function is called once to set up the terminal device streams.
204 * On VMS, it translates TT until it finds the terminal, then assigns
205 * a channel to it and sets it raw. On CPM it is a no-op.
206 */
ttopen()207 ttopen()
208 {
209 struct NewWindow new_win;
210 int i;
211 #if AZTEC
212 extern Enable_Abort; /* Turn off ctrl-C interrupt */
213
214 Enable_Abort = 0; /* for the Manx compiler */
215 #endif
216 strcpy(os, "AMIGADOS");
217
218 /* open the intuition library */
219 IntuitionBase = (struct IntuitionBase *)
220 OpenLibrary("intuition.library", INTUITION_REV);
221 if (IntuitionBase == NULL) {
222 printf("%%Can not open Intuition\n");
223 exit(-1);
224 }
225
226 /* initialize the new windows attributes */
227 new_win.LeftEdge = 0;
228 new_win.TopEdge = 0;
229 new_win.Width = 640;
230 new_win.Height = 200;
231 new_win.DetailPen = 0;
232 new_win.BlockPen = 1;
233 new_win.Title = (unsigned char *)"MicroEMACS 4.00/Amiga";
234 new_win.Flags = WINDOWCLOSE | SMART_REFRESH | ACTIVATE |
235 WINDOWDRAG | WINDOWDEPTH | WINDOWSIZING | SIZEBRIGHT |
236 RMBTRAP | NOCAREREFRESH;
237 new_win.IDCMPFlags = CLOSEWINDOW | NEWSIZE | MOUSEBUTTONS |
238 RAWKEY;
239 new_win.Type = WBENCHSCREEN;
240 new_win.FirstGadget = NULL;
241 new_win.CheckMark = NULL;
242 new_win.Screen = NULL;
243 new_win.BitMap = NULL;
244 new_win.MinWidth = 100;
245 new_win.MinHeight = 25;
246 new_win.MaxWidth = 640;
247 new_win.MaxHeight = 200;
248
249 /* open the window! */
250 win = (struct Window *)OpenWindow(&new_win);
251 if (win == NULL) {
252 printf("%%Can not open a window\n");
253 exit(-2);
254 }
255
256 /* and open up the console for output */
257 con.io_Data = (APTR)win;
258 OpenDevice("console.device", 0, &con, 0);
259
260 /* and init all the keyboard flags */
261 r_shiftflag = FALSE;
262 l_shiftflag = FALSE; r_altflag = FALSE;
263 l_altflag = FALSE;
264 r_amiflag = FALSE;
265 l_amiflag = FALSE;
266 ctrlflag = FALSE;
267 lockflag = FALSE;
268
269 /* initialize our private event queue */
270 in_init();
271
272 /* set the current sizes */
273 newwidth(TRUE, 77);
274 newsize(TRUE, 23);
275
276 /* on all screens we are not sure of the initial position
277 of the cursor */
278 ttrow = 999;
279 ttcol = 999;
280 }
281
282 /*
283 * This function gets called just before we go back home to the command
284 * interpreter. On VMS it puts the terminal back in a reasonable state.
285 * Another no-operation on CPM.
286 */
ttclose()287 ttclose()
288
289 {
290 /* make sure there is no pending output */
291 ttflush();
292
293 /* and now close up shop */
294 CloseDevice(&con);
295 CloseWindow(win);
296 OpenWorkBench();
297 }
298
299 /*
300 * Write a character to the display. On VMS, terminal output is buffered, and
301 * we just put the characters in the big array, after checking for overflow.
302 * On CPM terminal I/O unbuffered, so we just write the byte out. Ditto on
303 * MS-DOS (use the very very raw console output routine).
304 */
305
ttputc(c)306 ttputc(c)
307
308 char c;
309
310 {
311 /* add the character to the output buffer */
312 out_buf[out_ptr++] = c;
313
314 /* send the buffer out if we are at the limit */
315 if (out_ptr >= OBUFSIZE)
316 ttflush();
317 }
318
319 /*
320 * Flush terminal buffer. Does real work where the terminal output is buffered
321 * up. A no-operation on systems where byte at a time terminal I/O is done.
322 */
323
ttflush()324 ttflush()
325
326 {
327 /* if there are any characters waiting to display... */
328 if (out_ptr) {
329 out_buf[out_ptr] = 0; /* terminate the buffer string */
330 sendcon(out_buf); /* send them out */
331 out_ptr = 0; /* and reset the buffer */
332 }
333 }
334
335 /*
336 * Read a character from the terminal.
337 */
338
ttgetc()339 ttgetc()
340
341 {
342 /* make sure there is no pending output */
343 nxtchr: ttflush();
344
345 /* if it is already buffered up, get it */
346 if (in_check())
347 return(in_get());
348
349 /* process an INTUITION event (possibly loading the input buffer) */
350 doevent();
351 goto nxtchr;
352 }
353
354 #if TYPEAH
355 /* typahead: Check to see if any characters are already in the
356 keyboard buffer
357 */
358
typahead()359 typahead()
360
361 {
362 tcheck: /* if type ahead is already pending... */
363 if (in_check())
364 return(TRUE);
365
366 /* check the signal for IDCMP events pending */
367 if ((1 << win->UserPort->mp_SigBit) != 0)
368 return(TRUE);
369
370 /* no event in queue... no typeahead ready */
371 return(FALSE);
372 }
373 #endif
374
doevent()375 doevent()
376
377 {
378 register int eventX, eventY; /* local copies of the event info */
379 struct IntuiMessage *event; /* current event to repond to */
380 ULONG class; /* class of event */
381 USHORT code; /* data code */
382 SHORT x,y; /* mouse x/y position at time of event */
383 char buf[128]; /*temp buff*/
384
385 /* wait for an event to occur */
386 Wait(1 << win->UserPort->mp_SigBit);
387
388 /* get the event and parse it up */
389 while (event = GetMsg(win->UserPort)) {
390 class = event->Class;
391 code = event->Code;
392 eventX = event->MouseX;
393 eventY = event->MouseY;
394 ReplyMsg(event);
395
396 /* a normal keystroke? */
397 if (class == RAWKEY) { dokey(code);
398 continue;
399 }
400
401 /* User clicked on the close gadget! */
402 if (class == CLOSEWINDOW) {
403 quit(FALSE, 0);
404 stuffibuf(255, 0, 0); /* fake a char to force quit to work */
405 }
406
407 /* resolve the mouse address (border adjusted) */
408 if (class == NEWSIZE) {
409 x = (win->Width - 5) / CRWIDTH;
410 y = (win->Height - 10) / CRHEIGHT;
411 } else {
412 x = (eventX - 5) / CRWIDTH;
413 y = (eventY - 10) / CRHEIGHT;
414 }
415 if (x > 77)
416 x = 77;
417 if (y > 23)
418 y = 23;
419
420 /* are we resizing the window? */
421 if (class == NEWSIZE) {
422 stuffibuf(MOUS | '1', x, y);
423 continue;
424 }
425
426 /* and lastly, a mouse button press */
427 switch (code) {
428 case 104: stuffibuf(MOUS | mod('a'), x, y);
429 break;
430 case 232: stuffibuf(MOUS | mod('b'), x, y);
431 break;
432 case 105: stuffibuf(MOUS | mod('e'), x, y);
433 break;
434 case 233: stuffibuf(MOUS | mod('f'), x, y);
435 break;
436 }
437 }
438 return;
439 }
440
mod(c)441 int mod(c) /* modify a character by the current shift and control flags */
442
443 int c; /* original character */
444
445 {
446 /* first apply the shift and control modifiers */
447 if (l_shiftflag || r_shiftflag || lockflag)
448 c -= 32;
449 if (ctrlflag)
450 c |= CTRL;
451 return(c);
452 }
453
sendcon(buf)454 sendcon(buf) /* send a string to the console */
455
456 char *buf; /* buffer to write out */
457
458 {
459 /* initialize the IO request */
460 con.io_Data = (APTR)buf;
461 con.io_Length = strlen(buf);
462 con.io_Command = CMD_WRITE;
463
464 /* and perform the I/O */
465 SendIO(&con);
466 }
467
468
469 /* process an incomming keyboard code */
470
dokey(code)471 dokey(code)
472
473 int code; /* raw keycode to convert */
474
475 {
476 register int ekey; /* translate emacs key */
477 register int dir; /* key direction (up/down) */
478 char buf[NSTRING];
479
480 /* decode the direction of the key */
481 dir = TRUE;
482 if (code > 127) {
483 code = code & 127;
484 dir = FALSE;
485 }
486
487 /* process various shift keys */
488 if (code >= 0x60) {
489 switch (code) {
490
491 case 0x60: l_shiftflag = dir; break;
492 case 0x61: r_shiftflag = dir; break;
493 case 0x62: lockflag = dir; break;
494 case 0x63: ctrlflag = dir; break;
495 case 0x64: l_altflag = dir; break;
496 case 0x65: r_altflag = dir; break;
497 case 0x66: l_amiflag = dir; break;
498 case 0x67: r_amiflag = dir; break;
499
500 }
501 return;
502 }
503
504 /* up keystrokes are ignored for the rest of these */
505 if (dir == FALSE)
506 return;
507
508 /* first apply the shift and control modifiers */
509 if (ctrlflag)
510 ekey = keytrans[code].rw_ccode;
511 else if (l_shiftflag || r_shiftflag || lockflag)
512 ekey = keytrans[code].rw_scode;
513 else
514 ekey = keytrans[code].rw_code;
515
516 /* now apply the ALTD modifier */
517 if (r_altflag || l_altflag)
518 ekey |= ALTD;
519
520 /* apply the META prefix */
521 if (r_amiflag || l_amiflag) {
522 if ('a' <= ekey && ekey <= 'z')
523 ekey -= 32;
524 ekey |= META;
525 }
526
527 /* and place it in the input buffer */
528 stuffibuf(ekey, 0, 0);
529 }
530
stuffibuf(key,x,y)531 stuffibuf(key, x, y) /* stuff a key in the input buffer */
532
533 int key; /* extended keystroke to remember */
534 int x, y; /* mouse position to record */
535
536 {
537 register int upper; /* upper extended bits of key */
538
539 /* split the extended keystroke */
540 upper = key >> 8;
541 key = key & 255;
542
543 /* if it is JUST control... encode it in! */
544 if (upper == (CTRL >> 8)) {
545 in_put(key - 64);
546 return;
547 }
548
549 /* if it is normal, just place it inqueue */
550 if (upper == 0) {
551 in_put(key);
552 return;
553 }
554
555 /* queue up an extended escape sequence */
556 in_put(0); /* escape indicator */
557 in_put(upper); /* event type */
558 if (upper & (MOUS >> 8)) {
559 in_put(x); /* x position */
560 in_put(y); /* y position */
561 }
562 in_put(key); /* event code */
563 return;
564 }
565
566 /*
567 * Create a subjob with a copy of the command intrepreter in it. When the
568 * command interpreter exits, mark the screen as garbage so that you do a full
569 * repaint. Bound to "^X C". The message at the start in VMS puts out a newline.
570 * Under some (unknown) condition, you don't get one free when DCL starts up.
571 */
spawncli(f,n)572 spawncli(f, n)
573 {
574 long newcli;
575
576 /* don't allow this command if restricted */
577 if (restflag)
578 return(resterr());
579
580 mlwrite(TEXT1);
581 /* "[Starting new CLI]" */
582 sgarbf = TRUE;
583 Execute("NEWCLI \"CON:0/0/640/200/MicroEMACS Subprocess\"", 0L, 0L);
584 return(TRUE);
585 }
586
587 /*
588 * Run a one-liner in a subjob. When the command returns, wait for a single
589 * character to be typed, then mark the screen as garbage so a full repaint is
590 * done. Bound to "C-X !".
591 */
spawn(f,n)592 spawn(f, n)
593 {
594 register int s;
595 char line[NLINE];
596
597 long newcli;
598
599 /* don't allow this command if restricted */
600 if (restflag)
601 return(resterr());
602
603 if ((s=mlreply("!", line, NLINE)) != TRUE)
604 return (s);
605 newcli = Open("CON:0/0/640/200/MicroEMACS Subprocess", NEW);
606 Execute(line, 0L, newcli);
607 Close(newcli);
608 tgetc(); /* Pause. */
609 sgarbf = TRUE;
610 return(TRUE);
611 }
612
613 /*
614 * Run an external program with arguments. When it returns, wait for a single
615 * character to be typed, then mark the screen as garbage so a full repaint is
616 * done. Bound to "C-X $".
617 */
618
execprg(f,n)619 execprg(f, n)
620
621 {
622 register int s;
623 char line[NLINE];
624
625 long newcli;
626
627 /* don't allow this command if restricted */
628 if (restflag)
629 return(resterr());
630
631 if ((s=mlreply("!", line, NLINE)) != TRUE)
632 return (s);
633 newcli = Open("CON:0/0/640/200/MicroEMACS Subprocess", NEW);
634 Execute(line, 0L, newcli);
635 Close(newcli);
636 tgetc(); /* Pause. */
637 sgarbf = TRUE;
638 return(TRUE);
639 }
640
641 /*
642 * Pipe a one line command into a window
643 * Bound to ^X @
644 */
pipecmd(f,n)645 pipecmd(f, n)
646 {
647 register int s; /* return status from CLI */
648 register EWINDOW *wp; /* pointer to new window */
649 register BUFFER *bp; /* pointer to buffer to zot */
650 char line[NLINE]; /* command line send to shell */
651 static char bname[] = "command";
652
653 static char filnam[] = "ram:command";
654 long newcli;
655
656 /* don't allow this command if restricted */
657 if (restflag)
658 return(resterr());
659
660 /* get the command to pipe in */
661 if ((s=mlreply("@", line, NLINE)) != TRUE)
662 return(s);
663
664 /* get rid of the command output buffer if it exists */
665 if ((bp=bfind(bname, FALSE, 0)) != FALSE) {
666 /* try to make sure we are off screen */
667 wp = wheadp;
668 while (wp != NULL) {
669 if (wp->w_bufp == bp) {
670 onlywind(FALSE, 1);
671 break;
672 }
673 wp = wp->w_wndp;
674 }
675 if (zotbuf(bp) != TRUE)
676
677 return(FALSE);
678 }
679
680 newcli = Open("CON:0/0/640/200/MicroEMACS Subprocess", NEW);
681 strcat(line, " >");
682 strcat(line, filnam);
683 Execute(line, 0L, newcli);
684 s = TRUE;
685 Close(newcli);
686 sgarbf = TRUE;
687
688 if (s != TRUE)
689 return(s);
690
691 /* split the current window to make room for the command output */
692 if (splitwind(FALSE, 1) == FALSE)
693 return(FALSE);
694
695 /* and read the stuff in */
696 if (getfile(filnam, FALSE) == FALSE)
697 return(FALSE);
698
699 /* make this window in VIEW mode, update all mode lines */
700 curwp->w_bufp->b_mode |= MDVIEW;
701 wp = wheadp;
702 while (wp != NULL) {
703 wp->w_flag |= WFMODE;
704 wp = wp->w_wndp;
705 }
706
707 /* and get rid of the temporary file */
708 unlink(filnam);
709 return(TRUE);
710 }
711
712 /*
713 * filter a buffer through an external DOS program
714 * Bound to ^X #
715 */
filter(f,n)716 filter(f, n)
717
718 {
719 register int s; /* return status from CLI */
720 register BUFFER *bp; /* pointer to buffer to zot */
721 char line[NLINE]; /* command line send to shell */
722 char tmpnam[NFILEN]; /* place to store real file name */
723 static char bname1[] = "fltinp";
724
725 static char filnam1[] = "ram:fltinp";
726 static char filnam2[] = "ram:fltout";
727 long newcli;
728
729 /* don't allow this command if restricted */
730 if (restflag)
731 return(resterr());
732
733 if (curbp->b_mode&MDVIEW) /* don't allow this command if */
734 return(rdonly()); /* we are in read only mode */
735
736 /* get the filter name and its args */
737 if ((s=mlreply("#", line, NLINE)) != TRUE)
738 return(s);
739
740 /* setup the proper file names */
741 bp = curbp;
742 strcpy(tmpnam, bp->b_fname); /* save the original name */
743 strcpy(bp->b_fname, bname1); /* set it to our new one */
744
745 /* write it out, checking for errors */
746 if (writeout(filnam1, "w") != TRUE) {
747 mlwrite(TEXT2);
748 /* "[Cannot write filter file]" */
749 strcpy(bp->b_fname, tmpnam);
750 return(FALSE);
751 }
752
753 newcli = Open("CON:0/0/640/200/MicroEMACS Subprocess", NEW);
754 strcat(line, " <ram:fltinp >ram:fltout");
755 Execute(line,0L,newcli);
756 s = TRUE;
757 Close(newcli);
758 sgarbf = TRUE;
759
760 /* on failure, escape gracefully */
761 if (s != TRUE || (readin(filnam2,FALSE) == FALSE)) {
762 mlwrite(TEXT3);
763 /* "[Execution failed]" */
764 strcpy(bp->b_fname, tmpnam);
765 unlink(filnam1);
766 unlink(filnam2);
767 return(s);
768 }
769
770 /* reset file name */
771 strcpy(bp->b_fname, tmpnam); /* restore name */
772 bp->b_flag |= BFCHG; /* flag it as changed */
773
774 /* and get rid of the temporary file */
775 unlink(filnam1);
776 unlink(filnam2);
777 return(TRUE);
778 }
779
780 /* return a system dependant string with the current time */
781
timeset()782 char *PASCAL NEAR timeset()
783
784 {
785 return(errorm);
786 }
787
788 #if AZTEC
789 /* FILE Directory routines */
790
791 char path[NFILEN]; /* path of file to find */
792 char rbuf[NFILEN]; /* return file buffer */
793 extern char *scdir();
794
795 /* do a wild card directory search (for file name completion) */
796
getffile(fspec)797 char *PASCAL NEAR getffile(fspec)
798
799 char *fspec; /* pattern to match */
800
801 {
802 register int index; /* index into various strings */
803 char fname[NFILEN]; /* file/path for DOS call */
804
805 /* first parse the file path off the file spec */
806 strcpy(path, fspec);
807 index = strlen(path) - 1;
808 while (index >= 0 && (path[index] != '/' &&
809 path[index] != '\\' && path[index] != ':'))
810 --index;
811 path[index+1] = 0;
812
813 /* construct the composite wild card spec */
814 strcpy(fname, path);
815 strcat(fname, &fspec[index+1]);
816 strcat(fname, "*.*");
817
818 /* save the path/wildcard off */
819 strcpy(path, fname);
820
821 /* and call for the first file */
822 return(getnfile());
823 }
824
getnfile()825 char *PASCAL NEAR getnfile()
826
827 {
828 register char *sp; /* return from scdir */
829
830 /* and call for the next file */
831 sp = scdir(path);
832 if (sp == NULL)
833 return(NULL);
834
835 /* return the next file name! */
836 strcpy(rbuf, sp);
837 return(rbuf);
838 }
839 #else
getffile(fspec)840 char *PASCAL NEAR getffile(fspec)
841
842 char *fspec; /* file to match */
843
844 {
845 return(NULL);
846 }
847
getnfile()848 char *PASCAL NEAR getnfile()
849
850 {
851 return(NULL);
852 }
853 #endif
854
855 #if AZTEC
856
857 /* Big flame..... AZTEC C documents, but seems to be missing the
858 standard library realloc() function. A quick replacement is
859 below. Note that this ALWAYS copies to a new block, and is
860 thus inherently less efficient than a native one would be.
861 */
862
realloc(ptr,size)863 char *realloc(ptr, size)
864
865 char *ptr; /* original pointer */
866 int size; /* # of bytes for newly allocated block */
867
868 {
869 char *src, *dest; /* ptrs for byte copying */
870 char *nptr; /* newly allocated pointer */
871
872 /* allocate the new memory block */
873 nptr = malloc(size);
874 if (nptr == NULL)
875 return(NULL);
876
877 /* copy the bytes from the old one */
878 src = ptr;
879 dest = nptr;
880 while (size--)
881 *dest++ = *src++;
882
883 /* and free the old one */
884 free(ptr);
885 return(nptr);
886 }
887
888 #else
adoshello()889 adoshello()
890 {
891 }
892 #endif
893