Fix bug where, on an unformatted screen, we were changing the
[unix-history] / usr / src / usr.bin / tn3270 / ctlr / api.c
index f7f6186..79d4b61 100644 (file)
@@ -1,3 +1,28 @@
+/*
+ *     Copyright (c) 1984-1987 by the Regents of the
+ *     University of California and by Gregory Glenn Minshall.
+ *
+ *     Permission to use, copy, modify, and distribute these
+ *     programs and their documentation for any purpose and
+ *     without fee is hereby granted, provided that this
+ *     copyright and permission appear on all copies and
+ *     supporting documentation, the name of the Regents of
+ *     the University of California not be used in advertising
+ *     or publicity pertaining to distribution of the programs
+ *     without specific prior permission, and notice be given in
+ *     supporting documentation that copying and distribution is
+ *     by permission of the Regents of the University of California
+ *     and by Gregory Glenn Minshall.  Neither the Regents of the
+ *     University of California nor Gregory Glenn Minshall make
+ *     representations about the suitability of this software
+ *     for any purpose.  It is provided "as is" without
+ *     express or implied warranty.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)api.c      3.1 (Berkeley) %G%";
+#endif /* not lint */
+
 /*
  * This file implements the API used in the PC version.
  */
 /*
  * This file implements the API used in the PC version.
  */
 #include "api.h"
 #include "../general/general.h"
 
 #include "api.h"
 #include "../general/general.h"
 
-#include "../ctlr/screen.h"
-#include "../ctlr/oia.h"
+#include "../api/disp_asc.h"
 
 
-#include "../general/globals.h"
+#include "screen.h"
+#include "oia.h"
 
 
-int ApiDisableInput = 0;
+#include "../general/globals.h"
 
 /*
  * General utility routines.
  */
 
 #if    defined(MSDOS)
 
 /*
  * General utility routines.
  */
 
 #if    defined(MSDOS)
-static int ourds = 0;          /* Safe */
+
+#if    defined(LINT_ARGS)
+static void movetous(char *, int, int, int);
+static void movetothem(int, int, char *, int);
+#endif /* defined(LINT_ARGS) */
+
+#define        access_api(foo,length,copyin)   (foo)
+#define        unaccess_api(foo,goo,length,copyout)
 
 static void
 movetous(parms, es, di, length)
 char *parms;
 
 static void
 movetous(parms, es, di, length)
 char *parms;
+int es, di, length;
 {
 {
-    if (ourds == 0) {
-       struct SREGS sregs;
+    char far *farparms = parms;
 
 
-       segread(&sregs);
-       ourds = sregs.ds;
-    }
-    movedata(es, di, ourds, (int)parms, length);
+    movedata(es, di, (int) FP_SEG(farparms), (int) FP_OFF(farparms), length);
 }
 
 static void
 }
 
 static void
-movetothem(parms, es, di, length)
+movetothem(es, di, parms, length)
+int es, di;
+char *parms;
+int length;
 {
 {
-    if (ourds == 0) {
-       struct SREGS sregs;
+    char far *farparms = parms;
 
 
-       segread(&sregs);
-       ourds = sregs.es;
-    }
-    movedata(ourds, (int)parms, es, di, length);
+    movedata((int) FP_SEG(farparms), (int) FP_OFF(farparms), es, di, length);
 }
 #endif /* defined(MSDOS) */
 
 }
 #endif /* defined(MSDOS) */
 
-/* No Unix version yet... */
+#if    defined(unix)
+extern char *access_api(), *unaccess_api();
+#endif /* defined(unix) */
 
 
 /*
 
 
 /*
@@ -93,14 +123,12 @@ struct SREGS *sregs;
 
     movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
 
 
     movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
 
-    if (parms.rc != 0) {
-       regs->h.cl = 0x0c;
-       return;
-    }
-    if (parms.option_code != 0x01) {
-       regs->h.cl = 0x0d;      /* Invalid option code */
+    if ((parms.rc != 0) || (parms.function_id != 0)) {
+       parms.rc = 0x0c;
+    } else if (parms.option_code != 0x01) {
+       parms.rc = 0x0d;        /* Invalid option code */
     } else if (parms.data_code != 0x45) {
     } else if (parms.data_code != 0x45) {
-       regs->h.cl = 0x0b;
+       parms.rc = 0x0b;
     } else {
        NameArray list;
        NameArrayElement element;
     } else {
        NameArray list;
        NameArrayElement element;
@@ -109,7 +137,6 @@ struct SREGS *sregs;
                            FP_OFF(parms.name_array), sizeof list);
        if ((list.length < 14) || (list.length > 170)) {
            parms.rc = 0x12;
                            FP_OFF(parms.name_array), sizeof list);
        if ((list.length < 14) || (list.length > 170)) {
            parms.rc = 0x12;
-           regs->h.cl = 0x12;
        } else {
            list.number_matching_session = 1;
            list.name_array_element.short_name = parms.data_code;
        } else {
            list.number_matching_session = 1;
            list.name_array_element.short_name = parms.data_code;
@@ -120,10 +147,9 @@ struct SREGS *sregs;
            movetothem(FP_SEG(parms.name_array),
                FP_OFF(parms.name_array), (char *)&list, sizeof list);
            parms.rc = 0;
            movetothem(FP_SEG(parms.name_array),
                FP_OFF(parms.name_array), (char *)&list, sizeof list);
            parms.rc = 0;
-           regs->h.cl = 0;
        }
     }
        }
     }
