Logo Search packages:      
Sourcecode: nedit version File versions  Download package

Tree.c

/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 *
 * ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is the Microline Widget Library, originally made available under the NPL by Neuron Data <http://www.neurondata.com>.
 *
 * The Initial Developer of the Original Code is
 * Netscape Communications Corporation.
 * Portions created by the Initial Developer are Copyright (C) 1998
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * In addition, as a special exception to the GNU GPL, the copyright holders
 * give permission to link the code of this program with the Motif and Open
 * Motif libraries (or with modified versions of these that use the same
 * license), and distribute linked combinations including the two. You
 * must obey the GNU General Public License in all respects for all of
 * the code used other than linking with Motif/Open Motif. If you modify
 * this file, you may extend this exception to your version of the file,
 * but you are not obligated to do so. If you do not wish to do so,
 * delete this exception statement from your version.
 *
 * ***** END LICENSE BLOCK ***** */

#include "TreeP.h"

#include <stdio.h>

static void Initialize(Widget req, Widget newW, ArgList args, Cardinal *nargs);
static void Destroy(Widget w);
static Boolean SetValues(Widget curW, Widget, Widget newW, 
      ArgList args, Cardinal *nargs);
static int _PreLayout(XmLGridWidget g, int isVert);
static int _TreeCellAction(XmLGridCell cell, Widget w,
      XmLGridCallbackStruct *cbs);
static void DrawIconCell(XmLGridCell cell, Widget w,
      int row, XRectangle *clipRect, XmLGridDrawStruct *ds);
static void DrawConnectingLine(Display *dpy, Window win, GC gc,
      XRectangle *clipRect, int offFlag, int x1, int y1, int x2, int y2);
static void BtnPress(Widget w, XtPointer closure, XEvent *event,
      Boolean *ctd);
static void Activate(Widget w, XtPointer clientData, XtPointer callData);
static void SwitchRowState(XmLTreeWidget t, int row, XEvent *event);
static XmLGridRow _RowNew(Widget tree);
static void _GetRowValueMask(XmLGridWidget g, char *s, long *mask);
static void _GetRowValue(XmLGridWidget g, XmLGridRow r,
      XtArgVal value, long mask);
static int _SetRowValues(XmLGridWidget g, XmLGridRow r, long mask);
static int _SetCellValuesResize(XmLGridWidget g, XmLGridRow row,
      XmLGridColumn col, XmLGridCell cell, long mask);

static void GetManagerForeground(Widget w, int, XrmValue *value);
static void CreateDefaultPixmaps(XmLTreeWidget t);
static XmLTreeWidget WidgetToTree(Widget w, char *funcname);

static XtResource resources[] =
      {
            {
            XmNcollapseCallback, XmCCallback,
            XmRCallback, sizeof(XtCallbackList),
            XtOffset(XmLTreeWidget, tree.collapseCallback),
            XmRImmediate, (XtPointer)0,
            },
            {
            XmNconnectingLineColor, XmCConnectingLineColor,
            XmRPixel, sizeof(Pixel),
            XtOffset(XmLTreeWidget, tree.lineColor),
            XmRCallProc, (XtPointer)GetManagerForeground,
            },
            {
            XmNexpandCallback, XmCCallback,
            XmRCallback, sizeof(XtCallbackList),
            XtOffset(XmLTreeWidget, tree.expandCallback),
            XmRImmediate, (XtPointer)0,
            },
            {
            XmNlevelSpacing, XmCLevelSpacing,
            XmRDimension, sizeof(Dimension),
            XtOffset(XmLTreeWidget, tree.levelSpacing),
            XmRImmediate, (XtPointer)11,
            },
            {
            XmNplusMinusColor, XmCPlusMinusColor,
            XmRPixel, sizeof(Pixel),
            XtOffset(XmLTreeWidget, tree.pmColor),
            XmRCallProc, (XtPointer)GetManagerForeground,
            },
            /* Row Resources */
            {
            XmNrowExpands, XmCRowExpands,
            XmRBoolean, sizeof(Boolean),
            XtOffset(XmLTreeWidget, tree.rowExpands),
            XmRImmediate, (XtPointer)False,
            },
            {
            XmNrowIsExpanded, XmCRowIsExpanded,
            XmRBoolean, sizeof(Boolean),
            XtOffset(XmLTreeWidget, tree.rowIsExpanded),
            XmRImmediate, (XtPointer)True,
            },
            {
            XmNrowLevel, XmCRowLevel,
            XmRInt, sizeof(int),
            XtOffset(XmLTreeWidget, tree.rowLevel),
            XmRImmediate, (XtPointer)0,
            },

        /* XmNignorePixmaps.  Causes the tree to NOT render any pixmaps */
            {
            XmNignorePixmaps, XmCIgnorePixmaps,
            XmRBoolean, sizeof(Boolean),
            XtOffset(XmLTreeWidget, tree.ignorePixmaps),
            XmRImmediate, (XtPointer) False,
            },
      };

