/**
 *
 * $Id: ComboBox.c,v 1.6 1997/09/04 22:41:10 u27113 Exp $
 *
 * Copyright (C) 1997 Free Software Foundation, Inc.
 *
 * This file is part of the GNU LessTif Library.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the Free
 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 **/

static char rcsid[] = "$Id: ComboBox.c,v 1.6 1997/09/04 22:41:10 u27113 Exp $";

#include <LTconfig.h>
#include <XmI/XmI.h>

#include <Xm/XmP.h>
#include <Xm/ListP.h>
#include <Xm/TextF.h>
#include <Xm/GrabShell.h>
#include <Xm/ComboBoxP.h>
#include <Xm/TransltnsP.h>

#include <XmI/MessagesI.h>
#include <XmI/DebugUtil.h>

/* 
REMARK:

This widget is under construction.

END:
*/

/* Forward Declarations */
static void CallSelectionCallbacks(Widget w, 
   XtPointer client_data, 
   XtPointer data);
static void CBActivate(Widget w, 
   XEvent *xev, 
   String *params, 
   Cardinal *num_params);
static void CBArmAndDropDownList(Widget w, 
   XEvent *xev, 
   String *params, 
   Cardinal *num_params); 
static void CBCancel(Widget w,
   XEvent *xev, 
   String *params, 
   Cardinal *num_params);
static void CBDisarm(Widget w,
   XEvent *xev, 
   String *params, 
   Cardinal *num_params);
static void CBDropDownList(Widget w, 
   XEvent *xev, 
   String *params, 
   Cardinal *num_params);
static void CBFocusIn(Widget w,
   XEvent *xev, 
   String *params, 
   Cardinal *num_params);
static void CBFocusOut(Widget w,
   XEvent *xev, 
   String *params, 
   Cardinal *num_params);
static void CBGetSelectedItem(Widget w,
   XEvent *xev, 
   String *params, 
   Cardinal *num_params);
static void CBGetSelectedPos(Widget w,
   XEvent *xev, 
   String *params, 
   Cardinal *num_params);
static void CBListAction(Widget w,
   XEvent *xev, 
   String *params, 
   Cardinal *num_params);
static void CBSetSelectedItem(Widget w,
   XEvent *xev, 
   String *params, 
   Cardinal *num_params);
static void CBSetSelectedPos(Widget w,
   XEvent *xev, 
   String *params, 
   Cardinal *num_params);
static void CBTextFocusOut(Widget w,
   XEvent *xev, 
   String *params, 
   Cardinal *num_params);
static void ChangeManaged(Widget w);
static void CheckMinimalSize(Widget w, XtWidgetGeometry *reply);
static void CheckSetRenderTable(Widget w);
static void ClassInitialize();
static void ClassPartInitialize(WidgetClass class);
static void ComboBoxParentProcess(Widget w);
static void ComputeSize(Widget w, XtWidgetGeometry *reply);
static void ConstraintDestroy(Widget w);
static void CreateArrowGC(Widget w);
static void CreateChildren(Widget w);
static void CreateEditBox(Widget parent);
static void CreatePulldown(Widget parent);
static void CreateScrolledList(Widget cb);
static void Destroy(Widget w);
static void DoLayout(Widget w);
static void DrawArrow(Widget w);
static void DrawShadows(Widget w);
static Widget FindComboBox(Widget w);
static void FocusMovedCB(Widget w, XtPointer client_data, XtPointer data);
static XtGeometryResult GeometryManager(Widget w, 
   XtWidgetGeometry *request, 
   XtWidgetGeometry *reply);
static void GetDefaultArrowSize(Widget w);
static XmString GetEditBoxValue(Widget w);
static void GetIdealTextSize(Widget w);
static void GetThickness(Widget w);
static void HighlightBorder(Widget w);
static void Hit(Widget w);
static void Initialize(Widget request, 
   Widget c_new,
   ArgList args,
   Cardinal *num_args);
static void InsertChild(Widget w);
static void ListSelectionCB(Widget w, XtPointer client_data, XtPointer data);
static void PopdownList(Widget w);
static void PopupEH(Widget w, XtPointer udata, XEvent *xev, Boolean *pb);
static XtGeometryResult QueryGeometry(Widget w, 
   XtWidgetGeometry *proposed, 
   XtWidgetGeometry *answer);
static void Redisplay(Widget w, XEvent *event, Region region);
static void Reduce(Widget w);
static void ReduceResources(Widget w);
static void Resize(Widget w);
static void SBBtnDownEH(Widget w, XtPointer udata, XEvent *xev, Boolean *pb);
static void SBBtnUpEH(Widget w, XtPointer udata, XEvent *xev, Boolean *pb);
static void SetEditBoxValue(Widget w, XmString s);
static void SetHitArea(Widget w);
static Boolean SetValues(Widget current, 
   Widget request, 
   Widget c_new, 
   ArgList args,
   Cardinal *num_args);
static void ShellPopdownCB(Widget w, XtPointer client_data, XtPointer data);
static void ShellPopupCB(Widget w, XtPointer client_data, XtPointer data);
static void TextChangedCB(Widget w, XtPointer client_data, XtPointer data);
static void UnhighlightBorder(Widget w);

#define VALID(w) (w && XtIsManaged(w))
#define Unused(x) (void)(x)
#define superclass (&xmManagerClassRec)
#define Offset(field) XtOffsetOf(XmComboBoxRec, combo_box.field)

/* class names for private widgets */
#define CB_LIST_CN "List"
#define CB_LIST_SHELL_CN "GrabShell"
#define CB_TEXT_CN "Text"

/* FIXTHIS: This belongs in MacrosI.h */
#define CB_ArrowGC(w) \
    (((XmComboBoxWidget)(w))->combo_box.arrow_GC)

#define CB_IdealEBHeight(w) \
    (((XmComboBoxWidget)(w))->combo_box.ideal_ebheight)

#define CB_IdealEBWidth(w) \
    (((XmComboBoxWidget)(w))->combo_box.ideal_ebwidth)


