/*
 * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

#if MOTIF_VERSION!=2
    #error This file should only be compiled with motif 2.1
#endif

#include "awt_motif.h"
#include <Xm/Xm.h>
#include "awt.h"
#include "awt_p.h"
#include "awt_Component.h"

#define XmPER_SHELL 0
extern int32_t _XmImGetGeo(
                        Widget vw) ;

#define MAXARGS 10
static Arg xic_vlist[MAXARGS];

#define SEPARATOR_HEIGHT        2
#define MTEXTAREAPEER_CLASS_NAME        "sun/awt/motif/MTextAreaPeer"
extern struct MComponentPeerIDs mComponentPeerIDs;
static jobject  mTextAreaClass = NULL;

/*
 * Get the Motif text widget from the text component peer.  XmImGetXIC()
 * function should be issued on Motif text widgets.
 */
static Widget getTextWidget(jobject tc) {
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);

    if (mTextAreaClass == NULL) {
        jclass localClass = (*env)->FindClass(env, MTEXTAREAPEER_CLASS_NAME);
        mTextAreaClass = (jclass)(*env)->NewGlobalRef(env, localClass);
        (*env)->DeleteLocalRef(env, localClass);
    }

    if ((*env)->IsInstanceOf(env, tc, mTextAreaClass)) {
        struct TextAreaData * tdata = (struct TextAreaData *)
        JNU_GetLongFieldAsPtr(env, tc, mComponentPeerIDs.pData);
        return tdata->txt;
    } else {
        struct ComponentData * tdata = (struct ComponentData *)
        JNU_GetLongFieldAsPtr(env, tc, mComponentPeerIDs.pData);
        return tdata->widget;
    }
}

/* get_im_height: returns height of the input method status area in pixels.
 *
 * This function assumes that if any XIM related information cannot be
 * queried then the app must not have an input method status area in the
 * current locale and returns zero as the status area height
 */
int32_t
awt_motif_getIMStatusHeight(Widget w, jobject tc)
{
    XIC xic = NULL;
    XRectangle *im_rect=NULL;
    int32_t im_height = 0;
    char *ret;

    xic = XmImGetXIC(getTextWidget(tc), XmPER_SHELL, NULL, 0);

    if(xic != NULL) {
        /* finally query the server for the status area geometry */
        xic_vlist[0].name = XNArea;
        xic_vlist[0].value = (XtArgVal)&im_rect;
        xic_vlist[1].name = NULL;
        ret=XGetICValues(xic, XNStatusAttributes, &xic_vlist[0], NULL);
        if (ret == NULL && im_rect != NULL) {
            im_height = im_rect->height;
            if (im_height > 0) {
                im_height += SEPARATOR_HEIGHT;
            }
            XFree(im_rect);
        } else {
            im_height = 0;
        }
    }

    if (im_height == 0) {
        im_height = _XmImGetGeo(w);
    }

#if defined(DEBUG)
    jio_fprintf(stderr,"awt_motif_getIMStatusHeight: Height = %d",im_height);
#endif
    return im_height;
}


static XRectangle geomRect;
static Pixmap bpm;
XVaNestedList awt_motif_getXICStatusAreaList(Widget w, jobject tc)
{
    XIC xic;

    XRectangle *im_rect;
    XFontSet   *im_font;

    Pixel bg ;
    Pixel fg ;
    Dimension height, width ;
    Position x,y ;

    XVaNestedList list = NULL;

    char *ret;
    Widget p=w;

    while (!XtIsShell(p)) {
        p = XtParent(p);
    }

    XtVaGetValues(p,
        XmNx, &x,
        XmNy, &y,
        XmNwidth, &width,
        XmNheight, &height,
        XmNbackgroundPixmap, &bpm,
        NULL);



    xic = XmImGetXIC(getTextWidget(tc), XmPER_SHELL, NULL, 0);
    if(xic == NULL)
    {
#if defined DEBUG
        jio_fprintf(stderr,"Could not get XIC");
#endif
        return list ;
    }

   /* finally query the server for the required attributes area geometry */
    xic_vlist[0].name = XNFontSet ;
    xic_vlist[0].value =  (XtArgVal) &im_font ;
    xic_vlist[1].name = XNArea;
    xic_vlist[1].value = (XtArgVal) &im_rect;
    xic_vlist[2].name = XNBackground ;
    xic_vlist[2].value = (XtArgVal) &bg ;
    xic_vlist[3].name = XNForeground ;
    xic_vlist[3].value = (XtArgVal) &fg ;
    xic_vlist[4].name = NULL;


    if(ret=XGetICValues(xic, XNStatusAttributes, &xic_vlist[0], NULL))
    {
        return list ;
    } else {
        geomRect.x = 0 ;
        geomRect.y = height - im_rect->height ;
        geomRect.width = im_rect->width ;
        geomRect.height = im_rect->height ;
        XFree(im_rect) ;

        list = XVaCreateNestedList(0 ,
                        XNFontSet, im_font ,
                        XNArea, &geomRect ,
                        XNBackground, bg ,
                        XNForeground, fg ,
                        XNBackgroundPixmap, &bpm ,
                        NULL );
    }
#if defined(DEBUG)
    jio_fprintf(stderr,"awt_motif_getXICStatusAreaList:\n");
    jio_fprintf(stderr,"XNArea:x=%d,y=%d,width=%d,height=%d\n", \
         geomRect.x,geomRect.y,geomRect.width,geomRect.height);
    jio_fprintf(stderr,"XNBackground=0x%x\n",bg);
    jio_fprintf(stderr,"XNForeground=0x%x\n",fg);
    jio_fprintf(stderr,"XNBackgroundPixmap=0x%x\n",bpm);
#endif
    return list ;

}

    /* This function causes an UnsatisfiedLinkError on Linux.
     * Since Linux only links against Motif 2.1 and under 2.1 this function
     * is a no-op, we can safely remove
     * this function altogether from the Linux build.
     * bchristi 1/22/2001
     */

#ifdef __solaris__
void
awt_motif_adjustDragTriggerEvent(XEvent* xevent) {
    /* Do nothing. In Motif 2.1 the sanity check is corrected
       to allow any imput event as a drag trigger event. */
}
#endif /* __solaris__ */

static void
CheckDragInitiator(Widget w, XtPointer client_data,
                   XmDragStartCallbackStruct* cbstruct) {
    Widget drag_initiator = (Widget)client_data;
    /*
     * Fix for BugTraq ID 4407057.
     * Enable the drag operation only if it is registered on the specific
     * widget. We use this check to disable Motif default drag support.
     */
    if (drag_initiator != cbstruct->widget) {
        cbstruct->doit = False;
    }
}

void
awt_motif_enableSingleDragInitiator(Widget w) {
    XtAddCallback(XmGetXmDisplay(XtDisplay(w)),
                  XmNdragStartCallback, (XtCallbackProc)CheckDragInitiator,
                  (XtPointer)w);
}
