Mercurial > hg > xemacs-beta
annotate src/termcap.c @ 5576:071b810ceb18
Declare labels as line where appropriate; use #'labels, not #'flet, tests.
lisp/ChangeLog addition:
2011-10-03 Aidan Kehoe <kehoea@parhasard.net>
* simple.el (handle-pre-motion-command-current-command-is-motion):
Implement #'keysyms-equal with #'labels + (declare (inline ...)),
instead of abusing macrolet to the same end.
* specifier.el (let-specifier):
* mule/mule-cmds.el (describe-language-environment):
* mule/mule-cmds.el (set-language-environment-coding-systems):
* mule/mule-x-init.el (x-use-halfwidth-roman-font):
* faces.el (Face-frob-property):
* keymap.el (key-sequence-list-description):
* lisp-mode.el (construct-lisp-mode-menu):
* loadhist.el (unload-feature):
* mouse.el (default-mouse-track-check-for-activation):
Declare various labels inline in dumped files when that reduces
the size of the dumped image. Declaring labels inline is normally
only worthwhile for inner loops and so on, but it's reasonable
exercise of the related code to have these changes in core.
tests/ChangeLog addition:
2011-10-03 Aidan Kehoe <kehoea@parhasard.net>
* automated/case-tests.el (uni-mappings):
* automated/database-tests.el (delete-database-files):
* automated/hash-table-tests.el (iterations):
* automated/lisp-tests.el (test1):
* automated/lisp-tests.el (a):
* automated/lisp-tests.el (cl-floor):
* automated/lisp-tests.el (foo):
* automated/lisp-tests.el (list-nreverse):
* automated/lisp-tests.el (needs-lexical-context):
* automated/mule-tests.el (featurep):
* automated/os-tests.el (original-string):
* automated/os-tests.el (with):
* automated/symbol-tests.el (check-weak-list-unique):
Replace #'flet with #'labels where appropriate in these tests,
following my own advice on style in the docstrings of those
functions.
| author | Aidan Kehoe <kehoea@parhasard.net> |
|---|---|
| date | Mon, 03 Oct 2011 20:16:14 +0100 |
| parents | 308d34e9f07d |
| children | 574f0cded429 |
| rev | line source |
|---|---|
| 428 | 1 /* Work-alike for termcap, plus extra features. |
| 2 Copyright (C) 1985, 1986, 1993 Free Software Foundation, Inc. | |
| 771 | 3 Copyright (C) 2001 Ben Wing. |
| 428 | 4 |
| 5 This file is part of XEmacs. | |
| 6 | |
|
5402
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
5276
diff
changeset
|
7 XEmacs is free software: you can redistribute it and/or modify it |
| 428 | 8 under the terms of the GNU General Public License as published by the |
|
5402
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
5276
diff
changeset
|
9 Free Software Foundation, either version 3 of the License, or (at your |
|
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
5276
diff
changeset
|
10 option) any later version. |
| 428 | 11 |
| 12 XEmacs is distributed in the hope that it will be useful, but WITHOUT | |
| 13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 15 for more details. | |
| 16 | |
| 17 You should have received a copy of the GNU General Public License | |
|
5402
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
5276
diff
changeset
|
18 along with XEmacs. If not, see <http://www.gnu.org/licenses/>. */ |
| 428 | 19 |
| 20 /* Synched up with: Not synched with FSF. */ | |
| 21 | |
| 22 /* config.h may rename various library functions such as malloc. */ | |
| 23 #ifdef emacs | |
| 24 #include <config.h> | |
| 25 #include "lisp.h" /* For encapsulated open, close, read */ | |
|
5276
dd2976af8783
Add some missing #includes, termcap.c, hopefully fixing Adam Sjoegren's build.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4976
diff
changeset
|
26 #include "device.h" |
|
dd2976af8783
Add some missing #includes, termcap.c, hopefully fixing Adam Sjoegren's build.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4976
diff
changeset
|
27 #include "device-impl.h" /* For DEVICE_BAUD_RATE */ |
|
dd2976af8783
Add some missing #includes, termcap.c, hopefully fixing Adam Sjoegren's build.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4976
diff
changeset
|
28 #include "sysfile.h" |
|
dd2976af8783
Add some missing #includes, termcap.c, hopefully fixing Adam Sjoegren's build.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4976
diff
changeset
|
29 #include "process.h" |
| 428 | 30 #else /* not emacs */ |
| 31 | |
| 32 #include <stdlib.h> | |
| 33 #include <string.h> | |
| 34 | |
| 35 #ifdef HAVE_UNISTD_H | |
| 36 #include <unistd.h> | |
| 37 #endif | |
| 38 #ifdef _POSIX_VERSION | |
| 39 #include <fcntl.h> | |
| 40 #endif | |
| 41 | |
| 42 #endif /* not emacs */ | |
| 43 | |
| 44 /* BUFSIZE is the initial size allocated for the buffer | |
| 45 for reading the termcap file. | |
| 46 It is not a limit. | |
| 47 Make it large normally for speed. | |
| 48 Make it variable when debugging, so can exercise | |
| 49 increasing the space dynamically. */ | |
| 50 | |
| 51 #ifndef BUFSIZE | |
| 52 #ifdef DEBUG | |
| 53 #define BUFSIZE bufsize | |
| 54 | |
| 55 int bufsize = 128; | |
| 56 #else | |
| 57 #define BUFSIZE 2048 | |
| 58 #endif | |
| 59 #endif | |
| 60 | |
| 61 #ifndef emacs | |
| 62 static void | |
| 63 memory_out () | |
| 64 { | |
| 771 | 65 retry_write (2, "virtual memory exhausted\n", 25); |
| 428 | 66 exit (1); |
| 67 } | |
| 68 | |
| 69 static char * | |
| 70 xmalloc (size) | |
| 71 unsigned int size; | |
| 72 { | |
| 73 char *tem = malloc (size); | |
| 74 | |
| 75 if (!tem) | |
| 76 memory_out (); | |
| 77 return tem; | |
| 78 } | |
| 79 | |
| 80 static char * | |
| 81 xrealloc (ptr, size) | |
| 82 char *ptr; | |
| 83 unsigned size; | |
| 84 { | |
| 85 char *tem = realloc (ptr, size); | |
| 86 | |
| 87 if (!tem) | |
| 88 memory_out (); | |
| 89 return tem; | |
| 90 } | |
| 91 #endif /* not emacs */ | |
| 92 | |
| 93 /* Looking up capabilities in the entry already found. */ | |
| 94 | |
| 95 /* The pointer to the data made by tgetent is left here | |
| 96 for tgetnum, tgetflag and tgetstr to find. */ | |
| 97 static char *term_entry; | |
| 98 | |
| 442 | 99 static const char *tgetst1 (const char *ptr, char **area); |
| 428 | 100 |
| 101 /* Search entry BP for capability CAP. | |
| 102 Return a pointer to the capability (in BP) if found, | |
| 103 0 if not found. */ | |
| 104 | |
| 442 | 105 static const char * |
| 428 | 106 find_capability (bp, cap) |
| 442 | 107 const char *bp; |
| 108 const char *cap; | |
| 428 | 109 { |
| 110 for (; *bp; bp++) | |
| 111 if (bp[0] == ':' | |
| 112 && bp[1] == cap[0] | |
| 113 && bp[2] == cap[1]) | |
| 114 return &bp[4]; | |
| 115 return 0; | |
| 116 } | |
| 117 | |
| 118 int | |
| 119 tgetnum (cap) | |
| 442 | 120 const char *cap; |
| 428 | 121 { |
| 442 | 122 const char *ptr = find_capability (term_entry, cap); |
| 428 | 123 if (!ptr || ptr[-1] != '#') |
| 124 return -1; | |
| 125 return atoi (ptr); | |
| 126 } | |
| 127 | |
| 128 int | |
| 129 tgetflag (cap) | |
| 442 | 130 const char *cap; |
| 428 | 131 { |
| 442 | 132 const char *ptr = find_capability (term_entry, cap); |
| 428 | 133 return 0 != ptr && ptr[-1] == ':'; |
| 134 } | |
| 135 | |
| 136 /* Look up a string-valued capability CAP. | |
| 137 If AREA is nonzero, it points to a pointer to a block in which | |
| 138 to store the string. That pointer is advanced over the space used. | |
| 139 If AREA is zero, space is allocated with `malloc'. */ | |
| 140 | |
| 442 | 141 const char * |
| 428 | 142 tgetstr (cap, area) |
| 442 | 143 const char *cap; |
| 428 | 144 char **area; |
| 145 { | |
| 442 | 146 const char *ptr = find_capability (term_entry, cap); |
| 428 | 147 if (!ptr || (ptr[-1] != '=' && ptr[-1] != '~')) |
| 148 return 0; | |
| 149 return tgetst1 (ptr, area); | |
| 150 } | |
| 151 | |
| 152 /* Table, indexed by a character in range 0100 to 0140 with 0100 subtracted, | |
| 153 gives meaning of character following \, or a space if no special meaning. | |
| 154 Eight characters per line within the string. */ | |
| 155 | |
| 156 static char esctab[] | |
| 157 = " \007\010 \033\014 " | |
| 158 " \012 " | |
| 159 " \015 \011 \013 " | |
| 160 " "; | |
| 161 | |
| 162 /* PTR points to a string value inside a termcap entry. | |
| 163 Copy that value, processing \ and ^ abbreviations, | |
| 164 into the block that *AREA points to, | |
| 165 or to newly allocated storage if AREA is 0. */ | |
| 166 | |
| 442 | 167 static const char * |
| 428 | 168 tgetst1 (ptr, area) |
| 442 | 169 const char *ptr; |
| 428 | 170 char **area; |
| 171 { | |
| 442 | 172 const char *p; |
| 428 | 173 char *r; |
| 174 int c; | |
| 175 int size; | |
| 176 char *ret; | |
| 177 int c1; | |
| 178 | |
| 179 if (!ptr) | |
| 180 return 0; | |
| 181 | |
| 182 /* `ret' gets address of where to store the string. */ | |
| 183 if (!area) | |
| 184 { | |
| 185 /* Compute size of block needed (may overestimate). */ | |
| 186 p = ptr; | |
| 187 while ((c = *p++) && c != ':' && c != '\n') | |
| 188 ; | |
| 189 ret = (char *) xmalloc (p - ptr + 1); | |
| 190 } | |
| 191 else | |
| 192 ret = *area; | |
| 193 | |
| 194 /* Copy the string value, stopping at null or colon. | |
| 195 Also process ^ and \ abbreviations. */ | |
| 196 p = ptr; | |
| 197 r = ret; | |
| 198 while ((c = *p++) && c != ':' && c != '\n') | |
| 199 { | |
| 200 if (c == '^') | |
| 201 c = *p++ & 037; | |
| 202 else if (c == '\\') | |
| 203 { | |
| 204 c = *p++; | |
| 205 if (c >= '0' && c <= '7') | |
| 206 { | |
| 207 c -= '0'; | |
| 208 size = 0; | |
| 209 | |
| 210 while (++size < 3 && (c1 = *p) >= '0' && c1 <= '7') | |
| 211 { | |
| 212 c *= 8; | |
| 213 c += c1 - '0'; | |
| 214 p++; | |
| 215 } | |
| 216 } | |
| 217 else if (c >= 0100 && c < 0200) | |
| 218 { | |
| 219 c1 = esctab[(c & ~040) - 0100]; | |
| 220 if (c1 != ' ') | |
| 221 c = c1; | |
| 222 } | |
| 223 } | |
| 224 *r++ = c; | |
| 225 } | |
| 226 *r = 0; | |
| 227 /* Update *AREA. */ | |
| 228 if (area) | |
| 229 *area = r + 1; | |
| 230 return ret; | |
| 231 } | |
| 232 | |
| 233 /* Outputting a string with padding. */ | |
| 234 | |
| 235 #ifdef LINUX | |
| 236 speed_t ospeed; | |
| 237 #else | |
| 238 short ospeed; | |
| 239 #endif | |
| 240 /* If `ospeed' is 0, we use `tputs_baud_rate' as the actual baud rate. */ | |
| 241 int tputs_baud_rate; | |
| 242 char PC; | |
| 243 | |
| 244 /* Actual baud rate if positive; | |
| 245 - baud rate / 100 if negative. */ | |
| 246 | |
| 247 static short speeds[] = | |
| 248 { | |
| 249 0, 50, 75, 110, 135, 150, -2, -3, -6, -12, | |
| 250 -18, -24, -48, -96, -192, -288, -384, -576, -1152 | |
| 251 }; | |
| 252 | |
| 253 void | |
| 254 tputs (string, nlines, outfun) | |
| 442 | 255 const char *string; |
| 428 | 256 int nlines; |
| 257 void (*outfun) (int); | |
| 258 { | |
| 259 int padcount = 0; | |
| 260 int speed; | |
| 261 | |
| 262 #ifdef emacs | |
| 263 speed = DEVICE_BAUD_RATE (XDEVICE (Fselected_device (Qnil))); | |
| 264 #else | |
| 265 if (ospeed == 0) | |
| 266 speed = tputs_baud_rate; | |
| 267 else | |
| 268 speed = speeds[ospeed]; | |
| 269 #endif | |
| 270 | |
| 271 if (string == (char *) 0) | |
| 272 return; | |
| 273 | |
| 442 | 274 while (isdigit (* (const unsigned char *) string)) |
| 428 | 275 { |
| 276 padcount += *string++ - '0'; | |
| 277 padcount *= 10; | |
| 278 } | |
| 279 if (*string == '.') | |
| 280 { | |
| 281 string++; | |
| 282 padcount += *string++ - '0'; | |
| 283 } | |
| 284 if (*string == '*') | |
| 285 { | |
| 286 string++; | |
| 287 padcount *= nlines; | |
| 288 } | |
| 289 while (*string) | |
| 290 (*outfun) (*string++); | |
| 291 | |
| 292 /* padcount is now in units of tenths of msec. */ | |
| 293 padcount *= speeds[ospeed]; | |
| 294 padcount += 500; | |
| 295 padcount /= 1000; | |
| 296 if (speeds[ospeed] < 0) | |
| 297 padcount = -padcount; | |
| 298 else | |
| 299 { | |
| 300 padcount += 50; | |
| 301 padcount /= 100; | |
| 302 } | |
| 303 | |
| 304 while (padcount-- > 0) | |
| 305 (*outfun) (PC); | |
| 306 } | |
| 307 | |
| 308 /* Finding the termcap entry in the termcap data base. */ | |
| 309 | |
| 310 struct buffer | |
| 311 { | |
| 312 char *beg; | |
| 313 int size; | |
| 314 char *ptr; | |
| 315 int ateof; | |
| 316 int full; | |
| 317 }; | |
| 318 | |
| 319 /* Forward declarations of static functions. */ | |
| 320 | |
| 321 static int scan_file (); | |
| 322 static char *gobble_line (); | |
| 323 static int compare_contin (); | |
| 324 static int name_match (); | |
| 325 | |
| 326 | |
| 327 /* Find the termcap entry data for terminal type NAME | |
| 328 and store it in the block that BP points to. | |
| 329 Record its address for future use. | |
| 330 | |
| 331 If BP is zero, space is dynamically allocated. */ | |
| 332 | |
| 333 int | |
| 334 tgetent (bp, name) | |
| 335 char *bp; | |
| 442 | 336 const char *name; |
| 428 | 337 { |
| 338 char *tem; | |
| 339 int fd; | |
| 340 struct buffer buf; | |
| 341 char *bp1; | |
| 342 char *bp2; | |
| 442 | 343 const char *term; |
| 428 | 344 int malloc_size = 0; |
| 345 int c; | |
| 442 | 346 char *tcenv; /* TERMCAP value, if it contains :tc=. */ |
| 347 const char *indirect = 0; /* Terminal type in :tc= in TERMCAP value. */ | |
| 428 | 348 |
| 771 | 349 tem = egetenv ("TERMCAP"); |
| 428 | 350 if (tem && *tem == 0) tem = 0; |
| 351 | |
| 352 | |
| 353 /* If tem is non-null and starts with / (in the un*x case, that is), | |
| 354 it is a file name to use instead of /etc/termcap. | |
| 355 If it is non-null and does not start with /, | |
| 356 it is the entry itself, but only if | |
| 357 the name the caller requested matches the TERM variable. */ | |
| 358 | |
| 771 | 359 if (tem && !IS_DIRECTORY_SEP (*tem) && !strcmp (name, egetenv ("TERM"))) |
| 428 | 360 { |
| 361 indirect = tgetst1 (find_capability (tem, "tc"), 0); | |
| 362 if (!indirect) | |
| 363 { | |
| 364 if (!bp) | |
| 365 bp = tem; | |
| 366 else | |
| 367 strcpy (bp, tem); | |
| 368 goto ret; | |
| 369 } | |
| 370 else | |
| 371 { /* We will need to read /etc/termcap. */ | |
| 372 tcenv = tem; | |
| 373 tem = 0; | |
| 374 } | |
| 375 } | |
| 376 else | |
| 377 indirect = (char *) 0; | |
| 378 | |
| 379 if (!tem) | |
| 380 tem = "/etc/termcap"; | |
| 381 | |
| 382 /* Here we know we must search a file and tem has its name. */ | |
| 383 | |
| 867 | 384 fd = qxe_open ((Ibyte *) tem, 0, 0); |
| 428 | 385 if (fd < 0) |
| 386 return -1; | |
| 387 | |
| 388 buf.size = BUFSIZE; | |
| 389 /* Add 1 to size to ensure room for terminating null. */ | |
| 390 buf.beg = (char *) xmalloc (buf.size + 1); | |
| 391 term = indirect ? indirect : name; | |
| 392 | |
| 393 if (!bp) | |
| 394 { | |
| 395 malloc_size = indirect ? strlen (tcenv) + 1 : buf.size; | |
| 396 bp = (char *) xmalloc (malloc_size); | |
| 397 } | |
| 398 bp1 = bp; | |
| 399 | |
| 400 if (indirect) | |
| 401 /* Copy the data from the environment variable. */ | |
| 402 { | |
| 403 strcpy (bp, tcenv); | |
| 404 bp1 += strlen (tcenv); | |
| 405 } | |
| 406 | |
| 407 while (term) | |
| 408 { | |
| 409 /* Scan the file, reading it via buf, till find start of main entry. */ | |
| 410 if (scan_file (term, fd, &buf) == 0) | |
| 411 return 0; | |
| 412 | |
| 413 /* Free old `term' if appropriate. */ | |
| 414 if (term != name) | |
|
4976
16112448d484
Rename xfree(FOO, TYPE) -> xfree(FOO)
Ben Wing <ben@xemacs.org>
parents:
1726
diff
changeset
|
415 xfree (term); |
| 428 | 416 |
| 417 /* If BP is malloc'd by us, make sure it is big enough. */ | |
| 418 if (malloc_size) | |
| 419 { | |
| 420 malloc_size = bp1 - bp + buf.size; | |
| 421 tem = (char *) xrealloc (bp, malloc_size); | |
| 422 bp1 += tem - bp; | |
| 423 bp = tem; | |
| 424 } | |
| 425 | |
| 426 bp2 = bp1; | |
| 427 | |
| 428 /* Copy the line of the entry from buf into bp. */ | |
| 429 tem = buf.ptr; | |
| 430 while ((*bp1++ = c = *tem++) && c != '\n') | |
| 431 /* Drop out any \ newline sequence. */ | |
| 432 if (c == '\\' && *tem == '\n') | |
| 433 { | |
| 434 bp1--; | |
| 435 tem++; | |
| 436 } | |
| 437 *bp1 = 0; | |
| 438 | |
| 439 /* Does this entry refer to another terminal type's entry? | |
| 440 If something is found, copy it into heap and null-terminate it. */ | |
| 441 term = tgetst1 (find_capability (bp2, "tc"), 0); | |
| 442 } | |
| 443 | |
| 771 | 444 retry_close (fd); |
|
4976
16112448d484
Rename xfree(FOO, TYPE) -> xfree(FOO)
Ben Wing <ben@xemacs.org>
parents:
1726
diff
changeset
|
445 xfree (buf.beg); |
| 428 | 446 |
| 447 if (malloc_size) | |
| 448 { | |
| 449 bp = (char *) xrealloc (bp, bp1 - bp + 1); | |
| 450 } | |
| 451 | |
| 452 ret: | |
| 453 term_entry = bp; | |
| 454 if (malloc_size) | |
| 455 /* #### yuck, why the hell are we casting a pointer to an int? */ | |
| 456 return (int) (long) bp; | |
| 457 return 1; | |
| 458 } | |
| 459 | |
| 460 /* Given file open on FD and buffer BUFP, | |
| 461 scan the file from the beginning until a line is found | |
| 462 that starts the entry for terminal type STRING. | |
| 463 Returns 1 if successful, with that line in BUFP, | |
| 464 or returns 0 if no entry found in the file. */ | |
| 465 | |
| 466 static int | |
| 467 scan_file (string, fd, bufp) | |
| 468 char *string; | |
| 469 int fd; | |
| 470 struct buffer *bufp; | |
| 471 { | |
| 472 char *end; | |
| 473 | |
| 474 bufp->ptr = bufp->beg; | |
| 475 bufp->full = 0; | |
| 476 bufp->ateof = 0; | |
| 477 *bufp->ptr = 0; | |
| 478 | |
| 479 lseek (fd, 0L, 0); | |
| 480 | |
| 481 while (!bufp->ateof) | |
| 482 { | |
| 483 /* Read a line into the buffer. */ | |
| 484 end = 0; | |
| 485 do | |
| 486 { | |
| 487 /* if it is continued, append another line to it, | |
| 488 until a non-continued line ends. */ | |
| 489 end = gobble_line (fd, bufp, end); | |
| 490 } | |
| 491 while (!bufp->ateof && end[-2] == '\\'); | |
| 492 | |
| 493 if (*bufp->ptr != '#' | |
| 494 && name_match (bufp->ptr, string)) | |
| 495 return 1; | |
| 496 | |
| 497 /* Discard the line just processed. */ | |
| 498 bufp->ptr = end; | |
| 499 } | |
| 500 return 0; | |
| 501 } | |
| 502 | |
| 503 /* Return nonzero if NAME is one of the names specified | |
| 504 by termcap entry LINE. */ | |
| 505 | |
| 506 static int | |
| 507 name_match (line, name) | |
| 508 char *line, *name; | |
| 509 { | |
| 510 char *tem; | |
| 511 | |
| 512 if (!compare_contin (line, name)) | |
| 513 return 1; | |
| 514 /* This line starts an entry. Is it the right one? */ | |
| 515 for (tem = line; *tem && *tem != '\n' && *tem != ':'; tem++) | |
| 516 if (*tem == '|' && !compare_contin (tem + 1, name)) | |
| 517 return 1; | |
| 518 | |
| 519 return 0; | |
| 520 } | |
| 521 | |
| 522 static int | |
| 523 compare_contin (str1, str2) | |
| 524 char *str1, *str2; | |
| 525 { | |
| 526 int c1, c2; | |
| 527 while (1) | |
| 528 { | |
| 529 c1 = *str1++; | |
| 530 c2 = *str2++; | |
| 531 while (c1 == '\\' && *str1 == '\n') | |
| 532 { | |
| 533 str1++; | |
| 534 while ((c1 = *str1++) == ' ' || c1 == '\t'); | |
| 535 } | |
| 536 if (c2 == '\0') | |
| 537 { | |
| 538 /* End of type being looked up. */ | |
| 539 if (c1 == '|' || c1 == ':') | |
| 540 /* If end of name in data base, we win. */ | |
| 541 return 0; | |
| 542 else | |
| 543 return 1; | |
| 544 } | |
| 545 else if (c1 != c2) | |
| 546 return 1; | |
| 547 } | |
| 548 } | |
| 549 | |
| 550 /* Make sure that the buffer <- BUFP contains a full line | |
| 551 of the file open on FD, starting at the place BUFP->ptr | |
| 552 points to. Can read more of the file, discard stuff before | |
| 553 BUFP->ptr, or make the buffer bigger. | |
| 554 | |
| 555 Returns the pointer to after the newline ending the line, | |
| 556 or to the end of the file, if there is no newline to end it. | |
| 557 | |
| 558 Can also merge on continuation lines. If APPEND_END is | |
| 559 nonzero, it points past the newline of a line that is | |
| 560 continued; we add another line onto it and regard the whole | |
| 561 thing as one line. The caller decides when a line is continued. */ | |
| 562 | |
| 563 static char * | |
| 564 gobble_line (fd, bufp, append_end) | |
| 565 int fd; | |
| 566 struct buffer *bufp; | |
| 567 char *append_end; | |
| 568 { | |
| 569 char *end; | |
| 570 int nread; | |
| 571 char *buf = bufp->beg; | |
| 572 char *tem; | |
| 573 | |
| 574 if (append_end == 0) | |
| 575 append_end = bufp->ptr; | |
| 576 | |
| 577 while (1) | |
| 578 { | |
| 579 end = append_end; | |
| 580 while (*end && *end != '\n') end++; | |
| 581 if (*end) | |
| 582 break; | |
| 583 if (bufp->ateof) | |
| 584 return buf + bufp->full; | |
| 585 if (bufp->ptr == buf) | |
| 586 { | |
| 587 if (bufp->full == bufp->size) | |
| 588 { | |
| 589 bufp->size *= 2; | |
| 590 /* Add 1 to size to ensure room for terminating null. */ | |
| 591 tem = (char *) xrealloc (buf, bufp->size + 1); | |
| 592 bufp->ptr = (bufp->ptr - buf) + tem; | |
| 593 append_end = (append_end - buf) + tem; | |
| 594 bufp->beg = buf = tem; | |
| 595 } | |
| 596 } | |
| 597 else | |
| 598 { | |
| 599 append_end -= bufp->ptr - buf; | |
| 600 memcpy (buf, bufp->ptr, bufp->full -= bufp->ptr - buf); | |
| 601 bufp->ptr = buf; | |
| 602 } | |
| 771 | 603 if (!(nread = retry_read (fd, buf + bufp->full, bufp->size - bufp->full))) |
| 428 | 604 bufp->ateof = 1; |
| 605 bufp->full += nread; | |
| 606 buf[bufp->full] = 0; | |
| 607 } | |
| 608 return end + 1; | |
| 609 } | |
| 610 | |
| 611 #ifdef TEST | |
| 612 | |
| 613 #include <stdio.h> | |
| 614 | |
| 615 main (argc, argv) | |
| 616 int argc; | |
| 617 char **argv; | |
| 618 { | |
| 619 char *term; | |
| 620 char *buf; | |
| 621 | |
| 622 term = argv[1]; | |
| 623 printf ("TERM: %s\n", term); | |
| 624 | |
| 625 buf = (char *) tgetent (0, term); | |
| 626 if ((int) buf <= 0) | |
| 627 { | |
| 628 printf ("No entry.\n"); | |
| 629 return 0; | |
| 630 } | |
| 631 | |
| 632 printf ("Entry: %s\n", buf); | |
| 633 | |
| 634 tprint ("cm"); | |
| 635 tprint ("AL"); | |
| 636 | |
| 637 printf ("co: %d\n", tgetnum ("co")); | |
| 638 printf ("am: %d\n", tgetflag ("am")); | |
| 639 } | |
| 640 | |
| 641 tprint (cap) | |
| 442 | 642 const char *cap; |
| 428 | 643 { |
| 644 char *x = tgetstr (cap, 0); | |
| 645 char *y; | |
| 646 | |
| 647 printf ("%s: ", cap); | |
| 648 if (x) | |
| 649 { | |
| 650 for (y = x; *y; y++) | |
| 651 if (*y <= ' ' || *y == 0177) | |
| 652 printf ("\\%0o", *y); | |
| 653 else | |
| 654 putchar (*y); | |
|
4976
16112448d484
Rename xfree(FOO, TYPE) -> xfree(FOO)
Ben Wing <ben@xemacs.org>
parents:
1726
diff
changeset
|
655 xfree (x); |
| 428 | 656 } |
| 657 else | |
| 658 printf ("none"); | |
| 659 putchar ('\n'); | |
| 660 } | |
| 661 | |
| 662 #endif /* TEST */ | |
| 663 |
