
/*   $Id$   */

#include "xcp.h"
#include "logo.h"
#include <signal.h>
#include <sys/stat.h>
#ifndef linux
#  include <sys/mkdev.h>
#endif

/* function definitions */
extern void getuname(), getgrname(), getname(), make_sorted_list(),  
     remove_item(), remove_item_dir(), add_file_to_dir(), 
     list_remove_all_directories(), file_copy_okay(),
     file_copy_cancel(), dtrt(char *path), write_settings(), read_settings(); 
extern head_path_struct *add_to_list();
extern int get_new_names(), really_quit(), 
           idcompare();
extern Boolean copy_file(), remove_dir(), move_file();
extern int copy_dir(), move_dir();
void file_cb(), prefs_cb(), sort_cb(), help_cb(), pre_read_settings(),
     button_exec(), setup_window(), quit_cb(), copy_cb(),
     move_cb(), copyas_cb(), moveas_cb(), link_cb(), linkas_cb(),
     change_sides(), left_button_exec(), right_button_exec(), exit_well(),
     build_list(), rm_cb(), make_new(), get_home(), double_click_list(), 
     flip_side(), really_rm_cb(), file_display(), inform(), sync_cb(),
     check_for_scroll_widget(), exit_exit(), working(), done_work(),
     update_settings(), pop_it_away();
XmString make_correct();
/* done with functions */

extern int errno;

/* globals */
struct commands {
       char name[20], instruction[50];
     } command_list[17];
struct pathstruct {
       char name[MAXBUTTONLENGTH], expand[MAXPATHLEN];
     } top_button_list[8];
Widget toplevel, mainform, bottomrowcol, command[18], upperform, menubar,
       leftform, rightform, centerform, but_copy, but_move, but_link, 
       but_copyas, but_moveas, but_exit, but_linkas, but_rm, but_sync, 
       exit_frame, left_path, right_path, top_button[8], left_menu_form, 
       right_menu_form, left_file_list, right_file_list, scroll_window,
       list_row_col, scroll_window_list_shell = NULL, scroll_window_list_pane,
       request, request_form, request_left, request_right, inform_widget, but_arrow, label_name,
       scroll_window_list_okay, scroll_window_list_cancel, scroll_window_list_action,
       list_okay, list_cancel, prefs_menu, sortby_menu, scroll_window_list_control;
  /* using a global to avoid a poll  */

#include "fallbacks.h"
Pixmap logo[8];
int current_pixmap = 8;  /* no point in updating display yet  */
Pixel temp_pixel;
int prefs, sortby;
index_struct left_index, right_index;
char left_name[MAXPATHLEN], right_name[MAXPATHLEN], 
       new_left_name[MAXPATHLEN], new_right_name[MAXPATHLEN], *another_settings=NULL;
head_path_struct *file_list_head = NULL;
uidname *uidlist, *grplist;
int uidlength, grplength;
int side=LEFT, choice;
XtAppContext app;
XmString gtemp_string;
/* done with globals */


main(argc, argv)
  int argc;
  char *argv[];
{
  Widget temp_widget, menu;
  XmString file_name, prefs_name, sort_name, help_name, load_s_name, 
           save_d_name, save_name, quit_name, prompt_name, hot1, 
           hot2, hot3, hot4, hot5,
           prompt_quit_name, full_name, dir_first_name, sort_name_name, 
           sort_inode_name, sort_size_name, sort_date_name, overwrite_name;
  char button_name[10];
  int x,y;
  pid_t pid;

/* initialize  */
  if (argc!=1)
    exit(1);

#ifndef DEBUG
  printf("Please wait, initializing xcp version : %s\n\n", VERSION_NO);
  if ((pid = fork()) < 0){
    perror("fork");
    _exit(1);
  }
  else if (pid != 0)
    _exit(0);   

  close(0);   /* kill stdin ..  no input  */
  setpgid(0,0);  /* make new process group leader.. maintain session  */
#endif
  read_settings();
  file_list_head=NULL;
  atexit(exit_exit);
  right_index.file = (file_list_struct **)malloc(sizeof(file_list_struct) * 10);
  left_index.file = (file_list_struct **)malloc(sizeof(file_list_struct) * 10);
  left_index.total = 10;
  right_index.total = 10;

/*  Main form  */
  toplevel = XtVaAppInitialize (&app, "Xcp", NULL, 0, &argc, argv, fallbacks, NULL);
  mainform = XtVaCreateManagedWidget("form", xmFormWidgetClass, toplevel, NULL);

/*  Menu bar creation  */
  file_name = XmStringCreate ("File","menu");
  prefs_name = XmStringCreate ("Prefs","menu");
  sort_name = XmStringCreate ("Sort by","menu");
  help_name = XmStringCreate ("Help","menu");

  menubar = XmVaCreateSimpleMenuBar(mainform, "menubar",
				    XmNtopAttachment, XmATTACH_FORM,
				    XmNleftAttachment, XmATTACH_FORM,
				    XmNrightAttachment, XmATTACH_FORM,
				    XmVaCASCADEBUTTON, file_name, 'F',
				    XmVaCASCADEBUTTON, prefs_name, 'P',
				    XmVaCASCADEBUTTON, sort_name, 'S',
				    XmVaCASCADEBUTTON, help_name, 'H',
				    NULL);
  XmStringFree(file_name);
  XmStringFree(prefs_name);
  XmStringFree(sort_name);      /* will free help later... need it  */
/*  Make File Menu - callback = file_cb */
  load_s_name = XmStringCreate("Load Settings ...", "menu");
  save_d_name = XmStringCreate("Save Default", "menu");
  save_name = XmStringCreate("Save As...", "menu");
  quit_name = XmStringCreate("Quit", "menu");
  hot1= XmStringCreate("CTRL+l", "menu");
  hot2= XmStringCreate("CTRL+s", "menu");
  hot3= XmStringCreate("CTRL+q", "menu");
  XmVaCreateSimplePulldownMenu(menubar, "file_manu", 0, file_cb,
			       XmVaPUSHBUTTON, load_s_name, 'L', "Ctrl<Key>l", hot1,
			       XmVaPUSHBUTTON, save_d_name, NULL, NULL, NULL,
			       XmVaPUSHBUTTON, save_name, 'S', "Ctrl<Key>s", hot2,
			       XmVaSEPARATOR,
			       XmVaPUSHBUTTON, quit_name, 'Q', "Ctrl<Key>q", hot3,
			       NULL);
  XmStringFree(load_s_name);
  XmStringFree(save_name);
  XmStringFree(save_d_name);
  XmStringFree(quit_name);
  XmStringFree(hot1);
  XmStringFree(hot2);
  XmStringFree(hot3);

/* Make Prefs Menu  -  calback = prefs_cb  */
  prompt_name = XmStringCreate("prompt before rm","menu");
  prompt_quit_name = XmStringCreate ("prompt before quit","menu");
  full_name = XmStringCreate("full info","menu");
  dir_first_name = XmStringCreate("directories first","menu");
  overwrite_name = XmStringCreate("overwrite files", "menu");
  hot1=XmStringCreate("Meta-r","menu");
  hot2=XmStringCreate("Meta-q","menu");
  hot3=XmStringCreate("Meta-f","menu");
  hot4=XmStringCreate("Meta-d","menu");
  hot5=XmStringCreate("Meta-o","menu");
  prefs_menu=XmVaCreateSimplePulldownMenu(menubar, "prefs_menu", 1, prefs_cb,
               XmVaCHECKBUTTON, prompt_name, 'r', "Meta<Key>r", hot1,
               XmVaCHECKBUTTON, prompt_quit_name, 'q', "Meta<Key>q", hot2,
               XmVaCHECKBUTTON, full_name, 'f', "Meta<Key>f", hot3,
               XmVaCHECKBUTTON, dir_first_name, 'd', "Meta<Key>f", hot4,
	       XmVaCHECKBUTTON, overwrite_name, 'o', "Meta<Key>o", hot5,
               NULL);
  XmStringFree(prompt_name);
  XmStringFree(prompt_quit_name);
  XmStringFree(full_name);
  XmStringFree(dir_first_name);
  XmStringFree(overwrite_name);
  XmStringFree(hot1);
  XmStringFree(hot2);
  XmStringFree(hot3);
  XmStringFree(hot4);
  XmStringFree(hot5);
/*     YET more code that is hard to modify later....
*        y=1   =  PROMPT  
*        y=2   -  PROMPT_QUIT
*        y=4   -  FULLNAME
*        y=8   -  DIR_FIRST
*	y=16  -  OVERWRITE
*/
  y=1;  
  strcpy(button_name,"button_");
  button_name[8]='\0';
  for (x=0;x<=4;x++){
    button_name[7]=(char)(48+x);
    if (prefs&y)
      if (temp_widget = XtNameToWidget (prefs_menu, button_name))
	XtVaSetValues(temp_widget, XmNset, True, NULL);
    y<<=1;
  }

/* Make Sort Menu - callback = sort_cb  */
  sort_name_name = XmStringCreate("name","menu");
  sort_inode_name = XmStringCreate("inode","menu");
  sort_size_name = XmStringCreate("size","menu");
  sort_date_name = XmStringCreate("date","menu");
  sortby_menu= XmVaCreateSimplePulldownMenu(menubar, "sort_menu", 2, sort_cb,
                XmVaRADIOBUTTON, sort_name_name, 'n', NULL, NULL,
                XmVaRADIOBUTTON, sort_inode_name, 'i', NULL, NULL,
                XmVaRADIOBUTTON, sort_size_name, 's' ,NULL, NULL,
                XmVaRADIOBUTTON, sort_date_name, 'a', NULL, NULL,
                XmNradioBehavior, True,           /*  only one may be on   */
                XmNradioAlwaysOne, True, NULL);
  XmStringFree(sort_name_name);
  XmStringFree(sort_inode_name);
  XmStringFree(sort_size_name);
  XmStringFree(sort_date_name);
  strcpy(button_name, "button_");
  button_name[7]=(char)(48+sortby);   /* bad way..  need button_0, button_1 etc.. */
  button_name[8]='\0';
  if (temp_widget = XtNameToWidget(sortby_menu, button_name))
    XtVaSetValues(temp_widget, XmNset, True, NULL);
/*  make help menu  -  callback help_cb */
  /* define help as the "help" menu option */
  if (temp_widget = XtNameToWidget(menubar, "button_3"))
    XtVaSetValues (menubar, XmNmenuHelpWidget, temp_widget, NULL);
  XmVaCreateSimplePulldownMenu(menubar, "help_menu", 3, help_cb,
			       XmVaPUSHBUTTON, help_name, 'H', NULL, NULL, NULL);
  XmStringFree(help_name);
/* manage menu */
  XtManageChild(menubar);
/* manage mainform */

  setup_window();
  XtManageChild(mainform);

/*  DONE!!!!  */
  XtRealizeWidget(toplevel);
  current_pixmap = 0;
  inform("Xcp version ");
  inform(VERSION_NO);
  inform("\nwelcome to xcp\n");
  XtAppMainLoop(app);
}


