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