-    parms.function_id = 0x6d;
+    parms.function_id = 0x6b;
     movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
 }
 
     movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
 }
 
@@ -137,20 +163,18 @@ struct SREGS *sregs;
     movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
 
     if ((parms.rc !=0) || (parms.function_id != 0)) {
     movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
 
     if ((parms.rc !=0) || (parms.function_id != 0)) {
-       regs->h.cl = 0x0c;
-       return;
-    }
-    if (parms.session_id != 23) {
-       regs->h.cl = parms.rc = 0x02;
+       parms.rc = 0x0c;
+    } else if (parms.session_id != 23) {
+       parms.rc = 0x02;
     } else {
     } else {
-       regs->h.cl = parms.rc = 0;
-       parms.function_id = 0x6b;
+       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.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);
 }
 
     movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
 }
 
@@ -169,13 +193,13 @@ struct SREGS *sregs;
        parms.rc = 0x02;
     } else {
        parms.rc = 0;
        parms.rc = 0x02;
     } else {
        parms.rc = 0;
-       parms.function_id = 0x6b;
        parms.cursor_type = CURSOR_BLINKING;    /* XXX what is inhibited? */
        parms.row_address = ScreenLine(CursorAddress);
        parms.column_address = ScreenLineOffset(CursorAddress);
     }
 
        parms.cursor_type = CURSOR_BLINKING;    /* XXX what is inhibited? */
        parms.row_address = ScreenLine(CursorAddress);
        parms.column_address = ScreenLineOffset(CursorAddress);
     }
 
-    movetothem(sregs->es, regs->x.di, sizeof parms);
+    parms.function_id = 0x6b;
+    movetothem(sregs->es, regs->x.di, (char *) &parms, sizeof parms);
 }
 
 /*
 }
 
 /*
@@ -235,6 +259,71 @@ write_keystroke(regs, sregs)
 union REGS *regs;
 struct SREGS *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 != 23) {
+       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);
+
+           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 */
 }
 
 /* XXX */
 }
 
@@ -255,7 +344,7 @@ struct SREGS *sregs;
     } else if (parms.connectors_task_id != 0) {
        parms.rc = 0x04;
     } else {
     } else if (parms.connectors_task_id != 0) {
        parms.rc = 0x04;
     } else {
-       ApiDisableInput = 1;
+       SetOiaApiInhibit(&OperatorInformationArea);
        parms.rc = 0;
     }
     parms.function_id = 0x62;
        parms.rc = 0;
     }
     parms.function_id = 0x62;
@@ -279,7 +368,7 @@ struct SREGS *sregs;
     } else if (parms.connectors_task_id != 0) {
        parms.rc = 0x04;
     } else {
     } else if (parms.connectors_task_id != 0) {
        parms.rc = 0x04;
     } else {
-       ApiDisableInput = 0;
+       ResetOiaApiInhibit(&OperatorInformationArea);
        parms.rc = 0;
     }
     parms.function_id = 0x62;
        parms.rc = 0;
     }
     parms.function_id = 0x62;
@@ -291,20 +380,143 @@ struct SREGS *sregs;
  * Copy Services.
  */
 
  * Copy Services.
  */
 
