/************************************************************************
 * This program is Copyright (C) 1986 by Jonathan Payne.  JOVE is       *
 * provided to you without charge, and with no warranty.  You may give  *
 * away copies of JOVE, including sources, provided that this notice is *
 * included in all the files.                                           *
 ************************************************************************/
/*
 * Modified: Oct 1988 by Tom Hageman
 * - Word definition in Fundamental mode: all printable characters
 * - tab is punctuation
 * - underscore is Word in C mode
 * Mar 89 [TRH]
 * - add separate Word, Uppercase and Lowercase conversion tables
 * - Single character type table.
 * May 89 [TRH] Atari ST support
 * Oct 89 [TRH] MS-DOS and international character set support
 * Jan 90 [TRH] better system parametrization:
 * Feb 90 [TRH] add IBM line-draw and block characters
 * Jun 90 [TRH] add ISO Latin 1 character set
 * Feb 91 [TRH] add Macintosh character set; consider greek part of TEXT word;
 * - don't consider (') part of TEXT word.
 * Jun 91 [TRH] add NeXT (2.0 and newer) character set
 * - add help facility to `accent'
 * Mar 92 [TRH] include actual character tables so we can build them elsewhere
 */

#include "tune.h"	/* to allow definition of debug flags there. */

#ifdef DEBUG		/* General debug flag, turn on file-specific flag. */
#   ifndef CTYPE_DEBUG
#	define CTYPE_DEBUG	1
#   endif
#else
#   if CTYPE_DEBUG	/* File-specific debug flag, turn on general flag. */
#	define DEBUG
#   endif
#endif

#include "jove.h"

RCS("$Id: ctype.c,v 14.31.0.12 1994/06/23 02:46:24 tom Exp tom $")

#define _CTYPE_C_
#include "ctype.h"

#define CTABLESIZE	(1<<BPC)

int ModeMask = (1 << FUNDAMENTAL);

#include "ctype.inc"
/*
 * This include file should define and initialize the following tables:
 *
 *   public Const char CharTable[CTABLESIZE]	- character syntax flag bits
 *
 *   public Const char WordTable[CTABLESIZE]	- word flag bits
 *
 *   public Const char LocTable[CTABLESIZE]	- conversion to lower case
 *
 *   public Const char UpcTable[CTABLESIZE]	- conversion to upper case
#if (BPC > 7)
 *   public Const char CaseEquiv[CTABLESIZE]	- case equivalence table
 *	For 8-bit character sets, this table is used when searching with
 *	"case-ignore-search" on.  Apart from the character case mapping it
 *	also maps accented characters to their non-accented equivalents.
 *	For 7-bit character sets, the uppercase table is used instead.
 *
 *   private const char * const AccentTab[]	- accent definition table.
 *	The Accent table entry has the following structure:
 *		<Accent char>, {<base char>, <accented char>}...
#endif
 *   private const char charset_name[]		- name of the character-set.
 */

DEF_STR( "character-set", CharSetName, 40, V_STRING|V_CONST ) _IF(def PRIVATE) =
	(char *) charset_name;

#if (BPC > 7)

#ifdef SELECTABLE
private const char * const *SelectedAccentTab = AccentTab;

#   define AccentTab	SelectedAccentTab	/* for Accent's sake */
#endif

/*
 * Get an accented character.
 * e.g. bind this to {ESC,C-X} {' ^ ` " ~ , * / _ : ; (| # = % .)}
 */
