/* vi:ts=4:sw=4
 *
 * VIM - Vi IMitation 		Extension for Japanese Frontend Processor
 *
 * Code Contributions By:	Atsushi Nakamura	ann@mrit.mei.co.jp
 */

#include "vim.h"

#ifdef JP
#include "globals.h"
#include "proto.h"
#include "param.h"
#include "jp.h"

#define ISKFUNC(c)		((c & 0x60) == 0)
static char *saved_line = NULL;
#endif

#ifdef JPFEP
static char fep_buf[MAX_COLUMNS * 2 + 1] = "", *fbp = fep_buf;
static void fep_delchars();
static int fep_insstr();

#ifdef ONEW

static char kanakan_buf[MAX_COLUMNS + 1] = "";
static char hira_buf[MAX_COLUMNS + 1] = "";
static int  kanakan_len = 0;
static int  freq_save = FALSE;

void Onew_putmsg(), Onew_kakutei();
void Onew_RK_init(), Onew_RK_cmode_set(), Onew_KK_freqsave();
int Onew_RK_imode(), Onew_kanakan(), Onew_romkan();
char *Onew_version();

#define FUNCMASK		0xffffff00

	int
ONEW_GETCHAR()
{
	u_char c;

	c = (u_char)vgetc();

	if (c == K_ZERO || c == Ctrl('\\'))		/* convert key */
		return p_oh ? NUL : (K_ZERO | FUNCMASK);

	if (IsKanji(c) && ISKFUNC(c))			/* function key */
		return c | FUNCMASK;

	if (p_okc && isupper(c))
	{
		ONEW_KAKUTEI(c);
		return p_oh ? c : tolower(c);
	}

	return c;
}

	int
ONEW_PEEKCHAR(timeout)
	int *timeout;
{	int c;

	if(!( c = vpeekc() ))
		*timeout = -1;
	return c;
}

static char *modep = "";

	void
ONEW_DISP_ROMKANMODE(mode, help, imode)
	int imode;
	char *mode, *help;
{
	int rk;
	char *mchrs, *cp;
	static char modebuf[20];
	static int  oldimode = -1;

	if (!mode)
	{
		oldimode = -1;
		Onew_putmsg(FALSE, "");
		return;
	}

	rk = Onew_RK_imode();

	if (State == CMDLINE)
	{
		cmd_message(rk ? mode : "");

		modep = mode;
		if (oldimode != imode)
		{ 
			oldimode = imode;
			if (rk)
			    Onew_putmsg(rk, "%s %s", help, Onew_version());
			else
			    Onew_putmsg(rk, "");
		}
		cursorcmd();
		return;
	}

	switch(State)
	{
		case INSERT:
			mchrs = "[]";
			break;
		case REPLACE:
			mchrs = "<>";
			break;
		case NOMAPPING:
			mchrs = "()";
			break;
		default:
			mchrs = "//";
			break;
	}

	sprintf(modebuf, p_ri ? "%c<-%s": "%c%s", *mchrs++, mode + 1);
	cp = modebuf + strlen(modebuf) - 1;
	*cp++ = *mchrs;
	if (p_ja) *cp++ = *p_ji;
	*cp = NUL;

	if (oldimode != imode)
	{
		oldimode = imode;

		if (p_fm)
		{
			screen_msg(FALSE, NULL);
			Onew_putmsg(FALSE, Recording ? "[%s].%c...  %s/%s"
										 : "[%s]:%c     %s/%s",
							help, *p_jc, JpVersion, Onew_version());
		}
		else
			Onew_putmsg(rk, Recording ? "%s%s   ...%c   %s/%s"
									  : "%s%s      %c   %s/%s",
					modebuf, help, *p_jc, JpVersion, Onew_version());
	}

	if (p_fm && rk)
		screen_msg(rk, modebuf);

	cursupdate();
	setcursor();
}

	void
