#include        <Xm/RowColumn.h>
#include        <Xm/Label.h>
#include        <Xm/PushB.h>

void pasteCB(Widget w, XtPointer *p, XmPushButtonCallbackStruct *s);

XtAppContext app;
Widget paste_label;

int
main(int ac, char *av[])
{
    Widget top, pb, rc;
    Arg shell_args[] = {
	{XmNallowShellResize, True}
    };

    XtSetLanguageProc(NULL, NULL, NULL);
    top = XtAppInitialize(&app, "Sample", NULL, 0, &ac, av, NULL,
			  shell_args, XtNumber(shell_args));

    rc = XmCreateRowColumn(top, "rc", NULL, 0);
    XtManageChild(rc);
    paste_label = XmCreateLabel(rc, "Empty", NULL, 0);
    XtManageChild(paste_label);
    pb = XmCreatePushButton(rc, "Paste", NULL, 0);
    XtManageChild(pb);
    XtAddCallback(pb, XmNactivateCallback,
                  (XtCallbackProc)pasteCB, NULL);

    XtRealizeWidget(top);
    XtAppMainLoop(app);
}

#include <Xm/AtomMgr.h> /* XmInternAtom() */

typedef struct {
    Boolean is_text; /* text型で呼んだか */
    Time time; /* 時刻印 */
} SelectionInfo;

/* 値が得られたときに呼び出されるコールバック関数 */
void get_selectionCB(Widget w, SelectionInfo *p,
		       Atom *selection, Atom *type,
		       XtPointer value, unsigned long *n, int *form);

void
pasteCB(Widget w, XtPointer *p, XmPushButtonCallbackStruct *s)
{
    Atom text = XmInternAtom(XtDisplay(w), "TEXT", False);
    static SelectionInfo info;

    /* Primaryセレクションのownerに変換要求を出し、
       変換結果を受け取る関数を登録する */
    info.is_text = True;
    info.time = s->event->xbutton.time;
    XtGetSelectionValue(w,
	    XA_PRIMARY, /* Primaryセレクションを指定 */
	    text,  /* テキスト変換を指定 */
	    (XtSelectionCallbackProc)
	    get_selectionCB, /* 変換結果を受け取る関数 */
	    &info,  /* その二番目の引数に渡される値 */
	    info.time /* 要求の発生時刻 */);
}

void
get_selectionCB(Widget w, SelectionInfo *info,
		Atom *selection, Atom *type,
		XtPointer value, unsigned long *n, int *form)
{
    Atom ctext = XmInternAtom(XtDisplay(w), "COMPOUND_TEXT", False);
    String str;
    XmString xms;
    char **items = NULL;
    int nitems;

    if (*type == 0 /* 変換に失敗 */|| *n == 0 /* データがない */) {
	if (info->is_text) {
	    info->is_text = False;
	    /* 文字列型を指定してやり直し */
	    XtGetSelectionValue(w,
		    XA_PRIMARY,
		    XA_STRING,
		    (XtSelectionCallbackProc)get_selectionCB,
		    info,
		    info->time);
	    return;
	}
	/* セレクションが指定されていない */
	str = "Empty";
    } else if (*type == ctext) {
	XTextProperty prop = {value, ctext, 8, strlen(value)};

	/* マルチバイト文字列に変換 */
	if (XmbTextPropertyToTextList(XtDisplay(w),
				      &prop, &items, &nitems) != Success)
	    /* 怪しいCOMPUND_TEXTだった */
	    str = "Error";
	else
	    str = items[0];
    } else {
	/* *type == XA_STRING */
	str = value;
    }

    /* Labelウィジェットに設定する */
    xms = XmStringCreateLtoR(str, XmFONTLIST_DEFAULT_TAG);
    XtVaSetValues(paste_label, XmNlabelString, (XtArgVal)xms, NULL);
    XmStringFree(xms);

    if (value) XFree(value);
    if (items) XFreeStringList(items);
}