XmLTreeClassRec xmlTreeClassRec =
      {
            { /* core_class */
            (WidgetClass)&xmlGridClassRec,            /* superclass         */
            "XmLTree",                                /* class_name         */
            sizeof(XmLTreeRec),                       /* widget_size        */
            (XtProc)NULL,                             /* class_init         */
            0,                                        /* class_part_init    */
            FALSE,                                    /* class_inited       */
            (XtInitProc)Initialize,                   /* initialize         */
            0,                                        /* initialize_hook    */
            XtInheritRealize,                         /* realize            */
            NULL,                                     /* actions            */
            0,                                        /* num_actions        */
            resources,                                /* resources          */
            XtNumber(resources),                      /* num_resources      */
            NULLQUARK,                                /* xrm_class          */
            TRUE,                                     /* compress_motion    */
            XtExposeCompressMaximal,                  /* compress_exposure  */
            TRUE,                                     /* compress_enterleav */
            TRUE,                                     /* visible_interest   */
            (XtWidgetProc)Destroy,                    /* destroy            */
            XtInheritResize,                          /* resize             */
            XtInheritExpose,                          /* expose             */
            (XtSetValuesFunc)SetValues,               /* set_values         */
            0,                                        /* set_values_hook    */
            XtInheritSetValuesAlmost,                 /* set_values_almost  */
            0,                                        /* get_values_hook    */
            0,                                        /* accept_focus       */
            XtVersion,                                /* version            */
            0,                                        /* callback_private   */
            XtInheritTranslations,                    /* tm_table           */
            0,                                        /* query_geometry     */
            0,                                        /* display_accelerato */
            0,                                        /* extension          */
            },
            { /* composite_class */
            XtInheritGeometryManager,                 /* geometry_manager   */
            XtInheritChangeManaged,                   /* change_managed     */
            XtInheritInsertChild,                     /* insert_child       */
            XtInheritDeleteChild,                     /* delete_child       */
            0,                                        /* extension          */
            },
            { /* constraint_class */
            0,                                          /* subresources       */
            0,                                        /* subresource_count  */
            sizeof(XmLTreeConstraintRec),             /* constraint_size    */
            0,                                        /* initialize         */
            0,                                        /* destroy            */
            0,                                        /* set_values         */
            0,                                        /* extension          */
            },
            { /* manager_class */
            XtInheritTranslations,                    /* translations       */
            0,                                        /* syn resources      */
            0,                                        /* num syn_resources  */
            0,                                        /* get_cont_resources */
            0,                                        /* num_get_cont_resou */
            XmInheritParentProcess,                   /* parent_process     */
            0,                                        /* extension          */
            },
            { /* grid_class */
            0,                                        /* initial rows       */
            1,                                        /* initial cols       */
            _PreLayout,                               /* post layout        */
            sizeof(struct _XmLTreeRowRec),            /* row rec size       */
            _RowNew,                                  /* row new            */
            XmInheritGridRowFree,                     /* row free           */
            _GetRowValueMask,                         /* get row value mask */
            _GetRowValue,                             /* get row value      */
            _SetRowValues,                            /* set row values     */
            sizeof(struct _XmLGridColumnRec),         /* column rec size    */
            XmInheritGridColumnNew,                   /* column new         */
            XmInheritGridColumnFree,                  /* column free        */
            XmInheritGridGetColumnValueMask,          /* get col value mask */
            XmInheritGridGetColumnValue,              /* get column value   */
            XmInheritGridSetColumnValues,             /* set column values  */
            _SetCellValuesResize,                     /* set cell vl resize */
            _TreeCellAction,                          /* cell action        */
            },
            { /* tree_class */
            0,                                        /* unused             */
            }
      };

WidgetClass xmlTreeWidgetClass = (WidgetClass)&xmlTreeClassRec;

static void
Initialize(Widget reqW,
         Widget newW,
         ArgList args,
         Cardinal *narg)
      {
      XmLTreeWidget t;
 
      t = (XmLTreeWidget)newW;
      if ((int) t->core.width <= 0)
            t->core.width = 100;
      if (t->core.height <= (Dimension) 0)
            t->core.height = 100;
      t->tree.defaultPixmapsCreated = 0;
      t->tree.linesData = 0;
      t->tree.linesSize = 0;
      t->tree.recalcTreeWidth = 0;
      if (t->grid.rowCount)
            {
            XmLWarning(newW, "Initialize() - can't set XmNrows");
            XmLGridDeleteAllRows(newW, XmCONTENT);
            }
      XtAddCallback(newW, XmNactivateCallback, Activate, NULL);
      XtAddEventHandler(newW, ButtonPressMask,
            True, (XtEventHandler)BtnPress, (XtPointer)0);

      XtVaSetValues(newW,
            XmNcellDefaults, True,
            XmNcolumn, 0,
            XmNcellType, XmICON_CELL,
            NULL);
      }

static void
Destroy(Widget w)
      {
      XmLTreeWidget t;
      Display *dpy;
      XWindowAttributes attr;

      t = (XmLTreeWidget)w;
      dpy = XtDisplay(t);
      if (t->tree.linesData)
            free((char *)t->tree.linesData);
      if (t->tree.defaultPixmapsCreated)
            {
            XGetWindowAttributes(dpy, XtWindow(w), &attr);
            XFreePixmap(dpy, t->tree.filePixmask);
            XFreePixmap(dpy, t->tree.folderPixmask);
            XFreePixmap(dpy, t->tree.folderOpenPixmask);
            XFreePixmap(dpy, t->tree.filePixmask);
            XFreePixmap(dpy, t->tree.folderPixmask);
            XFreePixmap(dpy, t->tree.folderOpenPixmask);
            XFreeColors(dpy, attr.colormap, t->tree.pixColors, 4, 0L);
            }
      }

static Boolean
SetValues(Widget curW,
        Widget reqW,
        Widget newW,
        ArgList args,
        Cardinal *nargs)
{
      XmLTreeWidget t, cur;
      XmLGridColumn col;
      Boolean needsResize, needsRedraw;
 
      t = (XmLTreeWidget)newW;
      cur = (XmLTreeWidget)curW;
      needsResize = False;
      needsRedraw = False;

#define NE(value) (t->value != cur->value)
      if (NE(grid.rowCount))
            XmLWarning(newW, "SetValues() - can't set XmNrows");
      if (NE(tree.pmColor) || NE(tree.lineColor))
            needsRedraw = True;
      if (NE(tree.levelSpacing) ||
            t->tree.recalcTreeWidth)
            {
            col = XmLGridGetColumn(newW, XmCONTENT, 0);
            if (col)
                  col->grid.widthInPixelsValid = 0;
            t->tree.recalcTreeWidth = 0;
            needsResize = True;
            needsRedraw = True;
            }
#undef NE
      if (needsResize)
            _XmLGridLayout((XmLGridWidget)t);
      if (needsRedraw)
            XmLGridRedrawAll((Widget)t);
      return False;
}

