1 /* vim:tw=78:ts=8:sw=4:set ft=c: */
3 Copyright (C) 2002-2024 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
45 wordwrap_lines (wchar_t *** olines
, int *nlines
, int *width
)
48 wchar_t *buf
= NULL
, **lines
= *olines
;
49 int total
= *nlines
, w
= *width
;
51 for (i
= 0; i
< total
; i
++)
53 size_t len
= wcslen (lines
[i
]);
57 size_t blen
= wcslen (buf
);
59 lines
[i
] = Realloc (lines
[i
], len
+ blen
+ 1 * sizeof (wchar_t *));
60 wmemmove (&lines
[i
][blen
], lines
[i
], len
);
61 wmemcpy (lines
[i
], buf
, blen
);
62 lines
[i
][blen
+ len
] = 0;
65 len
= wcslen (lines
[i
]);
71 if (len
-- > MSG_WIDTH
)
75 for (p
= lines
[i
] + len
; *p
&& len
> 0; p
--, len
--)
77 if (iswspace (*p
) && len
<= MSG_WIDTH
)
85 /* Its a very long line without any unicode space. Create a
86 * new message line. */
92 t
= lines
[i
] + MSG_WIDTH
;
96 buf
= Malloc (len
* sizeof (wchar_t));
99 wmemcpy (bp
, t
, l
- 1);
108 lines
= Realloc (lines
, (total
+ 2) * sizeof (wchar_t *));
109 lines
[total
++] = buf
;
113 wordwrap_lines (olines
, nlines
, width
);
118 build_message_lines (const char *title
, const char *prompt
,
119 int force_trim
, const char *extra
, int *h
,
120 int *w
, wchar_t *** str
, const char *fmt
, va_list ap
)
124 wchar_t **lines
= NULL
;
125 int width
= 0, height
= 0, len
;
127 wchar_t *wc
, *wc_tmp
, *wc_line
, wc_delim
[] = { '\n', 0 };
129 #ifdef HAVE_VASPRINTF
130 vasprintf (&line
, fmt
, ap
);
132 line
= Malloc (LINE_MAX
);
133 vsnprintf (line
, LINE_MAX
, fmt
, ap
);
136 wc
= str_to_wchar (line
);
139 for (wc_line
= wcstok (wc
, wc_delim
, &wc_tmp
); wc_line
;
140 wc_line
= wcstok (NULL
, wc_delim
, &wc_tmp
))
142 lines
= Realloc (lines
, (total
+ 2) * sizeof (wchar_t *));
143 lines
[total
++] = wcsdup (wc_line
);
148 wordwrap_lines (&lines
, &total
, &width
);
150 if (width
> MSG_WIDTH
)
155 wc
= str_to_wchar (prompt
);
157 width
= len
> width
? len
: width
;
163 wc
= str_to_wchar (extra
);
165 width
= len
> width
? len
: width
;
171 wc
= str_to_wchar (title
);
173 width
= len
> width
? len
: width
;
185 height
+= 4; // 1 padding, 2 box, 1 prompt
186 width
+= 4; // 2 padding, 2 box
193 message_free (WIN
*w
)
195 struct message_s
*m
= w
->data
;
199 for (i
= 0; m
->lines
[i
]; i
++)
211 display_message (WIN
* win
)
213 struct message_s
*m
= win
->data
;
218 keypad (win
->w
, TRUE
);
219 window_draw_title (win
->w
, win
->title
, m
->w
, CP_MESSAGE_TITLE
,
222 for (i
= 0; m
->lines
[i
]; i
++)
226 if (m
->offset
&& i
< m
->offset
)
229 mvwprintw (win
->w
, (win
->title
) ? 2 + r
: 1 + r
,
230 (m
->center
|| (!i
&& !m
->lines
[i
+ 1])) ?
231 CENTERX (m
->w
, m
->lines
[i
]) : 1, "%ls", m
->lines
[i
]);
232 if (++r
>= LINES
- 5)
237 window_draw_prompt (win
->w
, (m
->prompt
) ? m
->h
- 3 : m
->h
- 2, m
->w
,
238 m
->extra
, CP_MESSAGE_PROMPT
);
241 window_draw_prompt (win
->w
, m
->h
- 2, m
->w
, m
->prompt
, CP_MESSAGE_PROMPT
);
243 if (m
->func
&& win
->c
== m
->c
)
251 if (win
->c
== KEY_DOWN
|| win
->c
== KEY_UP
)
255 n
+= m
->extra
? 1 : 0;
257 if ((n_lines
+ n
) - m
->offset
>= LINES
- 2)
258 m
->offset
= win
->c
== KEY_DOWN
? m
->offset
+ 1 : m
->offset
- 1;
259 else if (win
->c
== KEY_UP
)
267 return display_message (win
);
270 if (win
->c
== KEY_RESIZE
)
281 message_resize_func (WIN
*w
)
283 struct message_s
*m
= w
->data
;
284 size_t rows
= wcharv_length (m
->lines
);
286 if (m
->offset
&& rows
>= LINES
- 5)
289 m
->h
= w
->rows
= rows
>= LINES
- 5 ? LINES
- 1 : rows
+ 5;
290 m
->w
= w
->cols
= w
->cols
> COLS
- 2 ? COLS
- 2 : w
->cols
;
291 wresize (w
->w
, w
->rows
, w
->cols
);
292 move_panel (w
->p
, CALCPOSY (w
->rows
), CALCPOSX (w
->cols
));
298 * The force_trim parameter will trim whitespace reguardless if there is more
299 * than one line or not (help text vs. tag viewing).
302 construct_message (const char *title
, const char *prompt
, int center
,
303 int force_trim
, const char *extra_help
,
304 message_func
* func
, void *arg
, window_exit_func
* efunc
,
305 wint_t ckey
, int freedata
, window_resize_func
*rfunc
,
306 const char *fmt
, ...)
308 wchar_t **lines
= NULL
;
310 struct message_s
*m
= NULL
;
315 build_message_lines (title
, prompt
, force_trim
, extra_help
, &h
, &w
, &lines
,
319 m
= Calloc (1, sizeof (struct message_s
));
322 m
->h
= h
> LINES
- 2 ? LINES
- 2 : h
;
329 m
->prompt
= strdup (prompt
);
332 m
->extra
= strdup (extra_help
);
334 win
= window_create (title
, m
->h
, m
->w
, CALCPOSY (m
->h
), CALCPOSX (m
->w
),
335 display_message
, m
, efunc
,
336 rfunc
? rfunc
: message_resize_func
);
338 win
->freedata
= freedata
;
339 wbkgd (win
->w
, CP_MESSAGE_WINDOW
);