2 ** prompter.c -- simple prompting editor front-end
4 ** This code is Copyright (c) 2002, by the authors of nmh. See the
5 ** COPYRIGHT file in the root directory of the nmh distribution for
6 ** complete copyright information.
11 #include <h/signals.h>
36 static struct swit switches[] = {
66 static struct termios tio;
67 # define ERASE tio.c_cc[VERASE]
68 # define KILL tio.c_cc[VKILL]
69 # define INTR tio.c_cc[VINTR]
72 static struct termio tio;
73 # define ERASE tio.c_cc[VERASE]
74 # define KILL tio.c_cc[VKILL]
75 # define INTR tio.c_cc[VINTR]
77 static struct sgttyb tio;
78 static struct tchars tc;
79 # define ERASE tio.sg_erase
80 # define KILL tio.sg_kill
81 # define INTR tc.t_intrc
85 static int wtuser = 0;
86 static int sigint = 0;
87 static jmp_buf sigenv;
92 int getln(char *, int);
93 static int chrcnv(char *);
94 static void chrdsp(char *, char);
95 static RETSIGTYPE intrser(int);
99 main(int argc, char **argv)
101 int body = 1, prepend = 1, rapid = 0;
102 int doteof = 0, fdi, fdo, i, state;
103 char *cp, *drft = NULL, *erasep = NULL;
104 char *killp = NULL, name[NAMESZ], field[BUFSIZ];
105 char buffer[BUFSIZ], tmpfil[BUFSIZ];
106 char **arguments, **argp;
111 setlocale(LC_ALL, "");
113 invo_name = mhbasename(argv[0]);
115 /* read user profile/context */
118 arguments = getarguments(invo_name, argc, argv, 1);
121 while ((cp = *argp++))
123 switch (smatch(++cp, switches)) {
125 ambigsw(cp, switches);
128 adios(NULL, "-%s unknown", cp);
131 snprintf(buffer, sizeof(buffer),
132 "%s [switches] file",
134 print_help(buffer, switches, 1);
137 print_version(invo_name);
141 if (!(erasep = *argp++) || *erasep == '-')
142 adios(NULL, "missing argument to %s",
146 if (!(killp = *argp++) || *killp == '-')
147 adios(NULL, "missing argument to %s",
184 adios(NULL, "usage: %s [switches] file", invo_name);
185 if ((in = fopen(drft, "r")) == NULL)
186 adios(drft, "unable to open");
188 tfile = m_mktemp2(NULL, invo_name, NULL, &out);
190 adios("prompter", "unable to create temporary file");
192 strncpy(tmpfil, tfile, sizeof(tmpfil));
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),
264 ** Check if the value of field contains
265 ** anything other than space or tab.
267 for (cp = field; *cp; cp++)
268 if (*cp != ' ' && *cp != '\t')
271 /* If so, just add header line to draft */
272 if (*cp++ != '\n' || *cp != 0) {
273 printf("%s:%s", name, field);
274 fprintf(out, "%s:%s", name, field);
275 while (state == FLDPLUS) {
276 state = m_getfld(state, name, field,
279 fprintf(out, "%s", field);
282 /* Else, get value of header field */
283 printf("%s: ", name);
285 i = getln(field, sizeof(field));
288 if (killp || erasep) {
289 #ifdef HAVE_TERMIOS_H
290 tcsetattr(0, TCSADRAIN, &tio);
293 ioctl(0, TCSETA, &tio);
295 ioctl(0, TIOCSETN, (char *) &tio);
302 if (i != 0 || (field[0] != '\n' && field[0] != 0)) {
303 fprintf(out, "%s:", name);
305 if (field[0] != ' ' && field[0] != '\t')
307 fprintf(out, "%s", field);
308 } while (i == 1 && (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)
349 } while (state == BODY && (state = m_getfld(state, name, field, sizeof(field), in)));
350 if (prepend || !body)
353 printf ("\n--------Enter additional text\n\n");
358 getln(field, sizeof(field));
359 if (doteof && field[0] == '.' && field[1] == '\n')
363 fprintf(out, "%s", field);
368 adios(NULL, "skeleton is poorly formatted");
374 printf("--------\n");
379 SIGNAL(SIGINT, SIG_IGN);
381 if (killp || erasep) {
382 #ifdef HAVE_TERMIOS_H
383 tcsetattr(0, TCSADRAIN, &tio);
385 # ifdef HAVE_TERMIO_H
386 ioctl(0, TCSETAW, &tio);
388 ioctl(0, TIOCSETN, (char *) &tio);
393 if ((fdi = open(tmpfil, O_RDONLY)) == NOTOK)
394 adios(tmpfil, "unable to re-open");
395 if ((fdo = creat(drft, m_gmprot())) == NOTOK)
396 adios(drft, "unable to write");
397 cpydata(fdi, fdo, tmpfil, drft);
402 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);