/*
 * GraphApp - Cross-Platform Graphics Programming Library.
 *
 * File: controls.c -- manipulating scrollbars, buttons, etc.
 * Platform: Windows  Version: 2.40  Date: 1998/04/04
 *
 * Version: 1.00  Changes: Original version by Lachlan Patrick.
 * Version: 1.60  Changes: Added clear(), draw(), flashcontrol().
 * Version: 2.00  Changes: New object class system.
 * Version: 2.15  Changes: Transparent backgrounds added.
 * Version: 2.20  Changes: Non-native buttons supported.
 * Version: 2.35  Changes: New reference count technique.
 * Version: 2.40  Changes: Support for new controls.
 */

/* Copyright (C) 1993-1998 Lachlan Patrick

   This file is part of GraphApp, a cross-platform C graphics library.

   GraphApp is free software; you can redistribute it and/or modify it
   under the terms of the GNU Library General Public License.
   GraphApp is distributed in the hope that it will be useful, but
   WITHOUT ANY WARRANTY.

   See the file COPYLIB.TXT for details.
*/

/*  Copyright (C) 2004	The R Foundation

    Changes for R:

    sort out resize (confused screen and client coords)
    add printer and metafile handling
    Remove assumption of current->dest being non-NULL

 */

#include "internal.h"
#include <richedit.h>

# define alloca(x) __builtin_alloca((x))

/*
 *  Setting control call-backs.
 */
void setaction(control obj, actionfn fn)
{
    if (obj)
	obj->action = fn;
}

void sethit(control obj, intfn fn)
{
    if (obj)
	obj->hit = fn;
}

void setdel(control obj, actionfn fn)
{
    if (obj)
	if (obj->call)
	    obj->call->die = fn;
}

void setclose(control obj, actionfn fn)
{
    if (obj)
	if (obj->call)
	    obj->call->close = fn;
}

void setredraw(control obj, drawfn fn)
{
    if (obj)
	if (obj->call)
	    obj->call->redraw = fn;
}

void setresize(control obj, drawfn fn)
{
    if (obj)
	if (obj->call)
	    obj->call->resize = fn;
}

void setkeydown(control obj, keyfn fn)
{
    if (obj)
	if (obj->call)
	    obj->call->keydown = fn;
}

void setkeyaction(control obj, keyfn fn)
{
    if (obj)
	if (obj->call)
	    obj->call->keyaction = fn;
}

void setmousedown(control obj, mousefn fn)
{
    if (obj)
	if (obj->call)
	    obj->call->mousedown = fn;
}

void setmouseup(control obj, mousefn fn)
{
    if (obj)
	if (obj->call)
	    obj->call->mouseup = fn;
}

void setmousemove(control obj, mousefn fn)
{
    if (obj)
	if (obj->call)
	    obj->call->mousemove = fn;
}

void setmousedrag(control obj, mousefn fn)
{
    if (obj)
	if (obj->call)
	    obj->call->mousedrag = fn;
}

void setmouserepeat(control obj, mousefn fn)
{
    if (obj)
	if (obj->call)
	    obj->call->mouserepeat = fn;
}

void setdrop(control obj, dropfn fn)
{
    if (obj)
	if (obj->call) {
	    DragAcceptFiles(obj->handle, TRUE);
	    obj->call->drop = fn;
	}
}

void setonfocus(control obj, actionfn fn)
{
    if (obj)
	obj->call->focus = fn;
}

void setim(control obj, imfn fn)
{
    if (obj)
	obj->call->im = fn;
}

/*
 *  Drawing controls and windows.
 */
void clear(control obj)
{
    drawing prev;
    rgb old;

    if (! obj)
	return;
    if (! isvisible(obj))
	return;
    if (! isvisible(parentwindow(obj)))
	return;
    if (obj->bg == Transparent)
	return;
    prev = current->dest;
    drawto(obj);
    old = currentrgb();
    setrgb(obj->bg);
    fillrect(getrect(obj));
    if (prev) {
	setrgb(old);
	drawto(prev);
    }
}

