int GetCursorHeight(void) { int iAnd, iXor, dy = 16; WORD wMask[128]; ICONINFO ii; BITMAP bm; PCURSOR pcur; long lOffset = 0; if ((pcur = PtiCurrent()->pq->spcurCurrent) == NULL) { return dy; } if (!_InternalGetIconInfo(pcur, &ii, NULL, NULL, NULL, FALSE)) { return dy; } if (!GreExtGetObjectW(ii.hbmMask, sizeof(bm), (LPSTR)&bm)) { goto Bail; } /* * Use the AND mask to get the cursor height if the XOR mask is there. */ if (!GreGetBitmapBits(ii.hbmMask, sizeof(wMask), (BYTE*)wMask, &lOffset)) { goto Bail; } iAnd = (int)(bm.bmWidth * bm.bmHeight / bitsizeof(WORD)); if (ii.hbmColor == NULL) { /* * if no color (XOR) bitmap, then the hbmMask is a double height bitmap * with the cursor and the mask stacked. */ iXor = iAnd - 1; iAnd /= 2; } else { iXor = 0; } if (iAnd >= sizeof(wMask)) { iAnd = sizeof(wMask) - 1; } if (iXor >= sizeof(wMask)) { iXor = 0; } for (iAnd--; iAnd >= 0; iAnd--) { if ((iXor != 0 && wMask[iXor--] != 0) || wMask[iAnd] != 0xFFFF) { break; } } /* * Compute the distance between the pointer's lowest point and hotspot. */ dy = (iAnd + 1) * bitsizeof(WORD) / (int)bm.bmWidth - (int)ii.yHotspot; Bail: if (ii.hbmColor) { GreDeleteObject(ii.hbmColor); } if (ii.hbmMask) { GreDeleteObject(ii.hbmMask); } return dy; }
HBITMAP xxxExpandBitmap( HBITMAP hbm) { int nx; int ny; BITMAP bm; HBITMAP hbmNew; HBITMAP hbmD; LPRECT lprc; RECT rc; PMONITOR pMonitor; TL tlpMonitor; /* * Get the dimensions of the screen and bitmap we'll * be dealing with. We'll adjust the xScreen/yScreen * to reflect the new surface size. The default adjustment * is to stretch the image to fit the screen. */ GreExtGetObjectW(hbm, sizeof(bm), (PBITMAP)&bm); pMonitor = GetPrimaryMonitor(); lprc = &pMonitor->rcMonitor; nx = (lprc->right / TILE_XMINSIZE) / bm.bmWidth; ny = (lprc->bottom / TILE_YMINSIZE) / bm.bmHeight; if (nx == 0) nx++; if (ny == 0) ny++; if ((nx + ny) <= 2) return hbm; /* * Create the surface for the new-bitmap. */ rc.left = rc.top = 0; rc.right = nx * bm.bmWidth; rc.bottom = ny * bm.bmHeight; hbmD = GreSelectBitmap(ghdcMem, hbm); hbmNew = GreCreateCompatibleBitmap(ghdcMem, rc.right, rc.bottom); GreSelectBitmap(ghdcMem, hbmD); if (hbmNew == NULL) return hbm; if (hbmD = GreSelectBitmap(ghdcMem2, hbmNew)) { /* * Expand the bitmap to the new surface. */ ThreadLockAlways(pMonitor, &tlpMonitor); xxxDrawWallpaper(NULL, ghdcMem2, pMonitor, &rc); ThreadUnlock(&tlpMonitor); GreSelectBitmap(ghdcMem2, hbmD); } GreDeleteObject(hbm); GreSetBitmapOwner(hbmNew, OBJECT_OWNER_PUBLIC); return hbmNew; }
BOOL xxxLoadDesktopWallpaper( LPWSTR lpszFile) { UINT LR_flags; int dxDesired; int dyDesired; BITMAP bm; UNICODE_STRING strName; /* * If the bitmap is somewhat large (big bpp), then we'll deal * with it as a real-dib. We'll also do this for 8bpp since it * can utilize a palette. Chicago uses DIBSECTIONS since it can * count on the one-process handling the drawing. Since, NT can * have different processes doing the drawing, we can't use sections. */ LR_flags = LR_LOADFROMFILE; if (gpDispInfo->fAnyPalette || gpsi->BitCount >= 8) { LR_flags |= LR_CREATEREALDIB; } /* * If we're stretching, then we will ask the loaddib code to do * it. */ if (gwWPStyle & DTF_STRETCH) { PMONITOR pMonitor; int dxMonitor, dyMonitor; dxDesired = INT_MAX; dyDesired = INT_MAX; for ( pMonitor = gpDispInfo->pMonitorFirst; pMonitor; pMonitor = pMonitor->pMonitorNext) { if (!(pMonitor->dwMONFlags & MONF_VISIBLE)) continue; dxMonitor = pMonitor->rcMonitor.right - pMonitor->rcMonitor.left; dxDesired = min(dxDesired, dxMonitor); dyMonitor = pMonitor->rcMonitor.bottom - pMonitor->rcMonitor.top; dyDesired = min(dyDesired, dyMonitor); } } else { dxDesired = dyDesired = 0; } /* * Make a callback to the client to perform the loading. * Saves us some code. */ RtlInitUnicodeString(&strName, lpszFile); ghbmWallpaper = xxxClientLoadImage( &strName, 0, IMAGE_BITMAP, dxDesired, dyDesired, LR_flags, TRUE); if (ghbmWallpaper == NULL) return FALSE; /* * If it's a palette-display, then we will derive the global * wallpaper palette from the bitmap. */ if (gpDispInfo->fAnyPalette) { ghpalWallpaper = CreatePaletteFromBitmap(ghbmWallpaper); } /* * If the DIB is a higher bitdepth than the display, convert it to * a DDB, otherwise keep it as DIB. This way it takes the least * amount of memory and provides a identity-translation blt. * */ GreExtGetObjectW(ghbmWallpaper, sizeof(bm), &bm); if ( gpDispInfo->cMonitors == 1 && gpsi->BitCount <= bm.bmPlanes * bm.bmBitsPixel) { ghbmWallpaper = ConvertToDDB( gpDispInfo->hdcScreen, ghbmWallpaper, ghpalWallpaper); } /* * Expand bitmap if we are going to tile it. Mark the bitmap * as public, so any process can party with it. This must * preceed the expand, since it performs a xxxDrawWallpaper * call that can leave the section. */ GreSetBitmapOwner(ghbmWallpaper, OBJECT_OWNER_PUBLIC); if (gwWPStyle & DTF_TILE) { ghbmWallpaper = xxxExpandBitmap(ghbmWallpaper); } return TRUE; }
BOOL TileWallpaper(HDC hdc, LPCRECT lprc, BOOL fOffset) { int xO; int yO; int x; int y; BITMAP bm; HBITMAP hbmT = NULL; POINT ptOffset; if (fOffset) { ptOffset.x = gsrcWallpaper.x; ptOffset.y = gsrcWallpaper.y; } else { ptOffset.x = 0; ptOffset.y = 0; } /* * We need to get the dimensions of the bitmap here rather than rely on * the dimensions in srcWallpaper because this function may * be called as part of ExpandBitmap, before srcWallpaper is * set. */ if (GreExtGetObjectW(ghbmWallpaper, sizeof(BITMAP), (PBITMAP)&bm)) { xO = lprc->left - (lprc->left % bm.bmWidth) + (ptOffset.x % bm.bmWidth); if (xO > lprc->left) { xO -= bm.bmWidth; } yO = lprc->top - (lprc->top % bm.bmHeight) + (ptOffset.y % bm.bmHeight); if (yO > lprc->top) { yO -= bm.bmHeight; } /* * Tile the bitmap to the surface. */ if (hbmT = GreSelectBitmap(ghdcMem, ghbmWallpaper)) { for (y = yO; y < lprc->bottom; y += bm.bmHeight) { for (x = xO; x < lprc->right; x += bm.bmWidth) { GreBitBlt(hdc, x, y, bm.bmWidth, bm.bmHeight, ghdcMem, 0, 0, SRCCOPY, 0); } } GreSelectBitmap(ghdcMem, hbmT); } } return (hbmT != NULL); }
HBITMAP ConvertToDDB( HDC hdc, HBITMAP hbmOld, HPALETTE hpal) { BITMAP bm; HBITMAP hbmNew; /* * This object must be a REALDIB type bitmap. */ GreExtGetObjectW(hbmOld, sizeof(bm), &bm); /* * Create the new wallpaper-surface. */ if (hbmNew = GreCreateCompatibleBitmap(hdc, bm.bmWidth, bm.bmHeight)) { HPALETTE hpalDst; HPALETTE hpalSrc; HBITMAP hbmDst; HBITMAP hbmSrc; UINT bpp; BOOL fHalftone = FALSE; /* * Select in the surfaces. */ hbmDst = GreSelectBitmap(ghdcMem2, hbmNew); hbmSrc = GreSelectBitmap(ghdcMem, hbmOld); /* * Determine image bits/pixel. */ bpp = (bm.bmPlanes * bm.bmBitsPixel); /* * Use the palette if given. If the image is of a greater * resolution than the device, then we're going to go through * a halftone-palette to get better colors. */ if (hpal) { hpalDst = _SelectPalette(ghdcMem2, hpal, FALSE); hpalSrc = _SelectPalette(ghdcMem, hpal, FALSE); xxxRealizePalette(ghdcMem2); /* * Set the halftoning for the destination. This is done * for images of greater resolution than the device. */ if (bpp > gpsi->BitCount) { fHalftone = TRUE; DoHTColorAdjust(ghdcMem2); } } /* * Set the stretchbltmode. This is more necessary when doing * halftoning. Since otherwise, the colors won't translate * correctly. */ SetBestStretchMode(ghdcMem2, bpp, fHalftone); /* * Set the new surface bits. Use StretchBlt() so the SBMode * will be used in color-translation. */ GreStretchBlt(ghdcMem2, 0, 0, bm.bmWidth, bm.bmHeight, ghdcMem, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY, 0); /* * Restore palettes. */ if (hpal) { _SelectPalette(ghdcMem2, hpalDst, FALSE); _SelectPalette(ghdcMem, hpalSrc, FALSE); } /* * Restore the surfaces. */ GreSelectBitmap(ghdcMem2, hbmDst); GreSelectBitmap(ghdcMem, hbmSrc); GreDeleteObject(hbmOld); GreSetBitmapOwner(hbmNew, OBJECT_OWNER_PUBLIC); } else { hbmNew = hbmOld; } return hbmNew; }
BOOL xxxSetDeskWallpaper(PUNICODE_STRING pProfileUserName, LPWSTR lpszFile) { BITMAP bm; UINT WallpaperStyle2; PWND pwndShell; TL tl; PTHREADINFO ptiCurrent = PtiCurrent(); PDESKTOP pdesk; BOOL fRet = FALSE; HBITMAP hbmOld; PROFINTINFO apsi[] = { {PMAP_DESKTOP, (LPWSTR)STR_TILEWALL , 0, &gwWPStyle }, {PMAP_DESKTOP, (LPWSTR)STR_DTSTYLE , 0, &WallpaperStyle2 }, {PMAP_DESKTOP, (LPWSTR)STR_DTORIGINX, 0, &gsrcWallpaper.x }, {PMAP_DESKTOP, (LPWSTR)STR_DTORIGINY, 0, &gsrcWallpaper.y }, {0, NULL, 0, NULL } }; pdesk = ptiCurrent->rpdesk; hbmOld = ghbmWallpaper; /* * Get the shell-window. This could be NULL on system * initialization. We will use this to do palette realization. */ pwndShell = (pdesk ? pdesk->pDeskInfo->spwndShell : NULL); if ((lpszFile == SETWALLPAPER_METRICS) && !(gwWPStyle & DTF_STRETCH)) { gsrcWallpaper.x = 0; gsrcWallpaper.y = 0; if (ghbmWallpaper) goto CreateNewWallpaper; goto Metric_Change; } CreateNewWallpaper: /* * Delete the old wallpaper and palette if the exist. */ if (ghpalWallpaper) { GreDeleteObject(ghpalWallpaper); ghpalWallpaper = NULL; } if (ghbmWallpaper) { GreDeleteObject(ghbmWallpaper); ghbmWallpaper = NULL; } /* * Kill any SPBs no matter what. * Works if we're switching from/to palettized wallpaper. * Fixes a lot of problems because palette doesn't change, shell * paints funny on desktop, etc. */ FreeAllSpbs(); /* * If this is a metric-change (and stretched), then we need to * reload it. However, since we are called from the winlogon process * during a desktop-switch, we would be mapped to the wrong Luid * when we attempt to grab the name from GetDeskWallpaperName. This * would use the Luid from the DEFAULT user rather than the current * logged on user. In order to avoid this, we cache the wallpaer * name so that on METRIC-CHANGES we use the current-user's wallpaper. * * NOTE: we assume that prior to any METRIC change, we have already * setup the ghbmWallpaper and lpszCached. This is usually done * either on logon or during user desktop-changes through conrol-Panel. */ if (lpszFile == SETWALLPAPER_METRICS) { UserAssert(gpszWall != NULL); goto LoadWallpaper; } /* * Free the cached handle. */ if (gpszWall) { UserFreePool(gpszWall); gpszWall = NULL; } /* * Load the wallpaper-name. If this returns FALSE, then * the user specified (None). We will return true to force * the repainting of the desktop. */ gpszWall = GetDeskWallpaperName(pProfileUserName,lpszFile); if (!gpszWall) { fRet = TRUE; goto SDW_Exit; } /* * Retrieve the default settings from the registry. * * If tile is indicated, then normalize style to not include * FIT/STRETCH which are center-only styles. Likewise, if * we are centered, then normalize out the TILE bit. */ FastGetProfileIntsW(pProfileUserName, apsi); gwWPStyle &= DTF_TILE; if (!(gwWPStyle & DTF_TILE)) { gwWPStyle = WallpaperStyle2 & DTF_STRETCH; } /* * Load the wallpaper. This makes a callback to the client to * perform the bitmap-creation. */ LoadWallpaper: if (xxxLoadDesktopWallpaper(gpszWall) == FALSE) { gwWPStyle = 0; goto SDW_Exit; } /* * If we have a palette, then we need to do the correct realization and * notification. */ if (ghpalWallpaper != NULL) { PWND pwndSend; if (pwndShell) { pwndSend = pwndShell; } else { pwndSend = (pdesk ? pdesk->pDeskInfo->spwnd : NULL); } /* * Update the desktop with the new bitmap. This cleans * out the system-palette so colors can be realized. */ GreRealizeDefaultPalette(gpDispInfo->hdcScreen, TRUE); /* * Don't broadcast if system initialization is occuring. Otherwise * this gives the shell first-crack at realizing its colors * correctly. */ if (pwndSend) { HWND hwnd = HW(pwndSend); ThreadLockAlways(pwndSend, &tl); xxxSendNotifyMessage(pwndSend, WM_PALETTECHANGED, (WPARAM)hwnd, 0); ThreadUnlock(&tl); } } Metric_Change: if (fRet = GreExtGetObjectW(ghbmWallpaper, sizeof(bm), (PBITMAP)&bm)) { gsrcWallpaper.cx = bm.bmWidth; gsrcWallpaper.cy = bm.bmHeight; } // fall-through SDW_Exit: /* * Notify the shell-window that the wallpaper changed. */ if ((pwndShell != NULL) && ((hbmOld && !ghbmWallpaper) || (!hbmOld && ghbmWallpaper))) { ThreadLockAlways(pwndShell, &tl); xxxSendNotifyMessage(pwndShell, WM_SHELLNOTIFY, SHELLNOTIFY_WALLPAPERCHANGED, (LPARAM)ghbmWallpaper); ThreadUnlock(&tl); } return fRet; }
/***************************************************************************\ * xxxItemSize * * Calc the dimensions of bitmaps and strings. Loword of returned * value contains width, high word contains height of item. * * History: * 07-23-96 GerardoB - fixed up for 5.0 \***************************************************************************/ BOOL xxxMNItemSize( PMENU pMenu, PWND pwndNotify, HDC hdc, PITEM pItem, BOOL fPopup, LPPOINT lppt) { BITMAP bmp; int width = 0; int height = 0; DWORD xRightJustify; LPWSTR lpMenuString; HFONT hfnOld; int tcExtra; UNREFERENCED_PARAMETER(pMenu); CheckLock(pMenu); CheckLock(pwndNotify); if (!fPopup) { /* * Save off the height of the top menu bar since we will used this often * if the pItem is not in a popup. (ie. it is in the top level menu bar) */ height = SYSMET(CYMENUSIZE); } hfnOld = NULL; if (TestMFS(pItem, MFS_DEFAULT)) { if (ghMenuFontDef) hfnOld = GreSelectFont(hdc, ghMenuFontDef); else { tcExtra = GreGetTextCharacterExtra(hdc); GreSetTextCharacterExtra(hdc, tcExtra + 1 + (gcxMenuFontChar / gpsi->cxSysFontChar)); } } /* * Compute bitmap dimensions if needed */ if (pItem->hbmp != NULL) { if (pItem->hbmp == HBMMENU_CALLBACK) { xxxMNGetBitmapSize(pItem, pwndNotify); } else if (pItem->cxBmp == MNIS_MEASUREBMP) { if (TestMFS(pItem, MFS_CACHEDBMP)) { pItem->cxBmp = SYSMET(CXMENUSIZE); pItem->cyBmp = SYSMET(CYMENUSIZE); if (pItem->hbmp == HBMMENU_SYSTEM) { pItem->cxBmp += SYSMET(CXEDGE); /* * Chicago/Memphis only stretch the width, * not the height. NT Bug 124779. FritzS */ // pItem->cyBmp += SYSMET(CXEDGE); } } else { if (GreExtGetObjectW(pItem->hbmp, sizeof(BITMAP), (LPSTR)&bmp)) { pItem->cxBmp = bmp.bmWidth; pItem->cyBmp = bmp.bmHeight; } else { /* * If the bitmap is not useable, this is as good a default * as any. */ pItem->cxBmp = SYSMET(CXMENUSIZE); pItem->cyBmp = SYSMET(CYMENUSIZE); } } } width = pItem->cxBmp; /* * Remember the max bitmap width to align the text in all items. */ pMenu->cxTextAlign = max(pMenu->cxTextAlign, (DWORD)width); /* * In menu bars, we force the item to be at least CYMNSIZE. * Fixes many, many problems w/ apps that fake own MDI. */ if (fPopup) { height = pItem->cyBmp; } else { height = max((int)pItem->cyBmp, height); } } else if (TestMFT(pItem, MFT_OWNERDRAW)) { // This is an ownerdraw item -- the width and height are stored in // cxBmp and cyBmp xxxMNGetBitmapSize(pItem, pwndNotify); width = pItem->cxBmp; // // Ignore height with menu bar now--that's set by user. // if (fPopup) { height = pItem->cyBmp; // If this item has a popup (hierarchical) menu associated with it, then // reserve room for the bitmap that tells the user that a hierarchical // menu exists here. // B#2966, t-arthb UserAssert(fPopup == (TestMF(pMenu, MFISPOPUP) != 0)); width = width + (gcxMenuFontChar << 1); } } if ((pItem->lpstr != NULL) && (!TestMFT(pItem, MFT_OWNERDRAW)) ) { SIZE size; /* * This menu item contains a string */ /* * We want to keep the menu bar height if this isn't a popup. */ if (fPopup) { /* The thickness of mnemonic underscore is CYBORDER and the gap * between the characters and the underscore is another CYBORDER */ height = max(height, gcyMenuFontChar + gcyMenuFontExternLeading + SYSMET(CYEDGE)); } lpMenuString = TextPointer(pItem->lpstr); xRightJustify = FindCharPosition(lpMenuString, TEXT('\t')); xxxPSMGetTextExtent(hdc, lpMenuString, xRightJustify, &size); if (width) { width += MNXSPACE + size.cx; } else { width = size.cx; } } if (fPopup && !TestMFT(pItem, MFT_OWNERDRAW)) { /* * Add on space for checkmark, then horz spacing for default & disabled * plus some left margin. */ if (TestMF(pMenu, MNS_CHECKORBMP) || !TestMF(pMenu, MNS_NOCHECK)) { width += gpsi->oembmi[OBI_MENUCHECK].cx; } width += MNXSPACE + MNLEFTMARGIN + 2; height += 2; } if (TestMFS(pItem, MFS_DEFAULT)) { if (hfnOld) GreSelectFont(hdc, hfnOld); else GreSetTextCharacterExtra(hdc, tcExtra); } /* * Loword contains width, high word contains height of item. */ lppt->x = width; lppt->y = height; return(TestMFT(pItem, MFT_OWNERDRAW)); }
/***************************************************************************\ * * DrawState() * * Generic state drawing routine. Does simple drawing into same DC if * normal state; uses offscreen bitmap otherwise. * * We do drawing for these simple types ourselves: * (1) Text * lData is string pointer. * wData is string length * (2) Icon * LOWORD(lData) is hIcon * (3) Bitmap * LOWORD(lData) is hBitmap * (4) Glyph (internal) * LOWORD(lData) is OBI_ value, one of * OBI_CHECKMARK * OBI_BULLET * OBI_MENUARROW * right now * * Other types are required to draw via the callback function, and are * allowed to stick whatever they want in lData and wData. * * We apply the following effects onto the image: * (1) Normal (nothing) * (2) Default (drop shadow) * (3) Union (gray string dither) * (4) Disabled (embossed) * * Note that we do NOT stretch anything. We just clip. * \***************************************************************************/ BOOL _DrawState( HDC hdcDraw, HBRUSH hbrFore, DRAWSTATEPROC qfnCallBack, LPARAM lData, WPARAM wData, int x, int y, int cx, int cy, UINT uFlags) { HFONT hFont; HFONT hFontSave = NULL; HDC hdcT; HBITMAP hbmpT; POINT ptOrg; BOOL fResult; /* * These require monochrome conversion * * Enforce monochrome: embossed doesn't look great with 2 color displays */ if ((uFlags & DSS_DISABLED) && ((oemInfo.BitCount == 1) || SYSMET(SLOWMACHINE))) { uFlags &= ~DSS_DISABLED; uFlags |= DSS_UNION; } if (uFlags & (DSS_DISABLED | DSS_DEFAULT | DSS_UNION)) uFlags |= DSS_MONO; /* * Get drawing sizes etc. AND VALIDATE. */ switch (uFlags & DST_TYPEMASK) { case DST_GLYPH: /* * LOWORD(lData) is OBI_ value. */ UserAssert(LOWORD(lData) < (WORD)OBI_COUNT); if (!cx) cx = oemInfo.bm[LOWORD(lData)].cx; if (!cy) cy = oemInfo.bm[LOWORD(lData)].cy; break; case DST_BITMAP: /* * (lData) is hbmp. */ // if (IsGDIObject((HBITMAP)LOWORD(lData)) != GDIOBJ_BITMAP) // return FALSE; if (!cx || !cy) { BITMAP bmp; try { GreExtGetObjectW((HBITMAP)lData, sizeof(BITMAP), &bmp); if (!cx) cx = bmp.bmWidth; if (!cy) cy = bmp.bmHeight; } except (EXCEPTION_EXECUTE_HANDLER) { return FALSE; } } break; case DST_ICON: /* * lData is picon. */ if (!cx || !cy) { if (!cx) cx = ((PICON)lData)->cx; if (!cy) cy = ((PICON)lData)->cy / 2; // Icons are double height in NT } break; case DST_TEXT: /* * lData is LPSTR * NOTE THAT WE DO NOT VALIDATE lData, DUE TO COMPATIBILITY * WITH GRAYSTRING(). THIS _SHOULD_ FAULT IF YOU PASS IN NULL. * * wData is cch. */ if (!wData) wData = wcslen((LPWSTR)lData); if (!cx || !cy) { SIZE size; /* * Make sure we use right dc w/ right font. */ GreGetTextExtentW(hdcDraw, (LPWSTR)lData, wData, &size, GGTE_WIN3_EXTENT); if (!cx) cx = size.cx; if (!cy) cy = size.cy; } /* * Now, pretend we're complex if qfnCallBack is supplied AND * we're supporting GrayString(). */ // if ((uFlags & DST_GRAYSTRING) && SELECTOROF(qfnCallBack)) { // uFlags &= ~DST_TYPEMASK; // uFlags |= DST_COMPLEX; // } break; case DST_PREFIXTEXT: if (lData==0) { RIPMSG0(RIP_ERROR, "DrawState: NULL DST_PREFIXTEXT string"); return FALSE; } if (!wData) wData = wcslen((LPWSTR)lData); if (!cx || !cy) { SIZE size; PSMGetTextExtent(hdcDraw, (LPWSTR)lData, wData, &size); if (!cx) cx = size.cx; if (!cy) cy = size.cy; } /* * Add on height for prefix */ cy += 2*SYSMET(CYBORDER); break; case DST_COMPLEX: if (qfnCallBack == NULL) { RIPMSG0(RIP_ERROR, "DrawState: invalid callback for DST_COMPLEX"); return(FALSE); } break; default: RIPMSG0(RIP_ERROR, "DrawState: invalid DST_ type"); return FALSE; }