various string related changes, mainly replace sprintf/snprintf by g_snprintf
[obnox/wireshark/wip.git] / column.c
1 /* column.c
2  * Routines for handling column preferences
3  *
4  * $Id: column.c,v 1.46 2004/01/31 04:10:04 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", "%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         "Cumulative 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 == TS_ABSOLUTE)
216         return "00:00:00.000000";
217       else if (timestamp_type == TS_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 "Protocol";        /* not the longest, but the longest is too long */
262       break;
263     case COL_PACKET_LENGTH:
264       return "000000";
265       break;
266     case COL_CUMULATIVE_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 #define TIME_DEF      0
301 #define TIME_REL      1
302 #define TIME_ABS      2
303 #define DATE_TIME_ABS 3
304 #define TIME_DEL      4
305
306 #define RES_DEF  0
307 #define RES_DO   1
308 #define RES_DONT 2
309
310 #define ADDR_DEF 0
311 #define ADDR_DL  3
312 #define ADDR_NET 6
313
314 gint
315 get_column_format(gint col) {
316   GList    *clp = g_list_nth(prefs.col_list, col);
317   fmt_data *cfmt;
318
319   cfmt = (fmt_data *) clp->data;
320
321   return(get_column_format_from_str(cfmt->fmt));
322 }
323
324 gint
325 get_column_format_from_str(gchar *str) {
326   gchar *cptr = str;
327   gint      res_off = RES_DEF, addr_off = ADDR_DEF, time_off = TIME_DEF;
328   gint      prev_code = -1;
329
330   /* To do: Make this parse %-formatted strings "for real" */
331   while (*cptr != '\0') {
332     switch (*cptr) {
333       case 't':  /* To do: fix for absolute and delta */
334         return COL_CLS_TIME + time_off;
335         break;
336       case 'm':
337         return COL_NUMBER;
338         break;
339       case 's':
340         if (prev_code == COL_OXID) {
341           return COL_SRCIDX;
342         }
343         else {
344           return COL_DEF_SRC + res_off + addr_off;
345         }
346         break;
347       case 'd':
348         if (prev_code == COL_OXID) {
349           return COL_DSTIDX;
350         }
351         else {
352           return COL_DEF_DST + res_off + addr_off;
353         }
354         break;
355       case 'S':
356         return COL_DEF_SRC_PORT + res_off;
357         break;
358       case 'D':
359         return COL_DEF_DST_PORT + res_off;
360         break;
361       case 'p':
362         return COL_PROTOCOL;
363         break;
364       case 'i':
365         return COL_INFO;
366         break;
367       case 'r':
368         res_off = RES_DO;
369         break;
370       case 'u':
371         res_off = RES_DONT;
372         break;
373       case 'h':
374         addr_off = ADDR_DL;
375         break;
376       case 'n':
377         addr_off = ADDR_NET;
378         break;
379       case 'R':
380         if (prev_code == COL_OXID) {
381             return COL_RXID;
382         }
383         else {
384             time_off = TIME_REL;
385         }
386         break;
387       case 'A':
388         time_off = TIME_ABS;
389         break;
390       case 'Y':
391         time_off = DATE_TIME_ABS;
392         break;
393       case 'T':
394         time_off = TIME_DEL;
395         break;
396       case 'L':
397         return COL_PACKET_LENGTH;
398         break;
399       case 'B':
400         return COL_CUMULATIVE_BYTES;
401         break;
402       case 'X':
403         prev_code = COL_OXID;
404         break;
405       case 'O':
406         return COL_OXID;
407         break;
408       case 'I':
409         return COL_IF_DIR;
410         break;
411       case 'c':
412         return COL_CIRCUIT_ID;
413         break;
414       case 'V':
415         return COL_VSAN;
416         break;
417     }
418     cptr++;
419   }
420   return -1;    /* illegal */
421 }
422
423 gchar *
424 get_column_title(gint col) {
425   GList    *clp = g_list_nth(prefs.col_list, col);
426   fmt_data *cfmt;
427
428   cfmt = (fmt_data *) clp->data;
429
430   return(cfmt->title);
431 }