Logo Search packages:      
Sourcecode: vertex version File versions

editor.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>

#include "guiutils.h"
#include "v3dmp.h"
#include "v3dmodel.h"

#include "msglist.h" 
#include "primpalette.h"
#include "editor.h"
#include "editorcb.h"
#include "editorviewcb.h"
#include "editoridialog.h"
#include "editortdialog.h"
#include "editorheadercb.h"
#include "editorlightcb.h"
#include "editormodel.h"
#include "editormodelcb.h"
#include "editorp.h"
#include "editorpcb.h"
#include "editorpcreatecb.h"
#include "editorlist.h"
#include "editordnd.h"
#include "editortexture.h"
#include "editorprintcb.h"

#include "vpiinternal.h"
#include "vmastatusbar.h"
#include "vmacfg.h"
#include "vmacfglist.h"
#include "vma.h"

#include "messages.h"
#include "config.h"

#ifdef MEMWATCH
# include "memwatch.h"
#endif


#include "vertex.xpm"

#include "images/icon_new_20x20.xpm"
#include "images/icon_open_20x20.xpm"
#include "images/icon_save_20x20.xpm"
#include "images/icon_save_as_20x20.xpm"
#include "images/icon_backup_20x20.xpm" 
#include "images/icon_revert_20x20.xpm"
#include "images/icon_export_20x20.xpm"
#include "images/icon_import_20x20.xpm"
#include "images/icon_print_20x20.xpm"
#include "images/icon_close_20x20.xpm"
#include "images/icon_exit_20x20.xpm"

#include "images/icon_undo_20x20.xpm"
#include "images/icon_redo_20x20.xpm"
#include "images/icon_cut_20x20.xpm"
#include "images/icon_copy_20x20.xpm"
#include "images/icon_paste_20x20.xpm"
#include "images/icon_clipboard_20x20.xpm"
#include "images/icon_header_general_20x20.xpm"
#include "images/icon_secure_20x20.xpm"
#include "images/icon_insecure_20x20.xpm"
#include "images/icon_lighting_20x20.xpm"
#include "images/icon_mp_color_20x20.xpm"
#include "images/icon_texture_20x20.xpm"

#include "images/icon_model_create_20x20.xpm"
#include "images/icon_model_delete_20x20.xpm"
#include "images/icon_mp_delete_20x20.xpm"
#include "images/icon_winding_20x20.xpm"
#include "images/icon_unitlize_normal_20x20.xpm"
#include "images/icon_scale_20x20.xpm"
#include "images/icon_rotate_20x20.xpm"
#include "images/icon_translate_20x20.xpm"
#include "images/icon_mirror_20x20.xpm"
#include "images/icon_snap_20x20.xpm"
#include "images/icon_vertex_add_20x20.xpm"
#include "images/icon_vertex_remove_20x20.xpm"
#include "images/icon_scratchpad_20x20.xpm"

#include "images/icon_add_20x20.xpm"
#include "images/icon_remove_20x20.xpm"
#include "images/icon_properties_20x20.xpm"
#include "images/icon_options_20x20.xpm"
#include "images/icon_goto_20x20.xpm"

#include "images/icon_bulb_20x20.xpm"
#include "images/icon_about_20x20.xpm"

#include "images/icon_browse_20x20.xpm"
#include "images/icon_select_20x20.xpm"
#include "images/icon_vma_20x20.xpm"


guint EditorVertexPositionDecimals(void);
guint EditorVertexAngleDecimals(void);
gint EditorSelectedLightNumber(ma_editor_struct *editor);
gint EditorSelectedModelIndex(ma_editor_struct *editor);

static gint EditorBuildMenuBar(ma_editor_struct *editor, GtkWidget *parent);
static gint EditorBuildGeneralToolRibbon(
      ma_editor_struct *editor, GtkWidget *parent
);
static gint EditorBuildPrimitivesToolRibbon(
        ma_editor_struct *editor, GtkWidget *parent
);
static gint EditorBuildModelList(ma_editor_struct *editor, GtkWidget *parent);
static gint EditorBuildValuesList(ma_editor_struct *editor, GtkWidget *parent);
static gint EditorBuildViews(
      gpointer core_ptr, ma_editor_struct *editor, GtkWidget *parent
);

void EditorSetBusy(ma_editor_struct *editor);
void EditorSetReady(ma_editor_struct *editor);

ma_editor_struct *EditorCreate(gpointer core_ptr);
void EditorUpdateAppearance(ma_editor_struct *editor);
void EditorUpdateMenus(ma_editor_struct *editor);
static void EditorRenderMenuDestroy(ma_editor_struct *editor);
void EditorRenderMenuRegenerate(ma_editor_struct *editor);
void EditorSyncData(ma_editor_struct *editor);
void EditorReset(ma_editor_struct *editor, gbool unmap);
void EditorDelete(ma_editor_struct *editor);

void EditorMap(ma_editor_struct *editor);
void EditorUnmap(ma_editor_struct *editor);


#define MAX(a,b)        (((a) > (b)) ? (a) : (b))
#define MIN(a,b)        (((a) < (b)) ? (a) : (b))
#define CLIP(a,l,h)     (MIN(MAX((a),(l)),(h)))


/*
 *      Returns number of decimals to represent a vertex position
 *    from the global configuration options list.
 */
guint EditorVertexPositionDecimals(void)
{
      return(
          (guint)VMACFGItemListGetValueI(
            option, VMA_CFG_PARM_DATA_DECIMALS_POSITION
          )
      );
}

/*
 *    Returns number of decimals to represent a vertex angle
 *      from the global configuration options list.
 */
guint EditorVertexAngleDecimals(void)
{
        return(
            (guint)VMACFGItemListGetValueI(
                option, VMA_CFG_PARM_DATA_DECIMALS_ANGLE
            )
        );
}

/*
 *    Returns the selected light number on the given editor
 *    or -1 on error.
 *
 *    Returns whatever value is in the editor's light spin.
 */
gint EditorSelectedLightNumber(ma_editor_struct *editor)
{
      GtkSpinButton *spin;

      if(editor == NULL)
          return(-1);

      spin = (GtkSpinButton *)editor->primitive_light_num_spin;
      if(spin == NULL)
          return(-1);

      return(gtk_spin_button_get_value_as_int(spin));
}

/*
 *    Returns the selected model number on the given editor or -1
 *    on error.
 *
 *    Does not check if the returned index value is valid.
 */
gint EditorSelectedModelIndex(ma_editor_struct *editor)
{
        if(editor == NULL)
            return(-1);

        return(editor->selected_model_item);
}

/*
 *    Builds the menu bar and menus on to the editor and parents
 *    to the given parent widget (assumed to be a handle bar).
 *
 *    Note, list pop up menus are created in the EditorBuild*List()
 *    functions.
 *
 *    Inputs assumed valid, returns non-zero on error.
 */
static gint EditorBuildMenuBar(ma_editor_struct *editor, GtkWidget *parent)
{
      GtkWidget *menu_bar, *menu, *submenu, *w, *fw;
      gint accel_key;
      gpointer accel_group;
      guint accel_mods;
      gpointer client_data = (gpointer)editor;
      u_int8_t **icon;
      const gchar *label;
      void (*func_cb)(GtkWidget *, gpointer) = NULL;
      gint (*enter_cb)(gpointer, gpointer, gpointer) = (gpointer)EditorMenuItemEnterCB;

      /* Create menu bar. */
      menu_bar = (GtkWidget *)GUIMenuBarCreate(&accel_group);
      editor->menu_bar = menu_bar;
        gtk_container_add(GTK_CONTAINER(parent), menu_bar);
        gtk_widget_show(menu_bar);

#define DO_ADD_MENU_ITEM_LABEL      \
{ \
 w = GUIMenuItemCreate( \
  menu, GUI_MENU_ITEM_TYPE_LABEL, accel_group, \
  icon, label, accel_key, accel_mods, (void **)&fw, \
  client_data, func_cb \
 ); \
 GUISetMenuItemCrossingCB( \
  w, enter_cb, client_data, NULL, client_data \
 ); \
}
#define DO_ADD_MENU_ITEM_LABEL_NO_ENTERCB \
{ \
 w = GUIMenuItemCreate( \
  menu, GUI_MENU_ITEM_TYPE_LABEL, accel_group, \
  icon, label, accel_key, accel_mods, (void **)&fw, \
  client_data, func_cb \
 ); \
}
#define DO_ADD_MENU_ITEM_SUBMENU    \
{ \
 w = GUIMenuItemCreate( \
  menu, GUI_MENU_ITEM_TYPE_SUBMENU, accel_group, \
  icon, label, accel_key, accel_mods, (void **)&fw, \
  client_data, func_cb \
 ); \
 if(w != NULL) \
  GUIMenuItemSetSubMenu(w, submenu); \
}

#define DO_ADD_MENU_ITEM_CHECK  \
{ \
 w = GUIMenuItemCreate( \
  menu, GUI_MENU_ITEM_TYPE_CHECK, accel_group, \
  icon, label, accel_key, accel_mods, (void **)&fw, \
  client_data, func_cb \
 ); \
 GUISetMenuItemCrossingCB( \
  w, enter_cb, client_data, NULL, client_data \
 ); \
}

#define DO_ADD_MENU_SEP \
{ \
 w = GUIMenuItemCreate( \
  menu, GUI_MENU_ITEM_TYPE_SEPARATOR, NULL, \
  NULL, NULL, 0, 0, NULL, \
  NULL, NULL \
 ); \
}

      /* Create file menu. */
      menu = GUIMenuCreate();
      if(menu != NULL)
      {
          icon = (u_int8_t **)icon_new_20x20_xpm;
          label = "New";
          accel_key = 'n';
          accel_mods = GDK_CONTROL_MASK;
          func_cb = EditorNewFileCB;
          DO_ADD_MENU_ITEM_LABEL
            editor->new_mi = w;

          icon = (u_int8_t **)icon_open_20x20_xpm;
            label = "Open...";
          accel_key = 'o';
            accel_mods = GDK_CONTROL_MASK;
          func_cb = EditorOpenFileCB;
          DO_ADD_MENU_ITEM_LABEL
          editor->open_mi = w;

          icon = (u_int8_t **)icon_save_20x20_xpm;
            label = "Save";
            accel_key = 's';
            accel_mods = GDK_CONTROL_MASK;
            func_cb = EditorSaveFileCB;
            DO_ADD_MENU_ITEM_LABEL
            editor->save_mi = w;

          icon = (u_int8_t **)icon_save_as_20x20_xpm;
            label = "Save As...";
            accel_key = 'a';
            accel_mods = GDK_CONTROL_MASK;
            func_cb = EditorSaveAsFileCB;
            DO_ADD_MENU_ITEM_LABEL
            editor->save_as_mi = w;

          DO_ADD_MENU_SEP

            icon = (u_int8_t **)icon_backup_20x20_xpm;
            label = "Backup";
            accel_key = 0;
            accel_mods = 0;
            func_cb = EditorBackupCB;
            DO_ADD_MENU_ITEM_LABEL
            editor->backup_mi = w;

            icon = (u_int8_t **)icon_options_20x20_xpm;
            label = "Backup Preferences...";
            accel_key = 0;
            accel_mods = 0;
            func_cb = EditorBackupPreferencesCB;
            DO_ADD_MENU_ITEM_LABEL
          editor->backup_settings_mi = w;

            icon = (u_int8_t **)icon_revert_20x20_xpm;
            label = "Revert";
            accel_key = 0;
            accel_mods = 0;
            func_cb = EditorRevertFileCB;
            DO_ADD_MENU_ITEM_LABEL
            editor->revert_mi = w;

          DO_ADD_MENU_SEP

            icon = (u_int8_t **)icon_import_20x20_xpm;
            label = "Import...";
            accel_key = 0;
            accel_mods = 0;
            func_cb = EditorImportFileCB;
            DO_ADD_MENU_ITEM_LABEL   
            editor->import_mi = w;   

          icon = (u_int8_t **)icon_export_20x20_xpm;
            label = "Export...";
            accel_key = 'e';
            accel_mods = GDK_CONTROL_MASK;
            func_cb = EditorExportFileCB;
            DO_ADD_MENU_ITEM_LABEL
            editor->export_mi = w;

            DO_ADD_MENU_SEP

            icon = (u_int8_t **)icon_print_20x20_xpm;
            label = "Print...";
            accel_key = 'p';
            accel_mods = GDK_CONTROL_MASK;
            func_cb = EditorPrintCB;
            DO_ADD_MENU_ITEM_LABEL
          editor->print_mi = w;

            DO_ADD_MENU_SEP

          icon = (u_int8_t **)icon_close_20x20_xpm;
            label = "Close";
/*        accel_key = GDK_F4; */
          accel_key = 'w';
            accel_mods = GDK_CONTROL_MASK;
            func_cb = EditorCloseMCB;
            DO_ADD_MENU_ITEM_LABEL
          editor->close_mi = w;

            DO_ADD_MENU_SEP

          icon = (u_int8_t **)icon_exit_20x20_xpm;
            label = "Exit";
            accel_key = 'q';
            accel_mods = GDK_CONTROL_MASK;
            func_cb = EditorCloseAllMCB;
            DO_ADD_MENU_ITEM_LABEL
          editor->exit_mi = w;
      }
      GUIMenuAddToMenuBar(
          menu_bar, menu,
          "File",
          GUI_MENU_BAR_ALIGN_LEFT
      );

        /* Create edit menu. */
        menu = GUIMenuCreate();
        if(menu != NULL)
        {
            icon = (u_int8_t **)icon_undo_20x20_xpm;
            label = "Undo";
            accel_key = 'z';
            accel_mods = GDK_CONTROL_MASK;
            func_cb = EditorUndoCB;
            DO_ADD_MENU_ITEM_LABEL
          editor->undo_mi = w;
          editor->undo_milabel = fw;

            icon = (u_int8_t **)icon_redo_20x20_xpm;
            label = "Redo";
            accel_key = 'r';
            accel_mods = GDK_CONTROL_MASK;
            func_cb = EditorRedoCB;
            DO_ADD_MENU_ITEM_LABEL
          editor->redo_mi = w;
          editor->redo_milabel = fw;

            DO_ADD_MENU_SEP

            icon = (u_int8_t **)icon_cut_20x20_xpm;
            label = "Cut";
            accel_key = 'x';
            accel_mods = GDK_CONTROL_MASK;
            func_cb = EditorCutCB;
            DO_ADD_MENU_ITEM_LABEL
          editor->cut_mi = w;

            icon = (u_int8_t **)icon_copy_20x20_xpm;
            label = "Copy";
            accel_key = 'c';
            accel_mods = GDK_CONTROL_MASK;
            func_cb = EditorCopyCB;
            DO_ADD_MENU_ITEM_LABEL
            editor->copy_mi = w;

            icon = (u_int8_t **)icon_paste_20x20_xpm;
            label = "Paste";
            accel_key = 'v';
            accel_mods = GDK_CONTROL_MASK;
            func_cb = EditorPasteCB;
            DO_ADD_MENU_ITEM_LABEL
            editor->paste_mi = w;

            icon = (u_int8_t **)icon_clipboard_20x20_xpm;
            label = "Clipboard...";
            accel_key = 0;
            accel_mods = 0;
            func_cb = EditorMapClipboardCB;
            DO_ADD_MENU_ITEM_LABEL
          editor->clipboard_mi = w;

            DO_ADD_MENU_SEP

            icon = (u_int8_t **)icon_header_general_20x20_xpm;
            label = "Header...";
            accel_key = 0;
            accel_mods = 0;
            func_cb = EditorHeaderCB;
            DO_ADD_MENU_ITEM_LABEL
          editor->model_header_mi = w;;

            DO_ADD_MENU_SEP

            icon = (u_int8_t **)icon_secure_20x20_xpm;
            label = "Write Protect";
            accel_key = 0;
            accel_mods = 0;
            func_cb = EditorWriteProtectDisableCB;
            DO_ADD_MENU_ITEM_LABEL
            editor->write_protect_enabled_mi = w;;

            icon = (u_int8_t **)icon_insecure_20x20_xpm;
            label = "Write Protect";
            accel_key = 0;
            accel_mods = 0;
            func_cb = EditorWriteProtectEnableCB;
            DO_ADD_MENU_ITEM_LABEL
            editor->write_protect_disabled_mi = w;

            DO_ADD_MENU_SEP

            icon = NULL;
            label = "Sync Memory";
            accel_key = 0;
            accel_mods = 0;
            func_cb = EditorSyncMemoryCB;
            DO_ADD_MENU_ITEM_LABEL
            editor->sync_memory_mi = w;

          DO_ADD_MENU_SEP

            icon = (u_int8_t **)icon_options_20x20_xpm;
            label = "Preferences...";
            accel_key = 0;
            accel_mods = 0;
            func_cb = EditorPreferencesCB;
            DO_ADD_MENU_ITEM_LABEL
          editor->preferences_mi = w;
      }
        GUIMenuAddToMenuBar(
            menu_bar, menu,
            "Edit",
            GUI_MENU_BAR_ALIGN_LEFT
        );


        /* Create model menu. */ 
        menu = GUIMenuCreate();
        if(menu != NULL)   
        {   
            icon = (u_int8_t **)icon_model_create_20x20_xpm;
            label = "Create...";
            accel_key = 0;
            accel_mods = 0;
            func_cb = EditorModelCreateCB;
            DO_ADD_MENU_ITEM_LABEL
          editor->model_create_mi = w;

            icon = (u_int8_t **)icon_model_delete_20x20_xpm;
            label = "Delete";
            accel_key = 0;
            accel_mods = 0;
            func_cb = EditorModelDeleteCB;
            DO_ADD_MENU_ITEM_LABEL
          editor->model_delete_mi = w;

          DO_ADD_MENU_SEP

          icon = NULL;
            label = "Show";
            accel_key = 0;
            accel_mods = 0;
            func_cb = EditorToggleModelShowCB;
            DO_ADD_MENU_ITEM_CHECK
            editor->model_show_micheck = w;

          DO_ADD_MENU_SEP

            icon = (u_int8_t **)icon_properties_20x20_xpm;
            label = "Properties...";
            accel_key = 0;
            accel_mods = 0;
            func_cb = EditorModelPropertiesCB;
            DO_ADD_MENU_ITEM_LABEL
            editor->model_properties_mi = w;
      }
        GUIMenuAddToMenuBar(
            menu_bar, menu,
            "Model",
            GUI_MENU_BAR_ALIGN_LEFT
        );


      /* Create primitive create submenu (submenu in primitive menu). */
      submenu = EditorPrimitivesCreateCreateMenu(editor);
      editor->primitive_create_submenu = submenu;

        /* Create primitive menu. */
        menu = GUIMenuCreate();
        if(menu != NULL)
        {
            icon = (u_int8_t **)icon_add_20x20_xpm;
            label = "Create";
            accel_key = 0;
            accel_mods = 0;
            func_cb = NULL;
            DO_ADD_MENU_ITEM_SUBMENU
          editor->primitive_create_mi = w;

            icon = (u_int8_t **)icon_remove_20x20_xpm;
            label = "Delete";
            accel_key = GDK_Delete;
            accel_mods = GDK_CONTROL_MASK;
            func_cb = EditorPrimitiveDeleteCB;
            DO_ADD_MENU_ITEM_LABEL
            editor->primitive_delete_mi = w;

          DO_ADD_MENU_SEP

          icon = (u_int8_t **)icon_winding_20x20_xpm;
            label = "Flip Winding";
            accel_key = 'f';
            accel_mods = GDK_CONTROL_MASK;
            func_cb = EditorPrimitiveFlipWindingCB;
            DO_ADD_MENU_ITEM_LABEL
            editor->primitive_flip_winding_mi = w;

            icon = (u_int8_t **)icon_unitlize_normal_20x20_xpm;
            label = "Unitlize Normal";
            accel_key = 'u';
            accel_mods = GDK_CONTROL_MASK;
            func_cb = EditorPrimitiveUnitlizeNormalCB;
            DO_ADD_MENU_ITEM_LABEL
            editor->primitive_unitlize_normal_mi = w;

            icon = (u_int8_t **)icon_translate_20x20_xpm;
            label = "Translate Selected...";
            accel_key = 0;
            accel_mods = 0;
            func_cb = EditorPrimitiveTranslateCB;
            DO_ADD_MENU_ITEM_LABEL
            editor->primitive_translate_mi = w;

            icon = (u_int8_t **)icon_rotate_20x20_xpm;
            label = "Rotate Selected...";
            accel_key = 0;
            accel_mods = 0;
            func_cb = EditorPrimitiveRotateCB;
            DO_ADD_MENU_ITEM_LABEL
            editor->primitive_rotate_mi = w;

            icon = (u_int8_t **)icon_scale_20x20_xpm;
            label = "Scale Selected...";
            accel_key = 0;
            accel_mods = 0;
            func_cb = EditorPrimitiveScaleCB;
            DO_ADD_MENU_ITEM_LABEL
            editor->primitive_scale_mi = w;

            icon = (u_int8_t **)icon_mirror_20x20_xpm;
            label = "Mirror Selected..."; 
            accel_key = 'm';
            accel_mods = GDK_CONTROL_MASK;
            func_cb = EditorPrimitiveMirrorCB;
            DO_ADD_MENU_ITEM_LABEL
            editor->primitive_mirror_mi = w;

            icon = (u_int8_t **)icon_snap_20x20_xpm;
            label = "Snap Selected...";
            accel_key = 'y';
            accel_mods = GDK_CONTROL_MASK;
            func_cb = EditorPrimitiveSnapCB;
            DO_ADD_MENU_ITEM_LABEL
            editor->primitive_snap_mi = w;

            DO_ADD_MENU_SEP

            icon = (u_int8_t **)icon_vertex_add_20x20_xpm;
            label = "Add Vertex";
            accel_key = 0;
            accel_mods = 0;
            func_cb = EditorPrimitiveVertexAddCB;
            DO_ADD_MENU_ITEM_LABEL
          editor->primitive_add_vertex_mi = w;

            icon = (u_int8_t **)icon_vertex_remove_20x20_xpm;
            label = "Remove Vertex";
            accel_key = 0;  
            accel_mods = 0;
            func_cb = EditorPrimitiveVertexRemoveCB;
            DO_ADD_MENU_ITEM_LABEL
          editor->primitive_remove_vertex_mi = w;

            DO_ADD_MENU_SEP

            icon = NULL;
            label = "Insert To ScratchPad";
            accel_key = 0;
            accel_mods = 0;
            func_cb = EditorScratchPadVertexInsertCB;
            DO_ADD_MENU_ITEM_LABEL
            editor->primitive_scratchpad_insert_mi = w;

            icon = NULL;
            label = "Append To ScratchPad";
            accel_key = 0;
            accel_mods = 0;
            func_cb = EditorScratchPadVertexAppendCB;
            DO_ADD_MENU_ITEM_LABEL
            editor->primitive_scratchpad_append_mi = w;

            icon = NULL;
            label = "Edit ScratchPad...";
            accel_key = 0;
            accel_mods = 0;
            func_cb = EditorScratchPadVertexEditCB;
            DO_ADD_MENU_ITEM_LABEL
            editor->primitive_scratchpad_edit_mi = w;
      }
        editor->primitive_mh = GUIMenuAddToMenuBar(
            menu_bar, menu,
            "Primitive",
            GUI_MENU_BAR_ALIGN_LEFT
        );


      /* Create surface menu. */
      menu = GUIMenuCreate();
        if(menu != NULL)   
        {
            icon = (u_int8_t **)icon_mp_color_20x20_xpm;
            label = "Color...";
            accel_key = 'j';
            accel_mods = GDK_CONTROL_MASK;
            func_cb = EditorMapClrSelCB;
            DO_ADD_MENU_ITEM_LABEL
          editor->surface_clrsel_mi = w;

            icon = (u_int8_t **)icon_lighting_20x20_xpm;
            label = "Lighting...";
            accel_key = 'l';
            accel_mods = GDK_CONTROL_MASK;
            func_cb = EditorLightPropertiesCB;
            DO_ADD_MENU_ITEM_LABEL
          editor->surface_lighting_mi = w;

            icon = (u_int8_t **)icon_texture_20x20_xpm;
            label = "Texture...";
            accel_key = 't';
            accel_mods = GDK_CONTROL_MASK;
            func_cb = EditorMapTextureBrowserCB;
            DO_ADD_MENU_ITEM_LABEL
          editor->surface_texture_browser_mi = w;
      }
        GUIMenuAddToMenuBar(
            menu_bar, menu,
            "Surface",
            GUI_MENU_BAR_ALIGN_LEFT
        );

        /* Create render menu. */
        editor->render_menu = menu = GUIMenuCreate();
        if(menu != NULL)
        {

      }
      GUIMenuAddToMenuBar(
            menu_bar, menu,
            "Render",
            GUI_MENU_BAR_ALIGN_LEFT
        );

      /* Create windows menu. */
        menu = GUIMenuCreate();
        if(menu != NULL)
        {
            icon = (u_int8_t **)icon_vma_20x20_xpm;
            label = "New Editor...";
            accel_key = 0;
            accel_mods = 0;
            client_data = editor->core_ptr;
            func_cb = VMANewEditorCB;
            DO_ADD_MENU_ITEM_LABEL_NO_ENTERCB
            editor->window_vertex_mi = w;
          GUISetMenuItemCrossingCB(w, enter_cb, editor, NULL, editor);

            icon = (u_int8_t **)icon_mp_color_20x20_xpm;
            label = "Color Selector...";
            accel_key = 0;
            accel_mods = 0;
            client_data = editor;
            func_cb = EditorMapClrSelCB;
            DO_ADD_MENU_ITEM_LABEL
            editor->window_clrsel_mi = w;

            icon = (u_int8_t **)icon_lighting_20x20_xpm;
            label = "Lighting...";
            accel_key = 0;
            accel_mods = 0;
            client_data = editor;
            func_cb = EditorLightPropertiesCB;
            DO_ADD_MENU_ITEM_LABEL
            editor->window_lights_mi = w;

            icon = (u_int8_t **)icon_texture_20x20_xpm;
            label = "Texture Browser...";
            accel_key = 0;
            accel_mods = 0;
            client_data = editor;
            func_cb = EditorMapTextureBrowserCB;
            DO_ADD_MENU_ITEM_LABEL
            editor->window_texture_browser_mi = w;

            icon = (u_int8_t **)icon_scratchpad_20x20_xpm; 
            label = "ScratchPad...";
            accel_key = 0;
            accel_mods = 0;
            client_data = editor->core_ptr;
            func_cb = VMAScratchPadMapCB;
            DO_ADD_MENU_ITEM_LABEL_NO_ENTERCB
          editor->window_scratchpad_mi = w;
            GUISetMenuItemCrossingCB(w, enter_cb, editor, NULL, editor);  

          client_data = editor;
      }
      GUIMenuAddToMenuBar(
            menu_bar, menu,
            "Windows",
            GUI_MENU_BAR_ALIGN_LEFT
        );


        /* Create help menu. */
        menu = GUIMenuCreate();
        if(menu != NULL)
        {
          icon = NULL;
          label = "Contents";
          accel_key = GDK_F1;
            accel_mods = 0;
          client_data = (void *)editor->core_ptr;
            func_cb = VMAHelpContentsCB;
            DO_ADD_MENU_ITEM_LABEL_NO_ENTERCB
            GUISetMenuItemCrossingCB(  
                w, enter_cb, editor, NULL, editor
            );  
          editor->help_contents_mi = w;

            DO_ADD_MENU_SEP

            icon = NULL;
            label = "Tutorials";
            accel_key = 0;
            accel_mods = 0;
            client_data = (void *)editor->core_ptr;
            func_cb = VMAHelpTutorialCB;
            DO_ADD_MENU_ITEM_LABEL_NO_ENTERCB
            GUISetMenuItemCrossingCB(  
                w, enter_cb, editor, NULL, editor
            );
          editor->help_tutorial_mi = w;

            icon = NULL;
            label = "Viewing";
            accel_key = 0;
            accel_mods = 0;
            client_data = (void *)editor->core_ptr;
            func_cb = VMAHelpViewingCB;
            DO_ADD_MENU_ITEM_LABEL_NO_ENTERCB
            GUISetMenuItemCrossingCB(
                w, enter_cb, editor, NULL, editor
            );
          editor->help_viewing_mi = w;

            icon = NULL;
            label = "Keyboard";
            accel_key = 0;
            accel_mods = 0;
            client_data = (void *)editor->core_ptr;
            func_cb = VMAHelpKeyboardCB;
            DO_ADD_MENU_ITEM_LABEL_NO_ENTERCB
            GUISetMenuItemCrossingCB(
                w, enter_cb, editor, NULL, editor
            );
          editor->help_keyboard_mi = w;

            icon = NULL;
            label = "V3D Format";
            accel_key = 0;
            accel_mods = 0;
            client_data = (void *)editor->core_ptr;
            func_cb = VMAHelpV3DFormatCB;
            DO_ADD_MENU_ITEM_LABEL_NO_ENTERCB
            GUISetMenuItemCrossingCB(  
                w, enter_cb, editor, NULL, editor
            );
          editor->help_v3d_format_mi = w;

            icon = NULL;
            label = "Plug-Ins";
            accel_key = 0;
            accel_mods = 0;
            client_data = (void *)editor->core_ptr;
            func_cb = VMAHelpPluginsCB;
            DO_ADD_MENU_ITEM_LABEL_NO_ENTERCB
            GUISetMenuItemCrossingCB(
                w, enter_cb, editor, NULL, editor
            );
            editor->help_plugins_mi = w;

          DO_ADD_MENU_SEP

          icon = (u_int8_t **)icon_bulb_20x20_xpm;
            label = "Tip Of The Day";
            accel_key = 0;
            accel_mods = 0;
            client_data = (void *)editor->core_ptr;
            func_cb = VMATipOfDayCB;
            DO_ADD_MENU_ITEM_LABEL_NO_ENTERCB
            GUISetMenuItemCrossingCB(
                w, enter_cb, editor, NULL, editor
            );
          editor->help_tipofday_mi = w;

          DO_ADD_MENU_SEP

          icon = (u_int8_t **)icon_about_20x20_xpm;
            label = "About...";
            accel_key = 0;
            accel_mods = 0;
          client_data = (void *)editor->core_ptr;
            func_cb = VMAAboutDialogMapCB;
            DO_ADD_MENU_ITEM_LABEL_NO_ENTERCB
            GUISetMenuItemCrossingCB(
                w, enter_cb, editor, NULL, editor
            );
          editor->help_about_mi = w;

          client_data = (void *)editor;
        }
        GUIMenuAddToMenuBar(
            menu_bar, menu,
            "Help",
            GUI_MENU_BAR_ALIGN_RIGHT
        );

#undef DO_ADD_MENU_ITEM_LABEL
#undef DO_ADD_MENU_ITEM_LABEL_NO_ENTERCB
#undef DO_ADD_MENU_ITEM_SUBMENU
#undef DO_ADD_MENU_ITEM_CHECK
#undef DO_ADD_MENU_SEP

      /* Attach accel group to toplevel window. */
      if((editor->toplevel != NULL) &&
           (accel_group != NULL)
      )
      {
          gtk_window_add_accel_group(
            GTK_WINDOW(editor->toplevel),
            (GtkAccelGroup *)accel_group
          );
      }

      return(0);
}


