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