static int
_PreLayout(XmLGridWidget g,
           int isVert)
      {
      XmLTreeWidget t;
      XmLTreeRow row;
      Widget w;
      int i, j, size, maxLevel, hideLevel, lineWidth;
      char *thisLine, *prevLine;

      t = (XmLTreeWidget)g;
      w = (Widget)g;
      if (!t->grid.vertVisChangedHint)
            return 0; /* ?? */
      t->grid.vertVisChangedHint = 0;

      /* top down calculation of hidden states and maxLevel */
      hideLevel = -1;
      maxLevel = 0;
      t->grid.layoutFrozen = True;
      for (i = 0; i < t->grid.rowCount; i++)
            {
            row = (XmLTreeRow)XmLGridGetRow(w, XmCONTENT, i);
            if (row->tree.level > maxLevel)
                  maxLevel = row->tree.level;

            if (hideLevel != -1 && row->tree.level > hideLevel)
                  {
                  if (row->grid.height)
                        XtVaSetValues(w,
                              XmNrow, i,
                              XmNrowHeight, 0,
                              NULL);
                  }
            else
                  {
                  if (row->tree.expands == True && row->tree.isExpanded == False)
                        hideLevel = row->tree.level;
                  else
                        hideLevel = -1;
                  if (!row->grid.height)
                        XtVaSetValues(w,
                              XmNrow, i,
                              XmNrowHeight, 1,
                              NULL);
                  }
            }
      t->grid.layoutFrozen = False;
      t->tree.linesMaxLevel = maxLevel;
      if (!t->grid.rowCount)
            return 0;

      /* bottom up calculation of connecting lines */
      lineWidth = maxLevel + 1;
      size = lineWidth * t->grid.rowCount;
      if (t->tree.linesSize < size)
            {
            if (t->tree.linesData)
                  free((char *)t->tree.linesData);
            t->tree.linesSize = size;
            t->tree.linesData = (char *)malloc(size);
            }
      prevLine = 0;
      thisLine = &t->tree.linesData[size - lineWidth];
      for (i = t->grid.rowCount - 1; i >= 0; i--)
            {
            row = (XmLTreeRow)XmLGridGetRow(w, XmCONTENT, i);
            if (!row->grid.height)
                  {
                  thisLine -= lineWidth;
                  continue;
                  }
            for (j = 0; j < row->tree.level - 1; j++)
                  {
                  if (prevLine && (prevLine[j] == 'L' || prevLine[j] == 'I' ||
                        prevLine[j] == 'E'))
                        thisLine[j] = 'I';
                  else
                        thisLine[j] = ' ';
                  }     
            if (row->tree.level)
                  {
                  if (prevLine && (prevLine[j] == 'L' || prevLine[j] == 'I' ||
                        prevLine[j] == 'E'))
                        thisLine[j++] = 'E';
                  else
                        thisLine[j++] = 'L';
                  }
            thisLine[j++] = 'O';
            for (; j < lineWidth; j++)
                  thisLine[j] = ' ';
            prevLine = thisLine;
            thisLine -= lineWidth;
            }
      if (prevLine)
            {
            for (i = 0; i < lineWidth; i++)
                  {
                  if (prevLine[i] == 'L')
                        prevLine[i] = '-';
                  else if (prevLine[i] == 'E')
                        prevLine[i] = 'P';
                  }
            }

      /* if we are in VertLayout(), the horizontal size may need */
      /* recomputing because of the row hides. */
      if (isVert)
            return 1;

      /* if we are in HorizLayout(), the vertical recomputation */
      /* will be happening regardless, since row changes (vertical) */
      /* are why we are here */
      return 0;
      }

static int
_TreeCellAction(XmLGridCell cell,
            Widget w,
            XmLGridCallbackStruct *cbs)
      {
      XmLTreeWidget t;
      XmLTreeRow row;
      XmLGridColumn col;
      XmLGridWidgetClass sc;
      XmLGridCellActionProc cellActionProc;
      XmLGridCellRefValues *cellValues;
      XmLGridCellIcon *icon;
      /*    XRectangle *rect, cRect;*/
      int ret, h, isTreeCell;


      Dimension default_icon_width = 16;
      Dimension default_icon_height = 16;

      t = (XmLTreeWidget)w;
      if (cbs->rowType == XmCONTENT &&
            cbs->columnType == XmCONTENT &&
            cbs->column == 0)
            isTreeCell = 1;
      else
            isTreeCell = 0;
      sc = (XmLGridWidgetClass)xmlTreeWidgetClass->core_class.superclass;
      cellActionProc = sc->grid_class.cellActionProc;
      ret = 0;

      /* Check for ignore pixmaps */
      if (t->tree.ignorePixmaps)
      {
            default_icon_width = 0;
            default_icon_height = 0;
      }

      switch (cbs->reason)
            {
            case XmCR_CELL_DRAW:
                  if (isTreeCell)
                        DrawIconCell(cell, w, cbs->row, cbs->clipRect, cbs->drawInfo);
                  else
                        ret = cellActionProc(cell, w, cbs);
                  break;
            case XmCR_CONF_TEXT:
            if (isTreeCell)
            {
                int iconOffset;
                        cellValues = cell->cell.refValues;
                        row = (XmLTreeRow)XmLGridGetRow(w, XmCONTENT, cbs->row);
                        icon = (XmLGridCellIcon *)cell->cell.value;
                iconOffset = 4 + cellValues->leftMargin
                    + t->tree.levelSpacing * 2 * row->tree.level;
                        if (!icon)
                              iconOffset += default_icon_width;
                        else if (icon->pix.pixmap == XmUNSPECIFIED_PIXMAP)
                              iconOffset += default_icon_width;
                        else
                              iconOffset += icon->pix.width;
                cbs->clipRect->x += iconOffset;
                if (cbs->clipRect->width > iconOffset)
                    cbs->clipRect->width -= iconOffset;
                else
                    cbs->clipRect->width = 0;
            }
            ret = cellActionProc(cell, w, cbs);
                  break;
            case XmCR_PREF_HEIGHT:
                  ret = cellActionProc(cell, w, cbs);
                  if (isTreeCell)
                        {
                        cellValues = cell->cell.refValues;
                        if (cellValues->type != XmICON_CELL)
                              return 0;
                        icon = (XmLGridCellIcon *)cell->cell.value;

                        h = 4 + default_icon_height + cellValues->topMargin + cellValues->bottomMargin;

                        if (icon && icon->pix.pixmap == XmUNSPECIFIED_PIXMAP &&
                              ret < h)
                              ret = h;
                        }
                  break;
            case XmCR_PREF_WIDTH:
                  if (isTreeCell)
                        {
                        cellValues = cell->cell.refValues;
                        if (cellValues->type != XmICON_CELL)
                              return 0;
                        icon = (XmLGridCellIcon *)cell->cell.value;
                        col = (XmLGridColumn)cbs->object;
                        row = (XmLTreeRow)XmLGridGetRow(w, XmCONTENT, cbs->row);
                        if (row->tree.stringWidthValid == False)
                              {
                              if (icon && icon->string)
                                    row->tree.stringWidth =
                                          XmStringWidth(cellValues->fontList, icon->string);
                              else
                                    row->tree.stringWidth = 0;
                              row->tree.stringWidthValid = True;
                              }
                        ret = 4 + cellValues->leftMargin + t->tree.levelSpacing * 2 *
                              row->tree.level + t->grid.iconSpacing + row->tree.stringWidth +
                              cellValues->rightMargin;
                        if (!icon)
                              ret += default_icon_width;
                        else if (icon->pix.pixmap == XmUNSPECIFIED_PIXMAP)
                              ret += default_icon_width;
                        else
                              ret += icon->pix.width;
                        if (!row->grid.height)
                              ret = 0;
                        }
                  else
                        ret = cellActionProc(cell, w, cbs);
                  break;
            default:
                  ret = cellActionProc(cell, w, cbs);
                  break;
            }
      return ret;
      }