/*
 *      Builds the general tool ribbon, parent is assumed to be a
 *    handle box.
 * 
 *      Inputs assumed valid, returns non-zero on error.
 */
static gint EditorBuildGeneralToolRibbon(ma_editor_struct *editor, GtkWidget *parent)
{
      const gchar *msglist[] = VMA_MSGLIST_EDITOR_TOOLTIPS;
      GtkWidget *w, *parent2, *parent3;
      gint border_major = 5;
      gint bw = 60, bh = 50;
      gint sw = 5, sh = -1;
        gint (*enter_cb)(gpointer, gpointer, gpointer) = (gpointer)EditorMenuItemEnterCB;
 

      /* Create hbox to hold all general tool ribbon buttons. */
      w = gtk_hbox_new(FALSE, 0);
      editor->general_tool_ribbon = w;
        gtk_container_add(GTK_CONTAINER(parent), w);
        gtk_container_border_width(GTK_CONTAINER(w), 2);
        gtk_widget_show(w);
      parent2 = w;

#define DO_ADD_SEPARATOR      \
{ \
 w = gtk_vbox_new(TRUE, 0); \
 gtk_widget_set_usize(w, sw, sh); \
 gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0); \
 gtk_widget_show(w); \
 parent3 = w; \
 w = gtk_vseparator_new(); \
 gtk_box_pack_start(GTK_BOX(parent3), w, TRUE, TRUE, border_major); \
 gtk_widget_show(w); \
}

      /* New model set. */
      editor->new_btn = w = GUIButtonPixmapLabelV(
          (u_int8_t **)icon_new_20x20_xpm, "New", NULL
      );
      gtk_button_set_relief(GTK_BUTTON(w), GTK_RELIEF_NONE);
      gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
        gtk_widget_set_usize(w, bw, bh);
        gtk_signal_connect(
            GTK_OBJECT(w), "enter_notify_event",
            GTK_SIGNAL_FUNC(enter_cb),
            (gpointer)editor
        );
        gtk_signal_connect(
            GTK_OBJECT(w), "clicked",
            GTK_SIGNAL_FUNC(EditorNewFileCB),
            (gpointer)editor
        );
      GUISetWidgetTip(
          w,
          MsgListMatchCaseMessage(
            msglist, VMA_MSGNAME_EDITOR_MODELFILE_NEW
          )
      );
        gtk_widget_show(w);

      /* Open model file. */
      editor->open_btn = w = GUIButtonPixmapLabelV(
            (u_int8_t **)icon_open_20x20_xpm, "Open...", NULL
        );
      gtk_button_set_relief(GTK_BUTTON(w), GTK_RELIEF_NONE);
        gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
        gtk_widget_set_usize(w, bw, bh);
      gtk_signal_connect(
            GTK_OBJECT(w), "enter_notify_event",
            GTK_SIGNAL_FUNC(enter_cb),
            (gpointer)editor
        );
        gtk_signal_connect(
            GTK_OBJECT(w), "clicked",
            GTK_SIGNAL_FUNC(EditorOpenFileCB),
            (gpointer)editor
        );
        GUISetWidgetTip(
            w,
            MsgListMatchCaseMessage(
                msglist, VMA_MSGNAME_EDITOR_MODELFILE_OPEN
            )
        );
      gtk_widget_show(w);

        /* Save model file. */
      editor->save_btn = w = GUIButtonPixmapLabelV(
            (u_int8_t **)icon_save_20x20_xpm, "Save", NULL
        );
      gtk_button_set_relief(GTK_BUTTON(w), GTK_RELIEF_NONE);
        gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
        gtk_widget_set_usize(w, bw, bh);
        gtk_signal_connect(
            GTK_OBJECT(w), "enter_notify_event",
            GTK_SIGNAL_FUNC(enter_cb),
            (gpointer)editor
        );
        gtk_signal_connect(
            GTK_OBJECT(w), "clicked",
            GTK_SIGNAL_FUNC(EditorSaveFileCB),
            (gpointer)editor
        );
        GUISetWidgetTip(
            w,
            MsgListMatchCaseMessage(
                msglist, VMA_MSGNAME_EDITOR_MODELFILE_SAVE
            )
        );
        gtk_widget_show(w);

        /* Save model to an alternate name. */
      editor->save_as_btn = w = GUIButtonPixmapLabelV(
            (u_int8_t **)icon_save_as_20x20_xpm, "Save As", NULL
        );
        gtk_button_set_relief(GTK_BUTTON(w), GTK_RELIEF_NONE);
        gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
        gtk_widget_set_usize(w, bw, bh);
        gtk_signal_connect(
            GTK_OBJECT(w), "enter_notify_event",
            GTK_SIGNAL_FUNC(enter_cb),
            (gpointer)editor
        );
        gtk_signal_connect(
            GTK_OBJECT(w), "clicked",
            GTK_SIGNAL_FUNC(EditorSaveAsFileCB),
            (gpointer)editor
        );
        GUISetWidgetTip(
            w,
            MsgListMatchCaseMessage(
                msglist, VMA_MSGNAME_EDITOR_MODELFILE_SAVEAS
            )
        );
        gtk_widget_show(w);

      DO_ADD_SEPARATOR

        /* Import model from alternate file format. */
      editor->import_btn = w = GUIButtonPixmapLabelV(
            (u_int8_t **)icon_import_20x20_xpm, "Import", NULL
        );
        gtk_button_set_relief(GTK_BUTTON(w), GTK_RELIEF_NONE);
        gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
        gtk_widget_set_usize(w, bw, bh);
        gtk_signal_connect(
            GTK_OBJECT(w), "enter_notify_event",
            GTK_SIGNAL_FUNC(enter_cb),
            (gpointer)editor
        );
        gtk_signal_connect(
            GTK_OBJECT(w), "clicked",
            GTK_SIGNAL_FUNC(EditorImportFileCB),
            (gpointer)editor
        );
        GUISetWidgetTip(
            w,
            MsgListMatchCaseMessage(
                msglist, VMA_MSGNAME_EDITOR_IMPORT
            )
        );
        gtk_widget_show(w);

        /* Export model to alternate file format. */
      editor->export_btn = w = GUIButtonPixmapLabelV(
            (u_int8_t **)icon_export_20x20_xpm, "Export", NULL
        );
        gtk_button_set_relief(GTK_BUTTON(w), GTK_RELIEF_NONE);
        gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
        gtk_widget_set_usize(w, bw, bh);
        gtk_signal_connect(
            GTK_OBJECT(w), "enter_notify_event",
            GTK_SIGNAL_FUNC(enter_cb),
            (gpointer)editor
        );
        gtk_signal_connect(
            GTK_OBJECT(w), "clicked",
            GTK_SIGNAL_FUNC(EditorExportFileCB),
            (gpointer)editor
        );
        GUISetWidgetTip(
            w,
            MsgListMatchCaseMessage(
                msglist, VMA_MSGNAME_EDITOR_EXPORT
            )
        );
        gtk_widget_show(w);

      DO_ADD_SEPARATOR

        /* Print. */
      editor->print_btn = w = GUIButtonPixmapLabelV(
            (u_int8_t **)icon_print_20x20_xpm, "Print", NULL
        );  
        gtk_button_set_relief(GTK_BUTTON(w), GTK_RELIEF_NONE);
        gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
        gtk_widget_set_usize(w, bw, bh);
        gtk_signal_connect(
            GTK_OBJECT(w), "enter_notify_event",
            GTK_SIGNAL_FUNC(enter_cb),
            (gpointer)editor
        );
        gtk_signal_connect(
            GTK_OBJECT(w), "clicked",
            GTK_SIGNAL_FUNC(EditorPrintCB),
            (gpointer)editor
        );
        GUISetWidgetTip(
            w,
            MsgListMatchCaseMessage(
                msglist, VMA_MSGNAME_EDITOR_PRINT
            )
        );
        gtk_widget_show(w);

        /* Separator. */
        w = gtk_label_new("");
        gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
        gtk_widget_set_usize(w, sw, sh);
        gtk_widget_show(w);

        /* Undo last operation. */
      editor->undo_btn = w = GUIButtonPixmapLabelV(
            (u_int8_t **)icon_undo_20x20_xpm, "Undo", NULL
        );
        gtk_button_set_relief(GTK_BUTTON(w), GTK_RELIEF_NONE);
        gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
        gtk_widget_set_usize(w, bw, bh);
        gtk_signal_connect(
            GTK_OBJECT(w), "enter_notify_event",
            GTK_SIGNAL_FUNC(enter_cb),
            (gpointer)editor
        );
        gtk_signal_connect(
            GTK_OBJECT(w), "clicked",
            GTK_SIGNAL_FUNC(EditorUndoCB),
            (gpointer)editor
        );
        GUISetWidgetTip(
            w,
            MsgListMatchCaseMessage(
                msglist, VMA_MSGNAME_EDITOR_UNDO
            )
        );
        gtk_widget_show(w);

        /* Redo last operation. */
      editor->redo_btn = w = GUIButtonPixmapLabelV(
            (u_int8_t **)icon_redo_20x20_xpm, "Redo", NULL
        );
        gtk_button_set_relief(GTK_BUTTON(w), GTK_RELIEF_NONE);
        gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
        gtk_widget_set_usize(w, bw, bh);
        gtk_signal_connect(
            GTK_OBJECT(w), "enter_notify_event",
            GTK_SIGNAL_FUNC(enter_cb),
            (gpointer)editor
        );
        gtk_signal_connect(
            GTK_OBJECT(w), "clicked",
            GTK_SIGNAL_FUNC(EditorRedoCB),
            (gpointer)editor
        );
        GUISetWidgetTip(
            w,
            MsgListMatchCaseMessage(
                msglist, VMA_MSGNAME_EDITOR_REDO
            )
        );
        gtk_widget_show(w);

