annotate pager.c @ 18:1e39a251cbe9

Use libtecla for interactive input
author Guido Berhoerster <guido+pwm@berhoerster.name>
date Thu, 24 Aug 2017 13:10:56 +0200
parents a08ef0674d8e
children 5c6155c8e9b6
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
17
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
1 /*
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
2 * Copyright (C) 2017 Guido Berhoerster <guido+pwm@berhoerster.name>
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
3 *
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
4 * Permission is hereby granted, free of charge, to any person obtaining
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
5 * a copy of this software and associated documentation files (the
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
6 * "Software"), to deal in the Software without restriction, including
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
7 * without limitation the rights to use, copy, modify, merge, publish,
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
8 * distribute, sublicense, and/or sell copies of the Software, and to
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
9 * permit persons to whom the Software is furnished to do so, subject to
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
10 * the following conditions:
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
11 *
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
12 * The above copyright notice and this permission notice shall be included
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
13 * in all copies or substantial portions of the Software.
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
14 *
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
19 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
20 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
21 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
22 */
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
23
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
24 #include "compat.h"
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
25
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
26 #ifdef HAVE_ERR_H
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
27 #include <err.h>
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
28 #endif /* HAVE_ERR_H */
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
29 #include <errno.h>
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
30 #include <fcntl.h>
18
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 17
diff changeset
31 #include <libtecla.h>
17
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
32 #include <limits.h>
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
33 #include <signal.h>
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
34 #include <stdio.h>
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
35 #include <string.h>
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
36 #include <sys/ioctl.h>
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
37 #ifdef HAVE_SYS_QUEUE_H
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
38 #include <sys/queue.h>
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
39 #endif /* HAVE_SYS_QUEUE_H */
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
40 #include <sys/stat.h>
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
41 #include <sys/types.h>
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
42 #include <termios.h>
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
43 #include <unistd.h>
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
44 #include <wchar.h>
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
45
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
46 #include "pwm.h"
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
47 #include "pager.h"
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
48 #include "util.h"
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
49
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
50 struct pager {
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
51 TAILQ_HEAD(lines_head, lines_entry) lines_head;
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
52 FILE *fp;
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
53 size_t buf_size;
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
54 char *buf;
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
55 };
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
56
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
57 struct lines_entry {
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
58 TAILQ_ENTRY(lines_entry) entry;
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
59 char *line;
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
60 };
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
61
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
62 static int
18
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 17
diff changeset
63 getch_prompt(GetLine *gl, const char *prompt)
17
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
64 {
18
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 17
diff changeset
65 int c;
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 17
diff changeset
66 int saved_echo_mode;
17
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
67
18
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 17
diff changeset
68 /* prompt with echo off */
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 17
diff changeset
69 saved_echo_mode = gl_echo_mode(gl, -1);
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 17
diff changeset
70 gl_echo_mode(gl, 0);
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 17
diff changeset
71 c = gl_query_char(gl, prompt, '\0');
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 17
diff changeset
72 gl_echo_mode(gl, saved_echo_mode);
17
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
73
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
74 /* erase prompt */
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
75 printf("\r%*s\r", (int)strlen(prompt), "");
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
76
18
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 17
diff changeset
77 return (c);
17
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
78 }
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
79
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
80 struct pager *
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
81 pager_create(FILE *fp)
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
82 {
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
83 struct pager *pager;
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
84
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
85 pager = xmalloc(sizeof (struct pager));
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
86 TAILQ_INIT(&pager->lines_head);
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
87 pager->fp = fp;
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
88 pager->buf_size = BUFSIZ;
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
89 pager->buf = xmalloc(BUFSIZ);
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
90
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
91 return (pager);
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
92 }
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
93
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
94 void
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
95 pager_destroy(struct pager *pager)
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
96 {
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
97 struct lines_entry *entry;
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
98 struct lines_entry *entry_tmp;
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
99
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
100 if (pager == NULL) {
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
101 return;
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
102 }
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
103
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
104 TAILQ_FOREACH_SAFE(entry, &pager->lines_head, entry, entry_tmp) {
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
105 TAILQ_REMOVE(&pager->lines_head, entry, entry);
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
106 free(entry->line);
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
107 free(entry);
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
108 }
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
109 free(pager->buf);
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
110 free(pager);
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
111 }
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
112
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
113 int
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
114 pager_vprintf(struct pager *pager, const char *fmt, va_list args)
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
115 {
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
116 int len;
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
117 va_list args_new;
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
118 char *p;
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
119 size_t line_len;
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
120 struct lines_entry *entry;
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
121 size_t line_offset;
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
122
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
123 va_copy(args_new, args);
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
124
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
125 /* format multibyte string in buffer */
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
126 len = vsnprintf(NULL, 0, fmt, args);
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
127 if (len < 0) {
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
128 err(1, "vsnprintf");
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
129 }
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
130
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
131 if (pager->buf_size < (size_t)len + 1) {
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
132 pager->buf_size = len + 1;
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
133 pager->buf = xrealloc(pager->buf, pager->buf_size);
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
134 }
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
135
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
136 len = vsnprintf(pager->buf, pager->buf_size, fmt, args_new);
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
137 if (len < 0) {
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
138 err(1, "vsnprintf");
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
139 }
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
140
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
141 /* split buffer into lines */
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
142 for (p = pager->buf; *p != '\0'; p += line_len) {
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
143 line_len = strcspn(p, "\n");
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
144 if (p[line_len] == '\n') {
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
145 line_len++;
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
146 }
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
147
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
148 entry = TAILQ_LAST(&pager->lines_head, lines_head);
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
149 line_offset = (entry != NULL) ? strlen(entry->line) : 0;
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
150 if ((entry != NULL) && (entry->line[line_offset - 1] != '\n')) {
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
151 /*
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
152 * append to the last line if it doesn't end with a
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
153 * newline
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
154 */
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
155 entry->line = xrealloc(entry->line, line_offset +
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
156 line_len + 1);
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
157 memcpy(entry->line + line_offset, p, line_len);
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
158 entry->line[line_offset + line_len] = '\0';
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
159 } else {
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
160 entry = xmalloc(sizeof (struct lines_entry));
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
161 entry->line = xmalloc(line_len + 1);
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
162 memcpy(entry->line, p, line_len);
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
163 entry->line[line_len] = '\0';
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
164 TAILQ_INSERT_TAIL(&pager->lines_head, entry, entry);
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
165 }
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
166 }
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
167
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
168 va_end(args_new);
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
169
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
170 return (len);
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
171 }
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
172
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
173 int
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
174 pager_printf(struct pager *pager, const char *fmt, ...)
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
175 {
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
176 int len;
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
177 va_list args;
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
178
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
179 va_start(args, fmt);
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
180 len = pager_vprintf(pager, fmt, args);
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
181 va_end(args);
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
182
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
183 return (len);
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
184 }
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
185
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
186 static unsigned int
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
187 mbsnprint(unsigned int cols, const char *s, FILE *fp)
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
188 {
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
189 const char *p = s;
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
190 unsigned int col = 0;
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
191 int mb_len;
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
192 wchar_t wc;
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
193 int width;
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
194 char mb_buf[MB_LEN_MAX];
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
195
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
196 while ((*p != '\n') && (*p != '\0') && (col < cols)) {
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
197 mb_len = mbtowc(&wc, p, MB_CUR_MAX);
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
198 if (mb_len != -1) {
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
199 width = wcwidth(wc);
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
200 if (width != -1) {
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
201 if (snprintf(mb_buf, sizeof (mb_buf), "%.*s",
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
202 mb_len, p) != mb_len) {
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
203 err(1, "snprintf");
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
204 }
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
205 } else {
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
206 /*
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
207 * non-printable character, print
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
208 * replacement character
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
209 */
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
210 width = 1;
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
211 if (snprintf(mb_buf, sizeof (mb_buf),
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
212 "\357\277\275") != 3) {
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
213 err(1, "snprintf");
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
214 }
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
215 }
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
216 } else {
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
217 /*
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
218 * decoding failed, reset state and skip one
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
219 * byte
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
220 */
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
221 mbtowc(NULL, NULL, MB_CUR_MAX);
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
222 mb_len = 1;
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
223
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
224 /* print replacement character */
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
225 width = 1;
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
226 if (snprintf(mb_buf, sizeof (mb_buf),
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
227 "\357\277\275") != 3) {
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
228 err(1, "snprintf");
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
229 }
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
230 }
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
231
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
232 p += mb_len;
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
233 col += width;
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
234 if (col <= cols) {
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
235 if (fputs(mb_buf, fp) == EOF) {
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
236 err(1, "fputs");
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
237 }
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
238 }
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
239 }
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
240
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
241 fputc('\n', fp);
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
242 fflush(fp);
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
243
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
244 return (col);
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
245 }
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
246
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
247 void
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
248 pager_show(struct pager *pager)
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
249 {
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
250 int is_interactive;
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
251 unsigned int rows = 24;
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
252 unsigned int cols = 80;
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
253 #ifdef TIOCGWINSZ
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
254 struct winsize ws;
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
255 #endif /* TIOCGWINSZ */
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
256 unsigned int row = 0;
18
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 17
diff changeset
257 GetLine *gl;
17
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
258 struct lines_entry *entry;
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
259
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
260 is_interactive = (isatty(STDIN_FILENO) && (pager->fp == stdout));
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
261
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
262 #ifdef TIOCGWINSZ
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
263 if (is_interactive) {
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
264 /* determine terminal size */
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
265 if (ioctl(fileno(pager->fp), TIOCGWINSZ, &ws) == 0) {
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
266 rows = (ws.ws_row > 0) ? ws.ws_row : rows;
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
267 cols = (ws.ws_col > 0) ? ws.ws_col : cols;
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
268 }
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
269 }
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
270 #endif /* TIOCGWINSZ */
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
271
18
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 17
diff changeset
272 gl = new_GetLine(10, 0);
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 17
diff changeset
273 if (gl == NULL) {
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 17
diff changeset
274 err(1, "new_GetLine");
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 17
diff changeset
275 }
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 17
diff changeset
276
17
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
277 TAILQ_FOREACH(entry, &pager->lines_head, entry) {
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
278 if (is_interactive) {
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
279 mbsnprint(cols, entry->line, pager->fp);
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
280 row++;
18
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 17
diff changeset
281 if ((TAILQ_NEXT(entry, entry) != NULL) &&
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 17
diff changeset
282 (row == rows - 1)) {
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 17
diff changeset
283 getch_prompt(gl, "--More--");
17
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
284 row = 0;
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
285 }
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
286 } else {
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
287 fprintf(pager->fp, "%s", entry->line);
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
288 fflush(pager->fp);
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
289 }
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
290 }
18
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 17
diff changeset
291
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 17
diff changeset
292 del_GetLine(gl);
17
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
293 }