1 /* $Id: man_term.c,v 1.209 2017/07/31 15:19:06 schwarze Exp $ */
2 /*
3 * Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
4 * Copyright (c) 2010-2015, 2017 Ingo Schwarze <schwarze@openbsd.org>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18 #include "config.h"
19
20 #include <sys/types.h>
21
22 #include <assert.h>
23 #include <ctype.h>
24 #include <limits.h>
658 static int
659 pre_SS(DECL_ARGS)
660 {
661 int i;
662
663 switch (n->type) {
664 case ROFFT_BLOCK:
665 mt->fl &= ~MANT_LITERAL;
666 mt->lmargin[mt->lmargincur] = term_len(p, p->defindent);
667 mt->offset = term_len(p, p->defindent);
668
669 /*
670 * No vertical space before the first subsection
671 * and after an empty subsection.
672 */
673
674 do {
675 n = n->prev;
676 } while (n != NULL && n->tok >= MAN_TH &&
677 termacts[n->tok].flags & MAN_NOTEXT);
678 if (n == NULL || (n->tok == MAN_SS && n->body->child == NULL))
679 break;
680
681 for (i = 0; i < mt->pardist; i++)
682 term_vspace(p);
683 break;
684 case ROFFT_HEAD:
685 term_fontrepl(p, TERMFONT_BOLD);
686 p->tcol->offset = term_len(p, 3);
687 p->tcol->rmargin = mt->offset;
688 p->trailspace = mt->offset;
689 p->flags |= TERMP_NOBREAK | TERMP_BRIND;
690 break;
691 case ROFFT_BODY:
692 p->tcol->offset = mt->offset;
693 p->tcol->rmargin = p->maxrmargin;
694 p->trailspace = 0;
695 p->flags &= ~(TERMP_NOBREAK | TERMP_BRIND);
696 break;
697 default:
698 break;
720 static int
721 pre_SH(DECL_ARGS)
722 {
723 int i;
724
725 switch (n->type) {
726 case ROFFT_BLOCK:
727 mt->fl &= ~MANT_LITERAL;
728 mt->lmargin[mt->lmargincur] = term_len(p, p->defindent);
729 mt->offset = term_len(p, p->defindent);
730
731 /*
732 * No vertical space before the first section
733 * and after an empty section.
734 */
735
736 do {
737 n = n->prev;
738 } while (n != NULL && n->tok >= MAN_TH &&
739 termacts[n->tok].flags & MAN_NOTEXT);
740 if (n == NULL || (n->tok == MAN_SH && n->body->child == NULL))
741 break;
742
743 for (i = 0; i < mt->pardist; i++)
744 term_vspace(p);
745 break;
746 case ROFFT_HEAD:
747 term_fontrepl(p, TERMFONT_BOLD);
748 p->tcol->offset = 0;
749 p->tcol->rmargin = mt->offset;
750 p->trailspace = mt->offset;
751 p->flags |= TERMP_NOBREAK | TERMP_BRIND;
752 break;
753 case ROFFT_BODY:
754 p->tcol->offset = mt->offset;
755 p->tcol->rmargin = p->maxrmargin;
756 p->trailspace = 0;
757 p->flags &= ~(TERMP_NOBREAK | TERMP_BRIND);
758 break;
759 default:
760 break;
868
869 switch (n->type) {
870 case ROFFT_TEXT:
871 /*
872 * If we have a blank line, output a vertical space.
873 * If we have a space as the first character, break
874 * before printing the line's data.
875 */
876 if (*n->string == '\0') {
877 if (p->flags & TERMP_NONEWLINE)
878 term_newln(p);
879 else
880 term_vspace(p);
881 return;
882 } else if (*n->string == ' ' && n->flags & NODE_LINE &&
883 (p->flags & TERMP_NONEWLINE) == 0)
884 term_newln(p);
885
886 term_word(p, n->string);
887 goto out;
888
889 case ROFFT_EQN:
890 if ( ! (n->flags & NODE_LINE))
891 p->flags |= TERMP_NOSPACE;
892 term_eqn(p, n->eqn);
893 if (n->next != NULL && ! (n->next->flags & NODE_LINE))
894 p->flags |= TERMP_NOSPACE;
895 return;
896 case ROFFT_TBL:
897 if (p->tbl.cols == NULL)
898 term_vspace(p);
899 term_tbl(p, n->span);
900 return;
901 default:
902 break;
903 }
904
905 if (n->tok < ROFF_MAX) {
906 roff_term_pre(p, n);
907 return;
908 }
1012
1013 p->tcol->offset = p->tcol->rmargin;
1014 titlen = term_strlen(p, title);
1015 p->tcol->rmargin = p->maxrmargin > titlen ?
1016 p->maxrmargin - titlen : 0;
1017 p->flags |= TERMP_NOSPACE;
1018
1019 term_word(p, meta->date);
1020 term_flushln(p);
1021
1022 /* Bottom right corner: manual title and section. */
1023
1024 p->flags &= ~TERMP_NOBREAK;
1025 p->flags |= TERMP_NOSPACE;
1026 p->trailspace = 0;
1027 p->tcol->offset = p->tcol->rmargin;
1028 p->tcol->rmargin = p->maxrmargin;
1029
1030 term_word(p, title);
1031 term_flushln(p);
1032 free(title);
1033 }
1034
1035 static void
1036 print_man_head(struct termp *p, const struct roff_meta *meta)
1037 {
1038 const char *volume;
1039 char *title;
1040 size_t vollen, titlen;
1041
1042 assert(meta->title);
1043 assert(meta->msec);
1044
1045 volume = NULL == meta->vol ? "" : meta->vol;
1046 vollen = term_strlen(p, volume);
1047
1048 /* Top left corner: manual title and section. */
1049
1050 mandoc_asprintf(&title, "%s(%s)", meta->title, meta->msec);
1051 titlen = term_strlen(p, title);
|
1 /* $Id: man_term.c,v 1.211 2018/06/10 15:12:35 schwarze Exp $ */
2 /*
3 * Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
4 * Copyright (c) 2010-2015, 2017, 2018 Ingo Schwarze <schwarze@openbsd.org>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18 #include "config.h"
19
20 #include <sys/types.h>
21
22 #include <assert.h>
23 #include <ctype.h>
24 #include <limits.h>
658 static int
659 pre_SS(DECL_ARGS)
660 {
661 int i;
662
663 switch (n->type) {
664 case ROFFT_BLOCK:
665 mt->fl &= ~MANT_LITERAL;
666 mt->lmargin[mt->lmargincur] = term_len(p, p->defindent);
667 mt->offset = term_len(p, p->defindent);
668
669 /*
670 * No vertical space before the first subsection
671 * and after an empty subsection.
672 */
673
674 do {
675 n = n->prev;
676 } while (n != NULL && n->tok >= MAN_TH &&
677 termacts[n->tok].flags & MAN_NOTEXT);
678 if (n == NULL || n->type == ROFFT_COMMENT ||
679 (n->tok == MAN_SS && n->body->child == NULL))
680 break;
681
682 for (i = 0; i < mt->pardist; i++)
683 term_vspace(p);
684 break;
685 case ROFFT_HEAD:
686 term_fontrepl(p, TERMFONT_BOLD);
687 p->tcol->offset = term_len(p, 3);
688 p->tcol->rmargin = mt->offset;
689 p->trailspace = mt->offset;
690 p->flags |= TERMP_NOBREAK | TERMP_BRIND;
691 break;
692 case ROFFT_BODY:
693 p->tcol->offset = mt->offset;
694 p->tcol->rmargin = p->maxrmargin;
695 p->trailspace = 0;
696 p->flags &= ~(TERMP_NOBREAK | TERMP_BRIND);
697 break;
698 default:
699 break;
721 static int
722 pre_SH(DECL_ARGS)
723 {
724 int i;
725
726 switch (n->type) {
727 case ROFFT_BLOCK:
728 mt->fl &= ~MANT_LITERAL;
729 mt->lmargin[mt->lmargincur] = term_len(p, p->defindent);
730 mt->offset = term_len(p, p->defindent);
731
732 /*
733 * No vertical space before the first section
734 * and after an empty section.
735 */
736
737 do {
738 n = n->prev;
739 } while (n != NULL && n->tok >= MAN_TH &&
740 termacts[n->tok].flags & MAN_NOTEXT);
741 if (n == NULL || n->type == ROFFT_COMMENT ||
742 (n->tok == MAN_SH && n->body->child == NULL))
743 break;
744
745 for (i = 0; i < mt->pardist; i++)
746 term_vspace(p);
747 break;
748 case ROFFT_HEAD:
749 term_fontrepl(p, TERMFONT_BOLD);
750 p->tcol->offset = 0;
751 p->tcol->rmargin = mt->offset;
752 p->trailspace = mt->offset;
753 p->flags |= TERMP_NOBREAK | TERMP_BRIND;
754 break;
755 case ROFFT_BODY:
756 p->tcol->offset = mt->offset;
757 p->tcol->rmargin = p->maxrmargin;
758 p->trailspace = 0;
759 p->flags &= ~(TERMP_NOBREAK | TERMP_BRIND);
760 break;
761 default:
762 break;
870
871 switch (n->type) {
872 case ROFFT_TEXT:
873 /*
874 * If we have a blank line, output a vertical space.
875 * If we have a space as the first character, break
876 * before printing the line's data.
877 */
878 if (*n->string == '\0') {
879 if (p->flags & TERMP_NONEWLINE)
880 term_newln(p);
881 else
882 term_vspace(p);
883 return;
884 } else if (*n->string == ' ' && n->flags & NODE_LINE &&
885 (p->flags & TERMP_NONEWLINE) == 0)
886 term_newln(p);
887
888 term_word(p, n->string);
889 goto out;
890 case ROFFT_COMMENT:
891 return;
892 case ROFFT_EQN:
893 if ( ! (n->flags & NODE_LINE))
894 p->flags |= TERMP_NOSPACE;
895 term_eqn(p, n->eqn);
896 if (n->next != NULL && ! (n->next->flags & NODE_LINE))
897 p->flags |= TERMP_NOSPACE;
898 return;
899 case ROFFT_TBL:
900 if (p->tbl.cols == NULL)
901 term_vspace(p);
902 term_tbl(p, n->span);
903 return;
904 default:
905 break;
906 }
907
908 if (n->tok < ROFF_MAX) {
909 roff_term_pre(p, n);
910 return;
911 }
1015
1016 p->tcol->offset = p->tcol->rmargin;
1017 titlen = term_strlen(p, title);
1018 p->tcol->rmargin = p->maxrmargin > titlen ?
1019 p->maxrmargin - titlen : 0;
1020 p->flags |= TERMP_NOSPACE;
1021
1022 term_word(p, meta->date);
1023 term_flushln(p);
1024
1025 /* Bottom right corner: manual title and section. */
1026
1027 p->flags &= ~TERMP_NOBREAK;
1028 p->flags |= TERMP_NOSPACE;
1029 p->trailspace = 0;
1030 p->tcol->offset = p->tcol->rmargin;
1031 p->tcol->rmargin = p->maxrmargin;
1032
1033 term_word(p, title);
1034 term_flushln(p);
1035
1036 /*
1037 * Reset the terminal state for more output after the footer:
1038 * Some output modes, in particular PostScript and PDF, print
1039 * the header and the footer into a buffer such that it can be
1040 * reused for multiple output pages, then go on to format the
1041 * main text.
1042 */
1043
1044 p->tcol->offset = 0;
1045 p->flags = 0;
1046
1047 free(title);
1048 }
1049
1050 static void
1051 print_man_head(struct termp *p, const struct roff_meta *meta)
1052 {
1053 const char *volume;
1054 char *title;
1055 size_t vollen, titlen;
1056
1057 assert(meta->title);
1058 assert(meta->msec);
1059
1060 volume = NULL == meta->vol ? "" : meta->vol;
1061 vollen = term_strlen(p, volume);
1062
1063 /* Top left corner: manual title and section. */
1064
1065 mandoc_asprintf(&title, "%s(%s)", meta->title, meta->msec);
1066 titlen = term_strlen(p, title);
|