home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #16 / NN_1992_16.iso / spool / comp / editors / 1834 < prev    next >
Encoding:
Text File  |  1992-07-28  |  61.7 KB  |  2,560 lines

  1. Newsgroups: comp.editors
  2. Path: sparky!uunet!paladin.american.edu!darwin.sura.net!Sirius.dfn.de!math.fu-berlin.de!wolff
  3. From: wolff@inf.fu-berlin.de (Thomas Wolff)
  4. Subject: Editor mined (2/4)
  5. Message-ID: <52I57ND@math.fu-berlin.de>
  6. Sender: news@math.fu-berlin.de (Math Department)
  7. Organization: Free University of Berlin, Germany
  8. Date: Tue, 28 Jul 1992 15:03:16 GMT
  9. Lines: 2549
  10.  
  11. #! /bin/sh
  12. : This is a sharchive -- extract the files by running through sh
  13.  
  14. echo ---------------------- extracting mined1.c -----------------
  15. sed 's/^,//' << \EOSED > mined1.c
  16. ,/*  ==================================================================    *
  17. , *                Editor mined                *
  18. , *                Part 1                    *
  19. , *            for documentation see mined.doc            *
  20. , *  ==================================================================    */
  21. ,
  22. ,#include "mined.h"
  23. ,
  24. ,/* #define DEBUG */
  25. ,
  26. ,/*  ==================================================================    *
  27. , *            Definitions specific for mined1.c        *
  28. , *  ==================================================================    */
  29. ,
  30. ,#ifdef unix
  31. ,#define helpcommand "man mined"
  32. ,#define printcommand "lpr %s"
  33. ,#endif
  34. ,#ifdef vms
  35. ,#define helpcommand "help mined"
  36. ,#define printcommand "print %s"
  37. ,#endif
  38. ,#ifdef msdos
  39. ,#define helpcommand "more < \\mined\\mined.hlp"
  40. ,/* #define helpcommand "list \\Dienste\\mined\\mined.hlp" */
  41. ,#define printcommand "copy %s prn:"
  42. ,#endif
  43. ,
  44. ,/*  ==================================================================    *
  45. , *                Data section                *
  46. , *  ==================================================================    */
  47. ,
  48. ,extern int (* key_map [256]) ();
  49. ,extern int (* pc_key_map [256]) ();
  50. ,
  51. ,LINE * header;            /* Head of line list */
  52. ,LINE * tail;            /* Last line in line list */
  53. ,LINE * cur_line;        /* Current line in use */
  54. ,LINE * top_line;        /* First line of screen */
  55. ,LINE * bot_line;        /* Last line of screen */
  56. ,char * cur_text;        /* Current char on current line in use */
  57. ,int last_y;            /* Last y of screen. Usually SCREENMAX */
  58. ,int x = 0, y = 0;        /* x, y coordinates on screen */
  59. ,
  60. ,short YMAX, XMAX;
  61. ,char screen [screen_BUFL];    /* I/O buffer for "writes" and "reads" */
  62. ,int nlines;            /* Number of lines in file */
  63. ,FLAG modified = FALSE;        /* Set when file is modified */
  64. ,FLAG viewonly = FALSE;        /* Set when view only mode is selected */
  65. ,FLAG overwriteOK = FALSE;    /* Set if current file is OK for overwrite */
  66. ,FLAG writable;            /* Set if file cannot be written */
  67. ,FLAG loading = TRUE;        /* Loading a file? Init TRUE for error handling */
  68. ,FLAG quit = FALSE;        /* Set when quit character is typed */
  69. ,FLAG intr = FALSE;        /* Set when intr character is typed */
  70. ,FLAG winchg = FALSE;        /* Set when window size has changed */
  71. ,FLAG isscreenmode = FALSE;    /* Set when screen mode is on */
  72. ,FLAG stat_visible;        /* Set if status_line is visible */
  73. ,FLAG pagewrapped = FALSE;    /* Did output on the bottom line wrap and scroll? */
  74. ,FLAG waitingforinput = FALSE;    /* Set while waiting for the next command key */
  75. ,FLAG rpipe = FALSE;        /* Set if file should be read from stdin */
  76. ,FLAG wpipe = FALSE;        /* Set if file should be written to stdout */
  77. ,FLAG multiexit = FALSE;        /* Should exit command go to next file? */
  78. ,long chars_saved;        /* Nr of chars in buffer */
  79. ,int input_fd = STD_IN;        /* File descriptors for terminal dialog */
  80. ,int output_fd = STD_ERR;
  81. ,int out_count = 0;        /* Index in output buffer */
  82. ,char file_name [maxLINE_LEN];    /* Name of file in use */
  83. ,char text_buffer [MAX_CHARS];    /* for get_line, modifications, build_string */
  84. ,char blank_line [maxLINE_LEN];    /* Line filled with spaces, in case terminal cannot clear line */
  85. ,int hop_flag = 0;        /* Counter for the HOP function */
  86. ,#ifdef msdos
  87. ,char SHIFT_MARK = 175;        /* Char indicating that line continues */
  88. ,#else
  89. ,char SHIFT_MARK = '╗';        /* Char indicating that line continues */
  90. ,#endif
  91. ,char SHIFT_BEG = '\0';        /* Char indicating that line continues left */
  92. ,char TABchar = ' ';        /* Char to be shown in place of tab chars */
  93. ,char RET_MARK = '\0';        /* Char indicating end of line */
  94. ,char RET_BLANK = '\0';        /* Char to fill the end of line with */
  95. ,char RET_BLANK2 = '\0';        /* Char to fill last position of line with */
  96. ,#ifdef vms
  97. ,int fprot = 0;            /* To be used for all file creatings */
  98. ,#else
  99. ,int fprot = 0644;        /* To be used for all file creatings */
  100. ,#endif
  101. ,int panic_level = 0;        /* To adjust error handling to situation */
  102. ,int fnami;            /* Parameter index of current file name */
  103. ,int fnami_min, fnami_max, fnami_cnt;
  104. ,char * (* fnamv) [];
  105. ,/*
  106. , * Yank variables.
  107. , */
  108. ,FLAG yank_status = NOT_VALID;        /* Status of yank_file */
  109. ,char * temp_dir;
  110. ,char yank_file [maxLINE_LEN];
  111. ,char yankie_file [maxLINE_LEN];
  112. ,char panic_file [maxLINE_LEN];
  113. ,
  114. ,/*  ==================================================================    *
  115. , *                Output                    *
  116. , *  ==================================================================    */
  117. ,
  118. ,#ifdef msdos
  119. ,#define iscontrol(c)    (((c) == '\177') || ((u_char) c < (u_char) ' '))
  120. ,#else
  121. ,#define iscontrol(c)    (((c) == '\177') || ((u_char) ((c) & '\177') < (u_char) ' '))
  122. ,#endif
  123. ,#define controlchar(c)    (((c) == '\177') ? '?' : (c) + '@')
  124. ,
  125. ,/*
  126. , * Flush the I/O buffer on filedescriptor fd.
  127. ,flush () is flush_buffer (output_fd)
  128. , */
  129. ,flush_buffer (fd)
  130. ,  int fd;
  131. ,{
  132. ,  if (out_count <= 0)        /* There is nothing to flush */
  133. ,    return FINE;
  134. ,#ifdef conio
  135. ,  if (fd == output_fd) {
  136. ,    cputs (screen);
  137. ,  }
  138. ,  else
  139. ,#endif
  140. ,  if (write (fd, screen, out_count) != out_count) {
  141. ,    bad_write (fd);
  142. ,    return ERRORS;
  143. ,  }
  144. ,  clear_buffer (); /* Empty buffer: out_count = 0; */
  145. ,  return FINE;
  146. ,}
  147. ,
  148. ,/*
  149. , * Bad_write () is called when a write failed. Notify the user.
  150. , */
  151. ,bad_write (fd)
  152. ,  int fd;
  153. ,{
  154. ,  if (fd == output_fd) {    /* Cannot write to terminal? */
  155. ,    raw_mode (OFF);
  156. ,    panicio ("Write error on terminal", NIL_PTR);
  157. ,  }
  158. ,
  159. ,  clear_buffer (); /* out_count = 0; */
  160. ,  ring_bell ();
  161. ,  error ("Write aborted (File incomplete): ", serror ());
  162. ,}
  163. ,
  164. ,/*
  165. , * Write_char does a buffered output.
  166. ,putchar (c) is writechar (output_fd, (c))
  167. , */
  168. ,writechar (fd, c)
  169. ,  int fd;
  170. ,  char c;
  171. ,{
  172. ,  if (c == '\n') if (fd == output_fd) {
  173. ,    writechar (fd, '\015');
  174. ,  }
  175. ,  screen [out_count ++] = c;
  176. ,  if (out_count == screen_BUFL)    /* Flush on screen_BUFL chars */
  177. ,    return flush_buffer (fd);
  178. ,#ifdef DEBUG
  179. ,  if (fd == output_fd) flush ();
  180. ,#endif
  181. ,  return FINE;
  182. ,}
  183. ,
  184. ,/*
  185. , * Writestring writes the given string on the given filedescriptor.
  186. , * (buffered via writechar via screen !)
  187. ,putstring (str) is writestring (output_fd, (str))
  188. , */
  189. ,writestring (fd, text)
  190. ,  register int fd;
  191. ,  register char * text;
  192. ,{
  193. ,  while (* text)
  194. ,     if (writechar (fd, * text ++) == ERRORS)
  195. ,        return ERRORS;
  196. ,  return FINE;
  197. ,}
  198. ,
  199. ,/*
  200. , * Print string on terminal, printing controls with ^.
  201. , */
  202. ,int lpos = 0;
  203. ,print_char (c, limit)
  204. ,  register u_char c;
  205. ,  register int limit;
  206. ,{
  207. ,  if (lpos == limit) {putchar (SHIFT_MARK); return ERRORS;}
  208. ,  lpos ++;
  209. ,  if (iscontrol (c)) {
  210. ,    if (putchar ('^') == ERRORS) return ERRORS;
  211. ,    if (lpos == limit) {putchar (SHIFT_MARK); return ERRORS;}
  212. ,    lpos ++;
  213. ,    return putchar (controlchar (c));
  214. ,  }
  215. ,  else return putchar (c);
  216. ,}
  217. ,print_string (text, limit)
  218. ,  register char * text;
  219. ,  register int limit;
  220. ,{
  221. ,  lpos = 0;
  222. ,  while (* text != '\0')
  223. ,     if (print_char (* text ++, limit) == ERRORS)
  224. ,        return ERRORS;
  225. ,  return FINE;
  226. ,}
  227. ,
  228. ,/*  ==================================================================    *
  229. , *            Buffer oriented output                *
  230. , *  ==================================================================    */
  231. ,/*
  232. , * Convert cnt to nearest tab position
  233. , */
  234. ,#define tab(cnt)        (((cnt) + 8) & ~07)
  235. ,#define is_tab(c)        ((c) == '\t')
  236. ,
  237. ,/*
  238. , * Put_line prints the given line on the standard output.
  239. , * If offset is not zero, printing will start at that x-coordinate.
  240. , * If the FLAG clear_line is TRUE, then the screen line will be cleared
  241. , * when the end of the line has been reached.
  242. ,line_print (line) is put_line (line, 0, TRUE)
  243. , * put_line is directly called only by S () and delete_text ()
  244. , */
  245. ,put_line (line, offset, clear_line)
  246. ,  LINE * line;        /* Line to print */
  247. ,  int offset;        /* Offset to start */
  248. ,  FLAG clear_line;    /* Clear to eoln if TRUE */
  249. ,{
  250. ,  register char * textp = line->text;
  251. ,  register int count = get_shift (line->shift_count) * - SHIFT_SIZE;
  252. ,  int count_ini = count;
  253. ,  int tab_count;            /* Used in tab expansion */
  254. ,
  255. ,/* Skip all chars as indicated by the offset and the shift_count field */
  256. ,  while (count < offset) {
  257. ,    if (is_tab (* textp ++))
  258. ,        count = tab (count);
  259. ,    else
  260. ,        count ++;
  261. ,  }
  262. ,
  263. ,  if (count == 0 && count_ini < 0 && SHIFT_BEG != '\0') {
  264. ,    putchar (SHIFT_BEG);
  265. ,    count ++;
  266. ,    if (! is_tab (* textp)) textp ++;
  267. ,  }
  268. ,
  269. ,  while (* textp != '\n' && count < XBREAK) {
  270. ,    if (is_tab (* textp)) {        /* Expand tabs to spaces */
  271. ,        tab_count = tab (count);
  272. ,        while (count < XBREAK && count < tab_count) {
  273. ,            count ++;
  274. ,            putchar (TABchar);
  275. ,        }
  276. ,        textp ++;
  277. ,    }
  278. ,    else {
  279. ,        if (iscontrol (* textp)) {
  280. ,            reverse_on ();
  281. ,            putchar (controlchar (* textp));
  282. ,            reverse_off ();
  283. ,            textp ++;
  284. ,        }
  285. ,        else
  286. ,            putchar (* textp ++);
  287. ,    count ++;
  288. ,    }
  289. ,  }
  290. ,
  291. ,/* If line is longer than XBREAK chars, print the shift_mark */
  292. ,  if (count == XBREAK && * textp != '\n')
  293. ,    putchar (SHIFT_MARK);
  294. ,
  295. ,/* Mark end of line if so desired */
  296. ,  if (* textp == '\n' && RET_MARK != '\0') {
  297. ,    putchar (RET_MARK);
  298. ,    count ++;
  299. ,    if (RET_BLANK) {
  300. ,        while (count < XBREAK) {
  301. ,            putchar (RET_BLANK);
  302. ,            count ++;
  303. ,        }
  304. ,        if (RET_BLANK2) putchar (RET_BLANK2);
  305. ,    }
  306. ,  }
  307. ,
  308. ,/* Clear the rest of the line if clear_line is TRUE */
  309. ,  if (clear_line == TRUE) {
  310. ,     if (can_clear_eol == TRUE)
  311. ,    clear_eol ();
  312. ,     else {
  313. ,    while (count ++ <= XBREAK)
  314. ,        putchar (' ');
  315. ,     }
  316. ,     putchar ('\n');
  317. ,  }
  318. ,}
  319. ,
  320. ,/*
  321. , * Proceed returns the count'th line after `line'. When count is negative
  322. , * it returns the count'th line before `line'. When the next (previous)
  323. , * line is the tail (header) indicating EOF (tof) it stops.
  324. , */
  325. ,LINE *
  326. ,proceed (line, count)
  327. ,  register LINE * line;
  328. ,  register int count;
  329. ,{
  330. ,  if (count < 0)
  331. ,    while (count ++ < 0 && line != header)
  332. ,        line = line->prev;
  333. ,  else
  334. ,    while (count -- > 0 && line != tail)
  335. ,        line = line->next;
  336. ,  return line;
  337. ,}
  338. ,
  339. ,/*
  340. , * Reset assigns bot_line, top_line and cur_line according to `head_line'
  341. , * which must be the first line of the screen, and a y-coordinate,
  342. , * which will be the current y-coordinate (if it isn't larger than last_y)
  343. , */
  344. ,reset (head_line, screen_y)
  345. ,  LINE * head_line;
  346. ,  int screen_y;
  347. ,{
  348. ,  register LINE * line;
  349. ,
  350. ,  top_line = line = head_line;
  351. ,
  352. ,/* Search for bot_line (might be last line in file) */
  353. ,  for (last_y = 0; last_y < nlines - 1 && last_y < SCREENMAX
  354. ,                    && line->next != tail; last_y ++)
  355. ,    line = line->next;
  356. ,
  357. ,  bot_line = line;
  358. ,  y = (screen_y > last_y) ? last_y : screen_y;
  359. ,
  360. ,/* Set cur_line according to the new y value */
  361. ,  cur_line = proceed (top_line, y);
  362. ,}
  363. ,
  364. ,/*
  365. , * Display () shows count + 1 lines on the terminal starting at the given
  366. , * coordinates. When the tail of the list is encountered it will fill the
  367. , * rest of the screen with blank_line's.
  368. , * When count is negative, a backwards print from `line' will be done.
  369. , */
  370. ,display (x_coord, y_coord, line, count)
  371. ,  int x_coord, y_coord;
  372. ,  register LINE * line;
  373. ,  register int count;
  374. ,{
  375. ,  set_cursor (x_coord, y_coord);
  376. ,
  377. ,/* Find new startline if count is negative */
  378. ,  if (count < 0) {
  379. ,    line = proceed (line, count);
  380. ,    count = - count;
  381. ,  }
  382. ,
  383. ,/* Print the lines */
  384. ,  while (line != tail && count -- >= 0) {
  385. ,    line_print (line);
  386. ,    line = line->next;
  387. ,  }
  388. ,
  389. ,/* Print the blank lines (if any) */
  390. ,  if (loading == FALSE) {
  391. ,    while (count -- >= 0) {
  392. ,        clear_eol ();
  393. ,        putchar ('\n');
  394. ,    }
  395. ,  }
  396. ,}
  397. ,
  398. ,/*
  399. , * Redraw the screen
  400. , */
  401. ,RD ()
  402. ,{
  403. ,  reverse_off ();
  404. ,  clear_screen ();
  405. ,
  406. ,/* Print first page */
  407. ,  display (0, 0, top_line, last_y);
  408. ,
  409. ,/* Clear last line */
  410. ,  set_cursor (0, YMAX);
  411. ,  clear_eol ();
  412. ,  move_y (y);
  413. ,  if (stat_visible == TRUE) rd_bottom_line ();
  414. ,}
  415. ,
  416. ,/*  ==================================================================    *
  417. , *            Terminal Dialog                    *
  418. , *  ==================================================================    */
  419. ,
  420. ,/*
  421. , * promptyn reads in a 'y' or 'n' character.
  422. , */
  423. ,u_char
  424. ,promptyn ()
  425. ,{
  426. ,  register u_char c;
  427. ,  while ((c = readchar ()) != 'y' && c != 'n' && c != '\033' && quit == FALSE) {
  428. ,    ring_bell ();
  429. ,    flush ();
  430. ,  }
  431. ,  if (c == '\033') quit = TRUE;
  432. ,  return c;
  433. ,}
  434. ,
  435. ,/*
  436. , * Adjust current window size after WINCH signal
  437. , */
  438. ,RDwin ()
  439. ,{
  440. ,  register LINE * current_line;
  441. ,
  442. ,  winchg = FALSE;
  443. ,  getwinsize ();
  444. ,
  445. ,  current_line = cur_line;
  446. ,  reset (top_line, y);
  447. ,/*  move_y (find_y_w_o_RD (current_line)); */
  448. ,  move_address (cur_text, find_y_w_o_RD (current_line));
  449. ,  RD ();
  450. ,  flush ();
  451. ,}
  452. ,
  453. ,/*
  454. , * In case of a QUIT signal, swallow the dummy char generated by catchquit ()
  455. , * called by re_search () and change ()
  456. , */
  457. ,swallow_dummy_quit_char ()
  458. ,{
  459. ,#ifdef UNUSED
  460. ,  readchar (); /* Swallow away a quit character delivered by QUIT */
  461. ,/* Not needed because this character is ignored by being the CANCEL command */
  462. ,#endif UNUSED
  463. ,}
  464. ,
  465. ,/*
  466. , * Readchar () reads one character from the terminal.
  467. , * There are problems due to interruption of the read operation by signals
  468. , * (QUIT, WINCH). The waitingforinput flag is only a partial solution.
  469. , * Unix doesn't provide sufficient facilities to handle these situations
  470. , * neatly and properly. Moreover, different Unix versions yield different
  471. , * surprising effects. However, the use of select () could still be
  472. , * an improvement.
  473. , */
  474. ,readchar ()
  475. ,{
  476. ,  register u_char c;
  477. ,
  478. ,  waitingforinput = TRUE;
  479. ,/*  if (winchg == TRUE) RDwin (); /* This is now done in __readchar () */
  480. ,  c = _readchar ();
  481. ,  waitingforinput = FALSE;
  482. ,  /* the modification   if (quit == TRUE) c = QUITCHAR;   (now in __readchar)
  483. ,     must not be placed after resetting the flag  waitingforinput = FALSE;  .
  484. ,     Otherwise a QUIT signal coming in just between these two would
  485. ,     discard the last valid character just taken up. */
  486. ,  return c;
  487. ,}
  488. ,
  489. ,/*-------------------------------------------------------------------------*/
  490. ,
  491. ,#ifndef msdos
  492. ,
  493. ,#ifdef msdos
  494. ,#ifndef single_pass_compilation
  495. ,/* This seems to conflict with the same declaration in minedmp.c when
  496. ,   compiled with Turbo-C. C is just too stupid a language.
  497. ,   Luckily, we don't need this part at all on MSDOS */
  498. ,extern struct {char * fk; int (* fp) ();} keycode [];
  499. ,#endif
  500. ,#else
  501. ,extern struct {char * fk; int (* fp) ();} keycode [];
  502. ,#endif
  503. ,#define MAXCODELEN 7 /* max. length of function key sequence to be detected,
  504. ,            depending on the keycode table */
  505. ,
  506. ,/*
  507. , * queue collects the keys of an Escape sequence typed in until the 
  508. , * sequence can be detected or rejected.
  509. , * If the queue is not empty, queue [0] contains the character next 
  510. , * to be delivered by _readchar () (it's not a ring buffer).
  511. , * The queue contents is always terminated by a '\0', so queue can also 
  512. , * be taken as a character string.
  513. , */
  514. ,static u_char queue [MAXCODELEN + 1], * endp = queue;
  515. ,
  516. ,int
  517. ,q_empty ()
  518. ,{
  519. ,  return (endp == queue ? 1 : 0);
  520. ,}
  521. ,
  522. ,int
  523. ,q_notfull ()
  524. ,{
  525. ,  return (endp - queue == MAXCODELEN ? 0 : 1);
  526. ,}
  527. ,
  528. ,q_clear ()
  529. ,{
  530. ,  endp = queue;
  531. ,}
  532. ,
  533. ,int
  534. ,q_len ()
  535. ,{
  536. ,  return endp - queue;
  537. ,}
  538. ,
  539. ,q_put (c)
  540. ,  u_char c;
  541. ,/* queue must not be full prior to this call! */
  542. ,{
  543. ,  * endp = c;
  544. ,  * ++ endp = '\0';
  545. ,}
  546. ,
  547. ,u_char
  548. ,q_get ()
  549. ,{
  550. ,  u_char c;
  551. ,  register u_char * pd, * ps;
  552. ,
  553. ,  c = * queue; pd = queue; ps = pd + 1;
  554. ,  while (ps <= endp) * pd ++ = * ps ++;
  555. ,  if (endp > queue) endp --;
  556. ,  return c;
  557. ,}
  558. ,
  559. ,/*
  560. , * Look up key sequence in keycode table.
  561. , * findkey (str) >=  0: str == keycode [findkey (str)].fk
  562. , *         == -1: str is prefix of some entry in keycode
  563. , *         == -2: str is not contained in keycode
  564. , */
  565. ,int
  566. ,findkey (str)
  567. ,  char * str;
  568. ,{
  569. ,  static int lastmatch = 0;    /* last index with string matching prefix */
  570. ,  register int i;
  571. ,
  572. ,  if (keycode [0].fk == NIL_PTR) return -2;
  573. ,  i = lastmatch;
  574. ,  do {
  575. ,    if (strncmp (str, keycode [i].fk, strlen (str)) == 0) {
  576. ,        lastmatch = i;
  577. ,        return (strlen (str) == strlen (keycode [i].fk) ? i : -1);
  578. ,    }
  579. ,    ++ i;
  580. ,    if (keycode [i].fk == NIL_PTR) i = 0;
  581. ,  } while (i != lastmatch);
  582. ,  return -2;
  583. ,}
  584. ,
  585. ,/*
  586. , * Is a character available within a specified number of milliseconds ?
  587. , */
  588. ,char_ready_within (msec)
  589. ,  int msec;
  590. ,{
  591. ,  return (q_len () > 0) || inputreadyafter (input_fd, msec);
  592. ,}
  593. ,
  594. ,#else ndef msdos
  595. ,
  596. ,char_ready_within (msec)
  597. ,  int msec;
  598. ,{
  599. ,  return 0;
  600. ,}
  601. ,
  602. ,#endif def msdos
  603. ,
  604. ,extern I ();
  605. ,int (* keyproc) () = I;
  606. ,
  607. ,extern grave ();
  608. ,extern circumflex ();
  609. ,extern acute ();
  610. ,extern diaeresis ();
  611. ,extern tilde ();
  612. ,extern angstrom ();
  613. ,
  614. ,/*
  615. , * Read a character from terminal, considering function keys and 
  616. , * composing special character of an 8 bit character set.
  617. , * _readchar () takes the following actions:
  618. , *  -    function key sequences according to the table 'keycode' are 
  619. , *    transformed into a special controlling character which is 
  620. , *    assigned the function FUNKEY. Also the intended editor function, 
  621. , *    as taken from the table 'keycode', is saved in a variable for 
  622. , *    use by FUNKEY.
  623. , *  -    the prefix keys for diacritic and special characters are 
  624. , *    combined with the following key to make up the character.
  625. , */
  626. ,_readchar ()
  627. ,{
  628. ,  register u_char ch;
  629. ,  int res;
  630. ,
  631. ,#ifndef msdos
  632. ,  if (q_len () > 0) return q_get ();
  633. ,#endif
  634. ,  ch = __readchar ();
  635. ,#ifdef msdos
  636. ,  if (ch == '\000') {
  637. ,    ch = __readchar ();
  638. ,    keyproc = pc_key_map [ch];
  639. ,#ifdef DEBUG
  640. ,    if (keyproc == I) return ch;
  641. ,#endif
  642. ,    if ((keyproc == grave) || (keyproc == circumflex)
  643. ,         || (keyproc == acute) || (keyproc == diaeresis)
  644. ,         || (keyproc == tilde) || (keyproc == angstrom))
  645. ,        {ch = (* keyproc) (readchar ());
  646. ,         keyproc = I;
  647. ,         return ch;
  648. ,        }
  649. ,    else return FUNcmd /* index of FUNKEY */;
  650. ,  }
  651. ,#else
  652. ,  if (ch == '\033') {
  653. ,    /* q_clear (); */
  654. ,    q_put (ch);
  655. ,    while  ((res = findkey (queue)) == -1 /* prefix of table entry */
  656. ,        && q_notfull ()
  657. ,        && inputreadyafter (input_fd, 300)
  658. ,           )
  659. ,        q_put (__readchar ());
  660. ,    if (quit == TRUE) return '\0';
  661. ,    else if (res < 0) /* key pattern not detected in keycode table */
  662. ,         /* {if (q_len () > 1) return 0;
  663. ,         else return ch;} */
  664. ,         return q_get () /* just deliver the typed characters */;
  665. ,    else {
  666. ,         q_clear ();
  667. ,         keyproc = keycode [res].fp;
  668. ,         if ((keyproc == grave) || (keyproc == circumflex)
  669. ,         || (keyproc == acute) || (keyproc == diaeresis)
  670. ,         || (keyproc == tilde) || (keyproc == angstrom))
  671. ,        {ch = (* keyproc) (readchar ());
  672. ,         keyproc = I;
  673. ,         return ch;
  674. ,        }
  675. ,         else return FUNcmd /* index of FUNKEY */;
  676. ,    }
  677. ,  }
  678. ,#endif
  679. ,  else
  680. ,    return ch;
  681. ,}
  682. ,
  683. ,/*  ==================================================================    *
  684. , *            Status Line Dialog                *
  685. , *  ==================================================================    */
  686. ,
  687. ,/*
  688. , * Show concatenation of s1 and s2 on the status line (bottom of screen)
  689. , * If revfl is TRUE, turn on reverse video on both strings. Set stat_visible
  690. , * only if bottom_line is visible.
  691. , * The return value is FINE except for get_string, where it is taken
  692. , * from the call to input ().
  693. ,status_line (str1, str2)    is bottom_line (ON, (str1), (str2), NIL_PTR, FALSE)
  694. ,error (str1, str2)        is bottom_line (ON, (str1), (str2), NIL_PTR, FALSE)
  695. ,get_string (str1, str2, fl) is bottom_line (ON, (str1), NIL_PTR, (str2), fl)
  696. ,clear_status ()            is bottom_line (OFF, NIL_PTR, NIL_PTR, NIL_PTR, FALSE)
  697. ,status_msg (str)        is status_line (str, NIL_PTR)
  698. ,status_beg (str)        is bottom_line (ON, (str), NIL_PTR, NIL_PTR, TRUE)
  699. , */
  700. ,FLAG lastrevfl;
  701. ,char * lastinbuf;
  702. ,FLAG input_active = FALSE;
  703. ,char status_buf [maxLINE_LEN];
  704. ,
  705. ,rd_bottom_line ()
  706. ,{
  707. ,  set_cursor (0, YMAX);
  708. ,  reverse_on ();
  709. ,  if (lastinbuf == NIL_PTR)
  710. ,    print_string (status_buf, XBREAK);
  711. ,  else {
  712. ,    print_string (status_buf, -1);
  713. ,    print_string (lastinbuf, -1);
  714. ,  }
  715. ,  if (! input_active) {
  716. ,    reverse_off ();
  717. ,    set_cursor (x, y);    /* Set cursor back to old position */
  718. ,  }
  719. ,  flush ();    /* Perform the actual screen output */
  720. ,}
  721. ,
  722. ,int
  723. ,bottom_line (revfl, s1, s2, inbuf, statfl)
  724. ,  FLAG revfl;
  725. ,  char * s1, * s2;
  726. ,  char * inbuf;
  727. ,  FLAG statfl;
  728. ,{
  729. ,  int ret = FINE;
  730. ,
  731. ,  if (inbuf != NIL_PTR) * inbuf = '\0';
  732. ,  lastrevfl = revfl;
  733. ,  lastinbuf = inbuf;
  734. ,
  735. ,  if (pagewrapped == TRUE) {
  736. ,    status_buf [0] = '\0';
  737. ,    RD ();
  738. ,    pagewrapped = FALSE;
  739. ,  }
  740. ,
  741. ,  build_string (status_buf, " %s%s ", unnull (s1), unnull (s2));
  742. ,        /* (s1 == NIL_PTR) ? "" : s1, (s2 == NIL_PTR) ? "" : s2); */
  743. ,
  744. ,  if (revfl == ON && stat_visible == TRUE) {
  745. ,    set_cursor (0, YMAX);
  746. ,    clear_eol ();
  747. ,  }
  748. ,  set_cursor (0, YMAX);
  749. ,  if (revfl == ON) {        /* Print rev. start sequence */
  750. ,    reverse_on ();
  751. ,    stat_visible = TRUE;
  752. ,  }
  753. ,  else                /* Used as clear_status () */
  754. ,    stat_visible = FALSE;
  755. ,
  756. ,  if (inbuf == NIL_PTR)
  757. ,    print_string (status_buf, XBREAK);
  758. ,  else {
  759. ,    print_string (status_buf, -1);
  760. ,    input_active = TRUE;
  761. ,    ret = input (inbuf, statfl);
  762. ,    input_active = FALSE;
  763. ,  }
  764. ,
  765. ,  /* Print normal video */
  766. ,  reverse_off ();
  767. ,  clear_eol ();
  768. ,
  769. ,  if (inbuf != NIL_PTR) {
  770. ,    set_cursor (0, YMAX);
  771. ,  }
  772. ,  else if (statfl == TRUE)
  773. ,    reverse_on ();
  774. ,  else
  775. ,    set_cursor (x, y);    /* Set cursor back to old position */
  776. ,
  777. ,  flush ();    /* Perform the actual screen output */
  778. ,  if (ret != FINE) clear_status ();
  779. ,  return ret;
  780. ,}
  781. ,
  782. ,/*
  783. , * Input () reads a string from the terminal.
  784. , * Return values:
  785. , *    when QUIT character typed => ERRORS
  786. , *    when empty input and clearfl == TRUE: NO_INPUT
  787. , *    else: FINE
  788. , */
  789. ,input (inbuf, clearfl)
  790. ,  u_char * inbuf;
  791. ,  FLAG clearfl;
  792. ,{
  793. ,  register u_char * ptr;
  794. ,  register u_char c;
  795. ,
  796. ,  ptr = inbuf;
  797. ,  * ptr = '\0';
  798. ,  while (quit == FALSE) {
  799. ,    flush ();
  800. ,    if (lpos >= XBREAK) pagewrapped = TRUE;
  801. ,    switch (c = readchar ()) {
  802. ,        case '\b' :        /* Erase previous char */
  803. ,        case '\177' /* DEL */ :
  804. ,            if (ptr > inbuf) {
  805. ,                ptr --;
  806. ,                reverse_off ();
  807. ,                if (iscontrol (* ptr)) {
  808. ,                    putstring (" \b\b\b  \b\b");
  809. ,                    lpos = lpos - 2;
  810. ,                }
  811. ,                else {
  812. ,                    putstring (" \b\b \b");
  813. ,                    lpos = lpos - 1;
  814. ,                }
  815. ,                reverse_on ();
  816. ,                putstring (" \b");
  817. ,                * ptr = '\0';
  818. ,            }
  819. ,            else
  820. ,                ring_bell ();
  821. ,            break;
  822. ,        case QUITCHAR :
  823. ,        case '\033' :
  824. ,            quit = TRUE;
  825. ,            break;
  826. ,        case '\n' :        /* End of input */
  827. ,        case '\015' :
  828. ,            /* If inbuf is empty clear status_line */
  829. ,            return (ptr == inbuf && clearfl == TRUE) ?
  830. ,                NO_INPUT : FINE;
  831. ,        default :
  832. ,            if (c == '\026' /* ^V */) c = readchar ();
  833. ,            if ((ptr - inbuf) < maxLINE_LEN) {
  834. ,                if ((c > '\0')) {
  835. ,                    * ptr ++ = c;
  836. ,                    * ptr = '\0';
  837. ,                    print_char (c, -1);
  838. ,                    putstring (" \b");
  839. ,                }
  840. ,                else
  841. ,                    ring_bell ();
  842. ,            }
  843. ,            else
  844. ,                ring_bell ();
  845. ,    }
  846. ,  }
  847. ,  quit = FALSE;
  848. ,  return ERRORS;
  849. ,}
  850. ,
  851. ,/*
  852. , * Get_number () reads a number from the terminal.
  853. , * The last character typed in is returned.
  854. , * ERRORS is returned on a bad number or on interrupted input.
  855. , * The resulting number is put into the integer the arguments points to.
  856. , */
  857. ,get_number (message, firstdigit, result)
  858. ,  char * message;
  859. ,  char firstdigit;
  860. ,  int * result;
  861. ,{
  862. ,  register int index;
  863. ,  register int count;
  864. ,
  865. ,  status_beg (message);
  866. ,
  867. ,  if (firstdigit > '\0')
  868. ,    index = firstdigit;
  869. ,  else
  870. ,    index = readchar ();
  871. ,
  872. ,  if (index == QUITCHAR) quit = TRUE;
  873. ,  if (index == '\033') quit = TRUE;
  874. ,  if (quit == FALSE && (index < '0' || index > '9')) {
  875. ,    error ("Bad number", NIL_PTR);
  876. ,    return ERRORS;
  877. ,  }
  878. ,
  879. ,/* Convert input to a decimal number */
  880. ,  count = 0;
  881. ,  while (index >= '0' && index <= '9' && quit == FALSE) {
  882. ,    print_char (index, -1); flush ();
  883. ,    if (lpos >= XBREAK) pagewrapped = TRUE;
  884. ,    count *= 10;
  885. ,    count += index - '0';
  886. ,    index = readchar ();
  887. ,    if (index == QUITCHAR) quit = TRUE;
  888. ,    if (index == '\033') quit = TRUE;
  889. ,  }
  890. ,
  891. ,  clear_status ();
  892. ,  if (quit == TRUE) {
  893. ,    clear_status ();
  894. ,    return ERRORS;
  895. ,  }
  896. ,  * result = count;
  897. ,  return index;
  898. ,}
  899. ,
  900. ,/*
  901. , * get_digits () reads in a number. In contrast to get_number, it does no
  902. , * echoing, no messaging, and it does not require any digits at all.
  903. , * The last character typed in is returned.
  904. , * The resulting number is put into the integer the arguments points to.
  905. , */
  906. ,get_digits (result)
  907. ,  int * result;
  908. ,{
  909. ,  register int index;
  910. ,  register int count;
  911. ,
  912. ,  index = readchar ();
  913. ,  if (index == QUITCHAR) quit = TRUE;
  914. ,  * result = -1;
  915. ,/* Convert input to a decimal number */
  916. ,  count = 0;
  917. ,  while (index >= '0' && index <= '9' && quit == FALSE) {
  918. ,    count *= 10;
  919. ,    count += index - '0';
  920. ,    * result = count;
  921. ,    index = readchar ();
  922. ,    if (index == QUITCHAR) quit = TRUE;
  923. ,  }
  924. ,
  925. ,  if (quit == TRUE) {
  926. ,    return QUITCHAR;
  927. ,  }
  928. ,  return index;
  929. ,}
  930. ,
  931. ,/*
  932. , * Get_file () reads a filename from the terminal.
  933. , */
  934. ,int
  935. ,get_file (message, file)
  936. ,  char * message, * file;
  937. ,{
  938. ,  int ret = get_string (message, file, TRUE);
  939. ,#ifndef msdos
  940. ,  char * filei;
  941. ,  char file1 [maxLINE_LEN];
  942. ,
  943. ,  if (file [0] == '~' && file [1] == '/') {
  944. ,    filei = file; filei ++;
  945. ,    build_string (file1, "%s%s", unnull (getenv ("HOME")), filei);
  946. ,    build_string (file, file1);
  947. ,  }
  948. ,#endif
  949. ,  return ret;
  950. ,}
  951. ,
  952. ,/*  ==================================================================    *
  953. , *            Text buffer routines                *
  954. , *  ==================================================================    */
  955. ,
  956. ,/*
  957. , * Ask the user if he wants to save the file or not.
  958. , */
  959. ,ask_save ()
  960. ,{
  961. ,  register u_char c;
  962. ,
  963. ,  status_line (file_name [0] ? file_name : "[buffer]" ,
  964. ,            " has been modified. Save? (y/n)");
  965. ,    /* previously only basename (file_name) was printed */
  966. ,  c = promptyn ();
  967. ,  clear_status ();
  968. ,  if (c == 'y')
  969. ,    return WT ();
  970. ,  else if (c == 'n')
  971. ,    return FINE;
  972. ,  else {
  973. ,    quit = FALSE;    /* abort character has been given */
  974. ,    return ERRORS;
  975. ,  }
  976. ,}
  977. ,
  978. ,/*
  979. , * Ask user if named file should be overwritten.
  980. , */
  981. ,FLAG
  982. ,checkoverwrite (name)
  983. ,char * name;
  984. ,{
  985. ,  u_char c;
  986. ,
  987. ,  if (access (name, 0 /* F_OK */) < 0)    /* Cannot access file */
  988. ,    return TRUE;    /* thus no danger of unwanted damage */
  989. ,
  990. ,  status_line (name [0] ? name : "[buffer]" ,
  991. ,            ": OK to overwrite? (y/n)");
  992. ,    /* previously only basename (name) was printed */
  993. ,  c = promptyn ();
  994. ,  clear_status ();
  995. ,  if (c == 'y')
  996. ,    return TRUE;
  997. ,  else if (c == 'n')
  998. ,    return FALSE;
  999. ,  else {
  1000. ,/*    quit = FALSE;    /* abort character has been given */
  1001. ,    return FALSE;
  1002. ,  }
  1003. ,}
  1004. ,
  1005. ,/*
  1006. , * Attach new file name to buffer
  1007. , */
  1008. ,NN ()
  1009. ,{
  1010. ,  char file [maxLINE_LEN];    /* Buffer for new file name */
  1011. ,  if (get_file ("Enter new file name:", file) == ERRORS)
  1012. ,    return ERRORS;
  1013. ,  overwriteOK = FALSE;
  1014. ,  writable = TRUE;
  1015. ,  modified = TRUE;    /* cf. CHDI command */
  1016. ,  copy_string (file_name, file);    /* Save new file name */
  1017. ,/*  set_cursor (x, y);    /* Set cursor back to old position */
  1018. ,  clear_status ();
  1019. ,}
  1020. ,
  1021. ,/*
  1022. , * Write file in core to disc.
  1023. , */
  1024. ,/* Call graph for writing functions:
  1025. ,    panic --\
  1026. ,         > QUED --\
  1027. ,    ESC q --/       > ask_save --\
  1028. ,    ESC e ---> EDIT --/         \
  1029. ,    ESC v ---> VIEW -/          \
  1030. ,    ESC w -----------------------------> WT
  1031. ,    ESC z -----------> SUSP ----------/
  1032. ,    ESC ESC ---------> EXED ---------/
  1033. ,*/
  1034. ,long write_count    /* number of chars written */;
  1035. ,write_file (fd)
  1036. ,  int fd;
  1037. ,{
  1038. ,  register LINE * line;
  1039. ,
  1040. ,  write_count = 0L;
  1041. ,  clear_buffer (); /* out_count = 0; */
  1042. ,  for (line = header->next; line != tail; line = line->next) {
  1043. ,    if (line->shift_count & DUMMY) {
  1044. ,        if (line->next == tail && line->text [0] == '\n')
  1045. ,            continue;
  1046. ,    }
  1047. ,    if (writestring (fd, line->text) == ERRORS) {
  1048. ,        write_count = -1L;
  1049. ,        break;
  1050. ,    }
  1051. ,    write_count += (long) length_of (line->text);
  1052. ,  }
  1053. ,
  1054. ,  if (write_count > 0L && flush_buffer (fd) == ERRORS)
  1055. ,    write_count = -1L;
  1056. ,
  1057. ,  (void) close (fd);
  1058. ,}
  1059. ,
  1060. ,WT ()
  1061. ,{
  1062. ,  char file [maxLINE_LEN];    /* Buffer for new file name */
  1063. ,  int fd;            /* Filedescriptor of file */
  1064. ,  int ret;
  1065. ,
  1066. ,  if (wpipe) {
  1067. ,    fd = STD_OUT;
  1068. ,    status_line ("Writing ", "to standard output");
  1069. ,    wpipe = FALSE; /* no further write to same stream possible */
  1070. ,  }
  1071. ,  else {
  1072. ,    if (modified == FALSE) {
  1073. ,    status_msg ("Write not necessary.");
  1074. ,    return FINE;
  1075. ,    }
  1076. ,
  1077. ,    /* Check if file_name is valid and if file can be written */
  1078. ,    if (file_name [0] == '\0' || writable == FALSE) {
  1079. ,    overwriteOK = FALSE;
  1080. ,    if ((ret = get_file ("Enter file name:", file)) != FINE)
  1081. ,        return ret;
  1082. ,    copy_string (file_name, file);        /* Save file name */
  1083. ,    }
  1084. ,    if (overwriteOK == FALSE) {
  1085. ,    if (checkoverwrite (file_name) == TRUE)
  1086. ,        overwriteOK = TRUE;
  1087. ,    else {    if (quit == FALSE)
  1088. ,            writable = FALSE;
  1089. ,        return ERRORS;
  1090. ,    }
  1091. ,    }
  1092. ,    if ((fd = creat (file_name, fprot)) < 0) {    /* Empty file */
  1093. ,    error ("Cannot create or write: " /*, file_name */, serror ());
  1094. ,    writable = FALSE;
  1095. ,    return ERRORS;
  1096. ,    }
  1097. ,    else
  1098. ,    writable = TRUE;
  1099. ,
  1100. ,    status_line ("Writing ", file_name);
  1101. ,  }
  1102. ,
  1103. ,  write_file (fd);
  1104. ,
  1105. ,  if (write_count == -1L)
  1106. ,    return ERRORS;
  1107. ,
  1108. ,  modified = FALSE;
  1109. ,  rpipe = FALSE;    /* File name is now assigned */
  1110. ,
  1111. ,/* Display how many chars (and lines) were written */
  1112. ,  fstatus ("Wrote", write_count);
  1113. ,  return FINE;
  1114. ,}
  1115. ,
  1116. ,panic_write ()
  1117. ,{
  1118. ,  int fd;
  1119. ,  fd = creat (panic_file, fprot);
  1120. ,  write_file (fd);
  1121. ,  if (write_count == -1L)
  1122. ,    return ERRORS;
  1123. ,  else    return FINE;
  1124. ,}
  1125. ,
  1126. ,/*
  1127. , * Edit/view another file. If the current file has been modified, 
  1128. , * ask whether the user wants to save it.
  1129. , * (We could allow to switch between edit and view mode without changing 
  1130. , * the file, but we would have to consider carefully the relationship 
  1131. , * between viewonly and modified.)
  1132. , */
  1133. ,edit_file (prompt, vomode)
  1134. ,  char * prompt;
  1135. ,  FLAG vomode;
  1136. ,{
  1137. ,  char new_file [maxLINE_LEN];    /* Buffer to hold new file name */
  1138. ,
  1139. ,  if (modified == TRUE && ask_save () != FINE)
  1140. ,    return;
  1141. ,
  1142. ,  viewonly = vomode;
  1143. ,
  1144. ,/* Get new file name */
  1145. ,  if (get_file (prompt, new_file) == ERRORS)
  1146. ,    return;
  1147. ,
  1148. ,/* Free old linked list, initialize global variables and load new file */
  1149. ,  initialize ();
  1150. ,  clear_screen ();
  1151. ,  load_file (new_file [0] == '\0' ? NIL_PTR : new_file);
  1152. ,}
  1153. ,
  1154. ,EDIT ()
  1155. ,{
  1156. ,  edit_file ("Edit file:", FALSE);
  1157. ,}
  1158. ,
  1159. ,VIEW ()
  1160. ,{
  1161. ,  edit_file ("View file:", TRUE);
  1162. ,}
  1163. ,
  1164. ,edit_nth_file (n)
  1165. ,  int n;
  1166. ,{
  1167. ,  int number, index;
  1168. ,
  1169. ,  if (modified == TRUE && ask_save () != FINE)
  1170. ,    return;
  1171. ,
  1172. ,  if (n == -1) {
  1173. ,    index = get_number ("Edit which file (enter number) ...", '\0', & number);
  1174. ,    if (index == ERRORS) return;
  1175. ,    n = number - 1 + fnami_min;
  1176. ,  }
  1177. ,  if (n < fnami_min) n = fnami_min;
  1178. ,  if (n > fnami_max) n = fnami_max;
  1179. ,
  1180. ,/* Free old linked list, initialize global variables and load new file */
  1181. ,  initialize ();
  1182. ,  clear_screen ();
  1183. ,
  1184. ,  fnami = n;
  1185. ,  if (fnami < fnami_min) load_file (NIL_PTR);
  1186. ,  else load_file ((* fnamv) [fnami]);
  1187. ,}
  1188. ,
  1189. ,NXTFILE ()
  1190. ,{
  1191. ,  if (hop_flag > 0) edit_nth_file (fnami_max);
  1192. ,  else edit_nth_file (fnami + 1);
  1193. ,}
  1194. ,
  1195. ,PRVFILE ()
  1196. ,{
  1197. ,  if (hop_flag > 0) edit_nth_file (fnami_min);
  1198. ,  else edit_nth_file (fnami - 1);
  1199. ,}
  1200. ,
  1201. ,NTHFILE ()
  1202. ,{
  1203. ,  edit_nth_file (-1);
  1204. ,}
  1205. ,
  1206. ,/*
  1207. , * Leave editor. If the file has changed, ask if the user wants to save it.
  1208. , */
  1209. ,QUED ()
  1210. ,{
  1211. ,  if (modified == TRUE && ask_save () != FINE)
  1212. ,    return ERRORS;
  1213. ,
  1214. ,  delete_yank_file ();
  1215. ,  set_cursor (0, YMAX);
  1216. ,  putchar ('\n');
  1217. ,  raw_mode (OFF);
  1218. ,  exit (0);
  1219. ,}
  1220. ,
  1221. ,/*
  1222. , * Exit editor. If the file has changed, save it.
  1223. , */
  1224. ,EXED ()
  1225. ,{
  1226. ,  if (multiexit == TRUE) EXFILE ();
  1227. ,  else {
  1228. ,    if (modified == TRUE)
  1229. ,        if (WT () != FINE) return;
  1230. ,
  1231. ,    delete_yank_file ();
  1232. ,    set_cursor (0, YMAX);
  1233. ,    putchar ('\n');
  1234. ,    raw_mode (OFF);
  1235. ,    exit (0);
  1236. ,  }
  1237. ,}
  1238. ,
  1239. ,/*
  1240. , * Exit editing current file. If the file has changed, save it.
  1241. , * Edit next file if there is one.
  1242. , */
  1243. ,EXFILE ()
  1244. ,{
  1245. ,  if (modified == TRUE)
  1246. ,    if (WT () != FINE) return;
  1247. ,
  1248. ,  if (fnami < fnami_max) NXTFILE ();
  1249. ,  else {
  1250. ,    delete_yank_file ();
  1251. ,    set_cursor (0, YMAX);
  1252. ,    putchar ('\n');
  1253. ,    raw_mode (OFF);
  1254. ,    exit (0);
  1255. ,  }
  1256. ,}
  1257. ,
  1258. ,/*
  1259. , * Count_chars () count the number of chars that the line would occupy on the
  1260. , * screen. Counting starts at the real x-coordinate of the line.
  1261. , * Was only called by delete_text ().
  1262. , */
  1263. ,#ifdef UNUSED
  1264. ,count_chars (line)
  1265. ,  LINE * line;
  1266. ,{
  1267. ,  register int cnt = get_shift (line->shift_count) * - SHIFT_SIZE;
  1268. ,  register char * textp = line->text;
  1269. ,
  1270. ,/* Find begin of line on screen */
  1271. ,  while (cnt < 0) {
  1272. ,    if (is_tab (* textp ++))
  1273. ,        cnt = tab (cnt);
  1274. ,    else
  1275. ,        cnt ++;
  1276. ,  }
  1277. ,
  1278. ,/* Count number of chars left */
  1279. ,  cnt = 0;
  1280. ,  while (* textp != '\n') {
  1281. ,    if (is_tab (* textp ++))
  1282. ,         cnt = tab (cnt);
  1283. ,    else
  1284. ,        cnt ++;
  1285. ,  }
  1286. ,  return cnt;
  1287. ,}
  1288. ,#endif UNUSED
  1289. ,
  1290. ,/*-------------------------------------------------------------------------*/
  1291. ,
  1292. ,/*
  1293. , * move_to: move to given coordinates on screen.
  1294. , * move_y: move to given line on screen, staying in last explicit column.
  1295. , * move_address: move to given line at given text position.
  1296. , * The caller must check that scrolling is not needed.
  1297. , * If new x-position is < 0 or > XBREAK, move_it () will check if
  1298. , * the line can be shifted. If it can it sets (or resets) the shift_count
  1299. , * field of the current line accordingly. By this mechanism, the
  1300. , * pseudo-x-positions LINE_START / LINE_END (a very small / big value)
  1301. , * perform the appropriate positioning actions.
  1302. , * Move also sets cur_text to the right char.
  1303. , * "If we're moving to the same x coordinate, try to move the the x-coordinate
  1304. , * used on the other previous call." -- This worked erroneously and was 
  1305. , * replaced by an explicit old_x variable and move_y call.
  1306. , * move_address is directly called by move_next/previous_word(), re_search(), RDwin()
  1307. , */
  1308. ,int old_x = 0;
  1309. ,move_y (ny)
  1310. ,  register int ny;
  1311. ,{
  1312. ,  move_it (old_x, NIL_PTR, ny);
  1313. ,}
  1314. ,move_to (nx, ny)
  1315. ,  register int nx;
  1316. ,  register int ny;
  1317. ,{
  1318. ,  old_x = x;
  1319. ,  move_it (nx, NIL_PTR, ny);
  1320. ,  old_x = x;
  1321. ,}
  1322. ,move_address (nadd, ny)
  1323. ,  register char * nadd;
  1324. ,  register int ny;
  1325. ,{
  1326. ,  old_x = x;
  1327. ,  move_it (0, nadd, ny);
  1328. ,  old_x = x;
  1329. ,}
  1330. ,move_it (new_x, new_address, new_y)
  1331. ,  register int new_x;
  1332. ,  int new_y;
  1333. ,  char * new_address;
  1334. ,{
  1335. ,  register LINE * line = cur_line;    /* For building new cur_line */
  1336. ,  int shift = 0;            /* How many shifts to make */
  1337. ,/*  static int rel_x = 0;        /* Remember relative x position */
  1338. ,/*    This was used as a trick to stay virtually in the previous column 
  1339. ,    even when moving across shorter lines; but it had >= 2 errors.
  1340. ,    Renamed to old_x, made globally accessible and explicitly used 
  1341. ,    by appropriate calls to avoid these problems. TW */
  1342. ,  int tx = x;
  1343. ,  char * find_address ();
  1344. ,
  1345. ,/* Check for illegal values */
  1346. ,  if (new_y < 0 || new_y > last_y)
  1347. ,    return;
  1348. ,
  1349. ,/* Adjust y-coordinate and cur_line */
  1350. ,  if (new_y < y)
  1351. ,    while (y != new_y) {
  1352. ,        y --;
  1353. ,        line = line->prev;
  1354. ,    }
  1355. ,  else
  1356. ,    while (y != new_y) {
  1357. ,        y ++;
  1358. ,        line = line->next;
  1359. ,    }
  1360. ,
  1361. ,/* Set or unset relative x-coordinate */
  1362. ,  if (new_address == NIL_PTR) {
  1363. ,/*    new_address = find_address (line, (new_x == x) ? rel_x : new_x , & tx);
  1364. ,/*    if (new_x != x)
  1365. ,/*        rel_x = tx; */
  1366. ,    new_address = find_address (line, new_x , & tx);
  1367. ,    new_x = tx;
  1368. ,  }
  1369. ,  else
  1370. ,    /* rel_x = */ new_x = find_x (line, new_address);
  1371. ,
  1372. ,/* Adjust shift_count if new_x lower than 0 or higher than XBREAK */
  1373. ,  if (new_x < 0 || new_x >= XBREAK) {
  1374. ,    if (new_x > XBREAK || (new_x == XBREAK && * new_address != '\n'))
  1375. ,        shift = (new_x - XBREAK) / SHIFT_SIZE + 1;
  1376. ,    else {
  1377. ,        shift = new_x / SHIFT_SIZE;
  1378. ,        if (new_x % SHIFT_SIZE)
  1379. ,            shift --;
  1380. ,    }
  1381. ,
  1382. ,    if (shift != 0) {
  1383. ,        line->shift_count += shift;
  1384. ,        new_x = find_x (line, new_address);
  1385. ,        set_cursor (0, y);
  1386. ,        line_print (line);
  1387. ,        /* rel_x = new_x; */
  1388. ,    }
  1389. ,  }
  1390. ,
  1391. ,/* Assign and position cursor */
  1392. ,  x = new_x;
  1393. ,  cur_text = new_address;
  1394. ,  cur_line = line;
  1395. ,  set_cursor (x, y);
  1396. ,}
  1397. ,
  1398. ,/*
  1399. , * Find_x () returns the x coordinate belonging to address.
  1400. , * (Tabs are expanded).
  1401. , */
  1402. ,find_x (line, address)
  1403. ,  LINE * line;
  1404. ,  char * address;
  1405. ,{
  1406. ,  register char * textp = line->text;
  1407. ,  register int nx = get_shift (line->shift_count) * - SHIFT_SIZE;
  1408. ,
  1409. ,  while (textp != address && * textp != '\0') {
  1410. ,    if (is_tab (* textp ++))    /* Expand tabs */
  1411. ,        nx = tab (nx);
  1412. ,    else
  1413. ,        nx ++;
  1414. ,  }
  1415. ,  return nx;
  1416. ,}
  1417. ,
  1418. ,/*
  1419. , * Find_address () returns the pointer in the line with offset x_coord.
  1420. , * (Tabs are expanded).
  1421. , * find_address is only called by move_it ()
  1422. ,get_shift (cnt)        is    ((cnt) & DUMMY_MASK) ; DUMMY_MASK is 0x7F
  1423. ,tab (cnt)        is    (((cnt) + 8) & ~07)
  1424. ,is_tab (c)        is    ((c) == '\t')
  1425. , */
  1426. ,char *
  1427. ,find_address (line, new_x, cur_x)
  1428. ,  LINE * line;
  1429. ,  int new_x;
  1430. ,  int * cur_x;
  1431. ,{
  1432. ,  register char * textp = line->text;
  1433. ,  register int tx = get_shift (line->shift_count) * - SHIFT_SIZE;
  1434. ,
  1435. ,  while (tx < new_x && * textp != '\n') {
  1436. ,    if (is_tab (* textp)) {
  1437. ,        if (new_x == old_x /* (* cur_x) */ - 1 && tab (tx) > new_x)
  1438. ,            break;    /* Moving left over tab */
  1439. ,        else
  1440. ,            tx = tab (tx);
  1441. ,    }
  1442. ,    else    tx ++;
  1443. ,    textp ++;
  1444. ,  }
  1445. ,  * cur_x = tx;
  1446. ,  return textp;
  1447. ,}
  1448. ,
  1449. ,/*-------------------------------------------------------------------------*/
  1450. ,
  1451. ,/*
  1452. , * Initialize is called when a another file is edited. It free's the allocated 
  1453. , * space and sets modified back to FALSE and fixes the header/tail pointer.
  1454. , */
  1455. ,initialize ()
  1456. ,{
  1457. ,  register LINE * line, * next_line;
  1458. ,
  1459. ,/* Delete the whole list */
  1460. ,  for (line = header->next; line != tail; line = next_line) {
  1461. ,    next_line = line->next;
  1462. ,    free_space (line->text);
  1463. ,    free_space (line);
  1464. ,  }
  1465. ,
  1466. ,/* header and tail should point to itself */
  1467. ,  line->next = line->prev = line;
  1468. ,  x = y = 0;
  1469. ,  rpipe = modified = FALSE;
  1470. ,}
  1471. ,
  1472. ,/*
  1473. , * Load_file loads the file with given name or the input pipe into memory.
  1474. , * If the file couldn't be opened, just an empty line is installed.
  1475. , * Buffer pointers are initialized.
  1476. , */
  1477. ,load_file (file)
  1478. ,  char * file;
  1479. ,{
  1480. ,  load_file_w_o_display (file);
  1481. ,/* Print screen */
  1482. ,  display (0, 0, header->next, last_y);
  1483. ,  move_to (0, 0);
  1484. ,/* fstatus ("Read", -1L); */
  1485. ,}
  1486. ,
  1487. ,load_file_w_o_display (file)
  1488. ,  char * file;
  1489. ,{
  1490. ,  register LINE * line = header;
  1491. ,  register int len;
  1492. ,  long nr_of_chars = 0L;
  1493. ,  int fd = -1;            /* Filedescriptor for file */
  1494. ,
  1495. ,  nlines = 0;            /* Zero lines to start with */
  1496. ,
  1497. ,  overwriteOK = FALSE;
  1498. ,/* Open file */
  1499. ,  writable = TRUE;        /* Benefit of the doubt */
  1500. ,  if (file == NIL_PTR) {
  1501. ,    if (rpipe == FALSE)
  1502. ,        status_msg ("No file");
  1503. ,    else {
  1504. ,        fd = 0;
  1505. ,        file = "standard input";
  1506. ,    }
  1507. ,    file_name [0] = '\0';
  1508. ,  }
  1509. ,  else {
  1510. ,    copy_string (file_name, file);    /* Save file name */
  1511. ,    if (access (file, 0 /* F_OK */) < 0) {    /* Cannot access file */
  1512. ,        status_line ("New file ", file);
  1513. ,        overwriteOK = TRUE;
  1514. ,    }
  1515. ,    else if ((fd = open (file, O_RDWR, 0)) >= 0) {
  1516. ,        overwriteOK = TRUE;
  1517. ,        writable = TRUE;
  1518. ,    }
  1519. ,    else if ((fd = open (file, O_RDONLY, 0)) < 0)
  1520. ,        error ("Cannot open: " /*, file */, serror ());
  1521. ,    else {    overwriteOK = TRUE;
  1522. ,        writable = FALSE;
  1523. ,    }
  1524. ,  }
  1525. ,
  1526. ,/* Read file */
  1527. ,  loading = TRUE;        /* Loading file, so set flag */
  1528. ,  get_line_err1 = NIL_PTR;
  1529. ,  get_line_err2 = NIL_PTR;
  1530. ,
  1531. ,  if (fd >= 0) {
  1532. ,    status_line ("Reading ", file);
  1533. ,    while ((len = get_line (fd, text_buffer)) != ERRORS) {
  1534. ,        line = line_insert (line, text_buffer, len);
  1535. ,        nr_of_chars += (long) len;
  1536. ,    }
  1537. ,    if (nlines == 0)        /* The file was empty! */
  1538. ,        line = line_insert (line, "\n", 1);
  1539. ,    clear_buffer (); /* Clear output buffer: out_count = 0; */
  1540. ,    cur_line = header->next;
  1541. ,    (void) close (fd);        /* Close file */
  1542. ,    if ((get_line_err1 != NIL_PTR) || (get_line_err2 != NIL_PTR)) {
  1543. ,        ring_bell ();
  1544. ,        error (get_line_err1, get_line_err2);
  1545. ,        sleep (1);
  1546. ,    }
  1547. ,    fstatus ("Read", nr_of_chars);
  1548. ,  }
  1549. ,  else                /* Just install a "\n" */
  1550. ,    (void) line_insert (line, "\n", 1);
  1551. ,
  1552. ,  reset (header->next, 0);    /* Initialize pointers */
  1553. ,  move_to (0, 0);
  1554. ,  loading = FALSE;        /* Stop loading, reset flag */
  1555. ,}
  1556. ,
  1557. ,/*
  1558. , * Get_line reads one line from filedescriptor fd. If EOF is reached on fd,
  1559. , * get_line () returns ERRORS, else it returns the length of the string.
  1560. , */
  1561. ,char * get_line_err1;
  1562. ,char * get_line_err2;
  1563. ,
  1564. ,get_line (fd, buffer)
  1565. ,  int fd;
  1566. ,  register char buffer [MAX_CHARS];
  1567. ,{
  1568. ,  static char * last = NIL_PTR;
  1569. ,  static char * current = NIL_PTR;
  1570. ,  static int read_chars;
  1571. ,  register char * cur_pos = current;
  1572. ,  char * begin = buffer;
  1573. ,  char * fini = buffer + MAX_CHARS - 2 /* leave space for '\n\0' */;
  1574. ,
  1575. ,  do {
  1576. ,    if (cur_pos == last) {
  1577. ,        if ((read_chars = read (fd, screen, screen_BUFL)) <= 0)
  1578. ,            break;
  1579. ,        last = & screen [read_chars];
  1580. ,        cur_pos = screen;
  1581. ,    }
  1582. ,    if (* cur_pos == '\0' ) {
  1583. ,        get_line_err1 = "File contains NULL char's - changed to DEL's -   ";
  1584. ,        * cur_pos = '\177';
  1585. ,    }
  1586. ,#ifdef DEBUG
  1587. ,    if (* cur_pos == '\r' ) {
  1588. ,        get_line_err1 = "File contains RET char's - changed to DEL's -   ";
  1589. ,        * cur_pos = '\177';
  1590. ,    }
  1591. ,#endif
  1592. ,    if (buffer == fini) {
  1593. ,        get_line_err2 = "Line too long - split";
  1594. ,        * buffer ++ = '\n';
  1595. ,        break;
  1596. ,    }
  1597. ,  } while ((* buffer ++ = * cur_pos ++) != '\n');
  1598. ,
  1599. ,  current = cur_pos;
  1600. ,  if (read_chars <= 0) {
  1601. ,    if (buffer == begin)
  1602. ,        return ERRORS;
  1603. ,    if (* (buffer - 1) != '\n')
  1604. ,        if (loading == TRUE) /* Add '\n' to last line of file */
  1605. ,            * buffer ++ = '\n';
  1606. ,        else {
  1607. ,            * buffer = '\0';
  1608. ,            return NO_LINE;
  1609. ,        }
  1610. ,  }
  1611. ,
  1612. ,  * buffer = '\0';
  1613. ,  return buffer - begin;
  1614. ,}
  1615. ,
  1616. ,/*  ==================================================================    *
  1617. , *            Auxiliary routines                *
  1618. , *  ==================================================================    */
  1619. ,
  1620. ,/*
  1621. , * Unnull () changes a NULL string pointer into an empty string pointer 
  1622. , * to allow easy feading of string results into build_string / sprintf
  1623. , */
  1624. ,char *
  1625. ,unnull (s)
  1626. ,  char * s;
  1627. ,{
  1628. ,  if (s == NIL_PTR) return "";
  1629. ,  else return s;
  1630. ,}
  1631. ,
  1632. ,/*
  1633. , * Build_string () prints the arguments as described in fmt, into the buffer.
  1634. , * %s indicates a string argument, %d indicates an integer argument.
  1635. , */
  1636. ,#ifndef build_string /* otherwise build_string is sprintf */
  1637. ,/* VARARGS */
  1638. ,build_string (buf, fmt, args)
  1639. ,  register char * buf, * fmt;
  1640. ,  int args;
  1641. ,{
  1642. ,  int * argptr = & args;
  1643. ,  char * scanp;
  1644. ,  FLAG islong;
  1645. ,
  1646. ,  while (* fmt) {
  1647. ,     if (* fmt == '%') {
  1648. ,    fmt ++;
  1649. ,    if (* fmt == 'l') {islong = TRUE; fmt ++;}
  1650. ,             else islong = FALSE;
  1651. ,    switch (* fmt ++) {
  1652. ,    case 's' :
  1653. ,        scanp = (char *) * argptr;
  1654. ,        break;
  1655. ,    case 'd' :
  1656. ,        if (islong == TRUE) {
  1657. ,            scanp = num_out ((long) * ((long *) argptr));
  1658. ,            if (sizeof (long) > sizeof (int)) argptr ++;
  1659. ,        break;
  1660. ,        }
  1661. ,        else {
  1662. ,            scanp = num_out ((long) * argptr);
  1663. ,            break;
  1664. ,        }
  1665. ,    case 'D' :
  1666. ,        scanp = num_out ((long) * ((long *) argptr));
  1667. ,        if (sizeof (long) > sizeof (int)) argptr ++;
  1668. ,        break;
  1669. ,    default :
  1670. ,        scanp = "";
  1671. ,    }
  1672. ,    while (* buf ++ = * scanp ++)
  1673. ,        ;
  1674. ,    buf --;
  1675. ,    argptr ++;
  1676. ,     }
  1677. ,     else
  1678. ,    * buf ++ = * fmt ++;
  1679. ,  }
  1680. ,  * buf = '\0';
  1681. ,}
  1682. ,#endif not build_string
  1683. ,
  1684. ,/*
  1685. , * Output an (unsigned) long in a 10 digit field without leading zeros.
  1686. , * It returns a pointer to the first digit in the buffer.
  1687. , */
  1688. ,char *
  1689. ,num_out (number)
  1690. ,  long number;
  1691. ,{
  1692. ,  static char num_buf [11];        /* Buffer to build number */
  1693. ,  register long digit;            /* Next digit of number */
  1694. ,  register long pow = 1000000000L;    /* Highest ten power of long */
  1695. ,  FLAG digit_seen = FALSE;
  1696. ,  int i;
  1697. ,
  1698. ,  for (i = 0; i < 10; i ++) {
  1699. ,    digit = number / pow;        /* Get next digit */
  1700. ,    if (digit == 0L && digit_seen == FALSE && i != 9)
  1701. ,        num_buf [i] = ' ';
  1702. ,    else {
  1703. ,        num_buf [i] = '0' + (char) digit;
  1704. ,        number -= digit * pow;    /* Erase digit */
  1705. ,        digit_seen = TRUE;
  1706. ,    }
  1707. ,    pow /= 10L;            /* Get next digit */
  1708. ,  }
  1709. ,  num_buf [11] = '\0';
  1710. ,  for (i = 0; num_buf [i] == ' '; i ++)    /* Skip leading spaces */
  1711. ,    ;
  1712. ,  return (& num_buf [i]);
  1713. ,}
  1714. ,
  1715. ,/*
  1716. , * make_number () converts a string into a natural number
  1717. , * returns the character after the last digit
  1718. , */
  1719. ,make_number (num, str)
  1720. ,  int * num;
  1721. ,  char * str;
  1722. ,{
  1723. ,  register char * chpoi = str;
  1724. ,
  1725. ,  * num = 0;
  1726. ,  while (* chpoi >= '0' && * chpoi <= '9' && quit == FALSE) {
  1727. ,    * num *= 10;
  1728. ,    * num += * chpoi - '0';
  1729. ,    chpoi ++;
  1730. ,  }
  1731. ,  return * chpoi;
  1732. ,}
  1733. ,
  1734. ,/*
  1735. , * Length_of () returns the number of characters in the string `string'
  1736. , * excluding the '\0'.
  1737. , */
  1738. ,int
  1739. ,length_of (string)
  1740. ,  register char * string;
  1741. ,{
  1742. ,  register int count = 0;
  1743. ,
  1744. ,  if (string != NIL_PTR) {
  1745. ,    while (* string ++ != '\0')
  1746. ,        count ++;
  1747. ,  }
  1748. ,  return count;
  1749. ,}
  1750. ,
  1751. ,/*
  1752. , * Copy_string () copies the string `from' into the string `to'. `To' must be
  1753. , * long enough to hold `from'.
  1754. , */
  1755. ,copy_string (to, from)
  1756. ,  register char * to;
  1757. ,  register char * from;
  1758. ,{
  1759. ,  while ((* to ++ = * from ++))
  1760. ,    ;
  1761. ,}
  1762. ,
  1763. ,/*-------------------------------------------------------------------------*/
  1764. ,
  1765. ,/*
  1766. , * serrorof delivers the error message of the given errno value.
  1767. , * serror delivers the error message of the current errno value.
  1768. , * geterrno just returns the current errno value.
  1769. , */
  1770. ,#ifdef vms
  1771. ,/* #define includeerrno */
  1772. ,#  ifdef includeerrno
  1773. ,#  include <errno.h>
  1774. ,#  else
  1775. ,    extern volatile int noshare errno;
  1776. ,    extern volatile int noshare vaxc$errno; /* VMS error code when errno = EVMSERR */
  1777. ,#  define EVMSERR 65535
  1778. ,    extern volatile int noshare sys_nerr;
  1779. ,    extern volatile char noshare * sys_errlist [];
  1780. ,#  endif
  1781. ,#else
  1782. ,  extern int errno;
  1783. ,  extern int sys_nerr;
  1784. ,  extern char * sys_errlist [];
  1785. ,#endif
  1786. ,
  1787. ,char *
  1788. ,serrorof (errno)
  1789. ,  int errno;
  1790. ,{
  1791. ,  if ((errno < 0) || (errno >= sys_nerr))
  1792. ,    { static char s [20];
  1793. ,#ifdef vms
  1794. ,      if (errno == EVMSERR)
  1795. ,         build_string (s, "VMS error %d", vaxc$errno);
  1796. ,      else
  1797. ,#endif
  1798. ,         build_string (s, "Unknown error %d", errno);
  1799. ,      return s;
  1800. ,    }
  1801. ,  else    return sys_errlist [errno];
  1802. ,}
  1803. ,char *
  1804. ,serror ()
  1805. ,{ return serrorof (errno); }
  1806. ,int
  1807. ,geterrno ()
  1808. ,{ return errno; }
  1809. ,
  1810. ,/*
  1811. , * Panic () is called with a mined error msg and an optional system error msg.
  1812. , * It is called when something unrecoverable has happened.
  1813. , * It writes the message to the terminal, resets the tty and exits.
  1814. , * Ask the user if he wants to save his file.
  1815. , */
  1816. ,#define panic_msg(msg)    if (isscreenmode == TRUE) {status_msg (msg); sleep (2);} else printf ("%s\n", msg);
  1817. ,panic (message, err)
  1818. ,  register char * message;
  1819. ,  register char * err;
  1820. ,{
  1821. ,  int panic_written;
  1822. ,
  1823. ,  panic_level ++;
  1824. ,
  1825. ,  if (panic_level < 2) {
  1826. ,    if (loading == FALSE && modified == TRUE) {
  1827. ,        if ((panic_written = panic_write ()) == ERRORS) {
  1828. ,            build_string (text_buffer, "Error writing panic file %s", panic_file);
  1829. ,            sleep (2);
  1830. ,        }
  1831. ,        else
  1832. ,            build_string (text_buffer, "Panic file %s written", panic_file);
  1833. ,        ring_bell ();
  1834. ,        panic_msg (text_buffer);
  1835. ,    }
  1836. ,    if (err == NIL_PTR)
  1837. ,        build_string (text_buffer, "%s", message);
  1838. ,    else
  1839. ,        build_string (text_buffer, "%s (Error: %s)", message, err);
  1840. ,    panic_msg (text_buffer);
  1841. ,
  1842. ,    /* "normal" panic handling: */
  1843. ,    if (loading == FALSE) {
  1844. ,        if (QUED () == ERRORS)    /* Try to save the file */ {
  1845. ,            sleep (2);
  1846. ,            panic_msg ("Error writing file in panic mode - trying to continue");
  1847. ,            panic_level --;
  1848. ,            return;
  1849. ,        }
  1850. ,    }
  1851. ,  }
  1852. ,
  1853. ,  if (panic_level < 3) {
  1854. ,    if (isscreenmode == TRUE) {
  1855. ,        set_cursor (0, YMAX);
  1856. ,        putchar ('\n');
  1857. ,        raw_mode (OFF);
  1858. ,    }
  1859. ,    delete_yank_file ();
  1860. ,  }
  1861. ,  exit (1) /* abort () sends IOT which would again be caught */;
  1862. ,}
  1863. ,panicio (message, err)
  1864. ,  register char * message;
  1865. ,  register char * err;
  1866. ,{
  1867. ,/* Should panic_level already be increased here ? */
  1868. ,  panic (message, err);
  1869. ,}
  1870. ,
  1871. ,catch_interrupt ()
  1872. ,{
  1873. ,  panic ("External signal caught - terminating", NIL_PTR);
  1874. ,}
  1875. ,
  1876. ,/*
  1877. , * Memory allocation
  1878. , */
  1879. ,#ifdef msdos
  1880. ,#include <alloc.h>
  1881. ,#define allocate farmalloc
  1882. ,#define freemem farfree
  1883. ,#else
  1884. ,extern char * malloc ();
  1885. ,#define allocate malloc
  1886. ,#define freemem free
  1887. ,#endif
  1888. ,char *
  1889. ,alloc (bytes)
  1890. ,  int bytes;
  1891. ,{
  1892. ,  char * p;
  1893. ,
  1894. ,  if ((p = allocate ((unsigned) bytes)) == NIL_PTR)
  1895. ,    panic ("Out of memory", NIL_PTR);
  1896. ,  return p;
  1897. ,}
  1898. ,
  1899. ,free_space (p)
  1900. ,  char * p;
  1901. ,{
  1902. ,  freemem (p);
  1903. ,}
  1904. ,
  1905. ,/*
  1906. , * Basename () finds the absolute name of the file out of a given path_name.
  1907. , */
  1908. ,#ifdef UNUSED
  1909. ,char *
  1910. ,basename (path)
  1911. ,  char * path;
  1912. ,{
  1913. ,  register char * ptr = path;
  1914. ,  register char * last = NIL_PTR;
  1915. ,
  1916. ,  while (* ptr != '\0') {
  1917. ,    if (* ptr == '/')
  1918. ,        last = ptr;
  1919. ,    ptr ++;
  1920. ,  }
  1921. ,  if (last == NIL_PTR)
  1922. ,    return path;
  1923. ,  if (* (last + 1) == '\0') {    /* E.g. /usr/tmp/pipo/ */
  1924. ,    * last = '\0';
  1925. ,    return basename (path);    /* Try again */
  1926. ,  }
  1927. ,  return last + 1;
  1928. ,}
  1929. ,#endif
  1930. ,
  1931. ,/*
  1932. , * Delete file.
  1933. , */
  1934. ,delete_file (file)
  1935. ,  char * file;
  1936. ,{
  1937. ,#ifdef unix
  1938. ,  unlink (file);
  1939. ,#endif
  1940. ,#ifdef msdos
  1941. ,  unlink (file);
  1942. ,#endif
  1943. ,#ifdef vms
  1944. ,  delete (file);
  1945. ,#endif
  1946. ,}
  1947. ,
  1948. ,/*
  1949. , * Delete yank file if there is one.
  1950. , */
  1951. ,delete_yank_file ()
  1952. ,{
  1953. ,  if (yank_status == VALID) delete_file (yank_file);
  1954. ,}
  1955. ,
  1956. ,/*  ==================================================================    *
  1957. , *                Miscellaneous                *
  1958. , *  ==================================================================    */
  1959. ,
  1960. ,/*
  1961. , * Ignore this keystroke.
  1962. , */
  1963. ,I ()
  1964. ,{
  1965. ,}
  1966. ,
  1967. ,/*
  1968. , * Fortifying 'HOP' key.
  1969. , */
  1970. ,HOP ()
  1971. ,{
  1972. ,  hop_flag = 2;
  1973. ,  if (! char_ready_within (500))
  1974. ,    status_msg ("Continue HOP command (next command fortified) ...");
  1975. ,}
  1976. ,
  1977. ,/*
  1978. , * Cancel prefix function.
  1979. , */
  1980. ,CANCEL ()
  1981. ,{
  1982. ,  hop_flag = 0;
  1983. ,  clear_status ();
  1984. ,}
  1985. ,
  1986. ,/*
  1987. , * Call proc associated with function key.
  1988. , */
  1989. ,FUNKEY ()
  1990. ,{
  1991. ,  (* keyproc) ('\0');
  1992. ,  keyproc = I;
  1993. ,}
  1994. ,
  1995. ,/*
  1996. , * Combined command.
  1997. , */
  1998. ,extern MRT(), MLF();
  1999. ,
  2000. ,ESCAPE ()
  2001. ,{
  2002. ,  u_char c;
  2003. ,  int (* func) ();
  2004. ,
  2005. ,  if (! char_ready_within (500))
  2006. ,/*    status_msg ("Continue ESCape command (for help use h) ..."); */
  2007. ,    status_msg ("ESC(exit) q(uit w(rite e(dit /\\(search) r(eplace d(irectory h(elp ...");
  2008. ,  if (quit == TRUE) return I ();
  2009. ,  c = readchar ();
  2010. ,  if (quit == TRUE) return I ();
  2011. ,  clear_status ();
  2012. ,  if ('0' <= c && c <= '9') return REPT (c);
  2013. ,  switch (c) {
  2014. ,    case '\033' : return EXED ();    /* alternatively EXFILE () ? */
  2015. ,    case 'q' : return QUED ();
  2016. ,    case '/' : return SFW ();
  2017. ,    case '\\' : return SRV ();
  2018. ,    case 's' : return GR ();
  2019. ,    case 'l' : return LR ();
  2020. ,    case 'r' : return REPL ();
  2021. ,    case 'w' : return WT ();
  2022. ,    case 'e' : return EDIT ();
  2023. ,    case 'v' : return VIEW ();
  2024. ,    case 'h' : return HELP ();
  2025. ,    case '?' : return FS ();
  2026. ,    case '.' : return RD ();
  2027. ,    case 'i' : return INF ();
  2028. ,    case 'b' : return WB ();
  2029. ,    case '=' : return REPT (' ');
  2030. ,    case 'z' : return SUSP ();
  2031. ,    case 'd' : return CHDI ();
  2032. ,    case '!' : return SH ();
  2033. ,    case ']' : return GOMA ();
  2034. ,    case 'n' : return NN ();
  2035. ,    case 'p' : return PBUF ();
  2036. ,    case 'c' : return CMD ();
  2037. ,    case ' ' : return I ();
  2038. ,    case '+' : return NXTFILE ();
  2039. ,    case '-' : return PRVFILE ();
  2040. ,    case '#' : return NTHFILE ();
  2041. ,    case QUITCHAR : return CANCEL ();
  2042. ,    default : {
  2043. ,        /* func = key_map [c];
  2044. ,           if ((c < ' ') || (func == FUNKEY)) {
  2045. ,            hop_flag = 1;
  2046. ,            return (* func) (c);
  2047. ,           }
  2048. ,           else
  2049. ,        */
  2050. ,            return BAD (c);
  2051. ,          }
  2052. ,  }
  2053. ,}
  2054. ,
  2055. ,/*
  2056. , * DIRECT () reads in a direct cursor movement input sequence and moves.
  2057. , */
  2058. ,DIRECT ()
  2059. ,{
  2060. ,  u_char c;
  2061. ,  int xpos, ypos;
  2062. ,
  2063. ,  c = get_digits (& ypos); /* c should be ';' */
  2064. ,  c = get_digits (& xpos);
  2065. ,  ypos = ypos - 1;
  2066. ,  xpos = xpos - 1;
  2067. ,  if (ypos > last_y) ypos = last_y;
  2068. ,  move_to (xpos, ypos);
  2069. ,  if (c == 'm') MARK (); /* middle mouse button */
  2070. ,  if (c == 'r') YA (); /* right mouse button */
  2071. ,}
  2072. ,
  2073. ,/*
  2074. , * REPT () prompts for a count and wants a command after that. It repeats the
  2075. , * command count times. If a ^\ is given during repeating, stop looping and
  2076. , * return to main loop.
  2077. , */
  2078. ,REPT (firstdigit)
  2079. ,  char firstdigit;
  2080. ,{
  2081. ,  register int count;
  2082. ,  register int (* func) ();
  2083. ,  int index, number;
  2084. ,
  2085. ,  hop_flag = 0;
  2086. ,  if (firstdigit >= '0' && firstdigit <= '9')
  2087. ,     index = get_number ("Please continue repeat count...", firstdigit, & number);
  2088. ,  else
  2089. ,     index = get_number ("Please enter repeat count...", '\0', & number);
  2090. ,  if (index == ERRORS) return;
  2091. ,
  2092. ,  func = key_map [index];
  2093. ,  if (func == I) {    /* Function assigned? */
  2094. ,    clear_status ();
  2095. ,    return;
  2096. ,  }
  2097. ,  if (func == FUNKEY) {
  2098. ,    func = * keyproc;
  2099. ,    keyproc = I;
  2100. ,    index = '\0';
  2101. ,  }
  2102. ,
  2103. ,  count = number;
  2104. ,  while (count -- > 0 && quit == FALSE) {
  2105. ,    if (stat_visible == TRUE)
  2106. ,        clear_status ();
  2107. ,    (* func) (index);
  2108. ,    flush ();
  2109. ,  }
  2110. ,
  2111. ,  if (quit == TRUE)        /* Abort has been given */
  2112. ,    error ("Repeat aborted", NIL_PTR);
  2113. ,  else
  2114. ,    clear_status ();
  2115. ,}
  2116. ,
  2117. ,/*
  2118. , * Complains to illegal commands and eats up illegal escape sequences.
  2119. , */
  2120. ,BAD (c)
  2121. ,  u_char c;
  2122. ,{
  2123. ,  static char message2 [] = "'**' - type a blank";
  2124. ,
  2125. ,  if (c < ' ')    { message2 [1] = '^'; message2 [2] = c + '@'; }
  2126. ,  else        { message2 [1] = ' '; message2 [2] = c; }
  2127. ,  error ("Unknown command ", message2);
  2128. ,  while (readchar () != ' ' && quit == FALSE) {
  2129. ,    ring_bell ();
  2130. ,    flush ();
  2131. ,  }
  2132. ,  clear_status ();
  2133. ,}
  2134. ,
  2135. ,/*
  2136. , * Change working directory.
  2137. , */
  2138. ,CHDI ()
  2139. ,{
  2140. ,  char new_dir [maxLINE_LEN];    /* Buffer to hold new dir. name */
  2141. ,
  2142. ,#ifdef vms
  2143. ,#  define _getcwd_
  2144. ,#endif
  2145. ,#ifdef msdos
  2146. ,#  define _getcwd_
  2147. ,#endif
  2148. ,#ifdef _getcwd_
  2149. ,  build_string (text_buffer, "Directory: %s, change to:", unnull (getcwd (new_dir, maxLINE_LEN)));
  2150. ,#else
  2151. ,  build_string (text_buffer, "Directory: %s, change to:", unnull (getwd (new_dir)));
  2152. ,#endif
  2153. ,  if (get_file (text_buffer, new_dir) != FINE)
  2154. ,    return;
  2155. ,  if (chdir (new_dir) == 0) {
  2156. ,/*    set_cursor (x, y);    /* Set cursor back to old position */
  2157. ,    clear_status ();
  2158. ,    overwriteOK = FALSE;    /* Same file base name ... */
  2159. ,    writable = TRUE;
  2160. ,/*    if (viewmode == FALSE)    */
  2161. ,        modified = TRUE;    /* would mean different file now */
  2162. ,  }
  2163. ,  else    error ("Could not change work dir: ", serror ());
  2164. ,}
  2165. ,
  2166. ,/*
  2167. , * Print file status.
  2168. , */
  2169. ,FS ()
  2170. ,{
  2171. ,  fstatus (file_name [0] ? "" : "[buffer]", -1L);
  2172. ,}
  2173. ,
  2174. ,/*
  2175. , * Line_number () finds the line number we're on.
  2176. , */
  2177. ,line_number ()
  2178. ,{
  2179. ,  register LINE * line = header->next;
  2180. ,  register int count = 1;
  2181. ,
  2182. ,  while (line != cur_line) {
  2183. ,    count ++;
  2184. ,    line = line->next;
  2185. ,  }
  2186. ,
  2187. ,  return count;
  2188. ,}
  2189. ,
  2190. ,/*
  2191. , * Display a line telling how many chars and lines the file contains. Also tell
  2192. , * whether the file is readonly and/or modified.
  2193. ,fstatus (mess, cnt) is    file_status ((mess), (cnt), file_name, \
  2194. ,                     nlines, writable, modified, viewonly)
  2195. , */
  2196. ,file_status (message, count, file, lines, writefl, changed, viewing)
  2197. ,  char * message;
  2198. ,  register long count;        /* Contains number of characters in file */
  2199. ,  char * file;
  2200. ,  int lines;
  2201. ,  FLAG writefl, changed, viewing;
  2202. ,{
  2203. ,  register LINE * line;
  2204. ,  static char msg [maxLINE_LEN + 40];    /* Buffer to hold line */
  2205. ,  char yank_msg [maxLINE_LEN];    /* Buffer for msg of yank_file */
  2206. ,
  2207. ,  if (count < 0)        /* Not valid. Count chars in file */
  2208. ,    for (line = header->next; line != tail; line = line->next)
  2209. ,        count += length_of (line->text);
  2210. ,
  2211. ,  if (yank_status == VALID)    /* Append buffer info */
  2212. ,    build_string (yank_msg, " Buffer: %ld char%s.", chars_saved,
  2213. ,                    (chars_saved == 1L) ? "" : "s");
  2214. ,  else
  2215. ,    yank_msg [0] = '\0';
  2216. ,
  2217. ,  build_string (msg,
  2218. ,        "%s %s%s%s%s, %d line%s, %ld char%s. Line %d.%s",
  2219. ,        message,
  2220. ,        (rpipe == TRUE && * message != '[') ?
  2221. ,            "standard input" : file,
  2222. ,            /* previously only basename (file) was printed */
  2223. ,        (viewing == TRUE) ? " (View only)" : "",
  2224. ,        (changed == TRUE) ? " (modified)" : "",
  2225. ,        (writefl == FALSE) ? " (Readonly)" : "",
  2226. ,        lines, (lines == 1) ? "" : "s",
  2227. ,        count, (count == 1L) ? "" : "s",
  2228. ,        line_number (),
  2229. ,        yank_msg);
  2230. ,
  2231. ,  status_msg (msg);        /* Print the information */
  2232. ,}
  2233. ,
  2234. ,/*
  2235. , * Show Help information on screen
  2236. , */
  2237. ,HELP ()
  2238. ,{
  2239. ,  clear_screen ();
  2240. ,  status_msg ("Wait for help...");
  2241. ,  flush ();
  2242. ,  raw_mode (OFF);
  2243. ,  if (getenv ("MINEDHELP"))
  2244. ,    system ((char *) getenv ("MINEDHELP"));
  2245. ,  else    system (helpcommand);
  2246. ,  sleep (1);
  2247. ,  raw_mode (ON);
  2248. ,  clear_status ();
  2249. ,  RDwin ();
  2250. ,}
  2251. ,
  2252. ,/*
  2253. , * Print buffer
  2254. , */
  2255. ,PBUF ()
  2256. ,{
  2257. ,  int fd;
  2258. ,  char cmd [maxLINE_LEN];    /* Buffer for print command */
  2259. ,
  2260. ,  if ((fd = scratch_file (READ, FALSE)) == ERRORS) {
  2261. ,    error ("Buffer is empty.", NIL_PTR);
  2262. ,    return;
  2263. ,  }
  2264. ,  close (fd);
  2265. ,  build_string (cmd, getenv ("MINEDPRINT") ?
  2266. ,        (char *) getenv ("MINEDPRINT") : printcommand, yank_file);
  2267. ,  clear_status ();
  2268. ,  set_cursor (0, YMAX);
  2269. ,  flush ();
  2270. ,  system (cmd);
  2271. ,  sleep (1);
  2272. ,  RDwin ();
  2273. ,}
  2274. ,
  2275. ,/*
  2276. , * Pipe buffer
  2277. , */
  2278. ,CMD ()
  2279. ,{
  2280. ,  int fd;
  2281. ,  char cmd [maxLINE_LEN];    /* Buffer for command */
  2282. ,  char command [maxLINE_LEN];    /* Buffer for full command */
  2283. ,
  2284. ,  if ((fd = scratch_file (READ, FALSE)) == ERRORS) {
  2285. ,    error ("Buffer is empty.", NIL_PTR);
  2286. ,    return;
  2287. ,  }
  2288. ,  close (fd);
  2289. ,  if (get_string ("Command with buffer as input:", cmd, TRUE) != FINE)
  2290. ,    return;
  2291. ,  build_string (command, "%s < %s", cmd, yank_file);
  2292. ,  clear_status ();
  2293. ,  set_cursor (0, YMAX);
  2294. ,  flush ();
  2295. ,  raw_mode (OFF);
  2296. ,  system (command);
  2297. ,  sleep (1);
  2298. ,  raw_mode (ON);
  2299. ,  RDwin ();
  2300. ,}
  2301. ,
  2302. ,/*
  2303. , * Called if an operation is not implemented
  2304. , */
  2305. ,notimpl ()
  2306. ,{
  2307. ,  error ("Command not implemented", NIL_PTR);
  2308. ,}
  2309. ,
  2310. ,/*
  2311. , * Suspend editor after writing back the file.
  2312. , */
  2313. ,SUSP ()
  2314. ,{
  2315. ,  if (cansuspendmyself == TRUE) {
  2316. ,    if (hop_flag == 0 && modified == TRUE)
  2317. ,        if (WT () == ERRORS) return ERRORS;
  2318. ,    set_cursor (0, YMAX);
  2319. ,    raw_mode (OFF);
  2320. ,    suspendmyself ();
  2321. ,    raw_mode (ON);
  2322. ,    clear_status ();
  2323. ,    RDwin ();
  2324. ,  }
  2325. ,  else notimpl ();
  2326. ,}
  2327. ,
  2328. ,/*
  2329. , * Call an interactive shell.
  2330. , */
  2331. ,SH ()
  2332. ,{
  2333. ,#ifdef unix
  2334. ,  register int w;
  2335. ,  int pid, status, waiterr;
  2336. ,
  2337. ,  switch (pid = vfork ()) {
  2338. ,    case -1:            /* Error */
  2339. ,        error ("Cannot fork: ", serror ());
  2340. ,        return;
  2341. ,    case 0:                /* This is the child */
  2342. ,        set_cursor (0, YMAX);
  2343. ,        putchar ('\n');
  2344. ,        raw_mode (OFF);
  2345. ,        if (rpipe) {            /* Fix stdin */
  2346. ,            close (STD_IN);
  2347. ,            if (open ("/dev/tty", O_RDONLY, 0) < 0)
  2348. ,                  exit (126);
  2349. ,        }
  2350. ,        execl (getenv ("SHELL"), getenv ("SHELL"), 0);
  2351. ,        _exit (127);    /* Exit with 127 */
  2352. ,    default:            /* This is the parent */
  2353. ,        do {
  2354. ,            w = wait (& status);
  2355. ,        } while (w != -1 && w != pid);
  2356. ,        waiterr = geterrno ();
  2357. ,  }
  2358. ,
  2359. ,  raw_mode (ON);
  2360. ,  RDwin ();
  2361. ,
  2362. ,  if (w == -1) {
  2363. ,    error ("Wait error: ", serrorof (waiterr));
  2364. ,    if (((status >> 8) == 127) || ((status >> 8) == 126)) sleep (2);
  2365. ,  }
  2366. ,  if ((status >> 8) == 127)        /* Child died with 127 */
  2367. ,    error (getenv ("SHELL"), ": cannot exec this ${SHELL} (not found / not enough memory ?)");
  2368. ,  else if ((status >> 8) == 126)
  2369. ,    error ("Cannot open /dev/tty as fd #0", NIL_PTR);
  2370. ,#else
  2371. ,  notimpl ();
  2372. ,#endif
  2373. ,}
  2374. ,
  2375. ,/*  ==================================================================    *
  2376. , *                Main                    *
  2377. , *  ==================================================================    */
  2378. ,
  2379. ,main (argc, argv)
  2380. ,  int argc;
  2381. ,  char * argv [];
  2382. ,{
  2383. ,  register int index;    /* index in key table */
  2384. ,  int initlinenum;
  2385. ,  int initlinenumi = 0;
  2386. ,  LINE * initlinenumline;
  2387. ,  char * Mark;
  2388. ,  FLAG goon;
  2389. ,
  2390. ,/* fprot = umask (0); */
  2391. ,
  2392. ,  if (getenv ("NoCtrlSQ") || getenv ("NoControlSQ")) {
  2393. ,    /* ^S and ^Q may come arbitrarily from terminal, so don't use them */
  2394. ,    key_map ['\021'] = I;
  2395. ,    key_map ['\023'] = I;
  2396. ,  }
  2397. ,  if (getenv ("MINEDMULT")) multiexit = TRUE;
  2398. ,  Mark = (char *) getenv ("MINEDSHIFT");
  2399. ,  if (Mark != NIL_PTR) {
  2400. ,    SHIFT_MARK = Mark [0];
  2401. ,    if (Mark [0] != '\0') SHIFT_BEG = Mark [1];
  2402. ,  }
  2403. ,  Mark = (char *) getenv ("MINEDTAB");
  2404. ,  if (Mark != NIL_PTR) TABchar = (Mark [0] == '\0' ? '╖' : Mark [0]);
  2405. ,  Mark = (char *) getenv ("MINEDRET");
  2406. ,  if (Mark != NIL_PTR) {
  2407. ,    RET_MARK = Mark [0];
  2408. ,    if (RET_MARK) RET_BLANK = Mark [1];
  2409. ,    if (RET_BLANK) RET_BLANK2 = Mark [2];
  2410. ,  }
  2411. ,
  2412. ,  get_term ();
  2413. ,
  2414. ,  if (! can_clear_eol) {
  2415. ,    for (index = 0; index < XMAX; index ++) /* Fill blank_line with spaces*/
  2416. ,        blank_line [index] = ' ';
  2417. ,    blank_line [XMAX] = '\0';
  2418. ,  }
  2419. ,
  2420. ,  fnami = 1;
  2421. ,  goon = TRUE;
  2422. ,  do {
  2423. ,    if (fnami < argc) {
  2424. ,    if (* argv [fnami] == '+') {
  2425. ,       initlinenumi = fnami;
  2426. ,       fnami += 1;
  2427. ,    }
  2428. ,    else if (streq (argv [fnami], "-v")) {
  2429. ,       viewonly = TRUE;
  2430. ,       fnami += 1;
  2431. ,    }
  2432. ,    else goon = FALSE;
  2433. ,    } else goon = FALSE;
  2434. ,  } while (goon == TRUE);
  2435. ,
  2436. ,  fnami_min = fnami;
  2437. ,  fnami_max = argc - 1;
  2438. ,  fnami_cnt = argc - fnami_min;
  2439. ,  fnamv = argv;    /* Why does this produce a warning? C is such a stupid language! */
  2440. ,  if (! (fnami < argc))
  2441. ,     fnami = 0;
  2442. ,
  2443. ,  if (! isatty (STD_IN)) {    /* Reading from pipe */
  2444. ,    if (fnami != 0) {
  2445. ,        panic ("Cannot read both pipe and file", NIL_PTR);
  2446. ,    }
  2447. ,    rpipe = TRUE;
  2448. ,    modified = TRUE;    /* Set modified flag not to loose buffer */
  2449. ,    if ((input_fd = open ("/dev/tty", O_RDONLY, 0)) < 0)
  2450. ,       panic ("Cannot open /dev/tty for read", serror ());
  2451. ,  }
  2452. ,  if (! isatty (STD_OUT)) {
  2453. ,    wpipe = TRUE;
  2454. ,    modified = TRUE; /* Set modified flag not to ignore buffer on exit */
  2455. ,    /*    if ((output_fd = open ("/dev/tty", O_WRONLY, 0)) < 0)
  2456. ,       panic ("Cannot open /dev/tty for write", serror ()); */
  2457. ,  }
  2458. ,
  2459. ,  raw_mode (ON);    /* Set tty to appropriate mode */
  2460. ,  clear_screen ();
  2461. ,
  2462. ,/*
  2463. , * Generate names of paste files and of panic-file
  2464. , */
  2465. ,#ifdef unix
  2466. ,  temp_dir = (char *) getenv ("TMPDIR");
  2467. ,  if (temp_dir == NIL_PTR || temp_dir [0] == '\0') temp_dir = "/tmp";
  2468. ,  if (getenv ("USER")) {
  2469. ,    build_string (yankie_file, "%s/minedbuf.%s", temp_dir, getenv ("USER"));
  2470. ,    build_string (panic_file, "%s/minedpanic.%s.%d", temp_dir, getenv ("USER"), getpid ());
  2471. ,  }
  2472. ,  else {
  2473. ,    build_string (yankie_file, "%s/minedbuf.%d", temp_dir, geteuid ());
  2474. ,    build_string (panic_file, "%s/minedpanic.%d.%d", temp_dir, geteuid (), getpid ());
  2475. ,  }
  2476. ,#endif
  2477. ,#ifdef vms
  2478. ,  if (getenv ("SYS$SCRATCH"))
  2479. ,    temp_dir = "SYS$SCRATCH";
  2480. ,  else    temp_dir = "SYS$LOGIN";
  2481. ,  if (getenv ("USER")) {
  2482. ,    build_string (yankie_file, "%s:$MINEDBUF.%s", temp_dir, getenv ("USER"));
  2483. ,    build_string (panic_file, "%s:$MINEDPANIC.%s.%d", temp_dir, getenv ("USER"), getpid ());
  2484. ,  }
  2485. ,  else {
  2486. ,    build_string (yankie_file, "%s:$MINEDBUF.%d", temp_dir, geteuid ());
  2487. ,    build_string (panic_file, "%s:$MINEDPANIC.%d.%d", temp_dir, geteuid (), getpid ());
  2488. ,  }
  2489. ,#endif
  2490. ,#ifdef msdos
  2491. ,  temp_dir = (char *) getenv ("TEMP");
  2492. ,  if (temp_dir == NIL_PTR || temp_dir [0] == '\0') temp_dir = (char *) getenv ("TMP");
  2493. ,  if (temp_dir == NIL_PTR || temp_dir [0] == '\0') temp_dir = "\\";
  2494. ,  build_string (yankie_file, "%s\\minedbuf", temp_dir);
  2495. ,  build_string (panic_file, "%s\\mined-pa.nic", temp_dir);
  2496. ,#endif
  2497. ,
  2498. ,  header = tail = (LINE *) alloc (sizeof (LINE)); /* Make header of list*/
  2499. ,  header->text = NIL_PTR;
  2500. ,  header->next = tail->prev = header;
  2501. ,
  2502. ,/* Load the file (if any) */
  2503. ,  if (fnami == 0)
  2504. ,    load_file_w_o_display (NIL_PTR);
  2505. ,  else {
  2506. ,    /* This should be applied to all file names, or better, not at all:
  2507. ,    if (length_of (argv [fnami]) > maxLINE_LEN) {
  2508. ,        argv [fnami] [maxLINE_LEN] = '\0';
  2509. ,    }
  2510. ,    */
  2511. ,    load_file_w_o_display (argv [fnami]);
  2512. ,  }
  2513. ,  loading = TRUE;    /* keep loading flag TRUE until entering main loop */
  2514. ,
  2515. ,  if (initlinenumi != 0) {
  2516. ,     make_number (& initlinenum, argv [initlinenumi] + 1);
  2517. ,     if (initlinenum > 0) {
  2518. ,    if (initlinenum <= 0 || (initlinenumline = proceed (header->next, initlinenum - 1)) == tail)
  2519. ,       error ("Illegal line number: ", num_out ((long) initlinenum));
  2520. ,    else {
  2521. ,       move_to (x, find_y_w_o_RD (initlinenumline));
  2522. ,       fstatus ("Read", -1L);
  2523. ,    }
  2524. ,     }
  2525. ,  }
  2526. ,  if (wpipe) {
  2527. ,    file_name [0] = '\0'; /* don't let user believe he's editing a file */
  2528. ,    fstatus ("Editing for standard output", -1L);
  2529. ,  }
  2530. ,  RD ();
  2531. ,  flush ();
  2532. ,  catch_signals (catch_interrupt);
  2533. ,  loading = FALSE;
  2534. ,
  2535. ,/* Main loop of the editor */
  2536. ,  for (;;) {
  2537. ,    index = readchar ();
  2538. ,    if (stat_visible == TRUE)
  2539. ,        clear_status ();
  2540. ,    if (quit == FALSE) {    /* Call the function for the typed key */
  2541. ,        (* key_map [index]) (index);
  2542. ,        if (hop_flag > 0) hop_flag --;
  2543. ,        flush ();    /* Flush output (if any) */
  2544. ,    }
  2545. ,    if (quit == TRUE) {
  2546. ,        CANCEL ();
  2547. ,        quit = FALSE;
  2548. ,    }
  2549. ,  }
  2550. ,  /* NOTREACHED */
  2551. ,}
  2552. ,
  2553. ,/*  ==================================================================    *
  2554. , *                End                    *
  2555. , *  ==================================================================    */
  2556. EOSED
  2557.  
  2558. exit 0
  2559.  
  2560.