/*
 * tkWinUtil.c
 *
 * Copyright (c) 1994 Software Research Associates, Inc.
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose and without fee is hereby granted, provided
 * that the above copyright notice appear in all copies and that both that
 * copyright notice and this permission notice appear in supporting
 * documentation, and that the name of Software Research Associates not be
 * used in advertising or publicity pertaining to distribution of the
 * software without specific, written prior permission.  Software Research
 * Associates makes no representations about the suitability of this software
 * for any purpose.  It is provided "as is" without express or implied
 * warranty.
 */

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#undef WIN32_LEAN_AND_MEAN
#include "tkInt.h"
#include "tkConfig.h"
#include "util.h"
#include "wndproc.h"

/*
 * use management cursor 
 */
#define HDR_SIZE 0x46
#define	BM_SIZE 0x80

typedef struct {
	char dummy1[0x0a];
	UINT x_hot, y_hot;
	char dummy2[0x38];
} CURSORFILEHEADER;		

/*
 * use maneagement selection 
 */

typedef struct {
    char *string;		/* Contents of selection are					      
				 * here.  This space is malloc-ed. */
    int bytesAvl;		/* Total number of bytes available
				 * at string. */
    int bytesUsed;		/* Bytes currently in use in string,
				 * not including the terminating
				 * NULL. */
} GetInfo;


extern int	SelGetProc _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, char *portion));

extern void	TbSetClipboard _ANSI_ARGS_((Tk_Window tkwin));
extern int	TbGetClipboardData _ANSI_ARGS_((Tcl_Interp *interp, 
			    Tk_GetSelProc *proc, ClientData clientData));



/*
 * Tb_SetClipboard --
 *
 */

void
TbSetClipboard(Tk_Window tkwin)
{
    HGLOBAL hGlobal;
    char *pGlobal;
    char *pString;
    HWND hwnd = Tk_WindowId(tkwin);
    GetInfo getInfo;
    Tcl_Interp *interp;
    int result;

    interp = Tcl_CreateInterp();
    getInfo.string = (char *) ckalloc(100);
    getInfo.bytesAvl = 100;
    getInfo.bytesUsed = 0;
    result = Tk_GetSelection(interp, tkwin, XA_STRING, SelGetProc,
	    (ClientData) &getInfo);
    if (result != TCL_OK) {
        ckfree(getInfo.string);
	return;
    }
    Tcl_DeleteInterp(interp);
    if ((hGlobal = GlobalAlloc(GHND, strlen(getInfo.string) + 1)) == None) {
    	return;
    }
    pGlobal = GlobalLock(hGlobal);
    pString = getInfo.string;

    while(*pGlobal++ = *pString++) ;
    GlobalUnlock(hGlobal); 
    if (GetClipboardOwner() == hwnd) { 
	OpenClipboard(hwnd);
	SendMessage(hwnd, TKW_SELECTIONSAVE, 0, 0L);
	EmptyClipboard();
  	SetClipboardData(CF_TEXT, hGlobal);
	CloseClipboard();
    }
    ckfree(getInfo.string);
}

int
TbGetClipboardData(interp, proc, clientData)
    Tcl_Interp *interp;		/* Interpreter to use for reporting
				 * errors. */
    Tk_GetSelProc *proc;	/* Procedure to call to process the
				 * selection, once it has been retrieved. */
    ClientData clientData;	/* Arbitrary value to pass to proc. */
{
    HGLOBAL hGlobal;
    int result;
    char *pGlobal;

    if (OpenClipboard((HWND) NULL)) {
	if ((hGlobal = GetClipboardData(CF_TEXT)) == (HGLOBAL) NULL) {
	    CloseClipboard();
	    return TCL_ERROR;
	}
	pGlobal = GlobalLock(hGlobal);
	result = (*proc)(clientData, interp, pGlobal);
	GlobalUnlock(hGlobal);
	CloseClipboard();
	return result;
    }
    return TCL_ERROR;
}
/*
 * reberth
 */

static void
reberth(bits)
unsigned char *bits;
{
    unsigned char buffer[4];
    int i;

    for (i = 0; i < 64; i+= 4) {
    	memcpy(buffer, bits + i, 4);
	memcpy(bits + i, bits + (124 - i), 4);
	memcpy(bits + (124 - i), buffer, 4);
    }
} 

/*
 *	LoadCursorRuntime --
 *
 */
int 
LoadCursorRuntime(filename, width, height, cursor)
char *filename;
unsigned int *width, *height;
Cursor *cursor;
{
    struct _stat st;
    char *buffer;
    FILE *fp;
    int *src, *mask;
    CURSORFILEHEADER *csfh;
    HCURSOR hcs;

    if (_stat(filename, &st) != 0) {
	return 1;
    }
    if ((fp = fopen(filename, "rb")) == NULL) {
	return 1;
    }
    if ((buffer = (char *)malloc((size_t)st.st_size)) == NULL) {
	return 2;
    }
    if (fread(buffer, (size_t)st.st_size, 1, fp) != 1) {
	return 3;
    }
    fclose(fp);
    csfh = (CURSORFILEHEADER *)buffer;
    *width = 32;
    *height = 32;

    src = (int *)(buffer + HDR_SIZE);					
    reberth(src);
    mask = (int *)(buffer + HDR_SIZE + BM_SIZE);
    reberth(mask);
    hcs = CreateCursor(GetAppInstance(), csfh->x_hot, csfh->y_hot, 
		       32, 32, mask, src);	

    if (hcs == None) {
	return 4;
    }
    *cursor = hcs;
			
    free(buffer);

    return 0;
}	

HCURSOR 
GetCursorByShape(const char *shape)
{
    return LoadCursor(0, shape);
}

#if defined ( TB ) && defined ( KANJI )

int
TbWSTextWidth(font, wstr, gmask, len)
     XFontStruct *font;
     wchar *wstr;
     int gmask;
     int len;
{
#define bufsize	256
	XChar2b			buf[bufsize];
	XChar2b			*cp;
	XChar2b			*cpend = buf + bufsize;
	wchar			*wstr1 = wstr + len;
	int			c;
	int			width = 0;
	int			gr_mapping;

	while( wstr < wstr1 ) {
	    gr_mapping = 0;

	    cp = buf;

	    if( font == NULL ) {
		while( wstr < wstr1 && (*wstr & 0x8080) == (unsigned) gmask ) wstr++;
		continue;
	    }

	    while( wstr < wstr1 && ((c = *wstr) & 0x8080) == (unsigned) gmask ) {
		if( cp >= cpend - 1) {
		    /* flush */
		    width += XTextWidth16(font, buf, cp - buf);
		    cp = buf;
		}
		cp->byte1 = (c >> 8) & 0x7f;
		cp->byte2 = c & 0x7f;
		if (gr_mapping) {
		    if (cp->byte1 != 0) cp->byte1 |= 0x80;
		    cp->byte2 |= 0x80;
		}
		cp++;
		wstr++;
	    }

	    if( cp == buf ) continue;

	    /* flush */
	    width += XTextWidth16(font, buf, cp - buf);
	}

	return width;
}
#endif /* TB */
