1 /* -*-C-*-
2 *
3 * Module : amiga.c
4 *
5 * Author : Simon J Raybould. (sie@fulcrum.bt.co.uk).
6 *
7 * Date : Tuesday 11th June 1991.
8 *
9 * Desc : amiga specifics for beav binary editor.
10 *
11 *
12 * This file is public domain and you can do what you want with it, even roll
13 * it up into a ball and toss it for your cat to chase. I accept no
14 * resposibility for it being unfit for any purpose (including a feline toy).
15 * Any bugs you can either fix them yourself or tell me and I'll do it.
16 * Any major fixes should be reported to me and I will inform the main keeper
17 * of beav to be sure they are fixed in the next release. This only applies to
18 * bugs in THIS FILE or in AMIGA sections of other files. Any other bugs to the
19 * original author.
20 *
21 * SJR - 25.Aug.91
22 *
23 *
24 */
25
26 #ifdef AMIGA
27
28 #include <stdio.h>
29 #include <fcntl.h>
30 #include <errno.h>
31 #include <signal.h>
32 #include <libraries/dosextens.h>
33 #include <exec/memory.h>
34 #include <intuition/intuition.h>
35
36 #include "def.h"
37
38 #define SCRBUFSIZ 1024 /* buffered screen io */
39
40 struct NewWindow nw =
41 {
42 0, 0, 640, 256, -1, -1, NULL,
43 WINDOWDEPTH | WINDOWDRAG | SMART_REFRESH | ACTIVATE | BORDERLESS,
44 NULL, NULL,
45 "BEAV Amiga Port by S.J.Raybould (sie@fulcrum.bt.co.uk) Sep 1991",
46 NULL, NULL, 0, 0, 0, 0, WBENCHSCREEN
47 };
48
49 /* Opens/allocations we'll need to clean up */
50 struct Library *IntuitionBase = NULL;
51 struct Window *win = NULL, *OpenWindow ();
52 struct IOStdReq *writeReq = NULL; /* I/O request block pointer */
53 struct MsgPort *writePort = NULL; /* replyport for writes */
54
55 struct IOStdReq *readReq = NULL;/* I/O request block pointer */
56 struct MsgPort *readPort = NULL;/* replyport for reads */
57
58 struct MsgPort *CreatePort ();
59 BOOL OpenedConsole = FALSE;
60 UBYTE ibuf;
61 BYTE OpenConsole ();
62 void CloseConsole (), QueueRead (), ConWrite ();
63
64
65 int nrow; /* Terminal size, rows. */
66 int ncol; /* Terminal size, columns. */
67 #ifdef CRAP
68 int tceeol = 3; /* Costs. */
69 #endif /* CRAP */
70
71 int kbdpoll; /* in O_NDELAY mode */
72 int kbdqp; /* there is a char in kbdq */
73
74 char scrbuf[SCRBUFSIZ]; /* buffered screen io */
75 short scrbufpos = 0; /* current write position */
76
77 /* CODE TO REPLACE STUFF IN termio.c */
78
79 /*
80 * This function gets called just before we go back home to the command
81 * interpreter. On VMS it puts the terminal back in a reasonable state.
82 * Another no-operation on CPM.
83 */
84 void
ttclose()85 ttclose ()
86 {
87 /* Put TTY back in sesible state */
88 if (!(CheckIO (readReq)))
89 AbortIO (readReq);
90 WaitIO (readReq);
91 if (OpenedConsole)
92 CloseConsole (writeReq);
93 if (readReq)
94 DeleteExtIO (readReq);
95 if (readPort)
96 DeletePort (readPort);
97 if (writeReq)
98 DeleteExtIO (writeReq);
99 if (writePort)
100 DeletePort (writePort);
101 if (win)
102 CloseWindow (win);
103 if (IntuitionBase)
104 CloseLibrary (IntuitionBase);
105 }
106
107 /*
108 * Flush terminal buffer. Does real work where the terminal output is buffered
109 * up. A no-operation on systems where byte at a time terminal I/O is done.
110 */
111 void
ttflush()112 ttflush ()
113 {
114 if (scrbufpos > 0)
115 {
116 ConWrite (writeReq, scrbuf, scrbufpos);
117 scrbufpos = 0;
118 }
119 }
120
121 /*
122 * Write a character to the display. On VMS, terminal output is buffered, and
123 * we just put the characters in the big array, after checking for overflow.
124 * On CPM terminal I/O unbuffered, so we just write the byte out. Ditto on
125 * MS-DOS (use the very very raw console output routine).
126 */
127 void
ttputc(c)128 ttputc (c)
129 {
130 if (scrbufpos < SCRBUFSIZ)
131 scrbuf[scrbufpos++] = c;
132 else
133 {
134 ConWrite (writeReq, scrbuf, scrbufpos);
135 scrbufpos = 0;
136 scrbuf[scrbufpos++] = c;
137 }
138 }
139
140 void
ttputs(char * str)141 ttputs (char *str)
142 {
143 while (*str)
144 ttputc (*str++);
145 }
146
147 /*
148 * Read a character from the terminal, performing no editing and doing no echo
149 * at all. More complex in VMS that almost anyplace else, which figures. Very
150 * simple on CPM, because the system can do exactly what you want.
151 */
ttgetc()152 ttgetc ()
153 {
154 char c, ConGetChar ();
155 static char Buffer[8], ri = 0, wi = 0;
156
157 if (kbdqp)
158 kbdqp = FALSE;
159 /* If we stil have chars from last time, return them */
160 if (ri < wi)
161 return Buffer[ri++] & 0x7f;
162
163 /* Else empty the buffer and start a new read */
164 ri = wi = 0;
165 c = ConGetChar (readPort, &ibuf);
166 /*
167 * Attempt some translations !
168 * This is the place to extend, if you wish to add some more.
169 * SEE RKM L&D 1.3 pg 654 for more info.
170 */
171 if ((unsigned char) c == (unsigned char) 0x9b)
172 { /* ANSI esc start */
173 c = ConGetChar (readPort, &ibuf);
174 switch (c)
175 {
176 case 'A': /* UP */
177 Buffer[wi++] = 0x10;/* ^P */
178 break;
179 case 'B': /* DOWN */
180 Buffer[wi++] = 0x0e;/* ^N */
181 break;
182 case 'C': /* RIGHT */
183 Buffer[wi++] = 0x06;/* ^F */
184 break;
185 case 'D': /* LEFT */
186 Buffer[wi++] = 0x02;/* ^B */
187 break;
188 case '0': /* F1 */
189 ConGetChar (readPort, &ibuf); /* discard tilde */
190 Buffer[wi++] = 0x1b;/* HELP = "ESC ?" */
191 Buffer[wi++] = '?';
192 break;
193 case '1': /* F2 or SHIFTED function key */
194 c = ConGetChar (readPort, &ibuf); /* Get next char to see if it's a tilde */
195 switch (c)
196 {
197 case '~': /* was definately F2 */
198 Buffer[wi++] = 0x1b; /* mark-set = "ESC ." */
199 Buffer[wi++] = '.';
200 break;
201 case '0': /* SHIFTED F1 */
202 ConGetChar (readPort, &ibuf); /* Discard the tilde */
203 Buffer[wi++] = 0x18; /* binding-for-key = "Ctl-X ?" */
204 Buffer[wi++] = '?';
205 break;
206 case '1': /* SHIFTED F2 */
207 ConGetChar (readPort, &ibuf); /* Discard the tilde */
208 Buffer[wi++] = 0x18; /* file-read = "Ctl-X Ctl-R" */
209 Buffer[wi++] = 0x12;
210 break;
211 case '2': /* SHIFTED F3 */
212 ConGetChar (readPort, &ibuf); /* Discard the tilde */
213 Buffer[wi++] = 0x18; /* file-save = "Ctl-X Ctl-S" */
214 Buffer[wi++] = 0x13;
215 break;
216 case '3': /* SHIFTED F4 */
217 ConGetChar (readPort, &ibuf); /* Discard the tilde */
218 Buffer[wi++] = 0x18; /* file-visit = "Ctl-X Ctl-V" */
219 Buffer[wi++] = 0x16;
220 break;
221 case '4': /* SHIFTED F5 */
222 ConGetChar (readPort, &ibuf); /* Discard the tilde */
223 Buffer[wi++] = 0x18; /* file-write = "Ctl-X Ctl-W" */
224 Buffer[wi++] = 0x17;
225 break;
226 case '5': /* SHIFTED F6 */
227 ConGetChar (readPort, &ibuf); /* Discard the tilde */
228 Buffer[wi++] = 0x18; /* save-all-buffers = "Ctl-X return" */
229 Buffer[wi++] = '\r';
230 break;
231 case '6': /* SHIFTED F7 */
232 ConGetChar (readPort, &ibuf); /* Discard the tilde */
233 Buffer[wi++] = 0x18; /* buffer-set-file-name = "Ctl-X Ctl-F" */
234 Buffer[wi++] = 0x06;
235 break;
236 case '7': /* SHIFTED F8 */
237 ConGetChar (readPort, &ibuf); /* Discard the tilde */
238 Buffer[wi++] = 0x18; /* insert-file = "Ctl-X TAB" */
239 Buffer[wi++] = '\t';
240 break;
241 case '8': /* SHIFTED F9 */
242 ConGetChar (readPort, &ibuf); /* Discard the tilde */
243 Buffer[wi++] = 0x18; /* quit-save-all = "Ctl-X Ctl-E" */
244 Buffer[wi++] = 0x05;
245 break;
246 case '9': /* SHIFTED F10 */
247 ConGetChar (readPort, &ibuf); /* Discard the tilde */
248 Buffer[wi++] = 0x03; /* quit-no-save = "Ctl-C" */
249 break;
250 }
251 break;
252 case '2': /* F3 */
253 ConGetChar (readPort, &ibuf); /* Discard the tilde */
254 Buffer[wi++] = 0x1b;/* search-forv = "ESC s" */
255 Buffer[wi++] = 's';
256 break;
257 case '3': /* F4 */
258 ConGetChar (readPort, &ibuf); /* Discard the tilde */
259 Buffer[wi++] = 0x1b;/* search-again = "ESC t" */
260 Buffer[wi++] = 't';
261 break;
262 case '4': /* F5 */
263 ConGetChar (readPort, &ibuf); /* Discard the tilde */
264 Buffer[wi++] = 0x1b;/* replace = "ESC %" */
265 Buffer[wi++] = '%';
266 break;
267 case '5': /* F6 */
268 ConGetChar (readPort, &ibuf); /* Discard the tilde */
269 Buffer[wi++] = 0x19;/* yank = "Ctl-Y" */
270 break;
271 case '6': /* F7 */
272 ConGetChar (readPort, &ibuf); /* Discard the tilde */
273 Buffer[wi++] = 0x1b;/* copy-mark-to-cursor = "ESC w" */
274 Buffer[wi++] = 'w';
275 break;
276 case '7': /* F8 */
277 ConGetChar (readPort, &ibuf); /* Discard the tilde */
278 Buffer[wi++] = 0x17;/* delete-mark-to-cursor = "Ctl-W" */
279 break;
280 case '8': /* F9 */
281 ConGetChar (readPort, &ibuf); /* Discard the tilde */
282 Buffer[wi++] = 0x18;/* move-to-byte = "Ctl-X G" */
283 Buffer[wi++] = 'G';
284 break;
285 case '9': /* F10 */
286 ConGetChar (readPort, &ibuf); /* Discard the tilde */
287 Buffer[wi++] = 0x07;/* abort-cmd = "Ctl-G" */
288 break;
289 case '?': /* HELP */
290 ConGetChar (readPort, &ibuf); /* Discard the tilde */
291 Buffer[wi++] = 0x1b;/* help = "ESC ?" */
292 Buffer[wi++] = '?';
293 break;
294 }
295 return Buffer[ri++] & 0x7f;
296 }
297 else /* not an ANSI sequence */
298 return c & 0x7f;
299 }
300
301 /*
302 * This function is called once to set up the terminal device streams.
303 * On VMS, it translates TT until it finds the terminal, then assigns
304 * a channel to it and sets it raw. On CPM it is a no-op.
305 */
306
307 void
ttopen()308 ttopen ()
309 {
310 int Sig;
311 ULONG conreadsig, windowsig;
312 BYTE error;
313 struct Screen Screen; /* get a copy of WBENCHSCREEN in here */
314
315
316 if (!(IntuitionBase = (struct IntuitionBase *) OpenLibrary ("intuition.library", 0)))
317 {
318 printf ("Can't open intuition\n");
319 ttclose ();
320 exit (10);
321 }
322 /* Create reply port and io block for writing to console */
323 if (!(writePort = CreatePort ("LARN.console.write", 0)))
324 {
325 printf ("Can't create write port\n");
326 ttclose ();
327 exit (10);
328 }
329 if (!(writeReq = (struct IOStdReq *)
330 CreateExtIO (writePort, (LONG) sizeof (struct IOStdReq))))
331 {
332 printf ("Can't create write request\n");
333 ttclose ();
334 exit (10);
335 }
336 /* Create reply port and io block for reading from console */
337 if (!(readPort = CreatePort ("LARN.console.read", 0)))
338 {
339 printf ("Can't create read port\n");
340 ttclose ();
341 exit (10);
342 }
343 if (!(readReq = (struct IOStdReq *)
344 CreateExtIO (readPort, (LONG) sizeof (struct IOStdReq))))
345 {
346 printf ("Can't create read request\n");
347 ttclose ();
348 exit (10);
349 }
350 if (!GetScreenData (&Screen, sizeof (struct Screen), WBENCHSCREEN, NULL))
351 {
352 printf ("Can't get screen size\n");
353 ttclose ();
354 exit (10);
355 }
356 nrow = Screen.Height / 8 - 3;
357 ncol = Screen.Width / 8;
358 nw.Height = Screen.Height;
359 nw.Width = Screen.Width;
360
361 /* don't allow a larger number of rows than we can handle */
362 if (nrow > NROW)
363 nrow = NROW;
364 /* don't allow a larger number of cols than we can handle */
365 if (ncol > NCOL)
366 ncol = NCOL;
367
368 /* Open a window */
369 if (!(win = OpenWindow (&nw)))
370 {
371 printf ("Can't open window\n");
372 ttclose ();
373 exit (10);
374 }
375 /* Now, attach a console to the window */
376 if (error = OpenConsole (writeReq, readReq, win))
377 {
378 printf ("Can't open console.device\n");
379 ttclose ();
380 exit (10);
381 }
382 else
383 OpenedConsole = TRUE;
384
385 QueueRead (readReq, &ibuf); /* send the first console read request */
386 conreadsig = 1 << readPort->mp_SigBit;
387 windowsig = 1 << win->UserPort->mp_SigBit;
388 for (Sig = 0; Sig < NSIG; Sig++)
389 signal (Sig, SIG_IGN);
390
391 kbdpoll = FALSE;
392 /* on all screens we are not sure of the initial position of the cursor */
393 ttrow = 999;
394 ttcol = 999;
395 }
396
397 /* END OF TERMIO REPLACEMENT CODE */
398
399 /* Attach console device to an open Intuition window.
400 * This function returns a value of 0 if the console
401 * device opened correctly and a nonzero value (the error
402 * returned from OpenDevice) if there was an error.
403 */
404 BYTE
OpenConsole(writereq,readreq,window)405 OpenConsole (writereq, readreq, window)
406 struct IOStdReq *writereq;
407 struct IOStdReq *readreq;
408 struct Window *window;
409 {
410 BYTE error;
411
412 writereq->io_Data = (APTR) window;
413 writereq->io_Length = sizeof (struct Window);
414 error = OpenDevice ("console.device", 0, writereq, 0);
415 readreq->io_Device = writereq->io_Device; /* clone required parts */
416 readreq->io_Unit = writereq->io_Unit;
417 return (error);
418 }
419
420 void
CloseConsole(struct IOStdReq * writereq)421 CloseConsole (struct IOStdReq *writereq)
422 {
423 CloseDevice (writereq);
424 }
425
426 /* Output a single character to a specified console
427 */
428 void
ConPutChar(struct IOStdReq * writereq,UBYTE character)429 ConPutChar (struct IOStdReq *writereq, UBYTE character)
430 {
431 writereq->io_Command = CMD_WRITE;
432 writereq->io_Data = (APTR) & character;
433 writereq->io_Length = 1;
434 DoIO (writereq);
435 /* command works because DoIO blocks until command is done
436 * (otherwise ptr to the character could become invalid)
437 */
438 }
439
440 /* Output a stream of known length to a console
441 */
442 void
ConWrite(struct IOStdReq * writereq,UBYTE * string,LONG length)443 ConWrite (struct IOStdReq *writereq, UBYTE * string, LONG length)
444 {
445 writereq->io_Command = CMD_WRITE;
446 writereq->io_Data = (APTR) string;
447 writereq->io_Length = length;
448 DoIO (writereq);
449 /* command works because DoIO blocks until command is done
450 * (otherwise ptr to string could become invalid in the meantime)
451 */
452 }
453
454 /* Output a NULL-terminated string of characters to a console
455 */
456 void
ConPuts(struct IOStdReq * writereq,UBYTE * string)457 ConPuts (struct IOStdReq *writereq, UBYTE * string)
458 {
459 writereq->io_Command = CMD_WRITE;
460 writereq->io_Data = (APTR) string;
461 writereq->io_Length = -1; /* means print till terminating null */
462 DoIO (writereq);
463 }
464
465 /* Queue up a read request to console, passing it pointer
466 * to a buffer into which it can read the character
467 */
468 void
QueueRead(struct IOStdReq * readreq,UBYTE * whereto)469 QueueRead (struct IOStdReq *readreq, UBYTE * whereto)
470 {
471 readreq->io_Command = CMD_READ;
472 readreq->io_Data = (APTR) whereto;
473 readreq->io_Length = 1;
474 SendIO (readreq);
475 }
476
477 struct IOStdReq *readreq; /* ttkeyready() needs to be able to see this */
478
479 /* Wait for a character
480 */
481 char
ConGetChar(struct MsgPort * msgport,UBYTE * whereto)482 ConGetChar (struct MsgPort *msgport, UBYTE * whereto)
483 {
484 register temp;
485
486 WaitPort (msgport);
487 readreq = (struct IOStdReq *) GetMsg (msgport);
488 temp = *whereto; /* get the character */
489 QueueRead (readreq, whereto); /* then re-use the request block*/
490 return ((char) temp);
491 }
492
493 /* typahead(): Check to see if any characters are already in the
494 keyboard buffer
495 On the amiga, we do this by checking if the outstanding read request
496 has been satisfied yet by calling CheckIO().
497 */
ttkeyready()498 ttkeyready ()
499 {
500 if (!kbdqp)
501 kbdqp = CheckIO (readreq) ? 1 : 0;
502 return kbdqp;
503 }
504
505 /* UNIX support stuff */
506
507 #define BLOCKSIZE 4096
508
link(char * SPath,char * DPath)509 link (char *SPath, char *DPath)
510 {
511 int sfd, dfd, Bytes;
512 char BlkBuf[BLOCKSIZE];
513
514 if ((sfd = open (SPath, O_RDONLY)) == -1)
515 return -1;
516 if ((dfd = open (DPath, O_WRONLY | O_CREAT | O_TRUNC)) == -1)
517 return -1;
518 while ((Bytes = read (sfd, BlkBuf, BLOCKSIZE)) > 0)
519 write (dfd, BlkBuf, Bytes);
520 close (sfd);
521 close (dfd);
522 return 0;
523 }
524
525 #endif /* AMIGA */
526