|
|
1.1 root 1: /*
2: * Copyright (c) 1988 Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms are permitted
6: * provided that this notice is preserved and that due credit is given
7: * to the University of California at Berkeley. The name of the University
8: * may not be used to endorse or promote products derived from this
9: * software without specific prior written permission. This software
10: * is provided ``as is'' without express or implied warranty.
11: */
12:
13: #ifndef lint
14: static char sccsid[] = "@(#)api.c 3.2 (Berkeley) 3/28/88";
15: #endif /* not lint */
16:
17: /*
18: * This file implements the API used in the PC version.
19: */
20:
21: #include <stdio.h>
22:
23: #include "api.h"
24: #include "../general/general.h"
25:
26: #include "../api/disp_asc.h"
27:
28: #include "screen.h"
29: #include "oia.h"
30:
31: #include "../general/globals.h"
32:
33: /*
34: * General utility routines.
35: */
36:
37: #if defined(MSDOS)
38:
39: #if defined(LINT_ARGS)
40: static void movetous(char *, int, int, int);
41: static void movetothem(int, int, char *, int);
42: #endif /* defined(LINT_ARGS) */
43:
44: #define access_api(foo,length,copyin) (foo)
45: #define unaccess_api(foo,goo,length,copyout)
46:
47: static void
48: movetous(parms, es, di, length)
49: char *parms;
50: int es, di, length;
51: {
52: char far *farparms = parms;
53:
54: movedata(es, di, (int) FP_SEG(farparms), (int) FP_OFF(farparms), length);
55: }
56:
57: static void
58: movetothem(es, di, parms, length)
59: int es, di;
60: char *parms;
61: int length;
62: {
63: char far *farparms = parms;
64:
65: movedata((int) FP_SEG(farparms), (int) FP_OFF(farparms), es, di, length);
66: }
67: #endif /* defined(MSDOS) */
68:
69: #if defined(unix)
70: extern char *access_api(), *unaccess_api();
71: #endif /* defined(unix) */
72:
73:
74: /*
75: * Supervisor Services.
76: */
77:
78: static void
79: name_resolution(regs, sregs)
80: union REGS *regs;
81: struct SREGS *sregs;
82: {
83: NameResolveParms parms;
84:
85: movetous((char *) &parms, sregs->es, regs->x.di, sizeof parms);
86:
87: regs->h.cl = 0;
88: if (memcmp((char *)&parms, NAME_SESSMGR, sizeof parms.gate_name) == 0) {
89: regs->x.dx = GATE_SESSMGR;
90: } else if (memcmp((char *)&parms, NAME_KEYBOARD,
91: sizeof parms.gate_name) == 0) {
92: regs->x.dx = GATE_KEYBOARD;
93: } else if (memcmp((char *)&parms, NAME_COPY, sizeof parms.gate_name) == 0) {
94: regs->x.dx = GATE_COPY;
95: } else if (memcmp((char *)&parms, NAME_OIAM, sizeof parms.gate_name) == 0) {
96: regs->x.dx = GATE_OIAM;
97: } else {
98: regs->h.cl = 0x2e; /* Name not found */
99: }
100: regs->h.ch = 0x12;
101: regs->h.bh = 7;
102: }
103:
104: /*
105: * Session Information Services.
106: */
107:
108: static void
109: query_session_id(regs, sregs)
110: union REGS *regs;
111: struct SREGS *sregs;
112: {
113: QuerySessionIdParms parms;
114:
115: movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
116:
117: if ((parms.rc != 0) || (parms.function_id != 0)) {
118: parms.rc = 0x0c;
119: } else if (parms.option_code != 0x01) {
120: parms.rc = 0x0d; /* Invalid option code */
121: } else if (parms.data_code != 0x45) {
122: parms.rc = 0x0b;
123: } else {
124: NameArray list;
125: NameArrayElement element;
126:
127: movetous((char *)&list, FP_SEG(parms.name_array),
128: FP_OFF(parms.name_array), sizeof list);
129: if ((list.length < 14) || (list.length > 170)) {
130: parms.rc = 0x12;
131: } else {
132: list.number_matching_session = 1;
133: list.name_array_element.short_name = parms.data_code;
134: list.name_array_element.type = TYPE_DFT;
135: list.name_array_element.session_id = 23;
136: memcpy(list.name_array_element.long_name, "ONLYSESS",
137: sizeof list.name_array_element.long_name);
138: movetothem(FP_SEG(parms.name_array),
139: FP_OFF(parms.name_array), (char *)&list, sizeof list);
140: parms.rc = 0;
141: }
142: }
143: parms.function_id = 0x6b;
144: movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
145: }
146:
147: static void
148: query_session_parameters(regs, sregs)
149: union REGS *regs;
150: struct SREGS *sregs;
151: {
152: QuerySessionParametersParms parms;
153:
154: movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
155:
156: if ((parms.rc !=0) || (parms.function_id != 0)) {
157: parms.rc = 0x0c;
158: } else if (parms.session_id != 23) {
159: parms.rc = 0x02;
160: } else {
161: parms.rc = 0;
162: parms.session_type = TYPE_DFT;
163: parms.session_characteristics = 0; /* Neither EAB nor PSS */
164: parms.rows = MaxNumberLines;
165: parms.columns = MaxNumberColumns;
166: parms.presentation_space = 0;
167: }
168: parms.function_id = 0x6b;
169: movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
170: }
171:
172: static void
173: query_session_cursor(regs, sregs)
174: union REGS *regs;
175: struct SREGS *sregs;
176: {
177: QuerySessionCursorParms parms;
178:
179: movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
180:
181: if ((parms.rc != 0) || (parms.function_id != 0)) {
182: parms.rc = 0x0c;
183: } else if (parms.session_id != 23) {
184: parms.rc = 0x02;
185: } else {
186: parms.rc = 0;
187: parms.cursor_type = CURSOR_BLINKING; /* XXX what is inhibited? */
188: parms.row_address = ScreenLine(CursorAddress);
189: parms.column_address = ScreenLineOffset(CursorAddress);
190: }
191:
192: parms.function_id = 0x6b;
193: movetothem(sregs->es, regs->x.di, (char *) &parms, sizeof parms);
194: }
195:
196: /*
197: * Keyboard Services.
198: */
199:
200:
201: static void
202: connect_to_keyboard(regs, sregs)
203: union REGS *regs;
204: struct SREGS *sregs;
205: {
206: ConnectToKeyboardParms parms;
207:
208: movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
209:
210: if ((parms.rc != 0) || (parms.function_id != 0)) {
211: parms.rc = 0x0c;
212: } else if (parms.session_id != 23) {
213: parms.rc = 0x02;
214: } else if (parms.intercept_options != 0) {
215: parms.rc = 0x01;
216: } else {
217: parms.rc = 0;
218: parms.first_connection_identifier = 0;
219: }
220: parms.function_id = 0x62;
221:
222: movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
223: }
224:
225: static void
226: disconnect_from_keyboard(regs, sregs)
227: union REGS *regs;
228: struct SREGS *sregs;
229: {
230: DisconnectFromKeyboardParms parms;
231:
232: movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
233:
234: if ((parms.rc != 0) || (parms.function_id != 0)) {
235: parms.rc = 0x0c;
236: } else if (parms.session_id != 23) {
237: parms.rc = 0x02;
238: } else if (parms.connectors_task_id != 0) {
239: parms.rc = 04; /* XXX */
240: } else {
241: parms.rc = 0;
242: }
243: parms.function_id = 0x62;
244:
245: movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
246: }
247:
248: static void
249: write_keystroke(regs, sregs)
250: union REGS *regs;
251: struct SREGS *sregs;
252: {
253: WriteKeystrokeParms parms;
254:
255: movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
256:
257: if ((parms.rc != 0) || (parms.function_id != 0)) {
258: parms.rc = 0x0c;
259: } else if (parms.session_id != 23) {
260: parms.rc = 0x02;
261: } else if (parms.connectors_task_id != 0) {
262: parms.rc = 0x04;
263: } else {
264: parms.number_of_keys_sent = 0;
265: parms.rc = 0;
266: if (parms.options == OPTION_SINGLE_KEYSTROKE) {
267: KeystrokeEntry *entry = &parms.keystroke_specifier.keystroke_entry;
268:
269: if (AcceptKeystroke(entry->scancode, entry->shift_state) == 0) {
270: parms.rc = 0x10; /* XXX needs 0x12 too! */
271: }
272: parms.number_of_keys_sent++;
273: } else if (parms.options == OPTION_MULTIPLE_KEYSTROKES) {
274: KeystrokeList
275: list,
276: far *atlist = parms.keystroke_specifier.keystroke_list;
277: KeystrokeEntry
278: entry[10], /* 10 at a time */
279: *ourentry,
280: far *theirentry;
281: int
282: todo;
283:
284: movetous((char *)&list, FP_SEG(atlist),
285: FP_OFF(atlist), sizeof *atlist);
286: todo = list.length/2;
287: ourentry = entry+(highestof(entry)+1);
288:
289: while (todo) {
290: if (ourentry > &entry[highestof(entry)]) {
291: int thistime;
292:
293: thistime = todo;
294: if (thistime > numberof(entry)) {
295: thistime = numberof(entry);
296: }
297: movetous((char *)entry, FP_SEG(theirentry),
298: FP_OFF(theirentry), thistime*sizeof *theirentry);
299: theirentry += thistime;
300: ourentry = entry;
301: }
302: if (AcceptKeystroke(ourentry->scancode,
303: ourentry->shift_state) == 0) {
304: parms.rc = 0x10; /* XXX needs 0x12 too! */
305: break;
306: }
307: parms.number_of_keys_sent++;
308: ourentry++;
309: todo--;
310: }
311: } else {
312: parms.rc = 0x01;
313: }
314: }
315: parms.function_id = 0x62;
316:
317: movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
318: /* XXX */
319: }
320:
321:
322: static void
323: disable_input(regs, sregs)
324: union REGS *regs;
325: struct SREGS *sregs;
326: {
327: DisableInputParms parms;
328:
329: movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
330:
331: if ((parms.rc != 0) || (parms.function_id != 0)) {
332: parms.rc = 0x0c;
333: } else if (parms.session_id != 23) {
334: parms.rc = 0x02;
335: } else if (parms.connectors_task_id != 0) {
336: parms.rc = 0x04;
337: } else {
338: SetOiaApiInhibit(&OperatorInformationArea);
339: parms.rc = 0;
340: }
341: parms.function_id = 0x62;
342:
343: movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
344: }
345:
346: static void
347: enable_input(regs, sregs)
348: union REGS *regs;
349: struct SREGS *sregs;
350: {
351: EnableInputParms parms;
352:
353: movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
354:
355: if ((parms.rc != 0) || (parms.function_id != 0)) {
356: parms.rc = 0x0c;
357: } else if (parms.session_id != 23) {
358: parms.rc = 0x02;
359: } else if (parms.connectors_task_id != 0) {
360: parms.rc = 0x04;
361: } else {
362: ResetOiaApiInhibit(&OperatorInformationArea);
363: parms.rc = 0;
364: }
365: parms.function_id = 0x62;
366:
367: movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
368: }
369:
370: /*
371: * Copy Services.
372: */
373:
374: static
375: copy_subroutine(target, source, parms, what_is_user, length)
376: BufferDescriptor *target, *source;
377: CopyStringParms *parms;
378: int what_is_user;
379: #define USER_IS_TARGET 0
380: #define USER_IS_SOURCE 1
381: {
382: #define TARGET_NO_EAB 1
383: #define SOURCE_NO_EAB 2
384: #define TARGET_PC 4
385: #define SOURCE_PC 8
386: #define NO_FIELD_ATTRIBUTES 16
387: int needtodo = 0;
388: int access_length;
389: char far *input;
390: char far *output;
391: char far *access_pointer;
392:
393: if ((target->characteristics^source->characteristics)
394: &CHARACTERISTIC_EAB) {
395: if (target->characteristics&CHARACTERISTIC_EAB) {
396: needtodo |= TARGET_NO_EAB; /* Need to bump for EAB in target */
397: } else {
398: needtodo |= SOURCE_NO_EAB; /* Need to bump for EAB in source */
399: }
400: }
401: if (target->session_type != source->session_type) {
402: if (target->session_type == TYPE_PC) {
403: needtodo |= TARGET_PC; /* scan codes to PC */
404: } else {
405: needtodo |= SOURCE_PC; /* PC to scan codes */
406: }
407: }
408: if ((parms->copy_mode©_MODE_FIELD_ATTRIBUTES) == 0) {
409: needtodo |= NO_FIELD_ATTRIBUTES;
410: }
411: access_length = length;
412: if (what_is_user == USER_IS_TARGET) {
413: if (target->characteristics&CHARACTERISTIC_EAB) {
414: access_length *= 2;
415: }
416: input = (char far *) &Host[source->begin];
417: access_pointer = target->buffer;
418: output = access_api(target->buffer, access_length, 0);
419: } else {
420: if (source->characteristics&CHARACTERISTIC_EAB) {
421: access_length *= 2;
422: }
423: access_pointer = source->buffer;
424: input = access_api(source->buffer, access_length, 1);
425: output = (char far *) &Host[target->begin];
426: }
427: while (length--) {
428: if (needtodo&TARGET_PC) {
429: *output++ = disp_asc[*input++];
430: } else if (needtodo&SOURCE_PC) {
431: *output++ = asc_disp[*input++];
432: } else {
433: *output++ = *input++;
434: }
435: if (needtodo&TARGET_NO_EAB) {
436: *input++;
437: } else if (needtodo&SOURCE_NO_EAB) {
438: *output++ = 0; /* Should figure out good EAB? */
439: }
440: }
441: if (what_is_user == USER_IS_TARGET) {
442: unaccess_api(target->buffer, access_pointer, access_length, 1);
443: } else {
444: unaccess_api(source->buffer, access_pointer, access_length, 0);
445: }
446: }
447:
448:
449: static void
450: copy_string(regs, sregs)
451: union REGS *regs;
452: struct SREGS *sregs;
453: {
454: CopyStringParms parms;
455: BufferDescriptor *target = &parms.target, *source = &parms.source;
456: int length;
457:
458: movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
459:
460: length = 1+parms.source_end-source->begin;
461: if ((parms.rc != 0) || (parms.function_id !=0)) {
462: parms.rc = 0x0c;
463: } else if (target->session_id == 0) { /* Target is buffer */
464: if (source->session_id != 23) { /* A no-no */
465: parms.rc = 0x2;
466: } else {
467: if ((source->begin < 0) || (source->begin > highestof(Host))) {
468: parms.rc = 0x06; /* invalid source definition */
469: } else {
470: if ((source->begin+length) > highestof(Host)) {
471: length = highestof(Host)-source->begin;
472: parms.rc = 0x0f; /* Truncate */
473: }
474: if ((source->characteristics == target->characteristics) &&
475: (source->session_type == target->session_type)) {
476: if (source->characteristics&CHARACTERISTIC_EAB) {
477: length *= 2;
478: }
479: movetothem( (int) FP_SEG(target->buffer),
480: (int) FP_OFF(target->buffer),
481: (char *)&Host[source->begin], length);
482: } else {
483: copy_subroutine(target, source, &parms,
484: USER_IS_TARGET, length);
485: }
486: }
487: }
488: } else if (source->session_id != 0) {
489: parms.rc = 0xd;
490: } else {
491: if ((target->begin < 0) || (source->begin > highestof(Host))) {
492: parms.rc = 0x07; /* invalid source definition */
493: } else {
494: if ((source->begin+length) > highestof(Host)) {
495: length = highestof(Host)-source->begin;
496: parms.rc = 0x0f; /* Truncate */
497: }
498: if ((source->characteristics == target->characteristics) &&
499: (source->session_type == target->session_type)) {
500: if (source->characteristics&CHARACTERISTIC_EAB) {
501: length *= 2;
502: }
503: movetous((char *)&Host[target->begin],
504: (int) FP_SEG(source->buffer),
505: (int) FP_OFF(source->buffer), length);
506: } else {
507: copy_subroutine(target, source, &parms, USER_IS_SOURCE, length);
508: }
509: }
510: }
511: movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
512: }
513: /*
514: * Operator Information Area Services.
515: */
516:
517: static void
518: read_oia_group(regs, sregs)
519: union REGS *regs;
520: struct SREGS *sregs;
521: {
522: ReadOiaGroupParms parms;
523:
524: movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
525:
526: if ((parms.rc != 0) || (parms.function_id != 0)) {
527: parms.rc = 0x0c;
528: } else if (parms.session_id != 23) {
529: parms.rc = 0x02;
530: } else {
531: int group = parms.oia_group_number;
532: char *from;
533: int size;
534:
535: if ((group != API_OIA_ALL_GROUPS) &&
536: ((group > API_OIA_LAST_LEGAL_GROUP) || (group < 0))) {
537: } else {
538: if (group == API_OIA_ALL_GROUPS) {
539: size = API_OIA_BYTES_ALL_GROUPS;
540: from = (char *)&OperatorInformationArea;
541: } else if (group == API_OIA_INPUT_INHIBITED) {
542: size = sizeof OperatorInformationArea.input_inhibited;
543: from = (char *)&OperatorInformationArea.input_inhibited[0];
544: } else {
545: size = 1;
546: from = ((char *)&OperatorInformationArea)+group;
547: }
548: movetothem(FP_SEG(parms.oia_buffer), FP_OFF(parms.oia_buffer),
549: from, size);
550: }
551: }
552: parms.function_id = 0x6d;
553: movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
554: }
555:
556: static void
557: unknown_op(regs, sregs)
558: union REGS *regs;
559: struct SREGS *sregs;
560: {
561: regs->h.ch = 0x12;
562: regs->h.cl = 0x05;
563: }
564:
565:
566: handle_api(regs, sregs)
567: union REGS *regs;
568: struct SREGS *sregs;
569: {
570: if (regs->h.ah == NAME_RESOLUTION) {
571: name_resolution(regs, sregs);
572: #if defined(unix)
573: } else if (regs->h.ah == PS_OR_OIA_MODIFIED) {
574: while ((oia_modified == 0) && (ps_modified == 0)) {
575: (void) Scheduler(1);
576: }
577: oia_modified = ps_modified = 0;
578: #endif /* defined(unix) */
579: } else if (regs->h.ah != 0x09) {
580: regs->h.ch = 0x12;
581: regs->h.cl = 0x0f; /* XXX Invalid environmental access */
582: } else if (regs->x.bx != 0x8020) {
583: regs->h.ch = 0x12;
584: regs->h.cl = 0x08; /* XXX Invalid wait specified */
585: } else if (regs->h.ch != 0) {
586: regs->x.cx = 0x1206; /* XXX Invalid priority */
587: } else {
588: switch (regs->x.dx) {
589: case GATE_SESSMGR:
590: switch (regs->h.al) {
591: case QUERY_SESSION_ID:
592: if (regs->h.cl != 0) {
593: regs->x.cx = 0x1206;
594: } else {
595: regs->x.cx = 0x1200;
596: query_session_id(regs, sregs);
597: }
598: break;
599: case QUERY_SESSION_PARAMETERS:
600: if (regs->h.cl != 0) {
601: regs->x.cx = 0x1206;
602: } else {
603: regs->x.cx = 0x1200;
604: query_session_parameters(regs, sregs);
605: }
606: break;
607: case QUERY_SESSION_CURSOR:
608: if (regs->h.cl != 0xff) {
609: regs->x.cx = 0x1206;
610: } else {
611: regs->x.cx = 0x1200;
612: query_session_cursor(regs, sregs);
613: }
614: break;
615: default:
616: unknown_op(regs, sregs);
617: break;
618: }
619: break;
620: case GATE_KEYBOARD:
621: if (regs->h.cl != 00) {
622: regs->x.cx = 0x1206;
623: } else {
624: regs->x.cx = 0x1200;
625: switch (regs->h.al) {
626: case CONNECT_TO_KEYBOARD:
627: connect_to_keyboard(regs, sregs);
628: break;
629: case DISABLE_INPUT:
630: disable_input(regs, sregs);
631: break;
632: case WRITE_KEYSTROKE:
633: write_keystroke(regs, sregs);
634: break;
635: case ENABLE_INPUT:
636: enable_input(regs, sregs);
637: break;
638: case DISCONNECT_FROM_KEYBOARD:
639: disconnect_from_keyboard(regs, sregs);
640: break;
641: default:
642: unknown_op(regs, sregs);
643: break;
644: }
645: }
646: break;
647: case GATE_COPY:
648: if (regs->h.cl != 0xff) {
649: regs->x.cx = 0x1206;
650: } else {
651: regs->x.cx = 0x1200;
652: switch (regs->h.al) {
653: case COPY_STRING:
654: copy_string(regs, sregs);
655: break;
656: default:
657: unknown_op(regs, sregs);
658: break;
659: }
660: }
661: break;
662: case GATE_OIAM:
663: if (regs->h.cl != 0xff) {
664: regs->x.cx = 0x1206;
665: } else {
666: regs->x.cx = 0x1200;
667: switch (regs->h.al) {
668: case READ_OIA_GROUP:
669: read_oia_group(regs, sregs);
670: break;
671: default:
672: unknown_op(regs, sregs);
673: break;
674: }
675: }
676: break;
677: default:
678: regs->h.ch = 0x12;
679: regs->h.cl = 0x34; /* Invalid GATE entry */
680: break;
681: }
682: }
683: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.