static void
DrawIconCell(XmLGridCell cell,
             Widget w,
             int row,
             XRectangle *clipRect,
             XmLGridDrawStruct *ds)
      {
      XmLTreeWidget t;
      XmLTreeRow rowp;
      XmLGridCellRefValues *cellValues;
      XmLGridCellIcon *icon;
      XRectangle *cellRect, rect;
      Display *dpy;
      Window win;
      char *thisLine;
      int i, clipSet, pixWidth, pixHeight;
      int xoff, xoff2, midy, oddFlag, x1, y1, x2, y2;
      Pixmap pixmap, pixmask;

      t = (XmLTreeWidget)w;
      rowp = (XmLTreeRow)XmLGridGetRow(w, XmCONTENT, row);
      dpy = XtDisplay(w);
      win = XtWindow(w);
      cellValues = cell->cell.refValues;
      if (cellValues->type != XmICON_CELL)
            return;
      icon = (XmLGridCellIcon *)cell->cell.value;
      if (!icon)
            return;
      cellRect = ds->cellRect;
      if (!t->tree.linesData)
            {
            XmLWarning(w, "DrawIconCell() - no lines data calculated");
            return;
            }

      /* draw background */
      XSetForeground(dpy, ds->gc, cell->cell.refValues->background);
      XFillRectangle(dpy, win, ds->gc, clipRect->x, clipRect->y,
            clipRect->width, clipRect->height);

      if (t->grid.singleColScrollMode)
            oddFlag = t->grid.singleColScrollPos & 1;
      else
            oddFlag = 0;

      pixWidth = 0;
      xoff = t->tree.levelSpacing;
      xoff2 = xoff * 2;
      y1 = cellRect->y;
      y2 = cellRect->y + cellRect->height - 1;
      midy = cellRect->y + cellRect->height / 2;
      if (midy & 1)
            midy += 1;

      /* draw connecting lines and pixmap */
      XSetForeground(dpy, ds->gc, t->tree.lineColor);
      thisLine = &t->tree.linesData[row * (t->tree.linesMaxLevel + 1)];
      for (i = 0; i <= t->tree.linesMaxLevel; i++)
            {
            x1 = cellRect->x + (xoff2 * i);
            if (x1 >= clipRect->x + (int)clipRect->width)
                  continue;
            switch (thisLine[i])
                  {
                  case 'O':
              if (!t->tree.ignorePixmaps)
              {
                        rect.x = x1;
                        rect.y = cellRect->y;
                        rect.width = cellRect->width;
                        rect.height = cellRect->height;
                        if (icon->pix.pixmap != XmUNSPECIFIED_PIXMAP)
                              {
                              pixmap = icon->pix.pixmap;
                              pixmask = icon->pix.pixmask;
                              pixWidth = icon->pix.width;
                              pixHeight = icon->pix.height;
                              }
                        else
                              {
                              if (!t->tree.defaultPixmapsCreated)
                                    CreateDefaultPixmaps(t);
                              if (rowp->tree.expands && rowp->tree.isExpanded)
                                    {
                                    pixmap = t->tree.folderOpenPixmap;
                                    pixmask = t->tree.folderOpenPixmask;
                                    }
                              else if (rowp->tree.expands)
                                    {
                                    pixmap = t->tree.folderPixmap;
                                    pixmask = t->tree.folderPixmask;
                                    }
                              else
                                    {
                                    pixmap = t->tree.filePixmap;
                                    pixmask = t->tree.filePixmask;
                                    }
                              pixWidth = 16;
                              pixHeight = 16;
                              }
                        
                        XmLPixmapDraw(w, pixmap, pixmask, pixWidth, pixHeight,
                                            XmALIGNMENT_BOTTOM_LEFT, ds->gc, &rect, clipRect);
              } /* !t->tree.ignorePixmaps */
                        break;
                  case 'I':
                        DrawConnectingLine(dpy, win, ds->gc, clipRect, oddFlag,
                              x1 + xoff, y1, x1 + xoff, y2);
                        break;
                  case 'E':
                        DrawConnectingLine(dpy, win, ds->gc, clipRect, oddFlag,
                              x1 + xoff, y1, x1 + xoff, y2);
                        DrawConnectingLine(dpy, win, ds->gc, clipRect, oddFlag,
                              x1 + xoff, midy, x1 + xoff2, midy);
                        break;
                  case 'L':
                        DrawConnectingLine(dpy, win, ds->gc, clipRect, oddFlag,
                              x1 + xoff, y1, x1 + xoff, midy);
                        DrawConnectingLine(dpy, win, ds->gc, clipRect, oddFlag,
                              x1 + xoff, midy, x1 + xoff2, midy);
                        break;
                  case 'P':
                        DrawConnectingLine(dpy, win, ds->gc, clipRect, oddFlag,
                              x1 + xoff, midy, x1 + xoff, y2);
                        DrawConnectingLine(dpy, win, ds->gc, clipRect, oddFlag,
                              x1 + xoff, midy, x1 + xoff2, midy);
                        break;
                  case '-':
                        DrawConnectingLine(dpy, win, ds->gc, clipRect, oddFlag,
                              x1 + xoff, midy, x1 + xoff2, midy);
                        break;
                  }
            }

      clipSet = 0;

      /* draw expand/collapse graphic */
      rect.x = cellRect->x + (rowp->tree.level - 1) * xoff2 + xoff - 5;
      rect.y = midy - 5;
      rect.width = 11;
      rect.height = 11;
      i = XmLRectIntersect(&rect, clipRect);
      if (rowp->tree.expands && rowp->tree.level && i != XmLRectOutside)
            {
            if (i == XmLRectPartial)
                  {
                  clipSet = 1;
                  XSetClipRectangles(dpy, ds->gc, 0, 0, clipRect, 1, Unsorted);
                  }
            x1 = rect.x;
            x2 = rect.x + rect.width - 1;
            y1 = rect.y;
            y2 = rect.y + rect.height - 1;
            XSetForeground(dpy, ds->gc, cellValues->background);
            XFillRectangle(dpy, win, ds->gc, x1, y1, 11, 11);
            XSetForeground(dpy, ds->gc, t->tree.lineColor);
            XDrawLine(dpy, win, ds->gc, x1 + 2, y1 + 1, x2 - 2, y1 + 1);
            XDrawLine(dpy, win, ds->gc, x2 - 1, y1 + 2, x2 - 1, y2 - 2);
            XDrawLine(dpy, win, ds->gc, x1 + 2, y2 - 1, x2 - 2, y2 - 1);
            XDrawLine(dpy, win, ds->gc, x1 + 1, y1 + 2, x1 + 1, y2 - 2);
            XSetForeground(dpy, ds->gc, t->tree.pmColor);
            if (!rowp->tree.isExpanded)
                  XDrawLine(dpy, win, ds->gc, x1 + 5, y1 + 3, x1 + 5, y1 + 7);
            XDrawLine(dpy, win, ds->gc, x1 + 3, y1 + 5, x1 + 7, y1 + 5);
            }

      /* draw select background and highlight */
      i = rowp->tree.level * xoff2 + pixWidth + t->grid.iconSpacing;
      rect.x = cellRect->x + i;
      rect.y = cellRect->y;
      rect.height = cellRect->height;
      rect.width = 0;
      if (t->grid.colCount == 1 && rowp->tree.stringWidthValid)
            rect.width = rowp->tree.stringWidth + 4;
      else if ((int)cellRect->width > i)
            rect.width = cellRect->width - i;
      i = XmLRectIntersect(&rect, clipRect);
      if (i != XmLRectOutside && ds->drawSelected)
            {
            if (i == XmLRectPartial && !clipSet)
                  {
                  clipSet = 1;
                  XSetClipRectangles(dpy, ds->gc, 0, 0, clipRect, 1, Unsorted);
                  }
            XSetForeground(dpy, ds->gc, ds->selectBackground);
            XFillRectangle(dpy, win, ds->gc, rect.x, rect.y,
                  rect.width, rect.height);
            }
      if (ds->drawFocusType != XmDRAW_FOCUS_NONE &&
            t->grid.highlightThickness >= 2)
            {
            if (i == XmLRectPartial && !clipSet)
                  {
                  clipSet = 1;
                  XSetClipRectangles(dpy, ds->gc, 0, 0, clipRect, 1, Unsorted);
                  }
            XSetForeground(dpy, ds->gc, t->manager.highlight_color);
            x1 = rect.x;
            x2 = rect.x + rect.width - 1;
            y1 = rect.y;
            y2 = rect.y + rect.height - 1;
            XDrawLine(dpy, win, ds->gc, x1, y1, x2, y1);
            if (ds->drawFocusType == XmDRAW_FOCUS_CELL ||
                  ds->drawFocusType == XmDRAW_FOCUS_RIGHT)
                  XDrawLine(dpy, win, ds->gc, x2, y1, x2, y2);
            XDrawLine(dpy, win, ds->gc, x1, y2, x2, y2);
            XDrawLine(dpy, win, ds->gc, x1, y1, x1, y2);
            y1 += 1;
            y2 -= 1;
            XDrawLine(dpy, win, ds->gc, x1, y2, x2, y2);
            XDrawLine(dpy, win, ds->gc, x1, y1, x2, y1);
            x1 += 1;
            x2 -= 1;
            XDrawLine(dpy, win, ds->gc, x1, y1, x1, y2);
            if (ds->drawFocusType == XmDRAW_FOCUS_CELL ||
                  ds->drawFocusType == XmDRAW_FOCUS_RIGHT)
                  XDrawLine(dpy, win, ds->gc, x2, y1, x2, y2);
            }

      /* draw string */
      if (icon->string)
            {
            if (ds->drawSelected == True)
                  XSetForeground(dpy, ds->gc, ds->selectForeground);
            else
                  XSetForeground(dpy, ds->gc, cellValues->foreground);
            XmLStringDraw(w, icon->string, ds->stringDirection,
                  cellValues->fontList, XmALIGNMENT_LEFT,
                  ds->gc, &rect, clipRect);
            }

      if (clipSet)
            XSetClipMask(dpy, ds->gc, None);
      }