void draw(control obj)
{
    drawing prev;
    drawstate old = NULL;

    if (! obj)
	return;
    if (obj->kind == MenubarObject) {
	DrawMenuBar(obj->parent->handle);
	return;
    }

    if (! isvisible(obj))
	return;
    if (! isvisible(parentwindow(obj)))
	return;
    if ((obj->call == NULL) || (obj->call->redraw == NULL))
	return;
    prev = current->dest;
    drawto(obj);
    if (prev) old = copydrawstate();
    moveto(pt(0,0));
    obj->call->redraw(obj, getrect(obj));
    if (prev) {
	restoredrawstate(old);
	drawto(prev);
    }
}

void redraw(control obj)
{
    clear(obj);
    draw(obj);
}

/*  void getscreenrect(control obj, rect *r) */
/*  { */
/*      RECT W; */
/*      GetWindowRect(obj->handle, &W); */
/*      r->x = W.left; */
/*      r->y = W.top; */
/*      r->width = W.right - W.left; */
/*      r->height = W.bottom - W.top; */
/*  } */


/* The original here used GetWindowRect (which used screen coordinates)
   and MoveWindow (which uses client coordinates) so got the positioning
   hopelessly wrong.  This version works for WindowObjects, but I would be
   suspicious of it for other cases.  BDR 2000/04/05
*/
void resize(control obj, rect r)
{
    RECT R;
    WINDOWPLACEMENT W;
    int dw, dh, dx, dy;

    if (! obj)
	return;
    r = rcanon(r);
    if (obj->kind == WindowObject) {
	W.length = sizeof(WINDOWPLACEMENT);
	r.x = obj->rect.x;
	r.y = obj->rect.y;
	if (!equalr(r, obj->rect)) {
	    GetWindowPlacement(obj->handle, &W);
	    if (!isvisible(obj)) W.showCmd = SW_HIDE;  /* stops the resize from revealing the window */
	    dx = r.x - obj->rect.x;
	    dy = r.y - obj->rect.y;
	    /* don't believe current sizes!
	       dw = r.width - obj->rect.width;
	       dh = r.height - obj->rect.height;
	       Rprintf("dw %d dh %d\n", dw, dh); */
	    GetClientRect(obj->handle, &R);
	    dw = r.width - (R.right - R.left);
	    dh = r.height - (R.bottom - R.top);
	    W.rcNormalPosition.left += dx;
	    W.rcNormalPosition.top += dy;
	    W.rcNormalPosition.right += dx + dw;
	    W.rcNormalPosition.bottom += dy + dh;
	    SetWindowPlacement(obj->handle, &W);
	}
    }
    else {
	if (! equalr(r, obj->rect))
	    MoveWindow(obj->handle, r.x, r.y, r.width, r.height, 1);
	obj->rect.x = r.x;
	obj->rect.y = r.y;
    }
    obj->rect.width = r.width;
    obj->rect.height = r.height;
}

/*
 *  Showing and hiding controls and windows.
 */
void show(control obj)
{
    if (! obj)
	return;
    switch (obj->kind) {
    case CursorObject: case FontObject: case BitmapObject:
    case MenubarObject: case MenuObject: case MenuitemObject:
	break;
    case WindowObject:
	obj->state |= GA_Visible;
	show_window(obj);
	break;
    default:
	ShowWindow(obj->handle, SW_SHOWNORMAL);
	SetFocus(obj->handle);
	UpdateWindow(obj->handle);
    }
    obj->state |= GA_Visible;
}

void hide(control obj)
{
    if (! obj)
	return;
    switch (obj->kind) {
    case CursorObject: case FontObject: case BitmapObject:
    case MenubarObject: case MenuObject: case MenuitemObject:
	break;
    case WindowObject:
	hide_window(obj);
	break;
    default:
	ShowWindow(obj->handle, SW_HIDE);
    }
    obj->state &= ~GA_Visible;
}

int isvisible(control obj)
{
    if (! obj)
	return 0;
    return (obj->state & GA_Visible) ? 1 : 0;
}

/*
 *  Enabling and disabling controls and windows.
 */