void setup_window()
{
  extern Widget temp_widget;
  int row,col,x;
  XmString button_name;
  char name[20];
  Arg args[10];

/*   set up the bottom row of widgets - rowcolumns   */
  XtSetArg(args[0], XmNleftAttachment, XmATTACH_FORM);
  XtSetArg(args[1], XmNrightAttachment, XmATTACH_FORM);
  XtSetArg(args[2], XmNbottomAttachment, XmATTACH_FORM);
  XtSetArg(args[3], XmNeditable, False);
  XtSetArg(args[4], XmNtopAttachment, XmATTACH_POSITION);
  XtSetArg(args[5], XmNtopPosition, 85);
  XtSetArg(args[6], XmNscrollBarDisplayPolicy, XmSTATIC);
  XtSetArg(args[7], XmNautoShowCursorPosition, True);
  XtSetArg(args[8], XmNscrollHorizontal, False);
  XtSetArg(args[9], XmNeditMode, XmMULTI_LINE_EDIT);
  inform_widget = XmCreateScrolledText(mainform, "inform", args, 10);
  XtManageChild(inform_widget);
#ifdef ALPHA
  bottomrowcol= XtVaCreateManagedWidget("bottom-commands",
                      xmFormWidgetClass, mainform,
		      XmNfractionBase, 6,
                      XmNspacing, 2,
		      XmNbottomAttachment, XmATTACH_WIDGET,
		      XmNbottomWidget, inform_widget,		
                      XmNleftAttachment, XmATTACH_FORM,
                      XmNrightAttachment, XmATTACH_FORM,
					XmNheight, 0,
					XmNmaxHeight, 1,
					XmNminHeight,0,
                      NULL);
  for (row=0;row<3;row++)
    for (col=0;col<6;col++){
      getname(name,row,col);
      button_name = XmStringCreate(name,"buttons");
      command[(col + 6*row)]=XtVaCreateManagedWidget
	                          (name,
				   xmPushButtonGadgetClass, bottomrowcol,
				   XmNlabelString, button_name,
				   XmNtopAttachment, XmATTACH_POSITION,
				   XmNtopPosition, 2*row,
				   XmNleftAttachment, XmATTACH_POSITION,
				   XmNleftPosition, col,
				   XmNbottomAttachment, XmATTACH_POSITION,
				   XmNbottomPosition, 2*(row+1),
				   XmNrightAttachment, XmATTACH_POSITION,
				   XmNrightPosition, col+1,
				   NULL);
      XmStringFree(button_name);
      XtAddCallback(command[(col +6*row)], 
		    XmNactivateCallback, button_exec, NULL);
    }
  
#endif
/*   set up the upperform/subs... (will contain more forms inside)   */
  upperform= XtVaCreateManagedWidget ("upperform", xmFormWidgetClass, mainform,
				      XmNtopAttachment, XmATTACH_WIDGET,
				      XmNtopWidget, menubar,
                                      XmNleftAttachment, XmATTACH_FORM,
                                      XmNrightAttachment, XmATTACH_FORM,
				      XmNbottomAttachment, XmATTACH_WIDGET,
                                      XmNbottomWidget, 
#ifndef ALPHA
				      inform_widget,
#else
				      bottomrowcol,
#endif
                                      NULL);		      
  centerform = XtVaCreateManagedWidget ("centerform", xmFormWidgetClass, 
				       upperform, 
				       XmNtopAttachment, XmATTACH_FORM,
				       XmNbottomAttachment, XmATTACH_FORM,
				       XmNleftAttachment, XmATTACH_POSITION,
				       XmNleftPosition, 45,
				       XmNrightAttachment, XmATTACH_POSITION,
				       XmNrightPosition, 55,
				       XmNwidth,100,
				       XmNheight, 550,
				       XmNspacing, 4,
				       NULL);

  rightform= XtVaCreateManagedWidget ("rightform", xmFormWidgetClass, upperform,
				      XmNtopAttachment, XmATTACH_FORM,
				      XmNbottomAttachment, XmATTACH_FORM,
				      XmNrightAttachment, XmATTACH_FORM,
				      XmNleftAttachment, XmATTACH_WIDGET,
				      XmNleftWidget, centerform,
				      NULL);

  leftform= XtVaCreateManagedWidget ("leftform", xmFormWidgetClass, upperform,
				     XmNtopAttachment, XmATTACH_FORM,
				     XmNbottomAttachment, XmATTACH_FORM,
				     XmNleftAttachment, XmATTACH_FORM,
				     XmNrightAttachment, XmATTACH_WIDGET,
				     XmNrightWidget, centerform,
				     NULL);

/*  create the buttons in the centerform   */
/*  exit button with a frame  callback = quit_cb */
  button_name=XmStringCreate("EXIT","buttons");
  exit_frame= XtVaCreateManagedWidget("exit-frame", xmFrameWidgetClass,
				      centerform,
				      XmNshadowType, XmSHADOW_ETCHED_IN,
				      XmNtopAttachment, XmATTACH_FORM,
				      XmNrightAttachment, XmATTACH_FORM,
				      XmNleftAttachment, XmATTACH_FORM,
				      XmNbottomAttachment, XmATTACH_POSITION,
				      XmNbottomPosition, 11,
				      NULL);

  but_exit = XtVaCreateManagedWidget("exit", xmPushButtonGadgetClass, 
				     exit_frame,
				     XmNlabelString, button_name,
				     NULL);
  XmStringFree(button_name);
  XtAddCallback(but_exit, XmNactivateCallback, quit_cb, NULL);
/* copy >  button  callback = copy_cp  */
  button_name=XmStringCreate("Copy","buttons");
  but_copy = XtVaCreateManagedWidget("copy", xmPushButtonGadgetClass,
				     centerform,
				     XmNlabelString, button_name,
				     XmNrightAttachment, XmATTACH_FORM,
				     XmNleftAttachment, XmATTACH_FORM,
				     XmNtopAttachment, XmATTACH_WIDGET,
				     XmNtopWidget, exit_frame,
				     XmNbottomAttachment, XmATTACH_POSITION,
				     XmNbottomPosition, 19,
				     NULL);
  XmStringFree(button_name);
  XtAddCallback(but_copy, XmNactivateCallback, copy_cb, NULL);
/* move >  button  callback = move_cb  */
  button_name=XmStringCreate("Move","buttons");
  but_move = XtVaCreateManagedWidget("move", xmPushButtonGadgetClass,
				     centerform,
				     XmNlabelString, button_name,
				     XmNrightAttachment, XmATTACH_FORM,
				     XmNleftAttachment, XmATTACH_FORM,
				     XmNtopAttachment, XmATTACH_WIDGET,
				     XmNtopWidget, but_copy,
				     XmNbottomAttachment, XmATTACH_POSITION,
				     XmNbottomPosition, 26,
				     NULL);
  XmStringFree(button_name);
  XtAddCallback(but_move, XmNactivateCallback, move_cb, NULL);
/* copy as >   button   callback = copyas_cb  */
  button_name=XmStringCreate("Copy As","buttons");
  but_copyas = XtVaCreateManagedWidget("copyas", xmPushButtonGadgetClass,
				     centerform,
				     XmNlabelString, button_name,
				     XmNrightAttachment, XmATTACH_FORM,
				     XmNleftAttachment, XmATTACH_FORM,
				     XmNtopAttachment, XmATTACH_WIDGET,
				     XmNtopWidget, but_move,
				     XmNbottomAttachment, XmATTACH_POSITION,
				     XmNbottomPosition, 33,
				     NULL);
  XmStringFree(button_name);
  XtAddCallback(but_copyas, XmNactivateCallback, copyas_cb, NULL);
/* move As >  button  callback = moveas_cb  */
  button_name=XmStringCreate("Move As","buttons");
  but_moveas = XtVaCreateManagedWidget("moveas", xmPushButtonGadgetClass,
				     centerform,
				     XmNlabelString, button_name,
				     XmNrightAttachment, XmATTACH_FORM,
				     XmNleftAttachment, XmATTACH_FORM,
				     XmNtopAttachment, XmATTACH_WIDGET,
				     XmNtopWidget, but_copyas,
				     XmNbottomAttachment, XmATTACH_POSITION,
				     XmNbottomPosition, 40,
				     NULL);
  XmStringFree(button_name);
  XtAddCallback(but_moveas, XmNactivateCallback, moveas_cb, NULL);

/*  < Link   button  callback = link_cb  */
  button_name=XmStringCreate("Link","buttons");
  but_link = XtVaCreateManagedWidget("link", xmPushButtonGadgetClass,
				     centerform,
				     XmNlabelString, button_name,
				     XmNrightAttachment, XmATTACH_FORM,
				     XmNleftAttachment, XmATTACH_FORM,
				     XmNtopAttachment, XmATTACH_WIDGET,
				     XmNtopWidget, but_moveas,
				     XmNbottomAttachment, XmATTACH_POSITION,
				     XmNbottomPosition, 47,
				     NULL);
  XmStringFree(button_name);
  XtAddCallback(but_link, XmNactivateCallback, link_cb, NULL);

/* < Link As  button  callback = linkas_cb  */
  button_name=XmStringCreate("Link As","buttons");
  but_linkas = XtVaCreateManagedWidget("linkas", xmPushButtonGadgetClass,
				     centerform,
				     XmNlabelString, button_name,
				     XmNrightAttachment, XmATTACH_FORM,
				     XmNleftAttachment, XmATTACH_FORM,
				     XmNtopAttachment, XmATTACH_WIDGET,
				     XmNtopWidget, but_link,
				     XmNbottomAttachment, XmATTACH_POSITION,
				     XmNbottomPosition, 54,
				     NULL);
  XmStringFree(button_name);
  XtAddCallback(but_linkas, XmNactivateCallback, linkas_cb, NULL);
  button_name=XmStringCreate("Delete","bbuttons");
  but_rm = XtVaCreateManagedWidget("rm", xmPushButtonGadgetClass,
				     centerform,
				     XmNlabelString, button_name,
				     XmNrightAttachment, XmATTACH_FORM,
				     XmNleftAttachment, XmATTACH_FORM,
				     XmNtopAttachment, XmATTACH_WIDGET,
				     XmNtopWidget, but_linkas,
				     XmNbottomAttachment, XmATTACH_POSITION,
				     XmNbottomPosition, 61,
				     NULL);
  XmStringFree(button_name);
  XtAddCallback(but_rm, XmNactivateCallback, rm_cb, NULL);
  but_arrow = XtVaCreateManagedWidget("arrow", xmArrowButtonWidgetClass,
				      centerform,
				      XmNarrowDirection, XmARROW_RIGHT,
				      XmNrightAttachment, XmATTACH_FORM,
				      XmNleftAttachment, XmATTACH_FORM,
				      XmNtopAttachment, XmATTACH_WIDGET,
				      XmNtopWidget, but_rm,
				      XmNbottomAttachment, XmATTACH_POSITION,
				      XmNbottomPosition, 70,
				      NULL);
      /*  no callbacks.. let people have fun!!!   */
/* yuck i'm lazy.....   this can be so optimized!!!  cut paste!!  */

  XmInstallImage(&logo_image1, "anim1");
  XmInstallImage(&logo_image2, "anim2");
  XmInstallImage(&logo_image3, "anim3");
  XmInstallImage(&logo_image4, "anim4");
  XmInstallImage(&logo_image5, "anim5");
  XmInstallImage(&logo_image6, "anim6");
  XmInstallImage(&logo_image7, "anim7");
  XmInstallImage(&logo_image8, "anim8");
  XtVaGetValues(centerform,
		XmNbackground, &temp_pixel,
		NULL);
  for (x=1; x <= 8; x++){
    sprintf(name, "anim%d", x);
    logo[x-1] = XmGetPixmap (XtScreen(toplevel), name, 
			   BlackPixelOfScreen(XtScreen(toplevel)),
			   temp_pixel);
  }
/*
  XmUninstallImage(&logo_image1);
  XmUninstallImage(&logo_image2);
  XmUninstallImage(&logo_image3);
  XmUninstallImage(&logo_image4);
  XmUninstallImage(&logo_image5);
  XmUninstallImage(&logo_image6);
  XmUninstallImage(&logo_image7);
  XmUninstallImage(&logo_image8);
*/
  label_name = XtVaCreateManagedWidget("name", xmLabelWidgetClass,
				       centerform,
				       XmNrightAttachment, XmATTACH_FORM,
				       XmNleftAttachment, XmATTACH_FORM,
				       XmNtopAttachment, XmATTACH_WIDGET,
				       XmNtopWidget, but_arrow,
				       XmNbottomAttachment, XmATTACH_POSITION,
				       XmNbottomPosition, 90,
   				       XmNlabelType, XmPIXMAP,
				       XmNlabelPixmap, logo[0],
				       XmNrecomputeSize, False,
				       XmNalignment, XmALIGNMENT_CENTER,
				       NULL);

  button_name = XmStringCreate("Sync", "buttons");
  but_sync = XtVaCreateManagedWidget("rm", xmPushButtonGadgetClass,
				     centerform,
				     XmNlabelString, button_name,
				     XmNrightAttachment, XmATTACH_FORM,
				     XmNleftAttachment, XmATTACH_FORM,
				     XmNbottomAttachment, XmATTACH_FORM,
				     XmNtopAttachment, XmATTACH_POSITION,
				     XmNtopPosition, 90,
/*
				     XmNtopAttachment, XmATTACH_WIDGET,
				     XmNtopWidget, label_name,
*/
				     NULL);
  XmStringFree(button_name);
  XtAddCallback(but_sync, XmNactivateCallback, sync_cb, NULL);
 
/*  done with buttons --  now do left+right directory lists  */
/* first, the pathnames   */
  left_path = XtVaCreateManagedWidget("lefttext", xmTextFieldWidgetClass, leftform, 
				    XmNrightAttachment, XmATTACH_FORM,
				    XmNleftAttachment, XmATTACH_FORM,
				    XmNtopAttachment, XmATTACH_FORM,
				    XmNbottomAttachment, XmATTACH_POSITION,
				    XmNbottomPosition, 5,
				    XmNvalue, left_name,
				    XmNmaxLength, MAXPATHLEN-1,
				    XmNmarginHeight, 1,
				    NULL);
  XtAddCallback(left_path, XmNactivateCallback, make_new, NULL);
  right_path = XtVaCreateManagedWidget("righttext", xmTextFieldWidgetClass, rightform, 
				    XmNrightAttachment, XmATTACH_FORM,
				    XmNleftAttachment, XmATTACH_FORM,
				    XmNtopAttachment, XmATTACH_FORM,
				    XmNbottomAttachment, XmATTACH_POSITION,
				    XmNbottomPosition, 5,
				    XmNvalue, right_name,
				    XmNmaxLength, MAXPATHLEN-1,
				    XmNmarginHeight, 1,
				    NULL);
  XtAddCallback(right_path, XmNactivateCallback, make_new, NULL);

/*  now the directory menu   */
 /* setup the forms for the menu */
  left_menu_form = XtVaCreateManagedWidget("left_menu", xmFormWidgetClass,
					      leftform,
					      XmNrightAttachment, XmATTACH_FORM,
					      XmNleftAttachment, XmATTACH_FORM,
					      XmNtopAttachment, XmATTACH_WIDGET,
					      XmNtopWidget, left_path,
					      XmNbottomAttachment, XmATTACH_POSITION,
					      XmNbottomPosition, 10,
					      XmNfractionBase, 4,
					      NULL);
  right_menu_form = XtVaCreateManagedWidget("right_menu", xmFormWidgetClass,
					       rightform,
					       XmNrightAttachment, XmATTACH_FORM,
					       XmNleftAttachment, XmATTACH_FORM,
					       XmNtopAttachment, XmATTACH_WIDGET,
					       XmNtopWidget, right_path,
					       XmNbottomAttachment, XmATTACH_POSITION,
					       XmNbottomPosition, 10,
					       XmNfractionBase, 4,
					       NULL);
 /* make the buttons */
  for (x=0;x<=3;x++){
    button_name = XmStringCreate(top_button_list[x].name,"buttons");
    top_button[x] = XtVaCreateManagedWidget(top_button_list[x].name,
       xmPushButtonGadgetClass, left_menu_form,
       XmNlabelString, button_name,
       XmNtopAttachment, XmATTACH_FORM,
       XmNleftAttachment, XmATTACH_POSITION,
       XmNleftPosition, x,
       XmNbottomAttachment, XmATTACH_FORM,
       XmNrightAttachment, XmATTACH_POSITION,
       XmNrightPosition, x+1,
       NULL);
    XmStringFree(button_name);
    XtAddCallback(top_button[x], 
		  XmNactivateCallback, left_button_exec, NULL);
   }
  for (x=4;x<=7;x++){
    button_name = XmStringCreate(top_button_list[x].name,"buttons");
    top_button[x] = XtVaCreateManagedWidget(top_button_list[x].name,
       xmPushButtonGadgetClass, right_menu_form,
       XmNlabelString, button_name,
       XmNtopAttachment, XmATTACH_FORM,
       XmNleftAttachment, XmATTACH_POSITION,
       XmNleftPosition, (x-4),
       XmNbottomAttachment, XmATTACH_FORM,
       XmNrightAttachment, XmATTACH_POSITION,
       XmNrightPosition, (x-3),
       NULL);
    XmStringFree(button_name);
    XtAddCallback(top_button[x], 
		  XmNactivateCallback, right_button_exec, NULL);
  }

/*  and now for the list widgets to hold the filenames   */
  XtSetArg(args[0], XmNtopAttachment, XmATTACH_WIDGET);
  XtSetArg(args[1], XmNtopWidget, left_menu_form);
  XtSetArg(args[2], XmNleftAttachment, XmATTACH_FORM);
  XtSetArg(args[3], XmNrightAttachment, XmATTACH_FORM);
  XtSetArg(args[4], XmNbottomAttachment, XmATTACH_FORM);
  XtSetArg(args[5], XmNlistSizePolicy, XmCONSTANT);
  XtSetArg(args[6], XmNscrollBarDisplayPolicy, XmSTATIC);
  XtSetArg(args[7], XmNselectionPolicy, XmEXTENDED_SELECT);
  left_file_list = XmCreateScrolledList(leftform, "left_file",
					args, 8);
  XtAddCallback(left_file_list, XmNdefaultActionCallback, double_click_list, NULL);
  XtManageChild(left_file_list);
  XtSetArg(args[1], XmNtopWidget, right_menu_form);
  XtSetArg(args[8], XmNscrollBarPlacement, XmBOTTOM_LEFT);
  right_file_list = XmCreateScrolledList(rightform, "right_file", args, 9);
  XtAddCallback(right_file_list, XmNdefaultActionCallback, double_click_list, NULL);
  XtAddCallback(right_file_list, XmNextendedSelectionCallback, flip_side, NULL);
  XtManageChild(right_file_list);
/*  done with interface  */
/*  build filenames  */
/* cheap way to get full path from name */
  if (chdir(new_left_name)) {
    perror("chdir:");
    chdir(left_name);
    strcpy(new_left_name, left_name);
  }
  else
    build_list(left_file_list, new_left_name);
  if (chdir(new_right_name)) {
    perror("chdir:");
    chdir(right_name);
    strcpy(new_right_name, right_name);
  }
  else
    build_list(right_file_list, new_right_name); 
}

