Tcl-Tk-Tkwidget-treectrl

 view release on metacpan or  search on metacpan

shellicon/shellicon.c  view on Meta::CPAN

	    sticky &= ~(STICKY_W | STICKY_E);
    }
    if ((sticky & STICKY_N) && (sticky & STICKY_S)) {
	if (expandY)
	    *heightPtr += dy;
	else
	    sticky &= ~(STICKY_N | STICKY_S);
    }
    if (!(sticky & STICKY_W)) {
	*xPtr += (sticky & STICKY_E) ? dx : dx / 2;
    }
    if (!(sticky & STICKY_N)) {
	*yPtr += (sticky & STICKY_S) ? dy : dy / 2;
    }
}

/* This macro gets the value of a per-state option for an element, then
 * looks for a better match from the master element if it exists */
#define OPTION_FOR_STATE(xFUNC,xTYPE,xVAR,xFIELD,xSTATE) \
    xVAR = xFUNC(tree, &elemX->xFIELD, xSTATE, &match); \
    if ((match != MATCH_EXACT) && (masterX != NULL)) { \
	xTYPE varM = xFUNC(tree, &masterX->xFIELD, xSTATE, &match2); \
	if (match2 > match) \
	    xVAR = varM; \
    }
#define BOOLEAN_FOR_STATE(xVAR,xFIELD,xSTATE) \
    OPTION_FOR_STATE(PerStateBoolean_ForState,int,xVAR,xFIELD,xSTATE)

/* This macro gets the object for a per-state option for an element, then
 * looks for a better match from the master element if it exists */
#define OBJECT_FOR_STATE(xVAR,xTYPE,xFIELD,xSTATE) \
    xVAR = PerStateInfo_ObjForState(tree, &xTYPE, &elemX->xFIELD, xSTATE, &match); \
    if ((match != MATCH_EXACT) && (masterX != NULL)) { \
	Tcl_Obj *objM = PerStateInfo_ObjForState(tree, &xTYPE, &masterX->xFIELD, xSTATE, &matchM); \
	if (matchM > match) \
	    xVAR = objM; \
    }

typedef struct ElementShellIcon ElementShellIcon;

struct ElementShellIcon
{
    TreeElement_ header;
#ifdef DEPRECATED
    PerStateInfo draw;
#endif
    Tcl_Obj *pathObj;		/* path of file or directory */
    char *path;
    Tcl_Obj *widthObj;
    int width;
    Tcl_Obj *heightObj;
    int height;
#define TYPE_DIRECTORY 0
#define TYPE_FILE 1
    int type;			/* If specified, 'path' is assumed to exist */
#define SIZE_LARGE 0
#define SIZE_SMALL 1
    int size;			/* SIZE_LARGE if unspecified */
    HIMAGELIST hImgList;	/* the system image list */
    int iIcon;			/* index into hImgList */
    /* FIXME: overlays no longer work in Win7 */
    int addOverlays;		/* only when useImgList is FALSE */
    int useImgList;		/* if false, create icons */
#define USE_SEL_ALWAYS 0	/* always draw selected icon */
#define USE_SEL_AUTO 1		/* draw selected icon when item is selected */
#define USE_SEL_NEVER 2		/* never draw the selected icon */
    int useSelected;		/* when to draw the selected icon */
    HICON hIcon;		/* icon */
    HICON hIconSel;		/* selected icon */
};

#define SHELLICON_CONF_ICON 0x0001
#define SHELLICON_CONF_SIZE 0x0002
#define SHELLICON_CONF_DRAW 0x0004

static CONST char *sizeST[] = {
    "large", "small", (char *) NULL
};
static CONST char *typeST[] = {
    "directory", "file", (char *) NULL
};
static CONST char *useSelectedST[] = {
    "always", "auto", "never", (char *) NULL
};

