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