File: translat.c

package info (click to toggle)
ircii 4.4-3
  • links: PTS
  • area: main
  • in suites: hamm, slink
  • size: 4,256 kB
  • ctags: 2,797
  • sloc: ansic: 36,743; sh: 907; makefile: 483; lex: 16
file content (436 lines) | stat: -rw-r--r-- 10,095 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
/*
 * translat.c:  Stuff for handling character translation tables
 * and a digraph entry facility.  Support an international IRC!
 *
 * I listen to Sex Pistols, so I assume everyone in this world,
 * and more specifically, all servers, are using ISO 8859/1
 * (Latin-1).  And in case of doubt, please consult Jarkko 'Wiz'
 * Oikarinen's document "Internet Relay Chat Protocol" (doc/Comms
 * in the ircd package), paragraph 2.2.  Besides, all of the sane
 * world has already converted to this set.  (X-Windows, Digital,
 * MS-Windows, etc.)
 * If someone please would forward me some documentation on other
 * international sets, like 8859/2 - 8859/10 etc, please do so!
 * Moreover, feedback on the tables in the definition files would
 * be greatly appreciated!
 * Another idea, to be implemented some beautiful day, would be
 * to add transliteration of the Kanji/Katakana sets used in
 * the far east.  8-)
 *
 * Kare H. Pettersson.
 */

#ifndef lint
static	char	rcsid[] = "@(#)$Id: translat.c,v 1.16 1997/01/17 16:40:18 mrg Exp $";
#endif /* lint */

#include "irc.h"

#include "vars.h"
#include "translat.h"
#include "ircaux.h"
#include "window.h"
#include "screen.h"
#include "output.h"

static	unsigned char	my_getarg _((char **));

/* Globals */
unsigned char	transToClient[256];    /* Server to client translation. */
unsigned char	transFromClient[256];  /* Client to server translation. */
char	translation = 0;	/* 0 for transparent (no) translation. */
char	digraph_changed = 0;

/*
 * dig_table_lo[] and dig_table_hi[] contain the character pair that
 * will result in the digraph in dig_table_di[].  To avoid searching
 * both tables, I take the lower character of the pair, and only
 * search dig_table_lo[].  Thus, dig_table_lo[] must always contain
 * the lower character of the pair.
 *
 * The digraph tables are based on those in the excellent editor Elvis,
 * with some additions for those, like me, who are used to VT320 or
 * VT420 terminals.
 */

#define	DiLo(x)	x,
#define	DiHi(x)
#define	DiDi(x)

/*
 * Digraph tables.  Note that, when adding a new digraph, the character
 * of the pair with the lowest value, *must* be in the DiLo column.
 * The higher of the pair goes in DiHi, and the digraph itself in DiDi.
 */

unsigned char	dig_table_lo[DIG_TABLE_SIZE] =
{
#include "digraph.inc"
	0
};


#undef	DiLo
#undef	DiHi
#undef	DiDi
#define	DiLo(x)
#define	DiHi(x)	x,
#define	DiDi(x)

unsigned char	dig_table_hi[DIG_TABLE_SIZE] =
{
#include "digraph.inc"
	0
};


#undef	DiLo
#undef	DiHi
#undef	DiDi
#define	DiLo(x)
#define	DiHi(x)
#define	DiDi(x)	x,

unsigned char	dig_table_di[DIG_TABLE_SIZE] =
{
#include "digraph.inc"
	0
};


/*
 * enter_digraph:  The BIND function ENTER_DIGRAPH.
 */
#if defined(__STDC__) || defined(__cplusplus)
void	enter_digraph(unsigned char key, char *ptr)
#else
void	enter_digraph(key, str)
unsigned char	key;
char	*str;
#endif /* __STDC__ || __cplusplus */
{
	current_screen->digraph_hit = 1;  /* Just stuff away first character. */
}

/*
 * get_digraph:  Called by edit_char() when a digraph entry is activated.
 * Looks up a digraph given char c1 and the global char
 * current_screen->digraph_hit.
 */
