1: /************************************************************
*     Program: RMENU Menu Interpreter
*      Module: rmenu4.c
*        System-dependent Utility functions
*     Written by: Leor Zolman, 7/91
************************************************************/

#include "cmenu.h"
#include "rcmenu.h"

#if __STDC
#pragma hdrstop
#endif

#if DOS
#include <dir.h>

                        /* To set an explicit Near Heap size,    */
/* #define  HEAPSIZ 20000   /* define HEAPSIZ in the MAKEFILE   */
                        /* or un-comment this definition         */

static struct {
   int curdrive;
   char curpath[MAX_PATH];
} path_stack[MAX_PATH_STACK];

static int path_stackp = 0;

#ifdef HEAPSIZ
extern unsigned _heaplen = HEAPSIZ;
#endif
#endif


/************************************************************
 *                   CURSES FUNCTIONS                       *
 ************************************************************/

/************************************************************
 * init_win():
 * Initialize Curses system.
 ************************************************************/

Void init_win()
{
                     /* initialize screen, and check for failure */
   if (initscr() == INIT_FAIL)
   {
      fprintf(stderr, "initscr failed!\n");
      exit(1);
   }

   tty_curses();                     /* set tty modes for curses */
   hlight_end();                     /* set colors under DOS     */

#if DOS
   strcpy(SysShell, getenv("COMSPEC"));
#else
   strcpy(SysShell, SHELL_ESC);
#endif

   return;
}


/************************************************************
 * close_win(): 
 * Terminate Curses system
 ************************************************************/

Void close_win()
{
#if DOS
   attrset(A_COLOR(DOS_FCOLOR,DOS_BCOLOR));
#endif
   clear();
   noraw();
   refresh();                /* This is so cursor shows back up  */
   endwin();
}


/************************************************************
 * tty_shell()
 * Set tty mode for a shell call
 ************************************************************/

Void tty_shell()
{
#if XENIX || (UNIX && OLD_CURSES)
      resetty();
#else
      attrset(A_COLOR(DOS_FCOLOR,DOS_BCOLOR));
      clear();
      refresh();
      endwin();
#endif
   return;
}


/************************************************************
 * tty_curses()
 * Set tty mode for curses
 ************************************************************/
 
Void tty_curses()
{                                        /* set up tty modes     */
   raw();                                /* ignore ^C, etc.      */
   nonl();
   noecho();                             /* do not echo input    */
   keypad(stdscr, TRUE);                       /* enable keypad  */
#if DOS
   attrset(A_COLOR(M_FCOLOR, M_BCOLOR));
#endif
   return;
}


/************************************************************
 * hlight_on()
 * Set to standout mode (Reverse colors for DOS)
 ************************************************************/

Void hlight_on()
{
#if DOS
   attrset(A_COLOR(MREV_FCOLOR, MREV_BCOLOR));
#else
   standout();
#endif
}


/************************************************************
 * hlight_end()
 * Turn off standout mode (Normal colors for DOS)
 ************************************************************/

Void hlight_end()
{
#if DOS
   attrset(A_COLOR(M_FCOLOR, M_BCOLOR));
#else
   standend();
#endif
}


/************************************************************
 *             PATH MANAGEMENT FUNCTIONS                    *
 ************************************************************/

/************************************************************
 * push_path()
 * DOS only: save drive and path for later restoration, and
 *    select new drive based on new path
 *  Unix: a no-op, since sub-shells cannot affect parent path
 ************************************************************/

Void push_path()
{
#if DOS
   if (path_stackp == MAX_PATH_STACK)
      fatal("Maximum stack nesting reached");
   else
   {
      path_stack[path_stackp].curdrive = getdisk();
      getcwd(path_stack[path_stackp].curpath, MAX_PATH);
      path_stackp++;
   }
#endif   
   return;
}


/************************************************************
 * pop_path()
 * DOS only: restore drive and path from path stack
 *  Unix: a no-op, since sub-shells cannot affect parent path
 ************************************************************/

Void pop_path()
{
#if DOS
      path_stackp--;
      setdisk(path_stack[path_stackp].curdrive);
      chdir(path_stack[path_stackp].curpath);
#endif   
   return;
}


/************************************************************
 * trans_slash():
 * Translate forward slashes (/) into backslashes (\) in
 * DOS pathnames
 ************************************************************/

static char *trans_slash(str)
char *str;
{
   char *cptr;
   
#if DOS
   for (cptr = str; *cptr; cptr++)
      if (*cptr == '/')
         *cptr = '\\';
#endif

   return str;
}


/************************************************************
 * make_path():
 * Construct new path based on old default path, old_path,
 * and current incremental path, incr_path (which might be
 * absolute)
 ************************************************************/

char *make_path(old_path, incr_path)
char *old_path, *incr_path;
{
   static char newpath[MAX_PATH];
   
   trans_slash(old_path);
   trans_slash(incr_path);

   if (*incr_path == '/' || *incr_path == '\\')/* If path abs-   */
      strcpy(newpath, incr_path);    /* olute, then it's full    */
#if DOS
   else if (incr_path[1] == ':')     /* drive designator? if so, */
      strcpy(newpath, incr_path);    /* treat as ABSOLUTE path   */
#endif
   else
   {
      strcpy(newpath, old_path);         /* start with old path  */
      if (*incr_path && *newpath)        /* add path delimiter   */
#if DOS                                  /*    (if necessary)    */
         strcat(newpath, "\\");
#else
         strcat(newpath, "/");
#endif

      strcat(newpath, incr_path);        /* and append new path  */
   }
   return newpath;
}


/************************************************************
 * make_cmd():
 * Construct a system command string based on a given path
 * and action string. If the path is non-null, generate a
 * leading "cd" command to change the current directory.
 * If running under DOS, then generate a drive selection
 * statement as well to change the current drive.
 ************************************************************/

char *make_cmd(path, action)
char *path, *action;
{
   static char cmd_line[MAX_CMD];
   char strtemp[10];

   trans_slash(path);

   if (*path)                                 /* select new path */
   {
      sprintf(cmd_line, "cd %s; ", path);
#if DOS
      if (path[1] == ':')                    /* select new drive */
      {
         sprintf(strtemp, "%c:; ", path[0]);
         strcat(cmd_line, strtemp);
      }
#endif
      strcat(cmd_line, action);                   /* action text */
   }
   else                             /* no new path: trivial case */
      sprintf(cmd_line, "%s", action);

   return cmd_line;
}


/************************************************************
 * system0(): Execute a command via a system() call.
 *
 * If Unix, just pass the command string to a shell.
 *
 * if DOS, pass each sub-command (delimited by ;) to
 *       a command processor
 ************************************************************/

#if UNIX || XENIX                        /* Unix version trivial */

int system0(cmd)
char *cmd;
{
   return system(cmd);
}

#endif                                   /* end of Unix version  */

#if DOS
int system0(cmd)
char *cmd;
{
   char subcmd[MAX_CMD];
   char savcmd[MAX_CMD], *cmdp;
   int i, retval;
   char *cp = savcmd;
   char c, lastc;

   strcpy(savcmd, cmd);
   while (*cp)                       /* if more subcommands left */
   {
      if (*cp == ';')
         cp++;
      cmdp = cp;                     /* ptr to start of command  */
      while (*cp && *cp != ';')
         cp++;                       /* find end of subcommand   */
      lastc = *cp;                   /* save terminating char    */
      *cp = '\0';                    /* delimit subcommand       */
      retval = system(cmdp);             /* pass it to system()  */
      *cp = lastc;                   /* restore last terminator  */
   }
   return retval;
}
#endif                               /* end of DOS version       */
