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) (foo) 29 #define unaccess_api(foo,goo,length) 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 copy_subroutine(target, source, parms, what_is_user) 359 BufferDescriptor *target, *source; 360 CopyStringParms *parms; 361 int what_is_user; 362 #define USER_IS_TARGET 0 363 #define USER_IS_SOURCE 1 364 { 365 #define TARGET_NO_EAB 1 366 #define SOURCE_NO_EAB 2 367 #define TARGET_PC 4 368 #define SOURCE_PC 8 369 #define NO_FIELD_ATTRIBUTES 16 370 int needtodo = 0; 371 int length; 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 = parms->source_end-source->begin; 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); 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); 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); 427 } else { 428 unaccess_api(source->buffer, access_pointer, access_length); 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 if ((parms.rc != 0) || (parms.function_id !=0)) { 445 parms.rc = 0x0c; 446 } else if (target->session_id == 0) { /* Target is buffer */ 447 if (source->session_id != 23) { /* A no-no */ 448 parms.rc = 0x2; 449 } else { 450 if ((source->characteristics == target->characteristics) && 451 (source->session_type == target->session_type)) { 452 length = parms.source_end-source->begin; 453 if (source->characteristics&CHARACTERISTIC_EAB) { 454 length *= 2; 455 } 456 movetothem( (int) FP_SEG(target->buffer), 457 (int) FP_OFF(target->buffer), 458 (char *)&Host[source->begin], length); 459 } else { 460 copy_subroutine(target, source, &parms, USER_IS_TARGET); 461 } 462 } 463 } else if (source->session_id != 0) { 464 parms.rc = 0xd; 465 } else { 466 if ((source->characteristics == target->characteristics) && 467 (source->session_type == target->session_type)) { 468 length = parms.source_end-source->begin; 469 if (source->characteristics&CHARACTERISTIC_EAB) { 470 length *= 2; 471 } 472 movetous((char *)&Host[target->begin], 473 (int) FP_SEG(source->buffer), 474 (int) FP_OFF(source->buffer), length); 475 } else { 476 copy_subroutine(target, source, &parms, USER_IS_SOURCE); 477 } 478 } 479 movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms); 480 } 481 /* 482 * Operator Information Area Services. 483 */ 484 485 static void 486 read_oia_group(regs, sregs) 487 union REGS *regs; 488 struct SREGS *sregs; 489 { 490 ReadOiaGroupParms parms; 491 492 movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms); 493 494 if ((parms.rc != 0) || (parms.function_id != 0)) { 495 parms.rc = 0x0c; 496 } else if (parms.session_id != 23) { 497 parms.rc = 0x02; 498 } else { 499 int group = parms.oia_group_number; 500 char *from; 501 int size; 502 503 if ((group != API_OIA_ALL_GROUPS) && 504 ((group > API_OIA_LAST_LEGAL_GROUP) || (group < 0))) { 505 } else { 506 if (group == API_OIA_ALL_GROUPS) { 507 size = API_OIA_BYTES_ALL_GROUPS; 508 from = (char *)&OperatorInformationArea; 509 } else if (group == API_OIA_INPUT_INHIBITED) { 510 size = sizeof OperatorInformationArea.input_inhibited; 511 from = (char *)&OperatorInformationArea.input_inhibited[0]; 512 } else { 513 size = 1; 514 from = ((char *)&OperatorInformationArea)+group; 515 } 516 movetothem(FP_SEG(parms.oia_buffer), FP_OFF(parms.oia_buffer), 517 from, size); 518 } 519 } 520 parms.function_id = 0x6d; 521 movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms); 522 } 523 524 static void 525 unknown_op(regs, sregs) 526 union REGS *regs; 527 struct SREGS *sregs; 528 { 529 regs->h.ch = 0x12; 530 regs->h.cl = 0x05; 531 } 532 533 534 handle_api(regs, sregs) 535 union REGS *regs; 536 struct SREGS *sregs; 537 { 538 if (regs->h.ah == NAME_RESOLUTION) { 539 name_resolution(regs, sregs); 540 } else if (regs->h.ah != 0x09) { 541 regs->h.ch = 0x12; 542 regs->h.cl = 0x0f; /* XXX Invalid environmental access */ 543 } else if (regs->x.bx != 0x8020) { 544 regs->h.ch = 0x12; 545 regs->h.cl = 0x08; /* XXX Invalid wait specified */ 546 } else if (regs->h.ch != 0) { 547 regs->x.cx = 0x1206; /* XXX Invalid priority */ 548 } else { 549 switch (regs->x.dx) { 550 case GATE_SESSMGR: 551 switch (regs->h.al) { 552 case QUERY_SESSION_ID: 553 if (regs->h.cl != 0) { 554 regs->x.cx = 0x1206; 555 } else { 556 regs->x.cx = 0x1200; 557 query_session_id(regs, sregs); 558 } 559 break; 560 case QUERY_SESSION_PARAMETERS: 561 if (regs->h.cl != 0) { 562 regs->x.cx = 0x1206; 563 } else { 564 regs->x.cx = 0x1200; 565 query_session_parameters(regs, sregs); 566 } 567 break; 568 case QUERY_SESSION_CURSOR: 569 if (regs->h.cl != 0xff) { 570 regs->x.cx = 0x1206; 571 } else { 572 regs->x.cx = 0x1200; 573 query_session_cursor(regs, sregs); 574 } 575 break; 576 default: 577 unknown_op(regs, sregs); 578 break; 579 } 580 break; 581 case GATE_KEYBOARD: 582 if (regs->h.cl != 00) { 583 regs->x.cx = 0x1206; 584 } else { 585 regs->x.cx = 0x1200; 586 switch (regs->h.al) { 587 case CONNECT_TO_KEYBOARD: 588 connect_to_keyboard(regs, sregs); 589 break; 590 case DISABLE_INPUT: 591 disable_input(regs, sregs); 592 break; 593 case WRITE_KEYSTROKE: 594 write_keystroke(regs, sregs); 595 break; 596 case ENABLE_INPUT: 597 enable_input(regs, sregs); 598 break; 599 case DISCONNECT_FROM_KEYBOARD: 600 disconnect_from_keyboard(regs, sregs); 601 break; 602 default: 603 unknown_op(regs, sregs); 604 break; 605 } 606 } 607 break; 608 case GATE_COPY: 609 if (regs->h.cl != 0xff) { 610 regs->x.cx = 0x1206; 611 } else { 612 regs->x.cx = 0x1200; 613 switch (regs->h.al) { 614 case COPY_STRING: 615 copy_string(regs, sregs); 616 break; 617 default: 618 unknown_op(regs, sregs); 619 break; 620 } 621 } 622 break; 623 case GATE_OIAM: 624 if (regs->h.cl != 0xff) { 625 regs->x.cx = 0x1206; 626 } else { 627 regs->x.cx = 0x1200; 628 switch (regs->h.al) { 629 case READ_OIA_GROUP: 630 read_oia_group(regs, sregs); 631 break; 632 default: 633 unknown_op(regs, sregs); 634 break; 635 } 636 } 637 break; 638 default: 639 regs->h.ch = 0x12; 640 regs->h.cl = 0x34; /* Invalid GATE entry */ 641 break; 642 } 643 } 644 } 645