static void
DrawConnectingLine(Display *dpy,
                    Window win,
                    GC gc,
                    XRectangle *clipRect,
                    int oddFlag,
                    int x1,
                    int y1,
                    int x2,
                    int y2)
      {
      int i, x, y;
      XPoint points[100];

      i = 0;
      for (x = x1; x <= x2; x++)
            for (y = y1; y <= y2; y++)
                  {
                  if ((((x + oddFlag) & 1) == (y & 1)) ||
                        x < clipRect->x ||
                        x >= (clipRect->x + (int)clipRect->width) ||
                        y < clipRect->y ||
                        y >= (clipRect->y + (int)clipRect->height))
                        continue;
                  points[i].x = x;
                  points[i].y = y;
                  if (++i < 100)
                        continue;
                  XDrawPoints(dpy, win, gc, points, i, CoordModeOrigin);
                  i = 0;
                  }
      if (i)
            XDrawPoints(dpy, win, gc, points, i, CoordModeOrigin);
      }

static void
BtnPress(Widget w,
         XtPointer closure,
         XEvent *event,
         Boolean *ctd)
      {
      XmLTreeWidget t;
      XmLTreeRow rowp;
      unsigned char rowType, colType;
      int row, col, x1, y1, x2, y2, xoff;
      XRectangle rect;
      XButtonEvent *be;
      static int lastRow = -1;
      static Time lastSelectTime = 0;

      t = (XmLTreeWidget)w;
      if (event->type != ButtonPress)
            return;
      be = (XButtonEvent *)event;
      if (be->button != Button1 || be->state & ControlMask ||
            be->state & ShiftMask)
            return;
      if (XmLGridXYToRowColumn(w, be->x, be->y, &rowType, &row,
            &colType, &col) == -1)
            return;
      rowp = (XmLTreeRow)XmLGridGetRow(w, XmCONTENT, row);
      if (rowType != XmCONTENT || colType != XmCONTENT || col != 0)
            return;
      if (XmLGridRowColumnToXY(w, rowType, row, colType, col,
            False, &rect) == -1)
            return;
      if ((be->time - lastSelectTime) < XtGetMultiClickTime(XtDisplay(w)) &&
            lastRow == row)
            {
            /* activate callback will be handling expand/collapse */
            lastSelectTime = be->time;
            return;
            }
    /*
     * If the Grid is using single click activation the activateCallback 
     * called from Select() will take care of collapsing and
     * expanding. 
     */
    if (((XmLGridWidget)w)->grid.singleClickActivation)
      return;
      lastSelectTime = be->time;
      lastRow = row;
      xoff = t->tree.levelSpacing;
      x1 = rect.x + (rowp->tree.level - 1) * xoff * 2 + xoff - 6;
      x2 = x1 + 13;
      y1 = rect.y + rect.height / 2 - 6;
      y2 = y1 + 13;
      if (be->x > x2 || be->x < x1 || be->y > y2 || be->y < y1)
            return;
      SwitchRowState(t, row, event);

    /* Avoid having a cell edited when expand/collapse is done.
     * Yes, this is a hack. By setting this to zero, Grid.c:Select()
     * will ignore this click are a second click that would trigger
     * inplace editing.
     */
    ((XmLGridWidget)w)->grid.lastSelectTime = 0;
      }

