1 /* vim:tw=78:ts=8:sw=4:set ft=c: */
3 Copyright (C) 2002-2013 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
, int *w
, wchar_t ***str
,
111 const char *fmt
, va_list ap
)
115 wchar_t **lines
= NULL
;
116 int width
= 0, height
= 0, len
;
118 wchar_t *wc
, *wc_tmp
, *wc_line
, wc_delim
[] = { '\n', 0 };
120 #ifdef HAVE_VASPRINTF
121 vasprintf(&line
, fmt
, ap
);
123 line
= Malloc(LINE_MAX
);
124 vsnprintf(line
, LINE_MAX
, fmt
, ap
);
127 wc
= str_to_wchar (line
);
130 for (wc_line
= wcstok (wc
, wc_delim
, &wc_tmp
); wc_line
; wc_line
= wcstok (NULL
, wc_delim
, &wc_tmp
)) {
131 lines
= Realloc (lines
, (total
+2)*sizeof(wchar_t **));
132 lines
[total
++] = wcsdup (wc_line
);
137 wordwrap_lines (&lines
, &total
, &width
);
139 if (width
> MSG_WIDTH
)
143 wc
= str_to_wchar (prompt
);
145 width
= len
> width
? len
: width
;
150 wc
= str_to_wchar (extra
);
152 width
= len
> width
? len
: width
;
157 wc
= str_to_wchar (title
);
159 width
= len
> width
? len
: width
;
171 height
+= 4; // 1 padding, 2 box, 1 prompt
172 width
+= 4; // 2 padding, 2 box
178 static int display_message(WIN
*win
)
180 struct message_s
*m
= win
->data
;
184 keypad(win
->w
, TRUE
);
185 window_draw_title(win
->w
, win
->title
, m
->w
, CP_MESSAGE_TITLE
,
188 for (i
= 0; m
->lines
[i
]; i
++)
189 mvwprintw(win
->w
, (win
->title
) ? 2 + i
: 1 + i
,
190 (m
->center
|| (!i
&& !m
->lines
[i
+1])) ?
191 CENTERX(m
->w
, m
->lines
[i
]) : 1, "%ls", m
->lines
[i
]);
194 window_draw_prompt(win
->w
, (m
->prompt
) ? m
->h
- 3 : m
->h
- 2, m
->w
,
195 m
->extra
, CP_MESSAGE_PROMPT
);
198 window_draw_prompt(win
->w
, m
->h
- 2, m
->w
, m
->prompt
, CP_MESSAGE_PROMPT
);
200 if (m
->func
&& win
->c
== m
->c
) {
206 for (i
= 0; m
->lines
[i
]; i
++)
222 * The force_trim parameter will trim whitespace reguardless if there is more
223 * than one line or not (help text vs. tag viewing).
225 WIN
*construct_message(const char *title
, const char *prompt
, int center
,
226 int force_trim
, const char *extra_help
,
227 message_func
*func
, void *arg
, window_exit_func
*efunc
,
228 wint_t ckey
, int freedata
, const char *fmt
, ...)
230 wchar_t **lines
= NULL
;
232 struct message_s
*m
= NULL
;
237 build_message_lines(title
, prompt
, force_trim
, extra_help
, &h
, &w
, &lines
, fmt
, ap
);
240 m
= Calloc(1, sizeof(struct message_s
));
250 m
->prompt
= strdup(prompt
);
253 m
->extra
= strdup(extra_help
);
255 win
= window_create(title
, h
, w
, CALCPOSY(h
), CALCPOSX(w
), display_message
,
258 win
->freedata
= freedata
;
259 wbkgd(win
->w
, CP_MESSAGE_WINDOW
);