/* vi:ts=4:sw=4
 *
 * VIM - Vi IMproved
 *
 * Code Contributions By:	Bram Moolenaar			mool@oce.nl
 *							Tim Thompson			twitch!tjt
 *							Tony Andrews			onecom!wldrdg!tony 
 *							G. R. (Fred) Walter		watmath!watcgl!grwalter 
 */

#define EXTERN
#include "vim.h"
#ifdef JP
#include "jp.h"
#endif
#include "globals.h"
#include "proto.h"
#include "param.h"

static void usage __PARMS((int));

	static void
usage(n)
	int n;
{
	register int i;
	static char *(use[]) = {"[file ..]\n",
							"-t tag\n",
							"+[command] file ..\n",
							"-c {command} file ..\n",
							"-e [errorfile]\n"};
	static char *(errors[]) =  {"Unknown option\n",			/* 0 */
								"Too many arguments\n",		/* 1 */
								"Argument missing\n",		/* 2 */
								};

	fprintf(stderr, errors[n]);
	fprintf(stderr, "usage:");
	for (i = 0; ; ++i)
	{
#ifdef JP
		fprintf(stderr, " jvim [options] ");
#else
		fprintf(stderr, " vim [options] ");
#endif
		fprintf(stderr, use[i]);
		if (i == (sizeof(use) / sizeof(char *)) - 1)
			break;
		fprintf(stderr, "   or:");
	}
#ifdef AMIGA
	fprintf(stderr, "\noptions: -v -n -b -r -x -d device -s scriptin -w scriptout -T terminal\n");
#else
	fprintf(stderr, "\noptions: -v -n -b -r -s scriptin -w scriptout -T terminal\n");
#endif
	mch_windexit(1);
}

#ifdef USE_LOCALE
# include <locale.h>
#endif

	void