#if defined(__STDC__) || defined(__cplusplus)
unsigned char	get_digraph(unsigned char c1)
#else
unsigned char	get_digraph(c1)
unsigned char	c1;
#endif /* __STDC__ || __cplusplus */
{
	int	i = 0;
	unsigned char	c,
		c2 = current_screen->digraph_first;

	current_screen->digraph_hit = 0;
	if (c1 > c2)	/* Make sure we have the lowest one in c1. */
		c = c1,	c1 = c2, c2 = c;
	while (dig_table_lo[i])
	{	/* Find digraph and return it. */
		if ((dig_table_lo[i] == c1) && (dig_table_hi[i] == c2))
			return dig_table_di[i];
		i++;
	}
	return 0;		/* Failed lookup. */
}


/*
 * set_translation:  Called when the TRANSLATION variable is SET.
 * Attempts to load a new translation table.
 */
void
set_translation(tablename)
	char	*tablename;
{
	FILE	*table;
	unsigned char	temp_table[512];
	char	*filename = (char *) 0, *s;
	int	inputs[8];
	int	j,
		c = 0;

	if (!tablename)
	{
		translation = 0;
		return;
	}
	for (s = tablename; *s; s++)
		if (isspace(*s))
		{
			*s = '\0';
			break;
		}
	tablename = upper(tablename);

	/* Check for transparent mode; ISO-8859/1, Latin-1 */
	if (!strcmp("LATIN_1", tablename))
	{
		translation = 0;
		return;
	}

	/* Else try loading the translation table from disk. */
	malloc_strcpy(&filename, TRANSLATION_PATH);
	malloc_strcat(&filename, tablename);
	if ( !(table = fopen(filename, "r")) )
	{
		say("Cannot open character table definition \"%s\" !",
			tablename);
		set_string_var(TRANSLATION_VAR, (char *) 0);
		new_free(&filename);
		return;
	}

	/* Any problems in the translation tables between hosts are
	 * almost certain to be caused here.
	 * many scanf implementations do not work as defined. In particular,
	 * scanf should ignore white space including new lines (many stop
	 * at the new line character, hence the fgets and sscanf workaround),
	 * many fail to read 0xab as a hexadecimal number (failing on the
	 * x) despite the 0x being defined as optionally existing on input,
	 * and others zero out all the output variables if there is trailing
	 * non white space in the format string which doesn't appear on the
	 * input. Overall, the standard I/O libraries have a tendancy not
	 * to be very standard.
	 */

	while (fgets(buffer, 80, table))
	{
		sscanf(buffer, "0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x",
		    inputs+0, inputs+1, inputs+2, inputs+3,
		    inputs+4, inputs+5, inputs+6, inputs+7);
		for (j = 0; j<8; j++)
			temp_table[c++] = (unsigned char) inputs[j];
	}
	fclose(table);
	new_free(&filename);
	if (c == 512)
	{
		for (c = 0; c <= 255; c++)
		{
			transToClient[c] = temp_table[c];
			transFromClient[c] = temp_table[c | 256];
		}
		translation = 1;
	}
	else
	{
		say("Error loading translation table \"%s\" !", tablename);
		set_string_var(TRANSLATION_VAR, (char *) 0);
	}
}

/*
 * digraph:  The /DIGRAPH command with facilities.
 * This routine is *NOT* finished yet.
 */

