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) 03/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 } 684