ONEW_DISP_KANAHALVES(s)
	char *s;
{
	if (State == CMDLINE)
	{
		cmd_insertstr(s);
		cmd_delchars(strlen(s));
		cursorcmd();
	}
	else
	{
		int mode, n;
		char *cp;

		mode = State;
		State = INSERT;

		for(cp = s, n = 0; *cp; cp++, n++)
			insertchar(*cp, NUL);
		if (p_ri)
			KconvEnd += n;
		else
			Curpos.col -= n;

		cursupdate();
		setcursor();
		updateline();

		for(cp = s; *cp; cp++)
			delchar(FALSE);

		if (p_ri)
			KconvEnd -= n;

		State = mode;
	}
}

	int
ONEW_DISP_KANAKANB(so, left, cur, right)
	int so;
	char *left, *cur, *right;
{
	int mode = State;

	sprintf(kanakan_buf, "%s%s%s", left, cur, right);

	if (State == CMDLINE)
	{
		Kconvlnum	  = -1;
		KconvStart = KconvEnd = 0;
		KconvAltStart = strlen(left);					/* Reverse start    */
		KconvAltEnd   = KconvAltStart + strlen(cur);	/* Reverse end      */
	}
	else
	{
		if (State !=REPLACE)
			State = INSERT;

		Kconvlnum     = Curpos.lnum;
		KconvStart    = Curpos.col;								/* UL start */
		KconvAltStart = KconvStart   + strlen(p_ri?right:left);	/* RV start	*/
		KconvAltEnd   = KconvAltStart+ strlen(cur);				/* RV end	*/
		KconvEnd      = KconvAltEnd  + strlen(p_ri?left:right);	/* UL end   */
	}

	kanakan_len = fep_insstr(kanakan_buf);
	if (State == CMDLINE)
		cmd_message(modep);
	fep_delchars(kanakan_len);

	windgoto(Rows - 1, Columns - 1);

	State = mode;
	return 0;
}

int	onew_noredraw = FALSE;	/* to avoid textwidth folding */

	int
ONEW_KANAKAN(ch)
	int ch;
{
	if (fbp != fep_buf)
	{
		fep_delchars(strlen(fep_buf));
		strncpy(hira_buf, fep_buf, fbp - fep_buf);
		hira_buf[fbp - fep_buf] = NUL;

		ch = Onew_kanakan(ch, fep_buf, 0, fbp - fep_buf);
		freq_save = TRUE;

		strcpy(fep_buf, kanakan_buf);
		fbp = fep_buf + fep_insstr(fep_buf);

		Onew_kakutei(ch);
		if (ch != ESC && ch != TAB) ch = NUL;
	}

	return ch;
}

	int
ONEW_KAKUTEI(ch)
	int ch;
{
	int fix = FALSE;

	if (fbp != fep_buf)
	{
		if (ch == BS || ch == DEL)
		{
			fep_delchars(fbp - fep_buf);

			strcpy(fep_buf, hira_buf);
			fbp = fep_buf + strlen(fep_buf);
	
			if (State == CMDLINE)
			{
				Kconvlnum     =  0;
				KconvAltStart = 
				KconvAltEnd   = -1;
			}
			else
			{
				Kconvlnum  = Curpos.lnum;
				KconvStart = Curpos.col;
				KconvEnd   = KconvStart + (fbp - fep_buf);
			}

			fep_insstr(fep_buf);
		}
		else
		{
			*fbp = NUL;
			AppendToRedobuff(fep_buf);

			*(fbp = fep_buf)  = hira_buf[0] = NUL;
			fix = TRUE;
			Kconvlnum = 0;

			if (p_tw)
			{
				onew_noredraw = FALSE;
				insertchar(NUL, NUL);
				onew_noredraw = TRUE;
			}
		}
	}

	if (State == CMDLINE)
		redrawcmdline();
	else
	{
		cursupdate();
		setcursor();
		updateline();
	}


	kanakan_len = 0;
	return fix;
}

	void