#undef DO_ADD_SEPARATOR

      return(0);
}

/*
 *      Builds the primitives tool ribbon, parent is assumed to be a
 *      handle box.
 *
 *      Inputs assumed valid, returns non-zero on error.
 */
static gint EditorBuildPrimitivesToolRibbon(
        ma_editor_struct *editor, GtkWidget *parent
)
{
        const gchar *msglist[] = VMA_MSGLIST_EDITOR_TOOLTIPS;
        GtkWidget *w, *fw, *parent2, *menu;
        gint bw = 25, bh = 25;
        gint sw = 5, sh = 25;
      GtkAdjustment *adj;

      const gchar *label;
        gint accel_key;
        gpointer accel_group;
        guint accel_mods;
        u_int8_t **icon;
        gpointer mclient_data = (gpointer)editor;
        void (*func_cb)(GtkWidget *, gpointer) = NULL;
        gint (*enter_cb)(gpointer, gpointer, gpointer) = (gpointer)EditorMenuItemEnterCB;


#define DO_ADD_MENU_ITEM_LABEL      \
{ \
 w = GUIMenuItemCreate( \
  menu, GUI_MENU_ITEM_TYPE_LABEL, accel_group, \
  icon, label, accel_key, accel_mods, (void **)&fw, \
  mclient_data, func_cb \
 ); \
 GUISetMenuItemCrossingCB( \
  w, enter_cb, mclient_data, NULL, mclient_data \
 ); \
}
#define DO_ADD_MENU_ITEM_CHECK      \
{ \
 w = GUIMenuItemCreate( \
  menu, GUI_MENU_ITEM_TYPE_CHECK, accel_group, \
  icon, label, accel_key, accel_mods, (void **)&fw, \
  mclient_data, func_cb \
 ); \
 GUISetMenuItemCrossingCB( \
  w, enter_cb, mclient_data, NULL, mclient_data \
 ); \
}
#define DO_ADD_MENU_SEP       \
{ \
 w = GUIMenuItemCreate( \
  menu, GUI_MENU_ITEM_TYPE_SEPARATOR, NULL, \
  NULL, NULL, 0, 0, NULL, \
  NULL, NULL \
 ); \
}


        /* Create hbox to hold all primitives tool ribbon buttons. */
        w = gtk_hbox_new(FALSE, 0);
        editor->primitives_tool_ribbon = w;
        gtk_container_add(GTK_CONTAINER(parent), w);
        gtk_container_border_width(GTK_CONTAINER(w), 2);
        gtk_widget_show(w);
        parent2 = w;


        /* Edit model header items. */
        editor->model_header_btn = w = (GtkWidget *)GUIButtonPixmap(
            (u_int8_t **)icon_header_general_20x20_xpm
        );
        gtk_button_set_relief(GTK_BUTTON(w), GTK_RELIEF_NONE);
        gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
        gtk_widget_set_usize(w, bw, bh);
        gtk_signal_connect(
            GTK_OBJECT(w), "clicked",
            GTK_SIGNAL_FUNC(EditorHeaderCB),
            (gpointer)editor
        );
        GUISetWidgetTip(
            w,
            MsgListMatchCaseMessage(
                msglist, VMA_MSGNAME_EDITOR_MODEL_HEADER
            )
        );
        gtk_widget_show(w);

        /* Separator. */
        w = gtk_label_new("");
        gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
        gtk_widget_set_usize(w, sw, sh);
        gtk_widget_show(w);

        /* Create model. */
        editor->model_create_btn = w = (GtkWidget *)GUIButtonPixmap(
            (u_int8_t **)icon_model_create_20x20_xpm
        );
        gtk_button_set_relief(GTK_BUTTON(w), GTK_RELIEF_NONE);
        gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
        gtk_widget_set_usize(w, bw, bh);
        gtk_signal_connect(
            GTK_OBJECT(w), "clicked",
            GTK_SIGNAL_FUNC(EditorModelCreateCB),
            (gpointer)editor
      );
        GUISetWidgetTip(
            w,
            MsgListMatchCaseMessage(
                msglist, VMA_MSGNAME_EDITOR_MODEL_CREATE
            )
        );
      gtk_widget_show(w);

        /* Delete model. */
        editor->model_delete_btn = w = (GtkWidget *)GUIButtonPixmap(
            (u_int8_t **)icon_model_delete_20x20_xpm
        );
        gtk_button_set_relief(GTK_BUTTON(w), GTK_RELIEF_NONE);
        gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
        gtk_widget_set_usize(w, bw, bh);
        gtk_signal_connect(
            GTK_OBJECT(w), "clicked",
            GTK_SIGNAL_FUNC(EditorModelDeleteCB),
            (gpointer)editor
        );
        GUISetWidgetTip(
            w,
            MsgListMatchCaseMessage(
                msglist, VMA_MSGNAME_EDITOR_MODEL_DELETE
            )
        );
        gtk_widget_show(w);

        /* Separator. */
        w = gtk_label_new("");
        gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
        gtk_widget_set_usize(w, sw, sh);
        gtk_widget_show(w);

        /* Model properties. */
        editor->model_properties_btn = w = (GtkWidget *)GUIButtonPixmap(
            (u_int8_t **)icon_properties_20x20_xpm
        );
        gtk_button_set_relief(GTK_BUTTON(w), GTK_RELIEF_NONE);
        gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
        gtk_widget_set_usize(w, bw, bh);
        gtk_signal_connect(
            GTK_OBJECT(w), "clicked",
            GTK_SIGNAL_FUNC(EditorModelPropertiesCB),
            (gpointer)editor
        );
        GUISetWidgetTip(
            w,
            MsgListMatchCaseMessage(
                msglist, VMA_MSGNAME_EDITOR_MODEL_PROPERTIES
            )
        );
        gtk_widget_show(w);

        /* Separator. */   
        w = gtk_label_new("");
        gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
        gtk_widget_set_usize(w, sw, sh);
        gtk_widget_show(w);

      /* Primitives palette. */
        editor->prim_palette = VMAPrimPaletteNew(
            editor->core_ptr, editor,
            (editor->toplevel == NULL) ? NULL : editor->toplevel->window,
            (gpointer)editor,
            NULL,
            EditorPrimitivePrimPaletteCreateCB
        );
        if(editor->prim_palette != NULL)
        {
          w = editor->prim_palette->toplevel;

            gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
            gtk_widget_show(w);
        }

        /* Separator. */
        w = gtk_label_new("");
        gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
        gtk_widget_set_usize(w, sw, sh);
        gtk_widget_show(w);

        /* Delete primitive. */
        editor->primitive_delete_btn = w = (GtkWidget *)GUIButtonPixmap(
            (u_int8_t **)icon_mp_delete_20x20_xpm
        );
        gtk_button_set_relief(GTK_BUTTON(w), GTK_RELIEF_NONE);
        gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
        gtk_widget_set_usize(w, bw, bh);
        gtk_signal_connect(
            GTK_OBJECT(w), "clicked",
            GTK_SIGNAL_FUNC(EditorPrimitiveDeleteCB),
            (gpointer)editor
        );
        GUISetWidgetTip(
            w,
            MsgListMatchCaseMessage(
                msglist, VMA_MSGNAME_EDITOR_PRIMITIVE_DELETE
            )
        );
        gtk_widget_show(w);

        /* Separator. */
        w = gtk_label_new("");
        gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
        gtk_widget_set_usize(w, sw, sh);
        gtk_widget_show(w);

        /* Flip winding. */
        editor->primitive_flip_winding_btn = w = (GtkWidget *)GUIButtonPixmap(
            (u_int8_t **)icon_winding_20x20_xpm
        );
        gtk_button_set_relief(GTK_BUTTON(w), GTK_RELIEF_NONE);
        gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
        gtk_widget_set_usize(w, bw, bh);
        gtk_signal_connect(
            GTK_OBJECT(w), "clicked",
            GTK_SIGNAL_FUNC(EditorPrimitiveFlipWindingCB),
            (gpointer)editor
        );
        GUISetWidgetTip(
            w,
            MsgListMatchCaseMessage(
                msglist, VMA_MSGNAME_EDITOR_PRIMITIVE_FLIP_WINDING
            )
        );
        gtk_widget_show(w);

        /* Unitlize normal. */
        editor->primitive_unitlize_normal_btn = w = (GtkWidget *)GUIButtonPixmap(
            (u_int8_t **)icon_unitlize_normal_20x20_xpm
        );
        gtk_button_set_relief(GTK_BUTTON(w), GTK_RELIEF_NONE);
        gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
        gtk_widget_set_usize(w, bw, bh);
        gtk_signal_connect(
            GTK_OBJECT(w), "clicked",
            GTK_SIGNAL_FUNC(EditorPrimitiveUnitlizeNormalCB),
            (gpointer)editor
        );
        GUISetWidgetTip(
            w,
            MsgListMatchCaseMessage(
                msglist, VMA_MSGNAME_EDITOR_PRIMITIVE_UNITLIZE_NORMAL
            )
        );   
        gtk_widget_show(w);

        /* Translate. */
        editor->primitive_translate_btn = w = (GtkWidget *)GUIButtonPixmap(
            (u_int8_t **)icon_translate_20x20_xpm
        );
        gtk_button_set_relief(GTK_BUTTON(w), GTK_RELIEF_NONE);
        gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
        gtk_widget_set_usize(w, bw, bh);
        gtk_signal_connect(
            GTK_OBJECT(w), "clicked",
            GTK_SIGNAL_FUNC(EditorPrimitiveTranslateCB),
            (gpointer)editor
        );
        GUISetWidgetTip(
            w,
            MsgListMatchCaseMessage(  
                msglist, VMA_MSGNAME_EDITOR_PRIMITIVE_TRANSLATE
            )
        );
        gtk_widget_show(w);

        /* Rotate. */
        editor->primitive_rotate_btn = w = (GtkWidget *)GUIButtonPixmap(
            (u_int8_t **)icon_rotate_20x20_xpm
        );
        gtk_button_set_relief(GTK_BUTTON(w), GTK_RELIEF_NONE);
        gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
        gtk_widget_set_usize(w, bw, bh);
        gtk_signal_connect(
            GTK_OBJECT(w), "clicked",
            GTK_SIGNAL_FUNC(EditorPrimitiveRotateCB),
            (gpointer)editor
        );
        GUISetWidgetTip(
            w,
            MsgListMatchCaseMessage(
                msglist, VMA_MSGNAME_EDITOR_PRIMITIVE_ROTATE
            )
        );   
        gtk_widget_show(w);

        /* Scale. */
        editor->primitive_scale_btn = w = (GtkWidget *)GUIButtonPixmap(
            (u_int8_t **)icon_scale_20x20_xpm
        );
        gtk_button_set_relief(GTK_BUTTON(w), GTK_RELIEF_NONE);
        gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
        gtk_widget_set_usize(w, bw, bh);
        gtk_signal_connect(
            GTK_OBJECT(w), "clicked",
            GTK_SIGNAL_FUNC(EditorPrimitiveScaleCB),
            (gpointer)editor
        );
        GUISetWidgetTip(
            w,
            MsgListMatchCaseMessage(
                msglist, VMA_MSGNAME_EDITOR_PRIMITIVE_SCALE
            )
        );
        gtk_widget_show(w);

        /* Mirror. */
        editor->primitive_mirror_btn = w = (GtkWidget *)GUIButtonPixmap(
            (u_int8_t **)icon_mirror_20x20_xpm
        );
        gtk_button_set_relief(GTK_BUTTON(w), GTK_RELIEF_NONE);
        gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
        gtk_widget_set_usize(w, bw, bh);
        gtk_signal_connect(
            GTK_OBJECT(w), "clicked",
            GTK_SIGNAL_FUNC(EditorPrimitiveMirrorCB),
            (gpointer)editor
        );
        GUISetWidgetTip(
            w,
            MsgListMatchCaseMessage(
                msglist, VMA_MSGNAME_EDITOR_PRIMITIVE_MIRROR
            )
        );   
        gtk_widget_show(w);

        /* Separator. */
        w = gtk_label_new("");
        gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
        gtk_widget_set_usize(w, sw, sh);
        gtk_widget_show(w);

        /* Add vertex. */
        editor->primitive_add_vertex_btn = w = (GtkWidget *)GUIButtonPixmap(
            (u_int8_t **)icon_vertex_add_20x20_xpm
        );
        gtk_button_set_relief(GTK_BUTTON(w), GTK_RELIEF_NONE);
        gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
        gtk_widget_set_usize(w, bw, bh);
        gtk_signal_connect(
            GTK_OBJECT(w), "clicked",
            GTK_SIGNAL_FUNC(EditorPrimitiveVertexAddCB),
            (gpointer)editor
        );
        GUISetWidgetTip(
            w,
            MsgListMatchCaseMessage(
                msglist, VMA_MSGNAME_EDITOR_PRIMITIVE_ADD_VERTEX
            )
        );
        gtk_widget_show(w);

        /* Remove vertex. */
        editor->primitive_remove_vertex_btn = w = (GtkWidget *)GUIButtonPixmap(
            (u_int8_t **)icon_vertex_remove_20x20_xpm
        );
        gtk_button_set_relief(GTK_BUTTON(w), GTK_RELIEF_NONE);
        gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
        gtk_widget_set_usize(w, bw, bh);
        gtk_signal_connect(
            GTK_OBJECT(w), "clicked",
            GTK_SIGNAL_FUNC(EditorPrimitiveVertexRemoveCB),
            (gpointer)editor
        );
        GUISetWidgetTip(
            w,
            MsgListMatchCaseMessage(
                msglist, VMA_MSGNAME_EDITOR_PRIMITIVE_REMOVE_VERTEX
            )
        );   
        gtk_widget_show(w);


        /* Separator. */   
        w = gtk_label_new("");
        gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
        gtk_widget_set_usize(w, sw, sh);
        gtk_widget_show(w);


        /* Light button. */
        editor->primitive_light_btn = w = (GtkWidget *)GUIButtonPixmap(
            (u_int8_t **)icon_lighting_20x20_xpm
        );
        gtk_button_set_relief(GTK_BUTTON(w), GTK_RELIEF_NONE);
        gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
        gtk_widget_set_usize(w, bw, bh);
        gtk_signal_connect_after(
            GTK_OBJECT(w), "pressed",
            GTK_SIGNAL_FUNC(EditorButtonMenuMapCB),
            (gpointer)editor 
        );
        GUISetWidgetTip(
            w,
            MsgListMatchCaseMessage(
                msglist, VMA_MSGNAME_EDITOR_LIGHT_POPUP_MENU
            )
        );
        gtk_widget_show(w);  

        /* Light button menu. */
        menu = (GtkWidget *)GUIMenuCreate();
        editor->primitive_light_btn_menu = menu;
        accel_group = NULL;
        mclient_data = (void *)editor;
        if(menu != NULL)
        {
            icon = NULL;
            label = "Enabled";
            accel_key = 0;
            accel_mods = 0;
            func_cb = EditorLightToggleCB;
            DO_ADD_MENU_ITEM_CHECK
            editor->primitive_light_btn_enabled_micheck = w;

            icon = (u_int8_t **)icon_goto_20x20_xpm;
            label = "Move To Cursor";
            accel_key = 0;
            accel_mods = 0;
            func_cb = EditorLightMoveToCursorCB;
            DO_ADD_MENU_ITEM_LABEL
          editor->primitive_light_btn_move_to_cursor_mi = w;

          DO_ADD_MENU_SEP

            icon = (u_int8_t **)icon_properties_20x20_xpm;
            label = "Properties...";
            accel_key = 0;
            accel_mods = 0;
            func_cb = EditorLightPropertiesCB;
            DO_ADD_MENU_ITEM_LABEL
          editor->primitive_light_btn_properties_mi = w;
        }
        /* Need to attach basic "hide" signal to menu so we know when
         * it is unmapped.
         */
        gtk_signal_connect(
            GTK_OBJECT(menu), "hide",
            GTK_SIGNAL_FUNC(EditorMenuHideCB),
            (gpointer)editor
        );

      /* Light number spin. */
      adj = (GtkAdjustment *)gtk_adjustment_new(
          0.0,          /* Initial. */
          0.0,          /* Minimum. */
          VMA_LIGHTS_MAX - 1, /* Maximum. */
          1.0,          /* Step inc. */
          1.0,          /* Page inc. */
          1.0                 /* Page size. */
      );
        editor->primitive_light_num_spin = w = gtk_spin_button_new(
            adj,
            1.0,  /* Climb rate (0.0 to 1.0). */
            0           /* Digits. */
        );
        if(w != NULL)
        {
            gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
            gtk_widget_set_usize(w, 50, -1);
          GUISetWidgetTip(
            w,
            MsgListMatchCaseMessage(
                msglist, VMA_MSGNAME_EDITOR_LIGHT_NUMBER_SPIN
            )
          );
            gtk_widget_show(w);
        }   


        /* Separator. */   
        w = gtk_label_new("");
        gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
        gtk_widget_set_usize(w, sw, sh);
        gtk_widget_show(w);


        /* Scratch pad button. */
        editor->primitive_scratchpad_btn = w = (GtkWidget *)GUIButtonPixmap(
            (u_int8_t **)icon_scratchpad_20x20_xpm
        );
        gtk_button_set_relief(GTK_BUTTON(w), GTK_RELIEF_NONE);
        gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
        gtk_widget_set_usize(w, bw, bh);
        gtk_signal_connect_after( 
            GTK_OBJECT(w), "pressed",
            GTK_SIGNAL_FUNC(EditorButtonMenuMapCB),
            (gpointer)editor
        );
        GUISetWidgetTip(
            w,
            MsgListMatchCaseMessage(
                msglist, VMA_MSGNAME_EDITOR_SCRATCH_PAD
            )
        );
        gtk_widget_show(w);

        /* Scratch pad button menu. */
        menu = (GtkWidget *)GUIMenuCreate();
        editor->primitive_scratchpad_btn_menu = menu;
        accel_group = NULL;
        mclient_data = (void *)editor;
        if(menu != NULL)   
        {   
            icon = NULL;
            label = "Insert"; 
            accel_key = 0;
            accel_mods = 0;
            func_cb = EditorScratchPadVertexInsertCB;
            DO_ADD_MENU_ITEM_LABEL
            editor->primitive_scratchpad_btn_insert_mi = w;

            icon = NULL;
            label = "Append";
            accel_key = 0;
            accel_mods = 0;
            func_cb = EditorScratchPadVertexAppendCB;
            DO_ADD_MENU_ITEM_LABEL
            editor->primitive_scratchpad_btn_append_mi = w;

            DO_ADD_MENU_SEP

            icon = NULL;
            label = "Edit...";
            accel_key = 0;
            accel_mods = 0;
            func_cb = EditorScratchPadVertexEditCB;
            DO_ADD_MENU_ITEM_LABEL
            editor->primitive_scratchpad_btn_edit_mi = w;
        }
        /* Need to attach basic "hide" signal to menu so we know when
         * it is unmapped.
         */
        gtk_signal_connect(
            GTK_OBJECT(menu), "hide",
            GTK_SIGNAL_FUNC(EditorMenuHideCB),
            (gpointer)editor
        );

#undef DO_ADD_MENU_ITEM_LABEL
#undef DO_ADD_MENU_ITEM_CHECK
#undef DO_ADD_MENU_SEP

      return(0);
}



/*
 *    Builds the models and primitives list on the editor and parents
 *    it to the given parent widget.
 *
 *      Inputs assumed valid, returns non-zero on error.
 */