static Tk_OptionSpec shellIconOptionSpecs[] = {
    {TK_OPTION_CUSTOM, "-addoverlays", (char *) NULL, (char *) NULL,
     (char *) NULL, -1, Tk_Offset(ElementShellIcon, addOverlays),
     TK_OPTION_NULL_OK, (ClientData) NULL, SHELLICON_CONF_ICON},
#ifdef DEPRECATED
    {TK_OPTION_CUSTOM, "-draw", (char *) NULL, (char *) NULL,
     (char *) NULL, Tk_Offset(ElementShellIcon, draw.obj),
     Tk_Offset(ElementShellIcon, draw),
     TK_OPTION_NULL_OK, (ClientData) NULL, SHELLICON_CONF_DRAW},
#endif
    {TK_OPTION_PIXELS, "-height", (char *) NULL, (char *) NULL,
     (char *) NULL, Tk_Offset(ElementShellIcon, heightObj),
     Tk_Offset(ElementShellIcon, height),
     TK_OPTION_NULL_OK, (ClientData) NULL, SHELLICON_CONF_SIZE},
    {TK_OPTION_STRING, "-path", (char *) NULL, (char *) NULL,
     (char *) NULL, Tk_Offset(ElementShellIcon, pathObj),
     Tk_Offset(ElementShellIcon, path),
     TK_OPTION_NULL_OK, (ClientData) NULL, SHELLICON_CONF_ICON},
    {TK_OPTION_CUSTOM, "-size",(char *) NULL, (char *) NULL,
     (char *) NULL, -1, Tk_Offset(ElementShellIcon, size),
     TK_OPTION_NULL_OK, (ClientData) NULL, SHELLICON_CONF_ICON},
    {TK_OPTION_CUSTOM, "-type", (char *) NULL, (char *) NULL,
     (char *) NULL, -1, Tk_Offset(ElementShellIcon, type),
     TK_OPTION_NULL_OK, (ClientData) NULL, SHELLICON_CONF_ICON},
    {TK_OPTION_CUSTOM, "-useimagelist", (char *) NULL, (char *) NULL,
     (char *) NULL, -1, Tk_Offset(ElementShellIcon, useImgList),
     TK_OPTION_NULL_OK, (ClientData) NULL, SHELLICON_CONF_ICON},
    {TK_OPTION_CUSTOM, "-useselected", (char *) NULL, (char *) NULL,
     (char *) NULL, -1, Tk_Offset(ElementShellIcon, useSelected),
     TK_OPTION_NULL_OK, (ClientData) NULL, SHELLICON_CONF_DRAW},
    {TK_OPTION_PIXELS, "-width", (char *) NULL, (char *) NULL,
     (char *) NULL, Tk_Offset(ElementShellIcon, widthObj),
     Tk_Offset(ElementShellIcon, width),
     TK_OPTION_NULL_OK, (ClientData) NULL, SHELLICON_CONF_SIZE},
    {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL,
     (char *) NULL, 0, -1, 0, (ClientData) NULL, 0}
};

