/*
    UIT main file
    Copyright (c) Tudor Hulubei & Andrei Pitis, April 1994

This file is part of UIT (UNIX Interactive Tools)

UIT is free software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
Foundation; either version 2, or (at your option) any later version.

UIT is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
details .

You should have received a copy of the GNU General Public License along with
UIT; see the file COPYING.  If not, write to the Free Software Foundation,
675 Mass Ave, Cambridge, MA 02139, USA.  */


#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <signal.h>
#include <time.h>
#include <pwd.h>
#include <grp.h>
#include <malloc.h>
#include <limits.h>
#include <termios.h>
#include <sys/wait.h>
#include "tty.h"
#include "window.h"
#include "edit.h"
#include "status.h"
#include "panel.h"
#include "config.h"
#include "termcap.h"


#define MAX_STATIC_SIZE 60

#ifdef HAVE_LINUX
int  LinuxConsole = ON;
int  ColorMonitor = ON;
#else
int  LinuxConsole = OFF;
int  ColorMonitor = OFF;
#endif

edit *edt;
int  SignalsStatus;
int  SCREEN_X, SCREEN_Y;
int  suspended = OFF;
int  suspend_allowed = OFF;
char cSection[]  = "[UIT-Color]";
char bwSection[] = "[UIT-Monochrome]";
char title[] = "UNIX Interactive Tools 4.1c";
char login[] = "User:";
char tty[]   = "tty:";
char exit_msg[] = "*** (EXIT) Exit UNIX Interactive Tools ? (ENTER to confirm, TAB to cancel) ***";
char PS1[4]   = " $ ";
char *screen  = NULL;
char configfile[PATH_MAX] = "";
char TempDirectory[PATH_MAX];
char NormalModeHelp[256];
char CommandLineModeHelp[256];

extern int FrameDisplay;
static int UserHeartAttack;

#define BUILTIN_OPERATIONS		24

#define BUILTIN_Copy			-1
#define BUILTIN_RenameMove		-2
#define BUILTIN_MkDir			-3
#define BUILTIN_Delete			-4
#define BUILTIN_Exit			-5
#define BUILTIN_HistoryBack		-6
#define BUILTIN_ShowTty			-7
#define BUILTIN_Refresh			-8
#define BUILTIN_GotoRoot		-9
#define BUILTIN_SwitchPanels		-10
#define BUILTIN_HistoryNext		-11
#define BUILTIN_FileDisplayMode		-12
#define BUILTIN_DeleteCmdLn		-13
#define BUILTIN_FileSelect		-14
#define BUILTIN_CopyFileToCmdLn		-15
#define BUILTIN_Home			-16
#define BUILTIN_End			-17
#define BUILTIN_PageUp			-18
#define BUILTIN_PageDown		-19
#define BUILTIN_CursorLeft		-20
#define BUILTIN_CursorRight		-21
#define BUILTIN_CursorUp		-22
#define BUILTIN_CursorDown		-23
#define BUILTIN_ChangePanel		-24


#define MAX_BUILTIN_NAME		25


char built_in[BUILTIN_OPERATIONS][MAX_BUILTIN_NAME] =
{
    "<Copy>",			/* F5,		^kc */
    "<RenameMove>",		/* F6,		^km */
    "<MkDir>",			/* F7,		^kd */
    "<Delete>",			/* F8,		^ky */
    "<Exit>",			/* F10,		^kx */
    "<HistoryBack>",		/* ^e */
    "<ShowTty>",		/* ^o */
    "<Refresh>",		/* ^r */
    "<GotoRoot>",		/* ^t */
    "<SwitchPanels>",		/* ^u */
    "<HistoryNext>",		/* ^x */
    "<FileDisplayMode>",	/* ^ka */
    "<DeleteCmdLn>",		/* Delete,	^kh */
    "<FileSelect>",		/* Insert,	^l */
    "<CopyFileToCmdLn>",	/* ^a */
    "<Home>",			/* ^ku */
    "<End>",			/* ^kv */
    "<PageUp>",			/* PageUp,	*/
    "<PageDown>",		/* PageDown,	*/
    "<CursorLeft>",		/* CursorLeft,	^f */
    "<CursorRight>",		/* CursorRight,	^g */
    "<CursorUp>",		/* CursorUp,	^y */
    "<CursorDown>",		/* CursorDown,	^b */
    "<ChangePanel>",		/* TAB,		^ki */
};


typedef struct
{
    char  KeyName[12];
    char *OpName;
    char *OpCommand;
    char *OpNewDir;
    char  OpSaveScreen;
    char  OpPause;
    char  OpHide;
    char  OpBuiltin;
} ConfigKey;

#define KEYS_FIELDS	189
#define KEYSDATA_FIELDS	  8