void build_list(w, path)
/* does no checking to see if path is already the one being used... */
Widget w;    /*   where to build list   left/right   */
char *path;  /*   pathname(expanded) to get directory info for */
{
  head_path_struct *wanted_file_list;
  XmString *items;
  file_list_struct *traverse;
  int current_side;
  Boolean update;
  int val_ret, max_ret, size_ret;
  Widget scrolled_list_widget;

  if (strcmp(XtName(w), "left_file")){    /* right_file  */
    current_side = RIGHT;
    if (!strcmp(path, right_name))
      update=True;
    else
      update=False;
  }
  else{
    current_side = LEFT;
    if (!strcmp(path, left_name))
      update=True;
    else
      update=False;
  }
  if (!(wanted_file_list = add_to_list(path))){
    if (current_side == RIGHT)
      if (strcmp(right_name, new_right_name)){
	char message[MAXPATHLEN + 200];
	sprintf(message, "I am trying to access %s, which doesn't seem to exist on your system\n", path);
	strcpy(new_right_name, right_name);
	XmTextFieldSetString(right_path, right_name); 
	inform(message);
      }
      else {
	perror("loop error:");
	exit(0);
      }
    else
      if (strcmp(left_name, new_left_name)){
	char message[MAXPATHLEN + 200];
	sprintf(message, "I am trying to access %s, which doesn't seem to exist on your system\n", path);
	strcpy(new_left_name, left_name);
	XmTextFieldSetString(left_path, left_name);
	inform(message);
      }
      else {
	perror("loop error:");
	exit(0);
      }
    return;
  }
  if (update){
    scrolled_list_widget = (current_side == LEFT) ? left_file_list : right_file_list;
    XtVaGetValues(scrolled_list_widget,
		  XmNtopItemPosition, &val_ret, NULL);
  }
  XmListDeleteAllItems(w);   /*  clean up the window before adding everything from scratch  */
  traverse=wanted_file_list->first_file;
  items=(XmString *)malloc((wanted_file_list->total_files) * (sizeof(XmString)));
  if (wanted_file_list->total_files){
    make_sorted_list(items, traverse, wanted_file_list->total_files, current_side);
    XmListAddItems(w, items, wanted_file_list->total_files, 0);
  }
  if (current_side == RIGHT){  /* right_file  */
    strcpy(right_name, path);
    strcpy(new_right_name, path);
    XmTextFieldSetString(right_path, wanted_file_list->pathname);
  }
  else{
    strcpy(left_name, path);
    strcpy(new_left_name, path);
    XmTextFieldSetString(left_path, wanted_file_list->pathname);
  }
  if (update){
    XtVaGetValues(scrolled_list_widget,
		  XmNvisibleItemCount, &size_ret,
		  XmNitemCount, &max_ret,
		  NULL);
    if (val_ret > (max_ret - size_ret))
      XmListSetBottomPos(scrolled_list_widget, max_ret);
    else 
      XmListSetPos(scrolled_list_widget, val_ret);
  }
  done_work();
}

