FIx debug segfault.
[cboard.git] / src / message.c
blob5ab0855e03ee51e0e71e7cf26b9e5b5688050e11
1 /* vim:tw=78:ts=8:sw=4:set ft=c: */
2 /*
3 Copyright (C) 2002-2011 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
19 #ifdef HAVE_CONFIG_H
20 #include <config.h>
21 #endif
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <stdarg.h>
26 #include <string.h>
28 #ifdef HAVE_STDARG_H
29 #include <stdarg.h>
30 #endif
32 #ifdef HAVE_NCURSES_H
33 #include <ncurses.h>
34 #elif defined(HAVE_CURSES_H)
35 #include <curses.h>
36 #endif
38 #ifdef HAVE_PANEL_H
39 #include <panel.h>
40 #endif
42 #ifdef HAVE_LIMITS_H
43 #include <limits.h>
44 #endif
46 #include "chess.h"
47 #include "conf.h"
48 #include "colors.h"
49 #include "misc.h"
50 #include "window.h"
51 #include "message.h"
53 #ifdef WITH_DMALLOC
54 #include <dmalloc.h>
55 #endif
57 static void build_message_lines(const char *title, const char *prompt,
58 int force_trim, const char *extra, int *h, int *w, char ***str,
59 const char *fmt, va_list ap)
61 int i, n, pos;
62 char *line, **lines = NULL;
63 int width = 0, height = 0;
64 char buf[LINE_MAX];
65 char *p;
66 int total = 0;
68 #ifdef HAVE_VASPRINTF
69 vasprintf(&line, fmt, ap);
70 #else
71 line = Malloc(LINE_MAX);
72 vsnprintf(line, LINE_MAX, fmt, ap);
73 #endif
75 /* Get the longest line to dynamically adjust the message box width. */
76 for (i = n = pos = 0; line[i]; i++, n++) {
77 if (line[i] == '\n') {
78 if (n > pos)
79 pos = n;
81 n = 0;
85 pos = (n > pos) ? n : pos;
87 if (pos) {
88 if (pos > MSG_WIDTH)
89 width = MSG_WIDTH;
90 else
91 width = pos;
94 for (i = n = pos = 0; line[i]; i++, n++, pos++) {
95 if (line[i] == '\t')
96 continue;
98 if (line[i] == '\n')
99 pos = 0;
101 if (pos > width) {
102 while (line[--i] != ' ')
103 buf[--n] = ' ';
105 buf[n++] = '\n';
106 pos = 0;
109 buf[n] = line[i];
112 free(line);
114 buf[n] = '\0';
115 p = buf;
116 lines = split_str(p, "\n", &total, &width, force_trim);
118 if (prompt && width < strlen(prompt))
119 width = strlen(prompt);
121 if (extra && width < strlen(extra))
122 width = strlen(extra);
124 if (title && width < strlen(title))
125 width = strlen(title);
127 height = total;
129 if (extra)
130 height++;
132 if (title)
133 height++;
135 height += 4; // 1 padding, 2 box, 1 prompt
136 width += 4; // 2 padding, 2 box
137 *h = height;
138 *w = width;
139 *str = lines;
142 static int display_message(WIN *win)
144 struct message_s *m = win->data;
145 int i;
146 void *p = NULL;
148 keypad(win->w, TRUE);
149 window_draw_title(win->w, win->title, m->w, CP_MESSAGE_TITLE,
150 CP_MESSAGE_BORDER);
152 for (i = 0; m->lines[i]; i++)
153 mvwprintw(win->w, (win->title) ? 2 + i: 1 + i,
154 (m->center || (!i && !m->lines[i+1])) ?
155 CENTERX(m->w, m->lines[i]) : 1, "%s", m->lines[i]);
157 if (m->extra)
158 window_draw_prompt(win->w, (m->prompt) ? m->h - 3 : m->h - 2, m->w,
159 m->extra, CP_MESSAGE_PROMPT);
161 if (m->prompt)
162 window_draw_prompt(win->w, m->h - 2, m->w, m->prompt, CP_MESSAGE_PROMPT);
164 if (m->func && win->c == m->c) {
165 (*m->func)(m->arg);
166 return 1;
169 if (win->c != 0) {
170 for (i = 0; m->lines[i]; i++)
171 free(m->lines[i]);
173 free(m->lines);
175 if (m->prompt)
176 free(m->prompt);
178 if (m->extra)
179 free(m->extra);
181 if (m->arg)
182 p = m->arg;
184 free(m);
185 win->data = p;
186 return 0;
189 return 1;
193 * The force_trim parameter will trim whitespace reguardless if there is more
194 * than one line or not (help text vs. tag viewing).
196 WIN *construct_message(const char *title, const char *prompt, int center,
197 int force_trim, const char *extra_help, message_func *func, void *arg,
198 window_exit_func *efunc, int ckey, int freedata, const char *fmt, ...)
200 char **lines = NULL;
201 va_list ap;
202 struct message_s *m = NULL;
203 WIN *win = NULL;
204 int h, w;
206 va_start(ap, fmt);
207 build_message_lines(title, prompt, force_trim, extra_help, &h, &w, &lines, fmt, ap);
208 va_end(ap);
210 m = Calloc(1, sizeof(struct message_s));
211 m->lines = lines;
212 m->w = w;
213 m->h = h;
214 m->center = center;
215 m->c = ckey;
216 m->func = func;
217 m->arg = arg;
219 if (prompt)
220 m->prompt = strdup(prompt);
222 if (extra_help)
223 m->extra = strdup(extra_help);
225 win = window_create(title, h, w, CALCPOSY(h), CALCPOSX(w), display_message, m,
226 efunc);
228 win->freedata = freedata;
229 wbkgd(win->w, CP_MESSAGE_WINDOW);
230 (*win->func)(win);
231 return win;