|
|
1.1 ! root 1: /******************************Module*Header*******************************\ ! 2: * Module Name: enable.c ! 3: * ! 4: * This module contains the functions that enable and disable the ! 5: * driver, the pdev, and the surface. ! 6: * ! 7: * Copyright (c) 1992 Microsoft Corporation ! 8: \**************************************************************************/ ! 9: ! 10: #include "driver.h" ! 11: ! 12: // ! 13: // Build the driver function table gadrvfn with function index/address pairs ! 14: // ! 15: ! 16: DRVFN gadrvfn[] = { ! 17: { INDEX_DrvEnablePDEV, (PFN) DrvEnablePDEV }, ! 18: { INDEX_DrvCompletePDEV, (PFN) DrvCompletePDEV }, ! 19: { INDEX_DrvDisablePDEV, (PFN) DrvDisablePDEV }, ! 20: { INDEX_DrvEnableSurface, (PFN) DrvEnableSurface }, ! 21: { INDEX_DrvDisableSurface, (PFN) DrvDisableSurface }, ! 22: { INDEX_DrvAssertMode, (PFN) DrvAssertMode }, ! 23: { INDEX_DrvGetModes, (PFN) DrvGetModes }, ! 24: { INDEX_DrvDitherColor, (PFN) DrvDitherColor }, ! 25: { INDEX_DrvSetPalette, (PFN) DrvSetPalette }, ! 26: { INDEX_DrvCopyBits, (PFN) DrvCopyBits }, ! 27: { INDEX_DrvSetPointerShape, (PFN) DrvSetPointerShape }, ! 28: { INDEX_DrvBitBlt, (PFN) DrvBitBlt }, ! 29: { INDEX_DrvTextOut, (PFN) DrvTextOut }, ! 30: { INDEX_DrvStrokePath, (PFN) DrvStrokePath }, ! 31: { INDEX_DrvFillPath, (PFN) DrvFillPath }, ! 32: { INDEX_DrvRealizeBrush, (PFN) DrvRealizeBrush }, ! 33: { INDEX_DrvStretchBlt, (PFN) DrvStretchBlt }, ! 34: { INDEX_DrvPaint, (PFN) DrvPaint } ! 35: }; ! 36: ! 37: /******************************Public*Routine******************************\ ! 38: * DrvEnableDriver ! 39: * ! 40: * Enables the driver by retrieving the drivers function table and version. ! 41: * ! 42: \**************************************************************************/ ! 43: ! 44: BOOL DrvEnableDriver( ! 45: ULONG iEngineVersion, ! 46: ULONG cj, ! 47: PDRVENABLEDATA pded) ! 48: { ! 49: UNREFERENCED_PARAMETER(iEngineVersion); ! 50: ! 51: // Engine Version is passed down so future drivers can support previous ! 52: // engine versions. A next generation driver can support both the old ! 53: // and new engine conventions if told what version of engine it is ! 54: // working with. For the first version the driver does nothing with it. ! 55: ! 56: // Fill in as much as we can. ! 57: ! 58: if (cj >= sizeof(DRVENABLEDATA)) ! 59: pded->pdrvfn = gadrvfn; ! 60: ! 61: if (cj >= (sizeof(ULONG) * 2)) ! 62: pded->c = sizeof(gadrvfn) / sizeof(DRVFN); ! 63: ! 64: // DDI version this driver was targeted for is passed back to engine. ! 65: // Future graphic's engine may break calls down to old driver format. ! 66: ! 67: if (cj >= sizeof(ULONG)) ! 68: pded->iDriverVersion = DDI_DRIVER_VERSION; ! 69: ! 70: return(TRUE); ! 71: } ! 72: ! 73: /******************************Public*Routine******************************\ ! 74: * DrvDisableDriver ! 75: * ! 76: * Tells the driver it is being disabled. Release any resources allocated in ! 77: * DrvEnableDriver. ! 78: * ! 79: \**************************************************************************/ ! 80: ! 81: VOID DrvDisableDriver(VOID) ! 82: { ! 83: return; ! 84: } ! 85: ! 86: /******************************Public*Routine******************************\ ! 87: * DrvEnablePDEV ! 88: * ! 89: * DDI function, Enables the Physical Device. ! 90: * ! 91: * Return Value: device handle to pdev. ! 92: * ! 93: \**************************************************************************/ ! 94: ! 95: DHPDEV DrvEnablePDEV( ! 96: DEVMODEW *pDevmode, // Pointer to DEVMODE ! 97: PWSTR pwszLogAddress, // Logical address ! 98: ULONG cPatterns, // number of patterns ! 99: HSURF *ahsurfPatterns, // return standard patterns ! 100: ULONG cjGdiInfo, // Length of memory pointed to by pGdiInfo ! 101: ULONG *pGdiInfo, // Pointer to GdiInfo structure ! 102: ULONG cjDevInfo, // Length of following PDEVINFO structure ! 103: DEVINFO *pDevInfo, // physical device information structure ! 104: PWSTR pwszDataFile, // DataFile - not used ! 105: PWSTR pwszDeviceName, // DeviceName - not used ! 106: HANDLE hDriver) // Handle to base driver ! 107: { ! 108: GDIINFO GdiInfo; ! 109: DEVINFO DevInfo; ! 110: PPDEV ppdev; ! 111: BYTE *pjTemp; ! 112: INT i; ! 113: ! 114: UNREFERENCED_PARAMETER(pwszLogAddress); ! 115: UNREFERENCED_PARAMETER(pwszDataFile); ! 116: UNREFERENCED_PARAMETER(pwszDeviceName); ! 117: ! 118: // Allocate a physical device structure. ! 119: ! 120: ppdev = (PPDEV) LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, sizeof(PDEV)); ! 121: ! 122: if (ppdev == (PPDEV) NULL) ! 123: { ! 124: RIP("Couldn't allocate PDEV buffer"); ! 125: goto error0; ! 126: } ! 127: ! 128: // Create the table used for flipping bits 0-3 and 4-7 when drawing text. ! 129: // This table must be aligned to a 256-byte boundary. ! 130: ppdev->pjGlyphFlipTableBase = ! 131: (BYTE *) LocalAlloc((LMEM_FIXED | LMEM_ZEROINIT), ! 132: ((256+256)*sizeof(UCHAR))); ! 133: if (ppdev->pjGlyphFlipTableBase == NULL) { ! 134: goto error01; ! 135: } ! 136: ! 137: // Round the table start up to the nearest 256 byte boundary, because the ! 138: // table must start on 256-byte boundaries for look-up reasons ! 139: ! 140: ppdev->pjGlyphFlipTable = ! 141: (BYTE *) ((ULONG) (ppdev->pjGlyphFlipTableBase + 0xFF) & ~0xFF); ! 142: ! 143: // Set the table to convert bits 76543210 to 45670123, which we need for ! 144: // drawing text in planar mode (because plane 0 is the leftmost, not ! 145: // rightmost, pixel) ! 146: ! 147: pjTemp = ppdev->pjGlyphFlipTable; ! 148: for (i=0; i<256; i++) { ! 149: *pjTemp++ = ((i & 0x80) >> 3) | ! 150: ((i & 0x40) >> 1) | ! 151: ((i & 0x20) << 1) | ! 152: ((i & 0x10) << 3) | ! 153: ((i & 0x08) >> 3) | ! 154: ((i & 0x04) >> 1) | ! 155: ((i & 0x02) << 1) | ! 156: ((i & 0x01) << 3); ! 157: } ! 158: ! 159: // Set up pointers in PDEV to temporary structures we build up to return. ! 160: ! 161: ppdev->pGdiInfo = &GdiInfo; ! 162: ppdev->pDevInfo = &DevInfo; ! 163: ! 164: // Save the screen handle in the PDEV. ! 165: ! 166: ppdev->hDriver = hDriver; ! 167: ! 168: // Get the current screen mode information. Set up device caps and devinfo. ! 169: ! 170: if (!bInitPDEV(ppdev,pDevmode)) ! 171: { ! 172: DISPDBG((0,"vga256 Couldn't initialize PDEV")); ! 173: goto error1; ! 174: } ! 175: ! 176: // Initialize palette information. ! 177: ! 178: if (!bInitPaletteInfo(ppdev)) ! 179: { ! 180: RIP("Couldn't initialize palette"); ! 181: goto error1; ! 182: } ! 183: ! 184: // Initialize device standard patterns. ! 185: ! 186: if (!bInitPatterns(ppdev, min(cPatterns, HS_DDI_MAX))) ! 187: { ! 188: RIP("Couldn't initialize patterns"); ! 189: goto error2; ! 190: } ! 191: ! 192: // Copy the devinfo into the engine buffer. ! 193: ! 194: memcpy(pDevInfo, ppdev->pDevInfo, min(sizeof(DEVINFO), cjDevInfo)); ! 195: ! 196: // Set the ahsurfPatterns array to handles each of the standard ! 197: // patterns that were just created. ! 198: ! 199: memcpy((PVOID) ahsurfPatterns, ppdev->ahbmPat, ppdev->cPatterns*sizeof(HBITMAP)); ! 200: ! 201: // Set the pdevCaps with GdiInfo we have prepared to the list of caps for this ! 202: // pdev. ! 203: ! 204: memcpy(pGdiInfo, ppdev->pGdiInfo, min(cjGdiInfo, sizeof(GDIINFO))); ! 205: ! 206: // Set NULL into pointers for stack allocated memory. ! 207: ! 208: ppdev->pGdiInfo = (GDIINFO *) NULL; ! 209: ppdev->pDevInfo = (DEVINFO *) NULL; ! 210: ! 211: // Create a clip object we can use when we're given a NULL clip object: ! 212: ! 213: ppdev->pcoNull = EngCreateClip(); ! 214: if (ppdev->pcoNull == NULL) ! 215: { ! 216: RIP("Couldn't create clip"); ! 217: goto error2; ! 218: } ! 219: ! 220: ppdev->pdda = EngCreateDDA(); ! 221: if (ppdev->pdda == NULL) ! 222: { ! 223: RIP("Couldn't create DDA object"); ! 224: goto error3; ! 225: } ! 226: ! 227: ppdev->pcoNull->iDComplexity = DC_RECT; ! 228: ppdev->pcoNull->rclBounds.left = 0; ! 229: ppdev->pcoNull->rclBounds.top = 0; ! 230: ppdev->pcoNull->rclBounds.right = ppdev->cxScreen; ! 231: ppdev->pcoNull->rclBounds.bottom = ppdev->cyScreen; ! 232: ppdev->pcoNull->fjOptions = OC_BANK_CLIP; ! 233: ! 234: // pvSaveScan0 is non-NULL only when enumerating banks: ! 235: ! 236: ppdev->pvSaveScan0 = NULL; ! 237: ! 238: // We're all done: ! 239: ! 240: return((DHPDEV) ppdev); ! 241: ! 242: error3: ! 243: EngDeleteDDA(ppdev->pdda); ! 244: ! 245: error2: ! 246: vDisablePatterns(ppdev); ! 247: vDisablePalette(ppdev); ! 248: ! 249: error1: ! 250: LocalFree(ppdev->pjGlyphFlipTable); ! 251: ! 252: error01: ! 253: LocalFree(ppdev); ! 254: ! 255: error0: ! 256: return((DHPDEV) 0); ! 257: } ! 258: ! 259: /******************************Public*Routine******************************\ ! 260: * DrvCompletePDEV ! 261: * ! 262: * Store the HPDEV, the engines handle for this PDEV, in the DHPDEV. ! 263: * ! 264: \**************************************************************************/ ! 265: ! 266: VOID DrvCompletePDEV( ! 267: DHPDEV dhpdev, ! 268: HDEV hdev) ! 269: { ! 270: ((PPDEV) dhpdev)->hdevEng = hdev; ! 271: } ! 272: ! 273: /******************************Public*Routine******************************\ ! 274: * DrvDisablePDEV ! 275: * ! 276: * Release the resources allocated in DrvEnablePDEV. If a surface has been ! 277: * enabled DrvDisableSurface will have already been called. ! 278: * ! 279: \**************************************************************************/ ! 280: ! 281: VOID DrvDisablePDEV( ! 282: DHPDEV dhpdev) ! 283: { ! 284: PPDEV ppdev = (PPDEV) dhpdev; ! 285: ! 286: EngUnlockSurface(ppdev->psoTmp); ! 287: EngDeleteSurface((HSURF) ppdev->hbmTmp); ! 288: LocalFree(ppdev->pvTmp); ! 289: EngDeleteClip(ppdev->pcoNull); ! 290: EngDeleteDDA(ppdev->pdda); ! 291: vDisablePalette(ppdev); ! 292: vDisablePatterns(ppdev); ! 293: LocalFree(ppdev->pjGlyphFlipTable); ! 294: LocalFree(dhpdev); ! 295: } ! 296: ! 297: /******************************Public*Routine******************************\ ! 298: * DrvEnableSurface ! 299: * ! 300: * Enable the surface for the device. Hook the calls this driver supports. ! 301: * ! 302: * Return: Handle to the surface if successful, 0 for failure. ! 303: * ! 304: \**************************************************************************/ ! 305: ! 306: HSURF DrvEnableSurface( ! 307: DHPDEV dhpdev) ! 308: { ! 309: PPDEV ppdev; ! 310: HSURF hsurf; ! 311: HSURF hsurfBm; ! 312: SIZEL sizl; ! 313: ULONG ulBitmapType; ! 314: FLONG flHooks; ! 315: ! 316: // Create engine bitmap around frame buffer. ! 317: ! 318: ppdev = (PPDEV) dhpdev; ! 319: ! 320: if (!bInitSURF(ppdev, TRUE)) ! 321: goto error0; ! 322: ! 323: if (!bInit256ColorPalette(ppdev)) ! 324: goto error0; ! 325: ! 326: sizl.cx = ppdev->cxScreen; ! 327: sizl.cy = ppdev->cyScreen; ! 328: ! 329: ulBitmapType = BMF_8BPP; ! 330: flHooks = HOOKS_BMF8BPP; ! 331: ! 332: ASSERTVGA(ppdev->ulBitCount == 8, "Can only handle 8bpp VGAs"); ! 333: ! 334: hsurfBm = (HSURF) EngCreateBitmap(sizl, ! 335: (ULONG) ppdev->lDeltaScreen, ! 336: (ULONG) (ulBitmapType), ! 337: (FLONG) (((ppdev->lDeltaScreen > 0) ! 338: ? BMF_TOPDOWN ! 339: : 0)), ! 340: (PVOID) (ppdev->pjScreen)); ! 341: if (hsurfBm == 0) ! 342: { ! 343: RIP("Couldn't create surface"); ! 344: goto error0; ! 345: } ! 346: ! 347: if (!EngAssociateSurface(hsurfBm, ppdev->hdevEng, 0)) ! 348: { ! 349: RIP("Couldn't create or associate surface"); ! 350: goto error1; ! 351: } ! 352: ! 353: ppdev->hsurfBm = hsurfBm; ! 354: ! 355: ppdev->pSurfObj = EngLockSurface(hsurfBm); ! 356: if (ppdev->pSurfObj == NULL) ! 357: { ! 358: RIP("Couldn't lock surface"); ! 359: goto error1; ! 360: } ! 361: ! 362: hsurf = EngCreateSurface((DHSURF) ppdev, sizl); ! 363: if (hsurf == 0) ! 364: { ! 365: RIP("Couldn't create surface"); ! 366: goto error2; ! 367: } ! 368: ! 369: if (!EngAssociateSurface(hsurf, ppdev->hdevEng, flHooks)) ! 370: { ! 371: RIP("Couldn't associate surface"); ! 372: goto error3; ! 373: } ! 374: ! 375: ppdev->hsurfEng = hsurf; ! 376: ! 377: // Disable all the clipping. ! 378: ! 379: if (!bEnableBanking(ppdev)) ! 380: { ! 381: RIP("Couldn't initialize banking"); ! 382: goto error3; ! 383: } ! 384: ! 385: ppdev->pvTmp = (PVOID) LocalAlloc(LMEM_FIXED, TMP_BUFFER_SIZE); ! 386: if (ppdev->pvTmp == NULL) ! 387: { ! 388: RIP("Couldn't allocate temporary buffer"); ! 389: goto error4; ! 390: } ! 391: ! 392: ASSERTVGA(ppdev->lNextScan != 0, "lNextScan shouldn't be zero"); ! 393: ! 394: sizl.cx = ppdev->lNextScan; ! 395: sizl.cy = TMP_BUFFER_SIZE / abs(ppdev->lNextScan); ! 396: ! 397: ppdev->hbmTmp = EngCreateBitmap(sizl, sizl.cx, BMF_8BPP, 0, ppdev->pvTmp); ! 398: if (ppdev->hbmTmp == (HBITMAP) 0) ! 399: { ! 400: RIP("Couldn't create temporary bitmap"); ! 401: goto error5; ! 402: } ! 403: ! 404: ppdev->psoTmp = EngLockSurface((HSURF) ppdev->hbmTmp); ! 405: if (ppdev->psoTmp == (SURFOBJ*) NULL) ! 406: { ! 407: RIP("Couldn't lock temporary surface"); ! 408: goto error6; ! 409: } ! 410: ! 411: // Attempt to initialize the brush cache; if this fails, it sets a flag in ! 412: // the PDEV instructing us to punt brush fills to the engine ! 413: vInitBrushCache(ppdev); ! 414: ! 415: return(hsurf); ! 416: ! 417: error6: ! 418: EngDeleteSurface((HSURF) ppdev->hbmTmp); ! 419: ! 420: error5: ! 421: LocalFree(ppdev->pvTmp); ! 422: ! 423: error4: ! 424: vDisableBanking(ppdev); ! 425: ! 426: error3: ! 427: EngDeleteSurface(hsurf); ! 428: ! 429: error2: ! 430: EngUnlockSurface(ppdev->pSurfObj); ! 431: ! 432: error1: ! 433: EngDeleteSurface(hsurfBm); ! 434: ! 435: error0: ! 436: return((HSURF) 0); ! 437: } ! 438: ! 439: /******************************Public*Routine******************************\ ! 440: * DrvDisableSurface ! 441: * ! 442: * Free resources allocated by DrvEnableSurface. Release the surface. ! 443: * ! 444: \**************************************************************************/ ! 445: ! 446: VOID DrvDisableSurface( ! 447: DHPDEV dhpdev) ! 448: { ! 449: PPDEV ppdev = (PPDEV) dhpdev; ! 450: ! 451: EngUnlockSurface(ppdev->psoTmp); ! 452: EngDeleteSurface((HSURF) ppdev->hbmTmp); ! 453: LocalFree(ppdev->pvTmp); ! 454: EngDeleteSurface(ppdev->hsurfEng); ! 455: vDisableSURF(ppdev); ! 456: vDisableBrushCache(ppdev); ! 457: ppdev->hsurfEng = (HSURF) 0; ! 458: vDisableBanking(ppdev); ! 459: } ! 460: ! 461: /******************************Public*Routine******************************\ ! 462: * DrvAssertMode ! 463: * ! 464: * This asks the device to reset itself to the mode of the pdev passed in. ! 465: * ! 466: \**************************************************************************/ ! 467: ! 468: VOID DrvAssertMode( ! 469: DHPDEV dhpdev, ! 470: BOOL bEnable) ! 471: { ! 472: PPDEV ppdev = (PPDEV) dhpdev; ! 473: ULONG ulReturn; ! 474: ! 475: if (bEnable) ! 476: { ! 477: // The screen must be reenabled, reinitialize the device to ! 478: // a clean state. ! 479: ! 480: bInitSURF(ppdev, FALSE); ! 481: ! 482: // Restore the off screen data. This protects the Desktop ! 483: // from a DOS application that might trash the off screen ! 484: // memory. ! 485: ! 486: // Blow away our brush cache because a full-screen app may have ! 487: // overwritten the video memory where we cache our brushes: ! 488: ! 489: vResetBrushCache(ppdev); ! 490: } ! 491: else ! 492: { ! 493: // Call the kernel driver to reset the device to a known state. ! 494: ! 495: if (!DeviceIoControl(ppdev->hDriver, ! 496: IOCTL_VIDEO_RESET_DEVICE, ! 497: NULL, ! 498: 0, ! 499: NULL, ! 500: 0, ! 501: &ulReturn, ! 502: NULL)) ! 503: { ! 504: RIP("VIDEO_RESET_DEVICE failed"); ! 505: } ! 506: } ! 507: ! 508: return; ! 509: } ! 510: ! 511: /******************************Public*Routine******************************\ ! 512: * DrvGetModes ! 513: * ! 514: * Returns the list of available modes for the device. ! 515: * ! 516: \**************************************************************************/ ! 517: ! 518: ULONG DrvGetModes( ! 519: HANDLE hDriver, ! 520: ULONG cjSize, ! 521: DEVMODEW *pdm) ! 522: ! 523: { ! 524: ! 525: DWORD cModes; ! 526: DWORD cbOutputSize; ! 527: PVIDEO_MODE_INFORMATION pVideoModeInformation, pVideoTemp; ! 528: DWORD cOutputModes = cjSize / (sizeof(DEVMODEW) + DRIVER_EXTRA_SIZE); ! 529: DWORD cbModeSize; ! 530: ! 531: DISPDBG((2, "Vga256.dll: DrvGetModes\n")); ! 532: ! 533: cModes = getAvailableModes(hDriver, ! 534: (PVIDEO_MODE_INFORMATION *) &pVideoModeInformation, ! 535: &cbModeSize); ! 536: ! 537: if (cModes == 0) ! 538: { ! 539: DISPDBG((0, "VGA256 DISP DrvGetModes failed to get mode information")); ! 540: return 0; ! 541: } ! 542: ! 543: if (pdm == NULL) ! 544: { ! 545: cbOutputSize = cModes * (sizeof(DEVMODEW) + DRIVER_EXTRA_SIZE); ! 546: } ! 547: else ! 548: { ! 549: // ! 550: // Now copy the information for the supported modes back into the output ! 551: // buffer ! 552: // ! 553: ! 554: cbOutputSize = 0; ! 555: ! 556: pVideoTemp = pVideoModeInformation; ! 557: ! 558: do ! 559: { ! 560: if (pVideoTemp->Length != 0) ! 561: { ! 562: if (cOutputModes == 0) ! 563: { ! 564: break; ! 565: } ! 566: ! 567: // ! 568: // Zero the entire structure to start off with. ! 569: // ! 570: ! 571: memset(pdm, 0, sizeof(DEVMODEW)); ! 572: ! 573: // ! 574: // Set the name of the device to the name of the DLL. ! 575: // ! 576: ! 577: memcpy(&(pdm->dmDeviceName), L"vga256", sizeof(L"vga256")); ! 578: ! 579: pdm->dmSpecVersion = DM_SPECVERSION; ! 580: pdm->dmDriverVersion = DM_SPECVERSION; ! 581: ! 582: // ! 583: // We currently do not support Extra information in the driver ! 584: // ! 585: ! 586: pdm->dmDriverExtra = DRIVER_EXTRA_SIZE; ! 587: ! 588: pdm->dmSize = sizeof(DEVMODEW); ! 589: pdm->dmBitsPerPel = pVideoTemp->NumberOfPlanes * ! 590: pVideoTemp->BitsPerPlane; ! 591: pdm->dmPelsWidth = pVideoTemp->VisScreenWidth; ! 592: pdm->dmPelsHeight = pVideoTemp->VisScreenHeight; ! 593: pdm->dmDisplayFrequency = pVideoTemp->Frequency; ! 594: ! 595: if (pVideoTemp->AttributeFlags & VIDEO_MODE_INTERLACED) ! 596: { ! 597: pdm->dmDisplayFlags |= DM_INTERLACED; ! 598: } ! 599: ! 600: // ! 601: // Go to the next DEVMODE entry in the buffer. ! 602: // ! 603: ! 604: cOutputModes--; ! 605: ! 606: pdm = (LPDEVMODEW) ( ((ULONG)pdm) + sizeof(DEVMODEW) + ! 607: DRIVER_EXTRA_SIZE); ! 608: ! 609: cbOutputSize += (sizeof(DEVMODEW) + DRIVER_EXTRA_SIZE); ! 610: ! 611: } ! 612: ! 613: pVideoTemp = (PVIDEO_MODE_INFORMATION) ! 614: (((PUCHAR)pVideoTemp) + cbModeSize); ! 615: ! 616: } while (--cModes); ! 617: } ! 618: ! 619: LocalFree(pVideoModeInformation); ! 620: ! 621: return cbOutputSize; ! 622: ! 623: } ! 624: ! 625: ! 626: /******************************Public*Routine******************************\ ! 627: * DrvSetPointerShape ! 628: * ! 629: * Sets the new pointer shape. ! 630: \**************************************************************************/ ! 631: ! 632: ULONG DrvSetPointerShape ! 633: ( ! 634: SURFOBJ *pso, ! 635: SURFOBJ *psoMask, ! 636: SURFOBJ *psoColor, ! 637: XLATEOBJ *pxlo, ! 638: LONG xHot, ! 639: LONG yHot, ! 640: LONG x, ! 641: LONG y, ! 642: RECTL *prcl, ! 643: FLONG fl ! 644: ) ! 645: { ! 646: return(SPS_DECLINE); ! 647: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.