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>
28 static struct swit switches[] = {
57 static struct termios tio;
58 #define ERASE tio.c_cc[VERASE]
59 #define KILL tio.c_cc[VKILL]
60 #define INTR tio.c_cc[VINTR]
62 static int wtuser = 0;
63 static int sigint = 0;
64 static jmp_buf sigenv;
69 int getln(char *, int);
70 static int chrcnv(char *);
71 static void chrdsp(char *, char);
72 static RETSIGTYPE intrser(int);
76 main(int argc, char **argv)
78 int body = 1, prepend = 1, rapid = 0;
79 int doteof = 0, fdi, fdo, i, state;
80 char *cp, *drft = NULL, *erasep = NULL;
81 char *killp = NULL, name[NAMESZ], field[BUFSIZ];
82 char buffer[BUFSIZ], tmpfil[BUFSIZ];
83 char **arguments, **argp;
88 setlocale(LC_ALL, "");
90 invo_name = mhbasename(argv[0]);
92 /* read user profile/context */
95 arguments = getarguments(invo_name, argc, argv, 1);
98 while ((cp = *argp++))
100 switch (smatch(++cp, switches)) {
102 ambigsw(cp, switches);
105 adios(NULL, "-%s unknown", cp);
108 snprintf(buffer, sizeof(buffer),
109 "%s [switches] file",
111 print_help(buffer, switches, 1);
114 print_version(invo_name);
118 if (!(erasep = *argp++) || *erasep == '-')
119 adios(NULL, "missing argument to %s",
123 if (!(killp = *argp++) || *killp == '-')
124 adios(NULL, "missing argument to %s",
161 adios(NULL, "usage: %s [switches] file", invo_name);
162 if ((in = fopen(drft, "r")) == NULL)
163 adios(drft, "unable to open");
165 tfile = m_mktemp2(NULL, invo_name, NULL, &out);
167 adios("prompter", "unable to create temporary file");
169 strncpy(tmpfil, tfile, sizeof(tmpfil));
172 ** Are we changing the kill or erase character?
174 if (killp || erasep) {
175 cc_t save_erase, save_kill;
177 /* get the current terminal attributes */
180 /* save original kill, erase character for later */
184 /* set new kill, erase character in terminal structure */
185 KILL = killp ? chrcnv(killp) : save_kill;
186 ERASE = erasep ? chrcnv(erasep) : save_erase;
188 /* set the new terminal attributes */
189 tcsetattr(0, TCSADRAIN, &tio);
191 /* print out new kill erase characters */
192 chrdsp("erase", ERASE);
193 chrdsp(", kill", KILL);
194 chrdsp(", intr", INTR);
199 ** We set the kill and erase character back to original
200 ** setup in terminal structure so we can easily
201 ** restore it upon exit.
208 SIGNAL2(SIGINT, intrser);
211 ** Loop through the lines of the draft skeleton.
213 for (state = FLD;;) {
214 switch (state = m_getfld(state, name, field, sizeof(field),
220 ** Check if the value of field contains
221 ** anything other than space or tab.
223 for (cp = field; *cp; cp++)
224 if (*cp != ' ' && *cp != '\t')
227 /* If so, just add header line to draft */
228 if (*cp++ != '\n' || *cp != 0) {
229 printf("%s:%s", name, field);
230 fprintf(out, "%s:%s", name, field);
231 while (state == FLDPLUS) {
232 state = m_getfld(state, name, field,
235 fprintf(out, "%s", field);
238 /* Else, get value of header field */
239 printf("%s: ", name);
241 i = getln(field, sizeof(field));
244 if (killp || erasep) {
245 tcsetattr(0, TCSADRAIN, &tio);
250 if (i != 0 || (field[0] != '\n' && field[0] != 0)) {
251 fprintf(out, "%s:", name);
253 if (field[0] != ' ' && field[0] != '\t')
255 fprintf(out, "%s", field);
256 } while (i == 1 && (i = getln(field, sizeof(field))) >= 0);
262 if (state == FLDEOF) { /* moby hack */
263 fprintf(out, "--------\n");
264 printf("--------\n");
276 fprintf(out, "--------\n");
277 if (field[0] == 0 || !prepend)
278 printf("--------\n");
280 if (prepend && body) {
281 printf("\n--------Enter initial text\n\n");
284 getln(buffer, sizeof(buffer));
285 if (doteof && buffer[0] == '.' && buffer[1] == '\n')
289 fprintf(out, "%s", buffer);
294 fprintf(out, "%s", field);
295 if (!rapid && !sigint)
297 } while (state == BODY && (state = m_getfld(state, name, field, sizeof(field), in)));
298 if (prepend || !body)
301 printf ("\n--------Enter additional text\n\n");
306 getln(field, sizeof(field));
307 if (doteof && field[0] == '.' && field[1] == '\n')
311 fprintf(out, "%s", field);
316 adios(NULL, "skeleton is poorly formatted");
322 printf("--------\n");
327 SIGNAL(SIGINT, SIG_IGN);
329 if (killp || erasep) {
330 tcsetattr(0, TCSADRAIN, &tio);
333 if ((fdi = open(tmpfil, O_RDONLY)) == NOTOK)
334 adios(tmpfil, "unable to re-open");
335 if ((fdo = creat(drft, m_gmprot())) == NOTOK)
336 adios(drft, "unable to write");
337 cpydata(fdi, fdo, tmpfil, drft);
342 context_save(); /* save the context file */
349 getln(char *buffer, int n)
357 switch (setjmp(sigenv)) {
372 switch (c = getchar()) {
375 longjmp(sigenv, DONE);
378 if (cp[-1] == QUOTE) {
400 #ifndef RELIABLE_SIGNALS
401 SIGNAL(SIGINT, intrser);
405 longjmp(sigenv, NOTOK);
413 return (*cp != QUOTE ? *cp : m_atoi(++cp));
418 chrdsp(char *s, char c)
421 if (c < ' ' || c == 0177)
422 printf("^%c", c ^ 0100);