static gint EditorBuildModelList(ma_editor_struct *editor, GtkWidget *parent)
{
      GtkWidget *w, *fw, *parent2, *scroll_parent, *menu, *submenu;
      gint  panel0_size,
            panel_models_list_size;
      const gchar *label;
        gint accel_key;
      gpointer accel_group;
      guint accel_mods;
        u_int8_t **icon;
        gpointer mclient_data;
        void (*func_cb)(GtkWidget *, gpointer) = NULL;
        gint (*enter_cb)(gpointer, gpointer, gpointer) = (gpointer)EditorMenuItemEnterCB;
      gchar *heading[4];
      GtkTargetEntry dnd_type[3];


#define DO_ADD_MENU_ITEM_LABEL  \
{ \
 w = GUIMenuItemCreate( \
  menu, GUI_MENU_ITEM_TYPE_LABEL, accel_group, \
  icon, label, accel_key, accel_mods, (void **)&fw, \
  mclient_data, func_cb \
 ); \
 GUISetMenuItemCrossingCB( \
  w, enter_cb, mclient_data, NULL, mclient_data \
 ); \
}
#define DO_ADD_MENU_ITEM_SUBMENU        \
{ \
 w = GUIMenuItemCreate( \
  menu, GUI_MENU_ITEM_TYPE_SUBMENU, accel_group, \
  icon, label, accel_key, accel_mods, (void **)&fw, \
  mclient_data, func_cb \
 ); \
 if(w != NULL) \
  GUIMenuItemSetSubMenu(w, submenu); \
}
#define DO_ADD_MENU_ITEM_CHECK  \
{ \
 w = GUIMenuItemCreate( \
  menu, GUI_MENU_ITEM_TYPE_CHECK, accel_group, \
  icon, label, accel_key, accel_mods, (void **)&fw, \
  mclient_data, func_cb \
 ); \
 GUISetMenuItemCrossingCB( \
  w, enter_cb, mclient_data, NULL, mclient_data \
 ); \
}
#define DO_ADD_MENU_SEP \
{ \
 w = GUIMenuItemCreate( \
  menu, GUI_MENU_ITEM_TYPE_SEPARATOR, NULL, \
  NULL, NULL, 0, 0, NULL, \
  NULL, NULL \
 ); \
}  


        /* Get panel sizes from configuration options list. */
      panel0_size = VMACFGItemListGetValueI(
            option, VMA_CFG_PARM_PANEL0_SIZE
        );
      if(panel0_size < 1)
          panel0_size = 100;

      panel_models_list_size = VMACFGItemListGetValueI(
            option, VMA_CFG_PARM_PANEL_MODELS_LIST_SIZE
        );
      if(panel_models_list_size < 1)
          panel_models_list_size = 100;


      /* Split the models and primitives lists with a paned widget. */
        w = gtk_vpaned_new();
        gtk_paned_set_handle_size(GTK_PANED(w), VMA_DEF_PANED_HANDLE_SIZE);
        gtk_paned_set_gutter_size(GTK_PANED(w), VMA_DEF_PANED_GUTTER_SIZE);
        gtk_container_add(GTK_CONTAINER(parent), w);
        gtk_widget_show(w);
        parent2 = w;


      /* Models list. */
      w = gtk_scrolled_window_new(NULL, NULL);
      gtk_scrolled_window_set_policy(
          GTK_SCROLLED_WINDOW(w),
          GTK_POLICY_AUTOMATIC,
          GTK_POLICY_AUTOMATIC
      );
      gtk_paned_add1(GTK_PANED(parent2), w);
      gtk_widget_show(w);
      scroll_parent = w;

      heading[0] = strdup("Models");
      w = gtk_clist_new_with_titles(1, heading);
      free(heading[0]);
      editor->models_list = w;
      if(!GTK_WIDGET_NO_WINDOW(w))
      {
          /* Tie to button press callback (for mapping menu). */
            gtk_widget_add_events(
                w,
                GDK_BUTTON_PRESS_MASK
            );
            gtk_signal_connect(
                GTK_OBJECT(w),
                "button_press_event",
                GTK_SIGNAL_FUNC(EditorListMenuMapCB),
                editor
            );
      }
        gtk_widget_set_usize(w, -1, panel_models_list_size);
        gtk_clist_column_titles_passive(GTK_CLIST(w));
      gtk_clist_set_selection_mode(GTK_CLIST(w), GTK_SELECTION_SINGLE);
      gtk_clist_set_row_height(GTK_CLIST(w), VMA_LIST_ROW_SPACING);
      gtk_container_add(GTK_CONTAINER(scroll_parent), w);
        gtk_clist_set_column_justification(
            GTK_CLIST(w), 0, GTK_JUSTIFY_LEFT
        );
      gtk_clist_set_shadow_type(GTK_CLIST(w), GTK_SHADOW_IN);
      gtk_signal_connect(
          GTK_OBJECT(w),
          "select_row",
          GTK_SIGNAL_FUNC(EditorModelsListSelectCB),
            (gpointer)editor
      );
        gtk_signal_connect(
            GTK_OBJECT(w),
            "unselect_row",
            GTK_SIGNAL_FUNC(EditorModelsListUnselectCB),
            (gpointer)editor
        );
        gtk_signal_connect(
            GTK_OBJECT(w),
            "click_column",
            GTK_SIGNAL_FUNC(EditorListColumClickCB),
            (gpointer)editor
        );
        GTK_CLIST(w)->flags |= GTK_CLIST_DRAW_DRAG_LINE;
      GTK_CLIST(w)->flags |= GTK_CLIST_DRAW_DRAG_RECT;
/*    gtk_clist_set_reorderable(GTK_CLIST(w), TRUE); */
        /* Set up DND for the models clist, it can recieve
       * editor models and primitives transfer command strings.
       */
        dnd_type[0].target = EDITOR_DND_TYPE_MODELS_CMD;
        dnd_type[0].flags = GTK_TARGET_SAME_APP;
        dnd_type[0].info = 12345;         /* Ignored. */
        GUIDNDSetSrc(
            w,
            &dnd_type, 1,                       /* DND target types. */
            GDK_ACTION_COPY | GDK_ACTION_MOVE,  /* Actions. */
            GDK_BUTTON1_MASK | GDK_BUTTON2_MASK,/* Buttons. */
            NULL,
            EditorDNDModelsListDataRequestCB,
            EditorDNDModelsListDataDeleteCB, 
            NULL,
            editor
        );
        dnd_type[0].target = EDITOR_DND_TYPE_MODELS_CMD;
        dnd_type[0].flags = GTK_TARGET_SAME_APP;
        dnd_type[0].info = 12345;         /* Ignored. */
        dnd_type[1].target = EDITOR_DND_TYPE_PRIMITIVES_CMD;
        dnd_type[1].flags = GTK_TARGET_SAME_APP;
        dnd_type[1].info = 12345;         /* Ignored. */
        dnd_type[2].target = EDITOR_DND_TYPE_MODEL_CREATE_CMD;
        dnd_type[2].flags = GTK_TARGET_SAME_APP;
        dnd_type[2].info = 12345;         /* Ignored. */
        GUIDNDSetTar(
            w,
            &dnd_type, 3,                 /* DND target types. */
            GDK_ACTION_COPY | GDK_ACTION_MOVE,  /* Actions. */
            GDK_ACTION_MOVE,                    /* Default action if same. */
            GDK_ACTION_COPY,                    /* Default action. */
            EditorDNDModelsListDataRecievedCB,
            editor
        );
      gtk_widget_show(w);


      /* Models list right click menu. */
        menu = (GtkWidget *)GUIMenuCreate();
        editor->models_list_menu = menu;
        accel_group = NULL;
        mclient_data = editor;

      if(menu != NULL)
      {
            icon = (u_int8_t **)icon_model_create_20x20_xpm;
            label = "Create...";
            accel_key = 0; 
            accel_mods = 0;
            func_cb = EditorModelCreateCB;
            DO_ADD_MENU_ITEM_LABEL

            icon = (u_int8_t **)icon_model_delete_20x20_xpm;
            label = "Delete";
            accel_key = 0;
            accel_mods = 0;
            func_cb = EditorModelDeleteCB;
            DO_ADD_MENU_ITEM_LABEL
            editor->models_list_delete_mi = w;

            DO_ADD_MENU_SEP

            icon = NULL;
            label = "Show";
            accel_key = 0;
            accel_mods = 0;
            func_cb = EditorToggleModelShowCB;
            DO_ADD_MENU_ITEM_CHECK
            editor->models_list_show_micheck = w;

            DO_ADD_MENU_SEP

            icon = (u_int8_t **)icon_properties_20x20_xpm;
            label = "Properties...";
            accel_key = 0;
            accel_mods = 0;
            func_cb = EditorModelPropertiesCB;
            DO_ADD_MENU_ITEM_LABEL
            editor->models_list_properties_mi = w;
      }


        /* Primitives list. */
        w = gtk_scrolled_window_new(NULL, NULL);
        gtk_scrolled_window_set_policy(
            GTK_SCROLLED_WINDOW(w),
            GTK_POLICY_AUTOMATIC,
            GTK_POLICY_AUTOMATIC
        );
        gtk_paned_add2(GTK_PANED(parent2), w);
        gtk_widget_show(w);   
        scroll_parent = w;

        heading[0] = strdup("Primitives");
        w = gtk_clist_new_with_titles(1, heading);
      free(heading[0]);
      editor->primitives_list = w;
        if(!GTK_WIDGET_NO_WINDOW(w))
        {
            /* Tie to button press callback (for mapping menu). */
            gtk_widget_add_events(
                w,
                GDK_BUTTON_PRESS_MASK
            );
            gtk_signal_connect(
                GTK_OBJECT(w),   
                "button_press_event",
                GTK_SIGNAL_FUNC(EditorListMenuMapCB),
                editor
            );
        }
/*
        gtk_widget_set_usize(
             w,
             VMA_EDITOR_DEF_WIDTH * 0.25,
             VMA_EDITOR_DEF_HEIGHT * 0.75
        );
 */
        gtk_clist_column_titles_passive(GTK_CLIST(w));
      gtk_clist_set_selection_mode(GTK_CLIST(w), GTK_SELECTION_EXTENDED);
        gtk_clist_set_row_height(GTK_CLIST(w), VMA_LIST_ROW_SPACING);
        gtk_container_add(GTK_CONTAINER(scroll_parent), w);
        gtk_clist_set_column_justification(
            GTK_CLIST(w), 0, GTK_JUSTIFY_LEFT
        );
        gtk_clist_set_shadow_type(GTK_CLIST(w), GTK_SHADOW_IN);
        gtk_signal_connect(
            GTK_OBJECT(w),
            "select_row",
            GTK_SIGNAL_FUNC(EditorPrimitivesListSelectCB),
            editor  
        );
        gtk_signal_connect(
            GTK_OBJECT(w),
            "unselect_row",
            GTK_SIGNAL_FUNC(EditorPrimitivesListUnselectCB),
            editor
        );
        gtk_signal_connect(
            GTK_OBJECT(w),
            "click_column",
            GTK_SIGNAL_FUNC(EditorListColumClickCB),
            editor
        );
        GTK_CLIST(w)->flags |= GTK_CLIST_DRAW_DRAG_LINE;
        GTK_CLIST(w)->flags |= GTK_CLIST_DRAW_DRAG_RECT;
/*    gtk_clist_set_reorderable(GTK_CLIST(w), TRUE); */
      /* Set up DND for the primitives clist. */
      dnd_type[0].target = EDITOR_DND_TYPE_PRIMITIVES_CMD;
      dnd_type[0].flags = GTK_TARGET_SAME_APP;
      dnd_type[0].info = 12345;           /* Ignored. */
      GUIDNDSetSrc(
          w,
          &dnd_type, 1,             /* DND target types. */
          GDK_ACTION_COPY | GDK_ACTION_MOVE,    /* Actions. */
          GDK_BUTTON1_MASK | GDK_BUTTON2_MASK,/* Buttons. */
          NULL,
          EditorDNDPrimitivesListDataRequestCB,
          EditorDNDPrimitivesListDataDeleteCB,
          NULL,
          editor
      );
        dnd_type[0].target = EDITOR_DND_TYPE_PRIMITIVES_CMD;
        dnd_type[0].flags = GTK_TARGET_SAME_APP;
        dnd_type[0].info = 12345;               /* Ignored. */
        dnd_type[1].target = EDITOR_DND_TYPE_PRIMITIVE_CREATE_CMD;
        dnd_type[1].flags = GTK_TARGET_SAME_APP;
        dnd_type[1].info = 12345;               /* Ignored. */
      GUIDNDSetTar(
          w,
          &dnd_type, 2,             /* DND target types. */
          GDK_ACTION_COPY | GDK_ACTION_MOVE,    /* Actions. */
          GDK_ACTION_MOVE,                /* Default action if same. */
          GDK_ACTION_COPY,                /* Default action. */
          EditorDNDPrimitivesListDataRecievedCB,
          editor
      );
        gtk_widget_show(w);


        /* Primitives list right click menu. */
        menu = (GtkWidget *)GUIMenuCreate();
        editor->primitives_list_menu = menu;
        accel_group = NULL;
        mclient_data = editor;

      /* Primitives create submenu. */
      submenu = EditorPrimitivesCreateCreateMenu(editor);
      editor->primitives_list_create_submenu = submenu;

        if(menu != NULL)    
        {
            icon = (u_int8_t **)icon_add_20x20_xpm;
            label = "Create";
            accel_key = 0;
            accel_mods = 0;
            func_cb = NULL;
            DO_ADD_MENU_ITEM_SUBMENU

            icon = (u_int8_t **)icon_remove_20x20_xpm;
            label = "Delete";
            accel_key = 0;
            accel_mods = 0;
            func_cb = EditorPrimitiveDeleteCB;
            DO_ADD_MENU_ITEM_LABEL
            editor->primitives_list_delete_mi = w;

            DO_ADD_MENU_SEP

            icon = (u_int8_t **)icon_cut_20x20_xpm;
            label = "Cut";
            accel_key = 0;
            accel_mods = 0;
            func_cb = EditorCutCB;
            DO_ADD_MENU_ITEM_LABEL
            editor->primitives_list_cut_mi = w;
            
            icon = (u_int8_t **)icon_copy_20x20_xpm;
            label = "Copy";
            accel_key = 0;
            accel_mods = 0;
            func_cb = EditorCopyCB;
            DO_ADD_MENU_ITEM_LABEL
            editor->primitives_list_copy_mi = w;
  
            icon = (u_int8_t **)icon_paste_20x20_xpm;
            label = "Paste";
            accel_key = 0;
            accel_mods = 0;
            func_cb = EditorPasteCB;
            DO_ADD_MENU_ITEM_LABEL
            editor->primitives_list_paste_mi = w;

          DO_ADD_MENU_SEP

            icon = (u_int8_t **)icon_winding_20x20_xpm;
            label = "Flip Winding";
            accel_key = 0;
            accel_mods = 0;
            func_cb = EditorPrimitiveFlipWindingCB;
            DO_ADD_MENU_ITEM_LABEL
            editor->primitives_list_flip_winding_mi = w;

            icon = (u_int8_t **)icon_translate_20x20_xpm;
            label = "Translate Selected...";
            accel_key = 0;
            accel_mods = 0;
            func_cb = EditorPrimitiveTranslateCB;
            DO_ADD_MENU_ITEM_LABEL
            editor->primitives_list_translate_mi = w;

            icon = (u_int8_t **)icon_rotate_20x20_xpm;
            label = "Rotate Selected...";
            accel_key = 0;
            accel_mods = 0;
            func_cb = EditorPrimitiveRotateCB;
            DO_ADD_MENU_ITEM_LABEL
            editor->primitives_list_rotate_mi = w;

            icon = (u_int8_t **)icon_scale_20x20_xpm;
            label = "Scale Selected...";
            accel_key = 0;
            accel_mods = 0;
            func_cb = EditorPrimitiveScaleCB;
            DO_ADD_MENU_ITEM_LABEL
            editor->primitives_list_scale_mi = w;

            icon = (u_int8_t **)icon_mirror_20x20_xpm;
            label = "Mirror Selected...";
            accel_key = 0;
            accel_mods = 0;
            func_cb = EditorPrimitiveMirrorCB;
            DO_ADD_MENU_ITEM_LABEL
            editor->primitives_list_mirror_mi = w;

            icon = (u_int8_t **)icon_snap_20x20_xpm;
            label = "Snap Selected...";
            accel_key = 0;
            accel_mods = 0;
            func_cb = EditorPrimitiveSnapCB;
            DO_ADD_MENU_ITEM_LABEL
            editor->primitives_list_snap_mi = w;

            DO_ADD_MENU_SEP

            icon = (u_int8_t **)icon_vertex_add_20x20_xpm;
            label = "Add Vertex";
            accel_key = 0;
            accel_mods = 0;
            func_cb = EditorPrimitiveVertexAddCB;
            DO_ADD_MENU_ITEM_LABEL
          editor->primitives_list_add_vertex_mi = w;

            icon = (u_int8_t **)icon_vertex_remove_20x20_xpm;
            label = "Remove Vertex";
            accel_key = 0;  
            accel_mods = 0;
            func_cb = EditorPrimitiveVertexRemoveCB;
            DO_ADD_MENU_ITEM_LABEL
          editor->primitives_list_remove_vertex_mi = w;
        }






#undef DO_ADD_MENU_ITEM_LABEL
#undef DO_ADD_MENU_ITEM_SUBMENU
#undef DO_ADD_MENU_ITEM_CHECK
#undef DO_ADD_MENU_SEP

        return(0);
}  

/*
 *      Builds the values list on the editor and parents it
 *      to the given parent widget.
 *
 *      Inputs assumed valid, returns non-zero on error.
 */