ONEW_GOT_2BCHAR(buf, a, b)
	char *buf, a, b;
{
	sprintf(buf, "%c%c", a, b);
}

	int
ONEW_MESSAGE_COLS()
{
	return sc_col;
}

	void
ONEW_MESSAGE(so, form, a, b, c, d, e)
	int so;
	char *form, *a, *b, *c, *d, *e;
{
	sprintf(IObuff, form, a, b, c, d, e);

	if (!onew_rvmsg)
		so = FALSE;

	if (State == CMDLINE)
		screen_msg(so, IObuff);
	else
	{
		gotocmdline(TRUE, NUL);
		if (so && T_TI) outstr(T_TI);
		outtrans(IObuff, -1);
		if (so && T_TP) outstr(T_TP);
		flushbuf();
	}
}

	void
ONEW_BEEP()
{
	beep();
}

	static int
fep_insstr(s)
	char *s;
{
	int len;
	int sm;

	sm = p_sm;				/* turn off  showmatch option */
	p_sm = FALSE;

	if (State == CMDLINE)
		len = cmd_insertstr(s);
	else
	{
		int w;
		int mode;

		mode = State;
		if (State != REPLACE)
			State = INSERT;

		for(len = 0; *s; len += w, s += w)
		{
			insertchar(*s, *(s + 1));
			w = IsKanji(*s) ? 2 : 1;
		}

		cursupdate();
		setcursor();
		updateline();

		State = mode;
	}

	p_sm = sm; 				/* restore showmatch option */
	return len;
}

	static void
fep_delchars(len)
	int len;
{
	switch(State)
	{
	case CMDLINE:
		cmd_delchars(len);
		break;

	case REPLACE:
		if (saved_line)
		{
			char *p, *c, *s;
			int	 nins;
			int	 col;

			if (!p_ri)
			{
				Curpos.col -= len;
				col = Curpos.col;
			}
			else
			{
				col = Curpos.col + len;
				incCurpos();
			}
			p = nr2ptr(Curpos.lnum);
			c = p + Curpos.col;
			s = saved_line;

			while(p < c)
			{
				p += IsKanji(*p) ? 2 : 1;
				if (*s)
					s += IsKanji(*s) ? 2 : 1;
			}

			State = INSERT;
			for(nins = 0; len > 0; nins++)
			{
				if (IsKanji(*p))		/* delete one char. */
				{
					delchar(FALSE);
					len--;
				}
				delchar(FALSE);
				len--;
			}

			for(; nins > 0 && *s; nins--)
			{							/* insert one char. */
				insertchar(*s, *(s + 1));
				if (IsKanji(*s))
					s++;
				s++;
			}
			Curpos.col = col;
			State = REPLACE;
			return;
		}

	default:
		if (!p_ri)
			Curpos.col -= len;

		for(; len; len--)
			delchar(FALSE);
	}
}

#endif /* ONEW */

/*
 *	vim JPFEP interface
 */

/*
 *	fep_mode_switch(TRUE );	FEP turned into KANJI mode
 *                  FALSE ;                 ASCII mode
 */
	void
fep_mode_switch(mode)
	int mode;
{
#ifdef ONEW
	Onew_RK_init();
	Onew_RK_cmode_set(mode ? 'h' : '@');
#else
	return;
#endif
}

/*
 *	fep_mode() return TRUE ;	FEP is in KANJI mode
 *                    FALSE;	          ASCII mode
 */
	int
fep_mode()
{
#ifdef ONEW
	return Onew_RK_imode();
#else
	return FALSE;
#endif
}

/*
 *	fep_freqsave();	save dictionary contents
 */
	void
fep_freqsave()
{
#ifdef ONEW
	if (freq_save)
	{
		smsg("saving kanji frequency...");
		Onew_KK_freqsave();
		smsg("");
		freq_save = FALSE;
	}
#endif
}

