File: djterm.c

package info (click to toggle)
ispell 3.3.02-6
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd, wheezy
  • size: 4,444 kB
  • ctags: 2,246
  • sloc: ansic: 10,073; makefile: 1,912; yacc: 1,697; objc: 385; csh: 215; python: 112; perl: 87; sed: 32; sh: 15
file content (439 lines) | stat: -rw-r--r-- 10,900 bytes parent folder | download | duplicates (6)
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
437
438
439
#ifndef lint
static char DJGPP_Rcs_Id[] =
    "$Id";
#endif

/*
 * djterm.c - DJGPP-specific terminal driver for Ispell
 *
 * Eli Zaretskii <eliz@is.elta.co.il>, 1996, 2001
 *
 * Copyright 1996, Geoff Kuenning, Granada Hills, CA
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All modifications to the source code must be clearly marked as
 *    such.  Binary redistributions based on modified source code
 *    must be clearly marked as modified versions in the documentation
 *    and/or other materials provided with the distribution.
 * 4. The code that causes the 'ispell -v' command to display a prominent
 *    link to the official ispell Web site may not be removed.
 * 5. The name of Geoff Kuenning may not be used to endorse or promote
 *    products derived from this software without specific prior
 *    written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY GEOFF KUENNING AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL GEOFF KUENNING OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

/*
 * $Log: djterm.c,v $
 * Revision 1.4  2005/05/01 23:03:25  geoff
 * Updates from Eli Zaretskii.
 *
 * Revision 1.3  2005/04/13 23:54:23  geoff
 * Update license.
 *
 * Revision 1.2  2001/09/06 00:33:35  geoff
 * Make the license consistent, and do some style cleanups.
 *
 * Revision 1.1  2001/09/01 06:40:21  geoff
 * As received from Eli
 *
 */

/*
** DJGPP currently doesn't support Unixy ioctl directly, so we
** have to define minimal support here via the filesystem extensions.
*/

#include <errno.h>
#include <unistd.h>
#include <limits.h>
#include <sys/ioctl.h>
#include <conio.h>
#include <sys/fsext.h>

static struct text_info txinfo;
static unsigned char * saved_screen;
static unsigned char ispell_norm_attr, ispell_sout_attr;

/* These declarations are on <sys/ioctl.h>, but as of DJGPP v2.03 they
   are ifdefed away.  To accomodate for both old and new versions,
   where some of the TIOC* commands might be supported, we override
   any possible definitions of those commands, but provide
   declarations of structures they use only if they are not provided
   by the library.  */
#ifdef TIOCGWINSZ
#undef TIOCGWINSZ
#else
struct winsize
    {
    unsigned short	ws_row;
    unsigned short	ws_col;
    unsigned short	ws_xpixel;
    unsigned short	ws_ypixel;
    };
#endif

#ifdef TIOCGETP
#undef TIOCGETP
#else
struct sgttyb
    {
    char		sg_ispeed;
    char		sg_ospeed;
    char		sg_erase;
    char		sg_kill;
    short		sg_flags;
    };
#endif

#undef IOCPARM_MASK
#undef IOC_OUT
#undef IOC_IN
#undef IOC_INOUT

#define IOCPARM_MASK    0x7f
#define IOC_OUT         0x40000000
#define IOC_IN          0x80000000
#define IOC_INOUT       (IOC_IN|IOC_OUT)

#undef _IOR
#undef _IOW
#undef _IOWR

#define _IOR(x,y,t)     (IOC_OUT|((sizeof(t)&IOCPARM_MASK)<<16)|(x<<8)|y)
#define _IOW(x,y,t)     (IOC_IN|((sizeof(t)&IOCPARM_MASK)<<16)|(x<<8)|y)
#define _IOWR(x,y,t)    (IOC_INOUT|((sizeof(t)&IOCPARM_MASK)<<16)|(x<<8)|y)

#undef TIOCGPGRP
#undef TIOCSETP
#undef CBREAK
#undef ECHO

/* These are the only ones we support here.  */
#define TIOCGWINSZ  _IOR('t', 104, struct winsize)
#define TIOCGPGRP   _IOR('t', 119, int)
#define TIOCGETP    _IOR('t', 8, struct sgttyb)
#define TIOCSETP    _IOW('t', 9, struct sgttyb)
#define CBREAK      0x00000002
#define ECHO        0x00000008