static gint EditorBuildValuesList(ma_editor_struct *editor, GtkWidget *parent)
{
      const gchar *msglist[] = VMA_MSGLIST_EDITOR_TOOLTIPS;
        GtkWidget *w, *fw, *menu, *parent2, *parent3, *scroll_parent;
        const gchar *label;
        gint accel_key;
        gpointer accel_group;
        guint accel_mods;
        u_int8_t **icon;
        gpointer mclient_data;
        void (*func_cb)(GtkWidget *, gpointer);
        gint (*enter_cb)(gpointer, gpointer, gpointer) = (gpointer)EditorMenuItemEnterCB;
        gchar *heading[4];
        GtkTargetEntry dnd_type[1];
      gint i, x, y;
      gint colums, rows;
      gint  panel2_size,
            panel_values_list_size,
            values_list_chwidth0, values_list_chwidth1,
            values_list_chwidth2;
      gint bw = 25, bh = 25;
      gint bw2 = (100 + (2 * 3)), bh2 = (30 + (2 * 3));
      gchar text[80];


#define DO_ADD_MENU_ITEM_LABEL            \
{ \
 w = GUIMenuItemCreate( \
  menu, GUI_MENU_ITEM_TYPE_LABEL, accel_group, \
  icon, label, accel_key, accel_mods, (void **)&fw, \
  mclient_data, func_cb \
 ); \
 GUISetMenuItemCrossingCB( \
  w, enter_cb, mclient_data, NULL, mclient_data \
 ); \
}
#define DO_ADD_MENU_ITEM_SUBMENU    \
{ \
 w = GUIMenuItemCreate( \
  menu, GUI_MENU_ITEM_TYPE_SUBMENU, accel_group, \
  icon, label, accel_key, accel_mods, (void **)&fw, \
  mclient_data, func_cb \
 ); \
 if(w != NULL) \
  GUIMenuItemSetSubMenu(w, submenu); \
}
#define DO_ADD_MENU_ITEM_CHECK            \
{ \
 w = GUIMenuItemCreate( \
  menu, GUI_MENU_ITEM_TYPE_CHECK, accel_group, \
  icon, label, accel_key, accel_mods, (void **)&fw, \
  mclient_data, func_cb \
 ); \
 GUISetMenuItemCrossingCB( \
  w, enter_cb, mclient_data, NULL, mclient_data \
 ); \
}
#define DO_ADD_MENU_SEP             \
{ \
 w = GUIMenuItemCreate( \
  menu, GUI_MENU_ITEM_TYPE_SEPARATOR, NULL, \
  NULL, NULL, 0, 0, NULL, \
  NULL, NULL \
 ); \
}

        /* Get panel sizes from configuration options list. */
        panel2_size = VMACFGItemListGetValueI(
            option, VMA_CFG_PARM_PANEL2_SIZE
        );
      if(panel2_size < 1)
          panel2_size = 100;

      panel_values_list_size = VMACFGItemListGetValueI(
            option, VMA_CFG_PARM_PANEL_VALUES_LIST_SIZE
        );
        if(panel_values_list_size < 1)
            panel_values_list_size = 100;


      values_list_chwidth0 = VMACFGItemListGetValueI(
            option, VMA_CFG_PARM_EDITOR_VALUES_CHWIDTH0
        );
        if(values_list_chwidth0 < 1)
            values_list_chwidth0 = 100;

        values_list_chwidth1 = VMACFGItemListGetValueI(
            option, VMA_CFG_PARM_EDITOR_VALUES_CHWIDTH1
        );
        if(values_list_chwidth1 < 1)
            values_list_chwidth1 = 100;

        values_list_chwidth2 = VMACFGItemListGetValueI(
            option, VMA_CFG_PARM_EDITOR_VALUES_CHWIDTH2
        );
        if(values_list_chwidth2 < 1)
            values_list_chwidth2 = 100;


        /* Split the models and primitives lists with a paned widget. */
        w = gtk_vpaned_new();
        gtk_paned_set_handle_size(GTK_PANED(w), VMA_DEF_PANED_HANDLE_SIZE);
        gtk_paned_set_gutter_size(GTK_PANED(w), VMA_DEF_PANED_GUTTER_SIZE);
        gtk_container_add(GTK_CONTAINER(parent), w);
        gtk_widget_show(w);
        parent2 = w;

        /* Values list. */
        w = gtk_scrolled_window_new(NULL, NULL);
      /* Record scrolled window as values list toplevel. */
      editor->values_toplevel = w;
        gtk_scrolled_window_set_policy(
            GTK_SCROLLED_WINDOW(w),
            GTK_POLICY_AUTOMATIC,
            GTK_POLICY_AUTOMATIC
        );
        gtk_paned_add1(GTK_PANED(parent2), w);
      /* Restore size. */
        gtk_widget_set_usize(w, -1, panel_values_list_size);
        gtk_widget_show(w);  
        scroll_parent = w;

        heading[0] = strdup("Vertex");
        heading[1] = strdup("Normal");
        heading[2] = strdup("TexCoord");
        heading[3] = NULL;
        editor->values_list = w = gtk_clist_new_with_titles(3, heading);
      free(heading[0]);
      free(heading[1]);
      free(heading[2]);
        if(!GTK_WIDGET_NO_WINDOW(w))
        {
            /* Tie to button press callback (for mapping menu). */
            gtk_widget_add_events(
                w,
                GDK_BUTTON_PRESS_MASK
            );
            gtk_signal_connect(
                GTK_OBJECT(w),   
                "button_press_event",
                GTK_SIGNAL_FUNC(EditorListMenuMapCB),
                editor
            );
        }
        gtk_clist_column_titles_passive(GTK_CLIST(w));
      gtk_clist_set_selection_mode(GTK_CLIST(w), GTK_SELECTION_SINGLE);
        gtk_clist_set_row_height(GTK_CLIST(w), VMA_LIST_ROW_SPACING);
      gtk_container_add(GTK_CONTAINER(scroll_parent), w);
      gtk_clist_set_column_width(
          GTK_CLIST(w), 0, values_list_chwidth0
      );
      gtk_clist_set_column_justification(
          GTK_CLIST(w), 0, GTK_JUSTIFY_LEFT
      );
        gtk_clist_set_column_width(
            GTK_CLIST(w), 1, values_list_chwidth1
        );
        gtk_clist_set_column_justification(
            GTK_CLIST(w), 1, GTK_JUSTIFY_LEFT
        );
        gtk_clist_set_column_width(
            GTK_CLIST(w), 2, values_list_chwidth2
        );
        gtk_clist_set_column_justification(
            GTK_CLIST(w), 2, GTK_JUSTIFY_LEFT
        );
        gtk_clist_set_shadow_type(GTK_CLIST(w), GTK_SHADOW_IN);
        gtk_signal_connect(
            GTK_OBJECT(w), "select_row",
            GTK_SIGNAL_FUNC(EditorValuesListSelectCB),
            (gpointer)editor
        );
        gtk_signal_connect(
            GTK_OBJECT(w), "unselect_row", 
            GTK_SIGNAL_FUNC(EditorValuesListUnselectCB),
            (gpointer)editor
        );
        gtk_signal_connect(
            GTK_OBJECT(w), "click_column",
            GTK_SIGNAL_FUNC(EditorListColumClickCB),
            (gpointer)editor
        );
        /* Set up DND for the values clist, it can send and recieve
         * set vertex command strings.
         */
        dnd_type[0].target = EDITOR_DND_TYPE_VALUES_SET_CMD;
        dnd_type[0].flags = GTK_TARGET_SAME_APP;
        dnd_type[0].info = 12345;               /* Ignored. */
        GUIDNDSetSrc(
            w,
            &dnd_type, 1,                       /* DND target types. */
            GDK_ACTION_COPY | GDK_ACTION_MOVE,  /* Actions. */
            GDK_BUTTON1_MASK | GDK_BUTTON2_MASK,/* Buttons. */
            NULL,
            EditorDNDValuesListDataRequestCB,
            EditorDNDValuesListDataDeleteCB,
            NULL,
            editor
        );
        dnd_type[0].target = EDITOR_DND_TYPE_VALUES_SET_CMD;
        dnd_type[0].flags = GTK_TARGET_SAME_APP;
        dnd_type[0].info = 12345;               /* Ignored. */
        GUIDNDSetTar(
            w,
            &dnd_type, 1,                       /* DND target types. */
            GDK_ACTION_COPY | GDK_ACTION_MOVE,  /* Actions. */
            GDK_ACTION_MOVE,                    /* Default action if same. */
            GDK_ACTION_COPY,                    /* Default action. */
            EditorDNDValuesListDataRecievedCB,
            editor
        );
      gtk_widget_show(w);



        /* Values list right click menu. */
        menu = (GtkWidget *)GUIMenuCreate();
        editor->values_list_menu = menu;
        accel_group = NULL;
        mclient_data = editor;

        if(menu != NULL)
        {
            icon = (u_int8_t **)icon_undo_20x20_xpm;
            label = "Undo";
            accel_key = 0;
            accel_mods = 0;
            func_cb = EditorUndoCB;
            DO_ADD_MENU_ITEM_LABEL
            editor->values_list_undo_mi = w;
            editor->values_list_undo_milabel = fw;

            icon = (u_int8_t **)icon_redo_20x20_xpm;
            label = "Redo";
            accel_key = 0;
            accel_mods = 0;
            func_cb = EditorRedoCB;  
            DO_ADD_MENU_ITEM_LABEL
            editor->values_list_redo_mi = w;
            editor->values_list_redo_milabel = fw;

            DO_ADD_MENU_SEP

            icon = (u_int8_t **)icon_unitlize_normal_20x20_xpm;
            label = "Unitlize Normal";
            accel_key = 0;
            accel_mods = 0;
            func_cb = EditorPrimitiveUnitlizeNormalCB;
            DO_ADD_MENU_ITEM_LABEL
            editor->values_list_unitlize_normal_mi = w;

            icon = (u_int8_t **)icon_snap_20x20_xpm;
            label = "Snap Selected...";
            accel_key = 0;
            accel_mods = 0;
            func_cb = EditorPrimitiveSnapCB;
            DO_ADD_MENU_ITEM_LABEL
            editor->values_list_snap_mi = w;

          DO_ADD_MENU_SEP

            icon = (u_int8_t **)icon_vertex_add_20x20_xpm;
            label = "Add Vertex";
            accel_key = 0;
            accel_mods = 0;
            func_cb = EditorPrimitiveVertexAddCB;
            DO_ADD_MENU_ITEM_LABEL
          editor->values_list_add_vertex = w;

            icon = (u_int8_t **)icon_vertex_remove_20x20_xpm;
            label = "Remove Vertex";
            accel_key = 0;
            accel_mods = 0;
            func_cb = EditorPrimitiveVertexRemoveCB;
            DO_ADD_MENU_ITEM_LABEL
            editor->values_list_remove_vertex = w;

            DO_ADD_MENU_SEP

            icon = NULL;
            label = "Insert To ScratchPad";
            accel_key = 0;
            accel_mods = 0;
            func_cb = EditorScratchPadVertexInsertCB;
            DO_ADD_MENU_ITEM_LABEL
            editor->values_list_scratchpad_insert_mi = w;

            icon = NULL;
            label = "Append To ScratchPad";
            accel_key = 0;
            accel_mods = 0;
            func_cb = EditorScratchPadVertexAppendCB;
            DO_ADD_MENU_ITEM_LABEL
            editor->values_list_scratchpad_append_mi = w;

            icon = NULL;
            label = "Edit ScratchPad...";
            accel_key = 0;
            accel_mods = 0;
            func_cb = EditorScratchPadVertexEditCB;
            DO_ADD_MENU_ITEM_LABEL
            editor->values_list_scratchpad_edit_mi = w;
      }


      /* Vbox to hold values widgets. */
      w = gtk_vbox_new(FALSE, 5);
        gtk_paned_add2(GTK_PANED(parent2), w);
        gtk_container_border_width(GTK_CONTAINER(w), 5);
        gtk_widget_show(w);
      parent2 = w;

        /* Create values table to hold values prompts and related
       * widgets.
       */
      colums = 1 * 3;
      rows = 1 + (gint)(VMA_PRIMITIVES_MAX_VALUES / 1);
      w = gtk_table_new(rows, colums, FALSE);
      gtk_box_pack_start(GTK_BOX(parent2), w, TRUE, TRUE, 0);
      gtk_widget_show(w);
      parent3 = w;

      /* Create each values prompt and related widgets. */
      for(i = 0, x = 0, y = 0;
            i < VMA_PRIMITIVES_MAX_VALUES;
            i++
      )
      {
          /* Current row done? */
          if(x >= colums)
          {
            /* Go to next row. */
            x = 0;
            y++;
          }

          /* Label. */
          sprintf(text, "v%i:", i);
          w = gtk_label_new(text);
          editor->values_label[i] = w;
          gtk_table_attach(
            GTK_TABLE(parent3), w,
                x, x + 1,
                y, y + 1,
                0,
                0,
                2, 2
            );
            gtk_label_set_justify(GTK_LABEL(w), GTK_JUSTIFY_RIGHT);
          /* Do not show it just yet. */

          /* Text entry. */
          x++;
          w = gtk_entry_new_with_max_length(VMA_VALUE_TEXT_MAX);
          editor->values_text[i] = w;
            gtk_signal_connect(
                GTK_OBJECT(w), 
                "activate",
                GTK_SIGNAL_FUNC(EditorValueEnterCB),
                editor
            );
            gtk_table_attach(
            GTK_TABLE(parent3), w,
                x, x + 1,
            y, y + 1,
                GTK_FILL | GTK_SHRINK,
                GTK_SHRINK,
                2, 2
            );
          /* Do not show it just yet. */

          /* Browse button. */
          x++;
            w = GUIButtonPixmap((u_int8_t **)icon_browse_20x20_xpm);
            editor->values_browse_btn[i] = w;
            gtk_signal_connect(
                GTK_OBJECT(w), "clicked",
                GTK_SIGNAL_FUNC(EditorValueBrowseCB),
            (gpointer)editor
            );
            gtk_table_attach(
            GTK_TABLE(parent3), w,
                x, x + 1,
                y, y + 1,
                0,   
                0,   
                2, 2 
            );
          gtk_widget_set_usize(w, bw, bh);
          GUISetWidgetTip(
            w,
            MsgListMatchCaseMessage(
                msglist, VMA_MSGNAME_EDITOR_VALUES_BROWSE_BUTTON
            )
          );
            /* Do not show it just yet. */
          x++;
      }

      /* Create an hbox to hold values buttons. */
      w = gtk_hbox_new(TRUE, 5);
      gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
      gtk_widget_show(w);
      parent3 = w;

      /* Create apply button. */
        editor->values_apply_btn = w = (GtkWidget *)GUIButtonPixmapLabelH(
            (u_int8_t **)icon_select_20x20_xpm, "Apply", NULL
        );
      gtk_box_pack_start(GTK_BOX(parent3), w, TRUE, FALSE, 0);
      gtk_widget_set_usize(w, bw2, bh2);
        GTK_WIDGET_SET_FLAGS(w, GTK_CAN_DEFAULT);
      gtk_signal_connect(
            GTK_OBJECT(w), "clicked",
            GTK_SIGNAL_FUNC(EditorValueApplyCB),
            (gpointer)editor
        );
      gtk_widget_show(w);



#undef DO_ADD_MENU_ITEM_LABEL
#undef DO_ADD_MENU_ITEM_SUBMENU
#undef DO_ADD_MENU_ITEM_CHECK
#undef DO_ADD_MENU_SEP

        return(0);
}  

/*
 *      Builds the view widgets on the editor and parents it
 *      to the given parent widget, the parent widget should be
 *    a vbox and two paneled widgets will be put into it.
 *    The parents (both restored and maximized) for the views
 *    will be recorded on the editor structure.
 *
 *      Inputs assumed valid, returns non-zero on error.
 */
static gint EditorBuildViews(
      gpointer core_ptr, ma_editor_struct *editor, GtkWidget *parent
)
{
      gint i, total;
      gchar *parm;
        GtkWidget *w, *parent2, *parent3;
      vma_color_struct **color;
      vma_view_palette_struct vpalette;
      vma_view2d_struct *view2d;
      vma_view3d_struct *view3d;
      gint  panel_view_upper_size,
            panel_view0_size,
            panel_view2_size;


      /* Get panel sizes from configuration options list. */
      panel_view_upper_size = VMACFGItemListGetValueI(
          option, VMA_CFG_PARM_PANEL_VIEW_UPPER_SIZE
      );
      if(panel_view_upper_size < 1)
          panel_view_upper_size = 100;

      panel_view0_size = VMACFGItemListGetValueI(
          option, VMA_CFG_PARM_PANEL_VIEW0_SIZE
      );
      if(panel_view0_size < 1)
          panel_view0_size = 100;

      panel_view2_size = VMACFGItemListGetValueI(
            option, VMA_CFG_PARM_PANEL_VIEW2_SIZE
        );
      if(panel_view2_size < 1)
          panel_view2_size = 100;


      /* Set up view colors. */
#define DO_SET_COLOR    \
{ \
 (*color) = (vma_color_struct *)VMACFGItemListMatchGetValue( \
  option, parm, NULL \
 ); \
}
      color = &vpalette.background;
      parm = VMA_CFG_PARM_VIEW_COLOR_BACKGROUND;
      DO_SET_COLOR
        color = &vpalette.point;
        parm = VMA_CFG_PARM_VIEW_COLOR_POINT;
        DO_SET_COLOR
        color = &vpalette.line;
        parm = VMA_CFG_PARM_VIEW_COLOR_LINE;
        DO_SET_COLOR 
        color = &vpalette.line_strip;
        parm = VMA_CFG_PARM_VIEW_COLOR_LINE_STRIP;
        DO_SET_COLOR
        color = &vpalette.line_loop;
        parm = VMA_CFG_PARM_VIEW_COLOR_LINE_LOOP;
        DO_SET_COLOR
        color = &vpalette.triangle;
        parm = VMA_CFG_PARM_VIEW_COLOR_TRIANGLE;
        DO_SET_COLOR
        color = &vpalette.triangle_strip;
        parm = VMA_CFG_PARM_VIEW_COLOR_TRIANGLE_STRIP;
        DO_SET_COLOR
        color = &vpalette.triangle_fan;
        parm = VMA_CFG_PARM_VIEW_COLOR_TRIANGLE_FAN;
        DO_SET_COLOR
        color = &vpalette.quad;
        parm = VMA_CFG_PARM_VIEW_COLOR_QUAD;
        DO_SET_COLOR
        color = &vpalette.quad_strip;
        parm = VMA_CFG_PARM_VIEW_COLOR_QUAD_STRIP;
        DO_SET_COLOR
        color = &vpalette.polygon;
        parm = VMA_CFG_PARM_VIEW_COLOR_POLYGON;
        DO_SET_COLOR
        color = &vpalette.texture_outline;
        parm = VMA_CFG_PARM_VIEW_COLOR_TEXTURE_OUTLINE;
        DO_SET_COLOR
        color = &vpalette.texture_outline_selected;
        parm = VMA_CFG_PARM_VIEW_COLOR_TEXTURE_OUTLINE_SELECTED;
        DO_SET_COLOR
      color = &vpalette.heightfield;
      parm = VMA_CFG_PARM_VIEW_COLOR_HEIGHTFIELD;
        DO_SET_COLOR
        color = &vpalette.grid;
        parm = VMA_CFG_PARM_VIEW_COLOR_GRID;
        DO_SET_COLOR
        color = &vpalette.selected;
        parm = VMA_CFG_PARM_VIEW_COLOR_SELECTED;
        DO_SET_COLOR
        color = &vpalette.selected_vertex;
        parm = VMA_CFG_PARM_VIEW_COLOR_SELECTED_VERTEX;
        DO_SET_COLOR
        color = &vpalette.cursory;
        parm = VMA_CFG_PARM_VIEW_COLOR_CURSORY;
        DO_SET_COLOR
      color = &vpalette.normal_vector;
      parm = VMA_CFG_PARM_VIEW_COLOR_NORMAL_VECTOR;
        DO_SET_COLOR

#undef DO_SET_COLOR

      /* Record main vbox parent for all views and view maximized
       * state.
       */
      editor->view_maximized_toplevel = parent;


      /* Create two paneled widgets to hold four smaller vboxes which
       * will hold each viewer widget in their restored state and
       * record it on the editor structure.
       */
      total = VMA_MAX_2D_VIEWS_PER_EDITOR + VMA_MAX_3D_VIEWS_PER_EDITOR;

      /* Main panel. */
        w = gtk_vpaned_new();
      editor->view_restored_panel = w;
        gtk_paned_set_handle_size(GTK_PANED(w), VMA_DEF_PANED_HANDLE_SIZE);
        gtk_paned_set_gutter_size(GTK_PANED(w), VMA_DEF_PANED_GUTTER_SIZE);
        gtk_container_add(GTK_CONTAINER(parent), w);
        gtk_widget_show(w);
        parent2 = w;

      /* Upper panel for view 0 and 1. */
        w = gtk_hpaned_new();
        gtk_paned_set_handle_size(GTK_PANED(w), VMA_DEF_PANED_HANDLE_SIZE);
        gtk_paned_set_gutter_size(GTK_PANED(w), VMA_DEF_PANED_GUTTER_SIZE);
      gtk_paned_add1(GTK_PANED(parent2), w);
        gtk_widget_show(w);
      parent3 = w;

      i = 0;
      w = gtk_vbox_new(FALSE, 0);
      if(i < total)
          editor->view_restored_toplevel[i] = w;
      gtk_paned_add1(GTK_PANED(parent3), w);
      gtk_widget_set_usize(w, panel_view0_size, panel_view_upper_size);
      gtk_widget_show(w);

        i = 1;
        w = gtk_vbox_new(FALSE, 0);
        if(i < total)
            editor->view_restored_toplevel[i] = w;
        gtk_paned_add2(GTK_PANED(parent3), w);
        gtk_widget_show(w);

        /* Lower panel for view 2 and 3. */
        w = gtk_hpaned_new();
        gtk_paned_set_handle_size(GTK_PANED(w), VMA_DEF_PANED_HANDLE_SIZE);
        gtk_paned_set_gutter_size(GTK_PANED(w), VMA_DEF_PANED_GUTTER_SIZE);
        gtk_paned_add2(GTK_PANED(parent2), w);
        gtk_widget_show(w);
        parent3 = w;

        i = 2;
        w = gtk_vbox_new(FALSE, 0);
        if(i < total)
            editor->view_restored_toplevel[i] = w;
        gtk_paned_add1(GTK_PANED(parent3), w);
        gtk_widget_set_usize(w, panel_view2_size, -1);
        gtk_widget_show(w);

        i = 3;
        w = gtk_vbox_new(FALSE, 0);
        if(i < total)
            editor->view_restored_toplevel[i] = w;  
        gtk_paned_add2(GTK_PANED(parent3), w); 
        gtk_widget_show(w);


      /* 2d view XZ. */
      i = 0;
      if(i < total)
      {
          view2d = View2DCreate(
              core_ptr, editor,
            VMA_VIEW2D_TYPE_XZ,
            editor->view_restored_toplevel[i],
                editor->view_maximized_toplevel,
              editor, EditorView2DEventCB
          );
            if(view2d != NULL)
            {
                View2DSetPalette(view2d, &vpalette);
            }
          editor->view2d[i] = view2d;
      }

        /* 2d view YZ. */
        i = 1;
        if(i < total)
        {
            view2d = View2DCreate( 
                core_ptr, editor,
                VMA_VIEW2D_TYPE_YZ,
            editor->view_restored_toplevel[i],
                editor->view_maximized_toplevel,
                editor, EditorView2DEventCB   
            );
            if(view2d != NULL)
            {
            /* Flip i values on YZ view. */
            view2d->flags |= VMA_VIEW_FLAG_FLIP_I;
                View2DSetPalette(view2d, &vpalette);
            }
            editor->view2d[i] = view2d;
        }

      /* 2d view XY. */
        i = 2;
        if(i < total)
        {
            view2d = View2DCreate(
                core_ptr, editor,
                VMA_VIEW2D_TYPE_XY,
            editor->view_restored_toplevel[i],
                editor->view_maximized_toplevel,
                editor, EditorView2DEventCB
            );
            if(view2d != NULL)
            {
                View2DSetPalette(view2d, &vpalette);
            }
            editor->view2d[i] = view2d;
        }


        /* 3D view. */
        i = 3;
        if(i < total)
        {
          view3d = View3DCreate(
                core_ptr, editor,
                VMA_VIEW3D_TYPE_STANDARD,
            editor->view_restored_toplevel[i],
            editor->view_maximized_toplevel,
                editor, EditorView3DEventCB
            );
            if(view3d != NULL)
            {
                View3DSetPalette(view3d, &vpalette);
            }
            editor->view3d[0] = view3d;
      }


      return(0);
}