/* ========================================================================== */
/* Resources for the ComboBox class */
static XtResource resources[] = {

   {
     XmNarrowSize,
     XmCArrowSize,
     XmRHorizontalDimension,
     sizeof(Dimension),
     Offset(arrow_size),
     XmRImmediate,
     (XtPointer)0
   },

   {
     XmNarrowSpacing,
     XmCArrowSpacing,
     XmRHorizontalDimension,
     sizeof(Dimension),
     Offset(arrow_spacing),
     XmRImmediate,
     (XtPointer)0
   },

   {
     XmNcomboBoxType,
     XmCComboBoxType,
     XmRComboBoxType,
     sizeof(unsigned char),
     Offset(type),
     XmRImmediate, 
     (XtPointer)XmCOMBO_BOX
   },

   {
     XmNfontList,
     XmCFontList,
     XmRFontList,
     sizeof(XmFontList),
     Offset(render_table),
     XmRImmediate,
     (XtPointer)NULL
   },

   {
     XmNhighlightThickness,
     XmCHighlightThickness,
     XmRHorizontalDimension,
     sizeof(Dimension),
     Offset(highlight_thickness),
     XmRImmediate,
     (XtPointer)2
   },

   {
     XmNmarginWidth,
     XmCMarginWidth,
     XmRHorizontalDimension,
     sizeof(Dimension),
     Offset(margin_width),
     XmRImmediate, 
     (XtPointer)2
   },

   {
     XmNmarginHeight,
     XmCMarginHeight, 
     XmRVerticalDimension,
     sizeof(Dimension), 
     Offset(margin_height),
     XmRImmediate, 
     (XtPointer)2
   },

   {
     XmNmatchBehavior,
     XmCMatchBehavior,
     XmRMatchBehavior,
     sizeof(unsigned char),
     Offset(match_behavior),
     XmRImmediate,
     (XtPointer)XmNONE
   },

   {
     XmNrenderTable,
     XmCRenderTable,
     XmRRenderTable,
     sizeof(XmRenderTable), 
     Offset(render_table),
     XmRImmediate,
     (XtPointer)NULL
   },

   {
     XmNselectedItem,
     XmCSelectedItem,
     XmRXmString,
     sizeof(XmString), 
     Offset(selected_item),
     XmRImmediate,
     (XtPointer)NULL
   },

   {
     XmNselectedPosition,
     XmCSelectedPosition,
     XmRInt,
     sizeof(int), 
     Offset(selected_position),
     XmRImmediate,
     (XtPointer)0
   },

   {
     XmNselectionCallback,
     XmCCallback, 
     XtRCallback,
     sizeof(XtCallbackList),
     Offset(selection_callback),
     XmRImmediate,
     (XtPointer)NULL
   },

   {
     XmNshadowThickness,
     XmCShadowThickness,
     XmRHorizontalDimension,
     sizeof(Dimension),
     XtOffsetOf(XmComboBoxRec, manager.shadow_thickness),
     XmRImmediate,
     (XtPointer)2
   },

};

static XmSyntheticResource syn_resources[100];/* = {*/
   /* FIXTHIS: */
/*};*/

/* these get set in one of the initialize functions */
static XtTranslations parsed_list_translations;
static XtTranslations parsed_text_focus_translations;

static XtAccelerators parsed_accelerators;
static XtAccelerators parsed_list_accelerators;

/* Action table */
static XtActionsRec actionsList[] = {
   {"CBFocusIn", (XtActionProc) CBFocusIn},
   {"CBFocusOut", (XtActionProc) CBFocusOut},
   {"CBActivate", (XtActionProc) CBActivate},
   {"CBArmAndDropDownList", (XtActionProc) CBArmAndDropDownList},
   {"CBCancel", (XtActionProc) CBCancel},
   {"CBDisarm", (XtActionProc) CBDisarm},
   {"CBDropDownList", (XtActionProc) CBDropDownList},
   {"CBListAction", (XtActionProc) CBListAction},
   {"CBTextFocusOut", (XtActionProc) CBTextFocusOut},
};

/* ========================================================================== */
/* Class record */

XmComboBoxClassRec xmComboBoxClassRec = {
   /* Core class part */
   {
      (WidgetClass) &xmManagerClassRec,       /* superclass */
      "XmComboBox",                           /* class_name */
      sizeof(XmComboBoxRec),                  /* widget_size */
      ClassInitialize,                        /* class_initialize */
      ClassPartInitialize,                    /* class_part_initialize */
      FALSE,                                  /* class_inited */
      Initialize,                             /* initialize */
      NULL,                                   /* initialize_hook */
      0,/***********XtInheritRealize,*/                       /* realize */
      actionsList,                            /* actions */
      XtNumber(actionsList),                  /* num_actions */
      resources,                              /* resources */
      XtNumber(resources),                    /* num_resources */
      NULLQUARK,                              /* xrm_class */
      TRUE,                                   /* compress_motion */
      XtExposeCompressMaximal,                /* compress_exposure */
      TRUE,                                   /* compress_enterleave */
      FALSE,                                  /* visible_interest */
      Destroy,                                /* destroy */
      Resize, /* XtInheritResize,  */         /* resize */
      Redisplay, /* XtInheritExpose,  */      /* expose */
      SetValues,                              /* set_values */
      NULL,                                   /* set_values_hook */
      0,/*********XtInheritSetValuesAlmost,*/               /* set_values_almost */
      NULL,                                   /* get_values_hook */
      NULL,                                   /* accept_focus */
      XtVersion,                              /* version */
      NULL,                                   /* callback offsets */
      0,/**********XtInheritTranslations,*/                  /* tm_table */
      QueryGeometry,                          /* query_geometry */
      NULL,                                   /* display_accelerator */
      NULL                                    /* extension */ 
   },
   /* Composite class part */
   {
      GeometryManager,        /* geometry manager */
      ChangeManaged,          /* ChangeManaged */
      InsertChild,            /* insert_child */ 
      0,/**********XtInheritDeleteChild,*/   /* delete_child */ 
      NULL                    /* extension */ 
   },
   /* Constraint class part */
   {
      NULL,      /* FIXTHIS: */ /* subresources */
      0,         /* FIXTHIS: */ /* subresource_count */
      0,         /* FIXTHIS: */ /* constraint_size */
      NULL,      /* FIXTHIS: */ /* Initialize */
      ConstraintDestroy,        /* Destroy */
      NULL,      /* FIXTHIS: */ /* set_values */
      NULL                      /* extension */ 
   },
   /* XmManager class part */
   {
      NULL,                   /* translations */ 
      syn_resources,          /* syn_resources */ 
      XtNumber(syn_resources),/* num_syn_resources */
      NULL,                   /* syn_constraint_resources */ 
      0,                      /* num_syn_constraint_resources */
      0,/*********XmInheritParentProcess,*/ /* parent process */
      NULL                    /* extension */ 
   },
   /* XmComboBox class part */
   {
      NULL                    /* extension */ 
   }
};

int AMIWIN_ComboBox(void)
{
xmComboBoxClassRec.realize=XtInheritRealize;
xmComboBoxClassRec.set_values_almost=XtInheritSetValuesAlmost;
xmComboBoxClassRec.tm_table=AMIWIN_XtInheritTranslations;
xmComboBoxClassRec.delete_child=XtInheritDeleteChild;
xmComboBoxClassRec.parent_process=XmInheritParentProcess;
return(0);
}