void enable(control obj)
{
    if (! obj)
	return;
    switch (obj->kind) {
    case CursorObject: case FontObject: case BitmapObject:
    case MenubarObject:
	break;
    case MenuObject: case MenuitemObject:
	EnableMenuItem(obj->parent->handle,
		       obj->id, MF_ENABLED | MF_BYCOMMAND);
	break;
    case FieldObject: case TextboxObject:
	sendmessage(obj->handle, EM_SETREADONLY, FALSE, 0L);
	break;
    default:
	if (! isenabled(obj)) {
	    EnableWindow(obj->handle, 1);
	    obj->state |= GA_Enabled;
	    draw(obj);
	}
    }
    obj->state |= GA_Enabled;
}

void disable(control obj)
{
    if (! obj)
	return;
    switch (obj->kind) {
    case CursorObject: case FontObject: case BitmapObject:
    case MenubarObject: case MenuObject:
	break;
    case MenuitemObject:
	EnableMenuItem(obj->parent->handle,
		       obj->id, MF_GRAYED | MF_BYCOMMAND);
	break;
    case FieldObject: case TextboxObject:
	sendmessage(obj->handle, EM_SETREADONLY, TRUE, 0L);
	break;
    default:
	if (isenabled(obj)) {
	    EnableWindow(obj->handle, 0);
	    obj->state &= ~GA_Enabled;
	    draw(obj);
	}
    }
    obj->state &= ~GA_Enabled;
}

int isenabled(control obj)
{
    if (! obj)
	return 0;
    return (obj->state & GA_Enabled) ? 1 : 0;
}

/*
 *  Checking and unchecking controls.
 */
void check(control obj)
{
    if (! obj)
	return;
    switch (obj->kind) {
    case CursorObject: case FontObject: case BitmapObject:
    case MenubarObject: case MenuObject:
	break;
    case MenuitemObject:
	CheckMenuItem(obj->parent->handle, obj->id,
		      MF_CHECKED | MF_BYCOMMAND);
	break;
#if USE_NATIVE_BUTTONS
    case ButtonObject:
	sendmessage(obj->handle, BM_SETCHECK, 1, 0L);
	break;
#endif
#if USE_NATIVE_TOGGLES
    case CheckboxObject: case RadioObject:
	sendmessage(obj->handle, BM_SETCHECK, 1, 0L);
	break;
#endif
    default:
	if (! ischecked(obj)) {
	    obj->state |= GA_Checked;
	    draw(obj);
	}
    }
    obj->state |= GA_Checked;

}

void uncheck(control obj)
{
    if (! obj)
	return;
    switch (obj->kind) {
    case CursorObject: case FontObject: case BitmapObject:
    case MenubarObject: case MenuObject:
	break;
    case MenuitemObject:
	CheckMenuItem(obj->parent->handle, obj->id,
		      MF_UNCHECKED | MF_BYCOMMAND);
	break;
#if USE_NATIVE_BUTTONS
    case ButtonObject:
	sendmessage(obj->handle, BM_SETCHECK, 0, 0L);
	break;
#endif
#if USE_NATIVE_TOGGLES
    case CheckboxObject: case RadioObject:
	sendmessage(obj->handle, BM_SETCHECK, 0, 0L);
	break;
#endif
    default:
	if (ischecked(obj)) {
	    obj->state &= ~GA_Checked;
	    draw(obj);
	}
    }
    obj->state &= ~GA_Checked;
}

int ischecked(control obj)
{
    if (! obj)
	return 0;
    return (obj->state & GA_Checked) ? 1 : 0;
}

/*
 *  Highlighting and unhighlighting controls.
 */
void highlight(control obj)
{
    if (! obj)
	return;
    switch (obj->kind) {
    case CursorObject: case FontObject: case BitmapObject:
    case MenubarObject: case MenuObject: case MenuitemObject:
	break;
#if USE_NATIVE_BUTTONS
    case ButtonObject:
	sendmessage(obj->handle, BM_SETSTATE, 1, 0L);
	break;
#endif
#if USE_NATIVE_TOGGLES
    case CheckboxObject: case RadioObject:
	sendmessage(obj->handle, BM_SETSTATE, 1, 0L);
	break;
#endif
    case FieldObject: case TextboxObject:
	sendmessage(obj->handle, EM_SETSEL, 0, MAKELONG(0,-1));
	break;
    default:
	if (! ishighlighted(obj)) {
	    obj->state |= GA_Highlighted;
	    draw(obj);
	}
    }
    obj->state |= GA_Highlighted;
}