void make_new(w)
Widget w;
{
  char *desired;

  desired = (char *)XmTextFieldGetString(w);
  if (strcmp("lefttext", XtName(w))){     /*   right file list inputted  */
    strcpy(new_right_name, desired);
    XtFree(desired);
    build_list(right_file_list, new_right_name);
    return;
  }
  else{
    strcpy(new_left_name, desired);
    XtFree(desired);
    build_list(left_file_list, new_left_name);
    return;
  }
}   


void quit_cb(w, client_data, cbs)
/*   user has pushed the EXIT button  */
Widget w;
XtPointer client_data;
XmPushButtonCallbackStruct *cbs;
{ 
  if (!(prefs&PROMPT_QUIT))
    exit_well(0,0,0);
  else
    if (really_quit())
      exit_well(0,0,0);
  return;
}

void copy_cb(w, client_data, cbs)
/* user has pushed the copy button */
Widget w;
XtPointer client_data;
XmPushButtonCallbackStruct *cbs;
{ 
  int *pos_list, pos_count, x, copied;
  index_struct *index_real;
  Widget selected_list_widget, other_widget;
  char from_path[MAXPATHLEN], to_path[MAXPATHLEN], buf[MAXPATHLEN];

  if (!strcmp(left_name, right_name)){
    inform("You can't copy from and to the same directory using the same name\n");
    return;
  }
  if (side==LEFT){
    strcpy(from_path, left_name);
    strcpy(to_path, right_name);
    selected_list_widget = left_file_list;
    other_widget = right_file_list;
    index_real = &left_index;
  }
  else{
    strcpy(from_path, right_name);
    strcpy(to_path, left_name);
    selected_list_widget = right_file_list;
    other_widget = left_file_list;
    index_real = &right_index; }
  XmListGetSelectedPos(selected_list_widget, &pos_list, &pos_count);
  if (pos_count){
    for (x=0; x<pos_count; x++){
      strcpy(buf,to_path);
      if (buf[strlen(buf)-1] != '/')
	strcat(buf, "/");
      strcat(buf,index_real->file[pos_list[x]-1]->filename);
      copied=False;
      if (index_real->file[pos_list[x]-1]->link_info & IS_DIRECTORY)
	copied = copy_dir(index_real->file[pos_list[x]-1]->fullname, buf);
      else
	copied = (copy_file(index_real->file[pos_list[x]-1]->fullname, buf)
	                              ? COMPLETE : NONE);
      working();
      if (copied){
	if (copied == COMPLETE)
	  XmListDeselectPos(selected_list_widget, pos_list[x]);
      }
    }
    build_list (other_widget, to_path);
  }
  done_work();
}

void move_cb(w, client_data, cbs)
/* user has pushed the move button */
Widget w;
XtPointer client_data;
XmPushButtonCallbackStruct *cbs;
{
  int *pos_list, pos_count, x, moved;
  index_struct *index_real;
  Widget selected_list_widget, other_widget;
  char from_path[MAXPATHLEN], to_path[MAXPATHLEN], buf[MAXPATHLEN];
  XmString temp_string;

  if (!strcmp(left_name, right_name)){
    inform("You can't move from and to the same directory using the same name\n");
    return;
  }
  if (side==LEFT){
    strcpy(from_path, left_name);
    strcpy(to_path, right_name);
    selected_list_widget = left_file_list;
    other_widget = right_file_list;
    index_real = &left_index;
  }
  else{
    strcpy(from_path, right_name);
    strcpy(to_path, left_name);
    selected_list_widget = right_file_list;
    other_widget = left_file_list;
    index_real = &right_index; }
  XmListGetSelectedPos(selected_list_widget, &pos_list, &pos_count);
  if (pos_count){
    for (x=pos_count-1; x>=0; x--){
      strcpy(buf,to_path);
      if (buf[strlen(buf)-1] != '/')
	strcat(buf, "/");
      strcat(buf,index_real->file[pos_list[x]-1]->filename);
      moved=False;
      temp_string = XmStringCopy((prefs & FULLNAME) ? 
		      index_real->file[pos_list[x]-1]->fullname_str : 
		      index_real->file[pos_list[x]-1]->name_str);
      if (index_real->file[pos_list[x]-1]->link_info & IS_DIRECTORY)
	moved = move_dir(index_real->file[pos_list[x]-1]->fullname, buf);
      else 
	moved = (move_file(index_real->file[pos_list[x]-1]->fullname, buf)
		 ? COMPLETE : NONE);
      working();
      if (moved){
	XmListAddItem(other_widget, temp_string, 0);
	XmStringFree(temp_string);
	if (moved == COMPLETE)
	  XmListDeletePos(selected_list_widget, pos_list[x]);
      }
    }
    build_list (selected_list_widget, from_path);
    build_list (other_widget, to_path);
  }
  done_work();
}


void copyas_cb(w, client_data, cbs)
/* user has pushed the copy as button */
Widget w;
XtPointer client_data;
XmPushButtonCallbackStruct *cbs;
{
  int *pos_list, pos_count, x, copied;
  index_struct *index_real;
  Widget selected_list_widget, other_widget;
  char from_path[MAXPATHLEN], to_path[MAXPATHLEN], buf[MAXPATHLEN];
  copy_files_struct requester;

  check_for_scroll_widget();
  if (side==LEFT){
    strcpy(from_path, left_name);
    strcpy(to_path, right_name);
    selected_list_widget = left_file_list;
    other_widget = right_file_list;
    index_real = &left_index;
  }
  else{
    strcpy(from_path, right_name);
    strcpy(to_path, left_name);
    selected_list_widget = right_file_list;
    other_widget = left_file_list;
    index_real = &right_index;
  }
  strcpy(requester.source_path, from_path);
  strcpy(requester.dest_path, to_path);
  strcpy(requester.string_request, "Please select the new names for the files to be copied");
  strcpy(requester.button_okay, "Okay");
  strcpy(requester.button_cancel, "Abort");
  XmListGetSelectedPos(selected_list_widget, &pos_list, &pos_count);
  if (pos_count){
    if ((requester.files = malloc(sizeof(copy_file_struct) * pos_count)) == NULL){
      perror("malloc");
      return;
    }
    for (x=0; x<pos_count; x++)
      strcpy(requester.files[x].source, index_real->file[pos_list[x]-1]->filename);
    if (get_new_names(&requester, pos_count))
      for (x=0; x<pos_count; x++){
	if(requester.files[x].dest[0]!='\0'){
	  copied=False;
	  sprintf(buf, "%s/%s", to_path, requester.files[x].dest);
	  if (index_real->file[pos_list[x]-1]->link_info & IS_DIRECTORY)
	    copied = copy_dir(index_real->file[pos_list[x]-1]->fullname, buf);
	  else
	    copied = (copy_file(index_real->file[pos_list[x]-1]->fullname, buf)
		      ? COMPLETE : NONE);
	  working();
	  if (copied){
	    XmListAddItem(other_widget, (prefs & FULLNAME) ? 
			  index_real->file[pos_list[x]-1]->fullname_str : 
			  index_real->file[pos_list[x]-1]->name_str, 0);
	    if (copied==COMPLETE)
	      XmListDeselectPos(selected_list_widget, pos_list[x]);
	  }
	}
	XtFree(requester.files[x].dest);
      }
    build_list (other_widget, to_path);
    done_work();
  }
}