WidgetClass xmComboBoxWidgetClass = (WidgetClass) &xmComboBoxClassRec;

/* ========================================================================== */
/* functions */
/*
  FUNCTION: CallSelectionCallbacks
  SYNOPSIS: static void CallSelectionCallbacks(Widget w, XtPointer client_data, XtPointer data)
  DESCRIPTION:
  This function calls all XmNselectionCallback routines set by the application.
  END:

  FIXTHIS: Does this need to have a XtCallbackProc signature?
*/
static void
CallSelectionCallbacks(Widget w, XtPointer client_data, XtPointer data)
{
   XmComboBoxCallbackStruct cbs;
   XmString v; 

   Unused(client_data);

   if (CB_SelectionCB(w))
   {
      /* This is stored in a local because I don't trust programmers. ;^) */
      v = GetEditBoxValue(w); 

      /* Set default values. */
      cbs.reason = XmCR_SELECT;
      cbs.event = NULL;
      cbs.item_or_text = v;
      cbs.item_position = 0;

      /* Override default values if data was passed in. */
      if (data)
      {
         cbs.event = ((XmAnyCallbackStruct *) data)->event;

         if (((XmAnyCallbackStruct *) data)->reason == XmCR_BROWSE_SELECT)
         {
            cbs.item_position = ((XmListCallbackStruct *)data)->item_position;
         }
      }

      XtCallCallbackList(w,CB_SelectionCB(w),(XtPointer)&cbs);

      XmStringFree(v);
   }
}

static void 
CBActivate(
   Widget w, 
   XEvent *event, 
   String *params, 
   Cardinal *num_params)
{
   #if 0
   FindComboBox();
   ComboBoxParentProcess();
   #endif
}

static void 
CBArmAndDropDownList(
   Widget w, 
   XEvent *event,
   String *params, 
   Cardinal *num_params)
{
   #if 0
   FindComboBox(); 
   Hit();
   DrawArrow();
   CBDropDownList();
   #endif
}

static void 
CBCancel(
   Widget w, 
   XEvent *event,
   String *params, 
   Cardinal *num_params)
{
   #if 0
   FindComboBox();
   ComboBoxParentProcess();
   #endif
}

static void 
CBDisarm(
   Widget w,
   XEvent *event,
   String *params, 
   Cardinal *num_params)
{
   #if 0
   FindComboBox();
   DrawArrow();
   #endif
}

static void 
CBDropDownList(
   Widget w, 
   XEvent *event,
   String *params, 
   Cardinal *num_params)
{
   #if 0
   FindComboBox();
   PopdownList();
   CBDisarm();
   #endif
}


static void 
CBFocusIn(Widget w, XEvent *event, String *params, Cardinal *num_params)
{
   #if 0
   FindComboBox();
   HighlightBorder(w);
   #endif
}

static void 
CBFocusOut(Widget w, XEvent *event, String *params, Cardinal *num_params)
{
   #if 0
   FindComboBox();
   UnhighlightBorder(w);
   CallSelectionCallbacks(); 
   #endif
}

static void 
CBGetSelectedItem(
   Widget w, 
   XEvent *event,
   String *params, 
   Cardinal *num_params)
{
   #if 0
   GetEditBoxValue();
   #endif
}

static void 
CBGetSelectedPos(
   Widget w, 
   XEvent *event,
   String *params, 
   Cardinal *num_params)
{
}
   
static void 
CBListAction(
   Widget w, 
   XEvent *event,
   String *params, 
   Cardinal *num_params)
{
   #if 0
   FindComboBox();
   #endif
}

static void 
CBSetSelectedItem(
   Widget w, 
   XEvent *event,
   String *params, 
   Cardinal *num_params)
{
   #if 0
   GetEditBoxValue();
   SetEditBoxValue();
   #endif
}

static void 
CBSetSelectedPos(
   Widget w, 
   XEvent *event,
   String *params, 
   Cardinal *num_params)
{
}

static void 
CBTextFocusOut(
   Widget w,
   XEvent *event,
   String *params, 
   Cardinal *num_params)
{
   #if 0
   FindComboBox();
   #endif
}

/*
  FUNCTION: ChangeManaged
  SYNOPSIS: static void ChangeManaged(Widget w)
  DESCRIPTION:
  This function performs a layout if the combo box is managed.  
  Otherwise it just returns. 
  END:
*/
static void 
ChangeManaged(Widget w)
{
   XtWidgetGeometry geo;
   XtGeometryResult result;

   XdbDebug(__FILE__, w, "ChangeManaged ...\n");

   if (!XtIsManaged(w))
   {
      return;
   }

   /* FIXTHIS: When should the check for minimal size be called? */
   if (1)
   {
      ComputeSize(w, &geo);
   }
   else
   {
      CheckMinimalSize(w, &geo);
   }

   /* Make geometry request to parent */
   result = _XmMakeGeometryRequest(w, &geo);

   if (result != XtGeometryNo)
   {
      XtWidth(w) = geo.width;
      XtHeight(w) = geo.height;
   }

   ReduceResources(w); 

   DoLayout(w);
}

/*
  FUNCTION: CheckMinimalSize
  SYNOPSIS: static void CheckMinimalSize(Widget w, XtWidgetGeometry *reply);
  DESCRIPTION:
  This function does not check but returns the minimal size.
  END:
*/
static void
CheckMinimalSize(Widget w, XtWidgetGeometry *reply)
{
   reply->request_mode = (CWWidth|CWHeight);

   reply->width = 0;
   reply->height = 0;

   if (CB_Type(w) != XmCOMBO_BOX) 
   {
      GetDefaultArrowSize(w); 

      reply->width += CB_HitRect(w).width;
      reply->height += CB_HitRect(w).height;

      /* don't forget to include the arrow spacing to the width */
      reply->width += CB_ArrowSpacing(w);
   }
}

static void
CheckSetRenderTable(Widget w)
{
   /* FIXTHIS: CheckSetRenderTable needs to be implemented */
   Unused(w);
}

/*
  FUNCTION: ClassInitialize
  SYNOPSIS: static void ClassInitialize()
  DESCRIPTION:
  This function initialize class data.
  END:
*/
static void
ClassInitialize()
{
   /* parse translations */
   parsed_list_translations = XtParseTranslationTable(
      _XmComboBox_dropDownListTranslations);

   parsed_text_focus_translations = XtParseTranslationTable(
      _XmComboBox_textFocusTranslations);

   /* parse accelerators */
   parsed_accelerators = XtParseAcceleratorTable(
      _XmComboBox_defaultAccelerators);

   parsed_list_accelerators = XtParseAcceleratorTable(
      _XmComboBox_dropDownComboBoxAccelerators);
}

