3 * prompter.c -- simple prompting editor front-end
7 * This code is Copyright (c) 2002, by the authors of nmh. See the
8 * COPYRIGHT file in the root directory of the nmh distribution for
9 * complete copyright information.
14 #include <h/signals.h>
39 static struct swit switches[] = {
70 static struct termios tio;
71 # define ERASE tio.c_cc[VERASE]
72 # define KILL tio.c_cc[VKILL]
73 # define INTR tio.c_cc[VINTR]
76 static struct termio tio;
77 # define ERASE tio.c_cc[VERASE]
78 # define KILL tio.c_cc[VKILL]
79 # define INTR tio.c_cc[VINTR]
81 static struct sgttyb tio;
82 static struct tchars tc;
83 # define ERASE tio.sg_erase
84 # define KILL tio.sg_kill
85 # define INTR tc.t_intrc
89 static int wtuser = 0;
90 static int sigint = 0;
91 static jmp_buf sigenv;
96 int getln (char *, int);
97 static int chrcnv (char *);
98 static void chrdsp (char *, char);
99 static RETSIGTYPE intrser (int);
103 main (int argc, char **argv)
105 int body = 1, prepend = 1, rapid = 0;
106 int doteof = 0, fdi, fdo, i, state;
107 char *cp, *drft = NULL, *erasep = NULL;
108 char *killp = NULL, name[NAMESZ], field[BUFSIZ];
109 char buffer[BUFSIZ], tmpfil[BUFSIZ];
110 char **arguments, **argp;
114 setlocale(LC_ALL, "");
116 invo_name = r1bindex (argv[0], '/');
118 /* read user profile/context */
121 arguments = getarguments (invo_name, argc, argv, 1);
124 while ((cp = *argp++))
126 switch (smatch (++cp, switches)) {
128 ambigsw (cp, switches);
131 adios (NULL, "-%s unknown", cp);
134 snprintf (buffer, sizeof(buffer), "%s [switches] file",
136 print_help (buffer, switches, 1);
139 print_version(invo_name);
143 if (!(erasep = *argp++) || *erasep == '-')
144 adios (NULL, "missing argument to %s", argp[-2]);
147 if (!(killp = *argp++) || *killp == '-')
148 adios (NULL, "missing argument to %s", argp[-2]);
185 adios (NULL, "usage: %s [switches] file", invo_name);
186 if ((in = fopen (drft, "r")) == NULL)
187 adios (drft, "unable to open");
189 strncpy (tmpfil, m_tmpfil (invo_name), sizeof(tmpfil));
190 if ((out = fopen (tmpfil, "w")) == NULL)
191 adios (tmpfil, "unable to create");
192 chmod (tmpfil, 0600);
195 * Are we changing the kill or erase character?
197 if (killp || erasep) {
198 #ifdef HAVE_TERMIOS_H
199 cc_t save_erase, save_kill;
201 int save_erase, save_kill;
204 /* get the current terminal attributes */
205 #ifdef HAVE_TERMIOS_H
208 # ifdef HAVE_TERMIO_H
209 ioctl(0, TCGETA, &tio);
211 ioctl (0, TIOCGETP, (char *) &tio);
212 ioctl (0, TIOCGETC, (char *) &tc);
216 /* save original kill, erase character for later */
220 /* set new kill, erase character in terminal structure */
221 KILL = killp ? chrcnv (killp) : save_kill;
222 ERASE = erasep ? chrcnv (erasep) : save_erase;
224 /* set the new terminal attributes */
225 #ifdef HAVE_TERMIOS_H
226 tcsetattr(0, TCSADRAIN, &tio);
228 # ifdef HAVE_TERMIO_H
229 ioctl(0, TCSETAW, &tio);
231 ioctl (0, TIOCSETN, (char *) &tio);
235 /* print out new kill erase characters */
236 chrdsp ("erase", ERASE);
237 chrdsp (", kill", KILL);
238 chrdsp (", intr", INTR);
243 * We set the kill and erase character back to original
244 * setup in terminal structure so we can easily
245 * restore it upon exit.
252 SIGNAL2 (SIGINT, intrser);
255 * Loop through the lines of the draft skeleton.
257 for (state = FLD;;) {
258 switch (state = m_getfld (state, name, field, sizeof(field), in)) {
263 * Check if the value of field contains anything
264 * other than space or tab.
266 for (cp = field; *cp; cp++)
267 if (*cp != ' ' && *cp != '\t')
270 /* If so, just add header line to draft */
271 if (*cp++ != '\n' || *cp != 0) {
272 printf ("%s:%s", name, field);
273 fprintf (out, "%s:%s", name, field);
274 while (state == FLDPLUS) {
276 m_getfld (state, name, field, sizeof(field), in);
277 printf ("%s", field);
278 fprintf (out, "%s", field);
281 /* Else, get value of header field */
282 printf ("%s: ", name);
284 i = getln (field, sizeof(field));
287 if (killp || erasep) {
288 #ifdef HAVE_TERMIOS_H
289 tcsetattr(0, TCSADRAIN, &tio);
292 ioctl (0, TCSETA, &tio);
294 ioctl (0, TIOCSETN, (char *) &tio);
301 if (i != 0 || (field[0] != '\n' && field[0] != 0)) {
302 fprintf (out, "%s:", name);
304 if (field[0] != ' ' && field[0] != '\t')
306 fprintf (out, "%s", field);
308 && (i = getln (field, sizeof(field))) >= 0);
314 if (state == FLDEOF) { /* moby hack */
315 fprintf (out, "--------\n");
316 printf ("--------\n");
328 fprintf (out, "--------\n");
329 if (field[0] == 0 || !prepend)
330 printf ("--------\n");
332 if (prepend && body) {
333 printf ("\n--------Enter initial text\n\n");
336 getln (buffer, sizeof(buffer));
337 if (doteof && buffer[0] == '.' && buffer[1] == '\n')
341 fprintf (out, "%s", buffer);
346 fprintf (out, "%s", field);
347 if (!rapid && !sigint)
348 printf ("%s", field);
349 } while (state == BODY &&
350 (state = m_getfld (state, name, field, sizeof(field), in)));
351 if (prepend || !body)
354 printf ("\n--------Enter additional text\n\n");
359 getln (field, sizeof(field));
360 if (doteof && field[0] == '.' && field[1] == '\n')
364 fprintf (out, "%s", field);
369 adios (NULL, "skeleton is poorly formatted");
375 printf ("--------\n");
380 SIGNAL (SIGINT, SIG_IGN);
382 if (killp || erasep) {
383 #ifdef HAVE_TERMIOS_H
384 tcsetattr(0, TCSADRAIN, &tio);
386 # ifdef HAVE_TERMIO_H
387 ioctl (0, TCSETAW, &tio);
389 ioctl (0, TIOCSETN, (char *) &tio);
394 if ((fdi = open (tmpfil, O_RDONLY)) == NOTOK)
395 adios (tmpfil, "unable to re-open");
396 if ((fdo = creat (drft, m_gmprot ())) == NOTOK)
397 adios (drft, "unable to write");
398 cpydata (fdi, fdo, tmpfil, drft);
403 context_save (); /* save the context file */
409 getln (char *buffer, int n)
417 switch (setjmp (sigenv)) {
432 switch (c = getchar ()) {
435 longjmp (sigenv, DONE);
438 if (cp[-1] == QUOTE) {
460 #ifndef RELIABLE_SIGNALS
461 SIGNAL (SIGINT, intrser);
465 longjmp (sigenv, NOTOK);
473 return (*cp != QUOTE ? *cp : m_atoi (++cp));
478 chrdsp (char *s, char c)
481 if (c < ' ' || c == 0177)
482 printf ("^%c", c ^ 0100);