void unhighlight(control obj)
{
    if (! obj)
	return;
    switch (obj->kind) {
    case CursorObject: case FontObject: case BitmapObject:
    case MenubarObject: case MenuObject: case MenuitemObject:
	break;
#if USE_NATIVE_BUTTONS
    case ButtonObject:
	sendmessage(obj->handle, BM_SETSTATE, 0, 0L);
	break;
#endif
#if USE_NATIVE_TOGGLES
    case CheckboxObject: case RadioObject:
	sendmessage(obj->handle, BM_SETSTATE, 0, 0L);
	break;
#endif
    case FieldObject: case TextboxObject:
	sendmessage(obj->handle, EM_SETSEL, 0, MAKELONG(0,0));
	break;
    default:
	if (ishighlighted(obj)) {
	    obj->state &= ~GA_Highlighted;
	    draw(obj);
	}
    }
    obj->state &= ~GA_Highlighted;
}

int ishighlighted(control obj)
{
    if (! obj)
	return 0;
    return (obj->state & GA_Highlighted) ? 1 : 0;
}

/*
 *  The flashcontrol function highlights a control as if the user
 *  just used it, e.g. a button will become pressed down for a
 *  moment. Used in conjunction with activatecontrol() below,
 *  it can simulate a mouse-click on a button.
 */
void flashcontrol(control obj)
{
    highlight(obj);
    delay(150);
    unhighlight(obj);
}

/*
 *  The activatecontrol function is really useful. It causes
 *  a variety of controls to call their 'action functions.'
 *
 *  There are two types of action functions which a control can use.
 *  The first (obj->action) takes one argument, the control itself,
 *  and is used in buttons, checkboxes and the like as a response
 *  to a user clicking on these controls. The second function,
 *  (obj->hit) function, takes two arguments: the control and its
 *  current 'value'. A scrollbar's value changes as the user scrolls,
 *  and so its hit function is called whenever that happens.
 *
 *  The activatecontrol function tries to call the action function,
 *  and if that doesn't exist, calls the hit function, passing the
 *  object's value to it.
 */
void activatecontrol(control obj)
{
    if (! obj)
	return;
    drawto(obj);
    if (obj->action != NULL)
	obj->action(obj);
    else if (obj->hit != NULL)
	obj->hit(obj, obj->value);
}

/*
 *  Changing and determining the state of an object.
 *  These functions do not automatically redraw the object.
 */
#if 0
void setstate(control obj, long state)
{
    if (obj)
	obj->state = state;
}

long getstate(control obj)
{
    if (obj)
	return obj->state;
    else
	return 0;
}
#endif

void setvalue(control obj, int value)
{
    if (obj)
	obj->value = value;
}

int getvalue(control obj)
{
    if (obj)
	return obj->value;
    else
	return 0;
}

void setforeground(control obj, rgb fg)
{
    if (! obj)
	return;
    obj->fg = fg;
    if (obj->kind == TextboxObject) {
    	if (obj->handle) {    
    	    CHARFORMAT format;
    	    COLORREF wincolour = RGB((fg&gaRed)>>16,(fg&gaGreen)>>8,(fg&gaBlue)); 
    	    format.cbSize = sizeof(format);
    	    format.dwMask = CFM_COLOR;
    	    format.dwEffects = 0;
    	    format.crTextColor = wincolour;

	    sendmessage(obj->handle, EM_SETCHARFORMAT, 0, (LPARAM)&format);
	}
    } else {
    	InvalidateRect(obj->handle, NULL, TRUE);
    	redraw(obj);
    }
}

rgb getforeground(control obj)
{
    if (obj)
	return obj->fg;
    else
	return Black;
}