static void
ClassPartInitialize(WidgetClass widget_class)
{
   Unused(widget_class);
}

static void
ComboBoxParentProcess(Widget w)
{
   /* FIXTHIS: ComboBoxParentProcess needs to be implemented. */
   Unused(w);

   #if 0
   PopdownList();
   CBDisarm();
   GetEditBoxValue();
   CallSelectionCallbacks();
   #endif
}

/*
  FUNCTION: ComputeSize
  SYNOPSIS: static void ComputeSize(Widget w, XtWidgetGeometry *)
  DESCRIPTION:
  This function determines how big the ComboBox needs to be.
  END:
*/
static void
ComputeSize(Widget w, XtWidgetGeometry *reply)
{
   XdbDebug(__FILE__, w, "ComputeSize ...\n");

   reply->request_mode = (CWWidth|CWHeight);
   reply->width = 0;
   reply->height = 0;

   GetIdealTextSize(w);

   /* add the size of edit box */
   reply->width += CB_IdealEBWidth(w);
   reply->height += CB_IdealEBHeight(w);

   /* add the width and spacing for the arrow button */
   if (CB_Type(w) != XmCOMBO_BOX) 
   {
      XdbDebug(__FILE__, w, "ComputeSize: arrow_spacing(%d) ...\n", 
               CB_ArrowSpacing(w));
      XdbDebug(__FILE__, w, "ComputeSize: arrow_size(%d) ...\n",
               CB_ArrowSize(w));

      reply->width += CB_ArrowSpacing(w);
      reply->width += CB_ArrowSize(w);
   }
   /* add the height of scrolled window if type is XmCOMBO_BOX */
   else 
   {
      /*
         REMARK:
         06/2/97: The initial scrolled window widget geometry is incorrect.  
         Hence, the size computed by this function will be incorrect.  Don't
         try to fix this function.  The problem is with the scrolled window 
         geometry.  Test 14 in directory test/Xm/scrolledwindow demonstrates 
         the problem.
         END:
      */
      reply->height += XtHeight(CB_ScrolledW(w)); 
   }
   /* adjust for margins */
   reply->width += 2 * CB_MarginWidth(w);
   reply->height += 2 * CB_MarginHeight(w);

   /* adjust for highlight thickness */
   reply->width += 2 * CB_HighlightThickness(w);
   reply->height += 2 * CB_HighlightThickness(w);

   /* adjust for shadow thickness */
   reply->width += 2 * MGR_ShadowThickness(w);
   reply->height += 2 * MGR_ShadowThickness(w);
}

static void
ConstraintDestroy(Widget w)
{
   XdbDebug(__FILE__, w, "ConstraintDestroy ...\n");

   /* FIXTHIS: ConstraintDestroy needs to be implemented. */
   Unused(w);
}

/*
  FUNCTION: CreateArrowGC
  SYNOPSIS: static void CreateArrowGC(Widget w)
  DESCRIPTION:
  This function creates the arrow GC.
  END:
*/
static void
CreateArrowGC(Widget w)
{
   XGCValues values;
   XtGCMask mask;

   XdbDebug(__FILE__, w, "CreateArrowGC ...\n");

   mask = GCForeground | GCBackground;

   /* values.foreground = MGR_Foreground(w); */
   values.foreground = XtBackground(w);
   values.background = XtBackground(w);

   /* these GC's get used for shadow drawing, so set 'em up */
   mask |= GCLineWidth | GCLineStyle | GCJoinStyle | GCCapStyle;
   values.line_width = 1;
   values.line_style = LineSolid;
   values.join_style = JoinMiter;
   values.cap_style = CapButt;

   CB_ArrowGC(w) = XtGetGC(w, mask, &values);
}

/*
  FUNCTION: CreateChildren
  SYNOPSIS: static void CreateChildren(Widget w)
  DESCRIPTION:
  This function calls other functions which create the children 
  of the combobox widget.
  END:
*/
static void
CreateChildren(Widget w)
{
   XdbDebug(__FILE__, w, "CreateChildren ...\n");

   CreateEditBox(w);
   CreatePulldown(w);
   CreateScrolledList(w);
}

/*
  FUNCTION: CreateEditBox
  SYNOPSIS: static void CreateEditBox(Widget w)
  DESCRIPTION:
  This function creates the text field widget for the combobox widget.
  END:
*/
static void
CreateEditBox(Widget w)
{
   Widget text;
   Arg args[10];
   int n = 0;
 
   XdbDebug(__FILE__, w, "CreateEditBox ...\n");

   if (CB_Type(w) == XmDROP_DOWN_LIST)
   {  /* force these settings */
      XtSetArg(args[n], XmNeditable, False); n++;
      XtSetArg(args[n], XmNcursorPositionVisible, False); n++;
      XtSetArg(args[n], XmNshadowThickness, False); n++;
   }
   if (CB_Type(w) == XmCOMBO_BOX
       || CB_Type(w) == XmDROP_DOWN_COMBO_BOX)
   {  /* force these settings */
      XtSetArg(args[n], XmNeditable, True); n++;
      XtSetArg(args[n], XmNcursorPositionVisible, True); n++;
      XtSetArg(args[n], XmNeditMode, XmSINGLE_LINE_EDIT); n++;
   }

   XtSetArg(args[n], XmNnavigationType, XmNONE); n++;
   XtSetArg(args[n], XmNhighlightThickness, 0); n++;
   XtSetArg(args[n], XmNborderWidth, 0); n++;
            
   text = XmCreateTextField(w, CB_TEXT_CN, args, n);
   XtManageChild(text);
}

/*
  FUNCTION: CreatePulldown
  SYNOPSIS: static void CreatePulldown(Widget w)
  DESCRIPTION:
  This function creates a GrabShell widget for the combobox widget if
  the type is not XmCOMBO_BOX.  If the type is XmCOMBO_BOX the list_shell 
  member in the XmComboBoxPart structure will be set to the combobox widget. 
  END:

  FIXTHIS: Confirm if Motif 2.0 does it this way.
*/
static void
CreatePulldown(Widget w)
{

   XdbDebug(__FILE__, w, "CreatePulldown ...\n");

   if (CB_Type(w) == XmDROP_DOWN_LIST
       || CB_Type(w) == XmDROP_DOWN_COMBO_BOX)
   {
      /* Despite the function name a GrabShell widget is used */
      CB_ListShell(w) = XmCreateGrabShell(w,CB_LIST_SHELL_CN,NULL,0);
   }
   else /* if (CB_Type(w) == XmCOMBO_BOX) then make self the list shell */
   {
      CB_ListShell(w) = w;
   }
}

