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