static void
Activate(Widget w,
         XtPointer clientData,
         XtPointer callData)
      {
      XmLTreeWidget t;
      XmLGridCallbackStruct *cbs;

      t = (XmLTreeWidget)w;
      cbs = (XmLGridCallbackStruct *)callData;
      if (cbs->rowType != XmCONTENT)
      if (t->grid.selectionPolicy == XmSELECT_CELL &&
            (cbs->columnType != XmCONTENT || cbs->column != 0))
            return;
      SwitchRowState(t, cbs->row, cbs->event);
      }

static void
SwitchRowState(XmLTreeWidget t,
               int row,
               XEvent *event)
      {
      Widget w;
      XmLTreeRow rowp;
      XmLGridCallbackStruct cbs;

      w = (Widget)t;
      rowp = (XmLTreeRow)XmLGridGetRow(w, XmCONTENT, row);
      if (rowp->tree.expands == False) 
            return;
      cbs.event = event;
      cbs.columnType = XmCONTENT;
      cbs.column = 0;
      cbs.rowType = XmCONTENT;
      cbs.row = row;
      if (rowp->tree.isExpanded == True)
            {
            XtVaSetValues(w,
                  XmNrow, row,
                  XmNrowIsExpanded, False,
                  NULL);
            cbs.reason = XmCR_COLLAPSE_ROW;
            XtCallCallbackList(w, t->tree.collapseCallback, (XtPointer)&cbs);
            }
      else
            {
            XtVaSetValues(w,
                  XmNrow, row,
                  XmNrowIsExpanded, True,
                  NULL);
            cbs.reason = XmCR_EXPAND_ROW;
            XtCallCallbackList(w, t->tree.expandCallback, (XtPointer)&cbs);
            }
      }

/* Only to be called through Grid class */
static XmLGridRow
_RowNew(Widget tree)
      {
      XmLGridWidgetClass sc;
      XmLTreeRow row;

      sc = (XmLGridWidgetClass)xmlTreeWidgetClass->core_class.superclass;
      row = (XmLTreeRow)sc->grid_class.rowNewProc(tree);
      row->tree.level = 0;
      row->tree.expands = False;
      row->tree.isExpanded = True;
      row->tree.hasSiblings = False;
      row->tree.stringWidth = 0;
      row->tree.stringWidthValid = False;
      return (XmLGridRow)row;
      }

/* Only to be called through Grid class */
static void
_GetRowValueMask(XmLGridWidget g,
                 char *s,
                 long *mask)
        {
      XmLGridWidgetClass sc;
      static XrmQuark qLevel, qExpands, qIsExpanded;
      static int quarksValid = 0;
      XrmQuark q;
 
      sc = (XmLGridWidgetClass)xmlTreeWidgetClass->core_class.superclass;
      sc->grid_class.getRowValueMaskProc(g, s, mask);
      if (!quarksValid)
            {
            qLevel = XrmStringToQuark(XmNrowLevel);
            qExpands = XrmStringToQuark(XmNrowExpands);
            qIsExpanded = XrmStringToQuark(XmNrowIsExpanded);
            quarksValid = 1;
            }
      q = XrmStringToQuark(s);
      if (q == qLevel)
            *mask |= XmLTreeRowLevel;
      else if (q == qExpands)
            *mask |= XmLTreeRowExpands;
      else if (q == qIsExpanded)
            *mask |= XmLTreeRowIsExpanded;
      }

/* Only to be called through Grid class */
static void
_GetRowValue(XmLGridWidget g,
             XmLGridRow r,
             XtArgVal value,
             long mask)
      {
      XmLGridWidgetClass sc;
      XmLTreeRow row;

      sc = (XmLGridWidgetClass)xmlTreeWidgetClass->core_class.superclass;
      sc->grid_class.getRowValueProc(g, r, value, mask);
      row = (XmLTreeRow)r;
      switch (mask)
            {
            case XmLTreeRowLevel:
                  *((int *)value) = row->tree.level;
                  break;
            case XmLTreeRowExpands:
                  *((Boolean *)value) = row->tree.expands;
                  break;
            case XmLTreeRowIsExpanded:
                  *((Boolean *)value) = row->tree.isExpanded;
                  break;
            }
      }

