-
Notifications
You must be signed in to change notification settings - Fork 0
/
amitty.c
334 lines (280 loc) · 7.56 KB
/
amitty.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
/* amitty.c */
/*-
* Mike Rieser Dale Rahn
* 2410 Happy Hollow Rd. Apt D-10 540 Vine St.
* West Lafayette, IN 47906 West Lafayette, IN 47906
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <exec/memory.h>
#include <devices/conunit.h>
#include <dos/dos.h>
#include <clib/macros.h>
#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#if AZTEC_C
#include <pragmas/exec_lib.h>
#include <pragmas/dos_lib.h>
#else
#include <pragmas/exec.h>
#include <pragmas/dos.h>
#endif
#include "config.h"
/*-
* Defines for amigatty.
*
* Note: Amiga <CSI> Control Sequence Introducer is either:
* 0x9b or <ESC>[ == 0x1b 0x5b.
*
* The Amiga always responds with 0x9b.
*
* For you octal fans: 0x9b == \233, 0x1b == \033.
*/
#define CSI '\233'
#define TIME_FACTOR (100000)/* convert 1/10 sec to microsecs */
/* Amiga Console Control Sequences */
#define ENABLE_SCROLL ((UBYTE *) "\233>1h") /* Amiga default */
#define DISABLE_SCROLL ((UBYTE *) "\233>1l")
#define AUTOWRAP_ON ((UBYTE *) "\233?7h") /* Amiga default */
#define AUTOWRAP_OFF ((UBYTE *) "\233?7l")
#define CURSOR_ON ((UBYTE *) "\233 p") /* Amiga default */
#define CURSOR_OFF ((UBYTE *) "\2330 p")
#define RAW_EVENTS_ON ((UBYTE *) "\23312{") /* Set Window Resize Reports */
#define RAW_EVENTS_OFF ((UBYTE *) "\23312}") /* Reset Window Resize Reports */
/* take out for compiling with elvis */
#ifndef ctrl
#define ctrl(ch) ((ch)&037)
#endif
/* Variables */
static BPTR fh = 0, inputFH, outputFH, oldinputFH, oldoutputFH;
static UBYTE title[]= "RAW:0/0/999/999/Amiga Elvis 1.5/SIMPLE";
static int amigaterm = 0;
/* Function prototypes for amitty.c */
void amiopenwin(char *termtype);
void amiclosewin(void);
void ttysetup(void);
void ttyshutdown(void);
int ttywrite(char *buf, int len);
int ttyread(char *buf, int len, int time);
int CheckforSpecial(char *buf, long len);
LONG setRawCon(LONG toggle);
LONG sendpkt(struct MsgPort *pid, LONG action, LONG args[], LONG nargs);
/*
* amiopenwin - opens a window if we don't already have one.
*/
void
amiopenwin(char *termtype)
{
if (!IsInteractive(Input()))
{
/* open our own window in RAW mode */
if (isOldDOS() || (BPTR) 0 == (fh = Open(title, MODE_READWRITE)))
{
PutStr((UBYTE *) "Couldn't open RAW: window");
clean_exit(2);
} else
{
oldinputFH = SelectInput(fh);
oldoutputFH = SelectOutput(fh);
}
}
inputFH = Input();
outputFH = Output();
if (!strcmp(termtype, TERMTYPE))
{
amigaterm = 1;
Write(outputFH, AUTOWRAP_OFF, sizeof(AUTOWRAP_OFF));
}
return;
}
/*
* amiclosewin - closes a window if we opened one.
*/
void
amiclosewin()
{
if (amigaterm)
{
Write(outputFH, AUTOWRAP_ON, sizeof(AUTOWRAP_ON)); /* Amiga default */
}
if (fh)
{ /* Close down the window */
SelectInput(oldinputFH);
SelectOutput(oldoutputFH);
Close(fh);
}
return;
}
/*
* ttysetup - console initalization routine for Amiga Computers.
*
* Sets raw mode and enables resize notifications.
*/
void
ttysetup()
{
if (isOldDOS())
{
setRawCon(DOSTRUE);
} else
{
SetMode(inputFH, 1); /* Enter RAW mode */
}
if (amigaterm)
{
Write(outputFH, RAW_EVENTS_ON, sizeof(RAW_EVENTS_ON));
}
return;
}
/*
* ttyshutdown - console shutdown routine for Amiga Computers.
*
* Resets raw mode and disables resize notifications.
*/
void
ttyshutdown()
{
if (amigaterm)
{
Write(outputFH, RAW_EVENTS_OFF, sizeof(RAW_EVENTS_OFF));
}
if (isOldDOS())
{
setRawCon(DOSFALSE);
} else
{
SetMode(inputFH, 0); /* Leave RAW mode */
}
return;
}
/*
* ttywrite - amiga version of ttywrite.
*
* This version makes small writes to the console as suggested in the RKM.
* Also turns off the cursor to speed output to the screen.
*/
int
ttywrite(buf, len)
char *buf;
int len;
{
int cursor_off;
register int bytes;
register UBYTE *pc = (UBYTE *) buf;
/* See if turning off the cursor is worthwhile */
if (cursor_off = amigaterm && len > 2 * sizeof(CURSOR_OFF))
{
Write(outputFH, CURSOR_OFF, sizeof(CURSOR_OFF)); /* Turn Cursor OFF */
}
/* The console.device doesn't like large writes */
for (bytes = 0; len; pc += bytes, len -= bytes)
{
bytes = Write(outputFH, pc, MIN((LONG) len, 256L));
}
if (cursor_off)
{
Write(outputFH, CURSOR_ON, sizeof(CURSOR_ON)); /* Turn Cursor ON */
}
return pc - buf;
}
/*
* ttyread - amiga version of ttyread.
*/
int
ttyread(buf, len, time)
char *buf; /* where to store the gotten characters */
int len; /* maximum number of characters to read */
int time; /* maximum time in 1/10 sec for reading */
{
LONG bytes = 0; /* number of bytes actually read */
if (!time || WaitForChar(inputFH, time * TIME_FACTOR))
{ /* Read() if time == 0 or chars waiting */
bytes = Read(inputFH, (UBYTE *) buf, (LONG) len);
bytes = CheckforSpecial(buf, bytes);
}
return bytes; /* the number of bytes read in buf */
}
/*
* CheckforSpecial - crude parser for raw console events.
*/
int
CheckforSpecial(buf, len)
char *buf;
long len;
{
int isnewsize = 0;
char *pb, *peor, *pend;
pb = buf;
pend = &buf[len];
do
{
if (CSI != *pb)
continue;
if (WaitForChar(inputFH, 1))
{
pend += Read(inputFH, pend, 72);
}
if (peor = strchr((char *) pb, '|')) /* Window Resize Event */
{ /* bug == <CSI> seq <CSI> event '|' */
*pb = ctrl('L'); /* force redraw */
isnewsize = 1;
memmove(pb + 1, peor + 1, pend - peor);
pend -= peor - pb;
}
}
while (*pb++);
if (isnewsize)
getsize(0);
return pend - buf;
}
/* INDENT OFF */
/* sendpkt code - A. Finkel, P. Lindsay, C. Scheppner CBM */
LONG setRawCon(toggle)
LONG toggle; /* DOSTRUE (-1L) or DOSFALSE (0L) */
{
struct MsgPort *conid;
struct Process *me;
LONG myargs[8] ,nargs, res1;
me = (struct Process *) FindTask(NULL);
conid = (struct MsgPort *) me->pr_ConsoleTask;
myargs[0]= toggle;
nargs = 1;
res1 = (LONG)sendpkt(conid,ACTION_SCREEN_MODE,myargs,nargs);
return(res1);
}
LONG sendpkt(pid,action,args,nargs)
struct MsgPort *pid; /* process indentifier ... (handlers message port ) */
LONG action, /* packet type ... (what you want handler to do ) */
args[], /* a pointer to a argument list */
nargs; /* number of arguments in list */
{
struct MsgPort *replyport;
struct StandardPacket *packet;
LONG count, *pargs, res1;
replyport = (struct MsgPort *) CreatePort(NULL,0);
if(!replyport) return((LONG)NULL);
packet = (struct StandardPacket *)
AllocMem((long)sizeof(struct StandardPacket),MEMF_PUBLIC|MEMF_CLEAR);
if(!packet)
{
DeletePort(replyport);
return((LONG)NULL);
}
packet->sp_Msg.mn_Node.ln_Name = (char *)&(packet->sp_Pkt);
packet->sp_Pkt.dp_Link = &(packet->sp_Msg);
packet->sp_Pkt.dp_Port = replyport;
packet->sp_Pkt.dp_Type = action;
/* copy the args into the packet */
pargs = &(packet->sp_Pkt.dp_Arg1); /* address of first argument */
for(count=0;count < nargs;count++)
pargs[count]=args[count];
PutMsg(pid,(struct Message *)packet); /* send packet */
WaitPort(replyport);
GetMsg(replyport);
res1 = packet->sp_Pkt.dp_Res1;
FreeMem(packet,(long)sizeof(struct StandardPacket));
DeletePort(replyport);
return(res1);
}