void setbackground(control obj, rgb bg)
{
    COLORREF wincolour = RGB((bg&gaRed)>>16,(bg&gaGreen)>>8,(bg&gaBlue));

    if (! obj)
	return;
    obj->bg = bg;
    if (obj->kind == TextboxObject) {
    	if (obj->handle)
	    sendmessage(obj->handle, EM_SETBKGNDCOLOR, 0, wincolour);
    } else {
    	if (obj->bgbrush)
	    DeleteObject(obj->bgbrush);
    	obj->bgbrush = CreateSolidBrush(wincolour);

    	InvalidateRect(obj->handle, NULL, TRUE);
    	redraw(obj);
    }
}

rgb getbackground(control obj)
{
    if (obj)
	return obj->bg;
    else
	return Transparent;
}

void setdata(control obj, void *data)
{
    if (obj)
	obj->data = data;
}

void *getdata(control obj)
{
    if (obj)
	return obj->data;
    else
	return NULL;
}

/* These two are in none of the headers */
#ifdef UNUSED
void _setextradata(control obj, void *data)
{
    if (obj)
	obj->extra = data;
}

void *_getextradata(control obj)
{
    if (obj)
	return obj->extra;
    else
	return NULL;
}
#endif

/*
 *  Set the text of an object. This will set the names appearing
 *  in a window's title bar, a button, checkbox or radio button,
 *  or the value in a textbox or a text field.
 */
void settext(control obj, const char *text)
{
    char *old_text;

    if (! obj)
	return;
    if (! text)
	text = "";
    old_text = GA_gettext(obj);
    if (old_text && strcmp(old_text, text) == 0)
	return; /* no changes to be made */
    if (obj->text) {
	/* discard prior information */
	discard(obj->text);
	obj->text = NULL;
    }
    /* Set the new text. */
    obj->text = new_string(text);
    if (text) {
	if (obj->kind & ControlObject) {
	    text = to_dos_string(text);
	    if(localeCP > 0 && (localeCP != GetACP())) {
		/* This seems not actually to work */
		wchar_t *wc;
		int nc = strlen(text) + 1;
		wc = (wchar_t*) alloca(nc*sizeof(wchar_t));
		mbstowcs(wc, text, nc);
		SetWindowTextW(obj->handle, wc);
	    } else SetWindowText(obj->handle, text);
	    discard(text);
	}
	if (obj->kind == MenuitemObject) {
	    if(localeCP > 0 && (localeCP != GetACP())) {
		/* But this does */
		wchar_t wc[1000];
		mbstowcs(wc, text, 1000);
		ModifyMenuW(obj->parent->handle, obj->id,
			    MF_BYCOMMAND|MF_STRING, obj->id, wc);

	    } else
		ModifyMenu(obj->parent->handle, obj->id,
			   MF_BYCOMMAND|MF_STRING, obj->id, text);
	}

    }
    /* Redraw it if it's a redrawable object. */
    if (obj->call && obj->call->redraw)
	redraw(obj);
}

/*
 *  Get the text string from a window's title bar or from a
 *  control. This may be a button's name, for example, or
 *  the value inside a text field.
 */
char *GA_gettext(control obj)
{
    static char *empty = "";
    char *text;
    int length, index;
    HWND hwnd;
    UINT len_msg, gettext_msg;
    WPARAM arg1, arg2;

    if (! obj)
	return empty;
    if ((obj->kind & ControlObject) == 0)
	return obj->text ? obj->text : empty;

    hwnd = obj->handle;

    switch (obj->kind) {
    case ListboxObject:
    case MultilistObject:
	len_msg = LB_GETTEXTLEN;
	gettext_msg = LB_GETTEXT;
	index = getlistitem(obj);
	if (index < 0) return empty;
	arg1 = arg2 = index;
	break;
    case DroplistObject:
	len_msg = CB_GETLBTEXTLEN;
	gettext_msg = CB_GETLBTEXT;
	index = getlistitem(obj);
	if (index < 0) return empty;
	arg1 = arg2 = index;
	break;
    case DropfieldObject:
	// use default mechanism
    default:
	len_msg = WM_GETTEXTLENGTH;
	gettext_msg = WM_GETTEXT;
	arg1 = 0;
	arg2 = sendmessage(hwnd, len_msg, 0, 0L)+1;
	break;
    }

    /* Free any previous information. */
    if (obj->text)
	discard(obj->text);
    /* Find the length of the string. */
    length = sendmessage(obj->handle, len_msg, arg1, 0L);
    if (length == 0)
	return (obj->text = new_string(NULL));
    /* Copy the text from the object. */
    text = array(length+2, char);
    sendmessage(obj->handle, gettext_msg, arg2, (LPCSTR) text);
    obj->text = to_c_string(text);
    discard(text);
    /* Return the resultant string. */
    if (! obj->text)
	obj->text = new_string(NULL);
    return obj->text;
}

