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