/*
 *    Blocks input and sets editor as marked busy.
 */
void EditorSetBusy(ma_editor_struct *editor)
{
        GtkWidget *w;
      GdkCursor *cur;

        if(editor == NULL)
            return;

      w = editor->toplevel;
      if(w == NULL)
          return;

      cur = editor->busy_cur;
      if(cur == NULL)
          return;

      if(GTK_WIDGET_NO_WINDOW(w))
          return;

      gdk_window_set_cursor(w->window, cur);
      gdk_flush();
}

/*
 *    Allows input and sets editor as ready for input.
 */
void EditorSetReady(ma_editor_struct *editor)
{
        GtkWidget *w;

        if(editor == NULL)
            return;

        w = editor->toplevel;
        if(w == NULL)
            return;

        if(GTK_WIDGET_NO_WINDOW(w))
            return;

        gdk_window_set_cursor(w->window, NULL);
      gdk_flush();
}


/*
 *    Creates a new editor, returning the pointer to its structure or
 *    NULL on error.
 */
ma_editor_struct *EditorCreate(gpointer core_ptr)
{
      GtkWidget *w, *parent, *parent2, *parent3, *handle_box;
      gint  toplevel_width, toplevel_height,
            lists_and_views_paned_size,
            panel0_size, panel1_size, panel2_size;
      ma_editor_struct *editor = (ma_editor_struct *)calloc(
          1, sizeof(ma_editor_struct)
      );


      if((core_ptr == NULL) || (editor == NULL))
      {
          free(editor);
          return(NULL);
      }

      /* Get previous toplevel size. */
      toplevel_width = VMACFGItemListGetValueI(
          option, VMA_CFG_PARM_WIDTH
      );
      if(toplevel_width < 1)
          toplevel_width = VMA_EDITOR_DEF_WIDTH;

        toplevel_height = VMACFGItemListGetValueI(
            option, VMA_CFG_PARM_HEIGHT
        );
        if(toplevel_height < 1)
            toplevel_height = VMA_EDITOR_DEF_HEIGHT;

        /* Get panel sizes from configuration options list. */
      lists_and_views_paned_size = VMACFGItemListGetValueI(
          option, VMA_CFG_PARM_LIST_AND_VIEW_PANED_SIZE
      );
      if(lists_and_views_paned_size < 1)
          lists_and_views_paned_size = 100;

      panel0_size = VMACFGItemListGetValueI(
          option, VMA_CFG_PARM_PANEL0_SIZE
      );
      if(panel0_size < 1)
          panel0_size = 100;

      panel1_size = VMACFGItemListGetValueI(
          option, VMA_CFG_PARM_PANEL1_SIZE
      );
        if(panel1_size < 1)
          panel1_size = 100;

      panel2_size = VMACFGItemListGetValueI(
          option, VMA_CFG_PARM_PANEL2_SIZE
      );
        if(panel2_size < 1)
          panel2_size = 100;


      /* Reset values. */
      editor->initialized = TRUE;
      editor->map_state = FALSE;
      editor->processing = FALSE;

      editor->selected_model_item = -1;
        editor->selected_primitive = NULL;
      editor->total_selected_primitives = 0;
        editor->selected_value = NULL;
      editor->total_selected_values = 0;
      editor->loaded_filename = NULL;

      editor->core_ptr = core_ptr;

      memset(&editor->texture_browser, 0x00, sizeof(ma_texture_browser_struct));

      editor->undo = NULL;
      editor->total_undos = 0;
      editor->max_undos = VMACFGItemListGetValueI(
          option, VMA_CFG_PARM_UNDO_MAX
      );

        editor->redo = NULL;
        editor->total_redos = 0;
        editor->max_redos = VMACFGItemListGetValueI(
            option, VMA_CFG_PARM_UNDO_MAX
        );


      /* Load cursors. */
      editor->busy_cur = gdk_cursor_new(GDK_WATCH);


      /* Load fonts. */
/*
        editor->font_gtk = gdk_font_load(
            "-misc-fixed-medium-r-*-*-*-100-*-*-*-*-*-*"
        );
        editor->font_view =
 */

        /* Toplevel. */
        w = gtk_window_new(GTK_WINDOW_TOPLEVEL);
        editor->toplevel = w;
        gtk_widget_add_events(
          w,
            GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK
        );
        gtk_signal_connect(
            GTK_OBJECT(w), "key_press_event",
            GTK_SIGNAL_FUNC(EditorEventCB),
            editor
        );
        gtk_signal_connect(
            GTK_OBJECT(w), "key_release_event",
            GTK_SIGNAL_FUNC(EditorEventCB),
            editor
        );
        gtk_signal_connect(
            GTK_OBJECT(w), "configure_event",
            GTK_SIGNAL_FUNC(EditorEventCB),
            editor
        );

        gtk_widget_realize(w);
        GUISetWMIcon(w->window, (u_int8_t **)vertex_xpm);
        gtk_widget_set_usize(
          w, toplevel_width, toplevel_height
      );
        gtk_window_set_policy(
            GTK_WINDOW(w),
            TRUE, TRUE, FALSE
        );
        if(!GTK_WIDGET_NO_WINDOW(w))
        {
            GdkGeometry geometry;

            geometry.min_width = 100;
            geometry.min_height = 70;

            geometry.base_width = 0;
            geometry.base_height = 0;

            geometry.width_inc = 1;
            geometry.height_inc = 1;
/*
            geometry.min_aspect = 1.3;
            geometry.max_aspect = 1.3;
 */
            gdk_window_set_geometry_hints(
                w->window,
                &geometry,
                GDK_HINT_MIN_SIZE |
                GDK_HINT_BASE_SIZE |
                /* GDK_HINT_ASPECT | */
                GDK_HINT_RESIZE_INC
            );
        }
/*
        gdk_window_set_decorations(w->window,
            GDK_DECOR_TITLE |
            GDK_DECOR_MENU |
            GDK_DECOR_MINIMIZE
        );
        gdk_window_set_functions(w->window,
              GDK_FUNC_MOVE |
              GDK_FUNC_MINIMIZE |
              GDK_FUNC_CLOSE
        );
 */
        gtk_signal_connect(
            GTK_OBJECT(w),
            "delete_event",
            GTK_SIGNAL_FUNC(EditorCloseCB),
            editor
        );
        gtk_signal_connect(
            GTK_OBJECT(w),
            "destroy",
            GTK_SIGNAL_FUNC(EditorDestroyCB),
            editor
        );
        gtk_window_set_title(GTK_WINDOW(w), PROG_NAME);
        gtk_container_set_border_width(GTK_CONTAINER(w), 0);
      parent = w;


        /* Main vbox. */
        w = gtk_vbox_new(FALSE, 0);
        gtk_container_add(GTK_CONTAINER(parent), w);
        gtk_widget_show(w);
      parent = w;

      /* Build menu, first creating a handle box to place it in. */
      handle_box = gtk_handle_box_new();
      editor->menu_bar_dock = handle_box;
      gtk_box_pack_start(GTK_BOX(parent), handle_box, FALSE, FALSE, 0);
/*
      GTK_HANDLE_BOX(handle_box)->shrink_on_detach = 0;
 */
      gtk_widget_show(handle_box);
      EditorBuildMenuBar(editor, handle_box);

      /* Build general tool ribbon, first creating a handle box to
       * place it in.
       */
        handle_box = gtk_handle_box_new();
        editor->general_tool_ribbon_dock = handle_box;
        gtk_box_pack_start(GTK_BOX(parent), handle_box, FALSE, FALSE, 0);
        gtk_widget_show(handle_box);
      EditorBuildGeneralToolRibbon(editor, handle_box);

      /* Build primitives palette tool ribbon. */
      handle_box = gtk_handle_box_new();
        editor->primitives_tool_ribbon_dock = handle_box;
        gtk_box_pack_start(GTK_BOX(parent), handle_box, FALSE, FALSE, 0);
        gtk_widget_show(handle_box);
        EditorBuildPrimitivesToolRibbon(editor, handle_box);


      /* Create paned widget that separates the lists and views with
       * the text dialog.
       */
      w = gtk_vpaned_new();
      gtk_paned_set_handle_size(GTK_PANED(w), VMA_DEF_PANED_HANDLE_SIZE);
      gtk_paned_set_gutter_size(GTK_PANED(w), VMA_DEF_PANED_GUTTER_SIZE);
      gtk_box_pack_start(GTK_BOX(parent), w, TRUE, TRUE, 0);
      gtk_widget_show(w);
      parent2 = w;

      /* Vbox holding list and views. */
      w = gtk_vbox_new(FALSE, 0);
        gtk_paned_add1(GTK_PANED(parent2), w);
        gtk_widget_set_usize(w, -1, lists_and_views_paned_size);
      editor->lists_and_views_toplevel = w;
      gtk_widget_show(w);
        parent3 = w;


      /* Create paned widgets that will hold the lists and views. */
      w = gtk_hpaned_new();
      gtk_paned_set_handle_size(GTK_PANED(w), VMA_DEF_PANED_HANDLE_SIZE);
      gtk_paned_set_gutter_size(GTK_PANED(w), VMA_DEF_PANED_GUTTER_SIZE);
      gtk_box_pack_start(GTK_BOX(parent3), w, TRUE, TRUE, 0);
      gtk_widget_show(w);
      parent3 = w;

      /* Vbox that will hold models and primitives lists. */
      w = gtk_vbox_new(FALSE, 0);
      editor->panel[0] = w;
      gtk_widget_set_usize(w, panel0_size, -1);
      gtk_paned_add1(GTK_PANED(parent3), w);
      gtk_widget_show(w);

      /* Second paned widget that will go into the first paned widget
       * and hold the views and values lists.
       */
      w = gtk_hpaned_new();
      gtk_paned_set_handle_size(GTK_PANED(w), VMA_DEF_PANED_HANDLE_SIZE);
      gtk_paned_set_gutter_size(GTK_PANED(w), VMA_DEF_PANED_GUTTER_SIZE);
      gtk_paned_add2(GTK_PANED(parent3), w);
      gtk_widget_show(w);
      parent3 = w;

      /* Vbox that will hold parents for restored and maximized view
       * parents.
       */
      w = gtk_vbox_new(FALSE, 0);
      editor->panel[1] = w;
      gtk_widget_set_usize(w, panel1_size, -1);
      gtk_paned_add1(GTK_PANED(parent3), w);
      gtk_widget_show(w);

      /* Vbox that will hold values list. */
      w = gtk_vbox_new(FALSE, 0);
      editor->panel[2] = w;
      gtk_paned_add2(GTK_PANED(parent3), w);
      gtk_widget_show(w);


      /* Vbox parent for holding text dialog's pull out. */
        w = gtk_vbox_new(FALSE, 0);
        gtk_paned_add2(GTK_PANED(parent2), w);
      editor->text_dialog_toplevel = w;
      gtk_widget_show(w);

      /* Create text dialog. */
      EditorTDialogCreate(editor, &editor->tdialog);

      /* Create status bar. */
      editor->sb = VMAStatusBarNew(
          (void *)core_ptr, (void *)editor, parent
      );


      /* Build list and view widgets. */
      EditorBuildModelList(editor, editor->panel[0]);
      EditorBuildViews(core_ptr, editor, editor->panel[1]);
      EditorBuildValuesList(editor, editor->panel[2]);


      /* Build input dialog for this editor. */
      EditorIDialogCreate(editor, &editor->idialog);

        /* Color selection. */
        ClrSelCreate(&editor->clrsel, editor);

      /* Build texture browser for this editor. */
      TexBrowserCreate(&editor->texture_browser, editor);


        /* Do not update texture browser or view menus, they should
       * already be updated at their creation.
         */
      EditorReset(editor, FALSE);


      return(editor);
}


/*
 *    Updates apperance values for the given editor.
 *
 *    This function should be called whenever the global configuration
 *    has been changed.
 */
void EditorUpdateAppearance(ma_editor_struct *editor)
{
      static gbool reenterant = FALSE;
      gbool pointer_emulate_2button;
      gint n;
      gint undo_max;
      gint model_num, pn;
      v3d_model_struct *model_ptr;
        gpointer p;
      GtkWidget *w;
      vma_view2d_struct *view2d;
      vma_view3d_struct *view3d;
        vma_view_palette_struct view_palette;
      ma_texture_browser_struct *tb;


        if(editor == NULL)
            return;

        if(!editor->initialized || editor->processing)
            return;

        if(reenterant)
            return;
        else
            reenterant = TRUE;


      /* Clear undo (and redo) buffers if the maximum limits have
       * changed.
       */
      undo_max = VMACFGItemListGetValueI(
            option, VMA_CFG_PARM_UNDO_MAX
        );
      if(editor->max_undos != undo_max)
      {
          VMAUndoListDeleteAll(
            &editor->undo, &editor->total_undos
            );
            editor->max_undos = undo_max; /* Set new max. */
        }
      if(editor->max_redos != undo_max)
      {
          VMAUndoListDeleteAll(
            &editor->redo, &editor->total_redos
          );
          editor->max_redos = undo_max;   /* Set new max. */
      }

        /* Get selected model on editor. */
        model_num = EditorSelectedModelIndex(editor);
        model_ptr = V3DModelListGetPtr(
            editor->model, editor->total_models, model_num
        );

        /* Get selected primitive. */
        if(model_ptr != NULL)
        {
            pn = ((editor->total_selected_primitives == 1) ?
                editor->selected_primitive[0] : -1
            );
            p = V3DMPListGetPtr(
                model_ptr->primitive, model_ptr->total_primitives, pn
            );
        }
        else
        {
            pn = -1;
            p = NULL;
        }

      /* Need to update colors on the view's palette structure since
         * that structure now contains a bunch of pointers to invalid
         * pointers to the view color structures in the global
         * configuration options list.
         */
        memset(&view_palette, 0x00, sizeof(vma_view_palette_struct));
        view_palette.background = (vma_color_struct *)
            VMACFGItemListMatchGetValue(
                option, VMA_CFG_PARM_VIEW_COLOR_BACKGROUND, NULL
            );
        view_palette.point = (vma_color_struct *)
            VMACFGItemListMatchGetValue(
                option, VMA_CFG_PARM_VIEW_COLOR_POINT, NULL
            );
        view_palette.line = (vma_color_struct *)
            VMACFGItemListMatchGetValue(
                option, VMA_CFG_PARM_VIEW_COLOR_LINE, NULL
            );
        view_palette.line_strip = (vma_color_struct *)
            VMACFGItemListMatchGetValue(
                option, VMA_CFG_PARM_VIEW_COLOR_LINE_STRIP, NULL
            );
        view_palette.line_loop = (vma_color_struct *)
            VMACFGItemListMatchGetValue(
                option, VMA_CFG_PARM_VIEW_COLOR_LINE_LOOP, NULL
            );
        view_palette.triangle = (vma_color_struct *)
            VMACFGItemListMatchGetValue(
                option, VMA_CFG_PARM_VIEW_COLOR_TRIANGLE, NULL
            );
        view_palette.triangle_strip = (vma_color_struct *)
            VMACFGItemListMatchGetValue(
                option, VMA_CFG_PARM_VIEW_COLOR_TRIANGLE_STRIP, NULL
            );
        view_palette.triangle_fan = (vma_color_struct *)
            VMACFGItemListMatchGetValue(
                option, VMA_CFG_PARM_VIEW_COLOR_TRIANGLE_FAN, NULL
            );
        view_palette.quad = (vma_color_struct *)
            VMACFGItemListMatchGetValue(
                option, VMA_CFG_PARM_VIEW_COLOR_QUAD, NULL
            );
        view_palette.quad_strip = (vma_color_struct *)
            VMACFGItemListMatchGetValue(
                option, VMA_CFG_PARM_VIEW_COLOR_QUAD_STRIP, NULL
            );
        view_palette.polygon = (vma_color_struct *)
            VMACFGItemListMatchGetValue(
                option, VMA_CFG_PARM_VIEW_COLOR_POLYGON, NULL
            );
        view_palette.texture_outline = (vma_color_struct *)
            VMACFGItemListMatchGetValue(
                option, VMA_CFG_PARM_VIEW_COLOR_TEXTURE_OUTLINE, NULL
            );
        view_palette.texture_outline_selected = (vma_color_struct *)
            VMACFGItemListMatchGetValue(
                option, VMA_CFG_PARM_VIEW_COLOR_TEXTURE_OUTLINE_SELECTED, NULL
            );
        view_palette.heightfield = (vma_color_struct *)
           VMACFGItemListMatchGetValue(
                option, VMA_CFG_PARM_VIEW_COLOR_HEIGHTFIELD, NULL
           );
        view_palette.grid = (vma_color_struct *)
            VMACFGItemListMatchGetValue(
                option, VMA_CFG_PARM_VIEW_COLOR_GRID, NULL
            );
        view_palette.selected = (vma_color_struct *)
            VMACFGItemListMatchGetValue(
                option, VMA_CFG_PARM_VIEW_COLOR_SELECTED, NULL
            );
        view_palette.selected_vertex = (vma_color_struct *)
            VMACFGItemListMatchGetValue(
                option, VMA_CFG_PARM_VIEW_COLOR_SELECTED_VERTEX, NULL
            );
        view_palette.cursory = (vma_color_struct *)
            VMACFGItemListMatchGetValue(
                option, VMA_CFG_PARM_VIEW_COLOR_CURSORY, NULL
            );
        view_palette.normal_vector = (vma_color_struct *)
            VMACFGItemListMatchGetValue(
                option, VMA_CFG_PARM_VIEW_COLOR_NORMAL_VECTOR, NULL
            );

        /* Update all view values. */
      pointer_emulate_2button = VMACFGItemListGetValueI(
            option, VMA_CFG_PARM_POINTER_EMULATE_2BUTTON
        ) ? TRUE : FALSE;
        for(n = 0; n < VMA_MAX_2D_VIEWS_PER_EDITOR; n++)
        {
            view2d = editor->view2d[n];
            if(view2d == NULL)
                continue;

            View2DSetPalette(view2d, &view_palette);

            if(pointer_emulate_2button)
                view2d->flags |= VMA_VIEW_FLAG_POINTER_EMULATE_2BUTTON;
            else
                view2d->flags &= ~VMA_VIEW_FLAG_POINTER_EMULATE_2BUTTON;

            view2d->position_decimals = ViewPositionDecimals();
            view2d->angle_decimals = ViewAngleDecimals();
        }
        for(n = 0; n < VMA_MAX_3D_VIEWS_PER_EDITOR; n++)
        {
            view3d = editor->view3d[n];
            if(view3d == NULL)
                continue;

            View3DSetPalette(view3d, &view_palette);

            view3d->position_decimals = ViewPositionDecimals();
            view3d->angle_decimals = ViewAngleDecimals();

            if(pointer_emulate_2button)
                view3d->flags |= VMA_VIEW_FLAG_POINTER_EMULATE_2BUTTON;
            else
                view3d->flags &= ~VMA_VIEW_FLAG_POINTER_EMULATE_2BUTTON;

            view3d->render_state = ViewRenderState();
            w = view3d->render_toggle;
            if(w != NULL)
                gtk_toggle_button_set_active(
                    GTK_TOGGLE_BUTTON(w), view3d->render_state
                );

            view3d->cull_state = ViewCullState();
            w = view3d->cull_toggle;
            if(w != NULL)
                gtk_toggle_button_set_active(
                    GTK_TOGGLE_BUTTON(w), view3d->cull_state
                );
            /* Update cull direction, no widget. */
            view3d->cull_direction = ViewCullDirection();

            view3d->translations_state = ViewTranslationsState();
            w = view3d->translations_toggle;
            if(w != NULL)
                gtk_toggle_button_set_active(
                    GTK_TOGGLE_BUTTON(w), view3d->translations_state
                );

            view3d->enable_alpha_channel = ViewEnableAlphaChannel();
            /* No widget for enable alpha channel. */

            view3d->cam_clip_near = ViewCameraClipNear();
            view3d->cam_clip_far = ViewCameraClipFar();
            view3d->cam_fov = ViewCameraFOV();
        }

        /* Update vertex data resolution. */
        editor->vertex_decimals = EditorVertexPositionDecimals();
        editor->vertex_angle_decimals = EditorVertexAngleDecimals();


        /* Update values list on editor. */
        EditorListDeleteValuesG(editor);
        EditorListAddValuesRG(editor, p);


        /* Update view menus and redraw. */
        EditorUpdateAllViewMenus(editor);
        EditorRedrawAllViews(editor);

        /* Update menus on editor. */
        EditorUpdateMenus(editor);

        /* Update apperance and menus on editor's text dialog. */
      EditorTDialogUpdateAppearance(&editor->tdialog);


      /* Begin updating resources on editor's texture browser. */
      tb = &editor->texture_browser;
/* Nothing to do for texture browser. */

      /* Update menus on texture browser. */
      TexBrowserUpdateMenus(tb);



      reenterant = FALSE;
      return;
}

