/* 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