/*
  FUNCTION: CreateScrolledList
  SYNOPSIS: static void CreateScrolledList(Widget parent)
  DESCRIPTION:
  This function creates the scrolled list widget for the combobox widget.
  END:
*/
static void
CreateScrolledList(Widget cb)
{
   Arg args[15];
   int n = 0;

   XdbDebug(__FILE__, cb, "CreateScrolledList ...\n");

   /* force settings */
   if (CB_Type(cb) == XmCOMBO_BOX)
   {  
      XtSetArg(args[n], XmNtraversalOn, False); n++;
   }

   if (CB_Type(cb) == XmDROP_DOWN_COMBO_BOX)
   {
      XtSetArg(args[n], XmNhighlightThickness, 2); n++;
   }
   else
   {
      XtSetArg(args[n], XmNhighlightThickness, 0); n++;
   }

   XtSetArg(args[n], XmNborderWidth, 0); n++;
   XtSetArg(args[n], XmNnavigationType, XmNONE); n++;
   XtSetArg(args[n], XmNselectionPolicy, XmBROWSE_SELECT); n++;
   XtSetArg(args[n], XmNlistSizePolicy, XmVARIABLE); n++;
   XtSetArg(args[n], XmNspacing, 0); n++;
   XtSetArg(args[n], XmNvisualPolicy, XmVARIABLE); n++;
   XtSetArg(args[n], XmNselectedPositions, NULL); n++;
   XtSetArg(args[n], XmNselectedItemCount, 0); n++;

   /* 
      REMARK:
      XmCreateScrolledList returns an unmanage list. 
      The parent of the list is a managed scrolled window.
      END:
    */
   CB_List(cb) = XmCreateScrolledList(CB_ListShell(cb),CB_LIST_CN,args,n);
   XtManageChild(CB_List(cb));

   /* This may cause a problem if XtParent is a macro */
   CB_ScrolledW(cb) = XtParent(CB_List(cb));

   /* Setup callback for combobox. */
   XtAddCallback(CB_List(cb),
                 XmNbrowseSelectionCallback, 
                 (XtCallbackProc) ListSelectionCB,
                 (XtPointer) cb);

   #if 0
   SetEditBoxValue();
   #endif
}

/*
  FUNCTION: Destroy
  SYNOPSIS: static void Destroy(Widget w)
  DESCRIPTION:
  This function releases allocated memory done by the widgets instance.
  END:
*/
static void
Destroy(Widget w)
{

   XdbDebug(__FILE__, w, "Destroy ...\n");

   /* release GC's */
   XtReleaseGC(w,CB_ArrowGC(w));
}

/*
  FUNCTION: DoLayout
  SYNOPSIS: static void DoLayout(Widget w)
  DESCRIPTION:
  This function repositions child windows according to its own geometry.
  END:
*/
static void
DoLayout(Widget w)
{
   int x, y;

   XdbDebug(__FILE__, w, "DoLayout ...\n");

   /* layout children */
   /*
      FIXTHIS: Confirm if docs are correct.
      REMARK:
      The placement of the arrow button depends on the resource
      XmNlayoutDirection according to the documentation. 
      This resource is new to 2.0 and lives in the manager widget.  
      This will be implemented at a later date.  For now the button will 
      always be on the right side.
      END:
   */

   /* perform x,y adjustments to children */ 
   x = y = 0;

   x += CB_MarginWidth(w);
   y += CB_MarginHeight(w);

   x += CB_HighlightThickness(w);
   y += CB_HighlightThickness(w);

   x += MGR_ShadowThickness(w);
   y += MGR_ShadowThickness(w);

   /* configure the edit box */
   XmeConfigureObject(CB_EditBox(w),
                      x,
                      y,
                      XtWidth(CB_EditBox(w)),
                      XtHeight(CB_EditBox(w)),
                      XtBorderWidth(CB_EditBox(w)));

   /* Setup the hit area for the pseudo arrow button */
   if (CB_Type(w) != XmCOMBO_BOX) 
   {
      GetDefaultArrowSize(w);

      /* determine x, y for rectangle */
      CB_HitRect(w).y = XtY(CB_EditBox(w));

      /* For now its always to the right of the edit box */
      CB_HitRect(w).x = XtX(CB_EditBox(w)) + XtWidth(CB_EditBox(w)) 
                        + CB_ArrowSpacing(w);

      SetHitArea(w);
   }
   /* configure scrolled window if type is XmCOMBO_BOX */
   else /* if (CB_Type(w) == XmCOMBO_BOX) */ 
   {
      GetIdealTextSize(w);

      y += XtHeight(CB_EditBox(w));
      XmeConfigureObject(CB_ScrolledW(w),
                         x,
                         y,
                         XtWidth(CB_ScrolledW(w)),
                         XtHeight(CB_ScrolledW(w)),
                         XtBorderWidth(CB_ScrolledW(w)));
   }
}

/*
  FUNCTION: DrawArrow
  SYNOPSIS: static void DrawArrow(Widget w)
  DESCRIPTION:
  This function draws the arrow button.  The combo box widget simulates 
  its own arrow button. 
  END:
*/
static void
DrawArrow(Widget w)
{
   XdbDebug(__FILE__, w, "DrawArrow ...\n");

   /*
      REMARK:
      Assume the arrow's x, y, width and height values have not changed.  
      They will be updated by a resize event which also causes a layout.
      END:
   */

   XdbDebug(__FILE__, 
            w, 
            "DrawArrow: x(%d), y(%d), width(%d), height(%d) ...\n",
            (int) CB_HitRect(w).x,
            (int) CB_HitRect(w).y,
            (int) CB_HitRect(w).width,
            (int) CB_HitRect(w).height);

   XmeDrawArrow(XtDisplayOfObject(w),       /* display */
                XtWindowOfObject(w),        /* window */
                MGR_BottomShadowGC(w),      /* top gc */
                MGR_TopShadowGC(w),         /* bottom gc */
                CB_ArrowGC(w),              /* fill gc */
                CB_HitRect(w).x,            /* position x */
                CB_HitRect(w).y,            /* position y */
                CB_HitRect(w).width,        /* width */
                CB_HitRect(w).height,       /* height */
                MGR_ShadowThickness(w),     /* shadow thickness */
                XmARROW_DOWN);
}