#endif /* JPFEP */


/*
 *	jp_getchar(char *k1, char *k2);
 *				return EUC character into k1 & k2
 *				or ascii character into k1
 */
	void
jp_getchar(k1, k2, savedl)
	char *k1, *k2, *savedl;
{
#ifdef JP
	saved_line = savedl;
#endif
#ifdef ONEW
	if (!p_oh)
#endif
#ifdef JPFEP
	if (!KanjiInput)
#endif
	{
		char c;

		*k1 = c = vgetc();
#ifdef JP
		*k2 = (IsKanji(c) && !ISKFUNC(c)) ? vgetc() : NUL;
#endif
#ifdef DOSGEN
		if (c == Ctrl(']'))
		{
			c = vgetc();
#ifdef JP
			if (IsKanji(c) && !ISKFUNC(c))
			{
				beep();
				c = vgetc();
				jp_getchar(k1, k2, savedl);
				return;
			}
#endif
			switch (c)
			{
			case 'h':
			case Ctrl('B'):
				c = K_LARROW;
				break;
			case 'j':
			case Ctrl('N'):
				c = K_DARROW;
				break;
			case 'k':
			case Ctrl('P'):
				c = K_UARROW;
				break;
			case 'l':
			case Ctrl('F'):
				c = K_RARROW;
				break;
			case 'H':
			case 'b':
				c = K_SLARROW;
				break;
			case 'J':
				c = K_SDARROW;
				break;
			case 'K':
				c = K_SUARROW;
				break;
			case 'L':
			case 'w':
				c = K_SRARROW;
				break;
			default:
				beep();
				jp_getchar(k1, k2, savedl);
				return;
			}
			*k1 = c;
		}
#endif /* DOSGEN */
		return;
	}

	/* fep interface */

#ifdef ONEW
	{
	    int oin;
		u_char in, ink;
		static int first = TRUE;

		if (first)
		{
			*(fbp = fep_buf) = hira_buf[0] = NUL;
			first = FALSE;
		}

		if (onew_noredraw)
		{
			if (State != CMDLINE)
				updateline();
		}
		else
			onew_noredraw = TRUE;

		ink = NUL;
		if ((oin = Onew_romkan()) == -1)
			mch_windexit(5);

		in = oin & ~FUNCMASK;		/* for function key */
		if (in == NUL)
			in = K_ZERO;

		if (State == NOMAPPING)
			goto normal;

		switch(in)
		{
		case Ctrl('V'):
			got_int = FALSE;
			break;

		case Ctrl('C'):
			if (p_oh)
				in = ESC;
		case '\n': case '\r':
		case Ctrl('Q'):
		case K_ZERO:
		case ESC:
		    Onew_kakutei(in);
			Kconvlnum  = 0;
			first = TRUE;
			ONEW_DISP_ROMKANMODE(NULL, "", -1);
			smsg("");
			onew_noredraw = FALSE;
			screen_msg(FALSE, NULL);
			if (State == CMDLINE)
			{
				redrawcmdline();
				if (in == ESC)
					if (!p_oh)
						in = K_ZERO;
					else if (fep_mode())
					{
						fep_mode_switch(FALSE);
						in = K_ZERO;
					}
			}
			break;

		case Ctrl('U'):
			fep_delchars(fbp - fep_buf);
			*(fbp = fep_buf) = hira_buf[0] = NUL;
			if (State == CMDLINE)
				redrawcmdline();
			else
				updateline();
			break;

		case DEL:
		case BS:
			if (fbp != fep_buf)
			{
			    if (State == CMDLINE)
				{
					Kconvlnum  = 0;
					KconvStart = -1;
				}
				else
				{
					KconvStart = KconvEnd - (fbp - fep_buf);
					KconvEnd --;
				}

				if (IsKanji(* --fbp))
				{
					fbp --;
					KconvEnd --;
				}
			}
			else
				Kconvlnum = 0;
			break;

		case ' ':
		case TAB:
			*fbp++ = in;
			goto thru;

		case Ctrl('P'):
			ONEW_DISP_ROMKANMODE(NULL, "", -1);
		case Ctrl('D'):						/* pass through characters */
		case Ctrl('T'):
		case Ctrl('W'):
		case Ctrl('N'):
		case Ctrl('Y'):
		case Ctrl('E'):
		case Ctrl('B'):
		case Ctrl('F'):
		case Ctrl('X'):
		case K_DARROW:
		case K_UARROW:
		case K_RARROW:
		case K_LARROW:
thru:
			Onew_kakutei(in);
			Kconvlnum  = 0;
			ink = NUL;
			break;

normal:
		default:
			if (fbp - fep_buf > MAX_COLUMNS)
			{
				emsg("Input buffer filled.");
				in = ink = NUL;
				break;
			}

			if (IsKanji(in) && !ISKFUNC(in))
			{
				ink = Onew_romkan();
				*fbp++ = in;
				*fbp++ = ink;
				KconvEnd   = Curpos.col + (p_ri ? fbp - fep_buf : 2);
			}
			else if (State == NOMAPPING || (' ' <= in && in < DEL))
			{
				*fbp++ = in;
				KconvEnd   = Curpos.col + (p_ri ? fbp - fep_buf : 1);
			}
			else
			{
				first = TRUE;
				if (in < ' ')
					Onew_putmsg(TRUE,"JVim:'^%c' unsupported", in + '@');
				if (in >= DEL)
					Onew_putmsg(TRUE,"JVim:x'%c' unsupported", in & 0x7f);
				ONEW_BEEP(1);
				in = 0;
				break;
			}

			if (State == CMDLINE)
			{
				Kconvlnum =
				KconvAltStart = -1;
			}
			else
			{
				Kconvlnum  = Curpos.lnum;
				KconvStart = KconvEnd - (fbp - fep_buf);
				KconvAltStart = KconvAltEnd = Curpos.col;
			}
			break;
		}
		*fbp = NUL;

		*k1 = in;
		*k2 = ink;
		return;
	}

#endif /* ONEW */
#if defined(JPFEP) && !defined(ONEW)
	{
		char *cp;
		int  kanji;

		if (! *fbp)
		{
	  		smsg("Kanji> ");
			settmode(0);
			fgets(fep_buf, MAX_COLUMNS+1, stdin);
			settmode(1);

			cp = strchr(fep_buf, '\n');
			if (cp) *cp = '\0';

			if (State == CMDLINE)
				redrawcmdline();
			else
				updateScreen(VALID);
			fbp = fep_buf;
			fep_mode_switch(KanjiInput = FALSE);
		}

		*k1 = *fbp++;
		if (IsKanji(*k1))
			*k2 = *fbp++;

		return;
	}
#endif /* ONEW */
}

/*
 * get one kanji character from terminal
 */
	void
jp_getc1(cp1, cp2)
	char *cp1, *cp2;
{
#ifdef JPFEP
	int orgKanjiInput;

	orgKanjiInput = KanjiInput;
	fep_mode_switch(KanjiInput = TRUE);
#endif
	jp_getchar(cp1, cp2, NULL);

#ifdef JPFEP
	Kconvlnum = 0;
	updateline();
#endif
	screen_msg(FALSE, NULL);
	smsg("");
#ifdef ONEW
	onew_noredraw = FALSE;
	ONEW_DISP_ROMKANMODE(NULL, "", -1);
	hira_buf[0] =
#endif /* ONEW */
#ifdef JPFEP
	*(fbp = fep_buf)  = NUL;
	fep_mode_switch(KanjiInput = orgKanjiInput);
#endif
	showmode();
}





syntax highlighted by Code2HTML, v. 0.9.1