void moveas_cb(w, client_data, cbs)
/* user has pushed the move as button */
Widget w;
XtPointer client_data;
XmPushButtonCallbackStruct *cbs;
{
  int *pos_list, pos_count, x, moved;
  index_struct *index_real;
  Widget selected_list_widget, other_widget;
  char from_path[MAXPATHLEN], to_path[MAXPATHLEN], buf[MAXPATHLEN];
  file_list_struct *item;
  copy_files_struct requester;

  if (!strcmp(left_name, right_name)){
    inform("You can't move from and to the same directory using the same name\n");
    return;
  }
  if (side==LEFT){
    strcpy(from_path, left_name);
    strcpy(to_path, right_name);
    selected_list_widget = left_file_list;
    other_widget = right_file_list;
    index_real = &left_index;
  }
  else{
    strcpy(from_path, right_name);
    strcpy(to_path, left_name);
    selected_list_widget = right_file_list;
    other_widget = left_file_list;
    index_real = &right_index; }
  XmListGetSelectedPos(selected_list_widget, &pos_list, &pos_count);
  if (pos_count){
    check_for_scroll_widget();
    strcpy(requester.source_path, from_path);
    strcpy(requester.dest_path, to_path);
    strcpy(requester.string_request, "Please select the new names for the files to be moved");
    strcpy(requester.button_okay, "Move");
    strcpy(requester.button_cancel, "Abort");
    XmListGetSelectedPos(selected_list_widget, &pos_list, &pos_count);
    if (pos_count){
      if ((requester.files = malloc(sizeof(copy_file_struct) * pos_count)) == NULL){
	perror("malloc");
	return;
      }
      for (x=0; x<pos_count; x++)
	strcpy(requester.files[x].source, index_real->file[pos_list[x]-1]->filename);
      if (get_new_names(&requester, pos_count))
	for (x=0; x<pos_count; x++){
	  if(requester.files[x].dest[0]!='\0'){
	    sprintf(buf, "%s/%s", to_path, requester.files[x].dest);
	    moved=False;
	  if (index_real->file[pos_list[x]-1]->link_info & IS_DIRECTORY)
	    moved = move_dir(index_real->file[pos_list[x]-1]->fullname, buf);
	  else
	    moved = (move_file(index_real->file[pos_list[x]-1]->fullname, buf)
		     ? COMPLETE : NONE);
	    working();
	    if (moved){
	      if (!(item = (file_list_struct *)malloc(sizeof(file_list_struct)))){
		perror("malloc");
		return;
	      }
	      XmListAddItem(other_widget, (prefs & FULLNAME) ? item->fullname_str : item->name_str, 0);
	      XtFree(requester.files[x].dest);
	      if (moved == COMPLETE)
		XmListDeletePos(selected_list_widget, pos_list[x]);
	    }
	  }
	  build_list (other_widget, to_path);
	  build_list (selected_list_widget, from_path);
	}
    } 
  }
  done_work();
}

void link_cb(w, client_data, cbs)
/* user has pushed the link button */
Widget w;
XtPointer client_data;
XmPushButtonCallbackStruct *cbs;
{
  int *pos_list, pos_count, x;
  index_struct *index_real;
  Widget selected_list_widget, other_widget;
  char from_path[MAXPATHLEN], to_path[MAXPATHLEN], buf[MAXPATHLEN];
  file_list_struct *item;
  struct stat temp_buf;

  if (!strcmp(left_name, right_name)){
    inform("You can't symlink from and to the same directory using the same name\n");
    return;
  }
  if (side==LEFT){
    strcpy(from_path, right_name);
    strcpy(to_path, left_name);
    selected_list_widget = left_file_list;
    other_widget = right_file_list;
    index_real = &left_index;
    }
  else{
    strcpy(from_path, left_name);
    strcpy(to_path, right_name);
    selected_list_widget = right_file_list;
    other_widget = left_file_list;
    index_real = &right_index;
    }
  XmListGetSelectedPos(selected_list_widget, &pos_list, &pos_count);
  if (pos_count){
    chdir(from_path);
    for (x=0; x<pos_count; x++){
      strcpy(buf,to_path);
      if (buf[strlen(buf)-1] != '/')
	strcat(buf, "/");
      strcat(buf,index_real->file[pos_list[x]-1]->filename);
      if (!(symlink(buf, index_real->file[pos_list[x]-1]->filename))){ 
	                          /* make file_list structure and fill it  */
	if (!(item = (file_list_struct *)malloc(sizeof(file_list_struct)))){
	  perror("malloc");
	  return;
	}
	working();
	item->next_file=NULL;
	strcpy(item->filename, index_real->file[pos_list[x]-1]->filename);
	item->fullname = (char *)malloc(sizeof(char) * (strlen(buf) +1));
	strcpy(item->fullname, buf);
	if (index_real->file[pos_list[x]-1]->link_info & IS_DIRECTORY)
	  item->link_info = IS_LINK | IS_DIRECTORY;
	else
	  item->link_info = IS_LINK | IS_FILE;
	lstat(index_real->file[pos_list[x]-1]->filename, &temp_buf);
	memcpy(&item->stats, &temp_buf, sizeof(struct stat));
	item->name_str = make_correct(item, 0);
	item->fullname_str = make_correct(item, 1);
	add_file_to_dir(from_path,item);
	XmListAddItem(other_widget, (prefs & FULLNAME) ? item->fullname_str : item->name_str, 0);
	XmListDeselectPos(selected_list_widget, pos_list[x]);
      }
    }
    build_list (other_widget, from_path);
  }
  done_work();
}

void linkas_cb(w, client_data, cbs)
/* user has pushed the link as button */
Widget w;
XtPointer client_data;
XmPushButtonCallbackStruct *cbs;
{
  int *pos_list, pos_count, x, y;
  index_struct *index_real;
  Widget selected_list_widget, other_widget;
  char from_path[MAXPATHLEN], to_path[MAXPATHLEN], buf[MAXPATHLEN];
  file_list_struct *item;
  struct stat temp_buf;
  copy_files_struct requester;

  if (side==LEFT){
    strcpy(from_path, right_name);
    strcpy(to_path, left_name);
    selected_list_widget = left_file_list;
    other_widget = right_file_list;
    index_real = &left_index;
    }
  else{
    strcpy(from_path, left_name);
    strcpy(to_path, right_name);
    selected_list_widget = right_file_list;
    other_widget = left_file_list;
    index_real = &right_index;
    }
  check_for_scroll_widget();
  XmListGetSelectedPos(selected_list_widget, &pos_list, &pos_count);
  strcpy(requester.source_path, from_path);
  strcpy(requester.dest_path, to_path);
  strcpy(requester.string_request, "Please select the names for the links");
  strcpy(requester.button_okay, "Link");
  strcpy(requester.button_cancel, "Abort");
  XmListGetSelectedPos(selected_list_widget, &pos_list, &pos_count);
  if (pos_count){
    if ((requester.files = malloc(sizeof(copy_file_struct) * pos_count)) == NULL){
      perror("malloc");
      return;
    }
    for (x=0; x<pos_count; x++)
      strcpy(requester.files[x].source, index_real->file[pos_list[x]-1]->filename);
    if (get_new_names(&requester, pos_count)){
      chdir(from_path);
      for (x=0; x<pos_count; x++){
	strcpy(buf,to_path);
	if (buf[strlen(buf)-1] != '/')
	  strcat(buf, "/");
	strcat(buf,index_real->file[pos_list[x]-1]->filename);
	if (!(y = symlink(buf, requester.files[x].dest))){ 
	  /* make file_list structure and fill it  */
	  if (!(item = (file_list_struct *)malloc(sizeof(file_list_struct)))){
	    perror("malloc");
	    return;
	  }
	  working();
	  item->next_file=NULL;
	  strcpy(item->filename, requester.files[x].dest);
	  item->fullname = (char *)malloc(sizeof(char) * (strlen(buf) +1));
	  strcpy(item->fullname, buf);
	  if (index_real->file[pos_list[x]-1]->link_info & IS_DIRECTORY)
	    item->link_info = IS_LINK | IS_DIRECTORY;
	  else
	    item->link_info = IS_LINK | IS_FILE;
	  lstat(index_real->file[pos_list[x]-1]->filename, &temp_buf);
	memcpy(&item->stats, &temp_buf, sizeof(struct stat));
	  item->name_str = make_correct(item, 0);
	  item->fullname_str = make_correct(item, 1);
	  add_file_to_dir(from_path,item);
	  XmListAddItem(other_widget, (prefs & FULLNAME) ? item->fullname_str : item->name_str, 0);
	  XmListDeselectPos(selected_list_widget, pos_list[x]);
	}
      }
      build_list (other_widget, from_path);
      for(x=0;x<pos_count;x++)
	XtFree(requester.files[x].dest);
    }
  }
  done_work();
}
  
  