+static
+copy_subroutine(target, source, parms, what_is_user, length)
+BufferDescriptor *target, *source;
+CopyStringParms *parms;
+int what_is_user;
+#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;
+    char far *input;
+    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&COPY_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;
+       }
+       input = (char far *) &Host[source->begin];
+       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;
+       input = access_api(source->buffer, access_length, 1);
+       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) {
+           *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;
 static void
 copy_string(regs, sregs)
 union REGS *regs;
 struct SREGS *sregs;
 {
     CopyStringParms parms;
-    BufferDescriptor *target, *source;
+    BufferDescriptor *target = &parms.target, *source = &parms.source;
+    int length;
 
     movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
 
 
     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;
     if ((parms.rc != 0) || (parms.function_id !=0)) {
        parms.rc = 0x0c;
+    } else if (target->session_id == 0) {      /* Target is buffer */
+       if (source->session_id != 23) {         /* 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( (int) FP_SEG(target->buffer),
+                           (int) FP_OFF(target->buffer),
+                           (char *)&Host[source->begin], length);
+               } else {
+                   copy_subroutine(target, source, &parms,
+                                                       USER_IS_TARGET, length);
+               }
+           }
+       }
+    } else if (source->session_id != 0) {
+           parms.rc = 0xd;
+    } else {
+       if ((target->begin < 0) || (source->begin > highestof(Host))) {
+           parms.rc = 0x07;            /* 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;
+               }
+               movetous((char *)&Host[target->begin],
+                           (int) FP_SEG(source->buffer),
+                           (int) FP_OFF(source->buffer), length);
+           } else {
+               copy_subroutine(target, source, &parms, USER_IS_SOURCE, length);
+           }
+       }
     }
     }
-    /* XXX do something! */
     movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
 }
 /*
     movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
 }
 /*
@@ -329,7 +541,8 @@ struct SREGS *sregs;
        char *from;
        int size;
 
        char *from;
        int size;
 
-       if (group > API_OIA_LAST_LEGAL_GROUP) {
+       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;
        } else {
            if (group == API_OIA_ALL_GROUPS) {
                size = API_OIA_BYTES_ALL_GROUPS;
@@ -365,6 +578,13 @@ struct SREGS *sregs;
 {
     if (regs->h.ah == NAME_RESOLUTION) {
        name_resolution(regs, 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->h.ah != 0x09) {
        regs->h.ch = 0x12;
        regs->h.cl = 0x0f;              /* XXX Invalid environmental access */
@@ -372,27 +592,32 @@ struct SREGS *sregs;
        regs->h.ch = 0x12;
        regs->h.cl = 0x08;              /* XXX Invalid wait specified */
     } else if (regs->h.ch != 0) {
        regs->h.ch = 0x12;
        regs->h.cl = 0x08;              /* XXX Invalid wait specified */
     } else if (regs->h.ch != 0) {
-       regs->h.ch = 0x12;
-       regs->h.cl = 0x07;              /* XXX Invalid reply specified */
+       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) {
     } 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 {
                } else {
+                   regs->x.cx = 0x1200;
                    query_session_id(regs, sregs);
                }
                break;
                    query_session_id(regs, sregs);
                }
                break;
-           case QUERY_SESSION_PARMS:
+           case QUERY_SESSION_PARAMETERS:
                if (regs->h.cl != 0) {
                if (regs->h.cl != 0) {
+                   regs->x.cx = 0x1206;
                } else {
                } else {
+                   regs->x.cx = 0x1200;
                    query_session_parameters(regs, sregs);
                }
                break;
            case QUERY_SESSION_CURSOR:
                if (regs->h.cl != 0xff) {
                    query_session_parameters(regs, sregs);
                }
                break;
            case QUERY_SESSION_CURSOR:
                if (regs->h.cl != 0xff) {
+                   regs->x.cx = 0x1206;
                } else {
                } else {
+                   regs->x.cx = 0x1200;
                    query_session_cursor(regs, sregs);
                }
                break;
                    query_session_cursor(regs, sregs);
                }
                break;
@@ -403,7 +628,9 @@ struct SREGS *sregs;
            break;
        case GATE_KEYBOARD:
            if (regs->h.cl != 00) {
            break;
        case GATE_KEYBOARD:
            if (regs->h.cl != 00) {
+               regs->x.cx = 0x1206;
            } else {
            } else {
+               regs->x.cx = 0x1200;
                switch (regs->h.al) {
                case CONNECT_TO_KEYBOARD:
                    connect_to_keyboard(regs, sregs);
                switch (regs->h.al) {
                case CONNECT_TO_KEYBOARD:
                    connect_to_keyboard(regs, sregs);
@@ -428,7 +655,9 @@ struct SREGS *sregs;
            break;
        case GATE_COPY:
            if (regs->h.cl != 0xff) {
            break;
        case GATE_COPY:
            if (regs->h.cl != 0xff) {
+               regs->x.cx = 0x1206;
            } else {
            } else {
+               regs->x.cx = 0x1200;
                switch (regs->h.al) {
                case COPY_STRING:
                    copy_string(regs, sregs);
                switch (regs->h.al) {
                case COPY_STRING:
                    copy_string(regs, sregs);
@@ -441,7 +670,9 @@ struct SREGS *sregs;
            break;
        case GATE_OIAM:
            if (regs->h.cl != 0xff) {
            break;
        case GATE_OIAM:
            if (regs->h.cl != 0xff) {
+               regs->x.cx = 0x1206;
            } else {
            } else {
+               regs->x.cx = 0x1200;
                switch (regs->h.al) {
                case READ_OIA_GROUP:
                    read_oia_group(regs, sregs);
                switch (regs->h.al) {
                case READ_OIA_GROUP:
                    read_oia_group(regs, sregs);