DEF_CMD( "accent", Accent, EDIT ) _IF( BPC > 7 )
{
	extern int		alarmed;
	register const char 	* const *aa,
				*a;
	register int		c = LastKeyStruck,
				pass = 0;

	/* find accent descriptor */

	for (aa = AccentTab;;) {
		if ((a = *aa++) == NULL) {
			if (c == '?') {
				TOstart("*Help*", TRUE);
				for (aa = AccentTab; a = *aa++; )
					Typeout("  %c  %s", *a, &a[1]);
				TOstop();
				pass = 0;
			}
			if (pass > 0)
				complain((char *)0);
			pass++;

			s_mess("%N: %f (");
			for (aa = AccentTab; a = *aa++; )
				add_mess("%c", *a);
			add_mess(") ");

			c = addgetc();

			repl_strokes(mesgbuf);

			aa = AccentTab;
			continue;
		}
		if (c == *a++)
			break;
	}
	alarmed = 0;
	repl_strokes(sprint("%s(%s) ", key_strokes(), a));

	c = waitchar();

	/* find character */
	for (;;) {
		if (*a == '\0') {
			rbell();	/* not found... */
			return;
		}
		if (c == *a++)
			break;
		a++;			/* no match, skip result char */
	}
	Ungetc(*a);
	Ungetc(QuoteChar);		/* to get literal insert */
}

#ifdef SELECTABLE

#   undef AccentTab	/* unhide the sucker */

public void
set_char_tables(new_char_tables, offset, size, new_accent_table, new_name)
const char	* const *new_char_tables;
int		offset, size;
const char	* const *new_accent_table;
const char	*new_name;
{
	static char * const tables[NCTABLES] = {
		CharTable, WordTable, LocTable, CaseEquiv
	};
	static char *saved_tables ZERO;

	register int i;

	ASSERT(NCTABLES == sizeof tables / sizeof tables[0]);
#   if CTYPE_DEBUG
	if ((unsigned) offset + size > CTABLESIZE)
		complain("BUG: set_char_tables(\"%s\", off=%d, size=%d)",
			 new_name, offset, size);
#   endif
	if (saved_tables == NULL) {		/* initialize on first call. */
		if (new_char_tables == NULL)	/* restore tables is a no-op. */
			return;
		saved_tables = emalloc(NCTABLES * CTABLESIZE);

		{ i = NCTABLES - 1; } do {
			memcpy(saved_tables + i * CTABLESIZE, tables[i],
			       CTABLESIZE);
		} while (--i >= 0);
	}

	{ i = NCTABLES - 1; } do {
		register int		j;
		register const char	*src;
		register char		*dest = tables[i];

		/* Restore the original table. */
		memcpy(dest, saved_tables + i * CTABLESIZE, CTABLESIZE);

		if (new_char_tables == NULL ||
		    (src = new_char_tables[i]) == NULL)
			continue;

		/* Superimpose the new table--if any--over the original,
		   replacing only non-zero values. */

		dest += offset;
		for (j = size;  --j >= 0; )
			if (src[j])
				dest[j] = src[j];
	} while (--i >= 0);

	/* Now build the uppercase table form the lowercase table,
	   by observing that the relation ``toupper(tolower(c)) == c''
	   should always hold. */

	{ i = CTABLESIZE - 1; } do {
		UpcTable[i] = i;
	} while (--i >= 0);

	{ i = CTABLESIZE - 1; } do {
		if (tolower(i) != i)
			UpcTable[tolower(i)] = i;
	} while (--i >= 0);

	/* Setting the Accent Table is simple... */
	SelectedAccentTab = (new_accent_table) ? new_accent_table : AccentTab;

	/* ...so is setting the name. */
	CharSetName = (char *)((new_name) ? new_name : charset_name);
}

#endif /* SELECTABLE */

#endif /* (BPC > 7) */

/*======================================================================
 * $Log: ctype.c,v $
 * Revision 14.31.0.12  1994/06/23  02:46:24  tom
 * (Accent): fix name of scratch buffer.
 *
 * Revision 14.31.0.8  1993/11/11  01:42:23  tom
 * (Accent): push QuoteChar on Ungetc stack instead of calling QuotChar
 * directly (so i-search gets the chance to handle it transparently).
 *
 * Revision 14.31  1993/02/13  04:56:48  tom
 * allow debug options to be specified in "tune.h" cf. "Local.h".
 *
 * Revision 14.30  1993/02/05  00:55:21  tom
 * cleanup whitespace; some random optimizations and debug statements.
 *
 * Revision 14.26  1992/08/26  23:56:51  tom
 * PRIVATE-ized some Variable defs; add RCS directives.
 *
 */