/* Only to be called through Grid class */
static int
_SetRowValues(XmLGridWidget g,
              XmLGridRow r,
              long mask)
      {
      XmLGridWidgetClass sc;
      int needsResize;
      XmLTreeRow row;
      XmLTreeWidget t;

      sc = (XmLGridWidgetClass)xmlTreeWidgetClass->core_class.superclass;
      needsResize = sc->grid_class.setRowValuesProc(g, r, mask);
      t = (XmLTreeWidget)g;
      row = (XmLTreeRow)r;
      if ((mask & XmLGridRowHeight) && needsResize)
            t->tree.recalcTreeWidth = 1;
      if (mask & XmLTreeRowLevel)
            {
            row->tree.level = t->tree.rowLevel;
            t->tree.recalcTreeWidth = 1;
            t->grid.vertVisChangedHint = 1;
            needsResize = 1;
            }
      if (mask & XmLTreeRowExpands)
            {
            row->tree.expands = t->tree.rowExpands;
            t->grid.vertVisChangedHint = 1;
            needsResize = 1;
            }
      if (mask & XmLTreeRowIsExpanded)
            {
            row->tree.isExpanded = t->tree.rowIsExpanded;
            t->grid.vertVisChangedHint = 1;
            needsResize = 1;
            }
      return needsResize;
      }

/* Only to be called through Grid class */
static int
_SetCellValuesResize(XmLGridWidget g,
                  XmLGridRow row,
                  XmLGridColumn col,
                  XmLGridCell cell,
                  long mask)
      {
      XmLGridWidgetClass sc;
      int needsResize;

      sc = (XmLGridWidgetClass)xmlTreeWidgetClass->core_class.superclass;
      needsResize = 0;
      if (col->grid.pos == g->grid.headingColCount &&
            row->grid.pos >= g->grid.headingRowCount &&
            row->grid.pos < g->grid.headingRowCount + g->grid.rowCount)
            {
            if (mask & XmLGridCellFontList)
                  {
                  row->grid.heightInPixelsValid = 0;
                  ((XmLTreeRow)row)->tree.stringWidthValid = False;
                  col->grid.widthInPixelsValid = 0;
                  needsResize = 1;
                  }
            if (mask & XmLGridCellString)
                  {
                  ((XmLTreeRow)row)->tree.stringWidthValid = False;
                  col->grid.widthInPixelsValid = 0;
                  needsResize = 1;
                  }
            }
      if (sc->grid_class.setCellValuesResizeProc(g, row, col, cell, mask))
            needsResize = 1;
      return needsResize;
      }

/*
  Utility
*/

static void
GetManagerForeground(Widget w,
                      int offset,
                      XrmValue *value)
      {
      XmLTreeWidget t;

      t = (XmLTreeWidget)w;
      value->addr = (caddr_t)&t->manager.foreground;
      }

static void
CreateDefaultPixmaps(XmLTreeWidget t)
      {
      Display *dpy;
      Window win;
      XWindowAttributes attr;
      XColor color;
      Pixmap pixmap;
      Pixel pixel;
      XImage *image;
      int i, x, y;
      enum { white = 0, black = 1, yellow = 2, gray = 3 };
      static unsigned short colors[4][3] =
            {
                  { 65535, 65535, 65535 },
                  { 0,         0,     0 },
                  { 57344, 57344,     0 },
                  { 32768, 32768, 32768 },
            };
      static unsigned char fileMask_bits[] =
            {
            0xf8, 0x0f, 0xfc, 0x1f, 0xfc, 0x3f, 0xfc, 0x7f, 0xfc, 0x7f, 0xfc, 0x7f,
            0xfc, 0x7f, 0xfc, 0x7f, 0xfc, 0x7f, 0xfc, 0x7f, 0xfc, 0x7f, 0xfc, 0x7f,
            0xfc, 0x7f, 0xfc, 0x7f, 0xfc, 0x7f, 0xf8, 0x7f
            };
      static unsigned char folderMask_bits[] =
            {
            0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0xf0, 0x0f, 0xfc, 0x3f, 0xfe, 0x7f,
            0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff,
            0xfe, 0xff, 0xfe, 0xff, 0xfc, 0xff, 0xf8, 0x7f
            };
      static unsigned char folderOpenMask_bits[] =
            {
            0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0xf0, 0x0f, 0xfc, 0x3f, 0xfe, 0x7f,
            0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xfe, 0xff,
            0xfc, 0xff, 0xfc, 0xff, 0xf8, 0xff, 0xf0, 0x7f
            };
      static char icons[3][16][16] =
            {
                  {
                  "   GGGGGGGGG    ",
                  "  GWWWWWWWWKK   ",
                  "  GWWWWWWWWKWK  ",
                  "  GWWWWWWWWKKKK ",
                  "  GWWWWWWWWWWGK ",
                  "  GWGGGGGGGWWGK ",
                  "  GWWKKKKKKKWGK ",
                  "  GWWWWWWWWWWGK ",
                  "  GWGGGGGGGWWGK ",
                  "  GWWKKKKKKKWGK ",
                  "  GWWWWWWWWWWGK ",
                  "  GWGGGGGGGWWGK ",
                  "  GWWKKKKKKKWGK ",
                  "  GWWWWWWWWWWGK ",
                  "  GGGGGGGGGGGGK ",
                  "   KKKKKKKKKKKK ",
                  },
                  {
                  "                ",
                  "                ",
                  "     GGGGGG     ",
                  "    GYYYYYYG    ",
                  "  GGYYYYYYYYGG  ",
                  " GWWWWWWWWWWWYG ",
                  " GWYYYYYYYYYYYGK",
                  " GWYYYYYYYYYYYGK",
                  " GWYYYYYYYYYYYGK",
                  " GWYYYYYYYYYYYGK",
                  " GWYYYYYYYYYYYGK",
                  " GWYYYYYYYYYYYGK",
                  " GWYYYYYYYYYYYGK",
                  " GYYYYYYYYYYYYGK",
                  "  GGGGGGGGGGGGKK",
                  "   KKKKKKKKKKKK ",
                  },
                  {
                  "                ",
                  "                ",
                  "     GGGGGG     ",
                  "    GYYYYYYG    ",
                  "  GGYYYYYYYYGG  ",
                  " GYYYYYYYYYYYYG ",
                  " GYYYYYYYYYYYYGK",
                  "GGGGGGGGGGGYYYGK",
                  "GWWWWWWWWWYKYYGK",
                  "GWYYYYYYYYYKYYGK",
                  " GYYYYYYYYYYKYGK",
                  " GYYYYYYYYYYKYGK",
                  "  GYYYYYYYYYYKGK",
                  "  GYYYYYYYYYYKGK",
                  "   GGGGGGGGGGGKK",
                  "    KKKKKKKKKKK ",
                  },
            };

      dpy = XtDisplay(t);
      win = XtWindow(t);
      XGetWindowAttributes(dpy, win, &attr);
      t->tree.filePixmask = XCreatePixmapFromBitmapData(dpy, win,
            (char *)fileMask_bits, 16, 16, 1L, 0L, 1);
      t->tree.folderPixmask = XCreatePixmapFromBitmapData(dpy, win,
            (char *)folderMask_bits, 16, 16, 1L, 0L, 1);
      t->tree.folderOpenPixmask = XCreatePixmapFromBitmapData(dpy, win,
            (char *)folderOpenMask_bits, 16, 16, 1L, 0L, 1);
      for (i = 0; i < 4; i++)
            {
            color.red = colors[i][0];
            color.green = colors[i][1];
            color.blue = colors[i][2];
            color.flags = DoRed | DoGreen | DoBlue;
            if (XAllocColor(dpy, attr.colormap, &color))
                  t->tree.pixColors[i] = color.pixel;
            else
                  {
                  color.flags = 0;
                  XAllocColor(dpy, attr.colormap, &color);
                  t->tree.pixColors[i] = color.pixel;
                  }
            }
      image = XCreateImage(dpy, attr.visual, attr.depth, ZPixmap, 0,
            NULL, 16, 16, XBitmapPad(dpy), 0);
      if (!image)
            XmLWarning((Widget)t,
                  "CreateDefaultPixmaps() - can't allocate image");
      else
            image->data = (char *)malloc(image->bytes_per_line * 16);
      for (i = 0; i < 3; i++)
            {
            pixmap = XCreatePixmap(dpy, win, 16, 16, attr.depth);
            for (x = 0; x < 16; x++)
                  for (y = 0; y < 16; y++)
                        {
                        switch (icons[i][y][x])
                              {
                              case ' ':
                                    pixel = t->core.background_pixel;
                                    break;
                              case 'W':
                                    pixel = t->tree.pixColors[white];
                                    break;
                              case 'K':
                                    pixel = t->tree.pixColors[black];
                                    break;
                              case 'Y':
                                    pixel = t->tree.pixColors[yellow];
                                    break;
                              case 'G':
                                    pixel = t->tree.pixColors[gray];
                                    break;
                              }
                        XPutPixel(image, x, y, pixel);
                        }
            if (image)
                  XPutImage(dpy, pixmap, t->grid.gc, image, 0, 0, 0, 0, 16, 16);
            if (i == 0)
                  t->tree.filePixmap = pixmap;
            else if (i == 1)
                  t->tree.folderPixmap = pixmap;
            else
                  t->tree.folderOpenPixmap = pixmap;
            }
      if (image)
            XDestroyImage(image);
      t->tree.defaultPixmapsCreated = 1;
      }

