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