static void LoadIconIfNeeded(TreeElementArgs *args)
{
    TreeCtrl *tree = args->tree;
    TreeElement elem = args->elem;
    ElementShellIcon *elemX = (ElementShellIcon *) elem;
    ElementShellIcon *masterX = (ElementShellIcon *) elem->master;
    SHFILEINFO sfi;
    Tcl_DString dString1, dString2;
    UINT uFlags = SHGFI_SYSICONINDEX;
    DWORD dwFileAttributes = 0;
    char *nativePath;
    int size = SIZE_LARGE;
    int overlays = 1;
    int type = -1;
    int useImgList = TRUE;
    DWORD_PTR result;

    /* -useimagelist boolean */
    if (elemX->useImgList != -1)
	useImgList = elemX->useImgList;
    else if (masterX != NULL && masterX->useImgList != -1)
	useImgList = masterX->useImgList;

    /* Not using the system image list. */
    if (!useImgList) {

	/* Already have an icon, or no path is given so no icon used */
	if ((elemX->hIcon != NULL) || (elemX->path == NULL))
	    return;

	/* Equivalent to "file nativename $path" */
	nativePath = Tcl_TranslateFileName(tree->interp, elemX->path, &dString1);
	if (nativePath == NULL)
	    return;

	/* This will be passed to system calls, so convert from UTF8 */
	nativePath = Tcl_UtfToExternalDString(NULL, nativePath, -1, &dString2);

	uFlags = SHGFI_ICON;

	/* -addoverlays boolean */
	if (elemX->addOverlays != -1)
	    overlays = elemX->addOverlays;
	else if (masterX != NULL && masterX->addOverlays != -1)
	    overlays = masterX->addOverlays;
	if (overlays)
	    uFlags |= SHGFI_ADDOVERLAYS;

	/* -size small or large */
	if (elemX->size != -1)
	    size = elemX->size;
	else if (masterX != NULL && masterX->size != -1)
	    size = masterX->size;
	switch (size) {
	    case SIZE_LARGE: uFlags |= SHGFI_LARGEICON | SHGFI_SHELLICONSIZE; break;
	    case SIZE_SMALL: uFlags |= SHGFI_SMALLICON | SHGFI_SHELLICONSIZE; break;
	}

	/* -type file or -type directory */
	if (elemX->type != -1)
	    type = elemX->type;
	else if (masterX != NULL && masterX->type != -1)
	    type = masterX->type;
	/* If SHGFI_USEFILEATTRIBUTES is set, SHGetFileInfo is supposed to
	 * assume that the file is real but not look for it on disk. This
	 * can be used to get the icon for a certain type of file, ex *.exe.
	 * In practice, lots of files get a non-generic icon when a
	 * valid file path is given. */
	if (type != -1) {
	    dwFileAttributes = (type == TYPE_FILE) ?
		FILE_ATTRIBUTE_NORMAL : FILE_ATTRIBUTE_DIRECTORY;
	    uFlags |= SHGFI_USEFILEATTRIBUTES;
	}

	/* MSDN says SHGFI_OPENICON returns the image list containing the
	 * small open icon. In practice the large open icon gets returned
	 * for SHGFI_LARGEICON, so we support it. */
	if (/*(size == SIZE_SMALL) && */(args->state & STATE_ITEM_OPEN))
	    uFlags |= SHGFI_OPENICON;

	CoInitialize(NULL);

	result = SHGetFileInfo(
	    nativePath,
	    dwFileAttributes,
	    &sfi,
	    sizeof(sfi),
	    uFlags);
	if (result) {
	    elemX->hIcon = sfi.hIcon;

	    /* Remember the image list so we can get the icon size */
	    elemX->hImgList = (size == SIZE_LARGE) ? gImgListLarge : gImgListSmall;
	}

	result = SHGetFileInfo(
	    nativePath,
	    dwFileAttributes,
	    &sfi,
	    sizeof(sfi),
	    uFlags | SHGFI_SELECTED);
	if (result)
	    elemX->hIconSel = sfi.hIcon;


	CoUninitialize();

shellicon/shellicon.c  view on Meta::CPAN

#endif

    /* InitCommonControlsEx must be called to use the ImageList functions */
    /* This is already done by Tk on NT */
    if (TkWinGetPlatformId() != VER_PLATFORM_WIN32_NT) {
	INITCOMMONCONTROLSEX comctl;
	ZeroMemory(&comctl, sizeof(comctl));
	(void) InitCommonControlsEx(&comctl);
    }

#if 1
    /* Get the sytem image lists (small and large) */
    CoInitialize(NULL);
    gImgListSmall = (HIMAGELIST) SHGetFileInfo(".exe", FILE_ATTRIBUTE_NORMAL, &sfi,
	sizeof(sfi), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX | SHGFI_SMALLICON);
    gImgListLarge = (HIMAGELIST) SHGetFileInfo(".exe", FILE_ATTRIBUTE_NORMAL, &sfi,
	sizeof(sfi), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX | SHGFI_LARGEICON);
    CoUninitialize();
#else
    /* FIXME: WinXP only */
    /* This is broken somewhere */
    hLib = LoadLibraryA("shell32");
    SHGetImageListProc = (FARPROC) GetProcAddress(hLib, (LPCSTR) 727);
    SHGetImageListProc(SHIL_SMALL, &IID_IImageList, &gImgListSmall);
    SHGetImageListProc(SHIL_LARGE, &IID_IImageList, &gImgListLarge);
    SHGetImageListProc(SHIL_EXTRALARGE, &IID_IImageList, &gImgListXtraLarge);
    dbwin("small %p large %p xtralarge %p\n", gImgListSmall, gImgListLarge, gImgListXtraLarge);
    FreeLibrary(hLib);
#endif

#if 0
{
typedef BOOL (WINAPI *FileIconInitProc)(BOOL fFullInit);
HMODULE hShell32 = LoadLibrary("shell32.dll");
FileIconInitProc FileIconInit = (FileIconInitProc) GetProcAddress(hShell32, (LPCSTR)660);
FileIconInit(TRUE);
}
#endif

    /* Load TkTreeCtrl */
    if (Tcl_PkgRequire(interp, "treectrl", PACKAGE_PATCHLEVEL, TRUE) == NULL)
	return TCL_ERROR;

    /* Get the stubs table from TkTreeCtrl */
    stubs = Tcl_GetAssocData(interp, "TreeCtrlStubs", NULL);
    if (stubs == NULL)
	return TCL_ERROR;

#ifdef TREECTRL_DEBUG
    if (sizeof(TreeCtrl) != stubs->sizeofTreeCtrl ||
	    sizeof(TreeCtrlStubs) != stubs->sizeofTreeCtrlStubs ||
	    sizeof(TreeElement) != stubs->sizeofTreeElement ||
	    sizeof(TreeElementArgs) != stubs->sizeofTreeElementArgs) {
	Tcl_SetResult(interp, "probably forgot to recompile shellicon",
		TCL_VOLATILE);
	return TCL_ERROR;
    }
#endif

    /* Initialize the options table */
    BooleanCO_Init(shellIconOptionSpecs, "-addoverlays");
    BooleanCO_Init(shellIconOptionSpecs, "-useimagelist");
    PerStateCO_Init(shellIconOptionSpecs, "-draw", &pstBoolean,
	    TreeStateFromObj);
    StringTableCO_Init(shellIconOptionSpecs, "-size", sizeST);
    StringTableCO_Init(shellIconOptionSpecs, "-type", typeST);
    StringTableCO_Init(shellIconOptionSpecs, "-useselected", useSelectedST);

    /* Add the "shellicon" element type */
    if (TreeCtrl_RegisterElementType(interp, &elemTypeShellIcon) != TCL_OK)
	return TCL_ERROR;

    if (Tcl_PkgProvide(interp, PACKAGE_NAME, PACKAGE_PATCHLEVEL) != TCL_OK) {
	return TCL_ERROR;
    }

    return TCL_OK;
}

DLLEXPORT int Shellicon_SafeInit(Tcl_Interp *interp)
{
    return Shellicon_Init(interp);
}



( run in 0.592 second using v1.01-cache-2.11-cpan-ceb78f64989 )