/*
 *  Set the font used by a control.
 */
void settextfont(object obj, font f)
{
    if (! obj)
	return;
    if (! f)
	f = SystemFont;
    if (obj->drawstate) {
	decrease_refcount(obj->drawstate->fnt);
	obj->drawstate->fnt = f;
	increase_refcount(f);
    }
    else {
	sendmessage(obj->handle, WM_SETFONT, f->handle, 0L);
    }
}

/*
 *  Get the font used by a control.
 */
font gettextfont(object obj)
{
    font f = NULL;
    if (obj) {
	if (obj->drawstate)
	    f = obj->drawstate->fnt;
    }
    if (! f)
	f = SystemFont;
    return f;
}

/*
 *  Control and window functions.
 *  Parentwindow of a window is itself.
 */
window parentwindow(control obj)
{
    while (obj) {
	if (obj->kind == WindowObject)
	    break;
	obj = obj->parent;
    }
    return (window) obj;
}

/*
 *  Polymorphic functions:
 */
rect objrect(object obj)
{
    rect r;
    image img;

    if (! obj)
	return rect(0,0,0,0);

    switch (obj->kind)
    {
    case Image8: case Image32:
	img = (image) obj;
	r = rect(0,0,img->width,img->height);
	break;
    case BitmapObject:
    case FontObject:
    case CursorObject:
    case PrinterObject:
	r = obj->rect;
	break;
    case MetafileObject:
	r = obj->rect;
	break;
    default:
	GetClientRect(obj->handle, rect2RECT(&r));
	break;
    }
    return r;
}

int objwidth(object obj)
{
    rect r = objrect(obj);
    return r.width;
}

int objheight(object obj)
{
    rect r = objrect(obj);
    return r.height;
}

int objdepth(object obj)
{
    HDC screendc;
    int depth;

    if (! obj)
	return 0;

    switch (obj->kind)
    {
    case Image8: case Image32:
	depth = ((image)obj)->depth;
	break;
    case BitmapObject:
    case FontObject: case CursorObject:
	depth = obj->depth;
	break;
    default:
	screendc = GetDC(NULL);
	depth = GetDeviceCaps(screendc, BITSPIXEL) *
	    GetDeviceCaps(screendc, PLANES);
	ReleaseDC(NULL, screendc);
	break;
    }

    return depth;
}

void delobj(object obj)
{
    if (! obj)
	return;
    switch (obj->kind)
    {
    case Image8:
    case Image32:
	delimage((image)obj);
	break;
    default:
	/* if (obj->refcount == 1)   why would this test be here?? */
	decrease_refcount(obj);
	break;
    }
}

void setcaret(object obj, int x, int y, int width, int height)
{
    if (! obj)
    	return;
    if (width != obj->caretwidth || height != obj->caretheight) {
	if (obj->caretwidth > 0 && (obj->state & GA_Focus)) DestroyCaret();
	obj->caretwidth = width;
	obj->caretheight = height;
	if (width > 0) {
	    if (obj->state & GA_Focus)
		CreateCaret(obj->handle, (HBITMAP) NULL, width, height);
	    obj->caretshowing = 0;
	}
    }
    if (obj->state & GA_Focus)
    	SetCaretPos(x, y);
}

void showcaret(object obj, int showing)
{
    if (! obj || showing == obj->caretshowing)
    	return;
    obj->caretshowing = showing;
    if (showing)
    	ShowCaret(obj->handle);
    else
    	HideCaret(obj->handle);
}