void rm_cb(w, client_data, cbs)
     /* user has pushed the link as button */
     Widget w;
     XtPointer client_data;
     XmPushButtonCallbackStruct *cbs;
{ 
  int *pos_list, pos_count;
  index_struct *index;
  static XmString ok_string, cancel_string, title;
  XmString really_rm_string;
  Widget selected_list_widget, other_widget;
  int x, dirs=0, files=0, links = 0;
  char *text, path[MAXPATHLEN], buf[1000], counter[10];
  XmStringContext context;
  XmStringCharSet tag;
  XmStringDirection direction;
  Boolean separator, deleted, both= False;
  static Widget question_dialog;


  if (side==LEFT){
    strcpy(path, left_name);
    selected_list_widget = left_file_list;
    other_widget = right_file_list;
    index = &left_index;
  }
  else{
    strcpy(path, right_name);
    selected_list_widget = right_file_list;
    other_widget = left_file_list;
    index = &right_index;
  }
  if (!strcmp(left_name, right_name))
    both=True;
  XmListGetSelectedPos(selected_list_widget, &pos_list, &pos_count);
  if (pos_count){
    if (prefs & PROMPT){
      if (!ok_string)
	ok_string = XmStringCreate("OK","bbuttons");
      if (!cancel_string)
	cancel_string = XmStringCreate("Cancel","bbuttons");
      for (x=0; x<pos_count; x++)
	if (index->file[pos_list[x]-1]->link_info & IS_LINK)
	  links++;
	else
	  if (index->file[pos_list[x]-1]->link_info & IS_DIRECTORY)
	    dirs++;
	  else
	    files++;
      strcpy(buf, "   This will permanently delete:\n");
      if (files){
	sprintf(counter, "     %d", files);
	strcat(buf, counter);
	if (files==1)
	  strcat (buf, "  File\n");
	else
	  strcat (buf, "  Files\n");
      }
      if (dirs){
	sprintf(counter, "     %d", dirs);
	strcat(buf, counter);
	if (dirs==1)
	  strcat (buf, "  Directory\n");
	else
	  strcat (buf, "  Directories\n");	
      }
      if (links){
	sprintf(counter, "     %d", links);
	strcat(buf, counter);
	if (links == 1)
	  strcat (buf, "  Link\n");
	else
	  strcat (buf, "  Links\n");    
      }
      really_rm_string = XmStringConcat(XmStringCreate("WARNING:\n", "btext"), 
					XmStringCreateLtoR(buf, "buttons"));
      if (!title)
	title = XmStringCreateSimple("Warning");
      if (!question_dialog){
	question_dialog = XmCreateWarningDialog(toplevel, "Warning!", NULL, 0);
	XtVaSetValues(question_dialog, 
		      XmNmessageString,     really_rm_string,
		      XmNokLabelString,     ok_string,
		      XmNcancelLabelString, cancel_string,
		      XmNdefaultButtonType, XmDIALOG_CANCEL_BUTTON,
		      XmNdialogTitle,       title,
		      XmNdialogStyle,       XmDIALOG_FULL_APPLICATION_MODAL,
		      NULL);
	XtSetSensitive(XmMessageBoxGetChild(question_dialog, XmDIALOG_HELP_BUTTON), False);
	XtAddCallback(question_dialog, XmNokCallback, really_rm_cb, NULL);
	XtAddCallback(question_dialog, XmNcancelCallback, really_rm_cb, NULL);
      }
      else
	XtVaSetValues(question_dialog, XmNmessageString, really_rm_string, NULL);
      choice = OTHER;
      XtManageChild(question_dialog);
      XtPopup(XtParent(question_dialog), XtGrabNone);
      while (choice & OTHER) 
	XtAppProcessEvent(app, XtIMAll);
      XtPopdown(XtParent(question_dialog));
      if (choice & CANCEL)
	  return; 
    }
    chdir(path);
    for (x=pos_count; x>0; x--){   /*  must be done backwards so that wrong items are not deleted */
      deleted=False;
      if (index->file[pos_list[x-1]-1]->link_info == IS_DIRECTORY){
	deleted = remove_dir(path, index->file[pos_list[x-1]-1]->filename);
	remove_item_dir(index->file[pos_list[x-1]-1]->fullname);
	if (deleted){
	  remove_item(path, index->file[pos_list[x-1]-1]);
	  XmListDeletePos(selected_list_widget, pos_list[x-1]);
	  if (both)
	    XmListDeletePos(other_widget, pos_list[x-1]);
	}
      }
      else{
	if (!unlink(index->file[pos_list[x-1]-1]->filename)){
	  remove_item(path, index->file[pos_list[x-1]-1]);
	  XmListDeletePos(selected_list_widget, pos_list[x-1]);
	  if (both)
	    XmListDeletePos(other_widget, pos_list[x-1]);
	  deleted=True;
	}
      }
      working();
    }
    if (side == RIGHT)
      build_list(right_file_list, right_name);
    else
      build_list(left_file_list, left_name);
    if (both)
      if (side == RIGHT)
	build_list(left_file_list, left_name);
      else
	build_list(right_file_list, right_name);
  }
  done_work();
}


void really_rm_cb(w, data, cbs)
     Widget w;
     XtPointer data;
     XmAnyCallbackStruct *cbs;
{
  Widget help_dialog;
  XmString explain, done;
  char buf[1000];

  switch (cbs->reason){
  case XmCR_OK: 
    choice = OK;
    return;
  case XmCR_CANCEL:
    choice = CANCEL;
    return;
    
  }
}

void sync_cb(w, client_data, cbs)
Widget w;
XtPointer client_data;
XmPushButtonCallbackStruct *cbs;
{
  list_remove_all_directories();
  build_list(left_file_list, left_name);
  build_list(right_file_list, right_name);
  done_work();
  return;
}

void change_sides()
{
  static XmString left, right, mleft, mright, caleft, caright,
         maleft, maright, lleft, lright, laleft, laright;
  XmString b1,b2,b3,b4,b5,b6;

  if (!right)
    right=XmStringCreate("Copy","buttons");
  if (!left)
    left=XmStringCreate("Copy","buttons"); 
  if (!mright)
    mright=XmStringCreate("Move","buttons");
  if (!mleft)
    mleft=XmStringCreate("Move","buttons");  
  if (!maright)
    maright=XmStringCreate("Move As","buttons");
  if (!maleft)
    maleft=XmStringCreate("Move As","buttons");  
  if (!caright)
    caright=XmStringCreate("Copy As","buttons");
  if (!caleft)
    caleft=XmStringCreate("Copy As","buttons");
  if (!lright)
    lright=XmStringCreate("Link","buttons");
  if (!lleft)
    lleft=XmStringCreate("Link","buttons"); 
  if (!laright)
    laright=XmStringCreate("Link As","buttons");
  if (!laleft)
    laleft=XmStringCreate("Link As","buttons");  
  if (!side){
    b1 = right;
    b2 = mright;
    b3 = caright;
    b4 = maright;
    b5 = lright;
    b6 = laright;
  }
  else{
    b1=left;
    b2=mleft;
    b3=caleft;
    b4=maleft;
    b5=lleft;
    b6=laleft;
  }
  XtVaSetValues(but_copy, XmNlabelString, b1, NULL);
  XtVaSetValues(but_move, XmNlabelString, b2, NULL);
  XtVaSetValues(but_copyas, XmNlabelString, b3, NULL);
  XtVaSetValues(but_moveas, XmNlabelString, b4, NULL);
  XtVaSetValues(but_link, XmNlabelString, b5, NULL);
  XtVaSetValues(but_linkas, XmNlabelString, b6, NULL);
}

int really_quit()
{ 
  static Widget re_quit;
  XmString ok_str, cancel_str, text;

  if (!re_quit)
    re_quit=XmCreateWarningDialog(toplevel, "quit?", NULL, 0);
  text=XmStringCreate("Do you REALLY want to quit?","textual");
  ok_str= XmStringCreate("Quit","buttons");
  cancel_str= XmStringCreate("Cancel","buttons");
  XtVaSetValues(re_quit,
		XmNmessageString, text,
		XmNokLabelString, ok_str,
		XmNcancelLabelString, cancel_str,
		XmNdefaultButtonType, XmDIALOG_CANCEL_BUTTON,
		NULL);
  XmStringFree(text);
  XmStringFree(ok_str);
  XmStringFree(cancel_str);
  XtAddCallback(re_quit, 
		XmNokCallback, exit_well,
		NULL);
  XtManageChild(re_quit);
  XtPopup(XtParent(re_quit), XtGrabNone);
  return(0);
}

void button_exec (w, client_data, cbs)
Widget w;
XtPointer client_data;
XmPushButtonCallbackStruct *cbs;
{ 
  char buf[200];

  sprintf(buf,"%s: pushed\n", XtName(w));
  inform(" But since this is such a bad alpha release, there is no use to\n  this button\n");
  done_work();
}

void exit_exit()
{
  exit_well(0,0,0);
}

void exit_well (w, client_data, cbs)
Widget w;
XtPointer client_data;
XmPushButtonCallbackStruct *cbs;
{ /*  will _NOT_ use any of the arguments passed in  
            just do a cleanup and exit with 0   */
  kill(0, SIGTERM);  /*  try to kill all processes it started  */
  exit(0);
}

void left_button_exec (w, client_data, cbs)
Widget w;
XtPointer client_data;
XmPushButtonCallbackStruct *cbs;
{ 
  int x;
  char button_name[MAXBUTTONLENGTH];

  chdir(left_name);
  strcpy(button_name, XtName(w));
  for (x=0;x<=3;x++){
    if (strcmp(button_name, top_button_list[x].name) == 0){
      strcpy(new_left_name, top_button_list[x].expand);
      build_list(left_file_list, new_left_name);
      done_work();
      return;
    }
  }
  fprintf(stderr,"trouble reading your path\n");
  done_work();
}

void right_button_exec (w, client_data, cbs)
Widget w;
XtPointer client_data;
XmPushButtonCallbackStruct *cbs;
{ 
  int x;
  char button_name[MAXBUTTONLENGTH];

  strcpy(button_name, XtName(w));
  chdir(right_name);
  for (x=4;x<=8;x++){
    if (strcmp(button_name, top_button_list[x].name) == 0){
      strcpy(new_right_name, top_button_list[x].expand);
      build_list(right_file_list, new_right_name);
      done_work();
      return;
    }
  }
  fprintf(stderr,"trouble reading your path\n");
  done_work();
}

void double_click_list(w, client_data, cbs)
Widget w;
XtPointer client_data;
XmListCallbackStruct *cbs;
{
  char *new_item;
  int current_side;
  int current_position;

  if (strcmp(XtName(w), "left_file") == 0)
    current_side = LEFT;
  else
    current_side = RIGHT;
  current_position = cbs->item_position - 1;
  if (current_side==LEFT){
    if (left_index.file[current_position]->link_info & IS_DIRECTORY){
      if (left_index.file[current_position]->filename[0] == '/')
	strcpy(new_left_name, left_index.file[current_position]->filename);
      else {
	strcat(new_left_name,"/");
	strcat(new_left_name, left_index.file[current_position]->filename);
      }
      build_list(left_file_list, new_left_name); 
      done_work();
      return; 
    }
    else {
      file_display(left_name, left_index.file[current_position]->filename);
      done_work();
      return;
    }
  }
  else{
    if (right_index.file[current_position]->link_info & IS_DIRECTORY){
      if (right_index.file[current_position]->filename[0] == '/')
	strcpy(new_right_name, right_index.file[current_position]->filename);
      else {
	strcat(new_right_name,"/");
	strcat(new_right_name, right_index.file[current_position]->filename);
      }
      build_list(right_file_list, new_right_name); 
      done_work();
      return; 
    }
    else{
      file_display(right_name, right_index.file[current_position]->filename);
      done_work();
      return;
    }
  }
}   

