/* vi:ts=4:sw=4
*
* VIM - Vi IMitation Japanese extension
*
* Code Contributions By: Atsushi Nakamura ann@mrit.mei.co.jp
*/
#include "vim.h"
#include "globals.h"
#include "proto.h"
#include "param.h"
#include "ops.h"
#ifdef JP
#include "jp.h"
#include "jptab.h"
# ifdef sony
# define sjis2euc sjis_to_euc
# endif
#endif
static int jisx0201rto0208();
#ifdef GENERAL
# undef free
#endif
#if defined(UNIX) && !defined(GENERAL)
#include "signal.h"
/*
* handle core dump by some bugs.
*/
static void
core_handler(dummy)
int dummy;
{
static void abend_handler();
abend_handler(TRUE);
}
static void
hup_handler(dummy)
int dummy;
{
static void abend_handler();
abend_handler(FALSE);
}
static void
abend_handler(core)
int core;
{
char *text;
settmode(0);
stoptermcap();
flushbuf();
stopscript(); /* remove autoscript file */
#ifdef JPFEP
fep_freqsave();
#endif
signal(SIGQUIT, SIG_DFL);
signal(SIGHUP, SIG_DFL);
signal(SIGTERM, SIG_DFL);
signal(SIGSEGV, SIG_DFL);
#ifdef SIGILL
signal(SIGILL, SIG_DFL);
#endif
#ifdef SIGBUS
signal(SIGBUS, SIG_DFL);
#endif
#ifdef SIGLOST
signal(SIGLOST, SIG_DFL);
#endif
#ifdef SIGPWR
signal(SIGPWR, SIG_DFL);
#endif
#ifdef JP
printf("\n%s is killed by some bugs....\n", JpVersion);
#else
printf("\n%s is killed by some bugs....\n", Version);
#endif
text = modname(Filename, ".sav");
if (writeit(text, NULL, (linenr_t)1, line_count, FALSE, FALSE, TRUE))
printf("\nThe current text is saved into %s.\n", text);
else
printf("\nI couldn't save the current text.\n");
if (core)
kill(getpid(), SIGQUIT);
else
kill(getpid(), SIGKILL);
}
static void
core_init()
{
signal(SIGQUIT, core_handler);
signal(SIGHUP, hup_handler);
signal(SIGTERM, hup_handler);
signal(SIGSEGV, core_handler);
#ifdef SIGILL
signal(SIGILL, core_handler);
#endif
#ifdef SIGBUS
signal(SIGBUS, core_handler);
#endif
#ifdef SIGLOST
signal(SIGLOST, hup_handler);
#endif
#ifdef SIGPWR
signal(SIGPWR, hup_handler);
#endif
}
#endif /* UNIX && !GENERAL */
#ifdef JP
#ifndef GENERAL
void
jp_init()
{
JP_FCODE = JP_NEW;
#if defined(UNIX) && !defined(GENERAL)
core_init();
#endif
}
#endif /* !GENERAL */
/*
* convert EUC letter into suitable letter.
*/
void
kanjito(k1, k2, code)
u_char *k1, *k2;
char code;
{
u_char c1, c2;
switch(code)
{
case JP_NJIS:
case JP_JIS:
*k1 &= 0x7f;
*k2 &= 0x7f;
return;
case JP_SJIS:
c1 = *k1 & 0x7f;
c2 = *k2 & 0x7f;
*k1 = (((int)c1 - 1) >> 1) + ((c1 <= 0x5e) ? 0x71 : 0xb1);
*k2 = c2 + ((c1 & 1) ? ((c2 < 0x60) ? 0x1f : 0x20) : 0x7e);
return;
default:
return;
}
}
/*
* return kanji shift-in string
*/
char *
kanjiin(code)
char code;
{
switch(code)
{
case JP_NJIS:
return "\033$B";
case JP_JIS:
return "\033$@";
default:
return "";
}
}
/*
* return kanji shift-out string
*/
char *
kanjiout(code)
char code;
{
switch(code)
{
case JP_NJIS:
return "\033(B";
case JP_JIS:
return "\033(J";
default:
return "";
}
}
/*
* convert buffer to EUC code
*/
static int jis, euc, njis, sjis;
static int knj_asc;
static int jis0201r;
#define IsJIS0201r(c) ((u_char)(c) >= 0xa0 && (u_char)(c) <= 0xdf)
void
reset_jcount()
{
jis = euc = njis = sjis =
knj_asc =
jis0201r = 0;
}
#if defined(JPFEP) || defined(FEPCTRL)
char*
guess_jiauto(ji, th)
char* ji;
int th;
{
if (!th)
return ji;
if (knj_asc > th)
return isupper(*ji) ? "J": "j";
if (knj_asc < - th)
return isupper(*ji) ? "A": "a";
return ji;
}
#endif
char
judge_jcode(code)
char code;
{
if (code == JP_ANY || code == JP_SANY)
{
char judge;
if (!jis && !euc && !njis && !sjis)
judge = JP_NONE;
else if (njis)
judge = JP_NJIS;
else if (jis)
judge = JP_JIS;
else if (euc >= sjis)
judge = JP_EUC;
else
judge = JP_SJIS;
return judge;
}
else
return code;
}
int
num_jis0201r()
{
return jis0201r;
}
static void sjis2euc(ptr)
char *ptr;
{
int i, j;
i = (u_char) *ptr;
j = (u_char) *(ptr + 1);
i = (i * 2) - ((i <= 0x9f)? 0xe1 : 0x161);
if (j < 0x9f)
j -= ((j > 0x7f) ? 0x20 : 0x1f);
else
{
i ++;
j -= 0x7e;
}
*ptr++ = i | 0x80;
*ptr = j | 0x80;
}
#define CHARSET_ASCII FALSE /* or JISX0201 Left hand set */
#define CHARSET_JISX0208 1
#define CHARSET_JISX0201R 2
int /* return the length of dst */
kanjiconvsfrom(ptr, ptrlen, dst, dstlen, tail, code, charsetp)
char *ptr;
int ptrlen;
char *dst;
int dstlen;
char *tail;
char code;
int *charsetp;
{
char *top, *dtop;
u_char c;
#ifndef GENERAL
int firstchar = FALSE;
#endif
int charset;
charset = charsetp ? *charsetp : CHARSET_ASCII;
top = ptr;
dtop = dst;
if (tail)
tail[0] = NUL;
switch(code)
{
case JP_NONE:
while(ptrlen)
{
c = *ptr;
if (!IsKanji(c) || (c & 0x60))
{ /* if not Function key */
c &= 0x7f;
if (*ptr > ' ')
knj_asc --;
}
ptr ++;
*dst ++ = c;
ptrlen --;
if (dst - dtop >= dstlen)
return -1;
}
return dst - dtop;
case JP_EUC:
while(ptrlen)
{
if (dst - dtop >= dstlen)
return -1;
ptrlen --;
if (IsKanji(c = *dst ++ = *ptr ++))
{
if (! (c & 0x60)) /* if Function key */
continue;
if (c == 0xff) /* if NT Function key */
continue;
if (IsKanji(*ptr))
{ /* JIS0208 char. */
knj_asc ++;
*dst ++ = *ptr ++;
ptrlen --;
continue;
}
if (tail && ptrlen == 0)
{ /* not completed */
tail[0] = c;
tail[1] = NUL;
dst --;
continue;
}
else
{ /* Illegal char */
*(dst - 1) &= 0x7f;
continue;
}
}
else if (c > ' ') /* ASCII char */
knj_asc --;
}
return dst - dtop;
case JP_SJIS:
while(ptrlen)
{
if (dst - dtop >= dstlen)
return -1;
ptrlen --;
c = *dst ++ = *ptr ++;
if (IsKanji(c))
{
if (IsJIS0201r(c))
{ /* JIS X 0201R 8bit encoding */
char c1;
if (jisx0201rto0208(c, ptrlen ? *ptr : NUL, dst - 1, &c1))
{ /* 2 characters -> double byte character. */
* dst++ = c1;
ptr ++;
ptrlen --;
}
else if (c1)
/* 1 character -> double byte character. */
* dst++ = c1;
/* else
1 character -> single byte character. */
jis0201r ++;
continue;
}
if (ptrlen == 0)
{ /* not completed */
if (tail)
{
tail[0] = c;
tail[1] = NUL;
dst --;
}
else
*(dst - 1) &= 0x7f;
continue;
}
if (c == 0xff) /* if NT Function key */
continue;
else
{ /* SJIS character */
* dst++ = * ptr++;
ptrlen --;
knj_asc ++;
sjis2euc(dst - 2);
continue;
}
}
else if (c > ' ')
knj_asc --;
}
return dst - dtop;
case JP_NJIS:
case JP_JIS:
case JP_ANY:
case JP_SANY:
while(ptrlen)
{
if (dst - dtop >= dstlen)
return -1;
ptrlen --;
c = *dst ++ = *ptr ++;
if (IsKanji(c))
{
#ifndef GENERAL
/* check Function key */
if (!p_jse && code != JP_SJIS && code != JP_SANY)
{
if (!(c & 0x60))
continue;
}
else
{
if (firstchar ++ && !(c & 0x60) && !*ptr)
continue;
}
if (c == 0xff) /* if NT Function key */
continue;
#endif
if (ptrlen == 0)
{ /* not completed */
if (tail)
{
tail[0] = c;
tail[1] = NUL;
dst --;
}
else
*(dst - 1) &= 0x7f;
continue;
}
if ( (code == JP_SANY
|| code == JP_NJIS
|| code == JP_JIS) && IsJIS0201r(c))
{ /* JIS X 0201R 8bit encoding */
char c1;
if (jisx0201rto0208(c, ptrlen ? *ptr : NUL, dst - 1, &c1))
{ /* 2 characters -> double byte character. */
* dst++ = c1;
ptr ++;
ptrlen --;
}
else if (c1)
/* 1 character -> double byte character. */
* dst++ = c1;
/* else
1 character -> single byte character. */
jis0201r ++;
continue;
}
* dst++ = * ptr++;
switch(code)
{
case JP_SANY:
if (c < 0xa0 || c >= 0xe0)
{
sjis ++;
sjis2euc(dst - 2);
}
else
euc ++;
goto s_or_e;
case JP_ANY:
if (c < 0xa0)
{
sjis ++;
sjis2euc(dst - 2);
}
else
euc ++;
s_or_e:
ptrlen --;
knj_asc ++;
break;
default:
dst --;
ptr --;
*(dst - 1) &= 0x7f;
}
continue;
}
if (c == ESC)
{
dst --;
if (ptrlen == 0)
{
if (tail)
{
tail[0] = c;
tail[1] = NUL;
}
else
dst++;
continue;
}
if (*ptr == '(')
{
ptrlen --;
ptr ++;
if (ptrlen == 0)
{
if (tail)
{
tail[0] = c;
tail[1] = '(';
tail[2] = NUL;
}
else
{
dst ++;
* dst++ = '(';
}
continue;
}
if (*ptr == 'I')
{ /* JIS X 0201R ISO2022 encoding */
charset = CHARSET_JISX0201R;
ptr ++;
ptrlen --;
continue;
}
else if (*ptr == 'J' || *ptr == 'H' || *ptr == 'B' ||
code == JP_ANY) /* ASCII/JIS In */
{
charset = CHARSET_ASCII;
ptr ++;
ptrlen --;
continue;
}
else
{
dst ++;
* dst++ = '(';
continue;
}
}
if (*ptr == '$')
{
ptrlen --;
ptr ++;
if (ptrlen == 0)
{
if (tail)
{
tail[0] = c;
tail[1] = '$';
tail[2] = NUL;
}
else
{
dst ++;
* dst++ = '$';
}
continue;
}
if (*ptr == '@' || *ptr == 'B' ||
code == JP_ANY) /* Kanji In */
{
if (*ptr == '@') jis++;
else if (*ptr == 'B') njis++;
charset = CHARSET_JISX0208;
ptrlen --;
ptr ++;
continue;
}
else
{
dst ++;
* dst ++ = '$';
continue;
}
}
else
dst++;
}
switch(charset)
{
case CHARSET_ASCII:
if (c > ' ')
knj_asc --;
break;
case CHARSET_JISX0201R:
if (IsJIS0201r(c | 0x80))
{ /* This code is not examined. ann */
char c0, c1;
c0 = ptrlen ? *ptr : NUL;
if (! IsJIS0201r(c0 | 0x80))
c0 |= 0x80;
if (jisx0201rto0208(c | 0x80, c0, dst - 1, &c1))
{ /* 2 characters -> double byte character. */
* dst++ = c1;
ptr ++;
ptrlen --;
}
else if (c1)
/* 1 character -> double byte character. */
* dst++ = c1;
/* else
1 character -> single byte character. */
jis0201r ++;
}
else if (c == NUL || c =='\n' || c == '\r')
charset = CHARSET_ASCII;
break;
default: /* CHARSET_JISX0208 */
if (ptrlen == 0)
{
if (tail)
{
tail[0] = c;
tail[1] = NUL;
dst --;
}
}
else if (c > ' ' && *ptr > ' ')
{
ptrlen --;
*(dst - 1) |= 0x80;
* dst++ = * ptr++ | 0x80;
knj_asc ++;
}
else if (c == NUL || c == '\n' || c == '\r')
charset = CHARSET_ASCII;
}
}
if (charsetp)
*charsetp = charset;
return dst - dtop;
}
return dst - dtop;
}
/*
* convert buffer from EUC code
*/
#ifdef GENERAL
# define alloc_line(x) malloc(x)
#endif
#ifndef GENERAL
void
kanjiconvto(lnum, lend, code)
linenr_t lnum, lend;
char code;
{
char *ptr, *new;
for(; lnum <= lend; ++lnum)
{
ptr = nr2ptr(lnum);
new = kanjiconvsto(ptr, code);
if (new != ptr) free_line(replaceline(lnum, new));
}
}
#endif /* !GENERAL */
char *
kanjiconvsto(ptr, code)
char *ptr;
char code;
{
char *top, *ptr2;
char *kin, *kout, *cp;
int kanji, nshift, nchar;
top = ptr;
switch(code)
{
case JP_EUC:
return top;
case JP_NONE:
top = ptr2 = alloc_line(strlen(ptr));
while(*ptr)
*ptr2 ++ = *ptr ++ & ~0x80;
*ptr2 = NUL;
return top;
case JP_SJIS:
top = ptr2 = alloc_line(strlen(ptr));
while(*ptr)
if (IsKanji(*ptr2++ = *ptr++))
{
*ptr2 ++ = *ptr ++;
kanjito(ptr2 - 2, ptr2 - 1, code);
}
*ptr2 = NUL;
return top;
case JP_NJIS:
case JP_JIS:
case JP_ANY:
kin = kanjiin(code);
kout = kanjiout(code);
kanji = 0;
for(nshift = 0; *ptr; ptr++)
{
if (kanji != (*ptr & 0x80))
{
nshift++;
kanji ^= 0x80;
}
}
if (kanji) nshift++;
nchar = ptr - top;
if (!nshift) return top;
ptr = top;
top = ptr2 = alloc_line(nchar + nshift * 3);
kanji = 0;
while(*ptr)
{
if (kanji != (*ptr & 0x80))
{
if (kanji)
for(cp = kout; *cp;)
*ptr2++ = *cp++;
else
for(cp = kin; *cp;)
*ptr2++ = *cp++;
kanji ^= 0x80;
}
*ptr2++ = (*ptr++ & 0x7f);
}
if (kanji)
for(cp = kout; *cp;)
*ptr2++ = *cp++;
*ptr2 = 0;
return top;
}
return top;
}
#ifndef GENERAL
void
kanji_align()
{
int col;
char *line;
line = nr2ptr(Curpos.lnum);
for(col = 0; col < Curpos.col; line++, col++)
if (IsKanji(*line))
{
line ++;
col ++;
}
Curpos.col = col;
}
#endif /* !GENERAL */
/*
* Japanese Character class;
* Make sure this routine is consistent with search.c:cls().
*
* for Japanese
* 3 - alphabet, digits
* 4 - japanese hiragana
* 5 - japanese katakana
* 6 - symbols
* 7 - other multi-char letter
*/
int
jpcls(c, k)
char c, k;
{
if (c == ' ' || c == '\t' || c == NUL)
return 0;
if (IsKanji(c))
{
int ret;
return (ret = jptab[c & 0x7f].cls1) == JPC_KIGOU
? jptab[k & 0x7f].cls2
: ret;
}
#ifdef GENERAL
# ifdef __STDC__
if (isalnum(c) || c == '_')
# else
if (isalpha(c) || isdigit(c) || c == '_')
# endif
#else
if (isidchar(c))
#endif
return 1;
return -1;
}
/*
* isjppunc(c, k) returns whether a kanji character ck necessary KINSOKU
* processing or not.
*/
int
isjppunc(c, k, type)
char c, k;
int type;
{
k &= 0x7f;
switch(jptab[(int)c & 0x7f].cls1)
{
case JPC_KIGOU:
return type ? jptab[(int)k].punccsym : jptab[(int)k].puncosym;
case JPC_HIRA:
case JPC_KATA:
return type ? jptab[(int)k].puncckana : FALSE;
default:
return FALSE;
}
}
/*
* isaspunc(c, type) returns whether an ascii character ck necessary KINSOKU
* processing or not.
*/
int
isaspunc(c, type)
char c;
int type;
{
return(type ? jptab[(int)c].punccasc: jptab[(int)c].puncoasc);
}
/*
* isjsend(*cp) returns whether a JIS character *cp separates
* sentences or not.
*/
int
isjsend(cp)
u_char *cp;
{
return *cp == (0x80 | '!') && jptab[*(cp + 1) & 0x7f].stcend;
}
/*
* jptocase(&c, &k, tocase)
* modify c & k to case tocase
* tocase == UPPER : to upper
* tocase == LOWER : to lower
* tocase == others : swap case
*/
void
jptocase(cp, kp, tocase)
u_char *cp, *kp;
int tocase;
{
u_char k;
k = *kp & 0x7f;
switch(jptab[*cp & 0x7f].cls1)
{
case JPC_ALNUM:
if (tocase != LOWER && islower(k))
*kp = TO_UPPER(k) | 0x80;
if (tocase != UPPER && isupper(k))
*kp = TO_LOWER(k) | 0x80;
return;
case JPC_KIGOU:
if ( (tocase != LOWER && jptab[k].scase == JLOS)
|| (tocase != UPPER && jptab[k].scase == JUPS)
)
*kp = jptab[k].swap;
return;
case JPC_KATA:
if (tocase != -1)
*cp = JP1_HIRA | 0x80;
return;
case JPC_HIRA:
if (tocase != 1)
*cp = JP1_KATA | 0x80;
return;
default:
return;
}
}
/*
* JIS X 0201 Right hand set(hankaku kana) <-> JIS X 0208(zenkaku)
*
*/
static int
jisx0201rto0208(src0, src1, dst0, dst1)
char src0, src1, *dst0, *dst1;
{
u_char c, y;
u_char *x0201p, z;
int conv;
c = (u_char) src0;
x0201p = (u_char*)jisx0201r + 2 * (c - 0xa0);
if (! IsKanji(y = *x0201p))
{
*dst0 = y;
*dst1 = NUL;
return 0;
}
z = *(x0201p + 1);
conv = FALSE;
if ((u_char)src1 == 0xdf && /* maru */
(c >= 0xca && c <= 0xce)) /* ha - ho */
{
z += 2;
conv = TRUE;
}
else if ((u_char)src1 == 0xde) /* dakuten */
{
conv = TRUE;
if ( (c >= 0xb6 && c <= 0xc4) /* ka - to */
|| (c >= 0xca && c <= 0xce) ) /* ha - ho */
z ++;
else if (c == 0xb3) /* u -> vu*/
z = 0xf4;
else
conv = FALSE;
}
*dst0 = y;
*dst1 = z;
return conv ? 1 : 0;
}
#endif /* JP */
#ifdef GENERAL
/*
* The following codes are copied from alloc.c for jcat.c and jfold.c
*/
# ifdef BSD_UNIX
char *
bsdmemset(ptr, c, size)
char *ptr;
int c;
long size;
{
register char *p = ptr;
while (size-- > 0)
*p++ = c;
return ptr;
}
# endif
# ifdef MEMMOVE
/*
* Version of memmove that handles overlapping source and destination.
* For systems that don't have a function that is guaranteed to do that (SYSV).
*/
void *
memmove(desti, source, len)
void *source, *desti;
#ifdef __sgi
size_t len;
#else
int len;
#endif
{
char *src = (char *)source;
char *dst = (char *)desti;
if (dst > src && dst < src + len) /* overlap, copy backwards */
{
src +=len;
dst +=len;
while (len--)
*--dst = *--src;
}
else /* copy forwards */
while (len--)
*dst++ = *src++;
return desti;
}
# endif
#endif
syntax highlighted by Code2HTML, v. 0.9.1