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