void help_cb (w, item_no)
Widget w;
int item_no;
{
  inform("This is all you'll get... :-)\n");
  inform(" Basically, this is an 'easy' to use utility which will let you view, copy,\n");
  inform(" and delete files around the system.\n");
  inform(" Please send bug reports, and there should be many, to xcp-bugs@mit.edu\n");
  return;
}

void file_cb(w, item_no)
     Widget w;
     int item_no;
{
  /* item_no should be one of the following:
     0 - load settings
     1 - save defaults
     2 - save as
     3 - quit
     */
  static Widget dialog;   /* may be reused  */
  
  if (item_no == 3){  /*  quit  */
    if (!(prefs&PROMPT_QUIT))
      exit_well(0,0,0);
    else
      if (really_quit())
	exit_well(0,0,0);
    return;
  }
  if (item_no == 0){
    if(!dialog){
      dialog = (Widget)XmCreateFileSelectionDialog(toplevel, 
						   "File Selection", NULL, 0);
      XtAddCallback(dialog, XmNokCallback, pre_read_settings, NULL);
      XtAddCallback(dialog, XmNcancelCallback, 
		    pop_it_away, NULL);
    }
    XtManageChild(dialog);
    XtPopup(XtParent(dialog), XtGrabNone);
    choice = OTHER;
    while (choice & OTHER) 
      XtAppProcessEvent(app, XtIMAll);
    read_settings();
    update_settings();
    return;
  }
  if (item_no == 1){
    if (another_settings){
      XtFree(another_settings);
      another_settings = NULL;
    }
    write_settings();
    return;
  }
  if (item_no == 2){
    if(!dialog){
      dialog = (Widget)XmCreateFileSelectionDialog(toplevel, 
						   "File Selection", NULL, 0);
      XtAddCallback(dialog, XmNokCallback, pre_read_settings, NULL);
      XtAddCallback(dialog, XmNcancelCallback, 
		    pop_it_away, NULL);
    }
    XtManageChild(dialog);
    XtPopup(XtParent(dialog), XtGrabNone);
    choice = OTHER;
    while (choice & OTHER) 
      XtAppProcessEvent(app, XtIMAll);
    write_settings();
  }
}


void pre_read_settings(dialog, client, cbs)
Widget dialog;
XtPointer client;
XmFileSelectionBoxCallbackStruct *cbs;
{
  char *filename;
  
  if (cbs) {
    if (another_settings)  /*  free it before reallocating it  */
      XtFree(another_settings);
    if (!XmStringGetLtoR(cbs->value, XmSTRING_DEFAULT_CHARSET, &another_settings)){
      another_settings = NULL;
      choice = OK;
      return;
    }
    if (!strcmp(another_settings, "")){
      XtFree(another_settings);
      another_settings = NULL;
      choice=OK;
      return;
    }
  }
  choice = OK;
  XtUnmanageChild(dialog);
}
   
void pop_it_away(dialog, client, cbs)
Widget dialog;
XtPointer client;
XmFileSelectionBoxCallbackStruct *cbs;
{
  choice = CANCEL;
  XtUnmanageChild(dialog);
}  

void prefs_cb(w, item_no)
Widget w;
int item_no;
{
  /*  item_no = 
        0 - toggle prompt
        1 - toggle prompt_quit
        2 - toggle full
        3 - toggle dir_first
	4 - toggle overwrite
  */
  prefs^=(1<<item_no);
  if ((item_no == 2) || (item_no == 3)){
    build_list(left_file_list, left_name);
    build_list(right_file_list, right_name);
  }
  return;
}

void sort_cb(w, item_no)
Widget w;
int item_no;
{
    /*  sort by: (item_no = )
        0 - name
        1 - inode
        2 - size
        3 - date
    */
  sortby=item_no;
  build_list(left_file_list, left_name);
  build_list(right_file_list, right_name);
  return;
}

char *modes[] = {
  "---", "--x", "-w-", "-wx",
  "r--", "r-x", "rw-", "rwx" };

XmString make_correct(file, longlist)
/*  this will create a string for the filename according to the preferences  */
file_list_struct *file;
int longlist;
{
  char temp[MAXNAMELEN + 50], *temp2, temp3[MAXNAMELEN +1];
  static struct passwd *pwd;
  int thingie, x;  /* amount to shift S_IREAD etc.. by */
  XmString temp_string, throw, temp_string2;
  char charset[50];

  temp[0]='\0';
  if (longlist){
    if ((pwd == NULL) || (pwd->pw_uid != file->stats.st_uid))
      pwd=getpwuid(file->stats.st_uid);
    sscanf(temp,"%.10d   ", file->stats.st_ino);
    temp2=(&temp[(strlen(temp))]);
    switch ((file->stats.st_mode) & S_IFMT){
    case S_IFDIR:
      *temp2++='d';
      break;
#ifdef S_IFLNK
    case S_IFLNK:
      *temp2++='l';
      break;
#endif
#ifdef S_IFIFO
    case S_IFIFO:
      *temp2++='f';
      break;
#endif
    case S_IFCHR:
      *temp2++='c';
      break;
    case S_IFBLK:
      *temp2++='b';
      break;
#ifdef S_IFSOCK
    case S_IFSOCK:
      *temp2++='s';
      break;
    default:
      *temp2++='-';
      break;
#endif
    }
    temp2[0] = '\0';
    for (thingie=2; thingie>=0; thingie--){
      x = (file->stats.st_mode >> (thingie*3)) & 07;
      strcat(temp2, modes[x]);
    }
    if ((file->stats.st_mode & S_ISUID) != 0)
      temp2[2] = 's';
    if ((file->stats.st_mode & S_ISGID) != 0)
      temp2[5] = 's';
    if ((file->stats.st_mode & S_ISVTX) != 0)
      temp2[8] = 't';
    strcat(temp2,"   ");
    getuname(temp3,file->stats.st_uid);
    strcat(temp2, temp3);
    strcat(temp2,"   ");
    getgrname(temp3,file->stats.st_gid);
    strcat(temp2, temp3);
    temp2=(&temp[(strlen(temp))]);
#ifndef linux
    if ((file->stats.st_mode == S_IFBLK) || (file->stats.st_mode == S_IFCHR))
      sprintf(temp2, "%4d,%4d ", major(file->stats.st_rdev), minor(file->stats.st_rdev));
#  ifdef S_IFSOCK
    else if (file->stats.st_mode == S_IFSOCK)
      sprintf(temp2, "%9ld ", 0);
#  endif
    else		
      sprintf (temp2, "%9ld ", file->stats.st_size);
#else
#  ifdef S_IFSOCK
    if (file->stats.st_mode == S_IFSOCK)
      sprintf(temp2, "%9ld ", 0);
    else
#  endif
      sprintf (temp2, "%9ld ", file->stats.st_size);    
#endif
    temp2 = &temp[strlen(temp)];
    strcpy(temp2, ctime(&file->stats.st_mtime));
    temp2[24] = '\0';  /*  get rid of the \n in the output of ctime  */
    strcat (temp2, "  ");
    temp_string = XmStringCreate(temp, "files");
    switch ((file->stats.st_mode) & S_IFMT){
    case S_IFDIR:
      temp_string2 = XmStringConcat(temp_string, (throw = XmStringCreate(file->filename, "directories")));
      break;
#ifdef S_IFLNK
    case S_IFLNK:
      temp_string2 = XmStringConcat(temp_string, (throw = XmStringCreate(file->filename, "symlinks")));
      XmStringFree(throw);
      XmStringFree(temp_string);
      if (file->link_info & IS_DIRECTORY)
	strcpy(charset, "directories");
      else
	strcpy(charset, "files");
      temp_string = XmStringConcat(temp_string2, (throw = XmStringCreate(" -> ", "files")));
      XmStringFree(throw);
      XmStringFree(temp_string2);
      temp_string2 = XmStringConcat(temp_string, (throw = XmStringCreate(file->fullname, charset)));
      break;
#endif
    default:
      temp_string2 = XmStringConcat(temp_string, (throw = XmStringCreate(file->filename, "files")));
      break;
    }
    XmStringFree(throw);
    XmStringFree(temp_string);
    return(temp_string2);
  }
  else
    switch ((file->stats.st_mode) & S_IFMT){
    case S_IFDIR:
      temp_string2 = XmStringCreate(file->filename, "directories");
      break;
#ifdef S_IFLNK
    case S_IFLNK:
      temp_string2 = XmStringCreate(file->filename, "symlinks");
      if (file->link_info & IS_DIRECTORY)
	strcpy(charset, "directories");
      else
	strcpy(charset, "files");
      temp_string = XmStringConcat(temp_string2, (throw = XmStringCreate(" -> ", "files")));
      XmStringFree(throw);
      XmStringFree(temp_string2);
      temp_string2 = XmStringConcat(temp_string, (throw = XmStringCreate(file->fullname, charset)));
      break;
#endif
    default:
      temp_string2 = XmStringCreate(file->filename, "files");
      break;
    }
  return(temp_string2);
}

void flip_side(w, data, cbs)
     Widget w;
     XtPointer data;
     XmListCallbackStruct cbs;
{
  if (side==LEFT){
    XtRemoveCallback(right_file_list, XmNextendedSelectionCallback, flip_side, NULL);
    side=RIGHT;
    XmListDeselectAllItems(left_file_list);
    XtAddCallback(left_file_list, XmNextendedSelectionCallback, flip_side, NULL);
    XtVaSetValues(but_arrow, XmNarrowDirection, XmARROW_LEFT, NULL); 
  }
  else {
    XtRemoveCallback(left_file_list, XmNextendedSelectionCallback, flip_side, NULL);
    side=LEFT;
    XmListDeselectAllItems(right_file_list);
    XtAddCallback(right_file_list, XmNextendedSelectionCallback, flip_side, NULL);
    XtVaSetValues(but_arrow, XmNarrowDirection, XmARROW_RIGHT, NULL); 
  }
  change_sides();
  return;
}

void file_display (path, filename)
char *path, *filename;
{
  char buf[MAXPATHLEN + 50];
  chdir(path);
  strcpy(buf, path);
  if (buf[(strlen(buf)-1)] != '/')
    strcat(buf, "/");
  strcat(buf, filename);
  dtrt(buf);
  fflush(NULL);
  done_work();
  return;
}

