packet-ldap: fix regression for SASL handling
[wireshark-sm.git] / epan / column.c
blob922f03daeae98b08dad262d745300bd7bf940e77
1 /* column.c
2 * Routines for handling column preferences
4 * Wireshark - Network traffic analyzer
5 * By Gerald Combs <gerald@wireshark.org>
6 * Copyright 1998 Gerald Combs
8 * SPDX-License-Identifier: GPL-2.0-or-later
9 */
11 #include "config.h"
13 #include <stdio.h>
14 #include <string.h>
15 #include <errno.h>
17 #ifdef HAVE_UNISTD_H
18 #include <unistd.h>
19 #endif
21 #include <epan/timestamp.h>
22 #include <epan/prefs.h>
23 #include <epan/dfilter/dfilter.h>
24 #include <epan/column.h>
25 #include <epan/packet.h>
26 #include <wsutil/ws_printf.h> /* ws_debug_printf */
28 /* Given a format number (as defined in column-utils.h), returns its equivalent
29 string */
30 const gchar *
31 col_format_to_string(const gint fmt) {
32 static const gchar *const slist[NUM_COL_FMTS] = {
33 "%q", /* 0) COL_8021Q_VLAN_ID */
34 "%Yt", /* 1) COL_ABS_YMD_TIME */
35 "%YDOYt", /* 2) COL_ABS_YDOY_TIME */
36 "%At", /* 3) COL_ABS_TIME */
37 "%V", /* 4) COL_VSAN - !! DEPRECATED !!*/
38 "%B", /* 5) COL_CUMULATIVE_BYTES */
39 "%Cus", /* 6) COL_CUSTOM */
40 "%y", /* 7) COL_DCE_CALL */
41 "%Tt", /* 8) COL_DELTA_TIME */
42 "%Gt", /* 9) COL_DELTA_TIME_DIS */
43 "%rd", /* 10) COL_RES_DST */
44 "%ud", /* 11) COL_UNRES_DST */
45 "%rD", /* 12) COL_RES_DST_PORT */
46 "%uD", /* 13) COL_UNRES_DST_PORT */
47 "%d", /* 14) COL_DEF_DST */
48 "%D", /* 15) COL_DEF_DST_PORT */
49 "%a", /* 16) COL_EXPERT */
50 "%I", /* 17) COL_IF_DIR */
51 "%F", /* 18) COL_FREQ_CHAN */
52 "%hd", /* 19) COL_DEF_DL_DST */
53 "%hs", /* 20) COL_DEF_DL_SRC */
54 "%rhd", /* 21) COL_RES_DL_DST */
55 "%uhd", /* 22) COL_UNRES_DL_DST */
56 "%rhs", /* 23) COL_RES_DL_SRC*/
57 "%uhs", /* 24) COL_UNRES_DL_SRC */
58 "%e", /* 25) COL_RSSI */
59 "%x", /* 26) COL_TX_RATE */
60 "%f", /* 27) COL_DSCP_VALUE */
61 "%i", /* 28) COL_INFO */
62 "%rnd", /* 29) COL_RES_NET_DST */
63 "%und", /* 30) COL_UNRES_NET_DST */
64 "%rns", /* 31) COL_RES_NET_SRC */
65 "%uns", /* 32) COL_UNRES_NET_SRC */
66 "%nd", /* 33) COL_DEF_NET_DST */
67 "%ns", /* 34) COL_DEF_NET_SRC */
68 "%m", /* 35) COL_NUMBER */
69 "%L", /* 36) COL_PACKET_LENGTH */
70 "%p", /* 37) COL_PROTOCOL */
71 "%Rt", /* 38) COL_REL_TIME */
72 "%s", /* 39) COL_DEF_SRC */
73 "%S", /* 40) COL_DEF_SRC_PORT */
74 "%rs", /* 41) COL_RES_SRC */
75 "%us", /* 42) COL_UNRES_SRC */
76 "%rS", /* 43) COL_RES_SRC_PORT */
77 "%uS", /* 44) COL_UNRES_SRC_PORT */
78 "%E", /* 45) COL_TEI */
79 "%Yut", /* 46) COL_UTC_YMD_TIME */
80 "%YDOYut", /* 47) COL_UTC_YDOY_TIME */
81 "%Aut", /* 48) COL_UTC_TIME */
82 "%t" /* 49) COL_CLS_TIME */
85 /* The following formats have been used in deprecated columns. Noted here
86 * so they aren't reused
88 * "%U", COL_COS_VALUE
89 * "%c", COL_CIRCUIT_ID
90 * "%l", COL_BSSGP_TLLI
91 * "%H", COL_HPUX_SUBSYS
92 * "%P", COL_HPUX_DEVID
93 * "%C", COL_FR_DLCI
94 * "%rct", COL_REL_CONV_TIME
95 * "%dct", COL_DELTA_CONV_TIME
96 * "%XO", COL_OXID
97 * "%XR", COL_RXID
98 * "%Xd", COL_SRCIDX
99 * "%Xs", COL_DSTIDX
100 * "%z", COL_DCE_CTX
102 if (fmt < 0 || fmt >= NUM_COL_FMTS)
103 return NULL;
105 return(slist[fmt]);
108 /* Given a format number (as defined in column-utils.h), returns its
109 description */
110 const gchar *
111 col_format_desc(const gint fmt_num) {
113 /* This should be sorted alphabetically, e.g. `sort -t, -k2` */
115 * This is currently used in the preferences UI, so out-of-numeric-order
116 * performance shouldn't be an issue.
118 static const value_string dlist_vals[] = {
120 { COL_8021Q_VLAN_ID, "802.1Q VLAN id" },
121 { COL_ABS_YMD_TIME, "Absolute date, as YYYY-MM-DD, and time" },
122 { COL_ABS_YDOY_TIME, "Absolute date, as YYYY/DOY, and time" },
123 { COL_ABS_TIME, "Absolute time" },
124 { COL_VSAN, "Cisco VSAN" },
125 { COL_CUMULATIVE_BYTES, "Cumulative Bytes" },
126 { COL_CUSTOM, "Custom" },
127 { COL_DCE_CALL, "DCE/RPC call (cn_call_id / dg_seqnum)" },
128 { COL_DELTA_TIME_DIS, "Delta time displayed" },
129 { COL_DELTA_TIME, "Delta time" },
130 { COL_RES_DST, "Dest addr (resolved)" },
131 { COL_UNRES_DST, "Dest addr (unresolved)" },
132 { COL_RES_DST_PORT, "Dest port (resolved)" },
133 { COL_UNRES_DST_PORT, "Dest port (unresolved)" },
134 { COL_DEF_DST, "Destination address" },
135 { COL_DEF_DST_PORT, "Destination port" },
136 { COL_EXPERT, "Expert Info Severity" },
137 { COL_IF_DIR, "FW-1 monitor if/direction" },
138 { COL_FREQ_CHAN, "Frequency/Channel" },
139 { COL_DEF_DL_DST, "Hardware dest addr" },
140 { COL_DEF_DL_SRC, "Hardware src addr" },
141 { COL_RES_DL_DST, "Hw dest addr (resolved)" },
142 { COL_UNRES_DL_DST, "Hw dest addr (unresolved)" },
143 { COL_RES_DL_SRC, "Hw src addr (resolved)" },
144 { COL_UNRES_DL_SRC, "Hw src addr (unresolved)" },
145 { COL_RSSI, "IEEE 802.11 RSSI" },
146 { COL_TX_RATE, "IEEE 802.11 TX rate" },
147 { COL_DSCP_VALUE, "IP DSCP Value" },
148 { COL_INFO, "Information" },
149 { COL_RES_NET_DST, "Net dest addr (resolved)" },
150 { COL_UNRES_NET_DST, "Net dest addr (unresolved)" },
151 { COL_RES_NET_SRC, "Net src addr (resolved)" },
152 { COL_UNRES_NET_SRC, "Net src addr (unresolved)" },
153 { COL_DEF_NET_DST, "Network dest addr" },
154 { COL_DEF_NET_SRC, "Network src addr" },
155 { COL_NUMBER, "Number" },
156 { COL_PACKET_LENGTH, "Packet length (bytes)" },
157 { COL_PROTOCOL, "Protocol" },
158 { COL_REL_TIME, "Relative time" },
159 { COL_DEF_SRC, "Source address" },
160 { COL_DEF_SRC_PORT, "Source port" },
161 { COL_RES_SRC, "Src addr (resolved)" },
162 { COL_UNRES_SRC, "Src addr (unresolved)" },
163 { COL_RES_SRC_PORT, "Src port (resolved)" },
164 { COL_UNRES_SRC_PORT, "Src port (unresolved)" },
165 { COL_TEI, "TEI" },
166 { COL_CLS_TIME, "Time (format as specified)" },
167 { COL_UTC_YMD_TIME, "UTC date, as YYYY-MM-DD, and time" },
168 { COL_UTC_YDOY_TIME, "UTC date, as YYYY/DOY, and time" },
169 { COL_UTC_TIME, "UTC time" },
171 { 0, NULL }
174 const gchar *val_str = try_val_to_str(fmt_num, dlist_vals);
175 g_assert(val_str != NULL);
176 return val_str;
179 void
180 column_dump_column_formats(void)
182 gint fmt;
184 for (fmt = 0; fmt < NUM_COL_FMTS; fmt++) {
185 ws_debug_printf("%s\t%s\n", col_format_to_string(fmt), col_format_desc(fmt));
188 ws_debug_printf("\nFor example, to print Wireshark's default columns with tshark:\n\n"
189 #ifdef _WIN32
190 "tshark.exe -o \"gui.column.format:"
191 "\\\"No.\\\",\\\"%%m\\\","
192 "\\\"Time\\\",\\\"%%t\\\","
193 "\\\"Source\\\",\\\"%%s\\\","
194 "\\\"Destination\\\",\\\"%%d\\\","
195 "\\\"Protocol\\\",\\\"%%p\\\","
196 "\\\"Length\\\",\\\"%%L\\\","
197 "\\\"Info\\\",\\\"%%i\\\"\"\n");
198 #else
199 "tshark -o 'gui.column.format:"
200 "\"No.\",\"%%m\","
201 "\"Time\",\"%%t\","
202 "\"Source\",\"%%s\","
203 "\"Destination\",\"%%d\","
204 "\"Protocol\",\"%%p\","
205 "\"Length\",\"%%L\","
206 "\"Info\",\"%%i\"'\n");
207 #endif
210 /* Marks each array element true if it can be substituted for the given
211 column format */
212 void
213 get_column_format_matches(gboolean *fmt_list, const gint format) {
215 /* Get the obvious: the format itself */
216 if ((format >= 0) && (format < NUM_COL_FMTS))
217 fmt_list[format] = TRUE;
219 /* Get any formats lower down on the chain */
220 switch (format) {
221 case COL_DEF_SRC:
222 fmt_list[COL_RES_DL_SRC] = TRUE;
223 fmt_list[COL_RES_NET_SRC] = TRUE;
224 break;
225 case COL_RES_SRC:
226 fmt_list[COL_RES_DL_SRC] = TRUE;
227 fmt_list[COL_RES_NET_SRC] = TRUE;
228 break;
229 case COL_UNRES_SRC:
230 fmt_list[COL_UNRES_DL_SRC] = TRUE;
231 fmt_list[COL_UNRES_NET_SRC] = TRUE;
232 break;
233 case COL_DEF_DST:
234 fmt_list[COL_RES_DL_DST] = TRUE;
235 fmt_list[COL_RES_NET_DST] = TRUE;
236 break;
237 case COL_RES_DST:
238 fmt_list[COL_RES_DL_DST] = TRUE;
239 fmt_list[COL_RES_NET_DST] = TRUE;
240 break;
241 case COL_UNRES_DST:
242 fmt_list[COL_UNRES_DL_DST] = TRUE;
243 fmt_list[COL_UNRES_NET_DST] = TRUE;
244 break;
245 case COL_DEF_DL_SRC:
246 fmt_list[COL_RES_DL_SRC] = TRUE;
247 break;
248 case COL_DEF_DL_DST:
249 fmt_list[COL_RES_DL_DST] = TRUE;
250 break;
251 case COL_DEF_NET_SRC:
252 fmt_list[COL_RES_NET_SRC] = TRUE;
253 break;
254 case COL_DEF_NET_DST:
255 fmt_list[COL_RES_NET_DST] = TRUE;
256 break;
257 case COL_DEF_SRC_PORT:
258 fmt_list[COL_RES_SRC_PORT] = TRUE;
259 break;
260 case COL_DEF_DST_PORT:
261 fmt_list[COL_RES_DST_PORT] = TRUE;
262 break;
263 default:
264 break;
268 /* Returns a string representing the longest possible value for
269 a timestamp column type. */
270 static const char *
271 get_timestamp_column_longest_string(const gint type, const gint precision)
274 switch(type) {
275 case(TS_ABSOLUTE_WITH_YMD):
276 case(TS_UTC_WITH_YMD):
277 switch(precision) {
278 case(TS_PREC_FIXED_SEC):
279 return "0000-00-00 00:00:00";
280 break;
281 case(TS_PREC_FIXED_DSEC):
282 return "0000-00-00 00:00:00.0";
283 break;
284 case(TS_PREC_FIXED_CSEC):
285 return "0000-00-00 00:00:00.00";
286 break;
287 case(TS_PREC_FIXED_MSEC):
288 return "0000-00-00 00:00:00.000";
289 break;
290 case(TS_PREC_FIXED_USEC):
291 return "0000-00-00 00:00:00.000000";
292 break;
293 case(TS_PREC_FIXED_NSEC):
294 case(TS_PREC_AUTO): /* Leave enough room for the maximum */
295 return "0000-00-00 00:00:00.000000000";
296 break;
297 default:
298 g_assert_not_reached();
300 break;
301 case(TS_ABSOLUTE_WITH_YDOY):
302 case(TS_UTC_WITH_YDOY):
303 switch(precision) {
304 case(TS_PREC_FIXED_SEC):
305 return "0000/000 00:00:00";
306 break;
307 case(TS_PREC_FIXED_DSEC):
308 return "0000/000 00:00:00.0";
309 break;
310 case(TS_PREC_FIXED_CSEC):
311 return "0000/000 00:00:00.00";
312 break;
313 case(TS_PREC_FIXED_MSEC):
314 return "0000/000 00:00:00.000";
315 break;
316 case(TS_PREC_FIXED_USEC):
317 return "0000/000 00:00:00.000000";
318 break;
319 case(TS_PREC_FIXED_NSEC):
320 case(TS_PREC_AUTO): /* Leave enough room for the maximum */
321 return "0000/000 00:00:00.000000000";
322 break;
323 default:
324 g_assert_not_reached();
326 break;
327 case(TS_ABSOLUTE):
328 case(TS_UTC):
329 switch(precision) {
330 case(TS_PREC_FIXED_SEC):
331 return "00:00:00";
332 break;
333 case(TS_PREC_FIXED_DSEC):
334 return "00:00:00.0";
335 break;
336 case(TS_PREC_FIXED_CSEC):
337 return "00:00:00.00";
338 break;
339 case(TS_PREC_FIXED_MSEC):
340 return "00:00:00.000";
341 break;
342 case(TS_PREC_FIXED_USEC):
343 return "00:00:00.000000";
344 break;
345 case(TS_PREC_FIXED_NSEC):
346 case(TS_PREC_AUTO): /* Leave enough room for the maximum */
347 return "00:00:00.000000000";
348 break;
349 default:
350 g_assert_not_reached();
352 break;
353 case(TS_RELATIVE): /* fallthrough */
354 case(TS_DELTA):
355 case(TS_DELTA_DIS):
356 switch(precision) {
357 case(TS_PREC_FIXED_SEC):
358 return "0000";
359 break;
360 case(TS_PREC_FIXED_DSEC):
361 return "0000.0";
362 break;
363 case(TS_PREC_FIXED_CSEC):
364 return "0000.00";
365 break;
366 case(TS_PREC_FIXED_MSEC):
367 return "0000.000";
368 break;
369 case(TS_PREC_FIXED_USEC):
370 return "0000.000000";
371 break;
372 case(TS_PREC_FIXED_NSEC):
373 case(TS_PREC_AUTO): /* Leave enough room for the maximum */
374 return "0000.000000000";
375 break;
376 default:
377 g_assert_not_reached();
379 break;
380 case(TS_EPOCH):
381 /* This is enough to represent 2^63 (signed 64-bit integer) + fractions */
382 switch(precision) {
383 case(TS_PREC_FIXED_SEC):
384 return "0000000000000000000";
385 break;
386 case(TS_PREC_FIXED_DSEC):
387 return "0000000000000000000.0";
388 break;
389 case(TS_PREC_FIXED_CSEC):
390 return "0000000000000000000.00";
391 break;
392 case(TS_PREC_FIXED_MSEC):
393 return "0000000000000000000.000";
394 break;
395 case(TS_PREC_FIXED_USEC):
396 return "0000000000000000000.000000";
397 break;
398 case(TS_PREC_FIXED_NSEC):
399 case(TS_PREC_AUTO): /* Leave enough room for the maximum */
400 return "0000000000000000000.000000000";
401 break;
402 default:
403 g_assert_not_reached();
405 break;
406 case(TS_NOT_SET):
407 return "0000.000000";
408 break;
409 default:
410 g_assert_not_reached();
413 /* never reached, satisfy compiler */
414 return "";
417 /* Returns a string representing the longest possible value for a
418 particular column type. See also get_column_width_string() above.
420 Except for the COL...SRC and COL...DST columns, these are used
421 only when a capture is being displayed while it's taking place;
422 they are arguably somewhat fragile, as changes to the code that
423 generates them don't cause these widths to change, but that's
424 probably not too big a problem, given that the sizes are
425 recomputed based on the actual data in the columns when the capture
426 is done, and given that the width for COL...SRC and COL...DST columns
427 is somewhat arbitrary in any case. We should probably clean
428 that up eventually, though. */
429 static const char *
430 get_column_longest_string(const gint format)
432 switch (format) {
433 case COL_NUMBER:
434 return "0000000";
435 break;
436 case COL_CLS_TIME:
437 return get_timestamp_column_longest_string(timestamp_get_type(), timestamp_get_precision());
438 break;
439 case COL_ABS_YMD_TIME:
440 return get_timestamp_column_longest_string(TS_ABSOLUTE_WITH_YMD, timestamp_get_precision());
441 break;
442 case COL_ABS_YDOY_TIME:
443 return get_timestamp_column_longest_string(TS_ABSOLUTE_WITH_YDOY, timestamp_get_precision());
444 break;
445 case COL_UTC_YMD_TIME:
446 return get_timestamp_column_longest_string(TS_UTC_WITH_YMD, timestamp_get_precision());
447 break;
448 case COL_UTC_YDOY_TIME:
449 return get_timestamp_column_longest_string(TS_UTC_WITH_YDOY, timestamp_get_precision());
450 break;
451 case COL_ABS_TIME:
452 return get_timestamp_column_longest_string(TS_ABSOLUTE, timestamp_get_precision());
453 break;
454 case COL_UTC_TIME:
455 return get_timestamp_column_longest_string(TS_UTC, timestamp_get_precision());
456 break;
457 case COL_REL_TIME:
458 return get_timestamp_column_longest_string(TS_RELATIVE, timestamp_get_precision());
459 break;
460 case COL_DELTA_TIME:
461 return get_timestamp_column_longest_string(TS_DELTA, timestamp_get_precision());
462 break;
463 case COL_DELTA_TIME_DIS:
464 return get_timestamp_column_longest_string(TS_DELTA_DIS, timestamp_get_precision());
465 break;
466 case COL_DEF_SRC:
467 case COL_RES_SRC:
468 case COL_UNRES_SRC:
469 case COL_DEF_DL_SRC:
470 case COL_RES_DL_SRC:
471 case COL_UNRES_DL_SRC:
472 case COL_DEF_NET_SRC:
473 case COL_RES_NET_SRC:
474 case COL_UNRES_NET_SRC:
475 case COL_DEF_DST:
476 case COL_RES_DST:
477 case COL_UNRES_DST:
478 case COL_DEF_DL_DST:
479 case COL_RES_DL_DST:
480 case COL_UNRES_DL_DST:
481 case COL_DEF_NET_DST:
482 case COL_RES_NET_DST:
483 case COL_UNRES_NET_DST:
484 return "00000000.000000000000"; /* IPX-style */
485 break;
486 case COL_DEF_SRC_PORT:
487 case COL_RES_SRC_PORT:
488 case COL_UNRES_SRC_PORT:
489 case COL_DEF_DST_PORT:
490 case COL_RES_DST_PORT:
491 case COL_UNRES_DST_PORT:
492 return "000000";
493 break;
494 case COL_PROTOCOL:
495 return "Protocol"; /* not the longest, but the longest is too long */
496 break;
497 case COL_PACKET_LENGTH:
498 return "00000";
499 break;
500 case COL_CUMULATIVE_BYTES:
501 return "00000000";
502 break;
503 case COL_IF_DIR:
504 return "i 00000000 I";
505 break;
506 case COL_VSAN:
507 return "000000";
508 break;
509 case COL_TX_RATE:
510 return "108.0";
511 break;
512 case COL_RSSI:
513 return "100";
514 break;
515 case COL_DCE_CALL:
516 return "0000";
517 break;
518 case COL_8021Q_VLAN_ID:
519 return "0000";
520 break;
521 case COL_DSCP_VALUE:
522 return "AAA BBB"; /* not the longest, but the longest is too long */
523 break;
524 case COL_TEI:
525 return "127";
526 break;
527 case COL_EXPERT:
528 return "ERROR";
529 break;
530 case COL_FREQ_CHAN:
531 return "9999 MHz [A 999]";
532 break;
533 case COL_CUSTOM:
534 return "0000000000"; /* not the longest, but the longest is too long */
535 break;
536 default: /* COL_INFO */
537 return "Source port: kerberos-master Destination port: kerberos-master";
538 break;
542 /* Returns the longer string of the column title or the hard-coded width of
543 * its contents for building the packet list layout. */
544 const gchar *
545 get_column_width_string(const gint format, const gint col)
547 if(strlen(get_column_longest_string(format)) >
548 strlen(get_column_title(col)))
549 return get_column_longest_string(format);
550 else
551 return get_column_title(col);
554 /* Returns the longest possible width, in characters, for a particular
555 column type. */
556 gint
557 get_column_char_width(const gint format)
559 return (gint)strlen(get_column_longest_string(format));
562 gint
563 get_column_format(const gint col)
565 GList *clp = g_list_nth(prefs.col_list, col);
566 fmt_data *cfmt;
568 if (!clp) /* Invalid column requested */
569 return -1;
571 cfmt = (fmt_data *) clp->data;
573 return(cfmt->fmt);
576 void
577 set_column_format(const gint col, const gint fmt)
579 GList *clp = g_list_nth(prefs.col_list, col);
580 fmt_data *cfmt;
582 if (!clp) /* Invalid column requested */
583 return;
585 cfmt = (fmt_data *) clp->data;
587 cfmt->fmt = fmt;
590 gint
591 get_column_format_from_str(const gchar *str)
593 gint i;
595 for (i = 0; i < NUM_COL_FMTS; i++) {
596 if (strcmp(str, col_format_to_string(i)) == 0)
597 return i;
599 return -1; /* illegal */
602 gchar *
603 get_column_title(const gint col)
605 GList *clp = g_list_nth(prefs.col_list, col);
606 fmt_data *cfmt;
608 if (!clp) /* Invalid column requested */
609 return NULL;
611 cfmt = (fmt_data *) clp->data;
613 return(cfmt->title);
616 void
617 set_column_title(const gint col, const gchar *title)
619 GList *clp = g_list_nth(prefs.col_list, col);
620 fmt_data *cfmt;
622 if (!clp) /* Invalid column requested */
623 return;
625 cfmt = (fmt_data *) clp->data;
627 g_free (cfmt->title);
628 cfmt->title = g_strdup (title);
631 gboolean
632 get_column_visible(const gint col)
634 GList *clp = g_list_nth(prefs.col_list, col);
635 fmt_data *cfmt;
637 if (!clp) /* Invalid column requested */
638 return TRUE;
640 cfmt = (fmt_data *) clp->data;
642 return(cfmt->visible);
645 void
646 set_column_visible(const gint col, gboolean visible)
648 GList *clp = g_list_nth(prefs.col_list, col);
649 fmt_data *cfmt;
651 if (!clp) /* Invalid column requested */
652 return;
654 cfmt = (fmt_data *) clp->data;
656 cfmt->visible = visible;
659 gboolean
660 get_column_resolved(const gint col)
662 GList *clp = g_list_nth(prefs.col_list, col);
663 fmt_data *cfmt;
665 if (!clp) /* Invalid column requested */
666 return TRUE;
668 cfmt = (fmt_data *) clp->data;
670 return(cfmt->resolved);
673 void
674 set_column_resolved(const gint col, gboolean resolved)
676 GList *clp = g_list_nth(prefs.col_list, col);
677 fmt_data *cfmt;
679 if (!clp) /* Invalid column requested */
680 return;
682 cfmt = (fmt_data *) clp->data;
684 cfmt->resolved = resolved;
687 const gchar *
688 get_column_custom_fields(const gint col)
690 GList *clp = g_list_nth(prefs.col_list, col);
691 fmt_data *cfmt;
693 if (!clp) /* Invalid column requested */
694 return NULL;
696 cfmt = (fmt_data *) clp->data;
698 return(cfmt->custom_fields);
701 void
702 set_column_custom_fields(const gint col, const char *custom_fields)
704 GList *clp = g_list_nth(prefs.col_list, col);
705 fmt_data *cfmt;
707 if (!clp) /* Invalid column requested */
708 return;
710 cfmt = (fmt_data *) clp->data;
712 g_free (cfmt->custom_fields);
713 cfmt->custom_fields = g_strdup (custom_fields);
716 gint
717 get_column_custom_occurrence(const gint col)
719 GList *clp = g_list_nth(prefs.col_list, col);
720 fmt_data *cfmt;
722 if (!clp) /* Invalid column requested */
723 return 0;
725 cfmt = (fmt_data *) clp->data;
727 return(cfmt->custom_occurrence);
730 void
731 set_column_custom_occurrence(const gint col, const gint custom_occurrence)
733 GList *clp = g_list_nth(prefs.col_list, col);
734 fmt_data *cfmt;
736 if (!clp) /* Invalid column requested */
737 return;
739 cfmt = (fmt_data *) clp->data;
741 cfmt->custom_occurrence = custom_occurrence;
744 static gchar *
745 get_custom_field_tooltip (gchar *custom_field, gint occurrence)
747 header_field_info *hfi = proto_registrar_get_byname(custom_field);
748 if (hfi == NULL) {
749 /* Not a valid field */
750 return g_strdup_printf("Unknown Field: %s", custom_field);
753 if (hfi->parent == -1) {
754 /* Protocol */
755 return g_strdup_printf("%s (%s)", hfi->name, hfi->abbrev);
758 if (occurrence == 0) {
759 /* All occurrences */
760 return g_strdup_printf("%s\n%s (%s)", proto_get_protocol_name(hfi->parent), hfi->name, hfi->abbrev);
763 /* One given occurrence */
764 return g_strdup_printf("%s\n%s (%s#%d)", proto_get_protocol_name(hfi->parent), hfi->name, hfi->abbrev, occurrence);
767 gchar *
768 get_column_tooltip(const gint col)
770 GList *clp = g_list_nth(prefs.col_list, col);
771 fmt_data *cfmt;
772 gchar **fields;
773 gboolean first = TRUE;
774 GString *column_tooltip;
775 guint i;
777 if (!clp) /* Invalid column requested */
778 return NULL;
780 cfmt = (fmt_data *) clp->data;
782 if (cfmt->fmt != COL_CUSTOM) {
783 /* Use format description */
784 return g_strdup(col_format_desc(cfmt->fmt));
787 fields = g_regex_split_simple(COL_CUSTOM_PRIME_REGEX, cfmt->custom_fields,
788 (GRegexCompileFlags) (G_REGEX_ANCHORED | G_REGEX_RAW),
789 G_REGEX_MATCH_ANCHORED);
790 column_tooltip = g_string_new("");
792 for (i = 0; i < g_strv_length(fields); i++) {
793 if (fields[i] && *fields[i]) {
794 gchar *field_tooltip = get_custom_field_tooltip(fields[i], cfmt->custom_occurrence);
795 if (!first) {
796 g_string_append(column_tooltip, "\n\nOR\n\n");
798 g_string_append(column_tooltip, field_tooltip);
799 g_free (field_tooltip);
800 first = FALSE;
804 g_strfreev(fields);
806 return g_string_free (column_tooltip, FALSE);
809 void
810 col_finalize(column_info *cinfo)
812 int i;
813 col_item_t* col_item;
815 for (i = 0; i < cinfo->num_cols; i++) {
816 col_item = &cinfo->columns[i];
818 if (col_item->col_fmt == COL_CUSTOM) {
819 if(!dfilter_compile(col_item->col_custom_fields, &col_item->col_custom_dfilter, NULL)) {
820 /* XXX: Should we issue a warning? */
821 g_free(col_item->col_custom_fields);
822 col_item->col_custom_fields = NULL;
823 col_item->col_custom_occurrence = 0;
824 col_item->col_custom_dfilter = NULL;
826 if (col_item->col_custom_fields) {
827 gchar **fields = g_regex_split(cinfo->prime_regex, col_item->col_custom_fields,
828 G_REGEX_MATCH_ANCHORED);
829 guint i_field;
831 for (i_field = 0; i_field < g_strv_length(fields); i_field++) {
832 if (fields[i_field] && *fields[i_field]) {
833 header_field_info *hfinfo = proto_registrar_get_byname(fields[i_field]);
834 if (hfinfo) {
835 int *idx = g_new(int, 1);
836 *idx = hfinfo->id;
837 col_item->col_custom_fields_ids = g_slist_append(col_item->col_custom_fields_ids, idx);
841 g_strfreev(fields);
843 } else {
844 col_item->col_custom_fields = NULL;
845 col_item->col_custom_occurrence = 0;
846 col_item->col_custom_dfilter = NULL;
849 col_item->fmt_matx = g_new0(gboolean, NUM_COL_FMTS);
850 get_column_format_matches(col_item->fmt_matx, col_item->col_fmt);
851 col_item->col_data = NULL;
853 if (col_item->col_fmt == COL_INFO)
854 col_item->col_buf = g_new(gchar, COL_MAX_INFO_LEN);
855 else
856 col_item->col_buf = g_new(gchar, COL_MAX_LEN);
858 cinfo->col_expr.col_expr[i] = "";
859 cinfo->col_expr.col_expr_val[i] = g_new(gchar, COL_MAX_LEN);
862 cinfo->col_expr.col_expr[i] = NULL;
863 cinfo->col_expr.col_expr_val[i] = NULL;
865 for (i = 0; i < cinfo->num_cols; i++) {
866 int j;
868 for (j = 0; j < NUM_COL_FMTS; j++) {
869 if (!cinfo->columns[i].fmt_matx[j])
870 continue;
872 if (cinfo->col_first[j] == -1)
873 cinfo->col_first[j] = i;
875 cinfo->col_last[j] = i;
880 void
881 build_column_format_array(column_info *cinfo, const gint num_cols, const gboolean reset_fences)
883 int i;
884 col_item_t* col_item;
886 /* Build the column format array */
887 col_setup(cinfo, num_cols);
889 for (i = 0; i < cinfo->num_cols; i++) {
890 col_item = &cinfo->columns[i];
891 col_item->col_fmt = get_column_format(i);
892 col_item->col_title = g_strdup(get_column_title(i));
893 if (col_item->col_fmt == COL_CUSTOM) {
894 col_item->col_custom_fields = g_strdup(get_column_custom_fields(i));
895 col_item->col_custom_occurrence = get_column_custom_occurrence(i);
898 if(reset_fences)
899 col_item->col_fence = 0;
902 col_finalize(cinfo);
906 * Editor modelines - https://www.wireshark.org/tools/modelines.html
908 * Local variables:
909 * c-basic-offset: 2
910 * tab-width: 8
911 * indent-tabs-mode: nil
912 * End:
914 * vi: set shiftwidth=2 tabstop=8 expandtab:
915 * :indentSize=2:tabSize=8:noTabs=true: