Use wmem_new to get the automatic casts to fix the buildbot.
[metze/wireshark/wip.git] / epan / column.c
1 /* column.c
2  * Routines for handling column preferences
3  *
4  * $Id$
5  *
6  * Wireshark - Network traffic analyzer
7  * By Gerald Combs <gerald@wireshark.org>
8  * Copyright 1998 Gerald Combs
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23  */
24
25 #include "config.h"
26
27 #include <stdio.h>
28 #include <string.h>
29 #include <ctype.h>
30 #include <errno.h>
31
32 #ifdef HAVE_UNISTD_H
33 #include <unistd.h>
34 #endif
35
36 #include <epan/timestamp.h>
37 #include <epan/prefs.h>
38 #include <epan/dfilter/dfilter.h>
39 #include <epan/column.h>
40 #include <epan/packet.h>
41
42 /* Given a format number (as defined in column_info.h), returns its equivalent
43    string */
44 const gchar *
45 col_format_to_string(const gint fmt) {
46   static const gchar *const slist[NUM_COL_FMTS] = {
47     "%q",                                       /* 0) COL_8021Q_VLAN_ID */
48     "%Yt",                                      /* 1) COL_ABS_DATE_TIME */
49     "%At",                                      /* 2) COL_ABS_TIME */
50     "%c",                                       /* 3) COL_CIRCUIT_ID */
51     "%Xd",                                      /* 4) COL_DSTIDX */
52     "%Xs",                                      /* 5) COL_SRCIDX */
53     "%V",                                       /* 6) COL_VSAN */
54     "%B",                                       /* 7) COL_CUMULATIVE_BYTES */
55     "%Cus",                                     /* 8) COL_CUSTOM */
56     "%y",                                       /* 9) COL_DCE_CALL */
57     "%z",                                       /* 10) COL_DCE_CTX */
58     "%Tt",                                      /* 11) COL_DELTA_TIME */
59     "%dct",                                     /* 12) COL_DELTA_CONV_TIME */
60     "%Gt",                                      /* 13) COL_DELTA_TIME_DIS */
61     "%rd",                                      /* 14) COL_RES_DST */
62     "%ud",                                      /* 15) COL_UNRES_DST */
63     "%rD",                                      /* 16) COL_RES_DST_PORT */
64     "%uD",                                      /* 17) COL_UNRES_DST_PORT */
65     "%d",                                       /* 18) COL_DEF_DST */
66     "%D",                                       /* 19) COL_DEF_DST_PORT */
67     "%a",                                       /* 20) COL_EXPERT */
68     "%I",                                       /* 21) COL_IF_DIR */
69     "%XO",                                      /* 22) COL_OXID */
70     "%XR",                                      /* 23) COL_RXID */
71     "%C",                                       /* 24) !! DEPRECATED !! - COL_FR_DLCI */
72     "%F",                                       /* 25) COL_FREQ_CHAN */
73     "%l",                                       /* 26) !! DEPRECATED !! - COL_BSSGP_TLLI */
74     "%P",                                       /* 27) !! DEPRECATED !! - COL_HPUX_DEVID */
75     "%H",                                       /* 28) !! DEPRECATED !! - COL_HPUX_SUBSYS */
76     "%hd",                                      /* 29) COL_DEF_DL_DST */
77     "%hs",                                      /* 30) COL_DEF_DL_SRC */
78     "%rhd",                                     /* 31) COL_RES_DL_DST */
79     "%uhd",                                     /* 32) COL_UNRES_DL_DST */
80     "%rhs",                                     /* 33) COL_RES_DL_SRC*/
81     "%uhs",                                     /* 34) COL_UNRES_DL_SRC */
82     "%e",                                       /* 35) COL_RSSI */
83     "%x",                                       /* 36) COL_TX_RATE */
84     "%f",                                       /* 37) COL_DSCP_VALUE */
85     "%i",                                       /* 38) COL_INFO */
86     "%U",                                       /* 39) !! DEPRECATED !! - COL_COS_VALUE */
87     "%rnd",                                     /* 40) COL_RES_NET_DST */
88     "%und",                                     /* 41) COL_UNRES_NET_DST */
89     "%rns",                                     /* 42) COL_RES_NET_SRC */
90     "%uns",                                     /* 43) COL_UNRES_NET_SRC */
91     "%nd",                                      /* 44) COL_DEF_NET_DST */
92     "%ns",                                      /* 45) COL_DEF_NET_SRC */
93     "%m",                                       /* 46) COL_NUMBER */
94     "%L",                                       /* 47) COL_PACKET_LENGTH */
95     "%p",                                       /* 48) COL_PROTOCOL */
96     "%Rt",                                      /* 49) COL_REL_TIME */
97     "%rct",                                     /* 50) !! DEPRECATED !! - COL_REL_CONV_TIME */
98     "%s",                                       /* 51) COL_DEF_SRC */
99     "%S",                                       /* 52) COL_DEF_SRC_PORT */
100     "%rs",                                      /* 53) COL_RES_SRC */
101     "%us",                                      /* 54) COL_UNRES_SRC */
102     "%rS",                                      /* 55) COL_RES_SRC_PORT */
103     "%uS",                                      /* 56) COL_UNRES_SRC_PORT */
104     "%E",                                       /* 57) COL_TEI */
105     "%Yut",                                     /* 58) COL_UTC_DATE_TIME */
106     "%Aut",                                     /* 59) COL_UTC_TIME */
107     "%t"                                        /* 60) COL_CLS_TIME */
108   };
109
110   if (fmt < 0 || fmt >= NUM_COL_FMTS)
111     return NULL;
112
113   return(slist[fmt]);
114 }
115
116 /* Given a format number (as defined in column_info.h), returns its
117   description */
118 const gchar *
119 col_format_desc(const gint fmt) {
120   static const gchar *const dlist[NUM_COL_FMTS] = {
121     "802.1Q VLAN id",                           /* 0) COL_8021Q_VLAN_ID */
122     "Absolute date and time",                   /* 1) COL_ABS_DATE_TIME */
123     "Absolute time",                            /* 2) COL_ABS_TIME */
124     "Circuit ID",                               /* 3) COL_CIRCUIT_ID */
125     "Cisco Dst PortIdx",                        /* 4) COL_DSTIDX */
126     "Cisco Src PortIdx",                        /* 5) COL_SRCIDX */
127     "Cisco VSAN",                               /* 6) COL_VSAN */
128     "Cumulative Bytes" ,                        /* 7) COL_CUMULATIVE_BYTES */
129     "Custom",                                   /* 8) COL_CUSTOM */
130     "DCE/RPC call (cn_call_id / dg_seqnum)",    /* 9) COL_DCE_CALL */
131     "DCE/RPC context ID (cn_ctx_id)",           /* 10) COL_DCE_CTX */
132     "Delta time",                               /* 11) COL_DELTA_TIME */
133     "Delta time (conversation)",                /* 12) COL_DELTA_CONV_TIME */
134     "Delta time displayed",                     /* 13) COL_DELTA_TIME_DIS */
135     "Dest addr (resolved)",                     /* 14) COL_RES_DST */
136     "Dest addr (unresolved)",                   /* 15) COL_UNRES_DST */
137     "Dest port (resolved)",                     /* 16) COL_RES_DST_PORT */
138     "Dest port (unresolved)",                   /* 17) COL_UNRES_DST_PORT */
139     "Destination address",                      /* 18) COL_DEF_DST */
140     "Destination port",                         /* 19) COL_DEF_DST_PORT */
141     "Expert Info Severity",                     /* 20) COL_EXPERT */
142     "FW-1 monitor if/direction",                /* 21) COL_IF_DIR */
143     "Fibre Channel OXID",                       /* 22) COL_OXID */
144     "Fibre Channel RXID",                       /* 23) COL_RXID */
145     "Frame Relay DLCI",                         /* 24) !! DEPRECATED !! - COL_FR_DLCI */
146     "Frequency/Channel",                        /* 25) COL_FREQ_CHAN */
147     "GPRS BSSGP TLLI",                          /* 26) !! DEPRECATED !! - COL_BSSGP_TLLI */
148     "HP-UX Device ID",                          /* 27) !! DEPRECATED !! - COL_HPUX_DEVID */
149     "HP-UX Subsystem",                          /* 28) !! DEPRECATED !! - COL_HPUX_SUBSYS */
150     "Hardware dest addr",                       /* 29) COL_DEF_DL_DST */
151     "Hardware src addr",                        /* 30) COL_DEF_DL_SRC */
152     "Hw dest addr (resolved)",                  /* 31) COL_RES_DL_DST */
153     "Hw dest addr (unresolved)",                /* 32) COL_UNRES_DL_DST */
154     "Hw src addr (resolved)",                   /* 33) COL_RES_DL_SRC*/
155     "Hw src addr (unresolved)",                 /* 34) COL_UNRES_DL_SRC */
156     "IEEE 802.11 RSSI",                         /* 35) COL_RSSI */
157     "IEEE 802.11 TX rate",                      /* 36) COL_TX_RATE */
158     "IP DSCP Value",                            /* 37) COL_DSCP_VALUE */
159     "Information",                              /* 38) COL_INFO */
160     "L2 COS Value (802.1p)",                    /* 39) !! DEPRECATED !! - COL_COS_VALUE */
161     "Net dest addr (resolved)",                 /* 40) COL_RES_NET_DST */
162     "Net dest addr (unresolved)",               /* 41) COL_UNRES_NET_DST */
163     "Net src addr (resolved)",                  /* 42) COL_RES_NET_SRC */
164     "Net src addr (unresolved)",                /* 43) COL_UNRES_NET_SRC */
165     "Network dest addr",                        /* 44) COL_DEF_NET_DST */
166     "Network src addr",                         /* 45) COL_DEF_NET_SRC */
167     "Number",                                   /* 46) COL_NUMBER */
168     "Packet length (bytes)" ,                   /* 47) COL_PACKET_LENGTH */
169     "Protocol",                                 /* 48) COL_PROTOCOL */
170     "Relative time",                            /* 49) COL_REL_TIME */
171     "Relative time (conversation)",             /* 50) !! DEPRECATED !! - COL_REL_CONV_TIME */
172     "Source address",                           /* 51) COL_DEF_SRC */
173     "Source port",                              /* 52) COL_DEF_SRC_PORT */
174     "Src addr (resolved)",                      /* 53) COL_RES_SRC */
175     "Src addr (unresolved)",                    /* 54) COL_UNRES_SRC */
176     "Src port (resolved)",                      /* 55) COL_RES_SRC_PORT */
177     "Src port (unresolved)",                    /* 56) COL_UNRES_SRC_PORT */
178     "TEI",                                      /* 57) COL_TEI */
179     "UTC date and time",                        /* 58) COL_UTC_DATE_TIME */
180     "UTC time",                                 /* 59) COL_UTC_TIME */
181     "Time (format as specified)"                /* 60) COL_CLS_TIME */
182   };
183
184   g_assert((fmt >= 0) && (fmt < NUM_COL_FMTS));
185   return(dlist[fmt]);
186 }
187
188 /* Marks each array element true if it can be substituted for the given
189    column format */
190 void
191 get_column_format_matches(gboolean *fmt_list, const gint format) {
192
193   /* Get the obvious: the format itself */
194   if ((format >= 0) && (format < NUM_COL_FMTS))
195     fmt_list[format] = TRUE;
196
197   /* Get any formats lower down on the chain */
198   switch (format) {
199     case COL_DEF_SRC:
200       fmt_list[COL_RES_DL_SRC] = TRUE;
201       fmt_list[COL_RES_NET_SRC] = TRUE;
202       break;
203     case COL_RES_SRC:
204       fmt_list[COL_RES_DL_SRC] = TRUE;
205       fmt_list[COL_RES_NET_SRC] = TRUE;
206       break;
207     case COL_UNRES_SRC:
208       fmt_list[COL_UNRES_DL_SRC] = TRUE;
209       fmt_list[COL_UNRES_NET_SRC] = TRUE;
210       break;
211     case COL_DEF_DST:
212       fmt_list[COL_RES_DL_DST] = TRUE;
213       fmt_list[COL_RES_NET_DST] = TRUE;
214       break;
215     case COL_RES_DST:
216       fmt_list[COL_RES_DL_DST] = TRUE;
217       fmt_list[COL_RES_NET_DST] = TRUE;
218       break;
219     case COL_UNRES_DST:
220       fmt_list[COL_UNRES_DL_DST] = TRUE;
221       fmt_list[COL_UNRES_NET_DST] = TRUE;
222       break;
223     case COL_DEF_DL_SRC:
224       fmt_list[COL_RES_DL_SRC] = TRUE;
225       break;
226     case COL_DEF_DL_DST:
227       fmt_list[COL_RES_DL_DST] = TRUE;
228       break;
229     case COL_DEF_NET_SRC:
230       fmt_list[COL_RES_NET_SRC] = TRUE;
231       break;
232     case COL_DEF_NET_DST:
233       fmt_list[COL_RES_NET_DST] = TRUE;
234       break;
235     case COL_DEF_SRC_PORT:
236       fmt_list[COL_RES_SRC_PORT] = TRUE;
237       break;
238     case COL_DEF_DST_PORT:
239       fmt_list[COL_RES_DST_PORT] = TRUE;
240       break;
241     default:
242       break;
243   }
244 }
245
246 /* Returns a string representing the longest possible value for
247    a timestamp column type. */
248 static const char *
249 get_timestamp_column_longest_string(const gint type, const gint precision)
250 {
251
252     switch(type) {
253     case(TS_ABSOLUTE_WITH_DATE):
254     case(TS_UTC_WITH_DATE):
255         switch(precision) {
256             case(TS_PREC_AUTO_SEC):
257             case(TS_PREC_FIXED_SEC):
258                 return "0000-00-00 00:00:00";
259                 break;
260             case(TS_PREC_AUTO_DSEC):
261             case(TS_PREC_FIXED_DSEC):
262                 return "0000-00-00 00:00:00.0";
263                 break;
264             case(TS_PREC_AUTO_CSEC):
265             case(TS_PREC_FIXED_CSEC):
266                 return "0000-00-00 00:00:00.00";
267                 break;
268             case(TS_PREC_AUTO_MSEC):
269             case(TS_PREC_FIXED_MSEC):
270                 return "0000-00-00 00:00:00.000";
271                 break;
272             case(TS_PREC_AUTO_USEC):
273             case(TS_PREC_FIXED_USEC):
274                 return "0000-00-00 00:00:00.000000";
275                 break;
276             case(TS_PREC_AUTO_NSEC):
277             case(TS_PREC_FIXED_NSEC):
278                 return "0000-00-00 00:00:00.000000000";
279                 break;
280             default:
281                 g_assert_not_reached();
282         }
283             break;
284     case(TS_ABSOLUTE):
285     case(TS_UTC):
286         switch(precision) {
287             case(TS_PREC_AUTO_SEC):
288             case(TS_PREC_FIXED_SEC):
289                 return "00:00:00";
290                 break;
291             case(TS_PREC_AUTO_DSEC):
292             case(TS_PREC_FIXED_DSEC):
293                 return "00:00:00.0";
294                 break;
295             case(TS_PREC_AUTO_CSEC):
296             case(TS_PREC_FIXED_CSEC):
297                 return "00:00:00.00";
298                 break;
299             case(TS_PREC_AUTO_MSEC):
300             case(TS_PREC_FIXED_MSEC):
301                 return "00:00:00.000";
302                 break;
303             case(TS_PREC_AUTO_USEC):
304             case(TS_PREC_FIXED_USEC):
305                 return "00:00:00.000000";
306                 break;
307             case(TS_PREC_AUTO_NSEC):
308             case(TS_PREC_FIXED_NSEC):
309                 return "00:00:00.000000000";
310                 break;
311             default:
312                 g_assert_not_reached();
313         }
314         break;
315     case(TS_RELATIVE):  /* fallthrough */
316     case(TS_DELTA):
317     case(TS_DELTA_DIS):
318         switch(precision) {
319             case(TS_PREC_AUTO_SEC):
320             case(TS_PREC_FIXED_SEC):
321                 return "0000";
322                 break;
323             case(TS_PREC_AUTO_DSEC):
324             case(TS_PREC_FIXED_DSEC):
325                 return "0000.0";
326                 break;
327             case(TS_PREC_AUTO_CSEC):
328             case(TS_PREC_FIXED_CSEC):
329                 return "0000.00";
330                 break;
331             case(TS_PREC_AUTO_MSEC):
332             case(TS_PREC_FIXED_MSEC):
333                 return "0000.000";
334                 break;
335             case(TS_PREC_AUTO_USEC):
336             case(TS_PREC_FIXED_USEC):
337                 return "0000.000000";
338                 break;
339             case(TS_PREC_AUTO_NSEC):
340             case(TS_PREC_FIXED_NSEC):
341                 return "0000.000000000";
342                 break;
343             default:
344                 g_assert_not_reached();
345         }
346         break;
347     case(TS_EPOCH):
348         /* This is enough to represent 2^63 (signed 64-bit integer) + fractions */
349         switch(precision) {
350             case(TS_PREC_AUTO_SEC):
351             case(TS_PREC_FIXED_SEC):
352                 return "0000000000000000000";
353                 break;
354             case(TS_PREC_AUTO_DSEC):
355             case(TS_PREC_FIXED_DSEC):
356                 return "0000000000000000000.0";
357                 break;
358             case(TS_PREC_AUTO_CSEC):
359             case(TS_PREC_FIXED_CSEC):
360                 return "0000000000000000000.00";
361                 break;
362             case(TS_PREC_AUTO_MSEC):
363             case(TS_PREC_FIXED_MSEC):
364                 return "0000000000000000000.000";
365                 break;
366             case(TS_PREC_AUTO_USEC):
367             case(TS_PREC_FIXED_USEC):
368                 return "0000000000000000000.000000";
369                 break;
370             case(TS_PREC_AUTO_NSEC):
371             case(TS_PREC_FIXED_NSEC):
372                 return "0000000000000000000.000000000";
373                 break;
374             default:
375                 g_assert_not_reached();
376         }
377         break;
378     case(TS_NOT_SET):
379         return "0000.000000";
380         break;
381     default:
382         g_assert_not_reached();
383     }
384
385     /* never reached, satisfy compiler */
386     return "";
387 }
388
389 /* Returns the longer string of the column title or the hard-coded width of
390  * its contents for building the packet list layout. */
391 const gchar *
392 get_column_width_string(const gint format, const gint col)
393 {
394     if(strlen(get_column_longest_string(format)) >
395        strlen(get_column_title(col)))
396         return get_column_longest_string(format);
397     else
398         return get_column_title(col);
399 }
400
401 /* Returns a string representing the longest possible value for a
402    particular column type.  See also get_column_width_string() above.
403
404    Except for the COL...SRC and COL...DST columns, these are used
405    only when a capture is being displayed while it's taking place;
406    they are arguably somewhat fragile, as changes to the code that
407    generates them don't cause these widths to change, but that's
408    probably not too big a problem, given that the sizes are
409    recomputed based on the actual data in the columns when the capture
410    is done, and given that the width for COL...SRC and COL...DST columns
411    is somewhat arbitrary in any case.  We should probably clean
412    that up eventually, though. */
413 const char *
414 get_column_longest_string(const gint format)
415 {
416   switch (format) {
417     case COL_NUMBER:
418       return "0000000";
419       break;
420     case COL_CLS_TIME:
421       return get_timestamp_column_longest_string(timestamp_get_type(), timestamp_get_precision());
422       break;
423     case COL_ABS_DATE_TIME:
424       return get_timestamp_column_longest_string(TS_ABSOLUTE_WITH_DATE, timestamp_get_precision());
425       break;
426     case COL_UTC_DATE_TIME:
427       return get_timestamp_column_longest_string(TS_UTC_WITH_DATE, timestamp_get_precision());
428       break;
429     case COL_ABS_TIME:
430       return get_timestamp_column_longest_string(TS_ABSOLUTE, timestamp_get_precision());
431       break;
432     case COL_UTC_TIME:
433       return get_timestamp_column_longest_string(TS_UTC, timestamp_get_precision());
434       break;
435     case COL_REL_TIME:
436       return get_timestamp_column_longest_string(TS_RELATIVE, timestamp_get_precision());
437       break;
438     case COL_DELTA_TIME:
439       return get_timestamp_column_longest_string(TS_DELTA, timestamp_get_precision());
440       break;
441     case COL_DELTA_TIME_DIS:
442       return get_timestamp_column_longest_string(TS_DELTA_DIS, timestamp_get_precision());
443       break;
444     case COL_REL_CONV_TIME: /* 'abuse' TS_RELATIVE to set the time format */
445     case COL_DELTA_CONV_TIME:   /* for the conversation related time columns */
446       return get_timestamp_column_longest_string(TS_RELATIVE, timestamp_get_precision());
447       break;
448     case COL_DEF_SRC:
449     case COL_RES_SRC:
450     case COL_UNRES_SRC:
451     case COL_DEF_DL_SRC:
452     case COL_RES_DL_SRC:
453     case COL_UNRES_DL_SRC:
454     case COL_DEF_NET_SRC:
455     case COL_RES_NET_SRC:
456     case COL_UNRES_NET_SRC:
457     case COL_DEF_DST:
458     case COL_RES_DST:
459     case COL_UNRES_DST:
460     case COL_DEF_DL_DST:
461     case COL_RES_DL_DST:
462     case COL_UNRES_DL_DST:
463     case COL_DEF_NET_DST:
464     case COL_RES_NET_DST:
465     case COL_UNRES_NET_DST:
466       return "00000000.000000000000"; /* IPX-style */
467       break;
468     case COL_DEF_SRC_PORT:
469     case COL_RES_SRC_PORT:
470     case COL_UNRES_SRC_PORT:
471     case COL_DEF_DST_PORT:
472     case COL_RES_DST_PORT:
473     case COL_UNRES_DST_PORT:
474       return "000000";
475       break;
476     case COL_PROTOCOL:
477       return "Protocol";    /* not the longest, but the longest is too long */
478       break;
479     case COL_PACKET_LENGTH:
480       return "00000";
481       break;
482     case COL_CUMULATIVE_BYTES:
483       return "00000000";
484       break;
485     case COL_RXID:
486     case COL_OXID:
487       return "000000";
488       break;
489     case COL_IF_DIR:
490       return "i 00000000 I";
491       break;
492     case COL_CIRCUIT_ID:
493       return "000000";
494       break;
495     case COL_SRCIDX:
496     case COL_DSTIDX:
497       return "0000000";
498       break;
499     case COL_VSAN:
500      return "000000";
501       break;
502     case COL_TX_RATE:
503       return "108.0";
504       break;
505     case COL_RSSI:
506       return "100";
507       break;
508     case COL_HPUX_SUBSYS:
509       return "OTS9000-TRANSPORT";
510       break;
511     case COL_HPUX_DEVID:
512       return "0000";
513       break;
514     case COL_DCE_CALL:
515       return "0000";
516       break;
517     case COL_DCE_CTX:
518       return "0000";
519       break;
520     case COL_8021Q_VLAN_ID:
521       return "0000";
522       break;
523     case COL_DSCP_VALUE:
524       return "00";
525       break;
526     case COL_COS_VALUE:
527       return "0";
528       break;
529     case COL_TEI:
530       return "127";
531       break;
532     case COL_FR_DLCI:
533       return "8388608";
534       break;
535     case COL_BSSGP_TLLI:
536       return "0xffffffff";
537       break;
538     case COL_EXPERT:
539       return "ERROR";
540       break;
541     case COL_FREQ_CHAN:
542       return "9999 MHz [A 999]";
543       break;
544     case COL_CUSTOM:
545       return "0000000000";  /* not the longest, but the longest is too long */
546       break;
547     default: /* COL_INFO */
548       return "Source port: kerberos-master  Destination port: kerberos-master";
549       break;
550   }
551 }
552
553 /* Returns the longest possible width, in characters, for a particular
554    column type. */
555 gint
556 get_column_char_width(const gint format)
557 {
558   return (gint)strlen(get_column_longest_string(format));
559 }
560
561 gint
562 get_column_format(const gint col)
563 {
564   GList    *clp = g_list_nth(prefs.col_list, col);
565   fmt_data *cfmt;
566
567   if (!clp)  /* Invalid column requested */
568     return -1;
569
570   cfmt = (fmt_data *) clp->data;
571
572   return(cfmt->fmt);
573 }
574
575 void
576 set_column_format(const gint col, const gint fmt)
577 {
578   GList    *clp = g_list_nth(prefs.col_list, col);
579   fmt_data *cfmt;
580
581   if (!clp)  /* Invalid column requested */
582     return;
583
584   cfmt = (fmt_data *) clp->data;
585
586   cfmt->fmt = fmt;
587 }
588
589 gint
590 get_column_format_from_str(const gchar *str)
591 {
592   gint i;
593
594   for (i = 0; i < NUM_COL_FMTS; i++) {
595     if (strcmp(str, col_format_to_string(i)) == 0)
596       return i;
597   }
598   return -1;    /* illegal */
599 }
600
601 gchar *
602 get_column_title(const gint col)
603 {
604   GList    *clp = g_list_nth(prefs.col_list, col);
605   fmt_data *cfmt;
606
607   if (!clp)  /* Invalid column requested */
608     return NULL;
609
610   cfmt = (fmt_data *) clp->data;
611
612   return(cfmt->title);
613 }
614
615 void
616 set_column_title(const gint col, const gchar *title)
617 {
618   GList    *clp = g_list_nth(prefs.col_list, col);
619   fmt_data *cfmt;
620
621   if (!clp)  /* Invalid column requested */
622     return;
623
624   cfmt = (fmt_data *) clp->data;
625
626   g_free (cfmt->title);
627   cfmt->title = g_strdup (title);
628 }
629
630 gboolean
631 get_column_visible(const gint col)
632 {
633   GList    *clp = g_list_nth(prefs.col_list, col);
634   fmt_data *cfmt;
635
636   if (!clp)  /* Invalid column requested */
637     return TRUE;
638
639   cfmt = (fmt_data *) clp->data;
640
641   return(cfmt->visible);
642 }
643
644 void
645 set_column_visible(const gint col, gboolean visible)
646 {
647   GList    *clp = g_list_nth(prefs.col_list, col);
648   fmt_data *cfmt;
649
650   if (!clp)  /* Invalid column requested */
651     return;
652
653   cfmt = (fmt_data *) clp->data;
654
655   cfmt->visible = visible;
656 }
657
658 gboolean
659 get_column_resolved(const gint col)
660 {
661   GList    *clp = g_list_nth(prefs.col_list, col);
662   fmt_data *cfmt;
663
664   if (!clp)  /* Invalid column requested */
665     return TRUE;
666
667   cfmt = (fmt_data *) clp->data;
668
669   return(cfmt->resolved);
670 }
671
672 void
673 set_column_resolved(const gint col, gboolean resolved)
674 {
675   GList    *clp = g_list_nth(prefs.col_list, col);
676   fmt_data *cfmt;
677
678   if (!clp)  /* Invalid column requested */
679     return;
680
681   cfmt = (fmt_data *) clp->data;
682
683   cfmt->resolved = resolved;
684 }
685
686 const gchar *
687 get_column_custom_field(const gint col)
688 {
689   GList    *clp = g_list_nth(prefs.col_list, col);
690   fmt_data *cfmt;
691
692   if (!clp)  /* Invalid column requested */
693     return NULL;
694
695   cfmt = (fmt_data *) clp->data;
696
697   return(cfmt->custom_field);
698 }
699
700 void
701 set_column_custom_field(const gint col, const char *custom_field)
702 {
703   GList    *clp = g_list_nth(prefs.col_list, col);
704   fmt_data *cfmt;
705
706   if (!clp)  /* Invalid column requested */
707     return;
708
709   cfmt = (fmt_data *) clp->data;
710
711   g_free (cfmt->custom_field);
712   cfmt->custom_field = g_strdup (custom_field);
713 }
714
715 gint
716 get_column_custom_occurrence(const gint col)
717 {
718   GList    *clp = g_list_nth(prefs.col_list, col);
719   fmt_data *cfmt;
720
721   if (!clp)  /* Invalid column requested */
722     return 0;
723
724   cfmt = (fmt_data *) clp->data;
725
726   return(cfmt->custom_occurrence);
727 }
728
729 void
730 set_column_custom_occurrence(const gint col, const gint custom_occurrence)
731 {
732   GList    *clp = g_list_nth(prefs.col_list, col);
733   fmt_data *cfmt;
734
735   if (!clp)  /* Invalid column requested */
736     return;
737
738   cfmt = (fmt_data *) clp->data;
739
740   cfmt->custom_occurrence = custom_occurrence;
741 }
742
743 void
744 build_column_format_array(column_info *cinfo, const gint num_cols, const gboolean reset_fences)
745 {
746   int i;
747
748   /* Build the column format array */
749   col_setup(cinfo, num_cols);
750
751   for (i = 0; i < cinfo->num_cols; i++) {
752     cinfo->col_fmt[i] = get_column_format(i);
753     cinfo->col_title[i] = g_strdup(get_column_title(i));
754
755     if (cinfo->col_fmt[i] == COL_CUSTOM) {
756       cinfo->col_custom_field[i] = g_strdup(get_column_custom_field(i));
757       cinfo->col_custom_occurrence[i] = get_column_custom_occurrence(i);
758       if(!dfilter_compile(cinfo->col_custom_field[i], &cinfo->col_custom_dfilter[i])) {
759         /* XXX: Should we issue a warning? */
760         g_free(cinfo->col_custom_field[i]);
761         cinfo->col_custom_field[i] = NULL;
762         cinfo->col_custom_occurrence[i] = 0;
763         cinfo->col_custom_dfilter[i] = NULL;
764       }
765     } else {
766       cinfo->col_custom_field[i] = NULL;
767       cinfo->col_custom_occurrence[i] = 0;
768       cinfo->col_custom_dfilter[i] = NULL;
769     }
770
771     cinfo->fmt_matx[i] = (gboolean *) g_malloc0(sizeof(gboolean) * NUM_COL_FMTS);
772     get_column_format_matches(cinfo->fmt_matx[i], cinfo->col_fmt[i]);
773     cinfo->col_data[i] = NULL;
774
775     if (cinfo->col_fmt[i] == COL_INFO)
776       cinfo->col_buf[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_INFO_LEN);
777     else
778       cinfo->col_buf[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
779
780     if(reset_fences)
781       cinfo->col_fence[i] = 0;
782
783     cinfo->col_expr.col_expr[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
784     cinfo->col_expr.col_expr_val[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
785   }
786
787   cinfo->col_expr.col_expr[i] = NULL;
788   cinfo->col_expr.col_expr_val[i] = NULL;
789
790   for (i = 0; i < cinfo->num_cols; i++) {
791     int j;
792
793     for (j = 0; j < NUM_COL_FMTS; j++) {
794       if (!cinfo->fmt_matx[i][j])
795           continue;
796
797       if (cinfo->col_first[j] == -1)
798         cinfo->col_first[j] = i;
799
800       cinfo->col_last[j] = i;
801     }
802   }
803 }
804