/*
  FUNCTION: DrawShadows
  SYNOPSIS: static void DrawShadows(Widget w)
  DESCRIPTION:
  This function draws the shadow around the combobox by calling
  XmeDrawShadows.
  END:
*/
static void
DrawShadows(Widget w)
{
   XdbDebug(__FILE__, w, "DrawShadows ...\n");

   XdbDebug(__FILE__, 
            w, 
            "DrawShadows: x(%d), y(%d), width(%d), height(%d) ...\n",
            (int) 0,
            (int) 0,
            (int) XtWidth(w),
            (int) XtHeight(w));

   XmeDrawShadows(XtDisplayOfObject(w),       /* display */
                  XtWindowOfObject(w),        /* window */
                  MGR_TopShadowGC(w),         /* top gc */
                  MGR_BottomShadowGC(w),      /* bottom gc */
                  0,                          /* position x */
                  0,                          /* position y */
                  XtWidth(w),                 /* width */
                  XtHeight(w),                /* height */
                  MGR_ShadowThickness(w),     /* shadow thickness */
                  XmSHADOW_ETCHED_OUT_DASH);  /* shadow type */
}

/*
  FUNCTION: FindComboBox
  SYNOPSIS: static Widget FindComboBox(Widget w)
  DESCRIPTION:
  This function finds the combobox widget from the supplied widget.
  The supplied widget must be a child or descendent of the combobox.
  END:
*/
static Widget
FindComboBox(Widget w)
{
   Widget ww = w;

   XdbDebug(__FILE__, w, "FindComboBox ...\n");

   while(ww && !XmIsComboBox(ww))
   {
      w = ww;
      ww = XtParent(w); 
   }

   return ww;
}

static void
FocusMovedCB(Widget w, XtPointer client_data, XtPointer data)
{
   /* FIXTHIS: FocusMovedCB needs to be implemented. */

   Unused(w);
   Unused(client_data);
   Unused(data);

   #if 0
   CBFocusOut();
   PopdownList();
   CBDisarm();
   CBFocusIn();
   #endif
} 

static XtGeometryResult 
GeometryManager(Widget w, XtWidgetGeometry *request, XtWidgetGeometry *reply)
{
   XdbDebug(__FILE__, w, "GeometryManager ...\n");

   Unused(w);
   Unused(request);
   Unused(reply);

   /* FIXTHIS: GeometryManager needs to be implemented. */
   if (reply)
       *reply = *request;
   return (XtGeometryResult) XtGeometryYes;

   #if 0
   GetThickness();
   GetIdealTextSize();
   CheckMinimalSize();
   #endif
}

/*
  FUNCTION: GetDefaultArrowSize
  SYNOPSIS: static void GetDefaultArrowSize(Widget w)
  DESCRIPTION:
  This function fills in the width and height for the arrow button.
  END:
*/
static void
GetDefaultArrowSize(Widget w)
{
   XdbDebug(__FILE__, w, "GetDefaultArrowSize ...\n");

   GetIdealTextSize(w);

   /* Always use CB_ArrowSize for the width */
   CB_HitRect(w).width = CB_ArrowSize(w); 
   CB_HitRect(w).height = CB_IdealEBHeight(w); 
}

/*
  FUNCTION: GetEditBoxValue
  SYNOPSIS: static XmString GetEditBoxValue(Widget w)
  DESCRIPTION:
  This function returns the current value of the edit box.
  END:
*/
static XmString
GetEditBoxValue(Widget w)
{
   XmString s;
   _XtString v;

   XtVaGetValues(CB_EditBox(w),XmNvalue, &v, NULL);
   s = XmCvtCTToXmString(v);
   return s;
}

/*
  FUNCTION: GetIdealTextSize
  SYNOPSIS: static void GetIdealTextSize(Widget w)
  DESCRIPTION:
  This function fills in the ideal width and height for the text field.
  END:
*/
static void
GetIdealTextSize(Widget w)
{
   XdbDebug(__FILE__, w, "GetIdealTextSize ...\n");

   CB_IdealEBHeight(w) = XtHeight(CB_EditBox(w));
   CB_IdealEBWidth(w) = XtWidth(CB_EditBox(w));
}

static void
GetThickness(Widget w)
{
   /* FIXTHIS: GetThickness needs to be implemented. */
   Unused(w);
}

/*
  FUNCTION: HighlightBorder
  SYNOPSIS: static void HighlightBorder(Widget w)
  DESCRIPTION:
  This function draws the highlight around the combobox. 
  END:
*/
static void
HighlightBorder(Widget w)
{
   int highlight_offset = 0; /* adjust as needed (<0 makes it bigger) */

   /* check to see if thickness is zero */
   if(CB_HighlightThickness(w) == 0)
   {
      return;
   }

   XdbDebug(__FILE__, w, "HighlightBorder ...\n");

   XmeDrawHighlight(XtDisplayOfObject(w),
                    XtWindowOfObject(w),
                    MGR_HighlightGC(w),
                    highlight_offset,
                    highlight_offset,
                    XtWidth(w) - 2*highlight_offset,
                    XtHeight(w) - 2*highlight_offset,
                    CB_HighlightThickness(w));

   CB_Highlighted(w) = True;
}

static void
Hit(Widget w)
{
   /* FIXTHIS: Hit needs to be implemented. */
   Unused(w);
}

/*
  FUNCTION: Initialize
  SYNOPSIS: static void Initialize(Widget,Widget,ArgList,Cardinal *)
  DESCRIPTION:
  This function initializes the instance data.
  END:
*/
static void
Initialize(Widget request,
           Widget c_new,
           ArgList args,
           Cardinal *num_args)
{
   CreateArrowGC(c_new);
   /* FIXTHIS: Some of the args maybe needed by the children. */
   CreateChildren(c_new);

   /* initialize internal data */
   CB_Highlighted(c_new) = False;
   CB_ArrowPressed(c_new) = False;

   /* set the default values if not set */
   if(CB_ArrowSize(c_new) == 0)
   {
      if (CB_Type(c_new) == XmDROP_DOWN_LIST)
      {
         CB_ArrowSize(c_new) = 14; 
      }
      else if (CB_Type(c_new) == XmDROP_DOWN_COMBO_BOX)
      {
         CB_ArrowSize(c_new) = 17; 
      }
   }
   if(CB_ArrowSpacing(c_new) == 0)
   {
      if (CB_Type(c_new) == XmDROP_DOWN_LIST)
      {
         CB_ArrowSpacing(c_new) = 3; 
      }
      else if (CB_Type(c_new) == XmDROP_DOWN_COMBO_BOX)
      {
         CB_ArrowSpacing(c_new) = 3; 
      }
   }
}

/*
  FUNCTION: InsertChild
  SYNOPSIS: static void InsertChild(Widget w)
  DESCRIPTION:
  This function reports any errors and then calls the composite's insert 
  child routine to do the actual insert.
  END:
*/
static void
InsertChild(Widget w)
{
   Widget parent = XtParent(w);

   XdbDebug2(__FILE__, (Widget)parent, w, "InsertChild\n");

   /*
      REMARK: 
      The combobox in 2.0 checks to see if the child count is greater then 
      two before inserting another child.  If it is greater then it prints 
      a warning.
      END:
    */ 
   if (MGR_NumChildren(parent) > 2)
   {
      XmeWarning(parent, _XmMsgComboBox_0000);
   }

   (*superclass->composite_class.insert_child)(w);
}