/*
 *    Updates the menu items on the specified editor to match
 *    other values on the editor structure.
 */
void EditorUpdateMenus(ma_editor_struct *editor)
{
      static gbool reenterant = FALSE;
      gbool sensitivity, state;
      gint pn = -1, model_num = -1;
      v3d_model_struct *model_ptr = NULL;
      gpointer p = NULL;
      GtkWidget *w;
      gint toolbar_btn_layout = 2;


      if(editor == NULL)
          return;

        if(!editor->initialized)
            return;

      if(reenterant)
          return;
      else
          reenterant = TRUE;


      /* Get toolbar button style. */
      toolbar_btn_layout = VMACFGItemListGetValueI(
          option, VMA_CFG_PARM_TOOLBAR_STYLE
      );

      /* Get pointer to currently selected model if any. */
      model_num = EditorSelectedModelIndex(editor);
      model_ptr = V3DModelListGetPtr(
          editor->model, editor->total_models, model_num
      );

      /* Get pointer to single selected primitive if any. */
      if((editor->total_selected_primitives == 1) &&
           (model_ptr != NULL)
      )
      {
          pn = editor->selected_primitive[0];
          p = V3DMPListGetPtr(
            model_ptr->primitive, model_ptr->total_primitives, pn
          );
      }


      /* Update window title. */
      w = editor->toplevel;
      if(w != NULL)
      {
          gchar *buf = g_strdup_printf(
            PROG_NAME ": %s%s",
            (editor->loaded_filename != NULL) ?
                editor->loaded_filename : "Untitled",
            (editor->has_changes) ?
                " (*)" : ""
          );
          gtk_window_set_title(GTK_WINDOW(w), buf);
          g_free(buf);
      }


#define SET_WIDGET_SENSITIVITY      \
{ if(w != NULL) gtk_widget_set_sensitive(w, sensitivity); }

#define SET_CHECK_MENU_ITEM_STATE   \
{ \
 if(w != NULL) \
  gtk_check_menu_item_set_active( \
   GTK_CHECK_MENU_ITEM(w), \
   state \
  ); \
}

#define SET_BUTTON_LAYOUT           \
{ \
 if(w != NULL) \
 { \
  switch(toolbar_btn_layout) \
  { \
   case 2: \
    GUIButtonChangeLayout(w, 1, 1); \
    gtk_widget_set_usize(w, 60, 50); \
    break; \
   case 1: \
    GUIButtonChangeLayout(w, 1, 0); \
    gtk_widget_set_usize(w, 30, 30); \
    break; \
   default: \
    GUIButtonChangeLayout(w, 0, 1); \
    gtk_widget_set_usize(w, -1, 30); \
    break; \
  } \
 } \
}

      /* Standard menu items. */

      /* File menu. */
      /* New. */
        w = editor->new_mi;
      sensitivity = !FileBrowserIsQuery();
        SET_WIDGET_SENSITIVITY 

        /* Open. */
        w = editor->open_mi;
        sensitivity = !FileBrowserIsQuery();
        SET_WIDGET_SENSITIVITY

        /* Save. */
        w = editor->save_mi;
        sensitivity = !FileBrowserIsQuery();
        SET_WIDGET_SENSITIVITY

        /* Save as. */
        w = editor->save_as_mi;
        sensitivity = !FileBrowserIsQuery();
        SET_WIDGET_SENSITIVITY 

      /* Backup. */
      w = editor->backup_mi;
      if((editor->loaded_filename == NULL) ||
         FileBrowserIsQuery()
      )
          sensitivity = FALSE;
      else
          sensitivity = TRUE;
      SET_WIDGET_SENSITIVITY

      /* Revert. */
        w = editor->revert_mi;
        if((editor->loaded_filename == NULL) ||
           !(editor->has_changes)
      )
          sensitivity = FALSE;
      else
          sensitivity = TRUE;
      SET_WIDGET_SENSITIVITY

        /* Import. */
        w = editor->import_mi;
        sensitivity = !FileBrowserIsQuery();
        SET_WIDGET_SENSITIVITY

      /* Export. */
      w = editor->export_mi;
      sensitivity = !FileBrowserIsQuery();
        SET_WIDGET_SENSITIVITY


      /* Edit menu. */

      /* Undo. */
      w = editor->undo_milabel;
      if(w != NULL)
      {
          gint total = editor->total_undos;
          gchar text[256];

          (*text) = '\0';
          strcat(text, "Undo");
          if(total > 0)
          {
            vma_undo_common_struct *u = editor->undo[total - 1];
            char numstr[80];

            if(u != NULL)
            {
                if(u->name != NULL)
                {
                  strcat(text, " ");
                  strncat(text, u->name, 80);
                        text[256 - 1] = '\0';
                }
            }
            sprintf(numstr, "(%i)", total);
            strcat(text, numstr);
          }
          gtk_label_set_text(GTK_LABEL(w), text);
      }
      w = editor->undo_mi;
      sensitivity = ((editor->total_undos > 0) ?
          TRUE : FALSE
      );
      SET_WIDGET_SENSITIVITY

      /* Redo. */
        w = editor->redo_milabel;
        if(w != NULL)                              
        {
            gint total = editor->total_redos;   
            gchar text[256];

            *text = '\0';
            strcat(text, "Redo");
            if(total > 0)      
            {
                vma_undo_common_struct *u = editor->redo[total - 1];
                gchar numstr[80];

                if(u != NULL)
                {  
                    if(u->name != NULL)
                    {
                        strcat(text, " ");
                        strncat(text, u->name, 80);
                        text[256 - 1] = '\0';
                    }
                }
                sprintf(numstr, "(%i)", total);
                strcat(text, numstr);
            }
            gtk_label_set_text(GTK_LABEL(w), text);
        }
        w = editor->redo_mi;
      sensitivity = ((editor->total_redos > 0) ?
          TRUE : FALSE
      );
      SET_WIDGET_SENSITIVITY

      /* Cut. */
      w = editor->cut_mi;
        if(editor->total_selected_primitives > 0)
            sensitivity = TRUE;
        else
            sensitivity = FALSE;
      SET_WIDGET_SENSITIVITY
      /* Copy. */
      w = editor->copy_mi;
        if(editor->total_selected_primitives > 0)
            sensitivity = TRUE;
        else
            sensitivity = FALSE;
      SET_WIDGET_SENSITIVITY

        /* Write protect enabled. */
        w = editor->write_protect_enabled_mi;
      if(w != NULL)
      {
          if(editor->write_protect)
            gtk_widget_show(w);
          else
            gtk_widget_hide(w);
      }
        /* Write protect disabled. */
        w = editor->write_protect_disabled_mi;
        if(w != NULL)
        {
            if(editor->write_protect)
                gtk_widget_hide(w);
            else
                gtk_widget_show(w);
        }


      /* Model header. */
      w = editor->model_header_mi;
      sensitivity = TRUE;
      SET_WIDGET_SENSITIVITY

      /* Model menu. */
      /* Delete. */
      w = editor->model_delete_mi;
      if(model_ptr != NULL)
            sensitivity = TRUE;
        else
            sensitivity = FALSE;
      SET_WIDGET_SENSITIVITY
      /* Show. */
      w = editor->model_show_micheck;
      state = FALSE;
      sensitivity = FALSE;
      if(model_ptr != NULL)
      {
          if(model_ptr->flags & V3D_MODEL_FLAG_HIDE)
            state = FALSE;
          else
            state = TRUE;
          if(model_ptr->type == V3D_MODEL_TYPE_STANDARD)
            sensitivity = TRUE;
      }
      SET_CHECK_MENU_ITEM_STATE
      SET_WIDGET_SENSITIVITY

      /* Properties. */
      w = editor->model_properties_mi;
        if(model_ptr != NULL)
            sensitivity = TRUE;
        else
            sensitivity = FALSE; 
        SET_WIDGET_SENSITIVITY


      /* Primitives menu. */
      /* Menu heading. */
      w = editor->primitive_mh;
      if(w != NULL)
      {
          /* Hide primitive menu if no models selected. */
          if(EditorSelectedModelIndex(editor) < 0)
            gtk_widget_hide(w);
          else
            gtk_widget_show(w);
      }
      /* Delete. */
        w = editor->primitive_delete_mi;
      if(editor->total_selected_primitives > 0)
          sensitivity = TRUE;
      else
          sensitivity = FALSE;
      SET_WIDGET_SENSITIVITY
      /* Flip winding. */
      w = editor->primitive_flip_winding_mi;
      if(editor->total_selected_primitives > 0)
          sensitivity = TRUE;
      else
          sensitivity = FALSE;
      SET_WIDGET_SENSITIVITY
        /* Unitlize normal. */
        w = editor->primitive_unitlize_normal_mi;
        if(editor->total_selected_primitives > 0)
            sensitivity = TRUE;
        else
            sensitivity = FALSE;
        SET_WIDGET_SENSITIVITY
        /* Translate selected. */
        w = editor->primitive_translate_mi;
        if(editor->total_selected_primitives > 0)
            sensitivity = TRUE;
        else
            sensitivity = FALSE;
        SET_WIDGET_SENSITIVITY
        /* Rotate selected. */
        w = editor->primitive_rotate_mi;
        if(editor->total_selected_primitives > 0)
            sensitivity = TRUE;
        else
            sensitivity = FALSE;
        SET_WIDGET_SENSITIVITY
        /* Scale selected. */
        w = editor->primitive_scale_mi;
        if(editor->total_selected_primitives > 0)
            sensitivity = TRUE;
        else
            sensitivity = FALSE;
        SET_WIDGET_SENSITIVITY
      /* Mirror. */
      w = editor->primitive_mirror_mi;
      if(editor->total_selected_primitives > 0)
            sensitivity = TRUE;
        else
            sensitivity = FALSE;
      SET_WIDGET_SENSITIVITY
        /* Snap. */
        w = editor->primitive_snap_mi;
        if(editor->total_selected_primitives > 0)
            sensitivity = TRUE;
        else
            sensitivity = FALSE;
        SET_WIDGET_SENSITIVITY
      /* Add vertex. */
      w = editor->primitive_add_vertex_mi;
      if(editor->total_selected_primitives > 0)
            sensitivity = TRUE;
        else
            sensitivity = FALSE;
        SET_WIDGET_SENSITIVITY
      /* Remove vertex. */
        w = editor->primitive_remove_vertex_mi;
      if(editor->total_selected_primitives > 0)
            sensitivity = TRUE;
        else
            sensitivity = FALSE;
        SET_WIDGET_SENSITIVITY


      /* Popup menus. */

      /* Models list popup menu. */
        /* Delete. */
        w = editor->models_list_delete_mi;
        if(model_ptr != NULL)
            sensitivity = TRUE;
        else
            sensitivity = FALSE;
        SET_WIDGET_SENSITIVITY
        /* Show. */
        w = editor->models_list_show_micheck;
        state = FALSE;
      sensitivity = FALSE;
        if(model_ptr != NULL)
        {
            if(model_ptr->flags & V3D_MODEL_FLAG_HIDE)
                state = FALSE;
            else
                state = TRUE;
            if(model_ptr->type == V3D_MODEL_TYPE_STANDARD)
                sensitivity = TRUE;
        }
        SET_CHECK_MENU_ITEM_STATE
      SET_WIDGET_SENSITIVITY
        /* Properties. */  
        w = editor->models_list_properties_mi;
        if(model_ptr != NULL)
            sensitivity = TRUE;
        else
            sensitivity = FALSE;
        SET_WIDGET_SENSITIVITY


      /* Primitives list popup menu. */
        /* Delete. */
        w = editor->primitives_list_delete_mi;
        if(editor->total_selected_primitives > 0)
            sensitivity = TRUE;
        else
            sensitivity = FALSE;
        SET_WIDGET_SENSITIVITY   
      /* Cut. */
      w = editor->primitives_list_cut_mi;
        if(editor->total_selected_primitives > 0)
            sensitivity = TRUE;
        else
            sensitivity = FALSE;
      SET_WIDGET_SENSITIVITY
      /* Copy. */
      w = editor->primitives_list_copy_mi;
        if(editor->total_selected_primitives > 0)
            sensitivity = TRUE;
        else
            sensitivity = FALSE;
      SET_WIDGET_SENSITIVITY
        /* Flip winding. */
        w = editor->primitives_list_flip_winding_mi;
        if(editor->total_selected_primitives > 0)
            sensitivity = TRUE;
        else
            sensitivity = FALSE;
        SET_WIDGET_SENSITIVITY
        /* Translate selected. */
        w = editor->primitives_list_translate_mi;
        if(editor->total_selected_primitives > 0)
            sensitivity = TRUE;
        else
            sensitivity = FALSE;
        SET_WIDGET_SENSITIVITY
        /* Rotate selected. */
        w = editor->primitives_list_rotate_mi;
        if(editor->total_selected_primitives > 0)
            sensitivity = TRUE;
        else
            sensitivity = FALSE;
        SET_WIDGET_SENSITIVITY
        /* Scale selected. */
        w = editor->primitives_list_scale_mi;
        if(editor->total_selected_primitives > 0)
            sensitivity = TRUE;
        else
            sensitivity = FALSE;
        SET_WIDGET_SENSITIVITY
        /* Mirror. */
        w = editor->primitives_list_mirror_mi;
        if(editor->total_selected_primitives > 0)
            sensitivity = TRUE;
        else
            sensitivity = FALSE;
        SET_WIDGET_SENSITIVITY
        /* Snap. */
        w = editor->primitives_list_snap_mi;
        if(editor->total_selected_primitives > 0)
            sensitivity = TRUE;
        else
            sensitivity = FALSE;
        SET_WIDGET_SENSITIVITY
        /* Add vertex. */
        w = editor->primitives_list_add_vertex_mi;
        if(editor->total_selected_primitives > 0)
            sensitivity = TRUE;
        else
            sensitivity = FALSE;
        SET_WIDGET_SENSITIVITY
        /* Remove vertex. */
        w = editor->primitives_list_remove_vertex_mi;
        if(editor->total_selected_primitives > 0)
            sensitivity = TRUE;
        else
            sensitivity = FALSE;
        SET_WIDGET_SENSITIVITY


      /* Values list pop up menu. */
      w = editor->values_list_menu;
      if(w != NULL)
      {
        w = editor->values_list_undo_milabel;
          if(w != NULL)
          {
            gint total = editor->total_undos;
            gchar text[256];

            (*text) = '\0';
            strcat(text, "Undo");
            if(total > 0)
            {
                vma_undo_common_struct *u = editor->undo[total - 1];
                gchar numstr[80];

                if(u != NULL)
                {
                    if(u->name != NULL)
                    {
                        strcat(text, " ");
                        strncat(text, u->name, 80);
                        text[256 - 1] = '\0';
                    }
                }
                sprintf(numstr, "(%i)", total);
                strcat(text, numstr);
            }
            gtk_label_set_text(GTK_LABEL(w), text);
          }
          w = editor->values_list_undo_mi;
          sensitivity = ((editor->total_undos > 0) ?
            TRUE : FALSE
          );
          SET_WIDGET_SENSITIVITY

          /* Redo. */
          w = editor->values_list_redo_milabel;
          if(w != NULL)
          {
            gint total = editor->total_redos;
            gchar text[256];

            (*text) = '\0';
            strcat(text, "Redo");
            if(total > 0)
            {
                vma_undo_common_struct *u = editor->redo[total - 1];
                gchar numstr[80];
          
                if(u != NULL) 
                {
                    if(u->name != NULL)
                    {
                        strcat(text, " ");
                        strncat(text, u->name, 80);
                        text[256 - 1] = '\0';
                    }
                }
                sprintf(numstr, "(%i)", total);
                strcat(text, numstr);
            }
            gtk_label_set_text(GTK_LABEL(w), text);
          }   
          w = editor->values_list_redo_mi;
          sensitivity = ((editor->total_redos > 0) ?
              TRUE : FALSE
          );          
          SET_WIDGET_SENSITIVITY

            /* Unitlize normal. */
            w = editor->values_list_unitlize_normal_mi;
          if(editor->total_selected_primitives > 0)
            sensitivity = TRUE;
          else
            sensitivity = FALSE;
          SET_WIDGET_SENSITIVITY

            /* Snap. */
            w = editor->values_list_snap_mi;
            if(editor->total_selected_primitives > 0)
                sensitivity = TRUE;
            else
                sensitivity = FALSE;
            SET_WIDGET_SENSITIVITY

          /* Add vertex. */
          w = editor->values_list_add_vertex;
          if(editor->total_selected_primitives > 0)
            sensitivity = TRUE;
          else
            sensitivity = FALSE;
          SET_WIDGET_SENSITIVITY

          /* Remove vertex. */
          w = editor->values_list_remove_vertex;
          if(editor->total_selected_primitives > 0)
            sensitivity = TRUE;
          else
            sensitivity = FALSE;
          SET_WIDGET_SENSITIVITY
      }


      /* Tool ribbons. */

        /* General tool ribbon. */
        w = editor->general_tool_ribbon;
        if(w != NULL)
        {
            w = editor->new_btn;
            SET_BUTTON_LAYOUT
            sensitivity = !FileBrowserIsQuery();
            SET_WIDGET_SENSITIVITY   

            w = editor->open_btn;
          SET_BUTTON_LAYOUT
            sensitivity = !FileBrowserIsQuery();
            SET_WIDGET_SENSITIVITY

            w = editor->save_btn;
            SET_BUTTON_LAYOUT
            sensitivity = !FileBrowserIsQuery();
            SET_WIDGET_SENSITIVITY

            w = editor->save_as_btn;
          SET_BUTTON_LAYOUT
            sensitivity = !FileBrowserIsQuery();
            SET_WIDGET_SENSITIVITY

            w = editor->import_btn;
            SET_BUTTON_LAYOUT
            sensitivity = !FileBrowserIsQuery();
            SET_WIDGET_SENSITIVITY

            w = editor->export_btn;
            SET_BUTTON_LAYOUT
            sensitivity = !FileBrowserIsQuery();
            SET_WIDGET_SENSITIVITY

            w = editor->undo_btn;
            SET_BUTTON_LAYOUT
          sensitivity = ((editor->total_undos > 0) ? TRUE : FALSE);
            SET_WIDGET_SENSITIVITY

            w = editor->redo_btn;
            SET_BUTTON_LAYOUT
            sensitivity = ((editor->total_redos > 0) ? TRUE : FALSE);
            SET_WIDGET_SENSITIVITY

            w = editor->print_btn;
            SET_BUTTON_LAYOUT
            sensitivity = TRUE;
            SET_WIDGET_SENSITIVITY
      }
      w = editor->general_tool_ribbon_dock;
      if(w != NULL)
          gtk_widget_queue_resize(w);


      /* Primitives tool ribbon. */
      w = editor->primitives_tool_ribbon;
      if(w != NULL)
      {
            /* Model header items. */
            w = editor->model_header_btn;
          sensitivity = TRUE;
          SET_WIDGET_SENSITIVITY

          /* Create model. */
          w = editor->model_create_btn;
          sensitivity = TRUE;
            SET_WIDGET_SENSITIVITY

          /* Delete model. */
            w = editor->model_delete_btn;
            if(model_ptr != NULL)
                sensitivity = TRUE;
            else
                sensitivity = FALSE;
            SET_WIDGET_SENSITIVITY

          /* Model properties. */
            w = editor->model_properties_btn;
            if(model_ptr != NULL)
                sensitivity = TRUE;
            else
                sensitivity = FALSE;
            SET_WIDGET_SENSITIVITY


          /* Primitives palette. */
          sensitivity = FALSE;
          if(model_ptr != NULL)
            {
                if(model_ptr->type == V3D_MODEL_TYPE_STANDARD)
                    sensitivity = TRUE;
            }
          VMAPrimPaletteSensitivity(
            editor->prim_palette, sensitivity
          );


          /* Get sensitivity state for all subsequent buttons. */
          if(editor->total_selected_primitives > 0)
            sensitivity = TRUE;
          else
            sensitivity = FALSE;

          w = editor->primitive_delete_btn;
          SET_WIDGET_SENSITIVITY

            w = editor->primitive_flip_winding_btn;
            SET_WIDGET_SENSITIVITY

            w = editor->primitive_unitlize_normal_btn;
            SET_WIDGET_SENSITIVITY

            w = editor->primitive_translate_btn;
            SET_WIDGET_SENSITIVITY

            w = editor->primitive_rotate_btn;
            SET_WIDGET_SENSITIVITY

            w = editor->primitive_scale_btn;
            SET_WIDGET_SENSITIVITY       

            w = editor->primitive_mirror_btn;
            SET_WIDGET_SENSITIVITY

            w = editor->primitive_add_vertex_btn;
            SET_WIDGET_SENSITIVITY

            w = editor->primitive_remove_vertex_btn;
            SET_WIDGET_SENSITIVITY
      }


      /* Values apply button. */
      w = editor->values_apply_btn;
      if(w != NULL)
      {
          if(editor->total_selected_values > 0)
            sensitivity = TRUE;
          else
            sensitivity = FALSE;
            SET_WIDGET_SENSITIVITY
      }


      /* Status bar. */
      VMAStatusBarUpdateMenus(editor->sb);

#undef SET_WIDGET_SENSITIVITY
#undef SET_CHECK_MENU_ITEM_STATE
#undef SET_BUTTON_LAYOUT

      /* Do not update texture browser or view menus, allow calling
       * function to elect for their updates.
       */

      reenterant = FALSE;
      return;
}

