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