/* This will be called by low-level I/O functions.  */
static int djgpp_term (__FSEXT_Fnumber func, int *retval, va_list rest_args)
    {
    int fhandle = va_arg (rest_args, int);

    /*
    ** We only support ioctl on STDIN and write on STDOUT/STDERR.
    */
    if (func == __FSEXT_ioctl  &&  fhandle == fileno (stdin)
      && isatty (fhandle))
	{
	int cmd = va_arg (rest_args, int);

	switch (cmd)
	    {
	    case TIOCGWINSZ:
		{
		struct winsize *winfo = va_arg (rest_args, struct winsize *);

		winfo->ws_row = ScreenRows ();
		winfo->ws_col = ScreenCols ();
		winfo->ws_xpixel = 1;
		winfo->ws_ypixel = 1;
		*retval = 0;
		break;
		}
	    case TIOCGPGRP:
		*retval = 0;
		break;
	    case TIOCGETP:
		{
		struct sgttyb * gtty = va_arg (rest_args, struct sgttyb *);
		gtty->sg_ispeed = gtty->sg_ospeed = 0; /* unused */
		gtty->sg_erase = K_BackSpace;
		gtty->sg_kill  = K_Control_U;
		gtty->sg_flags = 0; /* unused */
		*retval = 0;
		break;
		}
	    case TIOCSETP:
		*retval = 0;
		break;
	    default:
		*retval = -1;
		break;
	    }
	return 1;
	}
    else if (func == __FSEXT_write
      &&  (fhandle == fileno (stdout)  ||  fhandle == fileno (stderr))
      &&  isatty (fhandle) &&  termchanged)
	{
	/*
	** Cannot write the output as is, because it might include
	** TABS.  We need to expand them into suitable number of spaces.
	*/
	int	col;
	int	dummy;
	char *	buf = va_arg (rest_args, char *);
	size_t	buflen = va_arg (rest_args, size_t);
	char *	local_buf;
	char *	s;
	char *	d;

	if (!buf)
	    {
	    errno = EINVAL;
	    *retval = -1;
	    return 1;
	    }

	*retval = buflen;	/* `_write' expects number of bytes written */
	local_buf = (char *) alloca (buflen+8+1); /* 8 for TAB, 1 for '\0' */
	ScreenGetCursor (&dummy, &col);

	for (s = buf, d = local_buf;  buflen--;  s++)
	    {
	    if (*s == '\0')	/* `cputs' treats '\0' as end of string */
		{
		*d = *s;
		cputs (local_buf);
		putch (*s);
		d = local_buf;
		col++;
		}
	    else if (*s == '\t')
		{
		*d++ = ' ';
		col++;
		while (col % 8)
		    {
		    *d++ = ' ';
		    col++;
		    }
		*d = '\0';
		cputs (local_buf);
		d = local_buf;
		}
	    else
	        {
		*d++ = *s;
		if (*s == '\r')
		    col = 0;
		else if (*s != '\n')
		    col++;
		}
	    }
	if (d > local_buf)
	    {
	    *d = '\0';
	    cputs (local_buf);
	    }

	return 1;
	}
    else
        return 0;
    }


/* This is called before `main' to install our terminal handler. */
static void __attribute__((constructor))
djgpp_ispell_startup (void)
{
  __FSEXT_set_function (fileno (stdin), djgpp_term);
  __FSEXT_set_function (fileno (stdout), djgpp_term);
  __FSEXT_set_function (fileno (stderr), djgpp_term);
}

