From e782f9dad3b7ab11e37a3feea17a9fa2b9841d29 Mon Sep 17 00:00:00 2001 From: "raveit65 (via Travis CI)" Date: Fri, 23 Feb 2024 17:44:39 +0000 Subject: Deploy mate-desktop/mate-utils to github.com/mate-desktop/mate-utils.git:gh-pages --- .../0.html | 745 +++ .../1.html | 4065 +++++++++++++ .../10.html | 3385 ++++++++++ .../11.html | 3055 ++++++++++ .../12.html | 1523 +++++ .../13.html | 1071 ++++ .../14.html | 4391 +++++++++++++ .../15.html | 3133 ++++++++++ .../16.html | 6433 ++++++++++++++++++++ .../17.html | 1097 ++++ .../18.html | 1349 ++++ .../19.html | 945 +++ .../2.html | 1721 ++++++ .../20.html | 2139 +++++++ .../21.html | 1251 ++++ .../22.html | 1095 ++++ .../23.html | 1389 +++++ .../24.html | 1023 ++++ .../25.html | 3533 +++++++++++ .../26.html | 479 ++ .../27.html | 4543 ++++++++++++++ .../28.html | 5999 ++++++++++++++++++ .../29.html | 2039 +++++++ .../3.html | 1143 ++++ .../30.html | 2609 ++++++++ .../31.html | 1877 ++++++ .../32.html | 609 ++ .../33.html | 1815 ++++++ .../34.html | 4663 ++++++++++++++ .../35.html | 997 +++ .../36.html | 853 +++ .../37.html | 821 +++ .../38.html | 2009 ++++++ .../39.html | 1027 ++++ .../4.html | 1593 +++++ .../5.html | 1021 ++++ .../6.html | 917 +++ .../7.html | 1323 ++++ .../8.html | 2903 +++++++++ .../9.html | 1531 +++++ .../index.html | 388 ++ .../stats.html | 190 + .../style.css | 177 + 43 files changed, 84869 insertions(+) create mode 100644 2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/0.html create mode 100644 2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/1.html create mode 100644 2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/10.html create mode 100644 2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/11.html create mode 100644 2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/12.html create mode 100644 2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/13.html create mode 100644 2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/14.html create mode 100644 2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/15.html create mode 100644 2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/16.html create mode 100644 2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/17.html create mode 100644 2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/18.html create mode 100644 2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/19.html create mode 100644 2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/2.html create mode 100644 2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/20.html create mode 100644 2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/21.html create mode 100644 2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/22.html create mode 100644 2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/23.html create mode 100644 2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/24.html create mode 100644 2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/25.html create mode 100644 2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/26.html create mode 100644 2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/27.html create mode 100644 2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/28.html create mode 100644 2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/29.html create mode 100644 2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/3.html create mode 100644 2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/30.html create mode 100644 2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/31.html create mode 100644 2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/32.html create mode 100644 2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/33.html create mode 100644 2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/34.html create mode 100644 2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/35.html create mode 100644 2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/36.html create mode 100644 2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/37.html create mode 100644 2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/38.html create mode 100644 2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/39.html create mode 100644 2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/4.html create mode 100644 2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/5.html create mode 100644 2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/6.html create mode 100644 2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/7.html create mode 100644 2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/8.html create mode 100644 2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/9.html create mode 100644 2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/index.html create mode 100644 2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/stats.html create mode 100644 2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/style.css (limited to '2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master') diff --git a/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/0.html b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/0.html new file mode 100644 index 00000000..4105fff2 --- /dev/null +++ b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/0.html @@ -0,0 +1,745 @@ + + + + + + Cppcheck - HTML report - mate-utils + + + + + +
+ + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
/* Copyright (C) 2006 Paolo Borelli
+ * Copyright (C) 2012-2021 MATE Developers
+ *
+ * This file is part of MATE Utils.
+ *
+ * MATE Utils is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * MATE Utils is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MATE Utils.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+
+#include "baobab-cell-renderer-progress.h"
+
+enum
+{
+  PROP_0,
+  PROP_PERC
+};
+
+struct _BaobabCellRendererProgressPrivate
+{
+  double perc;
+};
+
+G_DEFINE_TYPE_WITH_PRIVATE (BaobabCellRendererProgress, baobab_cell_renderer_progress, GTK_TYPE_CELL_RENDERER)<--- There is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
+
+static void
+baobab_cell_renderer_progress_init (BaobabCellRendererProgress *cellprogress)
+{
+  cellprogress->priv = baobab_cell_renderer_progress_get_instance_private (cellprogress);
+  cellprogress->priv->perc = 0;
+
+  gtk_cell_renderer_set_padding (GTK_CELL_RENDERER (cellprogress), 4, 4);
+}
+
+GtkCellRenderer*
+baobab_cell_renderer_progress_new (void)
+{
+  return g_object_new (BAOBAB_TYPE_CELL_RENDERER_PROGRESS, NULL);
+}
+
+static void
+baobab_cell_renderer_progress_get_property (GObject *object,
+					    guint param_id,
+					    GValue *value,
+					    GParamSpec *pspec)
+{
+  BaobabCellRendererProgress *cellprogress = BAOBAB_CELL_RENDERER_PROGRESS (object);
+
+  switch (param_id)
+    {
+    case PROP_PERC:
+      g_value_set_double (value, cellprogress->priv->perc);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+    }
+}
+
+static void
+baobab_cell_renderer_progress_set_property (GObject *object,
+					    guint param_id,
+					    const GValue *value,
+					    GParamSpec   *pspec)
+{
+  BaobabCellRendererProgress *cellprogress = BAOBAB_CELL_RENDERER_PROGRESS (object);
+
+  switch (param_id)
+    {
+    case PROP_PERC:
+      cellprogress->priv->perc = g_value_get_double (value);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+    }
+}
+
+/* we simply have a fixed size */
+
+#define FIXED_WIDTH   70
+#define FIXED_HEIGHT  8
+
+static void
+baobab_cell_renderer_progress_get_size (GtkCellRenderer *cell,
+					GtkWidget       *widget,
+					const GdkRectangle *cell_area,
+					gint            *x_offset,
+					gint            *y_offset,
+					gint            *width,
+					gint            *height)
+{
+  gint calc_width;
+  gint calc_height;
+  gint xpad;
+  gint ypad;
+  gfloat xalign;
+  gfloat yalign;
+
+  gtk_cell_renderer_get_padding (cell, &xpad, &ypad);
+  calc_width  = (gint) xpad * 2 + FIXED_WIDTH;
+  calc_height = (gint) ypad * 2 + FIXED_HEIGHT;
+
+  if (width)
+    *width = calc_width;
+
+  if (height)
+    *height = calc_height;
+
+  if (cell_area)
+  {
+    gtk_cell_renderer_get_alignment (cell, &xalign, &yalign);
+    if (x_offset)
+    {
+      *x_offset = (gint) (xalign * (gfloat) (cell_area->width - calc_width));
+      *x_offset = MAX (*x_offset, 0);
+    }
+
+    if (y_offset)
+    {
+      *y_offset = (gint) (yalign * (gfloat) (cell_area->height - calc_height));
+      *y_offset = MAX (*y_offset, 0);
+    }
+  }
+}
+
+static void
+set_color_according_to_perc (cairo_t *cr, double value)
+{
+  static GdkRGBA red;
+  static GdkRGBA yellow;
+  static GdkRGBA green;
+  static gboolean colors_initialized = FALSE;
+
+  if (!colors_initialized)
+    {
+      /* hardcoded tango colors */
+      gdk_rgba_parse (&red, "#cc0000");
+      gdk_rgba_parse (&yellow, "#edd400");
+      gdk_rgba_parse (&green, "#73d216");
+
+      colors_initialized = TRUE;
+    }
+
+  if (value <= 0)
+    {
+      cairo_set_source_rgb (cr, 1, 1, 1);
+      return;
+    }
+  else if (value <= 33.33)
+    {
+      gdk_cairo_set_source_rgba (cr, &green);
+      return;
+    }
+  else if (value <= 66.66)
+    {
+      gdk_cairo_set_source_rgba (cr, &yellow);
+      return;
+    }
+  else if (value <= 100.0)
+    {
+      gdk_cairo_set_source_rgba (cr, &red);
+      return;
+    }
+  else
+    g_assert_not_reached ();
+}
+
+static void
+baobab_cell_renderer_progress_render (GtkCellRenderer *cell,
+				      cairo_t         *cr,
+				      GtkWidget       *widget,
+				      const GdkRectangle *background_area,
+				      const GdkRectangle  *cell_area,
+				      guint            flags)
+{
+  BaobabCellRendererProgress *cellprogress = BAOBAB_CELL_RENDERER_PROGRESS (cell);
+  gint x, y, w, h, perc_w;
+  gboolean is_rtl;
+  gint xpad;
+  gint ypad;
+  GtkStyle *style;
+
+  is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
+
+  gtk_cell_renderer_get_padding (cell, &xpad, &ypad);
+
+  x = cell_area->x + xpad;
+  y = cell_area->y + ypad;
+
+  w = cell_area->width - xpad * 2;
+  h = cell_area->height - ypad * 2;
+
+  /*
+   * we always use a white bar with black
+   * border and green/yellow/red progress...
+   * I know it's not theme friendly, but we don't
+   * want a plain progress bar
+   */
+
+  cairo_rectangle (cr, x, y, w, h);
+  cairo_set_source_rgb (cr, 0, 0, 0);
+  cairo_fill (cr);
+
+  style = gtk_widget_get_style (widget);
+  x += style->xthickness;
+  y += style->ythickness;
+  w -= style->xthickness * 2;
+  h -= style->ythickness * 2;
+
+  cairo_rectangle (cr, x, y, w, h);
+  cairo_set_source_rgb (cr, 1, 1, 1);
+  cairo_fill (cr);
+
+  perc_w = (gint) (w * MAX (0, cellprogress->priv->perc) / 100);
+
+  cairo_rectangle (cr, is_rtl ? (x + w - perc_w) : x, y, perc_w, h);
+  set_color_according_to_perc (cr, cellprogress->priv->perc);
+  cairo_fill (cr);
+}
+
+static void
+baobab_cell_renderer_progress_class_init (BaobabCellRendererProgressClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS (klass);
+
+  object_class->get_property = baobab_cell_renderer_progress_get_property;
+  object_class->set_property = baobab_cell_renderer_progress_set_property;
+
+  cell_class->get_size = baobab_cell_renderer_progress_get_size;
+  cell_class->render = baobab_cell_renderer_progress_render;
+
+  g_object_class_install_property (object_class,
+				   PROP_PERC,
+				   g_param_spec_double ("perc",
+						        "percentage",
+						        "precentage",
+						        -1, 100, 0,
+						        G_PARAM_READWRITE));
+}
+
+ +
+ +
+ + diff --git a/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/1.html b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/1.html new file mode 100644 index 00000000..449060ed --- /dev/null +++ b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/1.html @@ -0,0 +1,4065 @@ + + + + + + Cppcheck - HTML report - mate-utils + + + + + +
+ + + +
+
   1
+   2
+   3
+   4
+   5
+   6
+   7
+   8
+   9
+  10
+  11
+  12
+  13
+  14
+  15
+  16
+  17
+  18
+  19
+  20
+  21
+  22
+  23
+  24
+  25
+  26
+  27
+  28
+  29
+  30
+  31
+  32
+  33
+  34
+  35
+  36
+  37
+  38
+  39
+  40
+  41
+  42
+  43
+  44
+  45
+  46
+  47
+  48
+  49
+  50
+  51
+  52
+  53
+  54
+  55
+  56
+  57
+  58
+  59
+  60
+  61
+  62
+  63
+  64
+  65
+  66
+  67
+  68
+  69
+  70
+  71
+  72
+  73
+  74
+  75
+  76
+  77
+  78
+  79
+  80
+  81
+  82
+  83
+  84
+  85
+  86
+  87
+  88
+  89
+  90
+  91
+  92
+  93
+  94
+  95
+  96
+  97
+  98
+  99
+ 100
+ 101
+ 102
+ 103
+ 104
+ 105
+ 106
+ 107
+ 108
+ 109
+ 110
+ 111
+ 112
+ 113
+ 114
+ 115
+ 116
+ 117
+ 118
+ 119
+ 120
+ 121
+ 122
+ 123
+ 124
+ 125
+ 126
+ 127
+ 128
+ 129
+ 130
+ 131
+ 132
+ 133
+ 134
+ 135
+ 136
+ 137
+ 138
+ 139
+ 140
+ 141
+ 142
+ 143
+ 144
+ 145
+ 146
+ 147
+ 148
+ 149
+ 150
+ 151
+ 152
+ 153
+ 154
+ 155
+ 156
+ 157
+ 158
+ 159
+ 160
+ 161
+ 162
+ 163
+ 164
+ 165
+ 166
+ 167
+ 168
+ 169
+ 170
+ 171
+ 172
+ 173
+ 174
+ 175
+ 176
+ 177
+ 178
+ 179
+ 180
+ 181
+ 182
+ 183
+ 184
+ 185
+ 186
+ 187
+ 188
+ 189
+ 190
+ 191
+ 192
+ 193
+ 194
+ 195
+ 196
+ 197
+ 198
+ 199
+ 200
+ 201
+ 202
+ 203
+ 204
+ 205
+ 206
+ 207
+ 208
+ 209
+ 210
+ 211
+ 212
+ 213
+ 214
+ 215
+ 216
+ 217
+ 218
+ 219
+ 220
+ 221
+ 222
+ 223
+ 224
+ 225
+ 226
+ 227
+ 228
+ 229
+ 230
+ 231
+ 232
+ 233
+ 234
+ 235
+ 236
+ 237
+ 238
+ 239
+ 240
+ 241
+ 242
+ 243
+ 244
+ 245
+ 246
+ 247
+ 248
+ 249
+ 250
+ 251
+ 252
+ 253
+ 254
+ 255
+ 256
+ 257
+ 258
+ 259
+ 260
+ 261
+ 262
+ 263
+ 264
+ 265
+ 266
+ 267
+ 268
+ 269
+ 270
+ 271
+ 272
+ 273
+ 274
+ 275
+ 276
+ 277
+ 278
+ 279
+ 280
+ 281
+ 282
+ 283
+ 284
+ 285
+ 286
+ 287
+ 288
+ 289
+ 290
+ 291
+ 292
+ 293
+ 294
+ 295
+ 296
+ 297
+ 298
+ 299
+ 300
+ 301
+ 302
+ 303
+ 304
+ 305
+ 306
+ 307
+ 308
+ 309
+ 310
+ 311
+ 312
+ 313
+ 314
+ 315
+ 316
+ 317
+ 318
+ 319
+ 320
+ 321
+ 322
+ 323
+ 324
+ 325
+ 326
+ 327
+ 328
+ 329
+ 330
+ 331
+ 332
+ 333
+ 334
+ 335
+ 336
+ 337
+ 338
+ 339
+ 340
+ 341
+ 342
+ 343
+ 344
+ 345
+ 346
+ 347
+ 348
+ 349
+ 350
+ 351
+ 352
+ 353
+ 354
+ 355
+ 356
+ 357
+ 358
+ 359
+ 360
+ 361
+ 362
+ 363
+ 364
+ 365
+ 366
+ 367
+ 368
+ 369
+ 370
+ 371
+ 372
+ 373
+ 374
+ 375
+ 376
+ 377
+ 378
+ 379
+ 380
+ 381
+ 382
+ 383
+ 384
+ 385
+ 386
+ 387
+ 388
+ 389
+ 390
+ 391
+ 392
+ 393
+ 394
+ 395
+ 396
+ 397
+ 398
+ 399
+ 400
+ 401
+ 402
+ 403
+ 404
+ 405
+ 406
+ 407
+ 408
+ 409
+ 410
+ 411
+ 412
+ 413
+ 414
+ 415
+ 416
+ 417
+ 418
+ 419
+ 420
+ 421
+ 422
+ 423
+ 424
+ 425
+ 426
+ 427
+ 428
+ 429
+ 430
+ 431
+ 432
+ 433
+ 434
+ 435
+ 436
+ 437
+ 438
+ 439
+ 440
+ 441
+ 442
+ 443
+ 444
+ 445
+ 446
+ 447
+ 448
+ 449
+ 450
+ 451
+ 452
+ 453
+ 454
+ 455
+ 456
+ 457
+ 458
+ 459
+ 460
+ 461
+ 462
+ 463
+ 464
+ 465
+ 466
+ 467
+ 468
+ 469
+ 470
+ 471
+ 472
+ 473
+ 474
+ 475
+ 476
+ 477
+ 478
+ 479
+ 480
+ 481
+ 482
+ 483
+ 484
+ 485
+ 486
+ 487
+ 488
+ 489
+ 490
+ 491
+ 492
+ 493
+ 494
+ 495
+ 496
+ 497
+ 498
+ 499
+ 500
+ 501
+ 502
+ 503
+ 504
+ 505
+ 506
+ 507
+ 508
+ 509
+ 510
+ 511
+ 512
+ 513
+ 514
+ 515
+ 516
+ 517
+ 518
+ 519
+ 520
+ 521
+ 522
+ 523
+ 524
+ 525
+ 526
+ 527
+ 528
+ 529
+ 530
+ 531
+ 532
+ 533
+ 534
+ 535
+ 536
+ 537
+ 538
+ 539
+ 540
+ 541
+ 542
+ 543
+ 544
+ 545
+ 546
+ 547
+ 548
+ 549
+ 550
+ 551
+ 552
+ 553
+ 554
+ 555
+ 556
+ 557
+ 558
+ 559
+ 560
+ 561
+ 562
+ 563
+ 564
+ 565
+ 566
+ 567
+ 568
+ 569
+ 570
+ 571
+ 572
+ 573
+ 574
+ 575
+ 576
+ 577
+ 578
+ 579
+ 580
+ 581
+ 582
+ 583
+ 584
+ 585
+ 586
+ 587
+ 588
+ 589
+ 590
+ 591
+ 592
+ 593
+ 594
+ 595
+ 596
+ 597
+ 598
+ 599
+ 600
+ 601
+ 602
+ 603
+ 604
+ 605
+ 606
+ 607
+ 608
+ 609
+ 610
+ 611
+ 612
+ 613
+ 614
+ 615
+ 616
+ 617
+ 618
+ 619
+ 620
+ 621
+ 622
+ 623
+ 624
+ 625
+ 626
+ 627
+ 628
+ 629
+ 630
+ 631
+ 632
+ 633
+ 634
+ 635
+ 636
+ 637
+ 638
+ 639
+ 640
+ 641
+ 642
+ 643
+ 644
+ 645
+ 646
+ 647
+ 648
+ 649
+ 650
+ 651
+ 652
+ 653
+ 654
+ 655
+ 656
+ 657
+ 658
+ 659
+ 660
+ 661
+ 662
+ 663
+ 664
+ 665
+ 666
+ 667
+ 668
+ 669
+ 670
+ 671
+ 672
+ 673
+ 674
+ 675
+ 676
+ 677
+ 678
+ 679
+ 680
+ 681
+ 682
+ 683
+ 684
+ 685
+ 686
+ 687
+ 688
+ 689
+ 690
+ 691
+ 692
+ 693
+ 694
+ 695
+ 696
+ 697
+ 698
+ 699
+ 700
+ 701
+ 702
+ 703
+ 704
+ 705
+ 706
+ 707
+ 708
+ 709
+ 710
+ 711
+ 712
+ 713
+ 714
+ 715
+ 716
+ 717
+ 718
+ 719
+ 720
+ 721
+ 722
+ 723
+ 724
+ 725
+ 726
+ 727
+ 728
+ 729
+ 730
+ 731
+ 732
+ 733
+ 734
+ 735
+ 736
+ 737
+ 738
+ 739
+ 740
+ 741
+ 742
+ 743
+ 744
+ 745
+ 746
+ 747
+ 748
+ 749
+ 750
+ 751
+ 752
+ 753
+ 754
+ 755
+ 756
+ 757
+ 758
+ 759
+ 760
+ 761
+ 762
+ 763
+ 764
+ 765
+ 766
+ 767
+ 768
+ 769
+ 770
+ 771
+ 772
+ 773
+ 774
+ 775
+ 776
+ 777
+ 778
+ 779
+ 780
+ 781
+ 782
+ 783
+ 784
+ 785
+ 786
+ 787
+ 788
+ 789
+ 790
+ 791
+ 792
+ 793
+ 794
+ 795
+ 796
+ 797
+ 798
+ 799
+ 800
+ 801
+ 802
+ 803
+ 804
+ 805
+ 806
+ 807
+ 808
+ 809
+ 810
+ 811
+ 812
+ 813
+ 814
+ 815
+ 816
+ 817
+ 818
+ 819
+ 820
+ 821
+ 822
+ 823
+ 824
+ 825
+ 826
+ 827
+ 828
+ 829
+ 830
+ 831
+ 832
+ 833
+ 834
+ 835
+ 836
+ 837
+ 838
+ 839
+ 840
+ 841
+ 842
+ 843
+ 844
+ 845
+ 846
+ 847
+ 848
+ 849
+ 850
+ 851
+ 852
+ 853
+ 854
+ 855
+ 856
+ 857
+ 858
+ 859
+ 860
+ 861
+ 862
+ 863
+ 864
+ 865
+ 866
+ 867
+ 868
+ 869
+ 870
+ 871
+ 872
+ 873
+ 874
+ 875
+ 876
+ 877
+ 878
+ 879
+ 880
+ 881
+ 882
+ 883
+ 884
+ 885
+ 886
+ 887
+ 888
+ 889
+ 890
+ 891
+ 892
+ 893
+ 894
+ 895
+ 896
+ 897
+ 898
+ 899
+ 900
+ 901
+ 902
+ 903
+ 904
+ 905
+ 906
+ 907
+ 908
+ 909
+ 910
+ 911
+ 912
+ 913
+ 914
+ 915
+ 916
+ 917
+ 918
+ 919
+ 920
+ 921
+ 922
+ 923
+ 924
+ 925
+ 926
+ 927
+ 928
+ 929
+ 930
+ 931
+ 932
+ 933
+ 934
+ 935
+ 936
+ 937
+ 938
+ 939
+ 940
+ 941
+ 942
+ 943
+ 944
+ 945
+ 946
+ 947
+ 948
+ 949
+ 950
+ 951
+ 952
+ 953
+ 954
+ 955
+ 956
+ 957
+ 958
+ 959
+ 960
+ 961
+ 962
+ 963
+ 964
+ 965
+ 966
+ 967
+ 968
+ 969
+ 970
+ 971
+ 972
+ 973
+ 974
+ 975
+ 976
+ 977
+ 978
+ 979
+ 980
+ 981
+ 982
+ 983
+ 984
+ 985
+ 986
+ 987
+ 988
+ 989
+ 990
+ 991
+ 992
+ 993
+ 994
+ 995
+ 996
+ 997
+ 998
+ 999
+1000
+1001
+1002
+1003
+1004
+1005
+1006
+1007
+1008
+1009
+1010
+1011
+1012
+1013
+1014
+1015
+1016
+1017
+1018
+1019
+1020
+1021
+1022
+1023
+1024
+1025
+1026
+1027
+1028
+1029
+1030
+1031
+1032
+1033
+1034
+1035
+1036
+1037
+1038
+1039
+1040
+1041
+1042
+1043
+1044
+1045
+1046
+1047
+1048
+1049
+1050
+1051
+1052
+1053
+1054
+1055
+1056
+1057
+1058
+1059
+1060
+1061
+1062
+1063
+1064
+1065
+1066
+1067
+1068
+1069
+1070
+1071
+1072
+1073
+1074
+1075
+1076
+1077
+1078
+1079
+1080
+1081
+1082
+1083
+1084
+1085
+1086
+1087
+1088
+1089
+1090
+1091
+1092
+1093
+1094
+1095
+1096
+1097
+1098
+1099
+1100
+1101
+1102
+1103
+1104
+1105
+1106
+1107
+1108
+1109
+1110
+1111
+1112
+1113
+1114
+1115
+1116
+1117
+1118
+1119
+1120
+1121
+1122
+1123
+1124
+1125
+1126
+1127
+1128
+1129
+1130
+1131
+1132
+1133
+1134
+1135
+1136
+1137
+1138
+1139
+1140
+1141
+1142
+1143
+1144
+1145
+1146
+1147
+1148
+1149
+1150
+1151
+1152
+1153
+1154
+1155
+1156
+1157
+1158
+1159
+1160
+1161
+1162
+1163
+1164
+1165
+1166
+1167
+1168
+1169
+1170
+1171
+1172
+1173
+1174
+1175
+1176
+1177
+1178
+1179
+1180
+1181
+1182
+1183
+1184
+1185
+1186
+1187
+1188
+1189
+1190
+1191
+1192
+1193
+1194
+1195
+1196
+1197
+1198
+1199
+1200
+1201
+1202
+1203
+1204
+1205
+1206
+1207
+1208
+1209
+1210
+1211
+1212
+1213
+1214
+1215
+1216
+1217
+1218
+1219
+1220
+1221
+1222
+1223
+1224
+1225
+1226
+1227
+1228
+1229
+1230
+1231
+1232
+1233
+1234
+1235
+1236
+1237
+1238
+1239
+1240
+1241
+1242
+1243
+1244
+1245
+1246
+1247
+1248
+1249
+1250
+1251
+1252
+1253
+1254
+1255
+1256
+1257
+1258
+1259
+1260
+1261
+1262
+1263
+1264
+1265
+1266
+1267
+1268
+1269
+1270
+1271
+1272
+1273
+1274
+1275
+1276
+1277
+1278
+1279
+1280
+1281
+1282
+1283
+1284
+1285
+1286
+1287
+1288
+1289
+1290
+1291
+1292
+1293
+1294
+1295
+1296
+1297
+1298
+1299
+1300
+1301
+1302
+1303
+1304
+1305
+1306
+1307
+1308
+1309
+1310
+1311
+1312
+1313
+1314
+1315
+1316
+1317
+1318
+1319
+1320
+1321
+1322
+1323
+1324
+1325
+1326
+1327
+1328
+1329
+1330
+1331
+1332
+1333
+1334
+1335
+1336
+1337
+1338
+1339
+1340
+1341
+1342
+1343
+1344
+1345
+1346
+1347
+1348
+1349
+1350
+1351
+1352
+1353
+1354
+1355
+1356
+1357
+1358
+1359
+1360
+1361
+1362
+1363
+1364
+1365
+1366
+1367
+1368
+1369
+1370
+1371
+1372
+1373
+1374
+1375
+1376
+1377
+1378
+1379
+1380
+1381
+1382
+1383
+1384
+1385
+1386
+1387
+1388
+1389
+1390
+1391
+1392
+1393
+1394
+1395
+1396
+1397
+1398
+1399
+1400
+1401
+1402
+1403
+1404
+1405
+1406
+1407
+1408
+1409
+1410
+1411
+1412
+1413
+1414
+1415
+1416
+1417
+1418
+1419
+1420
+1421
+1422
+1423
+1424
+1425
+1426
+1427
+1428
+1429
+1430
+1431
+1432
+1433
+1434
+1435
+1436
+1437
+1438
+1439
+1440
+1441
+1442
+1443
+1444
+1445
+1446
+1447
+1448
+1449
+1450
+1451
+1452
+1453
+1454
+1455
+1456
+1457
+1458
+1459
+1460
+1461
+1462
+1463
+1464
+1465
+1466
+1467
+1468
+1469
+1470
+1471
+1472
+1473
+1474
+1475
+1476
+1477
+1478
+1479
+1480
+1481
+1482
+1483
+1484
+1485
+1486
+1487
+1488
+1489
+1490
+1491
+1492
+1493
+1494
+1495
+1496
+1497
+1498
+1499
+1500
+1501
+1502
+1503
+1504
+1505
+1506
+1507
+1508
+1509
+1510
+1511
+1512
+1513
+1514
+1515
+1516
+1517
+1518
+1519
+1520
+1521
+1522
+1523
+1524
+1525
+1526
+1527
+1528
+1529
+1530
+1531
+1532
+1533
+1534
+1535
+1536
+1537
+1538
+1539
+1540
+1541
+1542
+1543
+1544
+1545
+1546
+1547
+1548
+1549
+1550
+1551
+1552
+1553
+1554
+1555
+1556
+1557
+1558
+1559
+1560
+1561
+1562
+1563
+1564
+1565
+1566
+1567
+1568
+1569
+1570
+1571
+1572
+1573
+1574
+1575
+1576
+1577
+1578
+1579
+1580
+1581
+1582
+1583
+1584
+1585
+1586
+1587
+1588
+1589
+1590
+1591
+1592
+1593
+1594
+1595
+1596
+1597
+1598
+1599
+1600
+1601
+1602
+1603
+1604
+1605
+1606
+1607
+1608
+1609
+1610
+1611
+1612
+1613
+1614
+1615
+1616
+1617
+1618
+1619
+1620
+1621
+1622
+1623
+1624
+1625
+1626
+1627
+1628
+1629
+1630
+1631
+1632
+1633
+1634
+1635
+1636
+1637
+1638
+1639
+1640
+1641
+1642
+1643
+1644
+1645
+1646
+1647
+1648
+1649
+1650
+1651
+1652
+1653
+1654
+1655
+1656
+1657
+1658
+1659
+1660
+1661
+1662
+1663
+1664
+1665
+1666
+1667
+1668
+1669
+1670
+1671
+1672
+1673
+1674
+1675
+1676
+1677
+1678
+1679
+1680
+1681
+1682
+1683
+1684
+1685
+1686
+1687
+1688
+1689
+1690
+1691
+1692
+1693
+1694
+1695
+1696
+1697
+1698
+1699
+1700
+1701
+1702
+1703
+1704
+1705
+1706
+1707
+1708
+1709
+1710
+1711
+1712
+1713
+1714
+1715
+1716
+1717
+1718
+1719
+1720
+1721
+1722
+1723
+1724
+1725
+1726
+1727
+1728
+1729
+1730
+1731
+1732
+1733
+1734
+1735
+1736
+1737
+1738
+1739
+1740
+1741
+1742
+1743
+1744
+1745
+1746
+1747
+1748
+1749
+1750
+1751
+1752
+1753
+1754
+1755
+1756
+1757
+1758
+1759
+1760
+1761
+1762
+1763
+1764
+1765
+1766
+1767
+1768
+1769
+1770
+1771
+1772
+1773
+1774
+1775
+1776
+1777
+1778
+1779
+1780
+1781
+1782
+1783
+1784
+1785
+1786
+1787
+1788
+1789
+1790
+1791
+1792
+1793
+1794
+1795
+1796
+1797
+1798
+1799
+1800
+1801
+1802
+1803
+1804
+1805
+1806
+1807
+1808
+1809
+1810
+1811
+1812
+1813
+1814
+1815
+1816
+1817
+1818
+1819
+1820
+1821
+1822
+1823
+1824
+1825
+1826
+1827
+1828
+1829
+1830
+1831
+1832
+1833
+1834
+1835
+1836
+1837
+1838
+1839
+1840
+1841
+1842
+1843
+1844
+1845
+1846
+1847
+1848
+1849
+1850
+1851
+1852
+1853
+1854
+1855
+1856
+1857
+1858
+1859
+1860
+1861
+1862
+1863
+1864
+1865
+1866
+1867
+1868
+1869
+1870
+1871
+1872
/* Copyright (C) 2006, 2007, 2008 Igalia
+ * Copyright (C) 2012-2021 MATE Developers
+ *
+ * This file is part of MATE Utils.
+ *
+ * MATE Utils is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * MATE Utils is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MATE Utils.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ *   Felipe Erias <femorandeira@igalia.com>
+ *   Pablo Santamaria <psantamaria@igalia.com>
+ *   Jacobo Aragunde <jaragunde@igalia.com>
+ *   Eduardo Lima <elima@igalia.com>
+ *   Mario Sanchez <msanchez@igalia.com>
+ *   Miguel Gomez <magomez@igalia.com>
+ *   Henrique Ferreiro <hferreiro@igalia.com>
+ *   Alejandro Pinheiro <apinheiro@igalia.com>
+ *   Carlos Sanmartin <csanmartin@igalia.com>
+ *   Alejandro Garcia <alex@igalia.com>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <gtk/gtk.h>
+#include <glib/gi18n.h>
+
+/* needed for floor and ceil */
+#include <math.h>
+
+#include "baobab-chart.h"
+
+#define SNAPSHOT_DEF_FILENAME_FORMAT "%s-disk-usage"
+
+#define BAOBAB_CHART_MAX_DEPTH 8
+#define BAOBAB_CHART_MIN_DEPTH 1
+
+enum
+{
+  LEFT_BUTTON   = 1,
+  MIDDLE_BUTTON = 2,
+  RIGHT_BUTTON  = 3
+};
+
+struct _BaobabChartPrivate
+{
+  guint name_column;
+  guint size_column;
+  guint info_column;
+  guint percentage_column;
+  guint valid_column;
+  gboolean button_pressed;
+  gboolean is_frozen;
+  cairo_surface_t *memento;
+
+  guint max_depth;
+  gboolean model_changed;
+
+  GtkTreeModel *model;
+  GtkTreeRowReference *root;
+
+  GList *first_item;
+  GList *last_item;
+  GList *highlighted_item;
+};
+
+/* Signals */
+enum
+{
+  ITEM_ACTIVATED,
+  LAST_SIGNAL
+};
+
+G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (BaobabChart, baobab_chart, GTK_TYPE_WIDGET);
+
+static guint baobab_chart_signals [LAST_SIGNAL] = { 0 };
+
+/* Properties */
+enum
+{
+  PROP_0,
+  PROP_MAX_DEPTH,
+  PROP_MODEL,
+  PROP_ROOT,
+};
+
+/* Colors */
+const BaobabChartColor baobab_chart_tango_colors[] = {{0.94, 0.16, 0.16}, /* tango: ef2929 */
+                                                      {0.68, 0.49, 0.66}, /* tango: ad7fa8 */
+                                                      {0.45, 0.62, 0.82}, /* tango: 729fcf */
+                                                      {0.54, 0.89, 0.20}, /* tango: 8ae234 */
+                                                      {0.91, 0.73, 0.43}, /* tango: e9b96e */
+                                                      {0.99, 0.68, 0.25}}; /* tango: fcaf3e */
+
+static void baobab_chart_realize (GtkWidget *widget);
+static void baobab_chart_dispose (GObject *object);
+static void baobab_chart_size_allocate (GtkWidget *widget,
+                                        GtkAllocation *allocation);
+static void baobab_chart_set_property (GObject *object,
+                                       guint prop_id,
+                                       const GValue *value,
+                                       GParamSpec *pspec);
+static void baobab_chart_get_property (GObject *object,
+                                       guint prop_id,
+                                       GValue *value,
+                                       GParamSpec *pspec);
+static void baobab_chart_free_items (GtkWidget *chart);
+static void baobab_chart_draw (GtkWidget *chart,
+                               cairo_t *cr,
+                               GdkRectangle area);
+static void baobab_chart_update_draw (BaobabChart *chart,
+                                      GtkTreePath *path);
+static void baobab_chart_row_changed (GtkTreeModel *model,
+                                      GtkTreePath *path,
+                                      GtkTreeIter *iter,
+                                      gpointer data);
+static void baobab_chart_row_inserted (GtkTreeModel *model,
+                                       GtkTreePath *path,
+                                       GtkTreeIter *iter,
+                                       gpointer data);
+static void baobab_chart_row_has_child_toggled (GtkTreeModel *model,
+                                                GtkTreePath *path,
+                                                GtkTreeIter *iter,
+                                                gpointer data);
+static void baobab_chart_row_deleted (GtkTreeModel *model,
+                                      GtkTreePath *path,
+                                      gpointer data);
+static void baobab_chart_rows_reordered (GtkTreeModel *model,
+                                         GtkTreePath *parent,
+                                         GtkTreeIter *iter,
+                                         gint *new_order,
+                                         gpointer data);
+static gboolean baobab_chart_expose (GtkWidget *chart,
+                                     cairo_t *cr);
+static void baobab_chart_interpolate_colors (BaobabChartColor *color,
+                                             BaobabChartColor colora,
+                                             BaobabChartColor colorb,
+                                             gdouble percentage);
+static gint baobab_chart_button_release (GtkWidget *widget,
+                                         GdkEventButton *event);
+static gint baobab_chart_scroll (GtkWidget *widget,
+                                 GdkEventScroll *event);
+static gint baobab_chart_motion_notify (GtkWidget *widget,
+                                        GdkEventMotion *event);
+static gint baobab_chart_leave_notify (GtkWidget *widget,
+                                       GdkEventCrossing *event);
+static inline void baobab_chart_disconnect_signals (GtkWidget *chart,
+                                                    GtkTreeModel *model);
+static inline void baobab_chart_connect_signals (GtkWidget *chart,
+                                                 GtkTreeModel *model);
+static void baobab_chart_get_items (GtkWidget *chart, GtkTreePath *root);
+static gboolean baobab_chart_query_tooltip (GtkWidget  *widget,
+                                            gint        x,
+                                            gint        y,
+                                            gboolean    keyboard_mode,
+                                            GtkTooltip *tooltip,
+                                            gpointer    user_data);
+
+static void
+baobab_chart_class_init (BaobabChartClass *class)
+{
+  GObjectClass *obj_class;
+  GtkWidgetClass *widget_class;
+
+  obj_class = G_OBJECT_CLASS (class);
+  widget_class = GTK_WIDGET_CLASS (class);
+
+  /* GtkObject signals */
+  obj_class->set_property = baobab_chart_set_property;
+  obj_class->get_property = baobab_chart_get_property;
+  obj_class->dispose = baobab_chart_dispose;
+
+  /* GtkWidget signals */
+  widget_class->realize = baobab_chart_realize;
+  widget_class->draw = baobab_chart_expose;
+  widget_class->size_allocate = baobab_chart_size_allocate;
+  widget_class->scroll_event = baobab_chart_scroll;
+
+  /* Baobab Chart abstract methods */
+  class->draw_item               = NULL;
+  class->pre_draw                = NULL;
+  class->post_draw               = NULL;
+  class->calculate_item_geometry = NULL;
+  class->is_point_over_item      = NULL;
+  class->get_item_rectangle      = NULL;
+  class->can_zoom_in             = NULL;
+  class->can_zoom_out            = NULL;
+
+  g_object_class_install_property (obj_class,
+                                   PROP_MAX_DEPTH,
+                                   g_param_spec_int ("max-depth",
+                                   _("Maximum depth"),
+                                   _("The maximum depth drawn in the chart from the root"),
+                                   1,
+                                   BAOBAB_CHART_MAX_DEPTH,
+                                   BAOBAB_CHART_MAX_DEPTH,
+                                   G_PARAM_READWRITE));
+
+  g_object_class_install_property (obj_class,
+                                   PROP_MODEL,
+                                   g_param_spec_object ("model",
+                                   _("Chart model"),
+                                   _("Set the model of the chart"),
+                                   GTK_TYPE_TREE_MODEL,
+                                   G_PARAM_READWRITE));
+
+  g_object_class_install_property (obj_class,
+                                   PROP_ROOT,
+                                   g_param_spec_boxed ("root",
+                                   _("Chart root node"),
+                                   _("Set the root node from the model"),
+                                   GTK_TYPE_TREE_ITER,
+                                   G_PARAM_READWRITE));
+
+  baobab_chart_signals[ITEM_ACTIVATED] =
+    g_signal_new ("item_activated",
+          G_TYPE_FROM_CLASS (obj_class),
+          G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+          G_STRUCT_OFFSET (BaobabChartClass, item_activated),
+          NULL, NULL,
+          g_cclosure_marshal_VOID__BOXED,
+          G_TYPE_NONE, 1,
+          GTK_TYPE_TREE_ITER);
+}
+
+static void
+baobab_chart_init (BaobabChart *chart)
+{
+  BaobabChartPrivate *priv;
+
+  priv = baobab_chart_get_instance_private (chart);
+  chart->priv = priv;
+
+  priv->model = NULL;
+  priv->max_depth = BAOBAB_CHART_MAX_DEPTH;
+  priv->name_column = 0;
+  priv->size_column = 0;
+  priv->info_column = 0;
+  priv->percentage_column = 0;
+  priv->valid_column = 0;
+  priv->button_pressed = FALSE;
+  priv->is_frozen = FALSE;
+  priv->memento = NULL;
+  priv->root = NULL;
+
+  priv->first_item = NULL;
+  priv->last_item = NULL;
+  priv->highlighted_item = NULL;
+}
+
+static void
+baobab_chart_dispose (GObject *object)
+{
+  BaobabChartPrivate *priv;
+
+  baobab_chart_free_items (GTK_WIDGET (object));
+
+  priv = BAOBAB_CHART (object)->priv;
+
+  if (priv->model)
+    {
+      baobab_chart_disconnect_signals (GTK_WIDGET (object),
+                                       priv->model);
+
+      g_object_unref (priv->model);
+
+      priv->model = NULL;
+    }
+
+  if (priv->root)
+    {
+      gtk_tree_row_reference_free (priv->root);
+
+      priv->root = NULL;
+    }
+
+  G_OBJECT_CLASS (baobab_chart_parent_class)->dispose (object);
+}
+
+static void
+baobab_chart_realize (GtkWidget *widget)
+{
+  BaobabChart *chart;
+  GdkWindowAttr attributes;
+  gint attributes_mask;
+  GtkAllocation allocation;
+  GdkWindow *window;
+
+  g_return_if_fail (BAOBAB_IS_CHART (widget));
+
+  chart = BAOBAB_CHART (widget);
+  gtk_widget_set_realized (widget, TRUE);
+
+  gtk_widget_get_allocation (widget, &allocation);
+
+  attributes.window_type = GDK_WINDOW_CHILD;
+  attributes.x = allocation.x;
+  attributes.y = allocation.y;
+  attributes.width = allocation.width;
+  attributes.height = allocation.height;
+  attributes.wclass = GDK_INPUT_OUTPUT;
+  attributes.visual = gtk_widget_get_visual (widget);
+  attributes.event_mask = gtk_widget_get_events (widget);
+
+  attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
+
+  window = gdk_window_new (gtk_widget_get_parent_window (widget),
+                           &attributes,
+                           attributes_mask);
+  gtk_widget_set_window (widget, window);
+  gdk_window_set_user_data (window, chart);
+
+  gtk_widget_add_events (widget,
+                         GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK |
+                         GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK |
+                         GDK_POINTER_MOTION_HINT_MASK | GDK_LEAVE_NOTIFY_MASK |
+                         GDK_SCROLL_MASK);
+}
+
+static void
+baobab_chart_size_allocate (GtkWidget *widget,
+                            GtkAllocation *allocation)
+{
+  BaobabChartPrivate *priv;
+  BaobabChartClass *class;
+  BaobabChartItem *item;
+  GList *node;
+
+  g_return_if_fail (BAOBAB_IS_CHART (widget));
+  g_return_if_fail (allocation != NULL);
+
+  priv = BAOBAB_CHART (widget)->priv;
+  class = BAOBAB_CHART_GET_CLASS (widget);
+
+  gtk_widget_set_allocation (widget, allocation);
+
+  if (gtk_widget_get_realized (widget))
+    {
+      gdk_window_move_resize (gtk_widget_get_window (widget),
+                  allocation->x, allocation->y,
+                  allocation->width, allocation->height);
+
+      node = priv->first_item;
+      while (node != NULL)
+        {
+          item = (BaobabChartItem *) node->data;
+          item->has_visible_children = FALSE;
+          item->visible = FALSE;
+          class->calculate_item_geometry (widget, item);
+
+          node = node->next;
+        }
+    }
+}
+
+static void
+baobab_chart_set_property (GObject         *object,
+                           guint            prop_id,
+                           const GValue    *value,
+                           GParamSpec      *pspec)
+{
+  BaobabChart *chart;
+
+  chart = BAOBAB_CHART (object);
+
+  switch (prop_id)
+    {
+    case PROP_MAX_DEPTH:
+      baobab_chart_set_max_depth (GTK_WIDGET (chart), g_value_get_uint (value));
+      break;
+    case PROP_MODEL:
+      baobab_chart_set_model (GTK_WIDGET (chart), g_value_get_object (value));
+      break;
+    case PROP_ROOT:
+      baobab_chart_set_root (GTK_WIDGET (chart), g_value_get_object (value));
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+baobab_chart_get_property (GObject    *object,
+                           guint       prop_id,
+                           GValue     *value,
+                           GParamSpec *pspec)
+{
+  BaobabChartPrivate *priv;
+
+  priv = BAOBAB_CHART (object)->priv;
+
+  switch (prop_id)
+    {
+    case PROP_MAX_DEPTH:
+      g_value_set_uint (value, priv->max_depth);
+      break;
+    case PROP_MODEL:
+      g_value_set_object (value, priv->model);
+      break;
+    case PROP_ROOT:
+      g_value_set_object (value, priv->root);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static GList
+*baobab_chart_add_item (GtkWidget *chart,
+                        guint depth,
+                        gdouble rel_start,
+                        gdouble rel_size,
+                        GtkTreeIter iter)
+{
+  BaobabChartPrivate *priv;
+  BaobabChartItem *item;
+
+  gchar *name;
+  gchar *size;
+
+  priv = BAOBAB_CHART (chart)->priv;
+
+  gtk_tree_model_get (priv->model, &iter,
+                      priv->name_column, &name, -1);
+  gtk_tree_model_get (priv->model, &iter,
+                      priv->size_column, &size, -1);
+
+  item = g_new (BaobabChartItem, 1);
+  item->name = name;
+  item->size = size;
+  item->depth = depth;
+  item->rel_start = rel_start;
+  item->rel_size = rel_size;
+  item->has_any_child = FALSE;
+  item->visible = FALSE;
+  item->has_visible_children = FALSE;
+
+  item->iter = iter;
+
+  item->parent = NULL;
+  item->data = NULL;
+
+  priv->last_item = g_list_prepend (priv->last_item, item);
+
+  return priv->last_item;
+}
+
+static void
+baobab_chart_free_items (GtkWidget *chart)
+{
+  BaobabChartPrivate *priv;
+  BaobabChartItem *item;
+  GList *node;
+  GList *next;
+
+  priv = BAOBAB_CHART (chart)->priv;
+
+  node = priv->first_item;
+  while (node != NULL)
+    {
+      next = node->next;
+
+      item = (BaobabChartItem *) node->data;
+
+      g_free (item->name);
+      g_free (item->size);
+
+      g_free (item->data);
+      item->data = NULL;
+
+      g_free (item);
+      g_list_free_1 (node);
+
+      node = next;
+    }
+
+  priv->first_item = NULL;
+  priv->last_item = NULL;
+  priv->highlighted_item = NULL;
+}
+
+static void
+baobab_chart_get_items (GtkWidget *chart, GtkTreePath *root)
+{
+  BaobabChartPrivate *priv;
+  BaobabChartItem *item;
+
+  GList *node;
+  GtkTreeIter initial_iter = {0};
+  gdouble size;
+  GtkTreePath *model_root_path;
+  GtkTreeIter model_root_iter;
+
+  BaobabChartClass *class;
+  GtkTreeIter child_iter = {0};
+  GList *child_node;
+  BaobabChartItem *child;
+  gdouble rel_start;
+
+  priv = BAOBAB_CHART (chart)->priv;
+
+  /* First we free current item list */
+  baobab_chart_free_items (chart);
+
+  /* Get the tree iteration corresponding to root */
+  if (!gtk_tree_model_get_iter (priv->model, &initial_iter, root))
+    {
+      priv->model_changed = FALSE;
+      return;
+    }
+
+  model_root_path = gtk_tree_path_new_first ();
+  gtk_tree_model_get_iter (priv->model, &model_root_iter, model_root_path);
+  gtk_tree_path_free (model_root_path);
+
+  gtk_tree_model_get (priv->model, &model_root_iter,
+                      priv->percentage_column, &size, -1);
+
+  /* Create first item */
+  node = baobab_chart_add_item (chart, 0, 0, 100, initial_iter);
+
+  /* Iterate through childs building the list */
+  class = BAOBAB_CHART_GET_CLASS (chart);
+
+  do
+    {
+      item = (BaobabChartItem *) node->data;
+      item->has_any_child = gtk_tree_model_iter_children (priv->model,
+                                                          &child_iter,
+                                                          &(item->iter));
+
+      /* Calculate item geometry */
+      class->calculate_item_geometry (chart, item);
+
+      if (! item->visible)
+        {
+          node = node->prev;
+          continue;
+        }
+
+      /* Get item's children and add them to the list */
+      if ((item->has_any_child) && (item->depth < priv->max_depth + 1))
+        {
+          rel_start = 0;
+
+          do
+            {
+              gtk_tree_model_get (priv->model, &child_iter,
+                                  priv->percentage_column, &size, -1);
+
+              child_node = baobab_chart_add_item (chart,
+                                                  item->depth + 1,
+                                                  rel_start,
+                                                  size,
+                                                  child_iter);
+              child = (BaobabChartItem *) child_node->data;
+              child->parent = node;
+              rel_start += size;
+            }
+          while (gtk_tree_model_iter_next (priv->model, &child_iter));
+        }
+
+      node = node->prev;
+    }
+  while (node != NULL);
+
+  /* Reverse the list, 'cause we created it from the tail, for efficiency reasons */
+  priv->first_item = g_list_reverse (priv->last_item);
+
+  priv->model_changed = FALSE;
+}
+
+static void
+baobab_chart_draw (GtkWidget *chart,
+                   cairo_t *cr,
+                   GdkRectangle area)
+{
+  BaobabChartPrivate *priv;
+  BaobabChartClass *class;
+
+  GList *node;
+  BaobabChartItem *item;
+  gboolean highlighted;
+
+  priv = BAOBAB_CHART (chart)->priv;
+  class = BAOBAB_CHART_GET_CLASS (chart);
+
+  /* call pre-draw abstract method */
+  if (class->pre_draw)
+    class->pre_draw (chart, cr);
+
+  cairo_save (cr);
+
+  node = priv->first_item;
+  while (node != NULL)
+    {
+      item = (BaobabChartItem *) node->data;
+
+      if ((item->visible) && (gdk_rectangle_intersect (&area, &item->rect, NULL))
+          && (item->depth <= priv->max_depth))
+        {
+          highlighted = (node == priv->highlighted_item);
+
+          class->draw_item (chart, cr, item, highlighted);
+        }
+
+      node = node->next;
+    }
+
+  cairo_restore (cr);
+
+  /* call post-draw abstract method */
+  if (class->post_draw)
+    class->post_draw (chart, cr);
+}
+
+static void
+baobab_chart_update_draw (BaobabChart* chart,
+                          GtkTreePath *path)
+{
+  BaobabChartPrivate *priv;
+  GtkTreePath *root_path = NULL;
+  gint root_depth, node_depth;
+
+  if (!gtk_widget_get_realized ( GTK_WIDGET (chart)))
+    return;
+
+  priv = BAOBAB_CHART (chart)->priv;
+
+  if (priv->root != NULL)
+    {
+      root_path = gtk_tree_row_reference_get_path (priv->root);
+
+      if (root_path == NULL)
+        {
+          gtk_tree_row_reference_free (priv->root);
+          priv->root = NULL;
+        }
+    }
+
+  if (priv->root == NULL)
+    root_path = gtk_tree_path_new_first ();
+
+  root_depth = gtk_tree_path_get_depth (root_path);
+  node_depth = gtk_tree_path_get_depth (path);
+
+  if (((node_depth-root_depth)<=priv->max_depth)&&
+      ((gtk_tree_path_is_ancestor (root_path, path))||
+       (gtk_tree_path_compare (root_path, path) == 0)))
+    {
+      gtk_widget_queue_draw (GTK_WIDGET (chart));
+    }
+
+  gtk_tree_path_free (root_path);
+}
+
+static void
+baobab_chart_row_changed (GtkTreeModel    *model,
+                          GtkTreePath     *path,
+                          GtkTreeIter     *iter,<--- Parameter 'iter' can be declared as pointer to const
+                          gpointer         data)
+{
+  g_return_if_fail (BAOBAB_IS_CHART (data));
+  g_return_if_fail (path != NULL || iter != NULL);
+
+  BAOBAB_CHART (data)->priv->model_changed = TRUE;
+
+  baobab_chart_update_draw (BAOBAB_CHART (data), path);
+}
+
+static void
+baobab_chart_row_inserted (GtkTreeModel    *model,
+                           GtkTreePath     *path,
+                           GtkTreeIter     *iter,<--- Parameter 'iter' can be declared as pointer to const
+                           gpointer         data)
+{
+  g_return_if_fail (BAOBAB_IS_CHART (data));
+  g_return_if_fail (path != NULL || iter != NULL);
+
+  BAOBAB_CHART (data)->priv->model_changed = TRUE;
+
+  baobab_chart_update_draw (BAOBAB_CHART (data), path);
+}
+
+static void
+baobab_chart_row_has_child_toggled (GtkTreeModel    *model,
+                                    GtkTreePath     *path,
+                                    GtkTreeIter     *iter,<--- Parameter 'iter' can be declared as pointer to const
+                                    gpointer         data)
+{
+  g_return_if_fail (BAOBAB_IS_CHART (data));
+  g_return_if_fail (path != NULL || iter != NULL);
+
+  BAOBAB_CHART (data)->priv->model_changed = TRUE;
+
+  baobab_chart_update_draw (BAOBAB_CHART (data), path);
+}
+
+static void
+baobab_chart_row_deleted (GtkTreeModel    *model,
+                          GtkTreePath     *path,
+                          gpointer         data)
+{
+  g_return_if_fail (BAOBAB_IS_CHART (data));
+  g_return_if_fail (path != NULL);
+
+  BAOBAB_CHART (data)->priv->model_changed = TRUE;
+
+  baobab_chart_update_draw (BAOBAB_CHART (data), path);
+
+}
+
+static void
+baobab_chart_rows_reordered (GtkTreeModel    *model,
+                             GtkTreePath     *path,
+                             GtkTreeIter     *iter,<--- Parameter 'iter' can be declared as pointer to const
+                             gint            *new_order,
+                             gpointer         data)
+{
+  g_return_if_fail (BAOBAB_IS_CHART (data));
+  g_return_if_fail (path != NULL || iter != NULL);
+
+  BAOBAB_CHART (data)->priv->model_changed = TRUE;
+
+  baobab_chart_update_draw (BAOBAB_CHART (data), path);
+
+}
+
+static gboolean
+baobab_chart_expose (GtkWidget *chart, cairo_t *cr)
+{
+  BaobabChartPrivate *priv;
+  gint w, h;
+  gdouble p, sx, sy, aux;
+  GtkTreePath *root_path = NULL;
+  GtkTreePath *current_path = NULL;
+  GtkAllocation allocation;
+
+  GdkRectangle area;
+  gdouble x1, y1, x2, y2;
+  cairo_clip_extents (cr, &x1, &y1, &x2, &y2);
+
+  aux = floor (x1);
+  area.x = (int)aux;
+
+  aux = floor (y1);
+  area.y = (int)aux;
+
+  aux = ceil (x2);
+  area.width = (int)aux - area.x;
+
+  aux = ceil (y2);
+  area.height = (int)aux - area.y;
+
+  priv = BAOBAB_CHART (chart)->priv;
+
+  /* the columns are not set we paint nothing */
+  if (priv->name_column == priv->percentage_column)
+    return FALSE;
+
+  /* get a cairo_t */
+  cr = gdk_cairo_create (gtk_widget_get_window (chart));
+
+  cairo_rectangle (cr,
+                   area.x, area.y,
+                   area.width, area.height);
+
+  /* there is no model we can not paint */
+  if ((priv->is_frozen) || (priv->model == NULL))
+    {
+      if (priv->memento != NULL)
+        {
+          w = cairo_image_surface_get_width (priv->memento);
+          h = cairo_image_surface_get_height (priv->memento);
+
+          cairo_clip (cr);
+
+          gtk_widget_get_allocation (GTK_WIDGET (chart), &allocation);
+          if (w > 0 && h > 0 &&
+          !(allocation.width == w && allocation.height == h))
+            {
+              /* minimal available proportion */
+              p = MIN (allocation.width / (1.0 * w),
+                       allocation.height / (1.0 * h));
+
+              sx = (gdouble) (allocation.width - w * p) / 2.0;
+              sy = (gdouble) (allocation.height - h * p) / 2.0;
+
+              cairo_translate (cr, sx, sy);
+              cairo_scale (cr, p, p);
+            }
+
+          cairo_set_source_surface (cr,
+                                    priv->memento,
+                                    0, 0);
+          cairo_paint (cr);
+        }
+    }
+  else
+    {
+      cairo_set_source_rgb (cr, 1, 1, 1);
+      cairo_fill_preserve (cr);
+
+      cairo_clip (cr);
+
+      if (priv->root != NULL)
+        root_path = gtk_tree_row_reference_get_path (priv->root);
+
+      if (root_path == NULL) {
+        root_path = gtk_tree_path_new_first ();
+        priv->root = NULL;
+      }
+
+      /* Check if tree model was modified in any way */
+      if ((priv->model_changed) ||
+           (priv->first_item == NULL))
+        baobab_chart_get_items (chart, root_path);
+      else
+        {
+          /* Check if root was changed */
+          current_path = gtk_tree_model_get_path (priv->model,
+                         &((BaobabChartItem*) priv->first_item->data)->iter);
+
+          if (gtk_tree_path_compare (root_path, current_path) != 0)
+            baobab_chart_get_items (chart, root_path);
+
+          gtk_tree_path_free (current_path);
+        }
+
+      gtk_tree_path_free (root_path);
+
+      baobab_chart_draw (chart, cr, area);
+    }
+
+  return FALSE;
+}
+
+static void
+baobab_chart_interpolate_colors (BaobabChartColor *color,
+                                 BaobabChartColor colora,
+                                 BaobabChartColor colorb,
+                                 gdouble percentage)
+{
+  gdouble diff;
+
+  diff = colora.red - colorb.red;
+  color->red = colora.red-diff*percentage;
+
+  diff = colora.green - colorb.green;
+  color->green = colora.green-diff*percentage;
+
+  diff = colora.blue - colorb.blue;
+  color->blue = colora.blue-diff*percentage;
+}
+
+void
+baobab_chart_get_item_color (BaobabChartColor *color,
+                             gdouble rel_position,
+                             guint depth,
+                             gboolean highlighted)
+{
+  gdouble intensity;
+  gint color_number;
+  gint next_color_number;
+  gdouble maximum;
+  static const BaobabChartColor level_color = {0.83, 0.84, 0.82};
+  static const BaobabChartColor level_color_hl = {0.88, 0.89, 0.87};
+
+  intensity = 1 - (((depth-1)*0.3) / BAOBAB_CHART_MAX_DEPTH);
+
+  if (depth == 0)
+    *color = level_color;
+  else
+    {
+      color_number = (int) (rel_position / (100.0/3.0));
+      next_color_number = (color_number + 1) % 6;
+
+      baobab_chart_interpolate_colors (color,
+                                       baobab_chart_tango_colors[color_number],
+                                       baobab_chart_tango_colors[next_color_number],
+                                       (rel_position - color_number * 100/3) / (100/3));
+      color->red = color->red * intensity;
+      color->green = color->green * intensity;
+      color->blue = color->blue * intensity;
+    }
+
+  if (highlighted)
+    {
+      if (depth == 0)
+        *color = level_color_hl;
+      else
+        {
+          maximum = MAX (color->red,
+                         MAX (color->green,
+                              color->blue));
+          color->red /= maximum;
+          color->green /= maximum;
+          color->blue /= maximum;
+        }
+    }
+}
+
+static gint
+baobab_chart_button_release (GtkWidget *widget,
+                             GdkEventButton *event)
+{
+  BaobabChartPrivate *priv;
+
+  priv = BAOBAB_CHART (widget)->priv;
+
+  if (priv->is_frozen)
+    return TRUE;
+
+  switch (event->button)
+    {
+    case LEFT_BUTTON:
+      /* Enter into a subdir */
+      if (priv->highlighted_item != NULL)
+        g_signal_emit (BAOBAB_CHART (widget),
+                       baobab_chart_signals[ITEM_ACTIVATED],
+                       0, &((BaobabChartItem*) priv->highlighted_item->data)->iter);
+
+      break;
+
+    case MIDDLE_BUTTON:
+      /* Go back to the parent dir */
+      baobab_chart_move_up_root (widget);
+      break;
+    }
+
+  return FALSE;
+}
+
+static gint
+baobab_chart_scroll (GtkWidget *widget,
+                     GdkEventScroll *event)
+{
+  switch (event->direction)
+    {
+    case GDK_SCROLL_LEFT :
+    case GDK_SCROLL_UP :
+      if (baobab_chart_can_zoom_out (widget))
+        baobab_chart_zoom_out (widget);
+      /* change the selected item when zooming */
+      baobab_chart_motion_notify (widget, (GdkEventMotion *)event);
+      break;
+
+    case GDK_SCROLL_RIGHT :
+    case GDK_SCROLL_DOWN :
+      if (baobab_chart_can_zoom_in (widget))
+        baobab_chart_zoom_in (widget);
+      break;
+
+    case GDK_SCROLL_SMOOTH :
+      /* since we don't add GDK_SMOOTH_SCROLL_MASK to received
+         events, this is actually never reached and it's here
+         just to silence compiler warnings */
+      break;
+    }
+
+  return FALSE;
+}
+
+static void
+baobab_chart_set_item_highlight (GtkWidget *chart,
+                                 GList *node,
+                                 gboolean highlighted)
+{
+  BaobabChartItem *item;
+  BaobabChartPrivate *priv;
+
+  if (node == NULL)
+    return;
+
+  item = (BaobabChartItem *) node->data;
+  priv = BAOBAB_CHART (chart)->priv;
+
+  if (highlighted)
+    priv->highlighted_item = node;
+  else
+    priv->highlighted_item = NULL;
+
+  gdk_window_invalidate_rect (gtk_widget_get_window ( GTK_WIDGET (chart)),
+                              &item->rect, TRUE);
+}
+
+static gint
+baobab_chart_motion_notify (GtkWidget *widget,
+                            GdkEventMotion *event)
+{
+  BaobabChartPrivate *priv;
+  BaobabChartClass *class;
+  GList *node;
+  BaobabChartItem *item;
+  gboolean found = FALSE;
+
+  priv = BAOBAB_CHART (widget)->priv;
+  class = BAOBAB_CHART_GET_CLASS (widget);
+
+  /* Check if the pointer is over an item */
+  node = priv->last_item;
+  while (node != NULL)
+    {
+      item = (BaobabChartItem *) node->data;
+
+      if ((item->visible) && (class->is_point_over_item (widget, item, event->x, event->y)))
+        {
+          if (priv->highlighted_item != node)
+            {
+              baobab_chart_set_item_highlight (widget, priv->highlighted_item, FALSE);
+
+              gtk_widget_set_has_tooltip (widget, TRUE);
+              baobab_chart_set_item_highlight (widget, node, TRUE);
+            }
+
+          found = TRUE;
+          break;
+        }
+      node = node->prev;
+    }
+
+  /* If we never found a highlighted item, but there is an old highlighted item,
+     redraw it to turn it off */
+  if (! found)
+    {
+      baobab_chart_set_item_highlight (widget, priv->highlighted_item, FALSE);
+      gtk_widget_set_has_tooltip (widget, FALSE);
+    }
+
+  /* Continue receiving motion notifies */
+  gdk_event_request_motions (event);
+
+  return FALSE;
+}
+
+static gint
+baobab_chart_leave_notify (GtkWidget *widget,
+                           GdkEventCrossing *event)
+{
+  BaobabChartPrivate *priv;
+
+  priv = BAOBAB_CHART (widget)->priv;
+  baobab_chart_set_item_highlight (widget, priv->highlighted_item, FALSE);
+
+  return FALSE;
+}
+
+static inline void
+baobab_chart_connect_signals (GtkWidget *chart,
+                              GtkTreeModel *model)
+{
+  g_signal_connect (model,
+                    "row_changed",
+                    G_CALLBACK (baobab_chart_row_changed),
+                    chart);
+  g_signal_connect (model,
+                    "row_inserted",
+                    G_CALLBACK (baobab_chart_row_inserted),
+                    chart);
+  g_signal_connect (model,
+                    "row_has_child_toggled",
+                    G_CALLBACK (baobab_chart_row_has_child_toggled),
+                    chart);
+  g_signal_connect (model,
+                    "row_deleted",
+                    G_CALLBACK (baobab_chart_row_deleted),
+                    chart);
+  g_signal_connect (model,
+                    "rows_reordered",
+                    G_CALLBACK (baobab_chart_rows_reordered),
+                    chart);
+  g_signal_connect (chart,
+                    "query-tooltip",
+                    G_CALLBACK (baobab_chart_query_tooltip),
+                    chart);
+  g_signal_connect (chart,
+                    "motion-notify-event",
+                    G_CALLBACK (baobab_chart_motion_notify),
+                    chart);
+  g_signal_connect (chart,
+                    "leave-notify-event",
+                    G_CALLBACK (baobab_chart_leave_notify),
+                    chart);
+  g_signal_connect (chart,
+                    "button-release-event",
+                    G_CALLBACK (baobab_chart_button_release),
+                    chart);
+}
+
+static inline void
+baobab_chart_disconnect_signals (GtkWidget *chart,
+                                 GtkTreeModel *model)
+{
+  g_signal_handlers_disconnect_by_func (model,
+                                        baobab_chart_row_changed,
+                                        chart);
+  g_signal_handlers_disconnect_by_func (model,
+                                        baobab_chart_row_inserted,
+                                        chart);
+  g_signal_handlers_disconnect_by_func (model,
+                                        baobab_chart_row_has_child_toggled,
+                                        chart);
+  g_signal_handlers_disconnect_by_func (model,
+                                        baobab_chart_row_deleted,
+                                        chart);
+  g_signal_handlers_disconnect_by_func (model,
+                                        baobab_chart_rows_reordered,
+                                        chart);
+  g_signal_handlers_disconnect_by_func (chart,
+                                        baobab_chart_query_tooltip,
+                                        chart);
+  g_signal_handlers_disconnect_by_func (chart,
+                                        baobab_chart_motion_notify,
+                                        chart);
+  g_signal_handlers_disconnect_by_func (chart,
+                                        baobab_chart_leave_notify,
+                                        chart);
+  g_signal_handlers_disconnect_by_func (chart,
+                                        baobab_chart_button_release,
+                                        chart);
+}
+
+static gboolean
+baobab_chart_query_tooltip (GtkWidget  *widget,
+                            gint        x,
+                            gint        y,
+                            gboolean    keyboard_mode,
+                            GtkTooltip *tooltip,
+                            gpointer    user_data)
+{
+  BaobabChartPrivate *priv;
+  BaobabChartItem *item;
+  char *markup;
+
+  priv = BAOBAB_CHART (widget)->priv;
+
+  if (priv->highlighted_item == NULL)
+    return FALSE;
+
+  item = (BaobabChartItem *) priv->highlighted_item->data;
+
+  if ( (item->name == NULL) || (item->size == NULL) )
+    return FALSE;
+
+  gtk_tooltip_set_tip_area (tooltip, &item->rect);
+
+  markup = g_strconcat (item->name,
+                        "\n",
+                        item->size,
+                        NULL);
+  gtk_tooltip_set_markup (tooltip, markup);
+  g_free (markup);
+
+  return TRUE;
+}
+
+static GdkPixbuf*
+baobab_chart_get_pixbuf (GtkWidget *widget)
+{
+  gint w, h;
+  GdkPixbuf *pixbuf;
+
+  g_return_val_if_fail (BAOBAB_IS_CHART (widget), NULL);
+
+		w = gdk_window_get_width(gtk_widget_get_window(widget));
+		h = gdk_window_get_height(gtk_widget_get_window(widget));
+
+  pixbuf = gdk_pixbuf_get_from_window (
+                                         gtk_widget_get_window (widget),
+                                         0, 0,
+                                         w, h);
+
+  return pixbuf;
+}
+
+/* Public functions start here */
+
+/**
+ * baobab_chart_new:
+ *
+ * Constructor for the baobab_chart class
+ *
+ * Returns: a new #BaobabChart object
+ *
+ **/
+GtkWidget *
+baobab_chart_new ()
+{
+  return g_object_new (BAOBAB_CHART_TYPE, NULL);
+}
+
+/**
+ * baobab_chart_set_model_with_columns:
+ * @chart: the #BaobabChart whose model is going to be set
+ * @model: the #GtkTreeModel which is going to set as the model of
+ * @chart
+ * @name_column: number of column inside @model where the file name is
+ * stored
+ * @size_column: number of column inside @model where the file size is
+ * stored
+ * @info_column: number of column inside @model where the percentage
+ * of disk usage is stored
+ * @percentage_column: number of column inside @model where the disk
+ * usage percentage is stored
+ * @valid_column: number of column inside @model where the flag indicating
+ * if the row data is right or not.
+ * @root: a #GtkTreePath indicating the node of @model which will be
+ * used as root.
+ *
+ * Sets @model as the #GtkTreeModel used by @chart. Indicates the
+ * columns inside @model where the values file name, file
+ * size, file information, disk usage percentage and data correction are stored, and
+ * the node which will be used as the root of @chart.  Once
+ * the model has been successfully set, a redraw of the window is
+ * forced.
+ * This function is intended to be used the first time a #GtkTreeModel
+ * is assigned to @chart, or when the columns containing the needed data
+ * are going to change. In other cases, #baobab_chart_set_model should
+ * be used.
+ * This function does not change the state of the signals from the model, which
+ * is controlled by he #baobab_chart_freeze_updates and the
+ * #baobab_chart_thaw_updates functions.
+ *
+ * Fails if @chart is not a #BaobabChart or if @model is not a
+ * #GtkTreeModel.
+ **/
+void
+baobab_chart_set_model_with_columns (GtkWidget *chart,
+                                     GtkTreeModel *model,
+                                     guint name_column,
+                                     guint size_column,
+                                     guint info_column,
+                                     guint percentage_column,
+                                     guint valid_column,
+                                     GtkTreePath *root)
+{
+  BaobabChartPrivate *priv;
+
+  g_return_if_fail (BAOBAB_IS_CHART (chart));
+  g_return_if_fail (GTK_IS_TREE_MODEL (model));
+
+  priv = BAOBAB_CHART (chart)->priv;
+
+  baobab_chart_set_model (chart, model);
+
+  if (root != NULL)
+    {
+      priv->root = gtk_tree_row_reference_new (model, root);
+      g_object_notify (G_OBJECT (chart), "root");
+    }
+
+  priv->name_column = name_column;
+  priv->size_column = size_column;
+  priv->info_column = info_column;
+  priv->percentage_column = percentage_column;
+  priv->valid_column = valid_column;
+}
+
+/**
+ * baobab_chart_set_model:
+ * @chart: the #BaobabChart whose model is going to be set
+ * @model: the #GtkTreeModel which is going to set as the model of
+ * @chart
+ *
+ * Sets @model as the #GtkTreeModel used by @chart, and takes the needed
+ * data from the columns especified in the last call to
+ * #baobab_chart_set_model_with_colums.
+ * This function does not change the state of the signals from the model, which
+ * is controlled by he #baobab_chart_freeze_updates and the
+ * #baobab_chart_thaw_updates functions.
+ *
+ * Fails if @chart is not a #BaobabChart or if @model is not a
+ * #GtkTreeModel.
+ **/
+void
+baobab_chart_set_model (GtkWidget *chart,
+                             GtkTreeModel *model)
+{
+  BaobabChartPrivate *priv;
+
+  g_return_if_fail (BAOBAB_IS_CHART (chart));
+  g_return_if_fail (GTK_IS_TREE_MODEL (model));
+
+  priv = BAOBAB_CHART (chart)->priv;
+
+  if (model == priv->model)
+    return;
+
+  if (priv->model)
+    {
+      if (! priv->is_frozen)
+        baobab_chart_disconnect_signals (chart,
+                                         priv->model);
+      g_object_unref (priv->model);
+    }
+
+  priv->model = model;
+  g_object_ref (priv->model);
+
+  if (! priv->is_frozen)
+    baobab_chart_connect_signals (chart,
+                                  priv->model);
+
+  if (priv->root)
+    gtk_tree_row_reference_free (priv->root);
+
+  priv->root = NULL;
+
+  g_object_notify (G_OBJECT (chart), "model");
+
+  gtk_widget_queue_draw (chart);
+}
+
+/**
+ * baobab_chart_get_model:
+ * @chart: a #BaobabChart whose model will be returned.
+ *
+ * Returns the #GtkTreeModel which is the model used by @chart.
+ *
+ * Returns: %NULL if @chart is not a #BaobabChart.
+ **/
+GtkTreeModel *
+baobab_chart_get_model (GtkWidget *chart)
+{
+  g_return_val_if_fail (BAOBAB_IS_CHART (chart), NULL);
+
+  return BAOBAB_CHART (chart)->priv->model;
+}
+
+/**
+ * baobab_chart_set_max_depth:
+ * @chart: a #BaobabChart
+ * @max_depth: the new maximum depth to show in the widget.
+ *
+ * Sets the maximum number of nested levels that are going to be show in the
+ * wigdet, and causes a redraw of the widget to show the new maximum
+ * depth. If max_depth is < 1 MAX_DRAWABLE_DEPTH is used.
+ *
+ * Fails if @chart is not a #BaobabChart.
+ **/
+void
+baobab_chart_set_max_depth (GtkWidget *chart,
+                            guint max_depth)
+{
+  BaobabChartPrivate *priv;
+
+  g_return_if_fail (BAOBAB_IS_CHART (chart));
+
+  priv = BAOBAB_CHART (chart)->priv;
+
+  max_depth = MIN (max_depth, BAOBAB_CHART_MAX_DEPTH);
+  max_depth = MAX (max_depth, BAOBAB_CHART_MIN_DEPTH);
+
+  if (max_depth == priv->max_depth)
+    return;
+
+  priv->max_depth = max_depth;
+  g_object_notify (G_OBJECT (chart), "max-depth");
+
+  priv->model_changed = TRUE;
+
+  gtk_widget_queue_draw (chart);
+}
+
+/**
+ * baobab_chart_get_max_depth:
+ * @chart: a #BaobabChart.
+ *
+ * Returns the maximum number of levels that will be show in the
+ * widget.
+ *
+ * Fails if @chart is not a #BaobabChart.
+ **/
+guint
+baobab_chart_get_max_depth (GtkWidget *chart)
+{
+  g_return_val_if_fail (BAOBAB_IS_CHART (chart), 0);
+
+  return BAOBAB_CHART (chart)->priv->max_depth;
+}
+
+/**
+ * baobab_chart_set_root:
+ * @chart: a #BaobabChart
+ * @root: a #GtkTreePath indicating the node which will be used as
+ * the widget root.
+ *
+ * Sets the node pointed by @root as the new root of the widget
+ * @chart.
+ *
+ * Fails if @chart is not a #BaobabChart or if @chart has not
+ * a #GtkTreeModel set.
+ **/
+void
+baobab_chart_set_root (GtkWidget *chart,
+                       GtkTreePath *root)
+{
+  BaobabChartPrivate *priv;
+  GtkTreePath *current_root;
+
+  g_return_if_fail (BAOBAB_IS_CHART (chart));
+
+  priv = BAOBAB_CHART (chart)->priv;
+
+  g_return_if_fail (priv->model != NULL);
+
+  if (priv->root) {
+    /* Check that given root is different from current */
+    current_root = gtk_tree_row_reference_get_path (priv->root);
+    if ( (current_root) && (gtk_tree_path_compare (current_root, root) == 0) )
+      return;
+
+    /* Free current root */
+    gtk_tree_row_reference_free (priv->root);
+  }
+
+  priv->root = gtk_tree_row_reference_new (priv->model, root);
+
+  g_object_notify (G_OBJECT (chart), "root");
+
+  gtk_widget_queue_draw (chart);
+}
+
+/**
+ * baobab_chart_get_root:
+ * @chart: a #BaobabChart.
+ *
+ * Returns a #GtkTreePath pointing to the root of the widget. The
+ * programmer has the responsability to free the used memory once
+ * finished with the returned value. It returns NULL if there is no
+ * root node defined
+ *
+ * Fails if @chart is not a #BaobabChart.
+ **/
+GtkTreePath*
+baobab_chart_get_root (GtkWidget *chart)
+{
+  g_return_val_if_fail (BAOBAB_IS_CHART (chart), NULL);
+
+  if (BAOBAB_CHART (chart)->priv->root)
+    return gtk_tree_row_reference_get_path (BAOBAB_CHART (chart)->priv->root);
+  else
+    return NULL;
+}
+
+/**
+ * baobab_chart_freeze_updates:
+ * @chart: the #BaobabChart whose model signals are going to be frozen.
+ *
+ * Disconnects @chart from the signals emitted by its model, and sets
+ * the window of @chart to a "processing" state, so that the window
+ * ignores changes in the chart's model and mouse events.
+ * In order to connect again the window to the model, a call to
+ * #baobab_chart_thaw_updates must be done.
+ *
+ * Fails if @chart is not a #BaobabChart.
+ **/
+void
+baobab_chart_freeze_updates (GtkWidget *chart)
+{
+  BaobabChartPrivate *priv;
+  cairo_surface_t *surface = NULL;
+  cairo_t *cr = NULL;
+  GdkRectangle area;
+  GtkAllocation allocation;
+
+  g_return_if_fail (BAOBAB_IS_CHART (chart));
+
+  priv = BAOBAB_CHART (chart)->priv;
+
+  if (priv->is_frozen)
+    return;
+
+  if (priv->model)
+    baobab_chart_disconnect_signals (chart,
+                                     priv->model);
+
+  gtk_widget_get_allocation (GTK_WIDGET (chart), &allocation);
+  surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
+                                        allocation.width,
+                                        allocation.height);
+
+  if (cairo_surface_status (surface) == CAIRO_STATUS_SUCCESS)
+    {
+      cr = cairo_create (surface);
+
+      area.x = 0;
+      area.y = 0;
+      area.width = allocation.width;
+      area.height = allocation.height;
+      baobab_chart_draw (chart, cr, area);
+
+      cairo_rectangle (cr,
+                       0, 0,
+                       allocation.width,
+                       allocation.height);
+
+      cairo_set_source_rgba (cr, 0.93, 0.93, 0.93, 0.5);  /* tango: eeeeec */
+      cairo_fill_preserve (cr);
+
+      cairo_clip (cr);
+
+      priv->memento = surface;
+
+      cairo_destroy (cr);
+    }
+
+  priv->is_frozen = TRUE;
+
+  gtk_widget_queue_draw (chart);
+}
+
+/**
+ * baobab_chart_thaw_updates:
+ * @chart: the #BaobabChart whose model signals are frozen.
+ *
+ * Reconnects @chart to the signals emitted by its model, which
+ * were disconnected through a call to #baobab_chart_freeze_updates.
+ * Takes the window out of its "processing" state and forces a redraw
+ * of the widget.
+ *
+ * Fails if @chart is not a #BaobabChart.
+ **/
+void
+baobab_chart_thaw_updates (GtkWidget *chart)
+{
+  BaobabChartPrivate *priv;
+
+  g_return_if_fail (BAOBAB_IS_CHART (chart));
+
+  priv = BAOBAB_CHART (chart)->priv;
+
+  if (priv->is_frozen)
+    {
+      if (priv->model)
+        baobab_chart_connect_signals (chart,
+                                      priv->model);
+
+      if (priv->memento)
+        {
+          cairo_surface_destroy (priv->memento);
+          priv->memento = NULL;
+        }
+
+      priv->is_frozen = FALSE;
+
+      priv->model_changed = TRUE;
+      gtk_widget_queue_draw (chart);
+    }
+}
+
+/**
+ * baobab_chart_zoom_in:
+ * @chart: the #BaobabChart requested to zoom in.
+ *
+ * Zooms in the chart by decreasing its maximun depth.
+ *
+ * Fails if @chart is not a #BaobabChart.
+ **/
+void
+baobab_chart_zoom_in (GtkWidget *chart)
+{
+  BaobabChartPrivate *priv;
+  BaobabChartClass *class;
+  guint new_max_depth;
+
+  g_return_if_fail (BAOBAB_IS_CHART (chart));
+
+  priv = BAOBAB_CHART (chart)->priv;
+  class = BAOBAB_CHART_GET_CLASS (chart);
+
+  if (class->can_zoom_in != NULL)
+    new_max_depth = class->can_zoom_in (chart);
+  else
+    new_max_depth = priv->max_depth - 1;
+
+  baobab_chart_set_max_depth (chart, new_max_depth);
+}
+
+/**
+ * baobab_chart_zoom_out:
+ * @chart: the #BaobabChart requested to zoom out.
+ *
+ * Zooms out the chart by increasing its maximun depth.
+ *
+ * Fails if @chart is not a #BaobabChart.
+ **/
+void
+baobab_chart_zoom_out (GtkWidget *chart)
+{
+  g_return_if_fail (BAOBAB_IS_CHART (chart));
+
+  baobab_chart_set_max_depth (chart,
+                              baobab_chart_get_max_depth (chart) + 1);
+}
+
+/**
+ * baobab_chart_move_up_root:
+ * @chart: the #BaobabChart whose root is requested to move up one level.
+ *
+ * Move root to the inmediate parent of the current root item of @chart.
+ *
+ * Fails if @chart is not a #BaobabChart.
+ **/
+void
+baobab_chart_move_up_root (GtkWidget *chart)
+{
+  BaobabChartPrivate *priv;
+
+  GtkTreeIter parent_iter;
+  GtkTreePath *path;
+  GtkTreeIter root_iter;
+
+  gint valid;
+  GtkTreePath *parent_path;
+
+  g_return_if_fail (BAOBAB_IS_CHART (chart));
+
+  priv = BAOBAB_CHART (chart)->priv;
+
+  if (priv->root == NULL)
+    return;
+
+  path = gtk_tree_row_reference_get_path (priv->root);
+
+  if (path != NULL)
+    gtk_tree_model_get_iter (priv->model, &root_iter, path);
+  else
+    return;
+
+  if (gtk_tree_model_iter_parent (priv->model, &parent_iter, &root_iter))
+    {
+      gtk_tree_model_get (priv->model, &parent_iter, priv->valid_column,
+                          &valid, -1);
+
+      if (valid == -1)
+        return;
+
+      gtk_tree_row_reference_free (priv->root);
+      parent_path = gtk_tree_model_get_path (priv->model, &parent_iter);
+      priv->root = gtk_tree_row_reference_new (priv->model, parent_path);
+      gtk_tree_path_free (parent_path);
+
+      g_signal_emit (BAOBAB_CHART (chart),
+                     baobab_chart_signals[ITEM_ACTIVATED],
+                     0, &parent_iter);
+
+      gtk_widget_queue_draw (chart);
+    }
+
+  gtk_tree_path_free (path);
+}
+
+/**
+ * baobab_chart_save_snapshot:
+ * @chart: the #BaobabChart requested to be exported to image.
+ *
+ * Opens a dialog to allow saving the current chart's image as a PNG, JPEG or
+ * BMP image.
+ *
+ * Fails if @chart is not a #BaobabChart.
+ **/
+void
+baobab_chart_save_snapshot (GtkWidget *chart)
+{
+  BaobabChartPrivate *priv;
+
+  GdkPixbuf *pixbuf;
+
+  GtkWidget *fs_dlg;
+  GtkWidget *vbox;
+  GtkWidget *hbox;
+  GtkWidget *label;
+  GtkWidget *opt_menu;
+  gchar *sel_type;
+  gchar *filename;
+  gchar *def_filename;
+
+  BaobabChartItem *item;
+
+  g_return_if_fail (BAOBAB_IS_CHART (chart));
+
+  while (gtk_events_pending ())
+    gtk_main_iteration ();
+
+  /* Get the chart's pixbuf */
+  pixbuf = baobab_chart_get_pixbuf (chart);
+  if (pixbuf == NULL)
+    {
+      GtkWidget *dialog;
+      dialog = gtk_message_dialog_new (NULL,
+                                       GTK_DIALOG_DESTROY_WITH_PARENT,
+                                       GTK_MESSAGE_ERROR,
+                                       GTK_BUTTONS_OK,
+                                       _("Cannot create pixbuf image!"));
+      gtk_dialog_run (GTK_DIALOG (dialog));
+      gtk_widget_destroy (dialog);
+
+      return;
+    }
+
+  priv = BAOBAB_CHART (chart)->priv;
+
+  /* Popup the File chooser dialog */
+  fs_dlg = gtk_file_chooser_dialog_new (_("Save Snapshot"),
+                                        NULL,
+                                        GTK_FILE_CHOOSER_ACTION_SAVE,
+                                        "gtk-cancel",
+                                        GTK_RESPONSE_CANCEL,
+                                        "gtk-save",
+                                        GTK_RESPONSE_ACCEPT, NULL);
+
+  item = (BaobabChartItem *) priv->first_item->data;
+  def_filename = g_strdup_printf (SNAPSHOT_DEF_FILENAME_FORMAT, item->name);
+
+  gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (fs_dlg), def_filename);
+  g_free (def_filename);
+
+  gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (fs_dlg),
+                                       g_get_home_dir ());
+
+  gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (fs_dlg), TRUE);
+
+  /* extra widget */
+  vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
+  gtk_container_set_border_width (GTK_CONTAINER (vbox), 0);
+  gtk_file_chooser_set_extra_widget (GTK_FILE_CHOOSER (fs_dlg), vbox);
+
+  hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 6);
+
+  label = gtk_label_new_with_mnemonic (_("_Image type:"));
+  gtk_box_pack_start (GTK_BOX (hbox),
+                      label,
+                      FALSE, FALSE, 0);
+
+  opt_menu = gtk_combo_box_text_new ();
+  gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (opt_menu), "png");
+  gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (opt_menu), "jpeg");
+  gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (opt_menu), "bmp");
+  gtk_combo_box_set_active (GTK_COMBO_BOX (opt_menu), 0);
+  gtk_box_pack_start (GTK_BOX (hbox), opt_menu, TRUE, TRUE, 0);
+
+  gtk_label_set_mnemonic_widget (GTK_LABEL (label), opt_menu);
+  gtk_widget_show_all (vbox);
+
+  if (gtk_dialog_run (GTK_DIALOG (fs_dlg)) == GTK_RESPONSE_ACCEPT)
+    {
+      filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (fs_dlg));
+      sel_type = gtk_combo_box_text_get_active_text (GTK_COMBO_BOX_TEXT (opt_menu));
+      if (! g_str_has_suffix (filename, sel_type))
+        {
+          gchar *tmp;
+          tmp = filename;
+          filename = g_strjoin (".", filename, sel_type, NULL);
+          g_free (tmp);
+        }
+      gdk_pixbuf_save (pixbuf, filename, sel_type, NULL, NULL);
+
+      g_free (filename);
+      g_free (sel_type);
+    }
+
+  gtk_widget_destroy (fs_dlg);
+  g_object_unref (pixbuf);
+}
+
+/**
+ * baobab_chart_is_frozen:
+ * @chart: the #BaobabChart to ask if frozen.
+ *
+ * Returns a boolean telling whether the chart is in a frozen state, meanning
+ * that no actions should be taken uppon it.
+ *
+ * Fails if @chart is not a #BaobabChart.
+ **/
+gboolean
+baobab_chart_is_frozen (GtkWidget *chart)
+{
+  BaobabChartPrivate *priv;
+
+  g_return_val_if_fail (BAOBAB_IS_CHART (chart), FALSE);
+
+  priv = BAOBAB_CHART (chart)->priv;
+  return priv->is_frozen;
+}
+
+/**
+ * baobab_chart_is_frozen:
+ * @chart: the #BaobabChart to obtain the highlighted it from.
+ *
+ * Returns a BaobabChartItem corresponding to the item that currently has mouse
+ * pointer over, or NULL if no item is highlighted.
+ *
+ * Fails if @chart is not a #BaobabChart.
+ **/
+BaobabChartItem *
+baobab_chart_get_highlighted_item (GtkWidget *chart)
+{
+  BaobabChartPrivate *priv;
+
+  g_return_val_if_fail (BAOBAB_IS_CHART (chart), NULL);
+
+  priv = BAOBAB_CHART (chart)->priv;
+  return (priv->highlighted_item ?
+    (BaobabChartItem *) priv->highlighted_item->data : NULL);
+}
+
+/**
+ * baobab_chart_can_zoom_in:
+ * @chart: the #BaobabChart to ask if can be zoomed in.
+ *
+ * Returns a boolean telling whether the chart can be zoomed in, given its current
+ * visualization conditions.
+ *
+ * Fails if @chart is not a #BaobabChart.
+ **/
+gboolean
+baobab_chart_can_zoom_in (GtkWidget *chart)
+{
+  BaobabChartPrivate *priv;
+  BaobabChartClass *class;
+
+  g_return_val_if_fail (BAOBAB_IS_CHART (chart), FALSE);
+
+  priv = BAOBAB_CHART (chart)->priv;
+  class = BAOBAB_CHART_GET_CLASS (chart);
+
+  if (class->can_zoom_in != NULL)
+    return class->can_zoom_in (chart) > 0;
+  else
+    return priv->max_depth > 1;
+}
+
+/**
+ * baobab_chart_can_zoom_out:
+ * @chart: the #BaobabChart to ask if can be zoomed out.
+ *
+ * Returns a boolean telling whether the chart can be zoomed out, given its current
+ * visualization conditions.
+ *
+ * Fails if @chart is not a #BaobabChart.
+ **/
+gboolean
+baobab_chart_can_zoom_out (GtkWidget *chart)
+{
+  BaobabChartPrivate *priv;
+  BaobabChartClass *class;
+
+  g_return_val_if_fail (BAOBAB_IS_CHART (chart), FALSE);
+
+  priv = BAOBAB_CHART (chart)->priv;
+  class = BAOBAB_CHART_GET_CLASS (chart);
+
+  if (class->can_zoom_out != NULL)
+    return class->can_zoom_out (chart) > 0;
+  else
+    return (priv->max_depth < BAOBAB_CHART_MAX_DEPTH);
+}
+
+ +
+ +
+ + diff --git a/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/10.html b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/10.html new file mode 100644 index 00000000..3f5494a4 --- /dev/null +++ b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/10.html @@ -0,0 +1,3385 @@ + + + + + + Cppcheck - HTML report - mate-utils + + + + + +
+ + + +
+
   1
+   2
+   3
+   4
+   5
+   6
+   7
+   8
+   9
+  10
+  11
+  12
+  13
+  14
+  15
+  16
+  17
+  18
+  19
+  20
+  21
+  22
+  23
+  24
+  25
+  26
+  27
+  28
+  29
+  30
+  31
+  32
+  33
+  34
+  35
+  36
+  37
+  38
+  39
+  40
+  41
+  42
+  43
+  44
+  45
+  46
+  47
+  48
+  49
+  50
+  51
+  52
+  53
+  54
+  55
+  56
+  57
+  58
+  59
+  60
+  61
+  62
+  63
+  64
+  65
+  66
+  67
+  68
+  69
+  70
+  71
+  72
+  73
+  74
+  75
+  76
+  77
+  78
+  79
+  80
+  81
+  82
+  83
+  84
+  85
+  86
+  87
+  88
+  89
+  90
+  91
+  92
+  93
+  94
+  95
+  96
+  97
+  98
+  99
+ 100
+ 101
+ 102
+ 103
+ 104
+ 105
+ 106
+ 107
+ 108
+ 109
+ 110
+ 111
+ 112
+ 113
+ 114
+ 115
+ 116
+ 117
+ 118
+ 119
+ 120
+ 121
+ 122
+ 123
+ 124
+ 125
+ 126
+ 127
+ 128
+ 129
+ 130
+ 131
+ 132
+ 133
+ 134
+ 135
+ 136
+ 137
+ 138
+ 139
+ 140
+ 141
+ 142
+ 143
+ 144
+ 145
+ 146
+ 147
+ 148
+ 149
+ 150
+ 151
+ 152
+ 153
+ 154
+ 155
+ 156
+ 157
+ 158
+ 159
+ 160
+ 161
+ 162
+ 163
+ 164
+ 165
+ 166
+ 167
+ 168
+ 169
+ 170
+ 171
+ 172
+ 173
+ 174
+ 175
+ 176
+ 177
+ 178
+ 179
+ 180
+ 181
+ 182
+ 183
+ 184
+ 185
+ 186
+ 187
+ 188
+ 189
+ 190
+ 191
+ 192
+ 193
+ 194
+ 195
+ 196
+ 197
+ 198
+ 199
+ 200
+ 201
+ 202
+ 203
+ 204
+ 205
+ 206
+ 207
+ 208
+ 209
+ 210
+ 211
+ 212
+ 213
+ 214
+ 215
+ 216
+ 217
+ 218
+ 219
+ 220
+ 221
+ 222
+ 223
+ 224
+ 225
+ 226
+ 227
+ 228
+ 229
+ 230
+ 231
+ 232
+ 233
+ 234
+ 235
+ 236
+ 237
+ 238
+ 239
+ 240
+ 241
+ 242
+ 243
+ 244
+ 245
+ 246
+ 247
+ 248
+ 249
+ 250
+ 251
+ 252
+ 253
+ 254
+ 255
+ 256
+ 257
+ 258
+ 259
+ 260
+ 261
+ 262
+ 263
+ 264
+ 265
+ 266
+ 267
+ 268
+ 269
+ 270
+ 271
+ 272
+ 273
+ 274
+ 275
+ 276
+ 277
+ 278
+ 279
+ 280
+ 281
+ 282
+ 283
+ 284
+ 285
+ 286
+ 287
+ 288
+ 289
+ 290
+ 291
+ 292
+ 293
+ 294
+ 295
+ 296
+ 297
+ 298
+ 299
+ 300
+ 301
+ 302
+ 303
+ 304
+ 305
+ 306
+ 307
+ 308
+ 309
+ 310
+ 311
+ 312
+ 313
+ 314
+ 315
+ 316
+ 317
+ 318
+ 319
+ 320
+ 321
+ 322
+ 323
+ 324
+ 325
+ 326
+ 327
+ 328
+ 329
+ 330
+ 331
+ 332
+ 333
+ 334
+ 335
+ 336
+ 337
+ 338
+ 339
+ 340
+ 341
+ 342
+ 343
+ 344
+ 345
+ 346
+ 347
+ 348
+ 349
+ 350
+ 351
+ 352
+ 353
+ 354
+ 355
+ 356
+ 357
+ 358
+ 359
+ 360
+ 361
+ 362
+ 363
+ 364
+ 365
+ 366
+ 367
+ 368
+ 369
+ 370
+ 371
+ 372
+ 373
+ 374
+ 375
+ 376
+ 377
+ 378
+ 379
+ 380
+ 381
+ 382
+ 383
+ 384
+ 385
+ 386
+ 387
+ 388
+ 389
+ 390
+ 391
+ 392
+ 393
+ 394
+ 395
+ 396
+ 397
+ 398
+ 399
+ 400
+ 401
+ 402
+ 403
+ 404
+ 405
+ 406
+ 407
+ 408
+ 409
+ 410
+ 411
+ 412
+ 413
+ 414
+ 415
+ 416
+ 417
+ 418
+ 419
+ 420
+ 421
+ 422
+ 423
+ 424
+ 425
+ 426
+ 427
+ 428
+ 429
+ 430
+ 431
+ 432
+ 433
+ 434
+ 435
+ 436
+ 437
+ 438
+ 439
+ 440
+ 441
+ 442
+ 443
+ 444
+ 445
+ 446
+ 447
+ 448
+ 449
+ 450
+ 451
+ 452
+ 453
+ 454
+ 455
+ 456
+ 457
+ 458
+ 459
+ 460
+ 461
+ 462
+ 463
+ 464
+ 465
+ 466
+ 467
+ 468
+ 469
+ 470
+ 471
+ 472
+ 473
+ 474
+ 475
+ 476
+ 477
+ 478
+ 479
+ 480
+ 481
+ 482
+ 483
+ 484
+ 485
+ 486
+ 487
+ 488
+ 489
+ 490
+ 491
+ 492
+ 493
+ 494
+ 495
+ 496
+ 497
+ 498
+ 499
+ 500
+ 501
+ 502
+ 503
+ 504
+ 505
+ 506
+ 507
+ 508
+ 509
+ 510
+ 511
+ 512
+ 513
+ 514
+ 515
+ 516
+ 517
+ 518
+ 519
+ 520
+ 521
+ 522
+ 523
+ 524
+ 525
+ 526
+ 527
+ 528
+ 529
+ 530
+ 531
+ 532
+ 533
+ 534
+ 535
+ 536
+ 537
+ 538
+ 539
+ 540
+ 541
+ 542
+ 543
+ 544
+ 545
+ 546
+ 547
+ 548
+ 549
+ 550
+ 551
+ 552
+ 553
+ 554
+ 555
+ 556
+ 557
+ 558
+ 559
+ 560
+ 561
+ 562
+ 563
+ 564
+ 565
+ 566
+ 567
+ 568
+ 569
+ 570
+ 571
+ 572
+ 573
+ 574
+ 575
+ 576
+ 577
+ 578
+ 579
+ 580
+ 581
+ 582
+ 583
+ 584
+ 585
+ 586
+ 587
+ 588
+ 589
+ 590
+ 591
+ 592
+ 593
+ 594
+ 595
+ 596
+ 597
+ 598
+ 599
+ 600
+ 601
+ 602
+ 603
+ 604
+ 605
+ 606
+ 607
+ 608
+ 609
+ 610
+ 611
+ 612
+ 613
+ 614
+ 615
+ 616
+ 617
+ 618
+ 619
+ 620
+ 621
+ 622
+ 623
+ 624
+ 625
+ 626
+ 627
+ 628
+ 629
+ 630
+ 631
+ 632
+ 633
+ 634
+ 635
+ 636
+ 637
+ 638
+ 639
+ 640
+ 641
+ 642
+ 643
+ 644
+ 645
+ 646
+ 647
+ 648
+ 649
+ 650
+ 651
+ 652
+ 653
+ 654
+ 655
+ 656
+ 657
+ 658
+ 659
+ 660
+ 661
+ 662
+ 663
+ 664
+ 665
+ 666
+ 667
+ 668
+ 669
+ 670
+ 671
+ 672
+ 673
+ 674
+ 675
+ 676
+ 677
+ 678
+ 679
+ 680
+ 681
+ 682
+ 683
+ 684
+ 685
+ 686
+ 687
+ 688
+ 689
+ 690
+ 691
+ 692
+ 693
+ 694
+ 695
+ 696
+ 697
+ 698
+ 699
+ 700
+ 701
+ 702
+ 703
+ 704
+ 705
+ 706
+ 707
+ 708
+ 709
+ 710
+ 711
+ 712
+ 713
+ 714
+ 715
+ 716
+ 717
+ 718
+ 719
+ 720
+ 721
+ 722
+ 723
+ 724
+ 725
+ 726
+ 727
+ 728
+ 729
+ 730
+ 731
+ 732
+ 733
+ 734
+ 735
+ 736
+ 737
+ 738
+ 739
+ 740
+ 741
+ 742
+ 743
+ 744
+ 745
+ 746
+ 747
+ 748
+ 749
+ 750
+ 751
+ 752
+ 753
+ 754
+ 755
+ 756
+ 757
+ 758
+ 759
+ 760
+ 761
+ 762
+ 763
+ 764
+ 765
+ 766
+ 767
+ 768
+ 769
+ 770
+ 771
+ 772
+ 773
+ 774
+ 775
+ 776
+ 777
+ 778
+ 779
+ 780
+ 781
+ 782
+ 783
+ 784
+ 785
+ 786
+ 787
+ 788
+ 789
+ 790
+ 791
+ 792
+ 793
+ 794
+ 795
+ 796
+ 797
+ 798
+ 799
+ 800
+ 801
+ 802
+ 803
+ 804
+ 805
+ 806
+ 807
+ 808
+ 809
+ 810
+ 811
+ 812
+ 813
+ 814
+ 815
+ 816
+ 817
+ 818
+ 819
+ 820
+ 821
+ 822
+ 823
+ 824
+ 825
+ 826
+ 827
+ 828
+ 829
+ 830
+ 831
+ 832
+ 833
+ 834
+ 835
+ 836
+ 837
+ 838
+ 839
+ 840
+ 841
+ 842
+ 843
+ 844
+ 845
+ 846
+ 847
+ 848
+ 849
+ 850
+ 851
+ 852
+ 853
+ 854
+ 855
+ 856
+ 857
+ 858
+ 859
+ 860
+ 861
+ 862
+ 863
+ 864
+ 865
+ 866
+ 867
+ 868
+ 869
+ 870
+ 871
+ 872
+ 873
+ 874
+ 875
+ 876
+ 877
+ 878
+ 879
+ 880
+ 881
+ 882
+ 883
+ 884
+ 885
+ 886
+ 887
+ 888
+ 889
+ 890
+ 891
+ 892
+ 893
+ 894
+ 895
+ 896
+ 897
+ 898
+ 899
+ 900
+ 901
+ 902
+ 903
+ 904
+ 905
+ 906
+ 907
+ 908
+ 909
+ 910
+ 911
+ 912
+ 913
+ 914
+ 915
+ 916
+ 917
+ 918
+ 919
+ 920
+ 921
+ 922
+ 923
+ 924
+ 925
+ 926
+ 927
+ 928
+ 929
+ 930
+ 931
+ 932
+ 933
+ 934
+ 935
+ 936
+ 937
+ 938
+ 939
+ 940
+ 941
+ 942
+ 943
+ 944
+ 945
+ 946
+ 947
+ 948
+ 949
+ 950
+ 951
+ 952
+ 953
+ 954
+ 955
+ 956
+ 957
+ 958
+ 959
+ 960
+ 961
+ 962
+ 963
+ 964
+ 965
+ 966
+ 967
+ 968
+ 969
+ 970
+ 971
+ 972
+ 973
+ 974
+ 975
+ 976
+ 977
+ 978
+ 979
+ 980
+ 981
+ 982
+ 983
+ 984
+ 985
+ 986
+ 987
+ 988
+ 989
+ 990
+ 991
+ 992
+ 993
+ 994
+ 995
+ 996
+ 997
+ 998
+ 999
+1000
+1001
+1002
+1003
+1004
+1005
+1006
+1007
+1008
+1009
+1010
+1011
+1012
+1013
+1014
+1015
+1016
+1017
+1018
+1019
+1020
+1021
+1022
+1023
+1024
+1025
+1026
+1027
+1028
+1029
+1030
+1031
+1032
+1033
+1034
+1035
+1036
+1037
+1038
+1039
+1040
+1041
+1042
+1043
+1044
+1045
+1046
+1047
+1048
+1049
+1050
+1051
+1052
+1053
+1054
+1055
+1056
+1057
+1058
+1059
+1060
+1061
+1062
+1063
+1064
+1065
+1066
+1067
+1068
+1069
+1070
+1071
+1072
+1073
+1074
+1075
+1076
+1077
+1078
+1079
+1080
+1081
+1082
+1083
+1084
+1085
+1086
+1087
+1088
+1089
+1090
+1091
+1092
+1093
+1094
+1095
+1096
+1097
+1098
+1099
+1100
+1101
+1102
+1103
+1104
+1105
+1106
+1107
+1108
+1109
+1110
+1111
+1112
+1113
+1114
+1115
+1116
+1117
+1118
+1119
+1120
+1121
+1122
+1123
+1124
+1125
+1126
+1127
+1128
+1129
+1130
+1131
+1132
+1133
+1134
+1135
+1136
+1137
+1138
+1139
+1140
+1141
+1142
+1143
+1144
+1145
+1146
+1147
+1148
+1149
+1150
+1151
+1152
+1153
+1154
+1155
+1156
+1157
+1158
+1159
+1160
+1161
+1162
+1163
+1164
+1165
+1166
+1167
+1168
+1169
+1170
+1171
+1172
+1173
+1174
+1175
+1176
+1177
+1178
+1179
+1180
+1181
+1182
+1183
+1184
+1185
+1186
+1187
+1188
+1189
+1190
+1191
+1192
+1193
+1194
+1195
+1196
+1197
+1198
+1199
+1200
+1201
+1202
+1203
+1204
+1205
+1206
+1207
+1208
+1209
+1210
+1211
+1212
+1213
+1214
+1215
+1216
+1217
+1218
+1219
+1220
+1221
+1222
+1223
+1224
+1225
+1226
+1227
+1228
+1229
+1230
+1231
+1232
+1233
+1234
+1235
+1236
+1237
+1238
+1239
+1240
+1241
+1242
+1243
+1244
+1245
+1246
+1247
+1248
+1249
+1250
+1251
+1252
+1253
+1254
+1255
+1256
+1257
+1258
+1259
+1260
+1261
+1262
+1263
+1264
+1265
+1266
+1267
+1268
+1269
+1270
+1271
+1272
+1273
+1274
+1275
+1276
+1277
+1278
+1279
+1280
+1281
+1282
+1283
+1284
+1285
+1286
+1287
+1288
+1289
+1290
+1291
+1292
+1293
+1294
+1295
+1296
+1297
+1298
+1299
+1300
+1301
+1302
+1303
+1304
+1305
+1306
+1307
+1308
+1309
+1310
+1311
+1312
+1313
+1314
+1315
+1316
+1317
+1318
+1319
+1320
+1321
+1322
+1323
+1324
+1325
+1326
+1327
+1328
+1329
+1330
+1331
+1332
+1333
+1334
+1335
+1336
+1337
+1338
+1339
+1340
+1341
+1342
+1343
+1344
+1345
+1346
+1347
+1348
+1349
+1350
+1351
+1352
+1353
+1354
+1355
+1356
+1357
+1358
+1359
+1360
+1361
+1362
+1363
+1364
+1365
+1366
+1367
+1368
+1369
+1370
+1371
+1372
+1373
+1374
+1375
+1376
+1377
+1378
+1379
+1380
+1381
+1382
+1383
+1384
+1385
+1386
+1387
+1388
+1389
+1390
+1391
+1392
+1393
+1394
+1395
+1396
+1397
+1398
+1399
+1400
+1401
+1402
+1403
+1404
+1405
+1406
+1407
+1408
+1409
+1410
+1411
+1412
+1413
+1414
+1415
+1416
+1417
+1418
+1419
+1420
+1421
+1422
+1423
+1424
+1425
+1426
+1427
+1428
+1429
+1430
+1431
+1432
+1433
+1434
+1435
+1436
+1437
+1438
+1439
+1440
+1441
+1442
+1443
+1444
+1445
+1446
+1447
+1448
+1449
+1450
+1451
+1452
+1453
+1454
+1455
+1456
+1457
+1458
+1459
+1460
+1461
+1462
+1463
+1464
+1465
+1466
+1467
+1468
+1469
+1470
+1471
+1472
+1473
+1474
+1475
+1476
+1477
+1478
+1479
+1480
+1481
+1482
+1483
+1484
+1485
+1486
+1487
+1488
+1489
+1490
+1491
+1492
+1493
+1494
+1495
+1496
+1497
+1498
+1499
+1500
+1501
+1502
+1503
+1504
+1505
+1506
+1507
+1508
+1509
+1510
+1511
+1512
+1513
+1514
+1515
+1516
+1517
+1518
+1519
+1520
+1521
+1522
+1523
+1524
+1525
+1526
+1527
+1528
+1529
+1530
+1531
+1532
+1533
+1534
+1535
+1536
+1537
+1538
/* eggdesktopfile.c - Freedesktop.Org Desktop Files
+ * Copyright (C) 2007 Novell, Inc.
+ *
+ * Based on mate-desktop-item.c
+ * Copyright (C) 1999, 2000 Red Hat Inc.
+ * Copyright (C) 2001 George Lebl
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; see the file COPYING.LIB. If not,
+ * write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "eggdesktopfile.h"
+
+#include <string.h>
+#include <unistd.h>
+
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+
+#if defined(GDK_WINDOWING_X11) || defined(HAVE_X11)
+#include <gdk/gdkx.h>
+#endif
+
+struct EggDesktopFile {
+  GKeyFile           *key_file;
+  char               *source;
+
+  char               *name, *icon;
+  EggDesktopFileType  type;
+  char                document_code;
+};
+
+/**
+ * egg_desktop_file_new:
+ * @desktop_file_path: path to a Freedesktop-style Desktop file
+ * @error: error pointer
+ *
+ * Creates a new #EggDesktopFile for @desktop_file.
+ *
+ * Return value: the new #EggDesktopFile, or %NULL on error.
+ **/
+EggDesktopFile *
+egg_desktop_file_new (const char *desktop_file_path, GError **error)
+{
+  GKeyFile *key_file;
+
+  key_file = g_key_file_new ();
+  if (!g_key_file_load_from_file (key_file, desktop_file_path, 0, error))
+    {
+      g_key_file_free (key_file);
+      return NULL;
+    }
+
+  return egg_desktop_file_new_from_key_file (key_file, desktop_file_path,
+					     error);
+}
+
+/**
+ * egg_desktop_file_new_from_data_dirs:
+ * @desktop_file_path: relative path to a Freedesktop-style Desktop file
+ * @error: error pointer
+ *
+ * Looks for @desktop_file_path in the paths returned from
+ * g_get_user_data_dir() and g_get_system_data_dirs(), and creates
+ * a new #EggDesktopFile from it.
+ *
+ * Return value: the new #EggDesktopFile, or %NULL on error.
+ **/
+EggDesktopFile *
+egg_desktop_file_new_from_data_dirs (const char  *desktop_file_path,
+				     GError     **error)
+{
+  EggDesktopFile *desktop_file;
+  GKeyFile *key_file;
+  char *full_path;
+
+  key_file = g_key_file_new ();
+  if (!g_key_file_load_from_data_dirs (key_file, desktop_file_path,
+				       &full_path, 0, error))
+    {
+      g_key_file_free (key_file);
+      return NULL;
+    }
+
+  desktop_file = egg_desktop_file_new_from_key_file (key_file,
+						     full_path,
+						     error);
+  g_free (full_path);
+  return desktop_file;
+}
+
+/**
+ * egg_desktop_file_new_from_dirs:
+ * @desktop_file_path: relative path to a Freedesktop-style Desktop file
+ * @search_dirs: NULL-terminated array of directories to search
+ * @error: error pointer
+ *
+ * Looks for @desktop_file_path in the paths returned from
+ * g_get_user_data_dir() and g_get_system_data_dirs(), and creates
+ * a new #EggDesktopFile from it.
+ *
+ * Return value: the new #EggDesktopFile, or %NULL on error.
+ **/
+EggDesktopFile *
+egg_desktop_file_new_from_dirs (const char  *desktop_file_path,
+				const char **search_dirs,
+				GError     **error)
+{
+  EggDesktopFile *desktop_file;
+  GKeyFile *key_file;
+  char *full_path;
+
+  key_file = g_key_file_new ();
+  if (!g_key_file_load_from_dirs (key_file, desktop_file_path, search_dirs,
+				  &full_path, 0, error))
+    {
+      g_key_file_free (key_file);
+      return NULL;
+    }
+
+  desktop_file = egg_desktop_file_new_from_key_file (key_file,
+						     full_path,
+						     error);
+  g_free (full_path);
+  return desktop_file;
+}
+
+/**
+ * egg_desktop_file_new_from_key_file:
+ * @key_file: a #GKeyFile representing a desktop file
+ * @source: the path or URI that @key_file was loaded from, or %NULL
+ * @error: error pointer
+ *
+ * Creates a new #EggDesktopFile for @key_file. Assumes ownership of
+ * @key_file (on success or failure); you should consider @key_file to
+ * be freed after calling this function.
+ *
+ * Return value: the new #EggDesktopFile, or %NULL on error.
+ **/
+EggDesktopFile *
+egg_desktop_file_new_from_key_file (GKeyFile    *key_file,
+				    const char  *source,
+				    GError     **error)
+{
+  EggDesktopFile *desktop_file;
+  char *version, *type;
+
+  if (!g_key_file_has_group (key_file, EGG_DESKTOP_FILE_GROUP))
+    {
+      g_set_error (error, EGG_DESKTOP_FILE_ERROR,
+		   EGG_DESKTOP_FILE_ERROR_INVALID,
+		   _("File is not a valid .desktop file"));
+      g_key_file_free (key_file);
+      return NULL;
+    }
+
+  version = g_key_file_get_value (key_file, EGG_DESKTOP_FILE_GROUP,
+				  EGG_DESKTOP_FILE_KEY_VERSION,
+				  NULL);
+  if (version)
+    {
+      double version_num;
+      char *end;
+
+      version_num = g_ascii_strtod (version, &end);
+      if (*end)
+	{
+	  g_warning ("Invalid Version string '%s' in %s",
+		     version, source ? source : "(unknown)");
+	}
+      else if (version_num > 1.0)
+	{
+      /* Translators: Version here is capitalized because it refers to a
+       * field in the desktop file */
+	  g_set_error (error, EGG_DESKTOP_FILE_ERROR,
+		       EGG_DESKTOP_FILE_ERROR_INVALID,
+		       _("Unrecognized desktop file Version '%s'"), version);
+	  g_free (version);
+	  g_key_file_free (key_file);
+	  return NULL;
+	}
+      g_free (version);
+    }
+
+  desktop_file = g_new0 (EggDesktopFile, 1);
+  desktop_file->key_file = key_file;
+
+  if (g_path_is_absolute (source))
+    desktop_file->source = g_filename_to_uri (source, NULL, NULL);
+  else
+    desktop_file->source = g_strdup (source);
+
+  desktop_file->name = g_key_file_get_string (key_file, EGG_DESKTOP_FILE_GROUP,
+					      EGG_DESKTOP_FILE_KEY_NAME, error);
+  if (!desktop_file->name)
+    {
+      egg_desktop_file_free (desktop_file);
+      return NULL;
+    }
+
+  type = g_key_file_get_string (key_file, EGG_DESKTOP_FILE_GROUP,
+				EGG_DESKTOP_FILE_KEY_TYPE, error);
+  if (!type)
+    {
+      egg_desktop_file_free (desktop_file);
+      return NULL;
+    }
+
+  if (!strcmp (type, "Application"))
+    {
+      char *exec, *p;
+
+      desktop_file->type = EGG_DESKTOP_FILE_TYPE_APPLICATION;
+
+      exec = g_key_file_get_string (key_file,
+				    EGG_DESKTOP_FILE_GROUP,
+				    EGG_DESKTOP_FILE_KEY_EXEC,
+				    error);
+      if (!exec)
+	{
+	  egg_desktop_file_free (desktop_file);
+	  g_free (type);
+	  return NULL;
+	}
+
+      /* See if it takes paths or URIs or neither */
+      for (p = exec; *p; p++)
+	{
+	  if (*p == '%')
+	    {
+	      if (p[1] == '\0' || strchr ("FfUu", p[1]))
+		{
+		  desktop_file->document_code = p[1];
+		  break;
+		}
+	      p++;
+	    }
+	}
+
+      g_free (exec);
+    }
+  else if (!strcmp (type, "Link"))
+    {
+      char *url;
+
+      desktop_file->type = EGG_DESKTOP_FILE_TYPE_LINK;
+
+      url = g_key_file_get_string (key_file,
+				   EGG_DESKTOP_FILE_GROUP,
+				   EGG_DESKTOP_FILE_KEY_URL,
+				   error);
+      if (!url)
+	{
+	  egg_desktop_file_free (desktop_file);
+	  g_free (type);
+	  return NULL;
+	}
+      g_free (url);
+    }
+  else if (!strcmp (type, "Directory"))
+    desktop_file->type = EGG_DESKTOP_FILE_TYPE_DIRECTORY;
+  else
+    desktop_file->type = EGG_DESKTOP_FILE_TYPE_UNRECOGNIZED;
+
+  g_free (type);
+
+  /* Check the Icon key */
+  desktop_file->icon = g_key_file_get_string (key_file,
+					      EGG_DESKTOP_FILE_GROUP,
+					      EGG_DESKTOP_FILE_KEY_ICON,
+					      NULL);
+  if (desktop_file->icon && !g_path_is_absolute (desktop_file->icon))
+    {
+      char *ext;
+
+      /* Lots of .desktop files still get this wrong */
+      ext = strrchr (desktop_file->icon, '.');
+      if (ext && (!strcmp (ext, ".png") ||
+		  !strcmp (ext, ".xpm") ||
+		  !strcmp (ext, ".svg")))
+	{
+	  g_warning ("Desktop file '%s' has malformed Icon key '%s'"
+		     "(should not include extension)",
+		     source ? source : "(unknown)",
+		     desktop_file->icon);
+	  *ext = '\0';
+	}
+    }
+
+  return desktop_file;
+}
+
+/**
+ * egg_desktop_file_free:
+ * @desktop_file: an #EggDesktopFile
+ *
+ * Frees @desktop_file.
+ **/
+void
+egg_desktop_file_free (EggDesktopFile *desktop_file)
+{
+  g_key_file_free (desktop_file->key_file);
+  g_free (desktop_file->source);
+  g_free (desktop_file->name);
+  g_free (desktop_file->icon);
+  g_free (desktop_file);
+}
+
+/**
+ * egg_desktop_file_get_source:
+ * @desktop_file: an #EggDesktopFile
+ *
+ * Gets the URI that @desktop_file was loaded from.
+ *
+ * Return value: @desktop_file's source URI
+ **/
+const char *
+egg_desktop_file_get_source (EggDesktopFile *desktop_file)
+{
+  return desktop_file->source;
+}
+
+/**
+ * egg_desktop_file_get_desktop_file_type:
+ * @desktop_file: an #EggDesktopFile
+ *
+ * Gets the desktop file type of @desktop_file.
+ *
+ * Return value: @desktop_file's type
+ **/
+EggDesktopFileType
+egg_desktop_file_get_desktop_file_type (EggDesktopFile *desktop_file)
+{
+  return desktop_file->type;
+}
+
+/**
+ * egg_desktop_file_get_name:
+ * @desktop_file: an #EggDesktopFile
+ *
+ * Gets the (localized) value of @desktop_file's "Name" key.
+ *
+ * Return value: the application/link name
+ **/
+const char *
+egg_desktop_file_get_name (EggDesktopFile *desktop_file)
+{
+  return desktop_file->name;
+}
+
+/**
+ * egg_desktop_file_get_icon:
+ * @desktop_file: an #EggDesktopFile
+ *
+ * Gets the value of @desktop_file's "Icon" key.
+ *
+ * If the icon string is a full path (that is, if g_path_is_absolute()
+ * returns %TRUE when called on it), it points to a file containing an
+ * unthemed icon. If the icon string is not a full path, it is the
+ * name of a themed icon, which can be looked up with %GtkIconTheme,
+ * or passed directly to a theme-aware widget like %GtkImage or
+ * %GtkCellRendererPixbuf.
+ *
+ * Return value: the icon path or name
+ **/
+const char *
+egg_desktop_file_get_icon (EggDesktopFile *desktop_file)
+{
+  return desktop_file->icon;
+}
+
+gboolean
+egg_desktop_file_has_key (EggDesktopFile  *desktop_file,
+			  const char      *key,
+			  GError         **error)
+{
+  return g_key_file_has_key (desktop_file->key_file,
+			     EGG_DESKTOP_FILE_GROUP, key,
+			     error);
+}
+
+char *
+egg_desktop_file_get_string (EggDesktopFile  *desktop_file,
+			     const char      *key,
+			     GError         **error)
+{
+  return g_key_file_get_string (desktop_file->key_file,
+				EGG_DESKTOP_FILE_GROUP, key,
+				error);
+}
+
+char *
+egg_desktop_file_get_locale_string (EggDesktopFile  *desktop_file,
+				    const char      *key,
+				    const char      *locale,
+				    GError         **error)
+{
+  return g_key_file_get_locale_string (desktop_file->key_file,
+				       EGG_DESKTOP_FILE_GROUP, key, locale,
+				       error);
+}
+
+gboolean
+egg_desktop_file_get_boolean (EggDesktopFile  *desktop_file,
+			      const char      *key,
+			      GError         **error)
+{
+  return g_key_file_get_boolean (desktop_file->key_file,
+				 EGG_DESKTOP_FILE_GROUP, key,
+				 error);
+}
+
+double
+egg_desktop_file_get_numeric (EggDesktopFile  *desktop_file,
+			      const char      *key,
+			      GError         **error)
+{
+  return g_key_file_get_double (desktop_file->key_file,
+				EGG_DESKTOP_FILE_GROUP, key,
+				error);
+}
+
+int
+egg_desktop_file_get_integer (EggDesktopFile *desktop_file,
+                              const char		*key,
+                              GError		   **error)
+{
+  return g_key_file_get_integer (desktop_file->key_file,
+                                 EGG_DESKTOP_FILE_GROUP, key,
+                                 error);
+}
+
+char **
+egg_desktop_file_get_string_list (EggDesktopFile  *desktop_file,
+				  const char      *key,
+				  gsize           *length,
+				  GError         **error)
+{
+  return g_key_file_get_string_list (desktop_file->key_file,
+				     EGG_DESKTOP_FILE_GROUP, key, length,
+				     error);
+}
+
+char **
+egg_desktop_file_get_locale_string_list (EggDesktopFile  *desktop_file,
+					 const char      *key,
+					 const char      *locale,
+					 gsize           *length,
+					 GError         **error)
+{
+  return g_key_file_get_locale_string_list (desktop_file->key_file,
+					    EGG_DESKTOP_FILE_GROUP, key,
+					    locale, length,
+					    error);
+}
+
+/**
+ * egg_desktop_file_can_launch:
+ * @desktop_file: an #EggDesktopFile
+ * @desktop_environment: the name of the running desktop environment,
+ * or %NULL
+ *
+ * Tests if @desktop_file can/should be launched in the current
+ * environment. If @desktop_environment is non-%NULL, @desktop_file's
+ * "OnlyShowIn" and "NotShowIn" keys are checked to make sure that
+ * this desktop_file is appropriate for the named environment.
+ *
+ * Furthermore, if @desktop_file has type
+ * %EGG_DESKTOP_FILE_TYPE_APPLICATION, its "TryExec" key (if any) is
+ * also checked, to make sure the binary it points to exists.
+ *
+ * egg_desktop_file_can_launch() does NOT check the value of the
+ * "Hidden" key.
+ *
+ * Return value: %TRUE if @desktop_file can be launched
+ **/
+gboolean
+egg_desktop_file_can_launch (EggDesktopFile *desktop_file,
+			     const char     *desktop_environment)
+{
+  char *try_exec, *found_program;
+  char **only_show_in, **not_show_in;
+  gboolean found;
+  int i;
+
+  if (desktop_file->type != EGG_DESKTOP_FILE_TYPE_APPLICATION &&
+      desktop_file->type != EGG_DESKTOP_FILE_TYPE_LINK)
+    return FALSE;
+
+  if (desktop_environment)
+    {
+      only_show_in = g_key_file_get_string_list (desktop_file->key_file,
+						 EGG_DESKTOP_FILE_GROUP,
+						 EGG_DESKTOP_FILE_KEY_ONLY_SHOW_IN,
+						 NULL, NULL);
+      if (only_show_in)
+	{
+	  for (i = 0, found = FALSE; only_show_in[i] && !found; i++)
+	    {
+	      if (!strcmp (only_show_in[i], desktop_environment))
+		found = TRUE;
+	    }
+
+	  g_strfreev (only_show_in);
+
+	  if (!found)
+	    return FALSE;
+	}
+
+      not_show_in = g_key_file_get_string_list (desktop_file->key_file,
+						EGG_DESKTOP_FILE_GROUP,
+						EGG_DESKTOP_FILE_KEY_NOT_SHOW_IN,
+						NULL, NULL);
+      if (not_show_in)
+	{
+	  for (i = 0, found = FALSE; not_show_in[i] && !found; i++)
+	    {
+	      if (!strcmp (not_show_in[i], desktop_environment))
+		found = TRUE;
+	    }
+
+	  g_strfreev (not_show_in);
+
+	  if (found)
+	    return FALSE;
+	}
+    }
+
+  if (desktop_file->type == EGG_DESKTOP_FILE_TYPE_APPLICATION)
+    {
+      try_exec = g_key_file_get_string (desktop_file->key_file,
+					EGG_DESKTOP_FILE_GROUP,
+					EGG_DESKTOP_FILE_KEY_TRY_EXEC,
+					NULL);
+      if (try_exec)
+	{
+	  found_program = g_find_program_in_path (try_exec);
+	  g_free (try_exec);
+
+	  if (!found_program)
+	    return FALSE;
+	  g_free (found_program);
+	}
+    }
+
+  return TRUE;
+}
+
+/**
+ * egg_desktop_file_accepts_documents:
+ * @desktop_file: an #EggDesktopFile
+ *
+ * Tests if @desktop_file represents an application that can accept
+ * documents on the command line.
+ *
+ * Return value: %TRUE or %FALSE
+ **/
+gboolean
+egg_desktop_file_accepts_documents (EggDesktopFile *desktop_file)
+{
+  return desktop_file->document_code != 0;
+}
+
+/**
+ * egg_desktop_file_accepts_multiple:
+ * @desktop_file: an #EggDesktopFile
+ *
+ * Tests if @desktop_file can accept multiple documents at once.
+ *
+ * If this returns %FALSE, you can still pass multiple documents to
+ * egg_desktop_file_launch(), but that will result in multiple copies
+ * of the application being launched. See egg_desktop_file_launch()
+ * for more details.
+ *
+ * Return value: %TRUE or %FALSE
+ **/
+gboolean
+egg_desktop_file_accepts_multiple (EggDesktopFile *desktop_file)
+{
+  return (desktop_file->document_code == 'F' ||
+	  desktop_file->document_code == 'U');
+}
+
+/**
+ * egg_desktop_file_accepts_uris:
+ * @desktop_file: an #EggDesktopFile
+ *
+ * Tests if @desktop_file can accept (non-"file:") URIs as documents to
+ * open.
+ *
+ * Return value: %TRUE or %FALSE
+ **/
+gboolean
+egg_desktop_file_accepts_uris (EggDesktopFile *desktop_file)
+{
+  return (desktop_file->document_code == 'U' ||
+	  desktop_file->document_code == 'u');
+}
+
+static void
+append_quoted_word (GString    *str,
+		    const char *s,
+		    gboolean    in_single_quotes,
+		    gboolean    in_double_quotes)
+{
+  const char *p;
+
+  if (!in_single_quotes && !in_double_quotes)
+    g_string_append_c (str, '\'');
+  else if (!in_single_quotes && in_double_quotes)
+    g_string_append (str, "\"'");
+
+  if (!strchr (s, '\''))
+    g_string_append (str, s);
+  else
+    {
+      for (p = s; *p != '\0'; p++)
+	{
+	  if (*p == '\'')
+	    g_string_append (str, "'\\''");
+	  else
+	    g_string_append_c (str, *p);
+	}
+    }
+
+  if (!in_single_quotes && !in_double_quotes)
+    g_string_append_c (str, '\'');
+  else if (!in_single_quotes && in_double_quotes)
+    g_string_append (str, "'\"");
+}
+
+static void
+do_percent_subst (EggDesktopFile *desktop_file,
+		  char            code,
+		  GString        *str,
+		  GSList        **documents,
+		  gboolean        in_single_quotes,
+		  gboolean        in_double_quotes)
+{
+  GSList *d;
+  char *doc;
+
+  switch (code)
+    {
+    case '%':
+      g_string_append_c (str, '%');
+      break;
+
+    case 'F':
+    case 'U':
+      for (d = *documents; d; d = d->next)
+	{
+	  doc = d->data;
+	  g_string_append (str, " ");
+	  append_quoted_word (str, doc, in_single_quotes, in_double_quotes);
+	}
+      *documents = NULL;
+      break;
+
+    case 'f':
+    case 'u':
+      if (*documents)
+	{
+	  doc = (*documents)->data;
+	  g_string_append (str, " ");
+	  append_quoted_word (str, doc, in_single_quotes, in_double_quotes);
+	  *documents = (*documents)->next;
+	}
+      break;
+
+    case 'i':
+      if (desktop_file->icon)
+	{
+	  g_string_append (str, "--icon ");
+	  append_quoted_word (str, desktop_file->icon,
+			      in_single_quotes, in_double_quotes);
+	}
+      break;
+
+    case 'c':
+      if (desktop_file->name)
+	{
+	  append_quoted_word (str, desktop_file->name,
+			      in_single_quotes, in_double_quotes);
+	}
+      break;
+
+    case 'k':
+      if (desktop_file->source)
+	{
+	  append_quoted_word (str, desktop_file->source,
+			      in_single_quotes, in_double_quotes);
+	}
+      break;
+
+    case 'D':
+    case 'N':
+    case 'd':
+    case 'n':
+    case 'v':
+    case 'm':
+      /* Deprecated; skip */
+      break;
+
+    default:
+      g_warning ("Unrecognized %%-code '%%%c' in Exec", code);
+      break;
+    }
+}
+
+static char *
+parse_exec (EggDesktopFile  *desktop_file,
+	    GSList         **documents,
+	    GError         **error)
+{
+  char *exec, *p, *command;
+  gboolean escape, single_quot, double_quot;
+  GString *gs;
+
+  exec = g_key_file_get_string (desktop_file->key_file,
+				EGG_DESKTOP_FILE_GROUP,
+				EGG_DESKTOP_FILE_KEY_EXEC,
+				error);
+  if (!exec)
+    return NULL;
+
+  /* Build the command */
+  gs = g_string_new (NULL);
+  escape = single_quot = double_quot = FALSE;
+
+  for (p = exec; *p != '\0'; p++)
+    {
+      if (escape)
+	{
+	  escape = FALSE;
+	  g_string_append_c (gs, *p);
+	}
+      else if (*p == '\\')
+	{
+	  if (!single_quot)
+	    escape = TRUE;
+	  g_string_append_c (gs, *p);
+	}
+      else if (*p == '\'')
+	{
+	  g_string_append_c (gs, *p);
+	  if (!single_quot && !double_quot)
+	    single_quot = TRUE;
+	  else if (single_quot)
+	    single_quot = FALSE;
+	}
+      else if (*p == '"')
+	{
+	  g_string_append_c (gs, *p);
+	  if (!single_quot && !double_quot)
+	    double_quot = TRUE;
+	  else if (double_quot)
+	    double_quot = FALSE;
+	}
+      else if (*p == '%' && p[1])
+	{
+	  do_percent_subst (desktop_file, p[1], gs, documents,
+			    single_quot, double_quot);
+	  p++;
+	}
+      else
+	g_string_append_c (gs, *p);
+    }
+
+  g_free (exec);
+  command = g_string_free (gs, FALSE);
+
+  /* Prepend "xdg-terminal " if needed (FIXME: use gvfs) */
+  if (g_key_file_has_key (desktop_file->key_file,
+			  EGG_DESKTOP_FILE_GROUP,
+			  EGG_DESKTOP_FILE_KEY_TERMINAL,
+			  NULL))
+    {
+      GError *terminal_error = NULL;
+      gboolean use_terminal =
+	g_key_file_get_boolean (desktop_file->key_file,
+				EGG_DESKTOP_FILE_GROUP,
+				EGG_DESKTOP_FILE_KEY_TERMINAL,
+				&terminal_error);
+      if (terminal_error)
+	{
+	  g_free (command);
+	  g_propagate_error (error, terminal_error);
+	  return NULL;
+	}
+
+      if (use_terminal)
+	{
+	  gs = g_string_new ("xdg-terminal ");
+	  append_quoted_word (gs, command, FALSE, FALSE);
+	  g_free (command);
+	  command = g_string_free (gs, FALSE);
+	}
+    }
+
+  return command;
+}
+
+static GSList *
+translate_document_list (EggDesktopFile *desktop_file, GSList *documents)
+{
+  gboolean accepts_uris = egg_desktop_file_accepts_uris (desktop_file);
+  GSList *ret, *d;
+
+  for (d = documents, ret = NULL; d; d = d->next)
+    {
+      const char *document = d->data;
+      gboolean is_uri = !g_path_is_absolute (document);
+      char *translated;
+
+      if (accepts_uris)
+	{
+	  if (is_uri)
+	    translated = g_strdup (document);
+	  else
+	    translated = g_filename_to_uri (document, NULL, NULL);
+	}
+      else
+	{
+	  if (is_uri)
+	    translated = g_filename_from_uri (document, NULL, NULL);
+	  else
+	    translated = g_strdup (document);
+	}
+
+      if (translated)
+	ret = g_slist_prepend (ret, translated);
+    }
+
+  return g_slist_reverse (ret);
+}
+
+static void
+free_document_list (GSList *documents)
+{
+  GSList *d;
+
+  for (d = documents; d; d = d->next)
+    g_free (d->data);
+  g_slist_free (documents);
+}
+
+/**
+ * egg_desktop_file_parse_exec:
+ * @desktop_file: a #EggDesktopFile
+ * @documents: a list of document paths or URIs
+ * @error: error pointer
+ *
+ * Parses @desktop_file's Exec key, inserting @documents into it, and
+ * returns the result.
+ *
+ * If @documents contains non-file: URIs and @desktop_file does not
+ * accept URIs, those URIs will be ignored. Likewise, if @documents
+ * contains more elements than @desktop_file accepts, the extra
+ * documents will be ignored.
+ *
+ * Return value: the parsed Exec string
+ **/
+char *
+egg_desktop_file_parse_exec (EggDesktopFile  *desktop_file,
+			     GSList          *documents,
+			     GError         **error)
+{
+  GSList *translated, *docs;
+  char *command;
+
+  docs = translated = translate_document_list (desktop_file, documents);
+  command = parse_exec (desktop_file, &docs, error);
+  free_document_list (translated);
+
+  return command;
+}
+
+static gboolean
+parse_link (EggDesktopFile  *desktop_file,
+	    EggDesktopFile **app_desktop_file,
+	    GSList         **documents,
+	    GError         **error)
+{
+  char *url;
+  GKeyFile *key_file;
+
+  url = g_key_file_get_string (desktop_file->key_file,
+			       EGG_DESKTOP_FILE_GROUP,
+			       EGG_DESKTOP_FILE_KEY_URL,
+			       error);
+  if (!url)
+    return FALSE;
+  *documents = g_slist_prepend (NULL, url);
+
+  /* FIXME: use gvfs */
+  key_file = g_key_file_new ();
+  g_key_file_set_string (key_file, EGG_DESKTOP_FILE_GROUP,
+			 EGG_DESKTOP_FILE_KEY_NAME,
+			 "xdg-open");
+  g_key_file_set_string (key_file, EGG_DESKTOP_FILE_GROUP,
+			 EGG_DESKTOP_FILE_KEY_TYPE,
+			 "Application");
+  g_key_file_set_string (key_file, EGG_DESKTOP_FILE_GROUP,
+			 EGG_DESKTOP_FILE_KEY_EXEC,
+			 "xdg-open %u");
+  *app_desktop_file = egg_desktop_file_new_from_key_file (key_file, NULL, NULL);
+  return TRUE;
+}
+
+#if defined(GDK_WINDOWING_X11) || defined(HAVE_X11)
+static char *
+start_startup_notification (GdkDisplay     *display,
+			    EggDesktopFile *desktop_file,
+			    const char     *argv0,
+			    int             screen,
+			    int             workspace,
+			    guint32         launch_time)
+{
+  static int sequence = 0;
+  char *startup_id;
+  char *description, *wmclass;
+  char *screen_str, *workspace_str;
+
+  g_assert(GDK_IS_X11_DISPLAY (display));
+
+  if (g_key_file_has_key (desktop_file->key_file,
+			  EGG_DESKTOP_FILE_GROUP,
+			  EGG_DESKTOP_FILE_KEY_STARTUP_NOTIFY,
+			  NULL))
+    {
+      if (!g_key_file_get_boolean (desktop_file->key_file,
+				   EGG_DESKTOP_FILE_GROUP,
+				   EGG_DESKTOP_FILE_KEY_STARTUP_NOTIFY,
+				   NULL))
+	return NULL;
+      wmclass = NULL;
+    }
+  else
+    {
+      wmclass = g_key_file_get_string (desktop_file->key_file,
+				       EGG_DESKTOP_FILE_GROUP,
+				       EGG_DESKTOP_FILE_KEY_STARTUP_WM_CLASS,
+				       NULL);
+      if (!wmclass)
+	return NULL;
+    }
+
+  if (launch_time == (guint32)-1)
+    launch_time = gdk_x11_display_get_user_time (display);
+  startup_id = g_strdup_printf ("%s-%lu-%s-%s-%d_TIME%lu",
+				g_get_prgname (),
+				(unsigned long)getpid (),
+				g_get_host_name (),
+				argv0,
+				sequence++,
+				(unsigned long)launch_time);
+
+  description = g_strdup_printf (_("Starting %s"), desktop_file->name);
+  screen_str = g_strdup_printf ("%d", screen);
+  workspace_str = workspace == -1 ? NULL : g_strdup_printf ("%d", workspace);
+
+  gdk_x11_display_broadcast_startup_message (display, "new",
+					     "ID", startup_id,
+					     "NAME", desktop_file->name,
+					     "SCREEN", screen_str,
+					     "BIN", argv0,
+					     "ICON", desktop_file->icon,
+					     "DESKTOP", workspace_str,
+					     "DESCRIPTION", description,
+					     "WMCLASS", wmclass,
+					     NULL);
+
+  g_free (description);
+  g_free (wmclass);
+  g_free (screen_str);
+  g_free (workspace_str);
+
+  return startup_id;
+}
+
+static void
+end_startup_notification (GdkDisplay *display,
+			  const char *startup_id)
+{
+  gdk_x11_display_broadcast_startup_message (display, "remove",
+					     "ID", startup_id,
+					     NULL);
+}
+
+#define EGG_DESKTOP_FILE_SN_TIMEOUT_LENGTH (30 /* seconds */)
+
+typedef struct {
+  GdkDisplay *display;
+  char *startup_id;
+} StartupNotificationData;
+
+static gboolean
+startup_notification_timeout (gpointer data)
+{
+  StartupNotificationData *sn_data = data;
+
+  end_startup_notification (sn_data->display, sn_data->startup_id);
+  g_object_unref (sn_data->display);
+  g_free (sn_data->startup_id);
+  g_free (sn_data);
+
+  return FALSE;
+}
+
+static void
+set_startup_notification_timeout (GdkDisplay *display,
+				  const char *startup_id)
+{
+  StartupNotificationData *sn_data;
+
+  sn_data = g_new (StartupNotificationData, 1);
+  sn_data->display = g_object_ref (display);
+  sn_data->startup_id = g_strdup (startup_id);
+
+  g_timeout_add_seconds (EGG_DESKTOP_FILE_SN_TIMEOUT_LENGTH,
+			 startup_notification_timeout, sn_data);
+}
+#endif // GDK_WINDOWING_X11
+
+static GPtrArray *
+array_putenv (GPtrArray *env, char *variable)
+{
+  guint i, keylen;
+
+  if (!env)
+    {
+      char **envp;
+
+      env = g_ptr_array_new ();
+
+      envp = g_listenv ();
+      for (i = 0; envp[i]; i++)
+        {
+          const char *value;
+
+          value = g_getenv (envp[i]);
+          g_ptr_array_add (env, g_strdup_printf ("%s=%s", envp[i],
+                                                 value ? value : ""));
+        }
+      g_strfreev (envp);
+    }
+
+  keylen = strcspn (variable, "=");
+
+  /* Remove old value of key */
+  for (i = 0; i < env->len; i++)
+    {
+      char *envvar = env->pdata[i];
+
+      if (!strncmp (envvar, variable, keylen) && envvar[keylen] == '=')
+	{
+	  g_free (envvar);
+	  g_ptr_array_remove_index_fast (env, i);
+	  break;
+	}
+    }
+
+  /* Add new value */
+  g_ptr_array_add (env, g_strdup (variable));
+
+  return env;
+}
+
+static gboolean
+egg_desktop_file_launchv (EggDesktopFile *desktop_file,
+			  GSList *documents, va_list args,
+			  GError **error)
+{
+  EggDesktopFileLaunchOption option;
+  GSList *translated_documents = NULL, *docs = NULL;
+  char *command, **argv;
+  int argc, i;
+  gboolean success, current_success;
+  GdkDisplay *display;
+  char *startup_id;
+
+  GPtrArray   *env = NULL;
+  char       **variables = NULL;
+  GdkScreen   *screen = NULL;
+  int          workspace = -1;
+  const char  *directory = NULL;
+  guint32      launch_time = (guint32)-1;
+  GSpawnFlags  flags = G_SPAWN_SEARCH_PATH;
+  GSpawnChildSetupFunc setup_func = NULL;
+  gpointer     setup_data = NULL;
+
+  GPid        *ret_pid = NULL;
+  int         *ret_stdin = NULL, *ret_stdout = NULL, *ret_stderr = NULL;
+  char       **ret_startup_id = NULL;
+
+  if (documents && desktop_file->document_code == 0)
+    {
+      g_set_error (error, EGG_DESKTOP_FILE_ERROR,
+		   EGG_DESKTOP_FILE_ERROR_NOT_LAUNCHABLE,
+		   _("Application does not accept documents on command line"));
+      return FALSE;
+    }
+
+  /* Read the options: technically it's incorrect for the caller to
+   * NULL-terminate the list of options (rather than 0-terminating
+   * it), but NULL-terminating lets us use G_GNUC_NULL_TERMINATED,
+   * it's more consistent with other glib/gtk methods, and it will
+   * work as long as sizeof (int) <= sizeof (NULL), and NULL is
+   * represented as 0. (Which is true everywhere we care about.)
+   */
+  while ((option = va_arg (args, EggDesktopFileLaunchOption)))
+    {
+      switch (option)
+	{
+	case EGG_DESKTOP_FILE_LAUNCH_CLEARENV:
+	  if (env)
+	    g_ptr_array_free (env, TRUE);
+	  env = g_ptr_array_new ();
+	  break;
+	case EGG_DESKTOP_FILE_LAUNCH_PUTENV:
+	  variables = va_arg (args, char **);
+	  for (i = 0; variables[i]; i++)
+	    env = array_putenv (env, variables[i]);
+	  break;
+
+	case EGG_DESKTOP_FILE_LAUNCH_SCREEN:
+	  screen = va_arg (args, GdkScreen *);
+	  break;
+	case EGG_DESKTOP_FILE_LAUNCH_WORKSPACE:
+	  workspace = va_arg (args, int);
+	  break;
+
+	case EGG_DESKTOP_FILE_LAUNCH_DIRECTORY:
+	  directory = va_arg (args, const char *);
+	  break;
+	case EGG_DESKTOP_FILE_LAUNCH_TIME:
+	  launch_time = va_arg (args, guint32);
+	  break;
+	case EGG_DESKTOP_FILE_LAUNCH_FLAGS:
+	  flags |= va_arg (args, GSpawnFlags);
+	  /* Make sure they didn't set any flags that don't make sense. */
+	  flags &= ~G_SPAWN_FILE_AND_ARGV_ZERO;
+	  break;
+	case EGG_DESKTOP_FILE_LAUNCH_SETUP_FUNC:
+	  setup_func = va_arg (args, GSpawnChildSetupFunc);
+	  setup_data = va_arg (args, gpointer);
+	  break;
+
+	case EGG_DESKTOP_FILE_LAUNCH_RETURN_PID:
+	  ret_pid = va_arg (args, GPid *);
+	  break;
+	case EGG_DESKTOP_FILE_LAUNCH_RETURN_STDIN_PIPE:
+	  ret_stdin = va_arg (args, int *);
+	  break;
+	case EGG_DESKTOP_FILE_LAUNCH_RETURN_STDOUT_PIPE:
+	  ret_stdout = va_arg (args, int *);
+	  break;
+	case EGG_DESKTOP_FILE_LAUNCH_RETURN_STDERR_PIPE:
+	  ret_stderr = va_arg (args, int *);
+	  break;
+	case EGG_DESKTOP_FILE_LAUNCH_RETURN_STARTUP_ID:
+	  ret_startup_id = va_arg (args, char **);
+	  break;
+
+	default:
+	  g_set_error (error, EGG_DESKTOP_FILE_ERROR,
+		       EGG_DESKTOP_FILE_ERROR_UNRECOGNIZED_OPTION,
+		       _("Unrecognized launch option: %d"),
+		       GPOINTER_TO_INT (option));
+	  success = FALSE;
+	  goto out;
+	}
+    }
+
+  if (screen)
+    {
+      display = gdk_screen_get_display (screen);
+      char *display_name = g_strdup (gdk_display_get_name (display));
+      char *display_env = g_strdup_printf ("DISPLAY=%s", display_name);
+      env = array_putenv (env, display_env);
+      g_free (display_name);
+      g_free (display_env);
+    }
+  else
+    {
+      display = gdk_display_get_default ();
+      screen = gdk_display_get_default_screen (display);
+    }
+
+  translated_documents = translate_document_list (desktop_file, documents);
+  docs = translated_documents;
+
+  success = FALSE;
+
+  do
+    {
+      command = parse_exec (desktop_file, &docs, error);
+      if (!command)
+	goto out;
+
+      if (!g_shell_parse_argv (command, &argc, &argv, error))
+	{
+	  g_free (command);
+	  goto out;
+	}
+      g_free (command);
+
+      startup_id = NULL;
+
+#if defined(GDK_WINDOWING_X11) || defined(HAVE_X11)
+      if (GDK_IS_X11_DISPLAY (display))
+        {
+	  int screen_num;
+
+	  screen_num = gdk_x11_screen_get_screen_number (screen);
+      startup_id = start_startup_notification (display, desktop_file,
+					       argv[0], screen_num,
+					       workspace, launch_time);
+      if (startup_id)
+	{
+	  char *startup_id_env = g_strdup_printf ("DESKTOP_STARTUP_ID=%s",
+						  startup_id);
+	  env = array_putenv (env, startup_id_env);
+	  g_free (startup_id_env);
+	}
+        }
+#else
+      // Suppress unused variable warnings when not compiling with X
+      (void)workspace;
+      (void)launch_time;
+#endif
+
+      if (env != NULL)
+	g_ptr_array_add (env, NULL);
+
+      current_success =
+	g_spawn_async_with_pipes (directory,
+				  argv,
+				  env ? (char **)(env->pdata) : NULL,
+				  flags,
+				  setup_func, setup_data,
+				  ret_pid,
+				  ret_stdin, ret_stdout, ret_stderr,
+				  error);
+      g_strfreev (argv);
+
+      if (startup_id)
+	{
+	  if (current_success)
+	    {
+#if defined(GDK_WINDOWING_X11) || defined(HAVE_X11)
+	      if (GDK_IS_X11_DISPLAY (display))
+		{
+	      set_startup_notification_timeout (display, startup_id);
+		}
+#endif
+
+	      if (ret_startup_id)
+		*ret_startup_id = startup_id;
+	      else
+		g_free (startup_id);
+	    }
+	  else
+	    g_free (startup_id);
+	}
+      else if (ret_startup_id)
+	*ret_startup_id = NULL;
+
+      if (current_success)
+	{
+	  /* If we successfully launch any instances of the app, make
+	   * sure we return TRUE and don't set @error.
+	   */
+	  success = TRUE;
+	  error = NULL;
+
+	  /* Also, only set the output params on the first one */
+	  ret_pid = NULL;
+	  ret_stdin = ret_stdout = ret_stderr = NULL;
+	  ret_startup_id = NULL;
+	}
+    }
+  while (docs && current_success);
+
+ out:
+  if (env)
+    {
+      g_ptr_array_set_free_func (env, g_free);
+      g_ptr_array_free (env, TRUE);
+    }
+  free_document_list (translated_documents);
+
+  return success;
+}
+
+/**
+ * egg_desktop_file_launch:
+ * @desktop_file: an #EggDesktopFile
+ * @documents: a list of URIs or paths to documents to open
+ * @error: error pointer
+ * @...: additional options
+ *
+ * Launches @desktop_file with the given arguments. Additional options
+ * can be specified as follows:
+ *
+ *   %EGG_DESKTOP_FILE_LAUNCH_CLEARENV: (no arguments)
+ *       clears the environment in the child process
+ *   %EGG_DESKTOP_FILE_LAUNCH_PUTENV: (char **variables)
+ *       adds the NAME=VALUE strings in the given %NULL-terminated
+ *       array to the child process's environment
+ *   %EGG_DESKTOP_FILE_LAUNCH_SCREEN: (GdkScreen *screen)
+ *       causes the application to be launched on the given screen
+ *   %EGG_DESKTOP_FILE_LAUNCH_WORKSPACE: (int workspace)
+ *       causes the application to be launched on the given workspace
+ *   %EGG_DESKTOP_FILE_LAUNCH_DIRECTORY: (char *dir)
+ *       causes the application to be launched in the given directory
+ *   %EGG_DESKTOP_FILE_LAUNCH_TIME: (guint32 launch_time)
+ *       sets the "launch time" for the application. If the user
+ *       interacts with another window after @launch_time but before
+ *       the launched application creates its first window, the window
+ *       manager may choose to not give focus to the new application.
+ *       Passing 0 for @launch_time will explicitly request that the
+ *       application not receive focus.
+ *   %EGG_DESKTOP_FILE_LAUNCH_FLAGS (GSpawnFlags flags)
+ *       Sets additional #GSpawnFlags to use. See g_spawn_async() for
+ *       more details.
+ *   %EGG_DESKTOP_FILE_LAUNCH_SETUP_FUNC (GSpawnChildSetupFunc, gpointer)
+ *       Sets the child setup callback and the data to pass to it.
+ *       (See g_spawn_async() for more details.)
+ *
+ *   %EGG_DESKTOP_FILE_LAUNCH_RETURN_PID (GPid **pid)
+ *       On a successful launch, sets *@pid to the PID of the launched
+ *       application.
+ *   %EGG_DESKTOP_FILE_LAUNCH_RETURN_STARTUP_ID (char **startup_id)
+ *       On a successful launch, sets *@startup_id to the Startup
+ *       Notification "startup id" of the launched application.
+ *   %EGG_DESKTOP_FILE_LAUNCH_RETURN_STDIN_PIPE (int *fd)
+ *       On a successful launch, sets *@fd to the file descriptor of
+ *       a pipe connected to the application's stdin.
+ *   %EGG_DESKTOP_FILE_LAUNCH_RETURN_STDOUT_PIPE (int *fd)
+ *       On a successful launch, sets *@fd to the file descriptor of
+ *       a pipe connected to the application's stdout.
+ *   %EGG_DESKTOP_FILE_LAUNCH_RETURN_STDERR_PIPE (int *fd)
+ *       On a successful launch, sets *@fd to the file descriptor of
+ *       a pipe connected to the application's stderr.
+ *
+ * The options should be terminated with a single %NULL.
+ *
+ * If @documents contains multiple documents, but
+ * egg_desktop_file_accepts_multiple() returns %FALSE for
+ * @desktop_file, then egg_desktop_file_launch() will actually launch
+ * multiple instances of the application. In that case, the return
+ * value (as well as any values passed via
+ * %EGG_DESKTOP_FILE_LAUNCH_RETURN_PID, etc) will only reflect the
+ * first instance of the application that was launched (but the
+ * %EGG_DESKTOP_FILE_LAUNCH_SETUP_FUNC will be called for each
+ * instance).
+ *
+ * Return value: %TRUE if the application was successfully launched.
+ **/
+gboolean
+egg_desktop_file_launch (EggDesktopFile *desktop_file,
+			 GSList *documents, GError **error,
+			 ...)
+{
+  va_list args;
+  gboolean success;
+  EggDesktopFile *app_desktop_file;
+
+  switch (desktop_file->type)
+    {
+    case EGG_DESKTOP_FILE_TYPE_APPLICATION:
+      va_start (args, error);
+      success = egg_desktop_file_launchv (desktop_file, documents,
+					  args, error);
+      va_end (args);
+      break;
+
+    case EGG_DESKTOP_FILE_TYPE_LINK:
+      if (documents)
+	{
+	  g_set_error (error, EGG_DESKTOP_FILE_ERROR,
+		       EGG_DESKTOP_FILE_ERROR_NOT_LAUNCHABLE,
+		       _("Can't pass document URIs to a 'Type=Link' desktop entry"));
+	  return FALSE;
+	}
+
+      if (!parse_link (desktop_file, &app_desktop_file, &documents, error))
+	return FALSE;
+
+      va_start (args, error);
+      success = egg_desktop_file_launchv (app_desktop_file, documents,
+					  args, error);
+      va_end (args);
+
+      egg_desktop_file_free (app_desktop_file);
+      free_document_list (documents);
+      break;
+
+    case EGG_DESKTOP_FILE_TYPE_UNRECOGNIZED:
+    case EGG_DESKTOP_FILE_TYPE_DIRECTORY:
+    default:
+      g_set_error (error, EGG_DESKTOP_FILE_ERROR,
+		   EGG_DESKTOP_FILE_ERROR_NOT_LAUNCHABLE,
+		   _("Not a launchable item"));
+      success = FALSE;
+      break;
+    }
+
+  return success;
+}
+
+
+GQuark
+egg_desktop_file_error_quark (void)
+{
+  return g_quark_from_static_string ("egg-desktop_file-error-quark");
+}
+
+
+G_LOCK_DEFINE_STATIC (egg_desktop_file);
+static EggDesktopFile *egg_desktop_file;
+
+static void
+egg_set_desktop_file_internal (const char *desktop_file_path,
+                               gboolean set_defaults)
+{
+  GError *error = NULL;
+
+  G_LOCK (egg_desktop_file);
+  if (egg_desktop_file)
+    egg_desktop_file_free (egg_desktop_file);
+
+  egg_desktop_file = egg_desktop_file_new (desktop_file_path, &error);
+  if (error)
+    {
+      g_warning ("Could not load desktop file '%s': %s",
+		 desktop_file_path, error->message);
+      g_error_free (error);
+    }
+
+  if (set_defaults && egg_desktop_file != NULL) {
+    /* Set localized application name and default window icon */
+    if (egg_desktop_file->name)
+      g_set_application_name (egg_desktop_file->name);
+    if (egg_desktop_file->icon)
+      {
+        if (g_path_is_absolute (egg_desktop_file->icon))
+          gtk_window_set_default_icon_from_file (egg_desktop_file->icon, NULL);
+        else
+          gtk_window_set_default_icon_name (egg_desktop_file->icon);
+      }
+  }
+
+  G_UNLOCK (egg_desktop_file);
+}
+
+/**
+ * egg_set_desktop_file:
+ * @desktop_file_path: path to the application's desktop file
+ *
+ * Creates an #EggDesktopFile for the application from the data at
+ * @desktop_file_path. This will also call g_set_application_name()
+ * with the localized application name from the desktop file, and
+ * gtk_window_set_default_icon_name() or
+ * gtk_window_set_default_icon_from_file() with the application's
+ * icon. Other code may use additional information from the desktop
+ * file.
+ * See egg_set_desktop_file_without_defaults() for a variant of this
+ * function that does not set the application name and default window
+ * icon.
+ *
+ * Note that for thread safety reasons, this function can only
+ * be called once, and is mutually exclusive with calling
+ * egg_set_desktop_file_without_defaults().
+ **/
+void
+egg_set_desktop_file (const char *desktop_file_path)
+{
+  egg_set_desktop_file_internal (desktop_file_path, TRUE);
+}
+
+/**
+ * egg_set_desktop_file_without_defaults:
+ * @desktop_file_path: path to the application's desktop file
+ *
+ * Creates an #EggDesktopFile for the application from the data at
+ * @desktop_file_path.
+ * See egg_set_desktop_file() for a variant of this function that
+ * sets the application name and default window icon from the information
+ * in the desktop file.
+ *
+ * Note that for thread safety reasons, this function can only
+ * be called once, and is mutually exclusive with calling
+ * egg_set_desktop_file().
+ **/
+void
+egg_set_desktop_file_without_defaults (const char *desktop_file_path)
+{
+  egg_set_desktop_file_internal (desktop_file_path, FALSE);
+}
+
+/**
+ * egg_get_desktop_file:
+ *
+ * Gets the application's #EggDesktopFile, as set by
+ * egg_set_desktop_file().
+ *
+ * Return value: the #EggDesktopFile, or %NULL if it hasn't been set.
+ **/
+EggDesktopFile *
+egg_get_desktop_file (void)
+{
+  EggDesktopFile *retval;
+
+  G_LOCK (egg_desktop_file);
+  retval = egg_desktop_file;
+  G_UNLOCK (egg_desktop_file);
+
+  return retval;
+}
+
+ +
+ +
+ + diff --git a/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/11.html b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/11.html new file mode 100644 index 00000000..4124e396 --- /dev/null +++ b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/11.html @@ -0,0 +1,3055 @@ + + + + + + Cppcheck - HTML report - mate-utils + + + + + +
+ + + +
+
   1
+   2
+   3
+   4
+   5
+   6
+   7
+   8
+   9
+  10
+  11
+  12
+  13
+  14
+  15
+  16
+  17
+  18
+  19
+  20
+  21
+  22
+  23
+  24
+  25
+  26
+  27
+  28
+  29
+  30
+  31
+  32
+  33
+  34
+  35
+  36
+  37
+  38
+  39
+  40
+  41
+  42
+  43
+  44
+  45
+  46
+  47
+  48
+  49
+  50
+  51
+  52
+  53
+  54
+  55
+  56
+  57
+  58
+  59
+  60
+  61
+  62
+  63
+  64
+  65
+  66
+  67
+  68
+  69
+  70
+  71
+  72
+  73
+  74
+  75
+  76
+  77
+  78
+  79
+  80
+  81
+  82
+  83
+  84
+  85
+  86
+  87
+  88
+  89
+  90
+  91
+  92
+  93
+  94
+  95
+  96
+  97
+  98
+  99
+ 100
+ 101
+ 102
+ 103
+ 104
+ 105
+ 106
+ 107
+ 108
+ 109
+ 110
+ 111
+ 112
+ 113
+ 114
+ 115
+ 116
+ 117
+ 118
+ 119
+ 120
+ 121
+ 122
+ 123
+ 124
+ 125
+ 126
+ 127
+ 128
+ 129
+ 130
+ 131
+ 132
+ 133
+ 134
+ 135
+ 136
+ 137
+ 138
+ 139
+ 140
+ 141
+ 142
+ 143
+ 144
+ 145
+ 146
+ 147
+ 148
+ 149
+ 150
+ 151
+ 152
+ 153
+ 154
+ 155
+ 156
+ 157
+ 158
+ 159
+ 160
+ 161
+ 162
+ 163
+ 164
+ 165
+ 166
+ 167
+ 168
+ 169
+ 170
+ 171
+ 172
+ 173
+ 174
+ 175
+ 176
+ 177
+ 178
+ 179
+ 180
+ 181
+ 182
+ 183
+ 184
+ 185
+ 186
+ 187
+ 188
+ 189
+ 190
+ 191
+ 192
+ 193
+ 194
+ 195
+ 196
+ 197
+ 198
+ 199
+ 200
+ 201
+ 202
+ 203
+ 204
+ 205
+ 206
+ 207
+ 208
+ 209
+ 210
+ 211
+ 212
+ 213
+ 214
+ 215
+ 216
+ 217
+ 218
+ 219
+ 220
+ 221
+ 222
+ 223
+ 224
+ 225
+ 226
+ 227
+ 228
+ 229
+ 230
+ 231
+ 232
+ 233
+ 234
+ 235
+ 236
+ 237
+ 238
+ 239
+ 240
+ 241
+ 242
+ 243
+ 244
+ 245
+ 246
+ 247
+ 248
+ 249
+ 250
+ 251
+ 252
+ 253
+ 254
+ 255
+ 256
+ 257
+ 258
+ 259
+ 260
+ 261
+ 262
+ 263
+ 264
+ 265
+ 266
+ 267
+ 268
+ 269
+ 270
+ 271
+ 272
+ 273
+ 274
+ 275
+ 276
+ 277
+ 278
+ 279
+ 280
+ 281
+ 282
+ 283
+ 284
+ 285
+ 286
+ 287
+ 288
+ 289
+ 290
+ 291
+ 292
+ 293
+ 294
+ 295
+ 296
+ 297
+ 298
+ 299
+ 300
+ 301
+ 302
+ 303
+ 304
+ 305
+ 306
+ 307
+ 308
+ 309
+ 310
+ 311
+ 312
+ 313
+ 314
+ 315
+ 316
+ 317
+ 318
+ 319
+ 320
+ 321
+ 322
+ 323
+ 324
+ 325
+ 326
+ 327
+ 328
+ 329
+ 330
+ 331
+ 332
+ 333
+ 334
+ 335
+ 336
+ 337
+ 338
+ 339
+ 340
+ 341
+ 342
+ 343
+ 344
+ 345
+ 346
+ 347
+ 348
+ 349
+ 350
+ 351
+ 352
+ 353
+ 354
+ 355
+ 356
+ 357
+ 358
+ 359
+ 360
+ 361
+ 362
+ 363
+ 364
+ 365
+ 366
+ 367
+ 368
+ 369
+ 370
+ 371
+ 372
+ 373
+ 374
+ 375
+ 376
+ 377
+ 378
+ 379
+ 380
+ 381
+ 382
+ 383
+ 384
+ 385
+ 386
+ 387
+ 388
+ 389
+ 390
+ 391
+ 392
+ 393
+ 394
+ 395
+ 396
+ 397
+ 398
+ 399
+ 400
+ 401
+ 402
+ 403
+ 404
+ 405
+ 406
+ 407
+ 408
+ 409
+ 410
+ 411
+ 412
+ 413
+ 414
+ 415
+ 416
+ 417
+ 418
+ 419
+ 420
+ 421
+ 422
+ 423
+ 424
+ 425
+ 426
+ 427
+ 428
+ 429
+ 430
+ 431
+ 432
+ 433
+ 434
+ 435
+ 436
+ 437
+ 438
+ 439
+ 440
+ 441
+ 442
+ 443
+ 444
+ 445
+ 446
+ 447
+ 448
+ 449
+ 450
+ 451
+ 452
+ 453
+ 454
+ 455
+ 456
+ 457
+ 458
+ 459
+ 460
+ 461
+ 462
+ 463
+ 464
+ 465
+ 466
+ 467
+ 468
+ 469
+ 470
+ 471
+ 472
+ 473
+ 474
+ 475
+ 476
+ 477
+ 478
+ 479
+ 480
+ 481
+ 482
+ 483
+ 484
+ 485
+ 486
+ 487
+ 488
+ 489
+ 490
+ 491
+ 492
+ 493
+ 494
+ 495
+ 496
+ 497
+ 498
+ 499
+ 500
+ 501
+ 502
+ 503
+ 504
+ 505
+ 506
+ 507
+ 508
+ 509
+ 510
+ 511
+ 512
+ 513
+ 514
+ 515
+ 516
+ 517
+ 518
+ 519
+ 520
+ 521
+ 522
+ 523
+ 524
+ 525
+ 526
+ 527
+ 528
+ 529
+ 530
+ 531
+ 532
+ 533
+ 534
+ 535
+ 536
+ 537
+ 538
+ 539
+ 540
+ 541
+ 542
+ 543
+ 544
+ 545
+ 546
+ 547
+ 548
+ 549
+ 550
+ 551
+ 552
+ 553
+ 554
+ 555
+ 556
+ 557
+ 558
+ 559
+ 560
+ 561
+ 562
+ 563
+ 564
+ 565
+ 566
+ 567
+ 568
+ 569
+ 570
+ 571
+ 572
+ 573
+ 574
+ 575
+ 576
+ 577
+ 578
+ 579
+ 580
+ 581
+ 582
+ 583
+ 584
+ 585
+ 586
+ 587
+ 588
+ 589
+ 590
+ 591
+ 592
+ 593
+ 594
+ 595
+ 596
+ 597
+ 598
+ 599
+ 600
+ 601
+ 602
+ 603
+ 604
+ 605
+ 606
+ 607
+ 608
+ 609
+ 610
+ 611
+ 612
+ 613
+ 614
+ 615
+ 616
+ 617
+ 618
+ 619
+ 620
+ 621
+ 622
+ 623
+ 624
+ 625
+ 626
+ 627
+ 628
+ 629
+ 630
+ 631
+ 632
+ 633
+ 634
+ 635
+ 636
+ 637
+ 638
+ 639
+ 640
+ 641
+ 642
+ 643
+ 644
+ 645
+ 646
+ 647
+ 648
+ 649
+ 650
+ 651
+ 652
+ 653
+ 654
+ 655
+ 656
+ 657
+ 658
+ 659
+ 660
+ 661
+ 662
+ 663
+ 664
+ 665
+ 666
+ 667
+ 668
+ 669
+ 670
+ 671
+ 672
+ 673
+ 674
+ 675
+ 676
+ 677
+ 678
+ 679
+ 680
+ 681
+ 682
+ 683
+ 684
+ 685
+ 686
+ 687
+ 688
+ 689
+ 690
+ 691
+ 692
+ 693
+ 694
+ 695
+ 696
+ 697
+ 698
+ 699
+ 700
+ 701
+ 702
+ 703
+ 704
+ 705
+ 706
+ 707
+ 708
+ 709
+ 710
+ 711
+ 712
+ 713
+ 714
+ 715
+ 716
+ 717
+ 718
+ 719
+ 720
+ 721
+ 722
+ 723
+ 724
+ 725
+ 726
+ 727
+ 728
+ 729
+ 730
+ 731
+ 732
+ 733
+ 734
+ 735
+ 736
+ 737
+ 738
+ 739
+ 740
+ 741
+ 742
+ 743
+ 744
+ 745
+ 746
+ 747
+ 748
+ 749
+ 750
+ 751
+ 752
+ 753
+ 754
+ 755
+ 756
+ 757
+ 758
+ 759
+ 760
+ 761
+ 762
+ 763
+ 764
+ 765
+ 766
+ 767
+ 768
+ 769
+ 770
+ 771
+ 772
+ 773
+ 774
+ 775
+ 776
+ 777
+ 778
+ 779
+ 780
+ 781
+ 782
+ 783
+ 784
+ 785
+ 786
+ 787
+ 788
+ 789
+ 790
+ 791
+ 792
+ 793
+ 794
+ 795
+ 796
+ 797
+ 798
+ 799
+ 800
+ 801
+ 802
+ 803
+ 804
+ 805
+ 806
+ 807
+ 808
+ 809
+ 810
+ 811
+ 812
+ 813
+ 814
+ 815
+ 816
+ 817
+ 818
+ 819
+ 820
+ 821
+ 822
+ 823
+ 824
+ 825
+ 826
+ 827
+ 828
+ 829
+ 830
+ 831
+ 832
+ 833
+ 834
+ 835
+ 836
+ 837
+ 838
+ 839
+ 840
+ 841
+ 842
+ 843
+ 844
+ 845
+ 846
+ 847
+ 848
+ 849
+ 850
+ 851
+ 852
+ 853
+ 854
+ 855
+ 856
+ 857
+ 858
+ 859
+ 860
+ 861
+ 862
+ 863
+ 864
+ 865
+ 866
+ 867
+ 868
+ 869
+ 870
+ 871
+ 872
+ 873
+ 874
+ 875
+ 876
+ 877
+ 878
+ 879
+ 880
+ 881
+ 882
+ 883
+ 884
+ 885
+ 886
+ 887
+ 888
+ 889
+ 890
+ 891
+ 892
+ 893
+ 894
+ 895
+ 896
+ 897
+ 898
+ 899
+ 900
+ 901
+ 902
+ 903
+ 904
+ 905
+ 906
+ 907
+ 908
+ 909
+ 910
+ 911
+ 912
+ 913
+ 914
+ 915
+ 916
+ 917
+ 918
+ 919
+ 920
+ 921
+ 922
+ 923
+ 924
+ 925
+ 926
+ 927
+ 928
+ 929
+ 930
+ 931
+ 932
+ 933
+ 934
+ 935
+ 936
+ 937
+ 938
+ 939
+ 940
+ 941
+ 942
+ 943
+ 944
+ 945
+ 946
+ 947
+ 948
+ 949
+ 950
+ 951
+ 952
+ 953
+ 954
+ 955
+ 956
+ 957
+ 958
+ 959
+ 960
+ 961
+ 962
+ 963
+ 964
+ 965
+ 966
+ 967
+ 968
+ 969
+ 970
+ 971
+ 972
+ 973
+ 974
+ 975
+ 976
+ 977
+ 978
+ 979
+ 980
+ 981
+ 982
+ 983
+ 984
+ 985
+ 986
+ 987
+ 988
+ 989
+ 990
+ 991
+ 992
+ 993
+ 994
+ 995
+ 996
+ 997
+ 998
+ 999
+1000
+1001
+1002
+1003
+1004
+1005
+1006
+1007
+1008
+1009
+1010
+1011
+1012
+1013
+1014
+1015
+1016
+1017
+1018
+1019
+1020
+1021
+1022
+1023
+1024
+1025
+1026
+1027
+1028
+1029
+1030
+1031
+1032
+1033
+1034
+1035
+1036
+1037
+1038
+1039
+1040
+1041
+1042
+1043
+1044
+1045
+1046
+1047
+1048
+1049
+1050
+1051
+1052
+1053
+1054
+1055
+1056
+1057
+1058
+1059
+1060
+1061
+1062
+1063
+1064
+1065
+1066
+1067
+1068
+1069
+1070
+1071
+1072
+1073
+1074
+1075
+1076
+1077
+1078
+1079
+1080
+1081
+1082
+1083
+1084
+1085
+1086
+1087
+1088
+1089
+1090
+1091
+1092
+1093
+1094
+1095
+1096
+1097
+1098
+1099
+1100
+1101
+1102
+1103
+1104
+1105
+1106
+1107
+1108
+1109
+1110
+1111
+1112
+1113
+1114
+1115
+1116
+1117
+1118
+1119
+1120
+1121
+1122
+1123
+1124
+1125
+1126
+1127
+1128
+1129
+1130
+1131
+1132
+1133
+1134
+1135
+1136
+1137
+1138
+1139
+1140
+1141
+1142
+1143
+1144
+1145
+1146
+1147
+1148
+1149
+1150
+1151
+1152
+1153
+1154
+1155
+1156
+1157
+1158
+1159
+1160
+1161
+1162
+1163
+1164
+1165
+1166
+1167
+1168
+1169
+1170
+1171
+1172
+1173
+1174
+1175
+1176
+1177
+1178
+1179
+1180
+1181
+1182
+1183
+1184
+1185
+1186
+1187
+1188
+1189
+1190
+1191
+1192
+1193
+1194
+1195
+1196
+1197
+1198
+1199
+1200
+1201
+1202
+1203
+1204
+1205
+1206
+1207
+1208
+1209
+1210
+1211
+1212
+1213
+1214
+1215
+1216
+1217
+1218
+1219
+1220
+1221
+1222
+1223
+1224
+1225
+1226
+1227
+1228
+1229
+1230
+1231
+1232
+1233
+1234
+1235
+1236
+1237
+1238
+1239
+1240
+1241
+1242
+1243
+1244
+1245
+1246
+1247
+1248
+1249
+1250
+1251
+1252
+1253
+1254
+1255
+1256
+1257
+1258
+1259
+1260
+1261
+1262
+1263
+1264
+1265
+1266
+1267
+1268
+1269
+1270
+1271
+1272
+1273
+1274
+1275
+1276
+1277
+1278
+1279
+1280
+1281
+1282
+1283
+1284
+1285
+1286
+1287
+1288
+1289
+1290
+1291
+1292
+1293
+1294
+1295
+1296
+1297
+1298
+1299
+1300
+1301
+1302
+1303
+1304
+1305
+1306
+1307
+1308
+1309
+1310
+1311
+1312
+1313
+1314
+1315
+1316
+1317
+1318
+1319
+1320
+1321
+1322
+1323
+1324
+1325
+1326
+1327
+1328
+1329
+1330
+1331
+1332
+1333
+1334
+1335
+1336
+1337
+1338
+1339
+1340
+1341
+1342
+1343
+1344
+1345
+1346
+1347
+1348
+1349
+1350
+1351
+1352
+1353
+1354
+1355
+1356
+1357
+1358
+1359
+1360
+1361
+1362
+1363
+1364
+1365
+1366
+1367
+1368
+1369
+1370
+1371
+1372
+1373
+1374
+1375
+1376
+1377
+1378
+1379
+1380
+1381
+1382
+1383
+1384
+1385
+1386
+1387
+1388
+1389
+1390
+1391
+1392
+1393
+1394
+1395
+1396
+1397
+1398
+1399
+1400
+1401
+1402
+1403
+1404
+1405
+1406
+1407
+1408
+1409
/*
+ * Copyright (C) 2007 Novell, Inc.
+ *
+ * Inspired by various other pieces of code including GsmClient (C)
+ * 2001 Havoc Pennington, MateClient (C) 1998 Carsten Schaar, and twm
+ * session code (C) 1998 The Open Group.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+
+#include "eggsmclient.h"
+#include "eggsmclient-private.h"
+
+#include "eggdesktopfile.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <X11/SM/SMlib.h>
+
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+
+#if defined(GDK_WINDOWING_X11) || defined(HAVE_X11)
+#include <gdk/gdkx.h>
+#endif
+
+#define EGG_TYPE_SM_CLIENT_XSMP            (egg_sm_client_xsmp_get_type ())
+#define EGG_SM_CLIENT_XSMP(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), EGG_TYPE_SM_CLIENT_XSMP, EggSMClientXSMP))
+#define EGG_SM_CLIENT_XSMP_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), EGG_TYPE_SM_CLIENT_XSMP, EggSMClientXSMPClass))
+#define EGG_IS_SM_CLIENT_XSMP(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EGG_TYPE_SM_CLIENT_XSMP))
+#define EGG_IS_SM_CLIENT_XSMP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EGG_TYPE_SM_CLIENT_XSMP))
+#define EGG_SM_CLIENT_XSMP_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), EGG_TYPE_SM_CLIENT_XSMP, EggSMClientXSMPClass))
+
+typedef struct _EggSMClientXSMP        EggSMClientXSMP;
+typedef struct _EggSMClientXSMPClass   EggSMClientXSMPClass;
+
+/* These mostly correspond to the similarly-named states in section
+ * 9.1 of the XSMP spec. Some of the states there aren't represented
+ * here, because we don't need them. SHUTDOWN_CANCELLED is slightly
+ * different from the spec; we use it when the client is IDLE after a
+ * ShutdownCancelled message, but the application is still interacting
+ * and doesn't know the shutdown has been cancelled yet.
+ */
+typedef enum
+{
+    XSMP_STATE_IDLE,
+    XSMP_STATE_SAVE_YOURSELF,
+    XSMP_STATE_INTERACT_REQUEST,
+    XSMP_STATE_INTERACT,
+    XSMP_STATE_SAVE_YOURSELF_DONE,
+    XSMP_STATE_SHUTDOWN_CANCELLED,
+    XSMP_STATE_CONNECTION_CLOSED
+} EggSMClientXSMPState;
+
+static const char *state_names[] =
+{
+    "idle",
+    "save-yourself",
+    "interact-request",
+    "interact",
+    "save-yourself-done",
+    "shutdown-cancelled",
+    "connection-closed"
+};
+
+#define EGG_SM_CLIENT_XSMP_STATE(xsmp) (state_names[(xsmp)->state])
+
+struct _EggSMClientXSMP
+{
+    EggSMClient parent;
+
+    SmcConn connection;
+    char *client_id;
+
+    EggSMClientXSMPState state;
+    char **restart_command;
+    gboolean set_restart_command;
+    int restart_style;
+	char **discard_command;
+	gboolean set_discard_command;
+
+    guint idle;
+
+    /* Current SaveYourself state */
+    guint expecting_initial_save_yourself : 1;
+    guint need_save_state : 1;
+    guint need_quit_requested : 1;
+    guint interact_errors : 1;
+    guint shutting_down : 1;
+
+    /* Todo list */
+    guint waiting_to_set_initial_properties : 1;
+    guint waiting_to_emit_quit : 1;
+    guint waiting_to_emit_quit_cancelled : 1;
+    guint waiting_to_save_myself : 1;
+
+};
+
+struct _EggSMClientXSMPClass
+{
+    EggSMClientClass parent_class;
+
+};
+
+static void     sm_client_xsmp_startup (EggSMClient *client,
+                                        const char  *client_id);
+static void     sm_client_xsmp_set_restart_command (EggSMClient  *client,
+        int           argc,
+        const char  **argv);
+static void     sm_client_xsmp_set_discard_command (EggSMClient  *client,
+        int           argc,
+        const char  **argv);
+static void     sm_client_xsmp_will_quit (EggSMClient *client,
+        gboolean     will_quit);
+static gboolean sm_client_xsmp_end_session (EggSMClient         *client,
+        EggSMClientEndStyle  style,
+        gboolean  request_confirmation);
+
+static void xsmp_save_yourself      (SmcConn   smc_conn,
+                                     SmPointer client_data,
+                                     int       save_style,
+                                     Bool      shutdown,
+                                     int       interact_style,
+                                     Bool      fast);
+static void xsmp_die                (SmcConn   smc_conn,
+                                     SmPointer client_data);
+static void xsmp_save_complete      (SmcConn   smc_conn,
+                                     SmPointer client_data);
+static void xsmp_shutdown_cancelled (SmcConn   smc_conn,
+                                     SmPointer client_data);
+static void xsmp_interact           (SmcConn   smc_conn,
+                                     SmPointer client_data);
+
+static SmProp *array_prop        (const char    *name,
+                                  ...);
+static SmProp *ptrarray_prop     (const char    *name,
+                                  GPtrArray     *values);
+static SmProp *string_prop       (const char    *name,
+                                  const char    *value);
+static SmProp *card8_prop        (const char    *name,
+                                  unsigned char  value);
+
+static void set_properties         (EggSMClientXSMP *xsmp, ...);
+static void delete_properties      (EggSMClientXSMP *xsmp, ...);
+
+static GPtrArray *generate_command (char       **restart_command,
+                                    const char  *client_id,
+                                    const char  *state_file);
+
+static void save_state            (EggSMClientXSMP *xsmp);
+static void do_save_yourself      (EggSMClientXSMP *xsmp);
+static void update_pending_events (EggSMClientXSMP *xsmp);
+
+static void     ice_init             (void);
+static gboolean process_ice_messages (IceConn       ice_conn);
+static void     smc_error_handler    (SmcConn       smc_conn,
+                                      Bool          swap,
+                                      int           offending_minor_opcode,
+                                      unsigned long offending_sequence,
+                                      int           error_class,
+                                      int           severity,
+                                      SmPointer     values);
+
+G_DEFINE_TYPE (EggSMClientXSMP, egg_sm_client_xsmp, EGG_TYPE_SM_CLIENT)<--- There is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE is a macro then please configure it.
+
+static void
+egg_sm_client_xsmp_init (EggSMClientXSMP *xsmp)
+{
+    xsmp->state = XSMP_STATE_CONNECTION_CLOSED;
+    xsmp->connection = NULL;
+    xsmp->restart_style = SmRestartIfRunning;
+}
+
+static void
+egg_sm_client_xsmp_class_init (EggSMClientXSMPClass *klass)
+{
+    EggSMClientClass *sm_client_class = EGG_SM_CLIENT_CLASS (klass);
+
+    sm_client_class->startup             = sm_client_xsmp_startup;
+    sm_client_class->set_restart_command = sm_client_xsmp_set_restart_command;
+	sm_client_class->set_discard_command = sm_client_xsmp_set_discard_command;
+    sm_client_class->will_quit           = sm_client_xsmp_will_quit;
+    sm_client_class->end_session         = sm_client_xsmp_end_session;
+}
+
+EggSMClient *
+egg_sm_client_xsmp_new (void)
+{
+    if (!g_getenv ("SESSION_MANAGER"))
+        return NULL;
+
+    return g_object_new (EGG_TYPE_SM_CLIENT_XSMP, NULL);
+}
+
+static gboolean
+sm_client_xsmp_set_initial_properties (gpointer user_data)
+{
+    EggSMClientXSMP *xsmp = user_data;
+    EggDesktopFile *desktop_file;
+    GPtrArray *clone, *restart;
+    char pid_str[64];
+
+    if (xsmp->idle)
+    {
+        g_source_remove (xsmp->idle);
+        xsmp->idle = 0;
+    }
+    xsmp->waiting_to_set_initial_properties = FALSE;
+
+    if (egg_sm_client_get_mode () == EGG_SM_CLIENT_MODE_NO_RESTART)
+        xsmp->restart_style = SmRestartNever;
+
+    /* Parse info out of desktop file */
+    desktop_file = egg_get_desktop_file ();
+    if (desktop_file)
+    {
+        GError *err = NULL;
+        char **argv;
+        int argc;
+
+        if (xsmp->restart_style == SmRestartIfRunning)
+        {
+            if (egg_desktop_file_get_boolean (desktop_file,
+                                              "X-MATE-AutoRestart", NULL))
+                xsmp->restart_style = SmRestartImmediately;
+        }
+
+        if (!xsmp->set_restart_command)
+        {
+            char *cmdline;
+
+            cmdline = egg_desktop_file_parse_exec (desktop_file, NULL, &err);
+            if (cmdline && g_shell_parse_argv (cmdline, &argc, &argv, &err))
+            {
+                egg_sm_client_set_restart_command (EGG_SM_CLIENT (xsmp),
+                                                   argc, (const char **)argv);
+                g_strfreev (argv);
+            }
+            else
+            {
+                g_warning ("Could not parse Exec line in desktop file: %s",
+                           err->message);
+                g_error_free (err);
+            }
+            g_free (cmdline);
+        }
+    }
+
+    if (!xsmp->set_restart_command)
+        xsmp->restart_command = g_strsplit (g_get_prgname (), " ", -1);
+
+    clone = generate_command (xsmp->restart_command, NULL, NULL);
+    restart = generate_command (xsmp->restart_command, xsmp->client_id, NULL);
+
+    g_debug ("Setting initial properties");
+
+    /* Program, CloneCommand, RestartCommand, and UserID are required.
+     * ProcessID isn't required, but the SM may be able to do something
+     * useful with it.
+     */
+    g_snprintf (pid_str, sizeof (pid_str), "%lu", (gulong) getpid ());
+    set_properties (xsmp,
+                    string_prop   (SmProgram, g_get_prgname ()),
+                    ptrarray_prop (SmCloneCommand, clone),
+                    ptrarray_prop (SmRestartCommand, restart),
+                    string_prop   (SmUserID, g_get_user_name ()),
+                    string_prop   (SmProcessID, pid_str),
+                    card8_prop    (SmRestartStyleHint, xsmp->restart_style),
+                    NULL);
+    g_ptr_array_free (clone, TRUE);
+    g_ptr_array_free (restart, TRUE);
+
+    if (desktop_file)
+    {
+        set_properties (xsmp,
+                        string_prop ("_GSM_DesktopFile", egg_desktop_file_get_source (desktop_file)),
+                        NULL);
+    }
+
+    update_pending_events (xsmp);
+    return FALSE;
+}
+
+/* This gets called from two different places: xsmp_die() (when the
+ * server asks us to disconnect) and process_ice_messages() (when the
+ * server disconnects unexpectedly).
+ */
+static void
+sm_client_xsmp_disconnect (EggSMClientXSMP *xsmp)
+{
+    SmcConn connection;
+
+    if (!xsmp->connection)
+        return;
+
+    g_debug ("Disconnecting");
+
+    connection = xsmp->connection;
+    xsmp->connection = NULL;
+    SmcCloseConnection (connection, 0, NULL);
+    xsmp->state = XSMP_STATE_CONNECTION_CLOSED;
+
+    xsmp->waiting_to_save_myself = FALSE;
+    update_pending_events (xsmp);
+}
+
+static void
+sm_client_xsmp_startup (EggSMClient *client,
+                        const char  *client_id)
+{
+    EggSMClientXSMP *xsmp = (EggSMClientXSMP *)client;
+    SmcCallbacks callbacks;
+    char *ret_client_id;
+    char error_string_ret[256];
+
+    xsmp->client_id = g_strdup (client_id);
+
+    ice_init ();
+    SmcSetErrorHandler (smc_error_handler);
+
+    callbacks.save_yourself.callback      = xsmp_save_yourself;
+    callbacks.die.callback                = xsmp_die;
+    callbacks.save_complete.callback      = xsmp_save_complete;
+    callbacks.shutdown_cancelled.callback = xsmp_shutdown_cancelled;
+
+    callbacks.save_yourself.client_data      = xsmp;
+    callbacks.die.client_data                = xsmp;
+    callbacks.save_complete.client_data      = xsmp;
+    callbacks.shutdown_cancelled.client_data = xsmp;
+
+    client_id = NULL;
+    error_string_ret[0] = '\0';
+    xsmp->connection =
+        SmcOpenConnection (NULL, xsmp, SmProtoMajor, SmProtoMinor,
+                           SmcSaveYourselfProcMask | SmcDieProcMask |
+                           SmcSaveCompleteProcMask |
+                           SmcShutdownCancelledProcMask,
+                           &callbacks,
+                           xsmp->client_id, &ret_client_id,
+                           sizeof (error_string_ret), error_string_ret);
+
+    if (!xsmp->connection)
+    {
+        g_warning ("Failed to connect to the session manager: %s\n",
+                   error_string_ret[0] ?
+                   error_string_ret : "no error message given");
+        xsmp->state = XSMP_STATE_CONNECTION_CLOSED;
+        return;
+    }
+
+    /* We expect a pointless initial SaveYourself if either (a) we
+     * didn't have an initial client ID, or (b) we DID have an initial
+     * client ID, but the server rejected it and gave us a new one.
+     */
+    if (!xsmp->client_id ||
+            (ret_client_id && strcmp (xsmp->client_id, ret_client_id) != 0))
+        xsmp->expecting_initial_save_yourself = TRUE;
+
+    if (ret_client_id)
+    {
+        g_free (xsmp->client_id);
+        xsmp->client_id = g_strdup (ret_client_id);
+        free (ret_client_id);
+
+#if defined(GDK_WINDOWING_X11) || defined(HAVE_X11)
+      if (GDK_IS_X11_DISPLAY (gdk_display_get_default ()))
+        gdk_x11_set_sm_client_id (xsmp->client_id);
+#endif
+
+        g_debug ("Got client ID \"%s\"", xsmp->client_id);
+    }
+
+    xsmp->state = XSMP_STATE_IDLE;
+
+    /* Do not set the initial properties until we reach the main loop,
+     * so that the application has a chance to call
+     * egg_set_desktop_file(). (This may also help the session manager
+     * have a better idea of when the application is fully up and
+     * running.)
+     */
+    xsmp->waiting_to_set_initial_properties = TRUE;
+    xsmp->idle = g_idle_add (sm_client_xsmp_set_initial_properties, client);
+}
+
+static void
+sm_client_xsmp_set_restart_command (EggSMClient  *client,
+                                    int           argc,
+                                    const char  **argv)
+{
+    EggSMClientXSMP *xsmp = (EggSMClientXSMP *)client;
+    int i;
+
+    g_strfreev (xsmp->restart_command);
+
+    xsmp->restart_command = g_new (char *, argc + 1);
+    for (i = 0; i < argc; i++)
+        xsmp->restart_command[i] = g_strdup (argv[i]);
+    xsmp->restart_command[i] = NULL;
+
+    xsmp->set_restart_command = TRUE;
+}
+
+static void
+sm_client_xsmp_set_discard_command (EggSMClient  *client,
+                                    int           argc,
+                                    const char  **argv)
+{
+	EggSMClientXSMP *xsmp = (EggSMClientXSMP *)client;
+	int i;
+
+	g_strfreev (xsmp->discard_command);
+
+	xsmp->discard_command = g_new (char *, argc + 1);
+	for (i = 0; i < argc; i++)
+		xsmp->discard_command[i] = g_strdup (argv[i]);
+	xsmp->discard_command[i] = NULL;
+
+	xsmp->set_discard_command = TRUE;
+}
+
+static void
+sm_client_xsmp_will_quit (EggSMClient *client,
+                          gboolean     will_quit)
+{
+    EggSMClientXSMP *xsmp = (EggSMClientXSMP *)client;
+
+    if (xsmp->state == XSMP_STATE_CONNECTION_CLOSED)
+    {
+        /* The session manager has already exited! Schedule a quit
+         * signal.
+         */
+        xsmp->waiting_to_emit_quit = TRUE;
+        update_pending_events (xsmp);
+        return;
+    }
+    else if (xsmp->state == XSMP_STATE_SHUTDOWN_CANCELLED)
+    {
+        /* We received a ShutdownCancelled message while the application
+         * was interacting; Schedule a quit_cancelled signal.
+         */
+        xsmp->waiting_to_emit_quit_cancelled = TRUE;
+        update_pending_events (xsmp);
+        return;
+    }
+
+    g_return_if_fail (xsmp->state == XSMP_STATE_INTERACT);
+
+    g_debug ("Sending InteractDone(%s)", will_quit ? "False" : "True");
+    SmcInteractDone (xsmp->connection, !will_quit);
+
+    if (will_quit && xsmp->need_save_state)
+        save_state (xsmp);
+
+    g_debug ("Sending SaveYourselfDone(%s)", will_quit ? "True" : "False");
+    SmcSaveYourselfDone (xsmp->connection, will_quit);
+    xsmp->state = XSMP_STATE_SAVE_YOURSELF_DONE;
+}
+
+static gboolean
+sm_client_xsmp_end_session (EggSMClient         *client,
+                            EggSMClientEndStyle  style,
+                            gboolean             request_confirmation)
+{
+    EggSMClientXSMP *xsmp = (EggSMClientXSMP *)client;
+    int save_type;
+
+    /* To end the session via XSMP, we have to send a
+     * SaveYourselfRequest. We aren't allowed to do that if anything
+     * else is going on, but we don't want to expose this fact to the
+     * application. So we do our best to patch things up here...
+     *
+     * In the worst case, this method might block for some length of
+     * time in process_ice_messages, but the only time that code path is
+     * honestly likely to get hit is if the application tries to end the
+     * session as the very first thing it does, in which case it
+     * probably won't actually block anyway. It's not worth gunking up
+     * the API to try to deal nicely with the other 0.01% of cases where
+     * this happens.
+     */
+
+    while (xsmp->state != XSMP_STATE_IDLE ||
+            xsmp->expecting_initial_save_yourself)
+    {
+        /* If we're already shutting down, we don't need to do anything. */
+        if (xsmp->shutting_down)
+            return TRUE;
+
+        switch (xsmp->state)
+        {
+        case XSMP_STATE_CONNECTION_CLOSED:
+            return FALSE;
+
+        case XSMP_STATE_SAVE_YOURSELF:
+            /* Trying to log out from the save_state callback? Whatever.
+             * Abort the save_state.
+             */
+            SmcSaveYourselfDone (xsmp->connection, FALSE);
+            xsmp->state = XSMP_STATE_SAVE_YOURSELF_DONE;
+            break;
+
+        case XSMP_STATE_INTERACT_REQUEST:
+        case XSMP_STATE_INTERACT:
+        case XSMP_STATE_SHUTDOWN_CANCELLED:
+            /* Already in a shutdown-related state, just ignore
+             * the new shutdown request...
+             */
+            return TRUE;
+
+        case XSMP_STATE_IDLE:
+            if (xsmp->waiting_to_set_initial_properties)
+                sm_client_xsmp_set_initial_properties (xsmp);
+
+            if (!xsmp->expecting_initial_save_yourself)
+                break;
+            /* else fall through */
+
+        case XSMP_STATE_SAVE_YOURSELF_DONE:
+            /* We need to wait for some response from the server.*/
+            process_ice_messages (SmcGetIceConnection (xsmp->connection));
+            break;
+
+        default:
+            /* Hm... shouldn't happen */
+            return FALSE;
+        }
+    }
+
+    /* xfce4-session will do the wrong thing if we pass SmSaveGlobal and
+     * the user chooses to save the session. But mate-session will do
+     * the wrong thing if we pass SmSaveBoth and the user chooses NOT to
+     * save the session... Sigh.
+     */
+    if (!strcmp (SmcVendor (xsmp->connection), "xfce4-session"))
+        save_type = SmSaveBoth;
+    else
+        save_type = SmSaveGlobal;
+
+    g_debug ("Sending SaveYourselfRequest(SmSaveGlobal, Shutdown, SmInteractStyleAny, %sFast)", request_confirmation ? "!" : "");
+    SmcRequestSaveYourself (xsmp->connection,
+                            save_type,
+                            True, /* shutdown */
+                            SmInteractStyleAny,
+                            !request_confirmation, /* fast */
+                            True /* global */);
+    return TRUE;
+}
+
+static gboolean
+idle_do_pending_events (gpointer data)
+{
+    EggSMClientXSMP *xsmp = data;
+    EggSMClient *client = data;
+
+    xsmp->idle = 0;
+
+    if (xsmp->waiting_to_emit_quit)
+    {
+        xsmp->waiting_to_emit_quit = FALSE;
+        egg_sm_client_quit (client);
+        goto out;
+    }
+
+    if (xsmp->waiting_to_emit_quit_cancelled)
+    {
+        xsmp->waiting_to_emit_quit_cancelled = FALSE;
+        egg_sm_client_quit_cancelled (client);
+        xsmp->state = XSMP_STATE_IDLE;
+    }
+
+    if (xsmp->waiting_to_save_myself)
+    {
+        xsmp->waiting_to_save_myself = FALSE;
+        do_save_yourself (xsmp);
+    }
+
+out:
+    return FALSE;
+}
+
+static void
+update_pending_events (EggSMClientXSMP *xsmp)
+{
+    gboolean want_idle =
+        xsmp->waiting_to_emit_quit ||
+        xsmp->waiting_to_emit_quit_cancelled ||
+        xsmp->waiting_to_save_myself;
+
+    if (want_idle)
+    {
+        if (xsmp->idle == 0)
+            xsmp->idle = g_idle_add (idle_do_pending_events, xsmp);
+    }
+    else
+    {
+        if (xsmp->idle != 0)
+            g_source_remove (xsmp->idle);
+        xsmp->idle = 0;
+    }
+}
+
+static void
+fix_broken_state (EggSMClientXSMP *xsmp, const char *message,
+                  gboolean send_interact_done,
+                  gboolean send_save_yourself_done)
+{
+    g_warning ("Received XSMP %s message in state %s: client or server error",
+               message, EGG_SM_CLIENT_XSMP_STATE (xsmp));
+
+    /* Forget any pending SaveYourself plans we had */
+    xsmp->waiting_to_save_myself = FALSE;
+    update_pending_events (xsmp);
+
+    if (send_interact_done)
+        SmcInteractDone (xsmp->connection, False);
+    if (send_save_yourself_done)
+        SmcSaveYourselfDone (xsmp->connection, True);
+
+    xsmp->state = send_save_yourself_done ? XSMP_STATE_SAVE_YOURSELF_DONE : XSMP_STATE_IDLE;
+}
+
+/* SM callbacks */
+
+static void
+xsmp_save_yourself (SmcConn   smc_conn,
+                    SmPointer client_data,
+                    int       save_type,
+                    Bool      shutdown,
+                    int       interact_style,
+                    Bool      fast)
+{
+    EggSMClientXSMP *xsmp = client_data;
+    gboolean wants_quit_requested;
+
+    g_debug ("Received SaveYourself(%s, %s, %s, %s) in state %s",
+             save_type == SmSaveLocal ? "SmSaveLocal" :
+             save_type == SmSaveGlobal ? "SmSaveGlobal" : "SmSaveBoth",
+             shutdown ? "Shutdown" : "!Shutdown",
+             interact_style == SmInteractStyleAny ? "SmInteractStyleAny" :
+             interact_style == SmInteractStyleErrors ? "SmInteractStyleErrors" :
+             "SmInteractStyleNone", fast ? "Fast" : "!Fast",
+             EGG_SM_CLIENT_XSMP_STATE (xsmp));
+
+    if (xsmp->state != XSMP_STATE_IDLE &&
+            xsmp->state != XSMP_STATE_SHUTDOWN_CANCELLED)
+    {
+        fix_broken_state (xsmp, "SaveYourself", FALSE, TRUE);
+        return;
+    }
+
+    if (xsmp->waiting_to_set_initial_properties)
+        sm_client_xsmp_set_initial_properties (xsmp);
+
+    /* If this is the initial SaveYourself, ignore it; we've already set
+     * properties and there's no reason to actually save state too.
+     */
+    if (xsmp->expecting_initial_save_yourself)
+    {
+        xsmp->expecting_initial_save_yourself = FALSE;
+
+        if (save_type == SmSaveLocal &&
+                interact_style == SmInteractStyleNone &&
+                !shutdown && !fast)
+        {
+            g_debug ("Sending SaveYourselfDone(True) for initial SaveYourself");
+            SmcSaveYourselfDone (xsmp->connection, True);
+            /* As explained in the comment at the end of
+             * do_save_yourself(), SAVE_YOURSELF_DONE is the correct
+             * state here, not IDLE.
+             */
+            xsmp->state = XSMP_STATE_SAVE_YOURSELF_DONE;
+            return;
+        }
+        else
+            g_warning ("First SaveYourself was not the expected one!");
+    }
+
+    /* Even ignoring the "fast" flag completely, there are still 18
+     * different combinations of save_type, shutdown and interact_style.
+     * We interpret them as follows:
+     *
+     *   Type  Shutdown  Interact	 Interpretation
+     *     G      F       A/E/N  	 do nothing (1)
+     *     G      T         N    	 do nothing (1)*
+     *     G      T        A/E   	 quit_requested (2)
+     *    L/B     F       A/E/N  	 save_state (3)
+     *    L/B     T         N    	 save_state (3)*
+     *    L/B     T        A/E   	 quit_requested, then save_state (4)
+     *
+     *   1. Do nothing, because the SM asked us to do something
+     *      uninteresting (save open files, but then don't quit
+     *      afterward) or rude (save open files without asking the user
+     *      for confirmation).
+     *
+     *   2. Request interaction and then emit ::quit_requested. This
+     *      perhaps isn't quite correct for the SmInteractStyleErrors
+     *      case, but we don't care.
+     *
+     *   3. Emit ::save_state. The SmSaveBoth SaveYourselfs in these
+     *      rows essentially get demoted to SmSaveLocal, because their
+     *      Global halves correspond to "do nothing".
+     *
+     *   4. Request interaction, emit ::quit_requested, and then emit
+     *      ::save_state after interacting. This is the SmSaveBoth
+     *      equivalent of #2, but we also promote SmSaveLocal shutdown
+     *      SaveYourselfs to SmSaveBoth here, because we want to give
+     *      the user a chance to save open files before quitting.
+     *
+     * (* It would be nice if we could do something useful when the
+     * session manager sends a SaveYourself with shutdown True and
+     * SmInteractStyleNone. But we can't, so we just pretend it didn't
+     * even tell us it was shutting down. The docs for ::quit mention
+     * that it might not always be preceded by ::quit_requested.)
+     */
+
+    /* As an optimization, we don't actually request interaction and
+     * emit ::quit_requested if the application isn't listening to the
+     * signal.
+     */
+    wants_quit_requested = g_signal_has_handler_pending (xsmp, g_signal_lookup ("quit_requested", EGG_TYPE_SM_CLIENT), 0, FALSE);
+
+    xsmp->need_save_state     = (save_type != SmSaveGlobal);
+    xsmp->need_quit_requested = (shutdown && wants_quit_requested &&
+                                 interact_style != SmInteractStyleNone);
+    xsmp->interact_errors     = (interact_style == SmInteractStyleErrors);
+
+    xsmp->shutting_down       = shutdown;
+
+    do_save_yourself (xsmp);
+}
+
+static void
+do_save_yourself (EggSMClientXSMP *xsmp)
+{
+    if (xsmp->state == XSMP_STATE_SHUTDOWN_CANCELLED)
+    {
+        /* The SM cancelled a previous SaveYourself, but we haven't yet
+         * had a chance to tell the application, so we can't start
+         * processing this SaveYourself yet.
+         */
+        xsmp->waiting_to_save_myself = TRUE;
+        update_pending_events (xsmp);
+        return;
+    }
+
+    if (xsmp->need_quit_requested)
+    {
+        xsmp->state = XSMP_STATE_INTERACT_REQUEST;
+
+        g_debug ("Sending InteractRequest(%s)",
+                 xsmp->interact_errors ? "Error" : "Normal");
+        SmcInteractRequest (xsmp->connection,
+                            xsmp->interact_errors ? SmDialogError : SmDialogNormal,
+                            xsmp_interact,
+                            xsmp);
+        return;
+    }
+
+    if (xsmp->need_save_state)
+    {
+        save_state (xsmp);
+
+        /* Though unlikely, the client could have been disconnected
+         * while the application was saving its state.
+         */
+        if (!xsmp->connection)
+            return;
+    }
+
+    g_debug ("Sending SaveYourselfDone(True)");
+    SmcSaveYourselfDone (xsmp->connection, True);
+
+    /* The client state diagram in the XSMP spec says that after a
+     * non-shutdown SaveYourself, we go directly back to "idle". But
+     * everything else in both the XSMP spec and the libSM docs
+     * disagrees.
+     */
+    xsmp->state = XSMP_STATE_SAVE_YOURSELF_DONE;
+}
+
+static void
+save_state (EggSMClientXSMP *xsmp)
+{
+    GKeyFile *state_file;
+    char *state_file_path, *data;
+    EggDesktopFile *desktop_file;
+	GPtrArray *restart, *discard;
+    int offset, fd;
+
+    /* We set xsmp->state before emitting save_state, but our caller is
+     * responsible for setting it back afterward.
+     */
+    xsmp->state = XSMP_STATE_SAVE_YOURSELF;
+
+    state_file = egg_sm_client_save_state ((EggSMClient *)xsmp);
+    if (!state_file)
+    {
+        restart = generate_command (xsmp->restart_command, xsmp->client_id, NULL);
+        set_properties (xsmp,
+                        ptrarray_prop (SmRestartCommand, restart),
+                        NULL);
+        g_ptr_array_free (restart, TRUE);
+
+		if (xsmp->set_discard_command)
+		{
+			discard = generate_command (xsmp->discard_command, NULL, NULL);
+			set_properties (xsmp,
+			                ptrarray_prop (SmDiscardCommand, discard),
+			                NULL);
+			g_ptr_array_free (discard, TRUE);
+		}
+		else
+        delete_properties (xsmp, SmDiscardCommand, NULL);
+
+        return;
+    }
+
+    desktop_file = egg_get_desktop_file ();
+    if (desktop_file)
+    {
+        GKeyFile *merged_file;
+        char *desktop_file_path;
+
+        merged_file = g_key_file_new ();
+        desktop_file_path =
+            g_filename_from_uri (egg_desktop_file_get_source (desktop_file),
+                                 NULL, NULL);
+        if (desktop_file_path &&
+                g_key_file_load_from_file (merged_file, desktop_file_path,
+                                           G_KEY_FILE_KEEP_COMMENTS |
+                                           G_KEY_FILE_KEEP_TRANSLATIONS, NULL))
+        {
+            guint g, k, i;
+            char **groups, **keys, *value, *exec;
+
+            groups = g_key_file_get_groups (state_file, NULL);
+            for (g = 0; groups[g]; g++)
+            {
+                keys = g_key_file_get_keys (state_file, groups[g], NULL, NULL);
+                for (k = 0; keys[k]; k++)
+                {
+                    value = g_key_file_get_value (state_file, groups[g],
+                                                  keys[k], NULL);
+                    if (value)
+                    {
+                        g_key_file_set_value (merged_file, groups[g],
+                                              keys[k], value);
+                        g_free (value);
+                    }
+                }
+                g_strfreev (keys);
+            }
+            g_strfreev (groups);
+
+            g_key_file_free (state_file);
+            state_file = merged_file;
+
+            /* Update Exec key using "--sm-client-state-file %k" */
+            restart = generate_command (xsmp->restart_command,
+                                        NULL, "%k");
+            for (i = 0; i < restart->len; i++)
+                restart->pdata[i] = g_shell_quote (restart->pdata[i]);
+            g_ptr_array_add (restart, NULL);
+            exec = g_strjoinv (" ", (char **)restart->pdata);
+            g_strfreev ((char **)restart->pdata);
+            g_ptr_array_free (restart, FALSE);
+
+            g_key_file_set_string (state_file, EGG_DESKTOP_FILE_GROUP,
+                                   EGG_DESKTOP_FILE_KEY_EXEC,
+                                   exec);
+            g_free (exec);
+        }
+        else
+            desktop_file = NULL;
+
+        g_free (desktop_file_path);
+    }
+
+    /* Now write state_file to disk. (We can't use mktemp(), because
+     * that requires the filename to end with "XXXXXX", and we want
+     * it to end with ".desktop".)
+     */
+
+    data = g_key_file_to_data (state_file, NULL, NULL);
+    g_key_file_free (state_file);
+
+    offset = 0;
+    while (1)
+    {
+        state_file_path = g_strdup_printf ("%s%csession-state%c%s-%ld.%s",
+                                           g_get_user_config_dir (),
+                                           G_DIR_SEPARATOR, G_DIR_SEPARATOR,
+                                           g_get_prgname (),
+                                           (long)time (NULL) + offset,
+                                           desktop_file ? "desktop" : "state");
+
+        fd = open (state_file_path, O_WRONLY | O_CREAT | O_EXCL, 0644);
+        if (fd == -1)
+        {
+            if (errno == EEXIST)
+            {
+                offset++;
+                g_free (state_file_path);
+                continue;
+            }
+            else if (errno == ENOTDIR || errno == ENOENT)
+            {
+                char *sep = strrchr (state_file_path, G_DIR_SEPARATOR);
+
+                *sep = '\0';
+                if (g_mkdir_with_parents (state_file_path, 0755) != 0)
+                {
+                    g_warning ("Could not create directory '%s'",
+                               state_file_path);
+                    g_free (state_file_path);
+                    state_file_path = NULL;
+                    break;
+                }
+
+                continue;
+            }
+
+            g_warning ("Could not create file '%s': %s",
+                       state_file_path, g_strerror (errno));
+            g_free (state_file_path);
+            state_file_path = NULL;
+            break;
+        }
+
+        close (fd);
+        g_file_set_contents (state_file_path, data, -1, NULL);
+        break;
+    }
+    g_free (data);
+
+    restart = generate_command (xsmp->restart_command, xsmp->client_id,
+                                state_file_path);
+    set_properties (xsmp,
+                    ptrarray_prop (SmRestartCommand, restart),
+                    NULL);
+    g_ptr_array_free (restart, TRUE);
+
+    if (state_file_path)
+    {
+        set_properties (xsmp,
+                        array_prop (SmDiscardCommand,
+                                    "/bin/rm", "-rf", state_file_path,
+                                    NULL),
+                        NULL);
+        g_free (state_file_path);
+    }
+}
+
+static void
+xsmp_interact (SmcConn   smc_conn,
+               SmPointer client_data)
+{
+    EggSMClientXSMP *xsmp = client_data;
+    EggSMClient *client = client_data;
+
+    g_debug ("Received Interact message in state %s",
+             EGG_SM_CLIENT_XSMP_STATE (xsmp));
+
+    if (xsmp->state != XSMP_STATE_INTERACT_REQUEST)
+    {
+        fix_broken_state (xsmp, "Interact", TRUE, TRUE);
+        return;
+    }
+
+    xsmp->state = XSMP_STATE_INTERACT;
+    egg_sm_client_quit_requested (client);
+}
+
+static void
+xsmp_die (SmcConn   smc_conn,
+          SmPointer client_data)
+{
+    EggSMClientXSMP *xsmp = client_data;
+    EggSMClient *client = client_data;
+
+    g_debug ("Received Die message in state %s",
+             EGG_SM_CLIENT_XSMP_STATE (xsmp));
+
+    sm_client_xsmp_disconnect (xsmp);
+    egg_sm_client_quit (client);
+}
+
+static void
+xsmp_save_complete (SmcConn   smc_conn,
+                    SmPointer client_data)
+{
+    EggSMClientXSMP *xsmp = client_data;
+
+    g_debug ("Received SaveComplete message in state %s",
+             EGG_SM_CLIENT_XSMP_STATE (xsmp));
+
+    if (xsmp->state == XSMP_STATE_SAVE_YOURSELF_DONE)
+        xsmp->state = XSMP_STATE_IDLE;
+    else
+        fix_broken_state (xsmp, "SaveComplete", FALSE, FALSE);
+}
+
+static void
+xsmp_shutdown_cancelled (SmcConn   smc_conn,
+                         SmPointer client_data)
+{
+    EggSMClientXSMP *xsmp = client_data;
+    EggSMClient *client = client_data;
+
+    g_debug ("Received ShutdownCancelled message in state %s",
+             EGG_SM_CLIENT_XSMP_STATE (xsmp));
+
+    xsmp->shutting_down = FALSE;
+
+    if (xsmp->state == XSMP_STATE_SAVE_YOURSELF_DONE)
+    {
+        /* We've finished interacting and now the SM has agreed to
+         * cancel the shutdown.
+         */
+        xsmp->state = XSMP_STATE_IDLE;
+        egg_sm_client_quit_cancelled (client);
+    }
+    else if (xsmp->state == XSMP_STATE_SHUTDOWN_CANCELLED)
+    {
+        /* Hm... ok, so we got a shutdown SaveYourself, which got
+         * cancelled, but the application was still interacting, so we
+         * didn't tell it yet, and then *another* SaveYourself arrived,
+         * which we must still be waiting to tell the app about, except
+         * that now that SaveYourself has been cancelled too! Dizzy yet?
+         */
+        xsmp->waiting_to_save_myself = FALSE;
+        update_pending_events (xsmp);
+    }
+    else
+    {
+        g_debug ("Sending SaveYourselfDone(False)");
+        SmcSaveYourselfDone (xsmp->connection, False);
+
+        if (xsmp->state == XSMP_STATE_INTERACT)
+        {
+            /* The application is currently interacting, so we can't
+             * tell it about the cancellation yet; we will wait until
+             * after it calls egg_sm_client_will_quit().
+             */
+            xsmp->state = XSMP_STATE_SHUTDOWN_CANCELLED;
+        }
+        else
+        {
+            /* The shutdown was cancelled before the application got a
+             * chance to interact.
+             */
+            xsmp->state = XSMP_STATE_IDLE;
+        }
+    }
+}
+
+/* Utilities */
+
+/* Create a restart/clone/Exec command based on @restart_command.
+ * If @client_id is non-%NULL, add "--sm-client-id @client_id".
+ * If @state_file is non-%NULL, add "--sm-client-state-file @state_file".
+ *
+ * None of the input strings are g_strdup()ed; the caller must keep
+ * them around until it is done with the returned GPtrArray, and must
+ * then free the array, but not its contents.
+ */
+static GPtrArray *
+generate_command (char **restart_command, const char *client_id,
+                  const char *state_file)
+{
+    GPtrArray *cmd;
+    int i;
+
+    cmd = g_ptr_array_new ();
+    g_ptr_array_add (cmd, restart_command[0]);
+
+    if (client_id)
+    {
+        g_ptr_array_add (cmd, (char *)"--sm-client-id");
+        g_ptr_array_add (cmd, (char *)client_id);
+    }
+
+    if (state_file)
+    {
+        g_ptr_array_add (cmd, (char *)"--sm-client-state-file");
+        g_ptr_array_add (cmd, (char *)state_file);
+    }
+
+    for (i = 1; restart_command[i]; i++)
+        g_ptr_array_add (cmd, restart_command[i]);
+
+    return cmd;
+}
+
+/* Takes a NULL-terminated list of SmProp * values, created by
+ * array_prop, ptrarray_prop, string_prop, card8_prop, sets them, and
+ * frees them.
+ */
+static void
+set_properties (EggSMClientXSMP *xsmp, ...)
+{
+    GPtrArray *props;
+    SmProp *prop;
+    va_list ap;
+    guint i;
+
+    props = g_ptr_array_new ();
+
+    va_start (ap, xsmp);
+    while ((prop = va_arg (ap, SmProp *)))
+        g_ptr_array_add (props, prop);
+    va_end (ap);
+
+    if (xsmp->connection)
+    {
+        SmcSetProperties (xsmp->connection, props->len,
+                          (SmProp **)props->pdata);
+    }
+
+    for (i = 0; i < props->len; i++)
+    {
+        prop = props->pdata[i];
+        g_free (prop->vals);
+        g_free (prop);
+    }
+    g_ptr_array_free (props, TRUE);
+}
+
+/* Takes a NULL-terminated list of property names and deletes them. */
+static void
+delete_properties (EggSMClientXSMP *xsmp, ...)
+{
+    GPtrArray *props;
+    char *prop;
+    va_list ap;
+
+    if (!xsmp->connection)
+        return;
+
+    props = g_ptr_array_new ();
+
+    va_start (ap, xsmp);
+    while ((prop = va_arg (ap, char *)))
+        g_ptr_array_add (props, prop);
+    va_end (ap);
+
+    SmcDeleteProperties (xsmp->connection, props->len,
+                         (char **)props->pdata);
+
+    g_ptr_array_free (props, TRUE);
+}
+
+/* Takes an array of strings and creates a LISTofARRAY8 property. The
+ * strings are neither dupped nor freed; they need to remain valid
+ * until you're done with the SmProp.
+ */
+static SmProp *
+array_prop (const char *name, ...)
+{
+    SmProp *prop;
+    SmPropValue pv;
+    GArray *vals;
+    char *value;
+    va_list ap;
+
+    prop = g_new (SmProp, 1);
+    prop->name = (char *)name;
+    prop->type = (char *)SmLISTofARRAY8;
+
+    vals = g_array_new (FALSE, FALSE, sizeof (SmPropValue));
+
+    va_start (ap, name);
+    while ((value = va_arg (ap, char *)))
+    {
+        pv.length = strlen (value);
+        pv.value = value;
+        g_array_append_val (vals, pv);
+    }
+    va_end (ap);
+
+    prop->num_vals = vals->len;
+    prop->vals = (SmPropValue *)vals->data;
+
+    g_array_free (vals, FALSE);
+
+    return prop;
+}
+
+/* Takes a GPtrArray of strings and creates a LISTofARRAY8 property.
+ * The array contents are neither dupped nor freed; they need to
+ * remain valid until you're done with the SmProp.
+ */
+static SmProp *
+ptrarray_prop (const char *name, GPtrArray *values)
+{
+    SmProp *prop;
+    SmPropValue pv;
+    GArray *vals;
+    guint i;
+
+    prop = g_new (SmProp, 1);
+    prop->name = (char *)name;
+    prop->type = (char *)SmLISTofARRAY8;
+
+    vals = g_array_new (FALSE, FALSE, sizeof (SmPropValue));
+
+    for (i = 0; i < values->len; i++)
+    {
+        pv.length = strlen (values->pdata[i]);
+        pv.value = values->pdata[i];
+        g_array_append_val (vals, pv);
+    }
+
+    prop->num_vals = vals->len;
+    prop->vals = (SmPropValue *)vals->data;
+
+    g_array_free (vals, FALSE);
+
+    return prop;
+}
+
+/* Takes a string and creates an ARRAY8 property. The string is
+ * neither dupped nor freed; it needs to remain valid until you're
+ * done with the SmProp.
+ */
+static SmProp *
+string_prop (const char *name, const char *value)
+{
+    SmProp *prop;
+
+    prop = g_new (SmProp, 1);
+    prop->name = (char *)name;
+    prop->type = (char *)SmARRAY8;
+
+    prop->num_vals = 1;
+    prop->vals = g_new (SmPropValue, 1);
+
+    prop->vals[0].length = strlen (value);
+    prop->vals[0].value = (char *)value;
+
+    return prop;
+}
+
+/* Takes a char and creates a CARD8 property. */
+static SmProp *
+card8_prop (const char *name, unsigned char value)
+{
+    SmProp *prop;
+    char *card8val;
+
+    /* To avoid having to allocate and free prop->vals[0], we cheat and
+     * make vals a 2-element-long array and then use the second element
+     * to store value.
+     */
+
+    prop = g_new (SmProp, 1);
+    prop->name = (char *)name;
+    prop->type = (char *)SmCARD8;
+
+    prop->num_vals = 1;
+    prop->vals = g_new (SmPropValue, 2);
+    card8val = (char *)(&prop->vals[1]);
+    card8val[0] = value;
+
+    prop->vals[0].length = 1;
+    prop->vals[0].value = card8val;
+
+    return prop;
+}
+
+/* ICE code. This makes no effort to play nice with anyone else trying
+ * to use libICE. Fortunately, no one uses libICE for anything other
+ * than SM. (DCOP uses ICE, but it has its own private copy of
+ * libICE.)
+ *
+ * When this moves to gtk, it will need to be cleverer, to avoid
+ * tripping over old apps that use MateClient or that use libSM
+ * directly.
+ */
+
+#include <X11/ICE/ICElib.h>
+#include <fcntl.h>
+
+static void        ice_error_handler    (IceConn        ice_conn,
+        Bool           swap,
+        int            offending_minor_opcode,
+        unsigned long  offending_sequence,
+        int            error_class,
+        int            severity,
+        IcePointer     values);
+static void        ice_io_error_handler (IceConn        ice_conn);
+static void        ice_connection_watch (IceConn        ice_conn,
+        IcePointer     client_data,
+        Bool           opening,
+        IcePointer    *watch_data);
+
+static void
+ice_init (void)
+{
+    IceSetIOErrorHandler (ice_io_error_handler);
+    IceSetErrorHandler (ice_error_handler);
+    IceAddConnectionWatch (ice_connection_watch, NULL);
+}
+
+static gboolean
+process_ice_messages (IceConn ice_conn)
+{
+    IceProcessMessagesStatus status;
+    status = IceProcessMessages (ice_conn, NULL, NULL);
+
+    switch (status)
+    {
+    case IceProcessMessagesSuccess:
+        return TRUE;
+
+    case IceProcessMessagesIOError:
+        sm_client_xsmp_disconnect (IceGetConnectionContext (ice_conn));
+        return FALSE;
+
+    case IceProcessMessagesConnectionClosed:
+        return FALSE;
+
+    default:
+        g_assert_not_reached ();
+    }
+}
+
+static gboolean
+ice_iochannel_watch (GIOChannel   *channel,
+                     GIOCondition  condition,
+                     gpointer      client_data)
+{
+    return process_ice_messages (client_data);
+}
+
+static void
+ice_connection_watch (IceConn     ice_conn,
+                      IcePointer  client_data,
+                      Bool        opening,
+                      IcePointer *watch_data)
+{
+    guint watch_id;
+
+    if (opening)
+    {
+        GIOChannel *channel;
+        int fd = IceConnectionNumber (ice_conn);
+
+        fcntl (fd, F_SETFD, fcntl (fd, F_GETFD, 0) | FD_CLOEXEC);
+        channel = g_io_channel_unix_new (fd);
+        watch_id = g_io_add_watch (channel, G_IO_IN | G_IO_ERR,
+                                   ice_iochannel_watch, ice_conn);
+        g_io_channel_unref (channel);
+
+        *watch_data = GUINT_TO_POINTER (watch_id);
+    }
+    else
+    {
+        watch_id = GPOINTER_TO_UINT (*watch_data);
+        g_source_remove (watch_id);
+    }
+}
+
+static void
+ice_error_handler (IceConn       ice_conn,
+                   Bool          swap,
+                   int           offending_minor_opcode,
+                   unsigned long offending_sequence,
+                   int           error_class,
+                   int           severity,
+                   IcePointer    values)
+{
+    /* Do nothing */
+}
+
+static void
+ice_io_error_handler (IceConn ice_conn)
+{
+    /* Do nothing */
+}
+
+static void
+smc_error_handler (SmcConn       smc_conn,
+                   Bool          swap,
+                   int           offending_minor_opcode,
+                   unsigned long offending_sequence,
+                   int           error_class,
+                   int           severity,
+                   SmPointer     values)
+{
+    /* Do nothing */
+}
+
+ +
+ +
+ + diff --git a/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/12.html b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/12.html new file mode 100644 index 00000000..747c79be --- /dev/null +++ b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/12.html @@ -0,0 +1,1523 @@ + + + + + + Cppcheck - HTML report - mate-utils + + + + + +
+ + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
+479
+480
+481
+482
+483
+484
+485
+486
+487
+488
+489
+490
+491
+492
+493
+494
+495
+496
+497
+498
+499
+500
+501
+502
+503
+504
+505
+506
+507
+508
+509
+510
+511
+512
+513
+514
+515
+516
+517
+518
+519
+520
+521
+522
+523
+524
+525
+526
+527
+528
+529
+530
+531
+532
+533
+534
+535
+536
+537
+538
+539
+540
+541
+542
+543
+544
+545
+546
+547
+548
+549
+550
+551
+552
+553
+554
+555
+556
+557
+558
+559
+560
+561
+562
+563
+564
+565
+566
+567
+568
+569
+570
+571
+572
+573
+574
+575
+576
+577
+578
+579
+580
+581
+582
+583
+584
+585
+586
+587
+588
+589
+590
+591
+592
+593
+594
+595
+596
+597
+598
+599
+600
+601
+602
+603
+604
+605
+606
+607
+608
+609
+610
+611
+612
+613
+614
+615
+616
+617
+618
+619
+620
+621
+622
+623
+624
+625
+626
+627
+628
+629
+630
+631
+632
+633
+634
+635
+636
+637
+638
+639
+640
+641
+642
+643
/*
+ * Copyright (C) 2007 Novell, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <glib/gi18n.h>
+
+#include "eggsmclient.h"
+#include "eggsmclient-private.h"
+
+static void egg_sm_client_debug_handler (const char *log_domain,
+        GLogLevelFlags log_level,
+        const char *message,
+        gpointer user_data);
+
+enum
+{
+    SAVE_STATE,
+    QUIT_REQUESTED,
+    QUIT_CANCELLED,
+    QUIT,
+    LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+typedef struct {
+    GKeyFile *state_file;
+}EggSMClientPrivate;
+
+G_DEFINE_TYPE_WITH_PRIVATE (EggSMClient, egg_sm_client, G_TYPE_OBJECT)<--- There is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
+
+static EggSMClient *global_client;
+static EggSMClientMode global_client_mode = EGG_SM_CLIENT_MODE_NORMAL;
+
+static gboolean
+running_in_mate (void)
+{
+    return (g_strcmp0 (g_getenv ("XDG_CURRENT_DESKTOP"), "MATE") == 0)
+        || (g_strcmp0 (g_getenv ("XDG_SESSION_DESKTOP"), "mate") == 0)
+        || (g_strcmp0 (g_getenv ("DESKTOP_SESSION"), "mate") == 0);
+}
+
+static void
+egg_sm_client_init (EggSMClient *client)
+{
+    ;
+}
+
+static void
+egg_sm_client_class_init (EggSMClientClass *klass)
+{
+    GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+    /**
+     * EggSMClient::save_state:
+     * @client: the client
+     * @state_file: a #GKeyFile to save state information into
+     *
+     * Emitted when the session manager has requested that the
+     * application save information about its current state. The
+     * application should save its state into @state_file, and then the
+     * session manager may then restart the application in a future
+     * session and tell it to initialize itself from that state.
+     *
+     * You should not save any data into @state_file's "start group"
+     * (ie, the %NULL group). Instead, applications should save their
+     * data into groups with names that start with the application name,
+     * and libraries that connect to this signal should save their data
+     * into groups with names that start with the library name.
+     *
+     * Alternatively, rather than (or in addition to) using @state_file,
+     * the application can save its state by calling
+     * egg_sm_client_set_restart_command() during the processing of this
+     * signal (eg, to include a list of files to open).
+     **/
+    signals[SAVE_STATE] =
+        g_signal_new ("save_state",
+                      G_OBJECT_CLASS_TYPE (object_class),
+                      G_SIGNAL_RUN_LAST,
+                      G_STRUCT_OFFSET (EggSMClientClass, save_state),
+                      NULL, NULL,
+                      g_cclosure_marshal_VOID__POINTER,
+                      G_TYPE_NONE,
+                      1, G_TYPE_POINTER);
+
+    /**
+     * EggSMClient::quit_requested:
+     * @client: the client
+     *
+     * Emitted when the session manager requests that the application
+     * exit (generally because the user is logging out). The application
+     * should decide whether or not it is willing to quit (perhaps after
+     * asking the user what to do with documents that have unsaved
+     * changes) and then call egg_sm_client_will_quit(), passing %TRUE
+     * or %FALSE to give its answer to the session manager. (It does not
+     * need to give an answer before returning from the signal handler;
+     * it can interact with the user asynchronously and then give its
+     * answer later on.) If the application does not connect to this
+     * signal, then #EggSMClient will automatically return %TRUE on its
+     * behalf.
+     *
+     * The application should not save its session state as part of
+     * handling this signal; if the user has requested that the session
+     * be saved when logging out, then ::save_state will be emitted
+     * separately.
+     *
+     * If the application agrees to quit, it should then wait for either
+     * the ::quit_cancelled or ::quit signals to be emitted.
+     **/
+    signals[QUIT_REQUESTED] =
+        g_signal_new ("quit_requested",
+                      G_OBJECT_CLASS_TYPE (object_class),
+                      G_SIGNAL_RUN_LAST,
+                      G_STRUCT_OFFSET (EggSMClientClass, quit_requested),
+                      NULL, NULL,
+                      g_cclosure_marshal_VOID__VOID,
+                      G_TYPE_NONE,
+                      0);
+
+    /**
+     * EggSMClient::quit_cancelled:
+     * @client: the client
+     *
+     * Emitted when the session manager decides to cancel a logout after
+     * the application has already agreed to quit. After receiving this
+     * signal, the application can go back to what it was doing before
+     * receiving the ::quit_requested signal.
+     **/
+    signals[QUIT_CANCELLED] =
+        g_signal_new ("quit_cancelled",
+                      G_OBJECT_CLASS_TYPE (object_class),
+                      G_SIGNAL_RUN_LAST,
+                      G_STRUCT_OFFSET (EggSMClientClass, quit_cancelled),
+                      NULL, NULL,
+                      g_cclosure_marshal_VOID__VOID,
+                      G_TYPE_NONE,
+                      0);
+
+    /**
+     * EggSMClient::quit:
+     * @client: the client
+     *
+     * Emitted when the session manager wants the application to quit
+     * (generally because the user is logging out). The application
+     * should exit as soon as possible after receiving this signal; if
+     * it does not, the session manager may choose to forcibly kill it.
+     *
+     * Normally a GUI application would only be sent a ::quit if it
+     * agreed to quit in response to a ::quit_requested signal. However,
+     * this is not guaranteed; in some situations the session manager
+     * may decide to end the session without giving applications a
+     * chance to object.
+     **/
+    signals[QUIT] =
+        g_signal_new ("quit",
+                      G_OBJECT_CLASS_TYPE (object_class),
+                      G_SIGNAL_RUN_LAST,
+                      G_STRUCT_OFFSET (EggSMClientClass, quit),
+                      NULL, NULL,
+                      g_cclosure_marshal_VOID__VOID,
+                      G_TYPE_NONE,
+                      0);
+}
+
+static gboolean sm_client_disable = FALSE;
+static char *sm_client_state_file = NULL;
+static char *sm_client_id = NULL;
+static char *sm_config_prefix = NULL;
+
+static gboolean
+sm_client_post_parse_func (GOptionContext  *context,
+                           GOptionGroup    *group,
+                           gpointer         data,
+                           GError         **error)
+{
+    EggSMClient *client = egg_sm_client_get ();
+
+    if (sm_client_id == NULL)
+    {
+        const gchar *desktop_autostart_id;
+
+        desktop_autostart_id = g_getenv ("DESKTOP_AUTOSTART_ID");
+
+        if (desktop_autostart_id != NULL)
+            sm_client_id = g_strdup (desktop_autostart_id);
+    }
+
+    /* Unset DESKTOP_AUTOSTART_ID in order to avoid child processes to
+     * use the same client id. */
+    g_unsetenv ("DESKTOP_AUTOSTART_ID");
+
+    if (global_client_mode != EGG_SM_CLIENT_MODE_DISABLED &&
+        EGG_SM_CLIENT_GET_CLASS (client)->startup)
+        EGG_SM_CLIENT_GET_CLASS (client)->startup (client, sm_client_id);
+    return TRUE;
+}
+
+/**
+ * egg_sm_client_get_option_group:
+ *
+ * Creates a %GOptionGroup containing the session-management-related
+ * options. You should add this group to the application's
+ * %GOptionContext if you want to use #EggSMClient.
+ *
+ * Return value: the %GOptionGroup
+ **/
+GOptionGroup *
+egg_sm_client_get_option_group (void)
+{
+    const GOptionEntry entries[] =
+    {
+        {
+            "sm-client-disable", 0, 0,
+            G_OPTION_ARG_NONE, &sm_client_disable,
+            N_("Disable connection to session manager"), NULL
+        },
+        {
+            "sm-client-state-file", 0, 0,
+            G_OPTION_ARG_FILENAME, &sm_client_state_file,
+            N_("Specify file containing saved configuration"), N_("FILE")
+        },
+        {
+            "sm-client-id", 0, 0,
+            G_OPTION_ARG_STRING, &sm_client_id,
+            N_("Specify session management ID"), N_("ID")
+        },
+        /* MateClient compatibility option */
+        {
+            "sm-disable", 0, G_OPTION_FLAG_HIDDEN,
+            G_OPTION_ARG_NONE, &sm_client_disable,
+            NULL, NULL
+        },
+        /* MateClient compatibility option. This is a dummy option that only
+         * exists so that sessions saved by apps with MateClient can be restored
+         * later when they've switched to EggSMClient. See bug #575308.
+         */
+        {
+            "sm-config-prefix", 0, G_OPTION_FLAG_HIDDEN,
+            G_OPTION_ARG_STRING, &sm_config_prefix,
+            NULL, NULL
+        },
+        { NULL }
+    };
+    GOptionGroup *group;
+
+    /* Use our own debug handler for the "EggSMClient" domain. */
+    g_log_set_handler (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG,
+                       egg_sm_client_debug_handler, NULL);
+
+    group = g_option_group_new ("sm-client",
+                                _("Session management options:"),
+                                _("Show session management options"),
+                                NULL, NULL);
+    g_option_group_add_entries (group, entries);
+    g_option_group_set_parse_hooks (group, NULL, sm_client_post_parse_func);
+
+    return group;
+}
+
+/**
+ * egg_sm_client_set_mode:
+ * @mode: an #EggSMClient mode
+ *
+ * Sets the "mode" of #EggSMClient as follows:
+ *
+ *    %EGG_SM_CLIENT_MODE_DISABLED: Session management is completely
+ *    disabled, until the mode is changed again. The application will
+ *    not even connect to the session manager. (egg_sm_client_get()
+ *    will still return an #EggSMClient object.)
+ *
+ *    %EGG_SM_CLIENT_MODE_NO_RESTART: The application will connect to
+ *    the session manager (and thus will receive notification when the
+ *    user is logging out, etc), but will request to not be
+ *    automatically restarted with saved state in future sessions.
+ *
+ *    %EGG_SM_CLIENT_MODE_NORMAL: The default. #EggSMCLient will
+ *    function normally.
+ *
+ * This must be called before the application's main loop begins and
+ * before any call to egg_sm_client_get(), unless the mode was set
+ * earlier to %EGG_SM_CLIENT_MODE_DISABLED and this call enables
+ * session management. Note that option parsing will call
+ * egg_sm_client_get().
+ **/
+void
+egg_sm_client_set_mode (EggSMClientMode mode)
+{
+    EggSMClientMode old_mode = global_client_mode;
+
+    g_return_if_fail (global_client == NULL || global_client_mode == EGG_SM_CLIENT_MODE_DISABLED);
+    g_return_if_fail (!(global_client != NULL && mode == EGG_SM_CLIENT_MODE_DISABLED));
+
+    global_client_mode = mode;
+
+    if (global_client != NULL && old_mode == EGG_SM_CLIENT_MODE_DISABLED)
+    {
+        if (EGG_SM_CLIENT_GET_CLASS (global_client)->startup)
+            EGG_SM_CLIENT_GET_CLASS (global_client)->startup (global_client, sm_client_id);
+    }
+}
+
+/**
+ * egg_sm_client_get_mode:
+ *
+ * Gets the global #EggSMClientMode. See egg_sm_client_set_mode()
+ * for details.
+ *
+ * Return value: the global #EggSMClientMode
+ **/
+EggSMClientMode
+egg_sm_client_get_mode (void)
+{
+    return global_client_mode;
+}
+
+/**
+ * egg_sm_client_get:
+ *
+ * Returns the master #EggSMClient for the application.
+ *
+ * On platforms that support saved sessions (ie, POSIX/X11), the
+ * application will only request to be restarted by the session
+ * manager if you call egg_set_desktop_file() to set an application
+ * desktop file. In particular, if the desktop file contains the key
+ * "X
+ *
+ * Return value: the master #EggSMClient.
+ **/
+EggSMClient *
+egg_sm_client_get (void)
+{
+    if (!global_client)
+    {
+        if (!sm_client_disable)
+        {
+            /* If both D-Bus and XSMP are compiled in, try XSMP first
+             * (since it supports state saving) and fall back to D-Bus
+             * if XSMP isn't available.
+             */
+#ifdef EGG_SM_CLIENT_BACKEND_XSMP
+            global_client = egg_sm_client_xsmp_new ();
+#endif
+#ifdef EGG_SM_CLIENT_BACKEND_DBUS
+            if (!global_client)
+                global_client = egg_sm_client_dbus_new ();
+#endif
+        }
+
+        /* Fallback: create a dummy client, so that callers don't have
+         * to worry about a %NULL return value.
+         */
+        if (!global_client)
+            global_client = g_object_new (EGG_TYPE_SM_CLIENT, NULL);
+        /*FIXME
+          Disabling when root/not in MATE in GtkApplication builds
+          as egg_sm_client_set_mode must be called prior to start of main loop
+          to stop caja restart but this is diffcult in GtkApplication */
+
+		if (geteuid () == 0 || !running_in_mate ()){
+            global_client = g_object_new (EGG_TYPE_SM_CLIENT, NULL);
+        }
+    }
+
+    return global_client;
+}
+
+/**
+ * egg_sm_client_is_resumed:
+ * @client: the client
+ *
+ * Checks whether or not the current session has been resumed from
+ * a previous saved session. If so, the application should call
+ * egg_sm_client_get_state_file() and restore its state from the
+ * returned #GKeyFile.
+ *
+ * Return value: %TRUE if the session has been resumed
+ **/
+gboolean
+egg_sm_client_is_resumed (EggSMClient *client)
+{
+    g_return_val_if_fail (client == global_client, FALSE);
+
+    return sm_client_state_file != NULL;
+}
+
+/**
+ * egg_sm_client_get_state_file:
+ * @client: the client
+ *
+ * If the application was resumed by the session manager, this will
+ * return the #GKeyFile containing its state from the previous
+ * session.
+ *
+ * Note that other libraries and #EggSMClient itself may also store
+ * state in the key file, so if you call egg_sm_client_get_groups(),
+ * on it, the return value will likely include groups that you did not
+ * put there yourself. (It is also not guaranteed that the first
+ * group created by the application will still be the "start group"
+ * when it is resumed.)
+ *
+ * Return value: the #GKeyFile containing the application's earlier
+ * state, or %NULL on error. You should not free this key file; it
+ * is owned by @client.
+ **/
+GKeyFile *
+egg_sm_client_get_state_file (EggSMClient *client)
+{
+    EggSMClientPrivate *priv = egg_sm_client_get_instance_private (client);
+    char *state_file_path;
+    GError *err = NULL;
+
+    g_return_val_if_fail (client == global_client, NULL);
+
+    if (!sm_client_state_file)
+        return NULL;
+    if (priv->state_file)
+        return priv->state_file;
+
+    if (!strncmp (sm_client_state_file, "file://", 7))
+        state_file_path = g_filename_from_uri (sm_client_state_file, NULL, NULL);
+    else
+        state_file_path = g_strdup (sm_client_state_file);
+
+    priv->state_file = g_key_file_new ();
+    if (!g_key_file_load_from_file (priv->state_file, state_file_path, 0, &err))
+    {
+        g_warning ("Could not load SM state file '%s': %s",
+                   sm_client_state_file, err->message);
+        g_clear_error (&err);
+        g_key_file_free (priv->state_file);
+        priv->state_file = NULL;
+    }
+
+    g_free (state_file_path);
+    return priv->state_file;
+}
+
+/**
+ * egg_sm_client_set_restart_command:
+ * @client: the client
+ * @argc: the length of @argv
+ * @argv: argument vector
+ *
+ * Sets the command used to restart @client if it does not have a
+ * .desktop file that can be used to find its restart command.
+ *
+ * This can also be used when handling the ::save_state signal, to
+ * save the current state via an updated command line. (Eg, providing
+ * a list of filenames to open when the application is resumed.)
+ **/
+void
+egg_sm_client_set_restart_command (EggSMClient  *client,
+                                   int           argc,
+                                   const char  **argv)
+{
+    g_return_if_fail (EGG_IS_SM_CLIENT (client));
+
+    if (EGG_SM_CLIENT_GET_CLASS (client)->set_restart_command)
+        EGG_SM_CLIENT_GET_CLASS (client)->set_restart_command (client, argc, argv);
+}
+
+/**
+ * egg_sm_client_set_discard_command:
+ * @client: the client
+ * @argc: the length of @argv
+ * @argv: argument vector
+ *
+ * Sets the command used to discard a custom state file if using
+ * egg_sm_client_set_restart_command(), which must be called before
+ * using this function.
+ **/
+void
+egg_sm_client_set_discard_command (EggSMClient  *client,
+                                   int           argc,
+                                   const char  **argv)
+{
+	g_return_if_fail (EGG_IS_SM_CLIENT (client));
+
+	if (EGG_SM_CLIENT_GET_CLASS (client)->set_discard_command)
+		EGG_SM_CLIENT_GET_CLASS (client)->set_discard_command (client, argc, argv);
+}
+
+/**
+ * egg_sm_client_will_quit:
+ * @client: the client
+ * @will_quit: whether or not the application is willing to quit
+ *
+ * This MUST be called in response to the ::quit_requested signal, to
+ * indicate whether or not the application is willing to quit. The
+ * application may call it either directly from the signal handler, or
+ * at some later point (eg, after asynchronously interacting with the
+ * user).
+ *
+ * If the application does not connect to ::quit_requested,
+ * #EggSMClient will call this method on its behalf (passing %TRUE
+ * for @will_quit).
+ *
+ * After calling this method, the application should wait to receive
+ * either ::quit_cancelled or ::quit.
+ **/
+void
+egg_sm_client_will_quit (EggSMClient *client,
+                         gboolean     will_quit)
+{
+    g_return_if_fail (EGG_IS_SM_CLIENT (client));
+
+    if (EGG_SM_CLIENT_GET_CLASS (client)->will_quit)
+        EGG_SM_CLIENT_GET_CLASS (client)->will_quit (client, will_quit);
+}
+
+/**
+ * egg_sm_client_end_session:
+ * @style: a hint at how to end the session
+ * @request_confirmation: whether or not the user should get a chance
+ * to confirm the action
+ *
+ * Requests that the session manager end the current session. @style
+ * indicates how the session should be ended, and
+ * @request_confirmation indicates whether or not the user should be
+ * given a chance to confirm the logout/reboot/shutdown. Both of these
+ * flags are merely hints though; the session manager may choose to
+ * ignore them.
+ *
+ * Return value: %TRUE if the request was sent; %FALSE if it could not
+ * be (eg, because it could not connect to the session manager).
+ **/
+gboolean
+egg_sm_client_end_session (EggSMClientEndStyle  style,
+                           gboolean             request_confirmation)
+{
+    EggSMClient *client = egg_sm_client_get ();
+
+    g_return_val_if_fail (EGG_IS_SM_CLIENT (client), FALSE);
+
+    if (EGG_SM_CLIENT_GET_CLASS (client)->end_session)
+    {
+        return EGG_SM_CLIENT_GET_CLASS (client)->end_session (client, style,
+                request_confirmation);
+    }
+    else
+        return FALSE;
+}
+
+/* Signal-emitting callbacks from platform-specific code */
+
+GKeyFile *
+egg_sm_client_save_state (EggSMClient *client)
+{
+    GKeyFile *state_file;
+    char *group;
+
+    g_return_val_if_fail (client == global_client, NULL);
+
+    state_file = g_key_file_new ();
+
+    g_debug ("Emitting save_state");
+    g_signal_emit (client, signals[SAVE_STATE], 0, state_file);
+    g_debug ("Done emitting save_state");
+
+    group = g_key_file_get_start_group (state_file);
+    if (group)
+    {
+        g_free (group);
+        return state_file;
+    }
+    else
+    {
+        g_key_file_free (state_file);
+        return NULL;
+    }
+}
+
+void
+egg_sm_client_quit_requested (EggSMClient *client)
+{
+    g_return_if_fail (client == global_client);
+
+    if (!g_signal_has_handler_pending (client, signals[QUIT_REQUESTED], 0, FALSE))
+    {
+        g_debug ("Not emitting quit_requested because no one is listening");
+        egg_sm_client_will_quit (client, TRUE);
+        return;
+    }
+
+    g_debug ("Emitting quit_requested");
+    g_signal_emit (client, signals[QUIT_REQUESTED], 0);
+    g_debug ("Done emitting quit_requested");
+}
+
+void
+egg_sm_client_quit_cancelled (EggSMClient *client)
+{
+    g_return_if_fail (client == global_client);
+
+    g_debug ("Emitting quit_cancelled");
+    g_signal_emit (client, signals[QUIT_CANCELLED], 0);
+    g_debug ("Done emitting quit_cancelled");
+}
+
+void
+egg_sm_client_quit (EggSMClient *client)
+{
+    g_return_if_fail (client == global_client);
+
+    g_debug ("Emitting quit");
+    g_signal_emit (client, signals[QUIT], 0);
+    g_debug ("Done emitting quit");
+
+    /* FIXME: should we just call gtk_main_quit() here? */
+}
+
+static void
+egg_sm_client_debug_handler (const char *log_domain,
+                             GLogLevelFlags log_level,
+                             const char *message,
+                             gpointer user_data)
+{
+    static int debug = -1;
+
+    if (debug < 0)
+        debug = (g_getenv ("EGG_SM_CLIENT_DEBUG") != NULL);
+
+    if (debug)
+        g_log_default_handler (log_domain, log_level, message, NULL);
+}
+
+ +
+ +
+ + diff --git a/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/13.html b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/13.html new file mode 100644 index 00000000..6d2ab7bd --- /dev/null +++ b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/13.html @@ -0,0 +1,1071 @@ + + + + + + Cppcheck - HTML report - mate-utils + + + + + +
+ + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
/* eggtreemultidnd.c
+ * Copyright (C) 2001  Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#include <gtk/gtk.h>
+#include "eggtreemultidnd.h"
+
+#define EGG_TREE_MULTI_DND_STRING "EggTreeMultiDndString"
+
+typedef struct
+{
+    guint pressed_button;
+    gint x;
+    gint y;
+    guint motion_notify_handler;
+    guint button_release_handler;
+    guint drag_data_get_handler;
+    GSList *event_list;
+} EggTreeMultiDndData;
+
+/* CUT-N-PASTE from gtktreeview.c */
+typedef struct _TreeViewDragInfo TreeViewDragInfo;
+struct _TreeViewDragInfo
+{
+    GdkModifierType start_button_mask;
+    GtkTargetList *source_target_list;<--- struct member '_TreeViewDragInfo::source_target_list' is never used.
+    GdkDragAction source_actions;
+
+    GtkTargetList *dest_target_list;<--- struct member '_TreeViewDragInfo::dest_target_list' is never used.
+
+    guint source_set : 1;
+    guint dest_set : 1;
+};
+
+
+GType
+egg_tree_multi_drag_source_get_type (void)
+{
+    static GType our_type = 0;
+
+    if (!our_type)
+    {
+        const GTypeInfo our_info =
+        {
+            sizeof (EggTreeMultiDragSourceIface), /* class_size */
+            NULL,		/* base_init */
+            NULL,		/* base_finalize */
+            NULL,
+            NULL,		/* class_finalize */
+            NULL,		/* class_data */
+            0,
+            0,              /* n_preallocs */
+            NULL
+        };
+
+        our_type = g_type_register_static (G_TYPE_INTERFACE, "EggTreeMultiDragSource", &our_info, 0);
+    }
+
+    return our_type;
+}
+
+
+/**
+ * egg_tree_multi_drag_source_row_draggable:
+ * @drag_source: a #EggTreeMultiDragSource
+ * @path: row on which user is initiating a drag
+ *
+ * Asks the #EggTreeMultiDragSource whether a particular row can be used as
+ * the source of a DND operation. If the source doesn't implement
+ * this interface, the row is assumed draggable.
+ *
+ * Return value: %TRUE if the row can be dragged
+ **/
+gboolean
+egg_tree_multi_drag_source_row_draggable (EggTreeMultiDragSource *drag_source,
+        GList                  *path_list)
+{
+    EggTreeMultiDragSourceIface *iface = EGG_TREE_MULTI_DRAG_SOURCE_GET_IFACE (drag_source);
+
+    g_return_val_if_fail (EGG_IS_TREE_MULTI_DRAG_SOURCE (drag_source), FALSE);
+    g_return_val_if_fail (iface->row_draggable != NULL, FALSE);
+    g_return_val_if_fail (path_list != NULL, FALSE);
+
+    if (iface->row_draggable)
+        return (* iface->row_draggable) (drag_source, path_list);
+    else
+        return TRUE;
+}
+
+
+/**
+ * egg_tree_multi_drag_source_drag_data_delete:
+ * @drag_source: a #EggTreeMultiDragSource
+ * @path: row that was being dragged
+ *
+ * Asks the #EggTreeMultiDragSource to delete the row at @path, because
+ * it was moved somewhere else via drag-and-drop. Returns %FALSE
+ * if the deletion fails because @path no longer exists, or for
+ * some model-specific reason. Should robustly handle a @path no
+ * longer found in the model!
+ *
+ * Return value: %TRUE if the row was successfully deleted
+ **/
+gboolean
+egg_tree_multi_drag_source_drag_data_delete (EggTreeMultiDragSource *drag_source,
+        GList                  *path_list)
+{
+    EggTreeMultiDragSourceIface *iface = EGG_TREE_MULTI_DRAG_SOURCE_GET_IFACE (drag_source);
+
+    g_return_val_if_fail (EGG_IS_TREE_MULTI_DRAG_SOURCE (drag_source), FALSE);
+    g_return_val_if_fail (iface->drag_data_delete != NULL, FALSE);
+    g_return_val_if_fail (path_list != NULL, FALSE);
+
+    return (* iface->drag_data_delete) (drag_source, path_list);
+}
+
+/**
+ * egg_tree_multi_drag_source_drag_data_get:
+ * @drag_source: a #EggTreeMultiDragSource
+ * @path: row that was dragged
+ * @selection_data: a #EggSelectionData to fill with data from the dragged row
+ *
+ * Asks the #EggTreeMultiDragSource to fill in @selection_data with a
+ * representation of the row at @path. @selection_data->target gives
+ * the required type of the data.  Should robustly handle a @path no
+ * longer found in the model!
+ *
+ * Return value: %TRUE if data of the required type was provided
+ **/
+gboolean
+egg_tree_multi_drag_source_drag_data_get    (EggTreeMultiDragSource *drag_source,
+        GList                  *path_list,
+        GtkSelectionData  *selection_data)
+{
+    EggTreeMultiDragSourceIface *iface = EGG_TREE_MULTI_DRAG_SOURCE_GET_IFACE (drag_source);
+
+    g_return_val_if_fail (EGG_IS_TREE_MULTI_DRAG_SOURCE (drag_source), FALSE);
+    g_return_val_if_fail (iface->drag_data_get != NULL, FALSE);
+    g_return_val_if_fail (path_list != NULL, FALSE);
+    g_return_val_if_fail (selection_data != NULL, FALSE);
+
+    return (* iface->drag_data_get) (drag_source, path_list, selection_data);
+}
+
+static void
+stop_drag_check (GtkWidget *widget)
+{
+    EggTreeMultiDndData *priv_data;
+    GSList *l;
+
+    priv_data = g_object_get_data (G_OBJECT (widget), EGG_TREE_MULTI_DND_STRING);
+
+    for (l = priv_data->event_list; l != NULL; l = l->next)
+        gdk_event_free (l->data);
+
+    g_slist_free (priv_data->event_list);
+    priv_data->event_list = NULL;
+    g_signal_handler_disconnect (widget, priv_data->motion_notify_handler);
+    g_signal_handler_disconnect (widget, priv_data->button_release_handler);
+}
+
+static gboolean
+egg_tree_multi_drag_button_release_event (GtkWidget      *widget,
+        GdkEventButton *event,
+        gpointer        data)
+{
+    EggTreeMultiDndData *priv_data;
+    GSList *l;
+
+    priv_data = g_object_get_data (G_OBJECT (widget), EGG_TREE_MULTI_DND_STRING);
+
+    for (l = priv_data->event_list; l != NULL; l = l->next)
+        gtk_propagate_event (widget, l->data);
+
+    stop_drag_check (widget);
+
+    return FALSE;
+}
+
+static void
+selection_foreach (GtkTreeModel *model,
+                   GtkTreePath  *path,
+                   GtkTreeIter  *iter,
+                   gpointer      data)
+{
+    GList **list_ptr;
+
+    list_ptr = (GList **) data;
+
+    *list_ptr = g_list_prepend (*list_ptr, gtk_tree_row_reference_new (model, path));
+}
+
+static void
+path_list_free (GList *path_list)
+{
+    g_list_foreach (path_list, (GFunc) gtk_tree_row_reference_free, NULL);
+    g_list_free (path_list);
+}
+
+static void
+set_context_data (GdkDragContext *context,
+                  GList          *path_list)
+{
+    g_object_set_data_full (G_OBJECT (context),
+                            "egg-tree-view-multi-source-row",
+                            path_list,
+                            (GDestroyNotify) path_list_free);
+}
+
+static GList *
+get_context_data (GdkDragContext *context)
+{
+    return g_object_get_data (G_OBJECT (context),
+                              "egg-tree-view-multi-source-row");
+}
+
+/* CUT-N-PASTE from gtktreeview.c */
+static TreeViewDragInfo*
+get_info (GtkTreeView *tree_view)
+{
+    return g_object_get_data (G_OBJECT (tree_view), "gtk-tree-view-drag-info");
+}
+
+
+static void
+egg_tree_multi_drag_drag_data_get (GtkWidget        *widget,
+                                   GdkDragContext   *context,
+                                   GtkSelectionData *selection_data,
+                                   guint             info,
+                                   guint             time)
+{
+    GtkTreeView *tree_view;
+    GtkTreeModel *model;
+    TreeViewDragInfo *di;
+    GList *path_list;
+
+    tree_view = GTK_TREE_VIEW (widget);
+
+    model = gtk_tree_view_get_model (tree_view);
+
+    if (model == NULL)
+        return;
+
+    di = get_info (GTK_TREE_VIEW (widget));
+
+    if (di == NULL)
+        return;
+
+    path_list = get_context_data (context);
+
+    if (path_list == NULL)
+        return;
+
+    /* We can implement the GTK_TREE_MODEL_ROW target generically for
+     * any model; for DragSource models there are some other targets
+     * we also support.
+     */
+
+    if (EGG_IS_TREE_MULTI_DRAG_SOURCE (model))
+    {
+        egg_tree_multi_drag_source_drag_data_get (EGG_TREE_MULTI_DRAG_SOURCE (model),
+                path_list,
+                selection_data);
+    }
+}
+
+static gboolean
+egg_tree_multi_drag_motion_event (GtkWidget      *widget,
+                                  GdkEventMotion *event,
+                                  gpointer        data)
+{
+    EggTreeMultiDndData *priv_data;
+
+    priv_data = g_object_get_data (G_OBJECT (widget), EGG_TREE_MULTI_DND_STRING);
+
+    if (gtk_drag_check_threshold (widget,
+                                  priv_data->x,
+                                  priv_data->y,
+                                  event->x,
+                                  event->y))
+    {
+        GList *path_list = NULL;
+        GtkTreeSelection *selection;
+        GtkTreeModel *model;
+        TreeViewDragInfo *di;
+
+        di = get_info (GTK_TREE_VIEW (widget));
+
+        if (di == NULL)
+            return FALSE;
+
+        selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
+        stop_drag_check (widget);
+        gtk_tree_selection_selected_foreach (selection, selection_foreach, &path_list);
+        path_list = g_list_reverse (path_list);
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (widget));
+        if (egg_tree_multi_drag_source_row_draggable (EGG_TREE_MULTI_DRAG_SOURCE (model), path_list))
+        {
+            GdkDragContext *context;
+
+            context = gtk_drag_begin_with_coordinates (widget,
+                                                       gtk_drag_source_get_target_list (widget),
+                                                       di->source_actions,
+                                                       priv_data->pressed_button,
+                                                       (GdkEvent*)event,
+                                                       event->x,
+                                                       event->y);
+            set_context_data (context, path_list);
+            gtk_drag_set_icon_default (context);
+
+        }
+        else
+        {
+            path_list_free (path_list);
+        }
+    }
+
+    return TRUE;
+}
+
+static gboolean
+egg_tree_multi_drag_button_press_event (GtkWidget      *widget,
+                                        GdkEventButton *event,
+                                        gpointer        data)
+{
+    GtkTreeView *tree_view;
+    GtkTreePath *path = NULL;
+    GtkTreeViewColumn *column = NULL;
+    gint cell_x, cell_y;
+    GtkTreeSelection *selection;
+    EggTreeMultiDndData *priv_data;
+
+    tree_view = GTK_TREE_VIEW (widget);
+    priv_data = g_object_get_data (G_OBJECT (tree_view), EGG_TREE_MULTI_DND_STRING);
+    if (priv_data == NULL)
+    {
+        priv_data = g_new0 (EggTreeMultiDndData, 1);
+        g_object_set_data (G_OBJECT (tree_view), EGG_TREE_MULTI_DND_STRING, priv_data);
+    }
+
+    if (g_slist_find (priv_data->event_list, event))
+        return FALSE;
+
+    if (priv_data->event_list)
+    {
+        /* save the event to be propagated in order */
+        priv_data->event_list = g_slist_append (priv_data->event_list, gdk_event_copy ((GdkEvent*)event));
+        return TRUE;
+    }
+
+    if (event->type == GDK_2BUTTON_PRESS)
+        return FALSE;
+
+    gtk_tree_view_get_path_at_pos (tree_view,
+                                   event->x, event->y,
+                                   &path, &column,
+                                   &cell_x, &cell_y);
+
+    selection = gtk_tree_view_get_selection (tree_view);
+
+    if (path && gtk_tree_selection_path_is_selected (selection, path))
+    {
+        priv_data->pressed_button = event->button;
+        priv_data->x = event->x;
+        priv_data->y = event->y;
+        priv_data->event_list = g_slist_append (priv_data->event_list, gdk_event_copy ((GdkEvent*)event));
+        priv_data->motion_notify_handler =
+            g_signal_connect (G_OBJECT (tree_view), "motion_notify_event", G_CALLBACK (egg_tree_multi_drag_motion_event), NULL);
+        priv_data->button_release_handler =
+            g_signal_connect (G_OBJECT (tree_view), "button_release_event", G_CALLBACK (egg_tree_multi_drag_button_release_event), NULL);
+
+        if (priv_data->drag_data_get_handler == 0)
+        {
+            priv_data->drag_data_get_handler =
+                g_signal_connect (G_OBJECT (tree_view), "drag_data_get", G_CALLBACK (egg_tree_multi_drag_drag_data_get), NULL);
+        }
+
+        gtk_tree_path_free (path);
+
+        return TRUE;
+    }
+
+    if (path)
+    {
+        gtk_tree_path_free (path);
+    }
+
+    return FALSE;
+}
+
+void
+egg_tree_multi_drag_add_drag_support (GtkTreeView *tree_view)
+{
+    g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
+    g_signal_connect (G_OBJECT (tree_view), "button_press_event", G_CALLBACK (egg_tree_multi_drag_button_press_event), NULL);
+}
+
+
+ +
+ +
+ + diff --git a/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/14.html b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/14.html new file mode 100644 index 00000000..7ab15014 --- /dev/null +++ b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/14.html @@ -0,0 +1,4391 @@ + + + + + + Cppcheck - HTML report - mate-utils + + + + + +
+ + + +
+
   1
+   2
+   3
+   4
+   5
+   6
+   7
+   8
+   9
+  10
+  11
+  12
+  13
+  14
+  15
+  16
+  17
+  18
+  19
+  20
+  21
+  22
+  23
+  24
+  25
+  26
+  27
+  28
+  29
+  30
+  31
+  32
+  33
+  34
+  35
+  36
+  37
+  38
+  39
+  40
+  41
+  42
+  43
+  44
+  45
+  46
+  47
+  48
+  49
+  50
+  51
+  52
+  53
+  54
+  55
+  56
+  57
+  58
+  59
+  60
+  61
+  62
+  63
+  64
+  65
+  66
+  67
+  68
+  69
+  70
+  71
+  72
+  73
+  74
+  75
+  76
+  77
+  78
+  79
+  80
+  81
+  82
+  83
+  84
+  85
+  86
+  87
+  88
+  89
+  90
+  91
+  92
+  93
+  94
+  95
+  96
+  97
+  98
+  99
+ 100
+ 101
+ 102
+ 103
+ 104
+ 105
+ 106
+ 107
+ 108
+ 109
+ 110
+ 111
+ 112
+ 113
+ 114
+ 115
+ 116
+ 117
+ 118
+ 119
+ 120
+ 121
+ 122
+ 123
+ 124
+ 125
+ 126
+ 127
+ 128
+ 129
+ 130
+ 131
+ 132
+ 133
+ 134
+ 135
+ 136
+ 137
+ 138
+ 139
+ 140
+ 141
+ 142
+ 143
+ 144
+ 145
+ 146
+ 147
+ 148
+ 149
+ 150
+ 151
+ 152
+ 153
+ 154
+ 155
+ 156
+ 157
+ 158
+ 159
+ 160
+ 161
+ 162
+ 163
+ 164
+ 165
+ 166
+ 167
+ 168
+ 169
+ 170
+ 171
+ 172
+ 173
+ 174
+ 175
+ 176
+ 177
+ 178
+ 179
+ 180
+ 181
+ 182
+ 183
+ 184
+ 185
+ 186
+ 187
+ 188
+ 189
+ 190
+ 191
+ 192
+ 193
+ 194
+ 195
+ 196
+ 197
+ 198
+ 199
+ 200
+ 201
+ 202
+ 203
+ 204
+ 205
+ 206
+ 207
+ 208
+ 209
+ 210
+ 211
+ 212
+ 213
+ 214
+ 215
+ 216
+ 217
+ 218
+ 219
+ 220
+ 221
+ 222
+ 223
+ 224
+ 225
+ 226
+ 227
+ 228
+ 229
+ 230
+ 231
+ 232
+ 233
+ 234
+ 235
+ 236
+ 237
+ 238
+ 239
+ 240
+ 241
+ 242
+ 243
+ 244
+ 245
+ 246
+ 247
+ 248
+ 249
+ 250
+ 251
+ 252
+ 253
+ 254
+ 255
+ 256
+ 257
+ 258
+ 259
+ 260
+ 261
+ 262
+ 263
+ 264
+ 265
+ 266
+ 267
+ 268
+ 269
+ 270
+ 271
+ 272
+ 273
+ 274
+ 275
+ 276
+ 277
+ 278
+ 279
+ 280
+ 281
+ 282
+ 283
+ 284
+ 285
+ 286
+ 287
+ 288
+ 289
+ 290
+ 291
+ 292
+ 293
+ 294
+ 295
+ 296
+ 297
+ 298
+ 299
+ 300
+ 301
+ 302
+ 303
+ 304
+ 305
+ 306
+ 307
+ 308
+ 309
+ 310
+ 311
+ 312
+ 313
+ 314
+ 315
+ 316
+ 317
+ 318
+ 319
+ 320
+ 321
+ 322
+ 323
+ 324
+ 325
+ 326
+ 327
+ 328
+ 329
+ 330
+ 331
+ 332
+ 333
+ 334
+ 335
+ 336
+ 337
+ 338
+ 339
+ 340
+ 341
+ 342
+ 343
+ 344
+ 345
+ 346
+ 347
+ 348
+ 349
+ 350
+ 351
+ 352
+ 353
+ 354
+ 355
+ 356
+ 357
+ 358
+ 359
+ 360
+ 361
+ 362
+ 363
+ 364
+ 365
+ 366
+ 367
+ 368
+ 369
+ 370
+ 371
+ 372
+ 373
+ 374
+ 375
+ 376
+ 377
+ 378
+ 379
+ 380
+ 381
+ 382
+ 383
+ 384
+ 385
+ 386
+ 387
+ 388
+ 389
+ 390
+ 391
+ 392
+ 393
+ 394
+ 395
+ 396
+ 397
+ 398
+ 399
+ 400
+ 401
+ 402
+ 403
+ 404
+ 405
+ 406
+ 407
+ 408
+ 409
+ 410
+ 411
+ 412
+ 413
+ 414
+ 415
+ 416
+ 417
+ 418
+ 419
+ 420
+ 421
+ 422
+ 423
+ 424
+ 425
+ 426
+ 427
+ 428
+ 429
+ 430
+ 431
+ 432
+ 433
+ 434
+ 435
+ 436
+ 437
+ 438
+ 439
+ 440
+ 441
+ 442
+ 443
+ 444
+ 445
+ 446
+ 447
+ 448
+ 449
+ 450
+ 451
+ 452
+ 453
+ 454
+ 455
+ 456
+ 457
+ 458
+ 459
+ 460
+ 461
+ 462
+ 463
+ 464
+ 465
+ 466
+ 467
+ 468
+ 469
+ 470
+ 471
+ 472
+ 473
+ 474
+ 475
+ 476
+ 477
+ 478
+ 479
+ 480
+ 481
+ 482
+ 483
+ 484
+ 485
+ 486
+ 487
+ 488
+ 489
+ 490
+ 491
+ 492
+ 493
+ 494
+ 495
+ 496
+ 497
+ 498
+ 499
+ 500
+ 501
+ 502
+ 503
+ 504
+ 505
+ 506
+ 507
+ 508
+ 509
+ 510
+ 511
+ 512
+ 513
+ 514
+ 515
+ 516
+ 517
+ 518
+ 519
+ 520
+ 521
+ 522
+ 523
+ 524
+ 525
+ 526
+ 527
+ 528
+ 529
+ 530
+ 531
+ 532
+ 533
+ 534
+ 535
+ 536
+ 537
+ 538
+ 539
+ 540
+ 541
+ 542
+ 543
+ 544
+ 545
+ 546
+ 547
+ 548
+ 549
+ 550
+ 551
+ 552
+ 553
+ 554
+ 555
+ 556
+ 557
+ 558
+ 559
+ 560
+ 561
+ 562
+ 563
+ 564
+ 565
+ 566
+ 567
+ 568
+ 569
+ 570
+ 571
+ 572
+ 573
+ 574
+ 575
+ 576
+ 577
+ 578
+ 579
+ 580
+ 581
+ 582
+ 583
+ 584
+ 585
+ 586
+ 587
+ 588
+ 589
+ 590
+ 591
+ 592
+ 593
+ 594
+ 595
+ 596
+ 597
+ 598
+ 599
+ 600
+ 601
+ 602
+ 603
+ 604
+ 605
+ 606
+ 607
+ 608
+ 609
+ 610
+ 611
+ 612
+ 613
+ 614
+ 615
+ 616
+ 617
+ 618
+ 619
+ 620
+ 621
+ 622
+ 623
+ 624
+ 625
+ 626
+ 627
+ 628
+ 629
+ 630
+ 631
+ 632
+ 633
+ 634
+ 635
+ 636
+ 637
+ 638
+ 639
+ 640
+ 641
+ 642
+ 643
+ 644
+ 645
+ 646
+ 647
+ 648
+ 649
+ 650
+ 651
+ 652
+ 653
+ 654
+ 655
+ 656
+ 657
+ 658
+ 659
+ 660
+ 661
+ 662
+ 663
+ 664
+ 665
+ 666
+ 667
+ 668
+ 669
+ 670
+ 671
+ 672
+ 673
+ 674
+ 675
+ 676
+ 677
+ 678
+ 679
+ 680
+ 681
+ 682
+ 683
+ 684
+ 685
+ 686
+ 687
+ 688
+ 689
+ 690
+ 691
+ 692
+ 693
+ 694
+ 695
+ 696
+ 697
+ 698
+ 699
+ 700
+ 701
+ 702
+ 703
+ 704
+ 705
+ 706
+ 707
+ 708
+ 709
+ 710
+ 711
+ 712
+ 713
+ 714
+ 715
+ 716
+ 717
+ 718
+ 719
+ 720
+ 721
+ 722
+ 723
+ 724
+ 725
+ 726
+ 727
+ 728
+ 729
+ 730
+ 731
+ 732
+ 733
+ 734
+ 735
+ 736
+ 737
+ 738
+ 739
+ 740
+ 741
+ 742
+ 743
+ 744
+ 745
+ 746
+ 747
+ 748
+ 749
+ 750
+ 751
+ 752
+ 753
+ 754
+ 755
+ 756
+ 757
+ 758
+ 759
+ 760
+ 761
+ 762
+ 763
+ 764
+ 765
+ 766
+ 767
+ 768
+ 769
+ 770
+ 771
+ 772
+ 773
+ 774
+ 775
+ 776
+ 777
+ 778
+ 779
+ 780
+ 781
+ 782
+ 783
+ 784
+ 785
+ 786
+ 787
+ 788
+ 789
+ 790
+ 791
+ 792
+ 793
+ 794
+ 795
+ 796
+ 797
+ 798
+ 799
+ 800
+ 801
+ 802
+ 803
+ 804
+ 805
+ 806
+ 807
+ 808
+ 809
+ 810
+ 811
+ 812
+ 813
+ 814
+ 815
+ 816
+ 817
+ 818
+ 819
+ 820
+ 821
+ 822
+ 823
+ 824
+ 825
+ 826
+ 827
+ 828
+ 829
+ 830
+ 831
+ 832
+ 833
+ 834
+ 835
+ 836
+ 837
+ 838
+ 839
+ 840
+ 841
+ 842
+ 843
+ 844
+ 845
+ 846
+ 847
+ 848
+ 849
+ 850
+ 851
+ 852
+ 853
+ 854
+ 855
+ 856
+ 857
+ 858
+ 859
+ 860
+ 861
+ 862
+ 863
+ 864
+ 865
+ 866
+ 867
+ 868
+ 869
+ 870
+ 871
+ 872
+ 873
+ 874
+ 875
+ 876
+ 877
+ 878
+ 879
+ 880
+ 881
+ 882
+ 883
+ 884
+ 885
+ 886
+ 887
+ 888
+ 889
+ 890
+ 891
+ 892
+ 893
+ 894
+ 895
+ 896
+ 897
+ 898
+ 899
+ 900
+ 901
+ 902
+ 903
+ 904
+ 905
+ 906
+ 907
+ 908
+ 909
+ 910
+ 911
+ 912
+ 913
+ 914
+ 915
+ 916
+ 917
+ 918
+ 919
+ 920
+ 921
+ 922
+ 923
+ 924
+ 925
+ 926
+ 927
+ 928
+ 929
+ 930
+ 931
+ 932
+ 933
+ 934
+ 935
+ 936
+ 937
+ 938
+ 939
+ 940
+ 941
+ 942
+ 943
+ 944
+ 945
+ 946
+ 947
+ 948
+ 949
+ 950
+ 951
+ 952
+ 953
+ 954
+ 955
+ 956
+ 957
+ 958
+ 959
+ 960
+ 961
+ 962
+ 963
+ 964
+ 965
+ 966
+ 967
+ 968
+ 969
+ 970
+ 971
+ 972
+ 973
+ 974
+ 975
+ 976
+ 977
+ 978
+ 979
+ 980
+ 981
+ 982
+ 983
+ 984
+ 985
+ 986
+ 987
+ 988
+ 989
+ 990
+ 991
+ 992
+ 993
+ 994
+ 995
+ 996
+ 997
+ 998
+ 999
+1000
+1001
+1002
+1003
+1004
+1005
+1006
+1007
+1008
+1009
+1010
+1011
+1012
+1013
+1014
+1015
+1016
+1017
+1018
+1019
+1020
+1021
+1022
+1023
+1024
+1025
+1026
+1027
+1028
+1029
+1030
+1031
+1032
+1033
+1034
+1035
+1036
+1037
+1038
+1039
+1040
+1041
+1042
+1043
+1044
+1045
+1046
+1047
+1048
+1049
+1050
+1051
+1052
+1053
+1054
+1055
+1056
+1057
+1058
+1059
+1060
+1061
+1062
+1063
+1064
+1065
+1066
+1067
+1068
+1069
+1070
+1071
+1072
+1073
+1074
+1075
+1076
+1077
+1078
+1079
+1080
+1081
+1082
+1083
+1084
+1085
+1086
+1087
+1088
+1089
+1090
+1091
+1092
+1093
+1094
+1095
+1096
+1097
+1098
+1099
+1100
+1101
+1102
+1103
+1104
+1105
+1106
+1107
+1108
+1109
+1110
+1111
+1112
+1113
+1114
+1115
+1116
+1117
+1118
+1119
+1120
+1121
+1122
+1123
+1124
+1125
+1126
+1127
+1128
+1129
+1130
+1131
+1132
+1133
+1134
+1135
+1136
+1137
+1138
+1139
+1140
+1141
+1142
+1143
+1144
+1145
+1146
+1147
+1148
+1149
+1150
+1151
+1152
+1153
+1154
+1155
+1156
+1157
+1158
+1159
+1160
+1161
+1162
+1163
+1164
+1165
+1166
+1167
+1168
+1169
+1170
+1171
+1172
+1173
+1174
+1175
+1176
+1177
+1178
+1179
+1180
+1181
+1182
+1183
+1184
+1185
+1186
+1187
+1188
+1189
+1190
+1191
+1192
+1193
+1194
+1195
+1196
+1197
+1198
+1199
+1200
+1201
+1202
+1203
+1204
+1205
+1206
+1207
+1208
+1209
+1210
+1211
+1212
+1213
+1214
+1215
+1216
+1217
+1218
+1219
+1220
+1221
+1222
+1223
+1224
+1225
+1226
+1227
+1228
+1229
+1230
+1231
+1232
+1233
+1234
+1235
+1236
+1237
+1238
+1239
+1240
+1241
+1242
+1243
+1244
+1245
+1246
+1247
+1248
+1249
+1250
+1251
+1252
+1253
+1254
+1255
+1256
+1257
+1258
+1259
+1260
+1261
+1262
+1263
+1264
+1265
+1266
+1267
+1268
+1269
+1270
+1271
+1272
+1273
+1274
+1275
+1276
+1277
+1278
+1279
+1280
+1281
+1282
+1283
+1284
+1285
+1286
+1287
+1288
+1289
+1290
+1291
+1292
+1293
+1294
+1295
+1296
+1297
+1298
+1299
+1300
+1301
+1302
+1303
+1304
+1305
+1306
+1307
+1308
+1309
+1310
+1311
+1312
+1313
+1314
+1315
+1316
+1317
+1318
+1319
+1320
+1321
+1322
+1323
+1324
+1325
+1326
+1327
+1328
+1329
+1330
+1331
+1332
+1333
+1334
+1335
+1336
+1337
+1338
+1339
+1340
+1341
+1342
+1343
+1344
+1345
+1346
+1347
+1348
+1349
+1350
+1351
+1352
+1353
+1354
+1355
+1356
+1357
+1358
+1359
+1360
+1361
+1362
+1363
+1364
+1365
+1366
+1367
+1368
+1369
+1370
+1371
+1372
+1373
+1374
+1375
+1376
+1377
+1378
+1379
+1380
+1381
+1382
+1383
+1384
+1385
+1386
+1387
+1388
+1389
+1390
+1391
+1392
+1393
+1394
+1395
+1396
+1397
+1398
+1399
+1400
+1401
+1402
+1403
+1404
+1405
+1406
+1407
+1408
+1409
+1410
+1411
+1412
+1413
+1414
+1415
+1416
+1417
+1418
+1419
+1420
+1421
+1422
+1423
+1424
+1425
+1426
+1427
+1428
+1429
+1430
+1431
+1432
+1433
+1434
+1435
+1436
+1437
+1438
+1439
+1440
+1441
+1442
+1443
+1444
+1445
+1446
+1447
+1448
+1449
+1450
+1451
+1452
+1453
+1454
+1455
+1456
+1457
+1458
+1459
+1460
+1461
+1462
+1463
+1464
+1465
+1466
+1467
+1468
+1469
+1470
+1471
+1472
+1473
+1474
+1475
+1476
+1477
+1478
+1479
+1480
+1481
+1482
+1483
+1484
+1485
+1486
+1487
+1488
+1489
+1490
+1491
+1492
+1493
+1494
+1495
+1496
+1497
+1498
+1499
+1500
+1501
+1502
+1503
+1504
+1505
+1506
+1507
+1508
+1509
+1510
+1511
+1512
+1513
+1514
+1515
+1516
+1517
+1518
+1519
+1520
+1521
+1522
+1523
+1524
+1525
+1526
+1527
+1528
+1529
+1530
+1531
+1532
+1533
+1534
+1535
+1536
+1537
+1538
+1539
+1540
+1541
+1542
+1543
+1544
+1545
+1546
+1547
+1548
+1549
+1550
+1551
+1552
+1553
+1554
+1555
+1556
+1557
+1558
+1559
+1560
+1561
+1562
+1563
+1564
+1565
+1566
+1567
+1568
+1569
+1570
+1571
+1572
+1573
+1574
+1575
+1576
+1577
+1578
+1579
+1580
+1581
+1582
+1583
+1584
+1585
+1586
+1587
+1588
+1589
+1590
+1591
+1592
+1593
+1594
+1595
+1596
+1597
+1598
+1599
+1600
+1601
+1602
+1603
+1604
+1605
+1606
+1607
+1608
+1609
+1610
+1611
+1612
+1613
+1614
+1615
+1616
+1617
+1618
+1619
+1620
+1621
+1622
+1623
+1624
+1625
+1626
+1627
+1628
+1629
+1630
+1631
+1632
+1633
+1634
+1635
+1636
+1637
+1638
+1639
+1640
+1641
+1642
+1643
+1644
+1645
+1646
+1647
+1648
+1649
+1650
+1651
+1652
+1653
+1654
+1655
+1656
+1657
+1658
+1659
+1660
+1661
+1662
+1663
+1664
+1665
+1666
+1667
+1668
+1669
+1670
+1671
+1672
+1673
+1674
+1675
+1676
+1677
+1678
+1679
+1680
+1681
+1682
+1683
+1684
+1685
+1686
+1687
+1688
+1689
+1690
+1691
+1692
+1693
+1694
+1695
+1696
+1697
+1698
+1699
+1700
+1701
+1702
+1703
+1704
+1705
+1706
+1707
+1708
+1709
+1710
+1711
+1712
+1713
+1714
+1715
+1716
+1717
+1718
+1719
+1720
+1721
+1722
+1723
+1724
+1725
+1726
+1727
+1728
+1729
+1730
+1731
+1732
+1733
+1734
+1735
+1736
+1737
+1738
+1739
+1740
+1741
+1742
+1743
+1744
+1745
+1746
+1747
+1748
+1749
+1750
+1751
+1752
+1753
+1754
+1755
+1756
+1757
+1758
+1759
+1760
+1761
+1762
+1763
+1764
+1765
+1766
+1767
+1768
+1769
+1770
+1771
+1772
+1773
+1774
+1775
+1776
+1777
+1778
+1779
+1780
+1781
+1782
+1783
+1784
+1785
+1786
+1787
+1788
+1789
+1790
+1791
+1792
+1793
+1794
+1795
+1796
+1797
+1798
+1799
+1800
+1801
+1802
+1803
+1804
+1805
+1806
+1807
+1808
+1809
+1810
+1811
+1812
+1813
+1814
+1815
+1816
+1817
+1818
+1819
+1820
+1821
+1822
+1823
+1824
+1825
+1826
+1827
+1828
+1829
+1830
+1831
+1832
+1833
+1834
+1835
+1836
+1837
+1838
+1839
+1840
+1841
+1842
+1843
+1844
+1845
+1846
+1847
+1848
+1849
+1850
+1851
+1852
+1853
+1854
+1855
+1856
+1857
+1858
+1859
+1860
+1861
+1862
+1863
+1864
+1865
+1866
+1867
+1868
+1869
+1870
+1871
+1872
+1873
+1874
+1875
+1876
+1877
+1878
+1879
+1880
+1881
+1882
+1883
+1884
+1885
+1886
+1887
+1888
+1889
+1890
+1891
+1892
+1893
+1894
+1895
+1896
+1897
+1898
+1899
+1900
+1901
+1902
+1903
+1904
+1905
+1906
+1907
+1908
+1909
+1910
+1911
+1912
+1913
+1914
+1915
+1916
+1917
+1918
+1919
+1920
+1921
+1922
+1923
+1924
+1925
+1926
+1927
+1928
+1929
+1930
+1931
+1932
+1933
+1934
+1935
+1936
+1937
+1938
+1939
+1940
+1941
+1942
+1943
+1944
+1945
+1946
+1947
+1948
+1949
+1950
+1951
+1952
+1953
+1954
+1955
+1956
+1957
+1958
+1959
+1960
+1961
+1962
+1963
+1964
+1965
+1966
+1967
+1968
+1969
+1970
+1971
+1972
+1973
+1974
+1975
+1976
+1977
+1978
+1979
+1980
+1981
+1982
+1983
+1984
+1985
+1986
+1987
+1988
+1989
+1990
+1991
+1992
+1993
+1994
+1995
+1996
+1997
+1998
+1999
+2000
+2001
+2002
+2003
+2004
+2005
+2006
+2007
+2008
+2009
+2010
+2011
+2012
+2013
+2014
+2015
+2016
+2017
+2018
+2019
+2020
+2021
+2022
+2023
+2024
+2025
+2026
+2027
+2028
+2029
+2030
+2031
+2032
+2033
+2034
+2035
+2036
+2037
+2038
+2039
+2040
+2041
+2042
+2043
+2044
+2045
+2046
+2047
+2048
+2049
+2050
+2051
+2052
+2053
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/* Copyright (C) 2002 the Free Software Foundation
+ * Copyright (C) 2012-2021 MATE Developers
+ *
+ * This file is part of MATE Utils.
+ *
+ * MATE Utils is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * MATE Utils is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MATE Utils.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ *   Dennis Cranston <dennis_cranston@yahoo.com>
+ *   George Lebl
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <sys/wait.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <glib/gi18n.h>
+#include <gio/gio.h>
+
+#include <gtk/gtk.h>
+#include <gdk/gdkkeysyms.h>
+
+#include "gsearchtool.h"
+#include "gsearchtool-callbacks.h"
+#include "gsearchtool-support.h"
+
+#define SILENT_WINDOW_OPEN_LIMIT 5
+
+gboolean row_selected_by_button_press_event;
+
+static void
+store_window_state_and_geometry (GSearchWindow *gsearch)
+{
+	gsearch->window_width = MAX (gsearch->window_width, MINIMUM_WINDOW_WIDTH);
+	gsearch->window_height = MAX (gsearch->window_height, MINIMUM_WINDOW_HEIGHT);
+
+	g_settings_set_int (gsearch->mate_search_tool_settings,
+	                    "default-window-width",
+	                    gsearch->window_width);
+	g_settings_set_int (gsearch->mate_search_tool_settings,
+	                    "default-window-height",
+		            gsearch->window_height);
+	g_settings_set_boolean (gsearch->mate_search_tool_settings,
+	                        "default-window-maximized",
+	                        gsearch->is_window_maximized);
+}
+
+static void
+quit_application (GSearchWindow * gsearch)
+{
+	GSearchCommandDetails * command_details = gsearch->command_details;
+
+	if (command_details->command_status == RUNNING) {
+#ifdef HAVE_GETPGID
+		pid_t pgid;
+#endif
+		command_details->command_status = MAKE_IT_QUIT;
+#ifdef HAVE_GETPGID
+		pgid = getpgid (command_details->command_pid);
+
+		if ((pgid > 1) && (pgid != getpid ())) {
+			kill (-(getpgid (command_details->command_pid)), SIGKILL);
+		}
+		else {
+			kill (command_details->command_pid, SIGKILL);
+		}
+#else
+		kill (command_details->command_pid, SIGKILL);
+#endif
+		wait (NULL);
+	}
+	store_window_state_and_geometry (gsearch);
+	gtk_main_quit ();
+}
+
+void
+version_cb (const gchar * option_name,
+            const gchar * value,
+            gpointer data,
+            GError ** error)
+{
+	g_print ("%s %s\n", g_get_application_name (), VERSION);
+	exit (0);
+}
+
+void
+quit_session_cb (EggSMClient * client,
+                 gpointer data)
+{
+	quit_application ((GSearchWindow *) data);
+}
+
+void
+quit_cb (GtkWidget * widget,
+         GdkEvent * event,
+	 gpointer data)
+{
+	quit_application ((GSearchWindow *) data);
+}
+
+void
+click_close_cb (GtkWidget * widget,
+                gpointer data)
+{
+	quit_application ((GSearchWindow *) data);
+}
+
+void
+click_find_cb (GtkWidget * widget,
+               gpointer data)
+{
+	GSearchWindow * gsearch = data;
+	gchar * command;
+
+	if (gsearch->command_details->is_command_timeout_enabled == TRUE) {
+		return;
+	}
+
+	if ((gsearch->command_details->command_status == STOPPED) ||
+	    (gsearch->command_details->command_status == ABORTED)) {
+	    	command = build_search_command (gsearch, TRUE);
+		if (command != NULL) {
+			spawn_search_command (gsearch, command);
+			g_free (command);
+		}
+	}
+}
+
+void
+click_stop_cb (GtkWidget * widget,
+               gpointer data)
+{
+	GSearchWindow * gsearch = data;
+
+	if (gsearch->command_details->command_status == RUNNING) {
+#ifdef HAVE_GETPGID
+		pid_t pgid;
+#endif
+		gtk_widget_set_sensitive (gsearch->stop_button, FALSE);
+		gsearch->command_details->command_status = MAKE_IT_STOP;
+#ifdef HAVE_GETPGID
+		pgid = getpgid (gsearch->command_details->command_pid);
+
+		if ((pgid > 1) && (pgid != getpid ())) {
+			kill (-(getpgid (gsearch->command_details->command_pid)), SIGKILL);
+		}
+		else {
+			kill (gsearch->command_details->command_pid, SIGKILL);
+		}
+#else
+		kill (gsearch->command_details->command_pid, SIGKILL);
+#endif
+		wait (NULL);
+	}
+}
+
+void
+click_help_cb (GtkWidget * widget,
+               gpointer data)
+{
+	GtkWidget * window = data;
+	GError * error = NULL;
+
+	gtk_show_uri_on_window (GTK_WINDOW (window), "help:mate-search-tool",
+	                        gtk_get_current_event_time (), &error);
+
+	if (error) {
+		GtkWidget * dialog;
+
+		dialog = gtk_message_dialog_new (GTK_WINDOW (window),
+		                                 GTK_DIALOG_DESTROY_WITH_PARENT,
+		                                 GTK_MESSAGE_ERROR,
+		                                 GTK_BUTTONS_OK,
+		                                 _("Could not open help document."));
+		gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+		                                          error->message, NULL);
+
+		gtk_window_set_title (GTK_WINDOW (dialog), "");
+		gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
+		gtk_box_set_spacing (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), 14);
+
+		g_signal_connect (dialog, "response",
+		                  G_CALLBACK (gtk_widget_destroy),
+		                  NULL);
+
+                gtk_widget_show (dialog);
+                g_error_free (error);
+        }
+}
+
+void
+click_expander_cb (GObject * object,
+                   GParamSpec * param_spec,
+                   gpointer data)
+{
+	GSearchWindow * gsearch = data;
+
+	if (gtk_expander_get_expanded (GTK_EXPANDER (object)) == TRUE) {
+		gtk_widget_show (gsearch->available_options_vbox);
+		gtk_window_set_geometry_hints (GTK_WINDOW (gsearch->window),
+		                               GTK_WIDGET (gsearch->window),
+		                               &gsearch->window_geometry,
+		                               GDK_HINT_MIN_SIZE);
+	}
+	else {
+		GdkGeometry default_geometry = { MINIMUM_WINDOW_WIDTH, MINIMUM_WINDOW_HEIGHT, 0, 0, 0, 0, 0, 0, 0.0, 0.0, 0 };
+
+		gtk_widget_hide (gsearch->available_options_vbox);
+		gtk_window_set_geometry_hints (GTK_WINDOW (gsearch->window),
+		                               GTK_WIDGET (gsearch->window),
+		                               &default_geometry,
+		                               GDK_HINT_MIN_SIZE);
+	}
+}
+
+void
+size_allocate_cb (GtkWidget * widget,
+                  GtkAllocation * allocation,
+                  gpointer data)
+{
+	GtkWidget * button = data;
+
+ 	gtk_widget_set_size_request (button, allocation->width, -1);
+}
+
+void
+add_constraint_cb (GtkWidget * widget,
+                   gpointer data)
+{
+	GSearchWindow * gsearch = data;
+	gint idx;
+
+	idx = gtk_combo_box_get_active (GTK_COMBO_BOX (gsearch->available_options_combo_box));
+	add_constraint (gsearch, idx, NULL, FALSE);
+}
+
+void
+remove_constraint_cb (GtkWidget * widget,
+                      gpointer data)
+{
+	GList * list = data;
+
+	GSearchWindow * gsearch = g_list_first (list)->data;
+	GSearchConstraint * constraint = g_list_last (list)->data;
+
+      	gsearch->window_geometry.min_height -= WINDOW_HEIGHT_STEP;
+
+	gtk_window_set_geometry_hints (GTK_WINDOW (gsearch->window),
+	                               GTK_WIDGET (gsearch->window),
+	                               &gsearch->window_geometry,
+	                               GDK_HINT_MIN_SIZE);
+
+	gtk_container_remove (GTK_CONTAINER (gsearch->available_options_vbox), gtk_widget_get_parent (widget));
+
+	gsearch->available_options_selected_list =
+	    g_list_remove (gsearch->available_options_selected_list, constraint);
+
+	set_constraint_selected_state (gsearch, constraint->constraint_id, FALSE);
+	set_constraint_gsettings_boolean (constraint->constraint_id, FALSE);
+	g_slice_free (GSearchConstraint, constraint);
+	g_list_free (list);
+}
+
+void
+constraint_activate_cb (GtkWidget * widget,
+                        gpointer data)
+{
+	GSearchWindow * gsearch = data;
+
+	if ((gtk_widget_get_visible (gsearch->find_button)) &&
+	    (gtk_widget_get_sensitive (gsearch->find_button))) {
+		click_find_cb (gsearch->find_button, data);
+	}
+}
+
+void
+constraint_update_info_cb (GtkWidget * widget,
+                           gpointer data)
+{
+	static gchar * string;
+	GSearchConstraint * opt = data;
+
+	string = (gchar *) gtk_entry_get_text (GTK_ENTRY (widget));
+	update_constraint_info (opt, string);
+}
+
+void
+name_contains_activate_cb (GtkWidget * widget,
+                           gpointer data)
+{
+	GSearchWindow * gsearch = data;
+
+	if ((gtk_widget_get_visible (gsearch->find_button)) &&
+	    (gtk_widget_get_sensitive (gsearch->find_button))) {
+		click_find_cb (gsearch->find_button, data);
+	}
+}
+
+void
+look_in_folder_changed_cb (GtkWidget * widget,
+                           gpointer data)
+{
+	GSearchWindow * gsearch = data;
+	gchar * value;
+
+	value = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (gsearch->look_in_folder_button));
+
+	if (value != NULL) {
+		g_settings_set_string (gsearch->mate_search_tool_settings, "look-in-folder", value);
+	}
+	g_free (value);
+}
+
+static gint
+display_dialog_file_open_limit (GtkWidget * window,
+                                  gint count)
+{
+	GtkWidget * dialog;
+	GtkWidget * button;
+	gchar * primary;
+	gchar * secondary;
+	gint response;
+
+	primary = g_strdup_printf (ngettext ("Are you sure you want to open %d document?",
+	                                     "Are you sure you want to open %d documents?",
+	                                     count),
+	                           count);
+
+	secondary = g_strdup_printf (ngettext ("This will open %d separate window.",
+	                                       "This will open %d separate windows.",
+	                                       count),
+	                             count);
+
+	dialog = gtk_message_dialog_new (GTK_WINDOW (window),
+	                                 GTK_DIALOG_DESTROY_WITH_PARENT,
+	                                 GTK_MESSAGE_QUESTION,
+	                                 GTK_BUTTONS_CANCEL,
+	                                 primary, NULL);
+	gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+	                                          secondary, NULL);
+
+	gtk_window_set_title (GTK_WINDOW (dialog), "");
+	gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
+	gtk_box_set_spacing (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), 14);
+
+	button = GTK_WIDGET (g_object_new (GTK_TYPE_BUTTON,
+					   "label", "gtk-open",
+					   "use-stock", TRUE,
+					   "use-underline", TRUE,
+					   NULL));
+
+	gtk_widget_set_can_default (button, TRUE);
+	gtk_widget_show (button);
+
+	gtk_dialog_add_action_widget (GTK_DIALOG (dialog), button, GTK_RESPONSE_OK);
+	gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
+
+	response = gtk_dialog_run (GTK_DIALOG (dialog));
+	gtk_widget_destroy (dialog);
+	g_free (primary);
+	g_free (secondary);
+
+	return response;
+}
+
+static void
+display_dialog_could_not_open_file (GtkWidget * window,
+                                    const gchar * file,
+                                    const gchar * message)
+{
+	GtkWidget * dialog;
+	gchar * primary;
+
+	primary = g_strdup_printf (_("Could not open document \"%s\"."), file);
+
+	dialog = gtk_message_dialog_new (GTK_WINDOW (window),
+	                                 GTK_DIALOG_DESTROY_WITH_PARENT,
+	                                 GTK_MESSAGE_ERROR,
+	                                 GTK_BUTTONS_OK,
+	                                 primary, NULL);
+	gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+	                                          message, NULL);
+
+	gtk_window_set_title (GTK_WINDOW (dialog), "");
+	gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
+	gtk_box_set_spacing (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), 14);
+
+	g_signal_connect (dialog, "response",
+	       		  G_CALLBACK (gtk_widget_destroy),
+	                  NULL);
+
+	gtk_widget_show (dialog);
+	g_free (primary);
+}
+
+static void
+display_dialog_could_not_open_folder (GtkWidget * window,
+                                      const gchar * folder)
+{
+	GtkWidget * dialog;
+	gchar * primary;
+
+	primary = g_strdup_printf (_("Could not open folder \"%s\"."), folder);
+
+	dialog = gtk_message_dialog_new (GTK_WINDOW (window),
+	                                 GTK_DIALOG_DESTROY_WITH_PARENT,
+	                                 GTK_MESSAGE_ERROR,
+	                                 GTK_BUTTONS_OK,
+	                                 primary, NULL);
+	gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+	                                          _("The caja file manager is not running."));
+
+	gtk_window_set_title (GTK_WINDOW (dialog), "");
+	gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
+	gtk_box_set_spacing (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), 14);
+
+	g_signal_connect (dialog, "response",
+	       		  G_CALLBACK (gtk_widget_destroy),
+	                  NULL);
+
+	gtk_widget_show (dialog);
+	g_free (primary);
+}
+
+void
+open_file_event_cb (GtkWidget * widget,
+                    GdkEventButton * event,
+                    gpointer data)
+{
+	open_file_cb ((GtkMenuItem *) widget, data);
+}
+
+void
+open_file_cb (GtkMenuItem * action,
+              gpointer data)
+{
+	GSearchWindow * gsearch = data;
+	GtkTreeModel * model;
+	GList * list;
+	guint idx;
+
+	if (gtk_tree_selection_count_selected_rows (GTK_TREE_SELECTION (gsearch->search_results_selection)) == 0) {
+		return;
+	}
+
+	list = gtk_tree_selection_get_selected_rows (GTK_TREE_SELECTION (gsearch->search_results_selection),
+						     &model);
+
+	if (g_list_length (list) > SILENT_WINDOW_OPEN_LIMIT) {
+		gint response;
+
+		response = display_dialog_file_open_limit (gsearch->window, g_list_length (list));
+
+		if (response == GTK_RESPONSE_CANCEL) {
+			g_list_free_full (list, (GDestroyNotify) gtk_tree_path_free);
+			return;
+		}
+	}
+
+	for (idx = 0; idx < g_list_length (list); idx++) {
+
+		gboolean no_files_found = FALSE;
+		gchar * utf8_name;
+		gchar * locale_file;
+		GtkTreeIter iter;
+
+		gtk_tree_model_get_iter (GTK_TREE_MODEL (gsearch->search_results_list_store), &iter,
+		                         g_list_nth_data (list, idx));
+
+		gtk_tree_model_get (GTK_TREE_MODEL (gsearch->search_results_list_store), &iter,
+    		                    COLUMN_NAME, &utf8_name,
+				    COLUMN_LOCALE_FILE, &locale_file,
+		                    COLUMN_NO_FILES_FOUND, &no_files_found,
+		                    -1);
+
+		if (!no_files_found) {
+			GAppInfo * app = NULL;
+
+			if (GTK_IS_MENU_ITEM (action)) {
+				app = g_object_get_data (G_OBJECT (action), "app");
+			}
+
+			if (!g_file_test (locale_file, G_FILE_TEST_EXISTS)) {
+				gtk_tree_selection_unselect_iter (GTK_TREE_SELECTION (gsearch->search_results_selection),
+				                                  &iter);
+				display_dialog_could_not_open_file (gsearch->window, utf8_name,
+				                                    _("The document does not exist."));
+
+			}
+			else if (open_file_with_application (gsearch->window, locale_file, app) == FALSE) {
+
+				if (launch_file (locale_file) == FALSE) {
+
+					if (g_file_test (locale_file, G_FILE_TEST_IS_DIR)) {
+
+						if (open_file_with_filemanager (gsearch->window, locale_file) == FALSE) {
+							display_dialog_could_not_open_folder (gsearch->window, utf8_name);
+						}
+					}
+					else {
+						display_dialog_could_not_open_file (gsearch->window, utf8_name,
+						                                    _("There is no installed viewer capable "
+						                                      "of displaying the document."));
+					}
+				}
+			}
+		}
+		g_free (utf8_name);
+		g_free (locale_file);
+	}
+	g_list_free_full (list, (GDestroyNotify) gtk_tree_path_free);
+}
+
+static gint
+display_dialog_folder_open_limit (GtkWidget * window,
+                                  gint count)
+{
+	GtkWidget * dialog;
+	GtkWidget * button;
+	gchar * primary;
+	gchar * secondary;
+	gint response;
+
+	primary = g_strdup_printf (ngettext ("Are you sure you want to open %d folder?",
+	                                     "Are you sure you want to open %d folders?",
+	                                     count),
+	                           count);
+
+	secondary = g_strdup_printf (ngettext ("This will open %d separate window.",
+					       "This will open %d separate windows.",
+					       count),
+	                             count);
+
+	dialog = gtk_message_dialog_new (GTK_WINDOW (window),
+	                                 GTK_DIALOG_DESTROY_WITH_PARENT,
+	                                 GTK_MESSAGE_QUESTION,
+	                                 GTK_BUTTONS_CANCEL,
+	                                 primary, NULL);
+	gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+	                                          secondary, NULL);
+
+	gtk_window_set_title (GTK_WINDOW (dialog), "");
+	gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
+	gtk_box_set_spacing (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), 14);
+
+	button = GTK_WIDGET (g_object_new (GTK_TYPE_BUTTON,
+					   "label", "gtk-open",
+					   "use-stock", TRUE,
+					   "use-underline", TRUE,
+					   NULL));
+
+	gtk_widget_set_can_default (button, TRUE);
+	gtk_widget_show (button);
+
+	gtk_dialog_add_action_widget (GTK_DIALOG (dialog), button, GTK_RESPONSE_OK);
+	gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
+
+	response = gtk_dialog_run (GTK_DIALOG (dialog));
+	gtk_widget_destroy (dialog);
+	g_free (primary);
+	g_free (secondary);
+
+	return response;
+}
+
+void
+open_folder_cb (GtkAction * action,
+                gpointer data)
+{
+	GSearchWindow * gsearch = data;
+	GtkTreeModel * model;
+	GFile * g_file = NULL;
+	GFileInfo * g_file_info = NULL;
+	GAppInfo * g_app_info = NULL;
+	GList * list;
+	guint idx;
+
+	if (gtk_tree_selection_count_selected_rows (GTK_TREE_SELECTION (gsearch->search_results_selection)) == 0) {
+		return;
+	}
+
+	list = gtk_tree_selection_get_selected_rows (GTK_TREE_SELECTION (gsearch->search_results_selection),
+						     &model);
+
+	if (g_list_length (list) > SILENT_WINDOW_OPEN_LIMIT) {
+		gint response;
+
+		response = display_dialog_folder_open_limit (gsearch->window, g_list_length (list));
+
+		if (response == GTK_RESPONSE_CANCEL) {
+			g_list_free_full (list, (GDestroyNotify) gtk_tree_path_free);
+			return;
+		}
+	}
+
+	for (idx = 0; idx < g_list_length (list); idx++) {
+
+		gchar * locale_folder;
+		gchar * utf8_folder;
+		gchar * locale_file;
+		GtkTreeIter iter;
+
+		gtk_tree_model_get_iter (GTK_TREE_MODEL (gsearch->search_results_list_store), &iter,
+					 g_list_nth_data (list, idx));
+
+		gtk_tree_model_get (GTK_TREE_MODEL (gsearch->search_results_list_store), &iter,
+				    COLUMN_RELATIVE_PATH, &utf8_folder,
+				    COLUMN_LOCALE_FILE, &locale_file,
+				    -1);
+
+		locale_folder = g_path_get_dirname (locale_file);
+
+		if (idx == 0) {
+			g_file = g_file_new_for_path (locale_folder);
+			g_file_info = g_file_query_info (g_file, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE, G_FILE_QUERY_INFO_NONE, NULL, NULL);
+			g_app_info = g_app_info_get_default_for_type (g_file_info_get_content_type (g_file_info), FALSE);
+		}
+
+		if (open_file_with_application (gsearch->window, locale_folder, g_app_info) == FALSE) {
+
+			if (open_file_with_filemanager (gsearch->window, locale_folder) == FALSE) {
+
+				display_dialog_could_not_open_folder (gsearch->window, utf8_folder);
+
+				g_list_free_full (list, (GDestroyNotify) gtk_tree_path_free);
+				g_free (locale_folder);
+				g_free (utf8_folder);
+				g_object_unref (g_file);
+				g_object_unref (g_file_info);
+				g_object_unref (g_app_info);
+				return;
+			}
+		}
+		g_free (locale_folder);
+		g_free (locale_file);
+		g_free (utf8_folder);
+	}
+	g_list_free_full (list, (GDestroyNotify) gtk_tree_path_free);
+	g_object_unref (g_file);
+	g_object_unref (g_file_info);
+	g_object_unref (g_app_info);
+}
+
+void
+copy_path_cb (GtkAction * action,
+              gpointer data)
+{
+	GSearchWindow * gsearch = data;
+	GtkTreeModel * model;
+	GtkTreeIter iter;
+	GList * list;
+	gchar * locale_path;
+	GtkClipboard* clipboard;
+
+	list = gtk_tree_selection_get_selected_rows (GTK_TREE_SELECTION (gsearch->search_results_selection),
+						     &model);
+
+	gtk_tree_model_get_iter (GTK_TREE_MODEL (gsearch->search_results_list_store), &iter,
+				 g_list_nth_data (list, 0));
+
+	gtk_tree_model_get (GTK_TREE_MODEL (gsearch->search_results_list_store), &iter,
+			    COLUMN_LOCALE_FILE, &locale_path,
+			    -1);
+	clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
+	gtk_clipboard_set_text(clipboard, locale_path, -1);
+
+	g_free (locale_path);
+	g_list_free_full (list, (GDestroyNotify) gtk_tree_path_free);
+}
+
+void
+file_changed_cb (GFileMonitor * handle,
+                 const gchar * monitor_uri,
+                 const gchar * info_uri,
+                 GFileMonitorEvent event_type,
+                 gpointer data)
+{
+	GSearchMonitor * monitor = data;
+	GSearchWindow * gsearch = monitor->gsearch;
+	GtkTreeModel * model;
+	GtkTreePath * path;
+	GtkTreeIter iter;
+
+	switch (event_type) {
+	case G_FILE_MONITOR_EVENT_DELETED:
+		path = gtk_tree_row_reference_get_path (monitor->reference);
+		model = gtk_tree_row_reference_get_model (monitor->reference);
+		gtk_tree_model_get_iter (model, &iter, path);
+		tree_model_iter_free_monitor (model, NULL, &iter, NULL);
+		gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
+		update_search_counts (gsearch);
+		break;
+	default:
+		break;
+	}
+}
+
+static void
+display_dialog_could_not_move_to_trash (GtkWidget * window,
+                                        const gchar * file,
+                                        const gchar * message)
+{
+	GtkWidget * dialog;
+	gchar * primary;
+
+	primary = g_strdup_printf (_("Could not move \"%s\" to trash."), file);
+
+	dialog = gtk_message_dialog_new (GTK_WINDOW (window),
+	                                 GTK_DIALOG_DESTROY_WITH_PARENT,
+	                                 GTK_MESSAGE_ERROR,
+	                                 GTK_BUTTONS_OK,
+	                                 primary, NULL);
+	gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+	                                          message, NULL);
+
+	gtk_window_set_title (GTK_WINDOW (dialog), "");
+	gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
+	gtk_box_set_spacing (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), 14);
+
+	g_signal_connect (dialog, "response",
+	       		  G_CALLBACK (gtk_widget_destroy),
+	                  NULL);
+	gtk_widget_show (dialog);
+	g_free (primary);
+}
+
+static gint
+display_dialog_delete_permanently (GtkWidget * window,
+                                   const gchar * file)
+{
+	GtkWidget * dialog;
+	GtkWidget * button;
+	gchar * primary;
+	gchar * secondary;
+	gint response;
+
+	primary = g_strdup_printf (_("Do you want to delete \"%s\" permanently?"),
+	                           g_path_get_basename (file));
+
+	secondary = g_strdup_printf (_("Trash is unavailable.  Could not move \"%s\" to the trash."),
+	                             file);
+
+	dialog = gtk_message_dialog_new (GTK_WINDOW (window),
+	                                 GTK_DIALOG_DESTROY_WITH_PARENT,
+	                                 GTK_MESSAGE_QUESTION,
+	                                 GTK_BUTTONS_CANCEL,
+	                                 primary, NULL);
+	gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+	                                          secondary, NULL);
+
+	gtk_window_set_title (GTK_WINDOW (dialog), "");
+	gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
+	gtk_box_set_spacing (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), 14);
+
+	button = GTK_WIDGET (g_object_new (GTK_TYPE_BUTTON,
+					   "label", "gtk-delete",
+					   "use-stock", TRUE,
+					   "use-underline", TRUE,
+					   NULL));
+
+	gtk_widget_set_can_default (button, TRUE);
+	gtk_widget_show (button);
+
+	gtk_dialog_add_action_widget (GTK_DIALOG (dialog), button, GTK_RESPONSE_OK);
+	gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
+
+	response = gtk_dialog_run (GTK_DIALOG (dialog));
+
+	gtk_widget_destroy (GTK_WIDGET(dialog));
+	g_free (primary);
+	g_free (secondary);
+
+	return response;
+}
+
+static void
+display_dialog_could_not_delete (GtkWidget * window,
+                                 const gchar * file,
+                                 const gchar * message)
+{
+	GtkWidget * dialog;
+	gchar * primary;
+
+	primary = g_strdup_printf (_("Could not delete \"%s\"."), file);
+
+	dialog = gtk_message_dialog_new (GTK_WINDOW (window),
+	                                 GTK_DIALOG_DESTROY_WITH_PARENT,
+	                                 GTK_MESSAGE_ERROR,
+	                                 GTK_BUTTONS_OK,
+	                                 primary, NULL);
+	gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+	                                          message, NULL);
+
+	gtk_window_set_title (GTK_WINDOW (dialog), "");
+	gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
+	gtk_box_set_spacing (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), 14);
+
+	g_signal_connect (dialog, "response",
+	       		  G_CALLBACK (gtk_widget_destroy),
+	                  NULL);
+	gtk_widget_show (dialog);
+	g_free (primary);
+}
+
+void
+move_to_trash_cb (GtkAction * action,
+                  gpointer data)
+{
+	GSearchWindow * gsearch = data;
+	GtkTreePath * last_selected_path = NULL;
+	gint total;
+	gint idx;
+
+	if (gtk_tree_selection_count_selected_rows (GTK_TREE_SELECTION (gsearch->search_results_selection)) == 0) {
+		return;
+	}
+
+	total = gtk_tree_selection_count_selected_rows (GTK_TREE_SELECTION (gsearch->search_results_selection));
+
+	for (idx = 0; idx < total; idx++) {
+		gboolean no_files_found = FALSE;
+		GtkTreeModel * model;
+		GtkTreeIter iter;
+		GList * list;
+		GFile * g_file;
+		GError * error = NULL;
+		gchar * utf8_basename;
+		gchar * utf8_filename;
+		gchar * locale_filename;
+		gboolean result;
+
+		list = gtk_tree_selection_get_selected_rows (GTK_TREE_SELECTION (gsearch->search_results_selection),
+ 		                                             &model);
+
+		gtk_tree_model_get_iter (GTK_TREE_MODEL (gsearch->search_results_list_store), &iter,
+					 g_list_nth_data (list, 0));
+
+		gtk_tree_model_get (GTK_TREE_MODEL (gsearch->search_results_list_store), &iter,
+    				    COLUMN_NAME, &utf8_basename,
+				    COLUMN_LOCALE_FILE, &locale_filename,
+			   	    COLUMN_NO_FILES_FOUND, &no_files_found,
+			   	    -1);
+
+		if (no_files_found) {
+			g_free (utf8_basename);
+			g_free (locale_filename);
+			return;
+		}
+
+		utf8_filename = g_filename_display_name (locale_filename);
+
+		if (idx + 1 == total) {
+			last_selected_path = gtk_tree_model_get_path (GTK_TREE_MODEL (gsearch->search_results_list_store), &iter);
+		}
+
+		if ((!g_file_test (locale_filename, G_FILE_TEST_EXISTS)) &&
+		    (!g_file_test (locale_filename, G_FILE_TEST_IS_SYMLINK))) {
+			gtk_tree_selection_unselect_iter (GTK_TREE_SELECTION (gsearch->search_results_selection), &iter);
+			display_dialog_could_not_move_to_trash (gsearch->window, utf8_basename,
+			                                        _("The document does not exist."));
+		}
+
+		g_file = g_file_new_for_path (locale_filename);
+		result = g_file_trash (g_file, NULL, &error);
+
+		gtk_tree_selection_unselect_iter (GTK_TREE_SELECTION (gsearch->search_results_selection), &iter);
+		g_object_unref (g_file);
+
+		if (result == TRUE) {
+			tree_model_iter_free_monitor (GTK_TREE_MODEL (gsearch->search_results_list_store),
+						      NULL, &iter, NULL);
+			gtk_list_store_remove (GTK_LIST_STORE (gsearch->search_results_list_store), &iter);
+		}
+		else {
+			gint response;
+
+			gtk_tree_selection_unselect_iter (GTK_TREE_SELECTION (gsearch->search_results_selection), &iter);
+			response = display_dialog_delete_permanently (gsearch->window, utf8_filename);
+
+			if (response == GTK_RESPONSE_OK) {
+				GFile * g_file_tmp;
+				GError * error_tmp = NULL;
+
+				g_file_tmp = g_file_new_for_path (locale_filename);
+				result = g_file_delete (g_file_tmp, NULL, &error_tmp);
+				g_object_unref (g_file_tmp);
+
+				if (result == TRUE) {
+					tree_model_iter_free_monitor (GTK_TREE_MODEL (gsearch->search_results_list_store),
+								      NULL, &iter, NULL);
+					gtk_list_store_remove (GTK_LIST_STORE (gsearch->search_results_list_store), &iter);
+				}
+				else {
+					gchar * message;
+
+					message = g_strdup_printf (_("Deleting \"%s\" failed: %s."),
+					                             utf8_filename, error_tmp->message);
+
+					display_dialog_could_not_delete (gsearch->window, utf8_basename, message);
+
+					g_error_free (error_tmp);
+					g_free (message);
+				}
+			}
+			else {
+				gchar * message;
+
+				message = g_strdup_printf (_("Moving \"%s\" failed: %s."),
+				                           utf8_filename,
+				                           error->message);
+				display_dialog_could_not_move_to_trash (gsearch->window, utf8_basename,
+				                                        message);
+				g_error_free (error);
+				g_free (message);
+			}
+		}
+		g_list_free_full (list, (GDestroyNotify) gtk_tree_path_free);
+		g_free (locale_filename);
+		g_free (utf8_filename);
+		g_free (utf8_basename);
+	}
+
+	/* Bugzilla #397945: Select next row in the search results list */
+	if (last_selected_path != NULL) {
+		if (gtk_tree_selection_count_selected_rows (GTK_TREE_SELECTION (gsearch->search_results_selection)) == 0) {
+			gtk_tree_selection_select_path (GTK_TREE_SELECTION (gsearch->search_results_selection),
+			                                last_selected_path);
+			if (gtk_tree_selection_count_selected_rows (GTK_TREE_SELECTION (gsearch->search_results_selection)) == 0) {
+				gtk_tree_path_prev (last_selected_path);
+				gtk_tree_selection_select_path (GTK_TREE_SELECTION (gsearch->search_results_selection),
+				                                last_selected_path);
+			}
+		}
+		gtk_tree_path_free (last_selected_path);
+	}
+
+	if (gsearch->command_details->command_status != RUNNING) {
+		update_search_counts (gsearch);
+	}
+}
+
+gboolean
+file_button_press_event_cb (GtkWidget * widget,
+                            GdkEventButton * event,
+                            gpointer data)
+{
+	GtkTreeView * tree = data;
+	GtkTreePath * path;
+
+	row_selected_by_button_press_event = TRUE;
+
+	if (event->window != gtk_tree_view_get_bin_window (tree)) {
+		return FALSE;
+	}
+
+	if (gtk_tree_view_get_path_at_pos (tree, event->x, event->y,
+		&path, NULL, NULL, NULL)) {
+
+		if ((event->button == 1 || event->button == 2 || event->button == 3)
+			&& gtk_tree_selection_path_is_selected (gtk_tree_view_get_selection (tree), path)) {
+			row_selected_by_button_press_event = FALSE;
+		}
+		gtk_tree_path_free (path);
+	}
+	else {
+		gtk_tree_selection_unselect_all (gtk_tree_view_get_selection (tree));
+	}
+
+	return !(row_selected_by_button_press_event);
+}
+
+gboolean
+file_key_press_event_cb (GtkWidget * widget,
+                         GdkEventKey * event,
+                         gpointer data)
+{
+	if (event->keyval == GDK_KEY_space  ||
+	    event->keyval == GDK_KEY_Return ||
+	    event->keyval == GDK_KEY_KP_Enter) {
+		if (event->state != GDK_CONTROL_MASK) {
+			open_file_cb ((GtkMenuItem *) NULL, data);
+			return TRUE;
+		}
+	}
+	else if (event->keyval == GDK_KEY_Delete) {
+		move_to_trash_cb ((GtkAction *) NULL, data);
+		return TRUE;
+	}
+	return FALSE;
+}
+
+static gint
+open_with_list_sort (gconstpointer a,
+                     gconstpointer b)
+{
+	const gchar * a_app_name = g_app_info_get_name ((GAppInfo *) a);
+	const gchar * b_app_name = g_app_info_get_name ((GAppInfo *) b);
+	gchar * a_utf8;
+	gchar * b_utf8;
+	gint result;
+
+	a_utf8 = g_utf8_casefold (a_app_name, -1);
+	b_utf8 = g_utf8_casefold (b_app_name, -1);
+
+	result = g_utf8_collate (a_utf8, b_utf8);
+
+	g_free (a_utf8);
+	g_free (b_utf8);
+
+	return result;
+}
+
+static GtkWidget *
+mate_image_menu_item_new_from_icon (const gchar *icon_name,
+                                    const gchar *label_name)
+{
+	gchar *concat;
+	GtkWidget *icon;
+	GtkWidget *box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+
+	if (icon_name)
+		icon = gtk_image_new_from_icon_name (icon_name, GTK_ICON_SIZE_MENU);
+	else
+		icon = gtk_image_new ();
+
+	concat = g_strconcat (label_name, "     ", NULL);
+	GtkWidget *label_menu = gtk_label_new_with_mnemonic (concat);
+	GtkWidget *menuitem = gtk_menu_item_new ();
+
+	gtk_container_add (GTK_CONTAINER (box), icon);
+
+	gtk_container_add (GTK_CONTAINER (box), label_menu);
+
+	gtk_container_add (GTK_CONTAINER (menuitem), box);
+	gtk_widget_show_all (menuitem);
+
+	g_free (concat);
+
+	return menuitem;
+}
+
+static GtkWidget *
+mate_image_menu_item_new_from_gicon (GIcon *icon_img,
+                                     const gchar *label_name)
+{
+	gchar *concat;
+	GtkWidget *icon;
+	GtkWidget *box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+
+	if (icon_img)
+		icon = gtk_image_new_from_gicon (icon_img, GTK_ICON_SIZE_MENU);
+	else
+		icon = gtk_image_new ();
+
+	concat = g_strconcat (label_name, "     ", NULL);
+	GtkWidget *label_menu = gtk_label_new_with_mnemonic (concat);
+	GtkWidget *menuitem = gtk_menu_item_new ();
+
+	gtk_container_add (GTK_CONTAINER (box), icon);
+
+	gtk_container_add (GTK_CONTAINER (box), label_menu);
+
+	gtk_container_add (GTK_CONTAINER (menuitem), box);
+	gtk_widget_show_all (menuitem);
+
+	g_free (concat);
+
+	return menuitem;
+}
+
+static GtkWidget *
+mate_image_menu_item_new_from_pixbuf (GdkPixbuf   *icon_pixbuf,
+                                      const gchar *label_name)
+{
+	gchar *concat;
+	GtkWidget *icon;
+	GtkWidget *box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+
+	if (icon_pixbuf)
+		icon = gtk_image_new_from_pixbuf (icon_pixbuf);
+	else
+		icon = gtk_image_new ();
+
+	concat = g_strconcat (label_name, "     ", NULL);
+	GtkWidget *label_menu = gtk_label_new_with_mnemonic (concat);
+	GtkWidget *menuitem = gtk_menu_item_new ();
+
+	gtk_container_add (GTK_CONTAINER (box), icon);
+
+	gtk_container_add (GTK_CONTAINER (box), label_menu);
+
+	gtk_container_add (GTK_CONTAINER (menuitem), box);
+	gtk_widget_show_all (menuitem);
+
+	g_free (concat);
+
+	return menuitem;
+}
+
+static void
+build_popup_menu_for_file (GSearchWindow * gsearch,
+                           gchar * file)
+{
+	GtkWidget * new1, * separatormenuitem1;
+	GtkWidget * new2;
+	gint i;
+
+	if (GTK_IS_MENU (gsearch->search_results_popup_menu) == TRUE) {
+		g_object_ref_sink (gsearch->search_results_popup_menu);
+		g_object_unref (gsearch->search_results_popup_menu);
+	}
+
+	if (GTK_IS_MENU (gsearch->search_results_popup_submenu) == TRUE) {
+		g_object_ref_sink (gsearch->search_results_popup_submenu);
+		g_object_unref (gsearch->search_results_popup_submenu);
+	}
+
+	gsearch->search_results_popup_menu = gtk_menu_new ();
+
+	gtk_menu_set_reserve_toggle_size (GTK_MENU (gsearch->search_results_popup_menu), FALSE);
+
+	if (file == NULL || g_file_test (file, G_FILE_TEST_IS_DIR) == TRUE) {
+		/* Popup menu item: Open */
+		new1 = mate_image_menu_item_new_from_icon ("document-open", _("_Open"));
+		gtk_container_add (GTK_CONTAINER (gsearch->search_results_popup_menu), new1);
+		gtk_widget_show (new1);
+
+		g_signal_connect (new1, "activate",
+		                  G_CALLBACK (open_file_cb),
+		                  (gpointer) gsearch);
+	}
+	else {
+		GFile * g_file;
+		GFileInfo * file_info;
+		GList * list;
+		gchar * str;
+		gint list_length;
+		GIcon * file_icon = NULL;
+
+		g_file = g_file_new_for_path (file);
+		file_info = g_file_query_info (g_file, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE, G_FILE_QUERY_INFO_NONE, NULL, NULL);
+		list = g_app_info_get_all_for_type (g_file_info_get_content_type (file_info));
+
+		list_length = g_list_length (list);
+
+		if (list_length <= 0) {
+
+			/* Popup menu item: Open */
+			new1 = mate_image_menu_item_new_from_icon ("document-open", _("_Open"));
+			gtk_container_add (GTK_CONTAINER (gsearch->search_results_popup_menu), new1);
+			gtk_widget_show (new1);
+
+			g_signal_connect (new1, "activate",
+			                  G_CALLBACK (open_file_cb),
+		        	          (gpointer) gsearch);
+		}
+		else {
+			if (list_length >= 3) { /* Sort all except first application by name */
+				GList * tmp;
+
+				tmp = g_list_first (list);
+				list = g_list_remove_link (list, tmp);
+				list = g_list_sort (list, open_with_list_sort);
+				list = g_list_prepend (list, tmp->data);
+				g_list_free (tmp);
+			}
+
+			/* Popup menu item: Open with (default) */
+
+			if (g_app_info_get_icon ((GAppInfo *)list->data) != NULL) {
+				file_icon = g_object_ref (g_app_info_get_icon ((GAppInfo *)list->data));
+
+				if (file_icon == NULL) {
+					file_icon = g_themed_icon_new ("gtk-open");
+				}
+			}
+
+			str = g_strdup_printf (_("_Open with %s"),  g_app_info_get_name (list->data));
+			new1 = mate_image_menu_item_new_from_gicon (file_icon, str);
+			g_free (str);
+			gtk_widget_show (new1);
+
+			g_object_set_data_full (G_OBJECT (new1), "app", (GAppInfo *)list->data,
+			                        g_object_unref);
+
+			gtk_container_add (GTK_CONTAINER (gsearch->search_results_popup_menu), new1);
+			g_signal_connect ((gpointer) new1, "activate", G_CALLBACK (open_file_cb),
+					  (gpointer) gsearch);
+
+			separatormenuitem1 = gtk_separator_menu_item_new ();
+			gtk_widget_show (separatormenuitem1);
+			gtk_container_add (GTK_CONTAINER (gsearch->search_results_popup_menu), separatormenuitem1);
+			gtk_widget_set_sensitive (separatormenuitem1, FALSE);
+
+			for (list = g_list_next (list), i = 0; list != NULL; list = g_list_next (list), i++) {
+
+				/* Popup menu item: Open with (others) */
+				if (list_length < 4) {
+					str = g_strdup_printf (_("Open with %s"),  g_app_info_get_name (list->data));
+				}
+				else {
+					str = g_strdup_printf ("%s",  g_app_info_get_name (list->data));
+				}
+
+				gboolean icon_done = FALSE;
+
+				if (list_length >= 4) {
+
+					if (g_app_info_get_icon ((GAppInfo *)list->data) != NULL) {
+						file_icon = g_object_ref (g_app_info_get_icon ((GAppInfo *)list->data));
+
+						if (file_icon == NULL) {
+							file_icon = g_themed_icon_new ("gtk-open");
+						}
+
+						icon_done = TRUE;
+						new1 = mate_image_menu_item_new_from_gicon (file_icon, str);
+						g_object_unref (file_icon);
+
+					}
+
+					if (i == 0) {
+						gsearch->search_results_popup_submenu = gtk_menu_new ();
+
+						gtk_menu_set_reserve_toggle_size (GTK_MENU (gsearch->search_results_popup_submenu), FALSE);
+
+						/* Popup menu item: Open With */
+					  	new2 = mate_image_menu_item_new_from_icon (NULL, _("Open Wit_h"));
+				  		gtk_widget_show (new2);
+					 	gtk_container_add (GTK_CONTAINER (gsearch->search_results_popup_menu), new2);
+
+		  			  	gtk_menu_item_set_submenu (GTK_MENU_ITEM (new2), gsearch->search_results_popup_submenu);
+		                       	}
+					gtk_container_add (GTK_CONTAINER (gsearch->search_results_popup_submenu), new1);
+
+					/* For submenu items, the "activate" signal is only emitted if the user first clicks
+					   on the parent menu item.  Since submenus in gtk+ are automatically displayed when
+					   the user hovers over them, most will never click on the parent menu item.
+					   The work-around is to connect to "button-press-event". */
+					g_signal_connect (new1, "button-press-event",
+					                  G_CALLBACK (open_file_event_cb),
+					                  (gpointer) gsearch);
+				}
+				else {
+					if (g_app_info_get_icon ((GAppInfo *)list->data) != NULL) {
+
+						file_icon = g_object_ref (g_app_info_get_icon ((GAppInfo *)list->data));
+
+						if (file_icon == NULL) {
+							file_icon = g_themed_icon_new ("gtk-open");
+						}
+
+						icon_done = TRUE;
+						new1 = mate_image_menu_item_new_from_gicon (file_icon, str);
+						g_object_unref (file_icon);
+					}
+					gtk_container_add (GTK_CONTAINER (gsearch->search_results_popup_menu), new1);
+					g_signal_connect ((gpointer) new1, "activate", G_CALLBACK (open_file_cb),
+					                  (gpointer) gsearch);
+				}
+				if (icon_done == FALSE)
+					new1 = mate_image_menu_item_new_from_icon (NULL, str);
+				g_free (str);
+				gtk_widget_show (new1);
+
+				g_object_set_data_full (G_OBJECT (new1), "app", (GAppInfo *)list->data,
+			                                g_object_unref);
+			}
+
+			if (list_length >= 2) {
+				separatormenuitem1 = gtk_separator_menu_item_new ();
+				gtk_container_add (GTK_CONTAINER (gsearch->search_results_popup_menu), separatormenuitem1);
+				gtk_widget_show (separatormenuitem1);
+			}
+		}
+	}
+
+	/* Popup menu item: Open Containing Folder */
+	new1 = mate_image_menu_item_new_from_icon ("document-open", _("Open Containing _Folder"));
+	gtk_container_add (GTK_CONTAINER (gsearch->search_results_popup_menu), new1);
+	gtk_widget_show (new1);
+
+	g_signal_connect (new1, "activate",
+	                  G_CALLBACK (open_folder_cb),
+	                  (gpointer) gsearch);
+
+	/* Popup menu item: Copy Path */
+	if (gtk_tree_selection_count_selected_rows (GTK_TREE_SELECTION (gsearch->search_results_selection)) == 1) {
+		new1 = mate_image_menu_item_new_from_icon ("edit-copy", _("Copy _Path"));
+		gtk_container_add (GTK_CONTAINER (gsearch->search_results_popup_menu), new1);
+		gtk_widget_show (new1);
+
+		g_signal_connect (new1, "activate",
+		                  G_CALLBACK (copy_path_cb),
+		                  (gpointer) gsearch);
+	}
+
+	/* Popup menu item: Move to Trash */
+	separatormenuitem1 = gtk_separator_menu_item_new ();
+	gtk_container_add (GTK_CONTAINER (gsearch->search_results_popup_menu), separatormenuitem1);
+	gtk_widget_show (separatormenuitem1);
+
+	GtkIconTheme *icon_theme;
+	GdkPixbuf *pixbuf;
+	icon_theme = gtk_icon_theme_get_default ();
+	pixbuf = gtk_icon_theme_load_icon (icon_theme, "user-trash", GTK_ICON_SIZE_MENU, 0, NULL);
+
+	new1 = mate_image_menu_item_new_from_pixbuf (pixbuf, _("Mo_ve to Trash"));
+	gtk_container_add (GTK_CONTAINER (gsearch->search_results_popup_menu), new1);
+	gtk_widget_show (new1);
+
+	g_signal_connect (new1, "activate",
+	                  G_CALLBACK (move_to_trash_cb),
+	                  (gpointer) gsearch);
+
+	/* Popup menu item: Save Results As... */
+	separatormenuitem1 = gtk_separator_menu_item_new ();
+	gtk_container_add (GTK_CONTAINER (gsearch->search_results_popup_menu), separatormenuitem1);
+	gtk_widget_show (separatormenuitem1);
+
+	gsearch->search_results_save_results_as_item = mate_image_menu_item_new_from_icon  ("document-save", _("_Save Results As..."));
+	gtk_container_add (GTK_CONTAINER (gsearch->search_results_popup_menu), gsearch->search_results_save_results_as_item);
+	gtk_widget_show (gsearch->search_results_save_results_as_item);
+
+	if (gsearch->command_details->command_status == RUNNING) {
+		gtk_widget_set_sensitive (gsearch->search_results_save_results_as_item, FALSE);
+	}
+
+	g_signal_connect (gsearch->search_results_save_results_as_item, "activate",
+	                  G_CALLBACK (show_file_selector_cb),
+	                  (gpointer) gsearch);
+}
+
+gboolean
+file_button_release_event_cb (GtkWidget * widget,
+                              GdkEventButton * event,
+                              gpointer data)
+{
+	GSearchWindow * gsearch = data;
+
+	if (event->window != gtk_tree_view_get_bin_window (GTK_TREE_VIEW (gsearch->search_results_tree_view))) {
+		return FALSE;
+	}
+
+	if (event->button == 1 || event->button == 2) {
+		GtkTreePath *path;
+
+		if (gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (gsearch->search_results_tree_view), event->x, event->y,
+		                                   &path, NULL, NULL, NULL)) {
+			if ((event->state & GDK_SHIFT_MASK) || (event->state & GDK_CONTROL_MASK)) {
+				if (row_selected_by_button_press_event) {
+					gtk_tree_selection_select_path (gtk_tree_view_get_selection (GTK_TREE_VIEW(gsearch->search_results_tree_view)), path);
+				}
+				else {
+					gtk_tree_selection_unselect_path (gtk_tree_view_get_selection (GTK_TREE_VIEW(gsearch->search_results_tree_view)), path);
+				}
+			}
+			else {
+				if (gsearch->is_search_results_single_click_to_activate == FALSE) {
+					gtk_tree_selection_unselect_all (gtk_tree_view_get_selection (GTK_TREE_VIEW(gsearch->search_results_tree_view)));
+				}
+				gtk_tree_selection_select_path (gtk_tree_view_get_selection (GTK_TREE_VIEW(gsearch->search_results_tree_view)), path);
+			}
+		}
+		gtk_tree_path_free (path);
+	}
+
+	if (gtk_tree_selection_count_selected_rows (GTK_TREE_SELECTION (gsearch->search_results_selection)) == 0) {
+		return FALSE;
+	}
+
+	if (event->button == 3) {
+		gboolean no_files_found = FALSE;
+		GtkTreeModel * model;
+		GtkTreeIter iter;
+		GList * list;
+		gchar * utf8_name_first;
+		gchar * locale_file_first;
+
+		list = gtk_tree_selection_get_selected_rows (GTK_TREE_SELECTION (gsearch->search_results_selection),
+		                                             &model);
+
+		gtk_tree_model_get_iter (GTK_TREE_MODEL (gsearch->search_results_list_store), &iter,
+		                         g_list_first (list)->data);
+
+		gtk_tree_model_get (GTK_TREE_MODEL (gsearch->search_results_list_store), &iter,
+		                    COLUMN_NAME, &utf8_name_first,
+				    COLUMN_LOCALE_FILE, &locale_file_first,
+			    	    COLUMN_NO_FILES_FOUND, &no_files_found,
+			   	    -1);
+
+		if (!no_files_found) {
+
+			gboolean show_app_list = TRUE;
+			GAppInfo * first_app_info = NULL;
+			GTimer * timer;
+			GList * tmp;
+			gchar * locale_file_tmp;
+			gchar * file = NULL;
+			gint idx;
+
+			timer = g_timer_new ();
+			g_timer_start (timer);
+
+			if (g_list_length (list) >= 2) {
+
+				/* Verify the selected files each have the same default handler. */
+				for (tmp = g_list_first (list), idx = 0; tmp != NULL; tmp = g_list_next (tmp), idx++) {
+
+					GFile * g_file;
+					GAppInfo * app_info;
+
+					gtk_tree_model_get_iter (GTK_TREE_MODEL (gsearch->search_results_list_store), &iter,
+					                         tmp->data);
+
+					gtk_tree_model_get (GTK_TREE_MODEL (gsearch->search_results_list_store), &iter,
+							    COLUMN_LOCALE_FILE, &locale_file_tmp,
+					                    -1);
+
+					g_file = g_file_new_for_path (locale_file_tmp);
+					app_info = g_file_query_default_handler (g_file, NULL, NULL);
+
+					if (G_IS_APP_INFO (app_info) == FALSE) {
+						show_app_list = FALSE;
+					}
+					else {
+						if (idx == 0) {
+							first_app_info = g_app_info_dup (app_info);
+							g_object_unref (app_info);
+							continue;
+						}
+
+						show_app_list = g_app_info_equal (app_info, first_app_info);
+						g_object_unref (app_info);
+
+						/* Break out, if more that 1.5 seconds have passed */
+						if (g_timer_elapsed (timer, NULL) > 1.50) {
+							show_app_list = FALSE;
+						}
+					}
+					g_object_unref (g_file);
+					g_free (locale_file_tmp);
+
+					if (show_app_list == FALSE) {
+						break;
+					}
+				}
+				g_timer_destroy (timer);
+				if (first_app_info != NULL) {
+					g_object_unref (first_app_info);
+				}
+			}
+
+			file = g_strdup (((show_app_list == TRUE) ? locale_file_first : NULL));
+
+			build_popup_menu_for_file (gsearch, file);
+			gtk_menu_popup_at_pointer (GTK_MENU (gsearch->search_results_popup_menu),
+			                           (const GdkEvent*) event);
+			g_free (file);
+
+		}
+		g_free (locale_file_first);
+		g_free (utf8_name_first);
+		g_list_free_full (list, (GDestroyNotify) gtk_tree_path_free);
+	}
+	else if (event->button == 1 || event->button == 2) {
+		if (gsearch->is_search_results_single_click_to_activate == TRUE) {
+			if (!(event->state & GDK_CONTROL_MASK) && !(event->state & GDK_SHIFT_MASK)) {
+			     	open_file_cb ((GtkMenuItem *) NULL, data);
+			}
+		}
+	}
+	return FALSE;
+}
+
+gboolean
+file_event_after_cb  (GtkWidget * widget,
+                      GdkEventButton * event,
+                      gpointer data)
+{
+	GSearchWindow * gsearch = data;
+
+	if (event->window != gtk_tree_view_get_bin_window (GTK_TREE_VIEW (gsearch->search_results_tree_view))) {
+		return FALSE;
+	}
+
+	if (gtk_tree_selection_count_selected_rows (GTK_TREE_SELECTION (gsearch->search_results_selection)) == 0) {
+		return FALSE;
+	}
+
+	if (!(event->state & GDK_CONTROL_MASK) && !(event->state & GDK_SHIFT_MASK)) {
+		if (gsearch->is_search_results_single_click_to_activate == FALSE) {
+			if (event->type == GDK_2BUTTON_PRESS) {
+				open_file_cb ((GtkMenuItem *) NULL, data);
+				return TRUE;
+			}
+		}
+	}
+	return FALSE;
+}
+
+gboolean
+file_motion_notify_cb (GtkWidget *widget,
+                       GdkEventMotion *event,
+                       gpointer user_data)
+{
+	GSearchWindow * gsearch = user_data;
+	GdkDisplay *display;
+	GdkCursor * cursor;
+	GtkTreePath * last_hover_path;
+	GtkTreeIter iter;
+
+	display = gtk_widget_get_display (GTK_WIDGET (user_data));
+
+	if (gsearch->is_search_results_single_click_to_activate == FALSE) {
+		return FALSE;
+	}
+
+	if (event->window != gtk_tree_view_get_bin_window (GTK_TREE_VIEW (gsearch->search_results_tree_view))) {
+                return FALSE;
+	}
+
+	last_hover_path = gsearch->search_results_hover_path;
+
+	gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (widget),
+				       event->x, event->y,
+				       &gsearch->search_results_hover_path,
+				       NULL, NULL, NULL);
+
+	if (gsearch->search_results_hover_path != NULL) {
+		cursor = gdk_cursor_new_for_display (display, GDK_HAND2);
+	}
+	else {
+		cursor = NULL;
+	}
+
+	gdk_window_set_cursor (event->window, cursor);
+
+	/* Redraw if the hover row has changed */
+	if (!(last_hover_path == NULL && gsearch->search_results_hover_path == NULL) &&
+	    (!(last_hover_path != NULL && gsearch->search_results_hover_path != NULL) ||
+	     gtk_tree_path_compare (last_hover_path, gsearch->search_results_hover_path))) {
+		if (last_hover_path) {
+			gtk_tree_model_get_iter (GTK_TREE_MODEL (gsearch->search_results_list_store),
+			                         &iter, last_hover_path);
+			gtk_tree_model_row_changed (GTK_TREE_MODEL (gsearch->search_results_list_store),
+			                            last_hover_path, &iter);
+		}
+
+		if (gsearch->search_results_hover_path) {
+			gtk_tree_model_get_iter (GTK_TREE_MODEL (gsearch->search_results_list_store),
+			                         &iter, gsearch->search_results_hover_path);
+			gtk_tree_model_row_changed (GTK_TREE_MODEL (gsearch->search_results_list_store),
+			                            gsearch->search_results_hover_path, &iter);
+		}
+	}
+
+	gtk_tree_path_free (last_hover_path);
+
+ 	return FALSE;
+}
+
+gboolean
+file_leave_notify_cb (GtkWidget *widget,
+                      GdkEventCrossing *event,
+                      gpointer user_data)
+{
+        GSearchWindow * gsearch = user_data;
+	GtkTreeIter iter;
+
+	if (gsearch->is_search_results_single_click_to_activate && (gsearch->search_results_hover_path != NULL)) {
+		gtk_tree_model_get_iter (GTK_TREE_MODEL (gsearch->search_results_list_store),
+		                         &iter,
+		                         gsearch->search_results_hover_path);
+		gtk_tree_model_row_changed (GTK_TREE_MODEL (gsearch->search_results_list_store),
+		                            gsearch->search_results_hover_path,
+		                            &iter);
+
+		gtk_tree_path_free (gsearch->search_results_hover_path);
+		gsearch->search_results_hover_path = NULL;
+
+		return TRUE;
+	}
+
+	return FALSE;
+}
+
+void
+drag_begin_file_cb (GtkWidget * widget,
+                    GdkDragContext * context,
+                    gpointer data)
+{
+	GSearchWindow * gsearch = data;
+	gint number_of_selected_rows;
+
+	number_of_selected_rows = gtk_tree_selection_count_selected_rows (GTK_TREE_SELECTION (gsearch->search_results_selection));
+
+	if (number_of_selected_rows > 1) {
+		gtk_drag_set_icon_name (context, "gtk-dnd-multiple", 0, 0);
+	}
+	else if (number_of_selected_rows == 1) {
+		GdkPixbuf * pixbuf;
+		GtkTreeModel * model;
+		GtkTreeIter iter;
+		GList * list;
+
+		list = gtk_tree_selection_get_selected_rows (GTK_TREE_SELECTION (gsearch->search_results_selection),
+		                                             &model);
+
+		gtk_tree_model_get_iter (GTK_TREE_MODEL (gsearch->search_results_list_store), &iter,
+		                         g_list_first (list)->data);
+
+		gtk_tree_model_get (GTK_TREE_MODEL (gsearch->search_results_list_store), &iter,
+		                    COLUMN_ICON, &pixbuf,
+		                    -1);
+		g_list_free_full (list, (GDestroyNotify) gtk_tree_path_free);
+
+		if (pixbuf) {
+			gtk_drag_set_icon_pixbuf (context, pixbuf, 0, 0);
+		}
+		else {
+			gtk_drag_set_icon_name (context, "gtk-dnd", 0, 0);
+		}
+	}
+}
+
+void
+drag_file_cb  (GtkWidget * widget,
+               GdkDragContext * context,
+               GtkSelectionData * selection_data,
+               guint info,
+               guint drag_time,
+               gpointer data)
+{
+	GSearchWindow * gsearch = data;
+	gchar * uri_list = NULL;
+	GList * list;
+	GtkTreeModel * model;
+	GtkTreeIter iter;
+	guint idx;
+
+	if (gtk_tree_selection_count_selected_rows (GTK_TREE_SELECTION (gsearch->search_results_selection)) == 0) {
+		return;
+	}
+
+	list = gtk_tree_selection_get_selected_rows (GTK_TREE_SELECTION (gsearch->search_results_selection),
+                                                     &model);
+
+	for (idx = 0; idx < g_list_length (list); idx++) {
+
+		gboolean no_files_found = FALSE;
+		gchar * utf8_name;
+		gchar * locale_file;
+
+		gtk_tree_model_get_iter (GTK_TREE_MODEL (gsearch->search_results_list_store), &iter,
+		                         g_list_nth_data (list, idx));
+
+		gtk_tree_model_get (GTK_TREE_MODEL (gsearch->search_results_list_store), &iter,
+		                    COLUMN_NAME, &utf8_name,
+		                    COLUMN_LOCALE_FILE, &locale_file,
+		                    COLUMN_NO_FILES_FOUND, &no_files_found,
+		                    -1);
+
+		if (!no_files_found) {
+			gchar * tmp_uri = g_filename_to_uri (locale_file, NULL, NULL);
+
+			if (uri_list == NULL) {
+				uri_list = g_strdup (tmp_uri);
+			}
+			else {
+				uri_list = g_strconcat (uri_list, "\n", tmp_uri, NULL);
+			}
+			gtk_selection_data_set (selection_data,
+			                        gtk_selection_data_get_target (selection_data),
+			                        8,
+			                        (guchar *) uri_list,
+			                        strlen (uri_list));
+			g_free (tmp_uri);
+		}
+		else {
+			gtk_selection_data_set_text (selection_data, utf8_name, -1);
+		}
+		g_free (utf8_name);
+		g_free (locale_file);
+	}
+	g_list_free_full (list, (GDestroyNotify) gtk_tree_path_free);
+	g_free (uri_list);
+}
+
+void
+show_file_selector_cb (GtkAction * action,
+                       gpointer data)
+{
+	GSearchWindow * gsearch = data;
+	GtkWidget * file_chooser;
+
+	file_chooser = gtk_file_chooser_dialog_new (_("Save Search Results As..."),
+	                                            GTK_WINDOW (gsearch->window),
+	                                            GTK_FILE_CHOOSER_ACTION_SAVE,
+	                                            "gtk-cancel", GTK_RESPONSE_CANCEL,
+	                                            "gtk-save", GTK_RESPONSE_OK,
+	                                            NULL);
+
+	gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (file_chooser), TRUE);
+	if (gsearch->save_results_as_default_filename != NULL) {
+		gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (file_chooser),
+		                               gsearch->save_results_as_default_filename);
+	}
+
+	g_signal_connect (file_chooser, "response",
+			  G_CALLBACK (save_results_cb), gsearch);
+
+	gtk_window_set_modal (GTK_WINDOW (file_chooser), TRUE);
+	gtk_window_set_position (GTK_WINDOW (file_chooser), GTK_WIN_POS_CENTER_ON_PARENT);
+
+	gtk_widget_show (GTK_WIDGET (file_chooser));
+}
+
+static void
+display_dialog_could_not_save_no_name (GtkWidget * window)
+{
+	GtkWidget * dialog;
+	gchar * primary;
+	gchar * secondary;
+
+	primary = g_strdup (_("Could not save document."));
+	secondary = g_strdup (_("You did not select a document name."));
+
+	dialog = gtk_message_dialog_new (GTK_WINDOW (window),
+	                                 GTK_DIALOG_DESTROY_WITH_PARENT,
+	                                 GTK_MESSAGE_ERROR,
+	                                 GTK_BUTTONS_OK,
+	                                 primary, NULL);
+	gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+	                                          secondary, NULL);
+
+	gtk_window_set_title (GTK_WINDOW (dialog), "");
+	gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
+	gtk_box_set_spacing (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), 14);
+
+	g_signal_connect (dialog, "response",
+	                  G_CALLBACK (gtk_widget_destroy),
+	                  NULL);
+	gtk_widget_show (dialog);
+	g_free (primary);
+	g_free (secondary);
+}
+
+static void
+display_dialog_could_not_save_to (GtkWidget * window,
+                                  const gchar * file,
+                                  const gchar * message)
+{
+	GtkWidget * dialog;
+	gchar * primary;
+
+	primary = g_strdup_printf (_("Could not save \"%s\" document to \"%s\"."),
+	                           g_path_get_basename (file),
+	                           g_path_get_dirname (file));
+
+	dialog = gtk_message_dialog_new (GTK_WINDOW (window),
+	                                 GTK_DIALOG_DESTROY_WITH_PARENT,
+	                                 GTK_MESSAGE_ERROR,
+	                                 GTK_BUTTONS_OK,
+	                                 primary, NULL);
+	gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+	                                          message, NULL);
+
+	gtk_window_set_title (GTK_WINDOW (dialog), "");
+	gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
+	gtk_box_set_spacing (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), 14);
+
+	g_signal_connect (dialog, "response",
+	                  G_CALLBACK (gtk_widget_destroy),
+	                  NULL);
+	gtk_widget_show (dialog);
+	g_free (primary);
+}
+
+static gint
+display_dialog_could_not_save_exists (GtkWidget * window,
+                                      const gchar * file)
+{
+	GtkWidget * dialog;
+	GtkWidget * button;
+	gchar * primary;
+	gchar * secondary;
+	gint response;
+
+	primary = g_strdup_printf (_("The document \"%s\" already exists.  "
+	                             "Would you like to replace it?"),
+	                           g_path_get_basename (file));
+
+	secondary = g_strdup (_("If you replace an existing file, "
+	                        "its contents will be overwritten."));
+
+	dialog = gtk_message_dialog_new (GTK_WINDOW (window),
+	                                 GTK_DIALOG_DESTROY_WITH_PARENT,
+	                                 GTK_MESSAGE_QUESTION,
+	                                 GTK_BUTTONS_CANCEL,
+	                                 "%s", primary);
+	gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+	                                          "%s", secondary);
+
+	gtk_window_set_title (GTK_WINDOW (dialog), "");
+	gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
+	gtk_box_set_spacing (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), 14);
+
+	button = gsearchtool_button_new_with_icon (_("_Replace"), "gtk-ok");
+	gtk_widget_set_can_default (button, TRUE);
+	gtk_widget_show (button);
+
+	gtk_dialog_add_action_widget (GTK_DIALOG (dialog), button, GTK_RESPONSE_OK);
+	gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
+
+	response = gtk_dialog_run (GTK_DIALOG (dialog));
+
+	gtk_widget_destroy (GTK_WIDGET(dialog));
+	g_free (primary);
+	g_free (secondary);
+
+	return response;
+}
+
+void
+save_results_cb (GtkWidget * chooser,
+                 gint response,<--- Shadowed declaration
+                 gpointer data)
+{
+	GSearchWindow * gsearch = data;
+	GtkListStore * store;
+	GtkTreeIter iter;
+	FILE * fp;
+	gchar * utf8 = NULL;
+
+	if (response != GTK_RESPONSE_OK) {
+		gtk_widget_destroy (GTK_WIDGET (chooser));
+		return;
+	}
+
+	store = gsearch->search_results_list_store;
+	g_free (gsearch->save_results_as_default_filename);
+
+	gsearch->save_results_as_default_filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (chooser));
+	gtk_widget_destroy (chooser);
+
+	if (gsearch->save_results_as_default_filename != NULL) {
+		utf8 = g_filename_to_utf8 (gsearch->save_results_as_default_filename, -1, NULL, NULL, NULL);
+	}
+
+	if (utf8 == NULL) {
+		display_dialog_could_not_save_no_name (gsearch->window);
+		return;
+	}
+
+	if (g_file_test (gsearch->save_results_as_default_filename, G_FILE_TEST_IS_DIR)) {
+		display_dialog_could_not_save_to (gsearch->window, utf8,
+		                                  _("The document name you selected is a folder."));
+		g_free (utf8);
+		return;
+	}
+
+	if (g_file_test (gsearch->save_results_as_default_filename, G_FILE_TEST_EXISTS)) {
+
+		gint response;<--- Shadow variable
+
+		response = display_dialog_could_not_save_exists (gsearch->window, utf8);
+
+		if (response != GTK_RESPONSE_OK) {
+			g_free (utf8);
+			return;
+		}
+	}
+
+	if ((fp = fopen (gsearch->save_results_as_default_filename, "w")) != NULL) {
+
+		gint idx;
+
+		for (idx = 0; idx < gtk_tree_model_iter_n_children (GTK_TREE_MODEL (store), NULL); idx++)
+		{
+			if (gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (store), &iter, NULL, idx) == TRUE) {
+
+				gchar * locale_file;
+
+				gtk_tree_model_get (GTK_TREE_MODEL (store), &iter, COLUMN_LOCALE_FILE, &locale_file, -1);
+				fprintf (fp, "%s\n", locale_file);
+				g_free (locale_file);
+			}
+		}
+		fclose (fp);
+	}
+	else {
+		display_dialog_could_not_save_to (gsearch->window, utf8,
+		                                  _("You may not have write permissions to the document."));
+	}
+	g_free (utf8);
+}
+
+void
+save_session_cb (EggSMClient * client,
+                 GKeyFile * state_file,
+                 gpointer client_data)
+{
+	GSearchWindow * gsearch = client_data;
+	char ** argv;
+	int argc;
+
+	set_clone_command (gsearch, &argc, &argv, "mate-search-tool", FALSE);
+	egg_sm_client_set_restart_command (client, argc, (const char **) argv);
+}
+
+gboolean
+key_press_cb (GtkWidget * widget,
+              GdkEventKey * event,
+              gpointer data)
+{
+	GSearchWindow * gsearch = data;
+
+	g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
+
+	if (event->keyval == GDK_KEY_Escape) {
+		if (gsearch->command_details->command_status == RUNNING) {
+			click_stop_cb (widget, data);
+		}
+		else if (gsearch->command_details->is_command_timeout_enabled == FALSE) {
+			quit_cb (widget, (GdkEvent *) NULL, data);
+		}
+	}
+	else if (event->keyval == GDK_KEY_F10) {
+		if (event->state & GDK_SHIFT_MASK) {
+			gboolean no_files_found = FALSE;
+			GtkTreeModel * model;
+			GtkTreeIter iter;
+			GList * list;
+
+			if (gtk_tree_selection_count_selected_rows (GTK_TREE_SELECTION (gsearch->search_results_selection)) == 0) {
+				return FALSE;
+			}
+
+			list = gtk_tree_selection_get_selected_rows (GTK_TREE_SELECTION (gsearch->search_results_selection),
+			                                             &model);
+
+			gtk_tree_model_get_iter (GTK_TREE_MODEL (gsearch->search_results_list_store), &iter,
+						 g_list_first (list)->data);
+
+			gtk_tree_model_get (GTK_TREE_MODEL (gsearch->search_results_list_store), &iter,
+					    COLUMN_NO_FILES_FOUND, &no_files_found, -1);
+
+			g_list_free_full (list, (GDestroyNotify) gtk_tree_path_free);
+
+			if (!no_files_found) {
+				gtk_menu_popup_at_pointer (GTK_MENU (gsearch->search_results_popup_menu),
+				                           (const GdkEvent*) event);
+				return TRUE;
+			}
+		}
+	}
+	return FALSE;
+}
+
+gboolean
+not_running_timeout_cb (gpointer data)
+{
+	GSearchWindow * gsearch = data;
+
+	gsearch->command_details->is_command_timeout_enabled = FALSE;
+	return FALSE;
+}
+
+void
+disable_quick_search_cb (GtkWidget * dialog,
+                         gint response,
+                         gpointer data)
+{
+	GSearchWindow * gsearch = data;
+
+	gtk_widget_destroy (GTK_WIDGET (dialog));
+
+	if (response == GTK_RESPONSE_OK) {
+		g_settings_set_boolean (gsearch->mate_search_tool_settings, "disable-quick-search", TRUE);
+	}
+}
+
+void
+single_click_to_activate_key_changed_cb (GSettings * settings,
+                                         gchar * key,
+                                         gpointer user_data)
+{
+	GSearchWindow * gsearch = user_data;
+	gchar * value;
+
+	value = g_settings_get_string (settings, key);
+
+	gsearch->is_search_results_single_click_to_activate =
+		(strncmp (value, "single", 6) == 0) ? TRUE : FALSE;
+
+	g_free (value);
+}
+
+void
+columns_changed_cb (GtkTreeView * treeview,
+                    gpointer user_data)
+{
+	GVariantBuilder array_builder;
+	GSearchWindow * gsearch = user_data;
+	GSList * order;
+	GSList * iter;
+
+	order = gsearchtool_get_columns_order (treeview);
+
+	g_variant_builder_init (&array_builder, G_VARIANT_TYPE ("ai"));
+	for (iter = order; iter; iter = iter->next)
+		g_variant_builder_add (&array_builder, "i", GPOINTER_TO_INT (iter->data));
+
+	if (g_slist_length (order) == NUM_VISIBLE_COLUMNS) {
+		g_settings_set_value (gsearch->mate_search_tool_settings, "columns-order", g_variant_new ("ai", &array_builder));
+	}
+	g_slist_free (order);
+}
+
+gboolean
+window_state_event_cb (GtkWidget * widget,
+                       GdkEventWindowState * event,
+                       gpointer data)
+{
+	GSearchWindow * gsearch = data;
+
+	if (event->new_window_state & GDK_WINDOW_STATE_MAXIMIZED) {
+		gsearch->is_window_maximized = TRUE;
+	}
+	else {
+		gsearch->is_window_maximized = FALSE;
+	}
+	return FALSE;
+}
+
+ +
+ +
+ + diff --git a/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/15.html b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/15.html new file mode 100644 index 00000000..faca307b --- /dev/null +++ b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/15.html @@ -0,0 +1,3133 @@ + + + + + + Cppcheck - HTML report - mate-utils + + + + + +
+ + + +
+
   1
+   2
+   3
+   4
+   5
+   6
+   7
+   8
+   9
+  10
+  11
+  12
+  13
+  14
+  15
+  16
+  17
+  18
+  19
+  20
+  21
+  22
+  23
+  24
+  25
+  26
+  27
+  28
+  29
+  30
+  31
+  32
+  33
+  34
+  35
+  36
+  37
+  38
+  39
+  40
+  41
+  42
+  43
+  44
+  45
+  46
+  47
+  48
+  49
+  50
+  51
+  52
+  53
+  54
+  55
+  56
+  57
+  58
+  59
+  60
+  61
+  62
+  63
+  64
+  65
+  66
+  67
+  68
+  69
+  70
+  71
+  72
+  73
+  74
+  75
+  76
+  77
+  78
+  79
+  80
+  81
+  82
+  83
+  84
+  85
+  86
+  87
+  88
+  89
+  90
+  91
+  92
+  93
+  94
+  95
+  96
+  97
+  98
+  99
+ 100
+ 101
+ 102
+ 103
+ 104
+ 105
+ 106
+ 107
+ 108
+ 109
+ 110
+ 111
+ 112
+ 113
+ 114
+ 115
+ 116
+ 117
+ 118
+ 119
+ 120
+ 121
+ 122
+ 123
+ 124
+ 125
+ 126
+ 127
+ 128
+ 129
+ 130
+ 131
+ 132
+ 133
+ 134
+ 135
+ 136
+ 137
+ 138
+ 139
+ 140
+ 141
+ 142
+ 143
+ 144
+ 145
+ 146
+ 147
+ 148
+ 149
+ 150
+ 151
+ 152
+ 153
+ 154
+ 155
+ 156
+ 157
+ 158
+ 159
+ 160
+ 161
+ 162
+ 163
+ 164
+ 165
+ 166
+ 167
+ 168
+ 169
+ 170
+ 171
+ 172
+ 173
+ 174
+ 175
+ 176
+ 177
+ 178
+ 179
+ 180
+ 181
+ 182
+ 183
+ 184
+ 185
+ 186
+ 187
+ 188
+ 189
+ 190
+ 191
+ 192
+ 193
+ 194
+ 195
+ 196
+ 197
+ 198
+ 199
+ 200
+ 201
+ 202
+ 203
+ 204
+ 205
+ 206
+ 207
+ 208
+ 209
+ 210
+ 211
+ 212
+ 213
+ 214
+ 215
+ 216
+ 217
+ 218
+ 219
+ 220
+ 221
+ 222
+ 223
+ 224
+ 225
+ 226
+ 227
+ 228
+ 229
+ 230
+ 231
+ 232
+ 233
+ 234
+ 235
+ 236
+ 237
+ 238
+ 239
+ 240
+ 241
+ 242
+ 243
+ 244
+ 245
+ 246
+ 247
+ 248
+ 249
+ 250
+ 251
+ 252
+ 253
+ 254
+ 255
+ 256
+ 257
+ 258
+ 259
+ 260
+ 261
+ 262
+ 263
+ 264
+ 265
+ 266
+ 267
+ 268
+ 269
+ 270
+ 271
+ 272
+ 273
+ 274
+ 275
+ 276
+ 277
+ 278
+ 279
+ 280
+ 281
+ 282
+ 283
+ 284
+ 285
+ 286
+ 287
+ 288
+ 289
+ 290
+ 291
+ 292
+ 293
+ 294
+ 295
+ 296
+ 297
+ 298
+ 299
+ 300
+ 301
+ 302
+ 303
+ 304
+ 305
+ 306
+ 307
+ 308
+ 309
+ 310
+ 311
+ 312
+ 313
+ 314
+ 315
+ 316
+ 317
+ 318
+ 319
+ 320
+ 321
+ 322
+ 323
+ 324
+ 325
+ 326
+ 327
+ 328
+ 329
+ 330
+ 331
+ 332
+ 333
+ 334
+ 335
+ 336
+ 337
+ 338
+ 339
+ 340
+ 341
+ 342
+ 343
+ 344
+ 345
+ 346
+ 347
+ 348
+ 349
+ 350
+ 351
+ 352
+ 353
+ 354
+ 355
+ 356
+ 357
+ 358
+ 359
+ 360
+ 361
+ 362
+ 363
+ 364
+ 365
+ 366
+ 367
+ 368
+ 369
+ 370
+ 371
+ 372
+ 373
+ 374
+ 375
+ 376
+ 377
+ 378
+ 379
+ 380
+ 381
+ 382
+ 383
+ 384
+ 385
+ 386
+ 387
+ 388
+ 389
+ 390
+ 391
+ 392
+ 393
+ 394
+ 395
+ 396
+ 397
+ 398
+ 399
+ 400
+ 401
+ 402
+ 403
+ 404
+ 405
+ 406
+ 407
+ 408
+ 409
+ 410
+ 411
+ 412
+ 413
+ 414
+ 415
+ 416
+ 417
+ 418
+ 419
+ 420
+ 421
+ 422
+ 423
+ 424
+ 425
+ 426
+ 427
+ 428
+ 429
+ 430
+ 431
+ 432
+ 433
+ 434
+ 435
+ 436
+ 437
+ 438
+ 439
+ 440
+ 441
+ 442
+ 443
+ 444
+ 445
+ 446
+ 447
+ 448
+ 449
+ 450
+ 451
+ 452
+ 453
+ 454
+ 455
+ 456
+ 457
+ 458
+ 459
+ 460
+ 461
+ 462
+ 463
+ 464
+ 465
+ 466
+ 467
+ 468
+ 469
+ 470
+ 471
+ 472
+ 473
+ 474
+ 475
+ 476
+ 477
+ 478
+ 479
+ 480
+ 481
+ 482
+ 483
+ 484
+ 485
+ 486
+ 487
+ 488
+ 489
+ 490
+ 491
+ 492
+ 493
+ 494
+ 495
+ 496
+ 497
+ 498
+ 499
+ 500
+ 501
+ 502
+ 503
+ 504
+ 505
+ 506
+ 507
+ 508
+ 509
+ 510
+ 511
+ 512
+ 513
+ 514
+ 515
+ 516
+ 517
+ 518
+ 519
+ 520
+ 521
+ 522
+ 523
+ 524
+ 525
+ 526
+ 527
+ 528
+ 529
+ 530
+ 531
+ 532
+ 533
+ 534
+ 535
+ 536
+ 537
+ 538
+ 539
+ 540
+ 541
+ 542
+ 543
+ 544
+ 545
+ 546
+ 547
+ 548
+ 549
+ 550
+ 551
+ 552
+ 553
+ 554
+ 555
+ 556
+ 557
+ 558
+ 559
+ 560
+ 561
+ 562
+ 563
+ 564
+ 565
+ 566
+ 567
+ 568
+ 569
+ 570
+ 571
+ 572
+ 573
+ 574
+ 575
+ 576
+ 577
+ 578
+ 579
+ 580
+ 581
+ 582
+ 583
+ 584
+ 585
+ 586
+ 587
+ 588
+ 589
+ 590
+ 591
+ 592
+ 593
+ 594
+ 595
+ 596
+ 597
+ 598
+ 599
+ 600
+ 601
+ 602
+ 603
+ 604
+ 605
+ 606
+ 607
+ 608
+ 609
+ 610
+ 611
+ 612
+ 613
+ 614
+ 615
+ 616
+ 617
+ 618
+ 619
+ 620
+ 621
+ 622
+ 623
+ 624
+ 625
+ 626
+ 627
+ 628
+ 629
+ 630
+ 631
+ 632
+ 633
+ 634
+ 635
+ 636
+ 637
+ 638
+ 639
+ 640
+ 641
+ 642
+ 643
+ 644
+ 645
+ 646
+ 647
+ 648
+ 649
+ 650
+ 651
+ 652
+ 653
+ 654
+ 655
+ 656
+ 657
+ 658
+ 659
+ 660
+ 661
+ 662
+ 663
+ 664
+ 665
+ 666
+ 667
+ 668
+ 669
+ 670
+ 671
+ 672
+ 673
+ 674
+ 675
+ 676
+ 677
+ 678
+ 679
+ 680
+ 681
+ 682
+ 683
+ 684
+ 685
+ 686
+ 687
+ 688
+ 689
+ 690
+ 691
+ 692
+ 693
+ 694
+ 695
+ 696
+ 697
+ 698
+ 699
+ 700
+ 701
+ 702
+ 703
+ 704
+ 705
+ 706
+ 707
+ 708
+ 709
+ 710
+ 711
+ 712
+ 713
+ 714
+ 715
+ 716
+ 717
+ 718
+ 719
+ 720
+ 721
+ 722
+ 723
+ 724
+ 725
+ 726
+ 727
+ 728
+ 729
+ 730
+ 731
+ 732
+ 733
+ 734
+ 735
+ 736
+ 737
+ 738
+ 739
+ 740
+ 741
+ 742
+ 743
+ 744
+ 745
+ 746
+ 747
+ 748
+ 749
+ 750
+ 751
+ 752
+ 753
+ 754
+ 755
+ 756
+ 757
+ 758
+ 759
+ 760
+ 761
+ 762
+ 763
+ 764
+ 765
+ 766
+ 767
+ 768
+ 769
+ 770
+ 771
+ 772
+ 773
+ 774
+ 775
+ 776
+ 777
+ 778
+ 779
+ 780
+ 781
+ 782
+ 783
+ 784
+ 785
+ 786
+ 787
+ 788
+ 789
+ 790
+ 791
+ 792
+ 793
+ 794
+ 795
+ 796
+ 797
+ 798
+ 799
+ 800
+ 801
+ 802
+ 803
+ 804
+ 805
+ 806
+ 807
+ 808
+ 809
+ 810
+ 811
+ 812
+ 813
+ 814
+ 815
+ 816
+ 817
+ 818
+ 819
+ 820
+ 821
+ 822
+ 823
+ 824
+ 825
+ 826
+ 827
+ 828
+ 829
+ 830
+ 831
+ 832
+ 833
+ 834
+ 835
+ 836
+ 837
+ 838
+ 839
+ 840
+ 841
+ 842
+ 843
+ 844
+ 845
+ 846
+ 847
+ 848
+ 849
+ 850
+ 851
+ 852
+ 853
+ 854
+ 855
+ 856
+ 857
+ 858
+ 859
+ 860
+ 861
+ 862
+ 863
+ 864
+ 865
+ 866
+ 867
+ 868
+ 869
+ 870
+ 871
+ 872
+ 873
+ 874
+ 875
+ 876
+ 877
+ 878
+ 879
+ 880
+ 881
+ 882
+ 883
+ 884
+ 885
+ 886
+ 887
+ 888
+ 889
+ 890
+ 891
+ 892
+ 893
+ 894
+ 895
+ 896
+ 897
+ 898
+ 899
+ 900
+ 901
+ 902
+ 903
+ 904
+ 905
+ 906
+ 907
+ 908
+ 909
+ 910
+ 911
+ 912
+ 913
+ 914
+ 915
+ 916
+ 917
+ 918
+ 919
+ 920
+ 921
+ 922
+ 923
+ 924
+ 925
+ 926
+ 927
+ 928
+ 929
+ 930
+ 931
+ 932
+ 933
+ 934
+ 935
+ 936
+ 937
+ 938
+ 939
+ 940
+ 941
+ 942
+ 943
+ 944
+ 945
+ 946
+ 947
+ 948
+ 949
+ 950
+ 951
+ 952
+ 953
+ 954
+ 955
+ 956
+ 957
+ 958
+ 959
+ 960
+ 961
+ 962
+ 963
+ 964
+ 965
+ 966
+ 967
+ 968
+ 969
+ 970
+ 971
+ 972
+ 973
+ 974
+ 975
+ 976
+ 977
+ 978
+ 979
+ 980
+ 981
+ 982
+ 983
+ 984
+ 985
+ 986
+ 987
+ 988
+ 989
+ 990
+ 991
+ 992
+ 993
+ 994
+ 995
+ 996
+ 997
+ 998
+ 999
+1000
+1001
+1002
+1003
+1004
+1005
+1006
+1007
+1008
+1009
+1010
+1011
+1012
+1013
+1014
+1015
+1016
+1017
+1018
+1019
+1020
+1021
+1022
+1023
+1024
+1025
+1026
+1027
+1028
+1029
+1030
+1031
+1032
+1033
+1034
+1035
+1036
+1037
+1038
+1039
+1040
+1041
+1042
+1043
+1044
+1045
+1046
+1047
+1048
+1049
+1050
+1051
+1052
+1053
+1054
+1055
+1056
+1057
+1058
+1059
+1060
+1061
+1062
+1063
+1064
+1065
+1066
+1067
+1068
+1069
+1070
+1071
+1072
+1073
+1074
+1075
+1076
+1077
+1078
+1079
+1080
+1081
+1082
+1083
+1084
+1085
+1086
+1087
+1088
+1089
+1090
+1091
+1092
+1093
+1094
+1095
+1096
+1097
+1098
+1099
+1100
+1101
+1102
+1103
+1104
+1105
+1106
+1107
+1108
+1109
+1110
+1111
+1112
+1113
+1114
+1115
+1116
+1117
+1118
+1119
+1120
+1121
+1122
+1123
+1124
+1125
+1126
+1127
+1128
+1129
+1130
+1131
+1132
+1133
+1134
+1135
+1136
+1137
+1138
+1139
+1140
+1141
+1142
+1143
+1144
+1145
+1146
+1147
+1148
+1149
+1150
+1151
+1152
+1153
+1154
+1155
+1156
+1157
+1158
+1159
+1160
+1161
+1162
+1163
+1164
+1165
+1166
+1167
+1168
+1169
+1170
+1171
+1172
+1173
+1174
+1175
+1176
+1177
+1178
+1179
+1180
+1181
+1182
+1183
+1184
+1185
+1186
+1187
+1188
+1189
+1190
+1191
+1192
+1193
+1194
+1195
+1196
+1197
+1198
+1199
+1200
+1201
+1202
+1203
+1204
+1205
+1206
+1207
+1208
+1209
+1210
+1211
+1212
+1213
+1214
+1215
+1216
+1217
+1218
+1219
+1220
+1221
+1222
+1223
+1224
+1225
+1226
+1227
+1228
+1229
+1230
+1231
+1232
+1233
+1234
+1235
+1236
+1237
+1238
+1239
+1240
+1241
+1242
+1243
+1244
+1245
+1246
+1247
+1248
+1249
+1250
+1251
+1252
+1253
+1254
+1255
+1256
+1257
+1258
+1259
+1260
+1261
+1262
+1263
+1264
+1265
+1266
+1267
+1268
+1269
+1270
+1271
+1272
+1273
+1274
+1275
+1276
+1277
+1278
+1279
+1280
+1281
+1282
+1283
+1284
+1285
+1286
+1287
+1288
+1289
+1290
+1291
+1292
+1293
+1294
+1295
+1296
+1297
+1298
+1299
+1300
+1301
+1302
+1303
+1304
+1305
+1306
+1307
+1308
+1309
+1310
+1311
+1312
+1313
+1314
+1315
+1316
+1317
+1318
+1319
+1320
+1321
+1322
+1323
+1324
+1325
+1326
+1327
+1328
+1329
+1330
+1331
+1332
+1333
+1334
+1335
+1336
+1337
+1338
+1339
+1340
+1341
+1342
+1343
+1344
+1345
+1346
+1347
+1348
+1349
+1350
+1351
+1352
+1353
+1354
+1355
+1356
+1357
+1358
+1359
+1360
+1361
+1362
+1363
+1364
+1365
+1366
+1367
+1368
+1369
+1370
+1371
+1372
+1373
+1374
+1375
+1376
+1377
+1378
+1379
+1380
+1381
+1382
+1383
+1384
+1385
+1386
+1387
+1388
+1389
+1390
+1391
+1392
+1393
+1394
+1395
+1396
+1397
+1398
+1399
+1400
+1401
+1402
+1403
+1404
+1405
+1406
+1407
+1408
+1409
+1410
+1411
+1412
+1413
+1414
+1415
+1416
+1417
+1418
+1419
+1420
+1421
+1422
+1423
+1424
+1425
+1426
+1427
+1428
+1429
+1430
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/* Copyright (C) 2002 the Free Software Foundation
+ * Copyright (C) 2012-2021 MATE Developers
+ *
+ * This file is part of MATE Utils.
+ *
+ * MATE Utils is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * MATE Utils is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MATE Utils.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ *  Authors:
+ *    Dennis Cranston <dennis_cranston@yahoo.com>
+ *    George Lebl
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#include <glib/gi18n.h>
+#include <glib.h>
+#include <regex.h>
+#include <stdlib.h>
+#include <gdk/gdkx.h>
+#include <gio/gio.h>
+#include <gio/gdesktopappinfo.h>
+
+#include "gsearchtool.h"
+#include "gsearchtool-callbacks.h"
+#include "gsearchtool-support.h"
+
+#define C_STANDARD_STRFTIME_CHARACTERS "aAbBcdHIjmMpSUwWxXyYZ"
+#define C_STANDARD_NUMERIC_STRFTIME_CHARACTERS "dHIjmMSUwWyY"
+#define SUS_EXTENDED_STRFTIME_MODIFIERS "EO"
+#define BINARY_EXEC_MIME_TYPE      "application/x-executable"
+
+GtkTreeViewColumn *
+gsearchtool_gtk_tree_view_get_column_with_sort_column_id (GtkTreeView * treeview,
+                                                          gint id);
+
+/* START OF GENERIC MATE-SEARCH-TOOL FUNCTIONS */
+
+gboolean
+is_path_hidden (const gchar * path)
+{
+	gint results = FALSE;
+	gchar * sub_str;
+	gchar * hidden_path_substr = g_strconcat (G_DIR_SEPARATOR_S, ".", NULL);
+
+	sub_str = g_strstr_len (path, strlen (path), hidden_path_substr);
+
+	if (sub_str != NULL) {
+		gchar * mate_desktop_str;
+
+		mate_desktop_str = g_strconcat (G_DIR_SEPARATOR_S, ".mate-desktop", G_DIR_SEPARATOR_S, NULL);
+
+		/* exclude the .mate-desktop folder */
+		if (strncmp (sub_str, mate_desktop_str, strlen (mate_desktop_str)) == 0) {
+			sub_str++;
+			results = (g_strstr_len (sub_str, strlen (sub_str), hidden_path_substr) != NULL);
+		}
+		else {
+			results = TRUE;
+		}
+
+		g_free (mate_desktop_str);
+	}
+
+	g_free (hidden_path_substr);
+	return results;
+}
+
+gboolean
+is_quick_search_excluded_path (const gchar * path)
+{
+	GSettings  * settings;
+	gchar     ** exclude_path_list;
+	gchar      * dir;
+	gboolean     results = FALSE;
+	gint         i;
+
+	dir = g_strdup (path);
+
+	/* Remove trailing G_DIR_SEPARATOR. */
+	if ((strlen (dir) > 1) && (g_str_has_suffix (dir, G_DIR_SEPARATOR_S) == TRUE)) {
+		dir[strlen (dir) - 1] = '\0';
+	}
+
+	/* Always exclude a path that is symbolic link. */
+	if (g_file_test (dir, G_FILE_TEST_IS_SYMLINK)) {
+		g_free (dir);
+
+		return TRUE;
+	}
+	g_free (dir);
+
+	settings = g_settings_new ("org.mate.search-tool");
+
+	/* Check path against the Quick-Search-Excluded-Paths list. */
+	exclude_path_list = g_settings_get_strv (settings, "quick-search-excluded-paths");
+
+	if (exclude_path_list) {
+		for (i = 0; exclude_path_list[i]; i++) {
+
+			/* Skip empty or null values. */
+			if (strlen (exclude_path_list[i]) == 0) {
+				continue;
+			}
+
+			dir = g_strdup (exclude_path_list[i]);
+
+			/* Wild-card comparisons. */
+			if (g_strstr_len (dir, strlen (dir), "*") != NULL) {
+
+				if (g_pattern_match_simple (dir, path) == TRUE) {
+
+					results = TRUE;
+					g_free (dir);
+					break;
+				}
+			}
+			/* Non-wild-card comparisons. */
+			else {
+				/* Add a trailing G_DIR_SEPARATOR. */
+				if (g_str_has_suffix (dir, G_DIR_SEPARATOR_S) == FALSE) {
+
+					gchar *tmp;
+
+					tmp = dir;
+					dir = g_strconcat (dir, G_DIR_SEPARATOR_S, NULL);
+					g_free (tmp);
+				}
+
+				if (strcmp (path, dir) == 0) {
+
+					results = TRUE;
+					g_free (dir);
+					break;
+				}
+			}
+			g_free (dir);
+		}
+		g_strfreev (exclude_path_list);
+	}
+
+	g_object_unref (settings);
+	return results;
+}
+
+gboolean
+is_second_scan_excluded_path (const gchar * path)
+{
+	GSettings  * settings;
+	gchar     ** exclude_path_list;
+	gchar      * dir;
+	gboolean     results = FALSE;
+	gint         i;
+
+	dir = g_strdup (path);
+
+	/* Remove trailing G_DIR_SEPARATOR. */
+	if ((strlen (dir) > 1) && (g_str_has_suffix (dir, G_DIR_SEPARATOR_S) == TRUE)) {
+		dir[strlen (dir) - 1] = '\0';
+	}
+
+	/* Always exclude a path that is symbolic link. */
+	if (g_file_test (dir, G_FILE_TEST_IS_SYMLINK)) {
+		g_free (dir);
+
+		return TRUE;
+	}
+	g_free (dir);
+
+	settings = g_settings_new ("org.mate.search-tool");
+
+	/* Check path against the Quick-Search-Excluded-Paths list. */
+	exclude_path_list = g_settings_get_strv (settings, "quick-search-second-scan-excluded-paths");
+
+	if (exclude_path_list) {
+		for (i = 0; exclude_path_list[i]; i++) {
+
+			/* Skip empty or null values. */
+			if (strlen (exclude_path_list[i]) == 0) {
+				continue;
+			}
+
+			dir = g_strdup (exclude_path_list[i]);
+
+			/* Wild-card comparisons. */
+			if (g_strstr_len (dir, strlen (dir), "*") != NULL) {
+
+				if (g_pattern_match_simple (dir, path) == TRUE) {
+
+					results = TRUE;
+					g_free (dir);
+					break;
+				}
+			}
+			/* Non-wild-card comparisons. */
+			else {
+				/* Add a trailing G_DIR_SEPARATOR. */
+				if (g_str_has_suffix (dir, G_DIR_SEPARATOR_S) == FALSE) {
+
+					gchar *tmp;
+
+					tmp = dir;
+					dir = g_strconcat (dir, G_DIR_SEPARATOR_S, NULL);
+					g_free (tmp);
+				}
+
+				if (strcmp (path, dir) == 0) {
+
+					results = TRUE;
+					g_free (dir);
+					break;
+				}
+			}
+			g_free (dir);
+		}
+		g_strfreev (exclude_path_list);
+	}
+
+	g_object_unref (settings);
+	return results;
+}
+
+gboolean
+compare_regex (const gchar * regex,
+	       const gchar * string)
+{
+	regex_t regexec_pattern;
+
+	if (regex == NULL) {
+		return TRUE;
+	}
+
+	if (!regcomp (&regexec_pattern, regex, REG_EXTENDED|REG_NOSUB)) {
+		if (regexec (&regexec_pattern, string, 0, 0, 0) != REG_NOMATCH) {
+			regfree (&regexec_pattern);
+			return TRUE;
+		}
+		regfree (&regexec_pattern);
+	}
+	return FALSE;
+}
+
+gboolean
+limit_string_to_x_lines (GString * string,
+			 gint x)
+{
+	int i;
+	int count = 0;
+	for (i = 0; string->str[i] != '\0'; i++) {
+		if (string->str[i] == '\n') {
+			count++;
+			if (count == x) {
+				g_string_truncate (string, i);
+				return TRUE;
+			}
+		}
+	}
+	return FALSE;
+}
+
+static gint
+count_of_char_in_string (const gchar * string,
+			 const gchar c)
+{
+	int cnt = 0;
+	for(; *string; string++) {
+		if (*string == c) cnt++;
+	}
+	return cnt;
+}
+
+gchar *
+escape_single_quotes (const gchar * string)
+{
+	GString * gs;
+
+	if (string == NULL) {
+		return NULL;
+	}
+
+	if (count_of_char_in_string (string, '\'') == 0) {
+		return g_strdup(string);
+	}
+	gs = g_string_new ("");
+	for(; *string; string++) {
+		if (*string == '\'') {
+			g_string_append(gs, "'\\''");
+		}
+		else {
+			g_string_append_c(gs, *string);
+		}
+	}
+	return g_string_free (gs, FALSE);
+}
+
+gchar *
+escape_double_quotes (const gchar * string)
+{
+	GString * gs;
+
+	if (string == NULL) {
+		return NULL;
+	}
+
+	if (count_of_char_in_string (string, '\"') == 0) {
+		return g_strdup(string);
+	}
+	gs = g_string_new ("");
+	for(; *string; string++) {
+		if (*string == '\"') {
+			g_string_append(gs, "\\\"");
+		}
+		else {
+			g_string_append_c(gs, *string);
+		}
+	}
+	return g_string_free (gs, FALSE);
+}
+
+gchar *
+backslash_backslash_characters (const gchar * string)
+{
+	GString * gs;
+
+	if (string == NULL) {
+		return NULL;
+	}
+
+	if (count_of_char_in_string (string, '\\') == 0){
+		return g_strdup(string);
+	}
+	gs = g_string_new ("");
+	for(; *string; string++) {
+		if (*string == '\\') {
+			g_string_append(gs, "\\\\");
+		}
+		else {
+			g_string_append_c(gs, *string);
+		}
+	}
+	return g_string_free (gs, FALSE);
+}
+
+gchar *
+backslash_special_characters (const gchar * string)
+{
+	GString * gs;
+
+	if (string == NULL) {
+		return NULL;
+	}
+
+	if ((count_of_char_in_string (string, '\\') == 0) &&
+	    (count_of_char_in_string (string, '-') == 0)) {
+		return g_strdup(string);
+	}
+	gs = g_string_new ("");
+	for(; *string; string++) {
+		if (*string == '\\') {
+			g_string_append(gs, "\\\\");
+		}
+		else if (*string == '-') {
+			g_string_append(gs, "\\-");
+		}
+		else {
+			g_string_append_c(gs, *string);
+		}
+	}
+	return g_string_free (gs, FALSE);
+}
+
+gchar *
+remove_mnemonic_character (const gchar * string)
+{
+	GString * gs;
+	gboolean first_mnemonic = TRUE;
+
+	if (string == NULL) {
+		return NULL;
+	}
+
+	gs = g_string_new ("");
+	for(; *string; string++) {
+		if ((first_mnemonic) && (*string == '_')) {
+			first_mnemonic = FALSE;
+			continue;
+		}
+		g_string_append_c(gs, *string);
+	}
+	return g_string_free (gs, FALSE);
+}
+
+gchar *
+get_readable_date (const CajaDateFormat  date_format_enum,
+                   GDateTime            *file_date_time)
+{
+	const gchar *format;
+	GDateTime   *now;
+	GTimeSpan    file_date_age;
+
+	/* Base format of date column on caja date-format key */
+	if (date_format_enum == CAJA_DATE_FORMAT_LOCALE) {
+		return g_date_time_format (file_date_time, "%c");
+	} else if (date_format_enum == CAJA_DATE_FORMAT_ISO) {
+		return g_date_time_format (file_date_time, "%Y-%m-%d %H:%M:%S");
+	}
+
+	now = g_date_time_new_now_local ();
+	file_date_age = g_date_time_difference (now, file_date_time);
+	g_date_time_unref (now);
+
+	if (file_date_age < G_TIME_SPAN_DAY)	{
+		format = _("today at %-I:%M %p");
+	} else if (file_date_age < 2 * G_TIME_SPAN_DAY) {
+		format = _("yesterday at %-I:%M %p");
+	} else {
+		format = _("%A, %B %-d %Y at %-I:%M:%S %p");
+	}
+
+	return g_date_time_format (file_date_time, format);
+}
+
+gchar *
+get_file_type_description (const gchar * file,
+                           GFileInfo * file_info)
+{
+	const char * content_type = NULL;
+	gchar * desc;
+
+	if (file != NULL) {
+		content_type = g_file_info_get_content_type (file_info);
+	}
+
+	if (content_type == NULL || g_content_type_is_unknown (content_type) == TRUE) {
+		return g_content_type_get_description ("application/octet-stream");
+	}
+
+	desc = g_content_type_get_description (content_type);
+
+	if (g_file_info_get_is_symlink (file_info) == TRUE) {
+
+		const gchar * symlink_target;
+		gchar * absolute_symlink = NULL;
+		gchar * str = NULL;
+
+		symlink_target = g_file_info_get_symlink_target (file_info);
+
+		if (g_path_is_absolute (symlink_target) != TRUE) {
+			gchar *dirname;
+
+			dirname = g_path_get_dirname (file);
+			absolute_symlink = g_strconcat (dirname, G_DIR_SEPARATOR_S, symlink_target, NULL);
+			g_free (dirname);
+		}
+		else {
+			absolute_symlink = g_strdup (symlink_target);
+		}
+
+		if (g_file_test (absolute_symlink, G_FILE_TEST_EXISTS) != TRUE) {
+                       if ((g_ascii_strcasecmp (content_type, "x-special/socket") != 0) &&
+                           (g_ascii_strcasecmp (content_type, "x-special/fifo") != 0)) {
+				g_free (absolute_symlink);
+				g_free (desc);
+				return g_strdup (_("link (broken)"));
+			}
+		}
+
+		str = g_strdup_printf (_("link to %s"), (desc != NULL) ? desc : content_type);
+		g_free (absolute_symlink);
+		g_free (desc);
+		return str;
+	}
+	return desc;
+}
+
+static gchar *
+gsearchtool_pixmap_file (const gchar * partial_path)
+{
+	gchar * path;
+
+	path = g_build_filename(DATADIR "/pixmaps/mate-search-tool", partial_path, NULL);
+	if (g_file_test(path, G_FILE_TEST_EXISTS)){
+		return path;
+	}
+	g_free (path);
+	return NULL;
+}
+
+static GdkPixbuf *
+gsearchtool_load_thumbnail_frame (void)
+{
+	GdkPixbuf * pixbuf = NULL;
+	gchar * image_path;
+
+	image_path = gsearchtool_pixmap_file("thumbnail_frame.png");
+
+	if (image_path != NULL){
+		pixbuf = gdk_pixbuf_new_from_file(image_path, NULL);
+	}
+	g_free(image_path);
+	return pixbuf;
+}
+
+static void
+gsearchtool_draw_frame_row (GdkPixbuf * frame_image,
+                            gint target_width,
+                            gint source_width,
+                            gint source_v_position,
+                            gint dest_v_position,
+                            GdkPixbuf * result_pixbuf,
+                            gint left_offset,
+                            gint height)
+{
+	gint remaining_width;
+	gint h_offset;
+	gint slab_width;
+
+	remaining_width = target_width;
+	h_offset = 0;
+	while (remaining_width > 0) {
+		slab_width = remaining_width > source_width ? source_width : remaining_width;
+		gdk_pixbuf_copy_area (frame_image, left_offset, source_v_position, slab_width,
+		                      height, result_pixbuf, left_offset + h_offset, dest_v_position);
+		remaining_width -= slab_width;
+		h_offset += slab_width;
+	}
+}
+
+static void
+gsearchtool_draw_frame_column (GdkPixbuf * frame_image,
+                               gint target_height,
+                               gint source_height,
+                               gint source_h_position,
+                               gint dest_h_position,
+                               GdkPixbuf * result_pixbuf,
+                               gint top_offset,
+                               gint width)
+{
+	gint remaining_height;
+	gint v_offset;
+	gint slab_height;
+
+	remaining_height = target_height;
+	v_offset = 0;
+	while (remaining_height > 0) {
+		slab_height = remaining_height > source_height ? source_height : remaining_height;
+		gdk_pixbuf_copy_area (frame_image, source_h_position, top_offset, width, slab_height,
+		                      result_pixbuf, dest_h_position, top_offset + v_offset);
+		remaining_height -= slab_height;
+		v_offset += slab_height;
+	}
+}
+
+static GdkPixbuf *
+gsearchtool_stretch_frame_image (GdkPixbuf *frame_image,
+                                 gint left_offset,
+                                 gint top_offset,
+                                 gint right_offset,
+                                 gint bottom_offset,
+                                 gint dest_width,
+                                 gint dest_height,
+                                 gboolean fill_flag)
+{
+	GdkPixbuf * result_pixbuf;
+	gint frame_width, frame_height;
+	gint target_width, target_frame_width;
+	gint target_height, target_frame_height;
+
+	frame_width = gdk_pixbuf_get_width (frame_image);
+	frame_height = gdk_pixbuf_get_height (frame_image);
+
+	if (fill_flag) {
+		result_pixbuf = gdk_pixbuf_scale_simple (frame_image, dest_width, dest_height, GDK_INTERP_NEAREST);
+	} else {
+		result_pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, dest_width, dest_height);
+	}
+
+	/* clear the new pixbuf */
+	if (fill_flag == FALSE) {
+		gdk_pixbuf_fill (result_pixbuf, 0xffffffff);
+	}
+
+	target_width  = dest_width - left_offset - right_offset;
+	target_frame_width = frame_width - left_offset - right_offset;
+
+	target_height  = dest_height - top_offset - bottom_offset;
+	target_frame_height = frame_height - top_offset - bottom_offset;
+
+	/* Draw the left top corner  and top row */
+	gdk_pixbuf_copy_area (frame_image, 0, 0, left_offset, top_offset, result_pixbuf, 0,  0);
+	gsearchtool_draw_frame_row (frame_image, target_width, target_frame_width, 0, 0,
+	                            result_pixbuf, left_offset, top_offset);
+
+	/* Draw the right top corner and left column */
+	gdk_pixbuf_copy_area (frame_image, frame_width - right_offset, 0, right_offset, top_offset,
+	                      result_pixbuf, dest_width - right_offset,  0);
+	gsearchtool_draw_frame_column (frame_image, target_height, target_frame_height, 0, 0,
+	                               result_pixbuf, top_offset, left_offset);
+
+	/* Draw the bottom right corner and bottom row */
+	gdk_pixbuf_copy_area (frame_image, frame_width - right_offset, frame_height - bottom_offset,
+	                      right_offset, bottom_offset, result_pixbuf, dest_width - right_offset,
+			      dest_height - bottom_offset);
+	gsearchtool_draw_frame_row (frame_image, target_width, target_frame_width,
+	                            frame_height - bottom_offset, dest_height - bottom_offset,
+				    result_pixbuf, left_offset, bottom_offset);
+
+	/* Draw the bottom left corner and the right column */
+	gdk_pixbuf_copy_area (frame_image, 0, frame_height - bottom_offset, left_offset, bottom_offset,
+	                      result_pixbuf, 0,  dest_height - bottom_offset);
+	gsearchtool_draw_frame_column (frame_image, target_height, target_frame_height,
+	                               frame_width - right_offset, dest_width - right_offset,
+				       result_pixbuf, top_offset, right_offset);
+	return result_pixbuf;
+}
+
+static GdkPixbuf *
+gsearchtool_embed_image_in_frame (GdkPixbuf * source_image,
+                                  GdkPixbuf * frame_image,
+                                  gint left_offset,
+                                  gint top_offset,
+                                  gint right_offset,
+                                  gint bottom_offset)
+{
+	GdkPixbuf * result_pixbuf;
+	gint source_width, source_height;
+	gint dest_width, dest_height;
+
+	source_width = gdk_pixbuf_get_width (source_image);
+	source_height = gdk_pixbuf_get_height (source_image);
+
+	dest_width = source_width + left_offset + right_offset;
+	dest_height = source_height + top_offset + bottom_offset;
+
+	result_pixbuf = gsearchtool_stretch_frame_image (frame_image, left_offset, top_offset, right_offset, bottom_offset,
+						         dest_width, dest_height, FALSE);
+
+	gdk_pixbuf_copy_area (source_image, 0, 0, source_width, source_height, result_pixbuf, left_offset, top_offset);
+
+	return result_pixbuf;
+}
+
+static void
+gsearchtool_thumbnail_frame_image (GdkPixbuf ** pixbuf)
+{
+	GdkPixbuf * pixbuf_with_frame;
+	GdkPixbuf * frame;
+
+	frame = gsearchtool_load_thumbnail_frame ();
+	if (frame == NULL) {
+		return;
+	}
+
+	pixbuf_with_frame = gsearchtool_embed_image_in_frame (*pixbuf, frame, 3, 3, 6, 6);
+	g_object_unref (*pixbuf);
+	g_object_unref (frame);
+
+	*pixbuf = pixbuf_with_frame;
+}
+
+static GdkPixbuf *
+gsearchtool_get_thumbnail_image (const gchar * thumbnail)
+{
+	GdkPixbuf * pixbuf = NULL;
+
+	if (thumbnail != NULL) {
+		if (g_file_test (thumbnail, G_FILE_TEST_EXISTS)) {
+
+			GdkPixbuf * thumbnail_pixbuf = NULL;
+			gfloat scale_factor_x = 1.0;
+			gfloat scale_factor_y = 1.0;
+			gint scale_x;
+			gint scale_y;
+			gint width;
+			gint height;
+
+			thumbnail_pixbuf = gdk_pixbuf_new_from_file (thumbnail, NULL);
+			gsearchtool_thumbnail_frame_image (&thumbnail_pixbuf);
+
+			width = gdk_pixbuf_get_width (thumbnail_pixbuf);
+			if (width > ICON_SIZE) {
+				scale_factor_x = (gfloat) ICON_SIZE / (gfloat) width;
+			}
+			height = gdk_pixbuf_get_height (thumbnail_pixbuf);
+			if (height > ICON_SIZE) {
+				scale_factor_y = (gfloat) ICON_SIZE / (gfloat) height;
+			}
+
+			if (width > height) {
+				scale_x = ICON_SIZE;
+				scale_y = (gint) (height * scale_factor_x);
+			}
+			else {
+				scale_x = (gint) (width * scale_factor_y);
+				scale_y = ICON_SIZE;
+			}
+
+			pixbuf = gdk_pixbuf_scale_simple (thumbnail_pixbuf, scale_x, scale_y, GDK_INTERP_BILINEAR);
+			g_object_unref (thumbnail_pixbuf);
+		}
+	}
+	return pixbuf;
+}
+
+static GdkPixbuf *
+get_themed_icon_pixbuf (GThemedIcon * icon,
+                        int size,
+                        GtkIconTheme * icon_theme)
+{
+	char ** icon_names;
+	GtkIconInfo * icon_info;
+	GdkPixbuf * pixbuf;
+	GError * error = NULL;
+
+	g_object_get (icon, "names", &icon_names, NULL);
+
+	icon_info = gtk_icon_theme_choose_icon (icon_theme, (const char **)icon_names, size, 0);
+	if (icon_info == NULL) {
+		icon_info = gtk_icon_theme_lookup_icon (icon_theme, "text-x-generic", size, GTK_ICON_LOOKUP_USE_BUILTIN);
+	}
+	pixbuf = gtk_icon_info_load_icon (icon_info, &error);
+	if (pixbuf == NULL) {
+		g_warning ("Could not load icon pixbuf: %s\n", error->message);
+		g_clear_error (&error);
+	}
+
+	g_object_unref (icon_info);
+	g_strfreev (icon_names);
+
+	return pixbuf;
+}
+
+GdkPixbuf *
+get_file_pixbuf (GSearchWindow * gsearch,
+                 GFileInfo * file_info)
+{
+	GdkPixbuf * pixbuf;
+	GIcon * icon = NULL;
+	const gchar * thumbnail_path = NULL;
+
+	if (file_info == NULL) {
+		return NULL;
+	}
+
+	icon = g_file_info_get_icon (file_info);
+
+	if (gsearch->show_thumbnails == TRUE) {
+		thumbnail_path = g_file_info_get_attribute_byte_string (file_info, G_FILE_ATTRIBUTE_THUMBNAIL_PATH);
+	}
+
+	if (thumbnail_path != NULL) {
+		pixbuf = gsearchtool_get_thumbnail_image (thumbnail_path);
+	}
+	else {
+		gchar * icon_string;
+
+		icon_string = g_icon_to_string (icon);
+		pixbuf = (GdkPixbuf *) g_hash_table_lookup (gsearch->search_results_filename_hash_table, icon_string);
+
+		if (pixbuf == NULL) {
+			pixbuf = get_themed_icon_pixbuf (G_THEMED_ICON (icon), ICON_SIZE, gtk_icon_theme_get_default ());
+			g_hash_table_insert (gsearch->search_results_filename_hash_table, g_strdup (icon_string), pixbuf);
+		}
+		g_free (icon_string);
+	}
+	return pixbuf;
+}
+
+gboolean
+open_file_with_filemanager (GtkWidget * window,
+                            const gchar * file)
+{
+	GDesktopAppInfo * d_app_info;
+	GKeyFile * key_file;
+	GdkAppLaunchContext * ctx = NULL;
+	GdkScreen *screen;
+	GdkDisplay *display;
+	GList * list = NULL;
+	GAppInfo * g_app_info;
+	GFile * g_file;
+	gchar * command;
+	gchar * contents;
+	gchar * uri;
+	gboolean result = TRUE;
+
+	uri = g_filename_to_uri (file, NULL, NULL);
+	list = g_list_prepend (list, uri);
+
+	g_file = g_file_new_for_path (file);
+	g_app_info = g_file_query_default_handler (g_file, NULL, NULL);
+
+	if (strcmp (g_app_info_get_executable (g_app_info), "caja") == 0) {
+		command = g_strconcat ("caja ",
+		                       "--sm-disable ",
+		                       "--no-desktop ",
+		                       "--no-default-window ",
+		                       NULL);
+	}
+	else {
+		command = g_strconcat (g_app_info_get_executable (g_app_info),
+		                       " ", NULL);
+	}
+
+	contents = g_strdup_printf ("[Desktop Entry]\n"
+				    "Name=Caja\n"
+				    "Icon=file-manager\n"
+				    "Exec=%s\n"
+				    "Terminal=false\n"
+				    "StartupNotify=true\n"
+				    "Type=Application\n",
+				    command);
+	key_file = g_key_file_new ();
+	g_key_file_load_from_data (key_file, contents, strlen(contents), G_KEY_FILE_NONE, NULL);
+	d_app_info = g_desktop_app_info_new_from_keyfile (key_file);
+
+	if (d_app_info != NULL) {
+		screen = gtk_widget_get_screen (GTK_WIDGET (window));
+		display = gdk_screen_get_display (screen);
+		ctx = gdk_display_get_app_launch_context (display);
+		gdk_app_launch_context_set_screen (ctx, gtk_widget_get_screen (window));
+
+		result = g_app_info_launch_uris (G_APP_INFO (d_app_info), list,  G_APP_LAUNCH_CONTEXT (ctx), NULL);
+	}
+	else {
+		result = FALSE;
+	}
+
+	g_object_unref (g_app_info);
+	g_object_unref (d_app_info);
+	g_object_unref (g_file);
+	g_object_unref (ctx);
+	g_key_file_free (key_file);
+	g_list_free (list);
+	g_free (contents);
+	g_free (command);
+	g_free (uri);
+
+	return result;
+}
+
+gboolean
+open_file_with_application (GtkWidget * window,
+                            const gchar * file,
+                            GAppInfo * app)
+{
+	GdkAppLaunchContext * context;
+	GdkDisplay *display;
+	GdkScreen * screen;
+	gboolean result;
+
+	if (g_file_test (file, G_FILE_TEST_IS_DIR) == TRUE) {
+		return FALSE;
+	}
+
+	screen = gtk_widget_get_screen (window);
+	display = gdk_screen_get_display (screen);
+	context = gdk_display_get_app_launch_context (display);
+	gdk_app_launch_context_set_screen (context, screen);
+
+	if (app == NULL) {
+		gchar * uri;
+
+		uri = g_filename_to_uri (file, NULL, NULL);
+		result = g_app_info_launch_default_for_uri (uri, (GAppLaunchContext *) context, NULL);
+		g_free (uri);
+	}
+	else {
+		GList * g_file_list = NULL;
+		GFile * g_file = NULL;
+
+		g_file = g_file_new_for_path (file);
+
+		if (g_file == NULL) {
+			result = FALSE;
+		}
+		else {
+			g_file_list = g_list_prepend (g_file_list, g_file);
+
+			result = g_app_info_launch (app, g_file_list, (GAppLaunchContext *) context, NULL);
+			g_list_free (g_file_list);
+			g_object_unref (g_file);
+		}
+	}
+	return result;
+}
+
+gboolean
+launch_file (const gchar * file)
+{
+	const char * content_type = g_content_type_guess (file, NULL, 0, NULL);
+	gboolean result = FALSE;
+
+	if ((g_file_test (file, G_FILE_TEST_IS_EXECUTABLE)) &&
+	    (g_ascii_strcasecmp (content_type, BINARY_EXEC_MIME_TYPE) == 0)) {
+		result = g_spawn_command_line_async (file, NULL);
+	}
+
+	return result;
+}
+
+gchar *
+gsearchtool_get_unique_filename (const gchar * path,
+                                 const gchar * suffix)
+{
+	const gint num_of_words = 12;
+	gchar     * words[] = {
+		    "foo",
+		    "bar",
+		    "blah",
+	   	    "cranston",
+		    "frobate",
+		    "hadjaha",
+		    "greasy",
+		    "hammer",
+		    "eek",
+		    "larry",
+		    "curly",
+		    "moe",
+		    NULL};
+	gchar * retval = NULL;
+	gboolean exists = TRUE;
+
+	while (exists) {
+		gchar * file;
+		gint rnd;
+		gint word;
+
+		rnd = rand ();
+		word = rand () % num_of_words;
+
+		file = g_strdup_printf ("%s-%010x%s",
+					    words [word],
+					    (guint) rnd,
+					    suffix);
+
+		g_free (retval);
+		retval = g_strconcat (path, G_DIR_SEPARATOR_S, file, NULL);
+		exists = g_file_test (retval, G_FILE_TEST_EXISTS);
+		g_free (file);
+	}
+	return retval;
+}
+
+GtkWidget *
+gsearchtool_button_new_with_icon (const gchar * string,
+                                  const gchar * icon_name)
+{
+	GtkWidget * button;
+	GtkWidget * hbox;
+	GtkWidget * image;
+	GtkWidget * label;
+
+	button = gtk_button_new ();
+	label = gtk_label_new_with_mnemonic (string);
+	gtk_label_set_mnemonic_widget (GTK_LABEL (label), GTK_WIDGET (button));
+	image = gtk_image_new_from_icon_name (icon_name, GTK_ICON_SIZE_BUTTON);
+	hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2);
+	gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 0);
+	gtk_box_pack_end (GTK_BOX (hbox), label, FALSE, FALSE, 0);
+	gtk_container_add (GTK_CONTAINER (button), hbox);
+	gtk_widget_show_all (hbox);
+
+	return button;
+}
+
+GSList *
+gsearchtool_get_columns_order (GtkTreeView * treeview)
+{
+	GSList *order = NULL;
+	GList * columns;
+	GList * col;
+
+	columns = gtk_tree_view_get_columns (treeview);
+
+	for (col = columns; col; col = col->next) {
+		gint id;
+
+		id = gtk_tree_view_column_get_sort_column_id (col->data);
+		order = g_slist_prepend (order, GINT_TO_POINTER (id));
+	}
+	g_list_free (columns);
+
+	order = g_slist_reverse (order);
+	return order;
+}
+
+GtkTreeViewColumn *
+gsearchtool_gtk_tree_view_get_column_with_sort_column_id (GtkTreeView * treeview,
+                                                          gint id)
+{
+	GtkTreeViewColumn * col = NULL;
+	GList * columns;
+	GList * it;
+
+	columns = gtk_tree_view_get_columns (treeview);
+
+	for (it = columns; it; it = it->next) {
+		if (gtk_tree_view_column_get_sort_column_id (it->data) == id) {
+			col = it->data;
+			break;
+		}
+	}
+	g_list_free (columns);
+	return col;
+}
+
+void
+gsearchtool_set_columns_order (GtkTreeView * treeview)
+{
+	GtkTreeViewColumn * last = NULL;
+	GSettings * settings;
+	GVariant * value;
+
+	settings = g_settings_new ("org.mate.search-tool");
+
+	value = g_settings_get_value (settings, "columns-order");
+
+	if (value) {
+		GVariantIter *iter;
+		GVariant     *item;
+
+		g_variant_get (value, "ai", &iter);
+
+		while ((item = g_variant_iter_next_value (iter))) {
+			GtkTreeViewColumn * cur;
+			gint id;
+
+			g_variant_get (item, "i", &id);
+
+			if (id >= 0 && id < NUM_COLUMNS) {
+
+				cur = gsearchtool_gtk_tree_view_get_column_with_sort_column_id (treeview, id);
+
+				if (cur && cur != last) {
+					gtk_tree_view_move_column_after (treeview, cur, last);
+					last = cur;
+				}
+			}
+			g_variant_unref (item);
+		}
+		g_variant_iter_free (iter);
+		g_variant_unref (value);
+	}
+	g_object_unref (settings);
+}
+
+void
+gsearchtool_get_stored_window_geometry (gint * width,
+                                        gint * height)
+{
+	GSettings * settings;
+	gint saved_width;
+	gint saved_height;
+
+	if (width == NULL || height == NULL) {
+		return;
+	}
+
+	settings = g_settings_new ("org.mate.search-tool");
+
+	saved_width = g_settings_get_int (settings, "default-window-width");
+	saved_height = g_settings_get_int (settings, "default-window-height");
+
+	if (saved_width == -1) {
+		saved_width = DEFAULT_WINDOW_WIDTH;
+	}
+
+	if (saved_height == -1) {
+		saved_height = DEFAULT_WINDOW_HEIGHT;
+	}
+
+	*width = MAX (saved_width, MINIMUM_WINDOW_WIDTH);
+	*height = MAX (saved_height, MINIMUM_WINDOW_HEIGHT);
+	g_object_unref (settings);
+}
+
+/* START OF CAJA/EEL FUNCTIONS: USED FOR HANDLING OF DUPLICATE FILENAMES */
+
+/* Localizers:
+ * Feel free to leave out the st, nd, rd and th suffix or
+ * make some or all of them match.
+ */
+
+/* localizers: tag used to detect the first copy of a file */
+static const char untranslated_copy_duplicate_tag[] = N_(" (copy)");
+/* localizers: tag used to detect the second copy of a file */
+static const char untranslated_another_copy_duplicate_tag[] = N_(" (another copy)");
+
+/* localizers: tag used to detect the x11th copy of a file */
+static const char untranslated_x11th_copy_duplicate_tag[] = N_("th copy)");
+/* localizers: tag used to detect the x12th copy of a file */
+static const char untranslated_x12th_copy_duplicate_tag[] = N_("th copy)");
+/* localizers: tag used to detect the x13th copy of a file */
+static const char untranslated_x13th_copy_duplicate_tag[] = N_("th copy)");
+
+/* localizers: tag used to detect the x1st copy of a file */
+static const char untranslated_st_copy_duplicate_tag[] = N_("st copy)");
+/* localizers: tag used to detect the x2nd copy of a file */
+static const char untranslated_nd_copy_duplicate_tag[] = N_("nd copy)");
+/* localizers: tag used to detect the x3rd copy of a file */
+static const char untranslated_rd_copy_duplicate_tag[] = N_("rd copy)");
+
+/* localizers: tag used to detect the xxth copy of a file */
+static const char untranslated_th_copy_duplicate_tag[] = N_("th copy)");
+
+#define COPY_DUPLICATE_TAG _(untranslated_copy_duplicate_tag)
+#define ANOTHER_COPY_DUPLICATE_TAG _(untranslated_another_copy_duplicate_tag)
+#define X11TH_COPY_DUPLICATE_TAG _(untranslated_x11th_copy_duplicate_tag)
+#define X12TH_COPY_DUPLICATE_TAG _(untranslated_x12th_copy_duplicate_tag)
+#define X13TH_COPY_DUPLICATE_TAG _(untranslated_x13th_copy_duplicate_tag)
+
+#define ST_COPY_DUPLICATE_TAG _(untranslated_st_copy_duplicate_tag)
+#define ND_COPY_DUPLICATE_TAG _(untranslated_nd_copy_duplicate_tag)
+#define RD_COPY_DUPLICATE_TAG _(untranslated_rd_copy_duplicate_tag)
+#define TH_COPY_DUPLICATE_TAG _(untranslated_th_copy_duplicate_tag)
+
+/* localizers: appended to first file copy */
+static const char untranslated_first_copy_duplicate_format[] = N_("%s (copy)%s");
+/* localizers: appended to second file copy */
+static const char untranslated_second_copy_duplicate_format[] = N_("%s (another copy)%s");
+
+/* localizers: appended to x11th file copy */
+static const char untranslated_x11th_copy_duplicate_format[] = N_("%s (%dth copy)%s");
+/* localizers: appended to x12th file copy */
+static const char untranslated_x12th_copy_duplicate_format[] = N_("%s (%dth copy)%s");
+/* localizers: appended to x13th file copy */
+static const char untranslated_x13th_copy_duplicate_format[] = N_("%s (%dth copy)%s");
+
+/* localizers: appended to x1st file copy */
+static const char untranslated_st_copy_duplicate_format[] = N_("%s (%dst copy)%s");
+/* localizers: appended to x2nd file copy */
+static const char untranslated_nd_copy_duplicate_format[] = N_("%s (%dnd copy)%s");
+/* localizers: appended to x3rd file copy */
+static const char untranslated_rd_copy_duplicate_format[] = N_("%s (%drd copy)%s");
+/* localizers: appended to xxth file copy */
+static const char untranslated_th_copy_duplicate_format[] = N_("%s (%dth copy)%s");
+
+#define FIRST_COPY_DUPLICATE_FORMAT _(untranslated_first_copy_duplicate_format)
+#define SECOND_COPY_DUPLICATE_FORMAT _(untranslated_second_copy_duplicate_format)
+#define X11TH_COPY_DUPLICATE_FORMAT _(untranslated_x11th_copy_duplicate_format)
+#define X12TH_COPY_DUPLICATE_FORMAT _(untranslated_x12th_copy_duplicate_format)
+#define X13TH_COPY_DUPLICATE_FORMAT _(untranslated_x13th_copy_duplicate_format)
+
+#define ST_COPY_DUPLICATE_FORMAT _(untranslated_st_copy_duplicate_format)
+#define ND_COPY_DUPLICATE_FORMAT _(untranslated_nd_copy_duplicate_format)
+#define RD_COPY_DUPLICATE_FORMAT _(untranslated_rd_copy_duplicate_format)
+#define TH_COPY_DUPLICATE_FORMAT _(untranslated_th_copy_duplicate_format)
+
+static gchar *
+make_valid_utf8 (const gchar * name)
+{
+	GString *string;
+	const char *remainder, *invalid;
+	int remaining_bytes, valid_bytes;
+
+	string = NULL;
+	remainder = name;
+	remaining_bytes = strlen (name);
+
+	while (remaining_bytes != 0) {
+		if (g_utf8_validate (remainder, remaining_bytes, &invalid)) {
+			break;
+		}
+		valid_bytes = invalid - remainder;
+
+		if (string == NULL) {
+			string = g_string_sized_new (remaining_bytes);
+		}
+		g_string_append_len (string, remainder, valid_bytes);
+		g_string_append_c (string, '?');
+
+		remaining_bytes -= valid_bytes + 1;
+		remainder = invalid + 1;
+	}
+
+	if (string == NULL) {
+		return g_strdup (name);
+	}
+
+	g_string_append (string, remainder);
+	g_string_append (string, _(" (invalid Unicode)"));
+	g_assert (g_utf8_validate (string->str, -1, NULL));
+
+	return g_string_free (string, FALSE);
+}
+
+static gchar *
+extract_string_until (const gchar * original,
+                      const gchar * until_substring)
+{
+	gchar * result;
+
+	g_assert ((gint) strlen (original) >= until_substring - original);
+	g_assert (until_substring - original >= 0);
+
+	result = g_malloc (until_substring - original + 1);
+	strncpy (result, original, until_substring - original);
+	result[until_substring - original] = '\0';
+
+	return result;
+}
+
+/* Dismantle a file name, separating the base name, the file suffix and removing any
+ * (xxxcopy), etc. string. Figure out the count that corresponds to the given
+ * (xxxcopy) substring.
+ */
+static void
+parse_previous_duplicate_name (const gchar * name,
+                               gchar ** name_base,
+                               const gchar ** suffix,
+                               gint * count)
+{
+	const gchar * tag;
+
+	g_assert (name[0] != '\0');
+
+	*suffix = strchr (name + 1, '.');
+	if (*suffix == NULL || (*suffix)[1] == '\0') {
+		/* no suffix */
+		*suffix = "";
+	}
+
+	tag = strstr (name, COPY_DUPLICATE_TAG);
+	if (tag != NULL) {
+		if (tag > *suffix) {
+			/* handle case "foo. (copy)" */
+			*suffix = "";
+		}
+		*name_base = extract_string_until (name, tag);
+		*count = 1;
+		return;
+	}
+
+	tag = strstr (name, ANOTHER_COPY_DUPLICATE_TAG);
+	if (tag != NULL) {
+		if (tag > *suffix) {
+			/* handle case "foo. (another copy)" */
+			*suffix = "";
+		}
+		*name_base = extract_string_until (name, tag);
+		*count = 2;
+		return;
+	}
+
+	/* Check to see if we got one of st, nd, rd, th. */
+	tag = strstr (name, X11TH_COPY_DUPLICATE_TAG);
+
+	if (tag == NULL) {
+		tag = strstr (name, X12TH_COPY_DUPLICATE_TAG);
+	}
+	if (tag == NULL) {
+		tag = strstr (name, X13TH_COPY_DUPLICATE_TAG);
+	}
+	if (tag == NULL) {
+		tag = strstr (name, ST_COPY_DUPLICATE_TAG);
+	}
+	if (tag == NULL) {
+		tag = strstr (name, ND_COPY_DUPLICATE_TAG);
+	}
+	if (tag == NULL) {
+		tag = strstr (name, RD_COPY_DUPLICATE_TAG);
+	}
+	if (tag == NULL) {
+		tag = strstr (name, TH_COPY_DUPLICATE_TAG);
+	}
+
+	/* If we got one of st, nd, rd, th, fish out the duplicate number. */
+	if (tag != NULL) {
+		/* localizers: opening parentheses to match the "th copy)" string */
+		tag = strstr (name, _(" ("));
+		if (tag != NULL) {
+			if (tag > *suffix) {
+				/* handle case "foo. (22nd copy)" */
+				*suffix = "";
+			}
+			*name_base = extract_string_until (name, tag);
+			/* localizers: opening parentheses of the "th copy)" string */
+			if (sscanf (tag, _(" (%d"), count) == 1) {
+				if (*count < 1 || *count > 1000000) {
+					/* keep the count within a reasonable range */
+					*count = 0;
+				}
+				return;
+			}
+			*count = 0;
+			return;
+		}
+	}
+
+	*count = 0;
+	if (**suffix != '\0') {
+		*name_base = extract_string_until (name, *suffix);
+	} else {
+		*name_base = g_strdup (name);
+	}
+}
+
+static gchar *
+make_next_duplicate_name (const gchar *base,
+                          const gchar *suffix,
+                          gint count)
+{
+	const gchar * format;
+	gchar * result;
+
+	if (count < 1) {
+		g_warning ("bad count %d in make_next_duplicate_name()", count);
+		count = 1;
+	}
+
+	if (count <= 2) {
+
+		/* Handle special cases for low numbers.
+		 * Perhaps for some locales we will need to add more.
+		 */
+		switch (count) {
+		default:
+			g_assert_not_reached ();
+			/* fall through */
+		case 1:
+			format = FIRST_COPY_DUPLICATE_FORMAT;
+			break;
+		case 2:
+			format = SECOND_COPY_DUPLICATE_FORMAT;
+			break;
+
+		}
+		result = g_strdup_printf (format, base, suffix);
+	} else {
+
+		/* Handle special cases for the first few numbers of each ten.
+		 * For locales where getting this exactly right is difficult,
+		 * these can just be made all the same as the general case below.
+		 */
+
+		/* Handle special cases for x11th - x20th.
+		 */
+		switch (count % 100) {
+		case 11:
+			format = X11TH_COPY_DUPLICATE_FORMAT;
+			break;
+		case 12:
+			format = X12TH_COPY_DUPLICATE_FORMAT;
+			break;
+		case 13:
+			format = X13TH_COPY_DUPLICATE_FORMAT;
+			break;
+		default:
+			format = NULL;
+			break;
+		}
+
+		if (format == NULL) {
+			switch (count % 10) {
+			case 1:
+				format = ST_COPY_DUPLICATE_FORMAT;
+				break;
+			case 2:
+				format = ND_COPY_DUPLICATE_FORMAT;
+				break;
+			case 3:
+				format = RD_COPY_DUPLICATE_FORMAT;
+				break;
+			default:
+				/* The general case. */
+				format = TH_COPY_DUPLICATE_FORMAT;
+				break;
+			}
+		}
+		result = g_strdup_printf (format, base, count, suffix);
+	}
+	return result;
+}
+
+static gchar *
+get_duplicate_name (const gchar *name)
+{
+	const gchar * suffix;
+	gchar * name_base;
+	gchar * result;
+	gint count;
+
+	parse_previous_duplicate_name (name, &name_base, &suffix, &count);
+	result = make_next_duplicate_name (name_base, suffix, count + 1);
+	g_free (name_base);
+
+	return result;
+}
+
+gchar *
+gsearchtool_get_next_duplicate_name (const gchar * basename)
+{
+	gchar * utf8_name;
+	gchar * utf8_result;
+	gchar * result;
+
+	utf8_name = g_filename_to_utf8 (basename, -1, NULL, NULL, NULL);
+
+	if (utf8_name == NULL) {
+		/* Couldn't convert to utf8 - probably
+		 * G_BROKEN_FILENAMES not set when it should be.
+		 * Try converting from the locale */
+		utf8_name = g_locale_to_utf8 (basename, -1, NULL, NULL, NULL);
+
+		if (utf8_name == NULL) {
+			utf8_name = make_valid_utf8 (basename);
+		}
+	}
+
+	utf8_result = get_duplicate_name (utf8_name);
+	g_free (utf8_name);
+
+	result = g_filename_from_utf8 (utf8_result, -1, NULL, NULL, NULL);
+	g_free (utf8_result);
+	return result;
+}
+
+ +
+ +
+ + diff --git a/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/16.html b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/16.html new file mode 100644 index 00000000..64645151 --- /dev/null +++ b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/16.html @@ -0,0 +1,6433 @@ + + + + + + Cppcheck - HTML report - mate-utils + + + + + +
+ + + +
+
   1
+   2
+   3
+   4
+   5
+   6
+   7
+   8
+   9
+  10
+  11
+  12
+  13
+  14
+  15
+  16
+  17
+  18
+  19
+  20
+  21
+  22
+  23
+  24
+  25
+  26
+  27
+  28
+  29
+  30
+  31
+  32
+  33
+  34
+  35
+  36
+  37
+  38
+  39
+  40
+  41
+  42
+  43
+  44
+  45
+  46
+  47
+  48
+  49
+  50
+  51
+  52
+  53
+  54
+  55
+  56
+  57
+  58
+  59
+  60
+  61
+  62
+  63
+  64
+  65
+  66
+  67
+  68
+  69
+  70
+  71
+  72
+  73
+  74
+  75
+  76
+  77
+  78
+  79
+  80
+  81
+  82
+  83
+  84
+  85
+  86
+  87
+  88
+  89
+  90
+  91
+  92
+  93
+  94
+  95
+  96
+  97
+  98
+  99
+ 100
+ 101
+ 102
+ 103
+ 104
+ 105
+ 106
+ 107
+ 108
+ 109
+ 110
+ 111
+ 112
+ 113
+ 114
+ 115
+ 116
+ 117
+ 118
+ 119
+ 120
+ 121
+ 122
+ 123
+ 124
+ 125
+ 126
+ 127
+ 128
+ 129
+ 130
+ 131
+ 132
+ 133
+ 134
+ 135
+ 136
+ 137
+ 138
+ 139
+ 140
+ 141
+ 142
+ 143
+ 144
+ 145
+ 146
+ 147
+ 148
+ 149
+ 150
+ 151
+ 152
+ 153
+ 154
+ 155
+ 156
+ 157
+ 158
+ 159
+ 160
+ 161
+ 162
+ 163
+ 164
+ 165
+ 166
+ 167
+ 168
+ 169
+ 170
+ 171
+ 172
+ 173
+ 174
+ 175
+ 176
+ 177
+ 178
+ 179
+ 180
+ 181
+ 182
+ 183
+ 184
+ 185
+ 186
+ 187
+ 188
+ 189
+ 190
+ 191
+ 192
+ 193
+ 194
+ 195
+ 196
+ 197
+ 198
+ 199
+ 200
+ 201
+ 202
+ 203
+ 204
+ 205
+ 206
+ 207
+ 208
+ 209
+ 210
+ 211
+ 212
+ 213
+ 214
+ 215
+ 216
+ 217
+ 218
+ 219
+ 220
+ 221
+ 222
+ 223
+ 224
+ 225
+ 226
+ 227
+ 228
+ 229
+ 230
+ 231
+ 232
+ 233
+ 234
+ 235
+ 236
+ 237
+ 238
+ 239
+ 240
+ 241
+ 242
+ 243
+ 244
+ 245
+ 246
+ 247
+ 248
+ 249
+ 250
+ 251
+ 252
+ 253
+ 254
+ 255
+ 256
+ 257
+ 258
+ 259
+ 260
+ 261
+ 262
+ 263
+ 264
+ 265
+ 266
+ 267
+ 268
+ 269
+ 270
+ 271
+ 272
+ 273
+ 274
+ 275
+ 276
+ 277
+ 278
+ 279
+ 280
+ 281
+ 282
+ 283
+ 284
+ 285
+ 286
+ 287
+ 288
+ 289
+ 290
+ 291
+ 292
+ 293
+ 294
+ 295
+ 296
+ 297
+ 298
+ 299
+ 300
+ 301
+ 302
+ 303
+ 304
+ 305
+ 306
+ 307
+ 308
+ 309
+ 310
+ 311
+ 312
+ 313
+ 314
+ 315
+ 316
+ 317
+ 318
+ 319
+ 320
+ 321
+ 322
+ 323
+ 324
+ 325
+ 326
+ 327
+ 328
+ 329
+ 330
+ 331
+ 332
+ 333
+ 334
+ 335
+ 336
+ 337
+ 338
+ 339
+ 340
+ 341
+ 342
+ 343
+ 344
+ 345
+ 346
+ 347
+ 348
+ 349
+ 350
+ 351
+ 352
+ 353
+ 354
+ 355
+ 356
+ 357
+ 358
+ 359
+ 360
+ 361
+ 362
+ 363
+ 364
+ 365
+ 366
+ 367
+ 368
+ 369
+ 370
+ 371
+ 372
+ 373
+ 374
+ 375
+ 376
+ 377
+ 378
+ 379
+ 380
+ 381
+ 382
+ 383
+ 384
+ 385
+ 386
+ 387
+ 388
+ 389
+ 390
+ 391
+ 392
+ 393
+ 394
+ 395
+ 396
+ 397
+ 398
+ 399
+ 400
+ 401
+ 402
+ 403
+ 404
+ 405
+ 406
+ 407
+ 408
+ 409
+ 410
+ 411
+ 412
+ 413
+ 414
+ 415
+ 416
+ 417
+ 418
+ 419
+ 420
+ 421
+ 422
+ 423
+ 424
+ 425
+ 426
+ 427
+ 428
+ 429
+ 430
+ 431
+ 432
+ 433
+ 434
+ 435
+ 436
+ 437
+ 438
+ 439
+ 440
+ 441
+ 442
+ 443
+ 444
+ 445
+ 446
+ 447
+ 448
+ 449
+ 450
+ 451
+ 452
+ 453
+ 454
+ 455
+ 456
+ 457
+ 458
+ 459
+ 460
+ 461
+ 462
+ 463
+ 464
+ 465
+ 466
+ 467
+ 468
+ 469
+ 470
+ 471
+ 472
+ 473
+ 474
+ 475
+ 476
+ 477
+ 478
+ 479
+ 480
+ 481
+ 482
+ 483
+ 484
+ 485
+ 486
+ 487
+ 488
+ 489
+ 490
+ 491
+ 492
+ 493
+ 494
+ 495
+ 496
+ 497
+ 498
+ 499
+ 500
+ 501
+ 502
+ 503
+ 504
+ 505
+ 506
+ 507
+ 508
+ 509
+ 510
+ 511
+ 512
+ 513
+ 514
+ 515
+ 516
+ 517
+ 518
+ 519
+ 520
+ 521
+ 522
+ 523
+ 524
+ 525
+ 526
+ 527
+ 528
+ 529
+ 530
+ 531
+ 532
+ 533
+ 534
+ 535
+ 536
+ 537
+ 538
+ 539
+ 540
+ 541
+ 542
+ 543
+ 544
+ 545
+ 546
+ 547
+ 548
+ 549
+ 550
+ 551
+ 552
+ 553
+ 554
+ 555
+ 556
+ 557
+ 558
+ 559
+ 560
+ 561
+ 562
+ 563
+ 564
+ 565
+ 566
+ 567
+ 568
+ 569
+ 570
+ 571
+ 572
+ 573
+ 574
+ 575
+ 576
+ 577
+ 578
+ 579
+ 580
+ 581
+ 582
+ 583
+ 584
+ 585
+ 586
+ 587
+ 588
+ 589
+ 590
+ 591
+ 592
+ 593
+ 594
+ 595
+ 596
+ 597
+ 598
+ 599
+ 600
+ 601
+ 602
+ 603
+ 604
+ 605
+ 606
+ 607
+ 608
+ 609
+ 610
+ 611
+ 612
+ 613
+ 614
+ 615
+ 616
+ 617
+ 618
+ 619
+ 620
+ 621
+ 622
+ 623
+ 624
+ 625
+ 626
+ 627
+ 628
+ 629
+ 630
+ 631
+ 632
+ 633
+ 634
+ 635
+ 636
+ 637
+ 638
+ 639
+ 640
+ 641
+ 642
+ 643
+ 644
+ 645
+ 646
+ 647
+ 648
+ 649
+ 650
+ 651
+ 652
+ 653
+ 654
+ 655
+ 656
+ 657
+ 658
+ 659
+ 660
+ 661
+ 662
+ 663
+ 664
+ 665
+ 666
+ 667
+ 668
+ 669
+ 670
+ 671
+ 672
+ 673
+ 674
+ 675
+ 676
+ 677
+ 678
+ 679
+ 680
+ 681
+ 682
+ 683
+ 684
+ 685
+ 686
+ 687
+ 688
+ 689
+ 690
+ 691
+ 692
+ 693
+ 694
+ 695
+ 696
+ 697
+ 698
+ 699
+ 700
+ 701
+ 702
+ 703
+ 704
+ 705
+ 706
+ 707
+ 708
+ 709
+ 710
+ 711
+ 712
+ 713
+ 714
+ 715
+ 716
+ 717
+ 718
+ 719
+ 720
+ 721
+ 722
+ 723
+ 724
+ 725
+ 726
+ 727
+ 728
+ 729
+ 730
+ 731
+ 732
+ 733
+ 734
+ 735
+ 736
+ 737
+ 738
+ 739
+ 740
+ 741
+ 742
+ 743
+ 744
+ 745
+ 746
+ 747
+ 748
+ 749
+ 750
+ 751
+ 752
+ 753
+ 754
+ 755
+ 756
+ 757
+ 758
+ 759
+ 760
+ 761
+ 762
+ 763
+ 764
+ 765
+ 766
+ 767
+ 768
+ 769
+ 770
+ 771
+ 772
+ 773
+ 774
+ 775
+ 776
+ 777
+ 778
+ 779
+ 780
+ 781
+ 782
+ 783
+ 784
+ 785
+ 786
+ 787
+ 788
+ 789
+ 790
+ 791
+ 792
+ 793
+ 794
+ 795
+ 796
+ 797
+ 798
+ 799
+ 800
+ 801
+ 802
+ 803
+ 804
+ 805
+ 806
+ 807
+ 808
+ 809
+ 810
+ 811
+ 812
+ 813
+ 814
+ 815
+ 816
+ 817
+ 818
+ 819
+ 820
+ 821
+ 822
+ 823
+ 824
+ 825
+ 826
+ 827
+ 828
+ 829
+ 830
+ 831
+ 832
+ 833
+ 834
+ 835
+ 836
+ 837
+ 838
+ 839
+ 840
+ 841
+ 842
+ 843
+ 844
+ 845
+ 846
+ 847
+ 848
+ 849
+ 850
+ 851
+ 852
+ 853
+ 854
+ 855
+ 856
+ 857
+ 858
+ 859
+ 860
+ 861
+ 862
+ 863
+ 864
+ 865
+ 866
+ 867
+ 868
+ 869
+ 870
+ 871
+ 872
+ 873
+ 874
+ 875
+ 876
+ 877
+ 878
+ 879
+ 880
+ 881
+ 882
+ 883
+ 884
+ 885
+ 886
+ 887
+ 888
+ 889
+ 890
+ 891
+ 892
+ 893
+ 894
+ 895
+ 896
+ 897
+ 898
+ 899
+ 900
+ 901
+ 902
+ 903
+ 904
+ 905
+ 906
+ 907
+ 908
+ 909
+ 910
+ 911
+ 912
+ 913
+ 914
+ 915
+ 916
+ 917
+ 918
+ 919
+ 920
+ 921
+ 922
+ 923
+ 924
+ 925
+ 926
+ 927
+ 928
+ 929
+ 930
+ 931
+ 932
+ 933
+ 934
+ 935
+ 936
+ 937
+ 938
+ 939
+ 940
+ 941
+ 942
+ 943
+ 944
+ 945
+ 946
+ 947
+ 948
+ 949
+ 950
+ 951
+ 952
+ 953
+ 954
+ 955
+ 956
+ 957
+ 958
+ 959
+ 960
+ 961
+ 962
+ 963
+ 964
+ 965
+ 966
+ 967
+ 968
+ 969
+ 970
+ 971
+ 972
+ 973
+ 974
+ 975
+ 976
+ 977
+ 978
+ 979
+ 980
+ 981
+ 982
+ 983
+ 984
+ 985
+ 986
+ 987
+ 988
+ 989
+ 990
+ 991
+ 992
+ 993
+ 994
+ 995
+ 996
+ 997
+ 998
+ 999
+1000
+1001
+1002
+1003
+1004
+1005
+1006
+1007
+1008
+1009
+1010
+1011
+1012
+1013
+1014
+1015
+1016
+1017
+1018
+1019
+1020
+1021
+1022
+1023
+1024
+1025
+1026
+1027
+1028
+1029
+1030
+1031
+1032
+1033
+1034
+1035
+1036
+1037
+1038
+1039
+1040
+1041
+1042
+1043
+1044
+1045
+1046
+1047
+1048
+1049
+1050
+1051
+1052
+1053
+1054
+1055
+1056
+1057
+1058
+1059
+1060
+1061
+1062
+1063
+1064
+1065
+1066
+1067
+1068
+1069
+1070
+1071
+1072
+1073
+1074
+1075
+1076
+1077
+1078
+1079
+1080
+1081
+1082
+1083
+1084
+1085
+1086
+1087
+1088
+1089
+1090
+1091
+1092
+1093
+1094
+1095
+1096
+1097
+1098
+1099
+1100
+1101
+1102
+1103
+1104
+1105
+1106
+1107
+1108
+1109
+1110
+1111
+1112
+1113
+1114
+1115
+1116
+1117
+1118
+1119
+1120
+1121
+1122
+1123
+1124
+1125
+1126
+1127
+1128
+1129
+1130
+1131
+1132
+1133
+1134
+1135
+1136
+1137
+1138
+1139
+1140
+1141
+1142
+1143
+1144
+1145
+1146
+1147
+1148
+1149
+1150
+1151
+1152
+1153
+1154
+1155
+1156
+1157
+1158
+1159
+1160
+1161
+1162
+1163
+1164
+1165
+1166
+1167
+1168
+1169
+1170
+1171
+1172
+1173
+1174
+1175
+1176
+1177
+1178
+1179
+1180
+1181
+1182
+1183
+1184
+1185
+1186
+1187
+1188
+1189
+1190
+1191
+1192
+1193
+1194
+1195
+1196
+1197
+1198
+1199
+1200
+1201
+1202
+1203
+1204
+1205
+1206
+1207
+1208
+1209
+1210
+1211
+1212
+1213
+1214
+1215
+1216
+1217
+1218
+1219
+1220
+1221
+1222
+1223
+1224
+1225
+1226
+1227
+1228
+1229
+1230
+1231
+1232
+1233
+1234
+1235
+1236
+1237
+1238
+1239
+1240
+1241
+1242
+1243
+1244
+1245
+1246
+1247
+1248
+1249
+1250
+1251
+1252
+1253
+1254
+1255
+1256
+1257
+1258
+1259
+1260
+1261
+1262
+1263
+1264
+1265
+1266
+1267
+1268
+1269
+1270
+1271
+1272
+1273
+1274
+1275
+1276
+1277
+1278
+1279
+1280
+1281
+1282
+1283
+1284
+1285
+1286
+1287
+1288
+1289
+1290
+1291
+1292
+1293
+1294
+1295
+1296
+1297
+1298
+1299
+1300
+1301
+1302
+1303
+1304
+1305
+1306
+1307
+1308
+1309
+1310
+1311
+1312
+1313
+1314
+1315
+1316
+1317
+1318
+1319
+1320
+1321
+1322
+1323
+1324
+1325
+1326
+1327
+1328
+1329
+1330
+1331
+1332
+1333
+1334
+1335
+1336
+1337
+1338
+1339
+1340
+1341
+1342
+1343
+1344
+1345
+1346
+1347
+1348
+1349
+1350
+1351
+1352
+1353
+1354
+1355
+1356
+1357
+1358
+1359
+1360
+1361
+1362
+1363
+1364
+1365
+1366
+1367
+1368
+1369
+1370
+1371
+1372
+1373
+1374
+1375
+1376
+1377
+1378
+1379
+1380
+1381
+1382
+1383
+1384
+1385
+1386
+1387
+1388
+1389
+1390
+1391
+1392
+1393
+1394
+1395
+1396
+1397
+1398
+1399
+1400
+1401
+1402
+1403
+1404
+1405
+1406
+1407
+1408
+1409
+1410
+1411
+1412
+1413
+1414
+1415
+1416
+1417
+1418
+1419
+1420
+1421
+1422
+1423
+1424
+1425
+1426
+1427
+1428
+1429
+1430
+1431
+1432
+1433
+1434
+1435
+1436
+1437
+1438
+1439
+1440
+1441
+1442
+1443
+1444
+1445
+1446
+1447
+1448
+1449
+1450
+1451
+1452
+1453
+1454
+1455
+1456
+1457
+1458
+1459
+1460
+1461
+1462
+1463
+1464
+1465
+1466
+1467
+1468
+1469
+1470
+1471
+1472
+1473
+1474
+1475
+1476
+1477
+1478
+1479
+1480
+1481
+1482
+1483
+1484
+1485
+1486
+1487
+1488
+1489
+1490
+1491
+1492
+1493
+1494
+1495
+1496
+1497
+1498
+1499
+1500
+1501
+1502
+1503
+1504
+1505
+1506
+1507
+1508
+1509
+1510
+1511
+1512
+1513
+1514
+1515
+1516
+1517
+1518
+1519
+1520
+1521
+1522
+1523
+1524
+1525
+1526
+1527
+1528
+1529
+1530
+1531
+1532
+1533
+1534
+1535
+1536
+1537
+1538
+1539
+1540
+1541
+1542
+1543
+1544
+1545
+1546
+1547
+1548
+1549
+1550
+1551
+1552
+1553
+1554
+1555
+1556
+1557
+1558
+1559
+1560
+1561
+1562
+1563
+1564
+1565
+1566
+1567
+1568
+1569
+1570
+1571
+1572
+1573
+1574
+1575
+1576
+1577
+1578
+1579
+1580
+1581
+1582
+1583
+1584
+1585
+1586
+1587
+1588
+1589
+1590
+1591
+1592
+1593
+1594
+1595
+1596
+1597
+1598
+1599
+1600
+1601
+1602
+1603
+1604
+1605
+1606
+1607
+1608
+1609
+1610
+1611
+1612
+1613
+1614
+1615
+1616
+1617
+1618
+1619
+1620
+1621
+1622
+1623
+1624
+1625
+1626
+1627
+1628
+1629
+1630
+1631
+1632
+1633
+1634
+1635
+1636
+1637
+1638
+1639
+1640
+1641
+1642
+1643
+1644
+1645
+1646
+1647
+1648
+1649
+1650
+1651
+1652
+1653
+1654
+1655
+1656
+1657
+1658
+1659
+1660
+1661
+1662
+1663
+1664
+1665
+1666
+1667
+1668
+1669
+1670
+1671
+1672
+1673
+1674
+1675
+1676
+1677
+1678
+1679
+1680
+1681
+1682
+1683
+1684
+1685
+1686
+1687
+1688
+1689
+1690
+1691
+1692
+1693
+1694
+1695
+1696
+1697
+1698
+1699
+1700
+1701
+1702
+1703
+1704
+1705
+1706
+1707
+1708
+1709
+1710
+1711
+1712
+1713
+1714
+1715
+1716
+1717
+1718
+1719
+1720
+1721
+1722
+1723
+1724
+1725
+1726
+1727
+1728
+1729
+1730
+1731
+1732
+1733
+1734
+1735
+1736
+1737
+1738
+1739
+1740
+1741
+1742
+1743
+1744
+1745
+1746
+1747
+1748
+1749
+1750
+1751
+1752
+1753
+1754
+1755
+1756
+1757
+1758
+1759
+1760
+1761
+1762
+1763
+1764
+1765
+1766
+1767
+1768
+1769
+1770
+1771
+1772
+1773
+1774
+1775
+1776
+1777
+1778
+1779
+1780
+1781
+1782
+1783
+1784
+1785
+1786
+1787
+1788
+1789
+1790
+1791
+1792
+1793
+1794
+1795
+1796
+1797
+1798
+1799
+1800
+1801
+1802
+1803
+1804
+1805
+1806
+1807
+1808
+1809
+1810
+1811
+1812
+1813
+1814
+1815
+1816
+1817
+1818
+1819
+1820
+1821
+1822
+1823
+1824
+1825
+1826
+1827
+1828
+1829
+1830
+1831
+1832
+1833
+1834
+1835
+1836
+1837
+1838
+1839
+1840
+1841
+1842
+1843
+1844
+1845
+1846
+1847
+1848
+1849
+1850
+1851
+1852
+1853
+1854
+1855
+1856
+1857
+1858
+1859
+1860
+1861
+1862
+1863
+1864
+1865
+1866
+1867
+1868
+1869
+1870
+1871
+1872
+1873
+1874
+1875
+1876
+1877
+1878
+1879
+1880
+1881
+1882
+1883
+1884
+1885
+1886
+1887
+1888
+1889
+1890
+1891
+1892
+1893
+1894
+1895
+1896
+1897
+1898
+1899
+1900
+1901
+1902
+1903
+1904
+1905
+1906
+1907
+1908
+1909
+1910
+1911
+1912
+1913
+1914
+1915
+1916
+1917
+1918
+1919
+1920
+1921
+1922
+1923
+1924
+1925
+1926
+1927
+1928
+1929
+1930
+1931
+1932
+1933
+1934
+1935
+1936
+1937
+1938
+1939
+1940
+1941
+1942
+1943
+1944
+1945
+1946
+1947
+1948
+1949
+1950
+1951
+1952
+1953
+1954
+1955
+1956
+1957
+1958
+1959
+1960
+1961
+1962
+1963
+1964
+1965
+1966
+1967
+1968
+1969
+1970
+1971
+1972
+1973
+1974
+1975
+1976
+1977
+1978
+1979
+1980
+1981
+1982
+1983
+1984
+1985
+1986
+1987
+1988
+1989
+1990
+1991
+1992
+1993
+1994
+1995
+1996
+1997
+1998
+1999
+2000
+2001
+2002
+2003
+2004
+2005
+2006
+2007
+2008
+2009
+2010
+2011
+2012
+2013
+2014
+2015
+2016
+2017
+2018
+2019
+2020
+2021
+2022
+2023
+2024
+2025
+2026
+2027
+2028
+2029
+2030
+2031
+2032
+2033
+2034
+2035
+2036
+2037
+2038
+2039
+2040
+2041
+2042
+2043
+2044
+2045
+2046
+2047
+2048
+2049
+2050
+2051
+2052
+2053
+2054
+2055
+2056
+2057
+2058
+2059
+2060
+2061
+2062
+2063
+2064
+2065
+2066
+2067
+2068
+2069
+2070
+2071
+2072
+2073
+2074
+2075
+2076
+2077
+2078
+2079
+2080
+2081
+2082
+2083
+2084
+2085
+2086
+2087
+2088
+2089
+2090
+2091
+2092
+2093
+2094
+2095
+2096
+2097
+2098
+2099
+2100
+2101
+2102
+2103
+2104
+2105
+2106
+2107
+2108
+2109
+2110
+2111
+2112
+2113
+2114
+2115
+2116
+2117
+2118
+2119
+2120
+2121
+2122
+2123
+2124
+2125
+2126
+2127
+2128
+2129
+2130
+2131
+2132
+2133
+2134
+2135
+2136
+2137
+2138
+2139
+2140
+2141
+2142
+2143
+2144
+2145
+2146
+2147
+2148
+2149
+2150
+2151
+2152
+2153
+2154
+2155
+2156
+2157
+2158
+2159
+2160
+2161
+2162
+2163
+2164
+2165
+2166
+2167
+2168
+2169
+2170
+2171
+2172
+2173
+2174
+2175
+2176
+2177
+2178
+2179
+2180
+2181
+2182
+2183
+2184
+2185
+2186
+2187
+2188
+2189
+2190
+2191
+2192
+2193
+2194
+2195
+2196
+2197
+2198
+2199
+2200
+2201
+2202
+2203
+2204
+2205
+2206
+2207
+2208
+2209
+2210
+2211
+2212
+2213
+2214
+2215
+2216
+2217
+2218
+2219
+2220
+2221
+2222
+2223
+2224
+2225
+2226
+2227
+2228
+2229
+2230
+2231
+2232
+2233
+2234
+2235
+2236
+2237
+2238
+2239
+2240
+2241
+2242
+2243
+2244
+2245
+2246
+2247
+2248
+2249
+2250
+2251
+2252
+2253
+2254
+2255
+2256
+2257
+2258
+2259
+2260
+2261
+2262
+2263
+2264
+2265
+2266
+2267
+2268
+2269
+2270
+2271
+2272
+2273
+2274
+2275
+2276
+2277
+2278
+2279
+2280
+2281
+2282
+2283
+2284
+2285
+2286
+2287
+2288
+2289
+2290
+2291
+2292
+2293
+2294
+2295
+2296
+2297
+2298
+2299
+2300
+2301
+2302
+2303
+2304
+2305
+2306
+2307
+2308
+2309
+2310
+2311
+2312
+2313
+2314
+2315
+2316
+2317
+2318
+2319
+2320
+2321
+2322
+2323
+2324
+2325
+2326
+2327
+2328
+2329
+2330
+2331
+2332
+2333
+2334
+2335
+2336
+2337
+2338
+2339
+2340
+2341
+2342
+2343
+2344
+2345
+2346
+2347
+2348
+2349
+2350
+2351
+2352
+2353
+2354
+2355
+2356
+2357
+2358
+2359
+2360
+2361
+2362
+2363
+2364
+2365
+2366
+2367
+2368
+2369
+2370
+2371
+2372
+2373
+2374
+2375
+2376
+2377
+2378
+2379
+2380
+2381
+2382
+2383
+2384
+2385
+2386
+2387
+2388
+2389
+2390
+2391
+2392
+2393
+2394
+2395
+2396
+2397
+2398
+2399
+2400
+2401
+2402
+2403
+2404
+2405
+2406
+2407
+2408
+2409
+2410
+2411
+2412
+2413
+2414
+2415
+2416
+2417
+2418
+2419
+2420
+2421
+2422
+2423
+2424
+2425
+2426
+2427
+2428
+2429
+2430
+2431
+2432
+2433
+2434
+2435
+2436
+2437
+2438
+2439
+2440
+2441
+2442
+2443
+2444
+2445
+2446
+2447
+2448
+2449
+2450
+2451
+2452
+2453
+2454
+2455
+2456
+2457
+2458
+2459
+2460
+2461
+2462
+2463
+2464
+2465
+2466
+2467
+2468
+2469
+2470
+2471
+2472
+2473
+2474
+2475
+2476
+2477
+2478
+2479
+2480
+2481
+2482
+2483
+2484
+2485
+2486
+2487
+2488
+2489
+2490
+2491
+2492
+2493
+2494
+2495
+2496
+2497
+2498
+2499
+2500
+2501
+2502
+2503
+2504
+2505
+2506
+2507
+2508
+2509
+2510
+2511
+2512
+2513
+2514
+2515
+2516
+2517
+2518
+2519
+2520
+2521
+2522
+2523
+2524
+2525
+2526
+2527
+2528
+2529
+2530
+2531
+2532
+2533
+2534
+2535
+2536
+2537
+2538
+2539
+2540
+2541
+2542
+2543
+2544
+2545
+2546
+2547
+2548
+2549
+2550
+2551
+2552
+2553
+2554
+2555
+2556
+2557
+2558
+2559
+2560
+2561
+2562
+2563
+2564
+2565
+2566
+2567
+2568
+2569
+2570
+2571
+2572
+2573
+2574
+2575
+2576
+2577
+2578
+2579
+2580
+2581
+2582
+2583
+2584
+2585
+2586
+2587
+2588
+2589
+2590
+2591
+2592
+2593
+2594
+2595
+2596
+2597
+2598
+2599
+2600
+2601
+2602
+2603
+2604
+2605
+2606
+2607
+2608
+2609
+2610
+2611
+2612
+2613
+2614
+2615
+2616
+2617
+2618
+2619
+2620
+2621
+2622
+2623
+2624
+2625
+2626
+2627
+2628
+2629
+2630
+2631
+2632
+2633
+2634
+2635
+2636
+2637
+2638
+2639
+2640
+2641
+2642
+2643
+2644
+2645
+2646
+2647
+2648
+2649
+2650
+2651
+2652
+2653
+2654
+2655
+2656
+2657
+2658
+2659
+2660
+2661
+2662
+2663
+2664
+2665
+2666
+2667
+2668
+2669
+2670
+2671
+2672
+2673
+2674
+2675
+2676
+2677
+2678
+2679
+2680
+2681
+2682
+2683
+2684
+2685
+2686
+2687
+2688
+2689
+2690
+2691
+2692
+2693
+2694
+2695
+2696
+2697
+2698
+2699
+2700
+2701
+2702
+2703
+2704
+2705
+2706
+2707
+2708
+2709
+2710
+2711
+2712
+2713
+2714
+2715
+2716
+2717
+2718
+2719
+2720
+2721
+2722
+2723
+2724
+2725
+2726
+2727
+2728
+2729
+2730
+2731
+2732
+2733
+2734
+2735
+2736
+2737
+2738
+2739
+2740
+2741
+2742
+2743
+2744
+2745
+2746
+2747
+2748
+2749
+2750
+2751
+2752
+2753
+2754
+2755
+2756
+2757
+2758
+2759
+2760
+2761
+2762
+2763
+2764
+2765
+2766
+2767
+2768
+2769
+2770
+2771
+2772
+2773
+2774
+2775
+2776
+2777
+2778
+2779
+2780
+2781
+2782
+2783
+2784
+2785
+2786
+2787
+2788
+2789
+2790
+2791
+2792
+2793
+2794
+2795
+2796
+2797
+2798
+2799
+2800
+2801
+2802
+2803
+2804
+2805
+2806
+2807
+2808
+2809
+2810
+2811
+2812
+2813
+2814
+2815
+2816
+2817
+2818
+2819
+2820
+2821
+2822
+2823
+2824
+2825
+2826
+2827
+2828
+2829
+2830
+2831
+2832
+2833
+2834
+2835
+2836
+2837
+2838
+2839
+2840
+2841
+2842
+2843
+2844
+2845
+2846
+2847
+2848
+2849
+2850
+2851
+2852
+2853
+2854
+2855
+2856
+2857
+2858
+2859
+2860
+2861
+2862
+2863
+2864
+2865
+2866
+2867
+2868
+2869
+2870
+2871
+2872
+2873
+2874
+2875
+2876
+2877
+2878
+2879
+2880
+2881
+2882
+2883
+2884
+2885
+2886
+2887
+2888
+2889
+2890
+2891
+2892
+2893
+2894
+2895
+2896
+2897
+2898
+2899
+2900
+2901
+2902
+2903
+2904
+2905
+2906
+2907
+2908
+2909
+2910
+2911
+2912
+2913
+2914
+2915
+2916
+2917
+2918
+2919
+2920
+2921
+2922
+2923
+2924
+2925
+2926
+2927
+2928
+2929
+2930
+2931
+2932
+2933
+2934
+2935
+2936
+2937
+2938
+2939
+2940
+2941
+2942
+2943
+2944
+2945
+2946
+2947
+2948
+2949
+2950
+2951
+2952
+2953
+2954
+2955
+2956
+2957
+2958
+2959
+2960
+2961
+2962
+2963
+2964
+2965
+2966
+2967
+2968
+2969
+2970
+2971
+2972
+2973
+2974
+2975
+2976
+2977
+2978
+2979
+2980
+2981
+2982
+2983
+2984
+2985
+2986
+2987
+2988
+2989
+2990
+2991
+2992
+2993
+2994
+2995
+2996
+2997
+2998
+2999
+3000
+3001
+3002
+3003
+3004
+3005
+3006
+3007
+3008
+3009
+3010
+3011
+3012
+3013
+3014
+3015
+3016
+3017
+3018
+3019
+3020
+3021
+3022
+3023
+3024
+3025
+3026
+3027
+3028
+3029
+3030
+3031
+3032
+3033
+3034
+3035
+3036
+3037
+3038
+3039
+3040
+3041
+3042
+3043
+3044
+3045
+3046
+3047
+3048
+3049
+3050
+3051
+3052
+3053
+3054
+3055
+3056
+3057
+3058
+3059
+3060
+3061
+3062
+3063
+3064
+3065
+3066
+3067
+3068
+3069
+3070
+3071
+3072
+3073
+3074
+3075
+3076
+3077
+3078
+3079
+3080
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/* Copyright (C) 1998, 2002 the Free Software Foundation
+ * Copyright (C) 2012-2021 MATE Developers
+ *
+ * This file is part of MATE Utils.
+ *
+ * MATE Utils is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * MATE Utils is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MATE Utils.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ *   Dennis Cranston <dennis_cranston@yahoo.com>
+ *   George Lebl
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <fnmatch.h>
+#ifndef FNM_CASEFOLD
+#define FNM_CASEFOLD 0
+#endif
+
+#include <string.h>
+#include <signal.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <sys/wait.h>
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gdk/gdk.h>
+#include <gio/gio.h>
+
+#ifdef ENABLE_NLS
+#include <locale.h>
+#endif /* ENABLE_NLS */
+
+#include "gsearchtool.h"
+#include "gsearchtool-callbacks.h"
+#include "gsearchtool-support.h"
+#include "gsearchtool-entry.h"
+
+#define MATE_SEARCH_TOOL_DEFAULT_ICON_SIZE 16
+#define MATE_SEARCH_TOOL_REFRESH_DURATION  50000
+#define LEFT_LABEL_SPACING "     "
+
+static GObjectClass * parent_class;
+
+typedef enum {
+	SEARCH_CONSTRAINT_TYPE_BOOLEAN,
+	SEARCH_CONSTRAINT_TYPE_NUMERIC,
+	SEARCH_CONSTRAINT_TYPE_TEXT,
+	SEARCH_CONSTRAINT_TYPE_DATE_BEFORE,
+	SEARCH_CONSTRAINT_TYPE_DATE_AFTER,
+	SEARCH_CONSTRAINT_TYPE_SEPARATOR,
+	SEARCH_CONSTRAINT_TYPE_NONE
+} GSearchConstraintType;
+
+typedef struct _GSearchOptionTemplate GSearchOptionTemplate;
+
+struct _GSearchOptionTemplate {
+	GSearchConstraintType type; /* The available option type */
+	gchar * option;             /* An option string to pass to the command */
+	gchar * desc;               /* The description for display */
+	gchar * units;              /* Optional units for display */
+	gboolean is_selected;
+};
+
+static GSearchOptionTemplate GSearchOptionTemplates[] = {
+	{ SEARCH_CONSTRAINT_TYPE_TEXT, NULL, N_("Contains the _text"), NULL, FALSE },
+	{ SEARCH_CONSTRAINT_TYPE_SEPARATOR, NULL, NULL, NULL, TRUE },
+	{ SEARCH_CONSTRAINT_TYPE_DATE_BEFORE, "-mtime -%d", N_("_Date modified less than"), N_("days"), FALSE },
+	{ SEARCH_CONSTRAINT_TYPE_DATE_AFTER, "\\( -mtime +%d -o -mtime %d \\)", N_("Date modified more than"), N_("days"), FALSE },
+	{ SEARCH_CONSTRAINT_TYPE_SEPARATOR, NULL, NULL, NULL, TRUE },
+	{ SEARCH_CONSTRAINT_TYPE_NUMERIC, "\\( -size %uc -o -size +%uc \\)", N_("S_ize at least"), N_("kilobytes"), FALSE },
+	{ SEARCH_CONSTRAINT_TYPE_NUMERIC, "\\( -size %uc -o -size -%uc \\)", N_("Si_ze at most"), N_("kilobytes"), FALSE },
+	{ SEARCH_CONSTRAINT_TYPE_BOOLEAN, "-size 0c \\( -type f -o -type d \\)", N_("File is empty"), NULL, FALSE },
+	{ SEARCH_CONSTRAINT_TYPE_SEPARATOR, NULL, NULL, NULL, TRUE },
+	{ SEARCH_CONSTRAINT_TYPE_TEXT, "-user '%s'", N_("Owned by _user"), NULL, FALSE },
+	{ SEARCH_CONSTRAINT_TYPE_TEXT, "-group '%s'", N_("Owned by _group"), NULL, FALSE },
+	{ SEARCH_CONSTRAINT_TYPE_BOOLEAN, "\\( -nouser -o -nogroup \\)", N_("Owner is unrecognized"), NULL, FALSE },
+	{ SEARCH_CONSTRAINT_TYPE_SEPARATOR, NULL, NULL, NULL, TRUE },
+	{ SEARCH_CONSTRAINT_TYPE_TEXT, "'!' -name '*%s*'", N_("Na_me does not contain"), NULL, FALSE },
+	{ SEARCH_CONSTRAINT_TYPE_TEXT, "-regex '%s'", N_("Name matches regular e_xpression"), NULL, FALSE },
+	{ SEARCH_CONSTRAINT_TYPE_SEPARATOR, NULL, NULL, NULL, TRUE },
+	{ SEARCH_CONSTRAINT_TYPE_BOOLEAN, "SHOW_HIDDEN_FILES", N_("Show hidden and backup files"), NULL, FALSE },
+	{ SEARCH_CONSTRAINT_TYPE_BOOLEAN, "-follow", N_("Follow symbolic links"), NULL, FALSE },
+	{ SEARCH_CONSTRAINT_TYPE_BOOLEAN, "EXCLUDE_OTHER_FILESYSTEMS", N_("Exclude other filesystems"), NULL, FALSE },
+	{ SEARCH_CONSTRAINT_TYPE_NONE, NULL, NULL, NULL, FALSE}
+};
+
+enum {
+	SEARCH_CONSTRAINT_CONTAINS_THE_TEXT,
+	SEARCH_CONSTRAINT_TYPE_SEPARATOR_00,
+	SEARCH_CONSTRAINT_DATE_MODIFIED_BEFORE,
+	SEARCH_CONSTRAINT_DATE_MODIFIED_AFTER,
+	SEARCH_CONSTRAINT_TYPE_SEPARATOR_01,
+	SEARCH_CONSTRAINT_SIZE_IS_MORE_THAN,
+	SEARCH_CONSTRAINT_SIZE_IS_LESS_THAN,
+	SEARCH_CONSTRAINT_FILE_IS_EMPTY,
+	SEARCH_CONSTRAINT_TYPE_SEPARATOR_02,
+	SEARCH_CONSTRAINT_OWNED_BY_USER,
+	SEARCH_CONSTRAINT_OWNED_BY_GROUP,
+	SEARCH_CONSTRAINT_OWNER_IS_UNRECOGNIZED,
+	SEARCH_CONSTRAINT_TYPE_SEPARATOR_03,
+	SEARCH_CONSTRAINT_FILE_IS_NOT_NAMED,
+	SEARCH_CONSTRAINT_FILE_MATCHES_REGULAR_EXPRESSION,
+	SEARCH_CONSTRAINT_TYPE_SEPARATOR_04,
+	SEARCH_CONSTRAINT_SHOW_HIDDEN_FILES_AND_FOLDERS,
+	SEARCH_CONSTRAINT_FOLLOW_SYMBOLIC_LINKS,
+	SEARCH_CONSTRAINT_SEARCH_OTHER_FILESYSTEMS,
+	SEARCH_CONSTRAINT_MAXIMUM_POSSIBLE
+};
+
+static GtkTargetEntry GSearchDndTable[] = {
+	{ "text/uri-list", 0, 1 },
+	{ "text/plain",    0, 0 },
+	{ "STRING",        0, 0 }
+};
+
+static guint GSearchTotalDnds = sizeof (GSearchDndTable) / sizeof (GSearchDndTable[0]);
+
+struct _GSearchGOptionArguments {
+	gchar * name;
+	gchar * path;
+	gchar * contains;
+	gchar * user;
+	gchar * group;
+	gboolean nouser;
+	gchar * mtimeless;
+	gchar * mtimemore;
+	gchar * sizeless;
+	gchar * sizemore;
+	gboolean empty;
+	gchar * notnamed;
+	gchar * regex;
+	gboolean hidden;
+	gboolean follow;
+	gboolean mounts;
+	gchar * sortby;
+	gboolean descending;
+	gboolean start;
+} GSearchGOptionArguments;
+
+static GOptionEntry GSearchGOptionEntries[] = {
+	{ "version", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, version_cb, N_("Show version of the application"), NULL},
+	{ "named", 0, 0, G_OPTION_ARG_STRING, &GSearchGOptionArguments.name, NULL, N_("STRING") },
+	{ "path", 0, 0, G_OPTION_ARG_STRING, &GSearchGOptionArguments.path, NULL, N_("PATH") },
+	{ "sortby", 0, 0, G_OPTION_ARG_STRING, &GSearchGOptionArguments.sortby, NULL, N_("VALUE") },
+	{ "descending", 0, 0, G_OPTION_ARG_NONE, &GSearchGOptionArguments.descending, NULL, NULL },
+	{ "start", 0, 0, G_OPTION_ARG_NONE, &GSearchGOptionArguments.start, NULL, NULL },
+	{ "contains", 0, 0, G_OPTION_ARG_STRING, &GSearchGOptionArguments.contains, NULL, N_("STRING") },
+	{ "mtimeless", 0, 0, G_OPTION_ARG_STRING, &GSearchGOptionArguments.mtimeless, NULL, N_("DAYS") },
+	{ "mtimemore", 0, 0, G_OPTION_ARG_STRING, &GSearchGOptionArguments.mtimemore, NULL, N_("DAYS") },
+	{ "sizemore", 0, 0, G_OPTION_ARG_STRING, &GSearchGOptionArguments.sizemore, NULL, N_("KILOBYTES") },
+	{ "sizeless", 0, 0, G_OPTION_ARG_STRING, &GSearchGOptionArguments.sizeless, NULL, N_("KILOBYTES") },
+	{ "empty", 0, 0, G_OPTION_ARG_NONE, &GSearchGOptionArguments.empty, NULL, NULL },
+	{ "user", 0, 0, G_OPTION_ARG_STRING, &GSearchGOptionArguments.user, NULL, N_("USER") },
+	{ "group", 0, 0, G_OPTION_ARG_STRING, &GSearchGOptionArguments.group, NULL, N_("GROUP") },
+	{ "nouser", 0, 0, G_OPTION_ARG_NONE, &GSearchGOptionArguments.nouser, NULL, NULL },
+	{ "notnamed", 0, 0, G_OPTION_ARG_STRING, &GSearchGOptionArguments.notnamed, NULL, N_("STRING") },
+	{ "regex", 0, 0, G_OPTION_ARG_STRING, &GSearchGOptionArguments.regex, NULL, N_("PATTERN") },
+	{ "hidden", 0, 0, G_OPTION_ARG_NONE, &GSearchGOptionArguments.hidden, NULL, NULL },
+	{ "follow", 0, 0, G_OPTION_ARG_NONE, &GSearchGOptionArguments.follow, NULL, NULL },
+	{ "mounts", 0, 0, G_OPTION_ARG_NONE, &GSearchGOptionArguments.mounts, NULL, NULL },
+	{ NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL }
+};
+
+static gchar * find_command_default_name_argument;
+static gchar * locate_command_default_options;
+pid_t locate_database_check_command_pid;
+
+static gboolean
+handle_locate_command_stdout_io (GIOChannel * ioc,
+                                 GIOCondition condition,
+                                 gpointer data)
+{
+	GSearchWindow * gsearch = data;
+	gboolean broken_pipe = FALSE;
+
+	if (condition & G_IO_IN) {
+
+		GError * error = NULL;
+		GString * string;
+
+		string = g_string_new (NULL);
+
+		while (ioc->is_readable != TRUE);
+
+		do {
+			gint status;
+
+			do {
+				status = g_io_channel_read_line_string (ioc, string, NULL, &error);
+
+				if (status == G_IO_STATUS_EOF) {
+					broken_pipe = TRUE;
+				}
+				else if (status == G_IO_STATUS_AGAIN) {
+					if (gtk_events_pending ()) {
+						while (gtk_events_pending ()) {
+							gtk_main_iteration ();
+						}
+					}
+				}
+				else if ((string->len != 0) && (strncmp (string->str, "/", 1) == 0)) {
+					gsearch->is_locate_database_available = TRUE;
+					broken_pipe = TRUE;
+				}
+
+			} while (status == G_IO_STATUS_AGAIN && broken_pipe == FALSE);
+
+			if (broken_pipe == TRUE) {
+				break;
+			}
+
+			if (status != G_IO_STATUS_NORMAL) {
+				if (error != NULL) {
+					g_warning ("handle_locate_command_stdout_io(): %s", error->message);
+					g_error_free (error);
+				}
+			}
+
+		} while (g_io_channel_get_buffer_condition (ioc) & G_IO_IN);
+
+		waitpid (locate_database_check_command_pid, NULL, 0);
+		g_string_free (string, TRUE);
+	}
+
+	if (!(condition & G_IO_IN) || broken_pipe == TRUE) {
+		gsearch->is_locate_database_check_finished = TRUE;
+		g_io_channel_shutdown (ioc, TRUE, NULL);
+		return FALSE;
+	}
+	return TRUE;
+}
+
+static void
+setup_case_insensitive_arguments (GSearchWindow * gsearch)
+{
+	static gboolean case_insensitive_arguments_initialized = FALSE;
+	gchar * cmd_stderr;
+	gchar * grep_cmd;
+	gchar * locate;
+
+	if (case_insensitive_arguments_initialized == TRUE) {
+		return;
+	}
+	case_insensitive_arguments_initialized = TRUE;
+
+	/* check find command for -iname argument compatibility */
+	g_spawn_command_line_sync ("find /dev/null -iname 'string'", NULL, &cmd_stderr, NULL, NULL);
+
+	if ((cmd_stderr != NULL) && (strlen (cmd_stderr) == 0)) {
+		find_command_default_name_argument = g_strdup ("-iname");
+		GSearchOptionTemplates[SEARCH_CONSTRAINT_FILE_IS_NOT_NAMED].option = g_strdup ("'!' -iname '*%s*'");
+	}
+	else {
+		find_command_default_name_argument = g_strdup ("-name");
+	}
+	g_free (cmd_stderr);
+
+	/* check grep command for -i argument compatibility */
+	grep_cmd = g_strdup_printf ("%s -i 'string' /dev/null", GREP_COMMAND);
+ 	g_spawn_command_line_sync (grep_cmd, NULL, &cmd_stderr, NULL, NULL);
+
+	if ((cmd_stderr != NULL) && (strlen (cmd_stderr) == 0)) {
+		g_free (cmd_stderr);
+		g_free (grep_cmd);
+
+		/* check grep command for -I argument compatibility, bug 568840 */
+		grep_cmd = g_strdup_printf ("%s -i -I 'string' /dev/null", GREP_COMMAND);
+	 	g_spawn_command_line_sync (grep_cmd, NULL, &cmd_stderr, NULL, NULL);
+
+		if ((cmd_stderr != NULL) && (strlen (cmd_stderr) == 0)) {
+	 		GSearchOptionTemplates[SEARCH_CONSTRAINT_CONTAINS_THE_TEXT].option =
+			    g_strdup_printf ("'!' -type p -exec %s -i -I -c '%%s' {} \\;", GREP_COMMAND);
+ 		}
+		else {
+	 		GSearchOptionTemplates[SEARCH_CONSTRAINT_CONTAINS_THE_TEXT].option =
+			    g_strdup_printf ("'!' -type p -exec %s -i -c '%%s' {} \\;", GREP_COMMAND);
+		}
+	}
+	else {
+ 		GSearchOptionTemplates[SEARCH_CONSTRAINT_CONTAINS_THE_TEXT].option =
+		    g_strdup_printf ("'!' -type p -exec %s -c '%%s' {} \\;", GREP_COMMAND);
+	}
+	g_free (cmd_stderr);
+
+	locate = g_find_program_in_path ("locate");
+
+	if (locate != NULL) {
+		GIOChannel * ioc_stdout;
+		gchar ** argv  = NULL;
+		gchar *command = NULL;
+		gint child_stdout;
+
+		/* check locate command for -i argument compatibility */
+		command = g_strconcat (locate, " -i /", NULL);
+		g_shell_parse_argv (command, NULL, &argv, NULL);
+		g_free (command);
+
+		gsearch->is_locate_database_check_finished = FALSE;
+		gsearch->is_locate_database_available = FALSE;
+
+		/* run locate command asynchronously because on some systems it can be slow */
+		if (g_spawn_async_with_pipes (g_get_home_dir (), argv, NULL,
+				       G_SPAWN_SEARCH_PATH, NULL, NULL,
+				       &locate_database_check_command_pid, NULL, &child_stdout,
+				       NULL, NULL)) {
+
+			ioc_stdout = g_io_channel_unix_new (child_stdout);
+			g_io_channel_set_encoding (ioc_stdout, NULL, NULL);
+			g_io_channel_set_flags (ioc_stdout, G_IO_FLAG_NONBLOCK, NULL);
+			g_io_add_watch (ioc_stdout, G_IO_IN | G_IO_HUP,
+					handle_locate_command_stdout_io, gsearch);
+			g_io_channel_unref (ioc_stdout);
+		}
+		else {
+			gsearch->is_locate_database_check_finished = TRUE;
+		}
+
+		g_strfreev (argv);
+
+		while (gsearch->is_locate_database_check_finished == FALSE) {
+			if (gtk_events_pending ()) {
+				while (gtk_events_pending ()) {
+					gtk_main_iteration ();
+				}
+			}
+		}
+
+		if (gsearch->is_locate_database_available == TRUE) {
+			locate_command_default_options = g_strdup ("-i");
+		}
+		else {
+			/* run locate again to check if it can find anything */
+			command = g_strconcat (locate, " /", NULL);
+			g_shell_parse_argv (command, NULL, &argv, NULL);
+			g_free (command);
+
+			gsearch->is_locate_database_check_finished = FALSE;
+			locate_command_default_options = g_strdup ("");
+
+			/* run locate command asynchronously because on some systems it can be slow */
+			if (g_spawn_async_with_pipes (g_get_home_dir (), argv, NULL,
+					       G_SPAWN_SEARCH_PATH, NULL, NULL,
+					       &locate_database_check_command_pid, NULL, &child_stdout,
+					       NULL, NULL)) {
+
+				ioc_stdout = g_io_channel_unix_new (child_stdout);
+				g_io_channel_set_encoding (ioc_stdout, NULL, NULL);
+				g_io_channel_set_flags (ioc_stdout, G_IO_FLAG_NONBLOCK, NULL);
+				g_io_add_watch (ioc_stdout, G_IO_IN | G_IO_HUP,
+						handle_locate_command_stdout_io, gsearch);
+				g_io_channel_unref (ioc_stdout);
+			}
+			else {
+				gsearch->is_locate_database_check_finished = TRUE;
+			}
+
+			g_strfreev (argv);
+
+			while (gsearch->is_locate_database_check_finished == FALSE) {
+				if (gtk_events_pending ()) {
+					while (gtk_events_pending ()) {
+						gtk_main_iteration ();
+					}
+				}
+			}
+
+			if (gsearch->is_locate_database_available == FALSE) {
+				g_warning (_("A locate database has probably not been created."));
+			}
+		}
+	}
+	else {
+		/* locate is not installed */
+		locate_command_default_options = g_strdup ("");
+		gsearch->is_locate_database_available = FALSE;
+	}
+	g_free (grep_cmd);
+	g_free (locate);
+}
+
+static gchar *
+setup_find_name_options (gchar * file)
+{
+	/* This function builds the name options for the find command.  This in
+	   done to insure that the find command returns hidden files and folders. */
+
+	GString * command;
+	command = g_string_new ("");
+
+	if (strstr (file, "*") == NULL) {
+
+		if ((strlen (file) == 0) || (file[0] != '.')) {
+	 		g_string_append_printf (command, "\\( %s \"*%s*\" -o %s \".*%s*\" \\) ",
+					find_command_default_name_argument, file,
+					find_command_default_name_argument, file);
+		}
+		else {
+			g_string_append_printf (command, "\\( %s \"*%s*\" -o %s \".*%s*\" -o %s \"%s*\" \\) ",
+					find_command_default_name_argument, file,
+					find_command_default_name_argument, file,
+					find_command_default_name_argument, file);
+		}
+	}
+	else {
+		if (file[0] == '.') {
+			g_string_append_printf (command, "\\( %s \"%s\" -o %s \".*%s\" \\) ",
+					find_command_default_name_argument, file,
+					find_command_default_name_argument, file);
+		}
+		else if (file[0] != '*') {
+			g_string_append_printf (command, "%s \"%s\" ",
+					find_command_default_name_argument, file);
+		}
+		else {
+			if ((strlen (file) >= 1) && (file[1] == '.')) {
+				g_string_append_printf (command, "\\( %s \"%s\" -o %s \"%s\" \\) ",
+					find_command_default_name_argument, file,
+					find_command_default_name_argument, &file[1]);
+			}
+			else {
+				g_string_append_printf (command, "\\( %s \"%s\" -o %s \".%s\" \\) ",
+					find_command_default_name_argument, file,
+					find_command_default_name_argument, file);
+			}
+		}
+	}
+	return g_string_free (command, FALSE);
+}
+
+static gboolean
+has_additional_constraints (GSearchWindow * gsearch)
+{
+	GList * list;
+
+	if (gsearch->available_options_selected_list != NULL) {
+
+		for (list = gsearch->available_options_selected_list; list != NULL; list = g_list_next (list)) {
+
+			GSearchConstraint * constraint = list->data;
+
+			switch (GSearchOptionTemplates[constraint->constraint_id].type) {
+			case SEARCH_CONSTRAINT_TYPE_BOOLEAN:
+			case SEARCH_CONSTRAINT_TYPE_NUMERIC:
+			case SEARCH_CONSTRAINT_TYPE_DATE_BEFORE:
+			case SEARCH_CONSTRAINT_TYPE_DATE_AFTER:
+				return TRUE;
+			case SEARCH_CONSTRAINT_TYPE_TEXT:
+				if (strlen (constraint->data.text) > 0) {
+					return TRUE;
+				}
+			default:
+				break;
+			}
+		}
+	}
+	return FALSE;
+}
+
+static void
+display_dialog_character_set_conversion_error (GtkWidget * window,
+                                               gchar * string,
+                                               GError * error)
+{
+	GtkWidget * dialog;
+
+	dialog = gtk_message_dialog_new (GTK_WINDOW (window),
+ 	                                 GTK_DIALOG_DESTROY_WITH_PARENT,
+	                                 GTK_MESSAGE_ERROR,
+	                                 GTK_BUTTONS_OK,
+	                                 _("Character set conversion failed for \"%s\""),
+					 string);
+
+	gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+	                                          (error == NULL) ? " " : error->message, NULL);
+
+	gtk_window_set_title (GTK_WINDOW (dialog), "");
+	gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
+	gtk_box_set_spacing (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), 14);
+
+	g_signal_connect (dialog, "response",
+	                  G_CALLBACK (gtk_widget_destroy),
+	                  NULL);
+
+	gtk_widget_show (dialog);
+}
+
+static void
+start_animation (GSearchWindow * gsearch, gboolean first_pass)
+{
+	if (first_pass == TRUE) {
+
+		gchar *title = NULL;
+
+		title = g_strconcat (_("Searching..."), " - ", _("Search for Files"), NULL);
+		gtk_window_set_title (GTK_WINDOW (gsearch->window), title);
+
+		gtk_label_set_text (GTK_LABEL (gsearch->files_found_label), "");
+		if (g_settings_get_boolean (gsearch->mate_desktop_interface_settings, "enable-animations")) {
+			gtk_spinner_start (GTK_SPINNER (gsearch->progress_spinner));
+			gtk_widget_show (gsearch->progress_spinner);
+		}
+		g_free (title);
+
+		gsearch->focus = gtk_window_get_focus (GTK_WINDOW (gsearch->window));
+
+		gtk_window_set_default (GTK_WINDOW (gsearch->window), gsearch->stop_button);
+		gtk_widget_show (gsearch->stop_button);
+		gtk_widget_set_sensitive (gsearch->stop_button, TRUE);
+		gtk_widget_hide (gsearch->find_button);
+		gtk_widget_set_sensitive (gsearch->find_button, FALSE);
+		gtk_widget_set_sensitive (gsearch->search_results_vbox, TRUE);
+		gtk_widget_set_sensitive (GTK_WIDGET (gsearch->search_results_tree_view), TRUE);
+		gtk_widget_set_sensitive (gsearch->available_options_vbox, FALSE);
+		gtk_widget_set_sensitive (gsearch->show_more_options_expander, FALSE);
+		gtk_widget_set_sensitive (gsearch->name_and_folder_table, FALSE);
+	}
+}
+
+static void
+stop_animation (GSearchWindow * gsearch)
+{
+	gtk_spinner_stop (GTK_SPINNER (gsearch->progress_spinner));
+
+	gtk_window_set_default (GTK_WINDOW (gsearch->window), gsearch->find_button);
+	gtk_widget_set_sensitive (gsearch->available_options_vbox, TRUE);
+	gtk_widget_set_sensitive (gsearch->show_more_options_expander, TRUE);
+	gtk_widget_set_sensitive (gsearch->name_and_folder_table, TRUE);
+	gtk_widget_set_sensitive (gsearch->find_button, TRUE);
+	gtk_widget_hide (gsearch->progress_spinner);
+	gtk_widget_hide (gsearch->stop_button);
+	gtk_widget_show (gsearch->find_button);
+
+	if (GTK_IS_MENU_ITEM (gsearch->search_results_save_results_as_item) == TRUE) {
+		gtk_widget_set_sensitive (gsearch->search_results_save_results_as_item, TRUE);
+	}
+
+	if (gtk_window_get_focus (GTK_WINDOW (gsearch->window)) == NULL) {
+		gtk_window_set_focus (GTK_WINDOW (gsearch->window), gsearch->focus);
+	}
+}
+
+gchar *
+build_search_command (GSearchWindow * gsearch,
+                      gboolean first_pass)
+{
+	GString * command;
+	GError * error = NULL;
+	gchar * file_is_named_utf8;
+	gchar * file_is_named_locale;
+	gchar * file_is_named_escaped;
+	gchar * file_is_named_backslashed;
+	gchar * look_in_folder_locale;
+	gchar * look_in_folder_escaped;
+	gchar * look_in_folder_backslashed;
+
+	start_animation (gsearch, first_pass);
+	setup_case_insensitive_arguments (gsearch);
+
+	file_is_named_utf8 = g_strdup ((gchar *) gtk_entry_get_text (GTK_ENTRY (gsearch_history_entry_get_entry
+	                                         (GSEARCH_HISTORY_ENTRY (gsearch->name_contains_entry)))));
+
+	if (!file_is_named_utf8 || !*file_is_named_utf8) {
+		g_free (file_is_named_utf8);
+		file_is_named_utf8 = g_strdup ("*");
+	}
+	else {
+		gchar * locale;
+
+		locale = g_locale_from_utf8 (file_is_named_utf8, -1, NULL, NULL, &error);
+		if (locale == NULL) {
+			stop_animation (gsearch);
+			display_dialog_character_set_conversion_error (gsearch->window, file_is_named_utf8, error);
+			g_free (file_is_named_utf8);
+			g_error_free (error);
+			return NULL;
+		}
+		gsearch_history_entry_prepend_text (GSEARCH_HISTORY_ENTRY (gsearch->name_contains_entry), file_is_named_utf8);
+
+		if ((strstr (locale, "*") == NULL) && (strstr (locale, "?") == NULL)) {
+			gchar *tmp;
+
+			tmp = file_is_named_utf8;
+			file_is_named_utf8 = g_strconcat ("*", file_is_named_utf8, "*", NULL);
+			g_free (tmp);
+		}
+
+		g_free (locale);
+	}
+
+	file_is_named_locale = g_locale_from_utf8 (file_is_named_utf8, -1, NULL, NULL, &error);
+	if (file_is_named_locale == NULL) {
+		stop_animation (gsearch);
+		display_dialog_character_set_conversion_error (gsearch->window, file_is_named_utf8, error);
+		g_free (file_is_named_utf8);
+		g_error_free (error);
+		return NULL;
+	}
+
+	look_in_folder_locale = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (gsearch->look_in_folder_button));
+
+	if (look_in_folder_locale == NULL) {
+		/* If for some reason a path was not returned fallback to the user's home directory. */
+		look_in_folder_locale = g_strdup (g_get_home_dir ());
+		gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (gsearch->look_in_folder_button), look_in_folder_locale);
+	}
+
+	if (!g_str_has_suffix (look_in_folder_locale, G_DIR_SEPARATOR_S)) {
+		gchar *tmp;
+
+		tmp = look_in_folder_locale;
+		look_in_folder_locale = g_strconcat (look_in_folder_locale, G_DIR_SEPARATOR_S, NULL);
+		g_free (tmp);
+	}
+	g_free (gsearch->command_details->look_in_folder_string);
+
+	look_in_folder_backslashed = backslash_backslash_characters (look_in_folder_locale);
+	look_in_folder_escaped = escape_double_quotes (look_in_folder_backslashed);
+	gsearch->command_details->look_in_folder_string = g_strdup (look_in_folder_locale);
+
+	command = g_string_new ("");
+	gsearch->command_details->is_command_show_hidden_files_enabled = FALSE;
+	gsearch->command_details->name_contains_regex_string = NULL;
+	gsearch->command_details->name_contains_pattern_string = NULL;
+
+	gsearch->command_details->is_command_first_pass = first_pass;
+	if (gsearch->command_details->is_command_first_pass == TRUE) {
+		gsearch->command_details->is_command_using_quick_mode = FALSE;
+	}
+
+	if ((gtk_widget_get_visible (gsearch->available_options_vbox) == FALSE) ||
+	    (has_additional_constraints (gsearch) == FALSE)) {
+
+		file_is_named_backslashed = backslash_backslash_characters (file_is_named_locale);
+		file_is_named_escaped = escape_double_quotes (file_is_named_backslashed);
+		gsearch->command_details->name_contains_pattern_string = g_strdup (file_is_named_utf8);
+
+		if (gsearch->command_details->is_command_first_pass == TRUE) {
+
+			gchar * locate;
+			CajaSpeedTradeoff show_thumbnails_enum;
+			gboolean disable_quick_search;
+
+			locate = g_find_program_in_path ("locate");
+			disable_quick_search = g_settings_get_boolean (gsearch->mate_search_tool_settings, "disable-quick-search");
+			gsearch->command_details->is_command_second_pass_enabled = !g_settings_get_boolean (gsearch->mate_search_tool_settings, "disable-quick-search-second-scan");
+
+			/* Use caja settings for thumbnails if caja is installed, else fall back to the caja default */
+			if (gsearch->caja_schema_exists) {
+				show_thumbnails_enum = g_settings_get_enum (gsearch->caja_settings, "show-image-thumbnails");
+			} else {
+				show_thumbnails_enum = SPEED_TRADEOFF_LOCAL_ONLY;
+			}
+
+			if (show_thumbnails_enum == SPEED_TRADEOFF_ALWAYS ||
+				show_thumbnails_enum == SPEED_TRADEOFF_LOCAL_ONLY) {
+				GVariant * value;
+				guint64 size_limit = 10485760;
+
+				if (gsearch->caja_schema_exists) {
+					value = g_settings_get_value (gsearch->caja_settings, "thumbnail-limit");
+					if (value) {
+						size_limit = g_variant_get_uint64 (value);
+						g_variant_unref (value);
+					}
+				}
+
+				gsearch->show_thumbnails = TRUE;
+				gsearch->show_thumbnails_file_size_limit = size_limit;
+			}
+			else {
+				gsearch->show_thumbnails = FALSE;
+				gsearch->show_thumbnails_file_size_limit = 0;
+			}
+
+			if ((disable_quick_search == FALSE)
+			    && (gsearch->is_locate_database_available == TRUE)
+			    && (locate != NULL)
+			    && (is_quick_search_excluded_path (look_in_folder_locale) == FALSE)) {
+
+					g_string_append_printf (command, "%s %s \"%s*%s\"",
+							locate,
+							locate_command_default_options,
+							look_in_folder_escaped,
+							file_is_named_escaped);
+					gsearch->command_details->is_command_using_quick_mode = TRUE;
+			}
+			else {
+				g_string_append_printf (command, "find \"%s\" %s \"%s\" -print",
+							look_in_folder_escaped,
+							find_command_default_name_argument,
+							file_is_named_escaped);
+			}
+			g_free (locate);
+		}
+		else {
+			g_string_append_printf (command, "find \"%s\" %s \"%s\" -print",
+						look_in_folder_escaped,
+						find_command_default_name_argument,
+						file_is_named_escaped);
+		}
+	}
+	else {
+		GList * list;
+		gboolean disable_mount_argument = TRUE;
+
+		gsearch->command_details->is_command_regex_matching_enabled = FALSE;
+		file_is_named_backslashed = backslash_backslash_characters (file_is_named_locale);
+		file_is_named_escaped = escape_double_quotes (file_is_named_backslashed);
+
+		g_string_append_printf (command, "find \"%s\" %s",
+					look_in_folder_escaped,
+					setup_find_name_options (file_is_named_escaped));
+
+		for (list = gsearch->available_options_selected_list; list != NULL; list = g_list_next (list)) {
+
+			GSearchConstraint * constraint = list->data;
+
+			switch (GSearchOptionTemplates[constraint->constraint_id].type) {
+			case SEARCH_CONSTRAINT_TYPE_BOOLEAN:
+				if (strcmp (GSearchOptionTemplates[constraint->constraint_id].option, "EXCLUDE_OTHER_FILESYSTEMS") == 0) {
+					disable_mount_argument = FALSE;
+				}
+				else if (strcmp (GSearchOptionTemplates[constraint->constraint_id].option, "SHOW_HIDDEN_FILES") == 0) {
+					gsearch->command_details->is_command_show_hidden_files_enabled = TRUE;
+				}
+				else {
+					g_string_append_printf (command, "%s ",
+						GSearchOptionTemplates[constraint->constraint_id].option);
+				}
+				break;
+			case SEARCH_CONSTRAINT_TYPE_TEXT:
+				if (strcmp (GSearchOptionTemplates[constraint->constraint_id].option, "-regex '%s'") == 0) {
+
+					gchar * escaped;
+					gchar * regex;
+
+					escaped = backslash_special_characters (constraint->data.text);
+					regex = escape_single_quotes (escaped);
+
+					if (regex != NULL) {
+						gsearch->command_details->is_command_regex_matching_enabled = TRUE;
+						gsearch->command_details->name_contains_regex_string = g_locale_from_utf8 (regex, -1, NULL, NULL, NULL);
+					}
+
+					g_free (escaped);
+					g_free (regex);
+				}
+				else {
+					gchar * escaped;
+					gchar * backslashed;
+					gchar * locale;
+
+					backslashed = backslash_special_characters (constraint->data.text);
+					escaped = escape_single_quotes (backslashed);
+
+					locale = g_locale_from_utf8 (escaped, -1, NULL, NULL, NULL);
+
+					if (strlen (locale) != 0) {
+						g_string_append_printf (command,
+							  	        GSearchOptionTemplates[constraint->constraint_id].option,
+						  		        locale);
+
+						g_string_append_c (command, ' ');
+					}
+
+					g_free (escaped);
+					g_free (backslashed);
+					g_free (locale);
+				}
+				break;
+			case SEARCH_CONSTRAINT_TYPE_NUMERIC:
+				g_string_append_printf (command,
+					  		GSearchOptionTemplates[constraint->constraint_id].option,
+							(constraint->data.number * 1024),
+					  		(constraint->data.number * 1024));
+				g_string_append_c (command, ' ');
+				break;
+			case SEARCH_CONSTRAINT_TYPE_DATE_BEFORE:
+				g_string_append_printf (command,
+					 		GSearchOptionTemplates[constraint->constraint_id].option,
+					  		constraint->data.time);
+				g_string_append_c (command, ' ');
+				break;
+			case SEARCH_CONSTRAINT_TYPE_DATE_AFTER:
+				g_string_append_printf (command,
+					 		GSearchOptionTemplates[constraint->constraint_id].option,
+					  		constraint->data.time,
+					  		constraint->data.time);
+				g_string_append_c (command, ' ');
+				break;
+			default:
+		        	break;
+			}
+		}
+		gsearch->command_details->name_contains_pattern_string = g_strdup ("*");
+
+		if (disable_mount_argument != TRUE) {
+			g_string_append (command, "-xdev ");
+		}
+
+		g_string_append (command, "-print ");
+	}
+	g_free (file_is_named_locale);
+	g_free (file_is_named_utf8);
+	g_free (file_is_named_backslashed);
+	g_free (file_is_named_escaped);
+	g_free (look_in_folder_locale);
+	g_free (look_in_folder_backslashed);
+	g_free (look_in_folder_escaped);
+
+	return g_string_free (command, FALSE);
+}
+
+static void
+add_file_to_search_results (const gchar * file,
+			    GtkListStore * store,
+			    GtkTreeIter * iter,
+			    GSearchWindow * gsearch)
+{
+	GdkPixbuf * pixbuf;
+	GSearchMonitor * monitor;
+	GFileMonitor * handle;
+	GFileInfo * file_info;
+	GFile * g_file;
+	GError * error = NULL;
+	GDateTime * file_dt;
+#if GLIB_CHECK_VERSION(2,61,2)
+	gint64 time_val;
+#else
+	GTimeVal time_val;
+#endif
+	GtkTreePath * path;
+	GtkTreeRowReference * reference;
+	gchar * description;
+	gchar * readable_size;
+	gchar * readable_date;
+	gchar * utf8_base_name;
+	gchar * utf8_relative_dir_name;
+	gchar * base_name;
+	gchar * dir_name;
+	gchar * relative_dir_name;
+	gchar * look_in_folder;
+
+	if (g_hash_table_lookup_extended (gsearch->search_results_filename_hash_table, file, NULL, NULL) == TRUE) {
+		return;
+	}
+
+	if ((g_file_test (file, G_FILE_TEST_EXISTS) != TRUE) &&
+	    (g_file_test (file, G_FILE_TEST_IS_SYMLINK) != TRUE)) {
+		return;
+	}
+
+	g_hash_table_insert (gsearch->search_results_filename_hash_table, g_strdup (file), NULL);
+
+	if (gtk_tree_view_get_headers_visible (GTK_TREE_VIEW (gsearch->search_results_tree_view)) == FALSE) {
+		gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (gsearch->search_results_tree_view), TRUE);
+	}
+
+	g_file = g_file_new_for_path (file);
+	file_info = g_file_query_info (g_file, "standard::*,time::modified,thumbnail::path", 0, NULL, NULL);
+
+	pixbuf = get_file_pixbuf (gsearch, file_info);
+	description = get_file_type_description (file, file_info);
+		readable_size = g_format_size (g_file_info_get_size (file_info));
+
+#if GLIB_CHECK_VERSION(2,61,2)
+	file_dt = g_file_info_get_modification_date_time (file_info);
+	time_val = g_date_time_to_unix (file_dt);
+#else
+	g_file_info_get_modification_time (file_info, &time_val);
+	file_dt = g_date_time_new_from_unix_local ((gint64) time_val.tv_sec);
+#endif
+	readable_date = get_readable_date (gsearch->search_results_date_format, file_dt);
+
+	base_name = g_path_get_basename (file);
+	dir_name = g_path_get_dirname (file);
+
+	look_in_folder = g_strdup (gsearch->command_details->look_in_folder_string);
+	if (strlen (look_in_folder) > 1) {
+		gchar * path_str;
+
+		if (g_str_has_suffix (look_in_folder, G_DIR_SEPARATOR_S) == TRUE) {
+			look_in_folder[strlen (look_in_folder) - 1] = '\0';
+		}
+		path_str = g_path_get_dirname (look_in_folder);
+		if (strcmp (path_str, G_DIR_SEPARATOR_S) == 0) {
+			relative_dir_name = g_strconcat (&dir_name[strlen (path_str)], NULL);
+		}
+		else {
+			relative_dir_name = g_strconcat (&dir_name[strlen (path_str) + 1], NULL);
+		}
+		g_free (path_str);
+	}
+	else {
+		relative_dir_name = g_strdup (dir_name);
+	}
+
+	utf8_base_name = g_filename_display_basename (file);
+	utf8_relative_dir_name = g_filename_display_name (relative_dir_name);
+
+	gtk_list_store_append (GTK_LIST_STORE (store), iter);
+	goffset file_size = g_file_info_get_size (file_info);
+	gtk_list_store_set (GTK_LIST_STORE (store), iter,
+			    COLUMN_ICON, pixbuf,
+			    COLUMN_NAME, utf8_base_name,
+			    COLUMN_RELATIVE_PATH, utf8_relative_dir_name,
+			    COLUMN_LOCALE_FILE, file,
+			    COLUMN_READABLE_SIZE, readable_size,
+			    COLUMN_SIZE, (-1) * (gdouble) file_size,
+			    COLUMN_TYPE, (description != NULL) ? description : g_strdup (g_file_info_get_content_type (file_info)),
+			    COLUMN_READABLE_DATE, readable_date,
+#if GLIB_CHECK_VERSION(2,61,2)
+			    COLUMN_DATE, (-1) * (gdouble) time_val,
+#else
+			    COLUMN_DATE, (-1) * (gdouble) time_val.tv_sec,
+#endif
+			    COLUMN_NO_FILES_FOUND, FALSE,
+			    -1);
+
+	monitor = g_slice_new0 (GSearchMonitor);
+	if (monitor) {
+		path = gtk_tree_model_get_path (GTK_TREE_MODEL (store), iter);
+		reference = gtk_tree_row_reference_new (GTK_TREE_MODEL (store), path);
+		gtk_tree_path_free (path);
+
+		handle = g_file_monitor_file (g_file, G_FILE_MONITOR_NONE, NULL, &error);
+
+		if (error == NULL) {
+			monitor->gsearch = gsearch;
+			monitor->reference = reference;
+			monitor->handle = handle;
+			gtk_list_store_set (GTK_LIST_STORE (store), iter,
+			                    COLUMN_MONITOR, monitor, -1);
+
+			g_signal_connect (handle, "changed",
+					  G_CALLBACK (file_changed_cb), monitor);
+		}
+		else {
+			gtk_tree_row_reference_free (reference);
+			g_slice_free (GSearchMonitor, monitor);
+			g_clear_error (&error);
+		}
+	}
+
+	g_object_unref (g_file);
+	g_object_unref (file_info);
+	g_date_time_unref (file_dt);
+	g_free (base_name);
+	g_free (dir_name);
+	g_free (relative_dir_name);
+	g_free (utf8_base_name);
+	g_free (utf8_relative_dir_name);
+	g_free (look_in_folder);
+	g_free (description);
+	g_free (readable_size);
+	g_free (readable_date);
+}
+
+static void
+add_no_files_found_message (GSearchWindow * gsearch)
+{
+	/* When the list is empty append a 'No Files Found.' message. */
+	gtk_widget_set_sensitive (GTK_WIDGET (gsearch->search_results_tree_view), FALSE);
+	gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (gsearch->search_results_tree_view), FALSE);
+	gtk_tree_view_column_set_visible (gsearch->search_results_folder_column, FALSE);
+	gtk_tree_view_column_set_visible (gsearch->search_results_size_column, FALSE);
+	gtk_tree_view_column_set_visible (gsearch->search_results_type_column, FALSE);
+	gtk_tree_view_column_set_visible (gsearch->search_results_date_column, FALSE);
+	gtk_tree_view_columns_autosize (GTK_TREE_VIEW (gsearch->search_results_tree_view));
+	g_object_set (gsearch->search_results_name_cell_renderer,
+	              "underline", PANGO_UNDERLINE_NONE,
+	              "underline-set", FALSE,
+	              NULL);
+	gtk_list_store_append (GTK_LIST_STORE (gsearch->search_results_list_store), &gsearch->search_results_iter);
+	gtk_list_store_set (GTK_LIST_STORE (gsearch->search_results_list_store), &gsearch->search_results_iter,
+		    	    COLUMN_ICON, NULL,
+			    COLUMN_NAME, _("No files found"),
+			    COLUMN_RELATIVE_PATH, "",
+			    COLUMN_LOCALE_FILE, "",
+			    COLUMN_READABLE_SIZE, "",
+			    COLUMN_SIZE, (gdouble) 0,
+			    COLUMN_TYPE, "",
+		    	    COLUMN_READABLE_DATE, "",
+		    	    COLUMN_DATE, (gdouble) 0,
+			    COLUMN_NO_FILES_FOUND, TRUE,
+		    	    -1);
+}
+
+void
+update_search_counts (GSearchWindow * gsearch)
+{
+	gchar * title_bar_string = NULL;
+	gchar * message_string = NULL;
+	gchar * stopped_string = NULL;
+	gchar * tmp;
+	gint total_files;
+
+	if (gsearch->command_details->command_status == ABORTED) {
+		stopped_string = g_strdup (_("(stopped)"));
+	}
+
+	total_files = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (gsearch->search_results_list_store), NULL);
+
+	if (total_files == 0) {
+		title_bar_string = g_strdup (_("No Files Found"));
+		message_string = g_strdup (_("No files found"));
+		add_no_files_found_message (gsearch);
+	}
+	else {
+		title_bar_string = g_strdup_printf (ngettext ("%'d File Found",
+					                      "%'d Files Found",
+					                      total_files),
+						    total_files);
+		message_string = g_strdup_printf (ngettext ("%'d file found",
+					                    "%'d files found",
+					                    total_files),
+						  total_files);
+	}
+
+	if (stopped_string != NULL) {
+		tmp = message_string;
+		message_string = g_strconcat (message_string, " ", stopped_string, NULL);
+		g_free (tmp);
+
+		tmp = title_bar_string;
+		title_bar_string = g_strconcat (title_bar_string, " ", stopped_string, NULL);
+		g_free (tmp);
+	}
+
+	tmp = title_bar_string;
+	title_bar_string = g_strconcat (title_bar_string, " - ", _("Search for Files"), NULL);
+	gtk_window_set_title (GTK_WINDOW (gsearch->window), title_bar_string);
+	g_free (tmp);
+
+	gtk_label_set_text (GTK_LABEL (gsearch->files_found_label), message_string);
+
+	g_free (title_bar_string);
+	g_free (message_string);
+	g_free (stopped_string);
+}
+
+static void
+intermediate_file_count_update (GSearchWindow * gsearch)
+{
+	gchar * string;
+	gint count;
+
+	count = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (gsearch->search_results_list_store), NULL);
+
+	if (count > 0) {
+
+		string = g_strdup_printf (ngettext ("%'d file found",
+		                                    "%'d files found",
+		                                    count),
+		                          count);
+
+		gtk_label_set_text (GTK_LABEL (gsearch->files_found_label), string);
+		g_free (string);
+	}
+}
+
+gboolean
+tree_model_iter_free_monitor (GtkTreeModel * model,
+                              GtkTreePath * path,
+                              GtkTreeIter * iter,
+                              gpointer data)
+{
+	GSearchMonitor * monitor;
+
+	g_return_val_if_fail (GTK_IS_TREE_MODEL (model), FALSE);
+
+	gtk_tree_model_get (model, iter, COLUMN_MONITOR, &monitor, -1);
+	if (monitor) {
+		g_file_monitor_cancel (monitor->handle);
+		gtk_tree_row_reference_free (monitor->reference);
+		g_slice_free (GSearchMonitor, monitor);
+	}
+	return FALSE;
+}
+
+static GtkTreeModel *
+gsearch_create_list_of_templates (void)
+{
+	GtkListStore * store;
+	GtkTreeIter iter;
+	gint idx;
+
+	store = gtk_list_store_new (1, G_TYPE_STRING);
+
+	for (idx = 0; GSearchOptionTemplates[idx].type != SEARCH_CONSTRAINT_TYPE_NONE; idx++) {
+
+		if (GSearchOptionTemplates[idx].type == SEARCH_CONSTRAINT_TYPE_SEPARATOR) {
+		        gtk_list_store_append (store, &iter);
+		        gtk_list_store_set (store, &iter, 0, "separator", -1);
+		}
+		else {
+			gchar * text = remove_mnemonic_character (_(GSearchOptionTemplates[idx].desc));
+			gtk_list_store_append (store, &iter);
+		        gtk_list_store_set (store, &iter, 0, text, -1);
+			g_free (text);
+		}
+	}
+	return GTK_TREE_MODEL (store);
+}
+
+static void
+set_constraint_info_defaults (GSearchConstraint * opt)
+{
+	switch (GSearchOptionTemplates[opt->constraint_id].type) {
+	case SEARCH_CONSTRAINT_TYPE_BOOLEAN:
+		break;
+	case SEARCH_CONSTRAINT_TYPE_TEXT:
+		opt->data.text = "";
+		break;
+	case SEARCH_CONSTRAINT_TYPE_NUMERIC:
+		opt->data.number = 0;
+		break;
+	case SEARCH_CONSTRAINT_TYPE_DATE_BEFORE:
+	case SEARCH_CONSTRAINT_TYPE_DATE_AFTER:
+		opt->data.time = 0;
+		break;
+	default:
+	        break;
+	}
+}
+
+void
+update_constraint_info (GSearchConstraint * constraint,
+			gchar * info)
+{
+	switch (GSearchOptionTemplates[constraint->constraint_id].type) {
+	case SEARCH_CONSTRAINT_TYPE_TEXT:
+		constraint->data.text = info;
+		break;
+	case SEARCH_CONSTRAINT_TYPE_NUMERIC:
+		sscanf (info, "%d", &constraint->data.number);
+		break;
+	case SEARCH_CONSTRAINT_TYPE_DATE_BEFORE:
+	case SEARCH_CONSTRAINT_TYPE_DATE_AFTER:
+		sscanf (info, "%d", &constraint->data.time);
+		break;
+	default:
+		g_warning (_("Entry changed called for a non entry option!"));
+		break;
+	}
+}
+
+void
+set_constraint_selected_state (GSearchWindow * gsearch,
+                               gint constraint_id,
+			       gboolean state)
+{
+	gint idx;
+
+	GSearchOptionTemplates[constraint_id].is_selected = state;
+
+	for (idx = 0; GSearchOptionTemplates[idx].type != SEARCH_CONSTRAINT_TYPE_NONE; idx++) {
+		if (GSearchOptionTemplates[idx].is_selected == FALSE) {
+			gtk_combo_box_set_active (GTK_COMBO_BOX (gsearch->available_options_combo_box), idx);
+			gtk_widget_set_sensitive (gsearch->available_options_add_button, TRUE);
+			gtk_widget_set_sensitive (gsearch->available_options_combo_box, TRUE);
+			gtk_widget_set_sensitive (gsearch->available_options_label, TRUE);
+			return;
+		}
+	}
+	gtk_widget_set_sensitive (gsearch->available_options_add_button, FALSE);
+	gtk_widget_set_sensitive (gsearch->available_options_combo_box, FALSE);
+	gtk_widget_set_sensitive (gsearch->available_options_label, FALSE);
+}
+
+void
+set_constraint_gsettings_boolean (gint constraint_id,
+                                  gboolean flag)
+{
+	GSettings * select_settings;
+
+	select_settings = g_settings_new ("org.mate.search-tool.select");
+
+	switch (constraint_id) {
+
+		case SEARCH_CONSTRAINT_CONTAINS_THE_TEXT:
+			g_settings_set_boolean (select_settings, "contains-the-text",
+	   		       	       	       	flag);
+			break;
+		case SEARCH_CONSTRAINT_DATE_MODIFIED_BEFORE:
+			g_settings_set_boolean (select_settings, "date-modified-less-than",
+	   		       	       	       	flag);
+			break;
+		case SEARCH_CONSTRAINT_DATE_MODIFIED_AFTER:
+			g_settings_set_boolean (select_settings, "date-modified-more-than",
+	   		       	       	       	flag);
+			break;
+		case SEARCH_CONSTRAINT_SIZE_IS_MORE_THAN:
+			g_settings_set_boolean (select_settings, "size-at-least",
+	   		       	       		    flag);
+			break;
+		case SEARCH_CONSTRAINT_SIZE_IS_LESS_THAN:
+			g_settings_set_boolean (select_settings, "size-at-most",
+	   		       	       	        flag);
+			break;
+		case SEARCH_CONSTRAINT_FILE_IS_EMPTY:
+			g_settings_set_boolean (select_settings, "file-is-empty",
+	   		       	       	        flag);
+			break;
+		case SEARCH_CONSTRAINT_OWNED_BY_USER:
+			g_settings_set_boolean (select_settings, "owned-by-user",
+	   		       	       	        flag);
+			break;
+		case SEARCH_CONSTRAINT_OWNED_BY_GROUP:
+			g_settings_set_boolean (select_settings, "owned-by-group",
+	   		       	       	        flag);
+			break;
+		case SEARCH_CONSTRAINT_OWNER_IS_UNRECOGNIZED:
+			g_settings_set_boolean (select_settings, "owner-is-unrecognized",
+	   		       	       	        flag);
+			break;
+		case SEARCH_CONSTRAINT_FILE_IS_NOT_NAMED:
+			g_settings_set_boolean (select_settings, "name-does-not-contain",
+	   		       	       	        flag);
+			break;
+		case SEARCH_CONSTRAINT_FILE_MATCHES_REGULAR_EXPRESSION:
+			g_settings_set_boolean (select_settings, "name-matches-regular-expression",
+	   		       	       	        flag);
+			break;
+		case SEARCH_CONSTRAINT_SHOW_HIDDEN_FILES_AND_FOLDERS:
+			g_settings_set_boolean (select_settings, "show-hidden-files-and-folders",
+	   		       	       	        flag);
+			break;
+		case SEARCH_CONSTRAINT_FOLLOW_SYMBOLIC_LINKS:
+			g_settings_set_boolean (select_settings, "follow-symbolic-links",
+	   		       	       	        flag);
+			break;
+		case SEARCH_CONSTRAINT_SEARCH_OTHER_FILESYSTEMS:
+			g_settings_set_boolean (select_settings, "exclude-other-filesystems",
+	   		       	       	        flag);
+			break;
+
+		default:
+			break;
+	}
+	g_object_unref (select_settings);
+}
+
+/*
+ * add_atk_namedesc
+ * @widget    : The Gtk Widget for which @name and @desc are added.
+ * @name      : Accessible Name
+ * @desc      : Accessible Description
+ * Description: This function adds accessible name and description to a
+ *              Gtk widget.
+ */
+
+static void
+add_atk_namedesc (GtkWidget * widget,
+		  const gchar * name,
+		  const gchar * desc)
+{
+	AtkObject * atk_widget;
+
+	g_assert (GTK_IS_WIDGET (widget));
+
+	atk_widget = gtk_widget_get_accessible (widget);
+
+	if (name != NULL)
+		atk_object_set_name (atk_widget, name);
+	if (desc !=NULL)
+		atk_object_set_description (atk_widget, desc);
+}
+
+/*
+ * add_atk_relation
+ * @obj1      : The first widget in the relation @rel_type
+ * @obj2      : The second widget in the relation @rel_type.
+ * @rel_type  : Relation type which relates @obj1 and @obj2
+ * Description: This function establishes Atk Relation between two given
+ *              objects.
+ */
+
+static void
+add_atk_relation (GtkWidget * obj1,
+		  GtkWidget * obj2,
+		  AtkRelationType rel_type)
+{
+	AtkObject * atk_obj1, * atk_obj2;
+	AtkRelationSet * relation_set;
+	AtkRelation * relation;
+
+	g_assert (GTK_IS_WIDGET (obj1));
+	g_assert (GTK_IS_WIDGET (obj2));
+
+	atk_obj1 = gtk_widget_get_accessible (obj1);
+
+	atk_obj2 = gtk_widget_get_accessible (obj2);
+
+	relation_set = atk_object_ref_relation_set (atk_obj1);
+	relation = atk_relation_new (&atk_obj2, 1, rel_type);
+	atk_relation_set_add (relation_set, relation);
+	g_object_unref (G_OBJECT (relation));
+
+}
+
+static void
+gsearch_setup_goption_descriptions (void)
+{
+	gint i = 1;
+	gint j;
+
+	GSearchGOptionEntries[i++].description = g_strdup (_("Set the text of \"Name contains\" search option"));
+	GSearchGOptionEntries[i++].description = g_strdup (_("Set the text of \"Look in folder\" search option"));
+  	GSearchGOptionEntries[i++].description = g_strdup (_("Sort files by one of the following: name, folder, size, type, or date"));
+  	GSearchGOptionEntries[i++].description = g_strdup (_("Set sort order to descending, the default is ascending"));
+  	GSearchGOptionEntries[i++].description = g_strdup (_("Automatically start a search"));
+
+	for (j = 0; GSearchOptionTemplates[j].type != SEARCH_CONSTRAINT_TYPE_NONE; j++) {
+		if (GSearchOptionTemplates[j].type != SEARCH_CONSTRAINT_TYPE_SEPARATOR) {
+			gchar *text = remove_mnemonic_character (_(GSearchOptionTemplates[j].desc));
+			if (GSearchOptionTemplates[j].type == SEARCH_CONSTRAINT_TYPE_BOOLEAN) {
+				GSearchGOptionEntries[i++].description = g_strdup_printf (_("Select the \"%s\" search option"), text);
+			}
+			else {
+				GSearchGOptionEntries[i++].description = g_strdup_printf (_("Select and set the \"%s\" search option"), text);
+			}
+			g_free (text);
+		}
+	}
+}
+
+static gboolean
+handle_goption_args (GSearchWindow * gsearch)
+{
+	gboolean goption_args_found = FALSE;
+	gint sort_by;
+
+	if (GSearchGOptionArguments.name != NULL) {
+		goption_args_found = TRUE;
+		gtk_entry_set_text (GTK_ENTRY (gsearch_history_entry_get_entry (GSEARCH_HISTORY_ENTRY (gsearch->name_contains_entry))),
+				    g_locale_to_utf8 (GSearchGOptionArguments.name, -1, NULL, NULL, NULL));
+	}
+	if (GSearchGOptionArguments.path != NULL) {
+		goption_args_found = TRUE;
+		gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (gsearch->look_in_folder_button),
+		                               g_locale_to_utf8 (GSearchGOptionArguments.path, -1, NULL, NULL, NULL));
+	}
+	if (GSearchGOptionArguments.contains != NULL) {
+		goption_args_found = TRUE;
+		add_constraint (gsearch, SEARCH_CONSTRAINT_CONTAINS_THE_TEXT,
+				GSearchGOptionArguments.contains, TRUE);
+	}
+	if (GSearchGOptionArguments.mtimeless != NULL) {
+		goption_args_found = TRUE;
+		add_constraint (gsearch, SEARCH_CONSTRAINT_DATE_MODIFIED_BEFORE,
+				GSearchGOptionArguments.mtimeless, TRUE);
+	}
+	if (GSearchGOptionArguments.mtimemore != NULL) {
+		goption_args_found = TRUE;
+		add_constraint (gsearch, SEARCH_CONSTRAINT_DATE_MODIFIED_AFTER,
+				GSearchGOptionArguments.mtimemore, TRUE);
+	}
+	if (GSearchGOptionArguments.sizemore != NULL) {
+		goption_args_found = TRUE;
+		add_constraint (gsearch, SEARCH_CONSTRAINT_SIZE_IS_MORE_THAN,
+				GSearchGOptionArguments.sizemore, TRUE);
+	}
+	if (GSearchGOptionArguments.sizeless != NULL) {
+		goption_args_found = TRUE;
+		add_constraint (gsearch, SEARCH_CONSTRAINT_SIZE_IS_LESS_THAN,
+				GSearchGOptionArguments.sizeless, TRUE);
+	}
+	if (GSearchGOptionArguments.empty) {
+		goption_args_found = TRUE;
+		add_constraint (gsearch, SEARCH_CONSTRAINT_FILE_IS_EMPTY, NULL, TRUE);
+	}
+	if (GSearchGOptionArguments.user != NULL) {
+		goption_args_found = TRUE;
+		add_constraint (gsearch, SEARCH_CONSTRAINT_OWNED_BY_USER,
+				GSearchGOptionArguments.user, TRUE);
+	}
+	if (GSearchGOptionArguments.group != NULL) {
+		goption_args_found = TRUE;
+		add_constraint (gsearch, SEARCH_CONSTRAINT_OWNED_BY_GROUP,
+				GSearchGOptionArguments.group, TRUE);
+	}
+	if (GSearchGOptionArguments.nouser) {
+		goption_args_found = TRUE;
+		add_constraint (gsearch, SEARCH_CONSTRAINT_OWNER_IS_UNRECOGNIZED, NULL, TRUE);
+	}
+	if (GSearchGOptionArguments.notnamed != NULL) {
+		goption_args_found = TRUE;
+		add_constraint (gsearch, SEARCH_CONSTRAINT_FILE_IS_NOT_NAMED,
+				GSearchGOptionArguments.notnamed, TRUE);
+	}
+	if (GSearchGOptionArguments.regex != NULL) {
+		goption_args_found = TRUE;
+		add_constraint (gsearch, SEARCH_CONSTRAINT_FILE_MATCHES_REGULAR_EXPRESSION,
+				GSearchGOptionArguments.regex, TRUE);
+	}
+	if (GSearchGOptionArguments.hidden) {
+		goption_args_found = TRUE;
+		add_constraint (gsearch, SEARCH_CONSTRAINT_SHOW_HIDDEN_FILES_AND_FOLDERS, NULL, TRUE);
+	}
+	if (GSearchGOptionArguments.follow) {
+		goption_args_found = TRUE;
+		add_constraint (gsearch, SEARCH_CONSTRAINT_FOLLOW_SYMBOLIC_LINKS, NULL, TRUE);
+	}
+	if (GSearchGOptionArguments.mounts) {
+		goption_args_found = TRUE;
+		add_constraint (gsearch, SEARCH_CONSTRAINT_SEARCH_OTHER_FILESYSTEMS, NULL, TRUE);
+	}
+	if (GSearchGOptionArguments.sortby != NULL) {
+
+		goption_args_found = TRUE;
+		if (strcmp (GSearchGOptionArguments.sortby, "name") == 0) {
+			sort_by = COLUMN_NAME;
+		}
+		else if (strcmp (GSearchGOptionArguments.sortby, "folder") == 0) {
+			sort_by = COLUMN_RELATIVE_PATH;
+		}
+		else if (strcmp (GSearchGOptionArguments.sortby, "size") == 0) {
+			sort_by = COLUMN_SIZE;
+		}
+		else if (strcmp (GSearchGOptionArguments.sortby, "type") == 0) {
+			sort_by = COLUMN_TYPE;
+		}
+		else if (strcmp (GSearchGOptionArguments.sortby, "date") == 0) {
+			sort_by = COLUMN_DATE;
+		}
+		else {
+			g_warning (_("Invalid option passed to sortby command line argument."));
+			sort_by = COLUMN_NAME;
+		}
+
+		if (GSearchGOptionArguments.descending) {
+			gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (gsearch->search_results_list_store), sort_by,
+							      GTK_SORT_DESCENDING);
+		}
+		else {
+			gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (gsearch->search_results_list_store), sort_by,
+							      GTK_SORT_ASCENDING);
+		}
+	}
+	if (GSearchGOptionArguments.start) {
+		goption_args_found = TRUE;
+		click_find_cb (gsearch->find_button, (gpointer) gsearch);
+	}
+	return goption_args_found;
+}
+
+static gboolean
+handle_search_command_stdout_io (GIOChannel * ioc,
+				 GIOCondition condition,
+				 gpointer data)
+{
+	GSearchWindow * gsearch = data;
+	gboolean broken_pipe = FALSE;
+
+	if (condition & G_IO_IN) {
+
+		GError * error = NULL;
+		GTimer * timer;
+		GString * string;
+		GdkRectangle prior_rect;
+		GdkRectangle after_rect;
+		gulong duration;
+		gint look_in_folder_string_length;
+
+		string = g_string_new (NULL);
+		look_in_folder_string_length = strlen (gsearch->command_details->look_in_folder_string);
+
+		timer = g_timer_new ();
+		g_timer_start (timer);
+
+		while (ioc->is_readable != TRUE);
+
+		do {
+			gchar * utf8 = NULL;
+			gchar * filename = NULL;
+			gint status;
+
+			if (gsearch->command_details->command_status == MAKE_IT_STOP) {
+				broken_pipe = TRUE;
+				break;
+			}
+			else if (gsearch->command_details->command_status != RUNNING) {
+			 	break;
+			}
+
+			do {
+				status = g_io_channel_read_line_string (ioc, string, NULL, &error);
+
+				if (status == G_IO_STATUS_EOF) {
+					broken_pipe = TRUE;
+				}
+				else if (status == G_IO_STATUS_AGAIN) {
+					if (gtk_events_pending ()) {
+						intermediate_file_count_update (gsearch);
+						while (gtk_events_pending ()) {
+							if (gsearch->command_details->command_status == MAKE_IT_QUIT) {
+								return FALSE;
+							}
+							gtk_main_iteration ();
+						}
+
+					}
+				}
+
+			} while (status == G_IO_STATUS_AGAIN && broken_pipe == FALSE);
+
+			if (broken_pipe == TRUE) {
+				break;
+			}
+
+			if (status != G_IO_STATUS_NORMAL) {
+				if (error != NULL) {
+					g_warning ("handle_search_command_stdout_io(): %s", error->message);
+					g_error_free (error);
+				}
+				continue;
+			}
+
+			string = g_string_truncate (string, string->len - 1);
+			if (string->len <= 1) {
+				continue;
+			}
+
+			utf8 = g_filename_display_name (string->str);
+			if (utf8 == NULL) {
+				continue;
+			}
+
+			if (strncmp (string->str, gsearch->command_details->look_in_folder_string, look_in_folder_string_length) == 0) {
+
+				if (strlen (string->str) != look_in_folder_string_length) {
+
+					filename = g_path_get_basename (utf8);
+
+					if (fnmatch (gsearch->command_details->name_contains_pattern_string, filename, FNM_NOESCAPE | FNM_CASEFOLD ) != FNM_NOMATCH) {
+						if (gsearch->command_details->is_command_show_hidden_files_enabled) {
+							if (gsearch->command_details->is_command_regex_matching_enabled == FALSE) {
+								add_file_to_search_results (string->str, gsearch->search_results_list_store, &gsearch->search_results_iter, gsearch);
+							}
+							else if (compare_regex (gsearch->command_details->name_contains_regex_string, filename)) {
+								add_file_to_search_results (string->str, gsearch->search_results_list_store, &gsearch->search_results_iter, gsearch);
+							}
+						}
+						else if ((is_path_hidden (string->str) == FALSE ||
+						          is_path_hidden (gsearch->command_details->look_in_folder_string) == TRUE) &&
+						          (!g_str_has_suffix (string->str, "~"))) {
+							if (gsearch->command_details->is_command_regex_matching_enabled == FALSE) {
+								add_file_to_search_results (string->str, gsearch->search_results_list_store, &gsearch->search_results_iter, gsearch);
+							}
+							else if (compare_regex (gsearch->command_details->name_contains_regex_string, filename)) {
+								add_file_to_search_results (string->str, gsearch->search_results_list_store, &gsearch->search_results_iter, gsearch);
+							}
+						}
+					}
+				}
+			}
+			g_free (utf8);
+			g_free (filename);
+
+			gtk_tree_view_get_visible_rect (GTK_TREE_VIEW (gsearch->search_results_tree_view), &prior_rect);
+
+			if (prior_rect.y == 0) {
+				gtk_tree_view_get_visible_rect (GTK_TREE_VIEW (gsearch->search_results_tree_view), &after_rect);
+				if (after_rect.y <= 40) {  /* limit this hack to the first few pixels */
+					gtk_tree_view_scroll_to_point (GTK_TREE_VIEW (gsearch->search_results_tree_view), -1, 0);
+				}
+			}
+
+			g_timer_elapsed (timer, &duration);
+
+			if (duration > MATE_SEARCH_TOOL_REFRESH_DURATION) {
+				if (gtk_events_pending ()) {
+					intermediate_file_count_update (gsearch);
+					while (gtk_events_pending ()) {
+						if (gsearch->command_details->command_status == MAKE_IT_QUIT) {
+							return FALSE;
+						}
+						gtk_main_iteration ();
+					}
+				}
+				g_timer_reset (timer);
+			}
+
+		} while (g_io_channel_get_buffer_condition (ioc) & G_IO_IN);
+
+		g_string_free (string, TRUE);
+		g_timer_destroy (timer);
+	}
+
+	if (!(condition & G_IO_IN) || broken_pipe == TRUE) {
+
+		g_io_channel_shutdown (ioc, TRUE, NULL);
+
+		if ((gsearch->command_details->command_status != MAKE_IT_STOP)
+		     && (gsearch->command_details->is_command_using_quick_mode == TRUE)
+		     && (gsearch->command_details->is_command_first_pass == TRUE)
+		     && (gsearch->command_details->is_command_second_pass_enabled == TRUE)
+		     && (is_second_scan_excluded_path (gsearch->command_details->look_in_folder_string) == FALSE)) {
+
+			gchar * command;
+
+			/* Free these strings now because they are reassign values during the second pass. */
+			g_free (gsearch->command_details->name_contains_pattern_string);
+			g_free (gsearch->command_details->name_contains_regex_string);
+
+			command = build_search_command (gsearch, FALSE);
+			if (command != NULL) {
+				spawn_search_command (gsearch, command);
+				g_free (command);
+			}
+		}
+		else {
+			gsearch->command_details->command_status = (gsearch->command_details->command_status == MAKE_IT_STOP) ? ABORTED : STOPPED;
+			gsearch->command_details->is_command_timeout_enabled = TRUE;
+			g_hash_table_destroy (gsearch->search_results_pixbuf_hash_table);
+			g_hash_table_destroy (gsearch->search_results_filename_hash_table);
+			g_timeout_add (500, not_running_timeout_cb, (gpointer) gsearch);
+
+			update_search_counts (gsearch);
+			stop_animation (gsearch);
+
+			/* Free the gchar fields of search_command structure. */
+			g_free (gsearch->command_details->name_contains_pattern_string);
+			g_free (gsearch->command_details->name_contains_regex_string);
+
+		}
+		return FALSE;
+	}
+	return TRUE;
+}
+
+static gboolean
+handle_search_command_stderr_io (GIOChannel * ioc,
+				 GIOCondition condition,
+				 gpointer data)
+{
+	GSearchWindow * gsearch = data;
+	static GString * error_msgs = NULL;
+	static gboolean truncate_error_msgs = FALSE;
+	gboolean broken_pipe = FALSE;
+
+	if (condition & G_IO_IN) {
+
+		GString * string;
+		GError * error = NULL;
+		gchar * utf8 = NULL;
+
+		string = g_string_new (NULL);
+
+		if (error_msgs == NULL) {
+			error_msgs = g_string_new (NULL);
+		}
+
+		while (ioc->is_readable != TRUE);
+
+		do {
+			gint status;
+
+			do {
+				status = g_io_channel_read_line_string (ioc, string, NULL, &error);
+
+				if (status == G_IO_STATUS_EOF) {
+					broken_pipe = TRUE;
+				}
+				else if (status == G_IO_STATUS_AGAIN) {
+					if (gtk_events_pending ()) {
+						intermediate_file_count_update (gsearch);
+						while (gtk_events_pending ()) {
+							if (gsearch->command_details->command_status == MAKE_IT_QUIT) {
+								break;
+							}
+							gtk_main_iteration ();
+
+						}
+					}
+				}
+
+			} while (status == G_IO_STATUS_AGAIN && broken_pipe == FALSE);
+
+			if (broken_pipe == TRUE) {
+				break;
+			}
+
+			if (status != G_IO_STATUS_NORMAL) {
+				if (error != NULL) {
+					g_warning ("handle_search_command_stderr_io(): %s", error->message);
+					g_error_free (error);
+				}
+				continue;
+			}
+
+			if (truncate_error_msgs == FALSE) {
+				if ((strstr (string->str, "ermission denied") == NULL) &&
+			   	    (strstr (string->str, "No such file or directory") == NULL) &&
+			   	    (strncmp (string->str, "grep: ", 6) != 0) &&
+			 	    (strcmp (string->str, "find: ") != 0)) {
+					utf8 = g_locale_to_utf8 (string->str, -1, NULL, NULL, NULL);
+					error_msgs = g_string_append (error_msgs, utf8);
+					truncate_error_msgs = limit_string_to_x_lines (error_msgs, 20);
+				}
+			}
+
+		} while (g_io_channel_get_buffer_condition (ioc) & G_IO_IN);
+
+		g_string_free (string, TRUE);
+		g_free (utf8);
+	}
+
+	if (!(condition & G_IO_IN) || broken_pipe == TRUE) {
+
+		if (error_msgs != NULL) {
+
+			if (error_msgs->len > 0) {
+
+				GtkWidget * dialog;
+
+				if (truncate_error_msgs) {
+					error_msgs = g_string_append (error_msgs,
+				     		_("\n... Too many errors to display ..."));
+				}
+
+				if (gsearch->command_details->is_command_using_quick_mode != TRUE) {
+
+					GtkWidget * hbox;
+					GtkWidget * spacer;
+					GtkWidget * expander;
+					GtkWidget * label;
+
+					dialog = gtk_message_dialog_new (GTK_WINDOW (gsearch->window),
+					                                 GTK_DIALOG_DESTROY_WITH_PARENT,
+					                                 GTK_MESSAGE_ERROR,
+					                                 GTK_BUTTONS_OK,
+					                                 _("The search results may be invalid."
+									   "  There were errors while performing this search."));
+					gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), " ");
+
+					gtk_window_set_title (GTK_WINDOW (dialog), "");
+					gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
+
+					hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+
+					spacer = gtk_label_new ("     ");
+					gtk_box_pack_start (GTK_BOX (hbox), spacer, FALSE, FALSE, 0);
+
+					expander = gtk_expander_new_with_mnemonic (_("Show more _details"));
+					gtk_container_set_border_width (GTK_CONTAINER (expander), 6);
+					gtk_expander_set_spacing (GTK_EXPANDER (expander), 6);
+					gtk_box_pack_start (GTK_BOX (hbox), expander, TRUE, TRUE, 0);
+
+					label = gtk_label_new (error_msgs->str);
+					gtk_container_add (GTK_CONTAINER (expander), label);
+
+					gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), hbox, FALSE, FALSE, 0);
+					gtk_widget_show_all (hbox);
+
+					g_signal_connect (dialog, "response",
+					                  G_CALLBACK (gtk_widget_destroy),
+					                  NULL);
+
+					gtk_widget_show (dialog);
+				}
+				else if ((gsearch->command_details->is_command_second_pass_enabled == FALSE) ||
+					 (is_second_scan_excluded_path (gsearch->command_details->look_in_folder_string) == TRUE)) {
+
+					GtkWidget * button;
+					GtkWidget * hbox;
+					GtkWidget * spacer;
+					GtkWidget * expander;
+					GtkWidget * label;
+
+					dialog = gtk_message_dialog_new (GTK_WINDOW (gsearch->window),
+					                                 GTK_DIALOG_DESTROY_WITH_PARENT,
+					                                 GTK_MESSAGE_ERROR,
+					                                 GTK_BUTTONS_CANCEL,
+					                                 _("The search results may be out of date or invalid."
+									   "  Do you want to disable the quick search feature?"));
+					gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+					                                          "Please reference the help documentation for instructions "
+										  "on how to configure and enable quick searches.");
+
+					gtk_window_set_title (GTK_WINDOW (dialog), "");
+					gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
+
+					hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+
+					spacer = gtk_label_new ("     ");
+					gtk_box_pack_start (GTK_BOX (hbox), spacer, FALSE, FALSE, 0);
+
+					expander = gtk_expander_new_with_mnemonic (_("Show more _details"));
+					gtk_container_set_border_width (GTK_CONTAINER (expander), 6);
+					gtk_expander_set_spacing (GTK_EXPANDER (expander), 6);
+					gtk_box_pack_start (GTK_BOX (hbox), expander, TRUE, TRUE, 0);
+
+					label = gtk_label_new (error_msgs->str);
+					gtk_container_add (GTK_CONTAINER (expander), label);
+
+					gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), hbox, FALSE, FALSE, 0);
+					gtk_widget_show_all (hbox);
+
+					button = gsearchtool_button_new_with_icon (_("Disable _Quick Search"), "gtk-ok");
+					gtk_widget_set_can_default (button, TRUE);
+					gtk_widget_show (button);
+
+					gtk_dialog_add_action_widget (GTK_DIALOG (dialog), button, GTK_RESPONSE_OK);
+					gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
+
+					g_signal_connect (dialog, "response",
+					                  G_CALLBACK (disable_quick_search_cb),
+					                  (gpointer) gsearch);
+
+					gtk_widget_show (dialog);
+				}
+			}
+			truncate_error_msgs = FALSE;
+			g_string_truncate (error_msgs, 0);
+		}
+		g_io_channel_shutdown (ioc, TRUE, NULL);
+		return FALSE;
+	}
+	return TRUE;
+}
+
+static void
+child_command_set_pgid_cb (gpointer data)
+{
+	if (setpgid (0, 0) < 0) {
+		g_print (_("Failed to set process group id of child %d: %s.\n"),
+		         getpid (), g_strerror (errno));
+	}
+}
+
+void
+spawn_search_command (GSearchWindow * gsearch,
+                      gchar * command)
+{
+	GIOChannel * ioc_stdout;
+	GIOChannel * ioc_stderr;
+	GError * error = NULL;
+	gchar ** argv  = NULL;
+	gint child_stdout;
+	gint child_stderr;
+
+	if (!g_shell_parse_argv (command, NULL, &argv, &error)) {
+		GtkWidget * dialog;
+
+		stop_animation (gsearch);
+
+		dialog = gtk_message_dialog_new (GTK_WINDOW (gsearch->window),
+		                                 GTK_DIALOG_DESTROY_WITH_PARENT,
+		                                 GTK_MESSAGE_ERROR,
+		                                 GTK_BUTTONS_OK,
+		                                 _("Error parsing the search command."));
+		gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+		                                          (error == NULL) ? " " : error->message, NULL);
+
+		gtk_window_set_title (GTK_WINDOW (dialog), "");
+		gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
+		gtk_box_set_spacing (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), 14);
+
+		gtk_dialog_run (GTK_DIALOG (dialog));
+		gtk_widget_destroy (dialog);
+		g_error_free (error);
+		g_strfreev (argv);
+
+		/* Free the gchar fields of search_command structure. */
+		g_free (gsearch->command_details->look_in_folder_string);
+		g_free (gsearch->command_details->name_contains_pattern_string);
+		g_free (gsearch->command_details->name_contains_regex_string);
+		return;
+	}
+
+	if (!g_spawn_async_with_pipes (g_get_home_dir (), argv, NULL,
+				       G_SPAWN_SEARCH_PATH,
+				       child_command_set_pgid_cb, NULL, &gsearch->command_details->command_pid, NULL, &child_stdout,
+				       &child_stderr, &error)) {
+		GtkWidget * dialog;
+
+		stop_animation (gsearch);
+
+		dialog = gtk_message_dialog_new (GTK_WINDOW (gsearch->window),
+		                                 GTK_DIALOG_DESTROY_WITH_PARENT,
+		                                 GTK_MESSAGE_ERROR,
+		                                 GTK_BUTTONS_OK,
+		                                 _("Error running the search command."));
+		gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+		                                          (error == NULL) ? " " : error->message, NULL);
+
+		gtk_window_set_title (GTK_WINDOW (dialog), "");
+		gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
+		gtk_box_set_spacing (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), 14);
+
+		gtk_dialog_run (GTK_DIALOG (dialog));
+		gtk_widget_destroy (dialog);
+		g_error_free (error);
+		g_strfreev (argv);
+
+		/* Free the gchar fields of search_command structure. */
+		g_free (gsearch->command_details->look_in_folder_string);
+		g_free (gsearch->command_details->name_contains_pattern_string);
+		g_free (gsearch->command_details->name_contains_regex_string);
+		return;
+	}
+
+	if (gsearch->command_details->is_command_first_pass == TRUE) {
+
+		gsearch->command_details->command_status = RUNNING;
+		gsearch->search_results_pixbuf_hash_table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
+		gsearch->search_results_filename_hash_table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+
+		/* Get the value of the caja date-format key if available. */
+		if (gsearch->caja_schema_exists) {
+			gsearch->search_results_date_format = g_settings_get_enum (gsearch->caja_settings, "date-format");
+		} else {
+			gsearch->search_results_date_format = CAJA_DATE_FORMAT_LOCALE;
+		}
+
+		gtk_tree_view_scroll_to_point (GTK_TREE_VIEW (gsearch->search_results_tree_view), 0, 0);
+		gtk_tree_model_foreach (GTK_TREE_MODEL (gsearch->search_results_list_store),
+					(GtkTreeModelForeachFunc) tree_model_iter_free_monitor, gsearch);
+		gtk_list_store_clear (GTK_LIST_STORE (gsearch->search_results_list_store));
+
+		gtk_tree_view_column_set_visible (gsearch->search_results_folder_column, TRUE);
+		gtk_tree_view_column_set_visible (gsearch->search_results_size_column, TRUE);
+		gtk_tree_view_column_set_visible (gsearch->search_results_type_column, TRUE);
+		gtk_tree_view_column_set_visible (gsearch->search_results_date_column, TRUE);
+	}
+
+	ioc_stdout = g_io_channel_unix_new (child_stdout);
+	ioc_stderr = g_io_channel_unix_new (child_stderr);
+
+	g_io_channel_set_encoding (ioc_stdout, NULL, NULL);
+	g_io_channel_set_encoding (ioc_stderr, NULL, NULL);
+
+	g_io_channel_set_flags (ioc_stdout, G_IO_FLAG_NONBLOCK, NULL);
+	g_io_channel_set_flags (ioc_stderr, G_IO_FLAG_NONBLOCK, NULL);
+
+	g_io_add_watch (ioc_stdout, G_IO_IN | G_IO_HUP,
+			handle_search_command_stdout_io, gsearch);
+	g_io_add_watch (ioc_stderr, G_IO_IN | G_IO_HUP,
+			handle_search_command_stderr_io, gsearch);
+
+	g_io_channel_unref (ioc_stdout);
+	g_io_channel_unref (ioc_stderr);
+	g_strfreev (argv);
+}
+
+static GtkWidget *
+create_constraint_box (GSearchWindow * gsearch,
+                       GSearchConstraint * opt,
+                       gchar * value)
+{
+	GtkWidget * hbox;
+	GtkWidget * label;
+	GtkWidget * entry;
+	GtkWidget * entry_hbox;
+	GtkWidget * button;
+
+	hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
+
+	switch (GSearchOptionTemplates[opt->constraint_id].type) {
+	case SEARCH_CONSTRAINT_TYPE_BOOLEAN:
+		{
+			gchar * text = remove_mnemonic_character (GSearchOptionTemplates[opt->constraint_id].desc);
+			gchar * desc = g_strconcat (LEFT_LABEL_SPACING, _(text), ".", NULL);
+			label = gtk_label_new (desc);
+			gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
+			g_free (desc);
+			g_free (text);
+		}
+		break;
+	case SEARCH_CONSTRAINT_TYPE_TEXT:
+	case SEARCH_CONSTRAINT_TYPE_NUMERIC:
+	case SEARCH_CONSTRAINT_TYPE_DATE_BEFORE:
+	case SEARCH_CONSTRAINT_TYPE_DATE_AFTER:
+		{
+			gchar * desc = g_strconcat (LEFT_LABEL_SPACING, _(GSearchOptionTemplates[opt->constraint_id].desc), ":", NULL);
+			label = gtk_label_new_with_mnemonic (desc);
+			g_free (desc);
+		}
+
+		/* add description label */
+		gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
+
+		if (GSearchOptionTemplates[opt->constraint_id].type == SEARCH_CONSTRAINT_TYPE_TEXT) {
+			entry = gtk_entry_new ();
+			if (value != NULL) {
+				gtk_entry_set_text (GTK_ENTRY (entry), value);
+				opt->data.text = value;
+			}
+		}
+		else {
+			entry = gtk_spin_button_new_with_range (0, 999999999, 1);
+			if (value != NULL) {
+				gtk_spin_button_set_value (GTK_SPIN_BUTTON (entry), atoi (value));
+				opt->data.time = atoi (value);
+				opt->data.number = atoi (value);
+			}
+		}
+
+		if (gsearch->is_window_accessible) {
+			gchar * text = remove_mnemonic_character (GSearchOptionTemplates[opt->constraint_id].desc);
+			gchar * name;
+			gchar * desc;
+
+			if (GSearchOptionTemplates[opt->constraint_id].units == NULL) {
+				name = g_strdup (_(text));
+				desc = g_strdup_printf (_("Enter a text value for the \"%s\" search option."), _(text));
+			}
+			else {
+				/* Translators:  Below is a string displaying the search options name
+				and unit value.  For example, "\"Date modified less than\" in days". */
+				name = g_strdup_printf (_("\"%s\" in %s"), _(text),
+				                        _(GSearchOptionTemplates[opt->constraint_id].units));
+				desc = g_strdup_printf (_("Enter a value in %s for the \"%s\" search option."),
+				                        _(GSearchOptionTemplates[opt->constraint_id].units),
+				                        _(text));
+			}
+			add_atk_namedesc (GTK_WIDGET (entry), name, desc);
+			g_free (name);
+			g_free (desc);
+			g_free (text);
+		}
+
+		gtk_label_set_mnemonic_widget (GTK_LABEL (label), GTK_WIDGET (entry));
+
+		g_signal_connect (entry, "changed",
+		                  G_CALLBACK (constraint_update_info_cb),
+		                  opt);
+
+		g_signal_connect (entry, "activate",
+		                  G_CALLBACK (constraint_activate_cb),
+				  (gpointer) gsearch);
+
+		/* add text field */
+		entry_hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+		gtk_box_pack_start (GTK_BOX (hbox), entry_hbox, TRUE, TRUE, 0);
+		gtk_box_pack_start (GTK_BOX (entry_hbox), entry, TRUE, TRUE, 0);
+
+		/* add units label */
+		if (GSearchOptionTemplates[opt->constraint_id].units != NULL)
+		{
+			label = gtk_label_new_with_mnemonic (_(GSearchOptionTemplates[opt->constraint_id].units));
+			gtk_box_pack_start (GTK_BOX (entry_hbox), label, FALSE, FALSE, 0);
+		}
+
+		break;
+	default:
+		/* This should never happen.  If it does, there is a bug */
+		label = gtk_label_new ("???");
+		gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, 0);
+	        break;
+	}
+
+	button = GTK_WIDGET (g_object_new (GTK_TYPE_BUTTON,
+					   "label", "gtk-remove",
+					   "use-stock", TRUE,
+					   "use-underline", TRUE,
+					   NULL));
+
+	gtk_widget_set_can_default (button, FALSE);
+
+	{
+		GList * list = NULL;
+
+		list = g_list_append (list, (gpointer) gsearch);
+		list = g_list_append (list, (gpointer) opt);
+
+		g_signal_connect (button, "clicked",
+		                  G_CALLBACK (remove_constraint_cb),
+		                  (gpointer) list);
+
+	}
+	gtk_size_group_add_widget (gsearch->available_options_button_size_group, button);
+	gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
+
+	if (gsearch->is_window_accessible) {
+		gchar * text = remove_mnemonic_character (GSearchOptionTemplates[opt->constraint_id].desc);
+		gchar * name = g_strdup_printf (_("Remove \"%s\""), _(text));
+		gchar * desc = g_strdup_printf (_("Click to remove the \"%s\" search option."), _(text));
+		add_atk_namedesc (GTK_WIDGET (button), name, desc);
+		g_free (name);
+		g_free (desc);
+		g_free (text);
+	}
+	return hbox;
+}
+
+void
+add_constraint (GSearchWindow * gsearch,
+                gint constraint_id,
+                gchar * value,
+                gboolean show_constraint)
+{
+	GSearchConstraint * constraint = g_slice_new (GSearchConstraint);
+	GtkWidget * widget;
+
+	if (show_constraint) {
+		if (gtk_widget_get_visible (gsearch->available_options_vbox) == FALSE) {
+			gtk_expander_set_expanded (GTK_EXPANDER (gsearch->show_more_options_expander), TRUE);
+			gtk_widget_show (gsearch->available_options_vbox);
+		}
+	}
+
+	gsearch->window_geometry.min_height += WINDOW_HEIGHT_STEP;
+
+	if (gtk_widget_get_visible (gsearch->available_options_vbox)) {
+		gtk_window_set_geometry_hints (GTK_WINDOW (gsearch->window),
+		                               GTK_WIDGET (gsearch->window),
+		                               &gsearch->window_geometry,
+		                               GDK_HINT_MIN_SIZE);
+	}
+
+	constraint->constraint_id = constraint_id;
+	set_constraint_info_defaults (constraint);
+	set_constraint_gsettings_boolean (constraint->constraint_id, TRUE);
+
+	widget = create_constraint_box (gsearch, constraint, value);
+	gtk_box_pack_start (GTK_BOX (gsearch->available_options_vbox), widget, FALSE, FALSE, 0);
+	gtk_widget_show_all (widget);
+
+	gsearch->available_options_selected_list =
+		g_list_append (gsearch->available_options_selected_list, constraint);
+
+	set_constraint_selected_state (gsearch, constraint->constraint_id, TRUE);
+}
+
+static void
+set_sensitive (GtkCellLayout * cell_layout,
+               GtkCellRenderer * cell,
+               GtkTreeModel * tree_model,
+               GtkTreeIter * iter,
+               gpointer data)
+{
+	GtkTreePath * path;
+	gint idx;
+
+	path = gtk_tree_model_get_path (tree_model, iter);
+	idx = gtk_tree_path_get_indices (path)[0];
+	gtk_tree_path_free (path);
+
+	g_object_set (cell, "sensitive", !(GSearchOptionTemplates[idx].is_selected), NULL);
+}
+
+static gboolean
+is_separator (GtkTreeModel * model,
+              GtkTreeIter * iter,
+              gpointer data)
+{
+	GtkTreePath * path;
+	gint idx;
+
+	path = gtk_tree_model_get_path (model, iter);
+	idx = gtk_tree_path_get_indices (path)[0];
+	gtk_tree_path_free (path);
+
+	return (GSearchOptionTemplates[idx].type == SEARCH_CONSTRAINT_TYPE_SEPARATOR);
+}
+
+static void
+create_additional_constraint_section (GSearchWindow * gsearch)
+{
+	GtkCellRenderer * renderer;
+	GtkTreeModel * model;
+	GtkWidget * hbox;
+	gchar * desc;
+
+	gsearch->available_options_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
+	hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
+
+	gtk_box_pack_end (GTK_BOX (gsearch->available_options_vbox), hbox, FALSE, FALSE, 0);
+
+	desc = g_strconcat (LEFT_LABEL_SPACING, _("A_vailable options:"), NULL);
+	gsearch->available_options_label = gtk_label_new_with_mnemonic (desc);
+	g_free (desc);
+
+	gtk_box_pack_start (GTK_BOX (hbox), gsearch->available_options_label, FALSE, FALSE, 0);
+
+	model = gsearch_create_list_of_templates ();
+	gsearch->available_options_combo_box = gtk_combo_box_new_with_model (model);
+	g_object_unref (model);
+
+	gtk_label_set_mnemonic_widget (GTK_LABEL (gsearch->available_options_label), GTK_WIDGET (gsearch->available_options_combo_box));
+	gtk_combo_box_set_active (GTK_COMBO_BOX (gsearch->available_options_combo_box), 0);
+	gtk_box_pack_start (GTK_BOX (hbox), gsearch->available_options_combo_box, TRUE, TRUE, 0);
+
+	renderer = gtk_cell_renderer_text_new ();
+	gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (gsearch->available_options_combo_box),
+	                            renderer,
+	                            TRUE);
+	gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (gsearch->available_options_combo_box), renderer,
+	                                "text", 0,
+	                                NULL);
+	gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (gsearch->available_options_combo_box),
+	                                    renderer,
+	                                    set_sensitive,
+	                                    NULL, NULL);
+	gtk_combo_box_set_row_separator_func (GTK_COMBO_BOX (gsearch->available_options_combo_box),
+	                                      is_separator, NULL, NULL);
+
+	if (gsearch->is_window_accessible) {
+		add_atk_namedesc (GTK_WIDGET (gsearch->available_options_combo_box), _("Available options"),
+				  _("Select a search option from the drop-down list."));
+	}
+
+	gsearch->available_options_add_button = GTK_WIDGET (g_object_new (GTK_TYPE_BUTTON,
+									  "label", "gtk-add",
+									  "use-stock", TRUE,
+									  "use-underline", TRUE,
+									  NULL));
+
+	gtk_widget_set_can_default (gsearch->available_options_add_button, FALSE);
+	gsearch->available_options_button_size_group = gtk_size_group_new (GTK_SIZE_GROUP_BOTH);
+	gtk_size_group_add_widget (gsearch->available_options_button_size_group, gsearch->available_options_add_button);
+
+	g_signal_connect (gsearch->available_options_add_button, "clicked",
+			  G_CALLBACK (add_constraint_cb),
+	                  (gpointer) gsearch);
+
+	if (gsearch->is_window_accessible) {
+		add_atk_namedesc (GTK_WIDGET (gsearch->available_options_add_button), _("Add search option"),
+				  _("Click to add the selected available search option."));
+	}
+
+	gtk_box_pack_end (GTK_BOX (hbox), gsearch->available_options_add_button, FALSE, FALSE, 0);
+}
+
+static void
+filename_cell_data_func (GtkTreeViewColumn * column,
+                         GtkCellRenderer * renderer,
+                         GtkTreeModel * model,
+                         GtkTreeIter * iter,
+                         GSearchWindow * gsearch)
+{
+	GtkTreePath * path;
+	PangoUnderline underline;
+	gboolean underline_set;
+
+	if (gsearch->is_search_results_single_click_to_activate == TRUE) {
+
+		path = gtk_tree_model_get_path (model, iter);
+
+		if ((gsearch->search_results_hover_path == NULL) ||
+		    (gtk_tree_path_compare (path, gsearch->search_results_hover_path) != 0)) {
+			underline = PANGO_UNDERLINE_NONE;
+			underline_set = FALSE;
+		}
+		else {
+			underline = PANGO_UNDERLINE_SINGLE;
+			underline_set = TRUE;
+		}
+		gtk_tree_path_free (path);
+	}
+	else {
+		underline = PANGO_UNDERLINE_NONE;
+		underline_set = FALSE;
+	}
+
+	g_object_set (gsearch->search_results_name_cell_renderer,
+	              "underline", underline,
+	              "underline-set", underline_set,
+	              NULL);
+}
+
+static gboolean
+gsearch_equal_func (GtkTreeModel * model,
+                    gint column,
+                    const gchar * key,
+                    GtkTreeIter * iter,
+                    gpointer search_data)
+{
+	gboolean results = TRUE;
+	gchar * name;
+
+	gtk_tree_model_get (model, iter, COLUMN_NAME, &name, -1);
+
+	if (name != NULL) {
+		gchar * casefold_key;
+		gchar * casefold_name;
+
+		casefold_key = g_utf8_casefold (key, -1);
+		casefold_name = g_utf8_casefold (name, -1);
+
+		if ((casefold_key != NULL) &&
+		    (casefold_name != NULL) &&
+		    (strstr (casefold_name, casefold_key) != NULL)) {
+			results = FALSE;
+		}
+		g_free (casefold_key);
+		g_free (casefold_name);
+		g_free (name);
+	}
+	return results;
+}
+
+static GtkWidget *
+create_search_results_section (GSearchWindow * gsearch)
+{
+	GtkWidget * label;
+	GtkWidget * vbox;
+	GtkWidget * hbox;
+	GtkWidget * window;
+	GtkTreeViewColumn * column;
+	GtkCellRenderer * renderer;
+
+	vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
+	hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+
+	gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
+
+	label = gtk_label_new_with_mnemonic (_("S_earch results:"));
+	g_object_set (G_OBJECT (label), "xalign", 0.0, NULL);
+	gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
+
+	gsearch->progress_spinner = gtk_spinner_new ();
+	gtk_widget_set_size_request (gsearch->progress_spinner,
+                                     GTK_ICON_SIZE_MENU, GTK_ICON_SIZE_MENU);
+	gtk_box_pack_start (GTK_BOX (hbox), gsearch->progress_spinner, FALSE, FALSE, 0);
+
+	gsearch->files_found_label = gtk_label_new (NULL);
+	gtk_label_set_selectable (GTK_LABEL (gsearch->files_found_label), TRUE);
+	g_object_set (G_OBJECT (gsearch->files_found_label), "xalign", 1.0, NULL);
+	gtk_box_pack_start (GTK_BOX (hbox), gsearch->files_found_label, TRUE, TRUE, 0);
+
+	window = gtk_scrolled_window_new (NULL, NULL);
+	gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (window), GTK_SHADOW_IN);
+	gtk_container_set_border_width (GTK_CONTAINER (window), 0);
+	gtk_widget_set_size_request (window, 530, 160);
+	gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (window),
+                                        GTK_POLICY_AUTOMATIC,
+                                        GTK_POLICY_AUTOMATIC);
+
+	gsearch->search_results_list_store = gtk_list_store_new (NUM_COLUMNS,
+					      GDK_TYPE_PIXBUF,
+					      G_TYPE_STRING,
+					      G_TYPE_STRING,
+					      G_TYPE_STRING,
+					      G_TYPE_STRING,
+					      G_TYPE_DOUBLE,
+					      G_TYPE_STRING,
+					      G_TYPE_STRING,
+					      G_TYPE_DOUBLE,
+					      G_TYPE_POINTER,
+					      G_TYPE_BOOLEAN);
+
+	gsearch->search_results_tree_view = GTK_TREE_VIEW (gtk_tree_view_new_with_model (GTK_TREE_MODEL (gsearch->search_results_list_store)));
+
+	gtk_tree_view_set_headers_visible (gsearch->search_results_tree_view, FALSE);
+	gtk_tree_view_set_search_equal_func (gsearch->search_results_tree_view,
+	                                     gsearch_equal_func, NULL, NULL);
+  	g_object_unref (G_OBJECT (gsearch->search_results_list_store));
+
+	if (gsearch->is_window_accessible) {
+		add_atk_namedesc (GTK_WIDGET (gsearch->search_results_tree_view), _("List View"), NULL);
+	}
+
+	gsearch->search_results_selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (gsearch->search_results_tree_view));
+
+	gtk_tree_selection_set_mode (GTK_TREE_SELECTION (gsearch->search_results_selection),
+				     GTK_SELECTION_MULTIPLE);
+
+	gtk_drag_source_set (GTK_WIDGET (gsearch->search_results_tree_view),
+			     GDK_BUTTON1_MASK | GDK_BUTTON2_MASK,
+			     GSearchDndTable, GSearchTotalDnds,
+			     GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_ASK);
+
+	g_signal_connect (gsearch->search_results_tree_view, "drag_data_get",
+	                  G_CALLBACK (drag_file_cb),
+	                  (gpointer) gsearch);
+
+	g_signal_connect (gsearch->search_results_tree_view, "drag_begin",
+	                  G_CALLBACK (drag_begin_file_cb),
+	                  (gpointer) gsearch);
+
+	g_signal_connect (gsearch->search_results_tree_view, "event_after",
+	                  G_CALLBACK (file_event_after_cb),
+	                  (gpointer) gsearch);
+
+	g_signal_connect (gsearch->search_results_tree_view, "button_release_event",
+	                  G_CALLBACK (file_button_release_event_cb),
+	                  (gpointer) gsearch);
+
+	g_signal_connect (gsearch->search_results_tree_view, "button_press_event",
+	                  G_CALLBACK (file_button_press_event_cb),
+	                  (gpointer) gsearch->search_results_tree_view);
+
+	g_signal_connect (gsearch->search_results_tree_view, "key_press_event",
+			  G_CALLBACK (file_key_press_event_cb),
+			  (gpointer) gsearch);
+
+	g_signal_connect (gsearch->search_results_tree_view, "motion_notify_event",
+	                  G_CALLBACK (file_motion_notify_cb),
+	                  (gpointer) gsearch);
+
+	g_signal_connect (gsearch->search_results_tree_view, "leave_notify_event",
+	                  G_CALLBACK (file_leave_notify_cb),
+	                  (gpointer) gsearch);
+
+	gtk_label_set_mnemonic_widget (GTK_LABEL (label), GTK_WIDGET (gsearch->search_results_tree_view));
+
+	gtk_container_add (GTK_CONTAINER (window), GTK_WIDGET (gsearch->search_results_tree_view));
+	gtk_box_pack_end (GTK_BOX (vbox), window, TRUE, TRUE, 0);
+
+	/* create the name column */
+	column = gtk_tree_view_column_new ();
+	gtk_tree_view_column_set_title (column, _("Name"));
+
+	renderer = gtk_cell_renderer_pixbuf_new ();
+	gtk_tree_view_column_pack_start (column, renderer, FALSE);
+        gtk_tree_view_column_set_attributes (column, renderer,
+                                             "pixbuf", COLUMN_ICON,
+                                             NULL);
+
+	gsearch->search_results_name_cell_renderer = gtk_cell_renderer_text_new ();
+        gtk_tree_view_column_pack_start (column, gsearch->search_results_name_cell_renderer, TRUE);
+        gtk_tree_view_column_set_attributes (column, gsearch->search_results_name_cell_renderer,
+                                             "text", COLUMN_NAME,
+					     NULL);
+	gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
+	gtk_tree_view_column_set_resizable (column, TRUE);
+	gtk_tree_view_column_set_sort_column_id (column, COLUMN_NAME);
+	gtk_tree_view_column_set_reorderable (column, TRUE);
+	gtk_tree_view_column_set_cell_data_func (column, renderer,
+	                                         (GtkTreeCellDataFunc) filename_cell_data_func,
+						 gsearch, NULL);
+	gtk_tree_view_append_column (GTK_TREE_VIEW (gsearch->search_results_tree_view), column);
+
+	/* create the folder column */
+	renderer = gtk_cell_renderer_text_new ();
+	column = gtk_tree_view_column_new_with_attributes (_("Folder"), renderer,
+							   "text", COLUMN_RELATIVE_PATH,
+							   NULL);
+	gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
+	gtk_tree_view_column_set_resizable (column, TRUE);
+	gtk_tree_view_column_set_sort_column_id (column, COLUMN_RELATIVE_PATH);
+	gtk_tree_view_column_set_reorderable (column, TRUE);
+	gtk_tree_view_append_column (GTK_TREE_VIEW (gsearch->search_results_tree_view), column);
+	gsearch->search_results_folder_column = column;
+
+	/* create the size column */
+	renderer = gtk_cell_renderer_text_new ();
+	g_object_set (renderer, "xalign", 1.0, NULL);
+	column = gtk_tree_view_column_new_with_attributes (_("Size"), renderer,
+							   "text", COLUMN_READABLE_SIZE,
+							   NULL);
+	gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
+	gtk_tree_view_column_set_resizable (column, TRUE);
+	gtk_tree_view_column_set_sort_column_id (column, COLUMN_SIZE);
+	gtk_tree_view_column_set_reorderable (column, TRUE);
+	gtk_tree_view_append_column (GTK_TREE_VIEW (gsearch->search_results_tree_view), column);
+	gsearch->search_results_size_column = column;
+
+	/* create the type column */
+	renderer = gtk_cell_renderer_text_new ();
+	column = gtk_tree_view_column_new_with_attributes (_("Type"), renderer,
+							   "text", COLUMN_TYPE,
+							   NULL);
+	gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
+	gtk_tree_view_column_set_resizable (column, TRUE);
+	gtk_tree_view_column_set_sort_column_id (column, COLUMN_TYPE);
+	gtk_tree_view_column_set_reorderable (column, TRUE);
+	gtk_tree_view_append_column (GTK_TREE_VIEW (gsearch->search_results_tree_view), column);
+	gsearch->search_results_type_column = column;
+
+	/* create the date modified column */
+	renderer = gtk_cell_renderer_text_new ();
+	column = gtk_tree_view_column_new_with_attributes (_("Date Modified"), renderer,
+							   "text", COLUMN_READABLE_DATE,
+							   NULL);
+	gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
+	gtk_tree_view_column_set_resizable (column, TRUE);
+	gtk_tree_view_column_set_sort_column_id (column, COLUMN_DATE);
+	gtk_tree_view_column_set_reorderable (column, TRUE);
+	gtk_tree_view_append_column (GTK_TREE_VIEW (gsearch->search_results_tree_view), column);
+	gsearch->search_results_date_column = column;
+
+	gsearchtool_set_columns_order (gsearch->search_results_tree_view);
+
+	g_signal_connect (gsearch->search_results_tree_view, "columns-changed",
+	                  G_CALLBACK (columns_changed_cb),
+	                  (gpointer) gsearch);
+	return vbox;
+}
+
+void
+set_clone_command (GSearchWindow * gsearch,
+                   gint * argcp,
+                   gchar *** argvp,
+                   gpointer client_data,
+                   gboolean escape_values)
+{
+	gchar ** argv;
+	gchar * file_is_named_utf8;
+	gchar * file_is_named_locale;
+	gchar * look_in_folder_locale;
+	gchar * tmp;
+	GList * list;
+	gint  i = 0;
+
+	argv = g_new0 (gchar*, SEARCH_CONSTRAINT_MAXIMUM_POSSIBLE);
+
+	argv[i++] = (gchar *) client_data;
+
+	file_is_named_utf8 = (gchar *) gtk_entry_get_text (GTK_ENTRY (gsearch_history_entry_get_entry (GSEARCH_HISTORY_ENTRY (gsearch->name_contains_entry))));
+	file_is_named_locale = g_locale_from_utf8 (file_is_named_utf8 != NULL ? file_is_named_utf8 : "" ,
+	                                           -1, NULL, NULL, NULL);
+	if (escape_values)
+		tmp = g_shell_quote (file_is_named_locale);
+	else
+		tmp = g_strdup (file_is_named_locale);
+	argv[i++] = g_strdup_printf ("--named=%s", tmp);
+	g_free (tmp);
+	g_free (file_is_named_locale);
+
+	look_in_folder_locale = gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (gsearch->look_in_folder_button));
+
+	if (look_in_folder_locale == NULL) {
+		look_in_folder_locale = g_strdup ("");
+	}
+
+	if (escape_values)
+		tmp = g_shell_quote (look_in_folder_locale);
+	else
+		tmp = g_strdup (look_in_folder_locale);
+	argv[i++] = g_strdup_printf ("--path=%s", tmp);
+	g_free (tmp);
+	g_free (look_in_folder_locale);
+
+	if (gtk_widget_get_visible (gsearch->available_options_vbox)) {
+		for (list = gsearch->available_options_selected_list; list != NULL; list = g_list_next (list)) {
+			GSearchConstraint * constraint = list->data;
+			gchar * locale = NULL;
+
+			switch (constraint->constraint_id) {
+			case SEARCH_CONSTRAINT_CONTAINS_THE_TEXT:
+				locale = g_locale_from_utf8 (constraint->data.text, -1, NULL, NULL, NULL);
+				if (escape_values)
+					tmp = g_shell_quote (locale);
+				else
+					tmp = g_strdup (locale);
+				argv[i++] = g_strdup_printf ("--contains=%s", tmp);
+				g_free (tmp);
+				break;
+			case SEARCH_CONSTRAINT_DATE_MODIFIED_BEFORE:
+				argv[i++] = g_strdup_printf ("--mtimeless=%d", constraint->data.time);
+				break;
+			case SEARCH_CONSTRAINT_DATE_MODIFIED_AFTER:
+				argv[i++] = g_strdup_printf ("--mtimemore=%d", constraint->data.time);
+				break;
+			case SEARCH_CONSTRAINT_SIZE_IS_MORE_THAN:
+				argv[i++] = g_strdup_printf ("--sizemore=%u", constraint->data.number);
+				break;
+			case SEARCH_CONSTRAINT_SIZE_IS_LESS_THAN:
+				argv[i++] = g_strdup_printf ("--sizeless=%u", constraint->data.number);
+				break;
+			case SEARCH_CONSTRAINT_FILE_IS_EMPTY:
+				argv[i++] = g_strdup ("--empty");
+				break;
+			case SEARCH_CONSTRAINT_OWNED_BY_USER:
+				locale = g_locale_from_utf8 (constraint->data.text, -1, NULL, NULL, NULL);
+				if (escape_values)
+					tmp = g_shell_quote (locale);
+				else
+					tmp = g_strdup (locale);
+				argv[i++] = g_strdup_printf ("--user=%s", tmp);
+				g_free (tmp);
+				break;
+			case SEARCH_CONSTRAINT_OWNED_BY_GROUP:
+				locale = g_locale_from_utf8 (constraint->data.text, -1, NULL, NULL, NULL);
+				if (escape_values)
+					tmp = g_shell_quote (locale);
+				else
+					tmp = g_strdup (locale);
+				argv[i++] = g_strdup_printf ("--group=%s", tmp);
+				g_free (tmp);
+				break;
+			case SEARCH_CONSTRAINT_OWNER_IS_UNRECOGNIZED:
+				argv[i++] = g_strdup ("--nouser");
+				break;
+			case SEARCH_CONSTRAINT_FILE_IS_NOT_NAMED:
+				locale = g_locale_from_utf8 (constraint->data.text, -1, NULL, NULL, NULL);
+				if (escape_values)
+					tmp = g_shell_quote (locale);
+				else
+					tmp = g_strdup (locale);
+				argv[i++] = g_strdup_printf ("--notnamed=%s", tmp);
+				g_free (tmp);
+				break;
+			case SEARCH_CONSTRAINT_FILE_MATCHES_REGULAR_EXPRESSION:
+				locale = g_locale_from_utf8 (constraint->data.text, -1, NULL, NULL, NULL);
+				if (escape_values)
+					tmp = g_shell_quote (locale);
+				else
+					tmp = g_strdup (locale);
+				argv[i++] = g_strdup_printf ("--regex=%s", tmp);
+				g_free (tmp);
+				break;
+			case SEARCH_CONSTRAINT_SHOW_HIDDEN_FILES_AND_FOLDERS:
+				argv[i++] = g_strdup ("--hidden");
+				break;
+			case SEARCH_CONSTRAINT_FOLLOW_SYMBOLIC_LINKS:
+				argv[i++] = g_strdup ("--follow");
+				break;
+			case SEARCH_CONSTRAINT_SEARCH_OTHER_FILESYSTEMS:
+				argv[i++] = g_strdup ("--mounts");
+				break;
+			default:
+				break;
+			}
+			g_free (locale);
+		}
+	}
+	*argvp = argv;
+	*argcp = i;
+}
+
+static void
+handle_gsettings_settings (GSearchWindow * gsearch)
+{
+	if (g_settings_get_boolean (gsearch->mate_search_tool_settings, "show-additional-options")) {
+		if (gtk_widget_get_visible (gsearch->available_options_vbox) == FALSE) {
+			gtk_expander_set_expanded (GTK_EXPANDER (gsearch->show_more_options_expander), TRUE);
+			gtk_widget_show (gsearch->available_options_vbox);
+		}
+	}
+
+	if (g_settings_get_boolean (gsearch->mate_search_tool_select_settings, "contains-the-text")) {
+		add_constraint (gsearch, SEARCH_CONSTRAINT_CONTAINS_THE_TEXT, "", FALSE);
+	}
+
+	if (g_settings_get_boolean (gsearch->mate_search_tool_select_settings, "date-modified-less-than")) {
+		add_constraint (gsearch, SEARCH_CONSTRAINT_DATE_MODIFIED_BEFORE, "", FALSE);
+	}
+
+	if (g_settings_get_boolean (gsearch->mate_search_tool_select_settings, "date-modified-more-than")) {
+		add_constraint (gsearch, SEARCH_CONSTRAINT_DATE_MODIFIED_AFTER, "", FALSE);
+	}
+
+	if (g_settings_get_boolean (gsearch->mate_search_tool_select_settings, "size-at-least")) {
+		add_constraint (gsearch, SEARCH_CONSTRAINT_SIZE_IS_MORE_THAN, "", FALSE);
+	}
+
+	if (g_settings_get_boolean (gsearch->mate_search_tool_select_settings, "size-at-most")) {
+		add_constraint (gsearch, SEARCH_CONSTRAINT_SIZE_IS_LESS_THAN, "", FALSE);
+	}
+
+	if (g_settings_get_boolean (gsearch->mate_search_tool_select_settings, "file-is-empty")) {
+		add_constraint (gsearch, SEARCH_CONSTRAINT_FILE_IS_EMPTY, NULL, FALSE);
+	}
+
+	if (g_settings_get_boolean (gsearch->mate_search_tool_select_settings, "owned-by-user")) {
+		add_constraint (gsearch, SEARCH_CONSTRAINT_OWNED_BY_USER, "", FALSE);
+	}
+
+	if (g_settings_get_boolean (gsearch->mate_search_tool_select_settings, "owned-by-group")) {
+		add_constraint (gsearch, SEARCH_CONSTRAINT_OWNED_BY_GROUP, "", FALSE);
+	}
+
+	if (g_settings_get_boolean (gsearch->mate_search_tool_select_settings, "owner-is-unrecognized")) {
+		add_constraint (gsearch, SEARCH_CONSTRAINT_OWNER_IS_UNRECOGNIZED, NULL, FALSE);
+	}
+
+	if (g_settings_get_boolean (gsearch->mate_search_tool_select_settings, "name-does-not-contain")) {
+		add_constraint (gsearch, SEARCH_CONSTRAINT_FILE_IS_NOT_NAMED, "", FALSE);
+	}
+
+	if (g_settings_get_boolean (gsearch->mate_search_tool_select_settings, "name-matches-regular-expression")) {
+		add_constraint (gsearch, SEARCH_CONSTRAINT_FILE_MATCHES_REGULAR_EXPRESSION, "", FALSE);
+	}
+
+	if (g_settings_get_boolean (gsearch->mate_search_tool_select_settings, "show-hidden-files-and-folders")) {
+		add_constraint (gsearch, SEARCH_CONSTRAINT_SHOW_HIDDEN_FILES_AND_FOLDERS, NULL, FALSE);
+	}
+
+	if (g_settings_get_boolean (gsearch->mate_search_tool_select_settings, "follow-symbolic-links")) {
+		add_constraint (gsearch, SEARCH_CONSTRAINT_FOLLOW_SYMBOLIC_LINKS, NULL, FALSE);
+	}
+
+	if (g_settings_get_boolean (gsearch->mate_search_tool_select_settings, "exclude-other-filesystems")) {
+		add_constraint (gsearch, SEARCH_CONSTRAINT_SEARCH_OTHER_FILESYSTEMS, NULL, FALSE);
+	}
+}
+
+static void
+gsearch_window_size_allocate (GtkWidget * widget,
+                              GtkAllocation * allocation,
+                              GSearchWindow * gsearch)
+{
+	if (gsearch->is_window_maximized == FALSE) {
+		gsearch->window_width = allocation->width;
+		gsearch->window_height = allocation->height;
+	}
+}
+
+static GtkWidget *
+gsearch_app_create (GSearchWindow * gsearch)
+{
+	gchar * locale_string;
+	gchar * utf8_string;
+	GtkWidget * hbox;
+	GtkWidget * vbox;
+	GtkWidget * entry;
+	GtkWidget * label;
+	GtkWidget * button;
+	GtkWidget * container;
+
+	gsearch->mate_search_tool_settings = g_settings_new ("org.mate.search-tool");
+	gsearch->mate_search_tool_select_settings = g_settings_new ("org.mate.search-tool.select");
+	gsearch->mate_desktop_interface_settings = g_settings_new ("org.mate.interface");
+
+	/* Check if caja schema is installed before trying to read caja settings */
+	gsearch->caja_schema_exists = FALSE;
+	GSettingsSchema *schema = g_settings_schema_source_lookup (g_settings_schema_source_get_default (),
+								   CAJA_PREFERENCES_SCHEMA,
+								   FALSE);
+
+	if (schema != NULL) {
+		gsearch->caja_schema_exists = TRUE;
+		g_settings_schema_unref (schema);
+	}
+
+	if (gsearch->caja_schema_exists) {
+		gsearch->caja_settings = g_settings_new (CAJA_PREFERENCES_SCHEMA);
+	} else {
+		gsearch->caja_settings = NULL;
+	}
+
+	gsearch->window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+	gsearch->is_window_maximized = g_settings_get_boolean (gsearch->mate_search_tool_settings, "default-window-maximized");
+	g_signal_connect (gsearch->window, "size-allocate",
+			  G_CALLBACK (gsearch_window_size_allocate),
+			  gsearch);
+	gsearch->command_details = g_slice_new0 (GSearchCommandDetails);
+	gsearch->window_geometry.min_height = MINIMUM_WINDOW_HEIGHT;
+	gsearch->window_geometry.min_width  = MINIMUM_WINDOW_WIDTH;
+
+	gtk_window_set_position (GTK_WINDOW (gsearch->window), GTK_WIN_POS_CENTER);
+	gtk_window_set_geometry_hints (GTK_WINDOW (gsearch->window), GTK_WIDGET (gsearch->window),
+				       &gsearch->window_geometry, GDK_HINT_MIN_SIZE);
+
+	gsearchtool_get_stored_window_geometry (&gsearch->window_width,
+	                                        &gsearch->window_height);
+	gtk_window_set_default_size (GTK_WINDOW (gsearch->window),
+	                             gsearch->window_width,
+	                             gsearch->window_height);
+
+	if (gsearch->is_window_maximized == TRUE) {
+		gtk_window_maximize (GTK_WINDOW (gsearch->window));
+	}
+
+	container = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
+	gtk_container_add (GTK_CONTAINER (gsearch->window), container);
+	gtk_container_set_border_width (GTK_CONTAINER (container), 12);
+
+	hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+	gtk_box_pack_start (GTK_BOX (container), hbox, FALSE, FALSE, 0);
+
+	gsearch->name_and_folder_table = gtk_grid_new ();
+	gtk_grid_set_row_spacing (GTK_GRID (gsearch->name_and_folder_table), 6);
+	gtk_grid_set_column_spacing (GTK_GRID (gsearch->name_and_folder_table), 12);
+	gtk_container_add (GTK_CONTAINER (hbox), gsearch->name_and_folder_table);
+
+	label = gtk_label_new_with_mnemonic (_("_Name contains:"));
+	gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
+	g_object_set (G_OBJECT (label), "xalign", 0.0, NULL);
+
+	gtk_grid_attach (GTK_GRID (gsearch->name_and_folder_table), label, 0, 0, 1, 1);
+
+	gsearch->name_contains_entry = gsearch_history_entry_new ("gsearchtool-file-entry", FALSE);
+	gtk_label_set_mnemonic_widget (GTK_LABEL (label), gsearch->name_contains_entry);
+	gsearch_history_entry_set_history_length (GSEARCH_HISTORY_ENTRY (gsearch->name_contains_entry), 10);
+	gtk_widget_set_hexpand (gsearch->name_contains_entry, TRUE);
+	gtk_grid_attach (GTK_GRID (gsearch->name_and_folder_table), gsearch->name_contains_entry, 1, 0, 1, 1);
+	entry =  gsearch_history_entry_get_entry (GSEARCH_HISTORY_ENTRY (gsearch->name_contains_entry));
+
+	if (GTK_IS_ACCESSIBLE (gtk_widget_get_accessible (gsearch->name_contains_entry))) {
+		gsearch->is_window_accessible = TRUE;
+		add_atk_namedesc (gsearch->name_contains_entry, NULL, _("Enter a filename or partial filename with or without wildcards."));
+		add_atk_namedesc (entry, _("Name contains"), _("Enter a filename or partial filename with or without wildcards."));
+	}
+	g_signal_connect (gsearch_history_entry_get_entry (GSEARCH_HISTORY_ENTRY (gsearch->name_contains_entry)), "activate",
+			  G_CALLBACK (name_contains_activate_cb),
+			  (gpointer) gsearch);
+
+	label = gtk_label_new_with_mnemonic (_("_Look in folder:"));
+	gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
+	g_object_set (G_OBJECT (label), "xalign", 0.0, NULL);
+
+	gtk_grid_attach (GTK_GRID (gsearch->name_and_folder_table), label, 0, 1, 1, 1);
+
+	gsearch->look_in_folder_button = gtk_file_chooser_button_new (_("Browse"), GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
+	gtk_label_set_mnemonic_widget (GTK_LABEL (label), GTK_WIDGET (gsearch->look_in_folder_button));
+	gtk_widget_set_hexpand (gsearch->look_in_folder_button, TRUE);
+	gtk_grid_attach (GTK_GRID (gsearch->name_and_folder_table), gsearch->look_in_folder_button, 1, 1, 1, 1);
+
+	g_signal_connect (gsearch->look_in_folder_button, "current-folder-changed",
+	                  G_CALLBACK (look_in_folder_changed_cb),
+	                  (gpointer) gsearch);
+
+	if (gsearch->is_window_accessible) {
+		add_atk_namedesc (GTK_WIDGET (gsearch->look_in_folder_button), _("Look in folder"), _("Select the folder or device from which you want to begin the search."));
+	}
+
+	locale_string = g_settings_get_string (gsearch->mate_search_tool_settings, "look-in-folder");
+
+	if ((g_file_test (locale_string, G_FILE_TEST_EXISTS) == FALSE) ||
+	    (g_file_test (locale_string, G_FILE_TEST_IS_DIR) == FALSE)) {
+		g_free (locale_string);
+		locale_string = g_get_current_dir ();
+	}
+
+	utf8_string = g_filename_to_utf8 (locale_string, -1, NULL, NULL, NULL);
+
+	gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (gsearch->look_in_folder_button), utf8_string);
+
+	g_free (locale_string);
+	g_free (utf8_string);
+
+	gsearch->show_more_options_expander = gtk_expander_new_with_mnemonic (_("Select more _options"));
+	gtk_box_pack_start (GTK_BOX (container), gsearch->show_more_options_expander, FALSE, FALSE, 0);
+	g_signal_connect (gsearch->show_more_options_expander, "notify::expanded",
+	                  G_CALLBACK (click_expander_cb),
+	                  (gpointer) gsearch);
+
+	create_additional_constraint_section (gsearch);
+	gtk_box_pack_start (GTK_BOX (container), GTK_WIDGET (gsearch->available_options_vbox), FALSE, FALSE, 0);
+
+	if (gsearch->is_window_accessible) {
+		add_atk_namedesc (GTK_WIDGET (gsearch->show_more_options_expander), _("Select more options"), _("Click to expand or collapse the list of available options."));
+		add_atk_relation (GTK_WIDGET (gsearch->available_options_vbox), GTK_WIDGET (gsearch->show_more_options_expander), ATK_RELATION_CONTROLLED_BY);
+		add_atk_relation (GTK_WIDGET (gsearch->show_more_options_expander), GTK_WIDGET (gsearch->available_options_vbox), ATK_RELATION_CONTROLLER_FOR);
+	}
+
+	vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
+	gtk_box_pack_start (GTK_BOX (container), vbox, TRUE, TRUE, 0);
+
+	gsearch->search_results_vbox = create_search_results_section (gsearch);
+	gtk_widget_set_sensitive (GTK_WIDGET (gsearch->search_results_vbox), FALSE);
+	gtk_box_pack_start (GTK_BOX (vbox), gsearch->search_results_vbox, TRUE, TRUE, 0);
+
+	hbox = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
+	gtk_button_box_set_layout (GTK_BUTTON_BOX (hbox), GTK_BUTTONBOX_END);
+	gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
+
+	gtk_box_set_spacing (GTK_BOX (hbox), 6);
+
+	button = GTK_WIDGET (g_object_new (GTK_TYPE_BUTTON,
+					   "label", "gtk-help",
+					   "use-stock", TRUE,
+					   "use-underline", TRUE,
+					   NULL));
+
+	gtk_widget_set_can_default (button, TRUE);
+	gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
+	gtk_button_box_set_child_secondary (GTK_BUTTON_BOX (hbox), button, TRUE);
+	g_signal_connect (button, "clicked",
+	                  G_CALLBACK (click_help_cb),
+	                  (gpointer) gsearch->window);
+  	if (gsearch->is_window_accessible) {
+		add_atk_namedesc (GTK_WIDGET (button), NULL, _("Click to display the help manual."));
+	}
+
+	button = GTK_WIDGET (g_object_new (GTK_TYPE_BUTTON,
+					   "label", "gtk-close",
+					   "use-stock", TRUE,
+					   "use-underline", TRUE,
+					   NULL));
+
+	gtk_widget_set_can_default (button, TRUE);
+	g_signal_connect (button, "clicked",
+	                  G_CALLBACK (click_close_cb),
+	                  (gpointer) gsearch);
+  	if (gsearch->is_window_accessible) {
+		add_atk_namedesc (GTK_WIDGET (button), NULL, _("Click to close \"Search for Files\"."));
+	}
+
+	gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
+
+	/* Find and Stop buttons... */
+	gsearch->find_button = GTK_WIDGET (g_object_new (GTK_TYPE_BUTTON,
+							 "label", "gtk-find",
+							 "use-stock", TRUE,
+							 "use-underline", TRUE,
+							 NULL));
+
+	gsearch->stop_button = GTK_WIDGET (g_object_new (GTK_TYPE_BUTTON,
+							 "label", "gtk-stop",
+							 "use-stock", TRUE,
+							 "use-underline", TRUE,
+							 NULL));
+
+	gtk_widget_set_can_default (gsearch->find_button, TRUE);
+	gtk_widget_set_can_default (gsearch->stop_button, TRUE);
+
+	gtk_box_pack_end (GTK_BOX (hbox), gsearch->stop_button, FALSE, FALSE, 0);
+	gtk_box_pack_end (GTK_BOX (hbox), gsearch->find_button, FALSE, FALSE, 0);
+
+	gtk_widget_set_sensitive (gsearch->stop_button, FALSE);
+	gtk_widget_set_sensitive (gsearch->find_button, TRUE);
+
+	g_signal_connect (gsearch->find_button, "clicked",
+	                  G_CALLBACK (click_find_cb),
+	                  (gpointer) gsearch);
+    	g_signal_connect (gsearch->find_button, "size_allocate",
+	                  G_CALLBACK (size_allocate_cb),
+	                  (gpointer) gsearch->available_options_add_button);
+	g_signal_connect (gsearch->stop_button, "clicked",
+	                  G_CALLBACK (click_stop_cb),
+	                  (gpointer) gsearch);
+
+	if (gsearch->is_window_accessible) {
+		add_atk_namedesc (GTK_WIDGET (gsearch->find_button), NULL, _("Click to perform a search."));
+		add_atk_namedesc (GTK_WIDGET (gsearch->stop_button), NULL, _("Click to stop a search."));
+	}
+
+	gtk_widget_show_all (container);
+	gtk_widget_hide (gsearch->available_options_vbox);
+	gtk_widget_hide (gsearch->progress_spinner);
+	gtk_widget_hide (gsearch->stop_button);
+
+	gtk_window_set_focus (GTK_WINDOW (gsearch->window),
+		GTK_WIDGET (gsearch_history_entry_get_entry (GSEARCH_HISTORY_ENTRY (gsearch->name_contains_entry))));
+
+	gtk_window_set_default (GTK_WINDOW (gsearch->window), gsearch->find_button);
+
+	return gsearch->window;
+}
+
+static void
+gsearch_window_finalize (GObject * object)
+{
+        parent_class->finalize (object);
+}
+
+static void
+gsearch_window_class_init (GSearchWindowClass * klass, void * dara)
+{
+	GObjectClass * object_class = (GObjectClass *) klass;
+
+	object_class->finalize = gsearch_window_finalize;
+	parent_class = g_type_class_peek_parent (klass);
+}
+
+GType
+gsearch_window_get_type (void)
+{
+	static GType object_type = 0;
+
+	if (!object_type) {
+		static const GTypeInfo object_info = {
+			sizeof (GSearchWindowClass),
+			NULL,
+			NULL,
+			(GClassInitFunc) gsearch_window_class_init,
+			NULL,
+			NULL,
+			sizeof (GSearchWindow),
+			0,
+			(GInstanceInitFunc)(void (*)(void)) gsearch_app_create,
+			NULL
+		};
+		object_type = g_type_register_static (GTK_TYPE_WINDOW, "GSearchWindow", &object_info, 0);
+	}
+	return object_type;
+}
+
+static void
+gsearchtool_setup_gsettings_notifications (GSearchWindow * gsearch)
+
+{
+	gchar * click_to_activate_pref;
+
+	/* Use the default double click behavior if caja isn't installed */
+	if (gsearch->caja_schema_exists == FALSE) {
+		gsearch->is_search_results_single_click_to_activate = FALSE;
+		return;
+	}
+
+	g_signal_connect (gsearch->caja_settings,
+	                  "changed::click-policy",
+	                  G_CALLBACK (single_click_to_activate_key_changed_cb),
+	                  gsearch);
+
+	/* Get value of caja click behavior (single or double click to activate items) */
+	click_to_activate_pref = g_settings_get_string (gsearch->caja_settings, "click-policy");
+
+	gsearch->is_search_results_single_click_to_activate =
+		(strncmp (click_to_activate_pref, "single", 6) == 0) ? TRUE : FALSE;
+
+	g_free (click_to_activate_pref);
+}
+
+int
+main (int argc,
+      char * argv[])
+{
+	GSearchWindow * gsearch;
+	GOptionContext * context;
+	GtkWidget * window;
+	GError * error = NULL;
+	EggSMClient * client;
+
+#ifdef ENABLE_NLS
+	setlocale (LC_ALL, "");
+	bindtextdomain (GETTEXT_PACKAGE, MATELOCALEDIR);
+	bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+	textdomain (GETTEXT_PACKAGE);
+#endif /* ENABLE_NLS */
+
+	context = g_option_context_new (N_("- the MATE Search Tool"));
+#ifdef ENABLE_NLS
+	g_option_context_set_translation_domain(context, GETTEXT_PACKAGE);
+#endif /* ENABLE_NLS */
+	gsearch_setup_goption_descriptions ();
+	g_option_context_add_main_entries (context, GSearchGOptionEntries, GETTEXT_PACKAGE);
+	g_option_context_add_group (context, gtk_get_option_group (TRUE));
+	g_option_context_add_group (context, egg_sm_client_get_option_group ());
+	g_option_context_parse (context, &argc, &argv, &error);
+
+	if (error) {
+		g_printerr (_("Failed to parse command line arguments: %s\n"), error->message);
+		return (-1);
+	}
+
+	g_option_context_free (context);
+
+	g_set_application_name (_("Search for Files"));
+	gtk_window_set_default_icon_name (MATE_SEARCH_TOOL_ICON);
+
+	window = g_object_new (GSEARCH_TYPE_WINDOW, NULL);
+	gsearch = GSEARCH_WINDOW (window);
+
+	gtk_window_set_resizable (GTK_WINDOW (gsearch->window), TRUE);
+
+	g_signal_connect (gsearch->window, "delete_event",
+	                  G_CALLBACK (quit_cb),
+	                  (gpointer) gsearch);
+	g_signal_connect (gsearch->window, "key_press_event",
+	                  G_CALLBACK (key_press_cb),
+	                  (gpointer) gsearch);
+	g_signal_connect (gsearch->window, "window_state_event",
+	                  G_CALLBACK (window_state_event_cb),
+	                  (gpointer) gsearch);
+
+	if ((client = egg_sm_client_get ()) != NULL) {
+		g_signal_connect (client, "save_state",
+		                  G_CALLBACK (save_session_cb),
+		                  (gpointer) gsearch);
+		g_signal_connect (client, "quit",
+		                  G_CALLBACK (quit_session_cb),
+		                  (gpointer) gsearch);
+	}
+
+	gtk_widget_show (gsearch->window);
+
+	gsearchtool_setup_gsettings_notifications (gsearch);
+
+	if (handle_goption_args (gsearch) == FALSE) {
+		handle_gsettings_settings (gsearch);
+	}
+
+	gtk_main ();
+	return 0;
+}
+
+ +
+ +
+ + diff --git a/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/17.html b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/17.html new file mode 100644 index 00000000..9bf535f2 --- /dev/null +++ b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/17.html @@ -0,0 +1,1097 @@ + + + + + + Cppcheck - HTML report - mate-utils + + + + + +
+ + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2; -*- */
+/* Copyright (C) 2008 Cosimo Cecchi <cosimoc@gnome.org>
+ * Copyright (C) 2012-2021 MATE Developers
+ *
+ * This file is part of MATE Utils.
+ *
+ * MATE Utils is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * MATE Utils is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MATE Utils.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "logview-app.h"
+
+#include "logview-manager.h"
+#include "logview-window.h"
+#include "logview-prefs.h"
+
+#include <glib/gi18n.h>
+
+struct _LogviewAppPrivate {
+  LogviewPrefs *prefs;
+  LogviewManager *manager;
+  LogviewWindow *window;
+};
+
+enum {
+  APP_QUIT,
+  LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+static LogviewApp *app_singleton = NULL;
+
+G_DEFINE_TYPE_WITH_PRIVATE (LogviewApp, logview_app, G_TYPE_OBJECT);
+
+static gboolean
+main_window_delete_cb (GtkWidget *widget,
+                       GdkEvent *event,
+                       gpointer user_data)
+{
+  LogviewApp *app = user_data;
+
+  g_signal_emit (app, signals[APP_QUIT], 0, NULL);
+
+  return FALSE;
+}
+
+static gboolean
+logview_app_set_window (LogviewApp *app)
+{
+  LogviewWindow *window;
+  gboolean retval = FALSE;
+
+  window = LOGVIEW_WINDOW (logview_window_new ());
+
+  if (window) {
+    app->priv->window = window;
+    g_signal_connect (window, "delete-event",
+                      G_CALLBACK (main_window_delete_cb), app);
+    retval = TRUE;
+  }
+
+  gtk_window_set_default_icon_name ("mate-system-log");
+
+  return retval;
+}
+
+typedef struct {
+  LogviewApp *app;
+  GSList *logs;
+} EnumerateJob;
+
+/* TODO: ideally we should parse configuration files in /etc/logrotate.conf
+ * and all the files in /etc/logrotate.d/ and group all the logs referring
+ * to the same entry under a category. Right now, we just do some
+ * parsing instead, and fill with quasi-sensible defaults.
+ */
+
+/* adapted from sysklogd sources */
+static GSList*
+parse_syslog (void)
+{
+  char cbuf[BUFSIZ];
+  char *cline, *p;
+  FILE *cf;
+  GSList *logfiles = NULL;
+
+  if ((cf = fopen ("/etc/syslog.conf", "r")) == NULL) {
+    return NULL;
+  }
+
+  cline = cbuf;
+  while (fgets (cline, sizeof (cbuf) - (cline - cbuf), cf) != NULL) {
+    gchar **list;
+    gint i;
+
+    for (p = cline; g_ascii_isspace (*p); ++p);
+    if (*p == '\0' || *p == '#' || *p == '\n')
+      continue;
+
+    list = g_strsplit_set (p, ", -\t()\n", 0);
+
+    for (i = 0; list[i]; ++i) {
+      if (*list[i] == '/' &&
+          g_slist_find_custom (logfiles, list[i],
+                               (GCompareFunc) g_ascii_strcasecmp) == NULL)
+      {
+        logfiles = g_slist_insert (logfiles,
+                                   g_strdup (list[i]), 0);
+      }
+    }
+
+    g_strfreev (list);
+  }
+
+  fclose (cf);
+
+  return logfiles;
+}
+
+static void
+enumerate_job_finish (EnumerateJob *job)
+{
+  GSList *files = job->logs;
+  LogviewApp *app = job->app;
+
+  logview_manager_add_logs_from_name_list (app->priv->manager, files, files->data);
+
+  g_slist_free_full (files, g_free);
+
+  g_object_unref (job->app);
+  g_slice_free (EnumerateJob, job);
+}
+
+static void
+enumerate_next_files_async_cb (GObject *source,
+                               GAsyncResult *res,
+                               gpointer user_data)
+{
+  EnumerateJob *job = user_data;
+  GList *enumerated_files, *l;
+  GFileInfo *info;
+  GSList *logs;
+  const char *content_type, *name;
+  char *parse_string, *container_path;
+  GFileType type;
+  GFile *container;
+
+  enumerated_files = g_file_enumerator_next_files_finish (G_FILE_ENUMERATOR (source),
+                                                          res, NULL);
+  if (!enumerated_files) {
+    enumerate_job_finish (job);
+    return;
+  }
+
+  logs = job->logs;
+  container = g_file_enumerator_get_container (G_FILE_ENUMERATOR (source));
+  container_path = g_file_get_path (container);
+
+  /* TODO: we don't support grouping rotated logs yet, skip gzipped files
+   * and those which name contains a formatted date.
+   */
+  for (l = enumerated_files; l; l = l->next) {
+    info = l->data;
+    type = g_file_info_get_file_type (info);
+    content_type = g_file_info_get_content_type (info);
+    name = g_file_info_get_name (info);
+
+    if (!g_file_info_get_attribute_boolean (info, "access::can-read")) {
+      g_object_unref (info);
+      continue;
+    }
+
+    if (((type != G_FILE_TYPE_REGULAR) && (type != G_FILE_TYPE_SYMBOLIC_LINK)) ||
+        !g_content_type_is_a (content_type, "text/plain"))
+    {
+      g_object_unref (info);
+      continue;
+    }
+
+    if (g_content_type_is_a (content_type, "application/x-gzip")) {
+      g_object_unref (info);
+      continue;
+    }
+
+    if (g_regex_match_simple ("\\d{8}$", name, 0, 0)) {
+      g_object_unref (info);
+      continue;
+    }
+
+    parse_string = g_build_filename (container_path, name, NULL);
+
+    if (g_slist_find_custom (logs, parse_string, (GCompareFunc) g_ascii_strcasecmp) == NULL) {
+      logs = g_slist_append (logs, parse_string);
+    } else {
+      g_free (parse_string);
+    }
+
+    g_object_unref (info);
+    parse_string = NULL;
+  }
+
+  g_list_free (enumerated_files);
+  g_object_unref (container);
+  g_free (container_path);
+
+  job->logs = logs;
+
+  enumerate_job_finish (job);
+}
+
+static void
+enumerate_children_async_cb (GObject *source,
+                             GAsyncResult *res,
+                             gpointer user_data)
+{
+  EnumerateJob *job = user_data;
+  GFileEnumerator *enumerator;
+
+  enumerator = g_file_enumerate_children_finish (G_FILE (source),
+                                                 res, NULL);
+  if (!enumerator) {
+    enumerate_job_finish (job);
+    return;
+  }
+
+  g_file_enumerator_next_files_async (enumerator, G_MAXINT,
+                                      G_PRIORITY_DEFAULT,
+                                      NULL, enumerate_next_files_async_cb, job);
+}
+
+static void
+logview_app_first_time_initialize (LogviewApp *app)
+{
+  GSList *logs;
+  GFile *log_dir;
+  EnumerateJob *job;
+
+  /* let's add all accessible files in /var/log and those mentioned
+   * in /etc/syslog.conf.
+   */
+
+  logs = parse_syslog ();
+
+  job = g_slice_new0 (EnumerateJob);
+  job->app = g_object_ref (app);
+  job->logs = logs;
+
+  log_dir = g_file_new_for_path ("/var/log/");
+  g_file_enumerate_children_async (log_dir,
+                                   "standard::*,access::can-read", 0,
+                                   G_PRIORITY_DEFAULT, NULL,
+                                   enumerate_children_async_cb, job);
+
+  g_object_unref (log_dir);
+}
+
+static void
+do_finalize (GObject *obj)
+{
+  LogviewApp *app = LOGVIEW_APP (obj);
+
+  g_object_unref (app->priv->manager);
+  g_object_unref (app->priv->prefs);
+
+  G_OBJECT_CLASS (logview_app_parent_class)->finalize (obj);
+}
+
+static void
+logview_app_class_init (LogviewAppClass *klass)
+{
+  GObjectClass *oclass = G_OBJECT_CLASS (klass);
+
+  oclass->finalize = do_finalize;
+
+  signals[APP_QUIT] =
+    g_signal_new ("app-quit",
+                  G_OBJECT_CLASS_TYPE (oclass),
+                  G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (LogviewAppClass, app_quit),
+                  NULL, NULL,
+                  g_cclosure_marshal_VOID__VOID,
+                  G_TYPE_NONE, 0);
+}
+
+static void
+logview_app_init (LogviewApp *self)
+{
+  LogviewAppPrivate *priv = self->priv = logview_app_get_instance_private (self);
+
+  priv->prefs = logview_prefs_get ();
+  priv->manager = logview_manager_get ();
+}
+
+LogviewApp*
+logview_app_get (void)
+{
+  if (!app_singleton) {
+    app_singleton = g_object_new (LOGVIEW_TYPE_APP, NULL);
+
+    if (!logview_app_set_window (app_singleton)) {
+      g_object_unref (app_singleton);
+      app_singleton = NULL;
+    }
+  }
+
+  return app_singleton;
+}
+
+void
+logview_app_initialize (LogviewApp *app, char **log_files)
+{
+  LogviewAppPrivate *priv;
+
+  g_assert (LOGVIEW_IS_APP (app));
+
+  priv = app->priv;
+
+  /* open regular logs and add each log passed as a parameter */
+
+  if (log_files == NULL) {
+    char *active_log;
+    gchar **logs;
+
+    active_log = logview_prefs_get_active_logfile (priv->prefs);
+    logs = logview_prefs_get_stored_logfiles (priv->prefs);
+
+    if (!logs || !logs[0]) {
+      logview_app_first_time_initialize (app);
+    } else {
+      logview_manager_add_logs_from_names (priv->manager,
+                                           logs, active_log);
+
+      g_free (active_log);
+      g_strfreev (logs);
+    }
+  } else {
+    logview_manager_add_logs_from_names (priv->manager, log_files, NULL);
+  }
+
+  gtk_widget_show (GTK_WIDGET (priv->window));
+}
+
+void
+logview_app_add_error (LogviewApp *app,
+                       const char *file_path,
+                       const char *secondary)
+{
+  LogviewWindow *window;
+  char *primary;
+
+  g_assert (LOGVIEW_IS_APP (app));
+
+  window = app->priv->window;
+  primary = g_strdup_printf (_("Impossible to open the file %s"), file_path);
+
+  logview_window_add_error (window, primary, secondary);
+
+  g_free (primary);
+}
+
+static void
+check_error_prefs (gpointer data,
+                   gpointer user_data)
+{
+  gchar **strings = data;
+  LogviewApp *app = user_data;
+  GFile *file = g_file_new_for_path (strings[0]);
+
+  logview_prefs_remove_stored_log (app->priv->prefs, file);
+  g_object_unref (file);
+}
+
+void
+logview_app_add_errors (LogviewApp *app,
+                        GPtrArray *errors)
+{
+  LogviewWindow *window;
+
+  g_assert (LOGVIEW_IS_APP (app));
+
+  window = app->priv->window;
+
+  if (errors->len == 0) {
+    return;
+  }
+
+  g_ptr_array_foreach (errors, check_error_prefs, app);
+
+  if (errors->len == 1) {
+    char **err;
+
+    err = g_ptr_array_index (errors, 0);
+    logview_window_add_error (window, err[0], err[1]);
+  } else {
+    logview_window_add_errors (window, errors);
+  }
+}
+
+ +
+ +
+ + diff --git a/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/18.html b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/18.html new file mode 100644 index 00000000..2b67768c --- /dev/null +++ b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/18.html @@ -0,0 +1,1349 @@ + + + + + + Cppcheck - HTML report - mate-utils + + + + + +
+ + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
+479
+480
+481
+482
+483
+484
+485
+486
+487
+488
+489
+490
+491
+492
+493
+494
+495
+496
+497
+498
+499
+500
+501
+502
+503
+504
+505
+506
+507
+508
+509
+510
+511
+512
+513
+514
+515
+516
+517
+518
+519
+520
+521
+522
+523
+524
+525
+526
+527
+528
+529
+530
+531
+532
/*-*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2; -*- */
+/* Copyright (C) Johannes Schmid 2009 <jhs@gnome.org>
+ * Copyright (C) 2012-2021 MATE Developers
+ *
+ * This file is part of MATE Utils.
+ *
+ * MATE Utils is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * MATE Utils is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MATE Utils.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "logview-filter-manager.h"
+#include "logview-prefs.h"
+#include <gtk/gtk.h>
+#include <string.h>
+#include <glib/gi18n.h>
+
+#define UI_RESOURCE "/org/mate/system-log/logview-filter.ui"
+#define GET_WIDGET(x) (GTK_WIDGET (gtk_builder_get_object (builder, (x))))
+
+struct _LogviewFilterManagerPrivate {
+  GtkWidget *tree;
+
+  GtkWidget *add_button;
+  GtkWidget *remove_button;
+  GtkWidget *edit_button;
+
+  GtkTreeModel *model;
+  GtkBuilder* builder;
+
+  LogviewPrefs* prefs;
+};
+
+enum {
+  COLUMN_NAME = 0,
+  COLUMN_FILTER,
+  N_COLUMNS
+};
+
+G_DEFINE_TYPE_WITH_PRIVATE (LogviewFilterManager, logview_filter_manager, GTK_TYPE_DIALOG);
+
+static void
+logview_filter_manager_update_model (LogviewFilterManager *manager)
+{
+  GList *filters;
+  GList *filter;
+  gchar *name;
+  GtkTreeIter iter;
+
+  gtk_list_store_clear (GTK_LIST_STORE (manager->priv->model));
+
+  filters = logview_prefs_get_filters (manager->priv->prefs);
+
+  for (filter = filters; filter != NULL; filter = g_list_next (filter)) {
+    g_object_get (filter->data, "name", &name, NULL);
+
+    gtk_list_store_append (GTK_LIST_STORE(manager->priv->model), &iter);
+    gtk_list_store_set (GTK_LIST_STORE (manager->priv->model),
+                        &iter,
+                        COLUMN_NAME, name,
+                        COLUMN_FILTER, filter->data,
+                        -1);
+
+    g_free (name);
+  }
+
+  g_list_free (filters);
+}
+
+static gboolean
+check_name (LogviewFilterManager *manager, const gchar *name)
+{
+  GtkWidget *dialog;
+
+  if (!strlen (name)) {
+    dialog = gtk_message_dialog_new (GTK_WINDOW (manager),
+                                     GTK_DIALOG_MODAL,
+                                     GTK_MESSAGE_ERROR,
+                                     GTK_BUTTONS_CLOSE,
+                                     "%s", _("Filter name is empty!"));
+    gtk_dialog_run (GTK_DIALOG (dialog));
+
+    gtk_widget_destroy (dialog);
+
+    return FALSE;
+  }
+
+  if (strstr (name, ":") != NULL) {
+    dialog = gtk_message_dialog_new (GTK_WINDOW(manager),
+                                     GTK_DIALOG_MODAL,
+                                     GTK_MESSAGE_ERROR,
+                                     GTK_BUTTONS_CLOSE,
+                                     "%s", _("Filter name may not contain the ':' character"));
+    gtk_dialog_run (GTK_DIALOG (dialog));
+
+    gtk_widget_destroy (dialog);
+
+    return FALSE;
+  }
+
+  return TRUE;
+}
+
+static gboolean
+check_regex (LogviewFilterManager *manager, const gchar *regex)
+{
+  GtkWidget *dialog;
+  GError *error = NULL;
+  GRegex *reg;
+
+  if (!strlen (regex)) {
+    dialog = gtk_message_dialog_new (GTK_WINDOW(manager),
+                                     GTK_DIALOG_MODAL,
+                                     GTK_MESSAGE_ERROR,
+                                     GTK_BUTTONS_CLOSE,
+                                     "%s", _("Regular expression is empty!"));
+
+    gtk_dialog_run (GTK_DIALOG (dialog));
+
+    gtk_widget_destroy (dialog);
+
+    return FALSE;
+  }
+
+  reg = g_regex_new (regex,
+                     0, 0, &error);
+  if (error) {
+    dialog = gtk_message_dialog_new (GTK_WINDOW (manager),
+                                     GTK_DIALOG_MODAL,
+                                     GTK_MESSAGE_ERROR,
+                                     GTK_BUTTONS_CLOSE,
+                                     _("Regular expression is invalid: %s"),
+                                     error->message);
+    gtk_dialog_run (GTK_DIALOG (dialog));
+
+    gtk_widget_destroy (dialog);
+    g_error_free (error);
+
+    return FALSE;
+  }
+
+  g_regex_unref (reg);
+
+  return TRUE;
+}
+
+static void
+on_dialog_add_edit_reponse (GtkWidget *dialog, int response_id,
+                            LogviewFilterManager *manager)
+{
+  GtkWidget *entry_name, *entry_regex;
+  GtkWidget *radio_color;
+  GtkWidget *check_foreground, *check_background;
+  GtkWidget *color_foreground, *color_background;
+  gchar *old_name;
+  const gchar *name;
+  const gchar *regex;
+  LogviewFilter *filter;
+  GtkTextTag *tag;
+  GtkBuilder *builder;
+
+  old_name = g_object_get_data (G_OBJECT (manager), "old_name");
+  builder = manager->priv->builder;
+
+  entry_name = GET_WIDGET ("entry_name");
+  entry_regex = GET_WIDGET ("entry_regex");
+  radio_color = GET_WIDGET ("radio_color");
+  check_foreground = GET_WIDGET ("check_foreground");
+  check_background = GET_WIDGET ("check_background");
+  color_foreground = GET_WIDGET ("color_foreground");
+  color_background = GET_WIDGET ("color_background");
+
+  if (response_id == GTK_RESPONSE_APPLY) {
+    name = gtk_entry_get_text (GTK_ENTRY (entry_name));
+    regex = gtk_entry_get_text (GTK_ENTRY (entry_regex));
+
+    if (!check_name (manager, name) || !check_regex (manager, regex)) {
+      return;
+    }
+
+    filter = logview_filter_new (name, regex);
+    tag = gtk_text_tag_new (name);
+
+    if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (radio_color))) {
+      if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (check_foreground))
+          && !gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (check_background))) {
+          GtkWidget *error_dialog;
+
+          error_dialog = gtk_message_dialog_new (GTK_WINDOW (manager),
+                                                 GTK_DIALOG_MODAL,
+                                                 GTK_MESSAGE_ERROR,
+                                                 GTK_BUTTONS_CLOSE,
+                                                 "%s",
+                                                 _("Please specify either foreground or background color!"));
+          gtk_dialog_run (GTK_DIALOG (error_dialog));
+          gtk_widget_destroy (error_dialog);
+          g_object_unref (tag);
+          g_object_unref (filter);
+
+          return;
+      }
+
+      GdkRGBA foreground_color, background_color;
+
+      gtk_color_chooser_get_rgba (GTK_COLOR_CHOOSER (color_foreground), &foreground_color);
+      g_object_set (G_OBJECT (tag),
+                    "foreground-rgba", &foreground_color,
+                    "foreground-set", gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (check_foreground)),
+                    NULL);
+      gtk_color_chooser_get_rgba (GTK_COLOR_CHOOSER (color_background), &background_color);
+      g_object_set (tag,
+                    "paragraph-background-rgba", &background_color,
+                    "paragraph-background-set", gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (check_background)),
+                    NULL);
+    } else { /* !gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (radio_color)) */
+      g_object_set (tag, "invisible", TRUE, NULL);
+    }
+
+    if (old_name && !g_str_equal (old_name, name)) {
+      logview_prefs_remove_filter (manager->priv->prefs, old_name);
+    }
+
+    g_object_set (G_OBJECT (filter), "texttag", tag, NULL);
+    g_object_unref (tag);
+
+    logview_prefs_add_filter (manager->priv->prefs, filter);
+    g_object_unref (filter);
+
+    logview_filter_manager_update_model (manager);
+  }
+
+  gtk_widget_destroy (dialog);
+}
+
+static void
+run_add_edit_dialog (LogviewFilterManager *manager, LogviewFilter *filter)
+{
+  GError *error;
+  gchar *name, *regex;
+  const gchar *title;
+  GtkWidget *dialog, *entry_name, *entry_regex, *radio_color;
+  GtkWidget *radio_visible, *check_foreground, *check_background;
+  GtkWidget *color_foreground, *color_background;
+  gboolean foreground_set, background_set, invisible;
+  GtkTextTag *tag;
+  GtkBuilder* builder;
+
+  builder = manager->priv->builder;
+
+  error = NULL;
+  name = NULL;
+
+  if (gtk_builder_add_from_resource (builder, UI_RESOURCE, &error) == 0) {
+    g_warning ("Could not load filter ui: %s", error->message);
+    g_error_free (error);
+    return;
+  }
+
+  dialog = GET_WIDGET ("dialog_filter");
+  entry_name = GET_WIDGET ("entry_name");
+  entry_regex = GET_WIDGET ("entry_regex");
+  radio_color = GET_WIDGET ("radio_color");
+  radio_visible = GET_WIDGET ("radio_visible");
+  check_foreground = GET_WIDGET ("check_foreground");
+  check_background = GET_WIDGET ("check_background");
+  color_foreground = GET_WIDGET ("color_foreground");
+  color_background = GET_WIDGET ("color_background");
+
+  title = (filter != NULL ? _("Edit filter") : _("Add new filter"));
+  gtk_window_set_title (GTK_WINDOW (dialog), title);
+
+  if (filter) {
+    GdkRGBA *foreground, *background;
+
+    g_object_get (filter,
+                  "name", &name,
+                  "regex", &regex,
+                  "texttag", &tag,
+                  NULL);
+
+    g_object_get (tag,
+                  "foreground-set", &foreground_set,
+                  "paragraph-background-set", &background_set,
+                  "invisible", &invisible,
+                  NULL);
+
+    gtk_entry_set_text (GTK_ENTRY(entry_name), name);
+    gtk_entry_set_text (GTK_ENTRY(entry_regex), regex);
+
+    if (foreground_set) {
+      g_object_get (tag, "foreground-rgba", &foreground, NULL);
+      gtk_color_chooser_set_rgba (GTK_COLOR_CHOOSER (color_foreground),
+                                  foreground);
+      gdk_rgba_free (foreground);
+    }
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_foreground),
+                                  foreground_set);
+
+    if (background_set) {
+      g_object_get (tag, "paragraph-background-rgba", &background, NULL);
+      gtk_color_chooser_set_rgba (GTK_COLOR_CHOOSER (color_background),
+                                  background);
+      gdk_rgba_free (background);
+    }
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_background),
+                                  background_set);
+
+    if (background_set || foreground_set) {
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (radio_color), TRUE);
+    } else if (invisible) {
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (radio_visible), TRUE);
+    }
+
+    g_free (regex);
+    g_object_unref (tag);
+  }
+
+  g_object_set_data_full (G_OBJECT (manager), "old_name", name, g_free);
+
+  g_signal_connect (dialog, "response",
+                    G_CALLBACK (on_dialog_add_edit_reponse),
+                    manager);
+  gtk_window_set_transient_for (GTK_WINDOW (dialog),
+                                GTK_WINDOW (manager));
+  gtk_window_set_modal (GTK_WINDOW (dialog),
+                        TRUE);
+
+  gtk_widget_show (GTK_WIDGET (dialog));
+}
+
+static void
+on_add_clicked (GtkWidget *button, LogviewFilterManager *manager)
+{
+  run_add_edit_dialog (manager, NULL);
+}
+
+static void
+on_edit_clicked (GtkWidget *button, LogviewFilterManager *manager)
+{
+  GtkTreeIter iter;
+  GtkTreeModel *model;
+  LogviewFilter *filter;
+  GtkTreeSelection *selection;
+
+  selection =
+    gtk_tree_view_get_selection (GTK_TREE_VIEW (manager->priv->tree));
+
+  gtk_tree_selection_get_selected (selection, &model, &iter);
+  gtk_tree_model_get (model, &iter, COLUMN_FILTER, &filter, -1);
+
+  run_add_edit_dialog (manager, filter);
+
+  g_object_unref (filter);
+}
+
+static void
+on_remove_clicked (GtkWidget *button, LogviewFilterManager *manager)
+{
+  GtkTreeSelection *selection;
+  GtkTreeIter iter;
+  GtkTreeModel *model;
+  gchar *name;
+
+  selection  =
+    gtk_tree_view_get_selection (GTK_TREE_VIEW (manager->priv->tree));
+
+  gtk_tree_selection_get_selected (selection, &model, &iter);
+  gtk_tree_model_get (model, &iter, COLUMN_NAME, &name, -1);
+
+  logview_prefs_remove_filter (manager->priv->prefs, name);
+  logview_filter_manager_update_model (manager);
+
+  g_free(name);
+}
+
+static void
+on_tree_selection_changed (GtkTreeSelection *selection, LogviewFilterManager *manager)
+{
+  gboolean status;
+
+  status = gtk_tree_selection_get_selected (selection, NULL, NULL);
+
+  gtk_widget_set_sensitive (manager->priv->edit_button, status);
+  gtk_widget_set_sensitive (manager->priv->remove_button, status);
+}
+
+static void
+logview_filter_manager_init (LogviewFilterManager *manager)
+{
+  GtkWidget *grid;
+  GtkWidget *scrolled_window;
+  GtkTreeViewColumn *column;
+  GtkCellRenderer *text_renderer;
+  LogviewFilterManagerPrivate *priv;
+
+  manager->priv = logview_filter_manager_get_instance_private (manager);
+  priv = manager->priv;
+
+  priv->builder = gtk_builder_new ();
+  g_object_ref (priv->builder);
+  priv->prefs = logview_prefs_get ();
+
+  gtk_dialog_add_button (GTK_DIALOG(manager),
+                         "gtk-close",
+                         GTK_RESPONSE_CLOSE);
+  gtk_window_set_modal (GTK_WINDOW (manager),
+                        TRUE);
+
+  priv->model = GTK_TREE_MODEL (gtk_list_store_new (N_COLUMNS,
+                                                    G_TYPE_STRING,
+                                                    G_TYPE_OBJECT));
+  logview_filter_manager_update_model (manager);
+
+  grid = gtk_grid_new ();
+  gtk_grid_set_row_spacing (GTK_GRID (grid), 6);
+  gtk_grid_set_column_spacing (GTK_GRID (grid), 6);
+  scrolled_window = gtk_scrolled_window_new (NULL, NULL);
+  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
+                                  GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+  gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window),
+                                       GTK_SHADOW_ETCHED_IN);
+  priv->tree = gtk_tree_view_new_with_model (priv->model);
+  gtk_widget_set_size_request (priv->tree, 150, 200);
+  gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (priv->tree), FALSE);
+  gtk_container_add (GTK_CONTAINER (scrolled_window), priv->tree);
+
+  text_renderer = gtk_cell_renderer_text_new ();
+
+  column = gtk_tree_view_column_new();
+  gtk_tree_view_column_pack_start (column, text_renderer, TRUE);
+  gtk_tree_view_column_set_attributes (column,
+                                       text_renderer,
+                                       "text", COLUMN_NAME,
+                                       NULL);
+  gtk_tree_view_append_column (GTK_TREE_VIEW (priv->tree),
+                               column);
+
+  priv->add_button = GTK_WIDGET (g_object_new (GTK_TYPE_BUTTON,
+					       "label", "gtk-add",
+					       "use-stock", TRUE,
+					       "use-underline", TRUE,
+					       NULL));
+
+  priv->edit_button = GTK_WIDGET (g_object_new (GTK_TYPE_BUTTON,
+						"label", "gtk-properties",
+						"use-stock", TRUE,
+						"use-underline", TRUE,
+						NULL));
+
+  priv->remove_button = GTK_WIDGET (g_object_new (GTK_TYPE_BUTTON,
+						  "label", "gtk-remove",
+						  "use-stock", TRUE,
+						  "use-underline", TRUE,
+						  NULL));
+
+  gtk_window_set_title (GTK_WINDOW (manager),
+                        _("Filters"));
+
+  g_signal_connect (priv->add_button, "clicked",
+                    G_CALLBACK (on_add_clicked), manager);
+  g_signal_connect (priv->edit_button, "clicked",
+                    G_CALLBACK (on_edit_clicked), manager);
+  g_signal_connect (priv->remove_button, "clicked",
+                    G_CALLBACK (on_remove_clicked), manager);
+
+  gtk_widget_set_sensitive (priv->edit_button, FALSE);
+  gtk_widget_set_sensitive (priv->remove_button, FALSE);
+
+  g_signal_connect (gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->tree)),
+                    "changed", G_CALLBACK (on_tree_selection_changed),
+                    manager);
+
+  gtk_widget_set_hexpand (scrolled_window, TRUE);
+  gtk_widget_set_vexpand (scrolled_window, TRUE);
+  gtk_grid_attach (GTK_GRID (grid), scrolled_window, 0, 0, 1, 3);
+  gtk_widget_set_valign (priv->add_button, GTK_ALIGN_CENTER);
+  gtk_grid_attach (GTK_GRID (grid), priv->add_button, 1, 0, 1, 1);
+  gtk_widget_set_valign (priv->edit_button, GTK_ALIGN_CENTER);
+  gtk_grid_attach (GTK_GRID (grid), priv->edit_button, 1, 1, 1, 1);
+  gtk_widget_set_valign (priv->remove_button, GTK_ALIGN_CENTER);
+  gtk_grid_attach (GTK_GRID (grid), priv->remove_button, 1, 2, 1, 1);
+  gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (manager))),
+                      grid, TRUE, TRUE, 5);
+  gtk_widget_show_all (GTK_WIDGET (manager));
+}
+
+static void
+logview_filter_manager_dispose (GObject *object)
+{
+  LogviewFilterManager* manager;
+
+  manager = LOGVIEW_FILTER_MANAGER (object);
+
+  g_object_unref (manager->priv->builder);
+
+  G_OBJECT_CLASS (logview_filter_manager_parent_class)->dispose (object);
+}
+
+static void
+logview_filter_manager_response (GtkDialog* dialog, gint response_id)
+{
+  gtk_widget_destroy (GTK_WIDGET (dialog));
+}
+
+static void
+logview_filter_manager_class_init (LogviewFilterManagerClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GtkDialogClass *parent_class = GTK_DIALOG_CLASS (klass);
+
+  object_class->dispose = logview_filter_manager_dispose;
+  parent_class->response = logview_filter_manager_response;
+}
+
+GtkWidget *
+logview_filter_manager_new (void)
+{
+  return g_object_new (LOGVIEW_TYPE_FILTER_MANAGER, NULL);
+}
+
+ +
+ +
+ + diff --git a/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/19.html b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/19.html new file mode 100644 index 00000000..8c1c5057 --- /dev/null +++ b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/19.html @@ -0,0 +1,945 @@ + + + + + + Cppcheck - HTML report - mate-utils + + + + + +
+ + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2; -*- */
+/* Copyright (C) 2005 Vincent Noel <vnoel@cox.net>
+ * Copyright (C) 2008 Cosimo Cecchi <cosimoc@gnome.org>
+ * Copyright (C) 2012-2021 MATE Developers
+ *
+ * This file is part of MATE Utils.
+ *
+ * MATE Utils is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * MATE Utils is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MATE Utils.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <gtk/gtk.h>
+#include <glib/gi18n.h>
+#include <gdk/gdkkeysyms.h>
+
+#include "logview-findbar.h"
+
+struct _LogviewFindbarPrivate {
+  GtkWidget *entry;
+  GtkWidget *message;
+
+  GtkToolItem *clear_button;
+  GtkToolItem *back_button;
+  GtkToolItem *forward_button;
+  GtkToolItem *status_item;
+  GtkToolItem *separator;
+
+  char *string;
+
+  guint status_bold_id;
+};
+
+enum {
+  PREVIOUS,
+  NEXT,
+  CLOSE,
+  TEXT_CHANGED,
+  LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+G_DEFINE_TYPE_WITH_PRIVATE (LogviewFindbar, logview_findbar, GTK_TYPE_TOOLBAR);
+
+static void
+back_button_clicked_cb (GtkToolButton *button,
+                        gpointer user_data)
+{
+  LogviewFindbar *findbar = user_data;
+
+  g_signal_emit (findbar, signals[PREVIOUS], 0);
+}
+
+static void
+forward_button_clicked_cb (GtkToolButton *button,
+                           gpointer user_data)
+{
+  LogviewFindbar *findbar = user_data;
+
+  g_signal_emit (findbar, signals[NEXT], 0);
+}
+
+static void
+clear_button_clicked_cb (GtkToolButton *button,
+                         gpointer user_data)
+{
+  LogviewFindbar *findbar = user_data;
+
+  logview_findbar_set_message (findbar, NULL);
+  gtk_entry_set_text (GTK_ENTRY (findbar->priv->entry), "");
+}
+
+static void
+entry_activate_cb (GtkWidget *entry,
+                   gpointer user_data)
+{
+  LogviewFindbar *findbar = user_data;
+
+  g_signal_emit (findbar, signals[NEXT], 0);
+}
+
+static void
+entry_changed_cb (GtkEditable *editable,
+                  gpointer user_data)
+{
+  LogviewFindbar *findbar = user_data;
+  const char *text;
+
+  text = gtk_entry_get_text (GTK_ENTRY (editable));
+
+  if (g_strcmp0 (text, "") == 0) {
+    return;
+  }
+
+  if (g_strcmp0 (findbar->priv->string, text) != 0) {
+    g_free (findbar->priv->string);
+    findbar->priv->string = g_strdup (text);
+
+    g_signal_emit (findbar, signals[TEXT_CHANGED], 0);
+  }
+}
+
+static gboolean
+entry_key_press_event_cb (GtkWidget *entry,
+                          GdkEventKey *event,
+                          gpointer user_data)
+{
+  LogviewFindbar *findbar = user_data;
+
+  if (event->keyval == GDK_KEY_Escape) {
+    g_signal_emit (findbar, signals[CLOSE], 0);
+    return TRUE;
+  }
+
+  return FALSE;
+}
+
+static gboolean
+unbold_timeout_cb (gpointer user_data)
+{
+  LogviewFindbar *findbar = user_data;
+  PangoFontDescription *desc;
+
+  desc = pango_font_description_new ();
+  gtk_widget_override_font (findbar->priv->message, desc);
+  pango_font_description_free (desc);
+
+  findbar->priv->status_bold_id = 0;
+
+  return FALSE;
+}
+
+static void
+logview_findbar_init (LogviewFindbar *findbar)
+{
+  GtkWidget *label, *w, *box;
+  GtkToolbar *gtoolbar;
+  GtkToolItem *item;
+  LogviewFindbarPrivate *priv;
+
+  priv = findbar->priv = logview_findbar_get_instance_private (findbar);
+
+  gtoolbar = GTK_TOOLBAR (findbar);
+
+  gtk_toolbar_set_style (gtoolbar, GTK_TOOLBAR_BOTH_HORIZ);
+
+  priv->status_bold_id = 0;
+
+  /* Find: |_______| */
+  box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
+  gtk_widget_set_halign (box, GTK_ALIGN_START);
+  gtk_widget_set_margin_start (box, 2);
+  gtk_widget_set_margin_end (box, 2);
+
+  label = gtk_label_new_with_mnemonic (_("_Find:"));
+  gtk_box_pack_start (GTK_BOX (box), label, FALSE, FALSE, 0);
+
+  priv->entry = gtk_entry_new ();
+  gtk_entry_set_width_chars (GTK_ENTRY (priv->entry), 32);
+  gtk_label_set_mnemonic_widget (GTK_LABEL (label), priv->entry);
+  gtk_box_pack_start (GTK_BOX (box), priv->entry, TRUE, TRUE, 0);
+
+  item = gtk_tool_item_new ();
+  gtk_container_add (GTK_CONTAINER (item), box);
+  gtk_toolbar_insert (gtoolbar, item, -1);
+  gtk_widget_show_all (GTK_WIDGET (item));
+
+  /* "Previous" and "Next" buttons */
+  w = gtk_image_new_from_icon_name ("pan-start-symbolic", GTK_ICON_SIZE_BUTTON);
+  priv->back_button = gtk_tool_button_new (w, _("Find Previous"));
+  gtk_tool_item_set_is_important (priv->back_button, TRUE);
+  gtk_tool_item_set_tooltip_text (priv->back_button,
+                                 _("Find previous occurrence of the search string"));
+  gtk_toolbar_insert (gtoolbar, priv->back_button, -1);
+  gtk_widget_show_all (GTK_WIDGET (priv->back_button));
+
+  w = gtk_image_new_from_icon_name ("pan-end-symbolic", GTK_ICON_SIZE_BUTTON);
+  priv->forward_button = gtk_tool_button_new (w, _("Find Next"));
+  gtk_tool_item_set_is_important (priv->forward_button, TRUE);
+  gtk_tool_item_set_tooltip_text (priv->forward_button,
+                                 _("Find next occurrence of the search string"));
+  gtk_toolbar_insert (gtoolbar, priv->forward_button, -1);
+  gtk_widget_show_all (GTK_WIDGET (priv->forward_button));
+
+  /* clear button */
+  w = gtk_image_new_from_icon_name ("edit-clear-all", GTK_ICON_SIZE_BUTTON);
+  priv->clear_button = gtk_tool_button_new (w, NULL);
+  gtk_tool_item_set_tooltip_text (priv->clear_button,
+                                 _("Clear the search string"));
+  gtk_toolbar_insert (gtoolbar, priv->clear_button, -1);
+  gtk_widget_show_all (GTK_WIDGET (priv->clear_button));
+
+  /* separator */
+  priv->separator = gtk_separator_tool_item_new ();
+  gtk_toolbar_insert (gtoolbar, priv->separator, -1);
+
+  /* message */
+  priv->status_item = gtk_tool_item_new ();
+  gtk_tool_item_set_expand (priv->status_item, TRUE);
+  priv->message = gtk_label_new ("");
+  gtk_label_set_use_markup (GTK_LABEL (priv->message), TRUE);
+  gtk_label_set_xalign (GTK_LABEL (priv->message), 0.0);
+  gtk_label_set_yalign (GTK_LABEL (priv->message), 0.5);
+  gtk_container_add (GTK_CONTAINER (priv->status_item), priv->message);
+  gtk_widget_show (priv->message);
+  gtk_toolbar_insert (gtoolbar, priv->status_item, -1);
+
+  priv->string = NULL;
+
+  /* signal handlers */
+  g_signal_connect (priv->back_button, "clicked",
+                    G_CALLBACK (back_button_clicked_cb), findbar);
+  g_signal_connect (priv->forward_button, "clicked",
+                    G_CALLBACK (forward_button_clicked_cb), findbar);
+  g_signal_connect (priv->clear_button, "clicked",
+                    G_CALLBACK (clear_button_clicked_cb), findbar);
+  g_signal_connect (priv->entry, "activate",
+                    G_CALLBACK (entry_activate_cb), findbar);
+  g_signal_connect (priv->entry, "changed",
+                    G_CALLBACK (entry_changed_cb), findbar);
+  g_signal_connect (priv->entry, "key-press-event",
+                    G_CALLBACK (entry_key_press_event_cb), findbar);
+}
+
+static void
+do_grab_focus (GtkWidget *widget)
+{
+  LogviewFindbar *findbar = LOGVIEW_FINDBAR (widget);
+
+  gtk_widget_grab_focus (findbar->priv->entry);
+}
+
+static void
+do_finalize (GObject *obj)
+{
+  LogviewFindbar *findbar = LOGVIEW_FINDBAR (obj);
+
+  g_free (findbar->priv->string);
+
+  G_OBJECT_CLASS (logview_findbar_parent_class)->finalize (obj);
+}
+
+static void
+logview_findbar_class_init (LogviewFindbarClass *klass)
+{
+  GObjectClass *oclass = G_OBJECT_CLASS (klass);
+  GtkWidgetClass *wclass = GTK_WIDGET_CLASS (klass);
+
+  oclass->finalize = do_finalize;
+
+  wclass->grab_focus = do_grab_focus;
+
+  signals[PREVIOUS] = g_signal_new ("previous",
+                                    G_OBJECT_CLASS_TYPE (oclass),
+                                    G_SIGNAL_RUN_LAST,
+                                    G_STRUCT_OFFSET (LogviewFindbarClass, previous),
+                                    NULL, NULL,
+                                    g_cclosure_marshal_VOID__VOID,
+                                    G_TYPE_NONE, 0);
+
+  signals[NEXT] = g_signal_new ("next",
+                                G_OBJECT_CLASS_TYPE (oclass),
+                                G_SIGNAL_RUN_LAST,
+                                G_STRUCT_OFFSET (LogviewFindbarClass, next),
+                                NULL, NULL,
+                                g_cclosure_marshal_VOID__VOID,
+                                G_TYPE_NONE, 0);
+
+  signals[CLOSE] = g_signal_new ("close",
+                                 G_OBJECT_CLASS_TYPE (oclass),
+                                 G_SIGNAL_RUN_LAST,
+                                 G_STRUCT_OFFSET (LogviewFindbarClass, close),
+                                 NULL, NULL,
+                                 g_cclosure_marshal_VOID__VOID,
+                                 G_TYPE_NONE, 0);
+
+  signals[TEXT_CHANGED] = g_signal_new ("text-changed",
+                                        G_OBJECT_CLASS_TYPE (oclass),
+                                        G_SIGNAL_RUN_LAST,
+                                        G_STRUCT_OFFSET (LogviewFindbarClass, text_changed),
+                                        NULL, NULL,
+                                        g_cclosure_marshal_VOID__VOID,
+                                        G_TYPE_NONE, 0);
+}
+
+/* public methods */
+
+GtkWidget *
+logview_findbar_new (void)
+{
+  GtkWidget *widget;
+  widget = g_object_new (LOGVIEW_TYPE_FINDBAR, NULL);
+  return widget;
+}
+
+void
+logview_findbar_open (LogviewFindbar *findbar)
+{
+  g_assert (LOGVIEW_IS_FINDBAR (findbar));
+
+  gtk_widget_show (GTK_WIDGET (findbar));
+  gtk_widget_grab_focus (GTK_WIDGET (findbar));
+}
+
+const char *
+logview_findbar_get_text (LogviewFindbar *findbar)
+{
+  g_assert (LOGVIEW_IS_FINDBAR (findbar));
+
+  return findbar->priv->string;
+}
+
+void
+logview_findbar_set_message (LogviewFindbar *findbar,
+                             const char *text)
+{
+  PangoFontDescription *desc;
+
+  g_assert (LOGVIEW_IS_FINDBAR (findbar));
+
+  if (text) {
+    desc = pango_font_description_new ();
+    pango_font_description_set_weight (desc, PANGO_WEIGHT_BOLD);
+    gtk_widget_override_font (findbar->priv->message, desc);
+    pango_font_description_free (desc);
+
+    findbar->priv->status_bold_id = g_timeout_add (600, unbold_timeout_cb, findbar);
+  }
+
+  gtk_label_set_text (GTK_LABEL (findbar->priv->message),
+                      text != NULL ? text : "");
+  g_object_set (findbar->priv->separator, "visible", text != NULL, NULL);
+  g_object_set (findbar->priv->status_item, "visible", text != NULL, NULL);
+}
+
+ +
+ +
+ + diff --git a/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/2.html b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/2.html new file mode 100644 index 00000000..d2b9a1df --- /dev/null +++ b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/2.html @@ -0,0 +1,1721 @@ + + + + + + Cppcheck - HTML report - mate-utils + + + + + +
+ + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
+479
+480
+481
+482
+483
+484
+485
+486
+487
+488
+489
+490
+491
+492
+493
+494
+495
+496
+497
+498
+499
+500
+501
+502
+503
+504
+505
+506
+507
+508
+509
+510
+511
+512
+513
+514
+515
+516
+517
+518
+519
+520
+521
+522
+523
+524
+525
+526
+527
+528
+529
+530
+531
+532
+533
+534
+535
+536
+537
+538
+539
+540
+541
+542
+543
+544
+545
+546
+547
+548
+549
+550
+551
+552
+553
+554
+555
+556
+557
+558
+559
+560
+561
+562
+563
+564
+565
+566
+567
+568
+569
+570
+571
+572
+573
+574
+575
+576
+577
+578
+579
+580
+581
+582
+583
+584
+585
+586
+587
+588
+589
+590
+591
+592
+593
+594
+595
+596
+597
+598
+599
+600
+601
+602
+603
+604
+605
+606
+607
+608
+609
+610
+611
+612
+613
+614
+615
+616
+617
+618
+619
+620
+621
+622
+623
+624
+625
+626
+627
+628
+629
+630
+631
+632
+633
+634
+635
+636
+637
+638
+639
+640
+641
+642
+643
+644
+645
+646
+647
+648
+649
+650
+651
+652
+653
+654
+655
+656
+657
+658
+659
+660
+661
+662
+663
+664
+665
+666
+667
+668
+669
+670
+671
+672
+673
+674
+675
+676
+677
+678
+679
+680
+681
+682
+683
+684
+685
+686
+687
+688
+689
+690
+691
+692
+693
+694
+695
+696
+697
+698
+699
+700
+701
+702
+703
+704
+705
+706
+707
+708
+709
+710
+711
+712
+713
+714
+715
+716
+717
+718
+719
+720
+721
+722
+723
+724
+725
+726
+727
+728
+729
+730
+731
+732
+733
+734
+735
+736
+737
+738
+739
+740
+741
+742
/* Copyright (C) 2005 Fabio Marzocca
+ * Copyright (C) 2012-2021 MATE Developers
+ *
+ * Modified module from caja-connect-server-dialog.c.
+ * Released under same licence.
+ * Copyright (C) 2003 Red Hat, Inc.
+ *
+ * This file is part of MATE Utils.
+ *
+ * MATE Utils is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * MATE Utils is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MATE Utils.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "baobab-remote-connect-dialog.h"
+
+#include <string.h>
+#include <glib/gi18n.h>
+#include <gio/gio.h>
+#include <gtk/gtk.h>
+
+#include "baobab.h"
+
+/* Translators: all the strings in this file are meant to map the
+   similar strings inside caja-connect-server and should be
+   translated the same way
+*/
+
+struct _BaobabRemoteConnectDialogDetails {
+	GtkWidget *grid;
+	GtkWidget *type_combo;
+	GtkWidget *uri_entry;
+	GtkWidget *server_entry;
+	GtkWidget *share_entry;
+	GtkWidget *port_entry;
+	GtkWidget *folder_entry;
+	GtkWidget *domain_entry;
+	GtkWidget *user_entry;
+};
+
+G_DEFINE_TYPE(BaobabRemoteConnectDialog, baobab_remote_connect_dialog, GTK_TYPE_DIALOG)<--- There is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE is a macro then please configure it.
+
+#define RESPONSE_CONNECT GTK_RESPONSE_OK
+
+static void
+display_error_dialog (GError *error,
+		      GFile *location,
+		      GtkWindow *parent)
+{
+	GtkWidget *dlg;
+	char *parse_name;
+
+	parse_name = g_file_get_parse_name (location);
+	dlg = gtk_message_dialog_new (parent,
+	                              GTK_DIALOG_DESTROY_WITH_PARENT,
+	                              GTK_MESSAGE_ERROR,
+	                              GTK_BUTTONS_OK,
+	                              _("Cannot scan location \"%s\""), parse_name);
+	g_free (parse_name);
+
+	gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dlg),
+						  "%s", error->message);
+
+	gtk_dialog_run (GTK_DIALOG (dlg));
+	gtk_widget_destroy (dlg);
+}
+
+static void
+mount_enclosing_ready_cb (GFile *location,
+			  GAsyncResult *res,
+			  GtkWindow *app)
+{
+	gboolean success;
+	GError *error = NULL;
+
+	success = g_file_mount_enclosing_volume_finish (location,
+							res, &error);
+
+	if (success ||
+	    g_error_matches (error, G_IO_ERROR, G_IO_ERROR_ALREADY_MOUNTED)) {
+		baobab_scan_location (location);
+	}
+	else {
+		display_error_dialog (error, location, app);
+	}
+
+	if (error)
+		g_error_free (error);
+
+	if (location)
+		g_object_unref (location);
+}
+
+static void
+connect_server_dialog_present_uri (GtkWindow *app,
+				   GFile *location,
+				   GtkWidget *widget)
+{
+	GMountOperation *op;
+
+	op = gtk_mount_operation_new (GTK_WINDOW (widget));
+
+	g_file_mount_enclosing_volume (location,
+				       0, op,
+				       NULL,
+				       (GAsyncReadyCallback) mount_enclosing_ready_cb,
+				       app);
+	g_object_unref (op);
+}
+
+struct MethodInfo {
+	const char *scheme;
+	guint flags;
+};
+
+/* A collection of flags for MethodInfo.flags */
+enum {
+	DEFAULT_METHOD = 0x00000001,
+
+	/* Widgets to display in setup_for_type */
+	SHOW_SHARE     = 0x00000010,
+	SHOW_PORT      = 0x00000020,
+	SHOW_USER      = 0x00000040,
+	SHOW_DOMAIN    = 0x00000080,
+
+	IS_ANONYMOUS   = 0x00001000
+};
+
+/* Remember to fill in descriptions below */
+static struct MethodInfo methods[] = {
+	/* FIXME: we need to alias ssh to sftp */
+	{ "sftp",  SHOW_PORT | SHOW_USER },
+	{ "ftp",  SHOW_PORT | SHOW_USER },
+	{ "ftp",  DEFAULT_METHOD | IS_ANONYMOUS | SHOW_PORT},
+	{ "smb",  SHOW_SHARE | SHOW_USER | SHOW_DOMAIN },
+	{ "dav",  SHOW_PORT | SHOW_USER },
+	/* FIXME: hrm, shouldn't it work? */
+	{ "davs", SHOW_PORT | SHOW_USER },
+	{ NULL,   0 }, /* Custom URI method */
+};
+
+/* To get around non constant gettext strings */
+static const char*
+get_method_description (struct MethodInfo *meth)
+{
+	if (!meth->scheme) {
+		return _("Custom Location");
+	} else if (strcmp (meth->scheme, "sftp") == 0) {
+		return _("SSH");
+	} else if (strcmp (meth->scheme, "ftp") == 0) {
+		if (meth->flags & IS_ANONYMOUS) {
+			return _("Public FTP");
+		} else {
+			return _("FTP (with login)");
+		}
+	} else if (strcmp (meth->scheme, "smb") == 0) {
+		return _("Windows share");
+	} else if (strcmp (meth->scheme, "dav") == 0) {
+		return _("WebDAV (HTTP)");
+	} else if (strcmp (meth->scheme, "davs") == 0) {
+		return _("Secure WebDAV (HTTPS)");
+
+	/* No descriptive text */
+	} else {
+		return meth->scheme;
+	}
+}
+
+static void
+baobab_remote_connect_dialog_finalize (GObject *object)
+{
+	BaobabRemoteConnectDialog *dialog;
+
+	dialog = BAOBAB_REMOTE_CONNECT_DIALOG(object);
+
+	g_object_unref (dialog->details->uri_entry);
+	g_object_unref (dialog->details->server_entry);
+	g_object_unref (dialog->details->share_entry);
+	g_object_unref (dialog->details->port_entry);
+	g_object_unref (dialog->details->folder_entry);
+	g_object_unref (dialog->details->domain_entry);
+	g_object_unref (dialog->details->user_entry);
+
+	g_free (dialog->details);
+
+	G_OBJECT_CLASS (baobab_remote_connect_dialog_parent_class)->finalize (object);
+}
+
+static void
+connect_to_server (BaobabRemoteConnectDialog *dialog, GtkWindow *app)
+{
+	struct MethodInfo *meth;
+	char *uri;
+	GFile *location;
+	int index;
+	GtkTreeIter iter;
+
+	/* Get our method info */
+	gtk_combo_box_get_active_iter (GTK_COMBO_BOX (dialog->details->type_combo), &iter);
+	gtk_tree_model_get (gtk_combo_box_get_model (GTK_COMBO_BOX (dialog->details->type_combo)),
+			    &iter, 0, &index, -1);
+	g_assert (index < G_N_ELEMENTS (methods) && index >= 0);
+	meth = &(methods[index]);
+
+	if (meth->scheme == NULL) {
+		uri = gtk_editable_get_chars (GTK_EDITABLE (dialog->details->uri_entry), 0, -1);
+		/* FIXME: we should validate it in some way? */
+	} else {
+		char *user, *port, *initial_path, *server, *folder ,*domain ;
+		char *t, *join;
+		gboolean free_initial_path, free_user, free_domain, free_port;
+
+		server = gtk_editable_get_chars (GTK_EDITABLE (dialog->details->server_entry), 0, -1);
+		if (strlen (server) == 0) {
+			GtkWidget *dlg;
+
+			dlg = gtk_message_dialog_new (GTK_WINDOW (dialog),
+						      GTK_DIALOG_DESTROY_WITH_PARENT,
+						      GTK_MESSAGE_ERROR,
+						      GTK_BUTTONS_OK,
+						      _("Cannot Connect to Server. You must enter a name for the server."));
+
+			gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dlg),
+					_("Please enter a name and try again."));
+
+			gtk_dialog_run (GTK_DIALOG (dlg));
+    			gtk_widget_destroy (dlg);
+
+			g_free (server);
+			return;
+		}
+
+		user = "";
+		port = "";
+		initial_path = "";
+		domain = "";
+		free_initial_path = FALSE;
+		free_user = FALSE;
+		free_domain = FALSE;
+		free_port = FALSE;
+
+		/* FTP special case */
+		if (meth->flags & IS_ANONYMOUS) {
+			user = "anonymous";
+
+		/* SMB special case */
+		} else if (strcmp (meth->scheme, "smb") == 0) {
+			t = gtk_editable_get_chars (GTK_EDITABLE (dialog->details->share_entry), 0, -1);
+			initial_path = g_strconcat ("/", t, NULL);
+			free_initial_path = TRUE;
+			g_free (t);
+		}
+
+		if (gtk_widget_get_parent (dialog->details->port_entry) != NULL) {
+			free_port = TRUE;
+			port = gtk_editable_get_chars (GTK_EDITABLE (dialog->details->port_entry), 0, -1);
+		}
+		folder = gtk_editable_get_chars (GTK_EDITABLE (dialog->details->folder_entry), 0, -1);
+		if (gtk_widget_get_parent (dialog->details->user_entry) != NULL) {
+			free_user = TRUE;
+
+			t = gtk_editable_get_chars (GTK_EDITABLE (dialog->details->user_entry), 0, -1);
+
+			user = g_uri_escape_string (t, G_URI_RESERVED_CHARS_ALLOWED_IN_USERINFO, FALSE);
+
+			g_free (t);
+		}
+		if (gtk_widget_get_parent (dialog->details->domain_entry) != NULL) {
+			free_domain = TRUE;
+
+			domain = gtk_editable_get_chars (GTK_EDITABLE (dialog->details->domain_entry), 0, -1);
+
+			if (strlen (domain) != 0) {
+				t = user;
+
+				user = g_strconcat (domain , ";" , t, NULL);
+
+				if (free_user) {
+					g_free (t);
+				}
+
+				free_user = TRUE;
+			}
+		}
+
+		if (folder[0] != 0 &&
+		    folder[0] != '/') {
+			join = "/";
+		} else {
+			join = "";
+		}
+
+		t = folder;
+		folder = g_strconcat (initial_path, join, t, NULL);
+		g_free (t);
+
+		t = folder;
+		folder = g_uri_escape_string (t, G_URI_RESERVED_CHARS_ALLOWED_IN_PATH, FALSE);
+		g_free (t);
+
+		uri = g_strdup_printf ("%s://%s%s%s%s%s%s",
+				       meth->scheme,
+				       user, (user[0] != 0) ? "@" : "",
+				       server,
+				       (port[0] != 0) ? ":" : "", port,
+				       folder);
+
+		if (free_initial_path) {
+			g_free (initial_path);
+		}
+		g_free (server);
+		if (free_port) {
+			g_free (port);
+		}
+		g_free (folder);
+		if (free_user) {
+			g_free (user);
+		}
+		if (free_domain) {
+			g_free (domain);
+		}
+	}
+
+	gtk_widget_hide (GTK_WIDGET (dialog));
+
+	location = g_file_new_for_uri (uri);
+	g_free (uri);
+
+	connect_server_dialog_present_uri (app,
+					   location,
+					   GTK_WIDGET (dialog));
+}
+
+static void
+response_callback (BaobabRemoteConnectDialog *dialog,
+		   int response_id,
+		   GtkWindow *app)
+{
+	switch (response_id) {
+	case RESPONSE_CONNECT:
+		connect_to_server (dialog, app);
+		break;
+	case GTK_RESPONSE_NONE:
+	case GTK_RESPONSE_DELETE_EVENT:
+	case GTK_RESPONSE_CANCEL:
+		break;
+	default :
+		g_assert_not_reached ();
+	}
+}
+
+static void
+baobab_remote_connect_dialog_class_init (BaobabRemoteConnectDialogClass *class)
+{
+	GObjectClass *gobject_class;
+
+	gobject_class = G_OBJECT_CLASS (class);
+	gobject_class->finalize = baobab_remote_connect_dialog_finalize;
+}
+static void
+destroy_label (GtkWidget *widget,
+               gpointer   user_data)
+{
+  gtk_widget_destroy (widget);
+}
+
+static void
+setup_for_type (BaobabRemoteConnectDialog *dialog)
+{
+	struct MethodInfo *meth;
+	int index, i;
+	GtkWidget *label, *grid;
+	GtkTreeIter iter;
+
+	/* Get our method info */
+	gtk_combo_box_get_active_iter (GTK_COMBO_BOX (dialog->details->type_combo), &iter);
+	gtk_tree_model_get (gtk_combo_box_get_model (GTK_COMBO_BOX (dialog->details->type_combo)),
+			    &iter, 0, &index, -1);
+	g_assert (index < G_N_ELEMENTS (methods) && index >= 0);
+	meth = &(methods[index]);
+
+	if (gtk_widget_get_parent (dialog->details->uri_entry) != NULL) {
+		gtk_container_remove (GTK_CONTAINER (dialog->details->grid),
+				      dialog->details->uri_entry);
+	}
+	if (gtk_widget_get_parent (dialog->details->server_entry) != NULL) {
+		gtk_container_remove (GTK_CONTAINER (dialog->details->grid),
+				      dialog->details->server_entry);
+	}
+	if (gtk_widget_get_parent (dialog->details->share_entry) != NULL) {
+		gtk_container_remove (GTK_CONTAINER (dialog->details->grid),
+				      dialog->details->share_entry);
+	}
+	if (gtk_widget_get_parent (dialog->details->port_entry) != NULL) {
+		gtk_container_remove (GTK_CONTAINER (dialog->details->grid),
+				      dialog->details->port_entry);
+	}
+	if (gtk_widget_get_parent (dialog->details->folder_entry) != NULL) {
+		gtk_container_remove (GTK_CONTAINER (dialog->details->grid),
+				      dialog->details->folder_entry);
+	}
+	if (gtk_widget_get_parent (dialog->details->user_entry) != NULL) {
+		gtk_container_remove (GTK_CONTAINER (dialog->details->grid),
+				      dialog->details->user_entry);
+	}
+	if (gtk_widget_get_parent (dialog->details->domain_entry) != NULL) {
+		gtk_container_remove (GTK_CONTAINER (dialog->details->grid),
+				      dialog->details->domain_entry);
+	}
+	/* Destroy all labels */
+	gtk_container_foreach (GTK_CONTAINER (dialog->details->grid),
+			       destroy_label, NULL);
+
+	i = 1;
+	grid = dialog->details->grid;
+
+	if (meth->scheme == NULL) {
+		label = gtk_label_new_with_mnemonic (_("_Location (URI):"));
+		gtk_label_set_xalign (GTK_LABEL (label), 0.0);
+		gtk_label_set_yalign (GTK_LABEL (label), 0.5);
+		gtk_widget_show (label);
+		gtk_grid_attach (GTK_GRID (grid), label, 0, i, 1, 1);
+
+		gtk_label_set_mnemonic_widget (GTK_LABEL (label), dialog->details->uri_entry);
+		gtk_widget_set_hexpand (dialog->details->uri_entry, TRUE);
+		gtk_widget_show (dialog->details->uri_entry);
+		gtk_grid_attach (GTK_GRID (grid), dialog->details->uri_entry, 1, i, 1, 1);
+
+		i++;
+
+		return;
+	}
+
+	label = gtk_label_new_with_mnemonic (_("_Server:"));
+	gtk_label_set_xalign (GTK_LABEL (label), 0.0);
+	gtk_label_set_yalign (GTK_LABEL (label), 0.5);
+	gtk_widget_show (label);
+	gtk_grid_attach (GTK_GRID (grid), label, 0, i, 1, 1);
+
+	gtk_label_set_mnemonic_widget (GTK_LABEL (label), dialog->details->server_entry);
+	gtk_widget_set_hexpand (dialog->details->server_entry, TRUE);
+	gtk_widget_show (dialog->details->server_entry);
+	gtk_grid_attach (GTK_GRID (grid), dialog->details->server_entry, 1, i, 1, 1);
+
+	i++;
+
+	label = gtk_label_new (_("Optional information:"));
+	gtk_label_set_xalign (GTK_LABEL (label), 0.0);
+	gtk_label_set_yalign (GTK_LABEL (label), 0.5);
+	gtk_widget_show (label);
+	gtk_grid_attach (GTK_GRID (grid), label, 0, i, 2, 1);
+
+	i++;
+
+	if (meth->flags & SHOW_SHARE) {
+		label = gtk_label_new_with_mnemonic (_("_Share:"));
+		gtk_label_set_xalign (GTK_LABEL (label), 0.0);
+		gtk_label_set_yalign (GTK_LABEL (label), 0.5);
+		gtk_widget_show (label);
+		gtk_grid_attach (GTK_GRID (grid), label, 0, i, 1, 1);
+
+		gtk_label_set_mnemonic_widget (GTK_LABEL (label), dialog->details->share_entry);
+		gtk_widget_set_hexpand (dialog->details->share_entry, TRUE);
+		gtk_widget_show (dialog->details->share_entry);
+		gtk_grid_attach (GTK_GRID (grid), dialog->details->share_entry, 1, i, 1, 1);
+
+		i++;
+	}
+
+	if (meth->flags & SHOW_PORT) {
+		label = gtk_label_new_with_mnemonic (_("_Port:"));
+		gtk_label_set_xalign (GTK_LABEL (label), 0.0);
+		gtk_label_set_yalign (GTK_LABEL (label), 0.5);
+		gtk_widget_show (label);
+		gtk_grid_attach (GTK_GRID (grid), label, 0, i, 1, 1);
+
+		gtk_label_set_mnemonic_widget (GTK_LABEL (label), dialog->details->port_entry);
+		gtk_widget_set_hexpand (dialog->details->port_entry, TRUE);
+		gtk_widget_show (dialog->details->port_entry);
+		gtk_grid_attach (GTK_GRID (grid), dialog->details->port_entry, 1, i, 1, 1);
+
+		i++;
+	}
+
+	label = gtk_label_new_with_mnemonic (_("_Folder:"));
+	gtk_label_set_xalign (GTK_LABEL (label), 0.0);
+	gtk_label_set_yalign (GTK_LABEL (label), 0.5);
+	gtk_widget_show (label);
+	gtk_grid_attach (GTK_GRID (grid), label, 0, i, 1, 1);
+
+	gtk_label_set_mnemonic_widget (GTK_LABEL (label), dialog->details->folder_entry);
+	gtk_widget_set_hexpand (dialog->details->folder_entry, TRUE);
+	gtk_widget_show (dialog->details->folder_entry);
+	gtk_grid_attach (GTK_GRID (grid), dialog->details->folder_entry, 1, i, 1, 1);
+
+	i++;
+
+	if (meth->flags & SHOW_USER) {
+		label = gtk_label_new_with_mnemonic (_("_User Name:"));
+		gtk_label_set_xalign (GTK_LABEL (label), 0.0);
+		gtk_label_set_yalign (GTK_LABEL (label), 0.5);
+		gtk_widget_show (label);
+		gtk_grid_attach (GTK_GRID (grid), label, 0, i, 1, 1);
+
+		gtk_label_set_mnemonic_widget (GTK_LABEL (label), dialog->details->user_entry);
+		gtk_widget_set_hexpand (dialog->details->user_entry, TRUE);
+		gtk_widget_show (dialog->details->user_entry);
+		gtk_grid_attach (GTK_GRID (grid), dialog->details->user_entry, 1, i, 1, 1);
+
+		i++;
+	}
+
+	if (meth->flags & SHOW_DOMAIN) {
+		label = gtk_label_new_with_mnemonic (_("_Domain Name:"));
+		gtk_label_set_xalign (GTK_LABEL (label), 0.0);
+		gtk_label_set_yalign (GTK_LABEL (label), 0.5);
+		gtk_widget_show (label);
+		gtk_grid_attach (GTK_GRID (grid), label, 0, i, 1, 1);
+
+		gtk_label_set_mnemonic_widget (GTK_LABEL (label), dialog->details->domain_entry);
+		gtk_widget_set_hexpand (dialog->details->user_entry, TRUE);
+		gtk_widget_show (dialog->details->domain_entry);
+		gtk_grid_attach (GTK_GRID (grid), dialog->details->domain_entry, 1, i, 1, 1);
+
+                i++;
+        }
+}
+
+static void
+combo_changed_callback (GtkComboBox *combo_box,
+			BaobabRemoteConnectDialog *dialog)
+{
+	setup_for_type (dialog);
+}
+
+static void
+port_insert_text (GtkEditable *editable,
+		  const gchar *new_text,
+		  gint         new_text_length,
+		  gint        *position)
+{
+	int pos;
+
+	/* Only allow digits to be inserted as port number */
+	for (pos = 0; pos < new_text_length; pos++) {
+		if (!g_ascii_isdigit (new_text[pos])) {
+			GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (editable));
+			if (toplevel != NULL) {
+				gdk_window_beep (gtk_widget_get_window (toplevel));
+			}
+		    g_signal_stop_emission_by_name (editable, "insert_text");
+		    return;
+		}
+	}
+}
+
+static void
+baobab_remote_connect_dialog_init (BaobabRemoteConnectDialog *dialog)
+{
+	GtkWidget *label;
+	GtkWidget *grid;
+	GtkWidget *combo;
+	GtkWidget *hbox;
+	GtkWidget *vbox;
+	GtkListStore *store;
+	GtkCellRenderer *renderer;
+	int i;
+
+	dialog->details = g_new0 (BaobabRemoteConnectDialogDetails, 1);
+
+	gtk_window_set_title (GTK_WINDOW (dialog), _("Connect to Server"));
+	gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
+	gtk_box_set_spacing (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), 2);
+	gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
+
+	vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
+	gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
+	gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))),
+			    vbox, FALSE, TRUE, 0);
+	gtk_widget_show (vbox);
+
+	hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+	gtk_box_pack_start (GTK_BOX (vbox),
+			    hbox, FALSE, TRUE, 0);
+	gtk_widget_show (hbox);
+
+	label = gtk_label_new_with_mnemonic (_("Service _type:"));
+	gtk_label_set_xalign (GTK_LABEL (label), 0.0);
+	gtk_label_set_yalign (GTK_LABEL (label), 0.5);
+	gtk_widget_show (label);
+	gtk_box_pack_start (GTK_BOX (hbox),
+			    label, FALSE, FALSE, 0);
+
+	dialog->details->type_combo = combo = gtk_combo_box_new ();
+
+	/* each row contains: method index, textual description */
+	store = gtk_list_store_new (2, G_TYPE_INT, G_TYPE_STRING);
+	gtk_combo_box_set_model (GTK_COMBO_BOX (combo), GTK_TREE_MODEL (store));
+	g_object_unref (G_OBJECT (store));
+
+	renderer = gtk_cell_renderer_text_new ();
+	gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), renderer, TRUE);
+	gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (combo), renderer, "text", 1);
+
+	for (i = 0; i < G_N_ELEMENTS (methods); i++) {
+		GtkTreeIter iter;
+		const gchar * const *supported;
+		int j;
+
+		/* skip methods that don't have corresponding MateVFSMethods */
+		supported = g_vfs_get_supported_uri_schemes (g_vfs_get_default ());
+
+		if (methods[i].scheme != NULL) {
+			gboolean found;
+
+			found = FALSE;
+			for (j = 0; supported[j] != NULL; j++) {
+				if (strcmp (methods[i].scheme, supported[j]) == 0) {
+					found = TRUE;
+					break;
+				}
+			}
+
+			if (!found) {
+				continue;
+			}
+		}
+
+		gtk_list_store_append (store, &iter);
+		gtk_list_store_set (store, &iter,
+				    0, i,
+				    1, get_method_description (&(methods[i])),
+				    -1);
+
+		if (methods[i].flags & DEFAULT_METHOD) {
+			gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combo), &iter);
+		}
+	}
+
+	if (gtk_combo_box_get_active (GTK_COMBO_BOX (combo)) < 0) {
+		/* default method not available, use any other */
+		gtk_combo_box_set_active (GTK_COMBO_BOX (combo), 0);
+	}
+
+	gtk_widget_show (combo);
+	gtk_label_set_mnemonic_widget (GTK_LABEL (label), combo);
+	gtk_box_pack_start (GTK_BOX (hbox),
+			    combo, TRUE, TRUE, 0);
+	g_signal_connect (combo, "changed",
+			  G_CALLBACK (combo_changed_callback),
+			  dialog);
+
+	hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+	gtk_box_pack_start (GTK_BOX (vbox),
+			    hbox, FALSE, TRUE, 0);
+	gtk_widget_show (hbox);
+
+	label = gtk_label_new_with_mnemonic ("    ");
+	gtk_widget_show (label);
+	gtk_box_pack_start (GTK_BOX (hbox),
+			    label, FALSE, FALSE, 0);
+
+	dialog->details->grid = grid = gtk_grid_new ();
+	gtk_grid_set_row_spacing (GTK_GRID (grid), 6);
+	gtk_grid_set_column_spacing (GTK_GRID (grid), 12);
+	gtk_widget_show (grid);
+	gtk_box_pack_start (GTK_BOX (hbox),
+			    grid, TRUE, TRUE, 0);
+
+	dialog->details->uri_entry = gtk_entry_new();
+	dialog->details->server_entry = gtk_entry_new ();
+	dialog->details->share_entry = gtk_entry_new ();
+	dialog->details->port_entry = gtk_entry_new ();
+	g_signal_connect (dialog->details->port_entry, "insert_text", G_CALLBACK (port_insert_text),
+			  NULL);
+	dialog->details->folder_entry = gtk_entry_new ();
+	dialog->details->domain_entry = gtk_entry_new ();
+	dialog->details->user_entry = gtk_entry_new ();
+
+	gtk_entry_set_activates_default (GTK_ENTRY (dialog->details->uri_entry), TRUE);
+	gtk_entry_set_activates_default (GTK_ENTRY (dialog->details->server_entry), TRUE);
+	gtk_entry_set_activates_default (GTK_ENTRY (dialog->details->share_entry), TRUE);
+	gtk_entry_set_activates_default (GTK_ENTRY (dialog->details->port_entry), TRUE);
+	gtk_entry_set_activates_default (GTK_ENTRY (dialog->details->folder_entry), TRUE);
+	gtk_entry_set_activates_default (GTK_ENTRY (dialog->details->domain_entry), TRUE);
+	gtk_entry_set_activates_default (GTK_ENTRY (dialog->details->user_entry), TRUE);
+
+	/* We need an extra ref so we can remove them from the table */
+	g_object_ref (dialog->details->uri_entry);
+	g_object_ref (dialog->details->server_entry);
+	g_object_ref (dialog->details->share_entry);
+	g_object_ref (dialog->details->port_entry);
+	g_object_ref (dialog->details->folder_entry);
+	g_object_ref (dialog->details->domain_entry);
+	g_object_ref (dialog->details->user_entry);
+
+	setup_for_type (dialog);
+
+	gtk_dialog_add_button (GTK_DIALOG (dialog),
+			       "gtk-cancel",
+			       GTK_RESPONSE_CANCEL);
+	gtk_dialog_add_button (GTK_DIALOG (dialog),
+			       _("_Scan"),
+			       RESPONSE_CONNECT);
+	gtk_dialog_set_default_response (GTK_DIALOG (dialog),
+					 RESPONSE_CONNECT);
+}
+
+GtkWidget *
+baobab_remote_connect_dialog_new (GtkWindow *window, GFile *location)
+{
+	GtkWidget *dialog;
+
+	dialog = gtk_widget_new (BAOBAB_TYPE_REMOTE_CONNECT_DIALOG, NULL);
+
+	gtk_window_set_transient_for (GTK_WINDOW (dialog), window);
+
+	g_signal_connect (dialog, "response",
+			  G_CALLBACK (response_callback),
+			  window);
+
+	if (window) {
+		gtk_window_set_screen (GTK_WINDOW (dialog),
+				       gtk_window_get_screen (GTK_WINDOW (window)));
+	}
+
+	return dialog;
+}
+
+
+ +
+ +
+ + diff --git a/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/20.html b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/20.html new file mode 100644 index 00000000..0c6f8f06 --- /dev/null +++ b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/20.html @@ -0,0 +1,2139 @@ + + + + + + Cppcheck - HTML report - mate-utils + + + + + +
+ + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
+479
+480
+481
+482
+483
+484
+485
+486
+487
+488
+489
+490
+491
+492
+493
+494
+495
+496
+497
+498
+499
+500
+501
+502
+503
+504
+505
+506
+507
+508
+509
+510
+511
+512
+513
+514
+515
+516
+517
+518
+519
+520
+521
+522
+523
+524
+525
+526
+527
+528
+529
+530
+531
+532
+533
+534
+535
+536
+537
+538
+539
+540
+541
+542
+543
+544
+545
+546
+547
+548
+549
+550
+551
+552
+553
+554
+555
+556
+557
+558
+559
+560
+561
+562
+563
+564
+565
+566
+567
+568
+569
+570
+571
+572
+573
+574
+575
+576
+577
+578
+579
+580
+581
+582
+583
+584
+585
+586
+587
+588
+589
+590
+591
+592
+593
+594
+595
+596
+597
+598
+599
+600
+601
+602
+603
+604
+605
+606
+607
+608
+609
+610
+611
+612
+613
+614
+615
+616
+617
+618
+619
+620
+621
+622
+623
+624
+625
+626
+627
+628
+629
+630
+631
+632
+633
+634
+635
+636
+637
+638
+639
+640
+641
+642
+643
+644
+645
+646
+647
+648
+649
+650
+651
+652
+653
+654
+655
+656
+657
+658
+659
+660
+661
+662
+663
+664
+665
+666
+667
+668
+669
+670
+671
+672
+673
+674
+675
+676
+677
+678
+679
+680
+681
+682
+683
+684
+685
+686
+687
+688
+689
+690
+691
+692
+693
+694
+695
+696
+697
+698
+699
+700
+701
+702
+703
+704
+705
+706
+707
+708
+709
+710
+711
+712
+713
+714
+715
+716
+717
+718
+719
+720
+721
+722
+723
+724
+725
+726
+727
+728
+729
+730
+731
+732
+733
+734
+735
+736
+737
+738
+739
+740
+741
+742
+743
+744
+745
+746
+747
+748
+749
+750
+751
+752
+753
+754
+755
+756
+757
+758
+759
+760
+761
+762
+763
+764
+765
+766
+767
+768
+769
+770
+771
+772
+773
+774
+775
+776
+777
+778
+779
+780
+781
+782
+783
+784
+785
+786
+787
+788
+789
+790
+791
+792
+793
+794
+795
+796
+797
+798
+799
+800
+801
+802
+803
+804
+805
+806
+807
+808
+809
+810
+811
+812
+813
+814
+815
+816
+817
+818
+819
+820
+821
+822
+823
+824
+825
+826
+827
+828
+829
+830
+831
+832
+833
+834
+835
+836
+837
+838
+839
+840
+841
+842
+843
+844
+845
+846
+847
+848
+849
+850
+851
+852
+853
+854
+855
+856
+857
+858
+859
+860
+861
+862
+863
+864
+865
+866
+867
+868
+869
+870
+871
+872
+873
+874
+875
+876
+877
+878
+879
+880
+881
+882
+883
+884
+885
+886
+887
+888
+889
+890
+891
+892
+893
+894
+895
+896
+897
+898
+899
+900
+901
+902
+903
+904
+905
+906
+907
+908
+909
+910
+911
+912
+913
+914
+915
+916
+917
+918
+919
+920
+921
+922
+923
+924
+925
+926
+927
/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2; -*- */
+/* Copyright (C) 1998 Cesar Miquel <miquel@df.uba.ar>
+ * Copyright (C) 2008 Cosimo Cecchi <cosimoc@gnome.org>
+ * Copyright (C) 2012-2021 MATE Developers
+ *
+ * This file is part of MATE Utils.
+ *
+ * MATE Utils is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * MATE Utils is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MATE Utils.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gio/gio.h>
+
+#ifdef HAVE_ZLIB
+#include <zlib.h>
+#endif
+
+#include "logview-log.h"
+#include "logview-utils.h"
+
+enum {
+  LOG_CHANGED,
+  LAST_SIGNAL
+};
+
+static guint signals [LAST_SIGNAL] = { 0 };
+
+struct _LogviewLogPrivate {
+  /* file and monitor */
+  GFile *file;
+  GFileMonitor *mon;
+
+  /* stats about the file */
+  time_t file_time;
+  goffset file_size;
+  char *display_name;
+  gboolean has_days;
+
+  /* lines and relative days */
+  GSList *days;
+  GPtrArray *lines;
+  guint lines_no;
+
+  /* stream poiting to the log */
+  GDataInputStream *stream;
+  gboolean has_new_lines;
+};
+
+typedef struct {
+  LogviewLog *log;
+  LogviewCreateCallback callback;
+  gpointer user_data;
+} LoadJob;
+
+typedef struct {
+  LogviewLog *log;
+  const char **lines;
+  GSList *new_days;
+  LogviewNewLinesCallback callback;
+  gpointer user_data;
+} NewLinesJob;
+
+typedef struct {
+  GInputStream *parent_str;<--- struct member 'GZHandle::parent_str' is never used.
+  guchar * buffer;<--- struct member 'GZHandle::buffer' is never used.
+  GFile *file;<--- struct member 'GZHandle::file' is never used.
+
+  gboolean last_str_result;
+  int last_z_result;<--- struct member 'GZHandle::last_z_result' is never used.
+  z_stream zstream;
+} GZHandle;
+
+G_DEFINE_TYPE_WITH_PRIVATE (LogviewLog, logview_log, G_TYPE_OBJECT);
+
+static void
+do_finalize (GObject *obj)
+{
+  LogviewLog *log = LOGVIEW_LOG (obj);
+  char ** lines;
+
+  if (log->priv->stream) {
+    g_object_unref (log->priv->stream);
+    log->priv->stream = NULL;
+  }
+
+  if (log->priv->file) {
+    g_object_unref (log->priv->file);
+    log->priv->file = NULL;
+  }
+
+  if (log->priv->mon) {
+    g_object_unref (log->priv->mon);
+    log->priv->mon = NULL;
+  }
+
+  if (log->priv->days) {
+    g_slist_free_full (log->priv->days,
+                       (GDestroyNotify) logview_utils_day_free);
+    log->priv->days = NULL;
+  }
+
+  if (log->priv->lines) {
+    lines = (char **) g_ptr_array_free (log->priv->lines, FALSE);
+    g_strfreev (lines);
+    log->priv->lines = NULL;
+  }
+
+  G_OBJECT_CLASS (logview_log_parent_class)->finalize (obj);
+}
+
+static void
+logview_log_class_init (LogviewLogClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->finalize = do_finalize;
+
+  signals[LOG_CHANGED] = g_signal_new ("log-changed",
+                                       G_OBJECT_CLASS_TYPE (object_class),
+                                       G_SIGNAL_RUN_LAST,
+                                       G_STRUCT_OFFSET (LogviewLogClass, log_changed),
+                                       NULL, NULL,
+                                       g_cclosure_marshal_VOID__VOID,
+                                       G_TYPE_NONE, 0);
+}
+
+static void
+logview_log_init (LogviewLog *self)
+{
+  self->priv = logview_log_get_instance_private (self);
+
+  self->priv->lines = NULL;
+  self->priv->lines_no = 0;
+  self->priv->days = NULL;
+  self->priv->file = NULL;
+  self->priv->mon = NULL;
+  self->priv->has_new_lines = FALSE;
+  self->priv->has_days = FALSE;
+}
+
+static void
+monitor_changed_cb (GFileMonitor *monitor,
+                    GFile *file,
+                    GFile *unused,
+                    GFileMonitorEvent event,
+                    gpointer user_data)
+{
+  LogviewLog *log = user_data;
+
+  if (event == G_FILE_MONITOR_EVENT_CHANGED) {
+    log->priv->has_new_lines = TRUE;
+    g_signal_emit (log, signals[LOG_CHANGED], 0, NULL);
+  }
+  /* TODO: handle the case where the log is deleted? */
+}
+
+static void
+setup_file_monitor (LogviewLog *log)
+{
+  GError *err = NULL;
+
+  log->priv->mon = g_file_monitor (log->priv->file,
+                                   0, NULL, &err);
+  if (err) {
+    /* it'd be strange to get this error at this point but whatever */
+    g_warning ("Impossible to monitor the log file: the changes won't be notified");
+    g_error_free (err);
+    return;
+  }
+
+  /* set the rate to 1sec, as I guess it's not unusual to have more than
+   * one line written consequently or in a short time, being a log file.
+   */
+  g_file_monitor_set_rate_limit (log->priv->mon, 1000);
+  g_signal_connect (log->priv->mon, "changed",
+                    G_CALLBACK (monitor_changed_cb), log);
+}
+
+static GSList *
+add_new_days_to_cache (LogviewLog *log, const char **new_lines, guint lines_offset)
+{
+  GSList *new_days, *l, *last_cached;
+  int res;
+  Day *day, *last;
+
+  new_days = log_read_dates (new_lines, log->priv->file_time);
+
+  /* the days are stored in chronological order, so we compare the last cached
+   * one with the new we got.
+   */
+  last_cached = g_slist_last (log->priv->days);
+
+  if (!last_cached) {
+    /* this means the day list is empty (i.e. we're on the first read */
+    log->priv->days = logview_utils_day_list_copy (new_days);
+    return new_days;
+  }
+
+  for (l = new_days; l; l = l->next) {
+    res = days_compare (l->data, last_cached->data);
+    day = l->data;
+
+    if (res > 0) {
+      /* this day in the list is newer than the last one, append to
+       * the cache.
+       */
+      day->first_line += lines_offset;
+      day->last_line += lines_offset;
+      log->priv->days = g_slist_append (log->priv->days, logview_utils_day_copy (day));
+    } else if (res == 0) {
+      last = last_cached->data;
+
+      /* update the lines number */
+      last->last_line += day->last_line;
+    }
+  }
+
+  return new_days;
+}
+
+static void
+new_lines_job_done (GObject      *source_object,
+                    GAsyncResult *res,
+                    gpointer      user_data)
+{
+  NewLinesJob      *job = user_data;
+  g_autoptr(GError) error = NULL;
+  gboolean          ret;
+
+  ret = g_task_propagate_boolean (G_TASK (res), &error);
+  if (!ret) {
+    job->callback (job->log, NULL, NULL, error, job->user_data);
+  } else {
+    job->callback (job->log, job->lines, job->new_days, error, job->user_data);
+  }
+
+  g_slist_free_full (job->new_days, (GDestroyNotify) logview_utils_day_free);
+
+  /* drop the reference we acquired before */
+  g_object_unref (job->log);
+
+  g_slice_free (NewLinesJob, job);
+}
+
+static void
+do_read_new_lines (GTask        *task,
+                   gpointer      source_object,
+                   gpointer      user_data,
+                   GCancellable *cancellable)
+{
+  /* this runs in a separate thread */
+  NewLinesJob *job = user_data;
+  LogviewLog *log = job->log;
+  char *line;
+  GError *err = NULL;
+  GPtrArray *lines;
+
+  g_assert (LOGVIEW_IS_LOG (log));
+  g_assert (log->priv->stream != NULL);
+
+  if (!log->priv->lines) {
+    log->priv->lines = g_ptr_array_new ();
+    g_ptr_array_add (log->priv->lines, NULL);
+  }
+
+  lines = log->priv->lines;
+
+  /* remove the NULL-terminator */
+  g_ptr_array_remove_index (lines, lines->len - 1);
+
+  while ((line = g_data_input_stream_read_line (log->priv->stream, NULL,
+                                                cancellable, &err)) != NULL)
+  {
+    g_ptr_array_add (lines, (gpointer) line);
+  }
+
+  /* NULL-terminate the array again */
+  g_ptr_array_add (lines, NULL);
+
+  if (err) {
+    g_task_return_error (task, err);
+  }
+
+  log->priv->has_new_lines = FALSE;
+
+  /* we'll return only the new lines in the callback */
+  job->lines = (const char **) lines->pdata + log->priv->lines_no;
+
+  /* save the new number of days and lines */
+  job->new_days = add_new_days_to_cache (log, job->lines, log->priv->lines_no);
+  log->priv->lines_no = (lines->len - 1);
+
+  g_task_return_boolean (task, TRUE);
+}
+
+static void
+log_load_done (GObject      *source_object,
+               GAsyncResult *res,
+               gpointer      user_data)
+{
+  LoadJob *job = user_data;
+  g_autoptr(GError) error = NULL;
+  gboolean          ret;
+
+  ret = g_task_propagate_boolean (G_TASK (res), &error);
+
+  if (!ret) {
+    g_object_unref (job->log);
+    job->callback (NULL, error, job->user_data);
+  } else {
+    job->callback (job->log, NULL, job->user_data);
+    setup_file_monitor (job->log);
+  }
+
+  g_slice_free (LoadJob, job);
+
+}
+
+#ifdef HAVE_ZLIB
+
+/* GZip functions adapted for GIO from mate-vfs/gzip-method.c */
+
+#define Z_BUFSIZE 16384
+
+#define GZIP_HEADER_SIZE 10
+#define GZIP_MAGIC_1 0x1f
+#define GZIP_MAGIC_2 0x8b
+#define GZIP_FLAG_ASCII        0x01 /* bit 0 set: file probably ascii text */
+#define GZIP_FLAG_HEAD_CRC     0x02 /* bit 1 set: header CRC present */
+#define GZIP_FLAG_EXTRA_FIELD  0x04 /* bit 2 set: extra field present */
+#define GZIP_FLAG_ORIG_NAME    0x08 /* bit 3 set: original file name present */
+#define GZIP_FLAG_COMMENT      0x10 /* bit 4 set: file comment present */
+#define GZIP_FLAG_RESERVED     0xE0 /* bits 5..7: reserved */
+
+static gboolean
+skip_string (GInputStream *is)
+{
+	guchar c;
+	gssize bytes_read;
+
+	do {
+		bytes_read = g_input_stream_read (is, &c, 1, NULL, NULL);
+
+		if (bytes_read != 1) {
+			return FALSE;
+    }
+	} while (c != 0);
+
+	return TRUE;
+}
+
+static gboolean
+read_gzip_header (GInputStream *is,
+                  time_t *modification_time)
+{
+	guchar buffer[GZIP_HEADER_SIZE];
+	gssize bytes, to_skip;
+	guint mode;
+	guint flags;
+
+	bytes = g_input_stream_read (is, buffer, GZIP_HEADER_SIZE,
+                               NULL, NULL);
+  if (bytes == -1) {
+    return FALSE;
+  }
+
+	if (bytes != GZIP_HEADER_SIZE)
+		return FALSE;
+
+	if (buffer[0] != GZIP_MAGIC_1 || buffer[1] != GZIP_MAGIC_2)
+		return FALSE;
+
+	mode = buffer[2];
+	if (mode != 8) /* Mode: deflate */
+		return FALSE;
+
+	flags = buffer[3];
+
+	if (flags & GZIP_FLAG_RESERVED)
+		return FALSE;
+
+	if (flags & GZIP_FLAG_EXTRA_FIELD) {
+		guchar tmp[2];
+
+    bytes = g_input_stream_read (is, tmp, 2, NULL, NULL);
+
+    if (bytes != 2) {
+			return FALSE;
+    }
+
+    to_skip = tmp[0] | (tmp[0] << 8);
+    bytes = g_input_stream_skip (is, to_skip, NULL, NULL);
+    if (bytes != to_skip) {
+      return FALSE;
+    }
+	}
+
+	if (flags & GZIP_FLAG_ORIG_NAME) {
+    if (!skip_string (is)) {
+      return FALSE;
+    }
+  }
+
+	if (flags & GZIP_FLAG_COMMENT) {
+    if (!skip_string (is)) {
+      return FALSE;
+    }
+  }
+
+	if (flags & GZIP_FLAG_HEAD_CRC) {
+    bytes = g_input_stream_skip (is, 2, NULL, NULL);
+		if (bytes != 2) {
+      return FALSE;
+    }
+  }
+
+  *modification_time = (buffer[4] | (buffer[5] << 8)
+                        | (buffer[6] << 16) | (buffer[7] << 24));
+
+	return TRUE;
+}
+
+static GZHandle *
+gz_handle_new (GFile *file,
+               GInputStream *parent_stream)
+{
+  GZHandle *ret;
+
+  ret = g_new (GZHandle, 1);
+  ret->parent_str = g_object_ref (parent_stream);
+  ret->file = g_object_ref (file);
+  ret->buffer = NULL;
+
+  return ret;
+}
+
+static gboolean
+gz_handle_init (GZHandle *gz)
+{
+  gz->zstream.zalloc = NULL;
+  gz->zstream.zfree = NULL;
+  gz->zstream.opaque = NULL;
+
+  g_free (gz->buffer);
+  gz->buffer = g_malloc (Z_BUFSIZE);
+  gz->zstream.next_in = gz->buffer;
+  gz->zstream.avail_in = 0;
+
+  if (inflateInit2 (&gz->zstream, -MAX_WBITS) != Z_OK) {
+    return FALSE;
+  }
+
+  gz->last_z_result = Z_OK;
+  gz->last_str_result = TRUE;
+
+  return TRUE;
+}
+
+static void
+gz_handle_free (GZHandle *gz)
+{
+  g_object_unref (gz->parent_str);
+  g_object_unref (gz->file);
+  g_free (gz->buffer);
+  g_free (gz);
+}
+
+static gboolean
+fill_buffer (GZHandle *gz,
+             gsize num_bytes)
+{
+  gsize count;
+
+  z_stream * zstream = &gz->zstream;
+
+  if (zstream->avail_in > 0) {
+    return TRUE;
+  }
+
+  count = g_input_stream_read (gz->parent_str,
+                               gz->buffer,
+                               Z_BUFSIZE,
+                               NULL, NULL);
+  if (count == -1) {
+    if (zstream->avail_out == num_bytes) {
+      return FALSE;
+    }
+    gz->last_str_result = FALSE;
+  } else {
+    zstream->next_in = gz->buffer;
+    zstream->avail_in = count;
+  }
+
+  return TRUE;
+}
+
+static gboolean
+result_from_z_result (int z_result)
+{
+  switch (z_result) {
+    case Z_OK:
+    case Z_STREAM_END:
+        return TRUE;
+    case Z_DATA_ERROR:
+      return FALSE;
+    default:
+      return FALSE;
+  }
+}
+
+static gboolean
+gz_handle_read (GZHandle *gz,
+                guchar *buffer,
+                gsize num_bytes,
+                gsize * bytes_read)
+{
+  z_stream *zstream;
+  gboolean res;
+  int z_result;
+
+  *bytes_read = 0;
+  zstream = &gz->zstream;
+
+  if (gz->last_z_result != Z_OK) {
+    if (gz->last_z_result == Z_STREAM_END) {
+      *bytes_read = 0;
+      return TRUE;
+    } else {
+      return result_from_z_result (gz->last_z_result);
+    }
+  } else if (gz->last_str_result == FALSE) {
+    return FALSE;
+  }
+
+  zstream->next_out = buffer;
+  zstream->avail_out = num_bytes;
+
+  while (zstream->avail_out != 0) {
+    res = fill_buffer (gz, num_bytes);
+
+    if (!res) {
+      return res;
+    }
+
+    z_result = inflate (zstream, Z_NO_FLUSH);
+    if (z_result == Z_STREAM_END) {
+      gz->last_z_result = z_result;
+      break;
+    } else if (z_result != Z_OK) {
+      gz->last_z_result = z_result;
+    }
+
+    if (gz->last_z_result != Z_OK && zstream->avail_out == num_bytes) {
+      return result_from_z_result (gz->last_z_result);
+    }
+  }
+
+  *bytes_read = num_bytes - zstream->avail_out;
+
+  return TRUE;
+}
+
+static GError *
+create_zlib_error (void)
+{
+  GError *err;
+
+  err = g_error_new_literal (LOGVIEW_ERROR_QUARK, LOGVIEW_ERROR_ZLIB,
+                             _("Error while uncompressing the GZipped log. The file "
+                               "might be corrupt."));
+  return err;
+}
+
+#endif /* HAVE_ZLIB */
+static void
+log_load (GTask        *task,
+          gpointer      source_object,
+          gpointer      user_data,
+          GCancellable *cancellable)
+{
+  /* this runs in a separate i/o thread */
+  LoadJob *job = user_data;
+  LogviewLog *log = job->log;
+  GFile *f = log->priv->file;
+  GFileInfo *info;
+  GInputStream *is;
+  const char *peeked_buffer;
+  const char * parse_data[2];
+  GSList *days;
+  const char *content_type;
+  GFileType type;
+  GError *err = NULL;
+  gboolean is_archive, can_read;
+
+  info = g_file_query_info (f,
+                            G_FILE_ATTRIBUTE_ACCESS_CAN_READ ","
+                            G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE ","
+                            G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME ","
+                            G_FILE_ATTRIBUTE_STANDARD_TYPE ","
+                            G_FILE_ATTRIBUTE_STANDARD_SIZE ","
+                            G_FILE_ATTRIBUTE_TIME_MODIFIED ",",
+                            0, NULL, &err);
+  if (err) {
+    if (err->code == G_IO_ERROR_PERMISSION_DENIED) {
+      /* TODO: PolicyKit integration */
+    }
+    goto out;
+  }
+
+  can_read = g_file_info_get_attribute_boolean (info,
+                                                G_FILE_ATTRIBUTE_ACCESS_CAN_READ);
+  if (!can_read) {
+    /* TODO: PolicyKit integration */
+    err = g_error_new_literal (LOGVIEW_ERROR_QUARK, LOGVIEW_ERROR_PERMISSION_DENIED,
+                               _("You don't have enough permissions to read the file."));
+    g_object_unref (info);
+
+    goto out;
+  }
+
+  type = g_file_info_get_file_type (info);
+  content_type = g_file_info_get_content_type (info);
+
+  is_archive = g_content_type_equals (content_type, "application/x-gzip");
+
+  if (((type != G_FILE_TYPE_REGULAR) && (type != G_FILE_TYPE_SYMBOLIC_LINK)) ||
+      (!g_content_type_is_a (content_type, "text/plain") && !is_archive))
+  {
+    err = g_error_new_literal (LOGVIEW_ERROR_QUARK, LOGVIEW_ERROR_NOT_A_LOG,
+                               _("The file is not a regular file or is not a text file."));
+    g_object_unref (info);
+
+    goto out;
+  }
+
+  log->priv->file_size = g_file_info_get_size (info);
+#if GLIB_CHECK_VERSION(2,61,2)
+  GDateTime *file_dt;
+  gint64 t;
+  file_dt = g_file_info_get_modification_date_time (info);
+  t = g_date_time_to_unix (file_dt);
+  g_date_time_unref (file_dt);
+  log->priv->file_time = t;
+#else
+  GTimeVal time_val;
+  g_file_info_get_modification_time (info, &time_val);
+  log->priv->file_time = time_val.tv_sec;
+#endif
+
+  log->priv->display_name = g_strdup (g_file_info_get_display_name (info));
+
+  g_object_unref (info);
+
+  /* initialize the stream */
+  is = G_INPUT_STREAM (g_file_read (f, NULL, &err));
+
+  if (err) {
+    if (err->code == G_IO_ERROR_PERMISSION_DENIED) {
+      /* TODO: PolicyKit integration */
+    }
+
+    goto out;
+  }
+
+  if (is_archive) {
+#ifdef HAVE_ZLIB
+    GZHandle *gz;
+    gboolean res;
+    guchar * buffer;
+    gsize bytes_read;
+    GInputStream *real_is;
+    time_t mtime; /* seconds */
+
+    /* this also skips the header from |is| */
+    res = read_gzip_header (is, &mtime);
+
+    if (!res) {
+      g_object_unref (is);
+
+      err = create_zlib_error ();
+      goto out;
+    }
+
+    log->priv->file_time = mtime;
+
+    gz = gz_handle_new (f, is);
+    res = gz_handle_init (gz);
+
+    if (!res) {
+      g_object_unref (is);
+      gz_handle_free (gz);
+
+      err = create_zlib_error ();
+      goto out;
+    }
+
+    real_is = g_memory_input_stream_new ();
+
+    do {
+      buffer = g_malloc (1024);
+      res = gz_handle_read (gz, buffer, 1024, &bytes_read);
+      g_memory_input_stream_add_data (G_MEMORY_INPUT_STREAM (real_is),
+                                      buffer, bytes_read, g_free);
+    } while (res == TRUE && bytes_read > 0);
+
+    if (!res) {
+      gz_handle_free (gz);
+      g_object_unref (real_is);
+      g_object_unref (is);
+
+      err = create_zlib_error ();
+      goto out;
+    }
+
+    g_object_unref (is);
+    is = real_is;
+
+    gz_handle_free (gz);
+#else /* HAVE_ZLIB */
+    g_object_unref (is);
+
+    err = g_error_new_literal (LOGVIEW_ERROR_QUARK, LOGVIEW_ERROR_NOT_SUPPORTED,
+                               _("This version of System Log does not support GZipped logs."));
+    goto out;
+#endif /* HAVE_ZLIB */
+  }
+
+  log->priv->stream = g_data_input_stream_new (is);
+
+  /* sniff into the stream for a timestamped line */
+  g_buffered_input_stream_fill (G_BUFFERED_INPUT_STREAM (log->priv->stream),
+                                (gssize) g_buffered_input_stream_get_buffer_size (G_BUFFERED_INPUT_STREAM (log->priv->stream)),
+                                NULL, &err);
+  if (err == NULL) {
+    peeked_buffer = g_buffered_input_stream_peek_buffer
+        (G_BUFFERED_INPUT_STREAM (log->priv->stream), NULL);
+    parse_data[0] = peeked_buffer;
+    parse_data[1] = NULL;
+
+    if ((days = log_read_dates (parse_data, time (NULL))) != NULL) {
+      log->priv->has_days = TRUE;
+      g_slist_free_full (days, (GDestroyNotify) logview_utils_day_free);
+    } else {
+      log->priv->has_days = FALSE;
+    }
+  } else {
+    log->priv->has_days = FALSE;
+    g_clear_error (&err);
+  }
+
+  g_object_unref (is);
+
+out:
+  if (err) {
+    g_task_return_error (task, err);
+  }
+
+  g_task_return_boolean (task, TRUE);
+}
+
+static void
+log_setup_load (LogviewLog *log, LogviewCreateCallback callback,
+                gpointer user_data)
+{
+  LoadJob *job;
+  GTask   *task;
+
+  job = g_slice_new0 (LoadJob);
+  job->callback = callback;
+  job->user_data = user_data;
+  job->log = log;
+
+  task = g_task_new (log, NULL, log_load_done, job);
+  g_task_set_task_data (task, job, NULL);
+  g_task_run_in_thread (task, log_load);
+  g_object_unref (task);
+}
+
+/* public methods */
+
+void
+logview_log_read_new_lines (LogviewLog *log,
+                            GCancellable *cancellable,
+                            LogviewNewLinesCallback callback,
+                            gpointer user_data)
+{
+  NewLinesJob *job;
+  GTask       *task;
+
+  /* initialize the job struct with sensible values */
+  job = g_slice_new0 (NewLinesJob);
+  job->callback = callback;
+  job->user_data = user_data;
+  job->log = g_object_ref (log);
+  job->lines = NULL;
+  job->new_days = NULL;
+
+  task = g_task_new (log, cancellable, new_lines_job_done, job);
+  g_task_set_task_data (task, job, NULL);
+  g_task_run_in_thread (task, do_read_new_lines);
+  g_object_unref (task);
+}
+
+void
+logview_log_create (const char *filename, LogviewCreateCallback callback,
+                    gpointer user_data)
+{
+  LogviewLog *log = g_object_new (LOGVIEW_TYPE_LOG, NULL);
+
+  log->priv->file = g_file_new_for_path (filename);
+
+  log_setup_load (log, callback, user_data);
+}
+
+void
+logview_log_create_from_gfile (GFile *file, LogviewCreateCallback callback,
+                               gpointer user_data)
+{
+  LogviewLog *log = g_object_new (LOGVIEW_TYPE_LOG, NULL);
+
+  log->priv->file = g_object_ref (file);
+
+  log_setup_load (log, callback, user_data);
+}
+
+const char *
+logview_log_get_display_name (LogviewLog *log)
+{
+  g_assert (LOGVIEW_IS_LOG (log));
+
+  return log->priv->display_name;
+}
+
+time_t
+logview_log_get_timestamp (LogviewLog *log)
+{
+  g_assert (LOGVIEW_IS_LOG (log));
+
+  return log->priv->file_time;
+}
+
+goffset
+logview_log_get_file_size (LogviewLog *log)
+{
+  g_assert (LOGVIEW_IS_LOG (log));
+
+  return log->priv->file_size;
+}
+
+guint
+logview_log_get_cached_lines_number (LogviewLog *log)
+{
+  g_assert (LOGVIEW_IS_LOG (log));
+
+  return log->priv->lines_no;
+}
+
+const char **
+logview_log_get_cached_lines (LogviewLog *log)
+{
+  const char ** lines = NULL;
+
+  g_assert (LOGVIEW_IS_LOG (log));
+
+  if (log->priv->lines) {
+    lines = (const char **) log->priv->lines->pdata;
+  }
+
+  return lines;
+}
+
+GSList *
+logview_log_get_days_for_cached_lines (LogviewLog *log)
+{
+  g_assert (LOGVIEW_IS_LOG (log));
+
+  return log->priv->days;
+}
+
+gboolean
+logview_log_has_new_lines (LogviewLog *log)
+{
+  g_assert (LOGVIEW_IS_LOG (log));
+
+  return log->priv->has_new_lines;
+}
+
+char *
+logview_log_get_uri (LogviewLog *log)
+{
+  g_assert (LOGVIEW_IS_LOG (log));
+
+  return g_file_get_uri (log->priv->file);
+}
+
+GFile *
+logview_log_get_gfile (LogviewLog *log)
+{
+  g_assert (LOGVIEW_IS_LOG (log));
+
+  return g_object_ref (log->priv->file);
+}
+
+gboolean
+logview_log_get_has_days (LogviewLog *log)
+{
+  g_assert (LOGVIEW_IS_LOG (log));
+
+  return log->priv->has_days;
+}
+
+
+ +
+ +
+ + diff --git a/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/21.html b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/21.html new file mode 100644 index 00000000..c27721a0 --- /dev/null +++ b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/21.html @@ -0,0 +1,1251 @@ + + + + + + Cppcheck - HTML report - mate-utils + + + + + +
+ + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
+479
+480
+481
+482
+483
+484
+485
+486
+487
+488
+489
+490
+491
+492
+493
+494
+495
/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2; -*- */
+/* Copyright (C) 2005 Vincent Noel <vnoel@cox.net>
+ * Copyright (C) 2008 Cosimo Cecchi <cosimoc@gnome.org>
+ * Copyright (C) 2012-2021 MATE Developers
+ *
+ * This file is part of MATE Utils.
+ *
+ * MATE Utils is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * MATE Utils is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MATE Utils.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <gtk/gtk.h>
+#include <glib/gi18n.h>
+
+#include "logview-manager.h"
+#include "logview-log.h"
+#include "logview-utils.h"
+
+#include "logview-loglist.h"
+
+struct _LogviewLoglistPrivate {
+  GtkTreeStore *model;
+  LogviewManager *manager;
+  GtkTreePath *selection;
+  gboolean has_day_selection;
+};
+
+G_DEFINE_TYPE_WITH_PRIVATE (LogviewLoglist, logview_loglist, GTK_TYPE_TREE_VIEW);
+
+enum {
+  LOG_OBJECT = 0,
+  LOG_NAME,
+  LOG_WEIGHT,
+  LOG_WEIGHT_SET,
+  LOG_DAY
+};
+
+enum {
+  DAY_SELECTED,
+  DAY_CLEARED,
+  LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+static void
+save_day_selection (LogviewLoglist *loglist, GtkTreeIter *iter)
+{
+  if (loglist->priv->selection) {
+    gtk_tree_path_free (loglist->priv->selection);
+  }
+
+  loglist->priv->selection = gtk_tree_model_get_path
+    (GTK_TREE_MODEL (loglist->priv->model), iter);
+}
+
+static void
+update_days_and_lines_for_log (LogviewLoglist *loglist,
+                               GtkTreeIter *log, GSList *days)
+{
+  gboolean res;
+  GtkTreeIter iter, dummy;
+  GSList *l;
+  int i;
+  char date[200];
+  Day *day;
+
+  /* if we have some days, we can't remove all the items immediately, otherwise,
+   * if the row is expanded, it will be collapsed because there are no items,
+   * so we create a dummy entry, remove all the others and then remove the
+   * dummy one.
+   */
+  res = gtk_tree_model_iter_children (GTK_TREE_MODEL (loglist->priv->model),
+                                      &iter, log);
+  if (res) {
+    gtk_tree_store_insert_before (loglist->priv->model, &dummy, log, &iter);
+    gtk_tree_store_set (loglist->priv->model, &dummy,
+                        LOG_NAME, "", -1);
+    do {
+      gtk_tree_store_remove (loglist->priv->model, &iter);
+    } while (gtk_tree_store_iter_is_valid (loglist->priv->model, &iter));
+  }
+
+  for (i = 1, l = days; l; l = l->next) {
+    /* now insert all the days */
+    day = l->data;
+
+    /* TRANSLATORS: "strftime format options, see the man page for strftime(3) for further information." */
+    g_date_strftime (date, 200, _("%A, %e %b"), day->date);
+
+    gtk_tree_store_insert (GTK_TREE_STORE (loglist->priv->model),
+                           &iter, log, i);
+    gtk_tree_store_set (GTK_TREE_STORE (loglist->priv->model),
+                        &iter, LOG_NAME, date, LOG_DAY, day, -1);
+    i++;
+  }
+
+  if (res) {
+    gtk_tree_store_remove (loglist->priv->model, &dummy);
+  }
+}
+
+static GtkTreeIter *
+logview_loglist_find_log (LogviewLoglist *list, LogviewLog *log)
+{
+  GtkTreeIter iter;
+  GtkTreeModel *model;
+  GtkTreeIter *retval = NULL;
+  LogviewLog *current;
+
+  model = GTK_TREE_MODEL (list->priv->model);
+
+  if (!gtk_tree_model_get_iter_first (model, &iter)) {
+    return NULL;
+  }
+
+  do {
+    gtk_tree_model_get (model, &iter, LOG_OBJECT, &current, -1);
+    if (current == log) {
+      retval = gtk_tree_iter_copy (&iter);
+    }
+    if (current)
+      g_object_unref (current);
+  } while (gtk_tree_model_iter_next (model, &iter) != FALSE && retval == NULL);
+
+  return retval;
+}
+
+static void
+log_changed_cb (LogviewLog *log,
+                gpointer user_data)
+{
+  LogviewLoglist *list = user_data;
+  LogviewLog *active;
+  GtkTreeIter *iter;
+
+  active = logview_manager_get_active_log (list->priv->manager);
+
+  if (log == active) {
+    g_object_unref (active);
+    return;
+  }
+
+  iter = logview_loglist_find_log (list, log);
+
+  if (!iter) {
+    return;
+  }
+
+  /* make the log bold in the list */
+  gtk_tree_store_set (list->priv->model, iter,
+                      LOG_WEIGHT, PANGO_WEIGHT_BOLD,
+                      LOG_WEIGHT_SET, TRUE, -1);
+
+  gtk_tree_iter_free (iter);
+}
+
+static void
+tree_selection_changed_cb (GtkTreeSelection *selection,
+                           gpointer user_data)
+{
+  LogviewLoglist *list = user_data;
+  GtkTreeModel *model;
+  GtkTreeIter iter, parent;
+  LogviewLog *log;
+  gboolean is_bold, is_active;
+  Day *day;
+
+  if (!gtk_tree_selection_get_selected (selection, &model, &iter)) {
+      return;
+  }
+
+  gtk_tree_model_get (model, &iter, LOG_OBJECT, &log,
+                      LOG_WEIGHT_SET, &is_bold,
+                      LOG_DAY, &day, -1);
+  if (log) {
+    is_active = logview_manager_log_is_active (list->priv->manager, log);
+
+    if (is_active && list->priv->has_day_selection) {
+      list->priv->has_day_selection = FALSE;
+      g_signal_emit (list, signals[DAY_CLEARED], 0, NULL);
+    } else if (!is_active) {
+      logview_manager_set_active_log (list->priv->manager, log);
+    }
+  } else if (day) {
+    list->priv->has_day_selection = TRUE;
+    gtk_tree_model_iter_parent (model, &parent, &iter);
+    gtk_tree_model_get (model, &parent, LOG_OBJECT, &log, -1);
+
+    if (!logview_manager_log_is_active (list->priv->manager, log)) {
+      save_day_selection (list, &iter);
+      logview_manager_set_active_log (list->priv->manager, log);
+    } else {
+      g_signal_emit (list, signals[DAY_SELECTED], 0, day, NULL);
+    }
+  }
+
+  if (is_bold) {
+    gtk_tree_store_set (GTK_TREE_STORE (model), &iter,
+                        LOG_WEIGHT_SET, FALSE, -1);
+  }
+
+  if (log) {
+    g_object_unref (log);
+  }
+}
+
+static void
+manager_active_changed_cb (LogviewManager *manager,
+                           LogviewLog *log,
+                           LogviewLog *old_log,
+                           gpointer user_data)
+{
+  LogviewLoglist *list = user_data;
+  GtkTreeIter * iter, sel_iter;
+  GtkTreeSelection * selection;
+
+  if (list->priv->selection &&
+      gtk_tree_model_get_iter (GTK_TREE_MODEL (list->priv->model),
+                               &sel_iter, list->priv->selection))
+  {
+    Day *day;
+
+    iter = gtk_tree_iter_copy (&sel_iter);
+
+    gtk_tree_model_get (GTK_TREE_MODEL (list->priv->model), iter,
+                        LOG_DAY, &day, -1);
+
+    if (day) {
+      g_signal_emit (list, signals[DAY_SELECTED], 0, day, NULL);
+    }
+
+    gtk_tree_path_free (list->priv->selection);
+    list->priv->selection = NULL;
+  } else {
+    iter = logview_loglist_find_log (list, log);
+  }
+
+  if (!iter) {
+    return;
+  }
+
+  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (list));
+  g_signal_handlers_block_by_func (selection, tree_selection_changed_cb, list);
+
+  gtk_tree_selection_select_iter (selection, iter);
+
+  g_signal_handlers_unblock_by_func (selection, tree_selection_changed_cb, list);
+  gtk_tree_iter_free (iter);
+}
+
+static void
+manager_log_closed_cb (LogviewManager *manager,
+                       LogviewLog *log,
+                       gpointer user_data)
+{
+  LogviewLoglist *list = user_data;
+  GtkTreeIter *iter;
+  gboolean res;
+
+  iter = logview_loglist_find_log (list, log);
+
+  if (!iter) {
+    return;
+  }
+
+  g_signal_handlers_disconnect_by_func (log, log_changed_cb, list);
+
+  res = gtk_tree_store_remove (list->priv->model, iter);
+  if (res) {
+    GtkTreeSelection *selection;
+
+    /* iter now points to the next valid row */
+    selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (list));
+    gtk_tree_selection_select_iter (selection, iter);
+  } else {
+    /* FIXME: what shall we do here? */
+  }
+
+  gtk_tree_iter_free (iter);
+}
+
+static void
+manager_log_added_cb (LogviewManager *manager,
+                      LogviewLog *log,
+                      gpointer user_data)
+{
+  LogviewLoglist *list = user_data;
+  GtkTreeIter iter, child;
+
+  gtk_tree_store_append (list->priv->model, &iter, NULL);
+  gtk_tree_store_set (list->priv->model, &iter,
+                      LOG_OBJECT, g_object_ref (log),
+                      LOG_NAME, logview_log_get_display_name (log), -1);
+  if (logview_log_get_has_days (log)) {
+    gtk_tree_store_insert (list->priv->model,
+                           &child, &iter, 0);
+    gtk_tree_store_set (list->priv->model, &child,
+                        LOG_NAME, _("Loading..."), -1);
+  }
+
+  g_signal_connect (log, "log-changed",
+                    G_CALLBACK (log_changed_cb), list);
+}
+
+static void
+row_expanded_cb (GtkTreeView *view,
+                 GtkTreeIter *iter,
+                 GtkTreePath *path,
+                 gpointer user_data)
+{
+  LogviewLoglist *list = user_data;
+  LogviewLog *log;
+
+  gtk_tree_model_get (GTK_TREE_MODEL (list->priv->model), iter,
+                      LOG_OBJECT, &log, -1);
+  if (!logview_manager_log_is_active (list->priv->manager, log)) {
+    logview_manager_set_active_log (list->priv->manager, log);
+  }
+
+  g_object_unref (log);
+}
+
+static int
+loglist_sort_func (GtkTreeModel *model,
+                   GtkTreeIter *a,
+                   GtkTreeIter *b,
+                   gpointer user_data)
+{
+  char *name_a, *name_b;
+  Day *day_a, *day_b;
+  int retval = 0;
+
+  switch (gtk_tree_store_iter_depth (GTK_TREE_STORE (model), a)) {
+    case 0:
+      gtk_tree_model_get (model, a, LOG_NAME, &name_a, -1);
+      gtk_tree_model_get (model, b, LOG_NAME, &name_b, -1);
+      retval = g_utf8_collate (name_a, name_b);
+      g_free (name_a);
+      g_free (name_b);
+
+      break;
+    case 1:
+      gtk_tree_model_get (model, a, LOG_DAY, &day_a, -1);
+      gtk_tree_model_get (model, b, LOG_DAY, &day_b, -1);
+      if (day_a && day_b) {
+        retval = days_compare (day_a, day_b);
+      } else {
+        retval = 0;
+      }
+
+      break;
+    default:
+      g_assert_not_reached ();
+
+      break;
+  }
+
+  return retval;
+}
+
+static void
+do_finalize (GObject *obj)
+{
+  LogviewLoglist *list = LOGVIEW_LOGLIST (obj);
+
+  g_object_unref (list->priv->model);
+  list->priv->model = NULL;
+
+  if (list->priv->selection) {
+    gtk_tree_path_free (list->priv->selection);
+    list->priv->selection = NULL;
+  }
+
+  G_OBJECT_CLASS (logview_loglist_parent_class)->finalize (obj);
+}
+
+static void
+logview_loglist_init (LogviewLoglist *list)
+{
+  GtkTreeStore *model;
+  GtkTreeViewColumn *column;
+  GtkTreeSelection *selection;
+  GtkCellRenderer *cell;
+
+  list->priv = logview_loglist_get_instance_private (list);
+  list->priv->has_day_selection = FALSE;
+  list->priv->selection = NULL;
+
+  model = gtk_tree_store_new (5, LOGVIEW_TYPE_LOG, G_TYPE_STRING, G_TYPE_INT,
+                              G_TYPE_BOOLEAN, G_TYPE_POINTER);
+  gtk_tree_view_set_model (GTK_TREE_VIEW (list), GTK_TREE_MODEL (model));
+  list->priv->model = model;
+  gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (list), FALSE);
+
+  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (list));
+  gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE);
+  g_signal_connect (selection, "changed",
+                    G_CALLBACK (tree_selection_changed_cb), list);
+
+  cell = gtk_cell_renderer_text_new ();
+  column = gtk_tree_view_column_new ();
+  gtk_tree_view_column_pack_start (column, cell, TRUE);
+  gtk_tree_view_column_set_attributes (column, cell,
+                                       "text", LOG_NAME,
+                                       "weight-set", LOG_WEIGHT_SET,
+                                       "weight", LOG_WEIGHT,
+                                       NULL);
+
+  gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (list->priv->model), LOG_NAME, GTK_SORT_ASCENDING);
+  gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (list->priv->model),
+                                   LOG_NAME,
+                                   (GtkTreeIterCompareFunc) loglist_sort_func,
+                                   list, NULL);
+  gtk_tree_view_append_column (GTK_TREE_VIEW (list), column);
+  gtk_tree_view_set_search_column (GTK_TREE_VIEW (list), -1);
+
+  list->priv->manager = logview_manager_get ();
+
+  g_signal_connect (list->priv->manager, "log-added",
+                    G_CALLBACK (manager_log_added_cb), list);
+  g_signal_connect (list->priv->manager, "log-closed",
+                    G_CALLBACK (manager_log_closed_cb), list);
+  g_signal_connect_after (list->priv->manager, "active-changed",
+                          G_CALLBACK (manager_active_changed_cb), list);
+  g_signal_connect (list, "row-expanded",
+                    G_CALLBACK (row_expanded_cb), list);
+}
+
+static void
+logview_loglist_class_init (LogviewLoglistClass *klass)
+{
+  GObjectClass *oclass = G_OBJECT_CLASS (klass);
+  oclass->finalize = do_finalize;
+
+  signals[DAY_SELECTED] = g_signal_new ("day-selected",
+                                        G_OBJECT_CLASS_TYPE (oclass),
+                                        G_SIGNAL_RUN_LAST,
+                                        G_STRUCT_OFFSET (LogviewLoglistClass, day_selected),
+                                        NULL, NULL,
+                                        g_cclosure_marshal_VOID__POINTER,
+                                        G_TYPE_NONE, 1,
+                                        G_TYPE_POINTER);
+
+  signals[DAY_CLEARED] = g_signal_new ("day-cleared",
+                                       G_OBJECT_CLASS_TYPE (oclass),
+                                       G_SIGNAL_RUN_LAST,
+                                       G_STRUCT_OFFSET (LogviewLoglistClass, day_cleared),
+                                       NULL, NULL,
+                                       g_cclosure_marshal_VOID__VOID,
+                                       G_TYPE_NONE, 0);
+}
+
+/* public methods */
+
+GtkWidget *
+logview_loglist_new (void)
+{
+  GtkWidget *widget;
+  widget = g_object_new (LOGVIEW_TYPE_LOGLIST, NULL);
+  return widget;
+}
+
+void
+logview_loglist_update_lines (LogviewLoglist *loglist, LogviewLog *log)
+{
+  GSList *days;
+  GtkTreeIter *parent;
+
+  g_assert (LOGVIEW_IS_LOGLIST (loglist));
+  g_assert (LOGVIEW_IS_LOG (log));
+
+  parent = logview_loglist_find_log (loglist, log);
+
+  if (parent) {
+    days = logview_log_get_days_for_cached_lines (log);
+    update_days_and_lines_for_log (loglist, parent, days);
+    gtk_tree_iter_free (parent);
+  }
+}
+
+
+ +
+ +
+ + diff --git a/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/22.html b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/22.html new file mode 100644 index 00000000..340d911e --- /dev/null +++ b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/22.html @@ -0,0 +1,1095 @@ + + + + + + Cppcheck - HTML report - mate-utils + + + + + +
+ + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2; -*- */
+/* Copyright (C) 2008 Cosimo Cecchi <cosimoc@gnome.org>
+ * Copyright (C) 2012-2021 MATE Developers
+ *
+ * This file is part of MATE Utils.
+ *
+ * MATE Utils is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * MATE Utils is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MATE Utils.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "logview-manager.h"
+
+#include <glib/gi18n.h>
+
+#include "logview-prefs.h"
+#include "logview-marshal.h"
+#include "logview-app.h"
+
+enum {
+  LOG_ADDED,
+  LOG_CLOSED,
+  ACTIVE_CHANGED,
+  LAST_SIGNAL
+};
+
+typedef struct {
+  LogviewManager *manager;
+  gboolean set_active;
+  gboolean is_multiple;
+  GFile *file;
+} CreateCBData;
+
+typedef struct {
+  int total;
+  int current;
+  GPtrArray *errors;
+} MultipleCreation;
+
+struct _LogviewManagerPrivate {
+  GHashTable *logs;
+  LogviewLog *active_log;
+};
+
+static LogviewManager *singleton = NULL;
+static MultipleCreation *op = NULL;
+static guint signals[LAST_SIGNAL] = { 0 };
+
+G_DEFINE_TYPE_WITH_PRIVATE (LogviewManager, logview_manager, G_TYPE_OBJECT);
+
+static void
+logview_manager_finalize (GObject *object)
+{
+  LogviewManager *manager;
+
+  manager = LOGVIEW_MANAGER (object);
+
+  if (manager->priv->active_log) {
+   g_object_unref (manager->priv->active_log);
+  }
+
+  g_hash_table_destroy (manager->priv->logs);
+
+  G_OBJECT_CLASS (logview_manager_parent_class)->finalize (object);
+}
+
+static void
+logview_manager_class_init (LogviewManagerClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->finalize = logview_manager_finalize;
+
+  signals[LOG_ADDED] = g_signal_new ("log-added",
+                                     G_OBJECT_CLASS_TYPE (object_class),
+                                     G_SIGNAL_RUN_LAST,
+                                     G_STRUCT_OFFSET (LogviewManagerClass, log_added),
+                                     NULL, NULL,
+                                     g_cclosure_marshal_VOID__OBJECT,
+                                     G_TYPE_NONE, 1,
+                                     LOGVIEW_TYPE_LOG);
+
+  signals[LOG_CLOSED] = g_signal_new ("log-closed",
+                                      G_OBJECT_CLASS_TYPE (object_class),
+                                      G_SIGNAL_RUN_LAST,
+                                      G_STRUCT_OFFSET (LogviewManagerClass, log_closed),
+                                      NULL, NULL,
+                                      g_cclosure_marshal_VOID__OBJECT,
+                                      G_TYPE_NONE, 1,
+                                      LOGVIEW_TYPE_LOG);
+
+  signals[ACTIVE_CHANGED] = g_signal_new ("active-changed",
+                                          G_OBJECT_CLASS_TYPE (object_class),
+                                          G_SIGNAL_RUN_LAST,
+                                          G_STRUCT_OFFSET (LogviewManagerClass, active_changed),
+                                          NULL, NULL,
+                                          logview_marshal_VOID__OBJECT_OBJECT,
+                                          G_TYPE_NONE, 2,
+                                          LOGVIEW_TYPE_LOG,
+                                          LOGVIEW_TYPE_LOG);
+}
+
+static void
+logview_manager_init (LogviewManager *self)
+{
+  LogviewManagerPrivate *priv = self->priv = logview_manager_get_instance_private (self);
+
+  priv->active_log = NULL;
+  priv->logs = g_hash_table_new_full (g_str_hash, g_str_equal,
+                                      g_free, g_object_unref);
+}
+
+static MultipleCreation *
+multiple_creation_op_new (int total)
+{
+  MultipleCreation *retval;
+
+  retval = g_slice_new0 (MultipleCreation);
+  retval->total = total;
+  retval->current = 0;
+  retval->errors = g_ptr_array_new ();
+
+  return retval;
+}
+
+static void
+multiple_creation_op_free (MultipleCreation *mc)
+{
+  g_ptr_array_set_free_func (mc->errors, (GDestroyNotify) g_strfreev);
+  g_ptr_array_free (mc->errors, TRUE);
+  g_slice_free (MultipleCreation, mc);
+}
+
+static void
+create_log_cb (LogviewLog *log,
+               GError *error,
+               gpointer user_data)
+{
+  CreateCBData *data = user_data;
+
+  if (log) {
+    char *log_uri;
+    LogviewPrefs *prefs;
+    GFile *file;
+
+    log_uri = logview_log_get_uri (log);
+
+    /* creation went well, store the log and notify */
+    g_hash_table_insert (data->manager->priv->logs,
+                         log_uri, log);
+
+    prefs = logview_prefs_get ();
+    file = logview_log_get_gfile (log);
+    logview_prefs_store_log (prefs, file);
+
+    g_object_unref (file);
+
+    g_signal_emit (data->manager, signals[LOG_ADDED], 0, log, NULL);
+
+    if (data->set_active) {
+      logview_manager_set_active_log (data->manager, log);
+    }
+  } else {
+    char *path;
+
+    /* notify the error */
+    path = g_file_get_path (data->file);
+
+    if (!data->is_multiple) {
+      logview_app_add_error (logview_app_get (),
+                             path, error->message);
+    } else {
+      char **error_arr = g_new0 (char *, 3);
+
+      error_arr[0] = g_strdup (path);
+      error_arr[1] = g_strdup (error->message);
+      error_arr[2] = NULL;
+
+      g_ptr_array_add (op->errors, error_arr);
+    }
+
+    g_free (path);
+  }
+
+  if (data->is_multiple) {
+    op->current++;
+
+    if (op->total == op->current) {
+      logview_app_add_errors (logview_app_get (), op->errors);
+      multiple_creation_op_free (op);
+      op = NULL;
+    }
+  }
+
+  g_object_unref (data->file);
+  g_slice_free (CreateCBData, data);
+}
+
+static void
+add_log_from_gfile_internal (LogviewManager *manager,
+                             GFile *file,
+                             gboolean set_active,
+                             gboolean is_multiple)
+{
+  char *file_uri;
+  LogviewLog *log;
+  CreateCBData *data;
+
+  file_uri = g_file_get_uri (file);
+
+  if (set_active == FALSE) {
+    /* if it's the first log being added, set it as active anyway */
+    set_active = (manager->priv->logs == NULL);
+  }
+
+  if ((log = g_hash_table_lookup (manager->priv->logs, file_uri)) != NULL) {
+    /* log already exists, don't load it */
+    if (set_active) {
+      logview_manager_set_active_log (manager, log);
+    }
+  } else {
+    data = g_slice_new0 (CreateCBData);
+    data->manager = manager;
+    data->set_active = set_active;
+    data->is_multiple = is_multiple;
+    data->file = g_object_ref (file);
+
+    logview_log_create_from_gfile (file, create_log_cb, data);
+  }
+
+  g_free (file_uri);
+}
+
+static void
+logview_manager_add_log_from_name (LogviewManager *manager,
+                                   const char *filename, gboolean set_active,
+                                   gboolean is_multiple)
+{
+  GFile *file;
+
+  file = g_file_new_for_path (filename);
+
+  add_log_from_gfile_internal (manager, file, set_active, is_multiple);
+
+  g_object_unref (file);
+}
+
+/* public methods */
+
+LogviewManager*
+logview_manager_get (void)
+{
+  if (!singleton) {
+    singleton = g_object_new (LOGVIEW_TYPE_MANAGER, NULL);
+  }
+
+  return singleton;
+}
+
+void
+logview_manager_set_active_log (LogviewManager *manager,
+                                LogviewLog *log)
+{
+  LogviewLog *old_log = NULL;
+  GFile *file;
+  char *path;
+
+  g_assert (LOGVIEW_IS_MANAGER (manager));
+
+  if (manager->priv->active_log) {
+    old_log = manager->priv->active_log;
+  }
+
+  manager->priv->active_log = g_object_ref (log);
+
+  file = logview_log_get_gfile (log);
+  path = g_file_get_path (file);
+  logview_prefs_store_active_logfile (logview_prefs_get (), path);
+  g_free (path);
+  g_object_unref (file);
+
+  g_signal_emit (manager, signals[ACTIVE_CHANGED], 0, log, old_log, NULL);
+
+  if (old_log) {
+    g_object_unref (old_log);
+  }
+}
+
+LogviewLog *
+logview_manager_get_active_log (LogviewManager *manager)
+{
+  g_assert (LOGVIEW_IS_MANAGER (manager));
+
+  return (manager->priv->active_log != NULL) ?
+    g_object_ref (manager->priv->active_log) :
+    NULL;
+}
+
+void
+logview_manager_add_log_from_gfile (LogviewManager *manager,
+                                    GFile *file,
+                                    gboolean set_active)
+{
+  g_assert (LOGVIEW_IS_MANAGER (manager));
+
+  add_log_from_gfile_internal (manager, file, set_active, FALSE);
+}
+
+void
+logview_manager_add_logs_from_name_list (LogviewManager *manager,
+                                         GSList *names,
+                                         const char *active)
+{
+  GSList *l;
+
+  g_assert (LOGVIEW_IS_MANAGER (manager));
+  g_assert (op == NULL);
+
+  op = multiple_creation_op_new (g_slist_length (names));
+
+  for (l = names; l; l = l->next) {
+    logview_manager_add_log_from_name (manager, l->data,
+                                       (g_ascii_strcasecmp (active, l->data) == 0),
+                                       TRUE);
+  }
+}
+
+void
+logview_manager_add_logs_from_names (LogviewManager *manager,
+                                     char ** names,
+                                     const gchar *active)
+{
+  int i;
+  gboolean set_active;
+
+  g_assert (LOGVIEW_IS_MANAGER (manager));
+  g_assert (op == NULL);
+
+  op = multiple_creation_op_new (g_strv_length (names));
+
+  for (i = 0; names[i]; i++) {
+    set_active = (active != NULL) && (!g_ascii_strcasecmp (active, names[i]));
+    logview_manager_add_log_from_name (manager, names[i], set_active,
+                                       TRUE);
+  }
+}
+
+int
+logview_manager_get_log_count (LogviewManager *manager)
+{
+  g_assert (LOGVIEW_IS_MANAGER (manager));
+
+  return g_hash_table_size (manager->priv->logs);
+}
+
+LogviewLog *
+logview_manager_get_if_loaded (LogviewManager *manager, char *uri)
+{
+  LogviewLog *log;
+
+  g_assert (LOGVIEW_IS_MANAGER (manager));
+
+  log = g_hash_table_lookup (manager->priv->logs, uri);
+
+  if (log != NULL) {
+    return g_object_ref (log);
+  }
+
+  return NULL;
+}
+
+void
+logview_manager_close_active_log (LogviewManager *manager)
+{
+  LogviewLog *active_log;
+  char *log_uri;
+  GFile *file;
+
+  g_assert (LOGVIEW_IS_MANAGER (manager));
+
+  active_log = manager->priv->active_log;
+  if (active_log == NULL) {
+    return;
+  }
+
+  log_uri = logview_log_get_uri (active_log);
+  file = logview_log_get_gfile (active_log);
+
+  g_signal_emit (manager, signals[LOG_CLOSED], 0, active_log, NULL);
+
+  logview_prefs_remove_stored_log (logview_prefs_get (), file);
+
+  g_object_unref (file);
+
+  /* drop the hash table ref */
+  g_hash_table_remove (manager->priv->logs, log_uri);
+
+  g_free (log_uri);
+
+  /* someone else will take care of setting the next active log to us */
+}
+
+gboolean
+logview_manager_log_is_active (LogviewManager *manager,
+                               LogviewLog *log)<--- Parameter 'log' can be declared as pointer to const
+{
+  g_assert (LOGVIEW_IS_MANAGER (manager));
+
+  return (manager->priv->active_log == log);
+}
+
+ +
+ +
+ + diff --git a/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/23.html b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/23.html new file mode 100644 index 00000000..0d7a59ab --- /dev/null +++ b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/23.html @@ -0,0 +1,1389 @@ + + + + + + Cppcheck - HTML report - mate-utils + + + + + +
+ + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
+479
+480
+481
+482
+483
+484
+485
+486
+487
+488
+489
+490
+491
+492
+493
+494
+495
+496
+497
+498
+499
+500
+501
+502
+503
+504
+505
+506
+507
+508
+509
+510
+511
+512
+513
+514
+515
+516
+517
+518
+519
+520
+521
+522
+523
+524
+525
+526
+527
+528
+529
+530
+531
+532
+533
+534
+535
+536
+537
+538
+539
+540
/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2; -*- */
+/* Copyright (C) 1998 Cesar Miquel <miquel@df.uba.ar>
+ * Copyright (C) 2004 Vincent Noel
+ * Copyright (C) 2006 Emmanuele Bassi
+ * Copyright (C) 2008 Cosimo Cecchi <cosimoc@gnome.org>
+ * Copyright (C) 2012-2021 MATE Developers
+ *
+ * This file is part of MATE Utils.
+ *
+ * MATE Utils is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * MATE Utils is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MATE Utils.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sys/stat.h>
+#include <string.h>
+#include <gtk/gtk.h>
+
+#include "logview-prefs.h"
+
+#define LOGVIEW_DEFAULT_HEIGHT 400
+#define LOGVIEW_DEFAULT_WIDTH 600
+
+/* logview settings */
+#define LOGVIEW_SCHEMA "org.mate.system-log"
+#define PREF_WIDTH    "width"
+#define PREF_HEIGHT	  "height"
+#define PREF_LOGFILE 	"logfile"
+#define PREF_LOGFILES "logfiles"
+#define PREF_FONTSIZE "fontsize"
+#define PREF_FILTERS  "filters"
+
+/* desktop-wide settings */
+#define MATE_MONOSPACE_FONT_NAME "monospace-font-name"
+#define MATE_MENUS_HAVE_TEAROFF  "menus-have-tearoff"
+
+static LogviewPrefs *singleton = NULL;
+
+enum {
+  SYSTEM_FONT_CHANGED,
+  HAVE_TEAROFF_CHANGED,
+  LAST_SIGNAL
+};
+
+enum {
+  FILTER_NAME,
+  FILTER_INVISIBLE,
+  FILTER_FOREGROUND,
+  FILTER_BACKGROUND,
+  FILTER_REGEX,
+  MAX_TOKENS
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+struct _LogviewPrefsPrivate {
+  GSettings *logview_prefs;
+  GSettings *interface_prefs;
+
+  GHashTable *filters;
+};
+
+G_DEFINE_TYPE_WITH_PRIVATE (LogviewPrefs, logview_prefs, G_TYPE_OBJECT);
+
+static void
+do_finalize (GObject *obj)
+{
+  LogviewPrefs *prefs = LOGVIEW_PREFS (obj);
+
+  g_hash_table_destroy (prefs->priv->filters);
+
+  g_object_unref (prefs->priv->logview_prefs);
+  g_object_unref (prefs->priv->interface_prefs);
+
+  G_OBJECT_CLASS (logview_prefs_parent_class)->finalize (obj);
+}
+
+static void
+logview_prefs_class_init (LogviewPrefsClass *klass)
+{
+  GObjectClass *oclass = G_OBJECT_CLASS (klass);
+
+  oclass->finalize = do_finalize;
+
+  signals[SYSTEM_FONT_CHANGED] = g_signal_new ("system-font-changed",
+                                               G_OBJECT_CLASS_TYPE (oclass),
+                                               G_SIGNAL_RUN_LAST,
+                                               G_STRUCT_OFFSET (LogviewPrefsClass, system_font_changed),
+                                               NULL, NULL,
+                                               g_cclosure_marshal_VOID__STRING,
+                                               G_TYPE_NONE, 1,
+                                               G_TYPE_STRING);
+  signals[HAVE_TEAROFF_CHANGED] = g_signal_new ("have-tearoff-changed",
+                                                G_OBJECT_CLASS_TYPE (oclass),
+                                                G_SIGNAL_RUN_LAST,
+                                                G_STRUCT_OFFSET (LogviewPrefsClass, have_tearoff_changed),
+                                                NULL, NULL,
+                                                g_cclosure_marshal_VOID__BOOLEAN,
+                                                G_TYPE_NONE, 1,
+                                                G_TYPE_BOOLEAN);
+}
+
+static void
+have_tearoff_changed_cb (GSettings *settings,
+                         gchar *key,
+                         gpointer data)
+{
+  LogviewPrefs *prefs = data;
+  gboolean add_tearoffs;
+
+  add_tearoffs = g_settings_get_boolean (settings, key);
+  g_signal_emit (prefs, signals[HAVE_TEAROFF_CHANGED], 0, add_tearoffs, NULL);
+}
+
+static void
+monospace_font_changed_cb (GSettings *settings,
+                           gchar *key,
+                           gpointer data)
+{
+  LogviewPrefs *prefs = data;
+  gchar *monospace_font_name;
+
+  monospace_font_name = g_settings_get_string (settings, key);
+  g_signal_emit (prefs, signals[SYSTEM_FONT_CHANGED], 0, monospace_font_name, NULL);
+
+  g_free (monospace_font_name);
+}
+
+#define DELIMITER ":"
+
+static void
+load_filters (LogviewPrefs *prefs)
+{
+  gchar **filters;
+  gchar **tokens;
+  const gchar *str;
+  LogviewFilter *filter;
+  GtkTextTag *tag;
+  GdkRGBA color;
+  gint idx;
+
+  filters = g_settings_get_strv (prefs->priv->logview_prefs,
+                                 PREF_FILTERS);
+
+  prefs->priv->filters = g_hash_table_new_full (g_str_hash, g_str_equal,
+                                                g_free,
+                                                g_object_unref);
+
+  for (idx = 0; filters[idx] != NULL; idx++) {
+    str = filters[idx];
+    tokens = g_strsplit (str, DELIMITER, MAX_TOKENS);
+    filter = logview_filter_new (tokens[FILTER_NAME], tokens[FILTER_REGEX]);
+    tag = gtk_text_tag_new (tokens[FILTER_NAME]);
+
+    g_object_set (tag, "invisible",
+                  g_str_equal (tokens[FILTER_INVISIBLE], "1"), NULL);
+
+    if (strlen (tokens[FILTER_FOREGROUND])) {
+      gdk_rgba_parse (&color, tokens[FILTER_FOREGROUND]);
+      g_object_set (tag, "foreground-rgba", &color,
+                    "foreground-set", TRUE, NULL);
+    }
+
+    if (strlen (tokens[FILTER_BACKGROUND])) {
+      gdk_rgba_parse (&color, tokens[FILTER_BACKGROUND]);
+      g_object_set (tag, "paragraph-background-rgba", &color,
+                    "paragraph-background-set", TRUE, NULL);
+    }
+
+    g_object_set (filter, "texttag", tag, NULL);
+    g_hash_table_insert (prefs->priv->filters,
+                         g_strdup(tokens[FILTER_NAME]),
+                         filter);
+
+    g_object_ref (filter);
+    g_object_unref (tag);
+    g_strfreev (tokens);
+  }
+
+  g_strfreev (filters);
+}
+
+static void
+save_filter_foreach_func (gpointer key, gpointer value, gpointer user_data)
+{
+  GPtrArray *filters;
+  const gchar *name;
+  LogviewFilter *filter;
+  GdkRGBA  *foreground;
+  gboolean foreground_set;
+  GdkRGBA  *background;
+  gboolean background_set;
+  gchar *regex, *color;
+  gboolean invisible;
+  GtkTextTag *tag;
+  GString *prefs_string;
+
+  filters = user_data;
+  filter = LOGVIEW_FILTER (value);
+  name = key;
+  color = NULL;
+
+  prefs_string = g_string_new (name);
+  g_string_append (prefs_string, DELIMITER);
+
+  g_object_get (filter,
+                "regex", &regex,
+                "texttag", &tag,
+                NULL);
+  g_object_get (tag,
+                "foreground-set", &foreground_set,
+                "foreground-rgba", &foreground,
+                "paragraph-background-set", &background_set,
+                "paragraph-background-rgba", &background,
+                "invisible", &invisible, NULL);
+
+  if (invisible) {
+    g_string_append (prefs_string, "1" DELIMITER);
+  } else {
+    g_string_append (prefs_string, "0" DELIMITER);
+  }
+
+  if (foreground_set) {
+    color = gdk_rgba_to_string (foreground);
+    g_string_append (prefs_string, color);
+    g_free (color);
+  }
+
+  if (foreground) {
+    gdk_rgba_free (foreground);
+  }
+
+  g_string_append (prefs_string, DELIMITER);
+
+  if (background_set) {
+    color = gdk_rgba_to_string (background);
+    g_string_append (prefs_string, color);
+    g_free (color);
+  }
+
+  if (background) {
+    gdk_rgba_free (background);
+  }
+
+  g_string_append (prefs_string, DELIMITER);
+  g_string_append (prefs_string, regex);
+
+  g_free (regex);
+  g_object_unref (tag);
+
+  g_ptr_array_add (filters, g_string_free (prefs_string, FALSE));
+}
+
+static void
+save_filters (LogviewPrefs *prefs)
+{
+  GPtrArray *filters;
+  gchar **filters_strv;
+
+  filters = g_ptr_array_new ();
+  g_hash_table_foreach (prefs->priv->filters,
+                        save_filter_foreach_func,
+                        filters);
+  g_ptr_array_add (filters, NULL);
+
+  filters_strv = (gchar **) g_ptr_array_free (filters, FALSE);
+  g_settings_set_strv (prefs->priv->logview_prefs,
+                       PREF_FILTERS,
+                       (const gchar **) filters_strv);
+
+  g_strfreev (filters_strv);
+}
+
+static void
+get_filters_foreach (gpointer key, gpointer value, gpointer user_data)
+{
+  GList **list;
+  list = user_data;
+  *list = g_list_append (*list, value);
+}
+
+static void
+logview_prefs_init (LogviewPrefs *self)
+{
+  LogviewPrefsPrivate *priv;
+
+  priv = self->priv = logview_prefs_get_instance_private (self);
+
+  priv->logview_prefs = g_settings_new (LOGVIEW_SCHEMA);
+  priv->interface_prefs = g_settings_new ("org.mate.interface");
+
+  g_signal_connect (priv->interface_prefs, "changed::" MATE_MONOSPACE_FONT_NAME,
+                    G_CALLBACK (monospace_font_changed_cb), self);
+  g_signal_connect (priv->interface_prefs, "changed::" MATE_MENUS_HAVE_TEAROFF,
+                    G_CALLBACK (have_tearoff_changed_cb), self);
+
+  load_filters (self);
+}
+
+/* public methods */
+
+LogviewPrefs *
+logview_prefs_get ()
+{
+  if (!singleton)
+    singleton = g_object_new (LOGVIEW_TYPE_PREFS, NULL);
+
+  return singleton;
+}
+
+void
+logview_prefs_store_window_size (LogviewPrefs *prefs,
+                                 int width, int height)
+{
+  g_assert (LOGVIEW_IS_PREFS (prefs));
+
+  g_settings_set_int (prefs->priv->logview_prefs,
+                      PREF_WIDTH, width);
+  g_settings_set_int (prefs->priv->logview_prefs,
+                      PREF_HEIGHT, height);
+}
+
+void
+logview_prefs_get_stored_window_size (LogviewPrefs *prefs,
+                                      int *width, int *height)
+{
+  g_assert (LOGVIEW_IS_PREFS (prefs));
+
+  *width = g_settings_get_int (prefs->priv->logview_prefs,
+                               PREF_WIDTH);
+  *height = g_settings_get_int (prefs->priv->logview_prefs,
+                                PREF_HEIGHT);
+
+  if ((*width == 0) ^ (*height == 0)) {
+    /* if one of the two failed, return default for both */
+    *width = LOGVIEW_DEFAULT_WIDTH;
+    *height = LOGVIEW_DEFAULT_HEIGHT;
+  }
+}
+
+char *
+logview_prefs_get_monospace_font_name (LogviewPrefs *prefs)
+{
+  g_assert (LOGVIEW_IS_PREFS (prefs));
+
+  return (g_settings_get_string (prefs->priv->interface_prefs, MATE_MONOSPACE_FONT_NAME));
+}
+
+gboolean
+logview_prefs_get_have_tearoff (LogviewPrefs *prefs)
+{
+  g_assert (LOGVIEW_IS_PREFS (prefs));
+
+	return (g_settings_get_boolean (prefs->priv->interface_prefs, MATE_MENUS_HAVE_TEAROFF));
+}
+
+/* the elements should be freed with g_free () */
+
+gchar **
+logview_prefs_get_stored_logfiles (LogviewPrefs *prefs)
+{
+  g_assert (LOGVIEW_IS_PREFS (prefs));
+
+  return g_settings_get_strv (prefs->priv->logview_prefs,
+                              PREF_LOGFILES);
+}
+
+void
+logview_prefs_store_log (LogviewPrefs *prefs, GFile *file)
+{
+  gchar **stored_logs;
+  GFile *stored;
+  gboolean found = FALSE;
+  gint idx, old_size;
+
+  g_assert (LOGVIEW_IS_PREFS (prefs));
+  g_assert (G_IS_FILE (file));
+
+  stored_logs = logview_prefs_get_stored_logfiles (prefs);
+
+  for (idx = 0; stored_logs[idx] != NULL; idx++) {
+    stored = g_file_parse_name (stored_logs[idx]);
+    if (g_file_equal (file, stored)) {
+      found = TRUE;
+    }
+
+    g_object_unref (stored);
+
+    if (found) {
+      break;
+    }
+  }
+
+  if (!found) {
+    old_size = g_strv_length (stored_logs);
+    stored_logs = g_realloc (stored_logs, (old_size + 2) * sizeof (gchar *));
+    stored_logs[old_size] = g_file_get_parse_name (file);
+    stored_logs[old_size + 1] = NULL;
+
+    g_settings_set_strv (prefs->priv->logview_prefs,
+                         PREF_LOGFILES,
+                         (const gchar **) stored_logs);
+  }
+
+  g_strfreev (stored_logs);
+}
+
+void
+logview_prefs_remove_stored_log (LogviewPrefs *prefs, GFile *target)
+{
+  gchar **stored_logs;
+  GFile *stored;
+  GPtrArray *new_value;
+  gint idx;
+
+  g_assert (LOGVIEW_IS_PREFS (prefs));
+  g_assert (G_IS_FILE (target));
+
+  stored_logs = logview_prefs_get_stored_logfiles (prefs);
+  new_value = g_ptr_array_new ();
+
+  for (idx = 0; stored_logs[idx] != NULL; idx++) {
+    stored = g_file_parse_name (stored_logs[idx]);
+    if (!g_file_equal (stored, target)) {
+      g_ptr_array_add (new_value, g_strdup (stored_logs[idx]));
+    }
+
+    g_object_unref (stored);
+  }
+
+  g_ptr_array_add (new_value, NULL);
+  g_strfreev (stored_logs);
+  stored_logs = (gchar **) g_ptr_array_free (new_value, FALSE);
+
+  g_settings_set_strv (prefs->priv->logview_prefs,
+                       PREF_LOGFILES,
+                       (const gchar **) stored_logs);
+
+  g_strfreev (stored_logs);
+}
+
+void
+logview_prefs_store_fontsize (LogviewPrefs *prefs, int fontsize)
+{
+  g_assert (LOGVIEW_IS_PREFS (prefs));
+  g_assert (fontsize > 0);
+
+  g_settings_set_int (prefs->priv->logview_prefs, PREF_FONTSIZE, fontsize);
+}
+
+int
+logview_prefs_get_stored_fontsize (LogviewPrefs *prefs)
+{
+  g_assert (LOGVIEW_IS_PREFS (prefs));
+
+	return g_settings_get_int (prefs->priv->logview_prefs, PREF_FONTSIZE);
+}
+
+void
+logview_prefs_store_active_logfile (LogviewPrefs *prefs,
+                                    const char *filename)
+{
+  g_assert (LOGVIEW_IS_PREFS (prefs));
+
+  g_settings_set_string (prefs->priv->logview_prefs,
+                         PREF_LOGFILE, filename);
+}
+
+char *
+logview_prefs_get_active_logfile (LogviewPrefs *prefs)
+{
+  g_assert (LOGVIEW_IS_PREFS (prefs));
+
+  return g_settings_get_string (prefs->priv->logview_prefs,
+                                PREF_LOGFILE);
+}
+
+GList *
+logview_prefs_get_filters (LogviewPrefs *prefs)
+{
+  GList *filters = NULL;
+
+  g_assert (LOGVIEW_IS_PREFS (prefs));
+
+  g_hash_table_foreach (prefs->priv->filters,
+                        get_filters_foreach,
+                        &filters);
+
+  return filters;
+}
+
+void
+logview_prefs_remove_filter (LogviewPrefs *prefs,
+                             const gchar *name)
+{
+  g_assert (LOGVIEW_IS_PREFS (prefs));
+
+  g_hash_table_remove (prefs->priv->filters,
+                       name);
+
+  save_filters (prefs);
+}
+
+void
+logview_prefs_add_filter (LogviewPrefs *prefs,
+                          LogviewFilter *filter)
+{
+  gchar* name;
+
+  g_assert (LOGVIEW_IS_PREFS (prefs));
+  g_assert (LOGVIEW_IS_FILTER (filter));
+
+  g_object_get (filter, "name", &name, NULL);
+  g_hash_table_insert (prefs->priv->filters, name, g_object_ref (filter));
+
+  save_filters (prefs);
+}
+
+LogviewFilter *
+logview_prefs_get_filter (LogviewPrefs *prefs,
+                          const gchar *name)
+{
+  g_assert (LOGVIEW_IS_PREFS (prefs));
+
+  return g_hash_table_lookup (prefs->priv->filters, name);
+}
+
+
+ +
+ +
+ + diff --git a/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/24.html b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/24.html new file mode 100644 index 00000000..6292d22f --- /dev/null +++ b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/24.html @@ -0,0 +1,1023 @@ + + + + + + Cppcheck - HTML report - mate-utils + + + + + +
+ + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
#include <gio/gio.h>
+
+#if defined (__ELF__) && ( __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 6))
+# define SECTION __attribute__ ((section (".gresource.logview"), aligned (8)))
+#else
+# define SECTION
+#endif
+
+static const SECTION union { const guint8 data[2997]; const double alignment; void * const ptr;}  logview_resource_data = { {<--- union member 'Anonymous0::alignment' is never used.<--- union member 'Anonymous0::ptr' is never used.
+  0107, 0126, 0141, 0162, 0151, 0141, 0156, 0164, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 
+  0030, 0000, 0000, 0000, 0310, 0000, 0000, 0000, 0000, 0000, 0000, 0050, 0006, 0000, 0000, 0000, 
+  0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0001, 0000, 0000, 0000, 0004, 0000, 0000, 0000, 
+  0004, 0000, 0000, 0000, 0005, 0000, 0000, 0000, 0113, 0120, 0220, 0013, 0002, 0000, 0000, 0000, 
+  0310, 0000, 0000, 0000, 0004, 0000, 0114, 0000, 0314, 0000, 0000, 0000, 0320, 0000, 0000, 0000, 
+  0340, 0045, 0316, 0011, 0003, 0000, 0000, 0000, 0320, 0000, 0000, 0000, 0023, 0000, 0166, 0000, 
+  0350, 0000, 0000, 0000, 0241, 0005, 0000, 0000, 0324, 0265, 0002, 0000, 0377, 0377, 0377, 0377, 
+  0241, 0005, 0000, 0000, 0001, 0000, 0114, 0000, 0244, 0005, 0000, 0000, 0250, 0005, 0000, 0000, 
+  0004, 0057, 0305, 0022, 0005, 0000, 0000, 0000, 0250, 0005, 0000, 0000, 0013, 0000, 0114, 0000, 
+  0264, 0005, 0000, 0000, 0274, 0005, 0000, 0000, 0340, 0370, 0142, 0020, 0003, 0000, 0000, 0000, 
+  0274, 0005, 0000, 0000, 0021, 0000, 0166, 0000, 0320, 0005, 0000, 0000, 0251, 0013, 0000, 0000, 
+  0201, 0321, 0040, 0031, 0000, 0000, 0000, 0000, 0251, 0013, 0000, 0000, 0005, 0000, 0114, 0000, 
+  0260, 0013, 0000, 0000, 0264, 0013, 0000, 0000, 0157, 0162, 0147, 0057, 0005, 0000, 0000, 0000, 
+  0154, 0157, 0147, 0166, 0151, 0145, 0167, 0055, 0164, 0157, 0157, 0154, 0142, 0141, 0162, 0056, 
+  0170, 0155, 0154, 0000, 0000, 0000, 0000, 0000, 0105, 0064, 0000, 0000, 0001, 0000, 0000, 0000, 
+  0170, 0332, 0355, 0133, 0337, 0163, 0243, 0066, 0020, 0176, 0277, 0277, 0102, 0345, 0261, 0063, 
+  0070, 0361, 0153, 0306, 0366, 0115, 0162, 0323, 0264, 0231, 0151, 0352, 0166, 0174, 0323, 0207, 
+  0276, 0060, 0002, 0026, 0243, 0073, 0041, 0161, 0222, 0210, 0343, 0374, 0365, 0225, 0204, 0363, 
+  0303, 0006, 0354, 0160, 0140, 0344, 0134, 0356, 0055, 0030, 0151, 0167, 0277, 0335, 0117, 0253, 
+  0135, 0211, 0114, 0076, 0336, 0147, 0024, 0335, 0201, 0220, 0204, 0263, 0251, 0067, 0036, 0235, 
+  0173, 0110, 0052, 0314, 0142, 0114, 0071, 0203, 0251, 0307, 0270, 0367, 0161, 0366, 0141, 0362, 
+  0213, 0357, 0377, 0352, 0243, 0214, 0307, 0160, 0201, 0314, 0004, 0375, 0344, 0353, 0237, 0011, 
+  0123, 0040, 0022, 0034, 0301, 0354, 0003, 0102, 0023, 0036, 0176, 0201, 0110, 0241, 0210, 0142, 
+  0051, 0247, 0336, 0357, 0352, 0353, 0115, 0206, 0227, 0340, 0041, 0022, 0117, 0275, 0014, 0130, 
+  0021, 0220, 0210, 0263, 0200, 0347, 0300, 0074, 0063, 0136, 0317, 0310, 0205, 0176, 0022, 0152, 
+  0215, 0030, 0316, 0264, 0262, 0073, 0042, 0111, 0110, 0301, 0233, 0175, 0026, 0005, 0114, 0316, 
+  0036, 0337, 0326, 0017, 0216, 0060, 0013, 0022, 0036, 0025, 0322, 0233, 0135, 0143, 0052, 0017, 
+  0216, 0067, 0312, 0175, 0363, 0247, 0067, 0213, 0365, 0064, 0155, 0220, 0362, 0215, 0055, 0333, 
+  0363, 0046, 0147, 0045, 0212, 0026, 0200, 0042, 0312, 0045, 0070, 0106, 0264, 0042, 0054, 0346, 
+  0053, 0337, 0232, 0322, 0031, 0320, 0267, 0202, 0050, 0307, 0170, 0160, 0236, 0123, 0022, 0141, 
+  0245, 0111, 0351, 0303, 0075, 0121, 0335, 0203, 0304, 0363, 0265, 0143, 0114, 0020, 0023, 0345, 
+  0033, 0073, 0072, 0203, 0111, 0164, 0264, 0117, 0001, 0214, 0261, 0243, 0063, 0030, 0342, 0072, 
+  0033, 0074, 0160, 0236, 0371, 0244, 0173, 0036, 0340, 0205, 0072, 0005, 0044, 0332, 0214, 0316, 
+  0120, 0030, 0027, 0031, 0246, 0047, 0201, 0106, 0220, 0045, 0141, 0230, 0166, 0206, 0224, 0002, 
+  0315, 0035, 0003, 0062, 0046, 0370, 0241, 0340, 0053, 0011, 0242, 0063, 0036, 0034, 0272, 0347, 
+  0233, 0005, 0144, 0015, 0151, 0003, 0347, 0126, 0143, 0270, 0302, 0242, 0004, 0104, 0371, 0322, 
+  0140, 0012, 0365, 0363, 0001, 0054, 0343, 0212, 0141, 0121, 0112, 0150, 0214, 0154, 0015, 0242, 
+  0031, 0342, 0333, 0307, 0251, 0207, 0243, 0010, 0344, 0146, 0216, 0035, 0127, 0261, 0341, 0122, 
+  0175, 0235, 0333, 0037, 0112, 0023, 0360, 0170, 0274, 0366, 0267, 0215, 0250, 0063, 0344, 0151, 
+  0326, 0305, 0305, 0263, 0212, 0215, 0043, 0076, 0247, 0200, 0066, 0022, 0166, 0255, 0334, 0366, 
+  0206, 0171, 0262, 0166, 0276, 0204, 0320, 0140, 0346, 0306, 0125, 0067, 0012, 0262, 0075, 0146, 
+  0065, 0373, 0247, 0156, 0064, 0305, 0041, 0120, 0017, 0051, 0201, 0231, 0244, 0130, 0141, 0075, 
+  0163, 0352, 0255, 0101, 0307, 0076, 0270, 0046, 0024, 0136, 0043, 0242, 0220, 0340, 0027, 0054, 
+  0006, 0101, 0011, 0153, 0124, 0133, 0206, 0106, 0255, 0163, 0075, 0101, 0026, 0241, 0361, 0315, 
+  0013, 0014, 0115, 0120, 0313, 0170, 0044, 0332, 0220, 0240, 0062, 0143, 0327, 0131, 0315, 0222, 
+  0354, 0162, 0171, 0362, 0234, 0025, 0151, 0352, 0274, 0200, 0154, 0073, 0362, 0373, 0034, 0372, 
+  0035, 0216, 0235, 0153, 0345, 0243, 0321, 0250, 0215, 0064, 0305, 0071, 0125, 0044, 0367, 0025, 
+  0334, 0253, 0132, 0241, 0106, 0046, 0302, 0110, 0257, 0036, 0224, 0010, 0236, 0241, 0244, 0041, 
+  0170, 0135, 0202, 0330, 0064, 0227, 0330, 0164, 0064, 0333, 0256, 0350, 0333, 0010, 0300, 0221, 
+  0255, 0353, 0236, 0052, 0327, 0221, 0101, 0363, 0047, 0137, 0066, 0313, 0330, 0136, 0102, 0317, 
+  0277, 0326, 0060, 0242, 0003, 0113, 0154, 0365, 0354, 0214, 0046, 0237, 0252, 0265, 0173, 0107, 
+  0222, 0130, 0211, 0110, 0245, 0104, 0032, 0242, 0070, 0243, 0107, 0324, 0026, 0130, 0205, 0037, 
+  0026, 0310, 0320, 0004, 0131, 0100, 0216, 0005, 0126, 0134, 0324, 0044, 0341, 0056, 0244, 0030, 
+  0206, 0313, 0246, 0207, 0163, 0106, 0345, 0177, 0212, 0335, 0216, 0255, 0043, 0223, 0215, 0100, 
+  0115, 0144, 0260, 0011, 0357, 0216, 0300, 0012, 0204, 0063, 0072, 0177, 0153, 0011, 0256, 0302, 
+  0346, 0375, 0336, 0171, 0065, 0075, 0252, 0003, 0167, 0006, 0275, 0221, 0272, 0343, 0267, 0270, 
+  0336, 0035, 0103, 0326, 0035, 0375, 0155, 0041, 0272, 0275, 0167, 0267, 0203, 0124, 0316, 0026, 
+  0272, 0156, 0040, 0132, 0240, 0135, 0166, 0022, 0050, 0130, 0032, 0273, 0333, 0104, 0132, 0142, 
+  0253, 0356, 0041, 0173, 0005, 0034, 0041, 0051, 0157, 0023, 0243, 0364, 0240, 0053, 0152, 0054, 
+  0254, 0166, 0024, 0134, 0122, 0332, 0053, 0101, 0066, 0162, 0015, 0105, 0200, 0051, 0042, 0140, 
+  0310, 0102, 0243, 0022, 0342, 0322, 0232, 0275, 0030, 0337, 0135, 0166, 0375, 0127, 0157, 0226, 
+  0157, 0063, 0273, 0176, 0112, 0041, 0332, 0135, 0104, 0012, 0253, 0102, 0072, 0313, 0257, 0013, 
+  0253, 0276, 0266, 0307, 0357, 0262, 0206, 0122, 0276, 0102, 0245, 0150, 0164, 0205, 0205, 0273, 
+  0325, 0243, 0355, 0050, 0315, 0330, 0153, 0305, 0021, 0062, 0145, 0135, 0244, 0111, 0354, 0254, 
+  0023, 0133, 0150, 0335, 0050, 0370, 0033, 0063, 0070, 0102, 0234, 0215, 0354, 0266, 0242, 0373, 
+  0017, 0263, 0266, 0042, 0034, 0070, 0310, 0307, 0152, 0247, 0152, 0335, 0025, 0224, 0260, 0003, 
+  0234, 0347, 0240, 0265, 0262, 0110, 0313, 0070, 0167, 0335, 0222, 0231, 0333, 0022, 0147, 0271, 
+  0353, 0132, 0053, 0357, 0373, 0020, 0312, 0310, 0104, 0030, 0255, 0270, 0210, 0021, 0027, 0050, 
+  0117, 0005, 0226, 0200, 0010, 0173, 0354, 0324, 0234, 0025, 0213, 0325, 0173, 0251, 0326, 0225, 
+  0004, 0026, 0121, 0372, 0163, 0175, 0014, 0272, 0076, 0210, 0263, 0043, 0332, 0377, 0070, 0317, 
+  0120, 0160, 0303, 0172, 0135, 0035, 0127, 0144, 0271, 0004, 0201, 0314, 0173, 0044, 0311, 0203, 
+  0273, 0343, 0131, 0322, 0355, 0160, 0326, 0124, 0220, 0306, 0101, 0373, 0334, 0063, 0014, 0101, 
+  0170, 0241, 0334, 0062, 0144, 0136, 0364, 0173, 0254, 0265, 0310, 0060, 0245, 0047, 0301, 0021, 
+  0136, 0250, 0136, 0110, 0262, 0327, 0103, 0303, 0260, 0244, 0274, 0273, 0166, 0266, 0321, 0376, 
+  0145, 0325, 0353, 0102, 0357, 0241, 0337, 0362, 0161, 0043, 0327, 0075, 0125, 0112, 0377, 0366, 
+  0302, 0226, 0361, 0371, 0371, 0133, 0151, 0325, 0037, 0157, 0046, 0025, 0010, 0035, 0014, 0064, 
+  0310, 0165, 0254, 0321, 0365, 0043, 0364, 0356, 0016, 0132, 0070, 0323, 0153, 0145, 0130, 0105, 
+  0051, 0110, 0304, 0031, 0355, 0367, 0130, 0164, 0256, 0005, 0042, 0151, 0124, 0030, 0207, 0113, 
+  0135, 0356, 0142, 0125, 0152, 0323, 0272, 0000, 0361, 0304, 0026, 0300, 0113, 0162, 0007, 0014, 
+  0045, 0315, 0141, 0034, 0244, 0335, 0053, 0151, 0164, 0153, 0214, 0233, 0357, 0365, 0303, 0061, 
+  0117, 0100, 0207, 0047, 0300, 0055, 0146, 0072, 0155, 0241, 0353, 0366, 0336, 0077, 0030, 0375, 
+  0215, 0350, 0123, 0011, 0254, 0061, 0346, 0275, 0104, 0265, 0304, 0214, 0214, 0366, 0176, 0143, 
+  0172, 0264, 0050, 0036, 0312, 0272, 0257, 0374, 0036, 0106, 0243, 0016, 0232, 0347, 0326, 0306, 
+  0270, 0061, 0316, 0357, 0360, 0020, 0374, 0017, 0240, 0371, 0017, 0163, 0305, 0150, 0076, 0272, 
+  0163, 0170, 0305, 0310, 0024, 0060, 0045, 0373, 0377, 0230, 0311, 0154, 0231, 0006, 0032, 0212, 
+  0066, 0052, 0120, 0302, 0305, 0251, 0334, 0371, 0247, 0015, 0004, 0172, 0165, 0266, 0066, 0014, 
+  0074, 0354, 0273, 0141, 0032, 0044, 0373, 0301, 0246, 0063, 0006, 0135, 0206, 0274, 0357, 0056, 
+  0332, 0124, 0142, 0206, 0050, 0026, 0030, 0212, 0011, 0266, 0237, 0305, 0235, 0016, 0173, 0160, 
+  0330, 0265, 0275, 0266, 0116, 0273, 0074, 0160, 0003, 0077, 0100, 0132, 0177, 0176, 0061, 0071, 
+  0173, 0361, 0277, 0077, 0377, 0003, 0163, 0361, 0304, 0221, 0000, 0050, 0165, 0165, 0141, 0171, 
+  0051, 0057, 0000, 0000, 0000, 0000, 0000, 0000, 0163, 0171, 0163, 0164, 0145, 0155, 0055, 0154, 
+  0157, 0147, 0057, 0000, 0004, 0000, 0000, 0000, 0001, 0000, 0000, 0000, 0154, 0157, 0147, 0166, 
+  0151, 0145, 0167, 0055, 0146, 0151, 0154, 0164, 0145, 0162, 0056, 0165, 0151, 0000, 0000, 0000, 
+  0322, 0101, 0000, 0000, 0001, 0000, 0000, 0000, 0170, 0332, 0355, 0134, 0113, 0157, 0343, 0066, 
+  0020, 0276, 0357, 0257, 0120, 0171, 0152, 0321, 0050, 0266, 0274, 0105, 0260, 0130, 0330, 0132, 
+  0354, 0156, 0223, 0264, 0100, 0321, 0303, 0142, 0173, 0026, 0050, 0211, 0226, 0330, 0320, 0244, 
+  0112, 0122, 0161, 0374, 0357, 0227, 0224, 0034, 0307, 0212, 0365, 0242, 0304, 0044, 0166, 0223, 
+  0103, 0002, 0105, 0342, 0220, 0234, 0341, 0174, 0337, 0014, 0137, 0231, 0177, 0272, 0133, 0021, 
+  0347, 0026, 0161, 0201, 0031, 0135, 0000, 0357, 0174, 0012, 0034, 0104, 0043, 0026, 0143, 0232, 
+  0054, 0300, 0077, 0337, 0257, 0334, 0017, 0340, 0223, 0377, 0156, 0376, 0223, 0353, 0072, 0327, 
+  0210, 0042, 0016, 0045, 0212, 0235, 0065, 0226, 0251, 0223, 0020, 0030, 0043, 0347, 0375, 0371, 
+  0154, 0166, 0356, 0071, 0256, 0253, 0012, 0141, 0052, 0021, 0137, 0302, 0010, 0371, 0357, 0034, 
+  0147, 0316, 0321, 0177, 0071, 0346, 0110, 0070, 0004, 0207, 0013, 0220, 0310, 0233, 0137, 0301, 
+  0103, 0103, 0132, 0014, 0114, 0212, 0162, 0054, 0374, 0027, 0105, 0322, 0211, 0010, 0024, 0142, 
+  0001, 0256, 0345, 0315, 0237, 0053, 0230, 0040, 0340, 0340, 0170, 0001, 0260, 0176, 0364, 0200, 
+  0056, 0247, 0112, 0146, 0234, 0145, 0210, 0313, 0215, 0103, 0341, 0012, 0055, 0300, 0055, 0026, 
+  0070, 0044, 0010, 0370, 0337, 0171, 0216, 0346, 0223, 0373, 0257, 0365, 0205, 0043, 0110, 0203, 
+  0045, 0213, 0162, 0001, 0374, 0053, 0110, 0104, 0147, 0171, 0034, 0061, 0032, 0350, 0107, 0340, 
+  0253, 0057, 0021, 0022, 0302, 0025, 0222, 0145, 0125, 0261, 0371, 0244, 0354, 0174, 0077, 0075, 
+  0146, 0057, 0254, 0207, 0032, 0002, 0027, 0146, 0031, 0331, 0230, 0050, 0361, 0073, 0206, 0204, 
+  0045, 0245, 0026, 0161, 0361, 0034, 0054, 0061, 0121, 0343, 0014, 0354, 0364, 0117, 0156, 0062, 
+  0024, 0244, 0312, 0163, 0200, 0137, 0126, 0177, 0040, 0020, 0245, 0230, 0304, 0345, 0263, 0026, 
+  0047, 0312, 0277, 0122, 0106, 0142, 0304, 0047, 0333, 0002, 0223, 0275, 0022, 0145, 0151, 0247, 
+  0360, 0104, 0012, 0211, 0133, 0374, 0251, 0114, 0034, 0262, 0073, 0260, 0253, 0343, 0100, 0311, 
+  0057, 0173, 0137, 0315, 0125, 0252, 0223, 0141, 0034, 0043, 0052, 0241, 0124, 0316, 0016, 0174, 
+  0345, 0365, 0022, 0107, 0220, 0364, 0021, 0024, 0031, 0214, 0024, 0366, 0200, 0357, 0315, 0152, 
+  0213, 0327, 0353, 0007, 0043, 0335, 0122, 0000, 0071, 0202, 0173, 0212, 0324, 0252, 0232, 0113, 
+  0311, 0150, 0125, 0341, 0241, 0112, 0327, 0311, 0021, 0270, 0141, 0271, 0014, 0204, 0334, 0150, 
+  0217, 0106, 0064, 0156, 0024, 0254, 0214, 0153, 0127, 0207, 0113, 0007, 0014, 0213, 0147, 0017, 
+  0074, 0226, 0252, 0353, 0106, 0210, 0010, 0160, 0044, 0207, 0124, 0020, 0050, 0241, 0302, 0327, 
+  0002, 0154, 0220, 0322, 0046, 0370, 0012, 0151, 0204, 0110, 0123, 0267, 0214, 0001, 0332, 0323, 
+  0210, 0246, 0242, 0034, 0105, 0010, 0337, 0042, 0021, 0304, 0150, 0011, 0163, 0042, 0315, 0153, 
+  0050, 0070, 0007, 0370, 0045, 0205, 0232, 0010, 0346, 0002, 0005, 0071, 0125, 0000, 0043, 0230, 
+  0016, 0120, 0032, 0222, 0065, 0334, 0210, 0100, 0244, 0154, 0035, 0154, 0373, 0320, 0136, 0305, 
+  0076, 0001, 0125, 0053, 0206, 0321, 0215, 0302, 0102, 0167, 0223, 0350, 0056, 0203, 0064, 0066, 
+  0357, 0252, 0142, 0062, 0142, 0056, 0225, 0061, 0201, 0113, 0140, 0117, 0333, 0224, 0252, 0355, 
+  0175, 0205, 0254, 0306, 0103, 0141, 0066, 0016, 0012, 0237, 0017, 0243, 0301, 0361, 0041, 0101, 
+  0213, 0016, 0006, 0101, 0012, 0107, 0040, 0310, 0056, 0006, 0147, 0157, 0030, 0174, 0012, 0014, 
+  0172, 0066, 0060, 0130, 0247, 0176, 0275, 0352, 0115, 0152, 0033, 0005, 0311, 0122, 0147, 0043, 
+  0221, 0116, 0322, 0251, 0121, 0366, 0100, 0321, 0103, 0242, 0351, 0312, 0205, 0006, 0223, 0200, 
+  0255, 0174, 0142, 0005, 0171, 0202, 0151, 0100, 0320, 0122, 0066, 0345, 0104, 0055, 0142, 0034, 
+  0047, 0351, 0020, 0071, 0225, 0351, 0233, 0110, 0365, 0316, 0366, 0006, 0144, 0174, 0046, 0001, 
+  0342, 0232, 0343, 0030, 0074, 0017, 0213, 0267, 0016, 0142, 0055, 0231, 0052, 0052, 0332, 0251, 
+  0172, 0141, 0324, 0052, 0043, 0371, 0212, 0366, 0025, 0256, 0065, 0125, 0275, 0271, 0376, 0052, 
+  0043, 0243, 0016, 0247, 0105, 0220, 0334, 0316, 0223, 0152, 0144, 0107, 0330, 0160, 0254, 0035, 
+  0353, 0243, 0032, 0301, 0211, 0162, 0065, 0041, 0041, 0227, 0246, 0302, 0055, 0371, 0300, 0337, 
+  0252, 0300, 0107, 0323, 0372, 0014, 0103, 0125, 0055, 0352, 0050, 0132, 0061, 0212, 0243, 0140, 
+  0215, 0343, 0004, 0111, 0075, 0157, 0220, 0174, 0123, 0014, 0107, 0147, 0125, 0060, 0322, 0223, 
+  0163, 0034, 0142, 0202, 0233, 0312, 0024, 0213, 0021, 0244, 0200, 0247, 0243, 0347, 0233, 0133, 
+  0033, 0270, 0113, 0306, 0225, 0035, 0024, 0342, 0221, 0124, 0104, 0276, 0153, 0022, 0114, 0032, 
+  0232, 0232, 0164, 0266, 0325, 0024, 0106, 0333, 0103, 0151, 0355, 0050, 0051, 0302, 0013, 0240, 
+  0224, 0060, 0112, 0133, 0363, 0314, 0172, 0151, 0305, 0137, 0175, 0205, 0033, 0202, 0144, 0143, 
+  0262, 0072, 0032, 0144, 0034, 0045, 0350, 0356, 0065, 0243, 0354, 0033, 0112, 0162, 0002, 0271, 
+  0163, 0171, 0227, 0161, 0355, 0116, 0214, 0036, 0021, 0346, 0212, 0321, 0171, 0146, 0320, 0225, 
+  0036, 0361, 0377, 0102, 0235, 0367, 0262, 0250, 0273, 0324, 0206, 0055, 0121, 0267, 0107, 0154, 
+  0317, 0013, 0272, 0041, 0342, 0151, 0337, 0151, 0304, 0110, 0067, 0044, 0050, 0166, 0303, 0315, 
+  0203, 0043, 0356, 0305, 0377, 0243, 0363, 0103, 0357, 0204, 0331, 0377, 0300, 0017, 0137, 0202, 
+  0375, 0117, 0317, 0021, 0217, 0224, 0021, 0275, 0243, 0142, 0104, 0173, 0153, 0026, 0306, 0223, 
+  0231, 0023, 0133, 0070, 0274, 0342, 0365, 0354, 0177, 0024, 0023, 0303, 0322, 0343, 0357, 0266, 
+  0311, 0326, 0324, 0104, 0124, 0244, 0060, 0126, 0323, 0112, 0015, 0047, 0340, 0123, 0106, 0221, 
+  0255, 0231, 0341, 0147, 0335, 0231, 0025, 0322, 0273, 0122, 0307, 0237, 0247, 0026, 0020, 0315, 
+  0140, 0034, 0167, 0254, 0042, 0164, 0033, 0242, 0357, 0212, 0220, 0065, 0123, 0330, 0060, 0107, 
+  0327, 0062, 0316, 0305, 0220, 0012, 0214, 0126, 0164, 0106, 0256, 0356, 0364, 0037, 0233, 0041, 
+  0343, 0143, 0145, 0214, 0154, 0215, 0223, 0125, 0123, 0367, 0263, 0127, 0275, 0315, 0276, 0301, 
+  0030, 0263, 0375, 0375, 0024, 0256, 0137, 0004, 0021, 0043, 0214, 0203, 0256, 0352, 0114, 0146, 
+  0173, 0177, 0340, 0044, 0045, 0172, 0025, 0262, 0257, 0106, 0326, 0306, 0313, 0102, 0122, 0144, 
+  0266, 0071, 0142, 0344, 0005, 0243, 0047, 0334, 0255, 0333, 0037, 0221, 0124, 0135, 0033, 0257, 
+  0143, 0314, 0341, 0072, 0300, 0064, 0126, 0036, 0051, 0265, 0137, 0230, 0325, 0327, 0226, 0204, 
+  0365, 0117, 0310, 0254, 0344, 0057, 0166, 0362, 0031, 0053, 0371, 0215, 0101, 0336, 0327, 0153, 
+  0066, 0142, 0203, 0015, 0212, 0165, 0363, 0202, 0006, 0364, 0101, 0221, 0301, 0054, 0040, 0020, 
+  0325, 0006, 0120, 0236, 0347, 0204, 0312, 0153, 0134, 0301, 0162, 0036, 0241, 0052, 0267, 0224, 
+  0137, 0356, 0005, 0167, 0256, 0072, 0071, 0016, 0122, 0030, 0355, 0110, 0075, 0267, 0153, 0172, 
+  0021, 0114, 0357, 0015, 0003, 0253, 0033, 0010, 0303, 0174, 0252, 0336, 0257, 0276, 0246, 0050, 
+  0252, 0354, 0332, 0107, 0372, 0205, 0062, 0266, 0232, 0337, 0161, 0226, 0323, 0030, 0364, 0251, 
+  0327, 0036, 0277, 0231, 0205, 0256, 0253, 0135, 0067, 0077, 0216, 0155, 0144, 0260, 0257, 0132, 
+  0016, 0142, 0117, 0024, 0310, 0254, 0006, 0063, 0373, 0201, 0310, 0044, 0030, 0231, 0005, 0244, 
+  0361, 0153, 0250, 0026, 0327, 0262, 0006, 0106, 0226, 0336, 0321, 0345, 0211, 0330, 0040, 0124, 
+  0235, 0074, 0001, 0066, 0370, 0262, 0353, 0346, 0033, 0033, 0274, 0261, 0301, 0021, 0260, 0201, 
+  0167, 0342, 0154, 0240, 0323, 0301, 0012, 0033, 0350, 0027, 0343, 0163, 0203, 0246, 0044, 0364, 
+  0040, 0365, 0030, 0236, 0211, 0236, 0076, 0246, 0255, 0324, 0232, 0204, 0020, 0370, 0352, 0367, 
+  0317, 0263, 0367, 0037, 0316, 0312, 0237, 0213, 0137, 0116, 0002, 0207, 0336, 0133, 0124, 0356, 
+  0302, 0341, 0350, 0250, 0334, 0216, 0303, 0275, 0352, 0337, 0160, 0150, 0013, 0207, 0336, 0305, 
+  0157, 0147, 0323, 0263, 0351, 0053, 0304, 0340, 0213, 0307, 0302, 0127, 0274, 0326, 0345, 0275, 
+  0304, 0132, 0127, 0037, 0173, 0367, 0263, 0265, 0025, 0073, 0217, 0267, 0361, 0350, 0265, 0304, 
+  0036, 0266, 0355, 0264, 0353, 0220, 0335, 0227, 0206, 0235, 0204, 0035, 0017, 0033, 0151, 0335, 
+  0266, 0217, 0020, 0017, 0266, 0245, 0355, 0355, 0236, 0061, 0325, 0214, 0234, 0137, 0131, 0231, 
+  0127, 0331, 0234, 0117, 0075, 0256, 0113, 0007, 0365, 0114, 0205, 0243, 0207, 0045, 0337, 0276, 
+  0356, 0373, 0152, 0000, 0355, 0075, 0027, 0240, 0333, 0155, 0332, 0042, 0334, 0054, 0330, 0161, 
+  0050, 0152, 0377, 0144, 0017, 0060, 0071, 0037, 0173, 0012, 0307, 0014, 0032, 0271, 0351, 0162, 
+  0271, 0124, 0072, 0165, 0037, 0142, 0125, 0331, 0012, 0307, 0141, 0056, 0221, 0150, 0034, 0261, 
+  0135, 0221, 0155, 0243, 0153, 0124, 0334, 0340, 0160, 0156, 0041, 0311, 0325, 0237, 0041, 0043, 
+  0161, 0313, 0261, 0250, 0326, 0372, 0215, 0007, 0365, 0204, 0317, 0027, 0235, 0356, 0245, 0050, 
+  0223, 0073, 0105, 0026, 0356, 0104, 0125, 0165, 0254, 0136, 0045, 0057, 0057, 0125, 0273, 0345, 
+  0371, 0350, 0235, 0113, 0125, 0137, 0073, 0034, 0211, 0214, 0121, 0241, 0172, 0343, 0136, 0000, 
+  0177, 0173, 0101, 0131, 0237, 0320, 0333, 0053, 0324, 0055, 0352, 0115, 0357, 0145, 0147, 0265, 
+  0262, 0217, 0136, 0212, 0352, 0275, 0375, 0371, 0144, 0357, 0077, 0057, 0374, 0000, 0330, 0165, 
+  0165, 0107, 0000, 0050, 0165, 0165, 0141, 0171, 0051, 0155, 0141, 0164, 0145, 0057, 0000, 0000, 
+  0003, 0000, 0000, 0000
+} };
+
+static GStaticResource static_resource = { logview_resource_data.data, sizeof (logview_resource_data.data) - 1 /* nul terminator */, NULL, NULL, NULL };
+
+G_MODULE_EXPORT
+GResource *logview_get_resource (void);
+GResource *logview_get_resource (void)
+{
+  return g_static_resource_get_resource (&static_resource);
+}
+/* GLIB - Library of useful routines for C programming
+ * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * Modified by the GLib Team and others 1997-2000.  See the AUTHORS
+ * file for a list of people on the GLib Team.  See the ChangeLog
+ * files for a list of changes.  These files are distributed with
+ * GLib at ftp://ftp.gtk.org/pub/gtk/.
+ */
+
+#ifndef __G_CONSTRUCTOR_H__
+#define __G_CONSTRUCTOR_H__
+
+/*
+  If G_HAS_CONSTRUCTORS is true then the compiler support *both* constructors and
+  destructors, in a usable way, including e.g. on library unload. If not you're on
+  your own.
+
+  Some compilers need #pragma to handle this, which does not work with macros,
+  so the way you need to use this is (for constructors):
+
+  #ifdef G_DEFINE_CONSTRUCTOR_NEEDS_PRAGMA
+  #pragma G_DEFINE_CONSTRUCTOR_PRAGMA_ARGS(my_constructor)
+  #endif
+  G_DEFINE_CONSTRUCTOR(my_constructor)
+  static void my_constructor(void) {
+   ...
+  }
+
+*/
+
+#ifndef __GTK_DOC_IGNORE__
+
+#if  __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7)
+
+#define G_HAS_CONSTRUCTORS 1
+
+#define G_DEFINE_CONSTRUCTOR(_func) static void __attribute__((constructor)) _func (void);
+#define G_DEFINE_DESTRUCTOR(_func) static void __attribute__((destructor)) _func (void);
+
+#elif defined (_MSC_VER) && (_MSC_VER >= 1500)
+/* Visual studio 2008 and later has _Pragma */
+
+/*
+ * Only try to include gslist.h if not already included via glib.h,
+ * so that items using gconstructor.h outside of GLib (such as
+ * GResources) continue to build properly.
+ */
+#ifndef __G_LIB_H__
+#include "gslist.h"
+#endif
+
+#include <stdlib.h>
+
+#define G_HAS_CONSTRUCTORS 1
+
+/* We do some weird things to avoid the constructors being optimized
+ * away on VS2015 if WholeProgramOptimization is enabled. First we
+ * make a reference to the array from the wrapper to make sure its
+ * references. Then we use a pragma to make sure the wrapper function
+ * symbol is always included at the link stage. Also, the symbols
+ * need to be extern (but not dllexport), even though they are not
+ * really used from another object file.
+ */
+
+/* We need to account for differences between the mangling of symbols
+ * for x86 and x64/ARM/ARM64 programs, as symbols on x86 are prefixed
+ * with an underscore but symbols on x64/ARM/ARM64 are not.
+ */
+#ifdef _M_IX86
+#define G_MSVC_SYMBOL_PREFIX "_"
+#else
+#define G_MSVC_SYMBOL_PREFIX ""
+#endif
+
+#define G_DEFINE_CONSTRUCTOR(_func) G_MSVC_CTOR (_func, G_MSVC_SYMBOL_PREFIX)
+#define G_DEFINE_DESTRUCTOR(_func) G_MSVC_DTOR (_func, G_MSVC_SYMBOL_PREFIX)
+
+#define G_MSVC_CTOR(_func,_sym_prefix) \
+  static void _func(void); \
+  extern int (* _array ## _func)(void);              \
+  int _func ## _wrapper(void) { _func(); g_slist_find (NULL,  _array ## _func); return 0; } \
+  __pragma(comment(linker,"/include:" _sym_prefix # _func "_wrapper")) \
+  __pragma(section(".CRT$XCU",read)) \
+  __declspec(allocate(".CRT$XCU")) int (* _array ## _func)(void) = _func ## _wrapper;
+
+#define G_MSVC_DTOR(_func,_sym_prefix) \
+  static void _func(void); \
+  extern int (* _array ## _func)(void);              \
+  int _func ## _constructor(void) { atexit (_func); g_slist_find (NULL,  _array ## _func); return 0; } \
+   __pragma(comment(linker,"/include:" _sym_prefix # _func "_constructor")) \
+  __pragma(section(".CRT$XCU",read)) \
+  __declspec(allocate(".CRT$XCU")) int (* _array ## _func)(void) = _func ## _constructor;
+
+#elif defined (_MSC_VER)
+
+#define G_HAS_CONSTRUCTORS 1
+
+/* Pre Visual studio 2008 must use #pragma section */
+#define G_DEFINE_CONSTRUCTOR_NEEDS_PRAGMA 1
+#define G_DEFINE_DESTRUCTOR_NEEDS_PRAGMA 1
+
+#define G_DEFINE_CONSTRUCTOR_PRAGMA_ARGS(_func) \
+  section(".CRT$XCU",read)
+#define G_DEFINE_CONSTRUCTOR(_func) \
+  static void _func(void); \
+  static int _func ## _wrapper(void) { _func(); return 0; } \
+  __declspec(allocate(".CRT$XCU")) static int (*p)(void) = _func ## _wrapper;
+
+#define G_DEFINE_DESTRUCTOR_PRAGMA_ARGS(_func) \
+  section(".CRT$XCU",read)
+#define G_DEFINE_DESTRUCTOR(_func) \
+  static void _func(void); \
+  static int _func ## _constructor(void) { atexit (_func); return 0; } \
+  __declspec(allocate(".CRT$XCU")) static int (* _array ## _func)(void) = _func ## _constructor;
+
+#elif defined(__SUNPRO_C)
+
+/* This is not tested, but i believe it should work, based on:
+ * http://opensource.apple.com/source/OpenSSL098/OpenSSL098-35/src/fips/fips_premain.c
+ */
+
+#define G_HAS_CONSTRUCTORS 1
+
+#define G_DEFINE_CONSTRUCTOR_NEEDS_PRAGMA 1
+#define G_DEFINE_DESTRUCTOR_NEEDS_PRAGMA 1
+
+#define G_DEFINE_CONSTRUCTOR_PRAGMA_ARGS(_func) \
+  init(_func)
+#define G_DEFINE_CONSTRUCTOR(_func) \
+  static void _func(void);
+
+#define G_DEFINE_DESTRUCTOR_PRAGMA_ARGS(_func) \
+  fini(_func)
+#define G_DEFINE_DESTRUCTOR(_func) \
+  static void _func(void);
+
+#else
+
+/* constructors not supported for this compiler */
+
+#endif
+
+#endif /* __GTK_DOC_IGNORE__ */
+#endif /* __G_CONSTRUCTOR_H__ */
+
+#ifdef G_HAS_CONSTRUCTORS
+
+#ifdef G_DEFINE_CONSTRUCTOR_NEEDS_PRAGMA
+#pragma G_DEFINE_CONSTRUCTOR_PRAGMA_ARGS(logviewresource_constructor)
+#endif
+G_DEFINE_CONSTRUCTOR(logviewresource_constructor)
+#ifdef G_DEFINE_DESTRUCTOR_NEEDS_PRAGMA
+#pragma G_DEFINE_DESTRUCTOR_PRAGMA_ARGS(logviewresource_destructor)
+#endif
+G_DEFINE_DESTRUCTOR(logviewresource_destructor)
+
+#else
+#warning "Constructor not supported on this compiler, linking in resources will not work"
+#endif
+
+static void logviewresource_constructor (void)
+{
+  g_static_resource_init (&static_resource);
+}
+
+static void logviewresource_destructor (void)
+{
+  g_static_resource_fini (&static_resource);
+}
+
+ +
+ +
+ + diff --git a/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/25.html b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/25.html new file mode 100644 index 00000000..214e92cf --- /dev/null +++ b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/25.html @@ -0,0 +1,3533 @@ + + + + + + Cppcheck - HTML report - mate-utils + + + + + +
+ + + +
+
   1
+   2
+   3
+   4
+   5
+   6
+   7
+   8
+   9
+  10
+  11
+  12
+  13
+  14
+  15
+  16
+  17
+  18
+  19
+  20
+  21
+  22
+  23
+  24
+  25
+  26
+  27
+  28
+  29
+  30
+  31
+  32
+  33
+  34
+  35
+  36
+  37
+  38
+  39
+  40
+  41
+  42
+  43
+  44
+  45
+  46
+  47
+  48
+  49
+  50
+  51
+  52
+  53
+  54
+  55
+  56
+  57
+  58
+  59
+  60
+  61
+  62
+  63
+  64
+  65
+  66
+  67
+  68
+  69
+  70
+  71
+  72
+  73
+  74
+  75
+  76
+  77
+  78
+  79
+  80
+  81
+  82
+  83
+  84
+  85
+  86
+  87
+  88
+  89
+  90
+  91
+  92
+  93
+  94
+  95
+  96
+  97
+  98
+  99
+ 100
+ 101
+ 102
+ 103
+ 104
+ 105
+ 106
+ 107
+ 108
+ 109
+ 110
+ 111
+ 112
+ 113
+ 114
+ 115
+ 116
+ 117
+ 118
+ 119
+ 120
+ 121
+ 122
+ 123
+ 124
+ 125
+ 126
+ 127
+ 128
+ 129
+ 130
+ 131
+ 132
+ 133
+ 134
+ 135
+ 136
+ 137
+ 138
+ 139
+ 140
+ 141
+ 142
+ 143
+ 144
+ 145
+ 146
+ 147
+ 148
+ 149
+ 150
+ 151
+ 152
+ 153
+ 154
+ 155
+ 156
+ 157
+ 158
+ 159
+ 160
+ 161
+ 162
+ 163
+ 164
+ 165
+ 166
+ 167
+ 168
+ 169
+ 170
+ 171
+ 172
+ 173
+ 174
+ 175
+ 176
+ 177
+ 178
+ 179
+ 180
+ 181
+ 182
+ 183
+ 184
+ 185
+ 186
+ 187
+ 188
+ 189
+ 190
+ 191
+ 192
+ 193
+ 194
+ 195
+ 196
+ 197
+ 198
+ 199
+ 200
+ 201
+ 202
+ 203
+ 204
+ 205
+ 206
+ 207
+ 208
+ 209
+ 210
+ 211
+ 212
+ 213
+ 214
+ 215
+ 216
+ 217
+ 218
+ 219
+ 220
+ 221
+ 222
+ 223
+ 224
+ 225
+ 226
+ 227
+ 228
+ 229
+ 230
+ 231
+ 232
+ 233
+ 234
+ 235
+ 236
+ 237
+ 238
+ 239
+ 240
+ 241
+ 242
+ 243
+ 244
+ 245
+ 246
+ 247
+ 248
+ 249
+ 250
+ 251
+ 252
+ 253
+ 254
+ 255
+ 256
+ 257
+ 258
+ 259
+ 260
+ 261
+ 262
+ 263
+ 264
+ 265
+ 266
+ 267
+ 268
+ 269
+ 270
+ 271
+ 272
+ 273
+ 274
+ 275
+ 276
+ 277
+ 278
+ 279
+ 280
+ 281
+ 282
+ 283
+ 284
+ 285
+ 286
+ 287
+ 288
+ 289
+ 290
+ 291
+ 292
+ 293
+ 294
+ 295
+ 296
+ 297
+ 298
+ 299
+ 300
+ 301
+ 302
+ 303
+ 304
+ 305
+ 306
+ 307
+ 308
+ 309
+ 310
+ 311
+ 312
+ 313
+ 314
+ 315
+ 316
+ 317
+ 318
+ 319
+ 320
+ 321
+ 322
+ 323
+ 324
+ 325
+ 326
+ 327
+ 328
+ 329
+ 330
+ 331
+ 332
+ 333
+ 334
+ 335
+ 336
+ 337
+ 338
+ 339
+ 340
+ 341
+ 342
+ 343
+ 344
+ 345
+ 346
+ 347
+ 348
+ 349
+ 350
+ 351
+ 352
+ 353
+ 354
+ 355
+ 356
+ 357
+ 358
+ 359
+ 360
+ 361
+ 362
+ 363
+ 364
+ 365
+ 366
+ 367
+ 368
+ 369
+ 370
+ 371
+ 372
+ 373
+ 374
+ 375
+ 376
+ 377
+ 378
+ 379
+ 380
+ 381
+ 382
+ 383
+ 384
+ 385
+ 386
+ 387
+ 388
+ 389
+ 390
+ 391
+ 392
+ 393
+ 394
+ 395
+ 396
+ 397
+ 398
+ 399
+ 400
+ 401
+ 402
+ 403
+ 404
+ 405
+ 406
+ 407
+ 408
+ 409
+ 410
+ 411
+ 412
+ 413
+ 414
+ 415
+ 416
+ 417
+ 418
+ 419
+ 420
+ 421
+ 422
+ 423
+ 424
+ 425
+ 426
+ 427
+ 428
+ 429
+ 430
+ 431
+ 432
+ 433
+ 434
+ 435
+ 436
+ 437
+ 438
+ 439
+ 440
+ 441
+ 442
+ 443
+ 444
+ 445
+ 446
+ 447
+ 448
+ 449
+ 450
+ 451
+ 452
+ 453
+ 454
+ 455
+ 456
+ 457
+ 458
+ 459
+ 460
+ 461
+ 462
+ 463
+ 464
+ 465
+ 466
+ 467
+ 468
+ 469
+ 470
+ 471
+ 472
+ 473
+ 474
+ 475
+ 476
+ 477
+ 478
+ 479
+ 480
+ 481
+ 482
+ 483
+ 484
+ 485
+ 486
+ 487
+ 488
+ 489
+ 490
+ 491
+ 492
+ 493
+ 494
+ 495
+ 496
+ 497
+ 498
+ 499
+ 500
+ 501
+ 502
+ 503
+ 504
+ 505
+ 506
+ 507
+ 508
+ 509
+ 510
+ 511
+ 512
+ 513
+ 514
+ 515
+ 516
+ 517
+ 518
+ 519
+ 520
+ 521
+ 522
+ 523
+ 524
+ 525
+ 526
+ 527
+ 528
+ 529
+ 530
+ 531
+ 532
+ 533
+ 534
+ 535
+ 536
+ 537
+ 538
+ 539
+ 540
+ 541
+ 542
+ 543
+ 544
+ 545
+ 546
+ 547
+ 548
+ 549
+ 550
+ 551
+ 552
+ 553
+ 554
+ 555
+ 556
+ 557
+ 558
+ 559
+ 560
+ 561
+ 562
+ 563
+ 564
+ 565
+ 566
+ 567
+ 568
+ 569
+ 570
+ 571
+ 572
+ 573
+ 574
+ 575
+ 576
+ 577
+ 578
+ 579
+ 580
+ 581
+ 582
+ 583
+ 584
+ 585
+ 586
+ 587
+ 588
+ 589
+ 590
+ 591
+ 592
+ 593
+ 594
+ 595
+ 596
+ 597
+ 598
+ 599
+ 600
+ 601
+ 602
+ 603
+ 604
+ 605
+ 606
+ 607
+ 608
+ 609
+ 610
+ 611
+ 612
+ 613
+ 614
+ 615
+ 616
+ 617
+ 618
+ 619
+ 620
+ 621
+ 622
+ 623
+ 624
+ 625
+ 626
+ 627
+ 628
+ 629
+ 630
+ 631
+ 632
+ 633
+ 634
+ 635
+ 636
+ 637
+ 638
+ 639
+ 640
+ 641
+ 642
+ 643
+ 644
+ 645
+ 646
+ 647
+ 648
+ 649
+ 650
+ 651
+ 652
+ 653
+ 654
+ 655
+ 656
+ 657
+ 658
+ 659
+ 660
+ 661
+ 662
+ 663
+ 664
+ 665
+ 666
+ 667
+ 668
+ 669
+ 670
+ 671
+ 672
+ 673
+ 674
+ 675
+ 676
+ 677
+ 678
+ 679
+ 680
+ 681
+ 682
+ 683
+ 684
+ 685
+ 686
+ 687
+ 688
+ 689
+ 690
+ 691
+ 692
+ 693
+ 694
+ 695
+ 696
+ 697
+ 698
+ 699
+ 700
+ 701
+ 702
+ 703
+ 704
+ 705
+ 706
+ 707
+ 708
+ 709
+ 710
+ 711
+ 712
+ 713
+ 714
+ 715
+ 716
+ 717
+ 718
+ 719
+ 720
+ 721
+ 722
+ 723
+ 724
+ 725
+ 726
+ 727
+ 728
+ 729
+ 730
+ 731
+ 732
+ 733
+ 734
+ 735
+ 736
+ 737
+ 738
+ 739
+ 740
+ 741
+ 742
+ 743
+ 744
+ 745
+ 746
+ 747
+ 748
+ 749
+ 750
+ 751
+ 752
+ 753
+ 754
+ 755
+ 756
+ 757
+ 758
+ 759
+ 760
+ 761
+ 762
+ 763
+ 764
+ 765
+ 766
+ 767
+ 768
+ 769
+ 770
+ 771
+ 772
+ 773
+ 774
+ 775
+ 776
+ 777
+ 778
+ 779
+ 780
+ 781
+ 782
+ 783
+ 784
+ 785
+ 786
+ 787
+ 788
+ 789
+ 790
+ 791
+ 792
+ 793
+ 794
+ 795
+ 796
+ 797
+ 798
+ 799
+ 800
+ 801
+ 802
+ 803
+ 804
+ 805
+ 806
+ 807
+ 808
+ 809
+ 810
+ 811
+ 812
+ 813
+ 814
+ 815
+ 816
+ 817
+ 818
+ 819
+ 820
+ 821
+ 822
+ 823
+ 824
+ 825
+ 826
+ 827
+ 828
+ 829
+ 830
+ 831
+ 832
+ 833
+ 834
+ 835
+ 836
+ 837
+ 838
+ 839
+ 840
+ 841
+ 842
+ 843
+ 844
+ 845
+ 846
+ 847
+ 848
+ 849
+ 850
+ 851
+ 852
+ 853
+ 854
+ 855
+ 856
+ 857
+ 858
+ 859
+ 860
+ 861
+ 862
+ 863
+ 864
+ 865
+ 866
+ 867
+ 868
+ 869
+ 870
+ 871
+ 872
+ 873
+ 874
+ 875
+ 876
+ 877
+ 878
+ 879
+ 880
+ 881
+ 882
+ 883
+ 884
+ 885
+ 886
+ 887
+ 888
+ 889
+ 890
+ 891
+ 892
+ 893
+ 894
+ 895
+ 896
+ 897
+ 898
+ 899
+ 900
+ 901
+ 902
+ 903
+ 904
+ 905
+ 906
+ 907
+ 908
+ 909
+ 910
+ 911
+ 912
+ 913
+ 914
+ 915
+ 916
+ 917
+ 918
+ 919
+ 920
+ 921
+ 922
+ 923
+ 924
+ 925
+ 926
+ 927
+ 928
+ 929
+ 930
+ 931
+ 932
+ 933
+ 934
+ 935
+ 936
+ 937
+ 938
+ 939
+ 940
+ 941
+ 942
+ 943
+ 944
+ 945
+ 946
+ 947
+ 948
+ 949
+ 950
+ 951
+ 952
+ 953
+ 954
+ 955
+ 956
+ 957
+ 958
+ 959
+ 960
+ 961
+ 962
+ 963
+ 964
+ 965
+ 966
+ 967
+ 968
+ 969
+ 970
+ 971
+ 972
+ 973
+ 974
+ 975
+ 976
+ 977
+ 978
+ 979
+ 980
+ 981
+ 982
+ 983
+ 984
+ 985
+ 986
+ 987
+ 988
+ 989
+ 990
+ 991
+ 992
+ 993
+ 994
+ 995
+ 996
+ 997
+ 998
+ 999
+1000
+1001
+1002
+1003
+1004
+1005
+1006
+1007
+1008
+1009
+1010
+1011
+1012
+1013
+1014
+1015
+1016
+1017
+1018
+1019
+1020
+1021
+1022
+1023
+1024
+1025
+1026
+1027
+1028
+1029
+1030
+1031
+1032
+1033
+1034
+1035
+1036
+1037
+1038
+1039
+1040
+1041
+1042
+1043
+1044
+1045
+1046
+1047
+1048
+1049
+1050
+1051
+1052
+1053
+1054
+1055
+1056
+1057
+1058
+1059
+1060
+1061
+1062
+1063
+1064
+1065
+1066
+1067
+1068
+1069
+1070
+1071
+1072
+1073
+1074
+1075
+1076
+1077
+1078
+1079
+1080
+1081
+1082
+1083
+1084
+1085
+1086
+1087
+1088
+1089
+1090
+1091
+1092
+1093
+1094
+1095
+1096
+1097
+1098
+1099
+1100
+1101
+1102
+1103
+1104
+1105
+1106
+1107
+1108
+1109
+1110
+1111
+1112
+1113
+1114
+1115
+1116
+1117
+1118
+1119
+1120
+1121
+1122
+1123
+1124
+1125
+1126
+1127
+1128
+1129
+1130
+1131
+1132
+1133
+1134
+1135
+1136
+1137
+1138
+1139
+1140
+1141
+1142
+1143
+1144
+1145
+1146
+1147
+1148
+1149
+1150
+1151
+1152
+1153
+1154
+1155
+1156
+1157
+1158
+1159
+1160
+1161
+1162
+1163
+1164
+1165
+1166
+1167
+1168
+1169
+1170
+1171
+1172
+1173
+1174
+1175
+1176
+1177
+1178
+1179
+1180
+1181
+1182
+1183
+1184
+1185
+1186
+1187
+1188
+1189
+1190
+1191
+1192
+1193
+1194
+1195
+1196
+1197
+1198
+1199
+1200
+1201
+1202
+1203
+1204
+1205
+1206
+1207
+1208
+1209
+1210
+1211
+1212
+1213
+1214
+1215
+1216
+1217
+1218
+1219
+1220
+1221
+1222
+1223
+1224
+1225
+1226
+1227
+1228
+1229
+1230
+1231
+1232
+1233
+1234
+1235
+1236
+1237
+1238
+1239
+1240
+1241
+1242
+1243
+1244
+1245
+1246
+1247
+1248
+1249
+1250
+1251
+1252
+1253
+1254
+1255
+1256
+1257
+1258
+1259
+1260
+1261
+1262
+1263
+1264
+1265
+1266
+1267
+1268
+1269
+1270
+1271
+1272
+1273
+1274
+1275
+1276
+1277
+1278
+1279
+1280
+1281
+1282
+1283
+1284
+1285
+1286
+1287
+1288
+1289
+1290
+1291
+1292
+1293
+1294
+1295
+1296
+1297
+1298
+1299
+1300
+1301
+1302
+1303
+1304
+1305
+1306
+1307
+1308
+1309
+1310
+1311
+1312
+1313
+1314
+1315
+1316
+1317
+1318
+1319
+1320
+1321
+1322
+1323
+1324
+1325
+1326
+1327
+1328
+1329
+1330
+1331
+1332
+1333
+1334
+1335
+1336
+1337
+1338
+1339
+1340
+1341
+1342
+1343
+1344
+1345
+1346
+1347
+1348
+1349
+1350
+1351
+1352
+1353
+1354
+1355
+1356
+1357
+1358
+1359
+1360
+1361
+1362
+1363
+1364
+1365
+1366
+1367
+1368
+1369
+1370
+1371
+1372
+1373
+1374
+1375
+1376
+1377
+1378
+1379
+1380
+1381
+1382
+1383
+1384
+1385
+1386
+1387
+1388
+1389
+1390
+1391
+1392
+1393
+1394
+1395
+1396
+1397
+1398
+1399
+1400
+1401
+1402
+1403
+1404
+1405
+1406
+1407
+1408
+1409
+1410
+1411
+1412
+1413
+1414
+1415
+1416
+1417
+1418
+1419
+1420
+1421
+1422
+1423
+1424
+1425
+1426
+1427
+1428
+1429
+1430
+1431
+1432
+1433
+1434
+1435
+1436
+1437
+1438
+1439
+1440
+1441
+1442
+1443
+1444
+1445
+1446
+1447
+1448
+1449
+1450
+1451
+1452
+1453
+1454
+1455
+1456
+1457
+1458
+1459
+1460
+1461
+1462
+1463
+1464
+1465
+1466
+1467
+1468
+1469
+1470
+1471
+1472
+1473
+1474
+1475
+1476
+1477
+1478
+1479
+1480
+1481
+1482
+1483
+1484
+1485
+1486
+1487
+1488
+1489
+1490
+1491
+1492
+1493
+1494
+1495
+1496
+1497
+1498
+1499
+1500
+1501
+1502
+1503
+1504
+1505
+1506
+1507
+1508
+1509
+1510
+1511
+1512
+1513
+1514
+1515
+1516
+1517
+1518
+1519
+1520
+1521
+1522
+1523
+1524
+1525
+1526
+1527
+1528
+1529
+1530
+1531
+1532
+1533
+1534
+1535
+1536
+1537
+1538
+1539
+1540
+1541
+1542
+1543
+1544
+1545
+1546
+1547
+1548
+1549
+1550
+1551
+1552
+1553
+1554
+1555
+1556
+1557
+1558
+1559
+1560
+1561
+1562
+1563
+1564
+1565
+1566
+1567
+1568
+1569
+1570
+1571
+1572
+1573
+1574
+1575
+1576
+1577
+1578
+1579
+1580
+1581
+1582
+1583
+1584
+1585
+1586
+1587
+1588
/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2; -*- */
+/* Copyright (C) 1998 Cesar Miquel <miquel@df.uba.ar>
+ * Copyright (C) 2008 Cosimo Cecchi <cosimoc@gnome.org>
+ * Copyright (C) 2012-2021 MATE Developers
+ *
+ * This file is part of MATE Utils.
+ *
+ * MATE Utils is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * MATE Utils is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MATE Utils.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <gtk/gtk.h>
+#include <gdk/gdkkeysyms.h>
+#include <glib/gi18n.h>
+
+#include "logview-window.h"
+
+#include "logview-loglist.h"
+#include "logview-findbar.h"
+#include "logview-about.h"
+#include "logview-prefs.h"
+#include "logview-manager.h"
+#include "logview-filter-manager.h"
+
+#define APP_NAME _("System Log Viewer")
+#define SEARCH_START_MARK "lw-search-start-mark"
+#define SEARCH_END_MARK "lw-search-end-mark"
+
+struct _LogviewWindowPrivate {
+  GtkBuilder     *ui_manager;
+  GActionGroup   *action_group;
+  GActionGroup   *filter_action_group;
+
+  GtkWidget *find_bar;
+  GtkWidget *loglist;
+  GtkWidget *sidebar;
+  GtkWidget *version_bar;
+  GtkWidget *version_selector;
+  GtkWidget *hpaned;
+  GtkWidget *text_view;
+  GtkWidget *statusbar;
+
+  GtkWidget *message_area;
+  GtkWidget *message_primary;
+  GtkWidget *message_secondary;
+
+  GtkTextTagTable *tag_table;
+
+  int original_fontsize, fontsize;
+
+  LogviewPrefs *prefs;
+  LogviewManager *manager;
+
+  gulong monitor_id;
+  guint search_timeout_id;
+
+  GCancellable *read_cancellable;
+
+  GList *active_filters;
+  gboolean matches_only;
+};
+
+G_DEFINE_TYPE_WITH_PRIVATE (LogviewWindow, logview_window, GTK_TYPE_WINDOW);
+
+static void findbar_close_cb  (LogviewFindbar *findbar,
+                               gpointer user_data);
+static void read_new_lines_cb (LogviewLog *log,
+                               const char **lines,
+                               GSList *new_days,
+                               GError *error,
+                               gpointer user_data);
+
+/* private functions */
+
+static void
+logview_version_selector_changed (GtkComboBox *version_selector, gpointer user_data)
+{
+
+}
+#if 0
+	LogviewWindow *logview = user_data;
+	Log *log = logview->curlog;
+	int selected;
+
+    g_assert (LOGVIEW_IS_WINDOW (logview));
+
+	selected = gtk_combo_box_get_active (version_selector);
+
+	if (selected == log->current_version)
+		return;
+
+	/* select a new version */
+	if (selected == 0) {
+		logview_select_log (logview, log->parent_log);
+	} else {
+		Log *new;
+		if (log->parent_log) {
+			new = log->parent_log->older_logs[selected];
+		} else {
+			new = log->older_logs[selected];
+		}
+
+		logview_select_log (logview, new);
+	}
+}
+
+#endif
+
+/* private helpers */
+
+static void
+populate_tag_table (GtkTextTagTable *tag_table)
+{
+  GtkTextTag *tag;
+
+  tag = gtk_text_tag_new ("bold");
+  g_object_set (tag, "weight", PANGO_WEIGHT_BOLD,
+                "weight-set", TRUE, NULL);
+
+  gtk_text_tag_table_add (tag_table, tag);
+
+  tag = gtk_text_tag_new ("invisible");
+  g_object_set (tag, "invisible", TRUE, "invisible-set", TRUE, NULL);
+  gtk_text_tag_table_add (tag_table, tag);
+
+  tag = gtk_text_tag_new ("invisible-filter");
+  g_object_set (tag, "invisible", TRUE, "invisible-set", TRUE, NULL);
+  gtk_text_tag_table_add (tag_table, tag);
+}
+
+static void
+populate_style_tag_table (LogviewWindow *logview)
+{
+  GtkTextTagTable *tag_table = logview->priv->tag_table;
+  GtkTextTag *tag;
+  GtkStyleContext *context;
+  GdkRGBA rgba;
+
+  tag = gtk_text_tag_table_lookup (tag_table, "gray");
+
+  if (tag) {
+    gtk_text_tag_table_remove (tag_table, tag);
+  }
+
+  tag = gtk_text_tag_new ("gray");
+
+  context = gtk_widget_get_style_context (logview->priv->text_view);
+  gtk_style_context_save (context);
+  gtk_style_context_add_class (context, "dim-label");
+  gtk_style_context_get_color (context, GTK_STATE_FLAG_NORMAL, &rgba);
+  gtk_style_context_restore (context);
+
+  g_object_set (tag, "foreground-rgba", &rgba, "foreground-set", TRUE, NULL);
+
+  gtk_text_tag_table_add (tag_table, tag);
+}
+
+static void
+_gtk_text_buffer_apply_tag_to_rectangle (GtkTextBuffer *buffer, int line_start, int line_end,
+                                        int offset_start, int offset_end, char *tag_name)
+{
+  GtkTextIter start, end;
+  int line_cur;
+
+  gtk_text_buffer_get_iter_at_line (buffer, &start, line_start);
+  gtk_text_buffer_get_iter_at_line (buffer, &end, line_start);
+
+  for (line_cur = line_start; line_cur < line_end + 1; line_cur++) {
+
+    if (offset_start > 0) {
+      gtk_text_iter_forward_chars (&start, offset_start);
+    }
+
+    gtk_text_iter_forward_chars (&end, offset_end);
+
+    gtk_text_buffer_apply_tag_by_name (buffer, tag_name, &start, &end);
+
+    gtk_text_iter_forward_line (&start);
+    gtk_text_iter_forward_line (&end);
+  }
+}
+
+static void
+activate_toggle (GSimpleAction *action,
+                 GVariant      *parameter,
+                 gpointer       user_data)
+{
+  GVariant *state;
+
+  state = g_action_get_state (G_ACTION (action));
+  g_action_change_state (G_ACTION (action), g_variant_new_boolean (!g_variant_get_boolean (state)));
+  g_variant_unref (state);
+}
+
+static void
+logview_update_statusbar (LogviewWindow *logview, LogviewLog *active)
+{
+  GDateTime *date_time;
+  char *statusbar_text;
+  char *size, *modified, *timestring;
+  time_t timestamp;
+
+  if (active == NULL) {
+    gtk_statusbar_pop (GTK_STATUSBAR (logview->priv->statusbar), 0);
+    return;
+  }
+
+  timestamp = logview_log_get_timestamp (active);
+  date_time = g_date_time_new_from_unix_local (timestamp);
+  timestring = g_date_time_format (date_time, "%c");
+  modified = g_strdup_printf (_("last update: %s"), timestring);
+
+  size = g_format_size (logview_log_get_file_size (active));
+
+  statusbar_text = g_strdup_printf (_("%d lines (%s) - %s"),
+                                    logview_log_get_cached_lines_number (active),
+                                    size, modified);
+
+  gtk_statusbar_pop (GTK_STATUSBAR (logview->priv->statusbar), 0);
+  gtk_statusbar_push (GTK_STATUSBAR (logview->priv->statusbar), 0, statusbar_text);
+
+  g_free (size);
+  g_free (timestring);
+  g_free (modified);
+  g_free (statusbar_text);
+  g_date_time_unref (date_time);
+}
+
+#define DEFAULT_LOGVIEW_FONT "Monospace 10"
+
+static void
+logview_set_font (LogviewWindow *logview,
+                  const char    *fontname)
+{
+  PangoFontDescription *font_desc;
+
+  if (fontname == NULL)
+    fontname = DEFAULT_LOGVIEW_FONT;
+
+  font_desc = pango_font_description_from_string (fontname);
+  if (font_desc) {
+    gtk_widget_override_font (logview->priv->text_view, font_desc);
+    pango_font_description_free (font_desc);
+  }
+}
+
+static void
+logview_set_fontsize (LogviewWindow *logview, gboolean store)
+{
+  PangoFontDescription *fontdesc;
+  PangoContext *context;
+  LogviewWindowPrivate *priv = logview->priv;
+
+  context = gtk_widget_get_pango_context (priv->text_view);
+  fontdesc = pango_context_get_font_description (context);
+  pango_font_description_set_size (fontdesc, (priv->fontsize) * PANGO_SCALE);
+  gtk_widget_override_font (priv->text_view, fontdesc);
+
+  if (store) {
+    logview_prefs_store_fontsize (logview->priv->prefs, priv->fontsize);
+  }
+}
+
+static void
+logview_set_window_title (LogviewWindow *logview, const char * log_name)
+{
+  char *window_title;
+
+  if (log_name) {
+    window_title = g_strdup_printf ("%s - %s", log_name, APP_NAME);
+  } else {
+    window_title = g_strdup_printf (APP_NAME);
+  }
+
+  gtk_window_set_title (GTK_WINDOW (logview), window_title);
+
+  g_free (window_title);
+}
+
+/* actions callbacks */
+
+static void
+open_file_selected_cb (GtkWidget *chooser, gint response, LogviewWindow *logview)
+{
+  GFile *f;
+  char *file_uri;
+  LogviewLog *log;
+
+  gtk_widget_hide (GTK_WIDGET (chooser));
+  if (response != GTK_RESPONSE_OK) {
+	  return;
+  }
+
+  f = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (chooser));
+  file_uri = g_file_get_uri (f);
+
+  log = logview_manager_get_if_loaded (logview->priv->manager, file_uri);
+
+  g_free (file_uri);
+
+  if (log) {
+    logview_manager_set_active_log (logview->priv->manager, log);
+    g_object_unref (log);
+    goto out;
+  }
+
+  logview_manager_add_log_from_gfile (logview->priv->manager, f, TRUE);
+
+out:
+  g_object_unref (f);
+}
+
+static void
+logview_open_log (GSimpleAction *action,
+                  GVariant      *parameter,
+                  gpointer       user_data)
+
+{
+  LogviewWindow    *logview = user_data;
+  static GtkWidget *chooser = NULL;
+  char *active;
+
+  if (chooser == NULL) {
+    chooser = gtk_file_chooser_dialog_new (_("Open Log"),
+                                           GTK_WINDOW (logview),
+                                           GTK_FILE_CHOOSER_ACTION_OPEN,
+                                           "gtk-cancel", GTK_RESPONSE_CANCEL,
+                                           "gtk-open", GTK_RESPONSE_OK,
+                                           NULL);
+    gtk_dialog_set_default_response (GTK_DIALOG (chooser), GTK_RESPONSE_OK);
+    gtk_window_set_modal (GTK_WINDOW (chooser), TRUE);
+    g_signal_connect (chooser, "response",
+                      G_CALLBACK (open_file_selected_cb), logview);
+    g_signal_connect (chooser, "destroy",
+                      G_CALLBACK (gtk_widget_destroyed), &chooser);
+    active = logview_prefs_get_active_logfile (logview->priv->prefs);
+    if (active != NULL) {
+      gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (chooser), active);
+      g_free (active);
+    }
+  }
+
+  gtk_window_present (GTK_WINDOW (chooser));
+}
+
+static void
+logview_close_log (GSimpleAction *action,
+                   GVariant      *parameter,
+                   gpointer       user_data)
+{
+  LogviewWindow *logview = user_data;
+
+  findbar_close_cb (LOGVIEW_FINDBAR (logview->priv->find_bar), logview);
+  logview_manager_close_active_log (logview->priv->manager);
+}
+
+static void
+logview_help (GSimpleAction *action,
+              GVariant      *parameter,
+              gpointer       user_data)
+{
+  GError *error = NULL;
+
+  gtk_show_uri_on_window (GTK_WINDOW (user_data),
+                "help:mate-system-log", gtk_get_current_event_time (),
+                &error);
+
+  if (error) {
+    g_warning (_("There was an error displaying help: %s"), error->message);
+    g_error_free (error);
+  }
+}
+
+static void
+logview_bigger_text (GSimpleAction *action,
+                     GVariant      *parameter,
+                     gpointer       user_data)
+{
+  LogviewWindow *logview = user_data;
+
+  logview->priv->fontsize = MIN (logview->priv->fontsize + 1, 24);
+  logview_set_fontsize (logview, TRUE);
+}
+
+static void
+logview_smaller_text (GSimpleAction *action,
+                      GVariant      *parameter,
+                      gpointer       user_data)
+{
+  LogviewWindow *logview = user_data;
+
+  logview->priv->fontsize = MAX (logview->priv->fontsize-1, 6);
+  logview_set_fontsize (logview, TRUE);
+}
+
+static void
+logview_normal_text (GSimpleAction *action,
+                     GVariant      *parameter,
+                     gpointer       user_data)
+{
+  LogviewWindow *logview = user_data;
+
+  logview->priv->fontsize = logview->priv->original_fontsize;
+  logview_set_fontsize (logview, TRUE);
+}
+
+static void
+logview_select_all (GSimpleAction *action,
+                    GVariant      *parameter,
+                    gpointer       user_data)
+{
+  LogviewWindow *logview = user_data;
+  GtkTextIter start, end;
+  GtkTextBuffer *buffer;
+
+  buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (logview->priv->text_view));
+
+  gtk_text_buffer_get_bounds (buffer, &start, &end);
+  gtk_text_buffer_select_range (buffer, &start, &end);
+
+  gtk_widget_grab_focus (GTK_WIDGET (logview->priv->text_view));
+}
+
+static void
+logview_copy (GSimpleAction *action,
+              GVariant      *parameter,
+              gpointer       user_data)
+{
+  LogviewWindow *logview = user_data;
+  GtkTextBuffer *buffer;
+  GtkClipboard *clipboard;
+
+  buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (logview->priv->text_view));
+  clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
+
+  gtk_text_buffer_copy_clipboard (buffer, clipboard);
+
+  gtk_widget_grab_focus (GTK_WIDGET (logview->priv->text_view));
+}
+
+static void
+findbar_close_cb (LogviewFindbar *findbar,
+                  gpointer user_data)
+{
+  gtk_widget_hide (GTK_WIDGET (findbar));
+  logview_findbar_set_message (findbar, NULL);
+}
+
+static void
+logview_search_text (LogviewWindow *logview, gboolean forward)
+{
+  GtkTextBuffer *buffer;
+  GtkTextMark *search_start, *search_end;
+  GtkTextIter search, start_m, end_m;
+  const char *text;
+  gboolean res, wrapped;
+
+  wrapped = FALSE;
+
+  text = logview_findbar_get_text (LOGVIEW_FINDBAR (logview->priv->find_bar));
+
+  if (!text || g_strcmp0 (text, "") == 0) {
+    return;
+  }
+
+  buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (logview->priv->text_view));
+  search_start = gtk_text_buffer_get_mark (buffer, SEARCH_START_MARK);
+  search_end = gtk_text_buffer_get_mark (buffer, SEARCH_END_MARK);
+
+  if (!search_start) {
+    /* this is our first search on the buffer, create a new search mark */
+    gtk_text_buffer_get_start_iter (buffer, &search);
+    search_start = gtk_text_buffer_create_mark (buffer, SEARCH_START_MARK,
+                                                &search, TRUE);
+    search_end = gtk_text_buffer_create_mark (buffer, SEARCH_END_MARK,
+                                              &search, TRUE);
+  } else {
+    if (forward) {
+      gtk_text_buffer_get_iter_at_mark (buffer, &search, search_end);
+    } else {
+      gtk_text_buffer_get_iter_at_mark (buffer, &search, search_start);
+    }
+  }
+
+wrap:
+
+  if (forward) {
+    res = gtk_text_iter_forward_search (&search, text, GTK_TEXT_SEARCH_VISIBLE_ONLY, &start_m, &end_m, NULL);
+  } else {
+    res = gtk_text_iter_backward_search (&search, text, GTK_TEXT_SEARCH_VISIBLE_ONLY, &start_m, &end_m, NULL);
+  }
+
+  if (res) {
+    gtk_text_buffer_select_range (buffer, &start_m, &end_m);
+    gtk_text_buffer_move_mark (buffer, search_start, &start_m);
+    gtk_text_buffer_move_mark (buffer, search_end, &end_m);
+
+    gtk_text_view_scroll_mark_onscreen (GTK_TEXT_VIEW (logview->priv->text_view), search_end);
+
+    if (wrapped) {
+      logview_findbar_set_message (LOGVIEW_FINDBAR (logview->priv->find_bar), _("Wrapped"));
+    }
+  } else {
+    if (wrapped) {
+
+      GtkTextMark *mark;
+      GtkTextIter iter;
+
+      if (gtk_text_buffer_get_has_selection (buffer)) {
+        /* unselect */
+        mark = gtk_text_buffer_get_mark (buffer, "insert");
+        gtk_text_buffer_get_iter_at_mark (buffer, &iter, mark);
+        gtk_text_buffer_move_mark_by_name (buffer, "selection_bound", &iter);
+      }
+
+      logview_findbar_set_message (LOGVIEW_FINDBAR (logview->priv->find_bar), _("Not found"));
+    } else {
+      if (forward) {
+        gtk_text_buffer_get_start_iter (buffer, &search);
+      } else {
+        gtk_text_buffer_get_end_iter (buffer, &search);
+      }
+
+      wrapped = TRUE;
+      goto wrap;
+    }
+  }
+}
+
+static void
+findbar_previous_cb (LogviewFindbar *findbar,
+                     gpointer user_data)
+{
+  LogviewWindow *logview = user_data;
+
+  logview_search_text (logview, FALSE);
+}
+
+static void
+findbar_next_cb (LogviewFindbar *findbar,
+                 gpointer user_data)
+{
+  LogviewWindow *logview = user_data;
+
+  logview_search_text (logview, TRUE);
+}
+
+static gboolean
+text_changed_timeout_cb (gpointer user_data)
+{
+  LogviewWindow *logview = user_data;
+  GtkTextMark *search_start, *search_end;
+  GtkTextIter start;
+  GtkTextBuffer *buffer;
+
+  logview->priv->search_timeout_id = 0;
+
+  buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (logview->priv->text_view));
+  search_start = gtk_text_buffer_get_mark (buffer, SEARCH_START_MARK);
+  search_end = gtk_text_buffer_get_mark (buffer, SEARCH_END_MARK);
+
+  if (search_start) {
+    /* reset the search mark to the start */
+    gtk_text_buffer_get_start_iter (buffer, &start);
+    gtk_text_buffer_move_mark (buffer, search_start, &start);
+    gtk_text_buffer_move_mark (buffer, search_end, &start);
+  }
+
+  logview_findbar_set_message (LOGVIEW_FINDBAR (logview->priv->find_bar), NULL);
+
+  logview_search_text (logview, TRUE);
+
+  return FALSE;
+}
+
+static void
+findbar_text_changed_cb (LogviewFindbar *findbar,
+                         gpointer user_data)
+{
+  LogviewWindow *logview = user_data;
+
+  if (logview->priv->search_timeout_id != 0) {
+    g_source_remove (logview->priv->search_timeout_id);
+  }
+
+  logview->priv->search_timeout_id = g_timeout_add (300, text_changed_timeout_cb, logview);
+}
+
+static void
+logview_search (GSimpleAction *action,
+                GVariant      *parameter,
+                gpointer       user_data)
+{
+  LogviewWindow *logview = user_data;
+
+  logview_findbar_open (LOGVIEW_FINDBAR (logview->priv->find_bar));
+}
+
+static void
+filter_buffer (LogviewWindow *logview, gint start_line)
+{
+  GtkTextBuffer *buffer;
+  GtkTextIter start, *end;
+  gchar* text;
+  GList* cur_filter;
+  gboolean matched;
+  int lines, i;
+
+  buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (logview->priv->text_view));
+  lines = gtk_text_buffer_get_line_count (buffer);
+
+  for (i = start_line; i < lines; i++) {
+    matched = FALSE;
+
+    gtk_text_buffer_get_iter_at_line (buffer, &start, i);
+    end = gtk_text_iter_copy (&start);
+    gtk_text_iter_forward_line (end);
+
+    text = gtk_text_buffer_get_text (buffer, &start, end, TRUE);
+
+    for (cur_filter = logview->priv->active_filters; cur_filter != NULL;
+         cur_filter = g_list_next (cur_filter))
+    {
+      if (logview_filter_filter (LOGVIEW_FILTER (cur_filter->data), text)) {
+        gtk_text_buffer_apply_tag (buffer,
+                                   logview_filter_get_tag (LOGVIEW_FILTER (cur_filter->data)),
+                                   &start, end);
+        matched = TRUE;
+      }
+    }
+
+    g_free (text);
+
+    if (!matched && logview->priv->matches_only) {
+      gtk_text_buffer_apply_tag_by_name (buffer,
+                                         "invisible-filter",
+                                         &start, end);
+    } else {
+      gtk_text_buffer_remove_tag_by_name (buffer,
+                                          "invisible-filter",
+                                          &start, end);
+    }
+
+    gtk_text_iter_free (end);
+  }
+}
+
+static void
+filter_remove (LogviewWindow *logview, LogviewFilter *filter)
+{
+  GtkTextIter start, end;
+  GtkTextBuffer *buffer;
+
+  buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (logview->priv->text_view));
+  gtk_text_buffer_get_bounds (buffer, &start, &end);
+
+  gtk_text_buffer_remove_tag (buffer, logview_filter_get_tag (filter),
+                              &start, &end);
+}
+
+static void
+on_filter_toggled (GtkCheckMenuItem *item, LogviewWindow *logview)
+{
+  LogviewWindowPrivate *priv = logview_window_get_instance_private (logview);
+  const gchar* name;
+  LogviewFilter *filter;
+
+  name = gtk_menu_item_get_label (GTK_MENU_ITEM (item));
+  if (gtk_check_menu_item_get_active (item)) {
+    priv->active_filters = g_list_append (priv->active_filters,
+                                          logview_prefs_get_filter (priv->prefs,
+                                                                    name));
+    filter_buffer(logview, 0);
+  } else {
+    filter = logview_prefs_get_filter (priv->prefs, name);
+    priv->active_filters = g_list_remove (priv->active_filters,
+                                          filter);
+
+    filter_remove (logview, filter);
+  }
+}
+static void remove_all_widget (GtkWidget *widget, gpointer filter_menu)
+{
+    gtk_container_remove (GTK_CONTAINER (filter_menu), widget);
+}
+
+static void
+update_filter_menu (LogviewWindow *window)
+{
+  LogviewWindowPrivate *priv;
+  GtkWidget *filter_menu;
+  char **actions;
+  int i = 0;
+  GList *l;
+  GList *filters;
+  GtkTextTagTable *table;
+  GtkTextTag *tag;
+  GSimpleAction  *action;
+  gchar* name;
+
+  priv = logview_window_get_instance_private (window);
+
+  g_return_if_fail (priv->filter_action_group != NULL);
+
+  table = priv->tag_table;
+
+  actions = g_action_group_list_actions (priv->filter_action_group);
+  filter_menu = (GtkWidget *)gtk_builder_get_object (priv->ui_manager, "filter_menu");
+
+  while (actions[i] != NULL) {
+    tag = gtk_text_tag_table_lookup (table, actions[i]);
+    gtk_text_tag_table_remove (table, tag);
+    g_action_map_remove_action (G_ACTION_MAP (priv->filter_action_group), actions[i]);
+    i++;
+  }
+
+  g_strfreev (actions);
+  gtk_container_foreach (GTK_CONTAINER (filter_menu), remove_all_widget, filter_menu);
+  filters = logview_prefs_get_filters (logview_prefs_get ());
+
+  for (l = filters; l != NULL; l = g_list_next (l)) {
+    g_object_get (l->data, "name", &name, NULL);
+    GtkWidget *item;
+    item = gtk_check_menu_item_new_with_label (name);
+    gtk_container_add (GTK_CONTAINER (filter_menu), item);
+    gtk_widget_show_all (filter_menu);
+    action = g_simple_action_new (name, NULL);;
+    g_action_map_add_action (G_ACTION_MAP (priv->filter_action_group), G_ACTION (action));
+    gtk_text_tag_table_add (table,
+                            logview_filter_get_tag (LOGVIEW_FILTER (l->data)));
+
+    g_signal_connect (item,
+                      "toggled",
+                      G_CALLBACK (on_filter_toggled),
+                      window);
+    g_object_unref (action);
+    g_free(name);
+  }
+
+  g_list_free (filters);
+
+}
+
+static void
+on_logview_filter_manager_response (GtkDialog *dialog,
+                                    gint response,
+                                    LogviewWindow *logview)
+{
+  update_filter_menu (logview);
+
+  g_list_free (logview->priv->active_filters);
+  logview->priv->active_filters = NULL;
+}
+
+static void
+logview_manage_filters (GSimpleAction *action,
+                        GVariant      *parameter,
+                        gpointer       user_data)
+{
+  GtkWidget *manager;
+
+  manager = logview_filter_manager_new ();
+
+  g_signal_connect (manager, "response",
+                    G_CALLBACK (on_logview_filter_manager_response),
+                    user_data);
+
+  gtk_window_set_transient_for (GTK_WINDOW (manager),
+                                GTK_WINDOW (user_data));
+  gtk_widget_show (GTK_WIDGET (manager));
+}
+
+static void
+logview_about (GSimpleAction *action,
+               GVariant      *parameter,
+               gpointer       window)
+{
+  g_return_if_fail (GTK_IS_WINDOW (window));
+
+  char *license_trans = g_strjoin ("\n\n", _(logview_about_license[0]),
+                                   _(logview_about_license[1]),
+                                   _(logview_about_license[2]), NULL);
+
+#ifdef ENABLE_NLS
+  const char **p;
+  for (p = logview_about_documenters; *p; ++p)
+    *p = _(*p);
+#endif
+
+  gtk_show_about_dialog (GTK_WINDOW (window),
+                         "program-name", _("System Log Viewer"),
+                         "version", VERSION,
+                         "title", _("About System Log Viewer"),
+                         "copyright", _("Copyright \xc2\xa9 1998-2008 Free Software Foundation, Inc.\n"
+                                        "Copyright \xc2\xa9 2011-2021 MATE developers"),
+                         "license", license_trans,
+                         "wrap-license", TRUE,
+                         "comments", _("View, monitor or analyze your system logs in a gradual manner."),
+                         "authors", logview_about_authors,
+                         "documenters", logview_about_documenters,
+                         "translator_credits", strcmp (logview_about_translator_credits,
+                                                       "translator-credits") != 0 ?
+                                               logview_about_translator_credits : NULL,
+                         "logo_icon_name", "mate-system-log",
+                         NULL);
+  g_free (license_trans);
+
+  return;
+}
+
+static void
+logview_toggle_statusbar (GSimpleAction *action,
+                          GVariant      *parameter,
+                          gpointer       user_data)
+{
+  LogviewWindow *logview = user_data;
+
+  if (gtk_widget_get_visible (logview->priv->statusbar))
+    gtk_widget_hide (logview->priv->statusbar);
+  else
+    gtk_widget_show (logview->priv->statusbar);
+}
+
+static void
+logview_toggle_sidebar (GSimpleAction *action,
+                        GVariant      *parameter,
+                        gpointer       user_data)
+{
+  LogviewWindow *logview = user_data;
+
+  if (gtk_widget_get_visible (logview->priv->sidebar))
+    gtk_widget_hide (logview->priv->sidebar);
+  else
+    gtk_widget_show (logview->priv->sidebar);
+}
+
+static void
+logview_toggle_match_filters (GSimpleAction *action,
+                              GVariant      *state,
+                              gpointer       user_data)
+{
+
+  LogviewWindow *logview = user_data;
+
+  logview->priv->matches_only = g_variant_get_boolean (state);
+  g_simple_action_set_state (action, state);
+  filter_buffer (logview, 0);
+}
+
+static void
+logview_quit (GSimpleAction *action,
+              GVariant      *parameter,
+              gpointer       user_data)
+{
+  gtk_widget_destroy (GTK_WIDGET (user_data));
+  gtk_main_quit ();
+}
+
+/* GObject functions */
+
+/* Menus */
+static GActionEntry win_entries[] = {
+  { "OpenLog", logview_open_log, NULL, NULL, NULL},
+  { "CloseLog", logview_close_log, NULL, NULL, NULL},
+  { "Quit", logview_quit, NULL, NULL, NULL },
+  { "Copy", logview_copy, NULL, NULL, NULL },
+  { "SelectAll", logview_select_all, NULL, NULL, NULL },
+  { "ShowStatusBar", logview_toggle_statusbar, NULL, "true", NULL},
+  { "ShowSidebar", logview_toggle_sidebar, NULL, "true", NULL},
+  { "Search", logview_search, NULL, NULL, NULL},
+  { "ViewZoomIn", logview_bigger_text, NULL, NULL, NULL},
+  { "ViewZoomOut", logview_smaller_text, NULL, NULL, NULL},
+  { "ViewZoom100", logview_normal_text, NULL, NULL, NULL},
+  { "FilterManage", logview_manage_filters, NULL, "false", NULL},
+  { "FilterMatchOnly", activate_toggle, NULL, "false", logview_toggle_match_filters},
+  { "HelpContents", logview_help, NULL, NULL, NULL },
+  { "AboutAction", logview_about, NULL, NULL, NULL },
+};
+
+static const struct {
+  guint keyval;
+  GdkModifierType modifier;
+  const gchar *widget_id;
+} menu_keybindings [] = {
+  { GDK_KEY_O,      GDK_CONTROL_MASK, "open_item" },
+  { GDK_KEY_W,      GDK_CONTROL_MASK, "close_item" },
+  { GDK_KEY_Q,      GDK_CONTROL_MASK, "quit_item" },
+  { GDK_KEY_C,      GDK_CONTROL_MASK, "copy_item" },
+  { GDK_KEY_A,      GDK_CONTROL_MASK, "select_item" },
+  { GDK_KEY_F9,     0, "side_item" },
+  { GDK_KEY_F,      GDK_CONTROL_MASK, "find_item" },
+  { GDK_KEY_plus,      GDK_CONTROL_MASK, "in_item" },
+  { GDK_KEY_minus, GDK_CONTROL_MASK, "out_item" },
+  { GDK_KEY_0,        GDK_CONTROL_MASK, "normal_item" },
+  { GDK_KEY_F1,     0, "help_item" }
+};
+
+static gboolean
+window_size_changed_cb (GtkWidget *widget, GdkEventConfigure *event,
+                        gpointer data)
+{
+  LogviewWindow *window = data;
+
+  logview_prefs_store_window_size (window->priv->prefs,
+                                   event->width, event->height);
+
+  return FALSE;
+}
+
+static void
+real_select_day (LogviewWindow *logview,
+                 GDate *date, int first_line, int last_line)
+{
+  GtkTextBuffer *buffer;
+  GtkTextIter start_iter, end_iter, start_vis, end_vis;
+  GdkRectangle visible_rect;
+
+  buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (logview->priv->text_view));
+
+  gtk_text_buffer_get_bounds (buffer, &start_iter, &end_iter);
+  gtk_text_buffer_get_iter_at_line (buffer, &start_vis, first_line);
+  gtk_text_buffer_get_iter_at_line (buffer, &end_vis, last_line + 1);
+
+  /* clear all previous invisible tags */
+  gtk_text_buffer_remove_tag_by_name (buffer, "invisible",
+                                      &start_iter, &end_iter);
+
+  gtk_text_buffer_apply_tag_by_name (buffer, "invisible",
+                                     &start_iter, &start_vis);
+  gtk_text_buffer_apply_tag_by_name (buffer, "invisible",
+                                     &end_vis, &end_iter);
+
+  /* FIXME: why is this needed to update the view when selecting a day back? */
+  gtk_text_view_get_visible_rect (GTK_TEXT_VIEW (logview->priv->text_view),
+                                  &visible_rect);
+  gdk_window_invalidate_rect (gtk_widget_get_window (logview->priv->text_view),
+                              &visible_rect, TRUE);
+}
+
+static void
+loglist_day_selected_cb (LogviewLoglist *loglist,
+                         Day *day,
+                         gpointer user_data)
+{
+  LogviewWindow *logview = user_data;
+
+  real_select_day (logview, day->date, day->first_line, day->last_line);
+}
+
+static void
+loglist_day_cleared_cb (LogviewLoglist *loglist,
+                        gpointer user_data)
+{
+  LogviewWindow *logview = user_data;
+  GtkTextBuffer *buffer;
+  GtkTextIter start, end;
+
+  buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (logview->priv->text_view));
+  gtk_text_buffer_get_bounds (buffer, &start, &end);
+
+  /* clear all previous invisible tags */
+  gtk_text_buffer_remove_tag_by_name (buffer, "invisible",
+                                      &start, &end);
+}
+
+static void
+logview_window_schedule_log_read (LogviewWindow *window,
+                                  LogviewLog *log)
+{
+  if (window->priv->read_cancellable != NULL) {
+    g_cancellable_cancel (window->priv->read_cancellable);
+    g_clear_object (&window->priv->read_cancellable);
+  }
+
+  window->priv->read_cancellable = g_cancellable_new ();
+  logview_log_read_new_lines (log,
+                              window->priv->read_cancellable,
+                              (LogviewNewLinesCallback) read_new_lines_cb,
+                              window);
+}
+
+static void
+log_monitor_changed_cb (LogviewLog *log,
+                        gpointer user_data)
+{
+  LogviewWindow *window = user_data;
+
+  /* reschedule a read */
+  logview_window_schedule_log_read (window, log);
+}
+
+static void
+paint_timestamps (GtkTextBuffer *buffer, int old_line_count,
+                  GSList *days)
+{
+  GSList *l;
+
+  for (l = days; l; l = l->next) {
+    Day *day = l->data;
+
+    _gtk_text_buffer_apply_tag_to_rectangle (buffer,
+                                             old_line_count + day->first_line - 1,
+                                             old_line_count + day->last_line,
+                                             0, day->timestamp_len, "gray");
+  }
+}
+
+static void
+read_new_lines_cb (LogviewLog *log,
+                   const char **lines,
+                   GSList *new_days,
+                   GError *error,
+                   gpointer user_data)
+{
+  LogviewWindow *window = user_data;
+  GtkTextBuffer *buffer;
+  gboolean boldify = FALSE;
+  int i, old_line_count, filter_start_line;
+  GtkTextIter iter, start;
+  GtkTextMark *mark;
+  char *converted, *primary;
+  gsize len;
+
+  if (error != NULL) {
+    if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
+      primary = g_strdup_printf (_("Can't read from \"%s\""),
+                                 logview_log_get_display_name (log));
+      logview_window_add_error (window, primary, error->message);
+      g_free (primary);
+    }
+
+    return;
+  }
+
+  if (lines == NULL) {
+    /* there's no error, but no lines have been read */
+    return;
+  }
+
+  buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (window->priv->text_view));
+  old_line_count = gtk_text_buffer_get_line_count (buffer);
+  filter_start_line = old_line_count > 0 ? (old_line_count - 1) : 0;
+
+  if (gtk_text_buffer_get_char_count (buffer) != 0) {
+    boldify = TRUE;
+  }
+
+  gtk_text_buffer_get_end_iter (buffer, &iter);
+
+  if (boldify) {
+    mark = gtk_text_buffer_create_mark (buffer, NULL, &iter, TRUE);
+  }
+
+  for (i = 0; lines[i]; i++) {
+    len = strlen (lines[i]);
+
+    if (!g_utf8_validate (lines[i], len, NULL)) {
+      converted = g_locale_to_utf8 (lines[i], (gssize) len, NULL, &len, NULL);
+      gtk_text_buffer_insert (buffer, &iter, converted, len);
+      g_free (converted);
+    } else {
+      gtk_text_buffer_insert (buffer, &iter, lines[i], strlen (lines[i]));
+    }
+
+    gtk_text_iter_forward_to_end (&iter);
+    gtk_text_buffer_insert (buffer, &iter, "\n", 1);
+    gtk_text_iter_forward_char (&iter);
+  }
+
+  if (boldify) {
+    gtk_text_buffer_get_iter_at_mark (buffer, &start, mark);
+    gtk_text_buffer_apply_tag_by_name (buffer, "bold", &start, &iter);
+    gtk_text_buffer_delete_mark (buffer, mark);
+  }
+  filter_buffer (window, filter_start_line);
+
+  gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (window->priv->text_view),
+                                &iter, 0.0, FALSE, 0.0, 0.0);
+
+  paint_timestamps (buffer, old_line_count, new_days);
+
+  if (window->priv->monitor_id == 0) {
+    window->priv->monitor_id = g_signal_connect (log, "log-changed",
+                                                 G_CALLBACK (log_monitor_changed_cb), window);
+  }
+
+  logview_update_statusbar (window, log);
+  logview_loglist_update_lines (LOGVIEW_LOGLIST (window->priv->loglist), log);
+}
+
+static void
+active_log_changed_cb (LogviewManager *manager,
+                       LogviewLog *log,
+                       LogviewLog *old_log,
+                       gpointer data)
+{
+  LogviewWindow *window = data;
+  const char **lines;
+  GtkTextBuffer *buffer;
+
+  findbar_close_cb (LOGVIEW_FINDBAR (window->priv->find_bar),
+                    window);
+
+  logview_set_window_title (window, logview_log_get_display_name (log));
+
+  if (window->priv->monitor_id) {
+    g_signal_handler_disconnect (old_log, window->priv->monitor_id);
+    window->priv->monitor_id = 0;
+  }
+
+  lines = logview_log_get_cached_lines (log);
+  buffer = gtk_text_buffer_new (window->priv->tag_table);
+
+  if (lines != NULL) {
+    int i;
+    GtkTextIter iter;
+
+    /* update the text view to show the current lines */
+    gtk_text_buffer_get_end_iter (buffer, &iter);
+
+    for (i = 0; lines[i]; i++) {
+      gtk_text_buffer_insert (buffer, &iter, lines[i], strlen (lines[i]));
+      gtk_text_iter_forward_to_end (&iter);
+      gtk_text_buffer_insert (buffer, &iter, "\n", 1);
+      gtk_text_iter_forward_char (&iter);
+    }
+
+    paint_timestamps (buffer, 1, logview_log_get_days_for_cached_lines (log));
+  }
+
+  if (lines == NULL || logview_log_has_new_lines (log)) {
+    /* read the new lines */
+    logview_window_schedule_log_read (window, log);
+  } else {
+    /* start now monitoring the log for changes */
+    window->priv->monitor_id = g_signal_connect (log, "log-changed",
+                                                 G_CALLBACK (log_monitor_changed_cb), window);
+  }
+
+  /* we set the buffer to the view anyway;
+   * if there are no lines it will be empty for the duration of the thread
+   * and will help us to distinguish the two cases of the following if
+   * cause in the callback.
+   */
+  gtk_text_view_set_buffer (GTK_TEXT_VIEW (window->priv->text_view), buffer);
+  g_object_unref (buffer);
+}
+
+static void
+font_changed_cb (LogviewPrefs *prefs,
+                 const char *font_name,
+                 gpointer user_data)
+{
+  LogviewWindow *window = user_data;
+
+  logview_set_font (window, font_name);
+}
+
+static const struct {
+  guint keyval;
+  GdkModifierType modifier;
+  const gchar *action;
+} extra_keybindings [] = {
+  { GDK_KEY_KP_Add,      GDK_CONTROL_MASK, "ViewZoomIn" },
+  { GDK_KEY_KP_Subtract, GDK_CONTROL_MASK, "ViewZoomOut" },
+  { GDK_KEY_KP_0,        GDK_CONTROL_MASK, "ViewZoom100" }
+};
+
+static gboolean
+key_press_event_cb (GtkWidget *widget,
+                    GdkEventKey *event,
+                    gpointer user_data)
+{
+  LogviewWindow *window = user_data;
+  guint modifier = event->state & gtk_accelerator_get_default_mod_mask ();
+  GAction *action;
+  int i;
+
+  /* handle accelerators that we want bound, but aren't associated with
+   * an action */
+  for (i = 0; i < G_N_ELEMENTS (extra_keybindings); i++) {
+    if (event->keyval == extra_keybindings[i].keyval &&
+        modifier == extra_keybindings[i].modifier) {
+      action = g_action_map_lookup_action (G_ACTION_MAP (window->priv->action_group),
+                                            extra_keybindings[i].action);
+      g_action_activate (action, NULL);
+      return TRUE;
+    }
+  }
+
+  return FALSE;
+}
+
+/* adapted from GEdit */
+
+static void
+message_area_create_error_box (LogviewWindow *window,
+                               GtkWidget *message_area)
+{
+  GtkWidget *hbox_content;
+  GtkWidget *image;
+  GtkWidget *vbox;
+  GtkWidget *primary_label;
+  GtkWidget *secondary_label;
+
+  hbox_content = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 8);
+  gtk_widget_show (hbox_content);
+
+  image = gtk_image_new_from_icon_name ("dialog-error",
+                                        GTK_ICON_SIZE_DIALOG);
+  gtk_widget_show (image);
+  gtk_box_pack_start (GTK_BOX (hbox_content), image, FALSE, FALSE, 0);
+  gtk_widget_set_halign (image, GTK_ALIGN_CENTER);
+  gtk_widget_set_valign (image, GTK_ALIGN_START);
+
+  vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
+  gtk_widget_show (vbox);
+  gtk_box_pack_start (GTK_BOX (hbox_content), vbox, TRUE, TRUE, 0);
+
+  primary_label = gtk_label_new (NULL);
+  gtk_widget_show (primary_label);
+  gtk_box_pack_start (GTK_BOX (vbox), primary_label, TRUE, TRUE, 0);
+  gtk_label_set_use_markup (GTK_LABEL (primary_label), TRUE);
+  gtk_label_set_line_wrap (GTK_LABEL (primary_label), TRUE);
+  gtk_label_set_xalign (GTK_LABEL (primary_label), 0.0);
+  gtk_label_set_yalign (GTK_LABEL (primary_label), 0.5);
+  gtk_widget_set_can_focus (primary_label, TRUE);
+  gtk_label_set_selectable (GTK_LABEL (primary_label), TRUE);
+
+  window->priv->message_primary = primary_label;
+
+  secondary_label = gtk_label_new (NULL);
+  gtk_widget_show (secondary_label);
+  gtk_box_pack_start (GTK_BOX (vbox), secondary_label, TRUE, TRUE, 0);
+  gtk_widget_set_can_focus (secondary_label, TRUE);
+  gtk_label_set_use_markup (GTK_LABEL (secondary_label), TRUE);
+  gtk_label_set_line_wrap (GTK_LABEL (secondary_label), TRUE);
+  gtk_label_set_selectable (GTK_LABEL (secondary_label), TRUE);
+  gtk_label_set_xalign (GTK_LABEL (secondary_label), 0.0);
+  gtk_label_set_yalign (GTK_LABEL (secondary_label), 0.5);
+
+  window->priv->message_secondary = secondary_label;
+
+  gtk_container_add
+      (GTK_CONTAINER (gtk_info_bar_get_content_area
+                      (GTK_INFO_BAR (message_area))),
+       hbox_content);
+}
+
+static void
+message_area_set_labels (LogviewWindow *window,
+                         const char *primary,
+                         const char *secondary)
+{
+  char *primary_markup, *secondary_markup;
+
+  primary_markup = g_markup_printf_escaped ("<b>%s</b>", primary);
+  secondary_markup = g_markup_printf_escaped ("<small>%s</small>",
+                                              secondary);
+
+  gtk_label_set_markup (GTK_LABEL (window->priv->message_primary),
+                        primary_markup);
+  gtk_label_set_markup (GTK_LABEL (window->priv->message_secondary),
+                        secondary_markup);
+
+  g_free (primary_markup);
+  g_free (secondary_markup);
+}
+
+static void
+message_area_response_cb (GtkInfoBar *message_area,
+                          int response_id, gpointer user_data)
+{
+  gtk_widget_hide (GTK_WIDGET (message_area));
+
+  g_signal_handlers_disconnect_by_func (message_area,
+                                        message_area_response_cb,
+                                        user_data);
+}
+
+static void
+logview_window_finalize (GObject *object)
+{
+  LogviewWindow *logview = LOGVIEW_WINDOW (object);
+
+  if (logview->priv->read_cancellable != NULL) {
+    g_cancellable_cancel (logview->priv->read_cancellable);
+    g_clear_object (&logview->priv->read_cancellable);
+  }
+
+  g_object_unref (logview->priv->ui_manager);
+  G_OBJECT_CLASS (logview_window_parent_class)->finalize (object);
+}
+
+static void
+logview_window_init (LogviewWindow *logview)
+{
+  GActionGroup  *action_group;
+  GtkAccelGroup *accel_group;
+  GError *error = NULL;
+  GtkWidget *hpaned, *main_view, *vbox, *w, *item;
+  PangoContext *context;
+  PangoFontDescription *fontdesc;
+  gchar *monospace_font_name;
+  LogviewWindowPrivate *priv;
+  int width, height;
+  gboolean res;
+  int i;
+
+  GtkStyleContext *s_context;
+
+  s_context = gtk_widget_get_style_context (GTK_WIDGET (logview));
+  gtk_style_context_add_class (s_context, "logview-window");
+
+  priv = logview->priv = logview_window_get_instance_private (logview);
+  priv->prefs = logview_prefs_get ();
+  priv->manager = logview_manager_get ();
+  priv->monitor_id = 0;
+
+  logview_prefs_get_stored_window_size (priv->prefs, &width, &height);
+  gtk_window_set_default_size (GTK_WINDOW (logview), width, height);
+
+  vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
+  gtk_container_add (GTK_CONTAINER (logview), vbox);
+
+  /* create menus */
+  action_group = (GActionGroup*)g_simple_action_group_new ();
+  g_action_map_add_action_entries (G_ACTION_MAP (action_group),
+                                   win_entries, G_N_ELEMENTS (win_entries),
+                                   logview);
+  priv->action_group = action_group;
+
+  priv->ui_manager = gtk_builder_new ();
+
+  gtk_widget_insert_action_group (GTK_WIDGET (logview), "win", action_group);
+  accel_group = gtk_accel_group_new ();
+  gtk_window_add_accel_group (GTK_WINDOW (logview), accel_group);
+
+  res = gtk_builder_add_from_resource (priv->ui_manager,
+                                      "/org/mate/system-log/logview-toolbar.xml",
+                                       &error);
+
+  if (res == FALSE) {
+    priv->ui_manager = NULL;
+    g_critical ("Can't load the UI description: %s", error->message);
+    g_error_free (error);
+    return;
+  }
+
+  w = (GtkWidget *)gtk_builder_get_object (priv->ui_manager, "logmenubar");
+  gtk_box_pack_start (GTK_BOX (vbox), w, FALSE, FALSE, 0);
+  gtk_widget_show (w);
+
+  for (i = 0; i < G_N_ELEMENTS (menu_keybindings); i++)
+  {
+    item = (GtkWidget*)gtk_builder_get_object (priv->ui_manager, menu_keybindings[i].widget_id);
+    gtk_widget_add_accelerator (item, "activate", accel_group,
+                                menu_keybindings[i].keyval,
+                                menu_keybindings[i].modifier,
+                                GTK_ACCEL_VISIBLE);
+  }
+  /* panes */
+  hpaned = gtk_paned_new (GTK_ORIENTATION_HORIZONTAL);
+  gtk_box_pack_start (GTK_BOX (vbox), hpaned, TRUE, TRUE, 0);
+  priv->hpaned = hpaned;
+  gtk_widget_show (hpaned);
+
+  /* first pane : sidebar (list of logs) */
+  priv->sidebar = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
+  gtk_widget_show (priv->sidebar);
+
+  /* first pane: log list */
+  w = gtk_scrolled_window_new (NULL, NULL);
+  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (w),
+                                  GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+  gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (w),
+                                       GTK_SHADOW_ETCHED_IN);
+
+  priv->loglist = logview_loglist_new ();
+  gtk_container_add (GTK_CONTAINER (w), priv->loglist);
+  gtk_box_pack_start (GTK_BOX (priv->sidebar), w, TRUE, TRUE, 0);
+  gtk_paned_pack1 (GTK_PANED (hpaned), priv->sidebar, FALSE, FALSE);
+  gtk_widget_show (w);
+  gtk_widget_show (priv->loglist);
+
+  g_signal_connect (priv->loglist, "day_selected",
+                    G_CALLBACK (loglist_day_selected_cb), logview);
+  g_signal_connect (priv->loglist, "day_cleared",
+                    G_CALLBACK (loglist_day_cleared_cb), logview);
+
+  /* second pane: log */
+  main_view = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
+  gtk_paned_pack2 (GTK_PANED (hpaned), main_view, TRUE, TRUE);
+
+  /* second pane: error message area */
+  priv->message_area = gtk_info_bar_new ();
+  message_area_create_error_box (logview, priv->message_area);
+  gtk_info_bar_add_button (GTK_INFO_BAR (priv->message_area),
+                           "gtk-close", GTK_RESPONSE_CLOSE);
+  gtk_box_pack_start (GTK_BOX (main_view), priv->message_area, FALSE, FALSE, 0);
+
+  /* second pane: text view */
+  w = gtk_scrolled_window_new (NULL, NULL);
+  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (w),
+                                  GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+  gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (w), GTK_SHADOW_IN);
+  gtk_box_pack_start (GTK_BOX (main_view), w, TRUE, TRUE, 0);
+  gtk_widget_show (w);
+
+  priv->tag_table = gtk_text_tag_table_new ();
+  populate_tag_table (priv->tag_table);
+
+  priv->text_view = gtk_text_view_new ();
+  g_object_set (priv->text_view, "editable", FALSE, NULL);
+  populate_style_tag_table (logview);
+
+  gtk_container_add (GTK_CONTAINER (w), priv->text_view);
+  gtk_widget_show (priv->text_view);
+
+  /* use the desktop monospace font */
+  monospace_font_name = logview_prefs_get_monospace_font_name (priv->prefs);
+  logview_set_font (logview, monospace_font_name);
+  g_free (monospace_font_name);
+
+  /* remember the original font size */
+  context = gtk_widget_get_pango_context (priv->text_view);
+  fontdesc = pango_context_get_font_description (context);
+  priv->original_fontsize = pango_font_description_get_size (fontdesc) / PANGO_SCALE;
+
+  /* restore saved zoom */
+  priv->fontsize = logview_prefs_get_stored_fontsize (priv->prefs);
+
+  if (priv->fontsize <= 0) {
+    /* restore the default */
+    logview_normal_text (NULL, NULL, logview);
+  } else {
+    logview_set_fontsize (logview, FALSE);
+  }
+
+  /* version selector */
+  priv->version_bar = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+  gtk_container_set_border_width (GTK_CONTAINER (priv->version_bar), 3);
+  priv->version_selector = gtk_combo_box_text_new ();
+  g_signal_connect (priv->version_selector, "changed",
+                    G_CALLBACK (logview_version_selector_changed), logview);
+  w = gtk_label_new (_("Version: "));
+
+  gtk_box_pack_end (GTK_BOX (priv->version_bar), priv->version_selector, FALSE, FALSE, 0);
+  gtk_box_pack_end (GTK_BOX (priv->version_bar), w, FALSE, FALSE, 0);
+  gtk_box_pack_end (GTK_BOX (main_view), priv->version_bar, FALSE, FALSE, 0);
+
+  priv->find_bar = logview_findbar_new ();
+  gtk_box_pack_end (GTK_BOX (main_view), priv->find_bar, FALSE, FALSE, 0);
+
+  g_signal_connect (priv->find_bar, "previous",
+                    G_CALLBACK (findbar_previous_cb), logview);
+  g_signal_connect (priv->find_bar, "next",
+                    G_CALLBACK (findbar_next_cb), logview);
+  g_signal_connect (priv->find_bar, "text_changed",
+                    G_CALLBACK (findbar_text_changed_cb), logview);
+  g_signal_connect (priv->find_bar, "close",
+                    G_CALLBACK (findbar_close_cb), logview);
+
+  /* signal handlers
+   * - first is used to remember/restore the window size on quit.
+   */
+  g_signal_connect (logview, "configure_event",
+                    G_CALLBACK (window_size_changed_cb), logview);
+  g_signal_connect (priv->prefs, "system-font-changed",
+                    G_CALLBACK (font_changed_cb), logview);
+  g_signal_connect (priv->manager, "active-changed",
+                    G_CALLBACK (active_log_changed_cb), logview);
+  g_signal_connect (logview, "key-press-event",
+                    G_CALLBACK (key_press_event_cb), logview);
+
+  /* status area at bottom */
+  priv->statusbar = gtk_statusbar_new ();
+	gtk_widget_set_margin_top (GTK_WIDGET (logview->priv->statusbar), 0);
+	gtk_widget_set_margin_bottom (GTK_WIDGET (logview->priv->statusbar), 0);
+
+  gtk_box_pack_start (GTK_BOX (vbox), priv->statusbar, FALSE, FALSE, 0);
+  gtk_widget_show (priv->statusbar);
+
+  /* Filter menu */
+  priv->filter_action_group = (GActionGroup*)g_simple_action_group_new ();
+  gtk_widget_insert_action_group (GTK_WIDGET (logview), "filter", priv->filter_action_group);
+  priv->active_filters = NULL;
+  update_filter_menu (logview);
+
+  gtk_widget_show (vbox);
+  gtk_widget_show (main_view);
+}
+
+static void
+logview_window_class_init (LogviewWindowClass *klass)
+{
+  GObjectClass *object_class = (GObjectClass *) klass;
+
+  object_class->finalize = logview_window_finalize;
+}
+
+/* public methods */
+
+GtkWidget *
+logview_window_new ()
+{
+  LogviewWindow *logview;
+
+  logview = g_object_new (LOGVIEW_TYPE_WINDOW, NULL);
+
+  if (logview->priv->ui_manager == NULL) {
+    return NULL;
+  }
+
+  return GTK_WIDGET (logview);
+}
+
+void
+logview_window_add_error (LogviewWindow *window,
+                          const char *primary,
+                          const char *secondary)
+{
+  LogviewWindowPrivate *priv;
+
+  g_assert (LOGVIEW_IS_WINDOW (window));
+  priv = window->priv;
+
+  message_area_set_labels (window,
+                           primary, secondary);
+
+  gtk_widget_show (priv->message_area);
+
+  g_signal_connect (priv->message_area, "response",
+                    G_CALLBACK (message_area_response_cb), window);
+}
+
+void
+logview_window_add_errors (LogviewWindow *window,
+                           GPtrArray *errors)
+{
+  char *primary, *secondary;
+  GString *str;
+  char **err;
+  int i;
+
+  g_assert (LOGVIEW_IS_WINDOW (window));
+  g_assert (errors->len > 1);
+
+  primary = g_strdup (_("Could not open the following files:"));
+  str = g_string_new (NULL);
+
+  for (i = 0; i < errors->len; i++) {
+    err = (char **) g_ptr_array_index (errors, i);
+    g_string_append (str, err[0]);
+    g_string_append (str, ": ");
+    g_string_append (str, err[1]);
+    g_string_append (str, "\n");
+  }
+
+  secondary = g_string_free (str, FALSE);
+
+  message_area_set_labels (window, primary, secondary);
+
+  gtk_widget_show (window->priv->message_area);
+
+  g_signal_connect (window->priv->message_area, "response",
+                    G_CALLBACK (message_area_response_cb), window);
+
+  g_free (primary);
+  g_free (secondary);
+}
+
+
+ +
+ +
+ + diff --git a/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/26.html b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/26.html new file mode 100644 index 00000000..59ad7c76 --- /dev/null +++ b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/26.html @@ -0,0 +1,479 @@ + + + + + + Cppcheck - HTML report - mate-utils + + + + + +
+ + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
/* This file is part of MATE Utils.
+ *
+ * MATE Utils is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * MATE Utils is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MATE Utils.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "../logview-log.h"
+#include "../logview-utils.h"
+
+#include <glib.h>
+#include <gio/gio.h>
+
+static GMainLoop *loop;
+
+static void
+new_lines_cb (LogviewLog *log,
+              const char **lines,
+              GSList *new_days,
+              GError *error,
+              gpointer user_data)
+{
+  int i;
+  guint8 day;<--- Unused variable: day
+  Day *day_s;
+  GSList *days, *l;
+
+  for (i = 0; lines[i]; i++) {
+    g_print ("line %d: %s\n", i, lines[i]);
+  }
+  g_print ("outside read, lines no %u\n", logview_log_get_cached_lines_number (log));
+
+  days = log_read_dates (lines, logview_log_get_timestamp (log));
+  g_print ("\ndays %p\n", days);
+
+  for (l = days; l; l = l->next) {
+    day_s = l->data;
+    g_print ("\nday %u month %u\n", g_date_get_day (day_s->date), g_date_get_month (day_s->date));
+  }
+
+  g_object_unref (log);
+
+  g_main_loop_quit (loop);
+}
+
+static void
+callback (LogviewLog *log,
+          GError *error,
+          gpointer user_data)
+{
+  g_print ("callback! err %p, log %p\n", error, log);
+
+  logview_log_read_new_lines (log, NULL, new_lines_cb, NULL);
+}
+
+int main (int argc, char **argv)
+{
+  GError *error = NULL;
+  gchar *log_filename = NULL;
+  gchar *usage;
+  GOptionContext *context;
+  GOptionEntry entries [] =
+    { { "file", 'f', 0, G_OPTION_ARG_FILENAME, &log_filename, "The log file, e.g. /var/log/dpkg.log.2.gz", NULL },
+      { NULL } };
+
+  context = g_option_context_new (NULL);
+  g_option_context_add_main_entries (context, entries, NULL);
+
+  if (!g_option_context_parse (context, &argc, &argv, &error)) {
+    if (error) {
+      g_printerr ("%s\n\n", error->message);
+      g_error_free (error);
+    }
+    goto arg_error;
+  }
+
+  if (!log_filename) {
+    g_printerr ("ERROR: You must specify the log file.\n\n");
+    goto arg_error;
+  }
+
+  g_option_context_free (context);
+
+  loop = g_main_loop_new (NULL, FALSE);
+  logview_log_create (log_filename, callback, NULL);
+
+  g_main_loop_run (loop);
+
+  g_main_loop_unref (loop);
+
+  g_free (log_filename);
+
+  return 0;
+
+arg_error:
+  usage = g_option_context_get_help (context, TRUE, NULL);
+  g_printerr ("%s", usage);
+  g_free (usage);
+  g_option_context_free (context);
+
+  return 1;
+}
+
+ +
+ +
+ + diff --git a/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/27.html b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/27.html new file mode 100644 index 00000000..6c720716 --- /dev/null +++ b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/27.html @@ -0,0 +1,4543 @@ + + + + + + Cppcheck - HTML report - mate-utils + + + + + +
+ + + +
+
   1
+   2
+   3
+   4
+   5
+   6
+   7
+   8
+   9
+  10
+  11
+  12
+  13
+  14
+  15
+  16
+  17
+  18
+  19
+  20
+  21
+  22
+  23
+  24
+  25
+  26
+  27
+  28
+  29
+  30
+  31
+  32
+  33
+  34
+  35
+  36
+  37
+  38
+  39
+  40
+  41
+  42
+  43
+  44
+  45
+  46
+  47
+  48
+  49
+  50
+  51
+  52
+  53
+  54
+  55
+  56
+  57
+  58
+  59
+  60
+  61
+  62
+  63
+  64
+  65
+  66
+  67
+  68
+  69
+  70
+  71
+  72
+  73
+  74
+  75
+  76
+  77
+  78
+  79
+  80
+  81
+  82
+  83
+  84
+  85
+  86
+  87
+  88
+  89
+  90
+  91
+  92
+  93
+  94
+  95
+  96
+  97
+  98
+  99
+ 100
+ 101
+ 102
+ 103
+ 104
+ 105
+ 106
+ 107
+ 108
+ 109
+ 110
+ 111
+ 112
+ 113
+ 114
+ 115
+ 116
+ 117
+ 118
+ 119
+ 120
+ 121
+ 122
+ 123
+ 124
+ 125
+ 126
+ 127
+ 128
+ 129
+ 130
+ 131
+ 132
+ 133
+ 134
+ 135
+ 136
+ 137
+ 138
+ 139
+ 140
+ 141
+ 142
+ 143
+ 144
+ 145
+ 146
+ 147
+ 148
+ 149
+ 150
+ 151
+ 152
+ 153
+ 154
+ 155
+ 156
+ 157
+ 158
+ 159
+ 160
+ 161
+ 162
+ 163
+ 164
+ 165
+ 166
+ 167
+ 168
+ 169
+ 170
+ 171
+ 172
+ 173
+ 174
+ 175
+ 176
+ 177
+ 178
+ 179
+ 180
+ 181
+ 182
+ 183
+ 184
+ 185
+ 186
+ 187
+ 188
+ 189
+ 190
+ 191
+ 192
+ 193
+ 194
+ 195
+ 196
+ 197
+ 198
+ 199
+ 200
+ 201
+ 202
+ 203
+ 204
+ 205
+ 206
+ 207
+ 208
+ 209
+ 210
+ 211
+ 212
+ 213
+ 214
+ 215
+ 216
+ 217
+ 218
+ 219
+ 220
+ 221
+ 222
+ 223
+ 224
+ 225
+ 226
+ 227
+ 228
+ 229
+ 230
+ 231
+ 232
+ 233
+ 234
+ 235
+ 236
+ 237
+ 238
+ 239
+ 240
+ 241
+ 242
+ 243
+ 244
+ 245
+ 246
+ 247
+ 248
+ 249
+ 250
+ 251
+ 252
+ 253
+ 254
+ 255
+ 256
+ 257
+ 258
+ 259
+ 260
+ 261
+ 262
+ 263
+ 264
+ 265
+ 266
+ 267
+ 268
+ 269
+ 270
+ 271
+ 272
+ 273
+ 274
+ 275
+ 276
+ 277
+ 278
+ 279
+ 280
+ 281
+ 282
+ 283
+ 284
+ 285
+ 286
+ 287
+ 288
+ 289
+ 290
+ 291
+ 292
+ 293
+ 294
+ 295
+ 296
+ 297
+ 298
+ 299
+ 300
+ 301
+ 302
+ 303
+ 304
+ 305
+ 306
+ 307
+ 308
+ 309
+ 310
+ 311
+ 312
+ 313
+ 314
+ 315
+ 316
+ 317
+ 318
+ 319
+ 320
+ 321
+ 322
+ 323
+ 324
+ 325
+ 326
+ 327
+ 328
+ 329
+ 330
+ 331
+ 332
+ 333
+ 334
+ 335
+ 336
+ 337
+ 338
+ 339
+ 340
+ 341
+ 342
+ 343
+ 344
+ 345
+ 346
+ 347
+ 348
+ 349
+ 350
+ 351
+ 352
+ 353
+ 354
+ 355
+ 356
+ 357
+ 358
+ 359
+ 360
+ 361
+ 362
+ 363
+ 364
+ 365
+ 366
+ 367
+ 368
+ 369
+ 370
+ 371
+ 372
+ 373
+ 374
+ 375
+ 376
+ 377
+ 378
+ 379
+ 380
+ 381
+ 382
+ 383
+ 384
+ 385
+ 386
+ 387
+ 388
+ 389
+ 390
+ 391
+ 392
+ 393
+ 394
+ 395
+ 396
+ 397
+ 398
+ 399
+ 400
+ 401
+ 402
+ 403
+ 404
+ 405
+ 406
+ 407
+ 408
+ 409
+ 410
+ 411
+ 412
+ 413
+ 414
+ 415
+ 416
+ 417
+ 418
+ 419
+ 420
+ 421
+ 422
+ 423
+ 424
+ 425
+ 426
+ 427
+ 428
+ 429
+ 430
+ 431
+ 432
+ 433
+ 434
+ 435
+ 436
+ 437
+ 438
+ 439
+ 440
+ 441
+ 442
+ 443
+ 444
+ 445
+ 446
+ 447
+ 448
+ 449
+ 450
+ 451
+ 452
+ 453
+ 454
+ 455
+ 456
+ 457
+ 458
+ 459
+ 460
+ 461
+ 462
+ 463
+ 464
+ 465
+ 466
+ 467
+ 468
+ 469
+ 470
+ 471
+ 472
+ 473
+ 474
+ 475
+ 476
+ 477
+ 478
+ 479
+ 480
+ 481
+ 482
+ 483
+ 484
+ 485
+ 486
+ 487
+ 488
+ 489
+ 490
+ 491
+ 492
+ 493
+ 494
+ 495
+ 496
+ 497
+ 498
+ 499
+ 500
+ 501
+ 502
+ 503
+ 504
+ 505
+ 506
+ 507
+ 508
+ 509
+ 510
+ 511
+ 512
+ 513
+ 514
+ 515
+ 516
+ 517
+ 518
+ 519
+ 520
+ 521
+ 522
+ 523
+ 524
+ 525
+ 526
+ 527
+ 528
+ 529
+ 530
+ 531
+ 532
+ 533
+ 534
+ 535
+ 536
+ 537
+ 538
+ 539
+ 540
+ 541
+ 542
+ 543
+ 544
+ 545
+ 546
+ 547
+ 548
+ 549
+ 550
+ 551
+ 552
+ 553
+ 554
+ 555
+ 556
+ 557
+ 558
+ 559
+ 560
+ 561
+ 562
+ 563
+ 564
+ 565
+ 566
+ 567
+ 568
+ 569
+ 570
+ 571
+ 572
+ 573
+ 574
+ 575
+ 576
+ 577
+ 578
+ 579
+ 580
+ 581
+ 582
+ 583
+ 584
+ 585
+ 586
+ 587
+ 588
+ 589
+ 590
+ 591
+ 592
+ 593
+ 594
+ 595
+ 596
+ 597
+ 598
+ 599
+ 600
+ 601
+ 602
+ 603
+ 604
+ 605
+ 606
+ 607
+ 608
+ 609
+ 610
+ 611
+ 612
+ 613
+ 614
+ 615
+ 616
+ 617
+ 618
+ 619
+ 620
+ 621
+ 622
+ 623
+ 624
+ 625
+ 626
+ 627
+ 628
+ 629
+ 630
+ 631
+ 632
+ 633
+ 634
+ 635
+ 636
+ 637
+ 638
+ 639
+ 640
+ 641
+ 642
+ 643
+ 644
+ 645
+ 646
+ 647
+ 648
+ 649
+ 650
+ 651
+ 652
+ 653
+ 654
+ 655
+ 656
+ 657
+ 658
+ 659
+ 660
+ 661
+ 662
+ 663
+ 664
+ 665
+ 666
+ 667
+ 668
+ 669
+ 670
+ 671
+ 672
+ 673
+ 674
+ 675
+ 676
+ 677
+ 678
+ 679
+ 680
+ 681
+ 682
+ 683
+ 684
+ 685
+ 686
+ 687
+ 688
+ 689
+ 690
+ 691
+ 692
+ 693
+ 694
+ 695
+ 696
+ 697
+ 698
+ 699
+ 700
+ 701
+ 702
+ 703
+ 704
+ 705
+ 706
+ 707
+ 708
+ 709
+ 710
+ 711
+ 712
+ 713
+ 714
+ 715
+ 716
+ 717
+ 718
+ 719
+ 720
+ 721
+ 722
+ 723
+ 724
+ 725
+ 726
+ 727
+ 728
+ 729
+ 730
+ 731
+ 732
+ 733
+ 734
+ 735
+ 736
+ 737
+ 738
+ 739
+ 740
+ 741
+ 742
+ 743
+ 744
+ 745
+ 746
+ 747
+ 748
+ 749
+ 750
+ 751
+ 752
+ 753
+ 754
+ 755
+ 756
+ 757
+ 758
+ 759
+ 760
+ 761
+ 762
+ 763
+ 764
+ 765
+ 766
+ 767
+ 768
+ 769
+ 770
+ 771
+ 772
+ 773
+ 774
+ 775
+ 776
+ 777
+ 778
+ 779
+ 780
+ 781
+ 782
+ 783
+ 784
+ 785
+ 786
+ 787
+ 788
+ 789
+ 790
+ 791
+ 792
+ 793
+ 794
+ 795
+ 796
+ 797
+ 798
+ 799
+ 800
+ 801
+ 802
+ 803
+ 804
+ 805
+ 806
+ 807
+ 808
+ 809
+ 810
+ 811
+ 812
+ 813
+ 814
+ 815
+ 816
+ 817
+ 818
+ 819
+ 820
+ 821
+ 822
+ 823
+ 824
+ 825
+ 826
+ 827
+ 828
+ 829
+ 830
+ 831
+ 832
+ 833
+ 834
+ 835
+ 836
+ 837
+ 838
+ 839
+ 840
+ 841
+ 842
+ 843
+ 844
+ 845
+ 846
+ 847
+ 848
+ 849
+ 850
+ 851
+ 852
+ 853
+ 854
+ 855
+ 856
+ 857
+ 858
+ 859
+ 860
+ 861
+ 862
+ 863
+ 864
+ 865
+ 866
+ 867
+ 868
+ 869
+ 870
+ 871
+ 872
+ 873
+ 874
+ 875
+ 876
+ 877
+ 878
+ 879
+ 880
+ 881
+ 882
+ 883
+ 884
+ 885
+ 886
+ 887
+ 888
+ 889
+ 890
+ 891
+ 892
+ 893
+ 894
+ 895
+ 896
+ 897
+ 898
+ 899
+ 900
+ 901
+ 902
+ 903
+ 904
+ 905
+ 906
+ 907
+ 908
+ 909
+ 910
+ 911
+ 912
+ 913
+ 914
+ 915
+ 916
+ 917
+ 918
+ 919
+ 920
+ 921
+ 922
+ 923
+ 924
+ 925
+ 926
+ 927
+ 928
+ 929
+ 930
+ 931
+ 932
+ 933
+ 934
+ 935
+ 936
+ 937
+ 938
+ 939
+ 940
+ 941
+ 942
+ 943
+ 944
+ 945
+ 946
+ 947
+ 948
+ 949
+ 950
+ 951
+ 952
+ 953
+ 954
+ 955
+ 956
+ 957
+ 958
+ 959
+ 960
+ 961
+ 962
+ 963
+ 964
+ 965
+ 966
+ 967
+ 968
+ 969
+ 970
+ 971
+ 972
+ 973
+ 974
+ 975
+ 976
+ 977
+ 978
+ 979
+ 980
+ 981
+ 982
+ 983
+ 984
+ 985
+ 986
+ 987
+ 988
+ 989
+ 990
+ 991
+ 992
+ 993
+ 994
+ 995
+ 996
+ 997
+ 998
+ 999
+1000
+1001
+1002
+1003
+1004
+1005
+1006
+1007
+1008
+1009
+1010
+1011
+1012
+1013
+1014
+1015
+1016
+1017
+1018
+1019
+1020
+1021
+1022
+1023
+1024
+1025
+1026
+1027
+1028
+1029
+1030
+1031
+1032
+1033
+1034
+1035
+1036
+1037
+1038
+1039
+1040
+1041
+1042
+1043
+1044
+1045
+1046
+1047
+1048
+1049
+1050
+1051
+1052
+1053
+1054
+1055
+1056
+1057
+1058
+1059
+1060
+1061
+1062
+1063
+1064
+1065
+1066
+1067
+1068
+1069
+1070
+1071
+1072
+1073
+1074
+1075
+1076
+1077
+1078
+1079
+1080
+1081
+1082
+1083
+1084
+1085
+1086
+1087
+1088
+1089
+1090
+1091
+1092
+1093
+1094
+1095
+1096
+1097
+1098
+1099
+1100
+1101
+1102
+1103
+1104
+1105
+1106
+1107
+1108
+1109
+1110
+1111
+1112
+1113
+1114
+1115
+1116
+1117
+1118
+1119
+1120
+1121
+1122
+1123
+1124
+1125
+1126
+1127
+1128
+1129
+1130
+1131
+1132
+1133
+1134
+1135
+1136
+1137
+1138
+1139
+1140
+1141
+1142
+1143
+1144
+1145
+1146
+1147
+1148
+1149
+1150
+1151
+1152
+1153
+1154
+1155
+1156
+1157
+1158
+1159
+1160
+1161
+1162
+1163
+1164
+1165
+1166
+1167
+1168
+1169
+1170
+1171
+1172
+1173
+1174
+1175
+1176
+1177
+1178
+1179
+1180
+1181
+1182
+1183
+1184
+1185
+1186
+1187
+1188
+1189
+1190
+1191
+1192
+1193
+1194
+1195
+1196
+1197
+1198
+1199
+1200
+1201
+1202
+1203
+1204
+1205
+1206
+1207
+1208
+1209
+1210
+1211
+1212
+1213
+1214
+1215
+1216
+1217
+1218
+1219
+1220
+1221
+1222
+1223
+1224
+1225
+1226
+1227
+1228
+1229
+1230
+1231
+1232
+1233
+1234
+1235
+1236
+1237
+1238
+1239
+1240
+1241
+1242
+1243
+1244
+1245
+1246
+1247
+1248
+1249
+1250
+1251
+1252
+1253
+1254
+1255
+1256
+1257
+1258
+1259
+1260
+1261
+1262
+1263
+1264
+1265
+1266
+1267
+1268
+1269
+1270
+1271
+1272
+1273
+1274
+1275
+1276
+1277
+1278
+1279
+1280
+1281
+1282
+1283
+1284
+1285
+1286
+1287
+1288
+1289
+1290
+1291
+1292
+1293
+1294
+1295
+1296
+1297
+1298
+1299
+1300
+1301
+1302
+1303
+1304
+1305
+1306
+1307
+1308
+1309
+1310
+1311
+1312
+1313
+1314
+1315
+1316
+1317
+1318
+1319
+1320
+1321
+1322
+1323
+1324
+1325
+1326
+1327
+1328
+1329
+1330
+1331
+1332
+1333
+1334
+1335
+1336
+1337
+1338
+1339
+1340
+1341
+1342
+1343
+1344
+1345
+1346
+1347
+1348
+1349
+1350
+1351
+1352
+1353
+1354
+1355
+1356
+1357
+1358
+1359
+1360
+1361
+1362
+1363
+1364
+1365
+1366
+1367
+1368
+1369
+1370
+1371
+1372
+1373
+1374
+1375
+1376
+1377
+1378
+1379
+1380
+1381
+1382
+1383
+1384
+1385
+1386
+1387
+1388
+1389
+1390
+1391
+1392
+1393
+1394
+1395
+1396
+1397
+1398
+1399
+1400
+1401
+1402
+1403
+1404
+1405
+1406
+1407
+1408
+1409
+1410
+1411
+1412
+1413
+1414
+1415
+1416
+1417
+1418
+1419
+1420
+1421
+1422
+1423
+1424
+1425
+1426
+1427
+1428
+1429
+1430
+1431
+1432
+1433
+1434
+1435
+1436
+1437
+1438
+1439
+1440
+1441
+1442
+1443
+1444
+1445
+1446
+1447
+1448
+1449
+1450
+1451
+1452
+1453
+1454
+1455
+1456
+1457
+1458
+1459
+1460
+1461
+1462
+1463
+1464
+1465
+1466
+1467
+1468
+1469
+1470
+1471
+1472
+1473
+1474
+1475
+1476
+1477
+1478
+1479
+1480
+1481
+1482
+1483
+1484
+1485
+1486
+1487
+1488
+1489
+1490
+1491
+1492
+1493
+1494
+1495
+1496
+1497
+1498
+1499
+1500
+1501
+1502
+1503
+1504
+1505
+1506
+1507
+1508
+1509
+1510
+1511
+1512
+1513
+1514
+1515
+1516
+1517
+1518
+1519
+1520
+1521
+1522
+1523
+1524
+1525
+1526
+1527
+1528
+1529
+1530
+1531
+1532
+1533
+1534
+1535
+1536
+1537
+1538
+1539
+1540
+1541
+1542
+1543
+1544
+1545
+1546
+1547
+1548
+1549
+1550
+1551
+1552
+1553
+1554
+1555
+1556
+1557
+1558
+1559
+1560
+1561
+1562
+1563
+1564
+1565
+1566
+1567
+1568
+1569
+1570
+1571
+1572
+1573
+1574
+1575
+1576
+1577
+1578
+1579
+1580
+1581
+1582
+1583
+1584
+1585
+1586
+1587
+1588
+1589
+1590
+1591
+1592
+1593
+1594
+1595
+1596
+1597
+1598
+1599
+1600
+1601
+1602
+1603
+1604
+1605
+1606
+1607
+1608
+1609
+1610
+1611
+1612
+1613
+1614
+1615
+1616
+1617
+1618
+1619
+1620
+1621
+1622
+1623
+1624
+1625
+1626
+1627
+1628
+1629
+1630
+1631
+1632
+1633
+1634
+1635
+1636
+1637
+1638
+1639
+1640
+1641
+1642
+1643
+1644
+1645
+1646
+1647
+1648
+1649
+1650
+1651
+1652
+1653
+1654
+1655
+1656
+1657
+1658
+1659
+1660
+1661
+1662
+1663
+1664
+1665
+1666
+1667
+1668
+1669
+1670
+1671
+1672
+1673
+1674
+1675
+1676
+1677
+1678
+1679
+1680
+1681
+1682
+1683
+1684
+1685
+1686
+1687
+1688
+1689
+1690
+1691
+1692
+1693
+1694
+1695
+1696
+1697
+1698
+1699
+1700
+1701
+1702
+1703
+1704
+1705
+1706
+1707
+1708
+1709
+1710
+1711
+1712
+1713
+1714
+1715
+1716
+1717
+1718
+1719
+1720
+1721
+1722
+1723
+1724
+1725
+1726
+1727
+1728
+1729
+1730
+1731
+1732
+1733
+1734
+1735
+1736
+1737
+1738
+1739
+1740
+1741
+1742
+1743
+1744
+1745
+1746
+1747
+1748
+1749
+1750
+1751
+1752
+1753
+1754
+1755
+1756
+1757
+1758
+1759
+1760
+1761
+1762
+1763
+1764
+1765
+1766
+1767
+1768
+1769
+1770
+1771
+1772
+1773
+1774
+1775
+1776
+1777
+1778
+1779
+1780
+1781
+1782
+1783
+1784
+1785
+1786
+1787
+1788
+1789
+1790
+1791
+1792
+1793
+1794
+1795
+1796
+1797
+1798
+1799
+1800
+1801
+1802
+1803
+1804
+1805
+1806
+1807
+1808
+1809
+1810
+1811
+1812
+1813
+1814
+1815
+1816
+1817
+1818
+1819
+1820
+1821
+1822
+1823
+1824
+1825
+1826
+1827
+1828
+1829
+1830
+1831
+1832
+1833
+1834
+1835
+1836
+1837
+1838
+1839
+1840
+1841
+1842
+1843
+1844
+1845
+1846
+1847
+1848
+1849
+1850
+1851
+1852
+1853
+1854
+1855
+1856
+1857
+1858
+1859
+1860
+1861
+1862
+1863
+1864
+1865
+1866
+1867
+1868
+1869
+1870
+1871
+1872
+1873
+1874
+1875
+1876
+1877
+1878
+1879
+1880
+1881
+1882
+1883
+1884
+1885
+1886
+1887
+1888
+1889
+1890
+1891
+1892
+1893
+1894
+1895
+1896
+1897
+1898
+1899
+1900
+1901
+1902
+1903
+1904
+1905
+1906
+1907
+1908
+1909
+1910
+1911
+1912
+1913
+1914
+1915
+1916
+1917
+1918
+1919
+1920
+1921
+1922
+1923
+1924
+1925
+1926
+1927
+1928
+1929
+1930
+1931
+1932
+1933
+1934
+1935
+1936
+1937
+1938
+1939
+1940
+1941
+1942
+1943
+1944
+1945
+1946
+1947
+1948
+1949
+1950
+1951
+1952
+1953
+1954
+1955
+1956
+1957
+1958
+1959
+1960
+1961
+1962
+1963
+1964
+1965
+1966
+1967
+1968
+1969
+1970
+1971
+1972
+1973
+1974
+1975
+1976
+1977
+1978
+1979
+1980
+1981
+1982
+1983
+1984
+1985
+1986
+1987
+1988
+1989
+1990
+1991
+1992
+1993
+1994
+1995
+1996
+1997
+1998
+1999
+2000
+2001
+2002
+2003
+2004
+2005
+2006
+2007
+2008
+2009
+2010
+2011
+2012
+2013
+2014
+2015
+2016
+2017
+2018
+2019
+2020
+2021
+2022
+2023
+2024
+2025
+2026
+2027
+2028
+2029
+2030
+2031
+2032
+2033
+2034
+2035
+2036
+2037
+2038
+2039
+2040
+2041
+2042
+2043
+2044
+2045
+2046
+2047
+2048
+2049
+2050
+2051
+2052
+2053
+2054
+2055
+2056
+2057
+2058
+2059
+2060
+2061
+2062
+2063
+2064
+2065
+2066
+2067
+2068
+2069
+2070
+2071
+2072
+2073
+2074
+2075
+2076
+2077
+2078
+2079
+2080
+2081
+2082
+2083
+2084
+2085
+2086
+2087
+2088
+2089
+2090
+2091
+2092
+2093
+2094
+2095
+2096
+2097
+2098
+2099
+2100
+2101
+2102
+2103
+2104
+2105
+2106
+2107
+2108
+2109
+2110
+2111
+2112
+2113
+2114
+2115
+2116
+2117
+2118
+2119
+2120
+2121
+2122
+2123
+2124
+2125
+2126
+2127
+2128
+2129
+2130
+2131
+2132
+2133
+2134
+2135
+2136
+2137
+2138
+2139
+2140
+2141
+2142
+2143
+2144
+2145
+2146
+2147
+2148
+2149
+2150
+2151
+2152
+2153
/* Copyright (C) 2005 Emmanuele Bassi <ebassi@gmail.com>
+ * Copyright (C) 2012-2021 MATE Developers
+ *
+ * This file is part of MATE Utils.
+ *
+ * MATE Utils is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * MATE Utils is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MATE Utils.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+/**
+ * SECTION:gdict-client-context
+ * @short_description: DICT client transport
+ *
+ * #GdictClientContext is an implementation of the #GdictContext interface.
+ * It implements the Dictionary Protocol as defined by the RFC 2229 in order
+ * to connect to a dictionary server.
+ *
+ * You should rarely instantiate this object directely: use an appropriate
+ * #GdictSource instead.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <fcntl.h>
+#include <errno.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <glib.h>
+#include <glib/gi18n-lib.h>
+
+#include "gdict-context-private.h"
+#include "gdict-context.h"
+#include "gdict-client-context.h"
+#include "gdict-enum-types.h"
+#include "gdict-marshal.h"
+#include "gdict-debug.h"
+#include "gdict-utils.h"
+#include "gdict-private.h"
+
+typedef enum {
+  CMD_CLIENT,
+  CMD_SHOW_DB,
+  CMD_SHOW_STRAT,
+  CMD_SHOW_INFO,        /* not implemented */
+  CMD_SHOW_SERVER,	/* not implemented */
+  CMD_MATCH,
+  CMD_DEFINE,
+  CMD_STATUS,		/* not implemented */
+  CMD_OPTION_MIME,	/* not implemented */
+  CMD_AUTH,		/* not implemented */
+  CMD_HELP,		/* not implemented */
+  CMD_QUIT,
+
+  CMD_INVALID
+} GdictCommandType;
+#define IS_VALID_CMD(cmd)	(((cmd) >= CMD_CLIENT) || ((cmd) < CMD_INVALID))
+
+/* command strings: keep synced with the enum above! */
+static const gchar *dict_command_strings[] = {
+  "CLIENT",
+  "SHOW DB",
+  "SHOW STRAT",
+  "SHOW INFO",
+  "SHOW SERVER",
+  "MATCH",
+  "DEFINE",
+  "STATUS",
+  "OPTION MIME",
+  "AUTH",
+  "HELP",
+  "QUIT",
+
+  NULL
+};
+
+/* command stata */
+enum
+{
+  S_START,
+
+  S_STATUS,
+  S_DATA,
+
+  S_FINISH
+};
+
+typedef struct
+{
+  GdictCommandType cmd_type;
+
+  gchar *cmd_string;
+  guint state;
+
+  /* optional parameters passed to the command */
+  gchar *database;
+  gchar *strategy;
+  gchar *word;
+
+  /* buffer used to hold the reply from the server */
+  GString *buffer;
+
+  gpointer data;
+  GDestroyNotify data_destroy;
+} GdictCommand;
+
+/* The default string to be passed to the CLIENT command */
+#define GDICT_DEFAULT_CLIENT	"MATE Dictionary (" VERSION ")"
+
+/* Default server:port couple */
+#define GDICT_DEFAULT_HOSTNAME	"dict.org"
+#define GDICT_DEFAULT_PORT	2628
+
+/* make the hostname lookup expire every five minutes */
+#define HOSTNAME_LOOKUP_EXPIRE 	300
+
+/* wait 30 seconds between connection and receiving data on the line */
+#define CONNECTION_TIMEOUT_SEC  30
+
+enum
+{
+  PROP_0,
+
+  PROP_HOSTNAME,
+  PROP_PORT,
+  PROP_STATUS,
+  PROP_CLIENT_NAME
+};
+
+enum
+{
+  CONNECTED,
+  DISCONNECTED,
+
+  LAST_SIGNAL
+};
+
+static guint gdict_client_context_signals[LAST_SIGNAL] = { 0 };
+
+struct _GdictClientContextPrivate
+{
+#ifdef ENABLE_IPV6
+  struct sockaddr_storage sockaddr;
+  struct addrinfo *host6info;
+#else
+  struct sockaddr_in sockaddr;
+#endif
+  struct hostent *hostinfo;
+
+  time_t last_lookup;
+
+  gchar *hostname;
+  gint port;
+
+  GIOChannel *channel;
+  guint source_id;
+  guint timeout_id;
+
+  GdictCommand *command;
+  GQueue *commands_queue;
+
+  gchar *client_name;
+
+  GdictStatusCode status_code;
+
+  guint local_only : 1;
+  guint is_connecting : 1;
+};
+
+static void gdict_client_context_iface_init (GdictContextIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (GdictClientContext,
+                         gdict_client_context,
+                         G_TYPE_OBJECT,
+                         G_ADD_PRIVATE (GdictClientContext)<--- There is an unknown macro here somewhere. Configuration is required. If G_ADD_PRIVATE is a macro then please configure it.
+                         G_IMPLEMENT_INTERFACE (GDICT_TYPE_CONTEXT,
+                                                gdict_client_context_iface_init));
+
+/* GObject methods */
+static void gdict_client_context_set_property (GObject      *object,
+					       guint         prop_id,
+					       const GValue *value,
+					       GParamSpec   *pspec);
+static void gdict_client_context_get_property (GObject      *object,
+					       guint         prop_id,
+					       GValue       *value,
+					       GParamSpec   *pspec);
+static void gdict_client_context_finalize     (GObject      *object);
+
+/* GdictContext methods */
+static gboolean gdict_client_context_get_databases     (GdictContext  *context,
+						        GError       **error);
+static gboolean gdict_client_context_get_strategies    (GdictContext  *context,
+						        GError       **error);
+static gboolean gdict_client_context_define_word       (GdictContext  *context,
+						        const gchar   *database,
+						        const gchar   *word,
+						        GError       **error);
+static gboolean gdict_client_context_match_word        (GdictContext  *context,
+						        const gchar   *database,
+						        const gchar   *strategy,
+						        const gchar   *word,
+						        GError       **error);
+
+static void     gdict_client_context_clear_hostinfo    (GdictClientContext  *context);
+static gboolean gdict_client_context_lookup_server     (GdictClientContext  *context,
+						        GError             **error);
+static gboolean gdict_client_context_io_watch_cb       (GIOChannel    *source,
+						        GIOCondition   condition,
+						        GdictClientContext  *context);
+static gboolean gdict_client_context_parse_line        (GdictClientContext  *context,
+						        const gchar         *buffer);
+static void     gdict_client_context_disconnect        (GdictClientContext  *context);
+static void     gdict_client_context_force_disconnect  (GdictClientContext  *context);
+static void     gdict_client_context_real_connected    (GdictClientContext  *context);
+static void     gdict_client_context_real_disconnected (GdictClientContext  *context);
+
+static GdictCommand *gdict_command_new  (GdictCommandType  cmd_type);
+static void          gdict_command_free (GdictCommand     *cmd);
+
+GQuark
+gdict_client_context_error_quark (void)
+{
+  return g_quark_from_static_string ("gdict-client-context-error-quark");
+}
+
+static void
+gdict_client_context_iface_init (GdictContextIface *iface)
+{
+  iface->get_databases = gdict_client_context_get_databases;
+  iface->get_strategies = gdict_client_context_get_strategies;
+  iface->match_word = gdict_client_context_match_word;
+  iface->define_word = gdict_client_context_define_word;
+}
+
+static void
+gdict_client_context_class_init (GdictClientContextClass *klass)
+{
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+  gobject_class->set_property = gdict_client_context_set_property;
+  gobject_class->get_property = gdict_client_context_get_property;
+  gobject_class->finalize = gdict_client_context_finalize;
+
+  g_object_class_override_property (gobject_class,
+		  		    GDICT_CONTEXT_PROP_LOCAL_ONLY,
+				    "local-only");
+
+  /**
+   * GdictClientContext:client-name
+   *
+   * The name of the client using this context; it will be advertised when
+   * connecting to the dictionary server.
+   *
+   * Since: 1.0
+   */
+  g_object_class_install_property (gobject_class,
+  				   PROP_CLIENT_NAME,
+  				   g_param_spec_string ("client-name",
+  				   			_("Client Name"),
+  				   			_("The name of the client of the context object"),
+  				   			NULL,
+  				   			(G_PARAM_READABLE | G_PARAM_WRITABLE)));
+  /**
+   * GdictClientContext:hostname
+   *
+   * The hostname of the dictionary server to connect to.
+   *
+   * Since: 1.0
+   */
+  g_object_class_install_property (gobject_class,
+  				   PROP_HOSTNAME,
+  				   g_param_spec_string ("hostname",
+  				   			_("Hostname"),
+  				   			_("The hostname of the dictionary server to connect to"),
+  				   			NULL,
+  				   			(G_PARAM_READABLE | G_PARAM_WRITABLE)));
+  /**
+   * GdictClientContext:port
+   *
+   * The port of the dictionary server to connect to.
+   *
+   * Since: 1.0
+   */
+  g_object_class_install_property (gobject_class,
+  				   PROP_PORT,
+  				   g_param_spec_uint ("port",
+  				   		      _("Port"),
+  				   		      _("The port of the dictionary server to connect to"),
+  				   		      0,
+  				   		      65535,
+  				   		      GDICT_DEFAULT_PORT,
+  				   		      (G_PARAM_READABLE | G_PARAM_WRITABLE)));
+  /**
+   * GdictClientContext:status
+   *
+   * The status code as returned by the dictionary server.
+   *
+   * Since: 1.0
+   */
+  g_object_class_install_property (gobject_class,
+  				   PROP_STATUS,
+  				   g_param_spec_enum ("status",
+  				   		      _("Status"),
+  				   		      _("The status code as returned by the dictionary server"),
+  				   		      GDICT_TYPE_STATUS_CODE,
+  				   		      GDICT_STATUS_INVALID,
+  				   		      G_PARAM_READABLE));
+
+  /**
+   * GdictClientContext::connected
+   * @client: the object which received the signal
+   *
+   * Emitted when a #GdictClientContext has successfully established a
+   * connection with a dictionary server.
+   *
+   * Since: 1.0
+   */
+  gdict_client_context_signals[CONNECTED] =
+    g_signal_new ("connected",
+                  G_OBJECT_CLASS_TYPE (gobject_class),
+                  G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (GdictClientContextClass, connected),
+                  NULL, NULL,
+                  gdict_marshal_VOID__VOID,
+                  G_TYPE_NONE, 0);
+  /**
+   * GdictClientContext::disconnected
+   * @client: the object which received the signal
+   *
+   * Emitted when a #GdictClientContext has disconnected from a dictionary
+   * server.
+   *
+   * Since: 1.0
+   */
+  gdict_client_context_signals[DISCONNECTED] =
+    g_signal_new ("disconnected",
+                  G_OBJECT_CLASS_TYPE (gobject_class),
+                  G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (GdictClientContextClass, disconnected),
+                  NULL, NULL,
+                  gdict_marshal_VOID__VOID,
+                  G_TYPE_NONE, 0);
+
+  klass->connected = gdict_client_context_real_connected;
+  klass->disconnected = gdict_client_context_real_disconnected;
+}
+
+static void
+gdict_client_context_init (GdictClientContext *context)
+{
+  GdictClientContextPrivate *priv;
+
+  priv = gdict_client_context_get_instance_private (context);
+  context->priv = priv;
+
+  priv->hostname = NULL;
+  priv->port = 0;
+
+  priv->hostinfo = NULL;
+#ifdef ENABLE_IPV6
+  priv->host6info = NULL;
+#endif
+
+  priv->last_lookup = (time_t) -1;
+
+  priv->is_connecting = FALSE;
+  priv->local_only = FALSE;
+
+  priv->status_code = GDICT_STATUS_INVALID;
+
+  priv->client_name = NULL;
+
+  priv->command = NULL;
+  priv->commands_queue = g_queue_new ();
+}
+
+static void
+gdict_client_context_set_property (GObject      *object,
+				   guint         prop_id,
+				   const GValue *value,
+				   GParamSpec   *pspec)
+{
+  GdictClientContextPrivate *priv = gdict_client_context_get_instance_private (GDICT_CLIENT_CONTEXT (object));
+
+  switch (prop_id)
+    {
+    case PROP_HOSTNAME:
+      g_free (priv->hostname);
+      priv->hostname = g_strdup (g_value_get_string (value));
+      gdict_client_context_clear_hostinfo (GDICT_CLIENT_CONTEXT (object));
+      break;
+    case PROP_PORT:
+      priv->port = g_value_get_uint (value);
+      break;
+    case PROP_CLIENT_NAME:
+      g_free (priv->client_name);
+      priv->client_name = g_strdup (g_value_get_string (value));
+      break;
+    case GDICT_CONTEXT_PROP_LOCAL_ONLY:
+      priv->local_only = (g_value_get_boolean (value) != FALSE);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+gdict_client_context_get_property (GObject    *object,
+				   guint       prop_id,
+				   GValue     *value,
+				   GParamSpec *pspec)
+{
+  GdictClientContextPrivate *priv = gdict_client_context_get_instance_private (GDICT_CLIENT_CONTEXT (object));
+
+  switch (prop_id)
+    {
+    case PROP_STATUS:
+      g_value_set_enum (value, priv->status_code);
+      break;
+    case PROP_HOSTNAME:
+      g_value_set_string (value, priv->hostname);
+      break;
+    case PROP_PORT:
+      g_value_set_uint (value, priv->port);
+      break;
+    case PROP_CLIENT_NAME:
+      g_value_set_string (value, priv->client_name);
+      break;
+    case GDICT_CONTEXT_PROP_LOCAL_ONLY:
+      g_value_set_boolean (value, priv->local_only);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+gdict_client_context_finalize (GObject *object)
+{
+  GdictClientContext *context = GDICT_CLIENT_CONTEXT (object);
+  GdictClientContextPrivate *priv = context->priv;
+
+  /* force disconnection */
+  gdict_client_context_force_disconnect (context);
+
+  gdict_command_free (priv->command);
+
+  if (priv->commands_queue)
+    {
+      g_queue_free_full (priv->commands_queue,
+                         (GDestroyNotify) gdict_command_free);
+      priv->commands_queue = NULL;
+    }
+
+  g_free (priv->client_name);
+  g_free (priv->hostname);
+
+#ifdef ENABLE_IPV6
+  if (priv->host6info)
+    freeaddrinfo (priv->host6info);
+#endif
+
+  /* chain up parent's finalize method */
+  G_OBJECT_CLASS (gdict_client_context_parent_class)->finalize (object);
+}
+
+/**
+ * gdict_client_context_new:
+ * @hostname: the hostname of a dictionary server, or %NULL for the
+ *    default server
+ * @port: port to be used when connecting to the dictionary server,
+ *    or -1 for the default port
+ *
+ * Creates a new #GdictClientContext object for @hostname. Use this
+ * object to connect and query the dictionary server using the Dictionary
+ * Protocol as defined by RFC 2229.
+ *
+ * Return value: the newly created #GdictClientContext object.  You should
+ *   free it using g_object_unref().
+ */
+GdictContext *
+gdict_client_context_new (const gchar *hostname,
+			  gint         port)
+{
+  return g_object_new (GDICT_TYPE_CLIENT_CONTEXT,
+                       "hostname", (hostname != NULL ? hostname : GDICT_DEFAULT_HOSTNAME),
+                       "port", (port != -1 ? port : GDICT_DEFAULT_PORT),
+                       "client-name", GDICT_DEFAULT_CLIENT,
+                       NULL);
+}
+
+/**
+ * gdict_client_context_set_hostname:
+ * @context: a #GdictClientContext
+ * @hostname: the hostname of a Dictionary server, or %NULL
+ *
+ * Sets @hostname as the hostname of the dictionary server to be used.
+ * If @hostname is %NULL, the default dictionary server will be used.
+ */
+void
+gdict_client_context_set_hostname (GdictClientContext *context,
+				   const gchar        *hostname)
+{
+  g_return_if_fail (GDICT_IS_CLIENT_CONTEXT (context));
+
+  g_object_set (G_OBJECT (context),
+                "hostname", (hostname != NULL ? hostname : GDICT_DEFAULT_HOSTNAME),
+                NULL);
+}
+
+/**
+ * gdict_client_context_get_hostname:
+ * @context: a #GdictClientContext
+ *
+ * Gets the hostname of the dictionary server used by @context.
+ *
+ * Return value: the hostname of a dictionary server. The returned string is
+ *   owned by the #GdictClientContext object and should never be modified or
+ *   freed.
+ */
+const gchar *
+gdict_client_context_get_hostname (GdictClientContext *context)
+{
+  gchar *hostname;
+
+  g_return_val_if_fail (GDICT_IS_CLIENT_CONTEXT (context), NULL);
+
+  g_object_get (G_OBJECT (context), "hostname", &hostname, NULL);
+
+  return hostname;
+}
+
+/**
+ * gdict_client_context_set_port:
+ * @context: a #GdictClientContext
+ * @port: port of the dictionary server to be used, or -1
+ *
+ * Sets the port of the dictionary server to be used when connecting.
+ *
+ * If @port is -1, the default port will be used.
+ */
+void
+gdict_client_context_set_port (GdictClientContext *context,
+			       gint                port)
+{
+  g_return_if_fail (GDICT_IS_CLIENT_CONTEXT (context));
+
+  g_object_set (G_OBJECT (context),
+                "port", (port != -1 ? port : GDICT_DEFAULT_PORT),
+                NULL);
+}
+
+/**
+ * gdict_client_context_get_port:
+ * @context: a #GdictClientContext
+ *
+ * Gets the port of the dictionary server used by @context.
+ *
+ * Return value: the number of the port.
+ */
+guint
+gdict_client_context_get_port (GdictClientContext *context)
+{
+  guint port;
+
+  g_return_val_if_fail (GDICT_IS_CLIENT_CONTEXT (context), -1);
+
+  g_object_get (G_OBJECT (context), "port", &port, NULL);
+
+  return port;
+}
+
+/**
+ * gdict_client_context_set_client:
+ * @context: a #GdictClientContext
+ * @client: the client name to use, or %NULL
+ *
+ * Sets @client as the client name to be used when advertising ourselves when
+ * a connection the the dictionary server has been established.
+ * If @client is %NULL, the default client name will be used.
+ */
+void
+gdict_client_context_set_client (GdictClientContext *context,
+				 const gchar        *client)
+{
+  g_return_if_fail (GDICT_IS_CLIENT_CONTEXT (context));
+
+  g_object_set (G_OBJECT (context),
+                "client-name", (client != NULL ? client : GDICT_DEFAULT_CLIENT),
+                NULL);
+}
+
+/**
+ * gdict_client_context_get_client:
+ * @context: a #GdictClientContext
+ *
+ * Gets the client name used by @context. See gdict_client_context_set_client().
+ *
+ * Return value: the client name. The returned string is owned by the
+ *   #GdictClientContext object and should never be modified or freed.
+ */
+const gchar *
+gdict_client_context_get_client (GdictClientContext *context)
+{
+  gchar *client_name;
+
+  g_return_val_if_fail (GDICT_IS_CLIENT_CONTEXT (context), NULL);
+
+  g_object_get (G_OBJECT (context), "client-name", &client_name, NULL);
+
+  return client_name;
+}
+
+/* creates a new command to be sent to the dictionary server */
+static GdictCommand *
+gdict_command_new (GdictCommandType cmd_type)
+{
+  GdictCommand *retval;
+
+  g_assert (IS_VALID_CMD (cmd_type));
+
+  retval = g_slice_new0 (GdictCommand);
+
+  retval->cmd_type = cmd_type;
+  retval->state = S_START;
+
+  return retval;
+}
+
+static void
+gdict_command_free (GdictCommand *cmd)
+{
+  if (!cmd)
+    return;
+
+  g_free (cmd->cmd_string);
+
+  switch (cmd->cmd_type)
+    {
+    case CMD_CLIENT:
+    case CMD_QUIT:
+      break;
+    case CMD_SHOW_DB:
+    case CMD_SHOW_STRAT:
+      break;
+    case CMD_MATCH:
+      g_free (cmd->database);
+      g_free (cmd->strategy);
+      g_free (cmd->word);
+      break;
+    case CMD_DEFINE:
+      g_free (cmd->database);
+      g_free (cmd->word);
+      break;
+    default:
+      break;
+    }
+
+  if (cmd->buffer)
+    g_string_free (cmd->buffer, TRUE);
+
+  if (cmd->data_destroy)
+    cmd->data_destroy (cmd->data);
+
+  g_slice_free (GdictCommand, cmd);
+}
+
+/* push @command into the head of the commands queue; the command queue is
+ * a FIFO-like pipe: commands go into the head and are retrieved from the
+ * tail.
+ */
+static gboolean
+gdict_client_context_push_command (GdictClientContext *context,
+                                   GdictCommand       *command)
+{
+  GdictClientContextPrivate *priv;
+
+  g_assert (GDICT_IS_CLIENT_CONTEXT (context));
+  g_assert (command != NULL);
+
+  priv = context->priv;
+
+  /* avoid pushing a command twice */
+  if (g_queue_find (priv->commands_queue, command))
+    {
+      g_warning ("gdict_client_context_push_command() called on a command already in queue\n");
+      return FALSE;
+    }
+
+  GDICT_NOTE (DICT, "Pushing command ('%s') into the queue...",
+              dict_command_strings[command->cmd_type]);
+
+  g_queue_push_head (priv->commands_queue, command);
+
+  return TRUE;
+}
+
+static GdictCommand *
+gdict_client_context_pop_command (GdictClientContext *context)
+{
+  GdictClientContextPrivate *priv;
+  GdictCommand *retval;
+
+  g_assert (GDICT_IS_CLIENT_CONTEXT (context));
+
+  priv = context->priv;
+
+  retval = (GdictCommand *) g_queue_pop_tail (priv->commands_queue);
+  if (!retval)
+    return NULL;
+
+  GDICT_NOTE (DICT, "Getting command ('%s') from the queue...",
+              dict_command_strings[retval->cmd_type]);
+
+  return retval;
+}
+
+/* send @command on the wire */
+static gboolean
+gdict_client_context_send_command (GdictClientContext  *context,
+                                   GdictCommand        *command,
+                                   GError             **error)
+{
+  GdictClientContextPrivate *priv;
+  GError *write_error;
+  gsize written_bytes;
+  GIOStatus res;
+
+  g_assert (GDICT_IS_CLIENT_CONTEXT (context));
+  g_assert (command != NULL && command->cmd_string != NULL);
+
+  priv = context->priv;
+
+  if (!priv->channel)
+    {
+      GDICT_NOTE (DICT, "No connection established");
+
+      g_set_error (error, GDICT_CLIENT_CONTEXT_ERROR,
+                   GDICT_CLIENT_CONTEXT_ERROR_NO_CONNECTION,
+                   _("No connection to the dictionary server at '%s:%d'"),
+                   priv->hostname,
+                   priv->port);
+
+      return FALSE;
+    }
+
+  write_error = NULL;
+  res = g_io_channel_write_chars (priv->channel,
+                                  command->cmd_string,
+                                  -1,
+                                  &written_bytes,
+                                  &write_error);
+  if (res != G_IO_STATUS_NORMAL)
+    {
+      g_propagate_error (error, write_error);
+
+      return FALSE;
+    }
+
+  /* force flushing of the write buffer */
+  g_io_channel_flush (priv->channel, NULL);
+
+  GDICT_NOTE (DICT, "Wrote %"G_GSIZE_FORMAT" bytes to the channel", written_bytes);
+
+  return TRUE;
+}
+
+/* gdict_client_context_run_command: runs @command inside @context; this
+ * function builds the command string and then passes it to the dictionary
+ * server.
+ */
+static gboolean
+gdict_client_context_run_command (GdictClientContext  *context,
+                                  GdictCommand        *command,
+                                  GError             **error)
+{
+  GdictClientContextPrivate *priv;
+  gchar *payload;
+  GError *send_error;
+  gboolean res;
+
+  g_assert (GDICT_IS_CLIENT_CONTEXT (context));
+  g_assert (command != NULL);
+  g_assert (IS_VALID_CMD (command->cmd_type));
+
+  GDICT_NOTE (DICT, "GdictCommand command =\n"
+                    "{\n"
+                    "  .cmd_type = '%02d' ('%s');\n"
+                    "  .database = '%s';\n"
+                    "  .strategy = '%s';\n"
+                    "  .word     = '%s';\n"
+                    "}\n",
+              command->cmd_type, dict_command_strings[command->cmd_type],
+              command->database ? command->database : "<none>",
+              command->strategy ? command->strategy : "<none>",
+              command->word ? command->word : "<none>");
+
+  priv = context->priv;
+
+  g_assert (priv->command == NULL);
+
+  priv->command = command;
+
+  /* build the command string to be sent to the server */
+  switch (command->cmd_type)
+    {
+    case CMD_CLIENT:
+      payload = g_shell_quote (priv->client_name);
+      command->cmd_string = g_strdup_printf ("%s %s\r\n",
+                                             dict_command_strings[CMD_CLIENT],
+                                             payload);
+      g_free (payload);
+      break;
+    case CMD_QUIT:
+      command->cmd_string = g_strdup_printf ("%s\r\n",
+                                             dict_command_strings[CMD_QUIT]);
+      break;
+    case CMD_SHOW_DB:
+      command->cmd_string = g_strdup_printf ("%s\r\n",
+                                             dict_command_strings[CMD_SHOW_DB]);
+      break;
+    case CMD_SHOW_STRAT:
+      command->cmd_string = g_strdup_printf ("%s\r\n",
+                                             dict_command_strings[CMD_SHOW_STRAT]);
+      break;
+    case CMD_MATCH:
+      g_assert (command->word);
+      payload = g_shell_quote (command->word);
+      command->cmd_string = g_strdup_printf ("%s %s %s %s\r\n",
+                                             dict_command_strings[CMD_MATCH],
+                                             (command->database != NULL ? command->database : "!"),
+                                             (command->strategy != NULL ? command->strategy : "*"),
+                                             payload);
+      g_free (payload);
+      break;
+    case CMD_DEFINE:
+      g_assert (command->word);
+      payload = g_shell_quote (command->word);
+      command->cmd_string = g_strdup_printf ("%s %s %s\r\n",
+                                             dict_command_strings[CMD_DEFINE],
+                                             (command->database != NULL ? command->database : "!"),
+                                             payload);
+      g_free (payload);
+      break;
+    default:
+      g_assert_not_reached ();
+      break;
+    }
+
+  g_assert (command->cmd_string);
+
+  GDICT_NOTE (DICT, "Sending command ('%s') to the server",
+              dict_command_strings[command->cmd_type]);
+
+  send_error = NULL;
+  res = gdict_client_context_send_command (context, command, &send_error);
+  if (!res)
+    {
+      g_propagate_error (error, send_error);
+
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
+/* we use this signal to advertise ourselves to the dictionary server */
+static void
+gdict_client_context_real_connected (GdictClientContext *context)
+{
+  GdictCommand *cmd;
+
+  cmd = gdict_command_new (CMD_CLIENT);
+  cmd->state = S_FINISH;
+
+  /* the CLIENT command should be the first one in our queue, so we place
+   * it above all other commands the user might have issued between the
+   * first and the emission of the "connected" signal, by calling it
+   * directely.
+   */
+  gdict_client_context_run_command (context, cmd, NULL);
+}
+
+static void
+clear_command_queue (GdictClientContext *context)
+{
+  GdictClientContextPrivate *priv = context->priv;
+
+  if (priv->commands_queue)
+    {
+      g_queue_free_full (priv->commands_queue,
+                         (GDestroyNotify) gdict_command_free);
+    }
+
+  /* renew */
+  priv->commands_queue = g_queue_new ();
+}
+
+/* force a disconnection from the server */
+static void
+gdict_client_context_force_disconnect (GdictClientContext *context)
+{
+  GdictClientContextPrivate *priv = context->priv;
+
+  if (priv->timeout_id)
+    {
+      g_source_remove (priv->timeout_id);
+      priv->timeout_id = 0;
+    }
+
+  if (priv->source_id)
+    {
+      g_source_remove (priv->source_id);
+      priv->source_id = 0;
+    }
+
+  if (priv->channel)
+    {
+      g_io_channel_shutdown (priv->channel, TRUE, NULL);
+      g_io_channel_unref (priv->channel);
+
+      priv->channel = NULL;
+    }
+
+  if (priv->command)
+    {
+      gdict_command_free (priv->command);
+      priv->command = NULL;
+    }
+
+  clear_command_queue (context);
+}
+
+static void
+gdict_client_context_real_disconnected (GdictClientContext *context)
+{
+  gdict_client_context_force_disconnect (context);
+}
+
+/* clear the lookup data */
+static void
+gdict_client_context_clear_hostinfo (GdictClientContext *context)
+{
+  GdictClientContextPrivate *priv;
+
+  g_assert (GDICT_IS_CLIENT_CONTEXT (context));
+
+  priv = context->priv;
+
+#ifdef ENABLE_IPV6
+  if (!priv->host6info)
+    return;
+#endif
+
+  if (!priv->hostinfo)
+    return;
+
+#ifdef ENABLE_IPV6
+  freeaddrinfo (priv->host6info);
+#endif
+  priv->hostinfo = NULL;
+}
+
+/* gdict_client_context_lookup_server: perform an hostname lookup in order to
+ * connect to the dictionary server
+ */
+static gboolean
+gdict_client_context_lookup_server (GdictClientContext  *context,
+                                    GError             **error)
+{
+  GdictClientContextPrivate *priv;
+  gboolean is_expired = FALSE;
+  time_t now;
+
+  g_assert (GDICT_IS_CLIENT_CONTEXT (context));
+
+  priv = context->priv;
+
+  /* we need the hostname, at this point */
+  g_assert (priv->hostname != NULL);
+
+  time (&now);
+  if (now >= (priv->last_lookup + HOSTNAME_LOOKUP_EXPIRE))
+    is_expired = TRUE;
+
+  /* we already have resolved the hostname */
+#ifdef ENABLE_IPV6
+  if (priv->host6info && !is_expired)
+    return TRUE;
+#endif
+
+  if (priv->hostinfo && !is_expired)
+    return TRUE;
+
+  /* clear any previously acquired lookup data */
+  gdict_client_context_clear_hostinfo (context);
+
+  GDICT_NOTE (DICT, "Looking up hostname '%s'", priv->hostname);
+
+#ifdef ENABLE_IPV6
+  if (_gdict_has_ipv6 ())
+    {
+      struct addrinfo hints, *res;
+
+      GDICT_NOTE (DICT, "Hostname '%s' look-up (using IPv6)", priv->hostname);
+
+      memset (&hints, 0, sizeof (hints));
+      hints.ai_socktype = SOCK_STREAM;
+
+      if (getaddrinfo (priv->hostname, NULL, &hints, &(priv->host6info)) == 0)
+        {
+          for (res = priv->host6info; res; res = res->ai_next)
+            if (res->ai_family == AF_INET6 || res->ai_family == AF_INET)
+              break;
+
+          if (!res)
+            {
+              g_set_error (error, GDICT_CLIENT_CONTEXT_ERROR,
+                           GDICT_CLIENT_CONTEXT_ERROR_LOOKUP,
+                           _("Lookup failed for hostname '%s': no suitable resources found"),
+                           priv->hostname);
+
+              return FALSE;
+            }
+          else
+	    {
+	      if (res->ai_family == AF_INET6)
+	        memcpy (&((struct sockaddr_in6 *) &priv->sockaddr)->sin6_addr,
+	                &((struct sockaddr_in6 *) res->ai_addr)->sin6_addr,
+	                sizeof (struct in6_addr));
+
+	      if (res->ai_family == AF_INET)
+		memcpy (&((struct sockaddr_in *) &priv->sockaddr)->sin_addr,
+		        &((struct sockaddr_in *) res->ai_addr)->sin_addr,
+		        sizeof (struct in_addr));
+
+	      priv->sockaddr.ss_family = res->ai_family;
+
+	      GDICT_NOTE (DICT, "Hostname '%s' found (using IPv6)",
+                          priv->hostname);
+
+	      priv->last_lookup = time (NULL);
+
+	      return TRUE;
+	    }
+        }
+      else
+        {
+          g_set_error (error, GDICT_CLIENT_CONTEXT_ERROR,
+                       GDICT_CLIENT_CONTEXT_ERROR_LOOKUP,
+                       _("Lookup failed for host '%s': %s"),
+                       priv->hostname,
+                       gai_strerror (errno));
+
+          return FALSE;
+        }
+    }
+  else
+    {
+#endif /* ENABLE_IPV6 */
+      /* if we don't support IPv6, fallback to usual IPv4 lookup */
+
+      GDICT_NOTE (DICT, "Hostname '%s' look-up (using IPv4)", priv->hostname);
+
+      ((struct sockaddr_in *) &priv->sockaddr)->sin_family = AF_INET;
+
+      priv->hostinfo = gethostbyname (priv->hostname);
+      if (priv->hostinfo)
+        {
+          memcpy (&((struct sockaddr_in *) &(priv->sockaddr))->sin_addr,
+                  priv->hostinfo->h_addr,
+                  priv->hostinfo->h_length);
+
+          GDICT_NOTE (DICT, "Hostname '%s' found (using IPv4)",
+		      priv->hostname);
+
+	  priv->last_lookup = time (NULL);
+
+          return TRUE;
+        }
+      else
+        {
+          g_set_error (error, GDICT_CLIENT_CONTEXT_ERROR,
+                       GDICT_CLIENT_CONTEXT_ERROR_LOOKUP,
+                       _("Lookup failed for host '%s': host not found"),
+                       priv->hostname);
+
+          return FALSE;
+        }
+#ifdef ENABLE_IPV6
+    }
+#endif
+
+  g_assert_not_reached ();
+
+  return FALSE;
+}
+
+/* gdict_client_context_parse_line: parses a line from the dictionary server
+ * this is the core of the RFC2229 protocol implementation, here's where
+ * the magic happens.
+ */
+static gboolean
+gdict_client_context_parse_line (GdictClientContext *context,
+			         const gchar        *buffer)
+{
+  GdictClientContextPrivate *priv;
+  GError *server_error = NULL;
+
+  g_assert (GDICT_IS_CLIENT_CONTEXT (context));
+  g_assert (buffer != NULL);
+
+  priv = context->priv;
+
+  GDICT_NOTE (DICT, "parse buffer: '%s'", buffer);
+
+  /* connection is a special case: we don't have a command, so we just
+   * make sure that the server replied with the correct code. WARNING:
+   * the server might be shutting down or not available, so we must
+   * take into account those responses too!
+   */
+  if (!priv->command)
+    {
+      if (priv->status_code == GDICT_STATUS_CONNECT)
+        {
+          /* the server accepts our connection */
+          g_signal_emit (context, gdict_client_context_signals[CONNECTED], 0);
+
+          return TRUE;
+        }
+      else if ((priv->status_code == GDICT_STATUS_SERVER_DOWN) ||
+               (priv->status_code == GDICT_STATUS_SHUTDOWN))
+        {
+          /* the server is shutting down or is not available */
+          g_set_error (&server_error, GDICT_CLIENT_CONTEXT_ERROR,
+                       GDICT_CLIENT_CONTEXT_ERROR_SERVER_DOWN,
+                       _("Unable to connect to the dictionary server "
+                         "at '%s:%d'. The server replied with "
+                         "code %d (server down)"),
+                       priv->hostname,
+                       priv->port,
+                       priv->status_code);
+
+          g_signal_emit_by_name (context, "error", server_error);
+
+          g_error_free (server_error);
+
+          return TRUE;
+        }
+      else
+        {
+          GError *parse_error = NULL;
+
+          g_set_error (&parse_error, GDICT_CONTEXT_ERROR,
+                       GDICT_CONTEXT_ERROR_PARSE,
+                       _("Unable to parse the dictionary server reply\n: '%s'"),
+                       buffer);
+
+          g_signal_emit_by_name (context, "error", parse_error);
+
+          g_error_free (parse_error);
+
+          return FALSE;
+        }
+    }
+
+  /* disconnection is another special case: the server replies with code
+   * 221, and closes the connection; we emit the "disconnected" signal
+   * and close the connection on our side.
+   */
+  if (priv->status_code == GDICT_STATUS_QUIT)
+    {
+      g_signal_emit (context, gdict_client_context_signals[DISCONNECTED], 0);
+
+      return TRUE;
+    }
+
+  /* here we catch all the errors codes that the server might give us */
+  server_error = NULL;
+  switch (priv->status_code)
+    {
+    case GDICT_STATUS_NO_MATCH:
+      g_set_error (&server_error, GDICT_CONTEXT_ERROR,
+                   GDICT_CONTEXT_ERROR_NO_MATCH,
+                   _("No definitions found for '%s'"),
+                   priv->command->word);
+
+      GDICT_NOTE (DICT, "No match: %s", server_error->message);
+
+      g_signal_emit_by_name (context, "error", server_error);
+
+      g_error_free (server_error);
+      server_error = NULL;
+
+      priv->command->state = S_FINISH;
+      break;
+    case GDICT_STATUS_BAD_DATABASE:
+      g_set_error (&server_error, GDICT_CONTEXT_ERROR,
+                   GDICT_CONTEXT_ERROR_INVALID_DATABASE,
+                   _("Invalid database '%s'"),
+                   priv->command->database);
+
+      GDICT_NOTE (DICT, "Bad DB: %s", server_error->message);
+
+      g_signal_emit_by_name (context, "error", server_error);
+
+      g_error_free (server_error);
+      server_error = NULL;
+
+      priv->command->state = S_FINISH;
+      break;
+    case GDICT_STATUS_BAD_STRATEGY:
+      g_set_error (&server_error, GDICT_CONTEXT_ERROR,
+                   GDICT_CONTEXT_ERROR_INVALID_STRATEGY,
+                   _("Invalid strategy '%s'"),
+                   priv->command->strategy);
+
+      GDICT_NOTE (DICT, "Bad strategy: %s", server_error->message);
+
+      g_signal_emit_by_name (context, "error", server_error);
+
+      g_error_free (server_error);
+      server_error = NULL;
+
+      priv->command->state = S_FINISH;
+      break;
+    case GDICT_STATUS_BAD_COMMAND:
+      g_set_error (&server_error, GDICT_CONTEXT_ERROR,
+                   GDICT_CONTEXT_ERROR_INVALID_COMMAND,
+                   _("Bad command '%s'"),
+                   dict_command_strings[priv->command->cmd_type]);
+
+      GDICT_NOTE (DICT, "Bad command: %s", server_error->message);
+
+      g_signal_emit_by_name (context, "error", server_error);
+
+      g_error_free (server_error);
+      server_error = NULL;
+
+      priv->command->state = S_FINISH;
+      break;
+    case GDICT_STATUS_BAD_PARAMETERS:
+      g_set_error (&server_error, GDICT_CONTEXT_ERROR,
+		   GDICT_CONTEXT_ERROR_INVALID_COMMAND,
+		   _("Bad parameters for command '%s'"),
+		   dict_command_strings[priv->command->cmd_type]);
+
+      GDICT_NOTE (DICT, "Bad params: %s", server_error->message);
+
+      g_signal_emit_by_name (context, "error", server_error);
+
+      g_error_free (server_error);
+      server_error = NULL;
+
+      priv->command->state = S_FINISH;
+      break;
+    case GDICT_STATUS_NO_DATABASES_PRESENT:
+      g_set_error (&server_error, GDICT_CONTEXT_ERROR,
+                   GDICT_CONTEXT_ERROR_NO_DATABASES,
+                   _("No databases found on dictionary server at '%s'"),
+                   priv->hostname);
+
+      GDICT_NOTE (DICT, "No DB: %s", server_error->message);
+
+      g_signal_emit_by_name (context, "error", server_error);
+
+      g_error_free (server_error);
+      server_error = NULL;
+
+      priv->command->state = S_FINISH;
+      break;
+    case GDICT_STATUS_NO_STRATEGIES_PRESENT:
+      g_set_error (&server_error, GDICT_CONTEXT_ERROR,
+                   GDICT_CONTEXT_ERROR_NO_STRATEGIES,
+                   _("No strategies found on dictionary server at '%s'"),
+                   priv->hostname);
+
+      GDICT_NOTE (DICT, "No strategies: %s", server_error->message);
+
+      g_signal_emit_by_name (context, "error", server_error);
+
+      g_error_free (server_error);
+      server_error = NULL;
+
+      priv->command->state = S_FINISH;
+      break;
+    default:
+      GDICT_NOTE (DICT, "non-error code: %d", priv->status_code);
+      break;
+    }
+
+  /* server replied with 'ok' or the command has reached its FINISH state,
+   * so now we are clear for destroying the current command and check if
+   * there are other commands on the queue, and run them.
+   */
+  if ((priv->status_code == GDICT_STATUS_OK) ||
+      (priv->command->state == S_FINISH))
+    {
+      GdictCommand *new_command;
+      GError *run_error;
+      GdictCommandType last_cmd;
+
+      last_cmd = priv->command->cmd_type;
+
+      gdict_command_free (priv->command);
+      priv->command = NULL;
+
+      /* notify the end of a command - ignore CLIENT and QUIT commands, as
+       * we issue them ourselves
+       */
+      if ((last_cmd != CMD_CLIENT) && (last_cmd != CMD_QUIT))
+        g_signal_emit_by_name (context, "lookup-end");
+
+      /* pop the next command from the queue */
+      new_command = gdict_client_context_pop_command (context);
+      if (!new_command)
+        {
+          /* if the queue is empty, quit */
+          gdict_client_context_disconnect (context);
+          new_command = gdict_client_context_pop_command (context);
+        }
+
+      run_error = NULL;
+      gdict_client_context_run_command (context, new_command, &run_error);
+      if (run_error)
+        {
+          g_signal_emit_by_name (context, "error", run_error);
+
+          g_error_free (run_error);
+        }
+
+      return TRUE;
+    }
+
+  GDICT_NOTE (DICT, "check command %d ('%s')[state:%d]",
+	      priv->command->cmd_type,
+	      dict_command_strings[priv->command->cmd_type],
+	      priv->command->state);
+
+  /* check command type */
+  switch (priv->command->cmd_type)
+    {
+    case CMD_CLIENT:
+    case CMD_QUIT:
+      break;
+    case CMD_SHOW_DB:
+      if (priv->status_code == GDICT_STATUS_N_DATABASES_PRESENT)
+        {
+          gchar *p;
+
+          priv->command->state = S_DATA;
+
+          p = g_utf8_strchr (buffer, -1, ' ');
+          if (p)
+            p = g_utf8_next_char (p);
+
+          GDICT_NOTE (DICT, "server replied: %d databases found", atoi (p));
+        }
+      else if (0 == strcmp (buffer, "."))
+        priv->command->state = S_FINISH;
+      else
+        {
+          GdictDatabase *db;
+          gchar *name, *full, *p;
+
+          g_assert (priv->command->state == S_DATA);
+
+          /* first token: database name;
+           * second token: database description;
+           */
+          name = (gchar *) buffer;
+          if (!name)
+            break;
+
+          p = g_utf8_strchr (name, -1, ' ');
+	  if (p)
+	    *p = '\0';
+
+	  full = g_utf8_next_char (p);
+
+          if (full[0] == '\"')
+            full = g_utf8_next_char (full);
+
+          p = g_utf8_strchr (full, -1, '\"');
+          if (p)
+            *p = '\0';
+
+          db = _gdict_database_new (name);
+          db->full_name = g_strdup (full);
+
+          g_signal_emit_by_name (context, "database-found", db);
+
+          gdict_database_unref (db);
+        }
+      break;
+    case CMD_SHOW_STRAT:
+      if (priv->status_code == GDICT_STATUS_N_STRATEGIES_PRESENT)
+        {
+          gchar *p;
+
+          priv->command->state = S_DATA;
+
+          p = g_utf8_strchr (buffer, -1, ' ');
+          if (p)
+            p = g_utf8_next_char (p);
+
+          GDICT_NOTE (DICT, "server replied: %d strategies found", atoi (p));
+        }
+      else if (0 == strcmp (buffer, "."))
+        priv->command->state = S_FINISH;
+      else
+        {
+          GdictStrategy *strat;
+          gchar *name, *desc, *p;
+
+          g_assert (priv->command->state == S_DATA);
+
+          name = (gchar *) buffer;
+          if (!name)
+            break;
+
+	  p = g_utf8_strchr (name, -1, ' ');
+          if (p)
+            *p = '\0';
+
+	  desc = g_utf8_next_char (p);
+
+          if (desc[0] == '\"')
+            desc = g_utf8_next_char (desc);
+
+          p = g_utf8_strchr (desc, -1, '\"');
+          if (p)
+            *p = '\0';
+
+          strat = _gdict_strategy_new (name);
+          strat->description = g_strdup (desc);
+
+          g_signal_emit_by_name (context, "strategy-found", strat);
+
+          gdict_strategy_unref (strat);
+        }
+      break;
+    case CMD_DEFINE:
+      if (priv->status_code == GDICT_STATUS_N_DEFINITIONS_RETRIEVED)
+        {
+          GdictDefinition *def;
+          gchar *p;
+
+          priv->command->state = S_STATUS;
+
+          p = g_utf8_strchr (buffer, -1, ' ');
+          if (p)
+            p = g_utf8_next_char (p);
+
+          GDICT_NOTE (DICT, "server replied: %d definitions found", atoi (p));
+
+          def = _gdict_definition_new (atoi (p));
+
+          priv->command->data = def;
+          priv->command->data_destroy = (GDestroyNotify) gdict_definition_unref;
+        }
+      else if (priv->status_code == GDICT_STATUS_WORD_DB_NAME)
+        {
+          GdictDefinition *def;
+          gchar *word, *db_name, *db_full, *p;
+
+	  word = (gchar *) buffer;
+
+	  /* skip the status code */
+	  word = g_utf8_strchr (word, -1, ' ');
+	  word = g_utf8_next_char (word);
+
+          if (word[0] == '\"')
+            word = g_utf8_next_char (word);
+
+          p = g_utf8_strchr (word, -1, '\"');
+          if (p)
+            *p = '\0';
+
+	  p = g_utf8_next_char (p);
+
+          /* the database name is not protected by "" */
+          db_name = g_utf8_next_char (p);
+          if (!db_name)
+            break;
+
+	  p = g_utf8_strchr (db_name, -1, ' ');
+	  if (p)
+	    *p = '\0';
+
+	  p = g_utf8_next_char (p);
+
+          db_full = g_utf8_next_char (p);
+          if (!db_full)
+            break;
+
+          if (db_full[0] == '\"')
+            db_full = g_utf8_next_char (db_full);
+
+          p = g_utf8_strchr (db_full, -1, '\"');
+          if (p)
+            *p = '\0';
+
+          def = (GdictDefinition *) priv->command->data;
+
+	  GDICT_NOTE (DICT, "{ word = '%s', db_name = '%s', db_full = '%s' }",
+		      word,
+		      db_name,
+		      db_full);
+
+          def->word = g_strdup (word);
+          def->database_name = g_strdup (db_name);
+          def->database_full = g_strdup (db_full);
+          def->definition = NULL;
+
+          priv->command->state = S_DATA;
+        }
+      else if (strcmp (buffer, ".") == 0)
+        {
+          GdictDefinition *def;
+	  gint num;
+
+          g_assert (priv->command->state == S_DATA);
+
+          def = (GdictDefinition *) priv->command->data;
+          if (!def)
+            break;
+
+          def->definition = g_string_free (priv->command->buffer, FALSE);
+
+	  /* store the numer of definitions */
+	  num = def->total;
+
+          g_signal_emit_by_name (context, "definition-found", def);
+
+          gdict_definition_unref (def);
+
+          priv->command->buffer = NULL;
+          priv->command->data = _gdict_definition_new (num);
+
+          priv->command->state = S_STATUS;
+        }
+      else
+        {
+          g_assert (priv->command->state == S_DATA);
+
+          if (!priv->command->buffer)
+            priv->command->buffer = g_string_new (NULL);
+
+	  GDICT_NOTE (DICT, "appending to buffer:\n %s", buffer);
+
+          /* TODO - collapse '..' to '.' */
+          g_string_append_printf (priv->command->buffer, "%s\n", buffer);
+        }
+      break;
+    case CMD_MATCH:
+      if (priv->status_code == GDICT_STATUS_N_MATCHES_FOUND)
+        {
+          gchar *p;
+
+          priv->command->state = S_DATA;
+
+          p = g_utf8_strchr (buffer, -1, ' ');
+          if (p)
+            p = g_utf8_next_char (p);
+
+          GDICT_NOTE (DICT, "server replied: %d matches found", atoi (p));
+        }
+      else if (0 == strcmp (buffer, "."))
+        priv->command->state = S_FINISH;
+      else
+        {
+          GdictMatch *match;
+          gchar *word, *db_name, *p;
+
+          g_assert (priv->command->state == S_DATA);
+
+          db_name = (gchar *) buffer;
+          if (!db_name)
+            break;
+
+          p = g_utf8_strchr (db_name, -1, ' ');
+          if (p)
+            *p = '\0';
+
+	  word = g_utf8_next_char (p);
+
+          if (word[0] == '\"')
+            word = g_utf8_next_char (word);
+
+          p = g_utf8_strchr (word, -1, '\"');
+          if (p)
+            *p = '\0';
+
+          match = _gdict_match_new (word);
+          match->database = g_strdup (db_name);
+
+          g_signal_emit_by_name (context, "match-found", match);
+
+          gdict_match_unref (match);
+        }
+      break;
+    default:
+      g_assert_not_reached ();
+      break;
+    }
+
+  return TRUE;
+}
+
+/* retrieve the status code from the server response line */
+static gint
+get_status_code (const gchar *line,
+		 gint         old_status)
+{
+  gchar *status;
+  gint possible_status, retval;
+
+  if (strlen (line) < 3)
+    return 0;
+
+  if (!g_unichar_isdigit (line[0]) ||
+      !g_unichar_isdigit (line[1]) ||
+      !g_unichar_isdigit (line[2]))
+    return 0;
+
+  if (!g_unichar_isspace (line[3]))
+    return 0;
+
+  status = g_strndup (line, 3);
+  possible_status = atoi (status);
+  g_free (status);
+
+  /* status whitelisting: sometimes, a database *cough* moby-thes *cough*
+   * might return a number as first word; we do a small check here for
+   * invalid status codes based on the previously set status; we don't check
+   * the whole line, as we need only to be sure that the status code is
+   * consistent with what we expect.
+   */
+  switch (old_status)
+    {
+    case GDICT_STATUS_WORD_DB_NAME:
+    case GDICT_STATUS_N_MATCHES_FOUND:
+      if (possible_status == GDICT_STATUS_OK)
+	retval = possible_status;
+      else
+        retval = 0;
+      break;
+    case GDICT_STATUS_N_DEFINITIONS_RETRIEVED:
+      if (possible_status == GDICT_STATUS_WORD_DB_NAME)
+	retval = possible_status;
+      else
+	retval = 0;
+      break;
+    default:
+      retval = possible_status;
+      break;
+    }
+
+  return retval;
+}
+
+static gboolean
+gdict_client_context_io_watch_cb (GIOChannel         *channel,
+				  GIOCondition        condition,
+				  GdictClientContext *context)
+{
+  GdictClientContextPrivate *priv;
+
+  g_assert (GDICT_IS_CLIENT_CONTEXT (context));
+  priv = context->priv;
+
+  /* since this is an asynchronous channel, we might end up here
+   * even though the channel has been shut down.
+   */
+  if (!priv->channel)
+    {
+      g_warning ("No channel available\n");
+
+      return FALSE;
+    }
+
+  if (priv->is_connecting)
+    {
+      priv->is_connecting = FALSE;
+
+      if (priv->timeout_id)
+        {
+          g_source_remove (priv->timeout_id);
+          priv->timeout_id = 0;
+        }
+    }
+
+  if (condition & G_IO_ERR)
+    {
+      GError *err = NULL;
+
+      g_set_error (&err, GDICT_CLIENT_CONTEXT_ERROR,
+                   GDICT_CLIENT_CONTEXT_ERROR_SOCKET,
+                   _("Connection failed to the dictionary server at %s:%d"),
+                   priv->hostname,
+                   priv->port);
+
+      g_signal_emit_by_name (context, "error", err);
+
+      g_error_free (err);
+
+      return FALSE;
+    }
+
+  while (1)
+    {
+      GIOStatus res;
+      guint status_code;
+      GError *read_err;
+      gsize len, term;
+      gchar *line;
+      gboolean parse_res;
+
+      /* we might sever the connection while still inside the read loop,
+       * so we must check the state of the channel before actually doing
+       * the line reading, otherwise we'll end up with death, destruction
+       * and chaos on all earth.  oh, and an assertion failed inside
+       * g_io_channel_read_line().
+       */
+      if (!priv->channel)
+        break;
+
+      read_err = NULL;
+      res = g_io_channel_read_line (priv->channel, &line, &len, &term, &read_err);
+      if (res == G_IO_STATUS_ERROR)
+        {
+          if (read_err)
+            {
+              GError *err = NULL;
+
+              g_set_error (&err, GDICT_CLIENT_CONTEXT_ERROR,
+                           GDICT_CLIENT_CONTEXT_ERROR_SOCKET,
+                           _("Error while reading reply from server:\n%s"),
+                           read_err->message);
+
+              g_signal_emit_by_name (context, "error", err);
+
+              g_error_free (err);
+              g_error_free (read_err);
+            }
+
+          gdict_client_context_force_disconnect (context);
+
+          return FALSE;
+        }
+
+      if (len == 0)
+        break;
+
+      /* truncate the line terminator before parsing */
+      line[term] = '\0';
+
+      status_code = get_status_code (line, priv->status_code);
+      if ((status_code == 0) || (GDICT_IS_VALID_STATUS_CODE (status_code)))
+        {
+          priv->status_code = status_code;
+
+          GDICT_NOTE (DICT, "new status = '%d'", priv->status_code);
+        }
+      else
+        priv->status_code = GDICT_STATUS_INVALID;
+
+      /* notify changes only for valid status codes */
+      if (priv->status_code != GDICT_STATUS_INVALID)
+        g_object_notify (G_OBJECT (context), "status");
+
+      parse_res = gdict_client_context_parse_line (context, line);
+      if (!parse_res)
+        {
+          g_free (line);
+
+          g_warning ("Parsing failed");
+
+          gdict_client_context_force_disconnect (context);
+
+          return FALSE;
+        }
+
+      g_free (line);
+    }
+
+  return TRUE;
+}
+
+static gboolean
+check_for_connection (gpointer data)
+{
+  GdictClientContext *context = data;
+
+#if 0
+  g_debug (G_STRLOC ": checking for connection (is connecting:%s)",
+           context->priv->is_connecting ? "true" : "false");
+#endif
+
+  if (context == NULL)
+    return FALSE;
+
+  if (context->priv->is_connecting)
+    {
+      GError *err = NULL;
+
+      GDICT_NOTE (DICT, "Forcing a disconnection due to timeout");
+
+      g_set_error (&err, GDICT_CLIENT_CONTEXT_ERROR,
+                   GDICT_CLIENT_CONTEXT_ERROR_SOCKET,
+                   _("Connection timeout for the dictionary server at '%s:%d'"),
+                   context->priv->hostname,
+                   context->priv->port);
+
+      g_signal_emit_by_name (context, "error", err);
+
+      g_error_free (err);
+
+      gdict_client_context_force_disconnect (context);
+    }
+
+  /* this is a one-off operation */
+  return FALSE;
+}
+
+static gboolean
+gdict_client_context_connect (GdictClientContext  *context,
+			      GError             **error)
+{
+  GdictClientContextPrivate *priv;
+  GError *lookup_error, *flags_error;
+  gboolean res;
+  gint sock_fd, sock_res;
+  gsize addrlen;
+  GIOFlags flags;
+
+  g_return_val_if_fail (GDICT_IS_CLIENT_CONTEXT (context), FALSE);
+
+  priv = context->priv;
+
+  if (!priv->hostname)
+    {
+      g_set_error (error, GDICT_CLIENT_CONTEXT_ERROR,
+                   GDICT_CLIENT_CONTEXT_ERROR_LOOKUP,
+                   _("No hostname defined for the dictionary server"));
+
+      return FALSE;
+    }
+
+  /* forgive the absence of a port */
+  if (!priv->port)
+    priv->port = GDICT_DEFAULT_PORT;
+
+  priv->is_connecting = TRUE;
+
+  lookup_error = NULL;
+  res = gdict_client_context_lookup_server (context, &lookup_error);
+  if (!res)
+    {
+      g_propagate_error (error, lookup_error);
+
+      return FALSE;
+    }
+
+#ifdef ENABLE_IPV6
+  if (priv->sockaddr.ss_family == AF_INET6)
+    ((struct sockaddr_in6 *) &priv->sockaddr)->sin6_port = g_htons (priv->port);
+  else
+#endif
+    ((struct sockaddr_in *) &priv->sockaddr)->sin_port = g_htons (priv->port);
+
+#ifdef ENABLE_IPV6
+  if (priv->sockaddr.ss_family == AF_INET6)
+    {
+      sock_fd = socket (AF_INET6, SOCK_STREAM, 0);
+      if (sock_fd < 0)
+        {
+          g_set_error (error, GDICT_CLIENT_CONTEXT_ERROR,
+                       GDICT_CLIENT_CONTEXT_ERROR_SOCKET,
+                       _("Unable to create socket"));
+
+          return FALSE;
+        }
+
+      addrlen = sizeof (struct sockaddr_in6);
+    }
+  else
+    {
+#endif /* ENABLE_IPV6 */
+      sock_fd = socket (AF_INET, SOCK_STREAM, 0);
+      if (sock_fd < 0)
+        {
+          g_set_error (error, GDICT_CLIENT_CONTEXT_ERROR,
+                       GDICT_CLIENT_CONTEXT_ERROR_SOCKET,
+                       _("Unable to create socket"));
+
+          return FALSE;
+        }
+
+      addrlen = sizeof (struct sockaddr_in);
+#ifdef ENABLE_IPV6
+    }
+#endif
+
+  priv->channel = g_io_channel_unix_new (sock_fd);
+
+  /* RFC2229 mandates the usage of UTF-8, so we force this encoding */
+  g_io_channel_set_encoding (priv->channel, "UTF-8", NULL);
+
+  g_io_channel_set_line_term (priv->channel, "\r\n", 2);
+
+  /* make sure that the channel is non-blocking */
+  flags = g_io_channel_get_flags (priv->channel);
+  flags |= G_IO_FLAG_NONBLOCK;
+  flags_error = NULL;
+  g_io_channel_set_flags (priv->channel, flags, &flags_error);
+  if (flags_error)
+    {
+      g_set_error (error, GDICT_CLIENT_CONTEXT_ERROR,
+                   GDICT_CLIENT_CONTEXT_ERROR_SOCKET,
+                   _("Unable to set the channel as non-blocking: %s"),
+                   flags_error->message);
+
+      g_error_free (flags_error);
+      g_io_channel_unref (priv->channel);
+
+      return FALSE;
+    }
+
+  /* let the magic begin */
+  sock_res = connect (sock_fd, (struct sockaddr *) &priv->sockaddr, addrlen);
+  if ((sock_res != 0) && (errno != EINPROGRESS))
+    {
+      g_set_error (error, GDICT_CLIENT_CONTEXT_ERROR,
+                   GDICT_CLIENT_CONTEXT_ERROR_SOCKET,
+                   _("Unable to connect to the dictionary server at '%s:%d'"),
+                   priv->hostname,
+                   priv->port);
+
+      return FALSE;
+    }
+
+  priv->timeout_id = g_timeout_add_seconds (CONNECTION_TIMEOUT_SEC,
+                                            check_for_connection,
+                                            context);
+
+  /* XXX - remember that g_io_add_watch() increases the reference count
+   * of the GIOChannel we are using.
+   */
+  priv->source_id = g_io_add_watch (priv->channel,
+                                    (G_IO_IN | G_IO_ERR),
+                                    (GIOFunc) gdict_client_context_io_watch_cb,
+                                    context);
+
+  return TRUE;
+}
+
+static void
+gdict_client_context_disconnect (GdictClientContext *context)
+{
+  GdictCommand *cmd;
+
+  g_return_if_fail (GDICT_IS_CLIENT_CONTEXT (context));
+
+  /* instead of just breaking the connection to the server, we push
+   * a QUIT command on the queue, and wait for every other scheduled
+   * command to perform; this allows the creation of a batch of
+   * commands.
+   */
+  cmd = gdict_command_new (CMD_QUIT);
+  cmd->state = S_FINISH;
+
+  gdict_client_context_push_command (context, cmd);
+}
+
+static gboolean
+gdict_client_context_is_connected (GdictClientContext *context)
+{
+  g_assert (GDICT_IS_CLIENT_CONTEXT (context));
+
+  /* we are in the middle of a connection attempt */
+  if (context->priv->is_connecting)
+    return TRUE;
+
+  return (context->priv->channel != NULL && context->priv->source_id != 0);
+}
+
+static gboolean
+gdict_client_context_get_databases (GdictContext  *context,
+                                    GError       **error)
+{
+  GdictClientContext *client_ctx;
+  GdictCommand *cmd;
+
+  g_return_val_if_fail (GDICT_IS_CLIENT_CONTEXT (context), FALSE);
+
+  client_ctx = GDICT_CLIENT_CONTEXT (context);
+
+  g_signal_emit_by_name (context, "lookup-start");
+
+  if (!gdict_client_context_is_connected (client_ctx))
+    {
+      GError *connect_error = NULL;
+
+      gdict_client_context_connect (client_ctx, &connect_error);
+      if (connect_error)
+        {
+          g_signal_emit_by_name (context, "lookup-end");
+
+          g_propagate_error (error, connect_error);
+
+          return FALSE;
+        }
+    }
+
+  cmd = gdict_command_new (CMD_SHOW_DB);
+
+  return gdict_client_context_push_command (client_ctx, cmd);
+}
+
+static gboolean
+gdict_client_context_get_strategies (GdictContext  *context,
+				     GError       **error)
+{
+  GdictClientContext *client_ctx;
+  GdictCommand *cmd;
+
+  g_return_val_if_fail (GDICT_IS_CLIENT_CONTEXT (context), FALSE);
+
+  client_ctx = GDICT_CLIENT_CONTEXT (context);
+
+  g_signal_emit_by_name (context, "lookup-start");
+
+  if (!gdict_client_context_is_connected (client_ctx))
+    {
+      GError *connect_error = NULL;
+
+      gdict_client_context_connect (client_ctx, &connect_error);
+      if (connect_error)
+        {
+          g_signal_emit_by_name (context, "lookup-end");
+
+          g_propagate_error (error, connect_error);
+
+          return FALSE;
+        }
+    }
+
+  cmd = gdict_command_new (CMD_SHOW_STRAT);
+
+  return gdict_client_context_push_command (client_ctx, cmd);
+}
+
+static gboolean
+gdict_client_context_define_word (GdictContext  *context,
+				  const gchar   *database,
+				  const gchar   *word,
+				  GError       **error)
+{
+  GdictClientContext *client_ctx;
+  GdictCommand *cmd;
+
+  g_return_val_if_fail (GDICT_IS_CLIENT_CONTEXT (context), FALSE);
+
+  client_ctx = GDICT_CLIENT_CONTEXT (context);
+
+  g_signal_emit_by_name (context, "lookup-start");
+
+  if (!gdict_client_context_is_connected (client_ctx))
+    {
+      GError *connect_error = NULL;
+
+      gdict_client_context_connect (client_ctx, &connect_error);
+      if (connect_error)
+        {
+          g_signal_emit_by_name (context, "lookup-end");
+
+          g_propagate_error (error, connect_error);
+
+          return FALSE;
+        }
+    }
+
+  cmd = gdict_command_new (CMD_DEFINE);
+  cmd->database = g_strdup ((database != NULL ? database : GDICT_DEFAULT_DATABASE));
+  cmd->word = g_utf8_normalize (word, -1, G_NORMALIZE_NFC);
+
+  return gdict_client_context_push_command (client_ctx, cmd);
+}
+
+static gboolean
+gdict_client_context_match_word (GdictContext  *context,
+				 const gchar   *database,
+				 const gchar   *strategy,
+				 const gchar   *word,
+				 GError       **error)
+{
+  GdictClientContext *client_ctx;
+  GdictCommand *cmd;
+
+  g_return_val_if_fail (GDICT_IS_CLIENT_CONTEXT (context), FALSE);
+
+  client_ctx = GDICT_CLIENT_CONTEXT (context);
+
+  g_signal_emit_by_name (context, "lookup-start");
+
+  if (!gdict_client_context_is_connected (client_ctx))
+    {
+      GError *connect_error = NULL;
+
+      gdict_client_context_connect (client_ctx, &connect_error);
+      if (connect_error)
+        {
+          g_signal_emit_by_name (context, "lookup-end");
+
+          g_propagate_error (error, connect_error);
+
+          return FALSE;
+        }
+    }
+
+  cmd = gdict_command_new (CMD_MATCH);
+  cmd->database = g_strdup ((database != NULL ? database : GDICT_DEFAULT_DATABASE));
+  cmd->strategy = g_strdup ((strategy != NULL ? strategy : GDICT_DEFAULT_STRATEGY));
+  cmd->word = g_utf8_normalize (word, -1, G_NORMALIZE_NFC);
+
+  return gdict_client_context_push_command (client_ctx, cmd);
+}
+
+ +
+ +
+ + diff --git a/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/28.html b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/28.html new file mode 100644 index 00000000..557bd4a4 --- /dev/null +++ b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/28.html @@ -0,0 +1,5999 @@ + + + + + + Cppcheck - HTML report - mate-utils + + + + + +
+ + + +
+
   1
+   2
+   3
+   4
+   5
+   6
+   7
+   8
+   9
+  10
+  11
+  12
+  13
+  14
+  15
+  16
+  17
+  18
+  19
+  20
+  21
+  22
+  23
+  24
+  25
+  26
+  27
+  28
+  29
+  30
+  31
+  32
+  33
+  34
+  35
+  36
+  37
+  38
+  39
+  40
+  41
+  42
+  43
+  44
+  45
+  46
+  47
+  48
+  49
+  50
+  51
+  52
+  53
+  54
+  55
+  56
+  57
+  58
+  59
+  60
+  61
+  62
+  63
+  64
+  65
+  66
+  67
+  68
+  69
+  70
+  71
+  72
+  73
+  74
+  75
+  76
+  77
+  78
+  79
+  80
+  81
+  82
+  83
+  84
+  85
+  86
+  87
+  88
+  89
+  90
+  91
+  92
+  93
+  94
+  95
+  96
+  97
+  98
+  99
+ 100
+ 101
+ 102
+ 103
+ 104
+ 105
+ 106
+ 107
+ 108
+ 109
+ 110
+ 111
+ 112
+ 113
+ 114
+ 115
+ 116
+ 117
+ 118
+ 119
+ 120
+ 121
+ 122
+ 123
+ 124
+ 125
+ 126
+ 127
+ 128
+ 129
+ 130
+ 131
+ 132
+ 133
+ 134
+ 135
+ 136
+ 137
+ 138
+ 139
+ 140
+ 141
+ 142
+ 143
+ 144
+ 145
+ 146
+ 147
+ 148
+ 149
+ 150
+ 151
+ 152
+ 153
+ 154
+ 155
+ 156
+ 157
+ 158
+ 159
+ 160
+ 161
+ 162
+ 163
+ 164
+ 165
+ 166
+ 167
+ 168
+ 169
+ 170
+ 171
+ 172
+ 173
+ 174
+ 175
+ 176
+ 177
+ 178
+ 179
+ 180
+ 181
+ 182
+ 183
+ 184
+ 185
+ 186
+ 187
+ 188
+ 189
+ 190
+ 191
+ 192
+ 193
+ 194
+ 195
+ 196
+ 197
+ 198
+ 199
+ 200
+ 201
+ 202
+ 203
+ 204
+ 205
+ 206
+ 207
+ 208
+ 209
+ 210
+ 211
+ 212
+ 213
+ 214
+ 215
+ 216
+ 217
+ 218
+ 219
+ 220
+ 221
+ 222
+ 223
+ 224
+ 225
+ 226
+ 227
+ 228
+ 229
+ 230
+ 231
+ 232
+ 233
+ 234
+ 235
+ 236
+ 237
+ 238
+ 239
+ 240
+ 241
+ 242
+ 243
+ 244
+ 245
+ 246
+ 247
+ 248
+ 249
+ 250
+ 251
+ 252
+ 253
+ 254
+ 255
+ 256
+ 257
+ 258
+ 259
+ 260
+ 261
+ 262
+ 263
+ 264
+ 265
+ 266
+ 267
+ 268
+ 269
+ 270
+ 271
+ 272
+ 273
+ 274
+ 275
+ 276
+ 277
+ 278
+ 279
+ 280
+ 281
+ 282
+ 283
+ 284
+ 285
+ 286
+ 287
+ 288
+ 289
+ 290
+ 291
+ 292
+ 293
+ 294
+ 295
+ 296
+ 297
+ 298
+ 299
+ 300
+ 301
+ 302
+ 303
+ 304
+ 305
+ 306
+ 307
+ 308
+ 309
+ 310
+ 311
+ 312
+ 313
+ 314
+ 315
+ 316
+ 317
+ 318
+ 319
+ 320
+ 321
+ 322
+ 323
+ 324
+ 325
+ 326
+ 327
+ 328
+ 329
+ 330
+ 331
+ 332
+ 333
+ 334
+ 335
+ 336
+ 337
+ 338
+ 339
+ 340
+ 341
+ 342
+ 343
+ 344
+ 345
+ 346
+ 347
+ 348
+ 349
+ 350
+ 351
+ 352
+ 353
+ 354
+ 355
+ 356
+ 357
+ 358
+ 359
+ 360
+ 361
+ 362
+ 363
+ 364
+ 365
+ 366
+ 367
+ 368
+ 369
+ 370
+ 371
+ 372
+ 373
+ 374
+ 375
+ 376
+ 377
+ 378
+ 379
+ 380
+ 381
+ 382
+ 383
+ 384
+ 385
+ 386
+ 387
+ 388
+ 389
+ 390
+ 391
+ 392
+ 393
+ 394
+ 395
+ 396
+ 397
+ 398
+ 399
+ 400
+ 401
+ 402
+ 403
+ 404
+ 405
+ 406
+ 407
+ 408
+ 409
+ 410
+ 411
+ 412
+ 413
+ 414
+ 415
+ 416
+ 417
+ 418
+ 419
+ 420
+ 421
+ 422
+ 423
+ 424
+ 425
+ 426
+ 427
+ 428
+ 429
+ 430
+ 431
+ 432
+ 433
+ 434
+ 435
+ 436
+ 437
+ 438
+ 439
+ 440
+ 441
+ 442
+ 443
+ 444
+ 445
+ 446
+ 447
+ 448
+ 449
+ 450
+ 451
+ 452
+ 453
+ 454
+ 455
+ 456
+ 457
+ 458
+ 459
+ 460
+ 461
+ 462
+ 463
+ 464
+ 465
+ 466
+ 467
+ 468
+ 469
+ 470
+ 471
+ 472
+ 473
+ 474
+ 475
+ 476
+ 477
+ 478
+ 479
+ 480
+ 481
+ 482
+ 483
+ 484
+ 485
+ 486
+ 487
+ 488
+ 489
+ 490
+ 491
+ 492
+ 493
+ 494
+ 495
+ 496
+ 497
+ 498
+ 499
+ 500
+ 501
+ 502
+ 503
+ 504
+ 505
+ 506
+ 507
+ 508
+ 509
+ 510
+ 511
+ 512
+ 513
+ 514
+ 515
+ 516
+ 517
+ 518
+ 519
+ 520
+ 521
+ 522
+ 523
+ 524
+ 525
+ 526
+ 527
+ 528
+ 529
+ 530
+ 531
+ 532
+ 533
+ 534
+ 535
+ 536
+ 537
+ 538
+ 539
+ 540
+ 541
+ 542
+ 543
+ 544
+ 545
+ 546
+ 547
+ 548
+ 549
+ 550
+ 551
+ 552
+ 553
+ 554
+ 555
+ 556
+ 557
+ 558
+ 559
+ 560
+ 561
+ 562
+ 563
+ 564
+ 565
+ 566
+ 567
+ 568
+ 569
+ 570
+ 571
+ 572
+ 573
+ 574
+ 575
+ 576
+ 577
+ 578
+ 579
+ 580
+ 581
+ 582
+ 583
+ 584
+ 585
+ 586
+ 587
+ 588
+ 589
+ 590
+ 591
+ 592
+ 593
+ 594
+ 595
+ 596
+ 597
+ 598
+ 599
+ 600
+ 601
+ 602
+ 603
+ 604
+ 605
+ 606
+ 607
+ 608
+ 609
+ 610
+ 611
+ 612
+ 613
+ 614
+ 615
+ 616
+ 617
+ 618
+ 619
+ 620
+ 621
+ 622
+ 623
+ 624
+ 625
+ 626
+ 627
+ 628
+ 629
+ 630
+ 631
+ 632
+ 633
+ 634
+ 635
+ 636
+ 637
+ 638
+ 639
+ 640
+ 641
+ 642
+ 643
+ 644
+ 645
+ 646
+ 647
+ 648
+ 649
+ 650
+ 651
+ 652
+ 653
+ 654
+ 655
+ 656
+ 657
+ 658
+ 659
+ 660
+ 661
+ 662
+ 663
+ 664
+ 665
+ 666
+ 667
+ 668
+ 669
+ 670
+ 671
+ 672
+ 673
+ 674
+ 675
+ 676
+ 677
+ 678
+ 679
+ 680
+ 681
+ 682
+ 683
+ 684
+ 685
+ 686
+ 687
+ 688
+ 689
+ 690
+ 691
+ 692
+ 693
+ 694
+ 695
+ 696
+ 697
+ 698
+ 699
+ 700
+ 701
+ 702
+ 703
+ 704
+ 705
+ 706
+ 707
+ 708
+ 709
+ 710
+ 711
+ 712
+ 713
+ 714
+ 715
+ 716
+ 717
+ 718
+ 719
+ 720
+ 721
+ 722
+ 723
+ 724
+ 725
+ 726
+ 727
+ 728
+ 729
+ 730
+ 731
+ 732
+ 733
+ 734
+ 735
+ 736
+ 737
+ 738
+ 739
+ 740
+ 741
+ 742
+ 743
+ 744
+ 745
+ 746
+ 747
+ 748
+ 749
+ 750
+ 751
+ 752
+ 753
+ 754
+ 755
+ 756
+ 757
+ 758
+ 759
+ 760
+ 761
+ 762
+ 763
+ 764
+ 765
+ 766
+ 767
+ 768
+ 769
+ 770
+ 771
+ 772
+ 773
+ 774
+ 775
+ 776
+ 777
+ 778
+ 779
+ 780
+ 781
+ 782
+ 783
+ 784
+ 785
+ 786
+ 787
+ 788
+ 789
+ 790
+ 791
+ 792
+ 793
+ 794
+ 795
+ 796
+ 797
+ 798
+ 799
+ 800
+ 801
+ 802
+ 803
+ 804
+ 805
+ 806
+ 807
+ 808
+ 809
+ 810
+ 811
+ 812
+ 813
+ 814
+ 815
+ 816
+ 817
+ 818
+ 819
+ 820
+ 821
+ 822
+ 823
+ 824
+ 825
+ 826
+ 827
+ 828
+ 829
+ 830
+ 831
+ 832
+ 833
+ 834
+ 835
+ 836
+ 837
+ 838
+ 839
+ 840
+ 841
+ 842
+ 843
+ 844
+ 845
+ 846
+ 847
+ 848
+ 849
+ 850
+ 851
+ 852
+ 853
+ 854
+ 855
+ 856
+ 857
+ 858
+ 859
+ 860
+ 861
+ 862
+ 863
+ 864
+ 865
+ 866
+ 867
+ 868
+ 869
+ 870
+ 871
+ 872
+ 873
+ 874
+ 875
+ 876
+ 877
+ 878
+ 879
+ 880
+ 881
+ 882
+ 883
+ 884
+ 885
+ 886
+ 887
+ 888
+ 889
+ 890
+ 891
+ 892
+ 893
+ 894
+ 895
+ 896
+ 897
+ 898
+ 899
+ 900
+ 901
+ 902
+ 903
+ 904
+ 905
+ 906
+ 907
+ 908
+ 909
+ 910
+ 911
+ 912
+ 913
+ 914
+ 915
+ 916
+ 917
+ 918
+ 919
+ 920
+ 921
+ 922
+ 923
+ 924
+ 925
+ 926
+ 927
+ 928
+ 929
+ 930
+ 931
+ 932
+ 933
+ 934
+ 935
+ 936
+ 937
+ 938
+ 939
+ 940
+ 941
+ 942
+ 943
+ 944
+ 945
+ 946
+ 947
+ 948
+ 949
+ 950
+ 951
+ 952
+ 953
+ 954
+ 955
+ 956
+ 957
+ 958
+ 959
+ 960
+ 961
+ 962
+ 963
+ 964
+ 965
+ 966
+ 967
+ 968
+ 969
+ 970
+ 971
+ 972
+ 973
+ 974
+ 975
+ 976
+ 977
+ 978
+ 979
+ 980
+ 981
+ 982
+ 983
+ 984
+ 985
+ 986
+ 987
+ 988
+ 989
+ 990
+ 991
+ 992
+ 993
+ 994
+ 995
+ 996
+ 997
+ 998
+ 999
+1000
+1001
+1002
+1003
+1004
+1005
+1006
+1007
+1008
+1009
+1010
+1011
+1012
+1013
+1014
+1015
+1016
+1017
+1018
+1019
+1020
+1021
+1022
+1023
+1024
+1025
+1026
+1027
+1028
+1029
+1030
+1031
+1032
+1033
+1034
+1035
+1036
+1037
+1038
+1039
+1040
+1041
+1042
+1043
+1044
+1045
+1046
+1047
+1048
+1049
+1050
+1051
+1052
+1053
+1054
+1055
+1056
+1057
+1058
+1059
+1060
+1061
+1062
+1063
+1064
+1065
+1066
+1067
+1068
+1069
+1070
+1071
+1072
+1073
+1074
+1075
+1076
+1077
+1078
+1079
+1080
+1081
+1082
+1083
+1084
+1085
+1086
+1087
+1088
+1089
+1090
+1091
+1092
+1093
+1094
+1095
+1096
+1097
+1098
+1099
+1100
+1101
+1102
+1103
+1104
+1105
+1106
+1107
+1108
+1109
+1110
+1111
+1112
+1113
+1114
+1115
+1116
+1117
+1118
+1119
+1120
+1121
+1122
+1123
+1124
+1125
+1126
+1127
+1128
+1129
+1130
+1131
+1132
+1133
+1134
+1135
+1136
+1137
+1138
+1139
+1140
+1141
+1142
+1143
+1144
+1145
+1146
+1147
+1148
+1149
+1150
+1151
+1152
+1153
+1154
+1155
+1156
+1157
+1158
+1159
+1160
+1161
+1162
+1163
+1164
+1165
+1166
+1167
+1168
+1169
+1170
+1171
+1172
+1173
+1174
+1175
+1176
+1177
+1178
+1179
+1180
+1181
+1182
+1183
+1184
+1185
+1186
+1187
+1188
+1189
+1190
+1191
+1192
+1193
+1194
+1195
+1196
+1197
+1198
+1199
+1200
+1201
+1202
+1203
+1204
+1205
+1206
+1207
+1208
+1209
+1210
+1211
+1212
+1213
+1214
+1215
+1216
+1217
+1218
+1219
+1220
+1221
+1222
+1223
+1224
+1225
+1226
+1227
+1228
+1229
+1230
+1231
+1232
+1233
+1234
+1235
+1236
+1237
+1238
+1239
+1240
+1241
+1242
+1243
+1244
+1245
+1246
+1247
+1248
+1249
+1250
+1251
+1252
+1253
+1254
+1255
+1256
+1257
+1258
+1259
+1260
+1261
+1262
+1263
+1264
+1265
+1266
+1267
+1268
+1269
+1270
+1271
+1272
+1273
+1274
+1275
+1276
+1277
+1278
+1279
+1280
+1281
+1282
+1283
+1284
+1285
+1286
+1287
+1288
+1289
+1290
+1291
+1292
+1293
+1294
+1295
+1296
+1297
+1298
+1299
+1300
+1301
+1302
+1303
+1304
+1305
+1306
+1307
+1308
+1309
+1310
+1311
+1312
+1313
+1314
+1315
+1316
+1317
+1318
+1319
+1320
+1321
+1322
+1323
+1324
+1325
+1326
+1327
+1328
+1329
+1330
+1331
+1332
+1333
+1334
+1335
+1336
+1337
+1338
+1339
+1340
+1341
+1342
+1343
+1344
+1345
+1346
+1347
+1348
+1349
+1350
+1351
+1352
+1353
+1354
+1355
+1356
+1357
+1358
+1359
+1360
+1361
+1362
+1363
+1364
+1365
+1366
+1367
+1368
+1369
+1370
+1371
+1372
+1373
+1374
+1375
+1376
+1377
+1378
+1379
+1380
+1381
+1382
+1383
+1384
+1385
+1386
+1387
+1388
+1389
+1390
+1391
+1392
+1393
+1394
+1395
+1396
+1397
+1398
+1399
+1400
+1401
+1402
+1403
+1404
+1405
+1406
+1407
+1408
+1409
+1410
+1411
+1412
+1413
+1414
+1415
+1416
+1417
+1418
+1419
+1420
+1421
+1422
+1423
+1424
+1425
+1426
+1427
+1428
+1429
+1430
+1431
+1432
+1433
+1434
+1435
+1436
+1437
+1438
+1439
+1440
+1441
+1442
+1443
+1444
+1445
+1446
+1447
+1448
+1449
+1450
+1451
+1452
+1453
+1454
+1455
+1456
+1457
+1458
+1459
+1460
+1461
+1462
+1463
+1464
+1465
+1466
+1467
+1468
+1469
+1470
+1471
+1472
+1473
+1474
+1475
+1476
+1477
+1478
+1479
+1480
+1481
+1482
+1483
+1484
+1485
+1486
+1487
+1488
+1489
+1490
+1491
+1492
+1493
+1494
+1495
+1496
+1497
+1498
+1499
+1500
+1501
+1502
+1503
+1504
+1505
+1506
+1507
+1508
+1509
+1510
+1511
+1512
+1513
+1514
+1515
+1516
+1517
+1518
+1519
+1520
+1521
+1522
+1523
+1524
+1525
+1526
+1527
+1528
+1529
+1530
+1531
+1532
+1533
+1534
+1535
+1536
+1537
+1538
+1539
+1540
+1541
+1542
+1543
+1544
+1545
+1546
+1547
+1548
+1549
+1550
+1551
+1552
+1553
+1554
+1555
+1556
+1557
+1558
+1559
+1560
+1561
+1562
+1563
+1564
+1565
+1566
+1567
+1568
+1569
+1570
+1571
+1572
+1573
+1574
+1575
+1576
+1577
+1578
+1579
+1580
+1581
+1582
+1583
+1584
+1585
+1586
+1587
+1588
+1589
+1590
+1591
+1592
+1593
+1594
+1595
+1596
+1597
+1598
+1599
+1600
+1601
+1602
+1603
+1604
+1605
+1606
+1607
+1608
+1609
+1610
+1611
+1612
+1613
+1614
+1615
+1616
+1617
+1618
+1619
+1620
+1621
+1622
+1623
+1624
+1625
+1626
+1627
+1628
+1629
+1630
+1631
+1632
+1633
+1634
+1635
+1636
+1637
+1638
+1639
+1640
+1641
+1642
+1643
+1644
+1645
+1646
+1647
+1648
+1649
+1650
+1651
+1652
+1653
+1654
+1655
+1656
+1657
+1658
+1659
+1660
+1661
+1662
+1663
+1664
+1665
+1666
+1667
+1668
+1669
+1670
+1671
+1672
+1673
+1674
+1675
+1676
+1677
+1678
+1679
+1680
+1681
+1682
+1683
+1684
+1685
+1686
+1687
+1688
+1689
+1690
+1691
+1692
+1693
+1694
+1695
+1696
+1697
+1698
+1699
+1700
+1701
+1702
+1703
+1704
+1705
+1706
+1707
+1708
+1709
+1710
+1711
+1712
+1713
+1714
+1715
+1716
+1717
+1718
+1719
+1720
+1721
+1722
+1723
+1724
+1725
+1726
+1727
+1728
+1729
+1730
+1731
+1732
+1733
+1734
+1735
+1736
+1737
+1738
+1739
+1740
+1741
+1742
+1743
+1744
+1745
+1746
+1747
+1748
+1749
+1750
+1751
+1752
+1753
+1754
+1755
+1756
+1757
+1758
+1759
+1760
+1761
+1762
+1763
+1764
+1765
+1766
+1767
+1768
+1769
+1770
+1771
+1772
+1773
+1774
+1775
+1776
+1777
+1778
+1779
+1780
+1781
+1782
+1783
+1784
+1785
+1786
+1787
+1788
+1789
+1790
+1791
+1792
+1793
+1794
+1795
+1796
+1797
+1798
+1799
+1800
+1801
+1802
+1803
+1804
+1805
+1806
+1807
+1808
+1809
+1810
+1811
+1812
+1813
+1814
+1815
+1816
+1817
+1818
+1819
+1820
+1821
+1822
+1823
+1824
+1825
+1826
+1827
+1828
+1829
+1830
+1831
+1832
+1833
+1834
+1835
+1836
+1837
+1838
+1839
+1840
+1841
+1842
+1843
+1844
+1845
+1846
+1847
+1848
+1849
+1850
+1851
+1852
+1853
+1854
+1855
+1856
+1857
+1858
+1859
+1860
+1861
+1862
+1863
+1864
+1865
+1866
+1867
+1868
+1869
+1870
+1871
+1872
+1873
+1874
+1875
+1876
+1877
+1878
+1879
+1880
+1881
+1882
+1883
+1884
+1885
+1886
+1887
+1888
+1889
+1890
+1891
+1892
+1893
+1894
+1895
+1896
+1897
+1898
+1899
+1900
+1901
+1902
+1903
+1904
+1905
+1906
+1907
+1908
+1909
+1910
+1911
+1912
+1913
+1914
+1915
+1916
+1917
+1918
+1919
+1920
+1921
+1922
+1923
+1924
+1925
+1926
+1927
+1928
+1929
+1930
+1931
+1932
+1933
+1934
+1935
+1936
+1937
+1938
+1939
+1940
+1941
+1942
+1943
+1944
+1945
+1946
+1947
+1948
+1949
+1950
+1951
+1952
+1953
+1954
+1955
+1956
+1957
+1958
+1959
+1960
+1961
+1962
+1963
+1964
+1965
+1966
+1967
+1968
+1969
+1970
+1971
+1972
+1973
+1974
+1975
+1976
+1977
+1978
+1979
+1980
+1981
+1982
+1983
+1984
+1985
+1986
+1987
+1988
+1989
+1990
+1991
+1992
+1993
+1994
+1995
+1996
+1997
+1998
+1999
+2000
+2001
+2002
+2003
+2004
+2005
+2006
+2007
+2008
+2009
+2010
+2011
+2012
+2013
+2014
+2015
+2016
+2017
+2018
+2019
+2020
+2021
+2022
+2023
+2024
+2025
+2026
+2027
+2028
+2029
+2030
+2031
+2032
+2033
+2034
+2035
+2036
+2037
+2038
+2039
+2040
+2041
+2042
+2043
+2044
+2045
+2046
+2047
+2048
+2049
+2050
+2051
+2052
+2053
+2054
+2055
+2056
+2057
+2058
+2059
+2060
+2061
+2062
+2063
+2064
+2065
+2066
+2067
+2068
+2069
+2070
+2071
+2072
+2073
+2074
+2075
+2076
+2077
+2078
+2079
+2080
+2081
+2082
+2083
+2084
+2085
+2086
+2087
+2088
+2089
+2090
+2091
+2092
+2093
+2094
+2095
+2096
+2097
+2098
+2099
+2100
+2101
+2102
+2103
+2104
+2105
+2106
+2107
+2108
+2109
+2110
+2111
+2112
+2113
+2114
+2115
+2116
+2117
+2118
+2119
+2120
+2121
+2122
+2123
+2124
+2125
+2126
+2127
+2128
+2129
+2130
+2131
+2132
+2133
+2134
+2135
+2136
+2137
+2138
+2139
+2140
+2141
+2142
+2143
+2144
+2145
+2146
+2147
+2148
+2149
+2150
+2151
+2152
+2153
+2154
+2155
+2156
+2157
+2158
+2159
+2160
+2161
+2162
+2163
+2164
+2165
+2166
+2167
+2168
+2169
+2170
+2171
+2172
+2173
+2174
+2175
+2176
+2177
+2178
+2179
+2180
+2181
+2182
+2183
+2184
+2185
+2186
+2187
+2188
+2189
+2190
+2191
+2192
+2193
+2194
+2195
+2196
+2197
+2198
+2199
+2200
+2201
+2202
+2203
+2204
+2205
+2206
+2207
+2208
+2209
+2210
+2211
+2212
+2213
+2214
+2215
+2216
+2217
+2218
+2219
+2220
+2221
+2222
+2223
+2224
+2225
+2226
+2227
+2228
+2229
+2230
+2231
+2232
+2233
+2234
+2235
+2236
+2237
+2238
+2239
+2240
+2241
+2242
+2243
+2244
+2245
+2246
+2247
+2248
+2249
+2250
+2251
+2252
+2253
+2254
+2255
+2256
+2257
+2258
+2259
+2260
+2261
+2262
+2263
+2264
+2265
+2266
+2267
+2268
+2269
+2270
+2271
+2272
+2273
+2274
+2275
+2276
+2277
+2278
+2279
+2280
+2281
+2282
+2283
+2284
+2285
+2286
+2287
+2288
+2289
+2290
+2291
+2292
+2293
+2294
+2295
+2296
+2297
+2298
+2299
+2300
+2301
+2302
+2303
+2304
+2305
+2306
+2307
+2308
+2309
+2310
+2311
+2312
+2313
+2314
+2315
+2316
+2317
+2318
+2319
+2320
+2321
+2322
+2323
+2324
+2325
+2326
+2327
+2328
+2329
+2330
+2331
+2332
+2333
+2334
+2335
+2336
+2337
+2338
+2339
+2340
+2341
+2342
+2343
+2344
+2345
+2346
+2347
+2348
+2349
+2350
+2351
+2352
+2353
+2354
+2355
+2356
+2357
+2358
+2359
+2360
+2361
+2362
+2363
+2364
+2365
+2366
+2367
+2368
+2369
+2370
+2371
+2372
+2373
+2374
+2375
+2376
+2377
+2378
+2379
+2380
+2381
+2382
+2383
+2384
+2385
+2386
+2387
+2388
+2389
+2390
+2391
+2392
+2393
+2394
+2395
+2396
+2397
+2398
+2399
+2400
+2401
+2402
+2403
+2404
+2405
+2406
+2407
+2408
+2409
+2410
+2411
+2412
+2413
+2414
+2415
+2416
+2417
+2418
+2419
+2420
+2421
+2422
+2423
+2424
+2425
+2426
+2427
+2428
+2429
+2430
+2431
+2432
+2433
+2434
+2435
+2436
+2437
+2438
+2439
+2440
+2441
+2442
+2443
+2444
+2445
+2446
+2447
+2448
+2449
+2450
+2451
+2452
+2453
+2454
+2455
+2456
+2457
+2458
+2459
+2460
+2461
+2462
+2463
+2464
+2465
+2466
+2467
+2468
+2469
+2470
+2471
+2472
+2473
+2474
+2475
+2476
+2477
+2478
+2479
+2480
+2481
+2482
+2483
+2484
+2485
+2486
+2487
+2488
+2489
+2490
+2491
+2492
+2493
+2494
+2495
+2496
+2497
+2498
+2499
+2500
+2501
+2502
+2503
+2504
+2505
+2506
+2507
+2508
+2509
+2510
+2511
+2512
+2513
+2514
+2515
+2516
+2517
+2518
+2519
+2520
+2521
+2522
+2523
+2524
+2525
+2526
+2527
+2528
+2529
+2530
+2531
+2532
+2533
+2534
+2535
+2536
+2537
+2538
+2539
+2540
+2541
+2542
+2543
+2544
+2545
+2546
+2547
+2548
+2549
+2550
+2551
+2552
+2553
+2554
+2555
+2556
+2557
+2558
+2559
+2560
+2561
+2562
+2563
+2564
+2565
+2566
+2567
+2568
+2569
+2570
+2571
+2572
+2573
+2574
+2575
+2576
+2577
+2578
+2579
+2580
+2581
+2582
+2583
+2584
+2585
+2586
+2587
+2588
+2589
+2590
+2591
+2592
+2593
+2594
+2595
+2596
+2597
+2598
+2599
+2600
+2601
+2602
+2603
+2604
+2605
+2606
+2607
+2608
+2609
+2610
+2611
+2612
+2613
+2614
+2615
+2616
+2617
+2618
+2619
+2620
+2621
+2622
+2623
+2624
+2625
+2626
+2627
+2628
+2629
+2630
+2631
+2632
+2633
+2634
+2635
+2636
+2637
+2638
+2639
+2640
+2641
+2642
+2643
+2644
+2645
+2646
+2647
+2648
+2649
+2650
+2651
+2652
+2653
+2654
+2655
+2656
+2657
+2658
+2659
+2660
+2661
+2662
+2663
+2664
+2665
+2666
+2667
+2668
+2669
+2670
+2671
+2672
+2673
+2674
+2675
+2676
+2677
+2678
+2679
+2680
+2681
+2682
+2683
+2684
+2685
+2686
+2687
+2688
+2689
+2690
+2691
+2692
+2693
+2694
+2695
+2696
+2697
+2698
+2699
+2700
+2701
+2702
+2703
+2704
+2705
+2706
+2707
+2708
+2709
+2710
+2711
+2712
+2713
+2714
+2715
+2716
+2717
+2718
+2719
+2720
+2721
+2722
+2723
+2724
+2725
+2726
+2727
+2728
+2729
+2730
+2731
+2732
+2733
+2734
+2735
+2736
+2737
+2738
+2739
+2740
+2741
+2742
+2743
+2744
+2745
+2746
+2747
+2748
+2749
+2750
+2751
+2752
+2753
+2754
+2755
+2756
+2757
+2758
+2759
+2760
+2761
+2762
+2763
+2764
+2765
+2766
+2767
+2768
+2769
+2770
+2771
+2772
+2773
+2774
+2775
+2776
+2777
+2778
+2779
+2780
+2781
+2782
+2783
+2784
+2785
+2786
+2787
+2788
+2789
+2790
+2791
+2792
+2793
+2794
+2795
+2796
+2797
+2798
+2799
+2800
+2801
+2802
+2803
+2804
+2805
+2806
+2807
+2808
+2809
+2810
+2811
+2812
+2813
+2814
+2815
+2816
+2817
+2818
+2819
+2820
+2821
+2822
+2823
+2824
+2825
+2826
+2827
+2828
+2829
+2830
+2831
+2832
+2833
+2834
+2835
+2836
+2837
+2838
+2839
+2840
+2841
+2842
+2843
+2844
+2845
+2846
+2847
+2848
+2849
+2850
+2851
+2852
+2853
+2854
+2855
+2856
+2857
+2858
+2859
+2860
+2861
+2862
+2863
+2864
+2865
+2866
+2867
+2868
+2869
+2870
+2871
+2872
+2873
+2874
+2875
+2876
+2877
+2878
+2879
+2880
+2881
/* Copyright (C) 2005-2006 Emmanuele Bassi <ebassi@gmail.com>
+ * Copyright (C) 2012-2021 MATE Developers
+ *
+ * This file is part of MATE Utils.
+ *
+ * MATE Utils is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * MATE Utils is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MATE Utils.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+/**
+ * SECTION:gdict-defbox
+ * @short_description: Display the list of definitions for a word
+ *
+ * The #GdictDefbox widget is a composite widget showing the list of
+ * definitions for a word. It queries the passed #GdictContext and displays
+ * the list of #GdictDefinition<!-- -->s obtained.
+ *
+ * It provides syntax highlighting, clickable links and an embedded find
+ * bar.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+
+#include <gtk/gtk.h>
+#include <gdk/gdkkeysyms.h>
+#include <glib/gi18n-lib.h>
+
+#include "gdict-defbox.h"
+#include "gdict-utils.h"
+#include "gdict-debug.h"
+#include "gdict-private.h"
+#include "gdict-enum-types.h"
+#include "gdict-marshal.h"
+
+#define QUERY_MARGIN	48
+#define ERROR_MARGIN	24
+
+typedef struct
+{
+  GdictDefinition *definition;
+
+  gint begin;
+} Definition;
+
+struct _GdictDefboxPrivate
+{
+  GtkWidget *text_view;
+
+  /* the "find" pane */
+  GtkWidget *find_pane;
+  GtkWidget *find_entry;
+  GtkWidget *find_next;
+  GtkWidget *find_prev;
+  GtkWidget *find_label;
+
+  GtkWidget *progress_dialog;
+
+  GtkTextBuffer *buffer;
+
+  GdictContext *context;
+  GSList *definitions;
+
+  gchar *word;
+  gchar *database;
+  gchar *font_name;
+
+  guint show_find : 1;
+  guint is_searching : 1;
+  guint is_hovering : 1;
+
+  GdkCursor *busy_cursor;
+  GdkCursor *hand_cursor;
+  GdkCursor *regular_cursor;
+
+  guint start_id;
+  guint end_id;
+  guint define_id;
+  guint error_id;
+  guint hide_timeout;
+
+  GtkTextTag *link_tag;
+  GtkTextTag *visited_link_tag;
+};
+
+enum
+{
+  PROP_0,
+
+  PROP_CONTEXT,
+  PROP_WORD,
+  PROP_DATABASE,
+  PROP_FONT_NAME,
+  PROP_COUNT
+};
+
+enum
+{
+  SHOW_FIND,
+  HIDE_FIND,
+  FIND_NEXT,
+  FIND_PREVIOUS,
+  LINK_CLICKED,
+
+  LAST_SIGNAL
+};
+
+static guint gdict_defbox_signals[LAST_SIGNAL] = { 0 };
+
+G_DEFINE_TYPE_WITH_PRIVATE (GdictDefbox, gdict_defbox, GTK_TYPE_BOX)<--- There is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
+
+static Definition *
+definition_new (void)
+{
+  Definition *def;
+
+  def = g_slice_new (Definition);
+  def->definition = NULL;
+  def->begin = -1;
+
+  return def;
+}
+
+static void
+definition_free (Definition *def)
+{
+  if (!def)
+    return;
+
+  gdict_definition_unref (def->definition);
+  g_slice_free (Definition, def);
+}
+
+static void
+gdict_defbox_dispose (GObject *gobject)
+{
+  GdictDefbox *defbox = GDICT_DEFBOX (gobject);
+  GdictDefboxPrivate *priv = defbox->priv;
+
+  if (priv->start_id)
+    {
+      g_signal_handler_disconnect (priv->context, priv->start_id);
+      g_signal_handler_disconnect (priv->context, priv->end_id);
+      g_signal_handler_disconnect (priv->context, priv->define_id);
+
+      priv->start_id = 0;
+      priv->end_id = 0;
+      priv->define_id = 0;
+    }
+
+  if (priv->error_id)
+    {
+      g_signal_handler_disconnect (priv->context, priv->error_id);
+      priv->error_id = 0;
+    }
+
+  if (priv->context)
+    {
+      g_object_unref (priv->context);
+      priv->context = NULL;
+    }
+
+  if (priv->buffer)
+    {
+      g_object_unref (priv->buffer);
+      priv->buffer = NULL;
+    }
+
+  if (priv->busy_cursor)
+    {
+      g_object_unref (priv->busy_cursor);
+      priv->busy_cursor = NULL;
+    }
+
+  if (priv->hand_cursor)
+    {
+      g_object_unref (priv->hand_cursor);
+      priv->hand_cursor = NULL;
+    }
+
+  if (priv->regular_cursor)
+    {
+      g_object_unref (priv->regular_cursor);
+      priv->regular_cursor = NULL;
+    }
+
+  g_clear_pointer (&priv->word, g_free);
+
+  G_OBJECT_CLASS (gdict_defbox_parent_class)->dispose (gobject);
+}
+
+static void
+gdict_defbox_finalize (GObject *object)
+{
+  GdictDefbox *defbox = GDICT_DEFBOX (object);
+  GdictDefboxPrivate *priv = defbox->priv;
+
+  g_free (priv->database);
+  g_free (priv->word);
+  g_free (priv->font_name);
+
+  if (priv->definitions)
+    {
+      g_slist_free_full (priv->definitions, (GDestroyNotify) definition_free);
+      priv->definitions = NULL;
+    }
+
+  G_OBJECT_CLASS (gdict_defbox_parent_class)->finalize (object);
+}
+
+static void
+set_gdict_context (GdictDefbox  *defbox,
+		   GdictContext *context)
+{
+  GdictDefboxPrivate *priv;
+
+  g_assert (GDICT_IS_DEFBOX (defbox));
+
+  priv = defbox->priv;
+  if (priv->context)
+    {
+      if (priv->start_id)
+        {
+          GDICT_NOTE (DEFBOX, "Removing old context handlers");
+
+          g_signal_handler_disconnect (priv->context, priv->start_id);
+          g_signal_handler_disconnect (priv->context, priv->define_id);
+          g_signal_handler_disconnect (priv->context, priv->end_id);
+
+          priv->start_id = 0;
+          priv->end_id = 0;
+          priv->define_id = 0;
+        }
+
+      if (priv->error_id)
+        {
+          g_signal_handler_disconnect (priv->context, priv->error_id);
+
+          priv->error_id = 0;
+        }
+
+      GDICT_NOTE (DEFBOX, "Removing old context");
+
+      g_object_unref (G_OBJECT (priv->context));
+    }
+
+  if (!context)
+    return;
+
+  if (!GDICT_IS_CONTEXT (context))
+    {
+      g_warning ("Object of type '%s' instead of a GdictContext\n",
+      		 g_type_name (G_OBJECT_TYPE (context)));
+      return;
+    }
+
+  GDICT_NOTE (DEFBOX, "Setting new context");
+
+  priv->context = context;
+  g_object_ref (G_OBJECT (priv->context));
+}
+
+static void
+gdict_defbox_set_property (GObject      *object,
+			   guint         prop_id,
+			   const GValue *value,
+			   GParamSpec   *pspec)
+{
+  GdictDefbox *defbox = GDICT_DEFBOX (object);
+  GdictDefboxPrivate *priv = defbox->priv;
+
+  switch (prop_id)
+    {
+    case PROP_WORD:
+      gdict_defbox_lookup (defbox, g_value_get_string (value));
+      break;
+    case PROP_CONTEXT:
+      set_gdict_context (defbox, g_value_get_object (value));
+      break;
+    case PROP_DATABASE:
+      g_free (priv->database);
+      priv->database = g_strdup (g_value_get_string (value));
+      break;
+    case PROP_FONT_NAME:
+      gdict_defbox_set_font_name (defbox, g_value_get_string (value));
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+gdict_defbox_get_property (GObject    *object,
+			   guint       prop_id,
+			   GValue     *value,
+			   GParamSpec *pspec)
+{
+  GdictDefbox *defbox = GDICT_DEFBOX (object);
+  GdictDefboxPrivate *priv = defbox->priv;
+
+  switch (prop_id)
+    {
+    case PROP_WORD:
+      g_value_set_string (value, priv->word);
+      break;
+    case PROP_CONTEXT:
+      g_value_set_object (value, priv->context);
+      break;
+    case PROP_DATABASE:
+      g_value_set_string (value, priv->database);
+      break;
+    case PROP_FONT_NAME:
+      g_value_set_string (value, priv->font_name);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+/*
+ * this code has been copied from gtksourceview; it's the implementation
+ * for case-insensitive search in a GtkTextBuffer. this is non-trivial, as
+ * searches on a utf-8 text stream involve a norm(casefold(norm(utf8)))
+ * operation which can be costly on large buffers. luckily for us, it's
+ * not the case on a set of definitions.
+ */
+
+#define GTK_TEXT_UNKNOWN_CHAR 0xFFFC
+
+/* this function acts like g_utf8_offset_to_pointer() except that if it finds a
+ * decomposable character it consumes the decomposition length from the given
+ * offset.  So it's useful when the offset was calculated for the normalized
+ * version of str, but we need a pointer to str itself. */
+static const gchar *
+pointer_from_offset_skipping_decomp (const gchar *str, gint offset)
+{
+	gchar *casefold, *normal;
+	const gchar *p, *q;
+
+	p = str;
+	while (offset > 0)
+	{
+		q = g_utf8_next_char (p);
+		casefold = g_utf8_casefold (p, q - p);
+		normal = g_utf8_normalize (casefold, -1, G_NORMALIZE_NFD);
+		offset -= g_utf8_strlen (normal, -1);
+		g_free (casefold);
+		g_free (normal);
+		p = q;
+	}
+	return p;
+}
+
+static gboolean
+exact_prefix_cmp (const gchar *string,
+		  const gchar *prefix,
+		  guint        prefix_len)
+{
+	GUnicodeType type;
+
+	if (strncmp (string, prefix, prefix_len) != 0)
+		return FALSE;
+	if (string[prefix_len] == '\0')
+		return TRUE;
+
+	type = g_unichar_type (g_utf8_get_char (string + prefix_len));
+
+	/* If string contains prefix, check that prefix is not followed
+	 * by a unicode mark symbol, e.g. that trailing 'a' in prefix
+	 * is not part of two-char a-with-hat symbol in string. */
+	return type != G_UNICODE_SPACING_MARK &&
+		type != G_UNICODE_ENCLOSING_MARK &&
+		type != G_UNICODE_NON_SPACING_MARK;
+}
+
+static const gchar *
+utf8_strcasestr (const gchar *haystack, const gchar *needle)
+{
+	gsize needle_len;
+	gsize haystack_len;
+	const gchar *ret = NULL;
+	gchar *p;
+	gchar *casefold;
+	gchar *caseless_haystack;
+	gint i;
+
+	g_return_val_if_fail (haystack != NULL, NULL);
+	g_return_val_if_fail (needle != NULL, NULL);
+
+	casefold = g_utf8_casefold (haystack, -1);
+	caseless_haystack = g_utf8_normalize (casefold, -1, G_NORMALIZE_NFD);
+	g_free (casefold);
+
+	needle_len = g_utf8_strlen (needle, -1);
+	haystack_len = g_utf8_strlen (caseless_haystack, -1);
+
+	if (needle_len == 0)
+	{
+		ret = (gchar *)haystack;
+		goto finally_1;
+	}
+
+	if (haystack_len < needle_len)
+	{
+		ret = NULL;
+		goto finally_1;
+	}
+
+	p = (gchar*)caseless_haystack;
+	needle_len = strlen (needle);
+	i = 0;
+
+	while (*p)
+	{
+		if (exact_prefix_cmp (p, needle, needle_len))
+		{
+			ret = pointer_from_offset_skipping_decomp (haystack, i);
+			goto finally_1;
+		}
+
+		p = g_utf8_next_char (p);
+		i++;
+	}
+
+finally_1:
+	g_free (caseless_haystack);
+
+	return ret;
+}
+
+static const gchar *
+utf8_strrcasestr (const gchar *haystack, const gchar *needle)
+{
+	gsize needle_len;
+	gsize haystack_len;
+	const gchar *ret = NULL;
+	gchar *p;
+	gchar *casefold;
+	gchar *caseless_haystack;
+	gint i;
+
+	g_return_val_if_fail (haystack != NULL, NULL);
+	g_return_val_if_fail (needle != NULL, NULL);
+
+	casefold = g_utf8_casefold (haystack, -1);
+	caseless_haystack = g_utf8_normalize (casefold, -1, G_NORMALIZE_NFD);
+	g_free (casefold);
+
+	needle_len = g_utf8_strlen (needle, -1);
+	haystack_len = g_utf8_strlen (caseless_haystack, -1);
+
+	if (needle_len == 0)
+	{
+		ret = (gchar *)haystack;
+		goto finally_1;
+	}
+
+	if (haystack_len < needle_len)
+	{
+		ret = NULL;
+		goto finally_1;
+	}
+
+	i = haystack_len - needle_len;
+	p = g_utf8_offset_to_pointer (caseless_haystack, i);
+	needle_len = strlen (needle);
+
+	while (p >= caseless_haystack)
+	{
+		if (exact_prefix_cmp (p, needle, needle_len))
+		{
+			ret = pointer_from_offset_skipping_decomp (haystack, i);
+			goto finally_1;
+		}
+
+		p = g_utf8_prev_char (p);
+		i--;
+	}
+
+finally_1:
+	g_free (caseless_haystack);
+
+	return ret;
+}
+
+static gboolean
+utf8_caselessnmatch (const char *s1, const char *s2,
+		     gssize n1, gssize n2)
+{
+	gchar *casefold;
+	gchar *normalized_s1;
+	gchar *normalized_s2;
+	gint len_s1;
+	gint len_s2;
+	gboolean ret = FALSE;
+
+	g_return_val_if_fail (s1 != NULL, FALSE);
+	g_return_val_if_fail (s2 != NULL, FALSE);
+	g_return_val_if_fail (n1 > 0, FALSE);
+	g_return_val_if_fail (n2 > 0, FALSE);
+
+	casefold = g_utf8_casefold (s1, n1);
+	normalized_s1 = g_utf8_normalize (casefold, -1, G_NORMALIZE_NFD);
+	g_free (casefold);
+
+	casefold = g_utf8_casefold (s2, n2);
+	normalized_s2 = g_utf8_normalize (casefold, -1, G_NORMALIZE_NFD);
+	g_free (casefold);
+
+	len_s1 = strlen (normalized_s1);
+	len_s2 = strlen (normalized_s2);
+
+	if (len_s1 < len_s2)
+		goto finally_2;
+
+	ret = (strncmp (normalized_s1, normalized_s2, len_s2) == 0);
+
+finally_2:
+	g_free (normalized_s1);
+	g_free (normalized_s2);
+
+	return ret;
+}
+
+/* FIXME: total horror */
+static gboolean
+char_is_invisible (const GtkTextIter *iter)
+{
+	GSList *tags;
+	gboolean invisible = FALSE;
+	tags = gtk_text_iter_get_tags (iter);
+	while (tags)
+	{
+		gboolean this_invisible, invisible_set;
+		g_object_get (tags->data, "invisible", &this_invisible,
+			      "invisible-set", &invisible_set, NULL);
+		if (invisible_set)
+			invisible = this_invisible;
+		tags = g_slist_delete_link (tags, tags);
+	}
+	return invisible;
+}
+
+static void
+forward_chars_with_skipping (GtkTextIter *iter,
+			     gint         count,
+			     gboolean     skip_invisible,
+			     gboolean     skip_nontext,
+			     gboolean     skip_decomp)
+{
+	gint i;
+
+	g_return_if_fail (count >= 0);
+
+	i = count;
+
+	while (i > 0)
+	{
+		gboolean ignored = FALSE;
+
+		/* minimal workaround to avoid the infinite loop of bug #168247.
+		 * It doesn't fix the problemjust the symptom...
+		 */
+		if (gtk_text_iter_is_end (iter))
+			return;
+
+		if (skip_nontext && gtk_text_iter_get_char (iter) == GTK_TEXT_UNKNOWN_CHAR)
+			ignored = TRUE;
+
+		/* FIXME: char_is_invisible() gets list of tags for each char there,
+		   and checks every tag. It doesn't sound like a good idea. */
+		if (!ignored && skip_invisible && char_is_invisible (iter))
+			ignored = TRUE;
+
+		if (!ignored && skip_decomp)
+		{
+			/* being UTF8 correct sucks; this accounts for extra
+			   offsets coming from canonical decompositions of
+			   UTF8 characters (e.g. accented characters) which
+			   g_utf8_normalize() performs */
+			gchar *normal;
+			gchar buffer[6];
+			gint buffer_len;
+
+			buffer_len = g_unichar_to_utf8 (gtk_text_iter_get_char (iter), buffer);
+			normal = g_utf8_normalize (buffer, buffer_len, G_NORMALIZE_NFD);
+			i -= (g_utf8_strlen (normal, -1) - 1);
+			g_free (normal);
+		}
+
+		gtk_text_iter_forward_char (iter);
+
+		if (!ignored)
+			--i;
+	}
+}
+
+static gboolean
+lines_match (const GtkTextIter *start,
+	     const gchar      **lines,
+	     gboolean           visible_only,
+	     gboolean           slice,
+	     GtkTextIter       *match_start,
+	     GtkTextIter       *match_end)
+{
+	GtkTextIter next;
+	gchar *line_text;
+	const gchar *found;
+	gint offset;
+
+	if (*lines == NULL || **lines == '\0')
+	{
+		if (match_start)
+			*match_start = *start;
+		if (match_end)
+			*match_end = *start;
+		return TRUE;
+	}
+
+	next = *start;
+	gtk_text_iter_forward_line (&next);
+
+	/* No more text in buffer, but *lines is nonempty */
+	if (gtk_text_iter_equal (start, &next))
+		return FALSE;
+
+	if (slice)
+	{
+		if (visible_only)
+			line_text = gtk_text_iter_get_visible_slice (start, &next);
+		else
+			line_text = gtk_text_iter_get_slice (start, &next);
+	}
+	else
+	{
+		if (visible_only)
+			line_text = gtk_text_iter_get_visible_text (start, &next);
+		else
+			line_text = gtk_text_iter_get_text (start, &next);
+	}
+
+	if (match_start) /* if this is the first line we're matching */
+	{
+		found = utf8_strcasestr (line_text, *lines);
+	}
+	else
+	{
+		/* If it's not the first line, we have to match from the
+		 * start of the line.
+		 */
+		if (utf8_caselessnmatch (line_text, *lines, strlen (line_text),
+					 strlen (*lines)))
+			found = line_text;
+		else
+			found = NULL;
+	}
+
+	if (found == NULL)
+	{
+		g_free (line_text);
+		return FALSE;
+	}
+
+	/* Get offset to start of search string */
+	offset = g_utf8_strlen (line_text, found - line_text);
+
+	next = *start;
+
+	/* If match start needs to be returned, set it to the
+	 * start of the search string.
+	 */
+	forward_chars_with_skipping (&next, offset, visible_only, !slice, FALSE);
+	if (match_start)
+	{
+		*match_start = next;
+	}
+
+	/* Go to end of search string */
+	forward_chars_with_skipping (&next, g_utf8_strlen (*lines, -1), visible_only, !slice, TRUE);
+
+	g_free (line_text);
+
+	++lines;
+
+	if (match_end)
+		*match_end = next;
+
+	/* pass NULL for match_start, since we don't need to find the
+	 * start again.
+	 */
+	return lines_match (&next, lines, visible_only, slice, NULL, match_end);
+}
+
+static gboolean
+backward_lines_match (const GtkTextIter *start,
+		      const gchar      **lines,
+		      gboolean           visible_only,
+		      gboolean           slice,
+		      GtkTextIter       *match_start,
+		      GtkTextIter       *match_end)
+{
+	GtkTextIter line, next;
+	gchar *line_text;
+	const gchar *found;
+	gint offset;
+
+	if (*lines == NULL || **lines == '\0')
+	{
+		if (match_start)
+			*match_start = *start;
+		if (match_end)
+			*match_end = *start;
+		return TRUE;
+	}
+
+	line = next = *start;
+	if (gtk_text_iter_get_line_offset (&next) == 0)
+	{
+		if (!gtk_text_iter_backward_line (&next))
+			return FALSE;
+	}
+	else
+		gtk_text_iter_set_line_offset (&next, 0);
+
+	if (slice)
+	{
+		if (visible_only)
+			line_text = gtk_text_iter_get_visible_slice (&next, &line);
+		else
+			line_text = gtk_text_iter_get_slice (&next, &line);
+	}
+	else
+	{
+		if (visible_only)
+			line_text = gtk_text_iter_get_visible_text (&next, &line);
+		else
+			line_text = gtk_text_iter_get_text (&next, &line);
+	}
+
+	if (match_start) /* if this is the first line we're matching */
+	{
+		found = utf8_strrcasestr (line_text, *lines);
+	}
+	else
+	{
+		/* If it's not the first line, we have to match from the
+		 * start of the line.
+		 */
+		if (utf8_caselessnmatch (line_text, *lines, strlen (line_text),
+					 strlen (*lines)))
+			found = line_text;
+		else
+			found = NULL;
+	}
+
+	if (found == NULL)
+	{
+		g_free (line_text);
+		return FALSE;
+	}
+
+	/* Get offset to start of search string */
+	offset = g_utf8_strlen (line_text, found - line_text);
+
+	forward_chars_with_skipping (&next, offset, visible_only, !slice, FALSE);
+
+	/* If match start needs to be returned, set it to the
+	 * start of the search string.
+	 */
+	if (match_start)
+	{
+		*match_start = next;
+	}
+
+	/* Go to end of search string */
+	forward_chars_with_skipping (&next, g_utf8_strlen (*lines, -1), visible_only, !slice, TRUE);
+
+	g_free (line_text);
+
+	++lines;
+
+	if (match_end)
+		*match_end = next;
+
+	/* try to match the rest of the lines forward, passing NULL
+	 * for match_start so lines_match will try to match the entire
+	 * line */
+	return lines_match (&next, lines, visible_only,
+			    slice, NULL, match_end);
+}
+
+/* strsplit () that retains the delimiter as part of the string. */
+static gchar **
+breakup_string (const char *string,
+		const char *delimiter,
+		gint        max_tokens)
+{
+	GSList *string_list = NULL, *slist;
+	gchar **str_array, *s, *casefold, *new_string;
+	guint i, n = 1;
+
+	g_return_val_if_fail (string != NULL, NULL);
+	g_return_val_if_fail (delimiter != NULL, NULL);
+
+	if (max_tokens < 1)
+		max_tokens = G_MAXINT;
+
+	s = strstr (string, delimiter);
+	if (s)
+	{
+		guint delimiter_len = strlen (delimiter);
+
+		do
+		{
+			guint len;
+
+			len = s - string + delimiter_len;
+			new_string = g_new (gchar, len + 1);
+			strncpy (new_string, string, len);
+			new_string[len] = 0;
+			casefold = g_utf8_casefold (new_string, -1);
+			g_free (new_string);
+			new_string = g_utf8_normalize (casefold, -1, G_NORMALIZE_NFD);
+			g_free (casefold);
+			string_list = g_slist_prepend (string_list, new_string);
+			n++;
+			string = s + delimiter_len;
+			s = strstr (string, delimiter);
+		} while (--max_tokens && s);
+	}
+
+	if (*string)
+	{
+		n++;
+		casefold = g_utf8_casefold (string, -1);
+		new_string = g_utf8_normalize (casefold, -1, G_NORMALIZE_NFD);
+		g_free (casefold);
+		string_list = g_slist_prepend (string_list, new_string);
+	}
+
+	str_array = g_new (gchar*, n);
+
+	i = n - 1;
+
+	str_array[i--] = NULL;
+	for (slist = string_list; slist; slist = slist->next)
+		str_array[i--] = slist->data;
+
+	g_slist_free (string_list);
+
+	return str_array;
+}
+
+static gboolean
+gdict_defbox_iter_forward_search (const GtkTextIter   *iter,
+                                  const gchar         *str,
+                                  GtkTextIter         *match_start,
+                                  GtkTextIter         *match_end,
+                                  const GtkTextIter   *limit)
+{
+  gchar **lines = NULL;
+  GtkTextIter match;
+  gboolean retval = FALSE;
+  GtkTextIter search;
+
+  g_return_val_if_fail (iter != NULL, FALSE);
+  g_return_val_if_fail (str != NULL, FALSE);
+
+  if (limit && gtk_text_iter_compare (iter, limit) >= 0)
+    return FALSE;
+
+  if (*str == '\0')
+    {
+      /* If we can move one char, return the empty string there */
+      match = *iter;
+
+      if (gtk_text_iter_forward_char (&match))
+        {
+          if (limit && gtk_text_iter_equal (&match, limit))
+            return FALSE;
+
+          if (match_start)
+            *match_start = match;
+
+          if (match_end)
+            *match_end = match;
+
+          return TRUE;
+        }
+      else
+        return FALSE;
+    }
+
+  /* locate all lines */
+  lines = breakup_string (str, "\n", -1);
+
+  search = *iter;
+
+  /* This loop has an inefficient worst-case, where
+   * gtk_text_iter_get_text () is called repeatedly on
+   * a single line.
+   */
+  do
+    {
+      GtkTextIter end;
+      gboolean res;
+
+      if (limit && gtk_text_iter_compare (&search, limit) >= 0)
+        break;
+
+      res = lines_match (&search, (const gchar**)lines,
+                         TRUE, FALSE,
+                         &match, &end);
+      if (res)
+        {
+          if (limit == NULL ||
+              (limit && gtk_text_iter_compare (&end, limit) <= 0))
+            {
+              retval = TRUE;
+
+              if (match_start)
+                *match_start = match;
+
+              if (match_end)
+                *match_end = end;
+            }
+
+          break;
+        }
+    } while (gtk_text_iter_forward_line (&search));
+
+  g_strfreev ((gchar**) lines);
+
+  return retval;
+}
+
+static gboolean
+gdict_defbox_iter_backward_search (const GtkTextIter   *iter,
+                                   const gchar         *str,
+                                   GtkTextIter         *match_start,
+                                   GtkTextIter         *match_end,
+                                   const GtkTextIter   *limit)
+{
+  gchar **lines = NULL;
+  GtkTextIter match;
+  gboolean retval = FALSE;
+  GtkTextIter search;
+
+  g_return_val_if_fail (iter != NULL, FALSE);
+  g_return_val_if_fail (str != NULL, FALSE);
+
+  if (limit && gtk_text_iter_compare (iter, limit) <= 0)
+    return FALSE;
+
+  if (*str == '\0')
+    {
+      /* If we can move one char, return the empty string there */
+      match = *iter;
+
+      if (gtk_text_iter_backward_char (&match))
+        {
+          if (limit && gtk_text_iter_equal (&match, limit))
+            return FALSE;
+
+          if (match_start)
+            *match_start = match;
+
+          if (match_end)
+            *match_end = match;
+
+          return TRUE;
+        }
+      else
+        return FALSE;
+    }
+
+  /* locate all lines */
+  lines = breakup_string (str, "\n", -1);
+
+  search = *iter;
+
+  /* This loop has an inefficient worst-case, where
+   * gtk_text_iter_get_text () is called repeatedly on
+   * a single line.
+   */
+  while (TRUE)
+    {
+      GtkTextIter end;
+      gboolean res;
+
+      if (limit && gtk_text_iter_compare (&search, limit) <= 0)
+        break;
+
+      res = backward_lines_match (&search, (const gchar**)lines,
+                                  TRUE, FALSE,
+                                  &match, &end);
+      if (res)
+        {
+           if (limit == NULL ||
+               (limit && gtk_text_iter_compare (&end, limit) > 0))
+             {
+               retval = TRUE;
+
+               if (match_start)
+                 *match_start = match;
+
+               if (match_end)
+                 *match_end = end;
+
+             }
+
+           break;
+        }
+
+      if (gtk_text_iter_get_line_offset (&search) == 0)
+        {
+          if (!gtk_text_iter_backward_line (&search))
+            break;
+        }
+      else
+        gtk_text_iter_set_line_offset (&search, 0);
+    }
+
+  g_strfreev ((gchar**) lines);
+
+  return retval;
+}
+
+static gboolean
+gdict_defbox_find_backward (GdictDefbox *defbox,
+			    const gchar *text)
+{
+  GdictDefboxPrivate *priv = defbox->priv;
+  GtkTextIter start_iter, end_iter;
+  GtkTextIter match_start, match_end;
+  GtkTextIter iter;
+  GtkTextMark *last_search;
+  gboolean res;
+
+  g_assert (GTK_IS_TEXT_BUFFER (priv->buffer));
+
+  gtk_text_buffer_get_bounds (priv->buffer, &start_iter, &end_iter);
+
+  /* if there already has been another result, begin from there */
+  last_search = gtk_text_buffer_get_mark (priv->buffer, "last-search-prev");
+  if (last_search)
+    gtk_text_buffer_get_iter_at_mark (priv->buffer, &iter, last_search);
+  else
+    iter = end_iter;
+
+  res = gdict_defbox_iter_backward_search (&iter, text,
+                                           &match_start, &match_end,
+                                           NULL);
+  if (res)
+    {
+      gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->text_view),
+      				    &match_start,
+      				    0.0,
+      				    TRUE,
+      				    0.0, 0.0);
+      gtk_text_buffer_place_cursor (priv->buffer, &match_end);
+      gtk_text_buffer_move_mark (priv->buffer,
+      				 gtk_text_buffer_get_mark (priv->buffer, "selection_bound"),
+      				 &match_start);
+      gtk_text_buffer_create_mark (priv->buffer, "last-search-prev", &match_start, FALSE);
+      gtk_text_buffer_create_mark (priv->buffer, "last-search-next", &match_end, FALSE);
+
+      return TRUE;
+    }
+
+  return FALSE;
+}
+
+static gboolean
+hide_find_pane (gpointer user_data)
+{
+  GdictDefbox *defbox = user_data;
+
+  gtk_widget_hide (defbox->priv->find_pane);
+  defbox->priv->show_find = FALSE;
+
+  gtk_widget_grab_focus (defbox->priv->text_view);
+
+  defbox->priv->hide_timeout = 0;
+
+  return FALSE;
+}
+
+static void
+find_prev_clicked_cb (GtkWidget *widget,
+		      gpointer   user_data)
+{
+  GdictDefbox *defbox = GDICT_DEFBOX (user_data);
+  GdictDefboxPrivate *priv = defbox->priv;
+  const gchar *text;
+  gboolean found;
+
+  gtk_widget_hide (priv->find_label);
+
+  text = gtk_entry_get_text (GTK_ENTRY (priv->find_entry));
+  if (!text)
+    return;
+
+  found = gdict_defbox_find_backward (defbox, text);
+  if (!found)
+    {
+      gchar *str;
+
+      str = g_strconcat ("  <i>", _("Not found"), "</i>", NULL);
+      gtk_label_set_markup (GTK_LABEL (priv->find_label), str);
+      gtk_widget_show (priv->find_label);
+
+      g_free (str);
+    }
+
+  if (priv->hide_timeout)
+    {
+      g_source_remove (priv->hide_timeout);
+      priv->hide_timeout = g_timeout_add_seconds (5, hide_find_pane, defbox);
+    }
+}
+
+static gboolean
+gdict_defbox_find_forward (GdictDefbox *defbox,
+			   const gchar *text,
+			   gboolean     is_typing)
+{
+  GdictDefboxPrivate *priv = defbox->priv;
+  GtkTextIter start_iter, end_iter;
+  GtkTextIter match_start, match_end;
+  GtkTextIter iter;
+  GtkTextMark *last_search;
+  gboolean res;
+
+  g_assert (GTK_IS_TEXT_BUFFER (priv->buffer));
+
+  gtk_text_buffer_get_bounds (priv->buffer, &start_iter, &end_iter);
+
+  if (!is_typing)
+    {
+      /* if there already has been another result, begin from there */
+      last_search = gtk_text_buffer_get_mark (priv->buffer, "last-search-next");
+
+      if (last_search)
+        gtk_text_buffer_get_iter_at_mark (priv->buffer, &iter, last_search);
+      else
+	iter = start_iter;
+    }
+  else
+    {
+      last_search = gtk_text_buffer_get_mark (priv->buffer, "last-search-prev");
+
+      if (last_search)
+	gtk_text_buffer_get_iter_at_mark (priv->buffer, &iter, last_search);
+      else
+	iter = start_iter;
+    }
+
+  res = gdict_defbox_iter_forward_search (&iter, text,
+                                          &match_start,
+                                          &match_end,
+                                          NULL);
+  if (res)
+    {
+      gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->text_view),
+      				    &match_start,
+      				    0.0,
+      				    TRUE,
+      				    0.0, 0.0);
+      gtk_text_buffer_place_cursor (priv->buffer, &match_end);
+      gtk_text_buffer_move_mark (priv->buffer,
+      				 gtk_text_buffer_get_mark (priv->buffer, "selection_bound"),
+      				 &match_start);
+      gtk_text_buffer_create_mark (priv->buffer, "last-search-prev", &match_start, FALSE);
+      gtk_text_buffer_create_mark (priv->buffer, "last-search-next", &match_end, FALSE);
+
+      return TRUE;
+    }
+
+  return FALSE;
+}
+
+static void
+find_next_clicked_cb (GtkWidget *widget,
+		      gpointer   user_data)
+{
+  GdictDefbox *defbox = GDICT_DEFBOX (user_data);
+  GdictDefboxPrivate *priv = defbox->priv;
+  const gchar *text;
+  gboolean found;
+
+  gtk_widget_hide (priv->find_label);
+
+  text = gtk_entry_get_text (GTK_ENTRY (priv->find_entry));
+  if (!text)
+    return;
+
+  found = gdict_defbox_find_forward (defbox, text, FALSE);
+  if (!found)
+    {
+      gchar *str;
+
+      str = g_strconcat ("  <i>", _("Not found"), "</i>", NULL);
+      gtk_label_set_markup (GTK_LABEL (priv->find_label), str);
+      gtk_widget_show (priv->find_label);
+
+      g_free (str);
+    }
+
+  if (priv->hide_timeout)
+    {
+      g_source_remove (priv->hide_timeout);
+      priv->hide_timeout = g_timeout_add_seconds (5, hide_find_pane, defbox);
+    }
+}
+
+static void
+find_entry_changed_cb (GtkWidget *widget,
+		       gpointer   user_data)
+{
+  GdictDefbox *defbox = GDICT_DEFBOX (user_data);
+  GdictDefboxPrivate *priv = defbox->priv;
+  gchar *text;
+  gboolean found;
+
+  gtk_widget_hide (priv->find_label);
+
+  text = gtk_editable_get_chars (GTK_EDITABLE (widget), 0, -1);
+  if (!text)
+    return;
+
+  found = gdict_defbox_find_forward (defbox, text, TRUE);
+  if (!found)
+    {
+      gchar *str;
+
+      str = g_strconcat ("  <i>", _("Not found"), "</i>", NULL);
+      gtk_label_set_markup (GTK_LABEL (priv->find_label), str);
+      gtk_widget_show (priv->find_label);
+
+      g_free (str);
+    }
+
+  g_free (text);
+
+  if (priv->hide_timeout)
+    {
+      g_source_remove (priv->hide_timeout);
+      priv->hide_timeout = g_timeout_add_seconds (5, hide_find_pane, defbox);
+    }
+}
+
+static void
+close_button_clicked (GtkButton *button,
+                      gpointer   data)
+{
+  GdictDefboxPrivate *priv = GDICT_DEFBOX (data)->priv;
+
+  if (priv->hide_timeout)
+    g_source_remove (priv->hide_timeout);
+
+  (void) hide_find_pane (data);
+}
+
+static GtkWidget *
+create_find_pane (GdictDefbox *defbox)
+{
+  GdictDefboxPrivate *priv;
+  GtkWidget *find_pane;
+  GtkWidget *label;
+  GtkWidget *sep;
+  GtkWidget *hbox1, *hbox2;
+  GtkWidget *button;
+
+  priv = defbox->priv;
+
+  find_pane = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+  gtk_container_set_border_width (GTK_CONTAINER (find_pane), 0);
+
+  hbox1 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+  gtk_box_pack_start (GTK_BOX (find_pane), hbox1, TRUE, TRUE, 0);
+  gtk_widget_show (hbox1);
+
+  button = gtk_button_new ();
+  gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
+  gtk_button_set_image (GTK_BUTTON (button),
+                        gtk_image_new_from_icon_name ("window-close",
+                                                      GTK_ICON_SIZE_BUTTON));
+  g_signal_connect (button, "clicked",
+                    G_CALLBACK (close_button_clicked), defbox);
+  gtk_box_pack_start (GTK_BOX (hbox1), button, FALSE, FALSE, 0);
+  gtk_widget_show (button);
+
+  hbox2 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
+  gtk_box_pack_start (GTK_BOX (hbox1), hbox2, TRUE, TRUE, 0);
+  gtk_widget_show (hbox2);
+
+  label = gtk_label_new_with_mnemonic (_("F_ind:"));
+  gtk_box_pack_start (GTK_BOX (hbox2), label, FALSE, FALSE, 0);
+
+  priv->find_entry = gtk_entry_new ();
+  g_signal_connect (priv->find_entry, "changed",
+  		    G_CALLBACK (find_entry_changed_cb), defbox);
+  gtk_box_pack_start (GTK_BOX (hbox2), priv->find_entry, TRUE, TRUE, 0);
+  gtk_label_set_mnemonic_widget (GTK_LABEL (label), priv->find_entry);
+
+  sep = gtk_separator_new (GTK_ORIENTATION_VERTICAL);
+  gtk_box_pack_start (GTK_BOX (hbox1), sep, FALSE, FALSE, 0);
+  gtk_widget_show (sep);
+
+  priv->find_prev = gtk_button_new_with_mnemonic (_("_Previous"));
+  gtk_button_set_image (GTK_BUTTON (priv->find_prev),
+                        gtk_image_new_from_icon_name ("go-previous",
+                                                      GTK_ICON_SIZE_MENU));
+  g_signal_connect (priv->find_prev, "clicked",
+  		    G_CALLBACK (find_prev_clicked_cb), defbox);
+  gtk_box_pack_start (GTK_BOX (hbox1), priv->find_prev, FALSE, FALSE, 0);
+
+  priv->find_next = gtk_button_new_with_mnemonic (_("_Next"));
+  gtk_button_set_image (GTK_BUTTON (priv->find_next),
+                        gtk_image_new_from_icon_name ("go-next",
+                                                      GTK_ICON_SIZE_MENU));
+  g_signal_connect (priv->find_next, "clicked",
+  		    G_CALLBACK (find_next_clicked_cb), defbox);
+  gtk_box_pack_start (GTK_BOX (hbox1), priv->find_next, FALSE, FALSE, 0);
+
+  priv->find_label = gtk_label_new (NULL);
+  gtk_label_set_use_markup (GTK_LABEL (priv->find_label), TRUE);
+  gtk_box_pack_end (GTK_BOX (find_pane), priv->find_label, FALSE, FALSE, 0);
+  gtk_widget_hide (priv->find_label);
+
+  return find_pane;
+}
+
+static void
+gdict_defbox_init_tags (GdictDefbox *defbox)
+{
+  GdictDefboxPrivate *priv = defbox->priv;
+
+  g_assert (GTK_IS_TEXT_BUFFER (priv->buffer));
+
+  gtk_text_buffer_create_tag (priv->buffer, "italic",
+  			      "style", PANGO_STYLE_ITALIC,
+  			      NULL);
+  gtk_text_buffer_create_tag (priv->buffer, "bold",
+  			      "weight", PANGO_WEIGHT_BOLD,
+  			      NULL);
+  gtk_text_buffer_create_tag (priv->buffer, "underline",
+  			      "underline", PANGO_UNDERLINE_SINGLE,
+  			      NULL);
+
+  gtk_text_buffer_create_tag (priv->buffer, "big",
+  			      "scale", 1.6,
+  			      NULL);
+  gtk_text_buffer_create_tag (priv->buffer, "small",
+		  	      "scale", PANGO_SCALE_SMALL,
+			      NULL);
+
+  {
+    GtkSettings *settings = gtk_widget_get_settings (GTK_WIDGET (defbox));
+    gboolean prefer_dark = FALSE;
+    GdkRGBA rgba;
+
+    /* HACK: we're hardcoding the Adwaita values because GtkTextTag
+     * cannot be styled via CSS
+     */
+    g_object_get (settings, "gtk-application-prefer-dark-theme", &prefer_dark, NULL);
+
+    if (!prefer_dark)
+      gdk_rgba_parse (&rgba, "#2a76c6");
+    else
+      gdk_rgba_parse (&rgba, "#4a90d9");
+
+    priv->link_tag =
+      gtk_text_buffer_create_tag (priv->buffer, "link",
+                                  "underline", PANGO_UNDERLINE_SINGLE,
+                                  "foreground-rgba", &rgba,
+                                  NULL);
+
+    if (!prefer_dark)
+      gdk_rgba_parse (&rgba, "#215d9c");
+    else
+      gdk_rgba_parse (&rgba, "#2a76c6");
+
+    priv->visited_link_tag =
+      gtk_text_buffer_create_tag (priv->buffer, "visited-link",
+                                  "underline", PANGO_UNDERLINE_SINGLE,
+                                  "foreground-rgba", &rgba,
+                                  NULL);
+  }
+
+  gtk_text_buffer_create_tag (priv->buffer, "phonetic",
+                              "foreground", "dark gray",
+                              NULL);
+
+  gtk_text_buffer_create_tag (priv->buffer, "query-title",
+		              "left-margin", QUERY_MARGIN,
+  			      "pixels-above-lines", 5,
+  			      "pixels-below-lines", 20,
+			      NULL);
+  gtk_text_buffer_create_tag (priv->buffer, "query-from",
+		  	      "foreground", "dark gray",
+			      "scale", PANGO_SCALE_SMALL,
+		  	      "left-margin", QUERY_MARGIN,
+			      "pixels-above-lines", 5,
+			      "pixels-below-lines", 10,
+			      NULL);
+
+  gtk_text_buffer_create_tag (priv->buffer, "error-title",
+		  	      "foreground", "dark red",
+			      "left-margin", ERROR_MARGIN,
+			      NULL);
+  gtk_text_buffer_create_tag (priv->buffer, "error-message",
+		              "left-margin", ERROR_MARGIN,
+			      NULL);
+}
+
+static void
+follow_if_is_link (GdictDefbox *defbox,
+                   GtkTextView *text_view,
+                   GtkTextIter *iter)
+{
+  GSList *tags, *l;
+
+  tags = gtk_text_iter_get_tags (iter);
+
+  for (l = tags; l != NULL; l = l->next)
+    {
+      GtkTextTag *tag = l->data;
+      gchar *name;
+
+      g_object_get (G_OBJECT (tag), "name", &name, NULL);
+      if (name &&
+          (strcmp (name, "link") == 0 ||
+           strcmp (name, "visited-link") == 0))
+        {
+          GtkTextBuffer *buffer = gtk_text_view_get_buffer (text_view);
+          GtkTextIter start, end;
+          gchar *link_str;
+
+          start = *iter;
+          end = *iter;
+
+          gtk_text_iter_backward_to_tag_toggle (&start, tag);
+          gtk_text_iter_forward_to_tag_toggle (&end, tag);
+
+          link_str = gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
+
+          g_signal_emit (defbox, gdict_defbox_signals[LINK_CLICKED], 0, link_str);
+
+          g_free (link_str);
+          g_free (name);
+
+          break;
+        }
+
+      g_free (name);
+    }
+
+  g_slist_free (tags);
+}
+
+static gboolean
+defbox_event_after_cb (GtkWidget   *text_view,
+                       GdkEvent    *event,
+                       GdictDefbox *defbox)
+{
+  GtkTextIter iter;
+  GtkTextBuffer *buffer;
+  GdkEventButton *button_event;
+  gint bx, by;
+
+  if (event->type != GDK_BUTTON_RELEASE)
+    return FALSE;
+
+  button_event = (GdkEventButton *) event;
+
+  if (button_event->button != 1)
+    return FALSE;
+
+  buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (text_view));
+  if (gtk_text_buffer_get_has_selection (buffer))
+    return FALSE;
+
+  gtk_text_view_window_to_buffer_coords (GTK_TEXT_VIEW (text_view),
+                                         GTK_TEXT_WINDOW_WIDGET,
+                                         button_event->x, button_event->y,
+                                         &bx, &by);
+
+  gtk_text_view_get_iter_at_location (GTK_TEXT_VIEW (text_view),
+                                      &iter,
+                                      bx, by);
+
+  follow_if_is_link (defbox, GTK_TEXT_VIEW (text_view), &iter);
+
+  return FALSE;
+}
+
+static void
+set_cursor_if_appropriate (GdictDefbox *defbox,
+                           GtkTextView *text_view,
+                           gint         x,
+                           gint         y)
+{
+  GdictDefboxPrivate *priv;
+  GSList *tags, *l;
+  GtkTextIter iter;
+  gboolean hovering = FALSE;
+
+  priv = defbox->priv;
+
+  if (!priv->hand_cursor)
+    {
+      GdkDisplay *display = gtk_widget_get_display (GTK_WIDGET (defbox));
+      priv->hand_cursor = gdk_cursor_new_for_display (display, GDK_HAND2);
+    }
+
+  if (!priv->regular_cursor)
+    {
+      GdkDisplay *display = gtk_widget_get_display (GTK_WIDGET (defbox));
+      priv->regular_cursor = gdk_cursor_new_for_display (display, GDK_XTERM);
+    }
+
+  gtk_text_view_get_iter_at_location (text_view, &iter, x, y);
+
+  tags = gtk_text_iter_get_tags (&iter);
+  for (l = tags; l != NULL; l = l->next)
+    {
+      GtkTextTag *tag = l->data;
+      gchar *name;
+
+      g_object_get (G_OBJECT (tag), "name", &name, NULL);
+      if (name &&
+          (strcmp (name, "link") == 0 ||
+           strcmp (name, "visited-link") == 0))
+        {
+          hovering = TRUE;
+          g_free (name);
+
+          break;
+        }
+
+      g_free (name);
+    }
+
+  if (hovering != defbox->priv->is_hovering)
+    {
+      defbox->priv->is_hovering = (hovering != FALSE);
+
+      if (defbox->priv->is_hovering)
+        gdk_window_set_cursor (gtk_text_view_get_window (text_view,
+                                                         GTK_TEXT_WINDOW_TEXT),
+                               defbox->priv->hand_cursor);
+      else
+        gdk_window_set_cursor (gtk_text_view_get_window (text_view,
+                                                         GTK_TEXT_WINDOW_TEXT),
+                               defbox->priv->regular_cursor);
+    }
+
+  if (tags)
+    g_slist_free (tags);
+}
+
+static gboolean
+defbox_motion_notify_cb (GtkWidget      *text_view,
+                         GdkEventMotion *event,
+                         GdictDefbox    *defbox)
+{
+  gint bx, by;
+
+  gtk_text_view_window_to_buffer_coords (GTK_TEXT_VIEW (text_view),
+                                         GTK_TEXT_WINDOW_WIDGET,
+                                         event->x, event->y,
+                                         &bx, &by);
+
+  set_cursor_if_appropriate (defbox, GTK_TEXT_VIEW (text_view), bx, by);
+
+  return FALSE;
+}
+
+static gboolean
+defbox_visibility_notify_cb (GtkWidget          *text_view,
+                             GdkEventVisibility *event,
+                             GdictDefbox        *defbox)
+{
+  GdkDisplay *display;
+  GdkSeat *seat;
+  GdkDevice *pointer;
+  gint wx, wy;
+  gint bx, by;
+
+  display = gdk_window_get_display (event->window);
+  seat = gdk_display_get_default_seat (display);
+  pointer = gdk_seat_get_pointer (seat);
+  gdk_window_get_device_position (gtk_widget_get_window (text_view), pointer, &wx, &wy, NULL);
+
+  gtk_text_view_window_to_buffer_coords (GTK_TEXT_VIEW (text_view),
+                                         GTK_TEXT_WINDOW_WIDGET,
+                                         wx, wy,
+                                         &bx, &by);
+
+  set_cursor_if_appropriate (defbox, GTK_TEXT_VIEW (text_view), bx, by);
+
+  return FALSE;
+}
+
+static GObject *
+gdict_defbox_constructor (GType                  type,
+			  guint                  n_construct_properties,
+			  GObjectConstructParam *construct_params)
+{
+  GdictDefbox *defbox;
+  GdictDefboxPrivate *priv;
+  GObject *object;
+  GtkWidget *sw;
+
+  object = G_OBJECT_CLASS (gdict_defbox_parent_class)->constructor (type,
+  						   n_construct_properties,
+  						   construct_params);
+  defbox = GDICT_DEFBOX (object);
+  priv = defbox->priv;
+
+  sw = gtk_scrolled_window_new (NULL, NULL);
+  gtk_widget_set_vexpand (sw, TRUE);
+  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
+  				  GTK_POLICY_AUTOMATIC,
+  				  GTK_POLICY_AUTOMATIC);
+  gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw),
+  				       GTK_SHADOW_IN);
+  gtk_box_pack_start (GTK_BOX (defbox), sw, TRUE, TRUE, 0);
+  gtk_widget_show (sw);
+
+  priv->buffer = gtk_text_buffer_new (NULL);
+  gdict_defbox_init_tags (defbox);
+
+  priv->text_view = gtk_text_view_new_with_buffer (priv->buffer);
+  gtk_text_view_set_editable (GTK_TEXT_VIEW (priv->text_view), FALSE);
+  gtk_text_view_set_left_margin (GTK_TEXT_VIEW (priv->text_view), 4);
+  gtk_container_add (GTK_CONTAINER (sw), priv->text_view);
+  gtk_widget_show (priv->text_view);
+
+  priv->find_pane = create_find_pane (defbox);
+  gtk_box_pack_end (GTK_BOX (defbox), priv->find_pane, FALSE, FALSE, 0);
+
+  /* stuff to make the link machinery work */
+  g_signal_connect (priv->text_view, "event-after",
+                    G_CALLBACK (defbox_event_after_cb),
+                    defbox);
+  g_signal_connect (priv->text_view, "motion-notify-event",
+                    G_CALLBACK (defbox_motion_notify_cb),
+                    defbox);
+  g_signal_connect (priv->text_view, "visibility-notify-event",
+                    G_CALLBACK (defbox_visibility_notify_cb),
+                    defbox);
+
+  return object;
+}
+
+/* we override the GtkWidget::show_all method since we have widgets
+ * we don't want to show, such as the find pane
+ */
+static void
+gdict_defbox_show_all (GtkWidget *widget)
+{
+  GdictDefbox *defbox = GDICT_DEFBOX (widget);
+  GdictDefboxPrivate *priv = defbox->priv;
+
+  gtk_widget_show (widget);
+
+  if (priv->show_find)
+    gtk_widget_show_all (priv->find_pane);
+}
+
+static void
+gdict_defbox_real_show_find (GdictDefbox *defbox)
+{
+  gtk_widget_show_all (defbox->priv->find_pane);
+  defbox->priv->show_find = TRUE;
+
+  gtk_widget_grab_focus (defbox->priv->find_entry);
+
+  defbox->priv->hide_timeout = g_timeout_add_seconds (5, hide_find_pane, defbox);
+}
+
+static void
+gdict_defbox_real_find_next (GdictDefbox *defbox)
+{
+  /* synthetize a "clicked" signal to the "next" button */
+  gtk_button_clicked (GTK_BUTTON (defbox->priv->find_next));
+}
+
+static void
+gdict_defbox_real_find_previous (GdictDefbox *defbox)
+{
+  /* synthetize a "clicked" signal to the "prev" button */
+  gtk_button_clicked (GTK_BUTTON (defbox->priv->find_prev));
+}
+
+static void
+gdict_defbox_real_hide_find (GdictDefbox *defbox)
+{
+  gtk_widget_hide (defbox->priv->find_pane);
+  defbox->priv->show_find = FALSE;
+
+  gtk_widget_grab_focus (defbox->priv->text_view);
+
+  if (defbox->priv->hide_timeout)
+    {
+      g_source_remove (defbox->priv->hide_timeout);
+      defbox->priv->hide_timeout = 0;
+    }
+}
+
+static void
+gdict_defbox_class_init (GdictDefboxClass *klass)
+{
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+  GtkBindingSet *binding_set;
+
+  gobject_class->constructor = gdict_defbox_constructor;
+  gobject_class->set_property = gdict_defbox_set_property;
+  gobject_class->get_property = gdict_defbox_get_property;
+  gobject_class->dispose = gdict_defbox_dispose;
+  gobject_class->finalize = gdict_defbox_finalize;
+
+  widget_class->show_all = gdict_defbox_show_all;
+
+  /**
+   * GdictDefbox:word:
+   *
+   * The word to look up.
+   *
+   * Since: 0.10
+   */
+  g_object_class_install_property (gobject_class,
+                                   PROP_WORD,
+                                   g_param_spec_string ("word",
+                                                        "Word",
+                                                        "The word to look up",
+                                                        NULL,
+                                                        G_PARAM_READWRITE));
+  /**
+   * GdictDefbox:context:
+   *
+   * The #GdictContext object used to get the word definition.
+   *
+   * Since: 0.1
+   */
+  g_object_class_install_property (gobject_class,
+  				   PROP_CONTEXT,
+  				   g_param_spec_object ("context",
+  				   			"Context",
+  				   			"The GdictContext object used to get the word definition",
+  				   			GDICT_TYPE_CONTEXT,
+  				   			(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT)));
+  /**
+   * GdictDefbox:database
+   *
+   * The database used by the #GdictDefbox bound to this object to get the word
+   * definition.
+   *
+   * Since: 0.1
+   */
+  g_object_class_install_property (gobject_class,
+		  		   PROP_DATABASE,
+				   g_param_spec_string ("database",
+					   		"Database",
+							"The database used to query the GdictContext",
+							GDICT_DEFAULT_DATABASE,
+							(G_PARAM_READABLE | G_PARAM_WRITABLE)));
+  /**
+   * GdictDefbox:font-name
+   *
+   * The name of the font used by the #GdictDefbox to display the definitions.
+   * use the same string you use for pango_font_description_from_string().
+   *
+   * Since: 0.3
+   */
+  g_object_class_install_property (gobject_class,
+		  		   PROP_FONT_NAME,
+				   g_param_spec_string ("font-name",
+					   		"Font Name",
+							"The font to be used by the defbox",
+							GDICT_DEFAULT_FONT_NAME,
+							(G_PARAM_READABLE | G_PARAM_WRITABLE)));
+
+  gdict_defbox_signals[SHOW_FIND] =
+    g_signal_new ("show-find",
+		  G_OBJECT_CLASS_TYPE (gobject_class),
+		  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+		  G_STRUCT_OFFSET (GdictDefboxClass, show_find),
+		  NULL, NULL,
+		  gdict_marshal_VOID__VOID,
+		  G_TYPE_NONE, 0);
+  gdict_defbox_signals[FIND_PREVIOUS] =
+    g_signal_new ("find-previous",
+                  G_OBJECT_CLASS_TYPE (gobject_class),
+                  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+                  G_STRUCT_OFFSET (GdictDefboxClass, find_previous),
+                  NULL, NULL,
+                  gdict_marshal_VOID__VOID,
+                  G_TYPE_NONE, 0);
+  gdict_defbox_signals[FIND_NEXT] =
+    g_signal_new ("find-next",
+		  G_OBJECT_CLASS_TYPE (gobject_class),
+		  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+		  G_STRUCT_OFFSET (GdictDefboxClass, find_next),
+		  NULL, NULL,
+		  gdict_marshal_VOID__VOID,
+		  G_TYPE_NONE, 0);
+  gdict_defbox_signals[HIDE_FIND] =
+    g_signal_new ("hide-find",
+		  G_OBJECT_CLASS_TYPE (gobject_class),
+		  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+		  G_STRUCT_OFFSET (GdictDefboxClass, hide_find),
+		  NULL, NULL,
+		  gdict_marshal_VOID__VOID,
+		  G_TYPE_NONE, 0);
+  gdict_defbox_signals[LINK_CLICKED] =
+    g_signal_new ("link-clicked",
+                  G_OBJECT_CLASS_TYPE (gobject_class),
+                  G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (GdictDefboxClass, link_clicked),
+                  NULL, NULL,
+                  gdict_marshal_VOID__STRING,
+                  G_TYPE_NONE, 1,
+                  G_TYPE_STRING);
+
+  klass->show_find = gdict_defbox_real_show_find;
+  klass->hide_find = gdict_defbox_real_hide_find;
+  klass->find_next = gdict_defbox_real_find_next;
+  klass->find_previous = gdict_defbox_real_find_previous;
+
+  binding_set = gtk_binding_set_by_class (klass);
+  gtk_binding_entry_add_signal (binding_set,
+  			        GDK_KEY_f, GDK_CONTROL_MASK,
+  			        "show-find",
+  			        0);
+  gtk_binding_entry_add_signal (binding_set,
+  			        GDK_KEY_g, GDK_CONTROL_MASK,
+  			        "find-next",
+  			        0);
+  gtk_binding_entry_add_signal (binding_set,
+  				GDK_KEY_g, GDK_SHIFT_MASK | GDK_CONTROL_MASK,
+  				"find-previous",
+  				0);
+  gtk_binding_entry_add_signal (binding_set,
+  			        GDK_KEY_Escape, 0,
+  			        "hide-find",
+  			        0);
+}
+
+static void
+gdict_defbox_init (GdictDefbox *defbox)
+{
+  GdictDefboxPrivate *priv;
+
+  gtk_orientable_set_orientation (GTK_ORIENTABLE (defbox), GTK_ORIENTATION_VERTICAL);
+  gtk_box_set_spacing (GTK_BOX (defbox), 6);
+
+  priv = gdict_defbox_get_instance_private (defbox);
+  defbox->priv = priv;
+
+  priv->context = NULL;
+  priv->database = g_strdup (GDICT_DEFAULT_DATABASE);
+  priv->font_name = g_strdup (GDICT_DEFAULT_FONT_NAME);
+  priv->word = NULL;
+
+  priv->definitions = NULL;
+
+  priv->busy_cursor = NULL;
+  priv->hand_cursor = NULL;
+  priv->regular_cursor = NULL;
+
+  priv->show_find = FALSE;
+  priv->is_searching = FALSE;
+  priv->is_hovering = FALSE;
+
+  priv->hide_timeout = 0;
+}
+
+/**
+ * gdict_defbox_new:
+ *
+ * Creates a new #GdictDefbox widget.  Use this widget to search for
+ * a word using a #GdictContext, and to show the resulting definition(s).
+ * You must set a #GdictContext for this widget using
+ * gdict_defbox_set_context().
+ *
+ * Return value: a new #GdictDefbox widget.
+ *
+ * Since: 0.1
+ */
+GtkWidget *
+gdict_defbox_new (void)
+{
+  return g_object_new (GDICT_TYPE_DEFBOX, NULL);
+}
+
+/**
+ * gdict_defbox_new_with_context:
+ * @context: a #GdictContext
+ *
+ * Creates a new #GdictDefbox widget. Use this widget to search for
+ * a word using @context, and to show the resulting definition.
+ *
+ * Return value: a new #GdictDefbox widget.
+ *
+ * Since: 0.1
+ */
+GtkWidget *
+gdict_defbox_new_with_context (GdictContext *context)
+{
+  g_return_val_if_fail (GDICT_IS_CONTEXT (context), NULL);
+
+  return g_object_new (GDICT_TYPE_DEFBOX, "context", context, NULL);
+}
+
+/**
+ * gdict_defbox_set_context:
+ * @defbox: a #GdictDefbox
+ * @context: a #GdictContext
+ *
+ * Sets @context as the #GdictContext to be used by @defbox in order
+ * to retrieve the definitions of a word.
+ *
+ * Since: 0.1
+ */
+void
+gdict_defbox_set_context (GdictDefbox  *defbox,
+			  GdictContext *context)
+{
+  g_return_if_fail (GDICT_IS_DEFBOX (defbox));
+  g_return_if_fail (context == NULL || GDICT_IS_CONTEXT (context));
+
+  g_object_set (defbox, "context", context, NULL);
+}
+
+/**
+ * gdict_defbox_get_context:
+ * @defbox: a #GdictDefbox
+ *
+ * Gets the #GdictContext used by @defbox.
+ *
+ * Return value: a #GdictContext.
+ *
+ * Since: 0.1
+ */
+GdictContext *
+gdict_defbox_get_context (GdictDefbox *defbox)
+{
+  g_return_val_if_fail (GDICT_IS_DEFBOX (defbox), NULL);
+
+  return defbox->priv->context;
+}
+
+/**
+ * gdict_defbox_set_database:
+ * @defbox: a #GdictDefbox
+ * @database: a database
+ *
+ * Sets @database as the database used by the #GdictContext bound to @defbox
+ * to query for word definitions.
+ *
+ * Since: 0.1
+ */
+void
+gdict_defbox_set_database (GdictDefbox *defbox,
+			   const gchar *database)
+{
+  GdictDefboxPrivate *priv;
+
+  g_return_if_fail (GDICT_IS_DEFBOX (defbox));
+
+  priv = defbox->priv;
+
+  g_free (priv->database);
+  priv->database = g_strdup (database);
+
+  g_object_notify (G_OBJECT (defbox), "database");
+}
+
+/**
+ * gdict_defbox_get_database:
+ * @defbox: a #GdictDefbox
+ *
+ * Gets the database used by @defbox.  See gdict_defbox_set_database().
+ *
+ * Return value: the name of a database. The return string is owned by
+ *   the #GdictDefbox widget and should not be modified or freed.
+ *
+ * Since: 0.1
+ */
+const gchar *
+gdict_defbox_get_database (GdictDefbox *defbox)
+{
+  g_return_val_if_fail (GDICT_IS_DEFBOX (defbox), NULL);
+
+  return defbox->priv->database;
+}
+
+/**
+ * gdict_defbox_get_word:
+ * @defbox: a #GdictDefbox
+ *
+ * Retrieves the word being looked up.
+ *
+ * Return value: the word looked up, or %NULL. The returned string is
+ *   owned by the #GdictDefbox widget and should never be modified or
+ *   freed.
+ *
+ * Since: 0.12
+ */
+const gchar *
+gdict_defbox_get_word (GdictDefbox *defbox)
+{
+  g_return_val_if_fail (GDICT_IS_DEFBOX (defbox), NULL);
+
+  return defbox->priv->word;
+}
+
+/**
+ * gdict_defbox_set_show_find:
+ * @defbox: a #GdictDefbox
+ * @show_find: %TRUE to show the find pane
+ *
+ * Whether @defbox should show the find pane.
+ *
+ * Since: 0.1
+ */
+void
+gdict_defbox_set_show_find (GdictDefbox *defbox,
+			    gboolean     show_find)
+{
+  GdictDefboxPrivate *priv;
+
+  g_return_if_fail (GDICT_IS_DEFBOX (defbox));
+
+  priv = defbox->priv;
+
+  if (priv->show_find == show_find)
+    return;
+
+  priv->show_find = (show_find != FALSE);
+  if (priv->show_find)
+    {
+      gtk_widget_show_all (priv->find_pane);
+      gtk_widget_grab_focus (priv->find_entry);
+
+      if (!priv->hide_timeout)
+        priv->hide_timeout = g_timeout_add_seconds (5, hide_find_pane, defbox);
+    }
+  else
+    {
+      gtk_widget_hide (priv->find_pane);
+
+      if (priv->hide_timeout)
+        {
+          g_source_remove (priv->hide_timeout);
+          priv->hide_timeout = 0;
+        }
+    }
+}
+
+/**
+ * gdict_defbox_get_show_find:
+ * @defbox: a #GdictDefbox
+ *
+ * Gets whether the find pane should be visible or not.
+ *
+ * Return value: %TRUE if the find pane is visible.
+ *
+ * Since: 0.1
+ */
+gboolean
+gdict_defbox_get_show_find (GdictDefbox *defbox)
+{
+  g_return_val_if_fail (GDICT_IS_DEFBOX (defbox), FALSE);
+
+  return (defbox->priv->show_find == TRUE);
+}
+
+static void
+lookup_start_cb (GdictContext *context,
+		 gpointer      user_data)
+{
+  GdictDefbox *defbox = GDICT_DEFBOX (user_data);
+  GdictDefboxPrivate *priv = defbox->priv;
+  GdkWindow *window;
+
+  priv->is_searching = TRUE;
+
+  if (!priv->busy_cursor)
+    {
+      GdkDisplay *display = gtk_widget_get_display (GTK_WIDGET (defbox));
+      priv->busy_cursor = gdk_cursor_new_for_display (display, GDK_WATCH);
+    }
+
+  window = gtk_text_view_get_window (GTK_TEXT_VIEW (priv->text_view),
+  				     GTK_TEXT_WINDOW_WIDGET);
+
+  gdk_window_set_cursor (window, priv->busy_cursor);
+}
+
+static void
+lookup_end_cb (GdictContext *context,
+	       gpointer      user_data)
+{
+  GdictDefbox *defbox = GDICT_DEFBOX (user_data);
+  GdictDefboxPrivate *priv = defbox->priv;
+  GtkTextBuffer *buffer;
+  GtkTextIter start;
+  GdkWindow *window;
+
+  /* explicitely move the cursor to the beginning */
+  buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->text_view));
+  gtk_text_buffer_get_start_iter (buffer, &start);
+  gtk_text_buffer_place_cursor (buffer, &start);
+
+  window = gtk_text_view_get_window (GTK_TEXT_VIEW (priv->text_view),
+  				     GTK_TEXT_WINDOW_WIDGET);
+
+  gdk_window_set_cursor (window, NULL);
+
+  priv->is_searching = FALSE;
+}
+
+static void
+gdict_defbox_insert_word (GdictDefbox *defbox,
+			  GtkTextIter *iter,
+			  const gchar *word)
+{
+  GdictDefboxPrivate *priv;
+  gchar *text;
+
+  if (!word)
+    return;
+
+  g_assert (GDICT_IS_DEFBOX (defbox));
+  priv = defbox->priv;
+
+  g_assert (GTK_IS_TEXT_BUFFER (priv->buffer));
+
+  text = g_strdup_printf ("%s\n", word);
+  gtk_text_buffer_insert_with_tags_by_name (priv->buffer,
+  					    iter,
+  					    text, strlen (text),
+  					    "big", "bold", "query-title",
+  					    NULL);
+  g_free (text);
+}
+
+/* escape a link string; links are expressed as "{...}".
+ * the link with the '{}' removed is stored inside link_str, while
+ * the returned value is a pointer to what follows the trailing '}'.
+ * link_str is allocated and should be freed.
+ */
+static const gchar *
+escape_link (const gchar  *str,
+             gchar       **link_str)
+{
+  gsize str_len;
+  GString *link_buf;
+  const gchar *p;
+
+  str_len = strlen (str);
+  link_buf = g_string_sized_new (str_len - 2);
+
+  for (p = str + 1; *p != '}'; p++)
+    {
+      link_buf = g_string_append_c (link_buf, *p);
+    }
+
+  if (link_str)
+    *link_str = g_string_free (link_buf, FALSE);
+
+  p++;
+
+  return p;
+}
+
+static const gchar *
+escape_phonethic (const gchar  *str,
+                  gchar       **phon_str)
+{
+  gsize str_len;
+  GString *phon_buf;
+  const gchar *p;
+
+  str_len = strlen (str);
+  phon_buf = g_string_sized_new (str_len - 2);
+
+  for (p = str + 1; *p != '\\'; p++)
+    {
+      phon_buf = g_string_append_c (phon_buf, *p);
+    }
+
+  if (phon_str)
+    *phon_str = g_string_free (phon_buf, FALSE);
+
+  p++;
+
+  return p;
+}
+
+static void
+gdict_defbox_insert_body (GdictDefbox *defbox,
+			  GtkTextIter *iter,
+			  const gchar *body)
+{
+  GdictDefboxPrivate *priv;
+  gchar **words;
+  gint len, i;
+  GtkTextIter end_iter;
+
+  if (!body)
+    return;
+
+  g_assert (GDICT_IS_DEFBOX (defbox));
+  priv = defbox->priv;
+
+  g_assert (GTK_IS_TEXT_BUFFER (priv->buffer));
+
+  words = g_strsplit (body, " ", -1);
+  len = g_strv_length (words);
+  end_iter = *iter;
+
+  for (i = 0; i < len; i++)
+    {
+      gchar *w = words[i];
+      gint w_len = strlen (w);
+      gchar *begin, *end;
+
+      if (w_len == 0)
+        continue;
+
+      begin = g_utf8_offset_to_pointer (w, 0);
+
+      if (*begin == '{')
+        {
+          end = g_utf8_strrchr (w, -1, '}');
+
+          /* see this is a self contained link */
+          if (end && *end == '}')
+            {
+              const gchar *rest;
+              gchar *link_str;
+
+              rest = escape_link (w, &link_str);
+
+              gtk_text_buffer_insert_with_tags_by_name (priv->buffer,
+                                                        &end_iter,
+                                                        link_str, -1,
+                                                        "link",
+                                                        NULL);
+
+              gtk_text_buffer_insert (priv->buffer, &end_iter, rest, -1);
+
+              gtk_text_buffer_get_end_iter (priv->buffer, &end_iter);
+              gtk_text_buffer_insert (priv->buffer, &end_iter, " ", 1);
+
+              g_free (link_str);
+
+              continue;
+            }
+          else
+            {
+              /* uh-oh: the link ends in another word */
+              GString *buf;
+              gchar *next;
+              gint cur = i;
+
+              buf = g_string_new (NULL);
+              next = words[cur++];
+
+              while (next && (end = g_utf8_strrchr (next, -1, '}')) == NULL)
+                {
+                  buf = g_string_append (buf, next);
+                  buf = g_string_append_c (buf, ' ');
+
+                  next = words[cur++];
+                }
+
+              buf = g_string_append (buf, next);
+
+              next = g_string_free (buf, FALSE);
+
+              if (end && *end == '}')
+                {
+                  const gchar *rest;
+                  gchar *link_str;
+
+                  rest = escape_link (next, &link_str);
+
+                  gtk_text_buffer_insert_with_tags_by_name (priv->buffer,
+                                                            &end_iter,
+                                                            link_str, -1,
+                                                            "link",
+                                                            NULL);
+
+                  gtk_text_buffer_insert (priv->buffer, &end_iter, rest, -1);
+                  gtk_text_buffer_insert (priv->buffer, &end_iter, " ", 1);
+
+                  g_free (link_str);
+                }
+
+              g_free (next);
+              i = cur;
+
+              continue;
+            }
+        }
+      else if (*begin == '\\')
+        {
+          end = g_utf8_strrchr (w, -1, '\\');
+
+          if (end && *end == '\\')
+            {
+              const gchar *rest;
+              gchar *phon;
+
+              rest = escape_phonethic (w, &phon);
+
+              gtk_text_buffer_insert_with_tags_by_name (priv->buffer,
+                                                        &end_iter,
+                                                        phon, -1,
+                                                        "italic", "phonetic",
+                                                        NULL);
+
+              gtk_text_buffer_insert (priv->buffer, &end_iter, rest, -1);
+
+              gtk_text_buffer_get_end_iter (priv->buffer, &end_iter);
+              gtk_text_buffer_insert (priv->buffer, &end_iter, " ", -1);
+
+              g_free (phon);
+
+              continue;
+            }
+        }
+
+      gtk_text_buffer_insert (priv->buffer, &end_iter, w, w_len);
+
+      gtk_text_buffer_get_end_iter (priv->buffer, &end_iter);
+      gtk_text_buffer_insert (priv->buffer, &end_iter, " ", 1);
+    }
+
+  gtk_text_buffer_get_end_iter (priv->buffer, &end_iter);
+  gtk_text_buffer_insert (priv->buffer, &end_iter, "\n", 1);
+
+  *iter = end_iter;
+
+  g_strfreev (words);
+}
+
+static void
+gdict_defbox_insert_from (GdictDefbox *defbox,
+			  GtkTextIter *iter,
+			  const gchar *database)
+{
+  GdictDefboxPrivate *priv;
+  gchar *text;
+
+  if (!database)
+    return;
+
+  g_assert (GDICT_IS_DEFBOX (defbox));
+  priv = defbox->priv;
+
+  g_assert (GTK_IS_TEXT_BUFFER (priv->buffer));
+
+  text = g_strdup_printf ("\t-- From %s\n\n", database);
+  gtk_text_buffer_insert_with_tags_by_name (priv->buffer,
+  					    iter,
+  					    text, strlen (text),
+  					    "small", "query-from",
+  					    NULL);
+  g_free (text);
+}
+
+static void
+gdict_defbox_insert_error (GdictDefbox *defbox,
+			   GtkTextIter *iter,
+			   const gchar *title,
+			   const gchar *message)
+{
+  GdictDefboxPrivate *priv;
+  GtkTextMark *mark;
+  GtkTextIter cur_iter;
+
+  if (!title)
+    return;
+
+  g_assert (GDICT_IS_DEFBOX (defbox));
+  priv = defbox->priv;
+
+  g_assert (GTK_IS_TEXT_BUFFER (priv->buffer));
+
+  mark = gtk_text_buffer_create_mark (priv->buffer, "block-cursor", iter, FALSE);
+  gtk_text_buffer_get_iter_at_mark (priv->buffer, &cur_iter, mark);
+
+  gtk_text_buffer_insert_with_tags_by_name (priv->buffer,
+  					    &cur_iter,
+  					    title, strlen (title),
+  					    "error-title", "big", "bold",
+  					    NULL);
+  gtk_text_buffer_get_iter_at_mark (priv->buffer, &cur_iter, mark);
+
+  gtk_text_buffer_insert (priv->buffer, &cur_iter, "\n\n", -1);
+  gtk_text_buffer_get_iter_at_mark (priv->buffer, &cur_iter, mark);
+
+  gtk_text_buffer_insert_with_tags_by_name (priv->buffer,
+		  			    &cur_iter,
+					    message, strlen (message),
+					    "error-message",
+					    NULL);
+}
+
+static void
+definition_found_cb (GdictContext    *context,
+		     GdictDefinition *definition,
+		     gpointer         user_data)
+{
+  GdictDefbox *defbox = GDICT_DEFBOX (user_data);
+  GdictDefboxPrivate *priv = defbox->priv;
+  GtkTextIter iter;
+  Definition *def;
+
+  /* insert the word if this is the first definition */
+  if (!priv->definitions)
+    {
+      gtk_text_buffer_get_start_iter (priv->buffer, &iter);
+      gdict_defbox_insert_word (defbox, &iter,
+				gdict_definition_get_word (definition));
+    }
+
+  def = definition_new ();
+
+  gtk_text_buffer_get_end_iter (priv->buffer, &iter);
+  def->begin = gtk_text_iter_get_offset (&iter);
+  gdict_defbox_insert_body (defbox, &iter, gdict_definition_get_text (definition));
+
+  gtk_text_buffer_get_end_iter (priv->buffer, &iter);
+  gdict_defbox_insert_from (defbox, &iter, gdict_definition_get_database (definition));
+
+  def->definition = gdict_definition_ref (definition);
+
+  priv->definitions = g_slist_append (priv->definitions, def);
+}
+
+static void
+error_cb (GdictContext *context,
+	  const GError *error,
+	  gpointer      user_data)
+{
+  GdictDefbox *defbox = GDICT_DEFBOX (user_data);
+  GdictDefboxPrivate *priv = defbox->priv;
+  GtkTextIter iter;
+
+  if (!error)
+    return;
+
+  gdict_defbox_clear (defbox);
+
+  gtk_text_buffer_get_start_iter (priv->buffer, &iter);
+  gdict_defbox_insert_error (defbox, &iter,
+		             _("Error while looking up definition"),
+		             error->message);
+
+  g_free (priv->word);
+  priv->word = NULL;
+
+  defbox->priv->is_searching = FALSE;
+}
+
+/**
+ * gdict_defbox_lookup:
+ * @defbox: a #GdictDefbox
+ * @word: the word to look up
+ *
+ * Searches @word inside the dictionary sources using the #GdictContext
+ * provided when creating @defbox or set using gdict_defbox_set_context().
+ *
+ * Since: 0.1
+ */
+void
+gdict_defbox_lookup (GdictDefbox *defbox,
+		     const gchar *word)
+{
+  GdictDefboxPrivate *priv;
+  GError *define_error;
+
+  g_return_if_fail (GDICT_IS_DEFBOX (defbox));
+
+  priv = defbox->priv;
+
+  if (!priv->context)
+    {
+      g_warning ("Attempting to look up `%s', but no GdictContext "
+		 "has been set.  Use gdict_defbox_set_context() "
+		 "before invoking gdict_defbox_lookup().",
+                 word);
+      return;
+    }
+
+  if (priv->is_searching)
+    {
+      _gdict_show_error_dialog (GTK_WIDGET (defbox),
+      			        _("Another search is in progress"),
+      			        _("Please wait until the current search ends."));
+
+      return;
+    }
+
+  gdict_defbox_clear (defbox);
+
+  if (!priv->start_id)
+    {
+      priv->start_id = g_signal_connect (priv->context, "lookup-start",
+  				         G_CALLBACK (lookup_start_cb),
+					 defbox);
+      priv->define_id = g_signal_connect (priv->context, "definition-found",
+  				          G_CALLBACK (definition_found_cb),
+  				          defbox);
+      priv->end_id = g_signal_connect (priv->context, "lookup-end",
+  				       G_CALLBACK (lookup_end_cb),
+  				       defbox);
+    }
+
+  if (!priv->error_id)
+    priv->error_id = g_signal_connect (priv->context, "error",
+  				       G_CALLBACK (error_cb),
+  				       defbox);
+
+  g_free (priv->word);
+  priv->word = g_strdup (word);
+  g_object_notify (G_OBJECT (defbox), "word");
+
+  define_error = NULL;
+  gdict_context_define_word (priv->context,
+  			     priv->database,
+  			     word,
+  			     &define_error);
+  if (define_error)
+    {
+      GtkTextIter iter;
+
+      gtk_text_buffer_get_start_iter (priv->buffer, &iter);
+      gdict_defbox_insert_error (defbox, &iter,
+    			         _("Error while retrieving the definition"),
+				 define_error->message);
+
+      g_error_free (define_error);
+    }
+}
+
+/**
+ * gdict_defbox_clear:
+ * @defbox: a @GdictDefbox
+ *
+ * Clears the buffer of @defbox
+ *
+ * Since: 0.1
+ */
+void
+gdict_defbox_clear (GdictDefbox *defbox)
+{
+  GdictDefboxPrivate *priv;
+  GtkTextIter start, end;
+
+  g_return_if_fail (GDICT_IS_DEFBOX (defbox));
+
+  priv = defbox->priv;
+
+  /* destroy previously found definitions */
+  if (priv->definitions)
+    {
+      g_slist_free_full (priv->definitions, (GDestroyNotify) definition_free);
+      priv->definitions = NULL;
+    }
+
+  gtk_text_buffer_get_bounds (priv->buffer, &start, &end);
+  gtk_text_buffer_delete (priv->buffer, &start, &end);
+}
+
+/**
+ * gdict_defbox_find_next:
+ * @defbox: a #GdictDefbox
+ *
+ * Emits the "find-next" signal.
+ *
+ * Since: 0.1
+ */
+void
+gdict_defbox_find_next (GdictDefbox *defbox)
+{
+  g_return_if_fail (GDICT_IS_DEFBOX (defbox));
+
+  g_signal_emit (defbox, gdict_defbox_signals[FIND_NEXT], 0);
+}
+
+/**
+ * gdict_defbox_find_previous:
+ * @defbox: a #GdictDefbox
+ *
+ * Emits the "find-previous" signal.
+ *
+ * Since: 0.1
+ */
+void
+gdict_defbox_find_previous (GdictDefbox *defbox)
+{
+  g_return_if_fail (GDICT_IS_DEFBOX (defbox));
+
+  g_signal_emit (defbox, gdict_defbox_signals[FIND_PREVIOUS], 0);
+}
+
+/**
+ * gdict_defbox_select_all:
+ * @defbox: a #GdictDefbox
+ *
+ * Selects all the text displayed by @defbox
+ *
+ * Since: 0.1
+ */
+void
+gdict_defbox_select_all (GdictDefbox *defbox)
+{
+  GdictDefboxPrivate *priv;
+  GtkTextBuffer *buffer;
+  GtkTextIter start, end;
+
+  g_return_if_fail (GDICT_IS_DEFBOX (defbox));
+
+  priv = defbox->priv;
+  buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->text_view));
+
+  gtk_text_buffer_get_bounds (buffer, &start, &end);
+  gtk_text_buffer_select_range (buffer, &start, &end);
+}
+
+/**
+ * gdict_defbox_copy_to_clipboard:
+ * @defbox: a #GdictDefbox
+ * @clipboard: a #GtkClipboard
+ *
+ * Copies the selected text inside @defbox into @clipboard.
+ *
+ * Since: 0.1
+ */
+void
+gdict_defbox_copy_to_clipboard (GdictDefbox  *defbox,
+				GtkClipboard *clipboard)
+{
+  GdictDefboxPrivate *priv;
+  GtkTextBuffer *buffer;
+
+  g_return_if_fail (GDICT_IS_DEFBOX (defbox));
+  g_return_if_fail (GTK_IS_CLIPBOARD (clipboard));
+
+  priv = defbox->priv;
+  buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->text_view));
+
+  gtk_text_buffer_copy_clipboard (buffer, clipboard);
+}
+
+/**
+ * gdict_defbox_count_definitions:
+ * @defbox: a #GdictDefbox
+ *
+ * Gets the number of definitions displayed by @defbox
+ *
+ * Return value: the number of definitions.
+ *
+ * Since: 0.1
+ */
+gint
+gdict_defbox_count_definitions (GdictDefbox *defbox)
+{
+  GdictDefboxPrivate *priv;
+
+  g_return_val_if_fail (GDICT_IS_DEFBOX (defbox), -1);
+
+  priv = defbox->priv;
+  if (!priv->definitions)
+    return -1;
+
+  return g_slist_length (priv->definitions);
+}
+
+/**
+ * gdict_defbox_jump_to_definition:
+ * @defbox: a #GdictDefbox
+ * @number: the definition to jump to
+ *
+ * Scrolls to the definition identified by @number.  If @number is -1,
+ * jumps to the last definition.
+ *
+ * Since: 0.1
+ */
+void
+gdict_defbox_jump_to_definition (GdictDefbox *defbox,
+				 gint         number)
+{
+  GdictDefboxPrivate *priv;
+  gint count;
+  Definition *def;
+  GtkTextBuffer *buffer;
+  GtkTextIter def_start;
+
+  g_return_if_fail (GDICT_IS_DEFBOX (defbox));
+
+  count = gdict_defbox_count_definitions (defbox) - 1;
+  if (count == -1)
+    return;
+
+  if ((number == -1) || (number > count))
+    number = count;
+
+  priv = defbox->priv;
+  def = (Definition *) g_slist_nth_data (priv->definitions, number);
+  if (!def)
+    return;
+
+  buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->text_view));
+  gtk_text_buffer_get_iter_at_offset (buffer, &def_start, def->begin);
+  gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->text_view),
+      				&def_start,
+      				0.0,
+      				TRUE,
+      				0.0, 0.0);
+}
+
+/**
+ * gdict_defbox_get_text:
+ * @defbox: a #GdictDefbox
+ * @length: return location for the text length or %NULL
+ *
+ * Gets the full contents of @defbox.
+ *
+ * Return value: a newly allocated string containing the text displayed by
+ *   @defbox.
+ *
+ * Since: 0.1
+ */
+gchar *
+gdict_defbox_get_text (GdictDefbox *defbox,
+		       gsize       *length)
+{
+  GdictDefboxPrivate *priv;
+  GtkTextBuffer *buffer;
+  GtkTextIter start, end;
+  gchar *retval;
+
+  g_return_val_if_fail (GDICT_IS_DEFBOX (defbox), NULL);
+
+  priv = defbox->priv;
+  buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->text_view));
+
+  gtk_text_buffer_get_bounds (buffer, &start, &end);
+
+  retval = gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
+
+  if (length)
+    *length = strlen (retval);
+
+  return retval;
+}
+
+/**
+ * gdict_defbox_set_font_name:
+ * @defbox: a #GdictDefbox
+ * @font_name: a font description, or %NULL
+ *
+ * Sets @font_name as the font for @defbox. It calls internally
+ * pango_font_description_from_string() and gtk_widget_modify_font().
+ *
+ * Passing %NULL for @font_name will reset any previously set font.
+ *
+ * Since: 0.3.0
+ */
+void
+gdict_defbox_set_font_name (GdictDefbox *defbox,
+			    const gchar *font_name)
+{
+  GdictDefboxPrivate *priv;
+  PangoFontDescription *font_desc;
+
+  g_return_if_fail (GDICT_IS_DEFBOX (defbox));
+
+  priv = defbox->priv;
+
+  if (font_name)
+    {
+      font_desc = pango_font_description_from_string (font_name);
+      g_return_if_fail (font_desc != NULL);
+    }
+  else
+    font_desc = NULL;
+
+  gtk_widget_override_font (priv->text_view, font_desc);
+
+  if (font_desc)
+    pango_font_description_free (font_desc);
+
+  g_free (priv->font_name);
+  priv->font_name = g_strdup (font_name);
+}
+
+/**
+ * gdict_defbox_get_font_name:
+ * @defbox: a #GdictDefbox
+ *
+ * Retrieves the font currently used by @defbox.
+ *
+ * Return value: a font name.  The returned string is owned by @defbox and
+ *   should not be modified or freed.
+ *
+ * Since: 0.3
+ */
+const gchar *
+gdict_defbox_get_font_name (GdictDefbox *defbox)
+{
+  g_return_val_if_fail (GDICT_IS_DEFBOX (defbox), NULL);
+
+  return defbox->priv->font_name;
+}
+
+/**
+ * gdict_defbox_get_selected_word:
+ * @defbox: a #GdictDefbox
+ *
+ * Retrieves the selected word from the defbox widget
+ *
+ * Return value: a newly allocated string containing the selected
+ *   word. Use g_free() when done using it.
+ *
+ * Since: 0.12
+ */
+gchar *
+gdict_defbox_get_selected_word (GdictDefbox *defbox)
+{
+  GdictDefboxPrivate *priv;
+  GtkTextBuffer *buffer;
+
+  g_return_val_if_fail (GDICT_IS_DEFBOX (defbox), NULL);
+
+  priv = defbox->priv;
+  buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->text_view));
+
+  if (!gtk_text_buffer_get_has_selection (buffer))
+    return NULL;
+  else
+    {
+      GtkTextIter start, end;
+      gchar *retval;
+
+      gtk_text_buffer_get_selection_bounds (buffer, &start, &end);
+      retval = gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
+
+      return retval;
+    }
+}
+
+ +
+ +
+ + diff --git a/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/29.html b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/29.html new file mode 100644 index 00000000..e9c13ad9 --- /dev/null +++ b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/29.html @@ -0,0 +1,2039 @@ + + + + + + Cppcheck - HTML report - mate-utils + + + + + +
+ + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
+479
+480
+481
+482
+483
+484
+485
+486
+487
+488
+489
+490
+491
+492
+493
+494
+495
+496
+497
+498
+499
+500
+501
+502
+503
+504
+505
+506
+507
+508
+509
+510
+511
+512
+513
+514
+515
+516
+517
+518
+519
+520
+521
+522
+523
+524
+525
+526
+527
+528
+529
+530
+531
+532
+533
+534
+535
+536
+537
+538
+539
+540
+541
+542
+543
+544
+545
+546
+547
+548
+549
+550
+551
+552
+553
+554
+555
+556
+557
+558
+559
+560
+561
+562
+563
+564
+565
+566
+567
+568
+569
+570
+571
+572
+573
+574
+575
+576
+577
+578
+579
+580
+581
+582
+583
+584
+585
+586
+587
+588
+589
+590
+591
+592
+593
+594
+595
+596
+597
+598
+599
+600
+601
+602
+603
+604
+605
+606
+607
+608
+609
+610
+611
+612
+613
+614
+615
+616
+617
+618
+619
+620
+621
+622
+623
+624
+625
+626
+627
+628
+629
+630
+631
+632
+633
+634
+635
+636
+637
+638
+639
+640
+641
+642
+643
+644
+645
+646
+647
+648
+649
+650
+651
+652
+653
+654
+655
+656
+657
+658
+659
+660
+661
+662
+663
+664
+665
+666
+667
+668
+669
+670
+671
+672
+673
+674
+675
+676
+677
+678
+679
+680
+681
+682
+683
+684
+685
+686
+687
+688
+689
+690
+691
+692
+693
+694
+695
+696
+697
+698
+699
+700
+701
+702
+703
+704
+705
+706
+707
+708
+709
+710
+711
+712
+713
+714
+715
+716
+717
+718
+719
+720
+721
+722
+723
+724
+725
+726
+727
+728
+729
+730
+731
+732
+733
+734
+735
+736
+737
+738
+739
+740
+741
+742
+743
+744
+745
+746
+747
+748
+749
+750
+751
+752
+753
+754
+755
+756
+757
+758
+759
+760
+761
+762
+763
+764
+765
+766
+767
+768
+769
+770
+771
+772
+773
+774
+775
+776
+777
+778
+779
+780
+781
+782
+783
+784
+785
+786
+787
+788
+789
+790
+791
+792
+793
+794
+795
+796
+797
+798
+799
+800
+801
+802
+803
+804
+805
+806
+807
+808
+809
+810
+811
+812
+813
+814
+815
+816
+817
+818
+819
+820
+821
+822
+823
+824
+825
+826
+827
+828
+829
+830
+831
+832
+833
+834
+835
+836
+837
+838
+839
+840
+841
+842
+843
+844
+845
+846
+847
+848
+849
+850
+851
+852
+853
+854
+855
+856
+857
+858
+859
+860
+861
+862
+863
+864
+865
+866
+867
+868
+869
+870
+871
+872
+873
+874
+875
+876
+877
+878
+879
+880
+881
+882
+883
+884
+885
+886
+887
+888
+889
+890
+891
+892
+893
+894
+895
+896
+897
+898
+899
+900
+901
/* Copyright (C) 2007 Emmanuele Bassi <ebassi@gnome.org>
+ * Copyright (C) 2012-2021 MATE Developers
+ *
+ * This file is part of MATE Utils.
+ *
+ * MATE Utils is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * MATE Utils is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MATE Utils.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+/**
+ * SECTION:gdict-source-chooser
+ * @short_description: Display the list of available sources
+ *
+ * #GdictSourceChooser is a widget that shows the list of available
+ * dictionary sources using a #GdictSourceLoader instance as a model.
+ * It can be used to allow choosing the current dictionary source.
+ *
+ * #GdictSourceChooser is available since Gdict 0.12.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib/gi18n-lib.h>
+
+#include <gdk/gdk.h>
+
+#include <gtk/gtk.h>
+
+#include "gdict-source-chooser.h"
+#include "gdict-utils.h"
+#include "gdict-private.h"
+#include "gdict-enum-types.h"
+#include "gdict-marshal.h"
+
+struct _GdictSourceChooserPrivate
+{
+  GtkListStore *store;
+
+  GtkWidget *treeview;
+  GtkWidget *refresh_button;
+  GtkWidget *buttons_box;
+
+  GdictSourceLoader *loader;
+  gint n_sources;
+
+  gchar *current_source;
+};
+
+enum
+{
+  SOURCE_TRANSPORT,
+  SOURCE_NAME,
+  SOURCE_DESCRIPTION,
+  SOURCE_CURRENT,
+
+  SOURCE_N_COLUMNS
+};
+
+enum
+{
+  PROP_0,
+
+  PROP_LOADER,
+  PROP_COUNT
+};
+
+enum
+{
+  SOURCE_ACTIVATED,
+  SELECTION_CHANGED,
+
+  LAST_SIGNAL
+};
+
+static guint source_chooser_signals[LAST_SIGNAL] = { 0, };
+
+G_DEFINE_TYPE_WITH_PRIVATE (GdictSourceChooser, gdict_source_chooser, GTK_TYPE_BOX)<--- There is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
+
+static void
+gdict_source_chooser_finalize (GObject *gobject)
+{
+  GdictSourceChooser *chooser = GDICT_SOURCE_CHOOSER (gobject);
+  GdictSourceChooserPrivate *priv = chooser->priv;
+
+  g_free (priv->current_source);
+
+  G_OBJECT_CLASS (gdict_source_chooser_parent_class)->finalize (gobject);
+}
+
+static void
+gdict_source_chooser_dispose (GObject *gobject)
+{
+  GdictSourceChooser *chooser = GDICT_SOURCE_CHOOSER (gobject);
+  GdictSourceChooserPrivate *priv = chooser->priv;
+
+  if (priv->store)
+    {
+      g_object_unref (priv->store);
+      priv->store = NULL;
+    }
+
+  if (priv->loader)
+    {
+      g_object_unref (priv->loader);
+      priv->loader = NULL;
+    }
+
+  G_OBJECT_CLASS (gdict_source_chooser_parent_class)->dispose (gobject);
+}
+
+static void
+gdict_source_chooser_set_property (GObject      *gobject,
+                                   guint         prop_id,
+                                   const GValue *value,
+                                   GParamSpec   *pspec)
+{
+  switch (prop_id)
+    {
+    case PROP_LOADER:
+      gdict_source_chooser_set_loader (GDICT_SOURCE_CHOOSER (gobject),
+                                       g_value_get_object (value));
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+gdict_source_chooser_get_property (GObject    *gobject,
+                                   guint       prop_id,
+                                   GValue     *value,
+                                   GParamSpec *pspec)
+{
+  GdictSourceChooserPrivate *priv;
+
+  priv = GDICT_SOURCE_CHOOSER (gobject)->priv;
+
+  switch (prop_id)
+    {
+    case PROP_LOADER:
+      g_value_set_object (value, priv->loader);
+      break;
+    case PROP_COUNT:
+      g_value_set_int (value, priv->n_sources);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+row_activated_cb (GtkTreeView       *treeview,
+                  GtkTreePath       *path,
+                  GtkTreeViewColumn *column,
+                  gpointer           data)
+{
+  GdictSourceChooser *chooser = GDICT_SOURCE_CHOOSER (data);
+  GdictSourceChooserPrivate *priv = chooser->priv;
+  GtkTreeIter iter;
+  gchar *name;
+  GdictSource *source;
+
+  if (!priv->loader)
+    return;
+
+  if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (priv->store), &iter, path))
+    return;
+
+  gtk_tree_model_get (GTK_TREE_MODEL (priv->store), &iter,
+                      SOURCE_NAME, &name,
+                      -1);
+  if (!name)
+    return;
+
+  source = gdict_source_loader_get_source (priv->loader, name);
+  if (!source)
+    {
+      g_free (name);
+      return;
+    }
+
+  g_signal_emit (chooser, source_chooser_signals[SOURCE_ACTIVATED], 0,
+                 name, source);
+
+  g_free (name);
+  g_object_unref (source);
+}
+
+static void
+refresh_button_clicked_cb (GtkButton *button,
+                           gpointer   data)
+{
+  gdict_source_chooser_refresh (GDICT_SOURCE_CHOOSER (data));
+}
+
+static void
+selection_changed_cb (GtkTreeSelection *selection,
+                      gpointer          data)
+{
+  g_signal_emit (data, source_chooser_signals[SELECTION_CHANGED], 0);
+}
+
+static GObject *
+gdict_source_chooser_constructor (GType                  gtype,
+                                  guint                  n_params,
+                                  GObjectConstructParam *params)
+{
+  GdictSourceChooser *chooser;
+  GdictSourceChooserPrivate *priv;
+  GObjectClass *parent_class;
+  GObject *retval;
+  GtkWidget *sw;
+  GtkCellRenderer *renderer;
+  GtkTreeViewColumn *column;
+  GtkWidget *hbox;
+
+  parent_class = G_OBJECT_CLASS (gdict_source_chooser_parent_class);
+  retval = parent_class->constructor (gtype, n_params, params);
+
+  chooser = GDICT_SOURCE_CHOOSER (retval);
+  priv = chooser->priv;
+
+  sw = gtk_scrolled_window_new (NULL, NULL);
+  gtk_widget_set_vexpand (sw, TRUE);
+  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
+                                  GTK_POLICY_AUTOMATIC,
+                                  GTK_POLICY_AUTOMATIC);
+  gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw),
+                                       GTK_SHADOW_IN);
+  gtk_box_pack_start (GTK_BOX (chooser), sw, TRUE, TRUE, 0);
+  gtk_widget_show (sw);
+
+  renderer = gtk_cell_renderer_text_new ();
+  column = gtk_tree_view_column_new_with_attributes ("sources",
+                                                     renderer,
+                                                     "text", SOURCE_DESCRIPTION,
+                                                     "weight", SOURCE_CURRENT,
+                                                     NULL);
+  priv->treeview = gtk_tree_view_new ();
+  gtk_tree_view_set_model (GTK_TREE_VIEW (priv->treeview),
+                           GTK_TREE_MODEL (priv->store));
+  gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (priv->treeview), FALSE);
+  gtk_tree_view_append_column (GTK_TREE_VIEW (priv->treeview), column);
+  g_signal_connect (gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->treeview)),
+                    "changed", G_CALLBACK (selection_changed_cb),
+                    chooser);
+  g_signal_connect (priv->treeview,
+                    "row-activated", G_CALLBACK (row_activated_cb),
+                    chooser);
+  gtk_container_add (GTK_CONTAINER (sw), priv->treeview);
+  gtk_widget_show (priv->treeview);
+
+  hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+  priv->buttons_box = hbox;
+
+  priv->refresh_button = gtk_button_new ();
+  gtk_button_set_image (GTK_BUTTON (priv->refresh_button),
+                        gtk_image_new_from_icon_name ("view-refresh",
+                                                      GTK_ICON_SIZE_BUTTON));
+  g_signal_connect (priv->refresh_button,
+                    "clicked", G_CALLBACK (refresh_button_clicked_cb),
+                    chooser);
+  gtk_box_pack_start (GTK_BOX (hbox), priv->refresh_button, FALSE, FALSE, 0);
+  gtk_widget_show (priv->refresh_button);
+  gtk_widget_set_tooltip_text (priv->refresh_button,
+                               _("Reload the list of available sources"));
+
+  gtk_box_pack_end (GTK_BOX (chooser), hbox, FALSE, FALSE, 0);
+  gtk_widget_show (hbox);
+
+  return retval;
+}
+
+static void
+gdict_source_chooser_class_init (GdictSourceChooserClass *klass)
+{
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+  gobject_class->finalize = gdict_source_chooser_finalize;
+  gobject_class->dispose = gdict_source_chooser_dispose;
+  gobject_class->set_property = gdict_source_chooser_set_property;
+  gobject_class->get_property = gdict_source_chooser_get_property;
+  gobject_class->constructor = gdict_source_chooser_constructor;
+
+  /**
+   * GdictSourceChooser:loader:
+   *
+   * The #GdictSourceLoader used to retrieve the list of available
+   * dictionary sources.
+   *
+   * Since: 0.12
+   */
+  g_object_class_install_property (gobject_class,
+                                   PROP_LOADER,
+                                   g_param_spec_object ("loader",
+                                                        "Loader",
+                                                        "The GdictSourceLoader used to get the list of sources",
+                                                        GDICT_TYPE_SOURCE_LOADER,
+                                                        G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+  /**
+   * GdictSourceChooser:count:
+   *
+   * The number of available dictionary sources, or -1 if no
+   * #GdictSourceLoader is set.
+   *
+   * Since: 0.12
+   */
+  g_object_class_install_property (gobject_class,
+                                   PROP_COUNT,
+                                   g_param_spec_int ("count",
+                                                     "Count",
+                                                     "The number of available dictionary sources",
+                                                     -1, G_MAXINT, -1,
+                                                     G_PARAM_READABLE));
+
+  /**
+   * GdictSourceChooser::source-activated:
+   * @chooser: the #GdictSourceChooser that received the signal
+   * @source_name: the name of the activated source
+   * @source: the activated #GdictSource
+   *
+   * The ::source-activated signal is emitted each time the user
+   * activates a row in the source chooser widget, either by double
+   * clicking on it or by a keyboard event.
+   *
+   * Since: 0.12
+   */
+  source_chooser_signals[SOURCE_ACTIVATED] =
+    g_signal_new ("source-activated",
+                  G_OBJECT_CLASS_TYPE (gobject_class),
+                  G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (GdictSourceChooserClass, source_activated),
+                  NULL, NULL,
+                  gdict_marshal_VOID__STRING_OBJECT,
+                  G_TYPE_NONE, 2,
+                  G_TYPE_STRING,
+                  GDICT_TYPE_SOURCE);
+  /**
+   * GdictSourceChooser::selection-changed:
+   * @chooser: the #GdictSourceChooser that received the signal
+   *
+   * The ::selection-changed signal is emitted each time the
+   * selection inside the source chooser widget has been changed.
+   *
+   * Since: 0.12
+   */
+  source_chooser_signals[SELECTION_CHANGED] =
+    g_signal_new ("selection-changed",
+                  G_OBJECT_CLASS_TYPE (gobject_class),
+                  G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (GdictSourceChooserClass, selection_changed),
+                  NULL, NULL,
+                  gdict_marshal_VOID__VOID,
+                  G_TYPE_NONE, 0);
+}
+
+static void
+gdict_source_chooser_init (GdictSourceChooser *chooser)
+{
+  GdictSourceChooserPrivate *priv;
+
+  chooser->priv = priv = gdict_source_chooser_get_instance_private (chooser);
+
+  gtk_orientable_set_orientation (GTK_ORIENTABLE (chooser), GTK_ORIENTATION_VERTICAL);
+
+  priv->store = gtk_list_store_new (SOURCE_N_COLUMNS,
+                                    G_TYPE_INT,    /* TRANSPORT */
+                                    G_TYPE_STRING, /* NAME */
+                                    G_TYPE_STRING, /* DESCRIPTION */
+                                    G_TYPE_INT     /* CURRENT */);
+
+  priv->loader = NULL;
+  priv->n_sources = -1;
+}
+
+/**
+ * gdict_source_chooser_new:
+ *
+ * Creates a new #GdictSourceChooser widget. This widget can be used to
+ * display the list of available dictionary sources.
+ *
+ * Return value: the newly created #GdictSourceChooser widget.
+ *
+ * Since: 0.12
+ */
+GtkWidget *
+gdict_source_chooser_new (void)
+{
+  return g_object_new (GDICT_TYPE_SOURCE_CHOOSER, NULL);
+}
+
+/**
+ * gdict_source_chooser_new_with_loader:
+ * @loader: a #GdictSourceLoader
+ *
+ * Creates a new #GdictSourceChooser widget and sets @loader as the
+ * #GdictSourceLoader object to be used to retrieve the list of
+ * available dictionary sources.
+ *
+ * Return value: the newly created #GdictSourceChooser widget.
+ *
+ * Since: 0.12
+ */
+GtkWidget *
+gdict_source_chooser_new_with_loader (GdictSourceLoader *loader)
+{
+  g_return_val_if_fail (GDICT_IS_SOURCE_LOADER (loader), NULL);
+
+  return g_object_new (GDICT_TYPE_SOURCE_CHOOSER, "loader", loader, NULL);
+}
+
+/**
+ * gdict_source_chooser_set_loader:
+ * @chooser: a #GdictSourceChooser
+ * @loader: a #GdictSourceLoader or %NULL to unset it
+ *
+ * Sets the #GdictSourceLoader to be used by the source chooser
+ * widget.
+ *
+ * Since: 0.12
+ */
+void
+gdict_source_chooser_set_loader (GdictSourceChooser *chooser,
+                                 GdictSourceLoader  *loader)
+{
+  GdictSourceChooserPrivate *priv;
+
+  g_return_if_fail (GDICT_IS_SOURCE_CHOOSER (chooser));
+  g_return_if_fail (loader == NULL || GDICT_IS_SOURCE_LOADER (loader));
+
+  priv = chooser->priv;
+
+  if (priv->loader != loader)
+    {
+      if (priv->loader)
+        g_object_unref (priv->loader);
+
+      if (loader)
+        {
+          priv->loader = g_object_ref (loader);
+          gdict_source_chooser_refresh (chooser);
+        }
+
+      g_object_notify (G_OBJECT (chooser), "loader");
+    }
+}
+
+/**
+ * gdict_source_chooser_get_loader:
+ * @chooser: a #GdictSourceChooser
+ *
+ * Retrieves the #GdictSourceLoader used by @chooser.
+ *
+ * Return value: a #GdictSourceLoader or %NULL is none is set
+ *
+ * Since: 0.12
+ */
+GdictSourceLoader *
+gdict_source_chooser_get_loader (GdictSourceChooser *chooser)
+{
+  g_return_val_if_fail (GDICT_IS_SOURCE_CHOOSER (chooser), NULL);
+
+  return chooser->priv->loader;
+}
+
+typedef struct
+{
+  gchar *source_name;
+  GdictSourceChooser *chooser;
+
+  guint found       : 1;
+  guint do_select   : 1;
+  guint do_activate : 1;
+} SelectData;
+
+static gboolean
+scan_for_source_name (GtkTreeModel *model,
+                      GtkTreePath  *path,
+                      GtkTreeIter  *iter,
+                      gpointer      user_data)
+{
+  SelectData *select_data = user_data;
+  gchar *source_name = NULL;
+
+  if (!select_data)
+    return TRUE;
+
+  gtk_tree_model_get (model, iter, SOURCE_NAME, &source_name, -1);
+  if (!source_name)
+    return FALSE;
+
+  if (strcmp (source_name, select_data->source_name) == 0)
+    {
+      GtkTreeView *tree_view;
+      GtkTreeSelection *selection;
+
+      select_data->found = TRUE;
+
+      tree_view = GTK_TREE_VIEW (select_data->chooser->priv->treeview);
+
+      if (select_data->do_activate)
+        {
+          GtkTreeViewColumn *column;
+
+          column = gtk_tree_view_get_column (tree_view, 2);
+
+          gtk_list_store_set (GTK_LIST_STORE (model), iter,
+                              SOURCE_CURRENT, PANGO_WEIGHT_BOLD,
+                              -1);
+
+          gtk_tree_view_row_activated (tree_view, path, column);
+        }
+
+      selection = gtk_tree_view_get_selection (tree_view);
+      if (select_data->do_select)
+        gtk_tree_selection_select_path (selection, path);
+      else
+        gtk_tree_selection_unselect_path (selection, path);
+    }
+  else
+    {
+      gtk_list_store_set (GTK_LIST_STORE (model), iter,
+                          SOURCE_CURRENT, PANGO_WEIGHT_NORMAL,
+                          -1);
+    }
+
+  g_free (source_name);
+
+  return FALSE;
+}
+
+/**
+ * gdict_source_chooser_select_source:
+ * @chooser: a #GdictSourceChooser
+ * @source_name: the name of a dictionary source
+ *
+ * Selects the dictionary source named @source_name inside @chooser.
+ * The selection is moved but the row containing the dictionary source
+ * is not activated.
+ *
+ * Return value: %TRUE if the source was found and selected
+ *
+ * Since: 0.12
+ */
+gboolean
+gdict_source_chooser_select_source (GdictSourceChooser *chooser,
+                                    const gchar        *source_name)
+{
+  GdictSourceChooserPrivate *priv;
+  SelectData data;
+  gboolean retval;
+
+  g_return_val_if_fail (GDICT_IS_SOURCE_CHOOSER (chooser), FALSE);
+  g_return_val_if_fail (source_name != NULL, FALSE);
+
+  priv = chooser->priv;
+
+  data.source_name = g_strdup (source_name);
+  data.chooser = chooser;
+  data.found = FALSE;
+  data.do_select = TRUE;
+  data.do_activate = FALSE;
+
+  gtk_tree_model_foreach (GTK_TREE_MODEL (priv->store),
+                          scan_for_source_name,
+                          &data);
+
+  retval = data.found;
+
+  g_free (data.source_name);
+
+  return retval;
+}
+
+/**
+ * gdict_source_chooser_unselect_source:
+ * @chooser: a #GdictSourceChooser
+ * @source_name: the name of a dictionary source
+ *
+ * Unselects @source_name inside @chooser.
+ *
+ * Return value: %TRUE if the source was found and unselected
+ *
+ * Since: 0.12
+ */
+gboolean
+gdict_source_chooser_unselect_source (GdictSourceChooser *chooser,
+                                      const gchar        *source_name)
+{
+  GdictSourceChooserPrivate *priv;
+  SelectData data;
+  gboolean retval;
+
+  g_return_val_if_fail (GDICT_IS_SOURCE_CHOOSER (chooser), FALSE);
+  g_return_val_if_fail (source_name != NULL, FALSE);
+
+  priv = chooser->priv;
+
+  data.source_name = g_strdup (source_name);
+  data.chooser = chooser;
+  data.found = FALSE;
+  data.do_select = FALSE;
+  data.do_activate = FALSE;
+
+  gtk_tree_model_foreach (GTK_TREE_MODEL (priv->store),
+                          scan_for_source_name,
+                          &data);
+
+  retval = data.found;
+
+  g_free (data.source_name);
+
+  return retval;
+}
+
+/**
+ * gdict_source_chooser_set_current_source:
+ * @chooser: a #GdictSourceChooser
+ * @source_name: the name of a dictionary source
+ *
+ * Sets the current dictionary source named @source_name. The row
+ * of the source, if found, will be selected and activated.
+ *
+ * Return value: %TRUE if the source was found
+ *
+ * Since: 0.12
+ */
+gboolean
+gdict_source_chooser_set_current_source (GdictSourceChooser *chooser,
+                                         const gchar        *source_name)
+{
+  GdictSourceChooserPrivate *priv;
+  SelectData data;
+  gboolean retval;
+
+  g_return_val_if_fail (GDICT_IS_SOURCE_CHOOSER (chooser), FALSE);
+  g_return_val_if_fail (source_name != NULL, FALSE);
+
+  priv = chooser->priv;
+
+  if (priv->current_source && !strcmp (priv->current_source, source_name))
+    return TRUE;
+
+  data.source_name = g_strdup (source_name);
+  data.chooser = chooser;
+  data.found = FALSE;
+  data.do_select = TRUE;
+  data.do_activate = TRUE;
+
+  gtk_tree_model_foreach (GTK_TREE_MODEL (priv->store),
+                          scan_for_source_name,
+                          &data);
+
+  retval = data.found;
+
+  GDICT_NOTE (CHOOSER, "%s current source: %s",
+              data.found ? "set" : "not set",
+              data.source_name);
+
+  if (data.found)
+    {
+      g_free (priv->current_source);
+      priv->current_source = data.source_name;
+    }
+  else
+    g_free (data.source_name);
+
+  return retval;
+}
+
+/**
+ * gdict_source_chooser_get_current_source:
+ * @chooser: a #GdictSourceChooser
+ *
+ * Retrieves the currently selected source.
+ *
+ * Return value: a newly allocated string containing the name of
+ *   the currently selected source. Use g_free() when done using it
+ *
+ * Since: 0.12
+ */
+gchar *
+gdict_source_chooser_get_current_source (GdictSourceChooser *chooser)
+{
+  GdictSourceChooserPrivate *priv;
+  GtkTreeSelection *selection;
+  GtkTreeModel *model;
+  GtkTreeIter iter;
+  gchar *retval = NULL;
+
+  g_return_val_if_fail (GDICT_IS_SOURCE_CHOOSER (chooser), NULL);
+
+  priv = chooser->priv;
+
+  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->treeview));
+  if (!gtk_tree_selection_get_selected (selection, &model, &iter))
+    return NULL;
+
+  gtk_tree_model_get (model, &iter, SOURCE_NAME, &retval, -1);
+
+  g_free (priv->current_source);
+  priv->current_source = g_strdup (retval);
+
+  return retval;
+}
+
+/**
+ * gdict_source_chooser_get_sources:
+ * @chooser: a #GdictSouceChooser
+ * @length: return location for the length of the returned vector
+ *
+ * Retrieves the names of the available dictionary sources.
+ *
+ * Return value: a newly allocated, %NULL terminated string vector
+ *   containing the names of the available sources. Use g_strfreev()
+ *   when done using it.
+ *
+ * Since: 0.12
+ */
+gchar **
+gdict_source_chooser_get_sources (GdictSourceChooser *chooser,
+                                  gsize              *length)
+{
+  GdictSourceChooserPrivate *priv;
+  gchar **retval;
+  gsize retval_len;
+
+  g_return_val_if_fail (GDICT_IS_SOURCE_CHOOSER (chooser), NULL);
+
+  priv = chooser->priv;
+
+  if (!priv->loader)
+    return NULL;
+
+  retval = gdict_source_loader_get_names (priv->loader, &retval_len);
+  if (length)
+    *length = retval_len;
+
+  return retval;
+}
+
+/**
+ * gdict_source_chooser_count_sources:
+ * @chooser: a #GdictSourceChooser
+ *
+ * Retrieve the number of available dictionary sources.
+ *
+ * Return value: the number of available sources, or -1 if no
+ *   #GdictSourceLoader has been set
+ *
+ * Since: 0.12
+ */
+gint
+gdict_source_chooser_count_sources (GdictSourceChooser *chooser)
+{
+  g_return_val_if_fail (GDICT_IS_SOURCE_CHOOSER (chooser), -1);
+
+  return chooser->priv->n_sources;
+}
+
+/**
+ * gdict_source_chooser_has_source:
+ * @chooser: a #GdictSourceChooser
+ * @source_name: the name of a dictionary source
+ *
+ * Checks whether @chooser has a dictionary source named @source_name.
+ *
+ * Return value: %TRUE if the dictionary source was found
+ *
+ * Since: 0.12
+ */
+gboolean
+gdict_source_chooser_has_source (GdictSourceChooser *chooser,
+                                 const gchar        *source_name)
+{
+  GdictSourceChooserPrivate *priv;
+
+  g_return_val_if_fail (GDICT_IS_SOURCE_CHOOSER (chooser), FALSE);
+  g_return_val_if_fail (source_name != NULL, FALSE);
+
+  priv = chooser->priv;
+
+  if (!priv->loader)
+    return FALSE;
+
+  return gdict_source_loader_has_source (priv->loader, source_name);
+}
+
+/**
+ * gdict_source_chooser_refresh:
+ * @chooser: a #GdictSourceChooser
+ *
+ * Forces a refresh on the contents of the source chooser widget
+ *
+ * Since: 0.12
+ */
+void
+gdict_source_chooser_refresh (GdictSourceChooser *chooser)
+{
+  GdictSourceChooserPrivate *priv;
+
+  g_return_if_fail (GDICT_IS_SOURCE_CHOOSER (chooser));
+
+  priv = chooser->priv;
+
+  if (priv->loader)
+    {
+      const GSList *sources, *l;
+
+      if (priv->treeview)
+        gtk_tree_view_set_model (GTK_TREE_VIEW (priv->treeview), NULL);
+
+      gtk_list_store_clear (priv->store);
+
+      sources = gdict_source_loader_get_sources (priv->loader);
+      for (l = sources; l != NULL; l = l->next)
+        {
+          GdictSource *source = l->data;
+          const gchar *name, *description;
+          GdictSourceTransport transport;
+          gint weight;
+
+          transport = gdict_source_get_transport (source);
+          name = gdict_source_get_name (source);
+          description = gdict_source_get_description (source);
+          weight = PANGO_WEIGHT_NORMAL;
+
+          if (priv->current_source && !strcmp (priv->current_source, name))
+            weight = PANGO_WEIGHT_BOLD;
+
+          gtk_list_store_insert_with_values (priv->store, NULL, -1,
+                                             SOURCE_TRANSPORT, transport,
+                                             SOURCE_NAME, name,
+                                             SOURCE_DESCRIPTION, description,
+                                             SOURCE_CURRENT, weight,
+                                             -1);
+        }
+
+      if (priv->treeview)
+        gtk_tree_view_set_model (GTK_TREE_VIEW (priv->treeview),
+                                 GTK_TREE_MODEL (priv->store));
+    }
+}
+
+/**
+ * gdict_source_chooser_add_button:
+ * @chooser: a #GdictSourceChooser
+ * @button_text: text of the button
+ *
+ * Adds a #GtkButton with @button_text to the button area on
+ * the bottom of @chooser. The @button_text can also be a
+ * stock ID.
+ *
+ * Return value: the newly packed button.
+ *
+ * Since: 0.12
+ */
+GtkWidget *
+gdict_source_chooser_add_button (GdictSourceChooser *chooser,
+                                 const gchar        *button_text)
+{
+  GdictSourceChooserPrivate *priv;
+  GtkWidget *button;
+
+  g_return_val_if_fail (GDICT_IS_SOURCE_CHOOSER (chooser), NULL);
+  g_return_val_if_fail (button_text != NULL, NULL);
+
+  priv = chooser->priv;
+
+  button = GTK_WIDGET (g_object_new (GTK_TYPE_BUTTON,
+                                     "label", button_text,
+                                     "use-stock", TRUE,
+                                     "use-underline", TRUE,
+                                     NULL));
+
+  gtk_widget_set_can_default (button, TRUE);
+
+  gtk_widget_show (button);
+
+  gtk_box_pack_end (GTK_BOX (priv->buttons_box), button, FALSE, TRUE, 0);
+
+  return button;
+}
+
+
+ +
+ +
+ + diff --git a/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/3.html b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/3.html new file mode 100644 index 00000000..6bb3a0a4 --- /dev/null +++ b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/3.html @@ -0,0 +1,1143 @@ + + + + + + Cppcheck - HTML report - mate-utils + + + + + +
+ + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
#include <gio/gio.h>
+
+#if defined (__ELF__) && ( __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 6))
+# define SECTION __attribute__ ((section (".gresource.baobab"), aligned (8)))
+#else
+# define SECTION
+#endif
+
+static const SECTION union { const guint8 data[3969]; const double alignment; void * const ptr;}  baobab_resource_data = { {<--- union member 'Anonymous0::alignment' is never used.<--- union member 'Anonymous0::ptr' is never used.
+  0107, 0126, 0141, 0162, 0151, 0141, 0156, 0164, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 
+  0030, 0000, 0000, 0000, 0310, 0000, 0000, 0000, 0000, 0000, 0000, 0050, 0006, 0000, 0000, 0000, 
+  0000, 0000, 0000, 0000, 0002, 0000, 0000, 0000, 0003, 0000, 0000, 0000, 0004, 0000, 0000, 0000, 
+  0005, 0000, 0000, 0000, 0005, 0000, 0000, 0000, 0052, 0250, 0067, 0035, 0001, 0000, 0000, 0000, 
+  0310, 0000, 0000, 0000, 0025, 0000, 0166, 0000, 0340, 0000, 0000, 0000, 0103, 0013, 0000, 0000, 
+  0020, 0367, 0105, 0111, 0005, 0000, 0000, 0000, 0103, 0013, 0000, 0000, 0024, 0000, 0114, 0000, 
+  0130, 0013, 0000, 0000, 0140, 0013, 0000, 0000, 0113, 0120, 0220, 0013, 0003, 0000, 0000, 0000, 
+  0140, 0013, 0000, 0000, 0004, 0000, 0114, 0000, 0144, 0013, 0000, 0000, 0150, 0013, 0000, 0000, 
+  0324, 0265, 0002, 0000, 0377, 0377, 0377, 0377, 0150, 0013, 0000, 0000, 0001, 0000, 0114, 0000, 
+  0154, 0013, 0000, 0000, 0160, 0013, 0000, 0000, 0103, 0122, 0065, 0057, 0001, 0000, 0000, 0000, 
+  0160, 0013, 0000, 0000, 0033, 0000, 0166, 0000, 0220, 0013, 0000, 0000, 0166, 0017, 0000, 0000, 
+  0201, 0321, 0040, 0031, 0002, 0000, 0000, 0000, 0166, 0017, 0000, 0000, 0005, 0000, 0114, 0000, 
+  0174, 0017, 0000, 0000, 0200, 0017, 0000, 0000, 0142, 0141, 0157, 0142, 0141, 0142, 0055, 0155, 
+  0141, 0151, 0156, 0055, 0167, 0151, 0156, 0144, 0157, 0167, 0056, 0165, 0151, 0000, 0000, 0000, 
+  0370, 0125, 0000, 0000, 0001, 0000, 0000, 0000, 0170, 0332, 0355, 0034, 0133, 0123, 0333, 0070, 
+  0367, 0275, 0277, 0302, 0137, 0036, 0277, 0051, 0044, 0116, 0010, 0027, 0017, 0260, 0223, 0322, 
+  0000, 0331, 0102, 0302, 0044, 0151, 0231, 0356, 0213, 0106, 0261, 0105, 0242, 0215, 0143, 0173, 
+  0055, 0031, 0010, 0277, 0176, 0217, 0354, 0134, 0211, 0057, 0222, 0161, 0102, 0267, 0155, 0247, 
+  0323, 0301, 0106, 0347, 0350, 0334, 0057, 0322, 0161, 0117, 0377, 0170, 0236, 0330, 0332, 0043, 
+  0361, 0031, 0165, 0235, 0263, 0222, 0276, 0137, 0051, 0375, 0161, 0376, 0341, 0364, 0177, 0173, 
+  0173, 0377, 0337, 0323, 0046, 0256, 0105, 0014, 0115, 0054, 0200, 0247, 0075, 0170, 0115, 0035, 
+  0116, 0374, 0007, 0154, 0222, 0363, 0017, 0232, 0166, 0352, 0016, 0376, 0046, 0046, 0327, 0114, 
+  0033, 0063, 0166, 0126, 0272, 0342, 0343, 0257, 0255, 0133, 0354, 0340, 0041, 0361, 0113, 0032, 
+  0265, 0316, 0112, 0001, 0235, 0104, 0217, 0172, 0111, 0254, 0007, 0010, 0163, 0104, 0155, 0053, 
+  0372, 0071, 0016, 0276, 0141, 0162, 0240, 0342, 0312, 0167, 0003, 0057, 0302, 0200, 0303, 0027, 
+  0103, 0361, 0142, 0216, 0143, 0023, 0117, 0032, 0256, 0010, 0315, 0204, 0070, 0001, 0345, 0144, 
+  0262, 0212, 0043, 0204, 0362, 0174, 0327, 0043, 0076, 0237, 0152, 0016, 0236, 0220, 0263, 0222, 
+  0370, 0267, 0164, 0276, 0130, 0175, 0132, 0236, 0377, 0076, 0035, 0314, 0306, 0003, 0142, 0227, 
+  0064, 0356, 0143, 0207, 0331, 0230, 0343, 0201, 0015, 0057, 0247, 0204, 0225, 0316, 0121, 0303, 
+  0301, 0366, 0364, 0205, 0370, 0361, 0250, 0116, 0313, 0021, 0331, 0053, 0234, 0225, 0137, 0261, 
+  0226, 0207, 0125, 0146, 0142, 0147, 0344, 0012, 0126, 0122, 0311, 0146, 0334, 0065, 0307, 0210, 
+  0132, 0245, 0363, 0041, 0037, 0357, 0011, 0000, 0131, 0206, 0227, 0162, 0232, 0157, 0365, 0166, 
+  0121, 0365, 0000, 0223, 0206, 0256, 0001, 0227, 0166, 0351, 0332, 0126, 0222, 0310, 0000, 0045, 
+  0243, 0103, 0220, 0252, 0066, 0302, 0216, 0145, 0023, 0377, 0254, 0344, 0072, 0150, 0225, 0024, 
+  0044, 0214, 0346, 0021, 0163, 0122, 0322, 0100, 0102, 0034, 0201, 0021, 0323, 0007, 0152, 0142, 
+  0041, 0043, 0304, 0251, 0240, 0342, 0236, 0130, 0037, 0265, 0152, 0115, 0153, 0004, 0103, 0255, 
+  0132, 0251, 0034, 0152, 0225, 0232, 0121, 0077, 0061, 0152, 0307, 0332, 0325, 0155, 0277, 0064, 
+  0043, 0165, 0201, 0246, 0234, 0256, 0062, 0170, 0207, 0115, 0223, 0000, 0051, 0230, 0273, 0276, 
+  0066, 0046, 0323, 0263, 0122, 0257, 0244, 0105, 0333, 0202, 0137, 0201, 0212, 0076, 0177, 0101, 
+  0027, 0235, 0166, 0277, 0333, 0271, 0101, 0267, 0215, 0336, 0227, 0125, 0214, 0205, 0050, 0034, 
+  0333, 0366, 0003, 0123, 0323, 0066, 0366, 0055, 0213, 0262, 0261, 0272, 0306, 0303, 0275, 0212, 
+  0122, 0367, 0045, 0265, 0011, 0233, 0062, 0160, 0066, 0125, 0155, 0207, 0144, 0110, 0250, 0272, 
+  0037, 0220, 0217, 0132, 0245, 0256, 0375, 0031, 0330, 0102, 0325, 0165, 0255, 0162, 0154, 0034, 
+  0034, 0031, 0325, 0303, 0242, 0124, 0175, 0271, 0133, 0125, 0013, 0053, 0267, 0250, 0257, 0244, 
+  0154, 0130, 0017, 0110, 0135, 0177, 0232, 0317, 0277, 0001, 0274, 0040, 0175, 0137, 0242, 0320, 
+  0263, 0367, 0367, 0367, 0363, 0070, 0067, 0320, 0361, 0043, 0050, 0274, 0263, 0133, 0205, 0043, 
+  0301, 0072, 0362, 0311, 0104, 0111, 0345, 0016, 0341, 0117, 0256, 0237, 0303, 0275, 0027, 0333, 
+  0025, 0240, 0162, 0044, 0164, 0336, 0045, 0023, 0227, 0317, 0143, 0172, 0016, 0315, 0057, 0010, 
+  0222, 0320, 0375, 0245, 0117, 0077, 0152, 0372, 0261, 0326, 0166, 0037, 0043, 0335, 0353, 0307, 
+  0106, 0265, 0142, 0124, 0353, 0171, 0164, 0137, 0214, 0273, 0162, 0327, 0123, 0122, 0234, 0000, 
+  0310, 0341, 0246, 0151, 0120, 0211, 0202, 0005, 0040, 0131, 0207, 0252, 0236, 0254, 0044, 0313, 
+  0003, 0003, 0376, 0326, 0217, 0212, 0162, 0250, 0046, 0150, 0330, 0043, 0153, 0136, 0125, 0051, 
+  0334, 0215, 0174, 0042, 0354, 0110, 0111, 0025, 0076, 0171, 0000, 0250, 0221, 0272, 0066, 0242, 
+  0275, 0224, 0365, 0021, 0201, 0111, 0150, 0244, 0207, 0071, 0150, 0344, 0130, 0353, 0000, 0307, 
+  0241, 0106, 0364, 0003, 0243, 0172, 0144, 0324, 0364, 0242, 0064, 0322, 0335, 0155, 0210, 0373, 
+  0007, 0312, 0155, 0045, 0315, 0010, 0000, 0165, 0265, 0244, 0102, 0305, 0050, 0105, 0254, 0337, 
+  0165, 0302, 0171, 0263, 0074, 0211, 0105, 0271, 0134, 0233, 0023, 0256, 0054, 0240, 0305, 0151, 
+  0132, 0111, 0142, 0335, 0006, 0173, 0317, 0036, 0150, 0010, 0101, 0365, 0047, 0307, 0343, 0142, 
+  0171, 0021, 0214, 0206, 0310, 0264, 0106, 0012, 0262, 0044, 0327, 0236, 0323, 0241, 0336, 0231, 
+  0350, 0107, 0206, 0136, 0061, 0152, 0265, 0167, 0061, 0046, 0323, 0265, 0155, 0354, 0061, 0042, 
+  0055, 0357, 0125, 0200, 0002, 0044, 0176, 0061, 0103, 0227, 0113, 0346, 0113, 0132, 0362, 0111, 
+  0275, 0146, 0124, 0017, 0336, 0105, 0352, 0036, 0044, 0036, 0342, 0023, 0347, 0205, 0350, 0112, 
+  0121, 0161, 0016, 0147, 0022, 0246, 0026, 0034, 0127, 0066, 0124, 0221, 0262, 0000, 0013, 0105, 
+  0235, 0121, 0220, 0125, 0016, 0126, 0012, 0062, 0335, 0320, 0241, 0321, 0176, 0237, 0202, 0354, 
+  0221, 0222, 0047, 0271, 0330, 0030, 0256, 0054, 0300, 0200, 0277, 0001, 0236, 0255, 0306, 0306, 
+  0276, 0073, 0034, 0332, 0344, 0065, 0223, 0210, 0017, 0062, 0330, 0014, 0145, 0016, 0214, 0366, 
+  0375, 0100, 0361, 0324, 0147, 0206, 0277, 0000, 0341, 0364, 0135, 0327, 0036, 0140, 0377, 0075, 
+  0344, 0303, 0266, 0054, 0037, 0126, 0200, 0174, 0172, 0120, 0174, 0360, 0200, 0355, 0136, 0102, 
+  0020, 0122, 0040, 0174, 0273, 0340, 0310, 0304, 0332, 0232, 0230, 0126, 0067, 0171, 0273, 0254, 
+  0040, 0077, 0240, 0010, 0227, 0326, 0363, 0260, 0111, 0124, 0302, 0330, 0052, 0045, 0022, 0271, 
+  0342, 0326, 0165, 0040, 0127, 0350, 0153, 0147, 0207, 0020, 0322, 0364, 0367, 0311, 0320, 0043, 
+  0142, 0173, 0162, 0041, 0055, 0134, 0131, 0200, 0327, 0136, 0003, 0236, 0235, 0225, 0173, 0202, 
+  0150, 0323, 0165, 0070, 0161, 0270, 0342, 0371, 0146, 0042, 0225, 0151, 0362, 0231, 0157, 0125, 
+  0110, 0351, 0222, 0201, 0052, 0306, 0022, 0127, 0111, 0220, 0256, 0132, 0016, 0265, 0206, 0347, 
+  0317, 0054, 0361, 0310, 0070, 0200, 0306, 0274, 0132, 0330, 0321, 0246, 0276, 0305, 0246, 0034, 
+  0017, 0334, 0100, 0255, 0353, 0013, 0041, 0324, 0224, 0232, 0016, 0022, 0243, 0202, 0020, 0040, 
+  0147, 0323, 0127, 0077, 0056, 0246, 0116, 0137, 0137, 0260, 0366, 0313, 0323, 0200, 0056, 0126, 
+  0211, 0312, 0013, 0222, 0303, 0154, 0257, 0331, 0323, 0332, 0055, 0231, 0170, 0247, 0105, 0127, 
+  0150, 0111, 0167, 0140, 0247, 0363, 0327, 0153, 0353, 0026, 0027, 0110, 0345, 0354, 0265, 0321, 
+  0335, 0103, 0131, 0016, 0251, 0070, 0271, 0226, 0130, 0272, 0074, 0363, 0134, 0137, 0314, 0210, 
+  0207, 0103, 0373, 0224, 0331, 0116, 0234, 0274, 0111, 0254, 0233, 0035, 0014, 0345, 0337, 0050, 
+  0074, 0275, 0130, 0363, 0014, 0361, 0066, 0111, 0015, 0233, 0375, 0371, 0046, 0326, 0225, 0046, 
+  0067, 0143, 0377, 0265, 0006, 0055, 0037, 0013, 0253, 0335, 0206, 0064, 0027, 0233, 0225, 0364, 
+  0046, 0342, 0171, 0041, 0132, 0226, 0130, 0306, 0062, 0227, 0255, 0025, 0045, 0322, 0164, 0156, 
+  0246, 0307, 0115, 0314, 0153, 0071, 0046, 0203, 0212, 0050, 0150, 0045, 0156, 0037, 0075, 0201, 
+  0033, 0316, 0135, 0067, 0162, 0327, 0125, 0207, 0336, 0014, 0212, 0367, 0324, 0261, 0334, 0247, 
+  0050, 0050, 0016, 0260, 0073, 0300, 0003, 0364, 0024, 0275, 0232, 0141, 0171, 0025, 0331, 0036, 
+  0051, 0243, 0220, 0150, 0342, 0213, 0256, 0327, 0213, 0071, 0345, 0260, 0064, 0056, 0103, 0175, 
+  0246, 0154, 0254, 0175, 0145, 0170, 0010, 0335, 0165, 0302, 0045, 0365, 0006, 0262, 0251, 0007, 
+  0333, 0136, 0365, 0277, 0240, 0373, 0126, 0373, 0163, 0347, 0036, 0365, 0073, 0167, 0067, 0315, 
+  0157, 0315, 0233, 0054, 0300, 0210, 0037, 0344, 0271, 0214, 0206, 0011, 0140, 0216, 0003, 0335, 
+  0165, 0172, 0350, 0242, 0331, 0356, 0067, 0273, 0131, 0050, 0040, 0006, 0143, 0273, 0164, 0176, 
+  0211, 0155, 0226, 0311, 0264, 0105, 0036, 0160, 0140, 0163, 0020, 0243, 0305, 0107, 0245, 0363, 
+  0343, 0112, 0105, 0026, 0142, 0104, 0350, 0160, 0004, 0131, 0251, 0236, 0015, 0002, 0161, 0203, 
+  0276, 0140, 0151, 0105, 0130, 0204, 0161, 0337, 0235, 0002, 0115, 0174, 0204, 0300, 0063, 0301, 
+  0332, 0244, 0271, 0061, 0135, 0077, 0252, 0305, 0145, 0066, 0142, 0143, 0352, 0041, 0216, 0331, 
+  0030, 0314, 0020, 0215, 0250, 0364, 0066, 0041, 0234, 0047, 0246, 0065, 0124, 0240, 0204, 0111, 
+  0314, 0326, 0213, 0143, 0342, 0271, 0135, 0174, 0277, 0153, 0242, 0353, 0126, 0273, 0217, 0332, 
+  0235, 0356, 0155, 0043, 0323, 0076, 0206, 0076, 0176, 0244, 0174, 0032, 0341, 0270, 0352, 0066, 
+  0276, 0265, 0372, 0337, 0005, 0150, 0377, 0032, 0335, 0067, 0173, 0375, 0054, 0360, 0007, 0327, 
+  0014, 0030, 0022, 0347, 0076, 0330, 0223, 0023, 0122, 0340, 0017, 0211, 0143, 0116, 0123, 0071, 
+  0215, 0251, 0016, 0054, 0250, 0217, 0270, 0314, 0201, 0122, 0057, 0200, 0046, 0241, 0246, 0057, 
+  0313, 0003, 0375, 0320, 0250, 0327, 0214, 0203, 0223, 0325, 0362, 0140, 0206, 0215, 0074, 0012, 
+  0133, 0050, 0313, 0115, 0310, 0174, 0373, 0344, 0076, 0317, 0372, 0330, 0201, 0373, 0274, 0226, 
+  0355, 0125, 0302, 0104, 0034, 0000, 0044, 0174, 0027, 0244, 0102, 0334, 0200, 0045, 0210, 0044, 
+  0326, 0154, 0240, 0335, 0242, 0316, 0260, 0164, 0136, 0211, 0135, 0055, 0121, 0024, 0336, 0102, 
+  0310, 0374, 0204, 0375, 0222, 0006, 0101, 0030, 0174, 0044, 0020, 0067, 0325, 0153, 0263, 0103, 
+  0213, 0173, 0202, 0127, 0365, 0115, 0056, 0256, 0343, 0200, 0200, 0205, 0061, 0212, 0056, 0311, 
+  0027, 0321, 0351, 0256, 0161, 0361, 0005, 0175, 0156, 0165, 0233, 0027, 0375, 0126, 0247, 0215, 
+  0156, 0372, 0135, 0131, 0154, 0041, 0313, 0350, 0055, 0070, 0143, 0253, 0163, 0201, 0020, 0004, 
+  0235, 0305, 0211, 0145, 0045, 0153, 0043, 0016, 0042, 0252, 0065, 0122, 0024, 0036, 0353, 0160, 
+  0324, 0266, 0123, 0101, 0340, 0355, 0153, 0162, 0163, 0036, 0116, 0204, 0107, 0104, 0221, 0011, 
+  0360, 0350, 0141, 0053, 0046, 0340, 0372, 0024, 0274, 0020, 0057, 0165, 0325, 0351, 0266, 0040, 
+  0057, 0065, 0102, 0105, 0135, 0303, 0303, 0137, 0035, 0170, 0272, 0221, 0105, 0307, 0106, 0220, 
+  0356, 0260, 0357, 0213, 0044, 0236, 0056, 0331, 0015, 0041, 0044, 0013, 0342, 0123, 0300, 0371, 
+  0274, 0173, 0342, 0203, 0204, 0041, 0257, 0334, 0022, 0211, 0215, 0356, 0260, 0053, 0247, 0336, 
+  0036, 0047, 0317, 0074, 0171, 0252, 0103, 0120, 0241, 0075, 0244, 0316, 0154, 0345, 0230, 0025, 
+  0271, 0116, 0231, 0052, 0213, 0015, 0351, 0120, 0005, 0007, 0016, 0320, 0140, 0123, 0047, 0007, 
+  0253, 0362, 0303, 0160, 0051, 0022, 0106, 0043, 0260, 0243, 0027, 0250, 0045, 0105, 0251, 0242, 
+  0112, 0301, 0034, 0307, 0043, 0274, 0203, 0154, 0222, 0003, 0003, 0145, 0210, 0116, 0074, 0327, 
+  0347, 0130, 0144, 0265, 0114, 0150, 0321, 0357, 0063, 0330, 0223, 0332, 0064, 0366, 0367, 0345, 
+  0254, 0005, 0061, 0031, 0162, 0151, 0227, 0310, 0264, 0251, 0071, 0206, 0252, 0105, 0341, 0326, 
+  0245, 0152, 0324, 0052, 0106, 0145, 0255, 0207, 0236, 0143, 0051, 0307, 0354, 0037, 0372, 0216, 
+  0026, 0316, 0244, 0002, 0035, 0173, 0341, 0243, 0350, 0272, 0043, 0252, 0355, 0070, 0327, 0330, 
+  0360, 0255, 0006, 0037, 0167, 0302, 0027, 0263, 0123, 0011, 0135, 0237, 0356, 0055, 0231, 0320, 
+  0143, 0121, 0154, 0112, 0176, 0201, 0305, 0060, 0226, 0333, 0243, 0360, 0014, 0342, 0255, 0156, 
+  0023, 0237, 0016, 0022, 0142, 0152, 0072, 0100, 0174, 0016, 0311, 0235, 0025, 0062, 0213, 0210, 
+  0164, 0013, 0214, 0311, 0021, 0211, 0074, 0275, 0055, 0114, 0156, 0336, 0136, 0276, 0103, 0224, 
+  0174, 0310, 0034, 0165, 0314, 0063, 0120, 0227, 0013, 0151, 0261, 0241, 0062, 0143, 0222, 0364, 
+  0277, 0022, 0056, 0263, 0115, 0075, 0061, 0334, 0201, 0175, 0145, 0107, 0273, 0160, 0150, 0247, 
+  0162, 0262, 0154, 0011, 0252, 0025, 0003, 0272, 0202, 0332, 0241, 0124, 0264, 0373, 0355, 0322, 
+  0353, 0056, 0275, 0071, 0002, 0373, 0016, 0056, 0215, 0213, 0257, 0172, 0056, 0225, 0021, 0026, 
+  0352, 0314, 0231, 0223, 0302, 0277, 0200, 0067, 0213, 0061, 0143, 0271, 0332, 0005, 0112, 0226, 
+  0145, 0203, 0137, 0063, 0364, 0272, 0161, 0120, 0371, 0355, 0315, 0212, 0336, 0274, 0070, 0353, 
+  0167, 0071, 0371, 0021, 0134, 0072, 0242, 0244, 0170, 0317, 0136, 0233, 0203, 0176, 0067, 0007, 
+  0317, 0230, 0013, 0377, 0311, 0335, 0173, 0325, 0326, 0262, 0175, 0174, 0163, 0232, 0274, 0156, 
+  0324, 0041, 0143, 0127, 0177, 0373, 0170, 0252, 0217, 0367, 0346, 0067, 0117, 0302, 0331, 0133, 
+  0120, 0233, 0106, 0256, 0276, 0270, 0220, 0022, 0236, 0050, 0156, 0125, 0016, 0266, 0351, 0356, 
+  0226, 0217, 0237, 0362, 0333, 0351, 0056, 0155, 0375, 0107, 0061, 0224, 0014, 0350, 0035, 0325, 
+  0166, 0233, 0337, 0113, 0024, 0152, 0026, 0214, 0070, 0342, 0016, 0112, 0314, 0054, 0051, 0113, 
+  0053, 0073, 0203, 0000, 0361, 0232, 0010, 0061, 0016, 0210, 0051, 0177, 0214, 0116, 0373, 0230, 
+  0343, 0147, 0257, 0277, 0304, 0047, 0051, 0352, 0255, 0024, 0364, 0121, 0142, 0012, 0353, 0130, 
+  0366, 0340, 0110, 0356, 0023, 0024, 0055, 0042, 0361, 0167, 0214, 0227, 0362, 0334, 0330, 0017, 
+  0154, 0166, 0133, 0301, 0165, 0323, 0077, 0330, 0051, 0072, 0036, 0050, 0175, 0055, 0364, 0223, 
+  0073, 0356, 0354, 0333, 0045, 0071, 0327, 0175, 0375, 0351, 0322, 0241, 0254, 0353, 0376, 0154, 
+  0376, 0366, 0373, 0242, 0057, 0376, 0136, 0273, 0272, 0215, 0053, 0076, 0371, 0142, 0107, 0355, 
+  0216, 0133, 0045, 0154, 0136, 0057, 0330, 0034, 0275, 0272, 0276, 0117, 0332, 0173, 0340, 0372, 
+  0320, 0372, 0315, 0107, 0131, 0252, 0071, 0102, 0203, 0172, 0104, 0120, 0051, 0013, 0363, 0110, 
+  0053, 0131, 0142, 0361, 0122, 0273, 0211, 0072, 0153, 0041, 0266, 0260, 0311, 0226, 0275, 0225, 
+  0221, 0026, 0200, 0122, 0073, 0137, 0226, 0203, 0177, 0325, 0266, 0147, 0212, 0061, 0011, 0307, 
+  0004, 0373, 0343, 0300, 0313, 0211, 0340, 0357, 0200, 0161, 0372, 0060, 0215, 0256, 0264, 0377, 
+  0374, 0332, 0353, 0267, 0056, 0277, 0243, 0233, 0346, 0145, 0137, 0025, 0321, 0223, 0217, 0363, 
+  0322, 0300, 0240, 0324, 0062, 0171, 0064, 0051, 0225, 0013, 0301, 0063, 0266, 0041, 0345, 0200, 
+  0075, 0355, 0327, 0052, 0341, 0037, 0135, 0077, 0251, 0352, 0252, 0130, 0246, 0013, 0054, 0165, 
+  0145, 0002, 0040, 0332, 0146, 0230, 0163, 0354, 0216, 0371, 0300, 0210, 0155, 0123, 0217, 0321, 
+  0027, 0020, 0327, 0135, 0243, 0175, 0325, 0101, 0315, 0233, 0233, 0326, 0135, 0257, 0365, 0127, 
+  0023, 0265, 0073, 0355, 0246, 0262, 0346, 0104, 0344, 0100, 0346, 0010, 0373, 0340, 0314, 0173, 
+  0312, 0142, 0143, 0340, 0312, 0120, 0136, 0010, 0043, 0026, 0371, 0074, 0257, 0016, 0261, 0300, 
+  0222, 0051, 0214, 0344, 0233, 0316, 0264, 0034, 0237, 0057, 0077, 0276, 0271, 0102, 0310, 0225, 
+  0057, 0063, 0152, 0204, 0224, 0113, 0335, 0324, 0220, 0351, 0331, 0330, 0044, 0243, 0360, 0150, 
+  0261, 0274, 0303, 0153, 0342, 0205, 0224, 0353, 0052, 0011, 0042, 0167, 0015, 0046, 0045, 0335, 
+  0155, 0164, 0073, 0327, 0167, 0330, 0021, 0125, 0155, 0230, 0270, 0075, 0361, 0063, 0204, 0145, 
+  0272, 0325, 0146, 0107, 0124, 0323, 0341, 0134, 0243, 0004, 0250, 0102, 0052, 0355, 0231, 0276, 
+  0153, 0333, 0304, 0132, 0035, 0072, 0146, 0263, 0167, 0321, 0224, 0356, 0116, 0222, 0253, 0002, 
+  0167, 0261, 0005, 0112, 0104, 0262, 0230, 0160, 0365, 0134, 0150, 0026, 0146, 0011, 0356, 0256, 
+  0163, 0323, 0272, 0370, 0216, 0032, 0137, 0373, 0235, 0333, 0106, 0277, 0165, 0241, 0212, 0366, 
+  0161, 0073, 0150, 0331, 0010, 0213, 0351, 0347, 0345, 0364, 0164, 0357, 0272, 0041, 0246, 0144, 
+  0133, 0155, 0365, 0130, 0036, 0315, 0121, 0013, 0157, 0237, 0204, 0023, 0304, 0002, 0335, 0105, 
+  0247, 0333, 0156, 0166, 0305, 0060, 0266, 0134, 0152, 0117, 0064, 0227, 0204, 0126, 0337, 0047, 
+  0104, 0174, 0307, 0072, 0153, 0364, 0341, 0051, 0356, 0073, 0332, 0354, 0024, 0344, 0223, 0177, 
+  0002, 0302, 0342, 0207, 0253, 0013, 0067, 0270, 0002, 0214, 0056, 0326, 0360, 0010, 0206, 0020, 
+  0313, 0320, 0202, 0026, 0251, 0054, 0021, 0073, 0076, 0036, 0330, 0204, 0315, 0346, 0217, 0363, 
+  0122, 0343, 0223, 0260, 0071, 0300, 0157, 0243, 0204, 0070, 0002, 0001, 0142, 0004, 0373, 0346, 
+  0050, 0077, 0061, 0017, 0364, 0031, 0302, 0142, 0064, 0100, 0257, 0122, 0051, 0304, 0067, 0040, 
+  0217, 0320, 0363, 0104, 0205, 0143, 0070, 0221, 0371, 0106, 0114, 0112, 0071, 0075, 0275, 0014, 
+  0111, 0311, 0317, 0105, 0326, 0057, 0154, 0344, 0123, 0147, 0234, 0057, 0072, 0206, 0137, 0046, 
+  0220, 0137, 0261, 0014, 0251, 0344, 0051, 0103, 0124, 0063, 0163, 0124, 0205, 0374, 0227, 0217, 
+  0200, 0124, 0116, 0115, 0262, 0270, 0055, 0352, 0000, 0250, 0307, 0147, 0037, 0273, 0317, 0152, 
+  0222, 0371, 0143, 0001, 0323, 0336, 0277, 0302, 0051, 0133, 0342, 0067, 0243, 0313, 0137, 0234, 
+  0226, 0127, 0376, 0367, 0326, 0017, 0377, 0002, 0371, 0155, 0075, 0312, 0000, 0050, 0165, 0165, 
+  0141, 0171, 0051, 0144, 0151, 0163, 0153, 0055, 0165, 0163, 0141, 0147, 0145, 0055, 0141, 0156, 
+  0141, 0154, 0171, 0172, 0145, 0162, 0057, 0000, 0004, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 
+  0157, 0162, 0147, 0057, 0005, 0000, 0000, 0000, 0057, 0000, 0000, 0000, 0002, 0000, 0000, 0000, 
+  0142, 0141, 0157, 0142, 0141, 0142, 0055, 0144, 0151, 0141, 0154, 0157, 0147, 0055, 0163, 0143, 
+  0141, 0156, 0055, 0160, 0162, 0157, 0160, 0163, 0056, 0165, 0151, 0000, 0000, 0000, 0000, 0000, 
+  0043, 0032, 0000, 0000, 0001, 0000, 0000, 0000, 0170, 0332, 0355, 0131, 0135, 0217, 0323, 0070, 
+  0024, 0175, 0347, 0127, 0170, 0375, 0212, 0062, 0231, 0266, 0132, 0026, 0241, 0064, 0210, 0017, 
+  0301, 0256, 0264, 0053, 0041, 0315, 0000, 0217, 0226, 0343, 0334, 0046, 0146, 0134, 0073, 0153, 
+  0073, 0355, 0204, 0137, 0217, 0223, 0024, 0146, 0322, 0072, 0315, 0244, 0035, 0012, 0203, 0170, 
+  0113, 0023, 0037, 0373, 0176, 0370, 0034, 0337, 0353, 0106, 0317, 0257, 0227, 0002, 0255, 0100, 
+  0033, 0256, 0344, 0034, 0117, 0316, 0316, 0061, 0002, 0311, 0124, 0312, 0145, 0066, 0307, 0357, 
+  0057, 0337, 0004, 0117, 0361, 0363, 0370, 0121, 0364, 0107, 0020, 0240, 0267, 0040, 0101, 0123, 
+  0013, 0051, 0132, 0163, 0233, 0243, 0114, 0320, 0024, 0320, 0354, 0154, 0366, 0344, 0354, 0034, 
+  0005, 0201, 0033, 0304, 0245, 0005, 0275, 0240, 0014, 0342, 0107, 0010, 0105, 0032, 0376, 0057, 
+  0271, 0006, 0203, 0004, 0117, 0346, 0070, 0263, 0127, 0217, 0361, 0315, 0102, 0263, 0263, 0351, 
+  0024, 0207, 0315, 0070, 0225, 0174, 0002, 0146, 0021, 0023, 0324, 0230, 0071, 0176, 0153, 0257, 
+  0376, 0131, 0322, 0014, 0060, 0342, 0351, 0034, 0363, 0372, 0161, 0202, 0353, 0161, 0156, 0144, 
+  0241, 0125, 0001, 0332, 0126, 0110, 0322, 0045, 0314, 0361, 0212, 0033, 0236, 0010, 0300, 0361, 
+  0245, 0056, 0041, 0012, 0277, 0176, 0365, 0017, 0146, 0124, 0222, 0205, 0142, 0245, 0301, 0361, 
+  0033, 0052, 0314, 0340, 0170, 0316, 0224, 0044, 0365, 0043, 0216, 0163, 0020, 0105, 0220, 0150, 
+  0265, 0066, 0240, 0273, 0260, 0050, 0154, 0215, 0277, 0233, 0037, 0323, 0037, 0354, 0307, 0232, 
+  0313, 0124, 0255, 0003, 0046, 0324, 0066, 0154, 0277, 0037, 0257, 0071, 0025, 0052, 0153, 0035, 
+  0111, 0233, 0147, 0142, 0152, 0063, 0352, 0031, 0014, 0276, 0037, 0063, 0023, 0245, 0123, 0320, 
+  0144, 0315, 0123, 0233, 0343, 0370, 0317, 0241, 0341, 0226, 0133, 0027, 0060, 0144, 0065, 0225, 
+  0106, 0120, 0113, 0135, 0370, 0346, 0270, 0002, 0267, 0332, 0153, 0156, 0256, 0320, 0173, 0343, 
+  0302, 0215, 0136, 0110, 0052, 0252, 0317, 0240, 0321, 0073, 0015, 0013, 0320, 0156, 0133, 0203, 
+  0031, 0232, 0070, 0205, 0005, 0055, 0205, 0045, 0071, 0360, 0054, 0267, 0070, 0236, 0315, 0316, 
+  0007, 0155, 0251, 0012, 0040, 0271, 0333, 0373, 0070, 0156, 0243, 0263, 0003, 0140, 0071, 0027, 
+  0051, 0152, 0330, 0341, 0114, 0012, 0232, 0237, 0056, 0355, 0211, 0272, 0336, 0104, 0317, 0027, 
+  0365, 0227, 0267, 0276, 0216, 0217, 0257, 0017, 0243, 0064, 0007, 0151, 0251, 0165, 0004, 0304, 
+  0261, 0143, 0242, 0345, 0214, 0212, 0273, 0000, 0115, 0101, 0231, 0323, 0003, 0034, 0117, 0275, 
+  0243, 0375, 0356, 0121, 0126, 0057, 0104, 0250, 0006, 0172, 0313, 0017, 0257, 0247, 0245, 0265, 
+  0112, 0166, 0375, 0075, 0324, 0147, 0037, 0116, 0320, 0112, 0225, 0226, 0030, 0133, 0325, 0044, 
+  0003, 0231, 0366, 0002, 0033, 0323, 0273, 0357, 0372, 0015, 0156, 0011, 0221, 0064, 0317, 0023, 
+  0274, 0215, 0362, 0231, 0221, 0200, 0360, 0356, 0131, 0362, 0267, 0123, 0230, 0076, 0243, 0106, 
+  0053, 0306, 0035, 0103, 0070, 0026, 0252, 0201, 0001, 0137, 0201, 0041, 0033, 0212, 0214, 0237, 
+  0241, 0021, 0101, 0034, 0267, 0232, 0076, 0006, 0130, 0032, 0040, 0245, 0164, 0372, 0040, 0270, 
+  0074, 0300, 0151, 0052, 0326, 0264, 0062, 0304, 0344, 0152, 0115, 0066, 0066, 0354, 0237, 0342, 
+  0266, 0034, 0166, 0047, 0246, 0354, 0312, 0021, 0141, 0170, 0111, 0270, 0056, 0250, 0114, 0307, 
+  0233, 0272, 0340, 0102, 0214, 0107, 0025, 0312, 0360, 0226, 0325, 0347, 0373, 0234, 0362, 0132, 
+  0037, 0205, 0236, 0115, 0177, 0070, 0021, 0246, 0307, 0021, 0341, 0325, 0356, 0331, 0364, 0253, 
+  0063, 0141, 0372, 0233, 0011, 0337, 0203, 0011, 0223, 0373, 0140, 0202, 0317, 0175, 0277, 0353, 
+  0175, 0156, 0217, 0072, 0250, 0132, 0237, 0107, 0101, 0006, 0251, 0357, 0161, 0166, 0307, 0321, 
+  0135, 0272, 0017, 0225, 0043, 0007, 0123, 0361, 0276, 0316, 0364, 0325, 0135, 0366, 0325, 0301, 
+  0005, 0320, 0336, 0042, 0350, 0311, 0261, 0345, 0303, 0277, 0215, 0376, 0235, 0106, 0333, 0366, 
+  0006, 0325, 0207, 0315, 0251, 0340, 0231, 0013, 0217, 0261, 0124, 0333, 0061, 0300, 0176, 0125, 
+  0277, 0000, 0121, 0007, 0300, 0311, 0345, 0212, 0273, 0022, 0034, 0131, 0345, 0212, 0105, 0046, 
+  0112, 0327, 0075, 0162, 0211, 0334, 0246, 0007, 0123, 0031, 0013, 0113, 0124, 0167, 0025, 0317, 
+  0116, 0050, 0207, 0113, 0011, 0113, 0045, 0071, 0253, 0333, 0216, 0014, 0234, 0216, 0133, 0015, 
+  0100, 0126, 0034, 0326, 0155, 0157, 0163, 0012, 0135, 0034, 0235, 0240, 0007, 0126, 0042, 0134, 
+  0060, 0255, 0204, 0200, 0364, 0143, 0323, 0174, 0342, 0237, 0363, 0104, 0317, 0017, 0075, 0245, 
+  0126, 0207, 0002, 0163, 0323, 0304, 0045, 0241, 0232, 0024, 0112, 0160, 0126, 0341, 0130, 0302, 
+  0152, 0373, 0176, 0141, 0377, 0034, 0046, 0247, 0056, 0244, 0244, 0356, 0077, 0135, 0055, 0041, 
+  0367, 0102, 0275, 0331, 0362, 0147, 0354, 0322, 0221, 0340, 0203, 0343, 0100, 0133, 0326, 0155, 
+  0121, 0002, 0373, 0346, 0070, 0042, 0211, 0107, 0046, 0362, 0250, 0144, 0036, 0225, 0320, 0075, 
+  0235, 0257, 0151, 0364, 0256, 0041, 0233, 0027, 0326, 0027, 0364, 0213, 0157, 0270, 0260, 0147, 
+  0275, 0260, 0077, 0215, 0075, 0202, 0324, 0013, 0172, 0300, 0012, 0066, 0071, 0255, 0202, 0275, 
+  0312, 0201, 0165, 0072, 0035, 0126, 0277, 0040, 0040, 0353, 0043, 0216, 0344, 0252, 0276, 0132, 
+  0073, 0246, 0347, 0371, 0317, 0035, 0101, 0126, 0151, 0304, 0162, 0052, 0263, 0366, 0170, 0254, 
+  0124, 0251, 0121, 0075, 0063, 0132, 0050, 0221, 0216, 0123, 0205, 0237, 0243, 0043, 0072, 0135, 
+  0335, 0161, 0144, 0015, 0220, 0152, 0352, 0172, 0041, 0231, 0272, 0122, 0320, 0045, 0341, 0164, 
+  0375, 0320, 0311, 0131, 0063, 0175, 0260, 0015, 0321, 0230, 0022, 0177, 0120, 0045, 0206, 0373, 
+  0241, 0256, 0217, 0235, 0217, 0121, 0173, 0251, 0031, 0264, 0365, 0242, 0371, 0206, 0350, 0274, 
+  0106, 0032, 0114, 0241, 0244, 0161, 0326, 0004, 0223, 0011, 0216, 0067, 0067, 0204, 0121, 0330, 
+  0031, 0065, 0214, 0375, 0353, 0053, 0164, 0352, 0205, 0156, 0275, 0064, 0235, 0273, 0346, 0272, 
+  0046, 0330, 0334, 0222, 0273, 0022, 0343, 0346, 0226, 0271, 0020, 0224, 0101, 0336, 0150, 0112, 
+  0270, 0343, 0337, 0215, 0343, 0121, 0170, 0353, 0257, 0234, 0057, 0252, 0254, 0274, 0155, 0000, 
+  0050, 0165, 0165, 0141, 0171, 0051, 0155, 0141, 0164, 0145, 0057, 0000, 0001, 0000, 0000, 0000
+} };
+
+static GStaticResource static_resource = { baobab_resource_data.data, sizeof (baobab_resource_data.data) - 1 /* nul terminator */, NULL, NULL, NULL };
+
+G_MODULE_EXPORT
+GResource *baobab_get_resource (void);
+GResource *baobab_get_resource (void)
+{
+  return g_static_resource_get_resource (&static_resource);
+}
+/* GLIB - Library of useful routines for C programming
+ * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * Modified by the GLib Team and others 1997-2000.  See the AUTHORS
+ * file for a list of people on the GLib Team.  See the ChangeLog
+ * files for a list of changes.  These files are distributed with
+ * GLib at ftp://ftp.gtk.org/pub/gtk/.
+ */
+
+#ifndef __G_CONSTRUCTOR_H__
+#define __G_CONSTRUCTOR_H__
+
+/*
+  If G_HAS_CONSTRUCTORS is true then the compiler support *both* constructors and
+  destructors, in a usable way, including e.g. on library unload. If not you're on
+  your own.
+
+  Some compilers need #pragma to handle this, which does not work with macros,
+  so the way you need to use this is (for constructors):
+
+  #ifdef G_DEFINE_CONSTRUCTOR_NEEDS_PRAGMA
+  #pragma G_DEFINE_CONSTRUCTOR_PRAGMA_ARGS(my_constructor)
+  #endif
+  G_DEFINE_CONSTRUCTOR(my_constructor)
+  static void my_constructor(void) {
+   ...
+  }
+
+*/
+
+#ifndef __GTK_DOC_IGNORE__
+
+#if  __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7)
+
+#define G_HAS_CONSTRUCTORS 1
+
+#define G_DEFINE_CONSTRUCTOR(_func) static void __attribute__((constructor)) _func (void);
+#define G_DEFINE_DESTRUCTOR(_func) static void __attribute__((destructor)) _func (void);
+
+#elif defined (_MSC_VER) && (_MSC_VER >= 1500)
+/* Visual studio 2008 and later has _Pragma */
+
+/*
+ * Only try to include gslist.h if not already included via glib.h,
+ * so that items using gconstructor.h outside of GLib (such as
+ * GResources) continue to build properly.
+ */
+#ifndef __G_LIB_H__
+#include "gslist.h"
+#endif
+
+#include <stdlib.h>
+
+#define G_HAS_CONSTRUCTORS 1
+
+/* We do some weird things to avoid the constructors being optimized
+ * away on VS2015 if WholeProgramOptimization is enabled. First we
+ * make a reference to the array from the wrapper to make sure its
+ * references. Then we use a pragma to make sure the wrapper function
+ * symbol is always included at the link stage. Also, the symbols
+ * need to be extern (but not dllexport), even though they are not
+ * really used from another object file.
+ */
+
+/* We need to account for differences between the mangling of symbols
+ * for x86 and x64/ARM/ARM64 programs, as symbols on x86 are prefixed
+ * with an underscore but symbols on x64/ARM/ARM64 are not.
+ */
+#ifdef _M_IX86
+#define G_MSVC_SYMBOL_PREFIX "_"
+#else
+#define G_MSVC_SYMBOL_PREFIX ""
+#endif
+
+#define G_DEFINE_CONSTRUCTOR(_func) G_MSVC_CTOR (_func, G_MSVC_SYMBOL_PREFIX)
+#define G_DEFINE_DESTRUCTOR(_func) G_MSVC_DTOR (_func, G_MSVC_SYMBOL_PREFIX)
+
+#define G_MSVC_CTOR(_func,_sym_prefix) \
+  static void _func(void); \
+  extern int (* _array ## _func)(void);              \
+  int _func ## _wrapper(void) { _func(); g_slist_find (NULL,  _array ## _func); return 0; } \
+  __pragma(comment(linker,"/include:" _sym_prefix # _func "_wrapper")) \
+  __pragma(section(".CRT$XCU",read)) \
+  __declspec(allocate(".CRT$XCU")) int (* _array ## _func)(void) = _func ## _wrapper;
+
+#define G_MSVC_DTOR(_func,_sym_prefix) \
+  static void _func(void); \
+  extern int (* _array ## _func)(void);              \
+  int _func ## _constructor(void) { atexit (_func); g_slist_find (NULL,  _array ## _func); return 0; } \
+   __pragma(comment(linker,"/include:" _sym_prefix # _func "_constructor")) \
+  __pragma(section(".CRT$XCU",read)) \
+  __declspec(allocate(".CRT$XCU")) int (* _array ## _func)(void) = _func ## _constructor;
+
+#elif defined (_MSC_VER)
+
+#define G_HAS_CONSTRUCTORS 1
+
+/* Pre Visual studio 2008 must use #pragma section */
+#define G_DEFINE_CONSTRUCTOR_NEEDS_PRAGMA 1
+#define G_DEFINE_DESTRUCTOR_NEEDS_PRAGMA 1
+
+#define G_DEFINE_CONSTRUCTOR_PRAGMA_ARGS(_func) \
+  section(".CRT$XCU",read)
+#define G_DEFINE_CONSTRUCTOR(_func) \
+  static void _func(void); \
+  static int _func ## _wrapper(void) { _func(); return 0; } \
+  __declspec(allocate(".CRT$XCU")) static int (*p)(void) = _func ## _wrapper;
+
+#define G_DEFINE_DESTRUCTOR_PRAGMA_ARGS(_func) \
+  section(".CRT$XCU",read)
+#define G_DEFINE_DESTRUCTOR(_func) \
+  static void _func(void); \
+  static int _func ## _constructor(void) { atexit (_func); return 0; } \
+  __declspec(allocate(".CRT$XCU")) static int (* _array ## _func)(void) = _func ## _constructor;
+
+#elif defined(__SUNPRO_C)
+
+/* This is not tested, but i believe it should work, based on:
+ * http://opensource.apple.com/source/OpenSSL098/OpenSSL098-35/src/fips/fips_premain.c
+ */
+
+#define G_HAS_CONSTRUCTORS 1
+
+#define G_DEFINE_CONSTRUCTOR_NEEDS_PRAGMA 1
+#define G_DEFINE_DESTRUCTOR_NEEDS_PRAGMA 1
+
+#define G_DEFINE_CONSTRUCTOR_PRAGMA_ARGS(_func) \
+  init(_func)
+#define G_DEFINE_CONSTRUCTOR(_func) \
+  static void _func(void);
+
+#define G_DEFINE_DESTRUCTOR_PRAGMA_ARGS(_func) \
+  fini(_func)
+#define G_DEFINE_DESTRUCTOR(_func) \
+  static void _func(void);
+
+#else
+
+/* constructors not supported for this compiler */
+
+#endif
+
+#endif /* __GTK_DOC_IGNORE__ */
+#endif /* __G_CONSTRUCTOR_H__ */
+
+#ifdef G_HAS_CONSTRUCTORS
+
+#ifdef G_DEFINE_CONSTRUCTOR_NEEDS_PRAGMA
+#pragma G_DEFINE_CONSTRUCTOR_PRAGMA_ARGS(baobabresource_constructor)
+#endif
+G_DEFINE_CONSTRUCTOR(baobabresource_constructor)
+#ifdef G_DEFINE_DESTRUCTOR_NEEDS_PRAGMA
+#pragma G_DEFINE_DESTRUCTOR_PRAGMA_ARGS(baobabresource_destructor)
+#endif
+G_DEFINE_DESTRUCTOR(baobabresource_destructor)
+
+#else
+#warning "Constructor not supported on this compiler, linking in resources will not work"
+#endif
+
+static void baobabresource_constructor (void)
+{
+  g_static_resource_init (&static_resource);
+}
+
+static void baobabresource_destructor (void)
+{
+  g_static_resource_fini (&static_resource);
+}
+
+ +
+ +
+ + diff --git a/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/30.html b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/30.html new file mode 100644 index 00000000..f453d93b --- /dev/null +++ b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/30.html @@ -0,0 +1,2609 @@ + + + + + + Cppcheck - HTML report - mate-utils + + + + + +
+ + + +
+
   1
+   2
+   3
+   4
+   5
+   6
+   7
+   8
+   9
+  10
+  11
+  12
+  13
+  14
+  15
+  16
+  17
+  18
+  19
+  20
+  21
+  22
+  23
+  24
+  25
+  26
+  27
+  28
+  29
+  30
+  31
+  32
+  33
+  34
+  35
+  36
+  37
+  38
+  39
+  40
+  41
+  42
+  43
+  44
+  45
+  46
+  47
+  48
+  49
+  50
+  51
+  52
+  53
+  54
+  55
+  56
+  57
+  58
+  59
+  60
+  61
+  62
+  63
+  64
+  65
+  66
+  67
+  68
+  69
+  70
+  71
+  72
+  73
+  74
+  75
+  76
+  77
+  78
+  79
+  80
+  81
+  82
+  83
+  84
+  85
+  86
+  87
+  88
+  89
+  90
+  91
+  92
+  93
+  94
+  95
+  96
+  97
+  98
+  99
+ 100
+ 101
+ 102
+ 103
+ 104
+ 105
+ 106
+ 107
+ 108
+ 109
+ 110
+ 111
+ 112
+ 113
+ 114
+ 115
+ 116
+ 117
+ 118
+ 119
+ 120
+ 121
+ 122
+ 123
+ 124
+ 125
+ 126
+ 127
+ 128
+ 129
+ 130
+ 131
+ 132
+ 133
+ 134
+ 135
+ 136
+ 137
+ 138
+ 139
+ 140
+ 141
+ 142
+ 143
+ 144
+ 145
+ 146
+ 147
+ 148
+ 149
+ 150
+ 151
+ 152
+ 153
+ 154
+ 155
+ 156
+ 157
+ 158
+ 159
+ 160
+ 161
+ 162
+ 163
+ 164
+ 165
+ 166
+ 167
+ 168
+ 169
+ 170
+ 171
+ 172
+ 173
+ 174
+ 175
+ 176
+ 177
+ 178
+ 179
+ 180
+ 181
+ 182
+ 183
+ 184
+ 185
+ 186
+ 187
+ 188
+ 189
+ 190
+ 191
+ 192
+ 193
+ 194
+ 195
+ 196
+ 197
+ 198
+ 199
+ 200
+ 201
+ 202
+ 203
+ 204
+ 205
+ 206
+ 207
+ 208
+ 209
+ 210
+ 211
+ 212
+ 213
+ 214
+ 215
+ 216
+ 217
+ 218
+ 219
+ 220
+ 221
+ 222
+ 223
+ 224
+ 225
+ 226
+ 227
+ 228
+ 229
+ 230
+ 231
+ 232
+ 233
+ 234
+ 235
+ 236
+ 237
+ 238
+ 239
+ 240
+ 241
+ 242
+ 243
+ 244
+ 245
+ 246
+ 247
+ 248
+ 249
+ 250
+ 251
+ 252
+ 253
+ 254
+ 255
+ 256
+ 257
+ 258
+ 259
+ 260
+ 261
+ 262
+ 263
+ 264
+ 265
+ 266
+ 267
+ 268
+ 269
+ 270
+ 271
+ 272
+ 273
+ 274
+ 275
+ 276
+ 277
+ 278
+ 279
+ 280
+ 281
+ 282
+ 283
+ 284
+ 285
+ 286
+ 287
+ 288
+ 289
+ 290
+ 291
+ 292
+ 293
+ 294
+ 295
+ 296
+ 297
+ 298
+ 299
+ 300
+ 301
+ 302
+ 303
+ 304
+ 305
+ 306
+ 307
+ 308
+ 309
+ 310
+ 311
+ 312
+ 313
+ 314
+ 315
+ 316
+ 317
+ 318
+ 319
+ 320
+ 321
+ 322
+ 323
+ 324
+ 325
+ 326
+ 327
+ 328
+ 329
+ 330
+ 331
+ 332
+ 333
+ 334
+ 335
+ 336
+ 337
+ 338
+ 339
+ 340
+ 341
+ 342
+ 343
+ 344
+ 345
+ 346
+ 347
+ 348
+ 349
+ 350
+ 351
+ 352
+ 353
+ 354
+ 355
+ 356
+ 357
+ 358
+ 359
+ 360
+ 361
+ 362
+ 363
+ 364
+ 365
+ 366
+ 367
+ 368
+ 369
+ 370
+ 371
+ 372
+ 373
+ 374
+ 375
+ 376
+ 377
+ 378
+ 379
+ 380
+ 381
+ 382
+ 383
+ 384
+ 385
+ 386
+ 387
+ 388
+ 389
+ 390
+ 391
+ 392
+ 393
+ 394
+ 395
+ 396
+ 397
+ 398
+ 399
+ 400
+ 401
+ 402
+ 403
+ 404
+ 405
+ 406
+ 407
+ 408
+ 409
+ 410
+ 411
+ 412
+ 413
+ 414
+ 415
+ 416
+ 417
+ 418
+ 419
+ 420
+ 421
+ 422
+ 423
+ 424
+ 425
+ 426
+ 427
+ 428
+ 429
+ 430
+ 431
+ 432
+ 433
+ 434
+ 435
+ 436
+ 437
+ 438
+ 439
+ 440
+ 441
+ 442
+ 443
+ 444
+ 445
+ 446
+ 447
+ 448
+ 449
+ 450
+ 451
+ 452
+ 453
+ 454
+ 455
+ 456
+ 457
+ 458
+ 459
+ 460
+ 461
+ 462
+ 463
+ 464
+ 465
+ 466
+ 467
+ 468
+ 469
+ 470
+ 471
+ 472
+ 473
+ 474
+ 475
+ 476
+ 477
+ 478
+ 479
+ 480
+ 481
+ 482
+ 483
+ 484
+ 485
+ 486
+ 487
+ 488
+ 489
+ 490
+ 491
+ 492
+ 493
+ 494
+ 495
+ 496
+ 497
+ 498
+ 499
+ 500
+ 501
+ 502
+ 503
+ 504
+ 505
+ 506
+ 507
+ 508
+ 509
+ 510
+ 511
+ 512
+ 513
+ 514
+ 515
+ 516
+ 517
+ 518
+ 519
+ 520
+ 521
+ 522
+ 523
+ 524
+ 525
+ 526
+ 527
+ 528
+ 529
+ 530
+ 531
+ 532
+ 533
+ 534
+ 535
+ 536
+ 537
+ 538
+ 539
+ 540
+ 541
+ 542
+ 543
+ 544
+ 545
+ 546
+ 547
+ 548
+ 549
+ 550
+ 551
+ 552
+ 553
+ 554
+ 555
+ 556
+ 557
+ 558
+ 559
+ 560
+ 561
+ 562
+ 563
+ 564
+ 565
+ 566
+ 567
+ 568
+ 569
+ 570
+ 571
+ 572
+ 573
+ 574
+ 575
+ 576
+ 577
+ 578
+ 579
+ 580
+ 581
+ 582
+ 583
+ 584
+ 585
+ 586
+ 587
+ 588
+ 589
+ 590
+ 591
+ 592
+ 593
+ 594
+ 595
+ 596
+ 597
+ 598
+ 599
+ 600
+ 601
+ 602
+ 603
+ 604
+ 605
+ 606
+ 607
+ 608
+ 609
+ 610
+ 611
+ 612
+ 613
+ 614
+ 615
+ 616
+ 617
+ 618
+ 619
+ 620
+ 621
+ 622
+ 623
+ 624
+ 625
+ 626
+ 627
+ 628
+ 629
+ 630
+ 631
+ 632
+ 633
+ 634
+ 635
+ 636
+ 637
+ 638
+ 639
+ 640
+ 641
+ 642
+ 643
+ 644
+ 645
+ 646
+ 647
+ 648
+ 649
+ 650
+ 651
+ 652
+ 653
+ 654
+ 655
+ 656
+ 657
+ 658
+ 659
+ 660
+ 661
+ 662
+ 663
+ 664
+ 665
+ 666
+ 667
+ 668
+ 669
+ 670
+ 671
+ 672
+ 673
+ 674
+ 675
+ 676
+ 677
+ 678
+ 679
+ 680
+ 681
+ 682
+ 683
+ 684
+ 685
+ 686
+ 687
+ 688
+ 689
+ 690
+ 691
+ 692
+ 693
+ 694
+ 695
+ 696
+ 697
+ 698
+ 699
+ 700
+ 701
+ 702
+ 703
+ 704
+ 705
+ 706
+ 707
+ 708
+ 709
+ 710
+ 711
+ 712
+ 713
+ 714
+ 715
+ 716
+ 717
+ 718
+ 719
+ 720
+ 721
+ 722
+ 723
+ 724
+ 725
+ 726
+ 727
+ 728
+ 729
+ 730
+ 731
+ 732
+ 733
+ 734
+ 735
+ 736
+ 737
+ 738
+ 739
+ 740
+ 741
+ 742
+ 743
+ 744
+ 745
+ 746
+ 747
+ 748
+ 749
+ 750
+ 751
+ 752
+ 753
+ 754
+ 755
+ 756
+ 757
+ 758
+ 759
+ 760
+ 761
+ 762
+ 763
+ 764
+ 765
+ 766
+ 767
+ 768
+ 769
+ 770
+ 771
+ 772
+ 773
+ 774
+ 775
+ 776
+ 777
+ 778
+ 779
+ 780
+ 781
+ 782
+ 783
+ 784
+ 785
+ 786
+ 787
+ 788
+ 789
+ 790
+ 791
+ 792
+ 793
+ 794
+ 795
+ 796
+ 797
+ 798
+ 799
+ 800
+ 801
+ 802
+ 803
+ 804
+ 805
+ 806
+ 807
+ 808
+ 809
+ 810
+ 811
+ 812
+ 813
+ 814
+ 815
+ 816
+ 817
+ 818
+ 819
+ 820
+ 821
+ 822
+ 823
+ 824
+ 825
+ 826
+ 827
+ 828
+ 829
+ 830
+ 831
+ 832
+ 833
+ 834
+ 835
+ 836
+ 837
+ 838
+ 839
+ 840
+ 841
+ 842
+ 843
+ 844
+ 845
+ 846
+ 847
+ 848
+ 849
+ 850
+ 851
+ 852
+ 853
+ 854
+ 855
+ 856
+ 857
+ 858
+ 859
+ 860
+ 861
+ 862
+ 863
+ 864
+ 865
+ 866
+ 867
+ 868
+ 869
+ 870
+ 871
+ 872
+ 873
+ 874
+ 875
+ 876
+ 877
+ 878
+ 879
+ 880
+ 881
+ 882
+ 883
+ 884
+ 885
+ 886
+ 887
+ 888
+ 889
+ 890
+ 891
+ 892
+ 893
+ 894
+ 895
+ 896
+ 897
+ 898
+ 899
+ 900
+ 901
+ 902
+ 903
+ 904
+ 905
+ 906
+ 907
+ 908
+ 909
+ 910
+ 911
+ 912
+ 913
+ 914
+ 915
+ 916
+ 917
+ 918
+ 919
+ 920
+ 921
+ 922
+ 923
+ 924
+ 925
+ 926
+ 927
+ 928
+ 929
+ 930
+ 931
+ 932
+ 933
+ 934
+ 935
+ 936
+ 937
+ 938
+ 939
+ 940
+ 941
+ 942
+ 943
+ 944
+ 945
+ 946
+ 947
+ 948
+ 949
+ 950
+ 951
+ 952
+ 953
+ 954
+ 955
+ 956
+ 957
+ 958
+ 959
+ 960
+ 961
+ 962
+ 963
+ 964
+ 965
+ 966
+ 967
+ 968
+ 969
+ 970
+ 971
+ 972
+ 973
+ 974
+ 975
+ 976
+ 977
+ 978
+ 979
+ 980
+ 981
+ 982
+ 983
+ 984
+ 985
+ 986
+ 987
+ 988
+ 989
+ 990
+ 991
+ 992
+ 993
+ 994
+ 995
+ 996
+ 997
+ 998
+ 999
+1000
+1001
+1002
+1003
+1004
+1005
+1006
+1007
+1008
+1009
+1010
+1011
+1012
+1013
+1014
+1015
+1016
+1017
+1018
+1019
+1020
+1021
+1022
+1023
+1024
+1025
+1026
+1027
+1028
+1029
+1030
+1031
+1032
+1033
+1034
+1035
+1036
+1037
+1038
+1039
+1040
+1041
+1042
+1043
+1044
+1045
+1046
+1047
+1048
+1049
+1050
+1051
+1052
+1053
+1054
+1055
+1056
+1057
+1058
+1059
+1060
+1061
+1062
+1063
+1064
+1065
+1066
+1067
+1068
+1069
+1070
+1071
+1072
+1073
+1074
+1075
+1076
+1077
+1078
+1079
+1080
+1081
+1082
+1083
+1084
+1085
+1086
+1087
+1088
+1089
+1090
+1091
+1092
+1093
+1094
+1095
+1096
+1097
+1098
+1099
+1100
+1101
+1102
+1103
+1104
+1105
+1106
+1107
+1108
+1109
+1110
+1111
+1112
+1113
+1114
+1115
+1116
+1117
+1118
+1119
+1120
+1121
+1122
+1123
+1124
+1125
+1126
+1127
+1128
+1129
+1130
+1131
+1132
+1133
+1134
+1135
+1136
+1137
+1138
+1139
+1140
+1141
+1142
+1143
+1144
+1145
+1146
+1147
+1148
+1149
+1150
+1151
+1152
+1153
+1154
+1155
+1156
+1157
+1158
+1159
+1160
+1161
+1162
+1163
+1164
+1165
+1166
+1167
+1168
+1169
+1170
+1171
+1172
+1173
+1174
+1175
+1176
+1177
+1178
+1179
+1180
+1181
+1182
+1183
+1184
+1185
+1186
/* Copyright (C) 2005 Emmanuele Bassi <ebassi@gmail.com>
+ * Copyright (C) 2012-2021 MATE Developers
+ *
+ * This file is part of MATE Utils.
+ *
+ * MATE Utils is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * MATE Utils is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MATE Utils.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+/**
+ * SECTION:gdict-source
+ * @short_description: A dictionary source definition
+ *
+ * #GdictSource is the representation of a #GdictContext. Each dictionary
+ * source provides a list of available dictionaries (databases) and a list
+ * of available matching strategies. Using a #GdictContext you can query
+ * the dictionary source for matching words and for definitions.
+ *
+ * By using a #GdictSource object you can retrieve the appropriate
+ * #GdictContext, already set up with the right parameters.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib/gi18n-lib.h>
+
+#include "gdict-source.h"
+#include "gdict-client-context.h"
+#include "gdict-utils.h"
+#include "gdict-enum-types.h"
+#include "gdict-private.h"
+
+/* Main group */
+#define SOURCE_GROUP		"Dictionary Source"
+
+/* Common keys */
+#define SOURCE_KEY_NAME		"Name"
+#define SOURCE_KEY_DESCRIPTION	"Description"
+#define SOURCE_KEY_TRANSPORT	"Transport"
+#define SOURCE_KEY_DATABASE 	"Database"
+#define SOURCE_KEY_STRATEGY 	"Strategy"
+
+/* dictd transport keys */
+#define SOURCE_KEY_HOSTNAME	"Hostname"
+#define SOURCE_KEY_PORT		"Port"
+
+struct _GdictSourcePrivate
+{
+  gchar *filename;
+  GKeyFile *keyfile;
+
+  gchar *name;
+  gchar *description;
+
+  gchar *database;
+  gchar *strategy;
+
+  GdictSourceTransport transport;
+
+  GdictContext *context;
+};
+
+enum
+{
+  PROP_0,
+
+  PROP_FILENAME,
+  PROP_NAME,
+  PROP_DESCRIPTION,
+  PROP_DATABASE,
+  PROP_STRATEGY,
+  PROP_TRANSPORT,
+  PROP_CONTEXT
+};
+
+/* keep in sync with GdictSourceTransport */
+static const gchar *valid_transports[] =
+{
+  "dictd",	/* GDICT_SOURCE_TRANSPORT_DICTD */
+
+  NULL		/* GDICT_SOURCE_TRANSPORT_INVALID */
+};
+
+#define IS_VALID_TRANSPORT(t)	(((t) >= GDICT_SOURCE_TRANSPORT_DICTD) && \
+				 ((t) < GDICT_SOURCE_TRANSPORT_INVALID))
+
+GQuark
+gdict_source_error_quark (void)
+{
+  static GQuark quark = 0;
+
+  if (G_UNLIKELY (quark == 0))
+    quark = g_quark_from_static_string ("gdict-source-error-quark");
+
+  return quark;
+}
+
+G_DEFINE_TYPE_WITH_PRIVATE (GdictSource, gdict_source, G_TYPE_OBJECT);
+
+static void
+gdict_source_set_property (GObject      *object,
+			   guint         prop_id,
+			   const GValue *value,
+			   GParamSpec   *pspec)
+{
+  GdictSource *source = GDICT_SOURCE (object);
+
+  switch (prop_id)
+    {
+    case PROP_NAME:
+      gdict_source_set_name (source, g_value_get_string (value));
+      break;
+    case PROP_DESCRIPTION:
+      gdict_source_set_description (source, g_value_get_string (value));
+      break;
+    case PROP_TRANSPORT:
+      gdict_source_set_transport (source, g_value_get_enum (value), NULL);
+      break;
+    case PROP_DATABASE:
+      gdict_source_set_database (source, g_value_get_string (value));
+      break;
+    case PROP_STRATEGY:
+      gdict_source_set_strategy (source, g_value_get_string (value));
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+gdict_source_get_property (GObject    *object,
+			   guint       prop_id,
+			   GValue     *value,
+			   GParamSpec *pspec)
+{
+  GdictSource *source = GDICT_SOURCE (object);
+  GdictSourcePrivate *priv = source->priv;
+
+  switch (prop_id)
+    {
+    case PROP_FILENAME:
+      g_value_set_string (value, priv->filename);
+      break;
+    case PROP_NAME:
+      g_value_set_string (value, priv->name);
+      break;
+    case PROP_DESCRIPTION:
+      g_value_set_string (value, priv->description);
+      break;
+    case PROP_DATABASE:
+      g_value_set_string (value, priv->database);
+      break;
+    case PROP_STRATEGY:
+      g_value_set_string (value, priv->strategy);
+      break;
+    case PROP_TRANSPORT:
+      g_value_set_enum (value, priv->transport);
+      break;
+    case PROP_CONTEXT:
+      g_value_set_object (value, gdict_source_peek_context (source));
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+gdict_source_finalize (GObject *object)
+{
+  GdictSourcePrivate *priv = gdict_source_get_instance_private (GDICT_SOURCE (object));
+
+  g_free (priv->filename);
+
+  if (priv->keyfile)
+    g_key_file_free (priv->keyfile);
+
+  g_free (priv->name);
+  g_free (priv->description);
+
+  g_free (priv->database);
+  g_free (priv->strategy);
+
+  if (priv->context)
+    g_object_unref (priv->context);
+
+  G_OBJECT_CLASS (gdict_source_parent_class)->finalize (object);
+}
+
+static void
+gdict_source_class_init (GdictSourceClass *klass)
+{
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+  gobject_class->set_property = gdict_source_set_property;
+  gobject_class->get_property = gdict_source_get_property;
+  gobject_class->finalize = gdict_source_finalize;
+
+  /**
+   * GdictSource:filename
+   *
+   * The filename used by this dictionary source.
+   *
+   * Since: 1.0
+   */
+  g_object_class_install_property (gobject_class,
+  				   PROP_FILENAME,
+  				   g_param_spec_string ("filename",
+  				   			_("Filename"),
+  				   			_("The filename used by this dictionary source"),
+  				   			NULL,
+  				   			G_PARAM_READABLE));
+  /**
+   * GdictSource:name
+   *
+   * The display name of this dictionary source.
+   *
+   * Since: 1.0
+   */
+  g_object_class_install_property (gobject_class,
+  				   PROP_NAME,
+  				   g_param_spec_string ("name",
+  				   			_("Name"),
+  				   			_("The display name of this dictionary source"),
+  				   			NULL,
+  				   			(G_PARAM_READABLE | G_PARAM_WRITABLE)));
+  /**
+   * GdictSource:description
+   *
+   * The description of this dictionary source.
+   *
+   * Since: 1.0
+   */
+  g_object_class_install_property (gobject_class,
+  				   PROP_DESCRIPTION,
+  				   g_param_spec_string ("description",
+  				   			_("Description"),
+  				   			_("The description of this dictionary source"),
+  				   			NULL,
+  				   			(G_PARAM_READABLE | G_PARAM_WRITABLE)));
+  /**
+   * GdictSource:database
+   *
+   * The default database of this dictionary source.
+   *
+   * Since: 1.0
+   */
+  g_object_class_install_property (gobject_class,
+  				   PROP_DATABASE,
+  				   g_param_spec_string ("database",
+  				   			_("Database"),
+  				   			_("The default database of this dictionary source"),
+  				   			NULL,
+  				   			(G_PARAM_READABLE | G_PARAM_WRITABLE)));
+  /**
+   * GdictSource:strategy
+   *
+   * The default strategy of this dictionary source.
+   *
+   * Since: 1.0
+   */
+  g_object_class_install_property (gobject_class,
+  				   PROP_STRATEGY,
+  				   g_param_spec_string ("strategy",
+  				   			_("Strategy"),
+  				   			_("The default strategy of this dictionary source"),
+  				   			NULL,
+  				   			(G_PARAM_READABLE | G_PARAM_WRITABLE)));
+  /**
+   * GdictSource:transport
+   *
+   * The transport mechanism used by this source.
+   *
+   * Since: 1.0
+   */
+  g_object_class_install_property (gobject_class,
+  				   PROP_TRANSPORT,
+  				   g_param_spec_enum ("transport",
+  				   		      _("Transport"),
+  				   		      _("The transport mechanism used by this dictionary source"),
+  				   		      GDICT_TYPE_SOURCE_TRANSPORT,
+  				   		      GDICT_SOURCE_TRANSPORT_INVALID,
+  				   		      (G_PARAM_READABLE | G_PARAM_WRITABLE)));
+  /**
+   * GdictSource:context
+   *
+   * The #GdictContext bound to this source.
+   *
+   * Since: 1.0
+   */
+  g_object_class_install_property (gobject_class,
+  				   PROP_CONTEXT,
+  				   g_param_spec_object ("context",
+  				   			_("Context"),
+  				   			_("The GdictContext bound to this source"),
+  				   			GDICT_TYPE_CONTEXT,
+  				   			G_PARAM_READABLE));
+}
+
+static void
+gdict_source_init (GdictSource *source)
+{
+  GdictSourcePrivate *priv;
+
+  priv = gdict_source_get_instance_private (source);
+  source->priv = priv;
+
+  priv->filename = NULL;
+  priv->keyfile = g_key_file_new ();
+
+  priv->name = NULL;
+  priv->description = NULL;
+  priv->database = NULL;
+  priv->strategy = NULL;
+  priv->transport = GDICT_SOURCE_TRANSPORT_INVALID;
+
+  priv->context = NULL;
+}
+
+/**
+ * gdict_source_new:
+ *
+ * Creates an empty #GdictSource object.  Use gdict_load_from_file() to
+ * read an existing dictionary source definition file.
+ *
+ * Return value: an empty #GdictSource
+ */
+GdictSource *
+gdict_source_new (void)
+{
+  return g_object_new (GDICT_TYPE_SOURCE, NULL);
+}
+
+static GdictSourceTransport
+gdict_source_resolve_transport (const gchar *transport)
+{
+  if (!transport)
+    return GDICT_SOURCE_TRANSPORT_INVALID;
+
+  if (strcmp (transport, "dictd") == 0)
+    return GDICT_SOURCE_TRANSPORT_DICTD;
+  else
+    return GDICT_SOURCE_TRANSPORT_INVALID;
+
+  g_assert_not_reached ();
+}
+
+static GdictContext *
+gdict_source_create_context (GdictSource           *source,
+			     GdictSourceTransport   transport,
+			     GError               **error)
+{
+  GdictSourcePrivate *priv;
+  GdictContext *context;
+
+  g_assert (GDICT_IS_SOURCE (source));
+
+  priv = source->priv;
+
+  switch (transport)
+    {
+    case GDICT_SOURCE_TRANSPORT_DICTD:
+      {
+      gchar *hostname;
+      gint port;
+
+      hostname = g_key_file_get_string (priv->keyfile,
+      					SOURCE_GROUP,
+      					SOURCE_KEY_HOSTNAME,
+      					NULL);
+
+      port = g_key_file_get_integer (priv->keyfile,
+      				     SOURCE_GROUP,
+      				     SOURCE_KEY_PORT,
+      				     NULL);
+      if (!port)
+        port = -1;
+
+      context = gdict_client_context_new (hostname, port);
+
+      g_free (hostname);
+      }
+      break;
+    default:
+      g_set_error (error, GDICT_SOURCE_ERROR,
+                   GDICT_SOURCE_ERROR_PARSE,
+                   _("Invalid transport type '%d'"),
+                   transport);
+      return NULL;
+    }
+
+  g_assert (context != NULL);
+
+  if (priv->transport != transport)<--- Condition 'priv->transport!=transport' is redundant
+    priv->transport = transport;<--- Assignment 'priv->transport=transport'
+
+  return context;
+}
+
+static gboolean
+gdict_source_parse (GdictSource  *source,
+		    GError      **error)
+{
+  GdictSourcePrivate *priv;
+  GError *parse_error;
+  gchar *transport;
+  GdictSourceTransport t;
+
+  priv = source->priv;
+
+  if (!g_key_file_has_group (priv->keyfile, SOURCE_GROUP))
+    {
+      g_set_error (error, GDICT_SOURCE_ERROR,
+                   GDICT_SOURCE_ERROR_PARSE,
+                   _("No '%s' group found inside the dictionary source definition"),
+                   SOURCE_GROUP);
+
+      return FALSE;
+    }
+
+  /* fetch the name for the dictionary source definition */
+  parse_error = NULL;
+  priv->name = g_key_file_get_string (priv->keyfile,
+		  		      SOURCE_GROUP,
+				      SOURCE_KEY_NAME,
+				      &parse_error);
+  if (parse_error)
+    {
+      g_set_error (error, GDICT_SOURCE_ERROR,
+                   GDICT_SOURCE_ERROR_PARSE,
+                   _("Unable to get the '%s' key inside the dictionary "
+                     "source definition: %s"),
+                   SOURCE_KEY_NAME,
+                   parse_error->message);
+      g_error_free (parse_error);
+
+      g_key_file_free (priv->keyfile);
+      priv->keyfile = NULL;
+
+      return FALSE;
+    }
+
+  /* if present, fetch the localized description */
+  if (g_key_file_has_key (priv->keyfile, SOURCE_GROUP, SOURCE_KEY_DESCRIPTION, NULL))
+    {
+      priv->description = g_key_file_get_locale_string (priv->keyfile,
+                                                        SOURCE_GROUP,
+                                                        SOURCE_KEY_DESCRIPTION,
+                                                        NULL,
+                                                        &parse_error);
+      if (parse_error)
+        {
+          g_set_error (error, GDICT_SOURCE_ERROR,
+                       GDICT_SOURCE_ERROR_PARSE,
+                       _("Unable to get the '%s' key inside the dictionary "
+                         "source definition: %s"),
+                       SOURCE_KEY_DESCRIPTION,
+                       parse_error->message);
+
+          g_error_free (parse_error);
+          g_key_file_free (priv->keyfile);
+          priv->keyfile = NULL;
+          g_free (priv->name);
+
+          return FALSE;
+        }
+    }
+
+  if (g_key_file_has_key (priv->keyfile, SOURCE_GROUP, SOURCE_KEY_DATABASE, NULL))
+    {
+      priv->database = g_key_file_get_string (priv->keyfile,
+                                              SOURCE_GROUP,
+                                              SOURCE_KEY_DATABASE,
+                                              &parse_error);
+      if (parse_error)
+        {
+          g_set_error (error, GDICT_SOURCE_ERROR,
+                       GDICT_SOURCE_ERROR_PARSE,
+                       _("Unable to get the '%s' key inside the dictionary "
+                         "source definition: %s"),
+                       SOURCE_KEY_DATABASE,
+                       parse_error->message);
+
+          g_error_free (parse_error);
+          g_key_file_free (priv->keyfile);
+          priv->keyfile = NULL;
+          g_free (priv->name);
+          g_free (priv->description);
+
+          return FALSE;
+        }
+    }
+
+  if (g_key_file_has_key (priv->keyfile, SOURCE_GROUP, SOURCE_KEY_STRATEGY, NULL))
+    {
+      priv->strategy = g_key_file_get_string (priv->keyfile,
+                                              SOURCE_GROUP,
+                                              SOURCE_KEY_STRATEGY,
+                                              &parse_error);
+      if (parse_error)
+        {
+          g_set_error (error, GDICT_SOURCE_ERROR,
+                       GDICT_SOURCE_ERROR_PARSE,
+                       _("Unable to get the '%s' key inside the dictionary "
+                         "source definition: %s"),
+                       SOURCE_KEY_STRATEGY,
+                       parse_error->message);
+
+          g_error_free (parse_error);
+          g_key_file_free (priv->keyfile);
+          priv->keyfile = NULL;
+
+          g_free (priv->name);
+          g_free (priv->description);
+          g_free (priv->database);
+
+          return FALSE;
+        }
+    }
+
+  transport = g_key_file_get_string (priv->keyfile,
+  				     SOURCE_GROUP,
+  				     SOURCE_KEY_TRANSPORT,
+  				     &parse_error);
+  if (parse_error)
+    {
+      g_set_error (error, GDICT_SOURCE_ERROR,
+      		   GDICT_SOURCE_ERROR_PARSE,
+      		   _("Unable to get the '%s' key inside the dictionary "
+      		     "source definition file: %s"),
+      		   SOURCE_KEY_TRANSPORT,
+      		   parse_error->message);
+
+      g_error_free (parse_error);
+      g_key_file_free (priv->keyfile);
+      priv->keyfile = NULL;
+      g_free (priv->name);
+      g_free (priv->description);
+      g_free (priv->database);
+      g_free (priv->strategy);
+
+      return FALSE;
+    }
+
+  t = gdict_source_resolve_transport (transport);
+  g_free (transport);
+
+  priv->context = gdict_source_create_context (source, t, &parse_error);
+  if (parse_error)
+    {
+      g_propagate_error (error, parse_error);
+
+      g_key_file_free (priv->keyfile);
+      priv->keyfile = NULL;
+
+      g_free (priv->name);
+      g_free (priv->description);
+      g_free (priv->database);
+      g_free (priv->strategy);
+
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
+/**
+ * gdict_source_load_from_file:
+ * @source: an empty #GdictSource
+ * @filename: path to a dictionary source file
+ * @error: return location for a #GError or %NULL
+ *
+ * Loads a dictionary source definition file into an empty #GdictSource
+ * object.
+ *
+ * Return value: %TRUE if @filename was loaded successfully.
+ *
+ * Since: 1.0
+ */
+gboolean
+gdict_source_load_from_file (GdictSource  *source,
+			     const gchar  *filename,
+			     GError      **error)
+{
+  GdictSourcePrivate *priv;
+  GError *read_error;
+  GError *parse_error;
+
+  g_return_val_if_fail (GDICT_IS_SOURCE (source), FALSE);
+  g_return_val_if_fail (filename != NULL, FALSE);
+
+  priv = source->priv;
+
+  if (!priv->keyfile)
+    priv->keyfile = g_key_file_new ();
+
+  read_error = NULL;
+  g_key_file_load_from_file (priv->keyfile,
+                             filename,
+                             G_KEY_FILE_KEEP_TRANSLATIONS,
+                             &read_error);
+  if (read_error)
+    {
+      g_propagate_error (error, read_error);
+
+      return FALSE;
+    }
+
+  parse_error = NULL;
+  gdict_source_parse (source, &parse_error);
+  if (parse_error)
+    {
+      g_propagate_error (error, parse_error);
+
+      return FALSE;
+    }
+
+  g_assert (priv->context != NULL);
+
+  priv->filename = g_strdup (filename);
+
+  return TRUE;
+}
+
+/**
+ * gdict_source_load_from_data:
+ * @source: a #GdictSource
+ * @data: string containing a dictionary source
+ * @length: length of @data
+ * @error: return location for a #GError or %NULL
+ *
+ * Loads a dictionary source definition from @data inside an empty
+ * #GdictSource object.
+ *
+ * Return value: %TRUE if @filename was loaded successfully.
+ *
+ * Since: 1.0
+ */
+gboolean
+gdict_source_load_from_data (GdictSource  *source,
+			     const gchar  *data,
+			     gsize         length,
+			     GError      **error)
+{
+  GdictSourcePrivate *priv;
+  GError *read_error;
+  GError *parse_error;
+
+  g_return_val_if_fail (GDICT_IS_SOURCE (source), FALSE);
+  g_return_val_if_fail (data != NULL, FALSE);
+
+  priv = source->priv;
+
+  if (!priv->keyfile)
+    priv->keyfile = g_key_file_new ();
+
+  read_error = NULL;
+  g_key_file_load_from_data (priv->keyfile,
+                             data,
+                             length,
+                             G_KEY_FILE_KEEP_TRANSLATIONS,
+                             &read_error);
+  if (read_error)
+    {
+      g_propagate_error (error, read_error);
+
+      return FALSE;
+    }
+
+  parse_error = NULL;
+  gdict_source_parse (source, &parse_error);
+  if (parse_error)
+    {
+      g_propagate_error (error, parse_error);
+
+      return FALSE;
+    }
+
+  g_assert (priv->context != NULL);
+
+  g_free (priv->filename);
+  priv->filename = NULL;
+
+  return TRUE;
+}
+
+/**
+ * gdict_source_to_data:
+ * @source: a #GdictSource
+ * @length: return loaction for the length of the string, or %NULL
+ * @error: return location for a #GError or %NULL
+ *
+ * Outputs a dictionary source as a string.
+ *
+ * Return value: a newly allocated string holding the contents of @source.
+ *
+ * Since: 1.0
+ */
+gchar *
+gdict_source_to_data (GdictSource  *source,
+		      gsize        *length,
+		      GError      **error)
+{
+  GdictSourcePrivate *priv;
+  gchar *retval = NULL;
+
+  g_return_val_if_fail (GDICT_IS_SOURCE (source), NULL);
+
+  priv = source->priv;
+
+  if (!priv->name)
+    {
+      g_set_error (error, GDICT_SOURCE_ERROR,
+                   GDICT_SOURCE_ERROR_INVALID_NAME,
+                   _("Dictionary source does not have name"));
+
+      return NULL;
+    }
+
+  if (!IS_VALID_TRANSPORT (priv->transport))
+    {
+      g_set_error (error, GDICT_SOURCE_ERROR,
+                   GDICT_SOURCE_ERROR_INVALID_TRANSPORT,
+                   _("Dictionary source '%s' has invalid transport '%s'"),
+                   priv->name,
+                   valid_transports[priv->transport]);
+
+      return NULL;
+    }
+
+  if (priv->keyfile)
+    {
+      GError *write_error = NULL;
+
+      retval = g_key_file_to_data (priv->keyfile,
+      				   length,
+      				   &write_error);
+      if (write_error)
+        g_propagate_error (error, write_error);
+    }
+
+  return retval;
+}
+
+/**
+ * gdict_source_set_name:
+ * @source: a #GdictSource
+ * @name: the UTF8-encoded name of the dictionary source
+ *
+ * Sets @name as the displayable name of the dictionary source.
+ *
+ * Since: 1.0
+ */
+void
+gdict_source_set_name (GdictSource *source,
+		       const gchar *name)
+{
+  g_return_if_fail (GDICT_IS_SOURCE (source));
+  g_return_if_fail (name != NULL);
+
+  g_free (source->priv->name);
+  source->priv->name = g_strdup (name);
+
+  if (!source->priv->keyfile)
+    source->priv->keyfile = g_key_file_new ();
+
+  g_key_file_set_string (source->priv->keyfile,
+    			 SOURCE_GROUP,
+    			 SOURCE_KEY_NAME,
+    			 name);
+}
+
+/**
+ * gdict_source_get_name:
+ * @source: a #GdictSource
+ *
+ * Retrieves the name of @source.
+ *
+ * Return value: the name of a #GdictSource.  The returned string is owned
+ *   by the #GdictSource object, and should not be modified or freed.
+ *
+ * Since: 1.0
+ */
+const gchar *
+gdict_source_get_name (GdictSource *source)
+{
+  g_return_val_if_fail (GDICT_IS_SOURCE (source), NULL);
+
+  return source->priv->name;
+}
+
+/**
+ * gdict_source_set_description:
+ * @source: a #GdictSource
+ * @description: a UTF-8 encoded description or %NULL
+ *
+ * Sets the description of @source.  If @description is %NULL, unsets the
+ * currently set description.
+ *
+ * Since: 1.0
+ */
+void
+gdict_source_set_description (GdictSource *source,
+			      const gchar *description)
+{
+  g_return_if_fail (GDICT_IS_SOURCE (source));
+
+  g_free (source->priv->description);
+
+  if (!source->priv->keyfile)
+    source->priv->keyfile = g_key_file_new ();
+
+  if (description && description[0] != '\0')
+    {
+      source->priv->description = g_strdup (description);
+
+      g_key_file_set_string (source->priv->keyfile,
+  			     SOURCE_GROUP,
+  			     SOURCE_KEY_DESCRIPTION,
+  			     description);
+    }
+  else
+    {
+      if (g_key_file_has_key (source->priv->keyfile,
+      			      SOURCE_GROUP,
+      			      SOURCE_KEY_DESCRIPTION,
+      			      NULL))
+        g_key_file_remove_key (source->priv->keyfile,
+                               SOURCE_GROUP,
+                               SOURCE_KEY_DESCRIPTION,
+                               NULL);
+    }
+}
+
+/**
+ * gdict_source_get_description:
+ * @source: a #GdictSource
+ *
+ * Retrieves the description of @source.
+ *
+ * Return value: the description of a #GdictSource.  The returned string is
+ *   owned by the #GdictSource object, and should not be modified or freed.
+ *
+ * Since: 1.0
+ */
+const gchar *
+gdict_source_get_description (GdictSource *source)
+{
+  g_return_val_if_fail (GDICT_IS_SOURCE (source), NULL);
+
+  return source->priv->description;
+}
+
+/**
+ * gdict_source_set_database:
+ * @source: a #GdictSource
+ * @database: a UTF-8 encoded database name or %NULL
+ *
+ * Sets the default database of @source.  If @database is %NULL, unsets the
+ * currently set database.
+ *
+ * Since: 1.0
+ */
+void
+gdict_source_set_database (GdictSource *source,
+			   const gchar *database)
+{
+  g_return_if_fail (GDICT_IS_SOURCE (source));
+
+  g_free (source->priv->database);
+
+  if (!source->priv->keyfile)
+    source->priv->keyfile = g_key_file_new ();
+
+  if (database && database[0] != '\0')
+    {
+      source->priv->database = g_strdup (database);
+
+      g_key_file_set_string (source->priv->keyfile,
+  			     SOURCE_GROUP,
+  			     SOURCE_KEY_DATABASE,
+  			     database);
+    }
+  else
+    {
+      if (g_key_file_has_key (source->priv->keyfile,
+      			      SOURCE_GROUP,
+      			      SOURCE_KEY_DATABASE,
+      			      NULL))
+        g_key_file_remove_key (source->priv->keyfile,
+                               SOURCE_GROUP,
+                               SOURCE_KEY_DATABASE,
+                               NULL);
+    }
+}
+
+/**
+ * gdict_source_get_database:
+ * @source: a #GdictSource
+ *
+ * Retrieves the default database of @source.
+ *
+ * Return value: the default strategy of a #GdictSource.  The returned string
+ *   is owned by the #GdictSource object, and should not be modified or freed.
+ *
+ * Since: 1.0
+ */
+const gchar *
+gdict_source_get_database (GdictSource *source)
+{
+  g_return_val_if_fail (GDICT_IS_SOURCE (source), NULL);
+
+  return source->priv->database;
+}
+
+/**
+ * gdict_source_set_strategy:
+ * @source: a #GdictSource
+ * @strategy: a UTF-8 encoded strategy or %NULL
+ *
+ * Sets the description of @source.  If @strategy is %NULL, unsets the
+ * currently set strategy.
+ *
+ * Since: 1.0
+ */
+void
+gdict_source_set_strategy (GdictSource *source,
+			   const gchar *strategy)
+{
+  g_return_if_fail (GDICT_IS_SOURCE (source));
+
+  g_free (source->priv->strategy);
+
+  if (!source->priv->keyfile)
+    source->priv->keyfile = g_key_file_new ();
+
+  if (strategy && strategy[0] != '\0')
+    {
+      source->priv->strategy = g_strdup (strategy);
+
+      g_key_file_set_string (source->priv->keyfile,
+  			     SOURCE_GROUP,
+  			     SOURCE_KEY_STRATEGY,
+  			     strategy);
+    }
+  else
+    {
+      if (g_key_file_has_key (source->priv->keyfile,
+      			      SOURCE_GROUP,
+      			      SOURCE_KEY_STRATEGY,
+      			      NULL))
+        g_key_file_remove_key (source->priv->keyfile,
+                               SOURCE_GROUP,
+                               SOURCE_KEY_STRATEGY,
+                               NULL);
+    }
+}
+
+/**
+ * gdict_source_get_strategy:
+ * @source: a #GdictSource
+ *
+ * Retrieves the default strategy of @source.
+ *
+ * Return value: the default strategy of a #GdictSource.  The returned string
+ *   is owned by the #GdictSource object, and should not be modified or freed.
+ *
+ * Since: 1.0
+ */
+const gchar *
+gdict_source_get_strategy (GdictSource *source)
+{
+  g_return_val_if_fail (GDICT_IS_SOURCE (source), NULL);
+
+  return source->priv->strategy;
+}
+
+/**
+ * gdict_source_set_transportv
+ * @source: a #GdictSource
+ * @transport: a #GdictSourceTransport
+ * @first_transport_property: FIXME
+ * @var_args: FIXME
+ *
+ * FIXME
+ *
+ * Since: 1.0
+ */
+void
+gdict_source_set_transportv (GdictSource          *source,
+			     GdictSourceTransport  transport,
+			     const gchar          *first_transport_property,
+			     va_list               var_args)
+{
+  GdictSourcePrivate *priv;
+
+  g_return_if_fail (GDICT_IS_SOURCE (source));
+  g_return_if_fail (IS_VALID_TRANSPORT (transport));
+
+  priv = source->priv;
+
+  priv->transport = transport;
+
+  if (priv->context)
+    g_object_unref (priv->context);
+
+  switch (priv->transport)
+    {
+    case GDICT_SOURCE_TRANSPORT_DICTD:
+      priv->context = gdict_client_context_new (NULL, -1);
+      g_assert (GDICT_IS_CLIENT_CONTEXT (priv->context));
+
+      g_object_set_valist (G_OBJECT (priv->context),
+                           first_transport_property,
+                           var_args);
+
+      break;
+    case GDICT_SOURCE_TRANSPORT_INVALID:
+    default:
+      g_assert_not_reached ();
+      break;
+    }
+
+  /* update the keyfile */
+  if (!priv->keyfile)
+    priv->keyfile = g_key_file_new ();
+
+  g_key_file_set_string (priv->keyfile,
+  			 SOURCE_GROUP,
+  			 SOURCE_KEY_TRANSPORT,
+  			 valid_transports[transport]);
+
+  switch (priv->transport)
+    {
+    case GDICT_SOURCE_TRANSPORT_DICTD:
+      g_key_file_set_string (priv->keyfile,
+      			     SOURCE_GROUP,
+      			     SOURCE_KEY_HOSTNAME,
+      			     gdict_client_context_get_hostname (GDICT_CLIENT_CONTEXT (priv->context)));
+      g_key_file_set_integer (priv->keyfile,
+      			      SOURCE_GROUP,
+      			      SOURCE_KEY_PORT,
+      			      gdict_client_context_get_port (GDICT_CLIENT_CONTEXT (priv->context)));
+      break;
+    case GDICT_SOURCE_TRANSPORT_INVALID:
+    default:
+      g_assert_not_reached ();
+      break;
+    }
+}
+
+/**
+ * gdict_source_set_transport:
+ * @source: a #GdictSource
+ * @transport: a valid transport
+ * @first_transport_property: property for the context bound to
+ *   the transport, or %NULL
+ * @Varargs: property value for first property name, then additionary
+ *   properties, ending with %NULL
+ *
+ * Sets @transport as the choosen transport for @source.  The @transport
+ * argument is a method of retrieving dictionary data from a source; it is
+ * used to create the right #GdictContext for this #GdictSource.  After
+ * @transport, property name/value pairs should be listed, with a %NULL
+ * pointer ending the list.  Properties are the same passed to a #GdictContext
+ * implementation instance using g_object_set().
+ *
+ * Here's a simple example:
+ *
+ * <informalexample><programlisting>
+ * #include &lt;gdict/gdict.h&gt;
+ *  GdictSource *source = gdict_source_new ();
+ *
+ *  gdict_source_set_name (source, "My Source");
+ *  gdict_source_set_transport (source, GDICT_SOURCE_TRANSPORT_DICTD,
+ *                              "hostname", "dictionary-server.org",
+ *                              "port", 2628,
+ *                              NULL);
+ * </programlisting></informalexample>
+ *
+ * Since: 1.0
+ */
+void
+gdict_source_set_transport (GdictSource          *source,
+			    GdictSourceTransport  transport,
+			    const gchar          *first_transport_property,
+			    ...)
+{
+  va_list args;
+
+  g_return_if_fail (GDICT_IS_SOURCE (source));
+  g_return_if_fail (IS_VALID_TRANSPORT (transport));
+
+  va_start (args, first_transport_property);
+
+  gdict_source_set_transportv (source, transport,
+                               first_transport_property,
+                               args);
+
+  va_end (args);
+}
+
+/**
+ * gdict_source_get_transport:
+ * @source: a #GdictSource
+ *
+ * FIXME
+ *
+ * Return value: FIXME
+ *
+ * Since: 1.0
+ */
+GdictSourceTransport
+gdict_source_get_transport (GdictSource *source)
+{
+  g_return_val_if_fail (GDICT_IS_SOURCE (source), GDICT_SOURCE_TRANSPORT_INVALID);
+
+  return source->priv->transport;
+}
+
+/**
+ * gdict_source_get_context:
+ * @source: a #GdictSource
+ *
+ * Gets the #GdictContext bound to @source.
+ *
+ * Return value: a #GdictContext for @source.  Use g_object_unref()
+ *   when you don't need it anymore.
+ *
+ * Since: 1.0
+ */
+GdictContext *
+gdict_source_get_context (GdictSource *source)
+{
+  GdictContext *retval;
+
+  g_return_val_if_fail (GDICT_IS_SOURCE (source), NULL);
+
+  retval = gdict_source_create_context (source,
+		  			source->priv->transport,
+					NULL);
+
+  return retval;
+}
+
+/**
+ * gdict_source_peek_context:
+ * @source: a #GdictSource
+ *
+ * Gets the #GdictContext bound to @source.  The returned object is a
+ * referenced copy of the context held by @source; if you want a different
+ * instance, use gdict_source_get_context().
+ *
+ * Return value: a referenced #GdictContext.  Use g_object_unref() when
+ *   finished using it.
+ *
+ * Since: 1.0
+ */
+GdictContext *
+gdict_source_peek_context (GdictSource *source)
+{
+  g_return_val_if_fail (GDICT_IS_SOURCE (source), NULL);
+
+  if (!source->priv->context)
+    source->priv->context = gdict_source_create_context (source,
+    							 source->priv->transport,
+    							 NULL);
+  return g_object_ref (source->priv->context);
+}
+
+ +
+ +
+ + diff --git a/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/31.html b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/31.html new file mode 100644 index 00000000..7975729f --- /dev/null +++ b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/31.html @@ -0,0 +1,1877 @@ + + + + + + Cppcheck - HTML report - mate-utils + + + + + +
+ + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
+479
+480
+481
+482
+483
+484
+485
+486
+487
+488
+489
+490
+491
+492
+493
+494
+495
+496
+497
+498
+499
+500
+501
+502
+503
+504
+505
+506
+507
+508
+509
+510
+511
+512
+513
+514
+515
+516
+517
+518
+519
+520
+521
+522
+523
+524
+525
+526
+527
+528
+529
+530
+531
+532
+533
+534
+535
+536
+537
+538
+539
+540
+541
+542
+543
+544
+545
+546
+547
+548
+549
+550
+551
+552
+553
+554
+555
+556
+557
+558
+559
+560
+561
+562
+563
+564
+565
+566
+567
+568
+569
+570
+571
+572
+573
+574
+575
+576
+577
+578
+579
+580
+581
+582
+583
+584
+585
+586
+587
+588
+589
+590
+591
+592
+593
+594
+595
+596
+597
+598
+599
+600
+601
+602
+603
+604
+605
+606
+607
+608
+609
+610
+611
+612
+613
+614
+615
+616
+617
+618
+619
+620
+621
+622
+623
+624
+625
+626
+627
+628
+629
+630
+631
+632
+633
+634
+635
+636
+637
+638
+639
+640
+641
+642
+643
+644
+645
+646
+647
+648
+649
+650
+651
+652
+653
+654
+655
+656
+657
+658
+659
+660
+661
+662
+663
+664
+665
+666
+667
+668
+669
+670
+671
+672
+673
+674
+675
+676
+677
+678
+679
+680
+681
+682
+683
+684
+685
+686
+687
+688
+689
+690
+691
+692
+693
+694
+695
+696
+697
+698
+699
+700
+701
+702
+703
+704
+705
+706
+707
+708
+709
+710
+711
+712
+713
+714
+715
+716
+717
+718
+719
+720
+721
+722
+723
+724
+725
+726
+727
+728
+729
+730
+731
+732
+733
+734
+735
+736
+737
+738
+739
+740
+741
+742
+743
+744
+745
+746
+747
+748
+749
+750
+751
+752
+753
+754
+755
+756
+757
+758
+759
+760
+761
+762
+763
+764
+765
+766
+767
+768
+769
+770
+771
+772
+773
+774
+775
+776
+777
+778
+779
+780
+781
+782
+783
+784
+785
+786
+787
+788
+789
+790
+791
+792
+793
+794
+795
+796
+797
+798
+799
+800
+801
+802
+803
+804
+805
+806
+807
+808
+809
+810
+811
+812
+813
+814
+815
+816
+817
+818
+819
+820
/* Copyright (C) 2006 Emmanuele Bassi <ebassi@gmail.com>
+ * Copyright (C) 2012-2021 MATE Developers
+ *
+ * This file is part of MATE Utils.
+ *
+ * MATE Utils is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * MATE Utils is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MATE Utils.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+/**
+ * SECTION:gdict-speller
+ * @short_description: Display matching words
+ *
+ * #GdictSpeller is a widget showing a list of words returned by a
+ * #GdictContext query, using a specific database and a matching strategy.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+
+#include <gdk/gdkkeysyms.h>
+#include <gtk/gtk.h>
+#include <glib/gi18n-lib.h>
+
+#include "gdict-speller.h"
+#include "gdict-utils.h"
+#include "gdict-enum-types.h"
+#include "gdict-marshal.h"
+#include "gdict-debug.h"
+#include "gdict-private.h"
+
+struct _GdictSpellerPrivate
+{
+  GdictContext *context;
+  gchar *database;
+  gchar *strategy;
+
+  gchar *word;
+
+  GtkWidget *treeview;
+  GtkWidget *clear_button;
+
+  GdkCursor *busy_cursor;
+
+  GtkListStore *store;
+  gint results;
+
+  guint start_id;
+  guint end_id;
+  guint match_id;
+  guint error_id;
+
+  guint is_searching : 1;
+};
+
+typedef enum
+{
+  MATCH_DB,
+  MATCH_WORD,
+  MATCH_ERROR
+} MatchType;
+
+enum
+{
+  MATCH_COLUMN_TYPE,
+  MATCH_COLUMN_DB_NAME,
+  MATCH_COLUMN_WORD,
+
+  MATCH_N_COLUMNS
+};
+
+enum
+{
+  PROP_0,
+
+  PROP_CONTEXT,
+  PROP_WORD,
+  PROP_DATABASE,
+  PROP_STRATEGY,
+  PROP_COUNT
+};
+
+enum
+{
+  WORD_ACTIVATED,
+
+  LAST_SIGNAL
+};
+
+static guint speller_signals[LAST_SIGNAL] = { 0 };
+
+G_DEFINE_TYPE_WITH_PRIVATE (GdictSpeller, gdict_speller, GTK_TYPE_BOX)<--- There is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
+
+static void
+set_gdict_context (GdictSpeller *speller,
+		   GdictContext *context)
+{
+  GdictSpellerPrivate *priv;
+
+  g_assert (GDICT_IS_SPELLER (speller));
+
+  priv = speller->priv;
+  if (priv->context)
+    {
+      if (priv->start_id)
+        {
+          GDICT_NOTE (SPELLER, "Removing old context handlers");
+
+          g_signal_handler_disconnect (priv->context, priv->start_id);
+          g_signal_handler_disconnect (priv->context, priv->match_id);
+          g_signal_handler_disconnect (priv->context, priv->end_id);
+
+          priv->start_id = 0;
+          priv->end_id = 0;
+          priv->match_id = 0;
+        }
+
+      if (priv->error_id)
+        {
+          g_signal_handler_disconnect (priv->context, priv->error_id);
+
+          priv->error_id = 0;
+        }
+
+      GDICT_NOTE (SPELLER, "Removing old context");
+
+      g_object_unref (G_OBJECT (priv->context));
+    }
+
+  if (!context)
+    return;
+
+  if (!GDICT_IS_CONTEXT (context))
+    {
+      g_warning ("Object of type `%s' instead of a GdictContext\n",
+      		 g_type_name (G_OBJECT_TYPE (context)));
+      return;
+    }
+
+  GDICT_NOTE (SPELLER, "Setting new context\n");
+
+  priv->context = context;
+  g_object_ref (G_OBJECT (priv->context));
+}
+
+static void
+gdict_speller_finalize (GObject *gobject)
+{
+  GdictSpeller *speller = GDICT_SPELLER (gobject);
+  GdictSpellerPrivate *priv = speller->priv;
+
+  if (priv->context)
+    set_gdict_context (speller, NULL);
+
+  if (priv->busy_cursor)
+    g_object_unref (priv->busy_cursor);
+
+  g_free (priv->strategy);
+  g_free (priv->database);
+  g_free (priv->word);
+
+  if (priv->store)
+    g_object_unref (priv->store);
+
+  G_OBJECT_CLASS (gdict_speller_parent_class)->finalize (gobject);
+}
+
+static void
+gdict_speller_set_property (GObject      *gobject,
+			    guint         prop_id,
+			    const GValue *value,
+			    GParamSpec   *pspec)
+{
+  GdictSpeller *speller = GDICT_SPELLER (gobject);
+  GdictSpellerPrivate *priv = speller->priv;
+
+  switch (prop_id)
+    {
+    case PROP_CONTEXT:
+      set_gdict_context (speller, g_value_get_object (value));
+      break;
+    case PROP_DATABASE:
+      g_free (priv->database);
+      priv->database = g_strdup (g_value_get_string (value));
+      break;
+    case PROP_STRATEGY:
+      g_free (priv->strategy);
+      priv->strategy = g_strdup (g_value_get_string (value));
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+gdict_speller_get_property (GObject    *gobject,
+			    guint       prop_id,
+			    GValue     *value,
+			    GParamSpec *pspec)
+{
+  GdictSpeller *speller = GDICT_SPELLER (gobject);
+
+  switch (prop_id)
+    {
+    case PROP_DATABASE:
+      g_value_set_string (value, speller->priv->database);
+      break;
+    case PROP_STRATEGY:
+      g_value_set_string (value, speller->priv->strategy);
+      break;
+    case PROP_CONTEXT:
+      g_value_set_object (value, speller->priv->context);
+      break;
+    case PROP_COUNT:
+      g_value_set_int (value, speller->priv->results);
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+row_activated_cb (GtkTreeView       *treeview,
+		  GtkTreePath       *path,
+		  GtkTreeViewColumn *column,
+		  gpointer           user_data)
+{
+  GdictSpeller *speller = GDICT_SPELLER (user_data);
+  GdictSpellerPrivate *priv = speller->priv;
+  GtkTreeIter iter;
+  gchar *word, *db_name;
+  gboolean valid;
+
+  valid = gtk_tree_model_get_iter (GTK_TREE_MODEL (priv->store),
+			           &iter,
+				   path);
+  if (!valid)
+    {
+      g_warning ("Invalid iterator found");
+
+      return;
+    }
+
+  gtk_tree_model_get (GTK_TREE_MODEL (priv->store), &iter,
+		      MATCH_COLUMN_WORD, &word,
+		      MATCH_COLUMN_DB_NAME, &db_name,
+		      -1);
+  if (word)
+    g_signal_emit (speller, speller_signals[WORD_ACTIVATED], 0,
+		   word, db_name);
+  else
+    {
+      gchar *row = gtk_tree_path_to_string (path);
+
+      g_warning ("Row %s activated, but no word attached", row);
+      g_free (row);
+    }
+
+  g_free (word);
+  g_free (db_name);
+}
+
+static void
+clear_button_clicked_cb (GtkWidget *widget,
+			 gpointer   user_data)
+{
+  GdictSpeller *speller = GDICT_SPELLER (user_data);
+
+  gdict_speller_clear (speller);
+}
+
+static GObject *
+gdict_speller_constructor (GType                  type,
+			   guint                  n_params,
+			   GObjectConstructParam *params)
+{
+  GObject *object;
+  GdictSpeller *speller;
+  GdictSpellerPrivate *priv;
+  GtkWidget *sw;
+  GtkCellRenderer *renderer;
+  GtkTreeViewColumn *column;
+  GtkWidget *hbox;
+
+  object = G_OBJECT_CLASS (gdict_speller_parent_class)->constructor (type,
+  						                     n_params,
+								     params);
+  speller = GDICT_SPELLER (object);
+  priv = speller->priv;
+
+  sw = gtk_scrolled_window_new (NULL, NULL);
+  gtk_widget_set_vexpand (sw, TRUE);
+  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
+  				  GTK_POLICY_AUTOMATIC,
+  				  GTK_POLICY_AUTOMATIC);
+  gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw),
+  				       GTK_SHADOW_IN);
+  gtk_box_pack_start (GTK_BOX (speller), sw, TRUE, TRUE, 0);
+  gtk_widget_show (sw);
+
+  renderer = gtk_cell_renderer_text_new ();
+  column = gtk_tree_view_column_new_with_attributes ("matches",
+		  				     renderer,
+						     "text", MATCH_COLUMN_WORD,
+						     NULL);
+
+  priv->treeview = gtk_tree_view_new ();
+  gtk_tree_view_set_model (GTK_TREE_VIEW (priv->treeview),
+		           GTK_TREE_MODEL (priv->store));
+  gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (priv->treeview), FALSE);
+  gtk_tree_view_append_column (GTK_TREE_VIEW (priv->treeview), column);
+  g_signal_connect (priv->treeview, "row-activated",
+		    G_CALLBACK (row_activated_cb), speller);
+  gtk_container_add (GTK_CONTAINER (sw), priv->treeview);
+  gtk_widget_show (priv->treeview);
+
+  hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+
+  priv->clear_button = gtk_button_new ();
+  gtk_button_set_image (GTK_BUTTON (priv->clear_button),
+                        gtk_image_new_from_icon_name ("edit-clear",
+                                                      GTK_ICON_SIZE_SMALL_TOOLBAR));
+  g_signal_connect (priv->clear_button, "clicked",
+		    G_CALLBACK (clear_button_clicked_cb),
+		    speller);
+  gtk_box_pack_start (GTK_BOX (hbox), priv->clear_button, FALSE, FALSE, 0);
+  gtk_widget_show (priv->clear_button);
+  gtk_widget_set_tooltip_text (priv->clear_button,
+                               _("Clear the list of similar words"));
+
+  gtk_box_pack_end (GTK_BOX (speller), hbox, FALSE, FALSE, 0);
+  gtk_widget_show (hbox);
+
+  return object;
+}
+
+static void
+gdict_speller_class_init (GdictSpellerClass *klass)
+{
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+  gobject_class->finalize = gdict_speller_finalize;
+  gobject_class->set_property = gdict_speller_set_property;
+  gobject_class->get_property = gdict_speller_get_property;
+  gobject_class->constructor = gdict_speller_constructor;
+
+  g_object_class_install_property (gobject_class,
+  				   PROP_CONTEXT,
+  				   g_param_spec_object ("context",
+  				   			_("Context"),
+  				   			_("The GdictContext object used to get the word definition"),
+  				   			GDICT_TYPE_CONTEXT,
+  				   			(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT)));
+  g_object_class_install_property (gobject_class,
+		  		   PROP_DATABASE,
+				   g_param_spec_string ("database",
+					   		_("Database"),
+							_("The database used to query the GdictContext"),
+							GDICT_DEFAULT_DATABASE,
+							(G_PARAM_READABLE | G_PARAM_WRITABLE)));
+  g_object_class_install_property (gobject_class,
+		  		   PROP_DATABASE,
+				   g_param_spec_string ("strategy",
+					   		_("Strategy"),
+							_("The strategy used to query the GdictContext"),
+							GDICT_DEFAULT_STRATEGY,
+							(G_PARAM_READABLE | G_PARAM_WRITABLE)));
+
+  speller_signals[WORD_ACTIVATED] =
+    g_signal_new ("word-activated",
+		  G_OBJECT_CLASS_TYPE (gobject_class),
+		  G_SIGNAL_RUN_LAST,
+		  G_STRUCT_OFFSET (GdictSpellerClass, word_activated),
+		  NULL, NULL,
+		  gdict_marshal_VOID__STRING_STRING,
+		  G_TYPE_NONE, 2,
+		  G_TYPE_STRING,
+		  G_TYPE_STRING);
+}
+
+static void
+gdict_speller_init (GdictSpeller *speller)
+{
+  GdictSpellerPrivate *priv;
+
+  speller->priv = priv = gdict_speller_get_instance_private (speller);
+
+  gtk_orientable_set_orientation (GTK_ORIENTABLE (speller), GTK_ORIENTATION_VERTICAL);
+
+  priv->database = NULL;
+  priv->strategy = NULL;
+  priv->word = NULL;
+
+  priv->results = -1;
+  priv->context = NULL;
+
+  priv->store = gtk_list_store_new (MATCH_N_COLUMNS,
+		                    G_TYPE_INT,    /* MatchType */
+		                    G_TYPE_STRING, /* db_name */
+				    G_TYPE_STRING  /* word */);
+
+  priv->start_id = 0;
+  priv->end_id = 0;
+  priv->match_id = 0;
+  priv->error_id = 0;
+}
+
+/**
+ * gdict_speller_new:
+ *
+ * FIXME
+ *
+ * Return value: FIXME
+ *
+ * Since:
+ */
+GtkWidget *
+gdict_speller_new (void)
+{
+  return g_object_new (GDICT_TYPE_SPELLER, NULL);
+}
+
+/**
+ * gdict_speller_new_with_context:
+ * @context: a #GdictContext
+ *
+ * FIXME
+ *
+ * Return value: FIXME
+ *
+ * Since:
+ */
+GtkWidget *
+gdict_speller_new_with_context (GdictContext *context)
+{
+  g_return_val_if_fail (GDICT_IS_CONTEXT (context), NULL);
+
+  return g_object_new (GDICT_TYPE_SPELLER,
+                       "context", context,
+                       NULL);
+}
+
+/**
+ * gdict_speller_set_context:
+ * @speller: a #GdictSpeller
+ * @context: a #GdictContext
+ *
+ * FIXME
+ *
+ * Since:
+ */
+void
+gdict_speller_set_context (GdictSpeller *speller,
+			   GdictContext *context)
+{
+  g_return_if_fail (GDICT_IS_SPELLER (speller));
+  g_return_if_fail (context == NULL || GDICT_IS_CONTEXT (context));
+
+  set_gdict_context (speller, context);
+
+  g_object_notify (G_OBJECT (speller), "context");
+}
+
+/**
+ * gdict_speller_get_context:
+ * @speller: a #GdictSpeller
+ *
+ * FIXME
+ *
+ * Return value: a #GdictContext
+ *
+ * Since:
+ */
+GdictContext *
+gdict_speller_get_context (GdictSpeller *speller)
+{
+  g_return_val_if_fail (GDICT_IS_SPELLER (speller), NULL);
+
+  return speller->priv->context;
+}
+
+/**
+ * gdict_speller_set_database:
+ * @speller: a #GdictSpeller
+ * @database: FIXME
+ *
+ * FIXME
+ *
+ * Since:
+ */
+void
+gdict_speller_set_database (GdictSpeller *speller,
+			    const gchar  *database)
+{
+  GdictSpellerPrivate *priv;
+
+  g_return_if_fail (GDICT_IS_SPELLER (speller));
+
+  priv = speller->priv;
+
+  if (!database || database[0] == '\0')
+    database = GDICT_DEFAULT_DATABASE;
+
+  g_free (priv->database);
+  priv->database = g_strdup (database);
+
+  g_object_notify (G_OBJECT (speller), "database");
+}
+
+/**
+ * gdict_speller_get_database:
+ * @speller: a #GdictSpeller
+ *
+ * FIXME
+ *
+ * Return value: FIXME
+ *
+ * Since: FIXME
+ */
+const gchar *
+gdict_speller_get_database (GdictSpeller *speller)
+{
+  g_return_val_if_fail (GDICT_IS_SPELLER (speller), NULL);
+
+  return speller->priv->database;
+}
+
+/**
+ * gdict_speller_set_strategy:
+ * @speller: a #GdictSpeller
+ * @strategy: FIXME
+ *
+ * FIXME
+ *
+ * Since: FIXME
+ */
+void
+gdict_speller_set_strategy (GdictSpeller *speller,
+			    const gchar  *strategy)
+{
+  GdictSpellerPrivate *priv;
+
+  g_return_if_fail (GDICT_IS_SPELLER (speller));
+
+  priv = speller->priv;
+
+  if (!strategy || strategy[0] == '\0')
+    strategy = GDICT_DEFAULT_STRATEGY;
+
+  g_free (priv->strategy);
+  priv->strategy = g_strdup (strategy);
+
+  g_object_notify (G_OBJECT (speller), "strategy");
+}
+
+/**
+ * gdict_speller_get_strategy:
+ * @speller: a #GdictSpeller
+ *
+ * FIXME
+ *
+ * Return value: FIXME
+ *
+ * Since: FIXME
+ */
+const gchar *
+gdict_speller_get_strategy (GdictSpeller *speller)
+{
+  g_return_val_if_fail (GDICT_IS_SPELLER (speller), NULL);
+
+  return speller->priv->strategy;
+}
+
+/**
+ * gdict_speller_clear:
+ * @speller: a #GdictSpeller
+ *
+ * FIXME
+ *
+ * Since: FIXME
+ */
+void
+gdict_speller_clear (GdictSpeller *speller)
+{
+  GdictSpellerPrivate *priv;
+
+  g_return_if_fail (GDICT_IS_SPELLER (speller));
+  priv = speller->priv;
+
+  gtk_tree_view_set_model (GTK_TREE_VIEW (priv->treeview), NULL);
+
+  gtk_list_store_clear (priv->store);
+  priv->results = -1;
+
+  gtk_tree_view_set_model (GTK_TREE_VIEW (priv->treeview),
+		           GTK_TREE_MODEL (priv->store));
+}
+
+static void
+lookup_start_cb (GdictContext *context,
+		 gpointer      user_data)
+{
+  GdictSpeller *speller = GDICT_SPELLER (user_data);
+  GdictSpellerPrivate *priv = speller->priv;
+
+  if (!priv->busy_cursor)
+    {
+      GdkDisplay *display = gtk_widget_get_display (GTK_WIDGET (speller));
+      priv->busy_cursor = gdk_cursor_new_for_display (display, GDK_WATCH);
+    }
+
+  if (gtk_widget_get_window (GTK_WIDGET (speller)))
+    gdk_window_set_cursor (gtk_widget_get_window (GTK_WIDGET (speller)), priv->busy_cursor);
+
+  priv->is_searching = TRUE;
+}
+
+static void
+lookup_end_cb (GdictContext *context,
+	       gpointer      user_data)
+{
+  GdictSpeller *speller = GDICT_SPELLER (user_data);
+  GdictSpellerPrivate *priv = speller->priv;
+
+  if (gtk_widget_get_window (GTK_WIDGET (speller)))
+    gdk_window_set_cursor (gtk_widget_get_window (GTK_WIDGET (speller)), NULL);
+
+  g_free (priv->word);
+  priv->word = NULL;
+
+  priv->is_searching = FALSE;
+}
+
+static void
+match_found_cb (GdictContext *context,
+		GdictMatch   *match,
+		gpointer      user_data)
+{
+  GdictSpeller *speller = GDICT_SPELLER (user_data);
+  GdictSpellerPrivate *priv = speller->priv;
+  GtkTreeIter iter;
+
+  GDICT_NOTE (SPELLER, "MATCH: `%s' (from `%s')",
+              gdict_match_get_word (match),
+              gdict_match_get_database (match));
+
+  gtk_list_store_append (priv->store, &iter);
+  gtk_list_store_set (priv->store, &iter,
+		      MATCH_COLUMN_TYPE, MATCH_WORD,
+		      MATCH_COLUMN_DB_NAME, gdict_match_get_database (match),
+		      MATCH_COLUMN_WORD, gdict_match_get_word (match),
+		      -1);
+
+  if (priv->results == -1)
+    priv->results = 1;
+  else
+    priv->results += 1;
+}
+
+static void
+error_cb (GdictContext *context,
+	  const GError *error,
+	  gpointer      user_data)
+{
+  GdictSpeller *speller = GDICT_SPELLER (user_data);
+  GdictSpellerPrivate *priv = speller->priv;
+
+  gdict_speller_clear (speller);
+
+  if (gtk_widget_get_window (GTK_WIDGET (speller)))
+    gdk_window_set_cursor (gtk_widget_get_window (GTK_WIDGET (speller)), NULL);
+
+  g_free (priv->word);
+  priv->word = NULL;
+
+  priv->is_searching = FALSE;
+}
+
+/**
+ * gdict_speller_match:
+ * @speller: a #GdictSpeller
+ * @word: FIXME
+ *
+ * FIXME
+ *
+ * Since: FIXME
+ */
+void
+gdict_speller_match (GdictSpeller *speller,
+		     const gchar  *word)
+{
+  GdictSpellerPrivate *priv;
+  GError *match_error;
+
+  g_return_if_fail (GDICT_IS_SPELLER (speller));
+  g_return_if_fail (word != NULL);
+
+  priv = speller->priv;
+
+  if (!priv->context)
+    {
+      g_warning ("Attempting to match `%s', but no GdictContext "
+		 "has been set.  Use gdict_speller_set_context() "
+		 "before invoking gdict_speller_match().",
+		 word);
+
+      return;
+    }
+
+  if (priv->is_searching)
+    {
+      _gdict_show_error_dialog (NULL,
+                                _("Another search is in progress"),
+                                _("Please wait until the current search ends."));
+
+      return;
+    }
+
+  gdict_speller_clear (speller);
+
+  if (!priv->start_id)
+    {
+      priv->start_id = g_signal_connect (priv->context, "lookup-start",
+		                         G_CALLBACK (lookup_start_cb),
+					 speller);
+      priv->match_id = g_signal_connect (priv->context, "match-found",
+                                         G_CALLBACK (match_found_cb),
+					 speller);
+      priv->end_id = g_signal_connect (priv->context, "lookup-end",
+		      		       G_CALLBACK (lookup_end_cb),
+				       speller);
+    }
+
+  if (!priv->error_id)
+    priv->error_id = g_signal_connect (priv->context, "error",
+		    		       G_CALLBACK (error_cb),
+				       speller);
+
+  g_free (priv->word);
+  priv->word = g_strdup (word);
+
+  match_error = NULL;
+  gdict_context_match_word (priv->context,
+		  	    priv->database,
+			    priv->strategy,
+			    priv->word,
+			    &match_error);
+  if (match_error)
+    {
+      GtkTreeIter iter;
+
+      gtk_list_store_append (priv->store, &iter);
+      gtk_list_store_set (priv->store, &iter,
+		          MATCH_COLUMN_TYPE, MATCH_ERROR,
+			  MATCH_COLUMN_DB_NAME, _("Error while matching"),
+			  MATCH_COLUMN_WORD, NULL,
+			  -1);
+
+      g_warning ("Error while matching `%s': %s",
+                 priv->word,
+                 match_error->message);
+
+      g_error_free (match_error);
+    }
+}
+
+/**
+ * gdict_speller_count_match:
+ * @speller: a #GdictSpeller
+ *
+ * FIXME
+ *
+ * Return value: FIXME
+ *
+ * Since: FIXME
+ */
+gint
+gdict_speller_count_matches (GdictSpeller *speller)
+{
+  g_return_val_if_fail (GDICT_IS_SPELLER (speller), -1);
+
+  return speller->priv->results;
+}
+
+/**
+ * gdict_speller_get_matches:
+ * @speller: a #GdictSpeller
+ * @length: FIXME
+ *
+ * FIXME
+ *
+ * Return value: FIXME
+ *
+ * Since: FIXME
+ */
+gchar **
+gdict_speller_get_matches (GdictSpeller *speller,
+			   gsize         length)
+{
+  g_return_val_if_fail (GDICT_IS_SPELLER (speller), NULL);
+
+  return NULL;
+}
+
+ +
+ +
+ + diff --git a/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/32.html b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/32.html new file mode 100644 index 00000000..9beb54ac --- /dev/null +++ b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/32.html @@ -0,0 +1,609 @@ + + + + + + Cppcheck - HTML report - mate-utils + + + + + +
+ + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
/* Copyright (C) 2005 Emmanuele Bassi
+ * Copyright (C) 2012-2021 MATE Developers
+ *
+ * This file is part of MATE Utils.
+ *
+ * MATE Utils is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * MATE Utils is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MATE Utils.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <sys/types.h>
+#include <errno.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib/gstdio.h>
+
+#include <gtk/gtk.h>
+
+#include "gdict-common.h"
+
+gchar *
+gdict_get_data_dir (void)
+{
+  gchar *retval;
+
+  retval = g_build_filename (g_get_user_config_dir (),
+		  	     "mate",
+			     "mate-dictionary",
+			     NULL);
+
+  return retval;
+}
+
+/* create the data directory inside $HOME, if it doesn't exist yet */
+gboolean
+gdict_create_data_dir (void)
+{
+  gchar *data_dir_name;
+
+  data_dir_name = gdict_get_data_dir ();
+  if (g_mkdir_with_parents (data_dir_name, 0700) == -1)
+    {
+      /* this is weird, but sometimes there's a "mate-dictionary" file
+       * inside $HOME/.mate2; see bug #329126.
+       */
+      if ((errno == EEXIST) &&
+          (g_file_test (data_dir_name, G_FILE_TEST_IS_REGULAR)))
+        {
+          gchar *backup = g_strdup_printf ("%s.pre-2-14", data_dir_name);
+
+	  if (g_rename (data_dir_name, backup) == -1)
+	    {
+              GtkWidget *error_dialog;
+
+	      error_dialog = gtk_message_dialog_new (NULL,
+                                                     GTK_DIALOG_MODAL,
+						     GTK_MESSAGE_ERROR,
+						     GTK_BUTTONS_CLOSE,
+						     _("Unable to rename file '%s' to '%s': %s"),
+						     data_dir_name,
+						     backup,
+						     g_strerror (errno));
+
+	      gtk_dialog_run (GTK_DIALOG (error_dialog));
+
+	      gtk_widget_destroy (error_dialog);
+	      g_free (backup);
+	      g_free (data_dir_name);
+
+	      return FALSE;
+            }
+
+	  g_free (backup);
+
+          if (g_mkdir_with_parents (data_dir_name, 0700) == -1)
+            {
+              GtkWidget *error_dialog;
+
+	      error_dialog = gtk_message_dialog_new (NULL,
+						     GTK_DIALOG_MODAL,
+						     GTK_MESSAGE_ERROR,
+						     GTK_BUTTONS_CLOSE,
+						     _("Unable to create the data directory '%s': %s"),
+						     data_dir_name,
+						     g_strerror (errno));
+
+	      gtk_dialog_run (GTK_DIALOG (error_dialog));
+
+	      gtk_widget_destroy (error_dialog);
+              g_free (data_dir_name);
+
+	      return FALSE;
+            }
+
+	  goto success;
+	}
+
+      if (errno != EEXIST)
+        {
+          GtkWidget *error_dialog;
+
+	  error_dialog = gtk_message_dialog_new (NULL,
+						 GTK_DIALOG_MODAL,
+						 GTK_MESSAGE_ERROR,
+						 GTK_BUTTONS_CLOSE,
+						 _("Unable to create the data directory '%s': %s"),
+						 data_dir_name,
+						 g_strerror (errno));
+
+	  gtk_dialog_run (GTK_DIALOG (error_dialog));
+
+	  gtk_widget_destroy (error_dialog);
+	  g_free (data_dir_name);
+
+	  return FALSE;
+	}
+    }
+
+success:
+  g_free (data_dir_name);
+
+  return TRUE;
+}
+
+/* shows an error dialog making it transient for @parent */
+void
+gdict_show_error_dialog (GtkWindow   *parent,
+			 const gchar *message,
+			 const gchar *detail)
+{
+  GtkWidget *dialog;
+
+  g_return_if_fail ((parent == NULL) || (GTK_IS_WINDOW (parent)));
+  g_return_if_fail (message != NULL);
+
+  dialog = gtk_message_dialog_new (parent,
+  				   GTK_DIALOG_DESTROY_WITH_PARENT,
+  				   GTK_MESSAGE_ERROR,
+  				   GTK_BUTTONS_OK,
+  				   "%s", message);
+  gtk_window_set_title (GTK_WINDOW (dialog), "");
+
+  if (detail)
+    gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+  					      "%s", detail);
+
+  if (parent && gtk_window_get_group (parent))
+    gtk_window_group_add_window (gtk_window_get_group (parent), GTK_WINDOW (dialog));
+
+  gtk_dialog_run (GTK_DIALOG (dialog));
+
+  gtk_widget_destroy (dialog);
+}
+
+void
+gdict_show_gerror_dialog (GtkWindow   *parent,
+			  const gchar *message,
+			  GError      *error)
+{
+  g_return_if_fail ((parent == NULL) || (GTK_IS_WINDOW (parent)));
+  g_return_if_fail (message != NULL);
+  g_return_if_fail (error != NULL);
+
+  gdict_show_error_dialog (parent, message, error->message);
+
+  g_error_free (error);
+  error = NULL;<--- Assignment of function parameter has no effect outside the function. Did you forget dereferencing it?
+}
+
+ +
+ +
+ + diff --git a/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/33.html b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/33.html new file mode 100644 index 00000000..984f7aeb --- /dev/null +++ b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/33.html @@ -0,0 +1,1815 @@ + + + + + + Cppcheck - HTML report - mate-utils + + + + + +
+ + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
+479
+480
+481
+482
+483
+484
+485
+486
+487
+488
+489
+490
+491
+492
+493
+494
+495
+496
+497
+498
+499
+500
+501
+502
+503
+504
+505
+506
+507
+508
+509
+510
+511
+512
+513
+514
+515
+516
+517
+518
+519
+520
+521
+522
+523
+524
+525
+526
+527
+528
+529
+530
+531
+532
+533
+534
+535
+536
+537
+538
+539
+540
+541
+542
+543
+544
+545
+546
+547
+548
+549
+550
+551
+552
+553
+554
+555
+556
+557
+558
+559
+560
+561
+562
+563
+564
+565
+566
+567
+568
+569
+570
+571
+572
+573
+574
+575
+576
+577
+578
+579
+580
+581
+582
+583
+584
+585
+586
+587
+588
+589
+590
+591
+592
+593
+594
+595
+596
+597
+598
+599
+600
+601
+602
+603
+604
+605
+606
+607
+608
+609
+610
+611
+612
+613
+614
+615
+616
+617
+618
+619
+620
+621
+622
+623
+624
+625
+626
+627
+628
+629
+630
+631
+632
+633
+634
+635
+636
+637
+638
+639
+640
+641
+642
+643
+644
+645
+646
+647
+648
+649
+650
+651
+652
+653
+654
+655
+656
+657
+658
+659
+660
+661
+662
+663
+664
+665
+666
+667
+668
+669
+670
+671
+672
+673
+674
+675
+676
+677
+678
+679
+680
+681
+682
+683
+684
+685
+686
+687
+688
+689
+690
+691
+692
+693
+694
+695
+696
+697
+698
+699
+700
+701
+702
+703
+704
+705
+706
+707
+708
+709
+710
+711
+712
+713
+714
+715
+716
+717
+718
+719
+720
+721
+722
+723
+724
+725
+726
+727
+728
+729
+730
+731
+732
+733
+734
+735
+736
+737
+738
+739
+740
+741
+742
+743
+744
+745
+746
+747
+748
+749
+750
+751
+752
+753
+754
+755
+756
+757
+758
+759
+760
+761
+762
+763
+764
+765
+766
+767
+768
+769
+770
+771
+772
+773
+774
+775
+776
+777
+778
+779
+780
+781
+782
+783
+784
+785
+786
+787
+788
+789
/* Copyright (C) 2005 Emmanuele Bassi
+ * Copyright (C) 2012-2021 MATE Developers
+ *
+ * This file is part of MATE Utils.
+ *
+ * MATE Utils is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * MATE Utils is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MATE Utils.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <sys/types.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <glib/gi18n.h>
+#include <gio/gio.h>
+
+#include "gdict-source-dialog.h"
+#include "gdict-pref-dialog.h"
+#include "gdict-common.h"
+
+#define GDICT_PREFERENCES_UI 	PKGDATADIR "/mate-dictionary-preferences.ui"
+#define GET_WIDGET(x) (GTK_WIDGET (gtk_builder_get_object (dialog->builder, (x))))
+
+#define DEFAULT_MIN_WIDTH 	220
+#define DEFAULT_MIN_HEIGHT 	330
+
+/*******************
+ * GdictPrefDialog *
+ *******************/
+
+static GtkWidget *global_dialog = NULL;
+
+enum
+{
+  SOURCES_ACTIVE_COLUMN = 0,
+  SOURCES_NAME_COLUMN,
+  SOURCES_DESCRIPTION_COLUMN,
+
+  SOURCES_N_COLUMNS
+};
+
+struct _GdictPrefDialog
+{
+  GtkDialog parent_instance;
+
+  GtkBuilder *builder;
+
+  GSettings *settings;
+
+  gchar *active_source;
+  GdictSourceLoader *loader;
+  GtkListStore *sources_list;
+
+  /* direct pointers to widgets */
+  GtkWidget *notebook;
+
+  GtkWidget *sources_view;
+  GtkWidget *sources_add;
+  GtkWidget *sources_remove;
+  GtkWidget *sources_edit;
+
+  gchar *print_font;
+  GtkWidget *font_button;
+
+  GtkWidget *help_button;<--- struct member '_GdictPrefDialog::help_button' is never used.
+  GtkWidget *close_button;<--- struct member '_GdictPrefDialog::close_button' is never used.
+};
+
+struct _GdictPrefDialogClass
+{
+  GtkDialogClass parent_class;
+};
+
+enum
+{
+  PROP_0,
+
+  PROP_SOURCE_LOADER
+};
+
+G_DEFINE_TYPE (GdictPrefDialog, gdict_pref_dialog, GTK_TYPE_DIALOG);
+
+static gboolean
+select_active_source_name (GtkTreeModel *model,
+			   GtkTreePath  *path,
+			   GtkTreeIter  *iter,
+			   gpointer      data)
+{
+  GdictPrefDialog *dialog = GDICT_PREF_DIALOG (data);
+  gboolean is_active;
+
+  gtk_tree_model_get (model, iter,
+      		      SOURCES_ACTIVE_COLUMN, &is_active,
+      		      -1);
+  if (is_active)
+    {
+      GtkTreeSelection *selection;
+
+      selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->sources_view));
+
+      gtk_tree_selection_select_iter (selection, iter);
+
+      return TRUE;
+    }
+
+  return FALSE;
+}
+
+static void
+update_sources_view (GdictPrefDialog *dialog)
+{
+  const GSList *sources, *l;
+
+  gtk_tree_view_set_model (GTK_TREE_VIEW (dialog->sources_view), NULL);
+
+  gtk_list_store_clear (dialog->sources_list);
+
+  /* force update of the sources list */
+  gdict_source_loader_update (dialog->loader);
+
+  sources = gdict_source_loader_get_sources (dialog->loader);
+  for (l = sources; l != NULL; l = l->next)
+    {
+      GdictSource *source = GDICT_SOURCE (l->data);
+      GtkTreeIter iter;
+      const gchar *name, *description;
+      gboolean is_active = FALSE;
+
+      name = gdict_source_get_name (source);
+      description = gdict_source_get_description (source);
+      if (!description)
+	description = name;
+
+      if (strcmp (name, dialog->active_source) == 0)
+        is_active = TRUE;
+
+      gtk_list_store_append (dialog->sources_list, &iter);
+      gtk_list_store_set (dialog->sources_list, &iter,
+      			  SOURCES_ACTIVE_COLUMN, is_active,
+      			  SOURCES_NAME_COLUMN, name,
+      			  SOURCES_DESCRIPTION_COLUMN, description,
+      			  -1);
+    }
+
+  gtk_tree_view_set_model (GTK_TREE_VIEW (dialog->sources_view),
+  			   GTK_TREE_MODEL (dialog->sources_list));
+
+  /* select the currently active source name */
+  gtk_tree_model_foreach (GTK_TREE_MODEL (dialog->sources_list),
+  			  select_active_source_name,
+  			  dialog);
+}
+
+static void
+source_renderer_toggled_cb (GtkCellRendererToggle *renderer,
+			    const gchar           *path,
+			    GdictPrefDialog       *dialog)
+{
+  GtkTreePath *treepath;
+  GtkTreeIter iter;
+  gboolean res;
+  gboolean is_active;
+  gchar *name;
+
+  treepath = gtk_tree_path_new_from_string (path);
+  res = gtk_tree_model_get_iter (GTK_TREE_MODEL (dialog->sources_list),
+                                 &iter,
+                                 treepath);
+  if (!res)
+    {
+      gtk_tree_path_free (treepath);
+
+      return;
+    }
+
+  gtk_tree_model_get (GTK_TREE_MODEL (dialog->sources_list), &iter,
+      		      SOURCES_NAME_COLUMN, &name,
+      		      SOURCES_ACTIVE_COLUMN, &is_active,
+      		      -1);
+  if (!is_active && name != NULL)
+    {
+      g_free (dialog->active_source);
+      dialog->active_source = g_strdup (name);
+
+      g_settings_set_string (dialog->settings, GDICT_SETTINGS_SOURCE_KEY, dialog->active_source);
+      update_sources_view (dialog);
+
+      g_free (name);
+    }
+
+  gtk_tree_path_free (treepath);
+}
+
+static void
+sources_view_row_activated_cb (GtkTreeView       *tree_view,
+			       GtkTreePath       *tree_path,
+			       GtkTreeViewColumn *tree_iter,
+			       GdictPrefDialog   *dialog)
+{
+  GtkWidget *edit_dialog;
+  gchar *source_name;
+  GtkTreeModel *model;
+  GtkTreeIter iter;
+
+  model = gtk_tree_view_get_model (tree_view);
+  if (!model)
+    return;
+
+  if (!gtk_tree_model_get_iter (model, &iter, tree_path))
+    return;
+
+  gtk_tree_model_get (model, &iter, SOURCES_NAME_COLUMN, &source_name, -1);
+  if (!source_name)
+    return;
+
+  edit_dialog = gdict_source_dialog_new (GTK_WINDOW (dialog),
+  					 _("Edit Dictionary Source"),
+  					 GDICT_SOURCE_DIALOG_EDIT,
+  					 dialog->loader,
+  					 source_name);
+  gtk_dialog_run (GTK_DIALOG (edit_dialog));
+
+  gtk_widget_destroy (edit_dialog);
+  g_free (source_name);
+
+  update_sources_view (dialog);
+}
+
+static void
+build_sources_view (GdictPrefDialog *dialog)
+{
+  GtkTreeViewColumn *column;
+  GtkCellRenderer *renderer;
+
+  if (dialog->sources_list)
+    return;
+
+  dialog->sources_list = gtk_list_store_new (SOURCES_N_COLUMNS,
+  					     G_TYPE_BOOLEAN,  /* active */
+  					     G_TYPE_STRING,   /* name */
+  					     G_TYPE_STRING    /* description */);
+  gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (dialog->sources_list),
+  					SOURCES_DESCRIPTION_COLUMN,
+  					GTK_SORT_ASCENDING);
+
+  renderer = gtk_cell_renderer_toggle_new ();
+  gtk_cell_renderer_toggle_set_radio (GTK_CELL_RENDERER_TOGGLE (renderer), TRUE);
+  g_signal_connect (renderer, "toggled",
+  		    G_CALLBACK (source_renderer_toggled_cb),
+  		    dialog);
+
+  column = gtk_tree_view_column_new_with_attributes ("active",
+  						     renderer,
+  						     "active", SOURCES_ACTIVE_COLUMN,
+  						     NULL);
+  gtk_tree_view_append_column (GTK_TREE_VIEW (dialog->sources_view), column);
+
+  renderer = gtk_cell_renderer_text_new ();
+  column = gtk_tree_view_column_new_with_attributes ("description",
+  						     renderer,
+  						     "text", SOURCES_DESCRIPTION_COLUMN,
+  						     NULL);
+  gtk_tree_view_append_column (GTK_TREE_VIEW (dialog->sources_view), column);
+
+  gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (dialog->sources_view), FALSE);
+  gtk_tree_view_set_model (GTK_TREE_VIEW (dialog->sources_view),
+  			   GTK_TREE_MODEL (dialog->sources_list));
+
+  g_signal_connect (dialog->sources_view, "row-activated",
+		    G_CALLBACK (sources_view_row_activated_cb),
+		    dialog);
+}
+
+static void
+source_add_clicked_cb (GtkWidget       *widget,
+		       GdictPrefDialog *dialog)
+{
+  GtkWidget *add_dialog;
+
+  add_dialog = gdict_source_dialog_new (GTK_WINDOW (dialog),
+  					_("Add Dictionary Source"),
+  					GDICT_SOURCE_DIALOG_CREATE,
+  					dialog->loader,
+  					NULL);
+
+  gtk_dialog_run (GTK_DIALOG (add_dialog));
+
+  gtk_widget_destroy (add_dialog);
+
+  update_sources_view (dialog);
+}
+
+static void
+source_remove_clicked_cb (GtkWidget       *widget,
+			  GdictPrefDialog *dialog)
+{
+  GtkTreeSelection *selection;
+  GtkTreeModel *model;
+  GtkTreeIter iter;
+  gboolean is_selected;
+  gchar *name, *description;
+
+  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->sources_view));
+  if (!selection)
+    return;
+
+  is_selected = gtk_tree_selection_get_selected (selection, &model, &iter);
+  if (!is_selected)
+    return;
+
+  gtk_tree_model_get (model, &iter,
+  		      SOURCES_NAME_COLUMN, &name,
+  		      SOURCES_DESCRIPTION_COLUMN, &description,
+  		      -1);
+  if (!name)
+    return;
+  else
+    {
+      GtkWidget *confirm_dialog;
+      gint response;
+
+      confirm_dialog = gtk_message_dialog_new (GTK_WINDOW (dialog),
+      					       GTK_DIALOG_DESTROY_WITH_PARENT,
+      					       GTK_MESSAGE_WARNING,
+      					       GTK_BUTTONS_NONE,
+      					       _("Remove \"%s\"?"), description);
+      gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (confirm_dialog),
+      						_("This will permanently remove the "
+      						  "dictionary source from the list."));
+
+      gtk_dialog_add_button (GTK_DIALOG (confirm_dialog),
+      			     "gtk-cancel",
+      			     GTK_RESPONSE_CANCEL);
+      gtk_dialog_add_button (GTK_DIALOG (confirm_dialog),
+      			     "gtk-remove",
+      			     GTK_RESPONSE_OK);
+
+      gtk_window_set_title (GTK_WINDOW (confirm_dialog), "");
+
+      response = gtk_dialog_run (GTK_DIALOG (confirm_dialog));
+      if (response == GTK_RESPONSE_CANCEL)
+        {
+          gtk_widget_destroy (confirm_dialog);
+
+          goto out;
+        }
+
+      gtk_widget_destroy (confirm_dialog);
+    }
+
+  if (gdict_source_loader_remove_source (dialog->loader, name))
+    gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
+  else
+    {
+      GtkWidget *error_dialog;
+      gchar *message;
+
+      message = g_strdup_printf (_("Unable to remove source '%s'"),
+      				 description);
+
+      error_dialog = gtk_message_dialog_new (GTK_WINDOW (dialog),
+      					     GTK_DIALOG_DESTROY_WITH_PARENT,
+      					     GTK_MESSAGE_ERROR,
+      					     GTK_BUTTONS_OK,
+      					     "%s", message);
+      gtk_window_set_title (GTK_WINDOW (error_dialog), "");
+
+      gtk_dialog_run (GTK_DIALOG (error_dialog));
+
+      gtk_widget_destroy (error_dialog);
+    }
+
+out:
+  g_free (name);
+  g_free (description);
+
+  update_sources_view (dialog);
+}
+
+static void
+source_edit_clicked_cb (GtkButton       *button,
+                        GdictPrefDialog *dialog)
+{
+  GtkTreeSelection *selection;
+  GtkTreeModel *model;
+  GtkTreeIter iter;
+  gboolean is_selected;
+  gchar *name;
+
+  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->sources_view));
+  if (!selection)
+    return;
+
+  is_selected = gtk_tree_selection_get_selected (selection, &model, &iter);
+  if (!is_selected)
+    return;
+
+  gtk_tree_model_get (model, &iter, SOURCES_NAME_COLUMN, &name, -1);
+  if (!name)
+    return;
+  else
+    {
+      GtkWidget *edit_dialog;
+
+      edit_dialog = gdict_source_dialog_new (GTK_WINDOW (dialog),
+                                             _("Edit Dictionary Source"),
+                                             GDICT_SOURCE_DIALOG_EDIT,
+                                             dialog->loader,
+                                             name);
+      gtk_dialog_run (GTK_DIALOG (edit_dialog));
+
+      gtk_widget_destroy (edit_dialog);
+    }
+
+  g_free (name);
+
+  update_sources_view (dialog);
+}
+
+static void
+set_source_loader (GdictPrefDialog   *dialog,
+		   GdictSourceLoader *loader)
+{
+  if (!dialog->sources_list)
+    return;
+
+  if (dialog->loader)
+    g_object_unref (dialog->loader);
+
+  dialog->loader = g_object_ref (loader);
+
+  update_sources_view (dialog);
+}
+
+static void
+font_button_font_set_cb (GtkWidget       *font_button,
+			 GdictPrefDialog *dialog)
+{
+  gchar *font;
+
+  font = gtk_font_chooser_get_font (GTK_FONT_CHOOSER (font_button));
+
+  if (!font || font[0] == '\0' || g_strcmp0 (dialog->print_font, font) == 0)
+    {
+      g_free (font);
+      return;
+    }
+
+  g_free (dialog->print_font);
+  dialog->print_font = g_strdup (font);
+
+  g_settings_set_string (dialog->settings, GDICT_SETTINGS_PRINT_FONT_KEY, dialog->print_font);
+
+  g_free (font);
+}
+
+static void
+response_cb (GtkDialog *dialog,
+	     gint       response_id,
+	     gpointer   user_data)
+{
+  GError *err = NULL;
+
+  switch (response_id)
+    {
+    case GTK_RESPONSE_HELP:
+      gtk_show_uri_on_window (GTK_WINDOW (dialog),
+                    "help:mate-dictionary/mate-dictionary-preferences",
+                    gtk_get_current_event_time (), &err);
+      if (err)
+	{
+          GtkWidget *error_dialog;
+	  gchar *message;
+
+	  message = g_strdup_printf (_("There was an error while displaying help"));
+	  error_dialog = gtk_message_dialog_new (GTK_WINDOW (dialog),
+      					         GTK_DIALOG_DESTROY_WITH_PARENT,
+      					         GTK_MESSAGE_ERROR,
+						 GTK_BUTTONS_OK,
+						 "%s", message);
+	  gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (error_dialog),
+			  			    "%s", err->message);
+	  gtk_window_set_title (GTK_WINDOW (error_dialog), "");
+
+	  gtk_dialog_run (GTK_DIALOG (error_dialog));
+
+          gtk_widget_destroy (error_dialog);
+	  g_error_free (err);
+        }
+
+      /* we don't want the dialog to close itself */
+      g_signal_stop_emission_by_name (dialog, "response");
+      break;
+    case GTK_RESPONSE_ACCEPT:
+    default:
+      gtk_widget_hide (GTK_WIDGET (dialog));
+      break;
+    }
+}
+
+static void
+gdict_pref_dialog_finalize (GObject *object)
+{
+  GdictPrefDialog *dialog = GDICT_PREF_DIALOG (object);
+
+  if (dialog->settings)
+    g_object_unref (dialog->settings);
+
+  if (dialog->builder)
+    g_object_unref (dialog->builder);
+
+  if (dialog->active_source)
+    g_free (dialog->active_source);
+
+  if (dialog->loader)
+    g_object_unref (dialog->loader);
+
+  G_OBJECT_CLASS (gdict_pref_dialog_parent_class)->finalize (object);
+}
+
+static void
+gdict_pref_dialog_set_property (GObject      *object,
+				guint         prop_id,
+				const GValue *value,
+				GParamSpec   *pspec)
+{
+  GdictPrefDialog *dialog = GDICT_PREF_DIALOG (object);
+
+  switch (prop_id)
+    {
+    case PROP_SOURCE_LOADER:
+      set_source_loader (dialog, g_value_get_object (value));
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+gdict_pref_dialog_get_property (GObject    *object,
+				guint       prop_id,
+				GValue     *value,
+				GParamSpec *pspec)
+{
+  GdictPrefDialog *dialog = GDICT_PREF_DIALOG (object);
+
+  switch (prop_id)
+    {
+    case PROP_SOURCE_LOADER:
+      g_value_set_object (value, dialog->loader);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static gboolean
+on_preferences_notebook_scroll_event (GtkWidget      *widget,
+                                      GdkEventScroll *event)
+{
+  GtkNotebook *notebook = GTK_NOTEBOOK (widget);
+  GtkWidget *child, *event_widget, *action_widget;
+
+  child = gtk_notebook_get_nth_page (notebook, gtk_notebook_get_current_page (notebook));
+  if (child == NULL)
+      return FALSE;
+
+  event_widget = gtk_get_event_widget ((GdkEvent *) event);
+
+  /* Ignore scroll events from the content of the page */
+  if (event_widget == NULL ||
+      event_widget == child ||
+      gtk_widget_is_ancestor (event_widget, child))
+      return FALSE;
+
+  /* And also from the action widgets */
+  action_widget = gtk_notebook_get_action_widget (notebook, GTK_PACK_START);
+  if (event_widget == action_widget ||
+      (action_widget != NULL && gtk_widget_is_ancestor (event_widget, action_widget)))
+      return FALSE;
+
+  action_widget = gtk_notebook_get_action_widget (notebook, GTK_PACK_END);
+  if (event_widget == action_widget ||
+      (action_widget != NULL && gtk_widget_is_ancestor (event_widget, action_widget)))
+      return FALSE;
+
+  switch (event->direction) {
+    case GDK_SCROLL_RIGHT:
+    case GDK_SCROLL_DOWN:
+      gtk_notebook_next_page (notebook);
+      break;
+    case GDK_SCROLL_LEFT:
+    case GDK_SCROLL_UP:
+      gtk_notebook_prev_page (notebook);
+      break;
+    case GDK_SCROLL_SMOOTH:
+      switch (gtk_notebook_get_tab_pos (notebook)) {
+        case GTK_POS_LEFT:
+        case GTK_POS_RIGHT:
+          if (event->delta_y > 0)
+            gtk_notebook_next_page (notebook);
+          else if (event->delta_y < 0)
+            gtk_notebook_prev_page (notebook);
+          break;
+        case GTK_POS_TOP:
+        case GTK_POS_BOTTOM:
+          if (event->delta_x > 0)
+            gtk_notebook_next_page (notebook);
+          else if (event->delta_x < 0)
+            gtk_notebook_prev_page (notebook);
+          break;
+      }
+      break;
+    }
+
+  return TRUE;
+}
+
+static void
+gdict_pref_dialog_class_init (GdictPrefDialogClass *klass)
+{
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+  gobject_class->set_property = gdict_pref_dialog_set_property;
+  gobject_class->get_property = gdict_pref_dialog_get_property;
+  gobject_class->finalize = gdict_pref_dialog_finalize;
+
+  g_object_class_install_property (gobject_class,
+  				   PROP_SOURCE_LOADER,
+  				   g_param_spec_object ("source-loader",
+  				   			"Source Loader",
+  				   			"The GdictSourceLoader used by the application",
+  				   			GDICT_TYPE_SOURCE_LOADER,
+  				   			(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)));
+}
+
+static void
+gdict_pref_dialog_init (GdictPrefDialog *dialog)
+{
+  gchar *font;
+  GError *error = NULL;
+
+  gtk_window_set_default_size (GTK_WINDOW (dialog),
+  			       DEFAULT_MIN_WIDTH,
+  			       DEFAULT_MIN_HEIGHT);
+
+  gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
+  gtk_box_set_spacing (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), 2);
+
+  /* add buttons */
+  gtk_dialog_add_button (GTK_DIALOG (dialog),
+  			 "gtk-help",
+  			 GTK_RESPONSE_HELP);
+  gtk_dialog_add_button (GTK_DIALOG (dialog),
+  			 "gtk-close",
+  			 GTK_RESPONSE_ACCEPT);
+
+  dialog->settings = g_settings_new (GDICT_SETTINGS_SCHEMA);
+
+  /* get the UI from the GtkBuilder file */
+  dialog->builder = gtk_builder_new ();
+  gtk_builder_add_from_file (dialog->builder, GDICT_PREFERENCES_UI, &error);
+
+  if (error) {
+    g_critical ("Unable to load the preferences user interface: %s", error->message);
+    g_error_free (error);
+    g_assert_not_reached ();
+  }
+
+  /* the main widget */
+  gtk_container_add (GTK_CONTAINER (gtk_dialog_get_content_area (GTK_DIALOG (dialog))),
+                     GET_WIDGET ("preferences_root"));
+
+  /* keep all the interesting widgets around */
+  dialog->notebook = GET_WIDGET ("preferences_notebook");
+
+  gtk_widget_add_events (dialog->notebook, GDK_SCROLL_MASK);
+  g_signal_connect (dialog->notebook,
+                    "scroll-event",
+                    G_CALLBACK (on_preferences_notebook_scroll_event),
+                    NULL);
+
+  dialog->sources_view = GET_WIDGET ("sources_treeview");
+  build_sources_view (dialog);
+
+  dialog->active_source = g_settings_get_string (dialog->settings, GDICT_SETTINGS_SOURCE_KEY);
+
+  dialog->sources_add = GET_WIDGET ("add_button");
+  gtk_widget_set_tooltip_text (dialog->sources_add,
+                               _("Add a new dictionary source"));
+  g_signal_connect (dialog->sources_add, "clicked",
+  		    G_CALLBACK (source_add_clicked_cb), dialog);
+
+  dialog->sources_remove = GET_WIDGET ("remove_button");
+  gtk_widget_set_tooltip_text (dialog->sources_remove,
+                               _("Remove the currently selected dictionary source"));
+  g_signal_connect (dialog->sources_remove, "clicked",
+  		    G_CALLBACK (source_remove_clicked_cb), dialog);
+
+  dialog->sources_edit = GET_WIDGET ("edit_button");
+  gtk_widget_set_tooltip_text (dialog->sources_edit,
+                               _("Edit the currently selected dictionary source"));
+  g_signal_connect (dialog->sources_edit, "clicked",
+                    G_CALLBACK (source_edit_clicked_cb), dialog);
+
+  font = g_settings_get_string (dialog->settings, GDICT_SETTINGS_PRINT_FONT_KEY);
+  dialog->font_button = GET_WIDGET ("print_font_button");
+  gtk_font_chooser_set_font (GTK_FONT_CHOOSER (dialog->font_button), font);
+  gtk_widget_set_tooltip_text (dialog->font_button,
+                               _("Set the font used for printing the definitions"));
+  g_signal_connect (dialog->font_button, "font-set",
+  		    G_CALLBACK (font_button_font_set_cb), dialog);
+  g_free (font);
+
+  gtk_widget_show_all (dialog->notebook);
+
+  /* we want to intercept the response signal before any other
+   * callbacks might be attached by the users of the
+   * GdictPrefDialog widget.
+   */
+  g_signal_connect (dialog, "response",
+		    G_CALLBACK (response_cb),
+		    NULL);
+}
+
+void
+gdict_show_pref_dialog (GtkWidget         *parent,
+			const gchar       *title,
+			GdictSourceLoader *loader)
+{
+  GtkWidget *dialog;
+
+  g_return_if_fail (GTK_IS_WIDGET (parent));
+  g_return_if_fail (GDICT_IS_SOURCE_LOADER (loader));
+
+  if (parent != NULL)
+    dialog = g_object_get_data (G_OBJECT (parent), "gdict-pref-dialog");
+  else
+    dialog = global_dialog;
+
+  if (dialog == NULL)
+    {
+      dialog = g_object_new (GDICT_TYPE_PREF_DIALOG,
+                             "source-loader", loader,
+                             "title", title,
+                             NULL);
+
+      g_object_ref_sink (dialog);
+
+      g_signal_connect (dialog, "delete-event",
+                        G_CALLBACK (gtk_widget_hide_on_delete),
+                        NULL);
+
+      if (parent != NULL && GTK_IS_WINDOW (parent))
+        {
+          gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (parent));
+          gtk_window_set_destroy_with_parent (GTK_WINDOW (dialog), TRUE);
+          g_object_set_data_full (G_OBJECT (parent), "gdict-pref-dialog",
+                                  dialog,
+                                  g_object_unref);
+        }
+      else
+        global_dialog = dialog;
+    }
+
+  gtk_window_set_screen (GTK_WINDOW (dialog), gtk_widget_get_screen (parent));
+  gtk_window_present (GTK_WINDOW (dialog));
+}
+
+ +
+ +
+ + diff --git a/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/34.html b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/34.html new file mode 100644 index 00000000..778ab01e --- /dev/null +++ b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/34.html @@ -0,0 +1,4663 @@ + + + + + + Cppcheck - HTML report - mate-utils + + + + + +
+ + + +
+
   1
+   2
+   3
+   4
+   5
+   6
+   7
+   8
+   9
+  10
+  11
+  12
+  13
+  14
+  15
+  16
+  17
+  18
+  19
+  20
+  21
+  22
+  23
+  24
+  25
+  26
+  27
+  28
+  29
+  30
+  31
+  32
+  33
+  34
+  35
+  36
+  37
+  38
+  39
+  40
+  41
+  42
+  43
+  44
+  45
+  46
+  47
+  48
+  49
+  50
+  51
+  52
+  53
+  54
+  55
+  56
+  57
+  58
+  59
+  60
+  61
+  62
+  63
+  64
+  65
+  66
+  67
+  68
+  69
+  70
+  71
+  72
+  73
+  74
+  75
+  76
+  77
+  78
+  79
+  80
+  81
+  82
+  83
+  84
+  85
+  86
+  87
+  88
+  89
+  90
+  91
+  92
+  93
+  94
+  95
+  96
+  97
+  98
+  99
+ 100
+ 101
+ 102
+ 103
+ 104
+ 105
+ 106
+ 107
+ 108
+ 109
+ 110
+ 111
+ 112
+ 113
+ 114
+ 115
+ 116
+ 117
+ 118
+ 119
+ 120
+ 121
+ 122
+ 123
+ 124
+ 125
+ 126
+ 127
+ 128
+ 129
+ 130
+ 131
+ 132
+ 133
+ 134
+ 135
+ 136
+ 137
+ 138
+ 139
+ 140
+ 141
+ 142
+ 143
+ 144
+ 145
+ 146
+ 147
+ 148
+ 149
+ 150
+ 151
+ 152
+ 153
+ 154
+ 155
+ 156
+ 157
+ 158
+ 159
+ 160
+ 161
+ 162
+ 163
+ 164
+ 165
+ 166
+ 167
+ 168
+ 169
+ 170
+ 171
+ 172
+ 173
+ 174
+ 175
+ 176
+ 177
+ 178
+ 179
+ 180
+ 181
+ 182
+ 183
+ 184
+ 185
+ 186
+ 187
+ 188
+ 189
+ 190
+ 191
+ 192
+ 193
+ 194
+ 195
+ 196
+ 197
+ 198
+ 199
+ 200
+ 201
+ 202
+ 203
+ 204
+ 205
+ 206
+ 207
+ 208
+ 209
+ 210
+ 211
+ 212
+ 213
+ 214
+ 215
+ 216
+ 217
+ 218
+ 219
+ 220
+ 221
+ 222
+ 223
+ 224
+ 225
+ 226
+ 227
+ 228
+ 229
+ 230
+ 231
+ 232
+ 233
+ 234
+ 235
+ 236
+ 237
+ 238
+ 239
+ 240
+ 241
+ 242
+ 243
+ 244
+ 245
+ 246
+ 247
+ 248
+ 249
+ 250
+ 251
+ 252
+ 253
+ 254
+ 255
+ 256
+ 257
+ 258
+ 259
+ 260
+ 261
+ 262
+ 263
+ 264
+ 265
+ 266
+ 267
+ 268
+ 269
+ 270
+ 271
+ 272
+ 273
+ 274
+ 275
+ 276
+ 277
+ 278
+ 279
+ 280
+ 281
+ 282
+ 283
+ 284
+ 285
+ 286
+ 287
+ 288
+ 289
+ 290
+ 291
+ 292
+ 293
+ 294
+ 295
+ 296
+ 297
+ 298
+ 299
+ 300
+ 301
+ 302
+ 303
+ 304
+ 305
+ 306
+ 307
+ 308
+ 309
+ 310
+ 311
+ 312
+ 313
+ 314
+ 315
+ 316
+ 317
+ 318
+ 319
+ 320
+ 321
+ 322
+ 323
+ 324
+ 325
+ 326
+ 327
+ 328
+ 329
+ 330
+ 331
+ 332
+ 333
+ 334
+ 335
+ 336
+ 337
+ 338
+ 339
+ 340
+ 341
+ 342
+ 343
+ 344
+ 345
+ 346
+ 347
+ 348
+ 349
+ 350
+ 351
+ 352
+ 353
+ 354
+ 355
+ 356
+ 357
+ 358
+ 359
+ 360
+ 361
+ 362
+ 363
+ 364
+ 365
+ 366
+ 367
+ 368
+ 369
+ 370
+ 371
+ 372
+ 373
+ 374
+ 375
+ 376
+ 377
+ 378
+ 379
+ 380
+ 381
+ 382
+ 383
+ 384
+ 385
+ 386
+ 387
+ 388
+ 389
+ 390
+ 391
+ 392
+ 393
+ 394
+ 395
+ 396
+ 397
+ 398
+ 399
+ 400
+ 401
+ 402
+ 403
+ 404
+ 405
+ 406
+ 407
+ 408
+ 409
+ 410
+ 411
+ 412
+ 413
+ 414
+ 415
+ 416
+ 417
+ 418
+ 419
+ 420
+ 421
+ 422
+ 423
+ 424
+ 425
+ 426
+ 427
+ 428
+ 429
+ 430
+ 431
+ 432
+ 433
+ 434
+ 435
+ 436
+ 437
+ 438
+ 439
+ 440
+ 441
+ 442
+ 443
+ 444
+ 445
+ 446
+ 447
+ 448
+ 449
+ 450
+ 451
+ 452
+ 453
+ 454
+ 455
+ 456
+ 457
+ 458
+ 459
+ 460
+ 461
+ 462
+ 463
+ 464
+ 465
+ 466
+ 467
+ 468
+ 469
+ 470
+ 471
+ 472
+ 473
+ 474
+ 475
+ 476
+ 477
+ 478
+ 479
+ 480
+ 481
+ 482
+ 483
+ 484
+ 485
+ 486
+ 487
+ 488
+ 489
+ 490
+ 491
+ 492
+ 493
+ 494
+ 495
+ 496
+ 497
+ 498
+ 499
+ 500
+ 501
+ 502
+ 503
+ 504
+ 505
+ 506
+ 507
+ 508
+ 509
+ 510
+ 511
+ 512
+ 513
+ 514
+ 515
+ 516
+ 517
+ 518
+ 519
+ 520
+ 521
+ 522
+ 523
+ 524
+ 525
+ 526
+ 527
+ 528
+ 529
+ 530
+ 531
+ 532
+ 533
+ 534
+ 535
+ 536
+ 537
+ 538
+ 539
+ 540
+ 541
+ 542
+ 543
+ 544
+ 545
+ 546
+ 547
+ 548
+ 549
+ 550
+ 551
+ 552
+ 553
+ 554
+ 555
+ 556
+ 557
+ 558
+ 559
+ 560
+ 561
+ 562
+ 563
+ 564
+ 565
+ 566
+ 567
+ 568
+ 569
+ 570
+ 571
+ 572
+ 573
+ 574
+ 575
+ 576
+ 577
+ 578
+ 579
+ 580
+ 581
+ 582
+ 583
+ 584
+ 585
+ 586
+ 587
+ 588
+ 589
+ 590
+ 591
+ 592
+ 593
+ 594
+ 595
+ 596
+ 597
+ 598
+ 599
+ 600
+ 601
+ 602
+ 603
+ 604
+ 605
+ 606
+ 607
+ 608
+ 609
+ 610
+ 611
+ 612
+ 613
+ 614
+ 615
+ 616
+ 617
+ 618
+ 619
+ 620
+ 621
+ 622
+ 623
+ 624
+ 625
+ 626
+ 627
+ 628
+ 629
+ 630
+ 631
+ 632
+ 633
+ 634
+ 635
+ 636
+ 637
+ 638
+ 639
+ 640
+ 641
+ 642
+ 643
+ 644
+ 645
+ 646
+ 647
+ 648
+ 649
+ 650
+ 651
+ 652
+ 653
+ 654
+ 655
+ 656
+ 657
+ 658
+ 659
+ 660
+ 661
+ 662
+ 663
+ 664
+ 665
+ 666
+ 667
+ 668
+ 669
+ 670
+ 671
+ 672
+ 673
+ 674
+ 675
+ 676
+ 677
+ 678
+ 679
+ 680
+ 681
+ 682
+ 683
+ 684
+ 685
+ 686
+ 687
+ 688
+ 689
+ 690
+ 691
+ 692
+ 693
+ 694
+ 695
+ 696
+ 697
+ 698
+ 699
+ 700
+ 701
+ 702
+ 703
+ 704
+ 705
+ 706
+ 707
+ 708
+ 709
+ 710
+ 711
+ 712
+ 713
+ 714
+ 715
+ 716
+ 717
+ 718
+ 719
+ 720
+ 721
+ 722
+ 723
+ 724
+ 725
+ 726
+ 727
+ 728
+ 729
+ 730
+ 731
+ 732
+ 733
+ 734
+ 735
+ 736
+ 737
+ 738
+ 739
+ 740
+ 741
+ 742
+ 743
+ 744
+ 745
+ 746
+ 747
+ 748
+ 749
+ 750
+ 751
+ 752
+ 753
+ 754
+ 755
+ 756
+ 757
+ 758
+ 759
+ 760
+ 761
+ 762
+ 763
+ 764
+ 765
+ 766
+ 767
+ 768
+ 769
+ 770
+ 771
+ 772
+ 773
+ 774
+ 775
+ 776
+ 777
+ 778
+ 779
+ 780
+ 781
+ 782
+ 783
+ 784
+ 785
+ 786
+ 787
+ 788
+ 789
+ 790
+ 791
+ 792
+ 793
+ 794
+ 795
+ 796
+ 797
+ 798
+ 799
+ 800
+ 801
+ 802
+ 803
+ 804
+ 805
+ 806
+ 807
+ 808
+ 809
+ 810
+ 811
+ 812
+ 813
+ 814
+ 815
+ 816
+ 817
+ 818
+ 819
+ 820
+ 821
+ 822
+ 823
+ 824
+ 825
+ 826
+ 827
+ 828
+ 829
+ 830
+ 831
+ 832
+ 833
+ 834
+ 835
+ 836
+ 837
+ 838
+ 839
+ 840
+ 841
+ 842
+ 843
+ 844
+ 845
+ 846
+ 847
+ 848
+ 849
+ 850
+ 851
+ 852
+ 853
+ 854
+ 855
+ 856
+ 857
+ 858
+ 859
+ 860
+ 861
+ 862
+ 863
+ 864
+ 865
+ 866
+ 867
+ 868
+ 869
+ 870
+ 871
+ 872
+ 873
+ 874
+ 875
+ 876
+ 877
+ 878
+ 879
+ 880
+ 881
+ 882
+ 883
+ 884
+ 885
+ 886
+ 887
+ 888
+ 889
+ 890
+ 891
+ 892
+ 893
+ 894
+ 895
+ 896
+ 897
+ 898
+ 899
+ 900
+ 901
+ 902
+ 903
+ 904
+ 905
+ 906
+ 907
+ 908
+ 909
+ 910
+ 911
+ 912
+ 913
+ 914
+ 915
+ 916
+ 917
+ 918
+ 919
+ 920
+ 921
+ 922
+ 923
+ 924
+ 925
+ 926
+ 927
+ 928
+ 929
+ 930
+ 931
+ 932
+ 933
+ 934
+ 935
+ 936
+ 937
+ 938
+ 939
+ 940
+ 941
+ 942
+ 943
+ 944
+ 945
+ 946
+ 947
+ 948
+ 949
+ 950
+ 951
+ 952
+ 953
+ 954
+ 955
+ 956
+ 957
+ 958
+ 959
+ 960
+ 961
+ 962
+ 963
+ 964
+ 965
+ 966
+ 967
+ 968
+ 969
+ 970
+ 971
+ 972
+ 973
+ 974
+ 975
+ 976
+ 977
+ 978
+ 979
+ 980
+ 981
+ 982
+ 983
+ 984
+ 985
+ 986
+ 987
+ 988
+ 989
+ 990
+ 991
+ 992
+ 993
+ 994
+ 995
+ 996
+ 997
+ 998
+ 999
+1000
+1001
+1002
+1003
+1004
+1005
+1006
+1007
+1008
+1009
+1010
+1011
+1012
+1013
+1014
+1015
+1016
+1017
+1018
+1019
+1020
+1021
+1022
+1023
+1024
+1025
+1026
+1027
+1028
+1029
+1030
+1031
+1032
+1033
+1034
+1035
+1036
+1037
+1038
+1039
+1040
+1041
+1042
+1043
+1044
+1045
+1046
+1047
+1048
+1049
+1050
+1051
+1052
+1053
+1054
+1055
+1056
+1057
+1058
+1059
+1060
+1061
+1062
+1063
+1064
+1065
+1066
+1067
+1068
+1069
+1070
+1071
+1072
+1073
+1074
+1075
+1076
+1077
+1078
+1079
+1080
+1081
+1082
+1083
+1084
+1085
+1086
+1087
+1088
+1089
+1090
+1091
+1092
+1093
+1094
+1095
+1096
+1097
+1098
+1099
+1100
+1101
+1102
+1103
+1104
+1105
+1106
+1107
+1108
+1109
+1110
+1111
+1112
+1113
+1114
+1115
+1116
+1117
+1118
+1119
+1120
+1121
+1122
+1123
+1124
+1125
+1126
+1127
+1128
+1129
+1130
+1131
+1132
+1133
+1134
+1135
+1136
+1137
+1138
+1139
+1140
+1141
+1142
+1143
+1144
+1145
+1146
+1147
+1148
+1149
+1150
+1151
+1152
+1153
+1154
+1155
+1156
+1157
+1158
+1159
+1160
+1161
+1162
+1163
+1164
+1165
+1166
+1167
+1168
+1169
+1170
+1171
+1172
+1173
+1174
+1175
+1176
+1177
+1178
+1179
+1180
+1181
+1182
+1183
+1184
+1185
+1186
+1187
+1188
+1189
+1190
+1191
+1192
+1193
+1194
+1195
+1196
+1197
+1198
+1199
+1200
+1201
+1202
+1203
+1204
+1205
+1206
+1207
+1208
+1209
+1210
+1211
+1212
+1213
+1214
+1215
+1216
+1217
+1218
+1219
+1220
+1221
+1222
+1223
+1224
+1225
+1226
+1227
+1228
+1229
+1230
+1231
+1232
+1233
+1234
+1235
+1236
+1237
+1238
+1239
+1240
+1241
+1242
+1243
+1244
+1245
+1246
+1247
+1248
+1249
+1250
+1251
+1252
+1253
+1254
+1255
+1256
+1257
+1258
+1259
+1260
+1261
+1262
+1263
+1264
+1265
+1266
+1267
+1268
+1269
+1270
+1271
+1272
+1273
+1274
+1275
+1276
+1277
+1278
+1279
+1280
+1281
+1282
+1283
+1284
+1285
+1286
+1287
+1288
+1289
+1290
+1291
+1292
+1293
+1294
+1295
+1296
+1297
+1298
+1299
+1300
+1301
+1302
+1303
+1304
+1305
+1306
+1307
+1308
+1309
+1310
+1311
+1312
+1313
+1314
+1315
+1316
+1317
+1318
+1319
+1320
+1321
+1322
+1323
+1324
+1325
+1326
+1327
+1328
+1329
+1330
+1331
+1332
+1333
+1334
+1335
+1336
+1337
+1338
+1339
+1340
+1341
+1342
+1343
+1344
+1345
+1346
+1347
+1348
+1349
+1350
+1351
+1352
+1353
+1354
+1355
+1356
+1357
+1358
+1359
+1360
+1361
+1362
+1363
+1364
+1365
+1366
+1367
+1368
+1369
+1370
+1371
+1372
+1373
+1374
+1375
+1376
+1377
+1378
+1379
+1380
+1381
+1382
+1383
+1384
+1385
+1386
+1387
+1388
+1389
+1390
+1391
+1392
+1393
+1394
+1395
+1396
+1397
+1398
+1399
+1400
+1401
+1402
+1403
+1404
+1405
+1406
+1407
+1408
+1409
+1410
+1411
+1412
+1413
+1414
+1415
+1416
+1417
+1418
+1419
+1420
+1421
+1422
+1423
+1424
+1425
+1426
+1427
+1428
+1429
+1430
+1431
+1432
+1433
+1434
+1435
+1436
+1437
+1438
+1439
+1440
+1441
+1442
+1443
+1444
+1445
+1446
+1447
+1448
+1449
+1450
+1451
+1452
+1453
+1454
+1455
+1456
+1457
+1458
+1459
+1460
+1461
+1462
+1463
+1464
+1465
+1466
+1467
+1468
+1469
+1470
+1471
+1472
+1473
+1474
+1475
+1476
+1477
+1478
+1479
+1480
+1481
+1482
+1483
+1484
+1485
+1486
+1487
+1488
+1489
+1490
+1491
+1492
+1493
+1494
+1495
+1496
+1497
+1498
+1499
+1500
+1501
+1502
+1503
+1504
+1505
+1506
+1507
+1508
+1509
+1510
+1511
+1512
+1513
+1514
+1515
+1516
+1517
+1518
+1519
+1520
+1521
+1522
+1523
+1524
+1525
+1526
+1527
+1528
+1529
+1530
+1531
+1532
+1533
+1534
+1535
+1536
+1537
+1538
+1539
+1540
+1541
+1542
+1543
+1544
+1545
+1546
+1547
+1548
+1549
+1550
+1551
+1552
+1553
+1554
+1555
+1556
+1557
+1558
+1559
+1560
+1561
+1562
+1563
+1564
+1565
+1566
+1567
+1568
+1569
+1570
+1571
+1572
+1573
+1574
+1575
+1576
+1577
+1578
+1579
+1580
+1581
+1582
+1583
+1584
+1585
+1586
+1587
+1588
+1589
+1590
+1591
+1592
+1593
+1594
+1595
+1596
+1597
+1598
+1599
+1600
+1601
+1602
+1603
+1604
+1605
+1606
+1607
+1608
+1609
+1610
+1611
+1612
+1613
+1614
+1615
+1616
+1617
+1618
+1619
+1620
+1621
+1622
+1623
+1624
+1625
+1626
+1627
+1628
+1629
+1630
+1631
+1632
+1633
+1634
+1635
+1636
+1637
+1638
+1639
+1640
+1641
+1642
+1643
+1644
+1645
+1646
+1647
+1648
+1649
+1650
+1651
+1652
+1653
+1654
+1655
+1656
+1657
+1658
+1659
+1660
+1661
+1662
+1663
+1664
+1665
+1666
+1667
+1668
+1669
+1670
+1671
+1672
+1673
+1674
+1675
+1676
+1677
+1678
+1679
+1680
+1681
+1682
+1683
+1684
+1685
+1686
+1687
+1688
+1689
+1690
+1691
+1692
+1693
+1694
+1695
+1696
+1697
+1698
+1699
+1700
+1701
+1702
+1703
+1704
+1705
+1706
+1707
+1708
+1709
+1710
+1711
+1712
+1713
+1714
+1715
+1716
+1717
+1718
+1719
+1720
+1721
+1722
+1723
+1724
+1725
+1726
+1727
+1728
+1729
+1730
+1731
+1732
+1733
+1734
+1735
+1736
+1737
+1738
+1739
+1740
+1741
+1742
+1743
+1744
+1745
+1746
+1747
+1748
+1749
+1750
+1751
+1752
+1753
+1754
+1755
+1756
+1757
+1758
+1759
+1760
+1761
+1762
+1763
+1764
+1765
+1766
+1767
+1768
+1769
+1770
+1771
+1772
+1773
+1774
+1775
+1776
+1777
+1778
+1779
+1780
+1781
+1782
+1783
+1784
+1785
+1786
+1787
+1788
+1789
+1790
+1791
+1792
+1793
+1794
+1795
+1796
+1797
+1798
+1799
+1800
+1801
+1802
+1803
+1804
+1805
+1806
+1807
+1808
+1809
+1810
+1811
+1812
+1813
+1814
+1815
+1816
+1817
+1818
+1819
+1820
+1821
+1822
+1823
+1824
+1825
+1826
+1827
+1828
+1829
+1830
+1831
+1832
+1833
+1834
+1835
+1836
+1837
+1838
+1839
+1840
+1841
+1842
+1843
+1844
+1845
+1846
+1847
+1848
+1849
+1850
+1851
+1852
+1853
+1854
+1855
+1856
+1857
+1858
+1859
+1860
+1861
+1862
+1863
+1864
+1865
+1866
+1867
+1868
+1869
+1870
+1871
+1872
+1873
+1874
+1875
+1876
+1877
+1878
+1879
+1880
+1881
+1882
+1883
+1884
+1885
+1886
+1887
+1888
+1889
+1890
+1891
+1892
+1893
+1894
+1895
+1896
+1897
+1898
+1899
+1900
+1901
+1902
+1903
+1904
+1905
+1906
+1907
+1908
+1909
+1910
+1911
+1912
+1913
+1914
+1915
+1916
+1917
+1918
+1919
+1920
+1921
+1922
+1923
+1924
+1925
+1926
+1927
+1928
+1929
+1930
+1931
+1932
+1933
+1934
+1935
+1936
+1937
+1938
+1939
+1940
+1941
+1942
+1943
+1944
+1945
+1946
+1947
+1948
+1949
+1950
+1951
+1952
+1953
+1954
+1955
+1956
+1957
+1958
+1959
+1960
+1961
+1962
+1963
+1964
+1965
+1966
+1967
+1968
+1969
+1970
+1971
+1972
+1973
+1974
+1975
+1976
+1977
+1978
+1979
+1980
+1981
+1982
+1983
+1984
+1985
+1986
+1987
+1988
+1989
+1990
+1991
+1992
+1993
+1994
+1995
+1996
+1997
+1998
+1999
+2000
+2001
+2002
+2003
+2004
+2005
+2006
+2007
+2008
+2009
+2010
+2011
+2012
+2013
+2014
+2015
+2016
+2017
+2018
+2019
+2020
+2021
+2022
+2023
+2024
+2025
+2026
+2027
+2028
+2029
+2030
+2031
+2032
+2033
+2034
+2035
+2036
+2037
+2038
+2039
+2040
+2041
+2042
+2043
+2044
+2045
+2046
+2047
+2048
+2049
+2050
+2051
+2052
+2053
+2054
+2055
+2056
+2057
+2058
+2059
+2060
+2061
+2062
+2063
+2064
+2065
+2066
+2067
+2068
+2069
+2070
+2071
+2072
+2073
+2074
+2075
+2076
+2077
+2078
+2079
+2080
+2081
+2082
+2083
+2084
+2085
+2086
+2087
+2088
+2089
+2090
+2091
+2092
+2093
+2094
+2095
+2096
+2097
+2098
+2099
+2100
+2101
+2102
+2103
+2104
+2105
+2106
+2107
+2108
+2109
+2110
+2111
+2112
+2113
+2114
+2115
+2116
+2117
+2118
+2119
+2120
+2121
+2122
+2123
+2124
+2125
+2126
+2127
+2128
+2129
+2130
+2131
+2132
+2133
+2134
+2135
+2136
+2137
+2138
+2139
+2140
+2141
+2142
+2143
+2144
+2145
+2146
+2147
+2148
+2149
+2150
+2151
+2152
+2153
+2154
+2155
+2156
+2157
+2158
+2159
+2160
+2161
+2162
+2163
+2164
+2165
+2166
+2167
+2168
+2169
+2170
+2171
+2172
+2173
+2174
+2175
+2176
+2177
+2178
+2179
+2180
+2181
+2182
+2183
+2184
+2185
+2186
+2187
+2188
+2189
+2190
+2191
+2192
+2193
+2194
+2195
+2196
+2197
+2198
+2199
+2200
+2201
+2202
+2203
+2204
+2205
+2206
+2207
/* Copyright (C) 2005 Emmanuele Bassi
+ * Copyright (C) 2012-2021 MATE Developers
+ *
+ * This file is part of MATE Utils.
+ *
+ * MATE Utils is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * MATE Utils is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MATE Utils.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <errno.h>
+
+#include <gtk/gtk.h>
+#include <glib.h>
+#include <glib/gstdio.h>
+#include <glib/gi18n.h>
+
+#include <libgdict/gdict.h>
+
+#include "gdict-sidebar.h"
+#include "gdict-print.h"
+#include "gdict-pref-dialog.h"
+#include "gdict-about.h"
+#include "gdict-window.h"
+#include "gdict-common.h"
+
+#define GDICT_WINDOW_COLUMNS      56
+#define GDICT_WINDOW_ROWS         33
+
+#define GDICT_WINDOW_MIN_WIDTH	  400
+#define GDICT_WINDOW_MIN_HEIGHT	  330
+
+/* sidebar pages logical ids */
+#define GDICT_SIDEBAR_SPELLER_PAGE      "speller"
+#define GDICT_SIDEBAR_DATABASES_PAGE    "db-chooser"
+#define GDICT_SIDEBAR_STRATEGIES_PAGE   "strat-chooser"
+#define GDICT_SIDEBAR_SOURCES_PAGE      "source-chooser"
+
+enum
+{
+  COMPLETION_TEXT_COLUMN,
+
+  COMPLETION_N_COLUMNS
+};
+
+enum
+{
+  PROP_0,
+
+  PROP_ACTION,
+  PROP_SOURCE_LOADER,
+  PROP_SOURCE_NAME,
+  PROP_DATABASE,
+  PROP_STRATEGY,
+  PROP_PRINT_FONT,
+  PROP_DEFBOX_FONT,
+  PROP_WORD,
+  PROP_WINDOW_ID,
+
+  LAST_PROP
+};
+
+enum
+{
+  CREATED,
+
+  LAST_SIGNAL
+};
+
+static GParamSpec *gdict_window_properties[LAST_PROP] = { NULL, };
+static guint gdict_window_signals[LAST_SIGNAL] = { 0 };
+
+static const GtkTargetEntry drop_types[] =
+{
+  { "text/plain",    0, 0 },
+  { "TEXT",          0, 0 },
+  { "STRING",        0, 0 },
+  { "UTF8_STRING",   0, 0 },
+};
+static const guint n_drop_types = G_N_ELEMENTS (drop_types);
+
+G_DEFINE_TYPE (GdictWindow, gdict_window, GTK_TYPE_WINDOW);
+
+static void
+gdict_window_finalize (GObject *gobject)
+{
+  GdictWindow *window = GDICT_WINDOW (gobject);
+
+  g_free (window->source_name);
+  g_free (window->print_font);
+  g_free (window->defbox_font);
+  g_free (window->word);
+  g_free (window->database);
+  g_free (window->strategy);
+
+  G_OBJECT_CLASS (gdict_window_parent_class)->finalize (gobject);
+}
+
+static void
+gdict_window_dispose (GObject *gobject)
+{
+  GdictWindow *window = GDICT_WINDOW (gobject);
+
+  if (window->desktop_settings != NULL)
+    {
+      g_object_unref (window->desktop_settings);
+      window->desktop_settings = NULL;
+    }
+
+  if (window->settings != NULL)
+    {
+      g_object_unref (window->settings);
+      window->settings = NULL;
+    }
+
+  if (window->context)
+    {
+      if (window->lookup_start_id)
+        {
+          g_signal_handler_disconnect (window->context, window->lookup_start_id);
+          g_signal_handler_disconnect (window->context, window->definition_id);
+          g_signal_handler_disconnect (window->context, window->lookup_end_id);
+          g_signal_handler_disconnect (window->context, window->error_id);
+
+          window->lookup_start_id = 0;
+          window->definition_id = 0;
+          window->lookup_end_id = 0;
+          window->error_id = 0;
+        }
+
+      g_object_unref (window->context);
+      window->context = NULL;
+    }
+
+  if (window->loader)
+    {
+      g_object_unref (window->loader);
+      window->loader = NULL;
+    }
+
+  if (window->ui_manager)
+    {
+      g_object_unref (window->ui_manager);
+      window->ui_manager = NULL;
+    }
+
+  if (window->action_group)
+    {
+      g_object_unref (window->action_group);
+      window->action_group = NULL;
+    }
+
+  if (window->completion)
+    {
+      g_object_unref (window->completion);
+      window->completion = NULL;
+    }
+
+  if (window->completion_model)
+    {
+      g_object_unref (window->completion_model);
+      window->completion_model = NULL;
+    }
+
+  if (window->busy_cursor)
+    {
+      g_object_unref (window->busy_cursor);
+      window->busy_cursor = NULL;
+    }
+
+  g_clear_pointer (&window->sidebar_page, g_free);
+
+  G_OBJECT_CLASS (gdict_window_parent_class)->dispose (gobject);
+}
+
+static const gchar *toggle_state[] = {
+  "save_as_item",
+  "preview_item",
+  "print_item",
+  "go_menu",
+};
+
+static gint n_toggle_state = G_N_ELEMENTS (toggle_state);
+
+static void
+gdict_window_ensure_menu_state (GdictWindow *window)
+{
+  gint i;
+  gboolean is_sensitive;
+
+  g_assert (GDICT_IS_WINDOW (window));
+
+  if (!window->ui_manager)
+    return;
+
+  is_sensitive = !!(window->word != NULL);
+  for (i = 0; i < n_toggle_state; i++)
+    {
+      GtkWidget *item;
+
+      item = (GtkWidget *)gtk_builder_get_object (window->ui_manager, toggle_state[i]);
+      if (!item)
+        continue;
+
+      gtk_widget_set_sensitive (item, is_sensitive);
+    }
+}
+
+static void
+gdict_window_set_sidebar_visible (GdictWindow *window,
+				  gboolean     is_visible)
+{
+  g_assert (GDICT_IS_WINDOW (window));
+
+  is_visible = !!is_visible;
+
+  if (is_visible != window->sidebar_visible)
+    {
+      GAction *action;
+
+      window->sidebar_visible = (is_visible != FALSE);
+
+      if (window->sidebar_visible)
+	gtk_widget_show (window->sidebar_frame);
+      else
+	gtk_widget_hide (window->sidebar_frame);
+
+      action = g_action_map_lookup_action (G_ACTION_MAP (window->action_group), "ViewSidebar");
+      g_simple_action_set_state (G_SIMPLE_ACTION (action), g_variant_new_boolean (window->sidebar_visible));
+    }
+}
+
+static void
+gdict_window_definition_cb (GdictContext    *context,
+			    GdictDefinition *definition,
+			    GdictWindow     *window)
+{
+  gint total, n;
+  gdouble fraction;
+
+  g_assert (GDICT_IS_WINDOW (window));
+
+  total = gdict_definition_get_total (definition);
+  n = window->current_definition + 1;
+
+  fraction = CLAMP (((gdouble) n / (gdouble) total), 0.0, 1.0);
+
+  gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (window->progress),
+		  		 fraction);
+  while (gtk_events_pending ())
+    gtk_main_iteration ();
+
+  window->current_definition = n;
+}
+
+static void
+gdict_window_lookup_start_cb (GdictContext *context,
+			      GdictWindow  *window)
+{
+  GdkDisplay *display;
+  gchar *message;
+
+  display = gtk_widget_get_display (GTK_WIDGET (window));
+
+  if (!window->word)
+    return;
+
+  if (!window->busy_cursor)
+    window->busy_cursor = gdk_cursor_new_for_display (display, GDK_WATCH);
+
+  message = g_strdup_printf (_("Searching for '%s'..."), window->word);
+
+  if (window->status && window->statusbar_visible)
+    gtk_statusbar_push (GTK_STATUSBAR (window->status), 0, message);
+
+  if (window->progress)
+    gtk_widget_show (window->progress);
+
+  window->max_definition = -1;
+  window->last_definition = 0;
+  window->current_definition = 0;
+
+  gdk_window_set_cursor (gtk_widget_get_window (GTK_WIDGET (window)), window->busy_cursor);
+
+  g_free (message);
+}
+
+static void
+gdict_window_lookup_end_cb (GdictContext *context,
+			    GdictWindow  *window)
+{
+  gchar *message;
+  gint count;
+  GtkTreeIter iter;
+  GdictSource *source;
+  GdictContext *speller_context;
+
+  count = window->current_definition;
+
+  window->max_definition = count - 1;
+
+  if (count == 0)
+    message = g_strdup (_("No definitions found"));
+  else
+    message = g_strdup_printf (ngettext("A definition found",
+					"%d definitions found",
+					count),
+		    	       count);
+
+  if (window->status && window->statusbar_visible)
+    gtk_statusbar_push (GTK_STATUSBAR (window->status), 0, message);
+
+  if (window->progress)
+    gtk_widget_hide (window->progress);
+
+  /* we clone the context, so that the signals that it
+   * fires do not get caught by the signal handlers we
+   * use for getting the definitions.
+   */
+  source = gdict_source_loader_get_source (window->loader, window->source_name);
+  speller_context = gdict_source_get_context (source);
+  gdict_speller_set_context (GDICT_SPELLER (window->speller), speller_context);
+  g_object_unref (speller_context);
+  g_object_unref (source);
+
+  /* search for similar words; if we have a no-match we already started
+   * looking in the error signal handler
+   */
+  if (count != 0 && window->word)
+    {
+      gdict_speller_set_strategy (GDICT_SPELLER (window->speller), window->strategy);
+      gdict_speller_match (GDICT_SPELLER (window->speller), window->word);
+      gtk_list_store_append (window->completion_model, &iter);
+      gtk_list_store_set (window->completion_model, &iter,
+                          COMPLETION_TEXT_COLUMN, window->word,
+                          -1);
+    }
+
+  gdk_window_set_cursor (gtk_widget_get_window (GTK_WIDGET (window)), NULL);
+  g_free (message);
+
+  if (count == 0)
+    {
+      g_free (window->word);
+      window->word = NULL;
+    }
+
+  gdict_window_ensure_menu_state (window);
+}
+
+static void
+gdict_window_error_cb (GdictContext *context,<--- Shadowed declaration
+		       const GError *error,
+		       GdictWindow  *window)
+{
+  gdk_window_set_cursor (gtk_widget_get_window (GTK_WIDGET (window)), NULL);
+
+  if (window->status && window->statusbar_visible)
+    gtk_statusbar_push (GTK_STATUSBAR (window->status), 0,
+                        _("No definitions found"));
+
+  gtk_widget_hide (window->progress);
+
+  /* launch the speller only on NO_MATCH */
+  if (error->code == GDICT_CONTEXT_ERROR_NO_MATCH)
+    {
+      GdictSource *source;
+      GdictContext *context;<--- Shadow variable
+
+      gdict_window_set_sidebar_visible (window, TRUE);
+      gdict_sidebar_view_page (GDICT_SIDEBAR (window->sidebar),
+                               GDICT_SIDEBAR_SPELLER_PAGE);
+
+      /* we clone the context, so that the signals that it
+       * fires do not get caught by the signal handlers we
+       * use for getting the definitions.
+       */
+      source = gdict_source_loader_get_source (window->loader,
+		      			       window->source_name);
+      context = gdict_source_get_context (source);
+
+      gdict_speller_set_context (GDICT_SPELLER (window->speller),
+		      		 context);
+      g_object_unref (context);
+      g_object_unref (source);
+
+      gdict_speller_set_strategy (GDICT_SPELLER (window->speller),
+			          window->strategy);
+
+      gdict_speller_match (GDICT_SPELLER (window->speller),
+		           window->word);
+    }
+
+  /* unset the word and update the UI */
+  g_free (window->word);
+  window->word = NULL;
+
+  gdict_window_ensure_menu_state (window);
+}
+
+static void
+gdict_window_set_database (GdictWindow *window,
+			   const gchar *database)
+{
+  if (g_strcmp0 (window->database, database) == 0)
+    return;
+
+  g_free (window->database);
+
+  if (database != NULL && *database != '\0')
+    window->database = g_strdup (database);
+  else
+    window->database = g_settings_get_string (window->settings, GDICT_SETTINGS_DATABASE_KEY);
+
+  if (window->defbox)
+    gdict_defbox_set_database (GDICT_DEFBOX (window->defbox),
+			       window->database);
+
+  if (window->db_chooser)
+    gdict_database_chooser_set_current_database (GDICT_DATABASE_CHOOSER (window->db_chooser),
+                                                 window->database);
+
+  g_object_notify_by_pspec (G_OBJECT (window), gdict_window_properties[PROP_DATABASE]);
+}
+
+static void
+gdict_window_set_strategy (GdictWindow *window,
+			   const gchar *strategy)
+{
+  if (g_strcmp0 (window->strategy, strategy) == 0)
+    return;
+
+  g_free (window->strategy);
+
+  if (strategy != NULL && *strategy != '\0')
+    window->strategy = g_strdup (strategy);
+  else
+    window->strategy = g_settings_get_string (window->settings, GDICT_SETTINGS_STRATEGY_KEY);
+
+  if (window->speller)
+    gdict_speller_set_strategy (GDICT_SPELLER (window->speller),
+                                window->strategy);
+
+  if (window->strat_chooser)
+    gdict_strategy_chooser_set_current_strategy (GDICT_STRATEGY_CHOOSER (window->strat_chooser),
+                                                 window->strategy);
+
+  g_object_notify_by_pspec (G_OBJECT (window), gdict_window_properties[PROP_STRATEGY]);
+}
+
+static GdictContext *
+get_context_from_loader (GdictWindow *window)
+{
+  GdictSource *source;
+  GdictContext *retval;
+
+  if (!window->source_name)
+    window->source_name = g_strdup (GDICT_DEFAULT_SOURCE_NAME);
+
+  source = gdict_source_loader_get_source (window->loader,
+		  			   window->source_name);
+  if (!source &&
+      strcmp (window->source_name, GDICT_DEFAULT_SOURCE_NAME) != 0)
+    {
+      g_free (window->source_name);
+      window->source_name = g_strdup (GDICT_DEFAULT_SOURCE_NAME);
+
+      source = gdict_source_loader_get_source (window->loader,
+                                               window->source_name);
+    }
+
+  if (!source)
+    {
+      gchar *detail;
+
+      detail = g_strdup_printf (_("No dictionary source available with name '%s'"),
+      				window->source_name);
+
+      gdict_show_error_dialog (GTK_WINDOW (window),
+                               _("Unable to find dictionary source"),
+                               detail);
+
+      g_free (detail);
+
+      return NULL;
+    }
+
+  gdict_window_set_database (window, gdict_source_get_database (source));
+  gdict_window_set_strategy (window, gdict_source_get_strategy (source));
+
+  retval = gdict_source_get_context (source);
+  if (!retval)
+    {
+      gchar *detail;
+
+      detail = g_strdup_printf (_("No context available for source '%s'"),
+      				gdict_source_get_description (source));
+
+      gdict_show_error_dialog (GTK_WINDOW (window),
+                               _("Unable to create a context"),
+                               detail);
+
+      g_free (detail);
+      g_object_unref (source);
+
+      return NULL;
+    }
+
+  g_object_unref (source);
+
+  return retval;
+}
+
+static void
+gdict_window_set_defbox_font (GdictWindow *window,
+			      const gchar *defbox_font)
+{
+  g_free (window->defbox_font);
+
+  if (defbox_font != NULL && *defbox_font != '\0')
+    window->defbox_font = g_strdup (defbox_font);
+  else
+    window->defbox_font = g_settings_get_string (window->desktop_settings, DOCUMENT_FONT_KEY);
+
+  gdict_defbox_set_font_name (GDICT_DEFBOX (window->defbox), window->defbox_font);
+}
+
+static void
+gdict_window_set_print_font (GdictWindow *window,
+			     const gchar *print_font)
+{
+  g_free (window->print_font);
+
+  if (print_font != NULL && *print_font != '\0')
+    window->print_font = g_strdup (print_font);
+  else
+    window->print_font = g_settings_get_string (window->settings, GDICT_SETTINGS_PRINT_FONT_KEY);
+}
+
+static void
+gdict_window_set_word (GdictWindow *window,
+		       const gchar *word,
+		       const gchar *database)
+{
+  gchar *title;
+
+  g_free (window->word);
+  window->word = NULL;
+
+  if (word && word[0] != '\0')
+    window->word = g_strdup (word);
+  else
+    return;
+
+  if (!database || database[0] == '\0')
+    database = window->database;
+
+  if (window->word)
+    title = g_strdup_printf (_("%s - Dictionary"), window->word);
+  else
+    title = g_strdup (_("Dictionary"));
+
+  gtk_window_set_title (GTK_WINDOW (window), title);
+  g_free (title);
+
+  if (window->defbox)
+    {
+      gdict_defbox_set_database (GDICT_DEFBOX (window->defbox), database);
+      gdict_defbox_lookup (GDICT_DEFBOX (window->defbox), word);
+    }
+}
+
+static void
+gdict_window_set_context (GdictWindow  *window,
+			  GdictContext *context)
+{
+  if (window->context)
+    {
+      g_signal_handler_disconnect (window->context, window->definition_id);
+      g_signal_handler_disconnect (window->context, window->lookup_start_id);
+      g_signal_handler_disconnect (window->context, window->lookup_end_id);
+      g_signal_handler_disconnect (window->context, window->error_id);
+
+      window->definition_id = 0;
+      window->lookup_start_id = 0;
+      window->lookup_end_id = 0;
+      window->error_id = 0;
+
+      g_object_unref (window->context);
+      window->context = NULL;
+    }
+
+  if (window->defbox)
+    gdict_defbox_set_context (GDICT_DEFBOX (window->defbox), context);
+
+  if (window->db_chooser)
+    gdict_database_chooser_set_context (GDICT_DATABASE_CHOOSER (window->db_chooser), context);
+
+  if (window->strat_chooser)
+    gdict_strategy_chooser_set_context (GDICT_STRATEGY_CHOOSER (window->strat_chooser), context);
+
+  if (!context)
+    return;
+
+  /* attach our callbacks */
+  window->definition_id   = g_signal_connect (context, "definition-found",
+		  			      G_CALLBACK (gdict_window_definition_cb),
+					      window);
+  window->lookup_start_id = g_signal_connect (context, "lookup-start",
+		  			      G_CALLBACK (gdict_window_lookup_start_cb),
+					      window);
+  window->lookup_end_id   = g_signal_connect (context, "lookup-end",
+		  			      G_CALLBACK (gdict_window_lookup_end_cb),
+					      window);
+  window->error_id        = g_signal_connect (context, "error",
+		  			      G_CALLBACK (gdict_window_error_cb),
+					      window);
+
+  window->context = context;
+}
+
+static void
+gdict_window_set_source_name (GdictWindow *window,
+			      const gchar *source_name)
+{
+  GdictContext *context;
+
+  if (window->source_name && source_name &&
+      strcmp (window->source_name, source_name) == 0)
+    return;
+
+  g_free (window->source_name);
+
+  if (source_name != NULL && *source_name != '\0')
+    window->source_name = g_strdup (source_name);
+  else
+    window->source_name = g_settings_get_string (window->settings, GDICT_SETTINGS_SOURCE_KEY);
+
+  context = get_context_from_loader (window);
+  gdict_window_set_context (window, context);
+
+  if (window->source_chooser)
+    gdict_source_chooser_set_current_source (GDICT_SOURCE_CHOOSER (window->source_chooser),
+                                             window->source_name);
+
+  g_object_notify_by_pspec (G_OBJECT (window), gdict_window_properties[PROP_SOURCE_NAME]);
+}
+
+static void
+gdict_window_set_property (GObject      *object,
+			   guint         prop_id,
+			   const GValue *value,
+			   GParamSpec   *pspec)
+{
+  GdictWindow *window = GDICT_WINDOW (object);
+
+  switch (prop_id)
+    {
+    case PROP_ACTION:
+      window->action = g_value_get_enum (value);
+      break;
+    case PROP_SOURCE_LOADER:
+      if (window->loader)
+        g_object_unref (window->loader);
+      window->loader = g_value_get_object (value);
+      g_object_ref (window->loader);
+      break;
+    case PROP_SOURCE_NAME:
+      gdict_window_set_source_name (window, g_value_get_string (value));
+      break;
+    case PROP_DATABASE:
+      gdict_window_set_database (window, g_value_get_string (value));
+      break;
+    case PROP_STRATEGY:
+      gdict_window_set_strategy (window, g_value_get_string (value));
+      break;
+    case PROP_WORD:
+      gdict_window_set_word (window, g_value_get_string (value), NULL);
+      break;
+    case PROP_PRINT_FONT:
+      gdict_window_set_print_font (window, g_value_get_string (value));
+      break;
+    case PROP_DEFBOX_FONT:
+      gdict_window_set_defbox_font (window, g_value_get_string (value));
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+gdict_window_get_property (GObject    *object,
+			   guint       prop_id,
+			   GValue     *value,
+			   GParamSpec *pspec)
+{
+  GdictWindow *window = GDICT_WINDOW (object);
+
+  switch (prop_id)
+    {
+    case PROP_ACTION:
+      g_value_set_enum (value, window->action);
+      break;
+    case PROP_SOURCE_LOADER:
+      g_value_set_object (value, window->loader);
+      break;
+    case PROP_SOURCE_NAME:
+      g_value_set_string (value, window->source_name);
+      break;
+    case PROP_DATABASE:
+      g_value_set_string (value, window->database);
+      break;
+    case PROP_STRATEGY:
+      g_value_set_string (value, window->strategy);
+      break;
+    case PROP_WORD:
+      g_value_set_string (value, window->word);
+      break;
+    case PROP_PRINT_FONT:
+      g_value_set_string (value, window->print_font);
+      break;
+    case PROP_DEFBOX_FONT:
+      g_value_set_string (value, window->defbox_font);
+      break;
+    case PROP_WINDOW_ID:
+      g_value_set_uint (value, window->window_id);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+gdict_window_store_state (GdictWindow *window)
+{
+  gchar *state_dir, *state_file;
+  GKeyFile *state_key;
+  gchar *data;
+  gsize data_len;
+  GError *error;
+  const gchar *page_id;
+
+  state_dir = g_build_filename (g_get_user_config_dir (),
+                                "mate",
+                                "mate-dictionary",
+                                NULL);
+
+  if (g_mkdir (state_dir, 0700) == -1)
+    {
+      if (errno != EEXIST)
+        {
+          g_warning ("Unable to create a cache directory: %s", g_strerror (errno));
+          g_free (state_dir);
+          return;
+        }
+    }
+
+  state_file = g_build_filename (state_dir, "window.ini", NULL);
+  state_key = g_key_file_new ();
+
+  /* store the default size of the window and its state, so that
+   * it's picked up by newly created windows
+   */
+  g_key_file_set_integer (state_key, "WindowState", "Width", window->current_width);
+  g_key_file_set_integer (state_key, "WindowState", "Height", window->current_height);
+  g_key_file_set_boolean (state_key, "WindowState", "IsMaximized", window->is_maximized);
+  g_key_file_set_boolean (state_key, "WindowState", "SidebarVisible", window->sidebar_visible);
+  g_key_file_set_boolean (state_key, "WindowState", "StatusbarVisible", window->statusbar_visible);
+  g_key_file_set_integer (state_key, "WindowState", "SidebarWidth", window->sidebar_width);
+
+  page_id = gdict_sidebar_current_page (GDICT_SIDEBAR (window->sidebar));
+  if (page_id == NULL)
+    page_id = GDICT_SIDEBAR_SPELLER_PAGE;
+
+  g_key_file_set_string (state_key, "WindowState", "SidebarPage", page_id);
+
+  error = NULL;
+  data = g_key_file_to_data (state_key, &data_len, &error);
+  if (error != NULL)
+    {
+      g_warning ("Unable to create the window state file: %s", error->message);
+      g_error_free (error);
+    }
+  else
+    {
+      g_file_set_contents (state_file, data, data_len, &error);
+      if (error != NULL)
+        {
+          g_warning ("Unable to write the window state file: %s", error->message);
+          g_error_free (error);
+        }
+
+      g_free (data);
+    }
+
+  g_key_file_free (state_key);
+  g_free (state_file);
+  g_free (state_dir);
+}
+
+static void
+gdict_window_load_state (GdictWindow *window)
+{
+  gchar *state_file;
+  GKeyFile *state_key;
+  GError *error;
+
+  state_file = g_build_filename (g_get_user_config_dir (),
+                                 "mate",
+                                 "mate-dictionary",
+                                 "window.ini",
+                                 NULL);
+  state_key = g_key_file_new ();
+
+  error = NULL;
+  g_key_file_load_from_file (state_key, state_file, 0, &error);
+  if (error != NULL)
+    {
+      g_warning ("Unable to load the window state file: %s", error->message);
+      g_error_free (error);
+      g_key_file_free (state_key);
+      g_free (state_file);
+      return;
+    }
+
+  window->default_width = g_key_file_get_integer (state_key, "WindowState", "Width", &error);
+  if (error != NULL)
+    {
+      g_clear_error (&error);
+      window->default_width = -1;
+    }
+
+  window->default_height = g_key_file_get_integer (state_key, "WindowState", "Height", &error);
+  if (error != NULL)
+    {
+      g_clear_error (&error);
+      window->default_height = -1;
+    }
+
+  window->is_maximized = (g_key_file_get_boolean (state_key, "WindowState", "IsMaximized", &error) != FALSE);
+  if (error != NULL)
+    {
+      g_clear_error (&error);
+      window->is_maximized = FALSE;
+    }
+
+  window->sidebar_visible = (g_key_file_get_boolean (state_key, "WindowState", "SidebarVisible", &error) != FALSE);
+  if (error != NULL)
+    {
+      g_clear_error (&error);
+      window->sidebar_visible = FALSE;
+    }
+
+  window->statusbar_visible = (g_key_file_get_boolean (state_key, "WindowState", "StatusbarVisible", &error) != FALSE);
+  if (error != NULL)
+    {
+      g_clear_error (&error);
+      window->statusbar_visible = FALSE;
+    }
+
+  window->sidebar_width = g_key_file_get_integer (state_key, "WindowState", "SidebarWidth", &error);
+  if (error != NULL)
+    {
+      g_clear_error (&error);
+      window->sidebar_width = -1;
+    }
+
+  window->sidebar_page = g_key_file_get_string (state_key, "WindowState", "SidebarPage", &error);
+  if (error != NULL)
+    {
+      g_clear_error (&error);
+      window->sidebar_page = NULL;
+    }
+
+  g_key_file_free (state_key);
+  g_free (state_file);
+}
+
+static void
+gdict_window_cmd_file_new (GSimpleAction *action,
+                           GVariant      *parameter,
+                           gpointer       user_data)
+{
+  GdictWindow *window = user_data;
+  GtkWidget *new_window;
+  gchar *word = NULL;
+
+  gdict_window_store_state (window);
+
+  word = gdict_defbox_get_selected_word (GDICT_DEFBOX (window->defbox));
+  if (word)
+    {
+      new_window = gdict_window_new (GDICT_WINDOW_ACTION_LOOKUP,
+                                     window->loader,
+                                     NULL, word);
+      g_free (word);
+    }
+  else
+    new_window = gdict_window_new (GDICT_WINDOW_ACTION_CLEAR,
+                                   window->loader,
+                                   NULL, NULL);
+
+  gtk_widget_show (new_window);
+
+  g_signal_emit (window, gdict_window_signals[CREATED], 0, new_window);
+}
+
+static void
+gdict_window_cmd_save_as (GSimpleAction *action,
+                          GVariant      *parameter,
+                          gpointer       user_data)
+{
+  GdictWindow *window = user_data;
+  GtkWidget *dialog;
+
+  g_assert (GDICT_IS_WINDOW (window));
+
+  dialog = gtk_file_chooser_dialog_new (_("Save a Copy"),
+  					GTK_WINDOW (window),
+  					GTK_FILE_CHOOSER_ACTION_SAVE,
+  					"gtk-cancel", GTK_RESPONSE_CANCEL,
+  					"gtk-save", GTK_RESPONSE_ACCEPT,
+  					NULL);
+  gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE);
+
+  /* default to user's home */
+  gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), g_get_home_dir ());
+  gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), _("Untitled document"));
+
+  if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
+    {
+      gchar *filename;
+      gchar *text;
+      gsize len;
+      GError *write_error = NULL;
+
+      filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
+
+      text = gdict_defbox_get_text (GDICT_DEFBOX (window->defbox), &len);
+
+      g_file_set_contents (filename,
+      			   text,
+      			   len,
+      			   &write_error);
+      if (write_error)
+        {
+          gchar *message;
+
+          message = g_strdup_printf (_("Error while writing to '%s'"), filename);
+
+          gdict_show_gerror_dialog (GTK_WINDOW (window),
+                                    message,
+                                    write_error);
+
+          g_free (message);
+        }
+
+      g_free (text);
+      g_free (filename);
+    }
+
+  gtk_widget_destroy (dialog);
+}
+
+static void
+gdict_window_cmd_file_preview (GSimpleAction *action,
+                               GVariant      *parameter,
+                               gpointer       user_data)
+{
+  GdictWindow *window = user_data;
+  g_assert (GDICT_IS_WINDOW (window));
+
+  gdict_show_print_preview (GTK_WINDOW (window),
+                            GDICT_DEFBOX (window->defbox));
+}
+
+static void
+gdict_window_cmd_file_print (GSimpleAction *action,
+                             GVariant      *parameter,
+                             gpointer       user_data)
+{
+  GdictWindow *window = user_data;
+  g_assert (GDICT_IS_WINDOW (window));
+
+  gdict_show_print_dialog (GTK_WINDOW (window),
+  			   GDICT_DEFBOX (window->defbox));
+}
+
+static void
+gdict_window_cmd_file_close_window (GSimpleAction *action,<--- Parameter 'action' can be declared as pointer to const
+                                    GVariant      *parameter,
+                                    gpointer       user_data)
+{
+  GdictWindow *window = user_data;
+  g_assert (GDICT_IS_WINDOW (window));
+
+  gdict_window_store_state (window);
+
+  /* if this was called from the uimanager, destroy the widget;
+   * otherwise, if it was called from the delete_event, the widget
+   * will destroy itself.
+   */
+  if (action)
+    gtk_widget_destroy (GTK_WIDGET (window));
+}
+
+static void
+gdict_window_cmd_edit_copy (GSimpleAction *action,
+                            GVariant      *parameter,
+                            gpointer       user_data)
+{
+  GdictWindow *window = user_data;
+  g_assert (GDICT_IS_WINDOW (window));
+
+  if (gtk_widget_has_focus (window->entry))
+    gtk_editable_copy_clipboard (GTK_EDITABLE (window->entry));
+  else
+    gdict_defbox_copy_to_clipboard (GDICT_DEFBOX (window->defbox),
+                                    gtk_clipboard_get (GDK_SELECTION_CLIPBOARD));
+}
+
+static void
+gdict_window_cmd_edit_select_all (GSimpleAction *action,
+                                  GVariant      *parameter,
+                                  gpointer       user_data)
+{
+  GdictWindow *window = user_data;
+  g_assert (GDICT_IS_WINDOW (window));
+
+  if (gtk_widget_has_focus (window->entry))
+    gtk_editable_select_region (GTK_EDITABLE (window->entry), 0, -1);
+  else
+    gdict_defbox_select_all (GDICT_DEFBOX (window->defbox));
+}
+
+static void
+gdict_window_cmd_edit_find (GSimpleAction *action,
+                            GVariant      *parameter,
+                            gpointer       user_data)
+{
+  GdictWindow *window = user_data;
+  g_assert (GDICT_IS_WINDOW (window));
+  gdict_defbox_set_show_find (GDICT_DEFBOX (window->defbox), TRUE);
+}
+
+static void
+gdict_window_cmd_edit_find_next (GSimpleAction *action,
+                                 GVariant      *parameter,
+                                 gpointer       user_data)
+{
+  GdictWindow *window = user_data;
+  g_assert (GDICT_IS_WINDOW (window));
+
+  gdict_defbox_find_next (GDICT_DEFBOX (window->defbox));
+}
+
+static void
+gdict_window_cmd_edit_find_previous (GSimpleAction *action,
+                                     GVariant      *parameter,
+                                     gpointer       user_data)
+{
+  GdictWindow *window = user_data;
+  g_assert (GDICT_IS_WINDOW (window));
+
+  gdict_defbox_find_previous (GDICT_DEFBOX (window->defbox));
+}
+
+static void
+gdict_window_cmd_edit_preferences (GSimpleAction *action,
+                                   GVariant      *parameter,
+                                   gpointer       user_data)
+{
+  GdictWindow *window = user_data;
+  g_assert (GDICT_IS_WINDOW (window));
+
+  gdict_show_pref_dialog (GTK_WIDGET (window),
+  			  _("Dictionary Preferences"),
+  			  window->loader);
+}
+
+static void
+sidebar_activate_toggle (GSimpleAction *action,
+                         GVariant      *parameter,
+                         gpointer       user_data)
+{
+  GVariant *state;
+
+  state = g_action_get_state (G_ACTION (action));
+  g_action_change_state (G_ACTION (action), g_variant_new_boolean (!g_variant_get_boolean (state)));
+  g_variant_unref (state);
+}
+
+static void
+statusbar_activate_toggle (GSimpleAction *action,
+                           GVariant      *parameter,
+                           gpointer       user_data)
+{
+  GVariant *state;
+
+  state = g_action_get_state (G_ACTION (action));
+  g_action_change_state (G_ACTION (action), g_variant_new_boolean (!g_variant_get_boolean (state)));
+  g_variant_unref (state);
+}
+
+static void
+gdict_window_cmd_view_sidebar (GSimpleAction *action,
+                               GVariant      *state,
+                               gpointer       user_data)
+{
+  GdictWindow *window = user_data;
+  g_assert (GDICT_IS_WINDOW (window));
+
+  g_variant_get_boolean (state);
+  window->sidebar_visible = (g_variant_get_boolean (state) != FALSE);
+  g_simple_action_set_state (action, state);
+
+  if (window->sidebar_visible)
+    gtk_widget_show (window->sidebar_frame);
+  else
+    gtk_widget_hide (window->sidebar_frame);
+}
+
+static void
+gdict_window_cmd_view_statusbar (GSimpleAction *action,
+                                 GVariant      *state,
+                                 gpointer       user_data)
+{
+  GdictWindow *window = user_data;
+  g_assert (GDICT_IS_WINDOW (window));
+
+  window->statusbar_visible = (g_variant_get_boolean (state) != FALSE);
+  g_simple_action_set_state (action, state);
+
+  if (window->statusbar_visible)
+    gtk_widget_show (window->status);
+  else
+    gtk_widget_hide (window->status);
+
+}
+
+static void
+gdict_window_cmd_view_speller (GSimpleAction *action,
+                               GVariant      *parameter,
+                               gpointer       user_data)
+
+{
+  GdictWindow *window = user_data;
+  g_assert (GDICT_IS_WINDOW (window));
+
+  gdict_sidebar_view_page (GDICT_SIDEBAR (window->sidebar),
+                           GDICT_SIDEBAR_SPELLER_PAGE);
+  gdict_window_set_sidebar_visible (window, TRUE);
+}
+
+static void
+gdict_window_cmd_view_databases (GSimpleAction *action,
+                                 GVariant      *parameter,
+                                 gpointer       user_data)
+
+{
+  GdictWindow *window = user_data;
+  g_assert (GDICT_IS_WINDOW (window));
+
+  gdict_sidebar_view_page (GDICT_SIDEBAR (window->sidebar),
+                           GDICT_SIDEBAR_DATABASES_PAGE);
+  gdict_window_set_sidebar_visible (window, TRUE);
+}
+
+static void
+gdict_window_cmd_view_strategies (GSimpleAction *action,
+                                  GVariant      *parameter,
+                                  gpointer       user_data)
+
+{
+  GdictWindow *window = user_data;
+  g_assert (GDICT_IS_WINDOW (window));
+
+  gdict_sidebar_view_page (GDICT_SIDEBAR (window->sidebar),
+                           GDICT_SIDEBAR_STRATEGIES_PAGE);
+  gdict_window_set_sidebar_visible (window, TRUE);
+}
+
+static void
+gdict_window_cmd_view_sources (GSimpleAction *action,
+                               GVariant      *parameter,
+                               gpointer       user_data)
+
+{
+  GdictWindow *window = user_data;
+  g_assert (GDICT_IS_WINDOW (window));
+
+  gdict_sidebar_view_page (GDICT_SIDEBAR (window->sidebar),
+                           GDICT_SIDEBAR_SOURCES_PAGE);
+  gdict_window_set_sidebar_visible (window, TRUE);
+}
+
+static void
+gdict_window_cmd_go_first_def (GSimpleAction *action,
+                               GVariant      *parameter,
+                               gpointer       user_data)
+{
+  GdictWindow *window = user_data;
+  g_assert (GDICT_IS_WINDOW (window));
+
+  window->last_definition = 0;
+  gdict_defbox_jump_to_definition (GDICT_DEFBOX (window->defbox),
+                                   window->last_definition);
+}
+
+static void
+gdict_window_cmd_go_previous_def (GSimpleAction *action,
+                                  GVariant      *parameter,
+                                  gpointer       user_data)
+{
+  GdictWindow *window = user_data;
+  g_assert (GDICT_IS_WINDOW (window));
+
+  if (window->last_definition == 0)
+    return;
+
+  window->last_definition -= 1;
+  gdict_defbox_jump_to_definition (GDICT_DEFBOX (window->defbox),
+                                   window->last_definition);
+}
+
+static void
+gdict_window_cmd_go_next_def (GSimpleAction *action,
+                              GVariant      *parameter,
+                              gpointer       user_data)
+{
+  GdictWindow *window = user_data;
+  g_assert (GDICT_IS_WINDOW (window));
+
+  if (window->max_definition == -1)
+    window->max_definition = gdict_defbox_count_definitions (GDICT_DEFBOX (window->defbox)) - 1;
+
+  if (window->last_definition == window->max_definition)
+    return;
+
+  window->last_definition += 1;
+  gdict_defbox_jump_to_definition (GDICT_DEFBOX (window->defbox),
+                                   window->last_definition);
+}
+
+static void
+gdict_window_cmd_go_last_def (GSimpleAction *action,
+                              GVariant      *parameter,
+                              gpointer       user_data)
+{
+  GdictWindow *window = user_data;
+  g_assert (GDICT_IS_WINDOW (window));
+
+  if (window->max_definition == -1)
+    window->last_definition = gdict_defbox_count_definitions (GDICT_DEFBOX (window->defbox)) - 1;
+
+  window->last_definition = window->max_definition;
+  gdict_defbox_jump_to_definition (GDICT_DEFBOX (window->defbox),
+                                   window->last_definition);
+}
+
+static void
+gdict_window_cmd_help_contents (GSimpleAction *action,
+                                GVariant      *parameter,
+                                gpointer       user_data)
+
+{
+  GdictWindow *window = user_data;
+  GError *err = NULL;
+
+  g_return_if_fail (GDICT_IS_WINDOW (window));
+
+  gtk_show_uri_on_window (GTK_WINDOW (window),
+                "help:mate-dictionary",
+                gtk_get_current_event_time (), &err);
+  if (err)
+    {
+      gdict_show_gerror_dialog (GTK_WINDOW (window),
+      		                _("There was an error while displaying help"),
+      			        err);
+    }
+}
+
+static void
+gdict_window_cmd_help_about (GSimpleAction *action,
+                             GVariant      *parameter,
+                             gpointer       user_data)
+
+{
+  GdictWindow *window = user_data;
+  g_assert (GDICT_IS_WINDOW (window));
+
+  gdict_show_about_dialog (GTK_WIDGET (window));
+}
+
+static void
+gdict_window_cmd_lookup (gpointer user_data)
+
+{
+  GdictWindow *window = user_data;
+  g_assert (GDICT_IS_WINDOW (window));
+
+  gtk_widget_grab_focus (window->entry);
+}
+
+static void
+gdict_window_cmd_escape (gpointer user_data)
+
+{
+  GdictWindow *window = user_data;
+  g_assert (GDICT_IS_WINDOW (window));
+
+  gdict_defbox_set_show_find (GDICT_DEFBOX (window->defbox), FALSE);
+}
+
+static void
+gdict_window_cmd_slash (gpointer user_data)
+{
+  GdictWindow *window = user_data;
+  g_assert (GDICT_IS_WINDOW (window));
+
+  gdict_defbox_set_show_find (GDICT_DEFBOX (window->defbox), TRUE);
+}
+
+static const GActionEntry entries[] =
+{
+  /* File menu */
+  { "FileNew",     gdict_window_cmd_file_new, NULL, NULL, NULL },
+  { "FileSaveAs",  gdict_window_cmd_save_as, NULL, NULL, NULL },
+  { "FilePreview", gdict_window_cmd_file_preview, NULL, NULL, NULL },
+  { "FilePrint",   gdict_window_cmd_file_print, NULL, NULL, NULL },
+  { "FileCloseWindow", gdict_window_cmd_file_close_window, NULL, NULL, NULL },
+
+  /* Edit menu */
+  { "EditCopy",      gdict_window_cmd_edit_copy, NULL, NULL, NULL },
+  { "EditSelectAll", gdict_window_cmd_edit_select_all, NULL, NULL, NULL },
+  { "EditFind",      gdict_window_cmd_edit_find, NULL, NULL, NULL },
+  { "EditFindNext",  gdict_window_cmd_edit_find_next, NULL, NULL, NULL },
+  { "EditFindPrevious", gdict_window_cmd_edit_find_previous, NULL, NULL, NULL },
+  { "EditPreferences", gdict_window_cmd_edit_preferences, NULL, NULL, NULL },
+
+  /* Go menu */
+  { "GoPreviousDef", gdict_window_cmd_go_previous_def, NULL, NULL, NULL },
+  { "GoNextDef",  gdict_window_cmd_go_next_def, NULL, NULL, NULL },
+  { "GoFirstDef", gdict_window_cmd_go_first_def, NULL, NULL, NULL },
+  { "GoLastDef",  gdict_window_cmd_go_last_def, NULL, NULL, NULL },
+
+  /* View menu */
+  { "ViewSidebar",   sidebar_activate_toggle, NULL, "false", gdict_window_cmd_view_sidebar },
+  { "ViewStatusbar", statusbar_activate_toggle, NULL, "false", gdict_window_cmd_view_statusbar },
+  { "ViewSpeller", gdict_window_cmd_view_speller, NULL, NULL, NULL },
+  { "ViewSource", gdict_window_cmd_view_sources, NULL, NULL, NULL },
+  { "ViewDB", gdict_window_cmd_view_databases, NULL, NULL, NULL },
+  { "ViewStrat", gdict_window_cmd_view_strategies, NULL, NULL, NULL },
+
+  /* Help menu */
+  { "HelpContents", gdict_window_cmd_help_contents, NULL, NULL, NULL },
+  { "HelpAbout", gdict_window_cmd_help_about, NULL, NULL, NULL },
+};
+
+static const struct {
+  guint keyval;
+  GdkModifierType modifier;
+  const gchar *widget_id;
+} menu_keybindings [] = {
+  { GDK_KEY_N,      GDK_CONTROL_MASK, "new_item" },
+  { GDK_KEY_S,      GDK_SHIFT_MASK | GDK_CONTROL_MASK, "preview_item" },
+  { GDK_KEY_P,      GDK_CONTROL_MASK, "print_item" },
+  { GDK_KEY_W,      GDK_CONTROL_MASK, "close_item" },
+  { GDK_KEY_C,      GDK_CONTROL_MASK, "copy_item" },
+  { GDK_KEY_A,      GDK_CONTROL_MASK, "select_item" },
+  { GDK_KEY_F,      GDK_CONTROL_MASK, "find_item" },
+  { GDK_KEY_G,      GDK_CONTROL_MASK, "find_next_item" },
+  { GDK_KEY_G,      GDK_SHIFT_MASK | GDK_CONTROL_MASK, "find_previous_item" },
+  { GDK_KEY_Page_Up,   GDK_CONTROL_MASK, "go_up_item" },
+  { GDK_KEY_Page_Down, GDK_CONTROL_MASK, "go_down_item" },
+  { GDK_KEY_Home,      GDK_CONTROL_MASK, "go_home_item" },
+  { GDK_KEY_End,       GDK_CONTROL_MASK, "go_end_item" },
+  { GDK_KEY_F9,     0, "side_item" },
+  { GDK_KEY_T,      GDK_CONTROL_MASK, "speller_item" },
+  { GDK_KEY_D,      GDK_CONTROL_MASK, "sources_item" },
+  { GDK_KEY_B,      GDK_CONTROL_MASK, "db_item" },
+  { GDK_KEY_R,      GDK_CONTROL_MASK, "strategies_item" },
+  { GDK_KEY_F1,     0, "help_item" }
+};
+
+static gboolean
+gdict_window_delete_event_cb (GtkWidget *widget,
+			      GdkEvent  *event,
+			      gpointer   user_data)
+{
+  gdict_window_cmd_file_close_window (NULL, NULL, GDICT_WINDOW (widget));
+
+  return FALSE;
+}
+
+static gboolean
+gdict_window_state_event_cb (GtkWidget           *widget,
+			     GdkEventWindowState *event,
+			     gpointer             user_data)
+{
+  GdictWindow *window = GDICT_WINDOW (widget);
+
+  if (event->new_window_state & GDK_WINDOW_STATE_MAXIMIZED)
+    window->is_maximized = TRUE;
+  else
+    window->is_maximized = FALSE;
+
+  return FALSE;
+}
+
+static void
+lookup_word (GdictWindow *window,
+             gpointer     dummy)
+{
+  const gchar *entry_text;
+  gchar *word;
+
+  g_assert (GDICT_IS_WINDOW (window));
+
+  if (!window->context)
+    return;
+
+  entry_text = gtk_entry_get_text (GTK_ENTRY (window->entry));
+  if (!entry_text || *entry_text == '\0')
+    return;
+
+  word = g_strdup (entry_text);
+  gdict_window_set_word (window, g_strstrip (word), NULL);
+
+  g_free (word);
+}
+
+static void
+source_activated_cb (GdictSourceChooser *chooser,
+                     const gchar        *source_name,
+                     GdictSource        *source,
+                     GdictWindow        *window)
+{
+  g_signal_handlers_block_by_func (chooser, source_activated_cb, window);
+  gdict_window_set_source_name (window, source_name);
+  g_signal_handlers_unblock_by_func (chooser, source_activated_cb, window);
+
+  if (window->status && window->statusbar_visible)
+    {
+      gchar *message;
+
+      message = g_strdup_printf (_("Dictionary source `%s' selected"),
+                                 gdict_source_get_description (source));
+      gtk_statusbar_push (GTK_STATUSBAR (window->status), 0, message);
+      g_free (message);
+    }
+}
+
+static void
+strategy_activated_cb (GdictStrategyChooser *chooser,
+                       const gchar          *strat_name,
+                       const gchar          *strat_desc,
+                       GdictWindow          *window)
+{
+  g_signal_handlers_block_by_func (chooser, strategy_activated_cb, window);
+  gdict_window_set_strategy (window, strat_name);
+  g_signal_handlers_unblock_by_func (chooser, strategy_activated_cb, window);
+
+  if (window->status && window->statusbar_visible)
+    {
+      gchar *message;
+
+      message = g_strdup_printf (_("Strategy `%s' selected"), strat_desc);
+      gtk_statusbar_push (GTK_STATUSBAR (window->status), 0, message);
+      g_free (message);
+    }
+}
+
+static void
+database_activated_cb (GdictDatabaseChooser *chooser,
+		       const gchar          *db_name,
+		       const gchar          *db_desc,
+		       GdictWindow          *window)
+{
+  g_signal_handlers_block_by_func (chooser, database_activated_cb, window);
+  gdict_window_set_database (window, db_name);
+  g_signal_handlers_unblock_by_func (chooser, database_activated_cb, window);
+
+  if (window->status && window->statusbar_visible)
+    {
+      gchar *message;
+
+      message = g_strdup_printf (_("Database `%s' selected"), db_desc);
+      gtk_statusbar_push (GTK_STATUSBAR (window->status), 0, message);
+      g_free (message);
+    }
+}
+
+static void
+speller_word_activated_cb (GdictSpeller *speller,
+			   const gchar  *word,
+			   const gchar  *db_name,
+			   GdictWindow  *window)
+{
+  gtk_entry_set_text (GTK_ENTRY (window->entry), word);
+
+  gdict_window_set_word (window, word, db_name);
+
+  if (window->status && window->statusbar_visible)
+    {
+      gchar *message;
+
+      message = g_strdup_printf (_("Word `%s' selected"), word);
+      gtk_statusbar_push (GTK_STATUSBAR (window->status), 0, message);
+      g_free (message);
+    }
+}
+
+static void
+sidebar_page_changed_cb (GdictSidebar *sidebar,
+			 GdictWindow  *window)
+{
+  const gchar *page_id;
+  const gchar *message;
+
+  page_id = gdict_sidebar_current_page (sidebar);
+
+  g_free (window->sidebar_page);
+  window->sidebar_page = g_strdup (page_id);
+
+  switch (page_id[0])
+    {
+    case 's':
+      {
+      switch (page_id[1])
+        {
+        case 'p': /* speller */
+          message = _("Double-click on the word to look up");
+          if (window->word)
+            gdict_speller_match (GDICT_SPELLER (window->speller),
+                                 window->word);
+          break;
+        case 't': /* strat-chooser */
+          message = _("Double-click on the matching strategy to use");
+
+          gdict_strategy_chooser_refresh (GDICT_STRATEGY_CHOOSER (window->strat_chooser));
+          break;
+        case 'o': /* source-chooser */
+          message = _("Double-click on the source to use");
+          gdict_source_chooser_refresh (GDICT_SOURCE_CHOOSER (window->source_chooser));
+          break;
+        default:
+          message = NULL;
+        }
+      }
+      break;
+    case 'd': /* db-chooser */
+      message = _("Double-click on the database to use");
+
+      gdict_database_chooser_refresh (GDICT_DATABASE_CHOOSER (window->db_chooser));
+      break;
+    default:
+      message = NULL;
+      break;
+    }
+
+  if (message && window->status && window->statusbar_visible)
+    gtk_statusbar_push (GTK_STATUSBAR (window->status), 0, message);
+}
+
+static void
+sidebar_closed_cb (GdictSidebar *sidebar,
+		   GdictWindow  *window)
+{
+  gdict_window_set_sidebar_visible (window, FALSE);
+}
+
+static void
+gdict_window_link_clicked (GdictDefbox *defbox,
+                           const gchar *link_text,
+                           GdictWindow *window)
+{
+  GtkWidget *new_window;
+
+  gdict_window_store_state (window);
+
+  new_window = gdict_window_new (GDICT_WINDOW_ACTION_LOOKUP,
+                                 window->loader,
+                                 NULL, link_text);
+  gtk_widget_show (new_window);
+
+  g_signal_emit (window, gdict_window_signals[CREATED], 0, new_window);
+}
+
+static void
+gdict_window_drag_data_received_cb (GtkWidget        *widget,
+				    GdkDragContext   *context,
+				    gint              x,
+				    gint              y,
+				    GtkSelectionData *data,
+				    guint             info,
+				    guint             time_,
+				    gpointer          user_data)
+{
+  GdictWindow *window = GDICT_WINDOW (user_data);
+  gchar *text;
+
+  text = (gchar *) gtk_selection_data_get_text (data);
+  if (text)
+    {
+      gtk_entry_set_text (GTK_ENTRY (window->entry), text);
+
+      gdict_window_set_word (window, text, NULL);
+      g_free (text);
+
+      gtk_drag_finish (context, TRUE, FALSE, time_);
+    }
+  else
+    gtk_drag_finish (context, FALSE, FALSE, time_);
+}
+
+static void
+gdict_window_size_allocate (GtkWidget     *widget,
+			    GtkAllocation *allocation)
+{
+  GdictWindow *window = GDICT_WINDOW (widget);
+
+  if (!window->is_maximized)
+    {
+      window->current_width = allocation->width;
+      window->current_height = allocation->height;
+    }
+
+  if (GTK_WIDGET_CLASS (gdict_window_parent_class)->size_allocate)
+    GTK_WIDGET_CLASS (gdict_window_parent_class)->size_allocate (widget,
+		    						 allocation);
+}
+
+static void
+gdict_window_handle_notify_position_cb (GtkWidget  *widget,
+					GParamSpec *pspec,
+					gpointer    user_data)
+{
+  GdictWindow *window = GDICT_WINDOW (user_data);
+  gint window_width, pos;
+  GtkAllocation allocation;
+
+  pos = gtk_paned_get_position (GTK_PANED (widget));
+  gtk_widget_get_allocation (GTK_WIDGET (window), &allocation);
+  window_width = allocation.width;
+
+  window->sidebar_width = window_width - pos;
+}
+
+static GObject *
+gdict_window_constructor (GType                  type,
+			  guint                  n_construct_properties,
+			  GObjectConstructParam *construct_params)
+{
+  GObject *object;
+  GdictWindow *window;
+  GtkWidget *hbox;
+  GtkWidget *handle;
+  GtkWidget *frame1, *frame2;
+  GtkWidget *vbox;
+  GtkWidget *button;
+  GtkWidget *item;
+  GActionGroup *action_group;
+  GtkAccelGroup *accel_group;
+  PangoFontDescription *font_desc;
+  gchar *font_name;
+  GError *error;
+  GtkAllocation allocation;
+  GClosure *lookup, *escape, *slash;
+  int i;
+
+  object = G_OBJECT_CLASS (gdict_window_parent_class)->constructor (type, n_construct_properties, construct_params);
+  window = GDICT_WINDOW (object);
+
+  window->in_construction = TRUE;
+
+  /* recover the state */
+  gdict_window_load_state (window);
+
+  window->main_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
+  gtk_container_add (GTK_CONTAINER (window), window->main_box);
+  gtk_widget_show (window->main_box);
+
+  /* build menus */
+  action_group = (GActionGroup*)g_simple_action_group_new ();
+  window->action_group = action_group;
+  g_action_map_add_action_entries (G_ACTION_MAP (action_group),
+                                   entries, G_N_ELEMENTS (entries),
+                                   window);
+
+  window->ui_manager = gtk_builder_new ();
+  gtk_widget_insert_action_group (GTK_WIDGET (window), "win", action_group);
+
+  accel_group = gtk_accel_group_new ();
+  gtk_window_add_accel_group (GTK_WINDOW (window), accel_group);
+
+  error = NULL;
+  if (!gtk_builder_add_from_file (window->ui_manager,
+  					PKGDATADIR "/mate-dictionary-ui.xml",
+  					&error))
+    {
+      g_warning ("Building menus failed: %s", error->message);
+      g_error_free (error);
+    }
+  else
+    {
+      window->menubar = (GtkWidget *)gtk_builder_get_object (window->ui_manager, "dictionarymenubar");
+
+      gtk_box_pack_start (GTK_BOX (window->main_box), window->menubar, FALSE, FALSE, 0);
+      gtk_widget_show (window->menubar);
+
+      gdict_window_ensure_menu_state (window);
+    }
+
+  for (i = 0; i < G_N_ELEMENTS (menu_keybindings); i++)
+  {
+    item = (GtkWidget*)gtk_builder_get_object (window->ui_manager, menu_keybindings[i].widget_id);
+    gtk_widget_add_accelerator (item, "activate", accel_group,
+                                menu_keybindings[i].keyval,
+                                menu_keybindings[i].modifier,
+                                GTK_ACCEL_VISIBLE);
+  }
+  lookup = g_cclosure_new_swap (G_CALLBACK (gdict_window_cmd_lookup), window, NULL);
+  gtk_accel_group_connect (accel_group, GDK_KEY_L, GDK_CONTROL_MASK, 0, lookup);
+
+  escape = g_cclosure_new_swap (G_CALLBACK (gdict_window_cmd_escape), window, NULL);
+  gtk_accel_group_connect (accel_group, GDK_KEY_Escape, 0, 0, escape);
+
+  slash = g_cclosure_new_swap (G_CALLBACK (gdict_window_cmd_slash), window, NULL);
+  gtk_accel_group_connect (accel_group, GDK_KEY_slash, 0, 0, slash);
+
+  vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
+  gtk_container_set_border_width (GTK_CONTAINER (vbox), 6);
+  gtk_container_add (GTK_CONTAINER (window->main_box), vbox);
+  gtk_widget_show (vbox);
+
+  hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
+  gtk_widget_show (hbox);
+
+  button = gtk_button_new_with_mnemonic (_("Look _up:"));
+  g_signal_connect_swapped (button, "clicked",
+                            G_CALLBACK (lookup_word),
+                            window);
+  gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
+  gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
+  gtk_widget_show (button);
+
+  window->completion_model = gtk_list_store_new (COMPLETION_N_COLUMNS,
+		  				 G_TYPE_STRING);
+
+  window->completion = gtk_entry_completion_new ();
+  gtk_entry_completion_set_popup_completion (window->completion, TRUE);
+  gtk_entry_completion_set_model (window->completion,
+		  		  GTK_TREE_MODEL (window->completion_model));
+  gtk_entry_completion_set_text_column (window->completion,
+		  			COMPLETION_TEXT_COLUMN);
+
+  window->entry = gtk_entry_new ();
+  if (window->word)
+    gtk_entry_set_text (GTK_ENTRY (window->entry), window->word);
+
+  gtk_entry_set_completion (GTK_ENTRY (window->entry),
+		  	    window->completion);
+  g_signal_connect_swapped (window->entry, "activate",
+                            G_CALLBACK (lookup_word),
+                            window);
+  gtk_box_pack_start (GTK_BOX (hbox), window->entry, TRUE, TRUE, 0);
+  gtk_widget_show (window->entry);
+
+  handle = gtk_paned_new (GTK_ORIENTATION_HORIZONTAL);
+  gtk_box_pack_start (GTK_BOX (vbox), handle, TRUE, TRUE, 0);
+  gtk_widget_show (handle);
+
+  frame1 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
+  frame2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
+
+  window->defbox = gdict_defbox_new ();
+  if (window->context)
+    gdict_defbox_set_context (GDICT_DEFBOX (window->defbox), window->context);
+
+  g_signal_connect (window->defbox, "link-clicked",
+                    G_CALLBACK (gdict_window_link_clicked),
+                    window);
+
+  gtk_drag_dest_set (window->defbox,
+  		     GTK_DEST_DEFAULT_ALL,
+  		     drop_types, n_drop_types,
+  		     GDK_ACTION_COPY);
+  g_signal_connect (window->defbox, "drag-data-received",
+  		    G_CALLBACK (gdict_window_drag_data_received_cb),
+  		    window);
+  gtk_container_add (GTK_CONTAINER (frame1), window->defbox);
+  gtk_widget_show (window->defbox);
+
+  /* Sidebar */
+  window->sidebar = gdict_sidebar_new ();
+  g_signal_connect (window->sidebar, "page-changed",
+		    G_CALLBACK (sidebar_page_changed_cb),
+		    window);
+  g_signal_connect (window->sidebar, "closed",
+		    G_CALLBACK (sidebar_closed_cb),
+		    window);
+  gtk_widget_show (window->sidebar);
+
+  /* Speller */
+  window->speller = gdict_speller_new ();
+  if (window->context)
+    gdict_speller_set_context (GDICT_SPELLER (window->speller),
+		    	       window->context);
+  g_signal_connect (window->speller, "word-activated",
+		    G_CALLBACK (speller_word_activated_cb),
+		    window);
+  gdict_sidebar_add_page (GDICT_SIDEBAR (window->sidebar),
+		          GDICT_SIDEBAR_SPELLER_PAGE,
+			  _("Similar words"),
+			  window->speller);
+  gtk_widget_show (window->speller);
+
+  /* Database chooser */
+  if (window->context)
+    gdict_database_chooser_set_context (GDICT_DATABASE_CHOOSER (window->db_chooser),
+			    		window->context);
+  g_signal_connect (window->db_chooser, "database-activated",
+	  	    G_CALLBACK (database_activated_cb),
+		    window);
+  gdict_sidebar_add_page (GDICT_SIDEBAR (window->sidebar),
+	  		  GDICT_SIDEBAR_DATABASES_PAGE,
+			  _("Available dictionaries"),
+			  window->db_chooser);
+  gtk_widget_show (window->db_chooser);
+
+  /* bind the database property to the database setting */
+  g_settings_bind (window->settings, GDICT_SETTINGS_DATABASE_KEY,
+                   window, "database",
+                   G_SETTINGS_BIND_DEFAULT);
+
+  /* Strategy chooser */
+  if (window->context)
+    gdict_strategy_chooser_set_context (GDICT_STRATEGY_CHOOSER (window->strat_chooser),
+                                        window->context);
+  g_signal_connect (window->strat_chooser, "strategy-activated",
+                    G_CALLBACK (strategy_activated_cb),
+                    window);
+  gdict_sidebar_add_page (GDICT_SIDEBAR (window->sidebar),
+                          GDICT_SIDEBAR_STRATEGIES_PAGE,
+                          _("Available strategies"),
+                          window->strat_chooser);
+  gtk_widget_show (window->strat_chooser);
+
+  /* bind the strategy property to the strategy setting */
+  g_settings_bind (window->settings, GDICT_SETTINGS_STRATEGY_KEY,
+                   window, "strategy",
+                   G_SETTINGS_BIND_DEFAULT);
+
+  /* Source chooser */
+  window->source_chooser = gdict_source_chooser_new_with_loader (window->loader);
+  g_signal_connect (window->source_chooser, "source-activated",
+                    G_CALLBACK (source_activated_cb),
+                    window);
+  gdict_sidebar_add_page (GDICT_SIDEBAR (window->sidebar),
+                          GDICT_SIDEBAR_SOURCES_PAGE,
+                          _("Dictionary sources"),
+                          window->source_chooser);
+  gtk_widget_show (window->source_chooser);
+
+  /* bind the source-name property to the source setting */
+  g_settings_bind (window->settings, GDICT_SETTINGS_SOURCE_KEY,
+                   window, "source-name",
+                   G_SETTINGS_BIND_DEFAULT);
+
+  gtk_container_add (GTK_CONTAINER (frame2), window->sidebar);
+
+  gtk_paned_pack1 (GTK_PANED (handle), frame1, TRUE, FALSE);
+  gtk_paned_pack2 (GTK_PANED (handle), frame2, FALSE, TRUE);
+
+  window->defbox_frame = frame1;
+  window->sidebar_frame = frame2;
+
+  gtk_widget_show (window->defbox_frame);
+
+  if (window->sidebar_visible)
+    {
+      GAction *action;
+
+      action = g_action_map_lookup_action (G_ACTION_MAP (window->action_group), "ViewSidebar");
+      g_simple_action_set_state (G_SIMPLE_ACTION (action), g_variant_new_boolean (TRUE));
+      gtk_widget_show (window->sidebar_frame);
+    }
+
+  window->status = gtk_statusbar_new ();
+  gtk_box_pack_end (GTK_BOX (window->main_box), window->status, FALSE, FALSE, 0);
+  if (window->statusbar_visible)
+    {
+      GAction *action;
+
+      action = g_action_map_lookup_action (G_ACTION_MAP (window->action_group), "ViewStatusbar");
+      g_simple_action_set_state (G_SIMPLE_ACTION (action), g_variant_new_boolean (TRUE));
+      gtk_widget_show (window->status);
+    }
+
+  window->progress = gtk_progress_bar_new ();
+  gtk_box_pack_end (GTK_BOX (window->status), window->progress, FALSE, FALSE, 0);
+
+  /* retrieve the document font size */
+  font_name = g_settings_get_string (window->desktop_settings, DOCUMENT_FONT_KEY);
+  gdict_window_set_defbox_font (window, font_name);
+  font_desc = pango_font_description_from_string (font_name);
+  g_free (font_name);
+
+  g_settings_bind (window->desktop_settings, DOCUMENT_FONT_KEY,
+                   window, "defbox-font",
+                   G_SETTINGS_BIND_GET);
+
+  /* if the (width, height) tuple is not defined, use the font to
+   * calculate the right window geometry
+   */
+  if (window->default_width == -1 || window->default_height == -1)
+    {
+      gint font_size;
+      gint width, height;
+
+      font_size = pango_font_description_get_size (font_desc);
+      font_size = PANGO_PIXELS (font_size);
+
+      width = MAX (GDICT_WINDOW_COLUMNS * font_size, GDICT_WINDOW_MIN_WIDTH);
+      height = MAX (GDICT_WINDOW_ROWS * font_size, GDICT_WINDOW_MIN_HEIGHT);
+
+      window->default_width = width;
+      window->default_height = height;
+    }
+
+  pango_font_description_free (font_desc);
+
+  gtk_window_set_title (GTK_WINDOW (window), _("Dictionary"));
+  gtk_window_set_default_size (GTK_WINDOW (window),
+                               window->default_width,
+                               window->default_height);
+  if (window->is_maximized)
+    gtk_window_maximize (GTK_WINDOW (window));
+
+  gtk_widget_get_allocation (GTK_WIDGET (window), &allocation);
+  gtk_paned_set_position (GTK_PANED (handle), allocation.width - window->sidebar_width);
+  if (window->sidebar_page != NULL)
+    gdict_sidebar_view_page (GDICT_SIDEBAR (window->sidebar), window->sidebar_page);
+  else
+    gdict_sidebar_view_page (GDICT_SIDEBAR (window->sidebar), GDICT_SIDEBAR_SPELLER_PAGE);
+
+  g_signal_connect (window, "delete-event",
+		    G_CALLBACK (gdict_window_delete_event_cb),
+		    NULL);
+  g_signal_connect (window, "window-state-event",
+		    G_CALLBACK (gdict_window_state_event_cb),
+		    NULL);
+  g_signal_connect (handle, "notify::position",
+		    G_CALLBACK (gdict_window_handle_notify_position_cb),
+		    window);
+
+  gtk_widget_grab_focus (window->entry);
+
+  window->in_construction = FALSE;
+
+  return object;
+}
+
+static void
+gdict_window_class_init (GdictWindowClass *klass)
+{
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+  gdict_window_properties[PROP_ACTION] =
+    g_param_spec_enum ("action",
+                       "Action",
+                       "The default action performed by the window",
+                       GDICT_TYPE_WINDOW_ACTION,
+                       GDICT_WINDOW_ACTION_CLEAR,
+                       G_PARAM_READWRITE |
+                       G_PARAM_STATIC_STRINGS |
+                       G_PARAM_CONSTRUCT_ONLY);
+
+  gdict_window_properties[PROP_SOURCE_LOADER] =
+    g_param_spec_object ("source-loader",
+                         "Source Loader",
+                         "The GdictSourceLoader to be used to load dictionary sources",
+                         GDICT_TYPE_SOURCE_LOADER,
+                         G_PARAM_READWRITE |
+                         G_PARAM_STATIC_STRINGS |
+                         G_PARAM_CONSTRUCT_ONLY);
+
+  gdict_window_properties[PROP_SOURCE_NAME] =
+    g_param_spec_string ("source-name",
+                         "Source Name",
+                         "The name of the GdictSource to be used",
+                         GDICT_DEFAULT_SOURCE_NAME,
+                         G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+  gdict_window_properties[PROP_DATABASE] =
+    g_param_spec_string ("database",
+                         "Database",
+                         "The name of the database to search",
+                         GDICT_DEFAULT_DATABASE,
+                         G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+  gdict_window_properties[PROP_STRATEGY] =
+    g_param_spec_string ("strategy",
+                         "Strategy",
+                         "The name of the strategy",
+                         GDICT_DEFAULT_STRATEGY,
+                         G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+  gdict_window_properties[PROP_PRINT_FONT] =
+    g_param_spec_string ("print-font",
+                         "Print Font",
+                         "The font name to be used when printing",
+                         GDICT_DEFAULT_PRINT_FONT,
+                         G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+  gdict_window_properties[PROP_DEFBOX_FONT] =
+    g_param_spec_string ("defbox-font",
+                         "Defbox Font",
+                         "The font name to be used by the defbox widget",
+                         GDICT_DEFAULT_DEFBOX_FONT,
+                         G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+  gdict_window_properties[PROP_WORD] =
+    g_param_spec_string ("word",
+                         "Word",
+                         "The word to search",
+                         NULL,
+                         G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+  gdict_window_properties[PROP_WINDOW_ID] =
+    g_param_spec_uint ("window-id",
+                       "Window ID",
+                       "The unique identifier for this window",
+                       0, G_MAXUINT,
+                       0,
+                       G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
+  gdict_window_signals[CREATED] =
+    g_signal_new ("created",
+                  G_OBJECT_CLASS_TYPE (gobject_class),
+                  G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (GdictWindowClass, created),
+                  NULL, NULL,
+                  g_cclosure_marshal_VOID__OBJECT,
+                  G_TYPE_NONE, 1,
+                  GDICT_TYPE_WINDOW);
+
+  gobject_class->finalize = gdict_window_finalize;
+  gobject_class->dispose = gdict_window_dispose;
+  gobject_class->set_property = gdict_window_set_property;
+  gobject_class->get_property = gdict_window_get_property;
+  gobject_class->constructor = gdict_window_constructor;
+
+  g_object_class_install_properties (gobject_class,
+                                     LAST_PROP,
+                                     gdict_window_properties);
+
+  widget_class->size_allocate = gdict_window_size_allocate;
+}
+
+static void
+gdict_window_init (GdictWindow *window)
+{
+  window->action = GDICT_WINDOW_ACTION_CLEAR;
+
+  window->loader = NULL;
+  window->context = NULL;
+
+  window->settings = g_settings_new (GDICT_SETTINGS_SCHEMA);
+  window->desktop_settings = g_settings_new (DESKTOP_SETTINGS_SCHEMA);
+
+  window->word = NULL;
+  window->source_name = NULL;
+  window->print_font = NULL;
+  window->defbox_font = NULL;
+
+  window->database = NULL;
+  window->strategy = NULL;
+
+  window->default_width = -1;
+  window->default_height = -1;
+  window->is_maximized = FALSE;
+  window->sidebar_visible = FALSE;
+  window->statusbar_visible = FALSE;
+  window->sidebar_page = NULL;
+
+  window->window_id = (gulong) time (NULL);
+
+  /* we need to create the chooser widgets for the sidebar before
+   * we set the construction properties
+   */
+  window->db_chooser = gdict_database_chooser_new ();
+  window->strat_chooser = gdict_strategy_chooser_new ();
+}
+
+GtkWidget *
+gdict_window_new (GdictWindowAction  action,
+		  GdictSourceLoader *loader,
+		  const gchar       *source_name,
+		  const gchar       *word)
+{
+  GtkWidget *retval;
+  GdictWindow *window;
+
+  g_return_val_if_fail (GDICT_IS_SOURCE_LOADER (loader), NULL);
+
+  retval = g_object_new (GDICT_TYPE_WINDOW,
+                         "action", action,
+                         "source-loader", loader,
+                         "source-name", source_name,
+                         NULL);
+
+  window = GDICT_WINDOW (retval);
+
+  if (word && word[0] != '\0')
+    {
+      switch (action)
+        {
+	case GDICT_WINDOW_ACTION_LOOKUP:
+	  gtk_entry_set_text (GTK_ENTRY (window->entry), word);
+	  gdict_window_set_word (window, word, NULL);
+	  break;
+
+	case GDICT_WINDOW_ACTION_MATCH:
+          {
+          GdictSource *source;
+          GdictContext *context;
+
+	  gtk_entry_set_text (GTK_ENTRY (window->entry), word);
+
+          gdict_window_set_sidebar_visible (window, TRUE);
+          gdict_sidebar_view_page (GDICT_SIDEBAR (window->sidebar),
+                                   GDICT_SIDEBAR_SPELLER_PAGE);
+
+          /* we clone the context, so that the signals that it
+           * fires do not get caught by the signal handlers we
+           * use for getting the definitions.
+           */
+          source = gdict_source_loader_get_source (window->loader,
+                                                   window->source_name);
+          context = gdict_source_get_context (source);
+
+          gdict_speller_set_context (GDICT_SPELLER (window->speller), context);
+
+          g_object_unref (context);
+          g_object_unref (source);
+
+          gdict_speller_set_strategy (GDICT_SPELLER (window->speller),
+                                      window->strategy);
+
+          gdict_speller_match (GDICT_SPELLER (window->speller), word);
+          }
+          break;
+
+	case GDICT_WINDOW_ACTION_CLEAR:
+          gdict_defbox_clear (GDICT_DEFBOX (window->defbox));
+	  break;
+
+	default:
+	  g_assert_not_reached ();
+	  break;
+	}
+    }
+
+  return retval;
+}
+
+/* GdictWindowAction */
+static const GEnumValue _gdict_window_action_values[] = {
+  { GDICT_WINDOW_ACTION_LOOKUP, "GDICT_WINDOW_ACTION_LOOKUP", "lookup" },
+  { GDICT_WINDOW_ACTION_MATCH, "GDICT_WINDOW_ACTION_MATCH", "match" },
+  { GDICT_WINDOW_ACTION_CLEAR, "GDICT_WINDOW_ACTION_CLEAR", "clear" },
+  { 0, NULL, NULL }
+};
+
+GType
+gdict_window_action_get_type (void)
+{
+  static GType our_type = 0;
+
+  if (!our_type)
+    our_type = g_enum_register_static ("GdictWindowAction", _gdict_window_action_values);
+
+  return our_type;
+}
+
+ +
+ +
+ + diff --git a/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/35.html b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/35.html new file mode 100644 index 00000000..2da69c73 --- /dev/null +++ b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/35.html @@ -0,0 +1,997 @@ + + + + + + Cppcheck - HTML report - mate-utils + + + + + +
+ + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
/* Copyright (C) 2001-2006 Jonathan Blandford <jrb@alum.mit.edu>
+ * Copyright (C) 2012-2021 MATE Developers
+ *
+ * This file is part of MATE Utils.
+ *
+ * MATE Utils is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * MATE Utils is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MATE Utils.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#include <stdlib.h>
+
+#include "screenshot-dialog.h"
+#include "screenshot-save.h"
+#include <gdk/gdkkeysyms.h>
+#include <glib/gi18n.h>
+#include <gio/gio.h>
+
+#define GET_WIDGET(x) (GTK_WIDGET (gtk_builder_get_object (dialog->builder, (x))))
+
+enum {
+  TYPE_IMAGE_PNG,
+  TYPE_TEXT_URI_LIST,
+
+  LAST_TYPE
+};
+
+static GtkTargetEntry drag_types[] =
+{
+  { "image/png", 0, TYPE_IMAGE_PNG },
+  { "text/uri-list", 0, TYPE_TEXT_URI_LIST },
+};
+
+struct ScreenshotDialog
+{
+  GtkBuilder *builder;
+  GdkPixbuf *screenshot;
+  GdkPixbuf *preview_image;
+  GtkWidget *save_widget;
+  GtkWidget *filename_entry;
+  gint drag_x;
+  gint drag_y;
+};
+
+static gboolean
+on_toplevel_key_press_event (GtkWidget *widget,
+			     GdkEventKey *key)
+{
+  if (key->keyval == GDK_KEY_F1)
+    {
+      gtk_dialog_response (GTK_DIALOG (widget), GTK_RESPONSE_HELP);
+      return TRUE;
+    }
+
+  return FALSE;
+}
+
+static void
+on_preview_draw (GtkWidget      *drawing_area,
+                 cairo_t        *cr,
+                 gpointer        data)
+{
+  ScreenshotDialog *dialog = data;
+  GtkStyleContext *context;
+  int width, height;
+
+  width = gtk_widget_get_allocated_width (drawing_area);
+  height = gtk_widget_get_allocated_height (drawing_area);
+
+  if (!dialog->preview_image ||
+      gdk_pixbuf_get_width (dialog->preview_image) != width ||
+      gdk_pixbuf_get_height (dialog->preview_image) != height)
+    {
+      g_clear_object (&dialog->preview_image);
+      dialog->preview_image = gdk_pixbuf_scale_simple (dialog->screenshot,
+                                                       width,
+                                                       height,
+                                                       GDK_INTERP_BILINEAR);
+    }
+
+  context = gtk_widget_get_style_context (drawing_area);
+  gtk_style_context_save (context);
+
+  gtk_style_context_set_state (context, gtk_widget_get_state_flags (drawing_area));
+  gtk_render_icon (context, cr, dialog->preview_image, 0, 0);
+
+  gtk_style_context_restore (context);
+}
+
+static gboolean
+on_preview_button_press_event (GtkWidget      *drawing_area,
+			       GdkEventButton *event,
+			       gpointer        data)
+{
+  ScreenshotDialog *dialog = data;
+
+  dialog->drag_x = (int) event->x;
+  dialog->drag_y = (int) event->y;
+
+  return FALSE;
+}
+
+static gboolean
+on_preview_button_release_event (GtkWidget      *drawing_area,
+				 GdkEventButton *event,
+				 gpointer        data)
+{
+  ScreenshotDialog *dialog = data;
+
+  dialog->drag_x = 0;
+  dialog->drag_y = 0;
+
+  return FALSE;
+}
+
+static void
+drag_data_get (GtkWidget          *widget,
+	       GdkDragContext     *context,
+	       GtkSelectionData   *selection_data,
+	       guint               info,
+	       guint               time,
+	       ScreenshotDialog   *dialog)
+{
+  if (info == TYPE_TEXT_URI_LIST)
+    {
+      gchar **uris;
+
+      uris = g_new (gchar *, 2);
+      uris[0] = g_strconcat ("file://",
+                             screenshot_save_get_filename (),
+                             NULL);
+      uris[1] = NULL;
+
+      gtk_selection_data_set_uris (selection_data, uris);
+      g_strfreev (uris);
+    }
+  else if (info == TYPE_IMAGE_PNG)
+    {
+      gtk_selection_data_set_pixbuf (selection_data, dialog->screenshot);
+    }
+  else
+    {
+      g_warning ("Unknown type %d", info);
+    }
+}
+
+static void
+drag_begin (GtkWidget        *widget,
+	    GdkDragContext   *context,
+	    ScreenshotDialog *dialog)
+{
+  gtk_drag_set_icon_pixbuf (context, dialog->preview_image,
+			    dialog->drag_x, dialog->drag_y);
+}
+
+ScreenshotDialog *
+screenshot_dialog_new (GdkPixbuf *screenshot,
+		       char      *initial_uri,
+		       gboolean   take_window_shot)
+{
+  ScreenshotDialog *dialog;<--- Shadowed declaration
+  GtkWidget *toplevel;
+  GtkWidget *preview_darea;
+  GtkWidget *aspect_frame;
+  GtkWidget *file_chooser_box;
+  gint width, height;
+  char *current_folder;
+  char *current_name;
+  char *ext;
+  gint pos;
+  GFile *tmp_file;
+  GFile *parent_file;
+  GError *error = NULL;
+
+  tmp_file = g_file_new_for_uri (initial_uri);
+  parent_file = g_file_get_parent (tmp_file);
+
+  current_name = g_file_get_basename (tmp_file);
+  current_folder = g_file_get_uri (parent_file);
+  g_object_unref (tmp_file);
+  g_object_unref (parent_file);
+
+  dialog = g_new0 (ScreenshotDialog, 1);
+
+  dialog->builder = gtk_builder_new ();
+
+  dialog->screenshot = screenshot;
+
+  if (gtk_builder_add_from_resource (dialog->builder, "/org/mate/screenshot/mate-screenshot.ui", &error) == 0)
+    {
+      GtkWidget *dialog;<--- Shadow variable
+      dialog = gtk_message_dialog_new (NULL, 0,
+				       GTK_MESSAGE_ERROR,
+				       GTK_BUTTONS_OK,
+				       _("Error loading UI definition file for the screenshot program: \n%s\n\n"
+				         "Please check your installation of mate-utils."), error->message);
+      gtk_dialog_run (GTK_DIALOG (dialog));
+      gtk_widget_destroy (dialog);
+
+      g_error_free (error);
+      exit (1);
+    }
+
+  gtk_builder_set_translation_domain (dialog->builder, GETTEXT_PACKAGE);
+
+  width = gdk_pixbuf_get_width (screenshot);
+  height = gdk_pixbuf_get_height (screenshot);
+
+  width /= 5;
+  height /= 5;
+
+  toplevel = GET_WIDGET ("toplevel");
+  aspect_frame = GET_WIDGET ("aspect_frame");
+  preview_darea = GET_WIDGET ("preview_darea");
+  dialog->filename_entry = GET_WIDGET ("filename_entry");
+  file_chooser_box = GET_WIDGET ("file_chooser_box");
+
+  dialog->save_widget = gtk_file_chooser_button_new (_("Select a folder"), GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
+  gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (dialog->save_widget), FALSE);
+  gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (dialog->save_widget), current_folder);
+  gtk_entry_set_text (GTK_ENTRY (dialog->filename_entry), current_name);
+
+  gtk_box_pack_start (GTK_BOX (file_chooser_box), dialog->save_widget, TRUE, TRUE, 0);
+  g_free (current_folder);
+
+  gtk_widget_set_size_request (preview_darea, width, height);
+  height = gdk_pixbuf_get_height (screenshot);
+  width = gdk_pixbuf_get_width (screenshot);
+  gtk_aspect_frame_set (GTK_ASPECT_FRAME (aspect_frame), 0.0, 0.5,
+                        (gfloat) width / (gfloat) height, FALSE);
+  g_signal_connect (toplevel, "key_press_event", G_CALLBACK (on_toplevel_key_press_event), dialog);
+  g_signal_connect (preview_darea, "draw", G_CALLBACK (on_preview_draw), dialog);
+  g_signal_connect (preview_darea, "button_press_event", G_CALLBACK (on_preview_button_press_event), dialog);
+  g_signal_connect (preview_darea, "button_release_event", G_CALLBACK (on_preview_button_release_event), dialog);
+
+  if (take_window_shot)
+    gtk_frame_set_shadow_type (GTK_FRAME (aspect_frame), GTK_SHADOW_NONE);
+  else
+    gtk_frame_set_shadow_type (GTK_FRAME (aspect_frame), GTK_SHADOW_IN);
+
+  /* setup dnd */
+  g_signal_connect (preview_darea, "drag_begin",
+                    G_CALLBACK (drag_begin),
+                    dialog);
+  g_signal_connect (preview_darea, "drag_data_get",
+                    G_CALLBACK (drag_data_get),
+                    dialog);
+
+  gtk_widget_show_all (toplevel);
+
+  /* select the name of the file but leave out the extension if there's any;
+   * the dialog must be realized for select_region to work
+   */
+  ext = g_utf8_strrchr (current_name, -1, '.');
+  if (ext)
+    pos = g_utf8_strlen (current_name, -1) - g_utf8_strlen (ext, -1);
+  else
+    pos = -1;
+
+  gtk_editable_select_region (GTK_EDITABLE (dialog->filename_entry),
+			      0,
+			      pos);
+
+  g_free (current_name);
+
+  return dialog;
+}
+
+void
+screenshot_dialog_focus_entry (ScreenshotDialog *dialog)
+{
+  gtk_widget_grab_focus (dialog->filename_entry);
+}
+
+void
+screenshot_dialog_enable_dnd (ScreenshotDialog *dialog)
+{
+  GtkWidget *preview_darea;
+
+  g_return_if_fail (dialog != NULL);
+
+  preview_darea = GET_WIDGET ("preview_darea");
+  gtk_drag_source_set (preview_darea,
+		       GDK_BUTTON1_MASK | GDK_BUTTON3_MASK,
+		       drag_types, G_N_ELEMENTS (drag_types),
+		       GDK_ACTION_COPY);
+}
+
+GtkWidget *
+screenshot_dialog_get_toplevel (ScreenshotDialog *dialog)
+{
+  return GET_WIDGET ("toplevel");
+}
+
+char *
+screenshot_dialog_get_uri (ScreenshotDialog *dialog)
+{
+  gchar *folder;
+  const gchar *file_name;
+  gchar *uri, *file, *tmp;
+  GError *error;
+
+  folder = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (dialog->save_widget));
+  file_name = gtk_entry_get_text (GTK_ENTRY (dialog->filename_entry));
+
+  error = NULL;
+  tmp = g_filename_from_utf8 (file_name, -1, NULL, NULL, &error);
+  if (error)
+    {
+      g_warning ("Unable to convert `%s' to valid UTF-8: %s\n"
+                 "Falling back to default file.",
+                 file_name,
+                 error->message);
+      g_error_free (error);
+      tmp = g_strdup (_("Screenshot.png"));
+    }
+
+  file = g_uri_escape_string (tmp, NULL, FALSE);
+  uri = g_build_filename (folder, file, NULL);
+
+  g_free (folder);
+  g_free (tmp);
+  g_free (file);
+
+  return uri;
+}
+
+char *
+screenshot_dialog_get_folder (ScreenshotDialog *dialog)
+{
+  return gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (dialog->save_widget));
+}
+
+GdkPixbuf *
+screenshot_dialog_get_screenshot (ScreenshotDialog *dialog)
+{
+  return dialog->screenshot;
+}
+
+void
+screenshot_dialog_set_busy (ScreenshotDialog *dialog,
+			    gboolean          busy)
+{
+  GtkWidget *toplevel;
+  GdkDisplay *display;
+
+  toplevel = screenshot_dialog_get_toplevel (dialog);
+  display = gtk_widget_get_display (toplevel);
+
+  if (busy)
+    {
+      GdkCursor *cursor;
+      /* Change cursor to busy */
+      cursor = gdk_cursor_new_for_display (display, GDK_WATCH);
+      gdk_window_set_cursor (gtk_widget_get_window (toplevel), cursor);
+      g_object_unref (cursor);
+    }
+  else
+    {
+      gdk_window_set_cursor (gtk_widget_get_window (toplevel), NULL);
+    }
+
+  gtk_widget_set_sensitive (toplevel, ! busy);
+
+  gdk_display_flush (display);
+}
+
+ +
+ +
+ + diff --git a/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/36.html b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/36.html new file mode 100644 index 00000000..3236b888 --- /dev/null +++ b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/36.html @@ -0,0 +1,853 @@ + + + + + + Cppcheck - HTML report - mate-utils + + + + + +
+ + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
#include <gio/gio.h>
+
+#if defined (__ELF__) && ( __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 6))
+# define SECTION __attribute__ ((section (".gresource.screenshot"), aligned (8)))
+#else
+# define SECTION
+#endif
+
+static const SECTION union { const guint8 data[1649]; const double alignment; void * const ptr;}  screenshot_resource_data = { {<--- union member 'Anonymous0::alignment' is never used.<--- union member 'Anonymous0::ptr' is never used.
+  0107, 0126, 0141, 0162, 0151, 0141, 0156, 0164, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 
+  0030, 0000, 0000, 0000, 0254, 0000, 0000, 0000, 0000, 0000, 0000, 0050, 0005, 0000, 0000, 0000, 
+  0000, 0000, 0000, 0000, 0004, 0000, 0000, 0000, 0004, 0000, 0000, 0000, 0005, 0000, 0000, 0000, 
+  0005, 0000, 0000, 0000, 0113, 0120, 0220, 0013, 0003, 0000, 0000, 0000, 0254, 0000, 0000, 0000, 
+  0004, 0000, 0114, 0000, 0260, 0000, 0000, 0000, 0264, 0000, 0000, 0000, 0014, 0026, 0162, 0052, 
+  0004, 0000, 0000, 0000, 0264, 0000, 0000, 0000, 0022, 0000, 0166, 0000, 0310, 0000, 0000, 0000, 
+  0114, 0006, 0000, 0000, 0201, 0321, 0040, 0031, 0000, 0000, 0000, 0000, 0114, 0006, 0000, 0000, 
+  0005, 0000, 0114, 0000, 0124, 0006, 0000, 0000, 0130, 0006, 0000, 0000, 0324, 0265, 0002, 0000, 
+  0377, 0377, 0377, 0377, 0130, 0006, 0000, 0000, 0001, 0000, 0114, 0000, 0134, 0006, 0000, 0000, 
+  0140, 0006, 0000, 0000, 0016, 0170, 0312, 0164, 0002, 0000, 0000, 0000, 0140, 0006, 0000, 0000, 
+  0013, 0000, 0114, 0000, 0154, 0006, 0000, 0000, 0160, 0006, 0000, 0000, 0157, 0162, 0147, 0057, 
+  0002, 0000, 0000, 0000, 0155, 0141, 0164, 0145, 0055, 0163, 0143, 0162, 0145, 0145, 0156, 0163, 
+  0150, 0157, 0164, 0056, 0165, 0151, 0000, 0000, 0275, 0063, 0000, 0000, 0001, 0000, 0000, 0000, 
+  0170, 0332, 0355, 0133, 0121, 0163, 0342, 0066, 0020, 0176, 0277, 0137, 0341, 0352, 0361, 0072, 
+  0012, 0001, 0172, 0231, 0314, 0015, 0370, 0046, 0115, 0232, 0153, 0347, 0256, 0167, 0063, 0115, 
+  0372, 0354, 0021, 0366, 0202, 0325, 0010, 0311, 0225, 0004, 0204, 0376, 0372, 0256, 0154, 0222, 
+  0100, 0060, 0066, 0062, 0114, 0041, 0151, 0336, 0210, 0255, 0135, 0355, 0176, 0336, 0157, 0245, 
+  0135, 0051, 0275, 0117, 0367, 0143, 0021, 0114, 0101, 0033, 0256, 0144, 0237, 0264, 0117, 0116, 
+  0111, 0000, 0062, 0126, 0011, 0227, 0243, 0076, 0371, 0363, 0366, 0232, 0236, 0223, 0117, 0341, 
+  0273, 0336, 0017, 0224, 0006, 0237, 0101, 0202, 0146, 0026, 0222, 0140, 0306, 0155, 0032, 0214, 
+  0004, 0113, 0040, 0350, 0236, 0164, 0317, 0117, 0072, 0001, 0245, 0305, 0240, 0367, 0064, 0030, 
+  0253, 0004, 0076, 0006, 0116, 0055, 0376, 0345, 0036, 0163, 0151, 0101, 0017, 0131, 0014, 0341, 
+  0273, 0040, 0350, 0151, 0370, 0173, 0302, 0065, 0230, 0100, 0360, 0101, 0237, 0214, 0354, 0335, 
+  0217, 0344, 0151, 0376, 0356, 0111, 0247, 0103, 0132, 0371, 0070, 0065, 0370, 0013, 0142, 0033, 
+  0304, 0202, 0031, 0323, 0047, 0237, 0355, 0335, 0157, 0143, 0066, 0002, 0022, 0360, 0244, 0117, 
+  0270, 0373, 0031, 0305, 0114, 0306, 0040, 0210, 0033, 0215, 0343, 0063, 0255, 0062, 0320, 0166, 
+  0036, 0110, 0066, 0206, 0076, 0231, 0162, 0303, 0007, 0002, 0110, 0170, 0253, 0047, 0320, 0153, 
+  0075, 0274, 0055, 0037, 0214, 0232, 0350, 0120, 0305, 0023, 0103, 0302, 0153, 0046, 0114, 0355, 
+  0170, 0036, 0053, 0111, 0335, 0117, 0022, 0342, 0233, 0030, 0214, 0241, 0306, 0252, 0154, 0125, 
+  0254, 0327, 0052, 0134, 0330, 0326, 0033, 0225, 0315, 0017, 0354, 0013, 0044, 0334, 0122, 0147, 
+  0307, 0116, 0216, 0244, 0040, 0262, 0003, 0073, 0342, 0114, 0240, 0003, 0255, 0146, 0006, 0264, 
+  0217, 0057, 0127, 0234, 0011, 0065, 0052, 0234, 0301, 0357, 0051, 0140, 0272, 0061, 0276, 0174, 
+  0255, 0033, 0050, 0235, 0200, 0246, 0063, 0236, 0330, 0224, 0204, 0037, 0352, 0206, 0133, 0156, 
+  0021, 0247, 0300, 0152, 0046, 0215, 0140, 0226, 0041, 0152, 0175, 0062, 0007, 0234, 0355, 0206, 
+  0115, 0041, 0270, 0211, 0065, 0200, 0064, 0251, 0262, 0165, 0212, 0220, 0151, 0374, 0037, 0226, 
+  0203, 0276, 0225, 0235, 0166, 0236, 0001, 0115, 0221, 0262, 0044, 0114, 0162, 0064, 0326, 0004, 
+  0014, 0037, 0111, 0046, 0026, 0303, 0357, 0140, 0116, 0063, 0355, 0010, 0200, 0130, 0241, 0120, 
+  0220, 0062, 0231, 0010, 0320, 0175, 0242, 0144, 0364, 0000, 0141, 0204, 0243, 0242, 0174, 0124, 
+  0264, 0030, 0145, 0146, 0054, 0313, 0000, 0121, 0226, 0252, 0240, 0073, 0352, 0215, 0123, 0056, 
+  0222, 0040, 0117, 0026, 0250, 0237, 0346, 0177, 0142, 0310, 0014, 0324, 0375, 0342, 0023, 0224, 
+  0175, 0261, 0237, 0361, 0155, 0376, 0271, 0012, 0143, 0251, 0033, 0336, 0176, 0034, 0357, 0031, 
+  0201, 0115, 0276, 0163, 0231, 0214, 0322, 0034, 0275, 0144, 0026, 0123, 0032, 0011, 0061, 0267, 
+  0131, 0036, 0063, 0261, 0215, 0240, 0311, 0130, 0214, 0211, 0227, 0204, 0235, 0322, 0321, 0345, 
+  0010, 0261, 0330, 0115, 0024, 0061, 0015, 0154, 0311, 0361, 0122, 0260, 0046, 0326, 0052, 0371, 
+  0034, 0262, 0045, 0371, 0366, 0212, 0202, 0006, 0350, 0065, 0105, 0260, 0114, 0116, 0260, 0271, 
+  0232, 0130, 0114, 0254, 0163, 0067, 0043, 0310, 0144, 0243, 0140, 0016, 0304, 0352, 0263, 0315, 
+  0356, 0027, 0276, 0273, 0014, 0021, 0015, 0212, 0007, 0317, 0045, 0313, 0114, 0031, 0140, 0042, 
+  0050, 0143, 0143, 0364, 0053, 0052, 0332, 0144, 0130, 0143, 0010, 0153, 0140, 0154, 0042, 0232, 
+  0300, 0220, 0115, 0204, 0365, 0027, 0326, 0020, 0003, 0237, 0202, 0171, 0322, 0120, 0371, 0025, 
+  0113, 0063, 0163, 0276, 0104, 0204, 0117, 0313, 0203, 0217, 0360, 0304, 0000, 0235, 0110, 0314, 
+  0235, 0202, 0313, 0006, 0260, 0061, 0061, 0143, 0163, 0134, 0236, 0123, 0065, 0243, 0013, 0073, 
+  0252, 0125, 0054, 0257, 0020, 0253, 0212, 0131, 0174, 0207, 0344, 0254, 0237, 0022, 0356, 0063, 
+  0114, 0202, 0015, 0160, 0032, 0162, 0041, 0374, 0075, 0314, 0224, 0341, 0105, 0252, 0071, 0255, 
+  0362, 0252, 0324, 0374, 0136, 0253, 0204, 0073, 0115, 0370, 0044, 0141, 0266, 0027, 0072, 0175, 
+  0203, 0331, 0377, 0221, 0024, 0322, 0317, 0355, 0227, 0313, 0011, 0137, 0123, 0167, 0245, 0104, 
+  0373, 0160, 0224, 0160, 0033, 0351, 0175, 0160, 0342, 0062, 0102, 0105, 0201, 0125, 0301, 0245, 
+  0340, 0331, 0100, 0061, 0235, 0274, 0255, 0067, 0036, 0324, 0132, 0257, 0147, 0216, 0213, 0133, 
+  0250, 0202, 0305, 0130, 0307, 0272, 0322, 0132, 0351, 0000, 0267, 0312, 0175, 0162, 0211, 0073, 
+  0344, 0174, 0227, 0135, 0354, 0356, 0246, 0130, 0164, 0023, 0127, 0127, 0363, 0041, 0307, 0112, 
+  0031, 0043, 0355, 0352, 0113, 0164, 0371, 0375, 0333, 0355, 0037, 0337, 0277, 0106, 0277, 0137, 
+  0334, 0174, 0171, 0330, 0103, 0277, 0212, 0125, 0254, 0163, 0100, 0312, 0346, 0035, 0205, 0275, 
+  0054, 0144, 0227, 0271, 0252, 0067, 0246, 0372, 0060, 0325, 0033, 0262, 0267, 0275, 0341, 0326, 
+  0254, 0352, 0036, 0216, 0125, 0352, 0156, 0057, 0214, 0162, 0215, 0217, 0127, 0315, 0247, 0224, 
+  0231, 0343, 0041, 0243, 0361, 0104, 0373, 0215, 0212, 0133, 0123, 0361, 0247, 0175, 0120, 0261, 
+  0314, 0377, 0162, 0337, 0033, 0371, 0355, 0357, 0363, 0232, 0277, 0150, 0013, 0165, 0335, 0304, 
+  0352, 0336, 0215, 0157, 0061, 0133, 0202, 0320, 0032, 0072, 0353, 0111, 0252, 0242, 0161, 0350, 
+  0072, 0206, 0335, 0143, 0352, 0173, 0325, 0164, 0212, 0167, 0156, 0072, 0126, 0066, 0036, 0333, 
+  0347, 0073, 0167, 0331, 0036, 0200, 0115, 0021, 0330, 0063, 0362, 0337, 0344, 0151, 0157, 0016, 
+  0077, 0071, 0334, 0251, 0024, 0053, 0165, 0272, 0334, 0361, 0013, 0223, 0341, 0203, 0153, 0355, 
+  0116, 0040, 0162, 0000, 0130, 0376, 0040, 0032, 0346, 0117, 0312, 0164, 0354, 0200, 0305, 0256, 
+  0170, 0154, 0134, 0173, 0351, 0075, 0023, 0130, 0172, 0124, 0066, 0223, 0252, 0304, 0347, 0115, 
+  0305, 0115, 0312, 0022, 0114, 0376, 0105, 0306, 0340, 0322, 0127, 0274, 0261, 0331, 0333, 0033, 
+  0274, 0061, 0026, 0312, 0343, 0341, 0112, 0263, 0031, 0206, 0330, 0205, 0353, 0313, 0347, 0361, 
+  0220, 0151, 0230, 0162, 0230, 0105, 0311, 0132, 0253, 0176, 0217, 0101, 0261, 0217, 0300, 0330, 
+  0274, 0272, 0126, 0354, 0014, 0353, 0005, 0067, 0057, 0315, 0073, 0055, 0317, 0315, 0227, 0350, 
+  0306, 0335, 0324, 0212, 0245, 0272, 0022, 0237, 0212, 0164, 0342, 0016, 0330, 0045, 0215, 0225, 
+  0230, 0214, 0245, 0351, 0167, 0361, 0267, 0073, 0276, 0304, 0037, 0356, 0010, 0175, 0233, 0160, 
+  0373, 0254, 0171, 0262, 0070, 0271, 0164, 0273, 0346, 0366, 0113, 0310, 0070, 0350, 0042, 0175, 
+  0314, 0304, 0147, 0336, 0263, 0347, 0140, 0321, 0055, 0123, 0171, 0023, 0012, 0177, 0055, 0252, 
+  0021, 0007, 0152, 0236, 0335, 0332, 0307, 0315, 0132, 0277, 0116, 0073, 0016, 0370, 0330, 0104, 
+  0247, 0347, 0116, 0177, 0223, 0232, 0261, 0204, 0261, 0222, 0074, 0166, 0033, 0235, 0021, 0140, 
+  0275, 0202, 0234, 0005, 0367, 0052, 0302, 0155, 0214, 0236, 0067, 0121, 0271, 0365, 0032, 0120, 
+  0227, 0340, 0352, 0162, 0125, 0051, 0324, 0060, 0264, 0224, 0131, 0313, 0342, 0164, 0053, 0013, 
+  0112, 0216, 0336, 0125, 0346, 0243, 0240, 0042, 0001, 0325, 0044, 0351, 0335, 0211, 0320, 0175, 
+  0075, 0104, 0310, 0357, 0123, 0160, 0031, 0104, 0103, 0045, 0060, 0250, 0017, 0111, 0211, 0127, 
+  0024, 0277, 0355, 0343, 0212, 0337, 0137, 0134, 0112, 0051, 0342, 0167, 0065, 0315, 0034, 0050, 
+  0216, 0233, 0252, 0340, 0162, 0141, 0005, 0215, 0123, 0246, 0111, 0370, 0276, 0211, 0222, 0207, 
+  0043, 0005, 0217, 0156, 0323, 0046, 0125, 0171, 0221, 0232, 0333, 0202, 0116, 0165, 0073, 0007, 
+  0217, 0333, 0366, 0053, 0313, 0273, 0217, 0305, 0264, 0213, 0332, 0050, 0116, 0225, 0062, 0240, 
+  0243, 0345, 0053, 0121, 0307, 0232, 0177, 0053, 0035, 0055, 0146, 0021, 0054, 0206, 0064, 0117, 
+  0272, 0255, 0012, 0105, 0255, 0152, 0310, 0216, 0074, 0236, 0016, 0233, 0007, 0353, 0041, 0176, 
+  0323, 0176, 0164, 0332, 0367, 0137, 0102, 0067, 0051, 0355, 0366, 0121, 0101, 0267, 0367, 0135, 
+  0101, 0277, 0334, 0173, 0050, 0247, 0307, 0321, 0363, 0367, 0351, 0137, 0067, 0150, 0371, 0327, 
+  0175, 0371, 0372, 0346, 0375, 0252, 0213, 0053, 0057, 0173, 0305, 0105, 0325, 0105, 0275, 0150, 
+  0036, 0045, 0126, 0036, 0007, 0032, 0114, 0246, 0244, 0101, 0153, 0150, 0273, 0135, 0334, 0004, 
+  0137, 0234, 0076, 0366, 0132, 0053, 0043, 0153, 0345, 0073, 0035, 0022, 0076, 0135, 0153, 0363, 
+  0225, 0306, 0271, 0227, 0056, 0000, 0371, 0112, 0323, 0063, 0024, 0137, 0276, 0214, 0340, 0255, 
+  0340, 0003, 0011, 0037, 0317, 0135, 0113, 0205, 0237, 0075, 0064, 0015, 0156, 0372, 0043, 0072, 
+  0007, 0276, 0350, 0237, 0240, 0330, 0030, 0067, 0362, 0164, 0355, 0002, 0235, 0247, 0053, 0356, 
+  0270, 0363, 0130, 0174, 0131, 0077, 0172, 0175, 0162, 0246, 0327, 0132, 0372, 0157, 0232, 0177, 
+  0001, 0203, 0316, 0235, 0136, 0000, 0050, 0165, 0165, 0141, 0171, 0051, 0155, 0141, 0164, 0145, 
+  0057, 0000, 0000, 0000, 0004, 0000, 0000, 0000, 0057, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 
+  0163, 0143, 0162, 0145, 0145, 0156, 0163, 0150, 0157, 0164, 0057, 0000, 0001, 0000, 0000, 0000
+} };
+
+static GStaticResource static_resource = { screenshot_resource_data.data, sizeof (screenshot_resource_data.data) - 1 /* nul terminator */, NULL, NULL, NULL };
+
+G_MODULE_EXPORT
+GResource *screenshot_get_resource (void);
+GResource *screenshot_get_resource (void)
+{
+  return g_static_resource_get_resource (&static_resource);
+}
+/* GLIB - Library of useful routines for C programming
+ * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * Modified by the GLib Team and others 1997-2000.  See the AUTHORS
+ * file for a list of people on the GLib Team.  See the ChangeLog
+ * files for a list of changes.  These files are distributed with
+ * GLib at ftp://ftp.gtk.org/pub/gtk/.
+ */
+
+#ifndef __G_CONSTRUCTOR_H__
+#define __G_CONSTRUCTOR_H__
+
+/*
+  If G_HAS_CONSTRUCTORS is true then the compiler support *both* constructors and
+  destructors, in a usable way, including e.g. on library unload. If not you're on
+  your own.
+
+  Some compilers need #pragma to handle this, which does not work with macros,
+  so the way you need to use this is (for constructors):
+
+  #ifdef G_DEFINE_CONSTRUCTOR_NEEDS_PRAGMA
+  #pragma G_DEFINE_CONSTRUCTOR_PRAGMA_ARGS(my_constructor)
+  #endif
+  G_DEFINE_CONSTRUCTOR(my_constructor)
+  static void my_constructor(void) {
+   ...
+  }
+
+*/
+
+#ifndef __GTK_DOC_IGNORE__
+
+#if  __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7)
+
+#define G_HAS_CONSTRUCTORS 1
+
+#define G_DEFINE_CONSTRUCTOR(_func) static void __attribute__((constructor)) _func (void);
+#define G_DEFINE_DESTRUCTOR(_func) static void __attribute__((destructor)) _func (void);
+
+#elif defined (_MSC_VER) && (_MSC_VER >= 1500)
+/* Visual studio 2008 and later has _Pragma */
+
+/*
+ * Only try to include gslist.h if not already included via glib.h,
+ * so that items using gconstructor.h outside of GLib (such as
+ * GResources) continue to build properly.
+ */
+#ifndef __G_LIB_H__
+#include "gslist.h"
+#endif
+
+#include <stdlib.h>
+
+#define G_HAS_CONSTRUCTORS 1
+
+/* We do some weird things to avoid the constructors being optimized
+ * away on VS2015 if WholeProgramOptimization is enabled. First we
+ * make a reference to the array from the wrapper to make sure its
+ * references. Then we use a pragma to make sure the wrapper function
+ * symbol is always included at the link stage. Also, the symbols
+ * need to be extern (but not dllexport), even though they are not
+ * really used from another object file.
+ */
+
+/* We need to account for differences between the mangling of symbols
+ * for x86 and x64/ARM/ARM64 programs, as symbols on x86 are prefixed
+ * with an underscore but symbols on x64/ARM/ARM64 are not.
+ */
+#ifdef _M_IX86
+#define G_MSVC_SYMBOL_PREFIX "_"
+#else
+#define G_MSVC_SYMBOL_PREFIX ""
+#endif
+
+#define G_DEFINE_CONSTRUCTOR(_func) G_MSVC_CTOR (_func, G_MSVC_SYMBOL_PREFIX)
+#define G_DEFINE_DESTRUCTOR(_func) G_MSVC_DTOR (_func, G_MSVC_SYMBOL_PREFIX)
+
+#define G_MSVC_CTOR(_func,_sym_prefix) \
+  static void _func(void); \
+  extern int (* _array ## _func)(void);              \
+  int _func ## _wrapper(void) { _func(); g_slist_find (NULL,  _array ## _func); return 0; } \
+  __pragma(comment(linker,"/include:" _sym_prefix # _func "_wrapper")) \
+  __pragma(section(".CRT$XCU",read)) \
+  __declspec(allocate(".CRT$XCU")) int (* _array ## _func)(void) = _func ## _wrapper;
+
+#define G_MSVC_DTOR(_func,_sym_prefix) \
+  static void _func(void); \
+  extern int (* _array ## _func)(void);              \
+  int _func ## _constructor(void) { atexit (_func); g_slist_find (NULL,  _array ## _func); return 0; } \
+   __pragma(comment(linker,"/include:" _sym_prefix # _func "_constructor")) \
+  __pragma(section(".CRT$XCU",read)) \
+  __declspec(allocate(".CRT$XCU")) int (* _array ## _func)(void) = _func ## _constructor;
+
+#elif defined (_MSC_VER)
+
+#define G_HAS_CONSTRUCTORS 1
+
+/* Pre Visual studio 2008 must use #pragma section */
+#define G_DEFINE_CONSTRUCTOR_NEEDS_PRAGMA 1
+#define G_DEFINE_DESTRUCTOR_NEEDS_PRAGMA 1
+
+#define G_DEFINE_CONSTRUCTOR_PRAGMA_ARGS(_func) \
+  section(".CRT$XCU",read)
+#define G_DEFINE_CONSTRUCTOR(_func) \
+  static void _func(void); \
+  static int _func ## _wrapper(void) { _func(); return 0; } \
+  __declspec(allocate(".CRT$XCU")) static int (*p)(void) = _func ## _wrapper;
+
+#define G_DEFINE_DESTRUCTOR_PRAGMA_ARGS(_func) \
+  section(".CRT$XCU",read)
+#define G_DEFINE_DESTRUCTOR(_func) \
+  static void _func(void); \
+  static int _func ## _constructor(void) { atexit (_func); return 0; } \
+  __declspec(allocate(".CRT$XCU")) static int (* _array ## _func)(void) = _func ## _constructor;
+
+#elif defined(__SUNPRO_C)
+
+/* This is not tested, but i believe it should work, based on:
+ * http://opensource.apple.com/source/OpenSSL098/OpenSSL098-35/src/fips/fips_premain.c
+ */
+
+#define G_HAS_CONSTRUCTORS 1
+
+#define G_DEFINE_CONSTRUCTOR_NEEDS_PRAGMA 1
+#define G_DEFINE_DESTRUCTOR_NEEDS_PRAGMA 1
+
+#define G_DEFINE_CONSTRUCTOR_PRAGMA_ARGS(_func) \
+  init(_func)
+#define G_DEFINE_CONSTRUCTOR(_func) \
+  static void _func(void);
+
+#define G_DEFINE_DESTRUCTOR_PRAGMA_ARGS(_func) \
+  fini(_func)
+#define G_DEFINE_DESTRUCTOR(_func) \
+  static void _func(void);
+
+#else
+
+/* constructors not supported for this compiler */
+
+#endif
+
+#endif /* __GTK_DOC_IGNORE__ */
+#endif /* __G_CONSTRUCTOR_H__ */
+
+#ifdef G_HAS_CONSTRUCTORS
+
+#ifdef G_DEFINE_CONSTRUCTOR_NEEDS_PRAGMA
+#pragma G_DEFINE_CONSTRUCTOR_PRAGMA_ARGS(screenshotresource_constructor)
+#endif
+G_DEFINE_CONSTRUCTOR(screenshotresource_constructor)
+#ifdef G_DEFINE_DESTRUCTOR_NEEDS_PRAGMA
+#pragma G_DEFINE_DESTRUCTOR_PRAGMA_ARGS(screenshotresource_destructor)
+#endif
+G_DEFINE_DESTRUCTOR(screenshotresource_destructor)
+
+#else
+#warning "Constructor not supported on this compiler, linking in resources will not work"
+#endif
+
+static void screenshotresource_constructor (void)
+{
+  g_static_resource_init (&static_resource);
+}
+
+static void screenshotresource_destructor (void)
+{
+  g_static_resource_fini (&static_resource);
+}
+
+ +
+ +
+ + diff --git a/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/37.html b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/37.html new file mode 100644 index 00000000..abc825ec --- /dev/null +++ b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/37.html @@ -0,0 +1,821 @@ + + + + + + Cppcheck - HTML report - mate-utils + + + + + +
+ + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
/* Copyright (C) 2001-2006 Jonathan Blandford <jrb@alum.mit.edu>
+ * Copyright (C) 2012-2021 MATE Developers
+ *
+ * This file is part of MATE Utils.
+ *
+ * MATE Utils is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * MATE Utils is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MATE Utils.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <signal.h>
+#include <string.h>
+#include <glib/gi18n.h>
+
+#include "screenshot-save.h"
+
+static char *parent_dir = NULL;
+static char *tmp_filename = NULL;
+
+static SaveFunction save_callback = NULL;
+static gpointer save_user_data = NULL;
+
+/* Strategy for saving:
+ *
+ * We keep another process around to handle saving the image.  This is
+ * done for two reasons.  One, the saving takes a non-zero amount of
+ * time (about a quarter of a second on my box.)  This will make it
+ * more interactive.  The second reason is to make the child
+ * responsible for cleaning up the temp dir.  If the parent process is
+ * killed or segfaults, the child process can clean up the temp dir.
+ */
+static void
+clean_up_temporary_dir (gboolean gui_on_error)
+{
+  char *message;
+  gboolean error_occurred = FALSE;
+  if (g_file_test (tmp_filename, G_FILE_TEST_EXISTS))
+    error_occurred = unlink (tmp_filename);
+  if (g_file_test (parent_dir, G_FILE_TEST_EXISTS))
+    error_occurred = rmdir (parent_dir) || error_occurred;
+
+  if (error_occurred)
+    {
+      message = g_strdup_printf (_("Unable to clear the temporary folder:\n%s"),
+				 tmp_filename);
+      if (gui_on_error)
+	{
+	  GtkWidget *dialog;
+
+	  dialog = gtk_message_dialog_new (NULL, 0,
+					   GTK_MESSAGE_ERROR,
+					   GTK_BUTTONS_OK,
+					   "%s", message);
+	  gtk_dialog_run (GTK_DIALOG (dialog));
+	  gtk_widget_destroy (dialog);
+	}
+      else
+	{
+	  g_warning ("%s", message);
+	}
+      g_free (message);
+    }
+  g_free (tmp_filename);
+  g_free (parent_dir);
+}
+
+static void
+child_done_notification (GPid     pid,
+			 gint     status,
+			 gpointer data)
+{
+  /* This should never be called. */
+
+  /* We expect the child to die after the parent.  If the child dies
+   * than it either segfaulted, or was randomly killed.  In either
+   * case, we can't reasonably continue.  */
+  GtkWidget *dialog;
+
+  dialog = gtk_message_dialog_new (NULL, 0,
+				   GTK_MESSAGE_ERROR,
+				   GTK_BUTTONS_OK,
+				   _("The child save process unexpectedly exited.  We are unable to write the screenshot to disk."));
+  gtk_dialog_run (GTK_DIALOG (dialog));
+  gtk_widget_destroy (dialog);
+
+  clean_up_temporary_dir (TRUE);
+
+  exit (1);
+}
+
+static gboolean
+read_pipe_from_child (GIOChannel   *source,
+		      GIOCondition  condition,
+		      gpointer      data)
+{
+  if (condition & G_IO_IN)
+    {
+      gchar *message = NULL;
+      gchar *error_message = NULL;
+      GtkWidget *dialog;
+      GIOStatus status;
+
+      status = g_io_channel_read_line (source, &error_message, NULL, NULL, NULL);
+
+      if (status == G_IO_STATUS_NORMAL)
+	{
+	  message = g_strdup_printf ("Unable to save the screenshot to disk:\n\n%s", error_message);
+	  dialog = gtk_message_dialog_new (NULL, 0,
+					   GTK_MESSAGE_ERROR,
+					   GTK_BUTTONS_OK,
+					   "%s", message);
+	  gtk_dialog_run (GTK_DIALOG (dialog));
+	  gtk_widget_destroy (dialog);
+	  exit (1);
+	}
+    }
+
+  (*save_callback) (save_user_data);
+
+  return FALSE;
+}
+
+static char *
+make_temp_directory (void)
+{
+  gint result, i;
+  gchar *dir_name;
+
+  i = 0;
+  do
+    {
+      gchar *tmp_dir = g_strdup_printf ("mate-screenshot.%u.%d",
+                                        (unsigned int) getpid (),
+                                        i++);
+
+      dir_name = g_build_filename (g_get_tmp_dir (),
+                                   tmp_dir,
+                                   NULL);
+      g_free (tmp_dir);
+
+      result = g_mkdir_with_parents (dir_name, 0777);
+      if (result < 0)
+        {
+          g_free (dir_name);
+
+          if (errno != EEXIST)
+            return NULL;
+          else
+            continue;
+        }
+      else
+        return dir_name;
+    }
+  while (TRUE);
+}
+
+static void
+signal_handler (int sig)
+{
+  clean_up_temporary_dir (FALSE);
+
+  signal (sig, SIG_DFL);
+  kill (getpid (), sig);
+}
+
+void
+screenshot_save_start (GdkPixbuf    *pixbuf,
+                       SaveFunction  callback,
+                       gpointer      user_data)
+{
+  GPid pid;
+  int  parent_exit_notification[2];
+  int  pipe_from_child[2];
+
+  if (pipe (parent_exit_notification) == -1)
+    perror("pipe error");
+
+  if (pipe (pipe_from_child) == -1)
+    perror("pipe error");
+
+  parent_dir = make_temp_directory ();
+  if (parent_dir == NULL)
+    return;
+
+  tmp_filename = g_build_filename (parent_dir,
+                                   _("Screenshot.png"),
+                                   NULL);
+  save_callback = callback;
+  save_user_data = user_data;
+
+  pid = fork ();
+  if (pid == 0)
+    {
+      GError *error = NULL;
+      char c;
+
+      signal (SIGINT, signal_handler);
+      signal (SIGTERM, signal_handler);
+
+      close (parent_exit_notification [1]);
+      close (pipe_from_child [0]);
+
+      if (! gdk_pixbuf_save (pixbuf, tmp_filename,
+                             "png", &error,
+                             "tEXt::Software", "mate-screenshot",
+                             NULL))
+        {
+          if (error && error->message)
+            {
+              if (write (pipe_from_child[1], error->message, strlen (error->message)) == -1)
+                perror("write error");
+            }
+          else
+            {
+#define ERROR_MESSAGE _("Unknown error saving screenshot to disk")
+              if (write (pipe_from_child[1], ERROR_MESSAGE, strlen (ERROR_MESSAGE)) == -1)
+                perror("write error");
+            }
+        }
+      /* By closing the pipe, we let the main process know that we're
+       * done saving it. */
+      close (pipe_from_child[1]);
+
+      if (read (parent_exit_notification[0], &c, 1) == -1)
+        perror("read error");
+
+      clean_up_temporary_dir (FALSE);
+      _exit (0);
+    }
+  else if (pid > 0)
+    {
+      GIOChannel *channel;
+
+      close (parent_exit_notification[0]);
+      close (pipe_from_child[1]);
+
+      channel = g_io_channel_unix_new (pipe_from_child[0]);
+      g_io_add_watch (channel,
+                      G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
+                      read_pipe_from_child,
+                      NULL);
+      g_io_channel_unref (channel);
+      g_child_watch_add (pid, child_done_notification, NULL);
+    }
+  else
+    /* George awesomely wrote code originally to handle the
+     * could-not-fork case synchronously.  I'm not copying it, as I'm
+     * guessing that the system is pretty hosed if that's the case.
+     * However, he gets major kudos for trying. (-:
+     */
+    g_assert_not_reached ();
+}
+
+const char *
+screenshot_save_get_filename (void)
+{
+  return tmp_filename;
+}
+
+ +
+ +
+ + diff --git a/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/38.html b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/38.html new file mode 100644 index 00000000..fc472a08 --- /dev/null +++ b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/38.html @@ -0,0 +1,2009 @@ + + + + + + Cppcheck - HTML report - mate-utils + + + + + +
+ + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
+479
+480
+481
+482
+483
+484
+485
+486
+487
+488
+489
+490
+491
+492
+493
+494
+495
+496
+497
+498
+499
+500
+501
+502
+503
+504
+505
+506
+507
+508
+509
+510
+511
+512
+513
+514
+515
+516
+517
+518
+519
+520
+521
+522
+523
+524
+525
+526
+527
+528
+529
+530
+531
+532
+533
+534
+535
+536
+537
+538
+539
+540
+541
+542
+543
+544
+545
+546
+547
+548
+549
+550
+551
+552
+553
+554
+555
+556
+557
+558
+559
+560
+561
+562
+563
+564
+565
+566
+567
+568
+569
+570
+571
+572
+573
+574
+575
+576
+577
+578
+579
+580
+581
+582
+583
+584
+585
+586
+587
+588
+589
+590
+591
+592
+593
+594
+595
+596
+597
+598
+599
+600
+601
+602
+603
+604
+605
+606
+607
+608
+609
+610
+611
+612
+613
+614
+615
+616
+617
+618
+619
+620
+621
+622
+623
+624
+625
+626
+627
+628
+629
+630
+631
+632
+633
+634
+635
+636
+637
+638
+639
+640
+641
+642
+643
+644
+645
+646
+647
+648
+649
+650
+651
+652
+653
+654
+655
+656
+657
+658
+659
+660
+661
+662
+663
+664
+665
+666
+667
+668
+669
+670
+671
+672
+673
+674
+675
+676
+677
+678
+679
+680
+681
+682
+683
+684
+685
+686
+687
+688
+689
+690
+691
+692
+693
+694
+695
+696
+697
+698
+699
+700
+701
+702
+703
+704
+705
+706
+707
+708
+709
+710
+711
+712
+713
+714
+715
+716
+717
+718
+719
+720
+721
+722
+723
+724
+725
+726
+727
+728
+729
+730
+731
+732
+733
+734
+735
+736
+737
+738
+739
+740
+741
+742
+743
+744
+745
+746
+747
+748
+749
+750
+751
+752
+753
+754
+755
+756
+757
+758
+759
+760
+761
+762
+763
+764
+765
+766
+767
+768
+769
+770
+771
+772
+773
+774
+775
+776
+777
+778
+779
+780
+781
+782
+783
+784
+785
+786
+787
+788
+789
+790
+791
+792
+793
+794
+795
+796
+797
+798
+799
+800
+801
+802
+803
+804
+805
+806
+807
+808
+809
+810
+811
+812
+813
+814
+815
+816
+817
+818
+819
+820
+821
+822
+823
+824
+825
+826
+827
+828
+829
+830
+831
+832
+833
+834
+835
+836
+837
+838
+839
+840
+841
+842
+843
+844
+845
+846
+847
+848
+849
+850
+851
+852
+853
+854
+855
+856
+857
+858
+859
+860
+861
+862
+863
+864
+865
+866
+867
+868
+869
+870
+871
+872
+873
+874
+875
+876
+877
+878
+879
+880
/* Copyright (C) 2001-2006 Jonathan Blandford <jrb@alum.mit.edu>
+ * Copyright (C) 2008 Cosimo Cecchi <cosimoc@gnome.org>
+ * Copyright (C) 2012-2021 MATE Developers
+ *
+ * This file is part of MATE Utils.
+ *
+ * MATE Utils is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * MATE Utils is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MATE Utils.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "screenshot-utils.h"
+
+#include <X11/Xatom.h>
+#include <gdk/gdkx.h>
+#include <gdk/gdkkeysyms.h>
+#include <gtk/gtk.h>
+#include <glib.h>
+#include <glib/gi18n.h>
+
+#ifdef HAVE_X11_EXTENSIONS_SHAPE_H
+#include <X11/extensions/shape.h>
+#endif
+
+static GtkWidget *selection_window;
+
+#define SELECTION_NAME "_MATE_PANEL_SCREENSHOT"
+
+/* To make sure there is only one screenshot taken at a time,
+ * (Imagine key repeat for the print screen key) we hold a selection
+ * until we are done taking the screenshot
+ */
+gboolean
+screenshot_grab_lock (void)
+{
+  GdkAtom selection_atom;
+  gboolean result = FALSE;
+  GdkDisplay *display;
+
+  selection_atom = gdk_atom_intern (SELECTION_NAME, FALSE);
+  gdk_x11_grab_server ();
+
+  if (gdk_selection_owner_get (selection_atom) != NULL)
+    goto out;
+
+  selection_window = gtk_invisible_new ();
+  gtk_widget_show (selection_window);
+
+  if (!gtk_selection_owner_set (selection_window,
+				gdk_atom_intern (SELECTION_NAME, FALSE),
+				GDK_CURRENT_TIME))
+    {
+      gtk_widget_destroy (selection_window);
+      selection_window = NULL;
+      goto out;
+    }
+
+  result = TRUE;
+
+ out:
+  gdk_x11_ungrab_server ();
+
+  display = gdk_display_get_default ();
+  gdk_display_flush (display);
+
+  return result;
+}
+
+void
+screenshot_release_lock (void)
+{
+  GdkDisplay *display;
+
+  if (selection_window)
+    {
+      gtk_widget_destroy (selection_window);
+      selection_window = NULL;
+    }
+
+  display = gdk_display_get_default ();
+  gdk_display_flush (display);
+}
+
+static GdkWindow *
+screen_get_active_window (GdkScreen *screen)
+{
+  GdkWindow *ret = NULL;
+  Atom type_return;
+  gint format_return;
+  gulong nitems_return;
+  gulong bytes_after_return;
+  guchar *data = NULL;
+
+  if (!gdk_x11_screen_supports_net_wm_hint (screen,
+                                            gdk_atom_intern_static_string ("_NET_ACTIVE_WINDOW")))
+    return NULL;
+
+  if (XGetWindowProperty (GDK_DISPLAY_XDISPLAY (gdk_screen_get_display (screen)),
+                          RootWindow (GDK_DISPLAY_XDISPLAY (gdk_screen_get_display (screen)),
+                                      GDK_SCREEN_XNUMBER (screen)),
+                          gdk_x11_get_xatom_by_name_for_display (gdk_screen_get_display (screen),
+                                                                 "_NET_ACTIVE_WINDOW"),
+                          0, 1, False, XA_WINDOW, &type_return,
+                          &format_return, &nitems_return,
+                          &bytes_after_return, &data)
+      == Success)
+    {
+      if ((type_return == XA_WINDOW) && (format_return == 32) && (data))
+        {
+          Window window = *(Window *) data;
+
+          if (window != None)
+            {
+              ret = gdk_x11_window_foreign_new_for_display (gdk_screen_get_display (screen),
+                                                            window);
+            }
+        }
+    }
+
+  if (data)
+    XFree (data);
+
+  return ret;
+}
+
+static GdkWindow *
+screenshot_find_active_window (void)
+{
+  GdkWindow *window;
+  GdkScreen *default_screen;
+
+  default_screen = gdk_screen_get_default ();
+  window = screen_get_active_window (default_screen);
+
+  return window;
+}
+
+static gboolean
+screenshot_window_is_desktop (GdkWindow *window)
+{
+  GdkWindow *root_window = gdk_get_default_root_window ();
+  GdkWindowTypeHint window_type_hint;
+
+  if (window == root_window)
+    return TRUE;
+
+  window_type_hint = gdk_window_get_type_hint (window);
+  if (window_type_hint == GDK_WINDOW_TYPE_HINT_DESKTOP)
+    return TRUE;
+
+  return FALSE;
+
+}
+
+GdkWindow *
+screenshot_find_current_window ()
+{
+  GdkWindow *current_window;
+  GdkDisplay *display;
+  GdkSeat *seat;
+  GdkDevice *device;
+
+  current_window = screenshot_find_active_window ();
+  display = gdk_window_get_display (current_window);
+  seat = gdk_display_get_default_seat (display);
+  device = gdk_seat_get_pointer (seat);
+
+  /* If there's no active window, we fall back to returning the
+   * window that the cursor is in.
+   */
+  if (!current_window)
+    current_window = gdk_device_get_window_at_position (device, NULL, NULL);
+
+  if (current_window)
+    {
+      if (screenshot_window_is_desktop (current_window))
+	/* if the current window is the desktop (e.g. caja), we
+	 * return NULL, as getting the whole screen makes more sense.
+         */
+        return NULL;
+
+      /* Once we have a window, we take the toplevel ancestor. */
+      current_window = gdk_window_get_toplevel (current_window);
+    }
+
+  return current_window;
+}
+
+typedef struct {
+  GdkRectangle rect;
+  gboolean button_pressed;
+  GtkWidget *window;
+} select_area_filter_data;
+
+static gboolean
+select_area_button_press (GtkWidget               *window,
+                          GdkEventButton          *event,
+			  select_area_filter_data *data)
+{
+  if (data->button_pressed)
+    return TRUE;
+
+  data->button_pressed = TRUE;
+  data->rect.x = event->x_root;
+  data->rect.y = event->y_root;
+
+  return TRUE;
+}
+
+static gboolean
+select_area_motion_notify (GtkWidget               *window,
+                           GdkEventMotion          *event,
+                           select_area_filter_data *data)
+{
+  GdkRectangle draw_rect;
+
+  if (!data->button_pressed)
+    return TRUE;
+
+  draw_rect.width = ABS (data->rect.x - event->x_root);
+  draw_rect.height = ABS (data->rect.y - event->y_root);
+  draw_rect.x = MIN (data->rect.x, event->x_root);
+  draw_rect.y = MIN (data->rect.y, event->y_root);
+
+  if (draw_rect.width <= 0 || draw_rect.height <= 0)
+    {
+      gtk_window_move (GTK_WINDOW (window), -100, -100);
+      gtk_window_resize (GTK_WINDOW (window), 10, 10);
+      return TRUE;
+    }
+
+  gtk_window_move (GTK_WINDOW (window), draw_rect.x, draw_rect.y);
+  gtk_window_resize (GTK_WINDOW (window), draw_rect.width, draw_rect.height);
+
+  /* We (ab)use app-paintable to indicate if we have an RGBA window */
+  if (!gtk_widget_get_app_paintable (window))
+    {
+      GdkWindow *gdkwindow = gtk_widget_get_window (window);
+
+      /* Shape the window to make only the outline visible */
+      if (draw_rect.width > 2 && draw_rect.height > 2)
+        {
+          cairo_region_t *region, *region2;
+          cairo_rectangle_int_t region_rect = {
+	    0, 0,
+            draw_rect.width - 2, draw_rect.height - 2
+          };
+
+          region = cairo_region_create_rectangle (&region_rect);
+          region_rect.x++;
+          region_rect.y++;
+          region_rect.width -= 2;
+          region_rect.height -= 2;
+          region2 = cairo_region_create_rectangle (&region_rect);
+          cairo_region_subtract (region, region2);
+
+          gdk_window_shape_combine_region (gdkwindow, region, 0, 0);
+
+          cairo_region_destroy (region);
+          cairo_region_destroy (region2);
+        }
+      else
+        gdk_window_shape_combine_region (gdkwindow, NULL, 0, 0);
+    }
+
+  return TRUE;
+}
+
+static gboolean
+select_area_button_release (GtkWidget *window,
+                            GdkEventButton *event,
+                            select_area_filter_data *data)
+{
+  if (!data->button_pressed)
+    return TRUE;
+
+  data->rect.width = ABS (data->rect.x - event->x_root);
+  data->rect.height = ABS (data->rect.y - event->y_root);
+  data->rect.x = MIN (data->rect.x, event->x_root);
+  data->rect.y = MIN (data->rect.y, event->y_root);
+
+  gtk_main_quit ();
+
+  return TRUE;
+}
+
+static gboolean
+select_area_key_press (GtkWidget *window,
+                       GdkEventKey *event,
+                       select_area_filter_data *data)
+{
+  if (event->keyval == GDK_KEY_Escape)
+    {
+      data->rect.x = 0;
+      data->rect.y = 0;
+      data->rect.width  = 0;
+      data->rect.height = 0;
+      gtk_main_quit ();
+    }
+
+  return TRUE;
+}
+
+static gboolean
+draw (GtkWidget *window, cairo_t *cr, gpointer unused)
+{
+  GtkStyleContext *style;
+
+  style = gtk_widget_get_style_context (window);
+
+  if (gtk_widget_get_app_paintable (window))
+    {
+      cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
+      cairo_set_source_rgba (cr, 0, 0, 0, 0);
+      cairo_paint (cr);
+
+      gtk_style_context_save (style);
+      gtk_style_context_add_class (style, GTK_STYLE_CLASS_RUBBERBAND);
+
+      gtk_render_background (style, cr,
+                             0, 0,
+                             gtk_widget_get_allocated_width (window),
+                             gtk_widget_get_allocated_height (window));
+      gtk_render_frame (style, cr,
+                        0, 0,
+                        gtk_widget_get_allocated_width (window),
+                        gtk_widget_get_allocated_height (window));
+
+      gtk_style_context_restore (style);
+    }
+
+  return TRUE;
+}
+
+static GtkWidget *
+create_select_window (void)
+{
+  GdkScreen *screen = gdk_screen_get_default ();
+  GtkWidget *window = gtk_window_new (GTK_WINDOW_POPUP);
+
+  GdkVisual *visual = gdk_screen_get_rgba_visual (screen);
+  if (gdk_screen_is_composited (screen) && visual)
+    {
+      gtk_widget_set_visual (window, visual);
+      gtk_widget_set_app_paintable (window, TRUE);
+    }
+
+  g_signal_connect (window, "draw", G_CALLBACK (draw), NULL);
+
+  gtk_window_move (GTK_WINDOW (window), -100, -100);
+  gtk_window_resize (GTK_WINDOW (window), 10, 10);
+  gtk_widget_show (window);
+  return window;
+}
+
+typedef struct {
+  GdkRectangle rectangle;
+  SelectAreaCallback callback;
+} CallbackData;
+
+static gboolean
+emit_select_callback_in_idle (gpointer user_data)
+{
+  CallbackData *data = user_data;
+
+  data->callback (&data->rectangle);
+
+  g_slice_free (CallbackData, data);
+
+  return FALSE;
+}
+
+void
+screenshot_select_area_async (SelectAreaCallback callback)
+{
+  GdkDisplay *display;
+  GdkCursor               *cursor;
+  GdkSeat *seat;
+  GdkGrabStatus res;
+  select_area_filter_data  data;
+  CallbackData *cb_data;
+
+  data.rect.x = 0;
+  data.rect.y = 0;
+  data.rect.width  = 0;
+  data.rect.height = 0;
+  data.button_pressed = FALSE;
+  data.window = create_select_window();
+
+  cb_data = g_slice_new0 (CallbackData);
+  cb_data->callback = callback;
+
+  g_signal_connect (data.window, "key-press-event", G_CALLBACK (select_area_key_press), &data);
+  g_signal_connect (data.window, "button-press-event", G_CALLBACK (select_area_button_press), &data);
+  g_signal_connect (data.window, "button-release-event", G_CALLBACK (select_area_button_release), &data);
+  g_signal_connect (data.window, "motion-notify-event", G_CALLBACK (select_area_motion_notify), &data);
+
+  display = gdk_display_get_default ();
+  cursor = gdk_cursor_new_for_display (display, GDK_CROSSHAIR);
+
+  seat = gdk_display_get_default_seat (display);
+
+  res = gdk_seat_grab (seat,
+                       gtk_widget_get_window (data.window),
+                       GDK_SEAT_CAPABILITY_ALL,
+                       FALSE,
+                       cursor,
+                       NULL,
+                       NULL,
+                       NULL);
+
+  if (res != GDK_GRAB_SUCCESS)
+    {
+      g_object_unref (cursor);
+      goto out;
+    }
+
+  gtk_main ();
+
+  gdk_seat_ungrab (seat);
+
+  gtk_widget_destroy (data.window);
+  g_object_unref (cursor);
+  gdk_display_flush (display);
+
+out:
+  cb_data->rectangle = data.rect;
+
+  /* FIXME: we should actually be emitting the callback When
+   * the compositor has finished re-drawing, but there seems to be no easy
+   * way to know that.
+   */
+  g_timeout_add (200, emit_select_callback_in_idle, cb_data);
+}
+
+static Window
+find_wm_window (Window xid)
+{
+  Window root, parent, *children;
+  unsigned int nchildren;
+
+  do
+    {
+      if (XQueryTree (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xid, &root,
+		      &parent, &children, &nchildren) == 0)
+	{
+	  g_warning ("Couldn't find window manager window");
+	  return None;
+	}
+
+      if (root == parent)
+	return xid;
+
+      xid = parent;
+    }
+  while (TRUE);
+}
+
+static cairo_region_t *
+make_region_with_monitors (GdkScreen *screen)
+{
+  GdkDisplay     *display;
+  cairo_region_t *region;
+  int num_monitors;
+  int i;
+
+  display = gdk_screen_get_display (screen);
+  num_monitors = gdk_display_get_n_monitors (display);
+
+  region = cairo_region_create ();
+
+  for (i = 0; i < num_monitors; i++)
+    {
+      GdkRectangle rect;
+
+      gdk_monitor_get_geometry (gdk_display_get_monitor (display, i), &rect);
+      cairo_region_union_rectangle (region, &rect);
+    }
+
+  return region;
+}
+
+static void
+blank_rectangle_in_pixbuf (GdkPixbuf *pixbuf, GdkRectangle *rect)
+{
+  int x, y;
+  int x2, y2;
+  guchar *pixels;
+  int rowstride;
+  int n_channels;
+  guchar *row;
+  gboolean has_alpha;
+
+  g_assert (gdk_pixbuf_get_colorspace (pixbuf) == GDK_COLORSPACE_RGB);
+
+  x2 = rect->x + rect->width;
+  y2 = rect->y + rect->height;
+
+  pixels = gdk_pixbuf_get_pixels (pixbuf);
+  rowstride = gdk_pixbuf_get_rowstride (pixbuf);
+  has_alpha = gdk_pixbuf_get_has_alpha (pixbuf);
+  n_channels = gdk_pixbuf_get_n_channels (pixbuf);
+
+  for (y = rect->y; y < y2; y++)
+    {
+      guchar *p;
+
+      row = pixels + y * rowstride;
+      p = row + rect->x * n_channels;
+
+      for (x = rect->x; x < x2; x++)
+	{
+	  *p++ = 0;
+	  *p++ = 0;
+	  *p++ = 0;
+
+	  if (has_alpha)
+	    *p++ = 255; /* opaque black */
+	}
+    }
+}
+
+static void
+blank_region_in_pixbuf (GdkPixbuf *pixbuf, cairo_region_t *region)
+{
+  int n_rects;
+  int i;
+  int width, height;
+  cairo_rectangle_int_t pixbuf_rect;
+
+  n_rects = cairo_region_num_rectangles (region);
+
+  width = gdk_pixbuf_get_width (pixbuf);
+  height = gdk_pixbuf_get_height (pixbuf);
+
+  pixbuf_rect.x	     = 0;
+  pixbuf_rect.y	     = 0;
+  pixbuf_rect.width  = width;
+  pixbuf_rect.height = height;
+
+  for (i = 0; i < n_rects; i++)
+    {
+      cairo_rectangle_int_t rect, dest;
+
+      cairo_region_get_rectangle (region, i, &rect);
+      if (gdk_rectangle_intersect (&rect, &pixbuf_rect, &dest))
+	blank_rectangle_in_pixbuf (pixbuf, &dest);
+
+    }
+}
+
+/* When there are multiple monitors with different resolutions, the visible area
+ * within the root window may not be rectangular (it may have an L-shape, for
+ * example).  In that case, mask out the areas of the root window which would
+ * not be visible in the monitors, so that screenshot do not end up with content
+ * that the user won't ever see.
+ */
+static void
+mask_monitors (GdkPixbuf *pixbuf, GdkWindow *root_window)
+{
+  GdkScreen *screen;
+  cairo_region_t *region_with_monitors;
+  cairo_region_t *invisible_region;
+  cairo_rectangle_int_t rect;
+  gint scale;
+
+  screen = gdk_window_get_screen (root_window);
+  scale = gdk_window_get_scale_factor (root_window);
+
+  region_with_monitors = make_region_with_monitors (screen);
+
+  rect.x = 0;
+  rect.y = 0;
+  rect.width = WidthOfScreen (gdk_x11_screen_get_xscreen (screen)) / scale;
+  rect.height = HeightOfScreen (gdk_x11_screen_get_xscreen (screen)) / scale;
+
+  invisible_region = cairo_region_create_rectangle (&rect);
+  cairo_region_subtract (invisible_region, region_with_monitors);
+
+  blank_region_in_pixbuf (pixbuf, invisible_region);
+
+  cairo_region_destroy (region_with_monitors);
+  cairo_region_destroy (invisible_region);
+}
+
+GdkPixbuf *
+screenshot_get_pixbuf (GdkWindow    *window,
+                       GdkRectangle *rectangle,
+                       gboolean      include_pointer,
+                       gboolean      include_border,
+                       gboolean      include_mask)
+{
+  GdkWindow *root;
+  GdkPixbuf *screenshot;
+  gint x_real_orig, y_real_orig, x_orig, y_orig;
+  gint width, real_width, height, real_height;
+  gint screen_width, screen_height, scale;
+
+  /* If the screenshot should include the border, we look for the WM window. */
+
+  if (include_border)
+    {
+      Window xid, wm;
+
+      xid = GDK_WINDOW_XID (window);
+      wm = find_wm_window (xid);
+
+      if (wm != None)
+        window = gdk_x11_window_foreign_new_for_display (gdk_display_get_default (), wm);
+
+      /* fallback to no border if we can't find the WM window. */
+    }
+
+  root = gdk_get_default_root_window ();
+  scale = gdk_window_get_scale_factor (root);
+
+  real_width = gdk_window_get_width (window);
+  real_height = gdk_window_get_height (window);
+
+  screen_width = WidthOfScreen (gdk_x11_screen_get_xscreen (gdk_screen_get_default ())) / scale;
+  screen_height = HeightOfScreen (gdk_x11_screen_get_xscreen (gdk_screen_get_default ())) / scale;
+
+  gdk_window_get_origin (window, &x_real_orig, &y_real_orig);
+
+  x_orig = x_real_orig;
+  y_orig = y_real_orig;
+  width  = real_width;
+  height = real_height;
+
+  if (x_orig < 0)
+    {
+      width = width + x_orig;
+      x_orig = 0;
+    }
+
+  if (y_orig < 0)
+    {
+      height = height + y_orig;
+      y_orig = 0;
+    }
+
+  if (x_orig + width > screen_width)
+    width = screen_width - x_orig;
+
+  if (y_orig + height > screen_height)
+    height = screen_height - y_orig;
+
+  if (rectangle)
+    {
+      x_orig = rectangle->x - x_orig;
+      y_orig = rectangle->y - y_orig;
+      width  = rectangle->width;
+      height = rectangle->height;
+    }
+
+  screenshot = gdk_pixbuf_get_from_window (root,
+                                           x_orig, y_orig,
+                                           width, height);
+
+  /*
+   * Masking currently only works properly with full-screen shots
+   */
+  if (include_mask)
+      mask_monitors (screenshot, root);
+
+#ifdef HAVE_X11_EXTENSIONS_SHAPE_H
+  if (include_border)
+    {
+      XRectangle *rectangles;
+      GdkPixbuf *tmp;
+      int rectangle_count, rectangle_order, i;
+
+      /* we must use XShape to avoid showing what's under the rounder corners
+       * of the WM decoration.
+       */
+
+      rectangles = XShapeGetRectangles (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
+                                        GDK_WINDOW_XID (window),
+                                        ShapeBounding,
+                                        &rectangle_count,
+                                        &rectangle_order);
+      if (rectangles && rectangle_count > 0 && window != root)
+        {
+          gboolean has_alpha = gdk_pixbuf_get_has_alpha (screenshot);
+
+          if (scale)
+            {
+              width *= scale;
+              height *= scale;
+            }
+
+          tmp = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, width, height);
+          gdk_pixbuf_fill (tmp, 0);
+
+          for (i = 0; i < rectangle_count; i++)
+            {
+              gint rec_x, rec_y;
+              gint rec_width, rec_height;
+              gint y;
+
+              rec_x = rectangles[i].x;
+              rec_y = rectangles[i].y;
+              rec_width = rectangles[i].width / scale;
+              rec_height = rectangles[i].height / scale;
+
+              if (x_real_orig < 0)
+                {
+                  rec_x += x_real_orig;
+                  rec_x = MAX(rec_x, 0);
+                  rec_width += x_real_orig;
+                }
+
+              if (y_real_orig < 0)
+                {
+                  rec_y += y_real_orig;
+                  rec_y = MAX(rec_y, 0);
+                  rec_height += y_real_orig;
+                }
+
+              if (x_orig + rec_x + rec_width > screen_width)
+                rec_width = screen_width - x_orig - rec_x;
+
+              if (y_orig + rec_y + rec_height > screen_height)
+                rec_height = screen_height - y_orig - rec_y;
+
+              if (scale)
+                {
+                  rec_width *= scale;
+                  rec_height *= scale;
+                }
+
+              for (y = rec_y; y < rec_y + rec_height; y++)
+                {
+                  guchar *src_pixels, *dest_pixels;
+                  gint x;
+
+                  src_pixels = gdk_pixbuf_get_pixels (screenshot)
+                             + y * gdk_pixbuf_get_rowstride (screenshot)
+                             + rec_x * (has_alpha ? 4 : 3);
+                  dest_pixels = gdk_pixbuf_get_pixels (tmp)
+                              + y * gdk_pixbuf_get_rowstride (tmp)
+                              + rec_x * 4;
+
+                  for (x = 0; x < rec_width; x++)
+                    {
+                      *dest_pixels++ = *src_pixels++;
+                      *dest_pixels++ = *src_pixels++;
+                      *dest_pixels++ = *src_pixels++;
+
+                      if (has_alpha)
+                        *dest_pixels++ = *src_pixels++;
+                      else
+                        *dest_pixels++ = 255;
+                    }
+                }
+            }
+
+          g_object_unref (screenshot);
+          screenshot = tmp;
+        }
+    }
+#endif /* HAVE_X11_EXTENSIONS_SHAPE_H */
+
+  /* if we have a selected area, there were by definition no cursor in the
+   * screenshot */
+  if (include_pointer && !rectangle)
+    {
+      GdkCursor *cursor;
+      GdkPixbuf *cursor_pixbuf;
+
+      cursor = gdk_cursor_new_for_display (gdk_display_get_default (), GDK_LEFT_PTR);
+      cursor_pixbuf = gdk_cursor_get_image (cursor);
+
+      if (cursor_pixbuf != NULL)
+        {
+          GdkDisplay *display;
+          GdkSeat *seat;
+          GdkDevice *device;
+          GdkRectangle r1, r2;
+          gint cx, cy, xhot, yhot;
+
+          display = gdk_window_get_display (window);
+          seat = gdk_display_get_default_seat (display);
+          device = gdk_seat_get_pointer (seat);
+
+          gdk_window_get_device_position (window, device, &cx, &cy, NULL);
+          sscanf (gdk_pixbuf_get_option (cursor_pixbuf, "x_hot"), "%d", &xhot);
+          sscanf (gdk_pixbuf_get_option (cursor_pixbuf, "y_hot"), "%d", &yhot);
+
+          if (scale)
+            {
+              cx *= scale;
+              cy *= scale;
+            }
+
+          /* in r1 we have the window coordinates */
+          r1.x = x_real_orig;
+          r1.y = y_real_orig;
+          r1.width = real_width * scale;
+          r1.height = real_height * scale;
+
+          /* in r2 we have the cursor window coordinates */
+          r2.x = cx + x_real_orig;
+          r2.y = cy + y_real_orig;
+          r2.width = gdk_pixbuf_get_width (cursor_pixbuf);
+          r2.height = gdk_pixbuf_get_height (cursor_pixbuf);
+
+          /* see if the pointer is inside the window */
+          if (gdk_rectangle_intersect (&r1, &r2, &r2))
+            {
+              gdk_pixbuf_composite (cursor_pixbuf, screenshot,
+                                    cx - xhot, cy - yhot,
+                                    r2.width, r2.height,
+                                    cx - xhot, cy - yhot,
+                                    1.0, 1.0,
+                                    GDK_INTERP_BILINEAR,
+                                    255);
+            }
+
+          g_object_unref (cursor_pixbuf);
+          g_object_unref (cursor);
+        }
+    }
+
+  return screenshot;
+}
+
+void
+screenshot_show_error_dialog (GtkWindow   *parent,
+                              const gchar *message,
+                              const gchar *detail)
+{
+  GtkWidget *dialog;
+
+  g_return_if_fail ((parent == NULL) || (GTK_IS_WINDOW (parent)));
+  g_return_if_fail (message != NULL);
+
+  dialog = gtk_message_dialog_new (parent,
+  				   GTK_DIALOG_DESTROY_WITH_PARENT,
+  				   GTK_MESSAGE_ERROR,
+  				   GTK_BUTTONS_OK,
+  				   "%s", message);
+  gtk_window_set_title (GTK_WINDOW (dialog), "");
+
+  if (detail)
+    gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+  					      "%s", detail);
+
+  if (parent && gtk_window_get_group (parent))
+    gtk_window_group_add_window (gtk_window_get_group (parent), GTK_WINDOW (dialog));
+
+  gtk_dialog_run (GTK_DIALOG (dialog));
+
+  gtk_widget_destroy (dialog);
+}
+
+void
+screenshot_show_gerror_dialog (GtkWindow   *parent,
+                               const gchar *message,
+                               GError      *error)
+{
+  g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
+  g_return_if_fail (message != NULL);
+  g_return_if_fail (error != NULL);
+
+  screenshot_show_error_dialog (parent, message, error->message);
+}
+
+ +
+ +
+ + diff --git a/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/39.html b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/39.html new file mode 100644 index 00000000..dac54fb5 --- /dev/null +++ b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/39.html @@ -0,0 +1,1027 @@ + + + + + + Cppcheck - HTML report - mate-utils + + + + + +
+ + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
/* Copyright (C) 2001-2006 Jonathan Blandford <jrb@alum.mit.edu>
+ * Copyright (C) 2008 Cosimo Cecchi <cosimoc@gnome.org>
+ * Copyright (C) 2012-2021 MATE Developers
+ *
+ * This file is part of MATE Utils.
+ *
+ * MATE Utils is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * MATE Utils is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MATE Utils.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "screenshot-xfer.h"
+
+#include <time.h>
+#include <glib/gi18n.h>
+
+typedef struct
+{
+  GtkWidget *dialog;
+  GtkWidget *progress_bar;
+  GCancellable *cancellable;<--- struct member 'TransferDialog::cancellable' is never used.
+} TransferDialog;
+
+typedef struct
+{
+  GFile *source;
+  GFile *dest;
+  GFileCopyFlags flags;
+  TransferCallback callback;
+  gpointer callback_data;
+  GCancellable *cancellable;
+  GtkWidget *parent;
+  TransferDialog *dialog;
+  TransferResult result;
+  GIOSchedulerJob *io_job;
+  char *error;
+  gint dialog_timeout_id;
+  goffset total_bytes;
+  goffset current_bytes;
+} TransferJob;
+
+typedef struct
+{
+  int resp;
+  GtkWidget *parent;
+  char *basename;
+} ErrorDialogData;
+
+static gboolean
+do_run_overwrite_confirm_dialog (gpointer _data)
+{
+  ErrorDialogData *data = _data;
+  GtkWidget *dialog;
+  gint response;
+
+  /* we need to ask the user if they want to overwrite this file */
+  dialog = gtk_message_dialog_new (GTK_WINDOW (data->parent),
+				   GTK_DIALOG_DESTROY_WITH_PARENT,
+				   GTK_MESSAGE_QUESTION,
+				   GTK_BUTTONS_NONE,
+				   _("File already exists"));
+
+  gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+					    _("The file \"%s\" already exists. "
+                                              "Would you like to replace it?"),
+					    data->basename);
+  gtk_dialog_add_button (GTK_DIALOG (dialog),
+			 "gtk-cancel",
+			 GTK_RESPONSE_CANCEL);
+  gtk_dialog_add_button (GTK_DIALOG (dialog),
+			 _("_Replace"),
+			 GTK_RESPONSE_OK);
+
+  response = gtk_dialog_run (GTK_DIALOG (dialog));
+  gtk_widget_destroy (dialog);
+
+  data->resp = response;
+
+  return FALSE;
+}
+
+static void
+transfer_dialog_response_cb (GtkDialog *d,
+                             gint response,
+                             GCancellable *cancellable)
+{
+  if (response == GTK_RESPONSE_CANCEL)
+    {
+      if (!g_cancellable_is_cancelled (cancellable))
+        {
+          g_cancellable_cancel (cancellable);
+        }
+    }
+}
+
+static gboolean
+transfer_progress_dialog_new (TransferJob *job)
+{
+  TransferDialog *dialog;
+  GtkWidget *gdialog;
+  GtkWidget *widget;
+
+  dialog = g_new0 (TransferDialog, 1);
+
+  gdialog = gtk_message_dialog_new (GTK_WINDOW (job->parent),
+                                    GTK_DIALOG_DESTROY_WITH_PARENT,
+                                    GTK_MESSAGE_OTHER,
+                                    GTK_BUTTONS_CANCEL,
+                                    _("Saving file..."));
+  widget = gtk_progress_bar_new ();
+  gtk_box_pack_start (GTK_BOX (gtk_message_dialog_get_message_area GTK_MESSAGE_DIALOG (gdialog)),
+                      widget, FALSE, 0, 0);
+  gtk_widget_show (widget);
+  dialog->progress_bar = widget;
+  dialog->dialog = gdialog;
+
+  g_signal_connect (gdialog,
+                    "response",
+                    G_CALLBACK (transfer_dialog_response_cb),
+                    job->cancellable);
+
+  job->dialog = dialog;
+  gtk_widget_show (gdialog);
+
+  return FALSE;
+}
+
+static void
+transfer_progress_dialog_start (TransferJob *job)
+{
+  /* sends to the mainloop and schedules show */
+  if (job->dialog_timeout_id == 0)
+    job->dialog_timeout_id = g_timeout_add_seconds (1,
+                                                    (GSourceFunc) transfer_progress_dialog_new,
+                                                    job);
+}
+
+static int
+run_overwrite_confirm_dialog (TransferJob *job)
+{
+  ErrorDialogData *data;
+  gboolean need_timeout;
+  int response;
+  char *basename;
+
+  basename = g_file_get_basename (job->dest);
+
+  data = g_slice_new0 (ErrorDialogData);
+  data->parent = job->parent;
+  data->basename = basename;
+
+  need_timeout = (job->dialog_timeout_id > 0);
+
+  if (need_timeout)
+    {
+      g_source_remove (job->dialog_timeout_id);
+      job->dialog_timeout_id = 0;
+    }
+
+  g_io_scheduler_job_send_to_mainloop (job->io_job,
+                                       do_run_overwrite_confirm_dialog,
+                                       data,
+                                       NULL);
+  response = data->resp;
+
+  if (need_timeout)
+    transfer_progress_dialog_start (job);
+
+  g_free (basename);
+  g_slice_free (ErrorDialogData, data);
+
+  return response;
+}
+
+static gboolean
+transfer_progress_dialog_update (TransferJob *job)
+{
+  TransferDialog *dialog = job->dialog;
+  double fraction;
+
+  fraction = ((double) job->current_bytes) / ((double) job->total_bytes);
+
+  gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (dialog->progress_bar),
+                                 fraction);
+
+  return FALSE;
+}
+
+static gboolean
+transfer_job_done (gpointer user_data)
+{
+  TransferJob *job = user_data;
+  TransferDialog *dialog;
+
+  dialog = job->dialog;
+
+  if (job->dialog_timeout_id)
+    {
+      g_source_remove (job->dialog_timeout_id);
+      job->dialog_timeout_id = 0;
+    }
+  if (dialog)
+      gtk_widget_destroy (dialog->dialog);
+
+  if (job->callback)
+    {
+      (job->callback) (job->result,
+                       job->error,
+                       job->callback_data);
+    }
+
+  g_object_unref (job->source);
+  g_object_unref (job->dest);
+  g_object_unref (job->cancellable);
+
+  g_free (dialog);
+  g_free (job->error);
+  g_slice_free (TransferJob, job);
+
+  return FALSE;
+}
+
+static void
+transfer_progress_cb (goffset current_num_bytes,
+                      goffset total_num_bytes,
+                      TransferJob *job)
+{
+  job->current_bytes = current_num_bytes;
+
+  if (!job->dialog)
+    return;
+
+  g_io_scheduler_job_send_to_mainloop_async (job->io_job,
+                                             (GSourceFunc) transfer_progress_dialog_update,
+                                             job,
+                                             NULL);
+}
+
+static goffset
+get_file_size (GFile *file)
+{
+  GFileInfo *file_info;
+  goffset size;
+
+  file_info = g_file_query_info (file,
+                                 G_FILE_ATTRIBUTE_STANDARD_SIZE,
+                                 0, NULL, NULL);
+  if (file_info != NULL)
+    {
+      size = g_file_info_get_size (file_info);
+      g_object_unref (file_info);
+    }
+  else
+    {
+      /* this should never fail as the source file is always local and in /tmp,
+       * but you never know.
+       */
+      size = -1;
+    }
+
+  return size;
+}
+
+static gboolean
+transfer_file (GIOSchedulerJob *io_job,
+               GCancellable *cancellable,
+               gpointer user_data)
+{
+  TransferJob *job = user_data;
+  GError *error;
+
+  job->io_job = io_job;
+  job->total_bytes = get_file_size (job->source);
+  if (job->total_bytes == -1)
+    {
+      /* we can't access the source file, abort early */
+      error = NULL;
+      job->result = TRANSFER_ERROR;
+      job->error = g_strdup (_("Can't access source file"));
+
+      goto out;
+    }
+
+  transfer_progress_dialog_start (job);
+
+retry:
+  error = NULL;
+  if (!g_file_copy (job->source,
+                    job->dest,
+                    job->flags,
+                    job->cancellable,
+                    (GFileProgressCallback) transfer_progress_cb,
+                    job,
+                    &error))
+    {
+      if (error->code == G_IO_ERROR_EXISTS)
+        {
+          int response;
+          /* ask the user if he wants to overwrite, otherwise
+           * return and report what happened.
+           */
+          response = run_overwrite_confirm_dialog (job);
+          if (response == GTK_RESPONSE_OK)
+            {
+              job->flags |= G_FILE_COPY_OVERWRITE;
+              g_error_free (error);
+
+              goto retry;
+            }
+          else
+            {
+              g_cancellable_cancel (job->cancellable);
+              job->result = TRANSFER_OVERWRITE;
+              goto out;
+            }
+        }
+      else if (error->code == G_IO_ERROR_CANCELLED)
+        {
+          job->result = TRANSFER_CANCELLED;
+
+          goto out;
+        }
+      else
+        {
+          /* other vfs error, abort the transfer and report
+           * the error.
+           */
+          g_cancellable_cancel (job->cancellable);
+          job->result = TRANSFER_ERROR;
+          job->error = g_strdup (error->message);
+
+          goto out;
+        }
+    }
+  else
+    {
+      /* success */
+      job->result = TRANSFER_OK;
+
+      goto out;
+    }
+
+out:
+  if (error)
+      g_error_free (error);
+
+  g_io_scheduler_job_send_to_mainloop_async (io_job,
+                                             transfer_job_done,
+                                             job,
+                                             NULL);
+  return FALSE;
+}
+
+void
+screenshot_xfer_uri (GFile *source_file,
+                     GFile *target_file,
+                     GtkWidget *parent,
+                     TransferCallback done_callback,
+                     gpointer done_callback_data)
+{
+  TransferJob *job;
+  GCancellable *cancellable;
+
+  cancellable = g_cancellable_new ();
+
+  job = g_slice_new0 (TransferJob);
+  job->parent = parent;
+  job->source = g_object_ref (source_file);
+  job->dest = g_object_ref (target_file);
+  job->flags = 0;
+  job->error = NULL;
+  job->dialog = NULL;
+  job->callback = done_callback;
+  job->callback_data = done_callback_data;
+  job->cancellable = cancellable;
+
+  g_io_scheduler_push_job (transfer_file,
+                           job,
+                           NULL, 0,
+                           job->cancellable);
+}
+
+
+ +
+ +
+ + diff --git a/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/4.html b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/4.html new file mode 100644 index 00000000..5e3fb275 --- /dev/null +++ b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/4.html @@ -0,0 +1,1593 @@ + + + + + + Cppcheck - HTML report - mate-utils + + + + + +
+ + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
+479
+480
+481
+482
+483
+484
+485
+486
+487
+488
+489
+490
+491
+492
+493
+494
+495
+496
+497
+498
+499
+500
+501
+502
+503
+504
+505
+506
+507
+508
+509
+510
+511
+512
+513
+514
+515
+516
+517
+518
+519
+520
+521
+522
+523
+524
+525
+526
+527
+528
+529
+530
+531
+532
+533
+534
+535
+536
+537
+538
+539
+540
+541
+542
+543
+544
+545
+546
+547
+548
+549
+550
+551
+552
+553
+554
+555
+556
+557
+558
+559
+560
+561
+562
+563
+564
+565
+566
+567
+568
+569
+570
+571
+572
+573
+574
+575
+576
+577
+578
+579
+580
+581
+582
+583
+584
+585
+586
+587
+588
+589
+590
+591
+592
+593
+594
+595
+596
+597
+598
+599
+600
+601
+602
+603
+604
+605
+606
+607
+608
+609
+610
+611
+612
+613
+614
+615
+616
+617
+618
+619
+620
+621
+622
+623
+624
+625
+626
+627
+628
+629
+630
+631
+632
+633
+634
+635
+636
+637
+638
+639
+640
+641
+642
+643
+644
+645
+646
+647
+648
+649
+650
+651
+652
+653
+654
+655
+656
+657
+658
+659
+660
+661
+662
+663
+664
+665
+666
/* Copyright (C) 2008 Igalia
+ * Copyright (C) 2012-2021 MATE Developers
+ *
+ * This file is part of MATE Utils.
+ *
+ * MATE Utils is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * MATE Utils is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MATE Utils.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ *   Felipe Erias <femorandeira@igalia.com>
+ *   Pablo Santamaria <psantamaria@igalia.com>
+ *   Jacobo Aragunde <jaragunde@igalia.com>
+ *   Eduardo Lima <elima@igalia.com>
+ *   Mario Sanchez <msanchez@igalia.com>
+ *   Miguel Gomez <magomez@igalia.com>
+ *   Henrique Ferreiro <hferreiro@igalia.com>
+ *   Alejandro Pinheiro <apinheiro@igalia.com>
+ *   Carlos Sanmartin <csanmartin@igalia.com>
+ *   Alejandro Garcia <alex@igalia.com>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <math.h>
+#include <string.h>
+
+#include <gtk/gtk.h>
+#include <pango/pangocairo.h>
+
+#include "baobab-chart.h"
+#include "baobab-ringschart.h"
+
+#define ITEM_BORDER_WIDTH  1
+#define CHART_PADDING     13
+#define ITEM_MIN_ANGLE     0.03
+#define EDGE_ANGLE         0.004
+
+#define SUBFOLDER_TIP_PADDING 3
+
+typedef struct _BaobabRingschartItem BaobabRingschartItem;
+
+struct _BaobabRingschartItem
+{
+  gdouble min_radius;
+  gdouble max_radius;
+  gdouble start_angle;
+  gdouble angle;
+  gboolean continued;
+};
+
+struct _BaobabRingschartPrivate
+{
+  gboolean subfoldertips_enabled;
+  BaobabChartItem *highlighted_item;
+  guint tips_timeout_event;
+  GList *subtip_items;
+  gboolean drawing_subtips;
+  guint subtip_timeout;
+};
+
+G_DEFINE_TYPE_WITH_PRIVATE (BaobabRingschart, baobab_ringschart, BAOBAB_CHART_TYPE);
+
+static void baobab_ringschart_draw_sector (cairo_t *cr,
+                                           gdouble center_x, gdouble center_y,
+                                           gdouble radius, gdouble thickness,
+                                           gdouble init_angle, gdouble final_angle,
+                                           BaobabChartColor fill_color,
+                                           gboolean continued, guint border);
+static void baobab_ringschart_draw_item (GtkWidget *chart,
+                                         cairo_t *cr,
+                                         BaobabChartItem *item,
+                                         gboolean highlighted);
+static void baobab_ringschart_calculate_item_geometry (GtkWidget *chart,
+                                                       BaobabChartItem *item);
+static gboolean baobab_ringschart_is_point_over_item (GtkWidget *chart,
+                                                      BaobabChartItem *item,
+                                                      gdouble x,
+                                                      gdouble y);
+static void baobab_ringschart_get_point_min_rect (gdouble cx, gdouble cy,
+                                                  gdouble radius, gdouble angle,
+                                                  GdkRectangle *rect);
+static void baobab_ringschart_get_item_rectangle (GtkWidget *chart,
+                                                  BaobabChartItem *item);
+static void baobab_ringschart_pre_draw (GtkWidget *chart, cairo_t *cr);
+static void baobab_ringschart_post_draw (GtkWidget *chart, cairo_t *cr);
+
+static void
+baobab_ringschart_class_init (BaobabRingschartClass *class)
+{
+  BaobabChartClass *chart_class;
+
+  chart_class = BAOBAB_CHART_CLASS (class);
+
+  /* BaobabChart abstract methods */
+  chart_class->draw_item = baobab_ringschart_draw_item;
+  chart_class->calculate_item_geometry = baobab_ringschart_calculate_item_geometry;
+  chart_class->is_point_over_item = baobab_ringschart_is_point_over_item;
+  chart_class->get_item_rectangle = baobab_ringschart_get_item_rectangle;
+  chart_class->pre_draw = baobab_ringschart_pre_draw;
+  chart_class->post_draw = baobab_ringschart_post_draw;
+}
+
+static void
+baobab_ringschart_init (BaobabRingschart *chart)
+{
+  BaobabRingschartPrivate *priv;
+  GtkSettings* settings;
+  gint timeout;
+
+  priv = baobab_ringschart_get_instance_private (chart);
+
+  priv->subfoldertips_enabled = FALSE;
+  priv->highlighted_item = NULL;
+  priv->tips_timeout_event = 0;
+  priv->subtip_items = NULL;
+  priv->drawing_subtips = FALSE;
+
+  settings = gtk_settings_get_default ();
+  g_object_get (G_OBJECT (settings), "gtk-tooltip-timeout", &timeout, NULL);
+  priv->subtip_timeout = 2 * (guint)timeout;
+}
+
+static void
+baobab_ringschart_draw_sector (cairo_t *cr,
+                               gdouble center_x,
+                               gdouble center_y,
+                               gdouble radius,
+                               gdouble thickness,
+                               gdouble init_angle,
+                               gdouble final_angle,
+                               BaobabChartColor fill_color,
+                               gboolean continued,
+                               guint border)
+{
+  cairo_set_line_width (cr, border);
+  if (radius > 0)
+    cairo_arc (cr, center_x, center_y, radius, init_angle, final_angle);
+  cairo_arc_negative (cr, center_x, center_y, radius+thickness,
+                      final_angle, init_angle);
+  cairo_close_path(cr);
+
+  cairo_set_source_rgb (cr, fill_color.red, fill_color.green, fill_color.blue);
+  cairo_fill_preserve (cr);
+  cairo_set_source_rgb (cr, 0, 0, 0);
+  cairo_stroke (cr);
+
+  if (continued)
+    {
+      cairo_set_line_width (cr, 3);
+      cairo_arc (cr, center_x, center_y, radius+thickness + 4,
+                 init_angle+EDGE_ANGLE, final_angle-EDGE_ANGLE);
+      cairo_stroke (cr);
+    }
+}
+
+static void
+baobab_ringschart_draw_item (GtkWidget *chart,
+                             cairo_t *cr,
+                             BaobabChartItem *item,
+                             gboolean highlighted)
+{
+  BaobabRingschartPrivate *priv;
+  BaobabRingschartItem *data;
+  BaobabChartColor fill_color;
+  GtkAllocation allocation;
+
+  priv = baobab_ringschart_get_instance_private (BAOBAB_RINGSCHART (chart));
+
+  data = (BaobabRingschartItem *) item->data;
+
+  if (priv->drawing_subtips)
+    if ( (priv->highlighted_item) && (item->parent) &&
+         (((BaobabChartItem *) item->parent->data) == priv->highlighted_item) )
+      {
+        GList *node;
+        node = g_new0 (GList, 1);
+        node->data = (gpointer) item;
+
+        node->next = priv->subtip_items;
+        if (priv->subtip_items)
+          priv->subtip_items->prev = node;
+        priv->subtip_items = node;
+      }
+
+  baobab_chart_get_item_color (&fill_color,
+                               data->start_angle / M_PI * 99,
+                               item->depth,
+                               highlighted);
+
+  gtk_widget_get_allocation (chart, &allocation);
+  baobab_ringschart_draw_sector (cr,
+                                 allocation.width / 2,
+                                 allocation.height / 2,
+                                 data->min_radius,
+                                 data->max_radius - data->min_radius,
+                                 data->start_angle,
+                                 data->start_angle + data->angle,
+                                 fill_color,
+                                 data->continued,
+                                 ITEM_BORDER_WIDTH);
+}
+
+static void
+baobab_ringschart_calculate_item_geometry (GtkWidget *chart,
+                                           BaobabChartItem *item)
+{
+  BaobabRingschartItem *data;
+  BaobabRingschartItem p_data;
+  BaobabChartItem *parent = NULL;
+  GtkAllocation allocation;
+
+  gdouble max_radius;
+  gdouble thickness;
+  guint max_depth;
+
+  max_depth = baobab_chart_get_max_depth (chart);
+
+  if (item->data == NULL)
+    item->data = g_new (BaobabRingschartItem, 1);
+
+  data = (BaobabRingschartItem *) item->data;
+
+  data->continued = FALSE;
+  item->visible = FALSE;
+
+  gtk_widget_get_allocation (chart, &allocation);
+  max_radius = MIN (allocation.width / 2, allocation.height / 2) - CHART_PADDING;
+  thickness = max_radius / (max_depth + 1);
+
+  if (item->parent == NULL)
+    {
+      data->min_radius = 0;
+      data->max_radius = thickness;
+      data->start_angle = 0;
+      data->angle = 2 * M_PI;
+    }
+  else
+    {
+      parent = (BaobabChartItem *) item->parent->data;
+      g_memmove (&p_data, parent->data, sizeof (BaobabRingschartItem));
+
+      data->min_radius = (item->depth) * thickness;
+
+      if (data->min_radius + thickness > max_radius)
+        return;
+      else
+        data->max_radius = data->min_radius + thickness;
+
+      data->angle = p_data.angle * item->rel_size / 100;
+      if (data->angle < ITEM_MIN_ANGLE)
+        return;
+
+      data->start_angle = p_data.start_angle + p_data.angle * item->rel_start / 100;
+
+      data->continued = (item->has_any_child) && (item->depth == max_depth);
+
+      parent->has_visible_children = TRUE;
+    }
+
+  item->visible = TRUE;
+  baobab_ringschart_get_item_rectangle (chart, item);
+}
+
+static gboolean
+baobab_ringschart_is_point_over_item (GtkWidget *chart,
+                                      BaobabChartItem *item,
+                                      gdouble x,
+                                      gdouble y)
+{
+  BaobabRingschartItem *data;
+  gdouble radius, angle;
+  GtkAllocation allocation;
+
+  data = (BaobabRingschartItem *) item->data;
+  gtk_widget_get_allocation (chart, &allocation);
+  x = x - allocation.width / 2;
+  y = y - allocation.height / 2;
+
+  radius = sqrt (x*x + y*y);
+  angle = atan2 (y, x);
+  angle = (angle > 0) ? angle : angle + 2*G_PI;
+
+  return (radius >= data->min_radius) &&
+         (radius <= data->max_radius) &&
+         (angle >= data->start_angle) &&
+         (angle <= data->start_angle + data->angle);
+}
+
+static void
+baobab_ringschart_get_point_min_rect (gdouble cx,
+                                      gdouble cy,
+                                      gdouble radius,
+                                      gdouble angle,
+                                      GdkRectangle *rect)
+{
+  int x, y;
+
+  x = (int) (cx + cos (angle) * radius);
+  y = (int) (cy + sin (angle) * radius);
+
+  rect->x = MIN (rect->x, x);
+  rect->y = MIN (rect->y, y);
+  rect->width = MAX (rect->width, x);
+  rect->height = MAX (rect->height, y);
+}
+
+static void
+baobab_ringschart_get_item_rectangle (GtkWidget *chart,
+                                       BaobabChartItem *item)
+{
+  BaobabRingschartItem *data;
+  GdkRectangle rect;
+  gdouble cx, cy, r1, r2, a1, a2;
+  GtkAllocation allocation;
+
+  data = (BaobabRingschartItem *) item->data;
+
+  gtk_widget_get_allocation (chart, &allocation);
+  cx = allocation.width / 2;
+  cy = allocation.height / 2;
+  r1 = data->min_radius;
+  r2 = data->max_radius;
+  a1 = data->start_angle;
+  a2 = data->start_angle + data->angle;
+
+  rect.x = allocation.width;
+  rect.y = allocation.height;
+  rect.width = 0;
+  rect.height = 0;
+
+  baobab_ringschart_get_point_min_rect (cx, cy, r1, a1, &rect);
+  baobab_ringschart_get_point_min_rect (cx, cy, r2, a1, &rect);
+  baobab_ringschart_get_point_min_rect (cx, cy, r1, a2, &rect);
+  baobab_ringschart_get_point_min_rect (cx, cy, r2, a2, &rect);
+
+  if ( (a1 <= M_PI/2) && (a2 >= M_PI/2) )
+    rect.height = MAX (rect.height, (int) (cy + sin (M_PI/2) * r2));
+
+  if ( (a1 <= M_PI) && (a2 >= M_PI) )
+    rect.x = MIN (rect.x, (int) (cx + cos (M_PI) * r2));
+
+  if ( (a1 <= M_PI*1.5) && (a2 >= M_PI*1.5) )
+    rect.y = MIN (rect.y, (int) (cy + sin (M_PI*1.5) * r2));
+
+  if ( (a1 <= M_PI*2) && (a2 >= M_PI*2) )
+    rect.width = MAX (rect.width, (int) (cx + cos (M_PI*2) * r2));
+
+  rect.width -= rect.x;
+  rect.height -= rect.y;
+
+  item->rect = rect;
+}
+
+static gboolean
+baobab_ringschart_subfolder_tips_timeout (gpointer data)
+{
+  BaobabRingschartPrivate *priv;
+
+  priv = baobab_ringschart_get_instance_private (BAOBAB_RINGSCHART (data));
+
+  priv->drawing_subtips = TRUE;
+
+  gtk_widget_queue_draw (GTK_WIDGET (data));
+
+  return FALSE;
+}
+
+static void
+baobab_ringschart_clean_subforlder_tips_state (GtkWidget *chart)
+{
+  BaobabRingschartPrivate *priv;
+  GList *node;
+
+  priv = baobab_ringschart_get_instance_private (BAOBAB_RINGSCHART (chart));
+
+  if (priv->drawing_subtips)
+    gtk_widget_queue_draw (chart);
+
+  priv->drawing_subtips = FALSE;
+
+  if (priv->highlighted_item == NULL)
+    return;
+
+  if (priv->tips_timeout_event)
+    {
+      g_source_remove (priv->tips_timeout_event);
+      priv->tips_timeout_event = 0;
+    }
+
+  priv->highlighted_item = NULL;
+
+  /* Free subtip_items GList */
+  node = priv->subtip_items;
+  while (node != NULL)
+    {
+      priv->subtip_items = node->next;
+      g_free (node);
+
+      node = priv->subtip_items;
+    }
+  priv->subtip_items = NULL;
+}
+
+static void
+baobab_ringschart_draw_subfolder_tips (GtkWidget *chart, cairo_t *cr)
+{
+  BaobabRingschartPrivate *priv;
+  GList *node;
+  BaobabChartItem *item;
+  BaobabRingschartItem *data;
+
+  gdouble q_angle, q_width, q_height;
+
+  gdouble tip_x, tip_y;
+  gdouble middle_angle, middle_angle_n, middle_radius;
+  gdouble sector_center_x, sector_center_y;
+  gdouble a;
+  guint i;
+  GtkAllocation allocation;
+
+  PangoLayout *layout;
+  PangoRectangle layout_rect;
+  gchar *markup = NULL;
+
+  cairo_rectangle_t tooltip_rect;
+  GdkRectangle _rect, last_rect;
+
+  priv = baobab_ringschart_get_instance_private (BAOBAB_RINGSCHART (chart));
+
+  gtk_widget_get_allocation (chart, &allocation);
+  q_width = allocation.width / 2;
+  q_height = allocation.height / 2;
+  q_angle = atan2 (q_height, q_width);
+
+  memset (&last_rect, 0, sizeof (GdkRectangle));
+
+  cairo_save (cr);
+
+  node = priv->subtip_items;
+  while (node != NULL)
+    {
+      item = (BaobabChartItem *) node->data;
+      data = (BaobabRingschartItem *) item->data;
+
+      /* get the middle angle */
+      middle_angle = data->start_angle + data->angle / 2;
+
+      /* normalize the middle angle (take it to the first quadrant) */
+      middle_angle_n = middle_angle;
+      while (middle_angle_n > M_PI/2)
+        middle_angle_n -= M_PI;
+      middle_angle_n = ABS (middle_angle_n);
+
+      /* get the pango layout and its enclosing rectangle */
+      layout = gtk_widget_create_pango_layout (chart, NULL);
+      markup = g_strconcat ("<span size=\"small\">", item->name, "</span>", NULL);
+      pango_layout_set_markup (layout, markup, -1);
+      g_free (markup);
+      pango_layout_set_indent (layout, 0);
+      pango_layout_set_spacing (layout, 0);
+      pango_layout_get_pixel_extents (layout, NULL, &layout_rect);
+
+      /* get the center point of the tooltip rectangle */
+      if (middle_angle_n < q_angle)
+        {
+          tip_x = q_width - layout_rect.width/2 - SUBFOLDER_TIP_PADDING * 2;
+          tip_y = tan (middle_angle_n) * tip_x;
+        }
+      else
+        {
+          tip_y = q_height - layout_rect.height/2 - SUBFOLDER_TIP_PADDING * 2;
+          tip_x = tip_y / tan (middle_angle_n);
+        }
+
+      /* get the tooltip rectangle */
+      tooltip_rect.x = q_width + tip_x - layout_rect.width/2 - SUBFOLDER_TIP_PADDING;
+      tooltip_rect.y = q_height + tip_y - layout_rect.height/2 - SUBFOLDER_TIP_PADDING;
+      tooltip_rect.width = layout_rect.width + SUBFOLDER_TIP_PADDING * 2;
+      tooltip_rect.height = layout_rect.height + SUBFOLDER_TIP_PADDING * 2;
+
+      /* Check tooltip's width is not greater than half of the widget */
+      if (tooltip_rect.width > q_width)
+        {
+          g_object_unref (layout);
+          node = node->next;
+          continue;
+        }
+
+      /* translate tooltip rectangle and edge angles to the original quadrant */
+      a = middle_angle;
+      i = 0;
+      while (a > M_PI/2)
+        {
+          if (i % 2 == 0)
+            tooltip_rect.x = allocation.width - tooltip_rect.x
+                             - tooltip_rect.width;
+          else
+            tooltip_rect.y = allocation.height - tooltip_rect.y
+                             - tooltip_rect.height;
+
+          i++;
+          a -= M_PI/2;
+        }
+
+      /* get the GdkRectangle of the tooltip (with a little padding) */
+      _rect.x = (int) (tooltip_rect.x - 1.0);
+      _rect.y = (int) (tooltip_rect.y - 1.0);
+      _rect.width = (int) (tooltip_rect.width + 2.0);
+      _rect.height = (int) (tooltip_rect.height + 2.0);
+
+      /* Check if tooltip overlaps */
+      if (! gdk_rectangle_intersect (&_rect, &last_rect, NULL))
+        {
+          g_memmove (&last_rect, &_rect, sizeof (GdkRectangle));
+
+          /* Finally draw the tooltip to cairo! */
+
+          /* TODO: Do not hardcode colors */
+
+          /* avoid blurred lines */
+          tooltip_rect.x = floor (tooltip_rect.x) + 0.5;
+          tooltip_rect.y = floor (tooltip_rect.y) + 0.5;
+
+          middle_radius = data->min_radius + (data->max_radius - data->min_radius) / 2;
+          sector_center_x = q_width + middle_radius * cos (middle_angle);
+          sector_center_y = q_height + middle_radius * sin (middle_angle);
+
+          /* draw line from sector center to tooltip center */
+          cairo_set_line_width (cr, 1);
+          cairo_move_to (cr, sector_center_x, sector_center_y);
+          cairo_set_source_rgb (cr, 0.8275, 0.8431, 0.8118); /* tango: #d3d7cf */
+          cairo_line_to (cr, tooltip_rect.x + tooltip_rect.width / 2,
+                             tooltip_rect.y + tooltip_rect.height / 2);
+          cairo_stroke (cr);
+
+          /* draw a tiny circle in sector center */
+          cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 0.6666 );
+          cairo_arc (cr, sector_center_x, sector_center_y, 1.0, 0, 2 * G_PI );
+          cairo_stroke (cr);
+
+          /* draw tooltip box */
+          cairo_set_line_width (cr, 0.5);
+          cairo_rectangle (cr, tooltip_rect.x, tooltip_rect.y,
+                               tooltip_rect.width, tooltip_rect.height);
+          cairo_set_source_rgb (cr, 0.8275, 0.8431, 0.8118);  /* tango: #d3d7cf */
+          cairo_fill_preserve(cr);
+          cairo_set_source_rgb (cr, 0.5333, 0.5412, 0.5216);  /* tango: #888a85 */
+          cairo_stroke (cr);
+
+          /* draw the text inside the box */
+          cairo_set_source_rgb (cr, 0, 0, 0);
+          cairo_move_to (cr, tooltip_rect.x + SUBFOLDER_TIP_PADDING,
+                             tooltip_rect.y + SUBFOLDER_TIP_PADDING);
+          pango_cairo_show_layout (cr, layout);
+          cairo_set_line_width (cr, 1);
+          cairo_stroke (cr);
+        }
+
+      /* Free stuff */
+      g_object_unref (layout);
+
+      node = node->next;
+    }
+
+  cairo_restore (cr);
+}
+
+static void
+baobab_ringschart_pre_draw (GtkWidget *chart, cairo_t *cr)
+{
+  BaobabRingschartPrivate *priv;
+  BaobabChartItem *hl_item;
+
+  priv = baobab_ringschart_get_instance_private (BAOBAB_RINGSCHART (chart));
+
+  hl_item = baobab_chart_get_highlighted_item (chart);
+
+  if ( (hl_item == NULL) || (! hl_item->has_visible_children) )
+    {
+      baobab_ringschart_clean_subforlder_tips_state (chart);
+
+      return;
+    }
+
+  if (hl_item != priv->highlighted_item)
+    {
+      baobab_ringschart_clean_subforlder_tips_state (chart);
+
+      priv->highlighted_item = hl_item;
+
+      /* Launch timer to show subfolder tooltips */
+      priv->tips_timeout_event = g_timeout_add (priv->subtip_timeout,
+                        (GSourceFunc) baobab_ringschart_subfolder_tips_timeout,
+                        (gpointer) chart);
+    }
+}
+
+static void
+baobab_ringschart_post_draw (GtkWidget *chart, cairo_t *cr)
+{
+  BaobabRingschartPrivate *priv;
+
+  priv = baobab_ringschart_get_instance_private (BAOBAB_RINGSCHART (chart));
+
+  if (priv->subfoldertips_enabled)
+    {
+      /* Reverse the glist, which was created from the tail */
+      priv->subtip_items = g_list_reverse (priv->subtip_items);
+
+      baobab_ringschart_draw_subfolder_tips (chart, cr);
+    }
+}
+
+/* Public functions start here */
+
+/**
+ * baobab_ringschart_new:
+ *
+ * Constructor for the baobab_ringschart class
+ *
+ * Returns: a new #BaobabRingschart object
+ *
+ **/
+GtkWidget *
+baobab_ringschart_new (void)
+{
+  return g_object_new (BAOBAB_RINGSCHART_TYPE, NULL);
+}
+
+/**
+ * baobab_ringschart_set_subfoldertips_enabled:
+ * @chart: the #BaobabRingschart to set the
+ * @enabled: boolean to determine whether to show sub-folder tips.
+ *
+ * Enables/disables drawing tooltips of sub-forlders of the highlighted sector.
+ *
+ * Fails if @chart is not a #BaobabRingschart.
+ *
+ **/
+void
+baobab_ringschart_set_subfoldertips_enabled (GtkWidget *chart, gboolean enabled)
+{
+  BaobabRingschartPrivate *priv;
+
+  priv = baobab_ringschart_get_instance_private (BAOBAB_RINGSCHART (chart));
+
+  priv->subfoldertips_enabled = enabled;
+
+  if ( (! enabled) && (priv->drawing_subtips) )
+    {
+      /* Turn off currently drawn tips */
+      baobab_ringschart_clean_subforlder_tips_state (chart);
+    }
+}
+
+ +
+ +
+ + diff --git a/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/5.html b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/5.html new file mode 100644 index 00000000..c04202b5 --- /dev/null +++ b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/5.html @@ -0,0 +1,1021 @@ + + + + + + Cppcheck - HTML report - mate-utils + + + + + +
+ + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
/* Copyright (C) 2005-2006 Fabio Marzocca <thesaltydog@gmail.com>
+ * Copyright (C) 2012-2021 MATE Developers
+ *
+ * This file is part of MATE Utils.
+ *
+ * MATE Utils is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * MATE Utils is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MATE Utils.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+
+#include <glib.h>
+#include <gtk/gtk.h>
+#include <gio/gio.h>
+
+#include "baobab.h"
+#include "baobab-utils.h"
+#include "baobab-scan.h"
+
+/*
+   Hardlinks handling.
+
+   As long as we're optimistic about hardlinks count
+   over the whole system (250 files with st_nlink > 1 here),
+   we keep linear search. If it turns out to be an bottleneck
+   we can switch to an hash table or tree.
+
+   TODO: get real timings about this code. find out the average
+   number of files with st_nlink > 1 on average computer.
+
+   To save memory, we store only { inode, dev } instead of full
+   GFileInfo.
+
+   EDIT: /me stupid. I realize that this code was not called that often
+   1 call per file with st_nlink > 1. BUT, i'm using pdumpfs to backup
+   my /etc. pdumpfs massively uses hard links. So there are more than
+   5000 files with st_nlink > 1. I believe this is the worst case.
+*/
+
+typedef struct {
+	guint64		    inode;
+	dev_t               device;
+} BaobabHardLink;
+
+typedef GArray BaobabHardLinkArray;
+
+static BaobabHardLinkArray *
+baobab_hardlinks_array_create (void)
+{
+	return g_array_new (FALSE, FALSE, sizeof(BaobabHardLink));
+}
+
+static gboolean
+baobab_hardlinks_array_has (BaobabHardLinkArray *a,
+			    BaobabHardLink      *s)
+{
+	guint i;
+
+	for (i = 0; i < a->len; ++i) {
+		BaobabHardLink *cur = &g_array_index (a, BaobabHardLink, i);
+
+		/*
+		 * cur->st_dev == s->st_dev is the common case and may be more
+		 * expansive than cur->st_ino == s->st_ino
+		 * so keep this order */
+		if (cur->inode == s->inode && cur->device == s->device)
+			return TRUE;
+	}
+
+	return FALSE;
+}
+
+/* return FALSE if the element was already in the array */
+static gboolean
+baobab_hardlinks_array_add (BaobabHardLinkArray *a,
+			    GFileInfo           *s)
+{
+
+	if (g_file_info_has_attribute (s, G_FILE_ATTRIBUTE_UNIX_INODE) &&
+	    g_file_info_has_attribute (s, G_FILE_ATTRIBUTE_UNIX_DEVICE))
+	{
+		BaobabHardLink hl;
+
+		hl.inode = g_file_info_get_attribute_uint64 (s,
+				G_FILE_ATTRIBUTE_UNIX_INODE);
+		hl.device = g_file_info_get_attribute_uint32 (s,
+				G_FILE_ATTRIBUTE_UNIX_DEVICE);
+
+		if (baobab_hardlinks_array_has (a, &hl))
+			return FALSE;
+
+		g_array_append_val (a, hl);
+
+		return TRUE;
+	}
+	else
+	{
+		g_warning ("Could not obtain inode and device for hardlink");
+	}
+
+	return FALSE;
+}
+
+static void
+baobab_hardlinks_array_free (BaobabHardLinkArray *a)
+{
+/*	g_print ("HL len was %d\n", a->len); */
+
+	g_array_free (a, TRUE);
+}
+
+#define BLOCK_SIZE 512UL
+
+struct allsizes {
+	guint64 size;
+	guint64 alloc_size;
+	guint depth;
+};
+
+static const char *dir_attributes = \
+	G_FILE_ATTRIBUTE_STANDARD_NAME "," \
+	G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME "," \
+	G_FILE_ATTRIBUTE_STANDARD_TYPE "," \
+	G_FILE_ATTRIBUTE_STANDARD_SIZE "," \
+	G_FILE_ATTRIBUTE_UNIX_BLOCKS "," \
+	G_FILE_ATTRIBUTE_UNIX_NLINK "," \
+	G_FILE_ATTRIBUTE_UNIX_INODE "," \
+	G_FILE_ATTRIBUTE_UNIX_DEVICE "," \
+	G_FILE_ATTRIBUTE_ACCESS_CAN_READ;
+
+static gboolean
+is_in_dot_gvfs (GFile *file)
+{
+	static GFile *dot_gvfs_dir = NULL;
+	GFile *parent;
+	gboolean res = FALSE;
+
+	if (dot_gvfs_dir == NULL)
+	{
+		gchar *dot_gvfs;
+
+		dot_gvfs = g_build_filename (g_get_home_dir (), ".gvfs", NULL);
+
+		dot_gvfs_dir = g_file_new_for_path (dot_gvfs);
+
+		g_free (dot_gvfs);
+	}
+
+	parent = g_file_get_parent (file);
+
+	if (parent != NULL)
+	{
+		res = g_file_equal (parent, dot_gvfs_dir);
+		g_object_unref (parent);
+	}
+
+	return res;
+}
+
+static struct allsizes
+loopdir (GFile *file,
+	 GFileInfo *info,
+	 guint count,
+	 BaobabHardLinkArray *hla,
+	 gint current_depth)
+{
+	guint64 tempHLsize = 0;
+	gint elements = 0;
+	struct chan_data data;
+	struct allsizes retloop, temp;
+	GFileInfo *temp_info;
+	GFileEnumerator *file_enum;
+	gchar *dir_uri = NULL;
+	gchar *display_name = NULL;
+	gchar *parse_name = NULL;
+	GError *err = NULL;
+
+	count++;
+	retloop.size = 0;
+	retloop.alloc_size = 0;
+	retloop.depth = 0;
+
+	/* Skip the user excluded folders */
+	if (baobab_is_excluded_location (file))
+		goto exit;
+
+	/* Skip the virtual file systems */
+	if (is_virtual_filesystem (file))
+ 		goto exit;
+
+	/* FIXME: skip dirs in ~/.gvfs. It would be better to have a way
+	 * to check if a file is a FUSE mountpoint instead of just
+	 * hardcoding .gvfs */
+	if (is_in_dot_gvfs (file))
+		goto exit;
+
+	parse_name = g_file_get_parse_name (file);
+
+	if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_SIZE)) {
+		goffset file_size = g_file_info_get_size (info);
+		retloop.size = (guint64) file_size;
+	}
+
+	if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_UNIX_BLOCKS))
+		retloop.alloc_size = BLOCK_SIZE *
+			g_file_info_get_attribute_uint64 (info,
+							  G_FILE_ATTRIBUTE_UNIX_BLOCKS);
+
+	if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME))
+		display_name = g_strdup (g_file_info_get_display_name (info));
+	else
+		/* paranoid fallback */
+		display_name = g_filename_display_basename (g_file_info_get_name (info));
+
+	/* load up the file enumerator */
+	file_enum = g_file_enumerate_children (file,
+					       dir_attributes,
+					       G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
+					       NULL,
+					       &err);
+
+	if (file_enum == NULL) {
+		if (!g_error_matches (err, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED)) {
+			g_warning ("couldn't get dir enum for dir %s: %s\n",
+			   	parse_name, err->message);
+		}
+		goto exit;
+	}
+
+	/* All skipped folders (i.e. bad type, excluded, /proc) must be
+	   skept *before* this point. Everything passes the prefill-model
+	   will be part of the GUI. */
+
+	/* prefill the model */
+	data.size = 1UL;
+	data.alloc_size = 1UL;
+	data.depth = (gint) count - 1;
+	data.elements = -1;
+	data.display_name = display_name;
+	data.parse_name = parse_name;
+	data.tempHLsize = tempHLsize;
+	baobab_fill_model (&data);
+
+	g_clear_error (&err);
+	while ((temp_info = g_file_enumerator_next_file (file_enum,
+							 NULL,
+							 &err)) != NULL) {
+		GFileType temp_type = g_file_info_get_file_type (temp_info);
+		if (baobab.STOP_SCANNING) {
+			g_object_unref (temp_info);
+			g_object_unref (file_enum);
+			goto exit;
+		}
+
+		/* is a directory? */
+		if (temp_type == G_FILE_TYPE_DIRECTORY) {
+			GFile *child_dir = g_file_get_child (file,
+						g_file_info_get_name (temp_info));
+			temp = loopdir (child_dir, temp_info, count, hla, current_depth+1);
+			retloop.size += temp.size;
+			retloop.alloc_size += temp.alloc_size;
+			retloop.depth = ((temp.depth + 1) > retloop.depth) ? temp.depth + 1 : retloop.depth;
+			elements++;
+			g_object_unref (child_dir);
+		}
+
+		/* is it a regular file? */
+		else if (temp_type == G_FILE_TYPE_REGULAR) {
+
+			/* check for hard links only on local files */
+			if (g_file_info_has_attribute (temp_info,
+						       G_FILE_ATTRIBUTE_UNIX_NLINK) &&
+				g_file_info_get_attribute_uint32 (temp_info,
+							    G_FILE_ATTRIBUTE_UNIX_NLINK) > 1) {
+
+				if (!baobab_hardlinks_array_add (hla, temp_info)) {
+					/* we already acconted for it */
+					goffset file_size = g_file_info_get_size (temp_info);
+					tempHLsize += (guint64) file_size;
+					g_object_unref (temp_info);
+					continue;
+				}
+			}
+
+			if (g_file_info_has_attribute (temp_info, G_FILE_ATTRIBUTE_UNIX_BLOCKS)) {
+				retloop.alloc_size += BLOCK_SIZE *
+					g_file_info_get_attribute_uint64 (temp_info,
+							G_FILE_ATTRIBUTE_UNIX_BLOCKS);
+			}
+			retloop.size += g_file_info_get_size (temp_info);
+			elements++;
+		}
+
+		/* ignore other types (symlinks, sockets, devices, etc) */
+
+		g_object_unref (temp_info);
+	}
+
+	/* won't be an error if we've finished normally */
+	if (err != NULL) {
+		g_warning ("error in dir %s: %s\n",
+			   parse_name, err->message);
+	}
+
+	data.display_name = display_name;
+	data.parse_name = parse_name;
+	data.size = retloop.size;
+	data.alloc_size = retloop.alloc_size;
+	data.depth = (gint) count - 1;
+	data.elements = elements;
+	data.tempHLsize = tempHLsize;
+	baobab_fill_model (&data);
+	g_object_unref (file_enum);
+
+ exit:
+	g_free (dir_uri);
+	g_free (display_name);
+	g_free (parse_name);
+	if (err)
+		g_error_free (err);
+
+	return retloop;
+}
+
+void
+baobab_scan_execute (GFile *location)
+{
+	BaobabHardLinkArray *hla;
+	GFileInfo *info;
+	GError *err = NULL;
+	GFileType ftype;
+	struct allsizes sizes;
+
+	g_return_if_fail (location != NULL);
+
+	/* NOTE: for the root of the scan we follow symlinks */
+	info = g_file_query_info (location,
+				  dir_attributes,
+				  G_FILE_QUERY_INFO_NONE,
+				  NULL,
+				  &err);
+
+	if (info == NULL) {
+		char *parse_name = g_file_get_parse_name (location);
+		g_warning ("couldn't get info for dir %s: %s\n",
+			   parse_name, err->message);
+		g_free (parse_name);
+		g_error_free (err);
+
+		return;
+	}
+
+	ftype = g_file_info_get_file_type (info);
+
+	if (ftype == G_FILE_TYPE_DIRECTORY) {
+		hla = baobab_hardlinks_array_create ();
+
+		sizes = loopdir (location, info, 0, hla, 0);
+		baobab.model_max_depth = sizes.depth;
+
+		baobab_hardlinks_array_free (hla);
+	}
+
+	g_object_unref (info);
+}
+
+
+ +
+ +
+ + diff --git a/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/6.html b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/6.html new file mode 100644 index 00000000..13e8ec8a --- /dev/null +++ b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/6.html @@ -0,0 +1,917 @@ + + + + + + Cppcheck - HTML report - mate-utils + + + + + +
+ + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
/* Copyright (C) 2008 Igalia
+ * Copyright (C) 2012-2021 MATE Developers
+ *
+ * This file is part of MATE Utils.
+ *
+ * MATE Utils is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * MATE Utils is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MATE Utils.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ *   Fabio Marzocca  <thesaltydog@gmail.com>
+ *   Paolo Borelli <pborelli@katamail.com>
+ *   Miguel Gomez <magomez@igalia.com>
+ *   Eduardo Lima Mitev <elima@igalia.com>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <math.h>
+#include <string.h>
+#include <gtk/gtk.h>
+
+#include "baobab-chart.h"
+#include "baobab-treemap.h"
+
+#define ITEM_TEXT_PADDING  3
+#define ITEM_BORDER_WIDTH  1
+#define ITEM_PADDING       6
+
+#define ITEM_MIN_WIDTH    3
+#define ITEM_MIN_HEIGHT   3
+
+#define ITEM_SHOW_LABEL   TRUE
+
+struct _BaobabTreemapPrivate
+{
+  guint max_visible_depth;
+  gboolean more_visible_childs;
+};
+
+G_DEFINE_TYPE_WITH_PRIVATE (BaobabTreemap, baobab_treemap, BAOBAB_CHART_TYPE);
+
+static void baobab_treemap_draw_rectangle (GtkWidget *chart,
+                                           cairo_t *cr,
+                                           gdouble x, gdouble y, gdouble width, gdouble height,
+                                           BaobabChartColor fill_color,
+                                           const char *text,
+                                           gboolean show_text);
+static void baobab_treemap_draw_item (GtkWidget *chart,
+                                      cairo_t *cr,
+                                      BaobabChartItem *item,
+                                      gboolean highlighted);
+static void baobab_treemap_calculate_item_geometry (GtkWidget *chart,
+                                                    BaobabChartItem *item);
+static gboolean baobab_treemap_is_point_over_item (GtkWidget *chart,
+                                                   BaobabChartItem *item,
+                                                   gdouble x,
+                                                   gdouble y);
+static void baobab_treemap_get_item_rectangle (GtkWidget *chart,
+                                               BaobabChartItem *item);
+guint baobab_treemap_can_zoom_in (GtkWidget *chart);
+guint baobab_treemap_can_zoom_out (GtkWidget *chart);
+
+static void
+baobab_treemap_class_init (BaobabTreemapClass *class)
+{
+  BaobabChartClass *chart_class;
+
+  chart_class = BAOBAB_CHART_CLASS (class);
+
+  /* BaobabChart abstract methods */
+  chart_class->draw_item = baobab_treemap_draw_item;
+  chart_class->calculate_item_geometry = baobab_treemap_calculate_item_geometry;
+  chart_class->is_point_over_item = baobab_treemap_is_point_over_item;
+  chart_class->get_item_rectangle = baobab_treemap_get_item_rectangle;
+  chart_class->can_zoom_in        = baobab_treemap_can_zoom_in;
+  chart_class->can_zoom_out       = baobab_treemap_can_zoom_out;
+}
+
+static void
+baobab_treemap_init (BaobabTreemap *chart)
+{
+  BaobabTreemapPrivate *priv;
+
+  priv = baobab_treemap_get_instance_private (chart);
+
+  chart->priv = priv;
+}
+
+static void
+baobab_treemap_draw_rectangle (GtkWidget *chart,
+                               cairo_t *cr,
+                               gdouble x, gdouble y, gdouble width, gdouble height,
+                               BaobabChartColor fill_color,
+                               const char *text,
+                               gboolean show_text)
+{
+  guint border = ITEM_BORDER_WIDTH;
+  PangoRectangle rect;
+  PangoLayout *layout;
+
+  cairo_stroke (cr);
+
+  cairo_set_line_width (cr, border);
+  cairo_rectangle (cr, x + border, y + border,
+                   width - border*2,
+                   height - border*2);
+  cairo_set_source_rgb (cr, fill_color.red, fill_color.green, fill_color.blue);
+  cairo_fill_preserve (cr);
+  cairo_set_source_rgb (cr, 0, 0, 0);
+  cairo_stroke (cr);
+
+  if ((show_text) && (ITEM_SHOW_LABEL))
+    {
+      layout = gtk_widget_create_pango_layout (chart, NULL);
+      pango_layout_set_markup (layout, text, -1);
+      pango_layout_get_pixel_extents (layout, NULL, &rect);
+
+      if ((rect.width + ITEM_TEXT_PADDING*2 <= width) &&
+          (rect.height + ITEM_TEXT_PADDING*2 <= height))
+        {
+          cairo_move_to (cr, x + width/2 - rect.width/2,
+                         y + height/2 - rect.height/2);
+          pango_cairo_show_layout (cr, layout);
+        }
+
+      g_object_unref (layout);
+    }
+}
+
+static void
+baobab_treemap_draw_item (GtkWidget *chart,
+                          cairo_t *cr,
+                          BaobabChartItem *item,
+                          gboolean highlighted)
+{
+  cairo_rectangle_t * rect;
+  BaobabChartColor fill_color;
+  GtkAllocation allocation;
+  gdouble width, height;
+
+  rect = (cairo_rectangle_t *) item->data;
+
+  gtk_widget_get_allocation (chart, &allocation);
+
+  if (item->depth % 2 != 0)
+    {
+      baobab_chart_get_item_color (&fill_color, rect->x/allocation.width*200,
+                                   item->depth, highlighted);
+      width = rect->width - ITEM_PADDING;
+      height = rect->height;
+    }
+  else
+    {
+      baobab_chart_get_item_color (&fill_color, rect->y/allocation.height*200,
+                                   item->depth, highlighted);
+      width = rect->width;
+      height = rect->height - ITEM_PADDING;
+    }
+
+  baobab_treemap_draw_rectangle (chart,
+                                 cr,
+                                 rect->x,
+                                 rect->y,
+                                 width,
+                                 height,
+                                 fill_color,
+                                 item->name,
+                                 (! item->has_visible_children) );
+}
+
+static void
+baobab_treemap_calculate_item_geometry (GtkWidget *chart,
+                                        BaobabChartItem *item)
+{
+  BaobabTreemapPrivate *priv;
+  cairo_rectangle_t p_area;
+  static cairo_rectangle_t *rect;
+  gdouble width, height;
+  BaobabChartItem *parent = NULL;
+  GtkAllocation allocation;
+
+  priv = BAOBAB_TREEMAP (chart)->priv;
+
+  if (item->depth == 0)
+    {
+      priv->max_visible_depth = 0;
+      priv->more_visible_childs = FALSE;
+    }
+
+  item->visible = FALSE;
+
+  if (item->parent == NULL)
+    {
+      gtk_widget_get_allocation (chart, &allocation);
+      p_area.x = 0 - ITEM_PADDING/2;
+      p_area.y = 0 - ITEM_PADDING/2;
+      p_area.width = allocation.width + ITEM_PADDING * 2;
+      p_area.height = allocation.height + ITEM_PADDING;
+    }
+  else
+    {
+      parent = (BaobabChartItem *) item->parent->data;
+      g_memmove (&p_area, parent->data, sizeof (cairo_rectangle_t));
+    }
+
+  if (item->data == NULL)
+    item->data = g_new (cairo_rectangle_t, 1);
+
+  rect = (cairo_rectangle_t *) item->data;
+
+  if (item->depth % 2 != 0)
+    {
+      width = p_area.width - ITEM_PADDING;
+
+      rect->x = p_area.x + (item->rel_start * width / 100) + ITEM_PADDING;
+      rect->y = p_area.y + ITEM_PADDING;
+      rect->width = width * item->rel_size / 100;
+      rect->height = p_area.height - ITEM_PADDING * 3;
+    }
+  else
+    {
+      height = p_area.height - ITEM_PADDING;
+
+      rect->x = p_area.x + ITEM_PADDING;
+      rect->y = p_area.y + (item->rel_start * height / 100) + ITEM_PADDING;
+      rect->width = p_area.width - ITEM_PADDING * 3;
+      rect->height = height * item->rel_size / 100;
+    }
+
+  if ((rect->width - ITEM_PADDING < ITEM_MIN_WIDTH) ||
+      (rect->height - ITEM_PADDING < ITEM_MIN_HEIGHT))
+    return;
+
+  rect->x = floor (rect->x) + 0.5;
+  rect->y = floor (rect->y) + 0.5;
+  rect->width = floor (rect->width);
+  rect->height = floor (rect->height);
+
+  item->visible = TRUE;
+
+  if (parent != NULL)
+    parent->has_visible_children = TRUE;
+
+  baobab_treemap_get_item_rectangle (chart, item);
+
+  if (item->depth == baobab_chart_get_max_depth (chart) + 1)
+    priv->more_visible_childs = TRUE;
+  else
+    priv->max_visible_depth = MAX (priv->max_visible_depth, item->depth);
+}
+
+static gboolean
+baobab_treemap_is_point_over_item (GtkWidget *chart,
+                                   BaobabChartItem *item,
+                                   gdouble x,
+                                   gdouble y)
+{
+  GdkRectangle *rect;
+
+  rect = &item->rect;
+  return ((x >= rect->x) && (x <= rect->x + rect->width) &&
+          (y >= rect->y) && (y <= rect->y + rect->height));
+}
+
+static void
+baobab_treemap_get_item_rectangle (GtkWidget *chart,
+                                   BaobabChartItem *item)
+{
+  cairo_rectangle_t *_rect;
+
+  _rect = (cairo_rectangle_t *) item->data;
+
+  item->rect.x = (int) _rect->x;
+  item->rect.y = (int) _rect->y;
+  if (item->depth % 2 != 0)
+    {
+      item->rect.width = (int) _rect->width - ITEM_PADDING;
+      item->rect.height = (int) _rect->height;
+    }
+  else
+    {
+      item->rect.width = (int) _rect->width;
+      item->rect.height = (int) _rect->height - ITEM_PADDING;
+    }
+
+}
+
+guint
+baobab_treemap_can_zoom_in (GtkWidget *chart)
+{
+  BaobabTreemapPrivate *priv;
+
+  priv = BAOBAB_TREEMAP (chart)->priv;
+
+  return MAX (0, (gint) (priv->max_visible_depth - 1));
+}
+
+guint
+baobab_treemap_can_zoom_out (GtkWidget *chart)
+{
+  BaobabTreemapPrivate *priv;
+
+  priv = BAOBAB_TREEMAP (chart)->priv;
+
+  return priv->more_visible_childs ? 1 : 0;
+}
+
+/* Public functions start here */
+
+/**
+ * baobab_treemap_new:
+ *
+ * Constructor for the baobab_treemap class
+ *
+ * Returns: a new #BaobabTreemap object
+ *
+ **/
+GtkWidget*
+baobab_treemap_new (void)
+{
+  return g_object_new (BAOBAB_TREEMAP_TYPE, NULL);
+}
+
+ +
+ +
+ + diff --git a/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/7.html b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/7.html new file mode 100644 index 00000000..573d6c76 --- /dev/null +++ b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/7.html @@ -0,0 +1,1323 @@ + + + + + + Cppcheck - HTML report - mate-utils + + + + + +
+ + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
+479
+480
+481
+482
+483
+484
+485
+486
+487
+488
+489
+490
+491
+492
+493
+494
+495
+496
+497
+498
+499
+500
+501
+502
+503
+504
+505
+506
+507
+508
+509
+510
+511
+512
+513
+514
+515
+516
+517
+518
+519
+520
+521
+522
+523
+524
+525
+526
+527
+528
+529
+530
+531
/* Copyright (C) 2005-2006 Fabio Marzocca <thesaltydog@gmail.com>
+ * Copyright (C) 2012-2021 MATE Developers
+ *
+ * This file is part of MATE Utils.
+ *
+ * MATE Utils is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * MATE Utils is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MATE Utils.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib.h>
+#include <glib/gstdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <glib/gi18n.h>
+#include <glib/gprintf.h>
+#include <gtk/gtk.h>
+#include <gio/gio.h>
+#include <glibtop/mountlist.h>
+#include <glibtop/fsusage.h>
+
+#include "baobab.h"
+#include "baobab-treeview.h"
+#include "baobab-utils.h"
+#include "callbacks.h"
+
+void
+baobab_get_filesystem (BaobabFS *fs)
+{
+	size_t i;
+	glibtop_mountlist mountlist;
+	glibtop_mountentry *mountentries;
+
+	memset (fs, 0, sizeof *fs);
+
+	mountentries = glibtop_get_mountlist (&mountlist, FALSE);
+
+	for (i = 0; i < mountlist.number; ++i) {
+		GFile *file;
+		glibtop_fsusage fsusage;
+
+		file = g_file_new_for_path (mountentries[i].mountdir);
+
+		if (!baobab_is_excluded_location (file)) {
+
+			glibtop_get_fsusage (&fsusage, mountentries[i].mountdir);
+
+			fs->total += fsusage.blocks * fsusage.block_size;
+			fs->avail += fsusage.bfree * fsusage.block_size;
+			fs->used += (fsusage.blocks - fsusage.bfree) * fsusage.block_size;
+		}
+
+		g_object_unref (file);
+	}
+
+	g_free (mountentries);
+}
+
+static void
+filechooser_cb (GtkWidget *chooser,
+                gint response,
+                gpointer data)
+{
+	if (response == GTK_RESPONSE_OK) {
+		gchar *filename;
+		GFile	*file;
+
+		filename = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (chooser));
+		gtk_widget_hide (chooser);
+
+		file = g_file_new_for_uri (filename);
+		baobab_scan_location (file);
+		g_free (filename);
+		g_object_unref (file);
+	}
+	else {
+		gtk_widget_hide (chooser);
+	}
+}
+
+/*
+ * GtkFileChooser to select a directory to scan
+ */
+gchar *
+dir_select (gboolean SEARCH, GtkWidget *parent)
+{
+	static GtkWidget *file_chooser = NULL;
+	GtkWidget *toggle;
+
+	if (file_chooser == NULL) {
+		file_chooser = gtk_file_chooser_dialog_new (_("Select Folder"),
+					      GTK_WINDOW (parent),
+					      GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
+					      "gtk-cancel",
+					      GTK_RESPONSE_CANCEL,
+					      "gtk-open",
+					      GTK_RESPONSE_OK, NULL);
+
+		gtk_file_chooser_set_show_hidden (GTK_FILE_CHOOSER (file_chooser), FALSE);
+		gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (file_chooser),
+					     g_get_home_dir ());
+		/* add extra widget */
+		toggle = gtk_check_button_new_with_mnemonic (_("_Show hidden folders"));
+		gtk_widget_show (toggle);
+		gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), FALSE);
+		g_signal_connect ((gpointer) toggle, "toggled",
+				  G_CALLBACK (on_toggled), file_chooser);
+		gtk_file_chooser_set_extra_widget (GTK_FILE_CHOOSER (file_chooser),
+						   toggle);
+
+		g_signal_connect (file_chooser, "response",
+				  G_CALLBACK (filechooser_cb), NULL);
+		g_signal_connect (file_chooser, "destroy",
+				  G_CALLBACK (gtk_widget_destroyed), &file_chooser);
+
+		gtk_window_set_modal (GTK_WINDOW (file_chooser), TRUE);
+		gtk_window_set_position (GTK_WINDOW (file_chooser), GTK_WIN_POS_CENTER_ON_PARENT);
+	}
+
+	gtk_widget_show (GTK_WIDGET (file_chooser));
+
+	return NULL;
+}
+
+void
+on_toggled (GtkToggleButton *togglebutton, gpointer dialog)
+{
+	gtk_file_chooser_set_show_hidden (GTK_FILE_CHOOSER (dialog),
+					  !gtk_file_chooser_get_show_hidden
+					  (GTK_FILE_CHOOSER (dialog)));
+}
+
+gboolean
+show_bars (GtkTreeModel *mdl,
+	   GtkTreePath *path,
+	   GtkTreeIter *iter,
+	   gpointer data)
+{
+	GtkTreeIter parent;
+	gdouble perc;
+	gint readelements, size_col;
+	guint64 refsize, size;
+	char *sizecstr = NULL;
+
+	if (baobab.show_allocated)
+		size_col = (gint) COL_H_ALLOCSIZE;
+	else
+		size_col = (gint) COL_H_SIZE;
+
+	if (gtk_tree_model_iter_parent (mdl, &parent, iter)) {
+		gtk_tree_model_get (mdl, iter, COL_H_ELEMENTS,
+				    &readelements, -1);
+
+		if (readelements == -1) {
+			gtk_tree_store_set (GTK_TREE_STORE (mdl), iter,
+					    COL_DIR_SIZE, "--",
+					    COL_ELEMENTS, "--", -1);
+			return FALSE;
+		}
+
+ 		gtk_tree_model_get (mdl, &parent, COL_H_ELEMENTS,
+ 				    &readelements, -1);
+
+                gtk_tree_model_get (mdl, iter, size_col, &size, -1);
+
+			sizecstr = g_format_size (size);
+
+ 		if (readelements == -1) {
+			gtk_tree_store_set (GTK_TREE_STORE (mdl), iter,
+				            COL_DIR_SIZE, sizecstr, -1);
+
+			g_free (sizecstr);
+			return FALSE;
+		}
+
+		gtk_tree_model_get (mdl, &parent, size_col, &refsize, -1);
+		perc = (refsize != 0) ? ((gdouble) size * 100) / (gdouble) refsize : 0.0;
+
+		gtk_tree_store_set (GTK_TREE_STORE (mdl), iter,
+				    COL_DIR_SIZE, sizecstr,
+				    COL_H_PERC, perc, -1);
+
+		g_free (sizecstr);
+	} else {
+		gtk_tree_model_get (mdl, iter, COL_H_ELEMENTS,
+				    &readelements, -1);
+
+		if (readelements != -1) {
+			gtk_tree_model_get (mdl, iter, size_col, &size,
+					    -1);
+
+				sizecstr = g_format_size (size);
+
+			gtk_tree_store_set (GTK_TREE_STORE (mdl), iter,
+					    COL_H_PERC, 100.0,
+					    COL_DIR_SIZE, sizecstr, -1);
+
+			g_free (sizecstr);
+		}
+		else {
+			gtk_tree_store_set (GTK_TREE_STORE (mdl), iter,
+		  		 	    COL_DIR_SIZE, "--",
+					    COL_ELEMENTS, "--", -1);
+		}
+	}
+
+	return FALSE;
+}
+
+void
+message (const gchar *primary_msg,
+	 const gchar *secondary_msg,
+	 GtkMessageType type,
+	 GtkWidget *parent)
+{
+	GtkWidget *dialog;
+	dialog = gtk_message_dialog_new (GTK_WINDOW (parent),
+					 GTK_DIALOG_DESTROY_WITH_PARENT,
+					 type,
+					 GTK_BUTTONS_OK, "%s", primary_msg);
+	gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+	                                          "%s", secondary_msg);
+	gtk_dialog_run (GTK_DIALOG (dialog));
+	gtk_widget_destroy (dialog);
+}
+
+gint
+messageyesno (const gchar *primary_msg,
+	      const gchar *secondary_msg,
+	      GtkMessageType type,
+	      gchar *ok_button,
+	      GtkWidget *parent)
+{
+	GtkWidget *dialog;
+	GtkWidget *button;
+	gint response;
+
+	dialog = gtk_message_dialog_new (GTK_WINDOW (parent),
+					 GTK_DIALOG_DESTROY_WITH_PARENT,
+					 type,
+					 GTK_BUTTONS_CANCEL,
+					 "%s", primary_msg);
+	gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+	                                          "%s", secondary_msg);
+
+	button = gtk_button_new_with_mnemonic (ok_button);
+	gtk_widget_set_can_default (button, TRUE);
+	gtk_widget_show (button);
+
+	gtk_dialog_add_action_widget (GTK_DIALOG (dialog), button, GTK_RESPONSE_OK);
+	gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
+	response = gtk_dialog_run (GTK_DIALOG (dialog));
+	gtk_widget_destroy (dialog);
+
+	return response;
+}
+
+gboolean
+baobab_check_dir (GFile	*file)
+{
+	GFileInfo *info;
+	GError *error = NULL;
+	gboolean ret = TRUE;
+
+	if (baobab_is_excluded_location (file)) {
+		message("", _("Cannot check an excluded folder!"), GTK_MESSAGE_INFO, baobab.window);
+		return FALSE;
+		}
+
+	info = g_file_query_info (file,
+				  G_FILE_ATTRIBUTE_STANDARD_TYPE,
+				  G_FILE_QUERY_INFO_NONE,
+				  NULL,
+				  &error);
+
+	if (!info) {
+		message("", error->message, GTK_MESSAGE_INFO, baobab.window);
+		g_error_free (error);
+
+		return FALSE;
+	}
+
+	if ((g_file_info_get_file_type (info) != G_FILE_TYPE_DIRECTORY) ||
+		is_virtual_filesystem(file)) {
+
+		char *error_msg = NULL;
+		gchar *name = NULL;
+
+	    	name = g_file_get_parse_name (file);
+		error_msg = g_strdup_printf (_("\"%s\" is not a valid folder"),
+					     name);
+
+		message (error_msg, _("Could not analyze disk usage."),
+		         GTK_MESSAGE_ERROR, baobab.window);
+
+		g_free (error_msg);
+		g_free (name);
+		ret = FALSE;
+	}
+
+	g_object_unref(info);
+
+	return ret;
+}
+
+static void
+add_popupmenu_item (GtkMenu *pmenu, const gchar *label, const gchar *icon_name, GCallback item_cb)
+{
+	GtkWidget *item;
+	GtkWidget *image;
+
+	item = gtk_image_menu_item_new_with_mnemonic (label);
+	image = gtk_image_new_from_icon_name (icon_name, GTK_ICON_SIZE_MENU);
+	gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
+
+	g_signal_connect (item, "activate", item_cb, NULL);
+
+	gtk_container_add (GTK_CONTAINER (pmenu), item);
+}
+
+void
+popupmenu_list (GtkTreePath *path, GdkEventButton *event, gboolean can_trash)
+{
+	GtkWidget *pmenu;
+
+	pmenu = gtk_menu_new ();
+
+	add_popupmenu_item (GTK_MENU (pmenu),
+			    _("_Open Folder"),
+			    "document-open",
+			    G_CALLBACK (open_file_cb));
+
+	if (baobab.is_local && can_trash) {
+		add_popupmenu_item (GTK_MENU (pmenu),
+				    _("Mo_ve to Trash"),
+				    "edit-delete",
+				    G_CALLBACK (trash_dir_cb));
+	}
+
+	gtk_widget_show_all (pmenu);
+	gtk_menu_popup_at_pointer (GTK_MENU (pmenu),
+	                           (const GdkEvent*) event);
+}
+
+void
+open_file_with_application (GFile *file)
+{
+	GAppInfo *application;
+	gchar *primary;
+	GFileInfo *info;
+	const char *content;
+
+	info = g_file_query_info (file,
+				  G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
+				  G_FILE_QUERY_INFO_NONE,
+				  NULL,
+				  NULL);
+	if (!info) return;
+
+	content = g_file_info_get_content_type (info);
+	application = g_app_info_get_default_for_type (content, TRUE);
+
+	if (!application) {
+			primary = g_strdup_printf (_("Could not open folder \"%s\""),
+			                           g_file_get_basename (file));
+			message (primary,
+			         _("There is no installed viewer capable "
+				   "of displaying the folder."),
+				 GTK_MESSAGE_ERROR,
+				 baobab.window);
+			g_free (primary);
+	}
+	else {
+		GList *uris = NULL;
+		gchar *uri;
+
+		uri = g_file_get_uri (file);
+		uris = g_list_append (uris, uri);
+		g_app_info_launch_uris (application, uris, NULL, NULL);
+
+		g_list_free (uris);
+		g_free (uri);
+	}
+
+	if (application)
+		g_object_unref (application);
+
+	g_object_unref (info);
+}
+
+gboolean
+can_trash_file (GFile *file)
+{
+	GFileInfo *info;
+	gboolean can_trash = FALSE;
+
+	info = g_file_query_info (file,
+				  G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH,
+				  G_FILE_QUERY_INFO_NONE,
+				  NULL,
+				  NULL);
+
+	if (info) {
+		if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH)) {
+			can_trash = g_file_info_get_attribute_boolean (info,
+								       G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH);
+		}
+
+		g_object_unref (info);
+	}
+
+	return can_trash;
+}
+
+gboolean
+trash_file (GFile *file)
+{
+	GError *error = NULL;
+
+	if (!g_file_trash (file, NULL, &error)) {
+		GFileInfo *info;
+		char *str = NULL;
+		char *mess;
+
+		info = g_file_query_info (file,
+					  G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME,
+					  G_FILE_QUERY_INFO_NONE,
+					  NULL,
+					  NULL);
+
+		if (info) {
+			const char *displayname = g_file_info_get_display_name (info);
+			if (displayname)
+				str = g_strdup_printf (_("Could not move \"%s\" to the Trash"),
+						      displayname);
+
+			g_object_unref (info);
+		}
+
+		/* fallback */
+		if (str == NULL)
+			str = g_strdup (_("Could not move file to the Trash"));
+
+		mess = g_strdup_printf (_("Details: %s"), error->message);
+		message (str, mess, GTK_MESSAGE_ERROR, baobab.window);
+		g_free (str);
+		g_free (mess);
+		g_error_free (error);
+
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+gboolean
+baobab_help_display (GtkWindow   *parent,
+		     const gchar *file_name,
+		     const gchar *link_id)
+{
+	GError *error = NULL;
+	char *uri;
+	gboolean ret;
+
+	uri = (link_id) ?
+		g_strdup_printf ("help:%s/%s", file_name, link_id) :
+		g_strdup_printf ("help:%s", file_name);
+
+	ret = gtk_show_uri_on_window (parent,
+	                              uri,
+	                              gtk_get_current_event_time (),
+	                              &error);
+	g_free (uri);
+
+	if (error != NULL) {
+		GtkWidget *dialog;
+
+		dialog = gtk_message_dialog_new (parent,
+						 GTK_DIALOG_DESTROY_WITH_PARENT,
+						 GTK_MESSAGE_ERROR,
+						 GTK_BUTTONS_CLOSE,
+						 _("There was an error displaying help."));
+
+		gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+							  "%s", error->message);
+
+		g_signal_connect (dialog, "response",
+		                  G_CALLBACK (gtk_widget_destroy),
+		                  NULL);
+
+		gtk_widget_show (dialog);
+
+		g_error_free (error);
+	}
+
+	return ret;
+}
+
+gboolean
+is_virtual_filesystem (GFile *file)
+{
+	gboolean ret = FALSE;
+	char *path;
+
+	path = g_file_get_path (file);
+
+	/* FIXME: we need a better way to check virtual FS */
+	if (path != NULL) {
+		if ((strcmp (path, "/proc") == 0) ||
+		    (strcmp (path, "/sys") == 0))
+	 		ret = TRUE;
+	}
+
+	g_free (path);
+
+	return ret;
+}
+
+ +
+ +
+ + diff --git a/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/8.html b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/8.html new file mode 100644 index 00000000..8f43835c --- /dev/null +++ b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/8.html @@ -0,0 +1,2903 @@ + + + + + + Cppcheck - HTML report - mate-utils + + + + + +
+ + + +
+
   1
+   2
+   3
+   4
+   5
+   6
+   7
+   8
+   9
+  10
+  11
+  12
+  13
+  14
+  15
+  16
+  17
+  18
+  19
+  20
+  21
+  22
+  23
+  24
+  25
+  26
+  27
+  28
+  29
+  30
+  31
+  32
+  33
+  34
+  35
+  36
+  37
+  38
+  39
+  40
+  41
+  42
+  43
+  44
+  45
+  46
+  47
+  48
+  49
+  50
+  51
+  52
+  53
+  54
+  55
+  56
+  57
+  58
+  59
+  60
+  61
+  62
+  63
+  64
+  65
+  66
+  67
+  68
+  69
+  70
+  71
+  72
+  73
+  74
+  75
+  76
+  77
+  78
+  79
+  80
+  81
+  82
+  83
+  84
+  85
+  86
+  87
+  88
+  89
+  90
+  91
+  92
+  93
+  94
+  95
+  96
+  97
+  98
+  99
+ 100
+ 101
+ 102
+ 103
+ 104
+ 105
+ 106
+ 107
+ 108
+ 109
+ 110
+ 111
+ 112
+ 113
+ 114
+ 115
+ 116
+ 117
+ 118
+ 119
+ 120
+ 121
+ 122
+ 123
+ 124
+ 125
+ 126
+ 127
+ 128
+ 129
+ 130
+ 131
+ 132
+ 133
+ 134
+ 135
+ 136
+ 137
+ 138
+ 139
+ 140
+ 141
+ 142
+ 143
+ 144
+ 145
+ 146
+ 147
+ 148
+ 149
+ 150
+ 151
+ 152
+ 153
+ 154
+ 155
+ 156
+ 157
+ 158
+ 159
+ 160
+ 161
+ 162
+ 163
+ 164
+ 165
+ 166
+ 167
+ 168
+ 169
+ 170
+ 171
+ 172
+ 173
+ 174
+ 175
+ 176
+ 177
+ 178
+ 179
+ 180
+ 181
+ 182
+ 183
+ 184
+ 185
+ 186
+ 187
+ 188
+ 189
+ 190
+ 191
+ 192
+ 193
+ 194
+ 195
+ 196
+ 197
+ 198
+ 199
+ 200
+ 201
+ 202
+ 203
+ 204
+ 205
+ 206
+ 207
+ 208
+ 209
+ 210
+ 211
+ 212
+ 213
+ 214
+ 215
+ 216
+ 217
+ 218
+ 219
+ 220
+ 221
+ 222
+ 223
+ 224
+ 225
+ 226
+ 227
+ 228
+ 229
+ 230
+ 231
+ 232
+ 233
+ 234
+ 235
+ 236
+ 237
+ 238
+ 239
+ 240
+ 241
+ 242
+ 243
+ 244
+ 245
+ 246
+ 247
+ 248
+ 249
+ 250
+ 251
+ 252
+ 253
+ 254
+ 255
+ 256
+ 257
+ 258
+ 259
+ 260
+ 261
+ 262
+ 263
+ 264
+ 265
+ 266
+ 267
+ 268
+ 269
+ 270
+ 271
+ 272
+ 273
+ 274
+ 275
+ 276
+ 277
+ 278
+ 279
+ 280
+ 281
+ 282
+ 283
+ 284
+ 285
+ 286
+ 287
+ 288
+ 289
+ 290
+ 291
+ 292
+ 293
+ 294
+ 295
+ 296
+ 297
+ 298
+ 299
+ 300
+ 301
+ 302
+ 303
+ 304
+ 305
+ 306
+ 307
+ 308
+ 309
+ 310
+ 311
+ 312
+ 313
+ 314
+ 315
+ 316
+ 317
+ 318
+ 319
+ 320
+ 321
+ 322
+ 323
+ 324
+ 325
+ 326
+ 327
+ 328
+ 329
+ 330
+ 331
+ 332
+ 333
+ 334
+ 335
+ 336
+ 337
+ 338
+ 339
+ 340
+ 341
+ 342
+ 343
+ 344
+ 345
+ 346
+ 347
+ 348
+ 349
+ 350
+ 351
+ 352
+ 353
+ 354
+ 355
+ 356
+ 357
+ 358
+ 359
+ 360
+ 361
+ 362
+ 363
+ 364
+ 365
+ 366
+ 367
+ 368
+ 369
+ 370
+ 371
+ 372
+ 373
+ 374
+ 375
+ 376
+ 377
+ 378
+ 379
+ 380
+ 381
+ 382
+ 383
+ 384
+ 385
+ 386
+ 387
+ 388
+ 389
+ 390
+ 391
+ 392
+ 393
+ 394
+ 395
+ 396
+ 397
+ 398
+ 399
+ 400
+ 401
+ 402
+ 403
+ 404
+ 405
+ 406
+ 407
+ 408
+ 409
+ 410
+ 411
+ 412
+ 413
+ 414
+ 415
+ 416
+ 417
+ 418
+ 419
+ 420
+ 421
+ 422
+ 423
+ 424
+ 425
+ 426
+ 427
+ 428
+ 429
+ 430
+ 431
+ 432
+ 433
+ 434
+ 435
+ 436
+ 437
+ 438
+ 439
+ 440
+ 441
+ 442
+ 443
+ 444
+ 445
+ 446
+ 447
+ 448
+ 449
+ 450
+ 451
+ 452
+ 453
+ 454
+ 455
+ 456
+ 457
+ 458
+ 459
+ 460
+ 461
+ 462
+ 463
+ 464
+ 465
+ 466
+ 467
+ 468
+ 469
+ 470
+ 471
+ 472
+ 473
+ 474
+ 475
+ 476
+ 477
+ 478
+ 479
+ 480
+ 481
+ 482
+ 483
+ 484
+ 485
+ 486
+ 487
+ 488
+ 489
+ 490
+ 491
+ 492
+ 493
+ 494
+ 495
+ 496
+ 497
+ 498
+ 499
+ 500
+ 501
+ 502
+ 503
+ 504
+ 505
+ 506
+ 507
+ 508
+ 509
+ 510
+ 511
+ 512
+ 513
+ 514
+ 515
+ 516
+ 517
+ 518
+ 519
+ 520
+ 521
+ 522
+ 523
+ 524
+ 525
+ 526
+ 527
+ 528
+ 529
+ 530
+ 531
+ 532
+ 533
+ 534
+ 535
+ 536
+ 537
+ 538
+ 539
+ 540
+ 541
+ 542
+ 543
+ 544
+ 545
+ 546
+ 547
+ 548
+ 549
+ 550
+ 551
+ 552
+ 553
+ 554
+ 555
+ 556
+ 557
+ 558
+ 559
+ 560
+ 561
+ 562
+ 563
+ 564
+ 565
+ 566
+ 567
+ 568
+ 569
+ 570
+ 571
+ 572
+ 573
+ 574
+ 575
+ 576
+ 577
+ 578
+ 579
+ 580
+ 581
+ 582
+ 583
+ 584
+ 585
+ 586
+ 587
+ 588
+ 589
+ 590
+ 591
+ 592
+ 593
+ 594
+ 595
+ 596
+ 597
+ 598
+ 599
+ 600
+ 601
+ 602
+ 603
+ 604
+ 605
+ 606
+ 607
+ 608
+ 609
+ 610
+ 611
+ 612
+ 613
+ 614
+ 615
+ 616
+ 617
+ 618
+ 619
+ 620
+ 621
+ 622
+ 623
+ 624
+ 625
+ 626
+ 627
+ 628
+ 629
+ 630
+ 631
+ 632
+ 633
+ 634
+ 635
+ 636
+ 637
+ 638
+ 639
+ 640
+ 641
+ 642
+ 643
+ 644
+ 645
+ 646
+ 647
+ 648
+ 649
+ 650
+ 651
+ 652
+ 653
+ 654
+ 655
+ 656
+ 657
+ 658
+ 659
+ 660
+ 661
+ 662
+ 663
+ 664
+ 665
+ 666
+ 667
+ 668
+ 669
+ 670
+ 671
+ 672
+ 673
+ 674
+ 675
+ 676
+ 677
+ 678
+ 679
+ 680
+ 681
+ 682
+ 683
+ 684
+ 685
+ 686
+ 687
+ 688
+ 689
+ 690
+ 691
+ 692
+ 693
+ 694
+ 695
+ 696
+ 697
+ 698
+ 699
+ 700
+ 701
+ 702
+ 703
+ 704
+ 705
+ 706
+ 707
+ 708
+ 709
+ 710
+ 711
+ 712
+ 713
+ 714
+ 715
+ 716
+ 717
+ 718
+ 719
+ 720
+ 721
+ 722
+ 723
+ 724
+ 725
+ 726
+ 727
+ 728
+ 729
+ 730
+ 731
+ 732
+ 733
+ 734
+ 735
+ 736
+ 737
+ 738
+ 739
+ 740
+ 741
+ 742
+ 743
+ 744
+ 745
+ 746
+ 747
+ 748
+ 749
+ 750
+ 751
+ 752
+ 753
+ 754
+ 755
+ 756
+ 757
+ 758
+ 759
+ 760
+ 761
+ 762
+ 763
+ 764
+ 765
+ 766
+ 767
+ 768
+ 769
+ 770
+ 771
+ 772
+ 773
+ 774
+ 775
+ 776
+ 777
+ 778
+ 779
+ 780
+ 781
+ 782
+ 783
+ 784
+ 785
+ 786
+ 787
+ 788
+ 789
+ 790
+ 791
+ 792
+ 793
+ 794
+ 795
+ 796
+ 797
+ 798
+ 799
+ 800
+ 801
+ 802
+ 803
+ 804
+ 805
+ 806
+ 807
+ 808
+ 809
+ 810
+ 811
+ 812
+ 813
+ 814
+ 815
+ 816
+ 817
+ 818
+ 819
+ 820
+ 821
+ 822
+ 823
+ 824
+ 825
+ 826
+ 827
+ 828
+ 829
+ 830
+ 831
+ 832
+ 833
+ 834
+ 835
+ 836
+ 837
+ 838
+ 839
+ 840
+ 841
+ 842
+ 843
+ 844
+ 845
+ 846
+ 847
+ 848
+ 849
+ 850
+ 851
+ 852
+ 853
+ 854
+ 855
+ 856
+ 857
+ 858
+ 859
+ 860
+ 861
+ 862
+ 863
+ 864
+ 865
+ 866
+ 867
+ 868
+ 869
+ 870
+ 871
+ 872
+ 873
+ 874
+ 875
+ 876
+ 877
+ 878
+ 879
+ 880
+ 881
+ 882
+ 883
+ 884
+ 885
+ 886
+ 887
+ 888
+ 889
+ 890
+ 891
+ 892
+ 893
+ 894
+ 895
+ 896
+ 897
+ 898
+ 899
+ 900
+ 901
+ 902
+ 903
+ 904
+ 905
+ 906
+ 907
+ 908
+ 909
+ 910
+ 911
+ 912
+ 913
+ 914
+ 915
+ 916
+ 917
+ 918
+ 919
+ 920
+ 921
+ 922
+ 923
+ 924
+ 925
+ 926
+ 927
+ 928
+ 929
+ 930
+ 931
+ 932
+ 933
+ 934
+ 935
+ 936
+ 937
+ 938
+ 939
+ 940
+ 941
+ 942
+ 943
+ 944
+ 945
+ 946
+ 947
+ 948
+ 949
+ 950
+ 951
+ 952
+ 953
+ 954
+ 955
+ 956
+ 957
+ 958
+ 959
+ 960
+ 961
+ 962
+ 963
+ 964
+ 965
+ 966
+ 967
+ 968
+ 969
+ 970
+ 971
+ 972
+ 973
+ 974
+ 975
+ 976
+ 977
+ 978
+ 979
+ 980
+ 981
+ 982
+ 983
+ 984
+ 985
+ 986
+ 987
+ 988
+ 989
+ 990
+ 991
+ 992
+ 993
+ 994
+ 995
+ 996
+ 997
+ 998
+ 999
+1000
+1001
+1002
+1003
+1004
+1005
+1006
+1007
+1008
+1009
+1010
+1011
+1012
+1013
+1014
+1015
+1016
+1017
+1018
+1019
+1020
+1021
+1022
+1023
+1024
+1025
+1026
+1027
+1028
+1029
+1030
+1031
+1032
+1033
+1034
+1035
+1036
+1037
+1038
+1039
+1040
+1041
+1042
+1043
+1044
+1045
+1046
+1047
+1048
+1049
+1050
+1051
+1052
+1053
+1054
+1055
+1056
+1057
+1058
+1059
+1060
+1061
+1062
+1063
+1064
+1065
+1066
+1067
+1068
+1069
+1070
+1071
+1072
+1073
+1074
+1075
+1076
+1077
+1078
+1079
+1080
+1081
+1082
+1083
+1084
+1085
+1086
+1087
+1088
+1089
+1090
+1091
+1092
+1093
+1094
+1095
+1096
+1097
+1098
+1099
+1100
+1101
+1102
+1103
+1104
+1105
+1106
+1107
+1108
+1109
+1110
+1111
+1112
+1113
+1114
+1115
+1116
+1117
+1118
+1119
+1120
+1121
+1122
+1123
+1124
+1125
+1126
+1127
+1128
+1129
+1130
+1131
+1132
+1133
+1134
+1135
+1136
+1137
+1138
+1139
+1140
+1141
+1142
+1143
+1144
+1145
+1146
+1147
+1148
+1149
+1150
+1151
+1152
+1153
+1154
+1155
+1156
+1157
+1158
+1159
+1160
+1161
+1162
+1163
+1164
+1165
+1166
+1167
+1168
+1169
+1170
+1171
+1172
+1173
+1174
+1175
+1176
+1177
+1178
+1179
+1180
+1181
+1182
+1183
+1184
+1185
+1186
+1187
+1188
+1189
+1190
+1191
+1192
+1193
+1194
+1195
+1196
+1197
+1198
+1199
+1200
+1201
+1202
+1203
+1204
+1205
+1206
+1207
+1208
+1209
+1210
+1211
+1212
+1213
+1214
+1215
+1216
+1217
+1218
+1219
+1220
+1221
+1222
+1223
+1224
+1225
+1226
+1227
+1228
+1229
+1230
+1231
+1232
+1233
+1234
+1235
+1236
+1237
+1238
+1239
+1240
+1241
+1242
+1243
+1244
+1245
+1246
+1247
+1248
+1249
+1250
+1251
+1252
+1253
+1254
+1255
+1256
+1257
+1258
+1259
+1260
+1261
+1262
+1263
+1264
+1265
+1266
+1267
+1268
+1269
+1270
+1271
+1272
+1273
+1274
+1275
+1276
+1277
+1278
+1279
+1280
+1281
+1282
+1283
+1284
+1285
+1286
+1287
+1288
+1289
+1290
+1291
+1292
+1293
+1294
+1295
+1296
+1297
+1298
+1299
+1300
+1301
+1302
+1303
+1304
+1305
+1306
+1307
+1308
+1309
+1310
+1311
+1312
+1313
+1314
+1315
+1316
+1317
+1318
+1319
+1320
+1321
+1322
+1323
+1324
+1325
+1326
+1327
/* Copyright (C) 2005-2006 Fabio Marzocca <thesaltydog@gmail.com>
+ * Copyright (C) 2012-2021 MATE Developers
+ *
+ * This file is part of MATE Utils.
+ *
+ * MATE Utils is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * MATE Utils is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MATE Utils.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <gtk/gtk.h>
+#include <glib/gi18n.h>
+#include <gio/gio.h>
+#include <glibtop.h>
+
+#include "baobab.h"
+#include "baobab-scan.h"
+#include "baobab-treeview.h"
+#include "baobab-utils.h"
+#include "callbacks.h"
+#include "baobab-prefs.h"
+
+#include "baobab-treemap.h"
+#include "baobab-ringschart.h"
+
+#define BAOBAB_UI_RESOURCE "/org/mate/disk-usage-analyzer/baobab-main-window.ui"
+#define GET_WIDGET(x) (GTK_WIDGET (gtk_builder_get_object (baobab.main_ui, (x))))
+#define GET_ACTION(x) (GTK_ACTION (gtk_builder_get_object (baobab.main_ui, (x))))
+#define GET_TOGGLE_ACTION(x) (GTK_TOGGLE_ACTION (gtk_builder_get_object (baobab.main_ui, (x))))
+
+static void push_iter_in_stack (GtkTreeIter *);
+static GtkTreeIter pop_iter_from_stack (void);
+
+BaobabApplication baobab;
+
+static gint currentdepth = 0;
+static GtkTreeIter currentiter;
+static GtkTreeIter firstiter;
+static GQueue *iterstack = NULL;
+
+enum {
+	DND_TARGET_URI_LIST
+};
+
+static GtkTargetEntry dnd_target_list[] = {
+	{ "text/uri-list", 0, DND_TARGET_URI_LIST },
+};
+
+static gboolean
+scan_is_local (GFile	*file)
+{
+	gchar *uri_scheme;
+	gboolean ret = FALSE;
+
+	uri_scheme = g_file_get_uri_scheme (file);
+	if (g_ascii_strcasecmp(uri_scheme,"file") == 0)
+		ret = TRUE;
+
+	g_free (uri_scheme);
+
+	return ret;
+}
+
+void
+baobab_set_busy (gboolean busy)
+{
+	static GdkCursor *busy_cursor = NULL;
+	GdkCursor *cursor = NULL;
+	GdkWindow *window;
+	GdkDisplay *display;
+
+	window = gtk_widget_get_window (baobab.window);
+
+	if (busy == TRUE) {
+		if (!busy_cursor && window) {
+			display = gtk_widget_get_display (baobab.window);
+			busy_cursor = gdk_cursor_new_for_display (display, GDK_WATCH);
+		}
+		cursor = busy_cursor;
+
+		gtk_widget_show (baobab.spinner);
+		gtk_spinner_start (GTK_SPINNER (baobab.spinner));
+
+		baobab_chart_freeze_updates (baobab.rings_chart);
+		baobab_chart_freeze_updates (baobab.treemap_chart);
+
+		gtk_widget_set_sensitive (baobab.chart_type_combo, FALSE);
+	}
+	else {
+		gtk_widget_hide (baobab.spinner);
+		gtk_spinner_stop (GTK_SPINNER (baobab.spinner));
+
+		baobab_chart_thaw_updates (baobab.rings_chart);
+		baobab_chart_thaw_updates (baobab.treemap_chart);
+
+		gtk_widget_set_sensitive (baobab.chart_type_combo, TRUE);
+	}
+
+	/* change the cursor */
+	if (window) {
+		gdk_window_set_cursor (window, cursor);
+	}
+}
+
+static void
+set_drop_target (GtkWidget *target, gboolean active) {
+	if (active) {
+		gtk_drag_dest_set (GTK_WIDGET (target),
+				   GTK_DEST_DEFAULT_DROP | GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_HIGHLIGHT,
+				   dnd_target_list,
+				   G_N_ELEMENTS (dnd_target_list),
+				   GDK_ACTION_COPY);
+	} else {
+		gtk_drag_dest_unset (target);
+	}
+}
+
+/* menu & toolbar sensitivity */
+static void
+check_menu_sens (gboolean scanning)
+{
+	gboolean has_current_location;
+
+	if (scanning) {
+		while (gtk_events_pending ())
+			gtk_main_iteration ();
+
+		baobab_set_statusbar (_("Scanning..."));
+		gtk_action_set_sensitive (GET_ACTION ("expand_all"), TRUE);
+		gtk_action_set_sensitive (GET_ACTION ("collapse_all"), TRUE);
+	}
+
+	has_current_location = baobab.current_location != NULL;
+
+	gtk_action_set_sensitive (GET_ACTION ("menuscanhome"), !scanning);
+	gtk_action_set_sensitive (GET_ACTION ("menuallfs"), !scanning);
+	gtk_action_set_sensitive (GET_ACTION ("menuscandir"), !scanning);
+	gtk_action_set_sensitive (GET_ACTION ("menustop"), scanning);
+	gtk_action_set_sensitive (GET_ACTION ("menurescan"), !scanning && has_current_location);
+	gtk_action_set_sensitive (GET_ACTION ("preferenze1"), !scanning);
+	gtk_action_set_sensitive (GET_ACTION ("menu_scan_rem"), !scanning);
+	gtk_action_set_sensitive (GET_ACTION ("ck_allocated"), !scanning && baobab.is_local);
+
+	gtk_widget_set_sensitive (GET_WIDGET ("tbscanhome"), !scanning);
+	gtk_widget_set_sensitive (GET_WIDGET ("tbscanall"), !scanning);
+	gtk_widget_set_sensitive (GET_WIDGET ("tbscandir"), !scanning);
+	gtk_widget_set_sensitive (GET_WIDGET ("tbstop"), scanning);
+	gtk_widget_set_sensitive (GET_WIDGET ("tbrescan"), !scanning && has_current_location);
+	gtk_widget_set_sensitive (GET_WIDGET ("tb_scan_remote"), !scanning);
+}
+
+static void
+check_drop_targets (gboolean scanning)
+{
+	set_drop_target (baobab.rings_chart, !scanning);
+	set_drop_target (baobab.treemap_chart, !scanning);
+}
+
+static void
+update_scan_label (void)
+{
+	gchar *markup;
+	gchar *total;
+	gchar *used;
+	gchar *available;
+
+		total = g_format_size (baobab.fs.total);
+		used = g_format_size (baobab.fs.used);
+		available = g_format_size (baobab.fs.avail);
+
+	/* Translators: these are labels for disk space */
+	markup = g_markup_printf_escaped  ("<small>%s <b>%s</b> (%s %s %s %s)</small>",
+					   _("Total filesystem capacity:"), total,
+					   _("used:"), used,
+					   _("available:"), available);
+
+	g_free (total);
+	g_free (used);
+	g_free (available);
+
+	gtk_label_set_markup (GTK_LABEL (GET_WIDGET ("label1")), markup);
+	g_free (markup);
+}
+
+void
+baobab_update_filesystem (void)
+{
+	baobab_get_filesystem (&baobab.fs);
+	update_scan_label ();
+}
+
+void
+baobab_scan_location (GFile *file)
+{
+	GtkToggleAction *ck_allocated;
+
+	if (!baobab_check_dir (file))
+		return;
+
+	if (iterstack !=NULL)
+		return;
+
+	if (baobab.current_location)
+		g_object_unref (baobab.current_location);
+	baobab.current_location = g_object_ref (file);
+
+	baobab.STOP_SCANNING = FALSE;
+	baobab_set_busy (TRUE);
+	check_menu_sens (TRUE);
+	check_drop_targets (TRUE);
+	gtk_tree_store_clear (baobab.model);
+	currentdepth = -1;	/* flag */
+	iterstack = g_queue_new ();
+
+	/* check if the file system is local or remote */
+	baobab.is_local = scan_is_local (file);
+	ck_allocated = GET_TOGGLE_ACTION ("ck_allocated");
+	if (!baobab.is_local) {
+		gtk_toggle_action_set_active (ck_allocated, FALSE);
+		gtk_action_set_sensitive (GTK_ACTION (ck_allocated), FALSE);
+		baobab.show_allocated = FALSE;
+	}
+	else {
+		gtk_action_set_sensitive (GTK_ACTION (ck_allocated), TRUE);
+	}
+
+	baobab_scan_execute (file);
+
+	/* set statusbar, percentage and allocated/normal size */
+	baobab_set_statusbar (_("Calculating percentage bars..."));
+	gtk_tree_model_foreach (GTK_TREE_MODEL (baobab.model),
+				show_bars,
+				NULL);
+
+	baobab_chart_set_max_depth (baobab.rings_chart, baobab.model_max_depth);
+	baobab_chart_set_max_depth (baobab.treemap_chart, baobab.model_max_depth);
+
+	baobab_set_busy (FALSE);
+	check_menu_sens (FALSE);
+	check_drop_targets (FALSE);
+	baobab_set_statusbar (_("Ready"));
+
+	gtk_tree_view_columns_autosize (GTK_TREE_VIEW (baobab.tree_view));
+	baobab.STOP_SCANNING = TRUE;
+	g_queue_free (iterstack);
+	iterstack = NULL;
+	baobab.CONTENTS_CHANGED_DELAYED = FALSE;
+}
+
+void
+baobab_scan_home (void)
+{
+	GFile *file;
+
+	file = g_file_new_for_path (g_get_home_dir ());
+	baobab_scan_location (file);
+	g_object_unref (file);
+}
+
+void
+baobab_scan_root (void)
+{
+	GFile *file;
+
+	file = g_file_new_for_uri ("file:///");
+	baobab_scan_location (file);
+	g_object_unref (file);
+}
+
+void
+baobab_rescan_current_dir (void)
+{
+	g_return_if_fail (baobab.current_location != NULL);
+
+	baobab_update_filesystem ();
+
+	g_object_ref (baobab.current_location);
+	baobab_scan_location (baobab.current_location);
+	g_object_unref (baobab.current_location);
+}
+
+void
+baobab_stop_scan (void)
+{
+	baobab.STOP_SCANNING = TRUE;
+
+	baobab_set_statusbar (_("Calculating percentage bars..."));
+	gtk_tree_model_foreach (GTK_TREE_MODEL (baobab.model),
+				show_bars, NULL);
+	gtk_tree_view_columns_autosize (GTK_TREE_VIEW (baobab.tree_view));
+}
+
+/*
+ * pre-fills model during scanning
+ */
+static void
+prefill_model (struct chan_data *data)
+{
+	GtkTreeIter iter, iterparent;
+	char *name;
+	char *str;
+
+	if (currentdepth == -1) {
+		gtk_tree_store_append (baobab.model, &iter, NULL);
+		firstiter = iter;
+	}
+	else if (data->depth == 1) {
+		GtkTreePath *path;
+
+		gtk_tree_store_append (baobab.model, &iter, &firstiter);
+		path = gtk_tree_model_get_path (GTK_TREE_MODEL (baobab.model),
+						&firstiter);
+		gtk_tree_view_expand_row (GTK_TREE_VIEW (baobab.tree_view),
+					  path, FALSE);
+		gtk_tree_path_free (path);
+	}
+	else if (data->depth > currentdepth) {
+		gtk_tree_store_append (baobab.model, &iter, &currentiter);
+	}
+	else if (data->depth == currentdepth) {<--- Assuming that condition 'data->depth==currentdepth' is not redundant
+		gtk_tree_model_iter_parent ((GtkTreeModel *) baobab.model,
+					    &iterparent, &currentiter);
+		gtk_tree_store_append (baobab.model, &iter, &iterparent);
+	}
+	else if (data->depth < currentdepth) {<--- Condition 'data->depth
+		GtkTreeIter tempiter;
+		gint i;
+		iter = currentiter;
+		for (i = 0; i <= (currentdepth - data->depth); i++) {
+			gtk_tree_model_iter_parent ((GtkTreeModel *)
+						    baobab.model,
+						    &tempiter, &iter);
+			iter = tempiter;
+		}
+		gtk_tree_store_append (baobab.model, &iter, &tempiter);
+	}
+
+	currentdepth = data->depth;
+	push_iter_in_stack (&iter);
+	currentiter = iter;
+
+	/* in case filenames contains gmarkup */
+	name = g_markup_escape_text (data->display_name, -1);
+
+	str = g_strdup_printf ("<small><i>%s</i></small>", _("Scanning..."));
+
+	gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (baobab.tree_view), TRUE);
+	gtk_tree_store_set (baobab.model, &iter,
+			    COL_DIR_NAME, name,
+			    COL_H_PARSENAME, "",
+			    COL_H_ELEMENTS, -1,
+			    COL_H_PERC, -1.0,
+			    COL_DIR_SIZE, str,
+			    COL_ELEMENTS, str, -1);
+
+	g_free (name);
+	g_free (str);
+
+	while (gtk_events_pending ()) {
+		gtk_main_iteration ();
+	}
+}
+
+static void
+first_row (void)
+{
+	char *size;
+	gdouble perc;
+	char *label;
+
+	GtkTreeIter root_iter;
+
+	gchar *capacity_label, *capacity_size;
+
+	gtk_tree_store_append (baobab.model, &root_iter, NULL);
+
+	capacity_size = g_format_size (baobab.fs.total);
+
+	capacity_label = g_strdup (_("Total filesystem capacity"));
+	gtk_tree_store_set (baobab.model, &root_iter,
+			    COL_DIR_NAME, capacity_label,
+			    COL_H_PARSENAME, "",
+			    COL_H_PERC, 100.0,
+			    COL_DIR_SIZE, capacity_size,
+			    COL_H_SIZE, baobab.fs.total,
+			    COL_H_ALLOCSIZE, baobab.fs.total,
+			    COL_H_ELEMENTS, -1, -1);
+	g_free (capacity_label);
+	g_free (capacity_size);
+
+	gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (baobab.tree_view), FALSE);
+	gtk_tree_store_append (baobab.model, &firstiter, &root_iter);
+
+		size = g_format_size (baobab.fs.used);
+
+	if (baobab.fs.total == 0 && baobab.fs.used == 0) {
+		perc = 100.0;
+	} else {
+		g_assert (baobab.fs.total != 0);
+		perc = ((gdouble) baobab.fs.used * 100) / (gdouble) baobab.fs.total;
+	}
+
+	label = g_strdup (_("Total filesystem usage"));
+	gtk_tree_store_set (baobab.model, &firstiter,
+			    COL_DIR_NAME, label,
+			    COL_H_PARSENAME, "",
+			    COL_H_PERC, perc,
+			    COL_DIR_SIZE, size,
+			    COL_H_SIZE, baobab.fs.used,
+			    COL_H_ALLOCSIZE, baobab.fs.used,
+			    COL_H_ELEMENTS, -1, -1);
+
+	g_free (size);
+	g_free (label);
+
+	gtk_tree_view_expand_all (GTK_TREE_VIEW (baobab.tree_view));
+}
+
+/* fills model during scanning */
+void
+baobab_fill_model (struct chan_data *data)
+{
+	GtkTreeIter iter;
+	GString *hardlinks;
+	GString *elements;
+	char *name;
+	char *size;
+	char *alloc_size;
+
+	if (data->elements == -1) {
+		prefill_model (data);
+		return;
+	}
+
+	iter = pop_iter_from_stack ();
+
+	/* in case filenames contains gmarkup */
+	name = g_markup_escape_text (data->display_name, -1);
+
+	hardlinks = g_string_new ("");
+	if (data->tempHLsize > 0) {
+		size = g_format_size (data->tempHLsize);
+
+		g_string_assign (hardlinks, "<i>(");
+		g_string_append (hardlinks, _("contains hardlinks for:"));
+		g_string_append (hardlinks, " ");
+		g_string_append (hardlinks, size);
+		g_string_append (hardlinks, ")</i>");
+		g_free (size);
+	}
+
+	elements = g_string_new ("");
+	g_string_printf (elements,
+			 ngettext ("%5d item", "%5d items",
+				   data->elements), data->elements);
+
+	size = g_format_size (data->size);
+	alloc_size = g_format_size (data->alloc_size);
+
+	gtk_tree_store_set (baobab.model, &iter,
+			    COL_DIR_NAME, name,
+			    COL_H_PARSENAME, data->parse_name,
+			    COL_H_PERC, -1.0,
+			    COL_DIR_SIZE,
+			    baobab.show_allocated ? alloc_size : size,
+			    COL_H_SIZE, data->size,
+			    COL_ELEMENTS, elements->str,
+			    COL_H_ELEMENTS, data->elements,
+			    COL_HARDLINK, hardlinks->str,
+			    COL_H_HARDLINK, data->tempHLsize,
+			    COL_H_ALLOCSIZE, data->alloc_size, -1);
+
+	while (gtk_events_pending ()) {
+		gtk_main_iteration ();
+	}
+
+	g_string_free (hardlinks, TRUE);
+	g_string_free (elements, TRUE);
+	g_free (name);
+	g_free (size);
+	g_free (alloc_size);
+}
+
+void
+push_iter_in_stack (GtkTreeIter *iter)
+{
+	g_queue_push_head (iterstack, iter->user_data3);
+	g_queue_push_head (iterstack, iter->user_data2);
+	g_queue_push_head (iterstack, iter->user_data);
+	g_queue_push_head (iterstack, GINT_TO_POINTER (iter->stamp));
+}
+
+GtkTreeIter
+pop_iter_from_stack (void)
+{
+	GtkTreeIter iter;
+
+	iter.stamp = GPOINTER_TO_INT (g_queue_pop_head (iterstack));
+	iter.user_data = g_queue_pop_head (iterstack);
+	iter.user_data2 = g_queue_pop_head (iterstack);
+	iter.user_data3 = g_queue_pop_head (iterstack);
+
+	return iter;
+}
+
+gboolean
+baobab_is_excluded_location (GFile *file)
+{
+	gboolean ret = FALSE;
+	GSList *l;
+
+	g_return_val_if_fail (file != NULL, FALSE);
+
+	for (l = baobab.excluded_locations; l != NULL; l = l->next) {
+		if (g_file_equal (l->data, file)) {
+			ret = TRUE;
+			break;
+		}
+	}
+
+	return ret;
+}
+
+static void
+volume_changed (GVolumeMonitor *volume_monitor,
+                GVolume        *volume,
+                gpointer        user_data)
+{
+	/* filesystem has changed (mounted or unmounted device) */
+	baobab_update_filesystem ();
+}
+
+static void
+home_contents_changed (GFileMonitor      *file_monitor,
+		       GFile             *child,
+		       GFile             *other_file,
+		       GFileMonitorEvent  event_type,
+		       gpointer           user_data)
+
+{
+	gchar *excluding;
+
+	if (baobab.CONTENTS_CHANGED_DELAYED)
+		return;
+
+	excluding = g_file_get_basename (child);
+	if (strcmp (excluding, ".recently-used") == 0   ||
+	    strcmp (excluding, ".mate2_private") == 0  ||
+	    strcmp (excluding, ".xsession-errors") == 0 ||
+	    strcmp (excluding, ".bash_history") == 0) {
+		g_free (excluding);
+		return;
+	}
+	g_free (excluding);
+
+	baobab.CONTENTS_CHANGED_DELAYED = TRUE;
+}
+
+static void
+monitor_volume (void)
+{
+	baobab.monitor_vol = g_volume_monitor_get ();
+
+	g_signal_connect (baobab.monitor_vol, "volume_changed",
+			  G_CALLBACK (volume_changed), NULL);
+}
+
+static void
+monitor_home (gboolean enable)
+{
+	if (enable && baobab.monitor_home == NULL) {
+		GFile *file;
+		GError *error = NULL;
+
+		file = g_file_new_for_path (g_get_home_dir ());
+		baobab.monitor_home = g_file_monitor_directory (file, 0, NULL, &error);
+		g_object_unref (file);
+
+		if (!baobab.monitor_home) {
+			message (_("Could not initialize monitoring"),
+				 _("Changes to your home folder will not be monitored."),
+				 GTK_MESSAGE_WARNING, NULL);
+			g_print ("homedir:%s\n", error->message);
+			g_error_free (error);
+		}
+		else {
+			g_signal_connect (baobab.monitor_home,
+					  "changed",
+					  G_CALLBACK (home_contents_changed),
+					  NULL);
+		}
+	}
+	else if (!enable && baobab.monitor_home != NULL) {
+		g_file_monitor_cancel (baobab.monitor_home);
+		g_object_unref (baobab.monitor_home);
+		baobab.monitor_home = NULL;
+	}
+}
+
+void
+baobab_set_statusbar (const gchar *text)
+{
+	gtk_statusbar_pop (GTK_STATUSBAR (baobab.statusbar), 1);
+	gtk_statusbar_push (GTK_STATUSBAR (baobab.statusbar), 1, text);
+
+	while (gtk_events_pending ())
+		gtk_main_iteration ();
+}
+
+static void
+toolbar_reconfigured_cb (GtkToolItem *item,
+			 GtkWidget   *spinner)
+{
+	GtkToolbarStyle style;
+	GtkIconSize size;
+
+	style = gtk_tool_item_get_toolbar_style (item);
+
+	if (style == GTK_TOOLBAR_BOTH)
+	{
+		size = GTK_ICON_SIZE_DIALOG;
+	}
+	else
+	{
+		size = GTK_ICON_SIZE_LARGE_TOOLBAR;
+	}
+
+	gtk_widget_set_size_request (spinner, size, size);
+}
+
+static void
+baobab_create_toolbar (void)
+{
+	GtkWidget *toolbar;
+	GtkToolItem *item;
+	GtkToolItem *separator;
+
+	toolbar = GET_WIDGET ("toolbar1");
+	if (toolbar == NULL) {
+		g_printerr ("Could not build toolbar\n");
+		return;
+	}
+
+	baobab.toolbar = toolbar;
+
+	separator = gtk_separator_tool_item_new ();
+	gtk_separator_tool_item_set_draw (GTK_SEPARATOR_TOOL_ITEM (separator), FALSE);
+	gtk_tool_item_set_expand (GTK_TOOL_ITEM (separator), TRUE);
+	gtk_container_add (GTK_CONTAINER (toolbar), GTK_WIDGET (separator));
+	gtk_widget_show (GTK_WIDGET (separator));
+
+	baobab.spinner = gtk_spinner_new ();
+	item = gtk_tool_item_new ();
+	gtk_container_add (GTK_CONTAINER (item), baobab.spinner);
+	gtk_container_add (GTK_CONTAINER (toolbar), GTK_WIDGET (item));
+	gtk_widget_show (GTK_WIDGET (item));
+
+	g_signal_connect (item, "toolbar-reconfigured",
+			  G_CALLBACK (toolbar_reconfigured_cb), baobab.spinner);
+	toolbar_reconfigured_cb (item, baobab.spinner);
+
+	g_settings_bind (baobab.ui_settings,
+			 BAOBAB_SETTINGS_TOOLBAR_VISIBLE,
+			 baobab.toolbar, "visible",
+			 G_SETTINGS_BIND_DEFAULT);
+	g_settings_bind (baobab.ui_settings,
+			 BAOBAB_SETTINGS_TOOLBAR_VISIBLE,
+			 GET_TOGGLE_ACTION ("view_tb"), "active",
+			 G_SETTINGS_BIND_DEFAULT);
+
+}
+
+static void
+baobab_create_statusbar (void)
+{
+	baobab.statusbar = GET_WIDGET ("statusbar1");
+	if (baobab.statusbar == NULL) {
+		g_printerr ("Could not build statusbar\n");
+		return;
+	}
+
+	g_settings_bind (baobab.ui_settings,
+			 BAOBAB_SETTINGS_STATUSBAR_VISIBLE,
+			 baobab.statusbar, "visible",
+			 G_SETTINGS_BIND_DEFAULT);
+	g_settings_bind (baobab.ui_settings,
+			 BAOBAB_SETTINGS_STATUSBAR_VISIBLE,
+			 GET_TOGGLE_ACTION ("view_sb"), "active",
+			 G_SETTINGS_BIND_DEFAULT);
+}
+
+static void
+baobab_settings_subfoldertips_changed (GSettings *settings,
+									   const gchar *key,
+									   gpointer user_data)
+{
+	gboolean visible;
+
+	visible = g_settings_get_boolean (settings, key);
+	baobab_ringschart_set_subfoldertips_enabled (baobab.rings_chart, visible);
+}
+
+static void
+baobab_set_excluded_locations (gchar **uris)
+{
+	gint i;
+
+	g_slist_free_full (baobab.excluded_locations, g_object_unref);
+	baobab.excluded_locations = NULL;
+	for (i = 0; uris[i] != NULL; ++i) {
+		baobab.excluded_locations = g_slist_prepend (baobab.excluded_locations,
+						g_file_new_for_uri (uris[i]));
+	}
+}
+
+static void
+store_excluded_locations (void)
+{
+	GSList *l;
+	GPtrArray *uris;
+
+	uris = g_ptr_array_new ();
+
+	for (l = baobab.excluded_locations; l != NULL; l = l->next) {
+		g_ptr_array_add (uris, g_file_get_uri (l->data));
+	}
+
+	g_ptr_array_add (uris, NULL);
+
+	g_settings_set_strv (baobab.prefs_settings,
+			     BAOBAB_SETTINGS_EXCLUDED_URIS,
+			     (const gchar *const *) uris->pdata);
+
+	g_ptr_array_free (uris, TRUE);
+}
+
+static void
+sanity_check_excluded_locations (void)
+{
+	GFile *root;
+	GSList *l;
+
+	/* Make sure the root dir is not excluded */
+	root = g_file_new_for_uri ("file:///");
+
+	for (l = baobab.excluded_locations; l != NULL; l = l->next) {
+		if (g_file_equal (l->data, root)) {
+			baobab.excluded_locations = g_slist_delete_link (baobab.excluded_locations, l);
+			store_excluded_locations ();
+			break;
+		}
+	}
+
+	g_object_unref (root);
+}
+
+static void
+excluded_uris_changed (GSettings   *settings,
+		       const gchar *key,
+		       gpointer     user_data)
+{
+	gchar **uris;
+
+	uris = g_settings_get_strv (settings, key);
+	baobab_set_excluded_locations (uris);
+	g_strfreev (uris);
+
+	baobab_update_filesystem ();
+
+	gtk_tree_store_clear (baobab.model);
+	first_row ();
+}
+
+static void
+baobab_setup_excluded_locations (void)
+{
+	gchar **uris;
+
+	g_signal_connect (baobab.prefs_settings,
+			 "changed::" BAOBAB_SETTINGS_EXCLUDED_URIS,
+			  G_CALLBACK (excluded_uris_changed),
+			  NULL);
+
+	uris = g_settings_get_strv (baobab.prefs_settings,
+				    BAOBAB_SETTINGS_EXCLUDED_URIS);
+	baobab_set_excluded_locations (uris);
+	g_strfreev (uris);
+
+	sanity_check_excluded_locations ();
+}
+
+static void
+baobab_settings_monitor_home_changed (GSettings *settings,
+				      const gchar *key,
+				      gpointer user_data)
+{
+	gboolean enable;
+
+	enable = g_settings_get_boolean (settings, key);
+
+	monitor_home (enable);
+}
+
+static void
+baobab_setup_monitors (void)
+{
+	gboolean enable;
+
+	monitor_volume ();
+
+	g_signal_connect (baobab.prefs_settings,
+			  "changed::" BAOBAB_SETTINGS_MONITOR_HOME,
+			  G_CALLBACK (baobab_settings_monitor_home_changed),
+			  NULL);
+
+	enable = g_settings_get_boolean (baobab.prefs_settings,
+					 BAOBAB_SETTINGS_MONITOR_HOME);
+
+	monitor_home (enable);
+}
+
+static void
+baobab_init (void)
+{
+	GError *error = NULL;
+
+	/* FileSystem usage */
+	baobab_get_filesystem (&baobab.fs);
+
+	/* Load the UI */
+	baobab.main_ui = gtk_builder_new ();
+	if (gtk_builder_add_from_resource (baobab.main_ui, BAOBAB_UI_RESOURCE, &error) == 0) {
+		g_object_unref (baobab.main_ui);
+		g_critical ("Unable to load the user interface file: %s", error->message);
+		g_error_free (error);
+		exit (1);
+	}
+
+	gtk_builder_connect_signals (baobab.main_ui, NULL);
+
+	/* Settings */
+	baobab.ui_settings = g_settings_new (BAOBAB_UI_SETTINGS_SCHEMA);
+	baobab.prefs_settings = g_settings_new (BAOBAB_PREFS_SETTINGS_SCHEMA);
+
+	/* Misc */
+	baobab.CONTENTS_CHANGED_DELAYED = FALSE;
+	baobab.STOP_SCANNING = TRUE;
+	baobab.show_allocated = TRUE;
+	baobab.is_local = TRUE;
+
+	baobab_setup_excluded_locations ();
+
+	baobab_create_toolbar ();
+	baobab_create_statusbar ();
+	baobab_setup_monitors ();
+
+	g_signal_connect (baobab.ui_settings, "changed::" BAOBAB_SETTINGS_SUBFLSTIPS_VISIBLE,
+					  (GCallback) baobab_settings_subfoldertips_changed, NULL);
+}
+
+static void
+baobab_shutdown (void)
+{
+	if (baobab.current_location) {
+		g_object_unref (baobab.current_location);
+	}
+
+	if (baobab.monitor_vol) {
+		g_object_unref (baobab.monitor_vol);
+	}
+
+	if (baobab.monitor_home) {
+		g_file_monitor_cancel (baobab.monitor_home);
+		g_object_unref (baobab.monitor_home);
+	}
+
+	g_free (baobab.selected_path);
+
+	g_slist_free_full (baobab.excluded_locations, g_object_unref);
+
+	if (baobab.ui_settings) {
+		g_object_unref (baobab.ui_settings);
+	}
+
+	if (baobab.prefs_settings) {
+		g_object_unref (baobab.prefs_settings);
+	}
+}
+
+static BaobabChartMenu *
+create_context_menu (void)
+{
+	BaobabChartMenu *menu = NULL;
+
+	baobab.chart_menu = g_new0 (BaobabChartMenu, 1);
+	menu = baobab.chart_menu;
+
+	menu->widget = gtk_menu_new ();
+
+	menu->up_item = gtk_image_menu_item_new_with_label (_("Move to parent folder"));
+	gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menu->up_item),
+				       gtk_image_new_from_icon_name("go-up", GTK_ICON_SIZE_MENU));
+
+	menu->zoom_in_item = gtk_image_menu_item_new_with_label (_("Zoom in")) ;
+	gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menu->zoom_in_item),
+				       gtk_image_new_from_icon_name("list-add", GTK_ICON_SIZE_MENU));
+
+	menu->zoom_out_item = gtk_image_menu_item_new_with_label (_("Zoom out"));
+	gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menu->zoom_out_item),
+				       gtk_image_new_from_icon_name("list-remove", GTK_ICON_SIZE_MENU));
+
+	menu->snapshot_item = gtk_image_menu_item_new_with_label (_("Save screenshot"));
+	gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menu->snapshot_item),
+				       gtk_image_new_from_icon_name ("applets-screenshooter", GTK_ICON_SIZE_MENU));
+
+	gtk_menu_shell_append (GTK_MENU_SHELL (menu->widget),
+			       menu->up_item);
+	gtk_menu_shell_append (GTK_MENU_SHELL (menu->widget),
+			       gtk_separator_menu_item_new ());
+	gtk_menu_shell_append (GTK_MENU_SHELL (menu->widget),
+			       menu->zoom_in_item);
+	gtk_menu_shell_append (GTK_MENU_SHELL (menu->widget),
+			       menu->zoom_out_item);
+	gtk_menu_shell_append (GTK_MENU_SHELL (menu->widget),
+			       gtk_separator_menu_item_new ());
+	gtk_menu_shell_append (GTK_MENU_SHELL (menu->widget),
+			       menu->snapshot_item);
+
+	/* connect signals */
+	g_signal_connect (menu->up_item, "activate",
+			  G_CALLBACK (on_move_upwards_cb), NULL);
+	g_signal_connect (menu->zoom_in_item, "activate",
+			  G_CALLBACK (on_zoom_in_cb), NULL);
+	g_signal_connect (menu->zoom_out_item, "activate",
+			  G_CALLBACK (on_zoom_out_cb), NULL);
+	g_signal_connect (menu->snapshot_item, "activate",
+					  G_CALLBACK (on_chart_snapshot_cb), NULL);
+
+	gtk_widget_show_all (menu->widget);
+
+	return menu;
+}
+
+static void
+on_chart_item_activated (BaobabChart *chart, GtkTreeIter *iter)
+{
+	GtkTreePath *path;
+
+	path = gtk_tree_model_get_path (GTK_TREE_MODEL (baobab.model), iter);
+
+	if (!gtk_tree_view_row_expanded (GTK_TREE_VIEW (baobab.tree_view), path))
+		gtk_tree_view_expand_to_path (GTK_TREE_VIEW (baobab.tree_view), path);
+
+	gtk_tree_view_set_cursor (GTK_TREE_VIEW (baobab.tree_view),
+				  path, NULL, FALSE);
+	gtk_tree_path_free (path);
+}
+
+static gboolean
+on_chart_button_release (BaobabChart *chart,
+			 GdkEventButton *event,
+			 gpointer data)
+{
+	if (baobab_chart_is_frozen (baobab.current_chart))
+		return FALSE;
+
+	if (event->button== 3) /* right button */
+	{
+		GtkTreePath *root_path;
+		BaobabChartMenu *menu;
+
+		root_path = baobab_chart_get_root (baobab.current_chart);
+
+		menu = baobab.chart_menu;
+		gtk_widget_set_sensitive (menu->up_item,
+					  ((root_path != NULL) &&
+					  (gtk_tree_path_get_depth (root_path) > 1)));
+		gtk_widget_set_sensitive (menu->zoom_in_item,
+					  baobab_chart_can_zoom_in (baobab.current_chart));
+		gtk_widget_set_sensitive (menu->zoom_out_item,
+					  baobab_chart_can_zoom_out (baobab.current_chart));
+
+		/* show the menu */
+		gtk_menu_popup_at_pointer (GTK_MENU (menu->widget),
+		                           (const GdkEvent*) event);
+
+		gtk_tree_path_free (root_path);
+	}
+
+	return FALSE;
+}
+
+static void
+drag_data_received_handl (GtkWidget *widget,
+			 GdkDragContext *context,
+			 gint x,
+			 gint y,
+			 GtkSelectionData *selection_data,
+			 guint target_type,
+			 guint time,
+			 gpointer data)
+{
+	GFile *gf = NULL;
+
+	/* set "gf" if we got some valid data */
+	if ((selection_data != NULL) &&
+	    (gtk_selection_data_get_length (selection_data) >= 0) &&
+	    (target_type == DND_TARGET_URI_LIST)) {
+		gchar **uri_list;
+		uri_list = g_uri_list_extract_uris ((const gchar *) gtk_selection_data_get_data (selection_data));
+		/* check list is 1 item long */
+		if (uri_list != NULL && uri_list[0] != NULL && uri_list[1] == NULL) {
+			gf = g_file_new_for_uri (uri_list[0]);
+		}
+		g_strfreev (uri_list);
+	}
+
+	/* success if "gf" has been set */
+	if (gf != NULL) {
+		/* finish drop before beginning scan, as the drag-drop can
+		   probably time out */
+		gtk_drag_finish (context, TRUE, FALSE, time);
+		baobab_scan_location (gf);
+		g_object_unref (gf);
+	} else {
+		gtk_drag_finish (context, FALSE, FALSE, time);
+	}
+}
+
+static void
+set_active_chart (GtkWidget *chart)
+{
+	if (baobab.current_chart != chart) {
+		if (baobab.current_chart) {
+			baobab_chart_freeze_updates (baobab.current_chart);
+
+			g_object_ref (baobab.current_chart);
+			gtk_container_remove (GTK_CONTAINER (baobab.chart_frame),
+					      baobab.current_chart);
+		}
+
+		gtk_container_add (GTK_CONTAINER (baobab.chart_frame), chart);
+		g_object_unref (chart);
+
+		baobab_chart_thaw_updates (chart);
+
+		baobab.current_chart = chart;
+
+		gtk_widget_show_all (baobab.chart_frame);
+
+		g_settings_set_string (baobab.ui_settings,
+				       BAOBAB_SETTINGS_ACTIVE_CHART,
+				       baobab.current_chart == baobab.rings_chart ? "rings" : "treemap");
+	}
+}
+
+static void
+on_chart_type_change (GtkWidget *combo, gpointer user_data)
+{
+	GtkWidget *chart;
+	gint active;
+
+	active = gtk_combo_box_get_active (GTK_COMBO_BOX (combo));
+
+	switch (active) {
+	case 0:
+		chart = baobab.rings_chart;
+		break;
+	case 1:
+		chart = baobab.treemap_chart;
+		break;
+	default:
+		g_return_if_reached ();
+	}
+
+	set_active_chart (chart);
+}
+
+static void
+initialize_charts (void)
+{
+	GtkWidget *hpaned_main;
+	GtkWidget *hbox1;
+	char *saved_chart;
+	gboolean visible;
+
+	baobab.chart_frame = gtk_frame_new (NULL);
+	gtk_frame_set_label_align (GTK_FRAME (baobab.chart_frame), 0.0, 0.0);
+	gtk_frame_set_shadow_type (GTK_FRAME (baobab.chart_frame), GTK_SHADOW_IN);
+
+	hpaned_main = GET_WIDGET ("hpaned_main");
+	gtk_paned_pack2 (GTK_PANED (hpaned_main),
+			 baobab.chart_frame, TRUE, TRUE);
+	gtk_paned_set_position (GTK_PANED (hpaned_main), 480);
+
+	baobab.chart_type_combo = gtk_combo_box_text_new ();
+	gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (baobab.chart_type_combo),
+				   _("View as Rings Chart"));
+	gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (baobab.chart_type_combo),
+				   _("View as Treemap Chart"));
+	gtk_widget_show (baobab.chart_type_combo);
+	g_signal_connect (baobab.chart_type_combo,
+			  "changed",
+			  G_CALLBACK (on_chart_type_change), NULL);
+
+	hbox1 = GET_WIDGET ("hbox1");
+	gtk_container_add (GTK_CONTAINER (hbox1), baobab.chart_type_combo);
+	gtk_box_set_spacing (GTK_BOX (hbox1), 50);
+	gtk_box_set_child_packing (GTK_BOX (hbox1),
+				   baobab.chart_type_combo,
+				   FALSE,
+				   TRUE,
+				   0, GTK_PACK_END);
+
+	baobab.chart_menu = create_context_menu ();
+
+	/* Baobab's Treemap Chart */
+	baobab.treemap_chart = baobab_treemap_new ();
+	baobab_chart_set_model_with_columns (baobab.treemap_chart,
+					     GTK_TREE_MODEL (baobab.model),
+					     COL_DIR_NAME,
+					     COL_DIR_SIZE,
+					     COL_H_PARSENAME,
+					     COL_H_PERC,
+					     COL_H_ELEMENTS,
+					     NULL);
+	baobab_chart_set_max_depth (baobab.treemap_chart, 1);
+	g_signal_connect (baobab.treemap_chart, "item_activated",
+			  G_CALLBACK (on_chart_item_activated), NULL);
+	g_signal_connect (baobab.treemap_chart, "button-release-event",
+			  G_CALLBACK (on_chart_button_release), NULL);
+	g_signal_connect (baobab.treemap_chart, "drag-data-received",
+			  G_CALLBACK (drag_data_received_handl), NULL);
+	gtk_widget_show (baobab.treemap_chart);
+	g_object_ref_sink (baobab.treemap_chart);
+	baobab_chart_freeze_updates (baobab.treemap_chart);
+
+	/* Baobab's Rings Chart */
+	baobab.rings_chart = (GtkWidget *) baobab_ringschart_new ();
+	baobab_chart_set_model_with_columns (baobab.rings_chart,
+					     GTK_TREE_MODEL (baobab.model),
+					     COL_DIR_NAME,
+					     COL_DIR_SIZE,
+					     COL_H_PARSENAME,
+					     COL_H_PERC,
+					     COL_H_ELEMENTS,
+					     NULL);
+
+	visible = g_settings_get_boolean (baobab.ui_settings,
+									  BAOBAB_SETTINGS_SUBFLSTIPS_VISIBLE);
+	baobab_ringschart_set_subfoldertips_enabled (baobab.rings_chart, visible);
+
+	baobab_chart_set_max_depth (baobab.rings_chart, 1);
+	g_signal_connect (baobab.rings_chart, "item_activated",
+			  G_CALLBACK (on_chart_item_activated), NULL);
+	g_signal_connect (baobab.rings_chart, "button-release-event",
+			  G_CALLBACK (on_chart_button_release), NULL);
+	g_signal_connect (baobab.rings_chart, "drag-data-received",
+			  G_CALLBACK (drag_data_received_handl), NULL);
+	gtk_widget_show (baobab.rings_chart);
+	g_object_ref_sink (baobab.rings_chart);
+	baobab_chart_freeze_updates (baobab.rings_chart);
+
+	saved_chart = g_settings_get_string (baobab.ui_settings,
+					     BAOBAB_SETTINGS_ACTIVE_CHART);
+
+	if (0 == g_ascii_strcasecmp (saved_chart, "treemap")) {
+		set_active_chart (baobab.treemap_chart);
+		gtk_combo_box_set_active (GTK_COMBO_BOX (baobab.chart_type_combo), 1);
+	} else {
+		set_active_chart (baobab.rings_chart);
+		gtk_combo_box_set_active (GTK_COMBO_BOX (baobab.chart_type_combo), 0);
+	}
+
+	g_free (saved_chart);
+
+	check_drop_targets (FALSE);
+}
+
+void
+baobab_quit ()
+{
+	baobab_stop_scan ();
+	gtk_main_quit ();
+}
+
+static gboolean
+start_proc_on_command_line (GFile *file)
+{
+	baobab_scan_location (file);
+
+	return FALSE;
+}
+
+static gboolean
+show_version (const gchar *option_name,
+              const gchar *value,
+              gpointer data,
+              GError **error)
+{
+	g_print("%s %s\n", g_get_application_name (), VERSION);
+	exit (0);
+	return TRUE; /* It's just good form */
+}
+
+int
+main (int argc, char *argv[])
+{
+	gchar **directories = NULL;
+	const GOptionEntry options[] = {
+		{"version", 'V', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, show_version, N_("Show version"), NULL},
+		{G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &directories, NULL, N_("[DIRECTORY]")},
+		{ NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL }
+	};
+	GOptionContext *context;
+	GError *error = NULL;
+
+#ifdef ENABLE_NLS
+	bindtextdomain (GETTEXT_PACKAGE, MATELOCALEDIR);
+	bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+	textdomain (GETTEXT_PACKAGE);
+#endif /* ENABLE_NLS */
+
+	g_set_application_name (_("Disk Usage Analyzer"));
+
+	context = g_option_context_new (NULL);
+	g_option_context_set_ignore_unknown_options (context, FALSE);
+	g_option_context_set_help_enabled (context, TRUE);
+	g_option_context_add_main_entries(context, options, GETTEXT_PACKAGE);
+	g_option_context_add_group (context, gtk_get_option_group (TRUE));
+
+	g_option_context_parse (context, &argc, &argv, &error);
+
+	if (error) {
+		g_critical ("Unable to parse option: %s", error->message);
+		g_error_free (error);
+		g_option_context_free (context);
+
+		exit (1);
+	}
+	g_option_context_free (context);
+
+	if (directories && directories[0] && directories[1]) {
+		g_critical (_("Too many arguments. Only one directory can be specified."));
+		exit (1);
+	}
+
+	glibtop_init ();
+
+	gtk_window_set_default_icon_name ("mate-disk-usage-analyzer");
+
+	baobab_init ();
+
+	if (baobab.fs.total == 0) {
+		GtkWidget *dialog;
+
+		dialog = gtk_message_dialog_new (NULL,
+				GTK_DIALOG_DESTROY_WITH_PARENT,
+				GTK_MESSAGE_ERROR,
+				GTK_BUTTONS_CLOSE,
+				_("Could not detect any mount point."));
+		gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG(dialog),
+				_("Without mount points disk usage cannot be analyzed."));
+		gtk_dialog_run (GTK_DIALOG (dialog));
+		gtk_widget_destroy (dialog);
+		goto closing;
+	}
+
+	check_menu_sens (FALSE);
+	update_scan_label ();
+
+	baobab.window = GET_WIDGET ("baobab_window");
+	gtk_window_set_position (GTK_WINDOW (baobab.window),
+				 GTK_WIN_POS_CENTER);
+
+	baobab.tree_view = create_directory_treeview ();
+
+	gtk_action_set_sensitive (GET_ACTION ("menurescan"), FALSE);
+
+	/* set allocated space checkbox */
+	gtk_toggle_action_set_active (GET_TOGGLE_ACTION ("ck_allocated"),
+				      baobab.show_allocated);
+
+	gtk_widget_show (baobab.window);
+
+	first_row ();
+	baobab_set_statusbar (_("Ready"));
+
+	initialize_charts ();
+
+	/* commandline */
+	if (directories && directories[0]) {
+		GFile *file;
+
+		file = g_file_new_for_commandline_arg (directories[0]);
+
+		/* start processing the dir specified on the
+		 * command line as soon as we enter the main loop */
+		g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
+		                 (GSourceFunc) start_proc_on_command_line,
+		                 file,
+		                 g_object_unref);
+	}
+	g_strfreev (directories);
+
+	gtk_main ();
+
+ closing:
+	baobab_shutdown ();
+
+	glibtop_close ();
+
+	return 0;
+}
+
+ +
+ +
+ + diff --git a/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/9.html b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/9.html new file mode 100644 index 00000000..763b42a1 --- /dev/null +++ b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/9.html @@ -0,0 +1,1531 @@ + + + + + + Cppcheck - HTML report - mate-utils + + + + + +
+ + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
+479
+480
+481
+482
+483
+484
+485
+486
+487
+488
+489
+490
+491
+492
+493
+494
+495
+496
+497
+498
+499
+500
+501
+502
+503
+504
+505
+506
+507
+508
+509
+510
+511
+512
+513
+514
+515
+516
+517
+518
+519
+520
+521
+522
+523
+524
+525
+526
+527
+528
+529
+530
+531
+532
+533
+534
+535
+536
+537
+538
+539
+540
+541
+542
+543
+544
+545
+546
+547
+548
+549
+550
+551
+552
+553
+554
+555
+556
+557
+558
+559
+560
+561
+562
+563
+564
+565
+566
+567
+568
+569
+570
+571
+572
+573
+574
+575
+576
+577
+578
+579
+580
+581
+582
+583
+584
+585
+586
+587
+588
+589
+590
+591
+592
+593
+594
+595
+596
+597
+598
+599
+600
+601
+602
+603
+604
+605
+606
+607
+608
+609
+610
+611
+612
+613
+614
+615
+616
+617
+618
+619
+620
+621
+622
+623
+624
+625
+626
+627
+628
+629
+630
+631
+632
+633
+634
+635
+636
+637
+638
+639
+640
+641
+642
+643
+644
+645
+646
+647
/* Copyright (C) 2009 Dennis Cranston
+ *
+ * This file was modified from gedit (gedit-history-entry.c).
+ * Copyright (C) Paolo Borelli
+ *
+ * This file is part of MATE Utils.
+ *
+ * MATE Utils is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * MATE Utils is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MATE Utils.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ * Author: Paolo Borelli
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+
+#include "gsearchtool-entry.h"
+
+enum {
+	PROP_0,
+	PROP_HISTORY_ID,
+	PROP_HISTORY_LENGTH
+};
+
+#define MIN_ITEM_LEN 0
+#define GSEARCH_HISTORY_ENTRY_HISTORY_LENGTH_DEFAULT 10
+
+struct _GsearchHistoryEntryPrivate
+{
+	gchar              *history_id;
+	guint               history_length;
+
+	GtkEntryCompletion *completion;
+
+	GSettings          *settings;
+};
+
+G_DEFINE_TYPE_WITH_PRIVATE (GsearchHistoryEntry, gsearch_history_entry, GTK_TYPE_COMBO_BOX)<--- There is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
+
+static void
+gsearch_history_entry_set_property (GObject      *object,
+				    guint         prop_id,
+				    const GValue *value,
+				    GParamSpec   *spec)
+{
+	GsearchHistoryEntry *entry;
+
+	g_return_if_fail (GSEARCH_IS_HISTORY_ENTRY (object));
+
+	entry = GSEARCH_HISTORY_ENTRY (object);
+
+	switch (prop_id) {
+	case PROP_HISTORY_ID:
+		entry->priv->history_id = g_value_dup_string (value);
+		break;
+	case PROP_HISTORY_LENGTH:
+		gsearch_history_entry_set_history_length (entry,
+						     g_value_get_uint (value));
+		break;
+	default:
+		break;
+	}
+}
+
+static void
+gsearch_history_entry_get_property (GObject    *object,
+				    guint       prop_id,
+				    GValue     *value,
+				    GParamSpec *spec)
+{
+	GsearchHistoryEntryPrivate *priv;
+
+	g_return_if_fail (GSEARCH_IS_HISTORY_ENTRY (object));
+
+	priv = GSEARCH_HISTORY_ENTRY (object)->priv;
+
+	switch (prop_id) {
+	case PROP_HISTORY_ID:
+		g_value_set_string (value, priv->history_id);
+		break;
+	case PROP_HISTORY_LENGTH:
+		g_value_set_uint (value, priv->history_length);
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, spec);
+	}
+}
+
+static void
+gsearch_history_entry_destroy (GtkWidget *object)
+{
+	gsearch_history_entry_set_enable_completion (GSEARCH_HISTORY_ENTRY (object),
+						   FALSE);
+
+	GTK_WIDGET_CLASS (gsearch_history_entry_parent_class)->destroy (object);
+}
+
+static void
+gsearch_history_entry_finalize (GObject *object)
+{
+	GsearchHistoryEntryPrivate *priv;
+
+	priv = GSEARCH_HISTORY_ENTRY (object)->priv;
+
+	g_free (priv->history_id);
+
+	if (priv->settings != NULL)
+	{
+		g_object_unref (G_OBJECT (priv->settings));
+		priv->settings = NULL;
+	}
+
+	G_OBJECT_CLASS (gsearch_history_entry_parent_class)->finalize (object);
+}
+
+static void
+gsearch_history_entry_class_init (GsearchHistoryEntryClass *klass)
+{
+	GObjectClass   *object_class = G_OBJECT_CLASS (klass);
+	GtkWidgetClass *gtkwidget_class = GTK_WIDGET_CLASS (klass);
+
+	object_class->set_property = gsearch_history_entry_set_property;
+	object_class->get_property = gsearch_history_entry_get_property;
+	object_class->finalize = gsearch_history_entry_finalize;
+	gtkwidget_class->destroy = gsearch_history_entry_destroy;
+
+	g_object_class_install_property (object_class,
+					 PROP_HISTORY_ID,
+					 g_param_spec_string ("history-id",
+							      "History ID",
+							      "History ID",
+							      NULL,
+							      G_PARAM_READWRITE |
+							      G_PARAM_STATIC_STRINGS));
+
+	g_object_class_install_property (object_class,
+					 PROP_HISTORY_LENGTH,
+					 g_param_spec_uint ("history-length",
+							    "Max History Length",
+							    "Max History Length",
+							    0,
+							    G_MAXUINT,
+							    GSEARCH_HISTORY_ENTRY_HISTORY_LENGTH_DEFAULT,
+							    G_PARAM_READWRITE |
+							    G_PARAM_STATIC_STRINGS));
+
+	/* TODO: Add enable-completion property */
+}
+
+static GtkListStore *
+get_history_store (GsearchHistoryEntry *entry)
+{
+	GtkTreeModel *store;
+
+	store = gtk_combo_box_get_model (GTK_COMBO_BOX (entry));
+	g_return_val_if_fail (GTK_IS_LIST_STORE (store), NULL);
+
+	return (GtkListStore *) store;
+}
+
+static char *
+get_history_key (GsearchHistoryEntry *entry)
+{
+	return g_strdup (entry->priv->history_id);
+}
+
+static GSList *
+get_history_list (GsearchHistoryEntry *entry)
+{
+	GtkListStore *store;
+	GtkTreeIter iter;
+	gboolean valid;
+	GSList *list = NULL;
+
+	store = get_history_store (entry);
+
+	valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store),
+					       &iter);
+
+	while (valid)
+	{
+		gchar *str;
+
+		gtk_tree_model_get (GTK_TREE_MODEL (store),
+				    &iter,
+				    0, &str,
+				    -1);
+
+		list = g_slist_prepend (list, str);
+
+		valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (store),
+						  &iter);
+	}
+
+	return g_slist_reverse (list);
+}
+
+static void
+gsearch_history_entry_save_history (GsearchHistoryEntry *entry)
+{
+	GVariant *history;
+	GSList *items;
+	gchar *key;
+	GVariantBuilder item_builder;
+	GVariantBuilder history_builder;
+	GVariantIter *iter;
+	GVariant     *item;
+	GVariant     *history_list;
+	GSList *list_iter;
+	gchar *history_key;
+
+	g_return_if_fail (GSEARCH_IS_HISTORY_ENTRY (entry));
+
+	items = get_history_list (entry);
+	key = get_history_key (entry);
+
+	history = g_settings_get_value (entry->priv->settings,
+				        "search-history");
+
+	g_variant_builder_init (&item_builder, G_VARIANT_TYPE ("as"));
+	for (list_iter = items; list_iter; list_iter = list_iter->next)
+		g_variant_builder_add (&item_builder, "s", (gchar *) list_iter->data);
+
+	g_variant_builder_init (&history_builder, G_VARIANT_TYPE ("a{sas}"));
+	g_variant_builder_add (&history_builder, "{sas}", key, &item_builder);
+
+	if (history) {
+		g_variant_get (history, "a{sas}", &iter);
+		while ((item = g_variant_iter_next_value (iter))) {
+			g_variant_get (item, "{s@as}", &history_key, &history_list);
+			if (g_strcmp0 (history_key, key) != 0)
+				g_variant_builder_add (&history_builder, "{s@as}", history_key, history_list);
+	 		g_free (history_key);
+	 		g_variant_unref (history_list);
+	 		g_variant_unref (item);
+ 		}
+ 		g_variant_iter_free (iter);
+ 		g_variant_unref (history);
+ 	}
+
+	g_settings_set_value (entry->priv->settings,
+			      "search-history",
+			      g_variant_new ("a{sas}", &history_builder));
+
+	g_slist_free_full (items, g_free);
+	g_free (key);
+}
+
+static gboolean
+remove_item (GtkListStore *store,
+	     const gchar  *text)
+{
+	GtkTreeIter iter;
+
+	g_return_val_if_fail (text != NULL, FALSE);
+
+	if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter))
+		return FALSE;
+
+	do
+	{
+		gchar *item_text;
+
+		gtk_tree_model_get (GTK_TREE_MODEL (store),
+				    &iter,
+				    0,
+				    &item_text,
+				    -1);
+
+		if (item_text != NULL &&
+		    strcmp (item_text, text) == 0)
+		{
+			gtk_list_store_remove (store, &iter);
+			g_free (item_text);
+			return TRUE;
+		}
+
+		g_free (item_text);
+
+	} while (gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &iter));
+
+	return FALSE;
+}
+
+static void
+clamp_list_store (GtkListStore *store,
+		  guint         max)
+{
+	GtkTreePath *path;
+	GtkTreeIter iter;
+
+	/* -1 because TreePath counts from 0 */
+	path = gtk_tree_path_new_from_indices (max - 1, -1);
+
+	if (gtk_tree_model_get_iter (GTK_TREE_MODEL (store), &iter, path))
+	{
+		while (1)
+		{
+			if (!gtk_list_store_remove (store, &iter))
+				break;
+		}
+	}
+
+	gtk_tree_path_free (path);
+}
+
+static void
+insert_history_item (GsearchHistoryEntry *entry,
+		     const gchar       *text,
+		     gboolean           prepend)
+{
+	GtkListStore *store;
+	GtkTreeIter iter;
+
+	if (g_utf8_strlen (text, -1) <= MIN_ITEM_LEN)
+		return;
+
+	store = get_history_store (entry);
+
+	/* remove the text from the store if it was already
+	 * present. If it wasn't, clamp to max history - 1
+	 * before inserting the new row, otherwise appending
+	 * would not work */
+
+	if (!remove_item (store, text))
+		clamp_list_store (store,
+				  entry->priv->history_length - 1);
+
+	if (prepend)
+		gtk_list_store_insert (store, &iter, 0);
+	else
+		gtk_list_store_append (store, &iter);
+
+	gtk_list_store_set (store,
+			    &iter,
+			    0,
+			    text,
+			    -1);
+
+	gsearch_history_entry_save_history (entry);
+}
+
+void
+gsearch_history_entry_prepend_text (GsearchHistoryEntry *entry,
+				    const gchar       *text)
+{
+	g_return_if_fail (GSEARCH_IS_HISTORY_ENTRY (entry));
+	g_return_if_fail (text != NULL);
+
+	insert_history_item (entry, text, TRUE);
+}
+
+void
+gsearch_history_entry_append_text (GsearchHistoryEntry *entry,
+				   const gchar       *text)
+{
+	g_return_if_fail (GSEARCH_IS_HISTORY_ENTRY (entry));
+	g_return_if_fail (text != NULL);
+
+	insert_history_item (entry, text, FALSE);
+}
+
+static void
+gsearch_history_entry_load_history (GsearchHistoryEntry *entry)
+{
+	GtkListStore *store;
+	GtkTreeIter iter;
+	GVariant *history;
+	gchar *key;
+	gint i;
+
+	g_return_if_fail (GSEARCH_IS_HISTORY_ENTRY (entry));
+
+	store = get_history_store (entry);
+	key = get_history_key (entry);
+
+	history = g_settings_get_value (entry->priv->settings,
+					"search-history");
+
+	gtk_list_store_clear (store);
+
+	if (history) {
+		GVariantIter *history_iter, *history_subiter;
+		GVariant     *history_item, *history_subitem;
+		gchar        *history_key;
+		gchar        *text;
+
+		g_variant_get (history, "a{sas}", &history_iter);
+
+		while ((history_item = g_variant_iter_next_value (history_iter))) {
+			i = 0;
+			g_variant_get (history_item, "{sas}", &history_key, &history_subiter);
+
+			if (g_strcmp0 (history_key, key) == 0) {
+				while ((history_subitem = g_variant_iter_next_value (history_subiter)) &&
+				       i < entry->priv->history_length) {
+					g_variant_get (history_subitem, "s", &text);
+					gtk_list_store_append (store, &iter);
+					gtk_list_store_set (store,
+							    &iter,
+							    0,
+							    text,
+							    -1);
+					g_free (text);
+					g_variant_unref (history_subitem);
+					i++;
+				}
+			}
+			g_free (history_key);
+	 		g_variant_iter_free (history_subiter);
+			g_variant_unref (history_item);
+ 		}
+ 		g_variant_iter_free (history_iter);
+		g_variant_unref (history);
+ 	}
+	g_free (key);
+}
+
+void
+gsearch_history_entry_clear (GsearchHistoryEntry *entry)
+{
+	GtkListStore *store;
+
+	g_return_if_fail (GSEARCH_IS_HISTORY_ENTRY (entry));
+
+	store = get_history_store (entry);
+	gtk_list_store_clear (store);
+
+	gsearch_history_entry_save_history (entry);
+}
+
+static void
+gsearch_history_entry_init (GsearchHistoryEntry *entry)
+{
+	GsearchHistoryEntryPrivate *priv;
+
+	priv = gsearch_history_entry_get_instance_private (entry);
+	entry->priv = priv;
+
+	priv->history_id = NULL;
+	priv->history_length = GSEARCH_HISTORY_ENTRY_HISTORY_LENGTH_DEFAULT;
+
+	priv->completion = NULL;
+
+	priv->settings = g_settings_new ("org.mate.search-tool");
+}
+
+void
+gsearch_history_entry_set_history_length (GsearchHistoryEntry *entry,
+					guint              history_length)
+{
+	g_return_if_fail (GSEARCH_IS_HISTORY_ENTRY (entry));
+	g_return_if_fail (history_length > 0);
+
+	entry->priv->history_length = history_length;
+
+	/* TODO: update if we currently have more items than max */
+}
+
+guint
+gsearch_history_entry_get_history_length (GsearchHistoryEntry *entry)
+{
+	g_return_val_if_fail (GSEARCH_IS_HISTORY_ENTRY (entry), 0);
+
+	return entry->priv->history_length;
+}
+
+gchar *
+gsearch_history_entry_get_history_id (GsearchHistoryEntry *entry)
+{
+	g_return_val_if_fail (GSEARCH_IS_HISTORY_ENTRY (entry), NULL);
+
+	return g_strdup (entry->priv->history_id);
+}
+
+void
+gsearch_history_entry_set_enable_completion (GsearchHistoryEntry *entry,
+					     gboolean           enable)
+{
+	g_return_if_fail (GSEARCH_IS_HISTORY_ENTRY (entry));
+
+	if (enable)
+	{
+		if (entry->priv->completion != NULL)
+			return;
+
+		entry->priv->completion = gtk_entry_completion_new ();
+		gtk_entry_completion_set_model (entry->priv->completion,
+						GTK_TREE_MODEL (get_history_store (entry)));
+
+		/* Use model column 0 as the text column */
+		gtk_entry_completion_set_text_column (entry->priv->completion, 0);
+
+		gtk_entry_completion_set_minimum_key_length (entry->priv->completion,
+							     MIN_ITEM_LEN);
+
+		gtk_entry_completion_set_popup_completion (entry->priv->completion, FALSE);
+		gtk_entry_completion_set_inline_completion (entry->priv->completion, TRUE);
+
+		/* Assign the completion to the entry */
+		gtk_entry_set_completion (GTK_ENTRY (gsearch_history_entry_get_entry(entry)),
+					  entry->priv->completion);
+	}
+	else
+	{
+		if (entry->priv->completion == NULL)
+			return;
+
+		gtk_entry_set_completion (GTK_ENTRY (gsearch_history_entry_get_entry (entry)),
+					  NULL);
+
+		g_object_unref (entry->priv->completion);
+
+		entry->priv->completion = NULL;
+	}
+}
+
+gboolean
+gsearch_history_entry_get_enable_completion (GsearchHistoryEntry *entry)
+{
+	g_return_val_if_fail (GSEARCH_IS_HISTORY_ENTRY (entry), FALSE);
+
+	return entry->priv->completion != NULL;
+}
+
+GtkWidget *
+gsearch_history_entry_new (const gchar *history_id,
+			   gboolean     enable_completion)
+{
+	GtkWidget *ret;
+	GtkListStore *store;
+
+	g_return_val_if_fail(history_id != NULL, NULL);
+
+	/* Note that we are setting the model, so
+	 * user must be careful to always manipulate
+	 * data in the history through gsearch_history_entry_
+	 * functions.
+	 */
+
+	store = gtk_list_store_new(1, G_TYPE_STRING);
+
+	ret = g_object_new(GSEARCH_TYPE_HISTORY_ENTRY,
+						"has-entry", TRUE,
+						"history-id", history_id,
+						"model", store,
+						"entry-text-column", 0,
+						NULL);
+
+	g_object_unref (store);
+
+	/* loading has to happen after the model
+	 * has been set. However the model is not a
+	 * G_PARAM_CONSTRUCT property of GtkComboBox
+	 * so we cannot do this in the constructor.
+	 * For now we simply do here since this widget is
+	 * not bound to other programming languages.
+	 * A maybe better alternative is to override the
+	 * model property of combobox and mark CONTRUCT_ONLY.
+	 * This would also ensure that the model cannot be
+	 * set explicitely at a later time.
+	 */
+	gsearch_history_entry_load_history (GSEARCH_HISTORY_ENTRY (ret));
+
+	gsearch_history_entry_set_enable_completion (GSEARCH_HISTORY_ENTRY (ret),
+						   enable_completion);
+
+	return ret;
+}
+
+/*
+ * Utility function to get the editable text entry internal widget.
+ * I would prefer to not expose this implementation detail and
+ * simply make the GsearchHistoryEntry widget implement the
+ * GtkEditable interface. Unfortunately both GtkEditable and
+ * GtkComboBox have a "changed" signal and I am not sure how to
+ * handle the conflict.
+ */
+GtkWidget *
+gsearch_history_entry_get_entry (GsearchHistoryEntry *entry)
+{
+	g_return_val_if_fail (GSEARCH_IS_HISTORY_ENTRY (entry), NULL);
+
+	return gtk_bin_get_child (GTK_BIN (entry));
+}
+
+static void
+escape_cell_data_func (GtkTreeViewColumn             *col,
+		       GtkCellRenderer               *renderer,
+		       GtkTreeModel                  *model,
+		       GtkTreeIter                   *iter,
+		       GsearchHistoryEntryEscapeFunc  escape_func)
+{
+	gchar *str;
+	gchar *escaped;
+
+	gtk_tree_model_get (model, iter, 0, &str, -1);
+	escaped = escape_func (str);
+	g_object_set (renderer, "text", escaped, NULL);
+
+	g_free (str);
+	g_free (escaped);
+}
+
+void
+gsearch_history_entry_set_escape_func (GsearchHistoryEntry           *entry,
+				       GsearchHistoryEntryEscapeFunc  escape_func)
+{
+	GList *cells;
+
+	g_return_if_fail (GSEARCH_IS_HISTORY_ENTRY (entry));
+
+	cells = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (entry));
+
+	/* We only have one cell renderer */
+	g_return_if_fail (cells->data != NULL && cells->next == NULL);
+
+	if (escape_func != NULL)
+		gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (entry),
+						    GTK_CELL_RENDERER (cells->data),
+						    (GtkCellLayoutDataFunc) escape_cell_data_func,
+						    escape_func,
+						    NULL);
+	else
+		gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (entry),
+						    GTK_CELL_RENDERER (cells->data),
+						    NULL,
+						    NULL,
+						    NULL);
+
+	g_list_free (cells);
+}
+
+ +
+ +
+ + diff --git a/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/index.html b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/index.html new file mode 100644 index 00000000..a1dffabd --- /dev/null +++ b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/index.html @@ -0,0 +1,388 @@ + + + + + + Cppcheck - HTML report - mate-utils + + + + + +
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
LineIdCWESeverityMessage
missingIncludeinformationCppcheck cannot find all the include files (use --check-config for details)
baobab/src/baobab-cell-renderer-progress.c
39unknownMacroerrorThere is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
baobab/src/baobab-chart.c
337variableScope398styleThe scope of the variable 'item' can be reduced.
465variableScope398styleThe scope of the variable 'item' can be reduced.
499variableScope398styleThe scope of the variable 'item' can be reduced.
673constParameter398styleParameter 'iter' can be declared as pointer to const
687constParameter398styleParameter 'iter' can be declared as pointer to const
701constParameter398styleParameter 'iter' can be declared as pointer to const
729constParameter398styleParameter 'iter' can be declared as pointer to const
1007variableScope398styleThe scope of the variable 'item' can be reduced.
1412variableScope398styleThe scope of the variable 'current_root' can be reduced.
1628variableScope398styleThe scope of the variable 'parent_path' can be reduced.
1688variableScope398styleThe scope of the variable 'sel_type' can be reduced.
baobab/src/baobab-remote-connect-dialog.c
54unknownMacroerrorThere is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE is a macro then please configure it.
baobab/src/baobab-resources.c
9unusedStructMember563styleunion member 'Anonymous0::alignment' is never used.
9unusedStructMember563styleunion member 'Anonymous0::ptr' is never used.
baobab/src/baobab-ringschart.c
421variableScope398styleThe scope of the variable 'item' can be reduced.
433variableScope398styleThe scope of the variable 'layout' can be reduced.
baobab/src/baobab-scan.c
342variableScope398styleThe scope of the variable 'hla' can be reduced.
346variableScope398styleThe scope of the variable 'sizes' can be reduced.
baobab/src/baobab-treemap.c
111variableScope398styleThe scope of the variable 'layout' can be reduced.
baobab/src/baobab-utils.c
102variableScope398styleThe scope of the variable 'toggle' can be reduced.
363variableScope398styleThe scope of the variable 'primary' can be reduced.
baobab/src/baobab.c
83variableScope398styleThe scope of the variable 'display' can be reduced.
338knownConditionTrueFalse571styleCondition 'data->depth<currentdepth' is always true
gsearchtool/libmateui-deprecated/gsearchtool-entry.c
53unknownMacroerrorThere is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
gsearchtool/mate-submodules/libegg/eggdesktopfile.c
497variableScope398styleThe scope of the variable 'try_exec' can be reduced.
497variableScope398styleThe scope of the variable 'found_program' can be reduced.
498variableScope398styleThe scope of the variable 'only_show_in' can be reduced.
498variableScope398styleThe scope of the variable 'not_show_in' can be reduced.
500variableScope398styleThe scope of the variable 'i' can be reduced.
622variableScope398styleThe scope of the variable 'p' can be reduced.
gsearchtool/mate-submodules/libegg/eggsmclient-xsmp.c
182unknownMacroerrorThere is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE is a macro then please configure it.
gsearchtool/mate-submodules/libegg/eggsmclient.c
48unknownMacroerrorThere is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
gsearchtool/mate-submodules/libegg/eggtreemultidnd.c
46unusedStructMember563stylestruct member '_TreeViewDragInfo::source_target_list' is never used.
49unusedStructMember563stylestruct member '_TreeViewDragInfo::dest_target_list' is never used.
gsearchtool/src/gsearchtool-callbacks.c
131variableScope398styleThe scope of the variable 'command' can be reduced.
1123variableScope398styleThe scope of the variable 'new2' can be reduced.
1154variableScope398styleThe scope of the variable 'str' can be reduced.
1415variableScope398styleThe scope of the variable 'tmp' can be reduced.
1883shadowArgument398styleLocal variable 'response' shadows outer argument
gsearchtool/src/gsearchtool-support.c
790variableScope398styleThe scope of the variable 'screen' can be reduced.
791variableScope398styleThe scope of the variable 'display' can be reduced.
1168variableScope398styleThe scope of the variable 'valid_bytes' can be reduced.
gsearchtool/src/gsearchtool.c
672variableScope398styleThe scope of the variable 'value' can be reduced.
1061variableScope398styleThe scope of the variable 'string' can be reduced.
2251variableScope398styleThe scope of the variable 'path' can be reduced.
logview/src/logview-app.c
156variableScope398styleThe scope of the variable 'info' can be reduced.
158variableScope398styleThe scope of the variable 'content_type' can be reduced.
158variableScope398styleThe scope of the variable 'name' can be reduced.
logview/src/logview-filter-manager.c
169variableScope398styleThe scope of the variable 'name' can be reduced.
170variableScope398styleThe scope of the variable 'regex' can be reduced.
171variableScope398styleThe scope of the variable 'filter' can be reduced.
172variableScope398styleThe scope of the variable 'tag' can be reduced.
logview/src/logview-findbar.c
331variableScope398styleThe scope of the variable 'desc' can be reduced.
logview/src/logview-log.c
80unusedStructMember563stylestruct member 'GZHandle::parent_str' is never used.
81unusedStructMember563stylestruct member 'GZHandle::buffer' is never used.
82unusedStructMember563stylestruct member 'GZHandle::file' is never used.
85unusedStructMember563stylestruct member 'GZHandle::last_z_result' is never used.
95variableScope398styleThe scope of the variable 'lines' can be reduced.
199variableScope398styleThe scope of the variable 'res' can be reduced.
200variableScope398styleThe scope of the variable 'day' can be reduced.
535variableScope398styleThe scope of the variable 'z_result' can be reduced.
logview/src/logview-loglist.c
80variableScope398styleThe scope of the variable 'day' can be reduced.
481variableScope398styleThe scope of the variable 'days' can be reduced.
logview/src/logview-manager.c
220variableScope398styleThe scope of the variable 'data' can be reduced.
418constParameter398styleParameter 'log' can be declared as pointer to const
logview/src/logview-prefs.c
148variableScope398styleThe scope of the variable 'tokens' can be reduced.
149variableScope398styleThe scope of the variable 'str' can be reduced.
150variableScope398styleThe scope of the variable 'filter' can be reduced.
151variableScope398styleThe scope of the variable 'tag' can be reduced.
385variableScope398styleThe scope of the variable 'stored' can be reduced.
425variableScope398styleThe scope of the variable 'stored' can be reduced.
logview/src/logview-resources.c
9unusedStructMember563styleunion member 'Anonymous0::alignment' is never used.
9unusedStructMember563styleunion member 'Anonymous0::ptr' is never used.
logview/src/logview-window.c
337variableScope398styleThe scope of the variable 'active' can be reduced.
522variableScope398styleThe scope of the variable 'mark' can be reduced.
619variableScope398styleThe scope of the variable 'end' can be reduced.
620variableScope398styleThe scope of the variable 'text' can be reduced.
682variableScope398styleThe scope of the variable 'filter' can be reduced.
713variableScope398styleThe scope of the variable 'tag' can be reduced.
714variableScope398styleThe scope of the variable 'action' can be reduced.
1037variableScope398styleThe scope of the variable 'primary' can be reduced.
1317variableScope398styleThe scope of the variable 'item' can be reduced.
1559variableScope398styleThe scope of the variable 'err' can be reduced.
logview/src/tests/test-reader.c
37unusedVariable563styleUnused variable: day
38variableScope398styleThe scope of the variable 'day_s' can be reduced.
mate-dictionary/libgdict/gdict-client-context.c
196unknownMacroerrorThere is an unknown macro here somewhere. Configuration is required. If G_ADD_PRIVATE is a macro then please configure it.
mate-dictionary/libgdict/gdict-defbox.c
126unknownMacroerrorThere is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
mate-dictionary/libgdict/gdict-source-chooser.c
92unknownMacroerrorThere is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
mate-dictionary/libgdict/gdict-source.c
411duplicateConditionalAssign398styleThe statement 'if (priv->transport!=transport) priv->transport=transport' is logically equivalent to 'priv->transport=transport'.
mate-dictionary/libgdict/gdict-speller.c
108unknownMacroerrorThere is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
mate-dictionary/src/gdict-common.c
185uselessAssignmentPtrArg398warningAssignment of function parameter has no effect outside the function. Did you forget dereferencing it?
mate-dictionary/src/gdict-pref-dialog.c
84unusedStructMember563stylestruct member '_GdictPrefDialog::help_button' is never used.
85unusedStructMember563stylestruct member '_GdictPrefDialog::close_button' is never used.
mate-dictionary/src/gdict-window.c
385shadowArgument398styleLocal variable 'context' shadows outer argument
1009constParameter398styleParameter 'action' can be declared as pointer to const
1681variableScope398styleThe scope of the variable 'item' can be reduced.
mate-screenshot/src/screenshot-dialog.c
205shadowVariable398styleLocal variable 'dialog' shadows outer variable
mate-screenshot/src/screenshot-resources.c
9unusedStructMember563styleunion member 'Anonymous0::alignment' is never used.
9unusedStructMember563styleunion member 'Anonymous0::ptr' is never used.
mate-screenshot/src/screenshot-save.c
51variableScope398styleThe scope of the variable 'message' can be reduced.
116variableScope398styleThe scope of the variable 'dialog' can be reduced.
143variableScope398styleThe scope of the variable 'dir_name' can be reduced.
mate-screenshot/src/screenshot-utils.c
684variableScope398styleThe scope of the variable 'i' can be reduced.
mate-screenshot/src/screenshot-xfer.c
34unusedStructMember563stylestruct member 'TransferDialog::cancellable' is never used.
+
+ +
+ + diff --git a/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/stats.html b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/stats.html new file mode 100644 index 00000000..9d5b1bdf --- /dev/null +++ b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/stats.html @@ -0,0 +1,190 @@ + + + + + + Cppcheck - HTML report - mate-utils + + + + + +
+ + + + + +
+ + diff --git a/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/style.css b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/style.css new file mode 100644 index 00000000..3897bfaf --- /dev/null +++ b/2023-09-10-084819-3471-cppcheck@b19cd9c47de3_master/style.css @@ -0,0 +1,177 @@ + +body { + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif; + font-size: 13px; + line-height: 1.5; + height: 100%; + margin: 0; +} + +#wrapper { + position: fixed; + height: 100vh; + width: 100vw; + display: grid; + grid-template-rows: fit-content(8rem) auto fit-content(8rem); + grid-template-columns: fit-content(25%) 1fr; + grid-template-areas: + "header header" + "menu content" + "footer footer"; +} + +h1 { + margin: 0 0 8px -2px; + font-size: 175%; +} + +.header { + padding: 0 0 5px 15px; + grid-area: header; + border-bottom: thin solid #aaa; +} + +.footer { + grid-area: footer; + border-top: thin solid #aaa; + font-size: 85%; + +} + +.footer > p { + margin: 4px; +} + +#menu, +#menu_index { + grid-area: menu; + text-align: left; + overflow: auto; + padding: 0 23px 15px 15px; + border-right: thin solid #aaa; + min-width: 200px; +} + +#menu > a { + display: block; + margin-left: 10px; + font-size: 12px; +} + +#content, +#content_index { + grid-area: content; + padding: 0px 5px 15px 15px; + overflow: auto; +} + +label { + white-space: nowrap; +} + +label.checkBtn.disabled { + color: #606060; + background: #e0e0e0; + font-style: italic; +} + +label.checkBtn, input[type="text"] { + border: 1px solid grey; + border-radius: 4px; + box-shadow: 1px 1px inset; + padding: 1px 5px; +} + +label.checkBtn { + white-space: nowrap; + background: #ccddff; +} + +label.unchecked { + background: #eff8ff; + box-shadow: 1px 1px 1px; +} + +label.checkBtn:hover, label.unchecked:hover{ + box-shadow: 0 0 2px; +} + +label.disabled:hover { + box-shadow: 1px 1px inset; +} + +label.checkBtn > input { + display:none; +} + +.summaryTable { + width: 100%; +} + +table.summaryTable td { padding: 0 5px 0 5px; } + +.statHeader, .severityHeader { + font-weight: bold; +} + +.warning { + background-color: #ffffa7; +} + +.error { + background-color: #ffb7b7; +} + +.error2 { + background-color: #faa; + display: inline-block; + margin-left: 4px; +} + +.inconclusive { + background-color: #b6b6b4; +} + +.inconclusive2 { + background-color: #b6b6b4; + display: inline-block; + margin-left: 4px; +} + +.verbose { + display: inline-block; + vertical-align: top; + cursor: help; +} + +.verbose .content { + display: none; + position: absolute; + padding: 10px; + margin: 4px; + max-width: 40%; + white-space: pre-wrap; + border: 1px solid #000; + background-color: #ffffcc; + cursor: auto; +} + +.highlight .hll { + padding: 1px; +} + +.highlighttable { + background-color: #fff; + position: relative; + margin: -10px; +} + +.linenos { + border-right: thin solid #aaa; + color: #d3d3d3; + padding-right: 6px; +} + +.id-filtered, .severity-filtered, .file-filtered, .tool-filtered, .text-filtered { + visibility: collapse; +} -- cgit v1.2.1