/*
  FUNCTION: ListSelectionCB
  SYNOPSIS: static void ListSelectionCB(Widget w, XtPointer client_data, XtPointer data)
  DESCRIPTION:
  This function handles a list selection.  The parameter client_data should
  always be the combo box widget. 
  END:
*/
static void
ListSelectionCB(Widget w, XtPointer client_data, XtPointer data)
{
   XmListCallbackStruct *cbs = (XmListCallbackStruct *) data;
   Widget cb = (Widget) client_data;
   XmString v;

   XdbDebug(__FILE__, w, "ListSelectionCB ...\n");

   v = GetEditBoxValue(cb);

   /* See if the edit box value needs to change. */
   if (XmStringCompare(v,cbs->item) == FALSE)
   {
      /* set string in edit box */
      SetEditBoxValue(cb, cbs->item);
   }

   /* Call internal selection callback list */
   CallSelectionCallbacks(cb, client_data, data);

   if (CB_Type(cb) == XmCOMBO_BOX)
   {
      return;
   }

   PopdownList(cb);

   CBDisarm(cb,cbs->event,NULL,NULL);
} 

static void
PopdownList(Widget w)
{
   /* FIXTHIS: PopdownList needs to be implemented. */
   Unused(w);
}

/*
  FUNCTION: PopupEH
  SYNOPSIS: static void PopupEH(Widget, XtPointer, XEvent *, Boolean *)
  DESCRIPTION:
  Popup event handler.
  END:
*/
static void
PopupEH(Widget w, XtPointer udata, XEvent *xev, Boolean *pb)
{
   XButtonPressedEvent *xbp = (XButtonPressedEvent *)xev;
   XRectangle *rect;

   XdbDebug(__FILE__, w, "PopupEH ...\n");

   Unused(udata);

   *pb = TRUE;
   rect = &CB_HitRect(w);

   if(xbp->button != Button1)
   {
      return;
   }

   XdbDebug(__FILE__, w, "PopupEH: hit at: x(%d), y(%d)\n",
            (int)xbp->x,(int)xbp->y);
   XdbDebug(__FILE__, w, 
            "PopupEH: hit area: x(%d), y(%d), width(%d), height(%d)\n",
            (int) CB_HitRect(w).x,
            (int) CB_HitRect(w).y,
            (int) CB_HitRect(w).width,
            (int) CB_HitRect(w).height);

   /* Is the press within the region? */
   if((xbp->x < rect->x || xbp->x > (rect->x + rect->width))
      || (xbp->y < rect->y || xbp->y > (rect->y + rect->height)))
   {
      return;
   }

   /* Is the grab shell managed? */
   if (!XtIsManaged(CB_ListShell(w)))
   {
      XdbDebug(__FILE__, w, "PopupEH: Not managed so show grab shell\n");

      /* display grab shell */
      XtPopup(CB_ListShell(w), XtGrabNone);
      /*
      CBArmAndDropDownList(w,xev,NULL,NULL);
      */
   }
   else
   {
      XdbDebug(__FILE__, w, "PopupEH: Managed so hide grab shell\n");

      XtUnmanageChild(CB_ListShell(w));
      /*
      CBDisarm(w,xev,NULL,NULL);
      */
   }
}

/*
  FUNCTION: QueryGeometry
  SYNOPSIS: static XtGeometryResult QueryGeometry(Widget,XtWidgetGeometry *,XtWidgetGeometry *)
  DESCRIPTION:
  END:
*/
static XtGeometryResult 
QueryGeometry(Widget w, XtWidgetGeometry *proposed, XtWidgetGeometry *answer)
{
   /* FIXTHIS: */
   Unused(w);
   Unused(proposed);
   Unused(answer);

   #if 0
   ComputeSize();
   #endif
   return (XtGeometryResult) NULL;
}

/* 
  FUNCTION: Redisplay
  SYNOPSIS: static void Redisplay(Widget w)
  DESCRIPTION:
  This routine handles expose events.
  END:
*/
static void 
Redisplay(Widget w, XEvent *event, Region region)
{
   XdbDebug(__FILE__, w, "Redisplay ...\n");

   Unused(event);
   Unused(region);

   /* Draw the arrow if I'm not a XmCOMBO_BOX */
   if (CB_Type(w) != XmCOMBO_BOX)
   {
      DrawArrow(w);
   }

   DrawShadows(w);

   #if 0
   if (CB_Highlighted(w) == True)
   {
      HighlightBorder(w);
   }
   else
   {
      UnhighlightBorder(w);
   }
   #endif
}

static void 
Reduce(Widget w)
{
   Unused(w);
}

static void 
ReduceResources(Widget w)
{
   Unused(w);
}

/* 
  FUNCTION: Resize
  SYNOPSIS: static void Resize(Widget w)
  DESCRIPTION:
  This routine handles resizing.
  END:
*/
static void 
Resize(Widget w)
{
   XdbDebug(__FILE__, w, "Resize ...\n");

   if(XtIsRealized(w))
   {  /* widgets must be resized */
      DoLayout(w);
   }

   (*superclass->core_class.resize)(w);
}

/*
  FUNCTION: SBBtnDownEH()
  SYNOPSIS: static void SBBtnDownEH()
  DESCRIPTION:
  Scrolled Button down event handler.
  END:
*/
static void
SBBtnDownEH(Widget w, XtPointer udata, XEvent *xev, Boolean *pb)
{
   Unused(w);
   Unused(udata);
   Unused(xev);
   Unused(pb);
}

/*
  FUNCTION: SBBtnUpEH()
  SYNOPSIS: static void SBBtnDownEH()
  DESCRIPTION:
  Scrolled Button up event handler.
  END:
*/
static void
SBBtnUpEH(Widget w, XtPointer udata, XEvent *xev, Boolean *pb)
{
   Unused(w);
   Unused(udata);
   Unused(xev);
   Unused(pb);
}

static void
SetEditBoxValue(Widget w, XmString s)
{
   _XtString v;

   /* Convert XmString to a string */
   v = XmCvtXmStringToCT(s);

   XtVaSetValues(CB_EditBox(w),XmNvalue, v, NULL);

   /* free memory */
   XtFree(v);
}

