]>
diplodocus.org Git - nmh/blob - docs/historical/mh-6.8.5/sbr/formatsbr.c
1 /* formatsbr.c - format string interpretation */
3 static char ident
[] = "@(#)$Id: formatsbr.c,v 1.25 1995/12/06 20:59:41 jromine Exp shettich $";
7 #include "../h/addrsbr.h"
8 #include "../h/formatsbr.h"
9 #include "../zotnet/tws.h"
10 #include "../h/fmtcompile.h"
13 #include <sys/types.h>
22 static char *formats
= 0;
23 extern char *formataddr (); /* hook for custom address formatting */
25 struct msgs
*fmt_current_folder
; /* current folder (set by main program) */
29 static int get_x400_comp();
31 extern int fmt_norm
; /* defined in sbr/formatdef.c = AD_NAME */
32 struct mailname fmt_mnull
;
39 /* MAJOR HACK: See MHCHANGES for discussion */
41 char *new_fs (form
, format
, def
)
53 if ((fp
= fopen (libpath (form
), "r")) == NULL
)
54 adios (form
, "unable to open format file");
56 if (fstat (fileno (fp
), &st
) == NOTOK
)
57 adios (form
, "unable to stat format file");
59 if ((formats
= malloc ((unsigned) st
.st_size
+ 1)) == NULLCP
)
60 adios (form
, "unable to allocate space for format");
62 if (read (fileno(fp
), formats
, (int) st
.st_size
) != st
.st_size
)
63 adios (form
, "error reading format file");
65 formats
[st
.st_size
] = '\0';
70 formats
= getcpy (format
? format
: def
);
85 for (dp
= cp
; *cp
; cp
++)
90 #define grot(y,z) case y: *dp++ = z; break;
112 * test if string "sub" appears anywhere in string "str"
113 * (case insensitive).
116 static int match (str
, sub
)
127 c1
= (isalpha(c1
) && isupper(c1
)) ? tolower(c1
) : c1
;
128 while ((c2
= *str
++) && c1
!= ((isalpha(c2
) && isupper(c2
)) ? tolower(c2
) : c2
))
132 s1
= sub
+ 1; s2
= str
;
133 while ((c1
= *s1
++) && ((isalpha(c1
) && isupper(c1
)) ? tolower(c1
) : c1
) == ((isalpha(c2
=*s2
++) && isupper(c2
)) ? tolower(c2
) : c2
))
140 while ((c2
= *str
++) && (c1
| 040) != (c2
| 040))
144 s1
= sub
+ 1; s2
= str
;
145 while ((c1
= *s1
++) && (c1
| 040) == (*s2
++ | 040))
155 /* macros to format data */
157 #define PUTDF(cp, num, wid, fill) if (cp + wid < ep){\
158 if((i = (num))<0) i = -(num);\
159 if((c = (wid))<0) c = -c;\
162 *--sp = (i % 10) + '0';\
164 } while (i > 0 && sp > cp);\
167 else if ((num) < 0 && sp > cp)\
173 #define PUTD(cp, num) if (cp < ep){\
174 if((i = (num))==0) *cp++ = '0';\
177 *cp++ = '-', i = -(num);\
181 while (cp < ep && c > 1) {\
183 *cp++ = (i / c) + '0';\
189 #define PUTSF(cp, str, wid, fill) {\
191 if ((i = (wid)) < 0) {\
201 while( --i >= c && cp < ep)\
206 while ((c = (unsigned char) *sp) && (iscntrl(c) || isspace(c)))\
209 while ((c = (unsigned char) *sp++) && --i >= 0 && cp < ep)\
213 while ((c = (unsigned char) *sp) && (iscntrl(c) || isspace(c)))\
219 while( --i >= 0 && cp < ep)\
222 #define PUTS(cp, str) {\
224 while ((c = (unsigned char) *sp) && (iscntrl(c) || isspace(c)))\
226 while((c = (unsigned char) *sp++) && cp < ep)\
230 while ((c = (unsigned char) *sp) && (iscntrl(c) || isspace(c)))\
237 #define PUTSF(cp, str, wid, fill) {\
239 if ((i = (wid)) < 0) {\
249 while( --i >= c && cp < ep)\
254 while ((c = *sp) && c <= 32)\
257 while ((c = *sp++) && --i >= 0 && cp < ep)\
261 while ((c = *sp) && c <= 32)\
267 while( --i >= 0 && cp < ep)\
270 #define PUTS(cp, str) {\
272 while ((c = *sp) && c <= 32)\
274 while( (c = *sp++) && cp < ep)\
278 while ( (c = *sp) && c <= 32 )\
287 static char *lmonth
[] = { "January", "February","March", "April",
288 "May", "June", "July", "August",
289 "September","October", "November","December" };
291 static char *get_x400_friendly (mbox
, buffer
)
305 if (get_x400_comp (mbox
, "/PN=", buffer
)) {
306 for (mbox
= buffer
; mbox
= index (mbox
, '.'); )
312 if (!get_x400_comp (mbox
, "/S=", surname
))
315 if (get_x400_comp (mbox
, "/G=", given
))
316 (void) sprintf (buffer
, "%s %s", given
, surname
);
318 (void) strcpy (buffer
, surname
);
323 static int get_x400_comp (mbox
, key
, buffer
)
331 if ((idx
= stringdex (key
, mbox
)) < 0
332 || !(cp
= index (mbox
+= idx
+ strlen (key
), '/')))
335 (void) sprintf (buffer
, "%*.*s", cp
- mbox
, cp
- mbox
, mbox
);
340 fmtscan (format
, scanl
, width
, dat
)
341 struct format
*format
;
346 register char *cp
= scanl
;
347 register char *ep
= scanl
+ width
- 1;
348 register struct format
*fmt
= format
;
349 register char *str
= NULLCP
;
350 register int value
= 0;
354 register struct comp
*comp
;
355 register struct tws
*tws
;
356 register struct mailname
*mn
;
363 switch (fmt
->f_type
) {
366 PUTS (cp
, fmt
->f_comp
->c_text
);
369 PUTSF (cp
, fmt
->f_comp
->c_text
, fmt
->f_width
, fmt
->f_fill
);
374 while( (c
= *sp
++) && cp
< ep
)
383 ljust
++; /* XXX should do something with this */
385 while( (c
= *sp
++) && --i
>= 0 && cp
< ep
)
387 while( --i
>= 0 && cp
< ep
)
395 PUTSF (cp
, str
, fmt
->f_width
, fmt
->f_fill
);
398 adios (NULLCP
, "internal error (FT_STRFW)");
404 PUTDF (cp
, value
, fmt
->f_width
, fmt
->f_fill
);
415 if (!(value
= (str
&& *str
))) {
422 if (!(value
= (str
== NULLCP
|| *str
== 0))) {
429 if (value
!= fmt
->f_value
) {
436 if (value
== fmt
->f_value
) {
443 if (value
<= fmt
->f_value
) {
450 if (!(value
= (str
&& match (str
, fmt
->f_text
)))) {
458 value
= match (str
, fmt
->f_text
);
464 if (!(value
= (str
&& uprf (str
, fmt
->f_text
)))) {
471 value
= uprf (str
, fmt
->f_text
);
475 value
= (str
!= NULLCP
&& *str
!= 0);
479 value
= (str
== NULLCP
|| *str
== 0);
483 value
= (fmt
->f_value
== value
);
487 value
= (fmt
->f_value
!= value
);
491 value
= (fmt
->f_value
> value
);
502 str
= fmt
->f_comp
->c_text
;
508 if (!(str
= getenv (fmt
->f_text
)))
512 if (!(str
= m_find (fmt
->f_text
)))
519 (void) strcpy(buffer
, str
);
521 while (isspace(*str
))
524 if ((i
= fmt
->f_width
) < 0) {
529 if (!ljust
&& i
> 0 && strlen(str
) > i
)
532 xp
+= strlen(str
) - 1;
533 while (xp
> str
&& isspace(*xp
))
535 if (ljust
&& i
> 0 && strlen(str
) > i
)
536 str
+= strlen(str
) - i
;
541 value
= fmt
->f_comp
->c_flags
;
544 value
= (comp
= fmt
->f_comp
)->c_text
? atoi(comp
->c_text
) : 0;
547 value
= fmt
->f_value
;
550 value
= dat
[fmt
->f_value
];
555 case FT_LV_CHAR_LEFT
:
556 value
= width
- (cp
- scanl
);
559 value
+= fmt
->f_value
;
562 value
= fmt
->f_value
- value
;
566 value
= value
/ fmt
->f_value
;
572 value
= value
% fmt
->f_value
;
581 value
= fmt
->f_comp
->c_tws
->tw_sec
;
584 value
= fmt
->f_comp
->c_tws
->tw_min
;
587 value
= fmt
->f_comp
->c_tws
->tw_hour
;
590 value
= fmt
->f_comp
->c_tws
->tw_mday
;
593 value
= fmt
->f_comp
->c_tws
->tw_mon
+ 1;
596 str
= tw_moty
[fmt
->f_comp
->c_tws
->tw_mon
];
599 str
= lmonth
[fmt
->f_comp
->c_tws
->tw_mon
];
602 str
= dtwszone (fmt
->f_comp
->c_tws
);
606 value
= fmt
->f_comp
->c_tws
->tw_year
;
608 value
= (fmt
->f_comp
->c_tws
->tw_year
) % 100;
612 if (!(((tws
= fmt
->f_comp
->c_tws
)->tw_flags
) & (TW_SEXP
|TW_SIMP
)))
614 value
= tws
->tw_wday
;
617 if (!(((tws
= fmt
->f_comp
->c_tws
)->tw_flags
) & (TW_SEXP
|TW_SIMP
)))
619 str
= tw_dotw
[tws
->tw_wday
];
622 if (!(((tws
= fmt
->f_comp
->c_tws
)->tw_flags
) & (TW_SEXP
|TW_SIMP
)))
624 str
= tw_ldotw
[tws
->tw_wday
];
627 value
= fmt
->f_comp
->c_tws
->tw_yday
;
630 value
= fmt
->f_comp
->c_tws
->tw_zone
;
633 if ((value
= fmt
->f_comp
->c_tws
->tw_clock
) == 0)
634 value
= twclock(fmt
->f_comp
->c_tws
);
637 if ((value
= fmt
->f_comp
->c_tws
->tw_clock
) == 0)
638 value
= twclock(fmt
->f_comp
->c_tws
);
639 value
= time((time_t *) 0) - value
;
642 if (!(((tws
= fmt
->f_comp
->c_tws
)->tw_flags
) & (TW_SEXP
|TW_SIMP
)))
644 switch (fmt
->f_comp
->c_tws
->tw_flags
& TW_SDAY
) {
653 if ((fmt
->f_comp
->c_tws
->tw_flags
& TW_SZONE
) == TW_SZEXP
)
659 value
= fmt
->f_comp
->c_tws
->tw_flags
& TW_DST
;
662 str
= dasctime ( fmt
->f_comp
->c_tws
, TW_ZONE
);
665 str
= dasctime ( fmt
->f_comp
->c_tws
, TW_NULL
);
669 str
= fmt
->f_comp
->c_mn
->m_pers
;
672 str
= fmt
->f_comp
->c_mn
->m_mbox
;
675 str
= fmt
->f_comp
->c_mn
->m_host
;
678 str
= fmt
->f_comp
->c_mn
->m_path
;
681 str
= fmt
->f_comp
->c_mn
->m_gname
;
684 str
= fmt
->f_comp
->c_mn
->m_note
;
687 str
= adrformat( fmt
->f_comp
->c_mn
);
690 value
= fmt
->f_comp
->c_mn
->m_type
;
693 value
= fmt
->f_comp
->c_mn
->m_ingrp
;
696 value
= fmt
->f_comp
->c_mn
->m_nohost
;
701 str
= fmt
->f_comp
->c_mn
->m_mbox
;
703 if ((mn
= fmt
-> f_comp
-> c_mn
) == &fmt_mnull
) {
704 str
= fmt
-> f_comp
-> c_text
;
707 if (fmt
-> f_type
== FT_LS_ADDR
)
709 if (!(str
= mn
-> m_pers
)
710 && (!(str
= get_x400_friendly (mn
-> m_mbox
, buffer
)))) {
711 if (str
= mn
-> m_note
) {
712 (void) strcpy (buffer
, str
);
716 sp
= str
+ strlen (str
) - 1;
730 switch (mn
-> m_type
) {
735 (void) sprintf (str
= buffer
, "%s!%s",
736 mn
-> m_host
, mn
-> m_mbox
);
740 (void) sprintf (str
= buffer
, "%s@%s", mn
-> m_mbox
,
752 if ((l
= comp
->c_tws
->tw_clock
) == 0)
753 l
= twclock(comp
->c_tws
);
754 tws
= dlocaltime(&l
);
760 if ((l
= comp
->c_tws
->tw_clock
) == 0)
761 l
= twclock(comp
->c_tws
);
768 if ((sp
= comp
->c_text
) && (tws
= dparsetime(sp
))) {
771 } else if (comp
->c_flags
>= 0) {
772 bzero ((char *) comp
-> c_tws
, sizeof *comp
-> c_tws
);
778 /* hook for custom address list formatting (see replsbr.c) */
779 str
= formataddr (savestr
, str
);
783 /* output the str register as an address component,
784 * splitting it into multiple lines if necessary. The
785 * value reg. contains the max line length. The lit.
786 * field may contain a string to prepend to the result
790 register char *lp
= str
;
792 register int wid
= value
;
793 register int len
= strlen (str
);
794 register char *lastb
;
797 indent
= strlen (sp
);
799 while( (c
= *sp
++) && cp
< ep
)
802 /* try to break at a comma; failing that, break at a
803 * space, failing that, just split the line.
805 lastb
= 0; sp
= lp
+ wid
;
806 while (sp
> lp
&& (c
= *--sp
) != ',') {
807 if (! lastb
&& isspace(c
))
814 while (cp
< ep
&& lp
<= sp
)
817 for (i
=indent
; cp
< ep
&& i
> 0; i
--)
828 if (comp
->c_mn
!= &fmt_mnull
)
830 if ((sp
= comp
->c_text
) && (sp
= getname(sp
)) &&
831 (mn
= getm (sp
, NULLCP
, 0, fmt_norm
, NULLCP
))) {
836 while (getname("")) /* XXX */
838 comp
->c_mn
= &fmt_mnull
;
844 * if there's no component, we say true. Otherwise we
845 * say "true" only if we can parse the address and it
846 * matches one of our addresses.
849 if (comp
->c_mn
!= &fmt_mnull
)
851 if ((sp
= comp
->c_text
) && (sp
= getname(sp
)) &&
852 (mn
= getm (sp
, NULLCP
, 0, AD_NAME
, NULLCP
))) {
854 comp
->c_flags
= ismymbox(mn
);
855 while (sp
= getname(sp
))
856 if (comp
->c_flags
== 0 &&
857 (mn
= getm (sp
, NULLCP
, 0, AD_NAME
, NULLCP
)))
858 comp
->c_flags
|= ismymbox(mn
);
860 while (getname("")) /* XXX */
862 comp
->c_flags
= (comp
->c_text
== 0);
863 comp
->c_mn
= &fmt_mnull
;
869 /* If we're working on a folder (as opposed to a file), add the
870 * current msg to sequence given in literal field. Don't
871 * disturb string or value registers.
873 if (fmt_current_folder
)
874 (void)m_seqadd(fmt_current_folder
, fmt
->f_text
, dat
[0], -1);
885 return ((struct format
*)0);
889 while (fmt
->f_type
!= FT_DONE
)
894 return (fmt
-> f_value
? ++fmt
: (struct format
*)0);