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