/* 
  FUNCTION: SetHitArea
  SYNOPSIS: static void SetHitArea(Widget w)
  DESCRIPTION:
  This routine will setup the hit area by installing an event handler
  for button events.
  END:
*/
static void
SetHitArea(Widget w)
{
   EventMask mask;

   XdbDebug(__FILE__, w, "SetHitArea ...\n");

   mask = ButtonPressMask;
   XtAddEventHandler(w, mask, FALSE, (XtEventHandler)PopupEH, (XtPointer) NULL);
}

/* 
  FUNCTION: SetValues
  SYNOPSIS: static Boolean SetValues(Widget,Widget,Widget,ArgList,Cardinal *)
  DESCRIPTION:
  This routine handles the setting of widget resources.
  END:
*/
static Boolean 
SetValues(Widget old, 
          Widget request, 
          Widget c_new, 
          ArgList args,
          Cardinal *num_args)
{
   XmComboBoxWidget ow = (XmComboBoxWidget) old;
   XmComboBoxWidget nw = (XmComboBoxWidget) c_new;
   Boolean need_refresh = False;

   /* FIXTHIS: */

   XdbDebug(__FILE__, old, "SetValues ...\n");

   if (CB_Type(ow) != CB_Type(nw))
   {
      CB_Type(nw) = CB_Type(ow);

      XmeWarning(old, _XmMsgComboBox_0001);
   }

   Unused(request);
   Unused(args);
   Unused(num_args);

   return need_refresh;
}

static void
ShellPopdownCB(Widget w, XtPointer client_data, XtPointer data) 
{
   /* FIXTHIS: */

   Unused(w);
   Unused(client_data);
   Unused(data);

   #if 0
   CBFocusOut();
   #endif
} 

static void
ShellPopupCB(Widget w, XtPointer client_data, XtPointer data)
{
   /* FIXTHIS: */

   Unused(w);
   Unused(client_data);
   Unused(data);
} 

static void
TextChangedCB(Widget w, XtPointer client_data, XtPointer data)
{
   /* FIXTHIS: */

   Unused(w);
   Unused(client_data);
   Unused(data);
} 

/*
  FUNCTION: UnhighlightBorder
  SYNOPSIS: static void UnhighlightBorder(Widget w)
  DESCRIPTION:
  This function removes the highlight around the combobox. 
  END:
*/
static void
UnhighlightBorder(Widget w)
{
   int highlight_offset = 0; /* adjust as needed (<0 makes it bigger) */

   /* check to see if thickness is zero */
   if(CB_HighlightThickness(w) == 0)
   {
      return;
   }

   XdbDebug(__FILE__, w, "UnhighlightBorder ...\n");

   XdbDebug(__FILE__, 
            w, 
            "UnhighlightBorder: x(%d), y(%d), width(%d), height(%d) ...\n",
            (int) highlight_offset,
            (int) highlight_offset,
            (int) XtWidth(w) - 2*highlight_offset,
            (int) XtHeight(w) - 2*highlight_offset);

   /* FIXTHIS: Should I be using my own background GC? */
   XmeDrawHighlight(XtDisplayOfObject(w),
                    XtWindowOfObject(w),
                    MGR_BackgroundGC(w),
                    highlight_offset,
                    highlight_offset,
                    XtWidth(w) - 2*highlight_offset,
                    XtHeight(w) - 2*highlight_offset,
                    CB_HighlightThickness(w));

   CB_Highlighted(w) = False;
}

/* ================================================================ */
/* Public routines */
/* 
  FUNCTION: XmCreateComboBox
  SYNOPSIS: Widget XmCreateComboBox(Widget,char *,ArgList,Cardinal)
  DESCRIPTION:
  Creates an instance of a XmComboxWidget.
  END:
*/
Widget 
XmCreateComboBox(Widget parent, char *name, ArgList arglist,
                 Cardinal cnt)
{
   return XtCreateWidget(name, 
                         xmComboBoxWidgetClass,
                         parent, 
                         arglist, 
                         cnt);
}

/* 
  FUNCTION: XmCreateDropDownComboBox
  SYNOPSIS: Widget XmCreateDropDownComboBox(Widget,char *,ArgList,Cardinal)
  DESCRIPTION:
  Creates an instance of a XmComboxWidget with XmNcomboBoxType 
  set to XmDROP_DOWN_COMBO_BOX.
  END:
*/
Widget 
XmCreateDropDownComboBox(Widget parent,
                         char *name,
                         Arg *arglist,
                         Cardinal cnt)
{
   Widget w;
   Arg myArgList[1];
   int n = 0;

   ArgList combined;

   XtSetArg(myArgList[n], XmNcomboBoxType, XmDROP_DOWN_COMBO_BOX); n++;

   combined = XtMergeArgLists(myArgList, n, arglist, cnt);

   w = XtCreateWidget(name,
                      xmComboBoxWidgetClass,
                      parent,
                      combined, 
                      n + cnt);

   XtFree((char *)combined);

   return w;
}

/* 
  FUNCTION: XmCreateDropDownList
  SYNOPSIS: Widget XmCreateDropDownList(Widget,char *,ArgList,Cardinal)
  DESCRIPTION:
  Creates an instance of a XmComboxWidget with XmNcomboBoxType 
  set to XmDROP_DOWN_LIST.
  END:
*/
Widget 
XmCreateDropDownList(Widget parent,
                     char *name,
                     Arg *arglist,
                     Cardinal cnt)
{
   Widget w;
   Arg myArgList[1];
   int n = 0;

   ArgList combined;

   XtSetArg(myArgList[n], XmNcomboBoxType, XmDROP_DOWN_LIST); n++;

   combined = XtMergeArgLists(myArgList, n, arglist, cnt);

   w = XtCreateWidget(name,
                      xmComboBoxWidgetClass,
                      parent,
                      combined, 
                      n + cnt);

   XtFree((char *)combined);

   return w;
}

/* 
  FUNCTION: XmComboBoxUpdate
  SYNOPSIS: void XmComboBoxUpdate(Widget w)
  DESCRIPTION:
  Communicates any dependent changes between child widgets.
  END:
*/
void 
XmComboBoxUpdate(Widget w)
{
   /* FIXTHIS: XmComboBoxUpdate needs to be implemented. */
   Unused(w);
}

/*
  REMARK:

* Determine if OSF/XmComboBox Widget actual creates a arrow button or
simulates it some how?

It looks like it simulates it.  It does not seem to ever resize the width
but does allow resizing of the height of the button along with the text field.

* Is the arrow button in the XmComboBox a gadget?

* Determine how children are layed out.  This is dependent on the previous
question.

Only one child, the text field.  The popup shell and the scrolled list 
will handle there own geometry.  The use of only one child simplies things.

* What is the name of the text field widget?

The text field widget is called "Text".

  END:
*/
