Handle the case of an empty interface list on Windows the same way we
[obnox/wireshark/wip.git] / column.c
1 /* column.c
2  * Routines for handling column preferences
3  *
4  * $Id: column.c,v 1.42 2003/01/27 20:45:42 guy Exp $
5  *
6  * Ethereal - Network traffic analyzer
7  * By Gerald Combs <gerald@ethereal.com>
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 #ifdef HAVE_SYS_STAT_H
39 #include <sys/stat.h>
40 #endif
41
42 #include <epan/timestamp.h>
43 #include "prefs.h"
44 #include "column.h"
45 #include <epan/packet.h>
46
47 /* Given a format number (as defined in packet.h), returns its equivalent
48    string */
49 gchar *
50 col_format_to_string(gint fmt) {
51   gchar *slist[] = { "%m", "%t", "%Rt", "%At", "%Yt", "%Tt", "%s", "%rs",
52                      "%us","%hs", "%rhs", "%uhs", "%ns", "%rns", "%uns", "%d",
53                      "%rd", "%ud", "%hd", "%rhd", "%uhd", "%nd", "%rnd",
54                      "%und", "%S", "%rS", "%uS", "%D", "%rD", "%uD", "%p",
55                      "%i", "%L", "%XO", "%XR", "%I", "%c", "%Xs", "%Xd", "%V" };
56                      
57   if (fmt < 0 || fmt > NUM_COL_FMTS)
58     return NULL;
59
60   return(slist[fmt]);
61 }
62
63 /* Given a format number (as defined in packet.h), returns its
64   description */
65 static gchar *dlist[NUM_COL_FMTS] = {
66         "Number",
67         "Time (command line specified)",
68         "Relative time",
69         "Absolute time",
70         "Absolute date and time",
71         "Delta time",
72         "Source address",
73         "Src addr (resolved)",
74         "Src addr (unresolved)",
75         "Hardware src addr",
76         "Hw src addr (resolved)",
77         "Hw src addr (unresolved)",
78         "Network src addr",
79         "Net src addr (resolved)",
80         "Net src addr (unresolved)",
81         "Destination address",
82         "Dest addr (resolved)",
83         "Dest addr (unresolved)",
84         "Hardware dest addr",
85         "Hw dest addr (resolved)",
86         "Hw dest addr (unresolved)",
87         "Network dest addr",
88         "Net dest addr (resolved)",
89         "Net dest addr (unresolved)",
90         "Source port",
91         "Src port (resolved)",
92         "Src port (unresolved)",
93         "Destination port",
94         "Dest port (resolved)",
95         "Dest port (unresolved)",
96         "Protocol",
97         "Information",
98         "Packet length (bytes)" ,
99         "OXID",
100         "RXID",
101         "FW-1 monitor if/direction",
102         "Circuit ID",
103         "Src PortIdx",
104         "Dst PortIdx",
105         "VSAN",
106 };
107
108 gchar *
109 col_format_desc(gint fmt) {
110   g_assert((fmt >= 0) && (fmt < NUM_COL_FMTS));
111   return(dlist[fmt]);
112 }
113
114 /* Marks each array element true if it can be substituted for the given
115    column format */
116 void
117 get_column_format_matches(gboolean *fmt_list, gint format) {
118
119   /* Get the obvious: the format itself */
120   if ((format >= 0) && (format < NUM_COL_FMTS))
121     fmt_list[format] = TRUE;
122
123   /* Get any formats lower down on the chain */
124   switch (format) {
125     case COL_DEF_SRC:
126       fmt_list[COL_RES_DL_SRC] = TRUE;
127       fmt_list[COL_RES_NET_SRC] = TRUE;
128       break;
129     case COL_RES_SRC:
130       fmt_list[COL_RES_DL_SRC] = TRUE;
131       fmt_list[COL_RES_NET_SRC] = TRUE;
132       break;
133     case COL_UNRES_SRC:
134       fmt_list[COL_UNRES_DL_SRC] = TRUE;
135       fmt_list[COL_UNRES_NET_SRC] = TRUE;
136       break;
137     case COL_DEF_DST:
138       fmt_list[COL_RES_DL_DST] = TRUE;
139       fmt_list[COL_RES_NET_DST] = TRUE;
140       break;
141     case COL_RES_DST:
142       fmt_list[COL_RES_DL_DST] = TRUE;
143       fmt_list[COL_RES_NET_DST] = TRUE;
144       break;
145     case COL_UNRES_DST:
146       fmt_list[COL_UNRES_DL_DST] = TRUE;
147       fmt_list[COL_UNRES_NET_DST] = TRUE;
148       break;
149     case COL_DEF_DL_SRC:
150       fmt_list[COL_RES_DL_SRC] = TRUE;
151       break;
152     case COL_DEF_DL_DST:
153       fmt_list[COL_RES_DL_DST] = TRUE;
154       break;
155     case COL_DEF_NET_SRC:
156       fmt_list[COL_RES_NET_SRC] = TRUE;
157       break;
158     case COL_DEF_NET_DST:
159       fmt_list[COL_RES_NET_DST] = TRUE;
160       break;
161     case COL_DEF_SRC_PORT:
162       fmt_list[COL_RES_SRC_PORT] = TRUE;
163       break;
164     case COL_DEF_DST_PORT:
165       fmt_list[COL_RES_DST_PORT] = TRUE;
166       break;
167     case COL_OXID:
168       fmt_list[COL_OXID] = TRUE;
169       break;
170     case COL_RXID:
171       fmt_list[COL_RXID] = TRUE;
172       break;
173     case COL_IF_DIR:
174       fmt_list[COL_IF_DIR] = TRUE;
175       break;
176     case COL_CIRCUIT_ID:
177       fmt_list[COL_CIRCUIT_ID] = TRUE;
178       break;
179     case COL_SRCIDX:
180       fmt_list[COL_SRCIDX] = TRUE;
181       break;
182     case COL_DSTIDX:
183       fmt_list[COL_DSTIDX] = TRUE;
184       break;
185     case COL_VSAN:
186       fmt_list[COL_VSAN] = TRUE;
187       break;
188     default:
189       break;
190   }
191 }
192
193 /* Returns a string representing the longest possible value for a
194    particular column type.
195
196    Except for the COL...SRC and COL...DST columns, these are used
197    only when a capture is being displayed while it's taking place;
198    they are arguably somewhat fragile, as changes to the code that
199    generates them don't cause these widths to change, but that's
200    probably not too big a problem, given that the sizes are
201    recomputed based on the actual data in the columns when the capture
202    is done, and given that the width for COL...SRC and COL...DST columns
203    is somewhat arbitrary in any case.  We should probably clean
204    that up eventually, though. */
205 char *
206 get_column_longest_string(gint format)
207 {
208   switch (format) {
209     case COL_NUMBER:
210       return "0000000";
211       break;
212     case COL_CLS_TIME:
213       if (timestamp_type == ABSOLUTE)
214         return "00:00:00.000000";
215       else if (timestamp_type == ABSOLUTE_WITH_DATE)
216         return "0000-00-00 00:00:00.000000";
217       else
218         return "0000.000000";
219       break;
220     case COL_ABS_TIME:
221       return "00:00:00.000000";
222       break;
223     case COL_ABS_DATE_TIME:
224       return "0000-00-00 00:00:00.000000";
225       break;
226     case COL_REL_TIME:
227     case COL_DELTA_TIME:
228       return "0000.000000";
229       break;
230     case COL_DEF_SRC:
231     case COL_RES_SRC:
232     case COL_UNRES_SRC:
233     case COL_DEF_DL_SRC:
234     case COL_RES_DL_SRC:
235     case COL_UNRES_DL_SRC:
236     case COL_DEF_NET_SRC:
237     case COL_RES_NET_SRC:
238     case COL_UNRES_NET_SRC:
239     case COL_DEF_DST:
240     case COL_RES_DST:
241     case COL_UNRES_DST:
242     case COL_DEF_DL_DST:
243     case COL_RES_DL_DST:
244     case COL_UNRES_DL_DST:
245     case COL_DEF_NET_DST:
246     case COL_RES_NET_DST:
247     case COL_UNRES_NET_DST:
248       return "00000000.000000000000"; /* IPX-style */
249       break;
250     case COL_DEF_SRC_PORT:
251     case COL_RES_SRC_PORT:
252     case COL_UNRES_SRC_PORT:
253     case COL_DEF_DST_PORT:
254     case COL_RES_DST_PORT:
255     case COL_UNRES_DST_PORT:
256       return "000000";
257       break;
258     case COL_PROTOCOL:
259       return "NetBIOS"; /* not the longest, but the longest is too long */
260       break;
261     case COL_PACKET_LENGTH:
262       return "000000";
263       break;
264     case COL_RXID:
265     case COL_OXID:
266       return "000000";
267       break;
268     case COL_IF_DIR:
269       return "i 00000000 I";
270       break;
271     case COL_CIRCUIT_ID:
272       return "000000";
273       break;
274     case COL_SRCIDX:
275     case COL_DSTIDX:
276       return "0000000";
277       break;
278     case COL_VSAN:
279       return "000000";
280       break;
281     default: /* COL_INFO */
282       return "Source port: kerberos-master  Destination port: kerberos-master";
283       break;
284   }
285 }
286
287 /* Returns the longest possible width, in characters, for a particular
288    column type. */
289 gint
290 get_column_char_width(gint format)
291 {
292   return strlen(get_column_longest_string(format));
293 }
294
295 enum col_resize_type
296 get_column_resize_type(gint format) {
297   switch (format) {
298     case COL_NUMBER:
299     case COL_CLS_TIME:
300     case COL_ABS_TIME:
301     case COL_ABS_DATE_TIME:
302     case COL_REL_TIME:
303     case COL_DELTA_TIME:
304     case COL_DEF_SRC_PORT:
305     case COL_RES_SRC_PORT:
306     case COL_UNRES_SRC_PORT:
307     case COL_DEF_DST_PORT:
308     case COL_RES_DST_PORT:
309     case COL_UNRES_DST_PORT:
310     case COL_PROTOCOL:
311     case COL_PACKET_LENGTH:
312     case COL_IF_DIR:
313     case COL_CIRCUIT_ID:
314       /* We don't want these to resize during a live capture, as that
315          gets in the way of trying to look at the data while it's being
316          captured. */
317       return (RESIZE_AUTO);
318       break;
319     case COL_DEF_SRC:
320     case COL_RES_SRC:
321     case COL_UNRES_SRC:
322     case COL_DEF_DL_SRC:
323     case COL_RES_DL_SRC:
324     case COL_UNRES_DL_SRC:
325     case COL_DEF_NET_SRC:
326     case COL_RES_NET_SRC:
327     case COL_UNRES_NET_SRC:
328     case COL_DEF_DST:
329     case COL_RES_DST:
330     case COL_UNRES_DST:
331     case COL_DEF_DL_DST:
332     case COL_RES_DL_DST:
333     case COL_UNRES_DL_DST:
334     case COL_DEF_NET_DST:
335     case COL_RES_NET_DST:
336     case COL_UNRES_NET_DST:
337     case COL_OXID:
338     case COL_RXID:
339     case COL_SRCIDX:
340     case COL_DSTIDX:
341     case COL_VSAN:
342       /* We don't want these to resize dynamically; if they get resolved
343          to names, those names could be very long, and auto-resizing
344          columns showing those names may leave too little room for
345          other columns such as the "Info" column. */
346       return (RESIZE_MANUAL);
347       break;
348     default: /* COL_INFO */
349       /* We want this to resize dynamically, even during a live capture,
350          because otherewise you won't be able to see all that's in
351          it. */
352       return (RESIZE_LIVE);
353       break;
354   }
355 }
356
357 #define TIME_DEF      0
358 #define TIME_REL      1
359 #define TIME_ABS      2
360 #define DATE_TIME_ABS 3
361 #define TIME_DEL      4
362
363 #define RES_DEF  0
364 #define RES_DO   1
365 #define RES_DONT 2
366
367 #define ADDR_DEF 0
368 #define ADDR_DL  3
369 #define ADDR_NET 6
370
371 gint
372 get_column_format(gint col) {
373   GList    *clp = g_list_nth(prefs.col_list, col);
374   fmt_data *cfmt;
375
376   cfmt = (fmt_data *) clp->data;
377
378   return(get_column_format_from_str(cfmt->fmt));
379 }
380
381 gint
382 get_column_format_from_str(gchar *str) {
383   gchar *cptr = str;
384   gint      res_off = RES_DEF, addr_off = ADDR_DEF, time_off = TIME_DEF;
385   gint      prev_code = -1;
386
387   /* To do: Make this parse %-formatted strings "for real" */
388   while (*cptr != '\0') {
389     switch (*cptr) {
390       case 't':  /* To do: fix for absolute and delta */
391         return COL_CLS_TIME + time_off;
392         break;
393       case 'm':
394         return COL_NUMBER;
395         break;
396       case 's':
397         if (prev_code == COL_OXID) {
398           return COL_SRCIDX;
399         }
400         else {
401           return COL_DEF_SRC + res_off + addr_off;
402         }
403         break;
404       case 'd':
405         if (prev_code == COL_OXID) {
406           return COL_DSTIDX;
407         }
408         else {
409           return COL_DEF_DST + res_off + addr_off;
410         }
411         break;
412       case 'S':
413         return COL_DEF_SRC_PORT + res_off;
414         break;
415       case 'D':
416         return COL_DEF_DST_PORT + res_off;
417         break;
418       case 'p':
419         return COL_PROTOCOL;
420         break;
421       case 'i':
422         return COL_INFO;
423         break;
424       case 'r':
425         res_off = RES_DO;
426         break;
427       case 'u':
428         res_off = RES_DONT;
429         break;
430       case 'h':
431         addr_off = ADDR_DL;
432         break;
433       case 'n':
434         addr_off = ADDR_NET;
435         break;
436       case 'R':
437         if (prev_code == COL_OXID) {
438             return COL_RXID;
439         }
440         else {
441             time_off = TIME_REL;
442         }
443         break;
444       case 'A':
445         time_off = TIME_ABS;
446         break;
447       case 'Y':
448         time_off = DATE_TIME_ABS;
449         break;
450       case 'T':
451         time_off = TIME_DEL;
452         break;
453       case 'L':
454         return COL_PACKET_LENGTH;
455         break;
456       case 'X':
457         prev_code = COL_OXID;
458         break;
459       case 'O':
460         return COL_OXID;
461         break;
462       case 'I':
463         return COL_IF_DIR;
464         break;
465       case 'c':
466         return COL_CIRCUIT_ID;
467         break;
468       case 'V':
469         return COL_VSAN;
470         break;
471     }
472     cptr++;
473   }
474   return -1;    /* illegal */
475 }
476
477 gchar *
478 get_column_title(gint col) {
479   GList    *clp = g_list_nth(prefs.col_list, col);
480   fmt_data *cfmt;
481
482   cfmt = (fmt_data *) clp->data;
483
484   return(cfmt->title);
485 }