static ConfigKey ConfigKeysFields[KEYS_FIELDS] = 
{
    { "CursorLeft", 	  built_in[19], NULL, NULL, 1, 0, 0, 1 },
    { "CursorRight", 	  built_in[20], NULL, NULL, 1, 0, 0, 1 },
    { "CursorUp", 	  built_in[21], NULL, NULL, 1, 0, 0, 1 },
    { "CursorDown", 	  built_in[22], NULL, NULL, 1, 0, 0, 1 },
    { "Home", 	  	  built_in[15], NULL, NULL, 1, 0, 0, 1 },
    { "End", 	  	  built_in[16], NULL, NULL, 1, 0, 0, 1 },
    { "Ins", 	  	  built_in[13], NULL, NULL, 1, 0, 0, 1 },
    { "Del", 	  	  built_in[12], NULL, NULL, 1, 0, 0, 1 },
    { "PageUp",	  	  built_in[17], NULL, NULL, 1, 0, 0, 1 },
    { "PageDown",	  built_in[18], NULL, NULL, 1, 0, 0, 1 },
    { "F1",	  	  NULL,	        NULL, NULL, 1, 0, 0, 0 },
    { "F2",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "F3",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "F4",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "F5",	  	  built_in[0],  NULL, NULL, 1, 0, 0, 1 },
    { "F6",	  	  built_in[1],  NULL, NULL, 1, 0, 0, 1 },
    { "F7",	  	  built_in[2],  NULL, NULL, 1, 0, 0, 1 },
    { "F8",	  	  built_in[3],  NULL, NULL, 1, 0, 0, 1 },
    { "F9", 	  	  NULL,	        NULL, NULL, 1, 0, 0, 0 },
    { "F10",	  	  built_in[4],  NULL, NULL, 1, 0, 0, 1 },

    { "Tab", 		  built_in[23], NULL, NULL, 1, 0, 0, 1 },
    { "^a", 	  	  built_in[14], NULL, NULL, 1, 0, 0, 1 },
    { "^b",	  	  built_in[22], NULL, NULL, 1, 0, 0, 1 },
    { "^da",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^db",	 	  NULL,		NULL, NULL, 1, 0, 0, 0 },
    { "^dc",	  	  NULL,	        NULL, NULL, 1, 0, 0, 0 },
    { "^dd",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^de",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^df",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^dg",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^dh",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^di",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^dj",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^dk",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^dl",	 	  NULL,		NULL, NULL, 1, 0, 0, 0 },
    { "^dm",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^dn",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^do",	 	  NULL,		NULL, NULL, 1, 0, 0, 0 },
    { "^dp",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^dq",	 	  NULL,		NULL, NULL, 1, 0, 0, 0 },
    { "^dr",	 	  NULL,		NULL, NULL, 1, 0, 0, 0 },
    { "^ds",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^dt",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^du",	 	  NULL,		NULL, NULL, 1, 0, 0, 0 },
    { "^dv",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^dw",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^dx", 	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^dy",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^dz",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^e",	 	  built_in[5],	NULL, NULL, 1, 0, 0, 1 },
    { "^f",	  	  built_in[19], NULL, NULL, 1, 0, 0, 1 },
    { "^g",	  	  built_in[20], NULL, NULL, 1, 0, 0, 1 },
    { "^ka",	  	  built_in[11],	NULL, NULL, 1, 0, 0, 1 },
    { "^kb",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^kc",	  	  built_in[0],	NULL, NULL, 1, 0, 0, 1 },
    { "^kd",	  	  built_in[2],	NULL, NULL, 1, 0, 0, 1 },
    { "^ke",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^kf",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^kg",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^kh",	 	  built_in[12],	NULL, NULL, 1, 0, 0, 1 },
    { "^ki",	  	  built_in[23],	NULL, NULL, 1, 0, 0, 1 },
    { "^kj",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^kk",	 	  NULL,		NULL, NULL, 1, 0, 0, 0 },
    { "^kl",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^km",	 	  built_in[1],	NULL, NULL, 1, 0, 0, 1 },
    { "^kn",	 	  NULL,		NULL, NULL, 1, 0, 0, 0 },
    { "^ko",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^kp",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^kq",	 	  NULL,		NULL, NULL, 1, 0, 0, 0 },
    { "^kr",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^ks",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^kt", 	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^ku",	  	  built_in[15],	NULL, NULL, 1, 0, 0, 1 },
    { "^kv",	  	  built_in[16],	NULL, NULL, 1, 0, 0, 1 },
    { "^kw",	 	  NULL,		NULL, NULL, 1, 0, 0, 0 },
    { "^kx",	  	  built_in[4],	NULL, NULL, 1, 0, 0, 1 },
    { "^ky",	  	  built_in[3],	NULL, NULL, 1, 0, 0, 1 },
    { "^kz",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^l",	  	  built_in[13],	NULL, NULL, 1, 0, 0, 1 },
    { "^na",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^nb",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^nc",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^nd",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^ne",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^nf",	 	  NULL,		NULL, NULL, 1, 0, 0, 0 },
    { "^ng",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^nh",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^ni",	 	  NULL,		NULL, NULL, 1, 0, 0, 0 },
    { "^nj",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^nk",	 	  NULL,		NULL, NULL, 1, 0, 0, 0 },
    { "^nl",	 	  NULL,		NULL, NULL, 1, 0, 0, 0 },
    { "^nm",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^nn",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^no",	 	  NULL,		NULL, NULL, 1, 0, 0, 0 },
    { "^np",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^nq",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^nr", 	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^ns",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^nt",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^nu",	 	  NULL,		NULL, NULL, 1, 0, 0, 0 },
    { "^nv",	  	  NULL,	        NULL, NULL, 1, 0, 0, 0 },
    { "^nw",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^nx",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^ny",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^nz",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^o",	  	  built_in[6],	NULL, NULL, 1, 0, 0, 1 },
    { "^pa",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^pb",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^pc",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^pd",	 	  NULL,		NULL, NULL, 1, 0, 0, 0 },
    { "^pe",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^pf",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^pg",	 	  NULL,		NULL, NULL, 1, 0, 0, 0 },
    { "^ph",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^pi",	 	  NULL,		NULL, NULL, 1, 0, 0, 0 },
    { "^pj",	 	  NULL,		NULL, NULL, 1, 0, 0, 0 },
    { "^pk",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^pl",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^pm",	 	  NULL,		NULL, NULL, 1, 0, 0, 0 },
    { "^pn",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^po",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^pp", 	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^pq",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^pr",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^ps",	 	  NULL,		NULL, NULL, 1, 0, 0, 0 },
    { "^pt",	 	  NULL,		NULL, NULL, 1, 0, 0, 0 },
    { "^pu",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^pv",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^pw",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^px",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^py",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^pz",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^r",	  	  built_in[7],  NULL, NULL, 1, 0, 0, 1 },
    { "^t",	  	  built_in[8],  NULL, NULL, 1, 0, 0, 1 },
    { "^u",	 	  built_in[9],	NULL, NULL, 1, 0, 0, 1 },
    { "^va",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^vb",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^vc",	 	  NULL,		NULL, NULL, 1, 0, 0, 0 },
    { "^vd",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^ve",	 	  NULL,		NULL, NULL, 1, 0, 0, 0 },
    { "^vf",	 	  NULL,		NULL, NULL, 1, 0, 0, 0 },
    { "^vg",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^vh",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^vi",	 	  NULL,		NULL, NULL, 1, 0, 0, 0 },
    { "^vj",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^vk",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^vl", 	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^vm",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^vn",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^vo",	 	  NULL,		NULL, NULL, 1, 0, 0, 0 },
    { "^vp",	  	  NULL,	        NULL, NULL, 1, 0, 0, 0 },
    { "^vq",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^vr",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^vs",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^vt",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^vu",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^vv",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^vw",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^vx",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^vy",	 	  NULL,		NULL, NULL, 1, 0, 0, 0 },
    { "^vz",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^wa",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^wb",	 	  NULL,		NULL, NULL, 1, 0, 0, 0 },
    { "^wc",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^wd",	 	  NULL,		NULL, NULL, 1, 0, 0, 0 },
    { "^we",	 	  NULL,		NULL, NULL, 1, 0, 0, 0 },
    { "^wf",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^wg",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^wh",	 	  NULL,		NULL, NULL, 1, 0, 0, 0 },
    { "^wi",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^wj",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^wk", 	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^wl",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^wm",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^wn",	 	  NULL,		NULL, NULL, 1, 0, 0, 0 },
    { "^wo",	  	  NULL,	        NULL, NULL, 1, 0, 0, 0 },
    { "^wp",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^wq",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^wr",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^ws",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^wt",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^wu",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^wv",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^ww",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^wx",	 	  NULL,		NULL, NULL, 1, 0, 0, 0 },
    { "^wy",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^wz",	  	  NULL,         NULL, NULL, 1, 0, 0, 0 },
    { "^x",	 	  built_in[10],	NULL, NULL, 1, 0, 0, 1 },
    { "^y",	  	  built_in[21],	NULL, NULL, 1, 0, 0, 1 },
}; 
 
 
#define TITLE_FIELDS	8
 
static char TitleFields[TITLE_FIELDS][40] = 
{
    "TitleForeground",
    "TitleBackground",
    "TitleBrightness",
    "UserName",
    "TtyName",
    "ClockForeground",
    "ClockBackground",
    "ClockBrightness"
};

#ifdef HAVE_LINUX
static int TitleColors[TITLE_FIELDS] = 
{
    CYAN, BLUE, ON, YELLOW, YELLOW, BLACK, CYAN, OFF
};
#else
static int TitleColors[TITLE_FIELDS] = 
{
    WHITE, BLACK, ON, WHITE, WHITE, BLACK, WHITE, OFF
};
#endif
 
#define TitleForeground	TitleColors[0]
#define TitleBackground	TitleColors[1]
#define TitleBrightness	TitleColors[2]
#define UserName 	TitleColors[3]
#define TtyName 	TitleColors[4]
#define ClockForeground TitleColors[5]
#define ClockBackground TitleColors[6]
#define ClockBrightness TitleColors[7]
 

void uitclock(int);


void user_panic(int signum)
{
    signal(signum, user_panic);
    tcdrain(1);
    tcflush(0, TCIFLUSH);
    UserHeartAttack = 1; 
}


void removelog(void)
{
    char name[PATH_MAX];
    
    sprintf(name, "%s/uit.1.%d", TempDirectory, getpid());
    remove(name);
    sprintf(name, "%s/uit.2.%d", TempDirectory, getpid());
    remove(name);
}


void fatal_signal(int signum)
{
    tty_end();
    tty_clrscr();

    switch (signum)
    {
	case SIGTERM:
	case SIGQUIT:
	    fprintf(stderr, "Got %s !\nbye\n",
	           (signum == SIGTERM) ? "SIGTERM" : "SIGQUIT");
	    break;
	
	case SIGSEGV:
	    fprintf(stderr, "Got SIGSEGV !\n");
	    fprintf(stderr, "Please report to tudor@ulise.cs.pub.ro\n");
	    break;

	case SIGHUP:
	    /* :-) */
	    fprintf(stderr, "Got SIGHUP !\n");
	    break;
	    
	default:
	    fprintf(stderr, "Got bad signal !\n");
	    fprintf(stderr, "Please report to tudor@ulise.cs.pub.ro\n");
	    break;
    }
    removelog();
    exit(1);
}


void signals_dfl(void)
{
    signal(SIGTERM, SIG_DFL);
    signal(SIGQUIT, SIG_DFL);
    signal(SIGINT , SIG_DFL);
}


void signals(int status)
{
    SignalsStatus = status;
    signal(SIGTERM, status == ON ? fatal_signal : SIG_IGN);
    signal(SIGQUIT, status == ON ? fatal_signal : SIG_IGN);
    signal(SIGINT , status == ON ? user_panic   : SIG_IGN);
}


void ignore_signals(void)
{
    signal(SIGILL,  SIG_IGN);
    signal(SIGTRAP, SIG_IGN);
    signal(SIGABRT, SIG_IGN);
    signal(SIGUSR1, SIG_IGN);
    signal(SIGUSR2, SIG_IGN);
    signal(SIGTTIN, SIG_IGN);
    signal(SIGTTOU, SIG_IGN);
    signal(SIGPIPE, SIG_IGN);
    signal(SIGFPE,  SIG_IGN);
}


void restore_signals(void)
{
    signal(SIGILL,  SIG_DFL);
    signal(SIGTRAP, SIG_DFL);
    signal(SIGABRT, SIG_DFL);
    signal(SIGUSR1, SIG_DFL);
    signal(SIGUSR2, SIG_DFL);
    signal(SIGTTIN, SIG_DFL);
    signal(SIGTTOU, SIG_DFL);
    signal(SIGPIPE, SIG_DFL);
    signal(SIGFPE,  SIG_DFL);
}


void settitle(void)
{
    char buf[256], *login_name = getlogin(), *tty_name = ttyname(1);
    window *title_win = window_init(0, 0, 1, SCREEN_X);

    if (login_name == NULL) login_name = "";
    if (tty_name   == NULL) tty_name   = "";

    tty_bright(TitleBrightness);
    tty_foreground(TitleForeground);
    tty_background(TitleBackground);
    window_cursormove(title_win, 0, 0);
    memset(buf, ' ', SCREEN_X);
    window_write(buf, SCREEN_X);

    sprintf(buf, "%s %s  %s %s        ", login, login_name, tty, tty_name);
    window_cursormove(title_win, 0, 1);
    window_write(title, strlen(title));
    window_cursormove(title_win, 0, SCREEN_X - strlen(buf)  - 1);
    window_write(login, strlen(login));
    window_putch(' ');
    tty_foreground(UserName);
    window_write(login_name, strlen(login_name));
    window_putch(' ');
    window_putch(' ');
    tty_foreground(TitleForeground);
    window_write(tty, strlen(tty));
    window_putch(' ');
    tty_foreground(TtyName);
    window_write(tty_name, strlen(tty_name));
}


void clock_on(int signum)
{
    struct tm *_tm;
    int hour;
    time_t _time;
    char buf[256];
    tty_status status;
    
    signal(SIGALRM, clock_on);
    _time = time(NULL);
    _tm = localtime(&_time);
    alarm(60 - _tm->tm_sec);
    tty_save(&status);
    if ((hour = _tm->tm_hour % 12) == 0) hour = 12;
    sprintf(buf, "%2d:%02d%c", hour, _tm->tm_min, (_tm->tm_hour < 12) ? 'a' : 'p');
    tty_cursormove(0, SCREEN_X - 7);
    tty_foreground(ClockForeground);
    tty_background(ClockBackground);
    tty_bright(ClockBrightness);
    tty_write(buf, strlen(buf));
    tty_restore(&status);
    edit_setcursor(edt);
}


void clock_off(void)
{
    signal(SIGALRM, SIG_IGN);
}


void uitclock(int status)
{
    if (status == ON)
        clock_on(0);
    else
        clock_off();
}


void uitclock_status(int status)
{
    if (status)
	signal(SIGALRM, clock_on);
    else
	signal(SIGALRM, SIG_IGN);
}


void Suspend(int signum)
{
    if (suspend_allowed)
    {
	suspended = ON;
	uitclock(OFF);
	tty_end();
	tty_putscreen(screen);
	signal(SIGTSTP, SIG_DFL);
	kill(getpid(), SIGTSTP);
    }
    else
	signal(SIGTSTP, Suspend);
}


int start(char *cmd, int hide)
{
    int child_exit_code;
    FILE *stdout_log, *stderr_log;
    char fname[PATH_MAX], *tty_name;
    
    if (hide)
    {
        uitclock(OFF);
        tty_name = ttyname(1);
        close(1);
        close(2);
        sprintf(fname, "%s/uit.1.%d", TempDirectory, getpid());
        stdout_log = fopen(fname, "w");
        sprintf(fname, "%s/uit.2.%d", TempDirectory, getpid());
	stderr_log = fopen(fname, "w");
	
	restore_signals();
	signals_dfl();
        child_exit_code = system(cmd);
	signals(SignalsStatus);
	ignore_signals();
	
	fclose(stderr_log);
        fclose(stdout_log);
        open(tty_name, O_RDWR);
        open(tty_name, O_RDWR);
    }
    else
    {
        uitclock(OFF);
        tty_end();
        tty_putscreen(screen);

	restore_signals();
	signals_dfl();
        child_exit_code = system(cmd);
        signals(SignalsStatus);
	ignore_signals();

	write(1, "\n\n", 2);
        tty_init();
    }
    return child_exit_code;
}


void fatal(char *postmsg)
{
    uitclock(OFF);
    tty_clrscr();
    tty_end();
    fprintf(stderr, "Fatal error : %s !\n", postmsg);
    removelog();
    exit(1);    
}


int getOpCommand(char *CommandName, char *src, char *dest, panel *p, panel *l, edit *e)
{
    char *ptr;
    struct group *grp;
    struct passwd *pwd;
    static int busy = 0;
    int  retval, uid, gid, len;
    char question[MAXLINE];
    char formatted[MAXLINE];
    
    
    while (*src)
    {
        if (*src != '%') *dest++ = *src++;
        else
        {
            switch(*++src)
            {
                case 's': if (busy) { busy = 0; return 0; }
                	  if (*++src != '{') return 0;
                	  if ((ptr = strchr(++src, ',')) == NULL) return 0;
                	  *ptr = 0;
                	  retval = getOpCommand(NULL, src, formatted, p, l, NULL);
                	  if (retval != 1) return retval;
                          sprintf(question, "(%s) %s", CommandName, formatted);
                          *ptr++ = ',';
                	  if ((src = strchr(ptr, '}')) == NULL) return 0;
                	  *src = 0;
                	  question[MAX_STATIC_SIZE] = 0;
                	  retval = getOpCommand(NULL, ptr, formatted, p, l, NULL);
                	  if (retval != 1)
                	  {
                  	      *src = '}';
                	      return retval;
                	  }
                	  if (!edit_gets(e, question, dest, formatted))
                	  {
                  	      *src = '}';
                	      return -1;
                	  }
                	  *src = '}';
                	  break;
                	  
                case 'f': if (panel_getcurrentfiletype(p) != FILE_ENTRY) return -1;
                	  sprintf(dest, "\"%s\"", panel_getcurrentfilename(p));
                	  break;

                case 'd': if (panel_getcurrentfiletype(p) != DIR_ENTRY) return -1;
                	  sprintf(dest, "\"%s\"", panel_getcurrentfilename(p));
                	  break;

                case 'l': if (panel_getcurrentfiletype(p) != SYMLINK_ENTRY) return -1;
                	  sprintf(dest, "\"%s\"", panel_getcurrentfilename(p));
                	  break;

                case 't': if (panel_getcurrentfiletype(p) != FIFO_ENTRY) return -1;
                	  sprintf(dest, "\"%s\"", panel_getcurrentfilename(p));
                	  break;

                case 'z': if (panel_getcurrentfiletype(p) != SOCKET_ENTRY) return -1;
                	  sprintf(dest, "\"%s\"", panel_getcurrentfilename(p));
                	  break;

                case 'a': sprintf(dest, "\"%s\"", panel_getcurrentfilename(p));
                	  break;
                	  
                case 'm': sprintf(dest, "%o", panel_getcurrentfilemode(p) & 07777); 
                	  break;
                
                case 'o': uid = panel_getcurrentfileuid(p);
                	  pwd = getpwuid(uid);
                	  if (pwd)
                	      sprintf(dest, "%s", pwd->pw_name);
                	  else
                	      sprintf(dest, "%o", uid);
                	  break;

                case 'g': gid = panel_getcurrentfilegid(p);
                	  grp = getgrgid(gid);
                	  if (grp)
                	      sprintf(dest, "%s", grp->gr_name);
                	  else
                	      sprintf(dest, "%o", gid);
                	  break;

                case 'p': dest[0] = '\"';
                	  panel_getpath(p, dest + 1, PATH_MAX);
                	  len = strlen(dest);
                	  dest[len] = '"';
                	  dest[len + 1] = 0;
			  break;

                case 'b': dest[0] = '\"';
                	  panel_getpath(p, dest + 1, PATH_MAX);
                	  ptr = strrchr(dest + 1, '/');
			  strcpy(dest + 1, (*++ptr) ? ptr : "root");
                	  len = strlen(dest);
                	  dest[len] = '"';
                	  dest[len + 1] = 0;
			  break;

                case 'F': if (panel_getcurrentfiletype(l) != FILE_ENTRY) return -1;
                	  sprintf(dest, "\"%s\"", panel_getcurrentfilename(l));
                	  break;

                case 'D': if (panel_getcurrentfiletype(l) != DIR_ENTRY) return -1;
                	  sprintf(dest, "\"%s\"", panel_getcurrentfilename(l));
                	  break;

                case 'L': if (panel_getcurrentfiletype(l) != SYMLINK_ENTRY) return -1;
                	  sprintf(dest, "\"%s\"", panel_getcurrentfilename(l));
                	  break;
                	  
                case 'T': if (panel_getcurrentfiletype(p) != FIFO_ENTRY) return -1;
                	  sprintf(dest, "\"%s\"", panel_getcurrentfilename(p));
                	  break;

                case 'Z': if (panel_getcurrentfiletype(p) != SOCKET_ENTRY) return -1;
                	  sprintf(dest, "\"%s\"", panel_getcurrentfilename(p));
                	  break;

                case 'A': sprintf(dest, "\"%s\"", panel_getcurrentfilename(l));
                	  break;
                	  
                case 'M': sprintf(dest, "%o", panel_getcurrentfilemode(l) & 07777); 
                	  break;
                
                case 'O': uid = panel_getcurrentfileuid(l);
                	  pwd = getpwuid(uid);
                	  if (pwd)
                	      sprintf(dest, "%s", pwd->pw_name);
                	  else
                	      sprintf(dest, "%o", uid);
                	  break;

                case 'G': gid = panel_getcurrentfilegid(l);
                	  grp = getgrgid(gid);
                	  if (grp)
                	      sprintf(dest, "%s", grp->gr_name);
                	  else
                	      sprintf(dest, "%o", gid);
                	  break;

                case 'P': dest[0] = '\"';
                	  panel_getpath(l, dest + 1, PATH_MAX);
                	  len = strlen(dest);
                	  dest[len] = '\"';
                	  dest[len + 1] = 0;
			  break;

		case 'B': dest[0] = '\"';
                	  panel_getpath(l, dest + 1, PATH_MAX);
                	  ptr = strrchr(dest + 1, '/');
			  strcpy(dest + 1, (*++ptr) ? ptr : "root");
                	  len = strlen(dest);
                	  dest[len] = '"';
                	  dest[len + 1] = 0;
			  break;

                default : return 0;
            }
            src++;
            dest += strlen(dest);
        }
    }
    *dest = 0;
    return 1;
}


int getConfigKey(int key)
{
    return (key >= 0) ? -1 : -(key + TTY_FIRST_CONFIG_KEY);
}


int main(void)
{
    FILE *stderr_log;
    char cmdln[PATH_MAX];
    char cmdname[PATH_MAX];
    configuration *config;
    char *homedirectory = cmdln;
    char temppath[2][PATH_MAX];
    char *home, *data = NULL, *section;
    int child_exit_code, repeat_count;
    int panel_no = 0, action_status, i, j, retval;
    int sectionptr = 0, index, key, configkey, app_end = 0, len, wait = 0;
    panel *left_panel, *right_panel, *current_panel, *other_panel, *temp_panel;

    signal(SIGSEGV, fatal_signal);
    signal(SIGHUP,  fatal_signal);
    signals(OFF);
    ignore_signals();

    printf("UNIX Interactive Tools 4.1c\n");
    printf("Copyright (c) April 1994 by Tudor Hulubei & Andrei Pitis\n");

    termcap_init();
    tty_kbdinit();

    strcpy(homedirectory, "/");
    strcpy(temppath[0], ".");
    strcpy(temppath[1], ".");
    
    if (home = getenv("HOME"))
    {
        strcpy(homedirectory, home);
        strcpy(configfile, home);
        if (configfile[strlen(configfile) - 1] != '/') strcat(configfile, "/");
    }
    strcat(configfile, ".uitrc");

    config = configuration_init(configfile);
 
    if (configuration_getstatus(config) == STATUS_OK)
    {
        if ((sectionptr = configuration_getsectionptr(config, "[Setup]")) == -1)
	    fprintf(stderr, "[Setup] section missing.");
	else
	{
	    configuration_getfielddata(config, sectionptr, "TempDirectory", &data, 1, DO_SEEK);
	    strncpy(TempDirectory, data ? data : homedirectory, PATH_MAX);
#ifdef HAVE_LINUX
	    configuration_getfielddata(config, sectionptr, "LinuxConsole", &data, 1, DO_SEEK);
	    LinuxConsole = data && strcmp(data, "ON") == 0;
	    configuration_getfielddata(config, sectionptr, "ColorMonitor", &data, 1, DO_SEEK);
	    ColorMonitor = data && strcmp(data, "ON") == 0;
#endif
	}

        if ((sectionptr = configuration_getsectionptr(config, "[UIT-Setup]")) == -1)
	    fprintf(stderr, "[UIT-Setup] section missing.");
	else
	{
	    configuration_getfielddata(config, sectionptr, "NormalModeHelp", &data, 1, DO_SEEK);
	    if (data) strncpy(NormalModeHelp, data, 256);
	    configuration_getfielddata(config, sectionptr, "CommandLineModeHelp", &data, 1, DO_SEEK);
	    if (data) strncpy(CommandLineModeHelp, data, 256);
	    configuration_getfielddata(config, sectionptr, "StartupLeftPanelPath", &data, 1, DO_SEEK);
	    strncpy(temppath[0], data ? data : ".", PATH_MAX);
	    configuration_getfielddata(config, sectionptr, "StartupRightPanelPath", &data, 1, DO_SEEK);
	    strncpy(temppath[1], data ? data : ".", PATH_MAX);
	}

	section = (LinuxConsole && ColorMonitor) ? cSection : bwSection;

        if ((sectionptr = configuration_getsectionptr(config, section)) == -1)
	    fprintf(stderr, "%s section missing.", section);
	else
            for (i = 0; i < TITLE_FIELDS; i++)
            {
                configuration_getfielddata(config, sectionptr, TitleFields[i], &data, 1, DO_SEEK);
                if (!data || (index  = tty_getcolorindex(data))== -1)
                    fprintf(stderr, "Invalid %s (%s).\n", TitleFields[i], data);
	        else
                    TitleColors[i] = index;
            }

        if ((sectionptr = configuration_getsectionptr(config, "[UIT-Keys]")) == -1)
	    fprintf(stderr, "[UIT-Keys] section missing.");
	else
	{
	    char *contents[KEYSDATA_FIELDS - 2];

	    for (i = 0; i < KEYS_FIELDS; i++)
	    {
	        configuration_getfielddata(config, sectionptr, ConfigKeysFields[i].KeyName, contents, KEYSDATA_FIELDS - 2, NO_SEEK);

		if (contents[0])
		{
	            ConfigKeysFields[i].OpName = malloc(strlen(contents[0]) + 1);
	            strcpy(ConfigKeysFields[i].OpName, contents[0]);
	        }
	        else
	        {
	            ConfigKeysFields[i].OpName = NULL;
	            continue;
	        }

		if (contents[1])
		{
	            ConfigKeysFields[i].OpCommand = malloc(strlen(contents[1]) + 1);
	            strcpy(ConfigKeysFields[i].OpCommand, contents[1]);
	        }
	        else
	        {
	            ConfigKeysFields[i].OpCommand = NULL;
	            continue;
	        }
	        
	        if (contents[2])
	        {
	            ConfigKeysFields[i].OpNewDir = malloc(strlen(contents[2]) + 1);
	            strcpy(ConfigKeysFields[i].OpNewDir, contents[2]);
	        }
	        else ConfigKeysFields[i].OpNewDir = NULL;
	        
		if (contents[3]) ConfigKeysFields[i].OpSaveScreen = atoi(contents[3]);
	        else ConfigKeysFields[i].OpSaveScreen = 1;

		if (contents[4]) ConfigKeysFields[i].OpPause = atoi(contents[4]);
	        else ConfigKeysFields[i].OpPause = 0;

		if (contents[5]) ConfigKeysFields[i].OpHide = atoi(contents[5]);
	        else ConfigKeysFields[i].OpHide = 0;
	    }
	    for (i = 0; i < KEYS_FIELDS; i++)
	    {
                ConfigKeysFields[i].OpBuiltin = 0;
	        if (ConfigKeysFields[i].OpName == NULL) continue;
	        for (j = 0; j < BUILTIN_OPERATIONS; j++)
	            if (strcmp(ConfigKeysFields[i].OpName, built_in[j]) == 0)
	            {
	                free(ConfigKeysFields[i].OpName);
	                ConfigKeysFields[i].OpName = built_in[j];
	                ConfigKeysFields[i].OpBuiltin = 1;
	                break;
	            }
	    }
	}
    }
    else
        fprintf(stderr, "Cannot open configuration file %s.\nUsing defaults.\n", configfile);

    tty_getsize(&SCREEN_X, &SCREEN_Y);

#ifdef HAVE_LINUX
    if (LinuxConsole)
    {
	screen = malloc(2 + SCREEN_X * SCREEN_Y);
	if (screen == NULL)
	    fatal("not enough memory");
    }
#endif
        
    status_init(SCREEN_X, SCREEN_Y - 1, NormalModeHelp, config);

    if (getuid() == 0) PS1[1] = '#';
    edt = edit_init(SCREEN_X, SCREEN_Y - 2, config);

    left_panel  = panel_init(SCREEN_Y - 3, SCREEN_X >> 1, 0            , 1, temppath[0],
    		             edt, &UserHeartAttack, config);
    right_panel = panel_init(SCREEN_Y - 3, SCREEN_X >> 1, SCREEN_X >> 1, 1, temppath[1], 
    		             edt, &UserHeartAttack, config);

    configuration_end(config);
    tty_getscreen(screen);
    tty_init();

    if (FrameDisplay == OFF) tty_clrscr();

restart:

    signals(OFF);
    signal(SIGTSTP, Suspend);
    
    if (wait)
        while (tty_getkey(NULL) == KEY_NOKEY);
    wait = 0;

    settitle();
    uitclock(ON);
    uitclock(OFF);

    current_panel = panel_no ? right_panel : left_panel;
    other_panel   = panel_no ? left_panel  : right_panel;

    panel_action(current_panel, act_REFRESH, other_panel,   (void *)-1, 1);
    panel_action(other_panel,   act_REFRESH, current_panel, (void *)-1, 1);
    
    panel_setfocus(current_panel, ON, other_panel);
    
    status(NULL, 0, 0, 1, MSG_OK);
    
    edit_gettext(edt, cmdln);
    edit_reset(edt);
    edit_puts(edt, strcat(panel_getpath(current_panel, temppath[0], MAX_STATIC_SIZE), PS1));
    edit_eos(edt);
    edit_puts(edt, cmdln);
    edit_update(edt);
    edit_setcursor(edt);
    
    signals(ON);
    uitclock(ON);

    while(!app_end)
    {
	UserHeartAttack = 0;
	suspend_allowed = ON;
	configkey = getConfigKey(key = tty_getkey(&repeat_count));
	suspend_allowed = OFF;
	if (suspended)
	{
            tty_init();
	    suspended = OFF;
	    panel_nooptimizations(current_panel);
	    panel_nooptimizations(other_panel);
            goto restart;
	}

	signals(OFF);

        if (configkey != -1)
            if (ConfigKeysFields[configkey].OpBuiltin)
    	        key = - 1 - (ConfigKeysFields[configkey].OpName - built_in[0]) / MAX_BUILTIN_NAME;
    	    else
    	    {
		if (ConfigKeysFields[configkey].OpName)
		{
		    panel_nooptimizations(current_panel);
		    panel_nooptimizations(other_panel);
		    if (ConfigKeysFields[configkey].OpCommand)
		    {
           	        if (retval = getOpCommand(ConfigKeysFields[configkey].OpName,
           	        			  ConfigKeysFields[configkey].OpCommand,
           	        		          cmdln, current_panel, other_panel, edt))
           	        {
           	            if (retval == 1)
           	            {
           	                sprintf(cmdname, "Executing %s: %s", ConfigKeysFields[configkey].OpName, cmdln);
				status(cmdname, 0, 0, 0, MSG_WARNING);
           	                child_exit_code = start(cmdln, ConfigKeysFields[configkey].OpHide);
           	                if (ConfigKeysFields[configkey].OpHide)
				{
				    sprintf(cmdln, "%s/uit.2.%d", TempDirectory, getpid());
				    stderr_log = fopen(cmdln, "r");
				    if (child_exit_code) tty_beep();
				    if (stderr_log == NULL)
				        status("*** Can't open stderr log file ***", 1, 1, 1, MSG_ERROR);
				    else
				    {
					while (fgets(cmdln, SCREEN_X, stderr_log))
					    if (status(cmdln, 1, 0, 0, MSG_ERROR) != KEY_ENTER) break;
				    }
				    fclose(stderr_log);
				}
				else
           	                {
            	                    if (ConfigKeysFields[configkey].OpSaveScreen)
            	                        tty_getscreen(screen);
            	                    if (FrameDisplay == OFF) tty_clrscr();
            	                    if (ConfigKeysFields[configkey].OpPause)
				        wait = 1;
				}
           	                if (child_exit_code == 0 && ConfigKeysFields[configkey].OpNewDir)
           	                    panel_action(current_panel, act_CHDIR, other_panel, ConfigKeysFields[configkey].OpNewDir, 1);
			        goto restart;
			    }
			    else
			        continue;
			}
			else
			{
			    sprintf(cmdln, "Bad configured command for key %s !", ConfigKeysFields[configkey].KeyName);
			    status(cmdln, 1, 1, 1, MSG_ERROR);
			    continue;
			}
		    }
		}
            }

        signals(ON);
        
        switch (key)
        {
            case BUILTIN_ChangePanel:
	    		     signals(OFF);
	    		     uitclock_status(OFF);
	    		     if ((repeat_count & 1) == 0) break;
            		     panel_setfocus(current_panel, OFF, NULL);
            		     temp_panel = current_panel;
            		     current_panel = other_panel;
            		     other_panel = temp_panel;
            		     panel_no = !panel_no;
            		     panel_setfocus(current_panel, ON, other_panel);
			     edit_gettext(edt, cmdln);
			     edit_reset(edt);
			     edit_puts(edt, strcat(panel_getpath(current_panel, temppath[0], MAX_STATIC_SIZE), PS1));
			     edit_eos(edt);
			     edit_puts(edt, cmdln);
			     edit_update(edt);
			     uitclock_status(ON);
            		     break;

            case BUILTIN_CursorUp:
	    		     signals(OFF);
			     uitclock_status(OFF);
            		     panel_action(current_panel, act_UP, other_panel, NULL, repeat_count);
			     uitclock_status(ON);
            		     break;

            case BUILTIN_CursorDown:
	    		     signals(OFF);
			     uitclock_status(OFF);
            		     panel_action(current_panel, act_DOWN, other_panel, NULL, repeat_count);
			     uitclock_status(ON);
            		     break;

            case KEY_ENTER:  action_status = 0;
            		     if (*edit_gettext(edt, cmdln))
           		         switch (*cmdln)
           		         {
           		             case '+': action_status = panel_action(current_panel, act_SELECTALL  , other_panel, NULL, 1); break;
           		             case '-': action_status = panel_action(current_panel, act_UNSELECTALL, other_panel, NULL, 1); break;
           		             case '*': action_status = panel_action(current_panel, act_TOGGLE, other_panel, NULL, 1); break;
           		             default : panel_nooptimizations(current_panel);
			                       panel_nooptimizations(other_panel);
           		             	       start(cmdln, 0);
           		             	       action_status = -1; 
           		             	       break;
              			}
              		     else
              		     {
            		         signals(OFF);
				 uitclock_status(OFF);
            		         action_status = panel_action(current_panel, act_ENTER , other_panel, screen, 1);
				 uitclock_status(ON);
			     }
			     
            		     if (action_status == 1)
            		     {
				 uitclock_status(OFF);
            		         edit_reset(edt);
            		         edit_puts(edt, strcat(panel_getpath(current_panel, temppath[0], MAX_STATIC_SIZE), PS1));
            		         edit_eos(edt);
            		         edit_update(edt);
				 uitclock_status(ON);
            		     }
            		     else
            		         if (action_status == -1) 
            		         {
				     uitclock_status(OFF);
            		             tty_getscreen(screen);
            		             edit_history(edt, EDIT_RECORD);
            		             edit_reset(edt);
				     uitclock_status(ON);
				     if (FrameDisplay == OFF) tty_clrscr();
 				     goto restart;
            		         }
            		     break;

            case BUILTIN_FileSelect:
	    		     signals(OFF);
			     uitclock_status(OFF);
	    		     for (i = 0; i < repeat_count; i++)
				 panel_action(current_panel, act_SELECT, other_panel, NULL, 1);
			     uitclock_status(ON);
            		     break;

            case BUILTIN_CursorLeft:
            case BUILTIN_PageUp:
	    		     signals(OFF);
			     uitclock_status(OFF);
	    		     for (i = 0; i < repeat_count; i++)
				 panel_action(current_panel, act_PGUP, other_panel, NULL, 1);
			     uitclock_status(ON);
            		     break;

            case BUILTIN_CursorRight:
            case BUILTIN_PageDown:  
	    		     signals(OFF);
			     uitclock_status(OFF);
	    		     for (i = 0; i < repeat_count; i++)
				 panel_action(current_panel, act_PGDOWN, other_panel, NULL, 1);
			     uitclock_status(ON);
            		     break;

            case BUILTIN_Home:
	    		     signals(OFF);
			     uitclock_status(OFF);
            		     panel_action(current_panel, act_HOME, other_panel, NULL, 1);
			     uitclock_status(ON);
            		     break;

            case BUILTIN_End:
	    		     signals(OFF);
			     uitclock_status(OFF);
            		     panel_action(current_panel, act_END, other_panel, NULL, 1);
			     uitclock_status(ON);
            		     break;

            case BUILTIN_GotoRoot:  
	    		     signals(OFF);
			     uitclock_status(OFF);
            		     panel_action(current_panel, act_CHDIR, other_panel, "/", 1);
			     edit_gettext(edt, cmdln);
			     edit_reset(edt);
			     edit_puts(edt, strcat(panel_getpath(current_panel, temppath[0], MAX_STATIC_SIZE), PS1));
			     edit_eos(edt);
			     edit_puts(edt, cmdln);
			     edit_update(edt);
			     uitclock_status(ON);
            		     break;

            case BUILTIN_Refresh:
			     panel_nooptimizations(current_panel);
			     panel_nooptimizations(other_panel);
			     goto restart;
				
            case BUILTIN_ShowTty:
			     if ((repeat_count & 1) == 0) break;
            		     uitclock(OFF);
            		     tty_putscreen(screen);
            		     status(CommandLineModeHelp, 0, 0, 0, MSG_OK);
			     edit_update(edt);
			     edit_setcursor(edt);

        		     while (1)
        		     {
				 suspend_allowed = ON;
        		         configkey = getConfigKey(key = tty_getkey(&repeat_count));
	                         if (suspended)
	                         {
                                     tty_init();
				     signal(SIGTSTP, Suspend);
 	                             status(CommandLineModeHelp, 0, 0, 0, MSG_OK);
                                     edit_update(edt);
                                     edit_setcursor(edt);
	                             suspended = OFF;
	                         }

		                 if (configkey != -1 && ConfigKeysFields[configkey].OpBuiltin)
    	    			     key = - 1 - (ConfigKeysFields[configkey].OpName - built_in[0]) / MAX_BUILTIN_NAME;

            		         if (key == BUILTIN_ShowTty && (repeat_count & 1)) break;

            		         switch (key)
            		         {
            		             case KEY_ENTER:
	            		          if (*edit_gettext(edt, cmdln))
	            		          {
            		                      tty_putscreen(screen);
	            		              start(cmdln, 0);
            		                      tty_getscreen(screen);
            		                      edit_history(edt, EDIT_RECORD);
            		                      edit_reset(edt);
                                              edit_puts(edt, strcat(panel_getpath(current_panel, temppath[0], MAX_STATIC_SIZE), PS1));
                                              edit_eos(edt);
                                              edit_update(edt);
            		                      status(CommandLineModeHelp, 0, 0, 0, MSG_OK);
	            		          }
            		                  break;

            		             case BUILTIN_HistoryBack:
            		             case BUILTIN_CursorUp:
	    				  for (i = 0; i < repeat_count; i++)
	    				      edit_history(edt, EDIT_PREVIOUS);
            		             	  break;

            		             case BUILTIN_HistoryNext:
            		             case BUILTIN_CursorDown:
            		                  for (i = 0; i < repeat_count; i++)
					      edit_history(edt, EDIT_NEXT);
					  break;

	                             case BUILTIN_DeleteCmdLn:
	                                  edit_del(edt);
	    		                  break;
	    		     
			             case BUILTIN_Refresh:
					  panel_nooptimizations(current_panel);
			     		  panel_nooptimizations(other_panel);
			                  tty_putscreen(screen);
			                  edit_update(edt);
			                  status(CommandLineModeHelp, 0, 0, 0, MSG_OK);
            		 		  break;
            		 		    
            		             case BUILTIN_Exit:
            		             	  if (status(exit_msg, 1, 1, 1, MSG_ERROR) == KEY_ENTER)
            		             	  {
	                                      app_end = 1;
	                                      goto end_ctrlo;
	                                  }
		                          status(CommandLineModeHelp, 0, 0, 0, MSG_OK);
	                                  break;

            		             default:
            		                  if (key) edit_putch(edt, key);
            		             	  break;
            		         }
		                 edit_setcursor(edt);
            		     }
			end_ctrlo:
			     panel_nooptimizations(current_panel);
			     panel_nooptimizations(other_panel);
			     status(NULL, 0, 0, 1, MSG_OK);
            		     if (app_end)
            		         continue;
            		     else
            		     {
				 if (FrameDisplay == OFF) tty_clrscr();
            		         goto restart;
            		     }

	    case BUILTIN_DeleteCmdLn:
	    		     signals(OFF);
			     uitclock_status(OFF);
	    		     edit_del(edt);
			     uitclock_status(ON);
	    		     break;
	    		     
            case BUILTIN_Copy:
			     uitclock_status(OFF);
            		     panel_action(current_panel, act_COPY, other_panel, NULL, 1);
			     uitclock_status(ON);
            		     break;

            case BUILTIN_RenameMove:
			     uitclock_status(OFF);
            		     panel_action(current_panel, act_MOVE, other_panel, NULL, 1);
			     uitclock_status(ON);
            		     break;
            		     
            case BUILTIN_MkDir:
	    		     signals(OFF);
			     uitclock_status(OFF);
            		     panel_action(current_panel, act_MKDIR, other_panel, NULL, 1);
			     uitclock_status(ON);
            		     break;

            case BUILTIN_Delete:
			     uitclock_status(OFF);
			     panel_action(current_panel, act_DELETE, other_panel, NULL, 1);
			     uitclock_status(ON);
            		     break;

	    case BUILTIN_FileDisplayMode:
	    		     signals(OFF);
			     uitclock_status(OFF);
	    		     for (i = 0; i < repeat_count; i++)
	    		         panel_action(current_panel, act_MODE, NULL, NULL, 1);
			     uitclock_status(ON);
	    		     break;

            case BUILTIN_Exit:
            		     signals(OFF);
			     uitclock_status(OFF);
            		     if (status(exit_msg, 1, 1, 1, MSG_ERROR) == KEY_ENTER)
                                 app_end = 1;
                             edit_setcursor(edt);
			     uitclock_status(ON);
                             continue;

            case BUILTIN_CopyFileToCmdLn:
			     signals(OFF);
			     uitclock_status(OFF);
                             edit_gettext(edt, cmdln);
                             len = strlen(cmdln);
                             if (len && isalnum(cmdln[len - 1]))
                             {
			         uitclock_status(ON);
                                 break;
                             }
                             strcpy(&cmdln[len], panel_getcurrentfilename(current_panel));
                             while (cmdln[len])
                                 edit_putch(edt, cmdln[len++]);
                             edit_putch(edt, ' ');
			     uitclock_status(ON);
                             break;
            
	    case BUILTIN_HistoryBack:
	    		     signals(OFF);
			     uitclock_status(OFF);
	    		     for (i = 0; i < repeat_count; i++)
	    		         edit_history(edt, EDIT_PREVIOUS);
			     uitclock_status(ON);
	    		     break;
	    		     
	    case BUILTIN_HistoryNext:
	    		     signals(OFF);
			     uitclock_status(OFF);
	    		     for (i = 0; i < repeat_count; i++)
	    		         edit_history(edt, EDIT_NEXT);
			     uitclock_status(ON);
	    		     break; 	     

	    case BUILTIN_SwitchPanels:
	    		     if ((repeat_count & 1) == 0) break;
	    		     signals(OFF);
			     uitclock_status(OFF);
			     panel_nooptimizations(current_panel);
			     panel_nooptimizations(other_panel);
			     panel_action(current_panel, act_SWITCH, other_panel, NULL, 1);
			     panel_action(other_panel, act_REFRESH, current_panel, (void *)-1, 1);
			     panel_action(current_panel, act_REFRESH, other_panel, (void *)-1, 1);
			     uitclock_status(ON);
			     break;

            default:	     if (key)
            		     {
            		         uitclock_status(OFF);
            		         edit_putch(edt, key);
            		         uitclock_status(ON);
            		     }
            		     break;
        }
	signals(ON);
        edit_setcursor(edt);
    }

    signals(OFF);
    edit_end(edt);
    panel_end(left_panel);
    panel_end(right_panel);
    uitclock(OFF);
    status_end();
    tty_end();
    removelog();

#ifdef HAVE_LINUX
    if (LinuxConsole)
    {
	tty_putscreen(screen);
	free(screen);
    }
    else
	tty_clrscr();
#else
    tty_clrscr();
#endif

    return 0;
}
