1 /* vim:tw=78:ts=8:sw=4:set ft=c: */
3 Copyright (C) 2002-2015 Ben Kibbey <bjk@luxsci.net>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
44 static void wordwrap_lines (wchar_t ***olines
, int *nlines
, int *width
)
47 wchar_t *buf
= NULL
, **lines
= *olines
;
48 int total
= *nlines
, w
= *width
;
50 for (i
= 0; i
< total
; i
++) {
51 size_t len
= wcslen (lines
[i
]);
54 size_t blen
= wcslen (buf
);
56 lines
[i
] = Realloc (lines
[i
], len
+blen
+1*sizeof(wchar_t *));
57 wmemmove (&lines
[i
][blen
], lines
[i
], len
);
58 wmemcpy (lines
[i
], buf
, blen
);
59 lines
[i
][blen
+len
] = 0;
62 len
= wcslen (lines
[i
]);
68 if (len
-- > MSG_WIDTH
) {
71 for (p
= lines
[i
]+len
; *p
&& len
> 0; p
--, len
--) {
72 if (iswspace (*p
) && len
<= MSG_WIDTH
) {
79 /* Its a very long line without any unicode space. Create a
80 * new message line. */
85 p
= lines
[i
]+MSG_WIDTH
;
89 buf
= Malloc (len
*sizeof(wchar_t));
92 wmemcpy (bp
, p
, len
-1);
100 lines
= Realloc (lines
, (total
+2)*sizeof(wchar_t *));
101 lines
[total
++] = buf
;
105 wordwrap_lines (olines
, nlines
, width
);
109 static void build_message_lines(const char *title
, const char *prompt
,
110 int force_trim
, const char *extra
, int *h
,
111 int *w
, wchar_t ***str
, const char *fmt
,
116 wchar_t **lines
= NULL
;
117 int width
= 0, height
= 0, len
;
119 wchar_t *wc
, *wc_tmp
, *wc_line
, wc_delim
[] = { '\n', 0 };
121 #ifdef HAVE_VASPRINTF
122 vasprintf(&line
, fmt
, ap
);
124 line
= Malloc(LINE_MAX
);
125 vsnprintf(line
, LINE_MAX
, fmt
, ap
);
128 wc
= str_to_wchar (line
);
131 for (wc_line
= wcstok (wc
, wc_delim
, &wc_tmp
); wc_line
; wc_line
= wcstok (NULL
, wc_delim
, &wc_tmp
)) {
132 lines
= Realloc (lines
, (total
+2)*sizeof(wchar_t *));
133 lines
[total
++] = wcsdup (wc_line
);
138 wordwrap_lines (&lines
, &total
, &width
);
140 if (width
> MSG_WIDTH
)
144 wc
= str_to_wchar (prompt
);
146 width
= len
> width
? len
: width
;
151 wc
= str_to_wchar (extra
);
153 width
= len
> width
? len
: width
;
158 wc
= str_to_wchar (title
);
160 width
= len
> width
? len
: width
;
172 height
+= 4; // 1 padding, 2 box, 1 prompt
173 width
+= 4; // 2 padding, 2 box
179 static int display_message(WIN
*win
)
181 struct message_s
*m
= win
->data
;
187 keypad(win
->w
, TRUE
);
188 window_draw_title(win
->w
, win
->title
, m
->w
, CP_MESSAGE_TITLE
,
191 for (i
= 0; m
->lines
[i
]; i
++) {
194 if (m
->offset
&& i
< m
->offset
)
197 mvwprintw(win
->w
, (win
->title
) ? 2 + r
: 1 + r
,
198 (m
->center
|| (!i
&& !m
->lines
[i
+1])) ?
199 CENTERX(m
->w
, m
->lines
[i
]) : 1, "%ls", m
->lines
[i
]);
206 window_draw_prompt(win
->w
, (m
->prompt
) ? m
->h
- 3 : m
->h
- 2, m
->w
,
207 m
->extra
, CP_MESSAGE_PROMPT
);
210 window_draw_prompt(win
->w
, m
->h
- 2, m
->w
, m
->prompt
, CP_MESSAGE_PROMPT
);
212 if (m
->func
&& win
->c
== m
->c
) {
218 if (win
->c
== KEY_DOWN
|| win
->c
== 'k' || win
->c
== KEY_UP
222 n
+= m
->extra
? 1 : 0;
224 if ((n_lines
+ n
) - m
->offset
>= LINES
-2)
225 m
->offset
= win
->c
== KEY_DOWN
|| win
->c
== 'k'
226 ? m
->offset
+1 : m
->offset
-1;
227 else if (win
->c
== KEY_UP
|| win
->c
== 'j')
235 return display_message (win
);
238 for (i
= 0; m
->lines
[i
]; i
++)
254 * The force_trim parameter will trim whitespace reguardless if there is more
255 * than one line or not (help text vs. tag viewing).
257 WIN
*construct_message(const char *title
, const char *prompt
, int center
,
258 int force_trim
, const char *extra_help
,
259 message_func
*func
, void *arg
, window_exit_func
*efunc
,
260 wint_t ckey
, int freedata
, const char *fmt
, ...)
262 wchar_t **lines
= NULL
;
264 struct message_s
*m
= NULL
;
269 build_message_lines(title
, prompt
, force_trim
, extra_help
, &h
, &w
, &lines
,
273 m
= Calloc(1, sizeof(struct message_s
));
276 m
->h
= h
> LINES
-2 ? LINES
-2 : h
;
283 m
->prompt
= strdup(prompt
);
286 m
->extra
= strdup(extra_help
);
288 win
= window_create(title
, m
->h
, m
->w
, CALCPOSY(m
->h
), CALCPOSX(m
->w
),
289 display_message
, m
, efunc
);
291 win
->freedata
= freedata
;
292 wbkgd(win
->w
, CP_MESSAGE_WINDOW
);