/* DJGPP-specific screen initialization and deinitialization.  */
static void djgpp_init_terminal (void)
    {
    if (li == 0)
	{
	/*
	** On MSDOS/DJGPP platforms, colors are used for normal and
	** inverse-video displays.  The colors and screen size seen
	** at program startup are saved, to be restored before exit.
	** The screen contents are also saved and restored.
	*/
	char *	ispell_colors;

	gettextinfo (&txinfo);
	saved_screen = (unsigned char *) malloc (
	  txinfo.screenwidth * txinfo.screenheight * 2);
	if (saved_screen)
	    ScreenRetrieve (saved_screen);

	/*
	** Let the user specify their favorite colors for normal
	** and standout text, like so:
	**
	**         set ISPELL_COLORS=0x1e.0x74
	**                            se   so
	*/
	ispell_colors = getenv ("ISPELL_COLORS");
	if (ispell_colors != NULL)
	    {
	    char *	next;
	    unsigned long coldesc = strtoul (ispell_colors, &next, 0);

	    if (next == ispell_colors  ||  coldesc > UCHAR_MAX)
	        ispell_colors = NULL;
	    else
		{
		char *	endp;

		ispell_norm_attr = (unsigned char) coldesc;
		coldesc = strtoul (next + 1, &endp, 0);
		if (endp == next + 1  ||  coldesc > UCHAR_MAX)
		    ispell_colors = NULL;
		else
		    ispell_sout_attr = (unsigned char) coldesc;
		}
	    }
	if (ispell_colors == NULL)
	    {
	    /* Use dull B&W color scheme */
	    ispell_norm_attr = LIGHTGRAY + (BLACK << 4);
	    ispell_sout_attr  = BLACK + (LIGHTGRAY << 4);
	    }
	}
    }

static void djgpp_restore_screen (void)
    {
    if (li != txinfo.screenheight)
        _set_screen_lines (txinfo.screenheight);
    textmode (txinfo.currmode);
    textattr (txinfo.attribute);
    gotoxy (1, txinfo.screenheight);
    clreol ();
    }

static void djgpp_deinit_term (void)
    {
    termchanged = 0;	/* so output uses stdio again */
    printf ("\n");	/* in case some garbage is pending */
    fflush (stdout);
    if (saved_screen)
	{
	ScreenUpdate (saved_screen);
	gotoxy (txinfo.curx, txinfo.cury);
	}
    }

static void djgpp_ispell_screen ()
    {
    fflush (stdout);
    if (li != txinfo.screenheight)
	_set_screen_lines (li);
    textattr (ispell_norm_attr);
    }

static int djgpp_column;
static int djgpp_row;

char * tgoto (char * cmd, int col, int row)
    {
    djgpp_column = col;
    djgpp_row = row;
    return "\2";
    }

char * tputs (const char * cmd, int cnt, int (*func)(int))
    {
    fflush (stdout);
    if (!cmd)
	abort ();
    switch (*cmd)
	{
	case '\1':		/* erase */
	    clrscr ();
	    break;
	case '\2':		/* move */
	    gotoxy (djgpp_column + 1, djgpp_row + 1);
	    break;
	case '\3':		/* stand-out */
	    textattr (ispell_sout_attr);
	    break;
	case '\4':		/* end stand-out */
	    textattr (ispell_norm_attr);
	    break;
	case '\5':		/* backup */
	    gotoxy (wherex () - cnt, wherey ());
	    break;
	case '\6':		/* terminal init */
	    djgpp_ispell_screen ();
	    clrscr ();
	    break;
	case '\7':		/* terminal termination */
	    djgpp_restore_screen ();
	    djgpp_deinit_term ();
	    break;
	default:
	    abort ();
	}
    }

int tgetent (char * buf, const char * term_name)
    {
    djgpp_init_terminal ();
    }

char * tgetstr (const char * cmd, char ** buf)
    {
    static struct emulated_cmd
	{
	char *external_name;
	char *internal_code;
	}
		commands[] =
        {
	    { "cl", "\1" },
	    { "cm", "\2" },
	    { "so", "\3" },
	    { "se", "\4" },
	    { "bc", "\5" },
	    { "ti", "\6" },
	    { "te", "\7" },
	};
		int i;

    for (i = 0; i < sizeof (commands) / sizeof (commands[0]); i++)
	{
	if (strcmp (cmd, commands[i].external_name) == 0)
	    return commands[i].internal_code;
	}

    return NULL;
    }

int tgetnum (const char * cmd)
    {
    if (cmd  &&  strcmp (cmd, "co") == 0)
	return 80;
    else if (cmd  &&  strcmp (cmd, "li") == 0)
	return 24;
    return -1;
    }