void
digraph(command, args, subargs)
	char	*command,
		*args,
		*subargs;
{
	char	*arg;
	u_char	c1,
		c2 = '\0',
		c3 = '\0';
	int	len,
		i;

	if ((arg = next_arg(args, &args)) && (*arg == '-'))
	{
		char	*cmd = (char *) 0;

		arg++;
		if ((len = strlen(arg)) == 0)
		{
			say("Unknown or missing flag.");
			return;
		}
		malloc_strcpy(&cmd, arg);
		lower(cmd);
		if (strncmp(cmd, "add", len) == 0)
		{
			/*
			 * Add a digraph to the table.
			 * I *know*.  This *is* a kludge.
			 */
			if ((i = strlen((char *)dig_table_lo)) ==
					DIG_TABLE_SIZE - 1)
				say("Sorry, digraph table full.");
			else
			{
				while ((c1 = my_getarg(&args)) &&
				    (c2 = my_getarg(&args)) &&
				    (c3 = my_getarg(&args)))
				{
					/* Pass c1 to get_digraph() */
					current_screen->digraph_first = c1;	    
					if (get_digraph(c2) == 0)
					{
						dig_table_di[i] = c3;
						/* Make sure c1 <= c2 */
						if (c1 > c2)
						    c3 = c1, c1 = c2, c2 = c3;
						dig_table_lo[i] = c1;
						dig_table_hi[i] = c2;
						i++;
						dig_table_lo[i] =
							dig_table_hi[i] =
					 		dig_table_di[i] =
							(unsigned char) 0;
						digraph_changed = 1;
						say("Digraph added to table.");
					}
					else
					{
				say("Digraph already defined in table.");
				break;
					}
				}
				if (!c2 || !c3)
					say("Unknown or missing argument.");
			}

		}
		else if (strncmp(cmd, "remove", len) == 0)
		{

			/* Remove a digraph from the table. */
			if ((i = strlen((char *)dig_table_lo)) == 0)
				say("Digraph table is already empty.");
			else
			{
				if ((c1 = my_getarg(&args)) &&
						(c2 = my_getarg(&args)))
				{
					i = 0;
					if (c1 > c2)
						c3 = c1, c1 = c2, c2 = c3;
					while (dig_table_lo[i])
					{
						if ((dig_table_lo[i] == c1) &&
						    (dig_table_hi[i] == c2))
					/*
					 * strcpy() is not guaranteed for
					 * overlapping copying, but this one
					 * is high -> low. Ought to be fixed.
					 */
	/* re-indent this block - phone, jan 1993. */
				{
					strcpy(((char *)dig_table_lo + i),
					    (char *)(dig_table_lo + (i + 1)));
					strcpy((char *)(dig_table_hi + i),
					    (char *)(dig_table_hi + (i + 1)));
					strcpy((char *)(dig_table_di + i),
					    (char *)(dig_table_di + (i + 1)));
					digraph_changed = 1;
					put_it("Digraph removed from table.");
					return;
				}
	/* much better */
						i++;
					}
					say("Digraph not found.");
				}
			}
		}
		else if (strncmp(cmd, "clear", len) == 0)
		{

			/* Clear digraph table. */
			dig_table_lo[0] = dig_table_hi[0] = dig_table_di[0] =
				(unsigned char) 0;
			digraph_changed = 1;
			say("Digraph table cleared.");

		}
		else
			say("Unknown flag.");
	}
	else
	{

		/* Display digraph table. */
		char	buffer1[8];
		char	buffer2[192];

		say("Digraph table:");
		buffer2[0] = (char) 0;
		i = 0;
		while(dig_table_lo[i])
		{
			sprintf(buffer1, "%c%c %c   ", dig_table_lo[i],
			    dig_table_hi[i], dig_table_di[i]);
			strcat(buffer2, buffer1);
			if ((++i % 10) == 0)
			{
				put_it(buffer2);
				buffer2[0] = (char) 0;
			}
		}
		if (buffer2[0])
			put_it(buffer2);
		sprintf(buffer2, "%d digraphs listed.", i);
		say(buffer2);
	}
}

static	unsigned char
my_getarg(args)
	char	**args;
{
	unsigned char *arg;

	arg = (unsigned char *)next_arg(*args, args);
	if (!args || !*args || !arg)
		return '\0';
	/* Don't trust isdigit() with 8 bits. */
	if ((*arg <= '9') && (*arg >= '0'))
	{
		unsigned char i = *arg & 0x0f;
		while ( *(++arg) )
			i = (i * 10) + (*arg & 0x0f);
		return i;
	}
	else if ( (*arg == '!') && (*(arg + 1)) )
		return *(arg + 1) | 0x80;
	return *arg;
}

#if defined(__STDC__) || defined(__cplusplus)
void	save_digraphs(FILE *fp)
#else
void	save_digraphs(fp)
FILE	*fp;
#endif /* __STDC__ || __cplusplus */
{
	if (digraph_changed)
	{

		int	i = 0;
		char	*command = "\nDIGRAPH -ADD ";

		fprintf(fp, "DIGRAPH -CLEAR");
		fprintf(fp, command);
		while(1)
		{
			fprintf(fp, "%d %d %d  ", dig_table_lo[i],
				dig_table_hi[i], dig_table_di[i]);
			if (!dig_table_lo[++i])
				break;
			if (!(i % 5))
				fprintf(fp, command);
		}
		fputc('\n', fp);

	}
}