/* -*-C-*-
 * gnuclient.c	-- pbreton Thu Jan 25 1996
 *
 * Client code to allow local and remote editing of files by GNU Emacs.
 *
 * This file is not part of GNU Emacs. 
 * 
 * Copying is permitted under those conditions described by the GNU
 * General Public License.
 *
 * Copyright (C) 1996 Peter Breton
 *
 * Author: Peter Breton (pbreton@cs.umb.edu)
 * Based heavily on Andy Norman's gnuserv (ange@hplb.hpl.hp.com), 
 * which in turn was based on 'etc/emacsclient.c' from the GNU 
 * Emacs 18.52 distribution.
 *
 * Modifications: Nico Francois (nico.francois@scala.nl) 
 *                Mon Jun 3 1996
 * See comment in gnuserv.c.
 *
 * Modifications: Nico Francois (nico.francois@scala.nl) 
 *                Sun Sep 15 1996
 * If WIN_VERSION is defined the -q (quick) flag is always turned on.
 * Will be defined when the client program is compiled and then linked
 * as a windows progranm.
 *
 * Modifications: Nico Francois (nico.francois@scala.nl) 
 *                Mon Oct 7 1996
 * filename_expand() has been modified to always make sure it has the
 * long filename of a file.
 *
 *
 * $Log: gnuclient.c,v $
 * Revision 1.1  1996/01/28 16:33:03  peter
 * Initial revision
 *
 */

static char rcsid [] = "$Header$";

#include "gnuserv.h" 
#include "getopt.h" 

/* Ascii codes in decimal */
#define FORWARD_SLASH   47
#define BACKWARD_SLASH  92

/* current working directory when calculated */
static char cwd[MAXPATHLEN+2]; 

/* ptr into valid bit of cwd above */
static char * cp = NULL;       

/* Name of this program */
static char * progname;

/*
 *  Returns the current working directory
 */
char * 
get_current_working_directory()
{
  /* haven't calculated it yet */
  if (cp == NULL) {		      
    if (0 == GetCurrentDirectory(MAXPATHLEN + 2, cwd)) {

      fprintf(stderr,
	      "%s: unable to get current working directory\n",
	      progname);
      exit(1);
    }; /* if */
    
  }; /* if */

  return cp;
    
} /* get_current_working_directory */


/*
 * filename_expand -- try to convert the given filename into a 
 * fully-qualified pathname.
 */
int
filename_expand(fullpath, filename)
     char *fullpath;  /* returned full pathname */
     char *filename;  /* filename to expand */
{
	WIN32_FIND_DATA finddata;
	HANDLE handle;
	char *p, *fname;

	if (0 == GetFullPathName (filename, MAXPATHLEN + 2, fullpath, &fname)) {
		fprintf(stderr,
				"Unable to get full pathname for %s\n",
				filename);
		return (0);
		}      

    /* Backslashes confuse emacs */
    for (p = fullpath; *p; p++) {
		if (BACKWARD_SLASH == *p)
			*p = FORWARD_SLASH;
		}

	/* Since GetFullPathName doesn't always seem to return the long
	   filename (as documented) we get it ourselves. */
	handle = FindFirstFile (filename, &finddata);
	if (handle == INVALID_HANDLE_VALUE) {
		fprintf(stderr,
				"Unable to get file info for %s\n",
				filename);
		return (0);
		}
	strcpy (fname, finddata.cFileName);
	FindClose (handle);

	return (1);
} /* filename_expand */

void
main(argc,argv)
     int argc;
     char *argv[];
{
  int    starting_line = 1;              /* line to start editing at */
  char   command[MAXPATHLEN+50];	 /* emacs command buffer */
  char   fullpath[MAXPATHLEN+1];	 /* full pathname to file */
  char   clientidstr[20];
  int    qflg   = 0;			 /* quick edit */
  int    dbgflg = 0;			 /* debug flag */
  int    errflg = 0;			 /* option error */
  int    c;				 /* char from getopt */
  HANDLE h;			         /* mailslot handle */
  char * hostarg = GNUSERV_DEFAULT_HOST; /* hostname */
  char * basecommand;
  HANDLE resultslot;
  DWORD  clientid = GetCurrentProcessId();
  BOOL   noresult = FALSE;

  progname = argv[0];

#ifdef WIN_VERSION
  qflg++;
#endif

  /* Parse arguments */
  while ((c = getopt(argc, argv, "h:qd?" )) != EOF)
    switch (c) {
    case 'q':					
      qflg++;
      break;

    case 'd':
      dbgflg++;
      break;

    case 'h':
      hostarg = optarg;
	  // FIX! We don't support results from a server on another host just yet.
	  noresult = TRUE;
      break;

    case '?':
      errflg++;
    };
  
  /* Print a usage message and quit */   
  if (errflg) {
    fprintf(stderr,
	    "usage: %s [-q] [-d] [-h hostname] [[+line] path] ...\n",
	    progname);
    exit (1);
  }; /* if */

  // First create mailslot to receive result
  resultslot = CreateGnuServSlot (TRUE, clientid);
  if (INVALID_HANDLE_VALUE == resultslot)
	  exit (1);

  /* Try to connect to the mailslot. Dies on failure  */
  h = ConnectToMailslot (hostarg, FALSE, 0);
  if (INVALID_HANDLE_VALUE == h)
	  exit (1);

  /* Send a lisp command... */
  basecommand = (qflg) ?
    "(server-edit-files-quickly '(" : "(server-edit-files '("; 

  sprintf (clientidstr, "C:%d ", clientid);
  if (!SendString (h, clientidstr)) exit (1);

  SendString (h, basecommand);

  if (dbgflg)
    printf(basecommand);

  /* ...followed by file names to the server process */
  for (; optind < argc; optind++)
  {
    if (*argv[optind] == '+')
      starting_line = atoi(argv[optind]);
    else
    {
      if (filename_expand(fullpath,argv[optind]))
      {
        sprintf(command,"(%d . \"%s\")",starting_line, fullpath);
	SendString (h, command);
	if (dbgflg)
	  printf(command);
	starting_line = 1;
      }
    } /* else */
  } /* for */

  /* Finish off the sexp and send an EOT */
  SendString (h, "))");
  SendString (h, EOT_STR);

  if (dbgflg)
    printf("))");

  /* Disconnect */
  DisconnectFromMailslot (h);

  // Now wait for result, then exit.
  if (!noresult) WaitForServerResult (resultslot, FALSE);
  DisconnectFromMailslot (resultslot);

  exit(0);

} /* main */