void inform(string)
char *string;
{
  char *temp, *tempbuf, *new;
  int x;

  if ((temp = XmTextGetString(inform_widget))== NULL){
    perror("XmTextGetString");
    return;
  }
  x = strlen(temp) + strlen (string) + 3;
  if ( x > MAXBUFFERSPACE){
    x = x-DIMINISHBUFFERBY;
    if ((tempbuf = malloc(x* sizeof(char))) == NULL){
      perror("malloc");
      XtFree(temp);
      return;
    }
    new = temp+DIMINISHBUFFERBY;
    new = strchr(new, '\n') + 1;
    strcpy(tempbuf, new);
    strcat(tempbuf, string);
    XtVaSetValues(inform_widget, XmNvalue, tempbuf, 
		                 XmNcursorPosition, x,
		                 NULL);
    XtFree(temp);
    free(tempbuf);
    return;
  }
  if ((temp = realloc(temp, x)) == NULL){
    perror("realloc");
    return;
  }
  strcat(temp, string);
  XtVaSetValues(inform_widget, XmNvalue, temp, 
		               XmNcursorPosition, x,
		               NULL);
  XtFree(temp);
  return;
}

void check_for_scroll_widget()
{
  /* This function checks whether a popup with the "foo"as has already been created,
     and if so, maps it. This is used for most of the dialogs with the As command.
     Else, it creates it.
     */
  Arg args[12];
  XmString temp;
  XtWidgetGeometry geom;

  if (scroll_window_list_shell){
    XtMapWidget(request_left);
    XtMapWidget(request_right);
    XtMapWidget(list_okay);
    XtMapWidget(list_cancel); 
    XtMapWidget(request);
    XtMapWidget(list_row_col);
    XtMapWidget(scroll_window);
    XtMapWidget(scroll_window_list_control);
    XtMapWidget(scroll_window_list_action);
    XtMapWidget(scroll_window_list_pane);
    XtMapWidget(scroll_window_list_shell);
    XtMapWidget(XtParent(scroll_window_list_shell));
    return;
  }
  XtSetArg(args[0], XmNtitle, "Name the files");
  scroll_window_list_shell = XmCreateDialogShell(toplevel, "Name the Files", args, 1);
  scroll_window_list_pane = XtVaCreateManagedWidget("scroll_window_list_pane", 
						    xmPanedWindowWidgetClass, 
						    scroll_window_list_shell,
						    NULL);
  scroll_window_list_control = (Widget)XtVaCreateManagedWidget("Scroll_window_list_control", 
							xmFormWidgetClass, scroll_window_list_pane,
							NULL);
  request_form = (Widget)XtVaCreateManagedWidget("request_form", xmFormWidgetClass,
						 scroll_window_list_control,
						 XmNtopAttachment, XmATTACH_FORM,
						 XmNleftAttachment, XmATTACH_FORM,
						 XmNrightAttachment, XmATTACH_FORM,
						 NULL);
  request = XtVaCreateManagedWidget("request", xmLabelWidgetClass, request_form,
			     XmNtopAttachment, XmATTACH_FORM,
			     XmNleftAttachment, XmATTACH_FORM,
			     XmNrightAttachment, XmATTACH_FORM,
			     XmNbottomAttachment, XmATTACH_POSITION,
			     XmNbottomPosition, 50,
			     XmNalignment, XmALIGNMENT_CENTER,
			     NULL);
  request_left = XtVaCreateManagedWidget( "request_left", xmLabelWidgetClass,
					 request_form,
					 XmNalignment, XmALIGNMENT_CENTER,
					 XmNleftAttachment, XmATTACH_FORM,
					 XmNrightAttachment, XmATTACH_POSITION,
					 XmNrightPosition, 50,
					 XmNtopAttachment, XmATTACH_WIDGET,
					 XmNtopWidget, request,
					 NULL);
  request_right = XtVaCreateManagedWidget("request_right", xmLabelWidgetClass,
					  request_form,
					  XmNalignment, XmALIGNMENT_CENTER,
					  XmNrightAttachment, XmATTACH_FORM,
					  XmNleftAttachment, XmATTACH_POSITION,
					  XmNleftPosition, 50,
					  XmNtopAttachment, XmATTACH_WIDGET,
					  XmNtopWidget, request,
					  NULL);
  geom.request_mode = CWHeight;
  XtQueryGeometry(request_form, NULL, &geom);
  XtVaSetValues (request_form,
                 XmNpaneMinimum, geom.height,
                 XmNpaneMaximum, geom.height,
                 NULL);
  XtSetArg(args[0], XmNscrollBarDisplayPolicy, XmAS_NEEDED);
  XtSetArg(args[1], XmNscrollingPolicy, XmAUTOMATIC);
  XtSetArg(args[2], XmNtopAttachment, XmATTACH_WIDGET);
  XtSetArg(args[3], XmNtopWidget, request_form);
  XtSetArg(args[4], XmNleftAttachment, XmATTACH_FORM);
  XtSetArg(args[5], XmNrightAttachment, XmATTACH_FORM);
  XtSetArg(args[6], XmNbottomAttachment, XmATTACH_FORM);
  XtSetArg(args[7], XmNwidth, 600);
  scroll_window = (Widget)XmCreateScrolledWindow(scroll_window_list_control, "new_names", args, 8);
  XtManageChild(scroll_window);
  XtSetArg(args[0], XmNentryAlignment, XmALIGNMENT_END);
  XtSetArg(args[1], XmNisAligned, True);
  XtSetArg(args[2], XmNmarginHeight, 2);
  XtSetArg(args[3], XmNmarginWidth, 10);
  XtSetArg(args[4], XmNnumColumns, 1);
  XtSetArg(args[5], XmNspacing, 2);
  XtSetArg(args[6], XmNpacking, XmPACK_COLUMN);
  XtSetArg(args[7], XmNrowColumnType, XmWORK_AREA);
  XtSetArg(args[8], XmNrightAttachment, XmATTACH_FORM);
  XtSetArg(args[9], XmNleftAttachment, XmATTACH_FORM);
  list_row_col = XmCreateRowColumn(scroll_window, "row_col", args, 10);
  XtManageChild(list_row_col);
  scroll_window_list_action= XtVaCreateManagedWidget("form_action", xmFormWidgetClass,
						     scroll_window_list_pane,
						     XmNfractionBase, 5,
						     XmNheight, 40,
						     XmNmaxHeight, 40,
						     XmNminHeight, 40,
						     NULL);
  list_okay = XtVaCreateManagedWidget("okay", xmPushButtonWidgetClass, 
				      scroll_window_list_action,
				      XmNresizable, False,
				      XmNmultiClick, XmMULTICLICK_DISCARD,
				      XmNtopAttachment, XmATTACH_FORM,
				      XmNbottomAttachment, XmATTACH_FORM,
				      XmNleftAttachment, XmATTACH_POSITION,
				      XmNleftPosition, 1,
				      XmNrightPosition, XmATTACH_POSITION,
				      XmNrightPosition, 2,
				      XmNshowAsDefault, True,
				      NULL);
  XtAddCallback(list_okay, 
		XmNactivateCallback, file_copy_okay, NULL);  
  list_cancel = XtVaCreateManagedWidget("cancel", xmPushButtonWidgetClass, 
				      scroll_window_list_action,
					XmNmultiClick, XmMULTICLICK_DISCARD,
					XmNresizable, False,
					XmNtopAttachment, XmATTACH_FORM,
					XmNbottomAttachment, XmATTACH_FORM,
					XmNleftAttachment, XmATTACH_POSITION,
					XmNleftPosition, 3,
					XmNrightPosition, XmATTACH_POSITION,
					XmNrightPosition, 4,
					XmNshowAsDefault, False,
				      NULL);
  XtAddCallback(list_cancel, XmNactivateCallback, file_copy_cancel, NULL);
  geom.request_mode = CWHeight;
  XtQueryGeometry(scroll_window_list_action, NULL, &geom);
  XtVaSetValues (scroll_window_list_action,
                 XmNpaneMinimum, geom.height,
                 XmNpaneMaximum, geom.height,
                 NULL);

  XtManageChild(scroll_window_list_shell);
}
				    
void working()
{
  /* this function just updates the spinning Xcp logo to tell
the user the program is alive....  should be called once per
file or directory depending on the speed of the operation */

  char name[20];

  if (current_pixmap > 7)
    return;
  current_pixmap = (1+current_pixmap)%8;
  XtVaSetValues(label_name, XmNlabelPixmap, logo[current_pixmap], NULL);
  XmUpdateDisplay(mainform);
}

void done_work()
{
  /* put the xcp in the non_spin state  */
  current_pixmap = 0;
  XtVaSetValues(label_name, XmNlabelPixmap, logo[0], NULL);
}

void update_settings()
{
/*  
*   this function redraws the buttons, menus, and other such things
*   really useful only if settings have somehow been changed
*/

  int row, col, x, y;
  XmString button_name;
  char name[20];
  Widget temp_widget;

  for (row=0;row<3;row++)
    for (col=0;col<6;col++){
      getname(name,row,col);
      button_name = XmStringCreate(name, "buttons");
      XtVaSetValues(command[(col + 6*row)], 
		    XmNlabelString, button_name,
		    NULL);
      XmStringFree(button_name);
    }
  for (x=0;x<=7;x++){
    button_name = XmStringCreate(top_button_list[x].name, "buttons");
    XtVaSetValues(top_button[x], XmNlabelString, button_name, NULL);
    XmStringFree(button_name);
  }
  y=1;  
  strcpy(name,"button_ ");
  for (x=0;x<=4;x++){
    name[7]=(char)(48+x);
    if (temp_widget = XtNameToWidget (prefs_menu, name))
      if (prefs&y)
	XtVaSetValues(temp_widget, XmNset, True, NULL);
      else
	XtVaSetValues(temp_widget, XmNset, False, NULL);
    y <<= 1;
  }  
  for (x=0; x<=3; x++){
    name[7]=(char)(48+x);   /* bad way..  need button_0, button_1 etc.. */ 
    if (temp_widget = XtNameToWidget(sortby_menu, name))
      XtVaSetValues(temp_widget, XmNset, (sortby == x) ? True : False , NULL);
  }   
  build_list(left_file_list, left_name);
  build_list(right_file_list, right_name);
}


