1/* Output generating routines for GDB CLI.
2
3   Copyright 1999, 2000, 2001, 2002, 2003 Free Software Foundation,
4   Inc.
5
6   Contributed by Cygnus Solutions.
7   Written by Fernando Nasser for Cygnus.
8
9   This file is part of GDB.
10
11   This program is free software; you can redistribute it and/or modify
12   it under the terms of the GNU General Public License as published by
13   the Free Software Foundation; either version 2 of the License, or
14   (at your option) any later version.
15
16   This program is distributed in the hope that it will be useful,
17   but WITHOUT ANY WARRANTY; without even the implied warranty of
18   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19   GNU General Public License for more details.
20
21   You should have received a copy of the GNU General Public License
22   along with this program; if not, write to the Free Software
23   Foundation, Inc., 59 Temple Place - Suite 330,
24   Boston, MA 02111-1307, USA.  */
25
26#include "defs.h"
27#include "ui-out.h"
28#include "tui.h"
29#include "gdb_string.h"
30#include "gdb_assert.h"
31
32struct ui_out_data
33  {
34    struct ui_file *stream;
35    int suppress_output;
36    int line;
37    int start_of_line;
38  };
39typedef struct ui_out_data tui_out_data;
40
41/* These are the CLI output functions */
42
43static void tui_table_begin (struct ui_out *uiout, int nbrofcols,
44			     int nr_rows, const char *tblid);
45static void tui_table_body (struct ui_out *uiout);
46static void tui_table_end (struct ui_out *uiout);
47static void tui_table_header (struct ui_out *uiout, int width,
48			      enum ui_align alig, const char *col_name,
49			      const char *colhdr);
50static void tui_begin (struct ui_out *uiout, enum ui_out_type type,
51		       int level, const char *lstid);
52static void tui_end (struct ui_out *uiout, enum ui_out_type type, int level);
53static void tui_field_int (struct ui_out *uiout, int fldno, int width,
54			   enum ui_align alig, const char *fldname, int value);
55static void tui_field_skip (struct ui_out *uiout, int fldno, int width,
56			    enum ui_align alig, const char *fldname);
57static void tui_field_string (struct ui_out *uiout, int fldno, int width,
58			      enum ui_align alig, const char *fldname,
59			      const char *string);
60static void tui_field_fmt (struct ui_out *uiout, int fldno,
61			   int width, enum ui_align align,
62			   const char *fldname, const char *format,
63			   va_list args);
64static void tui_spaces (struct ui_out *uiout, int numspaces);
65static void tui_text (struct ui_out *uiout, const char *string);
66static void tui_message (struct ui_out *uiout, int verbosity,
67			 const char *format, va_list args);
68static void tui_wrap_hint (struct ui_out *uiout, char *identstring);
69static void tui_flush (struct ui_out *uiout);
70
71/* This is the CLI ui-out implementation functions vector */
72
73/* FIXME: This can be initialized dynamically after default is set to
74   handle initial output in main.c */
75
76static struct ui_out_impl tui_ui_out_impl =
77{
78  tui_table_begin,
79  tui_table_body,
80  tui_table_end,
81  tui_table_header,
82  tui_begin,
83  tui_end,
84  tui_field_int,
85  tui_field_skip,
86  tui_field_string,
87  tui_field_fmt,
88  tui_spaces,
89  tui_text,
90  tui_message,
91  tui_wrap_hint,
92  tui_flush,
93  NULL,
94  0, /* Does not need MI hacks (i.e. needs CLI hacks).  */
95};
96
97/* Prototypes for local functions */
98
99extern void _initialize_tui_out (void);
100
101static void field_separator (void);
102
103static void out_field_fmt (struct ui_out *uiout, int fldno,
104			   const char *fldname,
105			   const char *format,...);
106
107/* local variables */
108
109/* (none yet) */
110
111/* Mark beginning of a table */
112
113void
114tui_table_begin (struct ui_out *uiout, int nbrofcols,
115		 int nr_rows,
116		 const char *tblid)
117{
118  tui_out_data *data = ui_out_data (uiout);
119  if (nr_rows == 0)
120    data->suppress_output = 1;
121  else
122    /* Only the table suppresses the output and, fortunately, a table
123       is not a recursive data structure. */
124    gdb_assert (data->suppress_output == 0);
125}
126
127/* Mark beginning of a table body */
128
129void
130tui_table_body (struct ui_out *uiout)
131{
132  tui_out_data *data = ui_out_data (uiout);
133  if (data->suppress_output)
134    return;
135  /* first, close the table header line */
136  tui_text (uiout, "\n");
137}
138
139/* Mark end of a table */
140
141void
142tui_table_end (struct ui_out *uiout)
143{
144  tui_out_data *data = ui_out_data (uiout);
145  data->suppress_output = 0;
146}
147
148/* Specify table header */
149
150void
151tui_table_header (struct ui_out *uiout, int width, enum ui_align alignment,
152		  const char *col_name,
153		  const char *colhdr)
154{
155  tui_out_data *data = ui_out_data (uiout);
156  if (data->suppress_output)
157    return;
158  tui_field_string (uiout, 0, width, alignment, 0, colhdr);
159}
160
161/* Mark beginning of a list */
162
163void
164tui_begin (struct ui_out *uiout,
165	   enum ui_out_type type,
166	   int level,
167	   const char *id)
168{
169  tui_out_data *data = ui_out_data (uiout);
170  if (data->suppress_output)
171    return;
172}
173
174/* Mark end of a list */
175
176void
177tui_end (struct ui_out *uiout,
178	 enum ui_out_type type,
179	 int level)
180{
181  tui_out_data *data = ui_out_data (uiout);
182  if (data->suppress_output)
183    return;
184}
185
186/* output an int field */
187
188void
189tui_field_int (struct ui_out *uiout, int fldno, int width,
190	       enum ui_align alignment,
191	       const char *fldname, int value)
192{
193  char buffer[20];		/* FIXME: how many chars long a %d can become? */
194
195  tui_out_data *data = ui_out_data (uiout);
196  if (data->suppress_output)
197    return;
198
199  /* Don't print line number, keep it for later.  */
200  if (data->start_of_line == 0 && strcmp (fldname, "line") == 0)
201    {
202      data->start_of_line ++;
203      data->line = value;
204      return;
205    }
206  data->start_of_line ++;
207  sprintf (buffer, "%d", value);
208  tui_field_string (uiout, fldno, width, alignment, fldname, buffer);
209}
210
211/* used to ommit a field */
212
213void
214tui_field_skip (struct ui_out *uiout, int fldno, int width,
215		enum ui_align alignment,
216		const char *fldname)
217{
218  tui_out_data *data = ui_out_data (uiout);
219  if (data->suppress_output)
220    return;
221  tui_field_string (uiout, fldno, width, alignment, fldname, "");
222}
223
224/* other specific tui_field_* end up here so alignment and field
225   separators are both handled by tui_field_string */
226
227void
228tui_field_string (struct ui_out *uiout,
229		  int fldno,
230		  int width,
231		  enum ui_align align,
232		  const char *fldname,
233		  const char *string)
234{
235  int before = 0;
236  int after = 0;
237
238  tui_out_data *data = ui_out_data (uiout);
239  if (data->suppress_output)
240    return;
241
242  if (fldname && data->line > 0 && strcmp (fldname, "file") == 0)
243    {
244      data->start_of_line ++;
245      if (data->line > 0)
246        {
247          tui_show_source (string, data->line);
248        }
249      return;
250    }
251
252  data->start_of_line ++;
253  if ((align != ui_noalign) && string)
254    {
255      before = width - strlen (string);
256      if (before <= 0)
257	before = 0;
258      else
259	{
260	  if (align == ui_right)
261	    after = 0;
262	  else if (align == ui_left)
263	    {
264	      after = before;
265	      before = 0;
266	    }
267	  else
268	    /* ui_center */
269	    {
270	      after = before / 2;
271	      before -= after;
272	    }
273	}
274    }
275
276  if (before)
277    ui_out_spaces (uiout, before);
278  if (string)
279    out_field_fmt (uiout, fldno, fldname, "%s", string);
280  if (after)
281    ui_out_spaces (uiout, after);
282
283  if (align != ui_noalign)
284    field_separator ();
285}
286
287/* This is the only field function that does not align */
288
289void
290tui_field_fmt (struct ui_out *uiout, int fldno,
291	       int width, enum ui_align align,
292	       const char *fldname,
293	       const char *format,
294	       va_list args)
295{
296  tui_out_data *data = ui_out_data (uiout);
297  if (data->suppress_output)
298    return;
299
300  data->start_of_line ++;
301  vfprintf_filtered (data->stream, format, args);
302
303  if (align != ui_noalign)
304    field_separator ();
305}
306
307void
308tui_spaces (struct ui_out *uiout, int numspaces)
309{
310  tui_out_data *data = ui_out_data (uiout);
311  if (data->suppress_output)
312    return;
313  print_spaces_filtered (numspaces, data->stream);
314}
315
316void
317tui_text (struct ui_out *uiout, const char *string)
318{
319  tui_out_data *data = ui_out_data (uiout);
320  if (data->suppress_output)
321    return;
322  data->start_of_line ++;
323  if (data->line > 0)
324    {
325      if (strchr (string, '\n') != 0)
326        {
327          data->line = -1;
328          data->start_of_line = 0;
329        }
330      return;
331    }
332  if (strchr (string, '\n'))
333    data->start_of_line = 0;
334  fputs_filtered (string, data->stream);
335}
336
337void
338tui_message (struct ui_out *uiout, int verbosity,
339	     const char *format, va_list args)
340{
341  tui_out_data *data = ui_out_data (uiout);
342  if (data->suppress_output)
343    return;
344  if (ui_out_get_verblvl (uiout) >= verbosity)
345    vfprintf_unfiltered (data->stream, format, args);
346}
347
348void
349tui_wrap_hint (struct ui_out *uiout, char *identstring)
350{
351  tui_out_data *data = ui_out_data (uiout);
352  if (data->suppress_output)
353    return;
354  wrap_here (identstring);
355}
356
357void
358tui_flush (struct ui_out *uiout)
359{
360  tui_out_data *data = ui_out_data (uiout);
361  gdb_flush (data->stream);
362}
363
364/* local functions */
365
366/* Like tui_field_fmt, but takes a variable number of args
367   and makes a va_list and does not insert a separator */
368
369/* VARARGS */
370static void
371out_field_fmt (struct ui_out *uiout, int fldno,
372	       const char *fldname,
373	       const char *format,...)
374{
375  tui_out_data *data = ui_out_data (uiout);
376  va_list args;
377
378  va_start (args, format);
379  vfprintf_filtered (data->stream, format, args);
380
381  va_end (args);
382}
383
384/* access to ui_out format private members */
385
386static void
387field_separator (void)
388{
389  tui_out_data *data = ui_out_data (uiout);
390  fputc_filtered (' ', data->stream);
391}
392
393/* initalize private members at startup */
394
395struct ui_out *
396tui_out_new (struct ui_file *stream)
397{
398  int flags = 0;
399
400  tui_out_data *data = XMALLOC (tui_out_data);
401  data->stream = stream;
402  data->suppress_output = 0;
403  data->line = -1;
404  data->start_of_line = 0;
405  return ui_out_new (&tui_ui_out_impl, data, flags);
406}
407
408/* standard gdb initialization hook */
409void
410_initialize_tui_out (void)
411{
412  /* nothing needs to be done */
413}
414