static XmLTreeWidget
WidgetToTree(Widget w,
             char *funcname)
      {
      char buf[256];

      if (!XmLIsTree(w))
            {
            sprintf(buf, "%s - widget not an XmLTree", funcname);
            XmLWarning(w, buf);
            return 0;
            }
      return (XmLTreeWidget)w;
      }

/*
   Public Functions
*/

Widget
XmLCreateTree(Widget parent,
              char *name,
              ArgList arglist,
              Cardinal argcount)
      {
      return XtCreateWidget(name, xmlTreeWidgetClass, parent,
            arglist, argcount);
      }

void
XmLTreeAddRow(Widget w,
              int level,
              Boolean expands,
              Boolean isExpanded,
              int position,
              Pixmap pixmap,
              Pixmap pixmask,
              XmString string)
      {
      XmLTreeRowDefinition row;

      row.level = level;
      row.expands = expands;
      row.isExpanded = isExpanded;
      row.pixmap = pixmap;
      row.pixmask = pixmask;
      row.string = string;
      XmLTreeAddRows(w, &row, 1, position);
      }

void 
XmLTreeAddRows(Widget w,
                XmLTreeRowDefinition *rows,
                int count,
                int position)
      {
      XmLTreeWidget t;
      XmLTreeRow row;
      int i, level;
      unsigned char layoutFrozen;

      t = WidgetToTree(w, "XmLTreeAddRows()");
      if (!t || count <= 0)
            return;
      if (position < 0 || position > t->grid.rowCount)
            position = t->grid.rowCount;
      layoutFrozen = t->grid.layoutFrozen;
      if (layoutFrozen == False)
            XtVaSetValues(w,
                  XmNlayoutFrozen, True,
                  NULL);
      XmLGridAddRows(w, XmCONTENT, position, count);
      for (i = 0; i < count; i++)
            {
            row = (XmLTreeRow)XmLGridGetRow(w, XmCONTENT, position + i);
            if (!row)
                  continue;
            level = rows[i].level;
            if (level < 0)
                  level = 0;
            row->tree.level = level;
            row->tree.expands = rows[i].expands;
            row->tree.isExpanded = rows[i].isExpanded;

            XtVaSetValues(w,
                  XmNrow, position + i,
                  XmNcolumn, 0,
                  XmNcellString, rows[i].string,
                  XmNcellPixmap, rows[i].pixmap,
                  XmNcellPixmapMask, rows[i].pixmask,
                  NULL);
            }
      if (layoutFrozen == False)
            XtVaSetValues(w,
                  XmNlayoutFrozen, False,
                  NULL);
      }



void
XmLTreeDeleteChildren(Widget w,
                      int row)
{
      XmLTreeWidget t;
      XmLTreeRow rowp;
      int ii, jj, level, rows;

      t = WidgetToTree(w, "XmLTreeDeleteChildren()");

      rowp = (XmLTreeRow)XmLGridGetRow(w, XmCONTENT, row);
    level = rowp->tree.level;

      rows = t->grid.rowCount;

      ii = row + 1;
      while (ii < rows)
      {
            rowp = (XmLTreeRow)XmLGridGetRow(w, XmCONTENT, ii);
            if (rowp->tree.level <= level)
                  break;
            ii++;
      }
      jj = ii - row - 1;

    if (jj > 0)
        XmLGridDeleteRows(w, XmCONTENT, row + 1, jj);
}


Generated by  Doxygen 1.6.0   Back to index