/* sysos2.c  -- OS/2 version of system.c */

/* Authors:
 *	Kai Uwe Rommel, rommel@ars.muc.de
 *	Greg R Roelofs, newt@uchicago.edu
 */

#include "config.h"
#include "vi.h"

#include <stdio.h>
#include <process.h>

#define	INCL_DOSPROCESS		/* doesn't exist in emx 0.8f...? */
#define INCL_VIO
#include <os2.h>

void raw_set_stdio(rawstate)
	int rawstate;
{
  	static int buffered = 0;

	if (!buffered)
	{
	  buffered = 1;
	  setvbuf(stdout, NULL, _IOFBF, BUFSIZ);
	}

	if (rawstate)
	  setmode(fileno(stdout), O_BINARY);
	else
	  setmode(fileno(stdout), O_TEXT);
}

int system(cmd)
	const	char	*cmd;	/* a command to run */
{
	int	status;	/* exit status of the command */

	if (cmd == o_shell)
	  status = spawnl(P_WAIT, o_shell, o_shell, 0);
	else
	  status = spawnl(P_WAIT, o_shell, o_shell, "/c", cmd, 0);

	return status;
}

static int pid[64];

int rpipe(cmd, in)
	char	*cmd;	/* the filter command to use */
	int	in;	/* the fd to use for stdin */
{
	int	r0w1[2];/* the pipe fd's */
	int 	old0, old1;

	if (pipe(r0w1) < 0)
		return -1;

	/* save the parent's stdin, redirect the child's */
	old0 = dup(0);
	fcntl(old0, F_SETFD, 1);
	dup2(in, 0);

	/* save the parent's stdout, redirect the child's */
	old1 = dup(1);
	fcntl(old1, F_SETFD, 1);
	dup2(r0w1[1], 1);

	/* let the parent forget the writing end of the pipe */
	close(r0w1[1]);
	/* and don't let the child inherit the reading end of the pipe */
	fcntl(r0w1[0], F_SETFD, 1);

	pid[r0w1[0]] = spawnl(P_NOWAIT, o_shell, o_shell, "/c", cmd, 0);

	/* restore parent's stdin */
	dup2(old0, 0);
	close(old0);

	/* restore parent's stdout */
	dup2(old1, 1);
	close(old1);

	/* return reading end of pipe, i.e. child's output */
	return r0w1[0];
}

int rpclose(fd)
	int	fd;
{
  	int	status;

	close(fd);
	waitpid(pid[fd], &status, 0);

	return status;
}

char *gethome(exe)
	char	*exe;	/* full pathname of the ELVIS.EXE file */
{
	static char	*home;

	if (!home)
	{
	  home = getenv("HOME");

	  if (!home)
	  {
	    PTIB pptib;
	    PPIB pppib;
	    char *path;

	    DosGetInfoBlocks(&pptib, &pppib);

	    path = pppib -> pib_pchenv;

	    while (*path)
	      path = strchr(path, 0) + 1;

	    home = path + 1;
	  }
	}

	return home;
}

void v_sr()   /* scroll reverse:  scroll whole screen down one line */
{
	CHAR cell[2];
	short len = sizeof(cell);

	refresh();   /* flush buffer before scrolling */
	VioReadCellStr(cell, &len, 0, 0, 0);   /* read current screen attr */
	cell[0] = ' ';
	VioScrollDn(0, 0, -1, -1, 1, cell, 0);
}

void audible_beep()   /* same pitch but shorter duration than ^G */
{
	DosBeep(800, 32);
}

static did_main_init = FALSE;
static ansi = FALSE;		/* assume no need to turn on ANSI */
static quit_attr = 0x07;	/* assume light gray on black, by default */

/* determine size of screen and set of attributes to use, and store
 * initial state */
void v_vio_init()
{
	char *str;
	CHAR cell[2];
	/* USHORT val = 2; */
	USHORT row, col, val=2;

	/* v_vio_init() is called from initscr(), which is called from main()
	 * before options and EXINIT are processed...uh oh.  So do our own
	 * quick and dirty pre-processing of EXINIT variable to see if vs or
	 * viomode is set there.
	 */
	str = getenv(EXINIT);
	if (str)
	{
		strlwr(str);
		if (strstr(str, "set viomode") != NULL ||
		    strstr(str, "set vm") != NULL)
		{
			*o_viomode = TRUE;
		}
	}
	if (!*o_viomode)	/* not allowed to use these functions */
	{
		return;
	}

	VioGetCurPos(&row, &col, 0);
	if (row > 0)
	{
		--row;	/* cursor is on fresh line after CR: check line above */
	}

	/* get attribute of first character of command line and save for exit */
        VioReadCellStr(cell, &val, row, 0, 0);
	if (val > 0)
	{
		quit_attr = cell[1];
	}

	VioGetAnsi(&val, 0);
	if (val == ANSI_OFF)
	{
		VioSetAnsi(ANSI_ON, 0);
		ansi = TRUE;
	}

	did_main_init = TRUE;
}

/* restore initial video state (more or less) */
void v_vio_restore()
{
	if (!did_main_init)
	{
		/* didn't save anything, so don't try to restore it */
		return;
	}

	if (ansi)	/* ANSI was off and we turned it on; turn off again */
	{
		CHAR cell[3] = {' ', (CHAR)quit_attr, '\0'};
		USHORT row, col, count;

		VioSetAnsi(ANSI_OFF, 0);
		VioGetCurPos(&row, &col, 0);
		count = COLS - col;
		VioWrtNCell(cell, count, row, col, 0);	/* cursor stays put */
	}
	else
	{
		static char sgr2[8] = {'0', '4', '2', '6', '1', '5', '3', '7'};
		char sgrbuf[24];

		/* build ANSI SGR string out of BIOS code of saved color via
		 * lookup table; honor foreground color (bits 0-2), background
		 * color (bits 4-6), and bold/normal attribute (bit 3), but
		 * forget about blinking attribute (bit 7):  too bad
		 */
		sprintf(sgrbuf, "\033[%c;3%c;4%cm", (quit_attr & 8)? '1' : '0', 
			sgr2[quit_attr & 0x07], sgr2[(quit_attr & 0x70) >> 4]);
		qaddstr(sgrbuf);
		refresh();
	}
}

#ifndef NO_CURSORSHAPE

static VIOCURSORINFO vioci;
static did_cursor_init = FALSE;

/* cursor big: set begin scan to end scan - 4 */
void v_cb()
{
	if (!did_cursor_init)
	{
		VioGetCurType(&vioci, 0);
		did_cursor_init = TRUE;
	}
	vioci.yStart = vioci.cEnd - 4;	/* cEnd never changes */
	VioSetCurType(&vioci, 0);
}

/* cursor small:  set begin scan to end scan - 1 */
void v_cs()
{
	if (!did_cursor_init)
	{
		VioGetCurType(&vioci, 0);
		did_cursor_init = TRUE;
	}
	vioci.yStart = vioci.cEnd - 1;	/* cEnd never changes */
	VioSetCurType(&vioci, 0);
}

#endif /* !NO_CURSORSHAPE */
