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 "../ctlr/screen.h" 11 #include "../ctlr/oia.h" 12 13 #include "../general/globals.h" 14 15 /* 16 * General utility routines. 17 */ 18 19 #if defined(MSDOS) 20 21 #if defined(LINT_ARGS) 22 static void movetous(char *, int, int, int); 23 static void movetothem(int, int, char *, int); 24 #endif /* defined(LINT_ARGS) */ 25 26 static void 27 movetous(parms, es, di, length) 28 char *parms; 29 int es, di, length; 30 { 31 char far *farparms = parms; 32 33 movedata(es, di, (int) FP_SEG(farparms), (int) FP_OFF(farparms), length); 34 } 35 36 static void 37 movetothem(es, di, parms, length) 38 int es, di; 39 char *parms; 40 int length; 41 { 42 char far *farparms = parms; 43 44 movedata((int) FP_SEG(farparms), (int) FP_OFF(farparms), es, di, length); 45 } 46 #endif /* defined(MSDOS) */ 47 48 /* No Unix version yet... */ 49 50 51 /* 52 * Supervisor Services. 53 */ 54 55 static void 56 name_resolution(regs, sregs) 57 union REGS *regs; 58 struct SREGS *sregs; 59 { 60 NameResolveParms parms; 61 62 movetous((char *) &parms, sregs->es, regs->x.di, sizeof parms); 63 64 regs->h.cl = 0; 65 if (memcmp((char *)&parms, NAME_SESSMGR, sizeof parms.gate_name) == 0) { 66 regs->x.dx = GATE_SESSMGR; 67 } else if (memcmp((char *)&parms, NAME_KEYBOARD, 68 sizeof parms.gate_name) == 0) { 69 regs->x.dx = GATE_KEYBOARD; 70 } else if (memcmp((char *)&parms, NAME_COPY, sizeof parms.gate_name) == 0) { 71 regs->x.dx = GATE_COPY; 72 } else if (memcmp((char *)&parms, NAME_OIAM, sizeof parms.gate_name) == 0) { 73 regs->x.dx = GATE_OIAM; 74 } else { 75 regs->h.cl = 0x2e; /* Name not found */ 76 } 77 regs->h.ch = 0x12; 78 regs->h.bh = 7; 79 } 80 81 /* 82 * Session Information Services. 83 */ 84 85 static void 86 query_session_id(regs, sregs) 87 union REGS *regs; 88 struct SREGS *sregs; 89 { 90 QuerySessionIdParms parms; 91 92 movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms); 93 94 if ((parms.rc != 0) || (parms.function_id != 0)) { 95 parms.rc = 0x0c; 96 } else if (parms.option_code != 0x01) { 97 parms.rc = 0x0d; /* Invalid option code */ 98 } else if (parms.data_code != 0x45) { 99 parms.rc = 0x0b; 100 } else { 101 NameArray list; 102 NameArrayElement element; 103 104 movetous((char *)&list, FP_SEG(parms.name_array), 105 FP_OFF(parms.name_array), sizeof list); 106 if ((list.length < 14) || (list.length > 170)) { 107 parms.rc = 0x12; 108 } else { 109 list.number_matching_session = 1; 110 list.name_array_element.short_name = parms.data_code; 111 list.name_array_element.type = TYPE_DFT; 112 list.name_array_element.session_id = 23; 113 memcpy(list.name_array_element.long_name, "ONLYSESS", 114 sizeof list.name_array_element.long_name); 115 movetothem(FP_SEG(parms.name_array), 116 FP_OFF(parms.name_array), (char *)&list, sizeof list); 117 parms.rc = 0; 118 } 119 } 120 parms.function_id = 0x6b; 121 movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms); 122 } 123 124 static void 125 query_session_parameters(regs, sregs) 126 union REGS *regs; 127 struct SREGS *sregs; 128 { 129 QuerySessionParametersParms parms; 130 131 movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms); 132 133 if ((parms.rc !=0) || (parms.function_id != 0)) { 134 parms.rc = 0x0c; 135 } else if (parms.session_id != 23) { 136 parms.rc = 0x02; 137 } else { 138 parms.rc = 0; 139 parms.session_type = TYPE_DFT; 140 parms.session_characteristics = 0; /* Neither EAB nor PSS */ 141 parms.rows = MaxNumberLines; 142 parms.columns = MaxNumberColumns; 143 parms.presentation_space = 0; 144 } 145 parms.function_id = 0x6b; 146 movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms); 147 } 148 149 static void 150 query_session_cursor(regs, sregs) 151 union REGS *regs; 152 struct SREGS *sregs; 153 { 154 QuerySessionCursorParms parms; 155 156 movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms); 157 158 if ((parms.rc != 0) || (parms.function_id != 0)) { 159 parms.rc = 0x0c; 160 } else if (parms.session_id != 23) { 161 parms.rc = 0x02; 162 } else { 163 parms.rc = 0; 164 parms.cursor_type = CURSOR_BLINKING; /* XXX what is inhibited? */ 165 parms.row_address = ScreenLine(CursorAddress); 166 parms.column_address = ScreenLineOffset(CursorAddress); 167 } 168 169 parms.function_id = 0x6b; 170 movetothem(sregs->es, regs->x.di, (char *) &parms, sizeof parms); 171 } 172 173 /* 174 * Keyboard Services. 175 */ 176 177 178 static void 179 connect_to_keyboard(regs, sregs) 180 union REGS *regs; 181 struct SREGS *sregs; 182 { 183 ConnectToKeyboardParms parms; 184 185 movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms); 186 187 if ((parms.rc != 0) || (parms.function_id != 0)) { 188 parms.rc = 0x0c; 189 } else if (parms.session_id != 23) { 190 parms.rc = 0x02; 191 } else if (parms.intercept_options != 0) { 192 parms.rc = 0x01; 193 } else { 194 parms.rc = 0; 195 parms.first_connection_identifier = 0; 196 } 197 parms.function_id = 0x62; 198 199 movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms); 200 } 201 202 static void 203 disconnect_from_keyboard(regs, sregs) 204 union REGS *regs; 205 struct SREGS *sregs; 206 { 207 DisconnectFromKeyboardParms parms; 208 209 movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms); 210 211 if ((parms.rc != 0) || (parms.function_id != 0)) { 212 parms.rc = 0x0c; 213 } else if (parms.session_id != 23) { 214 parms.rc = 0x02; 215 } else if (parms.connectors_task_id != 0) { 216 parms.rc = 04; /* XXX */ 217 } else { 218 parms.rc = 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 write_keystroke(regs, sregs) 227 union REGS *regs; 228 struct SREGS *sregs; 229 { 230 WriteKeystrokeParms 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 = 0x04; 240 } else { 241 parms.number_of_keys_sent = 0; 242 parms.rc = 0; 243 if (parms.options == OPTION_SINGLE_KEYSTROKE) { 244 KeystrokeEntry *entry = &parms.keystroke_specifier.keystroke_entry; 245 246 if (AcceptKeystroke(entry->scancode, entry->shift_state) == 0) { 247 parms.rc = 0x10; /* XXX needs 0x12 too! */ 248 } 249 parms.number_of_keys_sent++; 250 } else if (parms.options == OPTION_MULTIPLE_KEYSTROKES) { 251 KeystrokeList 252 list, 253 far *atlist = parms.keystroke_specifier.keystroke_list; 254 KeystrokeEntry 255 entry[10], /* 10 at a time */ 256 *ourentry, 257 far *theirentry; 258 int 259 todo; 260 261 movetous((char *)&list, FP_SEG(atlist), 262 FP_OFF(atlist), sizeof *atlist); 263 todo = list.length/2; 264 ourentry = entry+(highestof(entry)+1); 265 266 while (todo) { 267 if (ourentry > &entry[highestof(entry)]) { 268 int thistime; 269 270 thistime = todo; 271 if (thistime > numberof(entry)) { 272 thistime = numberof(entry); 273 } 274 movetous((char *)entry, FP_SEG(theirentry), 275 FP_OFF(theirentry), thistime*sizeof *theirentry); 276 theirentry += thistime; 277 ourentry = entry; 278 } 279 if (AcceptKeystroke(ourentry->scancode, 280 ourentry->shift_state) == 0) { 281 parms.rc = 0x10; /* XXX needs 0x12 too! */ 282 break; 283 } 284 parms.number_of_keys_sent++; 285 ourentry++; 286 todo--; 287 } 288 } else { 289 parms.rc = 0x01; 290 } 291 } 292 parms.function_id = 0x62; 293 294 movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms); 295 /* XXX */ 296 } 297 298 299 static void 300 disable_input(regs, sregs) 301 union REGS *regs; 302 struct SREGS *sregs; 303 { 304 DisableInputParms parms; 305 306 movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms); 307 308 if ((parms.rc != 0) || (parms.function_id != 0)) { 309 parms.rc = 0x0c; 310 } else if (parms.session_id != 23) { 311 parms.rc = 0x02; 312 } else if (parms.connectors_task_id != 0) { 313 parms.rc = 0x04; 314 } else { 315 SetOiaApiInhibit(&OperatorInformationArea); 316 parms.rc = 0; 317 } 318 parms.function_id = 0x62; 319 320 movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms); 321 } 322 323 static void 324 enable_input(regs, sregs) 325 union REGS *regs; 326 struct SREGS *sregs; 327 { 328 EnableInputParms parms; 329 330 movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms); 331 332 if ((parms.rc != 0) || (parms.function_id != 0)) { 333 parms.rc = 0x0c; 334 } else if (parms.session_id != 23) { 335 parms.rc = 0x02; 336 } else if (parms.connectors_task_id != 0) { 337 parms.rc = 0x04; 338 } else { 339 ResetOiaApiInhibit(&OperatorInformationArea); 340 parms.rc = 0; 341 } 342 parms.function_id = 0x62; 343 344 movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms); 345 } 346 347 /* 348 * Copy Services. 349 */ 350 351 static void 352 copy_string(regs, sregs) 353 union REGS *regs; 354 struct SREGS *sregs; 355 { 356 CopyStringParms parms; 357 BufferDescriptor *target, *source; 358 359 movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms); 360 361 if ((parms.rc != 0) || (parms.function_id !=0)) { 362 parms.rc = 0x0c; 363 } 364 /* XXX do something! */ 365 movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms); 366 } 367 /* 368 * Operator Information Area Services. 369 */ 370 371 static void 372 read_oia_group(regs, sregs) 373 union REGS *regs; 374 struct SREGS *sregs; 375 { 376 ReadOiaGroupParms parms; 377 378 movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms); 379 380 if ((parms.rc != 0) || (parms.function_id != 0)) { 381 parms.rc = 0x0c; 382 } else if (parms.session_id != 23) { 383 parms.rc = 0x02; 384 } else { 385 int group = parms.oia_group_number; 386 char *from; 387 int size; 388 389 if ((group != API_OIA_ALL_GROUPS) && 390 ((group > API_OIA_LAST_LEGAL_GROUP) || (group < 0))) { 391 } else { 392 if (group == API_OIA_ALL_GROUPS) { 393 size = API_OIA_BYTES_ALL_GROUPS; 394 from = (char *)&OperatorInformationArea; 395 } else if (group == API_OIA_INPUT_INHIBITED) { 396 size = sizeof OperatorInformationArea.input_inhibited; 397 from = (char *)&OperatorInformationArea.input_inhibited[0]; 398 } else { 399 size = 1; 400 from = ((char *)&OperatorInformationArea)+group; 401 } 402 movetothem(FP_SEG(parms.oia_buffer), FP_OFF(parms.oia_buffer), 403 from, size); 404 } 405 } 406 parms.function_id = 0x6d; 407 movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms); 408 } 409 410 static void 411 unknown_op(regs, sregs) 412 union REGS *regs; 413 struct SREGS *sregs; 414 { 415 regs->h.ch = 0x12; 416 regs->h.cl = 0x05; 417 } 418 419 420 handle_api(regs, sregs) 421 union REGS *regs; 422 struct SREGS *sregs; 423 { 424 if (regs->h.ah == NAME_RESOLUTION) { 425 name_resolution(regs, sregs); 426 } else if (regs->h.ah != 0x09) { 427 regs->h.ch = 0x12; 428 regs->h.cl = 0x0f; /* XXX Invalid environmental access */ 429 } else if (regs->x.bx != 0x8020) { 430 regs->h.ch = 0x12; 431 regs->h.cl = 0x08; /* XXX Invalid wait specified */ 432 } else if (regs->h.ch != 0) { 433 regs->x.cx = 0x1206; /* XXX Invalid priority */ 434 } else { 435 switch (regs->x.dx) { 436 case GATE_SESSMGR: 437 switch (regs->h.al) { 438 case QUERY_SESSION_ID: 439 if (regs->h.cl != 0) { 440 regs->x.cx = 0x1206; 441 } else { 442 regs->x.cx = 0x1200; 443 query_session_id(regs, sregs); 444 } 445 break; 446 case QUERY_SESSION_PARAMETERS: 447 if (regs->h.cl != 0) { 448 regs->x.cx = 0x1206; 449 } else { 450 regs->x.cx = 0x1200; 451 query_session_parameters(regs, sregs); 452 } 453 break; 454 case QUERY_SESSION_CURSOR: 455 if (regs->h.cl != 0xff) { 456 regs->x.cx = 0x1206; 457 } else { 458 regs->x.cx = 0x1200; 459 query_session_cursor(regs, sregs); 460 } 461 break; 462 default: 463 unknown_op(regs, sregs); 464 break; 465 } 466 break; 467 case GATE_KEYBOARD: 468 if (regs->h.cl != 00) { 469 regs->x.cx = 0x1206; 470 } else { 471 regs->x.cx = 0x1200; 472 switch (regs->h.al) { 473 case CONNECT_TO_KEYBOARD: 474 connect_to_keyboard(regs, sregs); 475 break; 476 case DISABLE_INPUT: 477 disable_input(regs, sregs); 478 break; 479 case WRITE_KEYSTROKE: 480 write_keystroke(regs, sregs); 481 break; 482 case ENABLE_INPUT: 483 enable_input(regs, sregs); 484 break; 485 case DISCONNECT_FROM_KEYBOARD: 486 disconnect_from_keyboard(regs, sregs); 487 break; 488 default: 489 unknown_op(regs, sregs); 490 break; 491 } 492 } 493 break; 494 case GATE_COPY: 495 if (regs->h.cl != 0xff) { 496 regs->x.cx = 0x1206; 497 } else { 498 regs->x.cx = 0x1200; 499 switch (regs->h.al) { 500 case COPY_STRING: 501 copy_string(regs, sregs); 502 break; 503 default: 504 unknown_op(regs, sregs); 505 break; 506 } 507 } 508 break; 509 case GATE_OIAM: 510 if (regs->h.cl != 0xff) { 511 regs->x.cx = 0x1206; 512 } else { 513 regs->x.cx = 0x1200; 514 switch (regs->h.al) { 515 case READ_OIA_GROUP: 516 read_oia_group(regs, sregs); 517 break; 518 default: 519 unknown_op(regs, sregs); 520 break; 521 } 522 } 523 break; 524 default: 525 regs->h.ch = 0x12; 526 regs->h.cl = 0x34; /* Invalid GATE entry */ 527 break; 528 } 529 } 530 } 531