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;
}
|