2003-08-07 15:13:06 +04:00
|
|
|
|
/* $NetBSD: api.c,v 1.7 2003/08/07 11:16:29 agc Exp $ */
|
1997-01-09 23:18:21 +03:00
|
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
|
/*-
|
|
|
|
|
* Copyright (c) 1988 The Regents of the University of California.
|
|
|
|
|
* All rights reserved.
|
|
|
|
|
*
|
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
|
* are met:
|
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
2003-08-07 15:13:06 +04:00
|
|
|
|
* 3. Neither the name of the University nor the names of its contributors
|
1993-03-21 12:45:37 +03:00
|
|
|
|
* may be used to endorse or promote products derived from this software
|
|
|
|
|
* without specific prior written permission.
|
|
|
|
|
*
|
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
|
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
|
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
|
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
|
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
|
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
|
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
|
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
|
|
|
* SUCH DAMAGE.
|
|
|
|
|
*/
|
|
|
|
|
|
1998-03-04 16:16:04 +03:00
|
|
|
|
#include <sys/cdefs.h>
|
1993-03-21 12:45:37 +03:00
|
|
|
|
#ifndef lint
|
1998-03-04 16:16:04 +03:00
|
|
|
|
#if 0
|
|
|
|
|
static char sccsid[] = "@(#)api.c 4.5 (Berkeley) 4/26/91";
|
|
|
|
|
#else
|
2003-08-07 15:13:06 +04:00
|
|
|
|
__RCSID("$NetBSD: api.c,v 1.7 2003/08/07 11:16:29 agc Exp $");
|
1998-03-04 16:16:04 +03:00
|
|
|
|
#endif
|
1993-03-21 12:45:37 +03:00
|
|
|
|
#endif /* not lint */
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* This file implements the API used in the PC version.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
|
|
#include "api.h"
|
|
|
|
|
#include "../general/general.h"
|
|
|
|
|
|
|
|
|
|
#include "../api/disp_asc.h"
|
|
|
|
|
|
|
|
|
|
#include "screen.h"
|
|
|
|
|
#include "hostctlr.h"
|
|
|
|
|
#include "oia.h"
|
1998-03-04 16:16:04 +03:00
|
|
|
|
#include "declare.h"
|
|
|
|
|
|
|
|
|
|
#include "externs.h"
|
1993-03-21 12:45:37 +03:00
|
|
|
|
|
|
|
|
|
#include "../general/globals.h"
|
|
|
|
|
|
|
|
|
|
int apitrace = 0;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Some defines for things we use internally.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#define PS_SESSION_ID 23
|
|
|
|
|
#define BUF_SESSION_ID 0
|
|
|
|
|
|
1998-03-04 16:16:04 +03:00
|
|
|
|
|
|
|
|
|
/* api.c */
|
|
|
|
|
#if defined(MSDOS)
|
2002-06-14 03:41:15 +04:00
|
|
|
|
static void movetous(char *, int, int , int);
|
|
|
|
|
static void movetothem(int, int , char *, int);
|
1998-03-04 16:16:04 +03:00
|
|
|
|
#else
|
|
|
|
|
#include "../sys_curses/telextrn.h"
|
|
|
|
|
#endif
|
2002-06-14 03:41:15 +04:00
|
|
|
|
static void name_resolution(union REGS *, struct SREGS *);
|
|
|
|
|
static void query_session_id(union REGS *, struct SREGS *);
|
|
|
|
|
static void query_session_parameters(union REGS *, struct SREGS *);
|
|
|
|
|
static void query_session_cursor(union REGS *, struct SREGS *);
|
|
|
|
|
static void connect_to_keyboard(union REGS *, struct SREGS *);
|
|
|
|
|
static void disconnect_from_keyboard(union REGS *, struct SREGS *);
|
|
|
|
|
static void write_keystroke(union REGS *, struct SREGS *);
|
|
|
|
|
static void disable_input(union REGS *, struct SREGS *);
|
|
|
|
|
static void enable_input(union REGS *, struct SREGS *);
|
|
|
|
|
static void copy_subroutine(BufferDescriptor *, BufferDescriptor *,
|
|
|
|
|
CopyStringParms *, int, int);
|
|
|
|
|
static void copy_string(union REGS *, struct SREGS *);
|
|
|
|
|
static void read_oia_group(union REGS *, struct SREGS *);
|
|
|
|
|
static void unknown_op(union REGS *, struct SREGS *);
|
1998-03-04 16:16:04 +03:00
|
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
|
/*
|
|
|
|
|
* General utility routines.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#if defined(MSDOS)
|
|
|
|
|
|
|
|
|
|
#define access_api(foo,length,copyin) (foo)
|
|
|
|
|
#define unaccess_api(foo,goo,length,copyout)
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
movetous(parms, es, di, length)
|
|
|
|
|
char *parms;
|
|
|
|
|
int es, di;
|
|
|
|
|
int length;
|
|
|
|
|
{
|
|
|
|
|
char far *farparms = parms;
|
|
|
|
|
|
|
|
|
|
movedata(es, di, FP_SEG(farparms), FP_OFF(farparms), length);
|
|
|
|
|
if (apitrace) {
|
|
|
|
|
Dump('(', parms, length);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
movetothem(es, di, parms, length)
|
|
|
|
|
int es, di;
|
|
|
|
|
char *parms;
|
|
|
|
|
int length;
|
|
|
|
|
{
|
|
|
|
|
char far *farparms = parms;
|
|
|
|
|
|
|
|
|
|
movedata(FP_SEG(farparms), FP_OFF(farparms), es, di, length);
|
|
|
|
|
if (apitrace) {
|
|
|
|
|
Dump(')', parms, length);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif /* defined(MSDOS) */
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Supervisor Services.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
name_resolution(regs, sregs)
|
|
|
|
|
union REGS *regs;
|
|
|
|
|
struct SREGS *sregs;
|
|
|
|
|
{
|
|
|
|
|
NameResolveParms parms;
|
|
|
|
|
|
|
|
|
|
movetous((char *) &parms, sregs->es, regs->x.di, sizeof parms);
|
|
|
|
|
|
|
|
|
|
regs->h.cl = 0;
|
|
|
|
|
if (memcmp((char *)&parms, NAME_SESSMGR, sizeof parms.gate_name) == 0) {
|
|
|
|
|
regs->x.dx = GATE_SESSMGR;
|
|
|
|
|
} else if (memcmp((char *)&parms, NAME_KEYBOARD,
|
|
|
|
|
sizeof parms.gate_name) == 0) {
|
|
|
|
|
regs->x.dx = GATE_KEYBOARD;
|
|
|
|
|
} else if (memcmp((char *)&parms, NAME_COPY, sizeof parms.gate_name) == 0) {
|
|
|
|
|
regs->x.dx = GATE_COPY;
|
|
|
|
|
} else if (memcmp((char *)&parms, NAME_OIAM, sizeof parms.gate_name) == 0) {
|
|
|
|
|
regs->x.dx = GATE_OIAM;
|
|
|
|
|
} else {
|
|
|
|
|
regs->h.cl = 0x2e; /* Name not found */
|
|
|
|
|
}
|
|
|
|
|
regs->h.ch = 0x12;
|
|
|
|
|
regs->h.bh = 7;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Session Information Services.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
query_session_id(regs, sregs)
|
|
|
|
|
union REGS *regs;
|
|
|
|
|
struct SREGS *sregs;
|
|
|
|
|
{
|
|
|
|
|
QuerySessionIdParms parms;
|
|
|
|
|
|
|
|
|
|
movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
|
|
|
|
|
|
|
|
|
|
if ((parms.rc != 0) || (parms.function_id != 0)) {
|
|
|
|
|
parms.rc = 0x0c;
|
|
|
|
|
} else if (parms.option_code != 0x01) {
|
|
|
|
|
parms.rc = 0x0d; /* Invalid option code */
|
|
|
|
|
#ifdef NOTOBS
|
|
|
|
|
} else if ((parms.data_code != 0x45) && (parms.data_code != 0x00/*OBS*/)) {
|
|
|
|
|
parms.rc = 0x0b;
|
|
|
|
|
#endif /* NOTOBS */
|
|
|
|
|
} else {
|
|
|
|
|
NameArray list;
|
|
|
|
|
|
|
|
|
|
movetous((char *)&list, FP_SEG(parms.name_array),
|
|
|
|
|
FP_OFF(parms.name_array), sizeof list);
|
|
|
|
|
if ((list.length < 14) || (list.length > 170)) {
|
|
|
|
|
parms.rc = 0x12;
|
|
|
|
|
} else {
|
|
|
|
|
list.number_matching_session = 1;
|
|
|
|
|
list.name_array_element.short_name = parms.data_code;
|
|
|
|
|
list.name_array_element.type = TYPE_DFT;
|
|
|
|
|
list.name_array_element.session_id = PS_SESSION_ID;
|
|
|
|
|
memcpy(list.name_array_element.long_name, "ONLYSESS",
|
|
|
|
|
sizeof list.name_array_element.long_name);
|
|
|
|
|
movetothem(FP_SEG(parms.name_array),
|
|
|
|
|
FP_OFF(parms.name_array), (char *)&list, sizeof list);
|
|
|
|
|
parms.rc = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
parms.function_id = 0x6b;
|
|
|
|
|
movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
query_session_parameters(regs, sregs)
|
|
|
|
|
union REGS *regs;
|
|
|
|
|
struct SREGS *sregs;
|
|
|
|
|
{
|
|
|
|
|
QuerySessionParametersParms parms;
|
|
|
|
|
|
|
|
|
|
movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
|
|
|
|
|
|
|
|
|
|
if ((parms.rc !=0) || (parms.function_id != 0)) {
|
|
|
|
|
parms.rc = 0x0c;
|
|
|
|
|
} else if (parms.session_id != PS_SESSION_ID) {
|
|
|
|
|
parms.rc = 0x02;
|
|
|
|
|
} else {
|
|
|
|
|
parms.rc = 0;
|
|
|
|
|
parms.session_type = TYPE_DFT;
|
|
|
|
|
parms.session_characteristics = 0; /* Neither EAB nor PSS */
|
|
|
|
|
parms.rows = MaxNumberLines;
|
|
|
|
|
parms.columns = MaxNumberColumns;
|
|
|
|
|
parms.presentation_space = 0;
|
|
|
|
|
}
|
|
|
|
|
parms.function_id = 0x6b;
|
|
|
|
|
movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
query_session_cursor(regs, sregs)
|
|
|
|
|
union REGS *regs;
|
|
|
|
|
struct SREGS *sregs;
|
|
|
|
|
{
|
|
|
|
|
QuerySessionCursorParms parms;
|
|
|
|
|
|
|
|
|
|
movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
|
|
|
|
|
|
|
|
|
|
if ((parms.rc != 0) || (parms.function_id != 0)) {
|
|
|
|
|
parms.rc = 0x0c;
|
|
|
|
|
} else if (parms.session_id != PS_SESSION_ID) {
|
|
|
|
|
parms.rc = 0x02;
|
|
|
|
|
} else {
|
|
|
|
|
parms.rc = 0;
|
|
|
|
|
parms.cursor_type = CURSOR_BLINKING; /* XXX what is inhibited? */
|
|
|
|
|
parms.row_address = ScreenLine(CursorAddress);
|
|
|
|
|
parms.column_address = ScreenLineOffset(CursorAddress);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
parms.function_id = 0x6b;
|
|
|
|
|
movetothem(sregs->es, regs->x.di, (char *) &parms, sizeof parms);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Keyboard Services.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
connect_to_keyboard(regs, sregs)
|
|
|
|
|
union REGS *regs;
|
|
|
|
|
struct SREGS *sregs;
|
|
|
|
|
{
|
|
|
|
|
ConnectToKeyboardParms parms;
|
|
|
|
|
|
|
|
|
|
movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
|
|
|
|
|
|
|
|
|
|
if ((parms.rc != 0) || (parms.function_id != 0)) {
|
|
|
|
|
parms.rc = 0x0c;
|
|
|
|
|
} else if (parms.session_id != PS_SESSION_ID) {
|
|
|
|
|
parms.rc = 0x02;
|
|
|
|
|
} else if (parms.intercept_options != 0) {
|
|
|
|
|
parms.rc = 0x01;
|
|
|
|
|
} else {
|
|
|
|
|
parms.rc = 0;
|
|
|
|
|
parms.first_connection_identifier = 0;
|
|
|
|
|
}
|
|
|
|
|
parms.function_id = 0x62;
|
|
|
|
|
|
|
|
|
|
movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
disconnect_from_keyboard(regs, sregs)
|
|
|
|
|
union REGS *regs;
|
|
|
|
|
struct SREGS *sregs;
|
|
|
|
|
{
|
|
|
|
|
DisconnectFromKeyboardParms parms;
|
|
|
|
|
|
|
|
|
|
movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
|
|
|
|
|
|
|
|
|
|
if ((parms.rc != 0) || (parms.function_id != 0)) {
|
|
|
|
|
parms.rc = 0x0c;
|
|
|
|
|
} else if (parms.session_id != PS_SESSION_ID) {
|
|
|
|
|
parms.rc = 0x02;
|
|
|
|
|
} else if (parms.connectors_task_id != 0) {
|
|
|
|
|
parms.rc = 04; /* XXX */
|
|
|
|
|
} else {
|
|
|
|
|
parms.rc = 0;
|
|
|
|
|
}
|
|
|
|
|
parms.function_id = 0x62;
|
|
|
|
|
|
|
|
|
|
movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
write_keystroke(regs, sregs)
|
|
|
|
|
union REGS *regs;
|
|
|
|
|
struct SREGS *sregs;
|
|
|
|
|
{
|
|
|
|
|
WriteKeystrokeParms parms;
|
|
|
|
|
|
|
|
|
|
movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
|
|
|
|
|
|
|
|
|
|
if ((parms.rc != 0) || (parms.function_id != 0)) {
|
|
|
|
|
parms.rc = 0x0c;
|
|
|
|
|
} else if (parms.session_id != PS_SESSION_ID) {
|
|
|
|
|
parms.rc = 0x02;
|
|
|
|
|
} else if (parms.connectors_task_id != 0) {
|
|
|
|
|
parms.rc = 0x04;
|
|
|
|
|
} else {
|
|
|
|
|
parms.number_of_keys_sent = 0;
|
|
|
|
|
parms.rc = 0;
|
|
|
|
|
if (parms.options == OPTION_SINGLE_KEYSTROKE) {
|
|
|
|
|
KeystrokeEntry *entry = &parms.keystroke_specifier.keystroke_entry;
|
|
|
|
|
|
|
|
|
|
if (AcceptKeystroke(entry->scancode, entry->shift_state) == 0) {
|
|
|
|
|
parms.rc = 0x10; /* XXX needs 0x12 too! */
|
|
|
|
|
}
|
|
|
|
|
parms.number_of_keys_sent++;
|
|
|
|
|
} else if (parms.options == OPTION_MULTIPLE_KEYSTROKES) {
|
|
|
|
|
KeystrokeList
|
|
|
|
|
list,
|
|
|
|
|
far *atlist = parms.keystroke_specifier.keystroke_list;
|
|
|
|
|
KeystrokeEntry
|
|
|
|
|
entry[10], /* 10 at a time */
|
|
|
|
|
*ourentry,
|
|
|
|
|
far *theirentry;
|
|
|
|
|
int
|
|
|
|
|
todo;
|
|
|
|
|
|
|
|
|
|
movetous((char *)&list, FP_SEG(atlist),
|
|
|
|
|
FP_OFF(atlist), sizeof *atlist);
|
|
|
|
|
todo = list.length/2;
|
|
|
|
|
ourentry = entry+(highestof(entry)+1);
|
|
|
|
|
theirentry = &atlist->keystrokes;
|
|
|
|
|
|
|
|
|
|
while (todo) {
|
|
|
|
|
if (ourentry > &entry[highestof(entry)]) {
|
|
|
|
|
int thistime;
|
|
|
|
|
|
|
|
|
|
thistime = todo;
|
|
|
|
|
if (thistime > numberof(entry)) {
|
|
|
|
|
thistime = numberof(entry);
|
|
|
|
|
}
|
|
|
|
|
movetous((char *)entry, FP_SEG(theirentry),
|
|
|
|
|
FP_OFF(theirentry), thistime*sizeof *theirentry);
|
|
|
|
|
theirentry += thistime;
|
|
|
|
|
ourentry = entry;
|
|
|
|
|
}
|
|
|
|
|
if (AcceptKeystroke(ourentry->scancode,
|
|
|
|
|
ourentry->shift_state) == 0) {
|
|
|
|
|
parms.rc = 0x10; /* XXX needs 0x12 too! */
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
parms.number_of_keys_sent++;
|
|
|
|
|
ourentry++;
|
|
|
|
|
todo--;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
parms.rc = 0x01;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
parms.function_id = 0x62;
|
|
|
|
|
|
|
|
|
|
movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
|
|
|
|
|
/* XXX */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
disable_input(regs, sregs)
|
|
|
|
|
union REGS *regs;
|
|
|
|
|
struct SREGS *sregs;
|
|
|
|
|
{
|
|
|
|
|
DisableInputParms parms;
|
|
|
|
|
|
|
|
|
|
movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
|
|
|
|
|
|
|
|
|
|
if ((parms.rc != 0) || (parms.function_id != 0)) {
|
|
|
|
|
parms.rc = 0x0c;
|
|
|
|
|
} else if (parms.session_id != PS_SESSION_ID) {
|
|
|
|
|
parms.rc = 0x02;
|
|
|
|
|
} else if (parms.connectors_task_id != 0) {
|
|
|
|
|
parms.rc = 0x04;
|
|
|
|
|
} else {
|
|
|
|
|
SetOiaApiInhibit(&OperatorInformationArea);
|
|
|
|
|
parms.rc = 0;
|
|
|
|
|
}
|
|
|
|
|
parms.function_id = 0x62;
|
|
|
|
|
|
|
|
|
|
movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
enable_input(regs, sregs)
|
|
|
|
|
union REGS *regs;
|
|
|
|
|
struct SREGS *sregs;
|
|
|
|
|
{
|
|
|
|
|
EnableInputParms parms;
|
|
|
|
|
|
|
|
|
|
movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
|
|
|
|
|
|
|
|
|
|
if ((parms.rc != 0) || (parms.function_id != 0)) {
|
|
|
|
|
parms.rc = 0x0c;
|
|
|
|
|
} else if (parms.session_id != PS_SESSION_ID) {
|
|
|
|
|
parms.rc = 0x02;
|
|
|
|
|
} else if (parms.connectors_task_id != 0) {
|
|
|
|
|
parms.rc = 0x04;
|
|
|
|
|
} else {
|
|
|
|
|
ResetOiaApiInhibit(&OperatorInformationArea);
|
|
|
|
|
parms.rc = 0;
|
|
|
|
|
}
|
|
|
|
|
parms.function_id = 0x62;
|
|
|
|
|
|
|
|
|
|
movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Copy Services.
|
|
|
|
|
*/
|
|
|
|
|
|
1998-03-04 16:16:04 +03:00
|
|
|
|
static void
|
1993-03-21 12:45:37 +03:00
|
|
|
|
copy_subroutine(target, source, parms, what_is_user, length)
|
|
|
|
|
BufferDescriptor *target, *source;
|
|
|
|
|
CopyStringParms *parms;
|
|
|
|
|
int what_is_user;
|
1998-07-09 22:32:52 +04:00
|
|
|
|
int length;
|
1993-03-21 12:45:37 +03:00
|
|
|
|
#define USER_IS_TARGET 0
|
|
|
|
|
#define USER_IS_SOURCE 1
|
|
|
|
|
{
|
|
|
|
|
#define TARGET_NO_EAB 1
|
|
|
|
|
#define SOURCE_NO_EAB 2
|
|
|
|
|
#define TARGET_PC 4
|
|
|
|
|
#define SOURCE_PC 8
|
|
|
|
|
#define NO_FIELD_ATTRIBUTES 16
|
|
|
|
|
int needtodo = 0;
|
|
|
|
|
int access_length;
|
1998-03-04 16:16:04 +03:00
|
|
|
|
unsigned char far *input;
|
1993-03-21 12:45:37 +03:00
|
|
|
|
char far *output;
|
|
|
|
|
char far *access_pointer;
|
|
|
|
|
|
|
|
|
|
if ((target->characteristics^source->characteristics)
|
|
|
|
|
&CHARACTERISTIC_EAB) {
|
|
|
|
|
if (target->characteristics&CHARACTERISTIC_EAB) {
|
|
|
|
|
needtodo |= TARGET_NO_EAB; /* Need to bump for EAB in target */
|
|
|
|
|
} else {
|
|
|
|
|
needtodo |= SOURCE_NO_EAB; /* Need to bump for EAB in source */
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (target->session_type != source->session_type) {
|
|
|
|
|
if (target->session_type == TYPE_PC) {
|
|
|
|
|
needtodo |= TARGET_PC; /* scan codes to PC */
|
|
|
|
|
} else {
|
|
|
|
|
needtodo |= SOURCE_PC; /* PC to scan codes */
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if ((parms->copy_mode©_MODE_FIELD_ATTRIBUTES) == 0) {
|
|
|
|
|
needtodo |= NO_FIELD_ATTRIBUTES;
|
|
|
|
|
}
|
|
|
|
|
access_length = length;
|
|
|
|
|
if (what_is_user == USER_IS_TARGET) {
|
|
|
|
|
if (target->characteristics&CHARACTERISTIC_EAB) {
|
|
|
|
|
access_length *= 2;
|
|
|
|
|
}
|
1998-03-04 16:16:04 +03:00
|
|
|
|
input = (unsigned char far *) &Host[source->begin];
|
1993-03-21 12:45:37 +03:00
|
|
|
|
access_pointer = target->buffer;
|
|
|
|
|
output = access_api(target->buffer, access_length, 0);
|
|
|
|
|
} else {
|
|
|
|
|
if (source->characteristics&CHARACTERISTIC_EAB) {
|
|
|
|
|
access_length *= 2;
|
|
|
|
|
}
|
|
|
|
|
access_pointer = source->buffer;
|
1998-03-04 16:16:04 +03:00
|
|
|
|
input = (unsigned char far *)
|
|
|
|
|
access_api(source->buffer, access_length, 1);
|
1993-03-21 12:45:37 +03:00
|
|
|
|
output = (char far *) &Host[target->begin];
|
|
|
|
|
}
|
|
|
|
|
while (length--) {
|
|
|
|
|
if (needtodo&TARGET_PC) {
|
|
|
|
|
*output++ = disp_asc[*input++];
|
|
|
|
|
} else if (needtodo&SOURCE_PC) {
|
|
|
|
|
*output++ = asc_disp[*input++];
|
|
|
|
|
} else {
|
|
|
|
|
*output++ = *input++;
|
|
|
|
|
}
|
|
|
|
|
if (needtodo&TARGET_NO_EAB) {
|
1998-03-04 16:16:04 +03:00
|
|
|
|
/* XXX: So why are we doing this? (bug) */
|
1993-03-21 12:45:37 +03:00
|
|
|
|
input++;
|
|
|
|
|
} else if (needtodo&SOURCE_NO_EAB) {
|
|
|
|
|
*output++ = 0; /* Should figure out good EAB? */
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (what_is_user == USER_IS_TARGET) {
|
|
|
|
|
unaccess_api(target->buffer, access_pointer, access_length, 1);
|
|
|
|
|
} else {
|
|
|
|
|
unaccess_api(source->buffer, access_pointer, access_length, 0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
copy_string(regs, sregs)
|
|
|
|
|
union REGS *regs;
|
|
|
|
|
struct SREGS *sregs;
|
|
|
|
|
{
|
|
|
|
|
CopyStringParms parms;
|
|
|
|
|
BufferDescriptor *target = &parms.target, *source = &parms.source;
|
|
|
|
|
int length;
|
|
|
|
|
|
|
|
|
|
movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
|
|
|
|
|
|
|
|
|
|
length = 1+parms.source_end-source->begin;
|
|
|
|
|
if ((parms.rc != 0) || (parms.function_id !=0)) {
|
|
|
|
|
parms.rc = 0x0c;
|
|
|
|
|
} else if (target->session_id == BUF_SESSION_ID) { /* Target is buffer */
|
|
|
|
|
if (source->session_id != PS_SESSION_ID) { /* A no-no */
|
|
|
|
|
parms.rc = 0x2;
|
|
|
|
|
} else {
|
|
|
|
|
if ((source->begin < 0) || (source->begin > highestof(Host))) {
|
|
|
|
|
parms.rc = 0x06; /* invalid source definition */
|
|
|
|
|
} else {
|
|
|
|
|
if ((source->begin+length) > highestof(Host)) {
|
|
|
|
|
length = highestof(Host)-source->begin;
|
|
|
|
|
parms.rc = 0x0f; /* Truncate */
|
|
|
|
|
}
|
|
|
|
|
if ((source->characteristics == target->characteristics) &&
|
|
|
|
|
(source->session_type == target->session_type)) {
|
|
|
|
|
if (source->characteristics&CHARACTERISTIC_EAB) {
|
|
|
|
|
length *= 2;
|
|
|
|
|
}
|
|
|
|
|
movetothem(FP_SEG(target->buffer),
|
|
|
|
|
FP_OFF(target->buffer),
|
|
|
|
|
(char *)&Host[source->begin], length);
|
|
|
|
|
} else {
|
|
|
|
|
copy_subroutine(target, source, &parms,
|
|
|
|
|
USER_IS_TARGET, length);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else if (source->session_id != BUF_SESSION_ID) {
|
|
|
|
|
parms.rc = 0xd;
|
|
|
|
|
} else {
|
|
|
|
|
/* Send to presentation space (3270 buffer) */
|
|
|
|
|
if ((target->begin < 0) || (target->begin > highestof(Host))) {
|
|
|
|
|
parms.rc = 0x07; /* invalid target definition */
|
|
|
|
|
} if (!UnLocked) {
|
|
|
|
|
parms.rc = 0x03; /* Keyboard locked */
|
|
|
|
|
} else if (parms.copy_mode != 0) {
|
|
|
|
|
parms.rc = 0x0f; /* Copy of field attr's not allowed */
|
|
|
|
|
} else if (IsProtected(target->begin) || /* Make sure no protected */
|
|
|
|
|
(WhereAttrByte(target->begin) != /* in range */
|
|
|
|
|
WhereAttrByte(target->begin+length-1))) {
|
|
|
|
|
parms.rc = 0x0e; /* Attempt to write in protected */
|
|
|
|
|
} else {
|
|
|
|
|
if ((target->begin+length) > highestof(Host)) {
|
|
|
|
|
length = highestof(Host)-target->begin;
|
|
|
|
|
parms.rc = 0x0f; /* Truncate */
|
|
|
|
|
}
|
|
|
|
|
TurnOnMdt(target->begin); /* Things have changed */
|
|
|
|
|
if ((source->characteristics == target->characteristics) &&
|
|
|
|
|
(source->session_type == target->session_type)) {
|
|
|
|
|
if (source->characteristics&CHARACTERISTIC_EAB) {
|
|
|
|
|
length *= 2;
|
|
|
|
|
}
|
|
|
|
|
movetous((char *)&Host[target->begin],
|
|
|
|
|
FP_SEG(source->buffer),
|
|
|
|
|
FP_OFF(source->buffer), length);
|
|
|
|
|
} else {
|
|
|
|
|
copy_subroutine(target, source, &parms, USER_IS_SOURCE, length);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
parms.function_id = 0x64;
|
|
|
|
|
movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Operator Information Area Services.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
read_oia_group(regs, sregs)
|
|
|
|
|
union REGS *regs;
|
|
|
|
|
struct SREGS *sregs;
|
|
|
|
|
{
|
|
|
|
|
ReadOiaGroupParms parms;
|
|
|
|
|
|
|
|
|
|
movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
|
|
|
|
|
|
|
|
|
|
if ((parms.rc != 0) || (parms.function_id != 0)) {
|
|
|
|
|
parms.rc = 0x0c;
|
|
|
|
|
} else if (parms.session_id != PS_SESSION_ID) {
|
|
|
|
|
parms.rc = 0x02;
|
|
|
|
|
} else {
|
|
|
|
|
int group = parms.oia_group_number;
|
|
|
|
|
char *from;
|
|
|
|
|
int size;
|
|
|
|
|
|
|
|
|
|
if ((group != API_OIA_ALL_GROUPS) &&
|
|
|
|
|
((group > API_OIA_LAST_LEGAL_GROUP) || (group < 0))) {
|
|
|
|
|
} else {
|
|
|
|
|
if (group == API_OIA_ALL_GROUPS) {
|
|
|
|
|
size = API_OIA_BYTES_ALL_GROUPS;
|
|
|
|
|
from = (char *)&OperatorInformationArea;
|
|
|
|
|
} else if (group == API_OIA_INPUT_INHIBITED) {
|
|
|
|
|
size = sizeof OperatorInformationArea.input_inhibited;
|
|
|
|
|
from = (char *)&OperatorInformationArea.input_inhibited[0];
|
|
|
|
|
} else {
|
|
|
|
|
size = 1;
|
|
|
|
|
from = ((char *)&OperatorInformationArea)+group;
|
|
|
|
|
}
|
|
|
|
|
movetothem(FP_SEG(parms.oia_buffer), FP_OFF(parms.oia_buffer),
|
|
|
|
|
from, size);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
parms.function_id = 0x6d;
|
|
|
|
|
movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*ARGSUSED*/
|
|
|
|
|
static void
|
|
|
|
|
unknown_op(regs, sregs)
|
|
|
|
|
union REGS *regs;
|
|
|
|
|
struct SREGS *sregs;
|
|
|
|
|
{
|
|
|
|
|
regs->h.ch = 0x12;
|
|
|
|
|
regs->h.cl = 0x05;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
1998-03-04 16:16:04 +03:00
|
|
|
|
void
|
1993-03-21 12:45:37 +03:00
|
|
|
|
handle_api(regs, sregs)
|
|
|
|
|
union REGS *regs;
|
|
|
|
|
struct SREGS *sregs;
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* Do we need to log this transaction?
|
|
|
|
|
*/
|
|
|
|
|
if (apitrace) {
|
|
|
|
|
Dump('<', (char *)regs, sizeof *regs);
|
|
|
|
|
Dump('<', (char *)sregs, sizeof *sregs);
|
|
|
|
|
}
|
|
|
|
|
if (regs->h.ah == NAME_RESOLUTION) {
|
|
|
|
|
name_resolution(regs, sregs);
|
|
|
|
|
#if defined(unix)
|
|
|
|
|
} else if (regs->h.ah == PS_OR_OIA_MODIFIED) {
|
|
|
|
|
while ((oia_modified == 0) && (ps_modified == 0)) {
|
|
|
|
|
(void) Scheduler(1);
|
|
|
|
|
}
|
|
|
|
|
oia_modified = ps_modified = 0;
|
|
|
|
|
#endif /* defined(unix) */
|
|
|
|
|
} else if (regs->h.ah != 0x09) {
|
|
|
|
|
regs->h.ch = 0x12;
|
|
|
|
|
regs->h.cl = 0x0f; /* XXX Invalid environmental access */
|
|
|
|
|
} else if (regs->x.bx != 0x8020) {
|
|
|
|
|
regs->h.ch = 0x12;
|
|
|
|
|
regs->h.cl = 0x08; /* XXX Invalid wait specified */
|
|
|
|
|
} else if (regs->h.ch != 0) {
|
|
|
|
|
regs->x.cx = 0x1206; /* XXX Invalid priority */
|
|
|
|
|
} else {
|
|
|
|
|
switch (regs->x.dx) {
|
|
|
|
|
case GATE_SESSMGR:
|
|
|
|
|
switch (regs->h.al) {
|
|
|
|
|
case QUERY_SESSION_ID:
|
|
|
|
|
if (regs->h.cl != 0) {
|
|
|
|
|
regs->x.cx = 0x1206;
|
|
|
|
|
} else {
|
|
|
|
|
regs->x.cx = 0x1200;
|
|
|
|
|
query_session_id(regs, sregs);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case QUERY_SESSION_PARAMETERS:
|
|
|
|
|
if (regs->h.cl != 0) {
|
|
|
|
|
regs->x.cx = 0x1206;
|
|
|
|
|
} else {
|
|
|
|
|
regs->x.cx = 0x1200;
|
|
|
|
|
query_session_parameters(regs, sregs);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case QUERY_SESSION_CURSOR:
|
|
|
|
|
if ((regs->h.cl != 0xff) && (regs->h.cl != 0x00/*OBS*/)) {
|
|
|
|
|
regs->x.cx = 0x1206;
|
|
|
|
|
} else {
|
|
|
|
|
regs->x.cx = 0x1200;
|
|
|
|
|
query_session_cursor(regs, sregs);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
unknown_op(regs, sregs);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case GATE_KEYBOARD:
|
|
|
|
|
if (regs->h.cl != 00) {
|
|
|
|
|
regs->x.cx = 0x1206;
|
|
|
|
|
} else {
|
|
|
|
|
regs->x.cx = 0x1200;
|
|
|
|
|
switch (regs->h.al) {
|
|
|
|
|
case CONNECT_TO_KEYBOARD:
|
|
|
|
|
connect_to_keyboard(regs, sregs);
|
|
|
|
|
break;
|
|
|
|
|
case DISABLE_INPUT:
|
|
|
|
|
disable_input(regs, sregs);
|
|
|
|
|
break;
|
|
|
|
|
case WRITE_KEYSTROKE:
|
|
|
|
|
write_keystroke(regs, sregs);
|
|
|
|
|
break;
|
|
|
|
|
case ENABLE_INPUT:
|
|
|
|
|
enable_input(regs, sregs);
|
|
|
|
|
break;
|
|
|
|
|
case DISCONNECT_FROM_KEYBOARD:
|
|
|
|
|
disconnect_from_keyboard(regs, sregs);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
unknown_op(regs, sregs);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case GATE_COPY:
|
|
|
|
|
if (regs->h.cl != 0xff) {
|
|
|
|
|
regs->x.cx = 0x1206;
|
|
|
|
|
} else {
|
|
|
|
|
regs->x.cx = 0x1200;
|
|
|
|
|
switch (regs->h.al) {
|
|
|
|
|
case COPY_STRING:
|
|
|
|
|
copy_string(regs, sregs);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
unknown_op(regs, sregs);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case GATE_OIAM:
|
|
|
|
|
if (regs->h.cl != 0xff) {
|
|
|
|
|
regs->x.cx = 0x1206;
|
|
|
|
|
} else {
|
|
|
|
|
regs->x.cx = 0x1200;
|
|
|
|
|
switch (regs->h.al) {
|
|
|
|
|
case READ_OIA_GROUP:
|
|
|
|
|
read_oia_group(regs, sregs);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
unknown_op(regs, sregs);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
regs->h.ch = 0x12;
|
|
|
|
|
regs->h.cl = 0x34; /* Invalid GATE entry */
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/*
|
|
|
|
|
* Do we need to log this transaction?
|
|
|
|
|
*/
|
|
|
|
|
if (apitrace) {
|
|
|
|
|
Dump('>', (char *)regs, sizeof *regs);
|
|
|
|
|
Dump('>', (char *)sregs, sizeof *sregs);
|
|
|
|
|
#ifdef MSDOS
|
|
|
|
|
{ char buf[10]; gets(buf); }
|
|
|
|
|
#endif /* MSDOS */
|
|
|
|
|
}
|
|
|
|
|
}
|