/*
 *    Destroys all menu items in the given editor's render menu
 *    and deallocates the editor's render menu item list.
 */
static void EditorRenderMenuDestroy(ma_editor_struct *editor)
{
      gint i;
      GtkWidget *w;
        vma_editor_render_mi_struct *render_mi;

        for(i = 0; i < editor->total_render_mis; i++)
        {
            render_mi = editor->render_mi[i];
            if(render_mi == NULL)
                continue;

          /* Reset functional widget, its a child of the menu item
           * widget so it'll get destroyed anyways.
           */
          render_mi->fw = NULL;

          /* Destroy menu item widget. */
            w = render_mi->w;
            if(w != NULL)
            {
                render_mi->w = NULL;
                gtk_widget_destroy(w);
                w = NULL;
            }

          /* Deallocate this render menu item structure. */            
            editor->render_mi[i] = NULL;
            g_free(render_mi);
            render_mi = NULL;
        }

      g_free(editor->render_mi);
        editor->render_mi = NULL;
        editor->total_render_mis = 0;

      return;
}

/*
 *    Deletes all menu items in the given editor's render menu
 *    and recreats them in accordance to the values set on the
 *    core structure's plug-ins list.
 */
void EditorRenderMenuRegenerate(ma_editor_struct *editor)
{
      static gbool reenterant = FALSE;
      GtkWidget *w, *fw, *menu;
      gint i, n;
      vma_core_struct *core_ptr;
      vma_plugin_struct *plugin_ptr;
      vma_editor_render_mi_struct *render_mi;

      gpointer accel_group = NULL;
      guint accel_mods;
      const gchar *label;
        u_int8_t **icon;
      gint accel_key;
        gpointer mclient_data;
        void (*func_cb)(GtkWidget *, gpointer);
        gint (*enter_cb)(gpointer, gpointer, gpointer) =
          (gpointer)EditorMenuItemEnterCB;


#define DO_ADD_MENU_ITEM_LABEL            \
{ \
 w = GUIMenuItemCreate( \
  menu, GUI_MENU_ITEM_TYPE_LABEL, accel_group, \
  icon, label, accel_key, accel_mods, (void **)&fw, \
  mclient_data, func_cb \
 ); \
 GUISetMenuItemCrossingCB( \
  w, enter_cb, mclient_data, NULL, mclient_data \
 ); \
}

      if(editor == NULL)
          return;

      if(!editor->initialized || editor->processing)
          return;

      core_ptr = (vma_core_struct *)editor->core_ptr;
      if(core_ptr == NULL)
          return;

      if(reenterant)
          return;
      else
          reenterant = TRUE;

      /* Destroy and deallocate references to old render menu items. */
      EditorRenderMenuDestroy(editor);

      /* Recreate render menu. */
      menu = editor->render_menu;
      mclient_data = (gpointer)editor;
      if(menu != NULL)
      {
          /* Itterate through each loaded and enabled plug-in. */
          for(i = 0; i < core_ptr->total_plugins; i++)
          {
            plugin_ptr = core_ptr->plugin[i];
            if((plugin_ptr == NULL) ? 1 : (plugin_ptr->handle == NULL))
                continue;

            /* Skip if have no rendering support. */
            if(plugin_ptr->render == NULL)
                continue;

            /* Allocate a new render menu item. */
            n = editor->total_render_mis;
            editor->total_render_mis = n + 1;
            editor->render_mi = (vma_editor_render_mi_struct **)g_realloc(
                editor->render_mi,
                editor->total_render_mis * sizeof(vma_editor_render_mi_struct *)
            );
            if(editor->render_mi == NULL)
            {
                editor->total_render_mis = 0;
                break;
            }
            editor->render_mi[n] = render_mi = (vma_editor_render_mi_struct *)calloc(
                1, sizeof(vma_editor_render_mi_struct)
            );

            /* Create new menu item. */
                icon = plugin_ptr->list_icon_data;
            label = ((plugin_ptr->render_label == NULL) ?
                plugin_ptr->title : plugin_ptr->render_label
            );
            if(label == NULL)
                label = "Untitled Rendering";
            accel_key = 0;
            accel_mods = 0;
            func_cb = EditorPluginRenderCB;
            DO_ADD_MENU_ITEM_LABEL

            /* Record values on render menu item structure. */
            if(render_mi != NULL)
            {
                render_mi->w = w;
                render_mi->fw = fw;
                render_mi->plugin_ptr = plugin_ptr;
            }
          }
      }


      /* If no render menu items were generated, then create one
       * to be a place holder.
       */
      if(editor->total_render_mis < 1)
      {
            /* Allocate a new render menu item. */
            n = 0;
            editor->total_render_mis = n + 1;
            editor->render_mi = (vma_editor_render_mi_struct **)realloc(
                editor->render_mi,
                editor->total_render_mis * sizeof(vma_editor_render_mi_struct *)
            );
            if(editor->render_mi == NULL)    
            {
                editor->total_render_mis = 0;
            }
          else
          {
            editor->render_mi[n] = render_mi = (vma_editor_render_mi_struct *)calloc(
                    1, sizeof(vma_editor_render_mi_struct)
                );
            if(render_mi != NULL)
            {
                /* Create new menu item. */
                icon = NULL;
                label = "No Render Plug-Ins";
                accel_key = 0;
                accel_mods = 0;
                func_cb = EditorPluginRenderCB;
                DO_ADD_MENU_ITEM_LABEL
 
                    render_mi->w = w;
                    render_mi->fw = fw;
                    render_mi->plugin_ptr = NULL;
            }
          }
      }

#undef DO_ADD_MENU_ITEM_LABEL

        reenterant = FALSE;
}


/*
 *    Applies any data in editor's widgets to actual data on editor.
 *
 *    Relevent displays will be updated.
 */
void EditorSyncData(ma_editor_struct *editor)
{
      if(editor == NULL)
          return;

        /* Editor's text dialog. */
        if(editor->tdialog.has_changes)
      {
            EditorTDialogApply(editor, &editor->tdialog);
          editor->tdialog.has_changes = FALSE;

          EditorTDialogUpdateMenus(&editor->tdialog);
      }
}



/*
 *    Deallocates the editor's user loaded data such as models
 *    and primitives. If unmap is set to true then the editor
 *    will be unmapped as needed.
 */
void EditorReset(ma_editor_struct *editor, gbool unmap)
{
      gint i;
      GtkWidget *w;
      vma_light_struct *light_ptr;


      if(editor == NULL)
          return;

      if(!editor->initialized || editor->processing)
          return;


      /* Begin resetting values. */

      /* Regenerate render menu. */
      EditorRenderMenuRegenerate(editor);

      /* Texture browser. */
      TexBrowserReset(&editor->texture_browser, unmap);

      /* Color selection. */
      ClrSelReset(&editor->clrsel, unmap);

      /* Text dialog. */
      EditorTDialogReset(&editor->tdialog, unmap);

      /* Undos and redos buffer. */
      VMAUndoListDeleteAll(&editor->undo, &editor->total_undos);
        VMAUndoListDeleteAll(&editor->redo, &editor->total_redos);

      editor->max_undos = VMACFGItemListGetValueI(
            option, VMA_CFG_PARM_UNDO_MAX
        );
      editor->max_redos = VMACFGItemListGetValueI(
            option, VMA_CFG_PARM_UNDO_MAX
        );


        /* Models, primitives and textures, both real and gui lists. */
        EditorListDeleteAllLists(editor);

      /* Lights. */
      w = editor->primitive_light_num_spin;
      if(w != NULL)
          gtk_spin_button_set_value(GTK_SPIN_BUTTON(w), 0);
      for(i = 0; i < VMA_LIGHTS_MAX; i++)
      {
          light_ptr = &(editor->light[i]);

          memset(light_ptr, 0x00, sizeof(vma_light_struct));
          if(i == 0)
          {
            /* First light. */
            light_ptr->spot_cutoff = (1.0 * PI);
            light_ptr->ambient.a = 1.0;
                light_ptr->ambient.r = 0.0;
                light_ptr->ambient.g = 0.0;
                light_ptr->ambient.b = 0.0;
                light_ptr->diffuse.a = 1.0;
                light_ptr->diffuse.r = 1.0;
                light_ptr->diffuse.g = 1.0;
                light_ptr->diffuse.b = 1.0;
                light_ptr->specular.a = 1.0;
                light_ptr->specular.r = 1.0;
                light_ptr->specular.g = 1.0;
                light_ptr->specular.b = 1.0;
                light_ptr->attenuation_constant = 1.0;
          }
          else
          {
            /* Some other light. */
                light_ptr->spot_cutoff = (1.0 * PI);
                light_ptr->ambient.a = 1.0;
                light_ptr->ambient.r = 0.0;
                light_ptr->ambient.g = 0.0;
                light_ptr->ambient.b = 0.0;
                light_ptr->diffuse.a = 1.0;
                light_ptr->diffuse.r = 0.0;
                light_ptr->diffuse.g = 0.0;
                light_ptr->diffuse.b = 0.0;
                light_ptr->specular.a = 1.0;
                light_ptr->specular.r = 0.0;
                light_ptr->specular.g = 0.0;
                light_ptr->specular.b = 0.0;
                light_ptr->attenuation_constant = 1.0;
          }
      }

      /* Views. */
      for(i = 0; i < VMA_MAX_2D_VIEWS_PER_EDITOR; i++)
            View2DReset(editor->view2d[i]);
        for(i = 0; i < VMA_MAX_3D_VIEWS_PER_EDITOR; i++)
            View3DReset(editor->view3d[i]);

      editor->vcursor_x = 0.0;
      editor->vcursor_y = 0.0;
      editor->vcursor_z = 0.0;

      /* Loaded model file name. */
      free(editor->loaded_filename);
      editor->loaded_filename = NULL;


      /* Reset other values. */
        editor->has_changes = FALSE;
        editor->write_protect = FALSE;

        editor->vertex_decimals = EditorVertexPositionDecimals();
        editor->vertex_angle_decimals = EditorVertexAngleDecimals();


        /* Update menus. */
        EditorUpdateMenus(editor);   
      EditorUpdateAllViewMenus(editor);

      /* Redraw all views on editor if not unmapping. */
      if(!unmap)
          EditorRedrawAllViews(editor);

      /* Unmap the editor. */
      if(unmap)
          EditorUnmap(editor);

      return;
}

/*
 *    Deallocates the editor structure's resources and the editor
 *    structure itself.
 */
void EditorDelete(ma_editor_struct *editor)
{
      gint i;
      GdkCursor **cur;
      GtkWidget **w;


      if(editor == NULL)
          return;

      if(!editor->initialized || editor->processing)
          return;


      /* Begin deleting editor structure and its resources. */

      /* Render menu. */
      EditorRenderMenuDestroy(editor);

      /* Status bar. */
      VMAStatusBarDelete(editor->sb);
      editor->sb = NULL;

      /* Text dialog. */
      EditorTDialogDestroy(editor, &editor->tdialog);

      /* Input dialog. */
      EditorIDialogDestroy(editor, &editor->idialog);

      /* Color selection. */
      ClrSelDestroy(&editor->clrsel);

      /* Texture browser. */
      TexBrowserDestroy(&editor->texture_browser);

        /* Undos and redos list. */
        VMAUndoListDeleteAll(&editor->undo, &editor->total_undos); 
        VMAUndoListDeleteAll(&editor->redo, &editor->total_redos);

        /* Models primitives and textures, both the real and gui
         * lists plus the selection lists.
         */
        EditorListDeleteAllLists(editor);

      /* Primitives palette. */
      VMAPrimPaletteDelete(editor->prim_palette);
      editor->prim_palette = NULL;

      /* Views. */
      for(i = 0; i < VMA_MAX_2D_VIEWS_PER_EDITOR; i++)
      {
          View2DDestroy(editor->view2d[i]);
          editor->view2d[i] = NULL;
      }
        for(i = 0; i < VMA_MAX_3D_VIEWS_PER_EDITOR; i++)
      {
            View3DDestroy(editor->view3d[i]);
          editor->view3d[i] = NULL;
      }

      /* Loaded model filename. */
      free(editor->loaded_filename);
      editor->loaded_filename = NULL;


      if(editor->initialized)
      {
#define DO_DESTROY_CURSOR     \
{ \
 if((*cur) != NULL) \
 { \
  GdkCursor *tc = *cur; \
  (*cur) = NULL; \
  gdk_cursor_destroy(tc); \
 } \
}

#define DO_DESTROY_WIDGET       \
{ \
 if((*w) != NULL) \
 { \
  GtkWidget *tmp_w = *w; \
  (*w) = NULL; \
  gtk_widget_destroy(tmp_w); \
 } \
}

          /* Begin destroying widgets. */

          w = &editor->primitive_scratchpad_btn_menu;
          editor->primitive_scratchpad_btn_insert_mi = NULL;
          editor->primitive_scratchpad_btn_append_mi = NULL;
          editor->primitive_scratchpad_btn_edit_mi = NULL;
          DO_DESTROY_WIDGET

            w = &editor->primitive_light_btn_menu;
            editor->primitive_light_btn_enabled_micheck = NULL;
            editor->primitive_light_btn_move_to_cursor_mi = NULL;
            editor->primitive_light_btn_properties_mi = NULL;
            DO_DESTROY_WIDGET

          w = &editor->primitive_create_submenu;
          DO_DESTROY_WIDGET

          w = &editor->values_list_menu;
          editor->values_list_undo_mi = NULL;
            editor->values_list_undo_milabel = NULL;
            editor->values_list_redo_mi = NULL;
            editor->values_list_redo_milabel = NULL;
          editor->values_list_unitlize_normal_mi = NULL;
            editor->values_list_add_vertex = NULL;
            editor->values_list_remove_vertex = NULL;
          DO_DESTROY_WIDGET

          w = &editor->primitives_list_create_submenu;
          DO_DESTROY_WIDGET
          w = &editor->primitives_list_menu;
            editor->primitives_list_delete_mi = NULL;
            editor->primitives_list_cut_mi = NULL;
            editor->primitives_list_copy_mi = NULL;
            editor->primitives_list_paste_mi = NULL;
            editor->primitives_list_flip_winding_mi = NULL;
            editor->primitives_list_translate_mi = NULL;
            editor->primitives_list_rotate_mi = NULL;
          editor->primitives_list_scale_mi = NULL;
            editor->primitives_list_mirror_mi = NULL;
            editor->primitives_list_snap_mi = NULL;
            editor->primitives_list_add_vertex_mi = NULL;
            editor->primitives_list_remove_vertex_mi = NULL;
          DO_DESTROY_WIDGET

          w = &editor->models_list_menu;
            editor->models_list_delete_mi = NULL;
            editor->models_list_show_micheck = NULL;
            editor->models_list_properties_mi = NULL;
          DO_DESTROY_WIDGET


          w = &editor->menu_bar;
          DO_DESTROY_WIDGET

          w = &editor->menu_bar_dock;
            DO_DESTROY_WIDGET


            w = &editor->general_tool_ribbon;
            DO_DESTROY_WIDGET

            w = &editor->general_tool_ribbon_dock;
            DO_DESTROY_WIDGET


          w = &editor->toplevel;
          DO_DESTROY_WIDGET
      }

        /* Cursors. */
        cur = &editor->busy_cur;
        DO_DESTROY_CURSOR

#undef DO_DESTROY_WIDGET
#undef DO_DESTROY_CURSOR   


      /* Deallocate structure itself. */
      free(editor);
}


/*
 *    Maps the editor as needed.
 */
void EditorMap(ma_editor_struct *editor)
{
      if(editor == NULL)
          return;

      if(!editor->initialized)
          return;

      if(!editor->map_state)
      {
          gtk_widget_show(editor->toplevel);
          editor->map_state = TRUE;
      }

      return;
}

/*
 *    Unmaps (shows) the editor as needed.
 */
void EditorUnmap(ma_editor_struct *editor)   
{
        if(editor == NULL)
            return;

        if(!editor->initialized)
            return;

        if(editor->map_state)
      {
            gtk_widget_hide(editor->toplevel);
          editor->map_state = FALSE;
      }

        return;
}


Generated by  Doxygen 1.6.0   Back to index