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