main(argc, argv)
	int				argc;
	char		  **argv;
{
	char		   *initstr;		/* init string from the environment */
	char		   *term = NULL;	/* specified terminal name */
	char		   *fname = NULL;	/* file name from command line */
	char		   *command = NULL;	/* command from + option */
	char		   *tagname = NULL;	/* tag from -t option */
	int 			c;
	int				doqf = 0;
	int				i;
	int				bin_mode = FALSE;	/* -b option used */

#ifdef DEBUG
# ifdef MSDOS
	OPENDEBUG("#debug#");
# else
	OPENDEBUG("/tmp/debug/vim");
# endif
#endif

/*
 * Check if we have an interactive window.
 * If not, open one with a newcli command (needed for :! to work).
 * check_win will also handle the -d argument (for the Amiga).
 */
	check_win(argc, argv);

/*
 * If the executable is called "view" we start in readonly mode.
 */
#ifdef JP
	if (strcmp(gettail(argv[0]), "jview") == 0
	 || strcmp(gettail(argv[0]), "view")  == 0)
#else
	if (strcmp(gettail(argv[0]), "view") == 0)
#endif
	{
		readonlymode = TRUE;
		p_ro = TRUE;
		p_uc = 0;
	}

	++argv;
	/*
	 * Process the command line arguments
	 * 		'-s scriptin'	read from script file
	 *		'-w scriptout'	write to script file
	 *		'-v'			view
	 *		'-b'			binary
	 *		'-n'			no .vim file
	 *		'-r'			recovery mode
	 *		'-x'			open window directly, not with newcli
	 *		'-T terminal'	terminal name
	 */
	while (argc > 1 && argv[0][0] == '-' &&
			strchr("vnbrxswTd", c = argv[0][1]) != NULL && c)
	{
		--argc;
		switch (c)
		{
		case 'v':
			readonlymode = TRUE;
			p_ro = TRUE;
			/*FALLTHROUGH*/

		case 'n':
			p_uc = 0;
			break;

		case 'b':
			bin_mode = TRUE;		/* postpone to after reading .exrc files */
			break;

		case 'r':
			recoverymode = 1;
			break;
		
		case 'x':
			break;	/* This is ignored as it is handled in check_win() */

		default:	/* options with argument */
			++argv;
			--argc;
			if (argc < 1)
				usage(2);

			switch (c)
			{
			case 's':
				if ((scriptin[0] = fopen(argv[0], READBIN)) == NULL)
				{
						fprintf(stderr, "cannot open %s for reading\n", argv[0]);
						mch_windexit(2);
				}
				break;
			
			case 'w':
				if ((scriptout = fopen(argv[0],
#ifdef MSDOS
													"ab"
#else
													"a"
#endif
														)) == NULL)
				{
						fprintf(stderr, "cannot open %s for output\n", argv[0]);
						mch_windexit(2);
				}
				break;

/*
 * The -T term option is always available and when TERMCAP is supported it
 * overrides the environment variable TERM.
 */
			case 'T':
				term = *argv;
				break;
			
		/*	case 'd':		This is ignored as it is handled in check_win() */
			}
		}
		++argv;
	}

	/*
	 * Allocate space for the generic buffer
	 */
#ifdef JP
	if ((IObuff = alloc(IOSIZE * 2)) == NULL)
#else
	if ((IObuff = alloc(IOSIZE)) == NULL)
#endif
		mch_windexit(0);

	/* note that we may use mch_windexit() before mch_windinit()! */
	mch_windinit();
	set_init();			/* after mch_windinit because Rows is used */

	/*
	 * Process the other command line arguments.
	 */
	if (argc > 1)
	{
		c = argv[0][1];
		switch (argv[0][0])
		{
		  case '-':
		    switch (c)
			{
		  	case 'e':			/* -e QuickFix mode */
				switch (argc)
				{
					case 2:
							if (argv[0][2])		/* -eerrorfile */
								p_ef = argv[0] + 2;
							break;				/* -e */

					case 3:						/* -e errorfile */
							++argv;
							p_ef = argv[0];
							break;

					default:					/* argc > 3: too many arguments */
							usage(1);
				}
				doqf = 1;
				break;

			case 'c':			/* -c {command} file .. */
				if (argc <= 3)
					usage(2);
				++argv;
				--argc;
				command = &(argv[0][0]);
				goto getfiles;

			case 't':			/* -t tag  or -ttag */
				switch (argc)
				{
					case 2:
							if (argv[0][2])		/* -ttag */
							{
								tagname = argv[0] + 2;
								break;
							}
							usage(2);			/* argument missing */
							break;

					case 3:						/* -t tag */
							++argv;
							tagname = argv[0];
							break;

					default:					/* argc > 3: too many arguments */
							usage(1);
				}
				break;

			default:
				usage(0);
			}
			break;

		  case '+': 			/* + or +{number} or +/{pat} or +{command} */
			if (argc < 3)		/* no filename */
					usage(2);
			if (c == NUL)
				command = "$";
			else
				command = &(argv[0][1]);

getfiles:
			++argv;
			--argc;
			/*FALLTHROUGH*/

		  default:				/* must be a file name */
#if !defined(UNIX)
			ExpandWildCards(argc - 1, argv, &numfiles, &files, TRUE, TRUE);
			if (numfiles != 0)
			{
				fname = files[0];
				files_exp = TRUE;
			}
#else
			files = argv;
			numfiles = argc - 1;
			fname = argv[0];
#endif
			if (numfiles > 1)
				printf("%d files to edit\n", numfiles);
			break;
		}
	}

	RedrawingDisabled = TRUE;
	filealloc();				/* Initialize storage structure */
	init_yank();				/* init yank buffers */
	termcapinit(term);			/* get terminal capabilities */

#ifdef USE_LOCALE
	setlocale(LC_ALL, "");		/* for ctype() and the like */
#endif

#if defined(MSDOS) && !defined(DOSGEN)
	/* default mapping for some often used keys */
	domap(0, "#1 :help\r", NORMAL);			/* F1 is help key */
	domap(0, "\316R i", NORMAL);			/* INSERT is 'i' */
	domap(0, "\316S \177", NORMAL);			/* DELETE is 0x7f */
	domap(0, "\316G 0", NORMAL);			/* HOME is '0' */
	domap(0, "\316w H", NORMAL);			/* CTRL-HOME is 'H' */
	domap(0, "\316O $", NORMAL);			/* END is '$' */
	domap(0, "\316u L", NORMAL);			/* CTRL-END is 'L' */
	domap(0, "\316I \002", NORMAL);			/* PageUp is '^B' */
	domap(0, "\316\204 1G", NORMAL);		/* CTRL-PageUp is '1G' */
	domap(0, "\316Q \006", NORMAL);			/* PageDown is '^F' */
	domap(0, "\316v G", NORMAL);			/* CTRL-PageDown is 'G' */
			/* insert mode */
	domap(0, "#1 \017:help\r", INSERT);		/* F1 is help key */
	domap(0, "\316R \033", INSERT);			/* INSERT is ESC */
			/* note: extra space needed to avoid the same memory used for this
			   and the one above, domap() will add a NUL to it */
	domap(0, "\316S  \177", INSERT+CMDLINE);	/* DELETE is 0x7f */
	domap(0, "\316G \017""0", INSERT);		/* HOME is '^O0' */
	domap(0, "\316w \017H", INSERT);		/* CTRL-HOME is '^OH' */
	domap(0, "\316O \017$", INSERT);		/* END is '^O$' */
	domap(0, "\316u \017L", INSERT);		/* CTRL-END is '^OL' */
	domap(0, "\316I \017\002", INSERT);		/* PageUp is '^O^B' */
	domap(0, "\316\204 \017\061G", INSERT);	/* CTRL-PageUp is '^O1G' */
	domap(0, "\316Q \017\006", INSERT);		/* PageDown is '^O^F' */
	domap(0, "\316v \017G", INSERT);		/* CTRL-PageDown is '^OG' */
#endif

/*
 * get system wide defaults (for unix)
 */
#ifdef DEFVIMRC_FILE
	dosource(DEFVIMRC_FILE);
#endif

/*
 * Try to read initialization commands from the following places:
 * - environment variable VIMINIT
 * - file s:.vimrc ($HOME/.vimrc for Unix)
 * - environment variable EXINIT
 * - file s:.exrc ($HOME/.exrc for Unix)
 * The first that exists is used, the rest is ignored.
 */
#ifdef SYSJVIMRC_FILE	/* JP */
	if ((initstr = (char *)vimgetenv("JVIMINIT")) != NULL)
		docmdline((u_char *)initstr);
	else if (!dosource(SYSJVIMRC_FILE))
	{}
	else
#endif
	if ((initstr = (char *)vimgetenv("VIMINIT")) != NULL)
		docmdline((u_char *)initstr);
	else if (dosource(SYSVIMRC_FILE))
	{
		if ((initstr = (char *)vimgetenv("EXINIT")) != NULL)
			docmdline((u_char *)initstr);
		else
			dosource(SYSEXRC_FILE);
	}

/*
 * Read initialization commands from ".vimrc" or ".exrc" in current directory.
 * This is only done if the 'exrc' option is set.
 * Because of security reasons we disallow shell and write commands now,
 * except for unix if the file is owned by the user or 'secure' option has been
 * reset in environmet of global ".exrc" or ".vimrc".
 * Only do this if VIMRC_FILE is not the same as SYSVIMRC_FILE or DEFVIMRC_FILE.
 */
	if (p_exrc)
	{
#ifdef UNIX
		struct stat s;
#endif
		i = 1;
#ifdef JVIMRC_FILE	/* JP initialize file */
#ifdef UNIX
			/* if ".jvimrc" file is not owned by user, set 'secure' mode */
		if (stat(JVIMRC_FILE, &s) || s.st_uid != getuid())
			secure = p_secure;
#else
		secure = p_secure;
#endif

		if (fullpathcmp(SYSJVIMRC_FILE, JVIMRC_FILE)
#ifdef DEFVIMRC_FILE
				&& fullpathcmp(DEFVIMRC_FILE, JVIMRC_FILE)
#endif
				)
			i = dosource(JVIMRC_FILE);
#endif /* JVIMRC_FILE */

#ifdef UNIX
			/* if ".vimrc" file is not owned by user, set 'secure' mode */
		if (i && (stat(VIMRC_FILE, &s) || s.st_uid != getuid()))
				secure = p_secure;
#endif

		if (i && fullpathcmp(SYSVIMRC_FILE, VIMRC_FILE)
#ifdef DEFVIMRC_FILE
				&& fullpathcmp(DEFVIMRC_FILE, VIMRC_FILE)
#endif
				)
			i = dosource(VIMRC_FILE);
#ifdef UNIX
		if (i)
		{
			struct stat s;

				/* if ".exrc" file is not owned by user set 'secure' mode */
			if (stat(EXRC_FILE, &s) || s.st_uid != getuid())
				secure = p_secure;
			else
				secure = 0;
		}
#endif
		if (i && fullpathcmp(SYSEXRC_FILE, EXRC_FILE))
			dosource(EXRC_FILE);
	}
#ifdef JP
	/*
	 *	read Kanji Code from environment JMASK
	 */
	if ((initstr = (char *)vimgetenv("JMASK")) != NULL)
	{
		if (strchr(JP_STR, initstr[0]) &&
			strchr(JP_STR, initstr[1]) &&
			strchr(JP_STR, initstr[2]) && initstr[3] == NUL)
		{
			int i;
			for(i = 0; i < 4; i++)
				p_jp[i] = initstr[i];
		}
		else
			emsg2("Environment JMASK(%s) ignored", initstr);
	}
#endif

/*
 * Call settmode and starttermcap here, so the T_KS and T_TS may be defined
 * by termcapinit and redifined in .exrc.
 */
	settmode(1);
	starttermcap();

	if (secure == 2)		/* done something that is not allowed */
		wait_return(TRUE);		/* must be called after settmode(1) */
	secure = 0;

#ifdef AMIGA
	fname_case(fname);		/* set correct case for file name */
#endif
	setfname(fname, NULL);
	maketitle();

	if (bin_mode)			/* -b option used */
	{
		p_bin = 1;			/* binary file I/O */
		p_tw = 0;			/* no automatic line wrap */
		p_tx = 0;			/* no text mode */
		p_ta = 0;			/* no text auto */
		p_ml = 0;			/* no modelines */
		p_et = 0;			/* no expand tab */
	}

/*
 * Start putting things on the screen.
 * Clear screen first, so file message will not be cleared.
 */
	starting = FALSE;
	screenclear();
#ifdef JP
	jp_init();
#endif
#ifdef JPFEP
	if (p_ja)
		switch(*p_ji)
		{
			case 'j':
				KanjiInput = TRUE;
				goto modeset;
			case 'a':
				KanjiInput = FALSE;
modeset:
				fep_mode_switch(KanjiInput);
				break;
		}
#endif
#ifdef FEPCTRL
	if (p_ja && p_fc)
	{
		switch(*p_ji)
		{
			case 'j':
				fep_force_on();
				break;
			case 'a':
				fep_force_off();
				break;
		}
		fep_off();
	}
#endif

	if (Filename != NULL)
		readfile(Filename, sFilename, (linenr_t)0, TRUE);
	else
		msg("Empty Buffer");
	UNCHANGED;

	setpcmark();
	if (!tagname)
		startscript();				/* start writing to auto script file */

	if (recoverymode && !scriptin[curscript])	/* first do script file, then recover */
		openrecover();

	/* position the display and the cursor at the top of the file. */
	Topline = 1;
	Curpos.lnum = 1;
	Curpos.col = 0;
	Cursrow = Curscol = 0;

	if (doqf && qf_init())		/* if reading error file fails: exit */
		mch_windexit(3);

	if (command)
		docmdline((u_char *)command);
	/*
	 * put the :ta command in the stuff buffer here, so that it will not
	 * be erased by an emsg().
	 */
	if (tagname)
	{
		stuffReadbuff(":ta ");
		stuffReadbuff(tagname);
		stuffReadbuff("\n");
	}

	RedrawingDisabled = FALSE;
	updateScreen(NOT_VALID);

		/* start in insert mode (already taken care of for :ta command) */
	if (p_im && stuff_empty())
		stuffReadbuff("i");
/*
 * main command loop
 */
	for (;;)
	{
		if (got_int)
		{
			(void)vgetc();				/* flush all buffers */
			got_int = FALSE;
		}
		adjustCurpos();
		if (stuff_empty())				/* only when no command pending */
		{
			cursupdate();	/* Figure out where the cursor is based on Curpos. */
			showruler(0);

			if (Visual.lnum)
				updateScreen(INVERTED);		/* update inverted part */
			if (must_redraw)
				updateScreen(VALID);
			setcursor();
		}

		normal();						/* get and execute a command */
	}
	/*NOTREACHED*/
}

	void
getout(r)
	int 			r;
{
	windgoto((int)Rows - 1, 0);
	outchar('\r');
	outchar('\n');
	mch_windexit(r);
}


syntax highlighted by Code2HTML, v. 0.9.1